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-15-101625-36191-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
643 // Combine fea meshes into a single mesh for the problem
644 status = mesh_combineMeshStruct(*numMesh,
645 (*feaMesh),
646 &feaProblem->feaMesh);
647 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 647
, __func__, 0); goto cleanup; }
;
648
649 if (*numMesh > 1) {
650 printf("\tCombined Number of nodal coordinates = %d\n", feaProblem->feaMesh.numNode);
651 printf("\tCombined Number of elements = %d\n", feaProblem->feaMesh.numElement);
652 printf("\tCombined Elemental Nodes = %d\n", feaProblem->feaMesh.meshQuickRef.numNode);
653 printf("\tCombined Elemental Rods = %d\n", feaProblem->feaMesh.meshQuickRef.numLine);
654 printf("\tCombined Elemental Tria3 = %d\n", feaProblem->feaMesh.meshQuickRef.numTriangle);
655 printf("\tCombined Elemental Quad4 = %d\n", feaProblem->feaMesh.meshQuickRef.numQuadrilateral);
656 }
657
658 // Set reference meshes
659 feaProblem->feaMesh.numReferenceMesh = *numMesh;
660 feaProblem->feaMesh.referenceMesh = (meshStruct *) EG_alloc(*numMesh*sizeof(meshStruct));
661 if (feaProblem->feaMesh.referenceMesh == NULL((void*)0)) {
662 status = EGADS_MALLOC-4;
663 goto cleanup;
664 }
665
666 for (body = 0; body < *numMesh; body++) {
667 feaProblem->feaMesh.referenceMesh[body] = (*feaMesh)[body];
668 }
669 }
670 }
671 status = CAPS_SUCCESS0;
672
673cleanup:
674
675 AIM_FREE(feaMeshes){ EG_free(feaMeshes); feaMeshes = ((void*)0); };
676 AIM_FREE(feaMeshList){ EG_free(feaMeshList); feaMeshList = ((void*)0); };
677
678 (void ) destroy_mapAttrToIndexStruct(&coordSystemMap);
679
680 (void ) destroy_mapAttrToIndexStruct(&attrMapTemp1);
681 (void ) destroy_mapAttrToIndexStruct(&attrMapTemp2);
682
683 return status;
684}
685
686// Convert an EGADS body to a boundary element model, modified by Ryan Durscher (AFRL)
687// from code originally written by John Dannenhoffer @ Syracuse University, patterned after code
688// written by Bob Haimes @ MIT
689int fea_bodyToBEM(void *aimInfo, // (in) AIM structure
690 ego ebody, // (in) EGADS Body
691 double paramTess[3], // (in) Tessellation parameters
692 int edgePointMin, // (in) minimum points along any Edge
693 int edgePointMax, // (in) maximum points along any Edge
694 int quadMesh, // (in) 0 - only do tris-for faces, 1 - mixed quad/tri, 2 - regularized quads
695 mapAttrToIndexStruct *attrMap, // (in) map from CAPSGroup names to indexes
696 mapAttrToIndexStruct *coordSystemMap,// (in) map from CoordSystem names to indexes
697 mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes
698 mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes
699 mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes
700 mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes
701 mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes
702 mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes
703 meshStruct *feaMesh) // (out) FEA mesh structure
704{
705 int status = 0; // Function return status
706
707 int isNodeBody;
708 int i, j, k, face, edge, patch; // Indexing
709 double scale;
710
711 // Body entities
712 int numNode = 0, numEdge = 0, numFace = 0;
713 ego *enodes=NULL((void*)0), *eedges=NULL((void*)0), *efaces=NULL((void*)0);
714
715 int atype, alen; // EGADS return variables
716 const int *ints;
717 const double *reals;
718 const char *string;
719
720 // Meshing
721 int numPoint = 0, numTri = 0;
722 const int *triConn = NULL((void*)0), *triNeighbor = NULL((void*)0); // Triangle
723
724 int numPatch = 0; // Patching
725 int n1, n2, *qints = NULL((void*)0);
726
727 int gID; // Global id
728
729 const double *xyz, *uv;
730
731 const int *ptype = NULL((void*)0), *pindex = NULL((void*)0), *pvindex = NULL((void*)0), *pbounds = NULL((void*)0);
732
733 int periodic, nchange, oclass, mtype, nchild, nchild2, *senses;
734
735 // Edge point distributions
736 int *points=NULL((void*)0), *isouth=NULL((void*)0), *ieast=NULL((void*)0), *inorth=NULL((void*)0), *iwest=NULL((void*)0);
737 double params[3], bbox[6], size, range[2], arclen, data[4], eval[18], eval2[18];
738 double *rpos=NULL((void*)0);
739 ego eref, *echilds, *echilds2, eloop, tempBody, topObj, prev, next;
740
741 int bodySubType = 0; // Body classification
742
743 int pointType, pointTopoIndex;
744 double xyzPoint[3], xyzNode[3];
745
746 // Attributues
747 const char *attrName;
748 int attrIndex, coordSystemIndex, loadIndex;
749
750 int numElement = 0; // Number of elements
751 int coordID = 0; // Default coordinate id for mesh
752
753 feaMeshDataStruct *feaData;
754
755 meshElementStruct *tempElement = NULL((void*)0);
756
757 // In case our geometry has ignores
758 int ignoreFound = (int) false0;
759
760 // ---------------------------------------------------------------
761
762 printf("Creating FEA BEM\n");
763
764 // Check for contradiction where quading is requested but dissabled on the body
765 if (quadMesh == (int)true1) {
766 status = EG_attributeRet(ebody, ".qParams", &atype, &alen, &ints, &reals, &string);
767 if (status == EGADS_SUCCESS0 && (atype != ATTRREAL2 || (atype == ATTRREAL2 && reals[0] <= 0 ))) {
768 printf("\tQuading on all faces disabled with .qParams attribute on the body\n");
769 quadMesh = (int) false0;
770 }
771 }
772
773 // Get number of Nodes, Edges, and Faces in ebody
774 status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes);
775 if (status < EGADS_SUCCESS0) goto cleanup;
776
777 status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges);
778 if (status != EGADS_SUCCESS0) goto cleanup;
779
780 status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces);
781 if (status < EGADS_SUCCESS0) goto cleanup;
782
783 // What type of BODY do we have?
784 isNodeBody = aim_isNodeBody(ebody, xyzNode);
785 if (isNodeBody < EGADS_SUCCESS0) goto cleanup;
786 if (isNodeBody == EGADS_SUCCESS0) {
787 // all attributes are on the body rather than the node for a node body
788 enodes[0] = ebody;
789 }
790
791 // Determine the nominal number of points along each Edge
792 points = (int *) EG_alloc((numEdge+1) *sizeof(int ));
793 rpos = (double *) EG_alloc((edgePointMax)*sizeof(double));
794 if (points == NULL((void*)0) || rpos == NULL((void*)0)) {
795 status = EGADS_MALLOC-4;
796 printf("\tError in fea_bodyToBEM: EG_alloc\n");
797 goto cleanup;
798 }
799
800 status = EG_getBoundingBox(ebody, bbox);
801 if (status < EGADS_SUCCESS0) {
802 printf("\tError in fea_bodyToBEM: EG_getBoundingBox\n");
803 goto cleanup;
804 }
805
806 size = sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[0])
807 +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])
808 +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]));
809
810 params[0] = paramTess[0] * size;
811 params[1] = paramTess[1] * size;
812 params[2] = paramTess[2];
813
814 status = EG_attributeAdd(ebody, ".tParam", ATTRREAL2, 3, NULL((void*)0), params, NULL((void*)0));
815 if (status < EGADS_SUCCESS0) {
816 printf("\tError in fea_bodyToBEM: EG_attributeAdd\n");
817 goto cleanup;
818 }
819
820 if (isNodeBody == EGADS_SUCCESS0)
821 params[0] = 1; // does not matter but can't be zero
822
823 if (params[0] <= 0.0) {
824 printf("\tError in fea_bodyToBEM: params[0] = %f must be a positive number!\n", params[0]);
825 status = CAPS_BADVALUE-311;
826 goto cleanup;
827 }
828
829 for (i = 1; i <= numEdge; i++) {
830 status = EG_getRange(eedges[i-1], range, &periodic);
831 if (status < EGADS_SUCCESS0) {
832 printf("\tError in fea_bodyToBEM: EG_getRange\n");
833 goto cleanup;
834 }
835
836 status = EG_arcLength(eedges[i-1], range[0], range[1], &arclen);
837 if (status < EGADS_SUCCESS0) {
838 printf("\tError in fea_bodyToBEM: EG_arcLength\n");
839 goto cleanup;
840 }
841
842 //points[i] = MIN(MAX(MAX(edgePointMin,2), (int)(1+arclen/params[0])), edgePointMax);
843 points[i] = (int) min_DoubleVal(
844 max_DoubleVal(
845 max_DoubleVal( (double) edgePointMin, 2.0),
846 (double) (1+arclen/params[0])),
847 (double) edgePointMax);
848 }
849
850
851 // make arrays for "opposite" sides of four-sided Faces (with only one loop)
852 isouth = (int *) EG_alloc((numFace+1)*sizeof(int));
853 ieast = (int *) EG_alloc((numFace+1)*sizeof(int));
854 inorth = (int *) EG_alloc((numFace+1)*sizeof(int));
855 iwest = (int *) EG_alloc((numFace+1)*sizeof(int));
856
857 if (isouth == NULL((void*)0) ||
858 ieast == NULL((void*)0) ||
859 inorth == NULL((void*)0) ||
860 iwest == NULL((void*)0) ) {
861
862 status = EGADS_MALLOC-4;
863 printf("\tError in fea_bodyToBEM: EG_alloc\n");
864 goto cleanup;
865 }
866
867 for (i = 1; i <= numFace; i++) {
868 isouth[i] = 0;
869 ieast [i] = 0;
870 inorth[i] = 0;
871 iwest [i] = 0;
872
873 // nothing to check if quading isn't requested
874 if (quadMesh == (int) false0)
875 continue;
876
877 // check if quading is disabled with .qParams
878 status = EG_attributeRet(efaces[i-1], ".qParams", &atype, &alen, &ints, &reals, &string);
879 if (status == EGADS_SUCCESS0 && (atype != ATTRREAL2 || (atype == ATTRREAL2 && reals[0] <= 0 ))) {
880 printf("\tFace %d quading disabled with attribute .qParams\n", i);
881 continue;
882 }
883
884 // quading only works with one loop
885 status = EG_getTopology(efaces[i-1], &eref, &oclass, &mtype, data, &nchild, &echilds, &senses);
886 if (status < EGADS_SUCCESS0) goto cleanup;
887
888 if (nchild != 1) continue;
889
890 // quading only works if the loop has 4 edges
891 eloop = echilds[0];
892 status = EG_getTopology(eloop, &eref, &oclass, &mtype, data, &nchild, &echilds, &senses);
893 if (status < EGADS_SUCCESS0) goto cleanup;
894
895 if (nchild != 4) continue;
896
897 // Check to see if two "straight" edges next to each other are parallel - Don't Quad if so
898 for (j = 0; j < 4; j++) {
899
900 status = EG_getTopology(echilds[j], &eref, &oclass, &mtype, data, &nchild2, &echilds2, &senses);
901 if (mtype == DEGENERATE5) { status = EGADS_DEGEN-24; break; }
902 if (status < EGADS_SUCCESS0) goto cleanup;
903
904 if (j < 3) k = j+1;
905 else k = 0;
906
907 status = EG_getTopology(echilds[k], &eref, &oclass, &mtype, range, &nchild2, &echilds2, &senses);
908 if (mtype == DEGENERATE5) { status = EGADS_DEGEN-24; break; }
909 if (status < EGADS_SUCCESS0) goto cleanup;
910
911 status = EG_evaluate(echilds[j], data, eval);
912 if (status < EGADS_SUCCESS0) goto cleanup;
913
914 status = EG_evaluate(echilds[k], range, eval2);
915 if (status < EGADS_SUCCESS0) goto cleanup;
916
917 scale = dot_DoubleVal(&eval[3], &eval[3]);
918 eval[3] /= scale;
919 eval[4] /= scale;
920 eval[5] /= scale;
921
922 scale = dot_DoubleVal(&eval2[3], &eval2[3]);
923 eval2[3] /= scale;
924 eval2[4] /= scale;
925 eval2[5] /= scale;
926
927 if (fabs(fabs(dot_DoubleVal(&eval[3], &eval2[3])) - 1) < 1E-6) {
928 status = EGADS_OUTSIDE1;
929 break;
930 }
931 }
932
933 if (status == EGADS_OUTSIDE1) {
934 if (quadMesh == (int)true1) {
935 printf("Face %d has parallel edges - not quading\n", i);
936 }
937 continue;
938 }
939
940 if (status == EGADS_DEGEN-24) {
941 if (quadMesh == (int)true1) {
942 printf("Face %d has a degenerate edge - not quading\n", i);
943 }
944 continue;
945 }
946
947 isouth[i] = status = EG_indexBodyTopo(ebody, echilds[0]);
948 if (status < EGADS_SUCCESS0) goto cleanup;
949
950 ieast[i] = status = EG_indexBodyTopo(ebody, echilds[1]);
951 if (status < EGADS_SUCCESS0) goto cleanup;
952
953 inorth[i] = status = EG_indexBodyTopo(ebody, echilds[2]);
954 if (status < EGADS_SUCCESS0) goto cleanup;
955
956 iwest[i] = status = EG_indexBodyTopo(ebody, echilds[3]);
957 if (status < EGADS_SUCCESS0) goto cleanup;
958 }
959
960 // make "opposite" sides of four-sided Faces (with only one loop) match
961 nchange = 1;
962 for (i = 0; i < 20; i++) {
963 nchange = 0;
964
965 for (face = 1; face <= numFace; face++) {
966 if (isouth[face] <= 0 || ieast[face] <= 0 ||
967 inorth[face] <= 0 || iwest[face] <= 0 ) continue;
968
969 if (points[iwest[face]] < points[ieast[face]]) {
970 points[iwest[face]] = points[ieast[face]];
971 nchange++;
972
973 } else if (points[ieast[face]] < points[iwest[face]]) {
974 points[ieast[face]] = points[iwest[face]];
975 nchange++;
976 }
977
978 if (points[isouth[face]] < points[inorth[face]]) {
979 points[isouth[face]] = points[inorth[face]];
980 nchange++;
981 } else if (points[inorth[face]] < points[isouth[face]]) {
982 points[inorth[face]] = points[isouth[face]];
983 nchange++;
984 }
985 }
986 if (nchange == 0) break;
987 }
988 if (nchange > 0) {
989 printf("Exceeded number of tries making \"opposite\" sides of four-sided Faces (with only one loop) match\n");
990 status = CAPS_MISMATCH-324;
991 goto cleanup;
992 }
993
994 // mark the Edges with points[iedge] evenly-spaced points
995 for (edge = 1; edge <= numEdge; edge++) {
996 for (i = 1; i < points[edge]-1; i++) {
997 rpos[i-1] = (double)(i) / (double)(points[edge]-1);
998 }
999
1000 if (points[edge] == 2) {
1001 i = 0;
1002 status = EG_attributeAdd(eedges[edge-1], ".rPos", ATTRINT1, 1, &i, NULL((void*)0), NULL((void*)0));
1003 if (status < EGADS_SUCCESS0) goto cleanup;
1004
1005 } else {
1006 status = EG_attributeAdd(eedges[edge-1], ".rPos", ATTRREAL2, points[edge]-2, NULL((void*)0), rpos, NULL((void*)0));
1007 if (status < EGADS_SUCCESS0) goto cleanup;
1008 }
1009 }
1010
1011 // Make tessellation
1012 status = EG_makeTessBody(ebody, params, &feaMesh->egadsTess);
1013 if (status != EGADS_SUCCESS0) {
1014 printf("\tError in fea_bodyToBEM: EG_makeTessBody\n");
1015 goto cleanup;
1016 }
1017
1018 // Make Quads on each four-sided Face
1019 params[0] = 0;
1020 params[1] = 0;
1021 params[2] = 0;
1022
1023 // If making quads on faces lets setup an array to keep track of which faces have been quaded.
1024 if (quadMesh == (int)true1) {
1025 if( numFace > 0) {
1026 AIM_ALLOC(qints, numFace, int, aimInfo, status){ if (qints != ((void*)0)) { status = -4; aim_status(aimInfo,
status, "feaUtils.c", 1026, __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"
, 1026, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "qints"
, memorysize, "int"); goto cleanup; } }
;
1027 }
1028 // Set default to 0
1029 for (face = 0; face < numFace; face++) qints[face] = 0;
1030 }
1031
1032 if (quadMesh == (int)true1) {
1033 for (face = 1; face <= numFace; face++) {
1034 if (iwest[face] <= 0) continue;
1035
1036 status = EG_makeQuads(feaMesh->egadsTess, params, face);
1037 if (status < EGADS_SUCCESS0) {
1038 printf("Face = %d, failed to make quads\n", face);
1039 printf("Edges = %d %d %d %d\n", inorth[face], ieast[face], isouth[face], iwest[face]);
1040 continue;
1041 //goto cleanup;
1042 }
1043 }
1044 }
1045
1046 // Set the mesh type information
1047 feaMesh->meshType = SurfaceMesh;
1048 feaMesh->analysisType = MeshStructure;
1049
1050 // Get number of point in the tessellation
1051 status = EG_statusTessBody(feaMesh->egadsTess, &tempBody, &i, &feaMesh->numNode);
1052 if (status != EGADS_SUCCESS0) goto cleanup;
1053
1054 feaMesh->node = (meshNodeStruct *) EG_alloc(feaMesh->numNode*sizeof(meshNodeStruct));
1055 if (feaMesh->node == NULL((void*)0)) {
1056 feaMesh->numNode = 0;
1057 status = EGADS_MALLOC-4;
1058 goto cleanup;
1059 }
1060
1061 for (i = 0; i < feaMesh->numNode; i++) {
1062 status = initiate_meshNodeStruct(&feaMesh->node[i], feaMesh->analysisType);
1063 if (status != CAPS_SUCCESS0) goto cleanup;
1064 }
1065
1066 // Fill up the Attributes for the nodes
1067 for (i = 0; i < feaMesh->numNode; i++) {
1068
1069 status = EG_getGlobal(feaMesh->egadsTess, i+1, &pointType, &pointTopoIndex, xyzPoint);
1070 if (status != EGADS_SUCCESS0) goto cleanup;
1071
1072 feaMesh->node[i].xyz[0] = xyzPoint[0];
1073 feaMesh->node[i].xyz[1] = xyzPoint[1];
1074 feaMesh->node[i].xyz[2] = xyzPoint[2];
1075
1076 feaMesh->node[i].nodeID = i+1;
1077
1078 feaData = (feaMeshDataStruct *) feaMesh->node[i].analysisData;
1079
1080 status = fea_setFEADataPoint(efaces, eedges, enodes,
1081 attrMap,
1082 coordSystemMap,
1083 constraintMap,
1084 loadMap,
1085 transferMap,
1086 connectMap,
1087 responseMap,
1088 referenceMap,
1089 pointType, pointTopoIndex,
1090 feaData); // Set the feaData structure
1091 if (status != CAPS_SUCCESS0) goto cleanup;
1092 }
1093
1094 // Fill element information
1095
1096 // If body is just a single node
1097 if (isNodeBody == EGADS_SUCCESS0) {
1098
1099 if (numNode != 1) {
1100 printf("NodeBody found, but more than one node being reported!\n");
1101 status = CAPS_BADVALUE-311;
1102 goto cleanup;
1103 }
1104
1105 numElement = numNode;
1106 feaMesh->numElement = numElement;
1107
1108 feaMesh->element = (meshElementStruct *) EG_alloc(feaMesh->numElement*sizeof(meshElementStruct));
1109 if (feaMesh->element == NULL((void*)0)) {
1110 status = EGADS_MALLOC-4;
1111 feaMesh->numElement = 0;
1112 goto cleanup;
1113 }
1114
1115 i = 0;
1116 (void) initiate_meshElementStruct(&feaMesh->element[i], feaMesh->analysisType);
1117
1118 status = retrieve_CAPSGroupAttr(enodes[i], &attrName);
1119 if (status != CAPS_SUCCESS0) {
1120 AIM_ERROR(aimInfo, "No capsGroup attribute found for node - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1120, __func__
, "No capsGroup attribute found for node - %d!!", i+1); }
;
1121 print_AllAttr(aimInfo, enodes[i]);
1122 goto cleanup;
1123 }
1124
1125 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1126 if (status != CAPS_SUCCESS0) {
1127 printf("\tError: capsGroup name %s not found in attribute to index map\n", attrName);
1128 goto cleanup;
1129 }
1130
1131 feaMesh->element[i].elementType = Node;
1132
1133 feaMesh->element[i].elementID = i+1;
1134
1135 status = mesh_allocMeshElementConnectivity(&feaMesh->element[i]);
1136 if (status != CAPS_SUCCESS0) goto cleanup;
1137
1138 feaMesh->element[i].markerID = attrIndex;
1139
1140 feaMesh->element[i].connectivity[0] = i+1;
1141
1142 feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
1143
1144 feaData->propertyID = attrIndex;
1145
1146 feaData->attrIndex = attrIndex;
1147
1148 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1149 if (status == CAPS_SUCCESS0) {
1150 feaData->coordID = coordSystemIndex;
1151 } else {
1152 feaData->coordID = coordID;
1153 }
1154
1155 feaMesh->meshQuickRef.numNode += 1; // Add count
1156
1157 feaMesh->meshQuickRef.startIndexNode = 0;
1158 feaMesh->meshQuickRef.useStartIndex = (int) true1;
1159
1160 status = CAPS_SUCCESS0;
1161 goto cleanup;
1162
1163 } //NODEBODY IF
1164
1165 /* Determine of the body type */
1166 status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses);
1167 if (status != EGADS_SUCCESS0) goto cleanup;
1168
1169 // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces
1170 // as "free" edges
1171 if (bodySubType == WIREBODY6) {
1172 feaMesh->numElement = numEdge;
1173
1174 feaMesh->element = (meshElementStruct *) EG_alloc(feaMesh->numElement*sizeof(meshElementStruct));
1175 if (feaMesh->element == NULL((void*)0)) {
1176 status = EGADS_MALLOC-4;
1177 feaMesh->numElement = 0;
1178 goto cleanup;
1179 }
1180
1181 for (i = 0; i < feaMesh->numElement; i++) {
1182 (void) initiate_meshElementStruct(&feaMesh->element[i], feaMesh->analysisType);
1183 }
1184
1185 for (i = 0; i < numEdge; i++) {
1186
1187 status = EG_getInfo(eedges[i], &oclass, &mtype, &topObj, &prev, &next);
1188 if (status != CAPS_SUCCESS0) goto cleanup;
1189 if (mtype == DEGENERATE5) continue;
1190
1191 status = retrieve_CAPSIgnoreAttr(eedges[i], &attrName);
1192 if (status == CAPS_SUCCESS0) {
1193 printf("\tcapsIgnore attribute found for edge - %d!!\n", i+1);
1194 continue;
1195 }
1196
1197 numElement += 1;
1198
1199 status = retrieve_CAPSGroupAttr(eedges[i], &attrName);
1200 if (status != CAPS_SUCCESS0) {
1201 AIM_ERROR(aimInfo, "No capsGroup attribute found for edge - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1201, __func__
, "No capsGroup attribute found for edge - %d!!", i+1); }
;
1202 print_AllAttr(aimInfo, eedges[i] );
1203 goto cleanup;
1204 }
1205
1206 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1207 if (status != CAPS_SUCCESS0) {
1208 AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map\n", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1208, __func__
, "capsGroup name %s not found in attribute to index map\n", attrName
); }
;
1209 goto cleanup;
1210 }
1211
1212 feaMesh->element[numElement-1].elementType = Line;
1213
1214 feaMesh->element[numElement-1].elementID = numElement;
1215
1216 status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]);
1217 if (status != CAPS_SUCCESS0) goto cleanup;
1218
1219 feaMesh->element[numElement-1].markerID = attrIndex;
1220
1221 status = EG_getTessEdge(feaMesh->egadsTess, i+1, &numPoint, &xyz, &uv);
1222 if (status < EGADS_SUCCESS0) goto cleanup;
1223
1224 status = EG_localToGlobal(feaMesh->egadsTess, -(i+1), 1, &gID);
1225 if (status != EGADS_SUCCESS0) goto cleanup;
1226
1227 feaMesh->element[numElement-1].connectivity[0] = gID;
1228
1229 status = EG_localToGlobal(feaMesh->egadsTess, -(i+1), numPoint, &gID);
1230 if (status != EGADS_SUCCESS0) goto cleanup;
1231
1232 feaMesh->element[numElement-1].connectivity[1] = gID;
1233
1234 feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData;
1235
1236 feaData->propertyID = attrIndex;
1237
1238 feaData->attrIndex = attrIndex;
1239
1240 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1241 if (status == CAPS_SUCCESS0) {
1242 feaData->coordID = coordSystemIndex;
1243 } else {
1244 feaData->coordID = coordID;
1245 }
1246
1247 feaMesh->meshQuickRef.numLine += 1; // Add count
1248
1249 }
1250
1251 if (feaMesh->meshQuickRef.numLine != numEdge) { // Resize our array in case we have some ignores
1252
1253 tempElement = (meshElementStruct *) EG_reall(feaMesh->element,
1254 feaMesh->meshQuickRef.numLine*sizeof(meshElementStruct));
1255
1256 if (tempElement == NULL((void*)0)) {
1257 status = EGADS_MALLOC-4;
1258 goto cleanup;
1259 }
1260
1261 feaMesh->element = tempElement;
1262
1263 feaMesh->numElement = feaMesh->meshQuickRef.numLine;
1264 }
1265
1266 feaMesh->meshQuickRef.startIndexLine = 0;
1267 feaMesh->meshQuickRef.useStartIndex = (int) true1;
1268
1269 status = CAPS_SUCCESS0;
1270 goto cleanup;
1271
1272 } //WIREBODY IF
1273
1274 if (quadMesh == (int) true1 && numFace > 0) {
1275 printf("\tGetting quads for BEM!\n");
1276
1277 // Turn off meshQuick guide if you are getting quads
1278 feaMesh->meshQuickRef.useStartIndex = (int) false0;
1279 } else {
1280 feaMesh->meshQuickRef.useStartIndex = (int) true1;
1281 feaMesh->meshQuickRef.startIndexTriangle = numElement;
1282 }
1283
1284 // Get Tris and Quads from faces
1285 for (face = 0; face < numFace; face++) {
1286
1287 status = retrieve_CAPSIgnoreAttr(efaces[face], &attrName);
1288 if (status == CAPS_SUCCESS0) {
1289 printf("\tcapsIgnore attribute found for face - %d!!\n", face+1);
1290 ignoreFound = (int) true1;
1291 continue;
1292 }
1293
1294 status = retrieve_CAPSGroupAttr(efaces[face], &attrName);
1295 if (status != CAPS_SUCCESS0) {
1296 AIM_ERROR(aimInfo, "No capsGroup attribute found for face - %d!!", face+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1296, __func__
, "No capsGroup attribute found for face - %d!!", face+1); }
;
1297 print_AllAttr(aimInfo, efaces[face]);
1298 goto cleanup;
1299 }
1300
1301 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1302 if (status != CAPS_SUCCESS0) {
1303 AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1303, __func__
, "capsGroup name %s not found in attribute to index map", attrName
); }
;
1304 goto cleanup;
1305 }
1306
1307 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1308 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1309
1310
1311 loadIndex = CAPSMAGIC1234321;
1312 status = retrieve_CAPSLoadAttr(efaces[face], &attrName);
1313 if (status == CAPS_SUCCESS0) {
1314
1315 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
1316
1317 if (status != CAPS_SUCCESS0) {
1318 printf("Error: capsLoad name %s not found in attribute to index map\n", attrName);
1319 goto cleanup;
1320 }
1321 }
1322
1323 if (quadMesh == (int) true1) {
1324 status = EG_getQuads(feaMesh->egadsTess, face+1, &numPoint, &xyz, &uv, &ptype, &pindex, &numPatch);
1325 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1325
, __func__, 0); goto cleanup; }
;
1326
1327 } else numPatch = -1;
1328
1329 if (numPatch > 0) {
1330
1331 if (numPatch != 1) {
1332 status = CAPS_NOTIMPLEMENT-334;
1333 printf("feaUtils: EG_localToGlobal accidentally only works for a single quad patch! FIXME!\n");
1334 goto cleanup;
1335 }
1336
1337 qints[face] = 0;
1338 for (patch = 1; patch <= numPatch; patch++) {
1339
1340 status = EG_getPatch(feaMesh->egadsTess, face+1, patch, &n1, &n2, &pvindex, &pbounds);
1341 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1341
, __func__, 0); goto cleanup; }
;
1342
1343 for (j = 1; j < n2; j++) {
1344 for (i = 1; i < n1; i++) {
1345 numElement += 1;
1346
1347 feaMesh->meshQuickRef.numQuadrilateral += 1;
1348 feaMesh->numElement = numElement;
1349
1350 tempElement = (meshElementStruct *) EG_reall(feaMesh->element,
1351 feaMesh->numElement*sizeof(meshElementStruct));
1352
1353 if (tempElement == NULL((void*)0)) {
1354 status = EGADS_MALLOC-4;
1355 feaMesh->numElement -= 1;
1356 goto cleanup;
1357 }
1358
1359 feaMesh->element = tempElement;
1360
1361 status = initiate_meshElementStruct(&feaMesh->element[numElement-1], feaMesh->analysisType);
1362 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1362
, __func__, 0); goto cleanup; }
;
1363
1364 qints[face] += 1;
1365
1366 feaMesh->element[numElement-1].elementType = Quadrilateral;
1367
1368 feaMesh->element[numElement-1].elementID = numElement;
1369
1370 status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]);
1371 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1371
, __func__, 0); goto cleanup; }
;
1372
1373 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i-1)+n1*(j-1)], &gID);
1374 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1374
, __func__, 0); goto cleanup; }
;
1375
1376 feaMesh->element[numElement-1].connectivity[0] = gID;
1377
1378 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i )+n1*(j-1)], &gID);
1379 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1379
, __func__, 0); goto cleanup; }
;
1380
1381 feaMesh->element[numElement-1].connectivity[1] = gID;
1382
1383 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i )+n1*(j )], &gID);
1384 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1384
, __func__, 0); goto cleanup; }
;
1385
1386 feaMesh->element[numElement-1].connectivity[2] = gID;
1387
1388 status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i-1)+n1*(j )], &gID);
1389 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1389
, __func__, 0); goto cleanup; }
;
1390
1391 feaMesh->element[numElement-1].connectivity[3] = gID;
1392
1393 feaMesh->element[numElement-1].markerID = attrIndex;
1394
1395 feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData;
1396
1397 feaData->propertyID = attrIndex;
1398 feaData->attrIndex = attrIndex;
1399 feaData->coordID = coordSystemIndex;
1400 feaData->loadIndex = loadIndex;
1401
1402 }
1403 }
1404
1405 }
1406 } else {
1407 status = EG_getTessFace(feaMesh->egadsTess, face+1,
1408 &numPoint, &xyz, &uv, &ptype, &pindex,
1409 &numTri, &triConn, &triNeighbor);
1410 if (status < EGADS_SUCCESS0) goto cleanup;
1411
1412 for (i= 0; i < numTri; i++) {
1413
1414 numElement += 1;
1415
1416 feaMesh->meshQuickRef.numTriangle += 1;
1417 feaMesh->numElement = numElement;
1418
1419
1420 tempElement = (meshElementStruct *) EG_reall(feaMesh->element,
1421 feaMesh->numElement*sizeof(meshElementStruct));
1422
1423 if (tempElement == NULL((void*)0)) {
1424 status = EGADS_MALLOC-4;
1425 feaMesh->numElement -= 1;
1426 goto cleanup;
1427 }
1428
1429 feaMesh->element = tempElement;
1430
1431 status = initiate_meshElementStruct(&feaMesh->element[numElement-1], feaMesh->analysisType);
1432 if (status != CAPS_SUCCESS0) goto cleanup;
1433
1434 feaMesh->element[numElement-1].elementType = Triangle;
1435
1436 feaMesh->element[numElement-1].elementID = numElement;
1437
1438 status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]);
1439 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1439
, __func__, 0); goto cleanup; }
;
1440
1441 status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 0], &gID);
1442 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1442
, __func__, 0); goto cleanup; }
;
1443
1444 feaMesh->element[numElement-1].connectivity[0] = gID;
1445
1446 status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 1], &gID);
1447 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1447
, __func__, 0); goto cleanup; }
;
1448
1449 feaMesh->element[numElement-1].connectivity[1] = gID;
1450
1451 status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 2], &gID);
1452 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1452
, __func__, 0); goto cleanup; }
;
1453
1454 feaMesh->element[numElement-1].connectivity[2] = gID;
1455
1456 feaMesh->element[numElement-1].markerID = attrIndex;
1457
1458 feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData;
1459
1460 feaData->propertyID = attrIndex;
1461 feaData->attrIndex = attrIndex;
1462 feaData->coordID = coordSystemIndex;
1463 feaData->loadIndex = loadIndex;
1464
1465 }
1466 }
1467
1468 }
1469
1470 if (numPatch > 0) {
1471 status = EG_attributeAdd(feaMesh->egadsTess, ".mixed", ATTRINT1, numFace, qints, NULL((void*)0), NULL((void*)0));
1472 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1472
, __func__, 0); goto cleanup; }
;
1473 }
1474
1475 if (ignoreFound == (int) true1) {
1476
1477 // 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
1478 // Note: that the nodeIDs for the nodes and element connectivity isn't changed, as such if using element connectivity to blindly
1479 // access a given node this could lead to seg-faults!. mesh_nodeID2Array must be used to access the node array index.
1480 status = mesh_removeUnusedNodes(feaMesh);
1481 if (status != CAPS_SUCCESS0) goto cleanup;
1482 }
1483
1484 status = CAPS_SUCCESS0;
1485
1486cleanup:
1487 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_bodyToBem, status = %d\n", status);
1488
1489 AIM_FREE(iwest ){ EG_free(iwest); iwest = ((void*)0); };
1490 AIM_FREE(inorth){ EG_free(inorth); inorth = ((void*)0); };
1491 AIM_FREE(ieast ){ EG_free(ieast); ieast = ((void*)0); };
1492 AIM_FREE(isouth){ EG_free(isouth); isouth = ((void*)0); };
1493 AIM_FREE(rpos ){ EG_free(rpos); rpos = ((void*)0); };
1494 AIM_FREE(points ){ EG_free(points); points = ((void*)0); };
1495
1496 AIM_FREE(enodes){ EG_free(enodes); enodes = ((void*)0); };
1497 AIM_FREE(eedges){ EG_free(eedges); eedges = ((void*)0); };
1498 AIM_FREE(efaces){ EG_free(efaces); efaces = ((void*)0); };
1499
1500 AIM_FREE(qints){ EG_free(qints); qints = ((void*)0); };
1501
1502 enodes = NULL((void*)0);
1503 eedges =NULL((void*)0);
1504 efaces =NULL((void*)0);
1505
1506 return status;
1507}
1508
1509// Set the fea analysis meta data in a mesh
1510int fea_setAnalysisData( void *aimInfo, // (in) AIM structure
1511 mapAttrToIndexStruct *attrMap, // (in) map from CAPSGroup names to indexes
1512 mapAttrToIndexStruct *coordSystemMap,// (in) map from CoordSystem names to indexes
1513 mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes
1514 mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes
1515 mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes
1516 mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes
1517 mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes
1518 mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes
1519 meshStruct *feaMesh) // (in/out) FEA mesh structure
1520{
1521 int status = 0; // Function return status
1522
1523 int i, face, edge, node, body; // Indexing
1524 int dummy;
1525
1526 int nodeOffset=0, elementOffset=0;
1527
1528 // Body entities
1529 int numNode = 0, numEdge = 0, numFace = 0;
1530 ego *enodes=NULL((void*)0), *eedges=NULL((void*)0), *efaces=NULL((void*)0);
1531 ego ebody;
1532
1533 // Meshing
1534 int elem;
1535
1536 int oclass, nchild, *senses;
1537
1538 // Edge point distributions
1539 int *points=NULL((void*)0), *isouth=NULL((void*)0), *ieast=NULL((void*)0), *inorth=NULL((void*)0), *iwest=NULL((void*)0);
1540 double data[4];
1541 double *rpos=NULL((void*)0);
1542 ego eref, *echilds;//, topObj, prev, next;
1543
1544 int isNodeBody, bodySubType = 0; // Body classification
1545
1546 int pointType, pointTopoIndex;
1547 double xyzPoint[3];
1548
1549 // Meshing
1550 int numPoint = 0, numTri = 0;
1551 const int *triConn = NULL((void*)0), *triNeighbor = NULL((void*)0); // Triangle
1552
1553 int gID; // Global id
1554
1555 const double *xyz, *uv;
1556 double result[18];
1557
1558 const int *ptype = NULL((void*)0), *pindex = NULL((void*)0);
1559
1560 // Attributues
1561 const char *attrName;
1562 int attrIndex, coordSystemIndex, loadIndex;
1563
1564 feaMeshDataStruct *feaData = NULL((void*)0);
1565 meshGeomDataStruct *geomData;
1566
1567 // ---------------------------------------------------------------
1568
1569 if (feaMesh->meshType == SurfaceMesh || feaMesh->meshType == Surface2DMesh ) {
1570 printf("Setting FEA Data\n");
1571
1572 // Get body from tessellation
1573 status = EG_statusTessBody(feaMesh->egadsTess, &ebody, &dummy, &dummy);
1574 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1574
, __func__, 0); goto cleanup; }
;
1575
1576 // Get number of Nodes, Edges, and Faces in ebody
1577 status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes);
1578 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1578
, __func__, 0); goto cleanup; }
;
1579
1580 status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges);
1581 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1581
, __func__, 0); goto cleanup; }
;
1582
1583 status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces);
1584 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1584
, __func__, 0); goto cleanup; }
;
1585
1586 // What type of BODY do we have?
1587 isNodeBody = aim_isNodeBody(ebody, xyzPoint);
1588 if (isNodeBody < EGADS_SUCCESS0) goto cleanup;
1589 if (isNodeBody == EGADS_SUCCESS0) {
1590 // all attributes are on the body rather than the node for a node body
1591 enodes[0] = ebody;
1592 }
1593
1594 // Fill up the Attributes for the nodes
1595 for (i = 0; i < feaMesh->numNode; i++) {
1596
1597 status = EG_getGlobal(feaMesh->egadsTess, feaMesh->node[i].nodeID, &pointType, &pointTopoIndex, xyzPoint);
1598 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1598
, __func__, 0); goto cleanup; }
;
1599
1600 feaData = (feaMeshDataStruct *) feaMesh->node[i].analysisData;
1601
1602 status = fea_setFEADataPoint(efaces, eedges, enodes,
1603 attrMap,
1604 coordSystemMap,
1605 constraintMap,
1606 loadMap,
1607 transferMap,
1608 connectMap,
1609 responseMap,
1610 referenceMap,
1611 pointType, pointTopoIndex,
1612 feaData); // Set the feaData structure
1613 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1613
, __func__, 0); goto cleanup; }
;
1614 }
1615
1616 // Fill element information
1617
1618 // If body is just a single node
1619 if (numNode == 1) {
1620
1621 if (feaMesh->numNode != 1) {
1622 AIM_ERROR(aimInfo, "NodeBody found, but more than one node being reported!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1622, __func__
, "NodeBody found, but more than one node being reported!\n")
; }
;
1623 status = CAPS_BADVALUE-311;
1624 goto cleanup;
1625 }
1626
1627 i = 0;
1628 status = retrieve_CAPSGroupAttr(enodes[i], &attrName);
1629 if (status != CAPS_SUCCESS0) {
1630 AIM_ERROR(aimInfo, "No capsGroup attribute found for node - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1630, __func__
, "No capsGroup attribute found for node - %d!!", i+1); }
;
1631 print_AllAttr(aimInfo, enodes[i] );
1632 goto cleanup;
1633 }
1634
1635 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
1636 if (status != CAPS_SUCCESS0) {
1637 AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1637, __func__
, "capsGroup name %s not found in attribute to index map", attrName
); }
;
1638 goto cleanup;
1639 }
1640
1641 feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
1642
1643 feaData->propertyID = attrIndex;
1644
1645 feaData->attrIndex = attrIndex;
1646
1647 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1648 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1649
1650 feaData->coordID = coordSystemIndex;
1651
1652 status = CAPS_SUCCESS0;
1653 goto cleanup;
1654
1655 } //NODEBODY IF
1656
1657#if 0
1658 /* Determine the body type */
1659 status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses);
1660 if (status != EGADS_SUCCESS0) goto cleanup;
1661
1662 // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces
1663 // as "free" edges
1664 if (bodySubType == WIREBODY6) {
1665
1666 for (i = 0; i < feaMesh->meshQuickRef.numLine; i++) {
1667
1668 status = EG_getInfo(eedges[i], &oclass, &mtype, &topObj, &prev, &next);
1669 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1669
, __func__, 0); goto cleanup; }
;
1670 if (mtype == DEGENERATE5) continue;
1671
1672 if (feaMesh->meshQuickRef.useStartIndex == (int)true1)
1673 elem = i + feaMesh->meshQuickRef.startIndexLine;
1674 else if (feaMesh->meshQuickRef.useListIndex == (int)true1)
1675 elem = feaMesh->meshQuickRef.listIndexLine[i];
1676 else {
1677 status = CAPS_BADOBJECT-310;
1678 printf("DEVELOPER ERROR: Both useStartIndex and useListIndex are true!\n");
1679 goto cleanup;
1680 }
1681
1682 attrIndex = feaMesh->element[elem].markerID;
1683
1684 // get the capsGroup attribute string value
1685 status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName);
1686 if (status != CAPS_SUCCESS0) {
1687 printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex);
1688 goto cleanup;
1689 }
1690
1691 feaData = (feaMeshDataStruct *) feaMesh->element[elem].analysisData;
1692
1693 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1694 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1695
1696 feaData->propertyID = attrIndex;
1697 feaData->coordID = coordSystemIndex;
1698 }
1699
1700 status = CAPS_SUCCESS0;
1701 goto cleanup;
1702
1703 }
1704#endif
1705
1706
1707 // Set line, tri and quad analysis data
1708 for (elem = 0; elem < feaMesh->numElement; elem++) {
1709
1710 if (feaMesh->element[elem].elementType != Node &&
1711 feaMesh->element[elem].elementType != Line &&
1712 feaMesh->element[elem].elementType != Triangle &&
1713 feaMesh->element[elem].elementType != Triangle_6 &&
1714 feaMesh->element[elem].elementType != Quadrilateral &&
1715 feaMesh->element[elem].elementType != Quadrilateral_8) continue;
1716
1717 attrIndex = feaMesh->element[elem].markerID;
1718
1719 // get the capsGroup attribute string value
1720 status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName);
1721 if (status != CAPS_SUCCESS0) {
1722 printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex);
1723 goto cleanup;
1724 }
1725
1726 status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1727 if (status != CAPS_SUCCESS0) coordSystemIndex = 0;
1728
1729 if (feaMesh->element[elem].elementType == Node) {
1730 // get the node index
1731 node = feaMesh->element[elem].topoIndex;
1732 if (node < 1 || node > numNode) {
1733 printf("Error: Element '%d': Invalid node topological index: %d, [1-%d]\n", elem, node, numNode);
1734 status = CAPS_BADVALUE-311;
1735 goto cleanup;
1736 }
1737
1738 eref = enodes[node-1];
1739
1740 } else if (feaMesh->element[elem].elementType == Line) {
1741 // get the edge index
1742 edge = feaMesh->element[elem].topoIndex;
1743 if (edge < 1 || edge > numEdge) {
1744 printf("Error: Element '%d': Invalid edge topological index: %d, [1-%d]\n", elem, edge, numEdge);
1745 status = CAPS_BADVALUE-311;
1746 goto cleanup;
1747 }
1748
1749 eref = eedges[edge-1];
1750
1751 } else {
1752
1753 // get the face index
1754 face = feaMesh->element[elem].topoIndex;
1755 if (face < 1 || face > numFace) {
1756 printf("Error: Element '%d': Invalid face topological index: %d, [1-%d]\n", elem, face, numFace);
1757 status = CAPS_BADVALUE-311;
1758 goto cleanup;
1759 }
1760
1761 eref = efaces[face-1];
1762
1763 // If this is a face in a capsBound, set geomData in nodes
1764 status = retrieve_CAPSBoundAttr(eref, &attrName);
1765 if (status == CAPS_SUCCESS0) {
1766
1767 status = EG_getTessFace(feaMesh->egadsTess, face,
1768 &numPoint, &xyz, &uv, &ptype, &pindex,
1769 &numTri, &triConn, &triNeighbor);
1770 if (status < EGADS_SUCCESS0) goto cleanup;
1771
1772 for (i = 0; i < numPoint; i++) {
1773
1774 status = EG_localToGlobal(feaMesh->egadsTess, face, i+1, &gID);
1775 if (status != EGADS_SUCCESS0) goto cleanup;
1776
1777 geomData = feaMesh->node[gID-1].geomData;
1778
1779 if (geomData == NULL((void*)0)) {
1780
1781 // Get geometry data for node
1782 geomData = EG_alloc(sizeof(meshGeomDataStruct));
1783
1784 if (geomData == NULL((void*)0)) {
1785 status = EGADS_MALLOC-4;
1786 goto cleanup;
1787 }
1788
1789 status = initiate_meshGeomDataStruct(geomData);
1790 if (status != CAPS_SUCCESS0) goto cleanup;
1791
1792 geomData->type = ptype[i];
1793 geomData->topoIndex = pindex[i];
1794
1795 // Want the face index to be set for topoIndex
1796 if (geomData->topoIndex < 0) geomData->topoIndex = face+1;
1797
1798 geomData->uv[0] = uv[2*i + 0];
1799 geomData->uv[1] = uv[2*i + 1];
1800
1801 status = EG_evaluate(eref, geomData->uv, result);
1802 if (status != EGADS_SUCCESS0) goto cleanup;
1803
1804 // dU
1805 geomData->firstDerivative[0] = result[3];
1806 geomData->firstDerivative[1] = result[4];
1807 geomData->firstDerivative[2] = result[5];
1808
1809 // dV
1810 geomData->firstDerivative[3] = result[6];
1811 geomData->firstDerivative[4] = result[7];
1812 geomData->firstDerivative[5] = result[8];
1813
1814 feaMesh->node[gID-1].geomData = geomData;
1815 }
1816 }
1817 }
1818 }
1819
1820 loadIndex = CAPSMAGIC1234321;
1821 status = retrieve_CAPSLoadAttr(eref, &attrName);
1822 if (status == CAPS_SUCCESS0) {
1823
1824 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
1825
1826 if (status != CAPS_SUCCESS0) {
1827 printf("Error: capsLoad name %s not found in attribute to index map\n", attrName);
1828 goto cleanup;
1829 }
1830 }
1831
1832 feaData = (feaMeshDataStruct *) feaMesh->element[elem].analysisData;
1833
1834 feaData->propertyID = attrIndex;
1835 feaData->attrIndex = attrIndex;
1836 feaData->coordID = coordSystemIndex;
1837 feaData->loadIndex = loadIndex;
1838 }
1839
1840 } else if (feaMesh->meshType == VolumeMesh) {
1841
1842 // Show warning statement
1843 printf("Warning - surface nodes are assumed to be packed sequentially in the volume\n");
1844
1845 // Loop through reference meshes
1846 for (body = 0; body < feaMesh->numReferenceMesh; body++) {
1847 printf("Setting FEA Data from reference mesh %d (of %d)\n", body+1, feaMesh->numReferenceMesh);
1848
1849 // Get body from tessellation
1850 status = EG_statusTessBody(feaMesh->referenceMesh[body].egadsTess, &ebody, &dummy, &dummy);
1851 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1851
, __func__, 0); goto cleanup; }
;
1852
1853 // Get number of Nodes, Edges, and Faces in ebody
1854 status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes);
1855 if (status < EGADS_SUCCESS0) goto cleanup;
1856
1857 status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges);
1858 if (status != EGADS_SUCCESS0) goto cleanup;
1859
1860 status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces);
1861 if (status < EGADS_SUCCESS0) goto cleanup;
1862
1863 // What type of BODY do we have?
1864 isNodeBody = aim_isNodeBody(ebody, xyzPoint);
1865 if (isNodeBody < EGADS_SUCCESS0) goto cleanup;
1866
1867 // If body is just a single node
1868 if (isNodeBody == EGADS_SUCCESS0) {
1869
1870 printf("NodeBody found, not currently supported for VolumeMesh!\n");
1871 status = CAPS_BADVALUE-311;
1872 goto cleanup;
1873
1874 } //NODEBODY IF
1875
1876 // Fill up the Attributes for the nodes
1877 for (i = 0; i < feaMesh->referenceMesh[body].numNode; i++) {
1878
1879 status = EG_getGlobal(feaMesh->referenceMesh[body].egadsTess, feaMesh->referenceMesh[body].node[i].nodeID, &pointType, &pointTopoIndex, xyzPoint);
1880 if (status != EGADS_SUCCESS0) goto cleanup;
1881
1882 feaData = (feaMeshDataStruct *) feaMesh->node[i+nodeOffset].analysisData;
1883
1884 status = fea_setFEADataPoint(efaces, eedges, enodes,
1885 attrMap,
1886 coordSystemMap,
1887 constraintMap,
1888 loadMap,
1889 transferMap,
1890 connectMap,
1891 responseMap,
1892 referenceMap,
1893 pointType, pointTopoIndex,
1894 feaData); // Set the feaData structure
1895 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1895
, __func__, 0); goto cleanup; }
;
1896 }
1897
1898 // Fill element information //
1899
1900 // Determine the body type
1901 status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses);
1902 if (status != EGADS_SUCCESS0) goto cleanup;
1903
1904 // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces
1905 // as "free" edges
1906 if (bodySubType == WIREBODY6) {
1907
1908 printf("WireBody found, not currently supported for VolumeMesh!\n");
1909 status = CAPS_BADVALUE-311;
1910 goto cleanup;
1911
1912 } //WIREBODY IF
1913
1914 // Set tri and quad analysis data
1915 for (elem = 0; elem < feaMesh->referenceMesh[body].numElement; elem++) {
1916
1917 if (feaMesh->referenceMesh[body].element[elem].elementType != Triangle &&
1918 feaMesh->referenceMesh[body].element[elem].elementType != Triangle_6 &&
1919 feaMesh->referenceMesh[body].element[elem].elementType != Quadrilateral &&
1920 feaMesh->referenceMesh[body].element[elem].elementType != Quadrilateral_8) continue;
1921
1922//
1923// attrIndex = feaMesh->referenceMesh[body].element[elem].markerID;
1924//
1925// // get the capsGroup attribute string value
1926// status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName);
1927// if (status != CAPS_SUCCESS) {
1928// printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex);
1929// goto cleanup;
1930// }
1931//
1932// status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex);
1933// if (status != CAPS_SUCCESS) coordSystemIndex = 0;
1934
1935 // get the face index
1936 face = feaMesh->referenceMesh[body].element[elem].topoIndex;
1937 if (face < 1 || face > numFace) {
1938 printf("Error: Element '%d': Invalid face topological index: %d, [1-%d]\n", elem, face, numFace);
1939 status = CAPS_BADVALUE-311;
1940 goto cleanup;
1941 }
1942
1943 loadIndex = CAPSMAGIC1234321;
1944 status = retrieve_CAPSLoadAttr(efaces[face-1], &attrName);
1945 if (status == CAPS_SUCCESS0) {
1946
1947 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
1948
1949 if (status != CAPS_SUCCESS0) {
1950 printf("Error: capsLoad name %s not found in attribute to index map\n", attrName);
1951 goto cleanup;
1952 }
1953 }
1954
1955 feaData = (feaMeshDataStruct *) feaMesh->element[elem+elementOffset].analysisData;
1956
1957 //feaData->propertyID = attrIndex; DONT THINK WE WANT TO CHANGE THE PROPERTY TYPE
1958 // feaData->coordID = coordSystemIndex; DONT THINK WE WANT TO CHANGE THE Coordinate TYPE
1959 feaData->loadIndex = loadIndex;
1960 }
1961
1962 nodeOffset += feaMesh->referenceMesh[body].numNode;
1963 elementOffset += feaMesh->referenceMesh[body].numElement;
1964 }
1965
1966 } else {
1967 printf("Unknown meshType!\n");
1968 status = CAPS_BADTYPE-306;
1969 goto cleanup;
1970 }
1971
1972 status = CAPS_SUCCESS0;
1973
1974 cleanup:
1975 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_setAnalysisData, status = %d\n", status);
1976
1977 EG_free(iwest );
1978 EG_free(inorth);
1979 EG_free(ieast );
1980 EG_free(isouth);
1981 EG_free(rpos );
1982 EG_free(points );
1983
1984 EG_free(enodes);
1985 EG_free(eedges);
1986 EG_free(efaces);
1987
1988 enodes = NULL((void*)0);
1989 eedges = NULL((void*)0);
1990 efaces = NULL((void*)0);
1991
1992 return status;
1993}
1994
1995// Set feaData for a given point index and topology index. Ego faces, edges, and nodes must be provided along with attribute maps
1996int fea_setFEADataPoint(ego *faces, ego *edges, ego *nodes,
1997 mapAttrToIndexStruct *attrMap,
1998 /*@unused@*/ mapAttrToIndexStruct *coordSystemMap,
1999 mapAttrToIndexStruct *constraintMap,
2000 mapAttrToIndexStruct *loadMap,
2001 mapAttrToIndexStruct *transferMap,
2002 mapAttrToIndexStruct *connectMap,
2003 mapAttrToIndexStruct *responseMap,
2004 mapAttrToIndexStruct *referenceMap,
2005 int pointType, int pointTopoIndex,
2006 feaMeshDataStruct *feaData) { // Set the feaData structure
2007
2008 int status;
2009
2010 int coordID = 0; // Default coordinate id for mesh
2011
2012 // Attributes
2013 const char *attrName;
2014 int constraintIndex=-1, loadIndex=-1, transferIndex=-1, connectIndex=-1;
2015 int connectLinkIndex=-1, attrIndex=-1, responseIndex=-1, referenceIndex=-1; //coordSystemIndex
2016
2017 ego object;
2018
2019 feaData->coordID = coordID;
2020
2021 // Get attribute index on entity
2022 constraintIndex = CAPSMAGIC1234321;
2023 loadIndex = CAPSMAGIC1234321;
2024 transferIndex = CAPSMAGIC1234321;
2025 connectIndex = CAPSMAGIC1234321;
2026 connectLinkIndex = CAPSMAGIC1234321;
2027 responseIndex = CAPSMAGIC1234321;
2028 referenceIndex = CAPSMAGIC1234321;
2029
2030 if (pointType == 0) { // Node
2031
2032 object = nodes[pointTopoIndex-1];
2033
2034 } else if (pointType > 0 ) { // Edge
2035
2036 object = edges[pointTopoIndex-1];
2037
2038 } else { // Face
2039
2040 object = faces[pointTopoIndex-1];
2041
2042 }
2043
2044 status = retrieve_CAPSGroupAttr(object, &attrName);
2045 if (status == CAPS_SUCCESS0) {
2046 status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex);
2047 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2048 }
2049
2050 status = retrieve_CAPSConstraintAttr(object, &attrName);
2051 if (status == CAPS_SUCCESS0) {
2052 status = get_mapAttrToIndexIndex(constraintMap, attrName, &constraintIndex);
2053 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2054 }
2055
2056 status = retrieve_CAPSLoadAttr(object, &attrName);
2057 if (status == CAPS_SUCCESS0) {
2058 status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex);
2059 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2060 }
2061
2062 status = retrieve_CAPSBoundAttr(object, &attrName);
2063 if (status == CAPS_SUCCESS0) {
2064 status = get_mapAttrToIndexIndex(transferMap, attrName, &transferIndex);
2065 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2066 }
2067
2068 status = retrieve_CAPSConnectAttr(object, &attrName);
2069 if (status == CAPS_SUCCESS0) {
2070 status = get_mapAttrToIndexIndex(connectMap, attrName, &connectIndex);
2071 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2072 }
2073
2074 status = retrieve_CAPSConnectLinkAttr(object, &attrName);
2075 if (status == CAPS_SUCCESS0) {
2076 status = get_mapAttrToIndexIndex(connectMap, attrName, &connectLinkIndex);
2077 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2078 }
2079
2080 status = retrieve_CAPSResponseAttr(object, &attrName);
2081 if (status == CAPS_SUCCESS0) {
2082 status = get_mapAttrToIndexIndex(responseMap, attrName, &responseIndex);
2083 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2084 }
2085
2086 status = retrieve_CAPSReferenceAttr(object, &attrName);
2087 if (status == CAPS_SUCCESS0) {
2088 status = get_mapAttrToIndexIndex(referenceMap, attrName, &referenceIndex);
2089 if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup;
2090 }
2091
2092 feaData->attrIndex = attrIndex;
2093
2094 feaData->constraintIndex = constraintIndex;
2095 feaData->loadIndex = loadIndex;
2096 feaData->transferIndex = transferIndex;
2097 feaData->connectIndex = connectIndex;
2098 feaData->connectLinkIndex = connectLinkIndex;
2099 feaData->responseIndex = responseIndex;
2100 feaData->referenceIndex = referenceIndex;
2101
2102 status = CAPS_SUCCESS0;
2103 goto cleanup;
2104
2105 cleanup:
2106
2107 if (status != CAPS_SUCCESS0) printf("Error: Premature exit in fea_setFEADataPoint, status %d\n", status);
2108
2109 return status;
2110}
2111
2112// Initiate (0 out all values and NULL all pointers) of feaProperty in the feaPropertyStruct structure format
2113int initiate_feaPropertyStruct(feaPropertyStruct *feaProperty) {
2114 int i;
2115
2116 feaProperty->name = NULL((void*)0);
2117
2118 feaProperty->propertyType = UnknownProperty;
2119
2120 feaProperty->propertyID = 0; // ID number of property
2121
2122 feaProperty->materialID = 0; // ID number of material
2123 feaProperty->materialName = NULL((void*)0); // Name of material associated with material ID
2124
2125 // Rods
2126 feaProperty->crossSecArea = 0.0; // Bar cross-sectional area
2127 feaProperty->torsionalConst = 0.0; // Torsional constant
2128 feaProperty->torsionalStressReCoeff = 0.0; // Torsional stress recovery coefficient
2129 feaProperty->massPerLength = 0.0; // Mass per unit length
2130
2131 // Bar - see rod for additional variables
2132 feaProperty->zAxisInertia = 0.0; // Section moment of inertia about the z axis
2133 feaProperty->yAxisInertia = 0.0; // Section moment of inertia about the y axis
2134
2135 feaProperty->yCoords[0] = 0.0; // Element y, z coordinates, in the bar cross-section, of
2136 feaProperty->yCoords[1] = 0.0; // of four points at which to recover stresses
2137 feaProperty->yCoords[2] = 0.0;
2138 feaProperty->yCoords[3] = 0.0;
2139
2140 feaProperty->zCoords[0] = 0.0;
2141 feaProperty->zCoords[1] = 0.0;
2142 feaProperty->zCoords[2] = 0.0;
2143 feaProperty->zCoords[3] = 0.0;
2144
2145 feaProperty->areaShearFactors[0] = 0.0; // Area factors for shear
2146 feaProperty->areaShearFactors[1] = 0.0;
2147
2148 feaProperty->crossProductInertia = 0.0; // Section cross-product of inertia
2149
2150 feaProperty->crossSecType = NULL((void*)0); // Type of cross sections
2151 for (i = 0; i < 10; i++) feaProperty->crossSecDimension[i] = 0.0; // Dimensions
2152
2153 feaProperty->orientationVec[0] = 0.0; // Orientation vector
2154 feaProperty->orientationVec[1] = 0.0;
2155 feaProperty->orientationVec[2] = 0.0;
2156
2157 // Shear
2158
2159 // Shell
2160 feaProperty->membraneThickness = 0.0; // Membrane thickness
2161 feaProperty->materialBendingID = 0; /// ID number of material for bending - if not specified and bendingInertiaRatio > 0 this value defaults to materialID
2162 feaProperty->bendingInertiaRatio = 1.0; // Ratio of actual bending moment inertia (I) to bending inertia of a solid
2163 // plate of thickness TM Real - default 1.0
2164 feaProperty->materialShearID = 0; // ID number of material for shear - if not specified and shearMembraneRatio > 0 this value defaults to materialID
2165 feaProperty->shearMembraneRatio = 5.0/6.0; // Ratio of shear to membrane thickness - default 5/6
2166 feaProperty->massPerArea = 0.0; // Mass per unit area
2167 //feaProperty->neutralPlaneDist[0] = 0; // Distances from the neutral plane of the plate to locations where
2168 //feaProperty->neutralPlaneDist[1] = 0; // stress is calculate
2169
2170 feaProperty->zOffsetRel = 0.0; // Offset from the surface of grid points to the element reference plane
2171
2172 feaProperty->compositeShearBondAllowable = 0.0; // Shear stress limit for bonding between plies
2173 feaProperty->compositeFailureTheory = NULL((void*)0); // HILL, HOFF, TSAI, STRN
2174 feaProperty->compositeSymmetricLaminate = (int) false0; // 1- SYM only half the plies are specified, for odd number plies 1/2 thickness of center ply is specified
2175 // the first ply is the bottom ply in the stack, default (0) all plies specified
2176 feaProperty->numPly = 0;
2177 feaProperty->compositeMaterialID = NULL((void*)0); // Vector of material ID's from bottom to top for all plies
2178 feaProperty->compositeThickness = NULL((void*)0); // Vector of thicknesses from bottom to top for all plies
2179 feaProperty->compositeOrientation = NULL((void*)0); // Vector of orientations from bottom to top for all plies
2180
2181 // Solid
2182
2183 // Concentrated Mass
2184 feaProperty->mass = 0.0; // Mass value
2185 feaProperty->massOffset[0] = 0.0; // Offset distance from the grid point to the center of gravity
2186 feaProperty->massOffset[1] = 0.0;
2187 feaProperty->massOffset[2] = 0.0;
2188 feaProperty->massInertia[0] = 0.0; // Mass moment of inertia measured at the mass center of gravity
2189 feaProperty->massInertia[1] = 0.0;
2190 feaProperty->massInertia[2] = 0.0;
2191 feaProperty->massInertia[3] = 0.0;
2192 feaProperty->massInertia[4] = 0.0;
2193 feaProperty->massInertia[5] = 0.0;
2194
2195 return CAPS_SUCCESS0;
2196}
2197
2198// Destroy (0 out all values and NULL all pointers) of feaProperty in the feaPropertyStruct structure format
2199int destroy_feaPropertyStruct(feaPropertyStruct *feaProperty) {
2200
2201 int i;
2202
2203 if (feaProperty->name != NULL((void*)0)) EG_free(feaProperty->name);
2204
2205 feaProperty->propertyType = UnknownProperty;
2206
2207 feaProperty->propertyID = 0; // ID number of property
2208
2209 feaProperty->materialID = 0; // ID number of material
2210
2211 if (feaProperty->materialName != NULL((void*)0)) EG_free(feaProperty->materialName); // Name of material associated with material ID
2212 feaProperty->materialName = NULL((void*)0);
2213
2214 // Rods
2215 feaProperty->crossSecArea = 0; // Bar cross-sectional area
2216 feaProperty->torsionalConst = 0; // Torsional constant
2217 feaProperty->torsionalStressReCoeff = 0; // Torsional stress recovery coefficient
2218 feaProperty->massPerLength = 0; // Mass per unit length
2219
2220 // Bar - see rod for additional variables
2221 feaProperty->zAxisInertia = 0; // Section moment of inertia about the z axis
2222 feaProperty->yAxisInertia = 0; // Section moment of inertia about the y axis
2223
2224 feaProperty->yCoords[0] = 0; // Element y, z coordinates, in the bar cross-section, of
2225 feaProperty->yCoords[1] = 0; // of four points at which to recover stresses
2226 feaProperty->yCoords[2] = 0;
2227 feaProperty->yCoords[3] = 0;
2228
2229 feaProperty->zCoords[0] = 0;
2230 feaProperty->zCoords[1] = 0;
2231 feaProperty->zCoords[2] = 0;
2232 feaProperty->zCoords[3] = 0;
2233
2234 feaProperty->areaShearFactors[0] = 0; // Area factors for shear
2235 feaProperty->areaShearFactors[1] = 0;
2236
2237 feaProperty->crossProductInertia = 0; // Section cross-product of inertia
2238
2239 if (feaProperty->crossSecType != NULL((void*)0)) EG_free(feaProperty->crossSecType);
2240 feaProperty->crossSecType = NULL((void*)0); // Type of cross sections
2241 for (i = 0; i < 10; i++) feaProperty->crossSecDimension[i] = 0.0; // Dimensions
2242
2243 feaProperty->orientationVec[0] = 0.0; // Orientation vector
2244 feaProperty->orientationVec[1] = 0.0;
2245 feaProperty->orientationVec[2] = 0.0;
2246
2247 // Shear
2248
2249 // Shell
2250 feaProperty->membraneThickness = 0; // Membrane thickness
2251 feaProperty->materialBendingID = 0; // ID number of material for bending
2252 feaProperty->bendingInertiaRatio = 1.0; // Ratio of actual bending moment inertia (I) to bending inertia of a solid
2253 // plate of thickness TM Real - default 1.0
2254 feaProperty->materialShearID = 0; // ID number of material for shear
2255 feaProperty->shearMembraneRatio = 5.0/6.0; // Ratio of shear to membrane thickness - default 5/6
2256 feaProperty->massPerArea = 0; // Mass per unit area
2257 //feaProperty->neutralPlaneDist[0] = 0; // Distances from the neutral plane of the plate to locations where
2258 //feaProperty->neutralPlaneDist[1] = 0; // stress is calculate
2259
2260 feaProperty->zOffsetRel = 0.0; // Offset from the surface of grid points to the element reference plane
2261
2262 feaProperty->numPly = 0;
2263 feaProperty->compositeShearBondAllowable = 0.0; // Shear stress limit for bonding between plies
2264 if (feaProperty->compositeFailureTheory != NULL((void*)0)) EG_free(feaProperty->compositeFailureTheory); // HILL, HOFF, TSAI, STRN
2265 feaProperty->compositeFailureTheory = NULL((void*)0);
2266 feaProperty->compositeSymmetricLaminate = (int) false0; // 1- SYM only half the plies are specified, for odd number plies 1/2 thickness of center ply is specified
2267 // the first ply is the bottom ply in the stack, default (0) all plies specified
2268 if (feaProperty->compositeMaterialID != NULL((void*)0)) EG_free(feaProperty->compositeMaterialID);
2269 if (feaProperty->compositeThickness != NULL((void*)0)) EG_free(feaProperty->compositeThickness);
2270 if (feaProperty->compositeOrientation != NULL((void*)0)) EG_free(feaProperty->compositeOrientation);
2271
2272 feaProperty->compositeMaterialID = NULL((void*)0);
2273 feaProperty->compositeThickness = NULL((void*)0);
2274 feaProperty->compositeOrientation = NULL((void*)0);
2275
2276 // Solid
2277
2278 // Concentrated Mass
2279 feaProperty->mass = 0.0; // Mass value
2280 feaProperty->massOffset[0] = 0.0; // Offset distance from the grid point to the center of gravity
2281 feaProperty->massOffset[1] = 0.0;
2282 feaProperty->massOffset[2] = 0.0;
2283 feaProperty->massInertia[0] = 0.0; // Mass moment of inertia measured at the mass center of gravity
2284 feaProperty->massInertia[1] = 0.0;
2285 feaProperty->massInertia[2] = 0.0;
2286 feaProperty->massInertia[3] = 0.0;
2287 feaProperty->massInertia[4] = 0.0;
2288 feaProperty->massInertia[5] = 0.0;
2289
2290 return CAPS_SUCCESS0;
2291}
2292
2293// Initiate (0 out all values and NULL all pointers) of feaMaterial in the feaMaterialStruct structure format
2294int initiate_feaMaterialStruct(feaMaterialStruct *feaMaterial) {
2295
2296 feaMaterial->name = NULL((void*)0); // Material name
2297
2298 feaMaterial->materialType = UnknownMaterial; // Set
2299
2300 feaMaterial->materialID = 0; // ID number of material
2301
2302 feaMaterial->youngModulus = 0.0; // E - Young's Modulus
2303 feaMaterial->shearModulus = 0.0; // G - Shear Modulus
2304 feaMaterial->poissonRatio = 0.0; // Poisson's Ratio
2305 feaMaterial->density = 0.0; // Rho - material mass density
2306 feaMaterial->thermalExpCoeff = 0.0; //Coefficient of thermal expansion
2307 feaMaterial->temperatureRef = 0.0; // Reference temperature
2308 feaMaterial->dampingCoeff = 0.0; // Damping coefficient
2309 feaMaterial->tensionAllow = 0.0; // Tension allowable for the material
2310 feaMaterial->compressAllow = 0.0; // Compression allowable for the material
2311 feaMaterial->shearAllow = 0.0; // Shear allowable for the material
2312
2313 feaMaterial->youngModulusLateral = 0.0; // Young's Modulus in the lateral direction
2314 feaMaterial->shearModulusTrans1Z = 0.0; // Transverse shear modulus in the 1-Z plane
2315 feaMaterial->shearModulusTrans2Z = 0.0; // Transverse shear modulus in the 2-Z plane
2316 feaMaterial->tensionAllowLateral = 0.0; // Tension allowable for the material
2317 feaMaterial->compressAllowLateral = 0.0; // Compression allowable for the material
2318 feaMaterial->thermalExpCoeffLateral = 0.0; //Coefficient of thermal expansion
2319 feaMaterial->allowType = 0;
2320
2321 feaMaterial->specificHeat = 0;
2322 feaMaterial->kappa = 0;
2323
2324 return CAPS_SUCCESS0;
2325}
2326
2327// Destroy (0 out all values and NULL all pointers) of feaMaterial in the feaMaterialStruct structure format
2328int destroy_feaMaterialStruct(feaMaterialStruct *feaMaterial) {
2329
2330 if (feaMaterial->name != NULL((void*)0)) EG_free(feaMaterial->name);
2331 feaMaterial->name = NULL((void*)0); // Material name
2332
2333 feaMaterial->materialType = UnknownMaterial; // Material type
2334
2335 feaMaterial->materialID = 0; // ID number of material
2336
2337 feaMaterial->youngModulus = 0.0; // E - Young's Modulus
2338 feaMaterial->shearModulus = 0.0; // G - Shear Modulus
2339 feaMaterial->poissonRatio = 0.0; // Poisson's Ratio
2340 feaMaterial->density = 0.0; // Rho - material mass density
2341 feaMaterial->thermalExpCoeff = 0.0; //Coefficient of thermal expansion
2342 feaMaterial->temperatureRef = 0.0; // Reference temperature
2343 feaMaterial->dampingCoeff = 0.0; // Damping coefficient
2344 feaMaterial->tensionAllow = 0.0; // Tension allowable for the material
2345 feaMaterial->compressAllow = 0.0; // Compression allowable for the material
2346 feaMaterial->shearAllow = 0.0; // Shear allowable for the material
2347
2348 feaMaterial->youngModulusLateral = 0.0; // Young's Modulus in the lateral direction
2349 feaMaterial->shearModulusTrans1Z = 0.0; // Transverse shear modulus in the 1-Z plane
2350 feaMaterial->shearModulusTrans2Z = 0.0; // Transverse shear modulus in the 2-Z plane
2351 feaMaterial->tensionAllowLateral = 0.0; // Tension allowable for the material
2352 feaMaterial->compressAllowLateral = 0.0; // Compression allowable for the material
2353 feaMaterial->thermalExpCoeffLateral = 0.0; //Coefficient of thermal expansion
2354 feaMaterial->allowType = 0;
2355
2356 feaMaterial->specificHeat = 0;
2357 feaMaterial->kappa = 0;
2358
2359 return CAPS_SUCCESS0;
2360}
2361
2362// Initiate (0 out all values and NULL all pointers) of feaUnits in the feaUnitsStruct structure format
2363int initiate_feaUnitsStruct(feaUnitsStruct *feaUnits) {
2364
2365 feaUnits->densityVol = NULL((void*)0);
2366 feaUnits->densityArea = NULL((void*)0);
2367 feaUnits->mass = NULL((void*)0);
2368 feaUnits->length = NULL((void*)0);
2369 feaUnits->pressure = NULL((void*)0);
2370 feaUnits->temperature = NULL((void*)0);
2371 feaUnits->momentOfInertia = NULL((void*)0);
2372
2373 return CAPS_SUCCESS0;
2374}
2375
2376// Destroy (0 out all values and NULL all pointers) of feaUnits in the feaUnitsStruct structure format
2377int destroy_feaUnitsStruct(feaUnitsStruct *feaUnits) {
2378
2379 AIM_FREE(feaUnits->densityVol){ EG_free(feaUnits->densityVol); feaUnits->densityVol =
((void*)0); }
;
2380 AIM_FREE(feaUnits->densityArea){ EG_free(feaUnits->densityArea); feaUnits->densityArea
= ((void*)0); }
;
2381 AIM_FREE(feaUnits->mass){ EG_free(feaUnits->mass); feaUnits->mass = ((void*)0);
}
;
2382 AIM_FREE(feaUnits->length){ EG_free(feaUnits->length); feaUnits->length = ((void*
)0); }
;
2383 AIM_FREE(feaUnits->pressure){ EG_free(feaUnits->pressure); feaUnits->pressure = ((void
*)0); }
;
2384 AIM_FREE(feaUnits->temperature){ EG_free(feaUnits->temperature); feaUnits->temperature
= ((void*)0); }
;
2385 AIM_FREE(feaUnits->momentOfInertia){ EG_free(feaUnits->momentOfInertia); feaUnits->momentOfInertia
= ((void*)0); }
;
2386
2387 return CAPS_SUCCESS0;
2388}
2389
2390// Initiate (0 out all values and NULL all pointers) of feaConstraint in the feaConstraintStruct structure format
2391int initiate_feaConstraintStruct(feaConstraintStruct *feaConstraint) {
2392
2393 feaConstraint->name = NULL((void*)0); // Constraint name
2394
2395 feaConstraint->constraintType = UnknownConstraint; // Constraint type
2396
2397 feaConstraint->constraintID = 0; // ID number of constraint
2398
2399 feaConstraint->numGridID = 0; // Component number of grid
2400 feaConstraint->gridIDSet = NULL((void*)0); // List of component number of grids to apply constraint to
2401
2402 feaConstraint->dofConstraint = 0; // Number to indicate DOF constraints
2403 feaConstraint->gridDisplacement = 0;
2404
2405 return CAPS_SUCCESS0;
2406}
2407
2408// Destroy (0 out all values and NULL all pointers) of feaConstraint in the feaConstraintStruct structure format
2409int destroy_feaConstraintStruct(feaConstraintStruct *feaConstraint) {
2410
2411 if (feaConstraint->name != NULL((void*)0)) EG_free(feaConstraint->name);
2412 feaConstraint->name = NULL((void*)0); // Constraint name
2413
2414 feaConstraint->constraintType = UnknownConstraint; // Constraint type
2415
2416 feaConstraint->constraintID = 0; // ID number of constraint
2417
2418 feaConstraint->numGridID = 0; // Number of grid IDs in grid ID set
2419
2420 if (feaConstraint->gridIDSet != NULL((void*)0)) EG_free(feaConstraint->gridIDSet); // List of component number of grids to apply constraint to
2421
2422 feaConstraint->dofConstraint = 0; // Number to indicate DOF constraints
2423 feaConstraint->gridDisplacement = 0; // The value for the displacement
2424
2425 return CAPS_SUCCESS0;
2426}
2427
2428// Initiate (0 out all values and NULL all pointers) of feaSupport in the feaSupportStruct structure format
2429int initiate_feaSupportStruct(feaSupportStruct *feaSupport) {
2430
2431 feaSupport->name = NULL((void*)0); // Support name
2432
2433 feaSupport->supportID = 0; // ID number of support
2434
2435 feaSupport->numGridID = 0; // Component number of grid
2436 feaSupport->gridIDSet = NULL((void*)0); // List of component number of grids to apply support to
2437
2438 feaSupport->dofSupport = 0; // Number to indicate DOF supports
2439
2440 return CAPS_SUCCESS0;
2441}
2442
2443// Destroy (0 out all values and NULL all pointers) of feaSupport in the feaSupportStruct structure format
2444int destroy_feaSupportStruct(feaSupportStruct *feaSupport) {
2445
2446 if (feaSupport->name != NULL((void*)0)) EG_free(feaSupport->name);
2447 feaSupport->name = NULL((void*)0); // Support name
2448
2449 feaSupport->supportID = 0; // ID number of support
2450
2451 feaSupport->numGridID = 0; // Number of grid IDs in grid ID set
2452
2453 if (feaSupport->gridIDSet != NULL((void*)0)) EG_free(feaSupport->gridIDSet); // List of component number of grids to apply support to
2454
2455 feaSupport->dofSupport = 0; // Number to indicate DOF supports
2456
2457 return CAPS_SUCCESS0;
2458}
2459
2460// Initiate (0 out all values and NULL all pointers) of feaAnalysis in the feaAnalysisStruct structure format
2461int initiate_feaAnalysisStruct(feaAnalysisStruct *feaAnalysis) {
2462
2463 feaAnalysis->name = NULL((void*)0); // Analysis name
2464
2465 feaAnalysis->analysisType = UnknownAnalysis; // Type of analysis
2466
2467 feaAnalysis->analysisID = 0; // ID number of analysis
2468
2469 // Loads for the analysis
2470 feaAnalysis->numLoad = 0; // Number of loads in the analysis
2471 feaAnalysis->loadSetID = NULL((void*)0); // List of the load IDSs
2472
2473 // Constraints for the analysis
2474 feaAnalysis->numConstraint = 0; // Number of constraints in the analysis
2475 feaAnalysis->constraintSetID = NULL((void*)0); // List of constraint IDs
2476
2477 // Supports for the analysis
2478 feaAnalysis->numSupport = 0; // Number of supports in the analysis
2479 feaAnalysis->supportSetID = NULL((void*)0); // List of support IDs
2480
2481 // Optimization constraints
2482 feaAnalysis->numDesignConstraint = 0; // Number of design constraints
2483 feaAnalysis->designConstraintSetID = NULL((void*)0); // List of design constraint IDs
2484
2485 // Optimization responses
2486 feaAnalysis->numDesignResponse = 0; // Number of design responses
2487 feaAnalysis->designResponseSetID = NULL((void*)0); // List of design response IDs
2488
2489 // Eigenvalue
2490 feaAnalysis->extractionMethod = NULL((void*)0);
2491
2492 feaAnalysis->frequencyRange[0] = 0;
2493 feaAnalysis->frequencyRange[1] = 0;
2494
2495 feaAnalysis->numEstEigenvalue = 0;
2496 feaAnalysis->numDesiredEigenvalue = 0;
2497 feaAnalysis->eigenNormaliztion = NULL((void*)0);
2498
2499 feaAnalysis->gridNormaliztion = 0;
2500 feaAnalysis->componentNormaliztion = 0;
2501
2502 feaAnalysis->lanczosMode = 2; //Lanczos mode for calculating eigenvalues
2503 feaAnalysis->lanczosType = NULL((void*)0); //Lanczos matrix type (DPB, DGB)
2504
2505 // Trim
2506 feaAnalysis->numMachNumber = 0;
2507 feaAnalysis->machNumber = NULL((void*)0); // Mach number
2508 feaAnalysis->dynamicPressure = 0.0; // Dynamic pressure
2509 feaAnalysis->density = 0.0; // Density
2510 feaAnalysis->aeroSymmetryXY = NULL((void*)0);
2511 feaAnalysis->aeroSymmetryXZ = NULL((void*)0);
2512
2513 feaAnalysis->numRigidVariable = 0; // Number of rigid trim variables
2514 feaAnalysis->rigidVariable = NULL((void*)0); // List of character labels identifying rigid trim variables, size=[numRigidVariables]
2515
2516 feaAnalysis->numRigidConstraint = 0; // Number of rigid trim constrained variables
2517 feaAnalysis->rigidConstraint = NULL((void*)0); // List of character labels identifying rigid constrained trim variables, size=[numRigidConstraint]
2518 feaAnalysis->magRigidConstraint = NULL((void*)0); // Magnitude of rigid constrained trim variables, size=[numRigidConstraint]
2519
2520 feaAnalysis->numControlConstraint = 0; // Number of control surface constrained variables
2521 feaAnalysis->controlConstraint = NULL((void*)0); // List of character labels identifying control surfaces to be constrained trim variables, size=[numControlConstraint]
2522 feaAnalysis->magControlConstraint = NULL((void*)0); // Magnitude of control surface constrained variables, size=[numControlConstraint]
2523
2524 // Flutter
2525 feaAnalysis->numReducedFreq = 0;
2526 feaAnalysis->reducedFreq = NULL((void*)0);
2527
2528 feaAnalysis->numFlutterVel = 0;
2529 feaAnalysis->flutterVel = NULL((void*)0);
2530
2531 feaAnalysis->flutterConvergenceParam = 0.0;
2532
2533 feaAnalysis->visualFlutter = (int) false0;
2534
2535 return CAPS_SUCCESS0;
2536}
2537
2538// Destroy (0 out all values and NULL all pointers) of feaAnalysis in the feaAnalysisStruct structure format
2539int destroy_feaAnalysisStruct(feaAnalysisStruct *feaAnalysis) {
2540 int status; // Function return status
2541
2542 if (feaAnalysis->name != NULL((void*)0)) EG_free(feaAnalysis->name);
2543 feaAnalysis->name = NULL((void*)0); // Analysis name
2544
2545 feaAnalysis->analysisType = UnknownAnalysis; // Type of analysis
2546
2547 feaAnalysis->analysisID = 0; // ID number of analysis
2548
2549 // Loads for the analysis
2550 feaAnalysis->numLoad = 0; // Number of loads in the analysis
2551 if(feaAnalysis->loadSetID != NULL((void*)0)) EG_free(feaAnalysis->loadSetID);
2552 feaAnalysis->loadSetID = NULL((void*)0); // List of the load IDSs
2553
2554 // Constraints for the analysis
2555 feaAnalysis->numConstraint = 0; // Number of constraints in the analysis
2556 if (feaAnalysis->constraintSetID != NULL((void*)0)) EG_free(feaAnalysis->constraintSetID);
2557 feaAnalysis->constraintSetID = NULL((void*)0); // List of constraint IDs
2558
2559 // Supports for the analysis
2560 feaAnalysis->numSupport = 0; // Number of supports in the analysis
2561 if (feaAnalysis->supportSetID != NULL((void*)0)) EG_free(feaAnalysis->supportSetID);
2562 feaAnalysis->supportSetID = NULL((void*)0); // List of support IDs
2563
2564 // Optimization constraints
2565 feaAnalysis->numDesignConstraint = 0; // Number of design constraints
2566 if (feaAnalysis->designConstraintSetID != NULL((void*)0)) EG_free(feaAnalysis->designConstraintSetID);
2567 feaAnalysis->designConstraintSetID = NULL((void*)0); // List of design constraint IDs
2568
2569 // Optimization responses
2570 feaAnalysis->numDesignResponse = 0; // Number of design responses
2571 if (feaAnalysis->designResponseSetID != NULL((void*)0)) EG_free(feaAnalysis->designResponseSetID);
2572 feaAnalysis->designResponseSetID = NULL((void*)0); // List of design response IDs
2573
2574 // Eigenvalue
2575 if (feaAnalysis->extractionMethod != NULL((void*)0)) EG_free(feaAnalysis->extractionMethod);
2576 feaAnalysis->extractionMethod = NULL((void*)0);
2577
2578 feaAnalysis->frequencyRange[0] = 0;
2579 feaAnalysis->frequencyRange[1] = 0;
2580
2581 feaAnalysis->numEstEigenvalue = 0;
2582 feaAnalysis->numDesiredEigenvalue = 0;
2583
2584 if (feaAnalysis->eigenNormaliztion != NULL((void*)0)) EG_free(feaAnalysis->eigenNormaliztion);
2585 feaAnalysis->eigenNormaliztion = NULL((void*)0);
2586
2587 feaAnalysis->gridNormaliztion = 0;
2588 feaAnalysis->componentNormaliztion = 0;
2589
2590 feaAnalysis->lanczosMode = 2; //Lanczos mode for calculating eigenvalues
2591
2592 if (feaAnalysis->lanczosType != NULL((void*)0)) EG_free(feaAnalysis->lanczosType);
2593 feaAnalysis->lanczosType = NULL((void*)0); //Lanczos matrix type (DPB, DGB)
2594
2595 // Trim
2596 feaAnalysis->numMachNumber = 0;
2597
2598 if (feaAnalysis->machNumber != NULL((void*)0)) EG_free(feaAnalysis->machNumber);
2599 feaAnalysis->machNumber = NULL((void*)0); // Mach number
2600
2601 //feaAnalysis->machNumber = 0.0; // Mach number
2602 feaAnalysis->dynamicPressure = 0.0; // Dynamic pressure
2603 feaAnalysis->density = 0.0; // Density
2604 if (feaAnalysis->aeroSymmetryXY != NULL((void*)0)) EG_free(feaAnalysis->aeroSymmetryXY);
2605 if (feaAnalysis->aeroSymmetryXZ != NULL((void*)0)) EG_free(feaAnalysis->aeroSymmetryXZ);
2606
2607 if (feaAnalysis->rigidVariable != NULL((void*)0)) {
2608 status = string_freeArray(feaAnalysis->numRigidVariable, &feaAnalysis->rigidVariable);
2609 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
2610 }
2611
2612 feaAnalysis->numRigidVariable = 0; // Number of trim rigid trim variables
2613 feaAnalysis->rigidVariable = NULL((void*)0); // List of character labels identifying rigid trim variables, size=[numRigidVariables]
2614
2615 if (feaAnalysis->rigidConstraint != NULL((void*)0)) {
2616 status = string_freeArray(feaAnalysis->numRigidConstraint, &feaAnalysis->rigidConstraint);
2617 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
2618 }
2619
2620 feaAnalysis->numRigidConstraint = 0; // Number of rigid trim constrained variables
2621 feaAnalysis->rigidConstraint = NULL((void*)0); // List of character labels identifying rigid constrained trim variables, size=[numRigidConstraint]
2622
2623 if (feaAnalysis->magRigidConstraint != NULL((void*)0)) EG_free(feaAnalysis->magRigidConstraint);
2624 feaAnalysis->magRigidConstraint = NULL((void*)0); // Magnitude of rigid constrained trim variables, size=[numRigidConstraint]
2625
2626 if (feaAnalysis->controlConstraint != NULL((void*)0)) {
2627 status = string_freeArray(feaAnalysis->numControlConstraint, &feaAnalysis->controlConstraint);
2628 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
2629 }
2630
2631 feaAnalysis->numControlConstraint = 0; // Number of control surface constrained variables
2632 feaAnalysis->controlConstraint = NULL((void*)0); // List of character labels identifying control surfaces to be constrained trim variables, size=[numControlConstraint]
2633
2634 EG_free(feaAnalysis->magControlConstraint);
2635 feaAnalysis->magControlConstraint = NULL((void*)0); // Magnitude of control surface constrained variables, size=[numControlConstraint]
2636
2637 // Flutter
2638 feaAnalysis->numReducedFreq = 0;
2639 EG_free(feaAnalysis->reducedFreq);
2640 feaAnalysis->reducedFreq = NULL((void*)0);
2641
2642 feaAnalysis->numFlutterVel = 0;
2643 EG_free(feaAnalysis->flutterVel);
2644 feaAnalysis->flutterVel = NULL((void*)0);
2645
2646 feaAnalysis->flutterConvergenceParam = 0.0;
2647
2648 feaAnalysis->visualFlutter = (int) false0;
2649
2650 return CAPS_SUCCESS0;
2651}
2652
2653// Initiate (0 out all values and NULL all pointers) of feaLoad in the feaLoadStruct structure format
2654int initiate_feaLoadStruct(feaLoadStruct *feaLoad) {
2655
2656 feaLoad->name = NULL((void*)0); // Load name
2657
2658 feaLoad->loadType = UnknownLoad; // Load type
2659
2660 feaLoad->loadID = 0; // ID number of load
2661
2662 feaLoad->loadScaleFactor = 1; // Scale factor for when combining loads
2663
2664 // Concentrated force at a grid point
2665 feaLoad->numGridID = 0; // Number of grid IDs in grid ID set
2666 feaLoad->gridIDSet = NULL((void*)0); // List of grid IDs to apply the constraint to. size = [numGridID]
2667 feaLoad->coordSystemID= 0; // Component number of coordinate system in which force vector is specified
2668
2669 feaLoad->forceScaleFactor= 0.0; // Overall scale factor for the force
2670 feaLoad->directionVector[0] = 0.0; // [0]-x, [1]-y, [2]-z components of the force vector
2671 feaLoad->directionVector[1] = 0.0;
2672 feaLoad->directionVector[2] = 0.0;
2673
2674 // Concentrated moment at a grid point (also uses coordSystemID and directionVector)
2675 feaLoad->momentScaleFactor= 0.0; // Overall scale factor for the moment
2676
2677 // Gravitational load (also uses coordSystemID and directionVector)
2678 feaLoad->gravityAcceleration= 0.0; // Gravitational acceleration
2679
2680 // Pressure load
2681 feaLoad->pressureForce= 0.0; // Pressure value
2682 feaLoad->pressureDistributeForce[0] = 0.0; // Pressure load at a specified grid location in the element
2683 feaLoad->pressureDistributeForce[1] = 0.0;
2684 feaLoad->pressureDistributeForce[2] = 0.0;
2685 feaLoad->pressureDistributeForce[3] = 0.0;
2686
2687 feaLoad->pressureMultiDistributeForce = NULL((void*)0); // Unique pressure load at a specified grid location for
2688 // each element in elementIDSet size = [numElementID][4] - used in type PressureExternal
2689 // where the pressure force is being provided by an external source (i.e. data transfer)
2690
2691 feaLoad->numElementID = 0; // Number of elements IDs in element ID set
2692 feaLoad->elementIDSet = NULL((void*)0); // List element IDs in which to apply the load. size = [numElementID]
2693
2694 // Rotational velocity (also uses coordSystemID and directionVector)
2695 feaLoad->angularVelScaleFactor = 0.0; // Overall scale factor for the angular velocity
2696 feaLoad->angularAccScaleFactor = 0.0; // Overall scale factor for the angular acceleration
2697
2698 // Thermal load - the temperature at a grid point - use gridIDSet
2699 feaLoad->temperature = 0.0; // Temperature value
2700 feaLoad->temperatureDefault = 0.0; // Default temperature of grid point explicitly not used
2701
2702 feaLoad->temperatureMultiDistribute = NULL((void*)0);
2703
2704 return CAPS_SUCCESS0;
2705}
2706
2707// Copy feaLoad in the feaLoadStruct structure format
2708// assumes that copy has been initialized with initiate_feaLoadStruct
2709int copy_feaLoadStruct(void *aimInfo, feaLoadStruct *feaLoad, feaLoadStruct *copy) {
2710
2711 int status = CAPS_SUCCESS0;
2712 int i;
2713
2714 if (feaLoad->name != NULL((void*)0)) {
2715 AIM_STRDUP(copy->name, feaLoad->name, aimInfo, status){ if (copy->name != ((void*)0)) { status = -4; aim_status(
aimInfo, status, "feaUtils.c", 2715, __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", 2715, __func__
, 2, "AIM_STRDUP: %s %s", "copy->name", feaLoad->name);
goto cleanup; } }
; // Load name
2716 }
2717
2718 copy->loadType = feaLoad->loadType; // Load type
2719
2720 copy->loadID = feaLoad->loadID; // ID number of load
2721
2722 copy->loadScaleFactor = feaLoad->loadScaleFactor; // Scale factor for when combining loads
2723
2724 // Concentrated force at a grid point
2725 copy->numGridID = feaLoad->numGridID; // Number of grid IDs in grid ID set
2726 // List of grid IDs to apply the constraint to
2727 AIM_ALLOC(copy->gridIDSet, feaLoad->numGridID, int, aimInfo, status){ if (copy->gridIDSet != ((void*)0)) { status = -4; aim_status
(aimInfo, status, "feaUtils.c", 2727, __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", 2727, __func__
, 3, "AIM_ALLOC: %s size %zu type %s", "copy->gridIDSet", memorysize
, "int"); goto cleanup; } }
;
2728 for (i = 0; i < feaLoad->numGridID; i++)
2729 copy->gridIDSet[i] = feaLoad->gridIDSet[i];
2730
2731 copy->coordSystemID = feaLoad->coordSystemID; // Component number of coordinate system in which force vector is specified
2732 copy->forceScaleFactor = feaLoad->forceScaleFactor; // Overall scale factor for the force
2733 copy->directionVector[0] = feaLoad->directionVector[0]; // [0]-x, [1]-y, [2]-z components of the force vector
2734 copy->directionVector[1] = feaLoad->directionVector[1];
2735 copy->directionVector[2] = feaLoad->directionVector[2];
2736
2737 // Concentrated moment at a grid pofeaLoad->(also uses coordSystemID and directionVector)
2738 copy->momentScaleFactor = feaLoad->momentScaleFactor; // Overall scale factor for the moment
2739
2740 // Gravitational load (also uses coordSystemID and directionVector)
2741 copy->gravityAcceleration = feaLoad->gravityAcceleration; // Gravitational acceleration
2742
2743 // Pressure load
2744 copy->pressureForce = feaLoad->pressureForce; // Pressure value
2745
2746 copy->pressureDistributeForce[0] = feaLoad->pressureDistributeForce[0]; // Pressure load at a specified grid location in the element
2747 copy->pressureDistributeForce[1] = feaLoad->pressureDistributeForce[1];
2748 copy->pressureDistributeForce[2] = feaLoad->pressureDistributeForce[2];
2749 copy->pressureDistributeForce[3] = feaLoad->pressureDistributeForce[3];
2750
2751 // Unique pressure load at a specified grid location for
2752 //each element in elementIDSet size = [4*numElementID]- used in type PressureExternal
2753 if (feaLoad->pressureMultiDistributeForce != NULL((void*)0)) {
2754 AIM_ALLOC(copy->pressureMultiDistributeForce, feaLoad->numElementID, double, aimInfo, status){ if (copy->pressureMultiDistributeForce != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 2754, __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"
, 2754, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->pressureMultiDistributeForce"
, memorysize, "double"); goto cleanup; } }
;
2755 for (i = 0; i < 4*feaLoad->numElementID; i++)
2756 copy->pressureMultiDistributeForce[i] = feaLoad->pressureMultiDistributeForce[i];
2757 } else {
2758 copy->pressureMultiDistributeForce = NULL((void*)0);
2759 }
2760
2761 copy->numElementID = feaLoad->numElementID; // Number of elements IDs in element ID set
2762 AIM_ALLOC(copy->elementIDSet, feaLoad->numElementID, int, aimInfo, status){ if (copy->elementIDSet != ((void*)0)) { status = -4; aim_status
(aimInfo, status, "feaUtils.c", 2762, __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"
, 2762, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->elementIDSet"
, memorysize, "int"); goto cleanup; } }
; // List element IDs in which to apply the load
2763 for (i = 0; i < feaLoad->numElementID; i++)
2764 copy->elementIDSet[i] = feaLoad->elementIDSet[i];
2765
2766 // Rotational velocity (also uses coordSystemID and directionVector)
2767 copy->angularVelScaleFactor = feaLoad->angularVelScaleFactor; // Overall scale factor for the angular velocity
2768 copy->angularAccScaleFactor = feaLoad->angularAccScaleFactor; // Overall scale factor for the angular acceleration
2769
2770 // Thermal load - the temperature at a grid point - use gridIDSet
2771 copy->temperature = feaLoad->temperature; // Temperature value
2772 copy->temperatureDefault = feaLoad->temperatureDefault; // Default temperature of grid point explicitly not used
2773
2774 if (feaLoad->temperatureMultiDistribute != NULL((void*)0)) {
2775 AIM_ALLOC(copy->temperatureMultiDistribute, feaLoad->numGridID, double, aimInfo, status){ if (copy->temperatureMultiDistribute != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 2775, __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"
, 2775, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->temperatureMultiDistribute"
, memorysize, "double"); goto cleanup; } }
;
2776 for (i = 0; i < feaLoad->numGridID; i++)
2777 copy->temperatureMultiDistribute[i] = feaLoad->temperatureMultiDistribute[i];
2778 } else {
2779 copy->temperatureMultiDistribute = NULL((void*)0);
2780 }
2781
2782cleanup:
2783 return status;
2784}
2785
2786// Destroy (0 out all values and NULL all pointers) of feaLoad in the feaLoadStruct structure format
2787int destroy_feaLoadStruct(feaLoadStruct *feaLoad) {
2788
2789 AIM_FREE(feaLoad->name){ EG_free(feaLoad->name); feaLoad->name = ((void*)0); }; // Load name
2790
2791 feaLoad->loadType = UnknownLoad; // Load type
2792
2793 feaLoad->loadID = 0; // ID number of load
2794
2795 feaLoad->loadScaleFactor = 1; // Scale factor for when combining loads
2796
2797 // Concentrated force at a grid point
2798 feaLoad->numGridID = 0; // Number of grid IDs in grid ID set
2799 AIM_FREE(feaLoad->gridIDSet){ EG_free(feaLoad->gridIDSet); feaLoad->gridIDSet = ((void
*)0); }
; // List of grid IDs to apply the constraint to
2800
2801 feaLoad->coordSystemID= 0; // Component number of coordinate system in which force vector is specified
2802 feaLoad->forceScaleFactor= 0; // Overall scale factor for the force
2803 feaLoad->directionVector[0] = 0; // [0]-x, [1]-y, [2]-z components of the force vector
2804 feaLoad->directionVector[1] = 0;
2805 feaLoad->directionVector[2] = 0;
2806
2807 // Concentrated moment at a grid pofeaLoad->(also uses coordSystemID and directionVector)
2808 feaLoad->momentScaleFactor= 0; // Overall scale factor for the moment
2809
2810 // Gravitational load (also uses coordSystemID and directionVector)
2811 feaLoad->gravityAcceleration= 0; // Gravitational acceleration
2812
2813 // Pressure load
2814 feaLoad->pressureForce= 0; // Pressure value
2815
2816 feaLoad->pressureDistributeForce[0] = 0; // Pressure load at a specified grid location in the element
2817 feaLoad->pressureDistributeForce[1] = 0;
2818 feaLoad->pressureDistributeForce[2] = 0;
2819 feaLoad->pressureDistributeForce[3] = 0;
2820
2821 // Unique pressure load at a specified grid location for
2822 //each element in elementIDSet size = [4*numElementID]- used in type PressureExternal
2823 AIM_FREE(feaLoad->pressureMultiDistributeForce){ EG_free(feaLoad->pressureMultiDistributeForce); feaLoad->
pressureMultiDistributeForce = ((void*)0); }
;
2824
2825
2826 feaLoad->numElementID = 0; // Number of elements IDs in element ID set
2827 AIM_FREE(feaLoad->elementIDSet){ EG_free(feaLoad->elementIDSet); feaLoad->elementIDSet
= ((void*)0); }
; // List element IDs in which to apply the load
2828
2829 // Rotational velocity (also uses coordSystemID and directionVector)
2830 feaLoad->angularVelScaleFactor = 0.0; // Overall scale factor for the angular velocity
2831 feaLoad->angularAccScaleFactor = 0.0; // Overall scale factor for the angular acceleration
2832
2833 // Thermal load - the temperature at a grid point - use gridIDSet
2834 feaLoad->temperature = 0.0; // Temperature value
2835 feaLoad->temperatureDefault = 0.0; // Default temperature of grid point explicitly not used
2836
2837 AIM_FREE(feaLoad->temperatureMultiDistribute){ EG_free(feaLoad->temperatureMultiDistribute); feaLoad->
temperatureMultiDistribute = ((void*)0); }
;
2838
2839 return CAPS_SUCCESS0;
2840}
2841
2842// Initiate (0 out all values and NULL all pointers) of feaDesignVariable in the feaDesignVariableStruct structure format
2843int initiate_feaDesignVariableStruct(feaDesignVariableStruct *feaDesignVariable) {
2844
2845 feaDesignVariable->name = NULL((void*)0);
2846
2847 feaDesignVariable->designVariableID = 0; // ID number of design variable
2848
2849
2850 feaDesignVariable->initialValue = 0.0; // Initial value of design variable
2851 feaDesignVariable->lowerBound = 0.0; // Lower bounds of variable
2852 feaDesignVariable->upperBound = 0.0; // Upper bounds of variable
2853 feaDesignVariable->maxDelta= 0.0; // Move limit for design variable
2854
2855 feaDesignVariable->numDiscreteValue = 0; // Number of discrete values that a design variable can assume
2856
2857 feaDesignVariable->discreteValue = NULL((void*)0); // List of discrete values that a design variable can assume;
2858
2859 feaDesignVariable->numIndependVariable = 0; // Number of independent variables this variables depends on
2860 feaDesignVariable->independVariable = NULL((void*)0); // List of independent variable names, size[numIndependVariable]
2861 feaDesignVariable->independVariableID = NULL((void*)0);// List of independent variable designVariableIDs, size[numIndependVariable]
2862 feaDesignVariable->independVariableWeight = NULL((void*)0); // List of independent variable weights, size[numIndependVariable]
2863
2864 feaDesignVariable->variableWeight[0] = 0.0; // Weight to apply to if variable is dependent
2865 feaDesignVariable->variableWeight[1] = 0.0;
2866
2867 feaDesignVariable->numRelation = 0;
2868 feaDesignVariable->relationSet = NULL((void*)0);
2869
2870 return CAPS_SUCCESS0;
2871}
2872
2873// Initiate (0 out all values and NULL all pointers) of feaDesignVariable in the feaDesignVariableStruct structure format
2874int destroy_feaDesignVariableStruct(feaDesignVariableStruct *feaDesignVariable) {
2875
2876 if (feaDesignVariable->name != NULL((void*)0)) EG_free(feaDesignVariable->name);
2877 feaDesignVariable->name = NULL((void*)0);
2878
2879 feaDesignVariable->designVariableID = 0; // ID number of design variable
2880
2881 feaDesignVariable->initialValue = 0.0; // Initial value of design variable
2882 feaDesignVariable->lowerBound = 0.0; // Lower bounds of variable
2883 feaDesignVariable->upperBound = 0.0; // Upper bounds of variable
2884 feaDesignVariable->maxDelta= 0.0; // Move limit for design variable
2885
2886 feaDesignVariable->numDiscreteValue = 0; // Number of discrete values that a design variable can assume;
2887 if (feaDesignVariable->discreteValue != NULL((void*)0)) EG_free(feaDesignVariable->discreteValue);
2888 feaDesignVariable->discreteValue = NULL((void*)0); // List of discrete values that a design variable can assume;
2889
2890 (void) string_freeArray(feaDesignVariable->numIndependVariable, &feaDesignVariable->independVariable);
2891 feaDesignVariable->independVariable = NULL((void*)0); // List of independent variable names, size[numIndependVariable]
2892
2893 feaDesignVariable->numIndependVariable = 0; // Number of independent variables this variables depends on
2894
2895 if (feaDesignVariable->independVariableID != NULL((void*)0)) EG_free(feaDesignVariable->independVariableID);
2896 feaDesignVariable->independVariableID = NULL((void*)0);// List of independent variable designVariableIDs
2897
2898 if (feaDesignVariable->independVariableWeight != NULL((void*)0)) EG_free(feaDesignVariable->independVariableWeight);
2899 feaDesignVariable->independVariableWeight = NULL((void*)0); // List of independent variable weights, size[numIndependVariable]
2900
2901 feaDesignVariable->variableWeight[0] = 0.0; // Weight to apply to if variable is dependent
2902 feaDesignVariable->variableWeight[1] = 0.0;
2903
2904 feaDesignVariable->numRelation = 0;
2905 if (feaDesignVariable->relationSet != NULL((void*)0)) EG_free(feaDesignVariable->relationSet);
2906
2907 return CAPS_SUCCESS0;
2908
2909}
2910
2911// Initiate (0 out all values and NULL all pointers) of feaDesignConstraint in the feaDesignConstraintStruct structure format
2912int initiate_feaDesignConstraintStruct(feaDesignConstraintStruct *feaDesignConstraint) {
2913
2914 feaDesignConstraint->name = NULL((void*)0);
2915
2916 feaDesignConstraint->designConstraintID = 0; // ID number of design constraint
2917
2918 feaDesignConstraint->designConstraintType = UnknownDesignCon;
2919
2920 feaDesignConstraint->responseType = NULL((void*)0); // Response type options for DRESP1 Entry
2921
2922 feaDesignConstraint->lowerBound = 0.0; // Lower bounds of design response
2923 feaDesignConstraint->upperBound = 0.0; // Upper bounds of design response
2924
2925 feaDesignConstraint->numPropertyID = 0; // Number of property ID to apply the design variable to
2926 feaDesignConstraint->propertySetID = NULL((void*)0); // List of property IDs
2927 feaDesignConstraint->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
2928
2929 feaDesignConstraint->fieldPosition = 0; // Position in card to apply design variable to
2930 feaDesignConstraint->fieldName = NULL((void*)0); // Name of property/material to apply design variable to
2931
2932 feaDesignConstraint->velocityType = NULL((void*)0);
2933 feaDesignConstraint->scalingFactor = 0.0;
2934
2935 feaDesignConstraint->numVelocity = 0;
2936 feaDesignConstraint->velocity = NULL((void*)0);
2937
2938 feaDesignConstraint->numDamping = 0;
2939 feaDesignConstraint->damping = NULL((void*)0);
2940
2941 return CAPS_SUCCESS0;
2942}
2943
2944// Destroy (0 out all values and NULL all pointers) of feaDesignConstraint in the feaDesignConstraintStruct structure format
2945int destroy_feaDesignConstraintStruct(feaDesignConstraintStruct *feaDesignConstraint) {
2946
2947 if (feaDesignConstraint->name != NULL((void*)0)) EG_free(feaDesignConstraint->name);
2948 feaDesignConstraint->name = NULL((void*)0);
2949
2950 feaDesignConstraint->designConstraintID = 0; // ID number of design constraint
2951
2952 feaDesignConstraint->designConstraintType = UnknownDesignCon;
2953
2954 if (feaDesignConstraint->responseType != NULL((void*)0)) EG_free(feaDesignConstraint->responseType);
2955 feaDesignConstraint->responseType = NULL((void*)0); // Response type options for DRESP1 Entry
2956
2957 feaDesignConstraint->lowerBound = 0.0; // Lower bounds of design response
2958 feaDesignConstraint->upperBound = 0.0; // Upper bounds of design response
2959
2960 feaDesignConstraint->numPropertyID = 0; // Number of property ID to apply the design variable to
2961
2962 if (feaDesignConstraint->propertySetID != NULL((void*)0)) EG_free(feaDesignConstraint->propertySetID);
2963 feaDesignConstraint->propertySetID = NULL((void*)0); // List of property IDs
2964
2965 if (feaDesignConstraint->propertySetType != NULL((void*)0)) EG_free(feaDesignConstraint->propertySetType);
2966 feaDesignConstraint->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
2967
2968 feaDesignConstraint->fieldPosition = 0; // Position in card to apply design variable to
2969 if (feaDesignConstraint->fieldName != NULL((void*)0)) EG_free(feaDesignConstraint->fieldName);
2970 feaDesignConstraint->fieldName = NULL((void*)0); // Name of property/material to apply design variable to
2971
2972 if (feaDesignConstraint->velocityType != NULL((void*)0)) EG_free(feaDesignConstraint->velocityType);
2973 feaDesignConstraint->velocityType = NULL((void*)0);
2974 feaDesignConstraint->scalingFactor = 0.0;
2975
2976 if (feaDesignConstraint->velocity != NULL((void*)0)) EG_free(feaDesignConstraint->velocity);
2977 feaDesignConstraint->numVelocity = 0;
2978 feaDesignConstraint->velocity = NULL((void*)0);
2979
2980 if (feaDesignConstraint->damping != NULL((void*)0)) EG_free(feaDesignConstraint->damping);
2981 feaDesignConstraint->numDamping = 0;
2982 feaDesignConstraint->damping = NULL((void*)0);
2983
2984 return CAPS_SUCCESS0;
2985
2986}
2987
2988// Initiate (0 out all values and NULL all pointers) of feaOptimizationControl in the feaOptimizationControlStruct structure format
2989int initiate_feaOptimizationControlStruct(feaOptimizationControlStruct *feaOptimizationControl) {
2990
2991 feaOptimizationControl->fullyStressedDesign = 0; // ASTROS specific - fully stressed design number of iterations
2992 feaOptimizationControl->mathProgramming = 0; // Math programming number of iteratinons
2993 feaOptimizationControl->maxIter = 0; // Maximum number of optimization iterations
2994 feaOptimizationControl->constraintRetention = 0.0; // Constraint retention factor
2995 feaOptimizationControl->eps = 0.0; // A different constraint retention factor?
2996 feaOptimizationControl->moveLimit = 0.0; // Move limit
2997
2998 return CAPS_SUCCESS0;
2999}
3000
3001// Destroy (0 out all values and NULL all pointers) of feaOptimizationControl in the feaOptimizationControlStruct structure format
3002int destroy_feaOptimzationControlStruct(feaOptimizationControlStruct *feaOptimizationControl) {
3003
3004 feaOptimizationControl->fullyStressedDesign = 0; // ASTROS specific - fully stressed design number of iterations
3005 feaOptimizationControl->mathProgramming = 0; // Math programming number of iteratinons
3006 feaOptimizationControl->maxIter = 0; // Maximum number of optimization iterations
3007 feaOptimizationControl->constraintRetention = 0.0; // Constraint retention factor
3008 feaOptimizationControl->eps = 0.0; // A different constraint retention factor?
3009 feaOptimizationControl->moveLimit = 0.0; // Move limit
3010
3011 return CAPS_SUCCESS0;
3012}
3013
3014// Initiate (0 out all values and NULL all pointers) of feaCoordSystem in the feaCoordSystemStruct structure format
3015int initiate_feaCoordSystemStruct(feaCoordSystemStruct *feaCoordSystem) {
3016
3017 int i; // Indexing
3018
3019 feaCoordSystem->name = NULL((void*)0); // Coordinate system name
3020
3021 feaCoordSystem->coordSystemType = UnknownCoordSystem; // Coordinate system type
3022
3023 feaCoordSystem->coordSystemID = 0; // ID number of coordinate system
3024 feaCoordSystem->refCoordSystemID = 0; // ID of reference coordinate system
3025
3026 for (i = 0; i < 3; i++) {
3027 feaCoordSystem->origin[i] = 0; // x, y, and z coordinates for the origin
3028
3029 feaCoordSystem->normal1[i] = 0; // First normal direction
3030 feaCoordSystem->normal2[i] = 0; // Second normal direction
3031 feaCoordSystem->normal3[i] = 0; // Third normal direction - found from normal1 x normal2
3032 }
3033
3034 return CAPS_SUCCESS0;
3035}
3036
3037// Destroy (0 out all values and NULL all pointers) of feaCoordSystem in the feaCoordSystemStruct structure format
3038int destroy_feaCoordSystemStruct(feaCoordSystemStruct *feaCoordSystem) {
3039
3040 int i; // Indexing
3041
3042 if (feaCoordSystem->name != NULL((void*)0)) EG_free(feaCoordSystem->name);
3043 feaCoordSystem->name = NULL((void*)0); // Coordinate system name
3044
3045 feaCoordSystem->coordSystemType = UnknownCoordSystem; // Coordinate system type
3046
3047 feaCoordSystem->coordSystemID = 0; // ID number of coordinate system
3048 feaCoordSystem->refCoordSystemID = 0; // ID of reference coordinate system
3049
3050 for (i = 0; i < 3; i++) {
3051 feaCoordSystem->origin[i] = 0; // x, y, and z coordinates for the origin
3052
3053 feaCoordSystem->normal1[i] = 0; // First normal direction
3054 feaCoordSystem->normal2[i] = 0; // Second normal direction
3055 feaCoordSystem->normal3[i] = 0; // Third normal direction - found from normal1 x normal2
3056 }
3057
3058 return CAPS_SUCCESS0;
3059}
3060
3061// Initiate (0 out all values and NULL all pointers) of feaAero in the feaAeroStruct structure format
3062int initiate_feaAeroStruct(feaAeroStruct *feaAero) {
3063
3064 int status; // Function return status
3065
3066 feaAero->name = NULL((void*)0); // Coordinate system name
3067
3068 feaAero->surfaceID = 0; // Surface ID
3069 feaAero->coordSystemID = 0; // Coordinate system ID
3070
3071 feaAero->numGridID = 0; // Number of grid IDs in grid ID set for the spline
3072 feaAero->gridIDSet = NULL((void*)0); // List of grid IDs to apply spline to. size = [numGridID]
3073
3074 status = initiate_vlmSurfaceStruct(&feaAero->vlmSurface);
3075 if (status != CAPS_SUCCESS0) printf("Status %d during initiate_vlmSurfaceStruct\n", status);
3076
3077 return CAPS_SUCCESS0;
3078}
3079
3080// Destroy (0 out all values and NULL all pointers) of feaAero in the feaAeroStruct structure format
3081int destroy_feaAeroStruct(feaAeroStruct *feaAero) {
3082
3083 int status; // Function return status
3084
3085 if (feaAero->name != NULL((void*)0)) EG_free(feaAero->name);
3086 feaAero->name = NULL((void*)0); // Coordinate system name
3087
3088 feaAero->surfaceID = 0; // Surface ID
3089 feaAero->coordSystemID = 0; // Coordinate system ID
3090
3091 feaAero->numGridID = 0; // Number of grid IDs in grid ID set for the spline
3092
3093 if (feaAero->gridIDSet != NULL((void*)0)) EG_free(feaAero->gridIDSet);
3094 feaAero->gridIDSet = NULL((void*)0); // List of grid IDs to apply spline to. size = [numGridID]
3095
3096 status = destroy_vlmSurfaceStruct(&feaAero->vlmSurface);
3097 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_vlmSurfaceStruct\n", status);
3098
3099 return CAPS_SUCCESS0;
3100}
3101
3102// Initiate (0 out all values and NULL all pointers) of feaAeroRef in the feaAeroRefStruct structure format
3103int initiate_feaAeroRefStruct(feaAeroRefStruct *feaAeroRef) {
3104
3105 feaAeroRef->coordSystemID = 0; // Aerodynamic coordinate sytem id
3106 feaAeroRef->rigidMotionCoordSystemID = 0; // Reference coordinate system identification for rigid body motions.
3107
3108 feaAeroRef->refChord = 1.0; // Reference chord length. Reference span. (Real > 0.0)
3109 feaAeroRef->refSpan = 1.0; // Reference span
3110 feaAeroRef->refArea = 1.0; // Reference area
3111 feaAeroRef->refGridID = 0;
3112
3113 feaAeroRef->symmetryXZ = 0; // Symmetry key for the aero coordinate x-z plane. (Integer = +1 for symmetry, 0 for no symmetry,
3114 // and -1 for antisymmetry; Default = 0)
3115 feaAeroRef->symmetryXY = 0; // The symmetry key for the aero coordinate x-y plane can be used to simulate ground effects.
3116 // (Integer = +1 for antisymmetry, 0 for no symmetry, and -1 for symmetry; Default = 0)
3117 return CAPS_SUCCESS0;
3118}
3119
3120// Destroy (0 out all values and NULL all pointers) of feaAeroRef in the feaAeroRefStruct structure format
3121int destroy_feaAeroRefStruct(feaAeroRefStruct *feaAeroRef) {
3122
3123 feaAeroRef->coordSystemID = 0; // Aerodynamic coordinate sytem id
3124 feaAeroRef->rigidMotionCoordSystemID = 0; // Reference coordinate system identification for rigid body motions.
3125
3126 feaAeroRef->refChord = 0; // Reference chord length. Reference span. (Real > 0.0)
3127 feaAeroRef->refSpan = 0; // Reference span
3128 feaAeroRef->refArea = 0; // Reference area
3129 feaAeroRef->refGridID = 0;
3130
3131 feaAeroRef->symmetryXZ = 0; // Symmetry key for the aero coordinate x-z plane. (Integer = +1 for symmetry, 0 for no symmetry,
3132 // and -1 for antisymmetry; Default = 0)
3133 feaAeroRef->symmetryXY = 0; // The symmetry key for the aero coordinate x-y plane can be used to simulate ground effects.
3134 // (Integer = +1 for antisymmetry, 0 for no symmetry, and -1 for symmetry; Default = 0)
3135 return CAPS_SUCCESS0;
3136}
3137
3138// Initiate (0 out all values and NULL all pointers) of feaConnect in the feaConnectionStruct structure format
3139int initiate_feaConnectionStruct(feaConnectionStruct *feaConnect) {
3140
3141 feaConnect->name = NULL((void*)0); // Connection name
3142
3143 feaConnect->connectionID =0; // Connection ID
3144
3145 feaConnect->connectionType = UnknownConnection; // Connection type
3146
3147 feaConnect->elementID = 0;
3148
3149 // RBE2 - dependent degrees of freedom
3150 feaConnect->connectivity[0] = 0; // Grid IDs - 0 index = Independent grid ID, 1 index = Dependent grid ID
3151 feaConnect->connectivity[1] = 0;
3152 feaConnect->dofDependent = 0;
3153
3154 // Spring
3155 feaConnect->stiffnessConst = 0.0;
3156 feaConnect->componentNumberStart = 0;
3157 feaConnect->componentNumberEnd = 0;
3158 feaConnect->dampingConst = 0.0;
3159 feaConnect->stressCoeff = 0.0;
3160
3161 // Damper - see spring for additional entries
3162
3163 // Mass (scalar) - see spring for additional entries
3164 feaConnect->mass = 0.0;
3165
3166 // RBE3 - master/slave
3167 feaConnect->numMaster = 0;
3168 feaConnect->masterIDSet = NULL((void*)0); // Independent
3169 feaConnect->masterWeighting = NULL((void*)0);
3170 feaConnect->masterComponent = NULL((void*)0);
3171
3172 return CAPS_SUCCESS0;
3173}
3174
3175// Destroy (0 out all values and NULL all pointers) of feaConnect in the feaConnectionStruct structure format
3176int destroy_feaConnectionStruct(feaConnectionStruct *feaConnect) {
3177
3178 if (feaConnect->name != NULL((void*)0)) EG_free(feaConnect->name);
3179 feaConnect->name = NULL((void*)0); // Connection name
3180
3181 feaConnect->connectionID =0; // Connection ID
3182
3183 feaConnect->connectionType = UnknownConnection; // Connection type
3184
3185 feaConnect->elementID = 0;
3186
3187 // RBE2 - dependent degrees of freedom
3188 feaConnect->connectivity[0] = 0; // Grid IDs - 0 index = Independent grid ID, 1 index = Dependent grid ID
3189 feaConnect->connectivity[1] = 0;
3190 feaConnect->dofDependent = 0;
3191
3192 // Spring
3193 feaConnect->stiffnessConst = 0.0;
3194 feaConnect->componentNumberStart = 0;
3195 feaConnect->componentNumberEnd = 0;
3196 feaConnect->dampingConst = 0.0;
3197 feaConnect->stressCoeff = 0.0;
3198
3199 // Damper - see spring for additional entries
3200
3201 // Mass (scalar) - see spring for additional entries
3202 feaConnect->mass = 0.0;
3203
3204 // RBE3 - master/slave
3205 feaConnect->numMaster = 0;
3206 if (feaConnect->masterIDSet != NULL((void*)0)) EG_free(feaConnect->masterIDSet);
3207 feaConnect->masterIDSet = NULL((void*)0); // Independent
3208 if (feaConnect->masterWeighting != NULL((void*)0)) EG_free(feaConnect->masterWeighting);
3209 feaConnect->masterWeighting = NULL((void*)0);
3210 if (feaConnect->masterComponent != NULL((void*)0)) EG_free(feaConnect->masterComponent);
3211 feaConnect->masterComponent = NULL((void*)0);
3212
3213 return CAPS_SUCCESS0;
3214}
3215
3216int initiate_feaDesignEquationStruct(feaDesignEquationStruct *equation) {
3217
3218 if (equation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3219
3220 equation->equationID = 0;
3221 equation->name = NULL((void*)0);
3222 equation->equationArraySize = 0;
3223 equation->equationArray = NULL((void*)0);
3224
3225 return CAPS_SUCCESS0;
3226}
3227
3228int destroy_feaDesignEquationStruct(feaDesignEquationStruct *equation) {
3229
3230 int i;
3231
3232 if (equation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3233
3234 if (equation->name != NULL((void*)0)) EG_free(equation->name);
3235
3236 if (equation->equationArray != NULL((void*)0)) {
3237 for (i = 0; i < equation->equationArraySize; i++) {
3238 if (equation->equationArray[i] != NULL((void*)0)) {
3239 EG_free(equation->equationArray[i]);
3240 }
3241 }
3242 EG_free(equation->equationArray);
3243 }
3244
3245 return initiate_feaDesignEquationStruct(equation);
3246}
3247
3248int initiate_feaDesignResponseStruct(feaDesignResponseStruct *response) {
3249
3250 if (response == NULL((void*)0)) return CAPS_NULLVALUE-307;
3251
3252 response->responseID = 0;
3253
3254 response->name = NULL((void*)0);
3255
3256 response->responseType = NULL((void*)0);
3257 response->propertyType = NULL((void*)0);
3258
3259 response->region = 0;
3260
3261 response->component = 0; // Component number
3262 response->itemCode = 0; // Item code
3263 response->modeNumber = 0; // Mode number
3264
3265 response->lamina = 0; // Lamina number
3266 response->frequency = 0.0; // Frequency value
3267 response->time = 0.0; // Time value
3268 response->restraintFlag = 0; // Restraint flag
3269
3270 response->gridID = 0; // Grid ID
3271 response->propertyID = 0; // Property entry ID
3272
3273 return CAPS_SUCCESS0;
3274}
3275
3276int destroy_feaDesignResponseStruct(feaDesignResponseStruct *response) {
3277
3278 if (response == NULL((void*)0)) return CAPS_NULLVALUE-307;
3279
3280 if (response->name != NULL((void*)0)) EG_free(response->name);
3281
3282 if (response->responseType != NULL((void*)0)) EG_free(response->responseType);
3283 if (response->propertyType != NULL((void*)0)) EG_free(response->propertyType);
3284
3285 return initiate_feaDesignResponseStruct(response);
3286}
3287
3288int initiate_feaDesignEquationResponseStruct(feaDesignEquationResponseStruct* equationResponse) {
3289
3290 if (equationResponse == NULL((void*)0)) return CAPS_NULLVALUE-307;
3291
3292 equationResponse->equationResponseID = 0;
3293
3294 equationResponse->name = NULL((void*)0); // Name of the equation
3295
3296 equationResponse->equationName = NULL((void*)0);
3297
3298 equationResponse->region = 0; // Region identifier for constant screening
3299
3300 equationResponse->numDesignVariable = 0;
3301 equationResponse->designVariableNameSet = NULL((void*)0); // Design variable names, size = [numDesignVariable]
3302
3303 equationResponse->numConstant = 0;
3304 equationResponse->constantLabelSet = NULL((void*)0); // Labels of the table constants, size = [numConstant]
3305
3306 equationResponse->numResponse = 0;
3307 equationResponse->responseNameSet = NULL((void*)0); // Names of design sensitivity response quantities, size = [numResponse]
3308
3309 equationResponse->numGrid = 0;
3310 equationResponse->gridIDSet = NULL((void*)0); // Grid IDs, size = [numGrid]
3311 equationResponse->dofNumberSet = NULL((void*)0); // Degree of freedom numbers, size = [numGrid]
3312
3313 equationResponse->numEquationResponse = 0;
3314 equationResponse->equationResponseNameSet = NULL((void*)0); // Names of design sensitivity equation response quantities, size = [numEquationResponse]
3315
3316 return CAPS_SUCCESS0;
3317}
3318
3319int destroy_feaDesignEquationResponseStruct(feaDesignEquationResponseStruct* equationResponse) {
3320
3321 if (equationResponse == NULL((void*)0)) return CAPS_NULLVALUE-307;
3322
3323 if (equationResponse->name != NULL((void*)0)) EG_free(equationResponse->name);
3324
3325 if (equationResponse->equationName != NULL((void*)0)) EG_free(equationResponse->equationName);
3326
3327 if (equationResponse->designVariableNameSet != NULL((void*)0)) {
3328 string_freeArray(equationResponse->numDesignVariable, &equationResponse->designVariableNameSet);
3329 }
3330
3331 if (equationResponse->constantLabelSet != NULL((void*)0)) {
3332 string_freeArray(equationResponse->numConstant, &equationResponse->constantLabelSet);
3333 }
3334
3335 if (equationResponse->responseNameSet != NULL((void*)0)) {
3336 string_freeArray(equationResponse->numResponse, &equationResponse->responseNameSet);
3337 }
3338
3339 if (equationResponse->gridIDSet != NULL((void*)0)) EG_free(equationResponse->gridIDSet);
3340 if (equationResponse->dofNumberSet != NULL((void*)0)) EG_free(equationResponse->dofNumberSet);
3341
3342 if (equationResponse->equationResponseNameSet != NULL((void*)0)) {
3343 string_freeArray(equationResponse->numEquationResponse, &equationResponse->equationResponseNameSet);
3344 }
3345
3346 return initiate_feaDesignEquationResponseStruct(equationResponse);
3347}
3348
3349int initiate_feaDesignTableStruct(feaDesignTableStruct *table) {
3350
3351 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3352
3353 table->numConstant = 0;
3354 table->constantLabel = NULL((void*)0);
3355 table->constantValue = NULL((void*)0);
3356
3357 return CAPS_SUCCESS0;
3358}
3359
3360int destroy_feaDesignTableStruct(feaDesignTableStruct *table) {
3361
3362 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3363
3364 if (table->constantLabel != NULL((void*)0)) string_freeArray(table->numConstant, &table->constantLabel);
3365 if (table->constantValue != NULL((void*)0)) EG_free(table->constantValue);
3366
3367 return initiate_feaDesignTableStruct(table);
3368}
3369
3370
3371int initiate_feaDesignOptParamStruct(feaDesignOptParamStruct *table) {
3372
3373 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3374
3375 table->numParam = 0;
3376 table->paramLabel = NULL((void*)0);
3377 table->paramValue = NULL((void*)0);
3378 table->paramType = NULL((void*)0);
3379
3380 return CAPS_SUCCESS0;
3381}
3382
3383int destroy_feaDesignOptParamStruct(feaDesignOptParamStruct *table) {
3384
3385 int i;
3386
3387 if (table == NULL((void*)0)) return CAPS_NULLVALUE-307;
3388
3389 if (table->paramLabel != NULL((void*)0)) string_freeArray(table->numParam, &table->paramLabel);
3390
3391 if (table->paramValue != NULL((void*)0)) {
3392 for (i = 0; i < table->numParam; i++) {
3393 if (table->paramValue[i] != NULL((void*)0)) {
3394 EG_free(table->paramValue[i]);
3395 }
3396 }
3397 EG_free(table->paramValue);
3398 }
3399
3400 if (table->paramType != NULL((void*)0)) EG_free(table->paramType);
3401
3402 return initiate_feaDesignOptParamStruct(table);
3403}
3404
3405int initiate_feaDesignVariableRelationStruct(feaDesignVariableRelationStruct *relation) {
3406
3407 if (relation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3408
3409 relation->name = NULL((void*)0);
3410
3411 relation->componentType = 0;
3412
3413 relation->relationID = 0;
3414
3415 relation->numDesignVariable = 0;
3416 relation->designVariableNameSet = NULL((void*)0);
3417 relation->designVariableSet = NULL((void*)0);
3418
3419 relation->fieldPosition = 0;
3420 relation->fieldName = NULL((void*)0);
3421
3422 relation->constantRelationCoeff = 0.0;
3423 relation->linearRelationCoeff = NULL((void*)0);
3424
3425 relation->numMaterialID = 0; // Number of materials to apply the design variable to
3426 relation->materialSetID = NULL((void*)0); // List of materials IDs
3427 relation->materialSetType = NULL((void*)0); // List of materials types corresponding to the materialSetID
3428
3429 relation->numPropertyID = 0; // Number of property ID to apply the design variable to
3430 relation->propertySetID = NULL((void*)0); // List of property IDs
3431 relation->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
3432
3433 relation->numElementID = 0; // Number of element ID to apply the design variable to
3434 relation->elementSetID = NULL((void*)0); // List of element IDs
3435 relation->elementSetType = NULL((void*)0); // List of element types corresponding to the elementSetID
3436 relation->elementSetSubType = NULL((void*)0); // List of element subtypes correspoding to the elementSetID
3437
3438 return CAPS_SUCCESS0;
3439}
3440
3441int destroy_feaDesignVariableRelationStruct(feaDesignVariableRelationStruct *relation) {
3442
3443 if (relation == NULL((void*)0)) return CAPS_NULLVALUE-307;
3444
3445 if (relation->designVariableNameSet != NULL((void*)0)) string_freeArray(relation->numDesignVariable, &relation->designVariableNameSet);
3446 if (relation->name != NULL((void*)0)) EG_free(relation->name);
3447 if (relation->designVariableSet != NULL((void*)0)) EG_free(relation->designVariableSet);
3448
3449 if (relation->fieldName != NULL((void*)0)) EG_free(relation->fieldName);
3450
3451 if (relation->linearRelationCoeff != NULL((void*)0)) EG_free(relation->linearRelationCoeff);
3452
3453 relation->numMaterialID = 0; // Number of materials to apply the design variable to
3454 if (relation->materialSetID != NULL((void*)0)) EG_free(relation->materialSetID);
3455 relation->materialSetID = NULL((void*)0); // List of materials IDs
3456
3457 if (relation->materialSetType != NULL((void*)0)) EG_free(relation->materialSetType);
3458 relation->materialSetType = NULL((void*)0); // List of materials types corresponding to the materialSetID
3459
3460 relation->numPropertyID = 0; // Number of property ID to apply the design variable to
3461 if (relation->propertySetID != NULL((void*)0)) EG_free(relation->propertySetID);
3462 relation->propertySetID = NULL((void*)0); // List of property IDs
3463
3464 if (relation->propertySetType != NULL((void*)0)) EG_free(relation->propertySetType);
3465 relation->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID
3466
3467 relation->numElementID = 0; // Number of element ID to apply the design variable to
3468 if (relation->elementSetID != NULL((void*)0)) EG_free(relation->elementSetID);
3469 relation->elementSetID = NULL((void*)0); // List of element IDs
3470
3471 if (relation->elementSetType != NULL((void*)0)) EG_free(relation->elementSetType);
3472 relation->elementSetType = NULL((void*)0); // List of element types corresponding to the elementSetID
3473
3474 if (relation->elementSetSubType != NULL((void*)0)) EG_free(relation->elementSetSubType);
3475 relation->elementSetSubType = NULL((void*)0); // List of element subtypes correspoding to the elementSetID
3476
3477 return initiate_feaDesignVariableRelationStruct(relation);
3478}
3479
3480// Get the material properties from a capsTuple
3481int fea_getMaterial(void *aimInfo,
3482 int numMaterialTuple,
3483 capsTuple materialTuple[],
3484 feaUnitsStruct *feaUnits,
3485 int *numMaterial,
3486 feaMaterialStruct *feaMaterial[]) {
3487
3488 /*! \page feaMaterial FEA Material
3489 * Structure for the material tuple = ("Material Name", "Value").
3490 * "Material Name" defines the reference name for the material being specified.
3491 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringMaterial) or a single string keyword
3492 * (see Section \ref keyStringMaterial).
3493 */
3494
3495 int status; //Function return
3496
3497 int i; // Indexing
3498
3499 char *keyValue = NULL((void*)0);
3500 char *keyWord = NULL((void*)0);
3501
3502 // Destroy our material structures coming in if aren't 0 and NULL already
3503 if (*feaMaterial != NULL((void*)0)) {
3504 for (i = 0; i < *numMaterial; i++) {
3505 status = destroy_feaMaterialStruct(&(*feaMaterial)[i]);
3506 if (status != CAPS_SUCCESS0) return status;
3507 }
3508 }
3509 if (*feaMaterial != NULL((void*)0)) EG_free(*feaMaterial);
3510 *feaMaterial = NULL((void*)0);
3511 *numMaterial = 0;
3512
3513 printf("\nGetting FEA materials.......\n");
3514
3515 *numMaterial = numMaterialTuple;
3516 printf("\tNumber of materials - %d\n", *numMaterial);
3517
3518 if (*numMaterial > 0) {
3519 *feaMaterial = (feaMaterialStruct *) EG_alloc(*numMaterial * sizeof(feaMaterialStruct));
3520 if (*feaMaterial == NULL((void*)0)) return EGADS_MALLOC-4;
3521
3522 } else {
3523 printf("\tNumber of material values in input tuple is 0\n");
3524 return CAPS_NOTFOUND-303;
3525 }
3526
3527 for (i = 0; i < *numMaterial; i++) {
3528 status = initiate_feaMaterialStruct(&(*feaMaterial)[i]);
3529 if (status != CAPS_SUCCESS0) return status;
3530 }
3531
3532 for (i = 0; i < *numMaterial; i++) {
3533
3534 printf("\tMaterial name - %s\n", materialTuple[i].name);
3535
3536 (*feaMaterial)[i].name = (char *) EG_alloc(((strlen(materialTuple[i].name)) + 1)*sizeof(char));
3537 if ((*feaMaterial)[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
3538
3539 memcpy((*feaMaterial)[i].name, materialTuple[i].name, strlen(materialTuple[i].name)*sizeof(char));
3540 (*feaMaterial)[i].name[strlen(materialTuple[i].name)] = '\0';
3541
3542 (*feaMaterial)[i].materialID = i + 1;
3543
3544 // Do we have a json string?
3545 if (strncmp(materialTuple[i].value, "{", 1) == 0) {
3546 //printf("JSON String - %s\n", materialTuple[i].value);
3547
3548
3549 /*! \page feaMaterial
3550 * \section jsonStringMaterial JSON String Dictionary
3551 *
3552 * If "Value" is JSON string dictionary
3553 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS || MASSTRAN)
3554 * (e.g. "Value" = {"density": 7850, "youngModulus": 120000.0, "poissonRatio": 0.5, "materialType": "isotropic"})
3555 * \endif
3556 * the following keywords ( = default values) may be used:
3557 *
3558 * <ul>
3559 * <li> <B>materialType = "Isotropic"</B> </li> <br>
3560 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
3561 * Material property type. Options: Isotropic, Anisothotropic, Orthotropic, or Anisotropic.
3562 * \elseif MASSTRAN
3563 * Material property type. Options: Isotropic.
3564 * \endif
3565 * </ul>
3566 */
3567
3568 // Get material Type
3569 keyWord = "materialType";
3570 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3571 if (status == CAPS_SUCCESS0) {
3572
3573 //{UnknownMaterial, Isotropic, Anisothotropic, Orthotropic, Anisotropic}
3574 if (strcasecmp(keyValue, "\"Isotropic\"") == 0) (*feaMaterial)[i].materialType = Isotropic;
3575 else if (strcasecmp(keyValue, "\"Anisothotropic\"") == 0) (*feaMaterial)[i].materialType = Anisothotropic;
3576 else if (strcasecmp(keyValue, "\"Orthotropic\"") == 0) (*feaMaterial)[i].materialType = Orthotropic;
3577 else if (strcasecmp(keyValue, "\"Anisotropic\"") == 0) (*feaMaterial)[i].materialType = Anisotropic;
3578 else {
3579
3580 printf("\tUnrecognized \"%s\" specified (%s) for Material tuple %s, defaulting to \"Isotropic\"\n", keyWord,
3581 keyValue,
3582 materialTuple[i].name);
3583 (*feaMaterial)[i].materialType = Isotropic;
3584 }
3585
3586 } else {
3587
3588 printf("\tNo \"%s\" specified for Material tuple %s, defaulting to \"Isotropic\"\n", keyWord,
3589 materialTuple[i].name);
3590 (*feaMaterial)[i].materialType = Isotropic;
3591 }
3592 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3593
3594 //Fill up material properties
3595
3596 /*! \page feaMaterial
3597 *
3598 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS)
3599 * <ul>
3600 * <li> <B>youngModulus = 0.0</B> </li> <br>
3601 * Also known as the elastic modulus, defines the relationship between stress and strain.
3602 * Default if `shearModulus' and `poissonRatio' != 0, youngModulus = 2*(1+poissonRatio)*shearModulus
3603 * </ul>
3604 * \endif
3605 *
3606 */
3607 keyWord = "youngModulus";
3608 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3609 if (status == CAPS_SUCCESS0) {
3610 if ( feaUnits->pressure != NULL((void*)0) ) {
3611 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->pressure, &(*feaMaterial)[i].youngModulus);
3612 } else {
3613 status = string_toDouble(keyValue, &(*feaMaterial)[i].youngModulus);
3614 }
3615 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3615
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3616 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3617 }
3618
3619 /*! \page feaMaterial
3620 *
3621 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS)
3622 * <ul>
3623 * <li> <B>shearModulus = 0.0</B> </li> <br>
3624 * Also known as the modulus of rigidity, is defined as the ratio of shear stress to the shear strain.
3625 * Default if `youngModulus' and `poissonRatio' != 0, shearModulus = youngModulus/(2*(1+poissonRatio))
3626 * </ul>
3627 * \endif
3628 */
3629 keyWord = "shearModulus";
3630 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3631 if (status == CAPS_SUCCESS0) {
3632
3633 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulus);
3634 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3634
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3635 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3636 }
3637
3638 /*! \page feaMaterial
3639 *
3640 *
3641 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS)
3642 * <ul>
3643 * <li> <B>poissonRatio = 0.0</B> </li> <br>
3644 * The fraction of expansion divided by the fraction of compression.
3645 * Default if `youngModulus' and `shearModulus' != 0, poissonRatio = (2*youngModulus/shearModulus) - 1
3646 * </ul>
3647 * \endif
3648 */
3649 keyWord = "poissonRatio";
3650 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3651 if (status == CAPS_SUCCESS0) {
3652
3653 status = string_toDouble(keyValue, &(*feaMaterial)[i].poissonRatio);
3654 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3654
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3655 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3656 }
3657
3658 // Check Young's modulus, shear modulus, and Poisson's ratio
3659 if ( ((*feaMaterial)[i].youngModulus == 0 && (*feaMaterial)[i].poissonRatio == 0) ||
3660 ((*feaMaterial)[i].shearModulus == 0 && (*feaMaterial)[i].poissonRatio == 0) ||
3661 ((*feaMaterial)[i].youngModulus == 0 && (*feaMaterial)[i].shearModulus == 0) ) {
3662 // Do nothing
3663
3664 } else if ((*feaMaterial)[i].youngModulus == 0) {
3665 (*feaMaterial)[i].youngModulus = 2*(1+(*feaMaterial)[i].poissonRatio)*(*feaMaterial)[i].shearModulus;
3666 } else if ((*feaMaterial)[i].shearModulus == 0) {
3667 (*feaMaterial)[i].shearModulus = (*feaMaterial)[i].youngModulus/(2*(1+(*feaMaterial)[i].poissonRatio));
3668 } else if ((*feaMaterial)[i].poissonRatio == 0) {
3669 (*feaMaterial)[i].poissonRatio = (*feaMaterial)[i].youngModulus/(2*(*feaMaterial)[i].shearModulus) -1;
3670 }
3671
3672 /*! \page feaMaterial
3673 *
3674 *
3675 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || MASSTRAN)
3676 * <ul>
3677 * <li> <B>density = 0.0</B> </li> <br>
3678 * Density of the material.
3679 * </ul>
3680 * \endif
3681 */
3682 keyWord = "density";
3683 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3684 if (status == CAPS_SUCCESS0) {
3685 if ( feaUnits->densityVol != NULL((void*)0) ) {
3686 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->densityVol, &(*feaMaterial)[i].density);
3687 } else {
3688 status = string_toDouble(keyValue, &(*feaMaterial)[i].density);
3689 }
3690 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3690
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3691 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3692 }
3693
3694 /*! \page feaMaterial
3695 *
3696 * \if (MYSTRAN || NASTRAN || ASTROS)
3697 * <ul>
3698 * <li> <B>thermalExpCoeff = 0.0</B> </li> <br>
3699 * Thermal expansion coefficient of the material.
3700 * </ul>
3701 * \endif
3702 */
3703 keyWord = "thermalExpCoeff";
3704 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3705 if (status == CAPS_SUCCESS0) {
3706
3707 status = string_toDouble(keyValue, &(*feaMaterial)[i].thermalExpCoeff);
3708 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3708
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3709 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3710 }
3711
3712 /*! \page feaMaterial
3713 *
3714 * \if (MYSTRAN || NASTRAN || ASTROS)
3715 * <ul>
3716 * <li> <B>thermalExpCoeffLateral = 0.0</B> </li> <br>
3717 * Thermal expansion coefficient of the material.
3718 * </ul>
3719 * \endif
3720 */
3721 keyWord = "thermalExpCoeffLateral";
3722 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3723 if (status == CAPS_SUCCESS0) {
3724
3725 status = string_toDouble(keyValue, &(*feaMaterial)[i].thermalExpCoeffLateral);
3726 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3726
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3727 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3728 }
3729
3730 /*! \page feaMaterial
3731 *
3732 *
3733 * \if (MYSTRAN || NASTRAN || ASTROS)
3734 * <ul>
3735 * <li> <B>temperatureRef = 0.0</B> </li> <br>
3736 * Reference temperature for material properties.
3737 * </ul>
3738 * \endif
3739 */
3740 keyWord = "temperatureRef";
3741 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3742 if (status == CAPS_SUCCESS0) {
3743
3744 status = string_toDouble(keyValue, &(*feaMaterial)[i].temperatureRef);
3745 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3745
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3746 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3747 }
3748
3749 /*! \page feaMaterial
3750 *
3751 * \if (MYSTRAN || NASTRAN || ASTROS)
3752 * <ul>
3753 * <li> <B>dampingCoeff = 0.0</B> </li> <br>
3754 * Damping coefficient for the material.
3755 * </ul>
3756 * \endif
3757 */
3758 keyWord = "dampingCoeff";
3759 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3760 if (status == CAPS_SUCCESS0) {
3761
3762 status = string_toDouble(keyValue, &(*feaMaterial)[i].dampingCoeff);
3763 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3763
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3764 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3765 }
3766
3767 /*! \page feaMaterial
3768 *
3769 *
3770 * \if NASTRAN
3771 * <ul>
3772 * <li> <B>yieldAllow = 0.0</B> </li> <br>
3773 * Yield strength/allowable for the material.
3774 * </ul>
3775 * \endif
3776 */
3777 keyWord = "yieldAllow";
3778 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3779 if (status == CAPS_SUCCESS0) {
3780
3781 status = string_toDouble(keyValue, &(*feaMaterial)[i].yieldAllow);
3782 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3782
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3783 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3784 }
3785
3786 /*! \page feaMaterial
3787 *
3788 *
3789 * \if NASTRAN
3790 * <ul>
3791 * <li> <B>tensionAllow = 0.0</B> </li> <br>
3792 * Tension allowable for the material.
3793 * </ul>
3794 * \endif
3795 */
3796 keyWord = "tensionAllow";
3797 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3798 if (status == CAPS_SUCCESS0) {
3799
3800 status = string_toDouble(keyValue, &(*feaMaterial)[i].tensionAllow);
3801 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3801
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3802 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3803 }
3804
3805 /*! \page feaMaterial
3806 *
3807 *
3808 * \if NASTRAN
3809 * <ul>
3810 * <li> <B>tensionAllowLateral = 0.0</B> </li> <br>
3811 * Lateral tension allowable for the material.
3812 * </ul>
3813 * \endif
3814 */
3815 keyWord = "tensionAllowLateral";
3816 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3817 if (status == CAPS_SUCCESS0) {
3818
3819 status = string_toDouble(keyValue, &(*feaMaterial)[i].tensionAllowLateral);
3820 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3820
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3821 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3822 }
3823
3824 /*! \page feaMaterial
3825 *
3826 * \if NASTRAN
3827 * <ul>
3828 * <li> <B>compressAllow = 0.0</B> </li> <br>
3829 * Compression allowable for the material.
3830 * </ul>
3831 * \endif
3832 */
3833 keyWord = "compressAllow";
3834 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3835 if (status == CAPS_SUCCESS0) {
3836
3837 status = string_toDouble(keyValue, &(*feaMaterial)[i].compressAllow);
3838 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3838
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3839 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3840 }
3841
3842 /*! \page feaMaterial
3843 *
3844 * \if NASTRAN
3845 * <ul>
3846 * <li> <B>compressAllowLateral = 0.0</B> </li> <br>
3847 * Lateral compression allowable for the material.
3848 * </ul>
3849 * \endif
3850 */
3851 keyWord = "compressAllowLateral";
3852 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3853 if (status == CAPS_SUCCESS0) {
3854
3855 status = string_toDouble(keyValue, &(*feaMaterial)[i].compressAllowLateral);
3856 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3856
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3857 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3858 }
3859
3860 /*! \page feaMaterial
3861 *
3862 * \if NASTRAN
3863 * <ul>
3864 * <li> <B>shearAllow = 0.0</B> </li> <br>
3865 * Shear allowable for the material.
3866 * </ul>
3867 * \endif
3868 */
3869 keyWord = "shearAllow";
3870 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3871 if (status == CAPS_SUCCESS0) {
3872
3873 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearAllow);
3874 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3874
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3875 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3876 }
3877
3878 /*! \page feaMaterial
3879 *
3880 * \if (NASTRAN)
3881 * <ul>
3882 * <li> <B>allowType = 0 </B> </li> <br>
3883 * 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).
3884 * </ul>
3885 * \endif
3886 */
3887 keyWord = "allowType";
3888 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3889 if (status == CAPS_SUCCESS0) {
3890 status = string_toInteger(keyValue, &(*feaMaterial)[i].allowType);
3891 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3891
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3892 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3893 }
3894
3895 /*! \page feaMaterial
3896 *
3897 * \if (MYSTRAN || NASTRAN || ABAQUS)
3898 * <ul>
3899 * <li> <B>youngModulusLateral = 0.0</B> </li> <br>
3900 * Elastic modulus in lateral direction for an orthotropic material
3901 * </ul>
3902 * \endif
3903 */
3904 keyWord = "youngModulusLateral";
3905 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3906 if (status == CAPS_SUCCESS0) {
3907
3908 status = string_toDouble(keyValue, &(*feaMaterial)[i].youngModulusLateral);
3909 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3909
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3910 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3911 }
3912
3913 /*! \page feaMaterial
3914 *
3915 * \if (MYSTRAN || NASTRAN || ABAQUS)
3916 * <ul>
3917 * <li> <B>shearModulusTrans1Z = 0.0</B> </li> <br>
3918 * Transverse shear modulus in the 1-Z plane for an orthotropic material
3919 * </ul>
3920 * \endif
3921 */
3922 keyWord = "shearModulusTrans1Z";
3923 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3924 if (status == CAPS_SUCCESS0) {
3925
3926 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulusTrans1Z);
3927 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3927
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3928 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3929 }
3930
3931 /*! \page feaMaterial
3932 *
3933 * \if (MYSTRAN || NASTRAN || ABAQUS)
3934 * <ul>
3935 * <li> <B>shearModulusTrans2Z = 0.0</B> </li> <br>
3936 * Transverse shear modulus in the 2-Z plane for an orthotropic material
3937 * </ul>
3938 * \endif
3939 */
3940 keyWord = "shearModulusTrans2Z";
3941 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3942 if (status == CAPS_SUCCESS0) {
3943
3944 status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulusTrans2Z);
3945 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3945
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3946 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3947 }
3948
3949 /*! \page feaMaterial
3950 *
3951 * \if (TACS || NASTRAN || ABAQUS)
3952 * <ul>
3953 * <li> <B>kappa = 0.0</B> </li> <br>
3954 * Thermal conductivity for an isotropic solid
3955 * </ul>
3956 * \endif
3957 */
3958 keyWord = "kappa";
3959 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3960 if (status == CAPS_SUCCESS0) {
3961
3962 status = string_toDouble(keyValue, &(*feaMaterial)[i].kappa);
3963 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3963
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3964 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3965 }
3966
3967 /*! \page feaMaterial
3968 *
3969 * \if (TACS || NASTRAN || ABAQUS)
3970 * <ul>
3971 * <li> <B>specificHeat = 0.0</B> </li> <br>
3972 * Specific heat constant pressure (per unit mass) for an isotropic solid
3973 * </ul>
3974 * \endif
3975 */
3976 keyWord = "specificHeat";
3977 status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue);
3978 if (status == CAPS_SUCCESS0) {
3979
3980 status = string_toDouble(keyValue, &(*feaMaterial)[i].specificHeat);
3981 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3981
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
3982 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
3983 }
3984
3985 } else {
3986
3987 /*! \page feaMaterial
3988 * \section keyStringMaterial Single Value String
3989 *
3990 * If "Value" is a string, the string value may correspond to an entry in a predefined material lookup
3991 * table. NOT YET IMPLEMENTED!!!!
3992 *
3993 */
3994 // CALL material look up
3995 AIM_ERROR(aimInfo, "Material tuple value ('%s') is expected to be a JSON string", materialTuple[i].value){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 3995, __func__
, "Material tuple value ('%s') is expected to be a JSON string"
, materialTuple[i].value); }
;
3996 status = CAPS_BADVALUE-311;
3997 goto cleanup;
3998 }
3999 }
4000
4001 printf("\tDone getting FEA materials\n");
4002 status = CAPS_SUCCESS0;
4003
4004cleanup:
4005 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4006
4007 return status;
4008}
4009
4010// Get the property properties from a capsTuple
4011int fea_getProperty(void *aimInfo,
4012 int numPropertyTuple,
4013 capsTuple propertyTuple[],
4014 mapAttrToIndexStruct *attrMap,
4015 feaUnitsStruct *feaUnits,
4016 feaProblemStruct *feaProblem) {
4017
4018 /*! \page feaProperty FEA Property
4019 * Structure for the property tuple = ("Property Name", "Value").
4020 * "Property Name" defines the reference <c>capsGroup</c> for the property being specified.
4021 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringProperty) or a single string keyword
4022 * (see Section \ref keyStringProperty).
4023 */
4024
4025 int status; //Function return
4026
4027 int i, j, matIndex; // Indexing
4028 int found; // Bool test function
4029
4030 int pidIndex; // Property identification index found in attribute map
4031
4032 int tempInteger;
4033
4034 char *keyValue = NULL((void*)0);
4035 char *keyWord = NULL((void*)0);
4036 char *tempString = NULL((void*)0);
4037 char **tempStringArray = NULL((void*)0);
4038
4039 // double tempDouble;
4040
4041 // Destroy our property structures coming in if aren't 0 and NULL already
4042 if (feaProblem->feaProperty != NULL((void*)0)) {
4043 for (i = 0; i < feaProblem->numProperty; i++) {
4044 status = destroy_feaPropertyStruct(&feaProblem->feaProperty[i]);
4045 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4045
, __func__, 0); goto cleanup; }
;
4046 }
4047 }
4048 AIM_FREE(feaProblem->feaProperty){ EG_free(feaProblem->feaProperty); feaProblem->feaProperty
= ((void*)0); }
;
4049 feaProblem->numProperty = 0;
4050
4051 printf("\nGetting FEA properties.......\n");
4052
4053 feaProblem->numProperty = numPropertyTuple;
4054 printf("\tNumber of properties - %d\n", feaProblem->numProperty);
4055
4056 if (feaProblem->numProperty > 0) {
4057
4058 feaProblem->feaProperty = (feaPropertyStruct *) EG_alloc(feaProblem->numProperty * sizeof(feaPropertyStruct));
4059 if (feaProblem->feaProperty == NULL((void*)0)) return EGADS_MALLOC-4;
4060
4061 } else {
4062 AIM_ERROR(aimInfo, "Number of property values in input tuple is 0\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4062, __func__
, "Number of property values in input tuple is 0\n"); }
;
4063 status = CAPS_NOTFOUND-303;
4064 goto cleanup;
4065 }
4066
4067 for (i = 0; i < feaProblem->numProperty; i++) {
4068 status = initiate_feaPropertyStruct(&feaProblem->feaProperty[i]);
4069 AIM_STATUS(aimInfo, status, "Unable to initiate feaProperty structure (number = %d)", i)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4069
, __func__, 2, "Unable to initiate feaProperty structure (number = %d)"
, i); goto cleanup; }
;
4070 }
4071
4072 for (i = 0; i < feaProblem->numProperty; i++) {
4073
4074 printf("\tProperty name - %s\n", propertyTuple[i].name);
4075
4076 // Set property name from tuple name
4077 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", 4077, __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"
, 4077, __func__, 2, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].name"
, propertyTuple[i].name); goto cleanup; } }
;
4078
4079 // Get to property ID number from the attribute map
4080 status = get_mapAttrToIndexIndex(attrMap, feaProblem->feaProperty[i].name, &pidIndex);
4081 if (status != CAPS_SUCCESS0) {
4082 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", 4082, __func__
, "Tuple name '%s' not found in attribute map of PIDS!!!!\n",
feaProblem->feaProperty[i].name); }
;
4083 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4084 goto cleanup;
4085 } else {
4086 feaProblem->feaProperty[i].propertyID = pidIndex;
4087 }
4088
4089 // Do we have a json string?
4090 if (strncmp(propertyTuple[i].value, "{", 1) == 0) {
4091 //printf("JSON String - %s\n",propertyTuple[i].value);
4092
4093 /*! \page feaProperty
4094 * \section jsonStringProperty JSON String Dictionary
4095 *
4096 * If "Value" is JSON string dictionary
4097 * \if (MYSTRAN || NASTRAN)
4098 * (e.g. "Value" = {"shearMembraneRatio": 0.83, "bendingInertiaRatio": 1.0, "membraneThickness": 0.2, "propertyType": "Shell"})
4099 * \endif
4100 * the following keywords ( = default values) may be used:
4101 *
4102 *
4103 * \if (MYSTRAN || NASTRAN)
4104 * <ul>
4105 * <li> <B>propertyType = No Default value</B> </li> <br>
4106 * Type of property to apply to a given capsGroup <c>Name</c>. Options: ConcentratedMass, Rod,
4107 * Bar, Shear, Shell, Composite, and Solid
4108 * </ul>
4109 * \elseif (MASSTRAN)
4110 * <ul>
4111 * <li> <B>propertyType = No Default value</B> </li> <br>
4112 * Type of property to apply to a given capsGroup <c>Name</c>. Options: ConcentratedMass, Shell
4113 * </ul>
4114 * \elseif ABAQUS
4115 *
4116 * Something else ....
4117 *
4118 * \elseif ASTROS
4119 * <ul>
4120 * <li> <B>propertyType = No Default value</B> </li> <br>
4121 * Type of property to apply to a give capsGroup <c>Name</c>. Options: ConcentratedMass, Rod,
4122 * Bar, Shear, Shell, Membrane, Composite, and Solid
4123 * </ul>
4124 * \endif
4125 *
4126 */
4127
4128 // Get property Type
4129 keyWord = "propertyType";
4130 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4131 if (status == CAPS_SUCCESS0) {
4132
4133 //{UnknownProperty, ConcentratedMass Rod, Bar, Shear, Shell, Composite, Solid}
4134 if (strcasecmp(keyValue, "\"ConcentratedMass\"") == 0) feaProblem->feaProperty[i].propertyType = ConcentratedMass;
4135 else if (strcasecmp(keyValue, "\"Rod\"") == 0) feaProblem->feaProperty[i].propertyType = Rod;
4136 else if (strcasecmp(keyValue, "\"Bar\"") == 0) feaProblem->feaProperty[i].propertyType = Bar;
4137 else if (strcasecmp(keyValue, "\"Shear\"") == 0) feaProblem->feaProperty[i].propertyType = Shear;
4138 else if (strcasecmp(keyValue, "\"Shell\"") == 0) feaProblem->feaProperty[i].propertyType = Shell;
4139 else if (strcasecmp(keyValue, "\"Membrane\"") == 0) feaProblem->feaProperty[i].propertyType = Membrane;
4140 else if (strcasecmp(keyValue, "\"Composite\"") == 0) feaProblem->feaProperty[i].propertyType = Composite;
4141 else if (strcasecmp(keyValue, "\"Solid\"") == 0) feaProblem->feaProperty[i].propertyType = Solid;
4142 else {
4143 AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4146, __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); }
4144 "\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4146, __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); }
4145 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4146, __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); }
4146 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4146, __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); }
;
4147 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4148
4149 status = CAPS_NOTFOUND-303;
4150 goto cleanup;
4151 }
4152
4153 } else {
4154 AIM_ERROR(aimInfo, "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4156, __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); }
4155 "\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4156, __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); }
4156 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4156, __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); }
;
4157 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4158
4159 status = CAPS_NOTFOUND-303;
4160 goto cleanup;
4161 }
4162 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4163
4164 /*! \page feaProperty
4165 *
4166 * \if (MYSTRAN || NASTRAN)
4167 * <ul>
4168 * <li> <B>material = "Material Name" (\ref feaMaterial) </B> </li> <br>
4169 * "Material Name" from \ref feaMaterial to use for property. If no material is set the first material
4170 * created will be used
4171 * </ul>
4172 * \elseif ABAQUS
4173 *
4174 * Something else ....
4175 *
4176 * \elseif ASTROS
4177 * <ul>
4178 * <li> <B>material = `Material Name' (\ref feaMaterial) </B> </li> <br>
4179 * `Material Name' from \ref feaMaterial to use for property. If no material is set the first material
4180 * created will be used
4181 * </ul>
4182 * \endif
4183 */
4184 keyWord = "material";
4185 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4186 if (status == CAPS_SUCCESS0) {
4187
4188 found = (int) false0;
4189 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4190
4191 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4192 tempString = string_removeQuotation(keyValue);
4193
4194 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4195 feaProblem->feaProperty[i].materialID = feaProblem->feaMaterial[matIndex].materialID;
4196
4197 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", 4197
, __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", 4197, __func__
, 2, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].materialName"
, feaProblem->feaMaterial[matIndex].name); goto cleanup; }
}
;
4198 feaProblem->feaProperty[i].materialName[strlen(feaProblem->feaMaterial[matIndex].name)] = '\0';
4199
4200 found = (int) true1;
4201 break;
4202 }
4203 }
4204
4205 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4206
4207 if (found == (int) false0) {
4208 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", 4210, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4209 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4210, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4210 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4210, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
;
4211 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4212 status = CAPS_NOTFOUND-303;
4213 goto cleanup;
4214 }
4215
4216 } else {
4217
4218 if (feaProblem->feaProperty[i].propertyType != ConcentratedMass &&
4219 feaProblem->feaProperty[i].propertyType != Composite) {
4220 printf("\tNo \"%s\" specified for Property tuple %s, defaulting to an index of 1\n", keyWord,
4221 propertyTuple[i].name);
4222 }
4223
4224 feaProblem->feaProperty[i].materialID = 1;
4225 if (feaProblem->numMaterial > 0) {
4226 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", 4226
, __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", 4226, __func__, 2
, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].materialName"
, feaProblem->feaMaterial[0].name); goto cleanup; } }
;
4227 }
4228 }
4229
4230 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4231
4232 // Fill up properties ///
4233
4234 // Rods
4235 /*! \page feaProperty
4236 *
4237 * \if (MYSTRAN || NASTRAN)
4238 * <ul>
4239 * <li> <B>crossSecArea = 0.0</B> </li> <br>
4240 * Cross sectional area.
4241 * </ul>
4242 * \elseif ABAQUS
4243 *
4244 * Something else ....
4245 *
4246 * \elseif ASTROS
4247 * <ul>
4248 * <li> <B>crossSecArea = 0.0</B> </li> <br>
4249 * Cross sectional area.
4250 * </ul>
4251 * \endif
4252 */
4253 keyWord = "crossSecArea";
4254 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4255 if (status == CAPS_SUCCESS0) {
4256
4257 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].crossSecArea);
4258 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4258
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4259 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4260 }
4261
4262 /*! \page feaProperty
4263 *
4264 * \if (MYSTRAN || NASTRAN)
4265 * <ul>
4266 * <li> <B>torsionalConst = 0.0</B> </li> <br>
4267 * Torsional constant.
4268 * </ul>
4269 * \elseif ABAQUS
4270 *
4271 * Something else ....
4272 *
4273 * \elseif ASTROS
4274 * <ul>
4275 * <li> <B>torsionalConst = 0.0</B> </li> <br>
4276 * Torsional constant.
4277 * </ul>
4278 * \endif
4279 */
4280 keyWord = "torsionalConst";
4281 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4282 if (status == CAPS_SUCCESS0) {
4283
4284 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].torsionalConst);
4285 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4285
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4286 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4287 }
4288
4289 /*! \page feaProperty
4290 *
4291 * \if (MYSTRAN || NASTRAN)
4292 * <ul>
4293 * <li> <B>torsionalStressReCoeff = 0.0</B> </li> <br>
4294 * Torsional stress recovery coefficient.
4295 * </ul>
4296 * \elseif ABAQUS
4297 *
4298 * Something else ....
4299 *
4300 * \elseif ASTROS
4301 * <ul>
4302 * <li> <B>torsionalStressReCoeff = 0.0</B> </li> <br>
4303 * Torsional stress recovery coefficient.
4304 * </ul>
4305 * \endif
4306 */
4307 keyWord = "torsionalStressReCoeff";
4308 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4309 if (status == CAPS_SUCCESS0) {
4310
4311 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].torsionalStressReCoeff);
4312 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4312
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4313 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4314 }
4315
4316 /*! \page feaProperty
4317 *
4318 * \if (HSM)
4319 * <ul>
4320 * <li> <B>massPerLength = 0.0</B> </li> <br>
4321 * Mass per unit length.
4322 * </ul>
4323 *
4324 * \elseif ( MYSTRAN || NASTRAN || ASTROS || ABAQUS)
4325 * <ul>
4326 * <li> <B>massPerLength = 0.0</B> </li> <br>
4327 * Non-structural mass per unit length.
4328 * </ul>
4329 *
4330 * \endif
4331 */
4332 keyWord = "massPerLength";
4333 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4334 if (status == CAPS_SUCCESS0) {
4335
4336 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].massPerLength);
4337 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4337
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4338 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4339 }
4340
4341 // Bar - see rod for additional variables
4342
4343 /*! \page feaProperty
4344 *
4345 * \if (MYSTRAN || NASTRAN)
4346 * <ul>
4347 * <li> <B>zAxisInertia = 0.0</B> </li> <br>
4348 * Section moment of inertia about the element z-axis.
4349 * </ul>
4350 * \elseif ABAQUS
4351 *
4352 * Something else ....
4353 *
4354 * \elseif ASTROS
4355 * <ul>
4356 * <li> <B>zAxisInertia = 0.0</B> </li> <br>
4357 * Section moment of inertia about the element z-axis.
4358 * </ul>
4359 * \endif
4360 */
4361 keyWord = "zAxisInertia";
4362 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4363 if (status == CAPS_SUCCESS0) {
4364
4365 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].zAxisInertia);
4366 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4366
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4367 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4368 }
4369
4370 /*! \page feaProperty
4371 *
4372 * \if (MYSTRAN || NASTRAN)
4373 * <ul>
4374 * <li> <B>yAxisInertia = 0.0</B> </li> <br>
4375 * Section moment of inertia about the element y-axis.
4376 * </ul>
4377 * \elseif ABAQUS
4378 *
4379 * Something else ....
4380 *
4381 * \elseif ASTROS
4382 * <ul>
4383 * <li> <B>yAxisInertia = 0.0</B> </li> <br>
4384 * Section moment of inertia about the element y-axis.
4385 * </ul>
4386 * \endif
4387 */
4388 keyWord = "yAxisInertia";
4389 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4390 if (status == CAPS_SUCCESS0) {
4391
4392 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].yAxisInertia);
4393 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4393
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4394 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4395 }
4396
4397 /*! \page feaProperty
4398 *
4399 * \if (MYSTRAN || NASTRAN)
4400 * <ul>
4401 * <li> <B>yCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4402 * Element y-coordinates, in the bar cross-section, of four points at which to recover stresses
4403 * </ul>
4404 * \elseif ABAQUS
4405 *
4406 * Something else ....
4407 *
4408 * \elseif ASTROS
4409 * <ul>
4410 * <li> <B>yCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4411 * Element y-coordinates, in the bar cross-section, of four points at which to recover stresses
4412 * </ul>
4413 * \endif
4414 */
4415 keyWord = "yCoords";
4416 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4417 if (status == CAPS_SUCCESS0) {
4418 status = string_toDoubleArray(keyValue,
4419 (int) sizeof(feaProblem->feaProperty[i].yCoords)/sizeof(double),
4420 feaProblem->feaProperty[i].yCoords);
4421 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4421
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4422 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4423 }
4424
4425 /*! \page feaProperty
4426 *
4427 * \if (MYSTRAN || NASTRAN)
4428 * <ul>
4429 * <li> <B>zCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4430 * Element z-coordinates, in the bar cross-section, of four points at which to recover stresses
4431 * </ul>
4432 * \elseif ABAQUS
4433 *
4434 * Something else ....
4435 *
4436 * \elseif ASTROS
4437 * <ul>
4438 * <li> <B>zCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br>
4439 * Element z-coordinates, in the bar cross-section, of four points at which to recover stresses
4440 * </ul>
4441 * \endif
4442 */
4443 keyWord = "zCoords";
4444 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4445 if (status == CAPS_SUCCESS0) {
4446 status = string_toDoubleArray(keyValue,
4447 (int) sizeof(feaProblem->feaProperty[i].zCoords)/sizeof(double),
4448 feaProblem->feaProperty[i].zCoords);
4449 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4449
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4450 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4451 }
4452
4453 /*! \page feaProperty
4454 *
4455 * \if (MYSTRAN || NASTRAN)
4456 * <ul>
4457 * <li> <B>areaShearFactors[2] = [0.0, 0.0]</B> </li> <br>
4458 * Area factors for shear.
4459 * </ul>
4460 * \elseif ABAQUS
4461 *
4462 * Something else ....
4463 *
4464 * \elseif ASTROS
4465 * <ul>
4466 * <li> <B>areaShearFactors[2] = [0.0, 0.0]</B> </li> <br>
4467 * Area factors for shear.
4468 * </ul>
4469 * \endif
4470 */
4471 keyWord = "areaShearFactors";
4472 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4473 if (status == CAPS_SUCCESS0) {
4474 status = string_toDoubleArray(keyValue,
4475 (int) sizeof(feaProblem->feaProperty[i].areaShearFactors)/sizeof(double),
4476 feaProblem->feaProperty[i].areaShearFactors);
4477 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4477
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4478 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4479 }
4480
4481 /*! \page feaProperty
4482 *
4483 * \if (MYSTRAN || NASTRAN)
4484 * <ul>
4485 * <li> <B>crossProductInertia = 0.0</B> </li> <br>
4486 * Section cross-product of inertia.
4487 * </ul>
4488 * \elseif ABAQUS
4489 *
4490 * Something else ....
4491 *
4492 * \elseif ASTROS
4493 * <ul>
4494 * <li> <B>crossProductInertia = 0.0</B> </li> <br>
4495 * Section cross-product of inertia.
4496 * </ul>
4497 * \endif
4498 */
4499 keyWord = "crossProductInertia";
4500 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4501 if (status == CAPS_SUCCESS0) {
4502 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].crossProductInertia);
4503 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4503
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4504 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4505 }
4506
4507 /*! \page feaProperty
4508 *
4509 * \if (MYSTRAN || NASTRAN )
4510 * <ul>
4511 * <li> <B>crossSecType = NULL</B> </li> <br>
4512 * Cross-section type. Must be one of following character variables: BAR, BOX, BOX1,
4513 * CHAN, CHAN1, CHAN2, CROSS, H, HAT, HEXA, I, I1, ROD, T, T1, T2, TUBE, or Z.
4514 * </ul>
4515 * \elseif ASTROS
4516 * <ul>
4517 * <li> <B>crossSecType = NULL</B> </li> <br>
4518 * Cross-section type. Must be one of following character variables: I, T, BOX, BAR,
4519 * TUBE, ROD, HAT, or GBOX.
4520 * </ul>
4521 * \endif
4522 */
4523 keyWord = "crossSecType";
4524 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4525 if (status == CAPS_SUCCESS0) {
4526 feaProblem->feaProperty[i].crossSecType = string_removeQuotation(keyValue);
4527 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4528 }
4529
4530 /*! \page feaProperty
4531 *
4532 * \if (MYSTRAN || NASTRAN || ASTROS)
4533 * <ul>
4534 * <li> <B>crossSecDimension = [0,0,0,....]</B> </li> <br>
4535 * Cross-sectional dimensions (length of array is dependent on the "crossSecType"). Max
4536 * supported length array is 10!
4537 * </ul>
4538 * \endif
4539 */
4540 keyWord = "crossSecDimension";
4541 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4542 if (status == CAPS_SUCCESS0) {
4543 status = string_toDoubleArray(keyValue,
4544 (int) sizeof(feaProblem->feaProperty[i].crossSecDimension)/sizeof(double),
4545 feaProblem->feaProperty[i].crossSecDimension);
4546 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4546
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4547 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4548 }
4549
4550
4551 /* UNDOCUMENTED orientation vector of bars - MAY be changed in the future without warning
4552 */
4553 keyWord = "orientationVec";
4554 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4555 if (status == CAPS_SUCCESS0) {
4556 status = string_toDoubleArray(keyValue,
4557 (int) sizeof(feaProblem->feaProperty[i].orientationVec)/sizeof(double),
4558 feaProblem->feaProperty[i].orientationVec);
4559 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4559
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4560 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4561 }
4562
4563
4564 // Shear
4565
4566 // Shell
4567
4568 /*! \page feaProperty
4569 *
4570 * \if (MYSTRAN || NASTRAN || MASSTRAN)
4571 * <ul>
4572 * <li> <B>membraneThickness = 0.0</B> </li> <br>
4573 * Membrane thickness.
4574 * </ul>
4575 * \elseif ABAQUS
4576 *
4577 * Something else ....
4578 *
4579 * \elseif ASTROS
4580 * <ul>
4581 * <li> <B>membraneThickness = 0.0</B> </li> <br>
4582 * Membrane thickness.
4583 * </ul>
4584 * \endif
4585 */
4586 keyWord = "membraneThickness";
4587 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4588 if (status == CAPS_SUCCESS0) {
4589 if ( feaUnits->length != NULL((void*)0) ) {
4590 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->length, &feaProblem->feaProperty[i].membraneThickness);
4591 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4591
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4592 } else {
4593 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].membraneThickness);
4594 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4594
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4595 }
4596 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4597 }
4598
4599
4600 /*! \page feaProperty
4601 *
4602 * \if (MYSTRAN || NASTRAN)
4603 * <ul>
4604 * <li> <B>bendingInertiaRatio = 1.0</B> </li> <br>
4605 * Ratio of actual bending moment inertia to the bending inertia of a solid plate of thickness "membraneThickness"
4606 * </ul>
4607 * \elseif ABAQUS
4608 *
4609 * Something else ....
4610 *
4611 * \elseif ASTROS
4612 * <ul>
4613 * <li> <B>bendingInertiaRatio = 1.0</B> </li> <br>
4614 * Ratio of actual bending moment inertia to the bending inertia of a solid plate of thickness "membraneThickness"
4615 * </ul>
4616 * \endif
4617 */
4618 keyWord = "bendingInertiaRatio";
4619 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4620 if (status == CAPS_SUCCESS0) {
4621 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].bendingInertiaRatio);
4622 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4622
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4623 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4624 }
4625
4626
4627 /*! \page feaProperty
4628 *
4629 * \if (MYSTRAN || NASTRAN)
4630 * <ul>
4631 * <li> <B>shearMembraneRatio = 5.0/6.0</B> </li> <br>
4632 * Ratio shear thickness to membrane thickness.
4633 * </ul>
4634 * \elseif ABAQUS
4635 *
4636 * Something else ....
4637 *
4638 * \elseif ASTROS
4639 * <ul>
4640 * <li> <B>shearMembraneRatio = 5.0/6.0</B> </li> <br>
4641 * Ratio shear thickness to membrane thickness.
4642 * </ul>
4643 * \endif
4644 */
4645 keyWord = "shearMembraneRatio";
4646 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4647 if (status == CAPS_SUCCESS0) {
4648 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].shearMembraneRatio);
4649 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4649
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4650 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4651 }
4652
4653 /*! \page feaProperty
4654 *
4655 * \if (MYSTRAN || NASTRAN)
4656 * <ul>
4657 * <li> <B>materialBending = "Material Name" (\ref feaMaterial)</B> </li> <br>
4658 * "Material Name" from \ref feaMaterial to use for property bending. If no material is given and
4659 * "bendingInertiaRatio" is greater than 0, the material name provided in "material" is used.
4660 * </ul>
4661 * \elseif ABAQUS
4662 *
4663 * Something else ....
4664 *
4665 * \elseif ASTROS
4666 * <ul>
4667 * <li> <B>materialBending = "Material Name" (\ref feaMaterial)</B> </li> <br>
4668 * "Material Name" from \ref feaMaterial to use for property bending.
4669 * </ul>
4670 * \endif
4671 */
4672 keyWord = "materialBending"; // Shell specific materials
4673 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4674 if (status == CAPS_SUCCESS0) {
4675
4676 found = (int) false0;
4677 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4678
4679 if (tempString != NULL((void*)0)) EG_free(tempString);
4680 tempString = string_removeQuotation(keyValue);
4681
4682 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4683 feaProblem->feaProperty[i].materialBendingID = feaProblem->feaMaterial[matIndex].materialID;
4684 found = (int) true1;
4685
4686 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4687 break;
4688 }
4689
4690 }
4691
4692 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4693
4694 if (found == (int) false0) {
4695 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", 4697, __func__
, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4696 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4697, __func__
, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4697 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4697, __func__
, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
;
4698 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4699 status = CAPS_NOTFOUND-303;
4700 goto cleanup;
4701 }
4702
4703 } else { // Don't default to anything - yet
4704
4705 /*
4706 printf("No \"%s\" specified for Property tuple %s which is a shell element, "
4707 " no bending material will be specified\n", keyWord,
4708 propertyTuple[i].name);
4709
4710 feaProblem->feaProperty[i].materialBendingID = 0;
4711 */
4712
4713 if (feaProblem->feaProperty[i].bendingInertiaRatio > 0) {
4714
4715 feaProblem->feaProperty[i].materialBendingID = feaProblem->feaProperty[i].materialID;
4716 }
4717 }
4718
4719 /*! \page feaProperty
4720 *
4721 * \if (MYSTRAN || NASTRAN)
4722 * <ul>
4723 * <li> <B>materialShear = "Material Name" (\ref feaMaterial)</B> </li> <br>
4724 * "Material Name" from \ref feaMaterial to use for property shear. If no material is given and
4725 * "shearMembraneRatio" is greater than 0, the material name provided in "material" is used.
4726 * </ul>
4727 * \elseif ABAQUS
4728 *
4729 * Something else ....
4730 *
4731 * \elseif ASTROS
4732 * <ul>
4733 * <li> <B>materialShear = "Material Name" (\ref feaMaterial)</B> </li> <br>
4734 * "Material Name" from \ref feaMaterial to use for property shear.
4735 * </ul>
4736 * \endif
4737 */
4738 keyWord = "materialShear"; // Shell specific materials
4739 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4740 if (status == CAPS_SUCCESS0) {
4741
4742 found = (int) false0;
4743 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4744
4745 if (tempString != NULL((void*)0)) EG_free(tempString);
4746 tempString = string_removeQuotation(keyValue);
4747
4748 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4749 feaProblem->feaProperty[i].materialShearID = feaProblem->feaMaterial[matIndex].materialID;
4750 found = (int) true1;
4751
4752 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4753 break;
4754 }
4755
4756 }
4757
4758 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4759
4760 if (found == (int) false0) {
4761 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", 4763, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4762 keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4763, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
4763 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4763, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyWord, keyValue, propertyTuple[i].name); }
;
4764 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4765 status = CAPS_NOTFOUND-303;
4766 goto cleanup;
4767 }
4768
4769 } else {
4770 /*
4771 printf("No \"%s\" specified for Property tuple %s which is a shell element, "
4772 " no shear material will be specified\n", keyWord,
4773 propertyTuple[i].name);
4774
4775 feaProblem->feaProperty[i].materialShearID = 0;
4776 */
4777
4778 if (feaProblem->feaProperty[i].shearMembraneRatio > 0) {
4779 feaProblem->feaProperty[i].materialShearID = feaProblem->feaProperty[i].materialID;
4780 }
4781 }
4782
4783 /*! \page feaProperty
4784 *
4785 * \if (HSM || MASSTRAN)
4786 * <ul>
4787 * <li> <B>massPerArea = 0.0</B> </li> <br>
4788 * Mass per unit area.
4789 * </ul>
4790 * \elseif (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
4791 *
4792 * <ul>
4793 * <li> <B>massPerArea = 0.0</B> </li> <br>
4794 * Non-structural mass per unit area.
4795 * </ul>
4796 * \endif
4797 */
4798 keyWord = "massPerArea";
4799 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4800 if (status == CAPS_SUCCESS0) {
4801 if ( feaUnits->densityArea != NULL((void*)0) ) {
4802 status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->densityArea, &feaProblem->feaProperty[i].massPerArea);
4803 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4803
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4804 } else {
4805 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].massPerArea);
4806 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4806
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4807 }
4808 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4809 }
4810
4811 /*! \page feaProperty
4812 *
4813 * \if (MYSTRAN || NASTRAN || ASTROS)
4814 * <ul>
4815 * <li> <B>zOffsetRel = 0.0</B> </li> <br>
4816 * Relative offset from the surface of grid points to the element reference
4817 * plane as a percentage of the thickness. zOffSet = thickness*zOffsetRel/100
4818 *
4819 * </ul>
4820 * \endif
4821 */
4822 keyWord = "zOffsetRel";
4823 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4824 if (status == CAPS_SUCCESS0) {
4825 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].zOffsetRel);
4826 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4826
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4827 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4828 }
4829
4830 // Composite
4831
4832 /*! \page feaProperty
4833 *
4834 * \if (MYSTRAN || NASTRAN)
4835 * <ul>
4836 * <li> <B>compositeMaterial = "no default" </B> </li> <br>
4837 * List of "Material Name"s, ["Material Name -1", "Material Name -2", ...], from \ref feaMaterial to use for composites.
4838 * </ul>
4839 * \elseif ABAQUS
4840 *
4841 * Something else ....
4842 *
4843 * \elseif ASTROS
4844 * <ul>
4845 * <li> <B>compositeMaterial = "no default" </B> </li> <br>
4846 * List of "Material Name"s, ["Material Name -1", "Material Name -2", ...], from \ref feaMaterial to use for composites.
4847 * </ul>
4848 * \endif
4849 */
4850 keyWord = "compositeMaterial";
4851 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4852 if (status == CAPS_SUCCESS0) {
4853
4854 status = string_toStringDynamicArray(keyValue, &feaProblem->feaProperty[i].numPly, &tempStringArray);
4855 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4855
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4856
4857 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"
, 4857, __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", 4857, __func__, 3
, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaProperty[i].compositeMaterialID"
, memorysize, "int"); goto cleanup; } }
;
4858
4859 for (j = 0; j < feaProblem->feaProperty[i].numPly; j++) {
4860 found = (int) false0;
4861 for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) {
4862
4863 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4864 tempString = string_removeQuotation(tempStringArray[j]);
4865
4866 if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) {
4867 feaProblem->feaProperty[i].compositeMaterialID[j] = feaProblem->feaMaterial[matIndex].materialID;
4868 found = (int) true1;
4869 break;
4870 }
4871
4872 }
4873
4874 if (found == (int) false0) {
4875 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", 4877, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyValue, keyWord, propertyTuple[i].name); }
4876 keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4877, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyValue, keyWord, propertyTuple[i].name); }
4877 propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4877, __func__
, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n"
, keyValue, keyWord, propertyTuple[i].name); }
;
4878
4879 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4880 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4881
4882 (void) string_freeArray(feaProblem->feaProperty[i].numPly, &tempStringArray);
4883
4884 status = CAPS_NOTFOUND-303;
4885 goto cleanup;
4886 }
4887
4888 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
4889 }
4890 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4891 status = string_freeArray(feaProblem->feaProperty[i].numPly, &tempStringArray);
4892 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4892
, __func__, 0); goto cleanup; }
;
4893 }
4894
4895 /*! \page feaProperty
4896 *
4897 * \if (MYSTRAN || NASTRAN)
4898 * <ul>
4899 * <li> <B>shearBondAllowable = 0.0 </B> </li> <br>
4900 * Allowable interlaminar shear stress.
4901 * </ul>
4902 * \elseif ABAQUS
4903 *
4904 * Something else ....
4905 *
4906 * \elseif ASTROS
4907 * <ul>
4908 * <li> <B>shearBondAllowable = 0.0 </B> </li> <br>
4909 * Allowable interlaminar shear stress.
4910 * </ul>
4911 * \endif
4912 */
4913 keyWord = "shearBondAllowable";
4914 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4915 if (status == CAPS_SUCCESS0) {
4916 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].compositeShearBondAllowable);
4917 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4917
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4918 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4919 }
4920
4921 /*! \page feaProperty
4922 *
4923 * \if (MYSTRAN || NASTRAN)
4924 * <ul>
4925 * <li> <B>symmetricLaminate = False </B> </li> <br>
4926 * Symmetric lamination option. True- SYM only half the plies are specified, for odd number plies 1/2 thickness
4927 * of center ply is specified with the first ply being the bottom ply in the stack, default (False) all plies specified.
4928 * </ul>
4929 * \elseif (ASTROS)
4930 * <ul>
4931 * <li> <B>symmetricLaminate = False </B> </li> <br>
4932 * Symmetric lamination option. If "True" only half the plies are specified (the plies will be repeated in
4933 * reverse order internally in the PCOMP card). For an odd number of plies, the 1/2 thickness
4934 * of the center ply is specified with the first ply being the bottom ply in the stack, default (False) all plies specified.
4935 * </ul>
4936 * \endif
4937 */
4938 keyWord = "symmetricLaminate";
4939 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4940 if (status == CAPS_SUCCESS0) {
4941 status = string_toBoolean(keyValue, &feaProblem->feaProperty[i].compositeSymmetricLaminate);
4942 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4942
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4943 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4944 }
4945
4946 /*! \page feaProperty
4947 *
4948 * \if (MYSTRAN || NASTRAN)
4949 * <ul>
4950 * <li> <B>compositeFailureTheory = "(no default)" </B> </li> <br>
4951 * Composite failure theory. Options: "HILL", "HOFF", "TSAI", and "STRN"
4952 * </ul>
4953 * \elseif ABAQUS
4954 *
4955 * Something else ....
4956 *
4957 * \elseif ASTROS
4958 * <ul>
4959 * <li> <B>compositeFailureTheory = "(no default)" </B> </li> <br>
4960 * Composite failure theory.
4961 * </ul>
4962 * \endif
4963 */
4964 keyWord = "compositeFailureTheory";
4965 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4966 if (status == CAPS_SUCCESS0) {
4967 feaProblem->feaProperty[i].compositeFailureTheory = string_removeQuotation(keyValue);
4968 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4968
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
4969 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
4970 }
4971
4972 /*! \page feaProperty
4973 *
4974 * \if (MYSTRAN || NASTRAN)
4975 * <ul>
4976 * <li> <B>compositeThickness = (no default) </B> </li> <br>
4977 * 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
4978 * of the "compositeMaterial" list, the list is either truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")]
4979 * in which case the last thickness provided is repeated.
4980 * </ul>
4981 * \elseif ABAQUS
4982 *
4983 * Something else ....
4984 *
4985 * \elseif ASTROS
4986 * <ul>
4987 * <li> <B>compositeThickness = (no default) </B> </li> <br>
4988 * 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
4989 * of the "compositeMaterial" list, the list is either truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")]
4990 * in which case the last thickness provided is repeated.
4991 * </ul>
4992 * \endif
4993 */
4994 keyWord = "compositeThickness";
4995 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
4996 if (status == CAPS_SUCCESS0) {
4997 status = string_toDoubleDynamicArray(keyValue, &tempInteger,
4998 &feaProblem->feaProperty[i].compositeThickness);
4999 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4999
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5000 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5001
5002 if (tempInteger < feaProblem->feaProperty[i].numPly) {
5003
5004 printf("\tThe number of thicknesses provided does not match the number of materials for the composite. "
5005 "The last thickness will be repeated %d times\n", feaProblem->feaProperty[i].numPly - tempInteger);
5006
5007 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"
, 5008, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
5008 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"
, 5008, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
;
5009
5010 for (j = 0; j < feaProblem->feaProperty[i].numPly - tempInteger; j++) {
5011
5012 feaProblem->feaProperty[i].compositeThickness[j+tempInteger] = feaProblem->feaProperty[i].compositeThickness[tempInteger-1];
5013 }
5014 }
5015
5016 if (tempInteger > feaProblem->feaProperty[i].numPly) {
5017
5018 printf("\tThe number of thicknesses provided does not match the number of materials for the composite. "
5019 "The last %d thicknesses will be not be used\n", tempInteger -feaProblem->feaProperty[i].numPly);
5020
5021 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"
, 5022, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
5022 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"
, 5022, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness"
, memorysize, "double"); goto cleanup; } }
;
5023 }
5024 } else {
5025
5026 if (feaProblem->feaProperty[i].numPly != 0 &&
5027 feaProblem->feaProperty[i].propertyType == Composite) {
5028
5029 AIM_ERROR(aimInfo, "\"compositeMaterial\" have been set but no thicknesses (\"compositeThickness\") provided!!!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5029, __func__
, "\"compositeMaterial\" have been set but no thicknesses (\"compositeThickness\") provided!!!"
); }
;
5030 status = CAPS_BADVALUE-311;
5031 goto cleanup;
5032 }
5033 }
5034
5035 /*! \page feaProperty
5036 *
5037 * \if (MYSTRAN || NASTRAN)
5038 * <ul>
5039 * <li> <B>compositeOrientation = (no default) </B> </li> <br>
5040 * List of composite orientations (angle relative element material axis) for each layer (eg. [5.0, 10.0, 30.0]).
5041 * If the length of this list doesn't match the length of the "compositeMaterial" list, the list is either
5042 * truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] in which case
5043 * the last orientation provided is repeated.
5044 * </ul>
5045 * \elseif ABAQUS
5046 *
5047 * Something else ....
5048 *
5049 * \elseif ASTROS
5050 * <ul>
5051 * <li> <B>compositeOrientation = (no default) </B> </li> <br>
5052 * List of composite orientations (angle relative element material axis) for each layer (eg. [5.0, 10.0, 30.0]).
5053 * If the length of this list doesn't match the length of the "compositeMaterial" list, the list is either
5054 * truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] in which case
5055 * the last orientation provided is repeated.
5056 * </ul>
5057 * \endif
5058 */
5059 keyWord = "compositeOrientation";
5060 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5061 if (status == CAPS_SUCCESS0) {
5062 status = string_toDoubleDynamicArray(keyValue, &tempInteger,
5063 &feaProblem->feaProperty[i].compositeOrientation);
5064 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5064
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5065 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5066
5067 if (tempInteger < feaProblem->feaProperty[i].numPly) {
5068
5069 printf("\tThe number of orientations provided does not match the number of materials for the composite. "
5070 "The last orientation will be repeated %d times\n", feaProblem->feaProperty[i].numPly - tempInteger);
5071
5072 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"
, 5073, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
5073 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"
, 5073, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
;
5074
5075 for (j = 0; j < feaProblem->feaProperty[i].numPly - tempInteger; j++) {
5076
5077 feaProblem->feaProperty[i].compositeOrientation[j+tempInteger] = feaProblem->feaProperty[i].compositeOrientation[tempInteger-1];
5078 }
5079 }
5080
5081 if (tempInteger > feaProblem->feaProperty[i].numPly) {
5082
5083 printf("\tThe number of orientations provided does not match the number of materials for the composite. "
5084 "The last %d orientation will be not be used\n", tempInteger -feaProblem->feaProperty[i].numPly);
5085
5086 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"
, 5087, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
5087 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"
, 5087, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation"
, memorysize, "double"); goto cleanup; } }
;
5088 }
5089
5090 } else {
5091
5092 if (feaProblem->feaProperty[i].numPly != 0 &&
5093 feaProblem->feaProperty[i].propertyType == Composite) {
5094
5095 AIM_ERROR(aimInfo, "\"compositeMaterial\" have been set but no Orientation (\"compositeOrientation\") provided!!!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5095, __func__
, "\"compositeMaterial\" have been set but no Orientation (\"compositeOrientation\") provided!!!"
); }
;
5096 status = CAPS_BADVALUE-311;
5097 goto cleanup;
5098 }
5099 }
5100
5101 // Mass
5102
5103 /*! \page feaProperty
5104 *
5105 * \if (MYSTRAN || NASTRAN)
5106 * <ul>
5107 * <li> <B>mass = 0.0</B> </li> <br>
5108 * Mass value.
5109 * </ul>
5110 * \elseif ABAQUS
5111 *
5112 * Something else ....
5113 *
5114 * \elseif ASTROS
5115 * <ul>
5116 * <li> <B>mass = 0.0</B> </li> <br>
5117 * Mass value.
5118 * </ul>
5119 * \endif
5120 */
5121 keyWord = "mass";
5122 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5123 if (status == CAPS_SUCCESS0) {
5124 status = string_toDouble(keyValue, &feaProblem->feaProperty[i].mass);
5125 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5125
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5126 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5127 }
5128
5129 /*! \page feaProperty
5130 *
5131 * \if (MYSTRAN || NASTRAN || MASSTRAN)
5132 * <ul>
5133 * <li> <B>massOffset = [0.0, 0.0, 0.0]</B> </li> <br>
5134 * Offset distance from the grid point to the center of gravity for a concentrated mass.
5135 * </ul>
5136 * \elseif ABAQUS
5137 *
5138 * Something else ....
5139 *
5140 * \elseif ASTROS
5141 * <ul>
5142 * <li> <B>massOffset = [0.0, 0.0, 0.0]</B> </li> <br>
5143 * Offset distance from the grid point to the center of gravity for a concentrated mass.
5144 * </ul>
5145 * \endif
5146 */
5147 keyWord = "massOffset";
5148 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5149 if (status == CAPS_SUCCESS0) {
5150 status = string_toDoubleArray(keyValue,
5151 (int) sizeof(feaProblem->feaProperty[i].massOffset)/sizeof(double),
5152 feaProblem->feaProperty[i].massOffset);
5153 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5153
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5154 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5155 }
5156
5157 /*! \page feaProperty
5158 *
5159 * \if (MYSTRAN || NASTRAN || MASSTRAN)
5160 * <ul>
5161 * <li> <B>massInertia = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</B> </li> <br>
5162 * Mass moment of inertia measured at the mass center of gravity.
5163 * </ul>
5164 * \elseif ABAQUS
5165 *v
5166 * Something else ....
5167 *
5168 * \elseif ASTROS
5169 * <ul>
5170 * <li> <B>massInertia = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</B> </li> <br>
5171 * Mass moment of inertia measured at the mass center of gravity.
5172 * </ul>
5173 * \endif
5174 */
5175 keyWord = "massInertia";
5176 status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue);
5177 if (status == CAPS_SUCCESS0) {
5178 status = string_toDoubleArray(keyValue,
5179 (int) sizeof(feaProblem->feaProperty[i].massInertia)/sizeof(double),
5180 feaProblem->feaProperty[i].massInertia);
5181 AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5181
, __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue
); goto cleanup; }
;
5182 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5183 }
5184
5185 } else {
5186
5187 /*! \page feaProperty
5188 * \section keyStringProperty Single Value String
5189 *
5190 * If "Value" is a string, the string value may correspond to an entry in a predefined property lookup
5191 * table. NOT YET IMPLEMENTED!!!!
5192 *
5193 */
5194
5195 // CALL property look up
5196 AIM_ERROR(aimInfo, "Property tuple value ('s') is expected to be a JSON string", propertyTuple[i].value){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5196, __func__
, "Property tuple value ('s') is expected to be a JSON string"
, propertyTuple[i].value); }
;
5197 status = CAPS_BADVALUE-311;
5198 goto cleanup;
5199 }
5200 }
5201
5202 printf("\tDone getting FEA properties\n");
5203 status = CAPS_SUCCESS0;
5204
5205cleanup:
5206 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
5207 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
5208
5209 return status;
5210}
5211
5212// Get the constraint properties from a capsTuple
5213int fea_getConstraint(int numConstraintTuple,
5214 capsTuple constraintTuple[],
5215 mapAttrToIndexStruct *attrMap,
5216 feaProblemStruct *feaProblem) {
5217
5218 /*! \page feaConstraint FEA Constraint
5219 * Structure for the constraint tuple = ("Constraint Name", "Value").
5220 * "Constraint Name" defines the reference name for the constraint being specified.
5221 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConstraint) or a single string keyword
5222 * (see Section \ref keyStringConstraint).
5223 */
5224
5225 int status; //Function return
5226
5227 int i, groupIndex, attrIndex, nodeIndex; // Indexing
5228
5229 char *keyValue = NULL((void*)0); // Key values from tuple searches
5230 char *keyWord = NULL((void*)0); // Key words to find in the tuples
5231
5232 int numGroupName = 0;
5233 char **groupName = NULL((void*)0);
5234
5235 feaMeshDataStruct *feaData;
5236
5237 // Destroy our constraint structures coming in if aren't 0 and NULL already
5238 if (feaProblem->feaConstraint != NULL((void*)0)) {
5239 for (i = 0; i < feaProblem->numConstraint; i++) {
5240 status = destroy_feaConstraintStruct(&feaProblem->feaConstraint[i]);
5241 if (status != CAPS_SUCCESS0) return status;
5242 }
5243 }
5244 if (feaProblem->feaConstraint != NULL((void*)0)) EG_free(feaProblem->feaConstraint);
5245 feaProblem->feaConstraint = NULL((void*)0);
5246 feaProblem->numConstraint = 0;
5247
5248 printf("\nGetting FEA constraints.......\n");
5249
5250 feaProblem->numConstraint = numConstraintTuple;
5251
5252 printf("\tNumber of constraints - %d\n", feaProblem->numConstraint);
5253
5254 // Allocate constraints
5255 if (feaProblem->numConstraint > 0) {
5256 feaProblem->feaConstraint = (feaConstraintStruct *) EG_alloc(feaProblem->numConstraint * sizeof(feaConstraintStruct));
5257
5258 if (feaProblem->feaConstraint == NULL((void*)0) ) return EGADS_MALLOC-4;
5259 }
5260
5261 // Initiate constraints to default values
5262 for (i = 0; i < feaProblem->numConstraint; i++) {
5263 status = initiate_feaConstraintStruct(&feaProblem->feaConstraint[i]);
5264 if (status != CAPS_SUCCESS0) return status;
5265 }
5266
5267 // Loop through tuples and fill out the constraint structures
5268 for (i = 0; i < feaProblem->numConstraint; i++) {
5269
5270 printf("\tConstraint name - %s\n", constraintTuple[i].name );
5271
5272 // Set constraint name to tuple attribute name
5273 feaProblem->feaConstraint[i].name = (char *) EG_alloc((strlen(constraintTuple[i].name) + 1)*sizeof(char));
5274 if (feaProblem->feaConstraint[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
5275
5276 memcpy(feaProblem->feaConstraint[i].name, constraintTuple[i].name, strlen(constraintTuple[i].name)*sizeof(char));
5277 feaProblem->feaConstraint[i].name[strlen(constraintTuple[i].name)] = '\0';
5278
5279 // Set constraint id -> 1 bias
5280 feaProblem->feaConstraint[i].constraintID = i+1;
5281
5282 // Do we have a json string?
5283 if (strncmp(constraintTuple[i].value, "{", 1) == 0) {
5284 //printf("JSON String - %s\n", constraintTuple[i].value);
5285
5286 /*! \page feaConstraint
5287 * \section jsonStringConstraint JSON String Dictionary
5288 *
5289 * If "Value" is JSON string dictionary
5290 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5291 * (eg. "Value" = {"groupName": "plateEdge", "dofConstraint": 123456})
5292 * \endif
5293 * the following keywords ( = default values) may be used:
5294 *
5295 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5296 * <ul>
5297 * <li> <B>constraintType = "ZeroDisplacement"</B> </li> <br>
5298 * Type of constraint. Options: "Displacement", "ZeroDisplacement".
5299 * </ul>
5300 * \endif
5301 *
5302 */
5303 // Get constraint Type
5304 keyWord = "constraintType";
5305 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5306 if (status == CAPS_SUCCESS0) {
5307
5308 //{UnknownConstraint, Displacement, ZeroDisplacement}
5309 if (strcasecmp(keyValue, "\"Displacement\"") == 0) feaProblem->feaConstraint[i].constraintType = Displacement;
5310 else if (strcasecmp(keyValue, "\"ZeroDisplacement\"") == 0) feaProblem->feaConstraint[i].constraintType = ZeroDisplacement;
5311 else {
5312
5313 printf("\tUnrecognized \"%s\" specified (%s) for Constraint tuple %s, defaulting to \"ZeroDisplacement\"\n", keyWord,
5314 keyValue,
5315 constraintTuple[i].name);
5316 feaProblem->feaConstraint[i].constraintType = ZeroDisplacement;
5317 }
5318
5319 } else {
5320
5321 printf("\tNo \"%s\" specified for Constraint tuple %s, defaulting to \"ZeroDisplacement\"\n", keyWord,
5322 constraintTuple[i].name);
5323 feaProblem->feaConstraint[i].constraintType = ZeroDisplacement;
5324 }
5325
5326 if (keyValue != NULL((void*)0)) {
5327 EG_free(keyValue);
5328 keyValue = NULL((void*)0);
5329 }
5330
5331 // Get constraint node set
5332
5333 /*! \page feaConstraint
5334 *
5335 * \if MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5336 * <ul>
5337 * <li> <B>groupName = "(no default)"</B> </li> <br>
5338 * Single or list of <c>capsConstraint</c> names on which to apply the constraint
5339 * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the constraint tuple name will be
5340 * used.
5341 * </ul>
5342 * \endif
5343 *
5344 */
5345 keyWord = "groupName";
5346 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5347 if (status == CAPS_SUCCESS0) {
5348
5349 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
5350 if (keyValue != NULL((void*)0)) EG_free(keyValue);
5351 keyValue = NULL((void*)0);
5352
5353 if (status != CAPS_SUCCESS0) return status;
5354
5355 } else {
5356
5357 printf("\tNo \"%s\" specified for Constraint tuple %s, going to use constraint name\n", keyWord,
5358 constraintTuple[i].name);
5359
5360 status = string_toStringDynamicArray(constraintTuple[i].name, &numGroupName, &groupName);
5361 if (status != CAPS_SUCCESS0) return status;
5362
5363 }
5364
5365 // Determine how many point constraints we have
5366 feaProblem->feaConstraint[i].numGridID = 0;
5367 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
5368
5369 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex);
5370
5371 if (status == CAPS_NOTFOUND-303) {
5372 printf("\tName %s not found in attribute map of capsConstraints!!!!\n", groupName[groupIndex]);
5373 continue;
5374 } else if (status != CAPS_SUCCESS0) return status;
5375
5376 // Now lets loop through the grid to see how many grid points have the attrIndex
5377 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
5378
5379 if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) {
5380 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
5381 } else {
5382 continue;
5383 }
5384
5385 if (feaData->constraintIndex == attrIndex) {
5386
5387 feaProblem->feaConstraint[i].numGridID += 1;
5388
5389 // Allocate/Re-allocate grid ID array
5390 if (feaProblem->feaConstraint[i].numGridID == 1) {
5391 feaProblem->feaConstraint[i].gridIDSet = (int *) EG_alloc(feaProblem->feaConstraint[i].numGridID*sizeof(int));
5392 } else {
5393 feaProblem->feaConstraint[i].gridIDSet = (int *) EG_reall(feaProblem->feaConstraint[i].gridIDSet,
5394 feaProblem->feaConstraint[i].numGridID*sizeof(int));
5395 }
5396
5397 if (feaProblem->feaConstraint[i].gridIDSet == NULL((void*)0)) {
5398 status = string_freeArray(numGroupName, &groupName);
5399 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
5400
5401 return EGADS_MALLOC-4;
5402 }
5403
5404 // Set grid ID value -> 1 bias
5405 feaProblem->feaConstraint[i].gridIDSet[feaProblem->feaConstraint[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID;
5406 }
5407 }
5408 }
5409
5410 status = string_freeArray(numGroupName, &groupName);
5411 if (status != CAPS_SUCCESS0) return status;
5412 groupName = NULL((void*)0);
5413
5414
5415 //Fill up constraint properties
5416 /*! \page feaConstraint
5417 *
5418 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5419 * <ul>
5420 * <li> <B>dofConstraint = 0 </B> </li> <br>
5421 * Component numbers / degrees of freedom that will be constrained (123 - zero translation in all three
5422 * directions).
5423 * </ul>
5424 * \endif
5425 */
5426 keyWord = "dofConstraint";
5427 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5428 if (status == CAPS_SUCCESS0) {
5429
5430 status = string_toInteger(keyValue, &feaProblem->feaConstraint[i].dofConstraint);
5431 if (keyValue != NULL((void*)0)) {
5432 EG_free(keyValue);
5433 keyValue = NULL((void*)0);
5434 }
5435 if (status != CAPS_SUCCESS0) return status;
5436 }
5437
5438 /*! \page feaConstraint
5439 *
5440 * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS)
5441 * <ul>
5442 * <li> <B>gridDisplacement = 0.0 </B> </li> <br>
5443 * Value of displacement for components defined in "dofConstraint".
5444 * </ul>
5445 * \endif
5446 */
5447 keyWord = "gridDisplacement";
5448 status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue);
5449 if (status == CAPS_SUCCESS0) {
5450
5451 status = string_toDouble(keyValue, &feaProblem->feaConstraint[i].gridDisplacement);
5452 if (keyValue != NULL((void*)0)) {
5453 EG_free(keyValue);
5454 keyValue = NULL((void*)0);
5455 }
5456 if (status != CAPS_SUCCESS0) return status;
5457 }
5458
5459 } else {
5460
5461 /*! \page feaConstraint
5462 * \section keyStringConstraint Single Value String
5463 *
5464 * If "Value" is a string, the string value may correspond to an entry in a predefined constraint lookup
5465 * table. NOT YET IMPLEMENTED!!!!
5466 *
5467 */
5468
5469 // Call some look up table maybe?
5470 printf("\tError: Constraint tuple value is expected to be a JSON string\n");
5471 return CAPS_BADVALUE-311;
5472 }
5473 }
5474
5475 if (keyValue != NULL((void*)0)) EG_free(keyValue);
5476
5477 printf("\tDone getting FEA constraints\n");
5478 return CAPS_SUCCESS0;
5479}
5480
5481// Get the support properties from a capsTuple
5482int fea_getSupport(int numSupportTuple,
5483 capsTuple supportTuple[],
5484 mapAttrToIndexStruct *attrMap,
5485 feaProblemStruct *feaProblem) {
5486
5487 /*! \page feaSupport FEA Support
5488 * Structure for the support tuple = ("Support Name", "Value").
5489 * "Support Name" defines the reference name for the support being specified.
5490 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringSupport) or a single string keyword
5491 * (see Section \ref keyStringSupport).
5492 */
5493
5494 int status; //Function return
5495
5496 int i, groupIndex, attrIndex, nodeIndex; // Indexing
5497
5498 char *keyValue = NULL((void*)0); // Key values from tuple searches
5499 char *keyWord = NULL((void*)0); // Key words to find in the tuples
5500
5501 int numGroupName = 0;
5502 char **groupName = NULL((void*)0);
5503
5504 feaMeshDataStruct *feaData;
5505
5506 // Destroy our support structures coming in if aren't 0 and NULL already
5507 if (feaProblem->feaSupport != NULL((void*)0)) {
5508 for (i = 0; i < feaProblem->numSupport; i++) {
5509 status = destroy_feaSupportStruct(&feaProblem->feaSupport[i]);
5510 if (status != CAPS_SUCCESS0) return status;
5511 }
5512 }
5513 if (feaProblem->feaSupport != NULL((void*)0)) EG_free(feaProblem->feaSupport);
5514 feaProblem->feaSupport = NULL((void*)0);
5515 feaProblem->numSupport = 0;
5516
5517 printf("\nGetting FEA supports.......\n");
5518
5519 feaProblem->numSupport = numSupportTuple;
5520
5521 printf("\tNumber of supports - %d\n", feaProblem->numSupport);
5522
5523 // Allocate supports
5524 if (feaProblem->numSupport > 0) {
5525 feaProblem->feaSupport = (feaSupportStruct *) EG_alloc(feaProblem->numSupport * sizeof(feaSupportStruct));
5526
5527 if (feaProblem->feaSupport == NULL((void*)0) ) return EGADS_MALLOC-4;
5528 }
5529
5530 // Initiate supports to default values
5531 for (i = 0; i < feaProblem->numSupport; i++) {
5532 status = initiate_feaSupportStruct(&feaProblem->feaSupport[i]);
5533 if (status != CAPS_SUCCESS0) return status;
5534 }
5535
5536 // Loop through tuples and fill out the support structures
5537 for (i = 0; i < feaProblem->numSupport; i++) {
5538
5539 printf("\tSupport name - %s\n", supportTuple[i].name );
5540
5541 // Set support name to tuple attribute name
5542 feaProblem->feaSupport[i].name = (char *) EG_alloc((strlen(supportTuple[i].name) + 1)*sizeof(char));
5543 if (feaProblem->feaSupport[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
5544
5545 memcpy(feaProblem->feaSupport[i].name, supportTuple[i].name, strlen(supportTuple[i].name)*sizeof(char));
5546 feaProblem->feaSupport[i].name[strlen(supportTuple[i].name)] = '\0';
5547
5548 // Set support id -> 1 bias
5549 feaProblem->feaSupport[i].supportID = i+1;
5550
5551 // Do we have a json string?
5552 if (strncmp(supportTuple[i].value, "{", 1) == 0) {
5553 //printf("JSON String - %s\n", supportTuple[i].value);
5554
5555 /*! \page feaSupport
5556 * \section jsonStringSupport JSON String Dictionary
5557 *
5558 * If "Value" is JSON string dictionary
5559 * \if (MYSTRAN || NASTRAN || ASTROS)
5560 * (eg. "Value" = {"groupName": "plateEdge", "dofSupport": 123456})
5561 * \endif
5562 * the following keywords ( = default values) may be used:
5563 */
5564
5565 // Get support node set
5566
5567 /*! \page feaSupport
5568 *
5569 * \if (MYSTRAN || NASTRAN || ASTROS)
5570 * <ul>
5571 * <li> <B>groupName = "(no default)"</B> </li> <br>
5572 * Single or list of <c>capsConstraint</c> names on which to apply the support
5573 * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the constraint tuple name will be
5574 * used.
5575 * </ul>
5576 * \endif
5577 */
5578 keyWord = "groupName";
5579 status = search_jsonDictionary( supportTuple[i].value, keyWord, &keyValue);
5580 if (status == CAPS_SUCCESS0) {
5581
5582 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
5583 if (keyValue != NULL((void*)0)) EG_free(keyValue);
5584 keyValue = NULL((void*)0);
5585
5586 if (status != CAPS_SUCCESS0) return status;
5587
5588 } else {
5589
5590 printf("\tNo \"%s\" specified for Support tuple %s, going to use support name\n", keyWord,
5591 supportTuple[i].name);
5592
5593 status = string_toStringDynamicArray(supportTuple[i].name, &numGroupName, &groupName);
5594 if (status != CAPS_SUCCESS0) return status;
5595
5596 }
5597
5598 // Determine how many point supports we have
5599 feaProblem->feaSupport[i].numGridID = 0;
5600 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
5601
5602 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex);
5603
5604 if (status == CAPS_NOTFOUND-303) {
5605 printf("\tName %s not found in attribute map of capsConstraints!!!!\n", groupName[groupIndex]);
5606 continue;
5607 } else if (status != CAPS_SUCCESS0) return status;
5608
5609 // Now lets loop through the grid to see how many grid points have the attrIndex
5610 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
5611
5612 if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) {
5613 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
5614 } else {
5615 continue;
5616 }
5617
5618 if (feaData->constraintIndex == attrIndex) {
5619
5620 feaProblem->feaSupport[i].numGridID += 1;
5621
5622 // Allocate/Re-allocate grid ID array
5623 if (feaProblem->feaSupport[i].numGridID == 1) {
5624 feaProblem->feaSupport[i].gridIDSet = (int *) EG_alloc(feaProblem->feaSupport[i].numGridID*sizeof(int));
5625 } else {
5626 feaProblem->feaSupport[i].gridIDSet = (int *) EG_reall(feaProblem->feaSupport[i].gridIDSet,
5627 feaProblem->feaSupport[i].numGridID*sizeof(int));
5628 }
5629
5630 if (feaProblem->feaSupport[i].gridIDSet == NULL((void*)0)) {
5631 status = string_freeArray(numGroupName, &groupName);
5632 if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status);
5633
5634 return EGADS_MALLOC-4;
5635 }
5636
5637 // Set grid ID value -> 1 bias
5638 feaProblem->feaSupport[i].gridIDSet[feaProblem->feaSupport[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID;
5639 }
5640 }
5641 }
5642
5643 status = string_freeArray(numGroupName, &groupName);
5644 if (status != CAPS_SUCCESS0) return status;
5645 groupName = NULL((void*)0);
5646
5647 //Fill up support properties
5648 /*! \page feaSupport
5649 *
5650 * \if (MYSTRAN || NASTRAN || ASTROS)
5651 * <ul>
5652 * <li> <B>dofSupport = 0 </B> </li> <br>
5653 * Component numbers / degrees of freedom that will be supported (123 - zero translation in all three
5654 * directions).
5655 * </ul>
5656 * \endif
5657 */
5658 keyWord = "dofSupport";
5659 status = search_jsonDictionary( supportTuple[i].value, keyWord, &keyValue);
5660 if (status == CAPS_SUCCESS0) {
5661
5662 status = string_toInteger(keyValue, &feaProblem->feaSupport[i].dofSupport);
5663 if (keyValue != NULL((void*)0)) {
5664 EG_free(keyValue);
5665 keyValue = NULL((void*)0);
5666 }
5667 if (status != CAPS_SUCCESS0) return status;
5668 }
5669
5670 } else {
5671
5672 /*! \page feaSupport
5673 * \section keyStringSupport Single Value String
5674 *
5675 * If "Value" is a string, the string value may correspond to an entry in a predefined support lookup
5676 * table. NOT YET IMPLEMENTED!!!!
5677 *
5678 */
5679
5680 // Call some look up table maybe?
5681 printf("\tError: Support tuple value is expected to be a JSON string\n");
5682 return CAPS_BADVALUE-311;
5683
5684 }
5685 }
5686
5687 if (keyValue != NULL((void*)0)) {
5688 EG_free(keyValue);
5689 keyValue = NULL((void*)0);
5690 }
5691
5692 printf("\tDone getting FEA supports\n");
5693 return CAPS_SUCCESS0;
5694}
5695
5696
5697static int fea_setConnection(char *connectionName,
5698 feaConnectionTypeEnum connectionType,
5699 int connectionID,
5700 int elementOffSet,
5701 int dofDependent,
5702 double stiffnessConst,
5703 double dampingConst,
5704 double stressCoeff,
5705 int componentNumberStart,
5706 int componentNumberEnd,
5707 int srcNodeID,
5708 double masterWeight,
5709 int masterComponent,
5710 int numNode, int *node,
5711 int *numConnect, feaConnectionStruct *feaConnect[]) { // Out
5712
5713 int status;
5714 int i;
5715
5716 if (numNode == 0) {
5717 status = CAPS_BADVALUE-311; // Nothing to do
5718 goto cleanup;
5719 }
5720
5721 if (connectionType == RigidBodyInterpolate) {
5722 *numConnect += 1;
5723
5724 (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),*numConnect*sizeof(feaConnectionStruct));
5725 if ((*feaConnect) == NULL((void*)0)) {
5726 *numConnect = 0;
5727 status = EGADS_MALLOC-4;
5728 goto cleanup;
5729 }
5730
5731 status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect-1]);
5732 if (status != CAPS_SUCCESS0) return status;
5733
5734 (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index
5735 (*feaConnect)[*numConnect-1].connectionType = connectionType;
5736
5737 (*feaConnect)[*numConnect-1].elementID = *numConnect + elementOffSet;
5738
5739 (*feaConnect)[*numConnect-1].dofDependent = dofDependent;
5740
5741 (*feaConnect)[*numConnect-1].connectivity[1] = srcNodeID; // Dependent
5742 (*feaConnect)[*numConnect-1].numMaster = numNode; // Independent
5743
5744 (*feaConnect)[*numConnect-1].masterIDSet = (int *) EG_alloc(numNode*sizeof(int)); // [numMaster]
5745 if ((*feaConnect)[*numConnect-1].masterIDSet == NULL((void*)0)) {
5746 status = EGADS_MALLOC-4;
5747 goto cleanup;
5748 }
5749 (*feaConnect)[*numConnect-1].masterWeighting = (double *) EG_alloc(numNode*sizeof(double));; // [numMaster]
5750 if ((*feaConnect)[*numConnect-1].masterWeighting == NULL((void*)0)) {
5751 status = EGADS_MALLOC-4;
5752 goto cleanup;
5753 }
5754
5755 (*feaConnect)[*numConnect-1].masterComponent =(int *) EG_alloc(numNode*sizeof(int));; // [numMaster]
5756 if ((*feaConnect)[*numConnect-1].masterComponent == NULL((void*)0)) {
5757 status = EGADS_MALLOC-4;
5758 goto cleanup;
5759 }
5760
5761 //printf("\tMasters (%d)", numNode);
5762 // Master values;
5763 for (i = 0; i < numNode; i++) {
5764 // printf(" %d", node[i]);
5765
5766 (*feaConnect)[*numConnect-1].masterIDSet[i] = node[i];
5767 (*feaConnect)[*numConnect-1].masterWeighting[i] = masterWeight;
5768 (*feaConnect)[*numConnect-1].masterComponent[i] = masterComponent;
5769 }
5770 //printf("\n");
5771
5772 } else { // For all other types of connections create an individual connection - single pair of nodes
5773
5774 (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),(*numConnect+numNode)*sizeof(feaConnectionStruct));
5775 if ((*feaConnect) == NULL((void*)0)) {
5776 *numConnect = 0;
5777 status = EGADS_MALLOC-4;
5778 goto cleanup;
5779 }
5780
5781 for (i = 0; i < numNode; i++) {
5782 status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect+i]);
5783 if (status != CAPS_SUCCESS0) return status;
5784 }
5785
5786 for (i = 0; i < numNode; i++) {
5787
5788 *numConnect += 1;
5789
5790 (*feaConnect)[*numConnect-1].name = (char *) EG_alloc((strlen(connectionName) + 1)*sizeof(char));
5791 if ((*feaConnect)[*numConnect-1].name == NULL((void*)0)) return EGADS_MALLOC-4;
5792
5793 memcpy((*feaConnect)[*numConnect-1].name,
5794 connectionName,
5795 strlen(connectionName)*sizeof(char));
5796 (*feaConnect)[*numConnect-1].name[strlen(connectionName)] = '\0';
5797
5798 (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index
5799
5800 (*feaConnect)[*numConnect-1].connectionType = connectionType;
5801 (*feaConnect)[*numConnect-1].elementID = *numConnect + elementOffSet;
5802
5803 (*feaConnect)[*numConnect-1].connectivity[0] = srcNodeID;
5804 (*feaConnect)[*numConnect-1].connectivity[1] = node[i];
5805
5806 (*feaConnect)[*numConnect-1].dofDependent = dofDependent;
5807 (*feaConnect)[*numConnect-1].stiffnessConst = stiffnessConst;
5808 (*feaConnect)[*numConnect-1].dampingConst = dampingConst;
5809 (*feaConnect)[*numConnect-1].stressCoeff = stressCoeff;
5810 (*feaConnect)[*numConnect-1].componentNumberStart = componentNumberStart;
5811 (*feaConnect)[*numConnect-1].componentNumberEnd = componentNumberEnd;
5812 }
5813 }
5814
5815 status = CAPS_SUCCESS0;
5816 goto cleanup;
5817
5818 cleanup:
5819 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_setConnection, status = %d\n", status);
5820 return status;
5821}
5822// Get the Connections properties from a capsTuple and create connections based on the mesh
5823int fea_getConnection(int numConnectionTuple,
5824 capsTuple connectionTuple[],
5825 mapAttrToIndexStruct *attrMap,
5826 feaProblemStruct *feaProblem) {
5827
5828 /*! \page feaConnection FEA Connection
5829 * Structure for the connection tuple = ("Connection Name", "Value").
5830 * "Connection Name" defines the reference name to the capsConnect being specified and denotes the "source" node
5831 * for the connection.
5832 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConnection) or a single string keyword
5833 * (see Section \ref keyStringConnection).
5834 */
5835
5836 int status; //Function return
5837
5838 int i, groupIndex, nodeIndex, nodeIndexDest; // Indexing
5839
5840 char *keyValue = NULL((void*)0); // Key values from tuple searches
5841 char *keyWord = NULL((void*)0); // Key words to find in the tuples
5842
5843 int numGroupName = 0;
5844 char **groupName = NULL((void*)0);
5845 int attrIndex, attrIndexDest;
5846
5847 // Values to set
5848 feaConnectionTypeEnum connectionType;
5849 int dofDependent = 0, componentNumberStart = 0, componentNumberEnd = 0;
5850 double stiffnessConst = 0.0, dampingConst = 0.0, stressCoeff = 0.0, mass = 0.0;
5851
5852 double weighting=1;
5853
5854 int glue = (int) false0, glueNumMaster = 5;
5855 double glueSearchRadius=0;
5856
5857 feaMeshDataStruct *feaData, *feaDataDest;
5858
5859 int numDestNode=0, *destNode=NULL((void*)0);
5860
5861 // Destroy our support structures coming in if aren't 0 and NULL already
5862 if (feaProblem->feaConnect != NULL((void*)0)) {
5863 for (i = 0; i < feaProblem->numConnect; i++) {
5864 status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]);
5865 if (status != CAPS_SUCCESS0) return status;
5866 }
5867 }
5868 if (feaProblem->feaConnect != NULL((void*)0)) EG_free(feaProblem->feaConnect);
5869 feaProblem->feaConnect = NULL((void*)0);
5870 feaProblem->numConnect = 0;
5871
5872 printf("\nGetting FEA connections.......\n");
5873
5874 printf("\tNumber of connection tuples - %d\n", numConnectionTuple);
5875
5876 // Loop through tuples and fill out the support structures
5877 for (i = 0; i < numConnectionTuple; i++) {
5878
5879 // Reset defaults
5880 dofDependent = componentNumberStart = componentNumberEnd = 0;
5881 stiffnessConst = dampingConst = stressCoeff = mass = 0.0;
5882
5883 weighting=1;
5884
5885 glue = (int) false0;
5886 glueNumMaster = 5;
5887 glueSearchRadius = 0;
5888
5889 printf("\tConnection name - %s\n", connectionTuple[i].name );
5890
5891 // Look for connection name in connection map
5892 status = get_mapAttrToIndexIndex(attrMap, (const char *) connectionTuple[i].name, &attrIndex);
5893 if (status == CAPS_NOTFOUND-303) {
5894 printf("\tName %s not found in attribute map of capsConnect!!!!\n", connectionTuple[i].name);
5895 continue;
5896 } else if (status != CAPS_SUCCESS0) return status;
5897
5898 // Do we have a json string?
5899 if (strncmp(connectionTuple[i].value, "{", 1) == 0) {
5900
5901 /*! \page feaConnection
5902 * \section jsonStringConnection JSON String Dictionary
5903 *
5904 * If "Value" is JSON string dictionary
5905 * \if (MYSTRAN || NASTRAN || ASTROS)
5906 * (e.g. "Value" = {"dofDependent": 1, "propertyType": "RigidBody"})
5907 * \endif
5908 * the following keywords ( = default values) may be used:
5909 *
5910 *
5911 * \if (MYSTRAN || NASTRAN)
5912 * <ul>
5913 * <li> <B>connectionType = RigidBody</B> </li> <br>
5914 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
5915 * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody, RigidBodyInterpolate.
5916 * </ul>
5917 * \elseif (ASTROS)
5918 * <ul>
5919 * <li> <B>connectionType = RigidBody</B> </li> <br>
5920 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
5921 * Options: Mass (scalar), Spring (scalar), RigidBody, RigidBodyInterpolate.
5922 * </ul>
5923 * \endif
5924 *
5925 */
5926 // Get connection Type
5927 keyWord = "connectionType";
5928 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
5929 if (status == CAPS_SUCCESS0) {
5930
5931 //{UnknownConnection, Mass, Spring, Damper, RigidBody}
5932 if (strcasecmp(keyValue, "\"Mass\"") == 0) connectionType = Mass;
5933 else if (strcasecmp(keyValue, "\"Spring\"") == 0) connectionType = Spring;
5934 else if (strcasecmp(keyValue, "\"Damper\"") == 0) connectionType = Damper;
5935 else if (strcasecmp(keyValue, "\"RigidBody\"") == 0) connectionType = RigidBody;
5936 else if (strcasecmp(keyValue, "\"RigidBodyInterpolate\"") == 0) connectionType = RigidBodyInterpolate;
5937 else {
5938 printf("\tUnrecognized \"%s\" specified (%s) for Connection tuple %s, current options are "
5939 "\"Mass, Spring, Damper, RigidBody, and RigidBodyInterpolate\"\n", keyWord,
5940 keyValue,
5941 connectionTuple[i].name);
5942 if (keyValue != NULL((void*)0)) {
5943 EG_free(keyValue);
5944 keyValue = NULL((void*)0);
5945 }
5946
5947 return CAPS_NOTFOUND-303;
5948 }
5949
5950 } else {
5951
5952 printf("\tNo \"%s\" specified for Connection tuple %s, defaulting to RigidBody\n", keyWord,
5953 connectionTuple[i].name);
5954 connectionType = RigidBody;
5955 }
5956
5957 /*! \page feaConnection
5958 *
5959 * \if (MYSTRAN || NASTRAN || ASTROS)
5960 * <ul>
5961 * <li> <B>dofDependent = 0 </B> </li> <br>
5962 * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three
5963 * directions).
5964 * </ul>
5965 * \endif
5966 *
5967 */
5968 keyWord = "dofDependent";
5969 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
5970 if (status == CAPS_SUCCESS0) {
5971
5972 status = string_toInteger(keyValue, &dofDependent);
5973 if (keyValue != NULL((void*)0)) {
5974 EG_free(keyValue);
5975 keyValue = NULL((void*)0);
5976 }
5977 if (status != CAPS_SUCCESS0) return status;
5978 }
5979
5980
5981 /*! \page feaConnection
5982 *
5983 * \if (MYSTRAN || NASTRAN || ASTROS)
5984 * <ul>
5985 * <li> <B>componentNumberStart = 0 </B> </li> <br>
5986 * Component numbers / degrees of freedom of the starting point of the connection for mass,
5987 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
5988 * </ul>
5989 * \endif
5990 */
5991 keyWord = "componentNumberStart";
5992 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
5993 if (status == CAPS_SUCCESS0) {
5994
5995 status = string_toInteger(keyValue, &componentNumberStart);
5996 if (keyValue != NULL((void*)0)) {
5997 EG_free(keyValue);
5998 keyValue = NULL((void*)0);
5999 }
6000 if (status != CAPS_SUCCESS0) return status;
6001 }
6002
6003 /*! \page feaConnection
6004 *
6005 * \if (MYSTRAN || NASTRAN || ASTROS)
6006 * <ul>
6007 * <li> <B>componentNumberEnd= 0 </B> </li> <br>
6008 * Component numbers / degrees of freedom of the ending point of the connection for mass,
6009 * spring, damper elements (scalar), and rigid body interpolative connection ( 0 <= Integer <= 6).
6010 * </ul>
6011 * \endif
6012 *
6013 */
6014 keyWord = "componentNumberEnd";
6015 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6016 if (status == CAPS_SUCCESS0) {
6017
6018 status = string_toInteger(keyValue, &componentNumberEnd);
6019 if (keyValue != NULL((void*)0)) {
6020 EG_free(keyValue);
6021 keyValue = NULL((void*)0);
6022 }
6023 if (status != CAPS_SUCCESS0) return status;
6024 }
6025
6026 /*! \page feaConnection
6027 *
6028 * \if (MYSTRAN || NASTRAN || ASTROS)
6029 * <ul>
6030 * <li> <B>stiffnessConst = 0.0 </B> </li> <br>
6031 * Stiffness constant of a spring element (scalar).
6032 * </ul>
6033 * \endif
6034 */
6035 keyWord = "stiffnessConst";
6036 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6037 if (status == CAPS_SUCCESS0) {
6038
6039 status = string_toDouble(keyValue, &stiffnessConst);
6040 if (keyValue != NULL((void*)0)) {
6041 EG_free(keyValue);
6042 keyValue = NULL((void*)0);
6043 }
6044 if (status != CAPS_SUCCESS0) return status;
6045 }
6046
6047 /*! \page feaConnection
6048 *
6049 * \if (MYSTRAN || NASTRAN || ASTROS)
6050 * <ul>
6051 * <li> <B>dampingConst = 0.0 </B> </li> <br>
6052 * Damping coefficient/constant of a spring or damping element (scalar).
6053 * </ul>
6054 * \endif
6055 */
6056 keyWord = "dampingConst";
6057 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6058 if (status == CAPS_SUCCESS0) {
6059
6060 status = string_toDouble(keyValue, &dampingConst);
6061 if (keyValue != NULL((void*)0)) {
6062 EG_free(keyValue);
6063 keyValue = NULL((void*)0);
6064 }
6065 if (status != CAPS_SUCCESS0) return status;
6066 }
6067
6068 /*! \page feaConnection
6069 *
6070 * \if (MYSTRAN || NASTRAN || ASTROS)
6071 * <ul>
6072 * <li> <B>stressCoeff = 0.0 </B> </li> <br>
6073 * Stress coefficient of a spring element (scalar).
6074 * </ul>
6075 * \endif
6076 */
6077 keyWord = "stressCoeff";
6078 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6079 if (status == CAPS_SUCCESS0) {
6080
6081 status = string_toDouble(keyValue, &stressCoeff);
6082 if (keyValue != NULL((void*)0)) {
6083 EG_free(keyValue);
6084 keyValue = NULL((void*)0);
6085 }
6086 if (status != CAPS_SUCCESS0) return status;
6087 }
6088
6089 /*! \page feaConnection
6090 *
6091 * \if (MYSTRAN || NASTRAN || ASTROS)
6092 * <ul>
6093 * <li> <B>mass = 0.0 </B> </li> <br>
6094 * Mass of a mass element (scalar).
6095 * </ul>
6096 * \endif
6097 */
6098 keyWord = "mass";
6099 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6100 if (status == CAPS_SUCCESS0) {
6101
6102 status = string_toDouble(keyValue, &mass);
6103 if (keyValue != NULL((void*)0)) {
6104 EG_free(keyValue);
6105 keyValue = NULL((void*)0);
6106 }
6107 if (status != CAPS_SUCCESS0) return status;
6108 }
6109
6110 /* \page feaConnection
6111 *
6112 * \if (MYSTRAN || NASTRAN || ASTROS)
6113 * <ul>
6114 * <li> <B>glue = False </B> </li> <br>
6115 * Turn on gluing for the connection.
6116 * </ul>
6117 * \endif
6118 */
6119 keyWord = "glue";
6120 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6121 if (status == CAPS_SUCCESS0) {
6122
6123 status = string_toBoolean(keyValue, &glue);
6124 if (keyValue != NULL((void*)0)) {
6125 EG_free(keyValue);
6126 keyValue = NULL((void*)0);
6127 }
6128 if (status != CAPS_SUCCESS0) return status;
6129 }
6130
6131 /* \page feaConnection
6132 *
6133 * \if (MYSTRAN || NASTRAN || ASTROS)
6134 * <ul>
6135 * <li> <B>glueNumMaster = 5 </B> </li> <br>
6136 * Maximum number of the masters for a glue connections.
6137 * </ul>
6138 * \endif
6139 */
6140 keyWord = "glueNumMaster";
6141 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6142 if (status == CAPS_SUCCESS0) {
6143
6144 status = string_toInteger(keyValue, &glueNumMaster);
6145 if (keyValue != NULL((void*)0)) {
6146 EG_free(keyValue);
6147 keyValue = NULL((void*)0);
6148 }
6149 if (status != CAPS_SUCCESS0) return status;
6150 }
6151
6152 /* \page feaConnection
6153 *
6154 * \if (MYSTRAN || NASTRAN || ASTROS)
6155 * <ul>
6156 * <li> <B>glueSearchRadius = 0 </B> </li> <br>
6157 * Search radius when looking for masters for a glue connections.
6158 * </ul>
6159 * \endif
6160 */
6161 keyWord = "glueSearchRadius";
6162 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6163 if (status == CAPS_SUCCESS0) {
6164
6165 status = string_toDouble(keyValue, &glueSearchRadius);
6166 if (keyValue != NULL((void*)0)) {
6167 EG_free(keyValue);
6168 keyValue = NULL((void*)0);
6169 }
6170 if (status != CAPS_SUCCESS0) return status;
6171 }
6172
6173 /*! \page feaConnection
6174 *
6175 * \if (MYSTRAN || NASTRAN || ASTROS)
6176 * <ul>
6177 * <li> <B>weighting = 1 </B> </li> <br>
6178 * Weighting factor for a rigid body interpolative connections.
6179 * </ul>
6180 * \endif
6181 */
6182 keyWord = "weighting";
6183 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6184 if (status == CAPS_SUCCESS0) {
6185
6186 status = string_toDouble(keyValue, &weighting);
6187 if (keyValue != NULL((void*)0)) {
6188 EG_free(keyValue);
6189 keyValue = NULL((void*)0);
6190 }
6191 if (status != CAPS_SUCCESS0) return status;
6192 }
6193
6194 /*! \page feaConnection
6195 *
6196 * \if (MYSTRAN || NASTRAN || ASTROS)
6197 * <ul>
6198 * <li> <B>groupName = "(no default)"</B> </li> <br>
6199 * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the
6200 * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...].
6201 * </ul>
6202 * \endif
6203 */
6204 numGroupName = 0;
6205 keyWord = "groupName";
6206 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6207 if (status == CAPS_SUCCESS0) {
6208
6209 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
6210 if (keyValue != NULL((void*)0)) EG_free(keyValue);
6211 keyValue = NULL((void*)0);
6212
6213 if (status != CAPS_SUCCESS0) return status;
6214 if (glue == (int) true1 && connectionType != RigidBodyInterpolate) {
6215 printf("\tInvalid connectionType while glue = True, setting glue to False!\n");
6216 glue = (int) false0;
6217 }
6218
6219 if (glue == (int) true1 && connectionType == RigidBodyInterpolate) {
6220 status = fea_glueMesh(&feaProblem->feaMesh,
6221 i+1, //connectionID
6222 connectionType,
6223 dofDependent,
6224 connectionTuple[i].name,
6225 numGroupName,
6226 groupName,
6227 attrMap,
6228 glueNumMaster,
6229 glueSearchRadius,
6230 &feaProblem->numConnect,
6231 &feaProblem->feaConnect);
6232 if (status != CAPS_SUCCESS0) return status;
6233
6234 } else {
6235
6236
6237 destNode = (int *) EG_alloc(feaProblem->feaMesh.numNode*sizeof(int));
6238 if (destNode == NULL((void*)0)) {
6239 (void) string_freeArray(numGroupName, &groupName);
6240 return EGADS_MALLOC-4;
6241 }
6242
6243 // Find the "source" node in the mesh
6244 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6245
6246 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6247
6248 // If "source" doesn't match - continue
6249 if (feaData->connectIndex != attrIndex) continue;
6250
6251 numDestNode = 0;
6252
6253 // Lets loop through the group names and create the connections
6254 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
6255
6256 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndexDest);
6257 if (status == CAPS_NOTFOUND-303) {
6258 printf("\tName %s not found in attribute map of capsConnects!!!!\n", groupName[groupIndex]);
6259 continue;
6260 } else if (status != CAPS_SUCCESS0) {
6261 (void) string_freeArray(numGroupName, &groupName);
6262 AIM_FREE(destNode){ EG_free(destNode); destNode = ((void*)0); };
6263 return status;
6264 }
6265
6266 // Find the "destination" node in the mesh
6267 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6268
6269 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6270
6271 // If the "destination" doesn't match - continue
6272 if (feaDataDest->connectIndex != attrIndexDest) continue;
6273
6274 destNode[numDestNode] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6275 numDestNode += 1;
6276 } // End destination loop
6277
6278 } // End group loop
6279
6280 if (numDestNode <= 0) {
6281 printf("\tNo destination nodes found for connection %s\n", connectionTuple[i].name);
6282 } else {
6283
6284 status = fea_setConnection(connectionTuple[i].name,
6285 connectionType,
6286 i+1,
6287 feaProblem->feaMesh.numElement,
6288 dofDependent,
6289 stiffnessConst,
6290 dampingConst,
6291 stressCoeff,
6292 componentNumberStart,
6293 componentNumberEnd,
6294 feaProblem->feaMesh.node[nodeIndex].nodeID,
6295 weighting,
6296 componentNumberEnd,
6297 numDestNode, destNode,
6298 &feaProblem->numConnect,
6299 &feaProblem->feaConnect);
6300 if (status != CAPS_SUCCESS0) {
6301 (void) string_freeArray(numGroupName, &groupName);
6302 if (destNode !=NULL((void*)0)) EG_free(destNode);
6303 return status;
6304 }
6305 }
6306 } // End source loop
6307 } // Glue ifelse
6308
6309 if (destNode !=NULL((void*)0)) EG_free(destNode);
6310 destNode = NULL((void*)0);
6311
6312 status = string_freeArray(numGroupName, &groupName);
6313 if (status != CAPS_SUCCESS0) return status;
6314
6315 } else {
6316 printf("\tNo \"%s\" specified for Connection tuple %s!\n", keyWord, connectionTuple[i].name);
6317 }
6318
6319 // Create automatic connections from the "capsConnectLink" tag
6320 printf("\tLooking for automatic connections from the use of capsConnectLink for %s\n", connectionTuple[i].name);
6321
6322 destNode = (int *) EG_alloc(feaProblem->feaMesh.numNode*sizeof(int));
6323 if (destNode == NULL((void*)0)) return EGADS_MALLOC-4;
6324
6325 // Find the "source" node in the mesh
6326 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6327
6328 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6329
6330 // If "source" doesn't match - continue
6331 if (feaData->connectIndex != attrIndex) continue;
6332
6333 numDestNode = 0;
6334 // Find the "destination" node in the mesh
6335 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6336
6337 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6338
6339 // If the "destination" doesn't match - continue
6340 if (feaDataDest->connectLinkIndex != attrIndex) continue;
6341
6342 destNode[numDestNode] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6343 numDestNode += 1;
6344 } // End destination loop
6345
6346 if (numDestNode > 0) {
6347 status = fea_setConnection(connectionTuple[i].name,
6348 connectionType,
6349 i+1,
6350 feaProblem->feaMesh.numElement,
6351 dofDependent,
6352 stiffnessConst,
6353 dampingConst,
6354 stressCoeff,
6355 componentNumberStart,
6356 componentNumberEnd,
6357 feaProblem->feaMesh.node[nodeIndex].nodeID,
6358 weighting,
6359 componentNumberEnd,
6360 numDestNode, destNode,
6361 &feaProblem->numConnect,
6362 &feaProblem->feaConnect);
6363 if (status != CAPS_SUCCESS0) {
6364 if (destNode !=NULL((void*)0)) EG_free(destNode);
6365 return status;
6366 }
6367 }
6368
6369 if (numDestNode > 0) {
6370 printf("\t%d automatic connections were made for capsConnect %s (node id %d)\n", numDestNode,
6371 connectionTuple[i].name,
6372 feaProblem->feaMesh.node[nodeIndex].nodeID);
6373 }
6374 } // End source loop
6375
6376 if (destNode !=NULL((void*)0)) EG_free(destNode);
6377 destNode = NULL((void*)0);
6378
6379 } else {
6380
6381 /*! \page feaConnection
6382 * \section keyStringConnection Single Value String
6383 *
6384 * If "Value" is a string, the string value may correspond to an entry in a predefined connection lookup
6385 * table. NOT YET IMPLEMENTED!!!!
6386 *
6387 */
6388
6389 // Call some look up table maybe?
6390 printf("\tError: Connection tuple value is expected to be a JSON string\n");
6391 return CAPS_BADVALUE-311;
6392
6393 }
6394 }
6395
6396 if (keyValue != NULL((void*)0)) {
6397 EG_free(keyValue);
6398 keyValue = NULL((void*)0);
6399 }
6400
6401 printf("\tDone getting FEA connections\n");
6402 return CAPS_SUCCESS0;
6403}
6404
6405#ifdef FEA_GETCONNECTIONORIG_DEPREICATE
6406// Get the Connections properties from a capsTuple and create connections based on the mesh
6407static int fea_getConnectionOrig(int numConnectionTuple,
6408 capsTuple connectionTuple[],
6409 mapAttrToIndexStruct *attrMap,
6410 feaProblemStruct *feaProblem) {
6411
6412 /* \page feaConnection FEA Connection
6413 * Structure for the connection tuple = ("Connection Name", "Value").
6414 * "Connection Name" defines the reference name to the capsConnect being specified and denotes the "source" node
6415 * for the connection.
6416 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConnection) or a single string keyword
6417 * (see Section \ref keyStringConnection).
6418 */
6419
6420 int status; //Function return
6421
6422 int i, groupIndex, nodeIndex, nodeIndexDest, counter = 0; // Indexing
6423
6424 char *keyValue = NULL((void*)0); // Key values from tuple searches
6425 char *keyWord = NULL((void*)0); // Key words to find in the tuples
6426
6427 int numGroupName = 0;
6428 char **groupName = NULL((void*)0);
6429 int attrIndex, attrIndexDest;
6430
6431 // Values to set
6432 feaConnectionTypeEnum connectionType;
6433 int dofDependent = 0, componentNumberStart = 0, componentNumberEnd = 0;
6434 double stiffnessConst = 0.0, dampingConst = 0.0, stressCoeff = 0.0, mass = 0.0;
6435
6436 feaMeshDataStruct *feaData, *feaDataDest;
6437
6438 // Destroy our support structures coming in if aren't 0 and NULL already
6439 if (feaProblem->feaConnect != NULL((void*)0)) {
6440 for (i = 0; i < feaProblem->numConnect; i++) {
6441 status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]);
6442 if (status != CAPS_SUCCESS0) return status;
6443 }
6444 }
6445 if (feaProblem->feaConnect != NULL((void*)0)) EG_free(feaProblem->feaConnect);
6446 feaProblem->feaConnect = NULL((void*)0);
6447 feaProblem->numConnect = 0;
6448
6449 printf("\nGetting FEA connections.......\n");
6450
6451 printf("\tNumber of connection tuples - %d\n", numConnectionTuple);
6452
6453 // Loop through tuples and fill out the support structures
6454 for (i = 0; i < numConnectionTuple; i++) {
6455
6456 // Reset defaults
6457 dofDependent = componentNumberStart = componentNumberEnd = 0;
6458 stiffnessConst = dampingConst = stressCoeff = mass = 0.0;
6459
6460 printf("\tConnection name - %s\n", connectionTuple[i].name );
6461
6462 // Look for connection name in connection map
6463 status = get_mapAttrToIndexIndex(attrMap, (const char *) connectionTuple[i].name, &attrIndex);
6464 if (status == CAPS_NOTFOUND-303) {
6465 printf("\tName %s not found in attribute map of capsConnect!!!!\n", connectionTuple[i].name);
6466 continue;
6467 } else if (status != CAPS_SUCCESS0) return status;
6468
6469 // Do we have a json string?
6470 if (strncmp(connectionTuple[i].value, "{", 1) == 0) {
6471
6472 /* \page feaConnection
6473 * \section jsonStringConnection JSON String Dictionary
6474 *
6475 * If "Value" is JSON string dictionary
6476 * \if (MYSTRAN || NASTRAN || ASTROS)
6477 * (e.g. "Value" = {"dofDependent": 1, "propertyType": "RigidBody"})
6478 * \endif
6479 * the following keywords ( = default values) may be used:
6480 *
6481 *
6482 * \if (MYSTRAN || NASTRAN)
6483 * <ul>
6484 * <li> <B>connectionType = RigidBody</B> </li> <br>
6485 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
6486 * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody.
6487 * </ul>
6488 * \elseif (ASTROS)
6489 * <ul>
6490 * <li> <B>connectionType = RigidBody</B> </li> <br>
6491 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
6492 * Options: Mass (scalar), Spring (scalar), RigidBody.
6493 * </ul>
6494 * \elseif ABAQUS
6495 *
6496 * Something else ....
6497 *
6498 * \else
6499 * <ul>
6500 * <li> <B>connectionType = RigidBody</B> </li> <br>
6501 * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName".
6502 * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody.
6503 * </ul>
6504 * \endif
6505 *
6506 */
6507
6508 // Get connection Type
6509 keyWord = "connectionType";
6510 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6511 if (status == CAPS_SUCCESS0) {
6512
6513 //{UnknownConnection, Mass, Spring, Damper, RigidBody}
6514 if (strcasecmp(keyValue, "\"Mass\"") == 0) connectionType = Mass;
6515 else if (strcasecmp(keyValue, "\"Spring\"") == 0) connectionType = Spring;
6516 else if (strcasecmp(keyValue, "\"Damper\"") == 0) connectionType = Damper;
6517 else if (strcasecmp(keyValue, "\"RigidBody\"") == 0) connectionType = RigidBody;
6518 else {
6519 printf("\tUnrecognized \"%s\" specified (%s) for Connection tuple %s, current options are "
6520 "\"Mass, Spring, Damper, and RigidBody\"\n", keyWord,
6521 keyValue,
6522 connectionTuple[i].name);
6523 if (keyValue != NULL((void*)0)) {
6524 EG_free(keyValue);
6525 keyValue = NULL((void*)0);
6526 }
6527
6528 return CAPS_NOTFOUND-303;
6529 }
6530
6531 } else {
6532
6533 printf("\tNo \"%s\" specified for Connection tuple %s, defaulting to RigidBody\n", keyWord,
6534 connectionTuple[i].name);
6535 connectionType = RigidBody;
6536 }
6537
6538 /* \page feaConnection
6539 *
6540 * \if (MYSTRAN || NASTRAN || ASTROS)
6541 * <ul>
6542 * <li> <B>dofDependent = 0 </B> </li> <br>
6543 * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three
6544 * directions).
6545 * </ul>
6546 * \elseif ABAQUS
6547 *
6548 * Something else ....
6549 *
6550 * \else
6551 * <ul>
6552 * <li> <B>dofDependent = 0 </B> </li> <br>
6553 * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three
6554 * directions).
6555 * </ul>
6556 * \endif
6557 *
6558 */
6559 keyWord = "dofDependent";
6560 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6561 if (status == CAPS_SUCCESS0) {
6562
6563 status = string_toInteger(keyValue, &dofDependent);
6564 if (keyValue != NULL((void*)0)) {
6565 EG_free(keyValue);
6566 keyValue = NULL((void*)0);
6567 }
6568 if (status != CAPS_SUCCESS0) return status;
6569 }
6570
6571
6572 /* \page feaConnection
6573 *
6574 * \if (MYSTRAN || NASTRAN || ASTROS)
6575 * <ul>
6576 * <li> <B>componentNumberStart = 0 </B> </li> <br>
6577 * Component numbers / degrees of freedom of the starting point of the connection for mass,
6578 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6579 * </ul>
6580 * \elseif ABAQUS
6581 *
6582 * Something else ....
6583 *
6584 * \else
6585 * <ul>
6586 * <li> <B>componentNumberStart = 0 </B> </li> <br>
6587 * Component numbers / degrees of freedom of the starting point of the connection for mass,
6588 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6589 * </ul>
6590 * \endif
6591 *
6592 */
6593 keyWord = "componentNumberStart";
6594 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6595 if (status == CAPS_SUCCESS0) {
6596
6597 status = string_toInteger(keyValue, &componentNumberStart);
6598 if (keyValue != NULL((void*)0)) {
6599 EG_free(keyValue);
6600 keyValue = NULL((void*)0);
6601 }
6602 if (status != CAPS_SUCCESS0) return status;
6603 }
6604
6605 /* \page feaConnection
6606 *
6607 * \if (MYSTRAN || NASTRAN || ASTROS)
6608 * <ul>
6609 * <li> <B>componentNumberEnd= 0 </B> </li> <br>
6610 * Component numbers / degrees of freedom of the ending point of the connection for mass,
6611 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6612 * </ul>
6613 * \elseif ABAQUS
6614 *
6615 * Something else ....
6616 *
6617 * \else
6618 * <ul>
6619 * <li> <B>componentNumberEnd = 0 </B> </li> <br>
6620 * Component numbers / degrees of freedom of the ending point of the connection for mass,
6621 * spring, and damper elements (scalar) ( 0 <= Integer <= 6).
6622 * </ul>
6623 * \endif
6624 *
6625 */
6626 keyWord = "componentNumberEnd";
6627 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6628 if (status == CAPS_SUCCESS0) {
6629
6630 status = string_toInteger(keyValue, &componentNumberEnd);
6631 if (keyValue != NULL((void*)0)) {
6632 EG_free(keyValue);
6633 keyValue = NULL((void*)0);
6634 }
6635 if (status != CAPS_SUCCESS0) return status;
6636 }
6637
6638 /* \page feaConnection
6639 *
6640 * \if (MYSTRAN || NASTRAN || ASTROS)
6641 * <ul>
6642 * <li> <B>stiffnessConst = 0.0 </B> </li> <br>
6643 * Stiffness constant of a spring element (scalar).
6644 * </ul>
6645 * \elseif ABAQUS
6646 *
6647 * Something else ....
6648 *
6649 * \else
6650 * <ul>
6651 * <li> <B>stiffnessConst = 0.00 </B> </li> <br>
6652 * Stiffness constant of a spring element (scalar).
6653 * </ul>
6654 * \endif
6655 *
6656 */
6657 keyWord = "stiffnessConst";
6658 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6659 if (status == CAPS_SUCCESS0) {
6660
6661 status = string_toDouble(keyValue, &stiffnessConst);
6662 if (keyValue != NULL((void*)0)) {
6663 EG_free(keyValue);
6664 keyValue = NULL((void*)0);
6665 }
6666 if (status != CAPS_SUCCESS0) return status;
6667 }
6668
6669 /* \page feaConnection
6670 *
6671 * \if (MYSTRAN || NASTRAN || ASTROS)
6672 * <ul>
6673 * <li> <B>dampingConst = 0.0 </B> </li> <br>
6674 * Damping coefficient/constant of a spring or damping element (scalar).
6675 * </ul>
6676 * \elseif ABAQUS
6677 *
6678 * Something else ....
6679 *
6680 * \else
6681 * <ul>
6682 * <li> <B>dampingConst = 0.0 </B> </li> <br>
6683 * Damping constant of a spring or damping element (scalar).
6684 * </ul>
6685 * \endif
6686 *
6687 */
6688 keyWord = "dampingConst";
6689 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6690 if (status == CAPS_SUCCESS0) {
6691
6692 status = string_toDouble(keyValue, &dampingConst);
6693 if (keyValue != NULL((void*)0)) {
6694 EG_free(keyValue);
6695 keyValue = NULL((void*)0);
6696 }
6697 if (status != CAPS_SUCCESS0) return status;
6698 }
6699
6700 /* \page feaConnection
6701 *
6702 * \if (MYSTRAN || NASTRAN || ASTROS)
6703 * <ul>
6704 * <li> <B>stressCoeff = 0.0 </B> </li> <br>
6705 * Stress coefficient of a spring element (scalar).
6706 * </ul>
6707 * \elseif ABAQUS
6708 *
6709 * Something else ....
6710 *
6711 * \else
6712 * <ul>
6713 * <li> <B>stressCoeff = 0.0 </B> </li> <br>
6714 * Stress coefficient of a spring element (scalar).
6715 * </ul>
6716 * \endif
6717 *
6718 */
6719 keyWord = "stressCoeff";
6720 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6721 if (status == CAPS_SUCCESS0) {
6722
6723 status = string_toDouble(keyValue, &stressCoeff);
6724 if (keyValue != NULL((void*)0)) {
6725 EG_free(keyValue);
6726 keyValue = NULL((void*)0);
6727 }
6728 if (status != CAPS_SUCCESS0) return status;
6729 }
6730
6731 /* \page feaConnection
6732 *
6733 * \if (MYSTRAN || NASTRAN || ASTROS)
6734 * <ul>
6735 * <li> <B>mass = 0.0 </B> </li> <br>
6736 * Mass of a mass element (scalar).
6737 * </ul>
6738 * \elseif ABAQUS
6739 *
6740 * Something else ....
6741 *
6742 * \else
6743 * <ul>
6744 * <li> <B>mass = 0.0 </B> </li> <br>
6745 * Mass of a mass element (scalar).
6746 * </ul>
6747 * \endif
6748 *
6749 */
6750 keyWord = "mass";
6751 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6752 if (status == CAPS_SUCCESS0) {
6753
6754 status = string_toDouble(keyValue, &mass);
6755 if (keyValue != NULL((void*)0)) {
6756 EG_free(keyValue);
6757 keyValue = NULL((void*)0);
6758 }
6759 if (status != CAPS_SUCCESS0) return status;
6760 }
6761
6762 /* \page feaConnection
6763 *
6764 * \if (MYSTRAN || NASTRAN || ASTROS)
6765 * <ul>
6766 * <li> <B>groupName = "(no default)"</B> </li> <br>
6767 * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the
6768 * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...].
6769 * </ul>
6770 * \elseif ABAQUS
6771 *
6772 * Something else ....
6773 *
6774 * \else
6775 * <ul>
6776 * <li> <B>groupName = "(no default)"</B> </li> <br>
6777 * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the
6778 * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...].
6779 * </ul>
6780 * \endif
6781 *
6782 */
6783 numGroupName = 0;
6784 keyWord = "groupName";
6785 status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue);
6786 if (status == CAPS_SUCCESS0) {
6787
6788 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
6789 if (keyValue != NULL((void*)0)) EG_free(keyValue);
6790 keyValue = NULL((void*)0);
6791
6792 if (status != CAPS_SUCCESS0) return status;
6793
6794 // Lets loop through the group names and create the connections
6795 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
6796
6797 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndexDest);
6798 if (status == CAPS_NOTFOUND-303) {
6799 printf("\tName %s not found in attribute map of capsConnects!!!!\n", groupName[groupIndex]);
6800 continue;
6801 } else if (status != CAPS_SUCCESS0) {
6802 (void) string_freeArray(numGroupName, &groupName);
6803 return status;
6804 }
6805
6806 // Find the "source" node in the mesh
6807 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6808
6809 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6810
6811 // If "source" doesn't match - continue
6812 if (feaData->connectIndex != attrIndex) continue;
6813
6814 // Find the "destination" node in the mesh
6815 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6816
6817 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6818
6819 // If the "destination" doesn't match - continue
6820 if (feaDataDest->connectIndex != attrIndexDest) continue;
6821
6822 feaProblem->numConnect += 1;
6823
6824 if (feaProblem->numConnect == 1) {
6825 feaProblem->feaConnect = (feaConnectionStruct *) EG_alloc(sizeof(feaConnectionStruct));
6826 } else {
6827 feaProblem->feaConnect = (feaConnectionStruct *) EG_reall(feaProblem->feaConnect ,
6828 feaProblem->numConnect*sizeof(feaConnectionStruct));
6829 }
6830
6831 if (feaProblem->feaConnect == NULL((void*)0)) {
6832 feaProblem->numConnect = 0;
6833 (void) string_freeArray(numGroupName, &groupName);
6834 return EGADS_MALLOC-4;
6835 }
6836
6837 status = initiate_feaConnectionStruct(&feaProblem->feaConnect[feaProblem->numConnect-1]);
6838 if (status != CAPS_SUCCESS0) return status;
6839
6840 feaProblem->feaConnect[feaProblem->numConnect-1].name = (char *) EG_alloc((strlen(connectionTuple[i].name) + 1)*sizeof(char));
6841 if (feaProblem->feaConnect[feaProblem->numConnect-1].name == NULL((void*)0)) {
6842 (void) string_freeArray(numGroupName, &groupName);
6843 return EGADS_MALLOC-4;
6844 }
6845
6846 memcpy(feaProblem->feaConnect[feaProblem->numConnect-1].name,
6847 connectionTuple[i].name,
6848 strlen(connectionTuple[i].name)*sizeof(char));
6849 feaProblem->feaConnect[feaProblem->numConnect-1].name[strlen(connectionTuple[i].name)] = '\0';
6850
6851 feaProblem->feaConnect[feaProblem->numConnect-1].connectionID = i+1; // ConnectionTuple index
6852
6853 feaProblem->feaConnect[feaProblem->numConnect-1].connectionType = connectionType;
6854 feaProblem->feaConnect[feaProblem->numConnect-1].elementID = feaProblem->numConnect + feaProblem->feaMesh.numElement;
6855 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[0] = feaProblem->feaMesh.node[nodeIndex].nodeID;
6856 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[1] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6857
6858 feaProblem->feaConnect[feaProblem->numConnect-1].dofDependent = dofDependent;
6859 feaProblem->feaConnect[feaProblem->numConnect-1].stiffnessConst = stiffnessConst;
6860 feaProblem->feaConnect[feaProblem->numConnect-1].dampingConst = dampingConst;
6861 feaProblem->feaConnect[feaProblem->numConnect-1].stressCoeff = stressCoeff;
6862 feaProblem->feaConnect[feaProblem->numConnect-1].mass = mass;
6863 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberStart = componentNumberStart;
6864 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberEnd = componentNumberEnd;
6865 } // End destination loop
6866 } // End source loop
6867 } // End group loop
6868
6869 status = string_freeArray(numGroupName, &groupName);
6870 if (status != CAPS_SUCCESS0) return status;
6871
6872 } else {
6873 printf("\tNo \"%s\" specified for Connection tuple %s!\n", keyWord,
6874 connectionTuple[i].name);
6875 }
6876
6877
6878 // Create automatic connections from the "capsConnectLink" tag
6879 printf("\tLooking for automatic connections from the use of capsConnectLink for %s\n", connectionTuple[i].name);
6880
6881 // Find the "source" node in the mesh
6882 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
6883
6884 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
6885
6886 // If "source" doesn't match - continue
6887 if (feaData->connectIndex != attrIndex) continue;
6888
6889 counter = 0;
6890 // Find the "destination" node in the mesh
6891 for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) {
6892
6893 feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData;
6894
6895 // If the "destination" doesn't match - continue
6896 if (feaDataDest->connectLinkIndex != attrIndex) continue;
6897
6898 counter +=1;
6899
6900 feaProblem->numConnect += 1;
6901
6902 if (feaProblem->numConnect == 1) {
6903 feaProblem->feaConnect = (feaConnectionStruct *) EG_alloc(sizeof(feaConnectionStruct));
6904 } else {
6905 feaProblem->feaConnect = (feaConnectionStruct *) EG_reall(feaProblem->feaConnect ,
6906 feaProblem->numConnect*sizeof(feaConnectionStruct));
6907 }
6908
6909 if (feaProblem->feaConnect == NULL((void*)0)) {
6910 feaProblem->numConnect = 0;
6911 return EGADS_MALLOC-4;
6912 }
6913
6914 feaProblem->feaConnect[feaProblem->numConnect-1].name = (char *) EG_alloc((strlen(connectionTuple[i].name) + 1)*sizeof(char));
6915 if (feaProblem->feaConnect[feaProblem->numConnect-1].name == NULL((void*)0)) return EGADS_MALLOC-4;
6916
6917 memcpy(feaProblem->feaConnect[feaProblem->numConnect-1].name,
6918 connectionTuple[i].name,
6919 strlen(connectionTuple[i].name)*sizeof(char));
6920 feaProblem->feaConnect[feaProblem->numConnect-1].name[strlen(connectionTuple[i].name)] = '\0';
6921
6922 feaProblem->feaConnect[feaProblem->numConnect-1].connectionID = i+1; // ConnectionTuple index
6923
6924 feaProblem->feaConnect[feaProblem->numConnect-1].connectionType = connectionType;
6925 feaProblem->feaConnect[feaProblem->numConnect-1].elementID = feaProblem->numConnect + feaProblem->feaMesh.numElement;
6926 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[0] = feaProblem->feaMesh.node[nodeIndex].nodeID;
6927 feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[1] = feaProblem->feaMesh.node[nodeIndexDest].nodeID;
6928
6929 feaProblem->feaConnect[feaProblem->numConnect-1].dofDependent = dofDependent;
6930 feaProblem->feaConnect[feaProblem->numConnect-1].stiffnessConst = stiffnessConst;
6931 feaProblem->feaConnect[feaProblem->numConnect-1].dampingConst = dampingConst;
6932 feaProblem->feaConnect[feaProblem->numConnect-1].stressCoeff = stressCoeff;
6933 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberStart = componentNumberStart;
6934 feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberEnd = componentNumberEnd;
6935 } // End destination loop
6936
6937 printf("\t%d automatic connections were made for capsConnect %s\n", counter,
6938 connectionTuple[i].name);
6939 } // End source loop
6940 } else {
6941
6942 /* \page feaConnection
6943 * \section keyStringConnection Single Value String
6944 *
6945 * If "Value" is a string, the string value may correspond to an entry in a predefined connection lookup
6946 * table. NOT YET IMPLEMENTED!!!!
6947 *
6948 */
6949
6950 // Call some look up table maybe?
6951 printf("\tError: Connection tuple value is expected to be a JSON string\n");
6952 return CAPS_BADVALUE-311;
6953
6954 }
6955 }
6956
6957 if (keyValue != NULL((void*)0)) {
6958 EG_free(keyValue);
6959 keyValue = NULL((void*)0);
6960 }
6961
6962 printf("\tDone getting FEA connections\n");
6963 return CAPS_SUCCESS0;
6964}
6965#endif
6966
6967// Get the load properties from a capsTuple
6968int fea_getLoad(int numLoadTuple,
6969 capsTuple loadTuple[],
6970 mapAttrToIndexStruct *attrMap,
6971 feaProblemStruct *feaProblem) {
6972
6973 /*! \page feaLoad FEA Load
6974 * Structure for the load tuple = ("Load Name", "Value").
6975 * "Load Name" defines the reference name for the load being specified.
6976 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringLoad) or a single string keyword
6977 * (see Section \ref keyStringLoad).
6978 */
6979
6980 int status; //Function return
6981
6982 int i, groupIndex, attrIndex, nodeIndex, elementIndex; // Indexing
6983
6984 char *keyValue = NULL((void*)0); // Key values from tuple searches
6985 char *keyWord = NULL((void*)0); // Key words to find in the tuples
6986
6987 int numGroupName = 0;
6988 char **groupName = NULL((void*)0);
6989
6990 char *tempString = NULL((void*)0); // Temporary string holder
6991
6992 feaMeshDataStruct *feaData;
6993
6994 // Destroy our load structures coming in if aren't 0 and NULL already
6995 if (feaProblem->feaLoad != NULL((void*)0)) {
6996 for (i = 0; i < feaProblem->numLoad; i++) {
6997 status = destroy_feaLoadStruct(&feaProblem->feaLoad[i]);
6998 if (status != CAPS_SUCCESS0) return status;
6999 }
7000 }
7001 AIM_FREE(feaProblem->feaLoad){ EG_free(feaProblem->feaLoad); feaProblem->feaLoad = (
(void*)0); }
;
7002 feaProblem->numLoad = 0;
7003
7004 printf("\nGetting FEA loads.......\n");
7005
7006 feaProblem->numLoad = numLoadTuple;
7007
7008 printf("\tNumber of loads - %d\n", feaProblem->numLoad);
7009
7010 // Allocate loads
7011 if (feaProblem->numLoad > 0) {
7012 feaProblem->feaLoad = (feaLoadStruct *) EG_alloc(feaProblem->numLoad * sizeof(feaLoadStruct));
7013
7014 if (feaProblem->feaLoad == NULL((void*)0) ) return EGADS_MALLOC-4;
7015 }
7016
7017 // Initiate loads to default values
7018 for (i = 0; i < feaProblem->numLoad; i++) {
7019 status = initiate_feaLoadStruct(&feaProblem->feaLoad[i]);
7020 if (status != CAPS_SUCCESS0) return status;
7021 }
7022
7023 // Loop through tuples and fill out the load structures
7024 for (i = 0; i < feaProblem->numLoad; i++) {
7025
7026 printf("\tLoad name - %s\n", loadTuple[i].name );
7027
7028 // Set load name to tuple attribute name
7029 feaProblem->feaLoad[i].name = (char *) EG_alloc((strlen(loadTuple[i].name) + 1)*sizeof(char));
7030 if (feaProblem->feaLoad[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
7031
7032 memcpy(feaProblem->feaLoad[i].name, loadTuple[i].name, strlen(loadTuple[i].name)*sizeof(char));
7033 feaProblem->feaLoad[i].name[strlen(loadTuple[i].name)] = '\0';
7034
7035 // Set load id -> 1 bias
7036 feaProblem->feaLoad[i].loadID = i+1;
7037
7038 // Do we have a json string?
7039 if (strncmp(loadTuple[i].value, "{", 1) == 0) {
7040 //printf("JSON String - %s\n", constraintTuple[i].value);
7041
7042 /*! \page feaLoad
7043 * \section jsonStringLoad JSON String Dictionary
7044 *
7045 * If "Value" is JSON string dictionary
7046 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7047 * (e.g. "Value" = {"groupName": "plate", "loadType": "Pressure", "pressureForce": 2000000.0})
7048 * \endif
7049 * the following keywords ( = default values) may be used:
7050 *
7051 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7052 * <ul>
7053 * <li> <B>loadType = "(no default)"</B> </li> <br>
7054 * Type of load. Options: "GridForce", "GridMoment", "Rotational", "Thermal",
7055 * "Pressure", "PressureDistribute", "PressureExternal", "TermalExternal", "Gravity".
7056 * </ul>
7057 * \elseif ABAQUS
7058 * <ul>
7059 * <li> <B>loadType = "(no default)"</B> </li> <br>
7060 * Type of load. Options: "Pressure", "Gravity".
7061 * </ul>
7062 * \elseif HSM
7063 * <ul>
7064 * <li> <B>loadType = "(no default)"</B> </li> <br>
7065 * Type of load. Options: "GridForce", "GridMoment", "LineForce", "LineMoment", "Rotational",
7066 * "Pressure", "PressureDistribute", "PressureExternal", "Gravity".
7067 * </ul>
7068 * \else
7069 * \endif
7070 *
7071 */
7072 // Get load Type
7073 keyWord = "loadType";
7074 status = search_jsonDictionary(loadTuple[i].value, keyWord, &keyValue);
7075 if (status == CAPS_SUCCESS0) {
7076
7077 //{UnknownLoad, GridForce, GridMoment, Gravity, Pressure, Rotational, Thermal}
7078 if (strcasecmp(keyValue, "\"GridForce\"") == 0) feaProblem->feaLoad[i].loadType = GridForce;
7079 else if (strcasecmp(keyValue, "\"GridMoment\"") == 0) feaProblem->feaLoad[i].loadType = GridMoment;
7080 else if (strcasecmp(keyValue, "\"LineForce\"") == 0) feaProblem->feaLoad[i].loadType = LineForce;
7081 else if (strcasecmp(keyValue, "\"LineMoment\"") == 0) feaProblem->feaLoad[i].loadType = LineMoment;
7082 else if (strcasecmp(keyValue, "\"Rotational\"") == 0) feaProblem->feaLoad[i].loadType = Rotational;
7083 else if (strcasecmp(keyValue, "\"Thermal\"") == 0) feaProblem->feaLoad[i].loadType = Thermal;
7084 else if (strcasecmp(keyValue, "\"Pressure\"") == 0) feaProblem->feaLoad[i].loadType = Pressure;
7085 else if (strcasecmp(keyValue, "\"PressureDistribute\"") == 0) feaProblem->feaLoad[i].loadType = PressureDistribute;
7086 else if (strcasecmp(keyValue, "\"PressureExternal\"") == 0) feaProblem->feaLoad[i].loadType = PressureExternal;
7087 else if (strcasecmp(keyValue, "\"ThermalExternal\"") == 0) feaProblem->feaLoad[i].loadType = ThermalExternal;
7088 else if (strcasecmp(keyValue, "\"Gravity\"") == 0) feaProblem->feaLoad[i].loadType = Gravity;
7089 else {
7090 printf("\tUnrecognized \"%s\" specified (%s) for Load tuple %s\n", keyWord,
7091 keyValue,
7092 loadTuple[i].name);
7093 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7094 return CAPS_NOTFOUND-303;
7095 }
7096
7097 } else {
7098 printf("\t\"loadType\" variable not found in tuple %s, this is required input!!\n", loadTuple[i].name);
7099
7100 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7101 return status;
7102 }
7103
7104 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
7105
7106 // Get load node/element set
7107 /*! \page feaLoad
7108 *
7109 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7110 * <ul>
7111 * <li> <B>groupName = "(no default)"</B> </li> <br>
7112 * Single or list of <c>capsLoad</c> names on which to apply the load
7113 * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the load tuple name will be
7114 * used.
7115 * </ul>
7116 * \endif
7117 *
7118 */
7119 keyWord = "groupName";
7120 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7121 if (status == CAPS_SUCCESS0) {
7122
7123 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7124 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7125 keyValue = NULL((void*)0);
7126
7127 if (status != CAPS_SUCCESS0) return status;
7128
7129 } else {
7130
7131 printf("\tNo \"%s\" specified for Load tuple %s, going to use load name\n", keyWord,
7132 loadTuple[i].name);
7133
7134 status = string_toStringDynamicArray(loadTuple[i].name, &numGroupName, &groupName);
7135 if (status != CAPS_SUCCESS0) return status;
7136
7137 }
7138
7139 // Determine how many element/point loads we have
7140 feaProblem->feaLoad[i].numGridID = 0;
7141 feaProblem->feaLoad[i].numElementID = 0;
7142 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7143
7144 // Do nothing for PressureExternal, ThermalExternal, and Gravity loads
7145 if (feaProblem->feaLoad[i].loadType == PressureExternal) continue;
7146 if (feaProblem->feaLoad[i].loadType == ThermalExternal) continue;
7147 if (feaProblem->feaLoad[i].loadType == Gravity) continue;
7148
7149 status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex);
7150
7151 if (status == CAPS_NOTFOUND-303) {
7152 printf("\tName %s not found in attribute map of capsLoads!!!!\n", groupName[groupIndex]);
7153 continue;
7154
7155 } else if (status != CAPS_SUCCESS0) {
7156
7157 (void) string_freeArray(numGroupName, &groupName);
7158 return status;
7159 }
7160
7161 //{UnknownLoad, GridForce, GridMoment, Gravity, Pressure, Rotational, Thermal}
7162 if (feaProblem->feaLoad[i].loadType == GridForce ||
7163 feaProblem->feaLoad[i].loadType == GridMoment ||
7164 feaProblem->feaLoad[i].loadType == Rotational ||
7165 feaProblem->feaLoad[i].loadType == Thermal) {
7166
7167 // Now lets loop through the grid to see how many grid points have the attrIndex
7168 for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) {
7169
7170 if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) {
7171 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData;
7172 } else {
7173 continue;
7174 }
7175
7176 if (feaData->loadIndex == attrIndex) {
7177
7178 feaProblem->feaLoad[i].numGridID += 1;
7179
7180 // Allocate/Re-allocate grid ID array
7181 if (feaProblem->feaLoad[i].numGridID == 1) {
7182
7183 feaProblem->feaLoad[i].gridIDSet = (int *) EG_alloc(feaProblem->feaLoad[i].numGridID*sizeof(int));
7184
7185 } else {
7186
7187 feaProblem->feaLoad[i].gridIDSet = (int *) EG_reall(feaProblem->feaLoad[i].gridIDSet,
7188 feaProblem->feaLoad[i].numGridID*sizeof(int));
7189 }
7190
7191 if (feaProblem->feaLoad[i].gridIDSet == NULL((void*)0)) {
7192 status = string_freeArray(numGroupName, &groupName);
7193 if (status == CAPS_SUCCESS0) return status;
7194
7195 return EGADS_MALLOC-4;
7196 }
7197
7198 // Set grid ID value -> 1 bias
7199 feaProblem->feaLoad[i].gridIDSet[feaProblem->feaLoad[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID;
7200
7201 //printf("GroupName = %s %d\n", groupName[groupIndex], feaProblem->feaMesh.node[nodeIndex].nodeID);
7202
7203 }
7204 }
7205
7206 } else if (feaProblem->feaLoad[i].loadType == LineForce ||
7207 feaProblem->feaLoad[i].loadType == LineMoment ) {
7208
7209 for (elementIndex = 0; elementIndex < feaProblem->feaMesh.numElement; elementIndex++) {
7210
7211 if (feaProblem->feaMesh.element[elementIndex].elementType != Line) {
7212 continue;
7213 }
7214
7215 if (feaProblem->feaMesh.element[elementIndex].analysisType == MeshStructure) {
7216 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.element[elementIndex].analysisData;
7217 } else {
7218 continue;
7219 }
7220
7221 if (feaData->loadIndex == attrIndex) {
7222
7223 feaProblem->feaLoad[i].numElementID += 1;
7224
7225 feaProblem->feaLoad[i].elementIDSet = (int *) EG_reall(feaProblem->feaLoad[i].elementIDSet,
7226 feaProblem->feaLoad[i].numElementID*sizeof(int));
7227
7228 if (feaProblem->feaLoad[i].elementIDSet == NULL((void*)0)) {
7229 string_freeArray(numGroupName, &groupName);
7230 return EGADS_MALLOC-4;
7231 }
7232
7233 // Set element ID value -> 1 bias
7234 feaProblem->feaLoad[i].elementIDSet[feaProblem->feaLoad[i].numElementID-1] = feaProblem->feaMesh.element[elementIndex].elementID;
7235 }
7236 }
7237
7238 } else if (feaProblem->feaLoad[i].loadType == LineForce ||
7239 feaProblem->feaLoad[i].loadType == LineMoment ||
7240 feaProblem->feaLoad[i].loadType == Pressure ||
7241 feaProblem->feaLoad[i].loadType == PressureDistribute) {
7242
7243 // Now lets loop through the elements to see how many elements have the attrIndex
7244
7245 // Element types - CTRIA3, CTRIA3K, CQUAD4, CQUAD4K
7246 for (elementIndex = 0; elementIndex < feaProblem->feaMesh.numElement; elementIndex++) {
7247
7248 if (feaProblem->feaMesh.element[elementIndex].elementType != Triangle &&
7249 feaProblem->feaMesh.element[elementIndex].elementType != Triangle_6 &&
7250 feaProblem->feaMesh.element[elementIndex].elementType != Quadrilateral &&
7251 feaProblem->feaMesh.element[elementIndex].elementType != Quadrilateral_8) {
7252 continue;
7253 }
7254
7255 if (feaProblem->feaMesh.element[elementIndex].analysisType == MeshStructure) {
7256 feaData = (feaMeshDataStruct *) feaProblem->feaMesh.element[elementIndex].analysisData;
7257 } else {
7258 continue;
7259 }
7260
7261 if (feaData->loadIndex == attrIndex) {
7262
7263 feaProblem->feaLoad[i].numElementID += 1;
7264
7265 // Allocate/Re-allocate element ID array
7266 if (feaProblem->feaLoad[i].numElementID == 1) {
7267
7268 feaProblem->feaLoad[i].elementIDSet = (int *) EG_alloc(feaProblem->feaLoad[i].numElementID*sizeof(int));
7269
7270 } else {
7271
7272 feaProblem->feaLoad[i].elementIDSet = (int *) EG_reall(feaProblem->feaLoad[i].elementIDSet,
7273 feaProblem->feaLoad[i].numElementID*sizeof(int));
7274 }
7275
7276 if (feaProblem->feaLoad[i].elementIDSet == NULL((void*)0)) {
7277 string_freeArray(numGroupName, &groupName);
7278 return EGADS_MALLOC-4;
7279 }
7280
7281 // Set element ID value -> 1 bias
7282 feaProblem->feaLoad[i].elementIDSet[feaProblem->feaLoad[i].numElementID-1] = feaProblem->feaMesh.element[elementIndex].elementID;
7283 }
7284 }
7285
7286 }
7287 } // End attr search loop
7288
7289 status = string_freeArray(numGroupName, &groupName);
7290 if (status != CAPS_SUCCESS0) return status;
7291 groupName = NULL((void*)0);
7292
7293 // Free keyValue (just in case)
7294 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
7295
7296 //Fill up load properties
7297
7298 /*! \page feaLoad
7299 *
7300 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7301 * <ul>
7302 * <li> <B>loadScaleFactor = 1.0 </B> </li> <br>
7303 * Scale factor to use when combining loads.
7304 * </ul>
7305 * \endif
7306 */
7307 keyWord = "loadScaleFactor";
7308 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7309 if (status == CAPS_SUCCESS0) {
7310
7311 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].loadScaleFactor);
7312 if (keyValue != NULL((void*)0)) {
7313 EG_free(keyValue);
7314 keyValue = NULL((void*)0);
7315 }
7316 if (status != CAPS_SUCCESS0) return status;
7317 }
7318
7319 /*! \page feaLoad
7320 *
7321 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS)
7322 * <ul>
7323 * <li> <B>forceScaleFactor = 0.0 </B> </li> <br>
7324 * Overall scale factor for the force for a "GridForce" load.
7325 * </ul>
7326 * \endif
7327 */
7328 keyWord = "forceScaleFactor";
7329 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7330 if (status == CAPS_SUCCESS0) {
7331
7332 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].forceScaleFactor);
7333 if (keyValue != NULL((void*)0)) {
7334 EG_free(keyValue);
7335 keyValue = NULL((void*)0);
7336 }
7337 if (status != CAPS_SUCCESS0) return status;
7338 }
7339
7340 /*! \page feaLoad
7341 *
7342 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS)
7343 * <ul>
7344 * <li> <B>directionVector = [0.0, 0.0, 0.0] </B> </li> <br>
7345 * X-, y-, and z- components of the force vector for a "GridForce", "GridMoment", or "Gravity" load.
7346 * </ul>
7347 * \elseif ABAQUS
7348 * <ul>
7349 * <li> <B>directionVector = [0.0, 0.0, 0.0] </B> </li> <br>
7350 * X-, y-, and z- components of the force vector for a "Gravity" load.
7351 * </ul>
7352 * \endif
7353 *
7354 */
7355 keyWord = "directionVector";
7356 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7357 if (status == CAPS_SUCCESS0) {
7358
7359 status = string_toDoubleArray(keyValue,
7360 (int) sizeof(feaProblem->feaLoad[i].directionVector)/sizeof(double),
7361 feaProblem->feaLoad[i].directionVector);
7362 if (keyValue != NULL((void*)0)) {
7363 EG_free(keyValue);
7364 keyValue = NULL((void*)0);
7365 }
7366 if (status != CAPS_SUCCESS0) return status;
7367 }
7368
7369 /*! \page feaLoad
7370 *
7371 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS)
7372 * <ul>
7373 * <li> <B>momentScaleFactor = 0.0 </B> </li> <br>
7374 * Overall scale factor for the moment for a "GridMoment" load.
7375 * </ul>
7376 * \endif
7377 *
7378 */
7379 keyWord = "momentScaleFactor";
7380 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7381 if (status == CAPS_SUCCESS0) {
7382
7383 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].momentScaleFactor);
7384 if (keyValue != NULL((void*)0)) {
7385 EG_free(keyValue);
7386 keyValue = NULL((void*)0);
7387 }
7388 if (status != CAPS_SUCCESS0) return status;
7389 }
7390
7391 /*! \page feaLoad
7392 *
7393 * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7394 * <ul>
7395 * <li> <B>gravityAcceleration = 0.0 </B> </li> <br>
7396 * Acceleration value for a "Gravity" load.
7397 * </ul>
7398 * \endif
7399 */
7400 keyWord = "gravityAcceleration";
7401 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7402 if (status == CAPS_SUCCESS0) {
7403
7404 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].gravityAcceleration);
7405 if (keyValue != NULL((void*)0)) {
7406 EG_free(keyValue);
7407 keyValue = NULL((void*)0);
7408 }
7409 if (status != CAPS_SUCCESS0) return status;
7410 }
7411
7412 /*! \page feaLoad
7413 *
7414 * \if MYSTRAN
7415 * <ul>
7416 * <li> <B>pressureForce = 0.0 </B> </li> <br>
7417 * Uniform pressure force for a "Pressure" load (only applicable to 2D elements).
7418 * </ul>
7419 * \elseif (NASTRAN || HSM || ASTROS || ABAQUS || TACS)
7420 * <ul>
7421 * <li> <B>pressureForce = 0.0 </B> </li> <br>
7422 * Uniform pressure force for a "Pressure" load.
7423 * </ul>
7424 * \endif
7425 */
7426 keyWord = "pressureForce";
7427 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7428 if (status == CAPS_SUCCESS0) {
7429
7430 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].pressureForce);
7431 if (keyValue != NULL((void*)0)) {
7432 EG_free(keyValue);
7433 keyValue = NULL((void*)0);
7434 }
7435 if (status != CAPS_SUCCESS0) return status;
7436 }
7437
7438 /*! \page feaLoad
7439 *
7440 * \if MYSTRAN
7441 * <ul>
7442 * <li> <B>pressureDistributeForce = [0.0, 0.0, 0.0, 0.0] </B> </li> <br>
7443 * Distributed pressure force for a "PressureDistribute" load (only applicable to 2D elements). The four values
7444 * correspond to the 4 (quadrilateral elements) or 3 (triangle elements) node locations.
7445 * </ul>
7446 * \elseif (NASTRAN || HSM || ASTROS || TACS)
7447 * <ul>
7448 * <li> <B>pressureDistributeForce = [0.0, 0.0, 0.0, 0.0] </B> </li> <br>
7449 * Distributed pressure force for a "PressureDistribute" load. The four values
7450 * correspond to the 4 (quadrilateral elements) or 3 (triangle elements) node locations.
7451 * </ul>
7452 * \endif
7453 */
7454 keyWord = "pressureDistributeForce";
7455 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7456 if (status == CAPS_SUCCESS0) {
7457
7458 status = string_toDoubleArray(keyValue,
7459 (int) sizeof(feaProblem->feaLoad[i].pressureDistributeForce)/sizeof(double),
7460 feaProblem->feaLoad[i].pressureDistributeForce);
7461 if (keyValue != NULL((void*)0)) {
7462 EG_free(keyValue);
7463 keyValue = NULL((void*)0);
7464 }
7465 if (status != CAPS_SUCCESS0) return status;
7466 }
7467
7468 /*! \page feaLoad
7469 *
7470 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7471 * <ul>
7472 * <li> <B>angularVelScaleFactor = 0.0 </B> </li> <br>
7473 * An overall scale factor for the angular velocity in revolutions per unit time for a "Rotational" load.
7474 * </ul>
7475 * \elseif HSM
7476 * <ul>
7477 * <li> <B>angularVelScaleFactor = 0.0 </B> </li> <br>
7478 * An overall scale factor for the angular velocity in revolutions per unit time for a "Rotational" load - applied in a global sense.
7479 * </ul>
7480 * \endif
7481 */
7482 keyWord = "angularVelScaleFactor";
7483 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7484 if (status == CAPS_SUCCESS0) {
7485
7486 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].angularVelScaleFactor);
7487 if (keyValue != NULL((void*)0)) {
7488 EG_free(keyValue);
7489 keyValue = NULL((void*)0);
7490 }
7491 if (status != CAPS_SUCCESS0) return status;
7492 }
7493
7494 /*! \page feaLoad
7495 *
7496 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7497 * <ul>
7498 * <li> <B>angularAccScaleFactor = 0.0 </B> </li> <br>
7499 * An overall scale factor for the angular acceleration in revolutions per unit time squared for a "Rotational" load.
7500 * </ul>
7501 * \elseif HSM
7502 * <ul>
7503 * <li> <B>angularAccScaleFactor = 0.0 </B> </li> <br>
7504 * An overall scale factor for the angular acceleration in revolutions per unit time squared for a "Rotational" load - applied in a global sense.
7505 * </ul>
7506 * \endif
7507 */
7508 keyWord = "angularAccScaleFactor";
7509 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7510 if (status == CAPS_SUCCESS0) {
7511
7512 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].angularAccScaleFactor);
7513 if (keyValue != NULL((void*)0)) {
7514 EG_free(keyValue);
7515 keyValue = NULL((void*)0);
7516 }
7517 if (status != CAPS_SUCCESS0) return status;
7518 }
7519
7520 /*! \page feaLoad
7521 *
7522 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7523 * <ul>
7524 * <li> <B>coordinateSystem = "(no default)" </B> </li> <br>
7525 * Name of coordinate system in which defined force components are in reference to. If no value
7526 * is provided the global system is assumed.
7527 * </ul>
7528 * \endif
7529 *
7530 */
7531 keyWord = "coordinateSystem";
7532 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7533 if (status == CAPS_SUCCESS0) {
7534
7535 tempString = string_removeQuotation(keyValue);
7536
7537 for (attrIndex = 0; attrIndex < feaProblem->numCoordSystem; attrIndex++) {
7538
7539 if (strcasecmp(tempString, feaProblem->feaCoordSystem[attrIndex].name) == 0) {
7540 feaProblem->feaLoad[i].coordSystemID = feaProblem->feaCoordSystem[attrIndex].coordSystemID;
7541 break;
7542 }
7543 }
7544
7545 if (feaProblem->feaLoad[i].coordSystemID == 0) {
7546 printf("\tCoordinate system %s not found, defaulting to global system!!", keyValue);
7547 }
7548
7549 if (keyValue != NULL((void*)0)) {
7550 EG_free(keyValue);
7551 keyValue = NULL((void*)0);
7552 }
7553
7554 if (tempString != NULL((void*)0)) {
7555 EG_free(tempString);
7556 tempString = NULL((void*)0);
7557 }
7558 }
7559
7560
7561 /*! \page feaLoad
7562 *
7563 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7564 * <ul>
7565 * <li> <B>temperature = 0.0 </B> </li> <br>
7566 * Temperature at a given node for a "Temperature" load.
7567 * </ul>
7568 * \endif
7569 */
7570 keyWord = "temperature";
7571 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7572 if (status == CAPS_SUCCESS0) {
7573
7574 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].temperature);
7575 if (keyValue != NULL((void*)0)) {
7576 EG_free(keyValue);
7577 keyValue = NULL((void*)0);
7578 }
7579 if (status != CAPS_SUCCESS0) return status;
7580 }
7581
7582 /*! \page feaLoad
7583 *
7584 * \if (MYSTRAN || NASTRAN || ASTROS || TACS)
7585 * <ul>
7586 * <li> <B>temperatureDefault = 0.0 </B> </li> <br>
7587 * Default temperature at a node not explicitly being used for a "Temperature" load.
7588 * </ul>
7589 * \endif
7590 */
7591 keyWord = "temperatureDefault";
7592 status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue);
7593 if (status == CAPS_SUCCESS0) {
7594
7595 status = string_toDouble(keyValue, &feaProblem->feaLoad[i].temperatureDefault);
7596 if (keyValue != NULL((void*)0)) {
7597 EG_free(keyValue);
7598 keyValue = NULL((void*)0);
7599 }
7600 if (status != CAPS_SUCCESS0) return status;
7601 }
7602
7603
7604 } else { // if not a JSON string search
7605
7606 /*! \page feaLoad
7607 * \section keyStringLoad Single Value String
7608 *
7609 * If "Value" is a string, the string value may correspond to an entry in a predefined load lookup
7610 * table. NOT YET IMPLEMENTED!!!!
7611 *
7612 */
7613
7614 // Call some look up table maybe?
7615 printf("\tError: Load tuple value is expected to be a JSON string\n");
7616 return CAPS_BADVALUE-311;
7617 }
7618 }
7619
7620 /// Free keyValue and tempString (just in case)
7621 if (keyValue != NULL((void*)0)) EG_free(keyValue);
7622
7623 if (tempString != NULL((void*)0)) EG_free(tempString);
7624
7625 printf("\tDone getting FEA loads\n");
7626
7627 return CAPS_SUCCESS0;
7628}
7629
7630// Get the analysis properties from a capsTuple
7631int fea_getAnalysis(int numAnalysisTuple,
7632 capsTuple analysisTuple[],
7633 feaProblemStruct *feaProblem) {
7634
7635 /*! \page feaAnalysis FEA Analysis
7636 * Structure for the analysis tuple = (`Analysis Name', `Value').
7637 * 'Analysis Name' defines the reference name for the analysis being specified.
7638 * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringAnalysis) or a single string keyword
7639 * (see Section \ref keyStringAnalysis).
7640 */
7641
7642 int status; //Function return
7643
7644 int i, j, groupIndex, attrIndex; // Indexing
7645
7646
7647 char *keyValue = NULL((void*)0);
7648 char *keyWord = NULL((void*)0);
7649
7650 char *tempString = NULL((void*)0);
7651
7652 char **groupName = NULL((void*)0);
7653 int numGroupName = 0;
7654
7655 int tempInt=0; // Temporary integer
7656
7657 // Destroy our analysis structures coming in if aren't 0 and NULL already
7658 if (feaProblem->feaAnalysis != NULL((void*)0)) {
7659 for (i = 0; i < feaProblem->numAnalysis; i++) {
7660 status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
7661 if (status != CAPS_SUCCESS0) return status;
7662 }
7663 }
7664
7665 if (feaProblem->feaAnalysis != NULL((void*)0)) EG_free(feaProblem->feaAnalysis);
7666 feaProblem->feaAnalysis = NULL((void*)0);
7667 feaProblem->numAnalysis = 0;
7668
7669 printf("\nGetting FEA analyses.......\n");
7670
7671 feaProblem->numAnalysis = numAnalysisTuple;
7672
7673 printf("\tNumber of analyses - %d\n", feaProblem->numAnalysis);
7674
7675 if (feaProblem->numAnalysis > 0) {
7676 feaProblem->feaAnalysis = (feaAnalysisStruct *) EG_alloc(feaProblem->numAnalysis * sizeof(feaAnalysisStruct));
7677 } else {
7678 printf("\tNumber of analysis values in input tuple is 0\n");
7679 return CAPS_NOTFOUND-303;
7680 }
7681
7682 for (i = 0; i < feaProblem->numAnalysis; i++) {
7683 status = initiate_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
7684 if (status != CAPS_SUCCESS0) return status;
7685 }
7686
7687 for (i = 0; i < feaProblem->numAnalysis; i++) {
7688
7689 printf("\tAnalysis name - %s\n", analysisTuple[i].name);
7690
7691 feaProblem->feaAnalysis[i].name = (char *) EG_alloc(((strlen(analysisTuple[i].name)) + 1)*sizeof(char));
7692 if (feaProblem->feaAnalysis[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
7693
7694 memcpy(feaProblem->feaAnalysis[i].name, analysisTuple[i].name, strlen(analysisTuple[i].name)*sizeof(char));
7695 feaProblem->feaAnalysis[i].name[strlen(analysisTuple[i].name)] = '\0';
7696
7697 feaProblem->feaAnalysis[i].analysisID = i + 1;
7698
7699 // Do we have a json string?
7700 if (strncmp(analysisTuple[i].value, "{", 1) == 0) {
7701 //printf("JSON String - %s\n", analysisTuple[i].value);
7702
7703 /*! \page feaAnalysis
7704 * \section jsonStringAnalysis JSON String Dictionary
7705 *
7706 * If "Value" is JSON string dictionary
7707 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
7708 * (e.g. "Value" = {"numDesiredEigenvalue": 10, "eigenNormaliztion": "MASS", "numEstEigenvalue": 1,
7709 * "extractionMethod": "GIV", "frequencyRange": [0, 10000]})
7710 * \endif
7711 * the following keywords ( = default values) may be used:
7712 *
7713 * \if MYSTRAN
7714 * <ul>
7715 * <li> <B>analysisType = "Modal"</B> </li> <br>
7716 * Type of load. Options: "Modal", "Static".
7717 * </ul>
7718 * \elseif (NASTRAN || ASTROS)
7719 * <ul>
7720 * <li> <B>analysisType = "Modal"</B> </li> <br>
7721 * Type of load. Options: "Modal", "Static", "AeroelasticTrim", "AeroelasticFlutter"
7722 * Note: "AeroelasticStatic" is still supported but refers to "AeroelasticTrim"
7723 * Note: "Optimization" and "StaticOpt" are not valid - Optimization is initialized by the Analysis_Type AIM Input
7724 * </ul>
7725 * \elseif ABAQUS
7726 * <ul>
7727 * <li> <B>analysisType = "Modal"</B> </li> <br>
7728 * Type of load. Options: "Modal", "Static"
7729 * </ul>
7730 * \endif
7731 *
7732 */
7733 // Get analysis Type
7734 keyWord = "analysisType";
7735 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7736 if (status == CAPS_SUCCESS0) {
7737
7738 //{UnknownAnalysis, Modal, Static}
7739 if (strcasecmp(keyValue, "\"Modal\"") == 0) feaProblem->feaAnalysis[i].analysisType = Modal;
7740 else if (strcasecmp(keyValue, "\"Static\"") == 0) feaProblem->feaAnalysis[i].analysisType = Static;
7741 else if (strcasecmp(keyValue, "\"StaticOpt\"") == 0) feaProblem->feaAnalysis[i].analysisType = Optimization;
7742 else if (strcasecmp(keyValue, "\"Optimization\"") == 0) feaProblem->feaAnalysis[i].analysisType = Optimization;
7743 else if (strcasecmp(keyValue, "\"AeroelasticTrim\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticTrim;
7744 else if (strcasecmp(keyValue, "\"AeroelasticStatic\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticTrim;
7745 else if (strcasecmp(keyValue, "\"AeroelasticFlutter\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticFlutter;
7746 else {
7747
7748 printf("\tUnrecognized \"%s\" specified (%s) for Analysis tuple %s, defaulting to \"Modal\"\n", keyWord,
7749 keyValue,
7750 analysisTuple[i].name);
7751 feaProblem->feaAnalysis[i].analysisType = Modal;
7752 }
7753
7754 } else {
7755
7756 printf("\tNo \"%s\" specified for Analysis tuple %s, defaulting to \"Modal\"\n", keyWord, analysisTuple[i].name);
7757
7758 feaProblem->feaAnalysis[i].analysisType = Modal;
7759 }
7760 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
7761
7762 // Get loads to be applied for a given analysis
7763
7764 /*! \page feaAnalysis
7765 *
7766 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
7767 * <ul>
7768 * <li> <B>analysisLoad = "(no default)"</B> </li> <br>
7769 * Single or list of "Load Name"s defined in \ref feaLoad in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...].
7770 * </ul>
7771 * \endif
7772 */
7773 keyWord = "analysisLoad";
7774 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7775 if (status == CAPS_SUCCESS0) {
7776
7777 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7778 if (keyValue != NULL((void*)0)) {
7779 EG_free(keyValue);
7780 keyValue = NULL((void*)0);
7781 }
7782
7783 if (status != CAPS_SUCCESS0) return status;
7784
7785 feaProblem->feaAnalysis[i].numLoad = 0;
7786 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7787
7788 for (attrIndex = 0; attrIndex < feaProblem->numLoad; attrIndex++) {
7789
7790 if (strcasecmp(feaProblem->feaLoad[attrIndex].name, groupName[groupIndex]) == 0) {
7791
7792// if (feaProblem->feaLoad[attrIndex].loadType == Thermal) {
7793// printf("Combining Thermal loads in a subcase isn't supported yet!\n");
7794// status = string_freeArray(numGroupName, &groupName);
7795// if (status != CAPS_SUCCESS) return status;
7796// groupName = NULL;
7797// return CAPS_BADVALUE;
7798// }
7799
7800 feaProblem->feaAnalysis[i].numLoad += 1;
7801
7802 if (feaProblem->feaAnalysis[i].numLoad == 1) {
7803
7804 feaProblem->feaAnalysis[i].loadSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numLoad *sizeof(int));
7805
7806 } else {
7807
7808 feaProblem->feaAnalysis[i].loadSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].loadSetID,
7809 feaProblem->feaAnalysis[i].numLoad *sizeof(int));
7810 }
7811
7812 if (feaProblem->feaAnalysis[i].loadSetID == NULL((void*)0)) {
7813 status = string_freeArray(numGroupName, &groupName);
7814 if (status != CAPS_SUCCESS0) return status;
7815 groupName = NULL((void*)0);
7816 return EGADS_MALLOC-4;
7817 }
7818
7819 feaProblem->feaAnalysis[i].loadSetID[feaProblem->feaAnalysis[i].numLoad-1] = feaProblem->feaLoad[attrIndex].loadID;
7820 break;
7821 }
7822 }
7823
7824 if (feaProblem->feaAnalysis[i].numLoad != groupIndex+1) {
7825
7826 printf("\tWarning: Analysis load name, %s, not found in feaLoad structure\n", groupName[groupIndex]);
7827
7828 }
7829 }
7830
7831 status = string_freeArray(numGroupName, &groupName);
7832 if (status != CAPS_SUCCESS0) return status;
7833 groupName = NULL((void*)0);
7834
7835 }
7836
7837 // Get constraints to be applied for a given analysis
7838 /*! \page feaAnalysis
7839 *
7840 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
7841 * <ul>
7842 * <li> <B>analysisConstraint = "(no default)"</B> </li> <br>
7843 * Single or list of "Constraint Name"s defined in \ref feaConstraint in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...].
7844 * </ul>
7845 * \endif
7846 */
7847 keyWord = "analysisConstraint";
7848 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7849 if (status == CAPS_SUCCESS0) {
7850
7851 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7852 if (keyValue != NULL((void*)0)) {
7853 EG_free(keyValue);
7854 keyValue = NULL((void*)0);
7855 }
7856
7857 if (status != CAPS_SUCCESS0) return status;
7858
7859 feaProblem->feaAnalysis[i].numConstraint = 0;
7860 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7861
7862 for (attrIndex = 0; attrIndex < feaProblem->numConstraint; attrIndex++) {
7863
7864 if (strcasecmp(feaProblem->feaConstraint[attrIndex].name, groupName[groupIndex]) == 0) {
7865
7866 feaProblem->feaAnalysis[i].numConstraint += 1;
7867
7868 if (feaProblem->feaAnalysis[i].numConstraint == 1) {
7869
7870 feaProblem->feaAnalysis[i].constraintSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numConstraint *sizeof(int));
7871
7872 } else {
7873
7874 feaProblem->feaAnalysis[i].constraintSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].constraintSetID,
7875 feaProblem->feaAnalysis[i].numConstraint *sizeof(int));
7876 }
7877
7878 if (feaProblem->feaAnalysis[i].constraintSetID == NULL((void*)0)) {
7879 status = string_freeArray(numGroupName, &groupName);
7880 if (status != CAPS_SUCCESS0) return status;
7881 groupName = NULL((void*)0);
7882 return EGADS_MALLOC-4;
7883 }
7884
7885 feaProblem->feaAnalysis[i].constraintSetID[feaProblem->feaAnalysis[i].numConstraint-1] = feaProblem->feaConstraint[attrIndex].constraintID;
7886 break;
7887 }
7888 }
7889
7890 if (feaProblem->feaAnalysis[i].numConstraint != groupIndex+1) {
7891
7892 printf("\tWarning: Analysis constraint name, %s, not found in feaConstraint structure\n", groupName[groupIndex]);
7893
7894 }
7895 }
7896
7897 status = string_freeArray(numGroupName, &groupName);
7898 if (status != CAPS_SUCCESS0) return status;
7899 groupName = NULL((void*)0);
7900
7901 }
7902
7903 // Get supports to be applied for a given analysis
7904 /*! \page feaAnalysis
7905 *
7906 * \if (MYSTRAN || NASTRAN || ASTROS)
7907 * <ul>
7908 * <li> <B>analysisSupport = "(no default)"</B> </li> <br>
7909 * Single or list of "Support Name"s defined in \ref feaSupport in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...].
7910 * </ul>
7911 * \endif
7912 *
7913 */
7914 keyWord = "analysisSupport";
7915 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7916 if (status == CAPS_SUCCESS0) {
7917
7918 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7919 if (keyValue != NULL((void*)0)) {
7920 EG_free(keyValue);
7921 keyValue = NULL((void*)0);
7922 }
7923
7924 if (status != CAPS_SUCCESS0) return status;
7925
7926 feaProblem->feaAnalysis[i].numSupport = 0;
7927 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7928
7929 for (attrIndex = 0; attrIndex < feaProblem->numSupport; attrIndex++) {
7930
7931 if (strcasecmp(feaProblem->feaSupport[attrIndex].name, groupName[groupIndex]) == 0) {
7932
7933 feaProblem->feaAnalysis[i].numSupport += 1;
7934
7935 if (feaProblem->feaAnalysis[i].numSupport == 1) {
7936
7937 feaProblem->feaAnalysis[i].supportSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numSupport *sizeof(int));
7938
7939 } else {
7940
7941 feaProblem->feaAnalysis[i].supportSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].supportSetID,
7942 feaProblem->feaAnalysis[i].numSupport *sizeof(int));
7943 }
7944
7945 if (feaProblem->feaAnalysis[i].supportSetID == NULL((void*)0)) {
7946 status = string_freeArray(numGroupName, &groupName);
7947 if (status != CAPS_SUCCESS0) return status;
7948 groupName = NULL((void*)0);
7949 return EGADS_MALLOC-4;
7950 }
7951
7952 feaProblem->feaAnalysis[i].supportSetID[feaProblem->feaAnalysis[i].numSupport-1] = feaProblem->feaSupport[attrIndex].supportID;
7953 break;
7954 }
7955 }
7956
7957 if (feaProblem->feaAnalysis[i].numSupport != groupIndex+1) {
7958
7959 printf("\tWarning: Analysis support name, %s, not found in feaSupport structure\n", groupName[groupIndex]);
7960
7961 }
7962 }
7963
7964 status = string_freeArray(numGroupName, &groupName);
7965 if (status != CAPS_SUCCESS0) return status;
7966 groupName = NULL((void*)0);
7967
7968 }
7969
7970 // Get design constraints to be applied for a given analysis
7971
7972 /*! \page feaAnalysis
7973 *
7974 * \if (NASTRAN || ASTROS)
7975 * <ul>
7976 * <li> <B>analysisDesignConstraint = "(no default)"</B> </li> <br>
7977 * 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",...].
7978 * </ul>
7979 * \endif
7980 */
7981 keyWord = "analysisDesignConstraint";
7982 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
7983 if (status == CAPS_SUCCESS0) {
7984
7985 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
7986 if (keyValue != NULL((void*)0)) {
7987 EG_free(keyValue);
7988 keyValue = NULL((void*)0);
7989 }
7990
7991 if (status != CAPS_SUCCESS0) return status;
7992
7993 feaProblem->feaAnalysis[i].numDesignConstraint = 0;
7994 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
7995
7996 for (attrIndex = 0; attrIndex < feaProblem->numDesignConstraint; attrIndex++) {
7997
7998 if (strcasecmp(feaProblem->feaDesignConstraint[attrIndex].name, groupName[groupIndex]) == 0) {
7999
8000 feaProblem->feaAnalysis[i].numDesignConstraint += 1;
8001
8002 if (feaProblem->feaAnalysis[i].numDesignConstraint == 1) {
8003
8004 feaProblem->feaAnalysis[i].designConstraintSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numDesignConstraint *sizeof(int));
8005
8006 } else {
8007
8008 feaProblem->feaAnalysis[i].designConstraintSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].designConstraintSetID,
8009 feaProblem->feaAnalysis[i].numDesignConstraint *sizeof(int));
8010 }
8011
8012 if (feaProblem->feaAnalysis[i].designConstraintSetID == NULL((void*)0)) {
8013 status = string_freeArray(numGroupName, &groupName);
8014 if (status != CAPS_SUCCESS0) return status;
8015 groupName = NULL((void*)0);
8016 return EGADS_MALLOC-4;
8017 }
8018
8019 feaProblem->feaAnalysis[i].designConstraintSetID[feaProblem->feaAnalysis[i].numDesignConstraint-1] = feaProblem->feaDesignConstraint[attrIndex].designConstraintID;
8020 break;
8021 }
8022 }
8023
8024 if (feaProblem->feaAnalysis[i].numDesignConstraint != groupIndex+1) {
8025
8026 printf("\tWarning: Analysis design constraint name, %s, not found in feaDesignConstraint structure\n", groupName[groupIndex]);
8027
8028 }
8029 }
8030
8031 status = string_freeArray(numGroupName, &groupName);
8032 if (status != CAPS_SUCCESS0) {
8033 if (tempString != NULL((void*)0)) EG_free(tempString);
8034
8035 return status;
8036 }
8037 groupName = NULL((void*)0);
8038
8039 }
8040
8041 //Fill up analysis properties
8042 /*! \page feaAnalysis
8043 *
8044 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
8045 * <ul>
8046 * <li> <B>extractionMethod = "(no default)"</B> </li> <br>
8047 * Extraction method for modal analysis.
8048 * </ul>
8049 * \endif
8050 */
8051 keyWord = "extractionMethod";
8052 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8053 if (status == CAPS_SUCCESS0) {
8054
8055 tempString = string_removeQuotation(keyValue);
8056
8057 if (keyValue != NULL((void*)0)) {
8058 EG_free(keyValue);
8059 keyValue = NULL((void*)0);
8060 }
8061
8062 feaProblem->feaAnalysis[i].extractionMethod = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8063 if(feaProblem->feaAnalysis[i].extractionMethod == NULL((void*)0)) {
8064 if (tempString != NULL((void*)0)) EG_free(tempString);
8065 return EGADS_MALLOC-4;
8066 }
8067
8068 memcpy(feaProblem->feaAnalysis[i].extractionMethod, tempString, strlen(tempString)*sizeof(char));
8069 feaProblem->feaAnalysis[i].extractionMethod[strlen(tempString)] = '\0';
8070
8071 if (tempString != NULL((void*)0)) {
8072 EG_free(tempString);
8073 tempString = NULL((void*)0);
8074 }
8075 }
8076
8077
8078 /*! \page feaAnalysis
8079 *
8080 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
8081 * <ul>
8082 * <li> <B>frequencyRange = [0.0, 0.0] </B> </li> <br>
8083 * Frequency range of interest for modal analysis.
8084 * </ul>
8085 * \endif
8086 */
8087 keyWord = "frequencyRange";
8088 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8089 if (status == CAPS_SUCCESS0) {
8090
8091 status = string_toDoubleArray(keyValue,
8092 (int) sizeof(feaProblem->feaAnalysis[i].frequencyRange)/sizeof(double),
8093 feaProblem->feaAnalysis[i].frequencyRange);
8094 if (keyValue != NULL((void*)0)) {
8095 EG_free(keyValue);
8096 keyValue = NULL((void*)0);
8097 }
8098 if (status != CAPS_SUCCESS0) return status;
8099 }
8100
8101 /*! \page feaAnalysis
8102 *
8103 * \if (MYSTRAN || NASTRAN || ASTROS)
8104 * <ul>
8105 * <li> <B>numEstEigenvalue = 0 </B> </li> <br>
8106 * Number of estimated eigenvalues for modal analysis.
8107 * </ul>
8108 * \endif
8109 */
8110 keyWord = "numEstEigenvalue";
8111 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8112 if (status == CAPS_SUCCESS0) {
8113
8114 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].numEstEigenvalue);
8115 if (keyValue != NULL((void*)0)) {
8116 EG_free(keyValue);
8117 keyValue = NULL((void*)0);
8118 }
8119 if (status != CAPS_SUCCESS0) return status;
8120 }
8121
8122 /*! \page feaAnalysis
8123 *
8124 * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS)
8125 * <ul>
8126 * <li> <B>numDesiredEigenvalue = 0</B> </li> <br>
8127 * Number of desired eigenvalues for modal analysis.
8128 * </ul>
8129 * \endif
8130 *
8131 */
8132 keyWord = "numDesiredEigenvalue";
8133 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8134 if (status == CAPS_SUCCESS0) {
8135
8136 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].numDesiredEigenvalue);
8137 if (keyValue != NULL((void*)0)) {
8138 EG_free(keyValue);
8139 keyValue = NULL((void*)0);
8140 }
8141 if (status != CAPS_SUCCESS0) return status;
8142 }
8143
8144 /*! \page feaAnalysis
8145 *
8146 * \if (MYSTRAN || NASTRAN || ASTROS)
8147 * <ul>
8148 * <li> <B>eigenNormaliztion = "(no default)"</B> </li> <br>
8149 * Method of eigenvector renormalization. Options: "POINT", "MAX", "MASS"
8150 * </ul>
8151 * \elseif ABAQUS
8152 * <ul>
8153 * <li> <B>eigenNormaliztion = "(no default)"</B> </li> <br>
8154 * Method of eigenvector renormalization. Options: "DISPLACEMENT", "MASS"
8155 * </ul>
8156 * \endif
8157 */
8158 keyWord = "eigenNormaliztion";
8159 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8160 if (status == CAPS_SUCCESS0) {
8161
8162 tempString = string_removeQuotation(keyValue);
8163
8164 feaProblem->feaAnalysis[i].eigenNormaliztion = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8165 if(feaProblem->feaAnalysis[i].eigenNormaliztion == NULL((void*)0)) {
8166 if (tempString != NULL((void*)0)) EG_free(tempString);
8167
8168 return EGADS_MALLOC-4;
8169 }
8170
8171 memcpy(feaProblem->feaAnalysis[i].eigenNormaliztion, tempString, strlen(tempString)*sizeof(char));
8172 feaProblem->feaAnalysis[i].eigenNormaliztion[strlen(tempString)] = '\0';
8173
8174 if (keyValue != NULL((void*)0)) {
8175 EG_free(keyValue);
8176 keyValue = NULL((void*)0);
8177 }
8178 if (tempString != NULL((void*)0)) {
8179 EG_free(tempString);
8180 tempString = NULL((void*)0);
8181 }
8182 }
8183
8184 /*! \page feaAnalysis
8185 *
8186 * \if (MYSTRAN || NASTRAN || ASTROS)
8187 * <ul>
8188 * <li> <B>gridNormaliztion = 0 </B> </li> <br>
8189 * Grid point to be used in normalizing eigenvector to 1.0 when using eigenNormaliztion = "POINT"
8190 * </ul>
8191 * \endif
8192 */
8193 keyWord = "gridNormaliztion";
8194 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8195 if (status == CAPS_SUCCESS0) {
8196
8197 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].gridNormaliztion);
8198 if (keyValue != NULL((void*)0)) {
8199 EG_free(keyValue);
8200 keyValue = NULL((void*)0);
8201 }
8202 if (status != CAPS_SUCCESS0) return status;
8203 }
8204
8205 /*! \page feaAnalysis
8206 *
8207 * \if (MYSTRAN || NASTRAN || ASTROS)
8208 * <ul>
8209 * <li> <B>componentNormaliztion = 0</B> </li> <br>
8210 * Degree of freedom about "gridNormalization" to be used in normalizing eigenvector to 1.0
8211 * when using eigenNormaliztion = "POINT"
8212 * </ul>
8213 * \endif
8214 *
8215 */
8216 keyWord = "componentNormaliztion";
8217 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8218 if (status == CAPS_SUCCESS0) {
8219
8220 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].componentNormaliztion);
8221 if (keyValue != NULL((void*)0)) {
8222 EG_free(keyValue);
8223 keyValue = NULL((void*)0);
8224 }
8225 if (status != CAPS_SUCCESS0) return status;
8226 }
8227
8228 /*! \page feaAnalysis
8229 *
8230 * \if (MYSTRAN || NASTRAN)
8231 * <ul>
8232 * <li> <B>lanczosMode = 2</B> </li> <br>
8233 * Mode refers to the Lanczos mode type to be used in the solution. In mode 3 the mass matrix, Maa,must
8234 * be nonsingular whereas in mode 2 the matrix K aa - sigma*Maa must be nonsingular
8235 * </ul>
8236 * \endif
8237 */
8238 keyWord = "lanczosMode";
8239 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8240 if (status == CAPS_SUCCESS0) {
8241
8242 status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].lanczosMode);
8243 if (keyValue != NULL((void*)0)) {
8244 EG_free(keyValue);
8245 keyValue = NULL((void*)0);
8246 }
8247 if (status != CAPS_SUCCESS0) return status;
8248 }
8249
8250 /*! \page feaAnalysis
8251 *
8252 * \if (MYSTRAN || NASTRAN)
8253 * <ul>
8254 * <li> <B>lanczosType = "(no default)"</B> </li> <br>
8255 * Lanczos matrix type. Options: DPB, DGB.
8256 * </ul>
8257 * \endif
8258 */
8259 keyWord = "lanczosType";
8260 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8261 if (status == CAPS_SUCCESS0) {
8262
8263 tempString = string_removeQuotation(keyValue);
8264
8265 feaProblem->feaAnalysis[i].lanczosType = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8266 if(feaProblem->feaAnalysis[i].lanczosType == NULL((void*)0)) {
8267 if (tempString != NULL((void*)0)) EG_free(tempString);
8268
8269 return EGADS_MALLOC-4;
8270 }
8271
8272 memcpy(feaProblem->feaAnalysis[i].lanczosType, tempString, strlen(tempString)*sizeof(char));
8273 feaProblem->feaAnalysis[i].lanczosType[strlen(tempString)] = '\0';
8274
8275 if (keyValue != NULL((void*)0)) {
8276 EG_free(keyValue);
8277 keyValue = NULL((void*)0);
8278 }
8279
8280 if (tempString != NULL((void*)0)) {
8281 EG_free(tempString);
8282 tempString = NULL((void*)0);
8283 }
8284 }
8285
8286 /*! \page feaAnalysis
8287 *
8288 * \if (NASTRAN)
8289 * <ul>
8290 * <li> <B>machNumber = 0.0 or [0.0, ..., 0.0]</B> </li> <br>
8291 * Mach number used in trim analysis OR Mach numbers used in flutter analysis..
8292 * </ul>
8293 * \elseif (ASTROS)
8294 * <ul>
8295 * <li> <B>machNumber = 0.0 or [0.0, ..., 0.0]</B> </li> <br>
8296 * Mach number used in trim analysis OR Mach up to 6 values used in flutter analysis..
8297 * </ul>
8298 * \endif
8299 */
8300 keyWord = "machNumber";
8301 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8302 if (status == CAPS_SUCCESS0) {
8303
8304 status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numMachNumber, &feaProblem->feaAnalysis[i].machNumber);
8305 if (keyValue != NULL((void*)0)) {
8306 EG_free(keyValue);
8307 keyValue = NULL((void*)0);
8308 }
8309 if (status != CAPS_SUCCESS0) return status;
8310 }
8311
8312 /*! \page feaAnalysis
8313 *
8314 * \if (NASTRAN || ASTROS)
8315 * <ul>
8316 * <li> <B>dynamicPressure = 0.0</B> </li> <br>
8317 * Dynamic pressure used in trim analysis.
8318 * </ul>
8319 * \endif
8320 */
8321 keyWord = "dynamicPressure";
8322 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8323 if (status == CAPS_SUCCESS0) {
8324
8325 status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].dynamicPressure);
8326 if (keyValue != NULL((void*)0)) {
8327 EG_free(keyValue);
8328 keyValue = NULL((void*)0);
8329 }
8330 if (status != CAPS_SUCCESS0) return status;
8331 }
8332
8333 /*! \page feaAnalysis
8334 *
8335 * \if (NASTRAN || ASTROS)
8336 * <ul>
8337 * <li> <B>density = 0.0</B> </li> <br>
8338 * Density used in trim analysis to determine true velocity, or flutter analysis.
8339 * </ul>
8340 * \endif
8341 */
8342 keyWord = "density";
8343 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8344 if (status == CAPS_SUCCESS0) {
8345
8346 status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].density);
8347 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8348 if (status != CAPS_SUCCESS0) return status;
8349 }
8350
8351 /*! \page feaAnalysis
8352 *
8353 * \if (MYSTRAN || NASTRAN || ASTROS)
8354 * <ul>
8355 * <li> <B>aeroSymmetryXY = "(no default)"</B> </li> <br>
8356 * Aerodynamic symmetry about the XY Plane. Options: SYM, ANTISYM, ASYM.
8357 * Aerodynamic symmetry about the XY Plane. Options: SYM, ANTISYM, ASYM. SYMMETRIC Indicates that a half span aerodynamic model
8358 * is moving in a symmetric manner with respect to the XY plane.
8359 * ANTISYMMETRIC Indicates that a half span aerodynamic model is moving in an antisymmetric manner with respect to the XY plane.
8360 * ASYMMETRIC Indicates that a full aerodynamic model is provided.
8361 * </ul>
8362 * \endif
8363 */
8364 keyWord = "aeroSymmetryXY";
8365 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8366 if (status == CAPS_SUCCESS0) {
8367
8368 tempString = string_removeQuotation(keyValue);
8369
8370 feaProblem->feaAnalysis[i].aeroSymmetryXY = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8371 if(feaProblem->feaAnalysis[i].aeroSymmetryXY == NULL((void*)0)) {
8372 if (tempString != NULL((void*)0)) EG_free(tempString);
8373
8374 return EGADS_MALLOC-4;
8375 }
8376
8377 memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXY, tempString, strlen(tempString)*sizeof(char));
8378 feaProblem->feaAnalysis[i].aeroSymmetryXY[strlen(tempString)] = '\0';
8379
8380 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8381 AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); };
8382 }
8383
8384 // check for the old option trimSymmetry
8385 keyWord = "trimSymmetry";
8386 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8387 if (status == CAPS_SUCCESS0) {
8388
8389 tempString = string_removeQuotation(keyValue);
8390
8391 feaProblem->feaAnalysis[i].aeroSymmetryXY = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8392 if(feaProblem->feaAnalysis[i].aeroSymmetryXY == NULL((void*)0)) {
8393 if (tempString != NULL((void*)0)) EG_free(tempString);
8394
8395 return EGADS_MALLOC-4;
8396 }
8397
8398 memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXY, tempString, strlen(tempString)*sizeof(char));
8399 feaProblem->feaAnalysis[i].aeroSymmetryXY[strlen(tempString)] = '\0';
8400
8401 if (keyValue != NULL((void*)0)) {
8402 EG_free(keyValue);
8403 keyValue = NULL((void*)0);
8404 }
8405
8406 if (tempString != NULL((void*)0)) {
8407 EG_free(tempString);
8408 tempString = NULL((void*)0);
8409 }
8410 }
8411
8412 /*! \page feaAnalysis
8413 *
8414 * \if (MYSTRAN || NASTRAN || ASTROS)
8415 * <ul>
8416 * <li> <B>aeroSymmetryXZ = "(no default)"</B> </li> <br>
8417 * Aerodynamic symmetry about the XZ Plane. Options: SYM, ANTISYM, ASYM. SYMMETRIC Indicates that a half span aerodynamic model
8418 * is moving in a symmetric manner with respect to the XZ plane.
8419 * ANTISYMMETRIC Indicates that a half span aerodynamic model is moving in an antisymmetric manner with respect to the XZ plane.
8420 * ASYMMETRIC Indicates that a full aerodynamic model is provided.
8421 * </ul>
8422 * \endif
8423 */
8424 keyWord = "aeroSymmetryXZ";
8425 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8426 if (status == CAPS_SUCCESS0) {
8427
8428 tempString = string_removeQuotation(keyValue);
8429
8430 feaProblem->feaAnalysis[i].aeroSymmetryXZ = EG_alloc((strlen(tempString) + 1)*sizeof(char));
8431 if(feaProblem->feaAnalysis[i].aeroSymmetryXZ == NULL((void*)0)) {
8432 if (tempString != NULL((void*)0)) EG_free(tempString);
8433
8434 return EGADS_MALLOC-4;
8435 }
8436
8437 memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXZ, tempString, strlen(tempString)*sizeof(char));
8438 feaProblem->feaAnalysis[i].aeroSymmetryXZ[strlen(tempString)] = '\0';
8439
8440 if (keyValue != NULL((void*)0)) {
8441 EG_free(keyValue);
8442 keyValue = NULL((void*)0);
8443 }
8444
8445 if (tempString != NULL((void*)0)) {
8446 EG_free(tempString);
8447 tempString = NULL((void*)0);
8448 }
8449 }
8450
8451 /*! \page feaAnalysis
8452 *
8453 * \if (NASTRAN )
8454 * <ul>
8455 * <li> <B>rigidVariable = ["no default"]</B> </li> <br>
8456 * List of rigid body motions to be used as trim variables during a trim analysis. Nastran
8457 * valid labels are: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8458 * </ul>
8459 * \elseif ASTROS
8460 * <ul>
8461 * <li> <B>rigidVariable = ["no default"]</B> </li> <br>
8462 * List of rigid body motions to be used as trim variables during a trim analysis. Nastran format
8463 * labels are used and will be converted by the AIM automatically.
8464 * Expected inputs: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8465 * </ul>
8466 * \endif
8467 */
8468 keyWord = "rigidVariable";
8469 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8470 if (status == CAPS_SUCCESS0) {
8471
8472 status = string_toStringDynamicArray(keyValue,
8473 &feaProblem->feaAnalysis[i].numRigidVariable,
8474 &feaProblem->feaAnalysis[i].rigidVariable);
8475 if (keyValue != NULL((void*)0)) {
8476 EG_free(keyValue);
8477 keyValue = NULL((void*)0);
8478 }
8479 if (status != CAPS_SUCCESS0) return status;
8480 }
8481
8482 /*! \page feaAnalysis
8483 *
8484 * \if (NASTRAN)
8485 * <ul>
8486 * <li> <B>rigidConstraint = ["no default"]</B> </li> <br>
8487 * List of rigid body motions to be used as trim constraint variables during a trim analysis. Nastran
8488 * valid labels are: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8489 * </ul>
8490 * \elseif ASTROS
8491 * <ul>
8492 * <li> <B>rigidConstraint = ["no default"]</B> </li> <br>
8493 * List of rigid body motions to be used as trim constraint variables during a trim analysis. Nastran format
8494 * labels are used and will be converted by the AIM automatically.
8495 * Expected inputs: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6
8496 * </ul>
8497 * \endif
8498 */
8499 keyWord = "rigidConstraint";
8500 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8501 if (status == CAPS_SUCCESS0) {
8502
8503 status = string_toStringDynamicArray(keyValue,
8504 &feaProblem->feaAnalysis[i].numRigidConstraint,
8505 &feaProblem->feaAnalysis[i].rigidConstraint);
8506 if (keyValue != NULL((void*)0)) {
8507 EG_free(keyValue);
8508 keyValue = NULL((void*)0);
8509 }
8510 if (status != CAPS_SUCCESS0) return status;
8511 }
8512
8513 if (feaProblem->feaAnalysis[i].numRigidConstraint != 0) {
8514 /*! \page feaAnalysis
8515 *
8516 * \if (NASTRAN || ASTROS)
8517 * <ul>
8518 * <li> <B>magRigidConstraint = [0.0 , 0.0, ...]</B> </li> <br>
8519 * List of magnitudes of trim constraint variables. If none and 'rigidConstraint'(s) are specified
8520 * then 0.0 is assumed for each rigid constraint.
8521 * </ul>
8522 * \endif
8523 */
8524 keyWord = "magRigidConstraint";
8525 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8526 if (status == CAPS_SUCCESS0) {
8527
8528 status = string_toDoubleDynamicArray(keyValue,
8529 &tempInt,
8530 &feaProblem->feaAnalysis[i].magRigidConstraint);
8531 if (keyValue != NULL((void*)0)) {
8532 EG_free(keyValue);
8533 keyValue = NULL((void*)0);
8534 }
8535 if (status != CAPS_SUCCESS0) return status;
8536 } else {
8537
8538 tempInt = feaProblem->feaAnalysis[i].numRigidConstraint;
8539
8540 feaProblem->feaAnalysis[i].magRigidConstraint = (double *) EG_alloc(tempInt*sizeof(double));
8541 if (feaProblem->feaAnalysis[i].magRigidConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8542
8543 for (j = 0; j < feaProblem->feaAnalysis[i].numRigidConstraint; j++) {
8544
8545 feaProblem->feaAnalysis[i].magRigidConstraint[j] = 0.0;
8546 }
8547 }
8548
8549 if (tempInt != feaProblem->feaAnalysis[i].numRigidConstraint) {
8550 printf("\tDimensional mismatch between 'magRigidConstraint' and 'rigidConstraint'.\n");
8551 printf("\t 'magRigidConstraint' will be resized.\n");
8552
8553 feaProblem->feaAnalysis[i].magRigidConstraint = (double *) EG_reall(feaProblem->feaAnalysis[i].magRigidConstraint,
8554 feaProblem->feaAnalysis[i].numRigidConstraint*sizeof(double));
8555
8556 if (feaProblem->feaAnalysis[i].magRigidConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8557
8558 for (j = tempInt; j < feaProblem->feaAnalysis[i].numRigidConstraint; j++) {
8559 feaProblem->feaAnalysis[i].magRigidConstraint[j] = 0.0;
8560 }
8561 }
8562 }
8563
8564 /*! \page feaAnalysis
8565 *
8566 * \if (NASTRAN || ASTROS)
8567 * <ul>
8568 * <li> <B>controlConstraint = ["no default"]</B> </li> <br>
8569 * List of controls surfaces to be used as trim constraint variables during a trim analysis.
8570 * </ul>
8571 * \endif
8572 */
8573 keyWord = "controlConstraint";
8574 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8575 if (status == CAPS_SUCCESS0) {
8576
8577 status = string_toStringDynamicArray(keyValue,
8578 &feaProblem->feaAnalysis[i].numControlConstraint,
8579 &feaProblem->feaAnalysis[i].controlConstraint);
8580 if (keyValue != NULL((void*)0)) {
8581 EG_free(keyValue);
8582 keyValue = NULL((void*)0);
8583 }
8584 if (status != CAPS_SUCCESS0) return status;
8585 }
8586
8587 if (feaProblem->feaAnalysis[i].numControlConstraint != 0) {
8588 /*! \page feaAnalysis
8589 *
8590 * \if (NASTRAN || ASTROS)
8591 * <ul>
8592 * <li> <B>magControlConstraint = [0.0 , 0.0, ...]</B> </li> <br>
8593 * List of magnitudes of trim control surface constraint variables. If none and 'controlConstraint'(s) are specified
8594 * then 0.0 is assumed for each control surface constraint.
8595 * </ul>
8596 * \endif
8597 */
8598 keyWord = "magControlConstraint";
8599 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8600 if (status == CAPS_SUCCESS0) {
8601
8602 status = string_toDoubleDynamicArray(keyValue,
8603 &tempInt,
8604 &feaProblem->feaAnalysis[i].magControlConstraint);
8605 if (keyValue != NULL((void*)0)) {
8606 EG_free(keyValue);
8607 keyValue = NULL((void*)0);
8608 }
8609 if (status != CAPS_SUCCESS0) return status;
8610 } else {
8611
8612 tempInt = feaProblem->feaAnalysis[i].numControlConstraint;
8613
8614 feaProblem->feaAnalysis[i].magControlConstraint = (double *) EG_alloc(tempInt*sizeof(double));
8615 if (feaProblem->feaAnalysis[i].magControlConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8616
8617 for (j = 0; j < feaProblem->feaAnalysis[i].numControlConstraint; j++) {
8618
8619 feaProblem->feaAnalysis[i].magControlConstraint[j] = 0.0;
8620 }
8621 }
8622
8623 if (tempInt != feaProblem->feaAnalysis[i].numControlConstraint) {
8624 printf("\tDimensional mismatch between 'magControlConstraint' and 'controlConstraint'.\n");
8625 printf("\t 'magControlConstraint' will be resized.\n");
8626
8627 feaProblem->feaAnalysis[i].magControlConstraint = (double *) EG_reall(feaProblem->feaAnalysis[i].magControlConstraint,
8628 feaProblem->feaAnalysis[i].numControlConstraint*sizeof(double));
8629
8630 if (feaProblem->feaAnalysis[i].magControlConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
8631
8632 for (j = tempInt; j < feaProblem->feaAnalysis[i].numControlConstraint; j++) {
8633 feaProblem->feaAnalysis[i].magControlConstraint[j] = 0.0;
8634 }
8635 }
8636 }
8637
8638 /*! \page feaAnalysis
8639 *
8640 * \if (NASTRAN || ASTROS)
8641 * <ul>
8642 * <li> <B>reducedFreq = [0.1, ..., 20.0], No Default Values are defined.</B> </li> <br>
8643 * Reduced Frequencies to be used in Flutter Analysis. Up to 8 values can be defined.
8644 * </ul>
8645 * \endif
8646 */
8647 keyWord = "reducedFreq";
8648 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8649 if (status == CAPS_SUCCESS0) {
8650
8651 status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numReducedFreq, &feaProblem->feaAnalysis[i].reducedFreq);
8652 if (keyValue != NULL((void*)0)) {
8653 EG_free(keyValue);
8654 keyValue = NULL((void*)0);
8655 }
8656 if (feaProblem->feaAnalysis[i].numReducedFreq > 8) {
8657 printf("\tError: The number of reduced frequencies (reducedFreq) entered in an Analysis AIM Input must be eight or less\n");
8658 return CAPS_BADVALUE-311;
8659 }
8660 if (status != CAPS_SUCCESS0) return status;
8661 }
8662
8663 /*! \page feaAnalysis
8664 *
8665 * \if (NASTRAN || ASTROS)
8666 * <ul>
8667 * <li> <B>flutterVel = [0.1, ..., 20.0]</B> </li> <br>
8668 * Velocities to be used in Flutter Analysis. If no values are provided the
8669 * following relation is used
8670 *
8671 * v = sqrt(2*dynamicPressure/density)
8672 * dv = (v*2 - v/2) / 20;
8673 *
8674 * flutterVel[0] = v/10
8675 * flutterVel[i] = v/2 + i*dv; where i = 1....21
8676 * flutterVel[22] = v*10;
8677 * </ul>
8678 * \endif
8679 */
8680 keyWord = "flutterVel";
8681 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8682 if (status == CAPS_SUCCESS0) {
8683
8684 status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numFlutterVel, &feaProblem->feaAnalysis[i].flutterVel);
8685 if (keyValue != NULL((void*)0)) {
8686 EG_free(keyValue);
8687 keyValue = NULL((void*)0);
8688 }
8689 if (status != CAPS_SUCCESS0) return status;
8690 }
8691
8692 /*! \page feaAnalysis
8693 *
8694 * \if (ASTROS)
8695 * <ul>
8696 * <li> <B>flutterConvergenceParam = 1e-5 </B> </li> <br>
8697 * Convergence parameter for flutter eigenvalue.
8698 * </ul>
8699 * \endif
8700 */
8701 keyWord = "flutterConvergenceParam";
8702 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8703 if (status == CAPS_SUCCESS0) {
8704
8705 status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].flutterConvergenceParam);
8706 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8707 if (status != CAPS_SUCCESS0) return status;
8708 }
8709 else {
8710 feaProblem->feaAnalysis[i].flutterConvergenceParam = 1.e-5;
8711 }
8712
8713 /*! \page feaAnalysis
8714 *
8715 * \if (NASTRAN || ASTROS)
8716 * <ul>
8717 * <li> <B>visualFlutter = False </B> </li> <br>
8718 * Turn on flutter visualization f06 output.
8719 * </ul>
8720 * \endif
8721 */
8722 // keyWord = "visualFlutter";
8723 // status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8724 // if (status == CAPS_SUCCESS) {
8725 //
8726 // status = string_toBoolean(keyValue, &feaProblem->feaAnalysis[i].visualFlutter);
8727 // if (keyValue != NULL) {
8728 // EG_free(keyValue);
8729 // keyValue = NULL;
8730 // }
8731 // if (status != CAPS_SUCCESS) return status;
8732 // }
8733
8734 /*! \page feaAnalysis
8735 *
8736 * \if (NASTRAN)
8737 * <ul>
8738 * <li> <B>analysisResponse = "(no default)"</B> </li> <br>
8739 * 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",...].
8740 * </ul>
8741 * \endif
8742 */
8743 keyWord = "analysisResponse";
8744 status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue);
8745 if (status == CAPS_SUCCESS0) {
8746
8747 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
8748 if (keyValue != NULL((void*)0)) {
8749 EG_free(keyValue);
8750 keyValue = NULL((void*)0);
8751 }
8752
8753 if (status != CAPS_SUCCESS0) return status;
8754
8755 feaProblem->feaAnalysis[i].numDesignResponse = 0;
8756 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
8757
8758 for (attrIndex = 0; attrIndex < feaProblem->numDesignResponse; attrIndex++) {
8759
8760 if (strcasecmp(feaProblem->feaDesignResponse[attrIndex].name, groupName[groupIndex]) == 0) {
8761
8762 feaProblem->feaAnalysis[i].numDesignResponse += 1;
8763
8764 if (feaProblem->feaAnalysis[i].numDesignResponse == 1) {
8765
8766 feaProblem->feaAnalysis[i].designResponseSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numDesignResponse *sizeof(int));
8767
8768 } else {
8769
8770 feaProblem->feaAnalysis[i].designResponseSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].designResponseSetID,
8771 feaProblem->feaAnalysis[i].numDesignResponse *sizeof(int));
8772 }
8773
8774 if (feaProblem->feaAnalysis[i].designResponseSetID == NULL((void*)0)) {
8775 status = string_freeArray(numGroupName, &groupName);
8776 if (status != CAPS_SUCCESS0) return status;
8777 groupName = NULL((void*)0);
8778 return EGADS_MALLOC-4;
8779 }
8780
8781 feaProblem->feaAnalysis[i].designResponseSetID[feaProblem->feaAnalysis[i].numDesignResponse-1] = feaProblem->feaDesignResponse[attrIndex].responseID;
8782 break;
8783 }
8784 }
8785
8786 if (feaProblem->feaAnalysis[i].numDesignResponse != groupIndex+1) {
8787
8788 printf("\tWarning: Analysis design response name, %s, not found in feaDesignResponse structure\n", groupName[groupIndex]);
8789
8790 }
8791 }
8792
8793 status = string_freeArray(numGroupName, &groupName);
8794 if (status != CAPS_SUCCESS0) {
8795 if (tempString != NULL((void*)0)) EG_free(tempString);
8796
8797 return status;
8798 }
8799 groupName = NULL((void*)0);
8800 }
8801
8802 if (feaProblem->feaAnalysis[i].analysisType == AeroelasticFlutter) {
8803 // Setup the default flutter velocities if not specified
8804 status = fea_defaultFlutterVelocity(&feaProblem->feaAnalysis[i]);
8805 if (status != CAPS_SUCCESS0) return status;
8806 }
8807
8808 } else { // Not JSONstring
8809
8810 /*! \page feaAnalysis
8811 * \section keyStringAnalysis Single Value String
8812 *
8813 * If "Value" is a string, the string value may correspond to an entry in a predefined analysis lookup
8814 * table. NOT YET IMPLEMENTED!!!!
8815 *
8816 *
8817 */
8818
8819 // CALL analysis look up
8820 printf("\tError: Analysis tuple value is expected to be a JSON string\n");
8821 //printf("\t%s", analysisTuple[i].value);
8822 return CAPS_BADVALUE-311;
8823 }
8824 }
8825
8826 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
8827
8828 printf("\tDone getting FEA analyses\n");
8829 return CAPS_SUCCESS0;
8830}
8831
8832// Get the design variables from a capsTuple
8833int fea_getDesignVariable(void *aimInfo,
8834 /*@unused@*/ int requireGroup,
8835 int numDesignVariableTuple,
8836 capsTuple designVariableTuple[],
8837 int numDesignVariableRelationTuple,
8838 capsTuple designVariableRelationTuple[],
8839 mapAttrToIndexStruct *attrMap,
8840 feaProblemStruct *feaProblem) {
8841
8842 /*! \page feaDesignVariable FEA Design Variables
8843 * Structure for the design variable tuple = ("DesignVariable Name", "Value").
8844 * "DesignVariable Name" defines the reference name for the design variable being specified.
8845 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
8846 * (see Section \ref jsonStringDesignVariable).
8847 * \if NASTRAN
8848 * In Nastran the DesignVariable Name will be the LABEL used in the DESVAR input.
8849 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
8850 *
8851 * - <c>DESVAR ID LABEL XINIT XLB XUB DELXV DDVAL</c>
8852 * \endif
8853 *
8854 */
8855 int status; //Function return
8856
8857 int i, j, k; // Indexing
8858 int found;
8859
8860 char *keyValue = NULL((void*)0);
8861 char *keyWord = NULL((void*)0);
8862
8863 int tempInteger = 0;
8864 int designVariableID = 0;
8865
8866 char **groupName = NULL((void*)0);
8867 int numGroupName = 0;
8868
8869 feaDesignVariableStruct *designVariable;
8870 feaDesignVariableRelationStruct *designVariableRelation;
8871
8872 // Destroy our design variable structures coming in if aren't 0 and NULL already
8873 if (feaProblem->feaDesignVariable != NULL((void*)0)) {
8874 for (i = 0; i < feaProblem->numDesignVariable; i++) {
8875 status = destroy_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]);
8876 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8876
, __func__, 0); goto cleanup; }
;
8877 }
8878 }
8879 AIM_FREE(feaProblem->feaDesignVariable){ EG_free(feaProblem->feaDesignVariable); feaProblem->feaDesignVariable
= ((void*)0); }
;
8880 feaProblem->feaDesignVariable = NULL((void*)0);
8881 feaProblem->numDesignVariable = 0;
8882
8883 // Destroy our design variable relation structures coming in if aren't 0 and NULL already
8884 if (feaProblem->feaDesignVariableRelation != NULL((void*)0)) {
8885 for (i = 0; i < feaProblem->numDesignVariableRelation; i++) {
8886 status = destroy_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]);
8887 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8887
, __func__, 0); goto cleanup; }
;
8888 }
8889 }
8890 AIM_FREE(feaProblem->feaDesignVariableRelation){ EG_free(feaProblem->feaDesignVariableRelation); feaProblem
->feaDesignVariableRelation = ((void*)0); }
;
8891 feaProblem->feaDesignVariableRelation = NULL((void*)0);
8892 feaProblem->numDesignVariableRelation = 0;
8893
8894
8895 printf("\nGetting FEA design variables.......\n");
8896
8897 feaProblem->numDesignVariable = numDesignVariableTuple;
8898
8899 printf("\tNumber of design variables - %d\n", feaProblem->numDesignVariable);
8900
8901 if (feaProblem->numDesignVariable > 0) {
8902 AIM_ALLOC(feaProblem->feaDesignVariable,{ if (feaProblem->feaDesignVariable != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 8903, __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", 8903, __func__, 3
, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariable"
, memorysize, "feaDesignVariableStruct"); goto cleanup; } }
8903 feaProblem->numDesignVariable, feaDesignVariableStruct, aimInfo, status){ if (feaProblem->feaDesignVariable != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 8903, __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", 8903, __func__, 3
, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariable"
, memorysize, "feaDesignVariableStruct"); goto cleanup; } }
;
8904
8905 } else {
8906 AIM_ERROR(aimInfo, "Number of design variable values in input tuple is 0\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 8906, __func__
, "Number of design variable values in input tuple is 0\n"); }
;
8907 return CAPS_NOTFOUND-303;
8908 }
8909
8910 for (i = 0; i < feaProblem->numDesignVariable; i++) {
8911 status = initiate_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]);
8912 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8912
, __func__, 0); goto cleanup; }
;
8913 }
8914
8915 for (i = 0; i < feaProblem->numDesignVariable; i++) {
8916
8917 designVariable = &feaProblem->feaDesignVariable[i];
8918
8919 printf("\tDesign_Variable name - %s\n", designVariableTuple[i].name);
8920
8921 AIM_STRDUP(designVariable->name, designVariableTuple[i].name, aimInfo, status){ if (designVariable->name != ((void*)0)) { status = -4; aim_status
(aimInfo, status, "feaUtils.c", 8921, __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", 8921, __func__, 2, "AIM_STRDUP: %s %s", "designVariable->name"
, designVariableTuple[i].name); goto cleanup; } }
;
8922
8923 // Do we have a json string?
8924 if (json_isDict(designVariableTuple[i].value)) {
8925
8926 /*! \page feaDesignVariable
8927 * \section jsonStringDesignVariable JSON String Dictionary
8928 *
8929 * If "Value" is JSON string dictionary
8930 * \if (NASTRAN || ASTROS || MASSTRAN)
8931 * (eg. "Value" = {"initialValue": 5.0, "upperBound": 10.0})
8932 * \endif
8933 * the following keywords ( = default values) may be used:
8934 *
8935 */
8936
8937 /*! \page feaDesignVariable
8938 *
8939 * \if (NASTRAN || ASTROS || MASSTRAN)
8940 * <ul>
8941 * <li> <B>initialValue = 0.0</B> </li> <br>
8942 * Initial value for the design variable.
8943 * </ul>
8944 * \endif
8945 *
8946 */
8947 keyWord = "initialValue";
8948 status = json_getDouble(
8949 designVariableTuple[i].value, keyWord,
8950 &designVariable->initialValue);
8951
8952 if (status != CAPS_SUCCESS0) {
8953 designVariable->initialValue = 0.0;
8954 }
8955
8956 /*! \page feaDesignVariable
8957 *
8958 * \if (NASTRAN || ASTROS)
8959 * <ul>
8960 * <li> <B>lowerBound = 0.0</B> </li> <br>
8961 * Lower bound for the design variable.
8962 * </ul>
8963 * \endif
8964 */
8965 keyWord = "lowerBound";
8966 status = json_getDouble(
8967 designVariableTuple[i].value, keyWord,
8968 &designVariable->lowerBound);
8969
8970 if (status != CAPS_SUCCESS0) {
8971 designVariable->lowerBound = 0.0;
8972 }
8973
8974 /*! \page feaDesignVariable
8975 *
8976 * \if (NASTRAN || ASTROS)
8977 * <ul>
8978 * <li> <B>upperBound = 0.0</B> </li> <br>
8979 * Upper bound for the design variable.
8980 * </ul>
8981 * \endif
8982 */
8983 keyWord = "upperBound";
8984 status = json_getDouble(
8985 designVariableTuple[i].value, keyWord,
8986 &designVariable->upperBound);
8987
8988 if (status != CAPS_SUCCESS0) {
8989 designVariable->upperBound = 0.0;
8990 }
8991
8992 /*! \page feaDesignVariable
8993 *
8994 * \if (NASTRAN || ASTROS)
8995 * <ul>
8996 * <li> <B>maxDelta = 0.0</B> </li> <br>
8997 * Move limit for the design variable.
8998 * </ul>
8999 * \endif
9000 */
9001 keyWord = "maxDelta";
9002 status = json_getDouble(
9003 designVariableTuple[i].value, keyWord,
9004 &designVariable->maxDelta);
9005
9006 if (status != CAPS_SUCCESS0) {
9007 designVariable->maxDelta = 0.0;
9008 }
9009
9010 /*! \page feaDesignVariable
9011 *
9012 * \if (NASTRAN || ASTROS)
9013 * <ul>
9014 * <li> <B>discreteValue = 0.0</B> </li> <br>
9015 * List of discrete values to use for the design variable (e.g. [0.0,1.0,1.5,3.0].
9016 * </ul>
9017 * \endif
9018 */
9019 keyWord = "discreteValue";
9020 status = json_getDoubleDynamicArray(
9021 designVariableTuple[i].value, keyWord,
9022 &designVariable->numDiscreteValue, &designVariable->discreteValue);
9023
9024 if (status != CAPS_SUCCESS0) {
9025 designVariable->numDiscreteValue = 0;
9026 designVariable->discreteValue = NULL((void*)0);
9027 }
9028
9029 /*! \page feaDesignVariable
9030 *
9031 * \if NASTRAN
9032 * <ul>
9033 * <li> <B>independentVariable = "(no default)"</B> </li> <br>
9034 * Single or list of "DesignVariable Name"s (that is the Tuple name) used to create/designate a
9035 * dependent design variable.
9036 * - independentValue = variableWeight[1] + variableWeight[2] * SUM{independentVariableWeight[i] * independentVariable[i]}
9037 * </ul>
9038 * \endif
9039 */
9040
9041 keyWord = "independentVariable";
9042 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9043 if (status == CAPS_SUCCESS0) {
9044
9045 status = string_toStringDynamicArray(keyValue,
9046 &designVariable->numIndependVariable,
9047 &designVariable->independVariable);
9048 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9049 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9049
, __func__, 0); goto cleanup; }
;
9050
9051 }
9052
9053 /*! \page feaDesignVariable
9054 *
9055 * \if NASTRAN
9056 * <ul>
9057 * <li> <B>independentVariableWeight = 1.0 or [1.0, 1.0, ...]</B> </li> <br>
9058 * Single or list of weighting constants with respect to the variables set for "independentVariable".
9059 * If the length of this list doesn't match the length
9060 * of the "independentVariable" list, the list is either truncated [ >length("independentVariable")] or expanded [ <length("independentVariable")]
9061 * in which case the <b>last weight is repeated</b>.
9062 * </ul>
9063 * \endif
9064 */
9065
9066 keyWord = "independentVariableWeight";
9067 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9068 if (status == CAPS_SUCCESS0) {
9069
9070 status = string_toDoubleDynamicArray(keyValue,
9071 &tempInteger,
9072 &designVariable->independVariableWeight);
9073 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9074 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9074
, __func__, 0); goto cleanup; }
;
9075
9076 // We have weights, but no variables
9077 if (designVariable->numIndependVariable == 0) {
9078
9079 printf("\tWeighting constants have been provided, but no independent design variables were set!\n");
9080
9081 // Less weights than variables
9082 } else if( tempInteger < designVariable->numIndependVariable) {
9083
9084 printf("\tThe number of weighting constants provided does not match the number of independent design variables. "
9085 "The last weight will be repeated %d times\n", designVariable->numIndependVariable - tempInteger);
9086
9087 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"
, 9088, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
9088 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"
, 9088, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
;
9089
9090 for (j = 0; j < designVariable->numIndependVariable - tempInteger; j++) {
9091
9092 designVariable->independVariableWeight[j+tempInteger] = designVariable->independVariableWeight[tempInteger-1];
9093 }
9094
9095 // More weights than variables
9096 } else if (tempInteger > designVariable->numIndependVariable) {
9097
9098 printf("\tThe number of weighting constants provided does not match the number of independent design variables. "
9099 "The last %d weights will be not be used\n", tempInteger -designVariable->numIndependVariable);
9100
9101 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"
, 9102, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
9102 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"
, 9102, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
;
9103 }
9104
9105 } else { // No weights provided - set default value of 1.0
9106
9107 if (designVariable->numIndependVariable != 0) {
9108 AIM_ALLOC(designVariable->independVariableWeight, designVariable->numIndependVariable, double, aimInfo, status){ if (designVariable->independVariableWeight != ((void*)0)
) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9108
, __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"
, 9108, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariable->independVariableWeight"
, memorysize, "double"); goto cleanup; } }
;
9109
9110 for (j = 0; j < designVariable->numIndependVariable; j++) {
9111 designVariable->independVariableWeight[j] = 1.0;
9112 }
9113 }
9114 }
9115
9116 /*! \page feaDesignVariable
9117 *
9118 * \if NASTRAN
9119 * <ul>
9120 * <li> <B>variableWeight = [1.0, 1.0]</B> </li> <br>
9121 * Weighting constants for a dependent variable - used if "independentVariable"(s) have been provided.
9122 * </ul>
9123 * \endif
9124 */
9125 keyWord = "variableWeight";
9126 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9127 if (status == CAPS_SUCCESS0) {
9128
9129 status = string_toDoubleArray(keyValue,
9130 2,
9131 designVariable->variableWeight);
9132 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9133
9134 if (status != CAPS_SUCCESS0) {
9135 AIM_ERROR(aimInfo, "Retrieving variableWeight - status %d\n", status){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9135, __func__
, "Retrieving variableWeight - status %d\n", status); }
;
9136 goto cleanup;
9137 }
9138 } else {
9139 designVariable->variableWeight[0] = 1.0;
9140 designVariable->variableWeight[1] = 1.0;
9141 }
9142
9143 // check if design variable relation info also included in input
9144 keyWord = "fieldName";
9145 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9146
9147 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9148
9149 if (status != CAPS_SUCCESS0) {
9150 keyWord = "fieldPosition";
9151 status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue);
9152 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9153 }
9154
9155 if (status == CAPS_SUCCESS0) {
9156
9157// // The main relation associated with this design variable, if defined in input
9158// AIM_REALL(feaProblem->feaDesignVariableRelation, relationIndex+1, feaDesignVariableRelationStruct, aimInfo, status);
9159//
9160// designVariableRelation = &feaProblem->feaDesignVariableRelation[relationIndex++];
9161//
9162// feaProblem->numDesignVariableRelation = relationIndex;
9163//
9164// status = initiate_feaDesignVariableRelationStruct(designVariableRelation);
9165// AIM_STATUS(aimInfo, status);
9166//
9167// printf("\tWarning: the ability to provide design variable relation data "
9168// "within Design_Variable input is deprecated and "
9169// "will be removed in the future. Please use provide relation data "
9170// "via \"Design_Variable_Relation\" instead.\n");
9171//
9172// status = fea_getDesignVariableRelationEntry( &designVariableTuple[i], designVariableRelation,
9173// attrMap, feaProblem, designVariable->name);
9174// AIM_STATUS(aimInfo, status);
9175//
9176// designVariableRelation->relationID = relationIndex;
9177
9178 AIM_ERROR(aimInfo, "The ability to provide design variable relation data "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9180, __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"); }
9179 "within Design_Variable input is deprecated. Please provide relation data "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9180, __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"); }
9180 "via \"Design_Variable_Relation\" instead.\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9180, __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"); }
;
9181 status = CAPS_BADVALUE-311;
9182 goto cleanup;
9183 }
9184
9185
9186 } else {
9187
9188 AIM_ERROR(aimInfo, "Design_Variable tuple value is expected to be a JSON string\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9188, __func__
, "Design_Variable tuple value is expected to be a JSON string\n"
); }
;
9189 status = CAPS_BADVALUE-311;
9190 goto cleanup;
9191
9192 }
9193 }
9194
9195 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9196
9197 // Order the design variable ID's such that Analysis and Geometry ID's are continuous.
9198 // This is required by the TACS AIM
9199
9200 designVariableID = 1;
9201 for( i = 0; i < feaProblem->numDesignVariable; i++) {
9202
9203 // only analysis design variables
9204 if (aim_getIndex(aimInfo, feaProblem->feaDesignVariable[i].name, GEOMETRYIN) <= 0)
9205 feaProblem->feaDesignVariable[i].designVariableID = designVariableID++;
9206 }
9207 for( i = 0; i < feaProblem->numDesignVariable; i++) {
9208
9209 // only geometry design variables
9210 if (aim_getIndex(aimInfo, feaProblem->feaDesignVariable[i].name, GEOMETRYIN) > 0)
9211 feaProblem->feaDesignVariable[i].designVariableID = designVariableID++;
9212 }
9213
9214 // Now that we are done going through all the tuples we need to populate/create the independVaraiableID array
9215 // if independentVariable was set for any of them.
9216 for (i = 0; i < feaProblem->numDesignVariable; i++) {
9217
9218 designVariable = &feaProblem->feaDesignVariable[i];
9219
9220 if (designVariable->numIndependVariable != 0) {
9221
9222 AIM_ALLOC(designVariable->independVariableID, designVariable->numIndependVariable, int, aimInfo, status){ if (designVariable->independVariableID != ((void*)0)) { status
= -4; aim_status(aimInfo, status, "feaUtils.c", 9222, __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"
, 9222, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariable->independVariableID"
, memorysize, "int"); goto cleanup; } }
;
9223
9224 // Loop through the independent variable names
9225 for (j = 0; j < designVariable->numIndependVariable; j++) {
9226
9227 // Compare the independent variable names with design variable name
9228 found = (int) false0;
9229 for (k = 0; k < feaProblem->numDesignVariable; k++) {
9230 if (strcasecmp(designVariable->independVariable[j], feaProblem->feaDesignVariable[k].name) == 0) {
9231 found = (int) true1;
9232 break;
9233 }
9234 }
9235
9236 // If NOT found
9237 if (found != (int) true1) {
9238 AIM_ERROR(aimInfo, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9240, __func__
, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "
"variable %s!!!\n", designVariable->independVariable[j], designVariable
->name); }
9239 "variable %s!!!\n", designVariable->independVariable[j],{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9240, __func__
, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "
"variable %s!!!\n", designVariable->independVariable[j], designVariable
->name); }
9240 designVariable->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9240, __func__
, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "
"variable %s!!!\n", designVariable->independVariable[j], designVariable
->name); }
;
9241 status = CAPS_NOTFOUND-303;
9242 goto cleanup;
9243 }
9244
9245 designVariable->independVariableID[j] = feaProblem->feaDesignVariable[k].designVariableID;
9246 }
9247 }
9248 }
9249
9250 if (designVariableRelationTuple != NULL((void*)0)) {
9251
9252 AIM_ALLOC(feaProblem->feaDesignVariableRelation, numDesignVariableRelationTuple, feaDesignVariableRelationStruct, aimInfo, status){ if (feaProblem->feaDesignVariableRelation != ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9252
, __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", 9252
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariableRelation"
, memorysize, "feaDesignVariableRelationStruct"); goto cleanup
; } }
;
9253 feaProblem->numDesignVariableRelation = numDesignVariableRelationTuple;
9254
9255 for (i = 0; i < numDesignVariableRelationTuple; i++) {
9256 status = initiate_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]);
9257 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9257
, __func__, 0); goto cleanup; }
;
9258 }
9259
9260 // Go through design variable relations defined via 'Design_Variable_Relation'
9261 for (i = 0; i < numDesignVariableRelationTuple; i++) {
9262
9263 /*! \page feaDesignVariableRelation FEA DesignVariableRelation
9264 * Structure for the design variable tuple = ("DesignVariableRelation Name", "Value").
9265 * "DesignVariableRelation Name" defines the reference name for the design variable being specified.
9266 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
9267 * (see Section \ref jsonStringDesignVariableRelation).
9268 *
9269 */
9270
9271 designVariableRelation = &feaProblem->feaDesignVariableRelation[i];
9272
9273 designVariableRelation->relationID = i+1;
9274
9275 status = fea_getDesignVariableRelationEntry(
9276 aimInfo, &designVariableRelationTuple[i], designVariableRelation,
9277 attrMap, feaProblem, NULL((void*)0)
9278 );
9279 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9279
, __func__, 0); goto cleanup; }
;
9280 }
9281
9282 }
9283 status = fea_linkDesignVariablesAndRelations(feaProblem);
9284 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9284
, __func__, 0); goto cleanup; }
;
9285
9286 printf("\tNumber of design variable relations - %d\n", feaProblem->numDesignVariableRelation);
9287 printf("\tDone getting FEA design variables\n");
9288 status = CAPS_SUCCESS0;
9289
9290cleanup:
9291
9292 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9293
9294 if (groupName != NULL((void*)0))
9295 string_freeArray(numGroupName, &groupName);
9296
9297 return status;
9298}
9299
9300int fea_getDesignVariableRelationEntry(void *aimInfo,
9301 capsTuple *designVariableInput,
9302 /*@unused@*/ feaDesignVariableRelationStruct *designVariableRelation,
9303 /*@unused@*/ mapAttrToIndexStruct *attrMap,
9304 /*@unused@*/ feaProblemStruct *feaProblem,
9305 /*@unused@*/ char *forceGroupName) {
9306
9307
9308 int status; //Function return
9309
9310 int i, j; // Indexing
9311
9312 int numLinearCoeff;
9313
9314 char *keyValue = NULL((void*)0);
9315 char *keyWord = NULL((void*)0);
9316
9317 char **groupName = NULL((void*)0);
9318 int numGroupName = 0;
9319
9320 feaMeshDataStruct *feaData = NULL((void*)0);
9321
9322 int numMaterial;
9323 feaMaterialStruct **materialSet = NULL((void*)0), *material;
9324
9325 int numProperty;
9326 feaPropertyStruct **propertySet = NULL((void*)0), *property;
9327
9328 int numElement;
9329 meshElementStruct **elementSet = NULL((void*)0), *element;
9330
9331 printf("\tDesign_Variable_Relation name - %s\n", designVariableInput->name);
9332
9333 designVariableRelation->name = EG_strdup(designVariableInput->name);
9334
9335 /*! \page feaDesignVariableRelation FEA Design Variable Relations
9336 * \section jsonStringDesignVariableRelation JSON String Dictionary
9337 *
9338 * If "Value" is JSON string dictionary
9339 * \if (NASTRAN || TACS || MASSTRAN)
9340 * (eg. "Value" = {"componentType": "Property", "componentName": "plate", "fieldName": "TM", "variableName": "MyDesVar"})
9341 * \endif
9342 * \if (ASTROS)
9343 * (eg. "Value" = {"componentType": "Property", "componentName": "plate", "variableName": "MyDesVar"})
9344 * \endif
9345 * the following keywords ( = default values) may be used:
9346 *
9347 */
9348 if (!json_isDict(designVariableInput->value)) {
9349 AIM_ERROR(aimInfo,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9350, __func__
, "'Design_Variable_Relation' tuple value must be a JSON dictionary"
); }
9350 "'Design_Variable_Relation' tuple value must be a JSON dictionary"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9350, __func__
, "'Design_Variable_Relation' tuple value must be a JSON dictionary"
); }
;
9351 return CAPS_BADVALUE-311;
9352 }
9353
9354 /*! \page feaDesignVariableRelation
9355 * \if (NASTRAN || TACS || MASSTRAN)
9356 * <ul>
9357 * <li> <B>componentType = "Property"</B> </li> <br>
9358 * The type of component for this design variable relation. Options: "Material", "Property", "Element".
9359 * </ul>
9360 * \endif
9361 * \if (ASTROS)
9362 * <ul>
9363 * <li> <B>componentType = "Property"</B> </li> <br>
9364 * The type of component for this design variable relation. Options: "Property".
9365 * </ul>
9366 * \endif
9367 *
9368 */
9369 // Get component type for design variable relation
9370 keyWord = "componentType";
9371 status = json_getString(
9372 designVariableInput->value, keyWord, &keyValue);
9373
9374 // If "componentType" not found, check "variableType" for legacy purposes
9375 // Warn that "variableType" is deprecated and will be removed in the future!
9376 if (status != CAPS_SUCCESS0) {
9377
9378 status = json_getString(
9379 designVariableInput->value, "variableType", &keyValue);
9380
9381 if (status == CAPS_SUCCESS0) {
9382 printf("\tWarning: \"variableType\" is deprecated and "
9383 "will be removed in the future. Please use \"componentType\" "
9384 "instead.\n");
9385 }
9386 }
9387
9388 if (status == CAPS_SUCCESS0) {
9389
9390 if (strcasecmp(keyValue, "Material") == 0) designVariableRelation->componentType = MaterialDesignVar;
9391 else if (strcasecmp(keyValue, "Property") == 0) designVariableRelation->componentType = PropertyDesignVar;
9392 else if (strcasecmp(keyValue, "Element") == 0) designVariableRelation->componentType = ElementDesignVar;
9393 else {
9394
9395 printf("\tUnrecognized \"%s\" specified (%s) for Design_Variable_Relation tuple %s, defaulting to \"Property\"\n", keyWord,
9396 keyValue,
9397 designVariableInput->name);
9398 designVariableRelation->componentType = PropertyDesignVar;
9399 }
9400
9401 }
9402 else {
9403 printf("\tNo \"%s\" specified for Design_Variable_Relation tuple %s, defaulting to \"Property\"\n", keyWord,
9404 designVariableInput->name);
9405
9406 designVariableRelation->componentType = PropertyDesignVar;
9407 }
9408
9409 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9410
9411 /*! \page feaDesignVariableRelation
9412 *
9413 * \if (NASTRAN || TACS || MASSTRAN)
9414 * <ul>
9415 * <li> <B>componentName = "(no default)"</B> </li> <br>
9416 * Single or list of FEA Property(ies), or FEA Material name(s) linked
9417 * to the design variable relation (e.g. "Name1" or ["Name1","Name2",...].
9418 * - For <c>componentType</c> Property a \ref feaProperty name (or names) is given.
9419 * - For <c>componentType</c> Material a \ref feaMaterial name (or names) is given.
9420 * \if (NASTRAN || TACS)
9421 * - For <c>componentType</c> Element a <c>capsGroup</c> Name (or names) is given.
9422 * \endif
9423 * </ul>
9424 * \endif
9425 * \if (ASTROS)
9426 * <ul>
9427 * <li> <B>componentName = "(no default)"</B> </li> <br>
9428 * Single FEA Property linked to the design variable (e.g. "Name1").
9429 * - For <c>componentType</c> Property a \ref feaProperty name (or names) is given.
9430 * </ul>
9431 * \endif
9432 *
9433 */
9434 keyWord = "componentName";
9435 status = json_getStringDynamicArray(
9436 designVariableInput->value, keyWord,
9437 &numGroupName, &groupName);
9438
9439 if (status != CAPS_SUCCESS0) {
9440 // required
9441 AIM_ERROR(aimInfo, "No \"%s\" specified for Design_Variable tuple %s",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9442, __func__
, "No \"%s\" specified for Design_Variable tuple %s", keyWord
, designVariableInput->name); }
9442 keyWord, designVariableInput->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9442, __func__
, "No \"%s\" specified for Design_Variable tuple %s", keyWord
, designVariableInput->name); }
;
9443 goto cleanup;
9444 }
9445
9446 // collect materials associated with groupName
9447 status = fea_findMaterialsByNames(feaProblem, numGroupName, groupName, &numMaterial, &materialSet);
9448
9449 if (status == CAPS_SUCCESS0) {
9450
9451 AIM_ALLOC(designVariableRelation->materialSetID, numMaterial, int, aimInfo, status){ if (designVariableRelation->materialSetID != ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9451
, __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", 9451
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->materialSetID"
, memorysize, "int"); goto cleanup; } }
;
9452 AIM_ALLOC(designVariableRelation->materialSetType, numMaterial, int, aimInfo, status){ if (designVariableRelation->materialSetType != ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9452
, __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",
9452, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->materialSetType"
, memorysize, "int"); goto cleanup; } }
;
9453 designVariableRelation->numMaterialID = numMaterial;
9454
9455 for (j = 0; j < numMaterial; j++) {
9456
9457 material = materialSet[j];
9458 designVariableRelation->materialSetID[j] = material->materialID;
9459 designVariableRelation->materialSetType[j] = material->materialType;
9460
9461 }
9462 }
9463
9464 // collect properties associated with groupName
9465 status = fea_findPropertiesByNames(feaProblem, numGroupName, groupName,
9466 &numProperty, &propertySet);
9467
9468 if (status == CAPS_SUCCESS0) {
9469
9470 AIM_ALLOC(designVariableRelation->propertySetID, numProperty, int, aimInfo, status){ if (designVariableRelation->propertySetID != ((void*)0))
{ status = -4; aim_status(aimInfo, status, "feaUtils.c", 9470
, __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", 9470
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->propertySetID"
, memorysize, "int"); goto cleanup; } }
;
9471 AIM_ALLOC(designVariableRelation->propertySetType, numProperty, int, aimInfo, status){ if (designVariableRelation->propertySetType != ((void*)0
)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9471
, __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",
9471, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->propertySetType"
, memorysize, "int"); goto cleanup; } }
;
9472 designVariableRelation->numPropertyID = numProperty;
9473
9474 for (j = 0; j < numProperty; j++) {
9475
9476 property = propertySet[j];
9477 designVariableRelation->propertySetID[j] = property->propertyID;
9478 designVariableRelation->propertySetType[j] = property->propertyType;
9479
9480 }
9481 }
9482
9483 // collect elements associated with groupName
9484 status = mesh_findGroupElements(
9485 &feaProblem->feaMesh, attrMap, numGroupName, groupName, &numElement, &elementSet);
9486
9487 if (status == CAPS_SUCCESS0) {
9488
9489 AIM_ALLOC(designVariableRelation->elementSetID, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetID != ((void*)0)) {
status = -4; aim_status(aimInfo, status, "feaUtils.c", 9489,
__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", 9489,
__func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetID"
, memorysize, "int"); goto cleanup; } }
;
9490 AIM_ALLOC(designVariableRelation->elementSetType, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetType != ((void*)0)
) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9490
, __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", 9490
, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetType"
, memorysize, "int"); goto cleanup; } }
;
9491 AIM_ALLOC(designVariableRelation->elementSetSubType, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetSubType != ((void*
)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c",
9491, __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"
, 9491, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetSubType"
, memorysize, "int"); goto cleanup; } }
;
9492 designVariableRelation->numElementID = numElement;
9493
9494 for (j = 0; j < numElement; j++) {
9495
9496 element = elementSet[j];
9497 designVariableRelation->elementSetID[j] = element->elementID;
9498 designVariableRelation->elementSetType[j] = element->elementType;
9499 feaData = (feaMeshDataStruct *) element->analysisData;
9500 designVariableRelation->elementSetSubType[j] = feaData->elementSubType;
9501
9502 }
9503 }
9504
9505 if (groupName != NULL((void*)0))
9506 string_freeArray(numGroupName, &groupName);
9507 numGroupName = 0;
9508 groupName = NULL((void*)0);
9509
9510 AIM_FREE(materialSet){ EG_free(materialSet); materialSet = ((void*)0); };
9511 AIM_FREE(propertySet){ EG_free(propertySet); propertySet = ((void*)0); };
9512 AIM_FREE(elementSet){ EG_free(elementSet); elementSet = ((void*)0); };
9513
9514 /*! \page feaDesignVariableRelation
9515 *
9516 * \if (NASTRAN || TACS || MASSTRAN)
9517 * <ul>
9518 * <li> <B>variableName = "(no default)"</B> </li> <br>
9519 * Single or list of names of design variables linked to this relation
9520 * </ul>
9521 * \endif
9522 * \if (ASTROS)
9523 * <ul>
9524 * <li> <B>variableName = "(no default)"</B> </li> <br>
9525 * Name of design variable linked to this relation
9526 * </ul>
9527 * \endif
9528 */
9529 keyWord = "variableName";
9530 status = json_getStringDynamicArray(
9531 designVariableInput->value, keyWord,
9532 &designVariableRelation->numDesignVariable, &designVariableRelation->designVariableNameSet);
9533 if (status != CAPS_SUCCESS0) {
9534 // required
9535 AIM_ERROR(aimInfo, "No \"%s\" specified for Design_Variable_Relation tuple %s",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9536, __func__
, "No \"%s\" specified for Design_Variable_Relation tuple %s"
, keyWord, designVariableInput->name); }
9536 keyWord, designVariableInput->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9536, __func__
, "No \"%s\" specified for Design_Variable_Relation tuple %s"
, keyWord, designVariableInput->name); }
;
9537 goto cleanup;
9538 }
9539
9540 /*! \page feaDesignVariableRelation
9541 *
9542 * \if (NASTRAN || TACS || MASSTRAN)
9543 * <ul>
9544 * <li> <B>fieldName = "(no default)"</B> </li> <br>
9545 * 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.
9546 * 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
9547 * specifies what aspect of the Material, Property, or Element is changing.
9548 * \if (MASSTRAN)
9549 * -# <b> Material Types</b> Selected based on the material type (see \ref feaMaterial, materialType) referenced in the <c>componentName</c> above.
9550 * - <c> materialType = "Isotropic" </c>
9551 * - "density"
9552 * -# <b> Property Types</b> (see \ref feaProperty)
9553 * - <c>propertyType = "ConcentratedMass"</c>
9554 * - "mass",
9555 * - "massOffset1", "massOffset2", "massOffset2"
9556 * - "Ixx", "Iyy", "Izz", "Ixy", "Ixz", "Iyz"
9557 * - <c>propertyType = "Shell"</c>
9558 * - "membraneThickness", "massPerArea"
9559 * \else
9560 * -# <b> Material Types</b> Selected based on the material type (see \ref feaMaterial, materialType) referenced in the <c>componentName</c> above.
9561 * - <c><b> MAT1</b>, materialType = "Isotropic" </c>
9562 * - "E", "G", "NU", "RHO", "A"
9563 * - <c><b> MAT2</b>, materialType = "Anisothotropic" </c>
9564 * - "G11", "G12", "G13", "G22", "G23", "G33", "RHO", "A1", "A2", "A3"
9565 * - <c><b> MAT8</b>, materialType = "Orthotropic" </c>
9566 * - "E1", "E2", "NU12", "G12", "G1Z", "G2Z", "RHO", "A1", "A2"
9567 * - <c><b> MAT9</b>, materialType = "Anisotropic" </c>
9568 * - "G11", "G12", "G13", "G14", "G15", "G16"
9569 * - "G22", "G23", "G24", "G25", "G26"
9570 * - "G33", "G34", "G35", "G36"
9571 * - "G44", "G45", "G46"
9572 * - "G55", "G56", "G66"
9573 * - "RHO", "A1", "A2", "A3", "A4", "A5", "A6"
9574 * -# <b> Property Types</b> (see \ref feaProperty)
9575 * - <c><b> PROD</b> </c> <c>propertyType = "Rod"</c>
9576 * - "A", "J"
9577 * - <c><b> PBAR</b> </c> <c>propertyType = "Bar"</c>
9578 * - "A", "I1", "I2", "J"
9579 * - <c><b> PSHELL</b> </c> <c>propertyType = "Shell"</c>
9580 * - "T"
9581 * - <c><b> PCOMP</b> </c> <c>propertyType = "Composite"</c>
9582 * - "T1", "THETA1", "T2", "THETA2", ... "Ti", "THETAi"
9583 * - <c><b> PSOLID</b> </c> <c>propertyType = "Solid"</c>
9584 * - not supported
9585 * -# <b> Element Types</b>
9586 * - <c><b> CTRIA3, CQUAD4</b> </c> <c>propertyType = "Shell"</c>
9587 * - "ZOFFS"
9588 * \endif
9589 * </ul>
9590 * \endif
9591 */
9592 keyWord = "fieldName";
9593 status = json_getString(
9594 designVariableInput->value, keyWord,
9595 &designVariableRelation->fieldName);
9596 if (status != CAPS_SUCCESS0) {
9597 // optional
9598 }
9599
9600 /*! \page feaDesignVariableRelation
9601 *
9602 * \if (NASTRAN || TACS)
9603 * <ul>
9604 * <li> <B>fieldPosition = 0</B> </li> <br>
9605 * This input is ignored if not defined. The user may use this field instead of the <c>fieldName</c> input defined above to
9606 * relate design variables and property, material, or elements. This requires knowledge of Nastran bulk data input format for material,
9607 * property, and element input cards.
9608 * </ul>
9609 * \endif
9610 */
9611
9612 keyWord = "fieldPosition";
9613 status = json_getInteger(
9614 designVariableInput->value, keyWord,
9615 &designVariableRelation->fieldPosition);
9616 if (status != CAPS_SUCCESS0) {
9617 // optional
9618 }
9619
9620 /*! \page feaDesignVariableRelation
9621 *
9622 * \if (NASTRAN || TACS || ASTROS || MASSTRAN)
9623 * <ul>
9624 * <li> <B>constantCoeff = 0.0</B> </li> <br>
9625 * Constant term of relation.
9626 * </ul>
9627 * \endif
9628 */
9629 keyWord = "constantCoeff";
9630 status = json_getDouble(
9631 designVariableInput->value, keyWord,
9632 &designVariableRelation->constantRelationCoeff);
9633 if (status != CAPS_SUCCESS0) {
9634 // default
9635 designVariableRelation->constantRelationCoeff = 0.0;
9636 }
9637
9638 /*! \page feaDesignVariableRelation
9639 *
9640 * \if (NASTRAN || TACS || ASTROS || MASSTRAN)
9641 * <ul>
9642 * <li> <B>linearCoeff = 1.0</B> </li> <br>
9643 * Single or list of coefficients of linear relation. Must be same length as <c>variableName</c>.
9644 * </ul>
9645 * \endif
9646 */
9647 keyWord = "linearCoeff";
9648 status = json_getDoubleDynamicArray(
9649 designVariableInput->value, keyWord,
9650 &numLinearCoeff, &designVariableRelation->linearRelationCoeff);
9651
9652 if (status != CAPS_SUCCESS0) {
9653 // default
9654 numLinearCoeff = designVariableRelation->numDesignVariable;
9655 designVariableRelation->linearRelationCoeff = EG_alloc(numLinearCoeff * sizeof(double));
9656 if (designVariableRelation->linearRelationCoeff == NULL((void*)0)) {
9657 status = EGADS_MALLOC-4;
9658 goto cleanup;
9659 }
9660
9661 for (i = 0; i < numLinearCoeff; i++) {
9662 designVariableRelation->linearRelationCoeff[i] = 1.0;
9663 }
9664 }
9665
9666 if (numLinearCoeff != designVariableRelation->numDesignVariable) {
9667 AIM_ERROR(aimInfo, "Number of \"linearCoeff\" values (%d) does not match"{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9669, __func__
, "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)"
, numLinearCoeff, designVariableRelation->numDesignVariable
); }
9668 " number of \"variableName\" values (%d)",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9669, __func__
, "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)"
, numLinearCoeff, designVariableRelation->numDesignVariable
); }
9669 numLinearCoeff, designVariableRelation->numDesignVariable){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9669, __func__
, "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)"
, numLinearCoeff, designVariableRelation->numDesignVariable
); }
;
9670 status = CAPS_BADVALUE-311;
9671 goto cleanup;
9672 }
9673
9674 status = CAPS_SUCCESS0;
9675
9676cleanup:
9677
9678 AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); };
9679
9680 return status;
9681}
9682
9683// Get the design constraints from a capsTuple
9684int fea_getDesignConstraint(int numDesignConstraintTuple,
9685 capsTuple designConstraintTuple[],
9686 feaProblemStruct *feaProblem) {
9687
9688 /*! \page feaDesignConstraint FEA Design Constraints
9689 * Structure for the design constraint tuple = (`DesignConstraint Name', `Value').
9690 * 'DesignConstraint Name' defines the reference name for the design constraint being specified.
9691 * The "Value" must be a JSON String dictionary (see Section \ref jsonStringDesignConstraint).
9692 */
9693
9694 int status; //Function return
9695
9696 int i, groupIndex, attrIndex; // Indexing
9697
9698 char *keyValue = NULL((void*)0);
9699 char *keyWord = NULL((void*)0);
9700
9701 char *tempString = NULL((void*)0);
9702
9703 char **groupName = NULL((void*)0);
9704 int numGroupName = 0;
9705
9706 // Destroy our design constraints structures coming in if aren't 0 and NULL already
9707 if (feaProblem->feaDesignConstraint != NULL((void*)0)) {
9708 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
9709 status = destroy_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]);
9710 if (status != CAPS_SUCCESS0) return status;
9711 }
9712 }
9713 if (feaProblem->feaDesignConstraint != NULL((void*)0)) EG_free(feaProblem->feaDesignConstraint);
9714 feaProblem->feaDesignConstraint = NULL((void*)0);
9715 feaProblem->numDesignConstraint = 0;
9716
9717 printf("\nGetting FEA design constraints.......\n");
9718
9719 feaProblem->numDesignConstraint = numDesignConstraintTuple;
9720
9721 printf("\tNumber of design constraints - %d\n", feaProblem->numDesignConstraint);
9722
9723 if (feaProblem->numDesignConstraint > 0) {
9724 feaProblem->feaDesignConstraint = (feaDesignConstraintStruct *) EG_alloc(feaProblem->numDesignConstraint * sizeof(feaDesignConstraintStruct));
9725
9726 if (feaProblem->feaDesignConstraint == NULL((void*)0)) return EGADS_MALLOC-4;
9727
9728 } else {
9729 printf("\tNumber of design constraint values in input tuple is 0\n");
9730 return CAPS_NOTFOUND-303;
9731 }
9732
9733 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
9734 status = initiate_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]);
9735 if (status != CAPS_SUCCESS0) return status;
9736 }
9737
9738 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
9739
9740 printf("\tDesign_Constraint name - %s\n", designConstraintTuple[i].name);
9741
9742 feaProblem->feaDesignConstraint[i].name = (char *) EG_alloc(((strlen(designConstraintTuple[i].name)) + 1)*sizeof(char));
9743 if (feaProblem->feaDesignConstraint[i].name == NULL((void*)0)) return EGADS_MALLOC-4;
9744
9745 memcpy(feaProblem->feaDesignConstraint[i].name, designConstraintTuple[i].name, strlen(designConstraintTuple[i].name)*sizeof(char));
9746 feaProblem->feaDesignConstraint[i].name[strlen(designConstraintTuple[i].name)] = '\0';
9747
9748 feaProblem->feaDesignConstraint[i].designConstraintID = i + 1;
9749
9750 // Do we have a json string?
9751 if (strncmp(designConstraintTuple[i].value, "{", 1) == 0) {
9752 //printf("JSON String - %s\n", designConstraintTuple[i].value);
9753
9754 /*! \page feaDesignConstraint
9755 * \section jsonStringDesignConstraint JSON String Dictionary
9756 *
9757 * If "Value" is JSON string dictionary
9758 * \if (NASTRAN || ASTROS)
9759 * (eg. "Value" = {"groupName": "plate", "upperBound": 10.0})
9760 * \endif
9761 * the following keywords ( = default values) may be used:
9762 *
9763 * \if (NASTRAN || ASTROS)
9764 * <ul>
9765 * <li> <B>groupName = "(no default)"</B> </li> <br>
9766 * Single or list of <c>capsGroup</c> name(s)
9767 * to the design variable (e.g. "Name1" or ["Name1","Name2",...].The property (see \ref feaProperty) also
9768 * assigned to the same <c>capsGroup</c> will be automatically related to this constraint entry.
9769 * </ul>
9770 * \endif
9771 *
9772 */
9773
9774 // Get material/properties that the design constraint should be applied to
9775 keyWord = "groupName";
9776 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9777 if (status == CAPS_SUCCESS0) {
9778
9779 status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName);
9780 if (keyValue != NULL((void*)0)) {
9781 EG_free(keyValue);
9782 keyValue = NULL((void*)0);
9783 }
9784
9785 if (status != CAPS_SUCCESS0) return status;
9786
9787 feaProblem->feaDesignConstraint[i].numPropertyID = 0;
9788 for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) {
9789
9790 for (attrIndex = 0; attrIndex < feaProblem->numProperty; attrIndex++) {
9791
9792 if (strcasecmp(feaProblem->feaProperty[attrIndex].name, groupName[groupIndex]) == 0) {
9793
9794 feaProblem->feaDesignConstraint[i].numPropertyID += 1;
9795
9796 if (feaProblem->feaDesignConstraint[i].numPropertyID == 1) {
9797
9798 feaProblem->feaDesignConstraint[i].propertySetID = (int *) EG_alloc(feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9799 feaProblem->feaDesignConstraint[i].propertySetType = (int *) EG_alloc(feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9800
9801 } else {
9802
9803 feaProblem->feaDesignConstraint[i].propertySetID = (int *) EG_reall(feaProblem->feaDesignConstraint[i].propertySetID,
9804 feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9805 feaProblem->feaDesignConstraint[i].propertySetType = (int *) EG_reall(feaProblem->feaDesignConstraint[i].propertySetType,
9806 feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int));
9807
9808 }
9809
9810 if (feaProblem->feaDesignConstraint[i].propertySetID == NULL((void*)0) ||
9811 feaProblem->feaDesignConstraint[i].propertySetType == NULL((void*)0) ) {
9812
9813 status = string_freeArray(numGroupName, &groupName);
9814 if (status != CAPS_SUCCESS0) return status;
9815 groupName = NULL((void*)0);
9816 return EGADS_MALLOC-4;
9817 }
9818
9819 feaProblem->feaDesignConstraint[i].propertySetID[feaProblem->feaDesignConstraint[i].numPropertyID-1] = feaProblem->feaProperty[attrIndex].propertyID;
9820 feaProblem->feaDesignConstraint[i].propertySetType[feaProblem->feaDesignConstraint[i].numPropertyID-1] = feaProblem->feaProperty[attrIndex].propertyType;
9821
9822 break;
9823 }
9824 }
9825
9826 if (feaProblem->feaDesignConstraint[i].numPropertyID != groupIndex+1) {
9827
9828 printf("\tWarning: DesignConstraint property name, %s, not found in feaProperty structure\n", groupName[groupIndex]);
9829
9830 }
9831 }
9832
9833 status = string_freeArray(numGroupName, &groupName);
9834 if (status != CAPS_SUCCESS0) return status;
9835 groupName = NULL((void*)0);
9836 }
9837
9838 //Fill up designConstraint properties
9839 /*! \page feaDesignConstraint
9840 *
9841 * \if (NASTRAN || ASTROS)
9842 * <ul>
9843 * <li> <B> constraintType = "Property" </B> </li> <br>
9844 * The type of design constraint. Options: "Property", "Flutter"
9845 * </ul>
9846 * \endif
9847 */
9848 keyWord = "constraintType";
9849 status = json_getString(
9850 designConstraintTuple[i].value, keyWord, &keyValue);
9851 if (status == CAPS_SUCCESS0) {
9852 if (strcasecmp(keyValue, "Property") == 0)
9853 feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon;
9854 else if (strcasecmp(keyValue, "Flutter") == 0)
9855 feaProblem->feaDesignConstraint[i].designConstraintType = FlutterDesignCon;
9856 else {
9857 PRINT_WARNING("Unknown constraintType %s... defaulting to Property.", keyValue)fprintf(stderr, "[ WARNING ] " "Unknown constraintType %s... defaulting to Property."
"\n", keyValue);
;
9858 feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon;
9859 }
9860 }
9861 else {
9862 feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon;
9863 }
9864
9865 if (keyValue != NULL((void*)0)) EG_free(keyValue);
9866 keyValue = NULL((void*)0);
9867
9868 /*! \page feaDesignConstraint
9869 *
9870 * \if (NASTRAN || ASTROS)
9871 * <ul>
9872 * <li> <B>lowerBound = 0.0</B> </li> <br>
9873 * Lower bound for the design constraint.
9874 * </ul>
9875 * \endif
9876 *
9877 */
9878 keyWord = "lowerBound";
9879 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9880 if (status == CAPS_SUCCESS0) {
9881
9882 status = string_toDouble(keyValue, &feaProblem->feaDesignConstraint[i].lowerBound);
9883 if (keyValue != NULL((void*)0)) {
9884 EG_free(keyValue);
9885 keyValue = NULL((void*)0);
9886 }
9887 if (status != CAPS_SUCCESS0) return status;
9888 }
9889
9890 /*! \page feaDesignConstraint
9891 *
9892 * \if (NASTRAN || ASTROS)
9893 * <ul>
9894 * <li> <B>upperBound = 0.0</B> </li> <br>
9895 * Upper bound for the design constraint.
9896 * </ul>
9897 * \endif
9898 *
9899 */
9900 keyWord = "upperBound";
9901 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9902 if (status == CAPS_SUCCESS0) {
9903
9904 status = string_toDouble(keyValue, &feaProblem->feaDesignConstraint[i].upperBound);
9905 if (keyValue != NULL((void*)0)) {
9906 EG_free(keyValue);
9907 keyValue = NULL((void*)0);
9908 }
9909 if (status != CAPS_SUCCESS0) return status;
9910 }
9911
9912 /*! \page feaDesignConstraint
9913 *
9914 * \if (NASTRAN || ASTROS)
9915 * <ul>
9916 * <li> <B>responseType = "(no default)"</B> </li> <br>
9917 * Response type options for DRESP1 Entry (see Nastran manual).
9918 * - Implemented Options
9919 * -# <c>STRESS</c>, for <c>propertyType = "Rod" or "Shell"</c> (see \ref feaProperty)
9920 * -# <c>CFAILURE</c>, for <c>propertyType = "Composite"</c> (see \ref feaProperty)
9921 * </ul>
9922 * \endif
9923 *
9924 */
9925 keyWord = "responseType";
9926 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9927 if (status == CAPS_SUCCESS0) {
9928
9929 tempString = string_removeQuotation(keyValue);
9930
9931 feaProblem->feaDesignConstraint[i].responseType = EG_alloc((strlen(tempString) + 1)*sizeof(char));
9932 if(feaProblem->feaDesignConstraint[i].responseType == NULL((void*)0)) {
9933 if (tempString != NULL((void*)0)) EG_free(tempString);
9934
9935 return EGADS_MALLOC-4;
9936 }
9937
9938 memcpy(feaProblem->feaDesignConstraint[i].responseType, tempString, strlen(tempString)*sizeof(char));
9939 feaProblem->feaDesignConstraint[i].responseType[strlen(tempString)] = '\0';
9940
9941 if (keyValue != NULL((void*)0)) {
9942 EG_free(keyValue);
9943 keyValue = NULL((void*)0);
9944 }
9945
9946 if (tempString != NULL((void*)0)) {
9947 EG_free(tempString);
9948 tempString = NULL((void*)0);
9949 }
9950 }
9951
9952 /*! \page feaDesignConstraint
9953 *
9954 * \if (NASTRAN || ASTROS)
9955 * <ul>
9956 * <li> <B>fieldName = "(no default)"</B> </li> <br>
9957 * For constraints, this field is only used currently when applying constraints to composites. This field is used to identify
9958 * the specific lamina in a stacking sequence that a constraint is being applied too. Note if the user has design variables
9959 * for both THEATA1 and T1 it is likely that only a single constraint on the first lamina is required. For this reason, the user
9960 * can simply enter LAMINA1 in addition to the possible entries defined in the \ref feaDesignVariable section.
9961 * Additionally, the <c>fieldPosition</c> integer entry below can be used. In this case <c>"LAMINA1" = 1</c>.
9962 *
9963 * * -# <b> Property Types</b> (see \ref feaProperty)
9964 * - <c><b> PCOMP</b> </c> <c>propertyType = "Composite"</c>
9965 * - "T1", "THETA1", "T2", "THETA2", ... "Ti", "THETAi"
9966 * - "LAMINA1", "LAMINA2", ... "LAMINAi"
9967 *
9968 * </ul>
9969 * \endif
9970 */
9971
9972 keyWord = "fieldName";
9973 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
9974 if (status == CAPS_SUCCESS0) {
9975
9976 tempString = string_removeQuotation(keyValue);
9977
9978 feaProblem->feaDesignConstraint[i].fieldName = EG_alloc((strlen(tempString) + 1)*sizeof(char));
9979 if(feaProblem->feaDesignConstraint[i].fieldName == NULL((void*)0)) {
9980 if (tempString != NULL((void*)0)) EG_free(tempString);
9981
9982 return EGADS_MALLOC-4;
9983 }
9984
9985 memcpy(feaProblem->feaDesignConstraint[i].fieldName, tempString, strlen(tempString)*sizeof(char));
9986 feaProblem->feaDesignConstraint[i].fieldName[strlen(tempString)] = '\0';
9987
9988 if (keyValue != NULL((void*)0)) {
9989 EG_free(keyValue);
9990 keyValue = NULL((void*)0);
9991 }
9992
9993 if (tempString != NULL((void*)0)) {
9994 EG_free(tempString);
9995 tempString = NULL((void*)0);
9996 }
9997 }
9998
9999 /*! \page feaDesignConstraint
10000 *
10001 * \if (NASTRAN || ASTROS)
10002 * <ul>
10003 * <li> <B>fieldPosition = 0</B> </li> <br>
10004 * This input is ignored if not defined. The user may use this field instead of the <c>fieldName</c> input defined above to
10005 * identify a specific lamina in a composite stacking sequence where a constraint is applied. Please read the <c>fieldName</c>
10006 * information above for more information.
10007 * </ul>
10008 * \endif
10009 */
10010
10011 keyWord = "fieldPosition";
10012 status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue);
10013 if (status == CAPS_SUCCESS0) {
10014
10015 status = string_toInteger(keyValue, &feaProblem->feaDesignConstraint[i].fieldPosition);
10016 if (keyValue != NULL((void*)0)) {
10017 EG_free(keyValue);
10018 keyValue = NULL((void*)0);
10019 }
10020 if (status != CAPS_SUCCESS0) return status;
10021 }
10022
10023 /*! \page feaDesignConstraint
10024 *
10025 * \if ASTROS
10026 * <ul>
10027 * <li> <B>velocityType = "TRUE" </B> </li> <br>
10028 * The nature of the velocity values defined with "velocity" keyword. Can be either "TRUE" for true velocity
10029 * or "EQUIV" for equivalent air speed.
10030 * </ul>
10031 * \endif
10032 */
10033 keyWord = "velocityType";
10034 status = json_getString(
10035 designConstraintTuple[i].value, keyWord,
10036 &feaProblem->feaDesignConstraint[i].velocityType);
10037 if (status != CAPS_SUCCESS0) {
10038 feaProblem->feaDesignConstraint[i].velocityType = EG_strdup("TRUE");
10039 }
10040
10041 /*! \page feaDesignConstraint
10042 *
10043 * \if ASTROS
10044 * <ul>
10045 * <li> <B>scalingFactor = 0.10 </B> </li> <br>
10046 * The constraint scaling factor.
10047 * </ul>
10048 * \endif
10049 */
10050 keyWord = "scalingFactor";
10051 status = json_getDouble(
10052 designConstraintTuple[i].value, keyWord,
10053 &feaProblem->feaDesignConstraint[i].scalingFactor);
10054 if (status != CAPS_SUCCESS0) {
10055 feaProblem->feaDesignConstraint[i].scalingFactor = 0.10;
10056 }
10057
10058 /*! \page feaDesignConstraint
10059 *
10060 * \if ASTROS
10061 * <ul>
10062 * <li> <B>velocity = (No Default) </B> </li> <br>
10063 * The velocity values for flutter constraint.
10064 * Must be an array with equal length to defined "damping" values.
10065 * </ul>
10066 * \endif
10067 */
10068 keyWord = "velocity";
10069 status = json_getDoubleDynamicArray(
10070 designConstraintTuple[i].value, keyWord,
10071 &feaProblem->feaDesignConstraint[i].numVelocity,
10072 &feaProblem->feaDesignConstraint[i].velocity);
10073 if (status != CAPS_SUCCESS0) {
10074 // only required if constraintType == FlutterCon
10075 }
10076
10077 /*! \page feaDesignConstraint
10078 *
10079 * \if ASTROS
10080 * <ul>
10081 * <li> <B>damping = (No Default) </B> </li> <br>
10082 * The damping values for flutter constraint.
10083 * Must be an array with equal length to defined "velocity" values.
10084 * </ul>
10085 * \endif
10086 */
10087 keyWord = "damping";
10088 status = json_getDoubleDynamicArray(
10089 designConstraintTuple[i].value, keyWord,
10090 &feaProblem->feaDesignConstraint[i].numDamping,
10091 &feaProblem->feaDesignConstraint[i].damping);
10092 if (status != CAPS_SUCCESS0) {
10093 // only required if constraintType == FlutterCon
10094 }
10095
10096 } else {
10097
10098 printf("\tError: Design_Constraint tuple value is expected to be a JSON string\n");
10099 return CAPS_BADVALUE-311;
10100 // CALL designConstraint look up
10101
10102 }
10103 }
10104
10105 if (keyValue != NULL((void*)0)) {
10106 EG_free(keyValue);
10107 keyValue = NULL((void*)0);
10108 }
10109
10110 printf("Done getting FEA design constraints\n");
10111 return CAPS_SUCCESS0;
10112}
10113
10114// Get the design constraints from a capsTuple
10115int fea_getOptimizationControl(char *optimizationControlInput,
10116 feaProblemStruct *feaProblem) {
10117
10118 /*! \page feaOptimizationControl FEA Optimization Control
10119 * Structure for the optimization control dictionary = `Value'.
10120 * The "Value" must be a JSON String dictionary (see Section \ref jsonStringDesignConstraint).
10121 */
10122
10123 int status; //Function return
10124
10125 char *keyValue = NULL((void*)0);
10126 char *keyWord = NULL((void*)0);
10127
10128 // Destroy our optimization control structures coming in if aren't 0 and NULL already
10129 status = destroy_feaOptimzationControlStruct(&feaProblem->feaOptimizationControl);
10130 if (status != CAPS_SUCCESS0) return status;
10131
10132 printf("\nGetting FEA optimization control.......\n");
10133
10134 status = initiate_feaOptimizationControlStruct(&feaProblem->feaOptimizationControl);
10135 if (status != CAPS_SUCCESS0) return status;
10136
10137 if (optimizationControlInput == NULL((void*)0)) {
10138 optimizationControlInput = "{}";
10139 }
10140
10141 // Do we have a json string?
10142 if (strncmp(optimizationControlInput, "{", 1) == 0) {
10143
10144 /*! \page feaOptimizationControl
10145 *
10146 * \if NASTRAN
10147 * <ul>
10148 * <li> <B>fullyStressedDesign = 0</B> </li> <br>
10149 * Number of iterations with fully stressed design.
10150 * </ul>
10151 * \endif
10152 *
10153 */
10154 keyWord = "fullyStressedDesign";
10155 status = json_getInteger(
10156 optimizationControlInput, keyWord,
10157 &feaProblem->feaOptimizationControl.fullyStressedDesign);
10158
10159 // Set default value if value is not in JSON
10160 if (status != CAPS_SUCCESS0) {
10161 feaProblem->feaOptimizationControl.fullyStressedDesign = 0;
10162 }
10163
10164 /*! \page feaOptimizationControl
10165 *
10166 * \if NASTRAN
10167 * <ul>
10168 * <li> <B>mathProgramming = 30</B> </li> <br>
10169 * Number of iterations for math programming methods.
10170 * </ul>
10171 * \endif
10172 *
10173 */
10174 keyWord = "mathProgramming";
10175 status = json_getInteger(
10176 optimizationControlInput, keyWord,
10177 &feaProblem->feaOptimizationControl.mathProgramming);
10178
10179 // Set default value if value is not in JSON
10180 if (status != CAPS_SUCCESS0) {
10181 feaProblem->feaOptimizationControl.mathProgramming = 30;
10182 }
10183
10184 /*! \page feaOptimizationControl
10185 *
10186 * \if NASTRAN
10187 * <ul>
10188 * <li> <B>maxIter = 30</B> </li> <br>
10189 * Maximum number of optimization iterations.
10190 * </ul>
10191 * \endif
10192 *
10193 */
10194 keyWord = "maxIter";
10195 status = json_getInteger(
10196 optimizationControlInput, keyWord,
10197 &feaProblem->feaOptimizationControl.maxIter);
10198
10199 // Set default value if value is not in JSON
10200 if (status != CAPS_SUCCESS0) {
10201 feaProblem->feaOptimizationControl.maxIter = 30;
10202 }
10203
10204 /*! \page feaOptimizationControl
10205 *
10206 * \if NASTRAN
10207 * <ul>
10208 * <li> <B>constraintRetention = 1.5</B> </li> <br>
10209 * Constraint retention factor.
10210 * Will be at least 1.5 times the number of design variables
10211 * </ul>
10212 * \endif
10213 *
10214 */
10215 keyWord = "constraintRetention";
10216 status = json_getDouble(
10217 optimizationControlInput, keyWord,
10218 &feaProblem->feaOptimizationControl.constraintRetention);
10219
10220 // Set default value if value is not in JSON
10221 if (status != CAPS_SUCCESS0) {
10222 feaProblem->feaOptimizationControl.constraintRetention = 1.5;
10223 }
10224
10225 /*! \page feaOptimizationControl
10226 *
10227 * \if NASTRAN
10228 * <ul>
10229 * <li> <B>eps = 1.0</B> </li> <br>
10230 * Constraint retention parameter in which all constraints having a
10231 * value greater than "eps" will be considered active.
10232 *
10233 * </ul>
10234 * \endif
10235 *
10236 */
10237 keyWord = "eps";
10238 status = json_getDouble(
10239 optimizationControlInput, keyWord,
10240 &feaProblem->feaOptimizationControl.eps);
10241
10242 // Set default value if value is not in JSON
10243 if (status != CAPS_SUCCESS0) {
10244 feaProblem->feaOptimizationControl.eps = 1.0;
10245 }
10246
10247 /*! \page feaOptimizationControl
10248 *
10249 * \if NASTRAN
10250 * <ul>
10251 * <li> <B>moveLimit = 1.0</B> </li> <br>
10252 * Move limit bound.
10253 * </ul>
10254 * \endif
10255 *
10256 */
10257 keyWord = "moveLimit";
10258 status = json_getDouble(
10259 optimizationControlInput, keyWord,
10260 &feaProblem->feaOptimizationControl.moveLimit);
10261
10262 // Set default value if value is not in JSON
10263 if (status != CAPS_SUCCESS0) {
10264 feaProblem->feaOptimizationControl.moveLimit = 1.5;
10265 }
10266
10267 } else {
10268
10269 printf("\tError: OptimizationControl tuple value is expected to be a JSON string\n");
10270 return CAPS_BADVALUE-311;
10271
10272 }
10273
10274 if (keyValue != NULL((void*)0)) {
10275 EG_free(keyValue);
10276 keyValue = NULL((void*)0);
10277 }
10278
10279 printf("Done getting FEA Optimization Control\n");
10280 return CAPS_SUCCESS0;
10281}
10282
10283// Get the coordinate system information from the bodies and an attribute map (of CoordSystem)
10284int fea_getCoordSystem(int numBody,
10285 ego bodies[],
10286 mapAttrToIndexStruct coordSystemMap,
10287 int *numCoordSystem,
10288 feaCoordSystemStruct *feaCoordSystem[]) {
10289
10290 int status; // Function return
10291
10292 int i, body, face, edge, node; // Indexing
10293
10294 int numFace = 0, numEdge = 0, numNode = 0; // Number of egos
10295 ego *faces = NULL((void*)0), *edges = NULL((void*)0), *nodes = NULL((void*)0); // Geometry
10296
10297 int atype, alen; // EGADS return variables
10298 const int *ints;
10299 const double *reals;
10300 const char *string;
10301
10302 int found = (int) false0;
10303
10304 // Destroy our CoordSystem structures coming in if aren't 0 and NULL already
10305 if (*feaCoordSystem != NULL((void*)0)) {
10306 for (i = 0; i < *numCoordSystem; i++) {
10307 status = destroy_feaCoordSystemStruct(&(*feaCoordSystem)[i]);
10308 if (status != CAPS_SUCCESS0) return status;
10309 }
10310 }
10311 if (*feaCoordSystem != NULL((void*)0)) EG_free(*feaCoordSystem);
10312 *feaCoordSystem = NULL((void*)0);
10313 *numCoordSystem = 0;
10314
10315 printf("\nGetting FEA coordinate systems.......\n");
10316
10317 *numCoordSystem = coordSystemMap.numAttribute;
10318 printf("\tNumber of coordinate systems - %d\n", *numCoordSystem);
10319
10320 if (*numCoordSystem > 0) {
10321 *feaCoordSystem = (feaCoordSystemStruct *) EG_alloc((*numCoordSystem)*sizeof(feaCoordSystemStruct));
10322 if (*feaCoordSystem == NULL((void*)0)) return EGADS_MALLOC-4;
10323
10324 } else {
10325 printf("\tNo coordinate systems found - defaulting to global\n");
10326 return CAPS_SUCCESS0;
10327 }
10328
10329 for (i = 0; i < *numCoordSystem; i++) {
10330 status = initiate_feaCoordSystemStruct(&(*feaCoordSystem)[i]);
10331 if (status != CAPS_SUCCESS0) return status;
10332 }
10333
10334 for (i = 0; i < *numCoordSystem; i++) {
10335
10336 if (faces != NULL((void*)0)) EG_free(faces);
10337 if (edges != NULL((void*)0)) EG_free(edges);
10338 if (nodes != NULL((void*)0)) EG_free(nodes);
10339
10340 faces = NULL((void*)0);
10341 edges = NULL((void*)0);
10342 nodes = NULL((void*)0);
10343
10344 printf("\tCoordinate system name - %s\n", coordSystemMap.attributeName[i]);
10345
10346 (*feaCoordSystem)[i].name = EG_strdup(coordSystemMap.attributeName[i]);
10347 if ((*feaCoordSystem)[i].name == NULL((void*)0)) { status = EGADS_MALLOC-4; goto cleanup; }
10348
10349 (*feaCoordSystem)[i].coordSystemID = coordSystemMap.attributeIndex[i];
10350
10351 (*feaCoordSystem)[i].refCoordSystemID = 0;
10352
10353 (*feaCoordSystem)[i].coordSystemType = RectangularCoordSystem;
10354
10355 found = (int) false0;
10356
10357 // Search through bodies
10358 for (body = 0; body < numBody; body++) {
10359
10360 // Look at the body level
10361 status = EG_attributeRet(bodies[body], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10362 if (status != EGADS_SUCCESS0 &&
10363 status != EGADS_NOTFOUND-1) goto cleanup;
10364
10365 if (atype == ATTRCSYS12) {
10366
10367 // Save the origin
10368 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10369 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10370 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10371
10372 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10373 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10374 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10375
10376 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10377 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10378 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10379
10380 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10381 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10382 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10383
10384 found = (int) true1;
10385 }
10386
10387 if (found == (int) true1) break;
10388
10389 // Determine the number of faces, edges, and nodes
10390 status = EG_getBodyTopos(bodies[body], NULL((void*)0), FACE23, &numFace, &faces);
10391 if (status != EGADS_SUCCESS0) goto cleanup;
10392
10393 status = EG_getBodyTopos(bodies[body], NULL((void*)0), EDGE21, &numEdge, &edges);
10394 if (status != EGADS_SUCCESS0) goto cleanup;
10395
10396 status = EG_getBodyTopos(bodies[body], NULL((void*)0), NODE20, &numNode, &nodes);
10397 if (status != EGADS_SUCCESS0) goto cleanup;
10398
10399 // Loop through faces
10400 for (face = 0; face < numFace; face++) {
10401
10402 status = EG_attributeRet(faces[face], (const char *) (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10403
10404 if (status == EGADS_NOTFOUND-1) continue;
10405 if (status != EGADS_SUCCESS0) goto cleanup;
10406
10407 if (atype == ATTRCSYS12) {
10408
10409 // Save the origin
10410 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10411 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10412 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10413
10414 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10415 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10416 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10417
10418 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10419 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10420 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10421
10422 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10423 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10424 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10425
10426 found = (int) true1;
10427
10428 break;
10429 }
10430 } // End face loop
10431
10432 if (found == (int) true1) break;
10433
10434 // Loop through edges
10435 for (edge = 0; edge < numEdge; edge++) {
10436
10437 status = EG_attributeRet(edges[edge], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10438
10439 if (status == EGADS_NOTFOUND-1) continue;
10440 if (status != EGADS_SUCCESS0) goto cleanup;
10441
10442 if (atype == ATTRCSYS12) {
10443
10444 // Save the origin
10445 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10446 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10447 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10448
10449 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10450 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10451 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10452
10453 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10454 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10455 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10456
10457 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10458 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10459 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10460
10461 found = (int) true1;
10462
10463 break;
10464 }
10465
10466 } // End edge loop
10467
10468 if (found == (int) true1) break;
10469
10470 // Loop through nodes
10471 for (node = 0; node < numNode; node++) {
10472
10473 status = EG_attributeRet(nodes[node], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string);
10474
10475 if (status == EGADS_NOTFOUND-1) continue;
10476 if (status != EGADS_SUCCESS0) goto cleanup;
10477
10478 if (atype == ATTRCSYS12) {
10479
10480 // Save the origin
10481 (*feaCoordSystem)[i].origin[0] = reals[alen+0];
10482 (*feaCoordSystem)[i].origin[1] = reals[alen+1];
10483 (*feaCoordSystem)[i].origin[2] = reals[alen+2];
10484
10485 (*feaCoordSystem)[i].normal1[0] = reals[alen+3];
10486 (*feaCoordSystem)[i].normal1[1] = reals[alen+4];
10487 (*feaCoordSystem)[i].normal1[2] = reals[alen+5];
10488
10489 (*feaCoordSystem)[i].normal2[0] = reals[alen+6];
10490 (*feaCoordSystem)[i].normal2[1] = reals[alen+7];
10491 (*feaCoordSystem)[i].normal2[2] = reals[alen+8];
10492
10493 (*feaCoordSystem)[i].normal3[0] = reals[alen+9];
10494 (*feaCoordSystem)[i].normal3[1] = reals[alen+10];
10495 (*feaCoordSystem)[i].normal3[2] = reals[alen+11];
10496
10497 found = (int) true1;
10498
10499 break;
10500 }
10501 } // End node loop
10502
10503 EG_free(faces); faces = NULL((void*)0);
10504 EG_free(edges); edges = NULL((void*)0);
10505 EG_free(nodes); nodes = NULL((void*)0);
10506
10507 if (found == (int) true1) break;
10508
10509 } // End body loop
10510 }
10511
10512 status = CAPS_SUCCESS0;
10513
10514 cleanup:
10515
10516 if (status != CAPS_SUCCESS0) printf("\tError in fea_getCoordSystem = %d\n", status);
10517
10518 EG_free(faces);
10519 EG_free(edges);
10520 EG_free(nodes);
10521
10522 return status;
10523}
10524
10525// Get the design equations from a capsTuple
10526int fea_getDesignEquation(int numEquationTuple,
10527 capsTuple equationTuple[],
10528 feaProblemStruct *feaProblem) {
10529
10530 /*! \page feaDesignEquation FEA Design Equations
10531 * Structure for the design equation tuple = ("DesignEquation Name", ["Value1", ... , "ValueN"]).
10532 * "DesignEquation Name" defines the reference name for the design equation being specified.
10533 * This string will be used in the FEA input directly. The values "Value1", ... , "ValueN" are a
10534 * list of strings containing the equation defintions.
10535 * (see Section \ref tupleValueDesignEquation).
10536 *
10537 */
10538 int i, status;
10539
10540 feaDesignEquationStruct *equation;
10541
10542 // Ensure we are starting with no equations
10543 if (feaProblem->feaEquation != NULL((void*)0)) {
10544 for (i = 0; i < feaProblem->numEquation; i++) {
10545 status = destroy_feaDesignEquationStruct(&feaProblem->feaEquation[i]);
10546 if (status != CAPS_SUCCESS0) return status;
10547 }
10548 EG_free(feaProblem->feaEquation);
10549 }
10550 feaProblem->numEquation = 0;
10551 feaProblem->feaEquation = NULL((void*)0);
10552
10553 printf("\nGetting Equations.......\n");
10554
10555 feaProblem->numEquation = numEquationTuple;
10556 printf("\tNumber of Equations - %d\n", feaProblem->numEquation);
10557
10558 if (feaProblem->numEquation > 0) {
10559
10560 feaProblem->feaEquation = EG_alloc(
10561 feaProblem->numEquation * sizeof(feaDesignEquationStruct));
10562 if (feaProblem->feaEquation == NULL((void*)0)) {
10563 return EGADS_MALLOC-4;
10564 }
10565
10566 } else {
10567 printf("\tNumber of equations in Analysis tuple is %d\n",
10568 feaProblem->numEquation);
10569 return CAPS_NOTFOUND-303;
10570 }
10571
10572 // for each analysis equation tuple
10573 for (i = 0; i < feaProblem->numEquation; i++) {
10574
10575 printf("\tDesign_Equation name - %s\n", equationTuple[i].name);
10576
10577 equation = &feaProblem->feaEquation[i];
10578
10579 // initiate equation structure
10580 status = initiate_feaDesignEquationStruct(equation);
10581 if (status != CAPS_SUCCESS0) return status;
10582
10583 // set name
10584 equation->name = EG_strdup(equationTuple[i].name);
10585
10586 // set equation ID
10587 equation->equationID = i+1;
10588
10589 /*! \page feaDesignEquation
10590 * \section tupleValueDesignEquation List of equation strings
10591 *
10592 * Each design equation tuple value is a list of strings containing the equation definitions
10593 * \if NASTRAN
10594 * (eg. ["dispsum3(s1,s2,s3)=sum(s1,s2,s3)"]
10595 * \endif
10596 *
10597 */
10598 // set the equation array
10599 status = string_toStringDynamicArray(
10600 equationTuple[i].value,
10601 &equation->equationArraySize,
10602 &equation->equationArray);
10603
10604 if (status != CAPS_SUCCESS0) return status;
10605 }
10606
10607 return CAPS_SUCCESS0;
10608}
10609
10610// Get the design table constants from a capsTuple
10611int fea_getDesignTable(int numConstantTuple,
10612 capsTuple constantTuple[],
10613 feaProblemStruct *feaProblem) {
10614
10615
10616 /*! \page feaDesignTable FEA Table Constants
10617 * Structure for the table constant tuple = ("TableConstant Name", "Value").
10618 * "TableConstant Name" defines the reference name for the table constant being specified.
10619 * This string will be used in the FEA input directly. The "Value" is the value of the
10620 * table constant.
10621 * \if NASTRAN
10622 * In Nastran the TableConstant Name will be the LABLi used in the DTABLE input.
10623 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
10624 *
10625 * - <c>DTABLE LABL1 VALU1 LABL2 VALU2 LABL3 VALU3 -etc- </c>
10626 * \endif
10627 *
10628 */
10629 int i, status;
10630
10631 feaDesignTableStruct *table = &feaProblem->feaDesignTable;
10632
10633 // Ensure we are starting with no constants
10634 status = destroy_feaDesignTableStruct(table);
10635 if (status != CAPS_SUCCESS0) return status;
10636
10637 printf("\nGetting Design Table Constants.......\n");
10638
10639 table->numConstant = numConstantTuple;
10640 printf("\tNumber of Design Table Constants - %d\n", table->numConstant);
10641
10642 if (table->numConstant > 0) {
10643
10644 table->constantLabel = EG_alloc(table->numConstant * sizeof(char *));
10645 if (table->constantLabel == NULL((void*)0)) {
10646 return EGADS_MALLOC-4;
10647 }
10648
10649 table->constantValue = EG_alloc(table->numConstant * sizeof(double));
10650 if (table->constantValue == NULL((void*)0)) {
10651 return EGADS_MALLOC-4;
10652 }
10653
10654 } else {
10655 printf("\tNumber of design table constants in Analysis tuple is %d\n",
10656 table->numConstant);
10657 return CAPS_NOTFOUND-303;
10658 }
10659
10660 // for each analysis table constant tuple
10661 for (i = 0; i < table->numConstant; i++) {
10662
10663 printf("\tDesign_Table - %s: %s\n",
10664 constantTuple[i].name, constantTuple[i].value);
10665
10666 // set constant label
10667 // TODO: ensure label <= 8 chars
10668 table->constantLabel[i] = EG_strdup(constantTuple[i].name);
10669
10670 // set constant value
10671 status = string_toDouble(constantTuple[i].value, &table->constantValue[i]);
10672 if (status != CAPS_SUCCESS0) return status;
10673 }
10674
10675 return CAPS_SUCCESS0;
10676}
10677
10678// Function used by fea_getDesignResponse to determine which nodes are in response group
10679static int _matchResponseNode(meshNodeStruct *node, void *responseIndex) {
10680
10681 feaMeshDataStruct *feaData;
10682
10683 if (node->analysisType == MeshStructure) {
10684
10685 feaData = (feaMeshDataStruct *) node->analysisData;
10686
10687 if (feaData->responseIndex == *((int *) responseIndex)) {
10688 return (int) true1;
10689 }
10690 }
10691 return (int) false0;
10692}
10693
10694int fea_getDesignResponse(/*@unused@*/ void *aimInfo,
10695 int numDesignResponseTuple,
10696 capsTuple designResponseTuple[],
10697 mapAttrToIndexStruct *responseMap,
10698 feaProblemStruct *feaProblem) {
10699
10700 /*! \page feaDesignResponse FEA Design Responses
10701 * Structure for the design response tuple = ("DesignResponse Name", "Value").
10702 * "DesignResponse Name" defines the reference name for the design response being specified.
10703 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
10704 * (see Section \ref jsonStringDesignResponse).
10705 * \if NASTRAN
10706 * In Nastran the DesignResponse Name will be the LABEL used in the DRESP1 input.
10707 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
10708 *
10709 * - <c>DRESP1 ID LABEL RTYPE PTYPE REGION ATTA ATTB ATT1\n ATT2 -etc-</c>
10710 * \endif
10711 *
10712 */
10713 int i, status;
10714
10715 int attrIndex;
10716
10717 char *keyword;
10718 char *groupName = NULL((void*)0);
10719
10720 int numNode;
10721 meshNodeStruct **nodeSet = NULL((void*)0);
10722
10723 feaDesignResponseStruct *response;
10724
10725 // Ensure we are starting with no design responses
10726 if (feaProblem->feaDesignResponse != NULL((void*)0)) {
10727 for (i = 0; i < feaProblem->numDesignResponse; i++) {
10728 status = destroy_feaDesignResponseStruct(&feaProblem->feaDesignResponse[i]);
10729 if (status != CAPS_SUCCESS0) return status;
10730 }
10731 EG_free(feaProblem->feaDesignResponse);
10732 }
10733 feaProblem->numDesignResponse = 0;
10734 feaProblem->feaDesignResponse = NULL((void*)0);
10735
10736 printf("\nGetting Design Responses.......\n");
10737
10738 feaProblem->numDesignResponse = numDesignResponseTuple;
10739 printf("\tNumber of Design Responses - %d\n", feaProblem->numDesignResponse);
10740
10741 if (feaProblem->numDesignResponse > 0) {
10742
10743 feaProblem->feaDesignResponse = EG_alloc(
10744 feaProblem->numDesignResponse * sizeof(feaDesignResponseStruct));
10745 if (feaProblem->feaDesignResponse == NULL((void*)0)) {
10746 return EGADS_MALLOC-4;
10747 }
10748
10749 } else {
10750 printf("\tNumber of design responses in Analysis tuple is %d\n",
10751 feaProblem->numDesignResponse);
10752 return CAPS_NOTFOUND-303;
10753 }
10754
10755 // for each analysis design response tuple
10756 for (i = 0; i < feaProblem->numDesignResponse; i++) {
10757
10758 printf("\tDesign_Response name - %s\n", designResponseTuple[i].name);
10759
10760 response = &feaProblem->feaDesignResponse[i];
10761
10762 // initiate design response structure
10763 status = initiate_feaDesignResponseStruct(response);
10764 if (status != CAPS_SUCCESS0) return status;
10765
10766 // set name
10767 response->name = EG_strdup(designResponseTuple[i].name);
10768
10769 // set response ID
10770 response->responseID = i+1;
10771
10772 /*! \page feaDesignResponse
10773 * \section jsonStringDesignResponse JSON String Dictionary
10774 *
10775 * If "Value" is JSON string dictionary
10776 * \if NASTRAN
10777 * (eg. "Value" = {"responseType": "DISP", groupName": "plate", "component": 3})
10778 * \endif
10779 * the following keywords ( = default values) may be used:
10780 *
10781 */
10782 // make sure design response tuple value is json string
10783 if (!json_isDict(designResponseTuple[i].value)) {
10784 AIM_ERROR(aimInfo,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10785, __func__
, "'Design_Response' tuple value must be a JSON dictionary");
}
10785 "'Design_Response' tuple value must be a JSON dictionary"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10785, __func__
, "'Design_Response' tuple value must be a JSON dictionary");
}
;
10786 return CAPS_BADVALUE-311;
10787 }
10788
10789 /*! \page feaDesignResponse
10790 *
10791 * \if NASTRAN
10792 * <ul>
10793 * <li> <B>responseType</B> </li> <br>
10794 * Type of design sensitivity response. For options,
10795 * see NASTRAN User Guide DRESP1 Design Sensitivity Response Attributes table.
10796 * </ul>
10797 * \endif
10798 */
10799 keyword = "responseType";
10800 status = json_getString(
10801 designResponseTuple[i].value, keyword, &response->responseType);
10802 if (status != CAPS_SUCCESS0) {
10803 AIM_ERROR(aimInfo, "Missing required entry \"responseType\" "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10804, __func__
, "Missing required entry \"responseType\" " "in 'Design_Response' tuple value"
); }
10804 "in 'Design_Response' tuple value"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10804, __func__
, "Missing required entry \"responseType\" " "in 'Design_Response' tuple value"
); }
;
10805 return status;
10806 }
10807
10808 // keyword = "propertyType";
10809 // status = json_getString(
10810 // designResponseTuple[i].value, keyword, &response->propertyType);
10811 // if (status != CAPS_SUCCESS) {
10812 // // optional
10813 // }
10814
10815 /*! \page feaDesignResponse
10816 *
10817 * \if NASTRAN
10818 * <ul>
10819 * <li> <B>component = "(no default)"</B> </li> <br>
10820 * Component flag.
10821 * </ul>
10822 * \endif
10823 */
10824 keyword = "component";
10825 status = json_getInteger(
10826 designResponseTuple[i].value, keyword, &response->component);
10827 if (status != CAPS_SUCCESS0) {
10828 // optional
10829 }
10830
10831 // TODO: temporary input
10832 keyword = "grid";
10833 status = json_getInteger(
10834 designResponseTuple[i].value, keyword, &response->gridID);
10835 if (status != CAPS_SUCCESS0) {
10836 // optional
10837 }
10838
10839 /*! \page feaDesignResponse
10840 *
10841 * \if NASTRAN
10842 * <ul>
10843 * <li> <B>groupName = "(no default)"</B> </li> <br>
10844 * Defines the reference <c>capsGroup</c> for the node being specified for the response.
10845 * </ul>
10846 * \endif
10847 */
10848 keyword = "groupName";
10849 status = json_getString(
10850 designResponseTuple[i].value, keyword, &groupName);
10851
10852 if (status == CAPS_SUCCESS0) {
10853
10854 // Get the corresponding response index
10855 status = get_mapAttrToIndexIndex(responseMap, (const char *) groupName, &attrIndex);
10856
10857 if (status == CAPS_NOTFOUND-303) {
10858 printf("\tName %s not found in attribute map!!!!\n", groupName);
10859 continue;
10860 } else if (status != CAPS_SUCCESS0) return status;
10861
10862 status = mesh_findNodes(&feaProblem->feaMesh,
10863 _matchResponseNode, (void *) &attrIndex,
10864 &numNode, &nodeSet);
10865 if (status != CAPS_SUCCESS0) return status;
10866
10867 if (numNode == 0) {
10868 AIM_ERROR(aimInfo, "No node found for capsGroup %s", groupName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10868, __func__
, "No node found for capsGroup %s", groupName); }
;
10869 return CAPS_NOTFOUND-303;
10870 }
10871 else if (numNode > 1) { // TODO: would there ever be more than 1 node expected?
10872 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);
10873 "... using first matching node.",fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s"
"... using first matching node." "\n", groupName);
10874 groupName)fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s"
"... using first matching node." "\n", groupName);
;
10875 }
10876
10877 response->gridID = nodeSet[0]->nodeID;
10878
10879 EG_free(nodeSet);
10880 nodeSet = NULL((void*)0);
10881
10882 }
10883 else {
10884 // required
10885 // AIM_ERROR(aimInfo, "Missing required entry \"groupName\" "
10886 // "in 'Design_Response' tuple value");
10887 // return status;
10888 }
10889
10890 if (groupName != NULL((void*)0)) {
10891 EG_free(groupName);
10892 groupName = NULL((void*)0);
10893 }
10894
10895 }
10896
10897 return CAPS_SUCCESS0;
10898}
10899
10900int fea_getDesignEquationResponse(int numDesignEquationResponseTuple,
10901 capsTuple designEquationResponseTuple[],
10902 feaProblemStruct *feaProblem) {
10903
10904 /*! \page feaDesignEquationResponse FEA Design Equation Responses
10905 * Structure for the design equation response tuple = ("DesignEquationResponse Name", "Value").
10906 * "DesignEquationResponse Name" defines the reference name for the design equation response being specified.
10907 * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary
10908 * (see Section \ref jsonStringDesignEquationResponse).
10909 * \if NASTRAN
10910 * In Nastran the DesignEquationResponse Name will be the LABEL used in the DRESP2 input.
10911 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
10912 *
10913 * - <c>DRESP2 ID LABEL EQID REGION ...</c>
10914 * \endif
10915 *
10916 */
10917 int i, status;
10918
10919 char *keyword;
10920
10921 feaDesignEquationResponseStruct *equationResponse;
10922
10923 // Ensure we are starting with no design equation responses
10924 if (feaProblem->feaEquationResponse != NULL((void*)0)) {
10925 for (i = 0; i < feaProblem->numEquationResponse; i++) {
10926 status = destroy_feaDesignEquationResponseStruct(&feaProblem->feaEquationResponse[i]);
10927 if (status != CAPS_SUCCESS0) return status;
10928 }
10929 EG_free(feaProblem->feaEquationResponse);
10930 }
10931 feaProblem->numEquationResponse = 0;
10932 feaProblem->feaEquationResponse = NULL((void*)0);
10933
10934 printf("\nGetting Design Equation Responses.......\n");
10935
10936 feaProblem->numEquationResponse = numDesignEquationResponseTuple;
10937 printf("\tNumber of Design Equation Responses - %d\n", feaProblem->numEquationResponse);
10938
10939 if (feaProblem->numEquationResponse > 0) {
10940
10941 feaProblem->feaEquationResponse = EG_alloc(
10942 feaProblem->numEquationResponse * sizeof(feaDesignEquationResponseStruct));
10943 if (feaProblem->feaEquationResponse == NULL((void*)0)) {
10944 return EGADS_MALLOC-4;
10945 }
10946
10947 } else {
10948 printf("\tNumber of design equation responses in Analysis tuple is %d\n",
10949 feaProblem->numEquationResponse);
10950 return CAPS_NOTFOUND-303;
10951 }
10952
10953 // for each analysis design equation response tuple
10954 for (i = 0; i < feaProblem->numEquationResponse; i++) {
10955
10956 printf("\tDesign_Equation_Response name - %s\n", designEquationResponseTuple[i].name);
10957
10958 equationResponse = &feaProblem->feaEquationResponse[i];
10959
10960 // initiate design response structure
10961 status = initiate_feaDesignEquationResponseStruct(equationResponse);
10962 if (status != CAPS_SUCCESS0) return status;
10963
10964 // set name
10965 equationResponse->name = EG_strdup(designEquationResponseTuple[i].name);
10966
10967 // set equation response ID
10968 equationResponse->equationResponseID = i+1;
10969
10970 /*! \page feaDesignEquationResponse
10971 * \section jsonStringDesignEquationResponse JSON String Dictionary
10972 *
10973 * If "Value" is JSON string dictionary
10974 * \if NASTRAN
10975 * (eg. "Value" = {"equation": "EQ1", "constant": ["PI", "YM", "L"]})
10976 * \endif
10977 * the following keywords ( = default values) may be used:
10978 *
10979 */
10980 // make sure design response tuple value is json string
10981 if (!json_isDict(designEquationResponseTuple[i].value)) {
10982 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", 10983, __func__);
10983 "'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", 10983, __func__);
;
10984 return CAPS_BADVALUE-311;
10985 }
10986
10987 /*! \page feaDesignEquationResponse
10988 *
10989 * \if NASTRAN
10990 * <ul>
10991 * <li> <B>equation</B> </li> <br>
10992 * The name of the equation referenced by this equation response.
10993 * </ul>
10994 * \endif
10995 */
10996 keyword = "equation";
10997 status = json_getString(
10998 designEquationResponseTuple[i].value, keyword, &equationResponse->equationName);
10999 if (status != CAPS_SUCCESS0) {
11000 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", 11001, __func__);
11001 "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", 11001, __func__);
;
11002 return status;
11003 }
11004
11005 /*! \page feaDesignEquationResponse
11006 *
11007 * \if NASTRAN
11008 * <ul>
11009 * <li> <B>variable = "(no default)"</B> </li> <br>
11010 * Single or list of names of design variable equation parameters.
11011 * </ul>
11012 * \endif
11013 */
11014 keyword = "variable";
11015 status = json_getStringDynamicArray(
11016 designEquationResponseTuple[i].value, keyword,
11017 &equationResponse->numDesignVariable, &equationResponse->designVariableNameSet);
11018 if (status != CAPS_SUCCESS0) {
11019 // optional
11020 }
11021
11022 /*! \page feaDesignEquationResponse
11023 *
11024 * \if NASTRAN
11025 * <ul>
11026 * <li> <B>constant = "(no default)"</B> </li> <br>
11027 * Single or list of names of table constant equation parameters.
11028 * </ul>
11029 * \endif
11030 */
11031 keyword = "constant";
11032 status = json_getStringDynamicArray(
11033 designEquationResponseTuple[i].value, keyword,
11034 &equationResponse->numConstant, &equationResponse->constantLabelSet);
11035 if (status != CAPS_SUCCESS0) {
11036 // optional
11037 }
11038
11039 /*! \page feaDesignEquationResponse
11040 *
11041 * \if NASTRAN
11042 * <ul>
11043 * <li> <B>response = "(no default)"</B> </li> <br>
11044 * Single or list of names of design response equation parameters.
11045 * </ul>
11046 * \endif
11047 */
11048 keyword = "response";
11049 status = json_getStringDynamicArray(
11050 designEquationResponseTuple[i].value, keyword,
11051 &equationResponse->numResponse, &equationResponse->responseNameSet);
11052 if (status != CAPS_SUCCESS0) {
11053 // optional
11054 }
11055
11056 /*! \page feaDesignEquationResponse
11057 *
11058 * \if NASTRAN
11059 * <ul>
11060 * <li> <B>equationResponse = "(no default)"</B> </li> <br>
11061 * Single or list of names of design equation response equation parameters.
11062 * </ul>
11063 * \endif
11064 */
11065 keyword = "equationResponse";
11066 status = json_getStringDynamicArray(
11067 designEquationResponseTuple[i].value, keyword,
11068 &equationResponse->numEquationResponse, &equationResponse->equationResponseNameSet);
11069 if (status != CAPS_SUCCESS0) {
11070 // optional
11071 }
11072 }
11073
11074 return CAPS_SUCCESS0;
11075}
11076
11077// Get the design optimization parameters from a capsTuple
11078int fea_getDesignOptParam(int numParamTuple,
11079 capsTuple paramTuple[],
11080 feaProblemStruct *feaProblem) {
11081
11082 /*! \page feaDesignOptParam FEA Design Optimization Parameters
11083 * Structure for the design optimization parameter tuple = ("DesignOptParam Name", "Value").
11084 * "DesignOptParam Name" defines the reference name for the design optimization parameter being specified.
11085 * This string will be used in the FEA input directly. The "Value" is the value of the
11086 * design optimization parameter.
11087 * \if NASTRAN
11088 * In Nastran the DesignOptParam Name will be the PARAMi used in the DOPTPRM input.
11089 * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less.
11090 *
11091 * - <c>DOPTPRM PARAM1 VAL1 PARAM2 VAL2 PARAM3 VAL3 -etc- </c>
11092 * \endif
11093 *
11094 */
11095 int i, status;
11096
11097 int *paramInt = NULL((void*)0);
11098 double *paramDouble = NULL((void*)0);
11099
11100 feaDesignOptParamStruct *table = &feaProblem->feaDesignOptParam;
11101
11102 // Ensure we are starting with no params
11103 status = destroy_feaDesignOptParamStruct(table);
11104 if (status != CAPS_SUCCESS0) return status;
11105
11106 printf("\nGetting Design Optimization Parameters.......\n");
11107
11108 table->numParam = numParamTuple;
11109 printf("\tNumber of Design Optimization Parameters - %d\n", table->numParam);
11110
11111 if (table->numParam > 0) {
11112
11113 table->paramLabel = EG_alloc(table->numParam * sizeof(char *));
11114 if (table->paramLabel == NULL((void*)0)) {
11115 return EGADS_MALLOC-4;
11116 }
11117
11118 table->paramValue = EG_alloc(table->numParam * sizeof(void *));
11119 if (table->paramValue == NULL((void*)0)) {
11120 return EGADS_MALLOC-4;
11121 }
11122
11123 table->paramType = EG_alloc(table->numParam * sizeof(int));
11124 if (table->paramType == NULL((void*)0)) {
11125 return EGADS_MALLOC-4;
11126 }
11127
11128 } else {
11129 printf("\tNumber of design optimization parameters in Analysis tuple is %d\n",
11130 table->numParam);
11131 return CAPS_NOTFOUND-303;
11132 }
11133
11134 // for each analysis design optimization parameter tuple
11135 for (i = 0; i < table->numParam; i++) {
11136
11137 printf("\tDesign_Opt_Param - %s: %s\n",
11138 paramTuple[i].name, paramTuple[i].value);
11139
11140 // set param label
11141 // TODO: ensure label <= 8 chars
11142 table->paramLabel[i] = EG_strdup(paramTuple[i].name);
11143
11144 // set param value
11145
11146 // if param value is real
11147 if (strchr(paramTuple[i].value, '.')
11148 || strchr(paramTuple[i].value, 'e')
11149 || strchr(paramTuple[i].value, 'E')) {
11150
11151 paramDouble = EG_alloc(sizeof(double));
11152 if (paramDouble == NULL((void*)0)) return EGADS_MALLOC-4;
11153
11154 status = string_toDouble(paramTuple[i].value, paramDouble);
11155 if (status != CAPS_SUCCESS0) {
11156 EG_free(paramDouble);
11157 return status;
11158 }
11159
11160 table->paramType[i] = Double;
11161 table->paramValue[i] = (void*) paramDouble;
11162 }
11163 // else param is integer
11164 else {
11165
11166 paramInt = EG_alloc(sizeof(int));
11167 if (paramInt == NULL((void*)0)) return EGADS_MALLOC-4;
11168
11169 status = string_toInteger(paramTuple[i].value, paramInt);
11170 if (status != CAPS_SUCCESS0) {
11171 EG_free(paramInt);
11172 return status;
11173 }
11174
11175 table->paramType[i] = Integer;
11176 table->paramValue[i] = (void*) paramInt;
11177 }
11178 }
11179
11180 return CAPS_SUCCESS0;
11181}
11182
11183// Function used by fea_getAeroReference to determine which nodes are in reference group
11184static int _matchReferenceNode(meshNodeStruct *node, void *referenceIndex) {
11185
11186 feaMeshDataStruct *feaData;
11187
11188 if (node->analysisType == MeshStructure) {
11189
11190 feaData = (feaMeshDataStruct *) node->analysisData;
11191
11192 if (feaData->referenceIndex == *((int *) referenceIndex)) {
11193 return (int) true1;
11194 }
11195 }
11196 return (int) false0;
11197}
11198
11199// Get aero reference information from json dict
11200int fea_getAeroReference(char *aeroRefInput,
11201 mapAttrToIndexStruct *attrMap,
11202 feaProblemStruct *feaProblem) {
11203
11204 /*! \page feaAeroReference FEA Aerodynamic References
11205 * The aerodynamic reference input must be a JSON String dictionary
11206 * (see Section \ref jsonStringAeroReference).
11207 *
11208 */
11209 int status, attrIndex = 0;
11210
11211 char *keyword, *refNodeName = NULL((void*)0);
11212
11213 int numNodes;
11214 meshNodeStruct **nodes = NULL((void*)0);
11215
11216 printf("\nGetting Aero Reference Parameters.......\n");
11217
11218 /*! \page feaAeroReference
11219 * \section jsonStringAeroReference JSON String Dictionary
11220 *
11221 * The following keywords ( = default values) may be used:
11222 *
11223 */
11224 // make sure input is json string
11225 if (!json_isDict(aeroRefInput)) {
11226 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", 11227, __func__);
11227 "'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", 11227, __func__);
;
11228 return CAPS_BADVALUE-311;
11229 }
11230
11231 /*! \page feaAeroReference
11232 *
11233 * \if ASTROS
11234 * <ul>
11235 * <li> <B>referenceNode</B> </li> <br>
11236 * Defines the reference <c>capsReference</c> for the node to be used for stability derivative calculations.
11237 * </ul>
11238 * \endif
11239 */
11240 keyword = "referenceNode";
11241 status = json_getString(
11242 aeroRefInput, keyword, &refNodeName);
11243 if (status == CAPS_SUCCESS0) {
11244
11245 // find node with capsReference == refNodeName
11246
11247 status = get_mapAttrToIndexIndex(attrMap, refNodeName, &attrIndex);
11248 if (status != CAPS_SUCCESS0) {
11249 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", 11249, __func__, refNodeName);
;
11250 goto cleanup;
11251 }
11252
11253 status = mesh_findNodes(
11254 &feaProblem->feaMesh, _matchReferenceNode, &attrIndex, &numNodes, &nodes);
11255 if (status == CAPS_NOTFOUND-303) {
11256 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", 11256, __func__, refNodeName);
;
11257 }
11258 if (status != CAPS_SUCCESS0) {
11259 goto cleanup;
11260 }
11261
11262 // set refGridID to the nodeID
11263 feaProblem->feaAeroRef.refGridID = nodes[0]->nodeID;
11264 }
11265
11266 status = CAPS_SUCCESS0;
11267
11268 cleanup:
11269
11270 if (refNodeName != NULL((void*)0)) EG_free(refNodeName);
11271 if (nodes != NULL((void*)0)) EG_free(nodes);
11272
11273 return status;
11274}
11275
11276// Find feaPropertyStructs with given names in feaProblem
11277int fea_findPropertiesByNames(feaProblemStruct *feaProblem,
11278 int numPropertyNames,
11279 char **propertyNames,
11280 int *numProperties,
11281 feaPropertyStruct ***properties) {
11282 int i, status;
11283
11284 int numFound;
11285 feaPropertyStruct **propertiesFound, *property;
11286
11287 propertiesFound = EG_alloc(sizeof(feaPropertyStruct *) * numPropertyNames);
11288
11289 numFound = 0;
11290 for (i = 0; i < feaProblem->numProperty; i++) {
11291
11292 property = &feaProblem->feaProperty[i];
11293
11294 if (string_isInArray(property->name, numPropertyNames, propertyNames)) {
11295
11296 propertiesFound[numFound++] = property;
11297
11298 if (numFound == numPropertyNames) {
11299 // found all
11300 break;
11301 }
11302 }
11303 }
11304
11305 if (numFound < numPropertyNames) {
11306 propertiesFound = EG_reall(propertiesFound, sizeof(feaPropertyStruct *) * numFound);
11307 status = CAPS_NOTFOUND-303;
11308 }
11309 else {
11310 status = CAPS_SUCCESS0;
11311 }
11312
11313 *numProperties = numFound;
11314 *properties = propertiesFound;
11315
11316 return status;
11317}
11318
11319// Find feaMaterialStructs with given names in feaProblem
11320int fea_findMaterialsByNames(feaProblemStruct *feaProblem,
11321 int numMaterialNames,
11322 char **materialNames,
11323 int *numMaterials,
11324 feaMaterialStruct ***materials) {
11325 int i, status;
11326
11327 int numFound;
11328 feaMaterialStruct **materialsFound, *material;
11329
11330 materialsFound = EG_alloc(sizeof(feaMaterialStruct *) * numMaterialNames);
11331
11332 numFound = 0;
11333 for (i = 0; i < feaProblem->numMaterial; i++) {
11334
11335 material = &feaProblem->feaMaterial[i];
11336
11337 if (string_isInArray(material->name, numMaterialNames, materialNames)) {
11338
11339 materialsFound[numFound++] = material;
11340
11341 if (numFound == numMaterialNames) {
11342 // found all
11343 break;
11344 }
11345 }
11346 }
11347
11348 if (numFound < numMaterialNames) {
11349 materialsFound = EG_reall(materialsFound, sizeof(feaMaterialStruct *) * numFound);
11350 status = CAPS_NOTFOUND-303;
11351 }
11352 else {
11353 status = CAPS_SUCCESS0;
11354 }
11355
11356 *numMaterials = numFound;
11357 *materials = materialsFound;
11358
11359 return status;
11360}
11361
11362// Find feaDesignVariableStructs with given names in feaProblem
11363int fea_findDesignVariablesByNames(const feaProblemStruct *feaProblem,
11364 int numDesignVariableNames,
11365 char **designVariableNames,
11366 int *numDesignVariables,
11367 feaDesignVariableStruct ***designVariables) {
11368 int i, status;
11369
11370 int numFound;
11371 feaDesignVariableStruct **designVariablesFound=NULL((void*)0), *designVariable=NULL((void*)0);
11372
11373 designVariablesFound = (feaDesignVariableStruct **) EG_alloc(numDesignVariableNames * sizeof(feaDesignVariableStruct *));
11374
11375 numFound = 0;
11376 for (i = 0; i < feaProblem->numDesignVariable; i++) {
11377
11378 designVariable = &feaProblem->feaDesignVariable[i];
11379
11380 if (string_isInArray(designVariable->name, numDesignVariableNames, designVariableNames)) {
11381
11382 designVariablesFound[numFound++] = designVariable;
11383
11384 if (numFound == numDesignVariableNames) {
11385 // found all
11386 break;
11387 }
11388 }
11389 }
11390
11391 if (numFound < numDesignVariableNames) {
11392 designVariablesFound = EG_reall(designVariablesFound, numFound * sizeof(feaDesignVariableStruct *));
11393 status = CAPS_NOTFOUND-303;
11394 } else {
11395 status = CAPS_SUCCESS0;
11396 }
11397
11398 *numDesignVariables = numFound;
11399 *designVariables = designVariablesFound;
11400
11401 return status;
11402}
11403
11404// Find feaDesignResponseStructs with given names in feaProblem
11405int fea_findDesignResponsesByNames(const feaProblemStruct *feaProblem,
11406 int numDesignResponseNames,
11407 char **designResponseNames,
11408 int *numDesignResponses,
11409 feaDesignResponseStruct ***designResponses) {
11410 int i, status;
11411
11412 int numFound;
11413 feaDesignResponseStruct **designResponsesFound, *designResponse;
11414
11415 designResponsesFound = EG_alloc(sizeof(feaDesignResponseStruct *) * numDesignResponseNames);
11416
11417 numFound = 0;
11418 for (i = 0; i < feaProblem->numDesignResponse; i++) {
11419
11420 designResponse = &feaProblem->feaDesignResponse[i];
11421
11422 if (string_isInArray(designResponse->name, numDesignResponseNames, designResponseNames)) {
11423
11424 designResponsesFound[numFound++] = designResponse;
11425
11426 if (numFound == numDesignResponseNames) {
11427 // found all
11428 break;
11429 }
11430 }
11431 }
11432
11433 if (numFound < numDesignResponseNames) {
11434 designResponsesFound = EG_reall(designResponsesFound, sizeof(feaDesignResponseStruct *) * numFound);
11435 status = CAPS_NOTFOUND-303;
11436 }
11437 else {
11438 status = CAPS_SUCCESS0;
11439 }
11440
11441 *numDesignResponses = numFound;
11442 *designResponses = designResponsesFound;
11443
11444 return status;
11445}
11446
11447// Find feaDesignEquationResponseStructs with given names in feaProblem
11448int fea_findEquationResponsesByNames(const feaProblemStruct *feaProblem,
11449 int numEquationResponseNames,
11450 char **equationResponseNames,
11451 int *numEquationResponses,
11452 feaDesignEquationResponseStruct ***equationResponses) {
11453 int i, status;
11454
11455 int numFound;
11456 feaDesignEquationResponseStruct **equationResponsesFound, *equationResponse;
11457
11458 equationResponsesFound = EG_alloc(sizeof(feaDesignEquationResponseStruct *) * numEquationResponseNames);
11459
11460 numFound = 0;
11461 for (i = 0; i < feaProblem->numEquationResponse; i++) {
11462
11463 equationResponse = &feaProblem->feaEquationResponse[i];
11464
11465 if (string_isInArray(equationResponse->name, numEquationResponseNames, equationResponseNames)) {
11466
11467 equationResponsesFound[numFound++] = equationResponse;
11468
11469 if (numFound == numEquationResponseNames) {
11470 // found all
11471 break;
11472 }
11473 }
11474 }
11475
11476 if (numFound < numEquationResponseNames) {
11477 equationResponsesFound = EG_reall(equationResponsesFound, sizeof(feaDesignEquationResponseStruct *) * numFound);
11478 status = CAPS_NOTFOUND-303;
11479 }
11480 else {
11481 status = CAPS_SUCCESS0;
11482 }
11483
11484 *numEquationResponses = numFound;
11485 *equationResponses = equationResponsesFound;
11486
11487 return status;
11488}
11489
11490// Find feaDesignEquationStruct with given equationName in feaProblem
11491int fea_findEquationByName(const feaProblemStruct *feaProblem, char *equationName, feaDesignEquationStruct **equation) {
11492
11493 int i;
11494
11495 for (i = 0; i < feaProblem->numEquation; i++) {
11496
11497 if (strcmp(feaProblem->feaEquation[i].name, equationName) == 0) {
11498 *equation = &feaProblem->feaEquation[i];
11499 return CAPS_SUCCESS0;
11500 }
11501 }
11502
11503 return CAPS_NOTFOUND-303;
11504}
11505
11506// Find vlmControlStruct with given controlSurfName in feaProble
11507int fea_findControlSurfaceByName(const feaProblemStruct *feaProblem, char *controlSurfName, vlmControlStruct **controlSurf) {
11508
11509 int isection, icontrol;
11510
11511 vlmSurfaceStruct *surface;
11512 vlmSectionStruct *section;
11513
11514 surface = &feaProblem->feaAero->vlmSurface;
11515
11516 for (isection = 0; isection < surface->numSection; isection++) {
11517
11518 section = &surface->vlmSection[isection];
11519
11520 for (icontrol = 0; icontrol < section->numControl; icontrol++) {
11521
11522 if (strcmp(section->vlmControl[icontrol].name, controlSurfName) == 0) {
11523 *controlSurf = &section->vlmControl[icontrol];
11524 return CAPS_SUCCESS0;
11525 }
11526 }
11527 }
11528
11529 return CAPS_NOTFOUND-303;
11530}
11531
11532// Find feaDesignConstraintStruct with given constraintType in feaProblem
11533int fea_findDesignConstraintByType(const feaProblemStruct *feaProblem, feaDesignConstraintTypeEnum constraintType, feaDesignConstraintStruct **designConstraint) {
11534
11535 int i;
11536
11537 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
11538
11539 if (feaProblem->feaDesignConstraint[i].designConstraintType == constraintType) {
11540 *designConstraint = &feaProblem->feaDesignConstraint[i];
11541 return CAPS_SUCCESS0;
11542 }
11543 }
11544
11545 return CAPS_NOTFOUND-303;
11546}
11547
11548static inline int _feaDesignVariableRelation_linkDesignVariable(feaDesignVariableRelationStruct *relation,
11549 feaDesignVariableStruct *desvar,
11550 int desvarIndex) {
11551 if (relation->designVariableSet == NULL((void*)0)) {
11552 relation->designVariableSet = (
11553 (feaDesignVariableStruct **)
11554 EG_alloc(sizeof(feaDesignVariableStruct *) * relation->numDesignVariable)
11555 );
11556 }
11557 if (relation->designVariableSet == NULL((void*)0)) {
11558 return EGADS_MALLOC-4;
11559 }
11560
11561 relation->designVariableSet[desvarIndex] = desvar;
11562
11563 return CAPS_SUCCESS0;
11564}
11565
11566static inline int _feaDesignVariable_linkDesignVariableRelation(feaDesignVariableStruct *desvar,
11567 feaDesignVariableRelationStruct *relation) {
11568
11569 if (desvar->numRelation == 0) {
11570 desvar->relationSet = (
11571 (feaDesignVariableRelationStruct **)
11572 EG_alloc(sizeof(feaDesignVariableRelationStruct *))
11573 );
11574 }
11575 else {
11576 desvar->relationSet = (
11577 (feaDesignVariableRelationStruct **)
11578 EG_reall(desvar->relationSet, sizeof(feaDesignVariableRelationStruct *) * (desvar->numRelation + 1))
11579 );
11580 }
11581 if (desvar->relationSet == NULL((void*)0)) {
11582 return EGADS_MALLOC-4;
11583 }
11584
11585 desvar->relationSet[desvar->numRelation] = relation;
11586 desvar->numRelation++;
11587
11588 return CAPS_SUCCESS0;
11589}
11590
11591// Populate the feaDesignVariable.relationSet and feaDesignVariableRelation.variableSet members
11592// in all feaDesignVariables and feaDesignVariableRelations
11593int fea_linkDesignVariablesAndRelations(const feaProblemStruct *feaProblem) {
11594
11595 int status;
11596 int idvGlobal, idv, irel;
11597
11598 char *desvarName = NULL((void*)0), **desvarNameSet = NULL((void*)0);
11599
11600 feaDesignVariableStruct *desvar = NULL((void*)0);
11601 feaDesignVariableRelationStruct *desvarRelation = NULL((void*)0);
11602
11603 for (irel = 0; irel < feaProblem->numDesignVariableRelation; irel++) {
11604
11605 desvarRelation = &feaProblem->feaDesignVariableRelation[irel];
11606 desvarNameSet = desvarRelation->designVariableNameSet;
11607
11608 for (idv = 0; idv < desvarRelation->numDesignVariable; idv++) {
11609
11610 desvarName = desvarNameSet[idv];
11611
11612 for (idvGlobal = 0; idvGlobal < feaProblem->numDesignVariable; idvGlobal++) {
11613
11614 desvar = &feaProblem->feaDesignVariable[idvGlobal];
11615
11616 if (strcmp(desvar->name, desvarName) == 0) {
11617
11618 status = _feaDesignVariableRelation_linkDesignVariable(desvarRelation, desvar, idv);
11619 if (status != CAPS_SUCCESS0) return status;
11620
11621 status = _feaDesignVariable_linkDesignVariableRelation(desvar, desvarRelation);
11622 if (status != CAPS_SUCCESS0) return status;
11623 break;
11624 }
11625 }
11626 }
11627 }
11628
11629 return CAPS_SUCCESS0;
11630}
11631
11632// Initiate (0 out all values and NULL all pointers) of feaProblem in the feaProblemStruct structure format
11633int initiate_feaProblemStruct(feaProblemStruct *feaProblem) {
11634
11635 int status = 0;
11636
11637 // Problem analysis
11638 feaProblem->numAnalysis = 0;
11639 feaProblem->feaAnalysis = NULL((void*)0);
11640
11641 // Materials
11642 feaProblem->numMaterial = 0;
11643 feaProblem->feaMaterial = NULL((void*)0);
11644
11645 // Properties
11646 feaProblem->numProperty = 0;
11647 feaProblem->feaProperty = NULL((void*)0);
11648
11649 // Constraints
11650 feaProblem->numConstraint = 0;
11651 feaProblem->feaConstraint = NULL((void*)0);
11652
11653 // Supports
11654 feaProblem->numSupport = 0;
11655 feaProblem->feaSupport = NULL((void*)0);
11656
11657 // Loads
11658 feaProblem->numLoad = 0;
11659 feaProblem->feaLoad = NULL((void*)0);
11660
11661 // Connections
11662 feaProblem->numConnect = 0;
11663 feaProblem->feaConnect = NULL((void*)0);
11664
11665 // Mesh
11666 status = initiate_meshStruct(&feaProblem->feaMesh);
11667 if (status != CAPS_SUCCESS0) goto cleanup;
11668
11669 // Output formatting
11670 status = initiate_feaFileFormatStruct(&feaProblem->feaFileFormat);
11671 if (status != CAPS_SUCCESS0) goto cleanup;
11672
11673 // Optimization - Design Variables
11674 feaProblem->numDesignVariable = 0;
11675 feaProblem->feaDesignVariable = NULL((void*)0);
11676
11677 // Optimization - Design Variable Relations
11678 feaProblem->numDesignVariableRelation = 0;
11679 feaProblem->feaDesignVariableRelation = NULL((void*)0);
11680
11681 // Optimization - Design Constraints
11682 feaProblem->numDesignConstraint = 0;
11683 feaProblem->feaDesignConstraint = NULL((void*)0);
11684
11685 // Optimization - Equations
11686 feaProblem->numEquation = 0;
11687 feaProblem->feaEquation = NULL((void*)0);
11688
11689 // Optimization - Table Constants
11690 status = initiate_feaDesignTableStruct(&feaProblem->feaDesignTable);
11691 if (status != CAPS_SUCCESS0) goto cleanup;
11692
11693 // Optimization - Design Optimization Parameters
11694 status = initiate_feaDesignOptParamStruct(&feaProblem->feaDesignOptParam);
11695 if (status != CAPS_SUCCESS0) goto cleanup;
11696
11697 // Optimization - Design Sensitivity Response Quantities
11698 feaProblem->numDesignResponse = 0;
11699 feaProblem->feaDesignResponse = NULL((void*)0);
11700
11701 // Optimization - Design Sensitivity Equation Response Quantities
11702 feaProblem->numEquationResponse = 0;
11703 feaProblem->feaEquationResponse = NULL((void*)0);
11704
11705 // Coordinate Systems
11706 feaProblem->numCoordSystem = 0;
11707 feaProblem->feaCoordSystem = NULL((void*)0);
11708
11709 // Aerodynamics
11710 feaProblem->numAero = 0;
11711 feaProblem->feaAero = NULL((void*)0);
11712 status = initiate_feaAeroRefStruct(&feaProblem->feaAeroRef);
11713 if (status != CAPS_SUCCESS0) goto cleanup;
11714
11715 aim_initMeshRef(&feaProblem->meshRefObj, aimUnknownMeshType);
11716 feaProblem->meshRefIn = NULL((void*)0);
11717
11718 status = CAPS_SUCCESS0;
11719
11720cleanup:
11721 if (status != CAPS_SUCCESS0) printf("Error: Status %d during initiate_feaProblemStruct!\n", status);
11722
11723 return status;
11724}
11725
11726// Destroy (0 out all values and NULL all pointers) of feaProblem in the feaProblemStruct structure format
11727int destroy_feaProblemStruct(feaProblemStruct *feaProblem) {
11728
11729 int i; // Indexing
11730
11731 int status = 0; // Status return
11732
11733 // Analysis
11734 if (feaProblem->feaAnalysis != NULL((void*)0)) {
11735 for (i = 0; i < feaProblem->numAnalysis; i++) {
11736 status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
11737 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaAnalysisStruct\n", status);
11738 }
11739 }
11740 AIM_FREE(feaProblem->feaAnalysis){ EG_free(feaProblem->feaAnalysis); feaProblem->feaAnalysis
= ((void*)0); }
;
11741 feaProblem->numAnalysis = 0;
11742
11743 // Materials
11744 if (feaProblem->feaMaterial != NULL((void*)0)) {
11745 for (i = 0; i < feaProblem->numMaterial; i++) {
11746 status = destroy_feaMaterialStruct(&feaProblem->feaMaterial[i]);
11747 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaMaterialStruct\n", status);
11748 }
11749 }
11750 AIM_FREE(feaProblem->feaMaterial){ EG_free(feaProblem->feaMaterial); feaProblem->feaMaterial
= ((void*)0); }
;
11751 feaProblem->numMaterial = 0;
11752
11753 // Properties
11754 if (feaProblem->feaProperty != NULL((void*)0)) {
11755 for (i = 0; i < feaProblem->numProperty; i++) {
11756 status = destroy_feaPropertyStruct(&feaProblem->feaProperty[i]);
11757 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaPropertyStruct\n", status);
11758 }
11759 }
11760 AIM_FREE(feaProblem->feaProperty){ EG_free(feaProblem->feaProperty); feaProblem->feaProperty
= ((void*)0); }
;
11761 feaProblem->numProperty = 0;
11762
11763 // Constraints
11764 if (feaProblem->feaConstraint != NULL((void*)0)) {
11765 for (i = 0; i < feaProblem->numConstraint; i++) {
11766 status = destroy_feaConstraintStruct(&feaProblem->feaConstraint[i]);
11767 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaConstraintStruct\n", status);
11768 }
11769 }
11770 AIM_FREE(feaProblem->feaConstraint){ EG_free(feaProblem->feaConstraint); feaProblem->feaConstraint
= ((void*)0); }
;
11771 feaProblem->numConstraint = 0;
11772
11773 // Supports
11774 if (feaProblem->feaSupport != NULL((void*)0)) {
11775 for (i = 0; i < feaProblem->numSupport; i++) {
11776 status = destroy_feaSupportStruct(&feaProblem->feaSupport[i]);
11777 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaSupportStruct\n", status);
11778 }
11779 }
11780 AIM_FREE(feaProblem->feaSupport){ EG_free(feaProblem->feaSupport); feaProblem->feaSupport
= ((void*)0); }
;
11781 feaProblem->numSupport = 0;
11782
11783 // Loads
11784 if (feaProblem->feaLoad != NULL((void*)0)) {
11785 for (i = 0; i < feaProblem->numLoad; i++) {
11786 status = destroy_feaLoadStruct(&feaProblem->feaLoad[i]);
11787 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaLoadStruct\n", status);
11788 }
11789 }
11790 AIM_FREE(feaProblem->feaLoad){ EG_free(feaProblem->feaLoad); feaProblem->feaLoad = (
(void*)0); }
;
11791 feaProblem->numLoad = 0;
11792
11793 // Connections
11794 if (feaProblem->feaConnect != NULL((void*)0)) {
11795 for (i = 0; i < feaProblem->numConnect; i++) {
11796 status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]);
11797 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaConnectStruct\n", status);
11798 }
11799 }
11800 AIM_FREE(feaProblem->feaConnect){ EG_free(feaProblem->feaConnect); feaProblem->feaConnect
= ((void*)0); }
;
11801 feaProblem->numConnect = 0;
11802
11803 // Mesh
11804 status = destroy_meshStruct(&feaProblem->feaMesh);
11805 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_meshStruct\n", status);
11806
11807 // Output formatting
11808 status = destroy_feaFileFormatStruct(&feaProblem->feaFileFormat);
11809 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaFileFormatStruct\n", status);
11810
11811
11812 if (feaProblem->feaDesignVariable != NULL((void*)0)) {
11813 for (i = 0; i < feaProblem->numDesignVariable; i++) {
11814 status = destroy_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]);
11815 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignVariableStruct\n", status);
11816 }
11817 }
11818 AIM_FREE(feaProblem->feaDesignVariable){ EG_free(feaProblem->feaDesignVariable); feaProblem->feaDesignVariable
= ((void*)0); }
;
11819 feaProblem->numDesignVariable = 0;
11820
11821 // Optimization - design variable relations
11822 if (feaProblem->feaDesignVariableRelation != NULL((void*)0)) {
11823 for (i = 0; i < feaProblem->numDesignVariableRelation; i++) {
11824 status = destroy_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]);
11825 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignVariableRelationStruct\n", status);
11826 }
11827 AIM_FREE(feaProblem->feaDesignVariableRelation){ EG_free(feaProblem->feaDesignVariableRelation); feaProblem
->feaDesignVariableRelation = ((void*)0); }
;
11828 }
11829 feaProblem->numDesignVariableRelation = 0;
11830
11831 // Optimization - design constraint
11832 if (feaProblem->feaDesignConstraint != NULL((void*)0)) {
11833 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
11834 status = destroy_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]);
11835 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignConstraintStruct\n", status);
11836 }
11837 }
11838 AIM_FREE(feaProblem->feaDesignConstraint){ EG_free(feaProblem->feaDesignConstraint); feaProblem->
feaDesignConstraint = ((void*)0); }
;
11839 feaProblem->numDesignConstraint = 0;
11840
11841 // Optimization - Equations
11842 if (feaProblem->feaEquation != NULL((void*)0)) {
11843 for (i = 0; i < feaProblem->numEquation; i++) {
11844 status = destroy_feaDesignEquationStruct(&feaProblem->feaEquation[i]);
11845 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignEquationStruct\n", status);
11846 }
11847 AIM_FREE(feaProblem->feaEquation){ EG_free(feaProblem->feaEquation); feaProblem->feaEquation
= ((void*)0); }
;
11848 }
11849 feaProblem->numEquation = 0;
11850
11851 // Optimization - Table Constants
11852 status = destroy_feaDesignTableStruct(&feaProblem->feaDesignTable);
11853 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignTableStruct\n", status);
11854
11855 // Optimization - Design Optimization Parameters
11856 status = destroy_feaDesignOptParamStruct(&feaProblem->feaDesignOptParam);
11857 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignOptParamStruct\n", status);
11858
11859 // Optimization - Design Sensitivity Response Quantities
11860 if (feaProblem->feaDesignResponse != NULL((void*)0)) {
11861 for (i = 0; i < feaProblem->numDesignResponse; i++) {
11862 status = destroy_feaDesignResponseStruct(&feaProblem->feaDesignResponse[i]);
11863 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignResponseStruct\n", status);
11864 }
11865 AIM_FREE(feaProblem->feaDesignResponse){ EG_free(feaProblem->feaDesignResponse); feaProblem->feaDesignResponse
= ((void*)0); }
;
11866 }
11867 feaProblem->numDesignResponse = 0;
11868
11869 // Optimization - Design Sensitivity Equation Response Quantities
11870 if (feaProblem->feaEquationResponse != NULL((void*)0)) {
11871 for (i = 0; i < feaProblem->numEquationResponse; i++) {
11872 status = destroy_feaDesignEquationResponseStruct(&feaProblem->feaEquationResponse[i]);
11873 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaEquationResponseStruct\n", status);
11874 }
11875 AIM_FREE(feaProblem->feaEquationResponse){ EG_free(feaProblem->feaEquationResponse); feaProblem->
feaEquationResponse = ((void*)0); }
;
11876 }
11877 feaProblem->numEquationResponse = 0;
11878
11879 // Coordinate Systems
11880 if (feaProblem->feaCoordSystem != NULL((void*)0)) {
11881
11882 for (i = 0; i < feaProblem->numCoordSystem; i++) {
11883 status = destroy_feaCoordSystemStruct(&feaProblem->feaCoordSystem[i]);
11884 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaCoordSystemStruct\n", status);
11885 }
11886 }
11887 AIM_FREE(feaProblem->feaCoordSystem){ EG_free(feaProblem->feaCoordSystem); feaProblem->feaCoordSystem
= ((void*)0); }
;
11888 feaProblem->numCoordSystem = 0;
11889
11890 // Aerodynamics
11891 if (feaProblem->feaAero != NULL((void*)0)) {
11892
11893 for (i = 0; i < feaProblem->numAero; i++) {
11894 status = destroy_feaAeroStruct(&feaProblem->feaAero[i]);
11895 if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaAeroStruct\n", status);
11896 }
11897 }
11898 AIM_FREE(feaProblem->feaAero){ EG_free(feaProblem->feaAero); feaProblem->feaAero = (
(void*)0); }
;
11899 feaProblem->numAero = 0;
11900
11901 (void) destroy_feaAeroRefStruct(&feaProblem->feaAeroRef);
11902
11903 aim_freeMeshRef(&feaProblem->meshRefObj);
11904 feaProblem->meshRefIn = NULL((void*)0);
11905
11906 return CAPS_SUCCESS0;
11907}
11908
11909// Initiate (0 out all values and NULL all pointers) of feaFileFormat in the feaFileFormatStruct structure format
11910int initiate_feaFileFormatStruct(feaFileFormatStruct *feaFileFormat) {
11911
11912 feaFileFormat->fileType = SmallField;
11913
11914 feaFileFormat->gridFileType = LargeField;
11915
11916 return CAPS_SUCCESS0;
11917}
11918
11919// Destroy (0 out all values and NULL all pointers) of feaFileFormat in the feaFileFormatStruct structure format
11920int destroy_feaFileFormatStruct(feaFileFormatStruct *feaFileFormat) {
11921
11922 feaFileFormat->fileType = SmallField;
11923
11924 feaFileFormat->gridFileType = LargeField;
11925
11926 return CAPS_SUCCESS0;
11927}
11928
11929// Transfer external pressure from the discrObj into the feaLoad structure
11930int fea_transferExternalPressure(void *aimInfo, const meshStruct *feaMesh, feaLoadStruct *feaLoad) {
11931
11932 // [in/out] feaLoad
11933 // [in] feaMesh
11934 // [in] aimInfo
11935
11936 int status; // Function status return
11937
11938 int i, j, bIndex; // Indexing
11939
11940 // Variables used in global node mapping
11941 int globalNodeID;
11942 int nodeIndex[4], transferIndex[4], elementID, elementIndex, elementCount;
11943
11944 // Discrete data transfer variables
11945 capsDiscr *dataTransferDiscreteObj;
11946 char **transferName = NULL((void*)0);
11947 int numTransferName, transferNameIndex;
11948 enum capsdMethod dataTransferMethod;
11949 int numDataTransferPoint;
11950 int numDataTransferElement = 0, discElements;
11951 int dataTransferRank;
11952 double *dataTransferData;
11953 char *units;
11954
11955 feaLoad->numElementID = 0;
11956 AIM_FREE(feaLoad->pressureMultiDistributeForce){ EG_free(feaLoad->pressureMultiDistributeForce); feaLoad->
pressureMultiDistributeForce = ((void*)0); }
;
11957 AIM_FREE(feaLoad->elementIDSet){ EG_free(feaLoad->elementIDSet); feaLoad->elementIDSet
= ((void*)0); }
;
11958
11959 //See if we have data transfer information
11960 status = aim_getBounds(aimInfo, &numTransferName, &transferName);
11961 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 11961
, __func__, 0); goto cleanup; }
;
11962
11963 numDataTransferElement = 0;
11964 elementIndex = 0;
11965 elementCount = 0;
11966
11967 for (transferNameIndex = 0; transferNameIndex < numTransferName; transferNameIndex++) {
11968
11969 status = aim_getDiscr(aimInfo, transferName[transferNameIndex], &dataTransferDiscreteObj);
11970 if (status == CAPS_NOTFOUND-303) continue;
11971 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 11971
, __func__, 0); goto cleanup; }
;
11972
11973 status = aim_getDataSet(dataTransferDiscreteObj,
11974 "Pressure",
11975 &dataTransferMethod,
11976 &numDataTransferPoint,
11977 &dataTransferRank,
11978 &dataTransferData,
11979 &units);
11980 if (status == CAPS_NOTFOUND-303) continue; // If no elements in this object skip to next transfer name
11981 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 11981
, __func__, 0); goto cleanup; }
;
11982
11983 printf("Extracting external pressure loads from data transfer....\n");
11984
11985 // If we do have data ready, how many elements there are?
11986 if (numDataTransferPoint == 1) {
11987 AIM_ERROR(aimInfo, "Pressures not initialized!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 11987, __func__
, "Pressures not initialized!"); }
;
11988 status = CAPS_BADINIT-338;
11989 goto cleanup;
11990 }
11991
11992 if (dataTransferRank != 1) {
11993 AIM_ERROR(aimInfo, "Pressure transfer data found however rank is %d not 1!!!!", dataTransferRank){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 11993, __func__
, "Pressure transfer data found however rank is %d not 1!!!!"
, dataTransferRank); }
;
11994 status = CAPS_BADRANK-301;
11995 goto cleanup;
11996 }
11997
11998 discElements = 0;
11999 for (bIndex = 0; bIndex < dataTransferDiscreteObj->nBodys; bIndex++)
12000 discElements += dataTransferDiscreteObj->bodys[bIndex].nElems;
12001
12002 numDataTransferElement += discElements;
12003 printf("\tTransferName = %s\n", transferName[transferNameIndex]);
12004 printf("\tNumber of Elements = %d (total = %d)\n", discElements, numDataTransferElement);
12005
12006 // allocate arrays
12007 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", 12007, __func__
, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->elementIDSet"
, memorysize, "int"); goto cleanup; } }
;
12008 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"
, 12008, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->pressureMultiDistributeForce"
, memorysize, "double"); goto cleanup; } }
;
12009
12010 //Now lets loop through our ctria3 mesh and get the node indexes for each element
12011 for (i = 0; i < feaMesh->numElement; i++) {
12012
12013 if (feaMesh->element[i].elementType != Triangle) continue;
12014
12015 elementID = feaMesh->element[i].elementID;
12016 //printf("Element Id = %d\n", elementID);
12017
12018 // elementID is 1 bias
12019 nodeIndex[0] = feaMesh->element[i].connectivity[0];
12020 nodeIndex[1] = feaMesh->element[i].connectivity[1];
12021 nodeIndex[2] = feaMesh->element[i].connectivity[2];
12022
12023 //printf("Node Index = %d %d %d\n", nodeIndex[0], nodeIndex[1], nodeIndex[2]);
12024
12025 transferIndex[0] = -1;
12026 transferIndex[1] = -1;
12027 transferIndex[2] = -1;
12028 transferIndex[3] = -1;
12029
12030 // Loop through the nodeMap of the data set getting nodeIDs trying
12031 // to match the nodes in the element
12032 for (j = 0; j < numDataTransferPoint; j++) {
12033
12034 bIndex = dataTransferDiscreteObj->tessGlobal[2*j ];
12035 globalNodeID = dataTransferDiscreteObj->tessGlobal[2*j+1] +
12036 dataTransferDiscreteObj->bodys[bIndex-1].globalOffset;
12037
12038 if (nodeIndex[0] == globalNodeID) transferIndex[0] = j;
12039 if (nodeIndex[1] == globalNodeID) transferIndex[1] = j;
12040 if (nodeIndex[2] == globalNodeID) transferIndex[2] = j;
12041
12042 // If the nodes completely match the nodes on the element - break
12043 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && transferIndex[2] >= 0) {
12044 break;
12045 }
12046 }
12047
12048 // If all the nodeIndexes match the transferIndex the element is in the data set
12049 // so transfer the pressure forces
12050 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && transferIndex[2] >= 0) {
12051
12052 feaLoad->elementIDSet[elementIndex] = elementID;
12053
12054 feaLoad->pressureMultiDistributeForce[4*elementIndex+0] = dataTransferData[transferIndex[0]];
12055 feaLoad->pressureMultiDistributeForce[4*elementIndex+1] = dataTransferData[transferIndex[1]];
12056 feaLoad->pressureMultiDistributeForce[4*elementIndex+2] = dataTransferData[transferIndex[2]];
12057 feaLoad->pressureMultiDistributeForce[4*elementIndex+3] = 0.0;
12058
12059 elementIndex += 1;
12060 elementCount += 1;
12061 feaLoad->numElementID += 1;
12062
12063 }
12064 }
12065
12066 //Now lets loop through our cquad4 mesh and get the node indexes for each element
12067 for (i = 0; i < feaMesh->numElement; i++) {
12068
12069 if (feaMesh->element[i].elementType != Quadrilateral) continue;
12070
12071 elementID = feaMesh->element[i].elementID;
12072
12073 // elementID is 1 bias
12074 nodeIndex[0] = feaMesh->element[i].connectivity[0];
12075 nodeIndex[1] = feaMesh->element[i].connectivity[1];
12076 nodeIndex[2] = feaMesh->element[i].connectivity[2];
12077 nodeIndex[3] = feaMesh->element[i].connectivity[3];
12078
12079 transferIndex[0] = -1;
12080 transferIndex[1] = -1;
12081 transferIndex[2] = -1;
12082 transferIndex[3] = -1;
12083
12084 // Loop through the nodeMap of the data set getting nodeIDs trying
12085 // to match the nodes in the element
12086 for (j = 0; j < numDataTransferPoint; j++) {
12087
12088 bIndex = dataTransferDiscreteObj->tessGlobal[2*j ];
12089 globalNodeID = dataTransferDiscreteObj->tessGlobal[2*j+1] +
12090 dataTransferDiscreteObj->bodys[bIndex-1].globalOffset;
12091
12092 if (nodeIndex[0] == globalNodeID) transferIndex[0] = j;
12093 if (nodeIndex[1] == globalNodeID) transferIndex[1] = j;
12094 if (nodeIndex[2] == globalNodeID) transferIndex[2] = j;
12095 if (nodeIndex[3] == globalNodeID) transferIndex[3] = j;
12096
12097 // If the nodes completely match the nodes on the element - break
12098 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 &&
12099 transferIndex[2] >= 0 && transferIndex[3] >= 0) {
12100 break;
12101 }
12102 }
12103
12104 // If all the nodeIndexes match the transferIndex the element is in the data set
12105 // so transfer the pressure forces
12106 if (transferIndex[0] >= 0 && transferIndex[1] >= 0 &&
12107 transferIndex[2] >= 0 && transferIndex[3] >= 0) {
12108
12109 feaLoad->elementIDSet[elementIndex] = elementID;
12110
12111 feaLoad->pressureMultiDistributeForce[4*elementIndex+0] = dataTransferData[transferIndex[0]];
12112 feaLoad->pressureMultiDistributeForce[4*elementIndex+1] = dataTransferData[transferIndex[1]];
12113 feaLoad->pressureMultiDistributeForce[4*elementIndex+2] = dataTransferData[transferIndex[2]];
12114 feaLoad->pressureMultiDistributeForce[4*elementIndex+3] = dataTransferData[transferIndex[3]];
12115
12116 elementIndex += 1;
12117 elementCount += 1;
12118 feaLoad->numElementID += 1;
12119 }
12120 }
12121
12122 if (elementCount != numDataTransferElement) {
12123 AIM_ERROR(aimInfo, "Element transfer mismatch: number of elements found = %d, number"{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12124, __func__
, "Element transfer mismatch: number of elements found = %d, number"
" of elements in transfer data set %d", elementCount, numDataTransferElement
); }
12124 " of elements in transfer data set %d", elementCount, numDataTransferElement){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12124, __func__
, "Element transfer mismatch: number of elements found = %d, number"
" of elements in transfer data set %d", elementCount, numDataTransferElement
); }
;
12125 AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); };
12126
12127 status = CAPS_MISMATCH-324;
12128 goto cleanup;
12129 }
12130
12131 // Resize
12132 if (feaLoad->numElementID != numDataTransferElement) {
12133 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", 12133, __func__
, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->pressureMultiDistributeForce"
, memorysize, "double"); goto cleanup; } }
;
12134 }
12135
12136 } // End data transfer name loop
12137
12138
12139 status = CAPS_SUCCESS0;
12140
12141cleanup:
12142
12143 AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); };
12144
12145 return status;
12146}
12147
12148// Transfer external temperature from the discrObj into the feaLoad structure
12149int fea_transferExternalTemperature(void *aimInfo, feaLoadStruct *feaLoad) {
12150
12151 // [in/out] feaLoad
12152 // [in] aimInfo
12153
12154 int status; // Function status return
12155
12156 int i, bIndex; // Indexing
12157
12158 // Variables used in global node mapping
12159 int globalNodeID;
12160
12161 // Discrete data transfer variables
12162 capsDiscr *dataTransferDiscreteObj;
12163 char **transferName = NULL((void*)0);
12164 int numTransferName, transferNameIndex;
12165 enum capsdMethod dataTransferMethod;
12166 int numDataTransferPoint;
12167 int dataTransferRank;
12168 double *dataTransferData;
12169 char *units;
12170
12171 feaLoad->numGridID = 0;
12172 AIM_FREE(feaLoad->temperatureMultiDistribute){ EG_free(feaLoad->temperatureMultiDistribute); feaLoad->
temperatureMultiDistribute = ((void*)0); }
;
12173 AIM_FREE(feaLoad->gridIDSet){ EG_free(feaLoad->gridIDSet); feaLoad->gridIDSet = ((void
*)0); }
;
12174
12175 //See if we have data transfer information
12176 status = aim_getBounds(aimInfo, &numTransferName, &transferName);
12177 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12177
, __func__, 0); goto cleanup; }
;
12178
12179 for (transferNameIndex = 0; transferNameIndex < numTransferName; transferNameIndex++) {
12180
12181 status = aim_getDiscr(aimInfo, transferName[transferNameIndex], &dataTransferDiscreteObj);
12182 if (status == CAPS_NOTFOUND-303) continue;
12183 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12183
, __func__, 0); goto cleanup; }
;
12184
12185 status = aim_getDataSet(dataTransferDiscreteObj,
12186 "Temperature",
12187 &dataTransferMethod,
12188 &numDataTransferPoint,
12189 &dataTransferRank,
12190 &dataTransferData,
12191 &units);
12192 if (status == CAPS_NOTFOUND-303) continue; // If no elements in this object skip to next transfer name
12193 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12193
, __func__, 0); goto cleanup; }
;
12194
12195 printf("Extracting external thermal loads from data transfer....\n");
12196
12197 // If we do have data ready, how many elements there are?
12198 if (numDataTransferPoint == 1) {
12199 AIM_ERROR(aimInfo, "Temperature not initialized!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12199, __func__
, "Temperature not initialized!"); }
;
12200 status = CAPS_BADINIT-338;
12201 goto cleanup;
12202 }
12203
12204 if (dataTransferRank != 1) {
12205 AIM_ERROR(aimInfo, "Temperature transfer data found however rank is %d not 1!!!!", dataTransferRank){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12205, __func__
, "Temperature transfer data found however rank is %d not 1!!!!"
, dataTransferRank); }
;
12206 status = CAPS_BADRANK-301;
12207 goto cleanup;
12208 }
12209
12210 printf("\tTransferName = %s\n", transferName[transferNameIndex]);
12211 printf("\tNumber of Nodes = %d (total = %d)\n", numDataTransferPoint, feaLoad->numGridID+numDataTransferPoint);
12212
12213 // allocate arrays
12214 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"
, 12214, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->gridIDSet"
, memorysize, "int"); goto cleanup; } }
;
12215 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", 12215
, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->temperatureMultiDistribute"
, memorysize, "double"); goto cleanup; } }
;
12216
12217 // Loop through the nodeMap of the data set getting nodeIDs trying
12218 // to match the nodes in the element
12219 for (i = 0; i < numDataTransferPoint; i++) {
12220
12221 bIndex = dataTransferDiscreteObj->tessGlobal[2*i ];
12222 globalNodeID = dataTransferDiscreteObj->tessGlobal[2*i+1] +
12223 dataTransferDiscreteObj->bodys[bIndex-1].globalOffset;
12224
12225 feaLoad->gridIDSet[feaLoad->numGridID+i] = globalNodeID;
12226 feaLoad->temperatureMultiDistribute[feaLoad->numGridID+i] = dataTransferData[i];
12227 }
12228
12229 feaLoad->numGridID += numDataTransferPoint;
12230
12231 } // End data transfer name loop
12232
12233 status = CAPS_SUCCESS0;
12234
12235cleanup:
12236
12237 AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); };
12238
12239 return status;
12240}
12241
12242// Retrieve aerodynamic reference quantities from bodies
12243int fea_retrieveAeroRef(int numBody, ego *bodies, feaAeroRefStruct *feaAeroRef) {
12244
12245 int status; // Function return status
12246 int body;
12247
12248 // EGADS return values
12249 int atype, alen;
12250 const int *ints;
12251 const char *string;
12252 const double *reals;
12253
12254 // Get reference quantities from the bodies
12255 for (body = 0; body < numBody; body++) {
12256
12257 status = EG_attributeRet(bodies[body], "capsReferenceArea", &atype, &alen, &ints, &reals, &string);
12258 if (status == EGADS_SUCCESS0 && atype == Double) {
12259
12260 feaAeroRef->refArea = (double) reals[0];
12261 }
12262
12263 status = EG_attributeRet(bodies[body], "capsReferenceChord", &atype, &alen, &ints, &reals, &string);
12264 if (status == EGADS_SUCCESS0 && atype == Double){
12265
12266 feaAeroRef->refChord = (double) reals[0];
12267 }
12268
12269 status = EG_attributeRet(bodies[body], "capsReferenceSpan", &atype, &alen, &ints, &reals, &string);
12270 if (status == EGADS_SUCCESS0 && atype == Double) {
12271
12272 feaAeroRef->refSpan = (double) reals[0];
12273 }
12274
12275 /*
12276 status = EG_attributeRet(bodies[body], "capsReferenceX", &atype, &alen, &ints, &reals, &string);
12277 if (status == EGADS_SUCCESS && atype == Double) {
12278 XX = (double) reals[0];
12279 }
12280
12281 status = EG_attributeRet(bodies[body], "capsReferenceY", &atype, &alen, &ints, &reals, &string);
12282 if (status == EGADS_SUCCESS && atype == Double) {
12283 XX = (double) reals[0];
12284 }
12285
12286 status = EG_attributeRet(bodies[body], "capsReferenceZ", &atype, &alen, &ints, &reals, &string);
12287 if (status == EGADS_SUCCESS && atype == Double) {
12288 XX = (double) reals[0];
12289 }
12290 */
12291 }
12292
12293 return CAPS_SUCCESS0;
12294}
12295
12296
12297// Assign element "subtypes" based on properties set
12298int fea_assignElementSubType(int numProperty, feaPropertyStruct *feaProperty, meshStruct *feaMesh)
12299{
12300 int propertyIndex, i ;
12301
12302 feaMeshDataStruct *feaData;
12303
12304 if (numProperty > 0 && feaProperty == NULL((void*)0)) return CAPS_NULLVALUE-307;
12305 if (feaMesh == NULL((void*)0)) return CAPS_NULLVALUE-307;
12306
12307 printf("Updating mesh element types based on properties input\n");
12308
12309 for (propertyIndex = 0; propertyIndex < numProperty; propertyIndex++ ) {
12310
12311 // Types that don't need subtypes - setting this correctly requires knowledge of what mesh_writeNastran
12312 // writes by default for each mesh element type
12313 if (feaProperty[propertyIndex].propertyType == Rod ||
12314 //feaProperty[propertyIndex].propertyType == Shell ||
12315 //feaProperty[propertyIndex].propertyType == Composite ||
12316 feaProperty[propertyIndex].propertyType == Solid) continue;
12317
12318 for (i = 0; i < feaMesh->numElement; i++) {
12319
12320 // What if this is a volume mesh we inherited ?
12321 if (feaMesh->element[i].analysisType != MeshStructure) {
12322 printf("Developer error: Analysis type not set to MeshStructure for element %d\n", feaMesh->element[i].elementID);
12323 return CAPS_BADVALUE-311;
12324 }
12325
12326 // Matching proptery id
12327 if (feaMesh->element[i].analysisData != NULL((void*)0)) {
12328 feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
12329
12330 if (feaData->propertyID != feaProperty[propertyIndex].propertyID) continue;
12331
12332 } else {
12333 printf("Developer error: No 'feaData' set on element %d\n", feaMesh->element[i].elementID);
12334 return CAPS_BADVALUE-311;
12335
12336 }
12337
12338// if (feaMesh->element[i].markerID != feaProperty[propertyIndex].propertyID) continue;
12339//
12340// feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData;
12341// if (feaData->propertyID != feaProperty[propertyIndex].propertyID) {
12342// printf("Developer error: Property ID mismatch between element \"markerID\" (%d) and feaData \"propertyID\" (%d) for element %d\n",
12343// feaData->propertyID, feaProperty[propertyIndex].propertyID, feaMesh->element[i].elementID);
12344// return CAPS_BADVALUE;
12345// }
12346
12347
12348 if (feaProperty[propertyIndex].propertyType == ConcentratedMass &&
12349 feaMesh->element[i].elementType == Node) {
12350
12351 feaData->elementSubType = ConcentratedMassElement;
12352 }
12353
12354 if (feaProperty[propertyIndex].propertyType == Bar &&
12355 feaMesh->element[i].elementType == Line) {
12356
12357 feaData->elementSubType = BarElement;
12358 }
12359
12360 if (feaProperty[propertyIndex].propertyType == Beam &&
12361 feaMesh->element[i].elementType == Line) {
12362
12363 feaData->elementSubType = BeamElement;
12364 }
12365
12366 if (feaProperty[propertyIndex].propertyType == Shear &&
12367 feaMesh->element[i].elementType == Quadrilateral){
12368
12369 feaData->elementSubType = ShearElement;
12370 }
12371
12372 if (feaProperty[propertyIndex].propertyType == Membrane &&
12373 feaMesh->element[i].elementType == Quadrilateral){
12374
12375 feaData->elementSubType = MembraneElement;
12376 }
12377
12378 // Only need to set these if the zOffset is needed based on mesh_writeNASTRAN
12379 if ( ( feaProperty[propertyIndex].propertyType == Shell || feaProperty[propertyIndex].propertyType == Composite ) &&
12380 feaProperty[propertyIndex].zOffsetRel != 0.0 &&
12381 ( feaMesh->element[i].elementType == Quadrilateral ||
12382 feaMesh->element[i].elementType == Triangle ||
12383 feaMesh->element[i].elementType == Triangle_6 ||
12384 feaMesh->element[i].elementType == Quadrilateral_8)) {
12385
12386 feaData->elementSubType = ShellElement;
12387 }
12388 }
12389 }
12390
12391 return CAPS_SUCCESS0;
12392}
12393
12394// Create connections for gluing - Connections are appended
12395int fea_glueMesh(meshStruct *mesh,
12396 int connectionID,
12397 /*@unused@*/ int connectionType,
12398 int dofDependent,
12399 char *slaveName,
12400 int numMasterName,
12401 char *masterName[],
12402 mapAttrToIndexStruct *attrMap,
12403 int maxNumMaster,
12404 double searchRadius,
12405 int *numConnect,
12406 feaConnectionStruct *feaConnect[]) {
12407
12408 // Input parameters
12409 //double exactTol=1E-9;
12410 //int weigthing = 1; // 1=linear
12411
12412 int masterWeight = 1;
12413 int masterComponent = 123;
12414
12415 int status;
12416 int i, masterIndex, slaveIndex, distIndex, attrIndex;
12417
12418 int numMaster;
12419
12420 int *glueConn=NULL((void*)0);
12421 double *glueDist=NULL((void*)0);
12422
12423 double dist, maxDist;
12424
12425 feaMeshDataStruct *feaData, *feaDataMaster;
12426
12427// int numConnect;
12428// feaConnectionStruct *feaConnect;
12429
12430
12431// maps from nodeID to mesh->node index
12432// mesh_nodeID2Array(nasMesh, &n2a);
12433
12434 printf("\tCreating glue connections\n");
12435
12436 if (searchRadius <=0) {
12437 printf("\tSearch radius must be greater than 0 when gluing, current value = %g\n", searchRadius);
12438 status = CAPS_BADVALUE-311;
12439 goto cleanup;
12440 }
12441
12442 status = array_allocIntegerVector(maxNumMaster, -1, &glueConn);
12443 if (status != CAPS_SUCCESS0) goto cleanup;
12444
12445 status = array_allocDoubleVector(maxNumMaster, 1E9, &glueDist);
12446 if (status != CAPS_SUCCESS0) goto cleanup;
12447
12448 for (slaveIndex = 0; slaveIndex < mesh->numNode; slaveIndex++) {
12449
12450 feaData = (feaMeshDataStruct *) mesh->node[slaveIndex].analysisData;
12451
12452 status = get_mapAttrToIndexIndex(attrMap, (const char *) slaveName, &attrIndex);
12453 if (status == CAPS_NOTFOUND-303) {
12454 printf("\tName %s not found in attribute map of capsConnect!!!!\n", slaveName);
12455 continue;
12456 } else if (status != CAPS_SUCCESS0) return status;
12457
12458 if (feaData->connectIndex != attrIndex) continue;
12459
12460 // We have a slave at this point
12461
12462 // printf("Slave - node ID %d\n", mesh->node[slaveIndex].nodeID);
12463
12464 status = array_setDoubleVectorValue(maxNumMaster, 1E9, &glueDist);
12465 if (status != CAPS_SUCCESS0) goto cleanup;
12466
12467 status = array_setIntegerVectorValue(maxNumMaster, -1, &glueConn);
12468 if (status != CAPS_SUCCESS0) goto cleanup;
12469
12470 for (masterIndex = 0; masterIndex < mesh->numNode; masterIndex++) {
12471
12472 if (slaveIndex == masterIndex) continue;
12473
12474 feaDataMaster = (feaMeshDataStruct *) mesh->node[masterIndex].analysisData;
12475
12476 for (i = 0; i < numMasterName; i++) {
12477 status = get_mapAttrToIndexIndex(attrMap, (const char *) masterName[i], &attrIndex);
12478 if (status == CAPS_NOTFOUND-303) {
12479 printf("\tName %s not found in attribute map of capsConnect!!!!\n", masterName[i]);
12480 continue;
12481 } else if (status != CAPS_SUCCESS0) return status;
12482
12483 if (feaDataMaster->connectIndex != attrIndex) continue;
12484
12485 break;
12486 }
12487
12488 if (i >= numMasterName) continue;
12489
12490 // We have a potential master at this point
12491
12492 dist = dist_DoubleVal(mesh->node[masterIndex].xyz, mesh->node[slaveIndex].xyz);
12493
12494 //printf("dist = %f (radius = %f), masterIndex %d\n", dist, searchRadius, masterIndex);
12495
12496 if ( dist > searchRadius) continue;
12497
12498 status = array_maxDoubleValue(maxNumMaster, glueDist, &distIndex, &maxDist);
12499 if (status != CAPS_SUCCESS0) goto cleanup;
12500
12501 //printf("dist = %f, maxdist = %e (index = %d)\n", dist, maxDist, distIndex);
12502
12503 if (dist < maxDist) {
12504 glueDist[distIndex] = dist;
12505 glueConn[distIndex] = masterIndex;
12506 }
12507 } // End of master loop
12508
12509 // How many masters were found
12510 numMaster = 0;
12511 for (i = 0; i < maxNumMaster; i++) {
12512 if (glueDist[i] > searchRadius) continue; // Nothing was every set
12513 numMaster += 1;
12514 }
12515
12516 if (numMaster <= 0) {
12517 printf("\tWarning: no masters were found for slave node (id = %d, slave name = %s)!\n", mesh->node[slaveIndex].nodeID, slaveName);
12518 } else {
12519 // Create and set connections
12520 status = fea_setConnection(slaveName,
12521 RigidBodyInterpolate,
12522 connectionID,
12523 mesh->numElement,
12524 dofDependent,
12525 0.0,
12526 0.0,
12527 0.0,
12528 0,
12529 0,
12530 mesh->node[slaveIndex].nodeID,
12531 masterWeight,
12532 masterComponent,
12533 numMaster, glueConn,
12534 numConnect,feaConnect);
12535 if (status != CAPS_SUCCESS0) goto cleanup;
12536 }
12537//
12538// *numConnect += 1;
12539//
12540// (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),*numConnect*sizeof(feaConnectionStruct));
12541// if ((*feaConnect) == NULL) {
12542// *numConnect = 0;
12543// status = EGADS_MALLOC;
12544// goto cleanup;
12545// }
12546//
12547// status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect-1]);
12548// if (status != CAPS_SUCCESS) goto cleanup;
12549//
12550// (*feaConnect)[*numConnect-1].name = (char *) EG_alloc((strlen(slaveName) + 1)*sizeof(char));
12551// if ((*feaConnect)[*numConnect-1].name == NULL) {
12552// status = EGADS_MALLOC;
12553// goto cleanup;
12554// }
12555//
12556// memcpy((*feaConnect)[*numConnect-1].name, slaveName, strlen(slaveName)*sizeof(char));
12557// (*feaConnect)[*numConnect-1].name[strlen(slaveName)] = '\0';
12558//
12559// (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index
12560// (*feaConnect)[*numConnect-1].connectionType = connectionType;
12561//
12562// (*feaConnect)[*numConnect-1].elementID = *numConnect + mesh->numElement;
12563//
12564// (*feaConnect)[*numConnect-1].dofDependent = dofDependent;
12565//
12566// (*feaConnect)[*numConnect-1].connectivity[1] = mesh->node[slaveIndex].nodeID; // Dependent
12567// (*feaConnect)[*numConnect-1].numMaster = numMaster; // Independent
12568//
12569// (*feaConnect)[*numConnect-1].masterIDSet = (int *) EG_alloc(numMaster*sizeof(int)); // [numMaster]
12570// if ((*feaConnect)[*numConnect-1].masterIDSet == NULL) {
12571// status = EGADS_MALLOC;
12572// goto cleanup;
12573// }
12574// (*feaConnect)[*numConnect-1].masterWeighting = (double *) EG_alloc(numMaster*sizeof(double));; // [numMaster]
12575// if ((*feaConnect)[*numConnect-1].masterWeighting == NULL) {
12576// status = EGADS_MALLOC;
12577// goto cleanup;
12578// }
12579//
12580// (*feaConnect)[*numConnect-1].masterComponent =(int *) EG_alloc(numMaster*sizeof(int));; // [numMaster]
12581// if ((*feaConnect)[*numConnect-1].masterComponent == NULL) {
12582// status = EGADS_MALLOC;
12583// goto cleanup;
12584// }
12585//
12586// printf("\tMasters (%d)", numMaster);
12587//
12588// // Master values;
12589// numMaster = 0;
12590// for (i = 0; i < maxNumMaster; i++) {
12591// if (glueDist[i] > searchRadius) continue; // Nothing was every set
12592// printf(" %d(%d)", mesh->node[glueConn[i]].nodeID, glueConn[i]);
12593// (*feaConnect)[*numConnect-1].masterIDSet[numMaster] = mesh->node[glueConn[i]].nodeID;
12594// (*feaConnect)[*numConnect-1].masterWeighting[numMaster] = masterWeight;
12595// (*feaConnect)[*numConnect-1].masterComponent[numMaster] = masterComponent;
12596// numMaster += 1;
12597// }
12598// printf("\n");
12599
12600 } // End of slave loop
12601
12602 cleanup:
12603 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_glueMesh, status = %d\n", status);
12604
12605 if (glueDist != NULL((void*)0)) EG_free(glueDist);
12606 if (glueConn != NULL((void*)0)) EG_free(glueConn);
12607
12608 return status;
12609}
12610
12611//int fea_glueMesh2(meshStruct *meshIn,
12612//
12613// mapAttrToIndexStruct *attrMap) {
12614//
12615// // Input parameters
12616// int numGlue=5;
12617// double exactTol=1E-9;
12618// double radiusOfInfluence = 0.1;//1E-3;
12619// int weigthing = 1; // 1=linear
12620//
12621// int status;
12622// int i, j, k, m, masterIndex, slaveIndex, distIndex;
12623// int found;
12624//
12625// int numMesh;
12626// meshStruct *mesh, *master, *slave, *search;
12627//
12628// int **glueConn=NULL;
12629// double **glueDist=NULL;
12630//
12631// double *tempDist=NULL;
12632// int *tempGlue=NULL;
12633// int numNode = 0;
12634// int *meshIndexStart=NULL;
12635//
12636// double dist, maxDist;
12637//
12638// feaMeshDataStruct *feaData;
12639//
12640//// maps from nodeID to mesh->node index
12641//// mesh_nodeID2Array(nasMesh, &n2a);
12642//
12643// printf("Welcome to glueing!\n");
12644// numMesh = meshIn->numReferenceMesh;
12645// mesh = meshIn->referenceMesh;
12646//
12647// printf("Start with allocation!\n");
12648// status = array_allocIntegerVector(numMesh, 0, &meshIndexStart);
12649// if (status != CAPS_SUCCESS) goto cleanup;
12650//
12651// // Determine number of nodes in reference meshes - Remember capsIgnore may have already been applied
12652// for (i=0; i < numMesh; i++) {
12653// meshIndexStart[i] = numNode;
12654// numNode += mesh[i].numNode;
12655// }
12656//
12657// if (numNode != meshIn->numNode) {
12658// printf("Inconsistent number of nodes determined!");
12659// status = CAPS_MISMATCH;
12660// goto cleanup;
12661// }
12662//
12663// // glueConn structure:
12664// // glueConn[row][col] where [row] is node index and
12665// // [row][0] : 1=master, 0=slave, -1=unused
12666// // [row][1:numGlue+1] : nearest node indices, -1=unused
12667// status = array_allocIntegerMatrix(numNode, numGlue+1, -1, &glueConn);
12668// if (status != CAPS_SUCCESS) goto cleanup;
12669//
12670// // glueDist structure:
12671// // glueDist[row][col] where [row] is node index and
12672// // [row][0:numGlue] : distance to nearest node indices found in glueConn[row][1:numGlue+1]
12673// status = array_allocDoubleMatrix(numNode, numGlue, -1, &glueDist);
12674// if (status != CAPS_SUCCESS) goto cleanup;
12675//
12676// status = array_allocIntegerVector(numGlue, 0, &tempGlue);
12677// if (status != CAPS_SUCCESS) goto cleanup;
12678//
12679// status = array_allocDoubleVector(numGlue, 0, &tempDist);
12680// if (status != CAPS_SUCCESS) goto cleanup;
12681//
12682// printf("Done with allocation!\n");
12683//
12684// // Lets mark all slaves
12685// //
12686//
12687// int attrIndex;
12688// int numSlave=1;
12689// char slaveName[] = "slave";
12690// int numMasterName;
12691// char **masterName;
12692//
12693// for (i = 0; i < numNode; i++) {
12694//
12695// feaData = (feaMeshDataStruct *) meshIn->node[i].analysisData;
12696//
12697// for (j = 0; j < numSlave; j++) {
12698// status = get_mapAttrToIndexIndex(attrMap, (const char *) slaveName, &attrIndex);
12699// if (status == CAPS_NOTFOUND) {
12700// printf("\tName %s not found in attribute map of capsConnect!!!!\n", slaveName);
12701// continue;
12702// } else if (status != CAPS_SUCCESS) return status;
12703//
12704//
12705// if (feaData->connectIndex != attrIndex) continue;
12706//
12707// glueConn[i][0] = 0;
12708// break;
12709// }
12710//
12711// if (glueConn[i][0] != 0) continue;
12712//
12713// status = string_toStringDynamicArray('["master"]', &numMasterName, &masterName);
12714// if (status != CAPS_SUCCESS); goto cleanup;
12715//
12716// for (k = 0; k < numNode; k++) {
12717//
12718// if (i == k) continue;
12719// for (m = 0; m < numMasterName; m++) {
12720//
12721// }
12722// }
12723//
12724//
12725// (void) string_freeArray(numMasterName, &masterName);
12726// masterName = NULL;
12727// numMasterName = 0;
12728// }
12729//
12730//
12731// // for (i = 0; i < numMesh; i++) { // THIS IS MOSTLY correct - error in master slave relation of RBE3 elements
12732//// master = &mesh[i];
12733////
12734////// printf("Master Mesh %d (of %d)\n", i, numMesh);
12735//// //Exhaustive search
12736//// for (masterIndex = 0; masterIndex < master->numNode; masterIndex++) {
12737////
12738////// printf("master index %d (of %d)\n", masterIndex, master->numNode);
12739//// // Slaves may be promoted to masters, but cannot be slaves to multiple masters
12740//// //if (glueConn[masterIndex+meshIndexStart[masterIndex]][0] != 0) continue;
12741////
12742//// status = array_setDoubleVectorValue(numGlue, 1E9, &tempDist);
12743//// if (status != CAPS_SUCCESS) goto cleanup;
12744////
12745//// status = array_setIntegerVectorValue(numGlue, -1, &tempGlue);
12746//// if (status != CAPS_SUCCESS) goto cleanup;
12747////
12748//// for (j = 0; j < numMesh; j++) {
12749////
12750//// if (i == j) continue;
12751////
12752//// slave = &mesh[j];
12753////
12754//// for (slaveIndex = 0; slaveIndex < slave->numNode; slaveIndex++) {
12755////
12756//// // Slaves cannot have multiple masters - FALSE
12757//// if (glueConn[slaveIndex+meshIndexStart[j]][0] == 0) continue;
12758////
12759//// // Make sure master slave relation doesn't already exist
12760//// found = (int) false;
12761//// for (k =1; k < numGlue+1; k++) {
12762//// if (masterIndex+meshIndexStart[i] == glueConn[slaveIndex+meshIndexStart[j]][k]){
12763//// found = (int) true;
12764//// break;
12765//// }
12766//// }
12767////
12768//// if (found == (int) true) continue;
12769////
12770////// printf("glueConn %d\n", glueConn[slaveIndex+meshIndexStart[j]][0]);
12771////
12772//// dist = dist_DoubleVal(master->node[masterIndex].xyz, slave->node[slaveIndex].xyz);
12773////
12774////// printf("dist = %f (radius = %f)\n", dist, radiusOfInfluence);
12775////
12776//// if ( dist > radiusOfInfluence) continue;
12777////
12778//// status = array_maxDoubleValue(numGlue, tempDist, &distIndex, &maxDist);
12779//// if (status != CAPS_SUCCESS) goto cleanup;
12780////
12781//// //printf("dist = %f, maxdist = %e (index = %d)\n", dist, maxDist, distIndex);
12782////
12783//// if (dist < maxDist) {
12784//// tempDist[distIndex] = dist;
12785//// tempGlue[distIndex] = slaveIndex + meshIndexStart[j] ;
12786//// }
12787//// }
12788//// }
12789////
12790//// if (tempDist[0] > radiusOfInfluence) continue; // Nothing was every set
12791////
12792//// // glueConn structure:
12793//// // glueConn[row][col] where [row] is node index and
12794//// // [row][0] : 1=master, 0=slave, -1=unused
12795//// // [row][1:numGlue+1] : nearest node indices, -1=unused
12796////
12797//// // glueDist[row][col] where [row] is node index and
12798//// // [row][0:numGlue] : distance to nearest node indices found in glueConn[row][1:numGlue+1]
12799////
12800//// glueConn[masterIndex+meshIndexStart[i]][0] = 1; //Mark as Master
12801//// distIndex = 0;
12802//// for (j = 0; j < numGlue; j++) {
12803//// if (tempDist[j] > radiusOfInfluence) continue; // Nothing was every set
12804////
12805//// glueDist[masterIndex+meshIndexStart[i]][distIndex] = tempDist[j]; // Distances for a master
12806//// glueConn[masterIndex+meshIndexStart[i]][distIndex+1] = tempGlue[j]; // Glue connections/slaves for a master
12807////
12808//// // Mark the masters slave's as slaves - A slave can become a master to another slave,
12809//// // but it can not be a slave to another master
12810//// if (glueConn[tempGlue[j]][0] < 0) glueConn[tempGlue[j]][0] = 0;
12811////
12812//// distIndex +=1;
12813//// }
12814////
12815//// printf("Set %d : %d: ",masterIndex+meshIndexStart[i], glueConn[masterIndex+meshIndexStart[i]][0]);
12816//// for(j = 0; j < numGlue; j++) {
12817//// printf("%d ", glueConn[masterIndex+meshIndexStart[i]][j+1]);
12818//// }
12819//// printf("\n");
12820//// }
12821//// }
12822////
12823//// for (i = 0; i < numNode;i++) {
12824//// if (glueConn[i][0] < 0) continue;
12825//// printf("Node %d : %d : ", i, glueConn[i][0]);
12826//// for(j = 0; j < numGlue; j++) {
12827////// printf("%d (%.2f)", glueConn[i][j+1], glueDist[i][j]);
12828//// printf("%d ", glueConn[i][j+1]);
12829//// }
12830//// printf("\n");
12831//// }
12832//// // Finished getting all my glue
12833//
12834// cleanup:
12835// if (status != CAPS_SUCCESS) printf("\tPremature exit in fea_glueMesh, status = %d\n", status);
12836//
12837// if (tempDist != NULL) EG_free(tempDist);
12838// if (tempGlue != NULL) EG_free(tempGlue);
12839// if (meshIndexStart != NULL) EG_free(meshIndexStart);
12840//
12841// if (glueConn != NULL) (void) array_freeIntegerMatrix(numNode, numGlue, &glueConn);
12842//
12843// if (glueDist != NULL) (void) array_freeDoubleMatrix(numNode, numGlue, &glueDist);
12844//
12845// (void) string_freeArray(numMasterName, &masterName);
12846// masterName = NULL;
12847//
12848// return status;
12849//}
12850
12851// Create a default analysis structure based on previous inputs
12852int fea_createDefaultAnalysis(feaProblemStruct *feaProblem, const char *analysisType) {
12853
12854 int status;
12855 int i;
12856
12857 capsTuple *tupleVal;
12858
12859 char *json=NULL((void*)0);
12860 int maxSize=2048;
12861
12862 if (feaProblem == NULL((void*)0)) return CAPS_NULLVALUE-307;
12863
12864 if (feaProblem->numAnalysis != 0 || feaProblem->feaAnalysis != NULL((void*)0)) {
12865 // Destroy our analysis structures coming in if aren't 0 and NULL already
12866 for (i = 0; i < feaProblem->numAnalysis; i++) {
12867 status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]);
12868 if (status != CAPS_SUCCESS0) return status;
12869 }
12870
12871 if (feaProblem->feaAnalysis != NULL((void*)0)) EG_free(feaProblem->feaAnalysis);
12872 feaProblem->feaAnalysis = NULL((void*)0);
12873 feaProblem->numAnalysis = 0;
12874 }
12875
12876 tupleVal = (capsTuple *) EG_alloc(1*sizeof(capsTuple));
12877 if (tupleVal == NULL((void*)0)) {
12878 status = EGADS_MALLOC-4;
12879 goto cleanup;
12880 }
12881 tupleVal[0].name = NULL((void*)0);
12882 tupleVal[0].value = NULL((void*)0);
12883
12884 json = (char *) EG_alloc(maxSize*sizeof(char));
12885 if (json == NULL((void*)0)) {
12886 status = EGADS_MALLOC-4;
12887 goto cleanup;
12888 }
12889
12890 strcpy(json,"{\"analysisType\":\"");
12891 if (strcasecmp(analysisType, "Optimization") == 0) strcat(json,"Static");
12892 else strcat(json, analysisType);
12893 strcat(json,"\"");
12894
12895 if (feaProblem->numLoad != 0) {
12896 strcat(json,",\"analysisLoad\":[");
12897 for (i = 0; i < feaProblem->numLoad; i++) {
12898 if (i != 0) strcat(json,",");
12899 strcat(json,"\"");
12900 strcat(json,feaProblem->feaLoad[i].name);
12901 strcat(json,"\"");
12902 }
12903 strcat(json, "]");
12904 }
12905
12906 if (feaProblem->numConstraint != 0) {
12907 strcat(json,",\"analysisConstraint\":[");
12908 for (i = 0; i < feaProblem->numConstraint; i++) {
12909 if (i != 0) strcat(json,",");
12910 strcat(json,"\"");
12911 strcat(json,feaProblem->feaConstraint[i].name);
12912 strcat(json,"\"");
12913 }
12914 strcat(json, "]");
12915 }
12916
12917 if (feaProblem->numSupport != 0) {
12918 strcat(json,",\"analysisSupport\":[");
12919 for (i = 0; i < feaProblem->numSupport; i++) {
12920 if (i != 0) strcat(json,",");
12921 strcat(json,"\"");
12922 strcat(json,feaProblem->feaSupport[i].name);
12923 strcat(json,"\"");
12924 }
12925 strcat(json, "]");
12926 }
12927
12928 if (feaProblem->numDesignConstraint != 0) {
12929 strcat(json,",\"analysisDesignConstraint\":[");
12930 for (i = 0; i < feaProblem->numDesignConstraint; i++) {
12931 if (i != 0) strcat(json,",");
12932 strcat(json,"\"");
12933 strcat(json,feaProblem->feaDesignConstraint[i].name);
12934 strcat(json,"\"");
12935 }
12936 strcat(json, "]");
12937 }
12938
12939 strcat(json,"}");
12940
12941 tupleVal[0].name = EG_strdup("Default");
12942 tupleVal[0].value = json;
12943
12944 //printf("Default analysis tuple - %s\n", tupleVal[0].value);
12945
12946 status = fea_getAnalysis(1,
12947 tupleVal,
12948 feaProblem);
12949 if (status != CAPS_SUCCESS0) goto cleanup;
12950
12951// feaProblem->numAnalysis = 1;
12952// feaProblem->feaAnalysis = (feaAnalysisStruct *) EG_alloc(feaProblem->numAnalysis*sizeof(feaAnalysisStruct));
12953// if (feaProblem->feaAnalysis == NULL) return EGADS_MALLOC;
12954//
12955// feaAnalysis=&feaProblem->feaAnalysis[0];
12956// status = initiate_feaAnalysisStruct(feaAnalysis);
12957// if (status != CAPS_SUCCESS) return status;
12958//
12959//
12960// feaAnalysis->name = (char *) EG_alloc(((strlen(name)) + 1)*sizeof(char));
12961// if (feaProblem->feaAnalysis->name == NULL) return EGADS_MALLOC;
12962//
12963// memcpy(feaAnalysis->name, name, strlen(name)*sizeof(char));
12964// feaAnalysis->name[strlen(name)] = '\0';
12965//
12966// feaAnalysis->analysisID = 1;
12967
12968
12969 status = CAPS_SUCCESS0;
12970 goto cleanup;
12971
12972 cleanup:
12973 if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_createDefaultAnalysis, status = %d\n", status);
12974
12975 if (tupleVal != NULL((void*)0)) {
12976 if (tupleVal[0].name != NULL((void*)0)) EG_free(tupleVal[0].name);
12977 if (tupleVal[0].value != NULL((void*)0)) EG_free(tupleVal[0].value);
12978 EG_free(tupleVal);
12979 }
12980
12981 return status;
12982}
12983
12984// Setup the default flutter velocities if not specified
12985int fea_defaultFlutterVelocity(feaAnalysisStruct *feaAnalysis) {
12986 int i;
12987
12988 int defaultNum = 23;
12989 double velocity=0, dv=1, vmin=0, vmax=0;
12990
12991 if (feaAnalysis->numFlutterVel == 0) {
12992 AIM_FREE(feaAnalysis->flutterVel){ EG_free(feaAnalysis->flutterVel); feaAnalysis->flutterVel
= ((void*)0); }
;
12993
12994 feaAnalysis->numFlutterVel = defaultNum;
12995 feaAnalysis->flutterVel = EG_alloc(feaAnalysis->numFlutterVel*sizeof(double));
12996 if (feaAnalysis->flutterVel == NULL((void*)0)) {
12997 return EGADS_MALLOC-4;
12998 }
12999
13000 velocity = sqrt(2*feaAnalysis->dynamicPressure/feaAnalysis->density);
13001 vmin = velocity / 2.0;
13002 vmax = 2 * velocity;
13003 dv = (vmax - vmin) / (double) (feaAnalysis->numFlutterVel-3);
13004
13005 for (i = 0; i < feaAnalysis->numFlutterVel-2; i++) {
13006 feaAnalysis->flutterVel[i+1] = vmin + (double) i * dv;
13007 }
13008
13009 feaAnalysis->flutterVel[0] = velocity/10;
13010 feaAnalysis->flutterVel[feaAnalysis->numFlutterVel-1] = velocity*10;
13011 }
13012
13013 return CAPS_SUCCESS0;
13014}