VIBES Toolbox Tutorials

The easiest way of familiarising with a software product – especially with MATLAB-based products – is by learning from existing pieces of code. The VIBES Toolbox for MATLAB comes with tutorials that demonstrate some of the core technology in simple step-by-step scripts. From here on, one takes a jump-start into Dynamic Substructuring, Experimental Modelling and Transfer Path Analysis.

The tutorials that ship with the Toolbox are listed here to give an impression of the functionalities, object-oriented way of working and data management.

Measurement Definition in the 3D environment

This tutorial covers the preparation a FRF measurement using an impact hammer. In the 3D environment of the VIBES Toolbox, one is able load CAD geometry (e.g. STL-file format) and place sensors and impact locations on the structure. Hereafter, one can export this measurement set-up in Data Acquisition software for the actual measurement.

If a finite element model of the structure is available in ANSYS (or alternatively M, K and C-matrices from another CAE-package), one is able to simulate the FRF measurement with the FEM-class of the Toolbox.

Furhermore, this FRF measurement set-up can be used for pre-analysis for experimental modelling of a struture using the Virtual Point transformation, click here.

Show CAD geometry in 3D viewer

Locate your STL-file in the repository with vibes.browse or specify the full file name using parts:

fn_stl = vibes.fullfile('Geometry','stl','subsA.stl');

% Open Figure3d
V = vibes.figure3d();
V.skyMode();

% Add geometry to the 3D figure
V.addGeometry(fn_stl)

Familiarising with the 3D viewer

Use the Right Mouse Button on an object to open a context menu, with self-explaining functions.

Place sensors and impacts by opening the context menu (RMB on structure) in the 3D environment. Use SHIFT+LMB or CTRL+LMB functions to move and rotate the sensors and impacts. Press SHIFT while rotating to snap to 30 degree angle rotations.

Keyboard shortkeys for camera and axes control:

  • (SHIFT)-1,2,3,4 - Transition camera to default positions
  • 0 - Reset camera
  • p - Change to perspective view
  • o - Change to orthogonal view
  • x - Toggle axes
  • g - Toggle grid (if axes are present)

Open the Figure3D object V in the workspace and check the properties. Observe that the object V contains the sensors and impacts that have been placed on the structure.

Save the Measurement Definition

Now the measurement is prepared, one can write the definition to a XLS-file. This file can be used for the definition of the measurement in your Data Acquisition System.

% Derive measurement Impacts and sensors from the 3D figure 'V'
Impacts = V.Impacts;
Sensors = V.Sensors;
Channels = Sensors.toChannel();

% Name for the EXCEL file
fn_xls = vibes.fullfile('Meta','Dummy.xlsx');

% Save the data
Sensors.writeXls(fn_xls,'sheet','Sensors');
Impacts.writeXls(fn_xls,'sheet','RefChannels');
Channels.writeXls(fn_xls,'sheet','Channels');

% Observe that the XLS-file is automatically stored in the repository, i.e.
% in the meta-data folder of the current project.

Edit an existing measurement definition

In this part, we are going to edit an existing measurement definition. Editting the measurement definition in can be done in MS Excel, but for now we will edit the XLS-file using the Toolbox.

% Locate the measurement definition (Dummy.xlsx)
fn_xls = vibes.fullfile('Meta','Dummy.xlsx');

% Load the sensors and impact from the right sheets in the XLS-file
sensors = vibes.ui.Sensor.fromXls(fn_xls,'Sensors');
impacts = vibes.ui.Impact.fromXls(fn_xls,'RefChannels');

% Assign a Grouping number to the sensors 1 and 2 by quering upon
% 'NodeNumber':
idx = sensors.find('NodeNumber',[1,2]);
sensors(idx).setArray('Grouping',1);

% Derive channels from sensors
channels = sensors.toChannel();

% Write the updated sensors and channels to the XLS-file
sensors.writeXls(fn_xls,'sheet','Sensors')
channels.writeXls(fn_xls,'sheet','Channels')

% Open the XLS-file to check it out!
winopen(fn_xls)

Version 1.1 | Last changed: April 2017 Copyright © 2017 Vibes Technology B.V. All rights reserved.

Experimental Modelling of a structure

This tutorial covers the experimental modelling of the structure using the virtual point transformation. One obtains a six degrees of freedom description of the coupling point of the structure. This model is suitable for Frequency Based Substructuring.

For more info: https://www.researchgate.net/publication/265793082

Load FRF matrix

Browse the repository to locate the FRF measurement of subsA.

% Load the FRFs of structure A.
YA = vibes.load('VIBES,Example,Dataset','mat','YA.FRFMatrix.mat');

Visualise the measurement on component A

Solely for demonstration purposes, the measurement on component A is visualised here.

% Locate the geometry on the structure
fn_geoA = vibes.fullfile('VIBES,Examples,geometry','subsA.mat');

% Open the 3D viewer and display the geometry
V = vibes.figure3d();
V.addGeometry(fn_geoA);

% Locate the XLS-file with the corresponding measurement definition
fn_xls = vibes.fullfile('Meta','Tutorials.xlsx');

% Load sensors and impacts
sensors = vibes.ui.Sensor.fromXls(fn_xls,'A_Sensors');
impacts = vibes.ui.Impact.fromXls(fn_xls,'A_Impacts');

% Plot in the 3D environment
sensors.plot();
impacts.plot();

Plot Frequency Response Functions

The VIBES Toolbox has lots of plot settings available.

% Find Channel 3 in the Channel array
dof_i = YA.Channels.find('Name','==','Channel 3');

vibes.figure('FRF-plot');
subplot(2,1,1)
YA.plot(dof_i, 1, 0:2000,'PlotType','log', 'Style', '2b-','Label','Example FRF')

subplot(2,1,2)
YA.plot(dof_i, 1, 0:2000,'PlotType','phase', 'Style', '2b-')

Consistency checks

An important feature of the virtual point transformation is the ability to quantify the consistency of the measurement. Classical coherence functions can assess the consistency of single FRFs, but they do not tell if a set of multiple FRFs is dynamically plausible. The consistency function in the toolbox is a quality indicator for the measured response to a load case (sensor consistency) and similarily for the excitation positions/orientations (hammer consistency).

% Selection of DoFs for consistency checks
dofs_i = YA.Channels.find('Grouping',1);
dofs_j = YA.RefChannels.find('Grouping',1);

Sensor consistency: check the overall consistency of the sensor channels belonging to grouping 1

YA.consistency(dofs_i,16,[0 3000],'Dim','Sensor','Type','Overall');

Hammer consistency: identify which individual impacts contribute to rigid behaviour of the interface point. One impact channel is marked as inconsistent impact (try yourself!):

wrong_j = [12];
dofs_j  = setdiff(dofs_j,wrong_j);

YA.consistency(dofs_i,dofs_j,[0 3000],'Dim','Hammer','Type','Spec','Ave',true);

Virtual Point Transformation

The virtual point transformation maps the physical measurement channels onto a set of virtual channels to obtain a nodal description of the interface. The interface connectivity is reduced to virtual points using a predefined set of interface displacement modes (IDMs).

% Load virtual channels
qA = vibes.Channel.fromXls(fn_xls,'sheet','VP Channels');
mA = vibes.Channel.fromXls(fn_xls,'sheet','VP RefChannels');

Create IDM matrix fot the sensor channels

IDMu = YA.Channels.createIDMMatrix(qA);

Create an IDM matrix fot the force channels. Observe that two impacts on the structure (belonging to group 10) will be kept out of the virtual point transformation. Instead, they are "forwarded" to the resulting list of channels, ending up right after the virtual forces/moments. These two impacts will be used for validation purposes, after structure A and structure B are coupled.

% Obtain all impact channels
fA = YA.RefChannels(dofs_j);

% Retain the impacts that belong to group 10
fA_extra = fA.select('Grouping',10);

% Create IDM matrix fot the impact channels
IDMf = fA.createIDMMatrix([mA; fA_extra]);

Visualise the transformation matrix (note the impacts fA_extra!)

IDMf.spy();

Create virtual FRFs by applying both virtual point transformations on either sides of the original (measured) FRF data:

Yqm = IDMu * YA * IDMf;

Store for later use

Store the experimental model in the current folder:

Yqm.save('Yqm');

% Also, store in the data repository for archiving or later retrieval:
Yqm.save('VIBES,examples,datasets','Yqm');

Version 1.0 | Last changed: April 2017 Copyright © 2017 Vibes Technology B.V. All rights reserved.

Finite Element Modelling

The FEM module of the VIBES Toolbox allows for import of ANSYS FEM models, calculation of modal parameters and synthesis of FRFs. To succesfully import a model, one first has to export the M and K matrices and additional model information (i.e. NodeTable, Mapping, Units etc.) from ANSYS. This is done via added APDL script to the Solution in ANSYS, see the file 'ansys_export.txt' for the required APDL script.

Load the ANSYS model

Load the ANSYS output files. To do so, you have to locate the ANSYS output file folder and create a object of class AnsysImport to import the files.

% Locate the ANSYS output file folder
fn_fld = vibes.fullfile('VIBES,Examples,Datasets','ansys');

% Check the ANSYS output files outside MATLAB
winopen(fn_fld)

Construct the object of class AnsysImport and set the folder. Please note that this only works in the standard ANSYS Output naming. If a custom ANSYS Output naming is used, you are able to set the ANSYS output-files individually in the object of class AnsysImport.

% Create importer object and set all import files
AnsImp = vibes.util.ansys.AnsysImport();
AnsImp.setFolder(fn_fld);

Construct the physical model of class vibes.MCKModel; please inspect the object!

mck = AnsImp.toMCKModel();

Convert the physical model to the modal domain

Now, one is able to transform the physical MCK-model to the modal domain. With the use of an eigensolver, the modal parameters can be derived i.e. the natural frequencies and modeshapes.

In the modal domain, one is able to apply reduction methods, which are known under the name component mode synthesis (CMS). Techniques such as the Hurty-Craig-Bampton, Rubin and McNeal are common reduction methods, which will available in the offical release of the Toolbox (after trial).

% Create object of class ModalModel and calculate the first 100 eigenmodes
nModes = 100;
mModel = mck.toModalModel(nModes);

% Add modal damping of 0.3%
zeta = 0.003;
mModel.addModalDamping(zeta);

% Plot/animate a mode
modeIdx = 8;
mModel.Modes(modeIdx).plotMode();

FRF measurement - DoF selection

You can synthesise FRFs and construct FRFMatrix object directly from the ModalModel class. To do so, degrees of freedom have to be specified. Basically, there are two options to provide these inputs:

  1. Find Nodes and/or DoFs from the MCK-model;
  2. Place sensors and impact locations in the 3D Environment.

First, it is demonstrated how to find and select DoFs. The MCKModel and ModalModel classes contain NodeTable and DoFTable objects. please be aware that the Nodes and the DoFs are not (directly) related.

% Get a single node from the NodeTable
nodeA = mck.NodeTable.getNode(1);

% Get an array of nodes based on its position
nodeC = mck.NodeTable.selectNode('Position',[0 0 0],'Amount',1);

% Get the node indices in the vicinity of a physical location
nodeB = mck.NodeTable.findNode('Position',[0 0 0],'Radius',0.01,'Amount',10);

% Get a single DoF from the DoFTable index
dofA = mck.DoFTable.getDoF(1);

% Get an array of DoFs based on its NodeNumber and direction
dofC = mck.DoFTable.selectDoF('Node',1:10,'Direction','Ux');

% Get DoF indices from the DoFTable
dofB = mck.DoFTable.findDoF('Node',1:10,'Direction',[1 2 3]);

% Get doF indices With the Node numbers
dofD = mck.DoFTable.findDoF('Node',nodeB);

FRF measurement - Virtual measurement equipment

Another convienent way to select DoFs for the FRF synthesis, is to place sensors and impacts on the structure in the 3D enviromment. For a more elaborate description on measurement preparation, see the specific measurement preparation tutorial here.

% Open 3D viewer and load the structure
fn = vibes.fullfile('Geometry','subsA.mat');
V = vibes.figure3d(); V.skyMode; hold on
V.addGeometry(fn)

% Plot Nodes
mck.NodeTable.plotNodes();

% Place sensors/impacts in the 3D environment or load sensoras and impacts.
fn_xls  = vibes.fullfile('Meta','Tutorials.xlsx');
Sensors = vibes.ui.Sensor.fromXls(fn_xls,'sheet','A_Sensors');
Impacts = vibes.ui.Impact.fromXls(fn_xls,'sheet','A_Impacts');

Sensors.plot();
Impacts.plot();

FRF synthesis

Synthesise FRFs (accelerance) using sensors and impact which are placed on the struture under test.

% Specify the Frequency Range
FreqRange = 0:2000;
FRFType = 2; % 0 = receptance, 1 = mobility, 2 = accelerance

% Construct the FRFMatrix object!
YAB = mModel.simulateImpactMeasurement(Sensors,Impacts,FreqRange,FRFType);

Version 1.1 | Last changed: April 2017 Copyright © 2017 Vibes Technology B.V. All rights reserved.

Dynamic Substructuring

In this tutorial, the structural dynamics of structure A and structure B will be coupled using Frequency Based Substructuring. The two separate structures have collocated DoFs on their interface. The nodal description of the interface is obtained with the Virtual Point Transformation, see here for more information of this topic.

Load the substructure FRFs

  1. Load the FRFs of the two separate structures A and B. These will be coupled using dynamic substructuring.
  2. Load the FRFs of the assembled structure. These FRFs are obtained by a (virtual) measurement of the structures A and B coupled together. These FRFs will serve as validation FRFs.
% Load the FRFs of the two separate structures A and B.
YA  = vibes.load('Datasets','mat','YAqm.FRFMatrix.mat');
YB  = vibes.load('Datasets','mat','YBqm.FRFMatrix.mat');

% Load the FRFs of the assembled structure.
YAB = vibes.load('Datasets','mat','YAB.FRFMatrix.mat');

Frequency Based Substructuring: the easy way

Both FRFMatrix objects contain Channel and RefChannels information. The toolbox will automatically match the right degrees of freedom, resulting in fully coupled substructures. This means that both compatibility and equililbrium conditions are met. The default operation returns the DoFs of the dual assembly, meaning that the coupling DoFs appear twice.

YAB_DS = couple(YA,YB);

Verify the results. Compare the coupled FRFs with the ones of the validation measurement.

% Select the Channel DoFs
ch_i = {'Description', 'Sensor 5 Z'};

% Select the RefChannel DoFs
ch_j = {'Name','Impact 22'};

freq = [0 3000];

vibes.figure('DS'); clf
YAB.plot(ch_i,ch_j,freq,'PlotType','log','Style','2b','Label','Validation'), hold on
YAB_DS.plot(ch_i,ch_j,freq,'PlotType','log','Style','2r','Label','DS')

ylim([1e-4 1e2])
legend show

Frequency Based Substructuring: LM-FBS with more control

Using additional options of the couple command, one is able to control the compatibility and equilibruim conditions of FBS. The available options include:

  • Compatibility to define the compatibility DoFs
  • Equilibrium to define the equilibrium DoFs
  • OutputDoFs to select dual or primal output format
  • Symmetrize to perform symmetrization of the matrices before coupling
% FBS coupling with control over the coupling conditions:
[YAB_DS2, Info] = couple(YA,YB, ...
    'Compatibility',{'Quantity','Rot','Grouping',1}, ...
    'Equilibrium',{'Unit','N','Grouping',1}, ...
    'OutputDoFs','primal');

% The compatibility (C) and equilibrium (E) that are used for the coupling
% FRFs are returned in the additional output structure:

disp(Info)

It is also possible to define the compatibility (C) and equilibruim (E) matrices yourself, hereby one one has full freedom to apply FBS. Obviously, you are free the develop your own de-/coupling routines, while using the bookkeeping functionalities of the VIBES Toolbox.

YAB = vibes.math.lmfbs(YA.Data,YB.Data,C,E,symmetrize);

Save the coupled structures in the repository

% YDS.save('YDS');

% Version 1.0 | Last changed: February 2017
% Copyright © 2017 Vibes Technology B.V. All rights reserved.

Blocked Force TPA

For a reliable prediction of vibro-acoustic performance of a vibration source in a source-receiver structure, one can use blocked-force TPA. The vibration source can be characterised by a set of blocked forces at the interface between the source and receiver structure. These blocked forces are an inherent property of the source and can therefore be applied to a dynamically different receiver.

In this tutorial we are going to characterise the active structure A on its interface. A force impact randomly applied to the structure is taken as an operational excitation.

Load FRF Matrix objects

YAB = vibes.load('VIBES,Examples,Datasets','mat','YABm.FRFMatrix.mat');

Operational Excitations

% Load an Operational Measurement (TimeSeries)
TS = vibes.load('VIBES,Examples,datasets','mat','Operational_Measurements.TimeSeries.mat');

% Choose the channel to track
ch_spd = TS.Channels.find('Name','MotorSpeed');

% Build the Block object with the tracked values
B = vibes.Block.fromTimeSeries(TS,'TrackChannel',ch_spd,'TrackValues',[33, 50, 60],'Align','left');

% Plot the engine Speeds
vibes.figure('Engine Speed')
TS.plot(ch_spd)
dashedline('x',[B.t1 B.t2])

% Build the TimeBlocks object
TB = vibes.TimeBlocks.fromTimeSeries(TS,B);

% Obtain Spectra
u = vibes.FreqBlocks.fromTimeBlocks(TB,'hann',YAB.Freq);

Characterise the vibration source

Calculate blocked forces with the sensors belonging to Group 1 with the in-situ method. There is no need to select the right channels in vector u as the corresponding channels are matched automatically. As the FRFs of the full structure are one-sided transformed to virtual forces, one obtains a six-DoF force description, hence forces and moments.

fbl = YAB.subs({'Grouping',1},[]) \ u;

Matrix regularisation

To gain more control over the matrix-inverse operation, one is able to use several matrix regularisation techniques, e.g. absolute and relative singular value truncation, Tikhonov regularisation and column balancing.

Please browse the documentation for more options: vibes.math.matrixinverse.

% Simulate white noise with |u_RMS = 1e-3| on the measured signals
u_noise = u.addNoise([],[],1e-3);

% Calculate incomplete inverse: 10% relative threshold and only the first 3
% singular values
[fbl_tr, Info] = YAB.matrixinverse(u_noise,'RelThreshold',0.1,'SingularValues',1:3);

% Display information on the matrix-inverse operation
disp(Info)

On-board TPA validation

Apply the blocked forces to the FRFs of assembly AB and simulate the responses on the passive side.

u_tpa = YAB * fbl;
u_tpa_tr = YAB * fbl_tr;

Plot simulation against the validation

Let us now evaluate the blocked-force TPA prediction against a validation measurement. The truncated inverse with noisy input signal is plotted too.

ch_i = 'Channel 19';
idx_b = 3;

plotType = 'maglog';
sm = 10;

vibes.figure('On-Board Validation'); clf
u.plot(ch_i,idx_b,[0 2000],'PlotType',plotType,'Smoothing',sm,'Style','2k','Label','Validation'); hold on
u_tpa.plot(ch_i,idx_b,[0 2000],'PlotType',plotType,'Smoothing',sm,'Style','2b--','Label','TPA: On-board validation')
u_tpa_tr.plot(ch_i,idx_b,[0 2000],'PlotType',plotType,'Smoothing',sm,'Style','2g-.','Label','TPA: Noise / truncated inverse')

legend location SE