File: | masstranAIM.cpp |
Warning: | line 1338, column 13 Potential leak of memory pointed to by 'feaProperty' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
118 | enum 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 | ||||
132 | enum 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 | ||||
153 | template<class T> | |||
154 | struct sensNode { | |||
155 | T xyz[3]; | |||
156 | }; | |||
157 | ||||
158 | template<class T> | |||
159 | struct 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 | ||||
176 | template<class T> | |||
177 | struct sensMaterialStruct { | |||
178 | materialTypeEnum materialType; | |||
179 | ||||
180 | int materialID; // ID number of material | |||
181 | ||||
182 | T density; // Rho - material mass density | |||
183 | }; | |||
184 | ||||
185 | template<class T> | |||
186 | struct 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 */ | |||
197 | typedef 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 | ||||
224 | static 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 | ||||
272 | cleanup: | |||
273 | return CAPS_SUCCESS0; | |||
274 | } | |||
275 | ||||
276 | ||||
277 | static 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 | ||||
327 | static 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 | ||||
453 | cleanup: | |||
454 | return status; | |||
455 | } | |||
456 | ||||
457 | ||||
458 | /****************** exposed AIM entry points -- Analysis **********************/ | |||
459 | ||||
460 | /* aimInitialize: Initialization Information for the AIM */ | |||
461 | extern "C" int | |||
462 | aimInitialize(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 | ||||
592 | cleanup: | |||
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 */ | |||
602 | extern "C" int | |||
603 | aimInputs(/*@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 | ||||
758 | cleanup: | |||
759 | if (status != CAPS_SUCCESS0) AIM_FREE(*ainame){ EG_free(*ainame); *ainame = __null; }; | |||
760 | return status; | |||
761 | } | |||
762 | ||||
763 | ||||
764 | // ********************** AIM Function Break ***************************** | |||
765 | extern "C" int | |||
766 | aimUpdateState(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; | |||
975 | cleanup: | |||
976 | ||||
977 | return status; | |||
978 | } | |||
979 | ||||
980 | ||||
981 | // ********************** AIM Function Break ***************************** | |||
982 | template<class T, class NodeType> | |||
983 | int | |||
984 | calcMassProps(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 | ||||
1233 | cleanup: | |||
1234 | return status; | |||
1235 | } | |||
1236 | ||||
1237 | // ********************** AIM Function Break ***************************** | |||
1238 | template<class T> | |||
1239 | void 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 ***************************** | |||
1252 | template<class T> | |||
1253 | int 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]; | |||
1266 | ||||
1267 | for (i = 0; i < masstranInstance->feaProblem.numProperty; i++) { | |||
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++) { | |||
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++) { | |||
1292 | ||||
1293 | designRelation = &masstranInstance->feaProblem.feaDesignVariableRelation[idr]; | |||
1294 | ||||
1295 | for (ip = 0; ip < designRelation->numPropertyID; ip++) { | |||
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++) { | |||
1333 | for (j = 0; j < masstranInstance->feaProblem.numMaterial; j++) { | |||
1334 | if (designRelation->materialSetID[im] == feaMaterial[j].materialID) { | |||
1335 | if (strncasecmp(designRelation->fieldName, "density", 7) == 0) { | |||
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); }; | |||
| ||||
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 | ||||
1351 | cleanup: | |||
1352 | return status; | |||
1353 | } | |||
1354 | ||||
1355 | // ********************** AIM Function Break ***************************** | |||
1356 | extern "C" int | |||
1357 | aimPreAnalysis(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; } }; | |||
| ||||
1375 | ||||
1376 | status = getComponents(aimInfo, masstranInstance, &feaProperty, &feaMaterial); | |||
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 | ||||
1427 | cleanup: | |||
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 ***************************** | |||
1440 | extern "C" int | |||
1441 | aimExecute(/*@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 ***************************** | |||
1450 | extern "C" int | |||
1451 | aimPostAnalysis( 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; | |||
1722 | cleanup: | |||
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 ***************************** | |||
1738 | extern "C" int | |||
1739 | aimOutputs( 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 | ||||
1886 | cleanup: | |||
1887 | AIM_FREE(tmpUnits){ EG_free(tmpUnits); tmpUnits = __null; }; | |||
1888 | ||||
1889 | return status; | |||
1890 | } | |||
1891 | ||||
1892 | ||||
1893 | /* aimCalcOutput: Calculate/Retrieve Output Information */ | |||
1894 | extern "C" int | |||
1895 | aimCalcOutput(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 | ||||
2177 | cleanup: | |||
2178 | return status; | |||
2179 | } | |||
2180 | ||||
2181 | ||||
2182 | /* aimCleanup: Free up the AIMs storage */ | |||
2183 | extern "C" void | |||
2184 | aimCleanup(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 | } |