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 function returns responses of an aerodynamic analysis.
#
# Response classes and items:
#
#  "mesh"       Mesh data
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "area"      Areas
#                args{1}  lsid(:)     List of lifting surfaces
#                                     (optional; default is all surfaces)
#                out{1}   A(:)        Array with areas
#                                     (If no lifting surfaces are defined,
#                                      only the total area is returned)
#
#  "statresp"   Steady areodynamics
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "aeload"    Aerodynamic load resultants
#                args{1}  refpnt(3)   Coordinates of reference point
#                                     (optional; default: [0, 0, 0])
#                args{2}  lsid(:)     List of lifting surfaces
#                                     (optional; default is all surfaces)
#                args{3}  cfg(:)      List of configuration numbers
#                                     (optional; default is all 
#                                      configurations)
#                out{1}   F(:, :)     Resulting forces
#                out{2}   M(:, :)     Resulting moments
#
#  "diverg"  Static divergence
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "qdyn"      Dynamic pressure at divergence
#
#  "trim"       Trim analysis
#
#    item        Meaning
#    ----------------------------------------------------------------------
#    "aeload"    Aerodynamic load resultants
#                args{1}  refpnt(3)   Coordinates of reference point
#                                     (optional; default: [0, 0, 0])
#                args{2}  lsid(:)     List of lifting surfaces
#                                     (optional; default is all surfaces)
#                args{3}  cfg(:)      List of configuration numbers
#                                     (optional; default is all 
#                                      configurations)
#                out{1}   F(:, :)     Resulting forces
#                out{2}   M(:, :)     Resulting moments
#    "params"    Trim parameter
#                args{1}  cfg(:)      List of configuration numbers
#                                     (optional; default is all 
#                                      configurations)
#                out{1}   tp          Structure with trim parameters:
#
# Fields of structure tp:
#   nconf            Number of configurations
#   qdyn(nconf)      Dynamic pressure
#   tpname(nconf)    Values of trim parameter tpname
#
# -------------------------------------------------------------------------

# Check arguments

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

# Initialize

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

# Branch according to response class

  switch class

  case "mesh"

# Mesh

     switch item

     case "area"             % Areas of lifting surfaces

        if (nargs == 0 || isempty(args{1}))
           A = sum(cmp.panels.area);
        else
           lsid = args{1};
           nofls = length(lsid);
           A = zeros(1, nofls);
           for l = 1 : nofls
               if ((ix = lookup(cmp.ls.ids, lsid(l), "m")))
                  p1 = cmp.ls.surfs(ix).p1;
                  p2 = cmp.ls.surfs(ix).pend;
                  A(l) = sum(cmp.panels.area(p1 : p2));
               else
                  printf("*E* mfs_getresp: lifting surface %d ", lsid(l));
                  printf("does not exist\n");
                  rc = 1;
               end
           end
        end

        out{1} = A;

     otherwise

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

     end

  case "statresp"

# statresp

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

     switch item

     case "aeload"           % Aerodynamic load resultants

        if (! isfield(cmp.statresp, "panres"))
           printf("*E* mfs_getresp: panel results missing\n");
           rc = 1;
           return;
        end

        if (nargs == 0 || isempty(args{1}))
           refpnt = zeros(3, 1);
        else
           ref = args{1};
           [nr, nc] = size(ref);
           if (nr * nc != 3)
              printf("*E* mfs_getresp: bad definition of reference");
              printf(" point\n");
              rc = 1;
              return;
           else
              if (nr == 3)
                 refpnt = ref;
              else
                 refpnt = ref';
              end
           end 
        end

        if (nargs < 2 || isempty(args{2}))
           P = cmp.statresp.panres.P; 
           f = cmp.statresp.panres.f;
        else
           px = [];
           for id = args{2}
               ix = lookup(cmp.ls.ids, id, "m");
               if (ix)
                   p1 = cmp.ls.surfs(ix).p1;
                   p2 = cmp.ls.surfs(ix).pend;
                   px = [px, [p1 : p2]];
               else
                  printf("*E* mfs_getresp: lifting surface %d ", id);
                  printf("does not exist\n");
                  rc = 1;
                end
           end
           if (rc)
              return;
           else
              P = cmp.statresp.panres.P(:, px);
              f = cmp.statresp.panres.f(:, px, :);
           end
        end

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

        [nr, nofpan] = size(P);

        F = zeros(3, nconf);
        M = zeros(3, nconf);

        rP = P - repmat(refpnt, 1, nofpan);
        for n = 1 : nconf
            m       = cfg(n);
            fn      = reshape(f(:, :, m), 3, nofpan);
            F(:, n) = sum(fn, 2);
            M(:, n) = sum(cross(rP, fn), 2);
        end

        out{1} = F;
        out{2} = M;

     otherwise

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

     end

# Static divergence

  case "diverg"

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

#    Process item

     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);
              rc = 1;
              return;
           end 
        end 

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

     otherwise

        printf("mfs_getresp: unknown response item \"%s\"\n", item);
        rc = 1;
        return;

     end

# trim

  case "trim"

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

     switch item

     case "aeload"           % Aerodynamic load resultants

        if (! isfield(cmp.trim, "panres"))
           printf("*E* mfs_getresp: panel results missing\n");
           rc = 1;
           return;
        end

        if (nargs == 0 || isempty(args{1}))
           refpnt = zeros(3, 1);
        else
           ref = args{1};
           [nr, nc] = size(ref);
           if (nr * nc != 3)
              printf("*E* mfs_getresp: bad definition of reference");
              printf(" point\n");
              rc = 1;
              return;
           else
              if (nr == 3)
                 refpnt = ref;
              else
                 refpnt = ref';
              end
           end 
        end

        if (nargs < 2 || isempty(args{2}))
           P = cmp.trim.panres.P; 
           f = cmp.trim.panres.f;
        else
           px = [];
           for id = args{2}
               ix = lookup(cmp.ls.ids, id, "m");
               if (ix)
                   p1 = cmp.ls.surfs(ix).p1;
                   p2 = cmp.ls.surfs(ix).pend;
                   px = [px, [p1 : p2]];
               else
                  printf("*E* mfs_getresp: lifting surface %d ", id);
                  printf("does not exist\n");
                  rc = 1;
                end
           end
           if (rc)
              return;
           else
              P = cmp.trim.panres.P(:, px);
              f = cmp.trim.panres.f(:, px, :);
           end
        end

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

        [nr, nofpan] = size(P);

        F = zeros(3, nconf);
        M = zeros(3, nconf);

        rP = P - repmat(refpnt, 1, nofpan);
        for n = 1 : nconf
            m       = cfg(n);
            fn      = reshape(f(:, :, m), 3, nofpan);
            F(:, n) = sum(fn, 2);
            M(:, n) = sum(cross(rP, fn), 2);
        end

        out{1} = F;
        out{2} = M;

     case "params"           % Trim parameter

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

        tp = struct("nconf", nconf, "qdyn", cmp.config.qdyn(cfg));

        for n = 1 : cmp.trim.ntp
            tp = setfield(tp, cmp.trim.tpnames{n}, 
                              cmp.trim.tpval(n, cfg));
        end

        out{1} = tp;

     otherwise

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

     end

  otherwise

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

  end

end
