function [cmp, rc] = mfs_statrespx(cmp)

# usage: [cmp, rc] = mfs_statrespx(cmp)
#
# Input  cmp     Structure with component data
#
# Output cmp     Structure with component data 
#        rc      Return code: 0 = no errors
#                             1 = errors
#
# The function computes the static response of a component.
# Displacements and reaction loads are added to the component
# structure.
#
# ---------------------------------------------------------------------

  rc = 0;

# Check arguments

  if (nargin != 1 || nargout != 2)
     print_usage();
  end

# Check component status

  if (! isfield(cmp, "stiff"))
     printf("*E* mfs_statresp: stiffness matrix missing\n");
     rc = 1;
  end
  if (! isfield(cmp, "load"))
     printf("*E* mfs_statresp: loads missing\n");
     rc = 1;
  end
  if (! cmp.dofs.ndofp)
     printf("*E* mfs_statresp: constraints missing\n");
     rc = 1;
  end
  if (rc) return; end
  if (isfield(cmp.load, "inertia") && ! isfield(cmp, "mass"))
     printf("*E* mfs_statresp: mass matrix needed to process inertia loads\n");
     rc = 1; return;
  end

# Initialize displacements

  ndofg  = cmp.dofs.ndofg;
  nofldc = cmp.load.nofldc;
  disp   = zeros(ndofg, nofldc, "double");

# Get dof lists

  dofl = cmp.dofs.dofl;
  dofp = cmp.dofs.dofp;
  if ((ndofd = cmp.dofs.ndofd))
     dofd = cmp.dofs.dofd;
  end

# Initialize right-hand side

  rhs = sparse(cmp.dofs.ndofl, nofldc);

# Determine load types

  isf = isfield(cmp.load, "f");
  isu = isfield(cmp.load, "u");
  isi = isfield(cmp.load, "inertia");

# Process forces

  if (isf)
     rhs = mfs_matpartr(cmp.load.f, cmp.dofs);
  end

# Get matrix partitions needed

  if (isu)
     [Kll, Klp] = mfs_matpart(cmp.stiff.K, cmp.dofs, [1, 1]);
  else
     Kll = mfs_matpart(cmp.stiff.K, cmp.dofs, [1, 0]);
  end

# Process prescribed displacements

  if (isu)
     rhs  = rhs - Klp * cmp.load.u(dofp, :);
  end

# Process inertia loads

  if (isi)
     ncoor  = cmp.nodes.ncoor;
     nofnod = cmp.nodes.nofnod;
     ar     = zeros(cmp.dofs.mxdofpnt, nofldc);
     ar(1 : ncoor, :) = cmp.load.ar;
     ag = repmat(ar, nofnod, 1);
     Ma = cmp.mass.M * ag;
     rhs -= mfs_matpartr(Ma, cmp.dofs);
  end

# Solve for l-dof displacements

  disp(dofl, :) = Kll \ rhs;

# Add prescribed displacements

  if (isu)
     disp(dofp, :) = cmp.load.u(dofp, :);
  end

# Add dependent displacement

  if (ndofd)
     disp(dofd, :) = cmp.dofs.C(dofd, :) * disp;
  end

# Compute reaction loads, internal constraint forces
# and strain energy

  L = sparse(ndofg, nofldc);
  if (isf)
     L = cmp.load.f;
  end
  if (isi)
     L -= Ma;
  end

  FE = cmp.stiff.K * disp;
  if (ndofd)
     dofda = unique([cmp.dofs.dofa; dofd]);
     FR    = FE - L;
     Fp    = cmp.dofs.C(:, dofp)' * FR;
     FR(dofp, :) -= Fp;
     Fda   = FR(dofda, :);
     icsl  = mfs_mat2nodedata(Fda, dofda, cmp.dofs.mxdofpnt, 4);
     icsl  = mfs_resnodedata(icsl, cmp.nodes);
  else
     Fp = FE(dofp, :) - L(dofp, :);
  end

  reac = mfs_mat2nodedata(Fp, dofp, cmp.dofs.mxdofpnt, 4);
  reac = mfs_resnodedata(reac, cmp.nodes);

  for l = 1 : nofldc
      ES(l) = 0.5 * disp(:, l)' * FE(:, l);
  end

# Compute work of residual

  R = mfs_matpartr(FE - L, cmp.dofs);
  for l = 1 : nofldc
      WR(l) = 0.5 * disp(dofl, l)' * R(:, l);
  end

# Store results

  statresp = struct("nofldc", nofldc, "disp", disp, "reac", reac,
                    "es", ES, "wr", WR);
  if (ndofd)
     statresp.icsl = icsl;
  end

  cmp.statresp = statresp;

end
