function [out, rc] = mfs_getrespx(cmp, class, item, args)

# usage: [out, rc] = mfs_getrespx(cmp, class, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#        args{:}    Additional arguments depending on class and item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This functions returns responses of an analysis in solid mechanics.
#
# Response classes and items:
#
#  "load"       Loads  (getload)
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "resultant" Load resultants
#                args{1}  refpnt(3)   Coordinates of reference point
#                                     (optional; default: [0, 0, 0])
#                args{2}  ldc(:)      List of loadcase numbers
#                                     (optional; default: all loadcases)
#                out{1}   F(:, :)     Resulting forces
#                out{2}   M(:, :)     Resulting moments 
#
#  "statresp"   Static response  (getstatresp)
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "strnegy"   Strain energy
#                args{1}  ldc(:)      List of loadcase numbers
#                                     (optional; default: all loadcases)
#                out{1}   segy(:)     Strain energies
#    "workrsl"   Work of residual load
#                args{1}  ldc(:)      List of loadcase numbers
#                                     (optional; default: all loadcases)
#                out{1}   wr(:)       Work of residual load
#    "disp"      Displacements
#                args{1}  nodids(:)   List of nodal point identifiers
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   disp(:, :)  Displacements (rows correspond to
#                                     nodal points)
#    "stress"    Stresses
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         List of load case numbers (optional / 1);
#                out{1}   result{:}   Cell array with element results
#    "resultant" Stress resultants
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         Lst of load case numbers (optional / 1);
#                out{1}   result{:}   Cell array with element results
#
#  "modes"      Normal modes  (getmodes)
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "freq"      Frequencies
#                args{1}  modno(:)    List of mode numbers
#                out{1}   freq(:)     Array with natural frequencies
#    "disp"      Displacements
#                args{1}  nodids(:)   List of nodal point identifiers
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   disp(:, :)  Displacements (rows correspond to
#
#  "freqresp"  Frequency response  (getfreqresp)
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "freq"      Frequencies
#                args{1}  ldc         Load case number (optional / 1)
#                out{1}   freq(:)     Array with excitation frequencies
#    "strnegy"   Strain energy
#                args{1}  ldc         Load case number (optional / 1)
#                out{1}   segy(:)     Array with strain energies
#                out{2}   freq(:)     Array with excitation frequencies
#    "workrsl"   Work of residual load
#                args{1}  ldc         Load case number (optional / 1)
#                out{1}   wr(:)       Array work of residual
#                out{2}   freq(:)     Array with excitation frequencies
#    "Q"         Modal coefficents
#                args{1}  modno(:)    List of mode numbers
#                out{1}   Q(:, :)     Modal coefficients
#                out{2}   freq(:)     Array with excitation frequencies
#    "disp"      Displacements
#                args{1}  rid(:, :)   rid(:, 1) = Node identifier
#                                     rid(:, 2) = Dof identifier   
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   disp(:, :)  Array with displacements
#                out{2}   freq(:)     Array with excitation frequencies
#    "reldisp"   Displacements relative to rigid body motion
#                args{1}  rid(:, :)   rid(:, 1) = Node identifier
#                                     rid(:, 2) = Dof identifier   
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   disp(:, :)  Array with displacements
#                out{2}   freq(:)     Array with excitation frequencies
#    "velo"      Velocites
#                args{1}  rid(:, :)   rid(:, 1) = Node identifier
#                                     rid(:, 2) = Dof identifier   
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   velo(:, :)  Array with velocities
#                out{2}   freq(:)     Array with excitation frequencies
#    "acce"      Accelerations
#                args{1}  rid(:, :)   rid(:, 1) = Node identifier
#                                     rid(:, 2) = Dof identifier   
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   acce(:, :)  Array with accelerations
#                out{2}   freq(:)     Array with excitation frequencies
#    "stress"    Stresses
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   result{:}   Cell array with element results
#                out{2}   freq(:)     Array with excitation frequencies
#    "resultant" Stress resultants
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   result{:}   Cell array with element results
#                out{2}   freq(:)     Array with excitation frequencies
#
#  "transresp"  Transient response  (getransresp)
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "time"      Time steps
#                args{1}  rcase       Result case number (optional / 1)
#                out{1}   time(:)     Array with excitation frequencies
#    "q"         Modal coefficents
#                args{1}  modno(:)    List of mode numbers
#                out{1}   q(:, :)     Modal coefficients
#                out{2}   t(:)        Time steps
#    "qd"        First derivatives of modal coefficents
#                args{1}  modno(:)    List of mode numbers
#                out{1}   qd(:, :)    1st derivatives of modal coefficients
#                out{2}   t(:)        Time steps
#    "qdd"       Second derivatives of modal coefficents
#                args{1}  modno(:)    List of mode numbers
#                out{1}   qdd(:, :)   2nd derivatives of modal coefficients
#                out{2}   t(:)        Time steps
#    "disp"      Displacements
#                args{1}  rid(:, :)   rid(:, 1) = Node identifier
#                                     rid(:, 2) = Dof identifier   
#                args{2}  ldc         Result case number (optional / 1);
#                out{1}   disp(:, :)  Array with displacements
#                out{2}   t(:)        Array with time steps
#    "velo"      Velocities
#                args{1}  rid(:, :)   rid(:, 1) = Node identifier
#                                     rid(:, 2) = Dof identifier   
#                args{2}  ldc         Result case number (optional / 1);
#                out{1}   velo(:, :)  Array with velocities
#                out{2}   t(:)        Array with time steps
#    "acce"      Accelerations
#                args{1}  rid(:, :)   rid(:, 1) = Node identifier
#                                     rid(:, 2) = Dof identifier   
#                args{2}  ldc         Result case number (optional / 1);
#                out{1}   acce(:, :)  Array with accelerations
#                out{2}   t(:)        Array with time steps
#    "stress"    Stresses
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   result{:}   Cell array with element results
#                out{2}   freq(:)     Array with excitation frequencies
#    "resultant" Stress resultants
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         Load case number (optional / 1);
#                out{1}   result{:}   Cell array with element results
#                out{2}   freq(:)     Array with excitation frequencies
#
#  "diverg"  Static divergence  (getdiverg)
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "qdyn"      Dynamic pressure at divergence
#
#  "trim"       Trim analysis  (gettrim)
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "disp"      Displacements
#                args{1}  nodids(:)   List of nodal point identifiers
#                args{2}  ldc         Configuration number (optional / 1);
#                out{1}   disp(:, :)  Displacements (rows correspond to
#                                     nodal points)
#    "stress"    Stresses
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         Configuration number (optional / 1);
#                out{1}   result{:}   Cell array with element results
#    "resultant" Stress resultants
#                args{1}  eltids(:)   List of element identifiers
#                args{2}  ldc         configuration number (optional / 1);
#                out{1}   result{:}   Cell array with element results
#
# -------------------------------------------------------------------------

# Copyright (c) by 2024 Johannes Wandinger

# Check arguments

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

# Branch according to response class

  switch class

  case "load"

     [out, rc] = getload(cmp, item, args);

  case "statresp"

     [out, rc] = getstatresp(cmp, item, args);

  case "modes"

     [out, rc] = getmodes(cmp, item, args);

  case "freqresp"

     [out, rc] = getfreqresp(cmp, item, args);

  case "transresp"

     [out, rc] = gettransresp(cmp, item, args);

  case "diverg"

     [out, rc] = getdiverg(cmp, item, args);

  case "trim"

     [out, rc] = gettrim(cmp, item, args);

  otherwise

     printf("*E* mfs_getresp: unknown response class \"%s\"\n", class);
     rc  = 1; out = cell();

  end

end

function [out, rc] = getload(cmp, item, args)

# usage: [out, rc] = getload(cmp, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This function is called by mfs_getrespx to process results of class
# "load".
#
# -------------------------------------------------------------------------

  nargs = length(args);
  out   = cell();
  rc    = 1;

  if (! isfield(cmp, "load"))
     printf("*E* mfs_getresp: no load data found\n");
     return;
  end

  switch item

  case "resultant"

     if (nargs == 0 || isempty(args{1}))
        refpnt = [0, 0, 0];
     else
        refpnt = args{1};
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1 : cmp.load.nofldc;
     else
        ldc = args{2};
        if ((lcb = max(ldc)) > cmp.load.nofldc || 
            (lcb = min(ldc)) < 1)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", lcb);
           return;
        end
     end

     if (! isfield(cmp.load, "f"))
        printf("*E* mfs_getresp: there are no forces or moments\n");
     else
        R = mfs_rigidmotion(cmp.nodes, cmp.dofs.mxdofpnt, refpnt);
        F = R(:, 1 : 3)' * cmp.load.f(:, ldc);
        M = R(:, 4 : 6)' * cmp.load.f(:, ldc);
        out{1} = F;
        out{2} = M;
        rc     = 0;
     end

  otherwise

     printf("*E* mfs_getresp: unknown response item \"%s\"\n", item);

  end

end

function [out, rc] = getstatresp(cmp, item, args)

# usage: [out, rc] = getstatresp(cmp, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This function is called by mfs_getrespx to process results of class
# "statresp".
#
# -------------------------------------------------------------------------

  nargs = length(args);
  out   = cell();
  rc    = 1;

  if (! isfield(cmp, "statresp"))
     printf("*E* mfs_getresp: no static response data found\n");
     return;
  end

  switch item

  case {"strnegy", "workrsl"}

     if (nargs == 0 || isempty(args{1}))
        ldc = 1 : cmp.statresp.nofldc;
     else
        ldc = args{1};
        if ((lcb = max(ldc)) > cmp.statresp.nofldc || 
            (lcb = min(ldc)) < 1)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", lcb);
           return;
        end
     end

     switch item

     case "strnegy"
        out{1} = cmp.statresp.es(ldc);
     case "workrsl"
        out{1} = cmp.statresp.wr(ldc);
     end

     rc = 0;

  case "disp"

     if (nargs == 0 || isempty(args{1})) 
        printf("*E* mfs_getresp: nodal point identifers undefined\n");
        return
     end

     nodids = args{1};
     if (isnumeric(nodids))
        nodids = nodids(:)';
        if (rows(nodids) > 1)
           printf("*E* mfs_getresp: bad definition of nodal point identifiers\n");
           return;
        end
     elseif (! ischar(nodids))
        printf("*E* mfs_getresp: bad definition of nodal point identifiers\n");
        return;
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1; 
     else
        ldc = args{2};
        if (length(ldc) != 1)
           printf("*E* mfs_getresp: only one loadcase allowed ");
           printf("for item \"disp\"\n");
           return;
        end
        if (ldc < 1 || ldc > cmp.statresp.nofldc)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end

     [ixdof, rc] = mfs_findnodedofs(cmp.nodes.ids, cmp.dofs.mxdofpnt,
                                    nodids, cmp.nset);
     if (! rc)
        displc = cmp.statresp.disp(:, ldc);
        out{1} = displc(ixdof)';
     end

  case {"stress", "resultant"}

     if (! isfield(cmp.statresp, "elres"))
        printf("*E* mfs_getresp: no element results found\n");
        return;
     end 

     if (nargs == 0 || isempty(args{1})) 
        printf("*E* mfs_getresp: element identifers undefined\n");
        return
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1; 
     else
        ldc = args{2};
        if (min(ldc) < 1 || max(ldc) > cmp.statresp.nofldc)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end

     [ixelt, rc] = mfs_findelts(cmp.elements.index, args{1}, cmp.eset);
     if (rc) return; end

     switch cmp.subtype
     case "2d"
        switch item
        case "stress"
           out{1} = mfs_getstress2d(cmp.statresp.elres.elem,
                                    ixelt, ldc);
        case "resultant"
           out{1} = mfs_getresultant2d(cmp.statresp.elres.elem,
                                       ixelt, ldc);
        end
     case "3d"
        switch item
        case "stress"
           out{1} = mfs_getstress3d(cmp.statresp.elres.elem,
                                    ixelt, ldc);
        case "resultant"
           out{1} = mfs_getresultant3d(cmp.statresp.elres.elem,
                                       ixelt, ldc);
        end
     end

  otherwise

     printf("*E* mfs_getresp: unknown response item \"%s\"\n", item);

  end

end

function [out, rc] = getmodes(cmp, item, args)

# usage: [out, rc] = getmodes(cmp, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This function is called by mfs_getrespx to process results of class
# "modes".
#
# -------------------------------------------------------------------------

  nargs = length(args);
  out   = cell();
  rc    = 1;

  if (! isfield(cmp, "modes"))
     printf("*E* mfs_getresp: no normal modes found\n");
     return;
  end

  switch item

  case "freq"

     if (nargs == 0 || isempty(args{1}))
        modno = 1 : cmp.modes.nofmod;
     else
        modno = args{1};
        if ((mb = min(modno)) < 1 || 
            (mb = max(modno)) > cmp.modes.nofmod)
           printf("*E* mfs_getresp: mode number %d does not exist\n", mb);
           return;
        end
     end

     out{1} = cmp.modes.freq(modno);
     rc     = 0;

  case "disp"

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: nodal point identifers undefined\n");
        return
     end

     nodids = args{1};
     if (isnumeric(nodids))
        nodids = nodids(:)';
        if (rows(nodids) > 1)
           printf("*E* mfs_getresp: bad definition of nodal point identifiers\n");
           return;
        end
     elseif (! ischar(nodids))
        printf("*E* mfs_getresp: bad definition of nodal point identifiers\n");
        return;
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        modno = args{2};
        if (length(modno) != 1)
           printf("*E* mfs_getresp: only one mode allowed ");
           printf("for item \"disp\"\n");
           return;
        end
        if (modno < 1 || modno > cmp.modes.nofmod)
           printf("*E* mfs_getresp: mode %d does not exist\n", ldc);
           return;
        end
     end

     [ixdof, rc] = mfs_findnodedofs(cmp.nodes.ids, cmp.dofs.mxdofpnt,
                                    nodids, cmp.nset);
     if (! rc)
        disp   = cmp.modes.disp(:, modno);
        out{1} = disp(ixdof)';
     end

  otherwise

     printf("*E* mfs_getresp: unknown response item \"%s\"\n", item);
     return;

  end

end

function [out, rc] = getfreqresp(cmp, item, args)

# usage: [out, rc] = getfreqresp(cmp, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This function is called by mfs_getrespx to process results of class
# "freqresp".
#
# -------------------------------------------------------------------------

  nargs = length(args);
  out   = cell();
  rc    = 1;

  if (! isfield(cmp, "freqresp"))
     printf("*E* mfs_getresp: no frequency response data found\n");
     return;
  end

  switch item

  case {"freq", "strnegy", "workrsl"}

     if (nargs > 1)
        printf("*E* mfs_getresp: wrong number of arguments ");
        printf("for item \"%s\"\n", item);
        return;
     end

     if (nargs == 0 || isempty(args{1}))
        ldc = 1;
     else
        ldc = args{1};
        if (ldc < 1 || ldc > cmp.freqresp.nfa)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end
     if (isempty(cmp.freqresp.resp{ldc}))
        printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
        return;
     end

     switch item

     case "freq"

        out{1} = cmp.freqresp.resp{ldc}.freq;
        rc     = 0;

     case "strnegy"
 
        out{1} = cmp.freqresp.resp{ldc}.es;
        out{2} = cmp.freqresp.resp{ldc}.freq;
        rc     = 0;

     case "workrsl"

        if (cmp.freqresp.resp{ldc}.method == 1)
           out{1} = cmp.freqresp.resp{ldc}.wr;
           out{2} = cmp.freqresp.resp{ldc}.freq;
           rc     = 0;
        else
           printf("*E* mfs_getresp: item \"%s\" only supported in", item);
           printf(" direct frequency response\n");
        end

     end

  case "Q"

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: mode numbers undefined\n");
        return;
     else
        modno = args{1};
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
        if (ldc < 1 || ldc > cmp.freqresp.nfa)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end
     if (isempty(cmp.freqresp.resp{ldc}))
        printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
        return;
     end
         
     if ((mb = min(modno)) < 1 || 
         (mb = max(modno)) > cmp.modes.nofmod)
        printf("*E* mfs_getresp: mode number %d does not exist\n", mb);
        return;
     end

     if (cmp.freqresp.resp{ldc}.method > 1)
        out{1} = cmp.freqresp.resp{ldc}.Q(modno, :);
        out{2} = cmp.freqresp.resp{ldc}.freq;
        rc     = 0;
     else
        printf("*E* mfs_getresp: modal coefficients not available\n");
        return;
     end

  case {"disp", "velo", "acce"}

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: response identifers undefined\n");
        return;
     else
        rid = args{1};
        if (columns(rid) != 2)
           printf("*E* mfs_getresp: wrong definition of response identifiers\n");
           return;
        end
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
        if (ldc < 1 || ldc > cmp.freqresp.nfa)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end
     if (isempty(cmp.freqresp.resp{ldc}))
        printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
        return;
     end

     [ixdof, rc] = mfs_finddof(cmp.nodes.ids, cmp.dofs.mxdofpnt,
                               rid(:, 1), rid(:, 2), cmp.nset);
     if (rc) return; end

     if (isfield(cmp, "modes"))
        modes = cmp.modes.disp;
        ndofr = cmp.stiff.ndofr;
     else
        modes = [];
        ndofr = 0;
     end

     [R, w] = mfs_getdispf(cmp.freqresp.resp{ldc}, modes, ixdof, 
                           ndofr, 1);

     switch item
       case "velo"
          R = R * i * diag(w);
       case "acce"
          R = - R * diag(w.^2);
     end

     out{1} = R;
     out{2} = cmp.freqresp.resp{ldc}.freq;

  case "reldisp"

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: response identifers undefined\n");
        return;
     else
        rid = args{1};
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
        if (ldc < 1 || ldc > cmp.freqresp.nfa)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end
     if (isempty(cmp.freqresp.resp{ldc}))
        printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
        return;
     end
     if (cmp.freqresp.resp{ldc}.method != 4)
        printf("*E* mfs_getresp: relative displacement only available ");
        printf("with force summation method\n");
        return;
     end

     [ixdof, rc] = mfs_finddof(cmp.nodes.ids, cmp.dofs.mxdofpnt,
                               rid(:, 1), rid(:, 2), cmp.nset);
     if (rc) return; end

     out{1} = cmp.freqresp.resp{ldc}.Ue(ixdof, :);
     out{2} = cmp.freqresp.resp{ldc}.freq;

  case {"stress", "resultant"}

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: response identifers undefined\n");
        return;
     else
        rid = args{1};
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
        if (ldc < 1 || ldc > cmp.freqresp.nfa)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end
     if (isempty(cmp.freqresp.resp{ldc}))
        printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
        return;
     end

     [ixdofs, elements, rid, rc] = mfs_prepelts(rid, cmp.elements.types,
                                                cmp.elements.index,
                                                cmp.elements.elem,
                                                cmp.eset);

     if (rc)
        printf("*E* mfs_getresp: requested elements do not exist\n");
        return;
     end
   
     if (isfield(cmp, "modes"))
        modes = cmp.modes.disp;
        ndofr = cmp.stiff.ndofr;
     else
        modes = 0;
        ndofr = 0;
     end

     [disp, w] = mfs_getdispf(cmp.freqresp.resp{ldc}, modes, ixdofs, 
                              ndofr, 0);
     elres = mfs_results_freqresp_elem(cmp.subtype, elements, 
                                       disp, w);

     cols  = 1 : cmp.freqresp.resp{ldc}.nfreq;
     ixelt = lookup([elres.elem.id], rid);

     switch cmp.subtype
     case "2d"
        switch item
        case "stress"
           out{1} = mfs_getstress2d(elres.elem, ixelt, cols);
        case "resultant"
           out{1} = mfs_getresultant2d(elres.elem, ixelt, cols);
        end
     case "3d"
        switch item
        case "stress"
           out{1} = mfs_getstress3d(elres.elem, ixelt, cols);
        case "resultant"
           out{1} = mfs_getresultant3d(elres.elem, ixelt, cols);
        end
     end

     out{2} = cmp.freqresp.resp{ldc}.freq;

     otherwise

     printf("*E* mfs_getresp: unknown response item \"%s\"\n", item);
     return;

  end

end

function [out, rc] = gettransresp(cmp, item, args)

# usage: [out, rc] = gettransresp(cmp, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This function is called by mfs_getrespx to process results of class
# "transresp".
#
# -------------------------------------------------------------------------

  nargs = length(args);
  out   = cell();
  rc    = 1;

  if (! isfield(cmp, "transresp"))
     printf("*E* mfs_getresp: no transient response data found\n");
     return;
  end

  switch item

  case "time"

     if (nargs > 1)
        printf("*E* mfs_getresp: wrong number of arguments ");
        printf("for item \"%s\"\n", item);
        return;
     end

     if (nargs == 0 || isempty(args{1}))
        ldc = 1;
     else
        ldc = args{1};
     end

     if ((rc = mfs_chk_respcase(ldc, cmp.transresp.nta,
                                cmp.transresp.resp)))
        return;
     end

     out{1} = cmp.transresp.resp{ldc}.tsteps;

  case {"q", "qd", "qdd"}

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: mode numbers undefined\n");
        return;
     else
        modno = args{1};
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
     end

     if ((rc = mfs_chk_respcase(ldc, cmp.transresp.nta,
                                cmp.transresp.resp)))
        return;
     end

     if (cmp.transresp.resp{ldc}.method < 2)
        printf("*E* mfs_getresp: modal coefficients not available\n");
        rc = 1; return;
     end

     if ((mb = min(modno)) < 1 ||
         (mb = max(modno)) > cmp.modes.nofmod)
        printf("*E* mfs_getresp: mode number %d does not exist\n", mb);
        rc = 1; return;
     end

     switch item
     case "q"
        out{1} = cmp.transresp.resp{ldc}.q(modno, :);
     case "qd"
        out{1} = cmp.transresp.resp{ldc}.qd(modno, :);
     case "qdd"
        out{1} = cmp.transresp.resp{ldc}.qdd(modno, :);
     end

     out{2} = cmp.transresp.resp{ldc}.tsteps;

  case {"disp", "velo", "acce"}

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: response identifers undefined\n");
        return;
     else
        rid = args{1};
        if (columns(rid) != 2)
           printf("*E* mfs_getresp: wrong definition of response identifiers\n");
           return;
        end
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
     end

     if ((rc = mfs_chk_respcase(ldc, cmp.transresp.nta,
                                cmp.transresp.resp)))
        return;
     end

     [ixdof, rc] = mfs_finddof(cmp.nodes.ids, cmp.dofs.mxdofpnt,
                               rid(:, 1), rid(:, 2), cmp.nset);
     if (rc) return; end

     if (isfield(cmp, "modes"))
        modes = cmp.modes.disp;
        ndofr = cmp.stiff.ndofr;
     else
        modes = [];
        ndofr = 0;
     end

     switch item
     case "disp"
        out{1} = mfs_getmotion(cmp.transresp.resp{ldc}, ixdof, 1,
                               modes, ndofr);
     case "velo"
        out{1} = mfs_getmotion(cmp.transresp.resp{ldc}, ixdof, 2,
                               modes, ndofr);
     case "acce"
        out{1} = mfs_getmotion(cmp.transresp.resp{ldc}, ixdof, 3,
                               modes, ndofr);
     end

     out{2} = cmp.transresp.resp{ldc}.tsteps;

  case {"reldisp"}

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: response identifers undefined\n");
        return;
     else
        rid = args{1};
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
        if (ldc < 1 || ldc > cmp.transresp.nta)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end
     if (isempty(cmp.transresp.resp{ldc}))
        printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
        return;
     end
     if (cmp.transresp.resp{ldc}.method != 4)
        printf("*E* mfs_getresp: relative displacement only available ");
        printf("with force summation method\n");
        return;
     end

     [ixdof, rc] = mfs_finddof(cmp.nodes.ids, cmp.dofs.mxdofpnt,
                               rid(:, 1), rid(:, 2), cmp.nset);
     if (rc) return; end

     out{1} = cmp.transresp.resp{ldc}.ue(ixdof, :);
     out{2} = cmp.transresp.resp{ldc}.tsteps;

  case {"stress", "resultant"}

     if (nargs == 0 || isempty(args{1}))
        printf("*E* mfs_getresp: response identifers undefined\n");
        return;
     else
        rid = args{1};
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1;
     else
        ldc = args{2};
        if (ldc < 1 || ldc > cmp.transresp.nta)
           printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
           return;
        end
     end
     if (isempty(cmp.transresp.resp{ldc}))
        printf("*E* mfs_getresp: loadcase %d does not exist\n", ldc);
        return;
     end

     [ixdofs, elements, rid, rc] = mfs_prepelts(rid, cmp.elements.types,
                                                cmp.elements.index,
                                                cmp.elements.elem,
                                                cmp.eset);
     if (rc)
        printf("*E* mfs_getresp: requested elements do not exist\n");
        return;
     end
   
     if (isfield(cmp, "modes"))
        modes = cmp.modes.disp;
        ndofr = cmp.stiff.ndofr;
     else
        modes = 0;
        ndofr = 0;
     end

     disp = mfs_getmotion(cmp.transresp.resp{ldc}, ixdofs, 1,
                          modes, ndofr);
     velo = mfs_getmotion(cmp.transresp.resp{ldc}, ixdofs, 2,
                          modes, ndofr);
     elres = mfs_results_transresp_elem(cmp.subtype, elements, 
                                        disp, velo);

     cols  = 1 : cmp.transresp.resp{ldc}.ntime;
     ixelt = lookup([elres.elem.id], rid);

     switch cmp.subtype
     case "2d"
        switch item
        case "stress"
           out{1} = mfs_getstress2d(elres.elem, ixelt, cols);
        case "resultant"
           out{1} = mfs_getresultant2d(elres.elem, ixelt, cols);
        end
     case "3d"
        switch item
        case "stress"
           out{1} = mfs_getstress3d(elres.elem, ixelt, cols);
        case "resultant"
           out{1} = mfs_getresultant3d(elres.elem, ixelt, cols);
        end
     end

     out{2} = cmp.transresp.resp{ldc}.tsteps;

  otherwise

     printf("*E* mfs_getresp: unknown response item \"%s\"\n", item);
     return;

  end

end

function [out, rc] = getdiverg(cmp, item, args)

# usage: [out, rc] = getdiverg(cmp, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This function is called by mfs_getrespx to process results of class
# "diverg".
#
# -------------------------------------------------------------------------

  nargs = length(args);
  out   = cell();
  rc    = 1;

  if (! isfield(cmp, "diverg"))
     printf("*E* mfs_getresp: no static divergence data found\n");
     return;
  end

  switch item

  case "qdyn"

     if (nargs == 0 || isempty(args{1}))
        nq = 1 : cmp.diverg.ndiv;
     else
        nq = args{1};
        if ((nb = min(nq)) < 1 || 
            (nb = max(nq)) > cmp.diverg.ndiv)
           printf("*E* mfs_getresp: divergence %d does not exist\n", nb);
           return;
        end
     end

     out{1} = cmp.diverg.qdyn(nq);
     rc     = 0;

  otherwise

     printf("*E* mfs_getresp: unknown response item \"%s\"\n", item);
     return;

  end

end

function [out, rc] = gettrim(cmp, item, args)

# usage: [out, rc] = gettrim(cmp, item, args)
#
# Input  cmp        Structure with component data
#        class      Response class
#        item       Response item
#
# Output out{:}     Output arguments depending on class and item
#        rc         Return code: 0 = no errors
#                                1 = errors
#
# This function is called by mfs_getrespx to process results of class
# "trim".
#
# -------------------------------------------------------------------------

  nargs = length(args);
  out   = cell();
  rc    = 1;

  if (! isfield(cmp, "trim"))
     printf("*E* mfs_getresp: no results from trim analysis found\n");
     return;
  end

  switch item

  case "disp"

     if (nargs == 0 || isempty(args{1})) 
        printf("*E* mfs_getresp: nodal point identifers undefined\n");
        return
     end

     nodids = args{1};
     if (isnumeric(nodids))
        nodids = nodids(:)';
        if (rows(nodids) > 1)
           printf("*E* mfs_getresp: bad definition of nodal point identifiers\n");
           return;
        end
     elseif (! ischar(nodids))
        printf("*E* mfs_getresp: bad definition of nodal point identifiers\n");
        return;
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1; 
     else
        ldc = args{2};
        if (length(ldc) != 1)
           printf("*E* mfs_getresp: only one configuration allowed ");
           printf("for item \"disp\"\n");
           return;
        end
        if (ldc < 1 || ldc > cmp.trim.nconf)
           printf("*E* mfs_getresp: configuration %d does not exist\n", ldc);
           return;
        end
     end

     [ixdof, rc] = mfs_findnodedofs(cmp.nodes.ids, cmp.dofs.mxdofpnt,
                                    nodids, cmp.nset);
     if (! rc)
        displc = cmp.trim.disp(:, ldc);
        out{1} = displc(ixdof)';
     end

  case {"stress", "resultant"}

     if (! isfield(cmp.trim, "elres"))
        printf("*E* mfs_getresp: no element results found\n");
        return;
     end 

     if (nargs == 0 || isempty(args{1})) 
        printf("*E* mfs_getresp: element identifers undefined\n");
        return
     end

     if (nargs < 2 || isempty(args{2}))
        ldc = 1; 
     else
        ldc = args{2};
        if (min(ldc) < 1 || max(ldc) > cmp.trim.nconf)
           printf("*E* mfs_getresp: configuration %d does not exist\n", ldc);
           return;
        end
     end

     [ixelt, rc] = mfs_findelts(cmp.elements.index, args{1}, cmp.eset);
     if (rc) return; end

     switch cmp.subtype
     case "2d"
        switch item
        case "stress"
           out{1} = mfs_getstress2d(cmp.trim.elres.elem,
                                    ixelt, ldc);
        case "resultant"
           out{1} = mfs_getresultant2d(cmp.trim.elres.elem,
                                       ixelt, ldc);
        end
     case "3d"
        switch item
        case "stress"
           out{1} = mfs_getstress3d(cmp.trim.elres.elem,
                                    ixelt, ldc);
        case "resultant"
           out{1} = mfs_getresultant3d(cmp.trim.elres.elem,
                                       ixelt, ldc);
        end
     end

  otherwise

     printf("*E* mfs_getresp: unknown response item \"%s\"\n", item);

  end

end
