4.8  Sensors : Data structure and init commands#

Sensors related to a finite element model are stored in the model structure as a SensDof case entry. This is a reference section on SensDof case entries. A tutorial on the basic configuration with a test wire frame and translation sensors is given in section 2.8 and the high level definition format of sensors is documented in section ??.

4.8.1  SensDof Data structure#

SensDof entries describe a sensor configuration and can contain the following fields


sens.tdofThe sens.tdof field declares translation sensors and their directions
  • [SensID NodeId nx ny nz] is the nominal 5 column matrix with rows giving a sensor identifier (integer or real), a node identifier, a direction.
  • can be single column DOF definition vector which can be transformed to 5 column format using tdof = fe_sens('tdof',sens.tdof)
  • SensId gives an identifier for each sensor. It should thus be unique and there may be conflicts if it is not.
  • NodeId specifies a node identifier for the spatial localization of the sensor. If not needed (resultant sensors for example), NodeId can be set to zero.

    NodeId>0 corresponds is for use of model.Node locations and sens.Node should not be defined. This should be used with Sens.InFEM=1 (the NodeId is sometimes then called FEMId in the documentation/code).

    NodeId<0 is used to look for the node position in sens.Node rather than model.Node and one expects Sens.InFEM=0 since Mixed definitions (some NodeId positive and other negative) are not supported.

    The use of a .vert0 field is deprecated.

  • nx ny nz specifies a measurement direction for sensors that need one.
sens.Nodeoptional nodes for test wireframe (sensor nodes that are not in the model). When defined, all node numbers in sens.tdof should refer to these nodes. The order typically differs from that in .tdof, you can get the positions with fe_sens('tdofNode',model,SensName).
sens.Elttest wireframe element description matrix.
sens.basCoordinate system definitions for sens.Node, see fe_sens basis. This is used in a transient fashion in dockCoTopo but should be avoided otherwise.
sens.InFEM1 when using nodes located in a FEM model. 0 when using wireframe nodes using their own definition.
sens.DOFDOF definition vector for the analysis (finite element model). It defines the meaning of columns in sens.cta. Two versions exist : DOF equal to the full FEM DOF (obtained with fe_case Sens), and DOF associated with superelement DOF (equal to SE.TR.adof, obtained with fe_case sensSE2)
sens.ctais an observation matrix associated with the observation equation {y}=[c]{q} (where q is defined on sens.DOF ). This is built using the fe_case sens command illustrated below.
sens.Stackcell array with one row per sensor giving 'sens','SensorTag',data with data is a structure. SensorTag is obtained from SensId (first column of tdof) using feutil('stringdof',SensId). It is used to define the tag uniquely and may differ from the label that the user may want to associated with a sensor which is stored in data.lab. data.time may contain 'u','v','a' to request the use of time derivatives (not yet fully supported).
sens.Selmay be used to store a feplot selection to view the mesh or a FEM representation associated with sensors.
sens.nmapcontains name maps. In particular Map:Nodes gives a node name to node number mapping. Map:tlab gives a sensor label to SensId mapping. Map:TestLab provides a data acquisition channel name to final sensor label mapping (upon reading test data, one expect tlab rather than TestLab labels).
sens.Editvhandle.uo handle object containing options for display, animation, ...

Use cases are

  • animate test. Are then needed: nodes for sensors position, sensor orientations, possibly wire-frame (elements connecting sensors) to ease viewing.
  • predict model outputs :
  • observe full FEM or superelement response on sensors (use for correlation)
  • estimate states/model view from sensors (expansion)

4.8.2  SensDof init commands#

All sensors are generated with the command
fe_case(model,'SensDof <append, combine> Sensor_type',Sensor,data,SensLab)
Sensor is the case entry name to which sensors will be added. data is a structure, a vector, or a matrix, which describes the sensor to be added. The nature of data depends on Sensor_type as detailed below. SensLab is an optional cell array used to define sensor labels. There should be as much elements in SensLab as sensors added. If there is only one string in the cell array SensLab, it is used to generate labels substituting for each sensor $id by its SensId, $type by its type (trans, strain ...), $j1 by its number in the set currently added. If SensLab is not given, default label generation is $type_$id.
In the default mode ('SensDof' command), new sensors replace any existing ones. In the append mode ('SensDof append'), if a sensor is added with an existing SensID, the SensID of new sensor will changed to a free SensID value. In the combine mode ('SensDof combine'), existing sensor with the same SensID will be replaced by the new one.

rel#

Relative displacement sensor or relative force sensor (spring load). Data passed to the command is [NodeID1 NodeID2].

This sensor measures the relative displacement between NodeID1 and NodeID2, along the direction defined from NodeID1 to NodeID2. One can use the command option -dof in order to measure along the defined DOF directions (mandatory if the two nodes are coincident). As many sensors as DOF are then added. For a relative force sensor, on can use the command option -coef to define the associated spring stiffness (sensor value is the product of the relative displacement and the stiffness of the spring).

If some DOF are missing, the sensor will be generated with a warning and a partial observation corresponding to the found DOF only.

The following example defines 3 relative displacement sensors (one in the direction of the two nodes, and two others along x and y):

model=demosdt('demo ubeam-pro')
data=[30 372];
model=fe_case(model,'SensDof append rel','output',data);
model=fe_case(model,'SensDof append rel -dof 1 2','output',data);

general#

General sensors are defined by a linear observation equation. This is a low level definition that should be used for sensors that can't be described otherwise. Data passed to the command is a structure with field .cta (observation matrix), .DOF DOF associated to the observation matrix, and possibly .lab giving a label for each row of the observation matrix.

The following example defines a general sensor

model=demosdt('demo ubeam-pro');
Sensor=struct('cta',[1 -1;0 1],'DOF',[8.03; 9.03]);
model=fe_case(model,'SensDof append general','output',Sensor);

trans#

Translation sensors (see also section 2.8.2) can be specified by giving

[DOF]
[DOF, BasID]
[SensID, NodeID, nx, ny, nz]
[SensID, x, y, z, nx, ny, nz]

This is often used with wire frames, see section 2.8.2. The definition of test sensors is given in section 3.1.1.

The basic case is the measurement of a translation corresponding the main directions of a coordinate system. The DOF format (1.02 for 1y, see section 7.5) can then be simply used, the DOF values are used as is then used as SensID. Note that this form is also acceptable to define sensors for other DOFs (rotation, temperature, ...).

A number of software packages use local coordinate systems rather than a direction to define sensors. SDT provides compatibility as follows.

If model.bas contains local coordinate systems and deformations are given in the global frame (DID in column 3 of model.Node is zero), the directions nx ny nz (sens.tdof columns 3 to 5) must reflect local definitions. A call giving [DOF, BasID] defines the sensor direction in the main directions of basis BasID and the sensor direction is adjusted.

If FEM results are given in local coordinates, you should not specify a basis for the sensor definition, the directions nx ny nz (sens.tdof columns 3 to 5) should be [1 0 0], ... as obtained with a simple [DOF] argument in the sensor definition call.

When specifying a BasId, it the sensor direction nx ny nz is adjusted and given in global FEM coordinates. Observation should thus be made using FEM deformations in global coordinates (with a DID set to zero). If your FEM results are given in local coordinates, you should not specify a basis for the sensor definition. You can also perform the local to global transformation with

cGL= basis('trans E',model.bas,model.node,def.DOF)
def.def=cGL*def.def


The last two input forms specify location as x y z or NodeID, and direction nx ny nz (this vector need not be normalized, sensor value is the scalar product of the direction vector and the displacement vector).

One can add multiple sensors in a single call fe_case(model,'SensDof <append> trans', Name, Sensor) when rows of sensors contain sensor entries of the same form.

Following example defines a translation sensor using each of the forms

model=demosdt('demo ubeam-pro')
model.bas=basis('rotate',[],'r=30;n=[0 1 1]',100);
model=fe_case(model,'SensDof append trans','output',...
  [1,0.0,0.5,2.5,0.0,0.0,1.0]);
model=fe_case(model,'SensDof append trans','output',...
  [2,8,-1.0,0.0,0.0]);
model=fe_case(model,'SensDof append trans','output',[314.03]);
model=fe_case(model,'SensDof append trans','output',...
  [324.03 100]);
cf=feplot;cf.sel(2)='-output';cf.o(1)={'sel2 ty 7','linewidth',2};

Sens.Stack entries for translation can use the following fields


.vert0physical position in global coordinates.
.IDNodeId for physical position. Positive if a model node, negative if SensDof entry node.
.matchcell array describing how the corresponding sensor is matched to the reference model. Columns are ElemF,elt,rstj,StickNode.


dof#

One can simply define a set of sensors along model DOFs with a direct SensDof call model=fe_case(model,'SensDof','SensDofName',DofList). There is no need in that case to pass through SensMatch step in order to get observation matrix.

model=demosdt('demo ubeam-pro')
model=fe_case(model,'SensDof','output',[1.01;2.03;10.01]);
Sens=fe_case(model,'sens','output')

triax,laser#

A triax is the same as defining 3 translation sensors, in each of the 3 translation DOF (0.01, 0.02 and 0.03) of a node. Use fe_case(model,'SensDof append triax', Name, NodeId) with a vector NodeId to add multiple triaxes. A positive NodeId refers to a FEM node, while a negative refers to a wire frame node.

For scanning laser vibrometer tests
fe_sens('laser px py pz',model,SightNodes,'SensDofName')
appends translation sensors based on line of sight direction from the laser scanner position px py pz to the measurement nodes SightNodes. Sighted nodes can be specified as a standard node matrix or using a node selection command such as 'NodeId>1000 & NodeId<1100' or also giving a vector of NodeId. If a test wire frame exists in the SensDofName entry, node selection command or NodeId list are defined in this model. If you want to flip the measurement direction, use a call of the form

cf.CStack{'output'}.tdof(:,3:5)=-cf.CStack{'output'}.tdof(:,3:5)

The following example defines some laser sensors, using a test wire frame:

[model,TEST]=demosdt('demo GartDataCotopo'); % load FEM + TEST wireframe
TEST.tdof=[];%Define test wire frame, but start with no tdof
model=fe_case(model,'SensDof','test',TEST);
% Add triax sensor at wireframe point 1001
model=fe_case(model,'SensDof Append Triax','test',-TEST.Node(1));
% Add laser sensors (measured from point 0 0 6) on TEST wire frame location 
model=fe_sens('laser 0 0 6',model,-TEST.Node(2:end,1),'test');
% Show result
cf=feplot(model);fecom(cf,'ShowFiTestDef'); % Display Wireframe only 
fecom('curtab Cases','output'); fecom('proviewon');

To add a sensor on FEM node you would use model=fe_sens('laser 0 0 6',model,20,'test'); but this is not possible here because SensDof entries do not support mixed definitions on test and FEM nodes.

strain,stress#

Note that an extended version of this functionality is now discussed in section 4.9. Strain sensors can be specified by giving

[SensID, NodeID]
[SensID, x, y, z]
[SensID, NodeID, n1x, n1y, n1z]
[SensID, x, y, z, n1x, n1y, n1z]
[SensID, NodeID, n1x, n1y, n1z, n2x, n2y, n2z]
[SensID, x, y, z, n1x, n1y, n1z, n2x, n2y, n2z]

when no direction is specified 6 sensors are added for stress/strains in the x, y, z, yz, zx, and xy directions (SensId is incremented by steps of 1). With n1x n1y n1z (this vector need not be normalized) on measures the axial strain in this direction. For shear, one specifies a second direction n2x n2y n2z (this vector need not be normalized) (if not given n2 is taken equal to n1). The sensor value is given by {n2}T[є]{n1}.
Sensor can also be a matrix if all rows are of the same type. Then, one can add a set of sensors with a single call to the fe_case(model,'SensDof <append> strain', Name, Sensor) command.

Following example defines a strain sensor with each possible way:

model=demosdt('demo ubeam-pro')
model=fe_case(model,'SensDof append strain','output',...
  [4,0.0,0.5,2.5,0.0,0.0,1.0]);
model=fe_case(model,'SensDof append strain','output',...
  [6,134,0.5,0.5,0.5]);
model=fe_case(model,'SensDof append strain','output',...
  [5,0.0,0.4,1.25,1.0,0.0,0.0,0.0,0.0,1.0]);
model=fe_case(model,'SensDof append strain','output',...
  [7,370,0.0,0.0,1.0,0.0,1.0,0.0]);

Stress sensor.
It is the same as the strain sensor. The sensor value is given by {n2}T[σ]{n1}.
Following example defines a stress sensor with each possible way:

model=demosdt('demo ubeam-pro')
model=fe_case(model,'SensDof append stress','output',...
  [4,0.0,0.5,2.5,0.0,0.0,1.0]);
model=fe_case(model,'SensDof append stress','output',...
  [6,134,0.5,0.5,0.5]);
model=fe_case(model,'SensDof append stress','output',...
  [5,0.0,0.4,1.25,1.0,0.0,0.0,0.0,0.0,1.0]);
model=fe_case(model,'SensDof append stress','output',...
  [7,370,0.0,0.0,1.0,0.0,1.0,0.0]);

Element formulations (see section 6.1) include definitions of fields and their derivatives that are strain/stress in mechanical applications and similar quantities otherwise. The general formula is {є}=[B(r,s,t)]{q}. These (generalized) strain vectors are defined for all points of a volume and the default is to use an exact evaluation at the location of the sensor.

In practice, the generalized strains are more accurately predicted at integration points. Placing the sensor arbitrarily can generate some inaccuracy (for example stress and strains are discontinuous across element boundaries two nearby sensors might give different results). The -stick option can be used to for placement at specific gauss points. -stick by itself forces placement of the sensor and the center of the matching element. This will typically be a more appropriate location to evaluate stresses or strains.

To allow arbitrary positioning some level of reinterpolation is needed. The procedure is then to evaluate strain/stresses at Gauss points and use shape functions for reinterpolation. The process must however involve multiple elements to limit interelement discontinuities. This procedure is currently implemented through the fe_caseg('StressCut') command, as detailed in section 4.9.

resultant#

Resultant sensors measure the resultant force on a given surface. Note that the observation of resultant fields is discussed in section 4.9.3. They can be specified by giving a structure with fields


.IDsensor ID.
.EltSelFindElt command that gives the elements concerned by the resultant.
.SurfSelFindNode command that gives the surface where the resultant is computed.
.dirwith 3 components direction of resultant measurement, with 6 origin and direction of resulting moment in global coordinates. This vector need not be normalized (scalar product). For non-mechanical DOF, .dir can be a scalar DOF ( .21 for electric field for example)
.typecontains the string 'resultant'.

Following example defines a resultant sensor:

model=demosdt('demo ubeam-pro')
Sensor.ID=1;
Sensor.EltSel='WithNode{z==1.25} & WithNode{z>1.25}';
Sensor.SurfSel='z==1.25';
Sensor.dir=[0.0 0.0 1.0];
Sensor.type='resultant';
model=fe_case(model,'SensDof append resultant','output',Sensor);

Resultant sensors are not yet available for superelements model.