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

# usage: [cmp, out, rc] = mfs_backx(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 cmp       Structure with component data
#        out       Additional output 
#        rc        Return code: 0 = no errors
#                               1 = errors 
#
# The functions performs the back transformation from modal to
# physical coordinates for solid components.
#
# class = freqresp
#
#   item   Description      Additional arguments
#   -------------------------------------------------------------------
#   disp   Displacements    args{1}   Load case number
#                           args{2}   List of excitation frequencies
#
# class = transresp
#
#   item   Description      Additional arguments
#   -------------------------------------------------------------------
#   disp   Displacements    args{1}   Response case number
#                           args{2}   List of time steps
#
# ------------------------------------------------------------------------

# Copyright (c) 2018 by Johannes Wandinger

# Check arguments

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

# Initialize

  out = [];
  rc  = 0;

# Branch according to response class

  switch class

# Frequency response

  case "freqresp"

     if (! isfield(cmp, "freqresp"))
        printf("*E* mfs_back: no frequency response results found\n");
        rc = 1; return;
     end

     if (isempty(args) || isempty(ldc = args{1}))
        printf("*E* mfs_back: loadcase not defined\n");
        rc = 1; return;
     end
     if (length(ldc) != 1)
        printf("*E* mfs_back: only one load case can be defined\n");
        rc = 1; return;
     end
     if (ldc < 0 || ldc > cmp.freqresp.nfa)
        printf("*E* mfs_back: loadcase %d does not exist\n", ldc);
        rc = 1; return;
     end
     if (isempty(resp = cmp.freqresp.resp{ldc}))
        printf("*E* mfs_back: no data found for loadcase %d\n", ldc);
        rc = 1; return;
     end

     if (isempty(f = args{2}))
        printf("*E* mfs_back: no frequencies defined\n");
        rc = 1; return;
     end
     if (min(f) < resp.freq(1) || max(f) > resp.freq(end))
        printf("*E* mfs_back: frequencies outside range ");
        printf("%7.2f < f < %7.2f\n", resp.freq(1), resp.freq(end));
        rc = 1; return;
     end

     if (resp.method == 1)
        printf("*W* mfs_back: results of direct frequency response");
        printf(" analyis found\n");
        printf("              no backtransformation needed\n");
        return;
     end

#    Find frequencies

     if (resp.nfreq == 1)

        nback    = 1;
        freqback = f;
        ixb      = 1;

     else   

        f     = sort(f);
        nback = length(f);

        ftest = [resp.freq, 10 * resp.freq(end)];
        ixl   = lookup(ftest, f); ixu   = ixl + 1;
        df    = [f - ftest(ixl); ftest(ixu) - f];
        [m, im] = min(df);
        ix  = [ixl; ixu];
        ixb = zeros(1, nback);
        for k = 1 : nback
            ixb(k) = ix(im(k), k);
        end
        freqback = ftest(ixb);

     end

     out = freqback;

     cmp.freqresp.resp{ldc}.nback    = nback;
     cmp.freqresp.resp{ldc}.freqback = freqback;

     w = 2 * pi * freqback;

#    Process item

     switch item

     case "disp"

        if (cmp.freqresp.resp{ldc}.type == 1)         % Force
           U = cmp.modes.disp * cmp.freqresp.resp{ldc}.Q(:, ixb);
           if (cmp.freqresp.resp{ldc}.method == 3)
              U += cmp.freqresp.resp{ldc}.mct;
           end 
        elseif (cmp.freqresp.resp{ldc}.type == 2)     % Displacement
           U = cmp.modes.disp * cmp.freqresp.resp{ldc}.Q(:, ixb);
           U += cmp.freqresp.resp{ldc}.base;
           if (cmp.freqresp.resp{ldc}.method == 3)
              U -= cmp.freqresp.resp{ldc}.mct .* (w.^2);
           end
        elseif (cmp.freqresp.resp{ldc}.type == 3)     % Velocity
           U = cmp.modes.disp * cmp.freqresp.resp{ldc}.Q(:, ixb);
           U -= i *  cmp.freqresp.resp{ldc}.base ./ w;
           if (cmp.freqresp.resp{ldc}.method == 3)
              U += i * cmp.freqresp.resp{ldc}.mct .* w;
           end
        elseif (cmp.freqresp.resp{ldc}.type == 4)     % Acceleration
           U = cmp.modes.disp * cmp.freqresp.resp{ldc}.Q(:, ixb);
           U -= cmp.freqresp.resp{ldc}.base ./ (w.^2);
           if (cmp.freqresp.resp{ldc}.method == 3)
              U += cmp.freqresp.resp{ldc}.mct;
           end
        elseif (cmp.freqresp.resp{ldc}.type == 11)     % Aeroelasticity
           if (cmp.freqresp.resp{ldc}.method == 4)
              U = cmp.freqresp.resp{ldc}.Ue(:, ixb);
              rigmod = 1 : cmp.stiff.ndofr;
              U += cmp.modes.disp(:, rigmod) ...
                 * cmp.freqresp.resp{ldc}.Q(rigmod, ixb);
           else
              U = cmp.modes.disp * cmp.freqresp.resp{ldc}.Q(:, ixb);
           end
        end

        cmp.freqresp.resp{ldc}.U = U;

     otherwise

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

     end    % item

# Transient response

  case "transresp"

     if (! isfield(cmp, "transresp"))
        printf("*E* mfs_back: no transient response results found\n");
        rc = 1; return;
     end

     if (isempty(args) || isempty(ldc = args{1}))
        printf("*E* mfs_back: result case not defined\n");
        rc = 1; return;
     end
     if (length(ldc) != 1)
        printf("*E* mfs_back: only one result case can be defined\n");
        rc = 1; return;
     end
     if (ldc < 0 || ldc > cmp.transresp.nta)
        printf("*E* mfs_back: result case %d does not exist\n", ldc);
        rc = 1; return;
     end
     if (isempty(resp = cmp.transresp.resp{ldc}))
        printf("*E* mfs_back: no data found for result case %d\n", ldc);
        rc = 1; return;
     end

     if (length(args) == 1 || isempty(args{2}))
        t = resp.tsteps;
     else
        t = args{2};
        if (min(t) < resp.tsteps(1) || max(t) > resp.tsteps(end))
           printf("*E* mfs_back: time steps outside range ");
           printf("%7.2f < t < %7.2f\n", resp.tsteps(1), resp.tsteps(end));
           rc = 1; return;
        end
     end

     if (resp.method == 1)
        printf("*W* mfs_back: results of direct transient response");
        printf(" analyis found\n");
        printf("              no backtransformation needed\n");
        return;
     end

#    Find time steps

     nback = length(t);
     t     = sort(t);

     if (nback == resp.ntime)
        tback = t; ixb = 1 : resp.ntime;
     else
        ttest = [resp.tsteps, 10 * resp.tsteps(end)];
        ixl   = lookup(ttest, t); ixu = ixl + 1;
        dt    = [t - ttest(ixl); ttest(ixu) - t];
        [m, im] = min(dt);
        ixb = zeros(1, nback);
        ix  = [ixl; ixu];
        for k = 1 : nback
            ixb(k) = ix(im(k), k);
        end
        tback = ttest(ixb);
     end

     out = tback;

     cmp.transresp.resp{ldc}.nback = nback;
     cmp.transresp.resp{ldc}.tback = tback;

#    Process item

     switch item

     case "disp"

        if (resp.method == 4)

           u = resp.ue(:, ixb);
           v = resp.ve(:, ixb);
           if ((ndofr = cmp.stiff.ndofr))
              u += cmp.modes.disp * resp.q(:, ixb);
              v += cmp.modes.disp * resp.qd(:, ixb); 
           end

        else

           X = cmp.modes.disp;
           if (resp.method == 3)
              X = [X, resp.Xs];
           end
           u = X * resp.q(:, ixb);
           v = X * resp.qd(:, ixb);
           if (isfield(resp, "base"))
              u += resp.base * resp.f(ixb);
              v += resp.base * resp.fd(ixb);
           end

        end

        cmp.transresp.resp{ldc}.u = u;
        cmp.transresp.resp{ldc}.v = v;

     otherwise

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

     end  % item

  otherwise

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

  end      % class

end
