Bug Summary

File:masstranAIM.cpp
Warning:line 1338, column 13
Potential leak of memory pointed to by 'feaProperty'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name masstranAIM.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D OCC_CONVERT_SIGNALS -D _GNU_SOURCE=1 -D NDEBUG -D No_Exception -D _OCC64 -D REVISION=7.6 -I /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/ESP/LINUX64/include -I ../utils -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-dangling-else -Wno-parentheses -Wno-unused-result -Wno-format-truncation -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/CAPS/aim/masstran -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/scanCAPS/2022-11-20-152934-90529-1 -x c++ masstranAIM.cpp
1/*
2 * CAPS: Computational Aircraft Prototype Syntheses
3 *
4 * masstran AIM
5 *
6 * Copyright 2014-2022, Massachusetts Institute of Technology
7 * Licensed under The GNU Lesser General Public License, version 2.1
8 * See http://www.opensource.org/licenses/lgpl-2.1.php
9 *
10 */
11
12
13/*! \mainpage Introduction
14 * \tableofcontents
15 *
16 * \section overviewMasstran Masstran AIM Overview
17 * A module in the Computational Aircraft Prototype Syntheses (CAPS) has been developed to compute
18 * mass properties using attributions for finite element structural solvers.
19 *
20 * An outline of the AIM's inputs, outputs and attributes are provided in \ref aimInputsMasstran and
21 * \ref aimOutputsMasstran and \ref attributeMasstran, respectively.
22 *
23 * Details on the use of units are outlined in \ref aimUnitsMasstran.
24 *
25 * The mass properties are computed via the formulas:
26 *
27 * \f{eqnarray*}{
28 * m &=& \sum_i m_i \\
29 * x_{cg} &=& \frac{1}{m}\sum_i m_i x_i \\
30 * y_{cg} &=& \frac{1}{m}\sum_i m_i y_i \\
31 * z_{cg} &=& \frac{1}{m}\sum_i m_i z_i \\
32 * \big(I_{xx}\big)_{cg} &=& \sum_i m_i \big(y_i^2 + z_i^2\big) - m \big(y_{cg}^2 + z_{cg}^2\big) \\
33 * \big(I_{yy}\big)_{cg} &=& \sum_i m_i \big(x_i^2 + z_i^2\big) - m \big(x_{cg}^2 + z_{cg}^2\big) \\
34 * \big(I_{zz}\big)_{cg} &=& \sum_i m_i \big(x_i^2 + y_i^2\big) - m \big(x_{cg}^2 + y_{cg}^2\big) \\
35 * \big(I_{xy}\big)_{cg} &=& \sum_i m_i \big(x_i y_i \big) - m \big(x_{cg} y_{cg} \big) \\
36 * \big(I_{xz}\big)_{cg} &=& \sum_i m_i \big(x_i z_i \big) - m \big(x_{cg} z_{cg} \big) \\
37 * \big(I_{yz}\big)_{cg} &=& \sum_i m_i \big(y_i z_i \big) - m \big(y_{cg} z_{cg} \big),
38 * \f}
39 *
40 * where i represents an element index in the mesh, and the mass \f$m_i\f$ is computed from the density, thickness, and area of the element.
41 *
42 * The moment of inertias are accessible individually, in vector form as
43 *
44 * \f[
45 * \vec{I} = \begin{bmatrix} I_{xx} & I_{yy} & I_{zz} & I_{xy} & I_{xz} & I_{yz} \end{bmatrix},
46 * \f]
47 *
48 * as lower/upper triangular form
49 *
50 * \f[
51 * \vec{I}_{lower} = \begin{bmatrix} I_{xx} & -I_{xy} & I_{yy} & -I_{xz} & -I_{yz} & I_{zz} \end{bmatrix},
52 * \f]
53 *
54 * \f[
55 * \vec{I}_{upper} = \begin{bmatrix} I_{xx} & -I_{xy} & -I_{xz} & I_{yy} & -I_{yz} & I_{zz} \end{bmatrix},
56 * \f]
57 *
58 * or in full tensor form as
59 *
60 * \f[
61 * \bar{\bar{I}} =
62 * \begin{bmatrix}
63 * I_{xx} & -I_{xy} & -I_{xz} \\
64 * -I_{xy} & I_{yy} & -I_{yz} \\
65 * -I_{xz} & -I_{yz} & I_{zz}
66 * \end{bmatrix}.
67 * \f]
68 *
69 *\section masstranExamples Examples
70 * An example problem using the Masstran AIM may be found at \ref masstranExample.
71 */
72
73
74/*! \page attributeMasstran Masstran AIM attributes
75 * The following list of attributes are required for the MYSTRAN AIM inside the geometry input.
76 *
77 * - <b> capsAIM</b> This attribute is a CAPS requirement to indicate the analysis the geometry
78 * representation supports.
79 *
80 * - <b> capsGroup</b> This is a name assigned to any geometric body. This body could be a solid, surface, face, wire, edge or node.
81 * Recall that a string in ESP starts with a $. For example, attribute <c>capsGroup $Wing</c>.
82 *
83 * - <b> capsIgnore</b> It is possible that there is a geometric body (or entity) that you do not want the Masstran AIM to pay attention to when creating
84 * a finite element model. The capsIgnore attribute allows a body (or entity) to be in the geometry and ignored by the AIM. For example,
85 * because of limitations in OpenCASCADE a situation where two edges are overlapping may occur; capsIgnore allows the user to only
86 * pay attention to one of the overlapping edges.
87 *
88 */
89
90#include "Surreal/SurrealS.h"
91
92#include <string.h>
93#include <math.h>
94#include "aimUtil.h"
95
96#include "meshUtils.h"
97#include "miscUtils.h"
98#include "feaUtils.h"
99
100#ifdef WIN32
101#define strcasecmp stricmp
102#define strncasecmp _strnicmp
103#define strtok_r strtok_s
104#endif
105
106//#define DEBUG
107
108#define NINT(A)(((A) < 0) ? (int)(A-0.5) : (int)(A+0.5)) (((A) < 0) ? (int)(A-0.5) : (int)(A+0.5))
109#define MIN(A,B)(((A) < (B)) ? (A) : (B)) (((A) < (B)) ? (A) : (B))
110#define MAX(A,B)(((A) < (B)) ? (B) : (A)) (((A) < (B)) ? (B) : (A))
111
112#define CROSS(a,b,c)a[0] = (b[1]*c[2]) - (b[2]*c[1]); a[1] = (b[2]*c[0]) - (b[0]*
c[2]); a[2] = (b[0]*c[1]) - (b[1]*c[0])
a[0] = (b[1]*c[2]) - (b[2]*c[1]);\
113 a[1] = (b[2]*c[0]) - (b[0]*c[2]);\
114 a[2] = (b[0]*c[1]) - (b[1]*c[0])
115#define DOT(a,b)(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) (a[0]*b[0] + a[1]*b[1] + a[2]*b[2])
116
117
118enum aimInputs
119{
120 inTess_Params = 1, /* index is 1-based */
121 inEdge_Point_Min,
122 inEdge_Point_Max,
123 inQuad_Mesh,
124 inProperty,
125 inMaterial,
126 inSurface_Mesh,
127 inDesign_Variable,
128 inDesign_Variable_Relation,
129 NUMINPUT = inDesign_Variable_Relation /* Total number of inputs */
130};
131
132enum aimOutputs
133{
134 outArea = 1, /* index is 1-based */
135 outMass,
136 outCentroid,
137 outCG,
138 outIxx,
139 outIyy,
140 outIzz,
141 outIxy,
142 outIxz,
143 outIyz,
144 outI_Vector,
145 outI_Lower,
146 outI_Upper,
147 outI_Tensor,
148 outMassProp,
149 NUMOUTPUT = outMassProp /* Total number of inputs */
150};
151
152
153template<class T>
154struct sensNode {
155 T xyz[3];
156};
157
158template<class T>
159struct sensPropertyStruct {
160 propertyTypeEnum propertyType;
161
162 int propertyID; // ID number of property
163
164 int materialID; // ID number of material
165
166 // Shell
167 T membraneThickness; // Membrane thickness
168 T massPerArea; // Mass per unit area or Non-structural mass per unit area
169
170 // Concentrated Mass
171 T mass; // Mass value
172 T massOffset[3]; // Offset distance from the grid point to the center of gravity
173 T massInertia[6]; // Mass moment of inertia measured at the mass center of gravity
174};
175
176template<class T>
177struct sensMaterialStruct {
178 materialTypeEnum materialType;
179
180 int materialID; // ID number of material
181
182 T density; // Rho - material mass density
183};
184
185template<class T>
186struct massProperties {
187 T area;
188 T mass;
189 T Ixx, Iyy, Izz;
190 T Ixy, Ixz, Iyz;
191 T Cx, Cy, Cz;
192 T CGx, CGy, CGz;
193};
194
195/* AIM "local" per instance storage
196 needed data should be added here & cleaned up in aimCleanup */
197typedef struct {
198
199 feaUnitsStruct units; // units system
200 double Lscale; // length scale
201
202 feaProblemStruct feaProblem;
203
204 // Attribute to index map
205 mapAttrToIndexStruct attrMap;
206
207 // Mesh holders
208 int numMesh;
209 meshStruct *feaMesh;
210
211 // mass properties
212 capsValue area;
213 capsValue mass;
214 capsValue Ixx, Iyy, Izz;
215 capsValue Ixy, Ixz, Iyz;
216 capsValue C;
217 capsValue CG;
218
219#define NUMVAR10 10
220 capsValue *values[NUMVAR10];
221
222} aimStorage;
223
224static int initiate_aimStorage(void *aimInfo, aimStorage *masstranInstance)
225{
226 int status = CAPS_SUCCESS0;
227 int i;
228
229 // Mesh holders
230 masstranInstance->numMesh = 0;
231 masstranInstance->feaMesh = NULL__null;
232
233 masstranInstance->Lscale = 1.0;
234 status = initiate_feaUnitsStruct(&masstranInstance->units);
235 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 235, __func__, 0); goto cleanup; }
;
236
237 // Container for attribute to index map
238 status = initiate_mapAttrToIndexStruct(&masstranInstance->attrMap);
239 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 239, __func__, 0); goto cleanup; }
;
240
241 status = initiate_feaProblemStruct(&masstranInstance->feaProblem);
242 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 242, __func__, 0); goto cleanup; }
;
243
244 masstranInstance->values[0] = &masstranInstance->area;
245 masstranInstance->values[1] = &masstranInstance->mass;
246 masstranInstance->values[2] = &masstranInstance->Ixx;
247 masstranInstance->values[3] = &masstranInstance->Iyy;
248 masstranInstance->values[4] = &masstranInstance->Izz;
249 masstranInstance->values[5] = &masstranInstance->Ixy;
250 masstranInstance->values[6] = &masstranInstance->Ixz;
251 masstranInstance->values[7] = &masstranInstance->Iyz;
252 masstranInstance->values[8] = &masstranInstance->C;
253 masstranInstance->values[9] = &masstranInstance->CG;
254#if NUMVAR10 != 10
255#error "Developer error! Update values array!"
256#endif
257 for (i = 0; i < NUMVAR10; i++) {
258 aim_initValue(masstranInstance->values[i]);
259 masstranInstance->values[i]->type = Double;
260 }
261
262 AIM_ALLOC(masstranInstance->C.vals.reals, 3, double, aimInfo, status){ if (masstranInstance->C.vals.reals != __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 262, __func__
, 1, "AIM_ALLOC: %s != NULL", "masstranInstance->C.vals.reals"
); goto cleanup; } size_t memorysize = 3; masstranInstance->
C.vals.reals = (double *) EG_alloc(memorysize*sizeof(double))
; if (masstranInstance->C.vals.reals == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 262, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "masstranInstance->C.vals.reals"
, memorysize, "double"); goto cleanup; } }
;
263 masstranInstance->C.dim = Vector;
264 masstranInstance->C.nrow = 3;
265 masstranInstance->C.length = 3;
266
267 AIM_ALLOC(masstranInstance->CG.vals.reals, 3, double, aimInfo, status){ if (masstranInstance->CG.vals.reals != __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 267, __func__
, 1, "AIM_ALLOC: %s != NULL", "masstranInstance->CG.vals.reals"
); goto cleanup; } size_t memorysize = 3; masstranInstance->
CG.vals.reals = (double *) EG_alloc(memorysize*sizeof(double)
); if (masstranInstance->CG.vals.reals == __null) { status
= -4; aim_status(aimInfo, status, "masstranAIM.cpp", 267, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "masstranInstance->CG.vals.reals"
, memorysize, "double"); goto cleanup; } }
;
268 masstranInstance->CG.dim = Vector;
269 masstranInstance->CG.nrow = 3;
270 masstranInstance->CG.length = 3;
271
272cleanup:
273 return CAPS_SUCCESS0;
274}
275
276
277static int destroy_aimStorage(aimStorage *masstranInstance)
278{
279
280 int status;
281 int i;
282
283 status = destroy_feaUnitsStruct(&masstranInstance->units);
284 if (status != CAPS_SUCCESS0)
285 printf("Error: Status %d during destroy_feaUnitsStruct!\n", status);
286
287 // Attribute to index map
288 status = destroy_mapAttrToIndexStruct(&masstranInstance->attrMap);
289 if (status != CAPS_SUCCESS0)
290 printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status);
291
292 // Cleanup meshes
293 if (masstranInstance->feaMesh != NULL__null) {
294
295 for (i = 0; i < masstranInstance->numMesh; i++) {
296 status = destroy_meshStruct(&masstranInstance->feaMesh[i]);
297 if (status != CAPS_SUCCESS0)
298 printf("Error: Status %d during destroy_meshStruct!\n", status);
299 }
300
301 AIM_FREE(masstranInstance->feaMesh){ EG_free(masstranInstance->feaMesh); masstranInstance->
feaMesh = __null; }
;
302 }
303
304 masstranInstance->feaMesh = NULL__null;
305 masstranInstance->numMesh = 0;
306
307 // Destroy FEA problem structure
308 status = destroy_feaProblemStruct(&masstranInstance->feaProblem);
309 if (status != CAPS_SUCCESS0)
310 printf("Error: Status %d during destroy_feaProblemStruct!\n", status);
311
312 aim_freeValue(&masstranInstance->area);
313 aim_freeValue(&masstranInstance->mass);
314 aim_freeValue(&masstranInstance->Ixx);
315 aim_freeValue(&masstranInstance->Iyy);
316 aim_freeValue(&masstranInstance->Izz);
317 aim_freeValue(&masstranInstance->Ixy);
318 aim_freeValue(&masstranInstance->Ixz);
319 aim_freeValue(&masstranInstance->Iyz);
320 aim_freeValue(&masstranInstance->C);
321 aim_freeValue(&masstranInstance->CG);
322
323 return CAPS_SUCCESS0;
324}
325
326
327static int checkAndCreateMesh(void *aimInfo, aimStorage *masstranInstance)
328{
329 // Function return flag
330 int status = CAPS_SUCCESS0;
331 int i, remesh = (int)false;
332
333 // Meshing related variables
334 double tessParam[3] = {0.025, 0.001, 15};
335 int edgePointMin = 2;
336 int edgePointMax = 50;
337 int quadMesh = (int) false;
338
339 // Dummy attribute to maps
340 mapAttrToIndexStruct constraintMap;
341 mapAttrToIndexStruct loadMap;
342 mapAttrToIndexStruct transferMap;
343 mapAttrToIndexStruct connectMap;
344
345 // analysis input values
346 capsValue *TessParams = NULL__null;
347 capsValue *EdgePoint_Min = NULL__null;
348 capsValue *EdgePoint_Max = NULL__null;
349 capsValue *QuadMesh = NULL__null;
350
351 for (i = 0; i < masstranInstance->numMesh; i++) {
352 remesh = remesh || (masstranInstance->feaMesh[i].egadsTess->oclass != TESSELLATION2);
353 }
354
355 // retrieve or create the mesh from fea_createMesh
356 status = aim_getValue(aimInfo, inTess_Params, ANALYSISIN, &TessParams);
357 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 357, __func__, 0); goto cleanup; }
;
358
359 remesh = remesh || (aim_newAnalysisIn(aimInfo, inTess_Params) == CAPS_SUCCESS0);
360
361 status = aim_getValue(aimInfo, inEdge_Point_Min, ANALYSISIN, &EdgePoint_Min);
362 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 362, __func__, 0); goto cleanup; }
;
363
364 remesh = remesh || (aim_newAnalysisIn(aimInfo, inEdge_Point_Min) == CAPS_SUCCESS0);
365
366 status = aim_getValue(aimInfo, inEdge_Point_Max, ANALYSISIN, &EdgePoint_Max);
367 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 367, __func__, 0); goto cleanup; }
;
368
369 remesh = remesh || (aim_newAnalysisIn(aimInfo, inEdge_Point_Max) == CAPS_SUCCESS0);
370
371 status = aim_getValue(aimInfo, inQuad_Mesh, ANALYSISIN, &QuadMesh);
372 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 372, __func__, 0); goto cleanup; }
;
373
374 remesh = remesh || (aim_newAnalysisIn(aimInfo, inQuad_Mesh) == CAPS_SUCCESS0);
375
376 remesh = remesh || (aim_newGeometry(aimInfo) == CAPS_SUCCESS0);
377 remesh = remesh || (masstranInstance->feaProblem.feaMesh.numNode == 0);
378
379 if (remesh == (int) false) return CAPS_SUCCESS0;
380
381 if (TessParams != NULL__null) {
382 tessParam[0] = TessParams->vals.reals[0];
383 tessParam[1] = TessParams->vals.reals[1];
384 tessParam[2] = TessParams->vals.reals[2];
385 }
386
387 // Max and min number of points
388 if (EdgePoint_Min != NULL__null && EdgePoint_Min->nullVal != IsNull) {
389 edgePointMin = EdgePoint_Min->vals.integer;
390 if (edgePointMin < 2) {
391 AIM_ANALYSISIN_ERROR(aimInfo, inEdge_Point_Min, "Edge_Point_Min = %d must be greater or equal to 2\n", edgePointMin){ aim_message(aimInfo, CERROR, inEdge_Point_Min, "masstranAIM.cpp"
, 391, __func__, "Edge_Point_Min = %d must be greater or equal to 2\n"
, edgePointMin); }
;
392 return CAPS_BADVALUE-311;
393 }
394 }
395
396 if (EdgePoint_Max != NULL__null && EdgePoint_Max->nullVal != IsNull) {
397 edgePointMax = EdgePoint_Max->vals.integer;
398 if (edgePointMax < 2) {
399 AIM_ANALYSISIN_ERROR(aimInfo, inEdge_Point_Max, "Edge_Point_Max = %d must be greater or equal to 2\n", edgePointMax){ aim_message(aimInfo, CERROR, inEdge_Point_Max, "masstranAIM.cpp"
, 399, __func__, "Edge_Point_Max = %d must be greater or equal to 2\n"
, edgePointMax); }
;
400 return CAPS_BADVALUE-311;
401 }
402 }
403
404 if (edgePointMin >= 2 && edgePointMax >= 2 && edgePointMin > edgePointMax) {
405 AIM_ERROR (aimInfo, "Edge_Point_Max must be greater or equal Edge_Point_Min"){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 405, __func__
, "Edge_Point_Max must be greater or equal Edge_Point_Min"); }
;
406 AIM_ADDLINE(aimInfo, "Edge_Point_Max = %d, Edge_Point_Min = %d\n",edgePointMax,edgePointMin){ aim_addLine(aimInfo, "Edge_Point_Max = %d, Edge_Point_Min = %d\n"
,edgePointMax,edgePointMin); }
;
407 return CAPS_BADVALUE-311;
408 }
409
410 if (QuadMesh != NULL__null) quadMesh = QuadMesh->vals.integer;
411
412 status = initiate_mapAttrToIndexStruct(&constraintMap);
413 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 413, __func__, 0); goto cleanup; }
;
414
415 status = initiate_mapAttrToIndexStruct(&loadMap);
416 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 416, __func__, 0); goto cleanup; }
;
417
418 status = initiate_mapAttrToIndexStruct(&transferMap);
419 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 419, __func__, 0); goto cleanup; }
;
420
421 status = initiate_mapAttrToIndexStruct(&connectMap);
422 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 422, __func__, 0); goto cleanup; }
;
423
424/*@-nullpass@*/
425 status = fea_createMesh(aimInfo,
426 tessParam,
427 edgePointMin,
428 edgePointMax,
429 quadMesh,
430 &masstranInstance->attrMap,
431 &constraintMap,
432 &loadMap,
433 &transferMap,
434 &connectMap,
435 NULL__null, NULL__null,
436 &masstranInstance->numMesh,
437 &masstranInstance->feaMesh,
438 &masstranInstance->feaProblem );
439 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 439, __func__, 0); goto cleanup; }
;
440
441 status = destroy_mapAttrToIndexStruct(&constraintMap);
442 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 442, __func__, 0); goto cleanup; }
;
443
444 status = destroy_mapAttrToIndexStruct(&loadMap);
445 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 445, __func__, 0); goto cleanup; }
;
446
447 status = destroy_mapAttrToIndexStruct(&transferMap);
448 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 448, __func__, 0); goto cleanup; }
;
449
450 status = destroy_mapAttrToIndexStruct(&connectMap);
451 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 451, __func__, 0); goto cleanup; }
;
452
453cleanup:
454 return status;
455}
456
457
458/****************** exposed AIM entry points -- Analysis **********************/
459
460/* aimInitialize: Initialization Information for the AIM */
461extern "C" int
462aimInitialize(int inst, const char *unitSys, void *aimInfo,
463 void **instStore, /*@unused@*/ int *major,
464 /*@unused@*/ int *minor, int *nIn, int *nOut,
465 int *nFields, char ***fnames, int **franks, int **fInOut)
466{
467 int status = CAPS_SUCCESS0;
468 aimStorage *masstranInstance=NULL__null;
469 const char *keyWord;
470 char *keyValue = NULL__null, *tmpUnits = NULL__null;
471 double real = 1.0;
472 feaUnitsStruct *units=NULL__null;
473
474#ifdef DEBUG
475 printf("\n masstranAIM/aimInitialize Instance!\n", inst);
476#endif
477
478 /* specify the number of analysis inputs defined in aimInputs
479 * and the number of analysis outputs defined in aimOutputs */
480 *nIn = NUMINPUT;
481 *nOut = NUMOUTPUT;
482
483 /* return if "query" only */
484 if (inst == -1) return CAPS_SUCCESS0;
485
486 /* specify the field variables this analysis can generate and consume */
487 *nFields = 0;
488 *fnames = NULL__null;
489 *franks = NULL__null;
490 *fInOut = NULL__null;
491
492 /* create our "local" storage for anything that needs to be persistent */
493 AIM_ALLOC(masstranInstance, 1, aimStorage, aimInfo, status){ if (masstranInstance != __null) { status = -4; aim_status(aimInfo
, status, "masstranAIM.cpp", 493, __func__, 1, "AIM_ALLOC: %s != NULL"
, "masstranInstance"); goto cleanup; } size_t memorysize = 1;
masstranInstance = (aimStorage *) EG_alloc(memorysize*sizeof
(aimStorage)); if (masstranInstance == __null) { status = -4;
aim_status(aimInfo, status, "masstranAIM.cpp", 493, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "masstranInstance", memorysize
, "aimStorage"); goto cleanup; } }
;
494
495 initiate_aimStorage(aimInfo, masstranInstance);
496 *instStore = masstranInstance;
497
498 /*! \page aimUnitsMasstran AIM Units
499 * A unit system may be optionally specified during AIM instance initiation. If
500 * a unit system is provided, all AIM input values which have associated units must be specified as well.
501 * If no unit system is used, AIM inputs, which otherwise would require units, will be assumed
502 * unit consistent. A unit system may be specified via a JSON string dictionary for example:
503 * unitSys = "{"mass": "kg", "length": "m"}"
504 */
505 if (unitSys != NULL__null) {
506 units = &masstranInstance->units;
507
508 // Do we have a json string?
509 if (strncmp( unitSys, "{", 1) != 0) {
510 AIM_ERROR(aimInfo, "unitSys ('%s') is expected to be a JSON string dictionary", unitSys){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 510, __func__
, "unitSys ('%s') is expected to be a JSON string dictionary"
, unitSys); }
;
511 return CAPS_BADVALUE-311;
512 }
513
514 /*! \page aimUnitsMasstran
515 * \section jsonStringMasstran JSON String Dictionary
516 * The key arguments of the dictionary are described in the following:
517 *
518 * <ul>
519 * <li> <B>mass = "None"</B> </li> <br>
520 * Mass units - e.g. "kilogram", "k", "slug", ...
521 * </ul>
522 */
523 keyWord = "mass";
524 status = search_jsonDictionary(unitSys, keyWord, &keyValue);
525 if (status == CAPS_SUCCESS0) {
526 units->mass = string_removeQuotation(keyValue);
527 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = __null; };
528 real = 1;
529 status = aim_convert(aimInfo, 1, units->mass, &real, "kg", &real);
530 AIM_STATUS(aimInfo, status, "unitSys ('%s'): %s is not a %s unit", unitSys, units->mass, keyWord)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 530, __func__, 4, "unitSys ('%s'): %s is not a %s unit", unitSys
, units->mass, keyWord); goto cleanup; }
;
531 } else {
532 AIM_ERROR(aimInfo, "unitSys ('%s') does not contain '%s'", unitSys, keyWord){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 532, __func__
, "unitSys ('%s') does not contain '%s'", unitSys, keyWord); }
;
533 status = CAPS_BADVALUE-311;
534 goto cleanup;
535 }
536
537 /*! \page aimUnitsMasstran
538 * <ul>
539 * <li> <B>length = "None"</B> </li> <br>
540 * Length units - e.g. "meter", "m", "inch", "in", "mile", ...
541 * </ul>
542 */
543 keyWord = "length";
544 status = search_jsonDictionary(unitSys, keyWord, &keyValue);
545 if (status == CAPS_SUCCESS0) {
546 units->length = string_removeQuotation(keyValue);
547 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = __null; };
548 real = 1;
549 status = aim_convert(aimInfo, 1, units->length, &real, "m", &real);
550 AIM_STATUS(aimInfo, status, "unitSys ('%s'): %s is not a %s unit", unitSys, units->length, keyWord)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 550, __func__, 4, "unitSys ('%s'): %s is not a %s unit", unitSys
, units->length, keyWord); goto cleanup; }
;
551 } else {
552 AIM_ERROR(aimInfo, "unitSys ('%s') does not contain '%s'", unitSys, keyWord){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 552, __func__
, "unitSys ('%s') does not contain '%s'", unitSys, keyWord); }
;
553 status = CAPS_BADVALUE-311;
554 goto cleanup;
555 }
556
557 // construct density volume unit
558 status = aim_unitRaise(aimInfo, units->length, -3, &tmpUnits); // 1/length^3
559 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 559, __func__, 0); goto cleanup; }
;
560 status = aim_unitMultiply(aimInfo, units->mass, tmpUnits, &units->densityVol); // mass/length^3, e.g volume density
561 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 561, __func__, 0); goto cleanup; }
;
562 AIM_FREE(tmpUnits){ EG_free(tmpUnits); tmpUnits = __null; };
563
564 // construct density area unit
565 status = aim_unitRaise(aimInfo, units->length, -2, &tmpUnits); // 1/length^2
566 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 566, __func__, 0); goto cleanup; }
;
567 status = aim_unitMultiply(aimInfo, units->mass, tmpUnits, &units->densityArea); // mass/length^2, e.g area density
568 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 568, __func__, 0); goto cleanup; }
;
569 AIM_FREE(tmpUnits){ EG_free(tmpUnits); tmpUnits = __null; };
570
571 status = aim_unitRaise(aimInfo, units->length, 2, &tmpUnits ); // length^2
572 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 572, __func__, 0); goto cleanup; }
;
573 status = aim_unitMultiply(aimInfo, units->mass, tmpUnits, &units->momentOfInertia ); // mass*length^2, e.g moment of inertia
574 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 574, __func__, 0); goto cleanup; }
;
575 AIM_FREE(tmpUnits){ EG_free(tmpUnits); tmpUnits = __null; };
576
577
578 // set units
579 status = aim_unitRaise(aimInfo, units->length, 2, &masstranInstance->area.units); // length^2
580 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 580, __func__, 0); goto cleanup; }
;
581 AIM_STRDUP(masstranInstance->mass.units, units->mass , aimInfo, status){ if (masstranInstance->mass.units != __null) { status = -
4; aim_status(aimInfo, status, "masstranAIM.cpp", 581, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->mass.units"
); goto cleanup; } masstranInstance->mass.units = EG_strdup
(units->mass); if (masstranInstance->mass.units == __null
) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 581, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->mass.units"
, units->mass); goto cleanup; } }
; // mass
582 AIM_STRDUP(masstranInstance->C.units , units->length , aimInfo, status){ if (masstranInstance->C.units != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 582, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "masstranInstance->C.units"); goto cleanup; } masstranInstance
->C.units = EG_strdup(units->length); if (masstranInstance
->C.units == __null) { status = -4; aim_status(aimInfo, status
, "masstranAIM.cpp", 582, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->C.units"
, units->length); goto cleanup; } }
; // lenth
583 AIM_STRDUP(masstranInstance->CG.units , units->length , aimInfo, status){ if (masstranInstance->CG.units != __null) { status = -4;
aim_status(aimInfo, status, "masstranAIM.cpp", 583, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->CG.units"
); goto cleanup; } masstranInstance->CG.units = EG_strdup(
units->length); if (masstranInstance->CG.units == __null
) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 583, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->CG.units"
, units->length); goto cleanup; } }
; // length
584 AIM_STRDUP(masstranInstance->Ixx.units , units->momentOfInertia, aimInfo, status){ if (masstranInstance->Ixx.units != __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 584, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->Ixx.units"
); goto cleanup; } masstranInstance->Ixx.units = EG_strdup
(units->momentOfInertia); if (masstranInstance->Ixx.units
== __null) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 584, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->Ixx.units"
, units->momentOfInertia); goto cleanup; } }
; // moment of inertia
585 AIM_STRDUP(masstranInstance->Iyy.units , units->momentOfInertia, aimInfo, status){ if (masstranInstance->Iyy.units != __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 585, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->Iyy.units"
); goto cleanup; } masstranInstance->Iyy.units = EG_strdup
(units->momentOfInertia); if (masstranInstance->Iyy.units
== __null) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 585, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->Iyy.units"
, units->momentOfInertia); goto cleanup; } }
; // moment of inertia
586 AIM_STRDUP(masstranInstance->Izz.units , units->momentOfInertia, aimInfo, status){ if (masstranInstance->Izz.units != __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 586, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->Izz.units"
); goto cleanup; } masstranInstance->Izz.units = EG_strdup
(units->momentOfInertia); if (masstranInstance->Izz.units
== __null) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 586, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->Izz.units"
, units->momentOfInertia); goto cleanup; } }
; // moment of inertia
587 AIM_STRDUP(masstranInstance->Ixy.units , units->momentOfInertia, aimInfo, status){ if (masstranInstance->Ixy.units != __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 587, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->Ixy.units"
); goto cleanup; } masstranInstance->Ixy.units = EG_strdup
(units->momentOfInertia); if (masstranInstance->Ixy.units
== __null) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 587, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->Ixy.units"
, units->momentOfInertia); goto cleanup; } }
; // moment of inertia
588 AIM_STRDUP(masstranInstance->Ixz.units , units->momentOfInertia, aimInfo, status){ if (masstranInstance->Ixz.units != __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 588, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->Ixz.units"
); goto cleanup; } masstranInstance->Ixz.units = EG_strdup
(units->momentOfInertia); if (masstranInstance->Ixz.units
== __null) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 588, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->Ixz.units"
, units->momentOfInertia); goto cleanup; } }
; // moment of inertia
589 AIM_STRDUP(masstranInstance->Iyz.units , units->momentOfInertia, aimInfo, status){ if (masstranInstance->Iyz.units != __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 589, __func__
, 1, "AIM_STRDUP: %s != NULL!", "masstranInstance->Iyz.units"
); goto cleanup; } masstranInstance->Iyz.units = EG_strdup
(units->momentOfInertia); if (masstranInstance->Iyz.units
== __null) { status = -4; aim_status(aimInfo, status, "masstranAIM.cpp"
, 589, __func__, 2, "AIM_STRDUP: %s %s", "masstranInstance->Iyz.units"
, units->momentOfInertia); goto cleanup; } }
; // moment of inertia
590 }
591
592cleanup:
593 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = __null; };
594 AIM_FREE(tmpUnits){ EG_free(tmpUnits); tmpUnits = __null; };
595
596 return status;
597}
598
599
600// ********************** AIM Function Break *****************************
601/* aimInputs: Input Information for the AIM */
602extern "C" int
603aimInputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo,
604 int index, char **ainame, capsValue *defval)
605{
606
607 /*! \page aimInputsMasstran AIM Inputs
608 * The following list outlines the Masstran inputs along with their default value available
609 * through the AIM interface.
610 */
611 int status = CAPS_SUCCESS0;
612
613#ifdef DEBUG
614 printf(" nastranAIM/aimInputs index = %d!\n", index);
615#endif
616
617 *ainame = NULL__null;
618
619 // Masstran Inputs
620 if (index == inTess_Params) {
621 *ainame = EG_strdup("Tess_Params");
622 defval->type = Double;
623 defval->dim = Vector;
624 defval->nrow = 3;
625 defval->ncol = 1;
626 defval->units = NULL__null;
627 defval->lfixed = Fixed;
628 defval->vals.reals = (double *) EG_alloc(defval->nrow*sizeof(double));
629 if (defval->vals.reals != NULL__null) {
630 defval->vals.reals[0] = 0.025;
631 defval->vals.reals[1] = 0.001;
632 defval->vals.reals[2] = 15.00;
633 } else return EGADS_MALLOC-4;
634
635 /*! \page aimInputsMasstran
636 * - <B> Tess_Params = [0.025, 0.001, 15.0]</B> <br>
637 * Body tessellation parameters used when creating a boundary element model.
638 * Tess_Params[0] and Tess_Params[1] get scaled by the bounding
639 * box of the body. (From the EGADS manual) A set of 3 parameters that drive the EDGE discretization
640 * and the FACE triangulation. The first is the maximum length of an EDGE segment or triangle side
641 * (in physical space). A zero is flag that allows for any length. The second is a curvature-based
642 * value that looks locally at the deviation between the centroid of the discrete object and the
643 * underlying geometry. Any deviation larger than the input value will cause the tessellation to
644 * be enhanced in those regions. The third is the maximum interior dihedral angle (in degrees)
645 * between triangle facets (or Edge segment tangents for a WIREBODY tessellation), note that a
646 * zero ignores this phase
647 */
648
649 } else if (index == inEdge_Point_Min) {
650 *ainame = EG_strdup("Edge_Point_Min");
651 defval->type = Integer;
652 defval->vals.integer = 2;
653 defval->lfixed = Fixed;
654 defval->nrow = 1;
655 defval->ncol = 1;
656 defval->nullVal = NotNull;
657
658 /*! \page aimInputsMasstran
659 * - <B> Edge_Point_Min = 2</B> <br>
660 * Minimum number of points on an edge including end points to use when creating a surface mesh (min 2).
661 */
662
663 } else if (index == inEdge_Point_Max) {
664 *ainame = EG_strdup("Edge_Point_Max");
665 defval->type = Integer;
666 defval->vals.integer = 50;
667 defval->lfixed = Fixed;
668 defval->nrow = 1;
669 defval->ncol = 1;
670 defval->nullVal = NotNull;
671
672 /*! \page aimInputsMasstran
673 * - <B> Edge_Point_Max = 50</B> <br>
674 * Maximum number of points on an edge including end points to use when creating a surface mesh (min 2).
675 */
676
677 } else if (index == inQuad_Mesh) {
678 *ainame = EG_strdup("Quad_Mesh");
679 defval->type = Boolean;
680 defval->vals.integer = (int) false;
681
682 /*! \page aimInputsMasstran
683 * - <B> Quad_Mesh = False</B> <br>
684 * Create a quadratic mesh on four edge faces when creating the boundary element model.
685 */
686
687 } else if (index == inProperty) {
688 *ainame = EG_strdup("Property");
689 defval->type = Tuple;
690 defval->nullVal = IsNull;
691 defval->lfixed = Change;
692 defval->vals.tuple = NULL__null;
693 defval->dim = Vector;
694
695 /*! \page aimInputsMasstran
696 * - <B> Property = NULL</B> <br>
697 * Property tuple used to input property information for the model, see \ref feaProperty for additional details.
698 */
699 } else if (index == inMaterial) {
700 *ainame = EG_strdup("Material");
701 defval->type = Tuple;
702 defval->nullVal = IsNull;
703 defval->lfixed = Change;
704 defval->vals.tuple = NULL__null;
705 defval->dim = Vector;
706
707 /*! \page aimInputsMasstran
708 * - <B> Material = NULL</B> <br>
709 * Material tuple used to input material information for the model, see \ref feaMaterial for additional details.
710 */
711
712 } else if (index == inSurface_Mesh) {
713 *ainame = EG_strdup("Surface_Mesh");
714 defval->type = Pointer;
715 defval->dim = Vector;
716 defval->lfixed = Change;
717 defval->sfixed = Change;
718 defval->vals.AIMptr = NULL__null;
719 defval->nullVal = IsNull;
720 AIM_STRDUP(defval->units, "meshStruct", aimInfo, status){ if (defval->units != __null) { status = -4; aim_status(aimInfo
, status, "masstranAIM.cpp", 720, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "defval->units"); goto cleanup; } defval->units = EG_strdup
("meshStruct"); if (defval->units == __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 720, __func__
, 2, "AIM_STRDUP: %s %s", "defval->units", "meshStruct"); goto
cleanup; } }
;
721
722 /*! \page aimInputsMasstran
723 * - <B>Surface_Mesh = NULL</B> <br>
724 * A Surface_Mesh link.
725 */
726
727 } else if (index == inDesign_Variable) {
728 *ainame = EG_strdup("Design_Variable");
729 defval->type = Tuple;
730 defval->nullVal = IsNull;
731 defval->lfixed = Change;
732 defval->vals.tuple = NULL__null;
733 defval->dim = Vector;
734
735 /*! \page aimInputsMasstran
736 * - <B> Design_Variable = NULL</B> <br>
737 * The design variable tuple is used to input design variable information for the model optimization, see \ref feaDesignVariable for additional details.
738 */
739
740 } else if (index == inDesign_Variable_Relation) {
741 *ainame = EG_strdup("Design_Variable_Relation");
742 defval->type = Tuple;
743 defval->nullVal = IsNull;
744 //defval->units = NULL;
745 defval->lfixed = Change;
746 defval->vals.tuple = NULL__null;
747 defval->dim = Vector;
748
749 /*! \page aimInputsMasstran
750 * - <B> Design_Variable_Relation = NULL</B> <br>
751 * The design variable relation tuple is used to input design variable relation information for the model optimization, see \ref feaDesignVariableRelation for additional details.
752 */
753
754 }
755
756 AIM_NOTNULL(*ainame, aimInfo, status){ if (*ainame == __null) { status = -307; aim_status(aimInfo,
status, "masstranAIM.cpp", 756, __func__, 1, "%s == NULL!", "*ainame"
); goto cleanup; } }
;
757
758cleanup:
759 if (status != CAPS_SUCCESS0) AIM_FREE(*ainame){ EG_free(*ainame); *ainame = __null; };
760 return status;
761}
762
763
764// ********************** AIM Function Break *****************************
765extern "C" int
766aimUpdateState(void *instStore, void *aimInfo,
767 capsValue *aimInputs)
768{
769 int status; // Function return status
770 int i, j, idv, len, index, len_wrt;
771
772 const feaUnitsStruct *units=NULL__null;
773
774 int numBody = 0;
775 ego *bodies=NULL__null;
776 const char *intents=NULL__null;
777
778 const char *bodyLunits=NULL__null, *name=NULL__null;
779 capsValue *geomInVal, **values;
780
781 aimStorage *masstranInstance;
782
783 masstranInstance = (aimStorage *) instStore;
784 AIM_NOTNULL(aimInputs, aimInfo, status){ if (aimInputs == __null) { status = -307; aim_status(aimInfo
, status, "masstranAIM.cpp", 784, __func__, 1, "%s == NULL!",
"aimInputs"); goto cleanup; } }
;
785
786 // Get FEA mesh if we don't already have one
787 status = checkAndCreateMesh(aimInfo, masstranInstance);
788 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 788, __func__, 0); goto cleanup; }
;
789
790 // Note: Setting order is important here.
791 // 1. Materials should be set before properties.
792 // 2. Coordinate system should be set before mesh and loads
793 // 3. Mesh should be set before loads, constraints, supports, and connections
794
795 // Set material properties
796 if (aimInputs[inMaterial-1].nullVal == NotNull) {
797 if (aim_newAnalysisIn(aimInfo, inMaterial) == CAPS_SUCCESS0 ||
798 masstranInstance->feaProblem.numMaterial == 0) {
799 status = fea_getMaterial(aimInfo,
800 aimInputs[inMaterial-1].length,
801 aimInputs[inMaterial-1].vals.tuple,
802 &masstranInstance->units,
803 &masstranInstance->feaProblem.numMaterial,
804 &masstranInstance->feaProblem.feaMaterial);
805 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 805, __func__, 0); goto cleanup; }
;
806 }
807 } else {
808 printf("Material tuple is NULL - No materials set\n");
809
810 if (masstranInstance->feaProblem.feaMaterial != NULL__null) {
811 for (i = 0; i < masstranInstance->feaProblem.numMaterial; i++) {
812 status = destroy_feaMaterialStruct(&masstranInstance->feaProblem.feaMaterial[i]);
813 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaMaterialStruct\n", status);
814 }
815 }
816 AIM_FREE(masstranInstance->feaProblem.feaMaterial){ EG_free(masstranInstance->feaProblem.feaMaterial); masstranInstance
->feaProblem.feaMaterial = __null; }
;
817 masstranInstance->feaProblem.numMaterial = 0;
818 }
819
820 // Set property properties
821 if (aimInputs[inProperty-1].nullVal == NotNull) {
822
823 if (aim_newAnalysisIn(aimInfo, inProperty) == CAPS_SUCCESS0 ||
824 masstranInstance->feaProblem.numProperty == 0) {
825 status = fea_getProperty(aimInfo,
826 aimInputs[inProperty-1].length,
827 aimInputs[inProperty-1].vals.tuple,
828 &masstranInstance->attrMap,
829 &masstranInstance->units,
830 &masstranInstance->feaProblem);
831 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 831, __func__, 0); goto cleanup; }
;
832 }
833
834 // Assign element "subtypes" based on properties set
835 status = fea_assignElementSubType(masstranInstance->feaProblem.numProperty,
836 masstranInstance->feaProblem.feaProperty,
837 &masstranInstance->feaProblem.feaMesh);
838 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 838, __func__, 0); goto cleanup; }
;
839
840 } else {
841 printf("Property tuple is NULL - No properties set\n");
842 for (i = 0; i < masstranInstance->feaProblem.numProperty; i++) {
843 status = destroy_feaPropertyStruct(&masstranInstance->feaProblem.feaProperty[i]);
844 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 844, __func__, 0); goto cleanup; }
;
845 }
846 AIM_FREE(masstranInstance->feaProblem.feaProperty){ EG_free(masstranInstance->feaProblem.feaProperty); masstranInstance
->feaProblem.feaProperty = __null; }
;
847 masstranInstance->feaProblem.numProperty = 0;
848 }
849
850 // Set design variables
851 if (aimInputs[inDesign_Variable-1].nullVal == NotNull &&
852 (aim_newAnalysisIn(aimInfo, inDesign_Variable) == CAPS_SUCCESS0 ||
853 aim_newAnalysisIn(aimInfo, inDesign_Variable_Relation) == CAPS_SUCCESS0 ||
854 masstranInstance->feaProblem.numDesignVariable == 0 ||
855 masstranInstance->feaProblem.numDesignVariableRelation == 0)) {
856 status = fea_getDesignVariable(aimInfo,
857 (int)false,
858 aimInputs[inDesign_Variable-1].length,
859 aimInputs[inDesign_Variable-1].vals.tuple,
860 aimInputs[inDesign_Variable_Relation-1].length,
861 aimInputs[inDesign_Variable_Relation-1].vals.tuple,
862 &masstranInstance->attrMap,
863 &masstranInstance->feaProblem);
864 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 864, __func__, 0); goto cleanup; }
;
865
866 /* allocate derivatives */
867 values = masstranInstance->values;
868 for (i = 0; i < NUMVAR10; i++) {
869 values[i]->type = DoubleDeriv;
870
871 if (values[i]->derivs != NULL__null) {
872 for (idv = 0; idv < values[i]->nderiv; idv++) {
873 AIM_FREE(values[i]->derivs[idv].name){ EG_free(values[i]->derivs[idv].name); values[i]->derivs
[idv].name = __null; }
;
874 AIM_FREE(values[i]->derivs[idv].deriv){ EG_free(values[i]->derivs[idv].deriv); values[i]->derivs
[idv].deriv = __null; }
;
875 }
876 AIM_FREE(values[i]->derivs){ EG_free(values[i]->derivs); values[i]->derivs = __null
; }
;
877 values[i]->nderiv = 0;
878 }
879
880 AIM_ALLOC(values[i]->derivs, masstranInstance->feaProblem.numDesignVariable, capsDeriv, aimInfo, status){ if (values[i]->derivs != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 880, __func__, 1, "AIM_ALLOC: %s != NULL"
, "values[i]->derivs"); goto cleanup; } size_t memorysize =
masstranInstance->feaProblem.numDesignVariable; values[i]
->derivs = (capsDeriv *) EG_alloc(memorysize*sizeof(capsDeriv
)); if (values[i]->derivs == __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 880, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "values[i]->derivs", memorysize, "capsDeriv"); goto cleanup
; } }
;
881 for (idv = 0; idv < masstranInstance->feaProblem.numDesignVariable; idv++) {
882 values[i]->derivs[idv].name = NULL__null;
883 values[i]->derivs[idv].deriv = NULL__null;
884 values[i]->derivs[idv].len_wrt = 0;
885 }
886 values[i]->nderiv = masstranInstance->feaProblem.numDesignVariable;
887 }
888
889 for (idv = 0; idv < masstranInstance->feaProblem.numDesignVariable; idv++) {
890
891 name = masstranInstance->feaProblem.feaDesignVariable[idv].name;
892
893 // Loop over the geometry in values and compute sensitivities for all bodies
894 index = aim_getIndex(aimInfo, name, GEOMETRYIN);
895 status = aim_getValue(aimInfo, index, GEOMETRYIN, &geomInVal);
896 if (status == CAPS_BADINDEX-304) {
897 len_wrt = 1;
898 } else {
899 len_wrt = geomInVal->length;
900 }
901
902 // setup derivative memory
903 for (i = 0; i < NUMVAR10; i++) {
904 AIM_FREE(values[i]->derivs[idv].name){ EG_free(values[i]->derivs[idv].name); values[i]->derivs
[idv].name = __null; }
;
905 AIM_STRDUP(values[i]->derivs[idv].name, name, aimInfo, status){ if (values[i]->derivs[idv].name != __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 905, __func__
, 1, "AIM_STRDUP: %s != NULL!", "values[i]->derivs[idv].name"
); goto cleanup; } values[i]->derivs[idv].name = EG_strdup
(name); if (values[i]->derivs[idv].name == __null) { status
= -4; aim_status(aimInfo, status, "masstranAIM.cpp", 905, __func__
, 2, "AIM_STRDUP: %s %s", "values[i]->derivs[idv].name", name
); goto cleanup; } }
;
906
907 values[i]->derivs[idv].len_wrt = len_wrt;
908
909 len = values[i]->length*values[i]->derivs[idv].len_wrt;
910 AIM_ALLOC(values[i]->derivs[idv].deriv, len, double, aimInfo, status){ if (values[i]->derivs[idv].deriv != __null) { status = -
4; aim_status(aimInfo, status, "masstranAIM.cpp", 910, __func__
, 1, "AIM_ALLOC: %s != NULL", "values[i]->derivs[idv].deriv"
); goto cleanup; } size_t memorysize = len; values[i]->derivs
[idv].deriv = (double *) EG_alloc(memorysize*sizeof(double));
if (values[i]->derivs[idv].deriv == __null) { status = -4
; aim_status(aimInfo, status, "masstranAIM.cpp", 910, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "values[i]->derivs[idv].deriv"
, memorysize, "double"); goto cleanup; } }
;
911 for (j = 0; j < len; j++)
912 values[i]->derivs[idv].deriv[j] = 0;
913 }
914 }
915
916 } else if (aimInputs[inDesign_Variable-1].nullVal == IsNull){
917 for (i = 0; i < masstranInstance->feaProblem.numDesignVariable; i++) {
918 status = destroy_feaDesignVariableStruct(&masstranInstance->feaProblem.feaDesignVariable[i]);
919 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 919, __func__, 0); goto cleanup; }
;
920 }
921 AIM_FREE(masstranInstance->feaProblem.feaDesignVariable){ EG_free(masstranInstance->feaProblem.feaDesignVariable);
masstranInstance->feaProblem.feaDesignVariable = __null; }
;
922 masstranInstance->feaProblem.numDesignVariable = 0;
923 for (i = 0; i < masstranInstance->feaProblem.numDesignVariableRelation; i++) {
924 status = destroy_feaDesignVariableRelationStruct(&masstranInstance->feaProblem.feaDesignVariableRelation[i]);
925 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 925, __func__, 0); goto cleanup; }
;
926 }
927 AIM_FREE(masstranInstance->feaProblem.feaDesignVariableRelation){ EG_free(masstranInstance->feaProblem.feaDesignVariableRelation
); masstranInstance->feaProblem.feaDesignVariableRelation =
__null; }
;
928 masstranInstance->feaProblem.numDesignVariableRelation = 0;
929
930 /* remove derivatives */
931 values = masstranInstance->values;
932 for (i = 0; i < NUMVAR10; i++) {
933 values[i]->type = Double;
934
935 for (idv = 0; idv < values[i]->nderiv; idv++) {
936 AIM_FREE(values[i]->derivs[idv].name){ EG_free(values[i]->derivs[idv].name); values[i]->derivs
[idv].name = __null; }
;
937 AIM_FREE(values[i]->derivs[idv].deriv){ EG_free(values[i]->derivs[idv].deriv); values[i]->derivs
[idv].deriv = __null; }
;
938 }
939 AIM_FREE(values[i]->derivs){ EG_free(values[i]->derivs); values[i]->derivs = __null
; }
;
940 values[i]->nderiv = 0;
941 }
942 }
943
944 if (masstranInstance->units.length != NULL__null) {
945 units = &masstranInstance->units;
946
947 status = aim_getBodies(aimInfo, &intents, &numBody, &bodies);
948 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 948, __func__, 0); goto cleanup; }
;
949
950 if (numBody == 0 || bodies == NULL__null) {
951 AIM_ERROR(aimInfo, "No Bodies!"){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 951, __func__
, "No Bodies!"); }
;
952 status = CAPS_SOURCEERR-330;
953 goto cleanup;
954 }
955
956 // Get length units
957 status = check_CAPSLength(numBody, bodies, &bodyLunits);
958 if (status != CAPS_SUCCESS0) {
959 AIM_ERROR(aimInfo, "capsLength is not set in *.csm file!"){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 959, __func__
, "capsLength is not set in *.csm file!"); }
;
960 status = CAPS_BADVALUE-311;
961 goto cleanup;
962 }
963
964 // conversion of the csm model units into units of Lunits
965 masstranInstance->Lscale = 1.0;
966 status = aim_convert(aimInfo, 1, bodyLunits, &masstranInstance->Lscale, units->length, &masstranInstance->Lscale);
967 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 967, __func__, 0); goto cleanup; }
;
968 } else {
969 status = destroy_feaUnitsStruct(&masstranInstance->units);
970 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 970, __func__, 0); goto cleanup; }
;
971 }
972
973
974 status = CAPS_SUCCESS0;
975cleanup:
976
977 return status;
978}
979
980
981// ********************** AIM Function Break *****************************
982template<class T, class NodeType>
983int
984calcMassProps(void *aimInfo,
985 const int numProperty,
986 const sensPropertyStruct<T> *feaProperties,
987 const int numMaterial,
988 const sensMaterialStruct<T> *feaMaterials,
989 const int *n2a,
990 const meshStruct *nasMesh,
991 const double Lscale,
992 const NodeType *node,
993 massProperties<T>& prop)
994{
995 int i, j; // Indexing
996 int status = CAPS_SUCCESS0; // Status return
997
998 T area;
999 T mass;
1000 T Ixx, Ixy, Izz;
1001 T Ixz, Iyy, Iyz;
1002 T CGx, CGy, CGz;
1003
1004 T cgxmom = 0;
1005 T cgymom = 0;
1006 T cgzmom = 0;
1007 T cxmom = 0;
1008 T cymom = 0;
1009 T czmom = 0;
1010 T xelem[4], yelem[4], zelem[4], elemArea;
1011 T xcent, ycent, zcent;
1012 T dx1[3], dx2[3], n[3];
1013 T thick, density;
1014 T elemWeight;
1015
1016 int elem[4];
1017
1018 feaMeshDataStruct *feaData = NULL__null;
1019 int propertyID, materialID;
1020 const sensPropertyStruct<T> *feaProperty;
1021 const sensMaterialStruct<T> *feaMaterial;
1022
1023
1024 area = 0;
1025 mass = 0;
1026 Ixx = Ixy = Izz = 0;
1027 Ixz = Iyy = Iyz = 0;
1028 CGx = CGy = CGz = 0;
1029
1030 for (i = 0; i < nasMesh->numElement; i++) {
1031
1032 // Get the property and material
1033 if (nasMesh->element[i].analysisType == MeshStructure) {
1034 feaData = (feaMeshDataStruct *) nasMesh->element[i].analysisData;
1035 propertyID = feaData->propertyID;
1036 } else {
1037 feaData = NULL__null;
1038 propertyID = nasMesh->element[i].markerID;
1039 }
1040 elemWeight = 0;
1041
1042 feaProperty = NULL__null;
1043 for (j = 0; j < numProperty; j++) {
1044 if (propertyID == feaProperties[j].propertyID) {
1045 feaProperty = &feaProperties[j];
1046 break;
1047 }
1048 }
1049
1050 if (feaProperty == NULL__null) {
1051 AIM_ERROR(aimInfo, "No property information found for element %d!\n",{ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1052, __func__
, "No property information found for element %d!\n", nasMesh->
element[i].elementID); }
1052 nasMesh->element[i].elementID){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1052, __func__
, "No property information found for element %d!\n", nasMesh->
element[i].elementID); }
;
1053 status = CAPS_BADVALUE-311;
1054 goto cleanup;
1055 }
1056
1057 if (nasMesh->element[i].elementType == Node ) {
1058
1059 if (feaData != NULL__null && feaData->elementSubType == ConcentratedMassElement) {
1060
1061 elem[0] = n2a[nasMesh->element[i].connectivity[0]];
1062
1063 xcent = (node[elem[0]].xyz[0] + feaProperty->massOffset[0]) * Lscale;
1064 ycent = (node[elem[0]].xyz[1] + feaProperty->massOffset[1]) * Lscale;
1065 zcent = (node[elem[0]].xyz[2] + feaProperty->massOffset[2]) * Lscale;
1066
1067 elemArea = 0;
1068
1069 elemWeight = feaProperty->mass;
1070
1071 // add the inertia at the point
1072 Ixx += feaProperty->massInertia[I11];
1073 Iyy += feaProperty->massInertia[I22];
1074 Izz += feaProperty->massInertia[I33];
1075 Ixy -= feaProperty->massInertia[I21];
1076 Ixz -= feaProperty->massInertia[I31];
1077 Iyz -= feaProperty->massInertia[I32];
1078 } else {
1079 continue; // nothing to do if the node is not a concentrated mass
1080 }
1081
1082 } else if ( nasMesh->element[i].elementType == Triangle) {
1083
1084 elem[0] = n2a[nasMesh->element[i].connectivity[0]];
1085 elem[1] = n2a[nasMesh->element[i].connectivity[1]];
1086 elem[2] = n2a[nasMesh->element[i].connectivity[2]];
1087
1088 xelem[0] = node[elem[0]].xyz[0] * Lscale;
1089 yelem[0] = node[elem[0]].xyz[1] * Lscale;
1090 zelem[0] = node[elem[0]].xyz[2] * Lscale;
1091 xelem[1] = node[elem[1]].xyz[0] * Lscale;
1092 yelem[1] = node[elem[1]].xyz[1] * Lscale;
1093 zelem[1] = node[elem[1]].xyz[2] * Lscale;
1094 xelem[2] = node[elem[2]].xyz[0] * Lscale;
1095 yelem[2] = node[elem[2]].xyz[1] * Lscale;
1096 zelem[2] = node[elem[2]].xyz[2] * Lscale;
1097
1098 xcent = (xelem[0] + xelem[1] + xelem[2]) / 3;
1099 ycent = (yelem[0] + yelem[1] + yelem[2]) / 3;
1100 zcent = (zelem[0] + zelem[1] + zelem[2]) / 3;
1101
1102 dx1[0] = xelem[1] - xelem[0];
1103 dx1[1] = yelem[1] - yelem[0];
1104 dx1[2] = zelem[1] - zelem[0];
1105 dx2[0] = xelem[2] - xelem[0];
1106 dx2[1] = yelem[2] - yelem[0];
1107 dx2[2] = zelem[2] - zelem[0];
1108
1109 CROSS(n, dx1, dx2)n[0] = (dx1[1]*dx2[2]) - (dx1[2]*dx2[1]); n[1] = (dx1[2]*dx2[
0]) - (dx1[0]*dx2[2]); n[2] = (dx1[0]*dx2[1]) - (dx1[1]*dx2[0
])
;
1110
1111 elemArea = sqrt(DOT(n, n)(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]))/2.0; /* 1/2 for area */
1112
1113 } else if ( nasMesh->element[i].elementType == Quadrilateral) {
1114
1115 elem[0] = n2a[nasMesh->element[i].connectivity[0]];
1116 elem[1] = n2a[nasMesh->element[i].connectivity[1]];
1117 elem[2] = n2a[nasMesh->element[i].connectivity[2]];
1118 elem[3] = n2a[nasMesh->element[i].connectivity[3]];
1119
1120 xelem[0] = node[elem[0]].xyz[0] * Lscale;
1121 yelem[0] = node[elem[0]].xyz[1] * Lscale;
1122 zelem[0] = node[elem[0]].xyz[2] * Lscale;
1123 xelem[1] = node[elem[1]].xyz[0] * Lscale;
1124 yelem[1] = node[elem[1]].xyz[1] * Lscale;
1125 zelem[1] = node[elem[1]].xyz[2] * Lscale;
1126 xelem[2] = node[elem[2]].xyz[0] * Lscale;
1127 yelem[2] = node[elem[2]].xyz[1] * Lscale;
1128 zelem[2] = node[elem[2]].xyz[2] * Lscale;
1129 xelem[3] = node[elem[3]].xyz[0] * Lscale;
1130 yelem[3] = node[elem[3]].xyz[1] * Lscale;
1131 zelem[3] = node[elem[3]].xyz[2] * Lscale;
1132
1133 xcent = (xelem[0] + xelem[1] + xelem[2] + xelem[3]) / 4;
1134 ycent = (yelem[0] + yelem[1] + yelem[2] + yelem[3]) / 4;
1135 zcent = (zelem[0] + zelem[1] + zelem[2] + zelem[3]) / 4;
1136
1137 dx1[0] = xelem[2] - xelem[0];
1138 dx1[1] = yelem[2] - yelem[0];
1139 dx1[2] = zelem[2] - zelem[0];
1140 dx2[0] = xelem[3] - xelem[1];
1141 dx2[1] = yelem[3] - yelem[1];
1142 dx2[2] = zelem[3] - zelem[1];
1143
1144 CROSS(n, dx1, dx2)n[0] = (dx1[1]*dx2[2]) - (dx1[2]*dx2[1]); n[1] = (dx1[2]*dx2[
0]) - (dx1[0]*dx2[2]); n[2] = (dx1[0]*dx2[1]) - (dx1[1]*dx2[0
])
;
1145
1146 elemArea = sqrt(DOT(n, n)(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]))/2.0; /* 1/2 for area */
1147
1148 } else {
1149 AIM_ERROR(aimInfo, "Unknown element type %d", nasMesh->element[i].elementType){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1149, __func__
, "Unknown element type %d", nasMesh->element[i].elementType
); }
;
1150 status = CAPS_BADVALUE-311;
1151 goto cleanup;
1152 }
1153
1154 if (feaData == NULL__null || feaData->elementSubType != ConcentratedMassElement) {
1155
1156 materialID = feaProperty->materialID;
1157
1158 feaMaterial = NULL__null;
1159 for (j = 0; j < numMaterial; j++) {
1160 if (materialID == feaMaterials[j].materialID) {
1161 feaMaterial = &feaMaterials[j];
1162 break;
1163 }
1164 }
1165
1166 if (feaMaterial == NULL__null) {
1167 AIM_ERROR(aimInfo, "No material information found for element %d!\n", nasMesh->element[i].elementID){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1167, __func__
, "No material information found for element %d!\n", nasMesh->
element[i].elementID); }
;
1168 status = CAPS_BADVALUE-311;
1169 goto cleanup;
1170 }
1171
1172 if (feaMaterial->density > 0 && feaProperty->massPerArea > 0) {
1173 AIM_ERROR(aimInfo, "Cannot specify both Material 'density' and Property 'massPerArea"){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1173, __func__
, "Cannot specify both Material 'density' and Property 'massPerArea"
); }
;
1174 status = CAPS_BADVALUE-311;
1175 goto cleanup;
1176 }
1177
1178 density = 1;
1179 if (feaMaterial->density > 0)
1180 density = feaMaterial->density;
1181
1182 thick = 1;
1183 if (feaProperty->membraneThickness > 0) {
1184 thick = feaProperty->membraneThickness;
1185 }
1186
1187 if (feaProperty->massPerArea > 0) {
1188 density = feaProperty->massPerArea;
1189 thick = 1;
1190 }
1191
1192 elemWeight = elemArea * density * thick;
1193 }
1194
1195 area += elemArea;
1196 mass += elemWeight;
1197
1198 cxmom += xcent * elemArea;
1199 cymom += ycent * elemArea;
1200 czmom += zcent * elemArea;
1201
1202 cgxmom += xcent * elemWeight;
1203 cgymom += ycent * elemWeight;
1204 cgzmom += zcent * elemWeight;
1205
1206 Ixx += (ycent * ycent + zcent * zcent) * elemWeight;
1207 Iyy += (xcent * xcent + zcent * zcent) * elemWeight;
1208 Izz += (xcent * xcent + ycent * ycent) * elemWeight;
1209 Ixy += (xcent * ycent ) * elemWeight;
1210 Ixz += (xcent * zcent ) * elemWeight;
1211 Iyz += (ycent * zcent ) * elemWeight;
1212 }
1213
1214 /* compute statistics for whole Body */
1215 prop.area = area;
1216 prop.mass = mass;
1217
1218 prop.Cx = cxmom / area;
1219 prop.Cy = cymom / area;
1220 prop.Cz = czmom / area;
1221
1222 prop.CGx = CGx = cgxmom / mass;
1223 prop.CGy = CGy = cgymom / mass;
1224 prop.CGz = CGz = cgzmom / mass;
1225
1226 prop.Ixx = Ixx - mass * (CGy * CGy + CGz * CGz);
1227 prop.Iyy = Iyy - mass * (CGx * CGx + CGz * CGz);
1228 prop.Izz = Izz - mass * (CGx * CGx + CGy * CGy);
1229 prop.Ixy = Ixy - mass * CGx * CGy;
1230 prop.Ixz = Ixz - mass * CGx * CGz;
1231 prop.Iyz = Iyz - mass * CGy * CGz;
1232
1233cleanup:
1234 return status;
1235}
1236
1237// ********************** AIM Function Break *****************************
1238template<class T>
1239void setDesignVariableRelation(feaDesignVariableRelationStruct *designRelation, T *var)
1240{
1241 int idv;
1242 double val;
1243
1244 *var = designRelation->constantRelationCoeff;
1245 for (idv = 0; idv < designRelation->numDesignVariable; idv++) {
1246 val = designRelation->designVariableSet[idv]->initialValue;
1247 *var += designRelation->linearRelationCoeff[idv]*val;
1248 }
1249}
1250
1251// ********************** AIM Function Break *****************************
1252template<class T>
1253int getComponents(void *aimInfo, const aimStorage *masstranInstance,
1254 sensPropertyStruct<T> **feaProperty_out,
1255 sensMaterialStruct<T> **feaMaterial_out)
1256{
1257 int status = CAPS_SUCCESS0;
1258 int i, j, idr, ip, im;
1259
1260 sensPropertyStruct<T> *feaProperty = NULL__null;
1261 sensMaterialStruct<T> *feaMaterial = NULL__null;
1262
1263 feaDesignVariableRelationStruct *designRelation = NULL__null;
1264
1265 feaProperty = new sensPropertyStruct<T>[masstranInstance->feaProblem.numProperty];
4
Memory is allocated
1266
1267 for (i = 0; i < masstranInstance->feaProblem.numProperty; i++) {
5
Assuming 'i' is >= field 'numProperty'
6
Loop condition is false. Execution continues on line 1282
1268 feaProperty[i].propertyType = masstranInstance->feaProblem.feaProperty[i].propertyType;
1269 feaProperty[i].propertyID = masstranInstance->feaProblem.feaProperty[i].propertyID;
1270 feaProperty[i].materialID = masstranInstance->feaProblem.feaProperty[i].materialID;
1271 feaProperty[i].membraneThickness = masstranInstance->feaProblem.feaProperty[i].membraneThickness;
1272 feaProperty[i].massPerArea = masstranInstance->feaProblem.feaProperty[i].massPerArea;
1273 feaProperty[i].mass = masstranInstance->feaProblem.feaProperty[i].mass;
1274 for (j = 0; j < 3; j++) {
1275 feaProperty[i].massOffset[j] = masstranInstance->feaProblem.feaProperty[i].massOffset[j];
1276 }
1277 for (j = 0; j < 6; j++) {
1278 feaProperty[i].massInertia[j] = masstranInstance->feaProblem.feaProperty[i].massInertia[j];
1279 }
1280 }
1281
1282 feaMaterial = new sensMaterialStruct<T>[masstranInstance->feaProblem.numMaterial];
1283
1284 for (i = 0; i < masstranInstance->feaProblem.numMaterial; i++) {
7
Assuming 'i' is < field 'numMaterial'
8
Loop condition is true. Entering loop body
9
Assuming 'i' is >= field 'numMaterial'
10
Loop condition is false. Execution continues on line 1291
1285 feaMaterial[i].materialType = masstranInstance->feaProblem.feaMaterial[i].materialType;
1286 feaMaterial[i].materialID = masstranInstance->feaProblem.feaMaterial[i].materialID;
1287 feaMaterial[i].density = masstranInstance->feaProblem.feaMaterial[i].density;
1288 }
1289
1290 /* set Design Variable Relation values */
1291 for (idr = 0; idr < masstranInstance->feaProblem.numDesignVariableRelation; idr++) {
11
Assuming 'idr' is < field 'numDesignVariableRelation'
12
Loop condition is true. Entering loop body
1292
1293 designRelation = &masstranInstance->feaProblem.feaDesignVariableRelation[idr];
1294
1295 for (ip = 0; ip < designRelation->numPropertyID; ip++) {
13
Assuming 'ip' is >= field 'numPropertyID'
14
Loop condition is false. Execution continues on line 1332
1296 for (j = 0; j < masstranInstance->feaProblem.numProperty; j++) {
1297 if (designRelation->propertySetID[ip] == feaProperty[j].propertyID) {
1298 if (strncasecmp(designRelation->fieldName, "membraneThickness", 17) == 0) {
1299 setDesignVariableRelation(designRelation, &feaProperty[j].membraneThickness);
1300 } else if (strncasecmp(designRelation->fieldName, "massPerArea", 11) == 0) {
1301 setDesignVariableRelation(designRelation, &feaProperty[j].massPerArea);
1302 } else if (strncasecmp(designRelation->fieldName, "mass", 4) == 0) {
1303 setDesignVariableRelation(designRelation, &feaProperty[j].mass);
1304 } else if (strncasecmp(designRelation->fieldName, "massOffset1", 11) == 0) {
1305 setDesignVariableRelation(designRelation, &feaProperty[j].massOffset[0]);
1306 } else if (strncasecmp(designRelation->fieldName, "massOffset2", 11) == 0) {
1307 setDesignVariableRelation(designRelation, &feaProperty[j].massOffset[1]);
1308 } else if (strncasecmp(designRelation->fieldName, "massOffset3", 11) == 0) {
1309 setDesignVariableRelation(designRelation, &feaProperty[j].massOffset[2]);
1310 } else if (strncasecmp(designRelation->fieldName, "Ixx", 3) == 0) {
1311 setDesignVariableRelation(designRelation, &feaProperty[j].massInertia[0]);
1312 } else if (strncasecmp(designRelation->fieldName, "Iyy", 3) == 0) {
1313 setDesignVariableRelation(designRelation, &feaProperty[j].massInertia[1]);
1314 } else if (strncasecmp(designRelation->fieldName, "Izz", 3) == 0) {
1315 setDesignVariableRelation(designRelation, &feaProperty[j].massInertia[2]);
1316 } else if (strncasecmp(designRelation->fieldName, "Ixy", 3) == 0) {
1317 setDesignVariableRelation(designRelation, &feaProperty[j].massInertia[3]);
1318 } else if (strncasecmp(designRelation->fieldName, "Ixz", 3) == 0) {
1319 setDesignVariableRelation(designRelation, &feaProperty[j].massInertia[4]);
1320 } else if (strncasecmp(designRelation->fieldName, "Iyz", 3) == 0) {
1321 setDesignVariableRelation(designRelation, &feaProperty[j].massInertia[5]);
1322 } else {
1323 AIM_ERROR(aimInfo, "Unknown Design_Variable_Relation fieldName = %s", designRelation->fieldName){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1323, __func__
, "Unknown Design_Variable_Relation fieldName = %s", designRelation
->fieldName); }
;
1324 status = CAPS_BADVALUE-311;
1325 goto cleanup;
1326 }
1327 break;
1328 }
1329 }
1330 }
1331
1332 for (im = 0; im < designRelation->numMaterialID; im++) {
15
Assuming 'im' is < field 'numMaterialID'
16
Loop condition is true. Entering loop body
1333 for (j = 0; j < masstranInstance->feaProblem.numMaterial; j++) {
17
Loop condition is true. Entering loop body
1334 if (designRelation->materialSetID[im] == feaMaterial[j].materialID) {
18
Assuming the condition is true
19
Taking true branch
1335 if (strncasecmp(designRelation->fieldName, "density", 7) == 0) {
20
Assuming the condition is false
21
Taking false branch
1336 setDesignVariableRelation(designRelation, &feaMaterial[j].density);
1337 } else {
1338 AIM_ERROR(aimInfo, "Unknown Design_Variable_Relation fieldName = %s", designRelation->fieldName){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1338, __func__
, "Unknown Design_Variable_Relation fieldName = %s", designRelation
->fieldName); }
;
22
Potential leak of memory pointed to by 'feaProperty'
1339 status = CAPS_BADVALUE-311;
1340 goto cleanup;
1341 }
1342 break;
1343 }
1344 }
1345 }
1346 }
1347
1348 *feaProperty_out = feaProperty;
1349 *feaMaterial_out = feaMaterial;
1350
1351cleanup:
1352 return status;
1353}
1354
1355// ********************** AIM Function Break *****************************
1356extern "C" int
1357aimPreAnalysis(const void *instStore, void *aimInfo, capsValue *aimInputs)
1358{
1359 int status; // Status return
1360
1361 int *n2a = NULL__null;
1362
1363 FILE *fp=NULL__null;
1364
1365 const meshStruct *nasMesh;
1366 const aimStorage *masstranInstance;
1367
1368 massProperties<double> massProp;
1369
1370 sensPropertyStruct<double> *feaProperty = NULL__null;
1371 sensMaterialStruct<double> *feaMaterial = NULL__null;
1372
1373 masstranInstance = (const aimStorage *) instStore;
1374 AIM_NOTNULL(aimInputs, aimInfo, status){ if (aimInputs == __null) { status = -307; aim_status(aimInfo
, status, "masstranAIM.cpp", 1374, __func__, 1, "%s == NULL!"
, "aimInputs"); goto cleanup; } }
;
1
Assuming the condition is false
2
Taking false branch
1375
1376 status = getComponents(aimInfo, masstranInstance, &feaProperty, &feaMaterial);
3
Calling 'getComponents<double>'
1377 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1377, __func__, 0); goto cleanup; }
;
1378
1379 nasMesh = &masstranInstance->feaProblem.feaMesh;
1380
1381 // maps from nodeID to mesh->node index
1382 mesh_nodeID2Array(nasMesh, &n2a);
1383 AIM_NOTNULL(n2a, aimInfo, status){ if (n2a == __null) { status = -307; aim_status(aimInfo, status
, "masstranAIM.cpp", 1383, __func__, 1, "%s == NULL!", "n2a")
; goto cleanup; } }
;
1384
1385 status = calcMassProps(aimInfo,
1386 masstranInstance->feaProblem.numProperty,
1387 feaProperty,
1388 masstranInstance->feaProblem.numMaterial,
1389 feaMaterial,
1390 n2a,
1391 nasMesh,
1392 masstranInstance->Lscale,
1393 nasMesh->node,
1394 massProp);
1395 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1395, __func__, 0); goto cleanup; }
;
1396
1397 // store the mass properties
1398 fp = aim_fopen(aimInfo, "masstran.out", "w");
1399 if (fp == NULL__null) {
1400 AIM_ERROR(aimInfo, "Failed to open masstran.out"){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1400, __func__
, "Failed to open masstran.out"); }
;
1401 status = CAPS_IOERR-332;
1402 goto cleanup;
1403 }
1404
1405 fprintf(fp, "%16.12e\n", massProp.area);
1406 fprintf(fp, "%16.12e\n", massProp.mass);
1407
1408 fprintf(fp, "%16.12e\n", massProp.Cx);
1409 fprintf(fp, "%16.12e\n", massProp.Cy);
1410 fprintf(fp, "%16.12e\n", massProp.Cz);
1411
1412 fprintf(fp, "%16.12e\n", massProp.CGx);
1413 fprintf(fp, "%16.12e\n", massProp.CGy);
1414 fprintf(fp, "%16.12e\n", massProp.CGz);
1415
1416 fprintf(fp, "%16.12e\n", massProp.Ixx);
1417 fprintf(fp, "%16.12e\n", massProp.Iyy);
1418 fprintf(fp, "%16.12e\n", massProp.Izz);
1419 fprintf(fp, "%16.12e\n", massProp.Ixy);
1420 fprintf(fp, "%16.12e\n", massProp.Ixz);
1421 fprintf(fp, "%16.12e\n", massProp.Iyz);
1422
1423 fclose(fp); fp = NULL__null;
1424
1425 status = CAPS_SUCCESS0;
1426
1427cleanup:
1428 AIM_FREE(n2a){ EG_free(n2a); n2a = __null; };
1429
1430 delete [] feaProperty;
1431 delete [] feaMaterial;
1432
1433 if (fp != NULL__null) fclose(fp);
1434
1435 return status;
1436}
1437
1438
1439// ********************** AIM Function Break *****************************
1440extern "C" int
1441aimExecute(/*@unused@*/ const void *instStore, /*@unused@*/ void *aimInfo,
1442 int *state)
1443{
1444 *state = 0;
1445 return CAPS_SUCCESS0;
1446}
1447
1448
1449// ********************** AIM Function Break *****************************
1450extern "C" int
1451aimPostAnalysis( void *instStore, /*@unused@*/ void *aimInfo,
1452 /*@unused@*/ int restart, /*@unused@*/ capsValue *inputs)
1453{
1454 int status = CAPS_SUCCESS0;
1455
1456 int i, j, d, idv, idr, irow, icol, ibody, im, ip; // Indexing
1457 int index;
1458 int *n2a = NULL__null;
1459
1460 int numNode = 0;
1461
1462 const char *name;
1463 double *dxyz = NULL__null;
1464
1465 feaDesignVariableStruct *designVariable = NULL__null;
1466 feaDesignVariableRelationStruct *designRelation = NULL__null;
1467
1468 capsValue *geomInVal;
1469 sensNode<SurrealS<1>> *sensNodes=NULL__null;
1470
1471 FILE *fp = NULL__null;
1472 massProperties<SurrealS<1>> massPropS;
1473
1474 sensPropertyStruct<SurrealS<1>> *feaProperty = NULL__null;
1475 sensMaterialStruct<SurrealS<1>> *feaMaterial = NULL__null;
1476
1477 aimStorage *masstranInstance;
1478
1479 masstranInstance = (aimStorage *) instStore;
1480
1481 fp = aim_fopen(aimInfo, "masstran.out", "r");
1482 if (fp == NULL__null) {
1483 AIM_ERROR(aimInfo, "Failed to open masstran.out"){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1483, __func__
, "Failed to open masstran.out"); }
;
1484 return CAPS_IOERR-332;
1485 }
1486
1487 // read the mass properties
1488 fscanf(fp, "%lf", &masstranInstance->area.vals.real);
1489 fscanf(fp, "%lf", &masstranInstance->mass.vals.real);
1490
1491 fscanf(fp, "%lf", &masstranInstance->C.vals.reals[0]);
1492 fscanf(fp, "%lf", &masstranInstance->C.vals.reals[1]);
1493 fscanf(fp, "%lf", &masstranInstance->C.vals.reals[2]);
1494
1495 fscanf(fp, "%lf", &masstranInstance->CG.vals.reals[0]);
1496 fscanf(fp, "%lf", &masstranInstance->CG.vals.reals[1]);
1497 fscanf(fp, "%lf", &masstranInstance->CG.vals.reals[2]);
1498
1499 fscanf(fp, "%lf", &masstranInstance->Ixx.vals.real);
1500 fscanf(fp, "%lf", &masstranInstance->Iyy.vals.real);
1501 fscanf(fp, "%lf", &masstranInstance->Izz.vals.real);
1502 fscanf(fp, "%lf", &masstranInstance->Ixy.vals.real);
1503 fscanf(fp, "%lf", &masstranInstance->Ixz.vals.real);
1504 fscanf(fp, "%lf", &masstranInstance->Iyz.vals.real);
1505
1506 fclose(fp); fp = NULL__null;
1507
1508 if (inputs[inDesign_Variable-1].nullVal == NotNull) {
1509
1510 // maps from nodeID to mesh->node index
1511 mesh_nodeID2Array(&masstranInstance->feaProblem.feaMesh, &n2a);
1512 AIM_NOTNULL(n2a, aimInfo, status){ if (n2a == __null) { status = -307; aim_status(aimInfo, status
, "masstranAIM.cpp", 1512, __func__, 1, "%s == NULL!", "n2a")
; goto cleanup; } }
;
1513
1514 numNode = masstranInstance->feaProblem.feaMesh.numNode;
1515
1516 /* copy over the mesh coordinates */
1517 sensNodes = new sensNode<SurrealS<1>>[numNode];
1518
1519 numNode = 0; j = 0;
1520 for (ibody = 0; ibody < masstranInstance->numMesh; ibody++) {
1521 for (i = 0; i < masstranInstance->feaMesh[ibody].numNode; i++, j++) {
1522 sensNodes[j].xyz[0] = masstranInstance->feaMesh[ibody].node[i].xyz[0];
1523 sensNodes[j].xyz[1] = masstranInstance->feaMesh[ibody].node[i].xyz[1];
1524 sensNodes[j].xyz[2] = masstranInstance->feaMesh[ibody].node[i].xyz[2];
1525 }
1526 numNode += masstranInstance->feaMesh[ibody].numNode;
1527 }
1528
1529 status = getComponents(aimInfo, masstranInstance, &feaProperty, &feaMaterial);
1530 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1530, __func__, 0); goto cleanup; }
;
1531
1532 /* set derivatives for AnalysisIn variables */
1533 for (idv = 0; idv < masstranInstance->feaProblem.numDesignVariable; idv++) {
1534
1535 designVariable = &masstranInstance->feaProblem.feaDesignVariable[idv];
1536
1537 for (idr = 0; idr < designVariable->numRelation; idr++) {
1538
1539 designRelation = designVariable->relationSet[idr];
1540
1541 for (i = 0; i < designRelation->numDesignVariable; i++) {
1542
1543 if (designVariable == designRelation->designVariableSet[i]) {
1544
1545 for (ip = 0; ip < designRelation->numPropertyID; ip++) {
1546 for (j = 0; j < masstranInstance->feaProblem.numProperty; j++) {
1547 if (designRelation->propertySetID[ip] == feaProperty[j].propertyID) {
1548 if (strncasecmp(designRelation->fieldName, "membraneThickness", 17) == 0) {
1549 feaProperty[j].membraneThickness.deriv() = designRelation->linearRelationCoeff[i];
1550 } else if (strncasecmp(designRelation->fieldName, "massPerArea", 11) == 0) {
1551 feaProperty[j].massPerArea.deriv() = designRelation->linearRelationCoeff[i];
1552 } else if (strncasecmp(designRelation->fieldName, "mass", 4) == 0) {
1553 feaProperty[j].mass.deriv() = designRelation->linearRelationCoeff[i];
1554 } else if (strncasecmp(designRelation->fieldName, "massOffset1", 11) == 0) {
1555 feaProperty[j].massOffset[0].deriv() = designRelation->linearRelationCoeff[i];
1556 } else if (strncasecmp(designRelation->fieldName, "massOffset2", 11) == 0) {
1557 feaProperty[j].massOffset[1].deriv() = designRelation->linearRelationCoeff[i];
1558 } else if (strncasecmp(designRelation->fieldName, "massOffset3", 11) == 0) {
1559 feaProperty[j].massOffset[2].deriv() = designRelation->linearRelationCoeff[i];
1560 } else if (strncasecmp(designRelation->fieldName, "Ixx", 3) == 0) {
1561 feaProperty[j].massInertia[0].deriv() = designRelation->linearRelationCoeff[i];
1562 } else if (strncasecmp(designRelation->fieldName, "Iyy", 3) == 0) {
1563 feaProperty[j].massInertia[1].deriv() = designRelation->linearRelationCoeff[i];
1564 } else if (strncasecmp(designRelation->fieldName, "Izz", 3) == 0) {
1565 feaProperty[j].massInertia[2].deriv() = designRelation->linearRelationCoeff[i];
1566 } else if (strncasecmp(designRelation->fieldName, "Ixy", 3) == 0) {
1567 feaProperty[j].massInertia[3].deriv() = designRelation->linearRelationCoeff[i];
1568 } else if (strncasecmp(designRelation->fieldName, "Ixz", 3) == 0) {
1569 feaProperty[j].massInertia[4].deriv() = designRelation->linearRelationCoeff[i];
1570 } else if (strncasecmp(designRelation->fieldName, "Iyz", 3) == 0) {
1571 feaProperty[j].massInertia[5].deriv() = designRelation->linearRelationCoeff[i];
1572 } else {
1573 AIM_ERROR(aimInfo, "Unknown Design_Variable_Relation fieldName = %s", designRelation->fieldName){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1573, __func__
, "Unknown Design_Variable_Relation fieldName = %s", designRelation
->fieldName); }
;
1574 status = CAPS_BADVALUE-311;
1575 goto cleanup;
1576 }
1577
1578 break;
1579 }
1580 }
1581 }
1582
1583 for (im = 0; im < designRelation->numMaterialID; im++) {
1584 for (j = 0; j < masstranInstance->feaProblem.numMaterial; j++) {
1585 if (designRelation->materialSetID[im] == feaMaterial[j].materialID) {
1586 if (strncasecmp(designRelation->fieldName, "density", 4) == 0) {
1587 feaMaterial[j].density.deriv() = designRelation->linearRelationCoeff[i];
1588 } else {
1589 AIM_ERROR(aimInfo, "Unknown Design_Variable_Relation fieldName = %s", designRelation->fieldName){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1589, __func__
, "Unknown Design_Variable_Relation fieldName = %s", designRelation
->fieldName); }
;
1590 status = CAPS_BADVALUE-311;
1591 goto cleanup;
1592 }
1593 break;
1594 }
1595 }
1596 }
1597 }
1598 }
1599 }
1600
1601 status = calcMassProps(aimInfo,
1602 masstranInstance->feaProblem.numProperty,
1603 feaProperty,
1604 masstranInstance->feaProblem.numMaterial,
1605 feaMaterial,
1606 n2a,
1607 &masstranInstance->feaProblem.feaMesh,
1608 masstranInstance->Lscale,
1609 sensNodes,
1610 massPropS);
1611 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1611, __func__, 0); goto cleanup; }
;
1612
1613
1614 masstranInstance->area.derivs[idv].deriv[0] = massPropS.area.deriv();
1615 masstranInstance->mass.derivs[idv].deriv[0] = massPropS.mass.deriv();
1616 masstranInstance->Ixx .derivs[idv].deriv[0] = massPropS.Ixx .deriv();
1617 masstranInstance->Iyy .derivs[idv].deriv[0] = massPropS.Iyy .deriv();
1618 masstranInstance->Izz .derivs[idv].deriv[0] = massPropS.Izz .deriv();
1619 masstranInstance->Ixy .derivs[idv].deriv[0] = massPropS.Ixy .deriv();
1620 masstranInstance->Ixz .derivs[idv].deriv[0] = massPropS.Ixz .deriv();
1621 masstranInstance->Iyz .derivs[idv].deriv[0] = massPropS.Iyz .deriv();
1622
1623 masstranInstance->C.derivs[idv].deriv[0] = massPropS.Cx.deriv();
1624 masstranInstance->C.derivs[idv].deriv[1] = massPropS.Cy.deriv();
1625 masstranInstance->C.derivs[idv].deriv[2] = massPropS.Cz.deriv();
1626
1627 masstranInstance->CG.derivs[idv].deriv[0] = massPropS.CGx.deriv();
1628 masstranInstance->CG.derivs[idv].deriv[1] = massPropS.CGy.deriv();
1629 masstranInstance->CG.derivs[idv].deriv[2] = massPropS.CGz.deriv();
1630
1631 for (j = 0; j < masstranInstance->feaProblem.numProperty; j++) {
1632 feaProperty[j].membraneThickness.deriv() = 0;
1633 feaProperty[j].massPerArea.deriv() = 0;
1634 feaProperty[j].mass.deriv() = 0;
1635 for (d = 0; d < 3; d++) {
1636 feaProperty[j].massOffset[d].deriv() = 0;
1637 }
1638 for (d = 0; d < 6; d++) {
1639 feaProperty[j].massInertia[d].deriv() = 0;
1640 }
1641 }
1642 for (j = 0; j < masstranInstance->feaProblem.numMaterial; j++) {
1643 feaMaterial[j].density.deriv() = 0;
1644 }
1645 }
1646
1647 /* set derivatives for GeomegtryIn variables */
1648 for (idv = 0; idv < masstranInstance->feaProblem.numDesignVariable; idv++) {
1649
1650 name = masstranInstance->feaProblem.feaDesignVariable[idv].name;
1651
1652 // Loop over the geometry in values and compute sensitivities for all bodies
1653 index = aim_getIndex(aimInfo, name, GEOMETRYIN);
1654 status = aim_getValue(aimInfo, index, GEOMETRYIN, &geomInVal);
1655 if (status == CAPS_BADINDEX-304) continue;
1656 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1656, __func__, 0); goto cleanup; }
;
1657
1658 if(aim_getGeomInType(aimInfo, index) != 0) {
1659 AIM_ERROR(aimInfo, "GeometryIn value %s is a configuration parameter and not a valid design parameter - can't get sensitivity\n",{ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1660, __func__
, "GeometryIn value %s is a configuration parameter and not a valid design parameter - can't get sensitivity\n"
, name); }
1660 name){ aim_message(aimInfo, CERROR, 0 , "masstranAIM.cpp", 1660, __func__
, "GeometryIn value %s is a configuration parameter and not a valid design parameter - can't get sensitivity\n"
, name); }
;
1661 status = CAPS_BADVALUE-311;
1662 goto cleanup;
1663 }
1664
1665 for (irow = 0; irow < geomInVal->nrow; irow++) {
1666 for (icol = 0; icol < geomInVal->ncol; icol++) {
1667
1668 j = 1; // 1-based
1669 for (ibody = 0; ibody < masstranInstance->numMesh; ibody++) {
1670 status = aim_tessSensitivity(aimInfo,
1671 name,
1672 irow+1, icol+1, // row, col
1673 masstranInstance->feaMesh[ibody].egadsTess,
1674 &i, &dxyz);
1675 AIM_STATUS(aimInfo, status, "Sensitivity for: %s\n", name)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1675, __func__, 2, "Sensitivity for: %s\n", name); goto cleanup
; }
;
1676 AIM_NOTNULL(dxyz, aimInfo, status){ if (dxyz == __null) { status = -307; aim_status(aimInfo, status
, "masstranAIM.cpp", 1676, __func__, 1, "%s == NULL!", "dxyz"
); goto cleanup; } }
;
1677
1678
1679 for (i = 0; i < masstranInstance->feaMesh[ibody].numNode; i++, j++) {
1680 if (n2a[j] < 0) continue;
1681 sensNodes[n2a[j]].xyz[0].deriv() = dxyz[3*i+0]; // dx/dGeomIn
1682 sensNodes[n2a[j]].xyz[1].deriv() = dxyz[3*i+1]; // dy/dGeomIn
1683 sensNodes[n2a[j]].xyz[2].deriv() = dxyz[3*i+2]; // dz/dGeomIn
1684 }
1685 AIM_FREE(dxyz){ EG_free(dxyz); dxyz = __null; };
1686 }
1687
1688 status = calcMassProps(aimInfo,
1689 masstranInstance->feaProblem.numProperty,
1690 feaProperty,
1691 masstranInstance->feaProblem.numMaterial,
1692 feaMaterial,
1693 n2a,
1694 &masstranInstance->feaProblem.feaMesh,
1695 masstranInstance->Lscale,
1696 sensNodes,
1697 massPropS);
1698 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1698, __func__, 0); goto cleanup; }
;
1699
1700 masstranInstance->area.derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.area.deriv();
1701 masstranInstance->mass.derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.mass.deriv();
1702 masstranInstance->Ixx .derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.Ixx .deriv();
1703 masstranInstance->Iyy .derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.Iyy .deriv();
1704 masstranInstance->Izz .derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.Izz .deriv();
1705 masstranInstance->Ixy .derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.Ixy .deriv();
1706 masstranInstance->Ixz .derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.Ixz .deriv();
1707 masstranInstance->Iyz .derivs[idv].deriv[geomInVal->ncol*irow + icol] = massPropS.Iyz .deriv();
1708
1709 masstranInstance->C.derivs[idv].deriv[0*geomInVal->length + geomInVal->ncol*irow + icol] = massPropS.Cx.deriv();
1710 masstranInstance->C.derivs[idv].deriv[1*geomInVal->length + geomInVal->ncol*irow + icol] = massPropS.Cy.deriv();
1711 masstranInstance->C.derivs[idv].deriv[2*geomInVal->length + geomInVal->ncol*irow + icol] = massPropS.Cz.deriv();
1712
1713 masstranInstance->CG.derivs[idv].deriv[0*geomInVal->length + geomInVal->ncol*irow + icol] = massPropS.CGx.deriv();
1714 masstranInstance->CG.derivs[idv].deriv[1*geomInVal->length + geomInVal->ncol*irow + icol] = massPropS.CGy.deriv();
1715 masstranInstance->CG.derivs[idv].deriv[2*geomInVal->length + geomInVal->ncol*irow + icol] = massPropS.CGz.deriv();
1716 }
1717 }
1718 }
1719 }
1720
1721 status = CAPS_SUCCESS0;
1722cleanup:
1723
1724 if (fp != NULL__null) fclose(fp);
1725
1726 AIM_FREE(n2a){ EG_free(n2a); n2a = __null; };
1727 AIM_FREE(dxyz){ EG_free(dxyz); dxyz = __null; };
1728
1729 delete [] sensNodes;
1730 delete [] feaProperty;
1731 delete [] feaMaterial;
1732
1733 return status;
1734}
1735
1736
1737// ********************** AIM Function Break *****************************
1738extern "C" int
1739aimOutputs( void *instStore, void *aimInfo,
1740 int index, char **aoname, capsValue *form)
1741{
1742 int status = CAPS_SUCCESS0;
1743
1744#ifdef DEBUG
1745 printf(" masstranAIM/aimOutputs index = %d!\n", index);
1746#endif
1747 feaUnitsStruct *units=NULL__null;
1748 aimStorage *masstranInstance;
1749 char *tmpUnits = NULL__null;
1750
1751 masstranInstance = (aimStorage *) instStore;
1752 AIM_NOTNULL(masstranInstance, aimInfo, status){ if (masstranInstance == __null) { status = -307; aim_status
(aimInfo, status, "masstranAIM.cpp", 1752, __func__, 1, "%s == NULL!"
, "masstranInstance"); goto cleanup; } }
;
1753
1754 units = &masstranInstance->units;
1755
1756 /*! \page aimOutputsMasstran AIM Outputs
1757 * The following list outlines the Masstran outputs available through the AIM interface.
1758 */
1759 /*! \page aimOutputsMasstran AIM Outputs
1760 * - <B>Area</B> = Total area of the mesh.
1761 * - <B>Mass</B> = Total mass of the model.
1762 * - <B>Centroid</B> = Centroid of the model.
1763 * - <B>CG</B> = Center of gravity of the model.
1764 * - <B>Ixx</B> = Moment of inertia
1765 * - <B>Iyy</B> = Moment of inertia
1766 * - <B>Izz</B> = Moment of inertia
1767 * - <B>Ixy</B> = Moment of inertia
1768 * - <B>Izy</B> = Moment of inertia
1769 * - <B>Iyz</B> = Moment of inertia
1770 * - <B>I_Vector</B> = Moment of inertia vector
1771 * \f[
1772 * \vec{I} = \begin{bmatrix} I_{xx} & I_{yy} & I_{zz} & I_{xy} & I_{xz} & I_{yz} \end{bmatrix}
1773 * \f]
1774 * - <B>I_Lower</B> = Moment of inertia lower triangular tensor
1775 * \f[
1776 * \vec{I}_{lower} = \begin{bmatrix} I_{xx} & -I_{xy} & I_{yy} & -I_{xz} & -I_{yz} & I_{zz} \end{bmatrix},
1777 * \f]
1778 * - <B>I_Upper</B> = Moment of inertia upper triangular tensor
1779 * \f[
1780 * \vec{I}_{upper} = \begin{bmatrix} I_{xx} & -I_{xy} & -I_{xz} & I_{yy} & -I_{yz} & I_{zz} \end{bmatrix},
1781 * \f]
1782 * - <B>I_Tensor</B> = Moment of inertia tensor
1783 * \f[
1784 * \bar{\bar{I}} =
1785 * \begin{bmatrix}
1786 * I_{xx} & -I_{xy} & -I_{xz} \\
1787 * -I_{xy} & I_{yy} & -I_{yz} \\
1788 * -I_{xz} & -I_{yz} & I_{zz}
1789 * \end{bmatrix}
1790 * \f]
1791 */
1792
1793 if (index == outArea) {
1794 *aoname = EG_strdup("Area");
1795 form->dim = Scalar;
1796
1797 } else if (index == outMass) {
1798 *aoname = EG_strdup("Mass");
1799 form->dim = Scalar;
1800
1801 } else if (index == outCentroid) {
1802 *aoname = EG_strdup("Centroid");
1803 form->nrow = 3;
1804 form->dim = Vector;
1805
1806 } else if (index == outCG) {
1807 *aoname = EG_strdup("CG");
1808 form->nrow = 3;
1809 form->dim = Vector;
1810
1811 } else if (index == outIxx) {
1812 *aoname = EG_strdup("Ixx");
1813 form->dim = Scalar;
1814
1815 } else if (index == outIyy) {
1816 *aoname = EG_strdup("Iyy");
1817 form->dim = Scalar;
1818
1819 } else if (index == outIzz) {
1820 *aoname = EG_strdup("Izz");
1821 form->dim = Scalar;
1822
1823 } else if (index == outIxy) {
1824 *aoname = EG_strdup("Ixy");
1825 form->dim = Scalar;
1826
1827 } else if (index == outIxz) {
1828 *aoname = EG_strdup("Ixz");
1829 form->dim = Scalar;
1830
1831 } else if (index == outIyz) {
1832 *aoname = EG_strdup("Iyz");
1833 form->dim = Scalar;
1834
1835 } else if (index == outI_Vector) {
1836 *aoname = EG_strdup("I_Vector");
1837 form->nrow = 6;
1838 form->dim = Vector;
1839
1840 } else if (index == outI_Lower) {
1841 *aoname = EG_strdup("I_Lower");
1842 form->nrow = 6;
1843 form->dim = Vector;
1844
1845 } else if (index == outI_Upper) {
1846 *aoname = EG_strdup("I_Upper");
1847 form->nrow = 6;
1848 form->dim = Vector;
1849
1850 } else if (index == outI_Tensor) {
1851 *aoname = EG_strdup("I_Tensor");
1852 form->nrow = 9;
1853 form->dim = Array2D;
1854
1855 } else if (index == outMassProp) {
1856 *aoname = EG_strdup("MassProp");
1857 form->type = String;
1858 form->nullVal = IsNull;
1859 goto cleanup;
1860
1861 }
1862
1863 if (*aoname == NULL__null) return EGADS_MALLOC-4;
1864
1865 form->type = Double;
1866 form->lfixed = Fixed;
1867 form->sfixed = Fixed;
1868 form->vals.reals = NULL__null;
1869 form->vals.real = 0;
1870
1871 if (form->nrow > 1) {
1872 AIM_ALLOC(form->vals.reals, form->nrow, double, aimInfo, status){ if (form->vals.reals != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 1872, __func__, 1, "AIM_ALLOC: %s != NULL"
, "form->vals.reals"); goto cleanup; } size_t memorysize =
form->nrow; form->vals.reals = (double *) EG_alloc(memorysize
*sizeof(double)); if (form->vals.reals == __null) { status
= -4; aim_status(aimInfo, status, "masstranAIM.cpp", 1872, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "form->vals.reals",
memorysize, "double"); goto cleanup; } }
;
1873 memset(form->vals.reals, 0, form->nrow*sizeof(double));
1874 }
1875
1876 if (units->momentOfInertia != NULL__null &&
1877 index >= outI_Vector && index <= outI_Tensor) {
1878 AIM_STRDUP(form->units, units->momentOfInertia, aimInfo, status){ if (form->units != __null) { status = -4; aim_status(aimInfo
, status, "masstranAIM.cpp", 1878, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "form->units"); goto cleanup; } form->units = EG_strdup
(units->momentOfInertia); if (form->units == __null) { status
= -4; aim_status(aimInfo, status, "masstranAIM.cpp", 1878, __func__
, 2, "AIM_STRDUP: %s %s", "form->units", units->momentOfInertia
); goto cleanup; } }
;
1879 }
1880
1881 if (index == outI_Tensor) {
1882 form->nrow = 3;
1883 form->ncol = 3;
1884 }
1885
1886cleanup:
1887 AIM_FREE(tmpUnits){ EG_free(tmpUnits); tmpUnits = __null; };
1888
1889 return status;
1890}
1891
1892
1893/* aimCalcOutput: Calculate/Retrieve Output Information */
1894extern "C" int
1895aimCalcOutput(void *instStore, /*@unused@*/ void *aimInfo,
1896 /*@unused@*/ int index, capsValue *val)
1897{
1898 int status = CAPS_SUCCESS0;
1899 int idv, j, len_wrt;
1900 double mass = 0, CGx = 0, CGy = 0, CGz = 0;
1901 double Ixx = 0;
1902 double Ixy = 0;
1903 double Izz = 0;
1904 double Ixz = 0;
1905 double Iyy = 0;
1906 double Iyz = 0;
1907 double *I;
1908 char massProp[512];
1909 feaUnitsStruct *units=NULL__null;
1910 aimStorage *masstranInstance;
1911
1912#ifdef DEBUG
1913 const char *name;
1914
1915 status = aim_getName(aimInfo, index, ANALYSISOUT, &name);
1916 printf(" masstranAIM/aimCalcOutput instance = %d index = %d %s %d!\n",
1917 aim_getInstance(aimInfo), index, name, status);
1918#endif
1919
1920 masstranInstance = (aimStorage *) instStore;
1921
1922 units = &masstranInstance->units;
1923
1924 if (index < outI_Vector)
1925 aim_freeValue(val);
1926
1927 if (index == outArea) {
1928 status = aim_copyValue(&masstranInstance->area, val);
1929 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1929, __func__, 0); goto cleanup; }
;
1930
1931 } else if (index == outMass) {
1932 status = aim_copyValue(&masstranInstance->mass, val);
1933 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1933, __func__, 0); goto cleanup; }
;
1934
1935 } else if (index == outCentroid) {
1936 status = aim_copyValue(&masstranInstance->C, val);
1937 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1937, __func__, 0); goto cleanup; }
;
1938
1939 } else if (index == outCG) {
1940 status = aim_copyValue(&masstranInstance->CG, val);
1941 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1941, __func__, 0); goto cleanup; }
;
1942
1943 } else if (index == outIxx) {
1944 status = aim_copyValue(&masstranInstance->Ixx, val);
1945 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1945, __func__, 0); goto cleanup; }
;
1946
1947 } else if (index == outIyy) {
1948 status = aim_copyValue(&masstranInstance->Iyy, val);
1949 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1949, __func__, 0); goto cleanup; }
;
1950
1951 } else if (index == outIzz) {
1952 status = aim_copyValue(&masstranInstance->Izz, val);
1953 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1953, __func__, 0); goto cleanup; }
;
1954
1955 } else if (index == outIxy) {
1956 status = aim_copyValue(&masstranInstance->Ixy, val);
1957 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1957, __func__, 0); goto cleanup; }
;
1958
1959 } else if (index == outIxz) {
1960 status = aim_copyValue(&masstranInstance->Ixz, val);
1961 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1961, __func__, 0); goto cleanup; }
;
1962
1963 } else if (index == outIyz) {
1964 status = aim_copyValue(&masstranInstance->Iyz, val);
1965 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "masstranAIM.cpp"
, 1965, __func__, 0); goto cleanup; }
;
1966
1967 } else if (index == outI_Vector) {
1968 val->type = Double;
1969 AIM_ALLOC(val->vals.reals, val->length, double, aimInfo, status){ if (val->vals.reals != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 1969, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->vals.reals"); goto cleanup; } size_t memorysize = val
->length; val->vals.reals = (double *) EG_alloc(memorysize
*sizeof(double)); if (val->vals.reals == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 1969, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->vals.reals", memorysize
, "double"); goto cleanup; } }
;
1970
1971 val->vals.reals[0] = masstranInstance->Ixx.vals.real;
1972 val->vals.reals[1] = masstranInstance->Iyy.vals.real;
1973 val->vals.reals[2] = masstranInstance->Izz.vals.real;
1974 val->vals.reals[3] = masstranInstance->Ixy.vals.real;
1975 val->vals.reals[4] = masstranInstance->Ixz.vals.real;
1976 val->vals.reals[5] = masstranInstance->Iyz.vals.real;
1977
1978 if (masstranInstance->Ixx.nderiv > 0) {
1979 val->type = DoubleDeriv;
1980
1981 /* allocate derivatives */
1982 AIM_ALLOC(val->derivs, masstranInstance->Ixx.nderiv, capsDeriv, aimInfo, status){ if (val->derivs != __null) { status = -4; aim_status(aimInfo
, status, "masstranAIM.cpp", 1982, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs"); goto cleanup; } size_t memorysize = masstranInstance
->Ixx.nderiv; val->derivs = (capsDeriv *) EG_alloc(memorysize
*sizeof(capsDeriv)); if (val->derivs == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 1982, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->derivs", memorysize
, "capsDeriv"); goto cleanup; } }
;
1983 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
1984 val->derivs[idv].name = NULL__null;
1985 val->derivs[idv].deriv = NULL__null;
1986 val->derivs[idv].len_wrt = 0;
1987 }
1988 val->nderiv = masstranInstance->Ixx.nderiv;
1989
1990 /* set derivatives */
1991 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
1992
1993 AIM_STRDUP(val->derivs[idv].name, masstranInstance->Ixx.derivs[idv].name, aimInfo, status){ if (val->derivs[idv].name != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 1993, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "val->derivs[idv].name"); goto cleanup; } val->derivs
[idv].name = EG_strdup(masstranInstance->Ixx.derivs[idv].name
); if (val->derivs[idv].name == __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 1993, __func__, 2, "AIM_STRDUP: %s %s"
, "val->derivs[idv].name", masstranInstance->Ixx.derivs
[idv].name); goto cleanup; } }
;
1994
1995 val->derivs[idv].len_wrt = masstranInstance->Ixx.derivs[idv].len_wrt;
1996
1997 len_wrt = val->derivs[idv].len_wrt;
1998 AIM_ALLOC(val->derivs[idv].deriv, val->length*len_wrt, double, aimInfo, status){ if (val->derivs[idv].deriv != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 1998, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs[idv].deriv"); goto cleanup; } size_t memorysize
= val->length*len_wrt; val->derivs[idv].deriv = (double
*) EG_alloc(memorysize*sizeof(double)); if (val->derivs[idv
].deriv == __null) { status = -4; aim_status(aimInfo, status,
"masstranAIM.cpp", 1998, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "val->derivs[idv].deriv", memorysize, "double"); goto cleanup
; } }
;
1999 for (j = 0; j < len_wrt; j++) {
2000 val->derivs[idv].deriv[0*len_wrt + j] = masstranInstance->Ixx.derivs[idv].deriv[j];
2001 val->derivs[idv].deriv[1*len_wrt + j] = masstranInstance->Iyy.derivs[idv].deriv[j];
2002 val->derivs[idv].deriv[2*len_wrt + j] = masstranInstance->Izz.derivs[idv].deriv[j];
2003 val->derivs[idv].deriv[3*len_wrt + j] = masstranInstance->Ixy.derivs[idv].deriv[j];
2004 val->derivs[idv].deriv[4*len_wrt + j] = masstranInstance->Ixz.derivs[idv].deriv[j];
2005 val->derivs[idv].deriv[5*len_wrt + j] = masstranInstance->Iyz.derivs[idv].deriv[j];
2006 }
2007 }
2008 }
2009
2010 } else if (index == outI_Lower) {
2011 val->type = Double;
2012 AIM_ALLOC(val->vals.reals, val->length, double, aimInfo, status){ if (val->vals.reals != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2012, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->vals.reals"); goto cleanup; } size_t memorysize = val
->length; val->vals.reals = (double *) EG_alloc(memorysize
*sizeof(double)); if (val->vals.reals == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 2012, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->vals.reals", memorysize
, "double"); goto cleanup; } }
;
2013
2014 val->vals.reals[0] = masstranInstance->Ixx.vals.real;
2015 val->vals.reals[1] = -masstranInstance->Ixy.vals.real;
2016 val->vals.reals[2] = masstranInstance->Iyy.vals.real;
2017 val->vals.reals[3] = -masstranInstance->Ixz.vals.real;
2018 val->vals.reals[4] = -masstranInstance->Iyz.vals.real;
2019 val->vals.reals[5] = masstranInstance->Izz.vals.real;
2020
2021 if (masstranInstance->Ixx.nderiv > 0) {
2022 val->type = DoubleDeriv;
2023
2024 /* allocate derivatives */
2025 AIM_ALLOC(val->derivs, masstranInstance->Ixx.nderiv, capsDeriv, aimInfo, status){ if (val->derivs != __null) { status = -4; aim_status(aimInfo
, status, "masstranAIM.cpp", 2025, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs"); goto cleanup; } size_t memorysize = masstranInstance
->Ixx.nderiv; val->derivs = (capsDeriv *) EG_alloc(memorysize
*sizeof(capsDeriv)); if (val->derivs == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 2025, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->derivs", memorysize
, "capsDeriv"); goto cleanup; } }
;
2026 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
2027 val->derivs[idv].name = NULL__null;
2028 val->derivs[idv].deriv = NULL__null;
2029 val->derivs[idv].len_wrt = 0;
2030 }
2031 val->nderiv = masstranInstance->Ixx.nderiv;
2032
2033 /* set derivatives */
2034 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
2035
2036 AIM_STRDUP(val->derivs[idv].name, masstranInstance->Ixx.derivs[idv].name, aimInfo, status){ if (val->derivs[idv].name != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2036, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "val->derivs[idv].name"); goto cleanup; } val->derivs
[idv].name = EG_strdup(masstranInstance->Ixx.derivs[idv].name
); if (val->derivs[idv].name == __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2036, __func__, 2, "AIM_STRDUP: %s %s"
, "val->derivs[idv].name", masstranInstance->Ixx.derivs
[idv].name); goto cleanup; } }
;
2037
2038 val->derivs[idv].len_wrt = masstranInstance->Ixx.derivs[idv].len_wrt;
2039
2040 len_wrt = val->derivs[idv].len_wrt;
2041 AIM_ALLOC(val->derivs[idv].deriv, val->length*len_wrt, double, aimInfo, status){ if (val->derivs[idv].deriv != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2041, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs[idv].deriv"); goto cleanup; } size_t memorysize
= val->length*len_wrt; val->derivs[idv].deriv = (double
*) EG_alloc(memorysize*sizeof(double)); if (val->derivs[idv
].deriv == __null) { status = -4; aim_status(aimInfo, status,
"masstranAIM.cpp", 2041, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "val->derivs[idv].deriv", memorysize, "double"); goto cleanup
; } }
;
2042 for (j = 0; j < len_wrt; j++) {
2043 val->derivs[idv].deriv[0*len_wrt + j] = masstranInstance->Ixx.derivs[idv].deriv[j];
2044 val->derivs[idv].deriv[1*len_wrt + j] = -masstranInstance->Ixy.derivs[idv].deriv[j];
2045 val->derivs[idv].deriv[2*len_wrt + j] = masstranInstance->Iyy.derivs[idv].deriv[j];
2046 val->derivs[idv].deriv[3*len_wrt + j] = -masstranInstance->Ixz.derivs[idv].deriv[j];
2047 val->derivs[idv].deriv[4*len_wrt + j] = -masstranInstance->Iyz.derivs[idv].deriv[j];
2048 val->derivs[idv].deriv[5*len_wrt + j] = masstranInstance->Izz.derivs[idv].deriv[j];
2049 }
2050 }
2051 }
2052
2053 } else if (index == outI_Upper) {
2054 val->type = Double;
2055 AIM_ALLOC(val->vals.reals, val->length, double, aimInfo, status){ if (val->vals.reals != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2055, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->vals.reals"); goto cleanup; } size_t memorysize = val
->length; val->vals.reals = (double *) EG_alloc(memorysize
*sizeof(double)); if (val->vals.reals == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 2055, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->vals.reals", memorysize
, "double"); goto cleanup; } }
;
2056
2057 val->vals.reals[0] = masstranInstance->Ixx.vals.real;
2058 val->vals.reals[1] = -masstranInstance->Ixy.vals.real;
2059 val->vals.reals[2] = -masstranInstance->Ixz.vals.real;
2060 val->vals.reals[3] = masstranInstance->Iyy.vals.real;
2061 val->vals.reals[4] = -masstranInstance->Iyz.vals.real;
2062 val->vals.reals[5] = masstranInstance->Izz.vals.real;
2063
2064 if (masstranInstance->Ixx.nderiv > 0) {
2065 val->type = DoubleDeriv;
2066
2067 /* allocate derivatives */
2068 AIM_ALLOC(val->derivs, masstranInstance->Ixx.nderiv, capsDeriv, aimInfo, status){ if (val->derivs != __null) { status = -4; aim_status(aimInfo
, status, "masstranAIM.cpp", 2068, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs"); goto cleanup; } size_t memorysize = masstranInstance
->Ixx.nderiv; val->derivs = (capsDeriv *) EG_alloc(memorysize
*sizeof(capsDeriv)); if (val->derivs == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 2068, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->derivs", memorysize
, "capsDeriv"); goto cleanup; } }
;
2069 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
2070 val->derivs[idv].name = NULL__null;
2071 val->derivs[idv].deriv = NULL__null;
2072 val->derivs[idv].len_wrt = 0;
2073 }
2074 val->nderiv = masstranInstance->Ixx.nderiv;
2075
2076 /* set derivatives */
2077 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
2078
2079 AIM_STRDUP(val->derivs[idv].name, masstranInstance->Ixx.derivs[idv].name, aimInfo, status){ if (val->derivs[idv].name != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2079, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "val->derivs[idv].name"); goto cleanup; } val->derivs
[idv].name = EG_strdup(masstranInstance->Ixx.derivs[idv].name
); if (val->derivs[idv].name == __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2079, __func__, 2, "AIM_STRDUP: %s %s"
, "val->derivs[idv].name", masstranInstance->Ixx.derivs
[idv].name); goto cleanup; } }
;
2080
2081 val->derivs[idv].len_wrt = masstranInstance->Ixx.derivs[idv].len_wrt;
2082
2083 len_wrt = val->derivs[idv].len_wrt;
2084 AIM_ALLOC(val->derivs[idv].deriv, val->length*len_wrt, double, aimInfo, status){ if (val->derivs[idv].deriv != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2084, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs[idv].deriv"); goto cleanup; } size_t memorysize
= val->length*len_wrt; val->derivs[idv].deriv = (double
*) EG_alloc(memorysize*sizeof(double)); if (val->derivs[idv
].deriv == __null) { status = -4; aim_status(aimInfo, status,
"masstranAIM.cpp", 2084, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "val->derivs[idv].deriv", memorysize, "double"); goto cleanup
; } }
;
2085 for (j = 0; j < len_wrt; j++) {
2086 val->derivs[idv].deriv[0*len_wrt + j] = masstranInstance->Ixx.derivs[idv].deriv[j];
2087 val->derivs[idv].deriv[1*len_wrt + j] = -masstranInstance->Ixy.derivs[idv].deriv[j];
2088 val->derivs[idv].deriv[2*len_wrt + j] = -masstranInstance->Ixz.derivs[idv].deriv[j];
2089 val->derivs[idv].deriv[3*len_wrt + j] = masstranInstance->Iyy.derivs[idv].deriv[j];
2090 val->derivs[idv].deriv[4*len_wrt + j] = -masstranInstance->Iyz.derivs[idv].deriv[j];
2091 val->derivs[idv].deriv[5*len_wrt + j] = masstranInstance->Izz.derivs[idv].deriv[j];
2092 }
2093 }
2094 }
2095
2096 } else if (index == outI_Tensor) {
2097 val->type = Double;
2098 AIM_ALLOC(val->vals.reals, val->length, double, aimInfo, status){ if (val->vals.reals != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2098, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->vals.reals"); goto cleanup; } size_t memorysize = val
->length; val->vals.reals = (double *) EG_alloc(memorysize
*sizeof(double)); if (val->vals.reals == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 2098, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->vals.reals", memorysize
, "double"); goto cleanup; } }
;
2099
2100 Ixx = masstranInstance->Ixx.vals.real;
2101 Iyy = masstranInstance->Iyy.vals.real;
2102 Iyz = masstranInstance->Iyz.vals.real;
2103 Ixy = masstranInstance->Ixy.vals.real;
2104 Ixz = masstranInstance->Ixz.vals.real;
2105 Izz = masstranInstance->Izz.vals.real;
2106 I = val->vals.reals;
2107
2108 // populate the tensor
2109 I[0] = Ixx; I[1] = -Ixy; I[2] = -Ixz;
2110 I[3] = -Ixy; I[4] = Iyy; I[5] = -Iyz;
2111 I[6] = -Ixz; I[7] = -Iyz; I[8] = Izz;
2112
2113 if (masstranInstance->Ixx.nderiv > 0) {
2114 val->type = DoubleDeriv;
2115
2116 /* allocate derivatives */
2117 AIM_ALLOC(val->derivs, masstranInstance->Ixx.nderiv, capsDeriv, aimInfo, status){ if (val->derivs != __null) { status = -4; aim_status(aimInfo
, status, "masstranAIM.cpp", 2117, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs"); goto cleanup; } size_t memorysize = masstranInstance
->Ixx.nderiv; val->derivs = (capsDeriv *) EG_alloc(memorysize
*sizeof(capsDeriv)); if (val->derivs == __null) { status =
-4; aim_status(aimInfo, status, "masstranAIM.cpp", 2117, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "val->derivs", memorysize
, "capsDeriv"); goto cleanup; } }
;
2118 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
2119 val->derivs[idv].name = NULL__null;
2120 val->derivs[idv].deriv = NULL__null;
2121 val->derivs[idv].len_wrt = 0;
2122 }
2123 val->nderiv = masstranInstance->Ixx.nderiv;
2124
2125 /* set derivatives */
2126 for (idv = 0; idv < masstranInstance->Ixx.nderiv; idv++) {
2127
2128 AIM_STRDUP(val->derivs[idv].name, masstranInstance->Ixx.derivs[idv].name, aimInfo, status){ if (val->derivs[idv].name != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2128, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "val->derivs[idv].name"); goto cleanup; } val->derivs
[idv].name = EG_strdup(masstranInstance->Ixx.derivs[idv].name
); if (val->derivs[idv].name == __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2128, __func__, 2, "AIM_STRDUP: %s %s"
, "val->derivs[idv].name", masstranInstance->Ixx.derivs
[idv].name); goto cleanup; } }
;
2129
2130 val->derivs[idv].len_wrt = masstranInstance->Ixx.derivs[idv].len_wrt;
2131
2132 len_wrt = val->derivs[idv].len_wrt;
2133 AIM_ALLOC(val->derivs[idv].deriv, val->length*len_wrt, double, aimInfo, status){ if (val->derivs[idv].deriv != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2133, __func__, 1, "AIM_ALLOC: %s != NULL"
, "val->derivs[idv].deriv"); goto cleanup; } size_t memorysize
= val->length*len_wrt; val->derivs[idv].deriv = (double
*) EG_alloc(memorysize*sizeof(double)); if (val->derivs[idv
].deriv == __null) { status = -4; aim_status(aimInfo, status,
"masstranAIM.cpp", 2133, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "val->derivs[idv].deriv", memorysize, "double"); goto cleanup
; } }
;
2134 for (j = 0; j < len_wrt; j++) {
2135 val->derivs[idv].deriv[0*len_wrt + j] = masstranInstance->Ixx.derivs[idv].deriv[j];
2136 val->derivs[idv].deriv[1*len_wrt + j] = -masstranInstance->Ixy.derivs[idv].deriv[j];
2137 val->derivs[idv].deriv[2*len_wrt + j] = -masstranInstance->Ixz.derivs[idv].deriv[j];
2138 val->derivs[idv].deriv[3*len_wrt + j] = -masstranInstance->Ixy.derivs[idv].deriv[j];
2139 val->derivs[idv].deriv[4*len_wrt + j] = masstranInstance->Iyy.derivs[idv].deriv[j];
2140 val->derivs[idv].deriv[5*len_wrt + j] = -masstranInstance->Iyz.derivs[idv].deriv[j];
2141 val->derivs[idv].deriv[6*len_wrt + j] = -masstranInstance->Ixz.derivs[idv].deriv[j];
2142 val->derivs[idv].deriv[7*len_wrt + j] = -masstranInstance->Iyz.derivs[idv].deriv[j];
2143 val->derivs[idv].deriv[8*len_wrt + j] = masstranInstance->Izz.derivs[idv].deriv[j];
2144 }
2145 }
2146 }
2147 } else if (index == outMassProp) {
2148
2149 mass = masstranInstance->mass.vals.real;
2150
2151 CGx = masstranInstance->CG.vals.reals[0];
2152 CGy = masstranInstance->CG.vals.reals[1];
2153 CGz = masstranInstance->CG.vals.reals[2];
2154
2155 Ixx = masstranInstance->Ixx.vals.real;
2156 Iyy = masstranInstance->Iyy.vals.real;
2157 Iyz = masstranInstance->Iyz.vals.real;
2158 Ixy = masstranInstance->Ixy.vals.real;
2159 Ixz = masstranInstance->Ixz.vals.real;
2160 Izz = masstranInstance->Izz.vals.real;
2161
2162 if (units->mass != NULL__null) {
2163
2164 snprintf(massProp, 512, "{\"mass\":[%20.14le, %s], \"CG\":[[%20.14le,%20.14le,%20.14le], %s], \"massInertia\":[[%20.14le, %20.14le, %20.14le, %20.14le, %20.14le, %20.14le], %s]}",
2165 mass, units->mass, CGx, CGy, CGz, units->length, Ixx, Iyy, Izz, Ixy, Ixz, Iyz, units->momentOfInertia);
2166
2167 } else {
2168
2169 snprintf(massProp, 512, "{\"mass\":%20.14le, \"CG\":[%20.14le,%20.14le,%20.14le], \"massInertia\":[%20.14le, %20.14le, %20.14le, %20.14le, %20.14le, %20.14le]}",
2170 mass, CGx, CGy, CGz, Ixx, Iyy, Izz, Ixy, Ixz, Iyz);
2171
2172 }
2173
2174 AIM_STRDUP(val->vals.string, massProp, aimInfo, status){ if (val->vals.string != __null) { status = -4; aim_status
(aimInfo, status, "masstranAIM.cpp", 2174, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "val->vals.string"); goto cleanup; } val->vals.string
= EG_strdup(massProp); if (val->vals.string == __null) { status
= -4; aim_status(aimInfo, status, "masstranAIM.cpp", 2174, __func__
, 2, "AIM_STRDUP: %s %s", "val->vals.string", massProp); goto
cleanup; } }
;
2175 }
2176
2177cleanup:
2178 return status;
2179}
2180
2181
2182/* aimCleanup: Free up the AIMs storage */
2183extern "C" void
2184aimCleanup(void *instStore)
2185{
2186 aimStorage *masstranInstance;
2187#ifdef DEBUG
2188 printf(" masstranAIM/aimCleanup!\n");
2189#endif
2190
2191 masstranInstance = (aimStorage *) instStore;
2192 destroy_aimStorage(masstranInstance);
2193 EG_free(masstranInstance);
2194}