function [pf, pu, ixf, ixu, rc] = mfs_trload(cmp, load)

# usage: [pf, pu, ixf, ixu, rc] = mfs_trload(cmp, load)
#
# Input  cmp       Structure with component data
#        load(:)   Structure array defining loads
#
# Output pf(:, :)  Array with force patterns
#        pu(:, :)  Array with displacement patterns
#        ixf(:)    Indices of force patterns
#        ixu(:)    Indices of displacement patterns
#        rc        Return code: 0 = no errors
#                               1 = errors
#
# The function checks the definition of the loads and returns the force
# and displacement patterns.
#
# ------------------------------------------------------------------------

# Copyright (c) 2021 by Johannes Wandinger

  required_fields = {"lc", "func"};
  legal_fields    = [required_fields, "params"];

# Check arguments

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

# Initialize output

  pf  = []; pu  = []; 
  ixf = []; ixu = [];
  rc = 0;

# Check if the required fields are defined and if there are
# illegal fields

  defined_fields = fieldnames(load);

  reqdef = ismember(required_fields, defined_fields);
  defleg = ismember(defined_fields, legal_fields);

  undef  = find(! reqdef); nundef = length(undef);
  illeg  = find(! defleg); nilleg = length(illeg);

  if (nundef)
     rc = 1;
     for n = 1 : nundef
         printf("*E* mfs_transresp: load: field %s undefined\n",
                required_fields{undef(n)});
     end
  end

  if (nilleg)
     rc = 1;
     for n = 1 : nilleg
         printf("*E* mfs_transresp: load: illegal field %s found\n",
                defined_fields{illeg(n)});
     end
  end

  if (rc) return; end

# Check the loads

  nofload = length(load);
  ix = zeros(2, nofload);

  bad = bin2dec("11100");

  for l = 1 : nofload

      lc = load(l).lc;

      if (lc < 1 || lc > cmp.load.nofldc)
         printf("*E* mfs_transresp: load(%d) references undefined loadcase",
                l);
         printf(" %d\n", lc);
         rc = 1;
      elseif (isempty(load(l).func))
         printf("*E* mfs_transresp: no function defined for load %d\n",
                l);
         rc = 1;
      elseif(! ischar(load(l).func))
         printf("*E* mfs_transresp: load(%d).func is not a ", l);
         printf("function name\n");
         rc = 1;
      else
         inflc = cmp.load.inflc(lc);
         if (! inflc)
            printf("*E* mfs_transresp: load(%d) references undefined loadcase",
                   l);
            printf(" %d\n", lc);
            rc = 1;
         elseif (bitand(bad, inflc))
            printf("*E* mfs_transresp: load(%d) references unsupported ", l);
            printf("load type\n");
            rc = 1;
         elseif (bitget(1, inflc))
            ix(1, l) = 1;
         else
            ix(2, l) = 1;
         end
      end

  end

  ixf = find(ix(1, :)); ixu = find(ix(2, :));
  nf  = length(ixf); nu = length(ixu);

  if (rc) return; end

# Check if the referenced functions are defined

  for l = 1 : nofload
      try
         fn = str2func(load(l).func);
      catch
         printf("*E* mfs_transresp: function %s referenced by load ", 
                load(l).func);
         printf("%d is not defined\n", l);
         rc = 1;
      end
  end

  if (rc) return; end

# Collect loads

  if (nf)
     pf = sparse(cmp.dofs.ndofg, nf);
  end
  if (nu)
     pu = sparse(cmp.dofs.ndofp, nu);
  end

  if (nf)
     for k = 1 : nf
         lc = load(ixf(k)).lc;
         pf(:, k) = cmp.load.f(:, lc);
     end
  end

  if (nu)
     for k = 1 : nu
         lc = load(ixu(k)).lc;
         pu(:, k) = cmp.load.u(cmp.dofs.dofp, lc);
     end
  end

end
