function mfs_printx(fid, cmp, class, items)

# usage: mfs_printx(fid, cmp, class, items)
#
# Input  fid       File handle 
#        cmp       Structure with component
#        class     Output data class
#        items{}   List of items to be printed
#
# The function prints the results of a solid component.
#
# The items supported depend on the class:
#
#  class = load
#        point     Point loads
#        disp      Prescribed displacements
#        velo      Prescribed velocities
#        acce      Prescribed accelerations
#
#  class = statresp
#        disp      Displacements
#        reac      Reaction loads
#        icsl      Internal constraint loads
#        stress    Stresses
#        strain    Strains
#        resultant Stress resultants
#
#  class = modes
#        disp      Displacements
#        freq      Frequencies
#        reac      Reaction loads
#        icsl      Internal constraint loads
#
#  class = freqresp
#        disp      Displacements
#        velo      Velocities
#        acce      Accelerations
#        stress    Stresses
#        strain    Strains
#        resultant Stress resultants
#
#  class = transresp
#        disp      Displacements
#        velo      Velocities
#        stress    Stresses
#        strain    Strains
#        resultant Stress resultants
#
#  class = diverg
#        qdyn      Dynamic pressure
#        disp      Displacements
#
#  class = trim
#        disp      Displacements
#        stress    Stresses
#        strain    Strains
#        resultant Stress resultants
#
#  class = flutter
#        disp      Displacements
#
# ---------------------------------------------------------------------

# Copyright (c) 2020 by Johannes Wandinger

  headl2 = {"Fx", "Fy", "Mz"};
  headl3 = {"Fx", "Fy", "Fz", "Mx", "My", "Mz"};
  headd2 = {"ux", "uy", "rz"};
  headd3 = {"ux", "uy", "uz", "rx", "ry", "rz"};
  headv2 = {"vx", "vy", "wz"};
  headv3 = {"vx", "vy", "vz", "wx", "wy", "wz"};
  heada2 = {"ax", "ay", "bz"};
  heada3 = {"ax", "ay", "az", "bx", "by", "bz"};

# Check arguments

  if (nargin < 4)
     print_usage();
  end

# Headers

  switch cmp.subtype
  case "2d"
     headl = headl2;
     headd = headd2;
     headv = headv2;
     heada = heada2;
  case "3d"
     headl = headl3;
     headd = headd3;
     headv = headv3;
     heada = heada3;
  end

# Process parameters

  switch class

  case {"load", "loads"}

     if (! isfield(cmp, "load"))
        printf("*W* mfs_print: there are no items of class \"loads\"\n");
       return;
     end      
 
     for k = 1 : length(items)
         [itm, sel] = getitem_load(items{k});
         switch itm
         case "point"
            if (isfield(cmp.load, "point"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.load.point,
                                "Point loads of loadcase", headl, 0, sel);
            else
               printf("*W* mfs_print: item \"point\" does not exist\n");
            end
         case "disp"
            if (isfield(cmp.load, "motion"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.load.motion,
                                "Prescribed displacements of loadcase", headd, 1);
            else
               printf("*W* mfs_print: item \"disp\" does not exist\n");
            end
         case "velo"
            if (isfield(cmp.load, "motion"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.load.motion,
                                "Prescribed velocities of loadcase", headv, 2);
            else
               printf("*W* mfs_print: item \"velo\" does not exist\n");
            end
         case "acce"
            if (isfield(cmp.load, "motion"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.load.motion,
                                "Prescribed accelerations of loadcase", heada, 3);
            else
               printf("*W* mfs_print: item \"acce\" does not exist\n");
            end
         case "none"
         otherwise
            printf("*W* mfs_print: unknown item \"%s\"\n", items{k});
         end
     end     % Item
       
  case "statresp"

     if (! isfield(cmp, "statresp"));
        printf("*W* mfs_print: there are no items of class \"statresp\"\n");
       return;
     end      
 
     for k = 1 : length(items)
         [itm, sel] = getitem(items{k}, cmp);
         switch itm
         case "disp"
            if (isfield(cmp.statresp, "disp"))
               mfs_prt_disp(fid, cmp.nodes, cmp.dofs.mxdofpnt, 
                            cmp.statresp.disp, "Displacements of loadcase",
                            headd, sel);
            else
               printf("*W* mfs_print: item \"disp\" does not exists\n");
            end
         case "reac"
            if (isfield(cmp.statresp, "reac"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.statresp.reac,
                                "Reaction loads of loadcase", headl,
                                4, sel);
            else
               printf("*W* mfs_print: item ""reac"" does not exists\n");
            end
         case "icsl"
            if (isfield(cmp.statresp, "icsl"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.statresp.icsl,
                                "Internal constraint loads of loadcase",
                                headl, 4, sel);
            else
               printf("*W* mfs_print: item ""icsl"" does not exists\n");
            end
         case "stress"
             if (isfield(cmp.statresp, "elres"))
                for lc = 1 : cmp.statresp.elres.nofcol
                    titles{lc} = sprintf("Stresses of loadcase %2.0d", lc);
                end
                mfs_prt_elres(fid, cmp.statresp.elres, "stress",
                              titles, sel);
             else
                printf("*W* mfs_print: no element results found\n");
             end
         case "strain"
             if (isfield(cmp.statresp, "elres"))
                for lc = 1 : cmp.statresp.elres.nofcol
                    titles{lc} = sprintf("Strains of loadcase %2.0d", lc);
                end
                mfs_prt_elres(fid, cmp.statresp.elres, "strain",
                              titles, sel);
             else
                printf("*W* mfs_print: no element results found\n");
             end
         case "resultant"
             if (isfield(cmp.statresp, "elres"))
                for lc = 1 : cmp.statresp.elres.nofcol
                    titles{lc} = sprintf("Stress resultants of loadcase %2.0d", lc);
                end
                mfs_prt_elres(fid, cmp.statresp.elres, "resultant",
                              titles, sel);
             else
                printf("*W* mfs_print: no element results found\n");
             end
         case "none"
         otherwise
            printf("*W* mfs_print: unknown item ""%s""\n", items{k})
         end
     end     % Item

  case "modes"

     if (! isfield(cmp, "modes"));
        printf("*W* mfs_print: there are no items of class \"modes\"\n");
       return;
     end      

     for k = 1 : length(items)
         [itm, sel] = getitem(items{k}, cmp);
         switch itm
         case "disp"
            mfs_prt_modes(fid, cmp, headd, sel);
         case "freq"
            mfs_prt_freq(fid, cmp);
         case "reac"
            if (isfield(cmp.modes, "reac"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.modes.reac,
                                "Reaction loads of mode", headl,
                                4, sel);
            else
               printf("*W* mfs_print: item ""reac"" does not exists\n");
            end
         case "icsl"
            if (isfield(cmp.modes, "icsl"))
               mfs_prt_nodedata(fid, cmp.nodes, cmp.modes.icsl,
                                "Internal constraint loads of mode",
                                headl, 4, sel);
            else
               printf("*W* mfs_print: item ""icsl"" does not exists\n");
            end
         case "none"
         otherwise
            printf("*W* mfs_print: unknown item ""%s""\n", items{k})
         end
     end     % Item
       
  case "freqresp"

     if (! isfield(cmp, "freqresp"));
        printf("*W* mfs_print: there are no items of class \"freqresp\"\n");
       return;
     end      

     for lc = 1 : cmp.freqresp.nfa

         resp = cmp.freqresp.resp{lc};

         if (! resp.nback)
            printf("*W* mfs_print: no results to print for load case %2.0d\n",
                   lc);
            continue
         end

         for k = 1 : length(items)
             [itm, sel] = getitem(items{k}, cmp);
             switch itm
             case "disp"
                for nf = 1 : resp.nback
                    titles{nf} = ...
                      sprintf("Loadcase %2.0d: Displacements at %7.2f Hz",
                              lc, resp.freqback(nf));
                end
                mfs_prt_cdisp(fid, cmp.nodes, cmp.dofs.mxdofpnt, resp.U,
                              titles, headd, sel);
             case "velo"
                for nf = 1 : resp.nback
                    titles{nf} = ...
                      sprintf("Loadcase %2.0d: Velocities at %7.2f Hz",
                              lc, resp.freqback(nf));
                end
                iw = diag(2 * pi * i * resp.freqback);
                V  = resp.U * iw;
                mfs_prt_cdisp(fid, cmp.nodes, cmp.dofs.mxdofpnt, V,
                              titles, headd, sel);
             case "acce"
                for nf = 1 : resp.nback
                    titles{nf} = ...
                      sprintf("Loadcase %2.0d: Accelerations at %7.2f Hz",
                              lc, resp.freqback(nf));
                end
                w2 = diag((2 * pi * resp.freqback).^2);
                A  = -resp.U * w2;
                mfs_prt_cdisp(fid, cmp.nodes, cmp.dofs.mxdofpnt, A,
                              titles, headd, sel);
             case "stress"
                if (isfield(resp, "elres"))
                   for nf = 1 : resp.nback
                       titles{nf} = ...
                         sprintf("Loadcase %2.0d: Stresses at %7.2f Hz",
                                 lc, resp.freqback(nf));
                   end
                   mfs_prt_elres(fid, resp.elres, "cstress", titles, sel);
                else
                   printf("*W* mfs_print: no element results found for loadcase %2.0d\n",
                          lc);
                end
             case "strain"
                if (isfield(resp, "elres"))
                   for nf = 1 : resp.nback
                       titles{nf} = ...
                         sprintf("Loadcase %2.0d: Strains at %7.2f Hz",
                                 lc, resp.freqback(nf));
                   end
                   mfs_prt_elres(fid, resp.elres, "cstrain", titles, sel);
                else
                   printf("*W* mfs_print: no element results found for loadcase %2.0d\n",
                          lc);
                end
             case "resultant"
                if (isfield(resp, "elres"))
                   for nf = 1 : resp.nback
                       titles{nf} = ...
                         sprintf("Loadcase %2.0d: Stress resultants at %7.2f Hz",
                                 lc, resp.freqback(nf));
                   end
                   mfs_prt_elres(fid, resp.elres, "cresultant", titles, sel);
                else
                   printf("*W* mfs_print: no element results found for loadcase %2.0d\n",
                          lc);
                end
             case "none"
             otherwise
                printf("*W* mfs_print: unknown item ""%s""\n", items{k})
             end 
         end  % Item
         
     end      % Loadcase
       
  case "transresp"

     if (! isfield(cmp, "transresp"));
        printf("*W* mfs_print: there are no items of class \"transresp\"\n");
       return;
     end      

     for lc = 1 : cmp.transresp.nta

         resp = cmp.transresp.resp{lc};

         if (! resp.nback)
            printf("*W* mfs_print: no results to print for result case %2.0d\n",
                   lc);
            continue
         end

         for k = 1 : length(items)
             [itm, sel] = getitem(items{k}, cmp);
             switch itm
             case "disp"
                for nt = 1 : resp.nback
                    titles{nt} = ...
                      sprintf("Result case %2.0d: Displacements at %10.3e s",
                              lc, resp.tback(nt));
                end
                mfs_prt_disp2(fid, cmp.nodes, cmp.dofs.mxdofpnt, resp.u,
                              titles, headd, sel);
             case "velo"
                for nt = 1 : resp.nback
                    titles{nt} = ...
                      sprintf("Result case %2.0d: Velocities at %10.3e s",
                              lc, resp.tback(nt));
                end
                mfs_prt_disp2(fid, cmp.nodes, cmp.dofs.mxdofpnt, resp.v,
                              titles, headd, sel);
             case "stress"
                 if (isfield(resp, "elres"))
                    for nt = 1 : resp.elres.nofcol
                        titles{nt} = ...
                          sprintf("Result case %2.0d: Stresses at %10.3e s",
                                  lc, resp.tback(nt));
                    end
                    mfs_prt_elres(fid, resp.elres, "stress", titles, sel);
                 else
                    printf("*W* mfs_print: no element results found\n");
                 end
             case "strain"
                 if (isfield(resp, "elres"))
                    for nt = 1 : resp.elres.nofcol
                        titles{nt} = ...
                          sprintf("Result case %2.0d: Strains at %10.3e s",
                                  lc, resp.tback(nt));
                    end
                    mfs_prt_elres(fid, resp.elres, "strain", titles, sel);
                 else
                    printf("*W* mfs_print: no element results found\n");
                 end
             case "resultant"
                 if (isfield(resp, "elres"))
                    for nt = 1 : resp.elres.nofcol
                        titles{nt} = ...
                          sprintf("Result case %2.0d: Stress resultants at %10.3e s",
                                  lc, resp.tback(nt));
                    end
                    mfs_prt_elres(fid, resp.elres, "resultant", titles, sel);
                 else
                    printf("*W* mfs_print: no element results found\n");
                 end
             case "none"
             otherwise
                printf("*W* mfs_print: unknown item ""%s""\n", items{k})
             end 
         end  % Item
         
     end      % Loadcase

  case "diverg"

     if (! isfield(cmp, "diverg"))
        printf("*W* mfs_print: there are no items of class \"diverg\"\n");
        return;
     end

     for k = 1 : length(items)
         [itm, sel] = getitem(items{k}, cmp);
         switch itm
         case "qdyn"
            mfs_prt_qdyn(fid, cmp);
         case "disp"
            mfs_prt_divmodes(fid, cmp, cmp.dofs.mxdofpnt, headd, sel);
         case "none"
         otherwise
            printf("*W* mfs_print: unknown item ""%s""\n", items{k})
         end
     end     % Item

  case "trim"

     if (! isfield(cmp, "trim"));
        printf("*W* mfs_print: there are no items of class \"trim\"\n");
       return;
     end

     for k = 1 : length(items)
         [itm, sel] = getitem(items{k}, cmp);
         switch itm
         case "disp"
            mfs_prt_disp(fid, cmp.nodes, cmp.dofs.mxdofpnt,
                         cmp.trim.disp, 
                         "Displacements of configuration", headd, sel);
         case "stress"
             if (isfield(cmp.trim, "elres"))
                for lc = 1 : cmp.trim.elres.nofcol
                    titles{lc} = sprintf("Stresses of configuration %2.0d", lc);
                end
                mfs_prt_elres(fid, cmp.trim.elres, "stress", titles, sel);
             else
                printf("*W* mfs_print: no element results found\n");
             end
         case "strain"
             if (isfield(cmp.trim, "elres"))
                for lc = 1 : cmp.trim.elres.nofcol
                    titles{lc} = sprintf("Stains of configuration %2.0d", lc);
                end
                mfs_prt_elres(fid, cmp.trim.elres, "strain", titlesm, sel);
             else
                printf("*W* mfs_print: no element results found\n");
             end
         case "resultant"
             if (isfield(cmp.trim, "elres"))
                for lc = 1 : cmp.trim.elres.nofcol
                    titles{lc} = sprintf("Stress resultants of configuration %2.0d", lc);
                end
                mfs_prt_elres(fid, cmp.trim.elres, "resultant", titles, sel);
             else
                printf("*W* mfs_print: no element results found\n");
             end
         case "none"
         otherwise
            printf("*W* mfs_print: unknown item ""%s""\n", items{k})
         end
     end     % Item

  case "flutter"

     if (! isfield(cmp, "flutter"));
        printf("*W* mfs_print: there are no items of class \"flutter\"\n");
       return;
     end

     for k = 1 : length(items)
         [itm, sel] = getitem(items{k}, cmp);
         switch itm
         case "disp"
            title1 = sprintf("Flutter shape: ");
            for ns = 1 : cmp.flutter.nshape
                title2 = sprintf("mode  = %2.0d, point  = %3.0d, ",
                                 cmp.flutter.mode(ns), 
                                 cmp.flutter.point(ns));
                title3 = sprintf("v = %10.3e, f = %8.2f Hz",
                                 cmp.flutter.v(ns), cmp.flutter.f(ns));
                titles{ns} = [title1, title2, title3]; 
            end     
            mfs_prt_cdisp(fid, cmp.nodes, cmp.dofs.mxdofpnt,
                          cmp.flutter.disp, titles, headd, sel);
         case "none"
         otherwise
            printf("*W* mfs_print: unknown item ""%s""\n", items{k})
         end
     end     % Item

  otherwise

     printf("*W* mfs_print: unknown class ""%s""\n", class);

  end    % Class

end

function [itm, sel] = getitem(item, cmp)

# Input  item    Item to be processed
#        cmp     Structure with component data
#
# Output itm     Name of item
#        sel(:)  List with indices of objects selected
#
# The function resolves the item definition. It returns the item and
# the selector.
#
# ---------------------------------------------------------------------

  itm = "none";
  sel = [];

  if (! iscell(item))
     itm = item;
     return;
  else
     if (length(item) != 2)
        printf("*W* mfs_print: wrong definition of item \"%s\"\n",
               item{1});
        return;
     end
  end

  itm   = item{1};
  selct = item{2};

  switch itm

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

#    Nodal point data, return nodal point indices (in nodes)

     if (isnumeric(selct))
        sel  = lookup(cmp.nodes.ids, selct, "m");
        bad  = find(sel == 0);
        nbad = length(bad);
        if (nbad)
           for n = 1 : nbad
               printf("*W* mfs_print: node %6d does not exist\n",
                      selct(bad(n)));
           end
           ix  = find(sel);
           sel = sel(ix);
        end
     elseif (ischar(selct))
        if (isfield(cmp.nset, selct))
           sel = cmp.nset.(selct);
        else
           printf("*W* mfs_print: node set \"%s\" does not exist\n",
                  selct)
           itm = "none";
        end
     else
        printf("*W* mfs_print: selector of item \"%s\" has wong type\n",
               itm);
        itm = "none";
     end

  case {"reac", "icsl"}

#    Reaction loads, return 1 if only resultants are requested

     if (! ischar(selct) || ! strcmp(selct, "res"))
        printf("*W* mfs_print: wrong selector used with item \"%s\"\n",
               itm);
        itm = "none";
     else
        sel = 1;
     end

  case {"stress", "strain", "resultant"}

#    Element data, return element indices in elem

     if (isnumeric(selct))
        sel  = lookup(cmp.elements.index(:, 1), selct, "m");
        bad  = find(sel == 0);
        nbad = length(bad);
        if (nbad)
           for n = 1 : nbad
               printf("*W* mfs_print: element %6d does not exist\n",
                      selct(bad(n)));
           end
           ix  = find(sel);
           sel = sel(ix);
        end
        sel = cmp.elements.index(sel, 2);
     elseif (ischar(selct))
        if ((ixtyp = find(strcmp(selct, {cmp.elements.types.name}))))
           nofelt = cmp.elements.types(ixtyp).nofelt;
           ix1    = cmp.elements.types(ixtyp).ixelt1;
           ix2    = ix1 + nofelt - 1;
           sel    = ix1 : ix2;
        else
           if (isfield(cmp.eset, selct))
              sel = cmp.eset.(selct);
              sel = cmp.elements.index(sel, 2);
           else
              printf("*W* mfs_print: element set \"%s\" does not exist\n",
                     selct)
              itm = "none";
           end
        end
     else
        printf("*W* mfs_print: selector of item \"%s\" has wong type\n",
               itm);
        itm = "none";
     end

  end

end

function [itm, rsonly] = getitem_load(item)

# Input  item    Item to be processed
#
# Output itm     Name of item
#        rsonly  Is 1 if only output of resultants is requested
#
# The function resolves the item definition. It returns the item and
# the selector.
#
# ---------------------------------------------------------------------

  itm    = "none";
  rsonly = [];

  if (! iscell(item))
     itm = item;
     return;
  else
     if (length(item) != 2)
        printf("*W* mfs_print: wrong definition of item \"%s\"\n",
               item{1});
        return;
     end
  end

  itm   = item{1};
  selct = item{2};

  switch itm

  case "point"

#    Point loads, return 1 if only resultants are requested

     if (! ischar(selct) || ! strcmp(selct, "res"))
        printf("*W* mfs_print: wrong selector used with item \"%s\"\n",
               itm);
        itm = "none";
     else
        rsonly = 1;
     end

  end

end
