# Example: Instrument panel
#          Normal modes analysis
#
# ----------------------------------------------------------------

  fid  = fopen("modes.res", "wt");

# Data (N, mm)

  % Parameters

  nofmod  =    3;  % Number of normal modes
  D       = 0.02;  % Modal damping ratio

  M    = dlmread("Gxx.csv");
  fmax = M(1, end); % Maximum excitation frequency

  % Shell thickness

  shell = struct("t", 1);

  % Cross section of stiffeners

  h = 5;    % Height of bar
  b = 1;    % Width of bar

  bar = mfs_beamsection("bar", b, h);

  % Material data

  mat = struct("type", "iso", "E", 70000, "ny", 0.34,
               "rho", 2.7e-9);

  % Masses of instruments

  m_speed = struct("m", 205e-6);
  m_alti  = struct("m", 235e-6);
  m_vario = struct("m", 145e-6);

# Model definition

  data = struct("type", "solid", "subtype", "3d");

  % Beam elements

  bar.v = [1, 0, 0];
  bar.P = [0, 0.5 * h];
  data.Front_Stiffeners = struct("type", "elements", "name", "b2",
                                 "geom", bar, "mat", mat);

  bar.v = [0, 0, 1];
  data.Upper_Stiffeners = struct("type", "elements", "name", "b2",
                                 "geom", bar, "mat", mat);

  % Shell elements

  data.Panel = struct("type", "elements", "name", "s4",
                      "geom", shell, "mat", mat);

  % Altimeter

  data.Altimeter = struct("type", "elements", "name", "m1",
                          "geom", m_alti, "mat", []);

  % Air-speed indicator

  data.AirSpeed = struct("type", "elements", "name", "m1",
                          "geom", m_speed, "mat", []);

  % Variometer

  data.Vario = struct("type", "elements", "name", "m1",
                         "geom", m_vario, "mat", []);

  % Constraints

  data.Bearings = struct("type", "constraints",
                         "name", "prescribed",
                         "dofs", 1 : 6);

  % Node sets

  data.Fix_Altimeter = struct("type", "nodeset");
  data.CM_Altimeter  = struct("type", "nodeset");
  data.Fix_AirSpeed  = struct("type", "nodeset");
  data.CM_AirSpeed   = struct("type", "nodeset");
  data.Fix_Vario     = struct("type", "nodeset");
  data.CM_Vario      = struct("type", "nodeset");

  % Prescribed accelerations

  data.Right_Ax = struct("type", "loads", "name", "acce",
                         "data", [1, 0, 0], "lc", 1);
  data.Right_Az = struct("type", "loads", "name", "acce",
                         "data", [0, 0, 1], "lc", 2);
  data.Left_Ax  = struct("type", "loads", "name", "acce",
                         "data", [1, 0, 0], "lc", 3);
  data.Left_Az  = struct("type", "loads", "name", "acce",
                         "data", [0, 0, 1], "lc", 4);

  [model, nset] = mfs_import(fid, "panel.msh", "msh", data);

  % Connect altimeter

  dofa = cell(4, 2);
  dofa(:, 1) = num2cell(nset.Fix_Altimeter);
  dofa(:, 2) = 1 : 3;
  model.constraints.rigfit(1) = ...
    struct("nodd", nset.CM_Altimeter, "dofa", {dofa});

  % Connect air-speed indicator

  dofa(:, 1) = num2cell(nset.Fix_AirSpeed);
  dofa(:, 2) = 1 : 3;
  model.constraints.rigfit(2) = ...
    struct("nodd", nset.CM_AirSpeed, "dofa", {dofa});

  % Connect variometer

  dofa(:, 1) = num2cell(nset.Fix_Vario);
  dofa(:, 2) = 1 : 3;
  model.constraints.rigfit(3) = ...
    struct("nodd", nset.CM_Vario, "dofa", {dofa});

  % Damping

  model.damping = struct("type", "ratios", "data", D);

# Analysis

  panel = mfs_new(fid, model);
  mfs_export("panel.axes", "msh", panel, "mesh", "axes");
  mfs_print(fid, panel, "load", "acce");

  panel = mfs_stiff(panel);
  panel = mfs_mass(panel);
  mfs_massproperties(fid, panel);

  panel = mfs_freevib(panel, nofmod);
  mfs_print(fid, panel, "modes", "freq");
  mfs_export("modes.dsp", "msh", panel, "modes", "disp");

  mfs_reductionerror(fid, panel, fmax);

# Save results

  save -binary modes.bin panel

  fclose(fid);
