Bug Summary

File:feaUtils.c
Warning:line 526, column 10
Value stored to 'refLen' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name feaUtils.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D REVISION=7.7 -I ../include -I /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/ESP/LINUX64/include -I . -D HAVE_PYTHON -I . -I /home/jenkins/util/ESP/Python/ESP_Python-3.9.13/include/python3.9 -I /home/jenkins/util/ESP/Python/ESP_Python-3.9.13/include/python3.9 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-dangling-else -Wno-parentheses -Wno-unused-result -Wno-format-truncation -fdebug-compilation-dir /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/CAPS/aim/utils -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/scanCAPS/2023-09-16-120425-80890-1 -x c feaUtils.c
1// This software has been cleared for public release on 05 Nov 2020, case number 88ABW-2020-3462.
2
3#include <string.h>
4#include <math.h>
5
6#include "aimUtil.h" // Bring in AIM utility functions
7
8#include "miscUtils.h" // Bring in misc. utility functions
9#include "meshUtils.h" // Bring in mesh utility functions
10#include "vlmUtils.h" // Bring in vortex lattice method utility functions
11
12#include "arrayUtils.h" // Bring in array utility functions
13
14#include "feaTypes.h" // Bring in FEA structures
15#include "meshTypes.h" // Bring in mesh structures
16#include "capsTypes.h" // Bring in CAPS types
17
18#include "feaUtils.h"
19#include "jsonUtils.h"
20
21#ifdef WIN32
22#define strcasecmp stricmp
23#endif
24
25//#define MIN(A,B) (((A) < (B)) ? (A) : (B))
26#define MAX(A,B)(((A) < (B)) ? (B) : (A)) (((A) < (B)) ? (B) : (A))
27
28
29
30int fea_createMesh(void *aimInfo,
31 /*@null@*/ double paramTess[3], // (in) Tessellation parameters
32 int edgePointMin, // (in) minimum points along any Edge
33 int edgePointMax, // (in) maximum points along any Edge
34 int quadMesh, // (in) only do tris-for faces
35 mapAttrToIndexStruct *groupMap, // (in) map from CAPSGroup names to indexes
36 mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes
37 mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes
38 mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes
39 mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes
40 mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes
41 /*@null@*/ mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes
42 int *numMesh, // (out) total number of FEA mesh structures
43 meshStruct **feaMesh, // (out) FEA mesh structure
44 feaProblemStruct *feaProblem ) { // (out) FEA problem structure
45
46 int status; // Function return status
47
48 int i, body; // Indexing
49
50 // Bodies
51 const char *intents;
52 int numBody; // Number of Bodies
53 ego *bodies;
54 const char *discipline;
55 int stat, nGlobal;
56
57 // Coordinate system
58 mapAttrToIndexStruct coordSystemMap, attrMapTemp1, attrMapTemp2, meshMap;
59
60 int meshInd;
61 capsValue *meshVal, *meshMorphVal;
62
63 meshStruct *feaMeshes = NULL((void*)0), tempMesh;
64 int *feaMeshList = NULL((void*)0); // List to seperate structural meshes for aero
65
66 ego tempBody;
67 double capsMeshLength = 0, bbox[6], refLen;
68
69 // Inherited fea/volume mesh related variables
70 int numFEAMesh = 0;
71 int feaMeshInherited = (int) false0;
72
73 // Destroy feaMeshes
74 if ((*feaMesh) != NULL((void*)0)) {
75
76 for (i = 0; i < *numMesh; i++) {
77 status = destroy_meshStruct(&(*feaMesh)[i]);
78 if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_meshStruct!\n", status);
79 }
80
81 AIM_FREE(*feaMesh){ EG_free(*feaMesh); *feaMesh = ((void*)0); };
82 }
83
84 (*feaMesh) = NULL((void*)0);
85 *numMesh = 0;
86
87 // Get AIM bodies
88 status = aim_getBodies(aimInfo, &intents, &numBody, &bodies);
89 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 89
, __func__, 0); goto cleanup; }
;
90
91 if ((numBody <= 0) || (bodies == NULL((void*)0))) {
92 AIM_ERROR(aimInfo, "No Bodies!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 92, __func__
, "No Bodies!\n"); }
;
93 return CAPS_SOURCEERR-330;
94 }
95
96 initiate_meshStruct(&tempMesh);
97
98 // Initiate our maps
99 status = initiate_mapAttrToIndexStruct(&coordSystemMap);
100 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 100
, __func__, 0); goto cleanup; }
;
101
102 status = initiate_mapAttrToIndexStruct(&attrMapTemp1);
103 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 103
, __func__, 0); goto cleanup; }
;
104
105 status = initiate_mapAttrToIndexStruct(&attrMapTemp2);
106 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 106
, __func__, 0); goto cleanup; }
;
107
108 status = initiate_mapAttrToIndexStruct(&meshMap);
109 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 109
, __func__, 0); goto cleanup; }
;
110
111 // Alloc feaMesh list
112 AIM_ALLOC(feaMeshList, numBody, int, aimInfo ,status){ if (feaMeshList != ((void*)0)) { status = -4; aim_status(aimInfo
, status, "feaUtils.c", 112, __func__, 1, "AIM_ALLOC: %s != NULL"
, "feaMeshList"); goto cleanup; } size_t memorysize = numBody
; feaMeshList = (int *) EG_alloc(memorysize*sizeof(int)); if (
feaMeshList == ((void*)0)) { status = -4; aim_status(aimInfo,
status, "feaUtils.c", 112, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "feaMeshList", memorysize, "int"); goto cleanup; } }
;
113
114 // Set all indexes to true
115 for (i = 0; i < numBody; i++ ) feaMeshList[i] = (int) true1;
116
117 // Check for capsDiscipline consistency
118 i = 0;
119 for (body = 0; body < numBody; body++) {
120
121 status = retrieve_CAPSDisciplineAttr(bodies[body], &discipline);
122 if (status != CAPS_SUCCESS0) continue; // Need to add an error code
123
124 if (strcasecmp(discipline, "structure") != 0) {
125 feaMeshList[body] = (int) false0;
126 i++;
127 }
128 }
129
130 if (i == numBody) {
131 AIM_ERROR(aimInfo, "No bodies with capsDiscipline Structure!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 131, __func__
, "No bodies with capsDiscipline Structure!"); }
;
132 status = CAPS_BADVALUE-311;
133 goto cleanup;
134 }
135
136 //for (body = 0; body< numBody; body++) printf("Body %i, FeaMeshList = %i\n", body, feaMeshList[body]);
137
138 // Get CoordSystem attribute to index mapping
139 status = create_CoordSystemAttrToIndexMap(numBody,
140 bodies,
141 3, //>2 - search the body, faces, edges, and all the nodes
142 &coordSystemMap);
143 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 143
, __func__, 0); goto cleanup; }
;
144
145 status = fea_getCoordSystem(numBody,
146 bodies,
147 coordSystemMap,
148 &feaProblem->numCoordSystem,
149 &feaProblem->feaCoordSystem);
150 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 150
, __func__, 0); goto cleanup; }
;
151
152 // Get capsConstraint name and index mapping
153 status = create_CAPSConstraintAttrToIndexMap(numBody,
154 bodies,
155 3, //>2 - search the body, faces, edges, and all the nodes
156 constraintMap);
157 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 157
, __func__, 0); goto cleanup; }
;
158
159 // Get capsLoad name and index mapping
160 status = create_CAPSLoadAttrToIndexMap(numBody,
161 bodies,
162 3, //>2 - search the body, faces, edges, and all the nodes
163 loadMap);
164 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 164
, __func__, 0); goto cleanup; }
;
165
166 // Get transfer to index mapping
167 status = create_CAPSBoundAttrToIndexMap(numBody,
168 bodies,
169 3, //>2 - search the body, faces, edges, and all the nodes
170 transferMap);
171 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 171
, __func__, 0); goto cleanup; }
;
172
173 if (connectMap != NULL((void*)0)) {
174 // Get connect to index mapping
175 status = create_CAPSConnectAttrToIndexMap(numBody,
176 bodies,
177 3, //>2 - search the body, faces, edges, and all the nodes
178 connectMap);
179 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 179
, __func__, 0); goto cleanup; }
;
180 }
181
182 if (responseMap != NULL((void*)0)) {
183 // Get response to index mapping
184 status = create_CAPSResponseAttrToIndexMap(numBody,
185 bodies,
186 3, //>2 - search the body, faces, edges, and all the nodes
187 responseMap);
188 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 188
, __func__, 0); goto cleanup; }
;
189 }
190
191 if (referenceMap != NULL((void*)0)) {
192 // Get response to index mapping
193 status = create_CAPSReferenceAttrToIndexMap(numBody,
194 bodies,
195 3, //>2 - search the body, faces, edges, and all the nodes
196 referenceMap);
197 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 197
, __func__, 0); goto cleanup; }
;
198 }
199
200 // Get capsGroup name and index mapping to make sure all faces have a capsGroup value
201 status = create_CAPSGroupAttrToIndexMap(numBody,
202 bodies,
203 3, //>2 - search the body, faces, edges, and all the nodes
204 groupMap);
205 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 205
, __func__, 0); goto cleanup; }
;
206
207 // Get the Mesh input Value
208 meshInd = aim_getIndex(aimInfo, "Mesh", ANALYSISIN);
209 if (meshInd < 1)
210 meshInd = aim_getIndex(aimInfo, "Surface_Mesh", ANALYSISIN);
211 if (meshInd < 1) {
212 AIM_ERROR(aimInfo, "Developer error: No 'Mesh' or 'Surface_Mesh' ANALYSISIN Index!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 212, __func__
, "Developer error: No 'Mesh' or 'Surface_Mesh' ANALYSISIN Index!"
); }
;
213 status = CAPS_BADINDEX-304;
214 goto cleanup;
215 }
216
217 status = aim_getValue(aimInfo, meshInd, ANALYSISIN, &meshVal);
218 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 218
, __func__, 0); goto cleanup; }
;
219
220 if (meshVal->type != PointerMesh) {
221 AIM_ERROR(aimInfo, "Developer error! Mesh is not a PointerMesh!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 221, __func__
, "Developer error! Mesh is not a PointerMesh!"); }
;
222 status = CAPS_NOTIMPLEMENT-334;
223 goto cleanup;
224 }
225
226 // Get the Mesh_Morph input Value
227 meshInd = aim_getIndex(aimInfo, "Mesh_Morph", ANALYSISIN);
228 if (meshInd < 1) {
229 AIM_ERROR(aimInfo, "Developer error: No 'Mesh_Morph' ANALYSISIN Index!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 229, __func__
, "Developer error: No 'Mesh_Morph' ANALYSISIN Index!"); }
;
230 status = CAPS_BADINDEX-304;
231 goto cleanup;
232 }
233
234 status = aim_getValue(aimInfo, meshInd, ANALYSISIN, &meshMorphVal);
235 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 235
, __func__, 0); goto cleanup; }
;
236
237
238 feaMeshInherited = (int) false0;
239
240 if ((meshVal->nullVal == NotNull) ||
241 (meshMorphVal->vals.integer == (int) true1 &&
242 meshVal->nullVal == IsNull)) {
243
244 if ( meshMorphVal->vals.integer == (int) true1 &&
245 meshVal->nullVal == IsNull ) { // If we are mighty morphing
246
247 if (aim_newGeometry(aimInfo) == CAPS_SUCCESS0 ||
248 feaProblem->meshRefIn == NULL((void*)0) ||
249 feaProblem->meshRefIn != &feaProblem->meshRefObj) {
250
251 // Lets "load" the meshRef now since it's not linked
252 status = aim_loadMeshRef(aimInfo, &feaProblem->meshRefObj);
253 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 253
, __func__, 0); goto cleanup; }
;
254
255 // Mighty Morph the mesh
256 status = aim_morphMeshUpdate(aimInfo, &feaProblem->meshRefObj, numBody, bodies);
257 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 257
, __func__, 0); goto cleanup; }
;
258 }
259 /*@-immediatetrans@*/
260 feaProblem->meshRefIn = &feaProblem->meshRefObj;
261 /*@+immediatetrans@*/
262 } else {
263 feaProblem->meshRefIn = (aimMeshRef *) meshVal->vals.AIMptr;
264 }
265
266 numFEAMesh = feaProblem->meshRefIn->nmap;
267
268 // See if a FEA mesh is available from parent
269 if (feaProblem->meshRefIn->type == aimAreaMesh ||
270 feaProblem->meshRefIn->type == aimSurfaceMesh) {
271
272 if (numFEAMesh != numBody) { // May not be an error if we are doing aero-struct
273
274 // Check for capsDiscipline consistency
275 for (body = 0; body < numFEAMesh; body++) {
276 // Dummy arguments
277 status = EG_statusTessBody(feaProblem->meshRefIn->maps[body].tess, &tempBody, &stat, &nGlobal);
278 if (status != EGADS_SUCCESS0) goto cleanup;
279
280 status = retrieve_CAPSDisciplineAttr(tempBody, &discipline);
281 if (status != EGADS_SUCCESS0) {
282 AIM_ERROR (aimInfo, "Failed to find a capsDiscipline attribute!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 282, __func__
, "Failed to find a capsDiscipline attribute!\n"); }
;
283 AIM_ADDLINE(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n"){ aim_addLine(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n"
); }
;
284 status= CAPS_SOURCEERR-330;
285 goto cleanup;
286 }
287
288 if (strcasecmp(discipline, "structure") != 0) {
289 AIM_ERROR (aimInfo, "Failed to find a capsDiscipline attribute - 'structure'!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 289, __func__
, "Failed to find a capsDiscipline attribute - 'structure'!\n"
); }
;
290 AIM_ADDLINE(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n"){ aim_addLine(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n"
); }
;
291 status= CAPS_SOURCEERR-330;
292 goto cleanup;
293 }
294
295 // need a check to make sure all tempMesh->groupMap are identical
296 }
297
298 // We need to update our capsGroup attribute map
299
300 // Get capsGroup name and index mapping to make sure all faces have a capsGroup value
301 status = create_CAPSGroupAttrToIndexMap(numBody,
302 bodies,
303 3, //>2 - search the body, faces, edges, and all the nodes
304 &attrMapTemp2);
305 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 305
, __func__, 0); goto cleanup; }
;
306
307 // Get attribute to index mapping
308 status = create_MeshRefToIndexMap(aimInfo, feaProblem->meshRefIn, &attrMapTemp1);
309 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 309
, __func__, 0); goto cleanup; }
;
310
311 status = merge_mapAttrToIndexStruct(&attrMapTemp1, &attrMapTemp2, groupMap);
312 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 312
, __func__, 0); goto cleanup; }
;
313 }
314
315 AIM_ALLOC(feaMeshes, numFEAMesh, meshStruct, aimInfo, status){ if (feaMeshes != ((void*)0)) { status = -4; aim_status(aimInfo
, status, "feaUtils.c", 315, __func__, 1, "AIM_ALLOC: %s != NULL"
, "feaMeshes"); goto cleanup; } size_t memorysize = numFEAMesh
; feaMeshes = (meshStruct *) EG_alloc(memorysize*sizeof(meshStruct
)); if (feaMeshes == ((void*)0)) { status = -4; aim_status(aimInfo
, status, "feaUtils.c", 315, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "feaMeshes", memorysize, "meshStruct"); goto cleanup; } }
;
316 for (body = 0; body < numFEAMesh; body++) (void) initiate_meshStruct(&feaMeshes[body]);
317
318 for (body = 0; body < numFEAMesh; body++) {
319
320 status = copy_mapAttrToIndexStruct( groupMap,
321 &tempMesh.groupMap );
322 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 322
, __func__, 0); goto cleanup; }
;
323
324 tempMesh.egadsTess = feaProblem->meshRefIn->maps[body].tess;
325 status = mesh_surfaceMeshEGADSTess(aimInfo, &tempMesh, (int)(feaProblem->meshRefIn->type == aimAreaMesh));
326 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 326
, __func__, 0); goto cleanup; }
;
327
328 // Create a new mesh with topology tagged with capsIgnore being removed, if capsIgnore isn't found the mesh is simply copied.
329 status = mesh_createIgnoreMesh(&tempMesh, &feaMeshes[body]);
330 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 330
, __func__, 0); goto cleanup; }
;
331
332 destroy_meshStruct(&tempMesh);
333
334 // Change the analysis type of the mesh
335 status = mesh_setAnalysisType(MeshStructure, &feaMeshes[body]);
336 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 336
, __func__, 0); goto cleanup; }
;
337
338
339 // Get FEA Problem from EGADs body
340 status = fea_setAnalysisData(aimInfo,
341 groupMap,
342 &coordSystemMap,
343 constraintMap,
344 loadMap,
345 transferMap,
346 connectMap,
347 responseMap,
348 referenceMap,
349 &feaMeshes[body]);
350 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 350
, __func__, 0); goto cleanup; }
;
351
352 status = mesh_fillQuickRefList( &feaMeshes[body]);
353 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 353
, __func__, 0); goto cleanup; }
;
354
355 printf("\tMesh for body = %d\n", body);
356 printf("\tNumber of nodal coordinates = %d\n", feaMeshes[body].numNode);
357 printf("\tNumber of elements = %d\n", feaMeshes[body].numElement);
358 printf("\tElemental Nodes = %d\n", feaMeshes[body].meshQuickRef.numNode);
359 printf("\tElemental Rods = %d\n", feaMeshes[body].meshQuickRef.numLine);
360 printf("\tElemental Tria3 = %d\n", feaMeshes[body].meshQuickRef.numTriangle);
361 printf("\tElemental Quad4 = %d\n", feaMeshes[body].meshQuickRef.numQuadrilateral);
362 }
363
364
365 if (numFEAMesh > 1) {
366 printf("Combining multiple FEA meshes!\n");
367 }
368
369 status = mesh_combineMeshStruct(numFEAMesh,
370 feaMeshes,
371 &feaProblem->feaMesh);
372 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 372
, __func__, 0); goto cleanup; }
;
373
374 if (numFEAMesh > 1) {
375 printf("\tCombined Number of nodal coordinates = %d\n", feaProblem->feaMesh.numNode);
376 printf("\tCombined Number of elements = %d\n", feaProblem->feaMesh.numElement);
377 printf("\tCombined Elemental Nodes = %d\n", feaProblem->feaMesh.meshQuickRef.numNode);
378 printf("\tCombined Elemental Rods = %d\n", feaProblem->feaMesh.meshQuickRef.numLine);
379 printf("\tCombined Elemental Tria3 = %d\n", feaProblem->feaMesh.meshQuickRef.numTriangle);
380 printf("\tCombined Elemental Quad4 = %d\n", feaProblem->feaMesh.meshQuickRef.numQuadrilateral);
381 }
382
383 // Set output meshes
384 *numMesh = numFEAMesh;
385 *feaMesh = feaMeshes;
386 feaMeshes = NULL((void*)0);
387
388 // Set reference meshes
389 feaProblem->feaMesh.numReferenceMesh = *numMesh;
390 feaProblem->feaMesh.referenceMesh = (meshStruct *) EG_alloc(*numMesh*sizeof(meshStruct));
391 if (feaProblem->feaMesh.referenceMesh == NULL((void*)0)) {
392 status = EGADS_MALLOC-4;
393 goto cleanup;
394 }
395
396 for (body = 0; body < *numMesh; body++) {
397 feaProblem->feaMesh.referenceMesh[body] = (*feaMesh)[body];
398 }
399
400 } else { // Check to see if a general unstructured volume mesh is available
401
402 printf("Found link for a volume mesh (Volume_Mesh) from parent\n");
403
404 numFEAMesh = 1;
405 if (numFEAMesh != 1) {
406 AIM_ERROR(aimInfo, "Can not accept multiple volume meshes"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 406, __func__
, "Can not accept multiple volume meshes"); }
;
407 status = CAPS_BADVALUE-311;
408 goto cleanup;
409 }
410
411 if (numFEAMesh != numBody) {
412 printf("Number of inherited volume meshes does not match the number of bodies - assuming volume mesh is already combined\n");
413 }
414
415 AIM_ERROR(aimInfo, "Volume meshes not yet supported for structural analysis"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 415, __func__
, "Volume meshes not yet supported for structural analysis");
}
;
416 status = CAPS_BADVALUE-311;
417 goto cleanup;
418
419#if 0
420 tempMesh = (meshStruct *) meshVal->vals.AIMptr;
421 status = mesh_copyMeshStruct( tempMesh, &feaProblem->feaMesh);
422 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 422
, __func__, 0); goto cleanup; }
;
423
424 //feaProblem->feaMesh.egadsTess =
425 status = mesh_surfaceMeshEGADSTess(aimInfo, &feaProblem->feaMesh.egadsTess, (int)false0);
426 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 426
, __func__, 0); goto cleanup; }
;
427
428
429 // Set reference meshes
430 feaProblem->feaMesh.numReferenceMesh = tempMesh->numReferenceMesh;
431 feaProblem->feaMesh.referenceMesh = (meshStruct *) EG_alloc(tempMesh->numReferenceMesh*sizeof(meshStruct));
432 if (feaProblem->feaMesh.referenceMesh == NULL((void*)0)) {
433 status = EGADS_MALLOC-4;
434 goto cleanup;
435 }
436
437 for (body = 0; body < tempMesh->numReferenceMesh; body++) {
438 feaProblem->feaMesh.referenceMesh[body] = tempMesh->referenceMesh[body];
439 }
440
441 for (i = 0; i < feaProblem->feaMesh.numReferenceMesh; i++) {
442
443 status = aim_newTess(aimInfo,
444 feaProblem->feaMesh.referenceMesh[i].egadsTess);
445 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 445
, __func__, 0); goto cleanup; }
;
446 }
447
448 // Update/change the analysis data in a meshStruct
449 status = change_meshAnalysis(&feaProblem->feaMesh, MeshStructure);
450 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 450
, __func__, 0); goto cleanup; }
;
451
452 // Get FEA Problem from EGADs body
453 status = fea_setAnalysisData(aimInfo,
454 groupMap,
455 &coordSystemMap,
456 constraintMap,
457 loadMap,
458 transferMap,
459 connectMap,
460 responseMap,
461 referenceMap,
462 &feaProblem->feaMesh);
463 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 463
, __func__, 0); goto cleanup; }
;
464#endif
465 }
466
467 feaMeshInherited = (int) true1;
468 }
469
470 // If we didn't inherit a FEA mesh we need to get one ourselves
471 if (feaMeshInherited == (int) false0) {
472
473 status = check_CAPSMeshLength(numBody, bodies, &capsMeshLength);
474
475 if (status == CAPS_NOTFOUND-303) capsMeshLength = -1;
476 else AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 476
, __func__, 0); goto cleanup; }
;
477
478 /*
479 if (capsMeshLength <= 0 || status != CAPS_SUCCESS) {
480 printf("**********************************************************\n");
481 if (status != CAPS_SUCCESS)
482 printf("capsMeshLength is not set on any body.\n");
483 else
484 printf("capsMeshLength: %f\n", capsMeshLength);
485 printf("\n");
486 printf("The capsMeshLength attribute must\n"
487 "present on at least one body.\n"
488 "\n"
489 "capsMeshLength should be a a positive value representative\n"
490 "of a characteristic length of the geometry,\n"
491 "e.g. the MAC of a wing or diameter of a fuselage.\n");
492 printf("**********************************************************\n");
493 status = CAPS_BADVALUE;
494 goto cleanup;
495 }*/
496
497 if (paramTess == NULL((void*)0)) {
498 AIM_ERROR(aimInfo, "Developer error paramTess == NULL"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 498, __func__
, "Developer error paramTess == NULL"); }
;
499 status = CAPS_BADVALUE-311;
500 goto cleanup;
501 }
502
503 if (edgePointMin < 2) {
504 printf("The minimum number of allowable edge points is 2 not %d\n", edgePointMin);
505 edgePointMin = 2;
506 }
507
508 if (edgePointMax < edgePointMin) {
509 printf("The maximum number of edge points must be greater than the current minimum (%d)\n", edgePointMin);
510 edgePointMax = edgePointMin+1;
511 }
512
513 if (capsMeshLength <= 0) {
514 refLen = 0;
515 for (body = 0; body < numBody; body++) {
516 if (feaMeshList[body] != (int) true1) continue;
517
518 status = EG_getBoundingBox(bodies[body], bbox);
519 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 519
, __func__, 0); goto cleanup; }
;
520
521 refLen = MAX(refLen, sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[0])(((refLen) < (sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[
0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox
[2]) * (bbox[5] - bbox[2])))) ? (sqrt( (bbox[3] - bbox[0]) * (
bbox[3] - bbox[0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])
+(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]))) : (refLen))
522 +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])(((refLen) < (sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[
0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox
[2]) * (bbox[5] - bbox[2])))) ? (sqrt( (bbox[3] - bbox[0]) * (
bbox[3] - bbox[0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])
+(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]))) : (refLen))
523 +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2])))(((refLen) < (sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[
0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox
[2]) * (bbox[5] - bbox[2])))) ? (sqrt( (bbox[3] - bbox[0]) * (
bbox[3] - bbox[0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])
+(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]))) : (refLen))
;
524 }
525 } else {
526 refLen = capsMeshLength;
Value stored to 'refLen' is never read
527 }
528
529 // Modify the EGADS body tessellation based on given inputs
530 /*@-nullpass@*/
531 status = mesh_modifyBodyTess(0,
532 NULL((void*)0),
533 edgePointMin,
534 edgePointMax,
535 quadMesh,
536 &capsMeshLength,
537 paramTess,
538 meshMap,
539 numBody,
540 bodies);
541 /*@+nullpass@*/
542 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 542
, __func__, 0); goto cleanup; }
;
543
544 for (body = 0; body < numBody; body++) {
545 if (feaMeshList[body] != (int) true1) continue;
546
547 if (capsMeshLength > 0) {
548 refLen = capsMeshLength;
549 } else {
550 status = EG_getBoundingBox(bodies[body], bbox);
551 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 551
, __func__, 0); goto cleanup; }
;
552
553 refLen = sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[0])
554 +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])
555 +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]));
556 }
557
558 status = copy_mapAttrToIndexStruct( groupMap,
559 &tempMesh.groupMap );
560 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 560
, __func__, 0); goto cleanup; }
;
561
562 status = mesh_surfaceMeshEGADSBody(aimInfo,
563 bodies[body],
564 refLen,
565 paramTess,
566 quadMesh,
567 &tempMesh.egadsTess);
568 AIM_STATUS(aimInfo, status, "Problem during surface meshing of body %d", body+1)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 568
, __func__, 2, "Problem during surface meshing of body %d", body
+1); goto cleanup; }
;
569 AIM_NOTNULL(tempMesh.egadsTess, aimInfo, status){ if (tempMesh.egadsTess == ((void*)0)) { status = -307; aim_status
(aimInfo, status, "feaUtils.c", 569, __func__, 1, "%s == NULL!"
, "tempMesh.egadsTess"); goto cleanup; } }
;
570
571 status = mesh_surfaceMeshEGADSTess(aimInfo, &tempMesh, (int)false0);
572 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 572
, __func__, 0); goto cleanup; }
;
573
574 *numMesh += 1;
575 AIM_REALL(*feaMesh, *numMesh, meshStruct, aimInfo, status){ size_t memorysize = *numMesh; *feaMesh = (meshStruct *) EG_reall
(*feaMesh, memorysize*sizeof(meshStruct)); if (*feaMesh == ((
void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 575, __func__, 3, "AIM_REALL: %s size %zu type %s", "*feaMesh"
, memorysize, "meshStruct"); goto cleanup; } }
;
576
577 status = initiate_meshStruct(&(*feaMesh)[*numMesh-1]);
578 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 578
, __func__, 0); goto cleanup; }
;
579
580 // Create a new mesh with topology tagged with capsIgnore being removed, if capsIgnore isn't found the mesh is simply copied.
581 status = mesh_createIgnoreMesh(&tempMesh, &(*feaMesh)[*numMesh-1]);
582 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 582
, __func__, 0); goto cleanup; }
;
583
584 destroy_meshStruct(&tempMesh);
585
586 // Change the analysis type of the mesh
587 status = mesh_setAnalysisType(MeshStructure, &(*feaMesh)[*numMesh-1]);
588 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 588
, __func__, 0); goto cleanup; }
;
589
590 // Get FEA Problem from EGADs body
591 status = fea_setAnalysisData(aimInfo,
592 groupMap,
593 &coordSystemMap,
594 constraintMap,
595 loadMap,
596 transferMap,
597 connectMap,
598 responseMap,
599 referenceMap,
600 &(*feaMesh)[*numMesh-1]);
601 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 601
, __func__, 0); goto cleanup; }
;
602
603 status = mesh_fillQuickRefList( &(*feaMesh)[*numMesh-1]);
604 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 604
, __func__, 0); goto cleanup; }
;
605
606
607#if 0
608 // Get FEA Problem from EGADs body
609 status = fea_bodyToBEM(aimInfo,
610 bodies[body], // (in) EGADS Body
611 paramTess, // (in) Tessellation parameters
612 edgePointMin, // (in) minimum points along any Edge
613 edgePointMax, // (in) maximum points along any Edge
614 quadMesh,
615 groupMap,
616 &coordSystemMap,
617 constraintMap,
618 loadMap,
619 transferMap,
620 connectMap,
621 responseMap,
622 referenceMap,
623 &(*feaMesh)[*numMesh-1]);
624#endif
625 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 625
, __func__, 0); goto cleanup; }
;
626 printf("\tMesh for body = %d\n", body);
627 printf("\tNumber of nodal coordinates = %d\n", (*feaMesh)[*numMesh-1].numNode);
628 printf("\tNumber of elements = %d\n", (*feaMesh)[*numMesh-1].numElement);
629 printf("\tElemental Nodes = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numNode);
630 printf("\tElemental Rods = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numLine);
631 printf("\tElemental Tria3 = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numTriangle);
632 printf("\tElemental Quad4 = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numQuadrilateral);
633
634 // set the resulting tessellation
635 status = aim_newTess(aimInfo, (*feaMesh)[*numMesh-1].egadsTess);
636 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 636
, __func__, 0); goto cleanup; }
;
637 }
638
639 // Only compbine if there are actual meshes
640 if (*numMesh > 0) {
641 if (*numMesh > 1) printf("Combining multiple FEA meshes!\n");
642 AIM_NOTNULL((*feaMesh), aimInfo, status){ if ((*feaMesh) == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 642, __func__, 1, "%s == NULL!", "(*feaMesh)"
); goto cleanup; } }
;
643
644 // Combine fea meshes into a single mesh for the problem
645 status = mesh_combineMeshStruct(*numMesh,
646 (*feaMesh),
647 &feaProblem->feaMesh);
648 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 648
, __func__, 0); goto cleanup; }
;
649
650 if (*numMesh > 1) {
651 printf("\tCombined Number of nodal coordinates = %d\n", feaProblem->feaMesh.numNode);
652 printf("\tCombined Number of elements = %d\n", feaProblem->feaMesh.numElement);
653 printf("\tCombined Elemental Nodes = %d\n", feaProblem->feaMesh.meshQuickRef.numNode);
654 printf("\tCombined Elemental Rods = %d\n", feaProblem->feaMesh.meshQuickRef.numLine);
655 printf("\tCombined Elemental Tria3 = %d\n", feaProblem->feaMesh.meshQuickRef.numTriangle);
656 printf("\tCombined Elemental Quad4 = %d\n", feaProblem->feaMesh.meshQuickRef.numQuadrilateral);
657 }
658
659 // Set reference meshes
660 feaProblem->feaMesh.numReferenceMesh = *numMesh;
661 feaProblem->feaMesh.referenceMesh = (meshStruct *) EG_alloc(*numMesh*sizeof(meshStruct));
662 if (feaProblem->feaMesh.referenceMesh == NULL((void*)0)) {
663 status = EGADS_MALLOC-4;
664 goto cleanup;
665 }
666
667 for (body = 0; body < *numMesh; body++) {
668 feaProblem->feaMesh.referenceMesh[body] = (*feaMesh)[body];
669 }
670 }
671 }
672 status = CAPS_SUCCESS0;
673
674cleanup:
675
676 AIM_FREE(feaMeshes){ EG_free(feaMeshes); feaMeshes = ((void*)0); };
677 AIM_FREE(feaMeshList){ EG_free(feaMeshList); feaMeshList = ((void*)0); };
678
679 (void ) destroy_mapAttrToIndexStruct(&coordSystemMap);
680
681 (void ) destroy_mapAttrToIndexStruct(&attrMapTemp1);
682 (void ) destroy_mapAttrToIndexStruct(&attrMapTemp2);
683
684 return status;
685}
686
687// Convert an EGADS body to a boundary element model, modified by Ryan Durscher (AFRL)
688// from code originally written by John Dannenhoffer @ Syracuse University, patterned after code
689// written by Bob Haimes @ MIT
690int fea_bodyToBEM(void *aimInfo, // (in) AIM structure
691 ego ebody, // (in) EGADS Body
692 double paramTess[3], // (in) Tessellation parameters
693 int edgePointMin, // (in) minimum points along any Edge
694 int edgePointMax, // (in) maximum points along any Edge
695 int quadMesh, // (in) 0 - only do tris-for faces, 1 - mixed quad/tri, 2 - regularized quads
696 mapAttrToIndexStruct *attrMap, // (in) map from CAPSGroup names to indexes
697 mapAttrToIndexStruct *coordSystemMap,// (in) map from CoordSystem names to indexes
698 mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes
699 mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes
700 mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes
701 mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes
702 mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes
703 mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes
704 meshStruct *feaMesh) // (out) FEA mesh structure
705{
706 int status = 0; // Function return status
707
708 int isNodeBody;
709 int i, j, k, face, edge, patch; // Indexing
710 double scale;
711
712 // Body entities
713 int numNode = 0, numEdge = 0, numFace = 0;
714 ego *enodes=NULL((void*)0), *eedges=NULL((void*)0), *efaces=NULL((void*)0);
715
716 int atype, alen; // EGADS return variables
717 const int *ints;
718 const double *reals;
719 const char *string;
720
721 // Meshing
722 int numPoint = 0, numTri = 0;
723 const int *triConn = NULL((void*)0), *triNeighbor = NULL((void*)0); // Triangle
724
725 int numPatch = 0; // Patching
726 int n1, n2, *qints = NULL((void*)0);
727
728 int gID; // Global id
729
730 const double *xyz, *uv;
731
732 const int *ptype = NULL((void*)0), *pindex = NULL((void*)0), *pvindex = NULL((void*)0), *pbounds = NULL((void*)0);
733
734 int periodic, nchange, oclass, mtype, nchild, nchild2, *senses;
735
736 // Edge point distributions
737 int *points=NULL((void*)0), *isouth=NULL((void*)0), *ieast=NULL((void*)0), *inorth=NULL((void*)0), *iwest=NULL((void*)0);
738 double params[3], bbox[6], size, range[2], arclen, data[4], eval[18], eval2[18];
739 double *rpos=NULL((void*)0);
740 ego eref, *echilds, *echilds2, eloop, tempBody, topObj, prev, next;
741
742 int bodySubType = 0; // Body classification
743
744 int pointType, pointTopoIndex;
745 double xyzPoint[3], xyzNode[3];
746
747 // Attributues
748 const char *attrName;
749 int attrIndex, coordSystemIndex, loadIndex;
750
751 int numElement = 0; // Number of elements
752 int coordID = 0; // Default coordinate id for mesh
753
754 feaMeshDataStruct *feaData;
755
756 meshElementStruct *tempElement = NULL((void*)0);
757
758 // In case our geometry has ignores
759 int ignoreFound = (int) false0;
760
761 // ---------------------------------------------------------------
762
763 printf("Creating FEA BEM\n");
764
765 // Check for contradiction where quading is requested but dissabled on the body
766 if (quadMesh == (int)true1) {
767 status = EG_attributeRet(ebody, ".qParams", &atype, &alen, &ints, &reals, &string);
768 if (status == EGADS_SUCCESS0 && (atype != ATTRREAL2 || (atype == ATTRREAL2 && reals[0] <= 0 ))) {
769 printf("\tQuading on all faces disabled with .qParams attribute on the body\n");
770 quadMesh = (int) false0;
771 }
772 }
773
774 // Get number of Nodes, Edges, and Faces in ebody
775 status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes);
776 if (status < EGADS_SUCCESS0) goto cleanup;
777 AIM_NOTNULL(enodes, aimInfo, status){ if (enodes == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 777, __func__, 1, "%s == NULL!", "enodes"
); goto cleanup; } }
;
778
779 status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges);
780 if (status != EGADS_SUCCESS0) goto cleanup;
781
782 status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces);
783 if (status < EGADS_SUCCESS0) goto cleanup;
784
785 // What type of BODY do we have?
786 isNodeBody = aim_isNodeBody(ebody, xyzNode);
787 if (isNodeBody < EGADS_SUCCESS0) goto cleanup;
788 if (isNodeBody == EGADS_SUCCESS0) {
789 // all attributes are on the body rather than the node for a node body
790 enodes[0] = ebody;
791 }
792
793 // Determine the nominal number of points along each Edge
794 points = (int *) EG_alloc((numEdge+1) *sizeof(int ));
795 rpos = (double *) EG_alloc((edgePointMax)*sizeof(double));
796 if (points == NULL((void*)0) || rpos == NULL((void*)0)) {
797 status = EGADS_MALLOC-4;
798 printf("\tError in fea_bodyToBEM: EG_alloc\n");
799 goto cleanup;
800 }
801
802 status = EG_getBoundingBox(ebody, bbox);
803 if (status < EGADS_SUCCESS0) {
804 printf("\tError in fea_bodyToBEM: EG_getBoundingBox\n");
805 goto cleanup;
806 }
807
808 size = sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[0])
809 +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])
810 +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]));
811
812 params[0] = paramTess[0] * size;
813 params[1] = paramTess[1] * size;
814 params[2] = paramTess[2];
815
816 status = EG_attributeAdd(ebody, ".tParam", ATTRREAL2, 3, NULL((void*)0), params, NULL((void*)0));
817 if (status < EGADS_SUCCESS0) {
818 printf("\tError in fea_bodyToBEM: EG_attributeAdd\n");
819 goto cleanup;
820 }
821
822 if (isNodeBody == EGADS_SUCCESS0)
823 params[0] = 1; // does not matter but can't be zero
824
825 if (params[0] <= 0.0) {
826 printf("\tError in fea_bodyToBEM: params[0] = %f must be a positive number!\n", params[0]);
827 status = CAPS_BADVALUE-311;
828 goto cleanup;
829 }
830
831 for (i = 1; i <= numEdge; i++) {
832 status = EG_getRange(eedges[i-1], range, &periodic);
833 if (status < EGADS_SUCCESS0) {
834 printf("\tError in fea_bodyToBEM: EG_getRange\n");
835 goto cleanup;
836 }
837
838 status = EG_arcLength(eedges[i-1], range[0], range[1], &arclen);
839 if (status < EGADS_SUCCESS0) {
840 printf("\tError in fea_bodyToBEM: EG_arcLength\n");
841 goto cleanup;
842 }
843
844 //points[i] = MIN(MAX(MAX(edgePointMin,2), (int)(1+arclen/params[0])), edgePointMax);
845 points[i] = (int) min_DoubleVal(
846 max_DoubleVal(
847 max_DoubleVal( (double) edgePointMin, 2.0),
848 (double) (1+arclen/params[0])),
849 (double) edgePointMax);
850 }
851
852
853 // make arrays for "opposite" sides of four-sided Faces (with only one loop)
854 isouth = (int *) EG_alloc((numFace+1)*sizeof(int));
855 ieast = (int *) EG_alloc((numFace+1)*sizeof(int));
856 inorth = (int *) EG_alloc((numFace+1)*sizeof(int));
857 iwest = (int *) EG_alloc((numFace+1)*sizeof(int));
858
859 if (isouth == NULL((void*)0) ||
860 ieast == NULL((void*)0) ||
861 inorth == NULL((void*)0) ||
862 iwest == NULL((void*)0) ) {
863
864 status = EGADS_MALLOC-4;
865 printf("\tError in fea_bodyToBEM: EG_alloc\n");
866 goto cleanup;
867 }
868
869 for (i = 1; i <= numFace; i++) {
870 isouth[i] = 0;
871 ieast [i] = 0;
872 inorth[i] = 0;
873 iwest [i] = 0;
874
875 // nothing to check if quading isn't requested
876 if (quadMesh == (int) false0)
877 continue;
878
879 // check if quading is disabled with .qParams
880 status = EG_attributeRet(efaces[i-1], ".qParams", &atype, &alen, &ints, &reals, &string);
881 if (status == EGADS_SUCCESS0 && (atype != ATTRREAL2 || (atype == ATTRREAL2 && reals[0] <= 0 ))) {
882 printf("\tFace %d quading disabled with attribute .qParams\n", i);
883 continue;
884 }
885
886 // quading only works with one loop
887 status = EG_getTopology(efaces[i-1], &eref, &oclass, &mtype, data, &nchild, &echilds, &senses);
888 if (status < EGADS_SUCCESS0) goto cleanup;
889
890 if (nchild != 1) continue;
891
892 // quading only works if the loop has 4 edges
893 eloop = echilds[0];
894 status = EG_getTopology(eloop, &eref, &oclass, &mtype, data, &nchild, &echilds, &senses);
895 if (status < EGADS_SUCCESS0) goto cleanup;
896
897 if (nchild != 4) continue;
898
899 // Check to see if two "straight" edges next to each other are parallel - Don't Quad if so
900 for (j = 0; j < 4; j++) {
901
902 status = EG_getTopology(echilds[j], &eref, &oclass, &mtype, data, &nchild2, &echilds2, &senses);
903 if (mtype == DEGENERATE5) { status = EGADS_DEGEN-24; break; }
904 if (status < EGADS_SUCCESS0) goto cleanup;
905
906 if (j < 3) k = j+1;
907 else k = 0;
908
909 status = EG_getTopology(echilds[k], &eref, &oclass, &mtype, range, &nchild2, &echilds2, &senses);
910 if (mtype == DEGENERATE5) { status = EGADS_DEGEN-24; break; }
911 if (status < EGADS_SUCCESS0) goto cleanup;
912
913 status = EG_evaluate(echilds[j], data, eval);
914 if (status < EGADS_SUCCESS0) goto cleanup;
915
916 status = EG_evaluate(echilds[k], range, eval2);
917 if (status < EGADS_SUCCESS0) goto cleanup;
918
919 scale = dot_DoubleVal(&eval[3], &eval[3]);
920 eval[3] /= scale;
921 eval[4] /= scale;
922 eval[5] /= scale;
923
924 scale = dot_DoubleVal(&eval2[3], &eval2[3]);
925 eval2[3] /= scale;
926 eval2[4] /= scale;
927 eval2[5] /= scale;
928
929 if (fabs(fabs(dot_DoubleVal(&eval[3], &eval2[3])) - 1) < 1E-6) {
930 status = EGADS_OUTSIDE1;
931 break;
932 }
933 }
934
935 if (status == EGADS_OUTSIDE1) {
936 if (quadMesh == (int)true1) {
937 printf("Face %d has parallel edges - not quading\n", i);
938 }
939 continue;
940 }
941
942 if (status == EGADS_DEGEN-24) {
943 if (quadMesh == (int)true1) {
944 printf("Face %d has a degenerate edge - not quading\n", i);
945 }
946 continue;
947 }
948
949 isouth[i] = status = EG_indexBodyTopo(ebody, echilds[0]);
950 if (status < EGADS_SUCCESS0) goto cleanup;
951
952 ieast[i] = status = EG_indexBodyTopo(ebody, echilds[1]);
953 if (status < EGADS_SUCCESS0) goto cleanup;
954
955 inorth[i] = status = EG_indexBodyTopo(ebody, echilds[2]);
956 if (status < EGADS_SUCCESS0) goto cleanup;
957
958 iwest[i] = status = EG_indexBodyTopo(ebody, echilds[3]);
959 if (status < EGADS_SUCCESS0) goto cleanup;
960 }
961
962 // make "opposite" sides of four-sided Faces (with only one loop) match
963 nchange = 1;
964 for (i = 0; i < 20; i++) {
965 nchange = 0;
966
967 for (face = 1; face <= numFace; face++) {
968 if (isouth[face] <= 0 || ieast[face] <= 0 ||
969 inorth[face] <= 0 || iwest[face] <= 0 ) continue;
970
971 if (points[iwest[face]] < points[ieast[face]]) {
972 points[iwest[face]] = points[ieast[face]];
973 nchange++;
974
975 } else if (points[ieast[face]] < points[iwest[face]]) {
976 points[ieast[face]] = points[iwest[face]];
977 nchange++;
978 }
979
980 if (points[isouth[face]] < points[inorth[face]]) {
981 points[isouth[face]] = points[inorth[face]];
982 nchange++;
983 } else if (points[inorth[face]] < points[isouth[face]]) {
984 points[inorth[face]] = points[isouth[face]];
985 nchange++;
986 }
987 }
988 if (nchange == 0) break;
989 }
990 if (nchange > 0) {
991 printf("Exceeded number of tries making \"opposite\" sides of four-sided Faces (with only one loop) match\n");
992 status = CAPS_MISMATCH-324;
993 goto cleanup;
994 }
995
996 // mark the Edges with points[iedge] evenly-spaced points
997 for (edge = 1; edge <= numEdge; edge++) {
998 for (i = 1; i < points[edge]-1; i++) {
999 rpos[i-1] = (double)(i) / (double)(points[edge]-1);
1000 }
1001
1002 if (points[edge] == 2) {
1003 i = 0;
1004 status = EG_attributeAdd(eedges[edge-1], ".rPos", ATTRINT1, 1, &i, NULL((void*)0), NULL((void*)0));
1005 if (status < EGADS_SUCCESS0) goto cleanup;
1006
1007 } else {
1008 status = EG_attributeAdd(eedges[edge-1], ".rPos", ATTRREAL2, points[edge]-2, NULL((void*)0), rpos, NULL((void*)0));
1009 if (status < EGADS_SUCCESS0) goto cleanup;
1010 }
1011 }
1012
1013 // Make tessellation
1014 status = EG_makeTessBody(ebody, params, &feaMesh->egadsTess);
1015 if (status != EGADS_SUCCESS0) {
1016 printf("\tError in fea_bodyToBEM: EG_makeTessBody\n");
1017 goto cleanup;
1018 }
1019
1020 // Make Quads on each four-sided Face
1021 params[0] = 0;
1022 params[1] = 0;
1023 params[2] = 0;
1024
1025 // If making quads on faces lets setup an array to keep track of which faces have been quaded.
1026 if (quadMesh == (int)true1) {
1027 if( numFace > 0) {
1028 AIM_ALLOC(qints, numFace, int, aimInfo, status){ if (qints != ((void*)0)) { status = -4; aim_status(aimInfo,
status, "feaUtils.c", 1028, __func__, 1, "AIM_ALLOC: %s != NULL"
, "qints"); goto cleanup; } size_t memorysize = numFace; qints
= (int *) EG_alloc(memorysize*sizeof(int)); if (qints == ((void
*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 1028, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "qints"
, memorysize, "int"); goto cleanup; } }
;
1029 }
1030 // Set default to 0
1031 for (face = 0; face < numFace; face++) qints[face] = 0;
1032 }
1033
1034 if (quadMesh == (int)true1) {
1035 for (face = 1; face <= numFace; face++) {
1036 if (iwest[face] <= 0) continue;
1037
1038 status = EG_makeQuads(feaMesh->egadsTess, params, face);
1039 if (status < EGADS_SUCCESS0) {
1040 printf("Face = %d, failed to make quads\n", face);
1041 printf("Edges = %d %d %d %d\n", inorth[face], ieast[face], isouth[face], iwest[face]);
1042 continue;
1043 //goto cleanup;
1044 }
1045 }
1046 }
1047
1048 // Set the mesh type information
1049 feaMesh->meshType = SurfaceMesh;
1050 feaMesh->analysisType = MeshStructure;
1051
1052 // Get number of point in the tessellation
1053 status = EG_statusTessBody(feaMesh->egadsTess, &tempBody, &i, &feaMesh->numNode);
1054 if (status != EGADS_SUCCESS0) goto cleanup;
1055
1056 feaMesh->node = (meshNodeStruct *) EG_alloc(feaMesh->numNode*sizeof(meshNodeStruct));
1057 if (feaMesh->node == NULL((void*)0)) {
1058 feaMesh->numNode = 0;
1059 status = EGADS_MALLOC-4;
1060 goto cleanup;
1061 }
1062
1063 for (i = 0; i < feaMesh->numNode; i++) {
1064 status = initiate_meshNodeStruct(&feaMesh->node[i], feaMesh->analysisType);
1065 if (status != CAPS_SUCCESS0) goto cleanup;
1066 }
1067
1068 // Fill up the Attributes for the nodes
1069 for (i = 0; i < feaMesh->numNode; i++) {
1070
1071 status = EG_getGlobal(feaMesh->egadsTess, i+1, &pointType, &pointTopoIndex, xyzPoint);
1072 if (status != EGADS_SUCCESS0) goto cleanup;
1073
1074 feaMesh->node[i].xyz[0] = xyzPoint[0];
1075 feaMesh->node[i].xyz[1] = xyzPoint[1];
1076 feaMesh->node[i].xyz[2] = xyzPoint[2];
1077
1078 feaMesh->node[i].nodeID = i+1;
1079
1080 feaData = (feaMeshDataStruct *) feaMesh->node[i].analysisData;
1081
1082 status = fea_setFEADataPoint(efaces, eedges, enodes,
1083 attrMap,
1084 coordSystemMap,
1085 constraintMap,
1086 loadMap,
1087 transferMap,
1088 connectMap,
1089 responseMap,
1090 referenceMap,
1091 pointType, pointTopoIndex,
1092 feaData); // Set the feaData structure
1093 if (status != CAPS_SUCCESS0) goto cleanup;
1094 }
1095
1096 // Fill element information
1097
1098 // If body is just a single node
1099 if (isNodeBody == EGADS_SUCCESS0) {
1100
1101 if (numNode != 1) {
1102 printf("NodeBody found, but more than one node being reported!\n");
1103 status = CAPS_BADVALUE-311;
1104 goto cleanup;
1105 }
1106
1107 numElement = numNode;
1108 feaMesh->numElement = numElement;
1109
1110 feaMesh->element = (meshElementStruct *) EG_alloc(feaMesh->numElement*sizeof(meshElementStruct));
1111 if (feaMesh->element == NULL((void*)0)) {
1112 status = EGADS_MALLOC-4;
1113 feaMesh->numElement = 0;
1114 goto cleanup;
1115 }
1116
1117 i = 0;
1118 (void) initiate_meshElementStruct(&feaMesh->element[i], feaMesh->analysisType);
1119
1120 status = retrieve_CAPSGroupAttr(enodes[i], &attrName);
1121 if (status != CAPS_SUCCESS0) {
1122 AIM_ERROR(aimInfo, "No capsGroup attribute found for node - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1122, __func__
, "No capsGroup attribute found for node - %d!!", i+1); }
;
1123 print_AllAttr(aimInfo, enodes[i]);
1124 goto cleanup;
1125 }
1126
1127 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1128 if (status != CAPS_SUCCESS0) {
1129 printf("\tError: capsGroup name %s not found in attribute to index map\n", attrName);
1130 goto cleanup;
1131 }
1132
1133 feaMesh->element[i].elementType = Node;
1134
1135 feaMesh->element[i].elementID = i+1;
1136
1137 status = mesh_allocMeshElementConnectivity(&feaMesh->element[i]);
1138 if (status != CAPS_SUCCESS0) goto cleanup;
1139
1140 feaMesh->element[i].markerID = attrIndex;
1141
1142 feaMesh->element[i].connectivity[0] = i+1;
1143
1144 feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
1145
1146 feaData->propertyID = attrIndex;
1147
1148 feaData->attrIndex = attrIndex;
1149
1150 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1151 if (status == CAPS_SUCCESS0) {
1152 feaData->coordID = coordSystemIndex;
1153 } else {
1154 feaData->coordID = coordID;
1155 }
1156
1157 feaMesh->meshQuickRef.numNode += 1; // Add count
1158
1159 feaMesh->meshQuickRef.startIndexNode = 0;
1160 feaMesh->meshQuickRef.useStartIndex = (int) true1;
1161
1162 status = CAPS_SUCCESS0;
1163 goto cleanup;
1164
1165 } //NODEBODY IF
1166
1167 /* Determine of the body type */
1168 status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses);
1169 if (status != EGADS_SUCCESS0) goto cleanup;
1170
1171 // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces
1172 // as "free" edges
1173 if (bodySubType == WIREBODY6) {
1174 feaMesh->numElement = numEdge;
1175
1176 feaMesh->element = (meshElementStruct *) EG_alloc(feaMesh->numElement*sizeof(meshElementStruct));
1177 if (feaMesh->element == NULL((void*)0)) {
1178 status = EGADS_MALLOC-4;
1179 feaMesh->numElement = 0;
1180 goto cleanup;
1181 }
1182
1183 for (i = 0; i < feaMesh->numElement; i++) {
1184 (void) initiate_meshElementStruct(&feaMesh->element[i], feaMesh->analysisType);
1185 }
1186
1187 for (i = 0; i < numEdge; i++) {
1188
1189 status = EG_getInfo(eedges[i], &oclass, &mtype, &topObj, &prev, &next);
1190 if (status != CAPS_SUCCESS0) goto cleanup;
1191 if (mtype == DEGENERATE5) continue;
1192
1193 status = retrieve_CAPSIgnoreAttr(eedges[i], &attrName);
1194 if (status == CAPS_SUCCESS0) {
1195 printf("\tcapsIgnore attribute found for edge - %d!!\n", i+1);
1196 continue;
1197 }
1198
1199 numElement += 1;
1200
1201 status = retrieve_CAPSGroupAttr(eedges[i], &attrName);
1202 if (status != CAPS_SUCCESS0) {
1203 AIM_ERROR(aimInfo, "No capsGroup attribute found for edge - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1203, __func__
, "No capsGroup attribute found for edge - %d!!", i+1); }
;
1204 print_AllAttr(aimInfo, eedges[i] );
1205 goto cleanup;
1206 }
1207
1208 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1209 if (status != CAPS_SUCCESS0) {
1210 AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map\n", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1210, __func__
, "capsGroup name %s not found in attribute to index map\n", attrName
); }
;
1211 goto cleanup;
1212 }
1213
1214 feaMesh->element[numElement-1].elementType = Line;
1215
1216 feaMesh->element[numElement-1].elementID = numElement;
1217
1218 status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]);
1219 if (status != CAPS_SUCCESS0) goto cleanup;
1220
1221 feaMesh->element[numElement-1].markerID = attrIndex;
1222
1223 status = EG_getTessEdge(feaMesh->egadsTess, i+1, &numPoint, &xyz, &uv);
1224 if (status < EGADS_SUCCESS0) goto cleanup;
1225
1226 status = EG_localToGlobal(feaMesh->egadsTess, -(i+1), 1, &gID);
1227 if (status != EGADS_SUCCESS0) goto cleanup;
1228
1229 feaMesh->element[numElement-1].connectivity[0] = gID;
1230
1231 status = EG_localToGlobal(feaMesh->egadsTess, -(i+1), numPoint, &gID);
1232 if (status != EGADS_SUCCESS0) goto cleanup;
1233
1234 feaMesh->element[numElement-1].connectivity[1] = gID;
1235
1236 feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData;
1237
1238 feaData->propertyID = attrIndex;
1239
1240 feaData->attrIndex = attrIndex;
1241
1242 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1243 if (status == CAPS_SUCCESS0) {
1244 feaData->coordID = coordSystemIndex;
1245 } else {
1246 feaData->coordID = coordID;
1247 }
1248
1249 feaMesh->meshQuickRef.numLine += 1; // Add count
1250
1251 }
1252
1253 if (feaMesh->meshQuickRef.numLine != numEdge) { // Resize our array in case we have some ignores
1254
1255 tempElement = (meshElementStruct *) EG_reall(feaMesh->element,
1256 feaMesh->meshQuickRef.numLine*sizeof(meshElementStruct));
1257
1258 if (tempElement == NULL((void*)0)) {
1259 status = EGADS_MALLOC-4;
1260 goto cleanup;
1261 }
1262
1263 feaMesh->element = tempElement;
1264
1265 feaMesh->numElement = feaMesh->meshQuickRef.numLine;
1266 }
1267
1268 feaMesh->meshQuickRef.startIndexLine = 0;
1269 feaMesh->meshQuickRef.useStartIndex = (int) true1;
1270
1271 status = CAPS_SUCCESS0;
1272 goto cleanup;
1273
1274 } //WIREBODY IF
1275
1276 if (quadMesh == (int) true1 && numFace > 0) {
1277 printf("\tGetting quads for BEM!\n");
1278
1279 // Turn off meshQuick guide if you are getting quads
1280 feaMesh->meshQuickRef.useStartIndex = (int) false0;
1281 } else {
1282 feaMesh->meshQuickRef.useStartIndex = (int) true1;
1283 feaMesh->meshQuickRef.startIndexTriangle = numElement;
1284 }
1285
1286 // Get Tris and Quads from faces
1287 for (face = 0; face < numFace; face++) {
1288
1289 status = retrieve_CAPSIgnoreAttr(efaces[face], &attrName);
1290 if (status == CAPS_SUCCESS0) {
1291 printf("\tcapsIgnore attribute found for face - %d!!\n", face+1);
1292 ignoreFound = (int) true1;
1293 continue;
1294 }
1295
1296 status = retrieve_CAPSGroupAttr(efaces[face], &attrName);
1297 if (status != CAPS_SUCCESS0) {
1298 AIM_ERROR(aimInfo, "No capsGroup attribute found for face - %d!!", face+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1298, __func__
, "No capsGroup attribute found for face - %d!!", face+1); }
;
1299 print_AllAttr(aimInfo, efaces[face]);
1300 goto cleanup;
1301 }
1302
1303 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1304 if (status != CAPS_SUCCESS0) {
1305 AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1305, __func__
, "capsGroup name %s not found in attribute to index map", attrName
); }
;
1306 goto cleanup;
1307 }
1308
1309 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1310 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1311
1312
1313 loadIndex = CAPSMAGIC1234321;
1314 status = retrieve_CAPSLoadAttr(efaces[face], &attrName);
1315 if (status == CAPS_SUCCESS0) {
1316
1317 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
1318
1319 if (status != CAPS_SUCCESS0) {
1320 printf("Error: capsLoad name %s not found in attribute to index map\n", attrName);
1321 goto cleanup;
1322 }
1323 }
1324
1325 if (quadMesh == (int) true1) {
1326 status = EG_getQuads(feaMesh->egadsTess, face+1, &numPoint, &xyz, &uv, &ptype, &pindex, &numPatch);
1327 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1327
, __func__, 0); goto cleanup; }
;
1328
1329 } else numPatch = -1;
1330
1331 if (numPatch > 0) {
1332
1333 if (numPatch != 1) {
1334 status = CAPS_NOTIMPLEMENT-334;
1335 printf("feaUtils: EG_localToGlobal accidentally only works for a single quad patch! FIXME!\n");
1336 goto cleanup;
1337 }
1338
1339 qints[face] = 0;
1340 for (patch = 1; patch <= numPatch; patch++) {
1341
1342 status = EG_getPatch(feaMesh->egadsTess, face+1, patch, &n1, &n2, &pvindex, &pbounds);
1343 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1343
, __func__, 0); goto cleanup; }
;
1344
1345 for (j = 1; j < n2; j++) {
1346 for (i = 1; i < n1; i++) {
1347 numElement += 1;
1348
1349 feaMesh->meshQuickRef.numQuadrilateral += 1;
1350 feaMesh->numElement = numElement;
1351
1352 tempElement = (meshElementStruct *) EG_reall(feaMesh->element,
1353 feaMesh->numElement*sizeof(meshElementStruct));
1354
1355 if (tempElement == NULL((void*)0)) {
1356 status = EGADS_MALLOC-4;
1357 feaMesh->numElement -= 1;
1358 goto cleanup;
1359 }
1360
1361 feaMesh->element = tempElement;
1362
1363 status = initiate_meshElementStruct(&feaMesh->element[numElement-1], feaMesh->analysisType);
1364 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1364
, __func__, 0); goto cleanup; }
;
1365
1366 qints[face] += 1;
1367
1368 feaMesh->element[numElement-1].elementType = Quadrilateral;
1369
1370 feaMesh->element[numElement-1].elementID = numElement;
1371
1372 status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]);
1373 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1373
, __func__, 0); goto cleanup; }
;
1374
1375 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i-1)+n1*(j-1)], &gID);
1376 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1376
, __func__, 0); goto cleanup; }
;
1377
1378 feaMesh->element[numElement-1].connectivity[0] = gID;
1379
1380 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i )+n1*(j-1)], &gID);
1381 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1381
, __func__, 0); goto cleanup; }
;
1382
1383 feaMesh->element[numElement-1].connectivity[1] = gID;
1384
1385 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i )+n1*(j )], &gID);
1386 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1386
, __func__, 0); goto cleanup; }
;
1387
1388 feaMesh->element[numElement-1].connectivity[2] = gID;
1389
1390 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i-1)+n1*(j )], &gID);
1391 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1391
, __func__, 0); goto cleanup; }
;
1392
1393 feaMesh->element[numElement-1].connectivity[3] = gID;
1394
1395 feaMesh->element[numElement-1].markerID = attrIndex;
1396
1397 feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData;
1398
1399 feaData->propertyID = attrIndex;
1400 feaData->attrIndex = attrIndex;
1401 feaData->coordID = coordSystemIndex;
1402 feaData->loadIndex = loadIndex;
1403
1404 }
1405 }
1406
1407 }
1408 } else {
1409 status = EG_getTessFace(feaMesh->egadsTess, face+1,
1410 &numPoint, &xyz, &uv, &ptype, &pindex,
1411 &numTri, &triConn, &triNeighbor);
1412 if (status < EGADS_SUCCESS0) goto cleanup;
1413
1414 for (i= 0; i < numTri; i++) {
1415
1416 numElement += 1;
1417
1418 feaMesh->meshQuickRef.numTriangle += 1;
1419 feaMesh->numElement = numElement;
1420
1421
1422 tempElement = (meshElementStruct *) EG_reall(feaMesh->element,
1423 feaMesh->numElement*sizeof(meshElementStruct));
1424
1425 if (tempElement == NULL((void*)0)) {
1426 status = EGADS_MALLOC-4;
1427 feaMesh->numElement -= 1;
1428 goto cleanup;
1429 }
1430
1431 feaMesh->element = tempElement;
1432
1433 status = initiate_meshElementStruct(&feaMesh->element[numElement-1], feaMesh->analysisType);
1434 if (status != CAPS_SUCCESS0) goto cleanup;
1435
1436 feaMesh->element[numElement-1].elementType = Triangle;
1437
1438 feaMesh->element[numElement-1].elementID = numElement;
1439
1440 status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]);
1441 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1441
, __func__, 0); goto cleanup; }
;
1442
1443 status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 0], &gID);
1444 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1444
, __func__, 0); goto cleanup; }
;
1445
1446 feaMesh->element[numElement-1].connectivity[0] = gID;
1447
1448 status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 1], &gID);
1449 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1449
, __func__, 0); goto cleanup; }
;
1450
1451 feaMesh->element[numElement-1].connectivity[1] = gID;
1452
1453 status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 2], &gID);
1454 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1454
, __func__, 0); goto cleanup; }
;
1455
1456 feaMesh->element[numElement-1].connectivity[2] = gID;
1457
1458 feaMesh->element[numElement-1].markerID = attrIndex;
1459
1460 feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData;
1461
1462 feaData->propertyID = attrIndex;
1463 feaData->attrIndex = attrIndex;
1464 feaData->coordID = coordSystemIndex;
1465 feaData->loadIndex = loadIndex;
1466
1467 }
1468 }
1469
1470 }
1471
1472 if (numPatch > 0) {
1473 status = EG_attributeAdd(feaMesh->egadsTess, ".mixed", ATTRINT1, numFace, qints, NULL((void*)0), NULL((void*)0));
1474 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1474
, __func__, 0); goto cleanup; }
;
1475 }
1476
1477 if (ignoreFound == (int) true1) {
1478
1479 // Look at the nodeID for each node and check to see if it is being used in the element connectivity; if not it is removed
1480 // Note: that the nodeIDs for the nodes and element connectivity isn't changed, as such if using element connectivity to blindly
1481 // access a given node this could lead to seg-faults!. mesh_nodeID2Array must be used to access the node array index.
1482 status = mesh_removeUnusedNodes(feaMesh);
1483 if (status != CAPS_SUCCESS0) goto cleanup;
1484 }
1485
1486 status = CAPS_SUCCESS0;
1487
1488cleanup:
1489 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_bodyToBem, status = %d\n", status);
1490
1491 AIM_FREE(iwest ){ EG_free(iwest); iwest = ((void*)0); };
1492 AIM_FREE(inorth){ EG_free(inorth); inorth = ((void*)0); };
1493 AIM_FREE(ieast ){ EG_free(ieast); ieast = ((void*)0); };
1494 AIM_FREE(isouth){ EG_free(isouth); isouth = ((void*)0); };
1495 AIM_FREE(rpos ){ EG_free(rpos); rpos = ((void*)0); };
1496 AIM_FREE(points ){ EG_free(points); points = ((void*)0); };
1497
1498 AIM_FREE(enodes){ EG_free(enodes); enodes = ((void*)0); };
1499 AIM_FREE(eedges){ EG_free(eedges); eedges = ((void*)0); };
1500 AIM_FREE(efaces){ EG_free(efaces); efaces = ((void*)0); };
1501
1502 AIM_FREE(qints){ EG_free(qints); qints = ((void*)0); };
1503
1504 enodes = NULL((void*)0);
1505 eedges =NULL((void*)0);
1506 efaces =NULL((void*)0);
1507
1508 return status;
1509}
1510
1511// Set the fea analysis meta data in a mesh
1512int fea_setAnalysisData( void *aimInfo, // (in) AIM structure
1513 mapAttrToIndexStruct *attrMap, // (in) map from CAPSGroup names to indexes
1514 mapAttrToIndexStruct *coordSystemMap,// (in) map from CoordSystem names to indexes
1515 mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes
1516 mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes
1517 mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes
1518 mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes
1519 mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes
1520 mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes
1521 meshStruct *feaMesh) // (in/out) FEA mesh structure
1522{
1523 int status = 0; // Function return status
1524
1525 int i, face, edge, node, body; // Indexing
1526 int dummy;
1527
1528 int nodeOffset=0, elementOffset=0;
1529
1530 // Body entities
1531 int numNode = 0, numEdge = 0, numFace = 0;
1532 ego *enodes=NULL((void*)0), *eedges=NULL((void*)0), *efaces=NULL((void*)0);
1533 ego ebody;
1534
1535 // Meshing
1536 int elem;
1537
1538 int oclass, nchild, *senses;
1539
1540 // Edge point distributions
1541 int *points=NULL((void*)0), *isouth=NULL((void*)0), *ieast=NULL((void*)0), *inorth=NULL((void*)0), *iwest=NULL((void*)0);
1542 double data[4];
1543 double *rpos=NULL((void*)0);
1544 ego eref, *echilds;//, topObj, prev, next;
1545
1546 int isNodeBody, bodySubType = 0; // Body classification
1547
1548 int pointType, pointTopoIndex;
1549 double xyzPoint[3];
1550
1551 // Meshing
1552 int numPoint = 0, numTri = 0;
1553 const int *triConn = NULL((void*)0), *triNeighbor = NULL((void*)0); // Triangle
1554
1555 int gID; // Global id
1556
1557 const double *xyz, *uv;
1558 double result[18];
1559
1560 const int *ptype = NULL((void*)0), *pindex = NULL((void*)0);
1561
1562 // Attributues
1563 const char *attrName;
1564 int attrIndex, coordSystemIndex, loadIndex;
1565
1566 feaMeshDataStruct *feaData = NULL((void*)0);
1567 meshGeomDataStruct *geomData;
1568
1569 // ---------------------------------------------------------------
1570
1571 if (feaMesh->meshType == SurfaceMesh || feaMesh->meshType == Surface2DMesh ) {
1572 printf("Setting FEA Data\n");
1573
1574 // Get body from tessellation
1575 status = EG_statusTessBody(feaMesh->egadsTess, &ebody, &dummy, &dummy);
1576 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1576
, __func__, 0); goto cleanup; }
;
1577
1578 // Get number of Nodes, Edges, and Faces in ebody
1579 status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes);
1580 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1580
, __func__, 0); goto cleanup; }
;
1581 AIM_NOTNULL(enodes, aimInfo, status){ if (enodes == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 1581, __func__, 1, "%s == NULL!", "enodes"
); goto cleanup; } }
;
1582
1583 status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges);
1584 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1584
, __func__, 0); goto cleanup; }
;
1585
1586 status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces);
1587 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1587
, __func__, 0); goto cleanup; }
;
1588
1589 // What type of BODY do we have?
1590 isNodeBody = aim_isNodeBody(ebody, xyzPoint);
1591 if (isNodeBody < EGADS_SUCCESS0) goto cleanup;
1592 if (isNodeBody == EGADS_SUCCESS0) {
1593 // all attributes are on the body rather than the node for a node body
1594 enodes[0] = ebody;
1595 }
1596
1597 // Fill up the Attributes for the nodes
1598 for (i = 0; i < feaMesh->numNode; i++) {
1599
1600 status = EG_getGlobal(feaMesh->egadsTess, feaMesh->node[i].nodeID, &pointType, &pointTopoIndex, xyzPoint);
1601 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1601
, __func__, 0); goto cleanup; }
;
1602
1603 feaData = (feaMeshDataStruct *) feaMesh->node[i].analysisData;
1604
1605 status = fea_setFEADataPoint(efaces, eedges, enodes,
1606 attrMap,
1607 coordSystemMap,
1608 constraintMap,
1609 loadMap,
1610 transferMap,
1611 connectMap,
1612 responseMap,
1613 referenceMap,
1614 pointType, pointTopoIndex,
1615 feaData); // Set the feaData structure
1616 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1616
, __func__, 0); goto cleanup; }
;
1617 }
1618
1619 // Fill element information
1620
1621 // If body is just a single node
1622 if (numNode == 1) {
1623
1624 if (feaMesh->numNode != 1) {
1625 AIM_ERROR(aimInfo, "NodeBody found, but more than one node being reported!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1625, __func__
, "NodeBody found, but more than one node being reported!\n")
; }
;
1626 status = CAPS_BADVALUE-311;
1627 goto cleanup;
1628 }
1629
1630 i = 0;
1631 status = retrieve_CAPSGroupAttr(enodes[i], &attrName);
1632 if (status != CAPS_SUCCESS0) {
1633 AIM_ERROR(aimInfo, "No capsGroup attribute found for node - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1633, __func__
, "No capsGroup attribute found for node - %d!!", i+1); }
;
1634 print_AllAttr(aimInfo, enodes[i] );
1635 goto cleanup;
1636 }
1637
1638 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1639 if (status != CAPS_SUCCESS0) {
1640 AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1640, __func__
, "capsGroup name %s not found in attribute to index map", attrName
); }
;
1641 goto cleanup;
1642 }
1643
1644 feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
1645
1646 feaData->propertyID = attrIndex;
1647
1648 feaData->attrIndex = attrIndex;
1649
1650 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1651 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1652
1653 feaData->coordID = coordSystemIndex;
1654
1655 status = CAPS_SUCCESS0;
1656 goto cleanup;
1657
1658 } //NODEBODY IF
1659
1660#if 0
1661 /* Determine the body type */
1662 status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses);
1663 if (status != EGADS_SUCCESS0) goto cleanup;
1664
1665 // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces
1666 // as "free" edges
1667 if (bodySubType == WIREBODY6) {
1668
1669 for (i = 0; i < feaMesh->meshQuickRef.numLine; i++) {
1670
1671 status = EG_getInfo(eedges[i], &oclass, &mtype, &topObj, &prev, &next);
1672 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1672
, __func__, 0); goto cleanup; }
;
1673 if (mtype == DEGENERATE5) continue;
1674
1675 if (feaMesh->meshQuickRef.useStartIndex == (int)true1)
1676 elem = i + feaMesh->meshQuickRef.startIndexLine;
1677 else if (feaMesh->meshQuickRef.useListIndex == (int)true1)
1678 elem = feaMesh->meshQuickRef.listIndexLine[i];
1679 else {
1680 status = CAPS_BADOBJECT-310;
1681 printf("DEVELOPER ERROR: Both useStartIndex and useListIndex are true!\n");
1682 goto cleanup;
1683 }
1684
1685 attrIndex = feaMesh->element[elem].markerID;
1686
1687 // get the capsGroup attribute string value
1688 status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName);
1689 if (status != CAPS_SUCCESS0) {
1690 printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex);
1691 goto cleanup;
1692 }
1693
1694 feaData = (feaMeshDataStruct *) feaMesh->element[elem].analysisData;
1695
1696 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1697 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1698
1699 feaData->propertyID = attrIndex;
1700 feaData->coordID = coordSystemIndex;
1701 }
1702
1703 status = CAPS_SUCCESS0;
1704 goto cleanup;
1705
1706 }
1707#endif
1708
1709
1710 // Set line, tri and quad analysis data
1711 for (elem = 0; elem < feaMesh->numElement; elem++) {
1712
1713 if (feaMesh->element[elem].elementType != Node &&
1714 feaMesh->element[elem].elementType != Line &&
1715 feaMesh->element[elem].elementType != Triangle &&
1716 feaMesh->element[elem].elementType != Triangle_6 &&
1717 feaMesh->element[elem].elementType != Quadrilateral &&
1718 feaMesh->element[elem].elementType != Quadrilateral_8) continue;
1719
1720 attrIndex = feaMesh->element[elem].markerID;
1721
1722 // get the capsGroup attribute string value
1723 status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName);
1724 if (status != CAPS_SUCCESS0) {
1725 printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex);
1726 goto cleanup;
1727 }
1728
1729 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1730 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1731
1732 if (feaMesh->element[elem].elementType == Node) {
1733 // get the node index
1734 node = feaMesh->element[elem].topoIndex;
1735 if (node < 1 || node > numNode) {
1736 printf("Error: Element '%d': Invalid node topological index: %d, [1-%d]\n", elem, node, numNode);
1737 status = CAPS_BADVALUE-311;
1738 goto cleanup;
1739 }
1740
1741 eref = enodes[node-1];
1742
1743 } else if (feaMesh->element[elem].elementType == Line) {
1744 // get the edge index
1745 edge = feaMesh->element[elem].topoIndex;
1746 if (edge < 1 || edge > numEdge) {
1747 printf("Error: Element '%d': Invalid edge topological index: %d, [1-%d]\n", elem, edge, numEdge);
1748 status = CAPS_BADVALUE-311;
1749 goto cleanup;
1750 }
1751
1752 eref = eedges[edge-1];
1753
1754 } else {
1755
1756 // get the face index
1757 face = feaMesh->element[elem].topoIndex;
1758 if (face < 1 || face > numFace) {
1759 printf("Error: Element '%d': Invalid face topological index: %d, [1-%d]\n", elem, face, numFace);
1760 status = CAPS_BADVALUE-311;
1761 goto cleanup;
1762 }
1763
1764 eref = efaces[face-1];
1765
1766 // If this is a face in a capsBound, set geomData in nodes
1767 status = retrieve_CAPSBoundAttr(eref, &attrName);
1768 if (status == CAPS_SUCCESS0) {
1769
1770 status = EG_getTessFace(feaMesh->egadsTess, face,
1771 &numPoint, &xyz, &uv, &ptype, &pindex,
1772 &numTri, &triConn, &triNeighbor);
1773 if (status < EGADS_SUCCESS0) goto cleanup;
1774
1775 for (i = 0; i < numPoint; i++) {
1776
1777 status = EG_localToGlobal(feaMesh->egadsTess, face, i+1, &gID);
1778 if (status != EGADS_SUCCESS0) goto cleanup;
1779
1780 geomData = feaMesh->node[gID-1].geomData;
1781
1782 if (geomData == NULL((void*)0)) {
1783
1784 // Get geometry data for node
1785 geomData = EG_alloc(sizeof(meshGeomDataStruct));
1786
1787 if (geomData == NULL((void*)0)) {
1788 status = EGADS_MALLOC-4;
1789 goto cleanup;
1790 }
1791
1792 status = initiate_meshGeomDataStruct(geomData);
1793 if (status != CAPS_SUCCESS0) goto cleanup;
1794
1795 geomData->type = ptype[i];
1796 geomData->topoIndex = pindex[i];
1797
1798 // Want the face index to be set for topoIndex
1799 if (geomData->topoIndex < 0) geomData->topoIndex = face+1;
1800
1801 geomData->uv[0] = uv[2*i + 0];
1802 geomData->uv[1] = uv[2*i + 1];
1803
1804 status = EG_evaluate(eref, geomData->uv, result);
1805 if (status != EGADS_SUCCESS0) goto cleanup;
1806
1807 // dU
1808 geomData->firstDerivative[0] = result[3];
1809 geomData->firstDerivative[1] = result[4];
1810 geomData->firstDerivative[2] = result[5];
1811
1812 // dV
1813 geomData->firstDerivative[3] = result[6];
1814 geomData->firstDerivative[4] = result[7];
1815 geomData->firstDerivative[5] = result[8];
1816
1817 feaMesh->node[gID-1].geomData = geomData;
1818 }
1819 }
1820 }
1821 }
1822
1823 loadIndex = CAPSMAGIC1234321;
1824 status = retrieve_CAPSLoadAttr(eref, &attrName);
1825 if (status == CAPS_SUCCESS0) {
1826
1827 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
1828
1829 if (status != CAPS_SUCCESS0) {
1830 printf("Error: capsLoad name %s not found in attribute to index map\n", attrName);
1831 goto cleanup;
1832 }
1833 }
1834
1835 feaData = (feaMeshDataStruct *) feaMesh->element[elem].analysisData;
1836
1837 feaData->propertyID = attrIndex;
1838 feaData->attrIndex = attrIndex;
1839 feaData->coordID = coordSystemIndex;
1840 feaData->loadIndex = loadIndex;
1841 }
1842
1843 } else if (feaMesh->meshType == VolumeMesh) {
1844
1845 // Show warning statement
1846 printf("Warning - surface nodes are assumed to be packed sequentially in the volume\n");
1847
1848 // Loop through reference meshes
1849 for (body = 0; body < feaMesh->numReferenceMesh; body++) {
1850 printf("Setting FEA Data from reference mesh %d (of %d)\n", body+1, feaMesh->numReferenceMesh);
1851
1852 // Get body from tessellation
1853 status = EG_statusTessBody(feaMesh->referenceMesh[body].egadsTess, &ebody, &dummy, &dummy);
1854 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1854
, __func__, 0); goto cleanup; }
;
1855
1856 // Get number of Nodes, Edges, and Faces in ebody
1857 status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes);
1858 if (status < EGADS_SUCCESS0) goto cleanup;
1859 AIM_NOTNULL(enodes, aimInfo, status){ if (enodes == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 1859, __func__, 1, "%s == NULL!", "enodes"
); goto cleanup; } }
;
1860
1861 status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges);
1862 if (status != EGADS_SUCCESS0) goto cleanup;
1863
1864 status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces);
1865 if (status < EGADS_SUCCESS0) goto cleanup;
1866
1867 // What type of BODY do we have?
1868 isNodeBody = aim_isNodeBody(ebody, xyzPoint);
1869 if (isNodeBody < EGADS_SUCCESS0) goto cleanup;
1870
1871 // If body is just a single node
1872 if (isNodeBody == EGADS_SUCCESS0) {
1873
1874 printf("NodeBody found, not currently supported for VolumeMesh!\n");
1875 status = CAPS_BADVALUE-311;
1876 goto cleanup;
1877
1878 } //NODEBODY IF
1879
1880 // Fill up the Attributes for the nodes
1881 for (i = 0; i < feaMesh->referenceMesh[body].numNode; i++) {
1882
1883 status = EG_getGlobal(feaMesh->referenceMesh[body].egadsTess, feaMesh->referenceMesh[body].node[i].nodeID, &pointType, &pointTopoIndex, xyzPoint);
1884 if (status != EGADS_SUCCESS0) goto cleanup;
1885
1886 feaData = (feaMeshDataStruct *) feaMesh->node[i+nodeOffset].analysisData;
1887
1888 status = fea_setFEADataPoint(efaces, eedges, enodes,
1889 attrMap,
1890 coordSystemMap,
1891 constraintMap,
1892 loadMap,
1893 transferMap,
1894 connectMap,
1895 responseMap,
1896 referenceMap,
1897 pointType, pointTopoIndex,
1898 feaData); // Set the feaData structure
1899 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1899
, __func__, 0); goto cleanup; }
;
1900 }
1901
1902 // Fill element information //
1903
1904 // Determine the body type
1905 status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses);
1906 if (status != EGADS_SUCCESS0) goto cleanup;
1907
1908 // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces
1909 // as "free" edges
1910 if (bodySubType == WIREBODY6) {
1911
1912 printf("WireBody found, not currently supported for VolumeMesh!\n");
1913 status = CAPS_BADVALUE-311;
1914 goto cleanup;
1915
1916 } //WIREBODY IF
1917
1918 // Set tri and quad analysis data
1919 for (elem = 0; elem < feaMesh->referenceMesh[body].numElement; elem++) {
1920
1921 if (feaMesh->referenceMesh[body].element[elem].elementType != Triangle &&
1922 feaMesh->referenceMesh[body].element[elem].elementType != Triangle_6 &&
1923 feaMesh->referenceMesh[body].element[elem].elementType != Quadrilateral &&
1924 feaMesh->referenceMesh[body].element[elem].elementType != Quadrilateral_8) continue;
1925
1926//
1927// attrIndex = feaMesh->referenceMesh[body].element[elem].markerID;
1928//
1929// // get the capsGroup attribute string value
1930// status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName);
1931// if (status != CAPS_SUCCESS) {
1932// printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex);
1933// goto cleanup;
1934// }
1935//
1936// status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1937// if (status != CAPS_SUCCESS) coordSystemIndex = 0;
1938
1939 // get the face index
1940 face = feaMesh->referenceMesh[body].element[elem].topoIndex;
1941 if (face < 1 || face > numFace) {
1942 printf("Error: Element '%d': Invalid face topological index: %d, [1-%d]\n", elem, face, numFace);
1943 status = CAPS_BADVALUE-311;
1944 goto cleanup;
1945 }
1946
1947 loadIndex = CAPSMAGIC1234321;
1948 status = retrieve_CAPSLoadAttr(efaces[face-1], &attrName);
1949 if (status == CAPS_SUCCESS0) {
1950
1951 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
1952
1953 if (status != CAPS_SUCCESS0) {
1954 printf("Error: capsLoad name %s not found in attribute to index map\n", attrName);
1955 goto cleanup;
1956 }
1957 }
1958
1959 feaData = (feaMeshDataStruct *) feaMesh->element[elem+elementOffset].analysisData;
1960
1961 //feaData->propertyID = attrIndex; DONT THINK WE WANT TO CHANGE THE PROPERTY TYPE
1962 // feaData->coordID = coordSystemIndex; DONT THINK WE WANT TO CHANGE THE Coordinate TYPE
1963 feaData->loadIndex = loadIndex;
1964 }
1965
1966 nodeOffset += feaMesh->referenceMesh[body].numNode;
1967 elementOffset += feaMesh->referenceMesh[body].numElement;
1968 }
1969
1970 } else {
1971 printf("Unknown meshType!\n");
1972 status = CAPS_BADTYPE-306;
1973 goto cleanup;
1974 }
1975
1976 status = CAPS_SUCCESS0;
1977
1978 cleanup:
1979 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_setAnalysisData, status = %d\n", status);
1980
1981 EG_free(iwest );
1982 EG_free(inorth);
1983 EG_free(ieast );
1984 EG_free(isouth);
1985 EG_free(rpos );
1986 EG_free(points );
1987
1988 EG_free(enodes);
1989 EG_free(eedges);
1990 EG_free(efaces);
1991
1992 enodes = NULL((void*)0);
1993 eedges = NULL((void*)0);
1994 efaces = NULL((void*)0);
1995
1996 return status;
1997}
1998
1999// Set feaData for a given point index and topology index. Ego faces, edges, and nodes must be provided along with attribute maps
2000int fea_setFEADataPoint(ego *faces, ego *edges, ego *nodes,
2001 mapAttrToIndexStruct *attrMap,
2002 /*@unused@*/ mapAttrToIndexStruct *coordSystemMap,
2003 mapAttrToIndexStruct *constraintMap,
2004 mapAttrToIndexStruct *loadMap,
2005 mapAttrToIndexStruct *transferMap,
2006 mapAttrToIndexStruct *connectMap,
2007 mapAttrToIndexStruct *responseMap,
2008 mapAttrToIndexStruct *referenceMap,
2009 int pointType, int pointTopoIndex,
2010 feaMeshDataStruct *feaData) { // Set the feaData structure
2011
2012 int status;
2013
2014 int coordID = 0; // Default coordinate id for mesh
2015
2016 // Attributes
2017 const char *attrName;
2018 int constraintIndex=-1, loadIndex=-1, transferIndex=-1, connectIndex=-1;
2019 int connectLinkIndex=-1, attrIndex=-1, responseIndex=-1, referenceIndex=-1; //coordSystemIndex
2020
2021 ego object;
2022
2023 feaData->coordID = coordID;
2024
2025 // Get attribute index on entity
2026 constraintIndex = CAPSMAGIC1234321;
2027 loadIndex = CAPSMAGIC1234321;
2028 transferIndex = CAPSMAGIC1234321;
2029 connectIndex = CAPSMAGIC1234321;
2030 connectLinkIndex = CAPSMAGIC1234321;
2031 responseIndex = CAPSMAGIC1234321;
2032 referenceIndex = CAPSMAGIC1234321;
2033
2034 if (pointType == 0) { // Node
2035
2036 object = nodes[pointTopoIndex-1];
2037
2038 } else if (pointType > 0 ) { // Edge
2039
2040 object = edges[pointTopoIndex-1];
2041
2042 } else { // Face
2043
2044 object = faces[pointTopoIndex-1];
2045
2046 }
2047
2048 status = retrieve_CAPSGroupAttr(object, &attrName);
2049 if (status == CAPS_SUCCESS0) {
2050 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
2051 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2052 }
2053
2054 status = retrieve_CAPSConstraintAttr(object, &attrName);
2055 if (status == CAPS_SUCCESS0) {
2056 status = get_mapAttrToIndexIndex(constraintMap, attrName, &constraintIndex);
2057 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2058 }
2059
2060 status = retrieve_CAPSLoadAttr(object, &attrName);
2061 if (status == CAPS_SUCCESS0) {
2062 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
2063 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2064 }
2065
2066 status = retrieve_CAPSBoundAttr(object, &attrName);
2067 if (status == CAPS_SUCCESS0) {
2068 status = get_mapAttrToIndexIndex(transferMap, attrName, &transferIndex);
2069 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2070 }
2071
2072 if (connectMap != NULL((void*)0)) {
2073 status = retrieve_CAPSConnectAttr(object, &attrName);
2074 if (status == CAPS_SUCCESS0) {
2075 status = get_mapAttrToIndexIndex(connectMap, attrName, &connectIndex);
2076 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2077 }
2078
2079 status = retrieve_CAPSConnectLinkAttr(object, &attrName);
2080 if (status == CAPS_SUCCESS0) {
2081 status = get_mapAttrToIndexIndex(connectMap, attrName, &connectLinkIndex);
2082 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2083 }
2084 }
2085
2086 if (responseMap != NULL((void*)0)) {
2087 status = retrieve_CAPSResponseAttr(object, &attrName);
2088 if (status == CAPS_SUCCESS0) {
2089 status = get_mapAttrToIndexIndex(responseMap, attrName, &responseIndex);
2090 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2091 }
2092 }
2093
2094 if (referenceMap != NULL((void*)0)) {
2095 status = retrieve_CAPSReferenceAttr(object, &attrName);
2096 if (status == CAPS_SUCCESS0) {
2097 status = get_mapAttrToIndexIndex(referenceMap, attrName, &referenceIndex);
2098 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2099 }
2100 }
2101
2102 feaData->attrIndex = attrIndex;
2103
2104 feaData->constraintIndex = constraintIndex;
2105 feaData->loadIndex = loadIndex;
2106 feaData->transferIndex = transferIndex;
2107 feaData->connectIndex = connectIndex;
2108 feaData->connectLinkIndex = connectLinkIndex;
2109 feaData->responseIndex = responseIndex;
2110 feaData->referenceIndex = referenceIndex;
2111
2112 status = CAPS_SUCCESS0;
2113 goto cleanup;
2114
2115 cleanup:
2116
2117 if (status != CAPS_SUCCESS0) printf("Error: Premature exit in fea_setFEADataPoint, status %d\n", status);
2118
2119 return status;
2120}
2121
2122// Initiate (0 out all values and NULL all pointers) of feaProperty in the feaPropertyStruct structure format
2123int initiate_feaPropertyStruct(feaPropertyStruct *feaProperty) {
2124 int i;
2125
2126 feaProperty->name = NULL((void*)0);
2127
2128 feaProperty->propertyType = UnknownProperty;
2129
2130 feaProperty->propertyID = 0; // ID number of property
2131
2132 feaProperty->materialID = 0; // ID number of material
2133 feaProperty->materialName = NULL((void*)0); // Name of material associated with material ID
2134
2135 // Rods
2136 feaProperty->crossSecArea = 0.0; // Bar cross-sectional area
2137 feaProperty->torsionalConst = 0.0; // Torsional constant
2138 feaProperty->torsionalStressReCoeff = 0.0; // Torsional stress recovery coefficient
2139 feaProperty->massPerLength = 0.0; // Mass per unit length
2140
2141 // Bar - see rod for additional variables
2142 feaProperty->zAxisInertia = 0.0; // Section moment of inertia about the z axis
2143 feaProperty->yAxisInertia = 0.0; // Section moment of inertia about the y axis
2144
2145 feaProperty->yCoords[0] = 0.0; // Element y, z coordinates, in the bar cross-section, of
2146 feaProperty->yCoords[1] = 0.0; // of four points at which to recover stresses
2147 feaProperty->yCoords[2] = 0.0;
2148 feaProperty->yCoords[3] = 0.0;
2149
2150 feaProperty->zCoords[0] = 0.0;
2151 feaProperty->zCoords[1] = 0.0;
2152 feaProperty->zCoords[2] = 0.0;
2153 feaProperty->zCoords[3] = 0.0;
2154
2155 feaProperty->areaShearFactors[0] = 0.0; // Area factors for shear
2156 feaProperty->areaShearFactors[1] = 0.0;
2157
2158 feaProperty->crossProductInertia = 0.0; // Section cross-product of inertia
2159
2160 feaProperty->crossSecType = NULL((void*)0); // Type of cross sections
2161 for (i = 0; i < 10; i++) feaProperty->crossSecDimension[i] = 0.0; // Dimensions
2162
2163 feaProperty->orientationVec[0] = 0.0; // Orientation vector
2164 feaProperty->orientationVec[1] = 0.0;
2165 feaProperty->orientationVec[2] = 0.0;
2166
2167 // Shear
2168
2169 // Shell
2170 feaProperty->membraneThickness = 0.0; // Membrane thickness
2171 feaProperty->materialBendingID = 0; /// ID number of material for bending - if not specified and bendingInertiaRatio > 0 this value defaults to materialID
2172 feaProperty->bendingInertiaRatio = 1.0; // Ratio of actual bending moment inertia (I) to bending inertia of a solid
2173 // plate of thickness TM Real - default 1.0
2174 feaProperty->materialShearID = 0; // ID number of material for shear - if not specified and shearMembraneRatio > 0 this value defaults to materialID
2175 feaProperty->shearMembraneRatio = 5.0/6.0; // Ratio of shear to membrane thickness - default 5/6
2176 feaProperty->massPerArea = 0.0; // Mass per unit area
2177 //feaProperty->neutralPlaneDist[0] = 0; // Distances from the neutral plane of the plate to locations where
2178 //feaProperty->neutralPlaneDist[1] = 0; // stress is calculate
2179
2180 feaProperty->zOffsetRel = 0.0; // Offset from the surface of grid points to the element reference plane
2181
2182 feaProperty->compositeShearBondAllowable = 0.0; // Shear stress limit for bonding between plies
2183 feaProperty->compositeFailureTheory = NULL((void*)0); // HILL, HOFF, TSAI, STRN
2184 feaProperty->compositeSymmetricLaminate = (int) false0; // 1- SYM only half the plies are specified, for odd number plies 1/2 thickness of center ply is specified
2185 // the first ply is the bottom ply in the stack, default (0) all plies specified
2186 feaProperty->numPly = 0;
2187 feaProperty->compositeMaterialID = NULL((void*)0); // Vector of material ID's from bottom to top for all plies
2188 feaProperty->compositeThickness = NULL((void*)0); // Vector of thicknesses from bottom to top for all plies
2189 feaProperty->compositeOrientation = NULL((void*)0); // Vector of orientations from bottom to top for all plies
2190
2191 // Solid
2192
2193 // Concentrated Mass
2194 feaProperty->mass = 0.0; // Mass value
2195 feaProperty->massOffset[0] = 0.0; // Offset distance from the grid point to the center of gravity
2196 feaProperty->massOffset[1] = 0.0;
2197 feaProperty->massOffset[2] = 0.0;
2198 feaProperty->massInertia[0] = 0.0; // Mass moment of inertia measured at the mass center of gravity
2199 feaProperty->massInertia[1] = 0.0;
2200 feaProperty->massInertia[2] = 0.0;
2201 feaProperty->massInertia[3] = 0.0;
2202 feaProperty->massInertia[4] = 0.0;
2203 feaProperty->massInertia[5] = 0.0;
2204
2205 return CAPS_SUCCESS0;
2206}
2207
2208// Destroy (0 out all values and NULL all pointers) of feaProperty in the feaPropertyStruct structure format
2209int destroy_feaPropertyStruct(feaPropertyStruct *feaProperty) {
2210
2211 int i;
2212
2213 if (feaProperty->name != NULL((void*)0)) EG_free(feaProperty->name);
2214
2215 feaProperty->propertyType = UnknownProperty;
2216
2217 feaProperty->propertyID = 0; // ID number of property
2218
2219 feaProperty->materialID = 0; // ID number of material
2220
2221 if (feaProperty->materialName != NULL((void*)0)) EG_free(feaProperty->materialName); // Name of material associated with material ID
2222 feaProperty->materialName = NULL((void*)0);
2223
2224 // Rods
2225 feaProperty->crossSecArea = 0; // Bar cross-sectional area
2226 feaProperty->torsionalConst = 0; // Torsional constant
2227 feaProperty->torsionalStressReCoeff = 0; // Torsional stress recovery coefficient
2228 feaProperty->massPerLength = 0; // Mass per unit length
2229
2230 // Bar - see rod for additional variables
2231 feaProperty->zAxisInertia = 0; // Section moment of inertia about the z axis
2232 feaProperty->yAxisInertia = 0; // Section moment of inertia about the y axis
2233
2234 feaProperty->yCoords[0] = 0; // Element y, z coordinates, in the bar cross-section, of
2235 feaProperty->yCoords[1] = 0; // of four points at which to recover stresses
2236 feaProperty->yCoords[2] = 0;
2237 feaProperty->yCoords[3] = 0;
2238
2239 feaProperty->zCoords[0] = 0;
2240 feaProperty->zCoords[1] = 0;
2241 feaProperty->zCoords[2] = 0;
2242 feaProperty->zCoords[3] = 0;
2243
2244 feaProperty->areaShearFactors[0] = 0; // Area factors for shear
2245 feaProperty->areaShearFactors[1] = 0;
2246
2247 feaProperty->crossProductInertia = 0; // Section cross-product of inertia
2248
2249 if (feaProperty->crossSecType != NULL((void*)0)) EG_free(feaProperty->crossSecType);
2250 feaProperty->crossSecType = NULL((void*)0); // Type of cross sections
2251 for (i = 0; i < 10; i++) feaProperty->crossSecDimension[i] = 0.0; // Dimensions
2252
2253 feaProperty->orientationVec[0] = 0.0; // Orientation vector
2254 feaProperty->orientationVec[1] = 0.0;
2255 feaProperty->orientationVec[2] = 0.0;
2256
2257 // Shear
2258
2259 // Shell
2260 feaProperty->membraneThickness = 0; // Membrane thickness
2261 feaProperty->materialBendingID = 0; // ID number of material for bending
2262 feaProperty->bendingInertiaRatio = 1.0; // Ratio of actual bending moment inertia (I) to bending inertia of a solid
2263 // plate of thickness TM Real - default 1.0
2264 feaProperty->materialShearID = 0; // ID number of material for shear
2265 feaProperty->shearMembraneRatio = 5.0/6.0; // Ratio of shear to membrane thickness - default 5/6
2266 feaProperty->massPerArea = 0; // Mass per unit area
2267 //feaProperty->neutralPlaneDist[0] = 0; // Distances from the neutral plane of the plate to locations where
2268 //feaProperty->neutralPlaneDist[1] = 0; // stress is calculate
2269
2270 feaProperty->zOffsetRel = 0.0; // Offset from the surface of grid points to the element reference plane
2271
2272 feaProperty->numPly = 0;
2273 feaProperty->compositeShearBondAllowable = 0.0; // Shear stress limit for bonding between plies
2274 if (feaProperty->compositeFailureTheory != NULL((void*)0)) EG_free(feaProperty->compositeFailureTheory); // HILL, HOFF, TSAI, STRN
2275 feaProperty->compositeFailureTheory = NULL((void*)0);
2276 feaProperty->compositeSymmetricLaminate = (int) false0; // 1- SYM only half the plies are specified, for odd number plies 1/2 thickness of center ply is specified
2277 // the first ply is the bottom ply in the stack, default (0) all plies specified
2278 if (feaProperty->compositeMaterialID != NULL((void*)0)) EG_free(feaProperty->compositeMaterialID);
2279 if (feaProperty->compositeThickness != NULL((void*)0)) EG_free(feaProperty->compositeThickness);
2280 if (feaProperty->compositeOrientation != NULL((void*)0)) EG_free(feaProperty->compositeOrientation);
2281
2282 feaProperty->compositeMaterialID = NULL((void*)0);
2283 feaProperty->compositeThickness = NULL((void*)0);
2284 feaProperty->compositeOrientation = NULL((void*)0);
2285
2286 // Solid
2287
2288 // Concentrated Mass
2289 feaProperty->mass = 0.0; // Mass value
2290 feaProperty->massOffset[0] = 0.0; // Offset distance from the grid point to the center of gravity
2291 feaProperty->massOffset[1] = 0.0;
2292 feaProperty->massOffset[2] = 0.0;
2293 feaProperty->massInertia[0] = 0.0; // Mass moment of inertia measured at the mass center of gravity
2294 feaProperty->massInertia[1] = 0.0;
2295 feaProperty->massInertia[2] = 0.0;
2296 feaProperty->massInertia[3] = 0.0;
2297 feaProperty->massInertia[4] = 0.0;
2298 feaProperty->massInertia[5] = 0.0;
2299
2300 return CAPS_SUCCESS0;
2301}
2302
2303// Initiate (0 out all values and NULL all pointers) of feaMaterial in the feaMaterialStruct structure format
2304int initiate_feaMaterialStruct(feaMaterialStruct *feaMaterial) {
2305
2306 feaMaterial->name = NULL((void*)0); // Material name
2307
2308 feaMaterial->materialType = UnknownMaterial; // Set
2309
2310 feaMaterial->materialID = 0; // ID number of material
2311
2312 feaMaterial->youngModulus = 0.0; // E - Young's Modulus
2313 feaMaterial->shearModulus = 0.0; // G - Shear Modulus
2314 feaMaterial->poissonRatio = 0.0; // Poisson's Ratio
2315 feaMaterial->density = 0.0; // Rho - material mass density
2316 feaMaterial->thermalExpCoeff = 0.0; //Coefficient of thermal expansion
2317 feaMaterial->temperatureRef = 0.0; // Reference temperature
2318 feaMaterial->dampingCoeff = 0.0; // Damping coefficient
2319 feaMaterial->tensionAllow = 0.0; // Tension allowable for the material
2320 feaMaterial->compressAllow = 0.0; // Compression allowable for the material
2321 feaMaterial->shearAllow = 0.0; // Shear allowable for the material
2322
2323 feaMaterial->youngModulusLateral = 0.0; // Young's Modulus in the lateral direction
2324 feaMaterial->shearModulusTrans1Z = 0.0; // Transverse shear modulus in the 1-Z plane
2325 feaMaterial->shearModulusTrans2Z = 0.0; // Transverse shear modulus in the 2-Z plane
2326 feaMaterial->tensionAllowLateral = 0.0; // Tension allowable for the material
2327 feaMaterial->compressAllowLateral = 0.0; // Compression allowable for the material
2328 feaMaterial->thermalExpCoeffLateral = 0.0; //Coefficient of thermal expansion
2329 feaMaterial->allowType = 0;
2330
2331 feaMaterial->specificHeat = 0;
2332 feaMaterial->kappa = 0;
2333
2334 return CAPS_SUCCESS0;
2335}
2336
2337// Destroy (0 out all values and NULL all pointers) of feaMaterial in the feaMaterialStruct structure format
2338int destroy_feaMaterialStruct(feaMaterialStruct *feaMaterial) {
2339
2340 if (feaMaterial->name != NULL((void*)0)) EG_free(feaMaterial->name);
2341 feaMaterial->name = NULL((void*)0); // Material name
2342
2343 feaMaterial->materialType = UnknownMaterial; // Material type
2344
2345 feaMaterial->materialID = 0; // ID number of material
2346
2347 feaMaterial->youngModulus = 0.0; // E - Young's Modulus
2348 feaMaterial->shearModulus = 0.0; // G - Shear Modulus
2349 feaMaterial->poissonRatio = 0.0; // Poisson's Ratio
2350 feaMaterial->density = 0.0; // Rho - material mass density
2351 feaMaterial->thermalExpCoeff = 0.0; //Coefficient of thermal expansion
2352 feaMaterial->temperatureRef = 0.0; // Reference temperature
2353 feaMaterial->dampingCoeff = 0.0; // Damping coefficient
2354 feaMaterial->tensionAllow = 0.0; // Tension allowable for the material
2355 feaMaterial->compressAllow = 0.0; // Compression allowable for the material
2356 feaMaterial->shearAllow = 0.0; // Shear allowable for the material
2357
2358 feaMaterial->youngModulusLateral = 0.0; // Young's Modulus in the lateral direction
2359 feaMaterial->shearModulusTrans1Z = 0.0; // Transverse shear modulus in the 1-Z plane
2360 feaMaterial->shearModulusTrans2Z = 0.0; // Transverse shear modulus in the 2-Z plane
2361 feaMaterial->tensionAllowLateral = 0.0; // Tension allowable for the material
2362 feaMaterial->compressAllowLateral = 0.0; // Compression allowable for the material
2363 feaMaterial->thermalExpCoeffLateral = 0.0; //Coefficient of thermal expansion
2364 feaMaterial->allowType = 0;
2365
2366 feaMaterial->specificHeat = 0;
2367 feaMaterial->kappa = 0;
2368
2369 return CAPS_SUCCESS0;
2370}
2371
2372// Initiate (0 out all values and NULL all pointers) of feaUnits in the feaUnitsStruct structure format
2373int initiate_feaUnitsStruct(feaUnitsStruct *feaUnits) {
2374
2375 feaUnits->densityVol = NULL((void*)0);
2376 feaUnits->densityArea = NULL((void*)0);
2377 feaUnits->mass = NULL((void*)0);
2378 feaUnits->length = NULL((void*)0);
2379 feaUnits->pressure = NULL((void*)0);
2380 feaUnits->temperature = NULL((void*)0);
2381 feaUnits->momentOfInertia = NULL((void*)0);
2382
2383 return CAPS_SUCCESS0;
2384}
2385
2386// Destroy (0 out all values and NULL all pointers) of feaUnits in the feaUnitsStruct structure format
2387int destroy_feaUnitsStruct(feaUnitsStruct *feaUnits) {
2388
2389 AIM_FREE(feaUnits->densityVol){ EG_free(feaUnits->densityVol); feaUnits->densityVol =
((void*)0); }
;
2390 AIM_FREE(feaUnits->densityArea){ EG_free(feaUnits->densityArea); feaUnits->densityArea
= ((void*)0); }
;
2391 AIM_FREE(feaUnits->mass){ EG_free(feaUnits->mass); feaUnits->mass = ((void*)0);
}
;
2392 AIM_FREE(feaUnits->length){ EG_free(feaUnits->length); feaUnits->length = ((void*
)0); }
;
2393 AIM_FREE(feaUnits->pressure){ EG_free(feaUnits->pressure); feaUnits->pressure = ((void
*)0); }
;
2394 AIM_FREE(feaUnits->temperature){ EG_free(feaUnits->temperature); feaUnits->temperature
= ((void*)0); }
;
2395 AIM_FREE(feaUnits->momentOfInertia){ EG_free(feaUnits->momentOfInertia); feaUnits->momentOfInertia
= ((void*)0); }
;
2396
2397 return CAPS_SUCCESS0;
2398}
2399
2400// Initiate (0 out all values and NULL all pointers) of feaConstraint in the feaConstraintStruct structure format
2401int initiate_feaConstraintStruct(feaConstraintStruct *feaConstraint) {
2402
2403 feaConstraint->name = NULL((void*)0); // Constraint name
2404
2405 feaConstraint->constraintType = UnknownConstraint; // Constraint type
2406
2407 feaConstraint->constraintID = 0; // ID number of constraint
2408
2409 feaConstraint->numGridID = 0; // Component number of grid
2410 feaConstraint->gridIDSet = NULL((void*)0); // List of component number of grids to apply constraint to
2411
2412 feaConstraint->dofConstraint = 0; // Number to indicate DOF constraints
2413 feaConstraint->gridDisplacement = 0;
2414
2415 return CAPS_SUCCESS0;
2416}
2417
2418// Destroy (0 out all values and NULL all pointers) of feaConstraint in the feaConstraintStruct structure format
2419int destroy_feaConstraintStruct(feaConstraintStruct *feaConstraint) {
2420
2421 if (feaConstraint->name != NULL((void*)0)) EG_free(feaConstraint->name);
2422 feaConstraint->name = NULL((void*)0); // Constraint name
2423
2424 feaConstraint->constraintType = UnknownConstraint; // Constraint type
2425
2426 feaConstraint->constraintID = 0; // ID number of constraint
2427
2428 feaConstraint->numGridID = 0; // Number of grid IDs in grid ID set
2429
2430 if (feaConstraint->gridIDSet != NULL((void*)0)) EG_free(feaConstraint->gridIDSet); // List of component number of grids to apply constraint to
2431
2432 feaConstraint->dofConstraint = 0; // Number to indicate DOF constraints
2433 feaConstraint->gridDisplacement = 0; // The value for the displacement
2434
2435 return CAPS_SUCCESS0;
2436}
2437
2438// Initiate (0 out all values and NULL all pointers) of feaSupport in the feaSupportStruct structure format
2439int initiate_feaSupportStruct(feaSupportStruct *feaSupport) {
2440
2441 feaSupport->name = NULL((void*)0); // Support name
2442
2443 feaSupport->supportID = 0; // ID number of support
2444
2445 feaSupport->numGridID = 0; // Component number of grid
2446 feaSupport->gridIDSet = NULL((void*)0); // List of component number of grids to apply support to
2447
2448 feaSupport->dofSupport = 0; // Number to indicate DOF supports
2449
2450 return CAPS_SUCCESS0;
2451}
2452
2453// Destroy (0 out all values and NULL all pointers) of feaSupport in the feaSupportStruct structure format
2454int destroy_feaSupportStruct(feaSupportStruct *feaSupport) {
2455
2456 if (feaSupport->name != NULL((void*)0)) EG_free(feaSupport->name);
2457 feaSupport->name = NULL((void*)0); // Support name
2458
2459 feaSupport->supportID = 0; // ID number of support
2460
2461 feaSupport->numGridID = 0; // Number of grid IDs in grid ID set
2462
2463 if (feaSupport->gridIDSet != NULL((void*)0)) EG_free(feaSupport->gridIDSet); // List of component number of grids to apply support to
2464
2465 feaSupport->dofSupport = 0; // Number to indicate DOF supports
2466
2467 return CAPS_SUCCESS0;
2468}
2469
2470// Initiate (0 out all values and NULL all pointers) of feaAnalysis in the feaAnalysisStruct structure format
2471int initiate_feaAnalysisStruct(feaAnalysisStruct *feaAnalysis) {
2472
2473 feaAnalysis->name = NULL((void*)0); // Analysis name
2474
2475 feaAnalysis->analysisType = UnknownAnalysis; // Type of analysis
2476
2477 feaAnalysis->analysisID = 0; // ID number of analysis
2478
2479 // Loads for the analysis
2480 feaAnalysis->numLoad = 0; // Number of loads in the analysis
2481 feaAnalysis->loadSetID = NULL((void*)0); // List of the load IDSs
2482
2483 // Constraints for the analysis
2484 feaAnalysis->numConstraint = 0; // Number of constraints in the analysis
2485 feaAnalysis->constraintSetID = NULL((void*)0); // List of constraint IDs
2486
2487 // Supports for the analysis
2488 feaAnalysis->numSupport = 0; // Number of supports in the analysis
2489 feaAnalysis->supportSetID = NULL((void*)0); // List of support IDs
2490
2491 // Optimization constraints
2492 feaAnalysis->numDesignConstraint = 0; // Number of design constraints
2493 feaAnalysis->designConstraintSetID = NULL((void*)0); // List of design constraint IDs
2494
2495 // Optimization responses
2496 feaAnalysis->numDesignResponse = 0; // Number of design responses
2497 feaAnalysis->designResponseSetID = NULL((void*)0); // List of design response IDs
2498
2499 // Eigenvalue
2500 feaAnalysis->extractionMethod = NULL((void*)0);
2501
2502 feaAnalysis->frequencyRange[0] = 0;
2503 feaAnalysis->frequencyRange[1] = 0;
2504
2505 feaAnalysis->numEstEigenvalue = 0;
2506 feaAnalysis->numDesiredEigenvalue = 0;
2507 feaAnalysis->eigenNormaliztion = NULL((void*)0);
2508
2509 feaAnalysis->gridNormaliztion = 0;
2510 feaAnalysis->componentNormaliztion = 0;
2511
2512 feaAnalysis->lanczosMode = 2; //Lanczos mode for calculating eigenvalues
2513 feaAnalysis->lanczosType = NULL((void*)0); //Lanczos matrix type (DPB, DGB)
2514
2515 // Trim
2516 feaAnalysis->numMachNumber = 0;
2517 feaAnalysis->machNumber = NULL((void*)0); // Mach number
2518 feaAnalysis->dynamicPressure = 0.0; // Dynamic pressure
2519 feaAnalysis->density = 0.0; // Density
2520 feaAnalysis->aeroSymmetryXY = NULL((void*)0);
2521 feaAnalysis->aeroSymmetryXZ = NULL((void*)0);
2522
2523 feaAnalysis->numRigidVariable = 0; // Number of rigid trim variables
2524 feaAnalysis->rigidVariable = NULL((void*)0); // List of character labels identifying rigid trim variables, size=[numRigidVariables]
2525
2526 feaAnalysis->numRigidConstraint = 0; // Number of rigid trim constrained variables
2527 feaAnalysis->rigidConstraint = NULL((void*)0); // List of character labels identifying rigid constrained trim variables, size=[numRigidConstraint]
2528 feaAnalysis->magRigidConstraint = NULL((void*)0); // Magnitude of rigid constrained trim variables, size=[numRigidConstraint]
2529
2530 feaAnalysis->numControlConstraint = 0; // Number of control surface constrained variables
2531 feaAnalysis->controlConstraint = NULL((void*)0); // List of character labels identifying control surfaces to be constrained trim variables, size=[numControlConstraint]
2532 feaAnalysis->magControlConstraint = NULL((void*)0); // Magnitude of control surface constrained variables, size=[numControlConstraint]
2533
2534 // Flutter
2535 feaAnalysis->numReducedFreq = 0;
2536 feaAnalysis->reducedFreq = NULL((void*)0);
2537
2538 feaAnalysis->numFlutterVel = 0;
2539 feaAnalysis->flutterVel = NULL((void*)0);
2540
2541 feaAnalysis->flutterConvergenceParam = 0.0;
2542
2543 feaAnalysis->visualFlutter = (int) false0;
2544
2545 return CAPS_SUCCESS0;
2546}
2547
2548// Destroy (0 out all values and NULL all pointers) of feaAnalysis in the feaAnalysisStruct structure format
2549int destroy_feaAnalysisStruct(feaAnalysisStruct *feaAnalysis) {
2550 int status; // Function return status
2551
2552 if (feaAnalysis->name != NULL((void*)0)) EG_free(feaAnalysis->name);
2553 feaAnalysis->name = NULL((void*)0); // Analysis name
2554
2555 feaAnalysis->analysisType = UnknownAnalysis; // Type of analysis
2556
2557 feaAnalysis->analysisID = 0; // ID number of analysis
2558
2559 // Loads for the analysis
2560 feaAnalysis->numLoad = 0; // Number of loads in the analysis
2561 if(feaAnalysis->loadSetID != NULL((void*)0)) EG_free(feaAnalysis->loadSetID);
2562 feaAnalysis->loadSetID = NULL((void*)0); // List of the load IDSs
2563
2564 // Constraints for the analysis
2565 feaAnalysis->numConstraint = 0; // Number of constraints in the analysis
2566 if (feaAnalysis->constraintSetID != NULL((void*)0)) EG_free(feaAnalysis->constraintSetID);
2567 feaAnalysis->constraintSetID = NULL((void*)0); // List of constraint IDs
2568
2569 // Supports for the analysis
2570 feaAnalysis->numSupport = 0; // Number of supports in the analysis
2571 if (feaAnalysis->supportSetID != NULL((void*)0)) EG_free(feaAnalysis->supportSetID);
2572 feaAnalysis->supportSetID = NULL((void*)0); // List of support IDs
2573
2574 // Optimization constraints
2575 feaAnalysis->numDesignConstraint = 0; // Number of design constraints
2576 if (feaAnalysis->designConstraintSetID != NULL((void*)0)) EG_free(feaAnalysis->designConstraintSetID);
2577 feaAnalysis->designConstraintSetID = NULL((void*)0); // List of design constraint IDs
2578
2579 // Optimization responses
2580 feaAnalysis->numDesignResponse = 0; // Number of design responses
2581 if (feaAnalysis->designResponseSetID != NULL((void*)0)) EG_free(feaAnalysis->designResponseSetID);
2582 feaAnalysis->designResponseSetID = NULL((void*)0); // List of design response IDs
2583
2584 // Eigenvalue
2585 if (feaAnalysis->extractionMethod != NULL((void*)0)) EG_free(feaAnalysis->extractionMethod);
2586 feaAnalysis->extractionMethod = NULL((void*)0);
2587
2588 feaAnalysis->frequencyRange[0] = 0;
2589 feaAnalysis->frequencyRange[1] = 0;
2590
2591 feaAnalysis->numEstEigenvalue = 0;
2592 feaAnalysis->numDesiredEigenvalue = 0;
2593
2594 if (feaAnalysis->eigenNormaliztion != NULL((void*)0)) EG_free(feaAnalysis->eigenNormaliztion);
2595 feaAnalysis->eigenNormaliztion = NULL((void*)0);
2596
2597 feaAnalysis->gridNormaliztion = 0;
2598 feaAnalysis->componentNormaliztion = 0;
2599
2600 feaAnalysis->lanczosMode = 2; //Lanczos mode for calculating eigenvalues
2601
2602 if (feaAnalysis->lanczosType != NULL((void*)0)) EG_free(feaAnalysis->lanczosType);
2603 feaAnalysis->lanczosType = NULL((void*)0); //Lanczos matrix type (DPB, DGB)
2604
2605 // Trim
2606 feaAnalysis->numMachNumber = 0;
2607
2608 if (feaAnalysis->machNumber != NULL((void*)0)) EG_free(feaAnalysis->machNumber);
2609 feaAnalysis->machNumber = NULL((void*)0); // Mach number
2610
2611 //feaAnalysis->machNumber = 0.0; // Mach number
2612 feaAnalysis->dynamicPressure = 0.0; // Dynamic pressure
2613 feaAnalysis->density = 0.0; // Density
2614 if (feaAnalysis->aeroSymmetryXY != NULL((void*)0)) EG_free(feaAnalysis->aeroSymmetryXY);
2615 if (feaAnalysis->aeroSymmetryXZ != NULL((void*)0)) EG_free(feaAnalysis->aeroSymmetryXZ);
2616
2617 if (feaAnalysis->rigidVariable != NULL((void*)0)) {
2618 status = string_freeArray(feaAnalysis->numRigidVariable, &feaAnalysis->rigidVariable);
2619 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
2620 }
2621
2622 feaAnalysis->numRigidVariable = 0; // Number of trim rigid trim variables
2623 feaAnalysis->rigidVariable = NULL((void*)0); // List of character labels identifying rigid trim variables, size=[numRigidVariables]
2624
2625 if (feaAnalysis->rigidConstraint != NULL((void*)0)) {
2626 status = string_freeArray(feaAnalysis->numRigidConstraint, &feaAnalysis->rigidConstraint);
2627 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
2628 }
2629
2630 feaAnalysis->numRigidConstraint = 0; // Number of rigid trim constrained variables
2631 feaAnalysis->rigidConstraint = NULL((void*)0); // List of character labels identifying rigid constrained trim variables, size=[numRigidConstraint]
2632
2633 if (feaAnalysis->magRigidConstraint != NULL((void*)0)) EG_free(feaAnalysis->magRigidConstraint);
2634 feaAnalysis->magRigidConstraint = NULL((void*)0); // Magnitude of rigid constrained trim variables, size=[numRigidConstraint]
2635
2636 if (feaAnalysis->controlConstraint != NULL((void*)0)) {
2637 status = string_freeArray(feaAnalysis->numControlConstraint, &feaAnalysis->controlConstraint);
2638 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
2639 }
2640
2641 feaAnalysis->numControlConstraint = 0; // Number of control surface constrained variables
2642 feaAnalysis->controlConstraint = NULL((void*)0); // List of character labels identifying control surfaces to be constrained trim variables, size=[numControlConstraint]
2643
2644 EG_free(feaAnalysis->magControlConstraint);
2645 feaAnalysis->magControlConstraint = NULL((void*)0); // Magnitude of control surface constrained variables, size=[numControlConstraint]
2646
2647 // Flutter
2648 feaAnalysis->numReducedFreq = 0;
2649 EG_free(feaAnalysis->reducedFreq);
2650 feaAnalysis->reducedFreq = NULL((void*)0);
2651
2652 feaAnalysis->numFlutterVel = 0;
2653 EG_free(feaAnalysis->flutterVel);
2654 feaAnalysis->flutterVel = NULL((void*)0);
2655
2656 feaAnalysis->flutterConvergenceParam = 0.0;
2657
2658 feaAnalysis->visualFlutter = (int) false0;
2659
2660 return CAPS_SUCCESS0;
2661}
2662
2663// Initiate (0 out all values and NULL all pointers) of feaLoad in the feaLoadStruct structure format
2664int initiate_feaLoadStruct(feaLoadStruct *feaLoad) {
2665
2666 feaLoad->name = NULL((void*)0); // Load name
2667
2668 feaLoad->loadType = UnknownLoad; // Load type
2669
2670 feaLoad->loadID = 0; // ID number of load
2671
2672 feaLoad->loadScaleFactor = 1; // Scale factor for when combining loads
2673
2674 // Concentrated force at a grid point
2675 feaLoad->numGridID = 0; // Number of grid IDs in grid ID set
2676 feaLoad->gridIDSet = NULL((void*)0); // List of grid IDs to apply the constraint to. size = [numGridID]
2677 feaLoad->coordSystemID= 0; // Component number of coordinate system in which force vector is specified
2678
2679 feaLoad->forceScaleFactor= 0.0; // Overall scale factor for the force
2680 feaLoad->directionVector[0] = 0.0; // [0]-x, [1]-y, [2]-z components of the force vector
2681 feaLoad->directionVector[1] = 0.0;
2682 feaLoad->directionVector[2] = 0.0;
2683
2684 // Concentrated moment at a grid point (also uses coordSystemID and directionVector)
2685 feaLoad->momentScaleFactor= 0.0; // Overall scale factor for the moment
2686
2687 // Gravitational load (also uses coordSystemID and directionVector)
2688 feaLoad->gravityAcceleration= 0.0; // Gravitational acceleration
2689
2690 // Pressure load
2691 feaLoad->pressureForce= 0.0; // Pressure value
2692 feaLoad->pressureDistributeForce[0] = 0.0; // Pressure load at a specified grid location in the element
2693 feaLoad->pressureDistributeForce[1] = 0.0;
2694 feaLoad->pressureDistributeForce[2] = 0.0;
2695 feaLoad->pressureDistributeForce[3] = 0.0;
2696
2697 feaLoad->pressureMultiDistributeForce = NULL((void*)0); // Unique pressure load at a specified grid location for
2698 // each element in elementIDSet size = [numElementID][4] - used in type PressureExternal
2699 // where the pressure force is being provided by an external source (i.e. data transfer)
2700
2701 feaLoad->numElementID = 0; // Number of elements IDs in element ID set
2702 feaLoad->elementIDSet = NULL((void*)0); // List element IDs in which to apply the load. size = [numElementID]
2703
2704 // Rotational velocity (also uses coordSystemID and directionVector)
2705 feaLoad->angularVelScaleFactor = 0.0; // Overall scale factor for the angular velocity
2706 feaLoad->angularAccScaleFactor = 0.0; // Overall scale factor for the angular acceleration
2707
2708 // Thermal load - the temperature at a grid point - use gridIDSet
2709 feaLoad->temperature = 0.0; // Temperature value
2710 feaLoad->temperatureDefault = 0.0; // Default temperature of grid point explicitly not used
2711
2712 feaLoad->temperatureMultiDistribute = NULL((void*)0);
2713
2714 return CAPS_SUCCESS0;
2715}
2716
2717// Copy feaLoad in the feaLoadStruct structure format
2718// assumes that copy has been initialized with initiate_feaLoadStruct
2719int copy_feaLoadStruct(void *aimInfo, feaLoadStruct *feaLoad, feaLoadStruct *copy) {
2720
2721 int status = CAPS_SUCCESS0;
2722 int i;
2723
2724 if (feaLoad->name != NULL((void*)0)) {
2725 AIM_STRDUP(copy->name, feaLoad->name, aimInfo, status){ if (copy->name != ((void*)0)) { status = -4; aim_status(
aimInfo, status, "feaUtils.c", 2725, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "copy->name"); goto cleanup; } copy->name = EG_strdup
(feaLoad->name); if (copy->name == ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 2725, __func__
, 2, "AIM_STRDUP: %s %s", "copy->name", feaLoad->name);
goto cleanup; } }
; // Load name
2726 }
2727
2728 copy->loadType = feaLoad->loadType; // Load type
2729
2730 copy->loadID = feaLoad->loadID; // ID number of load
2731
2732 copy->loadScaleFactor = feaLoad->loadScaleFactor; // Scale factor for when combining loads
2733
2734 // Concentrated force at a grid point
2735 copy->numGridID = feaLoad->numGridID; // Number of grid IDs in grid ID set
2736 // List of grid IDs to apply the constraint to
2737 AIM_ALLOC(copy->gridIDSet, feaLoad->numGridID, int, aimInfo, status){ if (copy->gridIDSet != ((void*)0)) { status = -4; aim_status
(aimInfo, status, "feaUtils.c", 2737, __func__, 1, "AIM_ALLOC: %s != NULL"
, "copy->gridIDSet"); goto cleanup; } size_t memorysize = feaLoad
->numGridID; copy->gridIDSet = (int *) EG_alloc(memorysize
*sizeof(int)); if (copy->gridIDSet == ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 2737, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "copy->gridIDSet", memorysize
, "int"); goto cleanup; } }
;
2738 for (i = 0; i < feaLoad->numGridID; i++)
2739 copy->gridIDSet[i] = feaLoad->gridIDSet[i];
2740
2741 copy->coordSystemID = feaLoad->coordSystemID; // Component number of coordinate system in which force vector is specified
2742 copy->forceScaleFactor = feaLoad->forceScaleFactor; // Overall scale factor for the force
2743 copy->directionVector[0] = feaLoad->directionVector[0]; // [0]-x, [1]-y, [2]-z components of the force vector
2744 copy->directionVector[1] = feaLoad->directionVector[1];
2745 copy->directionVector[2] = feaLoad->directionVector[2];
2746
2747 // Concentrated moment at a grid pofeaLoad->(also uses coordSystemID and directionVector)
2748 copy->momentScaleFactor = feaLoad->momentScaleFactor; // Overall scale factor for the moment
2749
2750 // Gravitational load (also uses coordSystemID and directionVector)
2751 copy->gravityAcceleration = feaLoad->gravityAcceleration; // Gravitational acceleration
2752
2753 // Pressure load
2754 copy->pressureForce = feaLoad->pressureForce; // Pressure value
2755
2756 copy->pressureDistributeForce[0] = feaLoad->pressureDistributeForce[0]; // Pressure load at a specified grid location in the element
2757 copy->pressureDistributeForce[1] = feaLoad->pressureDistributeForce[1];
2758 copy->pressureDistributeForce[2] = feaLoad->pressureDistributeForce[2];
2759 copy->pressureDistributeForce[3] = feaLoad->pressureDistributeForce[3];
2760
2761 // Unique pressure load at a specified grid location for
2762 //each element in elementIDSet size = [4*numElementID]- used in type PressureExternal
2763 if (feaLoad->pressureMultiDistributeForce != NULL((void*)0)) {
2764 AIM_ALLOC(copy->pressureMultiDistributeForce, feaLoad->numElementID, double, aimInfo, status){ if (copy->pressureMultiDistributeForce != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 2764, __func__
, 1, "AIM_ALLOC: %s != NULL", "copy->pressureMultiDistributeForce"
); goto cleanup; } size_t memorysize = feaLoad->numElementID
; copy->pressureMultiDistributeForce = (double *) EG_alloc
(memorysize*sizeof(double)); if (copy->pressureMultiDistributeForce
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 2764, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->pressureMultiDistributeForce"
, memorysize, "double"); goto cleanup; } }
;
2765 for (i = 0; i < 4*feaLoad->numElementID; i++)
2766 copy->pressureMultiDistributeForce[i] = feaLoad->pressureMultiDistributeForce[i];
2767 } else {
2768 copy->pressureMultiDistributeForce = NULL((void*)0);
2769 }
2770
2771 copy->numElementID = feaLoad->numElementID; // Number of elements IDs in element ID set
2772 AIM_ALLOC(copy->elementIDSet, feaLoad->numElementID, int, aimInfo, status){ if (copy->elementIDSet != ((void*)0)) { status = -4; aim_status
(aimInfo, status, "feaUtils.c", 2772, __func__, 1, "AIM_ALLOC: %s != NULL"
, "copy->elementIDSet"); goto cleanup; } size_t memorysize
= feaLoad->numElementID; copy->elementIDSet = (int *) EG_alloc
(memorysize*sizeof(int)); if (copy->elementIDSet == ((void
*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 2772, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->elementIDSet"
, memorysize, "int"); goto cleanup; } }
; // List element IDs in which to apply the load
2773 for (i = 0; i < feaLoad->numElementID; i++)
2774 copy->elementIDSet[i] = feaLoad->elementIDSet[i];
2775
2776 // Rotational velocity (also uses coordSystemID and directionVector)
2777 copy->angularVelScaleFactor = feaLoad->angularVelScaleFactor; // Overall scale factor for the angular velocity
2778 copy->angularAccScaleFactor = feaLoad->angularAccScaleFactor; // Overall scale factor for the angular acceleration
2779
2780 // Thermal load - the temperature at a grid point - use gridIDSet
2781 copy->temperature = feaLoad->temperature; // Temperature value
2782 copy->temperatureDefault = feaLoad->temperatureDefault; // Default temperature of grid point explicitly not used
2783
2784 if (feaLoad->temperatureMultiDistribute != NULL((void*)0)) {
2785 AIM_ALLOC(copy->temperatureMultiDistribute, feaLoad->numGridID, double, aimInfo, status){ if (copy->temperatureMultiDistribute != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 2785, __func__
, 1, "AIM_ALLOC: %s != NULL", "copy->temperatureMultiDistribute"
); goto cleanup; } size_t memorysize = feaLoad->numGridID;
copy->temperatureMultiDistribute = (double *) EG_alloc(memorysize
*sizeof(double)); if (copy->temperatureMultiDistribute == (
(void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 2785, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->temperatureMultiDistribute"
, memorysize, "double"); goto cleanup; } }
;
2786 for (i = 0; i < feaLoad->numGridID; i++)
2787 copy->temperatureMultiDistribute[i] = feaLoad->temperatureMultiDistribute[i];
2788 } else {
2789 copy->temperatureMultiDistribute = NULL((void*)0);
2790 }
2791
2792cleanup:
2793 return status;
2794}
2795
2796// Destroy (0 out all values and NULL all pointers) of feaLoad in the feaLoadStruct structure format
2797int destroy_feaLoadStruct(feaLoadStruct *feaLoad) {
2798
2799 AIM_FREE(feaLoad->name){ EG_free(feaLoad->name); feaLoad->name = ((void*)0); }; // Load name
2800
2801 feaLoad->loadType = UnknownLoad; // Load type
2802
2803 feaLoad->loadID = 0; // ID number of load
2804
2805 feaLoad->loadScaleFactor = 1; // Scale factor for when combining loads
2806
2807 // Concentrated force at a grid point
2808 feaLoad->numGridID = 0; // Number of grid IDs in grid ID set
2809 AIM_FREE(feaLoad->gridIDSet){ EG_free(feaLoad->gridIDSet); feaLoad->gridIDSet = ((void
*)0); }
; // List of grid IDs to apply the constraint to
2810
2811 feaLoad->coordSystemID= 0; // Component number of coordinate system in which force vector is specified
2812 feaLoad->forceScaleFactor= 0; // Overall scale factor for the force
2813 feaLoad->directionVector[0] = 0; // [0]-x, [1]-y, [2]-z components of the force vector
2814 feaLoad->directionVector[1] = 0;
2815 feaLoad->directionVector[2] = 0;
2816
2817 // Concentrated moment at a grid pofeaLoad->(also uses coordSystemID and directionVector)
2818 feaLoad->momentScaleFactor= 0; // Overall scale factor for the moment
2819
2820 // Gravitational load (also uses coordSystemID and directionVector)
2821 feaLoad->gravityAcceleration= 0; // Gravitational acceleration
2822
2823 // Pressure load
2824 feaLoad->pressureForce= 0; // Pressure value
2825
2826 feaLoad->pressureDistributeForce[0] = 0; // Pressure load at a specified grid location in the element
2827 feaLoad->pressureDistributeForce[1] = 0;
2828 feaLoad->pressureDistributeForce[2] = 0;
2829 feaLoad->pressureDistributeForce[3] = 0;
2830
2831 // Unique pressure load at a specified grid location for
2832 //each element in elementIDSet size = [4*numElementID]- used in type PressureExternal
2833 AIM_FREE(feaLoad->pressureMultiDistributeForce){ EG_free(feaLoad->pressureMultiDistributeForce); feaLoad->
pressureMultiDistributeForce = ((void*)0); }
;
2834
2835
2836 feaLoad->numElementID = 0; // Number of elements IDs in element ID set
2837 AIM_FREE(feaLoad->elementIDSet){ EG_free(feaLoad->elementIDSet); feaLoad->elementIDSet
= ((void*)0); }
; // List element IDs in which to apply the load
2838
2839 // Rotational velocity (also uses coordSystemID and directionVector)
2840 feaLoad->angularVelScaleFactor = 0.0; // Overall scale factor for the angular velocity
2841 feaLoad->angularAccScaleFactor = 0.0; // Overall scale factor for the angular acceleration
2842
2843 // Thermal load - the temperature at a grid point - use gridIDSet
2844 feaLoad->temperature = 0.0; // Temperature value
2845 feaLoad->temperatureDefault = 0.0; // Default temperature of grid point explicitly not used
2846
2847 AIM_FREE(feaLoad->temperatureMultiDistribute){ EG_free(feaLoad->temperatureMultiDistribute); feaLoad->
temperatureMultiDistribute = ((void*)0); }
;
2848
2849 return CAPS_SUCCESS0;
2850}
2851
2852// Initiate (0 out all values and NULL all pointers) of feaDesignVariable in the feaDesignVariableStruct structure format
2853int initiate_feaDesignVariableStruct(feaDesignVariableStruct *feaDesignVariable) {
2854
2855 feaDesignVariable->name = NULL((void*)0);
2856
2857 feaDesignVariable->designVariableID = 0; // ID number of design variable
2858
2859
2860 feaDesignVariable->initialValue = 0.0; // Initial value of design variable
2861 feaDesignVariable->lowerBound = 0.0; // Lower bounds of variable
2862 feaDesignVariable->upperBound = 0.0; // Upper bounds of variable
2863 feaDesignVariable->maxDelta= 0.0; // Move limit for design variable
2864
2865 feaDesignVariable->numDiscreteValue = 0; // Number of discrete values that a design variable can assume
2866
2867 feaDesignVariable->discreteValue = NULL((void*)0); // List of discrete values that a design variable can assume;
2868
2869 feaDesignVariable->numIndependVariable = 0; // Number of independent variables this variables depends on
2870 feaDesignVariable->independVariable = NULL((void*)0); // List of independent variable names, size[numIndependVariable]
2871 feaDesignVariable->independVariableID = NULL((void*)0);// List of independent variable designVariableIDs, size[numIndependVariable]
2872 feaDesignVariable->independVariableWeight = NULL((void*)0); // List of independent variable weights, size[numIndependVariable]
2873
2874 feaDesignVariable->variableWeight[0] = 0.0; // Weight to apply to if variable is dependent
2875 feaDesignVariable->variableWeight[1] = 0.0;
2876
2877 feaDesignVariable->numRelation = 0;
2878 feaDesignVariable->relationSet = NULL((void*)0);
2879
2880 return CAPS_SUCCESS0;
2881}
2882
2883// Initiate (0 out all values and NULL all pointers) of feaDesignVariable in the feaDesignVariableStruct structure format
2884int destroy_feaDesignVariableStruct(feaDesignVariableStruct *feaDesignVariable) {
2885
2886 if (feaDesignVariable->name != NULL((void*)0)) EG_free(feaDesignVariable->name);
2887 feaDesignVariable->name = NULL((void*)0);
2888
2889 feaDesignVariable->designVariableID = 0; // ID number of design variable
2890
2891 feaDesignVariable->initialValue = 0.0; // Initial value of design variable
2892 feaDesignVariable->lowerBound = 0.0; // Lower bounds of variable
2893 feaDesignVariable->upperBound = 0.0; // Upper bounds of variable
2894 feaDesignVariable->maxDelta= 0.0; // Move limit for design variable
2895
2896 feaDesignVariable->numDiscreteValue = 0; // Number of discrete values that a design variable can assume;
2897 if (feaDesignVariable->discreteValue != NULL((void*)0)) EG_free(feaDesignVariable->discreteValue);
2898 feaDesignVariable->discreteValue = NULL((void*)0); // List of discrete values that a design variable can assume;
2899
2900 (void) string_freeArray(feaDesignVariable->numIndependVariable, &feaDesignVariable->independVariable);
2901 feaDesignVariable->independVariable = NULL((void*)0); // List of independent variable names, size[numIndependVariable]
2902
2903 feaDesignVariable->numIndependVariable = 0; // Number of independent variables this variables depends on
2904
2905 if (feaDesignVariable->independVariableID != NULL((void*)0)) EG_free(feaDesignVariable->independVariableID);
2906 feaDesignVariable->independVariableID = NULL((void*)0);// List of independent variable designVariableIDs
2907
2908 if (feaDesignVariable->independVariableWeight != NULL((void*)0)) EG_free(feaDesignVariable->independVariableWeight);
2909 feaDesignVariable->independVariableWeight = NULL((void*)0); // List of independent variable weights, size[numIndependVariable]
2910
2911 feaDesignVariable->variableWeight[0] = 0.0; // Weight to apply to if variable is dependent
2912 feaDesignVariable->variableWeight[1] = 0.0;
2913
2914 feaDesignVariable->numRelation = 0;
2915 if (feaDesignVariable->relationSet != NULL((void*)0)) EG_free(feaDesignVariable->relationSet);
2916
2917 return CAPS_SUCCESS0;
2918
2919}
2920
2921// Initiate (0 out all values and NULL all pointers) of feaDesignConstraint in the feaDesignConstraintStruct structure format
2922int initiate_feaDesignConstraintStruct(feaDesignConstraintStruct *feaDesignConstraint) {
2923
2924 feaDesignConstraint->name = NULL((void*)0);
2925
2926 feaDesignConstraint->designConstraintID = 0; // ID number of design constraint
2927
2928 feaDesignConstraint->designConstraintType = UnknownDesignCon;
2929
2930 feaDesignConstraint->responseType = NULL((void*)0); // Response type options for DRESP1 Entry
2931
2932 feaDesignConstraint->lowerBound = 0.0; // Lower bounds of design response
2933 feaDesignConstraint->upperBound = 0.0; // Upper bounds of design response
2934
2935 feaDesignConstraint->numPropertyID = 0; // Number of property ID to apply the design variable to
2936 feaDesignConstraint->propertySetID = NULL((void*)0); // List of property IDs
2937 feaDesignConstraint->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
2938
2939 feaDesignConstraint->fieldPosition = 0; // Position in card to apply design variable to
2940 feaDesignConstraint->fieldName = NULL((void*)0); // Name of property/material to apply design variable to
2941
2942 feaDesignConstraint->velocityType = NULL((void*)0);
2943 feaDesignConstraint->scalingFactor = 0.0;
2944
2945 feaDesignConstraint->numVelocity = 0;
2946 feaDesignConstraint->velocity = NULL((void*)0);
2947
2948 feaDesignConstraint->numDamping = 0;
2949 feaDesignConstraint->damping = NULL((void*)0);
2950
2951 return CAPS_SUCCESS0;
2952}
2953
2954// Destroy (0 out all values and NULL all pointers) of feaDesignConstraint in the feaDesignConstraintStruct structure format
2955int destroy_feaDesignConstraintStruct(feaDesignConstraintStruct *feaDesignConstraint) {
2956
2957 if (feaDesignConstraint->name != NULL((void*)0)) EG_free(feaDesignConstraint->name);
2958 feaDesignConstraint->name = NULL((void*)0);
2959
2960 feaDesignConstraint->designConstraintID = 0; // ID number of design constraint
2961
2962 feaDesignConstraint->designConstraintType = UnknownDesignCon;
2963
2964 if (feaDesignConstraint->responseType != NULL((void*)0)) EG_free(feaDesignConstraint->responseType);
2965 feaDesignConstraint->responseType = NULL((void*)0); // Response type options for DRESP1 Entry
2966
2967 feaDesignConstraint->lowerBound = 0.0; // Lower bounds of design response
2968 feaDesignConstraint->upperBound = 0.0; // Upper bounds of design response
2969
2970 feaDesignConstraint->numPropertyID = 0; // Number of property ID to apply the design variable to
2971
2972 if (feaDesignConstraint->propertySetID != NULL((void*)0)) EG_free(feaDesignConstraint->propertySetID);
2973 feaDesignConstraint->propertySetID = NULL((void*)0); // List of property IDs
2974
2975 if (feaDesignConstraint->propertySetType != NULL((void*)0)) EG_free(feaDesignConstraint->propertySetType);
2976 feaDesignConstraint->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
2977
2978 feaDesignConstraint->fieldPosition = 0; // Position in card to apply design variable to
2979 if (feaDesignConstraint->fieldName != NULL((void*)0)) EG_free(feaDesignConstraint->fieldName);
2980 feaDesignConstraint->fieldName = NULL((void*)0); // Name of property/material to apply design variable to
2981
2982 if (feaDesignConstraint->velocityType != NULL((void*)0)) EG_free(feaDesignConstraint->velocityType);
2983 feaDesignConstraint->velocityType = NULL((void*)0);
2984 feaDesignConstraint->scalingFactor = 0.0;
2985
2986 if (feaDesignConstraint->velocity != NULL((void*)0)) EG_free(feaDesignConstraint->velocity);
2987 feaDesignConstraint->numVelocity = 0;
2988 feaDesignConstraint->velocity = NULL((void*)0);
2989
2990 if (feaDesignConstraint->damping != NULL((void*)0)) EG_free(feaDesignConstraint->damping);
2991 feaDesignConstraint->numDamping = 0;
2992 feaDesignConstraint->damping = NULL((void*)0);
2993
2994 return CAPS_SUCCESS0;
2995
2996}
2997
2998// Initiate (0 out all values and NULL all pointers) of feaOptimizationControl in the feaOptimizationControlStruct structure format
2999int initiate_feaOptimizationControlStruct(feaOptimizationControlStruct *feaOptimizationControl) {
3000
3001 feaOptimizationControl->fullyStressedDesign = 0; // ASTROS specific - fully stressed design number of iterations
3002 feaOptimizationControl->mathProgramming = 0; // Math programming number of iteratinons
3003 feaOptimizationControl->maxIter = 0; // Maximum number of optimization iterations
3004 feaOptimizationControl->constraintRetention = 0.0; // Constraint retention factor
3005 feaOptimizationControl->eps = 0.0; // A different constraint retention factor?
3006 feaOptimizationControl->moveLimit = 0.0; // Move limit
3007
3008 return CAPS_SUCCESS0;
3009}
3010
3011// Destroy (0 out all values and NULL all pointers) of feaOptimizationControl in the feaOptimizationControlStruct structure format
3012int destroy_feaOptimzationControlStruct(feaOptimizationControlStruct *feaOptimizationControl) {
3013
3014 feaOptimizationControl->fullyStressedDesign = 0; // ASTROS specific - fully stressed design number of iterations
3015 feaOptimizationControl->mathProgramming = 0; // Math programming number of iteratinons
3016 feaOptimizationControl->maxIter = 0; // Maximum number of optimization iterations
3017 feaOptimizationControl->constraintRetention = 0.0; // Constraint retention factor
3018 feaOptimizationControl->eps = 0.0; // A different constraint retention factor?
3019 feaOptimizationControl->moveLimit = 0.0; // Move limit
3020
3021 return CAPS_SUCCESS0;
3022}
3023
3024// Initiate (0 out all values and NULL all pointers) of feaCoordSystem in the feaCoordSystemStruct structure format
3025int initiate_feaCoordSystemStruct(feaCoordSystemStruct *feaCoordSystem) {
3026
3027 int i; // Indexing
3028
3029 feaCoordSystem->name = NULL((void*)0); // Coordinate system name
3030
3031 feaCoordSystem->coordSystemType = UnknownCoordSystem; // Coordinate system type
3032
3033 feaCoordSystem->coordSystemID = 0; // ID number of coordinate system
3034 feaCoordSystem->refCoordSystemID = 0; // ID of reference coordinate system
3035
3036 for (i = 0; i < 3; i++) {
3037 feaCoordSystem->origin[i] = 0; // x, y, and z coordinates for the origin
3038
3039 feaCoordSystem->normal1[i] = 0; // First normal direction
3040 feaCoordSystem->normal2[i] = 0; // Second normal direction
3041 feaCoordSystem->normal3[i] = 0; // Third normal direction - found from normal1 x normal2
3042 }
3043
3044 return CAPS_SUCCESS0;
3045}
3046
3047// Destroy (0 out all values and NULL all pointers) of feaCoordSystem in the feaCoordSystemStruct structure format
3048int destroy_feaCoordSystemStruct(feaCoordSystemStruct *feaCoordSystem) {
3049
3050 int i; // Indexing
3051
3052 if (feaCoordSystem->name != NULL((void*)0)) EG_free(feaCoordSystem->name);
3053 feaCoordSystem->name = NULL((void*)0); // Coordinate system name
3054
3055 feaCoordSystem->coordSystemType = UnknownCoordSystem; // Coordinate system type
3056
3057 feaCoordSystem->coordSystemID = 0; // ID number of coordinate system
3058 feaCoordSystem->refCoordSystemID = 0; // ID of reference coordinate system
3059
3060 for (i = 0; i < 3; i++) {
3061 feaCoordSystem->origin[i] = 0; // x, y, and z coordinates for the origin
3062
3063 feaCoordSystem->normal1[i] = 0; // First normal direction
3064 feaCoordSystem->normal2[i] = 0; // Second normal direction
3065 feaCoordSystem->normal3[i] = 0; // Third normal direction - found from normal1 x normal2
3066 }
3067
3068 return CAPS_SUCCESS0;
3069}
3070
3071// Initiate (0 out all values and NULL all pointers) of feaAero in the feaAeroStruct structure format
3072int initiate_feaAeroStruct(feaAeroStruct *feaAero) {
3073
3074 int status; // Function return status
3075
3076 feaAero->name = NULL((void*)0); // Coordinate system name
3077
3078 feaAero->surfaceID = 0; // Surface ID
3079 feaAero->coordSystemID = 0; // Coordinate system ID
3080
3081 feaAero->numGridID = 0; // Number of grid IDs in grid ID set for the spline
3082 feaAero->gridIDSet = NULL((void*)0); // List of grid IDs to apply spline to. size = [numGridID]
3083
3084 status = initiate_vlmSurfaceStruct(&feaAero->vlmSurface);
3085 if (status != CAPS_SUCCESS0) printf("Status %d during initiate_vlmSurfaceStruct\n", status);
3086
3087 return CAPS_SUCCESS0;
3088}
3089
3090// Destroy (0 out all values and NULL all pointers) of feaAero in the feaAeroStruct structure format
3091int destroy_feaAeroStruct(feaAeroStruct *feaAero) {
3092
3093 int status; // Function return status
3094
3095 if (feaAero->name != NULL((void*)0)) EG_free(feaAero->name);
3096 feaAero->name = NULL((void*)0); // Coordinate system name
3097
3098 feaAero->surfaceID = 0; // Surface ID
3099 feaAero->coordSystemID = 0; // Coordinate system ID
3100
3101 feaAero->numGridID = 0; // Number of grid IDs in grid ID set for the spline
3102
3103 if (feaAero->gridIDSet != NULL((void*)0)) EG_free(feaAero->gridIDSet);
3104 feaAero->gridIDSet = NULL((void*)0); // List of grid IDs to apply spline to. size = [numGridID]
3105
3106 status = destroy_vlmSurfaceStruct(&feaAero->vlmSurface);
3107 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_vlmSurfaceStruct\n", status);
3108
3109 return CAPS_SUCCESS0;
3110}
3111
3112// Initiate (0 out all values and NULL all pointers) of feaAeroRef in the feaAeroRefStruct structure format
3113int initiate_feaAeroRefStruct(feaAeroRefStruct *feaAeroRef) {
3114
3115 feaAeroRef->coordSystemID = 0; // Aerodynamic coordinate sytem id
3116 feaAeroRef->rigidMotionCoordSystemID = 0; // Reference coordinate system identification for rigid body motions.
3117
3118 feaAeroRef->refChord = 1.0; // Reference chord length. Reference span. (Real > 0.0)
3119 feaAeroRef->refSpan = 1.0; // Reference span
3120 feaAeroRef->refArea = 1.0; // Reference area
3121 feaAeroRef->refGridID = 0;
3122
3123 feaAeroRef->symmetryXZ = 0; // Symmetry key for the aero coordinate x-z plane. (Integer = +1 for symmetry, 0 for no symmetry,
3124 // and -1 for antisymmetry; Default = 0)
3125 feaAeroRef->symmetryXY = 0; // The symmetry key for the aero coordinate x-y plane can be used to simulate ground effects.
3126 // (Integer = +1 for antisymmetry, 0 for no symmetry, and -1 for symmetry; Default = 0)
3127 return CAPS_SUCCESS0;
3128}
3129
3130// Destroy (0 out all values and NULL all pointers) of feaAeroRef in the feaAeroRefStruct structure format
3131int destroy_feaAeroRefStruct(feaAeroRefStruct *feaAeroRef) {
3132
3133 feaAeroRef->coordSystemID = 0; // Aerodynamic coordinate sytem id
3134 feaAeroRef->rigidMotionCoordSystemID = 0; // Reference coordinate system identification for rigid body motions.
3135
3136 feaAeroRef->refChord = 0; // Reference chord length. Reference span. (Real > 0.0)
3137 feaAeroRef->refSpan = 0; // Reference span
3138 feaAeroRef->refArea = 0; // Reference area
3139 feaAeroRef->refGridID = 0;
3140
3141 feaAeroRef->symmetryXZ = 0; // Symmetry key for the aero coordinate x-z plane. (Integer = +1 for symmetry, 0 for no symmetry,
3142 // and -1 for antisymmetry; Default = 0)
3143 feaAeroRef->symmetryXY = 0; // The symmetry key for the aero coordinate x-y plane can be used to simulate ground effects.
3144 // (Integer = +1 for antisymmetry, 0 for no symmetry, and -1 for symmetry; Default = 0)
3145 return CAPS_SUCCESS0;
3146}
3147
3148// Initiate (0 out all values and NULL all pointers) of feaConnect in the feaConnectionStruct structure format
3149int initiate_feaConnectionStruct(feaConnectionStruct *feaConnect) {
3150
3151 feaConnect->name = NULL((void*)0); // Connection name
3152
3153 feaConnect->connectionID =0; // Connection ID
3154
3155 feaConnect->connectionType = UnknownConnection; // Connection type
3156
3157 feaConnect->elementID = 0;
3158
3159 // RBE2 - dependent degrees of freedom
3160 feaConnect->connectivity[0] = 0; // Grid IDs - 0 index = Independent grid ID, 1 index = Dependent grid ID
3161 feaConnect->connectivity[1] = 0;
3162 feaConnect->dofDependent = 0;
3163
3164 // Spring
3165 feaConnect->stiffnessConst = 0.0;
3166 feaConnect->componentNumberStart = 0;
3167 feaConnect->componentNumberEnd = 0;
3168 feaConnect->dampingConst = 0.0;
3169 feaConnect->stressCoeff = 0.0;
3170
3171 // Damper - see spring for additional entries
3172
3173 // Mass (scalar) - see spring for additional entries
3174 feaConnect->mass = 0.0;
3175
3176 // RBE3 - master/slave
3177 feaConnect->numMaster = 0;
3178 feaConnect->masterIDSet = NULL((void*)0); // Independent
3179 feaConnect->masterWeighting = NULL((void*)0);
3180 feaConnect->masterComponent = NULL((void*)0);
3181
3182 return CAPS_SUCCESS0;
3183}
3184
3185// Destroy (0 out all values and NULL all pointers) of feaConnect in the feaConnectionStruct structure format
3186int destroy_feaConnectionStruct(feaConnectionStruct *feaConnect) {
3187
3188 if (feaConnect->name != NULL((void*)0)) EG_free(feaConnect->name);
3189 feaConnect->name = NULL((void*)0); // Connection name
3190
3191 feaConnect->connectionID =0; // Connection ID
3192
3193 feaConnect->connectionType = UnknownConnection; // Connection type
3194
3195 feaConnect->elementID = 0;
3196
3197 // RBE2 - dependent degrees of freedom
3198 feaConnect->connectivity[0] = 0; // Grid IDs - 0 index = Independent grid ID, 1 index = Dependent grid ID
3199 feaConnect->connectivity[1] = 0;
3200 feaConnect->dofDependent = 0;
3201
3202 // Spring
3203 feaConnect->stiffnessConst = 0.0;
3204 feaConnect->componentNumberStart = 0;
3205 feaConnect->componentNumberEnd = 0;
3206 feaConnect->dampingConst = 0.0;
3207 feaConnect->stressCoeff = 0.0;
3208
3209 // Damper - see spring for additional entries
3210
3211 // Mass (scalar) - see spring for additional entries
3212 feaConnect->mass = 0.0;
3213
3214 // RBE3 - master/slave
3215 feaConnect->numMaster = 0;
3216 if (feaConnect->masterIDSet != NULL((void*)0)) EG_free(feaConnect->masterIDSet);
3217 feaConnect->masterIDSet = NULL((void*)0); // Independent
3218 if (feaConnect->masterWeighting != NULL((void*)0)) EG_free(feaConnect->masterWeighting);
3219 feaConnect->masterWeighting = NULL((void*)0);
3220 if (feaConnect->masterComponent != NULL((void*)0)) EG_free(feaConnect->masterComponent);
3221 feaConnect->masterComponent = NULL((void*)0);
3222
3223 return CAPS_SUCCESS0;
3224}
3225
3226int initiate_feaDesignEquationStruct(feaDesignEquationStruct *equation) {
3227
3228 if (equation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3229
3230 equation->equationID = 0;
3231 equation->name = NULL((void*)0);
3232 equation->equationArraySize = 0;
3233 equation->equationArray = NULL((void*)0);
3234
3235 return CAPS_SUCCESS0;
3236}
3237
3238int destroy_feaDesignEquationStruct(feaDesignEquationStruct *equation) {
3239
3240 int i;
3241
3242 if (equation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3243
3244 if (equation->name != NULL((void*)0)) EG_free(equation->name);
3245
3246 if (equation->equationArray != NULL((void*)0)) {
3247 for (i = 0; i < equation->equationArraySize; i++) {
3248 if (equation->equationArray[i] != NULL((void*)0)) {
3249 EG_free(equation->equationArray[i]);
3250 }
3251 }
3252 EG_free(equation->equationArray);
3253 }
3254
3255 return initiate_feaDesignEquationStruct(equation);
3256}
3257
3258int initiate_feaDesignResponseStruct(feaDesignResponseStruct *response) {
3259
3260 if (response == NULL((void*)0)) return CAPS_NULLVALUE-307;
3261
3262 response->responseID = 0;
3263
3264 response->name = NULL((void*)0);
3265
3266 response->responseType = NULL((void*)0);
3267 response->propertyType = NULL((void*)0);
3268
3269 response->region = 0;
3270
3271 response->component = 0; // Component number
3272 response->itemCode = 0; // Item code
3273 response->modeNumber = 0; // Mode number
3274
3275 response->lamina = 0; // Lamina number
3276 response->frequency = 0.0; // Frequency value
3277 response->time = 0.0; // Time value
3278 response->restraintFlag = 0; // Restraint flag
3279
3280 response->gridID = 0; // Grid ID
3281 response->propertyID = 0; // Property entry ID
3282
3283 return CAPS_SUCCESS0;
3284}
3285
3286int destroy_feaDesignResponseStruct(feaDesignResponseStruct *response) {
3287
3288 if (response == NULL((void*)0)) return CAPS_NULLVALUE-307;
3289
3290 if (response->name != NULL((void*)0)) EG_free(response->name);
3291
3292 if (response->responseType != NULL((void*)0)) EG_free(response->responseType);
3293 if (response->propertyType != NULL((void*)0)) EG_free(response->propertyType);
3294
3295 return initiate_feaDesignResponseStruct(response);
3296}
3297
3298int initiate_feaDesignEquationResponseStruct(feaDesignEquationResponseStruct* equationResponse) {
3299
3300 if (equationResponse == NULL((void*)0)) return CAPS_NULLVALUE-307;
3301
3302 equationResponse->equationResponseID = 0;
3303
3304 equationResponse->name = NULL((void*)0); // Name of the equation
3305
3306 equationResponse->equationName = NULL((void*)0);
3307
3308 equationResponse->region = 0; // Region identifier for constant screening
3309
3310 equationResponse->numDesignVariable = 0;
3311 equationResponse->designVariableNameSet = NULL((void*)0); // Design variable names, size = [numDesignVariable]
3312
3313 equationResponse->numConstant = 0;
3314 equationResponse->constantLabelSet = NULL((void*)0); // Labels of the table constants, size = [numConstant]
3315
3316 equationResponse->numResponse = 0;
3317 equationResponse->responseNameSet = NULL((void*)0); // Names of design sensitivity response quantities, size = [numResponse]
3318
3319 equationResponse->numGrid = 0;
3320 equationResponse->gridIDSet = NULL((void*)0); // Grid IDs, size = [numGrid]
3321 equationResponse->dofNumberSet = NULL((void*)0); // Degree of freedom numbers, size = [numGrid]
3322
3323 equationResponse->numEquationResponse = 0;
3324 equationResponse->equationResponseNameSet = NULL((void*)0); // Names of design sensitivity equation response quantities, size = [numEquationResponse]
3325
3326 return CAPS_SUCCESS0;
3327}
3328
3329int destroy_feaDesignEquationResponseStruct(feaDesignEquationResponseStruct* equationResponse) {
3330
3331 if (equationResponse == NULL((void*)0)) return CAPS_NULLVALUE-307;
3332
3333 if (equationResponse->name != NULL((void*)0)) EG_free(equationResponse->name);
3334
3335 if (equationResponse->equationName != NULL((void*)0)) EG_free(equationResponse->equationName);
3336
3337 if (equationResponse->designVariableNameSet != NULL((void*)0)) {
3338 string_freeArray(equationResponse->numDesignVariable, &equationResponse->designVariableNameSet);
3339 }
3340
3341 if (equationResponse->constantLabelSet != NULL((void*)0)) {
3342 string_freeArray(equationResponse->numConstant, &equationResponse->constantLabelSet);
3343 }
3344
3345 if (equationResponse->responseNameSet != NULL((void*)0)) {
3346 string_freeArray(equationResponse->numResponse, &equationResponse->responseNameSet);
3347 }
3348
3349 if (equationResponse->gridIDSet != NULL((void*)0)) EG_free(equationResponse->gridIDSet);
3350 if (equationResponse->dofNumberSet != NULL((void*)0)) EG_free(equationResponse->dofNumberSet);
3351
3352 if (equationResponse->equationResponseNameSet != NULL((void*)0)) {
3353 string_freeArray(equationResponse->numEquationResponse, &equationResponse->equationResponseNameSet);
3354 }
3355
3356 return initiate_feaDesignEquationResponseStruct(equationResponse);
3357}
3358
3359int initiate_feaDesignTableStruct(feaDesignTableStruct *table) {
3360
3361 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3362
3363 table->numConstant = 0;
3364 table->constantLabel = NULL((void*)0);
3365 table->constantValue = NULL((void*)0);
3366
3367 return CAPS_SUCCESS0;
3368}
3369
3370int destroy_feaDesignTableStruct(feaDesignTableStruct *table) {
3371
3372 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3373
3374 if (table->constantLabel != NULL((void*)0)) string_freeArray(table->numConstant, &table->constantLabel);
3375 if (table->constantValue != NULL((void*)0)) EG_free(table->constantValue);
3376
3377 return initiate_feaDesignTableStruct(table);
3378}
3379
3380
3381int initiate_feaDesignOptParamStruct(feaDesignOptParamStruct *table) {
3382
3383 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3384
3385 table->numParam = 0;
3386 table->paramLabel = NULL((void*)0);
3387 table->paramValue = NULL((void*)0);
3388 table->paramType = NULL((void*)0);
3389
3390 return CAPS_SUCCESS0;
3391}
3392
3393int destroy_feaDesignOptParamStruct(feaDesignOptParamStruct *table) {
3394
3395 int i;
3396
3397 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3398
3399 if (table->paramLabel != NULL((void*)0)) string_freeArray(table->numParam, &table->paramLabel);
3400
3401 if (table->paramValue != NULL((void*)0)) {
3402 for (i = 0; i < table->numParam; i++) {
3403 if (table->paramValue[i] != NULL((void*)0)) {
3404 EG_free(table->paramValue[i]);
3405 }
3406 }
3407 EG_free(table->paramValue);
3408 }
3409
3410 if (table->paramType != NULL((void*)0)) EG_free(table->paramType);
3411
3412 return initiate_feaDesignOptParamStruct(table);
3413}
3414
3415int initiate_feaDesignVariableRelationStruct(feaDesignVariableRelationStruct *relation) {
3416
3417 if (relation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3418
3419 relation->name = NULL((void*)0);
3420
3421 relation->componentType = 0;
3422
3423 relation->relationID = 0;
3424
3425 relation->numDesignVariable = 0;
3426 relation->designVariableNameSet = NULL((void*)0);
3427 relation->designVariableSet = NULL((void*)0);
3428
3429 relation->fieldPosition = 0;
3430 relation->fieldName = NULL((void*)0);
3431
3432 relation->constantRelationCoeff = 0.0;
3433 relation->linearRelationCoeff = NULL((void*)0);
3434
3435 relation->numMaterialID = 0; // Number of materials to apply the design variable to
3436 relation->materialSetID = NULL((void*)0); // List of materials IDs
3437 relation->materialSetType = NULL((void*)0); // List of materials types corresponding to the materialSetID
3438
3439 relation->numPropertyID = 0; // Number of property ID to apply the design variable to
3440 relation->propertySetID = NULL((void*)0); // List of property IDs
3441 relation->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
3442
3443 relation->numElementID = 0; // Number of element ID to apply the design variable to
3444 relation->elementSetID = NULL((void*)0); // List of element IDs
3445 relation->elementSetType = NULL((void*)0); // List of element types corresponding to the elementSetID
3446 relation->elementSetSubType = NULL((void*)0); // List of element subtypes correspoding to the elementSetID
3447
3448 return CAPS_SUCCESS0;
3449}
3450
3451int destroy_feaDesignVariableRelationStruct(feaDesignVariableRelationStruct *relation) {
3452
3453 if (relation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3454
3455 if (relation->designVariableNameSet != NULL((void*)0)) string_freeArray(relation->numDesignVariable, &relation->designVariableNameSet);
3456 if (relation->name != NULL((void*)0)) EG_free(relation->name);
3457 if (relation->designVariableSet != NULL((void*)0)) EG_free(relation->designVariableSet);
3458
3459 if (relation->fieldName != NULL((void*)0)) EG_free(relation->fieldName);
3460
3461 if (relation->linearRelationCoeff != NULL((void*)0)) EG_free(relation->linearRelationCoeff);
3462
3463 relation->numMaterialID = 0; // Number of materials to apply the design variable to
3464 if (relation->materialSetID != NULL((void*)0)) EG_free(relation->materialSetID);
3465 relation->materialSetID = NULL((void*)0); // List of materials IDs
3466
3467 if (relation->materialSetType != NULL((void*)0)) EG_free(relation->materialSetType);
3468 relation->materialSetType = NULL((void*)0); // List of materials types corresponding to the materialSetID
3469
3470 relation->numPropertyID = 0; // Number of property ID to apply the design variable to
3471 if (relation->propertySetID != NULL((void*)0)) EG_free(relation->propertySetID);
3472 relation->propertySetID = NULL((void*)0); // List of property IDs
3473
3474 if (relation->propertySetType != NULL((void*)0)) EG_free(relation->propertySetType);
3475 relation->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
3476
3477 relation->numElementID = 0; // Number of element ID to apply the design variable to
3478 if (relation->elementSetID != NULL((void*)0)) EG_free(relation->elementSetID);
3479 relation->elementSetID = NULL((void*)0); // List of element IDs
3480
3481 if (relation->elementSetType != NULL((void*)0)) EG_free(relation->elementSetType);
3482 relation->elementSetType = NULL((void*)0); // List of element types corresponding to the elementSetID
3483
3484 if (relation->elementSetSubType != NULL((void*)0)) EG_free(relation->elementSetSubType);
3485 relation->elementSetSubType = NULL((void*)0); // List of element subtypes correspoding to the elementSetID
3486
3487 return initiate_feaDesignVariableRelationStruct(relation);
3488}
3489
3490// Get the material properties from a capsTuple
3491int fea_getMaterial(void *aimInfo,
3492 int numMaterialTuple,
3493 capsTuple materialTuple[],
3494 feaUnitsStruct *feaUnits,
3495 int *numMaterial,
3496 feaMaterialStruct *feaMaterial[]) {
3497
3498 /*! \page feaMaterial FEA Material
3499 * Structure for the material tuple = ("Material Name", "Value").
3500 * "Material Name" defines the reference name for the material being specified.
3501 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringMaterial) or a single string keyword
3502 * (see Section \ref keyStringMaterial).
3503 */
3504
3505 int status; //Function return
3506
3507 int i; // Indexing
3508
3509 char *keyValue = NULL((void*)0);
3510 char *keyWord = NULL((void*)0);
3511
3512 // Destroy our material structures coming in if aren't 0 and NULL already
3513 if (*feaMaterial != NULL((void*)0)) {
3514 for (i = 0; i < *numMaterial; i++) {
3515 status = destroy_feaMaterialStruct(&(*feaMaterial)[i]);
3516 if (status != CAPS_SUCCESS0) return status;
3517 }
3518 }
3519 if (*feaMaterial != NULL((void*)0)) EG_free(*feaMaterial);
3520 *feaMaterial = NULL((void*)0);
3521 *numMaterial = 0;
3522
3523 printf("\nGetting FEA materials.......\n");
3524
3525 *numMaterial = numMaterialTuple;
3526 printf("\tNumber of materials - %d\n", *numMaterial);
3527
3528 if (*numMaterial > 0) {
3529 *feaMaterial = (feaMaterialStruct *) EG_alloc(*numMaterial * sizeof(feaMaterialStruct));
3530 if (*feaMaterial == NULL((void*)0)) return EGADS_MALLOC-4;
3531
3532 } else {
3533 printf("\tNumber of material values in input tuple is 0\n");
3534 return CAPS_NOTFOUND-303;
3535 }
3536
3537 for (i = 0; i < *numMaterial; i++) {
3538 status = initiate_feaMaterialStruct(&(*feaMaterial)[i]);
3539 if (status != CAPS_SUCCESS0) return status;
3540 }
3541
3542 for (i = 0; i < *numMaterial; i++) {
3543
3544 printf("\tMaterial name - %s\n", materialTuple[i].name);
3545
3546 (*feaMaterial)[i].name = (char *) EG_alloc(((strlen(materialTuple[i].name)) + 1)*sizeof(char));
3547 if ((*feaMaterial)[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
3548
3549 memcpy((*feaMaterial)[i].name, materialTuple[i].name, strlen(materialTuple[i].name)*sizeof(char));
3550 (*feaMaterial)[i].name[strlen(materialTuple[i].name)] = '\0';
3551
3552 (*feaMaterial)[i].materialID = i + 1;
3553
3554 // Do we have a json string?
3555 if (strncmp(materialTuple[i].value, "{", 1) == 0) {
3556 //printf("JSON String - %s\n", materialTuple[i].value);
3557
3558
3559 /*! \page feaMaterial
3560 * \section jsonStringMaterial JSON String Dictionary
3561 *
3562 * If "Value" is JSON string dictionary
3563 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS || MASSTRAN)
3564 * (e.g. "Value" = {"density": 7850, "youngModulus": 120000.0, "poissonRatio": 0.5, "materialType": "isotropic"})
3565 * \endif
3566 * the following keywords ( = default values) may be used:
3567 *
3568 * <ul>
3569 * <li> <B>materialType = "Isotropic"</B> </li> <br>
3570 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
3571 * Material property type. Options: Isotropic, Anisothotropic, Orthotropic, or Anisotropic.
3572 * \elseif MASSTRAN
3573 * Material property type. Options: Isotropic.
3574 * \endif
3575 * </ul>
3576 */
3577
3578 // Get material Type
3579 keyWord = "materialType";
3580 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3581 if (status == CAPS_SUCCESS0) {
3582 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3582, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3583
3584 //{UnknownMaterial, Isotropic, Anisothotropic, Orthotropic, Anisotropic}
3585 if (strcasecmp(keyValue, "\"Isotropic\"") == 0) (*feaMaterial)[i].materialType = Isotropic;
3586 else if (strcasecmp(keyValue, "\"Anisothotropic\"") == 0) (*feaMaterial)[i].materialType = Anisothotropic;
3587 else if (strcasecmp(keyValue, "\"Orthotropic\"") == 0) (*feaMaterial)[i].materialType = Orthotropic;
3588 else if (strcasecmp(keyValue, "\"Anisotropic\"") == 0) (*feaMaterial)[i].materialType = Anisotropic;
3589 else {
3590
3591 printf("\tUnrecognized \"%s\" specified (%s) for Material tuple %s, defaulting to \"Isotropic\"\n", keyWord,
3592 keyValue,
3593 materialTuple[i].name);
3594 (*feaMaterial)[i].materialType = Isotropic;
3595 }
3596
3597 } else {
3598
3599 printf("\tNo \"%s\" specified for Material tuple %s, defaulting to \"Isotropic\"\n", keyWord,
3600 materialTuple[i].name);
3601 (*feaMaterial)[i].materialType = Isotropic;
3602 }
3603 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3604
3605 //Fill up material properties
3606
3607 /*! \page feaMaterial
3608 *
3609 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS)
3610 * <ul>
3611 * <li> <B>youngModulus = 0.0</B> </li> <br>
3612 * Also known as the elastic modulus, defines the relationship between stress and strain.
3613 * Default if `shearModulus' and `poissonRatio' != 0, youngModulus = 2*(1+poissonRatio)*shearModulus
3614 * </ul>
3615 * \endif
3616 *
3617 */
3618 keyWord = "youngModulus";
3619 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3620 if (status == CAPS_SUCCESS0) {
3621 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3621, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3622 if ( feaUnits->pressure != NULL((void*)0) ) {
3623 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->pressure, &(*feaMaterial)[i].youngModulus);
3624 } else {
3625 status = string_toDouble(keyValue, &(*feaMaterial)[i].youngModulus);
3626 }
3627 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3627
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3628 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3629 }
3630
3631 /*! \page feaMaterial
3632 *
3633 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS)
3634 * <ul>
3635 * <li> <B>shearModulus = 0.0</B> </li> <br>
3636 * Also known as the modulus of rigidity, is defined as the ratio of shear stress to the shear strain.
3637 * Default if `youngModulus' and `poissonRatio' != 0, shearModulus = youngModulus/(2*(1+poissonRatio))
3638 * </ul>
3639 * \endif
3640 */
3641 keyWord = "shearModulus";
3642 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3643 if (status == CAPS_SUCCESS0) {
3644 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3644, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3645 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulus);
3646 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3646
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3647 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3648 }
3649
3650 /*! \page feaMaterial
3651 *
3652 *
3653 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS)
3654 * <ul>
3655 * <li> <B>poissonRatio = 0.0</B> </li> <br>
3656 * The fraction of expansion divided by the fraction of compression.
3657 * Default if `youngModulus' and `shearModulus' != 0, poissonRatio = (2*youngModulus/shearModulus) - 1
3658 * </ul>
3659 * \endif
3660 */
3661 keyWord = "poissonRatio";
3662 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3663 if (status == CAPS_SUCCESS0) {
3664 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3664, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3665 status = string_toDouble(keyValue, &(*feaMaterial)[i].poissonRatio);
3666 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3666
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3667 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3668 }
3669
3670 // Check Young's modulus, shear modulus, and Poisson's ratio
3671 if ( ((*feaMaterial)[i].youngModulus == 0 && (*feaMaterial)[i].poissonRatio == 0) ||
3672 ((*feaMaterial)[i].shearModulus == 0 && (*feaMaterial)[i].poissonRatio == 0) ||
3673 ((*feaMaterial)[i].youngModulus == 0 && (*feaMaterial)[i].shearModulus == 0) ) {
3674 // Do nothing
3675
3676 } else if ((*feaMaterial)[i].youngModulus == 0) {
3677 (*feaMaterial)[i].youngModulus = 2*(1+(*feaMaterial)[i].poissonRatio)*(*feaMaterial)[i].shearModulus;
3678 } else if ((*feaMaterial)[i].shearModulus == 0) {
3679 (*feaMaterial)[i].shearModulus = (*feaMaterial)[i].youngModulus/(2*(1+(*feaMaterial)[i].poissonRatio));
3680 } else if ((*feaMaterial)[i].poissonRatio == 0) {
3681 (*feaMaterial)[i].poissonRatio = (*feaMaterial)[i].youngModulus/(2*(*feaMaterial)[i].shearModulus) -1;
3682 }
3683
3684 /*! \page feaMaterial
3685 *
3686 *
3687 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || MASSTRAN)
3688 * <ul>
3689 * <li> <B>density = 0.0</B> </li> <br>
3690 * Density of the material.
3691 * </ul>
3692 * \endif
3693 */
3694 keyWord = "density";
3695 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3696 if (status == CAPS_SUCCESS0) {
3697 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3697, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3698 if ( feaUnits->densityVol != NULL((void*)0) ) {
3699 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->densityVol, &(*feaMaterial)[i].density);
3700 } else {
3701 status = string_toDouble(keyValue, &(*feaMaterial)[i].density);
3702 }
3703 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3703
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3704 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3705 }
3706
3707 /*! \page feaMaterial
3708 *
3709 * \if (MYSTRAN || NASTRAN || ASTROS)
3710 * <ul>
3711 * <li> <B>thermalExpCoeff = 0.0</B> </li> <br>
3712 * Thermal expansion coefficient of the material.
3713 * </ul>
3714 * \endif
3715 */
3716 keyWord = "thermalExpCoeff";
3717 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3718 if (status == CAPS_SUCCESS0) {
3719 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3719, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3720 status = string_toDouble(keyValue, &(*feaMaterial)[i].thermalExpCoeff);
3721 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3721
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3722 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3723 }
3724
3725 /*! \page feaMaterial
3726 *
3727 * \if (MYSTRAN || NASTRAN || ASTROS)
3728 * <ul>
3729 * <li> <B>thermalExpCoeffLateral = 0.0</B> </li> <br>
3730 * Thermal expansion coefficient of the material.
3731 * </ul>
3732 * \endif
3733 */
3734 keyWord = "thermalExpCoeffLateral";
3735 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3736 if (status == CAPS_SUCCESS0) {
3737 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3737, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3738 status = string_toDouble(keyValue, &(*feaMaterial)[i].thermalExpCoeffLateral);
3739 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3739
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3740 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3741 }
3742
3743 /*! \page feaMaterial
3744 *
3745 *
3746 * \if (MYSTRAN || NASTRAN || ASTROS)
3747 * <ul>
3748 * <li> <B>temperatureRef = 0.0</B> </li> <br>
3749 * Reference temperature for material properties.
3750 * </ul>
3751 * \endif
3752 */
3753 keyWord = "temperatureRef";
3754 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3755 if (status == CAPS_SUCCESS0) {
3756 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3756, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3757 status = string_toDouble(keyValue, &(*feaMaterial)[i].temperatureRef);
3758 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3758
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3759 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3760 }
3761
3762 /*! \page feaMaterial
3763 *
3764 * \if (MYSTRAN || NASTRAN || ASTROS)
3765 * <ul>
3766 * <li> <B>dampingCoeff = 0.0</B> </li> <br>
3767 * Damping coefficient for the material.
3768 * </ul>
3769 * \endif
3770 */
3771 keyWord = "dampingCoeff";
3772 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3773 if (status == CAPS_SUCCESS0) {
3774 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3774, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3775 status = string_toDouble(keyValue, &(*feaMaterial)[i].dampingCoeff);
3776 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3776
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3777 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3778 }
3779
3780 /*! \page feaMaterial
3781 *
3782 *
3783 * \if NASTRAN
3784 * <ul>
3785 * <li> <B>yieldAllow = 0.0</B> </li> <br>
3786 * Yield strength/allowable for the material.
3787 * </ul>
3788 * \endif
3789 */
3790 keyWord = "yieldAllow";
3791 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3792 if (status == CAPS_SUCCESS0) {
3793 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 3793, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
3794 status = string_toDouble(keyValue, &(*feaMaterial)[i].yieldAllow);
3795 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3795
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3796 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3797 }
3798
3799 /*! \page feaMaterial
3800 *
3801 *
3802 * \if NASTRAN
3803 * <ul>
3804 * <li> <B>tensionAllow = 0.0</B> </li> <br>
3805 * Tension allowable for the material.
3806 * </ul>
3807 * \endif
3808 */
3809 keyWord = "tensionAllow";
3810 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3811 if (status == CAPS_SUCCESS0) {
3812
3813 status = string_toDouble(keyValue, &(*feaMaterial)[i].tensionAllow);
3814 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3814
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3815 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3816 }
3817
3818 /*! \page feaMaterial
3819 *
3820 *
3821 * \if NASTRAN
3822 * <ul>
3823 * <li> <B>tensionAllowLateral = 0.0</B> </li> <br>
3824 * Lateral tension allowable for the material.
3825 * </ul>
3826 * \endif
3827 */
3828 keyWord = "tensionAllowLateral";
3829 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3830 if (status == CAPS_SUCCESS0) {
3831
3832 status = string_toDouble(keyValue, &(*feaMaterial)[i].tensionAllowLateral);
3833 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3833
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3834 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3835 }
3836
3837 /*! \page feaMaterial
3838 *
3839 * \if NASTRAN
3840 * <ul>
3841 * <li> <B>compressAllow = 0.0</B> </li> <br>
3842 * Compression allowable for the material.
3843 * </ul>
3844 * \endif
3845 */
3846 keyWord = "compressAllow";
3847 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3848 if (status == CAPS_SUCCESS0) {
3849
3850 status = string_toDouble(keyValue, &(*feaMaterial)[i].compressAllow);
3851 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3851
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3852 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3853 }
3854
3855 /*! \page feaMaterial
3856 *
3857 * \if NASTRAN
3858 * <ul>
3859 * <li> <B>compressAllowLateral = 0.0</B> </li> <br>
3860 * Lateral compression allowable for the material.
3861 * </ul>
3862 * \endif
3863 */
3864 keyWord = "compressAllowLateral";
3865 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3866 if (status == CAPS_SUCCESS0) {
3867
3868 status = string_toDouble(keyValue, &(*feaMaterial)[i].compressAllowLateral);
3869 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3869
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3870 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3871 }
3872
3873 /*! \page feaMaterial
3874 *
3875 * \if NASTRAN
3876 * <ul>
3877 * <li> <B>shearAllow = 0.0</B> </li> <br>
3878 * Shear allowable for the material.
3879 * </ul>
3880 * \endif
3881 */
3882 keyWord = "shearAllow";
3883 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3884 if (status == CAPS_SUCCESS0) {
3885
3886 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearAllow);
3887 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3887
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3888 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3889 }
3890
3891 /*! \page feaMaterial
3892 *
3893 * \if (NASTRAN)
3894 * <ul>
3895 * <li> <B>allowType = 0 </B> </li> <br>
3896 * This flag defines if the above allowables <c>compressAllow</c> etc. are defined in terms of stress (0) or strain (1). The default is stress (0).
3897 * </ul>
3898 * \endif
3899 */
3900 keyWord = "allowType";
3901 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3902 if (status == CAPS_SUCCESS0) {
3903 status = string_toInteger(keyValue, &(*feaMaterial)[i].allowType);
3904 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3904
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3905 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3906 }
3907
3908 /*! \page feaMaterial
3909 *
3910 * \if (MYSTRAN || NASTRAN || ABAQUS)
3911 * <ul>
3912 * <li> <B>youngModulusLateral = 0.0</B> </li> <br>
3913 * Elastic modulus in lateral direction for an orthotropic material
3914 * </ul>
3915 * \endif
3916 */
3917 keyWord = "youngModulusLateral";
3918 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3919 if (status == CAPS_SUCCESS0) {
3920
3921 status = string_toDouble(keyValue, &(*feaMaterial)[i].youngModulusLateral);
3922 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3922
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3923 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3924 }
3925
3926 /*! \page feaMaterial
3927 *
3928 * \if (MYSTRAN || NASTRAN || ABAQUS)
3929 * <ul>
3930 * <li> <B>shearModulusTrans1Z = 0.0</B> </li> <br>
3931 * Transverse shear modulus in the 1-Z plane for an orthotropic material
3932 * </ul>
3933 * \endif
3934 */
3935 keyWord = "shearModulusTrans1Z";
3936 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3937 if (status == CAPS_SUCCESS0) {
3938
3939 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulusTrans1Z);
3940 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3940
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3941 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3942 }
3943
3944 /*! \page feaMaterial
3945 *
3946 * \if (MYSTRAN || NASTRAN || ABAQUS)
3947 * <ul>
3948 * <li> <B>shearModulusTrans2Z = 0.0</B> </li> <br>
3949 * Transverse shear modulus in the 2-Z plane for an orthotropic material
3950 * </ul>
3951 * \endif
3952 */
3953 keyWord = "shearModulusTrans2Z";
3954 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3955 if (status == CAPS_SUCCESS0) {
3956
3957 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulusTrans2Z);
3958 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3958
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3959 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3960 }
3961
3962 /*! \page feaMaterial
3963 *
3964 * \if (TACS || NASTRAN || ABAQUS)
3965 * <ul>
3966 * <li> <B>kappa = 0.0</B> </li> <br>
3967 * Thermal conductivity for an isotropic solid
3968 * </ul>
3969 * \endif
3970 */
3971 keyWord = "kappa";
3972 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3973 if (status == CAPS_SUCCESS0) {
3974
3975 status = string_toDouble(keyValue, &(*feaMaterial)[i].kappa);
3976 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3976
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3977 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3978 }
3979
3980 /*! \page feaMaterial
3981 *
3982 * \if (TACS || NASTRAN || ABAQUS)
3983 * <ul>
3984 * <li> <B>specificHeat = 0.0</B> </li> <br>
3985 * Specific heat constant pressure (per unit mass) for an isotropic solid
3986 * </ul>
3987 * \endif
3988 */
3989 keyWord = "specificHeat";
3990 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3991 if (status == CAPS_SUCCESS0) {
3992
3993 status = string_toDouble(keyValue, &(*feaMaterial)[i].specificHeat);
3994 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3994
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3995 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3996 }
3997
3998 } else {
3999
4000 /*! \page feaMaterial
4001 * \section keyStringMaterial Single Value String
4002 *
4003 * If "Value" is a string, the string value may correspond to an entry in a predefined material lookup
4004 * table. NOT YET IMPLEMENTED!!!!
4005 *
4006 */
4007 // CALL material look up
4008 AIM_ERROR(aimInfo, "Material tuple value ('%s') is expected to be a JSON string", materialTuple[i].value){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4008, __func__
, "Material tuple value ('%s') is expected to be a JSON string"
, materialTuple[i].value); }
;
4009 status = CAPS_BADVALUE-311;
4010 goto cleanup;
4011 }
4012 }
4013
4014 printf("\tDone getting FEA materials\n");
4015 status = CAPS_SUCCESS0;
4016
4017cleanup:
4018 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4019
4020 return status;
4021}
4022
4023// Get the property properties from a capsTuple
4024int fea_getProperty(void *aimInfo,
4025 int numPropertyTuple,
4026 capsTuple propertyTuple[],
4027 mapAttrToIndexStruct *attrMap,
4028 feaUnitsStruct *feaUnits,
4029 feaProblemStruct *feaProblem) {
4030
4031 /*! \page feaProperty FEA Property
4032 * Structure for the property tuple = ("Property Name", "Value").
4033 * "Property Name" defines the reference <c>capsGroup</c> for the property being specified.
4034 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringProperty) or a single string keyword
4035 * (see Section \ref keyStringProperty).
4036 */
4037
4038 int status; //Function return
4039
4040 int i, j, matIndex; // Indexing
4041 int found; // Bool test function
4042
4043 int pidIndex; // Property identification index found in attribute map
4044
4045 int tempInteger;
4046
4047 char *keyValue = NULL((void*)0);
4048 char *keyWord = NULL((void*)0);
4049 char *tempString = NULL((void*)0);
4050 char **tempStringArray = NULL((void*)0);
4051
4052 // double tempDouble;
4053
4054 // Destroy our property structures coming in if aren't 0 and NULL already
4055 if (feaProblem->feaProperty != NULL((void*)0)) {
4056 for (i = 0; i < feaProblem->numProperty; i++) {
4057 status = destroy_feaPropertyStruct(&feaProblem->feaProperty[i]);
4058 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4058
, __func__, 0); goto cleanup; }
;
4059 }
4060 }
4061 AIM_FREE(feaProblem->feaProperty){ EG_free(feaProblem->feaProperty); feaProblem->feaProperty
= ((void*)0); }
;
4062 feaProblem->numProperty = 0;
4063
4064 printf("\nGetting FEA properties.......\n");
4065
4066 feaProblem->numProperty = numPropertyTuple;
4067 printf("\tNumber of properties - %d\n", feaProblem->numProperty);
4068
4069 if (feaProblem->numProperty > 0) {
4070
4071 feaProblem->feaProperty = (feaPropertyStruct *) EG_alloc(feaProblem->numProperty * sizeof(feaPropertyStruct));
4072 if (feaProblem->feaProperty == NULL((void*)0)) return EGADS_MALLOC-4;
4073
4074 } else {
4075 AIM_ERROR(aimInfo, "Number of property values in input tuple is 0\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4075, __func__
, "Number of property values in input tuple is 0\n"); }
;
4076 status = CAPS_NOTFOUND-303;
4077 goto cleanup;
4078 }
4079
4080 for (i = 0; i < feaProblem->numProperty; i++) {
4081 status = initiate_feaPropertyStruct(&feaProblem->feaProperty[i]);
4082 AIM_STATUS(aimInfo, status, "Unable to initiate feaProperty structure (number = %d)", i)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4082
, __func__, 2, "Unable to initiate feaProperty structure (number = %d)"
, i); goto cleanup; }
;
4083 }
4084
4085 for (i = 0; i < feaProblem->numProperty; i++) {
4086
4087 printf("\tProperty name - %s\n", propertyTuple[i].name);
4088
4089 // Set property name from tuple name
4090 AIM_STRDUP(feaProblem->feaProperty[i].name, propertyTuple[i].name, aimInfo, status){ if (feaProblem->feaProperty[i].name != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 4090, __func__
, 1, "AIM_STRDUP: %s != NULL!", "feaProblem->feaProperty[i].name"
); goto cleanup; } feaProblem->feaProperty[i].name = EG_strdup
(propertyTuple[i].name); if (feaProblem->feaProperty[i].name
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 4090, __func__, 2, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].name"
, propertyTuple[i].name); goto cleanup; } }
;
4091
4092 // Get to property ID number from the attribute map
4093 status = get_mapAttrToIndexIndex(attrMap, feaProblem->feaProperty[i].name, &pidIndex);
4094 if (status != CAPS_SUCCESS0) {
4095 AIM_ERROR(aimInfo, "Tuple name '%s' not found in attribute map of PIDS!!!!\n", feaProblem->feaProperty[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4095, __func__
, "Tuple name '%s' not found in attribute map of PIDS!!!!\n",
feaProblem->feaProperty[i].name); }
;
4096 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4097 goto cleanup;
4098 } else {
4099 feaProblem->feaProperty[i].propertyID = pidIndex;
4100 }
4101
4102 // Do we have a json string?
4103 if (strncmp(propertyTuple[i].value, "{", 1) == 0) {
4104 //printf("JSON String - %s\n",propertyTuple[i].value);
4105
4106 /*! \page feaProperty
4107 * \section jsonStringProperty JSON String Dictionary
4108 *
4109 * If "Value" is JSON string dictionary
4110 * \if (MYSTRAN || NASTRAN)
4111 * (e.g. "Value" = {"shearMembraneRatio": 0.83, "bendingInertiaRatio": 1.0, "membraneThickness": 0.2, "propertyType": "Shell"})
4112 * \endif
4113 * the following keywords ( = default values) may be used:
4114 *
4115 *
4116 * \if (MYSTRAN || NASTRAN)
4117 * <ul>
4118 * <li> <B>propertyType = No Default value</B> </li> <br>
4119 * Type of property to apply to a given capsGroup <c>Name</c>. Options: ConcentratedMass, Rod,
4120 * Bar, Shear, Shell, Composite, and Solid
4121 * </ul>
4122 * \elseif (MASSTRAN)
4123 * <ul>
4124 * <li> <B>propertyType = No Default value</B> </li> <br>
4125 * Type of property to apply to a given capsGroup <c>Name</c>. Options: ConcentratedMass, Shell
4126 * </ul>
4127 * \elseif ABAQUS
4128 *
4129 * Something else ....
4130 *
4131 * \elseif ASTROS
4132 * <ul>
4133 * <li> <B>propertyType = No Default value</B> </li> <br>
4134 * Type of property to apply to a give capsGroup <c>Name</c>. Options: ConcentratedMass, Rod,
4135 * Bar, Shear, Shell, Membrane, Composite, and Solid
4136 * </ul>
4137 * \endif
4138 *
4139 */
4140
4141 // Get property Type
4142 keyWord = "propertyType";
4143 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4144 if (status == CAPS_SUCCESS0) {
4145 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 4145, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
4146 //{UnknownProperty, ConcentratedMass Rod, Bar, Shear, Shell, Composite, Solid}
4147 if (strcasecmp(keyValue, "\"ConcentratedMass\"") == 0) feaProblem->feaProperty[i].propertyType = ConcentratedMass;
4148 else if (strcasecmp(keyValue, "\"Rod\"") == 0) feaProblem->feaProperty[i].propertyType = Rod;
4149 else if (strcasecmp(keyValue, "\"Bar\"") == 0) feaProblem->feaProperty[i].propertyType = Bar;
4150 else if (strcasecmp(keyValue, "\"Shear\"") == 0) feaProblem->feaProperty[i].propertyType = Shear;
4151 else if (strcasecmp(keyValue, "\"Shell\"") == 0) feaProblem->feaProperty[i].propertyType = Shell;
4152 else if (strcasecmp(keyValue, "\"Membrane\"") == 0) feaProblem->feaProperty[i].propertyType = Membrane;
4153 else if (strcasecmp(keyValue, "\"Composite\"") == 0) feaProblem->feaProperty[i].propertyType = Composite;
4154 else if (strcasecmp(keyValue, "\"Solid\"") == 0) feaProblem->feaProperty[i].propertyType = Solid;
4155 else {
4156 AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are "
"\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord
, keyValue, propertyTuple[i].name); }
4157 "\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are "
"\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord
, keyValue, propertyTuple[i].name); }
4158 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are "
"\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord
, keyValue, propertyTuple[i].name); }
4159 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are "
"\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord
, keyValue, propertyTuple[i].name); }
;
4160 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4161
4162 status = CAPS_NOTFOUND-303;
4163 goto cleanup;
4164 }
4165
4166 } else {
4167 AIM_ERROR(aimInfo, "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4169, __func__
, "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are "
"\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n"
, keyWord, propertyTuple[i].name); }
4168 "\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4169, __func__
, "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are "
"\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n"
, keyWord, propertyTuple[i].name); }
4169 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4169, __func__
, "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are "
"\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n"
, keyWord, propertyTuple[i].name); }
;
4170 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4171
4172 status = CAPS_NOTFOUND-303;
4173 goto cleanup;
4174 }
4175 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4176
4177 /*! \page feaProperty
4178 *
4179 * \if (MYSTRAN || NASTRAN)
4180 * <ul>
4181 * <li> <B>material = "Material Name" (\ref feaMaterial) </B> </li> <br>
4182 * "Material Name" from \ref feaMaterial to use for property. If no material is set the first material
4183 * created will be used
4184 * </ul>
4185 * \elseif ABAQUS
4186 *
4187 * Something else ....
4188 *
4189 * \elseif ASTROS
4190 * <ul>
4191 * <li> <B>material = `Material Name' (\ref feaMaterial) </B> </li> <br>
4192 * `Material Name' from \ref feaMaterial to use for property. If no material is set the first material
4193 * created will be used
4194 * </ul>
4195 * \endif
4196 */
4197 keyWord = "material";
4198 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4199 if (status == CAPS_SUCCESS0) {
4200
4201 found = (int) false0;
4202 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4203
4204 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4205 tempString = string_removeQuotation(keyValue);
4206 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 4206, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
4207
4208 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4209 feaProblem->feaProperty[i].materialID = feaProblem->feaMaterial[matIndex].materialID;
4210
4211 AIM_STRDUP(feaProblem->feaProperty[i].materialName, feaProblem->feaMaterial[matIndex].name, aimInfo, status){ if (feaProblem->feaProperty[i].materialName != ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 4211
, __func__, 1, "AIM_STRDUP: %s != NULL!", "feaProblem->feaProperty[i].materialName"
); goto cleanup; } feaProblem->feaProperty[i].materialName
= EG_strdup(feaProblem->feaMaterial[matIndex].name); if (
feaProblem->feaProperty[i].materialName == ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 4211, __func__
, 2, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].materialName"
, feaProblem->feaMaterial[matIndex].name); goto cleanup; }
}
;
4212 feaProblem->feaProperty[i].materialName[strlen(feaProblem->feaMaterial[matIndex].name)] = '\0';
4213
4214 found = (int) true1;
4215 break;
4216 }
4217 }
4218
4219 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4220
4221 if (found == (int) false0) {
4222 AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4224, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4223 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4224, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4224 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4224, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
;
4225 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4226 status = CAPS_NOTFOUND-303;
4227 goto cleanup;
4228 }
4229
4230 } else {
4231
4232 if (feaProblem->feaProperty[i].propertyType != ConcentratedMass &&
4233 feaProblem->feaProperty[i].propertyType != Composite) {
4234 printf("\tNo \"%s\" specified for Property tuple %s, defaulting to an index of 1\n", keyWord,
4235 propertyTuple[i].name);
4236 }
4237
4238 feaProblem->feaProperty[i].materialID = 1;
4239 if (feaProblem->numMaterial > 0) {
4240 AIM_STRDUP(feaProblem->feaProperty[i].materialName, feaProblem->feaMaterial[0].name, aimInfo, status){ if (feaProblem->feaProperty[i].materialName != ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 4240
, __func__, 1, "AIM_STRDUP: %s != NULL!", "feaProblem->feaProperty[i].materialName"
); goto cleanup; } feaProblem->feaProperty[i].materialName
= EG_strdup(feaProblem->feaMaterial[0].name); if (feaProblem
->feaProperty[i].materialName == ((void*)0)) { status = -4
; aim_status(aimInfo, status, "feaUtils.c", 4240, __func__, 2
, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].materialName"
, feaProblem->feaMaterial[0].name); goto cleanup; } }
;
4241 }
4242 }
4243
4244 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4245
4246 // Fill up properties ///
4247
4248 // Rods
4249 /*! \page feaProperty
4250 *
4251 * \if (MYSTRAN || NASTRAN)
4252 * <ul>
4253 * <li> <B>crossSecArea = 0.0</B> </li> <br>
4254 * Cross sectional area.
4255 * </ul>
4256 * \elseif ABAQUS
4257 *
4258 * Something else ....
4259 *
4260 * \elseif ASTROS
4261 * <ul>
4262 * <li> <B>crossSecArea = 0.0</B> </li> <br>
4263 * Cross sectional area.
4264 * </ul>
4265 * \endif
4266 */
4267 keyWord = "crossSecArea";
4268 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4269 if (status == CAPS_SUCCESS0) {
4270
4271 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].crossSecArea);
4272 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4272
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4273 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4274 }
4275
4276 /*! \page feaProperty
4277 *
4278 * \if (MYSTRAN || NASTRAN)
4279 * <ul>
4280 * <li> <B>torsionalConst = 0.0</B> </li> <br>
4281 * Torsional constant.
4282 * </ul>
4283 * \elseif ABAQUS
4284 *
4285 * Something else ....
4286 *
4287 * \elseif ASTROS
4288 * <ul>
4289 * <li> <B>torsionalConst = 0.0</B> </li> <br>
4290 * Torsional constant.
4291 * </ul>
4292 * \endif
4293 */
4294 keyWord = "torsionalConst";
4295 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4296 if (status == CAPS_SUCCESS0) {
4297
4298 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].torsionalConst);
4299 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4299
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4300 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4301 }
4302
4303 /*! \page feaProperty
4304 *
4305 * \if (MYSTRAN || NASTRAN)
4306 * <ul>
4307 * <li> <B>torsionalStressReCoeff = 0.0</B> </li> <br>
4308 * Torsional stress recovery coefficient.
4309 * </ul>
4310 * \elseif ABAQUS
4311 *
4312 * Something else ....
4313 *
4314 * \elseif ASTROS
4315 * <ul>
4316 * <li> <B>torsionalStressReCoeff = 0.0</B> </li> <br>
4317 * Torsional stress recovery coefficient.
4318 * </ul>
4319 * \endif
4320 */
4321 keyWord = "torsionalStressReCoeff";
4322 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4323 if (status == CAPS_SUCCESS0) {
4324
4325 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].torsionalStressReCoeff);
4326 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4326
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4327 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4328 }
4329
4330 /*! \page feaProperty
4331 *
4332 * \if (HSM)
4333 * <ul>
4334 * <li> <B>massPerLength = 0.0</B> </li> <br>
4335 * Mass per unit length.
4336 * </ul>
4337 *
4338 * \elseif ( MYSTRAN || NASTRAN || ASTROS || ABAQUS)
4339 * <ul>
4340 * <li> <B>massPerLength = 0.0</B> </li> <br>
4341 * Non-structural mass per unit length.
4342 * </ul>
4343 *
4344 * \endif
4345 */
4346 keyWord = "massPerLength";
4347 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4348 if (status == CAPS_SUCCESS0) {
4349
4350 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].massPerLength);
4351 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4351
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4352 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4353 }
4354
4355 // Bar - see rod for additional variables
4356
4357 /*! \page feaProperty
4358 *
4359 * \if (MYSTRAN || NASTRAN)
4360 * <ul>
4361 * <li> <B>zAxisInertia = 0.0</B> </li> <br>
4362 * Section moment of inertia about the element z-axis.
4363 * </ul>
4364 * \elseif ABAQUS
4365 *
4366 * Something else ....
4367 *
4368 * \elseif ASTROS
4369 * <ul>
4370 * <li> <B>zAxisInertia = 0.0</B> </li> <br>
4371 * Section moment of inertia about the element z-axis.
4372 * </ul>
4373 * \endif
4374 */
4375 keyWord = "zAxisInertia";
4376 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4377 if (status == CAPS_SUCCESS0) {
4378
4379 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].zAxisInertia);
4380 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4380
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4381 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4382 }
4383
4384 /*! \page feaProperty
4385 *
4386 * \if (MYSTRAN || NASTRAN)
4387 * <ul>
4388 * <li> <B>yAxisInertia = 0.0</B> </li> <br>
4389 * Section moment of inertia about the element y-axis.
4390 * </ul>
4391 * \elseif ABAQUS
4392 *
4393 * Something else ....
4394 *
4395 * \elseif ASTROS
4396 * <ul>
4397 * <li> <B>yAxisInertia = 0.0</B> </li> <br>
4398 * Section moment of inertia about the element y-axis.
4399 * </ul>
4400 * \endif
4401 */
4402 keyWord = "yAxisInertia";
4403 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4404 if (status == CAPS_SUCCESS0) {
4405
4406 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].yAxisInertia);
4407 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4407
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4408 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4409 }
4410
4411 /*! \page feaProperty
4412 *
4413 * \if (MYSTRAN || NASTRAN)
4414 * <ul>
4415 * <li> <B>yCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4416 * Element y-coordinates, in the bar cross-section, of four points at which to recover stresses
4417 * </ul>
4418 * \elseif ABAQUS
4419 *
4420 * Something else ....
4421 *
4422 * \elseif ASTROS
4423 * <ul>
4424 * <li> <B>yCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4425 * Element y-coordinates, in the bar cross-section, of four points at which to recover stresses
4426 * </ul>
4427 * \endif
4428 */
4429 keyWord = "yCoords";
4430 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4431 if (status == CAPS_SUCCESS0) {
4432 status = string_toDoubleArray(keyValue,
4433 (int) sizeof(feaProblem->feaProperty[i].yCoords)/sizeof(double),
4434 feaProblem->feaProperty[i].yCoords);
4435 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4435
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4436 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4437 }
4438
4439 /*! \page feaProperty
4440 *
4441 * \if (MYSTRAN || NASTRAN)
4442 * <ul>
4443 * <li> <B>zCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4444 * Element z-coordinates, in the bar cross-section, of four points at which to recover stresses
4445 * </ul>
4446 * \elseif ABAQUS
4447 *
4448 * Something else ....
4449 *
4450 * \elseif ASTROS
4451 * <ul>
4452 * <li> <B>zCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4453 * Element z-coordinates, in the bar cross-section, of four points at which to recover stresses
4454 * </ul>
4455 * \endif
4456 */
4457 keyWord = "zCoords";
4458 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4459 if (status == CAPS_SUCCESS0) {
4460 status = string_toDoubleArray(keyValue,
4461 (int) sizeof(feaProblem->feaProperty[i].zCoords)/sizeof(double),
4462 feaProblem->feaProperty[i].zCoords);
4463 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4463
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4464 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4465 }
4466
4467 /*! \page feaProperty
4468 *
4469 * \if (MYSTRAN || NASTRAN)
4470 * <ul>
4471 * <li> <B>areaShearFactors[2] = [0.0, 0.0]</B> </li> <br>
4472 * Area factors for shear.
4473 * </ul>
4474 * \elseif ABAQUS
4475 *
4476 * Something else ....
4477 *
4478 * \elseif ASTROS
4479 * <ul>
4480 * <li> <B>areaShearFactors[2] = [0.0, 0.0]</B> </li> <br>
4481 * Area factors for shear.
4482 * </ul>
4483 * \endif
4484 */
4485 keyWord = "areaShearFactors";
4486 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4487 if (status == CAPS_SUCCESS0) {
4488 status = string_toDoubleArray(keyValue,
4489 (int) sizeof(feaProblem->feaProperty[i].areaShearFactors)/sizeof(double),
4490 feaProblem->feaProperty[i].areaShearFactors);
4491 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4491
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4492 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4493 }
4494
4495 /*! \page feaProperty
4496 *
4497 * \if (MYSTRAN || NASTRAN)
4498 * <ul>
4499 * <li> <B>crossProductInertia = 0.0</B> </li> <br>
4500 * Section cross-product of inertia.
4501 * </ul>
4502 * \elseif ABAQUS
4503 *
4504 * Something else ....
4505 *
4506 * \elseif ASTROS
4507 * <ul>
4508 * <li> <B>crossProductInertia = 0.0</B> </li> <br>
4509 * Section cross-product of inertia.
4510 * </ul>
4511 * \endif
4512 */
4513 keyWord = "crossProductInertia";
4514 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4515 if (status == CAPS_SUCCESS0) {
4516 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].crossProductInertia);
4517 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4517
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4518 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4519 }
4520
4521 /*! \page feaProperty
4522 *
4523 * \if (MYSTRAN || NASTRAN )
4524 * <ul>
4525 * <li> <B>crossSecType = NULL</B> </li> <br>
4526 * Cross-section type. Must be one of following character variables: BAR, BOX, BOX1,
4527 * CHAN, CHAN1, CHAN2, CROSS, H, HAT, HEXA, I, I1, ROD, T, T1, T2, TUBE, or Z.
4528 * </ul>
4529 * \elseif ASTROS
4530 * <ul>
4531 * <li> <B>crossSecType = NULL</B> </li> <br>
4532 * Cross-section type. Must be one of following character variables: I, T, BOX, BAR,
4533 * TUBE, ROD, HAT, or GBOX.
4534 * </ul>
4535 * \endif
4536 */
4537 keyWord = "crossSecType";
4538 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4539 if (status == CAPS_SUCCESS0) {
4540 feaProblem->feaProperty[i].crossSecType = string_removeQuotation(keyValue);
4541 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4542 }
4543
4544 /*! \page feaProperty
4545 *
4546 * \if (MYSTRAN || NASTRAN || ASTROS)
4547 * <ul>
4548 * <li> <B>crossSecDimension = [0,0,0,....]</B> </li> <br>
4549 * Cross-sectional dimensions (length of array is dependent on the "crossSecType"). Max
4550 * supported length array is 10!
4551 * </ul>
4552 * \endif
4553 */
4554 keyWord = "crossSecDimension";
4555 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4556 if (status == CAPS_SUCCESS0) {
4557 status = string_toDoubleArray(keyValue,
4558 (int) sizeof(feaProblem->feaProperty[i].crossSecDimension)/sizeof(double),
4559 feaProblem->feaProperty[i].crossSecDimension);
4560 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4560
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4561 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4562 }
4563
4564
4565 /* UNDOCUMENTED orientation vector of bars - MAY be changed in the future without warning
4566 */
4567 keyWord = "orientationVec";
4568 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4569 if (status == CAPS_SUCCESS0) {
4570 status = string_toDoubleArray(keyValue,
4571 (int) sizeof(feaProblem->feaProperty[i].orientationVec)/sizeof(double),
4572 feaProblem->feaProperty[i].orientationVec);
4573 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4573
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4574 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4575 }
4576
4577
4578 // Shear
4579
4580 // Shell
4581
4582 /*! \page feaProperty
4583 *
4584 * \if (MYSTRAN || NASTRAN || MASSTRAN)
4585 * <ul>
4586 * <li> <B>membraneThickness = 0.0</B> </li> <br>
4587 * Membrane thickness.
4588 * </ul>
4589 * \elseif ABAQUS
4590 *
4591 * Something else ....
4592 *
4593 * \elseif ASTROS
4594 * <ul>
4595 * <li> <B>membraneThickness = 0.0</B> </li> <br>
4596 * Membrane thickness.
4597 * </ul>
4598 * \endif
4599 */
4600 keyWord = "membraneThickness";
4601 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4602 if (status == CAPS_SUCCESS0) {
4603 if ( feaUnits->length != NULL((void*)0) ) {
4604 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->length, &feaProblem->feaProperty[i].membraneThickness);
4605 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4605
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4606 } else {
4607 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].membraneThickness);
4608 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4608
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4609 }
4610 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4611 }
4612
4613
4614 /*! \page feaProperty
4615 *
4616 * \if (MYSTRAN || NASTRAN)
4617 * <ul>
4618 * <li> <B>bendingInertiaRatio = 1.0</B> </li> <br>
4619 * Ratio of actual bending moment inertia to the bending inertia of a solid plate of thickness "membraneThickness"
4620 * </ul>
4621 * \elseif ABAQUS
4622 *
4623 * Something else ....
4624 *
4625 * \elseif ASTROS
4626 * <ul>
4627 * <li> <B>bendingInertiaRatio = 1.0</B> </li> <br>
4628 * Ratio of actual bending moment inertia to the bending inertia of a solid plate of thickness "membraneThickness"
4629 * </ul>
4630 * \endif
4631 */
4632 keyWord = "bendingInertiaRatio";
4633 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4634 if (status == CAPS_SUCCESS0) {
4635 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].bendingInertiaRatio);
4636 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4636
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4637 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4638 }
4639
4640
4641 /*! \page feaProperty
4642 *
4643 * \if (MYSTRAN || NASTRAN)
4644 * <ul>
4645 * <li> <B>shearMembraneRatio = 5.0/6.0</B> </li> <br>
4646 * Ratio shear thickness to membrane thickness.
4647 * </ul>
4648 * \elseif ABAQUS
4649 *
4650 * Something else ....
4651 *
4652 * \elseif ASTROS
4653 * <ul>
4654 * <li> <B>shearMembraneRatio = 5.0/6.0</B> </li> <br>
4655 * Ratio shear thickness to membrane thickness.
4656 * </ul>
4657 * \endif
4658 */
4659 keyWord = "shearMembraneRatio";
4660 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4661 if (status == CAPS_SUCCESS0) {
4662 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].shearMembraneRatio);
4663 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4663
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4664 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4665 }
4666
4667 /*! \page feaProperty
4668 *
4669 * \if (MYSTRAN || NASTRAN)
4670 * <ul>
4671 * <li> <B>materialBending = "Material Name" (\ref feaMaterial)</B> </li> <br>
4672 * "Material Name" from \ref feaMaterial to use for property bending. If no material is given and
4673 * "bendingInertiaRatio" is greater than 0, the material name provided in "material" is used.
4674 * </ul>
4675 * \elseif ABAQUS
4676 *
4677 * Something else ....
4678 *
4679 * \elseif ASTROS
4680 * <ul>
4681 * <li> <B>materialBending = "Material Name" (\ref feaMaterial)</B> </li> <br>
4682 * "Material Name" from \ref feaMaterial to use for property bending.
4683 * </ul>
4684 * \endif
4685 */
4686 keyWord = "materialBending"; // Shell specific materials
4687 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4688 if (status == CAPS_SUCCESS0) {
4689
4690 found = (int) false0;
4691 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4692
4693 if (tempString != NULL((void*)0)) EG_free(tempString);
4694 tempString = string_removeQuotation(keyValue);
4695 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 4695, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
4696
4697 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4698 feaProblem->feaProperty[i].materialBendingID = feaProblem->feaMaterial[matIndex].materialID;
4699 found = (int) true1;
4700
4701 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4702 break;
4703 }
4704
4705 }
4706
4707 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4708
4709 if (found == (int) false0) {
4710 AIM_ERROR(aimInfo, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4712, __func__
, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4711 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4712, __func__
, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4712 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4712, __func__
, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
;
4713 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4714 status = CAPS_NOTFOUND-303;
4715 goto cleanup;
4716 }
4717
4718 } else { // Don't default to anything - yet
4719
4720 /*
4721 printf("No \"%s\" specified for Property tuple %s which is a shell element, "
4722 " no bending material will be specified\n", keyWord,
4723 propertyTuple[i].name);
4724
4725 feaProblem->feaProperty[i].materialBendingID = 0;
4726 */
4727
4728 if (feaProblem->feaProperty[i].bendingInertiaRatio > 0) {
4729
4730 feaProblem->feaProperty[i].materialBendingID = feaProblem->feaProperty[i].materialID;
4731 }
4732 }
4733
4734 /*! \page feaProperty
4735 *
4736 * \if (MYSTRAN || NASTRAN)
4737 * <ul>
4738 * <li> <B>materialShear = "Material Name" (\ref feaMaterial)</B> </li> <br>
4739 * "Material Name" from \ref feaMaterial to use for property shear. If no material is given and
4740 * "shearMembraneRatio" is greater than 0, the material name provided in "material" is used.
4741 * </ul>
4742 * \elseif ABAQUS
4743 *
4744 * Something else ....
4745 *
4746 * \elseif ASTROS
4747 * <ul>
4748 * <li> <B>materialShear = "Material Name" (\ref feaMaterial)</B> </li> <br>
4749 * "Material Name" from \ref feaMaterial to use for property shear.
4750 * </ul>
4751 * \endif
4752 */
4753 keyWord = "materialShear"; // Shell specific materials
4754 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4755 if (status == CAPS_SUCCESS0) {
4756
4757 found = (int) false0;
4758 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4759
4760 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4761 tempString = string_removeQuotation(keyValue);
4762 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 4762, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
4763
4764 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4765 feaProblem->feaProperty[i].materialShearID = feaProblem->feaMaterial[matIndex].materialID;
4766 found = (int) true1;
4767
4768 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4769 break;
4770 }
4771
4772 }
4773
4774 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4775
4776 if (found == (int) false0) {
4777 AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4779, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4778 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4779, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4779 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4779, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
;
4780 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4781 status = CAPS_NOTFOUND-303;
4782 goto cleanup;
4783 }
4784
4785 } else {
4786 /*
4787 printf("No \"%s\" specified for Property tuple %s which is a shell element, "
4788 " no shear material will be specified\n", keyWord,
4789 propertyTuple[i].name);
4790
4791 feaProblem->feaProperty[i].materialShearID = 0;
4792 */
4793
4794 if (feaProblem->feaProperty[i].shearMembraneRatio > 0) {
4795 feaProblem->feaProperty[i].materialShearID = feaProblem->feaProperty[i].materialID;
4796 }
4797 }
4798
4799 /*! \page feaProperty
4800 *
4801 * \if (HSM || MASSTRAN)
4802 * <ul>
4803 * <li> <B>massPerArea = 0.0</B> </li> <br>
4804 * Mass per unit area.
4805 * </ul>
4806 * \elseif (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
4807 *
4808 * <ul>
4809 * <li> <B>massPerArea = 0.0</B> </li> <br>
4810 * Non-structural mass per unit area.
4811 * </ul>
4812 * \endif
4813 */
4814 keyWord = "massPerArea";
4815 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4816 if (status == CAPS_SUCCESS0) {
4817 if ( feaUnits->densityArea != NULL((void*)0) ) {
4818 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->densityArea, &feaProblem->feaProperty[i].massPerArea);
4819 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4819
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4820 } else {
4821 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].massPerArea);
4822 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4822
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4823 }
4824 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4825 }
4826
4827 /*! \page feaProperty
4828 *
4829 * \if (MYSTRAN || NASTRAN || ASTROS)
4830 * <ul>
4831 * <li> <B>zOffsetRel = 0.0</B> </li> <br>
4832 * Relative offset from the surface of grid points to the element reference
4833 * plane as a percentage of the thickness. zOffSet = thickness*zOffsetRel/100
4834 *
4835 * </ul>
4836 * \endif
4837 */
4838 keyWord = "zOffsetRel";
4839 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4840 if (status == CAPS_SUCCESS0) {
4841 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].zOffsetRel);
4842 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4842
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4843 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4844 }
4845
4846 // Composite
4847
4848 /*! \page feaProperty
4849 *
4850 * \if (MYSTRAN || NASTRAN)
4851 * <ul>
4852 * <li> <B>compositeMaterial = "no default" </B> </li> <br>
4853 * List of "Material Name"s, ["Material Name -1", "Material Name -2", ...], from \ref feaMaterial to use for composites.
4854 * </ul>
4855 * \elseif ABAQUS
4856 *
4857 * Something else ....
4858 *
4859 * \elseif ASTROS
4860 * <ul>
4861 * <li> <B>compositeMaterial = "no default" </B> </li> <br>
4862 * List of "Material Name"s, ["Material Name -1", "Material Name -2", ...], from \ref feaMaterial to use for composites.
4863 * </ul>
4864 * \endif
4865 */
4866 keyWord = "compositeMaterial";
4867 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4868 if (status == CAPS_SUCCESS0) {
4869 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 4869, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
4870
4871 status = string_toStringDynamicArray(keyValue, &feaProblem->feaProperty[i].numPly, &tempStringArray);
4872 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4872
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4873
4874 AIM_ALLOC(feaProblem->feaProperty[i].compositeMaterialID, feaProblem->feaProperty[i].numPly, int, aimInfo, status){ if (feaProblem->feaProperty[i].compositeMaterialID != ((
void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 4874, __func__, 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaProperty[i].compositeMaterialID"
); goto cleanup; } size_t memorysize = feaProblem->feaProperty
[i].numPly; feaProblem->feaProperty[i].compositeMaterialID
= (int *) EG_alloc(memorysize*sizeof(int)); if (feaProblem->
feaProperty[i].compositeMaterialID == ((void*)0)) { status = -
4; aim_status(aimInfo, status, "feaUtils.c", 4874, __func__, 3
, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaProperty[i].compositeMaterialID"
, memorysize, "int"); goto cleanup; } }
;
4875
4876 for (j = 0; j < feaProblem->feaProperty[i].numPly; j++) {
4877 found = (int) false0;
4878 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4879
4880 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4881 tempString = string_removeQuotation(tempStringArray[j]);
4882 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 4882, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
4883
4884 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4885 feaProblem->feaProperty[i].compositeMaterialID[j] = feaProblem->feaMaterial[matIndex].materialID;
4886 found = (int) true1;
4887 break;
4888 }
4889
4890 }
4891
4892 if (found == (int) false0) {
4893 AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4895, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyValue, keyWord, propertyTuple[i].name); }
4894 keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4895, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyValue, keyWord, propertyTuple[i].name); }
4895 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4895, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyValue, keyWord, propertyTuple[i].name); }
;
4896
4897 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4898 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4899
4900 (void) string_freeArray(feaProblem->feaProperty[i].numPly, &tempStringArray);
4901
4902 status = CAPS_NOTFOUND-303;
4903 goto cleanup;
4904 }
4905
4906 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4907 }
4908 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4909 status = string_freeArray(feaProblem->feaProperty[i].numPly, &tempStringArray);
4910 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4910
, __func__, 0); goto cleanup; }
;
4911 }
4912
4913 /*! \page feaProperty
4914 *
4915 * \if (MYSTRAN || NASTRAN)
4916 * <ul>
4917 * <li> <B>shearBondAllowable = 0.0 </B> </li> <br>
4918 * Allowable interlaminar shear stress.
4919 * </ul>
4920 * \elseif ABAQUS
4921 *
4922 * Something else ....
4923 *
4924 * \elseif ASTROS
4925 * <ul>
4926 * <li> <B>shearBondAllowable = 0.0 </B> </li> <br>
4927 * Allowable interlaminar shear stress.
4928 * </ul>
4929 * \endif
4930 */
4931 keyWord = "shearBondAllowable";
4932 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4933 if (status == CAPS_SUCCESS0) {
4934 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].compositeShearBondAllowable);
4935 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4935
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4936 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4937 }
4938
4939 /*! \page feaProperty
4940 *
4941 * \if (MYSTRAN || NASTRAN)
4942 * <ul>
4943 * <li> <B>symmetricLaminate = False </B> </li> <br>
4944 * Symmetric lamination option. True- SYM only half the plies are specified, for odd number plies 1/2 thickness
4945 * of center ply is specified with the first ply being the bottom ply in the stack, default (False) all plies specified.
4946 * </ul>
4947 * \elseif (ASTROS)
4948 * <ul>
4949 * <li> <B>symmetricLaminate = False </B> </li> <br>
4950 * Symmetric lamination option. If "True" only half the plies are specified (the plies will be repeated in
4951 * reverse order internally in the PCOMP card). For an odd number of plies, the 1/2 thickness
4952 * of the center ply is specified with the first ply being the bottom ply in the stack, default (False) all plies specified.
4953 * </ul>
4954 * \endif
4955 */
4956 keyWord = "symmetricLaminate";
4957 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4958 if (status == CAPS_SUCCESS0) {
4959 status = string_toBoolean(keyValue, &feaProblem->feaProperty[i].compositeSymmetricLaminate);
4960 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4960
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4961 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4962 }
4963
4964 /*! \page feaProperty
4965 *
4966 * \if (MYSTRAN || NASTRAN)
4967 * <ul>
4968 * <li> <B>compositeFailureTheory = "(no default)" </B> </li> <br>
4969 * Composite failure theory. Options: "HILL", "HOFF", "TSAI", and "STRN"
4970 * </ul>
4971 * \elseif ABAQUS
4972 *
4973 * Something else ....
4974 *
4975 * \elseif ASTROS
4976 * <ul>
4977 * <li> <B>compositeFailureTheory = "(no default)" </B> </li> <br>
4978 * Composite failure theory.
4979 * </ul>
4980 * \endif
4981 */
4982 keyWord = "compositeFailureTheory";
4983 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4984 if (status == CAPS_SUCCESS0) {
4985 feaProblem->feaProperty[i].compositeFailureTheory = string_removeQuotation(keyValue);
4986 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4986
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4987 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4988 }
4989
4990 /*! \page feaProperty
4991 *
4992 * \if (MYSTRAN || NASTRAN)
4993 * <ul>
4994 * <li> <B>compositeThickness = (no default) </B> </li> <br>
4995 * List of composite thickness for each layer (e.g. [1.2, 4.0, 3.0]). If the length of this list doesn't match the length
4996 * of the "compositeMaterial" list, the list is either truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")]
4997 * in which case the last thickness provided is repeated.
4998 * </ul>
4999 * \elseif ABAQUS
5000 *
5001 * Something else ....
5002 *
5003 * \elseif ASTROS
5004 * <ul>
5005 * <li> <B>compositeThickness = (no default) </B> </li> <br>
5006 * List of composite thickness for each layer (e.g. [1.2, 4.0, 3.0]). If the length of this list doesn't match the length
5007 * of the "compositeMaterial" list, the list is either truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")]
5008 * in which case the last thickness provided is repeated.
5009 * </ul>
5010 * \endif
5011 */
5012 keyWord = "compositeThickness";
5013 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5014 if (status == CAPS_SUCCESS0) {
5015 status = string_toDoubleDynamicArray(keyValue, &tempInteger,
5016 &feaProblem->feaProperty[i].compositeThickness);
5017 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5017
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5018 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5019
5020 if (tempInteger < feaProblem->feaProperty[i].numPly) {
5021
5022 printf("\tThe number of thicknesses provided does not match the number of materials for the composite. "
5023 "The last thickness will be repeated %d times\n", feaProblem->feaProperty[i].numPly - tempInteger);
5024
5025 AIM_REALL(feaProblem->feaProperty[i].compositeThickness,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeThickness = (double *) EG_reall(
feaProblem->feaProperty[i].compositeThickness, memorysize*
sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5026, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
5026 feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeThickness = (double *) EG_reall(
feaProblem->feaProperty[i].compositeThickness, memorysize*
sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5026, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
;
5027
5028 for (j = 0; j < feaProblem->feaProperty[i].numPly - tempInteger; j++) {
5029
5030 feaProblem->feaProperty[i].compositeThickness[j+tempInteger] = feaProblem->feaProperty[i].compositeThickness[tempInteger-1];
5031 }
5032 }
5033
5034 if (tempInteger > feaProblem->feaProperty[i].numPly) {
5035
5036 printf("\tThe number of thicknesses provided does not match the number of materials for the composite. "
5037 "The last %d thicknesses will be not be used\n", tempInteger -feaProblem->feaProperty[i].numPly);
5038
5039 AIM_REALL(feaProblem->feaProperty[i].compositeThickness,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeThickness = (double *) EG_reall(
feaProblem->feaProperty[i].compositeThickness, memorysize*
sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5040, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
5040 feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeThickness = (double *) EG_reall(
feaProblem->feaProperty[i].compositeThickness, memorysize*
sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5040, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
;
5041 }
5042 } else {
5043
5044 if (feaProblem->feaProperty[i].numPly != 0 &&
5045 feaProblem->feaProperty[i].propertyType == Composite) {
5046
5047 AIM_ERROR(aimInfo, "\"compositeMaterial\" have been set but no thicknesses (\"compositeThickness\") provided!!!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5047, __func__
, "\"compositeMaterial\" have been set but no thicknesses (\"compositeThickness\") provided!!!"
); }
;
5048 status = CAPS_BADVALUE-311;
5049 goto cleanup;
5050 }
5051 }
5052
5053 /*! \page feaProperty
5054 *
5055 * \if (MYSTRAN || NASTRAN)
5056 * <ul>
5057 * <li> <B>compositeOrientation = (no default) </B> </li> <br>
5058 * List of composite orientations (angle relative element material axis) for each layer (eg. [5.0, 10.0, 30.0]).
5059 * If the length of this list doesn't match the length of the "compositeMaterial" list, the list is either
5060 * truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] in which case
5061 * the last orientation provided is repeated.
5062 * </ul>
5063 * \elseif ABAQUS
5064 *
5065 * Something else ....
5066 *
5067 * \elseif ASTROS
5068 * <ul>
5069 * <li> <B>compositeOrientation = (no default) </B> </li> <br>
5070 * List of composite orientations (angle relative element material axis) for each layer (eg. [5.0, 10.0, 30.0]).
5071 * If the length of this list doesn't match the length of the "compositeMaterial" list, the list is either
5072 * truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] in which case
5073 * the last orientation provided is repeated.
5074 * </ul>
5075 * \endif
5076 */
5077 keyWord = "compositeOrientation";
5078 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5079 if (status == CAPS_SUCCESS0) {
5080 status = string_toDoubleDynamicArray(keyValue, &tempInteger,
5081 &feaProblem->feaProperty[i].compositeOrientation);
5082 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5082
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5083 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5084
5085 if (tempInteger < feaProblem->feaProperty[i].numPly) {
5086
5087 printf("\tThe number of orientations provided does not match the number of materials for the composite. "
5088 "The last orientation will be repeated %d times\n", feaProblem->feaProperty[i].numPly - tempInteger);
5089
5090 AIM_REALL(feaProblem->feaProperty[i].compositeOrientation,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeOrientation = (double *) EG_reall
(feaProblem->feaProperty[i].compositeOrientation, memorysize
*sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5091, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
5091 feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeOrientation = (double *) EG_reall
(feaProblem->feaProperty[i].compositeOrientation, memorysize
*sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5091, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
;
5092
5093 for (j = 0; j < feaProblem->feaProperty[i].numPly - tempInteger; j++) {
5094
5095 feaProblem->feaProperty[i].compositeOrientation[j+tempInteger] = feaProblem->feaProperty[i].compositeOrientation[tempInteger-1];
5096 }
5097 }
5098
5099 if (tempInteger > feaProblem->feaProperty[i].numPly) {
5100
5101 printf("\tThe number of orientations provided does not match the number of materials for the composite. "
5102 "The last %d orientation will be not be used\n", tempInteger -feaProblem->feaProperty[i].numPly);
5103
5104 AIM_REALL(feaProblem->feaProperty[i].compositeOrientation,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeOrientation = (double *) EG_reall
(feaProblem->feaProperty[i].compositeOrientation, memorysize
*sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5105, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
5105 feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem
->feaProperty[i].compositeOrientation = (double *) EG_reall
(feaProblem->feaProperty[i].compositeOrientation, memorysize
*sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 5105, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
;
5106 }
5107
5108 } else {
5109
5110 if (feaProblem->feaProperty[i].numPly != 0 &&
5111 feaProblem->feaProperty[i].propertyType == Composite) {
5112
5113 AIM_ERROR(aimInfo, "\"compositeMaterial\" have been set but no Orientation (\"compositeOrientation\") provided!!!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5113, __func__
, "\"compositeMaterial\" have been set but no Orientation (\"compositeOrientation\") provided!!!"
); }
;
5114 status = CAPS_BADVALUE-311;
5115 goto cleanup;
5116 }
5117 }
5118
5119 // Mass
5120
5121 /*! \page feaProperty
5122 *
5123 * \if (MYSTRAN || NASTRAN)
5124 * <ul>
5125 * <li> <B>mass = 0.0</B> </li> <br>
5126 * Mass value.
5127 * </ul>
5128 * \elseif ABAQUS
5129 *
5130 * Something else ....
5131 *
5132 * \elseif ASTROS
5133 * <ul>
5134 * <li> <B>mass = 0.0</B> </li> <br>
5135 * Mass value.
5136 * </ul>
5137 * \endif
5138 */
5139 keyWord = "mass";
5140 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5141 if (status == CAPS_SUCCESS0) {
5142 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].mass);
5143 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5143
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5144 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5145 }
5146
5147 /*! \page feaProperty
5148 *
5149 * \if (MYSTRAN || NASTRAN || MASSTRAN)
5150 * <ul>
5151 * <li> <B>massOffset = [0.0, 0.0, 0.0]</B> </li> <br>
5152 * Offset distance from the grid point to the center of gravity for a concentrated mass.
5153 * </ul>
5154 * \elseif ABAQUS
5155 *
5156 * Something else ....
5157 *
5158 * \elseif ASTROS
5159 * <ul>
5160 * <li> <B>massOffset = [0.0, 0.0, 0.0]</B> </li> <br>
5161 * Offset distance from the grid point to the center of gravity for a concentrated mass.
5162 * </ul>
5163 * \endif
5164 */
5165 keyWord = "massOffset";
5166 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5167 if (status == CAPS_SUCCESS0) {
5168 status = string_toDoubleArray(keyValue,
5169 (int) sizeof(feaProblem->feaProperty[i].massOffset)/sizeof(double),
5170 feaProblem->feaProperty[i].massOffset);
5171 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5171
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5172 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5173 }
5174
5175 /*! \page feaProperty
5176 *
5177 * \if (MYSTRAN || NASTRAN || MASSTRAN)
5178 * <ul>
5179 * <li> <B>massInertia = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</B> </li> <br>
5180 * Mass moment of inertia measured at the mass center of gravity.
5181 * </ul>
5182 * \elseif ABAQUS
5183 *v
5184 * Something else ....
5185 *
5186 * \elseif ASTROS
5187 * <ul>
5188 * <li> <B>massInertia = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</B> </li> <br>
5189 * Mass moment of inertia measured at the mass center of gravity.
5190 * </ul>
5191 * \endif
5192 */
5193 keyWord = "massInertia";
5194 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5195 if (status == CAPS_SUCCESS0) {
5196 status = string_toDoubleArray(keyValue,
5197 (int) sizeof(feaProblem->feaProperty[i].massInertia)/sizeof(double),
5198 feaProblem->feaProperty[i].massInertia);
5199 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5199
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5200 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5201 }
5202
5203 } else {
5204
5205 /*! \page feaProperty
5206 * \section keyStringProperty Single Value String
5207 *
5208 * If "Value" is a string, the string value may correspond to an entry in a predefined property lookup
5209 * table. NOT YET IMPLEMENTED!!!!
5210 *
5211 */
5212
5213 // CALL property look up
5214 AIM_ERROR(aimInfo, "Property tuple value ('s') is expected to be a JSON string", propertyTuple[i].value){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5214, __func__
, "Property tuple value ('s') is expected to be a JSON string"
, propertyTuple[i].value); }
;
5215 status = CAPS_BADVALUE-311;
5216 goto cleanup;
5217 }
5218 }
5219
5220 printf("\tDone getting FEA properties\n");
5221 status = CAPS_SUCCESS0;
5222
5223cleanup:
5224 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
5225 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5226
5227 return status;
5228}
5229
5230// Get the constraint properties from a capsTuple
5231int fea_getConstraint(void *aimInfo,
5232 int numConstraintTuple,
5233 capsTuple constraintTuple[],
5234 mapAttrToIndexStruct *attrMap,
5235 feaProblemStruct *feaProblem) {
5236
5237 /*! \page feaConstraint FEA Constraint
5238 * Structure for the constraint tuple = ("Constraint Name", "Value").
5239 * "Constraint Name" defines the reference name for the constraint being specified.
5240 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConstraint) or a single string keyword
5241 * (see Section \ref keyStringConstraint).
5242 */
5243
5244 int status; //Function return
5245
5246 int i, groupIndex, attrIndex, nodeIndex; // Indexing
5247
5248 char *keyValue = NULL((void*)0); // Key values from tuple searches
5249 char *keyWord = NULL((void*)0); // Key words to find in the tuples
5250
5251 int numGroupName = 0;
5252 char **groupName = NULL((void*)0);
5253
5254 feaMeshDataStruct *feaData;
5255
5256 // Destroy our constraint structures coming in if aren't 0 and NULL already
5257 if (feaProblem->feaConstraint != NULL((void*)0)) {
5258 for (i = 0; i < feaProblem->numConstraint; i++) {
5259 status = destroy_feaConstraintStruct(&feaProblem->feaConstraint[i]);
5260 if (status != CAPS_SUCCESS0) return status;
5261 }
5262 }
5263 if (feaProblem->feaConstraint != NULL((void*)0)) EG_free(feaProblem->feaConstraint);
5264 feaProblem->feaConstraint = NULL((void*)0);
5265 feaProblem->numConstraint = 0;
5266
5267 printf("\nGetting FEA constraints.......\n");
5268
5269 feaProblem->numConstraint = numConstraintTuple;
5270
5271 printf("\tNumber of constraints - %d\n", feaProblem->numConstraint);
5272
5273 // Allocate constraints
5274 if (feaProblem->numConstraint > 0) {
5275 feaProblem->feaConstraint = (feaConstraintStruct *) EG_alloc(feaProblem->numConstraint * sizeof(feaConstraintStruct));
5276
5277 if (feaProblem->feaConstraint == NULL((void*)0) ) return EGADS_MALLOC-4;
5278 }
5279
5280 // Initiate constraints to default values
5281 for (i = 0; i < feaProblem->numConstraint; i++) {
5282 status = initiate_feaConstraintStruct(&feaProblem->feaConstraint[i]);
5283 if (status != CAPS_SUCCESS0) return status;
5284 }
5285
5286 // Loop through tuples and fill out the constraint structures
5287 for (i = 0; i < feaProblem->numConstraint; i++) {
5288
5289 printf("\tConstraint name - %s\n", constraintTuple[i].name );
5290
5291 // Set constraint name to tuple attribute name
5292 feaProblem->feaConstraint[i].name = (char *) EG_alloc((strlen(constraintTuple[i].name) + 1)*sizeof(char));
5293 if (feaProblem->feaConstraint[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
5294
5295 memcpy(feaProblem->feaConstraint[i].name, constraintTuple[i].name, strlen(constraintTuple[i].name)*sizeof(char));
5296 feaProblem->feaConstraint[i].name[strlen(constraintTuple[i].name)] = '\0';
5297
5298 // Set constraint id -> 1 bias
5299 feaProblem->feaConstraint[i].constraintID = i+1;
5300
5301 // Do we have a json string?
5302 if (strncmp(constraintTuple[i].value, "{", 1) == 0) {
5303 //printf("JSON String - %s\n", constraintTuple[i].value);
5304
5305 /*! \page feaConstraint
5306 * \section jsonStringConstraint JSON String Dictionary
5307 *
5308 * If "Value" is JSON string dictionary
5309 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5310 * (eg. "Value" = {"groupName": "plateEdge", "dofConstraint": 123456})
5311 * \endif
5312 * the following keywords ( = default values) may be used:
5313 *
5314 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5315 * <ul>
5316 * <li> <B>constraintType = "ZeroDisplacement"</B> </li> <br>
5317 * Type of constraint. Options: "Displacement", "ZeroDisplacement".
5318 * </ul>
5319 * \endif
5320 *
5321 */
5322 // Get constraint Type
5323 keyWord = "constraintType";
5324 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5325 if (status == CAPS_SUCCESS0) {
5326 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 5326, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
5327
5328 //{UnknownConstraint, Displacement, ZeroDisplacement}
5329 if (strcasecmp(keyValue, "\"Displacement\"") == 0) feaProblem->feaConstraint[i].constraintType = Displacement;
5330 else if (strcasecmp(keyValue, "\"ZeroDisplacement\"") == 0) feaProblem->feaConstraint[i].constraintType = ZeroDisplacement;
5331 else {
5332
5333 printf("\tUnrecognized \"%s\" specified (%s) for Constraint tuple %s, defaulting to \"ZeroDisplacement\"\n", keyWord,
5334 keyValue,
5335 constraintTuple[i].name);
5336 feaProblem->feaConstraint[i].constraintType = ZeroDisplacement;
5337 }
5338
5339 } else {
5340
5341 printf("\tNo \"%s\" specified for Constraint tuple %s, defaulting to \"ZeroDisplacement\"\n", keyWord,
5342 constraintTuple[i].name);
5343 feaProblem->feaConstraint[i].constraintType = ZeroDisplacement;
5344 }
5345
5346 if (keyValue != NULL((void*)0)) {
5347 EG_free(keyValue);
5348 keyValue = NULL((void*)0);
5349 }
5350
5351 // Get constraint node set
5352
5353 /*! \page feaConstraint
5354 *
5355 * \if MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5356 * <ul>
5357 * <li> <B>groupName = "(no default)"</B> </li> <br>
5358 * Single or list of <c>capsConstraint</c> names on which to apply the constraint
5359 * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the constraint tuple name will be
5360 * used.
5361 * </ul>
5362 * \endif
5363 *
5364 */
5365 keyWord = "groupName";
5366 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5367 if (status == CAPS_SUCCESS0) {
5368
5369 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
5370 if (keyValue != NULL((void*)0)) EG_free(keyValue);
5371 keyValue = NULL((void*)0);
5372
5373 if (status != CAPS_SUCCESS0) return status;
5374
5375 } else {
5376
5377 printf("\tNo \"%s\" specified for Constraint tuple %s, going to use constraint name\n", keyWord,
5378 constraintTuple[i].name);
5379
5380 status = string_toStringDynamicArray(constraintTuple[i].name, &numGroupName, &groupName);
5381 if (status != CAPS_SUCCESS0) return status;
5382
5383 }
5384
5385 // Determine how many point constraints we have
5386 feaProblem->feaConstraint[i].numGridID = 0;
5387 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
5388
5389 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex);
5390
5391 if (status == CAPS_NOTFOUND-303) {
5392 printf("\tName %s not found in attribute map of capsConstraints!!!!\n", groupName[groupIndex]);
5393 continue;
5394 } else if (status != CAPS_SUCCESS0) return status;
5395
5396 // Now lets loop through the grid to see how many grid points have the attrIndex
5397 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
5398
5399 if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) {
5400 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
5401 } else {
5402 continue;
5403 }
5404
5405 if (feaData->constraintIndex == attrIndex) {
5406
5407 feaProblem->feaConstraint[i].numGridID += 1;
5408
5409 // Allocate/Re-allocate grid ID array
5410 if (feaProblem->feaConstraint[i].numGridID == 1) {
5411 feaProblem->feaConstraint[i].gridIDSet = (int *) EG_alloc(feaProblem->feaConstraint[i].numGridID*sizeof(int));
5412 } else {
5413 feaProblem->feaConstraint[i].gridIDSet = (int *) EG_reall(feaProblem->feaConstraint[i].gridIDSet,
5414 feaProblem->feaConstraint[i].numGridID*sizeof(int));
5415 }
5416
5417 if (feaProblem->feaConstraint[i].gridIDSet == NULL((void*)0)) {
5418 status = string_freeArray(numGroupName, &groupName);
5419 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
5420
5421 return EGADS_MALLOC-4;
5422 }
5423
5424 // Set grid ID value -> 1 bias
5425 feaProblem->feaConstraint[i].gridIDSet[feaProblem->feaConstraint[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID;
5426 }
5427 }
5428 }
5429
5430 status = string_freeArray(numGroupName, &groupName);
5431 if (status != CAPS_SUCCESS0) return status;
5432 groupName = NULL((void*)0);
5433
5434
5435 //Fill up constraint properties
5436 /*! \page feaConstraint
5437 *
5438 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5439 * <ul>
5440 * <li> <B>dofConstraint = 0 </B> </li> <br>
5441 * Component numbers / degrees of freedom that will be constrained (123 - zero translation in all three
5442 * directions).
5443 * </ul>
5444 * \endif
5445 */
5446 keyWord = "dofConstraint";
5447 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5448 if (status == CAPS_SUCCESS0) {
5449
5450 status = string_toInteger(keyValue, &feaProblem->feaConstraint[i].dofConstraint);
5451 if (keyValue != NULL((void*)0)) {
5452 EG_free(keyValue);
5453 keyValue = NULL((void*)0);
5454 }
5455 if (status != CAPS_SUCCESS0) return status;
5456 }
5457
5458 /*! \page feaConstraint
5459 *
5460 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5461 * <ul>
5462 * <li> <B>gridDisplacement = 0.0 </B> </li> <br>
5463 * Value of displacement for components defined in "dofConstraint".
5464 * </ul>
5465 * \endif
5466 */
5467 keyWord = "gridDisplacement";
5468 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5469 if (status == CAPS_SUCCESS0) {
5470
5471 status = string_toDouble(keyValue, &feaProblem->feaConstraint[i].gridDisplacement);
5472 if (keyValue != NULL((void*)0)) {
5473 EG_free(keyValue);
5474 keyValue = NULL((void*)0);
5475 }
5476 if (status != CAPS_SUCCESS0) return status;
5477 }
5478
5479 } else {
5480
5481 /*! \page feaConstraint
5482 * \section keyStringConstraint Single Value String
5483 *
5484 * If "Value" is a string, the string value may correspond to an entry in a predefined constraint lookup
5485 * table. NOT YET IMPLEMENTED!!!!
5486 *
5487 */
5488
5489 // Call some look up table maybe?
5490 printf("\tError: Constraint tuple value is expected to be a JSON string\n");
5491 return CAPS_BADVALUE-311;
5492 }
5493 }
5494
5495 if (keyValue != NULL((void*)0)) EG_free(keyValue);
5496
5497 printf("\tDone getting FEA constraints\n");
5498
5499 status = CAPS_SUCCESS0;
5500cleanup:
5501 return status;
5502}
5503
5504// Get the support properties from a capsTuple
5505int fea_getSupport(int numSupportTuple,
5506 capsTuple supportTuple[],
5507 mapAttrToIndexStruct *attrMap,
5508 feaProblemStruct *feaProblem) {
5509
5510 /*! \page feaSupport FEA Support
5511 * Structure for the support tuple = ("Support Name", "Value").
5512 * "Support Name" defines the reference name for the support being specified.
5513 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringSupport) or a single string keyword
5514 * (see Section \ref keyStringSupport).
5515 */
5516
5517 int status; //Function return
5518
5519 int i, groupIndex, attrIndex, nodeIndex; // Indexing
5520
5521 char *keyValue = NULL((void*)0); // Key values from tuple searches
5522 char *keyWord = NULL((void*)0); // Key words to find in the tuples
5523
5524 int numGroupName = 0;
5525 char **groupName = NULL((void*)0);
5526
5527 feaMeshDataStruct *feaData;
5528
5529 // Destroy our support structures coming in if aren't 0 and NULL already
5530 if (feaProblem->feaSupport != NULL((void*)0)) {
5531 for (i = 0; i < feaProblem->numSupport; i++) {
5532 status = destroy_feaSupportStruct(&feaProblem->feaSupport[i]);
5533 if (status != CAPS_SUCCESS0) return status;
5534 }
5535 }
5536 if (feaProblem->feaSupport != NULL((void*)0)) EG_free(feaProblem->feaSupport);
5537 feaProblem->feaSupport = NULL((void*)0);
5538 feaProblem->numSupport = 0;
5539
5540 printf("\nGetting FEA supports.......\n");
5541
5542 feaProblem->numSupport = numSupportTuple;
5543
5544 printf("\tNumber of supports - %d\n", feaProblem->numSupport);
5545
5546 // Allocate supports
5547 if (feaProblem->numSupport > 0) {
5548 feaProblem->feaSupport = (feaSupportStruct *) EG_alloc(feaProblem->numSupport * sizeof(feaSupportStruct));
5549
5550 if (feaProblem->feaSupport == NULL((void*)0) ) return EGADS_MALLOC-4;
5551 }
5552
5553 // Initiate supports to default values
5554 for (i = 0; i < feaProblem->numSupport; i++) {
5555 status = initiate_feaSupportStruct(&feaProblem->feaSupport[i]);
5556 if (status != CAPS_SUCCESS0) return status;
5557 }
5558
5559 // Loop through tuples and fill out the support structures
5560 for (i = 0; i < feaProblem->numSupport; i++) {
5561
5562 printf("\tSupport name - %s\n", supportTuple[i].name );
5563
5564 // Set support name to tuple attribute name
5565 feaProblem->feaSupport[i].name = (char *) EG_alloc((strlen(supportTuple[i].name) + 1)*sizeof(char));
5566 if (feaProblem->feaSupport[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
5567
5568 memcpy(feaProblem->feaSupport[i].name, supportTuple[i].name, strlen(supportTuple[i].name)*sizeof(char));
5569 feaProblem->feaSupport[i].name[strlen(supportTuple[i].name)] = '\0';
5570
5571 // Set support id -> 1 bias
5572 feaProblem->feaSupport[i].supportID = i+1;
5573
5574 // Do we have a json string?
5575 if (strncmp(supportTuple[i].value, "{", 1) == 0) {
5576 //printf("JSON String - %s\n", supportTuple[i].value);
5577
5578 /*! \page feaSupport
5579 * \section jsonStringSupport JSON String Dictionary
5580 *
5581 * If "Value" is JSON string dictionary
5582 * \if (MYSTRAN || NASTRAN || ASTROS)
5583 * (eg. "Value" = {"groupName": "plateEdge", "dofSupport": 123456})
5584 * \endif
5585 * the following keywords ( = default values) may be used:
5586 */
5587
5588 // Get support node set
5589
5590 /*! \page feaSupport
5591 *
5592 * \if (MYSTRAN || NASTRAN || ASTROS)
5593 * <ul>
5594 * <li> <B>groupName = "(no default)"</B> </li> <br>
5595 * Single or list of <c>capsConstraint</c> names on which to apply the support
5596 * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the constraint tuple name will be
5597 * used.
5598 * </ul>
5599 * \endif
5600 */
5601 keyWord = "groupName";
5602 status = search_jsonDictionary( supportTuple[i].value, keyWord, &keyValue);
5603 if (status == CAPS_SUCCESS0) {
5604
5605 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
5606 if (keyValue != NULL((void*)0)) EG_free(keyValue);
5607 keyValue = NULL((void*)0);
5608
5609 if (status != CAPS_SUCCESS0) return status;
5610
5611 } else {
5612
5613 printf("\tNo \"%s\" specified for Support tuple %s, going to use support name\n", keyWord,
5614 supportTuple[i].name);
5615
5616 status = string_toStringDynamicArray(supportTuple[i].name, &numGroupName, &groupName);
5617 if (status != CAPS_SUCCESS0) return status;
5618
5619 }
5620
5621 // Determine how many point supports we have
5622 feaProblem->feaSupport[i].numGridID = 0;
5623 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
5624
5625 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex);
5626
5627 if (status == CAPS_NOTFOUND-303) {
5628 printf("\tName %s not found in attribute map of capsConstraints!!!!\n", groupName[groupIndex]);
5629 continue;
5630 } else if (status != CAPS_SUCCESS0) return status;
5631
5632 // Now lets loop through the grid to see how many grid points have the attrIndex
5633 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
5634
5635 if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) {
5636 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
5637 } else {
5638 continue;
5639 }
5640
5641 if (feaData->constraintIndex == attrIndex) {
5642
5643 feaProblem->feaSupport[i].numGridID += 1;
5644
5645 // Allocate/Re-allocate grid ID array
5646 if (feaProblem->feaSupport[i].numGridID == 1) {
5647 feaProblem->feaSupport[i].gridIDSet = (int *) EG_alloc(feaProblem->feaSupport[i].numGridID*sizeof(int));
5648 } else {
5649 feaProblem->feaSupport[i].gridIDSet = (int *) EG_reall(feaProblem->feaSupport[i].gridIDSet,
5650 feaProblem->feaSupport[i].numGridID*sizeof(int));
5651 }
5652
5653 if (feaProblem->feaSupport[i].gridIDSet == NULL((void*)0)) {
5654 status = string_freeArray(numGroupName, &groupName);
5655 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
5656
5657 return EGADS_MALLOC-4;
5658 }
5659
5660 // Set grid ID value -> 1 bias
5661 feaProblem->feaSupport[i].gridIDSet[feaProblem->feaSupport[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID;
5662 }
5663 }
5664 }
5665
5666 status = string_freeArray(numGroupName, &groupName);
5667 if (status != CAPS_SUCCESS0) return status;
5668 groupName = NULL((void*)0);
5669
5670 //Fill up support properties
5671 /*! \page feaSupport
5672 *
5673 * \if (MYSTRAN || NASTRAN || ASTROS)
5674 * <ul>
5675 * <li> <B>dofSupport = 0 </B> </li> <br>
5676 * Component numbers / degrees of freedom that will be supported (123 - zero translation in all three
5677 * directions).
5678 * </ul>
5679 * \endif
5680 */
5681 keyWord = "dofSupport";
5682 status = search_jsonDictionary( supportTuple[i].value, keyWord, &keyValue);
5683 if (status == CAPS_SUCCESS0) {
5684
5685 status = string_toInteger(keyValue, &feaProblem->feaSupport[i].dofSupport);
5686 if (keyValue != NULL((void*)0)) {
5687 EG_free(keyValue);
5688 keyValue = NULL((void*)0);
5689 }
5690 if (status != CAPS_SUCCESS0) return status;
5691 }
5692
5693 } else {
5694
5695 /*! \page feaSupport
5696 * \section keyStringSupport Single Value String
5697 *
5698 * If "Value" is a string, the string value may correspond to an entry in a predefined support lookup
5699 * table. NOT YET IMPLEMENTED!!!!
5700 *
5701 */
5702
5703 // Call some look up table maybe?
5704 printf("\tError: Support tuple value is expected to be a JSON string\n");
5705 return CAPS_BADVALUE-311;
5706
5707 }
5708 }
5709
5710 if (keyValue != NULL((void*)0)) {
5711 EG_free(keyValue);
5712 keyValue = NULL((void*)0);
5713 }
5714
5715 printf("\tDone getting FEA supports\n");
5716 return CAPS_SUCCESS0;
5717}
5718
5719
5720static int fea_setConnection(char *connectionName,
5721 feaConnectionTypeEnum connectionType,
5722 int connectionID,
5723 int elementOffSet,
5724 int dofDependent,
5725 double stiffnessConst,
5726 double dampingConst,
5727 double stressCoeff,
5728 int componentNumberStart,
5729 int componentNumberEnd,
5730 int srcNodeID,
5731 double masterWeight,
5732 int masterComponent,
5733 int numNode, int *node,
5734 int *numConnect, feaConnectionStruct *feaConnect[]) { // Out
5735
5736 int status;
5737 int i;
5738
5739 if (numNode == 0) {
5740 status = CAPS_BADVALUE-311; // Nothing to do
5741 goto cleanup;
5742 }
5743
5744 if (connectionType == RigidBodyInterpolate) {
5745 *numConnect += 1;
5746
5747 (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),*numConnect*sizeof(feaConnectionStruct));
5748 if ((*feaConnect) == NULL((void*)0)) {
5749 *numConnect = 0;
5750 status = EGADS_MALLOC-4;
5751 goto cleanup;
5752 }
5753
5754 status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect-1]);
5755 if (status != CAPS_SUCCESS0) return status;
5756
5757 (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index
5758 (*feaConnect)[*numConnect-1].connectionType = connectionType;
5759
5760 (*feaConnect)[*numConnect-1].elementID = *numConnect + elementOffSet;
5761
5762 (*feaConnect)[*numConnect-1].dofDependent = dofDependent;
5763
5764 (*feaConnect)[*numConnect-1].connectivity[1] = srcNodeID; // Dependent
5765 (*feaConnect)[*numConnect-1].numMaster = numNode; // Independent
5766
5767 (*feaConnect)[*numConnect-1].masterIDSet = (int *) EG_alloc(numNode*sizeof(int)); // [numMaster]
5768 if ((*feaConnect)[*numConnect-1].masterIDSet == NULL((void*)0)) {
5769 status = EGADS_MALLOC-4;
5770 goto cleanup;
5771 }
5772 (*feaConnect)[*numConnect-1].masterWeighting = (double *) EG_alloc(numNode*sizeof(double));; // [numMaster]
5773 if ((*feaConnect)[*numConnect-1].masterWeighting == NULL((void*)0)) {
5774 status = EGADS_MALLOC-4;
5775 goto cleanup;
5776 }
5777
5778 (*feaConnect)[*numConnect-1].masterComponent =(int *) EG_alloc(numNode*sizeof(int));; // [numMaster]
5779 if ((*feaConnect)[*numConnect-1].masterComponent == NULL((void*)0)) {
5780 status = EGADS_MALLOC-4;
5781 goto cleanup;
5782 }
5783
5784 //printf("\tMasters (%d)", numNode);
5785 // Master values;
5786 for (i = 0; i < numNode; i++) {
5787 // printf(" %d", node[i]);
5788
5789 (*feaConnect)[*numConnect-1].masterIDSet[i] = node[i];
5790 (*feaConnect)[*numConnect-1].masterWeighting[i] = masterWeight;
5791 (*feaConnect)[*numConnect-1].masterComponent[i] = masterComponent;
5792 }
5793 //printf("\n");
5794
5795 } else { // For all other types of connections create an individual connection - single pair of nodes
5796
5797 (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),(*numConnect+numNode)*sizeof(feaConnectionStruct));
5798 if ((*feaConnect) == NULL((void*)0)) {
5799 *numConnect = 0;
5800 status = EGADS_MALLOC-4;
5801 goto cleanup;
5802 }
5803
5804 for (i = 0; i < numNode; i++) {
5805 status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect+i]);
5806 if (status != CAPS_SUCCESS0) return status;
5807 }
5808
5809 for (i = 0; i < numNode; i++) {
5810
5811 *numConnect += 1;
5812
5813 (*feaConnect)[*numConnect-1].name = (char *) EG_alloc((strlen(connectionName) + 1)*sizeof(char));
5814 if ((*feaConnect)[*numConnect-1].name == NULL((void*)0)) return EGADS_MALLOC-4;
5815
5816 memcpy((*feaConnect)[*numConnect-1].name,
5817 connectionName,
5818 strlen(connectionName)*sizeof(char));
5819 (*feaConnect)[*numConnect-1].name[strlen(connectionName)] = '\0';
5820
5821 (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index
5822
5823 (*feaConnect)[*numConnect-1].connectionType = connectionType;
5824 (*feaConnect)[*numConnect-1].elementID = *numConnect + elementOffSet;
5825
5826 (*feaConnect)[*numConnect-1].connectivity[0] = srcNodeID;
5827 (*feaConnect)[*numConnect-1].connectivity[1] = node[i];
5828
5829 (*feaConnect)[*numConnect-1].dofDependent = dofDependent;
5830 (*feaConnect)[*numConnect-1].stiffnessConst = stiffnessConst;
5831 (*feaConnect)[*numConnect-1].dampingConst = dampingConst;
5832 (*feaConnect)[*numConnect-1].stressCoeff = stressCoeff;
5833 (*feaConnect)[*numConnect-1].componentNumberStart = componentNumberStart;
5834 (*feaConnect)[*numConnect-1].componentNumberEnd = componentNumberEnd;
5835 }
5836 }
5837
5838 status = CAPS_SUCCESS0;
5839 goto cleanup;
5840
5841 cleanup:
5842 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_setConnection, status = %d\n", status);
5843 return status;
5844}
5845// Get the Connections properties from a capsTuple and create connections based on the mesh
5846int fea_getConnection(void *aimInfo,
5847 int numConnectionTuple,
5848 capsTuple connectionTuple[],
5849 mapAttrToIndexStruct *attrMap,
5850 feaProblemStruct *feaProblem) {
5851
5852 /*! \page feaConnection FEA Connection
5853 * Structure for the connection tuple = ("Connection Name", "Value").
5854 * "Connection Name" defines the reference name to the capsConnect being specified and denotes the "source" node
5855 * for the connection.
5856 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConnection) or a single string keyword
5857 * (see Section \ref keyStringConnection).
5858 */
5859
5860 int status; //Function return
5861
5862 int i, groupIndex, nodeIndex, nodeIndexDest; // Indexing
5863
5864 char *keyValue = NULL((void*)0); // Key values from tuple searches
5865 char *keyWord = NULL((void*)0); // Key words to find in the tuples
5866
5867 int numGroupName = 0;
5868 char **groupName = NULL((void*)0);
5869 int attrIndex, attrIndexDest;
5870
5871 // Values to set
5872 feaConnectionTypeEnum connectionType;
5873 int dofDependent = 0, componentNumberStart = 0, componentNumberEnd = 0;
5874 double stiffnessConst = 0.0, dampingConst = 0.0, stressCoeff = 0.0, mass = 0.0;
5875
5876 double weighting=1;
5877
5878 int glue = (int) false0, glueNumMaster = 5;
5879 double glueSearchRadius=0;
5880
5881 feaMeshDataStruct *feaData, *feaDataDest;
5882
5883 int numDestNode=0, *destNode=NULL((void*)0);
5884
5885 // Destroy our support structures coming in if aren't 0 and NULL already
5886 if (feaProblem->feaConnect != NULL((void*)0)) {
5887 for (i = 0; i < feaProblem->numConnect; i++) {
5888 status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]);
5889 if (status != CAPS_SUCCESS0) return status;
5890 }
5891 }
5892 if (feaProblem->feaConnect != NULL((void*)0)) EG_free(feaProblem->feaConnect);
5893 feaProblem->feaConnect = NULL((void*)0);
5894 feaProblem->numConnect = 0;
5895
5896 printf("\nGetting FEA connections.......\n");
5897
5898 printf("\tNumber of connection tuples - %d\n", numConnectionTuple);
5899
5900 // Loop through tuples and fill out the support structures
5901 for (i = 0; i < numConnectionTuple; i++) {
5902
5903 // Reset defaults
5904 dofDependent = componentNumberStart = componentNumberEnd = 0;
5905 stiffnessConst = dampingConst = stressCoeff = mass = 0.0;
5906
5907 weighting=1;
5908
5909 glue = (int) false0;
5910 glueNumMaster = 5;
5911 glueSearchRadius = 0;
5912
5913 printf("\tConnection name - %s\n", connectionTuple[i].name );
5914
5915 // Look for connection name in connection map
5916 status = get_mapAttrToIndexIndex(attrMap, (const char *) connectionTuple[i].name, &attrIndex);
5917 if (status == CAPS_NOTFOUND-303) {
5918 printf("\tName %s not found in attribute map of capsConnect!!!!\n", connectionTuple[i].name);
5919 continue;
5920 } else if (status != CAPS_SUCCESS0) return status;
5921
5922 // Do we have a json string?
5923 if (strncmp(connectionTuple[i].value, "{", 1) == 0) {
5924
5925 /*! \page feaConnection
5926 * \section jsonStringConnection JSON String Dictionary
5927 *
5928 * If "Value" is JSON string dictionary
5929 * \if (MYSTRAN || NASTRAN || ASTROS)
5930 * (e.g. "Value" = {"dofDependent": 1, "propertyType": "RigidBody"})
5931 * \endif
5932 * the following keywords ( = default values) may be used:
5933 *
5934 *
5935 * \if (MYSTRAN || NASTRAN)
5936 * <ul>
5937 * <li> <B>connectionType = RigidBody</B> </li> <br>
5938 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
5939 * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody, RigidBodyInterpolate.
5940 * </ul>
5941 * \elseif (ASTROS)
5942 * <ul>
5943 * <li> <B>connectionType = RigidBody</B> </li> <br>
5944 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
5945 * Options: Mass (scalar), Spring (scalar), RigidBody, RigidBodyInterpolate.
5946 * </ul>
5947 * \endif
5948 *
5949 */
5950 // Get connection Type
5951 keyWord = "connectionType";
5952 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
5953 if (status == CAPS_SUCCESS0) {
5954 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 5954, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
5955
5956 //{UnknownConnection, Mass, Spring, Damper, RigidBody}
5957 if (strcasecmp(keyValue, "\"Mass\"") == 0) connectionType = Mass;
5958 else if (strcasecmp(keyValue, "\"Spring\"") == 0) connectionType = Spring;
5959 else if (strcasecmp(keyValue, "\"Damper\"") == 0) connectionType = Damper;
5960 else if (strcasecmp(keyValue, "\"RigidBody\"") == 0) connectionType = RigidBody;
5961 else if (strcasecmp(keyValue, "\"RigidBodyInterpolate\"") == 0) connectionType = RigidBodyInterpolate;
5962 else {
5963 printf("\tUnrecognized \"%s\" specified (%s) for Connection tuple %s, current options are "
5964 "\"Mass, Spring, Damper, RigidBody, and RigidBodyInterpolate\"\n", keyWord,
5965 keyValue,
5966 connectionTuple[i].name);
5967 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5968
5969 return CAPS_NOTFOUND-303;
5970 }
5971
5972 } else {
5973
5974 printf("\tNo \"%s\" specified for Connection tuple %s, defaulting to RigidBody\n", keyWord,
5975 connectionTuple[i].name);
5976 connectionType = RigidBody;
5977 }
5978
5979 /*! \page feaConnection
5980 *
5981 * \if (MYSTRAN || NASTRAN || ASTROS)
5982 * <ul>
5983 * <li> <B>dofDependent = 0 </B> </li> <br>
5984 * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three
5985 * directions).
5986 * </ul>
5987 * \endif
5988 *
5989 */
5990 keyWord = "dofDependent";
5991 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
5992 if (status == CAPS_SUCCESS0) {
5993
5994 status = string_toInteger(keyValue, &dofDependent);
5995 if (keyValue != NULL((void*)0)) {
5996 EG_free(keyValue);
5997 keyValue = NULL((void*)0);
5998 }
5999 if (status != CAPS_SUCCESS0) return status;
6000 }
6001
6002
6003 /*! \page feaConnection
6004 *
6005 * \if (MYSTRAN || NASTRAN || ASTROS)
6006 * <ul>
6007 * <li> <B>componentNumberStart = 0 </B> </li> <br>
6008 * Component numbers / degrees of freedom of the starting point of the connection for mass,
6009 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6010 * </ul>
6011 * \endif
6012 */
6013 keyWord = "componentNumberStart";
6014 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6015 if (status == CAPS_SUCCESS0) {
6016
6017 status = string_toInteger(keyValue, &componentNumberStart);
6018 if (keyValue != NULL((void*)0)) {
6019 EG_free(keyValue);
6020 keyValue = NULL((void*)0);
6021 }
6022 if (status != CAPS_SUCCESS0) return status;
6023 }
6024
6025 /*! \page feaConnection
6026 *
6027 * \if (MYSTRAN || NASTRAN || ASTROS)
6028 * <ul>
6029 * <li> <B>componentNumberEnd= 0 </B> </li> <br>
6030 * Component numbers / degrees of freedom of the ending point of the connection for mass,
6031 * spring, damper elements (scalar), and rigid body interpolative connection ( 0 <= Integer <= 6).
6032 * </ul>
6033 * \endif
6034 *
6035 */
6036 keyWord = "componentNumberEnd";
6037 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6038 if (status == CAPS_SUCCESS0) {
6039
6040 status = string_toInteger(keyValue, &componentNumberEnd);
6041 if (keyValue != NULL((void*)0)) {
6042 EG_free(keyValue);
6043 keyValue = NULL((void*)0);
6044 }
6045 if (status != CAPS_SUCCESS0) return status;
6046 }
6047
6048 /*! \page feaConnection
6049 *
6050 * \if (MYSTRAN || NASTRAN || ASTROS)
6051 * <ul>
6052 * <li> <B>stiffnessConst = 0.0 </B> </li> <br>
6053 * Stiffness constant of a spring element (scalar).
6054 * </ul>
6055 * \endif
6056 */
6057 keyWord = "stiffnessConst";
6058 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6059 if (status == CAPS_SUCCESS0) {
6060
6061 status = string_toDouble(keyValue, &stiffnessConst);
6062 if (keyValue != NULL((void*)0)) {
6063 EG_free(keyValue);
6064 keyValue = NULL((void*)0);
6065 }
6066 if (status != CAPS_SUCCESS0) return status;
6067 }
6068
6069 /*! \page feaConnection
6070 *
6071 * \if (MYSTRAN || NASTRAN || ASTROS)
6072 * <ul>
6073 * <li> <B>dampingConst = 0.0 </B> </li> <br>
6074 * Damping coefficient/constant of a spring or damping element (scalar).
6075 * </ul>
6076 * \endif
6077 */
6078 keyWord = "dampingConst";
6079 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6080 if (status == CAPS_SUCCESS0) {
6081
6082 status = string_toDouble(keyValue, &dampingConst);
6083 if (keyValue != NULL((void*)0)) {
6084 EG_free(keyValue);
6085 keyValue = NULL((void*)0);
6086 }
6087 if (status != CAPS_SUCCESS0) return status;
6088 }
6089
6090 /*! \page feaConnection
6091 *
6092 * \if (MYSTRAN || NASTRAN || ASTROS)
6093 * <ul>
6094 * <li> <B>stressCoeff = 0.0 </B> </li> <br>
6095 * Stress coefficient of a spring element (scalar).
6096 * </ul>
6097 * \endif
6098 */
6099 keyWord = "stressCoeff";
6100 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6101 if (status == CAPS_SUCCESS0) {
6102
6103 status = string_toDouble(keyValue, &stressCoeff);
6104 if (keyValue != NULL((void*)0)) {
6105 EG_free(keyValue);
6106 keyValue = NULL((void*)0);
6107 }
6108 if (status != CAPS_SUCCESS0) return status;
6109 }
6110
6111 /*! \page feaConnection
6112 *
6113 * \if (MYSTRAN || NASTRAN || ASTROS)
6114 * <ul>
6115 * <li> <B>mass = 0.0 </B> </li> <br>
6116 * Mass of a mass element (scalar).
6117 * </ul>
6118 * \endif
6119 */
6120 keyWord = "mass";
6121 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6122 if (status == CAPS_SUCCESS0) {
6123
6124 status = string_toDouble(keyValue, &mass);
6125 if (keyValue != NULL((void*)0)) {
6126 EG_free(keyValue);
6127 keyValue = NULL((void*)0);
6128 }
6129 if (status != CAPS_SUCCESS0) return status;
6130 }
6131
6132 /* \page feaConnection
6133 *
6134 * \if (MYSTRAN || NASTRAN || ASTROS)
6135 * <ul>
6136 * <li> <B>glue = False </B> </li> <br>
6137 * Turn on gluing for the connection.
6138 * </ul>
6139 * \endif
6140 */
6141 keyWord = "glue";
6142 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6143 if (status == CAPS_SUCCESS0) {
6144
6145 status = string_toBoolean(keyValue, &glue);
6146 if (keyValue != NULL((void*)0)) {
6147 EG_free(keyValue);
6148 keyValue = NULL((void*)0);
6149 }
6150 if (status != CAPS_SUCCESS0) return status;
6151 }
6152
6153 /* \page feaConnection
6154 *
6155 * \if (MYSTRAN || NASTRAN || ASTROS)
6156 * <ul>
6157 * <li> <B>glueNumMaster = 5 </B> </li> <br>
6158 * Maximum number of the masters for a glue connections.
6159 * </ul>
6160 * \endif
6161 */
6162 keyWord = "glueNumMaster";
6163 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6164 if (status == CAPS_SUCCESS0) {
6165
6166 status = string_toInteger(keyValue, &glueNumMaster);
6167 if (keyValue != NULL((void*)0)) {
6168 EG_free(keyValue);
6169 keyValue = NULL((void*)0);
6170 }
6171 if (status != CAPS_SUCCESS0) return status;
6172 }
6173
6174 /* \page feaConnection
6175 *
6176 * \if (MYSTRAN || NASTRAN || ASTROS)
6177 * <ul>
6178 * <li> <B>glueSearchRadius = 0 </B> </li> <br>
6179 * Search radius when looking for masters for a glue connections.
6180 * </ul>
6181 * \endif
6182 */
6183 keyWord = "glueSearchRadius";
6184 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6185 if (status == CAPS_SUCCESS0) {
6186
6187 status = string_toDouble(keyValue, &glueSearchRadius);
6188 if (keyValue != NULL((void*)0)) {
6189 EG_free(keyValue);
6190 keyValue = NULL((void*)0);
6191 }
6192 if (status != CAPS_SUCCESS0) return status;
6193 }
6194
6195 /*! \page feaConnection
6196 *
6197 * \if (MYSTRAN || NASTRAN || ASTROS)
6198 * <ul>
6199 * <li> <B>weighting = 1 </B> </li> <br>
6200 * Weighting factor for a rigid body interpolative connections.
6201 * </ul>
6202 * \endif
6203 */
6204 keyWord = "weighting";
6205 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6206 if (status == CAPS_SUCCESS0) {
6207
6208 status = string_toDouble(keyValue, &weighting);
6209 if (keyValue != NULL((void*)0)) {
6210 EG_free(keyValue);
6211 keyValue = NULL((void*)0);
6212 }
6213 if (status != CAPS_SUCCESS0) return status;
6214 }
6215
6216 /*! \page feaConnection
6217 *
6218 * \if (MYSTRAN || NASTRAN || ASTROS)
6219 * <ul>
6220 * <li> <B>groupName = "(no default)"</B> </li> <br>
6221 * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the
6222 * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...].
6223 * </ul>
6224 * \endif
6225 */
6226 numGroupName = 0;
6227 keyWord = "groupName";
6228 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6229 if (status == CAPS_SUCCESS0) {
6230
6231 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
6232 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
6233 AIM_NOTNULL(groupName, aimInfo, status){ if (groupName == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 6233, __func__, 1, "%s == NULL!", "groupName"
); goto cleanup; } }
;
6234
6235 if (status != CAPS_SUCCESS0) return status;
6236 if (glue == (int) true1 && connectionType != RigidBodyInterpolate) {
6237 printf("\tInvalid connectionType while glue = True, setting glue to False!\n");
6238 glue = (int) false0;
6239 }
6240
6241 if (glue == (int) true1 && connectionType == RigidBodyInterpolate) {
6242 status = fea_glueMesh(aimInfo,
6243 &feaProblem->feaMesh,
6244 i+1, //connectionID
6245 connectionType,
6246 dofDependent,
6247 connectionTuple[i].name,
6248 numGroupName,
6249 groupName,
6250 attrMap,
6251 glueNumMaster,
6252 glueSearchRadius,
6253 &feaProblem->numConnect,
6254 &feaProblem->feaConnect);
6255 if (status != CAPS_SUCCESS0) return status;
6256
6257 } else {
6258
6259
6260 destNode = (int *) EG_alloc(feaProblem->feaMesh.numNode*sizeof(int));
6261 if (destNode == NULL((void*)0)) {
6262 (void) string_freeArray(numGroupName, &groupName);
6263 return EGADS_MALLOC-4;
6264 }
6265
6266 // Find the "source" node in the mesh
6267 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6268
6269 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6270
6271 // If "source" doesn't match - continue
6272 if (feaData->connectIndex != attrIndex) continue;
6273
6274 numDestNode = 0;
6275
6276 // Lets loop through the group names and create the connections
6277 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
6278
6279 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndexDest);
6280 if (status == CAPS_NOTFOUND-303) {
6281 printf("\tName %s not found in attribute map of capsConnects!!!!\n", groupName[groupIndex]);
6282 continue;
6283 } else if (status != CAPS_SUCCESS0) {
6284 (void) string_freeArray(numGroupName, &groupName);
6285 AIM_FREE(destNode){ EG_free(destNode); destNode = ((void*)0); };
6286 return status;
6287 }
6288
6289 // Find the "destination" node in the mesh
6290 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6291
6292 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6293
6294 // If the "destination" doesn't match - continue
6295 if (feaDataDest->connectIndex != attrIndexDest) continue;
6296
6297 destNode[numDestNode] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6298 numDestNode += 1;
6299 } // End destination loop
6300
6301 } // End group loop
6302
6303 if (numDestNode <= 0) {
6304 printf("\tNo destination nodes found for connection %s\n", connectionTuple[i].name);
6305 } else {
6306
6307 status = fea_setConnection(connectionTuple[i].name,
6308 connectionType,
6309 i+1,
6310 feaProblem->feaMesh.numElement,
6311 dofDependent,
6312 stiffnessConst,
6313 dampingConst,
6314 stressCoeff,
6315 componentNumberStart,
6316 componentNumberEnd,
6317 feaProblem->feaMesh.node[nodeIndex].nodeID,
6318 weighting,
6319 componentNumberEnd,
6320 numDestNode, destNode,
6321 &feaProblem->numConnect,
6322 &feaProblem->feaConnect);
6323 if (status != CAPS_SUCCESS0) {
6324 (void) string_freeArray(numGroupName, &groupName);
6325 if (destNode !=NULL((void*)0)) EG_free(destNode);
6326 return status;
6327 }
6328 }
6329 } // End source loop
6330 } // Glue ifelse
6331
6332 if (destNode !=NULL((void*)0)) EG_free(destNode);
6333 destNode = NULL((void*)0);
6334
6335 status = string_freeArray(numGroupName, &groupName);
6336 if (status != CAPS_SUCCESS0) return status;
6337
6338 } else {
6339 printf("\tNo \"%s\" specified for Connection tuple %s!\n", keyWord, connectionTuple[i].name);
6340 }
6341
6342 // Create automatic connections from the "capsConnectLink" tag
6343 printf("\tLooking for automatic connections from the use of capsConnectLink for %s\n", connectionTuple[i].name);
6344
6345 destNode = (int *) EG_alloc(feaProblem->feaMesh.numNode*sizeof(int));
6346 if (destNode == NULL((void*)0)) return EGADS_MALLOC-4;
6347
6348 // Find the "source" node in the mesh
6349 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6350
6351 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6352
6353 // If "source" doesn't match - continue
6354 if (feaData->connectIndex != attrIndex) continue;
6355
6356 numDestNode = 0;
6357 // Find the "destination" node in the mesh
6358 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6359
6360 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6361
6362 // If the "destination" doesn't match - continue
6363 if (feaDataDest->connectLinkIndex != attrIndex) continue;
6364
6365 destNode[numDestNode] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6366 numDestNode += 1;
6367 } // End destination loop
6368
6369 if (numDestNode > 0) {
6370 status = fea_setConnection(connectionTuple[i].name,
6371 connectionType,
6372 i+1,
6373 feaProblem->feaMesh.numElement,
6374 dofDependent,
6375 stiffnessConst,
6376 dampingConst,
6377 stressCoeff,
6378 componentNumberStart,
6379 componentNumberEnd,
6380 feaProblem->feaMesh.node[nodeIndex].nodeID,
6381 weighting,
6382 componentNumberEnd,
6383 numDestNode, destNode,
6384 &feaProblem->numConnect,
6385 &feaProblem->feaConnect);
6386 if (status != CAPS_SUCCESS0) {
6387 if (destNode !=NULL((void*)0)) EG_free(destNode);
6388 return status;
6389 }
6390 }
6391
6392 if (numDestNode > 0) {
6393 printf("\t%d automatic connections were made for capsConnect %s (node id %d)\n", numDestNode,
6394 connectionTuple[i].name,
6395 feaProblem->feaMesh.node[nodeIndex].nodeID);
6396 }
6397 } // End source loop
6398
6399 if (destNode !=NULL((void*)0)) EG_free(destNode);
6400 destNode = NULL((void*)0);
6401
6402 } else {
6403
6404 /*! \page feaConnection
6405 * \section keyStringConnection Single Value String
6406 *
6407 * If "Value" is a string, the string value may correspond to an entry in a predefined connection lookup
6408 * table. NOT YET IMPLEMENTED!!!!
6409 *
6410 */
6411
6412 // Call some look up table maybe?
6413 printf("\tError: Connection tuple value is expected to be a JSON string\n");
6414 return CAPS_BADVALUE-311;
6415
6416 }
6417 }
6418
6419 if (keyValue != NULL((void*)0)) {
6420 EG_free(keyValue);
6421 keyValue = NULL((void*)0);
6422 }
6423
6424 printf("\tDone getting FEA connections\n");
6425 status = CAPS_SUCCESS0;
6426cleanup:
6427 return status;
6428}
6429
6430#ifdef FEA_GETCONNECTIONORIG_DEPREICATE
6431// Get the Connections properties from a capsTuple and create connections based on the mesh
6432static int fea_getConnectionOrig(int numConnectionTuple,
6433 capsTuple connectionTuple[],
6434 mapAttrToIndexStruct *attrMap,
6435 feaProblemStruct *feaProblem) {
6436
6437 /* \page feaConnection FEA Connection
6438 * Structure for the connection tuple = ("Connection Name", "Value").
6439 * "Connection Name" defines the reference name to the capsConnect being specified and denotes the "source" node
6440 * for the connection.
6441 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConnection) or a single string keyword
6442 * (see Section \ref keyStringConnection).
6443 */
6444
6445 int status; //Function return
6446
6447 int i, groupIndex, nodeIndex, nodeIndexDest, counter = 0; // Indexing
6448
6449 char *keyValue = NULL((void*)0); // Key values from tuple searches
6450 char *keyWord = NULL((void*)0); // Key words to find in the tuples
6451
6452 int numGroupName = 0;
6453 char **groupName = NULL((void*)0);
6454 int attrIndex, attrIndexDest;
6455
6456 // Values to set
6457 feaConnectionTypeEnum connectionType;
6458 int dofDependent = 0, componentNumberStart = 0, componentNumberEnd = 0;
6459 double stiffnessConst = 0.0, dampingConst = 0.0, stressCoeff = 0.0, mass = 0.0;
6460
6461 feaMeshDataStruct *feaData, *feaDataDest;
6462
6463 // Destroy our support structures coming in if aren't 0 and NULL already
6464 if (feaProblem->feaConnect != NULL((void*)0)) {
6465 for (i = 0; i < feaProblem->numConnect; i++) {
6466 status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]);
6467 if (status != CAPS_SUCCESS0) return status;
6468 }
6469 }
6470 if (feaProblem->feaConnect != NULL((void*)0)) EG_free(feaProblem->feaConnect);
6471 feaProblem->feaConnect = NULL((void*)0);
6472 feaProblem->numConnect = 0;
6473
6474 printf("\nGetting FEA connections.......\n");
6475
6476 printf("\tNumber of connection tuples - %d\n", numConnectionTuple);
6477
6478 // Loop through tuples and fill out the support structures
6479 for (i = 0; i < numConnectionTuple; i++) {
6480
6481 // Reset defaults
6482 dofDependent = componentNumberStart = componentNumberEnd = 0;
6483 stiffnessConst = dampingConst = stressCoeff = mass = 0.0;
6484
6485 printf("\tConnection name - %s\n", connectionTuple[i].name );
6486
6487 // Look for connection name in connection map
6488 status = get_mapAttrToIndexIndex(attrMap, (const char *) connectionTuple[i].name, &attrIndex);
6489 if (status == CAPS_NOTFOUND-303) {
6490 printf("\tName %s not found in attribute map of capsConnect!!!!\n", connectionTuple[i].name);
6491 continue;
6492 } else if (status != CAPS_SUCCESS0) return status;
6493
6494 // Do we have a json string?
6495 if (strncmp(connectionTuple[i].value, "{", 1) == 0) {
6496
6497 /* \page feaConnection
6498 * \section jsonStringConnection JSON String Dictionary
6499 *
6500 * If "Value" is JSON string dictionary
6501 * \if (MYSTRAN || NASTRAN || ASTROS)
6502 * (e.g. "Value" = {"dofDependent": 1, "propertyType": "RigidBody"})
6503 * \endif
6504 * the following keywords ( = default values) may be used:
6505 *
6506 *
6507 * \if (MYSTRAN || NASTRAN)
6508 * <ul>
6509 * <li> <B>connectionType = RigidBody</B> </li> <br>
6510 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
6511 * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody.
6512 * </ul>
6513 * \elseif (ASTROS)
6514 * <ul>
6515 * <li> <B>connectionType = RigidBody</B> </li> <br>
6516 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
6517 * Options: Mass (scalar), Spring (scalar), RigidBody.
6518 * </ul>
6519 * \elseif ABAQUS
6520 *
6521 * Something else ....
6522 *
6523 * \else
6524 * <ul>
6525 * <li> <B>connectionType = RigidBody</B> </li> <br>
6526 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
6527 * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody.
6528 * </ul>
6529 * \endif
6530 *
6531 */
6532
6533 // Get connection Type
6534 keyWord = "connectionType";
6535 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6536 if (status == CAPS_SUCCESS0) {
6537
6538 //{UnknownConnection, Mass, Spring, Damper, RigidBody}
6539 if (strcasecmp(keyValue, "\"Mass\"") == 0) connectionType = Mass;
6540 else if (strcasecmp(keyValue, "\"Spring\"") == 0) connectionType = Spring;
6541 else if (strcasecmp(keyValue, "\"Damper\"") == 0) connectionType = Damper;
6542 else if (strcasecmp(keyValue, "\"RigidBody\"") == 0) connectionType = RigidBody;
6543 else {
6544 printf("\tUnrecognized \"%s\" specified (%s) for Connection tuple %s, current options are "
6545 "\"Mass, Spring, Damper, and RigidBody\"\n", keyWord,
6546 keyValue,
6547 connectionTuple[i].name);
6548 if (keyValue != NULL((void*)0)) {
6549 EG_free(keyValue);
6550 keyValue = NULL((void*)0);
6551 }
6552
6553 return CAPS_NOTFOUND-303;
6554 }
6555
6556 } else {
6557
6558 printf("\tNo \"%s\" specified for Connection tuple %s, defaulting to RigidBody\n", keyWord,
6559 connectionTuple[i].name);
6560 connectionType = RigidBody;
6561 }
6562
6563 /* \page feaConnection
6564 *
6565 * \if (MYSTRAN || NASTRAN || ASTROS)
6566 * <ul>
6567 * <li> <B>dofDependent = 0 </B> </li> <br>
6568 * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three
6569 * directions).
6570 * </ul>
6571 * \elseif ABAQUS
6572 *
6573 * Something else ....
6574 *
6575 * \else
6576 * <ul>
6577 * <li> <B>dofDependent = 0 </B> </li> <br>
6578 * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three
6579 * directions).
6580 * </ul>
6581 * \endif
6582 *
6583 */
6584 keyWord = "dofDependent";
6585 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6586 if (status == CAPS_SUCCESS0) {
6587
6588 status = string_toInteger(keyValue, &dofDependent);
6589 if (keyValue != NULL((void*)0)) {
6590 EG_free(keyValue);
6591 keyValue = NULL((void*)0);
6592 }
6593 if (status != CAPS_SUCCESS0) return status;
6594 }
6595
6596
6597 /* \page feaConnection
6598 *
6599 * \if (MYSTRAN || NASTRAN || ASTROS)
6600 * <ul>
6601 * <li> <B>componentNumberStart = 0 </B> </li> <br>
6602 * Component numbers / degrees of freedom of the starting point of the connection for mass,
6603 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6604 * </ul>
6605 * \elseif ABAQUS
6606 *
6607 * Something else ....
6608 *
6609 * \else
6610 * <ul>
6611 * <li> <B>componentNumberStart = 0 </B> </li> <br>
6612 * Component numbers / degrees of freedom of the starting point of the connection for mass,
6613 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6614 * </ul>
6615 * \endif
6616 *
6617 */
6618 keyWord = "componentNumberStart";
6619 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6620 if (status == CAPS_SUCCESS0) {
6621
6622 status = string_toInteger(keyValue, &componentNumberStart);
6623 if (keyValue != NULL((void*)0)) {
6624 EG_free(keyValue);
6625 keyValue = NULL((void*)0);
6626 }
6627 if (status != CAPS_SUCCESS0) return status;
6628 }
6629
6630 /* \page feaConnection
6631 *
6632 * \if (MYSTRAN || NASTRAN || ASTROS)
6633 * <ul>
6634 * <li> <B>componentNumberEnd= 0 </B> </li> <br>
6635 * Component numbers / degrees of freedom of the ending point of the connection for mass,
6636 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6637 * </ul>
6638 * \elseif ABAQUS
6639 *
6640 * Something else ....
6641 *
6642 * \else
6643 * <ul>
6644 * <li> <B>componentNumberEnd = 0 </B> </li> <br>
6645 * Component numbers / degrees of freedom of the ending point of the connection for mass,
6646 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6647 * </ul>
6648 * \endif
6649 *
6650 */
6651 keyWord = "componentNumberEnd";
6652 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6653 if (status == CAPS_SUCCESS0) {
6654
6655 status = string_toInteger(keyValue, &componentNumberEnd);
6656 if (keyValue != NULL((void*)0)) {
6657 EG_free(keyValue);
6658 keyValue = NULL((void*)0);
6659 }
6660 if (status != CAPS_SUCCESS0) return status;
6661 }
6662
6663 /* \page feaConnection
6664 *
6665 * \if (MYSTRAN || NASTRAN || ASTROS)
6666 * <ul>
6667 * <li> <B>stiffnessConst = 0.0 </B> </li> <br>
6668 * Stiffness constant of a spring element (scalar).
6669 * </ul>
6670 * \elseif ABAQUS
6671 *
6672 * Something else ....
6673 *
6674 * \else
6675 * <ul>
6676 * <li> <B>stiffnessConst = 0.00 </B> </li> <br>
6677 * Stiffness constant of a spring element (scalar).
6678 * </ul>
6679 * \endif
6680 *
6681 */
6682 keyWord = "stiffnessConst";
6683 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6684 if (status == CAPS_SUCCESS0) {
6685
6686 status = string_toDouble(keyValue, &stiffnessConst);
6687 if (keyValue != NULL((void*)0)) {
6688 EG_free(keyValue);
6689 keyValue = NULL((void*)0);
6690 }
6691 if (status != CAPS_SUCCESS0) return status;
6692 }
6693
6694 /* \page feaConnection
6695 *
6696 * \if (MYSTRAN || NASTRAN || ASTROS)
6697 * <ul>
6698 * <li> <B>dampingConst = 0.0 </B> </li> <br>
6699 * Damping coefficient/constant of a spring or damping element (scalar).
6700 * </ul>
6701 * \elseif ABAQUS
6702 *
6703 * Something else ....
6704 *
6705 * \else
6706 * <ul>
6707 * <li> <B>dampingConst = 0.0 </B> </li> <br>
6708 * Damping constant of a spring or damping element (scalar).
6709 * </ul>
6710 * \endif
6711 *
6712 */
6713 keyWord = "dampingConst";
6714 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6715 if (status == CAPS_SUCCESS0) {
6716
6717 status = string_toDouble(keyValue, &dampingConst);
6718 if (keyValue != NULL((void*)0)) {
6719 EG_free(keyValue);
6720 keyValue = NULL((void*)0);
6721 }
6722 if (status != CAPS_SUCCESS0) return status;
6723 }
6724
6725 /* \page feaConnection
6726 *
6727 * \if (MYSTRAN || NASTRAN || ASTROS)
6728 * <ul>
6729 * <li> <B>stressCoeff = 0.0 </B> </li> <br>
6730 * Stress coefficient of a spring element (scalar).
6731 * </ul>
6732 * \elseif ABAQUS
6733 *
6734 * Something else ....
6735 *
6736 * \else
6737 * <ul>
6738 * <li> <B>stressCoeff = 0.0 </B> </li> <br>
6739 * Stress coefficient of a spring element (scalar).
6740 * </ul>
6741 * \endif
6742 *
6743 */
6744 keyWord = "stressCoeff";
6745 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6746 if (status == CAPS_SUCCESS0) {
6747
6748 status = string_toDouble(keyValue, &stressCoeff);
6749 if (keyValue != NULL((void*)0)) {
6750 EG_free(keyValue);
6751 keyValue = NULL((void*)0);
6752 }
6753 if (status != CAPS_SUCCESS0) return status;
6754 }
6755
6756 /* \page feaConnection
6757 *
6758 * \if (MYSTRAN || NASTRAN || ASTROS)
6759 * <ul>
6760 * <li> <B>mass = 0.0 </B> </li> <br>
6761 * Mass of a mass element (scalar).
6762 * </ul>
6763 * \elseif ABAQUS
6764 *
6765 * Something else ....
6766 *
6767 * \else
6768 * <ul>
6769 * <li> <B>mass = 0.0 </B> </li> <br>
6770 * Mass of a mass element (scalar).
6771 * </ul>
6772 * \endif
6773 *
6774 */
6775 keyWord = "mass";
6776 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6777 if (status == CAPS_SUCCESS0) {
6778
6779 status = string_toDouble(keyValue, &mass);
6780 if (keyValue != NULL((void*)0)) {
6781 EG_free(keyValue);
6782 keyValue = NULL((void*)0);
6783 }
6784 if (status != CAPS_SUCCESS0) return status;
6785 }
6786
6787 /* \page feaConnection
6788 *
6789 * \if (MYSTRAN || NASTRAN || ASTROS)
6790 * <ul>
6791 * <li> <B>groupName = "(no default)"</B> </li> <br>
6792 * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the
6793 * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...].
6794 * </ul>
6795 * \elseif ABAQUS
6796 *
6797 * Something else ....
6798 *
6799 * \else
6800 * <ul>
6801 * <li> <B>groupName = "(no default)"</B> </li> <br>
6802 * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the
6803 * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...].
6804 * </ul>
6805 * \endif
6806 *
6807 */
6808 numGroupName = 0;
6809 keyWord = "groupName";
6810 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6811 if (status == CAPS_SUCCESS0) {
6812
6813 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
6814 if (keyValue != NULL((void*)0)) EG_free(keyValue);
6815 keyValue = NULL((void*)0);
6816
6817 if (status != CAPS_SUCCESS0) return status;
6818
6819 // Lets loop through the group names and create the connections
6820 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
6821
6822 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndexDest);
6823 if (status == CAPS_NOTFOUND-303) {
6824 printf("\tName %s not found in attribute map of capsConnects!!!!\n", groupName[groupIndex]);
6825 continue;
6826 } else if (status != CAPS_SUCCESS0) {
6827 (void) string_freeArray(numGroupName, &groupName);
6828 return status;
6829 }
6830
6831 // Find the "source" node in the mesh
6832 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6833
6834 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6835
6836 // If "source" doesn't match - continue
6837 if (feaData->connectIndex != attrIndex) continue;
6838
6839 // Find the "destination" node in the mesh
6840 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6841
6842 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6843
6844 // If the "destination" doesn't match - continue
6845 if (feaDataDest->connectIndex != attrIndexDest) continue;
6846
6847 feaProblem->numConnect += 1;
6848
6849 if (feaProblem->numConnect == 1) {
6850 feaProblem->feaConnect = (feaConnectionStruct *) EG_alloc(sizeof(feaConnectionStruct));
6851 } else {
6852 feaProblem->feaConnect = (feaConnectionStruct *) EG_reall(feaProblem->feaConnect ,
6853 feaProblem->numConnect*sizeof(feaConnectionStruct));
6854 }
6855
6856 if (feaProblem->feaConnect == NULL((void*)0)) {
6857 feaProblem->numConnect = 0;
6858 (void) string_freeArray(numGroupName, &groupName);
6859 return EGADS_MALLOC-4;
6860 }
6861
6862 status = initiate_feaConnectionStruct(&feaProblem->feaConnect[feaProblem->numConnect-1]);
6863 if (status != CAPS_SUCCESS0) return status;
6864
6865 feaProblem->feaConnect[feaProblem->numConnect-1].name = (char *) EG_alloc((strlen(connectionTuple[i].name) + 1)*sizeof(char));
6866 if (feaProblem->feaConnect[feaProblem->numConnect-1].name == NULL((void*)0)) {
6867 (void) string_freeArray(numGroupName, &groupName);
6868 return EGADS_MALLOC-4;
6869 }
6870
6871 memcpy(feaProblem->feaConnect[feaProblem->numConnect-1].name,
6872 connectionTuple[i].name,
6873 strlen(connectionTuple[i].name)*sizeof(char));
6874 feaProblem->feaConnect[feaProblem->numConnect-1].name[strlen(connectionTuple[i].name)] = '\0';
6875
6876 feaProblem->feaConnect[feaProblem->numConnect-1].connectionID = i+1; // ConnectionTuple index
6877
6878 feaProblem->feaConnect[feaProblem->numConnect-1].connectionType = connectionType;
6879 feaProblem->feaConnect[feaProblem->numConnect-1].elementID = feaProblem->numConnect + feaProblem->feaMesh.numElement;
6880 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[0] = feaProblem->feaMesh.node[nodeIndex].nodeID;
6881 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[1] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6882
6883 feaProblem->feaConnect[feaProblem->numConnect-1].dofDependent = dofDependent;
6884 feaProblem->feaConnect[feaProblem->numConnect-1].stiffnessConst = stiffnessConst;
6885 feaProblem->feaConnect[feaProblem->numConnect-1].dampingConst = dampingConst;
6886 feaProblem->feaConnect[feaProblem->numConnect-1].stressCoeff = stressCoeff;
6887 feaProblem->feaConnect[feaProblem->numConnect-1].mass = mass;
6888 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberStart = componentNumberStart;
6889 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberEnd = componentNumberEnd;
6890 } // End destination loop
6891 } // End source loop
6892 } // End group loop
6893
6894 status = string_freeArray(numGroupName, &groupName);
6895 if (status != CAPS_SUCCESS0) return status;
6896
6897 } else {
6898 printf("\tNo \"%s\" specified for Connection tuple %s!\n", keyWord,
6899 connectionTuple[i].name);
6900 }
6901
6902
6903 // Create automatic connections from the "capsConnectLink" tag
6904 printf("\tLooking for automatic connections from the use of capsConnectLink for %s\n", connectionTuple[i].name);
6905
6906 // Find the "source" node in the mesh
6907 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6908
6909 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6910
6911 // If "source" doesn't match - continue
6912 if (feaData->connectIndex != attrIndex) continue;
6913
6914 counter = 0;
6915 // Find the "destination" node in the mesh
6916 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6917
6918 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6919
6920 // If the "destination" doesn't match - continue
6921 if (feaDataDest->connectLinkIndex != attrIndex) continue;
6922
6923 counter +=1;
6924
6925 feaProblem->numConnect += 1;
6926
6927 if (feaProblem->numConnect == 1) {
6928 feaProblem->feaConnect = (feaConnectionStruct *) EG_alloc(sizeof(feaConnectionStruct));
6929 } else {
6930 feaProblem->feaConnect = (feaConnectionStruct *) EG_reall(feaProblem->feaConnect ,
6931 feaProblem->numConnect*sizeof(feaConnectionStruct));
6932 }
6933
6934 if (feaProblem->feaConnect == NULL((void*)0)) {
6935 feaProblem->numConnect = 0;
6936 return EGADS_MALLOC-4;
6937 }
6938
6939 feaProblem->feaConnect[feaProblem->numConnect-1].name = (char *) EG_alloc((strlen(connectionTuple[i].name) + 1)*sizeof(char));
6940 if (feaProblem->feaConnect[feaProblem->numConnect-1].name == NULL((void*)0)) return EGADS_MALLOC-4;
6941
6942 memcpy(feaProblem->feaConnect[feaProblem->numConnect-1].name,
6943 connectionTuple[i].name,
6944 strlen(connectionTuple[i].name)*sizeof(char));
6945 feaProblem->feaConnect[feaProblem->numConnect-1].name[strlen(connectionTuple[i].name)] = '\0';
6946
6947 feaProblem->feaConnect[feaProblem->numConnect-1].connectionID = i+1; // ConnectionTuple index
6948
6949 feaProblem->feaConnect[feaProblem->numConnect-1].connectionType = connectionType;
6950 feaProblem->feaConnect[feaProblem->numConnect-1].elementID = feaProblem->numConnect + feaProblem->feaMesh.numElement;
6951 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[0] = feaProblem->feaMesh.node[nodeIndex].nodeID;
6952 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[1] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6953
6954 feaProblem->feaConnect[feaProblem->numConnect-1].dofDependent = dofDependent;
6955 feaProblem->feaConnect[feaProblem->numConnect-1].stiffnessConst = stiffnessConst;
6956 feaProblem->feaConnect[feaProblem->numConnect-1].dampingConst = dampingConst;
6957 feaProblem->feaConnect[feaProblem->numConnect-1].stressCoeff = stressCoeff;
6958 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberStart = componentNumberStart;
6959 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberEnd = componentNumberEnd;
6960 } // End destination loop
6961
6962 printf("\t%d automatic connections were made for capsConnect %s\n", counter,
6963 connectionTuple[i].name);
6964 } // End source loop
6965 } else {
6966
6967 /* \page feaConnection
6968 * \section keyStringConnection Single Value String
6969 *
6970 * If "Value" is a string, the string value may correspond to an entry in a predefined connection lookup
6971 * table. NOT YET IMPLEMENTED!!!!
6972 *
6973 */
6974
6975 // Call some look up table maybe?
6976 printf("\tError: Connection tuple value is expected to be a JSON string\n");
6977 return CAPS_BADVALUE-311;
6978
6979 }
6980 }
6981
6982 if (keyValue != NULL((void*)0)) {
6983 EG_free(keyValue);
6984 keyValue = NULL((void*)0);
6985 }
6986
6987 printf("\tDone getting FEA connections\n");
6988 return CAPS_SUCCESS0;
6989}
6990#endif
6991
6992// Get the load properties from a capsTuple
6993int fea_getLoad(void *aimInfo,
6994 int numLoadTuple,
6995 capsTuple loadTuple[],
6996 mapAttrToIndexStruct *attrMap,
6997 feaProblemStruct *feaProblem) {
6998
6999 /*! \page feaLoad FEA Load
7000 * Structure for the load tuple = ("Load Name", "Value").
7001 * "Load Name" defines the reference name for the load being specified.
7002 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringLoad) or a single string keyword
7003 * (see Section \ref keyStringLoad).
7004 */
7005
7006 int status; //Function return
7007
7008 int i, groupIndex, attrIndex, nodeIndex, elementIndex; // Indexing
7009
7010 char *keyValue = NULL((void*)0); // Key values from tuple searches
7011 char *keyWord = NULL((void*)0); // Key words to find in the tuples
7012
7013 int numGroupName = 0;
7014 char **groupName = NULL((void*)0);
7015
7016 char *tempString = NULL((void*)0); // Temporary string holder
7017
7018 feaMeshDataStruct *feaData;
7019
7020 // Destroy our load structures coming in if aren't 0 and NULL already
7021 if (feaProblem->feaLoad != NULL((void*)0)) {
7022 for (i = 0; i < feaProblem->numLoad; i++) {
7023 status = destroy_feaLoadStruct(&feaProblem->feaLoad[i]);
7024 if (status != CAPS_SUCCESS0) return status;
7025 }
7026 }
7027 AIM_FREE(feaProblem->feaLoad){ EG_free(feaProblem->feaLoad); feaProblem->feaLoad = (
(void*)0); }
;
7028 feaProblem->numLoad = 0;
7029
7030 printf("\nGetting FEA loads.......\n");
7031
7032 feaProblem->numLoad = numLoadTuple;
7033
7034 printf("\tNumber of loads - %d\n", feaProblem->numLoad);
7035
7036 // Allocate loads
7037 if (feaProblem->numLoad > 0) {
7038 feaProblem->feaLoad = (feaLoadStruct *) EG_alloc(feaProblem->numLoad * sizeof(feaLoadStruct));
7039
7040 if (feaProblem->feaLoad == NULL((void*)0) ) return EGADS_MALLOC-4;
7041 }
7042
7043 // Initiate loads to default values
7044 for (i = 0; i < feaProblem->numLoad; i++) {
7045 status = initiate_feaLoadStruct(&feaProblem->feaLoad[i]);
7046 if (status != CAPS_SUCCESS0) return status;
7047 }
7048
7049 // Loop through tuples and fill out the load structures
7050 for (i = 0; i < feaProblem->numLoad; i++) {
7051
7052 printf("\tLoad name - %s\n", loadTuple[i].name );
7053
7054 // Set load name to tuple attribute name
7055 feaProblem->feaLoad[i].name = (char *) EG_alloc((strlen(loadTuple[i].name) + 1)*sizeof(char));
7056 if (feaProblem->feaLoad[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
7057
7058 memcpy(feaProblem->feaLoad[i].name, loadTuple[i].name, strlen(loadTuple[i].name)*sizeof(char));
7059 feaProblem->feaLoad[i].name[strlen(loadTuple[i].name)] = '\0';
7060
7061 // Set load id -> 1 bias
7062 feaProblem->feaLoad[i].loadID = i+1;
7063
7064 // Do we have a json string?
7065 if (strncmp(loadTuple[i].value, "{", 1) == 0) {
7066 //printf("JSON String - %s\n", constraintTuple[i].value);
7067
7068 /*! \page feaLoad
7069 * \section jsonStringLoad JSON String Dictionary
7070 *
7071 * If "Value" is JSON string dictionary
7072 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7073 * (e.g. "Value" = {"groupName": "plate", "loadType": "Pressure", "pressureForce": 2000000.0})
7074 * \endif
7075 * the following keywords ( = default values) may be used:
7076 *
7077 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7078 * <ul>
7079 * <li> <B>loadType = "(no default)"</B> </li> <br>
7080 * Type of load. Options: "GridForce", "GridMoment", "Rotational", "Thermal",
7081 * "Pressure", "PressureDistribute", "PressureExternal", "TermalExternal", "Gravity".
7082 * </ul>
7083 * \elseif ABAQUS
7084 * <ul>
7085 * <li> <B>loadType = "(no default)"</B> </li> <br>
7086 * Type of load. Options: "Pressure", "Gravity".
7087 * </ul>
7088 * \elseif HSM
7089 * <ul>
7090 * <li> <B>loadType = "(no default)"</B> </li> <br>
7091 * Type of load. Options: "GridForce", "GridMoment", "LineForce", "LineMoment", "Rotational",
7092 * "Pressure", "PressureDistribute", "PressureExternal", "Gravity".
7093 * </ul>
7094 * \else
7095 * \endif
7096 *
7097 */
7098 // Get load Type
7099 keyWord = "loadType";
7100 status = search_jsonDictionary(loadTuple[i].value, keyWord, &keyValue);
7101 if (status == CAPS_SUCCESS0) {
7102 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 7102, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
7103
7104 //{UnknownLoad, GridForce, GridMoment, Gravity, Pressure, Rotational, Thermal}
7105 if (strcasecmp(keyValue, "\"GridForce\"") == 0) feaProblem->feaLoad[i].loadType = GridForce;
7106 else if (strcasecmp(keyValue, "\"GridMoment\"") == 0) feaProblem->feaLoad[i].loadType = GridMoment;
7107 else if (strcasecmp(keyValue, "\"LineForce\"") == 0) feaProblem->feaLoad[i].loadType = LineForce;
7108 else if (strcasecmp(keyValue, "\"LineMoment\"") == 0) feaProblem->feaLoad[i].loadType = LineMoment;
7109 else if (strcasecmp(keyValue, "\"Rotational\"") == 0) feaProblem->feaLoad[i].loadType = Rotational;
7110 else if (strcasecmp(keyValue, "\"Thermal\"") == 0) feaProblem->feaLoad[i].loadType = Thermal;
7111 else if (strcasecmp(keyValue, "\"Pressure\"") == 0) feaProblem->feaLoad[i].loadType = Pressure;
7112 else if (strcasecmp(keyValue, "\"PressureDistribute\"") == 0) feaProblem->feaLoad[i].loadType = PressureDistribute;
7113 else if (strcasecmp(keyValue, "\"PressureExternal\"") == 0) feaProblem->feaLoad[i].loadType = PressureExternal;
7114 else if (strcasecmp(keyValue, "\"ThermalExternal\"") == 0) feaProblem->feaLoad[i].loadType = ThermalExternal;
7115 else if (strcasecmp(keyValue, "\"Gravity\"") == 0) feaProblem->feaLoad[i].loadType = Gravity;
7116 else {
7117 printf("\tUnrecognized \"%s\" specified (%s) for Load tuple %s\n", keyWord,
7118 keyValue,
7119 loadTuple[i].name);
7120 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7121 return CAPS_NOTFOUND-303;
7122 }
7123
7124 } else {
7125 printf("\t\"loadType\" variable not found in tuple %s, this is required input!!\n", loadTuple[i].name);
7126
7127 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7128 return status;
7129 }
7130
7131 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
7132
7133 // Get load node/element set
7134 /*! \page feaLoad
7135 *
7136 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7137 * <ul>
7138 * <li> <B>groupName = "(no default)"</B> </li> <br>
7139 * Single or list of <c>capsLoad</c> names on which to apply the load
7140 * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the load tuple name will be
7141 * used.
7142 * </ul>
7143 * \endif
7144 *
7145 */
7146 keyWord = "groupName";
7147 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7148 if (status == CAPS_SUCCESS0) {
7149
7150 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7151 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7152 keyValue = NULL((void*)0);
7153
7154 if (status != CAPS_SUCCESS0) return status;
7155
7156 } else {
7157
7158 printf("\tNo \"%s\" specified for Load tuple %s, going to use load name\n", keyWord,
7159 loadTuple[i].name);
7160
7161 status = string_toStringDynamicArray(loadTuple[i].name, &numGroupName, &groupName);
7162 if (status != CAPS_SUCCESS0) return status;
7163
7164 }
7165
7166 // Determine how many element/point loads we have
7167 feaProblem->feaLoad[i].numGridID = 0;
7168 feaProblem->feaLoad[i].numElementID = 0;
7169 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7170
7171 // Do nothing for PressureExternal, ThermalExternal, and Gravity loads
7172 if (feaProblem->feaLoad[i].loadType == PressureExternal) continue;
7173 if (feaProblem->feaLoad[i].loadType == ThermalExternal) continue;
7174 if (feaProblem->feaLoad[i].loadType == Gravity) continue;
7175
7176 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex);
7177
7178 if (status == CAPS_NOTFOUND-303) {
7179 printf("\tName %s not found in attribute map of capsLoads!!!!\n", groupName[groupIndex]);
7180 continue;
7181
7182 } else if (status != CAPS_SUCCESS0) {
7183
7184 (void) string_freeArray(numGroupName, &groupName);
7185 return status;
7186 }
7187
7188 //{UnknownLoad, GridForce, GridMoment, Gravity, Pressure, Rotational, Thermal}
7189 if (feaProblem->feaLoad[i].loadType == GridForce ||
7190 feaProblem->feaLoad[i].loadType == GridMoment ||
7191 feaProblem->feaLoad[i].loadType == Rotational ||
7192 feaProblem->feaLoad[i].loadType == Thermal) {
7193
7194 // Now lets loop through the grid to see how many grid points have the attrIndex
7195 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
7196
7197 if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) {
7198 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
7199 } else {
7200 continue;
7201 }
7202
7203 if (feaData->loadIndex == attrIndex) {
7204
7205 feaProblem->feaLoad[i].numGridID += 1;
7206
7207 // Allocate/Re-allocate grid ID array
7208 if (feaProblem->feaLoad[i].numGridID == 1) {
7209
7210 feaProblem->feaLoad[i].gridIDSet = (int *) EG_alloc(feaProblem->feaLoad[i].numGridID*sizeof(int));
7211
7212 } else {
7213
7214 feaProblem->feaLoad[i].gridIDSet = (int *) EG_reall(feaProblem->feaLoad[i].gridIDSet,
7215 feaProblem->feaLoad[i].numGridID*sizeof(int));
7216 }
7217
7218 if (feaProblem->feaLoad[i].gridIDSet == NULL((void*)0)) {
7219 status = string_freeArray(numGroupName, &groupName);
7220 if (status == CAPS_SUCCESS0) return status;
7221
7222 return EGADS_MALLOC-4;
7223 }
7224
7225 // Set grid ID value -> 1 bias
7226 feaProblem->feaLoad[i].gridIDSet[feaProblem->feaLoad[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID;
7227
7228 //printf("GroupName = %s %d\n", groupName[groupIndex], feaProblem->feaMesh.node[nodeIndex].nodeID);
7229
7230 }
7231 }
7232
7233 } else if (feaProblem->feaLoad[i].loadType == LineForce ||
7234 feaProblem->feaLoad[i].loadType == LineMoment ) {
7235
7236 for (elementIndex = 0; elementIndex < feaProblem->feaMesh.numElement; elementIndex++) {
7237
7238 if (feaProblem->feaMesh.element[elementIndex].elementType != Line) {
7239 continue;
7240 }
7241
7242 if (feaProblem->feaMesh.element[elementIndex].analysisType == MeshStructure) {
7243 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.element[elementIndex].analysisData;
7244 } else {
7245 continue;
7246 }
7247
7248 if (feaData->loadIndex == attrIndex) {
7249
7250 feaProblem->feaLoad[i].numElementID += 1;
7251
7252 feaProblem->feaLoad[i].elementIDSet = (int *) EG_reall(feaProblem->feaLoad[i].elementIDSet,
7253 feaProblem->feaLoad[i].numElementID*sizeof(int));
7254
7255 if (feaProblem->feaLoad[i].elementIDSet == NULL((void*)0)) {
7256 string_freeArray(numGroupName, &groupName);
7257 return EGADS_MALLOC-4;
7258 }
7259
7260 // Set element ID value -> 1 bias
7261 feaProblem->feaLoad[i].elementIDSet[feaProblem->feaLoad[i].numElementID-1] = feaProblem->feaMesh.element[elementIndex].elementID;
7262 }
7263 }
7264
7265 } else if (feaProblem->feaLoad[i].loadType == LineForce ||
7266 feaProblem->feaLoad[i].loadType == LineMoment ||
7267 feaProblem->feaLoad[i].loadType == Pressure ||
7268 feaProblem->feaLoad[i].loadType == PressureDistribute) {
7269
7270 // Now lets loop through the elements to see how many elements have the attrIndex
7271
7272 // Element types - CTRIA3, CTRIA3K, CQUAD4, CQUAD4K
7273 for (elementIndex = 0; elementIndex < feaProblem->feaMesh.numElement; elementIndex++) {
7274
7275 if (feaProblem->feaMesh.element[elementIndex].elementType != Triangle &&
7276 feaProblem->feaMesh.element[elementIndex].elementType != Triangle_6 &&
7277 feaProblem->feaMesh.element[elementIndex].elementType != Quadrilateral &&
7278 feaProblem->feaMesh.element[elementIndex].elementType != Quadrilateral_8) {
7279 continue;
7280 }
7281
7282 if (feaProblem->feaMesh.element[elementIndex].analysisType == MeshStructure) {
7283 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.element[elementIndex].analysisData;
7284 } else {
7285 continue;
7286 }
7287
7288 if (feaData->loadIndex == attrIndex) {
7289
7290 feaProblem->feaLoad[i].numElementID += 1;
7291
7292 // Allocate/Re-allocate element ID array
7293 if (feaProblem->feaLoad[i].numElementID == 1) {
7294
7295 feaProblem->feaLoad[i].elementIDSet = (int *) EG_alloc(feaProblem->feaLoad[i].numElementID*sizeof(int));
7296
7297 } else {
7298
7299 feaProblem->feaLoad[i].elementIDSet = (int *) EG_reall(feaProblem->feaLoad[i].elementIDSet,
7300 feaProblem->feaLoad[i].numElementID*sizeof(int));
7301 }
7302
7303 if (feaProblem->feaLoad[i].elementIDSet == NULL((void*)0)) {
7304 string_freeArray(numGroupName, &groupName);
7305 return EGADS_MALLOC-4;
7306 }
7307
7308 // Set element ID value -> 1 bias
7309 feaProblem->feaLoad[i].elementIDSet[feaProblem->feaLoad[i].numElementID-1] = feaProblem->feaMesh.element[elementIndex].elementID;
7310 }
7311 }
7312
7313 }
7314 } // End attr search loop
7315
7316 status = string_freeArray(numGroupName, &groupName);
7317 if (status != CAPS_SUCCESS0) return status;
7318 groupName = NULL((void*)0);
7319
7320 // Free keyValue (just in case)
7321 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
7322
7323 //Fill up load properties
7324
7325 /*! \page feaLoad
7326 *
7327 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7328 * <ul>
7329 * <li> <B>loadScaleFactor = 1.0 </B> </li> <br>
7330 * Scale factor to use when combining loads.
7331 * </ul>
7332 * \endif
7333 */
7334 keyWord = "loadScaleFactor";
7335 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7336 if (status == CAPS_SUCCESS0) {
7337
7338 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].loadScaleFactor);
7339 if (keyValue != NULL((void*)0)) {
7340 EG_free(keyValue);
7341 keyValue = NULL((void*)0);
7342 }
7343 if (status != CAPS_SUCCESS0) return status;
7344 }
7345
7346 /*! \page feaLoad
7347 *
7348 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS)
7349 * <ul>
7350 * <li> <B>forceScaleFactor = 0.0 </B> </li> <br>
7351 * Overall scale factor for the force for a "GridForce" load.
7352 * </ul>
7353 * \endif
7354 */
7355 keyWord = "forceScaleFactor";
7356 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7357 if (status == CAPS_SUCCESS0) {
7358
7359 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].forceScaleFactor);
7360 if (keyValue != NULL((void*)0)) {
7361 EG_free(keyValue);
7362 keyValue = NULL((void*)0);
7363 }
7364 if (status != CAPS_SUCCESS0) return status;
7365 }
7366
7367 /*! \page feaLoad
7368 *
7369 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS)
7370 * <ul>
7371 * <li> <B>directionVector = [0.0, 0.0, 0.0] </B> </li> <br>
7372 * X-, y-, and z- components of the force vector for a "GridForce", "GridMoment", or "Gravity" load.
7373 * </ul>
7374 * \elseif ABAQUS
7375 * <ul>
7376 * <li> <B>directionVector = [0.0, 0.0, 0.0] </B> </li> <br>
7377 * X-, y-, and z- components of the force vector for a "Gravity" load.
7378 * </ul>
7379 * \endif
7380 *
7381 */
7382 keyWord = "directionVector";
7383 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7384 if (status == CAPS_SUCCESS0) {
7385
7386 status = string_toDoubleArray(keyValue,
7387 (int) sizeof(feaProblem->feaLoad[i].directionVector)/sizeof(double),
7388 feaProblem->feaLoad[i].directionVector);
7389 if (keyValue != NULL((void*)0)) {
7390 EG_free(keyValue);
7391 keyValue = NULL((void*)0);
7392 }
7393 if (status != CAPS_SUCCESS0) return status;
7394 }
7395
7396 /*! \page feaLoad
7397 *
7398 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS)
7399 * <ul>
7400 * <li> <B>momentScaleFactor = 0.0 </B> </li> <br>
7401 * Overall scale factor for the moment for a "GridMoment" load.
7402 * </ul>
7403 * \endif
7404 *
7405 */
7406 keyWord = "momentScaleFactor";
7407 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7408 if (status == CAPS_SUCCESS0) {
7409
7410 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].momentScaleFactor);
7411 if (keyValue != NULL((void*)0)) {
7412 EG_free(keyValue);
7413 keyValue = NULL((void*)0);
7414 }
7415 if (status != CAPS_SUCCESS0) return status;
7416 }
7417
7418 /*! \page feaLoad
7419 *
7420 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7421 * <ul>
7422 * <li> <B>gravityAcceleration = 0.0 </B> </li> <br>
7423 * Acceleration value for a "Gravity" load.
7424 * </ul>
7425 * \endif
7426 */
7427 keyWord = "gravityAcceleration";
7428 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7429 if (status == CAPS_SUCCESS0) {
7430
7431 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].gravityAcceleration);
7432 if (keyValue != NULL((void*)0)) {
7433 EG_free(keyValue);
7434 keyValue = NULL((void*)0);
7435 }
7436 if (status != CAPS_SUCCESS0) return status;
7437 }
7438
7439 /*! \page feaLoad
7440 *
7441 * \if MYSTRAN
7442 * <ul>
7443 * <li> <B>pressureForce = 0.0 </B> </li> <br>
7444 * Uniform pressure force for a "Pressure" load (only applicable to 2D elements).
7445 * </ul>
7446 * \elseif (NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7447 * <ul>
7448 * <li> <B>pressureForce = 0.0 </B> </li> <br>
7449 * Uniform pressure force for a "Pressure" load.
7450 * </ul>
7451 * \endif
7452 */
7453 keyWord = "pressureForce";
7454 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7455 if (status == CAPS_SUCCESS0) {
7456
7457 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].pressureForce);
7458 if (keyValue != NULL((void*)0)) {
7459 EG_free(keyValue);
7460 keyValue = NULL((void*)0);
7461 }
7462 if (status != CAPS_SUCCESS0) return status;
7463 }
7464
7465 /*! \page feaLoad
7466 *
7467 * \if MYSTRAN
7468 * <ul>
7469 * <li> <B>pressureDistributeForce = [0.0, 0.0, 0.0, 0.0] </B> </li> <br>
7470 * Distributed pressure force for a "PressureDistribute" load (only applicable to 2D elements). The four values
7471 * correspond to the 4 (quadrilateral elements) or 3 (triangle elements) node locations.
7472 * </ul>
7473 * \elseif (NASTRAN || HSM || ASTROS || TACS)
7474 * <ul>
7475 * <li> <B>pressureDistributeForce = [0.0, 0.0, 0.0, 0.0] </B> </li> <br>
7476 * Distributed pressure force for a "PressureDistribute" load. The four values
7477 * correspond to the 4 (quadrilateral elements) or 3 (triangle elements) node locations.
7478 * </ul>
7479 * \endif
7480 */
7481 keyWord = "pressureDistributeForce";
7482 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7483 if (status == CAPS_SUCCESS0) {
7484
7485 status = string_toDoubleArray(keyValue,
7486 (int) sizeof(feaProblem->feaLoad[i].pressureDistributeForce)/sizeof(double),
7487 feaProblem->feaLoad[i].pressureDistributeForce);
7488 if (keyValue != NULL((void*)0)) {
7489 EG_free(keyValue);
7490 keyValue = NULL((void*)0);
7491 }
7492 if (status != CAPS_SUCCESS0) return status;
7493 }
7494
7495 /*! \page feaLoad
7496 *
7497 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7498 * <ul>
7499 * <li> <B>angularVelScaleFactor = 0.0 </B> </li> <br>
7500 * An overall scale factor for the angular velocity in revolutions per unit time for a "Rotational" load.
7501 * </ul>
7502 * \elseif HSM
7503 * <ul>
7504 * <li> <B>angularVelScaleFactor = 0.0 </B> </li> <br>
7505 * An overall scale factor for the angular velocity in revolutions per unit time for a "Rotational" load - applied in a global sense.
7506 * </ul>
7507 * \endif
7508 */
7509 keyWord = "angularVelScaleFactor";
7510 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7511 if (status == CAPS_SUCCESS0) {
7512
7513 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].angularVelScaleFactor);
7514 if (keyValue != NULL((void*)0)) {
7515 EG_free(keyValue);
7516 keyValue = NULL((void*)0);
7517 }
7518 if (status != CAPS_SUCCESS0) return status;
7519 }
7520
7521 /*! \page feaLoad
7522 *
7523 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7524 * <ul>
7525 * <li> <B>angularAccScaleFactor = 0.0 </B> </li> <br>
7526 * An overall scale factor for the angular acceleration in revolutions per unit time squared for a "Rotational" load.
7527 * </ul>
7528 * \elseif HSM
7529 * <ul>
7530 * <li> <B>angularAccScaleFactor = 0.0 </B> </li> <br>
7531 * An overall scale factor for the angular acceleration in revolutions per unit time squared for a "Rotational" load - applied in a global sense.
7532 * </ul>
7533 * \endif
7534 */
7535 keyWord = "angularAccScaleFactor";
7536 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7537 if (status == CAPS_SUCCESS0) {
7538
7539 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].angularAccScaleFactor);
7540 if (keyValue != NULL((void*)0)) {
7541 EG_free(keyValue);
7542 keyValue = NULL((void*)0);
7543 }
7544 if (status != CAPS_SUCCESS0) return status;
7545 }
7546
7547 /*! \page feaLoad
7548 *
7549 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7550 * <ul>
7551 * <li> <B>coordinateSystem = "(no default)" </B> </li> <br>
7552 * Name of coordinate system in which defined force components are in reference to. If no value
7553 * is provided the global system is assumed.
7554 * </ul>
7555 * \endif
7556 *
7557 */
7558 keyWord = "coordinateSystem";
7559 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7560 if (status == CAPS_SUCCESS0) {
7561 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 7561, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
7562
7563 tempString = string_removeQuotation(keyValue);
7564 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 7564, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
7565
7566 for (attrIndex = 0; attrIndex < feaProblem->numCoordSystem; attrIndex++) {
7567
7568 if (strcasecmp(tempString, feaProblem->feaCoordSystem[attrIndex].name) == 0) {
7569 feaProblem->feaLoad[i].coordSystemID = feaProblem->feaCoordSystem[attrIndex].coordSystemID;
7570 break;
7571 }
7572 }
7573
7574 if (feaProblem->feaLoad[i].coordSystemID == 0) {
7575 printf("\tCoordinate system %s not found, defaulting to global system!!", keyValue);
7576 }
7577
7578 if (keyValue != NULL((void*)0)) {
7579 EG_free(keyValue);
7580 keyValue = NULL((void*)0);
7581 }
7582
7583 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
7584 }
7585
7586
7587 /*! \page feaLoad
7588 *
7589 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7590 * <ul>
7591 * <li> <B>temperature = 0.0 </B> </li> <br>
7592 * Temperature at a given node for a "Temperature" load.
7593 * </ul>
7594 * \endif
7595 */
7596 keyWord = "temperature";
7597 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7598 if (status == CAPS_SUCCESS0) {
7599
7600 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].temperature);
7601 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
7602 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 7602
, __func__, 0); goto cleanup; }
;
7603 }
7604
7605 /*! \page feaLoad
7606 *
7607 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7608 * <ul>
7609 * <li> <B>temperatureDefault = 0.0 </B> </li> <br>
7610 * Default temperature at a node not explicitly being used for a "Temperature" load.
7611 * </ul>
7612 * \endif
7613 */
7614 keyWord = "temperatureDefault";
7615 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7616 if (status == CAPS_SUCCESS0) {
7617
7618 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].temperatureDefault);
7619 if (keyValue != NULL((void*)0)) {
7620 EG_free(keyValue);
7621 keyValue = NULL((void*)0);
7622 }
7623 if (status != CAPS_SUCCESS0) return status;
7624 }
7625
7626
7627 } else { // if not a JSON string search
7628
7629 /*! \page feaLoad
7630 * \section keyStringLoad Single Value String
7631 *
7632 * If "Value" is a string, the string value may correspond to an entry in a predefined load lookup
7633 * table. NOT YET IMPLEMENTED!!!!
7634 *
7635 */
7636
7637 // Call some look up table maybe?
7638 printf("\tError: Load tuple value is expected to be a JSON string\n");
7639 return CAPS_BADVALUE-311;
7640 }
7641 }
7642
7643 /// Free keyValue and tempString (just in case)
7644 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7645
7646 if (tempString != NULL((void*)0)) EG_free(tempString);
7647
7648 printf("\tDone getting FEA loads\n");
7649 status = CAPS_SUCCESS0;
7650cleanup:
7651 return status;
7652}
7653
7654// Get the analysis properties from a capsTuple
7655int fea_getAnalysis(void *aimInfo,
7656 int numAnalysisTuple,
7657 capsTuple analysisTuple[],
7658 feaProblemStruct *feaProblem) {
7659
7660 /*! \page feaAnalysis FEA Analysis
7661 * Structure for the analysis tuple = (`Analysis Name', `Value').
7662 * 'Analysis Name' defines the reference name for the analysis being specified.
7663 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringAnalysis) or a single string keyword
7664 * (see Section \ref keyStringAnalysis).
7665 */
7666
7667 int status; //Function return
7668
7669 int i, j, groupIndex, attrIndex; // Indexing
7670
7671
7672 char *keyValue = NULL((void*)0);
7673 char *keyWord = NULL((void*)0);
7674
7675 char *tempString = NULL((void*)0);
7676
7677 char **groupName = NULL((void*)0);
7678 int numGroupName = 0;
7679
7680 int tempInt=0; // Temporary integer
7681
7682 // Destroy our analysis structures coming in if aren't 0 and NULL already
7683 if (feaProblem->feaAnalysis != NULL((void*)0)) {
7684 for (i = 0; i < feaProblem->numAnalysis; i++) {
7685 status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
7686 if (status != CAPS_SUCCESS0) return status;
7687 }
7688 }
7689
7690 if (feaProblem->feaAnalysis != NULL((void*)0)) EG_free(feaProblem->feaAnalysis);
7691 feaProblem->feaAnalysis = NULL((void*)0);
7692 feaProblem->numAnalysis = 0;
7693
7694 printf("\nGetting FEA analyses.......\n");
7695
7696 feaProblem->numAnalysis = numAnalysisTuple;
7697
7698 printf("\tNumber of analyses - %d\n", feaProblem->numAnalysis);
7699
7700 if (feaProblem->numAnalysis > 0) {
7701 feaProblem->feaAnalysis = (feaAnalysisStruct *) EG_alloc(feaProblem->numAnalysis * sizeof(feaAnalysisStruct));
7702 } else {
7703 printf("\tNumber of analysis values in input tuple is 0\n");
7704 return CAPS_NOTFOUND-303;
7705 }
7706
7707 for (i = 0; i < feaProblem->numAnalysis; i++) {
7708 status = initiate_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
7709 if (status != CAPS_SUCCESS0) return status;
7710 }
7711
7712 for (i = 0; i < feaProblem->numAnalysis; i++) {
7713
7714 printf("\tAnalysis name - %s\n", analysisTuple[i].name);
7715
7716 feaProblem->feaAnalysis[i].name = (char *) EG_alloc(((strlen(analysisTuple[i].name)) + 1)*sizeof(char));
7717 if (feaProblem->feaAnalysis[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
7718
7719 memcpy(feaProblem->feaAnalysis[i].name, analysisTuple[i].name, strlen(analysisTuple[i].name)*sizeof(char));
7720 feaProblem->feaAnalysis[i].name[strlen(analysisTuple[i].name)] = '\0';
7721
7722 feaProblem->feaAnalysis[i].analysisID = i + 1;
7723
7724 // Do we have a json string?
7725 if (strncmp(analysisTuple[i].value, "{", 1) == 0) {
7726 //printf("JSON String - %s\n", analysisTuple[i].value);
7727
7728 /*! \page feaAnalysis
7729 * \section jsonStringAnalysis JSON String Dictionary
7730 *
7731 * If "Value" is JSON string dictionary
7732 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
7733 * (e.g. "Value" = {"numDesiredEigenvalue": 10, "eigenNormaliztion": "MASS", "numEstEigenvalue": 1,
7734 * "extractionMethod": "GIV", "frequencyRange": [0, 10000]})
7735 * \endif
7736 * the following keywords ( = default values) may be used:
7737 *
7738 * \if MYSTRAN
7739 * <ul>
7740 * <li> <B>analysisType = "Modal"</B> </li> <br>
7741 * Type of load. Options: "Modal", "Static".
7742 * </ul>
7743 * \elseif (NASTRAN || ASTROS)
7744 * <ul>
7745 * <li> <B>analysisType = "Modal"</B> </li> <br>
7746 * Type of load. Options: "Modal", "Static", "AeroelasticTrim", "AeroelasticFlutter"
7747 * Note: "AeroelasticStatic" is still supported but refers to "AeroelasticTrim"
7748 * Note: "Optimization" and "StaticOpt" are not valid - Optimization is initialized by the Analysis_Type AIM Input
7749 * </ul>
7750 * \elseif ABAQUS
7751 * <ul>
7752 * <li> <B>analysisType = "Modal"</B> </li> <br>
7753 * Type of load. Options: "Modal", "Static"
7754 * </ul>
7755 * \endif
7756 *
7757 */
7758 // Get analysis Type
7759 keyWord = "analysisType";
7760 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7761 if (status == CAPS_SUCCESS0) {
7762 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 7762, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
7763
7764 //{UnknownAnalysis, Modal, Static}
7765 if (strcasecmp(keyValue, "\"Modal\"") == 0) feaProblem->feaAnalysis[i].analysisType = Modal;
7766 else if (strcasecmp(keyValue, "\"Static\"") == 0) feaProblem->feaAnalysis[i].analysisType = Static;
7767 else if (strcasecmp(keyValue, "\"StaticOpt\"") == 0) feaProblem->feaAnalysis[i].analysisType = Optimization;
7768 else if (strcasecmp(keyValue, "\"Optimization\"") == 0) feaProblem->feaAnalysis[i].analysisType = Optimization;
7769 else if (strcasecmp(keyValue, "\"AeroelasticTrim\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticTrim;
7770 else if (strcasecmp(keyValue, "\"AeroelasticStatic\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticTrim;
7771 else if (strcasecmp(keyValue, "\"AeroelasticFlutter\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticFlutter;
7772 else {
7773
7774 printf("\tUnrecognized \"%s\" specified (%s) for Analysis tuple %s, defaulting to \"Modal\"\n", keyWord,
7775 keyValue,
7776 analysisTuple[i].name);
7777 feaProblem->feaAnalysis[i].analysisType = Modal;
7778 }
7779
7780 } else {
7781
7782 printf("\tNo \"%s\" specified for Analysis tuple %s, defaulting to \"Modal\"\n", keyWord, analysisTuple[i].name);
7783
7784 feaProblem->feaAnalysis[i].analysisType = Modal;
7785 }
7786 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
7787
7788 // Get loads to be applied for a given analysis
7789
7790 /*! \page feaAnalysis
7791 *
7792 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
7793 * <ul>
7794 * <li> <B>analysisLoad = "(no default)"</B> </li> <br>
7795 * Single or list of "Load Name"s defined in \ref feaLoad in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...].
7796 * </ul>
7797 * \endif
7798 */
7799 keyWord = "analysisLoad";
7800 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7801 if (status == CAPS_SUCCESS0) {
7802
7803 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7804 if (keyValue != NULL((void*)0)) {
7805 EG_free(keyValue);
7806 keyValue = NULL((void*)0);
7807 }
7808
7809 if (status != CAPS_SUCCESS0) return status;
7810
7811 feaProblem->feaAnalysis[i].numLoad = 0;
7812 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7813
7814 for (attrIndex = 0; attrIndex < feaProblem->numLoad; attrIndex++) {
7815
7816 if (strcasecmp(feaProblem->feaLoad[attrIndex].name, groupName[groupIndex]) == 0) {
7817
7818// if (feaProblem->feaLoad[attrIndex].loadType == Thermal) {
7819// printf("Combining Thermal loads in a subcase isn't supported yet!\n");
7820// status = string_freeArray(numGroupName, &groupName);
7821// if (status != CAPS_SUCCESS) return status;
7822// groupName = NULL;
7823// return CAPS_BADVALUE;
7824// }
7825
7826 feaProblem->feaAnalysis[i].numLoad += 1;
7827
7828 if (feaProblem->feaAnalysis[i].numLoad == 1) {
7829
7830 feaProblem->feaAnalysis[i].loadSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numLoad *sizeof(int));
7831
7832 } else {
7833
7834 feaProblem->feaAnalysis[i].loadSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].loadSetID,
7835 feaProblem->feaAnalysis[i].numLoad *sizeof(int));
7836 }
7837
7838 if (feaProblem->feaAnalysis[i].loadSetID == NULL((void*)0)) {
7839 status = string_freeArray(numGroupName, &groupName);
7840 if (status != CAPS_SUCCESS0) return status;
7841 groupName = NULL((void*)0);
7842 return EGADS_MALLOC-4;
7843 }
7844
7845 feaProblem->feaAnalysis[i].loadSetID[feaProblem->feaAnalysis[i].numLoad-1] = feaProblem->feaLoad[attrIndex].loadID;
7846 break;
7847 }
7848 }
7849
7850 if (feaProblem->feaAnalysis[i].numLoad != groupIndex+1) {
7851
7852 printf("\tWarning: Analysis load name, %s, not found in feaLoad structure\n", groupName[groupIndex]);
7853
7854 }
7855 }
7856
7857 status = string_freeArray(numGroupName, &groupName);
7858 if (status != CAPS_SUCCESS0) return status;
7859 groupName = NULL((void*)0);
7860
7861 }
7862
7863 // Get constraints to be applied for a given analysis
7864 /*! \page feaAnalysis
7865 *
7866 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
7867 * <ul>
7868 * <li> <B>analysisConstraint = "(no default)"</B> </li> <br>
7869 * Single or list of "Constraint Name"s defined in \ref feaConstraint in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...].
7870 * </ul>
7871 * \endif
7872 */
7873 keyWord = "analysisConstraint";
7874 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7875 if (status == CAPS_SUCCESS0) {
7876
7877 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7878 if (keyValue != NULL((void*)0)) {
7879 EG_free(keyValue);
7880 keyValue = NULL((void*)0);
7881 }
7882
7883 if (status != CAPS_SUCCESS0) return status;
7884
7885 feaProblem->feaAnalysis[i].numConstraint = 0;
7886 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7887
7888 for (attrIndex = 0; attrIndex < feaProblem->numConstraint; attrIndex++) {
7889
7890 if (strcasecmp(feaProblem->feaConstraint[attrIndex].name, groupName[groupIndex]) == 0) {
7891
7892 feaProblem->feaAnalysis[i].numConstraint += 1;
7893
7894 if (feaProblem->feaAnalysis[i].numConstraint == 1) {
7895
7896 feaProblem->feaAnalysis[i].constraintSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numConstraint *sizeof(int));
7897
7898 } else {
7899
7900 feaProblem->feaAnalysis[i].constraintSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].constraintSetID,
7901 feaProblem->feaAnalysis[i].numConstraint *sizeof(int));
7902 }
7903
7904 if (feaProblem->feaAnalysis[i].constraintSetID == NULL((void*)0)) {
7905 status = string_freeArray(numGroupName, &groupName);
7906 if (status != CAPS_SUCCESS0) return status;
7907 groupName = NULL((void*)0);
7908 return EGADS_MALLOC-4;
7909 }
7910
7911 feaProblem->feaAnalysis[i].constraintSetID[feaProblem->feaAnalysis[i].numConstraint-1] = feaProblem->feaConstraint[attrIndex].constraintID;
7912 break;
7913 }
7914 }
7915
7916 if (feaProblem->feaAnalysis[i].numConstraint != groupIndex+1) {
7917
7918 printf("\tWarning: Analysis constraint name, %s, not found in feaConstraint structure\n", groupName[groupIndex]);
7919
7920 }
7921 }
7922
7923 status = string_freeArray(numGroupName, &groupName);
7924 if (status != CAPS_SUCCESS0) return status;
7925 groupName = NULL((void*)0);
7926
7927 }
7928
7929 // Get supports to be applied for a given analysis
7930 /*! \page feaAnalysis
7931 *
7932 * \if (MYSTRAN || NASTRAN || ASTROS)
7933 * <ul>
7934 * <li> <B>analysisSupport = "(no default)"</B> </li> <br>
7935 * Single or list of "Support Name"s defined in \ref feaSupport in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...].
7936 * </ul>
7937 * \endif
7938 *
7939 */
7940 keyWord = "analysisSupport";
7941 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7942 if (status == CAPS_SUCCESS0) {
7943
7944 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7945 if (keyValue != NULL((void*)0)) {
7946 EG_free(keyValue);
7947 keyValue = NULL((void*)0);
7948 }
7949
7950 if (status != CAPS_SUCCESS0) return status;
7951
7952 feaProblem->feaAnalysis[i].numSupport = 0;
7953 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7954
7955 for (attrIndex = 0; attrIndex < feaProblem->numSupport; attrIndex++) {
7956
7957 if (strcasecmp(feaProblem->feaSupport[attrIndex].name, groupName[groupIndex]) == 0) {
7958
7959 feaProblem->feaAnalysis[i].numSupport += 1;
7960
7961 if (feaProblem->feaAnalysis[i].numSupport == 1) {
7962
7963 feaProblem->feaAnalysis[i].supportSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numSupport *sizeof(int));
7964
7965 } else {
7966
7967 feaProblem->feaAnalysis[i].supportSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].supportSetID,
7968 feaProblem->feaAnalysis[i].numSupport *sizeof(int));
7969 }
7970
7971 if (feaProblem->feaAnalysis[i].supportSetID == NULL((void*)0)) {
7972 status = string_freeArray(numGroupName, &groupName);
7973 if (status != CAPS_SUCCESS0) return status;
7974 groupName = NULL((void*)0);
7975 return EGADS_MALLOC-4;
7976 }
7977
7978 feaProblem->feaAnalysis[i].supportSetID[feaProblem->feaAnalysis[i].numSupport-1] = feaProblem->feaSupport[attrIndex].supportID;
7979 break;
7980 }
7981 }
7982
7983 if (feaProblem->feaAnalysis[i].numSupport != groupIndex+1) {
7984
7985 printf("\tWarning: Analysis support name, %s, not found in feaSupport structure\n", groupName[groupIndex]);
7986
7987 }
7988 }
7989
7990 status = string_freeArray(numGroupName, &groupName);
7991 if (status != CAPS_SUCCESS0) return status;
7992 groupName = NULL((void*)0);
7993
7994 }
7995
7996 // Get design constraints to be applied for a given analysis
7997
7998 /*! \page feaAnalysis
7999 *
8000 * \if (NASTRAN || ASTROS)
8001 * <ul>
8002 * <li> <B>analysisDesignConstraint = "(no default)"</B> </li> <br>
8003 * Single or list of "Design Constraint Name"s defined in \ref feaDesignConstraint in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...].
8004 * </ul>
8005 * \endif
8006 */
8007 keyWord = "analysisDesignConstraint";
8008 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8009 if (status == CAPS_SUCCESS0) {
8010
8011 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
8012 if (keyValue != NULL((void*)0)) {
8013 EG_free(keyValue);
8014 keyValue = NULL((void*)0);
8015 }
8016
8017 if (status != CAPS_SUCCESS0) return status;
8018
8019 feaProblem->feaAnalysis[i].numDesignConstraint = 0;
8020 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
8021
8022 for (attrIndex = 0; attrIndex < feaProblem->numDesignConstraint; attrIndex++) {
8023
8024 if (strcasecmp(feaProblem->feaDesignConstraint[attrIndex].name, groupName[groupIndex]) == 0) {
8025
8026 feaProblem->feaAnalysis[i].numDesignConstraint += 1;
8027
8028 if (feaProblem->feaAnalysis[i].numDesignConstraint == 1) {
8029
8030 feaProblem->feaAnalysis[i].designConstraintSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numDesignConstraint *sizeof(int));
8031
8032 } else {
8033
8034 feaProblem->feaAnalysis[i].designConstraintSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].designConstraintSetID,
8035 feaProblem->feaAnalysis[i].numDesignConstraint *sizeof(int));
8036 }
8037
8038 if (feaProblem->feaAnalysis[i].designConstraintSetID == NULL((void*)0)) {
8039 status = string_freeArray(numGroupName, &groupName);
8040 if (status != CAPS_SUCCESS0) return status;
8041 groupName = NULL((void*)0);
8042 return EGADS_MALLOC-4;
8043 }
8044
8045 feaProblem->feaAnalysis[i].designConstraintSetID[feaProblem->feaAnalysis[i].numDesignConstraint-1] = feaProblem->feaDesignConstraint[attrIndex].designConstraintID;
8046 break;
8047 }
8048 }
8049
8050 if (feaProblem->feaAnalysis[i].numDesignConstraint != groupIndex+1) {
8051
8052 printf("\tWarning: Analysis design constraint name, %s, not found in feaDesignConstraint structure\n", groupName[groupIndex]);
8053
8054 }
8055 }
8056
8057 status = string_freeArray(numGroupName, &groupName);
8058 if (status != CAPS_SUCCESS0) {
8059 if (tempString != NULL((void*)0)) EG_free(tempString);
8060
8061 return status;
8062 }
8063 groupName = NULL((void*)0);
8064
8065 }
8066
8067 //Fill up analysis properties
8068 /*! \page feaAnalysis
8069 *
8070 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
8071 * <ul>
8072 * <li> <B>extractionMethod = "(no default)"</B> </li> <br>
8073 * Extraction method for modal analysis.
8074 * </ul>
8075 * \endif
8076 */
8077 keyWord = "extractionMethod";
8078 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8079 if (status == CAPS_SUCCESS0) {
8080
8081 tempString = string_removeQuotation(keyValue);
8082 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 8082, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
8083 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8084
8085 feaProblem->feaAnalysis[i].extractionMethod = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8086 if(feaProblem->feaAnalysis[i].extractionMethod == NULL((void*)0)) {
8087 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8088 status = EGADS_MALLOC-4;
8089 goto cleanup;
8090 }
8091
8092 memcpy(feaProblem->feaAnalysis[i].extractionMethod, tempString, strlen(tempString)*sizeof(char));
8093 feaProblem->feaAnalysis[i].extractionMethod[strlen(tempString)] = '\0';
8094
8095 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8096 }
8097
8098
8099 /*! \page feaAnalysis
8100 *
8101 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
8102 * <ul>
8103 * <li> <B>frequencyRange = [0.0, 0.0] </B> </li> <br>
8104 * Frequency range of interest for modal analysis.
8105 * </ul>
8106 * \endif
8107 */
8108 keyWord = "frequencyRange";
8109 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8110 if (status == CAPS_SUCCESS0) {
8111
8112 status = string_toDoubleArray(keyValue,
8113 (int) sizeof(feaProblem->feaAnalysis[i].frequencyRange)/sizeof(double),
8114 feaProblem->feaAnalysis[i].frequencyRange);
8115 if (keyValue != NULL((void*)0)) {
8116 EG_free(keyValue);
8117 keyValue = NULL((void*)0);
8118 }
8119 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8119
, __func__, 0); goto cleanup; }
;
8120 }
8121
8122 /*! \page feaAnalysis
8123 *
8124 * \if (MYSTRAN || NASTRAN || ASTROS)
8125 * <ul>
8126 * <li> <B>numEstEigenvalue = 0 </B> </li> <br>
8127 * Number of estimated eigenvalues for modal analysis.
8128 * </ul>
8129 * \endif
8130 */
8131 keyWord = "numEstEigenvalue";
8132 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8133 if (status == CAPS_SUCCESS0) {
8134
8135 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].numEstEigenvalue);
8136 if (keyValue != NULL((void*)0)) {
8137 EG_free(keyValue);
8138 keyValue = NULL((void*)0);
8139 }
8140 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8140
, __func__, 0); goto cleanup; }
;
8141 }
8142
8143 /*! \page feaAnalysis
8144 *
8145 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
8146 * <ul>
8147 * <li> <B>numDesiredEigenvalue = 0</B> </li> <br>
8148 * Number of desired eigenvalues for modal analysis.
8149 * </ul>
8150 * \endif
8151 *
8152 */
8153 keyWord = "numDesiredEigenvalue";
8154 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8155 if (status == CAPS_SUCCESS0) {
8156
8157 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].numDesiredEigenvalue);
8158 if (keyValue != NULL((void*)0)) {
8159 EG_free(keyValue);
8160 keyValue = NULL((void*)0);
8161 }
8162 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8162
, __func__, 0); goto cleanup; }
;
8163 }
8164
8165 /*! \page feaAnalysis
8166 *
8167 * \if (MYSTRAN || NASTRAN || ASTROS)
8168 * <ul>
8169 * <li> <B>eigenNormaliztion = "(no default)"</B> </li> <br>
8170 * Method of eigenvector renormalization. Options: "POINT", "MAX", "MASS"
8171 * </ul>
8172 * \elseif ABAQUS
8173 * <ul>
8174 * <li> <B>eigenNormaliztion = "(no default)"</B> </li> <br>
8175 * Method of eigenvector renormalization. Options: "DISPLACEMENT", "MASS"
8176 * </ul>
8177 * \endif
8178 */
8179 keyWord = "eigenNormaliztion";
8180 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8181 if (status == CAPS_SUCCESS0) {
8182
8183 tempString = string_removeQuotation(keyValue);
8184 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 8184, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
8185
8186 feaProblem->feaAnalysis[i].eigenNormaliztion = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8187 if(feaProblem->feaAnalysis[i].eigenNormaliztion == NULL((void*)0)) {
8188 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8189
8190 return EGADS_MALLOC-4;
8191 }
8192
8193 memcpy(feaProblem->feaAnalysis[i].eigenNormaliztion, tempString, strlen(tempString)*sizeof(char));
8194 feaProblem->feaAnalysis[i].eigenNormaliztion[strlen(tempString)] = '\0';
8195
8196 if (keyValue != NULL((void*)0)) {
8197 EG_free(keyValue);
8198 keyValue = NULL((void*)0);
8199 }
8200 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8201 }
8202
8203 /*! \page feaAnalysis
8204 *
8205 * \if (MYSTRAN || NASTRAN || ASTROS)
8206 * <ul>
8207 * <li> <B>gridNormaliztion = 0 </B> </li> <br>
8208 * Grid point to be used in normalizing eigenvector to 1.0 when using eigenNormaliztion = "POINT"
8209 * </ul>
8210 * \endif
8211 */
8212 keyWord = "gridNormaliztion";
8213 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8214 if (status == CAPS_SUCCESS0) {
8215
8216 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].gridNormaliztion);
8217 if (keyValue != NULL((void*)0)) {
8218 EG_free(keyValue);
8219 keyValue = NULL((void*)0);
8220 }
8221 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8221
, __func__, 0); goto cleanup; }
;
8222 }
8223
8224 /*! \page feaAnalysis
8225 *
8226 * \if (MYSTRAN || NASTRAN || ASTROS)
8227 * <ul>
8228 * <li> <B>componentNormaliztion = 0</B> </li> <br>
8229 * Degree of freedom about "gridNormalization" to be used in normalizing eigenvector to 1.0
8230 * when using eigenNormaliztion = "POINT"
8231 * </ul>
8232 * \endif
8233 *
8234 */
8235 keyWord = "componentNormaliztion";
8236 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8237 if (status == CAPS_SUCCESS0) {
8238
8239 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].componentNormaliztion);
8240 if (keyValue != NULL((void*)0)) {
8241 EG_free(keyValue);
8242 keyValue = NULL((void*)0);
8243 }
8244 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8244
, __func__, 0); goto cleanup; }
;
8245 }
8246
8247 /*! \page feaAnalysis
8248 *
8249 * \if (MYSTRAN || NASTRAN)
8250 * <ul>
8251 * <li> <B>lanczosMode = 2</B> </li> <br>
8252 * Mode refers to the Lanczos mode type to be used in the solution. In mode 3 the mass matrix, Maa,must
8253 * be nonsingular whereas in mode 2 the matrix K aa - sigma*Maa must be nonsingular
8254 * </ul>
8255 * \endif
8256 */
8257 keyWord = "lanczosMode";
8258 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8259 if (status == CAPS_SUCCESS0) {
8260
8261 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].lanczosMode);
8262 if (keyValue != NULL((void*)0)) {
8263 EG_free(keyValue);
8264 keyValue = NULL((void*)0);
8265 }
8266 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8266
, __func__, 0); goto cleanup; }
;
8267 }
8268
8269 /*! \page feaAnalysis
8270 *
8271 * \if (MYSTRAN || NASTRAN)
8272 * <ul>
8273 * <li> <B>lanczosType = "(no default)"</B> </li> <br>
8274 * Lanczos matrix type. Options: DPB, DGB.
8275 * </ul>
8276 * \endif
8277 */
8278 keyWord = "lanczosType";
8279 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8280 if (status == CAPS_SUCCESS0) {
8281
8282 tempString = string_removeQuotation(keyValue);
8283 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 8283, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
8284
8285 feaProblem->feaAnalysis[i].lanczosType = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8286 if(feaProblem->feaAnalysis[i].lanczosType == NULL((void*)0)) {
8287 if (tempString != NULL((void*)0)) EG_free(tempString);
8288
8289 return EGADS_MALLOC-4;
8290 }
8291
8292 memcpy(feaProblem->feaAnalysis[i].lanczosType, tempString, strlen(tempString)*sizeof(char));
8293 feaProblem->feaAnalysis[i].lanczosType[strlen(tempString)] = '\0';
8294
8295 if (keyValue != NULL((void*)0)) {
8296 EG_free(keyValue);
8297 keyValue = NULL((void*)0);
8298 }
8299
8300 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8301 }
8302
8303 /*! \page feaAnalysis
8304 *
8305 * \if (NASTRAN)
8306 * <ul>
8307 * <li> <B>machNumber = 0.0 or [0.0, ..., 0.0]</B> </li> <br>
8308 * Mach number used in trim analysis OR Mach numbers used in flutter analysis..
8309 * </ul>
8310 * \elseif (ASTROS)
8311 * <ul>
8312 * <li> <B>machNumber = 0.0 or [0.0, ..., 0.0]</B> </li> <br>
8313 * Mach number used in trim analysis OR Mach up to 6 values used in flutter analysis..
8314 * </ul>
8315 * \endif
8316 */
8317 keyWord = "machNumber";
8318 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8319 if (status == CAPS_SUCCESS0) {
8320
8321 status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numMachNumber, &feaProblem->feaAnalysis[i].machNumber);
8322 if (keyValue != NULL((void*)0)) {
8323 EG_free(keyValue);
8324 keyValue = NULL((void*)0);
8325 }
8326 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8326
, __func__, 0); goto cleanup; }
;
8327 }
8328
8329 /*! \page feaAnalysis
8330 *
8331 * \if (NASTRAN || ASTROS)
8332 * <ul>
8333 * <li> <B>dynamicPressure = 0.0</B> </li> <br>
8334 * Dynamic pressure used in trim analysis.
8335 * </ul>
8336 * \endif
8337 */
8338 keyWord = "dynamicPressure";
8339 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8340 if (status == CAPS_SUCCESS0) {
8341
8342 status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].dynamicPressure);
8343 if (keyValue != NULL((void*)0)) {
8344 EG_free(keyValue);
8345 keyValue = NULL((void*)0);
8346 }
8347 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8347
, __func__, 0); goto cleanup; }
;
8348 }
8349
8350 /*! \page feaAnalysis
8351 *
8352 * \if (NASTRAN || ASTROS)
8353 * <ul>
8354 * <li> <B>density = 0.0</B> </li> <br>
8355 * Density used in trim analysis to determine true velocity, or flutter analysis.
8356 * </ul>
8357 * \endif
8358 */
8359 keyWord = "density";
8360 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8361 if (status == CAPS_SUCCESS0) {
8362
8363 status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].density);
8364 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8365 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8365
, __func__, 0); goto cleanup; }
;
8366 }
8367
8368 /*! \page feaAnalysis
8369 *
8370 * \if (MYSTRAN || NASTRAN || ASTROS)
8371 * <ul>
8372 * <li> <B>aeroSymmetryXY = "(no default)"</B> </li> <br>
8373 * Aerodynamic symmetry about the XY Plane. Options: SYM, ANTISYM, ASYM.
8374 * Aerodynamic symmetry about the XY Plane. Options: SYM, ANTISYM, ASYM. SYMMETRIC Indicates that a half span aerodynamic model
8375 * is moving in a symmetric manner with respect to the XY plane.
8376 * ANTISYMMETRIC Indicates that a half span aerodynamic model is moving in an antisymmetric manner with respect to the XY plane.
8377 * ASYMMETRIC Indicates that a full aerodynamic model is provided.
8378 * </ul>
8379 * \endif
8380 */
8381 keyWord = "aeroSymmetryXY";
8382 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8383 if (status == CAPS_SUCCESS0) {
8384
8385 tempString = string_removeQuotation(keyValue);
8386 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 8386, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
8387
8388 feaProblem->feaAnalysis[i].aeroSymmetryXY = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8389 if(feaProblem->feaAnalysis[i].aeroSymmetryXY == NULL((void*)0)) {
8390 if (tempString != NULL((void*)0)) EG_free(tempString);
8391
8392 return EGADS_MALLOC-4;
8393 }
8394
8395 memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXY, tempString, strlen(tempString)*sizeof(char));
8396 feaProblem->feaAnalysis[i].aeroSymmetryXY[strlen(tempString)] = '\0';
8397
8398 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8399 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8400 }
8401
8402 // check for the old option trimSymmetry
8403 keyWord = "trimSymmetry";
8404 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8405 if (status == CAPS_SUCCESS0) {
8406
8407 tempString = string_removeQuotation(keyValue);
8408 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 8408, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
8409
8410 feaProblem->feaAnalysis[i].aeroSymmetryXY = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8411 if(feaProblem->feaAnalysis[i].aeroSymmetryXY == NULL((void*)0)) {
8412 if (tempString != NULL((void*)0)) EG_free(tempString);
8413
8414 return EGADS_MALLOC-4;
8415 }
8416
8417 memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXY, tempString, strlen(tempString)*sizeof(char));
8418 feaProblem->feaAnalysis[i].aeroSymmetryXY[strlen(tempString)] = '\0';
8419
8420 if (keyValue != NULL((void*)0)) {
8421 EG_free(keyValue);
8422 keyValue = NULL((void*)0);
8423 }
8424
8425 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8426 }
8427
8428 /*! \page feaAnalysis
8429 *
8430 * \if (MYSTRAN || NASTRAN || ASTROS)
8431 * <ul>
8432 * <li> <B>aeroSymmetryXZ = "(no default)"</B> </li> <br>
8433 * Aerodynamic symmetry about the XZ Plane. Options: SYM, ANTISYM, ASYM. SYMMETRIC Indicates that a half span aerodynamic model
8434 * is moving in a symmetric manner with respect to the XZ plane.
8435 * ANTISYMMETRIC Indicates that a half span aerodynamic model is moving in an antisymmetric manner with respect to the XZ plane.
8436 * ASYMMETRIC Indicates that a full aerodynamic model is provided.
8437 * </ul>
8438 * \endif
8439 */
8440 keyWord = "aeroSymmetryXZ";
8441 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8442 if (status == CAPS_SUCCESS0) {
8443
8444 tempString = string_removeQuotation(keyValue);
8445 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 8445, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
8446
8447 feaProblem->feaAnalysis[i].aeroSymmetryXZ = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8448 if(feaProblem->feaAnalysis[i].aeroSymmetryXZ == NULL((void*)0)) {
8449 if (tempString != NULL((void*)0)) EG_free(tempString);
8450
8451 return EGADS_MALLOC-4;
8452 }
8453
8454 memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXZ, tempString, strlen(tempString)*sizeof(char));
8455 feaProblem->feaAnalysis[i].aeroSymmetryXZ[strlen(tempString)] = '\0';
8456
8457 if (keyValue != NULL((void*)0)) {
8458 EG_free(keyValue);
8459 keyValue = NULL((void*)0);
8460 }
8461
8462 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8463 }
8464
8465 /*! \page feaAnalysis
8466 *
8467 * \if (NASTRAN )
8468 * <ul>
8469 * <li> <B>rigidVariable = ["no default"]</B> </li> <br>
8470 * List of rigid body motions to be used as trim variables during a trim analysis. Nastran
8471 * valid labels are: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8472 * </ul>
8473 * \elseif ASTROS
8474 * <ul>
8475 * <li> <B>rigidVariable = ["no default"]</B> </li> <br>
8476 * List of rigid body motions to be used as trim variables during a trim analysis. Nastran format
8477 * labels are used and will be converted by the AIM automatically.
8478 * Expected inputs: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8479 * </ul>
8480 * \endif
8481 */
8482 keyWord = "rigidVariable";
8483 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8484 if (status == CAPS_SUCCESS0) {
8485
8486 status = string_toStringDynamicArray(keyValue,
8487 &feaProblem->feaAnalysis[i].numRigidVariable,
8488 &feaProblem->feaAnalysis[i].rigidVariable);
8489 if (keyValue != NULL((void*)0)) {
8490 EG_free(keyValue);
8491 keyValue = NULL((void*)0);
8492 }
8493 if (status != CAPS_SUCCESS0) return status;
8494 }
8495
8496 /*! \page feaAnalysis
8497 *
8498 * \if (NASTRAN)
8499 * <ul>
8500 * <li> <B>rigidConstraint = ["no default"]</B> </li> <br>
8501 * List of rigid body motions to be used as trim constraint variables during a trim analysis. Nastran
8502 * valid labels are: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8503 * </ul>
8504 * \elseif ASTROS
8505 * <ul>
8506 * <li> <B>rigidConstraint = ["no default"]</B> </li> <br>
8507 * List of rigid body motions to be used as trim constraint variables during a trim analysis. Nastran format
8508 * labels are used and will be converted by the AIM automatically.
8509 * Expected inputs: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8510 * </ul>
8511 * \endif
8512 */
8513 keyWord = "rigidConstraint";
8514 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8515 if (status == CAPS_SUCCESS0) {
8516
8517 status = string_toStringDynamicArray(keyValue,
8518 &feaProblem->feaAnalysis[i].numRigidConstraint,
8519 &feaProblem->feaAnalysis[i].rigidConstraint);
8520 if (keyValue != NULL((void*)0)) {
8521 EG_free(keyValue);
8522 keyValue = NULL((void*)0);
8523 }
8524 if (status != CAPS_SUCCESS0) return status;
8525 }
8526
8527 if (feaProblem->feaAnalysis[i].numRigidConstraint != 0) {
8528 /*! \page feaAnalysis
8529 *
8530 * \if (NASTRAN || ASTROS)
8531 * <ul>
8532 * <li> <B>magRigidConstraint = [0.0 , 0.0, ...]</B> </li> <br>
8533 * List of magnitudes of trim constraint variables. If none and 'rigidConstraint'(s) are specified
8534 * then 0.0 is assumed for each rigid constraint.
8535 * </ul>
8536 * \endif
8537 */
8538 keyWord = "magRigidConstraint";
8539 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8540 if (status == CAPS_SUCCESS0) {
8541
8542 status = string_toDoubleDynamicArray(keyValue,
8543 &tempInt,
8544 &feaProblem->feaAnalysis[i].magRigidConstraint);
8545 if (keyValue != NULL((void*)0)) {
8546 EG_free(keyValue);
8547 keyValue = NULL((void*)0);
8548 }
8549 if (status != CAPS_SUCCESS0) return status;
8550 } else {
8551
8552 tempInt = feaProblem->feaAnalysis[i].numRigidConstraint;
8553
8554 feaProblem->feaAnalysis[i].magRigidConstraint = (double *) EG_alloc(tempInt*sizeof(double));
8555 if (feaProblem->feaAnalysis[i].magRigidConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8556
8557 for (j = 0; j < feaProblem->feaAnalysis[i].numRigidConstraint; j++) {
8558
8559 feaProblem->feaAnalysis[i].magRigidConstraint[j] = 0.0;
8560 }
8561 }
8562
8563 if (tempInt != feaProblem->feaAnalysis[i].numRigidConstraint) {
8564 printf("\tDimensional mismatch between 'magRigidConstraint' and 'rigidConstraint'.\n");
8565 printf("\t 'magRigidConstraint' will be resized.\n");
8566
8567 feaProblem->feaAnalysis[i].magRigidConstraint = (double *) EG_reall(feaProblem->feaAnalysis[i].magRigidConstraint,
8568 feaProblem->feaAnalysis[i].numRigidConstraint*sizeof(double));
8569
8570 if (feaProblem->feaAnalysis[i].magRigidConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8571
8572 for (j = tempInt; j < feaProblem->feaAnalysis[i].numRigidConstraint; j++) {
8573 feaProblem->feaAnalysis[i].magRigidConstraint[j] = 0.0;
8574 }
8575 }
8576 }
8577
8578 /*! \page feaAnalysis
8579 *
8580 * \if (NASTRAN || ASTROS)
8581 * <ul>
8582 * <li> <B>controlConstraint = ["no default"]</B> </li> <br>
8583 * List of controls surfaces to be used as trim constraint variables during a trim analysis.
8584 * </ul>
8585 * \endif
8586 */
8587 keyWord = "controlConstraint";
8588 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8589 if (status == CAPS_SUCCESS0) {
8590
8591 status = string_toStringDynamicArray(keyValue,
8592 &feaProblem->feaAnalysis[i].numControlConstraint,
8593 &feaProblem->feaAnalysis[i].controlConstraint);
8594 if (keyValue != NULL((void*)0)) {
8595 EG_free(keyValue);
8596 keyValue = NULL((void*)0);
8597 }
8598 if (status != CAPS_SUCCESS0) return status;
8599 }
8600
8601 if (feaProblem->feaAnalysis[i].numControlConstraint != 0) {
8602 /*! \page feaAnalysis
8603 *
8604 * \if (NASTRAN || ASTROS)
8605 * <ul>
8606 * <li> <B>magControlConstraint = [0.0 , 0.0, ...]</B> </li> <br>
8607 * List of magnitudes of trim control surface constraint variables. If none and 'controlConstraint'(s) are specified
8608 * then 0.0 is assumed for each control surface constraint.
8609 * </ul>
8610 * \endif
8611 */
8612 keyWord = "magControlConstraint";
8613 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8614 if (status == CAPS_SUCCESS0) {
8615
8616 status = string_toDoubleDynamicArray(keyValue,
8617 &tempInt,
8618 &feaProblem->feaAnalysis[i].magControlConstraint);
8619 if (keyValue != NULL((void*)0)) {
8620 EG_free(keyValue);
8621 keyValue = NULL((void*)0);
8622 }
8623 if (status != CAPS_SUCCESS0) return status;
8624 } else {
8625
8626 tempInt = feaProblem->feaAnalysis[i].numControlConstraint;
8627
8628 feaProblem->feaAnalysis[i].magControlConstraint = (double *) EG_alloc(tempInt*sizeof(double));
8629 if (feaProblem->feaAnalysis[i].magControlConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8630
8631 for (j = 0; j < feaProblem->feaAnalysis[i].numControlConstraint; j++) {
8632
8633 feaProblem->feaAnalysis[i].magControlConstraint[j] = 0.0;
8634 }
8635 }
8636
8637 if (tempInt != feaProblem->feaAnalysis[i].numControlConstraint) {
8638 printf("\tDimensional mismatch between 'magControlConstraint' and 'controlConstraint'.\n");
8639 printf("\t 'magControlConstraint' will be resized.\n");
8640
8641 feaProblem->feaAnalysis[i].magControlConstraint = (double *) EG_reall(feaProblem->feaAnalysis[i].magControlConstraint,
8642 feaProblem->feaAnalysis[i].numControlConstraint*sizeof(double));
8643
8644 if (feaProblem->feaAnalysis[i].magControlConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8645
8646 for (j = tempInt; j < feaProblem->feaAnalysis[i].numControlConstraint; j++) {
8647 feaProblem->feaAnalysis[i].magControlConstraint[j] = 0.0;
8648 }
8649 }
8650 }
8651
8652 /*! \page feaAnalysis
8653 *
8654 * \if (NASTRAN || ASTROS)
8655 * <ul>
8656 * <li> <B>reducedFreq = [0.1, ..., 20.0], No Default Values are defined.</B> </li> <br>
8657 * Reduced Frequencies to be used in Flutter Analysis. Up to 8 values can be defined.
8658 * </ul>
8659 * \endif
8660 */
8661 keyWord = "reducedFreq";
8662 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8663 if (status == CAPS_SUCCESS0) {
8664
8665 status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numReducedFreq, &feaProblem->feaAnalysis[i].reducedFreq);
8666 if (keyValue != NULL((void*)0)) {
8667 EG_free(keyValue);
8668 keyValue = NULL((void*)0);
8669 }
8670 if (feaProblem->feaAnalysis[i].numReducedFreq > 8) {
8671 printf("\tError: The number of reduced frequencies (reducedFreq) entered in an Analysis AIM Input must be eight or less\n");
8672 return CAPS_BADVALUE-311;
8673 }
8674 if (status != CAPS_SUCCESS0) return status;
8675 }
8676
8677 /*! \page feaAnalysis
8678 *
8679 * \if (NASTRAN || ASTROS)
8680 * <ul>
8681 * <li> <B>flutterVel = [0.1, ..., 20.0]</B> </li> <br>
8682 * Velocities to be used in Flutter Analysis. If no values are provided the
8683 * following relation is used
8684 *
8685 * v = sqrt(2*dynamicPressure/density)
8686 * dv = (v*2 - v/2) / 20;
8687 *
8688 * flutterVel[0] = v/10
8689 * flutterVel[i] = v/2 + i*dv; where i = 1....21
8690 * flutterVel[22] = v*10;
8691 * </ul>
8692 * \endif
8693 */
8694 keyWord = "flutterVel";
8695 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8696 if (status == CAPS_SUCCESS0) {
8697
8698 status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numFlutterVel, &feaProblem->feaAnalysis[i].flutterVel);
8699 if (keyValue != NULL((void*)0)) {
8700 EG_free(keyValue);
8701 keyValue = NULL((void*)0);
8702 }
8703 if (status != CAPS_SUCCESS0) return status;
8704 }
8705
8706 /*! \page feaAnalysis
8707 *
8708 * \if (ASTROS)
8709 * <ul>
8710 * <li> <B>flutterConvergenceParam = 1e-5 </B> </li> <br>
8711 * Convergence parameter for flutter eigenvalue.
8712 * </ul>
8713 * \endif
8714 */
8715 keyWord = "flutterConvergenceParam";
8716 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8717 if (status == CAPS_SUCCESS0) {
8718
8719 status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].flutterConvergenceParam);
8720 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8721 if (status != CAPS_SUCCESS0) return status;
8722 }
8723 else {
8724 feaProblem->feaAnalysis[i].flutterConvergenceParam = 1.e-5;
8725 }
8726
8727 /*! \page feaAnalysis
8728 *
8729 * \if (NASTRAN || ASTROS)
8730 * <ul>
8731 * <li> <B>visualFlutter = False </B> </li> <br>
8732 * Turn on flutter visualization f06 output.
8733 * </ul>
8734 * \endif
8735 */
8736 // keyWord = "visualFlutter";
8737 // status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8738 // if (status == CAPS_SUCCESS) {
8739 //
8740 // status = string_toBoolean(keyValue, &feaProblem->feaAnalysis[i].visualFlutter);
8741 // if (keyValue != NULL) {
8742 // EG_free(keyValue);
8743 // keyValue = NULL;
8744 // }
8745 // if (status != CAPS_SUCCESS) return status;
8746 // }
8747
8748 /*! \page feaAnalysis
8749 *
8750 * \if (NASTRAN)
8751 * <ul>
8752 * <li> <B>analysisResponse = "(no default)"</B> </li> <br>
8753 * Single or list of "DesignResponse Name"s defined in \ref feaDesignResponse to use for the analysis response spanning sets (e.g. "Name1" or ["Name1","Name2",...].
8754 * </ul>
8755 * \endif
8756 */
8757 keyWord = "analysisResponse";
8758 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8759 if (status == CAPS_SUCCESS0) {
8760
8761 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
8762 if (keyValue != NULL((void*)0)) {
8763 EG_free(keyValue);
8764 keyValue = NULL((void*)0);
8765 }
8766
8767 if (status != CAPS_SUCCESS0) return status;
8768
8769 feaProblem->feaAnalysis[i].numDesignResponse = 0;
8770 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
8771
8772 for (attrIndex = 0; attrIndex < feaProblem->numDesignResponse; attrIndex++) {
8773
8774 if (strcasecmp(feaProblem->feaDesignResponse[attrIndex].name, groupName[groupIndex]) == 0) {
8775
8776 feaProblem->feaAnalysis[i].numDesignResponse += 1;
8777
8778 if (feaProblem->feaAnalysis[i].numDesignResponse == 1) {
8779
8780 feaProblem->feaAnalysis[i].designResponseSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numDesignResponse *sizeof(int));
8781
8782 } else {
8783
8784 feaProblem->feaAnalysis[i].designResponseSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].designResponseSetID,
8785 feaProblem->feaAnalysis[i].numDesignResponse *sizeof(int));
8786 }
8787
8788 if (feaProblem->feaAnalysis[i].designResponseSetID == NULL((void*)0)) {
8789 status = string_freeArray(numGroupName, &groupName);
8790 if (status != CAPS_SUCCESS0) return status;
8791 groupName = NULL((void*)0);
8792 return EGADS_MALLOC-4;
8793 }
8794
8795 feaProblem->feaAnalysis[i].designResponseSetID[feaProblem->feaAnalysis[i].numDesignResponse-1] = feaProblem->feaDesignResponse[attrIndex].responseID;
8796 break;
8797 }
8798 }
8799
8800 if (feaProblem->feaAnalysis[i].numDesignResponse != groupIndex+1) {
8801
8802 printf("\tWarning: Analysis design response name, %s, not found in feaDesignResponse structure\n", groupName[groupIndex]);
8803
8804 }
8805 }
8806
8807 status = string_freeArray(numGroupName, &groupName);
8808 if (status != CAPS_SUCCESS0) {
8809 if (tempString != NULL((void*)0)) EG_free(tempString);
8810
8811 return status;
8812 }
8813 groupName = NULL((void*)0);
8814 }
8815
8816 if (feaProblem->feaAnalysis[i].analysisType == AeroelasticFlutter) {
8817 // Setup the default flutter velocities if not specified
8818 status = fea_defaultFlutterVelocity(&feaProblem->feaAnalysis[i]);
8819 if (status != CAPS_SUCCESS0) return status;
8820 }
8821
8822 } else { // Not JSONstring
8823
8824 /*! \page feaAnalysis
8825 * \section keyStringAnalysis Single Value String
8826 *
8827 * If "Value" is a string, the string value may correspond to an entry in a predefined analysis lookup
8828 * table. NOT YET IMPLEMENTED!!!!
8829 *
8830 *
8831 */
8832
8833 // CALL analysis look up
8834 printf("\tError: Analysis tuple value is expected to be a JSON string\n");
8835 //printf("\t%s", analysisTuple[i].value);
8836 return CAPS_BADVALUE-311;
8837 }
8838 }
8839
8840
8841 printf("\tDone getting FEA analyses\n");
8842 status = CAPS_SUCCESS0;
8843cleanup:
8844 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8845 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8846 return status;
8847}
8848
8849// Get the design variables from a capsTuple
8850int fea_getDesignVariable(void *aimInfo,
8851 /*@unused@*/ int requireGroup,
8852 int numDesignVariableTuple,
8853 capsTuple designVariableTuple[],
8854 int numDesignVariableRelationTuple,
8855 capsTuple designVariableRelationTuple[],
8856 mapAttrToIndexStruct *attrMap,
8857 feaProblemStruct *feaProblem) {
8858
8859 /*! \page feaDesignVariable FEA Design Variables
8860 * Structure for the design variable tuple = ("DesignVariable Name", "Value").
8861 * "DesignVariable Name" defines the reference name for the design variable being specified.
8862 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
8863 * (see Section \ref jsonStringDesignVariable).
8864 * \if NASTRAN
8865 * In Nastran the DesignVariable Name will be the LABEL used in the DESVAR input.
8866 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
8867 *
8868 * - <c>DESVAR ID LABEL XINIT XLB XUB DELXV DDVAL</c>
8869 * \endif
8870 *
8871 */
8872 int status; //Function return
8873
8874 int i, j, k; // Indexing
8875 int found;
8876
8877 char *keyValue = NULL((void*)0);
8878 char *keyWord = NULL((void*)0);
8879
8880 int tempInteger = 0;
8881 int designVariableID = 0;
8882
8883 char **groupName = NULL((void*)0);
8884 int numGroupName = 0;
8885
8886 feaDesignVariableStruct *designVariable;
8887 feaDesignVariableRelationStruct *designVariableRelation;
8888
8889 // Destroy our design variable structures coming in if aren't 0 and NULL already
8890 if (feaProblem->feaDesignVariable != NULL((void*)0)) {
8891 for (i = 0; i < feaProblem->numDesignVariable; i++) {
8892 status = destroy_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]);
8893 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8893
, __func__, 0); goto cleanup; }
;
8894 }
8895 }
8896 AIM_FREE(feaProblem->feaDesignVariable){ EG_free(feaProblem->feaDesignVariable); feaProblem->feaDesignVariable
= ((void*)0); }
;
8897 feaProblem->feaDesignVariable = NULL((void*)0);
8898 feaProblem->numDesignVariable = 0;
8899
8900 // Destroy our design variable relation structures coming in if aren't 0 and NULL already
8901 if (feaProblem->feaDesignVariableRelation != NULL((void*)0)) {
8902 for (i = 0; i < feaProblem->numDesignVariableRelation; i++) {
8903 status = destroy_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]);
8904 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8904
, __func__, 0); goto cleanup; }
;
8905 }
8906 }
8907 AIM_FREE(feaProblem->feaDesignVariableRelation){ EG_free(feaProblem->feaDesignVariableRelation); feaProblem
->feaDesignVariableRelation = ((void*)0); }
;
8908 feaProblem->feaDesignVariableRelation = NULL((void*)0);
8909 feaProblem->numDesignVariableRelation = 0;
8910
8911
8912 printf("\nGetting FEA design variables.......\n");
8913
8914 feaProblem->numDesignVariable = numDesignVariableTuple;
8915
8916 printf("\tNumber of design variables - %d\n", feaProblem->numDesignVariable);
8917
8918 if (feaProblem->numDesignVariable > 0) {
8919 AIM_ALLOC(feaProblem->feaDesignVariable,{ if (feaProblem->feaDesignVariable != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__
, 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaDesignVariable"
); goto cleanup; } size_t memorysize = feaProblem->numDesignVariable
; feaProblem->feaDesignVariable = (feaDesignVariableStruct
*) EG_alloc(memorysize*sizeof(feaDesignVariableStruct)); if (
feaProblem->feaDesignVariable == ((void*)0)) { status = -4
; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__, 3
, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariable"
, memorysize, "feaDesignVariableStruct"); goto cleanup; } }
8920 feaProblem->numDesignVariable, feaDesignVariableStruct, aimInfo, status){ if (feaProblem->feaDesignVariable != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__
, 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaDesignVariable"
); goto cleanup; } size_t memorysize = feaProblem->numDesignVariable
; feaProblem->feaDesignVariable = (feaDesignVariableStruct
*) EG_alloc(memorysize*sizeof(feaDesignVariableStruct)); if (
feaProblem->feaDesignVariable == ((void*)0)) { status = -4
; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__, 3
, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariable"
, memorysize, "feaDesignVariableStruct"); goto cleanup; } }
;
8921
8922 } else {
8923 AIM_ERROR(aimInfo, "Number of design variable values in input tuple is 0\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 8923, __func__
, "Number of design variable values in input tuple is 0\n"); }
;
8924 return CAPS_NOTFOUND-303;
8925 }
8926
8927 for (i = 0; i < feaProblem->numDesignVariable; i++) {
8928 status = initiate_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]);
8929 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8929
, __func__, 0); goto cleanup; }
;
8930 }
8931
8932 for (i = 0; i < feaProblem->numDesignVariable; i++) {
8933
8934 designVariable = &feaProblem->feaDesignVariable[i];
8935
8936 printf("\tDesign_Variable name - %s\n", designVariableTuple[i].name);
8937
8938 AIM_STRDUP(designVariable->name, designVariableTuple[i].name, aimInfo, status){ if (designVariable->name != ((void*)0)) { status = -4; aim_status
(aimInfo, status, "feaUtils.c", 8938, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "designVariable->name"); goto cleanup; } designVariable->
name = EG_strdup(designVariableTuple[i].name); if (designVariable
->name == ((void*)0)) { status = -4; aim_status(aimInfo, status
, "feaUtils.c", 8938, __func__, 2, "AIM_STRDUP: %s %s", "designVariable->name"
, designVariableTuple[i].name); goto cleanup; } }
;
8939
8940 // Do we have a json string?
8941 if (json_isDict(designVariableTuple[i].value)) {
8942
8943 /*! \page feaDesignVariable
8944 * \section jsonStringDesignVariable JSON String Dictionary
8945 *
8946 * If "Value" is JSON string dictionary
8947 * \if (NASTRAN || ASTROS || MASSTRAN)
8948 * (eg. "Value" = {"initialValue": 5.0, "upperBound": 10.0})
8949 * \endif
8950 * the following keywords ( = default values) may be used:
8951 *
8952 */
8953
8954 /*! \page feaDesignVariable
8955 *
8956 * \if (NASTRAN || ASTROS || MASSTRAN)
8957 * <ul>
8958 * <li> <B>initialValue = 0.0</B> </li> <br>
8959 * Initial value for the design variable.
8960 * </ul>
8961 * \endif
8962 *
8963 */
8964 keyWord = "initialValue";
8965 status = json_getDouble(
8966 designVariableTuple[i].value, keyWord,
8967 &designVariable->initialValue);
8968
8969 if (status != CAPS_SUCCESS0) {
8970 designVariable->initialValue = 0.0;
8971 }
8972
8973 /*! \page feaDesignVariable
8974 *
8975 * \if (NASTRAN || ASTROS)
8976 * <ul>
8977 * <li> <B>lowerBound = 0.0</B> </li> <br>
8978 * Lower bound for the design variable.
8979 * </ul>
8980 * \endif
8981 */
8982 keyWord = "lowerBound";
8983 status = json_getDouble(
8984 designVariableTuple[i].value, keyWord,
8985 &designVariable->lowerBound);
8986
8987 if (status != CAPS_SUCCESS0) {
8988 designVariable->lowerBound = 0.0;
8989 }
8990
8991 /*! \page feaDesignVariable
8992 *
8993 * \if (NASTRAN || ASTROS)
8994 * <ul>
8995 * <li> <B>upperBound = 0.0</B> </li> <br>
8996 * Upper bound for the design variable.
8997 * </ul>
8998 * \endif
8999 */
9000 keyWord = "upperBound";
9001 status = json_getDouble(
9002 designVariableTuple[i].value, keyWord,
9003 &designVariable->upperBound);
9004
9005 if (status != CAPS_SUCCESS0) {
9006 designVariable->upperBound = 0.0;
9007 }
9008
9009 /*! \page feaDesignVariable
9010 *
9011 * \if (NASTRAN || ASTROS)
9012 * <ul>
9013 * <li> <B>maxDelta = 0.0</B> </li> <br>
9014 * Move limit for the design variable.
9015 * </ul>
9016 * \endif
9017 */
9018 keyWord = "maxDelta";
9019 status = json_getDouble(
9020 designVariableTuple[i].value, keyWord,
9021 &designVariable->maxDelta);
9022
9023 if (status != CAPS_SUCCESS0) {
9024 designVariable->maxDelta = 0.0;
9025 }
9026
9027 /*! \page feaDesignVariable
9028 *
9029 * \if (NASTRAN || ASTROS)
9030 * <ul>
9031 * <li> <B>discreteValue = 0.0</B> </li> <br>
9032 * List of discrete values to use for the design variable (e.g. [0.0,1.0,1.5,3.0].
9033 * </ul>
9034 * \endif
9035 */
9036 keyWord = "discreteValue";
9037 status = json_getDoubleDynamicArray(
9038 designVariableTuple[i].value, keyWord,
9039 &designVariable->numDiscreteValue, &designVariable->discreteValue);
9040
9041 if (status != CAPS_SUCCESS0) {
9042 designVariable->numDiscreteValue = 0;
9043 designVariable->discreteValue = NULL((void*)0);
9044 }
9045
9046 /*! \page feaDesignVariable
9047 *
9048 * \if NASTRAN
9049 * <ul>
9050 * <li> <B>independentVariable = "(no default)"</B> </li> <br>
9051 * Single or list of "DesignVariable Name"s (that is the Tuple name) used to create/designate a
9052 * dependent design variable.
9053 * - independentValue = variableWeight[1] + variableWeight[2] * SUM{independentVariableWeight[i] * independentVariable[i]}
9054 * </ul>
9055 * \endif
9056 */
9057
9058 keyWord = "independentVariable";
9059 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9060 if (status == CAPS_SUCCESS0) {
9061
9062 status = string_toStringDynamicArray(keyValue,
9063 &designVariable->numIndependVariable,
9064 &designVariable->independVariable);
9065 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9066 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9066
, __func__, 0); goto cleanup; }
;
9067
9068 }
9069
9070 /*! \page feaDesignVariable
9071 *
9072 * \if NASTRAN
9073 * <ul>
9074 * <li> <B>independentVariableWeight = 1.0 or [1.0, 1.0, ...]</B> </li> <br>
9075 * Single or list of weighting constants with respect to the variables set for "independentVariable".
9076 * If the length of this list doesn't match the length
9077 * of the "independentVariable" list, the list is either truncated [ >length("independentVariable")] or expanded [ <length("independentVariable")]
9078 * in which case the <b>last weight is repeated</b>.
9079 * </ul>
9080 * \endif
9081 */
9082
9083 keyWord = "independentVariableWeight";
9084 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9085 if (status == CAPS_SUCCESS0) {
9086
9087 status = string_toDoubleDynamicArray(keyValue,
9088 &tempInteger,
9089 &designVariable->independVariableWeight);
9090 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9091 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9091
, __func__, 0); goto cleanup; }
;
9092
9093 // We have weights, but no variables
9094 if (designVariable->numIndependVariable == 0) {
9095
9096 printf("\tWeighting constants have been provided, but no independent design variables were set!\n");
9097
9098 // Less weights than variables
9099 } else if( tempInteger < designVariable->numIndependVariable) {
9100
9101 printf("\tThe number of weighting constants provided does not match the number of independent design variables. "
9102 "The last weight will be repeated %d times\n", designVariable->numIndependVariable - tempInteger);
9103
9104 AIM_REALL(designVariable->independVariableWeight,{ size_t memorysize = designVariable->numIndependVariable;
designVariable->independVariableWeight = (double *) EG_reall
(designVariable->independVariableWeight, memorysize*sizeof
(double)); if (designVariable->independVariableWeight == (
(void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 9105, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
9105 designVariable->numIndependVariable, double, aimInfo, status){ size_t memorysize = designVariable->numIndependVariable;
designVariable->independVariableWeight = (double *) EG_reall
(designVariable->independVariableWeight, memorysize*sizeof
(double)); if (designVariable->independVariableWeight == (
(void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 9105, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
;
9106
9107 for (j = 0; j < designVariable->numIndependVariable - tempInteger; j++) {
9108
9109 designVariable->independVariableWeight[j+tempInteger] = designVariable->independVariableWeight[tempInteger-1];
9110 }
9111
9112 // More weights than variables
9113 } else if (tempInteger > designVariable->numIndependVariable) {
9114
9115 printf("\tThe number of weighting constants provided does not match the number of independent design variables. "
9116 "The last %d weights will be not be used\n", tempInteger -designVariable->numIndependVariable);
9117
9118 AIM_REALL(designVariable->independVariableWeight,{ size_t memorysize = designVariable->numIndependVariable;
designVariable->independVariableWeight = (double *) EG_reall
(designVariable->independVariableWeight, memorysize*sizeof
(double)); if (designVariable->independVariableWeight == (
(void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 9119, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
9119 designVariable->numIndependVariable, double, aimInfo, status){ size_t memorysize = designVariable->numIndependVariable;
designVariable->independVariableWeight = (double *) EG_reall
(designVariable->independVariableWeight, memorysize*sizeof
(double)); if (designVariable->independVariableWeight == (
(void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 9119, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
;
9120 }
9121
9122 } else { // No weights provided - set default value of 1.0
9123
9124 if (designVariable->numIndependVariable != 0) {
9125 AIM_ALLOC(designVariable->independVariableWeight, designVariable->numIndependVariable, double, aimInfo, status){ if (designVariable->independVariableWeight != ((void*)0)
) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9125
, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariable->independVariableWeight"
); goto cleanup; } size_t memorysize = designVariable->numIndependVariable
; designVariable->independVariableWeight = (double *) EG_alloc
(memorysize*sizeof(double)); if (designVariable->independVariableWeight
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 9125, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
;
9126
9127 for (j = 0; j < designVariable->numIndependVariable; j++) {
9128 designVariable->independVariableWeight[j] = 1.0;
9129 }
9130 }
9131 }
9132
9133 /*! \page feaDesignVariable
9134 *
9135 * \if NASTRAN
9136 * <ul>
9137 * <li> <B>variableWeight = [1.0, 1.0]</B> </li> <br>
9138 * Weighting constants for a dependent variable - used if "independentVariable"(s) have been provided.
9139 * </ul>
9140 * \endif
9141 */
9142 keyWord = "variableWeight";
9143 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9144 if (status == CAPS_SUCCESS0) {
9145
9146 status = string_toDoubleArray(keyValue,
9147 2,
9148 designVariable->variableWeight);
9149 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9150
9151 if (status != CAPS_SUCCESS0) {
9152 AIM_ERROR(aimInfo, "Retrieving variableWeight - status %d\n", status){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9152, __func__
, "Retrieving variableWeight - status %d\n", status); }
;
9153 goto cleanup;
9154 }
9155 } else {
9156 designVariable->variableWeight[0] = 1.0;
9157 designVariable->variableWeight[1] = 1.0;
9158 }
9159
9160 // check if design variable relation info also included in input
9161 keyWord = "fieldName";
9162 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9163
9164 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9165
9166 if (status != CAPS_SUCCESS0) {
9167 keyWord = "fieldPosition";
9168 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9169 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9170 }
9171
9172 if (status == CAPS_SUCCESS0) {
9173
9174// // The main relation associated with this design variable, if defined in input
9175// AIM_REALL(feaProblem->feaDesignVariableRelation, relationIndex+1, feaDesignVariableRelationStruct, aimInfo, status);
9176//
9177// designVariableRelation = &feaProblem->feaDesignVariableRelation[relationIndex++];
9178//
9179// feaProblem->numDesignVariableRelation = relationIndex;
9180//
9181// status = initiate_feaDesignVariableRelationStruct(designVariableRelation);
9182// AIM_STATUS(aimInfo, status);
9183//
9184// printf("\tWarning: the ability to provide design variable relation data "
9185// "within Design_Variable input is deprecated and "
9186// "will be removed in the future. Please use provide relation data "
9187// "via \"Design_Variable_Relation\" instead.\n");
9188//
9189// status = fea_getDesignVariableRelationEntry( &designVariableTuple[i], designVariableRelation,
9190// attrMap, feaProblem, designVariable->name);
9191// AIM_STATUS(aimInfo, status);
9192//
9193// designVariableRelation->relationID = relationIndex;
9194
9195 AIM_ERROR(aimInfo, "The ability to provide design variable relation data "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9197, __func__
, "The ability to provide design variable relation data " "within Design_Variable input is deprecated. Please provide relation data "
"via \"Design_Variable_Relation\" instead.\n"); }
9196 "within Design_Variable input is deprecated. Please provide relation data "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9197, __func__
, "The ability to provide design variable relation data " "within Design_Variable input is deprecated. Please provide relation data "
"via \"Design_Variable_Relation\" instead.\n"); }
9197 "via \"Design_Variable_Relation\" instead.\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9197, __func__
, "The ability to provide design variable relation data " "within Design_Variable input is deprecated. Please provide relation data "
"via \"Design_Variable_Relation\" instead.\n"); }
;
9198 status = CAPS_BADVALUE-311;
9199 goto cleanup;
9200 }
9201
9202
9203 } else {
9204
9205 AIM_ERROR(aimInfo, "Design_Variable tuple value is expected to be a JSON string\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9205, __func__
, "Design_Variable tuple value is expected to be a JSON string\n"
); }
;
9206 status = CAPS_BADVALUE-311;
9207 goto cleanup;
9208
9209 }
9210 }
9211
9212 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9213
9214 // Order the design variable ID's such that Analysis and Geometry ID's are continuous.
9215 // This is required by the TACS AIM
9216
9217 designVariableID = 1;
9218 for( i = 0; i < feaProblem->numDesignVariable; i++) {
9219
9220 // only analysis design variables
9221 if (aim_getIndex(aimInfo, feaProblem->feaDesignVariable[i].name, GEOMETRYIN) <= 0)
9222 feaProblem->feaDesignVariable[i].designVariableID = designVariableID++;
9223 }
9224 for( i = 0; i < feaProblem->numDesignVariable; i++) {
9225
9226 // only geometry design variables
9227 if (aim_getIndex(aimInfo, feaProblem->feaDesignVariable[i].name, GEOMETRYIN) > 0)
9228 feaProblem->feaDesignVariable[i].designVariableID = designVariableID++;
9229 }
9230
9231 // Now that we are done going through all the tuples we need to populate/create the independVaraiableID array
9232 // if independentVariable was set for any of them.
9233 for (i = 0; i < feaProblem->numDesignVariable; i++) {
9234
9235 designVariable = &feaProblem->feaDesignVariable[i];
9236
9237 if (designVariable->numIndependVariable != 0) {
9238
9239 AIM_ALLOC(designVariable->independVariableID, designVariable->numIndependVariable, int, aimInfo, status){ if (designVariable->independVariableID != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 9239, __func__
, 1, "AIM_ALLOC: %s != NULL", "designVariable->independVariableID"
); goto cleanup; } size_t memorysize = designVariable->numIndependVariable
; designVariable->independVariableID = (int *) EG_alloc(memorysize
*sizeof(int)); if (designVariable->independVariableID == (
(void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 9239, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariable->independVariableID"
, memorysize, "int"); goto cleanup; } }
;
9240
9241 // Loop through the independent variable names
9242 for (j = 0; j < designVariable->numIndependVariable; j++) {
9243
9244 // Compare the independent variable names with design variable name
9245 found = (int) false0;
9246 for (k = 0; k < feaProblem->numDesignVariable; k++) {
9247 if (strcasecmp(designVariable->independVariable[j], feaProblem->feaDesignVariable[k].name) == 0) {
9248 found = (int) true1;
9249 break;
9250 }
9251 }
9252
9253 // If NOT found
9254 if (found != (int) true1) {
9255 AIM_ERROR(aimInfo, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9257, __func__
, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "
"variable %s!!!\n", designVariable->independVariable[j], designVariable
->name); }
9256 "variable %s!!!\n", designVariable->independVariable[j],{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9257, __func__
, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "
"variable %s!!!\n", designVariable->independVariable[j], designVariable
->name); }
9257 designVariable->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9257, __func__
, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "
"variable %s!!!\n", designVariable->independVariable[j], designVariable
->name); }
;
9258 status = CAPS_NOTFOUND-303;
9259 goto cleanup;
9260 }
9261
9262 designVariable->independVariableID[j] = feaProblem->feaDesignVariable[k].designVariableID;
9263 }
9264 }
9265 }
9266
9267 if (designVariableRelationTuple != NULL((void*)0)) {
9268
9269 AIM_ALLOC(feaProblem->feaDesignVariableRelation, numDesignVariableRelationTuple, feaDesignVariableRelationStruct, aimInfo, status){ if (feaProblem->feaDesignVariableRelation != ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9269
, __func__, 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaDesignVariableRelation"
); goto cleanup; } size_t memorysize = numDesignVariableRelationTuple
; feaProblem->feaDesignVariableRelation = (feaDesignVariableRelationStruct
*) EG_alloc(memorysize*sizeof(feaDesignVariableRelationStruct
)); if (feaProblem->feaDesignVariableRelation == ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9269
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariableRelation"
, memorysize, "feaDesignVariableRelationStruct"); goto cleanup
; } }
;
9270 feaProblem->numDesignVariableRelation = numDesignVariableRelationTuple;
9271
9272 for (i = 0; i < numDesignVariableRelationTuple; i++) {
9273 status = initiate_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]);
9274 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9274
, __func__, 0); goto cleanup; }
;
9275 }
9276
9277 // Go through design variable relations defined via 'Design_Variable_Relation'
9278 for (i = 0; i < numDesignVariableRelationTuple; i++) {
9279
9280 /*! \page feaDesignVariableRelation FEA DesignVariableRelation
9281 * Structure for the design variable tuple = ("DesignVariableRelation Name", "Value").
9282 * "DesignVariableRelation Name" defines the reference name for the design variable being specified.
9283 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
9284 * (see Section \ref jsonStringDesignVariableRelation).
9285 *
9286 */
9287
9288 designVariableRelation = &feaProblem->feaDesignVariableRelation[i];
9289
9290 designVariableRelation->relationID = i+1;
9291
9292 status = fea_getDesignVariableRelationEntry(
9293 aimInfo, &designVariableRelationTuple[i], designVariableRelation,
9294 attrMap, feaProblem, NULL((void*)0)
9295 );
9296 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9296
, __func__, 0); goto cleanup; }
;
9297 }
9298
9299 }
9300 status = fea_linkDesignVariablesAndRelations(feaProblem);
9301 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9301
, __func__, 0); goto cleanup; }
;
9302
9303 printf("\tNumber of design variable relations - %d\n", feaProblem->numDesignVariableRelation);
9304 printf("\tDone getting FEA design variables\n");
9305 status = CAPS_SUCCESS0;
9306
9307cleanup:
9308
9309 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9310
9311 if (groupName != NULL((void*)0))
9312 string_freeArray(numGroupName, &groupName);
9313
9314 return status;
9315}
9316
9317int fea_getDesignVariableRelationEntry(void *aimInfo,
9318 capsTuple *designVariableInput,
9319 /*@unused@*/ feaDesignVariableRelationStruct *designVariableRelation,
9320 /*@unused@*/ mapAttrToIndexStruct *attrMap,
9321 /*@unused@*/ feaProblemStruct *feaProblem,
9322 /*@unused@*/ char *forceGroupName) {
9323
9324
9325 int status; //Function return
9326
9327 int i, j; // Indexing
9328
9329 int numLinearCoeff;
9330
9331 char *keyValue = NULL((void*)0);
9332 char *keyWord = NULL((void*)0);
9333
9334 char **groupName = NULL((void*)0);
9335 int numGroupName = 0;
9336
9337 feaMeshDataStruct *feaData = NULL((void*)0);
9338
9339 int numMaterial;
9340 feaMaterialStruct **materialSet = NULL((void*)0), *material;
9341
9342 int numProperty;
9343 feaPropertyStruct **propertySet = NULL((void*)0), *property;
9344
9345 int numElement;
9346 meshElementStruct **elementSet = NULL((void*)0), *element;
9347
9348 printf("\tDesign_Variable_Relation name - %s\n", designVariableInput->name);
9349
9350 designVariableRelation->name = EG_strdup(designVariableInput->name);
9351
9352 /*! \page feaDesignVariableRelation FEA Design Variable Relations
9353 * \section jsonStringDesignVariableRelation JSON String Dictionary
9354 *
9355 * If "Value" is JSON string dictionary
9356 * \if (NASTRAN || TACS || MASSTRAN)
9357 * (eg. "Value" = {"componentType": "Property", "componentName": "plate", "fieldName": "TM", "variableName": "MyDesVar"})
9358 * \endif
9359 * \if (ASTROS)
9360 * (eg. "Value" = {"componentType": "Property", "componentName": "plate", "variableName": "MyDesVar"})
9361 * \endif
9362 * the following keywords ( = default values) may be used:
9363 *
9364 */
9365 if (!json_isDict(designVariableInput->value)) {
9366 AIM_ERROR(aimInfo,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9367, __func__
, "'Design_Variable_Relation' tuple value must be a JSON dictionary"
); }
9367 "'Design_Variable_Relation' tuple value must be a JSON dictionary"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9367, __func__
, "'Design_Variable_Relation' tuple value must be a JSON dictionary"
); }
;
9368 return CAPS_BADVALUE-311;
9369 }
9370
9371 /*! \page feaDesignVariableRelation
9372 * \if (NASTRAN || TACS || MASSTRAN)
9373 * <ul>
9374 * <li> <B>componentType = "Property"</B> </li> <br>
9375 * The type of component for this design variable relation. Options: "Material", "Property", "Element".
9376 * </ul>
9377 * \endif
9378 * \if (ASTROS)
9379 * <ul>
9380 * <li> <B>componentType = "Property"</B> </li> <br>
9381 * The type of component for this design variable relation. Options: "Property".
9382 * </ul>
9383 * \endif
9384 *
9385 */
9386 // Get component type for design variable relation
9387 keyWord = "componentType";
9388 status = json_getString(
9389 designVariableInput->value, keyWord, &keyValue);
9390
9391 // If "componentType" not found, check "variableType" for legacy purposes
9392 // Warn that "variableType" is deprecated and will be removed in the future!
9393 if (status != CAPS_SUCCESS0) {
9394
9395 status = json_getString(
9396 designVariableInput->value, "variableType", &keyValue);
9397
9398 if (status == CAPS_SUCCESS0) {
9399 printf("\tWarning: \"variableType\" is deprecated and "
9400 "will be removed in the future. Please use \"componentType\" "
9401 "instead.\n");
9402 }
9403 }
9404
9405 if (status == CAPS_SUCCESS0) {
9406 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 9406, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
9407
9408 if (strcasecmp(keyValue, "Material") == 0) designVariableRelation->componentType = MaterialDesignVar;
9409 else if (strcasecmp(keyValue, "Property") == 0) designVariableRelation->componentType = PropertyDesignVar;
9410 else if (strcasecmp(keyValue, "Element") == 0) designVariableRelation->componentType = ElementDesignVar;
9411 else {
9412
9413 printf("\tUnrecognized \"%s\" specified (%s) for Design_Variable_Relation tuple %s, defaulting to \"Property\"\n", keyWord,
9414 keyValue,
9415 designVariableInput->name);
9416 designVariableRelation->componentType = PropertyDesignVar;
9417 }
9418
9419 }
9420 else {
9421 printf("\tNo \"%s\" specified for Design_Variable_Relation tuple %s, defaulting to \"Property\"\n", keyWord,
9422 designVariableInput->name);
9423
9424 designVariableRelation->componentType = PropertyDesignVar;
9425 }
9426
9427 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9428
9429 /*! \page feaDesignVariableRelation
9430 *
9431 * \if (NASTRAN || TACS || MASSTRAN)
9432 * <ul>
9433 * <li> <B>componentName = "(no default)"</B> </li> <br>
9434 * Single or list of FEA Property(ies), or FEA Material name(s) linked
9435 * to the design variable relation (e.g. "Name1" or ["Name1","Name2",...].
9436 * - For <c>componentType</c> Property a \ref feaProperty name (or names) is given.
9437 * - For <c>componentType</c> Material a \ref feaMaterial name (or names) is given.
9438 * \if (NASTRAN || TACS)
9439 * - For <c>componentType</c> Element a <c>capsGroup</c> Name (or names) is given.
9440 * \endif
9441 * </ul>
9442 * \endif
9443 * \if (ASTROS)
9444 * <ul>
9445 * <li> <B>componentName = "(no default)"</B> </li> <br>
9446 * Single FEA Property linked to the design variable (e.g. "Name1").
9447 * - For <c>componentType</c> Property a \ref feaProperty name (or names) is given.
9448 * </ul>
9449 * \endif
9450 *
9451 */
9452 keyWord = "componentName";
9453 status = json_getStringDynamicArray(
9454 designVariableInput->value, keyWord,
9455 &numGroupName, &groupName);
9456
9457 if (status != CAPS_SUCCESS0) {
9458 // required
9459 AIM_ERROR(aimInfo, "No \"%s\" specified for Design_Variable tuple %s",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9460, __func__
, "No \"%s\" specified for Design_Variable tuple %s", keyWord
, designVariableInput->name); }
9460 keyWord, designVariableInput->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9460, __func__
, "No \"%s\" specified for Design_Variable tuple %s", keyWord
, designVariableInput->name); }
;
9461 goto cleanup;
9462 }
9463 AIM_NOTNULL(groupName, aimInfo, status){ if (groupName == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 9463, __func__, 1, "%s == NULL!", "groupName"
); goto cleanup; } }
;
9464
9465 // collect materials associated with groupName
9466 status = fea_findMaterialsByNames(feaProblem, numGroupName, groupName, &numMaterial, &materialSet);
9467
9468 if (status == CAPS_SUCCESS0) {
9469
9470 AIM_ALLOC(designVariableRelation->materialSetID, numMaterial, int, aimInfo, status){ if (designVariableRelation->materialSetID != ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9470
, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->materialSetID"
); goto cleanup; } size_t memorysize = numMaterial; designVariableRelation
->materialSetID = (int *) EG_alloc(memorysize*sizeof(int))
; if (designVariableRelation->materialSetID == ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9470
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->materialSetID"
, memorysize, "int"); goto cleanup; } }
;
9471 AIM_ALLOC(designVariableRelation->materialSetType, numMaterial, int, aimInfo, status){ if (designVariableRelation->materialSetType != ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9471
, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->materialSetType"
); goto cleanup; } size_t memorysize = numMaterial; designVariableRelation
->materialSetType = (int *) EG_alloc(memorysize*sizeof(int
)); if (designVariableRelation->materialSetType == ((void*
)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c",
9471, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->materialSetType"
, memorysize, "int"); goto cleanup; } }
;
9472 designVariableRelation->numMaterialID = numMaterial;
9473
9474 for (j = 0; j < numMaterial; j++) {
9475
9476 material = materialSet[j];
9477 designVariableRelation->materialSetID[j] = material->materialID;
9478 designVariableRelation->materialSetType[j] = material->materialType;
9479
9480 }
9481 }
9482
9483 // collect properties associated with groupName
9484 status = fea_findPropertiesByNames(feaProblem, numGroupName, groupName,
9485 &numProperty, &propertySet);
9486
9487 if (status == CAPS_SUCCESS0) {
9488
9489 AIM_ALLOC(designVariableRelation->propertySetID, numProperty, int, aimInfo, status){ if (designVariableRelation->propertySetID != ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9489
, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->propertySetID"
); goto cleanup; } size_t memorysize = numProperty; designVariableRelation
->propertySetID = (int *) EG_alloc(memorysize*sizeof(int))
; if (designVariableRelation->propertySetID == ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9489
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->propertySetID"
, memorysize, "int"); goto cleanup; } }
;
9490 AIM_ALLOC(designVariableRelation->propertySetType, numProperty, int, aimInfo, status){ if (designVariableRelation->propertySetType != ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9490
, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->propertySetType"
); goto cleanup; } size_t memorysize = numProperty; designVariableRelation
->propertySetType = (int *) EG_alloc(memorysize*sizeof(int
)); if (designVariableRelation->propertySetType == ((void*
)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c",
9490, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->propertySetType"
, memorysize, "int"); goto cleanup; } }
;
9491 designVariableRelation->numPropertyID = numProperty;
9492
9493 for (j = 0; j < numProperty; j++) {
9494
9495 property = propertySet[j];
9496 designVariableRelation->propertySetID[j] = property->propertyID;
9497 designVariableRelation->propertySetType[j] = property->propertyType;
9498
9499 }
9500 }
9501
9502 // collect elements associated with groupName
9503 status = mesh_findGroupElements(
9504 &feaProblem->feaMesh, attrMap, numGroupName, groupName, &numElement, &elementSet);
9505
9506 if (status == CAPS_SUCCESS0) {
9507
9508 AIM_ALLOC(designVariableRelation->elementSetID, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetID != ((void*)0)) {
status = -4; aim_status(aimInfo, status, "feaUtils.c", 9508,
__func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->elementSetID"
); goto cleanup; } size_t memorysize = numElement; designVariableRelation
->elementSetID = (int *) EG_alloc(memorysize*sizeof(int));
if (designVariableRelation->elementSetID == ((void*)0)) {
status = -4; aim_status(aimInfo, status, "feaUtils.c", 9508,
__func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetID"
, memorysize, "int"); goto cleanup; } }
;
9509 AIM_ALLOC(designVariableRelation->elementSetType, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetType != ((void*)0)
) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9509
, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->elementSetType"
); goto cleanup; } size_t memorysize = numElement; designVariableRelation
->elementSetType = (int *) EG_alloc(memorysize*sizeof(int)
); if (designVariableRelation->elementSetType == ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9509
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetType"
, memorysize, "int"); goto cleanup; } }
;
9510 AIM_ALLOC(designVariableRelation->elementSetSubType, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetSubType != ((void*
)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c",
9510, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->elementSetSubType"
); goto cleanup; } size_t memorysize = numElement; designVariableRelation
->elementSetSubType = (int *) EG_alloc(memorysize*sizeof(int
)); if (designVariableRelation->elementSetSubType == ((void
*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 9510, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetSubType"
, memorysize, "int"); goto cleanup; } }
;
9511 designVariableRelation->numElementID = numElement;
9512
9513 for (j = 0; j < numElement; j++) {
9514
9515 element = elementSet[j];
9516 designVariableRelation->elementSetID[j] = element->elementID;
9517 designVariableRelation->elementSetType[j] = element->elementType;
9518 feaData = (feaMeshDataStruct *) element->analysisData;
9519 designVariableRelation->elementSetSubType[j] = feaData->elementSubType;
9520
9521 }
9522 }
9523
9524 if (groupName != NULL((void*)0))
9525 string_freeArray(numGroupName, &groupName);
9526 numGroupName = 0;
9527 groupName = NULL((void*)0);
9528
9529 AIM_FREE(materialSet){ EG_free(materialSet); materialSet = ((void*)0); };
9530 AIM_FREE(propertySet){ EG_free(propertySet); propertySet = ((void*)0); };
9531 AIM_FREE(elementSet){ EG_free(elementSet); elementSet = ((void*)0); };
9532
9533 /*! \page feaDesignVariableRelation
9534 *
9535 * \if (NASTRAN || TACS || MASSTRAN)
9536 * <ul>
9537 * <li> <B>variableName = "(no default)"</B> </li> <br>
9538 * Single or list of names of design variables linked to this relation
9539 * </ul>
9540 * \endif
9541 * \if (ASTROS)
9542 * <ul>
9543 * <li> <B>variableName = "(no default)"</B> </li> <br>
9544 * Name of design variable linked to this relation
9545 * </ul>
9546 * \endif
9547 */
9548 keyWord = "variableName";
9549 status = json_getStringDynamicArray(
9550 designVariableInput->value, keyWord,
9551 &designVariableRelation->numDesignVariable, &designVariableRelation->designVariableNameSet);
9552 if (status != CAPS_SUCCESS0) {
9553 // required
9554 AIM_ERROR(aimInfo, "No \"%s\" specified for Design_Variable_Relation tuple %s",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9555, __func__
, "No \"%s\" specified for Design_Variable_Relation tuple %s"
, keyWord, designVariableInput->name); }
9555 keyWord, designVariableInput->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9555, __func__
, "No \"%s\" specified for Design_Variable_Relation tuple %s"
, keyWord, designVariableInput->name); }
;
9556 goto cleanup;
9557 }
9558
9559 /*! \page feaDesignVariableRelation
9560 *
9561 * \if (NASTRAN || TACS || MASSTRAN)
9562 * <ul>
9563 * <li> <B>fieldName = "(no default)"</B> </li> <br>
9564 * Fieldname of variable relation (e.g. "E" for Young's Modulus). Design Variable Relations can be defined as three types based on the <c>variableType</c> value.
9565 * These are Material, Property, or Element. This means that an aspect of a material, property, or element input can change in the optimization problem. This input
9566 * specifies what aspect of the Material, Property, or Element is changing.
9567 * \if (MASSTRAN)
9568 * -# <b> Material Types</b> Selected based on the material type (see \ref feaMaterial, materialType) referenced in the <c>componentName</c> above.
9569 * - <c> materialType = "Isotropic" </c>
9570 * - "density"
9571 * -# <b> Property Types</b> (see \ref feaProperty)
9572 * - <c>propertyType = "ConcentratedMass"</c>
9573 * - "mass",
9574 * - "massOffset1", "massOffset2", "massOffset2"
9575 * - "Ixx", "Iyy", "Izz", "Ixy", "Ixz", "Iyz"
9576 * - <c>propertyType = "Shell"</c>
9577 * - "membraneThickness", "massPerArea"
9578 * \else
9579 * -# <b> Material Types</b> Selected based on the material type (see \ref feaMaterial, materialType) referenced in the <c>componentName</c> above.
9580 * - <c><b> MAT1</b>, materialType = "Isotropic" </c>
9581 * - "E", "G", "NU", "RHO", "A"
9582 * - <c><b> MAT2</b>, materialType = "Anisothotropic" </c>
9583 * - "G11", "G12", "G13", "G22", "G23", "G33", "RHO", "A1", "A2", "A3"
9584 * - <c><b> MAT8</b>, materialType = "Orthotropic" </c>
9585 * - "E1", "E2", "NU12", "G12", "G1Z", "G2Z", "RHO", "A1", "A2"
9586 * - <c><b> MAT9</b>, materialType = "Anisotropic" </c>
9587 * - "G11", "G12", "G13", "G14", "G15", "G16"
9588 * - "G22", "G23", "G24", "G25", "G26"
9589 * - "G33", "G34", "G35", "G36"
9590 * - "G44", "G45", "G46"
9591 * - "G55", "G56", "G66"
9592 * - "RHO", "A1", "A2", "A3", "A4", "A5", "A6"
9593 * -# <b> Property Types</b> (see \ref feaProperty)
9594 * - <c><b> PROD</b> </c> <c>propertyType = "Rod"</c>
9595 * - "A", "J"
9596 * - <c><b> PBAR</b> </c> <c>propertyType = "Bar"</c>
9597 * - "A", "I1", "I2", "J"
9598 * - <c><b> PSHELL</b> </c> <c>propertyType = "Shell"</c>
9599 * - "T"
9600 * - <c><b> PCOMP</b> </c> <c>propertyType = "Composite"</c>
9601 * - "T1", "THETA1", "T2", "THETA2", ... "Ti", "THETAi"
9602 * - <c><b> PSOLID</b> </c> <c>propertyType = "Solid"</c>
9603 * - not supported
9604 * -# <b> Element Types</b>
9605 * - <c><b> CTRIA3, CQUAD4</b> </c> <c>propertyType = "Shell"</c>
9606 * - "ZOFFS"
9607 * \endif
9608 * </ul>
9609 * \endif
9610 */
9611 keyWord = "fieldName";
9612 status = json_getString(
9613 designVariableInput->value, keyWord,
9614 &designVariableRelation->fieldName);
9615 if (status != CAPS_SUCCESS0) {
9616 // optional
9617 }
9618
9619 /*! \page feaDesignVariableRelation
9620 *
9621 * \if (NASTRAN || TACS)
9622 * <ul>
9623 * <li> <B>fieldPosition = 0</B> </li> <br>
9624 * This input is ignored if not defined. The user may use this field instead of the <c>fieldName</c> input defined above to
9625 * relate design variables and property, material, or elements. This requires knowledge of Nastran bulk data input format for material,
9626 * property, and element input cards.
9627 * </ul>
9628 * \endif
9629 */
9630
9631 keyWord = "fieldPosition";
9632 status = json_getInteger(
9633 designVariableInput->value, keyWord,
9634 &designVariableRelation->fieldPosition);
9635 if (status != CAPS_SUCCESS0) {
9636 // optional
9637 }
9638
9639 /*! \page feaDesignVariableRelation
9640 *
9641 * \if (NASTRAN || TACS || ASTROS || MASSTRAN)
9642 * <ul>
9643 * <li> <B>constantCoeff = 0.0</B> </li> <br>
9644 * Constant term of relation.
9645 * </ul>
9646 * \endif
9647 */
9648 keyWord = "constantCoeff";
9649 status = json_getDouble(
9650 designVariableInput->value, keyWord,
9651 &designVariableRelation->constantRelationCoeff);
9652 if (status != CAPS_SUCCESS0) {
9653 // default
9654 designVariableRelation->constantRelationCoeff = 0.0;
9655 }
9656
9657 /*! \page feaDesignVariableRelation
9658 *
9659 * \if (NASTRAN || TACS || ASTROS || MASSTRAN)
9660 * <ul>
9661 * <li> <B>linearCoeff = 1.0</B> </li> <br>
9662 * Single or list of coefficients of linear relation. Must be same length as <c>variableName</c>.
9663 * </ul>
9664 * \endif
9665 */
9666 keyWord = "linearCoeff";
9667 status = json_getDoubleDynamicArray(
9668 designVariableInput->value, keyWord,
9669 &numLinearCoeff, &designVariableRelation->linearRelationCoeff);
9670
9671 if (status != CAPS_SUCCESS0) {
9672 // default
9673 numLinearCoeff = designVariableRelation->numDesignVariable;
9674 designVariableRelation->linearRelationCoeff = EG_alloc(numLinearCoeff * sizeof(double));
9675 if (designVariableRelation->linearRelationCoeff == NULL((void*)0)) {
9676 status = EGADS_MALLOC-4;
9677 goto cleanup;
9678 }
9679
9680 for (i = 0; i < numLinearCoeff; i++) {
9681 designVariableRelation->linearRelationCoeff[i] = 1.0;
9682 }
9683 }
9684
9685 if (numLinearCoeff != designVariableRelation->numDesignVariable) {
9686 AIM_ERROR(aimInfo, "Number of \"linearCoeff\" values (%d) does not match"{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9688, __func__
, "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)"
, numLinearCoeff, designVariableRelation->numDesignVariable
); }
9687 " number of \"variableName\" values (%d)",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9688, __func__
, "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)"
, numLinearCoeff, designVariableRelation->numDesignVariable
); }
9688 numLinearCoeff, designVariableRelation->numDesignVariable){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9688, __func__
, "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)"
, numLinearCoeff, designVariableRelation->numDesignVariable
); }
;
9689 status = CAPS_BADVALUE-311;
9690 goto cleanup;
9691 }
9692
9693 status = CAPS_SUCCESS0;
9694
9695cleanup:
9696
9697 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9698
9699 return status;
9700}
9701
9702// Get the design constraints from a capsTuple
9703int fea_getDesignConstraint(void *aimInfo,
9704 int numDesignConstraintTuple,
9705 capsTuple designConstraintTuple[],
9706 feaProblemStruct *feaProblem) {
9707
9708 /*! \page feaDesignConstraint FEA Design Constraints
9709 * Structure for the design constraint tuple = (`DesignConstraint Name', `Value').
9710 * 'DesignConstraint Name' defines the reference name for the design constraint being specified.
9711 * The "Value" must be a JSON String dictionary (see Section \ref jsonStringDesignConstraint).
9712 */
9713
9714 int status; //Function return
9715
9716 int i, groupIndex, attrIndex; // Indexing
9717
9718 char *keyValue = NULL((void*)0);
9719 char *keyWord = NULL((void*)0);
9720
9721 char *tempString = NULL((void*)0);
9722
9723 char **groupName = NULL((void*)0);
9724 int numGroupName = 0;
9725
9726 // Destroy our design constraints structures coming in if aren't 0 and NULL already
9727 if (feaProblem->feaDesignConstraint != NULL((void*)0)) {
9728 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
9729 status = destroy_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]);
9730 if (status != CAPS_SUCCESS0) return status;
9731 }
9732 }
9733 if (feaProblem->feaDesignConstraint != NULL((void*)0)) EG_free(feaProblem->feaDesignConstraint);
9734 feaProblem->feaDesignConstraint = NULL((void*)0);
9735 feaProblem->numDesignConstraint = 0;
9736
9737 printf("\nGetting FEA design constraints.......\n");
9738
9739 feaProblem->numDesignConstraint = numDesignConstraintTuple;
9740
9741 printf("\tNumber of design constraints - %d\n", feaProblem->numDesignConstraint);
9742
9743 if (feaProblem->numDesignConstraint > 0) {
9744 feaProblem->feaDesignConstraint = (feaDesignConstraintStruct *) EG_alloc(feaProblem->numDesignConstraint * sizeof(feaDesignConstraintStruct));
9745
9746 if (feaProblem->feaDesignConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
9747
9748 } else {
9749 printf("\tNumber of design constraint values in input tuple is 0\n");
9750 return CAPS_NOTFOUND-303;
9751 }
9752
9753 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
9754 status = initiate_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]);
9755 if (status != CAPS_SUCCESS0) return status;
9756 }
9757
9758 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
9759
9760 printf("\tDesign_Constraint name - %s\n", designConstraintTuple[i].name);
9761
9762 feaProblem->feaDesignConstraint[i].name = (char *) EG_alloc(((strlen(designConstraintTuple[i].name)) + 1)*sizeof(char));
9763 if (feaProblem->feaDesignConstraint[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
9764
9765 memcpy(feaProblem->feaDesignConstraint[i].name, designConstraintTuple[i].name, strlen(designConstraintTuple[i].name)*sizeof(char));
9766 feaProblem->feaDesignConstraint[i].name[strlen(designConstraintTuple[i].name)] = '\0';
9767
9768 feaProblem->feaDesignConstraint[i].designConstraintID = i + 1;
9769
9770 // Do we have a json string?
9771 if (strncmp(designConstraintTuple[i].value, "{", 1) == 0) {
9772 //printf("JSON String - %s\n", designConstraintTuple[i].value);
9773
9774 /*! \page feaDesignConstraint
9775 * \section jsonStringDesignConstraint JSON String Dictionary
9776 *
9777 * If "Value" is JSON string dictionary
9778 * \if (NASTRAN || ASTROS)
9779 * (eg. "Value" = {"groupName": "plate", "upperBound": 10.0})
9780 * \endif
9781 * the following keywords ( = default values) may be used:
9782 *
9783 * \if (NASTRAN || ASTROS)
9784 * <ul>
9785 * <li> <B>groupName = "(no default)"</B> </li> <br>
9786 * Single or list of <c>capsGroup</c> name(s)
9787 * to the design variable (e.g. "Name1" or ["Name1","Name2",...].The property (see \ref feaProperty) also
9788 * assigned to the same <c>capsGroup</c> will be automatically related to this constraint entry.
9789 * </ul>
9790 * \endif
9791 *
9792 */
9793
9794 // Get material/properties that the design constraint should be applied to
9795 keyWord = "groupName";
9796 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9797 if (status == CAPS_SUCCESS0) {
9798
9799 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
9800 if (keyValue != NULL((void*)0)) {
9801 EG_free(keyValue);
9802 keyValue = NULL((void*)0);
9803 }
9804
9805 if (status != CAPS_SUCCESS0) return status;
9806
9807 feaProblem->feaDesignConstraint[i].numPropertyID = 0;
9808 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
9809
9810 for (attrIndex = 0; attrIndex < feaProblem->numProperty; attrIndex++) {
9811
9812 if (strcasecmp(feaProblem->feaProperty[attrIndex].name, groupName[groupIndex]) == 0) {
9813
9814 feaProblem->feaDesignConstraint[i].numPropertyID += 1;
9815
9816 if (feaProblem->feaDesignConstraint[i].numPropertyID == 1) {
9817
9818 feaProblem->feaDesignConstraint[i].propertySetID = (int *) EG_alloc(feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9819 feaProblem->feaDesignConstraint[i].propertySetType = (int *) EG_alloc(feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9820
9821 } else {
9822
9823 feaProblem->feaDesignConstraint[i].propertySetID = (int *) EG_reall(feaProblem->feaDesignConstraint[i].propertySetID,
9824 feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9825 feaProblem->feaDesignConstraint[i].propertySetType = (int *) EG_reall(feaProblem->feaDesignConstraint[i].propertySetType,
9826 feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9827
9828 }
9829
9830 if (feaProblem->feaDesignConstraint[i].propertySetID == NULL((void*)0) ||
9831 feaProblem->feaDesignConstraint[i].propertySetType == NULL((void*)0) ) {
9832
9833 status = string_freeArray(numGroupName, &groupName);
9834 if (status != CAPS_SUCCESS0) return status;
9835 groupName = NULL((void*)0);
9836 return EGADS_MALLOC-4;
9837 }
9838
9839 feaProblem->feaDesignConstraint[i].propertySetID[feaProblem->feaDesignConstraint[i].numPropertyID-1] = feaProblem->feaProperty[attrIndex].propertyID;
9840 feaProblem->feaDesignConstraint[i].propertySetType[feaProblem->feaDesignConstraint[i].numPropertyID-1] = feaProblem->feaProperty[attrIndex].propertyType;
9841
9842 break;
9843 }
9844 }
9845
9846 if (feaProblem->feaDesignConstraint[i].numPropertyID != groupIndex+1) {
9847
9848 printf("\tWarning: DesignConstraint property name, %s, not found in feaProperty structure\n", groupName[groupIndex]);
9849
9850 }
9851 }
9852
9853 status = string_freeArray(numGroupName, &groupName);
9854 if (status != CAPS_SUCCESS0) return status;
9855 groupName = NULL((void*)0);
9856 }
9857
9858 //Fill up designConstraint properties
9859 /*! \page feaDesignConstraint
9860 *
9861 * \if (NASTRAN || ASTROS)
9862 * <ul>
9863 * <li> <B> constraintType = "Property" </B> </li> <br>
9864 * The type of design constraint. Options: "Property", "Flutter"
9865 * </ul>
9866 * \endif
9867 */
9868 keyWord = "constraintType";
9869 status = json_getString(
9870 designConstraintTuple[i].value, keyWord, &keyValue);
9871 if (status == CAPS_SUCCESS0) {
9872 AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 9872, __func__, 1, "%s == NULL!", "keyValue"
); goto cleanup; } }
;
9873 if (strcasecmp(keyValue, "Property") == 0)
9874 feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon;
9875 else if (strcasecmp(keyValue, "Flutter") == 0)
9876 feaProblem->feaDesignConstraint[i].designConstraintType = FlutterDesignCon;
9877 else {
9878 PRINT_WARNING("Unknown constraintType %s... defaulting to Property.", keyValue)fprintf(stderr, "[ WARNING ] " "Unknown constraintType %s... defaulting to Property."
"\n", keyValue);
;
9879 feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon;
9880 }
9881 }
9882 else {
9883 feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon;
9884 }
9885
9886 if (keyValue != NULL((void*)0)) EG_free(keyValue);
9887 keyValue = NULL((void*)0);
9888
9889 /*! \page feaDesignConstraint
9890 *
9891 * \if (NASTRAN || ASTROS)
9892 * <ul>
9893 * <li> <B>lowerBound = 0.0</B> </li> <br>
9894 * Lower bound for the design constraint.
9895 * </ul>
9896 * \endif
9897 *
9898 */
9899 keyWord = "lowerBound";
9900 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9901 if (status == CAPS_SUCCESS0) {
9902
9903 status = string_toDouble(keyValue, &feaProblem->feaDesignConstraint[i].lowerBound);
9904 if (keyValue != NULL((void*)0)) {
9905 EG_free(keyValue);
9906 keyValue = NULL((void*)0);
9907 }
9908 if (status != CAPS_SUCCESS0) return status;
9909 }
9910
9911 /*! \page feaDesignConstraint
9912 *
9913 * \if (NASTRAN || ASTROS)
9914 * <ul>
9915 * <li> <B>upperBound = 0.0</B> </li> <br>
9916 * Upper bound for the design constraint.
9917 * </ul>
9918 * \endif
9919 *
9920 */
9921 keyWord = "upperBound";
9922 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9923 if (status == CAPS_SUCCESS0) {
9924
9925 status = string_toDouble(keyValue, &feaProblem->feaDesignConstraint[i].upperBound);
9926 if (keyValue != NULL((void*)0)) {
9927 EG_free(keyValue);
9928 keyValue = NULL((void*)0);
9929 }
9930 if (status != CAPS_SUCCESS0) return status;
9931 }
9932
9933 /*! \page feaDesignConstraint
9934 *
9935 * \if (NASTRAN || ASTROS)
9936 * <ul>
9937 * <li> <B>responseType = "(no default)"</B> </li> <br>
9938 * Response type options for DRESP1 Entry (see Nastran manual).
9939 * - Implemented Options
9940 * -# <c>STRESS</c>, for <c>propertyType = "Rod" or "Shell"</c> (see \ref feaProperty)
9941 * -# <c>CFAILURE</c>, for <c>propertyType = "Composite"</c> (see \ref feaProperty)
9942 * </ul>
9943 * \endif
9944 *
9945 */
9946 keyWord = "responseType";
9947 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9948 if (status == CAPS_SUCCESS0) {
9949
9950 tempString = string_removeQuotation(keyValue);
9951 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 9951, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
9952
9953 feaProblem->feaDesignConstraint[i].responseType = EG_alloc((strlen(tempString) + 1)*sizeof(char));
9954 if(feaProblem->feaDesignConstraint[i].responseType == NULL((void*)0)) {
9955 if (tempString != NULL((void*)0)) EG_free(tempString);
9956
9957 return EGADS_MALLOC-4;
9958 }
9959
9960 memcpy(feaProblem->feaDesignConstraint[i].responseType, tempString, strlen(tempString)*sizeof(char));
9961 feaProblem->feaDesignConstraint[i].responseType[strlen(tempString)] = '\0';
9962
9963 if (keyValue != NULL((void*)0)) {
9964 EG_free(keyValue);
9965 keyValue = NULL((void*)0);
9966 }
9967
9968 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
9969 }
9970
9971 /*! \page feaDesignConstraint
9972 *
9973 * \if (NASTRAN || ASTROS)
9974 * <ul>
9975 * <li> <B>fieldName = "(no default)"</B> </li> <br>
9976 * For constraints, this field is only used currently when applying constraints to composites. This field is used to identify
9977 * the specific lamina in a stacking sequence that a constraint is being applied too. Note if the user has design variables
9978 * for both THEATA1 and T1 it is likely that only a single constraint on the first lamina is required. For this reason, the user
9979 * can simply enter LAMINA1 in addition to the possible entries defined in the \ref feaDesignVariable section.
9980 * Additionally, the <c>fieldPosition</c> integer entry below can be used. In this case <c>"LAMINA1" = 1</c>.
9981 *
9982 * * -# <b> Property Types</b> (see \ref feaProperty)
9983 * - <c><b> PCOMP</b> </c> <c>propertyType = "Composite"</c>
9984 * - "T1", "THETA1", "T2", "THETA2", ... "Ti", "THETAi"
9985 * - "LAMINA1", "LAMINA2", ... "LAMINAi"
9986 *
9987 * </ul>
9988 * \endif
9989 */
9990
9991 keyWord = "fieldName";
9992 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9993 if (status == CAPS_SUCCESS0) {
9994
9995 tempString = string_removeQuotation(keyValue);
9996 AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 9996, __func__, 1, "%s == NULL!", "tempString"
); goto cleanup; } }
;
9997
9998 feaProblem->feaDesignConstraint[i].fieldName = EG_alloc((strlen(tempString) + 1)*sizeof(char));
9999 if(feaProblem->feaDesignConstraint[i].fieldName == NULL((void*)0)) {
10000 if (tempString != NULL((void*)0)) EG_free(tempString);
10001
10002 return EGADS_MALLOC-4;
10003 }
10004
10005 memcpy(feaProblem->feaDesignConstraint[i].fieldName, tempString, strlen(tempString)*sizeof(char));
10006 feaProblem->feaDesignConstraint[i].fieldName[strlen(tempString)] = '\0';
10007
10008 if (keyValue != NULL((void*)0)) {
10009 EG_free(keyValue);
10010 keyValue = NULL((void*)0);
10011 }
10012
10013 if (tempString != NULL((void*)0)) {
10014 EG_free(tempString);
10015 tempString = NULL((void*)0);
10016 }
10017 }
10018
10019 /*! \page feaDesignConstraint
10020 *
10021 * \if (NASTRAN || ASTROS)
10022 * <ul>
10023 * <li> <B>fieldPosition = 0</B> </li> <br>
10024 * This input is ignored if not defined. The user may use this field instead of the <c>fieldName</c> input defined above to
10025 * identify a specific lamina in a composite stacking sequence where a constraint is applied. Please read the <c>fieldName</c>
10026 * information above for more information.
10027 * </ul>
10028 * \endif
10029 */
10030
10031 keyWord = "fieldPosition";
10032 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
10033 if (status == CAPS_SUCCESS0) {
10034
10035 status = string_toInteger(keyValue, &feaProblem->feaDesignConstraint[i].fieldPosition);
10036 if (keyValue != NULL((void*)0)) {
10037 EG_free(keyValue);
10038 keyValue = NULL((void*)0);
10039 }
10040 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 10040
, __func__, 0); goto cleanup; }
;
10041 }
10042
10043 /*! \page feaDesignConstraint
10044 *
10045 * \if ASTROS
10046 * <ul>
10047 * <li> <B>velocityType = "TRUE" </B> </li> <br>
10048 * The nature of the velocity values defined with "velocity" keyword. Can be either "TRUE" for true velocity
10049 * or "EQUIV" for equivalent air speed.
10050 * </ul>
10051 * \endif
10052 */
10053 keyWord = "velocityType";
10054 status = json_getString(
10055 designConstraintTuple[i].value, keyWord,
10056 &feaProblem->feaDesignConstraint[i].velocityType);
10057 if (status != CAPS_SUCCESS0) {
10058 feaProblem->feaDesignConstraint[i].velocityType = EG_strdup("TRUE");
10059 }
10060
10061 /*! \page feaDesignConstraint
10062 *
10063 * \if ASTROS
10064 * <ul>
10065 * <li> <B>scalingFactor = 0.10 </B> </li> <br>
10066 * The constraint scaling factor.
10067 * </ul>
10068 * \endif
10069 */
10070 keyWord = "scalingFactor";
10071 status = json_getDouble(
10072 designConstraintTuple[i].value, keyWord,
10073 &feaProblem->feaDesignConstraint[i].scalingFactor);
10074 if (status != CAPS_SUCCESS0) {
10075 feaProblem->feaDesignConstraint[i].scalingFactor = 0.10;
10076 }
10077
10078 /*! \page feaDesignConstraint
10079 *
10080 * \if ASTROS
10081 * <ul>
10082 * <li> <B>velocity = (No Default) </B> </li> <br>
10083 * The velocity values for flutter constraint.
10084 * Must be an array with equal length to defined "damping" values.
10085 * </ul>
10086 * \endif
10087 */
10088 keyWord = "velocity";
10089 status = json_getDoubleDynamicArray(
10090 designConstraintTuple[i].value, keyWord,
10091 &feaProblem->feaDesignConstraint[i].numVelocity,
10092 &feaProblem->feaDesignConstraint[i].velocity);
10093 if (status != CAPS_SUCCESS0) {
10094 // only required if constraintType == FlutterCon
10095 }
10096
10097 /*! \page feaDesignConstraint
10098 *
10099 * \if ASTROS
10100 * <ul>
10101 * <li> <B>damping = (No Default) </B> </li> <br>
10102 * The damping values for flutter constraint.
10103 * Must be an array with equal length to defined "velocity" values.
10104 * </ul>
10105 * \endif
10106 */
10107 keyWord = "damping";
10108 status = json_getDoubleDynamicArray(
10109 designConstraintTuple[i].value, keyWord,
10110 &feaProblem->feaDesignConstraint[i].numDamping,
10111 &feaProblem->feaDesignConstraint[i].damping);
10112 if (status != CAPS_SUCCESS0) {
10113 // only required if constraintType == FlutterCon
10114 }
10115
10116 } else {
10117
10118 printf("\tError: Design_Constraint tuple value is expected to be a JSON string\n");
10119 return CAPS_BADVALUE-311;
10120 // CALL designConstraint look up
10121
10122 }
10123 }
10124
10125 printf("Done getting FEA design constraints\n");
10126 status = CAPS_SUCCESS0;
10127cleanup:
10128 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
10129 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
10130 return status;
10131}
10132
10133// Get the design constraints from a capsTuple
10134int fea_getOptimizationControl(char *optimizationControlInput,
10135 feaProblemStruct *feaProblem) {
10136
10137 /*! \page feaOptimizationControl FEA Optimization Control
10138 * Structure for the optimization control dictionary = `Value'.
10139 * The "Value" must be a JSON String dictionary (see Section \ref jsonStringDesignConstraint).
10140 */
10141
10142 int status; //Function return
10143
10144 char *keyValue = NULL((void*)0);
10145 char *keyWord = NULL((void*)0);
10146
10147 // Destroy our optimization control structures coming in if aren't 0 and NULL already
10148 status = destroy_feaOptimzationControlStruct(&feaProblem->feaOptimizationControl);
10149 if (status != CAPS_SUCCESS0) return status;
10150
10151 printf("\nGetting FEA optimization control.......\n");
10152
10153 status = initiate_feaOptimizationControlStruct(&feaProblem->feaOptimizationControl);
10154 if (status != CAPS_SUCCESS0) return status;
10155
10156 if (optimizationControlInput == NULL((void*)0)) {
10157 optimizationControlInput = "{}";
10158 }
10159
10160 // Do we have a json string?
10161 if (strncmp(optimizationControlInput, "{", 1) == 0) {
10162
10163 /*! \page feaOptimizationControl
10164 *
10165 * \if NASTRAN
10166 * <ul>
10167 * <li> <B>fullyStressedDesign = 0</B> </li> <br>
10168 * Number of iterations with fully stressed design.
10169 * </ul>
10170 * \endif
10171 *
10172 */
10173 keyWord = "fullyStressedDesign";
10174 status = json_getInteger(
10175 optimizationControlInput, keyWord,
10176 &feaProblem->feaOptimizationControl.fullyStressedDesign);
10177
10178 // Set default value if value is not in JSON
10179 if (status != CAPS_SUCCESS0) {
10180 feaProblem->feaOptimizationControl.fullyStressedDesign = 0;
10181 }
10182
10183 /*! \page feaOptimizationControl
10184 *
10185 * \if NASTRAN
10186 * <ul>
10187 * <li> <B>mathProgramming = 30</B> </li> <br>
10188 * Number of iterations for math programming methods.
10189 * </ul>
10190 * \endif
10191 *
10192 */
10193 keyWord = "mathProgramming";
10194 status = json_getInteger(
10195 optimizationControlInput, keyWord,
10196 &feaProblem->feaOptimizationControl.mathProgramming);
10197
10198 // Set default value if value is not in JSON
10199 if (status != CAPS_SUCCESS0) {
10200 feaProblem->feaOptimizationControl.mathProgramming = 30;
10201 }
10202
10203 /*! \page feaOptimizationControl
10204 *
10205 * \if NASTRAN
10206 * <ul>
10207 * <li> <B>maxIter = 30</B> </li> <br>
10208 * Maximum number of optimization iterations.
10209 * </ul>
10210 * \endif
10211 *
10212 */
10213 keyWord = "maxIter";
10214 status = json_getInteger(
10215 optimizationControlInput, keyWord,
10216 &feaProblem->feaOptimizationControl.maxIter);
10217
10218 // Set default value if value is not in JSON
10219 if (status != CAPS_SUCCESS0) {
10220 feaProblem->feaOptimizationControl.maxIter = 30;
10221 }
10222
10223 /*! \page feaOptimizationControl
10224 *
10225 * \if NASTRAN
10226 * <ul>
10227 * <li> <B>constraintRetention = 1.5</B> </li> <br>
10228 * Constraint retention factor.
10229 * Will be at least 1.5 times the number of design variables
10230 * </ul>
10231 * \endif
10232 *
10233 */
10234 keyWord = "constraintRetention";
10235 status = json_getDouble(
10236 optimizationControlInput, keyWord,
10237 &feaProblem->feaOptimizationControl.constraintRetention);
10238
10239 // Set default value if value is not in JSON
10240 if (status != CAPS_SUCCESS0) {
10241 feaProblem->feaOptimizationControl.constraintRetention = 1.5;
10242 }
10243
10244 /*! \page feaOptimizationControl
10245 *
10246 * \if NASTRAN
10247 * <ul>
10248 * <li> <B>eps = 1.0</B> </li> <br>
10249 * Constraint retention parameter in which all constraints having a
10250 * value greater than "eps" will be considered active.
10251 *
10252 * </ul>
10253 * \endif
10254 *
10255 */
10256 keyWord = "eps";
10257 status = json_getDouble(
10258 optimizationControlInput, keyWord,
10259 &feaProblem->feaOptimizationControl.eps);
10260
10261 // Set default value if value is not in JSON
10262 if (status != CAPS_SUCCESS0) {
10263 feaProblem->feaOptimizationControl.eps = 1.0;
10264 }
10265
10266 /*! \page feaOptimizationControl
10267 *
10268 * \if NASTRAN
10269 * <ul>
10270 * <li> <B>moveLimit = 1.0</B> </li> <br>
10271 * Move limit bound.
10272 * </ul>
10273 * \endif
10274 *
10275 */
10276 keyWord = "moveLimit";
10277 status = json_getDouble(
10278 optimizationControlInput, keyWord,
10279 &feaProblem->feaOptimizationControl.moveLimit);
10280
10281 // Set default value if value is not in JSON
10282 if (status != CAPS_SUCCESS0) {
10283 feaProblem->feaOptimizationControl.moveLimit = 1.5;
10284 }
10285
10286 } else {
10287
10288 printf("\tError: OptimizationControl tuple value is expected to be a JSON string\n");
10289 return CAPS_BADVALUE-311;
10290
10291 }
10292
10293 if (keyValue != NULL((void*)0)) {
10294 EG_free(keyValue);
10295 keyValue = NULL((void*)0);
10296 }
10297
10298 printf("Done getting FEA Optimization Control\n");
10299 return CAPS_SUCCESS0;
10300}
10301
10302// Get the coordinate system information from the bodies and an attribute map (of CoordSystem)
10303int fea_getCoordSystem(int numBody,
10304 ego bodies[],
10305 mapAttrToIndexStruct coordSystemMap,
10306 int *numCoordSystem,
10307 feaCoordSystemStruct *feaCoordSystem[]) {
10308
10309 int status; // Function return
10310
10311 int i, body, face, edge, node; // Indexing
10312
10313 int numFace = 0, numEdge = 0, numNode = 0; // Number of egos
10314 ego *faces = NULL((void*)0), *edges = NULL((void*)0), *nodes = NULL((void*)0); // Geometry
10315
10316 int atype, alen; // EGADS return variables
10317 const int *ints;
10318 const double *reals;
10319 const char *string;
10320
10321 int found = (int) false0;
10322
10323 // Destroy our CoordSystem structures coming in if aren't 0 and NULL already
10324 if (*feaCoordSystem != NULL((void*)0)) {
10325 for (i = 0; i < *numCoordSystem; i++) {
10326 status = destroy_feaCoordSystemStruct(&(*feaCoordSystem)[i]);
10327 if (status != CAPS_SUCCESS0) return status;
10328 }
10329 }
10330 if (*feaCoordSystem != NULL((void*)0)) EG_free(*feaCoordSystem);
10331 *feaCoordSystem = NULL((void*)0);
10332 *numCoordSystem = 0;
10333
10334 printf("\nGetting FEA coordinate systems.......\n");
10335
10336 *numCoordSystem = coordSystemMap.numAttribute;
10337 printf("\tNumber of coordinate systems - %d\n", *numCoordSystem);
10338
10339 if (*numCoordSystem > 0) {
10340 *feaCoordSystem = (feaCoordSystemStruct *) EG_alloc((*numCoordSystem)*sizeof(feaCoordSystemStruct));
10341 if (*feaCoordSystem == NULL((void*)0)) return EGADS_MALLOC-4;
10342
10343 } else {
10344 printf("\tNo coordinate systems found - defaulting to global\n");
10345 return CAPS_SUCCESS0;
10346 }
10347
10348 for (i = 0; i < *numCoordSystem; i++) {
10349 status = initiate_feaCoordSystemStruct(&(*feaCoordSystem)[i]);
10350 if (status != CAPS_SUCCESS0) return status;
10351 }
10352
10353 for (i = 0; i < *numCoordSystem; i++) {
10354
10355 if (faces != NULL((void*)0)) EG_free(faces);
10356 if (edges != NULL((void*)0)) EG_free(edges);
10357 if (nodes != NULL((void*)0)) EG_free(nodes);
10358
10359 faces = NULL((void*)0);
10360 edges = NULL((void*)0);
10361 nodes = NULL((void*)0);
10362
10363 printf("\tCoordinate system name - %s\n", coordSystemMap.attributeName[i]);
10364
10365 (*feaCoordSystem)[i].name = EG_strdup(coordSystemMap.attributeName[i]);
10366 if ((*feaCoordSystem)[i].name == NULL((void*)0)) { status = EGADS_MALLOC-4; goto cleanup; }
10367
10368 (*feaCoordSystem)[i].coordSystemID = coordSystemMap.attributeIndex[i];
10369
10370 (*feaCoordSystem)[i].refCoordSystemID = 0;
10371
10372 (*feaCoordSystem)[i].coordSystemType = RectangularCoordSystem;
10373
10374 found = (int) false0;
10375
10376 // Search through bodies
10377 for (body = 0; body < numBody; body++) {
10378
10379 // Look at the body level
10380 status = EG_attributeRet(bodies[body], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10381 if (status != EGADS_SUCCESS0 &&
10382 status != EGADS_NOTFOUND-1) goto cleanup;
10383
10384 if (atype == ATTRCSYS12) {
10385
10386 // Save the origin
10387 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10388 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10389 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10390
10391 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10392 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10393 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10394
10395 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10396 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10397 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10398
10399 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10400 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10401 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10402
10403 found = (int) true1;
10404 }
10405
10406 if (found == (int) true1) break;
10407
10408 // Determine the number of faces, edges, and nodes
10409 status = EG_getBodyTopos(bodies[body], NULL((void*)0), FACE23, &numFace, &faces);
10410 if (status != EGADS_SUCCESS0) goto cleanup;
10411
10412 status = EG_getBodyTopos(bodies[body], NULL((void*)0), EDGE21, &numEdge, &edges);
10413 if (status != EGADS_SUCCESS0) goto cleanup;
10414
10415 status = EG_getBodyTopos(bodies[body], NULL((void*)0), NODE20, &numNode, &nodes);
10416 if (status != EGADS_SUCCESS0) goto cleanup;
10417
10418 // Loop through faces
10419 for (face = 0; face < numFace; face++) {
10420
10421 status = EG_attributeRet(faces[face], (const char *) (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10422
10423 if (status == EGADS_NOTFOUND-1) continue;
10424 if (status != EGADS_SUCCESS0) goto cleanup;
10425
10426 if (atype == ATTRCSYS12) {
10427
10428 // Save the origin
10429 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10430 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10431 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10432
10433 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10434 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10435 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10436
10437 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10438 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10439 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10440
10441 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10442 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10443 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10444
10445 found = (int) true1;
10446
10447 break;
10448 }
10449 } // End face loop
10450
10451 if (found == (int) true1) break;
10452
10453 // Loop through edges
10454 for (edge = 0; edge < numEdge; edge++) {
10455
10456 status = EG_attributeRet(edges[edge], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10457
10458 if (status == EGADS_NOTFOUND-1) continue;
10459 if (status != EGADS_SUCCESS0) goto cleanup;
10460
10461 if (atype == ATTRCSYS12) {
10462
10463 // Save the origin
10464 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10465 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10466 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10467
10468 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10469 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10470 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10471
10472 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10473 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10474 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10475
10476 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10477 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10478 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10479
10480 found = (int) true1;
10481
10482 break;
10483 }
10484
10485 } // End edge loop
10486
10487 if (found == (int) true1) break;
10488
10489 // Loop through nodes
10490 for (node = 0; node < numNode; node++) {
10491
10492 status = EG_attributeRet(nodes[node], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10493
10494 if (status == EGADS_NOTFOUND-1) continue;
10495 if (status != EGADS_SUCCESS0) goto cleanup;
10496
10497 if (atype == ATTRCSYS12) {
10498
10499 // Save the origin
10500 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10501 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10502 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10503
10504 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10505 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10506 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10507
10508 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10509 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10510 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10511
10512 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10513 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10514 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10515
10516 found = (int) true1;
10517
10518 break;
10519 }
10520 } // End node loop
10521
10522 EG_free(faces); faces = NULL((void*)0);
10523 EG_free(edges); edges = NULL((void*)0);
10524 EG_free(nodes); nodes = NULL((void*)0);
10525
10526 if (found == (int) true1) break;
10527
10528 } // End body loop
10529 }
10530
10531 status = CAPS_SUCCESS0;
10532
10533 cleanup:
10534
10535 if (status != CAPS_SUCCESS0) printf("\tError in fea_getCoordSystem = %d\n", status);
10536
10537 EG_free(faces);
10538 EG_free(edges);
10539 EG_free(nodes);
10540
10541 return status;
10542}
10543
10544// Get the design equations from a capsTuple
10545int fea_getDesignEquation(int numEquationTuple,
10546 capsTuple equationTuple[],
10547 feaProblemStruct *feaProblem) {
10548
10549 /*! \page feaDesignEquation FEA Design Equations
10550 * Structure for the design equation tuple = ("DesignEquation Name", ["Value1", ... , "ValueN"]).
10551 * "DesignEquation Name" defines the reference name for the design equation being specified.
10552 * This string will be used in the FEA input directly. The values "Value1", ... , "ValueN" are a
10553 * list of strings containing the equation defintions.
10554 * (see Section \ref tupleValueDesignEquation).
10555 *
10556 */
10557 int i, status;
10558
10559 feaDesignEquationStruct *equation;
10560
10561 // Ensure we are starting with no equations
10562 if (feaProblem->feaEquation != NULL((void*)0)) {
10563 for (i = 0; i < feaProblem->numEquation; i++) {
10564 status = destroy_feaDesignEquationStruct(&feaProblem->feaEquation[i]);
10565 if (status != CAPS_SUCCESS0) return status;
10566 }
10567 EG_free(feaProblem->feaEquation);
10568 }
10569 feaProblem->numEquation = 0;
10570 feaProblem->feaEquation = NULL((void*)0);
10571
10572 printf("\nGetting Equations.......\n");
10573
10574 feaProblem->numEquation = numEquationTuple;
10575 printf("\tNumber of Equations - %d\n", feaProblem->numEquation);
10576
10577 if (feaProblem->numEquation > 0) {
10578
10579 feaProblem->feaEquation = EG_alloc(
10580 feaProblem->numEquation * sizeof(feaDesignEquationStruct));
10581 if (feaProblem->feaEquation == NULL((void*)0)) {
10582 return EGADS_MALLOC-4;
10583 }
10584
10585 } else {
10586 printf("\tNumber of equations in Analysis tuple is %d\n",
10587 feaProblem->numEquation);
10588 return CAPS_NOTFOUND-303;
10589 }
10590
10591 // for each analysis equation tuple
10592 for (i = 0; i < feaProblem->numEquation; i++) {
10593
10594 printf("\tDesign_Equation name - %s\n", equationTuple[i].name);
10595
10596 equation = &feaProblem->feaEquation[i];
10597
10598 // initiate equation structure
10599 status = initiate_feaDesignEquationStruct(equation);
10600 if (status != CAPS_SUCCESS0) return status;
10601
10602 // set name
10603 equation->name = EG_strdup(equationTuple[i].name);
10604
10605 // set equation ID
10606 equation->equationID = i+1;
10607
10608 /*! \page feaDesignEquation
10609 * \section tupleValueDesignEquation List of equation strings
10610 *
10611 * Each design equation tuple value is a list of strings containing the equation definitions
10612 * \if NASTRAN
10613 * (eg. ["dispsum3(s1,s2,s3)=sum(s1,s2,s3)"]
10614 * \endif
10615 *
10616 */
10617 // set the equation array
10618 status = string_toStringDynamicArray(
10619 equationTuple[i].value,
10620 &equation->equationArraySize,
10621 &equation->equationArray);
10622
10623 if (status != CAPS_SUCCESS0) return status;
10624 }
10625
10626 return CAPS_SUCCESS0;
10627}
10628
10629// Get the design table constants from a capsTuple
10630int fea_getDesignTable(int numConstantTuple,
10631 capsTuple constantTuple[],
10632 feaProblemStruct *feaProblem) {
10633
10634
10635 /*! \page feaDesignTable FEA Table Constants
10636 * Structure for the table constant tuple = ("TableConstant Name", "Value").
10637 * "TableConstant Name" defines the reference name for the table constant being specified.
10638 * This string will be used in the FEA input directly. The "Value" is the value of the
10639 * table constant.
10640 * \if NASTRAN
10641 * In Nastran the TableConstant Name will be the LABLi used in the DTABLE input.
10642 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
10643 *
10644 * - <c>DTABLE LABL1 VALU1 LABL2 VALU2 LABL3 VALU3 -etc- </c>
10645 * \endif
10646 *
10647 */
10648 int i, status;
10649
10650 feaDesignTableStruct *table = &feaProblem->feaDesignTable;
10651
10652 // Ensure we are starting with no constants
10653 status = destroy_feaDesignTableStruct(table);
10654 if (status != CAPS_SUCCESS0) return status;
10655
10656 printf("\nGetting Design Table Constants.......\n");
10657
10658 table->numConstant = numConstantTuple;
10659 printf("\tNumber of Design Table Constants - %d\n", table->numConstant);
10660
10661 if (table->numConstant > 0) {
10662
10663 table->constantLabel = EG_alloc(table->numConstant * sizeof(char *));
10664 if (table->constantLabel == NULL((void*)0)) {
10665 return EGADS_MALLOC-4;
10666 }
10667
10668 table->constantValue = EG_alloc(table->numConstant * sizeof(double));
10669 if (table->constantValue == NULL((void*)0)) {
10670 return EGADS_MALLOC-4;
10671 }
10672
10673 } else {
10674 printf("\tNumber of design table constants in Analysis tuple is %d\n",
10675 table->numConstant);
10676 return CAPS_NOTFOUND-303;
10677 }
10678
10679 // for each analysis table constant tuple
10680 for (i = 0; i < table->numConstant; i++) {
10681
10682 printf("\tDesign_Table - %s: %s\n",
10683 constantTuple[i].name, constantTuple[i].value);
10684
10685 // set constant label
10686 // TODO: ensure label <= 8 chars
10687 table->constantLabel[i] = EG_strdup(constantTuple[i].name);
10688
10689 // set constant value
10690 status = string_toDouble(constantTuple[i].value, &table->constantValue[i]);
10691 if (status != CAPS_SUCCESS0) return status;
10692 }
10693
10694 return CAPS_SUCCESS0;
10695}
10696
10697// Function used by fea_getDesignResponse to determine which nodes are in response group
10698static int _matchResponseNode(meshNodeStruct *node, void *responseIndex) {
10699
10700 feaMeshDataStruct *feaData;
10701
10702 if (node->analysisType == MeshStructure) {
10703
10704 feaData = (feaMeshDataStruct *) node->analysisData;
10705
10706 if (feaData->responseIndex == *((int *) responseIndex)) {
10707 return (int) true1;
10708 }
10709 }
10710 return (int) false0;
10711}
10712
10713int fea_getDesignResponse(/*@unused@*/ void *aimInfo,
10714 int numDesignResponseTuple,
10715 capsTuple designResponseTuple[],
10716 mapAttrToIndexStruct *responseMap,
10717 feaProblemStruct *feaProblem) {
10718
10719 /*! \page feaDesignResponse FEA Design Responses
10720 * Structure for the design response tuple = ("DesignResponse Name", "Value").
10721 * "DesignResponse Name" defines the reference name for the design response being specified.
10722 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
10723 * (see Section \ref jsonStringDesignResponse).
10724 * \if NASTRAN
10725 * In Nastran the DesignResponse Name will be the LABEL used in the DRESP1 input.
10726 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
10727 *
10728 * - <c>DRESP1 ID LABEL RTYPE PTYPE REGION ATTA ATTB ATT1\n ATT2 -etc-</c>
10729 * \endif
10730 *
10731 */
10732 int i, status;
10733
10734 int attrIndex;
10735
10736 char *keyword;
10737 char *groupName = NULL((void*)0);
10738
10739 int numNode;
10740 meshNodeStruct **nodeSet = NULL((void*)0);
10741
10742 feaDesignResponseStruct *response;
10743
10744 // Ensure we are starting with no design responses
10745 if (feaProblem->feaDesignResponse != NULL((void*)0)) {
10746 for (i = 0; i < feaProblem->numDesignResponse; i++) {
10747 status = destroy_feaDesignResponseStruct(&feaProblem->feaDesignResponse[i]);
10748 if (status != CAPS_SUCCESS0) return status;
10749 }
10750 EG_free(feaProblem->feaDesignResponse);
10751 }
10752 feaProblem->numDesignResponse = 0;
10753 feaProblem->feaDesignResponse = NULL((void*)0);
10754
10755 printf("\nGetting Design Responses.......\n");
10756
10757 feaProblem->numDesignResponse = numDesignResponseTuple;
10758 printf("\tNumber of Design Responses - %d\n", feaProblem->numDesignResponse);
10759
10760 if (feaProblem->numDesignResponse > 0) {
10761
10762 feaProblem->feaDesignResponse = EG_alloc(
10763 feaProblem->numDesignResponse * sizeof(feaDesignResponseStruct));
10764 if (feaProblem->feaDesignResponse == NULL((void*)0)) {
10765 return EGADS_MALLOC-4;
10766 }
10767
10768 } else {
10769 printf("\tNumber of design responses in Analysis tuple is %d\n",
10770 feaProblem->numDesignResponse);
10771 return CAPS_NOTFOUND-303;
10772 }
10773
10774 // for each analysis design response tuple
10775 for (i = 0; i < feaProblem->numDesignResponse; i++) {
10776
10777 printf("\tDesign_Response name - %s\n", designResponseTuple[i].name);
10778
10779 response = &feaProblem->feaDesignResponse[i];
10780
10781 // initiate design response structure
10782 status = initiate_feaDesignResponseStruct(response);
10783 if (status != CAPS_SUCCESS0) return status;
10784
10785 // set name
10786 response->name = EG_strdup(designResponseTuple[i].name);
10787
10788 // set response ID
10789 response->responseID = i+1;
10790
10791 /*! \page feaDesignResponse
10792 * \section jsonStringDesignResponse JSON String Dictionary
10793 *
10794 * If "Value" is JSON string dictionary
10795 * \if NASTRAN
10796 * (eg. "Value" = {"responseType": "DISP", groupName": "plate", "component": 3})
10797 * \endif
10798 * the following keywords ( = default values) may be used:
10799 *
10800 */
10801 // make sure design response tuple value is json string
10802 if (!json_isDict(designResponseTuple[i].value)) {
10803 AIM_ERROR(aimInfo,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10804, __func__
, "'Design_Response' tuple value must be a JSON dictionary");
}
10804 "'Design_Response' tuple value must be a JSON dictionary"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10804, __func__
, "'Design_Response' tuple value must be a JSON dictionary");
}
;
10805 return CAPS_BADVALUE-311;
10806 }
10807
10808 /*! \page feaDesignResponse
10809 *
10810 * \if NASTRAN
10811 * <ul>
10812 * <li> <B>responseType</B> </li> <br>
10813 * Type of design sensitivity response. For options,
10814 * see NASTRAN User Guide DRESP1 Design Sensitivity Response Attributes table.
10815 * </ul>
10816 * \endif
10817 */
10818 keyword = "responseType";
10819 status = json_getString(
10820 designResponseTuple[i].value, keyword, &response->responseType);
10821 if (status != CAPS_SUCCESS0) {
10822 AIM_ERROR(aimInfo, "Missing required entry \"responseType\" "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10823, __func__
, "Missing required entry \"responseType\" " "in 'Design_Response' tuple value"
); }
10823 "in 'Design_Response' tuple value"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10823, __func__
, "Missing required entry \"responseType\" " "in 'Design_Response' tuple value"
); }
;
10824 return status;
10825 }
10826
10827 // keyword = "propertyType";
10828 // status = json_getString(
10829 // designResponseTuple[i].value, keyword, &response->propertyType);
10830 // if (status != CAPS_SUCCESS) {
10831 // // optional
10832 // }
10833
10834 /*! \page feaDesignResponse
10835 *
10836 * \if NASTRAN
10837 * <ul>
10838 * <li> <B>component = "(no default)"</B> </li> <br>
10839 * Component flag.
10840 * </ul>
10841 * \endif
10842 */
10843 keyword = "component";
10844 status = json_getInteger(
10845 designResponseTuple[i].value, keyword, &response->component);
10846 if (status != CAPS_SUCCESS0) {
10847 // optional
10848 }
10849
10850 // TODO: temporary input
10851 keyword = "grid";
10852 status = json_getInteger(
10853 designResponseTuple[i].value, keyword, &response->gridID);
10854 if (status != CAPS_SUCCESS0) {
10855 // optional
10856 }
10857
10858 /*! \page feaDesignResponse
10859 *
10860 * \if NASTRAN
10861 * <ul>
10862 * <li> <B>groupName = "(no default)"</B> </li> <br>
10863 * Defines the reference <c>capsGroup</c> for the node being specified for the response.
10864 * </ul>
10865 * \endif
10866 */
10867 keyword = "groupName";
10868 status = json_getString(
10869 designResponseTuple[i].value, keyword, &groupName);
10870
10871 if (status == CAPS_SUCCESS0) {
10872 AIM_NOTNULL(groupName, aimInfo, status){ if (groupName == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 10872, __func__, 1, "%s == NULL!", "groupName"
); goto cleanup; } }
;
10873
10874 // Get the corresponding response index
10875 status = get_mapAttrToIndexIndex(responseMap, (const char *) groupName, &attrIndex);
10876
10877 if (status == CAPS_NOTFOUND-303) {
10878 printf("\tName %s not found in attribute map!!!!\n", groupName);
10879 continue;
10880 } else if (status != CAPS_SUCCESS0) return status;
10881
10882 status = mesh_findNodes(&feaProblem->feaMesh,
10883 _matchResponseNode, (void *) &attrIndex,
10884 &numNode, &nodeSet);
10885 if (status != CAPS_SUCCESS0) return status;
10886
10887 if (numNode == 0) {
10888 AIM_ERROR(aimInfo, "No node found for capsGroup %s", groupName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10888, __func__
, "No node found for capsGroup %s", groupName); }
;
10889 return CAPS_NOTFOUND-303;
10890 }
10891 else if (numNode > 1) { // TODO: would there ever be more than 1 node expected?
10892 PRINT_WARNING("More than 1 node found for capsGroup %s"fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s"
"... using first matching node." "\n", groupName);
10893 "... using first matching node.",fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s"
"... using first matching node." "\n", groupName);
10894 groupName)fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s"
"... using first matching node." "\n", groupName);
;
10895 }
10896
10897 response->gridID = nodeSet[0]->nodeID;
10898
10899 EG_free(nodeSet);
10900 nodeSet = NULL((void*)0);
10901
10902 }
10903 else {
10904 // required
10905 // AIM_ERROR(aimInfo, "Missing required entry \"groupName\" "
10906 // "in 'Design_Response' tuple value");
10907 // return status;
10908 }
10909
10910 if (groupName != NULL((void*)0)) {
10911 EG_free(groupName);
10912 groupName = NULL((void*)0);
10913 }
10914
10915 }
10916
10917 status = CAPS_SUCCESS0;
10918cleanup:
10919 return status;
10920}
10921
10922int fea_getDesignEquationResponse(int numDesignEquationResponseTuple,
10923 capsTuple designEquationResponseTuple[],
10924 feaProblemStruct *feaProblem) {
10925
10926 /*! \page feaDesignEquationResponse FEA Design Equation Responses
10927 * Structure for the design equation response tuple = ("DesignEquationResponse Name", "Value").
10928 * "DesignEquationResponse Name" defines the reference name for the design equation response being specified.
10929 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
10930 * (see Section \ref jsonStringDesignEquationResponse).
10931 * \if NASTRAN
10932 * In Nastran the DesignEquationResponse Name will be the LABEL used in the DRESP2 input.
10933 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
10934 *
10935 * - <c>DRESP2 ID LABEL EQID REGION ...</c>
10936 * \endif
10937 *
10938 */
10939 int i, status;
10940
10941 char *keyword;
10942
10943 feaDesignEquationResponseStruct *equationResponse;
10944
10945 // Ensure we are starting with no design equation responses
10946 if (feaProblem->feaEquationResponse != NULL((void*)0)) {
10947 for (i = 0; i < feaProblem->numEquationResponse; i++) {
10948 status = destroy_feaDesignEquationResponseStruct(&feaProblem->feaEquationResponse[i]);
10949 if (status != CAPS_SUCCESS0) return status;
10950 }
10951 EG_free(feaProblem->feaEquationResponse);
10952 }
10953 feaProblem->numEquationResponse = 0;
10954 feaProblem->feaEquationResponse = NULL((void*)0);
10955
10956 printf("\nGetting Design Equation Responses.......\n");
10957
10958 feaProblem->numEquationResponse = numDesignEquationResponseTuple;
10959 printf("\tNumber of Design Equation Responses - %d\n", feaProblem->numEquationResponse);
10960
10961 if (feaProblem->numEquationResponse > 0) {
10962
10963 feaProblem->feaEquationResponse = EG_alloc(
10964 feaProblem->numEquationResponse * sizeof(feaDesignEquationResponseStruct));
10965 if (feaProblem->feaEquationResponse == NULL((void*)0)) {
10966 return EGADS_MALLOC-4;
10967 }
10968
10969 } else {
10970 printf("\tNumber of design equation responses in Analysis tuple is %d\n",
10971 feaProblem->numEquationResponse);
10972 return CAPS_NOTFOUND-303;
10973 }
10974
10975 // for each analysis design equation response tuple
10976 for (i = 0; i < feaProblem->numEquationResponse; i++) {
10977
10978 printf("\tDesign_Equation_Response name - %s\n", designEquationResponseTuple[i].name);
10979
10980 equationResponse = &feaProblem->feaEquationResponse[i];
10981
10982 // initiate design response structure
10983 status = initiate_feaDesignEquationResponseStruct(equationResponse);
10984 if (status != CAPS_SUCCESS0) return status;
10985
10986 // set name
10987 equationResponse->name = EG_strdup(designEquationResponseTuple[i].name);
10988
10989 // set equation response ID
10990 equationResponse->equationResponseID = i+1;
10991
10992 /*! \page feaDesignEquationResponse
10993 * \section jsonStringDesignEquationResponse JSON String Dictionary
10994 *
10995 * If "Value" is JSON string dictionary
10996 * \if NASTRAN
10997 * (eg. "Value" = {"equation": "EQ1", "constant": ["PI", "YM", "L"]})
10998 * \endif
10999 * the following keywords ( = default values) may be used:
11000 *
11001 */
11002 // make sure design response tuple value is json string
11003 if (!json_isDict(designEquationResponseTuple[i].value)) {
11004 PRINT_ERROR(fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"'Design_Equation_Response' tuple value must be a JSON dictionary"
"\n" "--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11005, __func__);
11005 "'Design_Equation_Response' tuple value must be a JSON dictionary")fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"'Design_Equation_Response' tuple value must be a JSON dictionary"
"\n" "--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11005, __func__);
;
11006 return CAPS_BADVALUE-311;
11007 }
11008
11009 /*! \page feaDesignEquationResponse
11010 *
11011 * \if NASTRAN
11012 * <ul>
11013 * <li> <B>equation</B> </li> <br>
11014 * The name of the equation referenced by this equation response.
11015 * </ul>
11016 * \endif
11017 */
11018 keyword = "equation";
11019 status = json_getString(
11020 designEquationResponseTuple[i].value, keyword, &equationResponse->equationName);
11021 if (status != CAPS_SUCCESS0) {
11022 PRINT_ERROR("Missing required entry \"equation\" "fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"Missing required entry \"equation\" " "in 'Design_Equation_Response' tuple value"
"\n" "--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11023, __func__);
11023 "in 'Design_Equation_Response' tuple value")fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"Missing required entry \"equation\" " "in 'Design_Equation_Response' tuple value"
"\n" "--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11023, __func__);
;
11024 return status;
11025 }
11026
11027 /*! \page feaDesignEquationResponse
11028 *
11029 * \if NASTRAN
11030 * <ul>
11031 * <li> <B>variable = "(no default)"</B> </li> <br>
11032 * Single or list of names of design variable equation parameters.
11033 * </ul>
11034 * \endif
11035 */
11036 keyword = "variable";
11037 status = json_getStringDynamicArray(
11038 designEquationResponseTuple[i].value, keyword,
11039 &equationResponse->numDesignVariable, &equationResponse->designVariableNameSet);
11040 if (status != CAPS_SUCCESS0) {
11041 // optional
11042 }
11043
11044 /*! \page feaDesignEquationResponse
11045 *
11046 * \if NASTRAN
11047 * <ul>
11048 * <li> <B>constant = "(no default)"</B> </li> <br>
11049 * Single or list of names of table constant equation parameters.
11050 * </ul>
11051 * \endif
11052 */
11053 keyword = "constant";
11054 status = json_getStringDynamicArray(
11055 designEquationResponseTuple[i].value, keyword,
11056 &equationResponse->numConstant, &equationResponse->constantLabelSet);
11057 if (status != CAPS_SUCCESS0) {
11058 // optional
11059 }
11060
11061 /*! \page feaDesignEquationResponse
11062 *
11063 * \if NASTRAN
11064 * <ul>
11065 * <li> <B>response = "(no default)"</B> </li> <br>
11066 * Single or list of names of design response equation parameters.
11067 * </ul>
11068 * \endif
11069 */
11070 keyword = "response";
11071 status = json_getStringDynamicArray(
11072 designEquationResponseTuple[i].value, keyword,
11073 &equationResponse->numResponse, &equationResponse->responseNameSet);
11074 if (status != CAPS_SUCCESS0) {
11075 // optional
11076 }
11077
11078 /*! \page feaDesignEquationResponse
11079 *
11080 * \if NASTRAN
11081 * <ul>
11082 * <li> <B>equationResponse = "(no default)"</B> </li> <br>
11083 * Single or list of names of design equation response equation parameters.
11084 * </ul>
11085 * \endif
11086 */
11087 keyword = "equationResponse";
11088 status = json_getStringDynamicArray(
11089 designEquationResponseTuple[i].value, keyword,
11090 &equationResponse->numEquationResponse, &equationResponse->equationResponseNameSet);
11091 if (status != CAPS_SUCCESS0) {
11092 // optional
11093 }
11094 }
11095
11096 return CAPS_SUCCESS0;
11097}
11098
11099// Get the design optimization parameters from a capsTuple
11100int fea_getDesignOptParam(int numParamTuple,
11101 capsTuple paramTuple[],
11102 feaProblemStruct *feaProblem) {
11103
11104 /*! \page feaDesignOptParam FEA Design Optimization Parameters
11105 * Structure for the design optimization parameter tuple = ("DesignOptParam Name", "Value").
11106 * "DesignOptParam Name" defines the reference name for the design optimization parameter being specified.
11107 * This string will be used in the FEA input directly. The "Value" is the value of the
11108 * design optimization parameter.
11109 * \if NASTRAN
11110 * In Nastran the DesignOptParam Name will be the PARAMi used in the DOPTPRM input.
11111 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
11112 *
11113 * - <c>DOPTPRM PARAM1 VAL1 PARAM2 VAL2 PARAM3 VAL3 -etc- </c>
11114 * \endif
11115 *
11116 */
11117 int i, status;
11118
11119 int *paramInt = NULL((void*)0);
11120 double *paramDouble = NULL((void*)0);
11121
11122 feaDesignOptParamStruct *table = &feaProblem->feaDesignOptParam;
11123
11124 // Ensure we are starting with no params
11125 status = destroy_feaDesignOptParamStruct(table);
11126 if (status != CAPS_SUCCESS0) return status;
11127
11128 printf("\nGetting Design Optimization Parameters.......\n");
11129
11130 table->numParam = numParamTuple;
11131 printf("\tNumber of Design Optimization Parameters - %d\n", table->numParam);
11132
11133 if (table->numParam > 0) {
11134
11135 table->paramLabel = EG_alloc(table->numParam * sizeof(char *));
11136 if (table->paramLabel == NULL((void*)0)) {
11137 return EGADS_MALLOC-4;
11138 }
11139
11140 table->paramValue = EG_alloc(table->numParam * sizeof(void *));
11141 if (table->paramValue == NULL((void*)0)) {
11142 return EGADS_MALLOC-4;
11143 }
11144
11145 table->paramType = EG_alloc(table->numParam * sizeof(int));
11146 if (table->paramType == NULL((void*)0)) {
11147 return EGADS_MALLOC-4;
11148 }
11149
11150 } else {
11151 printf("\tNumber of design optimization parameters in Analysis tuple is %d\n",
11152 table->numParam);
11153 return CAPS_NOTFOUND-303;
11154 }
11155
11156 // for each analysis design optimization parameter tuple
11157 for (i = 0; i < table->numParam; i++) {
11158
11159 printf("\tDesign_Opt_Param - %s: %s\n",
11160 paramTuple[i].name, paramTuple[i].value);
11161
11162 // set param label
11163 // TODO: ensure label <= 8 chars
11164 table->paramLabel[i] = EG_strdup(paramTuple[i].name);
11165
11166 // set param value
11167
11168 // if param value is real
11169 if (strchr(paramTuple[i].value, '.')
11170 || strchr(paramTuple[i].value, 'e')
11171 || strchr(paramTuple[i].value, 'E')) {
11172
11173 paramDouble = EG_alloc(sizeof(double));
11174 if (paramDouble == NULL((void*)0)) return EGADS_MALLOC-4;
11175
11176 status = string_toDouble(paramTuple[i].value, paramDouble);
11177 if (status != CAPS_SUCCESS0) {
11178 EG_free(paramDouble);
11179 return status;
11180 }
11181
11182 table->paramType[i] = Double;
11183 table->paramValue[i] = (void*) paramDouble;
11184 }
11185 // else param is integer
11186 else {
11187
11188 paramInt = EG_alloc(sizeof(int));
11189 if (paramInt == NULL((void*)0)) return EGADS_MALLOC-4;
11190
11191 status = string_toInteger(paramTuple[i].value, paramInt);
11192 if (status != CAPS_SUCCESS0) {
11193 EG_free(paramInt);
11194 return status;
11195 }
11196
11197 table->paramType[i] = Integer;
11198 table->paramValue[i] = (void*) paramInt;
11199 }
11200 }
11201
11202 return CAPS_SUCCESS0;
11203}
11204
11205// Function used by fea_getAeroReference to determine which nodes are in reference group
11206static int _matchReferenceNode(meshNodeStruct *node, void *referenceIndex) {
11207
11208 feaMeshDataStruct *feaData;
11209
11210 if (node->analysisType == MeshStructure) {
11211
11212 feaData = (feaMeshDataStruct *) node->analysisData;
11213
11214 if (feaData->referenceIndex == *((int *) referenceIndex)) {
11215 return (int) true1;
11216 }
11217 }
11218 return (int) false0;
11219}
11220
11221// Get aero reference information from json dict
11222int fea_getAeroReference(void *aimInfo,
11223 char *aeroRefInput,
11224 mapAttrToIndexStruct *attrMap,
11225 feaProblemStruct *feaProblem) {
11226
11227 /*! \page feaAeroReference FEA Aerodynamic References
11228 * The aerodynamic reference input must be a JSON String dictionary
11229 * (see Section \ref jsonStringAeroReference).
11230 *
11231 */
11232 int status, attrIndex = 0;
11233
11234 char *keyword, *refNodeName = NULL((void*)0);
11235
11236 int numNodes;
11237 meshNodeStruct **nodes = NULL((void*)0);
11238
11239 printf("\nGetting Aero Reference Parameters.......\n");
11240
11241 /*! \page feaAeroReference
11242 * \section jsonStringAeroReference JSON String Dictionary
11243 *
11244 * The following keywords ( = default values) may be used:
11245 *
11246 */
11247 // make sure input is json string
11248 if (!json_isDict(aeroRefInput)) {
11249 PRINT_ERROR(fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"'Aero_Reference' value must be a JSON dictionary" "\n" "--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11250, __func__);
11250 "'Aero_Reference' value must be a JSON dictionary")fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"'Aero_Reference' value must be a JSON dictionary" "\n" "--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11250, __func__);
;
11251 return CAPS_BADVALUE-311;
11252 }
11253
11254 /*! \page feaAeroReference
11255 *
11256 * \if ASTROS
11257 * <ul>
11258 * <li> <B>referenceNode</B> </li> <br>
11259 * Defines the reference <c>capsReference</c> for the node to be used for stability derivative calculations.
11260 * </ul>
11261 * \endif
11262 */
11263 keyword = "referenceNode";
11264 status = json_getString(
11265 aeroRefInput, keyword, &refNodeName);
11266 if (status == CAPS_SUCCESS0) {
11267 AIM_NOTNULL(refNodeName, aimInfo, status){ if (refNodeName == ((void*)0)) { status = -307; aim_status(
aimInfo, status, "feaUtils.c", 11267, __func__, 1, "%s == NULL!"
, "refNodeName"); goto cleanup; } }
;
11268
11269 // find node with capsReference == refNodeName
11270
11271 status = get_mapAttrToIndexIndex(attrMap, refNodeName, &attrIndex);
11272 if (status != CAPS_SUCCESS0) {
11273 PRINT_ERROR("capsGroup name %s not found in attribute to index map", refNodeName)fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"capsGroup name %s not found in attribute to index map" "\n"
"--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11273, __func__, refNodeName);
;
11274 goto cleanup;
11275 }
11276
11277 status = mesh_findNodes(
11278 &feaProblem->feaMesh, _matchReferenceNode, &attrIndex, &numNodes, &nodes);
11279 if (status == CAPS_NOTFOUND-303) {
11280 PRINT_ERROR("No node found with capsReference name %s", refNodeName)fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n"
"[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: "
"No node found with capsReference name %s" "\n" "--------------------------------------------------------------------------------\n"
"\n", "feaUtils.c", 11280, __func__, refNodeName);
;
11281 }
11282 if (status != CAPS_SUCCESS0) {
11283 goto cleanup;
11284 }
11285
11286 // set refGridID to the nodeID
11287 feaProblem->feaAeroRef.refGridID = nodes[0]->nodeID;
11288 }
11289
11290 status = CAPS_SUCCESS0;
11291
11292 cleanup:
11293
11294 AIM_FREE(refNodeName){ EG_free(refNodeName); refNodeName = ((void*)0); };
11295 AIM_FREE(nodes){ EG_free(nodes); nodes = ((void*)0); };
11296
11297 return status;
11298}
11299
11300// Find feaPropertyStructs with given names in feaProblem
11301int fea_findPropertiesByNames(feaProblemStruct *feaProblem,
11302 int numPropertyNames,
11303 char **propertyNames,
11304 int *numProperties,
11305 feaPropertyStruct ***properties) {
11306 int i, status;
11307
11308 int numFound;
11309 feaPropertyStruct **propertiesFound, *property;
11310
11311 propertiesFound = EG_alloc(sizeof(feaPropertyStruct *) * numPropertyNames);
11312
11313 numFound = 0;
11314 for (i = 0; i < feaProblem->numProperty; i++) {
11315
11316 property = &feaProblem->feaProperty[i];
11317
11318 if (string_isInArray(property->name, numPropertyNames, propertyNames)) {
11319
11320 propertiesFound[numFound++] = property;
11321
11322 if (numFound == numPropertyNames) {
11323 // found all
11324 break;
11325 }
11326 }
11327 }
11328
11329 if (numFound < numPropertyNames) {
11330 propertiesFound = EG_reall(propertiesFound, sizeof(feaPropertyStruct *) * numFound);
11331 status = CAPS_NOTFOUND-303;
11332 }
11333 else {
11334 status = CAPS_SUCCESS0;
11335 }
11336
11337 *numProperties = numFound;
11338 *properties = propertiesFound;
11339
11340 return status;
11341}
11342
11343// Find feaMaterialStructs with given names in feaProblem
11344int fea_findMaterialsByNames(feaProblemStruct *feaProblem,
11345 int numMaterialNames,
11346 char **materialNames,
11347 int *numMaterials,
11348 feaMaterialStruct ***materials) {
11349 int i, status;
11350
11351 int numFound;
11352 feaMaterialStruct **materialsFound, *material;
11353
11354 materialsFound = EG_alloc(sizeof(feaMaterialStruct *) * numMaterialNames);
11355
11356 numFound = 0;
11357 for (i = 0; i < feaProblem->numMaterial; i++) {
11358
11359 material = &feaProblem->feaMaterial[i];
11360
11361 if (string_isInArray(material->name, numMaterialNames, materialNames)) {
11362
11363 materialsFound[numFound++] = material;
11364
11365 if (numFound == numMaterialNames) {
11366 // found all
11367 break;
11368 }
11369 }
11370 }
11371
11372 if (numFound < numMaterialNames) {
11373 materialsFound = EG_reall(materialsFound, sizeof(feaMaterialStruct *) * numFound);
11374 status = CAPS_NOTFOUND-303;
11375 }
11376 else {
11377 status = CAPS_SUCCESS0;
11378 }
11379
11380 *numMaterials = numFound;
11381 *materials = materialsFound;
11382
11383 return status;
11384}
11385
11386// Find feaDesignVariableStructs with given names in feaProblem
11387int fea_findDesignVariablesByNames(const feaProblemStruct *feaProblem,
11388 int numDesignVariableNames,
11389 char **designVariableNames,
11390 int *numDesignVariables,
11391 feaDesignVariableStruct ***designVariables) {
11392 int i, status;
11393
11394 int numFound;
11395 feaDesignVariableStruct **designVariablesFound=NULL((void*)0), *designVariable=NULL((void*)0);
11396
11397 designVariablesFound = (feaDesignVariableStruct **) EG_alloc(numDesignVariableNames * sizeof(feaDesignVariableStruct *));
11398
11399 numFound = 0;
11400 for (i = 0; i < feaProblem->numDesignVariable; i++) {
11401
11402 designVariable = &feaProblem->feaDesignVariable[i];
11403
11404 if (string_isInArray(designVariable->name, numDesignVariableNames, designVariableNames)) {
11405
11406 designVariablesFound[numFound++] = designVariable;
11407
11408 if (numFound == numDesignVariableNames) {
11409 // found all
11410 break;
11411 }
11412 }
11413 }
11414
11415 if (numFound < numDesignVariableNames) {
11416 designVariablesFound = EG_reall(designVariablesFound, numFound * sizeof(feaDesignVariableStruct *));
11417 status = CAPS_NOTFOUND-303;
11418 } else {
11419 status = CAPS_SUCCESS0;
11420 }
11421
11422 *numDesignVariables = numFound;
11423 *designVariables = designVariablesFound;
11424
11425 return status;
11426}
11427
11428// Find feaDesignResponseStructs with given names in feaProblem
11429int fea_findDesignResponsesByNames(const feaProblemStruct *feaProblem,
11430 int numDesignResponseNames,
11431 char **designResponseNames,
11432 int *numDesignResponses,
11433 feaDesignResponseStruct ***designResponses) {
11434 int i, status;
11435
11436 int numFound;
11437 feaDesignResponseStruct **designResponsesFound, *designResponse;
11438
11439 designResponsesFound = EG_alloc(sizeof(feaDesignResponseStruct *) * numDesignResponseNames);
11440
11441 numFound = 0;
11442 for (i = 0; i < feaProblem->numDesignResponse; i++) {
11443
11444 designResponse = &feaProblem->feaDesignResponse[i];
11445
11446 if (string_isInArray(designResponse->name, numDesignResponseNames, designResponseNames)) {
11447
11448 designResponsesFound[numFound++] = designResponse;
11449
11450 if (numFound == numDesignResponseNames) {
11451 // found all
11452 break;
11453 }
11454 }
11455 }
11456
11457 if (numFound < numDesignResponseNames) {
11458 designResponsesFound = EG_reall(designResponsesFound, sizeof(feaDesignResponseStruct *) * numFound);
11459 status = CAPS_NOTFOUND-303;
11460 }
11461 else {
11462 status = CAPS_SUCCESS0;
11463 }
11464
11465 *numDesignResponses = numFound;
11466 *designResponses = designResponsesFound;
11467
11468 return status;
11469}
11470
11471// Find feaDesignEquationResponseStructs with given names in feaProblem
11472int fea_findEquationResponsesByNames(const feaProblemStruct *feaProblem,
11473 int numEquationResponseNames,
11474 char **equationResponseNames,
11475 int *numEquationResponses,
11476 feaDesignEquationResponseStruct ***equationResponses) {
11477 int i, status;
11478
11479 int numFound;
11480 feaDesignEquationResponseStruct **equationResponsesFound, *equationResponse;
11481
11482 equationResponsesFound = EG_alloc(sizeof(feaDesignEquationResponseStruct *) * numEquationResponseNames);
11483
11484 numFound = 0;
11485 for (i = 0; i < feaProblem->numEquationResponse; i++) {
11486
11487 equationResponse = &feaProblem->feaEquationResponse[i];
11488
11489 if (string_isInArray(equationResponse->name, numEquationResponseNames, equationResponseNames)) {
11490
11491 equationResponsesFound[numFound++] = equationResponse;
11492
11493 if (numFound == numEquationResponseNames) {
11494 // found all
11495 break;
11496 }
11497 }
11498 }
11499
11500 if (numFound < numEquationResponseNames) {
11501 equationResponsesFound = EG_reall(equationResponsesFound, sizeof(feaDesignEquationResponseStruct *) * numFound);
11502 status = CAPS_NOTFOUND-303;
11503 }
11504 else {
11505 status = CAPS_SUCCESS0;
11506 }
11507
11508 *numEquationResponses = numFound;
11509 *equationResponses = equationResponsesFound;
11510
11511 return status;
11512}
11513
11514// Find feaDesignEquationStruct with given equationName in feaProblem
11515int fea_findEquationByName(const feaProblemStruct *feaProblem, char *equationName, feaDesignEquationStruct **equation) {
11516
11517 int i;
11518
11519 for (i = 0; i < feaProblem->numEquation; i++) {
11520
11521 if (strcmp(feaProblem->feaEquation[i].name, equationName) == 0) {
11522 *equation = &feaProblem->feaEquation[i];
11523 return CAPS_SUCCESS0;
11524 }
11525 }
11526
11527 return CAPS_NOTFOUND-303;
11528}
11529
11530// Find vlmControlStruct with given controlSurfName in feaProble
11531int fea_findControlSurfaceByName(const feaProblemStruct *feaProblem, char *controlSurfName, vlmControlStruct **controlSurf) {
11532
11533 int isection, icontrol;
11534
11535 vlmSurfaceStruct *surface;
11536 vlmSectionStruct *section;
11537
11538 surface = &feaProblem->feaAero->vlmSurface;
11539
11540 for (isection = 0; isection < surface->numSection; isection++) {
11541
11542 section = &surface->vlmSection[isection];
11543
11544 for (icontrol = 0; icontrol < section->numControl; icontrol++) {
11545
11546 if (strcmp(section->vlmControl[icontrol].name, controlSurfName) == 0) {
11547 *controlSurf = &section->vlmControl[icontrol];
11548 return CAPS_SUCCESS0;
11549 }
11550 }
11551 }
11552
11553 return CAPS_NOTFOUND-303;
11554}
11555
11556// Find feaDesignConstraintStruct with given constraintType in feaProblem
11557int fea_findDesignConstraintByType(const feaProblemStruct *feaProblem, feaDesignConstraintTypeEnum constraintType, feaDesignConstraintStruct **designConstraint) {
11558
11559 int i;
11560
11561 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
11562
11563 if (feaProblem->feaDesignConstraint[i].designConstraintType == constraintType) {
11564 *designConstraint = &feaProblem->feaDesignConstraint[i];
11565 return CAPS_SUCCESS0;
11566 }
11567 }
11568
11569 return CAPS_NOTFOUND-303;
11570}
11571
11572static inline int _feaDesignVariableRelation_linkDesignVariable(feaDesignVariableRelationStruct *relation,
11573 feaDesignVariableStruct *desvar,
11574 int desvarIndex) {
11575 if (relation->designVariableSet == NULL((void*)0)) {
11576 relation->designVariableSet = (
11577 (feaDesignVariableStruct **)
11578 EG_alloc(sizeof(feaDesignVariableStruct *) * relation->numDesignVariable)
11579 );
11580 }
11581 if (relation->designVariableSet == NULL((void*)0)) {
11582 return EGADS_MALLOC-4;
11583 }
11584
11585 relation->designVariableSet[desvarIndex] = desvar;
11586
11587 return CAPS_SUCCESS0;
11588}
11589
11590static inline int _feaDesignVariable_linkDesignVariableRelation(feaDesignVariableStruct *desvar,
11591 feaDesignVariableRelationStruct *relation) {
11592
11593 if (desvar->numRelation == 0) {
11594 desvar->relationSet = (
11595 (feaDesignVariableRelationStruct **)
11596 EG_alloc(sizeof(feaDesignVariableRelationStruct *))
11597 );
11598 }
11599 else {
11600 desvar->relationSet = (
11601 (feaDesignVariableRelationStruct **)
11602 EG_reall(desvar->relationSet, sizeof(feaDesignVariableRelationStruct *) * (desvar->numRelation + 1))
11603 );
11604 }
11605 if (desvar->relationSet == NULL((void*)0)) {
11606 return EGADS_MALLOC-4;
11607 }
11608
11609 desvar->relationSet[desvar->numRelation] = relation;
11610 desvar->numRelation++;
11611
11612 return CAPS_SUCCESS0;
11613}
11614
11615// Populate the feaDesignVariable.relationSet and feaDesignVariableRelation.variableSet members
11616// in all feaDesignVariables and feaDesignVariableRelations
11617int fea_linkDesignVariablesAndRelations(const feaProblemStruct *feaProblem) {
11618
11619 int status;
11620 int idvGlobal, idv, irel;
11621
11622 char *desvarName = NULL((void*)0), **desvarNameSet = NULL((void*)0);
11623
11624 feaDesignVariableStruct *desvar = NULL((void*)0);
11625 feaDesignVariableRelationStruct *desvarRelation = NULL((void*)0);
11626
11627 for (irel = 0; irel < feaProblem->numDesignVariableRelation; irel++) {
11628
11629 desvarRelation = &feaProblem->feaDesignVariableRelation[irel];
11630 desvarNameSet = desvarRelation->designVariableNameSet;
11631
11632 for (idv = 0; idv < desvarRelation->numDesignVariable; idv++) {
11633
11634 desvarName = desvarNameSet[idv];
11635
11636 for (idvGlobal = 0; idvGlobal < feaProblem->numDesignVariable; idvGlobal++) {
11637
11638 desvar = &feaProblem->feaDesignVariable[idvGlobal];
11639
11640 if (strcmp(desvar->name, desvarName) == 0) {
11641
11642 status = _feaDesignVariableRelation_linkDesignVariable(desvarRelation, desvar, idv);
11643 if (status != CAPS_SUCCESS0) return status;
11644
11645 status = _feaDesignVariable_linkDesignVariableRelation(desvar, desvarRelation);
11646 if (status != CAPS_SUCCESS0) return status;
11647 break;
11648 }
11649 }
11650 }
11651 }
11652
11653 return CAPS_SUCCESS0;
11654}
11655
11656// Initiate (0 out all values and NULL all pointers) of feaProblem in the feaProblemStruct structure format
11657int initiate_feaProblemStruct(feaProblemStruct *feaProblem) {
11658
11659 int status = 0;
11660
11661 // Problem analysis
11662 feaProblem->numAnalysis = 0;
11663 feaProblem->feaAnalysis = NULL((void*)0);
11664
11665 // Materials
11666 feaProblem->numMaterial = 0;
11667 feaProblem->feaMaterial = NULL((void*)0);
11668
11669 // Properties
11670 feaProblem->numProperty = 0;
11671 feaProblem->feaProperty = NULL((void*)0);
11672
11673 // Constraints
11674 feaProblem->numConstraint = 0;
11675 feaProblem->feaConstraint = NULL((void*)0);
11676
11677 // Supports
11678 feaProblem->numSupport = 0;
11679 feaProblem->feaSupport = NULL((void*)0);
11680
11681 // Loads
11682 feaProblem->numLoad = 0;
11683 feaProblem->feaLoad = NULL((void*)0);
11684
11685 // Connections
11686 feaProblem->numConnect = 0;
11687 feaProblem->feaConnect = NULL((void*)0);
11688
11689 // Mesh
11690 status = initiate_meshStruct(&feaProblem->feaMesh);
11691 if (status != CAPS_SUCCESS0) goto cleanup;
11692
11693 // Output formatting
11694 status = initiate_feaFileFormatStruct(&feaProblem->feaFileFormat);
11695 if (status != CAPS_SUCCESS0) goto cleanup;
11696
11697 // Optimization - Design Variables
11698 feaProblem->numDesignVariable = 0;
11699 feaProblem->feaDesignVariable = NULL((void*)0);
11700
11701 // Optimization - Design Variable Relations
11702 feaProblem->numDesignVariableRelation = 0;
11703 feaProblem->feaDesignVariableRelation = NULL((void*)0);
11704
11705 // Optimization - Design Constraints
11706 feaProblem->numDesignConstraint = 0;
11707 feaProblem->feaDesignConstraint = NULL((void*)0);
11708
11709 // Optimization - Equations
11710 feaProblem->numEquation = 0;
11711 feaProblem->feaEquation = NULL((void*)0);
11712
11713 // Optimization - Table Constants
11714 status = initiate_feaDesignTableStruct(&feaProblem->feaDesignTable);
11715 if (status != CAPS_SUCCESS0) goto cleanup;
11716
11717 // Optimization - Design Optimization Parameters
11718 status = initiate_feaDesignOptParamStruct(&feaProblem->feaDesignOptParam);
11719 if (status != CAPS_SUCCESS0) goto cleanup;
11720
11721 // Optimization - Design Sensitivity Response Quantities
11722 feaProblem->numDesignResponse = 0;
11723 feaProblem->feaDesignResponse = NULL((void*)0);
11724
11725 // Optimization - Design Sensitivity Equation Response Quantities
11726 feaProblem->numEquationResponse = 0;
11727 feaProblem->feaEquationResponse = NULL((void*)0);
11728
11729 // Coordinate Systems
11730 feaProblem->numCoordSystem = 0;
11731 feaProblem->feaCoordSystem = NULL((void*)0);
11732
11733 // Aerodynamics
11734 feaProblem->numAero = 0;
11735 feaProblem->feaAero = NULL((void*)0);
11736 status = initiate_feaAeroRefStruct(&feaProblem->feaAeroRef);
11737 if (status != CAPS_SUCCESS0) goto cleanup;
11738
11739 aim_initMeshRef(&feaProblem->meshRefObj, aimUnknownMeshType);
11740 feaProblem->meshRefIn = NULL((void*)0);
11741
11742 status = CAPS_SUCCESS0;
11743
11744cleanup:
11745 if (status != CAPS_SUCCESS0) printf("Error: Status %d during initiate_feaProblemStruct!\n", status);
11746
11747 return status;
11748}
11749
11750// Destroy (0 out all values and NULL all pointers) of feaProblem in the feaProblemStruct structure format
11751int destroy_feaProblemStruct(feaProblemStruct *feaProblem) {
11752
11753 int i; // Indexing
11754
11755 int status = 0; // Status return
11756
11757 // Analysis
11758 if (feaProblem->feaAnalysis != NULL((void*)0)) {
11759 for (i = 0; i < feaProblem->numAnalysis; i++) {
11760 status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
11761 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaAnalysisStruct\n", status);
11762 }
11763 }
11764 AIM_FREE(feaProblem->feaAnalysis){ EG_free(feaProblem->feaAnalysis); feaProblem->feaAnalysis
= ((void*)0); }
;
11765 feaProblem->numAnalysis = 0;
11766
11767 // Materials
11768 if (feaProblem->feaMaterial != NULL((void*)0)) {
11769 for (i = 0; i < feaProblem->numMaterial; i++) {
11770 status = destroy_feaMaterialStruct(&feaProblem->feaMaterial[i]);
11771 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaMaterialStruct\n", status);
11772 }
11773 }
11774 AIM_FREE(feaProblem->feaMaterial){ EG_free(feaProblem->feaMaterial); feaProblem->feaMaterial
= ((void*)0); }
;
11775 feaProblem->numMaterial = 0;
11776
11777 // Properties
11778 if (feaProblem->feaProperty != NULL((void*)0)) {
11779 for (i = 0; i < feaProblem->numProperty; i++) {
11780 status = destroy_feaPropertyStruct(&feaProblem->feaProperty[i]);
11781 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaPropertyStruct\n", status);
11782 }
11783 }
11784 AIM_FREE(feaProblem->feaProperty){ EG_free(feaProblem->feaProperty); feaProblem->feaProperty
= ((void*)0); }
;
11785 feaProblem->numProperty = 0;
11786
11787 // Constraints
11788 if (feaProblem->feaConstraint != NULL((void*)0)) {
11789 for (i = 0; i < feaProblem->numConstraint; i++) {
11790 status = destroy_feaConstraintStruct(&feaProblem->feaConstraint[i]);
11791 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaConstraintStruct\n", status);
11792 }
11793 }
11794 AIM_FREE(feaProblem->feaConstraint){ EG_free(feaProblem->feaConstraint); feaProblem->feaConstraint
= ((void*)0); }
;
11795 feaProblem->numConstraint = 0;
11796
11797 // Supports
11798 if (feaProblem->feaSupport != NULL((void*)0)) {
11799 for (i = 0; i < feaProblem->numSupport; i++) {
11800 status = destroy_feaSupportStruct(&feaProblem->feaSupport[i]);
11801 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaSupportStruct\n", status);
11802 }
11803 }
11804 AIM_FREE(feaProblem->feaSupport){ EG_free(feaProblem->feaSupport); feaProblem->feaSupport
= ((void*)0); }
;
11805 feaProblem->numSupport = 0;
11806
11807 // Loads
11808 if (feaProblem->feaLoad != NULL((void*)0)) {
11809 for (i = 0; i < feaProblem->numLoad; i++) {
11810 status = destroy_feaLoadStruct(&feaProblem->feaLoad[i]);
11811 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaLoadStruct\n", status);
11812 }
11813 }
11814 AIM_FREE(feaProblem->feaLoad){ EG_free(feaProblem->feaLoad); feaProblem->feaLoad = (
(void*)0); }
;
11815 feaProblem->numLoad = 0;
11816
11817 // Connections
11818 if (feaProblem->feaConnect != NULL((void*)0)) {
11819 for (i = 0; i < feaProblem->numConnect; i++) {
11820 status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]);
11821 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaConnectStruct\n", status);
11822 }
11823 }
11824 AIM_FREE(feaProblem->feaConnect){ EG_free(feaProblem->feaConnect); feaProblem->feaConnect
= ((void*)0); }
;
11825 feaProblem->numConnect = 0;
11826
11827 // Mesh
11828 status = destroy_meshStruct(&feaProblem->feaMesh);
11829 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_meshStruct\n", status);
11830
11831 // Output formatting
11832 status = destroy_feaFileFormatStruct(&feaProblem->feaFileFormat);
11833 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaFileFormatStruct\n", status);
11834
11835
11836 if (feaProblem->feaDesignVariable != NULL((void*)0)) {
11837 for (i = 0; i < feaProblem->numDesignVariable; i++) {
11838 status = destroy_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]);
11839 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignVariableStruct\n", status);
11840 }
11841 }
11842 AIM_FREE(feaProblem->feaDesignVariable){ EG_free(feaProblem->feaDesignVariable); feaProblem->feaDesignVariable
= ((void*)0); }
;
11843 feaProblem->numDesignVariable = 0;
11844
11845 // Optimization - design variable relations
11846 if (feaProblem->feaDesignVariableRelation != NULL((void*)0)) {
11847 for (i = 0; i < feaProblem->numDesignVariableRelation; i++) {
11848 status = destroy_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]);
11849 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignVariableRelationStruct\n", status);
11850 }
11851 AIM_FREE(feaProblem->feaDesignVariableRelation){ EG_free(feaProblem->feaDesignVariableRelation); feaProblem
->feaDesignVariableRelation = ((void*)0); }
;
11852 }
11853 feaProblem->numDesignVariableRelation = 0;
11854
11855 // Optimization - design constraint
11856 if (feaProblem->feaDesignConstraint != NULL((void*)0)) {
11857 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
11858 status = destroy_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]);
11859 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignConstraintStruct\n", status);
11860 }
11861 }
11862 AIM_FREE(feaProblem->feaDesignConstraint){ EG_free(feaProblem->feaDesignConstraint); feaProblem->
feaDesignConstraint = ((void*)0); }
;
11863 feaProblem->numDesignConstraint = 0;
11864
11865 // Optimization - Equations
11866 if (feaProblem->feaEquation != NULL((void*)0)) {
11867 for (i = 0; i < feaProblem->numEquation; i++) {
11868 status = destroy_feaDesignEquationStruct(&feaProblem->feaEquation[i]);
11869 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignEquationStruct\n", status);
11870 }
11871 AIM_FREE(feaProblem->feaEquation){ EG_free(feaProblem->feaEquation); feaProblem->feaEquation
= ((void*)0); }
;
11872 }
11873 feaProblem->numEquation = 0;
11874
11875 // Optimization - Table Constants
11876 status = destroy_feaDesignTableStruct(&feaProblem->feaDesignTable);
11877 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignTableStruct\n", status);
11878
11879 // Optimization - Design Optimization Parameters
11880 status = destroy_feaDesignOptParamStruct(&feaProblem->feaDesignOptParam);
11881 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignOptParamStruct\n", status);
11882
11883 // Optimization - Design Sensitivity Response Quantities
11884 if (feaProblem->feaDesignResponse != NULL((void*)0)) {
11885 for (i = 0; i < feaProblem->numDesignResponse; i++) {
11886 status = destroy_feaDesignResponseStruct(&feaProblem->feaDesignResponse[i]);
11887 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignResponseStruct\n", status);
11888 }
11889 AIM_FREE(feaProblem->feaDesignResponse){ EG_free(feaProblem->feaDesignResponse); feaProblem->feaDesignResponse
= ((void*)0); }
;
11890 }
11891 feaProblem->numDesignResponse = 0;
11892
11893 // Optimization - Design Sensitivity Equation Response Quantities
11894 if (feaProblem->feaEquationResponse != NULL((void*)0)) {
11895 for (i = 0; i < feaProblem->numEquationResponse; i++) {
11896 status = destroy_feaDesignEquationResponseStruct(&feaProblem->feaEquationResponse[i]);
11897 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaEquationResponseStruct\n", status);
11898 }
11899 AIM_FREE(feaProblem->feaEquationResponse){ EG_free(feaProblem->feaEquationResponse); feaProblem->
feaEquationResponse = ((void*)0); }
;
11900 }
11901 feaProblem->numEquationResponse = 0;
11902
11903 // Coordinate Systems
11904 if (feaProblem->feaCoordSystem != NULL((void*)0)) {
11905
11906 for (i = 0; i < feaProblem->numCoordSystem; i++) {
11907 status = destroy_feaCoordSystemStruct(&feaProblem->feaCoordSystem[i]);
11908 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaCoordSystemStruct\n", status);
11909 }
11910 }
11911 AIM_FREE(feaProblem->feaCoordSystem){ EG_free(feaProblem->feaCoordSystem); feaProblem->feaCoordSystem
= ((void*)0); }
;
11912 feaProblem->numCoordSystem = 0;
11913
11914 // Aerodynamics
11915 if (feaProblem->feaAero != NULL((void*)0)) {
11916
11917 for (i = 0; i < feaProblem->numAero; i++) {
11918 status = destroy_feaAeroStruct(&feaProblem->feaAero[i]);
11919 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaAeroStruct\n", status);
11920 }
11921 }
11922 AIM_FREE(feaProblem->feaAero){ EG_free(feaProblem->feaAero); feaProblem->feaAero = (
(void*)0); }
;
11923 feaProblem->numAero = 0;
11924
11925 (void) destroy_feaAeroRefStruct(&feaProblem->feaAeroRef);
11926
11927 aim_freeMeshRef(&feaProblem->meshRefObj);
11928 feaProblem->meshRefIn = NULL((void*)0);
11929
11930 return CAPS_SUCCESS0;
11931}
11932
11933// Initiate (0 out all values and NULL all pointers) of feaFileFormat in the feaFileFormatStruct structure format
11934int initiate_feaFileFormatStruct(feaFileFormatStruct *feaFileFormat) {
11935
11936 feaFileFormat->fileType = SmallField;
11937
11938 feaFileFormat->gridFileType = LargeField;
11939
11940 return CAPS_SUCCESS0;
11941}
11942
11943// Destroy (0 out all values and NULL all pointers) of feaFileFormat in the feaFileFormatStruct structure format
11944int destroy_feaFileFormatStruct(feaFileFormatStruct *feaFileFormat) {
11945
11946 feaFileFormat->fileType = SmallField;
11947
11948 feaFileFormat->gridFileType = LargeField;
11949
11950 return CAPS_SUCCESS0;
11951}
11952
11953// Transfer external pressure from the discrObj into the feaLoad structure
11954int fea_transferExternalPressure(void *aimInfo, const meshStruct *feaMesh, feaLoadStruct *feaLoad) {
11955
11956 // [in/out] feaLoad
11957 // [in] feaMesh
11958 // [in] aimInfo
11959
11960 int status; // Function status return
11961
11962 int i, j, bIndex; // Indexing
11963
11964 // Variables used in global node mapping
11965 int globalNodeID;
11966 int nodeIndex[4], transferIndex[4], elementID, elementIndex, elementCount;
11967
11968 // Discrete data transfer variables
11969 capsDiscr *dataTransferDiscreteObj;
11970 char **transferName = NULL((void*)0);
11971 int numTransferName, transferNameIndex;
11972 enum capsdMethod dataTransferMethod;
11973 int numDataTransferPoint;
11974 int numDataTransferElement = 0, discElements;
11975 int dataTransferRank;
11976 double *dataTransferData;
11977 char *units;
11978
11979 feaLoad->numElementID = 0;
11980 AIM_FREE(feaLoad->pressureMultiDistributeForce){ EG_free(feaLoad->pressureMultiDistributeForce); feaLoad->
pressureMultiDistributeForce = ((void*)0); }
;
11981 AIM_FREE(feaLoad->elementIDSet){ EG_free(feaLoad->elementIDSet); feaLoad->elementIDSet
= ((void*)0); }
;
11982
11983 //See if we have data transfer information
11984 status = aim_getBounds(aimInfo, &numTransferName, &transferName);
11985 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 11985
, __func__, 0); goto cleanup; }
;
11986
11987 numDataTransferElement = 0;
11988 elementIndex = 0;
11989 elementCount = 0;
11990
11991 for (transferNameIndex = 0; transferNameIndex < numTransferName; transferNameIndex++) {
11992
11993 status = aim_getDiscr(aimInfo, transferName[transferNameIndex], &dataTransferDiscreteObj);
11994 if (status == CAPS_NOTFOUND-303) continue;
11995 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 11995
, __func__, 0); goto cleanup; }
;
11996
11997 status = aim_getDataSet(dataTransferDiscreteObj,
11998 "Pressure",
11999 &dataTransferMethod,
12000 &numDataTransferPoint,
12001 &dataTransferRank,
12002 &dataTransferData,
12003 &units);
12004 if (status == CAPS_NOTFOUND-303) continue; // If no elements in this object skip to next transfer name
12005 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12005
, __func__, 0); goto cleanup; }
;
12006
12007 printf("Extracting external pressure loads from data transfer....\n");
12008
12009 // If we do have data ready, how many elements there are?
12010 if (numDataTransferPoint == 1) {
12011 AIM_ERROR(aimInfo, "Pressures not initialized!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12011, __func__
, "Pressures not initialized!"); }
;
12012 status = CAPS_BADINIT-338;
12013 goto cleanup;
12014 }
12015
12016 if (dataTransferRank != 1) {
12017 AIM_ERROR(aimInfo, "Pressure transfer data found however rank is %d not 1!!!!", dataTransferRank){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12017, __func__
, "Pressure transfer data found however rank is %d not 1!!!!"
, dataTransferRank); }
;
12018 status = CAPS_BADRANK-301;
12019 goto cleanup;
12020 }
12021
12022 discElements = 0;
12023 for (bIndex = 0; bIndex < dataTransferDiscreteObj->nBodys; bIndex++)
12024 discElements += dataTransferDiscreteObj->bodys[bIndex].nElems;
12025
12026 numDataTransferElement += discElements;
12027 printf("\tTransferName = %s\n", transferName[transferNameIndex]);
12028 printf("\tNumber of Elements = %d (total = %d)\n", discElements, numDataTransferElement);
12029
12030 // allocate arrays
12031 AIM_REALL(feaLoad->elementIDSet, numDataTransferElement, int, aimInfo, status){ size_t memorysize = numDataTransferElement; feaLoad->elementIDSet
= (int *) EG_reall(feaLoad->elementIDSet, memorysize*sizeof
(int)); if (feaLoad->elementIDSet == ((void*)0)) { status =
-4; aim_status(aimInfo, status, "feaUtils.c", 12031, __func__
, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->elementIDSet"
, memorysize, "int"); goto cleanup; } }
;
12032 AIM_REALL(feaLoad->pressureMultiDistributeForce, 4*numDataTransferElement, double, aimInfo, status){ size_t memorysize = 4*numDataTransferElement; feaLoad->pressureMultiDistributeForce
= (double *) EG_reall(feaLoad->pressureMultiDistributeForce
, memorysize*sizeof(double)); if (feaLoad->pressureMultiDistributeForce
== ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 12032, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->pressureMultiDistributeForce"
, memorysize, "double"); goto cleanup; } }
;
12033
12034 //Now lets loop through our ctria3 mesh and get the node indexes for each element
12035 for (i = 0; i < feaMesh->numElement; i++) {
12036
12037 if (feaMesh->element[i].elementType != Triangle) continue;
12038
12039 elementID = feaMesh->element[i].elementID;
12040 //printf("Element Id = %d\n", elementID);
12041
12042 // elementID is 1 bias
12043 nodeIndex[0] = feaMesh->element[i].connectivity[0];
12044 nodeIndex[1] = feaMesh->element[i].connectivity[1];
12045 nodeIndex[2] = feaMesh->element[i].connectivity[2];
12046
12047 //printf("Node Index = %d %d %d\n", nodeIndex[0], nodeIndex[1], nodeIndex[2]);
12048
12049 transferIndex[0] = -1;
12050 transferIndex[1] = -1;
12051 transferIndex[2] = -1;
12052 transferIndex[3] = -1;
12053
12054 // Loop through the nodeMap of the data set getting nodeIDs trying
12055 // to match the nodes in the element
12056 for (j = 0; j < numDataTransferPoint; j++) {
12057
12058 bIndex = dataTransferDiscreteObj->tessGlobal[2*j ];
12059 globalNodeID = dataTransferDiscreteObj->tessGlobal[2*j+1] +
12060 dataTransferDiscreteObj->bodys[bIndex-1].globalOffset;
12061
12062 if (nodeIndex[0] == globalNodeID) transferIndex[0] = j;
12063 if (nodeIndex[1] == globalNodeID) transferIndex[1] = j;
12064 if (nodeIndex[2] == globalNodeID) transferIndex[2] = j;
12065
12066 // If the nodes completely match the nodes on the element - break
12067 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && transferIndex[2] >= 0) {
12068 break;
12069 }
12070 }
12071
12072 // If all the nodeIndexes match the transferIndex the element is in the data set
12073 // so transfer the pressure forces
12074 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && transferIndex[2] >= 0) {
12075
12076 feaLoad->elementIDSet[elementIndex] = elementID;
12077
12078 feaLoad->pressureMultiDistributeForce[4*elementIndex+0] = dataTransferData[transferIndex[0]];
12079 feaLoad->pressureMultiDistributeForce[4*elementIndex+1] = dataTransferData[transferIndex[1]];
12080 feaLoad->pressureMultiDistributeForce[4*elementIndex+2] = dataTransferData[transferIndex[2]];
12081 feaLoad->pressureMultiDistributeForce[4*elementIndex+3] = 0.0;
12082
12083 elementIndex += 1;
12084 elementCount += 1;
12085 feaLoad->numElementID += 1;
12086
12087 }
12088 }
12089
12090 //Now lets loop through our cquad4 mesh and get the node indexes for each element
12091 for (i = 0; i < feaMesh->numElement; i++) {
12092
12093 if (feaMesh->element[i].elementType != Quadrilateral) continue;
12094
12095 elementID = feaMesh->element[i].elementID;
12096
12097 // elementID is 1 bias
12098 nodeIndex[0] = feaMesh->element[i].connectivity[0];
12099 nodeIndex[1] = feaMesh->element[i].connectivity[1];
12100 nodeIndex[2] = feaMesh->element[i].connectivity[2];
12101 nodeIndex[3] = feaMesh->element[i].connectivity[3];
12102
12103 transferIndex[0] = -1;
12104 transferIndex[1] = -1;
12105 transferIndex[2] = -1;
12106 transferIndex[3] = -1;
12107
12108 // Loop through the nodeMap of the data set getting nodeIDs trying
12109 // to match the nodes in the element
12110 for (j = 0; j < numDataTransferPoint; j++) {
12111
12112 bIndex = dataTransferDiscreteObj->tessGlobal[2*j ];
12113 globalNodeID = dataTransferDiscreteObj->tessGlobal[2*j+1] +
12114 dataTransferDiscreteObj->bodys[bIndex-1].globalOffset;
12115
12116 if (nodeIndex[0] == globalNodeID) transferIndex[0] = j;
12117 if (nodeIndex[1] == globalNodeID) transferIndex[1] = j;
12118 if (nodeIndex[2] == globalNodeID) transferIndex[2] = j;
12119 if (nodeIndex[3] == globalNodeID) transferIndex[3] = j;
12120
12121 // If the nodes completely match the nodes on the element - break
12122 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 &&
12123 transferIndex[2] >= 0 && transferIndex[3] >= 0) {
12124 break;
12125 }
12126 }
12127
12128 // If all the nodeIndexes match the transferIndex the element is in the data set
12129 // so transfer the pressure forces
12130 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 &&
12131 transferIndex[2] >= 0 && transferIndex[3] >= 0) {
12132
12133 feaLoad->elementIDSet[elementIndex] = elementID;
12134
12135 feaLoad->pressureMultiDistributeForce[4*elementIndex+0] = dataTransferData[transferIndex[0]];
12136 feaLoad->pressureMultiDistributeForce[4*elementIndex+1] = dataTransferData[transferIndex[1]];
12137 feaLoad->pressureMultiDistributeForce[4*elementIndex+2] = dataTransferData[transferIndex[2]];
12138 feaLoad->pressureMultiDistributeForce[4*elementIndex+3] = dataTransferData[transferIndex[3]];
12139
12140 elementIndex += 1;
12141 elementCount += 1;
12142 feaLoad->numElementID += 1;
12143 }
12144 }
12145
12146 if (elementCount != numDataTransferElement) {
12147 AIM_ERROR(aimInfo, "Element transfer mismatch: number of elements found = %d, number"{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12148, __func__
, "Element transfer mismatch: number of elements found = %d, number"
" of elements in transfer data set %d", elementCount, numDataTransferElement
); }
12148 " of elements in transfer data set %d", elementCount, numDataTransferElement){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12148, __func__
, "Element transfer mismatch: number of elements found = %d, number"
" of elements in transfer data set %d", elementCount, numDataTransferElement
); }
;
12149 AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); };
12150
12151 status = CAPS_MISMATCH-324;
12152 goto cleanup;
12153 }
12154
12155 // Resize
12156 if (feaLoad->numElementID != numDataTransferElement) {
12157 AIM_REALL(feaLoad->pressureMultiDistributeForce, 4*feaLoad->numElementID, double, aimInfo, status){ size_t memorysize = 4*feaLoad->numElementID; feaLoad->
pressureMultiDistributeForce = (double *) EG_reall(feaLoad->
pressureMultiDistributeForce, memorysize*sizeof(double)); if (
feaLoad->pressureMultiDistributeForce == ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 12157, __func__
, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->pressureMultiDistributeForce"
, memorysize, "double"); goto cleanup; } }
;
12158 }
12159
12160 } // End data transfer name loop
12161
12162
12163 status = CAPS_SUCCESS0;
12164
12165cleanup:
12166
12167 AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); };
12168
12169 return status;
12170}
12171
12172// Transfer external temperature from the discrObj into the feaLoad structure
12173int fea_transferExternalTemperature(void *aimInfo, feaLoadStruct *feaLoad) {
12174
12175 // [in/out] feaLoad
12176 // [in] aimInfo
12177
12178 int status; // Function status return
12179
12180 int i, bIndex; // Indexing
12181
12182 // Variables used in global node mapping
12183 int globalNodeID;
12184
12185 // Discrete data transfer variables
12186 capsDiscr *dataTransferDiscreteObj;
12187 char **transferName = NULL((void*)0);
12188 int numTransferName, transferNameIndex;
12189 enum capsdMethod dataTransferMethod;
12190 int numDataTransferPoint;
12191 int dataTransferRank;
12192 double *dataTransferData;
12193 char *units;
12194
12195 feaLoad->numGridID = 0;
12196 AIM_FREE(feaLoad->temperatureMultiDistribute){ EG_free(feaLoad->temperatureMultiDistribute); feaLoad->
temperatureMultiDistribute = ((void*)0); }
;
12197 AIM_FREE(feaLoad->gridIDSet){ EG_free(feaLoad->gridIDSet); feaLoad->gridIDSet = ((void
*)0); }
;
12198
12199 //See if we have data transfer information
12200 status = aim_getBounds(aimInfo, &numTransferName, &transferName);
12201 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12201
, __func__, 0); goto cleanup; }
;
12202
12203 for (transferNameIndex = 0; transferNameIndex < numTransferName; transferNameIndex++) {
12204
12205 status = aim_getDiscr(aimInfo, transferName[transferNameIndex], &dataTransferDiscreteObj);
12206 if (status == CAPS_NOTFOUND-303) continue;
12207 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12207
, __func__, 0); goto cleanup; }
;
12208
12209 status = aim_getDataSet(dataTransferDiscreteObj,
12210 "Temperature",
12211 &dataTransferMethod,
12212 &numDataTransferPoint,
12213 &dataTransferRank,
12214 &dataTransferData,
12215 &units);
12216 if (status == CAPS_NOTFOUND-303) continue; // If no elements in this object skip to next transfer name
12217 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12217
, __func__, 0); goto cleanup; }
;
12218
12219 printf("Extracting external thermal loads from data transfer....\n");
12220
12221 // If we do have data ready, how many elements there are?
12222 if (numDataTransferPoint == 1) {
12223 AIM_ERROR(aimInfo, "Temperature not initialized!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12223, __func__
, "Temperature not initialized!"); }
;
12224 status = CAPS_BADINIT-338;
12225 goto cleanup;
12226 }
12227
12228 if (dataTransferRank != 1) {
12229 AIM_ERROR(aimInfo, "Temperature transfer data found however rank is %d not 1!!!!", dataTransferRank){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12229, __func__
, "Temperature transfer data found however rank is %d not 1!!!!"
, dataTransferRank); }
;
12230 status = CAPS_BADRANK-301;
12231 goto cleanup;
12232 }
12233
12234 printf("\tTransferName = %s\n", transferName[transferNameIndex]);
12235 printf("\tNumber of Nodes = %d (total = %d)\n", numDataTransferPoint, feaLoad->numGridID+numDataTransferPoint);
12236
12237 // allocate arrays
12238 AIM_REALL(feaLoad->gridIDSet, feaLoad->numGridID+numDataTransferPoint, int, aimInfo, status){ size_t memorysize = feaLoad->numGridID+numDataTransferPoint
; feaLoad->gridIDSet = (int *) EG_reall(feaLoad->gridIDSet
, memorysize*sizeof(int)); if (feaLoad->gridIDSet == ((void
*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c"
, 12238, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->gridIDSet"
, memorysize, "int"); goto cleanup; } }
;
12239 AIM_REALL(feaLoad->temperatureMultiDistribute, feaLoad->numGridID+numDataTransferPoint, double, aimInfo, status){ size_t memorysize = feaLoad->numGridID+numDataTransferPoint
; feaLoad->temperatureMultiDistribute = (double *) EG_reall
(feaLoad->temperatureMultiDistribute, memorysize*sizeof(double
)); if (feaLoad->temperatureMultiDistribute == ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 12239
, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->temperatureMultiDistribute"
, memorysize, "double"); goto cleanup; } }
;
12240
12241 // Loop through the nodeMap of the data set getting nodeIDs trying
12242 // to match the nodes in the element
12243 for (i = 0; i < numDataTransferPoint; i++) {
12244
12245 bIndex = dataTransferDiscreteObj->tessGlobal[2*i ];
12246 globalNodeID = dataTransferDiscreteObj->tessGlobal[2*i+1] +
12247 dataTransferDiscreteObj->bodys[bIndex-1].globalOffset;
12248
12249 feaLoad->gridIDSet[feaLoad->numGridID+i] = globalNodeID;
12250 feaLoad->temperatureMultiDistribute[feaLoad->numGridID+i] = dataTransferData[i];
12251 }
12252
12253 feaLoad->numGridID += numDataTransferPoint;
12254
12255 } // End data transfer name loop
12256
12257 status = CAPS_SUCCESS0;
12258
12259cleanup:
12260
12261 AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); };
12262
12263 return status;
12264}
12265
12266// Retrieve aerodynamic reference quantities from bodies
12267int fea_retrieveAeroRef(int numBody, ego *bodies, feaAeroRefStruct *feaAeroRef) {
12268
12269 int status; // Function return status
12270 int body;
12271
12272 // EGADS return values
12273 int atype, alen;
12274 const int *ints;
12275 const char *string;
12276 const double *reals;
12277
12278 // Get reference quantities from the bodies
12279 for (body = 0; body < numBody; body++) {
12280
12281 status = EG_attributeRet(bodies[body], "capsReferenceArea", &atype, &alen, &ints, &reals, &string);
12282 if (status == EGADS_SUCCESS0 && atype == Double) {
12283
12284 feaAeroRef->refArea = (double) reals[0];
12285 }
12286
12287 status = EG_attributeRet(bodies[body], "capsReferenceChord", &atype, &alen, &ints, &reals, &string);
12288 if (status == EGADS_SUCCESS0 && atype == Double){
12289
12290 feaAeroRef->refChord = (double) reals[0];
12291 }
12292
12293 status = EG_attributeRet(bodies[body], "capsReferenceSpan", &atype, &alen, &ints, &reals, &string);
12294 if (status == EGADS_SUCCESS0 && atype == Double) {
12295
12296 feaAeroRef->refSpan = (double) reals[0];
12297 }
12298
12299 /*
12300 status = EG_attributeRet(bodies[body], "capsReferenceX", &atype, &alen, &ints, &reals, &string);
12301 if (status == EGADS_SUCCESS && atype == Double) {
12302 XX = (double) reals[0];
12303 }
12304
12305 status = EG_attributeRet(bodies[body], "capsReferenceY", &atype, &alen, &ints, &reals, &string);
12306 if (status == EGADS_SUCCESS && atype == Double) {
12307 XX = (double) reals[0];
12308 }
12309
12310 status = EG_attributeRet(bodies[body], "capsReferenceZ", &atype, &alen, &ints, &reals, &string);
12311 if (status == EGADS_SUCCESS && atype == Double) {
12312 XX = (double) reals[0];
12313 }
12314 */
12315 }
12316
12317 return CAPS_SUCCESS0;
12318}
12319
12320
12321// Assign element "subtypes" based on properties set
12322int fea_assignElementSubType(int numProperty, feaPropertyStruct *feaProperty, meshStruct *feaMesh)
12323{
12324 int propertyIndex, i ;
12325
12326 feaMeshDataStruct *feaData;
12327
12328 if (numProperty > 0 && feaProperty == NULL((void*)0)) return CAPS_NULLVALUE-307;
12329 if (feaMesh == NULL((void*)0)) return CAPS_NULLVALUE-307;
12330
12331 printf("Updating mesh element types based on properties input\n");
12332
12333 for (propertyIndex = 0; propertyIndex < numProperty; propertyIndex++ ) {
12334
12335 // Types that don't need subtypes - setting this correctly requires knowledge of what mesh_writeNastran
12336 // writes by default for each mesh element type
12337 if (feaProperty[propertyIndex].propertyType == Rod ||
12338 //feaProperty[propertyIndex].propertyType == Shell ||
12339 //feaProperty[propertyIndex].propertyType == Composite ||
12340 feaProperty[propertyIndex].propertyType == Solid) continue;
12341
12342 for (i = 0; i < feaMesh->numElement; i++) {
12343
12344 // What if this is a volume mesh we inherited ?
12345 if (feaMesh->element[i].analysisType != MeshStructure) {
12346 printf("Developer error: Analysis type not set to MeshStructure for element %d\n", feaMesh->element[i].elementID);
12347 return CAPS_BADVALUE-311;
12348 }
12349
12350 // Matching proptery id
12351 if (feaMesh->element[i].analysisData != NULL((void*)0)) {
12352 feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
12353
12354 if (feaData->propertyID != feaProperty[propertyIndex].propertyID) continue;
12355
12356 } else {
12357 printf("Developer error: No 'feaData' set on element %d\n", feaMesh->element[i].elementID);
12358 return CAPS_BADVALUE-311;
12359
12360 }
12361
12362// if (feaMesh->element[i].markerID != feaProperty[propertyIndex].propertyID) continue;
12363//
12364// feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
12365// if (feaData->propertyID != feaProperty[propertyIndex].propertyID) {
12366// printf("Developer error: Property ID mismatch between element \"markerID\" (%d) and feaData \"propertyID\" (%d) for element %d\n",
12367// feaData->propertyID, feaProperty[propertyIndex].propertyID, feaMesh->element[i].elementID);
12368// return CAPS_BADVALUE;
12369// }
12370
12371
12372 if (feaProperty[propertyIndex].propertyType == ConcentratedMass &&
12373 feaMesh->element[i].elementType == Node) {
12374
12375 feaData->elementSubType = ConcentratedMassElement;
12376 }
12377
12378 if (feaProperty[propertyIndex].propertyType == Bar &&
12379 feaMesh->element[i].elementType == Line) {
12380
12381 feaData->elementSubType = BarElement;
12382 }
12383
12384 if (feaProperty[propertyIndex].propertyType == Beam &&
12385 feaMesh->element[i].elementType == Line) {
12386
12387 feaData->elementSubType = BeamElement;
12388 }
12389
12390 if (feaProperty[propertyIndex].propertyType == Shear &&
12391 feaMesh->element[i].elementType == Quadrilateral){
12392
12393 feaData->elementSubType = ShearElement;
12394 }
12395
12396 if (feaProperty[propertyIndex].propertyType == Membrane &&
12397 feaMesh->element[i].elementType == Quadrilateral){
12398
12399 feaData->elementSubType = MembraneElement;
12400 }
12401
12402 // Only need to set these if the zOffset is needed based on mesh_writeNASTRAN
12403 if ( ( feaProperty[propertyIndex].propertyType == Shell || feaProperty[propertyIndex].propertyType == Composite ) &&
12404 feaProperty[propertyIndex].zOffsetRel != 0.0 &&
12405 ( feaMesh->element[i].elementType == Quadrilateral ||
12406 feaMesh->element[i].elementType == Triangle ||
12407 feaMesh->element[i].elementType == Triangle_6 ||
12408 feaMesh->element[i].elementType == Quadrilateral_8)) {
12409
12410 feaData->elementSubType = ShellElement;
12411 }
12412 }
12413 }
12414
12415 return CAPS_SUCCESS0;
12416}
12417
12418// Create connections for gluing - Connections are appended
12419int fea_glueMesh(void *aimInfo,
12420 meshStruct *mesh,
12421 int connectionID,
12422 /*@unused@*/ int connectionType,
12423 int dofDependent,
12424 char *slaveName,
12425 int numMasterName,
12426 char *masterName[],
12427 mapAttrToIndexStruct *attrMap,
12428 int maxNumMaster,
12429 double searchRadius,
12430 int *numConnect,
12431 feaConnectionStruct *feaConnect[]) {
12432
12433 // Input parameters
12434 //double exactTol=1E-9;
12435 //int weigthing = 1; // 1=linear
12436
12437 int masterWeight = 1;
12438 int masterComponent = 123;
12439
12440 int status;
12441 int i, masterIndex, slaveIndex, distIndex, attrIndex;
12442
12443 int numMaster;
12444
12445 int *glueConn=NULL((void*)0);
12446 double *glueDist=NULL((void*)0);
12447
12448 double dist, maxDist;
12449
12450 feaMeshDataStruct *feaData, *feaDataMaster;
12451
12452// int numConnect;
12453// feaConnectionStruct *feaConnect;
12454
12455
12456// maps from nodeID to mesh->node index
12457// mesh_nodeID2Array(nasMesh, &n2a);
12458
12459 printf("\tCreating glue connections\n");
12460
12461 if (searchRadius <=0) {
12462 printf("\tSearch radius must be greater than 0 when gluing, current value = %g\n", searchRadius);
12463 status = CAPS_BADVALUE-311;
12464 goto cleanup;
12465 }
12466
12467 status = array_allocIntegerVector(maxNumMaster, -1, &glueConn);
12468 if (status != CAPS_SUCCESS0) goto cleanup;
12469
12470 status = array_allocDoubleVector(maxNumMaster, 1E9, &glueDist);
12471 if (status != CAPS_SUCCESS0) goto cleanup;
12472
12473 for (slaveIndex = 0; slaveIndex < mesh->numNode; slaveIndex++) {
12474
12475 feaData = (feaMeshDataStruct *) mesh->node[slaveIndex].analysisData;
12476
12477 status = get_mapAttrToIndexIndex(attrMap, (const char *) slaveName, &attrIndex);
12478 if (status == CAPS_NOTFOUND-303) {
12479 printf("\tName %s not found in attribute map of capsConnect!!!!\n", slaveName);
12480 continue;
12481 } else if (status != CAPS_SUCCESS0) return status;
12482
12483 if (feaData->connectIndex != attrIndex) continue;
12484
12485 // We have a slave at this point
12486
12487 // printf("Slave - node ID %d\n", mesh->node[slaveIndex].nodeID);
12488
12489 status = array_setDoubleVectorValue(maxNumMaster, 1E9, &glueDist);
12490 if (status != CAPS_SUCCESS0) goto cleanup;
12491
12492 status = array_setIntegerVectorValue(maxNumMaster, -1, &glueConn);
12493 if (status != CAPS_SUCCESS0) goto cleanup;
12494
12495 for (masterIndex = 0; masterIndex < mesh->numNode; masterIndex++) {
12496
12497 if (slaveIndex == masterIndex) continue;
12498
12499 feaDataMaster = (feaMeshDataStruct *) mesh->node[masterIndex].analysisData;
12500
12501 for (i = 0; i < numMasterName; i++) {
12502 status = get_mapAttrToIndexIndex(attrMap, (const char *) masterName[i], &attrIndex);
12503 if (status == CAPS_NOTFOUND-303) {
12504 printf("\tName %s not found in attribute map of capsConnect!!!!\n", masterName[i]);
12505 continue;
12506 } else if (status != CAPS_SUCCESS0) return status;
12507
12508 if (feaDataMaster->connectIndex != attrIndex) continue;
12509
12510 break;
12511 }
12512
12513 if (i >= numMasterName) continue;
12514
12515 // We have a potential master at this point
12516
12517 dist = dist_DoubleVal(mesh->node[masterIndex].xyz, mesh->node[slaveIndex].xyz);
12518
12519 //printf("dist = %f (radius = %f), masterIndex %d\n", dist, searchRadius, masterIndex);
12520
12521 if ( dist > searchRadius) continue;
12522 AIM_NOTNULL(glueDist, aimInfo, status){ if (glueDist == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 12522, __func__, 1, "%s == NULL!", "glueDist"
); goto cleanup; } }
;
12523
12524 status = array_maxDoubleValue(maxNumMaster, glueDist, &distIndex, &maxDist);
12525 if (status != CAPS_SUCCESS0) goto cleanup;
12526
12527 //printf("dist = %f, maxdist = %e (index = %d)\n", dist, maxDist, distIndex);
12528
12529 if (dist < maxDist) {
12530 glueDist[distIndex] = dist;
12531 glueConn[distIndex] = masterIndex;
12532 }
12533 } // End of master loop
12534
12535 // How many masters were found
12536 numMaster = 0;
12537 for (i = 0; i < maxNumMaster; i++) {
12538 if (glueDist[i] > searchRadius) continue; // Nothing was every set
12539 numMaster += 1;
12540 }
12541
12542 if (numMaster <= 0) {
12543 printf("\tWarning: no masters were found for slave node (id = %d, slave name = %s)!\n", mesh->node[slaveIndex].nodeID, slaveName);
12544 } else {
12545 AIM_NOTNULL(glueConn, aimInfo, status){ if (glueConn == ((void*)0)) { status = -307; aim_status(aimInfo
, status, "feaUtils.c", 12545, __func__, 1, "%s == NULL!", "glueConn"
); goto cleanup; } }
;
12546 // Create and set connections
12547 status = fea_setConnection(slaveName,
12548 RigidBodyInterpolate,
12549 connectionID,
12550 mesh->numElement,
12551 dofDependent,
12552 0.0,
12553 0.0,
12554 0.0,
12555 0,
12556 0,
12557 mesh->node[slaveIndex].nodeID,
12558 masterWeight,
12559 masterComponent,
12560 numMaster, glueConn,
12561 numConnect,feaConnect);
12562 if (status != CAPS_SUCCESS0) goto cleanup;
12563 }
12564//
12565// *numConnect += 1;
12566//
12567// (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),*numConnect*sizeof(feaConnectionStruct));
12568// if ((*feaConnect) == NULL) {
12569// *numConnect = 0;
12570// status = EGADS_MALLOC;
12571// goto cleanup;
12572// }
12573//
12574// status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect-1]);
12575// if (status != CAPS_SUCCESS) goto cleanup;
12576//
12577// (*feaConnect)[*numConnect-1].name = (char *) EG_alloc((strlen(slaveName) + 1)*sizeof(char));
12578// if ((*feaConnect)[*numConnect-1].name == NULL) {
12579// status = EGADS_MALLOC;
12580// goto cleanup;
12581// }
12582//
12583// memcpy((*feaConnect)[*numConnect-1].name, slaveName, strlen(slaveName)*sizeof(char));
12584// (*feaConnect)[*numConnect-1].name[strlen(slaveName)] = '\0';
12585//
12586// (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index
12587// (*feaConnect)[*numConnect-1].connectionType = connectionType;
12588//
12589// (*feaConnect)[*numConnect-1].elementID = *numConnect + mesh->numElement;
12590//
12591// (*feaConnect)[*numConnect-1].dofDependent = dofDependent;
12592//
12593// (*feaConnect)[*numConnect-1].connectivity[1] = mesh->node[slaveIndex].nodeID; // Dependent
12594// (*feaConnect)[*numConnect-1].numMaster = numMaster; // Independent
12595//
12596// (*feaConnect)[*numConnect-1].masterIDSet = (int *) EG_alloc(numMaster*sizeof(int)); // [numMaster]
12597// if ((*feaConnect)[*numConnect-1].masterIDSet == NULL) {
12598// status = EGADS_MALLOC;
12599// goto cleanup;
12600// }
12601// (*feaConnect)[*numConnect-1].masterWeighting = (double *) EG_alloc(numMaster*sizeof(double));; // [numMaster]
12602// if ((*feaConnect)[*numConnect-1].masterWeighting == NULL) {
12603// status = EGADS_MALLOC;
12604// goto cleanup;
12605// }
12606//
12607// (*feaConnect)[*numConnect-1].masterComponent =(int *) EG_alloc(numMaster*sizeof(int));; // [numMaster]
12608// if ((*feaConnect)[*numConnect-1].masterComponent == NULL) {
12609// status = EGADS_MALLOC;
12610// goto cleanup;
12611// }
12612//
12613// printf("\tMasters (%d)", numMaster);
12614//
12615// // Master values;
12616// numMaster = 0;
12617// for (i = 0; i < maxNumMaster; i++) {
12618// if (glueDist[i] > searchRadius) continue; // Nothing was every set
12619// printf(" %d(%d)", mesh->node[glueConn[i]].nodeID, glueConn[i]);
12620// (*feaConnect)[*numConnect-1].masterIDSet[numMaster] = mesh->node[glueConn[i]].nodeID;
12621// (*feaConnect)[*numConnect-1].masterWeighting[numMaster] = masterWeight;
12622// (*feaConnect)[*numConnect-1].masterComponent[numMaster] = masterComponent;
12623// numMaster += 1;
12624// }
12625// printf("\n");
12626
12627 } // End of slave loop
12628
12629 cleanup:
12630 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_glueMesh, status = %d\n", status);
12631
12632 if (glueDist != NULL((void*)0)) EG_free(glueDist);
12633 if (glueConn != NULL((void*)0)) EG_free(glueConn);
12634
12635 return status;
12636}
12637
12638//int fea_glueMesh2(meshStruct *meshIn,
12639//
12640// mapAttrToIndexStruct *attrMap) {
12641//
12642// // Input parameters
12643// int numGlue=5;
12644// double exactTol=1E-9;
12645// double radiusOfInfluence = 0.1;//1E-3;
12646// int weigthing = 1; // 1=linear
12647//
12648// int status;
12649// int i, j, k, m, masterIndex, slaveIndex, distIndex;
12650// int found;
12651//
12652// int numMesh;
12653// meshStruct *mesh, *master, *slave, *search;
12654//
12655// int **glueConn=NULL;
12656// double **glueDist=NULL;
12657//
12658// double *tempDist=NULL;
12659// int *tempGlue=NULL;
12660// int numNode = 0;
12661// int *meshIndexStart=NULL;
12662//
12663// double dist, maxDist;
12664//
12665// feaMeshDataStruct *feaData;
12666//
12667//// maps from nodeID to mesh->node index
12668//// mesh_nodeID2Array(nasMesh, &n2a);
12669//
12670// printf("Welcome to glueing!\n");
12671// numMesh = meshIn->numReferenceMesh;
12672// mesh = meshIn->referenceMesh;
12673//
12674// printf("Start with allocation!\n");
12675// status = array_allocIntegerVector(numMesh, 0, &meshIndexStart);
12676// if (status != CAPS_SUCCESS) goto cleanup;
12677//
12678// // Determine number of nodes in reference meshes - Remember capsIgnore may have already been applied
12679// for (i=0; i < numMesh; i++) {
12680// meshIndexStart[i] = numNode;
12681// numNode += mesh[i].numNode;
12682// }
12683//
12684// if (numNode != meshIn->numNode) {
12685// printf("Inconsistent number of nodes determined!");
12686// status = CAPS_MISMATCH;
12687// goto cleanup;
12688// }
12689//
12690// // glueConn structure:
12691// // glueConn[row][col] where [row] is node index and
12692// // [row][0] : 1=master, 0=slave, -1=unused
12693// // [row][1:numGlue+1] : nearest node indices, -1=unused
12694// status = array_allocIntegerMatrix(numNode, numGlue+1, -1, &glueConn);
12695// if (status != CAPS_SUCCESS) goto cleanup;
12696//
12697// // glueDist structure:
12698// // glueDist[row][col] where [row] is node index and
12699// // [row][0:numGlue] : distance to nearest node indices found in glueConn[row][1:numGlue+1]
12700// status = array_allocDoubleMatrix(numNode, numGlue, -1, &glueDist);
12701// if (status != CAPS_SUCCESS) goto cleanup;
12702//
12703// status = array_allocIntegerVector(numGlue, 0, &tempGlue);
12704// if (status != CAPS_SUCCESS) goto cleanup;
12705//
12706// status = array_allocDoubleVector(numGlue, 0, &tempDist);
12707// if (status != CAPS_SUCCESS) goto cleanup;
12708//
12709// printf("Done with allocation!\n");
12710//
12711// // Lets mark all slaves
12712// //
12713//
12714// int attrIndex;
12715// int numSlave=1;
12716// char slaveName[] = "slave";
12717// int numMasterName;
12718// char **masterName;
12719//
12720// for (i = 0; i < numNode; i++) {
12721//
12722// feaData = (feaMeshDataStruct *) meshIn->node[i].analysisData;
12723//
12724// for (j = 0; j < numSlave; j++) {
12725// status = get_mapAttrToIndexIndex(attrMap, (const char *) slaveName, &attrIndex);
12726// if (status == CAPS_NOTFOUND) {
12727// printf("\tName %s not found in attribute map of capsConnect!!!!\n", slaveName);
12728// continue;
12729// } else if (status != CAPS_SUCCESS) return status;
12730//
12731//
12732// if (feaData->connectIndex != attrIndex) continue;
12733//
12734// glueConn[i][0] = 0;
12735// break;
12736// }
12737//
12738// if (glueConn[i][0] != 0) continue;
12739//
12740// status = string_toStringDynamicArray('["master"]', &numMasterName, &masterName);
12741// if (status != CAPS_SUCCESS); goto cleanup;
12742//
12743// for (k = 0; k < numNode; k++) {
12744//
12745// if (i == k) continue;
12746// for (m = 0; m < numMasterName; m++) {
12747//
12748// }
12749// }
12750//
12751//
12752// (void) string_freeArray(numMasterName, &masterName);
12753// masterName = NULL;
12754// numMasterName = 0;
12755// }
12756//
12757//
12758// // for (i = 0; i < numMesh; i++) { // THIS IS MOSTLY correct - error in master slave relation of RBE3 elements
12759//// master = &mesh[i];
12760////
12761////// printf("Master Mesh %d (of %d)\n", i, numMesh);
12762//// //Exhaustive search
12763//// for (masterIndex = 0; masterIndex < master->numNode; masterIndex++) {
12764////
12765////// printf("master index %d (of %d)\n", masterIndex, master->numNode);
12766//// // Slaves may be promoted to masters, but cannot be slaves to multiple masters
12767//// //if (glueConn[masterIndex+meshIndexStart[masterIndex]][0] != 0) continue;
12768////
12769//// status = array_setDoubleVectorValue(numGlue, 1E9, &tempDist);
12770//// if (status != CAPS_SUCCESS) goto cleanup;
12771////
12772//// status = array_setIntegerVectorValue(numGlue, -1, &tempGlue);
12773//// if (status != CAPS_SUCCESS) goto cleanup;
12774////
12775//// for (j = 0; j < numMesh; j++) {
12776////
12777//// if (i == j) continue;
12778////
12779//// slave = &mesh[j];
12780////
12781//// for (slaveIndex = 0; slaveIndex < slave->numNode; slaveIndex++) {
12782////
12783//// // Slaves cannot have multiple masters - FALSE
12784//// if (glueConn[slaveIndex+meshIndexStart[j]][0] == 0) continue;
12785////
12786//// // Make sure master slave relation doesn't already exist
12787//// found = (int) false;
12788//// for (k =1; k < numGlue+1; k++) {
12789//// if (masterIndex+meshIndexStart[i] == glueConn[slaveIndex+meshIndexStart[j]][k]){
12790//// found = (int) true;
12791//// break;
12792//// }
12793//// }
12794////
12795//// if (found == (int) true) continue;
12796////
12797////// printf("glueConn %d\n", glueConn[slaveIndex+meshIndexStart[j]][0]);
12798////
12799//// dist = dist_DoubleVal(master->node[masterIndex].xyz, slave->node[slaveIndex].xyz);
12800////
12801////// printf("dist = %f (radius = %f)\n", dist, radiusOfInfluence);
12802////
12803//// if ( dist > radiusOfInfluence) continue;
12804////
12805//// status = array_maxDoubleValue(numGlue, tempDist, &distIndex, &maxDist);
12806//// if (status != CAPS_SUCCESS) goto cleanup;
12807////
12808//// //printf("dist = %f, maxdist = %e (index = %d)\n", dist, maxDist, distIndex);
12809////
12810//// if (dist < maxDist) {
12811//// tempDist[distIndex] = dist;
12812//// tempGlue[distIndex] = slaveIndex + meshIndexStart[j] ;
12813//// }
12814//// }
12815//// }
12816////
12817//// if (tempDist[0] > radiusOfInfluence) continue; // Nothing was every set
12818////
12819//// // glueConn structure:
12820//// // glueConn[row][col] where [row] is node index and
12821//// // [row][0] : 1=master, 0=slave, -1=unused
12822//// // [row][1:numGlue+1] : nearest node indices, -1=unused
12823////
12824//// // glueDist[row][col] where [row] is node index and
12825//// // [row][0:numGlue] : distance to nearest node indices found in glueConn[row][1:numGlue+1]
12826////
12827//// glueConn[masterIndex+meshIndexStart[i]][0] = 1; //Mark as Master
12828//// distIndex = 0;
12829//// for (j = 0; j < numGlue; j++) {
12830//// if (tempDist[j] > radiusOfInfluence) continue; // Nothing was every set
12831////
12832//// glueDist[masterIndex+meshIndexStart[i]][distIndex] = tempDist[j]; // Distances for a master
12833//// glueConn[masterIndex+meshIndexStart[i]][distIndex+1] = tempGlue[j]; // Glue connections/slaves for a master
12834////
12835//// // Mark the masters slave's as slaves - A slave can become a master to another slave,
12836//// // but it can not be a slave to another master
12837//// if (glueConn[tempGlue[j]][0] < 0) glueConn[tempGlue[j]][0] = 0;
12838////
12839//// distIndex +=1;
12840//// }
12841////
12842//// printf("Set %d : %d: ",masterIndex+meshIndexStart[i], glueConn[masterIndex+meshIndexStart[i]][0]);
12843//// for(j = 0; j < numGlue; j++) {
12844//// printf("%d ", glueConn[masterIndex+meshIndexStart[i]][j+1]);
12845//// }
12846//// printf("\n");
12847//// }
12848//// }
12849////
12850//// for (i = 0; i < numNode;i++) {
12851//// if (glueConn[i][0] < 0) continue;
12852//// printf("Node %d : %d : ", i, glueConn[i][0]);
12853//// for(j = 0; j < numGlue; j++) {
12854////// printf("%d (%.2f)", glueConn[i][j+1], glueDist[i][j]);
12855//// printf("%d ", glueConn[i][j+1]);
12856//// }
12857//// printf("\n");
12858//// }
12859//// // Finished getting all my glue
12860//
12861// cleanup:
12862// if (status != CAPS_SUCCESS) printf("\tPremature exit in fea_glueMesh, status = %d\n", status);
12863//
12864// if (tempDist != NULL) EG_free(tempDist);
12865// if (tempGlue != NULL) EG_free(tempGlue);
12866// if (meshIndexStart != NULL) EG_free(meshIndexStart);
12867//
12868// if (glueConn != NULL) (void) array_freeIntegerMatrix(numNode, numGlue, &glueConn);
12869//
12870// if (glueDist != NULL) (void) array_freeDoubleMatrix(numNode, numGlue, &glueDist);
12871//
12872// (void) string_freeArray(numMasterName, &masterName);
12873// masterName = NULL;
12874//
12875// return status;
12876//}
12877
12878// Create a default analysis structure based on previous inputs
12879int fea_createDefaultAnalysis(void *aimInfo, feaProblemStruct *feaProblem, const char *analysisType) {
12880
12881 int status;
12882 int i;
12883
12884 capsTuple *tupleVal;
12885
12886 char *json=NULL((void*)0);
12887 int maxSize=2048;
12888
12889 if (feaProblem == NULL((void*)0)) return CAPS_NULLVALUE-307;
12890
12891 if (feaProblem->numAnalysis != 0 || feaProblem->feaAnalysis != NULL((void*)0)) {
12892 // Destroy our analysis structures coming in if aren't 0 and NULL already
12893 for (i = 0; i < feaProblem->numAnalysis; i++) {
12894 status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
12895 if (status != CAPS_SUCCESS0) return status;
12896 }
12897
12898 if (feaProblem->feaAnalysis != NULL((void*)0)) EG_free(feaProblem->feaAnalysis);
12899 feaProblem->feaAnalysis = NULL((void*)0);
12900 feaProblem->numAnalysis = 0;
12901 }
12902
12903 tupleVal = (capsTuple *) EG_alloc(1*sizeof(capsTuple));
12904 if (tupleVal == NULL((void*)0)) {
12905 status = EGADS_MALLOC-4;
12906 goto cleanup;
12907 }
12908 tupleVal[0].name = NULL((void*)0);
12909 tupleVal[0].value = NULL((void*)0);
12910
12911 json = (char *) EG_alloc(maxSize*sizeof(char));
12912 if (json == NULL((void*)0)) {
12913 status = EGADS_MALLOC-4;
12914 goto cleanup;
12915 }
12916
12917 strcpy(json,"{\"analysisType\":\"");
12918 if (strcasecmp(analysisType, "Optimization") == 0) strcat(json,"Static");
12919 else strcat(json, analysisType);
12920 strcat(json,"\"");
12921
12922 if (feaProblem->numLoad != 0) {
12923 strcat(json,",\"analysisLoad\":[");
12924 for (i = 0; i < feaProblem->numLoad; i++) {
12925 if (i != 0) strcat(json,",");
12926 strcat(json,"\"");
12927 strcat(json,feaProblem->feaLoad[i].name);
12928 strcat(json,"\"");
12929 }
12930 strcat(json, "]");
12931 }
12932
12933 if (feaProblem->numConstraint != 0) {
12934 strcat(json,",\"analysisConstraint\":[");
12935 for (i = 0; i < feaProblem->numConstraint; i++) {
12936 if (i != 0) strcat(json,",");
12937 strcat(json,"\"");
12938 strcat(json,feaProblem->feaConstraint[i].name);
12939 strcat(json,"\"");
12940 }
12941 strcat(json, "]");
12942 }
12943
12944 if (feaProblem->numSupport != 0) {
12945 strcat(json,",\"analysisSupport\":[");
12946 for (i = 0; i < feaProblem->numSupport; i++) {
12947 if (i != 0) strcat(json,",");
12948 strcat(json,"\"");
12949 strcat(json,feaProblem->feaSupport[i].name);
12950 strcat(json,"\"");
12951 }
12952 strcat(json, "]");
12953 }
12954
12955 if (feaProblem->numDesignConstraint != 0) {
12956 strcat(json,",\"analysisDesignConstraint\":[");
12957 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
12958 if (i != 0) strcat(json,",");
12959 strcat(json,"\"");
12960 strcat(json,feaProblem->feaDesignConstraint[i].name);
12961 strcat(json,"\"");
12962 }
12963 strcat(json, "]");
12964 }
12965
12966 strcat(json,"}");
12967
12968 tupleVal[0].name = EG_strdup("Default");
12969 tupleVal[0].value = json;
12970
12971 //printf("Default analysis tuple - %s\n", tupleVal[0].value);
12972
12973 status = fea_getAnalysis(aimInfo,
12974 1,
12975 tupleVal,
12976 feaProblem);
12977 if (status != CAPS_SUCCESS0) goto cleanup;
12978
12979// feaProblem->numAnalysis = 1;
12980// feaProblem->feaAnalysis = (feaAnalysisStruct *) EG_alloc(feaProblem->numAnalysis*sizeof(feaAnalysisStruct));
12981// if (feaProblem->feaAnalysis == NULL) return EGADS_MALLOC;
12982//
12983// feaAnalysis=&feaProblem->feaAnalysis[0];
12984// status = initiate_feaAnalysisStruct(feaAnalysis);
12985// if (status != CAPS_SUCCESS) return status;
12986//
12987//
12988// feaAnalysis->name = (char *) EG_alloc(((strlen(name)) + 1)*sizeof(char));
12989// if (feaProblem->feaAnalysis->name == NULL) return EGADS_MALLOC;
12990//
12991// memcpy(feaAnalysis->name, name, strlen(name)*sizeof(char));
12992// feaAnalysis->name[strlen(name)] = '\0';
12993//
12994// feaAnalysis->analysisID = 1;
12995
12996
12997 status = CAPS_SUCCESS0;
12998 goto cleanup;
12999
13000 cleanup:
13001 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_createDefaultAnalysis, status = %d\n", status);
13002
13003 if (tupleVal != NULL((void*)0)) {
13004 if (tupleVal[0].name != NULL((void*)0)) EG_free(tupleVal[0].name);
13005 if (tupleVal[0].value != NULL((void*)0)) EG_free(tupleVal[0].value);
13006 EG_free(tupleVal);
13007 }
13008
13009 return status;
13010}
13011
13012// Setup the default flutter velocities if not specified
13013int fea_defaultFlutterVelocity(feaAnalysisStruct *feaAnalysis) {
13014 int i;
13015
13016 int defaultNum = 23;
13017 double velocity=0, dv=1, vmin=0, vmax=0;
13018
13019 if (feaAnalysis->numFlutterVel == 0) {
13020 AIM_FREE(feaAnalysis->flutterVel){ EG_free(feaAnalysis->flutterVel); feaAnalysis->flutterVel
= ((void*)0); }
;
13021
13022 feaAnalysis->numFlutterVel = defaultNum;
13023 feaAnalysis->flutterVel = EG_alloc(feaAnalysis->numFlutterVel*sizeof(double));
13024 if (feaAnalysis->flutterVel == NULL((void*)0)) {
13025 return EGADS_MALLOC-4;
13026 }
13027
13028 velocity = sqrt(2*feaAnalysis->dynamicPressure/feaAnalysis->density);
13029 vmin = velocity / 2.0;
13030 vmax = 2 * velocity;
13031 dv = (vmax - vmin) / (double) (feaAnalysis->numFlutterVel-3);
13032
13033 for (i = 0; i < feaAnalysis->numFlutterVel-2; i++) {
13034 feaAnalysis->flutterVel[i+1] = vmin + (double) i * dv;
13035 }
13036
13037 feaAnalysis->flutterVel[0] = velocity/10;
13038 feaAnalysis->flutterVel[feaAnalysis->numFlutterVel-1] = velocity*10;
13039 }
13040
13041 return CAPS_SUCCESS0;
13042}