File: | feaUtils.c |
Warning: | line 526, column 10 Value stored to 'refLen' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
30 | int fea_createMesh(void *aimInfo, |
31 | /*@null@*/ double paramTess[3], // (in) Tessellation parameters |
32 | int edgePointMin, // (in) minimum points along any Edge |
33 | int edgePointMax, // (in) maximum points along any Edge |
34 | int quadMesh, // (in) only do tris-for faces |
35 | mapAttrToIndexStruct *groupMap, // (in) map from CAPSGroup names to indexes |
36 | mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes |
37 | mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes |
38 | mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes |
39 | mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes |
40 | mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes |
41 | /*@null@*/ mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes |
42 | int *numMesh, // (out) total number of FEA mesh structures |
43 | meshStruct **feaMesh, // (out) FEA mesh structure |
44 | feaProblemStruct *feaProblem ) { // (out) FEA problem structure |
45 | |
46 | int status; // Function return status |
47 | |
48 | int i, body; // Indexing |
49 | |
50 | // Bodies |
51 | const char *intents; |
52 | int numBody; // Number of Bodies |
53 | ego *bodies; |
54 | const char *discipline; |
55 | int stat, nGlobal; |
56 | |
57 | // Coordinate system |
58 | mapAttrToIndexStruct coordSystemMap, attrMapTemp1, attrMapTemp2, meshMap; |
59 | |
60 | int meshInd; |
61 | capsValue *meshVal, *meshMorphVal; |
62 | |
63 | meshStruct *feaMeshes = NULL((void*)0), tempMesh; |
64 | int *feaMeshList = NULL((void*)0); // List to seperate structural meshes for aero |
65 | |
66 | ego tempBody; |
67 | double capsMeshLength = 0, bbox[6], refLen; |
68 | |
69 | // Inherited fea/volume mesh related variables |
70 | int numFEAMesh = 0; |
71 | int feaMeshInherited = (int) false0; |
72 | |
73 | // Destroy feaMeshes |
74 | if ((*feaMesh) != NULL((void*)0)) { |
75 | |
76 | for (i = 0; i < *numMesh; i++) { |
77 | status = destroy_meshStruct(&(*feaMesh)[i]); |
78 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_meshStruct!\n", status); |
79 | } |
80 | |
81 | AIM_FREE(*feaMesh){ EG_free(*feaMesh); *feaMesh = ((void*)0); }; |
82 | } |
83 | |
84 | (*feaMesh) = NULL((void*)0); |
85 | *numMesh = 0; |
86 | |
87 | // Get AIM bodies |
88 | status = aim_getBodies(aimInfo, &intents, &numBody, &bodies); |
89 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 89 , __func__, 0); goto cleanup; }; |
90 | |
91 | if ((numBody <= 0) || (bodies == NULL((void*)0))) { |
92 | AIM_ERROR(aimInfo, "No Bodies!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 92, __func__ , "No Bodies!\n"); }; |
93 | return CAPS_SOURCEERR-330; |
94 | } |
95 | |
96 | initiate_meshStruct(&tempMesh); |
97 | |
98 | // Initiate our maps |
99 | status = initiate_mapAttrToIndexStruct(&coordSystemMap); |
100 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 100 , __func__, 0); goto cleanup; }; |
101 | |
102 | status = initiate_mapAttrToIndexStruct(&attrMapTemp1); |
103 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 103 , __func__, 0); goto cleanup; }; |
104 | |
105 | status = initiate_mapAttrToIndexStruct(&attrMapTemp2); |
106 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 106 , __func__, 0); goto cleanup; }; |
107 | |
108 | status = initiate_mapAttrToIndexStruct(&meshMap); |
109 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 109 , __func__, 0); goto cleanup; }; |
110 | |
111 | // Alloc feaMesh list |
112 | AIM_ALLOC(feaMeshList, numBody, int, aimInfo ,status){ if (feaMeshList != ((void*)0)) { status = -4; aim_status(aimInfo , status, "feaUtils.c", 112, __func__, 1, "AIM_ALLOC: %s != NULL" , "feaMeshList"); goto cleanup; } size_t memorysize = numBody ; feaMeshList = (int *) EG_alloc(memorysize*sizeof(int)); if ( feaMeshList == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 112, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "feaMeshList", memorysize, "int"); goto cleanup; } }; |
113 | |
114 | // Set all indexes to true |
115 | for (i = 0; i < numBody; i++ ) feaMeshList[i] = (int) true1; |
116 | |
117 | // Check for capsDiscipline consistency |
118 | i = 0; |
119 | for (body = 0; body < numBody; body++) { |
120 | |
121 | status = retrieve_CAPSDisciplineAttr(bodies[body], &discipline); |
122 | if (status != CAPS_SUCCESS0) continue; // Need to add an error code |
123 | |
124 | if (strcasecmp(discipline, "structure") != 0) { |
125 | feaMeshList[body] = (int) false0; |
126 | i++; |
127 | } |
128 | } |
129 | |
130 | if (i == numBody) { |
131 | AIM_ERROR(aimInfo, "No bodies with capsDiscipline Structure!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 131, __func__ , "No bodies with capsDiscipline Structure!"); }; |
132 | status = CAPS_BADVALUE-311; |
133 | goto cleanup; |
134 | } |
135 | |
136 | //for (body = 0; body< numBody; body++) printf("Body %i, FeaMeshList = %i\n", body, feaMeshList[body]); |
137 | |
138 | // Get CoordSystem attribute to index mapping |
139 | status = create_CoordSystemAttrToIndexMap(numBody, |
140 | bodies, |
141 | 3, //>2 - search the body, faces, edges, and all the nodes |
142 | &coordSystemMap); |
143 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 143 , __func__, 0); goto cleanup; }; |
144 | |
145 | status = fea_getCoordSystem(numBody, |
146 | bodies, |
147 | coordSystemMap, |
148 | &feaProblem->numCoordSystem, |
149 | &feaProblem->feaCoordSystem); |
150 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 150 , __func__, 0); goto cleanup; }; |
151 | |
152 | // Get capsConstraint name and index mapping |
153 | status = create_CAPSConstraintAttrToIndexMap(numBody, |
154 | bodies, |
155 | 3, //>2 - search the body, faces, edges, and all the nodes |
156 | constraintMap); |
157 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 157 , __func__, 0); goto cleanup; }; |
158 | |
159 | // Get capsLoad name and index mapping |
160 | status = create_CAPSLoadAttrToIndexMap(numBody, |
161 | bodies, |
162 | 3, //>2 - search the body, faces, edges, and all the nodes |
163 | loadMap); |
164 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 164 , __func__, 0); goto cleanup; }; |
165 | |
166 | // Get transfer to index mapping |
167 | status = create_CAPSBoundAttrToIndexMap(numBody, |
168 | bodies, |
169 | 3, //>2 - search the body, faces, edges, and all the nodes |
170 | transferMap); |
171 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 171 , __func__, 0); goto cleanup; }; |
172 | |
173 | if (connectMap != NULL((void*)0)) { |
174 | // Get connect to index mapping |
175 | status = create_CAPSConnectAttrToIndexMap(numBody, |
176 | bodies, |
177 | 3, //>2 - search the body, faces, edges, and all the nodes |
178 | connectMap); |
179 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 179 , __func__, 0); goto cleanup; }; |
180 | } |
181 | |
182 | if (responseMap != NULL((void*)0)) { |
183 | // Get response to index mapping |
184 | status = create_CAPSResponseAttrToIndexMap(numBody, |
185 | bodies, |
186 | 3, //>2 - search the body, faces, edges, and all the nodes |
187 | responseMap); |
188 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 188 , __func__, 0); goto cleanup; }; |
189 | } |
190 | |
191 | if (referenceMap != NULL((void*)0)) { |
192 | // Get response to index mapping |
193 | status = create_CAPSReferenceAttrToIndexMap(numBody, |
194 | bodies, |
195 | 3, //>2 - search the body, faces, edges, and all the nodes |
196 | referenceMap); |
197 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 197 , __func__, 0); goto cleanup; }; |
198 | } |
199 | |
200 | // Get capsGroup name and index mapping to make sure all faces have a capsGroup value |
201 | status = create_CAPSGroupAttrToIndexMap(numBody, |
202 | bodies, |
203 | 3, //>2 - search the body, faces, edges, and all the nodes |
204 | groupMap); |
205 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 205 , __func__, 0); goto cleanup; }; |
206 | |
207 | // Get the Mesh input Value |
208 | meshInd = aim_getIndex(aimInfo, "Mesh", ANALYSISIN); |
209 | if (meshInd < 1) |
210 | meshInd = aim_getIndex(aimInfo, "Surface_Mesh", ANALYSISIN); |
211 | if (meshInd < 1) { |
212 | AIM_ERROR(aimInfo, "Developer error: No 'Mesh' or 'Surface_Mesh' ANALYSISIN Index!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 212, __func__ , "Developer error: No 'Mesh' or 'Surface_Mesh' ANALYSISIN Index!" ); }; |
213 | status = CAPS_BADINDEX-304; |
214 | goto cleanup; |
215 | } |
216 | |
217 | status = aim_getValue(aimInfo, meshInd, ANALYSISIN, &meshVal); |
218 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 218 , __func__, 0); goto cleanup; }; |
219 | |
220 | if (meshVal->type != PointerMesh) { |
221 | AIM_ERROR(aimInfo, "Developer error! Mesh is not a PointerMesh!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 221, __func__ , "Developer error! Mesh is not a PointerMesh!"); }; |
222 | status = CAPS_NOTIMPLEMENT-334; |
223 | goto cleanup; |
224 | } |
225 | |
226 | // Get the Mesh_Morph input Value |
227 | meshInd = aim_getIndex(aimInfo, "Mesh_Morph", ANALYSISIN); |
228 | if (meshInd < 1) { |
229 | AIM_ERROR(aimInfo, "Developer error: No 'Mesh_Morph' ANALYSISIN Index!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 229, __func__ , "Developer error: No 'Mesh_Morph' ANALYSISIN Index!"); }; |
230 | status = CAPS_BADINDEX-304; |
231 | goto cleanup; |
232 | } |
233 | |
234 | status = aim_getValue(aimInfo, meshInd, ANALYSISIN, &meshMorphVal); |
235 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 235 , __func__, 0); goto cleanup; }; |
236 | |
237 | |
238 | feaMeshInherited = (int) false0; |
239 | |
240 | if ((meshVal->nullVal == NotNull) || |
241 | (meshMorphVal->vals.integer == (int) true1 && |
242 | meshVal->nullVal == IsNull)) { |
243 | |
244 | if ( meshMorphVal->vals.integer == (int) true1 && |
245 | meshVal->nullVal == IsNull ) { // If we are mighty morphing |
246 | |
247 | if (aim_newGeometry(aimInfo) == CAPS_SUCCESS0 || |
248 | feaProblem->meshRefIn == NULL((void*)0) || |
249 | feaProblem->meshRefIn != &feaProblem->meshRefObj) { |
250 | |
251 | // Lets "load" the meshRef now since it's not linked |
252 | status = aim_loadMeshRef(aimInfo, &feaProblem->meshRefObj); |
253 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 253 , __func__, 0); goto cleanup; }; |
254 | |
255 | // Mighty Morph the mesh |
256 | status = aim_morphMeshUpdate(aimInfo, &feaProblem->meshRefObj, numBody, bodies); |
257 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 257 , __func__, 0); goto cleanup; }; |
258 | } |
259 | /*@-immediatetrans@*/ |
260 | feaProblem->meshRefIn = &feaProblem->meshRefObj; |
261 | /*@+immediatetrans@*/ |
262 | } else { |
263 | feaProblem->meshRefIn = (aimMeshRef *) meshVal->vals.AIMptr; |
264 | } |
265 | |
266 | numFEAMesh = feaProblem->meshRefIn->nmap; |
267 | |
268 | // See if a FEA mesh is available from parent |
269 | if (feaProblem->meshRefIn->type == aimAreaMesh || |
270 | feaProblem->meshRefIn->type == aimSurfaceMesh) { |
271 | |
272 | if (numFEAMesh != numBody) { // May not be an error if we are doing aero-struct |
273 | |
274 | // Check for capsDiscipline consistency |
275 | for (body = 0; body < numFEAMesh; body++) { |
276 | // Dummy arguments |
277 | status = EG_statusTessBody(feaProblem->meshRefIn->maps[body].tess, &tempBody, &stat, &nGlobal); |
278 | if (status != EGADS_SUCCESS0) goto cleanup; |
279 | |
280 | status = retrieve_CAPSDisciplineAttr(tempBody, &discipline); |
281 | if (status != EGADS_SUCCESS0) { |
282 | AIM_ERROR (aimInfo, "Failed to find a capsDiscipline attribute!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 282, __func__ , "Failed to find a capsDiscipline attribute!\n"); }; |
283 | AIM_ADDLINE(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n"){ aim_addLine(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n" ); }; |
284 | status= CAPS_SOURCEERR-330; |
285 | goto cleanup; |
286 | } |
287 | |
288 | if (strcasecmp(discipline, "structure") != 0) { |
289 | AIM_ERROR (aimInfo, "Failed to find a capsDiscipline attribute - 'structure'!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 289, __func__ , "Failed to find a capsDiscipline attribute - 'structure'!\n" ); }; |
290 | AIM_ADDLINE(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n"){ aim_addLine(aimInfo, "Number of linked surface meshes does not match the number of bodies, this is only allowed if doing aero-struct analysis\n" ); }; |
291 | status= CAPS_SOURCEERR-330; |
292 | goto cleanup; |
293 | } |
294 | |
295 | // need a check to make sure all tempMesh->groupMap are identical |
296 | } |
297 | |
298 | // We need to update our capsGroup attribute map |
299 | |
300 | // Get capsGroup name and index mapping to make sure all faces have a capsGroup value |
301 | status = create_CAPSGroupAttrToIndexMap(numBody, |
302 | bodies, |
303 | 3, //>2 - search the body, faces, edges, and all the nodes |
304 | &attrMapTemp2); |
305 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 305 , __func__, 0); goto cleanup; }; |
306 | |
307 | // Get attribute to index mapping |
308 | status = create_MeshRefToIndexMap(aimInfo, feaProblem->meshRefIn, &attrMapTemp1); |
309 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 309 , __func__, 0); goto cleanup; }; |
310 | |
311 | status = merge_mapAttrToIndexStruct(&attrMapTemp1, &attrMapTemp2, groupMap); |
312 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 312 , __func__, 0); goto cleanup; }; |
313 | } |
314 | |
315 | AIM_ALLOC(feaMeshes, numFEAMesh, meshStruct, aimInfo, status){ if (feaMeshes != ((void*)0)) { status = -4; aim_status(aimInfo , status, "feaUtils.c", 315, __func__, 1, "AIM_ALLOC: %s != NULL" , "feaMeshes"); goto cleanup; } size_t memorysize = numFEAMesh ; feaMeshes = (meshStruct *) EG_alloc(memorysize*sizeof(meshStruct )); if (feaMeshes == ((void*)0)) { status = -4; aim_status(aimInfo , status, "feaUtils.c", 315, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "feaMeshes", memorysize, "meshStruct"); goto cleanup; } }; |
316 | for (body = 0; body < numFEAMesh; body++) (void) initiate_meshStruct(&feaMeshes[body]); |
317 | |
318 | for (body = 0; body < numFEAMesh; body++) { |
319 | |
320 | status = copy_mapAttrToIndexStruct( groupMap, |
321 | &tempMesh.groupMap ); |
322 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 322 , __func__, 0); goto cleanup; }; |
323 | |
324 | tempMesh.egadsTess = feaProblem->meshRefIn->maps[body].tess; |
325 | status = mesh_surfaceMeshEGADSTess(aimInfo, &tempMesh, (int)(feaProblem->meshRefIn->type == aimAreaMesh)); |
326 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 326 , __func__, 0); goto cleanup; }; |
327 | |
328 | // Create a new mesh with topology tagged with capsIgnore being removed, if capsIgnore isn't found the mesh is simply copied. |
329 | status = mesh_createIgnoreMesh(&tempMesh, &feaMeshes[body]); |
330 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 330 , __func__, 0); goto cleanup; }; |
331 | |
332 | destroy_meshStruct(&tempMesh); |
333 | |
334 | // Change the analysis type of the mesh |
335 | status = mesh_setAnalysisType(MeshStructure, &feaMeshes[body]); |
336 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 336 , __func__, 0); goto cleanup; }; |
337 | |
338 | |
339 | // Get FEA Problem from EGADs body |
340 | status = fea_setAnalysisData(aimInfo, |
341 | groupMap, |
342 | &coordSystemMap, |
343 | constraintMap, |
344 | loadMap, |
345 | transferMap, |
346 | connectMap, |
347 | responseMap, |
348 | referenceMap, |
349 | &feaMeshes[body]); |
350 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 350 , __func__, 0); goto cleanup; }; |
351 | |
352 | status = mesh_fillQuickRefList( &feaMeshes[body]); |
353 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 353 , __func__, 0); goto cleanup; }; |
354 | |
355 | printf("\tMesh for body = %d\n", body); |
356 | printf("\tNumber of nodal coordinates = %d\n", feaMeshes[body].numNode); |
357 | printf("\tNumber of elements = %d\n", feaMeshes[body].numElement); |
358 | printf("\tElemental Nodes = %d\n", feaMeshes[body].meshQuickRef.numNode); |
359 | printf("\tElemental Rods = %d\n", feaMeshes[body].meshQuickRef.numLine); |
360 | printf("\tElemental Tria3 = %d\n", feaMeshes[body].meshQuickRef.numTriangle); |
361 | printf("\tElemental Quad4 = %d\n", feaMeshes[body].meshQuickRef.numQuadrilateral); |
362 | } |
363 | |
364 | |
365 | if (numFEAMesh > 1) { |
366 | printf("Combining multiple FEA meshes!\n"); |
367 | } |
368 | |
369 | status = mesh_combineMeshStruct(numFEAMesh, |
370 | feaMeshes, |
371 | &feaProblem->feaMesh); |
372 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 372 , __func__, 0); goto cleanup; }; |
373 | |
374 | if (numFEAMesh > 1) { |
375 | printf("\tCombined Number of nodal coordinates = %d\n", feaProblem->feaMesh.numNode); |
376 | printf("\tCombined Number of elements = %d\n", feaProblem->feaMesh.numElement); |
377 | printf("\tCombined Elemental Nodes = %d\n", feaProblem->feaMesh.meshQuickRef.numNode); |
378 | printf("\tCombined Elemental Rods = %d\n", feaProblem->feaMesh.meshQuickRef.numLine); |
379 | printf("\tCombined Elemental Tria3 = %d\n", feaProblem->feaMesh.meshQuickRef.numTriangle); |
380 | printf("\tCombined Elemental Quad4 = %d\n", feaProblem->feaMesh.meshQuickRef.numQuadrilateral); |
381 | } |
382 | |
383 | // Set output meshes |
384 | *numMesh = numFEAMesh; |
385 | *feaMesh = feaMeshes; |
386 | feaMeshes = NULL((void*)0); |
387 | |
388 | // Set reference meshes |
389 | feaProblem->feaMesh.numReferenceMesh = *numMesh; |
390 | feaProblem->feaMesh.referenceMesh = (meshStruct *) EG_alloc(*numMesh*sizeof(meshStruct)); |
391 | if (feaProblem->feaMesh.referenceMesh == NULL((void*)0)) { |
392 | status = EGADS_MALLOC-4; |
393 | goto cleanup; |
394 | } |
395 | |
396 | for (body = 0; body < *numMesh; body++) { |
397 | feaProblem->feaMesh.referenceMesh[body] = (*feaMesh)[body]; |
398 | } |
399 | |
400 | } else { // Check to see if a general unstructured volume mesh is available |
401 | |
402 | printf("Found link for a volume mesh (Volume_Mesh) from parent\n"); |
403 | |
404 | numFEAMesh = 1; |
405 | if (numFEAMesh != 1) { |
406 | AIM_ERROR(aimInfo, "Can not accept multiple volume meshes"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 406, __func__ , "Can not accept multiple volume meshes"); }; |
407 | status = CAPS_BADVALUE-311; |
408 | goto cleanup; |
409 | } |
410 | |
411 | if (numFEAMesh != numBody) { |
412 | printf("Number of inherited volume meshes does not match the number of bodies - assuming volume mesh is already combined\n"); |
413 | } |
414 | |
415 | AIM_ERROR(aimInfo, "Volume meshes not yet supported for structural analysis"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 415, __func__ , "Volume meshes not yet supported for structural analysis"); }; |
416 | status = CAPS_BADVALUE-311; |
417 | goto cleanup; |
418 | |
419 | #if 0 |
420 | tempMesh = (meshStruct *) meshVal->vals.AIMptr; |
421 | status = mesh_copyMeshStruct( tempMesh, &feaProblem->feaMesh); |
422 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 422 , __func__, 0); goto cleanup; }; |
423 | |
424 | //feaProblem->feaMesh.egadsTess = |
425 | status = mesh_surfaceMeshEGADSTess(aimInfo, &feaProblem->feaMesh.egadsTess, (int)false0); |
426 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 426 , __func__, 0); goto cleanup; }; |
427 | |
428 | |
429 | // Set reference meshes |
430 | feaProblem->feaMesh.numReferenceMesh = tempMesh->numReferenceMesh; |
431 | feaProblem->feaMesh.referenceMesh = (meshStruct *) EG_alloc(tempMesh->numReferenceMesh*sizeof(meshStruct)); |
432 | if (feaProblem->feaMesh.referenceMesh == NULL((void*)0)) { |
433 | status = EGADS_MALLOC-4; |
434 | goto cleanup; |
435 | } |
436 | |
437 | for (body = 0; body < tempMesh->numReferenceMesh; body++) { |
438 | feaProblem->feaMesh.referenceMesh[body] = tempMesh->referenceMesh[body]; |
439 | } |
440 | |
441 | for (i = 0; i < feaProblem->feaMesh.numReferenceMesh; i++) { |
442 | |
443 | status = aim_newTess(aimInfo, |
444 | feaProblem->feaMesh.referenceMesh[i].egadsTess); |
445 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 445 , __func__, 0); goto cleanup; }; |
446 | } |
447 | |
448 | // Update/change the analysis data in a meshStruct |
449 | status = change_meshAnalysis(&feaProblem->feaMesh, MeshStructure); |
450 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 450 , __func__, 0); goto cleanup; }; |
451 | |
452 | // Get FEA Problem from EGADs body |
453 | status = fea_setAnalysisData(aimInfo, |
454 | groupMap, |
455 | &coordSystemMap, |
456 | constraintMap, |
457 | loadMap, |
458 | transferMap, |
459 | connectMap, |
460 | responseMap, |
461 | referenceMap, |
462 | &feaProblem->feaMesh); |
463 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 463 , __func__, 0); goto cleanup; }; |
464 | #endif |
465 | } |
466 | |
467 | feaMeshInherited = (int) true1; |
468 | } |
469 | |
470 | // If we didn't inherit a FEA mesh we need to get one ourselves |
471 | if (feaMeshInherited == (int) false0) { |
472 | |
473 | status = check_CAPSMeshLength(numBody, bodies, &capsMeshLength); |
474 | |
475 | if (status == CAPS_NOTFOUND-303) capsMeshLength = -1; |
476 | else AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 476 , __func__, 0); goto cleanup; }; |
477 | |
478 | /* |
479 | if (capsMeshLength <= 0 || status != CAPS_SUCCESS) { |
480 | printf("**********************************************************\n"); |
481 | if (status != CAPS_SUCCESS) |
482 | printf("capsMeshLength is not set on any body.\n"); |
483 | else |
484 | printf("capsMeshLength: %f\n", capsMeshLength); |
485 | printf("\n"); |
486 | printf("The capsMeshLength attribute must\n" |
487 | "present on at least one body.\n" |
488 | "\n" |
489 | "capsMeshLength should be a a positive value representative\n" |
490 | "of a characteristic length of the geometry,\n" |
491 | "e.g. the MAC of a wing or diameter of a fuselage.\n"); |
492 | printf("**********************************************************\n"); |
493 | status = CAPS_BADVALUE; |
494 | goto cleanup; |
495 | }*/ |
496 | |
497 | if (paramTess == NULL((void*)0)) { |
498 | AIM_ERROR(aimInfo, "Developer error paramTess == NULL"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 498, __func__ , "Developer error paramTess == NULL"); }; |
499 | status = CAPS_BADVALUE-311; |
500 | goto cleanup; |
501 | } |
502 | |
503 | if (edgePointMin < 2) { |
504 | printf("The minimum number of allowable edge points is 2 not %d\n", edgePointMin); |
505 | edgePointMin = 2; |
506 | } |
507 | |
508 | if (edgePointMax < edgePointMin) { |
509 | printf("The maximum number of edge points must be greater than the current minimum (%d)\n", edgePointMin); |
510 | edgePointMax = edgePointMin+1; |
511 | } |
512 | |
513 | if (capsMeshLength <= 0) { |
514 | refLen = 0; |
515 | for (body = 0; body < numBody; body++) { |
516 | if (feaMeshList[body] != (int) true1) continue; |
517 | |
518 | status = EG_getBoundingBox(bodies[body], bbox); |
519 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 519 , __func__, 0); goto cleanup; }; |
520 | |
521 | refLen = MAX(refLen, sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[0])(((refLen) < (sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[ 0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox [2]) * (bbox[5] - bbox[2])))) ? (sqrt( (bbox[3] - bbox[0]) * ( bbox[3] - bbox[0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]))) : (refLen)) |
522 | +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1])(((refLen) < (sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[ 0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox [2]) * (bbox[5] - bbox[2])))) ? (sqrt( (bbox[3] - bbox[0]) * ( bbox[3] - bbox[0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]))) : (refLen)) |
523 | +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2])))(((refLen) < (sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[ 0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox [2]) * (bbox[5] - bbox[2])))) ? (sqrt( (bbox[3] - bbox[0]) * ( bbox[3] - bbox[0]) +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2]))) : (refLen)); |
524 | } |
525 | } else { |
526 | refLen = capsMeshLength; |
Value stored to 'refLen' is never read | |
527 | } |
528 | |
529 | // Modify the EGADS body tessellation based on given inputs |
530 | /*@-nullpass@*/ |
531 | status = mesh_modifyBodyTess(0, |
532 | NULL((void*)0), |
533 | edgePointMin, |
534 | edgePointMax, |
535 | quadMesh, |
536 | &capsMeshLength, |
537 | paramTess, |
538 | meshMap, |
539 | numBody, |
540 | bodies); |
541 | /*@+nullpass@*/ |
542 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 542 , __func__, 0); goto cleanup; }; |
543 | |
544 | for (body = 0; body < numBody; body++) { |
545 | if (feaMeshList[body] != (int) true1) continue; |
546 | |
547 | if (capsMeshLength > 0) { |
548 | refLen = capsMeshLength; |
549 | } else { |
550 | status = EG_getBoundingBox(bodies[body], bbox); |
551 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 551 , __func__, 0); goto cleanup; }; |
552 | |
553 | refLen = sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[0]) |
554 | +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) |
555 | +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2])); |
556 | } |
557 | |
558 | status = copy_mapAttrToIndexStruct( groupMap, |
559 | &tempMesh.groupMap ); |
560 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 560 , __func__, 0); goto cleanup; }; |
561 | |
562 | status = mesh_surfaceMeshEGADSBody(aimInfo, |
563 | bodies[body], |
564 | refLen, |
565 | paramTess, |
566 | quadMesh, |
567 | &tempMesh.egadsTess); |
568 | AIM_STATUS(aimInfo, status, "Problem during surface meshing of body %d", body+1)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 568 , __func__, 2, "Problem during surface meshing of body %d", body +1); goto cleanup; }; |
569 | AIM_NOTNULL(tempMesh.egadsTess, aimInfo, status){ if (tempMesh.egadsTess == ((void*)0)) { status = -307; aim_status (aimInfo, status, "feaUtils.c", 569, __func__, 1, "%s == NULL!" , "tempMesh.egadsTess"); goto cleanup; } }; |
570 | |
571 | status = mesh_surfaceMeshEGADSTess(aimInfo, &tempMesh, (int)false0); |
572 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 572 , __func__, 0); goto cleanup; }; |
573 | |
574 | *numMesh += 1; |
575 | AIM_REALL(*feaMesh, *numMesh, meshStruct, aimInfo, status){ size_t memorysize = *numMesh; *feaMesh = (meshStruct *) EG_reall (*feaMesh, memorysize*sizeof(meshStruct)); if (*feaMesh == (( void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 575, __func__, 3, "AIM_REALL: %s size %zu type %s", "*feaMesh" , memorysize, "meshStruct"); goto cleanup; } }; |
576 | |
577 | status = initiate_meshStruct(&(*feaMesh)[*numMesh-1]); |
578 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 578 , __func__, 0); goto cleanup; }; |
579 | |
580 | // Create a new mesh with topology tagged with capsIgnore being removed, if capsIgnore isn't found the mesh is simply copied. |
581 | status = mesh_createIgnoreMesh(&tempMesh, &(*feaMesh)[*numMesh-1]); |
582 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 582 , __func__, 0); goto cleanup; }; |
583 | |
584 | destroy_meshStruct(&tempMesh); |
585 | |
586 | // Change the analysis type of the mesh |
587 | status = mesh_setAnalysisType(MeshStructure, &(*feaMesh)[*numMesh-1]); |
588 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 588 , __func__, 0); goto cleanup; }; |
589 | |
590 | // Get FEA Problem from EGADs body |
591 | status = fea_setAnalysisData(aimInfo, |
592 | groupMap, |
593 | &coordSystemMap, |
594 | constraintMap, |
595 | loadMap, |
596 | transferMap, |
597 | connectMap, |
598 | responseMap, |
599 | referenceMap, |
600 | &(*feaMesh)[*numMesh-1]); |
601 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 601 , __func__, 0); goto cleanup; }; |
602 | |
603 | status = mesh_fillQuickRefList( &(*feaMesh)[*numMesh-1]); |
604 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 604 , __func__, 0); goto cleanup; }; |
605 | |
606 | |
607 | #if 0 |
608 | // Get FEA Problem from EGADs body |
609 | status = fea_bodyToBEM(aimInfo, |
610 | bodies[body], // (in) EGADS Body |
611 | paramTess, // (in) Tessellation parameters |
612 | edgePointMin, // (in) minimum points along any Edge |
613 | edgePointMax, // (in) maximum points along any Edge |
614 | quadMesh, |
615 | groupMap, |
616 | &coordSystemMap, |
617 | constraintMap, |
618 | loadMap, |
619 | transferMap, |
620 | connectMap, |
621 | responseMap, |
622 | referenceMap, |
623 | &(*feaMesh)[*numMesh-1]); |
624 | #endif |
625 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 625 , __func__, 0); goto cleanup; }; |
626 | printf("\tMesh for body = %d\n", body); |
627 | printf("\tNumber of nodal coordinates = %d\n", (*feaMesh)[*numMesh-1].numNode); |
628 | printf("\tNumber of elements = %d\n", (*feaMesh)[*numMesh-1].numElement); |
629 | printf("\tElemental Nodes = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numNode); |
630 | printf("\tElemental Rods = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numLine); |
631 | printf("\tElemental Tria3 = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numTriangle); |
632 | printf("\tElemental Quad4 = %d\n", (*feaMesh)[*numMesh-1].meshQuickRef.numQuadrilateral); |
633 | |
634 | // set the resulting tessellation |
635 | status = aim_newTess(aimInfo, (*feaMesh)[*numMesh-1].egadsTess); |
636 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 636 , __func__, 0); goto cleanup; }; |
637 | } |
638 | |
639 | // Only compbine if there are actual meshes |
640 | if (*numMesh > 0) { |
641 | if (*numMesh > 1) printf("Combining multiple FEA meshes!\n"); |
642 | AIM_NOTNULL((*feaMesh), aimInfo, status){ if ((*feaMesh) == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 642, __func__, 1, "%s == NULL!", "(*feaMesh)" ); goto cleanup; } }; |
643 | |
644 | // Combine fea meshes into a single mesh for the problem |
645 | status = mesh_combineMeshStruct(*numMesh, |
646 | (*feaMesh), |
647 | &feaProblem->feaMesh); |
648 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 648 , __func__, 0); goto cleanup; }; |
649 | |
650 | if (*numMesh > 1) { |
651 | printf("\tCombined Number of nodal coordinates = %d\n", feaProblem->feaMesh.numNode); |
652 | printf("\tCombined Number of elements = %d\n", feaProblem->feaMesh.numElement); |
653 | printf("\tCombined Elemental Nodes = %d\n", feaProblem->feaMesh.meshQuickRef.numNode); |
654 | printf("\tCombined Elemental Rods = %d\n", feaProblem->feaMesh.meshQuickRef.numLine); |
655 | printf("\tCombined Elemental Tria3 = %d\n", feaProblem->feaMesh.meshQuickRef.numTriangle); |
656 | printf("\tCombined Elemental Quad4 = %d\n", feaProblem->feaMesh.meshQuickRef.numQuadrilateral); |
657 | } |
658 | |
659 | // Set reference meshes |
660 | feaProblem->feaMesh.numReferenceMesh = *numMesh; |
661 | feaProblem->feaMesh.referenceMesh = (meshStruct *) EG_alloc(*numMesh*sizeof(meshStruct)); |
662 | if (feaProblem->feaMesh.referenceMesh == NULL((void*)0)) { |
663 | status = EGADS_MALLOC-4; |
664 | goto cleanup; |
665 | } |
666 | |
667 | for (body = 0; body < *numMesh; body++) { |
668 | feaProblem->feaMesh.referenceMesh[body] = (*feaMesh)[body]; |
669 | } |
670 | } |
671 | } |
672 | status = CAPS_SUCCESS0; |
673 | |
674 | cleanup: |
675 | |
676 | AIM_FREE(feaMeshes){ EG_free(feaMeshes); feaMeshes = ((void*)0); }; |
677 | AIM_FREE(feaMeshList){ EG_free(feaMeshList); feaMeshList = ((void*)0); }; |
678 | |
679 | (void ) destroy_mapAttrToIndexStruct(&coordSystemMap); |
680 | |
681 | (void ) destroy_mapAttrToIndexStruct(&attrMapTemp1); |
682 | (void ) destroy_mapAttrToIndexStruct(&attrMapTemp2); |
683 | |
684 | return status; |
685 | } |
686 | |
687 | // Convert an EGADS body to a boundary element model, modified by Ryan Durscher (AFRL) |
688 | // from code originally written by John Dannenhoffer @ Syracuse University, patterned after code |
689 | // written by Bob Haimes @ MIT |
690 | int fea_bodyToBEM(void *aimInfo, // (in) AIM structure |
691 | ego ebody, // (in) EGADS Body |
692 | double paramTess[3], // (in) Tessellation parameters |
693 | int edgePointMin, // (in) minimum points along any Edge |
694 | int edgePointMax, // (in) maximum points along any Edge |
695 | int quadMesh, // (in) 0 - only do tris-for faces, 1 - mixed quad/tri, 2 - regularized quads |
696 | mapAttrToIndexStruct *attrMap, // (in) map from CAPSGroup names to indexes |
697 | mapAttrToIndexStruct *coordSystemMap,// (in) map from CoordSystem names to indexes |
698 | mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes |
699 | mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes |
700 | mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes |
701 | mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes |
702 | mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes |
703 | mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes |
704 | meshStruct *feaMesh) // (out) FEA mesh structure |
705 | { |
706 | int status = 0; // Function return status |
707 | |
708 | int isNodeBody; |
709 | int i, j, k, face, edge, patch; // Indexing |
710 | double scale; |
711 | |
712 | // Body entities |
713 | int numNode = 0, numEdge = 0, numFace = 0; |
714 | ego *enodes=NULL((void*)0), *eedges=NULL((void*)0), *efaces=NULL((void*)0); |
715 | |
716 | int atype, alen; // EGADS return variables |
717 | const int *ints; |
718 | const double *reals; |
719 | const char *string; |
720 | |
721 | // Meshing |
722 | int numPoint = 0, numTri = 0; |
723 | const int *triConn = NULL((void*)0), *triNeighbor = NULL((void*)0); // Triangle |
724 | |
725 | int numPatch = 0; // Patching |
726 | int n1, n2, *qints = NULL((void*)0); |
727 | |
728 | int gID; // Global id |
729 | |
730 | const double *xyz, *uv; |
731 | |
732 | const int *ptype = NULL((void*)0), *pindex = NULL((void*)0), *pvindex = NULL((void*)0), *pbounds = NULL((void*)0); |
733 | |
734 | int periodic, nchange, oclass, mtype, nchild, nchild2, *senses; |
735 | |
736 | // Edge point distributions |
737 | int *points=NULL((void*)0), *isouth=NULL((void*)0), *ieast=NULL((void*)0), *inorth=NULL((void*)0), *iwest=NULL((void*)0); |
738 | double params[3], bbox[6], size, range[2], arclen, data[4], eval[18], eval2[18]; |
739 | double *rpos=NULL((void*)0); |
740 | ego eref, *echilds, *echilds2, eloop, tempBody, topObj, prev, next; |
741 | |
742 | int bodySubType = 0; // Body classification |
743 | |
744 | int pointType, pointTopoIndex; |
745 | double xyzPoint[3], xyzNode[3]; |
746 | |
747 | // Attributues |
748 | const char *attrName; |
749 | int attrIndex, coordSystemIndex, loadIndex; |
750 | |
751 | int numElement = 0; // Number of elements |
752 | int coordID = 0; // Default coordinate id for mesh |
753 | |
754 | feaMeshDataStruct *feaData; |
755 | |
756 | meshElementStruct *tempElement = NULL((void*)0); |
757 | |
758 | // In case our geometry has ignores |
759 | int ignoreFound = (int) false0; |
760 | |
761 | // --------------------------------------------------------------- |
762 | |
763 | printf("Creating FEA BEM\n"); |
764 | |
765 | // Check for contradiction where quading is requested but dissabled on the body |
766 | if (quadMesh == (int)true1) { |
767 | status = EG_attributeRet(ebody, ".qParams", &atype, &alen, &ints, &reals, &string); |
768 | if (status == EGADS_SUCCESS0 && (atype != ATTRREAL2 || (atype == ATTRREAL2 && reals[0] <= 0 ))) { |
769 | printf("\tQuading on all faces disabled with .qParams attribute on the body\n"); |
770 | quadMesh = (int) false0; |
771 | } |
772 | } |
773 | |
774 | // Get number of Nodes, Edges, and Faces in ebody |
775 | status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes); |
776 | if (status < EGADS_SUCCESS0) goto cleanup; |
777 | AIM_NOTNULL(enodes, aimInfo, status){ if (enodes == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 777, __func__, 1, "%s == NULL!", "enodes" ); goto cleanup; } }; |
778 | |
779 | status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges); |
780 | if (status != EGADS_SUCCESS0) goto cleanup; |
781 | |
782 | status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces); |
783 | if (status < EGADS_SUCCESS0) goto cleanup; |
784 | |
785 | // What type of BODY do we have? |
786 | isNodeBody = aim_isNodeBody(ebody, xyzNode); |
787 | if (isNodeBody < EGADS_SUCCESS0) goto cleanup; |
788 | if (isNodeBody == EGADS_SUCCESS0) { |
789 | // all attributes are on the body rather than the node for a node body |
790 | enodes[0] = ebody; |
791 | } |
792 | |
793 | // Determine the nominal number of points along each Edge |
794 | points = (int *) EG_alloc((numEdge+1) *sizeof(int )); |
795 | rpos = (double *) EG_alloc((edgePointMax)*sizeof(double)); |
796 | if (points == NULL((void*)0) || rpos == NULL((void*)0)) { |
797 | status = EGADS_MALLOC-4; |
798 | printf("\tError in fea_bodyToBEM: EG_alloc\n"); |
799 | goto cleanup; |
800 | } |
801 | |
802 | status = EG_getBoundingBox(ebody, bbox); |
803 | if (status < EGADS_SUCCESS0) { |
804 | printf("\tError in fea_bodyToBEM: EG_getBoundingBox\n"); |
805 | goto cleanup; |
806 | } |
807 | |
808 | size = sqrt( (bbox[3] - bbox[0]) * (bbox[3] - bbox[0]) |
809 | +(bbox[4] - bbox[1]) * (bbox[4] - bbox[1]) |
810 | +(bbox[5] - bbox[2]) * (bbox[5] - bbox[2])); |
811 | |
812 | params[0] = paramTess[0] * size; |
813 | params[1] = paramTess[1] * size; |
814 | params[2] = paramTess[2]; |
815 | |
816 | status = EG_attributeAdd(ebody, ".tParam", ATTRREAL2, 3, NULL((void*)0), params, NULL((void*)0)); |
817 | if (status < EGADS_SUCCESS0) { |
818 | printf("\tError in fea_bodyToBEM: EG_attributeAdd\n"); |
819 | goto cleanup; |
820 | } |
821 | |
822 | if (isNodeBody == EGADS_SUCCESS0) |
823 | params[0] = 1; // does not matter but can't be zero |
824 | |
825 | if (params[0] <= 0.0) { |
826 | printf("\tError in fea_bodyToBEM: params[0] = %f must be a positive number!\n", params[0]); |
827 | status = CAPS_BADVALUE-311; |
828 | goto cleanup; |
829 | } |
830 | |
831 | for (i = 1; i <= numEdge; i++) { |
832 | status = EG_getRange(eedges[i-1], range, &periodic); |
833 | if (status < EGADS_SUCCESS0) { |
834 | printf("\tError in fea_bodyToBEM: EG_getRange\n"); |
835 | goto cleanup; |
836 | } |
837 | |
838 | status = EG_arcLength(eedges[i-1], range[0], range[1], &arclen); |
839 | if (status < EGADS_SUCCESS0) { |
840 | printf("\tError in fea_bodyToBEM: EG_arcLength\n"); |
841 | goto cleanup; |
842 | } |
843 | |
844 | //points[i] = MIN(MAX(MAX(edgePointMin,2), (int)(1+arclen/params[0])), edgePointMax); |
845 | points[i] = (int) min_DoubleVal( |
846 | max_DoubleVal( |
847 | max_DoubleVal( (double) edgePointMin, 2.0), |
848 | (double) (1+arclen/params[0])), |
849 | (double) edgePointMax); |
850 | } |
851 | |
852 | |
853 | // make arrays for "opposite" sides of four-sided Faces (with only one loop) |
854 | isouth = (int *) EG_alloc((numFace+1)*sizeof(int)); |
855 | ieast = (int *) EG_alloc((numFace+1)*sizeof(int)); |
856 | inorth = (int *) EG_alloc((numFace+1)*sizeof(int)); |
857 | iwest = (int *) EG_alloc((numFace+1)*sizeof(int)); |
858 | |
859 | if (isouth == NULL((void*)0) || |
860 | ieast == NULL((void*)0) || |
861 | inorth == NULL((void*)0) || |
862 | iwest == NULL((void*)0) ) { |
863 | |
864 | status = EGADS_MALLOC-4; |
865 | printf("\tError in fea_bodyToBEM: EG_alloc\n"); |
866 | goto cleanup; |
867 | } |
868 | |
869 | for (i = 1; i <= numFace; i++) { |
870 | isouth[i] = 0; |
871 | ieast [i] = 0; |
872 | inorth[i] = 0; |
873 | iwest [i] = 0; |
874 | |
875 | // nothing to check if quading isn't requested |
876 | if (quadMesh == (int) false0) |
877 | continue; |
878 | |
879 | // check if quading is disabled with .qParams |
880 | status = EG_attributeRet(efaces[i-1], ".qParams", &atype, &alen, &ints, &reals, &string); |
881 | if (status == EGADS_SUCCESS0 && (atype != ATTRREAL2 || (atype == ATTRREAL2 && reals[0] <= 0 ))) { |
882 | printf("\tFace %d quading disabled with attribute .qParams\n", i); |
883 | continue; |
884 | } |
885 | |
886 | // quading only works with one loop |
887 | status = EG_getTopology(efaces[i-1], &eref, &oclass, &mtype, data, &nchild, &echilds, &senses); |
888 | if (status < EGADS_SUCCESS0) goto cleanup; |
889 | |
890 | if (nchild != 1) continue; |
891 | |
892 | // quading only works if the loop has 4 edges |
893 | eloop = echilds[0]; |
894 | status = EG_getTopology(eloop, &eref, &oclass, &mtype, data, &nchild, &echilds, &senses); |
895 | if (status < EGADS_SUCCESS0) goto cleanup; |
896 | |
897 | if (nchild != 4) continue; |
898 | |
899 | // Check to see if two "straight" edges next to each other are parallel - Don't Quad if so |
900 | for (j = 0; j < 4; j++) { |
901 | |
902 | status = EG_getTopology(echilds[j], &eref, &oclass, &mtype, data, &nchild2, &echilds2, &senses); |
903 | if (mtype == DEGENERATE5) { status = EGADS_DEGEN-24; break; } |
904 | if (status < EGADS_SUCCESS0) goto cleanup; |
905 | |
906 | if (j < 3) k = j+1; |
907 | else k = 0; |
908 | |
909 | status = EG_getTopology(echilds[k], &eref, &oclass, &mtype, range, &nchild2, &echilds2, &senses); |
910 | if (mtype == DEGENERATE5) { status = EGADS_DEGEN-24; break; } |
911 | if (status < EGADS_SUCCESS0) goto cleanup; |
912 | |
913 | status = EG_evaluate(echilds[j], data, eval); |
914 | if (status < EGADS_SUCCESS0) goto cleanup; |
915 | |
916 | status = EG_evaluate(echilds[k], range, eval2); |
917 | if (status < EGADS_SUCCESS0) goto cleanup; |
918 | |
919 | scale = dot_DoubleVal(&eval[3], &eval[3]); |
920 | eval[3] /= scale; |
921 | eval[4] /= scale; |
922 | eval[5] /= scale; |
923 | |
924 | scale = dot_DoubleVal(&eval2[3], &eval2[3]); |
925 | eval2[3] /= scale; |
926 | eval2[4] /= scale; |
927 | eval2[5] /= scale; |
928 | |
929 | if (fabs(fabs(dot_DoubleVal(&eval[3], &eval2[3])) - 1) < 1E-6) { |
930 | status = EGADS_OUTSIDE1; |
931 | break; |
932 | } |
933 | } |
934 | |
935 | if (status == EGADS_OUTSIDE1) { |
936 | if (quadMesh == (int)true1) { |
937 | printf("Face %d has parallel edges - not quading\n", i); |
938 | } |
939 | continue; |
940 | } |
941 | |
942 | if (status == EGADS_DEGEN-24) { |
943 | if (quadMesh == (int)true1) { |
944 | printf("Face %d has a degenerate edge - not quading\n", i); |
945 | } |
946 | continue; |
947 | } |
948 | |
949 | isouth[i] = status = EG_indexBodyTopo(ebody, echilds[0]); |
950 | if (status < EGADS_SUCCESS0) goto cleanup; |
951 | |
952 | ieast[i] = status = EG_indexBodyTopo(ebody, echilds[1]); |
953 | if (status < EGADS_SUCCESS0) goto cleanup; |
954 | |
955 | inorth[i] = status = EG_indexBodyTopo(ebody, echilds[2]); |
956 | if (status < EGADS_SUCCESS0) goto cleanup; |
957 | |
958 | iwest[i] = status = EG_indexBodyTopo(ebody, echilds[3]); |
959 | if (status < EGADS_SUCCESS0) goto cleanup; |
960 | } |
961 | |
962 | // make "opposite" sides of four-sided Faces (with only one loop) match |
963 | nchange = 1; |
964 | for (i = 0; i < 20; i++) { |
965 | nchange = 0; |
966 | |
967 | for (face = 1; face <= numFace; face++) { |
968 | if (isouth[face] <= 0 || ieast[face] <= 0 || |
969 | inorth[face] <= 0 || iwest[face] <= 0 ) continue; |
970 | |
971 | if (points[iwest[face]] < points[ieast[face]]) { |
972 | points[iwest[face]] = points[ieast[face]]; |
973 | nchange++; |
974 | |
975 | } else if (points[ieast[face]] < points[iwest[face]]) { |
976 | points[ieast[face]] = points[iwest[face]]; |
977 | nchange++; |
978 | } |
979 | |
980 | if (points[isouth[face]] < points[inorth[face]]) { |
981 | points[isouth[face]] = points[inorth[face]]; |
982 | nchange++; |
983 | } else if (points[inorth[face]] < points[isouth[face]]) { |
984 | points[inorth[face]] = points[isouth[face]]; |
985 | nchange++; |
986 | } |
987 | } |
988 | if (nchange == 0) break; |
989 | } |
990 | if (nchange > 0) { |
991 | printf("Exceeded number of tries making \"opposite\" sides of four-sided Faces (with only one loop) match\n"); |
992 | status = CAPS_MISMATCH-324; |
993 | goto cleanup; |
994 | } |
995 | |
996 | // mark the Edges with points[iedge] evenly-spaced points |
997 | for (edge = 1; edge <= numEdge; edge++) { |
998 | for (i = 1; i < points[edge]-1; i++) { |
999 | rpos[i-1] = (double)(i) / (double)(points[edge]-1); |
1000 | } |
1001 | |
1002 | if (points[edge] == 2) { |
1003 | i = 0; |
1004 | status = EG_attributeAdd(eedges[edge-1], ".rPos", ATTRINT1, 1, &i, NULL((void*)0), NULL((void*)0)); |
1005 | if (status < EGADS_SUCCESS0) goto cleanup; |
1006 | |
1007 | } else { |
1008 | status = EG_attributeAdd(eedges[edge-1], ".rPos", ATTRREAL2, points[edge]-2, NULL((void*)0), rpos, NULL((void*)0)); |
1009 | if (status < EGADS_SUCCESS0) goto cleanup; |
1010 | } |
1011 | } |
1012 | |
1013 | // Make tessellation |
1014 | status = EG_makeTessBody(ebody, params, &feaMesh->egadsTess); |
1015 | if (status != EGADS_SUCCESS0) { |
1016 | printf("\tError in fea_bodyToBEM: EG_makeTessBody\n"); |
1017 | goto cleanup; |
1018 | } |
1019 | |
1020 | // Make Quads on each four-sided Face |
1021 | params[0] = 0; |
1022 | params[1] = 0; |
1023 | params[2] = 0; |
1024 | |
1025 | // If making quads on faces lets setup an array to keep track of which faces have been quaded. |
1026 | if (quadMesh == (int)true1) { |
1027 | if( numFace > 0) { |
1028 | AIM_ALLOC(qints, numFace, int, aimInfo, status){ if (qints != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 1028, __func__, 1, "AIM_ALLOC: %s != NULL" , "qints"); goto cleanup; } size_t memorysize = numFace; qints = (int *) EG_alloc(memorysize*sizeof(int)); if (qints == ((void *)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 1028, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "qints" , memorysize, "int"); goto cleanup; } }; |
1029 | } |
1030 | // Set default to 0 |
1031 | for (face = 0; face < numFace; face++) qints[face] = 0; |
1032 | } |
1033 | |
1034 | if (quadMesh == (int)true1) { |
1035 | for (face = 1; face <= numFace; face++) { |
1036 | if (iwest[face] <= 0) continue; |
1037 | |
1038 | status = EG_makeQuads(feaMesh->egadsTess, params, face); |
1039 | if (status < EGADS_SUCCESS0) { |
1040 | printf("Face = %d, failed to make quads\n", face); |
1041 | printf("Edges = %d %d %d %d\n", inorth[face], ieast[face], isouth[face], iwest[face]); |
1042 | continue; |
1043 | //goto cleanup; |
1044 | } |
1045 | } |
1046 | } |
1047 | |
1048 | // Set the mesh type information |
1049 | feaMesh->meshType = SurfaceMesh; |
1050 | feaMesh->analysisType = MeshStructure; |
1051 | |
1052 | // Get number of point in the tessellation |
1053 | status = EG_statusTessBody(feaMesh->egadsTess, &tempBody, &i, &feaMesh->numNode); |
1054 | if (status != EGADS_SUCCESS0) goto cleanup; |
1055 | |
1056 | feaMesh->node = (meshNodeStruct *) EG_alloc(feaMesh->numNode*sizeof(meshNodeStruct)); |
1057 | if (feaMesh->node == NULL((void*)0)) { |
1058 | feaMesh->numNode = 0; |
1059 | status = EGADS_MALLOC-4; |
1060 | goto cleanup; |
1061 | } |
1062 | |
1063 | for (i = 0; i < feaMesh->numNode; i++) { |
1064 | status = initiate_meshNodeStruct(&feaMesh->node[i], feaMesh->analysisType); |
1065 | if (status != CAPS_SUCCESS0) goto cleanup; |
1066 | } |
1067 | |
1068 | // Fill up the Attributes for the nodes |
1069 | for (i = 0; i < feaMesh->numNode; i++) { |
1070 | |
1071 | status = EG_getGlobal(feaMesh->egadsTess, i+1, &pointType, &pointTopoIndex, xyzPoint); |
1072 | if (status != EGADS_SUCCESS0) goto cleanup; |
1073 | |
1074 | feaMesh->node[i].xyz[0] = xyzPoint[0]; |
1075 | feaMesh->node[i].xyz[1] = xyzPoint[1]; |
1076 | feaMesh->node[i].xyz[2] = xyzPoint[2]; |
1077 | |
1078 | feaMesh->node[i].nodeID = i+1; |
1079 | |
1080 | feaData = (feaMeshDataStruct *) feaMesh->node[i].analysisData; |
1081 | |
1082 | status = fea_setFEADataPoint(efaces, eedges, enodes, |
1083 | attrMap, |
1084 | coordSystemMap, |
1085 | constraintMap, |
1086 | loadMap, |
1087 | transferMap, |
1088 | connectMap, |
1089 | responseMap, |
1090 | referenceMap, |
1091 | pointType, pointTopoIndex, |
1092 | feaData); // Set the feaData structure |
1093 | if (status != CAPS_SUCCESS0) goto cleanup; |
1094 | } |
1095 | |
1096 | // Fill element information |
1097 | |
1098 | // If body is just a single node |
1099 | if (isNodeBody == EGADS_SUCCESS0) { |
1100 | |
1101 | if (numNode != 1) { |
1102 | printf("NodeBody found, but more than one node being reported!\n"); |
1103 | status = CAPS_BADVALUE-311; |
1104 | goto cleanup; |
1105 | } |
1106 | |
1107 | numElement = numNode; |
1108 | feaMesh->numElement = numElement; |
1109 | |
1110 | feaMesh->element = (meshElementStruct *) EG_alloc(feaMesh->numElement*sizeof(meshElementStruct)); |
1111 | if (feaMesh->element == NULL((void*)0)) { |
1112 | status = EGADS_MALLOC-4; |
1113 | feaMesh->numElement = 0; |
1114 | goto cleanup; |
1115 | } |
1116 | |
1117 | i = 0; |
1118 | (void) initiate_meshElementStruct(&feaMesh->element[i], feaMesh->analysisType); |
1119 | |
1120 | status = retrieve_CAPSGroupAttr(enodes[i], &attrName); |
1121 | if (status != CAPS_SUCCESS0) { |
1122 | AIM_ERROR(aimInfo, "No capsGroup attribute found for node - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1122, __func__ , "No capsGroup attribute found for node - %d!!", i+1); }; |
1123 | print_AllAttr(aimInfo, enodes[i]); |
1124 | goto cleanup; |
1125 | } |
1126 | |
1127 | status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex); |
1128 | if (status != CAPS_SUCCESS0) { |
1129 | printf("\tError: capsGroup name %s not found in attribute to index map\n", attrName); |
1130 | goto cleanup; |
1131 | } |
1132 | |
1133 | feaMesh->element[i].elementType = Node; |
1134 | |
1135 | feaMesh->element[i].elementID = i+1; |
1136 | |
1137 | status = mesh_allocMeshElementConnectivity(&feaMesh->element[i]); |
1138 | if (status != CAPS_SUCCESS0) goto cleanup; |
1139 | |
1140 | feaMesh->element[i].markerID = attrIndex; |
1141 | |
1142 | feaMesh->element[i].connectivity[0] = i+1; |
1143 | |
1144 | feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData; |
1145 | |
1146 | feaData->propertyID = attrIndex; |
1147 | |
1148 | feaData->attrIndex = attrIndex; |
1149 | |
1150 | status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex); |
1151 | if (status == CAPS_SUCCESS0) { |
1152 | feaData->coordID = coordSystemIndex; |
1153 | } else { |
1154 | feaData->coordID = coordID; |
1155 | } |
1156 | |
1157 | feaMesh->meshQuickRef.numNode += 1; // Add count |
1158 | |
1159 | feaMesh->meshQuickRef.startIndexNode = 0; |
1160 | feaMesh->meshQuickRef.useStartIndex = (int) true1; |
1161 | |
1162 | status = CAPS_SUCCESS0; |
1163 | goto cleanup; |
1164 | |
1165 | } //NODEBODY IF |
1166 | |
1167 | /* Determine of the body type */ |
1168 | status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses); |
1169 | if (status != EGADS_SUCCESS0) goto cleanup; |
1170 | |
1171 | // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces |
1172 | // as "free" edges |
1173 | if (bodySubType == WIREBODY6) { |
1174 | feaMesh->numElement = numEdge; |
1175 | |
1176 | feaMesh->element = (meshElementStruct *) EG_alloc(feaMesh->numElement*sizeof(meshElementStruct)); |
1177 | if (feaMesh->element == NULL((void*)0)) { |
1178 | status = EGADS_MALLOC-4; |
1179 | feaMesh->numElement = 0; |
1180 | goto cleanup; |
1181 | } |
1182 | |
1183 | for (i = 0; i < feaMesh->numElement; i++) { |
1184 | (void) initiate_meshElementStruct(&feaMesh->element[i], feaMesh->analysisType); |
1185 | } |
1186 | |
1187 | for (i = 0; i < numEdge; i++) { |
1188 | |
1189 | status = EG_getInfo(eedges[i], &oclass, &mtype, &topObj, &prev, &next); |
1190 | if (status != CAPS_SUCCESS0) goto cleanup; |
1191 | if (mtype == DEGENERATE5) continue; |
1192 | |
1193 | status = retrieve_CAPSIgnoreAttr(eedges[i], &attrName); |
1194 | if (status == CAPS_SUCCESS0) { |
1195 | printf("\tcapsIgnore attribute found for edge - %d!!\n", i+1); |
1196 | continue; |
1197 | } |
1198 | |
1199 | numElement += 1; |
1200 | |
1201 | status = retrieve_CAPSGroupAttr(eedges[i], &attrName); |
1202 | if (status != CAPS_SUCCESS0) { |
1203 | AIM_ERROR(aimInfo, "No capsGroup attribute found for edge - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1203, __func__ , "No capsGroup attribute found for edge - %d!!", i+1); }; |
1204 | print_AllAttr(aimInfo, eedges[i] ); |
1205 | goto cleanup; |
1206 | } |
1207 | |
1208 | status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex); |
1209 | if (status != CAPS_SUCCESS0) { |
1210 | AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map\n", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1210, __func__ , "capsGroup name %s not found in attribute to index map\n", attrName ); }; |
1211 | goto cleanup; |
1212 | } |
1213 | |
1214 | feaMesh->element[numElement-1].elementType = Line; |
1215 | |
1216 | feaMesh->element[numElement-1].elementID = numElement; |
1217 | |
1218 | status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]); |
1219 | if (status != CAPS_SUCCESS0) goto cleanup; |
1220 | |
1221 | feaMesh->element[numElement-1].markerID = attrIndex; |
1222 | |
1223 | status = EG_getTessEdge(feaMesh->egadsTess, i+1, &numPoint, &xyz, &uv); |
1224 | if (status < EGADS_SUCCESS0) goto cleanup; |
1225 | |
1226 | status = EG_localToGlobal(feaMesh->egadsTess, -(i+1), 1, &gID); |
1227 | if (status != EGADS_SUCCESS0) goto cleanup; |
1228 | |
1229 | feaMesh->element[numElement-1].connectivity[0] = gID; |
1230 | |
1231 | status = EG_localToGlobal(feaMesh->egadsTess, -(i+1), numPoint, &gID); |
1232 | if (status != EGADS_SUCCESS0) goto cleanup; |
1233 | |
1234 | feaMesh->element[numElement-1].connectivity[1] = gID; |
1235 | |
1236 | feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData; |
1237 | |
1238 | feaData->propertyID = attrIndex; |
1239 | |
1240 | feaData->attrIndex = attrIndex; |
1241 | |
1242 | status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex); |
1243 | if (status == CAPS_SUCCESS0) { |
1244 | feaData->coordID = coordSystemIndex; |
1245 | } else { |
1246 | feaData->coordID = coordID; |
1247 | } |
1248 | |
1249 | feaMesh->meshQuickRef.numLine += 1; // Add count |
1250 | |
1251 | } |
1252 | |
1253 | if (feaMesh->meshQuickRef.numLine != numEdge) { // Resize our array in case we have some ignores |
1254 | |
1255 | tempElement = (meshElementStruct *) EG_reall(feaMesh->element, |
1256 | feaMesh->meshQuickRef.numLine*sizeof(meshElementStruct)); |
1257 | |
1258 | if (tempElement == NULL((void*)0)) { |
1259 | status = EGADS_MALLOC-4; |
1260 | goto cleanup; |
1261 | } |
1262 | |
1263 | feaMesh->element = tempElement; |
1264 | |
1265 | feaMesh->numElement = feaMesh->meshQuickRef.numLine; |
1266 | } |
1267 | |
1268 | feaMesh->meshQuickRef.startIndexLine = 0; |
1269 | feaMesh->meshQuickRef.useStartIndex = (int) true1; |
1270 | |
1271 | status = CAPS_SUCCESS0; |
1272 | goto cleanup; |
1273 | |
1274 | } //WIREBODY IF |
1275 | |
1276 | if (quadMesh == (int) true1 && numFace > 0) { |
1277 | printf("\tGetting quads for BEM!\n"); |
1278 | |
1279 | // Turn off meshQuick guide if you are getting quads |
1280 | feaMesh->meshQuickRef.useStartIndex = (int) false0; |
1281 | } else { |
1282 | feaMesh->meshQuickRef.useStartIndex = (int) true1; |
1283 | feaMesh->meshQuickRef.startIndexTriangle = numElement; |
1284 | } |
1285 | |
1286 | // Get Tris and Quads from faces |
1287 | for (face = 0; face < numFace; face++) { |
1288 | |
1289 | status = retrieve_CAPSIgnoreAttr(efaces[face], &attrName); |
1290 | if (status == CAPS_SUCCESS0) { |
1291 | printf("\tcapsIgnore attribute found for face - %d!!\n", face+1); |
1292 | ignoreFound = (int) true1; |
1293 | continue; |
1294 | } |
1295 | |
1296 | status = retrieve_CAPSGroupAttr(efaces[face], &attrName); |
1297 | if (status != CAPS_SUCCESS0) { |
1298 | AIM_ERROR(aimInfo, "No capsGroup attribute found for face - %d!!", face+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1298, __func__ , "No capsGroup attribute found for face - %d!!", face+1); }; |
1299 | print_AllAttr(aimInfo, efaces[face]); |
1300 | goto cleanup; |
1301 | } |
1302 | |
1303 | status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex); |
1304 | if (status != CAPS_SUCCESS0) { |
1305 | AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1305, __func__ , "capsGroup name %s not found in attribute to index map", attrName ); }; |
1306 | goto cleanup; |
1307 | } |
1308 | |
1309 | status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex); |
1310 | if (status != CAPS_SUCCESS0) coordSystemIndex = 0; |
1311 | |
1312 | |
1313 | loadIndex = CAPSMAGIC1234321; |
1314 | status = retrieve_CAPSLoadAttr(efaces[face], &attrName); |
1315 | if (status == CAPS_SUCCESS0) { |
1316 | |
1317 | status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex); |
1318 | |
1319 | if (status != CAPS_SUCCESS0) { |
1320 | printf("Error: capsLoad name %s not found in attribute to index map\n", attrName); |
1321 | goto cleanup; |
1322 | } |
1323 | } |
1324 | |
1325 | if (quadMesh == (int) true1) { |
1326 | status = EG_getQuads(feaMesh->egadsTess, face+1, &numPoint, &xyz, &uv, &ptype, &pindex, &numPatch); |
1327 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1327 , __func__, 0); goto cleanup; }; |
1328 | |
1329 | } else numPatch = -1; |
1330 | |
1331 | if (numPatch > 0) { |
1332 | |
1333 | if (numPatch != 1) { |
1334 | status = CAPS_NOTIMPLEMENT-334; |
1335 | printf("feaUtils: EG_localToGlobal accidentally only works for a single quad patch! FIXME!\n"); |
1336 | goto cleanup; |
1337 | } |
1338 | |
1339 | qints[face] = 0; |
1340 | for (patch = 1; patch <= numPatch; patch++) { |
1341 | |
1342 | status = EG_getPatch(feaMesh->egadsTess, face+1, patch, &n1, &n2, &pvindex, &pbounds); |
1343 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1343 , __func__, 0); goto cleanup; }; |
1344 | |
1345 | for (j = 1; j < n2; j++) { |
1346 | for (i = 1; i < n1; i++) { |
1347 | numElement += 1; |
1348 | |
1349 | feaMesh->meshQuickRef.numQuadrilateral += 1; |
1350 | feaMesh->numElement = numElement; |
1351 | |
1352 | tempElement = (meshElementStruct *) EG_reall(feaMesh->element, |
1353 | feaMesh->numElement*sizeof(meshElementStruct)); |
1354 | |
1355 | if (tempElement == NULL((void*)0)) { |
1356 | status = EGADS_MALLOC-4; |
1357 | feaMesh->numElement -= 1; |
1358 | goto cleanup; |
1359 | } |
1360 | |
1361 | feaMesh->element = tempElement; |
1362 | |
1363 | status = initiate_meshElementStruct(&feaMesh->element[numElement-1], feaMesh->analysisType); |
1364 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1364 , __func__, 0); goto cleanup; }; |
1365 | |
1366 | qints[face] += 1; |
1367 | |
1368 | feaMesh->element[numElement-1].elementType = Quadrilateral; |
1369 | |
1370 | feaMesh->element[numElement-1].elementID = numElement; |
1371 | |
1372 | status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]); |
1373 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1373 , __func__, 0); goto cleanup; }; |
1374 | |
1375 | status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i-1)+n1*(j-1)], &gID); |
1376 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1376 , __func__, 0); goto cleanup; }; |
1377 | |
1378 | feaMesh->element[numElement-1].connectivity[0] = gID; |
1379 | |
1380 | status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i )+n1*(j-1)], &gID); |
1381 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1381 , __func__, 0); goto cleanup; }; |
1382 | |
1383 | feaMesh->element[numElement-1].connectivity[1] = gID; |
1384 | |
1385 | status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i )+n1*(j )], &gID); |
1386 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1386 , __func__, 0); goto cleanup; }; |
1387 | |
1388 | feaMesh->element[numElement-1].connectivity[2] = gID; |
1389 | |
1390 | status = EG_localToGlobal(feaMesh->egadsTess, face+1, pvindex[(i-1)+n1*(j )], &gID); |
1391 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1391 , __func__, 0); goto cleanup; }; |
1392 | |
1393 | feaMesh->element[numElement-1].connectivity[3] = gID; |
1394 | |
1395 | feaMesh->element[numElement-1].markerID = attrIndex; |
1396 | |
1397 | feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData; |
1398 | |
1399 | feaData->propertyID = attrIndex; |
1400 | feaData->attrIndex = attrIndex; |
1401 | feaData->coordID = coordSystemIndex; |
1402 | feaData->loadIndex = loadIndex; |
1403 | |
1404 | } |
1405 | } |
1406 | |
1407 | } |
1408 | } else { |
1409 | status = EG_getTessFace(feaMesh->egadsTess, face+1, |
1410 | &numPoint, &xyz, &uv, &ptype, &pindex, |
1411 | &numTri, &triConn, &triNeighbor); |
1412 | if (status < EGADS_SUCCESS0) goto cleanup; |
1413 | |
1414 | for (i= 0; i < numTri; i++) { |
1415 | |
1416 | numElement += 1; |
1417 | |
1418 | feaMesh->meshQuickRef.numTriangle += 1; |
1419 | feaMesh->numElement = numElement; |
1420 | |
1421 | |
1422 | tempElement = (meshElementStruct *) EG_reall(feaMesh->element, |
1423 | feaMesh->numElement*sizeof(meshElementStruct)); |
1424 | |
1425 | if (tempElement == NULL((void*)0)) { |
1426 | status = EGADS_MALLOC-4; |
1427 | feaMesh->numElement -= 1; |
1428 | goto cleanup; |
1429 | } |
1430 | |
1431 | feaMesh->element = tempElement; |
1432 | |
1433 | status = initiate_meshElementStruct(&feaMesh->element[numElement-1], feaMesh->analysisType); |
1434 | if (status != CAPS_SUCCESS0) goto cleanup; |
1435 | |
1436 | feaMesh->element[numElement-1].elementType = Triangle; |
1437 | |
1438 | feaMesh->element[numElement-1].elementID = numElement; |
1439 | |
1440 | status = mesh_allocMeshElementConnectivity(&feaMesh->element[numElement-1]); |
1441 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1441 , __func__, 0); goto cleanup; }; |
1442 | |
1443 | status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 0], &gID); |
1444 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1444 , __func__, 0); goto cleanup; }; |
1445 | |
1446 | feaMesh->element[numElement-1].connectivity[0] = gID; |
1447 | |
1448 | status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 1], &gID); |
1449 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1449 , __func__, 0); goto cleanup; }; |
1450 | |
1451 | feaMesh->element[numElement-1].connectivity[1] = gID; |
1452 | |
1453 | status = EG_localToGlobal(feaMesh->egadsTess, face+1, triConn[3*i + 2], &gID); |
1454 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1454 , __func__, 0); goto cleanup; }; |
1455 | |
1456 | feaMesh->element[numElement-1].connectivity[2] = gID; |
1457 | |
1458 | feaMesh->element[numElement-1].markerID = attrIndex; |
1459 | |
1460 | feaData = (feaMeshDataStruct *) feaMesh->element[numElement-1].analysisData; |
1461 | |
1462 | feaData->propertyID = attrIndex; |
1463 | feaData->attrIndex = attrIndex; |
1464 | feaData->coordID = coordSystemIndex; |
1465 | feaData->loadIndex = loadIndex; |
1466 | |
1467 | } |
1468 | } |
1469 | |
1470 | } |
1471 | |
1472 | if (numPatch > 0) { |
1473 | status = EG_attributeAdd(feaMesh->egadsTess, ".mixed", ATTRINT1, numFace, qints, NULL((void*)0), NULL((void*)0)); |
1474 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1474 , __func__, 0); goto cleanup; }; |
1475 | } |
1476 | |
1477 | if (ignoreFound == (int) true1) { |
1478 | |
1479 | // Look at the nodeID for each node and check to see if it is being used in the element connectivity; if not it is removed |
1480 | // Note: that the nodeIDs for the nodes and element connectivity isn't changed, as such if using element connectivity to blindly |
1481 | // access a given node this could lead to seg-faults!. mesh_nodeID2Array must be used to access the node array index. |
1482 | status = mesh_removeUnusedNodes(feaMesh); |
1483 | if (status != CAPS_SUCCESS0) goto cleanup; |
1484 | } |
1485 | |
1486 | status = CAPS_SUCCESS0; |
1487 | |
1488 | cleanup: |
1489 | if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_bodyToBem, status = %d\n", status); |
1490 | |
1491 | AIM_FREE(iwest ){ EG_free(iwest); iwest = ((void*)0); }; |
1492 | AIM_FREE(inorth){ EG_free(inorth); inorth = ((void*)0); }; |
1493 | AIM_FREE(ieast ){ EG_free(ieast); ieast = ((void*)0); }; |
1494 | AIM_FREE(isouth){ EG_free(isouth); isouth = ((void*)0); }; |
1495 | AIM_FREE(rpos ){ EG_free(rpos); rpos = ((void*)0); }; |
1496 | AIM_FREE(points ){ EG_free(points); points = ((void*)0); }; |
1497 | |
1498 | AIM_FREE(enodes){ EG_free(enodes); enodes = ((void*)0); }; |
1499 | AIM_FREE(eedges){ EG_free(eedges); eedges = ((void*)0); }; |
1500 | AIM_FREE(efaces){ EG_free(efaces); efaces = ((void*)0); }; |
1501 | |
1502 | AIM_FREE(qints){ EG_free(qints); qints = ((void*)0); }; |
1503 | |
1504 | enodes = NULL((void*)0); |
1505 | eedges =NULL((void*)0); |
1506 | efaces =NULL((void*)0); |
1507 | |
1508 | return status; |
1509 | } |
1510 | |
1511 | // Set the fea analysis meta data in a mesh |
1512 | int fea_setAnalysisData( void *aimInfo, // (in) AIM structure |
1513 | mapAttrToIndexStruct *attrMap, // (in) map from CAPSGroup names to indexes |
1514 | mapAttrToIndexStruct *coordSystemMap,// (in) map from CoordSystem names to indexes |
1515 | mapAttrToIndexStruct *constraintMap, // (in) map from CAPSConstraint names to indexes |
1516 | mapAttrToIndexStruct *loadMap, // (in) map from CAPSLoad names to indexes |
1517 | mapAttrToIndexStruct *transferMap, // (in) map from CAPSTransfer names to indexes |
1518 | mapAttrToIndexStruct *connectMap, // (in) map from CAPSConnect names to indexes |
1519 | mapAttrToIndexStruct *responseMap, // (in) map from CAPSResponse names to indexes |
1520 | mapAttrToIndexStruct *referenceMap, // (in) map from CAPSReference names to indexes |
1521 | meshStruct *feaMesh) // (in/out) FEA mesh structure |
1522 | { |
1523 | int status = 0; // Function return status |
1524 | |
1525 | int i, face, edge, node, body; // Indexing |
1526 | int dummy; |
1527 | |
1528 | int nodeOffset=0, elementOffset=0; |
1529 | |
1530 | // Body entities |
1531 | int numNode = 0, numEdge = 0, numFace = 0; |
1532 | ego *enodes=NULL((void*)0), *eedges=NULL((void*)0), *efaces=NULL((void*)0); |
1533 | ego ebody; |
1534 | |
1535 | // Meshing |
1536 | int elem; |
1537 | |
1538 | int oclass, nchild, *senses; |
1539 | |
1540 | // Edge point distributions |
1541 | int *points=NULL((void*)0), *isouth=NULL((void*)0), *ieast=NULL((void*)0), *inorth=NULL((void*)0), *iwest=NULL((void*)0); |
1542 | double data[4]; |
1543 | double *rpos=NULL((void*)0); |
1544 | ego eref, *echilds;//, topObj, prev, next; |
1545 | |
1546 | int isNodeBody, bodySubType = 0; // Body classification |
1547 | |
1548 | int pointType, pointTopoIndex; |
1549 | double xyzPoint[3]; |
1550 | |
1551 | // Meshing |
1552 | int numPoint = 0, numTri = 0; |
1553 | const int *triConn = NULL((void*)0), *triNeighbor = NULL((void*)0); // Triangle |
1554 | |
1555 | int gID; // Global id |
1556 | |
1557 | const double *xyz, *uv; |
1558 | double result[18]; |
1559 | |
1560 | const int *ptype = NULL((void*)0), *pindex = NULL((void*)0); |
1561 | |
1562 | // Attributues |
1563 | const char *attrName; |
1564 | int attrIndex, coordSystemIndex, loadIndex; |
1565 | |
1566 | feaMeshDataStruct *feaData = NULL((void*)0); |
1567 | meshGeomDataStruct *geomData; |
1568 | |
1569 | // --------------------------------------------------------------- |
1570 | |
1571 | if (feaMesh->meshType == SurfaceMesh || feaMesh->meshType == Surface2DMesh ) { |
1572 | printf("Setting FEA Data\n"); |
1573 | |
1574 | // Get body from tessellation |
1575 | status = EG_statusTessBody(feaMesh->egadsTess, &ebody, &dummy, &dummy); |
1576 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1576 , __func__, 0); goto cleanup; }; |
1577 | |
1578 | // Get number of Nodes, Edges, and Faces in ebody |
1579 | status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes); |
1580 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1580 , __func__, 0); goto cleanup; }; |
1581 | AIM_NOTNULL(enodes, aimInfo, status){ if (enodes == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 1581, __func__, 1, "%s == NULL!", "enodes" ); goto cleanup; } }; |
1582 | |
1583 | status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges); |
1584 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1584 , __func__, 0); goto cleanup; }; |
1585 | |
1586 | status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces); |
1587 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1587 , __func__, 0); goto cleanup; }; |
1588 | |
1589 | // What type of BODY do we have? |
1590 | isNodeBody = aim_isNodeBody(ebody, xyzPoint); |
1591 | if (isNodeBody < EGADS_SUCCESS0) goto cleanup; |
1592 | if (isNodeBody == EGADS_SUCCESS0) { |
1593 | // all attributes are on the body rather than the node for a node body |
1594 | enodes[0] = ebody; |
1595 | } |
1596 | |
1597 | // Fill up the Attributes for the nodes |
1598 | for (i = 0; i < feaMesh->numNode; i++) { |
1599 | |
1600 | status = EG_getGlobal(feaMesh->egadsTess, feaMesh->node[i].nodeID, &pointType, &pointTopoIndex, xyzPoint); |
1601 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1601 , __func__, 0); goto cleanup; }; |
1602 | |
1603 | feaData = (feaMeshDataStruct *) feaMesh->node[i].analysisData; |
1604 | |
1605 | status = fea_setFEADataPoint(efaces, eedges, enodes, |
1606 | attrMap, |
1607 | coordSystemMap, |
1608 | constraintMap, |
1609 | loadMap, |
1610 | transferMap, |
1611 | connectMap, |
1612 | responseMap, |
1613 | referenceMap, |
1614 | pointType, pointTopoIndex, |
1615 | feaData); // Set the feaData structure |
1616 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1616 , __func__, 0); goto cleanup; }; |
1617 | } |
1618 | |
1619 | // Fill element information |
1620 | |
1621 | // If body is just a single node |
1622 | if (numNode == 1) { |
1623 | |
1624 | if (feaMesh->numNode != 1) { |
1625 | AIM_ERROR(aimInfo, "NodeBody found, but more than one node being reported!\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1625, __func__ , "NodeBody found, but more than one node being reported!\n") ; }; |
1626 | status = CAPS_BADVALUE-311; |
1627 | goto cleanup; |
1628 | } |
1629 | |
1630 | i = 0; |
1631 | status = retrieve_CAPSGroupAttr(enodes[i], &attrName); |
1632 | if (status != CAPS_SUCCESS0) { |
1633 | AIM_ERROR(aimInfo, "No capsGroup attribute found for node - %d!!", i+1){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1633, __func__ , "No capsGroup attribute found for node - %d!!", i+1); }; |
1634 | print_AllAttr(aimInfo, enodes[i] ); |
1635 | goto cleanup; |
1636 | } |
1637 | |
1638 | status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex); |
1639 | if (status != CAPS_SUCCESS0) { |
1640 | AIM_ERROR(aimInfo, "capsGroup name %s not found in attribute to index map", attrName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 1640, __func__ , "capsGroup name %s not found in attribute to index map", attrName ); }; |
1641 | goto cleanup; |
1642 | } |
1643 | |
1644 | feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData; |
1645 | |
1646 | feaData->propertyID = attrIndex; |
1647 | |
1648 | feaData->attrIndex = attrIndex; |
1649 | |
1650 | status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex); |
1651 | if (status != CAPS_SUCCESS0) coordSystemIndex = 0; |
1652 | |
1653 | feaData->coordID = coordSystemIndex; |
1654 | |
1655 | status = CAPS_SUCCESS0; |
1656 | goto cleanup; |
1657 | |
1658 | } //NODEBODY IF |
1659 | |
1660 | #if 0 |
1661 | /* Determine the body type */ |
1662 | status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses); |
1663 | if (status != EGADS_SUCCESS0) goto cleanup; |
1664 | |
1665 | // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces |
1666 | // as "free" edges |
1667 | if (bodySubType == WIREBODY6) { |
1668 | |
1669 | for (i = 0; i < feaMesh->meshQuickRef.numLine; i++) { |
1670 | |
1671 | status = EG_getInfo(eedges[i], &oclass, &mtype, &topObj, &prev, &next); |
1672 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1672 , __func__, 0); goto cleanup; }; |
1673 | if (mtype == DEGENERATE5) continue; |
1674 | |
1675 | if (feaMesh->meshQuickRef.useStartIndex == (int)true1) |
1676 | elem = i + feaMesh->meshQuickRef.startIndexLine; |
1677 | else if (feaMesh->meshQuickRef.useListIndex == (int)true1) |
1678 | elem = feaMesh->meshQuickRef.listIndexLine[i]; |
1679 | else { |
1680 | status = CAPS_BADOBJECT-310; |
1681 | printf("DEVELOPER ERROR: Both useStartIndex and useListIndex are true!\n"); |
1682 | goto cleanup; |
1683 | } |
1684 | |
1685 | attrIndex = feaMesh->element[elem].markerID; |
1686 | |
1687 | // get the capsGroup attribute string value |
1688 | status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName); |
1689 | if (status != CAPS_SUCCESS0) { |
1690 | printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex); |
1691 | goto cleanup; |
1692 | } |
1693 | |
1694 | feaData = (feaMeshDataStruct *) feaMesh->element[elem].analysisData; |
1695 | |
1696 | status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex); |
1697 | if (status != CAPS_SUCCESS0) coordSystemIndex = 0; |
1698 | |
1699 | feaData->propertyID = attrIndex; |
1700 | feaData->coordID = coordSystemIndex; |
1701 | } |
1702 | |
1703 | status = CAPS_SUCCESS0; |
1704 | goto cleanup; |
1705 | |
1706 | } |
1707 | #endif |
1708 | |
1709 | |
1710 | // Set line, tri and quad analysis data |
1711 | for (elem = 0; elem < feaMesh->numElement; elem++) { |
1712 | |
1713 | if (feaMesh->element[elem].elementType != Node && |
1714 | feaMesh->element[elem].elementType != Line && |
1715 | feaMesh->element[elem].elementType != Triangle && |
1716 | feaMesh->element[elem].elementType != Triangle_6 && |
1717 | feaMesh->element[elem].elementType != Quadrilateral && |
1718 | feaMesh->element[elem].elementType != Quadrilateral_8) continue; |
1719 | |
1720 | attrIndex = feaMesh->element[elem].markerID; |
1721 | |
1722 | // get the capsGroup attribute string value |
1723 | status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName); |
1724 | if (status != CAPS_SUCCESS0) { |
1725 | printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex); |
1726 | goto cleanup; |
1727 | } |
1728 | |
1729 | status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex); |
1730 | if (status != CAPS_SUCCESS0) coordSystemIndex = 0; |
1731 | |
1732 | if (feaMesh->element[elem].elementType == Node) { |
1733 | // get the node index |
1734 | node = feaMesh->element[elem].topoIndex; |
1735 | if (node < 1 || node > numNode) { |
1736 | printf("Error: Element '%d': Invalid node topological index: %d, [1-%d]\n", elem, node, numNode); |
1737 | status = CAPS_BADVALUE-311; |
1738 | goto cleanup; |
1739 | } |
1740 | |
1741 | eref = enodes[node-1]; |
1742 | |
1743 | } else if (feaMesh->element[elem].elementType == Line) { |
1744 | // get the edge index |
1745 | edge = feaMesh->element[elem].topoIndex; |
1746 | if (edge < 1 || edge > numEdge) { |
1747 | printf("Error: Element '%d': Invalid edge topological index: %d, [1-%d]\n", elem, edge, numEdge); |
1748 | status = CAPS_BADVALUE-311; |
1749 | goto cleanup; |
1750 | } |
1751 | |
1752 | eref = eedges[edge-1]; |
1753 | |
1754 | } else { |
1755 | |
1756 | // get the face index |
1757 | face = feaMesh->element[elem].topoIndex; |
1758 | if (face < 1 || face > numFace) { |
1759 | printf("Error: Element '%d': Invalid face topological index: %d, [1-%d]\n", elem, face, numFace); |
1760 | status = CAPS_BADVALUE-311; |
1761 | goto cleanup; |
1762 | } |
1763 | |
1764 | eref = efaces[face-1]; |
1765 | |
1766 | // If this is a face in a capsBound, set geomData in nodes |
1767 | status = retrieve_CAPSBoundAttr(eref, &attrName); |
1768 | if (status == CAPS_SUCCESS0) { |
1769 | |
1770 | status = EG_getTessFace(feaMesh->egadsTess, face, |
1771 | &numPoint, &xyz, &uv, &ptype, &pindex, |
1772 | &numTri, &triConn, &triNeighbor); |
1773 | if (status < EGADS_SUCCESS0) goto cleanup; |
1774 | |
1775 | for (i = 0; i < numPoint; i++) { |
1776 | |
1777 | status = EG_localToGlobal(feaMesh->egadsTess, face, i+1, &gID); |
1778 | if (status != EGADS_SUCCESS0) goto cleanup; |
1779 | |
1780 | geomData = feaMesh->node[gID-1].geomData; |
1781 | |
1782 | if (geomData == NULL((void*)0)) { |
1783 | |
1784 | // Get geometry data for node |
1785 | geomData = EG_alloc(sizeof(meshGeomDataStruct)); |
1786 | |
1787 | if (geomData == NULL((void*)0)) { |
1788 | status = EGADS_MALLOC-4; |
1789 | goto cleanup; |
1790 | } |
1791 | |
1792 | status = initiate_meshGeomDataStruct(geomData); |
1793 | if (status != CAPS_SUCCESS0) goto cleanup; |
1794 | |
1795 | geomData->type = ptype[i]; |
1796 | geomData->topoIndex = pindex[i]; |
1797 | |
1798 | // Want the face index to be set for topoIndex |
1799 | if (geomData->topoIndex < 0) geomData->topoIndex = face+1; |
1800 | |
1801 | geomData->uv[0] = uv[2*i + 0]; |
1802 | geomData->uv[1] = uv[2*i + 1]; |
1803 | |
1804 | status = EG_evaluate(eref, geomData->uv, result); |
1805 | if (status != EGADS_SUCCESS0) goto cleanup; |
1806 | |
1807 | // dU |
1808 | geomData->firstDerivative[0] = result[3]; |
1809 | geomData->firstDerivative[1] = result[4]; |
1810 | geomData->firstDerivative[2] = result[5]; |
1811 | |
1812 | // dV |
1813 | geomData->firstDerivative[3] = result[6]; |
1814 | geomData->firstDerivative[4] = result[7]; |
1815 | geomData->firstDerivative[5] = result[8]; |
1816 | |
1817 | feaMesh->node[gID-1].geomData = geomData; |
1818 | } |
1819 | } |
1820 | } |
1821 | } |
1822 | |
1823 | loadIndex = CAPSMAGIC1234321; |
1824 | status = retrieve_CAPSLoadAttr(eref, &attrName); |
1825 | if (status == CAPS_SUCCESS0) { |
1826 | |
1827 | status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex); |
1828 | |
1829 | if (status != CAPS_SUCCESS0) { |
1830 | printf("Error: capsLoad name %s not found in attribute to index map\n", attrName); |
1831 | goto cleanup; |
1832 | } |
1833 | } |
1834 | |
1835 | feaData = (feaMeshDataStruct *) feaMesh->element[elem].analysisData; |
1836 | |
1837 | feaData->propertyID = attrIndex; |
1838 | feaData->attrIndex = attrIndex; |
1839 | feaData->coordID = coordSystemIndex; |
1840 | feaData->loadIndex = loadIndex; |
1841 | } |
1842 | |
1843 | } else if (feaMesh->meshType == VolumeMesh) { |
1844 | |
1845 | // Show warning statement |
1846 | printf("Warning - surface nodes are assumed to be packed sequentially in the volume\n"); |
1847 | |
1848 | // Loop through reference meshes |
1849 | for (body = 0; body < feaMesh->numReferenceMesh; body++) { |
1850 | printf("Setting FEA Data from reference mesh %d (of %d)\n", body+1, feaMesh->numReferenceMesh); |
1851 | |
1852 | // Get body from tessellation |
1853 | status = EG_statusTessBody(feaMesh->referenceMesh[body].egadsTess, &ebody, &dummy, &dummy); |
1854 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1854 , __func__, 0); goto cleanup; }; |
1855 | |
1856 | // Get number of Nodes, Edges, and Faces in ebody |
1857 | status = EG_getBodyTopos(ebody, NULL((void*)0), NODE20, &numNode, &enodes); |
1858 | if (status < EGADS_SUCCESS0) goto cleanup; |
1859 | AIM_NOTNULL(enodes, aimInfo, status){ if (enodes == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 1859, __func__, 1, "%s == NULL!", "enodes" ); goto cleanup; } }; |
1860 | |
1861 | status = EG_getBodyTopos(ebody, NULL((void*)0), EDGE21, &numEdge, &eedges); |
1862 | if (status != EGADS_SUCCESS0) goto cleanup; |
1863 | |
1864 | status = EG_getBodyTopos(ebody, NULL((void*)0), FACE23, &numFace, &efaces); |
1865 | if (status < EGADS_SUCCESS0) goto cleanup; |
1866 | |
1867 | // What type of BODY do we have? |
1868 | isNodeBody = aim_isNodeBody(ebody, xyzPoint); |
1869 | if (isNodeBody < EGADS_SUCCESS0) goto cleanup; |
1870 | |
1871 | // If body is just a single node |
1872 | if (isNodeBody == EGADS_SUCCESS0) { |
1873 | |
1874 | printf("NodeBody found, not currently supported for VolumeMesh!\n"); |
1875 | status = CAPS_BADVALUE-311; |
1876 | goto cleanup; |
1877 | |
1878 | } //NODEBODY IF |
1879 | |
1880 | // Fill up the Attributes for the nodes |
1881 | for (i = 0; i < feaMesh->referenceMesh[body].numNode; i++) { |
1882 | |
1883 | status = EG_getGlobal(feaMesh->referenceMesh[body].egadsTess, feaMesh->referenceMesh[body].node[i].nodeID, &pointType, &pointTopoIndex, xyzPoint); |
1884 | if (status != EGADS_SUCCESS0) goto cleanup; |
1885 | |
1886 | feaData = (feaMeshDataStruct *) feaMesh->node[i+nodeOffset].analysisData; |
1887 | |
1888 | status = fea_setFEADataPoint(efaces, eedges, enodes, |
1889 | attrMap, |
1890 | coordSystemMap, |
1891 | constraintMap, |
1892 | loadMap, |
1893 | transferMap, |
1894 | connectMap, |
1895 | responseMap, |
1896 | referenceMap, |
1897 | pointType, pointTopoIndex, |
1898 | feaData); // Set the feaData structure |
1899 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 1899 , __func__, 0); goto cleanup; }; |
1900 | } |
1901 | |
1902 | // Fill element information // |
1903 | |
1904 | // Determine the body type |
1905 | status = EG_getTopology(ebody, &eref, &oclass, &bodySubType, data, &nchild, &echilds, &senses); |
1906 | if (status != EGADS_SUCCESS0) goto cleanup; |
1907 | |
1908 | // Can only have "free" edges in wire bodies - Don't want to count the edges of the faces |
1909 | // as "free" edges |
1910 | if (bodySubType == WIREBODY6) { |
1911 | |
1912 | printf("WireBody found, not currently supported for VolumeMesh!\n"); |
1913 | status = CAPS_BADVALUE-311; |
1914 | goto cleanup; |
1915 | |
1916 | } //WIREBODY IF |
1917 | |
1918 | // Set tri and quad analysis data |
1919 | for (elem = 0; elem < feaMesh->referenceMesh[body].numElement; elem++) { |
1920 | |
1921 | if (feaMesh->referenceMesh[body].element[elem].elementType != Triangle && |
1922 | feaMesh->referenceMesh[body].element[elem].elementType != Triangle_6 && |
1923 | feaMesh->referenceMesh[body].element[elem].elementType != Quadrilateral && |
1924 | feaMesh->referenceMesh[body].element[elem].elementType != Quadrilateral_8) continue; |
1925 | |
1926 | // |
1927 | // attrIndex = feaMesh->referenceMesh[body].element[elem].markerID; |
1928 | // |
1929 | // // get the capsGroup attribute string value |
1930 | // status = get_mapAttrToIndexKeyword(attrMap, attrIndex, &attrName); |
1931 | // if (status != CAPS_SUCCESS) { |
1932 | // printf("\tError: capsGroup index '%d' not found in attribute to index map\n", attrIndex); |
1933 | // goto cleanup; |
1934 | // } |
1935 | // |
1936 | // status = get_mapAttrToIndexIndex(coordSystemMap, attrName, &coordSystemIndex); |
1937 | // if (status != CAPS_SUCCESS) coordSystemIndex = 0; |
1938 | |
1939 | // get the face index |
1940 | face = feaMesh->referenceMesh[body].element[elem].topoIndex; |
1941 | if (face < 1 || face > numFace) { |
1942 | printf("Error: Element '%d': Invalid face topological index: %d, [1-%d]\n", elem, face, numFace); |
1943 | status = CAPS_BADVALUE-311; |
1944 | goto cleanup; |
1945 | } |
1946 | |
1947 | loadIndex = CAPSMAGIC1234321; |
1948 | status = retrieve_CAPSLoadAttr(efaces[face-1], &attrName); |
1949 | if (status == CAPS_SUCCESS0) { |
1950 | |
1951 | status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex); |
1952 | |
1953 | if (status != CAPS_SUCCESS0) { |
1954 | printf("Error: capsLoad name %s not found in attribute to index map\n", attrName); |
1955 | goto cleanup; |
1956 | } |
1957 | } |
1958 | |
1959 | feaData = (feaMeshDataStruct *) feaMesh->element[elem+elementOffset].analysisData; |
1960 | |
1961 | //feaData->propertyID = attrIndex; DONT THINK WE WANT TO CHANGE THE PROPERTY TYPE |
1962 | // feaData->coordID = coordSystemIndex; DONT THINK WE WANT TO CHANGE THE Coordinate TYPE |
1963 | feaData->loadIndex = loadIndex; |
1964 | } |
1965 | |
1966 | nodeOffset += feaMesh->referenceMesh[body].numNode; |
1967 | elementOffset += feaMesh->referenceMesh[body].numElement; |
1968 | } |
1969 | |
1970 | } else { |
1971 | printf("Unknown meshType!\n"); |
1972 | status = CAPS_BADTYPE-306; |
1973 | goto cleanup; |
1974 | } |
1975 | |
1976 | status = CAPS_SUCCESS0; |
1977 | |
1978 | cleanup: |
1979 | if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_setAnalysisData, status = %d\n", status); |
1980 | |
1981 | EG_free(iwest ); |
1982 | EG_free(inorth); |
1983 | EG_free(ieast ); |
1984 | EG_free(isouth); |
1985 | EG_free(rpos ); |
1986 | EG_free(points ); |
1987 | |
1988 | EG_free(enodes); |
1989 | EG_free(eedges); |
1990 | EG_free(efaces); |
1991 | |
1992 | enodes = NULL((void*)0); |
1993 | eedges = NULL((void*)0); |
1994 | efaces = NULL((void*)0); |
1995 | |
1996 | return status; |
1997 | } |
1998 | |
1999 | // Set feaData for a given point index and topology index. Ego faces, edges, and nodes must be provided along with attribute maps |
2000 | int fea_setFEADataPoint(ego *faces, ego *edges, ego *nodes, |
2001 | mapAttrToIndexStruct *attrMap, |
2002 | /*@unused@*/ mapAttrToIndexStruct *coordSystemMap, |
2003 | mapAttrToIndexStruct *constraintMap, |
2004 | mapAttrToIndexStruct *loadMap, |
2005 | mapAttrToIndexStruct *transferMap, |
2006 | mapAttrToIndexStruct *connectMap, |
2007 | mapAttrToIndexStruct *responseMap, |
2008 | mapAttrToIndexStruct *referenceMap, |
2009 | int pointType, int pointTopoIndex, |
2010 | feaMeshDataStruct *feaData) { // Set the feaData structure |
2011 | |
2012 | int status; |
2013 | |
2014 | int coordID = 0; // Default coordinate id for mesh |
2015 | |
2016 | // Attributes |
2017 | const char *attrName; |
2018 | int constraintIndex=-1, loadIndex=-1, transferIndex=-1, connectIndex=-1; |
2019 | int connectLinkIndex=-1, attrIndex=-1, responseIndex=-1, referenceIndex=-1; //coordSystemIndex |
2020 | |
2021 | ego object; |
2022 | |
2023 | feaData->coordID = coordID; |
2024 | |
2025 | // Get attribute index on entity |
2026 | constraintIndex = CAPSMAGIC1234321; |
2027 | loadIndex = CAPSMAGIC1234321; |
2028 | transferIndex = CAPSMAGIC1234321; |
2029 | connectIndex = CAPSMAGIC1234321; |
2030 | connectLinkIndex = CAPSMAGIC1234321; |
2031 | responseIndex = CAPSMAGIC1234321; |
2032 | referenceIndex = CAPSMAGIC1234321; |
2033 | |
2034 | if (pointType == 0) { // Node |
2035 | |
2036 | object = nodes[pointTopoIndex-1]; |
2037 | |
2038 | } else if (pointType > 0 ) { // Edge |
2039 | |
2040 | object = edges[pointTopoIndex-1]; |
2041 | |
2042 | } else { // Face |
2043 | |
2044 | object = faces[pointTopoIndex-1]; |
2045 | |
2046 | } |
2047 | |
2048 | status = retrieve_CAPSGroupAttr(object, &attrName); |
2049 | if (status == CAPS_SUCCESS0) { |
2050 | status = get_mapAttrToIndexIndex(attrMap, attrName, &attrIndex); |
2051 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2052 | } |
2053 | |
2054 | status = retrieve_CAPSConstraintAttr(object, &attrName); |
2055 | if (status == CAPS_SUCCESS0) { |
2056 | status = get_mapAttrToIndexIndex(constraintMap, attrName, &constraintIndex); |
2057 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2058 | } |
2059 | |
2060 | status = retrieve_CAPSLoadAttr(object, &attrName); |
2061 | if (status == CAPS_SUCCESS0) { |
2062 | status = get_mapAttrToIndexIndex(loadMap, attrName, &loadIndex); |
2063 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2064 | } |
2065 | |
2066 | status = retrieve_CAPSBoundAttr(object, &attrName); |
2067 | if (status == CAPS_SUCCESS0) { |
2068 | status = get_mapAttrToIndexIndex(transferMap, attrName, &transferIndex); |
2069 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2070 | } |
2071 | |
2072 | if (connectMap != NULL((void*)0)) { |
2073 | status = retrieve_CAPSConnectAttr(object, &attrName); |
2074 | if (status == CAPS_SUCCESS0) { |
2075 | status = get_mapAttrToIndexIndex(connectMap, attrName, &connectIndex); |
2076 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2077 | } |
2078 | |
2079 | status = retrieve_CAPSConnectLinkAttr(object, &attrName); |
2080 | if (status == CAPS_SUCCESS0) { |
2081 | status = get_mapAttrToIndexIndex(connectMap, attrName, &connectLinkIndex); |
2082 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2083 | } |
2084 | } |
2085 | |
2086 | if (responseMap != NULL((void*)0)) { |
2087 | status = retrieve_CAPSResponseAttr(object, &attrName); |
2088 | if (status == CAPS_SUCCESS0) { |
2089 | status = get_mapAttrToIndexIndex(responseMap, attrName, &responseIndex); |
2090 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2091 | } |
2092 | } |
2093 | |
2094 | if (referenceMap != NULL((void*)0)) { |
2095 | status = retrieve_CAPSReferenceAttr(object, &attrName); |
2096 | if (status == CAPS_SUCCESS0) { |
2097 | status = get_mapAttrToIndexIndex(referenceMap, attrName, &referenceIndex); |
2098 | if (status != CAPS_SUCCESS0 && status != CAPS_NOTFOUND-303 && status != CAPS_NULLVALUE-307) goto cleanup; |
2099 | } |
2100 | } |
2101 | |
2102 | feaData->attrIndex = attrIndex; |
2103 | |
2104 | feaData->constraintIndex = constraintIndex; |
2105 | feaData->loadIndex = loadIndex; |
2106 | feaData->transferIndex = transferIndex; |
2107 | feaData->connectIndex = connectIndex; |
2108 | feaData->connectLinkIndex = connectLinkIndex; |
2109 | feaData->responseIndex = responseIndex; |
2110 | feaData->referenceIndex = referenceIndex; |
2111 | |
2112 | status = CAPS_SUCCESS0; |
2113 | goto cleanup; |
2114 | |
2115 | cleanup: |
2116 | |
2117 | if (status != CAPS_SUCCESS0) printf("Error: Premature exit in fea_setFEADataPoint, status %d\n", status); |
2118 | |
2119 | return status; |
2120 | } |
2121 | |
2122 | // Initiate (0 out all values and NULL all pointers) of feaProperty in the feaPropertyStruct structure format |
2123 | int initiate_feaPropertyStruct(feaPropertyStruct *feaProperty) { |
2124 | int i; |
2125 | |
2126 | feaProperty->name = NULL((void*)0); |
2127 | |
2128 | feaProperty->propertyType = UnknownProperty; |
2129 | |
2130 | feaProperty->propertyID = 0; // ID number of property |
2131 | |
2132 | feaProperty->materialID = 0; // ID number of material |
2133 | feaProperty->materialName = NULL((void*)0); // Name of material associated with material ID |
2134 | |
2135 | // Rods |
2136 | feaProperty->crossSecArea = 0.0; // Bar cross-sectional area |
2137 | feaProperty->torsionalConst = 0.0; // Torsional constant |
2138 | feaProperty->torsionalStressReCoeff = 0.0; // Torsional stress recovery coefficient |
2139 | feaProperty->massPerLength = 0.0; // Mass per unit length |
2140 | |
2141 | // Bar - see rod for additional variables |
2142 | feaProperty->zAxisInertia = 0.0; // Section moment of inertia about the z axis |
2143 | feaProperty->yAxisInertia = 0.0; // Section moment of inertia about the y axis |
2144 | |
2145 | feaProperty->yCoords[0] = 0.0; // Element y, z coordinates, in the bar cross-section, of |
2146 | feaProperty->yCoords[1] = 0.0; // of four points at which to recover stresses |
2147 | feaProperty->yCoords[2] = 0.0; |
2148 | feaProperty->yCoords[3] = 0.0; |
2149 | |
2150 | feaProperty->zCoords[0] = 0.0; |
2151 | feaProperty->zCoords[1] = 0.0; |
2152 | feaProperty->zCoords[2] = 0.0; |
2153 | feaProperty->zCoords[3] = 0.0; |
2154 | |
2155 | feaProperty->areaShearFactors[0] = 0.0; // Area factors for shear |
2156 | feaProperty->areaShearFactors[1] = 0.0; |
2157 | |
2158 | feaProperty->crossProductInertia = 0.0; // Section cross-product of inertia |
2159 | |
2160 | feaProperty->crossSecType = NULL((void*)0); // Type of cross sections |
2161 | for (i = 0; i < 10; i++) feaProperty->crossSecDimension[i] = 0.0; // Dimensions |
2162 | |
2163 | feaProperty->orientationVec[0] = 0.0; // Orientation vector |
2164 | feaProperty->orientationVec[1] = 0.0; |
2165 | feaProperty->orientationVec[2] = 0.0; |
2166 | |
2167 | // Shear |
2168 | |
2169 | // Shell |
2170 | feaProperty->membraneThickness = 0.0; // Membrane thickness |
2171 | feaProperty->materialBendingID = 0; /// ID number of material for bending - if not specified and bendingInertiaRatio > 0 this value defaults to materialID |
2172 | feaProperty->bendingInertiaRatio = 1.0; // Ratio of actual bending moment inertia (I) to bending inertia of a solid |
2173 | // plate of thickness TM Real - default 1.0 |
2174 | feaProperty->materialShearID = 0; // ID number of material for shear - if not specified and shearMembraneRatio > 0 this value defaults to materialID |
2175 | feaProperty->shearMembraneRatio = 5.0/6.0; // Ratio of shear to membrane thickness - default 5/6 |
2176 | feaProperty->massPerArea = 0.0; // Mass per unit area |
2177 | //feaProperty->neutralPlaneDist[0] = 0; // Distances from the neutral plane of the plate to locations where |
2178 | //feaProperty->neutralPlaneDist[1] = 0; // stress is calculate |
2179 | |
2180 | feaProperty->zOffsetRel = 0.0; // Offset from the surface of grid points to the element reference plane |
2181 | |
2182 | feaProperty->compositeShearBondAllowable = 0.0; // Shear stress limit for bonding between plies |
2183 | feaProperty->compositeFailureTheory = NULL((void*)0); // HILL, HOFF, TSAI, STRN |
2184 | feaProperty->compositeSymmetricLaminate = (int) false0; // 1- SYM only half the plies are specified, for odd number plies 1/2 thickness of center ply is specified |
2185 | // the first ply is the bottom ply in the stack, default (0) all plies specified |
2186 | feaProperty->numPly = 0; |
2187 | feaProperty->compositeMaterialID = NULL((void*)0); // Vector of material ID's from bottom to top for all plies |
2188 | feaProperty->compositeThickness = NULL((void*)0); // Vector of thicknesses from bottom to top for all plies |
2189 | feaProperty->compositeOrientation = NULL((void*)0); // Vector of orientations from bottom to top for all plies |
2190 | |
2191 | // Solid |
2192 | |
2193 | // Concentrated Mass |
2194 | feaProperty->mass = 0.0; // Mass value |
2195 | feaProperty->massOffset[0] = 0.0; // Offset distance from the grid point to the center of gravity |
2196 | feaProperty->massOffset[1] = 0.0; |
2197 | feaProperty->massOffset[2] = 0.0; |
2198 | feaProperty->massInertia[0] = 0.0; // Mass moment of inertia measured at the mass center of gravity |
2199 | feaProperty->massInertia[1] = 0.0; |
2200 | feaProperty->massInertia[2] = 0.0; |
2201 | feaProperty->massInertia[3] = 0.0; |
2202 | feaProperty->massInertia[4] = 0.0; |
2203 | feaProperty->massInertia[5] = 0.0; |
2204 | |
2205 | return CAPS_SUCCESS0; |
2206 | } |
2207 | |
2208 | // Destroy (0 out all values and NULL all pointers) of feaProperty in the feaPropertyStruct structure format |
2209 | int destroy_feaPropertyStruct(feaPropertyStruct *feaProperty) { |
2210 | |
2211 | int i; |
2212 | |
2213 | if (feaProperty->name != NULL((void*)0)) EG_free(feaProperty->name); |
2214 | |
2215 | feaProperty->propertyType = UnknownProperty; |
2216 | |
2217 | feaProperty->propertyID = 0; // ID number of property |
2218 | |
2219 | feaProperty->materialID = 0; // ID number of material |
2220 | |
2221 | if (feaProperty->materialName != NULL((void*)0)) EG_free(feaProperty->materialName); // Name of material associated with material ID |
2222 | feaProperty->materialName = NULL((void*)0); |
2223 | |
2224 | // Rods |
2225 | feaProperty->crossSecArea = 0; // Bar cross-sectional area |
2226 | feaProperty->torsionalConst = 0; // Torsional constant |
2227 | feaProperty->torsionalStressReCoeff = 0; // Torsional stress recovery coefficient |
2228 | feaProperty->massPerLength = 0; // Mass per unit length |
2229 | |
2230 | // Bar - see rod for additional variables |
2231 | feaProperty->zAxisInertia = 0; // Section moment of inertia about the z axis |
2232 | feaProperty->yAxisInertia = 0; // Section moment of inertia about the y axis |
2233 | |
2234 | feaProperty->yCoords[0] = 0; // Element y, z coordinates, in the bar cross-section, of |
2235 | feaProperty->yCoords[1] = 0; // of four points at which to recover stresses |
2236 | feaProperty->yCoords[2] = 0; |
2237 | feaProperty->yCoords[3] = 0; |
2238 | |
2239 | feaProperty->zCoords[0] = 0; |
2240 | feaProperty->zCoords[1] = 0; |
2241 | feaProperty->zCoords[2] = 0; |
2242 | feaProperty->zCoords[3] = 0; |
2243 | |
2244 | feaProperty->areaShearFactors[0] = 0; // Area factors for shear |
2245 | feaProperty->areaShearFactors[1] = 0; |
2246 | |
2247 | feaProperty->crossProductInertia = 0; // Section cross-product of inertia |
2248 | |
2249 | if (feaProperty->crossSecType != NULL((void*)0)) EG_free(feaProperty->crossSecType); |
2250 | feaProperty->crossSecType = NULL((void*)0); // Type of cross sections |
2251 | for (i = 0; i < 10; i++) feaProperty->crossSecDimension[i] = 0.0; // Dimensions |
2252 | |
2253 | feaProperty->orientationVec[0] = 0.0; // Orientation vector |
2254 | feaProperty->orientationVec[1] = 0.0; |
2255 | feaProperty->orientationVec[2] = 0.0; |
2256 | |
2257 | // Shear |
2258 | |
2259 | // Shell |
2260 | feaProperty->membraneThickness = 0; // Membrane thickness |
2261 | feaProperty->materialBendingID = 0; // ID number of material for bending |
2262 | feaProperty->bendingInertiaRatio = 1.0; // Ratio of actual bending moment inertia (I) to bending inertia of a solid |
2263 | // plate of thickness TM Real - default 1.0 |
2264 | feaProperty->materialShearID = 0; // ID number of material for shear |
2265 | feaProperty->shearMembraneRatio = 5.0/6.0; // Ratio of shear to membrane thickness - default 5/6 |
2266 | feaProperty->massPerArea = 0; // Mass per unit area |
2267 | //feaProperty->neutralPlaneDist[0] = 0; // Distances from the neutral plane of the plate to locations where |
2268 | //feaProperty->neutralPlaneDist[1] = 0; // stress is calculate |
2269 | |
2270 | feaProperty->zOffsetRel = 0.0; // Offset from the surface of grid points to the element reference plane |
2271 | |
2272 | feaProperty->numPly = 0; |
2273 | feaProperty->compositeShearBondAllowable = 0.0; // Shear stress limit for bonding between plies |
2274 | if (feaProperty->compositeFailureTheory != NULL((void*)0)) EG_free(feaProperty->compositeFailureTheory); // HILL, HOFF, TSAI, STRN |
2275 | feaProperty->compositeFailureTheory = NULL((void*)0); |
2276 | feaProperty->compositeSymmetricLaminate = (int) false0; // 1- SYM only half the plies are specified, for odd number plies 1/2 thickness of center ply is specified |
2277 | // the first ply is the bottom ply in the stack, default (0) all plies specified |
2278 | if (feaProperty->compositeMaterialID != NULL((void*)0)) EG_free(feaProperty->compositeMaterialID); |
2279 | if (feaProperty->compositeThickness != NULL((void*)0)) EG_free(feaProperty->compositeThickness); |
2280 | if (feaProperty->compositeOrientation != NULL((void*)0)) EG_free(feaProperty->compositeOrientation); |
2281 | |
2282 | feaProperty->compositeMaterialID = NULL((void*)0); |
2283 | feaProperty->compositeThickness = NULL((void*)0); |
2284 | feaProperty->compositeOrientation = NULL((void*)0); |
2285 | |
2286 | // Solid |
2287 | |
2288 | // Concentrated Mass |
2289 | feaProperty->mass = 0.0; // Mass value |
2290 | feaProperty->massOffset[0] = 0.0; // Offset distance from the grid point to the center of gravity |
2291 | feaProperty->massOffset[1] = 0.0; |
2292 | feaProperty->massOffset[2] = 0.0; |
2293 | feaProperty->massInertia[0] = 0.0; // Mass moment of inertia measured at the mass center of gravity |
2294 | feaProperty->massInertia[1] = 0.0; |
2295 | feaProperty->massInertia[2] = 0.0; |
2296 | feaProperty->massInertia[3] = 0.0; |
2297 | feaProperty->massInertia[4] = 0.0; |
2298 | feaProperty->massInertia[5] = 0.0; |
2299 | |
2300 | return CAPS_SUCCESS0; |
2301 | } |
2302 | |
2303 | // Initiate (0 out all values and NULL all pointers) of feaMaterial in the feaMaterialStruct structure format |
2304 | int initiate_feaMaterialStruct(feaMaterialStruct *feaMaterial) { |
2305 | |
2306 | feaMaterial->name = NULL((void*)0); // Material name |
2307 | |
2308 | feaMaterial->materialType = UnknownMaterial; // Set |
2309 | |
2310 | feaMaterial->materialID = 0; // ID number of material |
2311 | |
2312 | feaMaterial->youngModulus = 0.0; // E - Young's Modulus |
2313 | feaMaterial->shearModulus = 0.0; // G - Shear Modulus |
2314 | feaMaterial->poissonRatio = 0.0; // Poisson's Ratio |
2315 | feaMaterial->density = 0.0; // Rho - material mass density |
2316 | feaMaterial->thermalExpCoeff = 0.0; //Coefficient of thermal expansion |
2317 | feaMaterial->temperatureRef = 0.0; // Reference temperature |
2318 | feaMaterial->dampingCoeff = 0.0; // Damping coefficient |
2319 | feaMaterial->tensionAllow = 0.0; // Tension allowable for the material |
2320 | feaMaterial->compressAllow = 0.0; // Compression allowable for the material |
2321 | feaMaterial->shearAllow = 0.0; // Shear allowable for the material |
2322 | |
2323 | feaMaterial->youngModulusLateral = 0.0; // Young's Modulus in the lateral direction |
2324 | feaMaterial->shearModulusTrans1Z = 0.0; // Transverse shear modulus in the 1-Z plane |
2325 | feaMaterial->shearModulusTrans2Z = 0.0; // Transverse shear modulus in the 2-Z plane |
2326 | feaMaterial->tensionAllowLateral = 0.0; // Tension allowable for the material |
2327 | feaMaterial->compressAllowLateral = 0.0; // Compression allowable for the material |
2328 | feaMaterial->thermalExpCoeffLateral = 0.0; //Coefficient of thermal expansion |
2329 | feaMaterial->allowType = 0; |
2330 | |
2331 | feaMaterial->specificHeat = 0; |
2332 | feaMaterial->kappa = 0; |
2333 | |
2334 | return CAPS_SUCCESS0; |
2335 | } |
2336 | |
2337 | // Destroy (0 out all values and NULL all pointers) of feaMaterial in the feaMaterialStruct structure format |
2338 | int destroy_feaMaterialStruct(feaMaterialStruct *feaMaterial) { |
2339 | |
2340 | if (feaMaterial->name != NULL((void*)0)) EG_free(feaMaterial->name); |
2341 | feaMaterial->name = NULL((void*)0); // Material name |
2342 | |
2343 | feaMaterial->materialType = UnknownMaterial; // Material type |
2344 | |
2345 | feaMaterial->materialID = 0; // ID number of material |
2346 | |
2347 | feaMaterial->youngModulus = 0.0; // E - Young's Modulus |
2348 | feaMaterial->shearModulus = 0.0; // G - Shear Modulus |
2349 | feaMaterial->poissonRatio = 0.0; // Poisson's Ratio |
2350 | feaMaterial->density = 0.0; // Rho - material mass density |
2351 | feaMaterial->thermalExpCoeff = 0.0; //Coefficient of thermal expansion |
2352 | feaMaterial->temperatureRef = 0.0; // Reference temperature |
2353 | feaMaterial->dampingCoeff = 0.0; // Damping coefficient |
2354 | feaMaterial->tensionAllow = 0.0; // Tension allowable for the material |
2355 | feaMaterial->compressAllow = 0.0; // Compression allowable for the material |
2356 | feaMaterial->shearAllow = 0.0; // Shear allowable for the material |
2357 | |
2358 | feaMaterial->youngModulusLateral = 0.0; // Young's Modulus in the lateral direction |
2359 | feaMaterial->shearModulusTrans1Z = 0.0; // Transverse shear modulus in the 1-Z plane |
2360 | feaMaterial->shearModulusTrans2Z = 0.0; // Transverse shear modulus in the 2-Z plane |
2361 | feaMaterial->tensionAllowLateral = 0.0; // Tension allowable for the material |
2362 | feaMaterial->compressAllowLateral = 0.0; // Compression allowable for the material |
2363 | feaMaterial->thermalExpCoeffLateral = 0.0; //Coefficient of thermal expansion |
2364 | feaMaterial->allowType = 0; |
2365 | |
2366 | feaMaterial->specificHeat = 0; |
2367 | feaMaterial->kappa = 0; |
2368 | |
2369 | return CAPS_SUCCESS0; |
2370 | } |
2371 | |
2372 | // Initiate (0 out all values and NULL all pointers) of feaUnits in the feaUnitsStruct structure format |
2373 | int initiate_feaUnitsStruct(feaUnitsStruct *feaUnits) { |
2374 | |
2375 | feaUnits->densityVol = NULL((void*)0); |
2376 | feaUnits->densityArea = NULL((void*)0); |
2377 | feaUnits->mass = NULL((void*)0); |
2378 | feaUnits->length = NULL((void*)0); |
2379 | feaUnits->pressure = NULL((void*)0); |
2380 | feaUnits->temperature = NULL((void*)0); |
2381 | feaUnits->momentOfInertia = NULL((void*)0); |
2382 | |
2383 | return CAPS_SUCCESS0; |
2384 | } |
2385 | |
2386 | // Destroy (0 out all values and NULL all pointers) of feaUnits in the feaUnitsStruct structure format |
2387 | int destroy_feaUnitsStruct(feaUnitsStruct *feaUnits) { |
2388 | |
2389 | AIM_FREE(feaUnits->densityVol){ EG_free(feaUnits->densityVol); feaUnits->densityVol = ((void*)0); }; |
2390 | AIM_FREE(feaUnits->densityArea){ EG_free(feaUnits->densityArea); feaUnits->densityArea = ((void*)0); }; |
2391 | AIM_FREE(feaUnits->mass){ EG_free(feaUnits->mass); feaUnits->mass = ((void*)0); }; |
2392 | AIM_FREE(feaUnits->length){ EG_free(feaUnits->length); feaUnits->length = ((void* )0); }; |
2393 | AIM_FREE(feaUnits->pressure){ EG_free(feaUnits->pressure); feaUnits->pressure = ((void *)0); }; |
2394 | AIM_FREE(feaUnits->temperature){ EG_free(feaUnits->temperature); feaUnits->temperature = ((void*)0); }; |
2395 | AIM_FREE(feaUnits->momentOfInertia){ EG_free(feaUnits->momentOfInertia); feaUnits->momentOfInertia = ((void*)0); }; |
2396 | |
2397 | return CAPS_SUCCESS0; |
2398 | } |
2399 | |
2400 | // Initiate (0 out all values and NULL all pointers) of feaConstraint in the feaConstraintStruct structure format |
2401 | int initiate_feaConstraintStruct(feaConstraintStruct *feaConstraint) { |
2402 | |
2403 | feaConstraint->name = NULL((void*)0); // Constraint name |
2404 | |
2405 | feaConstraint->constraintType = UnknownConstraint; // Constraint type |
2406 | |
2407 | feaConstraint->constraintID = 0; // ID number of constraint |
2408 | |
2409 | feaConstraint->numGridID = 0; // Component number of grid |
2410 | feaConstraint->gridIDSet = NULL((void*)0); // List of component number of grids to apply constraint to |
2411 | |
2412 | feaConstraint->dofConstraint = 0; // Number to indicate DOF constraints |
2413 | feaConstraint->gridDisplacement = 0; |
2414 | |
2415 | return CAPS_SUCCESS0; |
2416 | } |
2417 | |
2418 | // Destroy (0 out all values and NULL all pointers) of feaConstraint in the feaConstraintStruct structure format |
2419 | int destroy_feaConstraintStruct(feaConstraintStruct *feaConstraint) { |
2420 | |
2421 | if (feaConstraint->name != NULL((void*)0)) EG_free(feaConstraint->name); |
2422 | feaConstraint->name = NULL((void*)0); // Constraint name |
2423 | |
2424 | feaConstraint->constraintType = UnknownConstraint; // Constraint type |
2425 | |
2426 | feaConstraint->constraintID = 0; // ID number of constraint |
2427 | |
2428 | feaConstraint->numGridID = 0; // Number of grid IDs in grid ID set |
2429 | |
2430 | if (feaConstraint->gridIDSet != NULL((void*)0)) EG_free(feaConstraint->gridIDSet); // List of component number of grids to apply constraint to |
2431 | |
2432 | feaConstraint->dofConstraint = 0; // Number to indicate DOF constraints |
2433 | feaConstraint->gridDisplacement = 0; // The value for the displacement |
2434 | |
2435 | return CAPS_SUCCESS0; |
2436 | } |
2437 | |
2438 | // Initiate (0 out all values and NULL all pointers) of feaSupport in the feaSupportStruct structure format |
2439 | int initiate_feaSupportStruct(feaSupportStruct *feaSupport) { |
2440 | |
2441 | feaSupport->name = NULL((void*)0); // Support name |
2442 | |
2443 | feaSupport->supportID = 0; // ID number of support |
2444 | |
2445 | feaSupport->numGridID = 0; // Component number of grid |
2446 | feaSupport->gridIDSet = NULL((void*)0); // List of component number of grids to apply support to |
2447 | |
2448 | feaSupport->dofSupport = 0; // Number to indicate DOF supports |
2449 | |
2450 | return CAPS_SUCCESS0; |
2451 | } |
2452 | |
2453 | // Destroy (0 out all values and NULL all pointers) of feaSupport in the feaSupportStruct structure format |
2454 | int destroy_feaSupportStruct(feaSupportStruct *feaSupport) { |
2455 | |
2456 | if (feaSupport->name != NULL((void*)0)) EG_free(feaSupport->name); |
2457 | feaSupport->name = NULL((void*)0); // Support name |
2458 | |
2459 | feaSupport->supportID = 0; // ID number of support |
2460 | |
2461 | feaSupport->numGridID = 0; // Number of grid IDs in grid ID set |
2462 | |
2463 | if (feaSupport->gridIDSet != NULL((void*)0)) EG_free(feaSupport->gridIDSet); // List of component number of grids to apply support to |
2464 | |
2465 | feaSupport->dofSupport = 0; // Number to indicate DOF supports |
2466 | |
2467 | return CAPS_SUCCESS0; |
2468 | } |
2469 | |
2470 | // Initiate (0 out all values and NULL all pointers) of feaAnalysis in the feaAnalysisStruct structure format |
2471 | int initiate_feaAnalysisStruct(feaAnalysisStruct *feaAnalysis) { |
2472 | |
2473 | feaAnalysis->name = NULL((void*)0); // Analysis name |
2474 | |
2475 | feaAnalysis->analysisType = UnknownAnalysis; // Type of analysis |
2476 | |
2477 | feaAnalysis->analysisID = 0; // ID number of analysis |
2478 | |
2479 | // Loads for the analysis |
2480 | feaAnalysis->numLoad = 0; // Number of loads in the analysis |
2481 | feaAnalysis->loadSetID = NULL((void*)0); // List of the load IDSs |
2482 | |
2483 | // Constraints for the analysis |
2484 | feaAnalysis->numConstraint = 0; // Number of constraints in the analysis |
2485 | feaAnalysis->constraintSetID = NULL((void*)0); // List of constraint IDs |
2486 | |
2487 | // Supports for the analysis |
2488 | feaAnalysis->numSupport = 0; // Number of supports in the analysis |
2489 | feaAnalysis->supportSetID = NULL((void*)0); // List of support IDs |
2490 | |
2491 | // Optimization constraints |
2492 | feaAnalysis->numDesignConstraint = 0; // Number of design constraints |
2493 | feaAnalysis->designConstraintSetID = NULL((void*)0); // List of design constraint IDs |
2494 | |
2495 | // Optimization responses |
2496 | feaAnalysis->numDesignResponse = 0; // Number of design responses |
2497 | feaAnalysis->designResponseSetID = NULL((void*)0); // List of design response IDs |
2498 | |
2499 | // Eigenvalue |
2500 | feaAnalysis->extractionMethod = NULL((void*)0); |
2501 | |
2502 | feaAnalysis->frequencyRange[0] = 0; |
2503 | feaAnalysis->frequencyRange[1] = 0; |
2504 | |
2505 | feaAnalysis->numEstEigenvalue = 0; |
2506 | feaAnalysis->numDesiredEigenvalue = 0; |
2507 | feaAnalysis->eigenNormaliztion = NULL((void*)0); |
2508 | |
2509 | feaAnalysis->gridNormaliztion = 0; |
2510 | feaAnalysis->componentNormaliztion = 0; |
2511 | |
2512 | feaAnalysis->lanczosMode = 2; //Lanczos mode for calculating eigenvalues |
2513 | feaAnalysis->lanczosType = NULL((void*)0); //Lanczos matrix type (DPB, DGB) |
2514 | |
2515 | // Trim |
2516 | feaAnalysis->numMachNumber = 0; |
2517 | feaAnalysis->machNumber = NULL((void*)0); // Mach number |
2518 | feaAnalysis->dynamicPressure = 0.0; // Dynamic pressure |
2519 | feaAnalysis->density = 0.0; // Density |
2520 | feaAnalysis->aeroSymmetryXY = NULL((void*)0); |
2521 | feaAnalysis->aeroSymmetryXZ = NULL((void*)0); |
2522 | |
2523 | feaAnalysis->numRigidVariable = 0; // Number of rigid trim variables |
2524 | feaAnalysis->rigidVariable = NULL((void*)0); // List of character labels identifying rigid trim variables, size=[numRigidVariables] |
2525 | |
2526 | feaAnalysis->numRigidConstraint = 0; // Number of rigid trim constrained variables |
2527 | feaAnalysis->rigidConstraint = NULL((void*)0); // List of character labels identifying rigid constrained trim variables, size=[numRigidConstraint] |
2528 | feaAnalysis->magRigidConstraint = NULL((void*)0); // Magnitude of rigid constrained trim variables, size=[numRigidConstraint] |
2529 | |
2530 | feaAnalysis->numControlConstraint = 0; // Number of control surface constrained variables |
2531 | feaAnalysis->controlConstraint = NULL((void*)0); // List of character labels identifying control surfaces to be constrained trim variables, size=[numControlConstraint] |
2532 | feaAnalysis->magControlConstraint = NULL((void*)0); // Magnitude of control surface constrained variables, size=[numControlConstraint] |
2533 | |
2534 | // Flutter |
2535 | feaAnalysis->numReducedFreq = 0; |
2536 | feaAnalysis->reducedFreq = NULL((void*)0); |
2537 | |
2538 | feaAnalysis->numFlutterVel = 0; |
2539 | feaAnalysis->flutterVel = NULL((void*)0); |
2540 | |
2541 | feaAnalysis->flutterConvergenceParam = 0.0; |
2542 | |
2543 | feaAnalysis->visualFlutter = (int) false0; |
2544 | |
2545 | return CAPS_SUCCESS0; |
2546 | } |
2547 | |
2548 | // Destroy (0 out all values and NULL all pointers) of feaAnalysis in the feaAnalysisStruct structure format |
2549 | int destroy_feaAnalysisStruct(feaAnalysisStruct *feaAnalysis) { |
2550 | int status; // Function return status |
2551 | |
2552 | if (feaAnalysis->name != NULL((void*)0)) EG_free(feaAnalysis->name); |
2553 | feaAnalysis->name = NULL((void*)0); // Analysis name |
2554 | |
2555 | feaAnalysis->analysisType = UnknownAnalysis; // Type of analysis |
2556 | |
2557 | feaAnalysis->analysisID = 0; // ID number of analysis |
2558 | |
2559 | // Loads for the analysis |
2560 | feaAnalysis->numLoad = 0; // Number of loads in the analysis |
2561 | if(feaAnalysis->loadSetID != NULL((void*)0)) EG_free(feaAnalysis->loadSetID); |
2562 | feaAnalysis->loadSetID = NULL((void*)0); // List of the load IDSs |
2563 | |
2564 | // Constraints for the analysis |
2565 | feaAnalysis->numConstraint = 0; // Number of constraints in the analysis |
2566 | if (feaAnalysis->constraintSetID != NULL((void*)0)) EG_free(feaAnalysis->constraintSetID); |
2567 | feaAnalysis->constraintSetID = NULL((void*)0); // List of constraint IDs |
2568 | |
2569 | // Supports for the analysis |
2570 | feaAnalysis->numSupport = 0; // Number of supports in the analysis |
2571 | if (feaAnalysis->supportSetID != NULL((void*)0)) EG_free(feaAnalysis->supportSetID); |
2572 | feaAnalysis->supportSetID = NULL((void*)0); // List of support IDs |
2573 | |
2574 | // Optimization constraints |
2575 | feaAnalysis->numDesignConstraint = 0; // Number of design constraints |
2576 | if (feaAnalysis->designConstraintSetID != NULL((void*)0)) EG_free(feaAnalysis->designConstraintSetID); |
2577 | feaAnalysis->designConstraintSetID = NULL((void*)0); // List of design constraint IDs |
2578 | |
2579 | // Optimization responses |
2580 | feaAnalysis->numDesignResponse = 0; // Number of design responses |
2581 | if (feaAnalysis->designResponseSetID != NULL((void*)0)) EG_free(feaAnalysis->designResponseSetID); |
2582 | feaAnalysis->designResponseSetID = NULL((void*)0); // List of design response IDs |
2583 | |
2584 | // Eigenvalue |
2585 | if (feaAnalysis->extractionMethod != NULL((void*)0)) EG_free(feaAnalysis->extractionMethod); |
2586 | feaAnalysis->extractionMethod = NULL((void*)0); |
2587 | |
2588 | feaAnalysis->frequencyRange[0] = 0; |
2589 | feaAnalysis->frequencyRange[1] = 0; |
2590 | |
2591 | feaAnalysis->numEstEigenvalue = 0; |
2592 | feaAnalysis->numDesiredEigenvalue = 0; |
2593 | |
2594 | if (feaAnalysis->eigenNormaliztion != NULL((void*)0)) EG_free(feaAnalysis->eigenNormaliztion); |
2595 | feaAnalysis->eigenNormaliztion = NULL((void*)0); |
2596 | |
2597 | feaAnalysis->gridNormaliztion = 0; |
2598 | feaAnalysis->componentNormaliztion = 0; |
2599 | |
2600 | feaAnalysis->lanczosMode = 2; //Lanczos mode for calculating eigenvalues |
2601 | |
2602 | if (feaAnalysis->lanczosType != NULL((void*)0)) EG_free(feaAnalysis->lanczosType); |
2603 | feaAnalysis->lanczosType = NULL((void*)0); //Lanczos matrix type (DPB, DGB) |
2604 | |
2605 | // Trim |
2606 | feaAnalysis->numMachNumber = 0; |
2607 | |
2608 | if (feaAnalysis->machNumber != NULL((void*)0)) EG_free(feaAnalysis->machNumber); |
2609 | feaAnalysis->machNumber = NULL((void*)0); // Mach number |
2610 | |
2611 | //feaAnalysis->machNumber = 0.0; // Mach number |
2612 | feaAnalysis->dynamicPressure = 0.0; // Dynamic pressure |
2613 | feaAnalysis->density = 0.0; // Density |
2614 | if (feaAnalysis->aeroSymmetryXY != NULL((void*)0)) EG_free(feaAnalysis->aeroSymmetryXY); |
2615 | if (feaAnalysis->aeroSymmetryXZ != NULL((void*)0)) EG_free(feaAnalysis->aeroSymmetryXZ); |
2616 | |
2617 | if (feaAnalysis->rigidVariable != NULL((void*)0)) { |
2618 | status = string_freeArray(feaAnalysis->numRigidVariable, &feaAnalysis->rigidVariable); |
2619 | if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status); |
2620 | } |
2621 | |
2622 | feaAnalysis->numRigidVariable = 0; // Number of trim rigid trim variables |
2623 | feaAnalysis->rigidVariable = NULL((void*)0); // List of character labels identifying rigid trim variables, size=[numRigidVariables] |
2624 | |
2625 | if (feaAnalysis->rigidConstraint != NULL((void*)0)) { |
2626 | status = string_freeArray(feaAnalysis->numRigidConstraint, &feaAnalysis->rigidConstraint); |
2627 | if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status); |
2628 | } |
2629 | |
2630 | feaAnalysis->numRigidConstraint = 0; // Number of rigid trim constrained variables |
2631 | feaAnalysis->rigidConstraint = NULL((void*)0); // List of character labels identifying rigid constrained trim variables, size=[numRigidConstraint] |
2632 | |
2633 | if (feaAnalysis->magRigidConstraint != NULL((void*)0)) EG_free(feaAnalysis->magRigidConstraint); |
2634 | feaAnalysis->magRigidConstraint = NULL((void*)0); // Magnitude of rigid constrained trim variables, size=[numRigidConstraint] |
2635 | |
2636 | if (feaAnalysis->controlConstraint != NULL((void*)0)) { |
2637 | status = string_freeArray(feaAnalysis->numControlConstraint, &feaAnalysis->controlConstraint); |
2638 | if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status); |
2639 | } |
2640 | |
2641 | feaAnalysis->numControlConstraint = 0; // Number of control surface constrained variables |
2642 | feaAnalysis->controlConstraint = NULL((void*)0); // List of character labels identifying control surfaces to be constrained trim variables, size=[numControlConstraint] |
2643 | |
2644 | EG_free(feaAnalysis->magControlConstraint); |
2645 | feaAnalysis->magControlConstraint = NULL((void*)0); // Magnitude of control surface constrained variables, size=[numControlConstraint] |
2646 | |
2647 | // Flutter |
2648 | feaAnalysis->numReducedFreq = 0; |
2649 | EG_free(feaAnalysis->reducedFreq); |
2650 | feaAnalysis->reducedFreq = NULL((void*)0); |
2651 | |
2652 | feaAnalysis->numFlutterVel = 0; |
2653 | EG_free(feaAnalysis->flutterVel); |
2654 | feaAnalysis->flutterVel = NULL((void*)0); |
2655 | |
2656 | feaAnalysis->flutterConvergenceParam = 0.0; |
2657 | |
2658 | feaAnalysis->visualFlutter = (int) false0; |
2659 | |
2660 | return CAPS_SUCCESS0; |
2661 | } |
2662 | |
2663 | // Initiate (0 out all values and NULL all pointers) of feaLoad in the feaLoadStruct structure format |
2664 | int initiate_feaLoadStruct(feaLoadStruct *feaLoad) { |
2665 | |
2666 | feaLoad->name = NULL((void*)0); // Load name |
2667 | |
2668 | feaLoad->loadType = UnknownLoad; // Load type |
2669 | |
2670 | feaLoad->loadID = 0; // ID number of load |
2671 | |
2672 | feaLoad->loadScaleFactor = 1; // Scale factor for when combining loads |
2673 | |
2674 | // Concentrated force at a grid point |
2675 | feaLoad->numGridID = 0; // Number of grid IDs in grid ID set |
2676 | feaLoad->gridIDSet = NULL((void*)0); // List of grid IDs to apply the constraint to. size = [numGridID] |
2677 | feaLoad->coordSystemID= 0; // Component number of coordinate system in which force vector is specified |
2678 | |
2679 | feaLoad->forceScaleFactor= 0.0; // Overall scale factor for the force |
2680 | feaLoad->directionVector[0] = 0.0; // [0]-x, [1]-y, [2]-z components of the force vector |
2681 | feaLoad->directionVector[1] = 0.0; |
2682 | feaLoad->directionVector[2] = 0.0; |
2683 | |
2684 | // Concentrated moment at a grid point (also uses coordSystemID and directionVector) |
2685 | feaLoad->momentScaleFactor= 0.0; // Overall scale factor for the moment |
2686 | |
2687 | // Gravitational load (also uses coordSystemID and directionVector) |
2688 | feaLoad->gravityAcceleration= 0.0; // Gravitational acceleration |
2689 | |
2690 | // Pressure load |
2691 | feaLoad->pressureForce= 0.0; // Pressure value |
2692 | feaLoad->pressureDistributeForce[0] = 0.0; // Pressure load at a specified grid location in the element |
2693 | feaLoad->pressureDistributeForce[1] = 0.0; |
2694 | feaLoad->pressureDistributeForce[2] = 0.0; |
2695 | feaLoad->pressureDistributeForce[3] = 0.0; |
2696 | |
2697 | feaLoad->pressureMultiDistributeForce = NULL((void*)0); // Unique pressure load at a specified grid location for |
2698 | // each element in elementIDSet size = [numElementID][4] - used in type PressureExternal |
2699 | // where the pressure force is being provided by an external source (i.e. data transfer) |
2700 | |
2701 | feaLoad->numElementID = 0; // Number of elements IDs in element ID set |
2702 | feaLoad->elementIDSet = NULL((void*)0); // List element IDs in which to apply the load. size = [numElementID] |
2703 | |
2704 | // Rotational velocity (also uses coordSystemID and directionVector) |
2705 | feaLoad->angularVelScaleFactor = 0.0; // Overall scale factor for the angular velocity |
2706 | feaLoad->angularAccScaleFactor = 0.0; // Overall scale factor for the angular acceleration |
2707 | |
2708 | // Thermal load - the temperature at a grid point - use gridIDSet |
2709 | feaLoad->temperature = 0.0; // Temperature value |
2710 | feaLoad->temperatureDefault = 0.0; // Default temperature of grid point explicitly not used |
2711 | |
2712 | feaLoad->temperatureMultiDistribute = NULL((void*)0); |
2713 | |
2714 | return CAPS_SUCCESS0; |
2715 | } |
2716 | |
2717 | // Copy feaLoad in the feaLoadStruct structure format |
2718 | // assumes that copy has been initialized with initiate_feaLoadStruct |
2719 | int copy_feaLoadStruct(void *aimInfo, feaLoadStruct *feaLoad, feaLoadStruct *copy) { |
2720 | |
2721 | int status = CAPS_SUCCESS0; |
2722 | int i; |
2723 | |
2724 | if (feaLoad->name != NULL((void*)0)) { |
2725 | AIM_STRDUP(copy->name, feaLoad->name, aimInfo, status){ if (copy->name != ((void*)0)) { status = -4; aim_status( aimInfo, status, "feaUtils.c", 2725, __func__, 1, "AIM_STRDUP: %s != NULL!" , "copy->name"); goto cleanup; } copy->name = EG_strdup (feaLoad->name); if (copy->name == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 2725, __func__ , 2, "AIM_STRDUP: %s %s", "copy->name", feaLoad->name); goto cleanup; } }; // Load name |
2726 | } |
2727 | |
2728 | copy->loadType = feaLoad->loadType; // Load type |
2729 | |
2730 | copy->loadID = feaLoad->loadID; // ID number of load |
2731 | |
2732 | copy->loadScaleFactor = feaLoad->loadScaleFactor; // Scale factor for when combining loads |
2733 | |
2734 | // Concentrated force at a grid point |
2735 | copy->numGridID = feaLoad->numGridID; // Number of grid IDs in grid ID set |
2736 | // List of grid IDs to apply the constraint to |
2737 | AIM_ALLOC(copy->gridIDSet, feaLoad->numGridID, int, aimInfo, status){ if (copy->gridIDSet != ((void*)0)) { status = -4; aim_status (aimInfo, status, "feaUtils.c", 2737, __func__, 1, "AIM_ALLOC: %s != NULL" , "copy->gridIDSet"); goto cleanup; } size_t memorysize = feaLoad ->numGridID; copy->gridIDSet = (int *) EG_alloc(memorysize *sizeof(int)); if (copy->gridIDSet == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 2737, __func__ , 3, "AIM_ALLOC: %s size %zu type %s", "copy->gridIDSet", memorysize , "int"); goto cleanup; } }; |
2738 | for (i = 0; i < feaLoad->numGridID; i++) |
2739 | copy->gridIDSet[i] = feaLoad->gridIDSet[i]; |
2740 | |
2741 | copy->coordSystemID = feaLoad->coordSystemID; // Component number of coordinate system in which force vector is specified |
2742 | copy->forceScaleFactor = feaLoad->forceScaleFactor; // Overall scale factor for the force |
2743 | copy->directionVector[0] = feaLoad->directionVector[0]; // [0]-x, [1]-y, [2]-z components of the force vector |
2744 | copy->directionVector[1] = feaLoad->directionVector[1]; |
2745 | copy->directionVector[2] = feaLoad->directionVector[2]; |
2746 | |
2747 | // Concentrated moment at a grid pofeaLoad->(also uses coordSystemID and directionVector) |
2748 | copy->momentScaleFactor = feaLoad->momentScaleFactor; // Overall scale factor for the moment |
2749 | |
2750 | // Gravitational load (also uses coordSystemID and directionVector) |
2751 | copy->gravityAcceleration = feaLoad->gravityAcceleration; // Gravitational acceleration |
2752 | |
2753 | // Pressure load |
2754 | copy->pressureForce = feaLoad->pressureForce; // Pressure value |
2755 | |
2756 | copy->pressureDistributeForce[0] = feaLoad->pressureDistributeForce[0]; // Pressure load at a specified grid location in the element |
2757 | copy->pressureDistributeForce[1] = feaLoad->pressureDistributeForce[1]; |
2758 | copy->pressureDistributeForce[2] = feaLoad->pressureDistributeForce[2]; |
2759 | copy->pressureDistributeForce[3] = feaLoad->pressureDistributeForce[3]; |
2760 | |
2761 | // Unique pressure load at a specified grid location for |
2762 | //each element in elementIDSet size = [4*numElementID]- used in type PressureExternal |
2763 | if (feaLoad->pressureMultiDistributeForce != NULL((void*)0)) { |
2764 | AIM_ALLOC(copy->pressureMultiDistributeForce, feaLoad->numElementID, double, aimInfo, status){ if (copy->pressureMultiDistributeForce != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 2764, __func__ , 1, "AIM_ALLOC: %s != NULL", "copy->pressureMultiDistributeForce" ); goto cleanup; } size_t memorysize = feaLoad->numElementID ; copy->pressureMultiDistributeForce = (double *) EG_alloc (memorysize*sizeof(double)); if (copy->pressureMultiDistributeForce == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 2764, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->pressureMultiDistributeForce" , memorysize, "double"); goto cleanup; } }; |
2765 | for (i = 0; i < 4*feaLoad->numElementID; i++) |
2766 | copy->pressureMultiDistributeForce[i] = feaLoad->pressureMultiDistributeForce[i]; |
2767 | } else { |
2768 | copy->pressureMultiDistributeForce = NULL((void*)0); |
2769 | } |
2770 | |
2771 | copy->numElementID = feaLoad->numElementID; // Number of elements IDs in element ID set |
2772 | AIM_ALLOC(copy->elementIDSet, feaLoad->numElementID, int, aimInfo, status){ if (copy->elementIDSet != ((void*)0)) { status = -4; aim_status (aimInfo, status, "feaUtils.c", 2772, __func__, 1, "AIM_ALLOC: %s != NULL" , "copy->elementIDSet"); goto cleanup; } size_t memorysize = feaLoad->numElementID; copy->elementIDSet = (int *) EG_alloc (memorysize*sizeof(int)); if (copy->elementIDSet == ((void *)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 2772, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->elementIDSet" , memorysize, "int"); goto cleanup; } }; // List element IDs in which to apply the load |
2773 | for (i = 0; i < feaLoad->numElementID; i++) |
2774 | copy->elementIDSet[i] = feaLoad->elementIDSet[i]; |
2775 | |
2776 | // Rotational velocity (also uses coordSystemID and directionVector) |
2777 | copy->angularVelScaleFactor = feaLoad->angularVelScaleFactor; // Overall scale factor for the angular velocity |
2778 | copy->angularAccScaleFactor = feaLoad->angularAccScaleFactor; // Overall scale factor for the angular acceleration |
2779 | |
2780 | // Thermal load - the temperature at a grid point - use gridIDSet |
2781 | copy->temperature = feaLoad->temperature; // Temperature value |
2782 | copy->temperatureDefault = feaLoad->temperatureDefault; // Default temperature of grid point explicitly not used |
2783 | |
2784 | if (feaLoad->temperatureMultiDistribute != NULL((void*)0)) { |
2785 | AIM_ALLOC(copy->temperatureMultiDistribute, feaLoad->numGridID, double, aimInfo, status){ if (copy->temperatureMultiDistribute != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 2785, __func__ , 1, "AIM_ALLOC: %s != NULL", "copy->temperatureMultiDistribute" ); goto cleanup; } size_t memorysize = feaLoad->numGridID; copy->temperatureMultiDistribute = (double *) EG_alloc(memorysize *sizeof(double)); if (copy->temperatureMultiDistribute == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 2785, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "copy->temperatureMultiDistribute" , memorysize, "double"); goto cleanup; } }; |
2786 | for (i = 0; i < feaLoad->numGridID; i++) |
2787 | copy->temperatureMultiDistribute[i] = feaLoad->temperatureMultiDistribute[i]; |
2788 | } else { |
2789 | copy->temperatureMultiDistribute = NULL((void*)0); |
2790 | } |
2791 | |
2792 | cleanup: |
2793 | return status; |
2794 | } |
2795 | |
2796 | // Destroy (0 out all values and NULL all pointers) of feaLoad in the feaLoadStruct structure format |
2797 | int destroy_feaLoadStruct(feaLoadStruct *feaLoad) { |
2798 | |
2799 | AIM_FREE(feaLoad->name){ EG_free(feaLoad->name); feaLoad->name = ((void*)0); }; // Load name |
2800 | |
2801 | feaLoad->loadType = UnknownLoad; // Load type |
2802 | |
2803 | feaLoad->loadID = 0; // ID number of load |
2804 | |
2805 | feaLoad->loadScaleFactor = 1; // Scale factor for when combining loads |
2806 | |
2807 | // Concentrated force at a grid point |
2808 | feaLoad->numGridID = 0; // Number of grid IDs in grid ID set |
2809 | AIM_FREE(feaLoad->gridIDSet){ EG_free(feaLoad->gridIDSet); feaLoad->gridIDSet = ((void *)0); }; // List of grid IDs to apply the constraint to |
2810 | |
2811 | feaLoad->coordSystemID= 0; // Component number of coordinate system in which force vector is specified |
2812 | feaLoad->forceScaleFactor= 0; // Overall scale factor for the force |
2813 | feaLoad->directionVector[0] = 0; // [0]-x, [1]-y, [2]-z components of the force vector |
2814 | feaLoad->directionVector[1] = 0; |
2815 | feaLoad->directionVector[2] = 0; |
2816 | |
2817 | // Concentrated moment at a grid pofeaLoad->(also uses coordSystemID and directionVector) |
2818 | feaLoad->momentScaleFactor= 0; // Overall scale factor for the moment |
2819 | |
2820 | // Gravitational load (also uses coordSystemID and directionVector) |
2821 | feaLoad->gravityAcceleration= 0; // Gravitational acceleration |
2822 | |
2823 | // Pressure load |
2824 | feaLoad->pressureForce= 0; // Pressure value |
2825 | |
2826 | feaLoad->pressureDistributeForce[0] = 0; // Pressure load at a specified grid location in the element |
2827 | feaLoad->pressureDistributeForce[1] = 0; |
2828 | feaLoad->pressureDistributeForce[2] = 0; |
2829 | feaLoad->pressureDistributeForce[3] = 0; |
2830 | |
2831 | // Unique pressure load at a specified grid location for |
2832 | //each element in elementIDSet size = [4*numElementID]- used in type PressureExternal |
2833 | AIM_FREE(feaLoad->pressureMultiDistributeForce){ EG_free(feaLoad->pressureMultiDistributeForce); feaLoad-> pressureMultiDistributeForce = ((void*)0); }; |
2834 | |
2835 | |
2836 | feaLoad->numElementID = 0; // Number of elements IDs in element ID set |
2837 | AIM_FREE(feaLoad->elementIDSet){ EG_free(feaLoad->elementIDSet); feaLoad->elementIDSet = ((void*)0); }; // List element IDs in which to apply the load |
2838 | |
2839 | // Rotational velocity (also uses coordSystemID and directionVector) |
2840 | feaLoad->angularVelScaleFactor = 0.0; // Overall scale factor for the angular velocity |
2841 | feaLoad->angularAccScaleFactor = 0.0; // Overall scale factor for the angular acceleration |
2842 | |
2843 | // Thermal load - the temperature at a grid point - use gridIDSet |
2844 | feaLoad->temperature = 0.0; // Temperature value |
2845 | feaLoad->temperatureDefault = 0.0; // Default temperature of grid point explicitly not used |
2846 | |
2847 | AIM_FREE(feaLoad->temperatureMultiDistribute){ EG_free(feaLoad->temperatureMultiDistribute); feaLoad-> temperatureMultiDistribute = ((void*)0); }; |
2848 | |
2849 | return CAPS_SUCCESS0; |
2850 | } |
2851 | |
2852 | // Initiate (0 out all values and NULL all pointers) of feaDesignVariable in the feaDesignVariableStruct structure format |
2853 | int initiate_feaDesignVariableStruct(feaDesignVariableStruct *feaDesignVariable) { |
2854 | |
2855 | feaDesignVariable->name = NULL((void*)0); |
2856 | |
2857 | feaDesignVariable->designVariableID = 0; // ID number of design variable |
2858 | |
2859 | |
2860 | feaDesignVariable->initialValue = 0.0; // Initial value of design variable |
2861 | feaDesignVariable->lowerBound = 0.0; // Lower bounds of variable |
2862 | feaDesignVariable->upperBound = 0.0; // Upper bounds of variable |
2863 | feaDesignVariable->maxDelta= 0.0; // Move limit for design variable |
2864 | |
2865 | feaDesignVariable->numDiscreteValue = 0; // Number of discrete values that a design variable can assume |
2866 | |
2867 | feaDesignVariable->discreteValue = NULL((void*)0); // List of discrete values that a design variable can assume; |
2868 | |
2869 | feaDesignVariable->numIndependVariable = 0; // Number of independent variables this variables depends on |
2870 | feaDesignVariable->independVariable = NULL((void*)0); // List of independent variable names, size[numIndependVariable] |
2871 | feaDesignVariable->independVariableID = NULL((void*)0);// List of independent variable designVariableIDs, size[numIndependVariable] |
2872 | feaDesignVariable->independVariableWeight = NULL((void*)0); // List of independent variable weights, size[numIndependVariable] |
2873 | |
2874 | feaDesignVariable->variableWeight[0] = 0.0; // Weight to apply to if variable is dependent |
2875 | feaDesignVariable->variableWeight[1] = 0.0; |
2876 | |
2877 | feaDesignVariable->numRelation = 0; |
2878 | feaDesignVariable->relationSet = NULL((void*)0); |
2879 | |
2880 | return CAPS_SUCCESS0; |
2881 | } |
2882 | |
2883 | // Initiate (0 out all values and NULL all pointers) of feaDesignVariable in the feaDesignVariableStruct structure format |
2884 | int destroy_feaDesignVariableStruct(feaDesignVariableStruct *feaDesignVariable) { |
2885 | |
2886 | if (feaDesignVariable->name != NULL((void*)0)) EG_free(feaDesignVariable->name); |
2887 | feaDesignVariable->name = NULL((void*)0); |
2888 | |
2889 | feaDesignVariable->designVariableID = 0; // ID number of design variable |
2890 | |
2891 | feaDesignVariable->initialValue = 0.0; // Initial value of design variable |
2892 | feaDesignVariable->lowerBound = 0.0; // Lower bounds of variable |
2893 | feaDesignVariable->upperBound = 0.0; // Upper bounds of variable |
2894 | feaDesignVariable->maxDelta= 0.0; // Move limit for design variable |
2895 | |
2896 | feaDesignVariable->numDiscreteValue = 0; // Number of discrete values that a design variable can assume; |
2897 | if (feaDesignVariable->discreteValue != NULL((void*)0)) EG_free(feaDesignVariable->discreteValue); |
2898 | feaDesignVariable->discreteValue = NULL((void*)0); // List of discrete values that a design variable can assume; |
2899 | |
2900 | (void) string_freeArray(feaDesignVariable->numIndependVariable, &feaDesignVariable->independVariable); |
2901 | feaDesignVariable->independVariable = NULL((void*)0); // List of independent variable names, size[numIndependVariable] |
2902 | |
2903 | feaDesignVariable->numIndependVariable = 0; // Number of independent variables this variables depends on |
2904 | |
2905 | if (feaDesignVariable->independVariableID != NULL((void*)0)) EG_free(feaDesignVariable->independVariableID); |
2906 | feaDesignVariable->independVariableID = NULL((void*)0);// List of independent variable designVariableIDs |
2907 | |
2908 | if (feaDesignVariable->independVariableWeight != NULL((void*)0)) EG_free(feaDesignVariable->independVariableWeight); |
2909 | feaDesignVariable->independVariableWeight = NULL((void*)0); // List of independent variable weights, size[numIndependVariable] |
2910 | |
2911 | feaDesignVariable->variableWeight[0] = 0.0; // Weight to apply to if variable is dependent |
2912 | feaDesignVariable->variableWeight[1] = 0.0; |
2913 | |
2914 | feaDesignVariable->numRelation = 0; |
2915 | if (feaDesignVariable->relationSet != NULL((void*)0)) EG_free(feaDesignVariable->relationSet); |
2916 | |
2917 | return CAPS_SUCCESS0; |
2918 | |
2919 | } |
2920 | |
2921 | // Initiate (0 out all values and NULL all pointers) of feaDesignConstraint in the feaDesignConstraintStruct structure format |
2922 | int initiate_feaDesignConstraintStruct(feaDesignConstraintStruct *feaDesignConstraint) { |
2923 | |
2924 | feaDesignConstraint->name = NULL((void*)0); |
2925 | |
2926 | feaDesignConstraint->designConstraintID = 0; // ID number of design constraint |
2927 | |
2928 | feaDesignConstraint->designConstraintType = UnknownDesignCon; |
2929 | |
2930 | feaDesignConstraint->responseType = NULL((void*)0); // Response type options for DRESP1 Entry |
2931 | |
2932 | feaDesignConstraint->lowerBound = 0.0; // Lower bounds of design response |
2933 | feaDesignConstraint->upperBound = 0.0; // Upper bounds of design response |
2934 | |
2935 | feaDesignConstraint->numPropertyID = 0; // Number of property ID to apply the design variable to |
2936 | feaDesignConstraint->propertySetID = NULL((void*)0); // List of property IDs |
2937 | feaDesignConstraint->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID |
2938 | |
2939 | feaDesignConstraint->fieldPosition = 0; // Position in card to apply design variable to |
2940 | feaDesignConstraint->fieldName = NULL((void*)0); // Name of property/material to apply design variable to |
2941 | |
2942 | feaDesignConstraint->velocityType = NULL((void*)0); |
2943 | feaDesignConstraint->scalingFactor = 0.0; |
2944 | |
2945 | feaDesignConstraint->numVelocity = 0; |
2946 | feaDesignConstraint->velocity = NULL((void*)0); |
2947 | |
2948 | feaDesignConstraint->numDamping = 0; |
2949 | feaDesignConstraint->damping = NULL((void*)0); |
2950 | |
2951 | return CAPS_SUCCESS0; |
2952 | } |
2953 | |
2954 | // Destroy (0 out all values and NULL all pointers) of feaDesignConstraint in the feaDesignConstraintStruct structure format |
2955 | int destroy_feaDesignConstraintStruct(feaDesignConstraintStruct *feaDesignConstraint) { |
2956 | |
2957 | if (feaDesignConstraint->name != NULL((void*)0)) EG_free(feaDesignConstraint->name); |
2958 | feaDesignConstraint->name = NULL((void*)0); |
2959 | |
2960 | feaDesignConstraint->designConstraintID = 0; // ID number of design constraint |
2961 | |
2962 | feaDesignConstraint->designConstraintType = UnknownDesignCon; |
2963 | |
2964 | if (feaDesignConstraint->responseType != NULL((void*)0)) EG_free(feaDesignConstraint->responseType); |
2965 | feaDesignConstraint->responseType = NULL((void*)0); // Response type options for DRESP1 Entry |
2966 | |
2967 | feaDesignConstraint->lowerBound = 0.0; // Lower bounds of design response |
2968 | feaDesignConstraint->upperBound = 0.0; // Upper bounds of design response |
2969 | |
2970 | feaDesignConstraint->numPropertyID = 0; // Number of property ID to apply the design variable to |
2971 | |
2972 | if (feaDesignConstraint->propertySetID != NULL((void*)0)) EG_free(feaDesignConstraint->propertySetID); |
2973 | feaDesignConstraint->propertySetID = NULL((void*)0); // List of property IDs |
2974 | |
2975 | if (feaDesignConstraint->propertySetType != NULL((void*)0)) EG_free(feaDesignConstraint->propertySetType); |
2976 | feaDesignConstraint->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID |
2977 | |
2978 | feaDesignConstraint->fieldPosition = 0; // Position in card to apply design variable to |
2979 | if (feaDesignConstraint->fieldName != NULL((void*)0)) EG_free(feaDesignConstraint->fieldName); |
2980 | feaDesignConstraint->fieldName = NULL((void*)0); // Name of property/material to apply design variable to |
2981 | |
2982 | if (feaDesignConstraint->velocityType != NULL((void*)0)) EG_free(feaDesignConstraint->velocityType); |
2983 | feaDesignConstraint->velocityType = NULL((void*)0); |
2984 | feaDesignConstraint->scalingFactor = 0.0; |
2985 | |
2986 | if (feaDesignConstraint->velocity != NULL((void*)0)) EG_free(feaDesignConstraint->velocity); |
2987 | feaDesignConstraint->numVelocity = 0; |
2988 | feaDesignConstraint->velocity = NULL((void*)0); |
2989 | |
2990 | if (feaDesignConstraint->damping != NULL((void*)0)) EG_free(feaDesignConstraint->damping); |
2991 | feaDesignConstraint->numDamping = 0; |
2992 | feaDesignConstraint->damping = NULL((void*)0); |
2993 | |
2994 | return CAPS_SUCCESS0; |
2995 | |
2996 | } |
2997 | |
2998 | // Initiate (0 out all values and NULL all pointers) of feaOptimizationControl in the feaOptimizationControlStruct structure format |
2999 | int initiate_feaOptimizationControlStruct(feaOptimizationControlStruct *feaOptimizationControl) { |
3000 | |
3001 | feaOptimizationControl->fullyStressedDesign = 0; // ASTROS specific - fully stressed design number of iterations |
3002 | feaOptimizationControl->mathProgramming = 0; // Math programming number of iteratinons |
3003 | feaOptimizationControl->maxIter = 0; // Maximum number of optimization iterations |
3004 | feaOptimizationControl->constraintRetention = 0.0; // Constraint retention factor |
3005 | feaOptimizationControl->eps = 0.0; // A different constraint retention factor? |
3006 | feaOptimizationControl->moveLimit = 0.0; // Move limit |
3007 | |
3008 | return CAPS_SUCCESS0; |
3009 | } |
3010 | |
3011 | // Destroy (0 out all values and NULL all pointers) of feaOptimizationControl in the feaOptimizationControlStruct structure format |
3012 | int destroy_feaOptimzationControlStruct(feaOptimizationControlStruct *feaOptimizationControl) { |
3013 | |
3014 | feaOptimizationControl->fullyStressedDesign = 0; // ASTROS specific - fully stressed design number of iterations |
3015 | feaOptimizationControl->mathProgramming = 0; // Math programming number of iteratinons |
3016 | feaOptimizationControl->maxIter = 0; // Maximum number of optimization iterations |
3017 | feaOptimizationControl->constraintRetention = 0.0; // Constraint retention factor |
3018 | feaOptimizationControl->eps = 0.0; // A different constraint retention factor? |
3019 | feaOptimizationControl->moveLimit = 0.0; // Move limit |
3020 | |
3021 | return CAPS_SUCCESS0; |
3022 | } |
3023 | |
3024 | // Initiate (0 out all values and NULL all pointers) of feaCoordSystem in the feaCoordSystemStruct structure format |
3025 | int initiate_feaCoordSystemStruct(feaCoordSystemStruct *feaCoordSystem) { |
3026 | |
3027 | int i; // Indexing |
3028 | |
3029 | feaCoordSystem->name = NULL((void*)0); // Coordinate system name |
3030 | |
3031 | feaCoordSystem->coordSystemType = UnknownCoordSystem; // Coordinate system type |
3032 | |
3033 | feaCoordSystem->coordSystemID = 0; // ID number of coordinate system |
3034 | feaCoordSystem->refCoordSystemID = 0; // ID of reference coordinate system |
3035 | |
3036 | for (i = 0; i < 3; i++) { |
3037 | feaCoordSystem->origin[i] = 0; // x, y, and z coordinates for the origin |
3038 | |
3039 | feaCoordSystem->normal1[i] = 0; // First normal direction |
3040 | feaCoordSystem->normal2[i] = 0; // Second normal direction |
3041 | feaCoordSystem->normal3[i] = 0; // Third normal direction - found from normal1 x normal2 |
3042 | } |
3043 | |
3044 | return CAPS_SUCCESS0; |
3045 | } |
3046 | |
3047 | // Destroy (0 out all values and NULL all pointers) of feaCoordSystem in the feaCoordSystemStruct structure format |
3048 | int destroy_feaCoordSystemStruct(feaCoordSystemStruct *feaCoordSystem) { |
3049 | |
3050 | int i; // Indexing |
3051 | |
3052 | if (feaCoordSystem->name != NULL((void*)0)) EG_free(feaCoordSystem->name); |
3053 | feaCoordSystem->name = NULL((void*)0); // Coordinate system name |
3054 | |
3055 | feaCoordSystem->coordSystemType = UnknownCoordSystem; // Coordinate system type |
3056 | |
3057 | feaCoordSystem->coordSystemID = 0; // ID number of coordinate system |
3058 | feaCoordSystem->refCoordSystemID = 0; // ID of reference coordinate system |
3059 | |
3060 | for (i = 0; i < 3; i++) { |
3061 | feaCoordSystem->origin[i] = 0; // x, y, and z coordinates for the origin |
3062 | |
3063 | feaCoordSystem->normal1[i] = 0; // First normal direction |
3064 | feaCoordSystem->normal2[i] = 0; // Second normal direction |
3065 | feaCoordSystem->normal3[i] = 0; // Third normal direction - found from normal1 x normal2 |
3066 | } |
3067 | |
3068 | return CAPS_SUCCESS0; |
3069 | } |
3070 | |
3071 | // Initiate (0 out all values and NULL all pointers) of feaAero in the feaAeroStruct structure format |
3072 | int initiate_feaAeroStruct(feaAeroStruct *feaAero) { |
3073 | |
3074 | int status; // Function return status |
3075 | |
3076 | feaAero->name = NULL((void*)0); // Coordinate system name |
3077 | |
3078 | feaAero->surfaceID = 0; // Surface ID |
3079 | feaAero->coordSystemID = 0; // Coordinate system ID |
3080 | |
3081 | feaAero->numGridID = 0; // Number of grid IDs in grid ID set for the spline |
3082 | feaAero->gridIDSet = NULL((void*)0); // List of grid IDs to apply spline to. size = [numGridID] |
3083 | |
3084 | status = initiate_vlmSurfaceStruct(&feaAero->vlmSurface); |
3085 | if (status != CAPS_SUCCESS0) printf("Status %d during initiate_vlmSurfaceStruct\n", status); |
3086 | |
3087 | return CAPS_SUCCESS0; |
3088 | } |
3089 | |
3090 | // Destroy (0 out all values and NULL all pointers) of feaAero in the feaAeroStruct structure format |
3091 | int destroy_feaAeroStruct(feaAeroStruct *feaAero) { |
3092 | |
3093 | int status; // Function return status |
3094 | |
3095 | if (feaAero->name != NULL((void*)0)) EG_free(feaAero->name); |
3096 | feaAero->name = NULL((void*)0); // Coordinate system name |
3097 | |
3098 | feaAero->surfaceID = 0; // Surface ID |
3099 | feaAero->coordSystemID = 0; // Coordinate system ID |
3100 | |
3101 | feaAero->numGridID = 0; // Number of grid IDs in grid ID set for the spline |
3102 | |
3103 | if (feaAero->gridIDSet != NULL((void*)0)) EG_free(feaAero->gridIDSet); |
3104 | feaAero->gridIDSet = NULL((void*)0); // List of grid IDs to apply spline to. size = [numGridID] |
3105 | |
3106 | status = destroy_vlmSurfaceStruct(&feaAero->vlmSurface); |
3107 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_vlmSurfaceStruct\n", status); |
3108 | |
3109 | return CAPS_SUCCESS0; |
3110 | } |
3111 | |
3112 | // Initiate (0 out all values and NULL all pointers) of feaAeroRef in the feaAeroRefStruct structure format |
3113 | int initiate_feaAeroRefStruct(feaAeroRefStruct *feaAeroRef) { |
3114 | |
3115 | feaAeroRef->coordSystemID = 0; // Aerodynamic coordinate sytem id |
3116 | feaAeroRef->rigidMotionCoordSystemID = 0; // Reference coordinate system identification for rigid body motions. |
3117 | |
3118 | feaAeroRef->refChord = 1.0; // Reference chord length. Reference span. (Real > 0.0) |
3119 | feaAeroRef->refSpan = 1.0; // Reference span |
3120 | feaAeroRef->refArea = 1.0; // Reference area |
3121 | feaAeroRef->refGridID = 0; |
3122 | |
3123 | feaAeroRef->symmetryXZ = 0; // Symmetry key for the aero coordinate x-z plane. (Integer = +1 for symmetry, 0 for no symmetry, |
3124 | // and -1 for antisymmetry; Default = 0) |
3125 | feaAeroRef->symmetryXY = 0; // The symmetry key for the aero coordinate x-y plane can be used to simulate ground effects. |
3126 | // (Integer = +1 for antisymmetry, 0 for no symmetry, and -1 for symmetry; Default = 0) |
3127 | return CAPS_SUCCESS0; |
3128 | } |
3129 | |
3130 | // Destroy (0 out all values and NULL all pointers) of feaAeroRef in the feaAeroRefStruct structure format |
3131 | int destroy_feaAeroRefStruct(feaAeroRefStruct *feaAeroRef) { |
3132 | |
3133 | feaAeroRef->coordSystemID = 0; // Aerodynamic coordinate sytem id |
3134 | feaAeroRef->rigidMotionCoordSystemID = 0; // Reference coordinate system identification for rigid body motions. |
3135 | |
3136 | feaAeroRef->refChord = 0; // Reference chord length. Reference span. (Real > 0.0) |
3137 | feaAeroRef->refSpan = 0; // Reference span |
3138 | feaAeroRef->refArea = 0; // Reference area |
3139 | feaAeroRef->refGridID = 0; |
3140 | |
3141 | feaAeroRef->symmetryXZ = 0; // Symmetry key for the aero coordinate x-z plane. (Integer = +1 for symmetry, 0 for no symmetry, |
3142 | // and -1 for antisymmetry; Default = 0) |
3143 | feaAeroRef->symmetryXY = 0; // The symmetry key for the aero coordinate x-y plane can be used to simulate ground effects. |
3144 | // (Integer = +1 for antisymmetry, 0 for no symmetry, and -1 for symmetry; Default = 0) |
3145 | return CAPS_SUCCESS0; |
3146 | } |
3147 | |
3148 | // Initiate (0 out all values and NULL all pointers) of feaConnect in the feaConnectionStruct structure format |
3149 | int initiate_feaConnectionStruct(feaConnectionStruct *feaConnect) { |
3150 | |
3151 | feaConnect->name = NULL((void*)0); // Connection name |
3152 | |
3153 | feaConnect->connectionID =0; // Connection ID |
3154 | |
3155 | feaConnect->connectionType = UnknownConnection; // Connection type |
3156 | |
3157 | feaConnect->elementID = 0; |
3158 | |
3159 | // RBE2 - dependent degrees of freedom |
3160 | feaConnect->connectivity[0] = 0; // Grid IDs - 0 index = Independent grid ID, 1 index = Dependent grid ID |
3161 | feaConnect->connectivity[1] = 0; |
3162 | feaConnect->dofDependent = 0; |
3163 | |
3164 | // Spring |
3165 | feaConnect->stiffnessConst = 0.0; |
3166 | feaConnect->componentNumberStart = 0; |
3167 | feaConnect->componentNumberEnd = 0; |
3168 | feaConnect->dampingConst = 0.0; |
3169 | feaConnect->stressCoeff = 0.0; |
3170 | |
3171 | // Damper - see spring for additional entries |
3172 | |
3173 | // Mass (scalar) - see spring for additional entries |
3174 | feaConnect->mass = 0.0; |
3175 | |
3176 | // RBE3 - master/slave |
3177 | feaConnect->numMaster = 0; |
3178 | feaConnect->masterIDSet = NULL((void*)0); // Independent |
3179 | feaConnect->masterWeighting = NULL((void*)0); |
3180 | feaConnect->masterComponent = NULL((void*)0); |
3181 | |
3182 | return CAPS_SUCCESS0; |
3183 | } |
3184 | |
3185 | // Destroy (0 out all values and NULL all pointers) of feaConnect in the feaConnectionStruct structure format |
3186 | int destroy_feaConnectionStruct(feaConnectionStruct *feaConnect) { |
3187 | |
3188 | if (feaConnect->name != NULL((void*)0)) EG_free(feaConnect->name); |
3189 | feaConnect->name = NULL((void*)0); // Connection name |
3190 | |
3191 | feaConnect->connectionID =0; // Connection ID |
3192 | |
3193 | feaConnect->connectionType = UnknownConnection; // Connection type |
3194 | |
3195 | feaConnect->elementID = 0; |
3196 | |
3197 | // RBE2 - dependent degrees of freedom |
3198 | feaConnect->connectivity[0] = 0; // Grid IDs - 0 index = Independent grid ID, 1 index = Dependent grid ID |
3199 | feaConnect->connectivity[1] = 0; |
3200 | feaConnect->dofDependent = 0; |
3201 | |
3202 | // Spring |
3203 | feaConnect->stiffnessConst = 0.0; |
3204 | feaConnect->componentNumberStart = 0; |
3205 | feaConnect->componentNumberEnd = 0; |
3206 | feaConnect->dampingConst = 0.0; |
3207 | feaConnect->stressCoeff = 0.0; |
3208 | |
3209 | // Damper - see spring for additional entries |
3210 | |
3211 | // Mass (scalar) - see spring for additional entries |
3212 | feaConnect->mass = 0.0; |
3213 | |
3214 | // RBE3 - master/slave |
3215 | feaConnect->numMaster = 0; |
3216 | if (feaConnect->masterIDSet != NULL((void*)0)) EG_free(feaConnect->masterIDSet); |
3217 | feaConnect->masterIDSet = NULL((void*)0); // Independent |
3218 | if (feaConnect->masterWeighting != NULL((void*)0)) EG_free(feaConnect->masterWeighting); |
3219 | feaConnect->masterWeighting = NULL((void*)0); |
3220 | if (feaConnect->masterComponent != NULL((void*)0)) EG_free(feaConnect->masterComponent); |
3221 | feaConnect->masterComponent = NULL((void*)0); |
3222 | |
3223 | return CAPS_SUCCESS0; |
3224 | } |
3225 | |
3226 | int initiate_feaDesignEquationStruct(feaDesignEquationStruct *equation) { |
3227 | |
3228 | if (equation == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3229 | |
3230 | equation->equationID = 0; |
3231 | equation->name = NULL((void*)0); |
3232 | equation->equationArraySize = 0; |
3233 | equation->equationArray = NULL((void*)0); |
3234 | |
3235 | return CAPS_SUCCESS0; |
3236 | } |
3237 | |
3238 | int destroy_feaDesignEquationStruct(feaDesignEquationStruct *equation) { |
3239 | |
3240 | int i; |
3241 | |
3242 | if (equation == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3243 | |
3244 | if (equation->name != NULL((void*)0)) EG_free(equation->name); |
3245 | |
3246 | if (equation->equationArray != NULL((void*)0)) { |
3247 | for (i = 0; i < equation->equationArraySize; i++) { |
3248 | if (equation->equationArray[i] != NULL((void*)0)) { |
3249 | EG_free(equation->equationArray[i]); |
3250 | } |
3251 | } |
3252 | EG_free(equation->equationArray); |
3253 | } |
3254 | |
3255 | return initiate_feaDesignEquationStruct(equation); |
3256 | } |
3257 | |
3258 | int initiate_feaDesignResponseStruct(feaDesignResponseStruct *response) { |
3259 | |
3260 | if (response == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3261 | |
3262 | response->responseID = 0; |
3263 | |
3264 | response->name = NULL((void*)0); |
3265 | |
3266 | response->responseType = NULL((void*)0); |
3267 | response->propertyType = NULL((void*)0); |
3268 | |
3269 | response->region = 0; |
3270 | |
3271 | response->component = 0; // Component number |
3272 | response->itemCode = 0; // Item code |
3273 | response->modeNumber = 0; // Mode number |
3274 | |
3275 | response->lamina = 0; // Lamina number |
3276 | response->frequency = 0.0; // Frequency value |
3277 | response->time = 0.0; // Time value |
3278 | response->restraintFlag = 0; // Restraint flag |
3279 | |
3280 | response->gridID = 0; // Grid ID |
3281 | response->propertyID = 0; // Property entry ID |
3282 | |
3283 | return CAPS_SUCCESS0; |
3284 | } |
3285 | |
3286 | int destroy_feaDesignResponseStruct(feaDesignResponseStruct *response) { |
3287 | |
3288 | if (response == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3289 | |
3290 | if (response->name != NULL((void*)0)) EG_free(response->name); |
3291 | |
3292 | if (response->responseType != NULL((void*)0)) EG_free(response->responseType); |
3293 | if (response->propertyType != NULL((void*)0)) EG_free(response->propertyType); |
3294 | |
3295 | return initiate_feaDesignResponseStruct(response); |
3296 | } |
3297 | |
3298 | int initiate_feaDesignEquationResponseStruct(feaDesignEquationResponseStruct* equationResponse) { |
3299 | |
3300 | if (equationResponse == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3301 | |
3302 | equationResponse->equationResponseID = 0; |
3303 | |
3304 | equationResponse->name = NULL((void*)0); // Name of the equation |
3305 | |
3306 | equationResponse->equationName = NULL((void*)0); |
3307 | |
3308 | equationResponse->region = 0; // Region identifier for constant screening |
3309 | |
3310 | equationResponse->numDesignVariable = 0; |
3311 | equationResponse->designVariableNameSet = NULL((void*)0); // Design variable names, size = [numDesignVariable] |
3312 | |
3313 | equationResponse->numConstant = 0; |
3314 | equationResponse->constantLabelSet = NULL((void*)0); // Labels of the table constants, size = [numConstant] |
3315 | |
3316 | equationResponse->numResponse = 0; |
3317 | equationResponse->responseNameSet = NULL((void*)0); // Names of design sensitivity response quantities, size = [numResponse] |
3318 | |
3319 | equationResponse->numGrid = 0; |
3320 | equationResponse->gridIDSet = NULL((void*)0); // Grid IDs, size = [numGrid] |
3321 | equationResponse->dofNumberSet = NULL((void*)0); // Degree of freedom numbers, size = [numGrid] |
3322 | |
3323 | equationResponse->numEquationResponse = 0; |
3324 | equationResponse->equationResponseNameSet = NULL((void*)0); // Names of design sensitivity equation response quantities, size = [numEquationResponse] |
3325 | |
3326 | return CAPS_SUCCESS0; |
3327 | } |
3328 | |
3329 | int destroy_feaDesignEquationResponseStruct(feaDesignEquationResponseStruct* equationResponse) { |
3330 | |
3331 | if (equationResponse == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3332 | |
3333 | if (equationResponse->name != NULL((void*)0)) EG_free(equationResponse->name); |
3334 | |
3335 | if (equationResponse->equationName != NULL((void*)0)) EG_free(equationResponse->equationName); |
3336 | |
3337 | if (equationResponse->designVariableNameSet != NULL((void*)0)) { |
3338 | string_freeArray(equationResponse->numDesignVariable, &equationResponse->designVariableNameSet); |
3339 | } |
3340 | |
3341 | if (equationResponse->constantLabelSet != NULL((void*)0)) { |
3342 | string_freeArray(equationResponse->numConstant, &equationResponse->constantLabelSet); |
3343 | } |
3344 | |
3345 | if (equationResponse->responseNameSet != NULL((void*)0)) { |
3346 | string_freeArray(equationResponse->numResponse, &equationResponse->responseNameSet); |
3347 | } |
3348 | |
3349 | if (equationResponse->gridIDSet != NULL((void*)0)) EG_free(equationResponse->gridIDSet); |
3350 | if (equationResponse->dofNumberSet != NULL((void*)0)) EG_free(equationResponse->dofNumberSet); |
3351 | |
3352 | if (equationResponse->equationResponseNameSet != NULL((void*)0)) { |
3353 | string_freeArray(equationResponse->numEquationResponse, &equationResponse->equationResponseNameSet); |
3354 | } |
3355 | |
3356 | return initiate_feaDesignEquationResponseStruct(equationResponse); |
3357 | } |
3358 | |
3359 | int initiate_feaDesignTableStruct(feaDesignTableStruct *table) { |
3360 | |
3361 | if (table == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3362 | |
3363 | table->numConstant = 0; |
3364 | table->constantLabel = NULL((void*)0); |
3365 | table->constantValue = NULL((void*)0); |
3366 | |
3367 | return CAPS_SUCCESS0; |
3368 | } |
3369 | |
3370 | int destroy_feaDesignTableStruct(feaDesignTableStruct *table) { |
3371 | |
3372 | if (table == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3373 | |
3374 | if (table->constantLabel != NULL((void*)0)) string_freeArray(table->numConstant, &table->constantLabel); |
3375 | if (table->constantValue != NULL((void*)0)) EG_free(table->constantValue); |
3376 | |
3377 | return initiate_feaDesignTableStruct(table); |
3378 | } |
3379 | |
3380 | |
3381 | int initiate_feaDesignOptParamStruct(feaDesignOptParamStruct *table) { |
3382 | |
3383 | if (table == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3384 | |
3385 | table->numParam = 0; |
3386 | table->paramLabel = NULL((void*)0); |
3387 | table->paramValue = NULL((void*)0); |
3388 | table->paramType = NULL((void*)0); |
3389 | |
3390 | return CAPS_SUCCESS0; |
3391 | } |
3392 | |
3393 | int destroy_feaDesignOptParamStruct(feaDesignOptParamStruct *table) { |
3394 | |
3395 | int i; |
3396 | |
3397 | if (table == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3398 | |
3399 | if (table->paramLabel != NULL((void*)0)) string_freeArray(table->numParam, &table->paramLabel); |
3400 | |
3401 | if (table->paramValue != NULL((void*)0)) { |
3402 | for (i = 0; i < table->numParam; i++) { |
3403 | if (table->paramValue[i] != NULL((void*)0)) { |
3404 | EG_free(table->paramValue[i]); |
3405 | } |
3406 | } |
3407 | EG_free(table->paramValue); |
3408 | } |
3409 | |
3410 | if (table->paramType != NULL((void*)0)) EG_free(table->paramType); |
3411 | |
3412 | return initiate_feaDesignOptParamStruct(table); |
3413 | } |
3414 | |
3415 | int initiate_feaDesignVariableRelationStruct(feaDesignVariableRelationStruct *relation) { |
3416 | |
3417 | if (relation == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3418 | |
3419 | relation->name = NULL((void*)0); |
3420 | |
3421 | relation->componentType = 0; |
3422 | |
3423 | relation->relationID = 0; |
3424 | |
3425 | relation->numDesignVariable = 0; |
3426 | relation->designVariableNameSet = NULL((void*)0); |
3427 | relation->designVariableSet = NULL((void*)0); |
3428 | |
3429 | relation->fieldPosition = 0; |
3430 | relation->fieldName = NULL((void*)0); |
3431 | |
3432 | relation->constantRelationCoeff = 0.0; |
3433 | relation->linearRelationCoeff = NULL((void*)0); |
3434 | |
3435 | relation->numMaterialID = 0; // Number of materials to apply the design variable to |
3436 | relation->materialSetID = NULL((void*)0); // List of materials IDs |
3437 | relation->materialSetType = NULL((void*)0); // List of materials types corresponding to the materialSetID |
3438 | |
3439 | relation->numPropertyID = 0; // Number of property ID to apply the design variable to |
3440 | relation->propertySetID = NULL((void*)0); // List of property IDs |
3441 | relation->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID |
3442 | |
3443 | relation->numElementID = 0; // Number of element ID to apply the design variable to |
3444 | relation->elementSetID = NULL((void*)0); // List of element IDs |
3445 | relation->elementSetType = NULL((void*)0); // List of element types corresponding to the elementSetID |
3446 | relation->elementSetSubType = NULL((void*)0); // List of element subtypes correspoding to the elementSetID |
3447 | |
3448 | return CAPS_SUCCESS0; |
3449 | } |
3450 | |
3451 | int destroy_feaDesignVariableRelationStruct(feaDesignVariableRelationStruct *relation) { |
3452 | |
3453 | if (relation == NULL((void*)0)) return CAPS_NULLVALUE-307; |
3454 | |
3455 | if (relation->designVariableNameSet != NULL((void*)0)) string_freeArray(relation->numDesignVariable, &relation->designVariableNameSet); |
3456 | if (relation->name != NULL((void*)0)) EG_free(relation->name); |
3457 | if (relation->designVariableSet != NULL((void*)0)) EG_free(relation->designVariableSet); |
3458 | |
3459 | if (relation->fieldName != NULL((void*)0)) EG_free(relation->fieldName); |
3460 | |
3461 | if (relation->linearRelationCoeff != NULL((void*)0)) EG_free(relation->linearRelationCoeff); |
3462 | |
3463 | relation->numMaterialID = 0; // Number of materials to apply the design variable to |
3464 | if (relation->materialSetID != NULL((void*)0)) EG_free(relation->materialSetID); |
3465 | relation->materialSetID = NULL((void*)0); // List of materials IDs |
3466 | |
3467 | if (relation->materialSetType != NULL((void*)0)) EG_free(relation->materialSetType); |
3468 | relation->materialSetType = NULL((void*)0); // List of materials types corresponding to the materialSetID |
3469 | |
3470 | relation->numPropertyID = 0; // Number of property ID to apply the design variable to |
3471 | if (relation->propertySetID != NULL((void*)0)) EG_free(relation->propertySetID); |
3472 | relation->propertySetID = NULL((void*)0); // List of property IDs |
3473 | |
3474 | if (relation->propertySetType != NULL((void*)0)) EG_free(relation->propertySetType); |
3475 | relation->propertySetType = NULL((void*)0); // List of property types corresponding to the propertySetID |
3476 | |
3477 | relation->numElementID = 0; // Number of element ID to apply the design variable to |
3478 | if (relation->elementSetID != NULL((void*)0)) EG_free(relation->elementSetID); |
3479 | relation->elementSetID = NULL((void*)0); // List of element IDs |
3480 | |
3481 | if (relation->elementSetType != NULL((void*)0)) EG_free(relation->elementSetType); |
3482 | relation->elementSetType = NULL((void*)0); // List of element types corresponding to the elementSetID |
3483 | |
3484 | if (relation->elementSetSubType != NULL((void*)0)) EG_free(relation->elementSetSubType); |
3485 | relation->elementSetSubType = NULL((void*)0); // List of element subtypes correspoding to the elementSetID |
3486 | |
3487 | return initiate_feaDesignVariableRelationStruct(relation); |
3488 | } |
3489 | |
3490 | // Get the material properties from a capsTuple |
3491 | int fea_getMaterial(void *aimInfo, |
3492 | int numMaterialTuple, |
3493 | capsTuple materialTuple[], |
3494 | feaUnitsStruct *feaUnits, |
3495 | int *numMaterial, |
3496 | feaMaterialStruct *feaMaterial[]) { |
3497 | |
3498 | /*! \page feaMaterial FEA Material |
3499 | * Structure for the material tuple = ("Material Name", "Value"). |
3500 | * "Material Name" defines the reference name for the material being specified. |
3501 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringMaterial) or a single string keyword |
3502 | * (see Section \ref keyStringMaterial). |
3503 | */ |
3504 | |
3505 | int status; //Function return |
3506 | |
3507 | int i; // Indexing |
3508 | |
3509 | char *keyValue = NULL((void*)0); |
3510 | char *keyWord = NULL((void*)0); |
3511 | |
3512 | // Destroy our material structures coming in if aren't 0 and NULL already |
3513 | if (*feaMaterial != NULL((void*)0)) { |
3514 | for (i = 0; i < *numMaterial; i++) { |
3515 | status = destroy_feaMaterialStruct(&(*feaMaterial)[i]); |
3516 | if (status != CAPS_SUCCESS0) return status; |
3517 | } |
3518 | } |
3519 | if (*feaMaterial != NULL((void*)0)) EG_free(*feaMaterial); |
3520 | *feaMaterial = NULL((void*)0); |
3521 | *numMaterial = 0; |
3522 | |
3523 | printf("\nGetting FEA materials.......\n"); |
3524 | |
3525 | *numMaterial = numMaterialTuple; |
3526 | printf("\tNumber of materials - %d\n", *numMaterial); |
3527 | |
3528 | if (*numMaterial > 0) { |
3529 | *feaMaterial = (feaMaterialStruct *) EG_alloc(*numMaterial * sizeof(feaMaterialStruct)); |
3530 | if (*feaMaterial == NULL((void*)0)) return EGADS_MALLOC-4; |
3531 | |
3532 | } else { |
3533 | printf("\tNumber of material values in input tuple is 0\n"); |
3534 | return CAPS_NOTFOUND-303; |
3535 | } |
3536 | |
3537 | for (i = 0; i < *numMaterial; i++) { |
3538 | status = initiate_feaMaterialStruct(&(*feaMaterial)[i]); |
3539 | if (status != CAPS_SUCCESS0) return status; |
3540 | } |
3541 | |
3542 | for (i = 0; i < *numMaterial; i++) { |
3543 | |
3544 | printf("\tMaterial name - %s\n", materialTuple[i].name); |
3545 | |
3546 | (*feaMaterial)[i].name = (char *) EG_alloc(((strlen(materialTuple[i].name)) + 1)*sizeof(char)); |
3547 | if ((*feaMaterial)[i].name == NULL((void*)0)) return EGADS_MALLOC-4; |
3548 | |
3549 | memcpy((*feaMaterial)[i].name, materialTuple[i].name, strlen(materialTuple[i].name)*sizeof(char)); |
3550 | (*feaMaterial)[i].name[strlen(materialTuple[i].name)] = '\0'; |
3551 | |
3552 | (*feaMaterial)[i].materialID = i + 1; |
3553 | |
3554 | // Do we have a json string? |
3555 | if (strncmp(materialTuple[i].value, "{", 1) == 0) { |
3556 | //printf("JSON String - %s\n", materialTuple[i].value); |
3557 | |
3558 | |
3559 | /*! \page feaMaterial |
3560 | * \section jsonStringMaterial JSON String Dictionary |
3561 | * |
3562 | * If "Value" is JSON string dictionary |
3563 | * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS || MASSTRAN) |
3564 | * (e.g. "Value" = {"density": 7850, "youngModulus": 120000.0, "poissonRatio": 0.5, "materialType": "isotropic"}) |
3565 | * \endif |
3566 | * the following keywords ( = default values) may be used: |
3567 | * |
3568 | * <ul> |
3569 | * <li> <B>materialType = "Isotropic"</B> </li> <br> |
3570 | * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS) |
3571 | * Material property type. Options: Isotropic, Anisothotropic, Orthotropic, or Anisotropic. |
3572 | * \elseif MASSTRAN |
3573 | * Material property type. Options: Isotropic. |
3574 | * \endif |
3575 | * </ul> |
3576 | */ |
3577 | |
3578 | // Get material Type |
3579 | keyWord = "materialType"; |
3580 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3581 | if (status == CAPS_SUCCESS0) { |
3582 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3582, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3583 | |
3584 | //{UnknownMaterial, Isotropic, Anisothotropic, Orthotropic, Anisotropic} |
3585 | if (strcasecmp(keyValue, "\"Isotropic\"") == 0) (*feaMaterial)[i].materialType = Isotropic; |
3586 | else if (strcasecmp(keyValue, "\"Anisothotropic\"") == 0) (*feaMaterial)[i].materialType = Anisothotropic; |
3587 | else if (strcasecmp(keyValue, "\"Orthotropic\"") == 0) (*feaMaterial)[i].materialType = Orthotropic; |
3588 | else if (strcasecmp(keyValue, "\"Anisotropic\"") == 0) (*feaMaterial)[i].materialType = Anisotropic; |
3589 | else { |
3590 | |
3591 | printf("\tUnrecognized \"%s\" specified (%s) for Material tuple %s, defaulting to \"Isotropic\"\n", keyWord, |
3592 | keyValue, |
3593 | materialTuple[i].name); |
3594 | (*feaMaterial)[i].materialType = Isotropic; |
3595 | } |
3596 | |
3597 | } else { |
3598 | |
3599 | printf("\tNo \"%s\" specified for Material tuple %s, defaulting to \"Isotropic\"\n", keyWord, |
3600 | materialTuple[i].name); |
3601 | (*feaMaterial)[i].materialType = Isotropic; |
3602 | } |
3603 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3604 | |
3605 | //Fill up material properties |
3606 | |
3607 | /*! \page feaMaterial |
3608 | * |
3609 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS) |
3610 | * <ul> |
3611 | * <li> <B>youngModulus = 0.0</B> </li> <br> |
3612 | * Also known as the elastic modulus, defines the relationship between stress and strain. |
3613 | * Default if `shearModulus' and `poissonRatio' != 0, youngModulus = 2*(1+poissonRatio)*shearModulus |
3614 | * </ul> |
3615 | * \endif |
3616 | * |
3617 | */ |
3618 | keyWord = "youngModulus"; |
3619 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3620 | if (status == CAPS_SUCCESS0) { |
3621 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3621, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3622 | if ( feaUnits->pressure != NULL((void*)0) ) { |
3623 | status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->pressure, &(*feaMaterial)[i].youngModulus); |
3624 | } else { |
3625 | status = string_toDouble(keyValue, &(*feaMaterial)[i].youngModulus); |
3626 | } |
3627 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3627 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3628 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3629 | } |
3630 | |
3631 | /*! \page feaMaterial |
3632 | * |
3633 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS) |
3634 | * <ul> |
3635 | * <li> <B>shearModulus = 0.0</B> </li> <br> |
3636 | * Also known as the modulus of rigidity, is defined as the ratio of shear stress to the shear strain. |
3637 | * Default if `youngModulus' and `poissonRatio' != 0, shearModulus = youngModulus/(2*(1+poissonRatio)) |
3638 | * </ul> |
3639 | * \endif |
3640 | */ |
3641 | keyWord = "shearModulus"; |
3642 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3643 | if (status == CAPS_SUCCESS0) { |
3644 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3644, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3645 | status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulus); |
3646 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3646 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3647 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3648 | } |
3649 | |
3650 | /*! \page feaMaterial |
3651 | * |
3652 | * |
3653 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS) |
3654 | * <ul> |
3655 | * <li> <B>poissonRatio = 0.0</B> </li> <br> |
3656 | * The fraction of expansion divided by the fraction of compression. |
3657 | * Default if `youngModulus' and `shearModulus' != 0, poissonRatio = (2*youngModulus/shearModulus) - 1 |
3658 | * </ul> |
3659 | * \endif |
3660 | */ |
3661 | keyWord = "poissonRatio"; |
3662 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3663 | if (status == CAPS_SUCCESS0) { |
3664 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3664, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3665 | status = string_toDouble(keyValue, &(*feaMaterial)[i].poissonRatio); |
3666 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3666 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3667 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3668 | } |
3669 | |
3670 | // Check Young's modulus, shear modulus, and Poisson's ratio |
3671 | if ( ((*feaMaterial)[i].youngModulus == 0 && (*feaMaterial)[i].poissonRatio == 0) || |
3672 | ((*feaMaterial)[i].shearModulus == 0 && (*feaMaterial)[i].poissonRatio == 0) || |
3673 | ((*feaMaterial)[i].youngModulus == 0 && (*feaMaterial)[i].shearModulus == 0) ) { |
3674 | // Do nothing |
3675 | |
3676 | } else if ((*feaMaterial)[i].youngModulus == 0) { |
3677 | (*feaMaterial)[i].youngModulus = 2*(1+(*feaMaterial)[i].poissonRatio)*(*feaMaterial)[i].shearModulus; |
3678 | } else if ((*feaMaterial)[i].shearModulus == 0) { |
3679 | (*feaMaterial)[i].shearModulus = (*feaMaterial)[i].youngModulus/(2*(1+(*feaMaterial)[i].poissonRatio)); |
3680 | } else if ((*feaMaterial)[i].poissonRatio == 0) { |
3681 | (*feaMaterial)[i].poissonRatio = (*feaMaterial)[i].youngModulus/(2*(*feaMaterial)[i].shearModulus) -1; |
3682 | } |
3683 | |
3684 | /*! \page feaMaterial |
3685 | * |
3686 | * |
3687 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || MASSTRAN) |
3688 | * <ul> |
3689 | * <li> <B>density = 0.0</B> </li> <br> |
3690 | * Density of the material. |
3691 | * </ul> |
3692 | * \endif |
3693 | */ |
3694 | keyWord = "density"; |
3695 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3696 | if (status == CAPS_SUCCESS0) { |
3697 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3697, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3698 | if ( feaUnits->densityVol != NULL((void*)0) ) { |
3699 | status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->densityVol, &(*feaMaterial)[i].density); |
3700 | } else { |
3701 | status = string_toDouble(keyValue, &(*feaMaterial)[i].density); |
3702 | } |
3703 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3703 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3704 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3705 | } |
3706 | |
3707 | /*! \page feaMaterial |
3708 | * |
3709 | * \if (MYSTRAN || NASTRAN || ASTROS) |
3710 | * <ul> |
3711 | * <li> <B>thermalExpCoeff = 0.0</B> </li> <br> |
3712 | * Thermal expansion coefficient of the material. |
3713 | * </ul> |
3714 | * \endif |
3715 | */ |
3716 | keyWord = "thermalExpCoeff"; |
3717 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3718 | if (status == CAPS_SUCCESS0) { |
3719 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3719, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3720 | status = string_toDouble(keyValue, &(*feaMaterial)[i].thermalExpCoeff); |
3721 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3721 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3722 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3723 | } |
3724 | |
3725 | /*! \page feaMaterial |
3726 | * |
3727 | * \if (MYSTRAN || NASTRAN || ASTROS) |
3728 | * <ul> |
3729 | * <li> <B>thermalExpCoeffLateral = 0.0</B> </li> <br> |
3730 | * Thermal expansion coefficient of the material. |
3731 | * </ul> |
3732 | * \endif |
3733 | */ |
3734 | keyWord = "thermalExpCoeffLateral"; |
3735 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3736 | if (status == CAPS_SUCCESS0) { |
3737 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3737, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3738 | status = string_toDouble(keyValue, &(*feaMaterial)[i].thermalExpCoeffLateral); |
3739 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3739 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3740 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3741 | } |
3742 | |
3743 | /*! \page feaMaterial |
3744 | * |
3745 | * |
3746 | * \if (MYSTRAN || NASTRAN || ASTROS) |
3747 | * <ul> |
3748 | * <li> <B>temperatureRef = 0.0</B> </li> <br> |
3749 | * Reference temperature for material properties. |
3750 | * </ul> |
3751 | * \endif |
3752 | */ |
3753 | keyWord = "temperatureRef"; |
3754 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3755 | if (status == CAPS_SUCCESS0) { |
3756 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3756, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3757 | status = string_toDouble(keyValue, &(*feaMaterial)[i].temperatureRef); |
3758 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3758 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3759 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3760 | } |
3761 | |
3762 | /*! \page feaMaterial |
3763 | * |
3764 | * \if (MYSTRAN || NASTRAN || ASTROS) |
3765 | * <ul> |
3766 | * <li> <B>dampingCoeff = 0.0</B> </li> <br> |
3767 | * Damping coefficient for the material. |
3768 | * </ul> |
3769 | * \endif |
3770 | */ |
3771 | keyWord = "dampingCoeff"; |
3772 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3773 | if (status == CAPS_SUCCESS0) { |
3774 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3774, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3775 | status = string_toDouble(keyValue, &(*feaMaterial)[i].dampingCoeff); |
3776 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3776 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3777 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3778 | } |
3779 | |
3780 | /*! \page feaMaterial |
3781 | * |
3782 | * |
3783 | * \if NASTRAN |
3784 | * <ul> |
3785 | * <li> <B>yieldAllow = 0.0</B> </li> <br> |
3786 | * Yield strength/allowable for the material. |
3787 | * </ul> |
3788 | * \endif |
3789 | */ |
3790 | keyWord = "yieldAllow"; |
3791 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3792 | if (status == CAPS_SUCCESS0) { |
3793 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 3793, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
3794 | status = string_toDouble(keyValue, &(*feaMaterial)[i].yieldAllow); |
3795 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3795 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3796 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3797 | } |
3798 | |
3799 | /*! \page feaMaterial |
3800 | * |
3801 | * |
3802 | * \if NASTRAN |
3803 | * <ul> |
3804 | * <li> <B>tensionAllow = 0.0</B> </li> <br> |
3805 | * Tension allowable for the material. |
3806 | * </ul> |
3807 | * \endif |
3808 | */ |
3809 | keyWord = "tensionAllow"; |
3810 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3811 | if (status == CAPS_SUCCESS0) { |
3812 | |
3813 | status = string_toDouble(keyValue, &(*feaMaterial)[i].tensionAllow); |
3814 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3814 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3815 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3816 | } |
3817 | |
3818 | /*! \page feaMaterial |
3819 | * |
3820 | * |
3821 | * \if NASTRAN |
3822 | * <ul> |
3823 | * <li> <B>tensionAllowLateral = 0.0</B> </li> <br> |
3824 | * Lateral tension allowable for the material. |
3825 | * </ul> |
3826 | * \endif |
3827 | */ |
3828 | keyWord = "tensionAllowLateral"; |
3829 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3830 | if (status == CAPS_SUCCESS0) { |
3831 | |
3832 | status = string_toDouble(keyValue, &(*feaMaterial)[i].tensionAllowLateral); |
3833 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3833 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3834 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3835 | } |
3836 | |
3837 | /*! \page feaMaterial |
3838 | * |
3839 | * \if NASTRAN |
3840 | * <ul> |
3841 | * <li> <B>compressAllow = 0.0</B> </li> <br> |
3842 | * Compression allowable for the material. |
3843 | * </ul> |
3844 | * \endif |
3845 | */ |
3846 | keyWord = "compressAllow"; |
3847 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3848 | if (status == CAPS_SUCCESS0) { |
3849 | |
3850 | status = string_toDouble(keyValue, &(*feaMaterial)[i].compressAllow); |
3851 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3851 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3852 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3853 | } |
3854 | |
3855 | /*! \page feaMaterial |
3856 | * |
3857 | * \if NASTRAN |
3858 | * <ul> |
3859 | * <li> <B>compressAllowLateral = 0.0</B> </li> <br> |
3860 | * Lateral compression allowable for the material. |
3861 | * </ul> |
3862 | * \endif |
3863 | */ |
3864 | keyWord = "compressAllowLateral"; |
3865 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3866 | if (status == CAPS_SUCCESS0) { |
3867 | |
3868 | status = string_toDouble(keyValue, &(*feaMaterial)[i].compressAllowLateral); |
3869 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3869 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3870 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3871 | } |
3872 | |
3873 | /*! \page feaMaterial |
3874 | * |
3875 | * \if NASTRAN |
3876 | * <ul> |
3877 | * <li> <B>shearAllow = 0.0</B> </li> <br> |
3878 | * Shear allowable for the material. |
3879 | * </ul> |
3880 | * \endif |
3881 | */ |
3882 | keyWord = "shearAllow"; |
3883 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3884 | if (status == CAPS_SUCCESS0) { |
3885 | |
3886 | status = string_toDouble(keyValue, &(*feaMaterial)[i].shearAllow); |
3887 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3887 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3888 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3889 | } |
3890 | |
3891 | /*! \page feaMaterial |
3892 | * |
3893 | * \if (NASTRAN) |
3894 | * <ul> |
3895 | * <li> <B>allowType = 0 </B> </li> <br> |
3896 | * This flag defines if the above allowables <c>compressAllow</c> etc. are defined in terms of stress (0) or strain (1). The default is stress (0). |
3897 | * </ul> |
3898 | * \endif |
3899 | */ |
3900 | keyWord = "allowType"; |
3901 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3902 | if (status == CAPS_SUCCESS0) { |
3903 | status = string_toInteger(keyValue, &(*feaMaterial)[i].allowType); |
3904 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3904 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3905 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3906 | } |
3907 | |
3908 | /*! \page feaMaterial |
3909 | * |
3910 | * \if (MYSTRAN || NASTRAN || ABAQUS) |
3911 | * <ul> |
3912 | * <li> <B>youngModulusLateral = 0.0</B> </li> <br> |
3913 | * Elastic modulus in lateral direction for an orthotropic material |
3914 | * </ul> |
3915 | * \endif |
3916 | */ |
3917 | keyWord = "youngModulusLateral"; |
3918 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3919 | if (status == CAPS_SUCCESS0) { |
3920 | |
3921 | status = string_toDouble(keyValue, &(*feaMaterial)[i].youngModulusLateral); |
3922 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3922 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3923 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3924 | } |
3925 | |
3926 | /*! \page feaMaterial |
3927 | * |
3928 | * \if (MYSTRAN || NASTRAN || ABAQUS) |
3929 | * <ul> |
3930 | * <li> <B>shearModulusTrans1Z = 0.0</B> </li> <br> |
3931 | * Transverse shear modulus in the 1-Z plane for an orthotropic material |
3932 | * </ul> |
3933 | * \endif |
3934 | */ |
3935 | keyWord = "shearModulusTrans1Z"; |
3936 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3937 | if (status == CAPS_SUCCESS0) { |
3938 | |
3939 | status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulusTrans1Z); |
3940 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3940 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3941 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3942 | } |
3943 | |
3944 | /*! \page feaMaterial |
3945 | * |
3946 | * \if (MYSTRAN || NASTRAN || ABAQUS) |
3947 | * <ul> |
3948 | * <li> <B>shearModulusTrans2Z = 0.0</B> </li> <br> |
3949 | * Transverse shear modulus in the 2-Z plane for an orthotropic material |
3950 | * </ul> |
3951 | * \endif |
3952 | */ |
3953 | keyWord = "shearModulusTrans2Z"; |
3954 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3955 | if (status == CAPS_SUCCESS0) { |
3956 | |
3957 | status = string_toDouble(keyValue, &(*feaMaterial)[i].shearModulusTrans2Z); |
3958 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3958 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3959 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3960 | } |
3961 | |
3962 | /*! \page feaMaterial |
3963 | * |
3964 | * \if (TACS || NASTRAN || ABAQUS) |
3965 | * <ul> |
3966 | * <li> <B>kappa = 0.0</B> </li> <br> |
3967 | * Thermal conductivity for an isotropic solid |
3968 | * </ul> |
3969 | * \endif |
3970 | */ |
3971 | keyWord = "kappa"; |
3972 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3973 | if (status == CAPS_SUCCESS0) { |
3974 | |
3975 | status = string_toDouble(keyValue, &(*feaMaterial)[i].kappa); |
3976 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3976 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3977 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3978 | } |
3979 | |
3980 | /*! \page feaMaterial |
3981 | * |
3982 | * \if (TACS || NASTRAN || ABAQUS) |
3983 | * <ul> |
3984 | * <li> <B>specificHeat = 0.0</B> </li> <br> |
3985 | * Specific heat constant pressure (per unit mass) for an isotropic solid |
3986 | * </ul> |
3987 | * \endif |
3988 | */ |
3989 | keyWord = "specificHeat"; |
3990 | status = search_jsonDictionary( materialTuple[i].value, keyWord, &keyValue); |
3991 | if (status == CAPS_SUCCESS0) { |
3992 | |
3993 | status = string_toDouble(keyValue, &(*feaMaterial)[i].specificHeat); |
3994 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 3994 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
3995 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
3996 | } |
3997 | |
3998 | } else { |
3999 | |
4000 | /*! \page feaMaterial |
4001 | * \section keyStringMaterial Single Value String |
4002 | * |
4003 | * If "Value" is a string, the string value may correspond to an entry in a predefined material lookup |
4004 | * table. NOT YET IMPLEMENTED!!!! |
4005 | * |
4006 | */ |
4007 | // CALL material look up |
4008 | AIM_ERROR(aimInfo, "Material tuple value ('%s') is expected to be a JSON string", materialTuple[i].value){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4008, __func__ , "Material tuple value ('%s') is expected to be a JSON string" , materialTuple[i].value); }; |
4009 | status = CAPS_BADVALUE-311; |
4010 | goto cleanup; |
4011 | } |
4012 | } |
4013 | |
4014 | printf("\tDone getting FEA materials\n"); |
4015 | status = CAPS_SUCCESS0; |
4016 | |
4017 | cleanup: |
4018 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4019 | |
4020 | return status; |
4021 | } |
4022 | |
4023 | // Get the property properties from a capsTuple |
4024 | int fea_getProperty(void *aimInfo, |
4025 | int numPropertyTuple, |
4026 | capsTuple propertyTuple[], |
4027 | mapAttrToIndexStruct *attrMap, |
4028 | feaUnitsStruct *feaUnits, |
4029 | feaProblemStruct *feaProblem) { |
4030 | |
4031 | /*! \page feaProperty FEA Property |
4032 | * Structure for the property tuple = ("Property Name", "Value"). |
4033 | * "Property Name" defines the reference <c>capsGroup</c> for the property being specified. |
4034 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringProperty) or a single string keyword |
4035 | * (see Section \ref keyStringProperty). |
4036 | */ |
4037 | |
4038 | int status; //Function return |
4039 | |
4040 | int i, j, matIndex; // Indexing |
4041 | int found; // Bool test function |
4042 | |
4043 | int pidIndex; // Property identification index found in attribute map |
4044 | |
4045 | int tempInteger; |
4046 | |
4047 | char *keyValue = NULL((void*)0); |
4048 | char *keyWord = NULL((void*)0); |
4049 | char *tempString = NULL((void*)0); |
4050 | char **tempStringArray = NULL((void*)0); |
4051 | |
4052 | // double tempDouble; |
4053 | |
4054 | // Destroy our property structures coming in if aren't 0 and NULL already |
4055 | if (feaProblem->feaProperty != NULL((void*)0)) { |
4056 | for (i = 0; i < feaProblem->numProperty; i++) { |
4057 | status = destroy_feaPropertyStruct(&feaProblem->feaProperty[i]); |
4058 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4058 , __func__, 0); goto cleanup; }; |
4059 | } |
4060 | } |
4061 | AIM_FREE(feaProblem->feaProperty){ EG_free(feaProblem->feaProperty); feaProblem->feaProperty = ((void*)0); }; |
4062 | feaProblem->numProperty = 0; |
4063 | |
4064 | printf("\nGetting FEA properties.......\n"); |
4065 | |
4066 | feaProblem->numProperty = numPropertyTuple; |
4067 | printf("\tNumber of properties - %d\n", feaProblem->numProperty); |
4068 | |
4069 | if (feaProblem->numProperty > 0) { |
4070 | |
4071 | feaProblem->feaProperty = (feaPropertyStruct *) EG_alloc(feaProblem->numProperty * sizeof(feaPropertyStruct)); |
4072 | if (feaProblem->feaProperty == NULL((void*)0)) return EGADS_MALLOC-4; |
4073 | |
4074 | } else { |
4075 | AIM_ERROR(aimInfo, "Number of property values in input tuple is 0\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4075, __func__ , "Number of property values in input tuple is 0\n"); }; |
4076 | status = CAPS_NOTFOUND-303; |
4077 | goto cleanup; |
4078 | } |
4079 | |
4080 | for (i = 0; i < feaProblem->numProperty; i++) { |
4081 | status = initiate_feaPropertyStruct(&feaProblem->feaProperty[i]); |
4082 | AIM_STATUS(aimInfo, status, "Unable to initiate feaProperty structure (number = %d)", i)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4082 , __func__, 2, "Unable to initiate feaProperty structure (number = %d)" , i); goto cleanup; }; |
4083 | } |
4084 | |
4085 | for (i = 0; i < feaProblem->numProperty; i++) { |
4086 | |
4087 | printf("\tProperty name - %s\n", propertyTuple[i].name); |
4088 | |
4089 | // Set property name from tuple name |
4090 | AIM_STRDUP(feaProblem->feaProperty[i].name, propertyTuple[i].name, aimInfo, status){ if (feaProblem->feaProperty[i].name != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 4090, __func__ , 1, "AIM_STRDUP: %s != NULL!", "feaProblem->feaProperty[i].name" ); goto cleanup; } feaProblem->feaProperty[i].name = EG_strdup (propertyTuple[i].name); if (feaProblem->feaProperty[i].name == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 4090, __func__, 2, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].name" , propertyTuple[i].name); goto cleanup; } }; |
4091 | |
4092 | // Get to property ID number from the attribute map |
4093 | status = get_mapAttrToIndexIndex(attrMap, feaProblem->feaProperty[i].name, &pidIndex); |
4094 | if (status != CAPS_SUCCESS0) { |
4095 | AIM_ERROR(aimInfo, "Tuple name '%s' not found in attribute map of PIDS!!!!\n", feaProblem->feaProperty[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4095, __func__ , "Tuple name '%s' not found in attribute map of PIDS!!!!\n", feaProblem->feaProperty[i].name); }; |
4096 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4097 | goto cleanup; |
4098 | } else { |
4099 | feaProblem->feaProperty[i].propertyID = pidIndex; |
4100 | } |
4101 | |
4102 | // Do we have a json string? |
4103 | if (strncmp(propertyTuple[i].value, "{", 1) == 0) { |
4104 | //printf("JSON String - %s\n",propertyTuple[i].value); |
4105 | |
4106 | /*! \page feaProperty |
4107 | * \section jsonStringProperty JSON String Dictionary |
4108 | * |
4109 | * If "Value" is JSON string dictionary |
4110 | * \if (MYSTRAN || NASTRAN) |
4111 | * (e.g. "Value" = {"shearMembraneRatio": 0.83, "bendingInertiaRatio": 1.0, "membraneThickness": 0.2, "propertyType": "Shell"}) |
4112 | * \endif |
4113 | * the following keywords ( = default values) may be used: |
4114 | * |
4115 | * |
4116 | * \if (MYSTRAN || NASTRAN) |
4117 | * <ul> |
4118 | * <li> <B>propertyType = No Default value</B> </li> <br> |
4119 | * Type of property to apply to a given capsGroup <c>Name</c>. Options: ConcentratedMass, Rod, |
4120 | * Bar, Shear, Shell, Composite, and Solid |
4121 | * </ul> |
4122 | * \elseif (MASSTRAN) |
4123 | * <ul> |
4124 | * <li> <B>propertyType = No Default value</B> </li> <br> |
4125 | * Type of property to apply to a given capsGroup <c>Name</c>. Options: ConcentratedMass, Shell |
4126 | * </ul> |
4127 | * \elseif ABAQUS |
4128 | * |
4129 | * Something else .... |
4130 | * |
4131 | * \elseif ASTROS |
4132 | * <ul> |
4133 | * <li> <B>propertyType = No Default value</B> </li> <br> |
4134 | * Type of property to apply to a give capsGroup <c>Name</c>. Options: ConcentratedMass, Rod, |
4135 | * Bar, Shear, Shell, Membrane, Composite, and Solid |
4136 | * </ul> |
4137 | * \endif |
4138 | * |
4139 | */ |
4140 | |
4141 | // Get property Type |
4142 | keyWord = "propertyType"; |
4143 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4144 | if (status == CAPS_SUCCESS0) { |
4145 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 4145, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
4146 | //{UnknownProperty, ConcentratedMass Rod, Bar, Shear, Shell, Composite, Solid} |
4147 | if (strcasecmp(keyValue, "\"ConcentratedMass\"") == 0) feaProblem->feaProperty[i].propertyType = ConcentratedMass; |
4148 | else if (strcasecmp(keyValue, "\"Rod\"") == 0) feaProblem->feaProperty[i].propertyType = Rod; |
4149 | else if (strcasecmp(keyValue, "\"Bar\"") == 0) feaProblem->feaProperty[i].propertyType = Bar; |
4150 | else if (strcasecmp(keyValue, "\"Shear\"") == 0) feaProblem->feaProperty[i].propertyType = Shear; |
4151 | else if (strcasecmp(keyValue, "\"Shell\"") == 0) feaProblem->feaProperty[i].propertyType = Shell; |
4152 | else if (strcasecmp(keyValue, "\"Membrane\"") == 0) feaProblem->feaProperty[i].propertyType = Membrane; |
4153 | else if (strcasecmp(keyValue, "\"Composite\"") == 0) feaProblem->feaProperty[i].propertyType = Composite; |
4154 | else if (strcasecmp(keyValue, "\"Solid\"") == 0) feaProblem->feaProperty[i].propertyType = Solid; |
4155 | else { |
4156 | AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are " "\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord , keyValue, propertyTuple[i].name); } |
4157 | "\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are " "\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord , keyValue, propertyTuple[i].name); } |
4158 | keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are " "\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord , keyValue, propertyTuple[i].name); } |
4159 | propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4159, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s, current options are " "\"Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord , keyValue, propertyTuple[i].name); }; |
4160 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4161 | |
4162 | status = CAPS_NOTFOUND-303; |
4163 | goto cleanup; |
4164 | } |
4165 | |
4166 | } else { |
4167 | AIM_ERROR(aimInfo, "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4169, __func__ , "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are " "\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n" , keyWord, propertyTuple[i].name); } |
4168 | "\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4169, __func__ , "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are " "\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n" , keyWord, propertyTuple[i].name); } |
4169 | propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4169, __func__ , "\tNo \"%s\" specified for Property tuple %s, this mandatory! Current options are " "\"ConcentratedMass, Rod, Bar, Shear, Shell, Composite, and Solid\"\n" , keyWord, propertyTuple[i].name); }; |
4170 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4171 | |
4172 | status = CAPS_NOTFOUND-303; |
4173 | goto cleanup; |
4174 | } |
4175 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4176 | |
4177 | /*! \page feaProperty |
4178 | * |
4179 | * \if (MYSTRAN || NASTRAN) |
4180 | * <ul> |
4181 | * <li> <B>material = "Material Name" (\ref feaMaterial) </B> </li> <br> |
4182 | * "Material Name" from \ref feaMaterial to use for property. If no material is set the first material |
4183 | * created will be used |
4184 | * </ul> |
4185 | * \elseif ABAQUS |
4186 | * |
4187 | * Something else .... |
4188 | * |
4189 | * \elseif ASTROS |
4190 | * <ul> |
4191 | * <li> <B>material = `Material Name' (\ref feaMaterial) </B> </li> <br> |
4192 | * `Material Name' from \ref feaMaterial to use for property. If no material is set the first material |
4193 | * created will be used |
4194 | * </ul> |
4195 | * \endif |
4196 | */ |
4197 | keyWord = "material"; |
4198 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4199 | if (status == CAPS_SUCCESS0) { |
4200 | |
4201 | found = (int) false0; |
4202 | for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) { |
4203 | |
4204 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4205 | tempString = string_removeQuotation(keyValue); |
4206 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 4206, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
4207 | |
4208 | if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) { |
4209 | feaProblem->feaProperty[i].materialID = feaProblem->feaMaterial[matIndex].materialID; |
4210 | |
4211 | AIM_STRDUP(feaProblem->feaProperty[i].materialName, feaProblem->feaMaterial[matIndex].name, aimInfo, status){ if (feaProblem->feaProperty[i].materialName != ((void*)0 )) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 4211 , __func__, 1, "AIM_STRDUP: %s != NULL!", "feaProblem->feaProperty[i].materialName" ); goto cleanup; } feaProblem->feaProperty[i].materialName = EG_strdup(feaProblem->feaMaterial[matIndex].name); if ( feaProblem->feaProperty[i].materialName == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 4211, __func__ , 2, "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].materialName" , feaProblem->feaMaterial[matIndex].name); goto cleanup; } }; |
4212 | feaProblem->feaProperty[i].materialName[strlen(feaProblem->feaMaterial[matIndex].name)] = '\0'; |
4213 | |
4214 | found = (int) true1; |
4215 | break; |
4216 | } |
4217 | } |
4218 | |
4219 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4220 | |
4221 | if (found == (int) false0) { |
4222 | AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4224, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); } |
4223 | keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4224, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); } |
4224 | propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4224, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); }; |
4225 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4226 | status = CAPS_NOTFOUND-303; |
4227 | goto cleanup; |
4228 | } |
4229 | |
4230 | } else { |
4231 | |
4232 | if (feaProblem->feaProperty[i].propertyType != ConcentratedMass && |
4233 | feaProblem->feaProperty[i].propertyType != Composite) { |
4234 | printf("\tNo \"%s\" specified for Property tuple %s, defaulting to an index of 1\n", keyWord, |
4235 | propertyTuple[i].name); |
4236 | } |
4237 | |
4238 | feaProblem->feaProperty[i].materialID = 1; |
4239 | if (feaProblem->numMaterial > 0) { |
4240 | AIM_STRDUP(feaProblem->feaProperty[i].materialName, feaProblem->feaMaterial[0].name, aimInfo, status){ if (feaProblem->feaProperty[i].materialName != ((void*)0 )) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 4240 , __func__, 1, "AIM_STRDUP: %s != NULL!", "feaProblem->feaProperty[i].materialName" ); goto cleanup; } feaProblem->feaProperty[i].materialName = EG_strdup(feaProblem->feaMaterial[0].name); if (feaProblem ->feaProperty[i].materialName == ((void*)0)) { status = -4 ; aim_status(aimInfo, status, "feaUtils.c", 4240, __func__, 2 , "AIM_STRDUP: %s %s", "feaProblem->feaProperty[i].materialName" , feaProblem->feaMaterial[0].name); goto cleanup; } }; |
4241 | } |
4242 | } |
4243 | |
4244 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4245 | |
4246 | // Fill up properties /// |
4247 | |
4248 | // Rods |
4249 | /*! \page feaProperty |
4250 | * |
4251 | * \if (MYSTRAN || NASTRAN) |
4252 | * <ul> |
4253 | * <li> <B>crossSecArea = 0.0</B> </li> <br> |
4254 | * Cross sectional area. |
4255 | * </ul> |
4256 | * \elseif ABAQUS |
4257 | * |
4258 | * Something else .... |
4259 | * |
4260 | * \elseif ASTROS |
4261 | * <ul> |
4262 | * <li> <B>crossSecArea = 0.0</B> </li> <br> |
4263 | * Cross sectional area. |
4264 | * </ul> |
4265 | * \endif |
4266 | */ |
4267 | keyWord = "crossSecArea"; |
4268 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4269 | if (status == CAPS_SUCCESS0) { |
4270 | |
4271 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].crossSecArea); |
4272 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4272 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4273 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4274 | } |
4275 | |
4276 | /*! \page feaProperty |
4277 | * |
4278 | * \if (MYSTRAN || NASTRAN) |
4279 | * <ul> |
4280 | * <li> <B>torsionalConst = 0.0</B> </li> <br> |
4281 | * Torsional constant. |
4282 | * </ul> |
4283 | * \elseif ABAQUS |
4284 | * |
4285 | * Something else .... |
4286 | * |
4287 | * \elseif ASTROS |
4288 | * <ul> |
4289 | * <li> <B>torsionalConst = 0.0</B> </li> <br> |
4290 | * Torsional constant. |
4291 | * </ul> |
4292 | * \endif |
4293 | */ |
4294 | keyWord = "torsionalConst"; |
4295 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4296 | if (status == CAPS_SUCCESS0) { |
4297 | |
4298 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].torsionalConst); |
4299 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4299 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4300 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4301 | } |
4302 | |
4303 | /*! \page feaProperty |
4304 | * |
4305 | * \if (MYSTRAN || NASTRAN) |
4306 | * <ul> |
4307 | * <li> <B>torsionalStressReCoeff = 0.0</B> </li> <br> |
4308 | * Torsional stress recovery coefficient. |
4309 | * </ul> |
4310 | * \elseif ABAQUS |
4311 | * |
4312 | * Something else .... |
4313 | * |
4314 | * \elseif ASTROS |
4315 | * <ul> |
4316 | * <li> <B>torsionalStressReCoeff = 0.0</B> </li> <br> |
4317 | * Torsional stress recovery coefficient. |
4318 | * </ul> |
4319 | * \endif |
4320 | */ |
4321 | keyWord = "torsionalStressReCoeff"; |
4322 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4323 | if (status == CAPS_SUCCESS0) { |
4324 | |
4325 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].torsionalStressReCoeff); |
4326 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4326 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4327 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4328 | } |
4329 | |
4330 | /*! \page feaProperty |
4331 | * |
4332 | * \if (HSM) |
4333 | * <ul> |
4334 | * <li> <B>massPerLength = 0.0</B> </li> <br> |
4335 | * Mass per unit length. |
4336 | * </ul> |
4337 | * |
4338 | * \elseif ( MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
4339 | * <ul> |
4340 | * <li> <B>massPerLength = 0.0</B> </li> <br> |
4341 | * Non-structural mass per unit length. |
4342 | * </ul> |
4343 | * |
4344 | * \endif |
4345 | */ |
4346 | keyWord = "massPerLength"; |
4347 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4348 | if (status == CAPS_SUCCESS0) { |
4349 | |
4350 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].massPerLength); |
4351 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4351 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4352 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4353 | } |
4354 | |
4355 | // Bar - see rod for additional variables |
4356 | |
4357 | /*! \page feaProperty |
4358 | * |
4359 | * \if (MYSTRAN || NASTRAN) |
4360 | * <ul> |
4361 | * <li> <B>zAxisInertia = 0.0</B> </li> <br> |
4362 | * Section moment of inertia about the element z-axis. |
4363 | * </ul> |
4364 | * \elseif ABAQUS |
4365 | * |
4366 | * Something else .... |
4367 | * |
4368 | * \elseif ASTROS |
4369 | * <ul> |
4370 | * <li> <B>zAxisInertia = 0.0</B> </li> <br> |
4371 | * Section moment of inertia about the element z-axis. |
4372 | * </ul> |
4373 | * \endif |
4374 | */ |
4375 | keyWord = "zAxisInertia"; |
4376 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4377 | if (status == CAPS_SUCCESS0) { |
4378 | |
4379 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].zAxisInertia); |
4380 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4380 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4381 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4382 | } |
4383 | |
4384 | /*! \page feaProperty |
4385 | * |
4386 | * \if (MYSTRAN || NASTRAN) |
4387 | * <ul> |
4388 | * <li> <B>yAxisInertia = 0.0</B> </li> <br> |
4389 | * Section moment of inertia about the element y-axis. |
4390 | * </ul> |
4391 | * \elseif ABAQUS |
4392 | * |
4393 | * Something else .... |
4394 | * |
4395 | * \elseif ASTROS |
4396 | * <ul> |
4397 | * <li> <B>yAxisInertia = 0.0</B> </li> <br> |
4398 | * Section moment of inertia about the element y-axis. |
4399 | * </ul> |
4400 | * \endif |
4401 | */ |
4402 | keyWord = "yAxisInertia"; |
4403 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4404 | if (status == CAPS_SUCCESS0) { |
4405 | |
4406 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].yAxisInertia); |
4407 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4407 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4408 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4409 | } |
4410 | |
4411 | /*! \page feaProperty |
4412 | * |
4413 | * \if (MYSTRAN || NASTRAN) |
4414 | * <ul> |
4415 | * <li> <B>yCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br> |
4416 | * Element y-coordinates, in the bar cross-section, of four points at which to recover stresses |
4417 | * </ul> |
4418 | * \elseif ABAQUS |
4419 | * |
4420 | * Something else .... |
4421 | * |
4422 | * \elseif ASTROS |
4423 | * <ul> |
4424 | * <li> <B>yCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br> |
4425 | * Element y-coordinates, in the bar cross-section, of four points at which to recover stresses |
4426 | * </ul> |
4427 | * \endif |
4428 | */ |
4429 | keyWord = "yCoords"; |
4430 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4431 | if (status == CAPS_SUCCESS0) { |
4432 | status = string_toDoubleArray(keyValue, |
4433 | (int) sizeof(feaProblem->feaProperty[i].yCoords)/sizeof(double), |
4434 | feaProblem->feaProperty[i].yCoords); |
4435 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4435 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4436 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4437 | } |
4438 | |
4439 | /*! \page feaProperty |
4440 | * |
4441 | * \if (MYSTRAN || NASTRAN) |
4442 | * <ul> |
4443 | * <li> <B>zCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br> |
4444 | * Element z-coordinates, in the bar cross-section, of four points at which to recover stresses |
4445 | * </ul> |
4446 | * \elseif ABAQUS |
4447 | * |
4448 | * Something else .... |
4449 | * |
4450 | * \elseif ASTROS |
4451 | * <ul> |
4452 | * <li> <B>zCoords[4] = [0.0, 0.0, 0.0, 0.0]</B> </li> <br> |
4453 | * Element z-coordinates, in the bar cross-section, of four points at which to recover stresses |
4454 | * </ul> |
4455 | * \endif |
4456 | */ |
4457 | keyWord = "zCoords"; |
4458 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4459 | if (status == CAPS_SUCCESS0) { |
4460 | status = string_toDoubleArray(keyValue, |
4461 | (int) sizeof(feaProblem->feaProperty[i].zCoords)/sizeof(double), |
4462 | feaProblem->feaProperty[i].zCoords); |
4463 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4463 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4464 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4465 | } |
4466 | |
4467 | /*! \page feaProperty |
4468 | * |
4469 | * \if (MYSTRAN || NASTRAN) |
4470 | * <ul> |
4471 | * <li> <B>areaShearFactors[2] = [0.0, 0.0]</B> </li> <br> |
4472 | * Area factors for shear. |
4473 | * </ul> |
4474 | * \elseif ABAQUS |
4475 | * |
4476 | * Something else .... |
4477 | * |
4478 | * \elseif ASTROS |
4479 | * <ul> |
4480 | * <li> <B>areaShearFactors[2] = [0.0, 0.0]</B> </li> <br> |
4481 | * Area factors for shear. |
4482 | * </ul> |
4483 | * \endif |
4484 | */ |
4485 | keyWord = "areaShearFactors"; |
4486 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4487 | if (status == CAPS_SUCCESS0) { |
4488 | status = string_toDoubleArray(keyValue, |
4489 | (int) sizeof(feaProblem->feaProperty[i].areaShearFactors)/sizeof(double), |
4490 | feaProblem->feaProperty[i].areaShearFactors); |
4491 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4491 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4492 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4493 | } |
4494 | |
4495 | /*! \page feaProperty |
4496 | * |
4497 | * \if (MYSTRAN || NASTRAN) |
4498 | * <ul> |
4499 | * <li> <B>crossProductInertia = 0.0</B> </li> <br> |
4500 | * Section cross-product of inertia. |
4501 | * </ul> |
4502 | * \elseif ABAQUS |
4503 | * |
4504 | * Something else .... |
4505 | * |
4506 | * \elseif ASTROS |
4507 | * <ul> |
4508 | * <li> <B>crossProductInertia = 0.0</B> </li> <br> |
4509 | * Section cross-product of inertia. |
4510 | * </ul> |
4511 | * \endif |
4512 | */ |
4513 | keyWord = "crossProductInertia"; |
4514 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4515 | if (status == CAPS_SUCCESS0) { |
4516 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].crossProductInertia); |
4517 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4517 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4518 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4519 | } |
4520 | |
4521 | /*! \page feaProperty |
4522 | * |
4523 | * \if (MYSTRAN || NASTRAN ) |
4524 | * <ul> |
4525 | * <li> <B>crossSecType = NULL</B> </li> <br> |
4526 | * Cross-section type. Must be one of following character variables: BAR, BOX, BOX1, |
4527 | * CHAN, CHAN1, CHAN2, CROSS, H, HAT, HEXA, I, I1, ROD, T, T1, T2, TUBE, or Z. |
4528 | * </ul> |
4529 | * \elseif ASTROS |
4530 | * <ul> |
4531 | * <li> <B>crossSecType = NULL</B> </li> <br> |
4532 | * Cross-section type. Must be one of following character variables: I, T, BOX, BAR, |
4533 | * TUBE, ROD, HAT, or GBOX. |
4534 | * </ul> |
4535 | * \endif |
4536 | */ |
4537 | keyWord = "crossSecType"; |
4538 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4539 | if (status == CAPS_SUCCESS0) { |
4540 | feaProblem->feaProperty[i].crossSecType = string_removeQuotation(keyValue); |
4541 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4542 | } |
4543 | |
4544 | /*! \page feaProperty |
4545 | * |
4546 | * \if (MYSTRAN || NASTRAN || ASTROS) |
4547 | * <ul> |
4548 | * <li> <B>crossSecDimension = [0,0,0,....]</B> </li> <br> |
4549 | * Cross-sectional dimensions (length of array is dependent on the "crossSecType"). Max |
4550 | * supported length array is 10! |
4551 | * </ul> |
4552 | * \endif |
4553 | */ |
4554 | keyWord = "crossSecDimension"; |
4555 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4556 | if (status == CAPS_SUCCESS0) { |
4557 | status = string_toDoubleArray(keyValue, |
4558 | (int) sizeof(feaProblem->feaProperty[i].crossSecDimension)/sizeof(double), |
4559 | feaProblem->feaProperty[i].crossSecDimension); |
4560 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4560 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4561 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4562 | } |
4563 | |
4564 | |
4565 | /* UNDOCUMENTED orientation vector of bars - MAY be changed in the future without warning |
4566 | */ |
4567 | keyWord = "orientationVec"; |
4568 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4569 | if (status == CAPS_SUCCESS0) { |
4570 | status = string_toDoubleArray(keyValue, |
4571 | (int) sizeof(feaProblem->feaProperty[i].orientationVec)/sizeof(double), |
4572 | feaProblem->feaProperty[i].orientationVec); |
4573 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4573 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4574 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4575 | } |
4576 | |
4577 | |
4578 | // Shear |
4579 | |
4580 | // Shell |
4581 | |
4582 | /*! \page feaProperty |
4583 | * |
4584 | * \if (MYSTRAN || NASTRAN || MASSTRAN) |
4585 | * <ul> |
4586 | * <li> <B>membraneThickness = 0.0</B> </li> <br> |
4587 | * Membrane thickness. |
4588 | * </ul> |
4589 | * \elseif ABAQUS |
4590 | * |
4591 | * Something else .... |
4592 | * |
4593 | * \elseif ASTROS |
4594 | * <ul> |
4595 | * <li> <B>membraneThickness = 0.0</B> </li> <br> |
4596 | * Membrane thickness. |
4597 | * </ul> |
4598 | * \endif |
4599 | */ |
4600 | keyWord = "membraneThickness"; |
4601 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4602 | if (status == CAPS_SUCCESS0) { |
4603 | if ( feaUnits->length != NULL((void*)0) ) { |
4604 | status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->length, &feaProblem->feaProperty[i].membraneThickness); |
4605 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4605 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4606 | } else { |
4607 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].membraneThickness); |
4608 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4608 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4609 | } |
4610 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4611 | } |
4612 | |
4613 | |
4614 | /*! \page feaProperty |
4615 | * |
4616 | * \if (MYSTRAN || NASTRAN) |
4617 | * <ul> |
4618 | * <li> <B>bendingInertiaRatio = 1.0</B> </li> <br> |
4619 | * Ratio of actual bending moment inertia to the bending inertia of a solid plate of thickness "membraneThickness" |
4620 | * </ul> |
4621 | * \elseif ABAQUS |
4622 | * |
4623 | * Something else .... |
4624 | * |
4625 | * \elseif ASTROS |
4626 | * <ul> |
4627 | * <li> <B>bendingInertiaRatio = 1.0</B> </li> <br> |
4628 | * Ratio of actual bending moment inertia to the bending inertia of a solid plate of thickness "membraneThickness" |
4629 | * </ul> |
4630 | * \endif |
4631 | */ |
4632 | keyWord = "bendingInertiaRatio"; |
4633 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4634 | if (status == CAPS_SUCCESS0) { |
4635 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].bendingInertiaRatio); |
4636 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4636 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4637 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4638 | } |
4639 | |
4640 | |
4641 | /*! \page feaProperty |
4642 | * |
4643 | * \if (MYSTRAN || NASTRAN) |
4644 | * <ul> |
4645 | * <li> <B>shearMembraneRatio = 5.0/6.0</B> </li> <br> |
4646 | * Ratio shear thickness to membrane thickness. |
4647 | * </ul> |
4648 | * \elseif ABAQUS |
4649 | * |
4650 | * Something else .... |
4651 | * |
4652 | * \elseif ASTROS |
4653 | * <ul> |
4654 | * <li> <B>shearMembraneRatio = 5.0/6.0</B> </li> <br> |
4655 | * Ratio shear thickness to membrane thickness. |
4656 | * </ul> |
4657 | * \endif |
4658 | */ |
4659 | keyWord = "shearMembraneRatio"; |
4660 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4661 | if (status == CAPS_SUCCESS0) { |
4662 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].shearMembraneRatio); |
4663 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4663 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4664 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4665 | } |
4666 | |
4667 | /*! \page feaProperty |
4668 | * |
4669 | * \if (MYSTRAN || NASTRAN) |
4670 | * <ul> |
4671 | * <li> <B>materialBending = "Material Name" (\ref feaMaterial)</B> </li> <br> |
4672 | * "Material Name" from \ref feaMaterial to use for property bending. If no material is given and |
4673 | * "bendingInertiaRatio" is greater than 0, the material name provided in "material" is used. |
4674 | * </ul> |
4675 | * \elseif ABAQUS |
4676 | * |
4677 | * Something else .... |
4678 | * |
4679 | * \elseif ASTROS |
4680 | * <ul> |
4681 | * <li> <B>materialBending = "Material Name" (\ref feaMaterial)</B> </li> <br> |
4682 | * "Material Name" from \ref feaMaterial to use for property bending. |
4683 | * </ul> |
4684 | * \endif |
4685 | */ |
4686 | keyWord = "materialBending"; // Shell specific materials |
4687 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4688 | if (status == CAPS_SUCCESS0) { |
4689 | |
4690 | found = (int) false0; |
4691 | for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) { |
4692 | |
4693 | if (tempString != NULL((void*)0)) EG_free(tempString); |
4694 | tempString = string_removeQuotation(keyValue); |
4695 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 4695, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
4696 | |
4697 | if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) { |
4698 | feaProblem->feaProperty[i].materialBendingID = feaProblem->feaMaterial[matIndex].materialID; |
4699 | found = (int) true1; |
4700 | |
4701 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4702 | break; |
4703 | } |
4704 | |
4705 | } |
4706 | |
4707 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4708 | |
4709 | if (found == (int) false0) { |
4710 | AIM_ERROR(aimInfo, "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4712, __func__ , "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); } |
4711 | keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4712, __func__ , "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); } |
4712 | propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4712, __func__ , "\tUnrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); }; |
4713 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4714 | status = CAPS_NOTFOUND-303; |
4715 | goto cleanup; |
4716 | } |
4717 | |
4718 | } else { // Don't default to anything - yet |
4719 | |
4720 | /* |
4721 | printf("No \"%s\" specified for Property tuple %s which is a shell element, " |
4722 | " no bending material will be specified\n", keyWord, |
4723 | propertyTuple[i].name); |
4724 | |
4725 | feaProblem->feaProperty[i].materialBendingID = 0; |
4726 | */ |
4727 | |
4728 | if (feaProblem->feaProperty[i].bendingInertiaRatio > 0) { |
4729 | |
4730 | feaProblem->feaProperty[i].materialBendingID = feaProblem->feaProperty[i].materialID; |
4731 | } |
4732 | } |
4733 | |
4734 | /*! \page feaProperty |
4735 | * |
4736 | * \if (MYSTRAN || NASTRAN) |
4737 | * <ul> |
4738 | * <li> <B>materialShear = "Material Name" (\ref feaMaterial)</B> </li> <br> |
4739 | * "Material Name" from \ref feaMaterial to use for property shear. If no material is given and |
4740 | * "shearMembraneRatio" is greater than 0, the material name provided in "material" is used. |
4741 | * </ul> |
4742 | * \elseif ABAQUS |
4743 | * |
4744 | * Something else .... |
4745 | * |
4746 | * \elseif ASTROS |
4747 | * <ul> |
4748 | * <li> <B>materialShear = "Material Name" (\ref feaMaterial)</B> </li> <br> |
4749 | * "Material Name" from \ref feaMaterial to use for property shear. |
4750 | * </ul> |
4751 | * \endif |
4752 | */ |
4753 | keyWord = "materialShear"; // Shell specific materials |
4754 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4755 | if (status == CAPS_SUCCESS0) { |
4756 | |
4757 | found = (int) false0; |
4758 | for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) { |
4759 | |
4760 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4761 | tempString = string_removeQuotation(keyValue); |
4762 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 4762, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
4763 | |
4764 | if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) { |
4765 | feaProblem->feaProperty[i].materialShearID = feaProblem->feaMaterial[matIndex].materialID; |
4766 | found = (int) true1; |
4767 | |
4768 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4769 | break; |
4770 | } |
4771 | |
4772 | } |
4773 | |
4774 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4775 | |
4776 | if (found == (int) false0) { |
4777 | AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4779, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); } |
4778 | keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4779, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); } |
4779 | propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4779, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyWord, keyValue, propertyTuple[i].name); }; |
4780 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4781 | status = CAPS_NOTFOUND-303; |
4782 | goto cleanup; |
4783 | } |
4784 | |
4785 | } else { |
4786 | /* |
4787 | printf("No \"%s\" specified for Property tuple %s which is a shell element, " |
4788 | " no shear material will be specified\n", keyWord, |
4789 | propertyTuple[i].name); |
4790 | |
4791 | feaProblem->feaProperty[i].materialShearID = 0; |
4792 | */ |
4793 | |
4794 | if (feaProblem->feaProperty[i].shearMembraneRatio > 0) { |
4795 | feaProblem->feaProperty[i].materialShearID = feaProblem->feaProperty[i].materialID; |
4796 | } |
4797 | } |
4798 | |
4799 | /*! \page feaProperty |
4800 | * |
4801 | * \if (HSM || MASSTRAN) |
4802 | * <ul> |
4803 | * <li> <B>massPerArea = 0.0</B> </li> <br> |
4804 | * Mass per unit area. |
4805 | * </ul> |
4806 | * \elseif (MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
4807 | * |
4808 | * <ul> |
4809 | * <li> <B>massPerArea = 0.0</B> </li> <br> |
4810 | * Non-structural mass per unit area. |
4811 | * </ul> |
4812 | * \endif |
4813 | */ |
4814 | keyWord = "massPerArea"; |
4815 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4816 | if (status == CAPS_SUCCESS0) { |
4817 | if ( feaUnits->densityArea != NULL((void*)0) ) { |
4818 | status = string_toDoubleUnits(aimInfo, keyValue, feaUnits->densityArea, &feaProblem->feaProperty[i].massPerArea); |
4819 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4819 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4820 | } else { |
4821 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].massPerArea); |
4822 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4822 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4823 | } |
4824 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4825 | } |
4826 | |
4827 | /*! \page feaProperty |
4828 | * |
4829 | * \if (MYSTRAN || NASTRAN || ASTROS) |
4830 | * <ul> |
4831 | * <li> <B>zOffsetRel = 0.0</B> </li> <br> |
4832 | * Relative offset from the surface of grid points to the element reference |
4833 | * plane as a percentage of the thickness. zOffSet = thickness*zOffsetRel/100 |
4834 | * |
4835 | * </ul> |
4836 | * \endif |
4837 | */ |
4838 | keyWord = "zOffsetRel"; |
4839 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4840 | if (status == CAPS_SUCCESS0) { |
4841 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].zOffsetRel); |
4842 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4842 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4843 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4844 | } |
4845 | |
4846 | // Composite |
4847 | |
4848 | /*! \page feaProperty |
4849 | * |
4850 | * \if (MYSTRAN || NASTRAN) |
4851 | * <ul> |
4852 | * <li> <B>compositeMaterial = "no default" </B> </li> <br> |
4853 | * List of "Material Name"s, ["Material Name -1", "Material Name -2", ...], from \ref feaMaterial to use for composites. |
4854 | * </ul> |
4855 | * \elseif ABAQUS |
4856 | * |
4857 | * Something else .... |
4858 | * |
4859 | * \elseif ASTROS |
4860 | * <ul> |
4861 | * <li> <B>compositeMaterial = "no default" </B> </li> <br> |
4862 | * List of "Material Name"s, ["Material Name -1", "Material Name -2", ...], from \ref feaMaterial to use for composites. |
4863 | * </ul> |
4864 | * \endif |
4865 | */ |
4866 | keyWord = "compositeMaterial"; |
4867 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4868 | if (status == CAPS_SUCCESS0) { |
4869 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 4869, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
4870 | |
4871 | status = string_toStringDynamicArray(keyValue, &feaProblem->feaProperty[i].numPly, &tempStringArray); |
4872 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4872 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4873 | |
4874 | AIM_ALLOC(feaProblem->feaProperty[i].compositeMaterialID, feaProblem->feaProperty[i].numPly, int, aimInfo, status){ if (feaProblem->feaProperty[i].compositeMaterialID != (( void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 4874, __func__, 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaProperty[i].compositeMaterialID" ); goto cleanup; } size_t memorysize = feaProblem->feaProperty [i].numPly; feaProblem->feaProperty[i].compositeMaterialID = (int *) EG_alloc(memorysize*sizeof(int)); if (feaProblem-> feaProperty[i].compositeMaterialID == ((void*)0)) { status = - 4; aim_status(aimInfo, status, "feaUtils.c", 4874, __func__, 3 , "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaProperty[i].compositeMaterialID" , memorysize, "int"); goto cleanup; } }; |
4875 | |
4876 | for (j = 0; j < feaProblem->feaProperty[i].numPly; j++) { |
4877 | found = (int) false0; |
4878 | for (matIndex = 0; matIndex < feaProblem->numMaterial; matIndex++ ) { |
4879 | |
4880 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4881 | tempString = string_removeQuotation(tempStringArray[j]); |
4882 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 4882, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
4883 | |
4884 | if (strcasecmp(feaProblem->feaMaterial[matIndex].name, tempString) == 0) { |
4885 | feaProblem->feaProperty[i].compositeMaterialID[j] = feaProblem->feaMaterial[matIndex].materialID; |
4886 | found = (int) true1; |
4887 | break; |
4888 | } |
4889 | |
4890 | } |
4891 | |
4892 | if (found == (int) false0) { |
4893 | AIM_ERROR(aimInfo, "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n", keyValue,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4895, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyValue, keyWord, propertyTuple[i].name); } |
4894 | keyWord,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4895, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyValue, keyWord, propertyTuple[i].name); } |
4895 | propertyTuple[i].name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 4895, __func__ , "Unrecognized \"%s\" specified (%s) for Property tuple %s. No match in Material tuple\n" , keyValue, keyWord, propertyTuple[i].name); }; |
4896 | |
4897 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4898 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4899 | |
4900 | (void) string_freeArray(feaProblem->feaProperty[i].numPly, &tempStringArray); |
4901 | |
4902 | status = CAPS_NOTFOUND-303; |
4903 | goto cleanup; |
4904 | } |
4905 | |
4906 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
4907 | } |
4908 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4909 | status = string_freeArray(feaProblem->feaProperty[i].numPly, &tempStringArray); |
4910 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4910 , __func__, 0); goto cleanup; }; |
4911 | } |
4912 | |
4913 | /*! \page feaProperty |
4914 | * |
4915 | * \if (MYSTRAN || NASTRAN) |
4916 | * <ul> |
4917 | * <li> <B>shearBondAllowable = 0.0 </B> </li> <br> |
4918 | * Allowable interlaminar shear stress. |
4919 | * </ul> |
4920 | * \elseif ABAQUS |
4921 | * |
4922 | * Something else .... |
4923 | * |
4924 | * \elseif ASTROS |
4925 | * <ul> |
4926 | * <li> <B>shearBondAllowable = 0.0 </B> </li> <br> |
4927 | * Allowable interlaminar shear stress. |
4928 | * </ul> |
4929 | * \endif |
4930 | */ |
4931 | keyWord = "shearBondAllowable"; |
4932 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4933 | if (status == CAPS_SUCCESS0) { |
4934 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].compositeShearBondAllowable); |
4935 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4935 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4936 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4937 | } |
4938 | |
4939 | /*! \page feaProperty |
4940 | * |
4941 | * \if (MYSTRAN || NASTRAN) |
4942 | * <ul> |
4943 | * <li> <B>symmetricLaminate = False </B> </li> <br> |
4944 | * Symmetric lamination option. True- SYM only half the plies are specified, for odd number plies 1/2 thickness |
4945 | * of center ply is specified with the first ply being the bottom ply in the stack, default (False) all plies specified. |
4946 | * </ul> |
4947 | * \elseif (ASTROS) |
4948 | * <ul> |
4949 | * <li> <B>symmetricLaminate = False </B> </li> <br> |
4950 | * Symmetric lamination option. If "True" only half the plies are specified (the plies will be repeated in |
4951 | * reverse order internally in the PCOMP card). For an odd number of plies, the 1/2 thickness |
4952 | * of the center ply is specified with the first ply being the bottom ply in the stack, default (False) all plies specified. |
4953 | * </ul> |
4954 | * \endif |
4955 | */ |
4956 | keyWord = "symmetricLaminate"; |
4957 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4958 | if (status == CAPS_SUCCESS0) { |
4959 | status = string_toBoolean(keyValue, &feaProblem->feaProperty[i].compositeSymmetricLaminate); |
4960 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4960 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4961 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4962 | } |
4963 | |
4964 | /*! \page feaProperty |
4965 | * |
4966 | * \if (MYSTRAN || NASTRAN) |
4967 | * <ul> |
4968 | * <li> <B>compositeFailureTheory = "(no default)" </B> </li> <br> |
4969 | * Composite failure theory. Options: "HILL", "HOFF", "TSAI", and "STRN" |
4970 | * </ul> |
4971 | * \elseif ABAQUS |
4972 | * |
4973 | * Something else .... |
4974 | * |
4975 | * \elseif ASTROS |
4976 | * <ul> |
4977 | * <li> <B>compositeFailureTheory = "(no default)" </B> </li> <br> |
4978 | * Composite failure theory. |
4979 | * </ul> |
4980 | * \endif |
4981 | */ |
4982 | keyWord = "compositeFailureTheory"; |
4983 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
4984 | if (status == CAPS_SUCCESS0) { |
4985 | feaProblem->feaProperty[i].compositeFailureTheory = string_removeQuotation(keyValue); |
4986 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 4986 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
4987 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
4988 | } |
4989 | |
4990 | /*! \page feaProperty |
4991 | * |
4992 | * \if (MYSTRAN || NASTRAN) |
4993 | * <ul> |
4994 | * <li> <B>compositeThickness = (no default) </B> </li> <br> |
4995 | * List of composite thickness for each layer (e.g. [1.2, 4.0, 3.0]). If the length of this list doesn't match the length |
4996 | * of the "compositeMaterial" list, the list is either truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] |
4997 | * in which case the last thickness provided is repeated. |
4998 | * </ul> |
4999 | * \elseif ABAQUS |
5000 | * |
5001 | * Something else .... |
5002 | * |
5003 | * \elseif ASTROS |
5004 | * <ul> |
5005 | * <li> <B>compositeThickness = (no default) </B> </li> <br> |
5006 | * List of composite thickness for each layer (e.g. [1.2, 4.0, 3.0]). If the length of this list doesn't match the length |
5007 | * of the "compositeMaterial" list, the list is either truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] |
5008 | * in which case the last thickness provided is repeated. |
5009 | * </ul> |
5010 | * \endif |
5011 | */ |
5012 | keyWord = "compositeThickness"; |
5013 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
5014 | if (status == CAPS_SUCCESS0) { |
5015 | status = string_toDoubleDynamicArray(keyValue, &tempInteger, |
5016 | &feaProblem->feaProperty[i].compositeThickness); |
5017 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5017 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
5018 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
5019 | |
5020 | if (tempInteger < feaProblem->feaProperty[i].numPly) { |
5021 | |
5022 | printf("\tThe number of thicknesses provided does not match the number of materials for the composite. " |
5023 | "The last thickness will be repeated %d times\n", feaProblem->feaProperty[i].numPly - tempInteger); |
5024 | |
5025 | AIM_REALL(feaProblem->feaProperty[i].compositeThickness,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeThickness = (double *) EG_reall( feaProblem->feaProperty[i].compositeThickness, memorysize* sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5026, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness" , memorysize, "double"); goto cleanup; } } |
5026 | feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeThickness = (double *) EG_reall( feaProblem->feaProperty[i].compositeThickness, memorysize* sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5026, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness" , memorysize, "double"); goto cleanup; } }; |
5027 | |
5028 | for (j = 0; j < feaProblem->feaProperty[i].numPly - tempInteger; j++) { |
5029 | |
5030 | feaProblem->feaProperty[i].compositeThickness[j+tempInteger] = feaProblem->feaProperty[i].compositeThickness[tempInteger-1]; |
5031 | } |
5032 | } |
5033 | |
5034 | if (tempInteger > feaProblem->feaProperty[i].numPly) { |
5035 | |
5036 | printf("\tThe number of thicknesses provided does not match the number of materials for the composite. " |
5037 | "The last %d thicknesses will be not be used\n", tempInteger -feaProblem->feaProperty[i].numPly); |
5038 | |
5039 | AIM_REALL(feaProblem->feaProperty[i].compositeThickness,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeThickness = (double *) EG_reall( feaProblem->feaProperty[i].compositeThickness, memorysize* sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5040, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness" , memorysize, "double"); goto cleanup; } } |
5040 | feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeThickness = (double *) EG_reall( feaProblem->feaProperty[i].compositeThickness, memorysize* sizeof(double)); if (feaProblem->feaProperty[i].compositeThickness == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5040, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeThickness" , memorysize, "double"); goto cleanup; } }; |
5041 | } |
5042 | } else { |
5043 | |
5044 | if (feaProblem->feaProperty[i].numPly != 0 && |
5045 | feaProblem->feaProperty[i].propertyType == Composite) { |
5046 | |
5047 | AIM_ERROR(aimInfo, "\"compositeMaterial\" have been set but no thicknesses (\"compositeThickness\") provided!!!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5047, __func__ , "\"compositeMaterial\" have been set but no thicknesses (\"compositeThickness\") provided!!!" ); }; |
5048 | status = CAPS_BADVALUE-311; |
5049 | goto cleanup; |
5050 | } |
5051 | } |
5052 | |
5053 | /*! \page feaProperty |
5054 | * |
5055 | * \if (MYSTRAN || NASTRAN) |
5056 | * <ul> |
5057 | * <li> <B>compositeOrientation = (no default) </B> </li> <br> |
5058 | * List of composite orientations (angle relative element material axis) for each layer (eg. [5.0, 10.0, 30.0]). |
5059 | * If the length of this list doesn't match the length of the "compositeMaterial" list, the list is either |
5060 | * truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] in which case |
5061 | * the last orientation provided is repeated. |
5062 | * </ul> |
5063 | * \elseif ABAQUS |
5064 | * |
5065 | * Something else .... |
5066 | * |
5067 | * \elseif ASTROS |
5068 | * <ul> |
5069 | * <li> <B>compositeOrientation = (no default) </B> </li> <br> |
5070 | * List of composite orientations (angle relative element material axis) for each layer (eg. [5.0, 10.0, 30.0]). |
5071 | * If the length of this list doesn't match the length of the "compositeMaterial" list, the list is either |
5072 | * truncated [ >length("compositeMaterial")] or expanded [ <length("compositeMaterial")] in which case |
5073 | * the last orientation provided is repeated. |
5074 | * </ul> |
5075 | * \endif |
5076 | */ |
5077 | keyWord = "compositeOrientation"; |
5078 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
5079 | if (status == CAPS_SUCCESS0) { |
5080 | status = string_toDoubleDynamicArray(keyValue, &tempInteger, |
5081 | &feaProblem->feaProperty[i].compositeOrientation); |
5082 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5082 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
5083 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
5084 | |
5085 | if (tempInteger < feaProblem->feaProperty[i].numPly) { |
5086 | |
5087 | printf("\tThe number of orientations provided does not match the number of materials for the composite. " |
5088 | "The last orientation will be repeated %d times\n", feaProblem->feaProperty[i].numPly - tempInteger); |
5089 | |
5090 | AIM_REALL(feaProblem->feaProperty[i].compositeOrientation,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeOrientation = (double *) EG_reall (feaProblem->feaProperty[i].compositeOrientation, memorysize *sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5091, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation" , memorysize, "double"); goto cleanup; } } |
5091 | feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeOrientation = (double *) EG_reall (feaProblem->feaProperty[i].compositeOrientation, memorysize *sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5091, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation" , memorysize, "double"); goto cleanup; } }; |
5092 | |
5093 | for (j = 0; j < feaProblem->feaProperty[i].numPly - tempInteger; j++) { |
5094 | |
5095 | feaProblem->feaProperty[i].compositeOrientation[j+tempInteger] = feaProblem->feaProperty[i].compositeOrientation[tempInteger-1]; |
5096 | } |
5097 | } |
5098 | |
5099 | if (tempInteger > feaProblem->feaProperty[i].numPly) { |
5100 | |
5101 | printf("\tThe number of orientations provided does not match the number of materials for the composite. " |
5102 | "The last %d orientation will be not be used\n", tempInteger -feaProblem->feaProperty[i].numPly); |
5103 | |
5104 | AIM_REALL(feaProblem->feaProperty[i].compositeOrientation,{ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeOrientation = (double *) EG_reall (feaProblem->feaProperty[i].compositeOrientation, memorysize *sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5105, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation" , memorysize, "double"); goto cleanup; } } |
5105 | feaProblem->feaProperty[i].numPly, double, aimInfo, status){ size_t memorysize = feaProblem->feaProperty[i].numPly; feaProblem ->feaProperty[i].compositeOrientation = (double *) EG_reall (feaProblem->feaProperty[i].compositeOrientation, memorysize *sizeof(double)); if (feaProblem->feaProperty[i].compositeOrientation == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 5105, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaProblem->feaProperty[i].compositeOrientation" , memorysize, "double"); goto cleanup; } }; |
5106 | } |
5107 | |
5108 | } else { |
5109 | |
5110 | if (feaProblem->feaProperty[i].numPly != 0 && |
5111 | feaProblem->feaProperty[i].propertyType == Composite) { |
5112 | |
5113 | AIM_ERROR(aimInfo, "\"compositeMaterial\" have been set but no Orientation (\"compositeOrientation\") provided!!!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5113, __func__ , "\"compositeMaterial\" have been set but no Orientation (\"compositeOrientation\") provided!!!" ); }; |
5114 | status = CAPS_BADVALUE-311; |
5115 | goto cleanup; |
5116 | } |
5117 | } |
5118 | |
5119 | // Mass |
5120 | |
5121 | /*! \page feaProperty |
5122 | * |
5123 | * \if (MYSTRAN || NASTRAN) |
5124 | * <ul> |
5125 | * <li> <B>mass = 0.0</B> </li> <br> |
5126 | * Mass value. |
5127 | * </ul> |
5128 | * \elseif ABAQUS |
5129 | * |
5130 | * Something else .... |
5131 | * |
5132 | * \elseif ASTROS |
5133 | * <ul> |
5134 | * <li> <B>mass = 0.0</B> </li> <br> |
5135 | * Mass value. |
5136 | * </ul> |
5137 | * \endif |
5138 | */ |
5139 | keyWord = "mass"; |
5140 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
5141 | if (status == CAPS_SUCCESS0) { |
5142 | status = string_toDouble(keyValue, &feaProblem->feaProperty[i].mass); |
5143 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5143 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
5144 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
5145 | } |
5146 | |
5147 | /*! \page feaProperty |
5148 | * |
5149 | * \if (MYSTRAN || NASTRAN || MASSTRAN) |
5150 | * <ul> |
5151 | * <li> <B>massOffset = [0.0, 0.0, 0.0]</B> </li> <br> |
5152 | * Offset distance from the grid point to the center of gravity for a concentrated mass. |
5153 | * </ul> |
5154 | * \elseif ABAQUS |
5155 | * |
5156 | * Something else .... |
5157 | * |
5158 | * \elseif ASTROS |
5159 | * <ul> |
5160 | * <li> <B>massOffset = [0.0, 0.0, 0.0]</B> </li> <br> |
5161 | * Offset distance from the grid point to the center of gravity for a concentrated mass. |
5162 | * </ul> |
5163 | * \endif |
5164 | */ |
5165 | keyWord = "massOffset"; |
5166 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
5167 | if (status == CAPS_SUCCESS0) { |
5168 | status = string_toDoubleArray(keyValue, |
5169 | (int) sizeof(feaProblem->feaProperty[i].massOffset)/sizeof(double), |
5170 | feaProblem->feaProperty[i].massOffset); |
5171 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5171 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
5172 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
5173 | } |
5174 | |
5175 | /*! \page feaProperty |
5176 | * |
5177 | * \if (MYSTRAN || NASTRAN || MASSTRAN) |
5178 | * <ul> |
5179 | * <li> <B>massInertia = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</B> </li> <br> |
5180 | * Mass moment of inertia measured at the mass center of gravity. |
5181 | * </ul> |
5182 | * \elseif ABAQUS |
5183 | *v |
5184 | * Something else .... |
5185 | * |
5186 | * \elseif ASTROS |
5187 | * <ul> |
5188 | * <li> <B>massInertia = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]</B> </li> <br> |
5189 | * Mass moment of inertia measured at the mass center of gravity. |
5190 | * </ul> |
5191 | * \endif |
5192 | */ |
5193 | keyWord = "massInertia"; |
5194 | status = search_jsonDictionary( propertyTuple[i].value, keyWord, &keyValue); |
5195 | if (status == CAPS_SUCCESS0) { |
5196 | status = string_toDoubleArray(keyValue, |
5197 | (int) sizeof(feaProblem->feaProperty[i].massInertia)/sizeof(double), |
5198 | feaProblem->feaProperty[i].massInertia); |
5199 | AIM_STATUS(aimInfo, status, "While parsing \"%s\":\"%s\"", keyWord, keyValue)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 5199 , __func__, 3, "While parsing \"%s\":\"%s\"", keyWord, keyValue ); goto cleanup; }; |
5200 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
5201 | } |
5202 | |
5203 | } else { |
5204 | |
5205 | /*! \page feaProperty |
5206 | * \section keyStringProperty Single Value String |
5207 | * |
5208 | * If "Value" is a string, the string value may correspond to an entry in a predefined property lookup |
5209 | * table. NOT YET IMPLEMENTED!!!! |
5210 | * |
5211 | */ |
5212 | |
5213 | // CALL property look up |
5214 | AIM_ERROR(aimInfo, "Property tuple value ('s') is expected to be a JSON string", propertyTuple[i].value){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 5214, __func__ , "Property tuple value ('s') is expected to be a JSON string" , propertyTuple[i].value); }; |
5215 | status = CAPS_BADVALUE-311; |
5216 | goto cleanup; |
5217 | } |
5218 | } |
5219 | |
5220 | printf("\tDone getting FEA properties\n"); |
5221 | status = CAPS_SUCCESS0; |
5222 | |
5223 | cleanup: |
5224 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
5225 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
5226 | |
5227 | return status; |
5228 | } |
5229 | |
5230 | // Get the constraint properties from a capsTuple |
5231 | int fea_getConstraint(void *aimInfo, |
5232 | int numConstraintTuple, |
5233 | capsTuple constraintTuple[], |
5234 | mapAttrToIndexStruct *attrMap, |
5235 | feaProblemStruct *feaProblem) { |
5236 | |
5237 | /*! \page feaConstraint FEA Constraint |
5238 | * Structure for the constraint tuple = ("Constraint Name", "Value"). |
5239 | * "Constraint Name" defines the reference name for the constraint being specified. |
5240 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConstraint) or a single string keyword |
5241 | * (see Section \ref keyStringConstraint). |
5242 | */ |
5243 | |
5244 | int status; //Function return |
5245 | |
5246 | int i, groupIndex, attrIndex, nodeIndex; // Indexing |
5247 | |
5248 | char *keyValue = NULL((void*)0); // Key values from tuple searches |
5249 | char *keyWord = NULL((void*)0); // Key words to find in the tuples |
5250 | |
5251 | int numGroupName = 0; |
5252 | char **groupName = NULL((void*)0); |
5253 | |
5254 | feaMeshDataStruct *feaData; |
5255 | |
5256 | // Destroy our constraint structures coming in if aren't 0 and NULL already |
5257 | if (feaProblem->feaConstraint != NULL((void*)0)) { |
5258 | for (i = 0; i < feaProblem->numConstraint; i++) { |
5259 | status = destroy_feaConstraintStruct(&feaProblem->feaConstraint[i]); |
5260 | if (status != CAPS_SUCCESS0) return status; |
5261 | } |
5262 | } |
5263 | if (feaProblem->feaConstraint != NULL((void*)0)) EG_free(feaProblem->feaConstraint); |
5264 | feaProblem->feaConstraint = NULL((void*)0); |
5265 | feaProblem->numConstraint = 0; |
5266 | |
5267 | printf("\nGetting FEA constraints.......\n"); |
5268 | |
5269 | feaProblem->numConstraint = numConstraintTuple; |
5270 | |
5271 | printf("\tNumber of constraints - %d\n", feaProblem->numConstraint); |
5272 | |
5273 | // Allocate constraints |
5274 | if (feaProblem->numConstraint > 0) { |
5275 | feaProblem->feaConstraint = (feaConstraintStruct *) EG_alloc(feaProblem->numConstraint * sizeof(feaConstraintStruct)); |
5276 | |
5277 | if (feaProblem->feaConstraint == NULL((void*)0) ) return EGADS_MALLOC-4; |
5278 | } |
5279 | |
5280 | // Initiate constraints to default values |
5281 | for (i = 0; i < feaProblem->numConstraint; i++) { |
5282 | status = initiate_feaConstraintStruct(&feaProblem->feaConstraint[i]); |
5283 | if (status != CAPS_SUCCESS0) return status; |
5284 | } |
5285 | |
5286 | // Loop through tuples and fill out the constraint structures |
5287 | for (i = 0; i < feaProblem->numConstraint; i++) { |
5288 | |
5289 | printf("\tConstraint name - %s\n", constraintTuple[i].name ); |
5290 | |
5291 | // Set constraint name to tuple attribute name |
5292 | feaProblem->feaConstraint[i].name = (char *) EG_alloc((strlen(constraintTuple[i].name) + 1)*sizeof(char)); |
5293 | if (feaProblem->feaConstraint[i].name == NULL((void*)0)) return EGADS_MALLOC-4; |
5294 | |
5295 | memcpy(feaProblem->feaConstraint[i].name, constraintTuple[i].name, strlen(constraintTuple[i].name)*sizeof(char)); |
5296 | feaProblem->feaConstraint[i].name[strlen(constraintTuple[i].name)] = '\0'; |
5297 | |
5298 | // Set constraint id -> 1 bias |
5299 | feaProblem->feaConstraint[i].constraintID = i+1; |
5300 | |
5301 | // Do we have a json string? |
5302 | if (strncmp(constraintTuple[i].value, "{", 1) == 0) { |
5303 | //printf("JSON String - %s\n", constraintTuple[i].value); |
5304 | |
5305 | /*! \page feaConstraint |
5306 | * \section jsonStringConstraint JSON String Dictionary |
5307 | * |
5308 | * If "Value" is JSON string dictionary |
5309 | * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS) |
5310 | * (eg. "Value" = {"groupName": "plateEdge", "dofConstraint": 123456}) |
5311 | * \endif |
5312 | * the following keywords ( = default values) may be used: |
5313 | * |
5314 | * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS) |
5315 | * <ul> |
5316 | * <li> <B>constraintType = "ZeroDisplacement"</B> </li> <br> |
5317 | * Type of constraint. Options: "Displacement", "ZeroDisplacement". |
5318 | * </ul> |
5319 | * \endif |
5320 | * |
5321 | */ |
5322 | // Get constraint Type |
5323 | keyWord = "constraintType"; |
5324 | status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue); |
5325 | if (status == CAPS_SUCCESS0) { |
5326 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 5326, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
5327 | |
5328 | //{UnknownConstraint, Displacement, ZeroDisplacement} |
5329 | if (strcasecmp(keyValue, "\"Displacement\"") == 0) feaProblem->feaConstraint[i].constraintType = Displacement; |
5330 | else if (strcasecmp(keyValue, "\"ZeroDisplacement\"") == 0) feaProblem->feaConstraint[i].constraintType = ZeroDisplacement; |
5331 | else { |
5332 | |
5333 | printf("\tUnrecognized \"%s\" specified (%s) for Constraint tuple %s, defaulting to \"ZeroDisplacement\"\n", keyWord, |
5334 | keyValue, |
5335 | constraintTuple[i].name); |
5336 | feaProblem->feaConstraint[i].constraintType = ZeroDisplacement; |
5337 | } |
5338 | |
5339 | } else { |
5340 | |
5341 | printf("\tNo \"%s\" specified for Constraint tuple %s, defaulting to \"ZeroDisplacement\"\n", keyWord, |
5342 | constraintTuple[i].name); |
5343 | feaProblem->feaConstraint[i].constraintType = ZeroDisplacement; |
5344 | } |
5345 | |
5346 | if (keyValue != NULL((void*)0)) { |
5347 | EG_free(keyValue); |
5348 | keyValue = NULL((void*)0); |
5349 | } |
5350 | |
5351 | // Get constraint node set |
5352 | |
5353 | /*! \page feaConstraint |
5354 | * |
5355 | * \if MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS) |
5356 | * <ul> |
5357 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
5358 | * Single or list of <c>capsConstraint</c> names on which to apply the constraint |
5359 | * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the constraint tuple name will be |
5360 | * used. |
5361 | * </ul> |
5362 | * \endif |
5363 | * |
5364 | */ |
5365 | keyWord = "groupName"; |
5366 | status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue); |
5367 | if (status == CAPS_SUCCESS0) { |
5368 | |
5369 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
5370 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
5371 | keyValue = NULL((void*)0); |
5372 | |
5373 | if (status != CAPS_SUCCESS0) return status; |
5374 | |
5375 | } else { |
5376 | |
5377 | printf("\tNo \"%s\" specified for Constraint tuple %s, going to use constraint name\n", keyWord, |
5378 | constraintTuple[i].name); |
5379 | |
5380 | status = string_toStringDynamicArray(constraintTuple[i].name, &numGroupName, &groupName); |
5381 | if (status != CAPS_SUCCESS0) return status; |
5382 | |
5383 | } |
5384 | |
5385 | // Determine how many point constraints we have |
5386 | feaProblem->feaConstraint[i].numGridID = 0; |
5387 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
5388 | |
5389 | status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex); |
5390 | |
5391 | if (status == CAPS_NOTFOUND-303) { |
5392 | printf("\tName %s not found in attribute map of capsConstraints!!!!\n", groupName[groupIndex]); |
5393 | continue; |
5394 | } else if (status != CAPS_SUCCESS0) return status; |
5395 | |
5396 | // Now lets loop through the grid to see how many grid points have the attrIndex |
5397 | for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) { |
5398 | |
5399 | if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) { |
5400 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData; |
5401 | } else { |
5402 | continue; |
5403 | } |
5404 | |
5405 | if (feaData->constraintIndex == attrIndex) { |
5406 | |
5407 | feaProblem->feaConstraint[i].numGridID += 1; |
5408 | |
5409 | // Allocate/Re-allocate grid ID array |
5410 | if (feaProblem->feaConstraint[i].numGridID == 1) { |
5411 | feaProblem->feaConstraint[i].gridIDSet = (int *) EG_alloc(feaProblem->feaConstraint[i].numGridID*sizeof(int)); |
5412 | } else { |
5413 | feaProblem->feaConstraint[i].gridIDSet = (int *) EG_reall(feaProblem->feaConstraint[i].gridIDSet, |
5414 | feaProblem->feaConstraint[i].numGridID*sizeof(int)); |
5415 | } |
5416 | |
5417 | if (feaProblem->feaConstraint[i].gridIDSet == NULL((void*)0)) { |
5418 | status = string_freeArray(numGroupName, &groupName); |
5419 | if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status); |
5420 | |
5421 | return EGADS_MALLOC-4; |
5422 | } |
5423 | |
5424 | // Set grid ID value -> 1 bias |
5425 | feaProblem->feaConstraint[i].gridIDSet[feaProblem->feaConstraint[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID; |
5426 | } |
5427 | } |
5428 | } |
5429 | |
5430 | status = string_freeArray(numGroupName, &groupName); |
5431 | if (status != CAPS_SUCCESS0) return status; |
5432 | groupName = NULL((void*)0); |
5433 | |
5434 | |
5435 | //Fill up constraint properties |
5436 | /*! \page feaConstraint |
5437 | * |
5438 | * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS) |
5439 | * <ul> |
5440 | * <li> <B>dofConstraint = 0 </B> </li> <br> |
5441 | * Component numbers / degrees of freedom that will be constrained (123 - zero translation in all three |
5442 | * directions). |
5443 | * </ul> |
5444 | * \endif |
5445 | */ |
5446 | keyWord = "dofConstraint"; |
5447 | status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue); |
5448 | if (status == CAPS_SUCCESS0) { |
5449 | |
5450 | status = string_toInteger(keyValue, &feaProblem->feaConstraint[i].dofConstraint); |
5451 | if (keyValue != NULL((void*)0)) { |
5452 | EG_free(keyValue); |
5453 | keyValue = NULL((void*)0); |
5454 | } |
5455 | if (status != CAPS_SUCCESS0) return status; |
5456 | } |
5457 | |
5458 | /*! \page feaConstraint |
5459 | * |
5460 | * \if (MYSTRAN || NASTRAN || ASTROS || HSM || ABAQUS) |
5461 | * <ul> |
5462 | * <li> <B>gridDisplacement = 0.0 </B> </li> <br> |
5463 | * Value of displacement for components defined in "dofConstraint". |
5464 | * </ul> |
5465 | * \endif |
5466 | */ |
5467 | keyWord = "gridDisplacement"; |
5468 | status = search_jsonDictionary( constraintTuple[i].value, keyWord, &keyValue); |
5469 | if (status == CAPS_SUCCESS0) { |
5470 | |
5471 | status = string_toDouble(keyValue, &feaProblem->feaConstraint[i].gridDisplacement); |
5472 | if (keyValue != NULL((void*)0)) { |
5473 | EG_free(keyValue); |
5474 | keyValue = NULL((void*)0); |
5475 | } |
5476 | if (status != CAPS_SUCCESS0) return status; |
5477 | } |
5478 | |
5479 | } else { |
5480 | |
5481 | /*! \page feaConstraint |
5482 | * \section keyStringConstraint Single Value String |
5483 | * |
5484 | * If "Value" is a string, the string value may correspond to an entry in a predefined constraint lookup |
5485 | * table. NOT YET IMPLEMENTED!!!! |
5486 | * |
5487 | */ |
5488 | |
5489 | // Call some look up table maybe? |
5490 | printf("\tError: Constraint tuple value is expected to be a JSON string\n"); |
5491 | return CAPS_BADVALUE-311; |
5492 | } |
5493 | } |
5494 | |
5495 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
5496 | |
5497 | printf("\tDone getting FEA constraints\n"); |
5498 | |
5499 | status = CAPS_SUCCESS0; |
5500 | cleanup: |
5501 | return status; |
5502 | } |
5503 | |
5504 | // Get the support properties from a capsTuple |
5505 | int fea_getSupport(int numSupportTuple, |
5506 | capsTuple supportTuple[], |
5507 | mapAttrToIndexStruct *attrMap, |
5508 | feaProblemStruct *feaProblem) { |
5509 | |
5510 | /*! \page feaSupport FEA Support |
5511 | * Structure for the support tuple = ("Support Name", "Value"). |
5512 | * "Support Name" defines the reference name for the support being specified. |
5513 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringSupport) or a single string keyword |
5514 | * (see Section \ref keyStringSupport). |
5515 | */ |
5516 | |
5517 | int status; //Function return |
5518 | |
5519 | int i, groupIndex, attrIndex, nodeIndex; // Indexing |
5520 | |
5521 | char *keyValue = NULL((void*)0); // Key values from tuple searches |
5522 | char *keyWord = NULL((void*)0); // Key words to find in the tuples |
5523 | |
5524 | int numGroupName = 0; |
5525 | char **groupName = NULL((void*)0); |
5526 | |
5527 | feaMeshDataStruct *feaData; |
5528 | |
5529 | // Destroy our support structures coming in if aren't 0 and NULL already |
5530 | if (feaProblem->feaSupport != NULL((void*)0)) { |
5531 | for (i = 0; i < feaProblem->numSupport; i++) { |
5532 | status = destroy_feaSupportStruct(&feaProblem->feaSupport[i]); |
5533 | if (status != CAPS_SUCCESS0) return status; |
5534 | } |
5535 | } |
5536 | if (feaProblem->feaSupport != NULL((void*)0)) EG_free(feaProblem->feaSupport); |
5537 | feaProblem->feaSupport = NULL((void*)0); |
5538 | feaProblem->numSupport = 0; |
5539 | |
5540 | printf("\nGetting FEA supports.......\n"); |
5541 | |
5542 | feaProblem->numSupport = numSupportTuple; |
5543 | |
5544 | printf("\tNumber of supports - %d\n", feaProblem->numSupport); |
5545 | |
5546 | // Allocate supports |
5547 | if (feaProblem->numSupport > 0) { |
5548 | feaProblem->feaSupport = (feaSupportStruct *) EG_alloc(feaProblem->numSupport * sizeof(feaSupportStruct)); |
5549 | |
5550 | if (feaProblem->feaSupport == NULL((void*)0) ) return EGADS_MALLOC-4; |
5551 | } |
5552 | |
5553 | // Initiate supports to default values |
5554 | for (i = 0; i < feaProblem->numSupport; i++) { |
5555 | status = initiate_feaSupportStruct(&feaProblem->feaSupport[i]); |
5556 | if (status != CAPS_SUCCESS0) return status; |
5557 | } |
5558 | |
5559 | // Loop through tuples and fill out the support structures |
5560 | for (i = 0; i < feaProblem->numSupport; i++) { |
5561 | |
5562 | printf("\tSupport name - %s\n", supportTuple[i].name ); |
5563 | |
5564 | // Set support name to tuple attribute name |
5565 | feaProblem->feaSupport[i].name = (char *) EG_alloc((strlen(supportTuple[i].name) + 1)*sizeof(char)); |
5566 | if (feaProblem->feaSupport[i].name == NULL((void*)0)) return EGADS_MALLOC-4; |
5567 | |
5568 | memcpy(feaProblem->feaSupport[i].name, supportTuple[i].name, strlen(supportTuple[i].name)*sizeof(char)); |
5569 | feaProblem->feaSupport[i].name[strlen(supportTuple[i].name)] = '\0'; |
5570 | |
5571 | // Set support id -> 1 bias |
5572 | feaProblem->feaSupport[i].supportID = i+1; |
5573 | |
5574 | // Do we have a json string? |
5575 | if (strncmp(supportTuple[i].value, "{", 1) == 0) { |
5576 | //printf("JSON String - %s\n", supportTuple[i].value); |
5577 | |
5578 | /*! \page feaSupport |
5579 | * \section jsonStringSupport JSON String Dictionary |
5580 | * |
5581 | * If "Value" is JSON string dictionary |
5582 | * \if (MYSTRAN || NASTRAN || ASTROS) |
5583 | * (eg. "Value" = {"groupName": "plateEdge", "dofSupport": 123456}) |
5584 | * \endif |
5585 | * the following keywords ( = default values) may be used: |
5586 | */ |
5587 | |
5588 | // Get support node set |
5589 | |
5590 | /*! \page feaSupport |
5591 | * |
5592 | * \if (MYSTRAN || NASTRAN || ASTROS) |
5593 | * <ul> |
5594 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
5595 | * Single or list of <c>capsConstraint</c> names on which to apply the support |
5596 | * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the constraint tuple name will be |
5597 | * used. |
5598 | * </ul> |
5599 | * \endif |
5600 | */ |
5601 | keyWord = "groupName"; |
5602 | status = search_jsonDictionary( supportTuple[i].value, keyWord, &keyValue); |
5603 | if (status == CAPS_SUCCESS0) { |
5604 | |
5605 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
5606 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
5607 | keyValue = NULL((void*)0); |
5608 | |
5609 | if (status != CAPS_SUCCESS0) return status; |
5610 | |
5611 | } else { |
5612 | |
5613 | printf("\tNo \"%s\" specified for Support tuple %s, going to use support name\n", keyWord, |
5614 | supportTuple[i].name); |
5615 | |
5616 | status = string_toStringDynamicArray(supportTuple[i].name, &numGroupName, &groupName); |
5617 | if (status != CAPS_SUCCESS0) return status; |
5618 | |
5619 | } |
5620 | |
5621 | // Determine how many point supports we have |
5622 | feaProblem->feaSupport[i].numGridID = 0; |
5623 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
5624 | |
5625 | status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex); |
5626 | |
5627 | if (status == CAPS_NOTFOUND-303) { |
5628 | printf("\tName %s not found in attribute map of capsConstraints!!!!\n", groupName[groupIndex]); |
5629 | continue; |
5630 | } else if (status != CAPS_SUCCESS0) return status; |
5631 | |
5632 | // Now lets loop through the grid to see how many grid points have the attrIndex |
5633 | for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) { |
5634 | |
5635 | if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) { |
5636 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData; |
5637 | } else { |
5638 | continue; |
5639 | } |
5640 | |
5641 | if (feaData->constraintIndex == attrIndex) { |
5642 | |
5643 | feaProblem->feaSupport[i].numGridID += 1; |
5644 | |
5645 | // Allocate/Re-allocate grid ID array |
5646 | if (feaProblem->feaSupport[i].numGridID == 1) { |
5647 | feaProblem->feaSupport[i].gridIDSet = (int *) EG_alloc(feaProblem->feaSupport[i].numGridID*sizeof(int)); |
5648 | } else { |
5649 | feaProblem->feaSupport[i].gridIDSet = (int *) EG_reall(feaProblem->feaSupport[i].gridIDSet, |
5650 | feaProblem->feaSupport[i].numGridID*sizeof(int)); |
5651 | } |
5652 | |
5653 | if (feaProblem->feaSupport[i].gridIDSet == NULL((void*)0)) { |
5654 | status = string_freeArray(numGroupName, &groupName); |
5655 | if (status != CAPS_SUCCESS0) printf("Status %d during string_freeArray\n", status); |
5656 | |
5657 | return EGADS_MALLOC-4; |
5658 | } |
5659 | |
5660 | // Set grid ID value -> 1 bias |
5661 | feaProblem->feaSupport[i].gridIDSet[feaProblem->feaSupport[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID; |
5662 | } |
5663 | } |
5664 | } |
5665 | |
5666 | status = string_freeArray(numGroupName, &groupName); |
5667 | if (status != CAPS_SUCCESS0) return status; |
5668 | groupName = NULL((void*)0); |
5669 | |
5670 | //Fill up support properties |
5671 | /*! \page feaSupport |
5672 | * |
5673 | * \if (MYSTRAN || NASTRAN || ASTROS) |
5674 | * <ul> |
5675 | * <li> <B>dofSupport = 0 </B> </li> <br> |
5676 | * Component numbers / degrees of freedom that will be supported (123 - zero translation in all three |
5677 | * directions). |
5678 | * </ul> |
5679 | * \endif |
5680 | */ |
5681 | keyWord = "dofSupport"; |
5682 | status = search_jsonDictionary( supportTuple[i].value, keyWord, &keyValue); |
5683 | if (status == CAPS_SUCCESS0) { |
5684 | |
5685 | status = string_toInteger(keyValue, &feaProblem->feaSupport[i].dofSupport); |
5686 | if (keyValue != NULL((void*)0)) { |
5687 | EG_free(keyValue); |
5688 | keyValue = NULL((void*)0); |
5689 | } |
5690 | if (status != CAPS_SUCCESS0) return status; |
5691 | } |
5692 | |
5693 | } else { |
5694 | |
5695 | /*! \page feaSupport |
5696 | * \section keyStringSupport Single Value String |
5697 | * |
5698 | * If "Value" is a string, the string value may correspond to an entry in a predefined support lookup |
5699 | * table. NOT YET IMPLEMENTED!!!! |
5700 | * |
5701 | */ |
5702 | |
5703 | // Call some look up table maybe? |
5704 | printf("\tError: Support tuple value is expected to be a JSON string\n"); |
5705 | return CAPS_BADVALUE-311; |
5706 | |
5707 | } |
5708 | } |
5709 | |
5710 | if (keyValue != NULL((void*)0)) { |
5711 | EG_free(keyValue); |
5712 | keyValue = NULL((void*)0); |
5713 | } |
5714 | |
5715 | printf("\tDone getting FEA supports\n"); |
5716 | return CAPS_SUCCESS0; |
5717 | } |
5718 | |
5719 | |
5720 | static int fea_setConnection(char *connectionName, |
5721 | feaConnectionTypeEnum connectionType, |
5722 | int connectionID, |
5723 | int elementOffSet, |
5724 | int dofDependent, |
5725 | double stiffnessConst, |
5726 | double dampingConst, |
5727 | double stressCoeff, |
5728 | int componentNumberStart, |
5729 | int componentNumberEnd, |
5730 | int srcNodeID, |
5731 | double masterWeight, |
5732 | int masterComponent, |
5733 | int numNode, int *node, |
5734 | int *numConnect, feaConnectionStruct *feaConnect[]) { // Out |
5735 | |
5736 | int status; |
5737 | int i; |
5738 | |
5739 | if (numNode == 0) { |
5740 | status = CAPS_BADVALUE-311; // Nothing to do |
5741 | goto cleanup; |
5742 | } |
5743 | |
5744 | if (connectionType == RigidBodyInterpolate) { |
5745 | *numConnect += 1; |
5746 | |
5747 | (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),*numConnect*sizeof(feaConnectionStruct)); |
5748 | if ((*feaConnect) == NULL((void*)0)) { |
5749 | *numConnect = 0; |
5750 | status = EGADS_MALLOC-4; |
5751 | goto cleanup; |
5752 | } |
5753 | |
5754 | status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect-1]); |
5755 | if (status != CAPS_SUCCESS0) return status; |
5756 | |
5757 | (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index |
5758 | (*feaConnect)[*numConnect-1].connectionType = connectionType; |
5759 | |
5760 | (*feaConnect)[*numConnect-1].elementID = *numConnect + elementOffSet; |
5761 | |
5762 | (*feaConnect)[*numConnect-1].dofDependent = dofDependent; |
5763 | |
5764 | (*feaConnect)[*numConnect-1].connectivity[1] = srcNodeID; // Dependent |
5765 | (*feaConnect)[*numConnect-1].numMaster = numNode; // Independent |
5766 | |
5767 | (*feaConnect)[*numConnect-1].masterIDSet = (int *) EG_alloc(numNode*sizeof(int)); // [numMaster] |
5768 | if ((*feaConnect)[*numConnect-1].masterIDSet == NULL((void*)0)) { |
5769 | status = EGADS_MALLOC-4; |
5770 | goto cleanup; |
5771 | } |
5772 | (*feaConnect)[*numConnect-1].masterWeighting = (double *) EG_alloc(numNode*sizeof(double));; // [numMaster] |
5773 | if ((*feaConnect)[*numConnect-1].masterWeighting == NULL((void*)0)) { |
5774 | status = EGADS_MALLOC-4; |
5775 | goto cleanup; |
5776 | } |
5777 | |
5778 | (*feaConnect)[*numConnect-1].masterComponent =(int *) EG_alloc(numNode*sizeof(int));; // [numMaster] |
5779 | if ((*feaConnect)[*numConnect-1].masterComponent == NULL((void*)0)) { |
5780 | status = EGADS_MALLOC-4; |
5781 | goto cleanup; |
5782 | } |
5783 | |
5784 | //printf("\tMasters (%d)", numNode); |
5785 | // Master values; |
5786 | for (i = 0; i < numNode; i++) { |
5787 | // printf(" %d", node[i]); |
5788 | |
5789 | (*feaConnect)[*numConnect-1].masterIDSet[i] = node[i]; |
5790 | (*feaConnect)[*numConnect-1].masterWeighting[i] = masterWeight; |
5791 | (*feaConnect)[*numConnect-1].masterComponent[i] = masterComponent; |
5792 | } |
5793 | //printf("\n"); |
5794 | |
5795 | } else { // For all other types of connections create an individual connection - single pair of nodes |
5796 | |
5797 | (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),(*numConnect+numNode)*sizeof(feaConnectionStruct)); |
5798 | if ((*feaConnect) == NULL((void*)0)) { |
5799 | *numConnect = 0; |
5800 | status = EGADS_MALLOC-4; |
5801 | goto cleanup; |
5802 | } |
5803 | |
5804 | for (i = 0; i < numNode; i++) { |
5805 | status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect+i]); |
5806 | if (status != CAPS_SUCCESS0) return status; |
5807 | } |
5808 | |
5809 | for (i = 0; i < numNode; i++) { |
5810 | |
5811 | *numConnect += 1; |
5812 | |
5813 | (*feaConnect)[*numConnect-1].name = (char *) EG_alloc((strlen(connectionName) + 1)*sizeof(char)); |
5814 | if ((*feaConnect)[*numConnect-1].name == NULL((void*)0)) return EGADS_MALLOC-4; |
5815 | |
5816 | memcpy((*feaConnect)[*numConnect-1].name, |
5817 | connectionName, |
5818 | strlen(connectionName)*sizeof(char)); |
5819 | (*feaConnect)[*numConnect-1].name[strlen(connectionName)] = '\0'; |
5820 | |
5821 | (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index |
5822 | |
5823 | (*feaConnect)[*numConnect-1].connectionType = connectionType; |
5824 | (*feaConnect)[*numConnect-1].elementID = *numConnect + elementOffSet; |
5825 | |
5826 | (*feaConnect)[*numConnect-1].connectivity[0] = srcNodeID; |
5827 | (*feaConnect)[*numConnect-1].connectivity[1] = node[i]; |
5828 | |
5829 | (*feaConnect)[*numConnect-1].dofDependent = dofDependent; |
5830 | (*feaConnect)[*numConnect-1].stiffnessConst = stiffnessConst; |
5831 | (*feaConnect)[*numConnect-1].dampingConst = dampingConst; |
5832 | (*feaConnect)[*numConnect-1].stressCoeff = stressCoeff; |
5833 | (*feaConnect)[*numConnect-1].componentNumberStart = componentNumberStart; |
5834 | (*feaConnect)[*numConnect-1].componentNumberEnd = componentNumberEnd; |
5835 | } |
5836 | } |
5837 | |
5838 | status = CAPS_SUCCESS0; |
5839 | goto cleanup; |
5840 | |
5841 | cleanup: |
5842 | if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_setConnection, status = %d\n", status); |
5843 | return status; |
5844 | } |
5845 | // Get the Connections properties from a capsTuple and create connections based on the mesh |
5846 | int fea_getConnection(void *aimInfo, |
5847 | int numConnectionTuple, |
5848 | capsTuple connectionTuple[], |
5849 | mapAttrToIndexStruct *attrMap, |
5850 | feaProblemStruct *feaProblem) { |
5851 | |
5852 | /*! \page feaConnection FEA Connection |
5853 | * Structure for the connection tuple = ("Connection Name", "Value"). |
5854 | * "Connection Name" defines the reference name to the capsConnect being specified and denotes the "source" node |
5855 | * for the connection. |
5856 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConnection) or a single string keyword |
5857 | * (see Section \ref keyStringConnection). |
5858 | */ |
5859 | |
5860 | int status; //Function return |
5861 | |
5862 | int i, groupIndex, nodeIndex, nodeIndexDest; // Indexing |
5863 | |
5864 | char *keyValue = NULL((void*)0); // Key values from tuple searches |
5865 | char *keyWord = NULL((void*)0); // Key words to find in the tuples |
5866 | |
5867 | int numGroupName = 0; |
5868 | char **groupName = NULL((void*)0); |
5869 | int attrIndex, attrIndexDest; |
5870 | |
5871 | // Values to set |
5872 | feaConnectionTypeEnum connectionType; |
5873 | int dofDependent = 0, componentNumberStart = 0, componentNumberEnd = 0; |
5874 | double stiffnessConst = 0.0, dampingConst = 0.0, stressCoeff = 0.0, mass = 0.0; |
5875 | |
5876 | double weighting=1; |
5877 | |
5878 | int glue = (int) false0, glueNumMaster = 5; |
5879 | double glueSearchRadius=0; |
5880 | |
5881 | feaMeshDataStruct *feaData, *feaDataDest; |
5882 | |
5883 | int numDestNode=0, *destNode=NULL((void*)0); |
5884 | |
5885 | // Destroy our support structures coming in if aren't 0 and NULL already |
5886 | if (feaProblem->feaConnect != NULL((void*)0)) { |
5887 | for (i = 0; i < feaProblem->numConnect; i++) { |
5888 | status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]); |
5889 | if (status != CAPS_SUCCESS0) return status; |
5890 | } |
5891 | } |
5892 | if (feaProblem->feaConnect != NULL((void*)0)) EG_free(feaProblem->feaConnect); |
5893 | feaProblem->feaConnect = NULL((void*)0); |
5894 | feaProblem->numConnect = 0; |
5895 | |
5896 | printf("\nGetting FEA connections.......\n"); |
5897 | |
5898 | printf("\tNumber of connection tuples - %d\n", numConnectionTuple); |
5899 | |
5900 | // Loop through tuples and fill out the support structures |
5901 | for (i = 0; i < numConnectionTuple; i++) { |
5902 | |
5903 | // Reset defaults |
5904 | dofDependent = componentNumberStart = componentNumberEnd = 0; |
5905 | stiffnessConst = dampingConst = stressCoeff = mass = 0.0; |
5906 | |
5907 | weighting=1; |
5908 | |
5909 | glue = (int) false0; |
5910 | glueNumMaster = 5; |
5911 | glueSearchRadius = 0; |
5912 | |
5913 | printf("\tConnection name - %s\n", connectionTuple[i].name ); |
5914 | |
5915 | // Look for connection name in connection map |
5916 | status = get_mapAttrToIndexIndex(attrMap, (const char *) connectionTuple[i].name, &attrIndex); |
5917 | if (status == CAPS_NOTFOUND-303) { |
5918 | printf("\tName %s not found in attribute map of capsConnect!!!!\n", connectionTuple[i].name); |
5919 | continue; |
5920 | } else if (status != CAPS_SUCCESS0) return status; |
5921 | |
5922 | // Do we have a json string? |
5923 | if (strncmp(connectionTuple[i].value, "{", 1) == 0) { |
5924 | |
5925 | /*! \page feaConnection |
5926 | * \section jsonStringConnection JSON String Dictionary |
5927 | * |
5928 | * If "Value" is JSON string dictionary |
5929 | * \if (MYSTRAN || NASTRAN || ASTROS) |
5930 | * (e.g. "Value" = {"dofDependent": 1, "propertyType": "RigidBody"}) |
5931 | * \endif |
5932 | * the following keywords ( = default values) may be used: |
5933 | * |
5934 | * |
5935 | * \if (MYSTRAN || NASTRAN) |
5936 | * <ul> |
5937 | * <li> <B>connectionType = RigidBody</B> </li> <br> |
5938 | * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName". |
5939 | * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody, RigidBodyInterpolate. |
5940 | * </ul> |
5941 | * \elseif (ASTROS) |
5942 | * <ul> |
5943 | * <li> <B>connectionType = RigidBody</B> </li> <br> |
5944 | * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName". |
5945 | * Options: Mass (scalar), Spring (scalar), RigidBody, RigidBodyInterpolate. |
5946 | * </ul> |
5947 | * \endif |
5948 | * |
5949 | */ |
5950 | // Get connection Type |
5951 | keyWord = "connectionType"; |
5952 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
5953 | if (status == CAPS_SUCCESS0) { |
5954 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 5954, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
5955 | |
5956 | //{UnknownConnection, Mass, Spring, Damper, RigidBody} |
5957 | if (strcasecmp(keyValue, "\"Mass\"") == 0) connectionType = Mass; |
5958 | else if (strcasecmp(keyValue, "\"Spring\"") == 0) connectionType = Spring; |
5959 | else if (strcasecmp(keyValue, "\"Damper\"") == 0) connectionType = Damper; |
5960 | else if (strcasecmp(keyValue, "\"RigidBody\"") == 0) connectionType = RigidBody; |
5961 | else if (strcasecmp(keyValue, "\"RigidBodyInterpolate\"") == 0) connectionType = RigidBodyInterpolate; |
5962 | else { |
5963 | printf("\tUnrecognized \"%s\" specified (%s) for Connection tuple %s, current options are " |
5964 | "\"Mass, Spring, Damper, RigidBody, and RigidBodyInterpolate\"\n", keyWord, |
5965 | keyValue, |
5966 | connectionTuple[i].name); |
5967 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
5968 | |
5969 | return CAPS_NOTFOUND-303; |
5970 | } |
5971 | |
5972 | } else { |
5973 | |
5974 | printf("\tNo \"%s\" specified for Connection tuple %s, defaulting to RigidBody\n", keyWord, |
5975 | connectionTuple[i].name); |
5976 | connectionType = RigidBody; |
5977 | } |
5978 | |
5979 | /*! \page feaConnection |
5980 | * |
5981 | * \if (MYSTRAN || NASTRAN || ASTROS) |
5982 | * <ul> |
5983 | * <li> <B>dofDependent = 0 </B> </li> <br> |
5984 | * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three |
5985 | * directions). |
5986 | * </ul> |
5987 | * \endif |
5988 | * |
5989 | */ |
5990 | keyWord = "dofDependent"; |
5991 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
5992 | if (status == CAPS_SUCCESS0) { |
5993 | |
5994 | status = string_toInteger(keyValue, &dofDependent); |
5995 | if (keyValue != NULL((void*)0)) { |
5996 | EG_free(keyValue); |
5997 | keyValue = NULL((void*)0); |
5998 | } |
5999 | if (status != CAPS_SUCCESS0) return status; |
6000 | } |
6001 | |
6002 | |
6003 | /*! \page feaConnection |
6004 | * |
6005 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6006 | * <ul> |
6007 | * <li> <B>componentNumberStart = 0 </B> </li> <br> |
6008 | * Component numbers / degrees of freedom of the starting point of the connection for mass, |
6009 | * spring, and damper elements (scalar) ( 0 <= Integer <= 6). |
6010 | * </ul> |
6011 | * \endif |
6012 | */ |
6013 | keyWord = "componentNumberStart"; |
6014 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6015 | if (status == CAPS_SUCCESS0) { |
6016 | |
6017 | status = string_toInteger(keyValue, &componentNumberStart); |
6018 | if (keyValue != NULL((void*)0)) { |
6019 | EG_free(keyValue); |
6020 | keyValue = NULL((void*)0); |
6021 | } |
6022 | if (status != CAPS_SUCCESS0) return status; |
6023 | } |
6024 | |
6025 | /*! \page feaConnection |
6026 | * |
6027 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6028 | * <ul> |
6029 | * <li> <B>componentNumberEnd= 0 </B> </li> <br> |
6030 | * Component numbers / degrees of freedom of the ending point of the connection for mass, |
6031 | * spring, damper elements (scalar), and rigid body interpolative connection ( 0 <= Integer <= 6). |
6032 | * </ul> |
6033 | * \endif |
6034 | * |
6035 | */ |
6036 | keyWord = "componentNumberEnd"; |
6037 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6038 | if (status == CAPS_SUCCESS0) { |
6039 | |
6040 | status = string_toInteger(keyValue, &componentNumberEnd); |
6041 | if (keyValue != NULL((void*)0)) { |
6042 | EG_free(keyValue); |
6043 | keyValue = NULL((void*)0); |
6044 | } |
6045 | if (status != CAPS_SUCCESS0) return status; |
6046 | } |
6047 | |
6048 | /*! \page feaConnection |
6049 | * |
6050 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6051 | * <ul> |
6052 | * <li> <B>stiffnessConst = 0.0 </B> </li> <br> |
6053 | * Stiffness constant of a spring element (scalar). |
6054 | * </ul> |
6055 | * \endif |
6056 | */ |
6057 | keyWord = "stiffnessConst"; |
6058 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6059 | if (status == CAPS_SUCCESS0) { |
6060 | |
6061 | status = string_toDouble(keyValue, &stiffnessConst); |
6062 | if (keyValue != NULL((void*)0)) { |
6063 | EG_free(keyValue); |
6064 | keyValue = NULL((void*)0); |
6065 | } |
6066 | if (status != CAPS_SUCCESS0) return status; |
6067 | } |
6068 | |
6069 | /*! \page feaConnection |
6070 | * |
6071 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6072 | * <ul> |
6073 | * <li> <B>dampingConst = 0.0 </B> </li> <br> |
6074 | * Damping coefficient/constant of a spring or damping element (scalar). |
6075 | * </ul> |
6076 | * \endif |
6077 | */ |
6078 | keyWord = "dampingConst"; |
6079 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6080 | if (status == CAPS_SUCCESS0) { |
6081 | |
6082 | status = string_toDouble(keyValue, &dampingConst); |
6083 | if (keyValue != NULL((void*)0)) { |
6084 | EG_free(keyValue); |
6085 | keyValue = NULL((void*)0); |
6086 | } |
6087 | if (status != CAPS_SUCCESS0) return status; |
6088 | } |
6089 | |
6090 | /*! \page feaConnection |
6091 | * |
6092 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6093 | * <ul> |
6094 | * <li> <B>stressCoeff = 0.0 </B> </li> <br> |
6095 | * Stress coefficient of a spring element (scalar). |
6096 | * </ul> |
6097 | * \endif |
6098 | */ |
6099 | keyWord = "stressCoeff"; |
6100 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6101 | if (status == CAPS_SUCCESS0) { |
6102 | |
6103 | status = string_toDouble(keyValue, &stressCoeff); |
6104 | if (keyValue != NULL((void*)0)) { |
6105 | EG_free(keyValue); |
6106 | keyValue = NULL((void*)0); |
6107 | } |
6108 | if (status != CAPS_SUCCESS0) return status; |
6109 | } |
6110 | |
6111 | /*! \page feaConnection |
6112 | * |
6113 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6114 | * <ul> |
6115 | * <li> <B>mass = 0.0 </B> </li> <br> |
6116 | * Mass of a mass element (scalar). |
6117 | * </ul> |
6118 | * \endif |
6119 | */ |
6120 | keyWord = "mass"; |
6121 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6122 | if (status == CAPS_SUCCESS0) { |
6123 | |
6124 | status = string_toDouble(keyValue, &mass); |
6125 | if (keyValue != NULL((void*)0)) { |
6126 | EG_free(keyValue); |
6127 | keyValue = NULL((void*)0); |
6128 | } |
6129 | if (status != CAPS_SUCCESS0) return status; |
6130 | } |
6131 | |
6132 | /* \page feaConnection |
6133 | * |
6134 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6135 | * <ul> |
6136 | * <li> <B>glue = False </B> </li> <br> |
6137 | * Turn on gluing for the connection. |
6138 | * </ul> |
6139 | * \endif |
6140 | */ |
6141 | keyWord = "glue"; |
6142 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6143 | if (status == CAPS_SUCCESS0) { |
6144 | |
6145 | status = string_toBoolean(keyValue, &glue); |
6146 | if (keyValue != NULL((void*)0)) { |
6147 | EG_free(keyValue); |
6148 | keyValue = NULL((void*)0); |
6149 | } |
6150 | if (status != CAPS_SUCCESS0) return status; |
6151 | } |
6152 | |
6153 | /* \page feaConnection |
6154 | * |
6155 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6156 | * <ul> |
6157 | * <li> <B>glueNumMaster = 5 </B> </li> <br> |
6158 | * Maximum number of the masters for a glue connections. |
6159 | * </ul> |
6160 | * \endif |
6161 | */ |
6162 | keyWord = "glueNumMaster"; |
6163 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6164 | if (status == CAPS_SUCCESS0) { |
6165 | |
6166 | status = string_toInteger(keyValue, &glueNumMaster); |
6167 | if (keyValue != NULL((void*)0)) { |
6168 | EG_free(keyValue); |
6169 | keyValue = NULL((void*)0); |
6170 | } |
6171 | if (status != CAPS_SUCCESS0) return status; |
6172 | } |
6173 | |
6174 | /* \page feaConnection |
6175 | * |
6176 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6177 | * <ul> |
6178 | * <li> <B>glueSearchRadius = 0 </B> </li> <br> |
6179 | * Search radius when looking for masters for a glue connections. |
6180 | * </ul> |
6181 | * \endif |
6182 | */ |
6183 | keyWord = "glueSearchRadius"; |
6184 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6185 | if (status == CAPS_SUCCESS0) { |
6186 | |
6187 | status = string_toDouble(keyValue, &glueSearchRadius); |
6188 | if (keyValue != NULL((void*)0)) { |
6189 | EG_free(keyValue); |
6190 | keyValue = NULL((void*)0); |
6191 | } |
6192 | if (status != CAPS_SUCCESS0) return status; |
6193 | } |
6194 | |
6195 | /*! \page feaConnection |
6196 | * |
6197 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6198 | * <ul> |
6199 | * <li> <B>weighting = 1 </B> </li> <br> |
6200 | * Weighting factor for a rigid body interpolative connections. |
6201 | * </ul> |
6202 | * \endif |
6203 | */ |
6204 | keyWord = "weighting"; |
6205 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6206 | if (status == CAPS_SUCCESS0) { |
6207 | |
6208 | status = string_toDouble(keyValue, &weighting); |
6209 | if (keyValue != NULL((void*)0)) { |
6210 | EG_free(keyValue); |
6211 | keyValue = NULL((void*)0); |
6212 | } |
6213 | if (status != CAPS_SUCCESS0) return status; |
6214 | } |
6215 | |
6216 | /*! \page feaConnection |
6217 | * |
6218 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6219 | * <ul> |
6220 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
6221 | * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the |
6222 | * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...]. |
6223 | * </ul> |
6224 | * \endif |
6225 | */ |
6226 | numGroupName = 0; |
6227 | keyWord = "groupName"; |
6228 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6229 | if (status == CAPS_SUCCESS0) { |
6230 | |
6231 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
6232 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
6233 | AIM_NOTNULL(groupName, aimInfo, status){ if (groupName == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 6233, __func__, 1, "%s == NULL!", "groupName" ); goto cleanup; } }; |
6234 | |
6235 | if (status != CAPS_SUCCESS0) return status; |
6236 | if (glue == (int) true1 && connectionType != RigidBodyInterpolate) { |
6237 | printf("\tInvalid connectionType while glue = True, setting glue to False!\n"); |
6238 | glue = (int) false0; |
6239 | } |
6240 | |
6241 | if (glue == (int) true1 && connectionType == RigidBodyInterpolate) { |
6242 | status = fea_glueMesh(aimInfo, |
6243 | &feaProblem->feaMesh, |
6244 | i+1, //connectionID |
6245 | connectionType, |
6246 | dofDependent, |
6247 | connectionTuple[i].name, |
6248 | numGroupName, |
6249 | groupName, |
6250 | attrMap, |
6251 | glueNumMaster, |
6252 | glueSearchRadius, |
6253 | &feaProblem->numConnect, |
6254 | &feaProblem->feaConnect); |
6255 | if (status != CAPS_SUCCESS0) return status; |
6256 | |
6257 | } else { |
6258 | |
6259 | |
6260 | destNode = (int *) EG_alloc(feaProblem->feaMesh.numNode*sizeof(int)); |
6261 | if (destNode == NULL((void*)0)) { |
6262 | (void) string_freeArray(numGroupName, &groupName); |
6263 | return EGADS_MALLOC-4; |
6264 | } |
6265 | |
6266 | // Find the "source" node in the mesh |
6267 | for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) { |
6268 | |
6269 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData; |
6270 | |
6271 | // If "source" doesn't match - continue |
6272 | if (feaData->connectIndex != attrIndex) continue; |
6273 | |
6274 | numDestNode = 0; |
6275 | |
6276 | // Lets loop through the group names and create the connections |
6277 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
6278 | |
6279 | status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndexDest); |
6280 | if (status == CAPS_NOTFOUND-303) { |
6281 | printf("\tName %s not found in attribute map of capsConnects!!!!\n", groupName[groupIndex]); |
6282 | continue; |
6283 | } else if (status != CAPS_SUCCESS0) { |
6284 | (void) string_freeArray(numGroupName, &groupName); |
6285 | AIM_FREE(destNode){ EG_free(destNode); destNode = ((void*)0); }; |
6286 | return status; |
6287 | } |
6288 | |
6289 | // Find the "destination" node in the mesh |
6290 | for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) { |
6291 | |
6292 | feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData; |
6293 | |
6294 | // If the "destination" doesn't match - continue |
6295 | if (feaDataDest->connectIndex != attrIndexDest) continue; |
6296 | |
6297 | destNode[numDestNode] = feaProblem->feaMesh.node[nodeIndexDest].nodeID; |
6298 | numDestNode += 1; |
6299 | } // End destination loop |
6300 | |
6301 | } // End group loop |
6302 | |
6303 | if (numDestNode <= 0) { |
6304 | printf("\tNo destination nodes found for connection %s\n", connectionTuple[i].name); |
6305 | } else { |
6306 | |
6307 | status = fea_setConnection(connectionTuple[i].name, |
6308 | connectionType, |
6309 | i+1, |
6310 | feaProblem->feaMesh.numElement, |
6311 | dofDependent, |
6312 | stiffnessConst, |
6313 | dampingConst, |
6314 | stressCoeff, |
6315 | componentNumberStart, |
6316 | componentNumberEnd, |
6317 | feaProblem->feaMesh.node[nodeIndex].nodeID, |
6318 | weighting, |
6319 | componentNumberEnd, |
6320 | numDestNode, destNode, |
6321 | &feaProblem->numConnect, |
6322 | &feaProblem->feaConnect); |
6323 | if (status != CAPS_SUCCESS0) { |
6324 | (void) string_freeArray(numGroupName, &groupName); |
6325 | if (destNode !=NULL((void*)0)) EG_free(destNode); |
6326 | return status; |
6327 | } |
6328 | } |
6329 | } // End source loop |
6330 | } // Glue ifelse |
6331 | |
6332 | if (destNode !=NULL((void*)0)) EG_free(destNode); |
6333 | destNode = NULL((void*)0); |
6334 | |
6335 | status = string_freeArray(numGroupName, &groupName); |
6336 | if (status != CAPS_SUCCESS0) return status; |
6337 | |
6338 | } else { |
6339 | printf("\tNo \"%s\" specified for Connection tuple %s!\n", keyWord, connectionTuple[i].name); |
6340 | } |
6341 | |
6342 | // Create automatic connections from the "capsConnectLink" tag |
6343 | printf("\tLooking for automatic connections from the use of capsConnectLink for %s\n", connectionTuple[i].name); |
6344 | |
6345 | destNode = (int *) EG_alloc(feaProblem->feaMesh.numNode*sizeof(int)); |
6346 | if (destNode == NULL((void*)0)) return EGADS_MALLOC-4; |
6347 | |
6348 | // Find the "source" node in the mesh |
6349 | for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) { |
6350 | |
6351 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData; |
6352 | |
6353 | // If "source" doesn't match - continue |
6354 | if (feaData->connectIndex != attrIndex) continue; |
6355 | |
6356 | numDestNode = 0; |
6357 | // Find the "destination" node in the mesh |
6358 | for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) { |
6359 | |
6360 | feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData; |
6361 | |
6362 | // If the "destination" doesn't match - continue |
6363 | if (feaDataDest->connectLinkIndex != attrIndex) continue; |
6364 | |
6365 | destNode[numDestNode] = feaProblem->feaMesh.node[nodeIndexDest].nodeID; |
6366 | numDestNode += 1; |
6367 | } // End destination loop |
6368 | |
6369 | if (numDestNode > 0) { |
6370 | status = fea_setConnection(connectionTuple[i].name, |
6371 | connectionType, |
6372 | i+1, |
6373 | feaProblem->feaMesh.numElement, |
6374 | dofDependent, |
6375 | stiffnessConst, |
6376 | dampingConst, |
6377 | stressCoeff, |
6378 | componentNumberStart, |
6379 | componentNumberEnd, |
6380 | feaProblem->feaMesh.node[nodeIndex].nodeID, |
6381 | weighting, |
6382 | componentNumberEnd, |
6383 | numDestNode, destNode, |
6384 | &feaProblem->numConnect, |
6385 | &feaProblem->feaConnect); |
6386 | if (status != CAPS_SUCCESS0) { |
6387 | if (destNode !=NULL((void*)0)) EG_free(destNode); |
6388 | return status; |
6389 | } |
6390 | } |
6391 | |
6392 | if (numDestNode > 0) { |
6393 | printf("\t%d automatic connections were made for capsConnect %s (node id %d)\n", numDestNode, |
6394 | connectionTuple[i].name, |
6395 | feaProblem->feaMesh.node[nodeIndex].nodeID); |
6396 | } |
6397 | } // End source loop |
6398 | |
6399 | if (destNode !=NULL((void*)0)) EG_free(destNode); |
6400 | destNode = NULL((void*)0); |
6401 | |
6402 | } else { |
6403 | |
6404 | /*! \page feaConnection |
6405 | * \section keyStringConnection Single Value String |
6406 | * |
6407 | * If "Value" is a string, the string value may correspond to an entry in a predefined connection lookup |
6408 | * table. NOT YET IMPLEMENTED!!!! |
6409 | * |
6410 | */ |
6411 | |
6412 | // Call some look up table maybe? |
6413 | printf("\tError: Connection tuple value is expected to be a JSON string\n"); |
6414 | return CAPS_BADVALUE-311; |
6415 | |
6416 | } |
6417 | } |
6418 | |
6419 | if (keyValue != NULL((void*)0)) { |
6420 | EG_free(keyValue); |
6421 | keyValue = NULL((void*)0); |
6422 | } |
6423 | |
6424 | printf("\tDone getting FEA connections\n"); |
6425 | status = CAPS_SUCCESS0; |
6426 | cleanup: |
6427 | return status; |
6428 | } |
6429 | |
6430 | #ifdef FEA_GETCONNECTIONORIG_DEPREICATE |
6431 | // Get the Connections properties from a capsTuple and create connections based on the mesh |
6432 | static int fea_getConnectionOrig(int numConnectionTuple, |
6433 | capsTuple connectionTuple[], |
6434 | mapAttrToIndexStruct *attrMap, |
6435 | feaProblemStruct *feaProblem) { |
6436 | |
6437 | /* \page feaConnection FEA Connection |
6438 | * Structure for the connection tuple = ("Connection Name", "Value"). |
6439 | * "Connection Name" defines the reference name to the capsConnect being specified and denotes the "source" node |
6440 | * for the connection. |
6441 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringConnection) or a single string keyword |
6442 | * (see Section \ref keyStringConnection). |
6443 | */ |
6444 | |
6445 | int status; //Function return |
6446 | |
6447 | int i, groupIndex, nodeIndex, nodeIndexDest, counter = 0; // Indexing |
6448 | |
6449 | char *keyValue = NULL((void*)0); // Key values from tuple searches |
6450 | char *keyWord = NULL((void*)0); // Key words to find in the tuples |
6451 | |
6452 | int numGroupName = 0; |
6453 | char **groupName = NULL((void*)0); |
6454 | int attrIndex, attrIndexDest; |
6455 | |
6456 | // Values to set |
6457 | feaConnectionTypeEnum connectionType; |
6458 | int dofDependent = 0, componentNumberStart = 0, componentNumberEnd = 0; |
6459 | double stiffnessConst = 0.0, dampingConst = 0.0, stressCoeff = 0.0, mass = 0.0; |
6460 | |
6461 | feaMeshDataStruct *feaData, *feaDataDest; |
6462 | |
6463 | // Destroy our support structures coming in if aren't 0 and NULL already |
6464 | if (feaProblem->feaConnect != NULL((void*)0)) { |
6465 | for (i = 0; i < feaProblem->numConnect; i++) { |
6466 | status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]); |
6467 | if (status != CAPS_SUCCESS0) return status; |
6468 | } |
6469 | } |
6470 | if (feaProblem->feaConnect != NULL((void*)0)) EG_free(feaProblem->feaConnect); |
6471 | feaProblem->feaConnect = NULL((void*)0); |
6472 | feaProblem->numConnect = 0; |
6473 | |
6474 | printf("\nGetting FEA connections.......\n"); |
6475 | |
6476 | printf("\tNumber of connection tuples - %d\n", numConnectionTuple); |
6477 | |
6478 | // Loop through tuples and fill out the support structures |
6479 | for (i = 0; i < numConnectionTuple; i++) { |
6480 | |
6481 | // Reset defaults |
6482 | dofDependent = componentNumberStart = componentNumberEnd = 0; |
6483 | stiffnessConst = dampingConst = stressCoeff = mass = 0.0; |
6484 | |
6485 | printf("\tConnection name - %s\n", connectionTuple[i].name ); |
6486 | |
6487 | // Look for connection name in connection map |
6488 | status = get_mapAttrToIndexIndex(attrMap, (const char *) connectionTuple[i].name, &attrIndex); |
6489 | if (status == CAPS_NOTFOUND-303) { |
6490 | printf("\tName %s not found in attribute map of capsConnect!!!!\n", connectionTuple[i].name); |
6491 | continue; |
6492 | } else if (status != CAPS_SUCCESS0) return status; |
6493 | |
6494 | // Do we have a json string? |
6495 | if (strncmp(connectionTuple[i].value, "{", 1) == 0) { |
6496 | |
6497 | /* \page feaConnection |
6498 | * \section jsonStringConnection JSON String Dictionary |
6499 | * |
6500 | * If "Value" is JSON string dictionary |
6501 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6502 | * (e.g. "Value" = {"dofDependent": 1, "propertyType": "RigidBody"}) |
6503 | * \endif |
6504 | * the following keywords ( = default values) may be used: |
6505 | * |
6506 | * |
6507 | * \if (MYSTRAN || NASTRAN) |
6508 | * <ul> |
6509 | * <li> <B>connectionType = RigidBody</B> </li> <br> |
6510 | * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName". |
6511 | * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody. |
6512 | * </ul> |
6513 | * \elseif (ASTROS) |
6514 | * <ul> |
6515 | * <li> <B>connectionType = RigidBody</B> </li> <br> |
6516 | * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName". |
6517 | * Options: Mass (scalar), Spring (scalar), RigidBody. |
6518 | * </ul> |
6519 | * \elseif ABAQUS |
6520 | * |
6521 | * Something else .... |
6522 | * |
6523 | * \else |
6524 | * <ul> |
6525 | * <li> <B>connectionType = RigidBody</B> </li> <br> |
6526 | * Type of connection to apply to a given capsConnect pair defined by "Connection Name" and the "groupName". |
6527 | * Options: Mass (scalar), Spring (scalar), Damper (scalar), RigidBody. |
6528 | * </ul> |
6529 | * \endif |
6530 | * |
6531 | */ |
6532 | |
6533 | // Get connection Type |
6534 | keyWord = "connectionType"; |
6535 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6536 | if (status == CAPS_SUCCESS0) { |
6537 | |
6538 | //{UnknownConnection, Mass, Spring, Damper, RigidBody} |
6539 | if (strcasecmp(keyValue, "\"Mass\"") == 0) connectionType = Mass; |
6540 | else if (strcasecmp(keyValue, "\"Spring\"") == 0) connectionType = Spring; |
6541 | else if (strcasecmp(keyValue, "\"Damper\"") == 0) connectionType = Damper; |
6542 | else if (strcasecmp(keyValue, "\"RigidBody\"") == 0) connectionType = RigidBody; |
6543 | else { |
6544 | printf("\tUnrecognized \"%s\" specified (%s) for Connection tuple %s, current options are " |
6545 | "\"Mass, Spring, Damper, and RigidBody\"\n", keyWord, |
6546 | keyValue, |
6547 | connectionTuple[i].name); |
6548 | if (keyValue != NULL((void*)0)) { |
6549 | EG_free(keyValue); |
6550 | keyValue = NULL((void*)0); |
6551 | } |
6552 | |
6553 | return CAPS_NOTFOUND-303; |
6554 | } |
6555 | |
6556 | } else { |
6557 | |
6558 | printf("\tNo \"%s\" specified for Connection tuple %s, defaulting to RigidBody\n", keyWord, |
6559 | connectionTuple[i].name); |
6560 | connectionType = RigidBody; |
6561 | } |
6562 | |
6563 | /* \page feaConnection |
6564 | * |
6565 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6566 | * <ul> |
6567 | * <li> <B>dofDependent = 0 </B> </li> <br> |
6568 | * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three |
6569 | * directions). |
6570 | * </ul> |
6571 | * \elseif ABAQUS |
6572 | * |
6573 | * Something else .... |
6574 | * |
6575 | * \else |
6576 | * <ul> |
6577 | * <li> <B>dofDependent = 0 </B> </li> <br> |
6578 | * Component numbers / degrees of freedom of the dependent end of rigid body connections (ex. 123 - translation in all three |
6579 | * directions). |
6580 | * </ul> |
6581 | * \endif |
6582 | * |
6583 | */ |
6584 | keyWord = "dofDependent"; |
6585 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6586 | if (status == CAPS_SUCCESS0) { |
6587 | |
6588 | status = string_toInteger(keyValue, &dofDependent); |
6589 | if (keyValue != NULL((void*)0)) { |
6590 | EG_free(keyValue); |
6591 | keyValue = NULL((void*)0); |
6592 | } |
6593 | if (status != CAPS_SUCCESS0) return status; |
6594 | } |
6595 | |
6596 | |
6597 | /* \page feaConnection |
6598 | * |
6599 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6600 | * <ul> |
6601 | * <li> <B>componentNumberStart = 0 </B> </li> <br> |
6602 | * Component numbers / degrees of freedom of the starting point of the connection for mass, |
6603 | * spring, and damper elements (scalar) ( 0 <= Integer <= 6). |
6604 | * </ul> |
6605 | * \elseif ABAQUS |
6606 | * |
6607 | * Something else .... |
6608 | * |
6609 | * \else |
6610 | * <ul> |
6611 | * <li> <B>componentNumberStart = 0 </B> </li> <br> |
6612 | * Component numbers / degrees of freedom of the starting point of the connection for mass, |
6613 | * spring, and damper elements (scalar) ( 0 <= Integer <= 6). |
6614 | * </ul> |
6615 | * \endif |
6616 | * |
6617 | */ |
6618 | keyWord = "componentNumberStart"; |
6619 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6620 | if (status == CAPS_SUCCESS0) { |
6621 | |
6622 | status = string_toInteger(keyValue, &componentNumberStart); |
6623 | if (keyValue != NULL((void*)0)) { |
6624 | EG_free(keyValue); |
6625 | keyValue = NULL((void*)0); |
6626 | } |
6627 | if (status != CAPS_SUCCESS0) return status; |
6628 | } |
6629 | |
6630 | /* \page feaConnection |
6631 | * |
6632 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6633 | * <ul> |
6634 | * <li> <B>componentNumberEnd= 0 </B> </li> <br> |
6635 | * Component numbers / degrees of freedom of the ending point of the connection for mass, |
6636 | * spring, and damper elements (scalar) ( 0 <= Integer <= 6). |
6637 | * </ul> |
6638 | * \elseif ABAQUS |
6639 | * |
6640 | * Something else .... |
6641 | * |
6642 | * \else |
6643 | * <ul> |
6644 | * <li> <B>componentNumberEnd = 0 </B> </li> <br> |
6645 | * Component numbers / degrees of freedom of the ending point of the connection for mass, |
6646 | * spring, and damper elements (scalar) ( 0 <= Integer <= 6). |
6647 | * </ul> |
6648 | * \endif |
6649 | * |
6650 | */ |
6651 | keyWord = "componentNumberEnd"; |
6652 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6653 | if (status == CAPS_SUCCESS0) { |
6654 | |
6655 | status = string_toInteger(keyValue, &componentNumberEnd); |
6656 | if (keyValue != NULL((void*)0)) { |
6657 | EG_free(keyValue); |
6658 | keyValue = NULL((void*)0); |
6659 | } |
6660 | if (status != CAPS_SUCCESS0) return status; |
6661 | } |
6662 | |
6663 | /* \page feaConnection |
6664 | * |
6665 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6666 | * <ul> |
6667 | * <li> <B>stiffnessConst = 0.0 </B> </li> <br> |
6668 | * Stiffness constant of a spring element (scalar). |
6669 | * </ul> |
6670 | * \elseif ABAQUS |
6671 | * |
6672 | * Something else .... |
6673 | * |
6674 | * \else |
6675 | * <ul> |
6676 | * <li> <B>stiffnessConst = 0.00 </B> </li> <br> |
6677 | * Stiffness constant of a spring element (scalar). |
6678 | * </ul> |
6679 | * \endif |
6680 | * |
6681 | */ |
6682 | keyWord = "stiffnessConst"; |
6683 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6684 | if (status == CAPS_SUCCESS0) { |
6685 | |
6686 | status = string_toDouble(keyValue, &stiffnessConst); |
6687 | if (keyValue != NULL((void*)0)) { |
6688 | EG_free(keyValue); |
6689 | keyValue = NULL((void*)0); |
6690 | } |
6691 | if (status != CAPS_SUCCESS0) return status; |
6692 | } |
6693 | |
6694 | /* \page feaConnection |
6695 | * |
6696 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6697 | * <ul> |
6698 | * <li> <B>dampingConst = 0.0 </B> </li> <br> |
6699 | * Damping coefficient/constant of a spring or damping element (scalar). |
6700 | * </ul> |
6701 | * \elseif ABAQUS |
6702 | * |
6703 | * Something else .... |
6704 | * |
6705 | * \else |
6706 | * <ul> |
6707 | * <li> <B>dampingConst = 0.0 </B> </li> <br> |
6708 | * Damping constant of a spring or damping element (scalar). |
6709 | * </ul> |
6710 | * \endif |
6711 | * |
6712 | */ |
6713 | keyWord = "dampingConst"; |
6714 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6715 | if (status == CAPS_SUCCESS0) { |
6716 | |
6717 | status = string_toDouble(keyValue, &dampingConst); |
6718 | if (keyValue != NULL((void*)0)) { |
6719 | EG_free(keyValue); |
6720 | keyValue = NULL((void*)0); |
6721 | } |
6722 | if (status != CAPS_SUCCESS0) return status; |
6723 | } |
6724 | |
6725 | /* \page feaConnection |
6726 | * |
6727 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6728 | * <ul> |
6729 | * <li> <B>stressCoeff = 0.0 </B> </li> <br> |
6730 | * Stress coefficient of a spring element (scalar). |
6731 | * </ul> |
6732 | * \elseif ABAQUS |
6733 | * |
6734 | * Something else .... |
6735 | * |
6736 | * \else |
6737 | * <ul> |
6738 | * <li> <B>stressCoeff = 0.0 </B> </li> <br> |
6739 | * Stress coefficient of a spring element (scalar). |
6740 | * </ul> |
6741 | * \endif |
6742 | * |
6743 | */ |
6744 | keyWord = "stressCoeff"; |
6745 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6746 | if (status == CAPS_SUCCESS0) { |
6747 | |
6748 | status = string_toDouble(keyValue, &stressCoeff); |
6749 | if (keyValue != NULL((void*)0)) { |
6750 | EG_free(keyValue); |
6751 | keyValue = NULL((void*)0); |
6752 | } |
6753 | if (status != CAPS_SUCCESS0) return status; |
6754 | } |
6755 | |
6756 | /* \page feaConnection |
6757 | * |
6758 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6759 | * <ul> |
6760 | * <li> <B>mass = 0.0 </B> </li> <br> |
6761 | * Mass of a mass element (scalar). |
6762 | * </ul> |
6763 | * \elseif ABAQUS |
6764 | * |
6765 | * Something else .... |
6766 | * |
6767 | * \else |
6768 | * <ul> |
6769 | * <li> <B>mass = 0.0 </B> </li> <br> |
6770 | * Mass of a mass element (scalar). |
6771 | * </ul> |
6772 | * \endif |
6773 | * |
6774 | */ |
6775 | keyWord = "mass"; |
6776 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6777 | if (status == CAPS_SUCCESS0) { |
6778 | |
6779 | status = string_toDouble(keyValue, &mass); |
6780 | if (keyValue != NULL((void*)0)) { |
6781 | EG_free(keyValue); |
6782 | keyValue = NULL((void*)0); |
6783 | } |
6784 | if (status != CAPS_SUCCESS0) return status; |
6785 | } |
6786 | |
6787 | /* \page feaConnection |
6788 | * |
6789 | * \if (MYSTRAN || NASTRAN || ASTROS) |
6790 | * <ul> |
6791 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
6792 | * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the |
6793 | * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...]. |
6794 | * </ul> |
6795 | * \elseif ABAQUS |
6796 | * |
6797 | * Something else .... |
6798 | * |
6799 | * \else |
6800 | * <ul> |
6801 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
6802 | * Single or list of <c>capsConnect</c> names on which to connect the nodes found with the |
6803 | * tuple name ("Connection Name") to. (e.g. "Name1" or ["Name1","Name2",...]. |
6804 | * </ul> |
6805 | * \endif |
6806 | * |
6807 | */ |
6808 | numGroupName = 0; |
6809 | keyWord = "groupName"; |
6810 | status = search_jsonDictionary( connectionTuple[i].value, keyWord, &keyValue); |
6811 | if (status == CAPS_SUCCESS0) { |
6812 | |
6813 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
6814 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
6815 | keyValue = NULL((void*)0); |
6816 | |
6817 | if (status != CAPS_SUCCESS0) return status; |
6818 | |
6819 | // Lets loop through the group names and create the connections |
6820 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
6821 | |
6822 | status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndexDest); |
6823 | if (status == CAPS_NOTFOUND-303) { |
6824 | printf("\tName %s not found in attribute map of capsConnects!!!!\n", groupName[groupIndex]); |
6825 | continue; |
6826 | } else if (status != CAPS_SUCCESS0) { |
6827 | (void) string_freeArray(numGroupName, &groupName); |
6828 | return status; |
6829 | } |
6830 | |
6831 | // Find the "source" node in the mesh |
6832 | for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) { |
6833 | |
6834 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData; |
6835 | |
6836 | // If "source" doesn't match - continue |
6837 | if (feaData->connectIndex != attrIndex) continue; |
6838 | |
6839 | // Find the "destination" node in the mesh |
6840 | for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) { |
6841 | |
6842 | feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData; |
6843 | |
6844 | // If the "destination" doesn't match - continue |
6845 | if (feaDataDest->connectIndex != attrIndexDest) continue; |
6846 | |
6847 | feaProblem->numConnect += 1; |
6848 | |
6849 | if (feaProblem->numConnect == 1) { |
6850 | feaProblem->feaConnect = (feaConnectionStruct *) EG_alloc(sizeof(feaConnectionStruct)); |
6851 | } else { |
6852 | feaProblem->feaConnect = (feaConnectionStruct *) EG_reall(feaProblem->feaConnect , |
6853 | feaProblem->numConnect*sizeof(feaConnectionStruct)); |
6854 | } |
6855 | |
6856 | if (feaProblem->feaConnect == NULL((void*)0)) { |
6857 | feaProblem->numConnect = 0; |
6858 | (void) string_freeArray(numGroupName, &groupName); |
6859 | return EGADS_MALLOC-4; |
6860 | } |
6861 | |
6862 | status = initiate_feaConnectionStruct(&feaProblem->feaConnect[feaProblem->numConnect-1]); |
6863 | if (status != CAPS_SUCCESS0) return status; |
6864 | |
6865 | feaProblem->feaConnect[feaProblem->numConnect-1].name = (char *) EG_alloc((strlen(connectionTuple[i].name) + 1)*sizeof(char)); |
6866 | if (feaProblem->feaConnect[feaProblem->numConnect-1].name == NULL((void*)0)) { |
6867 | (void) string_freeArray(numGroupName, &groupName); |
6868 | return EGADS_MALLOC-4; |
6869 | } |
6870 | |
6871 | memcpy(feaProblem->feaConnect[feaProblem->numConnect-1].name, |
6872 | connectionTuple[i].name, |
6873 | strlen(connectionTuple[i].name)*sizeof(char)); |
6874 | feaProblem->feaConnect[feaProblem->numConnect-1].name[strlen(connectionTuple[i].name)] = '\0'; |
6875 | |
6876 | feaProblem->feaConnect[feaProblem->numConnect-1].connectionID = i+1; // ConnectionTuple index |
6877 | |
6878 | feaProblem->feaConnect[feaProblem->numConnect-1].connectionType = connectionType; |
6879 | feaProblem->feaConnect[feaProblem->numConnect-1].elementID = feaProblem->numConnect + feaProblem->feaMesh.numElement; |
6880 | feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[0] = feaProblem->feaMesh.node[nodeIndex].nodeID; |
6881 | feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[1] = feaProblem->feaMesh.node[nodeIndexDest].nodeID; |
6882 | |
6883 | feaProblem->feaConnect[feaProblem->numConnect-1].dofDependent = dofDependent; |
6884 | feaProblem->feaConnect[feaProblem->numConnect-1].stiffnessConst = stiffnessConst; |
6885 | feaProblem->feaConnect[feaProblem->numConnect-1].dampingConst = dampingConst; |
6886 | feaProblem->feaConnect[feaProblem->numConnect-1].stressCoeff = stressCoeff; |
6887 | feaProblem->feaConnect[feaProblem->numConnect-1].mass = mass; |
6888 | feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberStart = componentNumberStart; |
6889 | feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberEnd = componentNumberEnd; |
6890 | } // End destination loop |
6891 | } // End source loop |
6892 | } // End group loop |
6893 | |
6894 | status = string_freeArray(numGroupName, &groupName); |
6895 | if (status != CAPS_SUCCESS0) return status; |
6896 | |
6897 | } else { |
6898 | printf("\tNo \"%s\" specified for Connection tuple %s!\n", keyWord, |
6899 | connectionTuple[i].name); |
6900 | } |
6901 | |
6902 | |
6903 | // Create automatic connections from the "capsConnectLink" tag |
6904 | printf("\tLooking for automatic connections from the use of capsConnectLink for %s\n", connectionTuple[i].name); |
6905 | |
6906 | // Find the "source" node in the mesh |
6907 | for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) { |
6908 | |
6909 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData; |
6910 | |
6911 | // If "source" doesn't match - continue |
6912 | if (feaData->connectIndex != attrIndex) continue; |
6913 | |
6914 | counter = 0; |
6915 | // Find the "destination" node in the mesh |
6916 | for (nodeIndexDest = 0; nodeIndexDest < feaProblem->feaMesh.numNode; nodeIndexDest++) { |
6917 | |
6918 | feaDataDest = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndexDest].analysisData; |
6919 | |
6920 | // If the "destination" doesn't match - continue |
6921 | if (feaDataDest->connectLinkIndex != attrIndex) continue; |
6922 | |
6923 | counter +=1; |
6924 | |
6925 | feaProblem->numConnect += 1; |
6926 | |
6927 | if (feaProblem->numConnect == 1) { |
6928 | feaProblem->feaConnect = (feaConnectionStruct *) EG_alloc(sizeof(feaConnectionStruct)); |
6929 | } else { |
6930 | feaProblem->feaConnect = (feaConnectionStruct *) EG_reall(feaProblem->feaConnect , |
6931 | feaProblem->numConnect*sizeof(feaConnectionStruct)); |
6932 | } |
6933 | |
6934 | if (feaProblem->feaConnect == NULL((void*)0)) { |
6935 | feaProblem->numConnect = 0; |
6936 | return EGADS_MALLOC-4; |
6937 | } |
6938 | |
6939 | feaProblem->feaConnect[feaProblem->numConnect-1].name = (char *) EG_alloc((strlen(connectionTuple[i].name) + 1)*sizeof(char)); |
6940 | if (feaProblem->feaConnect[feaProblem->numConnect-1].name == NULL((void*)0)) return EGADS_MALLOC-4; |
6941 | |
6942 | memcpy(feaProblem->feaConnect[feaProblem->numConnect-1].name, |
6943 | connectionTuple[i].name, |
6944 | strlen(connectionTuple[i].name)*sizeof(char)); |
6945 | feaProblem->feaConnect[feaProblem->numConnect-1].name[strlen(connectionTuple[i].name)] = '\0'; |
6946 | |
6947 | feaProblem->feaConnect[feaProblem->numConnect-1].connectionID = i+1; // ConnectionTuple index |
6948 | |
6949 | feaProblem->feaConnect[feaProblem->numConnect-1].connectionType = connectionType; |
6950 | feaProblem->feaConnect[feaProblem->numConnect-1].elementID = feaProblem->numConnect + feaProblem->feaMesh.numElement; |
6951 | feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[0] = feaProblem->feaMesh.node[nodeIndex].nodeID; |
6952 | feaProblem->feaConnect[feaProblem->numConnect-1].connectivity[1] = feaProblem->feaMesh.node[nodeIndexDest].nodeID; |
6953 | |
6954 | feaProblem->feaConnect[feaProblem->numConnect-1].dofDependent = dofDependent; |
6955 | feaProblem->feaConnect[feaProblem->numConnect-1].stiffnessConst = stiffnessConst; |
6956 | feaProblem->feaConnect[feaProblem->numConnect-1].dampingConst = dampingConst; |
6957 | feaProblem->feaConnect[feaProblem->numConnect-1].stressCoeff = stressCoeff; |
6958 | feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberStart = componentNumberStart; |
6959 | feaProblem->feaConnect[feaProblem->numConnect-1].componentNumberEnd = componentNumberEnd; |
6960 | } // End destination loop |
6961 | |
6962 | printf("\t%d automatic connections were made for capsConnect %s\n", counter, |
6963 | connectionTuple[i].name); |
6964 | } // End source loop |
6965 | } else { |
6966 | |
6967 | /* \page feaConnection |
6968 | * \section keyStringConnection Single Value String |
6969 | * |
6970 | * If "Value" is a string, the string value may correspond to an entry in a predefined connection lookup |
6971 | * table. NOT YET IMPLEMENTED!!!! |
6972 | * |
6973 | */ |
6974 | |
6975 | // Call some look up table maybe? |
6976 | printf("\tError: Connection tuple value is expected to be a JSON string\n"); |
6977 | return CAPS_BADVALUE-311; |
6978 | |
6979 | } |
6980 | } |
6981 | |
6982 | if (keyValue != NULL((void*)0)) { |
6983 | EG_free(keyValue); |
6984 | keyValue = NULL((void*)0); |
6985 | } |
6986 | |
6987 | printf("\tDone getting FEA connections\n"); |
6988 | return CAPS_SUCCESS0; |
6989 | } |
6990 | #endif |
6991 | |
6992 | // Get the load properties from a capsTuple |
6993 | int fea_getLoad(void *aimInfo, |
6994 | int numLoadTuple, |
6995 | capsTuple loadTuple[], |
6996 | mapAttrToIndexStruct *attrMap, |
6997 | feaProblemStruct *feaProblem) { |
6998 | |
6999 | /*! \page feaLoad FEA Load |
7000 | * Structure for the load tuple = ("Load Name", "Value"). |
7001 | * "Load Name" defines the reference name for the load being specified. |
7002 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringLoad) or a single string keyword |
7003 | * (see Section \ref keyStringLoad). |
7004 | */ |
7005 | |
7006 | int status; //Function return |
7007 | |
7008 | int i, groupIndex, attrIndex, nodeIndex, elementIndex; // Indexing |
7009 | |
7010 | char *keyValue = NULL((void*)0); // Key values from tuple searches |
7011 | char *keyWord = NULL((void*)0); // Key words to find in the tuples |
7012 | |
7013 | int numGroupName = 0; |
7014 | char **groupName = NULL((void*)0); |
7015 | |
7016 | char *tempString = NULL((void*)0); // Temporary string holder |
7017 | |
7018 | feaMeshDataStruct *feaData; |
7019 | |
7020 | // Destroy our load structures coming in if aren't 0 and NULL already |
7021 | if (feaProblem->feaLoad != NULL((void*)0)) { |
7022 | for (i = 0; i < feaProblem->numLoad; i++) { |
7023 | status = destroy_feaLoadStruct(&feaProblem->feaLoad[i]); |
7024 | if (status != CAPS_SUCCESS0) return status; |
7025 | } |
7026 | } |
7027 | AIM_FREE(feaProblem->feaLoad){ EG_free(feaProblem->feaLoad); feaProblem->feaLoad = ( (void*)0); }; |
7028 | feaProblem->numLoad = 0; |
7029 | |
7030 | printf("\nGetting FEA loads.......\n"); |
7031 | |
7032 | feaProblem->numLoad = numLoadTuple; |
7033 | |
7034 | printf("\tNumber of loads - %d\n", feaProblem->numLoad); |
7035 | |
7036 | // Allocate loads |
7037 | if (feaProblem->numLoad > 0) { |
7038 | feaProblem->feaLoad = (feaLoadStruct *) EG_alloc(feaProblem->numLoad * sizeof(feaLoadStruct)); |
7039 | |
7040 | if (feaProblem->feaLoad == NULL((void*)0) ) return EGADS_MALLOC-4; |
7041 | } |
7042 | |
7043 | // Initiate loads to default values |
7044 | for (i = 0; i < feaProblem->numLoad; i++) { |
7045 | status = initiate_feaLoadStruct(&feaProblem->feaLoad[i]); |
7046 | if (status != CAPS_SUCCESS0) return status; |
7047 | } |
7048 | |
7049 | // Loop through tuples and fill out the load structures |
7050 | for (i = 0; i < feaProblem->numLoad; i++) { |
7051 | |
7052 | printf("\tLoad name - %s\n", loadTuple[i].name ); |
7053 | |
7054 | // Set load name to tuple attribute name |
7055 | feaProblem->feaLoad[i].name = (char *) EG_alloc((strlen(loadTuple[i].name) + 1)*sizeof(char)); |
7056 | if (feaProblem->feaLoad[i].name == NULL((void*)0)) return EGADS_MALLOC-4; |
7057 | |
7058 | memcpy(feaProblem->feaLoad[i].name, loadTuple[i].name, strlen(loadTuple[i].name)*sizeof(char)); |
7059 | feaProblem->feaLoad[i].name[strlen(loadTuple[i].name)] = '\0'; |
7060 | |
7061 | // Set load id -> 1 bias |
7062 | feaProblem->feaLoad[i].loadID = i+1; |
7063 | |
7064 | // Do we have a json string? |
7065 | if (strncmp(loadTuple[i].value, "{", 1) == 0) { |
7066 | //printf("JSON String - %s\n", constraintTuple[i].value); |
7067 | |
7068 | /*! \page feaLoad |
7069 | * \section jsonStringLoad JSON String Dictionary |
7070 | * |
7071 | * If "Value" is JSON string dictionary |
7072 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS) |
7073 | * (e.g. "Value" = {"groupName": "plate", "loadType": "Pressure", "pressureForce": 2000000.0}) |
7074 | * \endif |
7075 | * the following keywords ( = default values) may be used: |
7076 | * |
7077 | * \if (MYSTRAN || NASTRAN || ASTROS || TACS) |
7078 | * <ul> |
7079 | * <li> <B>loadType = "(no default)"</B> </li> <br> |
7080 | * Type of load. Options: "GridForce", "GridMoment", "Rotational", "Thermal", |
7081 | * "Pressure", "PressureDistribute", "PressureExternal", "TermalExternal", "Gravity". |
7082 | * </ul> |
7083 | * \elseif ABAQUS |
7084 | * <ul> |
7085 | * <li> <B>loadType = "(no default)"</B> </li> <br> |
7086 | * Type of load. Options: "Pressure", "Gravity". |
7087 | * </ul> |
7088 | * \elseif HSM |
7089 | * <ul> |
7090 | * <li> <B>loadType = "(no default)"</B> </li> <br> |
7091 | * Type of load. Options: "GridForce", "GridMoment", "LineForce", "LineMoment", "Rotational", |
7092 | * "Pressure", "PressureDistribute", "PressureExternal", "Gravity". |
7093 | * </ul> |
7094 | * \else |
7095 | * \endif |
7096 | * |
7097 | */ |
7098 | // Get load Type |
7099 | keyWord = "loadType"; |
7100 | status = search_jsonDictionary(loadTuple[i].value, keyWord, &keyValue); |
7101 | if (status == CAPS_SUCCESS0) { |
7102 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 7102, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
7103 | |
7104 | //{UnknownLoad, GridForce, GridMoment, Gravity, Pressure, Rotational, Thermal} |
7105 | if (strcasecmp(keyValue, "\"GridForce\"") == 0) feaProblem->feaLoad[i].loadType = GridForce; |
7106 | else if (strcasecmp(keyValue, "\"GridMoment\"") == 0) feaProblem->feaLoad[i].loadType = GridMoment; |
7107 | else if (strcasecmp(keyValue, "\"LineForce\"") == 0) feaProblem->feaLoad[i].loadType = LineForce; |
7108 | else if (strcasecmp(keyValue, "\"LineMoment\"") == 0) feaProblem->feaLoad[i].loadType = LineMoment; |
7109 | else if (strcasecmp(keyValue, "\"Rotational\"") == 0) feaProblem->feaLoad[i].loadType = Rotational; |
7110 | else if (strcasecmp(keyValue, "\"Thermal\"") == 0) feaProblem->feaLoad[i].loadType = Thermal; |
7111 | else if (strcasecmp(keyValue, "\"Pressure\"") == 0) feaProblem->feaLoad[i].loadType = Pressure; |
7112 | else if (strcasecmp(keyValue, "\"PressureDistribute\"") == 0) feaProblem->feaLoad[i].loadType = PressureDistribute; |
7113 | else if (strcasecmp(keyValue, "\"PressureExternal\"") == 0) feaProblem->feaLoad[i].loadType = PressureExternal; |
7114 | else if (strcasecmp(keyValue, "\"ThermalExternal\"") == 0) feaProblem->feaLoad[i].loadType = ThermalExternal; |
7115 | else if (strcasecmp(keyValue, "\"Gravity\"") == 0) feaProblem->feaLoad[i].loadType = Gravity; |
7116 | else { |
7117 | printf("\tUnrecognized \"%s\" specified (%s) for Load tuple %s\n", keyWord, |
7118 | keyValue, |
7119 | loadTuple[i].name); |
7120 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
7121 | return CAPS_NOTFOUND-303; |
7122 | } |
7123 | |
7124 | } else { |
7125 | printf("\t\"loadType\" variable not found in tuple %s, this is required input!!\n", loadTuple[i].name); |
7126 | |
7127 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
7128 | return status; |
7129 | } |
7130 | |
7131 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
7132 | |
7133 | // Get load node/element set |
7134 | /*! \page feaLoad |
7135 | * |
7136 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS) |
7137 | * <ul> |
7138 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
7139 | * Single or list of <c>capsLoad</c> names on which to apply the load |
7140 | * (e.g. "Name1" or ["Name1","Name2",...]. If not provided, the load tuple name will be |
7141 | * used. |
7142 | * </ul> |
7143 | * \endif |
7144 | * |
7145 | */ |
7146 | keyWord = "groupName"; |
7147 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7148 | if (status == CAPS_SUCCESS0) { |
7149 | |
7150 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
7151 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
7152 | keyValue = NULL((void*)0); |
7153 | |
7154 | if (status != CAPS_SUCCESS0) return status; |
7155 | |
7156 | } else { |
7157 | |
7158 | printf("\tNo \"%s\" specified for Load tuple %s, going to use load name\n", keyWord, |
7159 | loadTuple[i].name); |
7160 | |
7161 | status = string_toStringDynamicArray(loadTuple[i].name, &numGroupName, &groupName); |
7162 | if (status != CAPS_SUCCESS0) return status; |
7163 | |
7164 | } |
7165 | |
7166 | // Determine how many element/point loads we have |
7167 | feaProblem->feaLoad[i].numGridID = 0; |
7168 | feaProblem->feaLoad[i].numElementID = 0; |
7169 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
7170 | |
7171 | // Do nothing for PressureExternal, ThermalExternal, and Gravity loads |
7172 | if (feaProblem->feaLoad[i].loadType == PressureExternal) continue; |
7173 | if (feaProblem->feaLoad[i].loadType == ThermalExternal) continue; |
7174 | if (feaProblem->feaLoad[i].loadType == Gravity) continue; |
7175 | |
7176 | status = get_mapAttrToIndexIndex(attrMap, (const char *) groupName[groupIndex], &attrIndex); |
7177 | |
7178 | if (status == CAPS_NOTFOUND-303) { |
7179 | printf("\tName %s not found in attribute map of capsLoads!!!!\n", groupName[groupIndex]); |
7180 | continue; |
7181 | |
7182 | } else if (status != CAPS_SUCCESS0) { |
7183 | |
7184 | (void) string_freeArray(numGroupName, &groupName); |
7185 | return status; |
7186 | } |
7187 | |
7188 | //{UnknownLoad, GridForce, GridMoment, Gravity, Pressure, Rotational, Thermal} |
7189 | if (feaProblem->feaLoad[i].loadType == GridForce || |
7190 | feaProblem->feaLoad[i].loadType == GridMoment || |
7191 | feaProblem->feaLoad[i].loadType == Rotational || |
7192 | feaProblem->feaLoad[i].loadType == Thermal) { |
7193 | |
7194 | // Now lets loop through the grid to see how many grid points have the attrIndex |
7195 | for (nodeIndex = 0; nodeIndex < feaProblem->feaMesh.numNode; nodeIndex++ ) { |
7196 | |
7197 | if (feaProblem->feaMesh.node[nodeIndex].analysisType == MeshStructure) { |
7198 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.node[nodeIndex].analysisData; |
7199 | } else { |
7200 | continue; |
7201 | } |
7202 | |
7203 | if (feaData->loadIndex == attrIndex) { |
7204 | |
7205 | feaProblem->feaLoad[i].numGridID += 1; |
7206 | |
7207 | // Allocate/Re-allocate grid ID array |
7208 | if (feaProblem->feaLoad[i].numGridID == 1) { |
7209 | |
7210 | feaProblem->feaLoad[i].gridIDSet = (int *) EG_alloc(feaProblem->feaLoad[i].numGridID*sizeof(int)); |
7211 | |
7212 | } else { |
7213 | |
7214 | feaProblem->feaLoad[i].gridIDSet = (int *) EG_reall(feaProblem->feaLoad[i].gridIDSet, |
7215 | feaProblem->feaLoad[i].numGridID*sizeof(int)); |
7216 | } |
7217 | |
7218 | if (feaProblem->feaLoad[i].gridIDSet == NULL((void*)0)) { |
7219 | status = string_freeArray(numGroupName, &groupName); |
7220 | if (status == CAPS_SUCCESS0) return status; |
7221 | |
7222 | return EGADS_MALLOC-4; |
7223 | } |
7224 | |
7225 | // Set grid ID value -> 1 bias |
7226 | feaProblem->feaLoad[i].gridIDSet[feaProblem->feaLoad[i].numGridID-1] = feaProblem->feaMesh.node[nodeIndex].nodeID; |
7227 | |
7228 | //printf("GroupName = %s %d\n", groupName[groupIndex], feaProblem->feaMesh.node[nodeIndex].nodeID); |
7229 | |
7230 | } |
7231 | } |
7232 | |
7233 | } else if (feaProblem->feaLoad[i].loadType == LineForce || |
7234 | feaProblem->feaLoad[i].loadType == LineMoment ) { |
7235 | |
7236 | for (elementIndex = 0; elementIndex < feaProblem->feaMesh.numElement; elementIndex++) { |
7237 | |
7238 | if (feaProblem->feaMesh.element[elementIndex].elementType != Line) { |
7239 | continue; |
7240 | } |
7241 | |
7242 | if (feaProblem->feaMesh.element[elementIndex].analysisType == MeshStructure) { |
7243 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.element[elementIndex].analysisData; |
7244 | } else { |
7245 | continue; |
7246 | } |
7247 | |
7248 | if (feaData->loadIndex == attrIndex) { |
7249 | |
7250 | feaProblem->feaLoad[i].numElementID += 1; |
7251 | |
7252 | feaProblem->feaLoad[i].elementIDSet = (int *) EG_reall(feaProblem->feaLoad[i].elementIDSet, |
7253 | feaProblem->feaLoad[i].numElementID*sizeof(int)); |
7254 | |
7255 | if (feaProblem->feaLoad[i].elementIDSet == NULL((void*)0)) { |
7256 | string_freeArray(numGroupName, &groupName); |
7257 | return EGADS_MALLOC-4; |
7258 | } |
7259 | |
7260 | // Set element ID value -> 1 bias |
7261 | feaProblem->feaLoad[i].elementIDSet[feaProblem->feaLoad[i].numElementID-1] = feaProblem->feaMesh.element[elementIndex].elementID; |
7262 | } |
7263 | } |
7264 | |
7265 | } else if (feaProblem->feaLoad[i].loadType == LineForce || |
7266 | feaProblem->feaLoad[i].loadType == LineMoment || |
7267 | feaProblem->feaLoad[i].loadType == Pressure || |
7268 | feaProblem->feaLoad[i].loadType == PressureDistribute) { |
7269 | |
7270 | // Now lets loop through the elements to see how many elements have the attrIndex |
7271 | |
7272 | // Element types - CTRIA3, CTRIA3K, CQUAD4, CQUAD4K |
7273 | for (elementIndex = 0; elementIndex < feaProblem->feaMesh.numElement; elementIndex++) { |
7274 | |
7275 | if (feaProblem->feaMesh.element[elementIndex].elementType != Triangle && |
7276 | feaProblem->feaMesh.element[elementIndex].elementType != Triangle_6 && |
7277 | feaProblem->feaMesh.element[elementIndex].elementType != Quadrilateral && |
7278 | feaProblem->feaMesh.element[elementIndex].elementType != Quadrilateral_8) { |
7279 | continue; |
7280 | } |
7281 | |
7282 | if (feaProblem->feaMesh.element[elementIndex].analysisType == MeshStructure) { |
7283 | feaData = (feaMeshDataStruct *) feaProblem->feaMesh.element[elementIndex].analysisData; |
7284 | } else { |
7285 | continue; |
7286 | } |
7287 | |
7288 | if (feaData->loadIndex == attrIndex) { |
7289 | |
7290 | feaProblem->feaLoad[i].numElementID += 1; |
7291 | |
7292 | // Allocate/Re-allocate element ID array |
7293 | if (feaProblem->feaLoad[i].numElementID == 1) { |
7294 | |
7295 | feaProblem->feaLoad[i].elementIDSet = (int *) EG_alloc(feaProblem->feaLoad[i].numElementID*sizeof(int)); |
7296 | |
7297 | } else { |
7298 | |
7299 | feaProblem->feaLoad[i].elementIDSet = (int *) EG_reall(feaProblem->feaLoad[i].elementIDSet, |
7300 | feaProblem->feaLoad[i].numElementID*sizeof(int)); |
7301 | } |
7302 | |
7303 | if (feaProblem->feaLoad[i].elementIDSet == NULL((void*)0)) { |
7304 | string_freeArray(numGroupName, &groupName); |
7305 | return EGADS_MALLOC-4; |
7306 | } |
7307 | |
7308 | // Set element ID value -> 1 bias |
7309 | feaProblem->feaLoad[i].elementIDSet[feaProblem->feaLoad[i].numElementID-1] = feaProblem->feaMesh.element[elementIndex].elementID; |
7310 | } |
7311 | } |
7312 | |
7313 | } |
7314 | } // End attr search loop |
7315 | |
7316 | status = string_freeArray(numGroupName, &groupName); |
7317 | if (status != CAPS_SUCCESS0) return status; |
7318 | groupName = NULL((void*)0); |
7319 | |
7320 | // Free keyValue (just in case) |
7321 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
7322 | |
7323 | //Fill up load properties |
7324 | |
7325 | /*! \page feaLoad |
7326 | * |
7327 | * \if (MYSTRAN || NASTRAN || ASTROS || TACS) |
7328 | * <ul> |
7329 | * <li> <B>loadScaleFactor = 1.0 </B> </li> <br> |
7330 | * Scale factor to use when combining loads. |
7331 | * </ul> |
7332 | * \endif |
7333 | */ |
7334 | keyWord = "loadScaleFactor"; |
7335 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7336 | if (status == CAPS_SUCCESS0) { |
7337 | |
7338 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].loadScaleFactor); |
7339 | if (keyValue != NULL((void*)0)) { |
7340 | EG_free(keyValue); |
7341 | keyValue = NULL((void*)0); |
7342 | } |
7343 | if (status != CAPS_SUCCESS0) return status; |
7344 | } |
7345 | |
7346 | /*! \page feaLoad |
7347 | * |
7348 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS) |
7349 | * <ul> |
7350 | * <li> <B>forceScaleFactor = 0.0 </B> </li> <br> |
7351 | * Overall scale factor for the force for a "GridForce" load. |
7352 | * </ul> |
7353 | * \endif |
7354 | */ |
7355 | keyWord = "forceScaleFactor"; |
7356 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7357 | if (status == CAPS_SUCCESS0) { |
7358 | |
7359 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].forceScaleFactor); |
7360 | if (keyValue != NULL((void*)0)) { |
7361 | EG_free(keyValue); |
7362 | keyValue = NULL((void*)0); |
7363 | } |
7364 | if (status != CAPS_SUCCESS0) return status; |
7365 | } |
7366 | |
7367 | /*! \page feaLoad |
7368 | * |
7369 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS) |
7370 | * <ul> |
7371 | * <li> <B>directionVector = [0.0, 0.0, 0.0] </B> </li> <br> |
7372 | * X-, y-, and z- components of the force vector for a "GridForce", "GridMoment", or "Gravity" load. |
7373 | * </ul> |
7374 | * \elseif ABAQUS |
7375 | * <ul> |
7376 | * <li> <B>directionVector = [0.0, 0.0, 0.0] </B> </li> <br> |
7377 | * X-, y-, and z- components of the force vector for a "Gravity" load. |
7378 | * </ul> |
7379 | * \endif |
7380 | * |
7381 | */ |
7382 | keyWord = "directionVector"; |
7383 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7384 | if (status == CAPS_SUCCESS0) { |
7385 | |
7386 | status = string_toDoubleArray(keyValue, |
7387 | (int) sizeof(feaProblem->feaLoad[i].directionVector)/sizeof(double), |
7388 | feaProblem->feaLoad[i].directionVector); |
7389 | if (keyValue != NULL((void*)0)) { |
7390 | EG_free(keyValue); |
7391 | keyValue = NULL((void*)0); |
7392 | } |
7393 | if (status != CAPS_SUCCESS0) return status; |
7394 | } |
7395 | |
7396 | /*! \page feaLoad |
7397 | * |
7398 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || TACS) |
7399 | * <ul> |
7400 | * <li> <B>momentScaleFactor = 0.0 </B> </li> <br> |
7401 | * Overall scale factor for the moment for a "GridMoment" load. |
7402 | * </ul> |
7403 | * \endif |
7404 | * |
7405 | */ |
7406 | keyWord = "momentScaleFactor"; |
7407 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7408 | if (status == CAPS_SUCCESS0) { |
7409 | |
7410 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].momentScaleFactor); |
7411 | if (keyValue != NULL((void*)0)) { |
7412 | EG_free(keyValue); |
7413 | keyValue = NULL((void*)0); |
7414 | } |
7415 | if (status != CAPS_SUCCESS0) return status; |
7416 | } |
7417 | |
7418 | /*! \page feaLoad |
7419 | * |
7420 | * \if (MYSTRAN || NASTRAN || HSM || ASTROS || ABAQUS || TACS) |
7421 | * <ul> |
7422 | * <li> <B>gravityAcceleration = 0.0 </B> </li> <br> |
7423 | * Acceleration value for a "Gravity" load. |
7424 | * </ul> |
7425 | * \endif |
7426 | */ |
7427 | keyWord = "gravityAcceleration"; |
7428 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7429 | if (status == CAPS_SUCCESS0) { |
7430 | |
7431 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].gravityAcceleration); |
7432 | if (keyValue != NULL((void*)0)) { |
7433 | EG_free(keyValue); |
7434 | keyValue = NULL((void*)0); |
7435 | } |
7436 | if (status != CAPS_SUCCESS0) return status; |
7437 | } |
7438 | |
7439 | /*! \page feaLoad |
7440 | * |
7441 | * \if MYSTRAN |
7442 | * <ul> |
7443 | * <li> <B>pressureForce = 0.0 </B> </li> <br> |
7444 | * Uniform pressure force for a "Pressure" load (only applicable to 2D elements). |
7445 | * </ul> |
7446 | * \elseif (NASTRAN || HSM || ASTROS || ABAQUS || TACS) |
7447 | * <ul> |
7448 | * <li> <B>pressureForce = 0.0 </B> </li> <br> |
7449 | * Uniform pressure force for a "Pressure" load. |
7450 | * </ul> |
7451 | * \endif |
7452 | */ |
7453 | keyWord = "pressureForce"; |
7454 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7455 | if (status == CAPS_SUCCESS0) { |
7456 | |
7457 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].pressureForce); |
7458 | if (keyValue != NULL((void*)0)) { |
7459 | EG_free(keyValue); |
7460 | keyValue = NULL((void*)0); |
7461 | } |
7462 | if (status != CAPS_SUCCESS0) return status; |
7463 | } |
7464 | |
7465 | /*! \page feaLoad |
7466 | * |
7467 | * \if MYSTRAN |
7468 | * <ul> |
7469 | * <li> <B>pressureDistributeForce = [0.0, 0.0, 0.0, 0.0] </B> </li> <br> |
7470 | * Distributed pressure force for a "PressureDistribute" load (only applicable to 2D elements). The four values |
7471 | * correspond to the 4 (quadrilateral elements) or 3 (triangle elements) node locations. |
7472 | * </ul> |
7473 | * \elseif (NASTRAN || HSM || ASTROS || TACS) |
7474 | * <ul> |
7475 | * <li> <B>pressureDistributeForce = [0.0, 0.0, 0.0, 0.0] </B> </li> <br> |
7476 | * Distributed pressure force for a "PressureDistribute" load. The four values |
7477 | * correspond to the 4 (quadrilateral elements) or 3 (triangle elements) node locations. |
7478 | * </ul> |
7479 | * \endif |
7480 | */ |
7481 | keyWord = "pressureDistributeForce"; |
7482 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7483 | if (status == CAPS_SUCCESS0) { |
7484 | |
7485 | status = string_toDoubleArray(keyValue, |
7486 | (int) sizeof(feaProblem->feaLoad[i].pressureDistributeForce)/sizeof(double), |
7487 | feaProblem->feaLoad[i].pressureDistributeForce); |
7488 | if (keyValue != NULL((void*)0)) { |
7489 | EG_free(keyValue); |
7490 | keyValue = NULL((void*)0); |
7491 | } |
7492 | if (status != CAPS_SUCCESS0) return status; |
7493 | } |
7494 | |
7495 | /*! \page feaLoad |
7496 | * |
7497 | * \if (MYSTRAN || NASTRAN || ASTROS || TACS) |
7498 | * <ul> |
7499 | * <li> <B>angularVelScaleFactor = 0.0 </B> </li> <br> |
7500 | * An overall scale factor for the angular velocity in revolutions per unit time for a "Rotational" load. |
7501 | * </ul> |
7502 | * \elseif HSM |
7503 | * <ul> |
7504 | * <li> <B>angularVelScaleFactor = 0.0 </B> </li> <br> |
7505 | * An overall scale factor for the angular velocity in revolutions per unit time for a "Rotational" load - applied in a global sense. |
7506 | * </ul> |
7507 | * \endif |
7508 | */ |
7509 | keyWord = "angularVelScaleFactor"; |
7510 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7511 | if (status == CAPS_SUCCESS0) { |
7512 | |
7513 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].angularVelScaleFactor); |
7514 | if (keyValue != NULL((void*)0)) { |
7515 | EG_free(keyValue); |
7516 | keyValue = NULL((void*)0); |
7517 | } |
7518 | if (status != CAPS_SUCCESS0) return status; |
7519 | } |
7520 | |
7521 | /*! \page feaLoad |
7522 | * |
7523 | * \if (MYSTRAN || NASTRAN || ASTROS || TACS) |
7524 | * <ul> |
7525 | * <li> <B>angularAccScaleFactor = 0.0 </B> </li> <br> |
7526 | * An overall scale factor for the angular acceleration in revolutions per unit time squared for a "Rotational" load. |
7527 | * </ul> |
7528 | * \elseif HSM |
7529 | * <ul> |
7530 | * <li> <B>angularAccScaleFactor = 0.0 </B> </li> <br> |
7531 | * An overall scale factor for the angular acceleration in revolutions per unit time squared for a "Rotational" load - applied in a global sense. |
7532 | * </ul> |
7533 | * \endif |
7534 | */ |
7535 | keyWord = "angularAccScaleFactor"; |
7536 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7537 | if (status == CAPS_SUCCESS0) { |
7538 | |
7539 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].angularAccScaleFactor); |
7540 | if (keyValue != NULL((void*)0)) { |
7541 | EG_free(keyValue); |
7542 | keyValue = NULL((void*)0); |
7543 | } |
7544 | if (status != CAPS_SUCCESS0) return status; |
7545 | } |
7546 | |
7547 | /*! \page feaLoad |
7548 | * |
7549 | * \if (MYSTRAN || NASTRAN || ASTROS || TACS) |
7550 | * <ul> |
7551 | * <li> <B>coordinateSystem = "(no default)" </B> </li> <br> |
7552 | * Name of coordinate system in which defined force components are in reference to. If no value |
7553 | * is provided the global system is assumed. |
7554 | * </ul> |
7555 | * \endif |
7556 | * |
7557 | */ |
7558 | keyWord = "coordinateSystem"; |
7559 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7560 | if (status == CAPS_SUCCESS0) { |
7561 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 7561, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
7562 | |
7563 | tempString = string_removeQuotation(keyValue); |
7564 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 7564, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
7565 | |
7566 | for (attrIndex = 0; attrIndex < feaProblem->numCoordSystem; attrIndex++) { |
7567 | |
7568 | if (strcasecmp(tempString, feaProblem->feaCoordSystem[attrIndex].name) == 0) { |
7569 | feaProblem->feaLoad[i].coordSystemID = feaProblem->feaCoordSystem[attrIndex].coordSystemID; |
7570 | break; |
7571 | } |
7572 | } |
7573 | |
7574 | if (feaProblem->feaLoad[i].coordSystemID == 0) { |
7575 | printf("\tCoordinate system %s not found, defaulting to global system!!", keyValue); |
7576 | } |
7577 | |
7578 | if (keyValue != NULL((void*)0)) { |
7579 | EG_free(keyValue); |
7580 | keyValue = NULL((void*)0); |
7581 | } |
7582 | |
7583 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
7584 | } |
7585 | |
7586 | |
7587 | /*! \page feaLoad |
7588 | * |
7589 | * \if (MYSTRAN || NASTRAN || ASTROS || TACS) |
7590 | * <ul> |
7591 | * <li> <B>temperature = 0.0 </B> </li> <br> |
7592 | * Temperature at a given node for a "Temperature" load. |
7593 | * </ul> |
7594 | * \endif |
7595 | */ |
7596 | keyWord = "temperature"; |
7597 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7598 | if (status == CAPS_SUCCESS0) { |
7599 | |
7600 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].temperature); |
7601 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
7602 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 7602 , __func__, 0); goto cleanup; }; |
7603 | } |
7604 | |
7605 | /*! \page feaLoad |
7606 | * |
7607 | * \if (MYSTRAN || NASTRAN || ASTROS || TACS) |
7608 | * <ul> |
7609 | * <li> <B>temperatureDefault = 0.0 </B> </li> <br> |
7610 | * Default temperature at a node not explicitly being used for a "Temperature" load. |
7611 | * </ul> |
7612 | * \endif |
7613 | */ |
7614 | keyWord = "temperatureDefault"; |
7615 | status = search_jsonDictionary( loadTuple[i].value, keyWord, &keyValue); |
7616 | if (status == CAPS_SUCCESS0) { |
7617 | |
7618 | status = string_toDouble(keyValue, &feaProblem->feaLoad[i].temperatureDefault); |
7619 | if (keyValue != NULL((void*)0)) { |
7620 | EG_free(keyValue); |
7621 | keyValue = NULL((void*)0); |
7622 | } |
7623 | if (status != CAPS_SUCCESS0) return status; |
7624 | } |
7625 | |
7626 | |
7627 | } else { // if not a JSON string search |
7628 | |
7629 | /*! \page feaLoad |
7630 | * \section keyStringLoad Single Value String |
7631 | * |
7632 | * If "Value" is a string, the string value may correspond to an entry in a predefined load lookup |
7633 | * table. NOT YET IMPLEMENTED!!!! |
7634 | * |
7635 | */ |
7636 | |
7637 | // Call some look up table maybe? |
7638 | printf("\tError: Load tuple value is expected to be a JSON string\n"); |
7639 | return CAPS_BADVALUE-311; |
7640 | } |
7641 | } |
7642 | |
7643 | /// Free keyValue and tempString (just in case) |
7644 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
7645 | |
7646 | if (tempString != NULL((void*)0)) EG_free(tempString); |
7647 | |
7648 | printf("\tDone getting FEA loads\n"); |
7649 | status = CAPS_SUCCESS0; |
7650 | cleanup: |
7651 | return status; |
7652 | } |
7653 | |
7654 | // Get the analysis properties from a capsTuple |
7655 | int fea_getAnalysis(void *aimInfo, |
7656 | int numAnalysisTuple, |
7657 | capsTuple analysisTuple[], |
7658 | feaProblemStruct *feaProblem) { |
7659 | |
7660 | /*! \page feaAnalysis FEA Analysis |
7661 | * Structure for the analysis tuple = (`Analysis Name', `Value'). |
7662 | * 'Analysis Name' defines the reference name for the analysis being specified. |
7663 | * The "Value" can either be a JSON String dictionary (see Section \ref jsonStringAnalysis) or a single string keyword |
7664 | * (see Section \ref keyStringAnalysis). |
7665 | */ |
7666 | |
7667 | int status; //Function return |
7668 | |
7669 | int i, j, groupIndex, attrIndex; // Indexing |
7670 | |
7671 | |
7672 | char *keyValue = NULL((void*)0); |
7673 | char *keyWord = NULL((void*)0); |
7674 | |
7675 | char *tempString = NULL((void*)0); |
7676 | |
7677 | char **groupName = NULL((void*)0); |
7678 | int numGroupName = 0; |
7679 | |
7680 | int tempInt=0; // Temporary integer |
7681 | |
7682 | // Destroy our analysis structures coming in if aren't 0 and NULL already |
7683 | if (feaProblem->feaAnalysis != NULL((void*)0)) { |
7684 | for (i = 0; i < feaProblem->numAnalysis; i++) { |
7685 | status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]); |
7686 | if (status != CAPS_SUCCESS0) return status; |
7687 | } |
7688 | } |
7689 | |
7690 | if (feaProblem->feaAnalysis != NULL((void*)0)) EG_free(feaProblem->feaAnalysis); |
7691 | feaProblem->feaAnalysis = NULL((void*)0); |
7692 | feaProblem->numAnalysis = 0; |
7693 | |
7694 | printf("\nGetting FEA analyses.......\n"); |
7695 | |
7696 | feaProblem->numAnalysis = numAnalysisTuple; |
7697 | |
7698 | printf("\tNumber of analyses - %d\n", feaProblem->numAnalysis); |
7699 | |
7700 | if (feaProblem->numAnalysis > 0) { |
7701 | feaProblem->feaAnalysis = (feaAnalysisStruct *) EG_alloc(feaProblem->numAnalysis * sizeof(feaAnalysisStruct)); |
7702 | } else { |
7703 | printf("\tNumber of analysis values in input tuple is 0\n"); |
7704 | return CAPS_NOTFOUND-303; |
7705 | } |
7706 | |
7707 | for (i = 0; i < feaProblem->numAnalysis; i++) { |
7708 | status = initiate_feaAnalysisStruct(&feaProblem->feaAnalysis[i]); |
7709 | if (status != CAPS_SUCCESS0) return status; |
7710 | } |
7711 | |
7712 | for (i = 0; i < feaProblem->numAnalysis; i++) { |
7713 | |
7714 | printf("\tAnalysis name - %s\n", analysisTuple[i].name); |
7715 | |
7716 | feaProblem->feaAnalysis[i].name = (char *) EG_alloc(((strlen(analysisTuple[i].name)) + 1)*sizeof(char)); |
7717 | if (feaProblem->feaAnalysis[i].name == NULL((void*)0)) return EGADS_MALLOC-4; |
7718 | |
7719 | memcpy(feaProblem->feaAnalysis[i].name, analysisTuple[i].name, strlen(analysisTuple[i].name)*sizeof(char)); |
7720 | feaProblem->feaAnalysis[i].name[strlen(analysisTuple[i].name)] = '\0'; |
7721 | |
7722 | feaProblem->feaAnalysis[i].analysisID = i + 1; |
7723 | |
7724 | // Do we have a json string? |
7725 | if (strncmp(analysisTuple[i].value, "{", 1) == 0) { |
7726 | //printf("JSON String - %s\n", analysisTuple[i].value); |
7727 | |
7728 | /*! \page feaAnalysis |
7729 | * \section jsonStringAnalysis JSON String Dictionary |
7730 | * |
7731 | * If "Value" is JSON string dictionary |
7732 | * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
7733 | * (e.g. "Value" = {"numDesiredEigenvalue": 10, "eigenNormaliztion": "MASS", "numEstEigenvalue": 1, |
7734 | * "extractionMethod": "GIV", "frequencyRange": [0, 10000]}) |
7735 | * \endif |
7736 | * the following keywords ( = default values) may be used: |
7737 | * |
7738 | * \if MYSTRAN |
7739 | * <ul> |
7740 | * <li> <B>analysisType = "Modal"</B> </li> <br> |
7741 | * Type of load. Options: "Modal", "Static". |
7742 | * </ul> |
7743 | * \elseif (NASTRAN || ASTROS) |
7744 | * <ul> |
7745 | * <li> <B>analysisType = "Modal"</B> </li> <br> |
7746 | * Type of load. Options: "Modal", "Static", "AeroelasticTrim", "AeroelasticFlutter" |
7747 | * Note: "AeroelasticStatic" is still supported but refers to "AeroelasticTrim" |
7748 | * Note: "Optimization" and "StaticOpt" are not valid - Optimization is initialized by the Analysis_Type AIM Input |
7749 | * </ul> |
7750 | * \elseif ABAQUS |
7751 | * <ul> |
7752 | * <li> <B>analysisType = "Modal"</B> </li> <br> |
7753 | * Type of load. Options: "Modal", "Static" |
7754 | * </ul> |
7755 | * \endif |
7756 | * |
7757 | */ |
7758 | // Get analysis Type |
7759 | keyWord = "analysisType"; |
7760 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
7761 | if (status == CAPS_SUCCESS0) { |
7762 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 7762, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
7763 | |
7764 | //{UnknownAnalysis, Modal, Static} |
7765 | if (strcasecmp(keyValue, "\"Modal\"") == 0) feaProblem->feaAnalysis[i].analysisType = Modal; |
7766 | else if (strcasecmp(keyValue, "\"Static\"") == 0) feaProblem->feaAnalysis[i].analysisType = Static; |
7767 | else if (strcasecmp(keyValue, "\"StaticOpt\"") == 0) feaProblem->feaAnalysis[i].analysisType = Optimization; |
7768 | else if (strcasecmp(keyValue, "\"Optimization\"") == 0) feaProblem->feaAnalysis[i].analysisType = Optimization; |
7769 | else if (strcasecmp(keyValue, "\"AeroelasticTrim\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticTrim; |
7770 | else if (strcasecmp(keyValue, "\"AeroelasticStatic\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticTrim; |
7771 | else if (strcasecmp(keyValue, "\"AeroelasticFlutter\"") == 0) feaProblem->feaAnalysis[i].analysisType = AeroelasticFlutter; |
7772 | else { |
7773 | |
7774 | printf("\tUnrecognized \"%s\" specified (%s) for Analysis tuple %s, defaulting to \"Modal\"\n", keyWord, |
7775 | keyValue, |
7776 | analysisTuple[i].name); |
7777 | feaProblem->feaAnalysis[i].analysisType = Modal; |
7778 | } |
7779 | |
7780 | } else { |
7781 | |
7782 | printf("\tNo \"%s\" specified for Analysis tuple %s, defaulting to \"Modal\"\n", keyWord, analysisTuple[i].name); |
7783 | |
7784 | feaProblem->feaAnalysis[i].analysisType = Modal; |
7785 | } |
7786 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
7787 | |
7788 | // Get loads to be applied for a given analysis |
7789 | |
7790 | /*! \page feaAnalysis |
7791 | * |
7792 | * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
7793 | * <ul> |
7794 | * <li> <B>analysisLoad = "(no default)"</B> </li> <br> |
7795 | * Single or list of "Load Name"s defined in \ref feaLoad in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...]. |
7796 | * </ul> |
7797 | * \endif |
7798 | */ |
7799 | keyWord = "analysisLoad"; |
7800 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
7801 | if (status == CAPS_SUCCESS0) { |
7802 | |
7803 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
7804 | if (keyValue != NULL((void*)0)) { |
7805 | EG_free(keyValue); |
7806 | keyValue = NULL((void*)0); |
7807 | } |
7808 | |
7809 | if (status != CAPS_SUCCESS0) return status; |
7810 | |
7811 | feaProblem->feaAnalysis[i].numLoad = 0; |
7812 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
7813 | |
7814 | for (attrIndex = 0; attrIndex < feaProblem->numLoad; attrIndex++) { |
7815 | |
7816 | if (strcasecmp(feaProblem->feaLoad[attrIndex].name, groupName[groupIndex]) == 0) { |
7817 | |
7818 | // if (feaProblem->feaLoad[attrIndex].loadType == Thermal) { |
7819 | // printf("Combining Thermal loads in a subcase isn't supported yet!\n"); |
7820 | // status = string_freeArray(numGroupName, &groupName); |
7821 | // if (status != CAPS_SUCCESS) return status; |
7822 | // groupName = NULL; |
7823 | // return CAPS_BADVALUE; |
7824 | // } |
7825 | |
7826 | feaProblem->feaAnalysis[i].numLoad += 1; |
7827 | |
7828 | if (feaProblem->feaAnalysis[i].numLoad == 1) { |
7829 | |
7830 | feaProblem->feaAnalysis[i].loadSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numLoad *sizeof(int)); |
7831 | |
7832 | } else { |
7833 | |
7834 | feaProblem->feaAnalysis[i].loadSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].loadSetID, |
7835 | feaProblem->feaAnalysis[i].numLoad *sizeof(int)); |
7836 | } |
7837 | |
7838 | if (feaProblem->feaAnalysis[i].loadSetID == NULL((void*)0)) { |
7839 | status = string_freeArray(numGroupName, &groupName); |
7840 | if (status != CAPS_SUCCESS0) return status; |
7841 | groupName = NULL((void*)0); |
7842 | return EGADS_MALLOC-4; |
7843 | } |
7844 | |
7845 | feaProblem->feaAnalysis[i].loadSetID[feaProblem->feaAnalysis[i].numLoad-1] = feaProblem->feaLoad[attrIndex].loadID; |
7846 | break; |
7847 | } |
7848 | } |
7849 | |
7850 | if (feaProblem->feaAnalysis[i].numLoad != groupIndex+1) { |
7851 | |
7852 | printf("\tWarning: Analysis load name, %s, not found in feaLoad structure\n", groupName[groupIndex]); |
7853 | |
7854 | } |
7855 | } |
7856 | |
7857 | status = string_freeArray(numGroupName, &groupName); |
7858 | if (status != CAPS_SUCCESS0) return status; |
7859 | groupName = NULL((void*)0); |
7860 | |
7861 | } |
7862 | |
7863 | // Get constraints to be applied for a given analysis |
7864 | /*! \page feaAnalysis |
7865 | * |
7866 | * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
7867 | * <ul> |
7868 | * <li> <B>analysisConstraint = "(no default)"</B> </li> <br> |
7869 | * Single or list of "Constraint Name"s defined in \ref feaConstraint in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...]. |
7870 | * </ul> |
7871 | * \endif |
7872 | */ |
7873 | keyWord = "analysisConstraint"; |
7874 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
7875 | if (status == CAPS_SUCCESS0) { |
7876 | |
7877 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
7878 | if (keyValue != NULL((void*)0)) { |
7879 | EG_free(keyValue); |
7880 | keyValue = NULL((void*)0); |
7881 | } |
7882 | |
7883 | if (status != CAPS_SUCCESS0) return status; |
7884 | |
7885 | feaProblem->feaAnalysis[i].numConstraint = 0; |
7886 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
7887 | |
7888 | for (attrIndex = 0; attrIndex < feaProblem->numConstraint; attrIndex++) { |
7889 | |
7890 | if (strcasecmp(feaProblem->feaConstraint[attrIndex].name, groupName[groupIndex]) == 0) { |
7891 | |
7892 | feaProblem->feaAnalysis[i].numConstraint += 1; |
7893 | |
7894 | if (feaProblem->feaAnalysis[i].numConstraint == 1) { |
7895 | |
7896 | feaProblem->feaAnalysis[i].constraintSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numConstraint *sizeof(int)); |
7897 | |
7898 | } else { |
7899 | |
7900 | feaProblem->feaAnalysis[i].constraintSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].constraintSetID, |
7901 | feaProblem->feaAnalysis[i].numConstraint *sizeof(int)); |
7902 | } |
7903 | |
7904 | if (feaProblem->feaAnalysis[i].constraintSetID == NULL((void*)0)) { |
7905 | status = string_freeArray(numGroupName, &groupName); |
7906 | if (status != CAPS_SUCCESS0) return status; |
7907 | groupName = NULL((void*)0); |
7908 | return EGADS_MALLOC-4; |
7909 | } |
7910 | |
7911 | feaProblem->feaAnalysis[i].constraintSetID[feaProblem->feaAnalysis[i].numConstraint-1] = feaProblem->feaConstraint[attrIndex].constraintID; |
7912 | break; |
7913 | } |
7914 | } |
7915 | |
7916 | if (feaProblem->feaAnalysis[i].numConstraint != groupIndex+1) { |
7917 | |
7918 | printf("\tWarning: Analysis constraint name, %s, not found in feaConstraint structure\n", groupName[groupIndex]); |
7919 | |
7920 | } |
7921 | } |
7922 | |
7923 | status = string_freeArray(numGroupName, &groupName); |
7924 | if (status != CAPS_SUCCESS0) return status; |
7925 | groupName = NULL((void*)0); |
7926 | |
7927 | } |
7928 | |
7929 | // Get supports to be applied for a given analysis |
7930 | /*! \page feaAnalysis |
7931 | * |
7932 | * \if (MYSTRAN || NASTRAN || ASTROS) |
7933 | * <ul> |
7934 | * <li> <B>analysisSupport = "(no default)"</B> </li> <br> |
7935 | * Single or list of "Support Name"s defined in \ref feaSupport in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...]. |
7936 | * </ul> |
7937 | * \endif |
7938 | * |
7939 | */ |
7940 | keyWord = "analysisSupport"; |
7941 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
7942 | if (status == CAPS_SUCCESS0) { |
7943 | |
7944 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
7945 | if (keyValue != NULL((void*)0)) { |
7946 | EG_free(keyValue); |
7947 | keyValue = NULL((void*)0); |
7948 | } |
7949 | |
7950 | if (status != CAPS_SUCCESS0) return status; |
7951 | |
7952 | feaProblem->feaAnalysis[i].numSupport = 0; |
7953 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
7954 | |
7955 | for (attrIndex = 0; attrIndex < feaProblem->numSupport; attrIndex++) { |
7956 | |
7957 | if (strcasecmp(feaProblem->feaSupport[attrIndex].name, groupName[groupIndex]) == 0) { |
7958 | |
7959 | feaProblem->feaAnalysis[i].numSupport += 1; |
7960 | |
7961 | if (feaProblem->feaAnalysis[i].numSupport == 1) { |
7962 | |
7963 | feaProblem->feaAnalysis[i].supportSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numSupport *sizeof(int)); |
7964 | |
7965 | } else { |
7966 | |
7967 | feaProblem->feaAnalysis[i].supportSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].supportSetID, |
7968 | feaProblem->feaAnalysis[i].numSupport *sizeof(int)); |
7969 | } |
7970 | |
7971 | if (feaProblem->feaAnalysis[i].supportSetID == NULL((void*)0)) { |
7972 | status = string_freeArray(numGroupName, &groupName); |
7973 | if (status != CAPS_SUCCESS0) return status; |
7974 | groupName = NULL((void*)0); |
7975 | return EGADS_MALLOC-4; |
7976 | } |
7977 | |
7978 | feaProblem->feaAnalysis[i].supportSetID[feaProblem->feaAnalysis[i].numSupport-1] = feaProblem->feaSupport[attrIndex].supportID; |
7979 | break; |
7980 | } |
7981 | } |
7982 | |
7983 | if (feaProblem->feaAnalysis[i].numSupport != groupIndex+1) { |
7984 | |
7985 | printf("\tWarning: Analysis support name, %s, not found in feaSupport structure\n", groupName[groupIndex]); |
7986 | |
7987 | } |
7988 | } |
7989 | |
7990 | status = string_freeArray(numGroupName, &groupName); |
7991 | if (status != CAPS_SUCCESS0) return status; |
7992 | groupName = NULL((void*)0); |
7993 | |
7994 | } |
7995 | |
7996 | // Get design constraints to be applied for a given analysis |
7997 | |
7998 | /*! \page feaAnalysis |
7999 | * |
8000 | * \if (NASTRAN || ASTROS) |
8001 | * <ul> |
8002 | * <li> <B>analysisDesignConstraint = "(no default)"</B> </li> <br> |
8003 | * Single or list of "Design Constraint Name"s defined in \ref feaDesignConstraint in which to use for the analysis (e.g. "Name1" or ["Name1","Name2",...]. |
8004 | * </ul> |
8005 | * \endif |
8006 | */ |
8007 | keyWord = "analysisDesignConstraint"; |
8008 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8009 | if (status == CAPS_SUCCESS0) { |
8010 | |
8011 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
8012 | if (keyValue != NULL((void*)0)) { |
8013 | EG_free(keyValue); |
8014 | keyValue = NULL((void*)0); |
8015 | } |
8016 | |
8017 | if (status != CAPS_SUCCESS0) return status; |
8018 | |
8019 | feaProblem->feaAnalysis[i].numDesignConstraint = 0; |
8020 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
8021 | |
8022 | for (attrIndex = 0; attrIndex < feaProblem->numDesignConstraint; attrIndex++) { |
8023 | |
8024 | if (strcasecmp(feaProblem->feaDesignConstraint[attrIndex].name, groupName[groupIndex]) == 0) { |
8025 | |
8026 | feaProblem->feaAnalysis[i].numDesignConstraint += 1; |
8027 | |
8028 | if (feaProblem->feaAnalysis[i].numDesignConstraint == 1) { |
8029 | |
8030 | feaProblem->feaAnalysis[i].designConstraintSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numDesignConstraint *sizeof(int)); |
8031 | |
8032 | } else { |
8033 | |
8034 | feaProblem->feaAnalysis[i].designConstraintSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].designConstraintSetID, |
8035 | feaProblem->feaAnalysis[i].numDesignConstraint *sizeof(int)); |
8036 | } |
8037 | |
8038 | if (feaProblem->feaAnalysis[i].designConstraintSetID == NULL((void*)0)) { |
8039 | status = string_freeArray(numGroupName, &groupName); |
8040 | if (status != CAPS_SUCCESS0) return status; |
8041 | groupName = NULL((void*)0); |
8042 | return EGADS_MALLOC-4; |
8043 | } |
8044 | |
8045 | feaProblem->feaAnalysis[i].designConstraintSetID[feaProblem->feaAnalysis[i].numDesignConstraint-1] = feaProblem->feaDesignConstraint[attrIndex].designConstraintID; |
8046 | break; |
8047 | } |
8048 | } |
8049 | |
8050 | if (feaProblem->feaAnalysis[i].numDesignConstraint != groupIndex+1) { |
8051 | |
8052 | printf("\tWarning: Analysis design constraint name, %s, not found in feaDesignConstraint structure\n", groupName[groupIndex]); |
8053 | |
8054 | } |
8055 | } |
8056 | |
8057 | status = string_freeArray(numGroupName, &groupName); |
8058 | if (status != CAPS_SUCCESS0) { |
8059 | if (tempString != NULL((void*)0)) EG_free(tempString); |
8060 | |
8061 | return status; |
8062 | } |
8063 | groupName = NULL((void*)0); |
8064 | |
8065 | } |
8066 | |
8067 | //Fill up analysis properties |
8068 | /*! \page feaAnalysis |
8069 | * |
8070 | * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
8071 | * <ul> |
8072 | * <li> <B>extractionMethod = "(no default)"</B> </li> <br> |
8073 | * Extraction method for modal analysis. |
8074 | * </ul> |
8075 | * \endif |
8076 | */ |
8077 | keyWord = "extractionMethod"; |
8078 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8079 | if (status == CAPS_SUCCESS0) { |
8080 | |
8081 | tempString = string_removeQuotation(keyValue); |
8082 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 8082, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
8083 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
8084 | |
8085 | feaProblem->feaAnalysis[i].extractionMethod = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
8086 | if(feaProblem->feaAnalysis[i].extractionMethod == NULL((void*)0)) { |
8087 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8088 | status = EGADS_MALLOC-4; |
8089 | goto cleanup; |
8090 | } |
8091 | |
8092 | memcpy(feaProblem->feaAnalysis[i].extractionMethod, tempString, strlen(tempString)*sizeof(char)); |
8093 | feaProblem->feaAnalysis[i].extractionMethod[strlen(tempString)] = '\0'; |
8094 | |
8095 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8096 | } |
8097 | |
8098 | |
8099 | /*! \page feaAnalysis |
8100 | * |
8101 | * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
8102 | * <ul> |
8103 | * <li> <B>frequencyRange = [0.0, 0.0] </B> </li> <br> |
8104 | * Frequency range of interest for modal analysis. |
8105 | * </ul> |
8106 | * \endif |
8107 | */ |
8108 | keyWord = "frequencyRange"; |
8109 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8110 | if (status == CAPS_SUCCESS0) { |
8111 | |
8112 | status = string_toDoubleArray(keyValue, |
8113 | (int) sizeof(feaProblem->feaAnalysis[i].frequencyRange)/sizeof(double), |
8114 | feaProblem->feaAnalysis[i].frequencyRange); |
8115 | if (keyValue != NULL((void*)0)) { |
8116 | EG_free(keyValue); |
8117 | keyValue = NULL((void*)0); |
8118 | } |
8119 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8119 , __func__, 0); goto cleanup; }; |
8120 | } |
8121 | |
8122 | /*! \page feaAnalysis |
8123 | * |
8124 | * \if (MYSTRAN || NASTRAN || ASTROS) |
8125 | * <ul> |
8126 | * <li> <B>numEstEigenvalue = 0 </B> </li> <br> |
8127 | * Number of estimated eigenvalues for modal analysis. |
8128 | * </ul> |
8129 | * \endif |
8130 | */ |
8131 | keyWord = "numEstEigenvalue"; |
8132 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8133 | if (status == CAPS_SUCCESS0) { |
8134 | |
8135 | status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].numEstEigenvalue); |
8136 | if (keyValue != NULL((void*)0)) { |
8137 | EG_free(keyValue); |
8138 | keyValue = NULL((void*)0); |
8139 | } |
8140 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8140 , __func__, 0); goto cleanup; }; |
8141 | } |
8142 | |
8143 | /*! \page feaAnalysis |
8144 | * |
8145 | * \if (MYSTRAN || NASTRAN || ASTROS || ABAQUS) |
8146 | * <ul> |
8147 | * <li> <B>numDesiredEigenvalue = 0</B> </li> <br> |
8148 | * Number of desired eigenvalues for modal analysis. |
8149 | * </ul> |
8150 | * \endif |
8151 | * |
8152 | */ |
8153 | keyWord = "numDesiredEigenvalue"; |
8154 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8155 | if (status == CAPS_SUCCESS0) { |
8156 | |
8157 | status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].numDesiredEigenvalue); |
8158 | if (keyValue != NULL((void*)0)) { |
8159 | EG_free(keyValue); |
8160 | keyValue = NULL((void*)0); |
8161 | } |
8162 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8162 , __func__, 0); goto cleanup; }; |
8163 | } |
8164 | |
8165 | /*! \page feaAnalysis |
8166 | * |
8167 | * \if (MYSTRAN || NASTRAN || ASTROS) |
8168 | * <ul> |
8169 | * <li> <B>eigenNormaliztion = "(no default)"</B> </li> <br> |
8170 | * Method of eigenvector renormalization. Options: "POINT", "MAX", "MASS" |
8171 | * </ul> |
8172 | * \elseif ABAQUS |
8173 | * <ul> |
8174 | * <li> <B>eigenNormaliztion = "(no default)"</B> </li> <br> |
8175 | * Method of eigenvector renormalization. Options: "DISPLACEMENT", "MASS" |
8176 | * </ul> |
8177 | * \endif |
8178 | */ |
8179 | keyWord = "eigenNormaliztion"; |
8180 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8181 | if (status == CAPS_SUCCESS0) { |
8182 | |
8183 | tempString = string_removeQuotation(keyValue); |
8184 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 8184, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
8185 | |
8186 | feaProblem->feaAnalysis[i].eigenNormaliztion = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
8187 | if(feaProblem->feaAnalysis[i].eigenNormaliztion == NULL((void*)0)) { |
8188 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8189 | |
8190 | return EGADS_MALLOC-4; |
8191 | } |
8192 | |
8193 | memcpy(feaProblem->feaAnalysis[i].eigenNormaliztion, tempString, strlen(tempString)*sizeof(char)); |
8194 | feaProblem->feaAnalysis[i].eigenNormaliztion[strlen(tempString)] = '\0'; |
8195 | |
8196 | if (keyValue != NULL((void*)0)) { |
8197 | EG_free(keyValue); |
8198 | keyValue = NULL((void*)0); |
8199 | } |
8200 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8201 | } |
8202 | |
8203 | /*! \page feaAnalysis |
8204 | * |
8205 | * \if (MYSTRAN || NASTRAN || ASTROS) |
8206 | * <ul> |
8207 | * <li> <B>gridNormaliztion = 0 </B> </li> <br> |
8208 | * Grid point to be used in normalizing eigenvector to 1.0 when using eigenNormaliztion = "POINT" |
8209 | * </ul> |
8210 | * \endif |
8211 | */ |
8212 | keyWord = "gridNormaliztion"; |
8213 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8214 | if (status == CAPS_SUCCESS0) { |
8215 | |
8216 | status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].gridNormaliztion); |
8217 | if (keyValue != NULL((void*)0)) { |
8218 | EG_free(keyValue); |
8219 | keyValue = NULL((void*)0); |
8220 | } |
8221 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8221 , __func__, 0); goto cleanup; }; |
8222 | } |
8223 | |
8224 | /*! \page feaAnalysis |
8225 | * |
8226 | * \if (MYSTRAN || NASTRAN || ASTROS) |
8227 | * <ul> |
8228 | * <li> <B>componentNormaliztion = 0</B> </li> <br> |
8229 | * Degree of freedom about "gridNormalization" to be used in normalizing eigenvector to 1.0 |
8230 | * when using eigenNormaliztion = "POINT" |
8231 | * </ul> |
8232 | * \endif |
8233 | * |
8234 | */ |
8235 | keyWord = "componentNormaliztion"; |
8236 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8237 | if (status == CAPS_SUCCESS0) { |
8238 | |
8239 | status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].componentNormaliztion); |
8240 | if (keyValue != NULL((void*)0)) { |
8241 | EG_free(keyValue); |
8242 | keyValue = NULL((void*)0); |
8243 | } |
8244 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8244 , __func__, 0); goto cleanup; }; |
8245 | } |
8246 | |
8247 | /*! \page feaAnalysis |
8248 | * |
8249 | * \if (MYSTRAN || NASTRAN) |
8250 | * <ul> |
8251 | * <li> <B>lanczosMode = 2</B> </li> <br> |
8252 | * Mode refers to the Lanczos mode type to be used in the solution. In mode 3 the mass matrix, Maa,must |
8253 | * be nonsingular whereas in mode 2 the matrix K aa - sigma*Maa must be nonsingular |
8254 | * </ul> |
8255 | * \endif |
8256 | */ |
8257 | keyWord = "lanczosMode"; |
8258 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8259 | if (status == CAPS_SUCCESS0) { |
8260 | |
8261 | status = string_toInteger(keyValue, &feaProblem->feaAnalysis[i].lanczosMode); |
8262 | if (keyValue != NULL((void*)0)) { |
8263 | EG_free(keyValue); |
8264 | keyValue = NULL((void*)0); |
8265 | } |
8266 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8266 , __func__, 0); goto cleanup; }; |
8267 | } |
8268 | |
8269 | /*! \page feaAnalysis |
8270 | * |
8271 | * \if (MYSTRAN || NASTRAN) |
8272 | * <ul> |
8273 | * <li> <B>lanczosType = "(no default)"</B> </li> <br> |
8274 | * Lanczos matrix type. Options: DPB, DGB. |
8275 | * </ul> |
8276 | * \endif |
8277 | */ |
8278 | keyWord = "lanczosType"; |
8279 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8280 | if (status == CAPS_SUCCESS0) { |
8281 | |
8282 | tempString = string_removeQuotation(keyValue); |
8283 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 8283, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
8284 | |
8285 | feaProblem->feaAnalysis[i].lanczosType = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
8286 | if(feaProblem->feaAnalysis[i].lanczosType == NULL((void*)0)) { |
8287 | if (tempString != NULL((void*)0)) EG_free(tempString); |
8288 | |
8289 | return EGADS_MALLOC-4; |
8290 | } |
8291 | |
8292 | memcpy(feaProblem->feaAnalysis[i].lanczosType, tempString, strlen(tempString)*sizeof(char)); |
8293 | feaProblem->feaAnalysis[i].lanczosType[strlen(tempString)] = '\0'; |
8294 | |
8295 | if (keyValue != NULL((void*)0)) { |
8296 | EG_free(keyValue); |
8297 | keyValue = NULL((void*)0); |
8298 | } |
8299 | |
8300 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8301 | } |
8302 | |
8303 | /*! \page feaAnalysis |
8304 | * |
8305 | * \if (NASTRAN) |
8306 | * <ul> |
8307 | * <li> <B>machNumber = 0.0 or [0.0, ..., 0.0]</B> </li> <br> |
8308 | * Mach number used in trim analysis OR Mach numbers used in flutter analysis.. |
8309 | * </ul> |
8310 | * \elseif (ASTROS) |
8311 | * <ul> |
8312 | * <li> <B>machNumber = 0.0 or [0.0, ..., 0.0]</B> </li> <br> |
8313 | * Mach number used in trim analysis OR Mach up to 6 values used in flutter analysis.. |
8314 | * </ul> |
8315 | * \endif |
8316 | */ |
8317 | keyWord = "machNumber"; |
8318 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8319 | if (status == CAPS_SUCCESS0) { |
8320 | |
8321 | status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numMachNumber, &feaProblem->feaAnalysis[i].machNumber); |
8322 | if (keyValue != NULL((void*)0)) { |
8323 | EG_free(keyValue); |
8324 | keyValue = NULL((void*)0); |
8325 | } |
8326 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8326 , __func__, 0); goto cleanup; }; |
8327 | } |
8328 | |
8329 | /*! \page feaAnalysis |
8330 | * |
8331 | * \if (NASTRAN || ASTROS) |
8332 | * <ul> |
8333 | * <li> <B>dynamicPressure = 0.0</B> </li> <br> |
8334 | * Dynamic pressure used in trim analysis. |
8335 | * </ul> |
8336 | * \endif |
8337 | */ |
8338 | keyWord = "dynamicPressure"; |
8339 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8340 | if (status == CAPS_SUCCESS0) { |
8341 | |
8342 | status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].dynamicPressure); |
8343 | if (keyValue != NULL((void*)0)) { |
8344 | EG_free(keyValue); |
8345 | keyValue = NULL((void*)0); |
8346 | } |
8347 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8347 , __func__, 0); goto cleanup; }; |
8348 | } |
8349 | |
8350 | /*! \page feaAnalysis |
8351 | * |
8352 | * \if (NASTRAN || ASTROS) |
8353 | * <ul> |
8354 | * <li> <B>density = 0.0</B> </li> <br> |
8355 | * Density used in trim analysis to determine true velocity, or flutter analysis. |
8356 | * </ul> |
8357 | * \endif |
8358 | */ |
8359 | keyWord = "density"; |
8360 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8361 | if (status == CAPS_SUCCESS0) { |
8362 | |
8363 | status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].density); |
8364 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
8365 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8365 , __func__, 0); goto cleanup; }; |
8366 | } |
8367 | |
8368 | /*! \page feaAnalysis |
8369 | * |
8370 | * \if (MYSTRAN || NASTRAN || ASTROS) |
8371 | * <ul> |
8372 | * <li> <B>aeroSymmetryXY = "(no default)"</B> </li> <br> |
8373 | * Aerodynamic symmetry about the XY Plane. Options: SYM, ANTISYM, ASYM. |
8374 | * Aerodynamic symmetry about the XY Plane. Options: SYM, ANTISYM, ASYM. SYMMETRIC Indicates that a half span aerodynamic model |
8375 | * is moving in a symmetric manner with respect to the XY plane. |
8376 | * ANTISYMMETRIC Indicates that a half span aerodynamic model is moving in an antisymmetric manner with respect to the XY plane. |
8377 | * ASYMMETRIC Indicates that a full aerodynamic model is provided. |
8378 | * </ul> |
8379 | * \endif |
8380 | */ |
8381 | keyWord = "aeroSymmetryXY"; |
8382 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8383 | if (status == CAPS_SUCCESS0) { |
8384 | |
8385 | tempString = string_removeQuotation(keyValue); |
8386 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 8386, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
8387 | |
8388 | feaProblem->feaAnalysis[i].aeroSymmetryXY = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
8389 | if(feaProblem->feaAnalysis[i].aeroSymmetryXY == NULL((void*)0)) { |
8390 | if (tempString != NULL((void*)0)) EG_free(tempString); |
8391 | |
8392 | return EGADS_MALLOC-4; |
8393 | } |
8394 | |
8395 | memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXY, tempString, strlen(tempString)*sizeof(char)); |
8396 | feaProblem->feaAnalysis[i].aeroSymmetryXY[strlen(tempString)] = '\0'; |
8397 | |
8398 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
8399 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8400 | } |
8401 | |
8402 | // check for the old option trimSymmetry |
8403 | keyWord = "trimSymmetry"; |
8404 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8405 | if (status == CAPS_SUCCESS0) { |
8406 | |
8407 | tempString = string_removeQuotation(keyValue); |
8408 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 8408, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
8409 | |
8410 | feaProblem->feaAnalysis[i].aeroSymmetryXY = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
8411 | if(feaProblem->feaAnalysis[i].aeroSymmetryXY == NULL((void*)0)) { |
8412 | if (tempString != NULL((void*)0)) EG_free(tempString); |
8413 | |
8414 | return EGADS_MALLOC-4; |
8415 | } |
8416 | |
8417 | memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXY, tempString, strlen(tempString)*sizeof(char)); |
8418 | feaProblem->feaAnalysis[i].aeroSymmetryXY[strlen(tempString)] = '\0'; |
8419 | |
8420 | if (keyValue != NULL((void*)0)) { |
8421 | EG_free(keyValue); |
8422 | keyValue = NULL((void*)0); |
8423 | } |
8424 | |
8425 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8426 | } |
8427 | |
8428 | /*! \page feaAnalysis |
8429 | * |
8430 | * \if (MYSTRAN || NASTRAN || ASTROS) |
8431 | * <ul> |
8432 | * <li> <B>aeroSymmetryXZ = "(no default)"</B> </li> <br> |
8433 | * Aerodynamic symmetry about the XZ Plane. Options: SYM, ANTISYM, ASYM. SYMMETRIC Indicates that a half span aerodynamic model |
8434 | * is moving in a symmetric manner with respect to the XZ plane. |
8435 | * ANTISYMMETRIC Indicates that a half span aerodynamic model is moving in an antisymmetric manner with respect to the XZ plane. |
8436 | * ASYMMETRIC Indicates that a full aerodynamic model is provided. |
8437 | * </ul> |
8438 | * \endif |
8439 | */ |
8440 | keyWord = "aeroSymmetryXZ"; |
8441 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8442 | if (status == CAPS_SUCCESS0) { |
8443 | |
8444 | tempString = string_removeQuotation(keyValue); |
8445 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 8445, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
8446 | |
8447 | feaProblem->feaAnalysis[i].aeroSymmetryXZ = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
8448 | if(feaProblem->feaAnalysis[i].aeroSymmetryXZ == NULL((void*)0)) { |
8449 | if (tempString != NULL((void*)0)) EG_free(tempString); |
8450 | |
8451 | return EGADS_MALLOC-4; |
8452 | } |
8453 | |
8454 | memcpy(feaProblem->feaAnalysis[i].aeroSymmetryXZ, tempString, strlen(tempString)*sizeof(char)); |
8455 | feaProblem->feaAnalysis[i].aeroSymmetryXZ[strlen(tempString)] = '\0'; |
8456 | |
8457 | if (keyValue != NULL((void*)0)) { |
8458 | EG_free(keyValue); |
8459 | keyValue = NULL((void*)0); |
8460 | } |
8461 | |
8462 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8463 | } |
8464 | |
8465 | /*! \page feaAnalysis |
8466 | * |
8467 | * \if (NASTRAN ) |
8468 | * <ul> |
8469 | * <li> <B>rigidVariable = ["no default"]</B> </li> <br> |
8470 | * List of rigid body motions to be used as trim variables during a trim analysis. Nastran |
8471 | * valid labels are: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6 |
8472 | * </ul> |
8473 | * \elseif ASTROS |
8474 | * <ul> |
8475 | * <li> <B>rigidVariable = ["no default"]</B> </li> <br> |
8476 | * List of rigid body motions to be used as trim variables during a trim analysis. Nastran format |
8477 | * labels are used and will be converted by the AIM automatically. |
8478 | * Expected inputs: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6 |
8479 | * </ul> |
8480 | * \endif |
8481 | */ |
8482 | keyWord = "rigidVariable"; |
8483 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8484 | if (status == CAPS_SUCCESS0) { |
8485 | |
8486 | status = string_toStringDynamicArray(keyValue, |
8487 | &feaProblem->feaAnalysis[i].numRigidVariable, |
8488 | &feaProblem->feaAnalysis[i].rigidVariable); |
8489 | if (keyValue != NULL((void*)0)) { |
8490 | EG_free(keyValue); |
8491 | keyValue = NULL((void*)0); |
8492 | } |
8493 | if (status != CAPS_SUCCESS0) return status; |
8494 | } |
8495 | |
8496 | /*! \page feaAnalysis |
8497 | * |
8498 | * \if (NASTRAN) |
8499 | * <ul> |
8500 | * <li> <B>rigidConstraint = ["no default"]</B> </li> <br> |
8501 | * List of rigid body motions to be used as trim constraint variables during a trim analysis. Nastran |
8502 | * valid labels are: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6 |
8503 | * </ul> |
8504 | * \elseif ASTROS |
8505 | * <ul> |
8506 | * <li> <B>rigidConstraint = ["no default"]</B> </li> <br> |
8507 | * List of rigid body motions to be used as trim constraint variables during a trim analysis. Nastran format |
8508 | * labels are used and will be converted by the AIM automatically. |
8509 | * Expected inputs: ANGLEA, SIDES, ROLL, PITCH, YAW, URDD1, URDD2, URDD3, URDD4, URDD5, URDD6 |
8510 | * </ul> |
8511 | * \endif |
8512 | */ |
8513 | keyWord = "rigidConstraint"; |
8514 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8515 | if (status == CAPS_SUCCESS0) { |
8516 | |
8517 | status = string_toStringDynamicArray(keyValue, |
8518 | &feaProblem->feaAnalysis[i].numRigidConstraint, |
8519 | &feaProblem->feaAnalysis[i].rigidConstraint); |
8520 | if (keyValue != NULL((void*)0)) { |
8521 | EG_free(keyValue); |
8522 | keyValue = NULL((void*)0); |
8523 | } |
8524 | if (status != CAPS_SUCCESS0) return status; |
8525 | } |
8526 | |
8527 | if (feaProblem->feaAnalysis[i].numRigidConstraint != 0) { |
8528 | /*! \page feaAnalysis |
8529 | * |
8530 | * \if (NASTRAN || ASTROS) |
8531 | * <ul> |
8532 | * <li> <B>magRigidConstraint = [0.0 , 0.0, ...]</B> </li> <br> |
8533 | * List of magnitudes of trim constraint variables. If none and 'rigidConstraint'(s) are specified |
8534 | * then 0.0 is assumed for each rigid constraint. |
8535 | * </ul> |
8536 | * \endif |
8537 | */ |
8538 | keyWord = "magRigidConstraint"; |
8539 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8540 | if (status == CAPS_SUCCESS0) { |
8541 | |
8542 | status = string_toDoubleDynamicArray(keyValue, |
8543 | &tempInt, |
8544 | &feaProblem->feaAnalysis[i].magRigidConstraint); |
8545 | if (keyValue != NULL((void*)0)) { |
8546 | EG_free(keyValue); |
8547 | keyValue = NULL((void*)0); |
8548 | } |
8549 | if (status != CAPS_SUCCESS0) return status; |
8550 | } else { |
8551 | |
8552 | tempInt = feaProblem->feaAnalysis[i].numRigidConstraint; |
8553 | |
8554 | feaProblem->feaAnalysis[i].magRigidConstraint = (double *) EG_alloc(tempInt*sizeof(double)); |
8555 | if (feaProblem->feaAnalysis[i].magRigidConstraint == NULL((void*)0)) return EGADS_MALLOC-4; |
8556 | |
8557 | for (j = 0; j < feaProblem->feaAnalysis[i].numRigidConstraint; j++) { |
8558 | |
8559 | feaProblem->feaAnalysis[i].magRigidConstraint[j] = 0.0; |
8560 | } |
8561 | } |
8562 | |
8563 | if (tempInt != feaProblem->feaAnalysis[i].numRigidConstraint) { |
8564 | printf("\tDimensional mismatch between 'magRigidConstraint' and 'rigidConstraint'.\n"); |
8565 | printf("\t 'magRigidConstraint' will be resized.\n"); |
8566 | |
8567 | feaProblem->feaAnalysis[i].magRigidConstraint = (double *) EG_reall(feaProblem->feaAnalysis[i].magRigidConstraint, |
8568 | feaProblem->feaAnalysis[i].numRigidConstraint*sizeof(double)); |
8569 | |
8570 | if (feaProblem->feaAnalysis[i].magRigidConstraint == NULL((void*)0)) return EGADS_MALLOC-4; |
8571 | |
8572 | for (j = tempInt; j < feaProblem->feaAnalysis[i].numRigidConstraint; j++) { |
8573 | feaProblem->feaAnalysis[i].magRigidConstraint[j] = 0.0; |
8574 | } |
8575 | } |
8576 | } |
8577 | |
8578 | /*! \page feaAnalysis |
8579 | * |
8580 | * \if (NASTRAN || ASTROS) |
8581 | * <ul> |
8582 | * <li> <B>controlConstraint = ["no default"]</B> </li> <br> |
8583 | * List of controls surfaces to be used as trim constraint variables during a trim analysis. |
8584 | * </ul> |
8585 | * \endif |
8586 | */ |
8587 | keyWord = "controlConstraint"; |
8588 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8589 | if (status == CAPS_SUCCESS0) { |
8590 | |
8591 | status = string_toStringDynamicArray(keyValue, |
8592 | &feaProblem->feaAnalysis[i].numControlConstraint, |
8593 | &feaProblem->feaAnalysis[i].controlConstraint); |
8594 | if (keyValue != NULL((void*)0)) { |
8595 | EG_free(keyValue); |
8596 | keyValue = NULL((void*)0); |
8597 | } |
8598 | if (status != CAPS_SUCCESS0) return status; |
8599 | } |
8600 | |
8601 | if (feaProblem->feaAnalysis[i].numControlConstraint != 0) { |
8602 | /*! \page feaAnalysis |
8603 | * |
8604 | * \if (NASTRAN || ASTROS) |
8605 | * <ul> |
8606 | * <li> <B>magControlConstraint = [0.0 , 0.0, ...]</B> </li> <br> |
8607 | * List of magnitudes of trim control surface constraint variables. If none and 'controlConstraint'(s) are specified |
8608 | * then 0.0 is assumed for each control surface constraint. |
8609 | * </ul> |
8610 | * \endif |
8611 | */ |
8612 | keyWord = "magControlConstraint"; |
8613 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8614 | if (status == CAPS_SUCCESS0) { |
8615 | |
8616 | status = string_toDoubleDynamicArray(keyValue, |
8617 | &tempInt, |
8618 | &feaProblem->feaAnalysis[i].magControlConstraint); |
8619 | if (keyValue != NULL((void*)0)) { |
8620 | EG_free(keyValue); |
8621 | keyValue = NULL((void*)0); |
8622 | } |
8623 | if (status != CAPS_SUCCESS0) return status; |
8624 | } else { |
8625 | |
8626 | tempInt = feaProblem->feaAnalysis[i].numControlConstraint; |
8627 | |
8628 | feaProblem->feaAnalysis[i].magControlConstraint = (double *) EG_alloc(tempInt*sizeof(double)); |
8629 | if (feaProblem->feaAnalysis[i].magControlConstraint == NULL((void*)0)) return EGADS_MALLOC-4; |
8630 | |
8631 | for (j = 0; j < feaProblem->feaAnalysis[i].numControlConstraint; j++) { |
8632 | |
8633 | feaProblem->feaAnalysis[i].magControlConstraint[j] = 0.0; |
8634 | } |
8635 | } |
8636 | |
8637 | if (tempInt != feaProblem->feaAnalysis[i].numControlConstraint) { |
8638 | printf("\tDimensional mismatch between 'magControlConstraint' and 'controlConstraint'.\n"); |
8639 | printf("\t 'magControlConstraint' will be resized.\n"); |
8640 | |
8641 | feaProblem->feaAnalysis[i].magControlConstraint = (double *) EG_reall(feaProblem->feaAnalysis[i].magControlConstraint, |
8642 | feaProblem->feaAnalysis[i].numControlConstraint*sizeof(double)); |
8643 | |
8644 | if (feaProblem->feaAnalysis[i].magControlConstraint == NULL((void*)0)) return EGADS_MALLOC-4; |
8645 | |
8646 | for (j = tempInt; j < feaProblem->feaAnalysis[i].numControlConstraint; j++) { |
8647 | feaProblem->feaAnalysis[i].magControlConstraint[j] = 0.0; |
8648 | } |
8649 | } |
8650 | } |
8651 | |
8652 | /*! \page feaAnalysis |
8653 | * |
8654 | * \if (NASTRAN || ASTROS) |
8655 | * <ul> |
8656 | * <li> <B>reducedFreq = [0.1, ..., 20.0], No Default Values are defined.</B> </li> <br> |
8657 | * Reduced Frequencies to be used in Flutter Analysis. Up to 8 values can be defined. |
8658 | * </ul> |
8659 | * \endif |
8660 | */ |
8661 | keyWord = "reducedFreq"; |
8662 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8663 | if (status == CAPS_SUCCESS0) { |
8664 | |
8665 | status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numReducedFreq, &feaProblem->feaAnalysis[i].reducedFreq); |
8666 | if (keyValue != NULL((void*)0)) { |
8667 | EG_free(keyValue); |
8668 | keyValue = NULL((void*)0); |
8669 | } |
8670 | if (feaProblem->feaAnalysis[i].numReducedFreq > 8) { |
8671 | printf("\tError: The number of reduced frequencies (reducedFreq) entered in an Analysis AIM Input must be eight or less\n"); |
8672 | return CAPS_BADVALUE-311; |
8673 | } |
8674 | if (status != CAPS_SUCCESS0) return status; |
8675 | } |
8676 | |
8677 | /*! \page feaAnalysis |
8678 | * |
8679 | * \if (NASTRAN || ASTROS) |
8680 | * <ul> |
8681 | * <li> <B>flutterVel = [0.1, ..., 20.0]</B> </li> <br> |
8682 | * Velocities to be used in Flutter Analysis. If no values are provided the |
8683 | * following relation is used |
8684 | * |
8685 | * v = sqrt(2*dynamicPressure/density) |
8686 | * dv = (v*2 - v/2) / 20; |
8687 | * |
8688 | * flutterVel[0] = v/10 |
8689 | * flutterVel[i] = v/2 + i*dv; where i = 1....21 |
8690 | * flutterVel[22] = v*10; |
8691 | * </ul> |
8692 | * \endif |
8693 | */ |
8694 | keyWord = "flutterVel"; |
8695 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8696 | if (status == CAPS_SUCCESS0) { |
8697 | |
8698 | status = string_toDoubleDynamicArray(keyValue, &feaProblem->feaAnalysis[i].numFlutterVel, &feaProblem->feaAnalysis[i].flutterVel); |
8699 | if (keyValue != NULL((void*)0)) { |
8700 | EG_free(keyValue); |
8701 | keyValue = NULL((void*)0); |
8702 | } |
8703 | if (status != CAPS_SUCCESS0) return status; |
8704 | } |
8705 | |
8706 | /*! \page feaAnalysis |
8707 | * |
8708 | * \if (ASTROS) |
8709 | * <ul> |
8710 | * <li> <B>flutterConvergenceParam = 1e-5 </B> </li> <br> |
8711 | * Convergence parameter for flutter eigenvalue. |
8712 | * </ul> |
8713 | * \endif |
8714 | */ |
8715 | keyWord = "flutterConvergenceParam"; |
8716 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8717 | if (status == CAPS_SUCCESS0) { |
8718 | |
8719 | status = string_toDouble(keyValue, &feaProblem->feaAnalysis[i].flutterConvergenceParam); |
8720 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
8721 | if (status != CAPS_SUCCESS0) return status; |
8722 | } |
8723 | else { |
8724 | feaProblem->feaAnalysis[i].flutterConvergenceParam = 1.e-5; |
8725 | } |
8726 | |
8727 | /*! \page feaAnalysis |
8728 | * |
8729 | * \if (NASTRAN || ASTROS) |
8730 | * <ul> |
8731 | * <li> <B>visualFlutter = False </B> </li> <br> |
8732 | * Turn on flutter visualization f06 output. |
8733 | * </ul> |
8734 | * \endif |
8735 | */ |
8736 | // keyWord = "visualFlutter"; |
8737 | // status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8738 | // if (status == CAPS_SUCCESS) { |
8739 | // |
8740 | // status = string_toBoolean(keyValue, &feaProblem->feaAnalysis[i].visualFlutter); |
8741 | // if (keyValue != NULL) { |
8742 | // EG_free(keyValue); |
8743 | // keyValue = NULL; |
8744 | // } |
8745 | // if (status != CAPS_SUCCESS) return status; |
8746 | // } |
8747 | |
8748 | /*! \page feaAnalysis |
8749 | * |
8750 | * \if (NASTRAN) |
8751 | * <ul> |
8752 | * <li> <B>analysisResponse = "(no default)"</B> </li> <br> |
8753 | * Single or list of "DesignResponse Name"s defined in \ref feaDesignResponse to use for the analysis response spanning sets (e.g. "Name1" or ["Name1","Name2",...]. |
8754 | * </ul> |
8755 | * \endif |
8756 | */ |
8757 | keyWord = "analysisResponse"; |
8758 | status = search_jsonDictionary( analysisTuple[i].value, keyWord, &keyValue); |
8759 | if (status == CAPS_SUCCESS0) { |
8760 | |
8761 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
8762 | if (keyValue != NULL((void*)0)) { |
8763 | EG_free(keyValue); |
8764 | keyValue = NULL((void*)0); |
8765 | } |
8766 | |
8767 | if (status != CAPS_SUCCESS0) return status; |
8768 | |
8769 | feaProblem->feaAnalysis[i].numDesignResponse = 0; |
8770 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
8771 | |
8772 | for (attrIndex = 0; attrIndex < feaProblem->numDesignResponse; attrIndex++) { |
8773 | |
8774 | if (strcasecmp(feaProblem->feaDesignResponse[attrIndex].name, groupName[groupIndex]) == 0) { |
8775 | |
8776 | feaProblem->feaAnalysis[i].numDesignResponse += 1; |
8777 | |
8778 | if (feaProblem->feaAnalysis[i].numDesignResponse == 1) { |
8779 | |
8780 | feaProblem->feaAnalysis[i].designResponseSetID = (int *) EG_alloc(feaProblem->feaAnalysis[i].numDesignResponse *sizeof(int)); |
8781 | |
8782 | } else { |
8783 | |
8784 | feaProblem->feaAnalysis[i].designResponseSetID = (int *) EG_reall(feaProblem->feaAnalysis[i].designResponseSetID, |
8785 | feaProblem->feaAnalysis[i].numDesignResponse *sizeof(int)); |
8786 | } |
8787 | |
8788 | if (feaProblem->feaAnalysis[i].designResponseSetID == NULL((void*)0)) { |
8789 | status = string_freeArray(numGroupName, &groupName); |
8790 | if (status != CAPS_SUCCESS0) return status; |
8791 | groupName = NULL((void*)0); |
8792 | return EGADS_MALLOC-4; |
8793 | } |
8794 | |
8795 | feaProblem->feaAnalysis[i].designResponseSetID[feaProblem->feaAnalysis[i].numDesignResponse-1] = feaProblem->feaDesignResponse[attrIndex].responseID; |
8796 | break; |
8797 | } |
8798 | } |
8799 | |
8800 | if (feaProblem->feaAnalysis[i].numDesignResponse != groupIndex+1) { |
8801 | |
8802 | printf("\tWarning: Analysis design response name, %s, not found in feaDesignResponse structure\n", groupName[groupIndex]); |
8803 | |
8804 | } |
8805 | } |
8806 | |
8807 | status = string_freeArray(numGroupName, &groupName); |
8808 | if (status != CAPS_SUCCESS0) { |
8809 | if (tempString != NULL((void*)0)) EG_free(tempString); |
8810 | |
8811 | return status; |
8812 | } |
8813 | groupName = NULL((void*)0); |
8814 | } |
8815 | |
8816 | if (feaProblem->feaAnalysis[i].analysisType == AeroelasticFlutter) { |
8817 | // Setup the default flutter velocities if not specified |
8818 | status = fea_defaultFlutterVelocity(&feaProblem->feaAnalysis[i]); |
8819 | if (status != CAPS_SUCCESS0) return status; |
8820 | } |
8821 | |
8822 | } else { // Not JSONstring |
8823 | |
8824 | /*! \page feaAnalysis |
8825 | * \section keyStringAnalysis Single Value String |
8826 | * |
8827 | * If "Value" is a string, the string value may correspond to an entry in a predefined analysis lookup |
8828 | * table. NOT YET IMPLEMENTED!!!! |
8829 | * |
8830 | * |
8831 | */ |
8832 | |
8833 | // CALL analysis look up |
8834 | printf("\tError: Analysis tuple value is expected to be a JSON string\n"); |
8835 | //printf("\t%s", analysisTuple[i].value); |
8836 | return CAPS_BADVALUE-311; |
8837 | } |
8838 | } |
8839 | |
8840 | |
8841 | printf("\tDone getting FEA analyses\n"); |
8842 | status = CAPS_SUCCESS0; |
8843 | cleanup: |
8844 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
8845 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
8846 | return status; |
8847 | } |
8848 | |
8849 | // Get the design variables from a capsTuple |
8850 | int fea_getDesignVariable(void *aimInfo, |
8851 | /*@unused@*/ int requireGroup, |
8852 | int numDesignVariableTuple, |
8853 | capsTuple designVariableTuple[], |
8854 | int numDesignVariableRelationTuple, |
8855 | capsTuple designVariableRelationTuple[], |
8856 | mapAttrToIndexStruct *attrMap, |
8857 | feaProblemStruct *feaProblem) { |
8858 | |
8859 | /*! \page feaDesignVariable FEA Design Variables |
8860 | * Structure for the design variable tuple = ("DesignVariable Name", "Value"). |
8861 | * "DesignVariable Name" defines the reference name for the design variable being specified. |
8862 | * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary |
8863 | * (see Section \ref jsonStringDesignVariable). |
8864 | * \if NASTRAN |
8865 | * In Nastran the DesignVariable Name will be the LABEL used in the DESVAR input. |
8866 | * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less. |
8867 | * |
8868 | * - <c>DESVAR ID LABEL XINIT XLB XUB DELXV DDVAL</c> |
8869 | * \endif |
8870 | * |
8871 | */ |
8872 | int status; //Function return |
8873 | |
8874 | int i, j, k; // Indexing |
8875 | int found; |
8876 | |
8877 | char *keyValue = NULL((void*)0); |
8878 | char *keyWord = NULL((void*)0); |
8879 | |
8880 | int tempInteger = 0; |
8881 | int designVariableID = 0; |
8882 | |
8883 | char **groupName = NULL((void*)0); |
8884 | int numGroupName = 0; |
8885 | |
8886 | feaDesignVariableStruct *designVariable; |
8887 | feaDesignVariableRelationStruct *designVariableRelation; |
8888 | |
8889 | // Destroy our design variable structures coming in if aren't 0 and NULL already |
8890 | if (feaProblem->feaDesignVariable != NULL((void*)0)) { |
8891 | for (i = 0; i < feaProblem->numDesignVariable; i++) { |
8892 | status = destroy_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]); |
8893 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8893 , __func__, 0); goto cleanup; }; |
8894 | } |
8895 | } |
8896 | AIM_FREE(feaProblem->feaDesignVariable){ EG_free(feaProblem->feaDesignVariable); feaProblem->feaDesignVariable = ((void*)0); }; |
8897 | feaProblem->feaDesignVariable = NULL((void*)0); |
8898 | feaProblem->numDesignVariable = 0; |
8899 | |
8900 | // Destroy our design variable relation structures coming in if aren't 0 and NULL already |
8901 | if (feaProblem->feaDesignVariableRelation != NULL((void*)0)) { |
8902 | for (i = 0; i < feaProblem->numDesignVariableRelation; i++) { |
8903 | status = destroy_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]); |
8904 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8904 , __func__, 0); goto cleanup; }; |
8905 | } |
8906 | } |
8907 | AIM_FREE(feaProblem->feaDesignVariableRelation){ EG_free(feaProblem->feaDesignVariableRelation); feaProblem ->feaDesignVariableRelation = ((void*)0); }; |
8908 | feaProblem->feaDesignVariableRelation = NULL((void*)0); |
8909 | feaProblem->numDesignVariableRelation = 0; |
8910 | |
8911 | |
8912 | printf("\nGetting FEA design variables.......\n"); |
8913 | |
8914 | feaProblem->numDesignVariable = numDesignVariableTuple; |
8915 | |
8916 | printf("\tNumber of design variables - %d\n", feaProblem->numDesignVariable); |
8917 | |
8918 | if (feaProblem->numDesignVariable > 0) { |
8919 | AIM_ALLOC(feaProblem->feaDesignVariable,{ if (feaProblem->feaDesignVariable != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__ , 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaDesignVariable" ); goto cleanup; } size_t memorysize = feaProblem->numDesignVariable ; feaProblem->feaDesignVariable = (feaDesignVariableStruct *) EG_alloc(memorysize*sizeof(feaDesignVariableStruct)); if ( feaProblem->feaDesignVariable == ((void*)0)) { status = -4 ; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__, 3 , "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariable" , memorysize, "feaDesignVariableStruct"); goto cleanup; } } |
8920 | feaProblem->numDesignVariable, feaDesignVariableStruct, aimInfo, status){ if (feaProblem->feaDesignVariable != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__ , 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaDesignVariable" ); goto cleanup; } size_t memorysize = feaProblem->numDesignVariable ; feaProblem->feaDesignVariable = (feaDesignVariableStruct *) EG_alloc(memorysize*sizeof(feaDesignVariableStruct)); if ( feaProblem->feaDesignVariable == ((void*)0)) { status = -4 ; aim_status(aimInfo, status, "feaUtils.c", 8920, __func__, 3 , "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariable" , memorysize, "feaDesignVariableStruct"); goto cleanup; } }; |
8921 | |
8922 | } else { |
8923 | AIM_ERROR(aimInfo, "Number of design variable values in input tuple is 0\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 8923, __func__ , "Number of design variable values in input tuple is 0\n"); }; |
8924 | return CAPS_NOTFOUND-303; |
8925 | } |
8926 | |
8927 | for (i = 0; i < feaProblem->numDesignVariable; i++) { |
8928 | status = initiate_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]); |
8929 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 8929 , __func__, 0); goto cleanup; }; |
8930 | } |
8931 | |
8932 | for (i = 0; i < feaProblem->numDesignVariable; i++) { |
8933 | |
8934 | designVariable = &feaProblem->feaDesignVariable[i]; |
8935 | |
8936 | printf("\tDesign_Variable name - %s\n", designVariableTuple[i].name); |
8937 | |
8938 | AIM_STRDUP(designVariable->name, designVariableTuple[i].name, aimInfo, status){ if (designVariable->name != ((void*)0)) { status = -4; aim_status (aimInfo, status, "feaUtils.c", 8938, __func__, 1, "AIM_STRDUP: %s != NULL!" , "designVariable->name"); goto cleanup; } designVariable-> name = EG_strdup(designVariableTuple[i].name); if (designVariable ->name == ((void*)0)) { status = -4; aim_status(aimInfo, status , "feaUtils.c", 8938, __func__, 2, "AIM_STRDUP: %s %s", "designVariable->name" , designVariableTuple[i].name); goto cleanup; } }; |
8939 | |
8940 | // Do we have a json string? |
8941 | if (json_isDict(designVariableTuple[i].value)) { |
8942 | |
8943 | /*! \page feaDesignVariable |
8944 | * \section jsonStringDesignVariable JSON String Dictionary |
8945 | * |
8946 | * If "Value" is JSON string dictionary |
8947 | * \if (NASTRAN || ASTROS || MASSTRAN) |
8948 | * (eg. "Value" = {"initialValue": 5.0, "upperBound": 10.0}) |
8949 | * \endif |
8950 | * the following keywords ( = default values) may be used: |
8951 | * |
8952 | */ |
8953 | |
8954 | /*! \page feaDesignVariable |
8955 | * |
8956 | * \if (NASTRAN || ASTROS || MASSTRAN) |
8957 | * <ul> |
8958 | * <li> <B>initialValue = 0.0</B> </li> <br> |
8959 | * Initial value for the design variable. |
8960 | * </ul> |
8961 | * \endif |
8962 | * |
8963 | */ |
8964 | keyWord = "initialValue"; |
8965 | status = json_getDouble( |
8966 | designVariableTuple[i].value, keyWord, |
8967 | &designVariable->initialValue); |
8968 | |
8969 | if (status != CAPS_SUCCESS0) { |
8970 | designVariable->initialValue = 0.0; |
8971 | } |
8972 | |
8973 | /*! \page feaDesignVariable |
8974 | * |
8975 | * \if (NASTRAN || ASTROS) |
8976 | * <ul> |
8977 | * <li> <B>lowerBound = 0.0</B> </li> <br> |
8978 | * Lower bound for the design variable. |
8979 | * </ul> |
8980 | * \endif |
8981 | */ |
8982 | keyWord = "lowerBound"; |
8983 | status = json_getDouble( |
8984 | designVariableTuple[i].value, keyWord, |
8985 | &designVariable->lowerBound); |
8986 | |
8987 | if (status != CAPS_SUCCESS0) { |
8988 | designVariable->lowerBound = 0.0; |
8989 | } |
8990 | |
8991 | /*! \page feaDesignVariable |
8992 | * |
8993 | * \if (NASTRAN || ASTROS) |
8994 | * <ul> |
8995 | * <li> <B>upperBound = 0.0</B> </li> <br> |
8996 | * Upper bound for the design variable. |
8997 | * </ul> |
8998 | * \endif |
8999 | */ |
9000 | keyWord = "upperBound"; |
9001 | status = json_getDouble( |
9002 | designVariableTuple[i].value, keyWord, |
9003 | &designVariable->upperBound); |
9004 | |
9005 | if (status != CAPS_SUCCESS0) { |
9006 | designVariable->upperBound = 0.0; |
9007 | } |
9008 | |
9009 | /*! \page feaDesignVariable |
9010 | * |
9011 | * \if (NASTRAN || ASTROS) |
9012 | * <ul> |
9013 | * <li> <B>maxDelta = 0.0</B> </li> <br> |
9014 | * Move limit for the design variable. |
9015 | * </ul> |
9016 | * \endif |
9017 | */ |
9018 | keyWord = "maxDelta"; |
9019 | status = json_getDouble( |
9020 | designVariableTuple[i].value, keyWord, |
9021 | &designVariable->maxDelta); |
9022 | |
9023 | if (status != CAPS_SUCCESS0) { |
9024 | designVariable->maxDelta = 0.0; |
9025 | } |
9026 | |
9027 | /*! \page feaDesignVariable |
9028 | * |
9029 | * \if (NASTRAN || ASTROS) |
9030 | * <ul> |
9031 | * <li> <B>discreteValue = 0.0</B> </li> <br> |
9032 | * List of discrete values to use for the design variable (e.g. [0.0,1.0,1.5,3.0]. |
9033 | * </ul> |
9034 | * \endif |
9035 | */ |
9036 | keyWord = "discreteValue"; |
9037 | status = json_getDoubleDynamicArray( |
9038 | designVariableTuple[i].value, keyWord, |
9039 | &designVariable->numDiscreteValue, &designVariable->discreteValue); |
9040 | |
9041 | if (status != CAPS_SUCCESS0) { |
9042 | designVariable->numDiscreteValue = 0; |
9043 | designVariable->discreteValue = NULL((void*)0); |
9044 | } |
9045 | |
9046 | /*! \page feaDesignVariable |
9047 | * |
9048 | * \if NASTRAN |
9049 | * <ul> |
9050 | * <li> <B>independentVariable = "(no default)"</B> </li> <br> |
9051 | * Single or list of "DesignVariable Name"s (that is the Tuple name) used to create/designate a |
9052 | * dependent design variable. |
9053 | * - independentValue = variableWeight[1] + variableWeight[2] * SUM{independentVariableWeight[i] * independentVariable[i]} |
9054 | * </ul> |
9055 | * \endif |
9056 | */ |
9057 | |
9058 | keyWord = "independentVariable"; |
9059 | status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue); |
9060 | if (status == CAPS_SUCCESS0) { |
9061 | |
9062 | status = string_toStringDynamicArray(keyValue, |
9063 | &designVariable->numIndependVariable, |
9064 | &designVariable->independVariable); |
9065 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9066 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9066 , __func__, 0); goto cleanup; }; |
9067 | |
9068 | } |
9069 | |
9070 | /*! \page feaDesignVariable |
9071 | * |
9072 | * \if NASTRAN |
9073 | * <ul> |
9074 | * <li> <B>independentVariableWeight = 1.0 or [1.0, 1.0, ...]</B> </li> <br> |
9075 | * Single or list of weighting constants with respect to the variables set for "independentVariable". |
9076 | * If the length of this list doesn't match the length |
9077 | * of the "independentVariable" list, the list is either truncated [ >length("independentVariable")] or expanded [ <length("independentVariable")] |
9078 | * in which case the <b>last weight is repeated</b>. |
9079 | * </ul> |
9080 | * \endif |
9081 | */ |
9082 | |
9083 | keyWord = "independentVariableWeight"; |
9084 | status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue); |
9085 | if (status == CAPS_SUCCESS0) { |
9086 | |
9087 | status = string_toDoubleDynamicArray(keyValue, |
9088 | &tempInteger, |
9089 | &designVariable->independVariableWeight); |
9090 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9091 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9091 , __func__, 0); goto cleanup; }; |
9092 | |
9093 | // We have weights, but no variables |
9094 | if (designVariable->numIndependVariable == 0) { |
9095 | |
9096 | printf("\tWeighting constants have been provided, but no independent design variables were set!\n"); |
9097 | |
9098 | // Less weights than variables |
9099 | } else if( tempInteger < designVariable->numIndependVariable) { |
9100 | |
9101 | printf("\tThe number of weighting constants provided does not match the number of independent design variables. " |
9102 | "The last weight will be repeated %d times\n", designVariable->numIndependVariable - tempInteger); |
9103 | |
9104 | AIM_REALL(designVariable->independVariableWeight,{ size_t memorysize = designVariable->numIndependVariable; designVariable->independVariableWeight = (double *) EG_reall (designVariable->independVariableWeight, memorysize*sizeof (double)); if (designVariable->independVariableWeight == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 9105, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight" , memorysize, "double"); goto cleanup; } } |
9105 | designVariable->numIndependVariable, double, aimInfo, status){ size_t memorysize = designVariable->numIndependVariable; designVariable->independVariableWeight = (double *) EG_reall (designVariable->independVariableWeight, memorysize*sizeof (double)); if (designVariable->independVariableWeight == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 9105, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight" , memorysize, "double"); goto cleanup; } }; |
9106 | |
9107 | for (j = 0; j < designVariable->numIndependVariable - tempInteger; j++) { |
9108 | |
9109 | designVariable->independVariableWeight[j+tempInteger] = designVariable->independVariableWeight[tempInteger-1]; |
9110 | } |
9111 | |
9112 | // More weights than variables |
9113 | } else if (tempInteger > designVariable->numIndependVariable) { |
9114 | |
9115 | printf("\tThe number of weighting constants provided does not match the number of independent design variables. " |
9116 | "The last %d weights will be not be used\n", tempInteger -designVariable->numIndependVariable); |
9117 | |
9118 | AIM_REALL(designVariable->independVariableWeight,{ size_t memorysize = designVariable->numIndependVariable; designVariable->independVariableWeight = (double *) EG_reall (designVariable->independVariableWeight, memorysize*sizeof (double)); if (designVariable->independVariableWeight == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 9119, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight" , memorysize, "double"); goto cleanup; } } |
9119 | designVariable->numIndependVariable, double, aimInfo, status){ size_t memorysize = designVariable->numIndependVariable; designVariable->independVariableWeight = (double *) EG_reall (designVariable->independVariableWeight, memorysize*sizeof (double)); if (designVariable->independVariableWeight == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 9119, __func__, 3, "AIM_REALL: %s size %zu type %s", "designVariable->independVariableWeight" , memorysize, "double"); goto cleanup; } }; |
9120 | } |
9121 | |
9122 | } else { // No weights provided - set default value of 1.0 |
9123 | |
9124 | if (designVariable->numIndependVariable != 0) { |
9125 | AIM_ALLOC(designVariable->independVariableWeight, designVariable->numIndependVariable, double, aimInfo, status){ if (designVariable->independVariableWeight != ((void*)0) ) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9125 , __func__, 1, "AIM_ALLOC: %s != NULL", "designVariable->independVariableWeight" ); goto cleanup; } size_t memorysize = designVariable->numIndependVariable ; designVariable->independVariableWeight = (double *) EG_alloc (memorysize*sizeof(double)); if (designVariable->independVariableWeight == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 9125, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariable->independVariableWeight" , memorysize, "double"); goto cleanup; } }; |
9126 | |
9127 | for (j = 0; j < designVariable->numIndependVariable; j++) { |
9128 | designVariable->independVariableWeight[j] = 1.0; |
9129 | } |
9130 | } |
9131 | } |
9132 | |
9133 | /*! \page feaDesignVariable |
9134 | * |
9135 | * \if NASTRAN |
9136 | * <ul> |
9137 | * <li> <B>variableWeight = [1.0, 1.0]</B> </li> <br> |
9138 | * Weighting constants for a dependent variable - used if "independentVariable"(s) have been provided. |
9139 | * </ul> |
9140 | * \endif |
9141 | */ |
9142 | keyWord = "variableWeight"; |
9143 | status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue); |
9144 | if (status == CAPS_SUCCESS0) { |
9145 | |
9146 | status = string_toDoubleArray(keyValue, |
9147 | 2, |
9148 | designVariable->variableWeight); |
9149 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9150 | |
9151 | if (status != CAPS_SUCCESS0) { |
9152 | AIM_ERROR(aimInfo, "Retrieving variableWeight - status %d\n", status){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9152, __func__ , "Retrieving variableWeight - status %d\n", status); }; |
9153 | goto cleanup; |
9154 | } |
9155 | } else { |
9156 | designVariable->variableWeight[0] = 1.0; |
9157 | designVariable->variableWeight[1] = 1.0; |
9158 | } |
9159 | |
9160 | // check if design variable relation info also included in input |
9161 | keyWord = "fieldName"; |
9162 | status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue); |
9163 | |
9164 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9165 | |
9166 | if (status != CAPS_SUCCESS0) { |
9167 | keyWord = "fieldPosition"; |
9168 | status = search_jsonDictionary( designVariableTuple[i].value, keyWord, &keyValue); |
9169 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9170 | } |
9171 | |
9172 | if (status == CAPS_SUCCESS0) { |
9173 | |
9174 | // // The main relation associated with this design variable, if defined in input |
9175 | // AIM_REALL(feaProblem->feaDesignVariableRelation, relationIndex+1, feaDesignVariableRelationStruct, aimInfo, status); |
9176 | // |
9177 | // designVariableRelation = &feaProblem->feaDesignVariableRelation[relationIndex++]; |
9178 | // |
9179 | // feaProblem->numDesignVariableRelation = relationIndex; |
9180 | // |
9181 | // status = initiate_feaDesignVariableRelationStruct(designVariableRelation); |
9182 | // AIM_STATUS(aimInfo, status); |
9183 | // |
9184 | // printf("\tWarning: the ability to provide design variable relation data " |
9185 | // "within Design_Variable input is deprecated and " |
9186 | // "will be removed in the future. Please use provide relation data " |
9187 | // "via \"Design_Variable_Relation\" instead.\n"); |
9188 | // |
9189 | // status = fea_getDesignVariableRelationEntry( &designVariableTuple[i], designVariableRelation, |
9190 | // attrMap, feaProblem, designVariable->name); |
9191 | // AIM_STATUS(aimInfo, status); |
9192 | // |
9193 | // designVariableRelation->relationID = relationIndex; |
9194 | |
9195 | AIM_ERROR(aimInfo, "The ability to provide design variable relation data "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9197, __func__ , "The ability to provide design variable relation data " "within Design_Variable input is deprecated. Please provide relation data " "via \"Design_Variable_Relation\" instead.\n"); } |
9196 | "within Design_Variable input is deprecated. Please provide relation data "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9197, __func__ , "The ability to provide design variable relation data " "within Design_Variable input is deprecated. Please provide relation data " "via \"Design_Variable_Relation\" instead.\n"); } |
9197 | "via \"Design_Variable_Relation\" instead.\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9197, __func__ , "The ability to provide design variable relation data " "within Design_Variable input is deprecated. Please provide relation data " "via \"Design_Variable_Relation\" instead.\n"); }; |
9198 | status = CAPS_BADVALUE-311; |
9199 | goto cleanup; |
9200 | } |
9201 | |
9202 | |
9203 | } else { |
9204 | |
9205 | AIM_ERROR(aimInfo, "Design_Variable tuple value is expected to be a JSON string\n"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9205, __func__ , "Design_Variable tuple value is expected to be a JSON string\n" ); }; |
9206 | status = CAPS_BADVALUE-311; |
9207 | goto cleanup; |
9208 | |
9209 | } |
9210 | } |
9211 | |
9212 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9213 | |
9214 | // Order the design variable ID's such that Analysis and Geometry ID's are continuous. |
9215 | // This is required by the TACS AIM |
9216 | |
9217 | designVariableID = 1; |
9218 | for( i = 0; i < feaProblem->numDesignVariable; i++) { |
9219 | |
9220 | // only analysis design variables |
9221 | if (aim_getIndex(aimInfo, feaProblem->feaDesignVariable[i].name, GEOMETRYIN) <= 0) |
9222 | feaProblem->feaDesignVariable[i].designVariableID = designVariableID++; |
9223 | } |
9224 | for( i = 0; i < feaProblem->numDesignVariable; i++) { |
9225 | |
9226 | // only geometry design variables |
9227 | if (aim_getIndex(aimInfo, feaProblem->feaDesignVariable[i].name, GEOMETRYIN) > 0) |
9228 | feaProblem->feaDesignVariable[i].designVariableID = designVariableID++; |
9229 | } |
9230 | |
9231 | // Now that we are done going through all the tuples we need to populate/create the independVaraiableID array |
9232 | // if independentVariable was set for any of them. |
9233 | for (i = 0; i < feaProblem->numDesignVariable; i++) { |
9234 | |
9235 | designVariable = &feaProblem->feaDesignVariable[i]; |
9236 | |
9237 | if (designVariable->numIndependVariable != 0) { |
9238 | |
9239 | AIM_ALLOC(designVariable->independVariableID, designVariable->numIndependVariable, int, aimInfo, status){ if (designVariable->independVariableID != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9239, __func__ , 1, "AIM_ALLOC: %s != NULL", "designVariable->independVariableID" ); goto cleanup; } size_t memorysize = designVariable->numIndependVariable ; designVariable->independVariableID = (int *) EG_alloc(memorysize *sizeof(int)); if (designVariable->independVariableID == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 9239, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariable->independVariableID" , memorysize, "int"); goto cleanup; } }; |
9240 | |
9241 | // Loop through the independent variable names |
9242 | for (j = 0; j < designVariable->numIndependVariable; j++) { |
9243 | |
9244 | // Compare the independent variable names with design variable name |
9245 | found = (int) false0; |
9246 | for (k = 0; k < feaProblem->numDesignVariable; k++) { |
9247 | if (strcasecmp(designVariable->independVariable[j], feaProblem->feaDesignVariable[k].name) == 0) { |
9248 | found = (int) true1; |
9249 | break; |
9250 | } |
9251 | } |
9252 | |
9253 | // If NOT found |
9254 | if (found != (int) true1) { |
9255 | AIM_ERROR(aimInfo, "\tDesign variable name, \"%s\", not found when searching for independent design variables for "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9257, __func__ , "\tDesign variable name, \"%s\", not found when searching for independent design variables for " "variable %s!!!\n", designVariable->independVariable[j], designVariable ->name); } |
9256 | "variable %s!!!\n", designVariable->independVariable[j],{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9257, __func__ , "\tDesign variable name, \"%s\", not found when searching for independent design variables for " "variable %s!!!\n", designVariable->independVariable[j], designVariable ->name); } |
9257 | designVariable->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9257, __func__ , "\tDesign variable name, \"%s\", not found when searching for independent design variables for " "variable %s!!!\n", designVariable->independVariable[j], designVariable ->name); }; |
9258 | status = CAPS_NOTFOUND-303; |
9259 | goto cleanup; |
9260 | } |
9261 | |
9262 | designVariable->independVariableID[j] = feaProblem->feaDesignVariable[k].designVariableID; |
9263 | } |
9264 | } |
9265 | } |
9266 | |
9267 | if (designVariableRelationTuple != NULL((void*)0)) { |
9268 | |
9269 | AIM_ALLOC(feaProblem->feaDesignVariableRelation, numDesignVariableRelationTuple, feaDesignVariableRelationStruct, aimInfo, status){ if (feaProblem->feaDesignVariableRelation != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9269 , __func__, 1, "AIM_ALLOC: %s != NULL", "feaProblem->feaDesignVariableRelation" ); goto cleanup; } size_t memorysize = numDesignVariableRelationTuple ; feaProblem->feaDesignVariableRelation = (feaDesignVariableRelationStruct *) EG_alloc(memorysize*sizeof(feaDesignVariableRelationStruct )); if (feaProblem->feaDesignVariableRelation == ((void*)0 )) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9269 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "feaProblem->feaDesignVariableRelation" , memorysize, "feaDesignVariableRelationStruct"); goto cleanup ; } }; |
9270 | feaProblem->numDesignVariableRelation = numDesignVariableRelationTuple; |
9271 | |
9272 | for (i = 0; i < numDesignVariableRelationTuple; i++) { |
9273 | status = initiate_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]); |
9274 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9274 , __func__, 0); goto cleanup; }; |
9275 | } |
9276 | |
9277 | // Go through design variable relations defined via 'Design_Variable_Relation' |
9278 | for (i = 0; i < numDesignVariableRelationTuple; i++) { |
9279 | |
9280 | /*! \page feaDesignVariableRelation FEA DesignVariableRelation |
9281 | * Structure for the design variable tuple = ("DesignVariableRelation Name", "Value"). |
9282 | * "DesignVariableRelation Name" defines the reference name for the design variable being specified. |
9283 | * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary |
9284 | * (see Section \ref jsonStringDesignVariableRelation). |
9285 | * |
9286 | */ |
9287 | |
9288 | designVariableRelation = &feaProblem->feaDesignVariableRelation[i]; |
9289 | |
9290 | designVariableRelation->relationID = i+1; |
9291 | |
9292 | status = fea_getDesignVariableRelationEntry( |
9293 | aimInfo, &designVariableRelationTuple[i], designVariableRelation, |
9294 | attrMap, feaProblem, NULL((void*)0) |
9295 | ); |
9296 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9296 , __func__, 0); goto cleanup; }; |
9297 | } |
9298 | |
9299 | } |
9300 | status = fea_linkDesignVariablesAndRelations(feaProblem); |
9301 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 9301 , __func__, 0); goto cleanup; }; |
9302 | |
9303 | printf("\tNumber of design variable relations - %d\n", feaProblem->numDesignVariableRelation); |
9304 | printf("\tDone getting FEA design variables\n"); |
9305 | status = CAPS_SUCCESS0; |
9306 | |
9307 | cleanup: |
9308 | |
9309 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9310 | |
9311 | if (groupName != NULL((void*)0)) |
9312 | string_freeArray(numGroupName, &groupName); |
9313 | |
9314 | return status; |
9315 | } |
9316 | |
9317 | int fea_getDesignVariableRelationEntry(void *aimInfo, |
9318 | capsTuple *designVariableInput, |
9319 | /*@unused@*/ feaDesignVariableRelationStruct *designVariableRelation, |
9320 | /*@unused@*/ mapAttrToIndexStruct *attrMap, |
9321 | /*@unused@*/ feaProblemStruct *feaProblem, |
9322 | /*@unused@*/ char *forceGroupName) { |
9323 | |
9324 | |
9325 | int status; //Function return |
9326 | |
9327 | int i, j; // Indexing |
9328 | |
9329 | int numLinearCoeff; |
9330 | |
9331 | char *keyValue = NULL((void*)0); |
9332 | char *keyWord = NULL((void*)0); |
9333 | |
9334 | char **groupName = NULL((void*)0); |
9335 | int numGroupName = 0; |
9336 | |
9337 | feaMeshDataStruct *feaData = NULL((void*)0); |
9338 | |
9339 | int numMaterial; |
9340 | feaMaterialStruct **materialSet = NULL((void*)0), *material; |
9341 | |
9342 | int numProperty; |
9343 | feaPropertyStruct **propertySet = NULL((void*)0), *property; |
9344 | |
9345 | int numElement; |
9346 | meshElementStruct **elementSet = NULL((void*)0), *element; |
9347 | |
9348 | printf("\tDesign_Variable_Relation name - %s\n", designVariableInput->name); |
9349 | |
9350 | designVariableRelation->name = EG_strdup(designVariableInput->name); |
9351 | |
9352 | /*! \page feaDesignVariableRelation FEA Design Variable Relations |
9353 | * \section jsonStringDesignVariableRelation JSON String Dictionary |
9354 | * |
9355 | * If "Value" is JSON string dictionary |
9356 | * \if (NASTRAN || TACS || MASSTRAN) |
9357 | * (eg. "Value" = {"componentType": "Property", "componentName": "plate", "fieldName": "TM", "variableName": "MyDesVar"}) |
9358 | * \endif |
9359 | * \if (ASTROS) |
9360 | * (eg. "Value" = {"componentType": "Property", "componentName": "plate", "variableName": "MyDesVar"}) |
9361 | * \endif |
9362 | * the following keywords ( = default values) may be used: |
9363 | * |
9364 | */ |
9365 | if (!json_isDict(designVariableInput->value)) { |
9366 | AIM_ERROR(aimInfo,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9367, __func__ , "'Design_Variable_Relation' tuple value must be a JSON dictionary" ); } |
9367 | "'Design_Variable_Relation' tuple value must be a JSON dictionary"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9367, __func__ , "'Design_Variable_Relation' tuple value must be a JSON dictionary" ); }; |
9368 | return CAPS_BADVALUE-311; |
9369 | } |
9370 | |
9371 | /*! \page feaDesignVariableRelation |
9372 | * \if (NASTRAN || TACS || MASSTRAN) |
9373 | * <ul> |
9374 | * <li> <B>componentType = "Property"</B> </li> <br> |
9375 | * The type of component for this design variable relation. Options: "Material", "Property", "Element". |
9376 | * </ul> |
9377 | * \endif |
9378 | * \if (ASTROS) |
9379 | * <ul> |
9380 | * <li> <B>componentType = "Property"</B> </li> <br> |
9381 | * The type of component for this design variable relation. Options: "Property". |
9382 | * </ul> |
9383 | * \endif |
9384 | * |
9385 | */ |
9386 | // Get component type for design variable relation |
9387 | keyWord = "componentType"; |
9388 | status = json_getString( |
9389 | designVariableInput->value, keyWord, &keyValue); |
9390 | |
9391 | // If "componentType" not found, check "variableType" for legacy purposes |
9392 | // Warn that "variableType" is deprecated and will be removed in the future! |
9393 | if (status != CAPS_SUCCESS0) { |
9394 | |
9395 | status = json_getString( |
9396 | designVariableInput->value, "variableType", &keyValue); |
9397 | |
9398 | if (status == CAPS_SUCCESS0) { |
9399 | printf("\tWarning: \"variableType\" is deprecated and " |
9400 | "will be removed in the future. Please use \"componentType\" " |
9401 | "instead.\n"); |
9402 | } |
9403 | } |
9404 | |
9405 | if (status == CAPS_SUCCESS0) { |
9406 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 9406, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
9407 | |
9408 | if (strcasecmp(keyValue, "Material") == 0) designVariableRelation->componentType = MaterialDesignVar; |
9409 | else if (strcasecmp(keyValue, "Property") == 0) designVariableRelation->componentType = PropertyDesignVar; |
9410 | else if (strcasecmp(keyValue, "Element") == 0) designVariableRelation->componentType = ElementDesignVar; |
9411 | else { |
9412 | |
9413 | printf("\tUnrecognized \"%s\" specified (%s) for Design_Variable_Relation tuple %s, defaulting to \"Property\"\n", keyWord, |
9414 | keyValue, |
9415 | designVariableInput->name); |
9416 | designVariableRelation->componentType = PropertyDesignVar; |
9417 | } |
9418 | |
9419 | } |
9420 | else { |
9421 | printf("\tNo \"%s\" specified for Design_Variable_Relation tuple %s, defaulting to \"Property\"\n", keyWord, |
9422 | designVariableInput->name); |
9423 | |
9424 | designVariableRelation->componentType = PropertyDesignVar; |
9425 | } |
9426 | |
9427 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9428 | |
9429 | /*! \page feaDesignVariableRelation |
9430 | * |
9431 | * \if (NASTRAN || TACS || MASSTRAN) |
9432 | * <ul> |
9433 | * <li> <B>componentName = "(no default)"</B> </li> <br> |
9434 | * Single or list of FEA Property(ies), or FEA Material name(s) linked |
9435 | * to the design variable relation (e.g. "Name1" or ["Name1","Name2",...]. |
9436 | * - For <c>componentType</c> Property a \ref feaProperty name (or names) is given. |
9437 | * - For <c>componentType</c> Material a \ref feaMaterial name (or names) is given. |
9438 | * \if (NASTRAN || TACS) |
9439 | * - For <c>componentType</c> Element a <c>capsGroup</c> Name (or names) is given. |
9440 | * \endif |
9441 | * </ul> |
9442 | * \endif |
9443 | * \if (ASTROS) |
9444 | * <ul> |
9445 | * <li> <B>componentName = "(no default)"</B> </li> <br> |
9446 | * Single FEA Property linked to the design variable (e.g. "Name1"). |
9447 | * - For <c>componentType</c> Property a \ref feaProperty name (or names) is given. |
9448 | * </ul> |
9449 | * \endif |
9450 | * |
9451 | */ |
9452 | keyWord = "componentName"; |
9453 | status = json_getStringDynamicArray( |
9454 | designVariableInput->value, keyWord, |
9455 | &numGroupName, &groupName); |
9456 | |
9457 | if (status != CAPS_SUCCESS0) { |
9458 | // required |
9459 | AIM_ERROR(aimInfo, "No \"%s\" specified for Design_Variable tuple %s",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9460, __func__ , "No \"%s\" specified for Design_Variable tuple %s", keyWord , designVariableInput->name); } |
9460 | keyWord, designVariableInput->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9460, __func__ , "No \"%s\" specified for Design_Variable tuple %s", keyWord , designVariableInput->name); }; |
9461 | goto cleanup; |
9462 | } |
9463 | AIM_NOTNULL(groupName, aimInfo, status){ if (groupName == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 9463, __func__, 1, "%s == NULL!", "groupName" ); goto cleanup; } }; |
9464 | |
9465 | // collect materials associated with groupName |
9466 | status = fea_findMaterialsByNames(feaProblem, numGroupName, groupName, &numMaterial, &materialSet); |
9467 | |
9468 | if (status == CAPS_SUCCESS0) { |
9469 | |
9470 | AIM_ALLOC(designVariableRelation->materialSetID, numMaterial, int, aimInfo, status){ if (designVariableRelation->materialSetID != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9470 , __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->materialSetID" ); goto cleanup; } size_t memorysize = numMaterial; designVariableRelation ->materialSetID = (int *) EG_alloc(memorysize*sizeof(int)) ; if (designVariableRelation->materialSetID == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9470 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->materialSetID" , memorysize, "int"); goto cleanup; } }; |
9471 | AIM_ALLOC(designVariableRelation->materialSetType, numMaterial, int, aimInfo, status){ if (designVariableRelation->materialSetType != ((void*)0 )) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9471 , __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->materialSetType" ); goto cleanup; } size_t memorysize = numMaterial; designVariableRelation ->materialSetType = (int *) EG_alloc(memorysize*sizeof(int )); if (designVariableRelation->materialSetType == ((void* )0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9471, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->materialSetType" , memorysize, "int"); goto cleanup; } }; |
9472 | designVariableRelation->numMaterialID = numMaterial; |
9473 | |
9474 | for (j = 0; j < numMaterial; j++) { |
9475 | |
9476 | material = materialSet[j]; |
9477 | designVariableRelation->materialSetID[j] = material->materialID; |
9478 | designVariableRelation->materialSetType[j] = material->materialType; |
9479 | |
9480 | } |
9481 | } |
9482 | |
9483 | // collect properties associated with groupName |
9484 | status = fea_findPropertiesByNames(feaProblem, numGroupName, groupName, |
9485 | &numProperty, &propertySet); |
9486 | |
9487 | if (status == CAPS_SUCCESS0) { |
9488 | |
9489 | AIM_ALLOC(designVariableRelation->propertySetID, numProperty, int, aimInfo, status){ if (designVariableRelation->propertySetID != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9489 , __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->propertySetID" ); goto cleanup; } size_t memorysize = numProperty; designVariableRelation ->propertySetID = (int *) EG_alloc(memorysize*sizeof(int)) ; if (designVariableRelation->propertySetID == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9489 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->propertySetID" , memorysize, "int"); goto cleanup; } }; |
9490 | AIM_ALLOC(designVariableRelation->propertySetType, numProperty, int, aimInfo, status){ if (designVariableRelation->propertySetType != ((void*)0 )) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9490 , __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->propertySetType" ); goto cleanup; } size_t memorysize = numProperty; designVariableRelation ->propertySetType = (int *) EG_alloc(memorysize*sizeof(int )); if (designVariableRelation->propertySetType == ((void* )0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9490, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->propertySetType" , memorysize, "int"); goto cleanup; } }; |
9491 | designVariableRelation->numPropertyID = numProperty; |
9492 | |
9493 | for (j = 0; j < numProperty; j++) { |
9494 | |
9495 | property = propertySet[j]; |
9496 | designVariableRelation->propertySetID[j] = property->propertyID; |
9497 | designVariableRelation->propertySetType[j] = property->propertyType; |
9498 | |
9499 | } |
9500 | } |
9501 | |
9502 | // collect elements associated with groupName |
9503 | status = mesh_findGroupElements( |
9504 | &feaProblem->feaMesh, attrMap, numGroupName, groupName, &numElement, &elementSet); |
9505 | |
9506 | if (status == CAPS_SUCCESS0) { |
9507 | |
9508 | AIM_ALLOC(designVariableRelation->elementSetID, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetID != ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9508, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->elementSetID" ); goto cleanup; } size_t memorysize = numElement; designVariableRelation ->elementSetID = (int *) EG_alloc(memorysize*sizeof(int)); if (designVariableRelation->elementSetID == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9508, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetID" , memorysize, "int"); goto cleanup; } }; |
9509 | AIM_ALLOC(designVariableRelation->elementSetType, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetType != ((void*)0) ) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9509 , __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->elementSetType" ); goto cleanup; } size_t memorysize = numElement; designVariableRelation ->elementSetType = (int *) EG_alloc(memorysize*sizeof(int) ); if (designVariableRelation->elementSetType == ((void*)0 )) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9509 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetType" , memorysize, "int"); goto cleanup; } }; |
9510 | AIM_ALLOC(designVariableRelation->elementSetSubType, numElement, int, aimInfo, status){ if (designVariableRelation->elementSetSubType != ((void* )0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 9510, __func__, 1, "AIM_ALLOC: %s != NULL", "designVariableRelation->elementSetSubType" ); goto cleanup; } size_t memorysize = numElement; designVariableRelation ->elementSetSubType = (int *) EG_alloc(memorysize*sizeof(int )); if (designVariableRelation->elementSetSubType == ((void *)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 9510, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "designVariableRelation->elementSetSubType" , memorysize, "int"); goto cleanup; } }; |
9511 | designVariableRelation->numElementID = numElement; |
9512 | |
9513 | for (j = 0; j < numElement; j++) { |
9514 | |
9515 | element = elementSet[j]; |
9516 | designVariableRelation->elementSetID[j] = element->elementID; |
9517 | designVariableRelation->elementSetType[j] = element->elementType; |
9518 | feaData = (feaMeshDataStruct *) element->analysisData; |
9519 | designVariableRelation->elementSetSubType[j] = feaData->elementSubType; |
9520 | |
9521 | } |
9522 | } |
9523 | |
9524 | if (groupName != NULL((void*)0)) |
9525 | string_freeArray(numGroupName, &groupName); |
9526 | numGroupName = 0; |
9527 | groupName = NULL((void*)0); |
9528 | |
9529 | AIM_FREE(materialSet){ EG_free(materialSet); materialSet = ((void*)0); }; |
9530 | AIM_FREE(propertySet){ EG_free(propertySet); propertySet = ((void*)0); }; |
9531 | AIM_FREE(elementSet){ EG_free(elementSet); elementSet = ((void*)0); }; |
9532 | |
9533 | /*! \page feaDesignVariableRelation |
9534 | * |
9535 | * \if (NASTRAN || TACS || MASSTRAN) |
9536 | * <ul> |
9537 | * <li> <B>variableName = "(no default)"</B> </li> <br> |
9538 | * Single or list of names of design variables linked to this relation |
9539 | * </ul> |
9540 | * \endif |
9541 | * \if (ASTROS) |
9542 | * <ul> |
9543 | * <li> <B>variableName = "(no default)"</B> </li> <br> |
9544 | * Name of design variable linked to this relation |
9545 | * </ul> |
9546 | * \endif |
9547 | */ |
9548 | keyWord = "variableName"; |
9549 | status = json_getStringDynamicArray( |
9550 | designVariableInput->value, keyWord, |
9551 | &designVariableRelation->numDesignVariable, &designVariableRelation->designVariableNameSet); |
9552 | if (status != CAPS_SUCCESS0) { |
9553 | // required |
9554 | AIM_ERROR(aimInfo, "No \"%s\" specified for Design_Variable_Relation tuple %s",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9555, __func__ , "No \"%s\" specified for Design_Variable_Relation tuple %s" , keyWord, designVariableInput->name); } |
9555 | keyWord, designVariableInput->name){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9555, __func__ , "No \"%s\" specified for Design_Variable_Relation tuple %s" , keyWord, designVariableInput->name); }; |
9556 | goto cleanup; |
9557 | } |
9558 | |
9559 | /*! \page feaDesignVariableRelation |
9560 | * |
9561 | * \if (NASTRAN || TACS || MASSTRAN) |
9562 | * <ul> |
9563 | * <li> <B>fieldName = "(no default)"</B> </li> <br> |
9564 | * Fieldname of variable relation (e.g. "E" for Young's Modulus). Design Variable Relations can be defined as three types based on the <c>variableType</c> value. |
9565 | * These are Material, Property, or Element. This means that an aspect of a material, property, or element input can change in the optimization problem. This input |
9566 | * specifies what aspect of the Material, Property, or Element is changing. |
9567 | * \if (MASSTRAN) |
9568 | * -# <b> Material Types</b> Selected based on the material type (see \ref feaMaterial, materialType) referenced in the <c>componentName</c> above. |
9569 | * - <c> materialType = "Isotropic" </c> |
9570 | * - "density" |
9571 | * -# <b> Property Types</b> (see \ref feaProperty) |
9572 | * - <c>propertyType = "ConcentratedMass"</c> |
9573 | * - "mass", |
9574 | * - "massOffset1", "massOffset2", "massOffset2" |
9575 | * - "Ixx", "Iyy", "Izz", "Ixy", "Ixz", "Iyz" |
9576 | * - <c>propertyType = "Shell"</c> |
9577 | * - "membraneThickness", "massPerArea" |
9578 | * \else |
9579 | * -# <b> Material Types</b> Selected based on the material type (see \ref feaMaterial, materialType) referenced in the <c>componentName</c> above. |
9580 | * - <c><b> MAT1</b>, materialType = "Isotropic" </c> |
9581 | * - "E", "G", "NU", "RHO", "A" |
9582 | * - <c><b> MAT2</b>, materialType = "Anisothotropic" </c> |
9583 | * - "G11", "G12", "G13", "G22", "G23", "G33", "RHO", "A1", "A2", "A3" |
9584 | * - <c><b> MAT8</b>, materialType = "Orthotropic" </c> |
9585 | * - "E1", "E2", "NU12", "G12", "G1Z", "G2Z", "RHO", "A1", "A2" |
9586 | * - <c><b> MAT9</b>, materialType = "Anisotropic" </c> |
9587 | * - "G11", "G12", "G13", "G14", "G15", "G16" |
9588 | * - "G22", "G23", "G24", "G25", "G26" |
9589 | * - "G33", "G34", "G35", "G36" |
9590 | * - "G44", "G45", "G46" |
9591 | * - "G55", "G56", "G66" |
9592 | * - "RHO", "A1", "A2", "A3", "A4", "A5", "A6" |
9593 | * -# <b> Property Types</b> (see \ref feaProperty) |
9594 | * - <c><b> PROD</b> </c> <c>propertyType = "Rod"</c> |
9595 | * - "A", "J" |
9596 | * - <c><b> PBAR</b> </c> <c>propertyType = "Bar"</c> |
9597 | * - "A", "I1", "I2", "J" |
9598 | * - <c><b> PSHELL</b> </c> <c>propertyType = "Shell"</c> |
9599 | * - "T" |
9600 | * - <c><b> PCOMP</b> </c> <c>propertyType = "Composite"</c> |
9601 | * - "T1", "THETA1", "T2", "THETA2", ... "Ti", "THETAi" |
9602 | * - <c><b> PSOLID</b> </c> <c>propertyType = "Solid"</c> |
9603 | * - not supported |
9604 | * -# <b> Element Types</b> |
9605 | * - <c><b> CTRIA3, CQUAD4</b> </c> <c>propertyType = "Shell"</c> |
9606 | * - "ZOFFS" |
9607 | * \endif |
9608 | * </ul> |
9609 | * \endif |
9610 | */ |
9611 | keyWord = "fieldName"; |
9612 | status = json_getString( |
9613 | designVariableInput->value, keyWord, |
9614 | &designVariableRelation->fieldName); |
9615 | if (status != CAPS_SUCCESS0) { |
9616 | // optional |
9617 | } |
9618 | |
9619 | /*! \page feaDesignVariableRelation |
9620 | * |
9621 | * \if (NASTRAN || TACS) |
9622 | * <ul> |
9623 | * <li> <B>fieldPosition = 0</B> </li> <br> |
9624 | * This input is ignored if not defined. The user may use this field instead of the <c>fieldName</c> input defined above to |
9625 | * relate design variables and property, material, or elements. This requires knowledge of Nastran bulk data input format for material, |
9626 | * property, and element input cards. |
9627 | * </ul> |
9628 | * \endif |
9629 | */ |
9630 | |
9631 | keyWord = "fieldPosition"; |
9632 | status = json_getInteger( |
9633 | designVariableInput->value, keyWord, |
9634 | &designVariableRelation->fieldPosition); |
9635 | if (status != CAPS_SUCCESS0) { |
9636 | // optional |
9637 | } |
9638 | |
9639 | /*! \page feaDesignVariableRelation |
9640 | * |
9641 | * \if (NASTRAN || TACS || ASTROS || MASSTRAN) |
9642 | * <ul> |
9643 | * <li> <B>constantCoeff = 0.0</B> </li> <br> |
9644 | * Constant term of relation. |
9645 | * </ul> |
9646 | * \endif |
9647 | */ |
9648 | keyWord = "constantCoeff"; |
9649 | status = json_getDouble( |
9650 | designVariableInput->value, keyWord, |
9651 | &designVariableRelation->constantRelationCoeff); |
9652 | if (status != CAPS_SUCCESS0) { |
9653 | // default |
9654 | designVariableRelation->constantRelationCoeff = 0.0; |
9655 | } |
9656 | |
9657 | /*! \page feaDesignVariableRelation |
9658 | * |
9659 | * \if (NASTRAN || TACS || ASTROS || MASSTRAN) |
9660 | * <ul> |
9661 | * <li> <B>linearCoeff = 1.0</B> </li> <br> |
9662 | * Single or list of coefficients of linear relation. Must be same length as <c>variableName</c>. |
9663 | * </ul> |
9664 | * \endif |
9665 | */ |
9666 | keyWord = "linearCoeff"; |
9667 | status = json_getDoubleDynamicArray( |
9668 | designVariableInput->value, keyWord, |
9669 | &numLinearCoeff, &designVariableRelation->linearRelationCoeff); |
9670 | |
9671 | if (status != CAPS_SUCCESS0) { |
9672 | // default |
9673 | numLinearCoeff = designVariableRelation->numDesignVariable; |
9674 | designVariableRelation->linearRelationCoeff = EG_alloc(numLinearCoeff * sizeof(double)); |
9675 | if (designVariableRelation->linearRelationCoeff == NULL((void*)0)) { |
9676 | status = EGADS_MALLOC-4; |
9677 | goto cleanup; |
9678 | } |
9679 | |
9680 | for (i = 0; i < numLinearCoeff; i++) { |
9681 | designVariableRelation->linearRelationCoeff[i] = 1.0; |
9682 | } |
9683 | } |
9684 | |
9685 | if (numLinearCoeff != designVariableRelation->numDesignVariable) { |
9686 | AIM_ERROR(aimInfo, "Number of \"linearCoeff\" values (%d) does not match"{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9688, __func__ , "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)" , numLinearCoeff, designVariableRelation->numDesignVariable ); } |
9687 | " number of \"variableName\" values (%d)",{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9688, __func__ , "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)" , numLinearCoeff, designVariableRelation->numDesignVariable ); } |
9688 | numLinearCoeff, designVariableRelation->numDesignVariable){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 9688, __func__ , "Number of \"linearCoeff\" values (%d) does not match" " number of \"variableName\" values (%d)" , numLinearCoeff, designVariableRelation->numDesignVariable ); }; |
9689 | status = CAPS_BADVALUE-311; |
9690 | goto cleanup; |
9691 | } |
9692 | |
9693 | status = CAPS_SUCCESS0; |
9694 | |
9695 | cleanup: |
9696 | |
9697 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
9698 | |
9699 | return status; |
9700 | } |
9701 | |
9702 | // Get the design constraints from a capsTuple |
9703 | int fea_getDesignConstraint(void *aimInfo, |
9704 | int numDesignConstraintTuple, |
9705 | capsTuple designConstraintTuple[], |
9706 | feaProblemStruct *feaProblem) { |
9707 | |
9708 | /*! \page feaDesignConstraint FEA Design Constraints |
9709 | * Structure for the design constraint tuple = (`DesignConstraint Name', `Value'). |
9710 | * 'DesignConstraint Name' defines the reference name for the design constraint being specified. |
9711 | * The "Value" must be a JSON String dictionary (see Section \ref jsonStringDesignConstraint). |
9712 | */ |
9713 | |
9714 | int status; //Function return |
9715 | |
9716 | int i, groupIndex, attrIndex; // Indexing |
9717 | |
9718 | char *keyValue = NULL((void*)0); |
9719 | char *keyWord = NULL((void*)0); |
9720 | |
9721 | char *tempString = NULL((void*)0); |
9722 | |
9723 | char **groupName = NULL((void*)0); |
9724 | int numGroupName = 0; |
9725 | |
9726 | // Destroy our design constraints structures coming in if aren't 0 and NULL already |
9727 | if (feaProblem->feaDesignConstraint != NULL((void*)0)) { |
9728 | for (i = 0; i < feaProblem->numDesignConstraint; i++) { |
9729 | status = destroy_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]); |
9730 | if (status != CAPS_SUCCESS0) return status; |
9731 | } |
9732 | } |
9733 | if (feaProblem->feaDesignConstraint != NULL((void*)0)) EG_free(feaProblem->feaDesignConstraint); |
9734 | feaProblem->feaDesignConstraint = NULL((void*)0); |
9735 | feaProblem->numDesignConstraint = 0; |
9736 | |
9737 | printf("\nGetting FEA design constraints.......\n"); |
9738 | |
9739 | feaProblem->numDesignConstraint = numDesignConstraintTuple; |
9740 | |
9741 | printf("\tNumber of design constraints - %d\n", feaProblem->numDesignConstraint); |
9742 | |
9743 | if (feaProblem->numDesignConstraint > 0) { |
9744 | feaProblem->feaDesignConstraint = (feaDesignConstraintStruct *) EG_alloc(feaProblem->numDesignConstraint * sizeof(feaDesignConstraintStruct)); |
9745 | |
9746 | if (feaProblem->feaDesignConstraint == NULL((void*)0)) return EGADS_MALLOC-4; |
9747 | |
9748 | } else { |
9749 | printf("\tNumber of design constraint values in input tuple is 0\n"); |
9750 | return CAPS_NOTFOUND-303; |
9751 | } |
9752 | |
9753 | for (i = 0; i < feaProblem->numDesignConstraint; i++) { |
9754 | status = initiate_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]); |
9755 | if (status != CAPS_SUCCESS0) return status; |
9756 | } |
9757 | |
9758 | for (i = 0; i < feaProblem->numDesignConstraint; i++) { |
9759 | |
9760 | printf("\tDesign_Constraint name - %s\n", designConstraintTuple[i].name); |
9761 | |
9762 | feaProblem->feaDesignConstraint[i].name = (char *) EG_alloc(((strlen(designConstraintTuple[i].name)) + 1)*sizeof(char)); |
9763 | if (feaProblem->feaDesignConstraint[i].name == NULL((void*)0)) return EGADS_MALLOC-4; |
9764 | |
9765 | memcpy(feaProblem->feaDesignConstraint[i].name, designConstraintTuple[i].name, strlen(designConstraintTuple[i].name)*sizeof(char)); |
9766 | feaProblem->feaDesignConstraint[i].name[strlen(designConstraintTuple[i].name)] = '\0'; |
9767 | |
9768 | feaProblem->feaDesignConstraint[i].designConstraintID = i + 1; |
9769 | |
9770 | // Do we have a json string? |
9771 | if (strncmp(designConstraintTuple[i].value, "{", 1) == 0) { |
9772 | //printf("JSON String - %s\n", designConstraintTuple[i].value); |
9773 | |
9774 | /*! \page feaDesignConstraint |
9775 | * \section jsonStringDesignConstraint JSON String Dictionary |
9776 | * |
9777 | * If "Value" is JSON string dictionary |
9778 | * \if (NASTRAN || ASTROS) |
9779 | * (eg. "Value" = {"groupName": "plate", "upperBound": 10.0}) |
9780 | * \endif |
9781 | * the following keywords ( = default values) may be used: |
9782 | * |
9783 | * \if (NASTRAN || ASTROS) |
9784 | * <ul> |
9785 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
9786 | * Single or list of <c>capsGroup</c> name(s) |
9787 | * to the design variable (e.g. "Name1" or ["Name1","Name2",...].The property (see \ref feaProperty) also |
9788 | * assigned to the same <c>capsGroup</c> will be automatically related to this constraint entry. |
9789 | * </ul> |
9790 | * \endif |
9791 | * |
9792 | */ |
9793 | |
9794 | // Get material/properties that the design constraint should be applied to |
9795 | keyWord = "groupName"; |
9796 | status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue); |
9797 | if (status == CAPS_SUCCESS0) { |
9798 | |
9799 | status = string_toStringDynamicArray(keyValue, &numGroupName, &groupName); |
9800 | if (keyValue != NULL((void*)0)) { |
9801 | EG_free(keyValue); |
9802 | keyValue = NULL((void*)0); |
9803 | } |
9804 | |
9805 | if (status != CAPS_SUCCESS0) return status; |
9806 | |
9807 | feaProblem->feaDesignConstraint[i].numPropertyID = 0; |
9808 | for (groupIndex = 0; groupIndex < numGroupName; groupIndex++) { |
9809 | |
9810 | for (attrIndex = 0; attrIndex < feaProblem->numProperty; attrIndex++) { |
9811 | |
9812 | if (strcasecmp(feaProblem->feaProperty[attrIndex].name, groupName[groupIndex]) == 0) { |
9813 | |
9814 | feaProblem->feaDesignConstraint[i].numPropertyID += 1; |
9815 | |
9816 | if (feaProblem->feaDesignConstraint[i].numPropertyID == 1) { |
9817 | |
9818 | feaProblem->feaDesignConstraint[i].propertySetID = (int *) EG_alloc(feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int)); |
9819 | feaProblem->feaDesignConstraint[i].propertySetType = (int *) EG_alloc(feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int)); |
9820 | |
9821 | } else { |
9822 | |
9823 | feaProblem->feaDesignConstraint[i].propertySetID = (int *) EG_reall(feaProblem->feaDesignConstraint[i].propertySetID, |
9824 | feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int)); |
9825 | feaProblem->feaDesignConstraint[i].propertySetType = (int *) EG_reall(feaProblem->feaDesignConstraint[i].propertySetType, |
9826 | feaProblem->feaDesignConstraint[i].numPropertyID *sizeof(int)); |
9827 | |
9828 | } |
9829 | |
9830 | if (feaProblem->feaDesignConstraint[i].propertySetID == NULL((void*)0) || |
9831 | feaProblem->feaDesignConstraint[i].propertySetType == NULL((void*)0) ) { |
9832 | |
9833 | status = string_freeArray(numGroupName, &groupName); |
9834 | if (status != CAPS_SUCCESS0) return status; |
9835 | groupName = NULL((void*)0); |
9836 | return EGADS_MALLOC-4; |
9837 | } |
9838 | |
9839 | feaProblem->feaDesignConstraint[i].propertySetID[feaProblem->feaDesignConstraint[i].numPropertyID-1] = feaProblem->feaProperty[attrIndex].propertyID; |
9840 | feaProblem->feaDesignConstraint[i].propertySetType[feaProblem->feaDesignConstraint[i].numPropertyID-1] = feaProblem->feaProperty[attrIndex].propertyType; |
9841 | |
9842 | break; |
9843 | } |
9844 | } |
9845 | |
9846 | if (feaProblem->feaDesignConstraint[i].numPropertyID != groupIndex+1) { |
9847 | |
9848 | printf("\tWarning: DesignConstraint property name, %s, not found in feaProperty structure\n", groupName[groupIndex]); |
9849 | |
9850 | } |
9851 | } |
9852 | |
9853 | status = string_freeArray(numGroupName, &groupName); |
9854 | if (status != CAPS_SUCCESS0) return status; |
9855 | groupName = NULL((void*)0); |
9856 | } |
9857 | |
9858 | //Fill up designConstraint properties |
9859 | /*! \page feaDesignConstraint |
9860 | * |
9861 | * \if (NASTRAN || ASTROS) |
9862 | * <ul> |
9863 | * <li> <B> constraintType = "Property" </B> </li> <br> |
9864 | * The type of design constraint. Options: "Property", "Flutter" |
9865 | * </ul> |
9866 | * \endif |
9867 | */ |
9868 | keyWord = "constraintType"; |
9869 | status = json_getString( |
9870 | designConstraintTuple[i].value, keyWord, &keyValue); |
9871 | if (status == CAPS_SUCCESS0) { |
9872 | AIM_NOTNULL(keyValue, aimInfo, status){ if (keyValue == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 9872, __func__, 1, "%s == NULL!", "keyValue" ); goto cleanup; } }; |
9873 | if (strcasecmp(keyValue, "Property") == 0) |
9874 | feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon; |
9875 | else if (strcasecmp(keyValue, "Flutter") == 0) |
9876 | feaProblem->feaDesignConstraint[i].designConstraintType = FlutterDesignCon; |
9877 | else { |
9878 | PRINT_WARNING("Unknown constraintType %s... defaulting to Property.", keyValue)fprintf(stderr, "[ WARNING ] " "Unknown constraintType %s... defaulting to Property." "\n", keyValue);; |
9879 | feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon; |
9880 | } |
9881 | } |
9882 | else { |
9883 | feaProblem->feaDesignConstraint[i].designConstraintType = PropertyDesignCon; |
9884 | } |
9885 | |
9886 | if (keyValue != NULL((void*)0)) EG_free(keyValue); |
9887 | keyValue = NULL((void*)0); |
9888 | |
9889 | /*! \page feaDesignConstraint |
9890 | * |
9891 | * \if (NASTRAN || ASTROS) |
9892 | * <ul> |
9893 | * <li> <B>lowerBound = 0.0</B> </li> <br> |
9894 | * Lower bound for the design constraint. |
9895 | * </ul> |
9896 | * \endif |
9897 | * |
9898 | */ |
9899 | keyWord = "lowerBound"; |
9900 | status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue); |
9901 | if (status == CAPS_SUCCESS0) { |
9902 | |
9903 | status = string_toDouble(keyValue, &feaProblem->feaDesignConstraint[i].lowerBound); |
9904 | if (keyValue != NULL((void*)0)) { |
9905 | EG_free(keyValue); |
9906 | keyValue = NULL((void*)0); |
9907 | } |
9908 | if (status != CAPS_SUCCESS0) return status; |
9909 | } |
9910 | |
9911 | /*! \page feaDesignConstraint |
9912 | * |
9913 | * \if (NASTRAN || ASTROS) |
9914 | * <ul> |
9915 | * <li> <B>upperBound = 0.0</B> </li> <br> |
9916 | * Upper bound for the design constraint. |
9917 | * </ul> |
9918 | * \endif |
9919 | * |
9920 | */ |
9921 | keyWord = "upperBound"; |
9922 | status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue); |
9923 | if (status == CAPS_SUCCESS0) { |
9924 | |
9925 | status = string_toDouble(keyValue, &feaProblem->feaDesignConstraint[i].upperBound); |
9926 | if (keyValue != NULL((void*)0)) { |
9927 | EG_free(keyValue); |
9928 | keyValue = NULL((void*)0); |
9929 | } |
9930 | if (status != CAPS_SUCCESS0) return status; |
9931 | } |
9932 | |
9933 | /*! \page feaDesignConstraint |
9934 | * |
9935 | * \if (NASTRAN || ASTROS) |
9936 | * <ul> |
9937 | * <li> <B>responseType = "(no default)"</B> </li> <br> |
9938 | * Response type options for DRESP1 Entry (see Nastran manual). |
9939 | * - Implemented Options |
9940 | * -# <c>STRESS</c>, for <c>propertyType = "Rod" or "Shell"</c> (see \ref feaProperty) |
9941 | * -# <c>CFAILURE</c>, for <c>propertyType = "Composite"</c> (see \ref feaProperty) |
9942 | * </ul> |
9943 | * \endif |
9944 | * |
9945 | */ |
9946 | keyWord = "responseType"; |
9947 | status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue); |
9948 | if (status == CAPS_SUCCESS0) { |
9949 | |
9950 | tempString = string_removeQuotation(keyValue); |
9951 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 9951, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
9952 | |
9953 | feaProblem->feaDesignConstraint[i].responseType = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
9954 | if(feaProblem->feaDesignConstraint[i].responseType == NULL((void*)0)) { |
9955 | if (tempString != NULL((void*)0)) EG_free(tempString); |
9956 | |
9957 | return EGADS_MALLOC-4; |
9958 | } |
9959 | |
9960 | memcpy(feaProblem->feaDesignConstraint[i].responseType, tempString, strlen(tempString)*sizeof(char)); |
9961 | feaProblem->feaDesignConstraint[i].responseType[strlen(tempString)] = '\0'; |
9962 | |
9963 | if (keyValue != NULL((void*)0)) { |
9964 | EG_free(keyValue); |
9965 | keyValue = NULL((void*)0); |
9966 | } |
9967 | |
9968 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
9969 | } |
9970 | |
9971 | /*! \page feaDesignConstraint |
9972 | * |
9973 | * \if (NASTRAN || ASTROS) |
9974 | * <ul> |
9975 | * <li> <B>fieldName = "(no default)"</B> </li> <br> |
9976 | * For constraints, this field is only used currently when applying constraints to composites. This field is used to identify |
9977 | * the specific lamina in a stacking sequence that a constraint is being applied too. Note if the user has design variables |
9978 | * for both THEATA1 and T1 it is likely that only a single constraint on the first lamina is required. For this reason, the user |
9979 | * can simply enter LAMINA1 in addition to the possible entries defined in the \ref feaDesignVariable section. |
9980 | * Additionally, the <c>fieldPosition</c> integer entry below can be used. In this case <c>"LAMINA1" = 1</c>. |
9981 | * |
9982 | * * -# <b> Property Types</b> (see \ref feaProperty) |
9983 | * - <c><b> PCOMP</b> </c> <c>propertyType = "Composite"</c> |
9984 | * - "T1", "THETA1", "T2", "THETA2", ... "Ti", "THETAi" |
9985 | * - "LAMINA1", "LAMINA2", ... "LAMINAi" |
9986 | * |
9987 | * </ul> |
9988 | * \endif |
9989 | */ |
9990 | |
9991 | keyWord = "fieldName"; |
9992 | status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue); |
9993 | if (status == CAPS_SUCCESS0) { |
9994 | |
9995 | tempString = string_removeQuotation(keyValue); |
9996 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 9996, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; |
9997 | |
9998 | feaProblem->feaDesignConstraint[i].fieldName = EG_alloc((strlen(tempString) + 1)*sizeof(char)); |
9999 | if(feaProblem->feaDesignConstraint[i].fieldName == NULL((void*)0)) { |
10000 | if (tempString != NULL((void*)0)) EG_free(tempString); |
10001 | |
10002 | return EGADS_MALLOC-4; |
10003 | } |
10004 | |
10005 | memcpy(feaProblem->feaDesignConstraint[i].fieldName, tempString, strlen(tempString)*sizeof(char)); |
10006 | feaProblem->feaDesignConstraint[i].fieldName[strlen(tempString)] = '\0'; |
10007 | |
10008 | if (keyValue != NULL((void*)0)) { |
10009 | EG_free(keyValue); |
10010 | keyValue = NULL((void*)0); |
10011 | } |
10012 | |
10013 | if (tempString != NULL((void*)0)) { |
10014 | EG_free(tempString); |
10015 | tempString = NULL((void*)0); |
10016 | } |
10017 | } |
10018 | |
10019 | /*! \page feaDesignConstraint |
10020 | * |
10021 | * \if (NASTRAN || ASTROS) |
10022 | * <ul> |
10023 | * <li> <B>fieldPosition = 0</B> </li> <br> |
10024 | * This input is ignored if not defined. The user may use this field instead of the <c>fieldName</c> input defined above to |
10025 | * identify a specific lamina in a composite stacking sequence where a constraint is applied. Please read the <c>fieldName</c> |
10026 | * information above for more information. |
10027 | * </ul> |
10028 | * \endif |
10029 | */ |
10030 | |
10031 | keyWord = "fieldPosition"; |
10032 | status = search_jsonDictionary( designConstraintTuple[i].value, keyWord, &keyValue); |
10033 | if (status == CAPS_SUCCESS0) { |
10034 | |
10035 | status = string_toInteger(keyValue, &feaProblem->feaDesignConstraint[i].fieldPosition); |
10036 | if (keyValue != NULL((void*)0)) { |
10037 | EG_free(keyValue); |
10038 | keyValue = NULL((void*)0); |
10039 | } |
10040 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 10040 , __func__, 0); goto cleanup; }; |
10041 | } |
10042 | |
10043 | /*! \page feaDesignConstraint |
10044 | * |
10045 | * \if ASTROS |
10046 | * <ul> |
10047 | * <li> <B>velocityType = "TRUE" </B> </li> <br> |
10048 | * The nature of the velocity values defined with "velocity" keyword. Can be either "TRUE" for true velocity |
10049 | * or "EQUIV" for equivalent air speed. |
10050 | * </ul> |
10051 | * \endif |
10052 | */ |
10053 | keyWord = "velocityType"; |
10054 | status = json_getString( |
10055 | designConstraintTuple[i].value, keyWord, |
10056 | &feaProblem->feaDesignConstraint[i].velocityType); |
10057 | if (status != CAPS_SUCCESS0) { |
10058 | feaProblem->feaDesignConstraint[i].velocityType = EG_strdup("TRUE"); |
10059 | } |
10060 | |
10061 | /*! \page feaDesignConstraint |
10062 | * |
10063 | * \if ASTROS |
10064 | * <ul> |
10065 | * <li> <B>scalingFactor = 0.10 </B> </li> <br> |
10066 | * The constraint scaling factor. |
10067 | * </ul> |
10068 | * \endif |
10069 | */ |
10070 | keyWord = "scalingFactor"; |
10071 | status = json_getDouble( |
10072 | designConstraintTuple[i].value, keyWord, |
10073 | &feaProblem->feaDesignConstraint[i].scalingFactor); |
10074 | if (status != CAPS_SUCCESS0) { |
10075 | feaProblem->feaDesignConstraint[i].scalingFactor = 0.10; |
10076 | } |
10077 | |
10078 | /*! \page feaDesignConstraint |
10079 | * |
10080 | * \if ASTROS |
10081 | * <ul> |
10082 | * <li> <B>velocity = (No Default) </B> </li> <br> |
10083 | * The velocity values for flutter constraint. |
10084 | * Must be an array with equal length to defined "damping" values. |
10085 | * </ul> |
10086 | * \endif |
10087 | */ |
10088 | keyWord = "velocity"; |
10089 | status = json_getDoubleDynamicArray( |
10090 | designConstraintTuple[i].value, keyWord, |
10091 | &feaProblem->feaDesignConstraint[i].numVelocity, |
10092 | &feaProblem->feaDesignConstraint[i].velocity); |
10093 | if (status != CAPS_SUCCESS0) { |
10094 | // only required if constraintType == FlutterCon |
10095 | } |
10096 | |
10097 | /*! \page feaDesignConstraint |
10098 | * |
10099 | * \if ASTROS |
10100 | * <ul> |
10101 | * <li> <B>damping = (No Default) </B> </li> <br> |
10102 | * The damping values for flutter constraint. |
10103 | * Must be an array with equal length to defined "velocity" values. |
10104 | * </ul> |
10105 | * \endif |
10106 | */ |
10107 | keyWord = "damping"; |
10108 | status = json_getDoubleDynamicArray( |
10109 | designConstraintTuple[i].value, keyWord, |
10110 | &feaProblem->feaDesignConstraint[i].numDamping, |
10111 | &feaProblem->feaDesignConstraint[i].damping); |
10112 | if (status != CAPS_SUCCESS0) { |
10113 | // only required if constraintType == FlutterCon |
10114 | } |
10115 | |
10116 | } else { |
10117 | |
10118 | printf("\tError: Design_Constraint tuple value is expected to be a JSON string\n"); |
10119 | return CAPS_BADVALUE-311; |
10120 | // CALL designConstraint look up |
10121 | |
10122 | } |
10123 | } |
10124 | |
10125 | printf("Done getting FEA design constraints\n"); |
10126 | status = CAPS_SUCCESS0; |
10127 | cleanup: |
10128 | AIM_FREE(keyValue){ EG_free(keyValue); keyValue = ((void*)0); }; |
10129 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; |
10130 | return status; |
10131 | } |
10132 | |
10133 | // Get the design constraints from a capsTuple |
10134 | int fea_getOptimizationControl(char *optimizationControlInput, |
10135 | feaProblemStruct *feaProblem) { |
10136 | |
10137 | /*! \page feaOptimizationControl FEA Optimization Control |
10138 | * Structure for the optimization control dictionary = `Value'. |
10139 | * The "Value" must be a JSON String dictionary (see Section \ref jsonStringDesignConstraint). |
10140 | */ |
10141 | |
10142 | int status; //Function return |
10143 | |
10144 | char *keyValue = NULL((void*)0); |
10145 | char *keyWord = NULL((void*)0); |
10146 | |
10147 | // Destroy our optimization control structures coming in if aren't 0 and NULL already |
10148 | status = destroy_feaOptimzationControlStruct(&feaProblem->feaOptimizationControl); |
10149 | if (status != CAPS_SUCCESS0) return status; |
10150 | |
10151 | printf("\nGetting FEA optimization control.......\n"); |
10152 | |
10153 | status = initiate_feaOptimizationControlStruct(&feaProblem->feaOptimizationControl); |
10154 | if (status != CAPS_SUCCESS0) return status; |
10155 | |
10156 | if (optimizationControlInput == NULL((void*)0)) { |
10157 | optimizationControlInput = "{}"; |
10158 | } |
10159 | |
10160 | // Do we have a json string? |
10161 | if (strncmp(optimizationControlInput, "{", 1) == 0) { |
10162 | |
10163 | /*! \page feaOptimizationControl |
10164 | * |
10165 | * \if NASTRAN |
10166 | * <ul> |
10167 | * <li> <B>fullyStressedDesign = 0</B> </li> <br> |
10168 | * Number of iterations with fully stressed design. |
10169 | * </ul> |
10170 | * \endif |
10171 | * |
10172 | */ |
10173 | keyWord = "fullyStressedDesign"; |
10174 | status = json_getInteger( |
10175 | optimizationControlInput, keyWord, |
10176 | &feaProblem->feaOptimizationControl.fullyStressedDesign); |
10177 | |
10178 | // Set default value if value is not in JSON |
10179 | if (status != CAPS_SUCCESS0) { |
10180 | feaProblem->feaOptimizationControl.fullyStressedDesign = 0; |
10181 | } |
10182 | |
10183 | /*! \page feaOptimizationControl |
10184 | * |
10185 | * \if NASTRAN |
10186 | * <ul> |
10187 | * <li> <B>mathProgramming = 30</B> </li> <br> |
10188 | * Number of iterations for math programming methods. |
10189 | * </ul> |
10190 | * \endif |
10191 | * |
10192 | */ |
10193 | keyWord = "mathProgramming"; |
10194 | status = json_getInteger( |
10195 | optimizationControlInput, keyWord, |
10196 | &feaProblem->feaOptimizationControl.mathProgramming); |
10197 | |
10198 | // Set default value if value is not in JSON |
10199 | if (status != CAPS_SUCCESS0) { |
10200 | feaProblem->feaOptimizationControl.mathProgramming = 30; |
10201 | } |
10202 | |
10203 | /*! \page feaOptimizationControl |
10204 | * |
10205 | * \if NASTRAN |
10206 | * <ul> |
10207 | * <li> <B>maxIter = 30</B> </li> <br> |
10208 | * Maximum number of optimization iterations. |
10209 | * </ul> |
10210 | * \endif |
10211 | * |
10212 | */ |
10213 | keyWord = "maxIter"; |
10214 | status = json_getInteger( |
10215 | optimizationControlInput, keyWord, |
10216 | &feaProblem->feaOptimizationControl.maxIter); |
10217 | |
10218 | // Set default value if value is not in JSON |
10219 | if (status != CAPS_SUCCESS0) { |
10220 | feaProblem->feaOptimizationControl.maxIter = 30; |
10221 | } |
10222 | |
10223 | /*! \page feaOptimizationControl |
10224 | * |
10225 | * \if NASTRAN |
10226 | * <ul> |
10227 | * <li> <B>constraintRetention = 1.5</B> </li> <br> |
10228 | * Constraint retention factor. |
10229 | * Will be at least 1.5 times the number of design variables |
10230 | * </ul> |
10231 | * \endif |
10232 | * |
10233 | */ |
10234 | keyWord = "constraintRetention"; |
10235 | status = json_getDouble( |
10236 | optimizationControlInput, keyWord, |
10237 | &feaProblem->feaOptimizationControl.constraintRetention); |
10238 | |
10239 | // Set default value if value is not in JSON |
10240 | if (status != CAPS_SUCCESS0) { |
10241 | feaProblem->feaOptimizationControl.constraintRetention = 1.5; |
10242 | } |
10243 | |
10244 | /*! \page feaOptimizationControl |
10245 | * |
10246 | * \if NASTRAN |
10247 | * <ul> |
10248 | * <li> <B>eps = 1.0</B> </li> <br> |
10249 | * Constraint retention parameter in which all constraints having a |
10250 | * value greater than "eps" will be considered active. |
10251 | * |
10252 | * </ul> |
10253 | * \endif |
10254 | * |
10255 | */ |
10256 | keyWord = "eps"; |
10257 | status = json_getDouble( |
10258 | optimizationControlInput, keyWord, |
10259 | &feaProblem->feaOptimizationControl.eps); |
10260 | |
10261 | // Set default value if value is not in JSON |
10262 | if (status != CAPS_SUCCESS0) { |
10263 | feaProblem->feaOptimizationControl.eps = 1.0; |
10264 | } |
10265 | |
10266 | /*! \page feaOptimizationControl |
10267 | * |
10268 | * \if NASTRAN |
10269 | * <ul> |
10270 | * <li> <B>moveLimit = 1.0</B> </li> <br> |
10271 | * Move limit bound. |
10272 | * </ul> |
10273 | * \endif |
10274 | * |
10275 | */ |
10276 | keyWord = "moveLimit"; |
10277 | status = json_getDouble( |
10278 | optimizationControlInput, keyWord, |
10279 | &feaProblem->feaOptimizationControl.moveLimit); |
10280 | |
10281 | // Set default value if value is not in JSON |
10282 | if (status != CAPS_SUCCESS0) { |
10283 | feaProblem->feaOptimizationControl.moveLimit = 1.5; |
10284 | } |
10285 | |
10286 | } else { |
10287 | |
10288 | printf("\tError: OptimizationControl tuple value is expected to be a JSON string\n"); |
10289 | return CAPS_BADVALUE-311; |
10290 | |
10291 | } |
10292 | |
10293 | if (keyValue != NULL((void*)0)) { |
10294 | EG_free(keyValue); |
10295 | keyValue = NULL((void*)0); |
10296 | } |
10297 | |
10298 | printf("Done getting FEA Optimization Control\n"); |
10299 | return CAPS_SUCCESS0; |
10300 | } |
10301 | |
10302 | // Get the coordinate system information from the bodies and an attribute map (of CoordSystem) |
10303 | int fea_getCoordSystem(int numBody, |
10304 | ego bodies[], |
10305 | mapAttrToIndexStruct coordSystemMap, |
10306 | int *numCoordSystem, |
10307 | feaCoordSystemStruct *feaCoordSystem[]) { |
10308 | |
10309 | int status; // Function return |
10310 | |
10311 | int i, body, face, edge, node; // Indexing |
10312 | |
10313 | int numFace = 0, numEdge = 0, numNode = 0; // Number of egos |
10314 | ego *faces = NULL((void*)0), *edges = NULL((void*)0), *nodes = NULL((void*)0); // Geometry |
10315 | |
10316 | int atype, alen; // EGADS return variables |
10317 | const int *ints; |
10318 | const double *reals; |
10319 | const char *string; |
10320 | |
10321 | int found = (int) false0; |
10322 | |
10323 | // Destroy our CoordSystem structures coming in if aren't 0 and NULL already |
10324 | if (*feaCoordSystem != NULL((void*)0)) { |
10325 | for (i = 0; i < *numCoordSystem; i++) { |
10326 | status = destroy_feaCoordSystemStruct(&(*feaCoordSystem)[i]); |
10327 | if (status != CAPS_SUCCESS0) return status; |
10328 | } |
10329 | } |
10330 | if (*feaCoordSystem != NULL((void*)0)) EG_free(*feaCoordSystem); |
10331 | *feaCoordSystem = NULL((void*)0); |
10332 | *numCoordSystem = 0; |
10333 | |
10334 | printf("\nGetting FEA coordinate systems.......\n"); |
10335 | |
10336 | *numCoordSystem = coordSystemMap.numAttribute; |
10337 | printf("\tNumber of coordinate systems - %d\n", *numCoordSystem); |
10338 | |
10339 | if (*numCoordSystem > 0) { |
10340 | *feaCoordSystem = (feaCoordSystemStruct *) EG_alloc((*numCoordSystem)*sizeof(feaCoordSystemStruct)); |
10341 | if (*feaCoordSystem == NULL((void*)0)) return EGADS_MALLOC-4; |
10342 | |
10343 | } else { |
10344 | printf("\tNo coordinate systems found - defaulting to global\n"); |
10345 | return CAPS_SUCCESS0; |
10346 | } |
10347 | |
10348 | for (i = 0; i < *numCoordSystem; i++) { |
10349 | status = initiate_feaCoordSystemStruct(&(*feaCoordSystem)[i]); |
10350 | if (status != CAPS_SUCCESS0) return status; |
10351 | } |
10352 | |
10353 | for (i = 0; i < *numCoordSystem; i++) { |
10354 | |
10355 | if (faces != NULL((void*)0)) EG_free(faces); |
10356 | if (edges != NULL((void*)0)) EG_free(edges); |
10357 | if (nodes != NULL((void*)0)) EG_free(nodes); |
10358 | |
10359 | faces = NULL((void*)0); |
10360 | edges = NULL((void*)0); |
10361 | nodes = NULL((void*)0); |
10362 | |
10363 | printf("\tCoordinate system name - %s\n", coordSystemMap.attributeName[i]); |
10364 | |
10365 | (*feaCoordSystem)[i].name = EG_strdup(coordSystemMap.attributeName[i]); |
10366 | if ((*feaCoordSystem)[i].name == NULL((void*)0)) { status = EGADS_MALLOC-4; goto cleanup; } |
10367 | |
10368 | (*feaCoordSystem)[i].coordSystemID = coordSystemMap.attributeIndex[i]; |
10369 | |
10370 | (*feaCoordSystem)[i].refCoordSystemID = 0; |
10371 | |
10372 | (*feaCoordSystem)[i].coordSystemType = RectangularCoordSystem; |
10373 | |
10374 | found = (int) false0; |
10375 | |
10376 | // Search through bodies |
10377 | for (body = 0; body < numBody; body++) { |
10378 | |
10379 | // Look at the body level |
10380 | status = EG_attributeRet(bodies[body], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string); |
10381 | if (status != EGADS_SUCCESS0 && |
10382 | status != EGADS_NOTFOUND-1) goto cleanup; |
10383 | |
10384 | if (atype == ATTRCSYS12) { |
10385 | |
10386 | // Save the origin |
10387 | (*feaCoordSystem)[i].origin[0] = reals[alen+0]; |
10388 | (*feaCoordSystem)[i].origin[1] = reals[alen+1]; |
10389 | (*feaCoordSystem)[i].origin[2] = reals[alen+2]; |
10390 | |
10391 | (*feaCoordSystem)[i].normal1[0] = reals[alen+3]; |
10392 | (*feaCoordSystem)[i].normal1[1] = reals[alen+4]; |
10393 | (*feaCoordSystem)[i].normal1[2] = reals[alen+5]; |
10394 | |
10395 | (*feaCoordSystem)[i].normal2[0] = reals[alen+6]; |
10396 | (*feaCoordSystem)[i].normal2[1] = reals[alen+7]; |
10397 | (*feaCoordSystem)[i].normal2[2] = reals[alen+8]; |
10398 | |
10399 | (*feaCoordSystem)[i].normal3[0] = reals[alen+9]; |
10400 | (*feaCoordSystem)[i].normal3[1] = reals[alen+10]; |
10401 | (*feaCoordSystem)[i].normal3[2] = reals[alen+11]; |
10402 | |
10403 | found = (int) true1; |
10404 | } |
10405 | |
10406 | if (found == (int) true1) break; |
10407 | |
10408 | // Determine the number of faces, edges, and nodes |
10409 | status = EG_getBodyTopos(bodies[body], NULL((void*)0), FACE23, &numFace, &faces); |
10410 | if (status != EGADS_SUCCESS0) goto cleanup; |
10411 | |
10412 | status = EG_getBodyTopos(bodies[body], NULL((void*)0), EDGE21, &numEdge, &edges); |
10413 | if (status != EGADS_SUCCESS0) goto cleanup; |
10414 | |
10415 | status = EG_getBodyTopos(bodies[body], NULL((void*)0), NODE20, &numNode, &nodes); |
10416 | if (status != EGADS_SUCCESS0) goto cleanup; |
10417 | |
10418 | // Loop through faces |
10419 | for (face = 0; face < numFace; face++) { |
10420 | |
10421 | status = EG_attributeRet(faces[face], (const char *) (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string); |
10422 | |
10423 | if (status == EGADS_NOTFOUND-1) continue; |
10424 | if (status != EGADS_SUCCESS0) goto cleanup; |
10425 | |
10426 | if (atype == ATTRCSYS12) { |
10427 | |
10428 | // Save the origin |
10429 | (*feaCoordSystem)[i].origin[0] = reals[alen+0]; |
10430 | (*feaCoordSystem)[i].origin[1] = reals[alen+1]; |
10431 | (*feaCoordSystem)[i].origin[2] = reals[alen+2]; |
10432 | |
10433 | (*feaCoordSystem)[i].normal1[0] = reals[alen+3]; |
10434 | (*feaCoordSystem)[i].normal1[1] = reals[alen+4]; |
10435 | (*feaCoordSystem)[i].normal1[2] = reals[alen+5]; |
10436 | |
10437 | (*feaCoordSystem)[i].normal2[0] = reals[alen+6]; |
10438 | (*feaCoordSystem)[i].normal2[1] = reals[alen+7]; |
10439 | (*feaCoordSystem)[i].normal2[2] = reals[alen+8]; |
10440 | |
10441 | (*feaCoordSystem)[i].normal3[0] = reals[alen+9]; |
10442 | (*feaCoordSystem)[i].normal3[1] = reals[alen+10]; |
10443 | (*feaCoordSystem)[i].normal3[2] = reals[alen+11]; |
10444 | |
10445 | found = (int) true1; |
10446 | |
10447 | break; |
10448 | } |
10449 | } // End face loop |
10450 | |
10451 | if (found == (int) true1) break; |
10452 | |
10453 | // Loop through edges |
10454 | for (edge = 0; edge < numEdge; edge++) { |
10455 | |
10456 | status = EG_attributeRet(edges[edge], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string); |
10457 | |
10458 | if (status == EGADS_NOTFOUND-1) continue; |
10459 | if (status != EGADS_SUCCESS0) goto cleanup; |
10460 | |
10461 | if (atype == ATTRCSYS12) { |
10462 | |
10463 | // Save the origin |
10464 | (*feaCoordSystem)[i].origin[0] = reals[alen+0]; |
10465 | (*feaCoordSystem)[i].origin[1] = reals[alen+1]; |
10466 | (*feaCoordSystem)[i].origin[2] = reals[alen+2]; |
10467 | |
10468 | (*feaCoordSystem)[i].normal1[0] = reals[alen+3]; |
10469 | (*feaCoordSystem)[i].normal1[1] = reals[alen+4]; |
10470 | (*feaCoordSystem)[i].normal1[2] = reals[alen+5]; |
10471 | |
10472 | (*feaCoordSystem)[i].normal2[0] = reals[alen+6]; |
10473 | (*feaCoordSystem)[i].normal2[1] = reals[alen+7]; |
10474 | (*feaCoordSystem)[i].normal2[2] = reals[alen+8]; |
10475 | |
10476 | (*feaCoordSystem)[i].normal3[0] = reals[alen+9]; |
10477 | (*feaCoordSystem)[i].normal3[1] = reals[alen+10]; |
10478 | (*feaCoordSystem)[i].normal3[2] = reals[alen+11]; |
10479 | |
10480 | found = (int) true1; |
10481 | |
10482 | break; |
10483 | } |
10484 | |
10485 | } // End edge loop |
10486 | |
10487 | if (found == (int) true1) break; |
10488 | |
10489 | // Loop through nodes |
10490 | for (node = 0; node < numNode; node++) { |
10491 | |
10492 | status = EG_attributeRet(nodes[node], (*feaCoordSystem)[i].name, &atype, &alen, &ints, &reals, &string); |
10493 | |
10494 | if (status == EGADS_NOTFOUND-1) continue; |
10495 | if (status != EGADS_SUCCESS0) goto cleanup; |
10496 | |
10497 | if (atype == ATTRCSYS12) { |
10498 | |
10499 | // Save the origin |
10500 | (*feaCoordSystem)[i].origin[0] = reals[alen+0]; |
10501 | (*feaCoordSystem)[i].origin[1] = reals[alen+1]; |
10502 | (*feaCoordSystem)[i].origin[2] = reals[alen+2]; |
10503 | |
10504 | (*feaCoordSystem)[i].normal1[0] = reals[alen+3]; |
10505 | (*feaCoordSystem)[i].normal1[1] = reals[alen+4]; |
10506 | (*feaCoordSystem)[i].normal1[2] = reals[alen+5]; |
10507 | |
10508 | (*feaCoordSystem)[i].normal2[0] = reals[alen+6]; |
10509 | (*feaCoordSystem)[i].normal2[1] = reals[alen+7]; |
10510 | (*feaCoordSystem)[i].normal2[2] = reals[alen+8]; |
10511 | |
10512 | (*feaCoordSystem)[i].normal3[0] = reals[alen+9]; |
10513 | (*feaCoordSystem)[i].normal3[1] = reals[alen+10]; |
10514 | (*feaCoordSystem)[i].normal3[2] = reals[alen+11]; |
10515 | |
10516 | found = (int) true1; |
10517 | |
10518 | break; |
10519 | } |
10520 | } // End node loop |
10521 | |
10522 | EG_free(faces); faces = NULL((void*)0); |
10523 | EG_free(edges); edges = NULL((void*)0); |
10524 | EG_free(nodes); nodes = NULL((void*)0); |
10525 | |
10526 | if (found == (int) true1) break; |
10527 | |
10528 | } // End body loop |
10529 | } |
10530 | |
10531 | status = CAPS_SUCCESS0; |
10532 | |
10533 | cleanup: |
10534 | |
10535 | if (status != CAPS_SUCCESS0) printf("\tError in fea_getCoordSystem = %d\n", status); |
10536 | |
10537 | EG_free(faces); |
10538 | EG_free(edges); |
10539 | EG_free(nodes); |
10540 | |
10541 | return status; |
10542 | } |
10543 | |
10544 | // Get the design equations from a capsTuple |
10545 | int fea_getDesignEquation(int numEquationTuple, |
10546 | capsTuple equationTuple[], |
10547 | feaProblemStruct *feaProblem) { |
10548 | |
10549 | /*! \page feaDesignEquation FEA Design Equations |
10550 | * Structure for the design equation tuple = ("DesignEquation Name", ["Value1", ... , "ValueN"]). |
10551 | * "DesignEquation Name" defines the reference name for the design equation being specified. |
10552 | * This string will be used in the FEA input directly. The values "Value1", ... , "ValueN" are a |
10553 | * list of strings containing the equation defintions. |
10554 | * (see Section \ref tupleValueDesignEquation). |
10555 | * |
10556 | */ |
10557 | int i, status; |
10558 | |
10559 | feaDesignEquationStruct *equation; |
10560 | |
10561 | // Ensure we are starting with no equations |
10562 | if (feaProblem->feaEquation != NULL((void*)0)) { |
10563 | for (i = 0; i < feaProblem->numEquation; i++) { |
10564 | status = destroy_feaDesignEquationStruct(&feaProblem->feaEquation[i]); |
10565 | if (status != CAPS_SUCCESS0) return status; |
10566 | } |
10567 | EG_free(feaProblem->feaEquation); |
10568 | } |
10569 | feaProblem->numEquation = 0; |
10570 | feaProblem->feaEquation = NULL((void*)0); |
10571 | |
10572 | printf("\nGetting Equations.......\n"); |
10573 | |
10574 | feaProblem->numEquation = numEquationTuple; |
10575 | printf("\tNumber of Equations - %d\n", feaProblem->numEquation); |
10576 | |
10577 | if (feaProblem->numEquation > 0) { |
10578 | |
10579 | feaProblem->feaEquation = EG_alloc( |
10580 | feaProblem->numEquation * sizeof(feaDesignEquationStruct)); |
10581 | if (feaProblem->feaEquation == NULL((void*)0)) { |
10582 | return EGADS_MALLOC-4; |
10583 | } |
10584 | |
10585 | } else { |
10586 | printf("\tNumber of equations in Analysis tuple is %d\n", |
10587 | feaProblem->numEquation); |
10588 | return CAPS_NOTFOUND-303; |
10589 | } |
10590 | |
10591 | // for each analysis equation tuple |
10592 | for (i = 0; i < feaProblem->numEquation; i++) { |
10593 | |
10594 | printf("\tDesign_Equation name - %s\n", equationTuple[i].name); |
10595 | |
10596 | equation = &feaProblem->feaEquation[i]; |
10597 | |
10598 | // initiate equation structure |
10599 | status = initiate_feaDesignEquationStruct(equation); |
10600 | if (status != CAPS_SUCCESS0) return status; |
10601 | |
10602 | // set name |
10603 | equation->name = EG_strdup(equationTuple[i].name); |
10604 | |
10605 | // set equation ID |
10606 | equation->equationID = i+1; |
10607 | |
10608 | /*! \page feaDesignEquation |
10609 | * \section tupleValueDesignEquation List of equation strings |
10610 | * |
10611 | * Each design equation tuple value is a list of strings containing the equation definitions |
10612 | * \if NASTRAN |
10613 | * (eg. ["dispsum3(s1,s2,s3)=sum(s1,s2,s3)"] |
10614 | * \endif |
10615 | * |
10616 | */ |
10617 | // set the equation array |
10618 | status = string_toStringDynamicArray( |
10619 | equationTuple[i].value, |
10620 | &equation->equationArraySize, |
10621 | &equation->equationArray); |
10622 | |
10623 | if (status != CAPS_SUCCESS0) return status; |
10624 | } |
10625 | |
10626 | return CAPS_SUCCESS0; |
10627 | } |
10628 | |
10629 | // Get the design table constants from a capsTuple |
10630 | int fea_getDesignTable(int numConstantTuple, |
10631 | capsTuple constantTuple[], |
10632 | feaProblemStruct *feaProblem) { |
10633 | |
10634 | |
10635 | /*! \page feaDesignTable FEA Table Constants |
10636 | * Structure for the table constant tuple = ("TableConstant Name", "Value"). |
10637 | * "TableConstant Name" defines the reference name for the table constant being specified. |
10638 | * This string will be used in the FEA input directly. The "Value" is the value of the |
10639 | * table constant. |
10640 | * \if NASTRAN |
10641 | * In Nastran the TableConstant Name will be the LABLi used in the DTABLE input. |
10642 | * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less. |
10643 | * |
10644 | * - <c>DTABLE LABL1 VALU1 LABL2 VALU2 LABL3 VALU3 -etc- </c> |
10645 | * \endif |
10646 | * |
10647 | */ |
10648 | int i, status; |
10649 | |
10650 | feaDesignTableStruct *table = &feaProblem->feaDesignTable; |
10651 | |
10652 | // Ensure we are starting with no constants |
10653 | status = destroy_feaDesignTableStruct(table); |
10654 | if (status != CAPS_SUCCESS0) return status; |
10655 | |
10656 | printf("\nGetting Design Table Constants.......\n"); |
10657 | |
10658 | table->numConstant = numConstantTuple; |
10659 | printf("\tNumber of Design Table Constants - %d\n", table->numConstant); |
10660 | |
10661 | if (table->numConstant > 0) { |
10662 | |
10663 | table->constantLabel = EG_alloc(table->numConstant * sizeof(char *)); |
10664 | if (table->constantLabel == NULL((void*)0)) { |
10665 | return EGADS_MALLOC-4; |
10666 | } |
10667 | |
10668 | table->constantValue = EG_alloc(table->numConstant * sizeof(double)); |
10669 | if (table->constantValue == NULL((void*)0)) { |
10670 | return EGADS_MALLOC-4; |
10671 | } |
10672 | |
10673 | } else { |
10674 | printf("\tNumber of design table constants in Analysis tuple is %d\n", |
10675 | table->numConstant); |
10676 | return CAPS_NOTFOUND-303; |
10677 | } |
10678 | |
10679 | // for each analysis table constant tuple |
10680 | for (i = 0; i < table->numConstant; i++) { |
10681 | |
10682 | printf("\tDesign_Table - %s: %s\n", |
10683 | constantTuple[i].name, constantTuple[i].value); |
10684 | |
10685 | // set constant label |
10686 | // TODO: ensure label <= 8 chars |
10687 | table->constantLabel[i] = EG_strdup(constantTuple[i].name); |
10688 | |
10689 | // set constant value |
10690 | status = string_toDouble(constantTuple[i].value, &table->constantValue[i]); |
10691 | if (status != CAPS_SUCCESS0) return status; |
10692 | } |
10693 | |
10694 | return CAPS_SUCCESS0; |
10695 | } |
10696 | |
10697 | // Function used by fea_getDesignResponse to determine which nodes are in response group |
10698 | static int _matchResponseNode(meshNodeStruct *node, void *responseIndex) { |
10699 | |
10700 | feaMeshDataStruct *feaData; |
10701 | |
10702 | if (node->analysisType == MeshStructure) { |
10703 | |
10704 | feaData = (feaMeshDataStruct *) node->analysisData; |
10705 | |
10706 | if (feaData->responseIndex == *((int *) responseIndex)) { |
10707 | return (int) true1; |
10708 | } |
10709 | } |
10710 | return (int) false0; |
10711 | } |
10712 | |
10713 | int fea_getDesignResponse(/*@unused@*/ void *aimInfo, |
10714 | int numDesignResponseTuple, |
10715 | capsTuple designResponseTuple[], |
10716 | mapAttrToIndexStruct *responseMap, |
10717 | feaProblemStruct *feaProblem) { |
10718 | |
10719 | /*! \page feaDesignResponse FEA Design Responses |
10720 | * Structure for the design response tuple = ("DesignResponse Name", "Value"). |
10721 | * "DesignResponse Name" defines the reference name for the design response being specified. |
10722 | * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary |
10723 | * (see Section \ref jsonStringDesignResponse). |
10724 | * \if NASTRAN |
10725 | * In Nastran the DesignResponse Name will be the LABEL used in the DRESP1 input. |
10726 | * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less. |
10727 | * |
10728 | * - <c>DRESP1 ID LABEL RTYPE PTYPE REGION ATTA ATTB ATT1\n ATT2 -etc-</c> |
10729 | * \endif |
10730 | * |
10731 | */ |
10732 | int i, status; |
10733 | |
10734 | int attrIndex; |
10735 | |
10736 | char *keyword; |
10737 | char *groupName = NULL((void*)0); |
10738 | |
10739 | int numNode; |
10740 | meshNodeStruct **nodeSet = NULL((void*)0); |
10741 | |
10742 | feaDesignResponseStruct *response; |
10743 | |
10744 | // Ensure we are starting with no design responses |
10745 | if (feaProblem->feaDesignResponse != NULL((void*)0)) { |
10746 | for (i = 0; i < feaProblem->numDesignResponse; i++) { |
10747 | status = destroy_feaDesignResponseStruct(&feaProblem->feaDesignResponse[i]); |
10748 | if (status != CAPS_SUCCESS0) return status; |
10749 | } |
10750 | EG_free(feaProblem->feaDesignResponse); |
10751 | } |
10752 | feaProblem->numDesignResponse = 0; |
10753 | feaProblem->feaDesignResponse = NULL((void*)0); |
10754 | |
10755 | printf("\nGetting Design Responses.......\n"); |
10756 | |
10757 | feaProblem->numDesignResponse = numDesignResponseTuple; |
10758 | printf("\tNumber of Design Responses - %d\n", feaProblem->numDesignResponse); |
10759 | |
10760 | if (feaProblem->numDesignResponse > 0) { |
10761 | |
10762 | feaProblem->feaDesignResponse = EG_alloc( |
10763 | feaProblem->numDesignResponse * sizeof(feaDesignResponseStruct)); |
10764 | if (feaProblem->feaDesignResponse == NULL((void*)0)) { |
10765 | return EGADS_MALLOC-4; |
10766 | } |
10767 | |
10768 | } else { |
10769 | printf("\tNumber of design responses in Analysis tuple is %d\n", |
10770 | feaProblem->numDesignResponse); |
10771 | return CAPS_NOTFOUND-303; |
10772 | } |
10773 | |
10774 | // for each analysis design response tuple |
10775 | for (i = 0; i < feaProblem->numDesignResponse; i++) { |
10776 | |
10777 | printf("\tDesign_Response name - %s\n", designResponseTuple[i].name); |
10778 | |
10779 | response = &feaProblem->feaDesignResponse[i]; |
10780 | |
10781 | // initiate design response structure |
10782 | status = initiate_feaDesignResponseStruct(response); |
10783 | if (status != CAPS_SUCCESS0) return status; |
10784 | |
10785 | // set name |
10786 | response->name = EG_strdup(designResponseTuple[i].name); |
10787 | |
10788 | // set response ID |
10789 | response->responseID = i+1; |
10790 | |
10791 | /*! \page feaDesignResponse |
10792 | * \section jsonStringDesignResponse JSON String Dictionary |
10793 | * |
10794 | * If "Value" is JSON string dictionary |
10795 | * \if NASTRAN |
10796 | * (eg. "Value" = {"responseType": "DISP", groupName": "plate", "component": 3}) |
10797 | * \endif |
10798 | * the following keywords ( = default values) may be used: |
10799 | * |
10800 | */ |
10801 | // make sure design response tuple value is json string |
10802 | if (!json_isDict(designResponseTuple[i].value)) { |
10803 | AIM_ERROR(aimInfo,{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10804, __func__ , "'Design_Response' tuple value must be a JSON dictionary"); } |
10804 | "'Design_Response' tuple value must be a JSON dictionary"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10804, __func__ , "'Design_Response' tuple value must be a JSON dictionary"); }; |
10805 | return CAPS_BADVALUE-311; |
10806 | } |
10807 | |
10808 | /*! \page feaDesignResponse |
10809 | * |
10810 | * \if NASTRAN |
10811 | * <ul> |
10812 | * <li> <B>responseType</B> </li> <br> |
10813 | * Type of design sensitivity response. For options, |
10814 | * see NASTRAN User Guide DRESP1 Design Sensitivity Response Attributes table. |
10815 | * </ul> |
10816 | * \endif |
10817 | */ |
10818 | keyword = "responseType"; |
10819 | status = json_getString( |
10820 | designResponseTuple[i].value, keyword, &response->responseType); |
10821 | if (status != CAPS_SUCCESS0) { |
10822 | AIM_ERROR(aimInfo, "Missing required entry \"responseType\" "{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10823, __func__ , "Missing required entry \"responseType\" " "in 'Design_Response' tuple value" ); } |
10823 | "in 'Design_Response' tuple value"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10823, __func__ , "Missing required entry \"responseType\" " "in 'Design_Response' tuple value" ); }; |
10824 | return status; |
10825 | } |
10826 | |
10827 | // keyword = "propertyType"; |
10828 | // status = json_getString( |
10829 | // designResponseTuple[i].value, keyword, &response->propertyType); |
10830 | // if (status != CAPS_SUCCESS) { |
10831 | // // optional |
10832 | // } |
10833 | |
10834 | /*! \page feaDesignResponse |
10835 | * |
10836 | * \if NASTRAN |
10837 | * <ul> |
10838 | * <li> <B>component = "(no default)"</B> </li> <br> |
10839 | * Component flag. |
10840 | * </ul> |
10841 | * \endif |
10842 | */ |
10843 | keyword = "component"; |
10844 | status = json_getInteger( |
10845 | designResponseTuple[i].value, keyword, &response->component); |
10846 | if (status != CAPS_SUCCESS0) { |
10847 | // optional |
10848 | } |
10849 | |
10850 | // TODO: temporary input |
10851 | keyword = "grid"; |
10852 | status = json_getInteger( |
10853 | designResponseTuple[i].value, keyword, &response->gridID); |
10854 | if (status != CAPS_SUCCESS0) { |
10855 | // optional |
10856 | } |
10857 | |
10858 | /*! \page feaDesignResponse |
10859 | * |
10860 | * \if NASTRAN |
10861 | * <ul> |
10862 | * <li> <B>groupName = "(no default)"</B> </li> <br> |
10863 | * Defines the reference <c>capsGroup</c> for the node being specified for the response. |
10864 | * </ul> |
10865 | * \endif |
10866 | */ |
10867 | keyword = "groupName"; |
10868 | status = json_getString( |
10869 | designResponseTuple[i].value, keyword, &groupName); |
10870 | |
10871 | if (status == CAPS_SUCCESS0) { |
10872 | AIM_NOTNULL(groupName, aimInfo, status){ if (groupName == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 10872, __func__, 1, "%s == NULL!", "groupName" ); goto cleanup; } }; |
10873 | |
10874 | // Get the corresponding response index |
10875 | status = get_mapAttrToIndexIndex(responseMap, (const char *) groupName, &attrIndex); |
10876 | |
10877 | if (status == CAPS_NOTFOUND-303) { |
10878 | printf("\tName %s not found in attribute map!!!!\n", groupName); |
10879 | continue; |
10880 | } else if (status != CAPS_SUCCESS0) return status; |
10881 | |
10882 | status = mesh_findNodes(&feaProblem->feaMesh, |
10883 | _matchResponseNode, (void *) &attrIndex, |
10884 | &numNode, &nodeSet); |
10885 | if (status != CAPS_SUCCESS0) return status; |
10886 | |
10887 | if (numNode == 0) { |
10888 | AIM_ERROR(aimInfo, "No node found for capsGroup %s", groupName){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 10888, __func__ , "No node found for capsGroup %s", groupName); }; |
10889 | return CAPS_NOTFOUND-303; |
10890 | } |
10891 | else if (numNode > 1) { // TODO: would there ever be more than 1 node expected? |
10892 | PRINT_WARNING("More than 1 node found for capsGroup %s"fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s" "... using first matching node." "\n", groupName); |
10893 | "... using first matching node.",fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s" "... using first matching node." "\n", groupName); |
10894 | groupName)fprintf(stderr, "[ WARNING ] " "More than 1 node found for capsGroup %s" "... using first matching node." "\n", groupName);; |
10895 | } |
10896 | |
10897 | response->gridID = nodeSet[0]->nodeID; |
10898 | |
10899 | EG_free(nodeSet); |
10900 | nodeSet = NULL((void*)0); |
10901 | |
10902 | } |
10903 | else { |
10904 | // required |
10905 | // AIM_ERROR(aimInfo, "Missing required entry \"groupName\" " |
10906 | // "in 'Design_Response' tuple value"); |
10907 | // return status; |
10908 | } |
10909 | |
10910 | if (groupName != NULL((void*)0)) { |
10911 | EG_free(groupName); |
10912 | groupName = NULL((void*)0); |
10913 | } |
10914 | |
10915 | } |
10916 | |
10917 | status = CAPS_SUCCESS0; |
10918 | cleanup: |
10919 | return status; |
10920 | } |
10921 | |
10922 | int fea_getDesignEquationResponse(int numDesignEquationResponseTuple, |
10923 | capsTuple designEquationResponseTuple[], |
10924 | feaProblemStruct *feaProblem) { |
10925 | |
10926 | /*! \page feaDesignEquationResponse FEA Design Equation Responses |
10927 | * Structure for the design equation response tuple = ("DesignEquationResponse Name", "Value"). |
10928 | * "DesignEquationResponse Name" defines the reference name for the design equation response being specified. |
10929 | * This string will be used in the FEA input directly. The "Value" must be a JSON String dictionary |
10930 | * (see Section \ref jsonStringDesignEquationResponse). |
10931 | * \if NASTRAN |
10932 | * In Nastran the DesignEquationResponse Name will be the LABEL used in the DRESP2 input. |
10933 | * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less. |
10934 | * |
10935 | * - <c>DRESP2 ID LABEL EQID REGION ...</c> |
10936 | * \endif |
10937 | * |
10938 | */ |
10939 | int i, status; |
10940 | |
10941 | char *keyword; |
10942 | |
10943 | feaDesignEquationResponseStruct *equationResponse; |
10944 | |
10945 | // Ensure we are starting with no design equation responses |
10946 | if (feaProblem->feaEquationResponse != NULL((void*)0)) { |
10947 | for (i = 0; i < feaProblem->numEquationResponse; i++) { |
10948 | status = destroy_feaDesignEquationResponseStruct(&feaProblem->feaEquationResponse[i]); |
10949 | if (status != CAPS_SUCCESS0) return status; |
10950 | } |
10951 | EG_free(feaProblem->feaEquationResponse); |
10952 | } |
10953 | feaProblem->numEquationResponse = 0; |
10954 | feaProblem->feaEquationResponse = NULL((void*)0); |
10955 | |
10956 | printf("\nGetting Design Equation Responses.......\n"); |
10957 | |
10958 | feaProblem->numEquationResponse = numDesignEquationResponseTuple; |
10959 | printf("\tNumber of Design Equation Responses - %d\n", feaProblem->numEquationResponse); |
10960 | |
10961 | if (feaProblem->numEquationResponse > 0) { |
10962 | |
10963 | feaProblem->feaEquationResponse = EG_alloc( |
10964 | feaProblem->numEquationResponse * sizeof(feaDesignEquationResponseStruct)); |
10965 | if (feaProblem->feaEquationResponse == NULL((void*)0)) { |
10966 | return EGADS_MALLOC-4; |
10967 | } |
10968 | |
10969 | } else { |
10970 | printf("\tNumber of design equation responses in Analysis tuple is %d\n", |
10971 | feaProblem->numEquationResponse); |
10972 | return CAPS_NOTFOUND-303; |
10973 | } |
10974 | |
10975 | // for each analysis design equation response tuple |
10976 | for (i = 0; i < feaProblem->numEquationResponse; i++) { |
10977 | |
10978 | printf("\tDesign_Equation_Response name - %s\n", designEquationResponseTuple[i].name); |
10979 | |
10980 | equationResponse = &feaProblem->feaEquationResponse[i]; |
10981 | |
10982 | // initiate design response structure |
10983 | status = initiate_feaDesignEquationResponseStruct(equationResponse); |
10984 | if (status != CAPS_SUCCESS0) return status; |
10985 | |
10986 | // set name |
10987 | equationResponse->name = EG_strdup(designEquationResponseTuple[i].name); |
10988 | |
10989 | // set equation response ID |
10990 | equationResponse->equationResponseID = i+1; |
10991 | |
10992 | /*! \page feaDesignEquationResponse |
10993 | * \section jsonStringDesignEquationResponse JSON String Dictionary |
10994 | * |
10995 | * If "Value" is JSON string dictionary |
10996 | * \if NASTRAN |
10997 | * (eg. "Value" = {"equation": "EQ1", "constant": ["PI", "YM", "L"]}) |
10998 | * \endif |
10999 | * the following keywords ( = default values) may be used: |
11000 | * |
11001 | */ |
11002 | // make sure design response tuple value is json string |
11003 | if (!json_isDict(designEquationResponseTuple[i].value)) { |
11004 | PRINT_ERROR(fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "'Design_Equation_Response' tuple value must be a JSON dictionary" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11005, __func__); |
11005 | "'Design_Equation_Response' tuple value must be a JSON dictionary")fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "'Design_Equation_Response' tuple value must be a JSON dictionary" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11005, __func__);; |
11006 | return CAPS_BADVALUE-311; |
11007 | } |
11008 | |
11009 | /*! \page feaDesignEquationResponse |
11010 | * |
11011 | * \if NASTRAN |
11012 | * <ul> |
11013 | * <li> <B>equation</B> </li> <br> |
11014 | * The name of the equation referenced by this equation response. |
11015 | * </ul> |
11016 | * \endif |
11017 | */ |
11018 | keyword = "equation"; |
11019 | status = json_getString( |
11020 | designEquationResponseTuple[i].value, keyword, &equationResponse->equationName); |
11021 | if (status != CAPS_SUCCESS0) { |
11022 | PRINT_ERROR("Missing required entry \"equation\" "fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "Missing required entry \"equation\" " "in 'Design_Equation_Response' tuple value" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11023, __func__); |
11023 | "in 'Design_Equation_Response' tuple value")fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "Missing required entry \"equation\" " "in 'Design_Equation_Response' tuple value" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11023, __func__);; |
11024 | return status; |
11025 | } |
11026 | |
11027 | /*! \page feaDesignEquationResponse |
11028 | * |
11029 | * \if NASTRAN |
11030 | * <ul> |
11031 | * <li> <B>variable = "(no default)"</B> </li> <br> |
11032 | * Single or list of names of design variable equation parameters. |
11033 | * </ul> |
11034 | * \endif |
11035 | */ |
11036 | keyword = "variable"; |
11037 | status = json_getStringDynamicArray( |
11038 | designEquationResponseTuple[i].value, keyword, |
11039 | &equationResponse->numDesignVariable, &equationResponse->designVariableNameSet); |
11040 | if (status != CAPS_SUCCESS0) { |
11041 | // optional |
11042 | } |
11043 | |
11044 | /*! \page feaDesignEquationResponse |
11045 | * |
11046 | * \if NASTRAN |
11047 | * <ul> |
11048 | * <li> <B>constant = "(no default)"</B> </li> <br> |
11049 | * Single or list of names of table constant equation parameters. |
11050 | * </ul> |
11051 | * \endif |
11052 | */ |
11053 | keyword = "constant"; |
11054 | status = json_getStringDynamicArray( |
11055 | designEquationResponseTuple[i].value, keyword, |
11056 | &equationResponse->numConstant, &equationResponse->constantLabelSet); |
11057 | if (status != CAPS_SUCCESS0) { |
11058 | // optional |
11059 | } |
11060 | |
11061 | /*! \page feaDesignEquationResponse |
11062 | * |
11063 | * \if NASTRAN |
11064 | * <ul> |
11065 | * <li> <B>response = "(no default)"</B> </li> <br> |
11066 | * Single or list of names of design response equation parameters. |
11067 | * </ul> |
11068 | * \endif |
11069 | */ |
11070 | keyword = "response"; |
11071 | status = json_getStringDynamicArray( |
11072 | designEquationResponseTuple[i].value, keyword, |
11073 | &equationResponse->numResponse, &equationResponse->responseNameSet); |
11074 | if (status != CAPS_SUCCESS0) { |
11075 | // optional |
11076 | } |
11077 | |
11078 | /*! \page feaDesignEquationResponse |
11079 | * |
11080 | * \if NASTRAN |
11081 | * <ul> |
11082 | * <li> <B>equationResponse = "(no default)"</B> </li> <br> |
11083 | * Single or list of names of design equation response equation parameters. |
11084 | * </ul> |
11085 | * \endif |
11086 | */ |
11087 | keyword = "equationResponse"; |
11088 | status = json_getStringDynamicArray( |
11089 | designEquationResponseTuple[i].value, keyword, |
11090 | &equationResponse->numEquationResponse, &equationResponse->equationResponseNameSet); |
11091 | if (status != CAPS_SUCCESS0) { |
11092 | // optional |
11093 | } |
11094 | } |
11095 | |
11096 | return CAPS_SUCCESS0; |
11097 | } |
11098 | |
11099 | // Get the design optimization parameters from a capsTuple |
11100 | int fea_getDesignOptParam(int numParamTuple, |
11101 | capsTuple paramTuple[], |
11102 | feaProblemStruct *feaProblem) { |
11103 | |
11104 | /*! \page feaDesignOptParam FEA Design Optimization Parameters |
11105 | * Structure for the design optimization parameter tuple = ("DesignOptParam Name", "Value"). |
11106 | * "DesignOptParam Name" defines the reference name for the design optimization parameter being specified. |
11107 | * This string will be used in the FEA input directly. The "Value" is the value of the |
11108 | * design optimization parameter. |
11109 | * \if NASTRAN |
11110 | * In Nastran the DesignOptParam Name will be the PARAMi used in the DOPTPRM input. |
11111 | * For this reason the user should keep the length of this input to a minimum number of characters, ideally 7 or less. |
11112 | * |
11113 | * - <c>DOPTPRM PARAM1 VAL1 PARAM2 VAL2 PARAM3 VAL3 -etc- </c> |
11114 | * \endif |
11115 | * |
11116 | */ |
11117 | int i, status; |
11118 | |
11119 | int *paramInt = NULL((void*)0); |
11120 | double *paramDouble = NULL((void*)0); |
11121 | |
11122 | feaDesignOptParamStruct *table = &feaProblem->feaDesignOptParam; |
11123 | |
11124 | // Ensure we are starting with no params |
11125 | status = destroy_feaDesignOptParamStruct(table); |
11126 | if (status != CAPS_SUCCESS0) return status; |
11127 | |
11128 | printf("\nGetting Design Optimization Parameters.......\n"); |
11129 | |
11130 | table->numParam = numParamTuple; |
11131 | printf("\tNumber of Design Optimization Parameters - %d\n", table->numParam); |
11132 | |
11133 | if (table->numParam > 0) { |
11134 | |
11135 | table->paramLabel = EG_alloc(table->numParam * sizeof(char *)); |
11136 | if (table->paramLabel == NULL((void*)0)) { |
11137 | return EGADS_MALLOC-4; |
11138 | } |
11139 | |
11140 | table->paramValue = EG_alloc(table->numParam * sizeof(void *)); |
11141 | if (table->paramValue == NULL((void*)0)) { |
11142 | return EGADS_MALLOC-4; |
11143 | } |
11144 | |
11145 | table->paramType = EG_alloc(table->numParam * sizeof(int)); |
11146 | if (table->paramType == NULL((void*)0)) { |
11147 | return EGADS_MALLOC-4; |
11148 | } |
11149 | |
11150 | } else { |
11151 | printf("\tNumber of design optimization parameters in Analysis tuple is %d\n", |
11152 | table->numParam); |
11153 | return CAPS_NOTFOUND-303; |
11154 | } |
11155 | |
11156 | // for each analysis design optimization parameter tuple |
11157 | for (i = 0; i < table->numParam; i++) { |
11158 | |
11159 | printf("\tDesign_Opt_Param - %s: %s\n", |
11160 | paramTuple[i].name, paramTuple[i].value); |
11161 | |
11162 | // set param label |
11163 | // TODO: ensure label <= 8 chars |
11164 | table->paramLabel[i] = EG_strdup(paramTuple[i].name); |
11165 | |
11166 | // set param value |
11167 | |
11168 | // if param value is real |
11169 | if (strchr(paramTuple[i].value, '.') |
11170 | || strchr(paramTuple[i].value, 'e') |
11171 | || strchr(paramTuple[i].value, 'E')) { |
11172 | |
11173 | paramDouble = EG_alloc(sizeof(double)); |
11174 | if (paramDouble == NULL((void*)0)) return EGADS_MALLOC-4; |
11175 | |
11176 | status = string_toDouble(paramTuple[i].value, paramDouble); |
11177 | if (status != CAPS_SUCCESS0) { |
11178 | EG_free(paramDouble); |
11179 | return status; |
11180 | } |
11181 | |
11182 | table->paramType[i] = Double; |
11183 | table->paramValue[i] = (void*) paramDouble; |
11184 | } |
11185 | // else param is integer |
11186 | else { |
11187 | |
11188 | paramInt = EG_alloc(sizeof(int)); |
11189 | if (paramInt == NULL((void*)0)) return EGADS_MALLOC-4; |
11190 | |
11191 | status = string_toInteger(paramTuple[i].value, paramInt); |
11192 | if (status != CAPS_SUCCESS0) { |
11193 | EG_free(paramInt); |
11194 | return status; |
11195 | } |
11196 | |
11197 | table->paramType[i] = Integer; |
11198 | table->paramValue[i] = (void*) paramInt; |
11199 | } |
11200 | } |
11201 | |
11202 | return CAPS_SUCCESS0; |
11203 | } |
11204 | |
11205 | // Function used by fea_getAeroReference to determine which nodes are in reference group |
11206 | static int _matchReferenceNode(meshNodeStruct *node, void *referenceIndex) { |
11207 | |
11208 | feaMeshDataStruct *feaData; |
11209 | |
11210 | if (node->analysisType == MeshStructure) { |
11211 | |
11212 | feaData = (feaMeshDataStruct *) node->analysisData; |
11213 | |
11214 | if (feaData->referenceIndex == *((int *) referenceIndex)) { |
11215 | return (int) true1; |
11216 | } |
11217 | } |
11218 | return (int) false0; |
11219 | } |
11220 | |
11221 | // Get aero reference information from json dict |
11222 | int fea_getAeroReference(void *aimInfo, |
11223 | char *aeroRefInput, |
11224 | mapAttrToIndexStruct *attrMap, |
11225 | feaProblemStruct *feaProblem) { |
11226 | |
11227 | /*! \page feaAeroReference FEA Aerodynamic References |
11228 | * The aerodynamic reference input must be a JSON String dictionary |
11229 | * (see Section \ref jsonStringAeroReference). |
11230 | * |
11231 | */ |
11232 | int status, attrIndex = 0; |
11233 | |
11234 | char *keyword, *refNodeName = NULL((void*)0); |
11235 | |
11236 | int numNodes; |
11237 | meshNodeStruct **nodes = NULL((void*)0); |
11238 | |
11239 | printf("\nGetting Aero Reference Parameters.......\n"); |
11240 | |
11241 | /*! \page feaAeroReference |
11242 | * \section jsonStringAeroReference JSON String Dictionary |
11243 | * |
11244 | * The following keywords ( = default values) may be used: |
11245 | * |
11246 | */ |
11247 | // make sure input is json string |
11248 | if (!json_isDict(aeroRefInput)) { |
11249 | PRINT_ERROR(fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "'Aero_Reference' value must be a JSON dictionary" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11250, __func__); |
11250 | "'Aero_Reference' value must be a JSON dictionary")fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "'Aero_Reference' value must be a JSON dictionary" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11250, __func__);; |
11251 | return CAPS_BADVALUE-311; |
11252 | } |
11253 | |
11254 | /*! \page feaAeroReference |
11255 | * |
11256 | * \if ASTROS |
11257 | * <ul> |
11258 | * <li> <B>referenceNode</B> </li> <br> |
11259 | * Defines the reference <c>capsReference</c> for the node to be used for stability derivative calculations. |
11260 | * </ul> |
11261 | * \endif |
11262 | */ |
11263 | keyword = "referenceNode"; |
11264 | status = json_getString( |
11265 | aeroRefInput, keyword, &refNodeName); |
11266 | if (status == CAPS_SUCCESS0) { |
11267 | AIM_NOTNULL(refNodeName, aimInfo, status){ if (refNodeName == ((void*)0)) { status = -307; aim_status( aimInfo, status, "feaUtils.c", 11267, __func__, 1, "%s == NULL!" , "refNodeName"); goto cleanup; } }; |
11268 | |
11269 | // find node with capsReference == refNodeName |
11270 | |
11271 | status = get_mapAttrToIndexIndex(attrMap, refNodeName, &attrIndex); |
11272 | if (status != CAPS_SUCCESS0) { |
11273 | PRINT_ERROR("capsGroup name %s not found in attribute to index map", refNodeName)fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "capsGroup name %s not found in attribute to index map" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11273, __func__, refNodeName);; |
11274 | goto cleanup; |
11275 | } |
11276 | |
11277 | status = mesh_findNodes( |
11278 | &feaProblem->feaMesh, _matchReferenceNode, &attrIndex, &numNodes, &nodes); |
11279 | if (status == CAPS_NOTFOUND-303) { |
11280 | PRINT_ERROR("No node found with capsReference name %s", refNodeName)fprintf(stderr, "\n" "--------------------------------------------------------------------------------\n" "[ ERROR ]\n" "File: %s\n" "Line: %d\n" "Function: %s\n" "Reason: " "No node found with capsReference name %s" "\n" "--------------------------------------------------------------------------------\n" "\n", "feaUtils.c", 11280, __func__, refNodeName);; |
11281 | } |
11282 | if (status != CAPS_SUCCESS0) { |
11283 | goto cleanup; |
11284 | } |
11285 | |
11286 | // set refGridID to the nodeID |
11287 | feaProblem->feaAeroRef.refGridID = nodes[0]->nodeID; |
11288 | } |
11289 | |
11290 | status = CAPS_SUCCESS0; |
11291 | |
11292 | cleanup: |
11293 | |
11294 | AIM_FREE(refNodeName){ EG_free(refNodeName); refNodeName = ((void*)0); }; |
11295 | AIM_FREE(nodes){ EG_free(nodes); nodes = ((void*)0); }; |
11296 | |
11297 | return status; |
11298 | } |
11299 | |
11300 | // Find feaPropertyStructs with given names in feaProblem |
11301 | int fea_findPropertiesByNames(feaProblemStruct *feaProblem, |
11302 | int numPropertyNames, |
11303 | char **propertyNames, |
11304 | int *numProperties, |
11305 | feaPropertyStruct ***properties) { |
11306 | int i, status; |
11307 | |
11308 | int numFound; |
11309 | feaPropertyStruct **propertiesFound, *property; |
11310 | |
11311 | propertiesFound = EG_alloc(sizeof(feaPropertyStruct *) * numPropertyNames); |
11312 | |
11313 | numFound = 0; |
11314 | for (i = 0; i < feaProblem->numProperty; i++) { |
11315 | |
11316 | property = &feaProblem->feaProperty[i]; |
11317 | |
11318 | if (string_isInArray(property->name, numPropertyNames, propertyNames)) { |
11319 | |
11320 | propertiesFound[numFound++] = property; |
11321 | |
11322 | if (numFound == numPropertyNames) { |
11323 | // found all |
11324 | break; |
11325 | } |
11326 | } |
11327 | } |
11328 | |
11329 | if (numFound < numPropertyNames) { |
11330 | propertiesFound = EG_reall(propertiesFound, sizeof(feaPropertyStruct *) * numFound); |
11331 | status = CAPS_NOTFOUND-303; |
11332 | } |
11333 | else { |
11334 | status = CAPS_SUCCESS0; |
11335 | } |
11336 | |
11337 | *numProperties = numFound; |
11338 | *properties = propertiesFound; |
11339 | |
11340 | return status; |
11341 | } |
11342 | |
11343 | // Find feaMaterialStructs with given names in feaProblem |
11344 | int fea_findMaterialsByNames(feaProblemStruct *feaProblem, |
11345 | int numMaterialNames, |
11346 | char **materialNames, |
11347 | int *numMaterials, |
11348 | feaMaterialStruct ***materials) { |
11349 | int i, status; |
11350 | |
11351 | int numFound; |
11352 | feaMaterialStruct **materialsFound, *material; |
11353 | |
11354 | materialsFound = EG_alloc(sizeof(feaMaterialStruct *) * numMaterialNames); |
11355 | |
11356 | numFound = 0; |
11357 | for (i = 0; i < feaProblem->numMaterial; i++) { |
11358 | |
11359 | material = &feaProblem->feaMaterial[i]; |
11360 | |
11361 | if (string_isInArray(material->name, numMaterialNames, materialNames)) { |
11362 | |
11363 | materialsFound[numFound++] = material; |
11364 | |
11365 | if (numFound == numMaterialNames) { |
11366 | // found all |
11367 | break; |
11368 | } |
11369 | } |
11370 | } |
11371 | |
11372 | if (numFound < numMaterialNames) { |
11373 | materialsFound = EG_reall(materialsFound, sizeof(feaMaterialStruct *) * numFound); |
11374 | status = CAPS_NOTFOUND-303; |
11375 | } |
11376 | else { |
11377 | status = CAPS_SUCCESS0; |
11378 | } |
11379 | |
11380 | *numMaterials = numFound; |
11381 | *materials = materialsFound; |
11382 | |
11383 | return status; |
11384 | } |
11385 | |
11386 | // Find feaDesignVariableStructs with given names in feaProblem |
11387 | int fea_findDesignVariablesByNames(const feaProblemStruct *feaProblem, |
11388 | int numDesignVariableNames, |
11389 | char **designVariableNames, |
11390 | int *numDesignVariables, |
11391 | feaDesignVariableStruct ***designVariables) { |
11392 | int i, status; |
11393 | |
11394 | int numFound; |
11395 | feaDesignVariableStruct **designVariablesFound=NULL((void*)0), *designVariable=NULL((void*)0); |
11396 | |
11397 | designVariablesFound = (feaDesignVariableStruct **) EG_alloc(numDesignVariableNames * sizeof(feaDesignVariableStruct *)); |
11398 | |
11399 | numFound = 0; |
11400 | for (i = 0; i < feaProblem->numDesignVariable; i++) { |
11401 | |
11402 | designVariable = &feaProblem->feaDesignVariable[i]; |
11403 | |
11404 | if (string_isInArray(designVariable->name, numDesignVariableNames, designVariableNames)) { |
11405 | |
11406 | designVariablesFound[numFound++] = designVariable; |
11407 | |
11408 | if (numFound == numDesignVariableNames) { |
11409 | // found all |
11410 | break; |
11411 | } |
11412 | } |
11413 | } |
11414 | |
11415 | if (numFound < numDesignVariableNames) { |
11416 | designVariablesFound = EG_reall(designVariablesFound, numFound * sizeof(feaDesignVariableStruct *)); |
11417 | status = CAPS_NOTFOUND-303; |
11418 | } else { |
11419 | status = CAPS_SUCCESS0; |
11420 | } |
11421 | |
11422 | *numDesignVariables = numFound; |
11423 | *designVariables = designVariablesFound; |
11424 | |
11425 | return status; |
11426 | } |
11427 | |
11428 | // Find feaDesignResponseStructs with given names in feaProblem |
11429 | int fea_findDesignResponsesByNames(const feaProblemStruct *feaProblem, |
11430 | int numDesignResponseNames, |
11431 | char **designResponseNames, |
11432 | int *numDesignResponses, |
11433 | feaDesignResponseStruct ***designResponses) { |
11434 | int i, status; |
11435 | |
11436 | int numFound; |
11437 | feaDesignResponseStruct **designResponsesFound, *designResponse; |
11438 | |
11439 | designResponsesFound = EG_alloc(sizeof(feaDesignResponseStruct *) * numDesignResponseNames); |
11440 | |
11441 | numFound = 0; |
11442 | for (i = 0; i < feaProblem->numDesignResponse; i++) { |
11443 | |
11444 | designResponse = &feaProblem->feaDesignResponse[i]; |
11445 | |
11446 | if (string_isInArray(designResponse->name, numDesignResponseNames, designResponseNames)) { |
11447 | |
11448 | designResponsesFound[numFound++] = designResponse; |
11449 | |
11450 | if (numFound == numDesignResponseNames) { |
11451 | // found all |
11452 | break; |
11453 | } |
11454 | } |
11455 | } |
11456 | |
11457 | if (numFound < numDesignResponseNames) { |
11458 | designResponsesFound = EG_reall(designResponsesFound, sizeof(feaDesignResponseStruct *) * numFound); |
11459 | status = CAPS_NOTFOUND-303; |
11460 | } |
11461 | else { |
11462 | status = CAPS_SUCCESS0; |
11463 | } |
11464 | |
11465 | *numDesignResponses = numFound; |
11466 | *designResponses = designResponsesFound; |
11467 | |
11468 | return status; |
11469 | } |
11470 | |
11471 | // Find feaDesignEquationResponseStructs with given names in feaProblem |
11472 | int fea_findEquationResponsesByNames(const feaProblemStruct *feaProblem, |
11473 | int numEquationResponseNames, |
11474 | char **equationResponseNames, |
11475 | int *numEquationResponses, |
11476 | feaDesignEquationResponseStruct ***equationResponses) { |
11477 | int i, status; |
11478 | |
11479 | int numFound; |
11480 | feaDesignEquationResponseStruct **equationResponsesFound, *equationResponse; |
11481 | |
11482 | equationResponsesFound = EG_alloc(sizeof(feaDesignEquationResponseStruct *) * numEquationResponseNames); |
11483 | |
11484 | numFound = 0; |
11485 | for (i = 0; i < feaProblem->numEquationResponse; i++) { |
11486 | |
11487 | equationResponse = &feaProblem->feaEquationResponse[i]; |
11488 | |
11489 | if (string_isInArray(equationResponse->name, numEquationResponseNames, equationResponseNames)) { |
11490 | |
11491 | equationResponsesFound[numFound++] = equationResponse; |
11492 | |
11493 | if (numFound == numEquationResponseNames) { |
11494 | // found all |
11495 | break; |
11496 | } |
11497 | } |
11498 | } |
11499 | |
11500 | if (numFound < numEquationResponseNames) { |
11501 | equationResponsesFound = EG_reall(equationResponsesFound, sizeof(feaDesignEquationResponseStruct *) * numFound); |
11502 | status = CAPS_NOTFOUND-303; |
11503 | } |
11504 | else { |
11505 | status = CAPS_SUCCESS0; |
11506 | } |
11507 | |
11508 | *numEquationResponses = numFound; |
11509 | *equationResponses = equationResponsesFound; |
11510 | |
11511 | return status; |
11512 | } |
11513 | |
11514 | // Find feaDesignEquationStruct with given equationName in feaProblem |
11515 | int fea_findEquationByName(const feaProblemStruct *feaProblem, char *equationName, feaDesignEquationStruct **equation) { |
11516 | |
11517 | int i; |
11518 | |
11519 | for (i = 0; i < feaProblem->numEquation; i++) { |
11520 | |
11521 | if (strcmp(feaProblem->feaEquation[i].name, equationName) == 0) { |
11522 | *equation = &feaProblem->feaEquation[i]; |
11523 | return CAPS_SUCCESS0; |
11524 | } |
11525 | } |
11526 | |
11527 | return CAPS_NOTFOUND-303; |
11528 | } |
11529 | |
11530 | // Find vlmControlStruct with given controlSurfName in feaProble |
11531 | int fea_findControlSurfaceByName(const feaProblemStruct *feaProblem, char *controlSurfName, vlmControlStruct **controlSurf) { |
11532 | |
11533 | int isection, icontrol; |
11534 | |
11535 | vlmSurfaceStruct *surface; |
11536 | vlmSectionStruct *section; |
11537 | |
11538 | surface = &feaProblem->feaAero->vlmSurface; |
11539 | |
11540 | for (isection = 0; isection < surface->numSection; isection++) { |
11541 | |
11542 | section = &surface->vlmSection[isection]; |
11543 | |
11544 | for (icontrol = 0; icontrol < section->numControl; icontrol++) { |
11545 | |
11546 | if (strcmp(section->vlmControl[icontrol].name, controlSurfName) == 0) { |
11547 | *controlSurf = §ion->vlmControl[icontrol]; |
11548 | return CAPS_SUCCESS0; |
11549 | } |
11550 | } |
11551 | } |
11552 | |
11553 | return CAPS_NOTFOUND-303; |
11554 | } |
11555 | |
11556 | // Find feaDesignConstraintStruct with given constraintType in feaProblem |
11557 | int fea_findDesignConstraintByType(const feaProblemStruct *feaProblem, feaDesignConstraintTypeEnum constraintType, feaDesignConstraintStruct **designConstraint) { |
11558 | |
11559 | int i; |
11560 | |
11561 | for (i = 0; i < feaProblem->numDesignConstraint; i++) { |
11562 | |
11563 | if (feaProblem->feaDesignConstraint[i].designConstraintType == constraintType) { |
11564 | *designConstraint = &feaProblem->feaDesignConstraint[i]; |
11565 | return CAPS_SUCCESS0; |
11566 | } |
11567 | } |
11568 | |
11569 | return CAPS_NOTFOUND-303; |
11570 | } |
11571 | |
11572 | static inline int _feaDesignVariableRelation_linkDesignVariable(feaDesignVariableRelationStruct *relation, |
11573 | feaDesignVariableStruct *desvar, |
11574 | int desvarIndex) { |
11575 | if (relation->designVariableSet == NULL((void*)0)) { |
11576 | relation->designVariableSet = ( |
11577 | (feaDesignVariableStruct **) |
11578 | EG_alloc(sizeof(feaDesignVariableStruct *) * relation->numDesignVariable) |
11579 | ); |
11580 | } |
11581 | if (relation->designVariableSet == NULL((void*)0)) { |
11582 | return EGADS_MALLOC-4; |
11583 | } |
11584 | |
11585 | relation->designVariableSet[desvarIndex] = desvar; |
11586 | |
11587 | return CAPS_SUCCESS0; |
11588 | } |
11589 | |
11590 | static inline int _feaDesignVariable_linkDesignVariableRelation(feaDesignVariableStruct *desvar, |
11591 | feaDesignVariableRelationStruct *relation) { |
11592 | |
11593 | if (desvar->numRelation == 0) { |
11594 | desvar->relationSet = ( |
11595 | (feaDesignVariableRelationStruct **) |
11596 | EG_alloc(sizeof(feaDesignVariableRelationStruct *)) |
11597 | ); |
11598 | } |
11599 | else { |
11600 | desvar->relationSet = ( |
11601 | (feaDesignVariableRelationStruct **) |
11602 | EG_reall(desvar->relationSet, sizeof(feaDesignVariableRelationStruct *) * (desvar->numRelation + 1)) |
11603 | ); |
11604 | } |
11605 | if (desvar->relationSet == NULL((void*)0)) { |
11606 | return EGADS_MALLOC-4; |
11607 | } |
11608 | |
11609 | desvar->relationSet[desvar->numRelation] = relation; |
11610 | desvar->numRelation++; |
11611 | |
11612 | return CAPS_SUCCESS0; |
11613 | } |
11614 | |
11615 | // Populate the feaDesignVariable.relationSet and feaDesignVariableRelation.variableSet members |
11616 | // in all feaDesignVariables and feaDesignVariableRelations |
11617 | int fea_linkDesignVariablesAndRelations(const feaProblemStruct *feaProblem) { |
11618 | |
11619 | int status; |
11620 | int idvGlobal, idv, irel; |
11621 | |
11622 | char *desvarName = NULL((void*)0), **desvarNameSet = NULL((void*)0); |
11623 | |
11624 | feaDesignVariableStruct *desvar = NULL((void*)0); |
11625 | feaDesignVariableRelationStruct *desvarRelation = NULL((void*)0); |
11626 | |
11627 | for (irel = 0; irel < feaProblem->numDesignVariableRelation; irel++) { |
11628 | |
11629 | desvarRelation = &feaProblem->feaDesignVariableRelation[irel]; |
11630 | desvarNameSet = desvarRelation->designVariableNameSet; |
11631 | |
11632 | for (idv = 0; idv < desvarRelation->numDesignVariable; idv++) { |
11633 | |
11634 | desvarName = desvarNameSet[idv]; |
11635 | |
11636 | for (idvGlobal = 0; idvGlobal < feaProblem->numDesignVariable; idvGlobal++) { |
11637 | |
11638 | desvar = &feaProblem->feaDesignVariable[idvGlobal]; |
11639 | |
11640 | if (strcmp(desvar->name, desvarName) == 0) { |
11641 | |
11642 | status = _feaDesignVariableRelation_linkDesignVariable(desvarRelation, desvar, idv); |
11643 | if (status != CAPS_SUCCESS0) return status; |
11644 | |
11645 | status = _feaDesignVariable_linkDesignVariableRelation(desvar, desvarRelation); |
11646 | if (status != CAPS_SUCCESS0) return status; |
11647 | break; |
11648 | } |
11649 | } |
11650 | } |
11651 | } |
11652 | |
11653 | return CAPS_SUCCESS0; |
11654 | } |
11655 | |
11656 | // Initiate (0 out all values and NULL all pointers) of feaProblem in the feaProblemStruct structure format |
11657 | int initiate_feaProblemStruct(feaProblemStruct *feaProblem) { |
11658 | |
11659 | int status = 0; |
11660 | |
11661 | // Problem analysis |
11662 | feaProblem->numAnalysis = 0; |
11663 | feaProblem->feaAnalysis = NULL((void*)0); |
11664 | |
11665 | // Materials |
11666 | feaProblem->numMaterial = 0; |
11667 | feaProblem->feaMaterial = NULL((void*)0); |
11668 | |
11669 | // Properties |
11670 | feaProblem->numProperty = 0; |
11671 | feaProblem->feaProperty = NULL((void*)0); |
11672 | |
11673 | // Constraints |
11674 | feaProblem->numConstraint = 0; |
11675 | feaProblem->feaConstraint = NULL((void*)0); |
11676 | |
11677 | // Supports |
11678 | feaProblem->numSupport = 0; |
11679 | feaProblem->feaSupport = NULL((void*)0); |
11680 | |
11681 | // Loads |
11682 | feaProblem->numLoad = 0; |
11683 | feaProblem->feaLoad = NULL((void*)0); |
11684 | |
11685 | // Connections |
11686 | feaProblem->numConnect = 0; |
11687 | feaProblem->feaConnect = NULL((void*)0); |
11688 | |
11689 | // Mesh |
11690 | status = initiate_meshStruct(&feaProblem->feaMesh); |
11691 | if (status != CAPS_SUCCESS0) goto cleanup; |
11692 | |
11693 | // Output formatting |
11694 | status = initiate_feaFileFormatStruct(&feaProblem->feaFileFormat); |
11695 | if (status != CAPS_SUCCESS0) goto cleanup; |
11696 | |
11697 | // Optimization - Design Variables |
11698 | feaProblem->numDesignVariable = 0; |
11699 | feaProblem->feaDesignVariable = NULL((void*)0); |
11700 | |
11701 | // Optimization - Design Variable Relations |
11702 | feaProblem->numDesignVariableRelation = 0; |
11703 | feaProblem->feaDesignVariableRelation = NULL((void*)0); |
11704 | |
11705 | // Optimization - Design Constraints |
11706 | feaProblem->numDesignConstraint = 0; |
11707 | feaProblem->feaDesignConstraint = NULL((void*)0); |
11708 | |
11709 | // Optimization - Equations |
11710 | feaProblem->numEquation = 0; |
11711 | feaProblem->feaEquation = NULL((void*)0); |
11712 | |
11713 | // Optimization - Table Constants |
11714 | status = initiate_feaDesignTableStruct(&feaProblem->feaDesignTable); |
11715 | if (status != CAPS_SUCCESS0) goto cleanup; |
11716 | |
11717 | // Optimization - Design Optimization Parameters |
11718 | status = initiate_feaDesignOptParamStruct(&feaProblem->feaDesignOptParam); |
11719 | if (status != CAPS_SUCCESS0) goto cleanup; |
11720 | |
11721 | // Optimization - Design Sensitivity Response Quantities |
11722 | feaProblem->numDesignResponse = 0; |
11723 | feaProblem->feaDesignResponse = NULL((void*)0); |
11724 | |
11725 | // Optimization - Design Sensitivity Equation Response Quantities |
11726 | feaProblem->numEquationResponse = 0; |
11727 | feaProblem->feaEquationResponse = NULL((void*)0); |
11728 | |
11729 | // Coordinate Systems |
11730 | feaProblem->numCoordSystem = 0; |
11731 | feaProblem->feaCoordSystem = NULL((void*)0); |
11732 | |
11733 | // Aerodynamics |
11734 | feaProblem->numAero = 0; |
11735 | feaProblem->feaAero = NULL((void*)0); |
11736 | status = initiate_feaAeroRefStruct(&feaProblem->feaAeroRef); |
11737 | if (status != CAPS_SUCCESS0) goto cleanup; |
11738 | |
11739 | aim_initMeshRef(&feaProblem->meshRefObj, aimUnknownMeshType); |
11740 | feaProblem->meshRefIn = NULL((void*)0); |
11741 | |
11742 | status = CAPS_SUCCESS0; |
11743 | |
11744 | cleanup: |
11745 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during initiate_feaProblemStruct!\n", status); |
11746 | |
11747 | return status; |
11748 | } |
11749 | |
11750 | // Destroy (0 out all values and NULL all pointers) of feaProblem in the feaProblemStruct structure format |
11751 | int destroy_feaProblemStruct(feaProblemStruct *feaProblem) { |
11752 | |
11753 | int i; // Indexing |
11754 | |
11755 | int status = 0; // Status return |
11756 | |
11757 | // Analysis |
11758 | if (feaProblem->feaAnalysis != NULL((void*)0)) { |
11759 | for (i = 0; i < feaProblem->numAnalysis; i++) { |
11760 | status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]); |
11761 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaAnalysisStruct\n", status); |
11762 | } |
11763 | } |
11764 | AIM_FREE(feaProblem->feaAnalysis){ EG_free(feaProblem->feaAnalysis); feaProblem->feaAnalysis = ((void*)0); }; |
11765 | feaProblem->numAnalysis = 0; |
11766 | |
11767 | // Materials |
11768 | if (feaProblem->feaMaterial != NULL((void*)0)) { |
11769 | for (i = 0; i < feaProblem->numMaterial; i++) { |
11770 | status = destroy_feaMaterialStruct(&feaProblem->feaMaterial[i]); |
11771 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaMaterialStruct\n", status); |
11772 | } |
11773 | } |
11774 | AIM_FREE(feaProblem->feaMaterial){ EG_free(feaProblem->feaMaterial); feaProblem->feaMaterial = ((void*)0); }; |
11775 | feaProblem->numMaterial = 0; |
11776 | |
11777 | // Properties |
11778 | if (feaProblem->feaProperty != NULL((void*)0)) { |
11779 | for (i = 0; i < feaProblem->numProperty; i++) { |
11780 | status = destroy_feaPropertyStruct(&feaProblem->feaProperty[i]); |
11781 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaPropertyStruct\n", status); |
11782 | } |
11783 | } |
11784 | AIM_FREE(feaProblem->feaProperty){ EG_free(feaProblem->feaProperty); feaProblem->feaProperty = ((void*)0); }; |
11785 | feaProblem->numProperty = 0; |
11786 | |
11787 | // Constraints |
11788 | if (feaProblem->feaConstraint != NULL((void*)0)) { |
11789 | for (i = 0; i < feaProblem->numConstraint; i++) { |
11790 | status = destroy_feaConstraintStruct(&feaProblem->feaConstraint[i]); |
11791 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaConstraintStruct\n", status); |
11792 | } |
11793 | } |
11794 | AIM_FREE(feaProblem->feaConstraint){ EG_free(feaProblem->feaConstraint); feaProblem->feaConstraint = ((void*)0); }; |
11795 | feaProblem->numConstraint = 0; |
11796 | |
11797 | // Supports |
11798 | if (feaProblem->feaSupport != NULL((void*)0)) { |
11799 | for (i = 0; i < feaProblem->numSupport; i++) { |
11800 | status = destroy_feaSupportStruct(&feaProblem->feaSupport[i]); |
11801 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaSupportStruct\n", status); |
11802 | } |
11803 | } |
11804 | AIM_FREE(feaProblem->feaSupport){ EG_free(feaProblem->feaSupport); feaProblem->feaSupport = ((void*)0); }; |
11805 | feaProblem->numSupport = 0; |
11806 | |
11807 | // Loads |
11808 | if (feaProblem->feaLoad != NULL((void*)0)) { |
11809 | for (i = 0; i < feaProblem->numLoad; i++) { |
11810 | status = destroy_feaLoadStruct(&feaProblem->feaLoad[i]); |
11811 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaLoadStruct\n", status); |
11812 | } |
11813 | } |
11814 | AIM_FREE(feaProblem->feaLoad){ EG_free(feaProblem->feaLoad); feaProblem->feaLoad = ( (void*)0); }; |
11815 | feaProblem->numLoad = 0; |
11816 | |
11817 | // Connections |
11818 | if (feaProblem->feaConnect != NULL((void*)0)) { |
11819 | for (i = 0; i < feaProblem->numConnect; i++) { |
11820 | status = destroy_feaConnectionStruct(&feaProblem->feaConnect[i]); |
11821 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaConnectStruct\n", status); |
11822 | } |
11823 | } |
11824 | AIM_FREE(feaProblem->feaConnect){ EG_free(feaProblem->feaConnect); feaProblem->feaConnect = ((void*)0); }; |
11825 | feaProblem->numConnect = 0; |
11826 | |
11827 | // Mesh |
11828 | status = destroy_meshStruct(&feaProblem->feaMesh); |
11829 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_meshStruct\n", status); |
11830 | |
11831 | // Output formatting |
11832 | status = destroy_feaFileFormatStruct(&feaProblem->feaFileFormat); |
11833 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaFileFormatStruct\n", status); |
11834 | |
11835 | |
11836 | if (feaProblem->feaDesignVariable != NULL((void*)0)) { |
11837 | for (i = 0; i < feaProblem->numDesignVariable; i++) { |
11838 | status = destroy_feaDesignVariableStruct(&feaProblem->feaDesignVariable[i]); |
11839 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignVariableStruct\n", status); |
11840 | } |
11841 | } |
11842 | AIM_FREE(feaProblem->feaDesignVariable){ EG_free(feaProblem->feaDesignVariable); feaProblem->feaDesignVariable = ((void*)0); }; |
11843 | feaProblem->numDesignVariable = 0; |
11844 | |
11845 | // Optimization - design variable relations |
11846 | if (feaProblem->feaDesignVariableRelation != NULL((void*)0)) { |
11847 | for (i = 0; i < feaProblem->numDesignVariableRelation; i++) { |
11848 | status = destroy_feaDesignVariableRelationStruct(&feaProblem->feaDesignVariableRelation[i]); |
11849 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignVariableRelationStruct\n", status); |
11850 | } |
11851 | AIM_FREE(feaProblem->feaDesignVariableRelation){ EG_free(feaProblem->feaDesignVariableRelation); feaProblem ->feaDesignVariableRelation = ((void*)0); }; |
11852 | } |
11853 | feaProblem->numDesignVariableRelation = 0; |
11854 | |
11855 | // Optimization - design constraint |
11856 | if (feaProblem->feaDesignConstraint != NULL((void*)0)) { |
11857 | for (i = 0; i < feaProblem->numDesignConstraint; i++) { |
11858 | status = destroy_feaDesignConstraintStruct(&feaProblem->feaDesignConstraint[i]); |
11859 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignConstraintStruct\n", status); |
11860 | } |
11861 | } |
11862 | AIM_FREE(feaProblem->feaDesignConstraint){ EG_free(feaProblem->feaDesignConstraint); feaProblem-> feaDesignConstraint = ((void*)0); }; |
11863 | feaProblem->numDesignConstraint = 0; |
11864 | |
11865 | // Optimization - Equations |
11866 | if (feaProblem->feaEquation != NULL((void*)0)) { |
11867 | for (i = 0; i < feaProblem->numEquation; i++) { |
11868 | status = destroy_feaDesignEquationStruct(&feaProblem->feaEquation[i]); |
11869 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignEquationStruct\n", status); |
11870 | } |
11871 | AIM_FREE(feaProblem->feaEquation){ EG_free(feaProblem->feaEquation); feaProblem->feaEquation = ((void*)0); }; |
11872 | } |
11873 | feaProblem->numEquation = 0; |
11874 | |
11875 | // Optimization - Table Constants |
11876 | status = destroy_feaDesignTableStruct(&feaProblem->feaDesignTable); |
11877 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignTableStruct\n", status); |
11878 | |
11879 | // Optimization - Design Optimization Parameters |
11880 | status = destroy_feaDesignOptParamStruct(&feaProblem->feaDesignOptParam); |
11881 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignOptParamStruct\n", status); |
11882 | |
11883 | // Optimization - Design Sensitivity Response Quantities |
11884 | if (feaProblem->feaDesignResponse != NULL((void*)0)) { |
11885 | for (i = 0; i < feaProblem->numDesignResponse; i++) { |
11886 | status = destroy_feaDesignResponseStruct(&feaProblem->feaDesignResponse[i]); |
11887 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaDesignResponseStruct\n", status); |
11888 | } |
11889 | AIM_FREE(feaProblem->feaDesignResponse){ EG_free(feaProblem->feaDesignResponse); feaProblem->feaDesignResponse = ((void*)0); }; |
11890 | } |
11891 | feaProblem->numDesignResponse = 0; |
11892 | |
11893 | // Optimization - Design Sensitivity Equation Response Quantities |
11894 | if (feaProblem->feaEquationResponse != NULL((void*)0)) { |
11895 | for (i = 0; i < feaProblem->numEquationResponse; i++) { |
11896 | status = destroy_feaDesignEquationResponseStruct(&feaProblem->feaEquationResponse[i]); |
11897 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaEquationResponseStruct\n", status); |
11898 | } |
11899 | AIM_FREE(feaProblem->feaEquationResponse){ EG_free(feaProblem->feaEquationResponse); feaProblem-> feaEquationResponse = ((void*)0); }; |
11900 | } |
11901 | feaProblem->numEquationResponse = 0; |
11902 | |
11903 | // Coordinate Systems |
11904 | if (feaProblem->feaCoordSystem != NULL((void*)0)) { |
11905 | |
11906 | for (i = 0; i < feaProblem->numCoordSystem; i++) { |
11907 | status = destroy_feaCoordSystemStruct(&feaProblem->feaCoordSystem[i]); |
11908 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaCoordSystemStruct\n", status); |
11909 | } |
11910 | } |
11911 | AIM_FREE(feaProblem->feaCoordSystem){ EG_free(feaProblem->feaCoordSystem); feaProblem->feaCoordSystem = ((void*)0); }; |
11912 | feaProblem->numCoordSystem = 0; |
11913 | |
11914 | // Aerodynamics |
11915 | if (feaProblem->feaAero != NULL((void*)0)) { |
11916 | |
11917 | for (i = 0; i < feaProblem->numAero; i++) { |
11918 | status = destroy_feaAeroStruct(&feaProblem->feaAero[i]); |
11919 | if (status != CAPS_SUCCESS0) printf("Status %d during destroy_feaAeroStruct\n", status); |
11920 | } |
11921 | } |
11922 | AIM_FREE(feaProblem->feaAero){ EG_free(feaProblem->feaAero); feaProblem->feaAero = ( (void*)0); }; |
11923 | feaProblem->numAero = 0; |
11924 | |
11925 | (void) destroy_feaAeroRefStruct(&feaProblem->feaAeroRef); |
11926 | |
11927 | aim_freeMeshRef(&feaProblem->meshRefObj); |
11928 | feaProblem->meshRefIn = NULL((void*)0); |
11929 | |
11930 | return CAPS_SUCCESS0; |
11931 | } |
11932 | |
11933 | // Initiate (0 out all values and NULL all pointers) of feaFileFormat in the feaFileFormatStruct structure format |
11934 | int initiate_feaFileFormatStruct(feaFileFormatStruct *feaFileFormat) { |
11935 | |
11936 | feaFileFormat->fileType = SmallField; |
11937 | |
11938 | feaFileFormat->gridFileType = LargeField; |
11939 | |
11940 | return CAPS_SUCCESS0; |
11941 | } |
11942 | |
11943 | // Destroy (0 out all values and NULL all pointers) of feaFileFormat in the feaFileFormatStruct structure format |
11944 | int destroy_feaFileFormatStruct(feaFileFormatStruct *feaFileFormat) { |
11945 | |
11946 | feaFileFormat->fileType = SmallField; |
11947 | |
11948 | feaFileFormat->gridFileType = LargeField; |
11949 | |
11950 | return CAPS_SUCCESS0; |
11951 | } |
11952 | |
11953 | // Transfer external pressure from the discrObj into the feaLoad structure |
11954 | int fea_transferExternalPressure(void *aimInfo, const meshStruct *feaMesh, feaLoadStruct *feaLoad) { |
11955 | |
11956 | // [in/out] feaLoad |
11957 | // [in] feaMesh |
11958 | // [in] aimInfo |
11959 | |
11960 | int status; // Function status return |
11961 | |
11962 | int i, j, bIndex; // Indexing |
11963 | |
11964 | // Variables used in global node mapping |
11965 | int globalNodeID; |
11966 | int nodeIndex[4], transferIndex[4], elementID, elementIndex, elementCount; |
11967 | |
11968 | // Discrete data transfer variables |
11969 | capsDiscr *dataTransferDiscreteObj; |
11970 | char **transferName = NULL((void*)0); |
11971 | int numTransferName, transferNameIndex; |
11972 | enum capsdMethod dataTransferMethod; |
11973 | int numDataTransferPoint; |
11974 | int numDataTransferElement = 0, discElements; |
11975 | int dataTransferRank; |
11976 | double *dataTransferData; |
11977 | char *units; |
11978 | |
11979 | feaLoad->numElementID = 0; |
11980 | AIM_FREE(feaLoad->pressureMultiDistributeForce){ EG_free(feaLoad->pressureMultiDistributeForce); feaLoad-> pressureMultiDistributeForce = ((void*)0); }; |
11981 | AIM_FREE(feaLoad->elementIDSet){ EG_free(feaLoad->elementIDSet); feaLoad->elementIDSet = ((void*)0); }; |
11982 | |
11983 | //See if we have data transfer information |
11984 | status = aim_getBounds(aimInfo, &numTransferName, &transferName); |
11985 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 11985 , __func__, 0); goto cleanup; }; |
11986 | |
11987 | numDataTransferElement = 0; |
11988 | elementIndex = 0; |
11989 | elementCount = 0; |
11990 | |
11991 | for (transferNameIndex = 0; transferNameIndex < numTransferName; transferNameIndex++) { |
11992 | |
11993 | status = aim_getDiscr(aimInfo, transferName[transferNameIndex], &dataTransferDiscreteObj); |
11994 | if (status == CAPS_NOTFOUND-303) continue; |
11995 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 11995 , __func__, 0); goto cleanup; }; |
11996 | |
11997 | status = aim_getDataSet(dataTransferDiscreteObj, |
11998 | "Pressure", |
11999 | &dataTransferMethod, |
12000 | &numDataTransferPoint, |
12001 | &dataTransferRank, |
12002 | &dataTransferData, |
12003 | &units); |
12004 | if (status == CAPS_NOTFOUND-303) continue; // If no elements in this object skip to next transfer name |
12005 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12005 , __func__, 0); goto cleanup; }; |
12006 | |
12007 | printf("Extracting external pressure loads from data transfer....\n"); |
12008 | |
12009 | // If we do have data ready, how many elements there are? |
12010 | if (numDataTransferPoint == 1) { |
12011 | AIM_ERROR(aimInfo, "Pressures not initialized!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12011, __func__ , "Pressures not initialized!"); }; |
12012 | status = CAPS_BADINIT-338; |
12013 | goto cleanup; |
12014 | } |
12015 | |
12016 | if (dataTransferRank != 1) { |
12017 | AIM_ERROR(aimInfo, "Pressure transfer data found however rank is %d not 1!!!!", dataTransferRank){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12017, __func__ , "Pressure transfer data found however rank is %d not 1!!!!" , dataTransferRank); }; |
12018 | status = CAPS_BADRANK-301; |
12019 | goto cleanup; |
12020 | } |
12021 | |
12022 | discElements = 0; |
12023 | for (bIndex = 0; bIndex < dataTransferDiscreteObj->nBodys; bIndex++) |
12024 | discElements += dataTransferDiscreteObj->bodys[bIndex].nElems; |
12025 | |
12026 | numDataTransferElement += discElements; |
12027 | printf("\tTransferName = %s\n", transferName[transferNameIndex]); |
12028 | printf("\tNumber of Elements = %d (total = %d)\n", discElements, numDataTransferElement); |
12029 | |
12030 | // allocate arrays |
12031 | AIM_REALL(feaLoad->elementIDSet, numDataTransferElement, int, aimInfo, status){ size_t memorysize = numDataTransferElement; feaLoad->elementIDSet = (int *) EG_reall(feaLoad->elementIDSet, memorysize*sizeof (int)); if (feaLoad->elementIDSet == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 12031, __func__ , 3, "AIM_REALL: %s size %zu type %s", "feaLoad->elementIDSet" , memorysize, "int"); goto cleanup; } }; |
12032 | AIM_REALL(feaLoad->pressureMultiDistributeForce, 4*numDataTransferElement, double, aimInfo, status){ size_t memorysize = 4*numDataTransferElement; feaLoad->pressureMultiDistributeForce = (double *) EG_reall(feaLoad->pressureMultiDistributeForce , memorysize*sizeof(double)); if (feaLoad->pressureMultiDistributeForce == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 12032, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->pressureMultiDistributeForce" , memorysize, "double"); goto cleanup; } }; |
12033 | |
12034 | //Now lets loop through our ctria3 mesh and get the node indexes for each element |
12035 | for (i = 0; i < feaMesh->numElement; i++) { |
12036 | |
12037 | if (feaMesh->element[i].elementType != Triangle) continue; |
12038 | |
12039 | elementID = feaMesh->element[i].elementID; |
12040 | //printf("Element Id = %d\n", elementID); |
12041 | |
12042 | // elementID is 1 bias |
12043 | nodeIndex[0] = feaMesh->element[i].connectivity[0]; |
12044 | nodeIndex[1] = feaMesh->element[i].connectivity[1]; |
12045 | nodeIndex[2] = feaMesh->element[i].connectivity[2]; |
12046 | |
12047 | //printf("Node Index = %d %d %d\n", nodeIndex[0], nodeIndex[1], nodeIndex[2]); |
12048 | |
12049 | transferIndex[0] = -1; |
12050 | transferIndex[1] = -1; |
12051 | transferIndex[2] = -1; |
12052 | transferIndex[3] = -1; |
12053 | |
12054 | // Loop through the nodeMap of the data set getting nodeIDs trying |
12055 | // to match the nodes in the element |
12056 | for (j = 0; j < numDataTransferPoint; j++) { |
12057 | |
12058 | bIndex = dataTransferDiscreteObj->tessGlobal[2*j ]; |
12059 | globalNodeID = dataTransferDiscreteObj->tessGlobal[2*j+1] + |
12060 | dataTransferDiscreteObj->bodys[bIndex-1].globalOffset; |
12061 | |
12062 | if (nodeIndex[0] == globalNodeID) transferIndex[0] = j; |
12063 | if (nodeIndex[1] == globalNodeID) transferIndex[1] = j; |
12064 | if (nodeIndex[2] == globalNodeID) transferIndex[2] = j; |
12065 | |
12066 | // If the nodes completely match the nodes on the element - break |
12067 | if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && transferIndex[2] >= 0) { |
12068 | break; |
12069 | } |
12070 | } |
12071 | |
12072 | // If all the nodeIndexes match the transferIndex the element is in the data set |
12073 | // so transfer the pressure forces |
12074 | if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && transferIndex[2] >= 0) { |
12075 | |
12076 | feaLoad->elementIDSet[elementIndex] = elementID; |
12077 | |
12078 | feaLoad->pressureMultiDistributeForce[4*elementIndex+0] = dataTransferData[transferIndex[0]]; |
12079 | feaLoad->pressureMultiDistributeForce[4*elementIndex+1] = dataTransferData[transferIndex[1]]; |
12080 | feaLoad->pressureMultiDistributeForce[4*elementIndex+2] = dataTransferData[transferIndex[2]]; |
12081 | feaLoad->pressureMultiDistributeForce[4*elementIndex+3] = 0.0; |
12082 | |
12083 | elementIndex += 1; |
12084 | elementCount += 1; |
12085 | feaLoad->numElementID += 1; |
12086 | |
12087 | } |
12088 | } |
12089 | |
12090 | //Now lets loop through our cquad4 mesh and get the node indexes for each element |
12091 | for (i = 0; i < feaMesh->numElement; i++) { |
12092 | |
12093 | if (feaMesh->element[i].elementType != Quadrilateral) continue; |
12094 | |
12095 | elementID = feaMesh->element[i].elementID; |
12096 | |
12097 | // elementID is 1 bias |
12098 | nodeIndex[0] = feaMesh->element[i].connectivity[0]; |
12099 | nodeIndex[1] = feaMesh->element[i].connectivity[1]; |
12100 | nodeIndex[2] = feaMesh->element[i].connectivity[2]; |
12101 | nodeIndex[3] = feaMesh->element[i].connectivity[3]; |
12102 | |
12103 | transferIndex[0] = -1; |
12104 | transferIndex[1] = -1; |
12105 | transferIndex[2] = -1; |
12106 | transferIndex[3] = -1; |
12107 | |
12108 | // Loop through the nodeMap of the data set getting nodeIDs trying |
12109 | // to match the nodes in the element |
12110 | for (j = 0; j < numDataTransferPoint; j++) { |
12111 | |
12112 | bIndex = dataTransferDiscreteObj->tessGlobal[2*j ]; |
12113 | globalNodeID = dataTransferDiscreteObj->tessGlobal[2*j+1] + |
12114 | dataTransferDiscreteObj->bodys[bIndex-1].globalOffset; |
12115 | |
12116 | if (nodeIndex[0] == globalNodeID) transferIndex[0] = j; |
12117 | if (nodeIndex[1] == globalNodeID) transferIndex[1] = j; |
12118 | if (nodeIndex[2] == globalNodeID) transferIndex[2] = j; |
12119 | if (nodeIndex[3] == globalNodeID) transferIndex[3] = j; |
12120 | |
12121 | // If the nodes completely match the nodes on the element - break |
12122 | if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && |
12123 | transferIndex[2] >= 0 && transferIndex[3] >= 0) { |
12124 | break; |
12125 | } |
12126 | } |
12127 | |
12128 | // If all the nodeIndexes match the transferIndex the element is in the data set |
12129 | // so transfer the pressure forces |
12130 | if (transferIndex[0] >= 0 && transferIndex[1] >= 0 && |
12131 | transferIndex[2] >= 0 && transferIndex[3] >= 0) { |
12132 | |
12133 | feaLoad->elementIDSet[elementIndex] = elementID; |
12134 | |
12135 | feaLoad->pressureMultiDistributeForce[4*elementIndex+0] = dataTransferData[transferIndex[0]]; |
12136 | feaLoad->pressureMultiDistributeForce[4*elementIndex+1] = dataTransferData[transferIndex[1]]; |
12137 | feaLoad->pressureMultiDistributeForce[4*elementIndex+2] = dataTransferData[transferIndex[2]]; |
12138 | feaLoad->pressureMultiDistributeForce[4*elementIndex+3] = dataTransferData[transferIndex[3]]; |
12139 | |
12140 | elementIndex += 1; |
12141 | elementCount += 1; |
12142 | feaLoad->numElementID += 1; |
12143 | } |
12144 | } |
12145 | |
12146 | if (elementCount != numDataTransferElement) { |
12147 | AIM_ERROR(aimInfo, "Element transfer mismatch: number of elements found = %d, number"{ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12148, __func__ , "Element transfer mismatch: number of elements found = %d, number" " of elements in transfer data set %d", elementCount, numDataTransferElement ); } |
12148 | " of elements in transfer data set %d", elementCount, numDataTransferElement){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12148, __func__ , "Element transfer mismatch: number of elements found = %d, number" " of elements in transfer data set %d", elementCount, numDataTransferElement ); }; |
12149 | AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); }; |
12150 | |
12151 | status = CAPS_MISMATCH-324; |
12152 | goto cleanup; |
12153 | } |
12154 | |
12155 | // Resize |
12156 | if (feaLoad->numElementID != numDataTransferElement) { |
12157 | AIM_REALL(feaLoad->pressureMultiDistributeForce, 4*feaLoad->numElementID, double, aimInfo, status){ size_t memorysize = 4*feaLoad->numElementID; feaLoad-> pressureMultiDistributeForce = (double *) EG_reall(feaLoad-> pressureMultiDistributeForce, memorysize*sizeof(double)); if ( feaLoad->pressureMultiDistributeForce == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 12157, __func__ , 3, "AIM_REALL: %s size %zu type %s", "feaLoad->pressureMultiDistributeForce" , memorysize, "double"); goto cleanup; } }; |
12158 | } |
12159 | |
12160 | } // End data transfer name loop |
12161 | |
12162 | |
12163 | status = CAPS_SUCCESS0; |
12164 | |
12165 | cleanup: |
12166 | |
12167 | AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); }; |
12168 | |
12169 | return status; |
12170 | } |
12171 | |
12172 | // Transfer external temperature from the discrObj into the feaLoad structure |
12173 | int fea_transferExternalTemperature(void *aimInfo, feaLoadStruct *feaLoad) { |
12174 | |
12175 | // [in/out] feaLoad |
12176 | // [in] aimInfo |
12177 | |
12178 | int status; // Function status return |
12179 | |
12180 | int i, bIndex; // Indexing |
12181 | |
12182 | // Variables used in global node mapping |
12183 | int globalNodeID; |
12184 | |
12185 | // Discrete data transfer variables |
12186 | capsDiscr *dataTransferDiscreteObj; |
12187 | char **transferName = NULL((void*)0); |
12188 | int numTransferName, transferNameIndex; |
12189 | enum capsdMethod dataTransferMethod; |
12190 | int numDataTransferPoint; |
12191 | int dataTransferRank; |
12192 | double *dataTransferData; |
12193 | char *units; |
12194 | |
12195 | feaLoad->numGridID = 0; |
12196 | AIM_FREE(feaLoad->temperatureMultiDistribute){ EG_free(feaLoad->temperatureMultiDistribute); feaLoad-> temperatureMultiDistribute = ((void*)0); }; |
12197 | AIM_FREE(feaLoad->gridIDSet){ EG_free(feaLoad->gridIDSet); feaLoad->gridIDSet = ((void *)0); }; |
12198 | |
12199 | //See if we have data transfer information |
12200 | status = aim_getBounds(aimInfo, &numTransferName, &transferName); |
12201 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12201 , __func__, 0); goto cleanup; }; |
12202 | |
12203 | for (transferNameIndex = 0; transferNameIndex < numTransferName; transferNameIndex++) { |
12204 | |
12205 | status = aim_getDiscr(aimInfo, transferName[transferNameIndex], &dataTransferDiscreteObj); |
12206 | if (status == CAPS_NOTFOUND-303) continue; |
12207 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12207 , __func__, 0); goto cleanup; }; |
12208 | |
12209 | status = aim_getDataSet(dataTransferDiscreteObj, |
12210 | "Temperature", |
12211 | &dataTransferMethod, |
12212 | &numDataTransferPoint, |
12213 | &dataTransferRank, |
12214 | &dataTransferData, |
12215 | &units); |
12216 | if (status == CAPS_NOTFOUND-303) continue; // If no elements in this object skip to next transfer name |
12217 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "feaUtils.c", 12217 , __func__, 0); goto cleanup; }; |
12218 | |
12219 | printf("Extracting external thermal loads from data transfer....\n"); |
12220 | |
12221 | // If we do have data ready, how many elements there are? |
12222 | if (numDataTransferPoint == 1) { |
12223 | AIM_ERROR(aimInfo, "Temperature not initialized!"){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12223, __func__ , "Temperature not initialized!"); }; |
12224 | status = CAPS_BADINIT-338; |
12225 | goto cleanup; |
12226 | } |
12227 | |
12228 | if (dataTransferRank != 1) { |
12229 | AIM_ERROR(aimInfo, "Temperature transfer data found however rank is %d not 1!!!!", dataTransferRank){ aim_message(aimInfo, CERROR, 0 , "feaUtils.c", 12229, __func__ , "Temperature transfer data found however rank is %d not 1!!!!" , dataTransferRank); }; |
12230 | status = CAPS_BADRANK-301; |
12231 | goto cleanup; |
12232 | } |
12233 | |
12234 | printf("\tTransferName = %s\n", transferName[transferNameIndex]); |
12235 | printf("\tNumber of Nodes = %d (total = %d)\n", numDataTransferPoint, feaLoad->numGridID+numDataTransferPoint); |
12236 | |
12237 | // allocate arrays |
12238 | AIM_REALL(feaLoad->gridIDSet, feaLoad->numGridID+numDataTransferPoint, int, aimInfo, status){ size_t memorysize = feaLoad->numGridID+numDataTransferPoint ; feaLoad->gridIDSet = (int *) EG_reall(feaLoad->gridIDSet , memorysize*sizeof(int)); if (feaLoad->gridIDSet == ((void *)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c" , 12238, __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->gridIDSet" , memorysize, "int"); goto cleanup; } }; |
12239 | AIM_REALL(feaLoad->temperatureMultiDistribute, feaLoad->numGridID+numDataTransferPoint, double, aimInfo, status){ size_t memorysize = feaLoad->numGridID+numDataTransferPoint ; feaLoad->temperatureMultiDistribute = (double *) EG_reall (feaLoad->temperatureMultiDistribute, memorysize*sizeof(double )); if (feaLoad->temperatureMultiDistribute == ((void*)0)) { status = -4; aim_status(aimInfo, status, "feaUtils.c", 12239 , __func__, 3, "AIM_REALL: %s size %zu type %s", "feaLoad->temperatureMultiDistribute" , memorysize, "double"); goto cleanup; } }; |
12240 | |
12241 | // Loop through the nodeMap of the data set getting nodeIDs trying |
12242 | // to match the nodes in the element |
12243 | for (i = 0; i < numDataTransferPoint; i++) { |
12244 | |
12245 | bIndex = dataTransferDiscreteObj->tessGlobal[2*i ]; |
12246 | globalNodeID = dataTransferDiscreteObj->tessGlobal[2*i+1] + |
12247 | dataTransferDiscreteObj->bodys[bIndex-1].globalOffset; |
12248 | |
12249 | feaLoad->gridIDSet[feaLoad->numGridID+i] = globalNodeID; |
12250 | feaLoad->temperatureMultiDistribute[feaLoad->numGridID+i] = dataTransferData[i]; |
12251 | } |
12252 | |
12253 | feaLoad->numGridID += numDataTransferPoint; |
12254 | |
12255 | } // End data transfer name loop |
12256 | |
12257 | status = CAPS_SUCCESS0; |
12258 | |
12259 | cleanup: |
12260 | |
12261 | AIM_FREE(transferName){ EG_free(transferName); transferName = ((void*)0); }; |
12262 | |
12263 | return status; |
12264 | } |
12265 | |
12266 | // Retrieve aerodynamic reference quantities from bodies |
12267 | int fea_retrieveAeroRef(int numBody, ego *bodies, feaAeroRefStruct *feaAeroRef) { |
12268 | |
12269 | int status; // Function return status |
12270 | int body; |
12271 | |
12272 | // EGADS return values |
12273 | int atype, alen; |
12274 | const int *ints; |
12275 | const char *string; |
12276 | const double *reals; |
12277 | |
12278 | // Get reference quantities from the bodies |
12279 | for (body = 0; body < numBody; body++) { |
12280 | |
12281 | status = EG_attributeRet(bodies[body], "capsReferenceArea", &atype, &alen, &ints, &reals, &string); |
12282 | if (status == EGADS_SUCCESS0 && atype == Double) { |
12283 | |
12284 | feaAeroRef->refArea = (double) reals[0]; |
12285 | } |
12286 | |
12287 | status = EG_attributeRet(bodies[body], "capsReferenceChord", &atype, &alen, &ints, &reals, &string); |
12288 | if (status == EGADS_SUCCESS0 && atype == Double){ |
12289 | |
12290 | feaAeroRef->refChord = (double) reals[0]; |
12291 | } |
12292 | |
12293 | status = EG_attributeRet(bodies[body], "capsReferenceSpan", &atype, &alen, &ints, &reals, &string); |
12294 | if (status == EGADS_SUCCESS0 && atype == Double) { |
12295 | |
12296 | feaAeroRef->refSpan = (double) reals[0]; |
12297 | } |
12298 | |
12299 | /* |
12300 | status = EG_attributeRet(bodies[body], "capsReferenceX", &atype, &alen, &ints, &reals, &string); |
12301 | if (status == EGADS_SUCCESS && atype == Double) { |
12302 | XX = (double) reals[0]; |
12303 | } |
12304 | |
12305 | status = EG_attributeRet(bodies[body], "capsReferenceY", &atype, &alen, &ints, &reals, &string); |
12306 | if (status == EGADS_SUCCESS && atype == Double) { |
12307 | XX = (double) reals[0]; |
12308 | } |
12309 | |
12310 | status = EG_attributeRet(bodies[body], "capsReferenceZ", &atype, &alen, &ints, &reals, &string); |
12311 | if (status == EGADS_SUCCESS && atype == Double) { |
12312 | XX = (double) reals[0]; |
12313 | } |
12314 | */ |
12315 | } |
12316 | |
12317 | return CAPS_SUCCESS0; |
12318 | } |
12319 | |
12320 | |
12321 | // Assign element "subtypes" based on properties set |
12322 | int fea_assignElementSubType(int numProperty, feaPropertyStruct *feaProperty, meshStruct *feaMesh) |
12323 | { |
12324 | int propertyIndex, i ; |
12325 | |
12326 | feaMeshDataStruct *feaData; |
12327 | |
12328 | if (numProperty > 0 && feaProperty == NULL((void*)0)) return CAPS_NULLVALUE-307; |
12329 | if (feaMesh == NULL((void*)0)) return CAPS_NULLVALUE-307; |
12330 | |
12331 | printf("Updating mesh element types based on properties input\n"); |
12332 | |
12333 | for (propertyIndex = 0; propertyIndex < numProperty; propertyIndex++ ) { |
12334 | |
12335 | // Types that don't need subtypes - setting this correctly requires knowledge of what mesh_writeNastran |
12336 | // writes by default for each mesh element type |
12337 | if (feaProperty[propertyIndex].propertyType == Rod || |
12338 | //feaProperty[propertyIndex].propertyType == Shell || |
12339 | //feaProperty[propertyIndex].propertyType == Composite || |
12340 | feaProperty[propertyIndex].propertyType == Solid) continue; |
12341 | |
12342 | for (i = 0; i < feaMesh->numElement; i++) { |
12343 | |
12344 | // What if this is a volume mesh we inherited ? |
12345 | if (feaMesh->element[i].analysisType != MeshStructure) { |
12346 | printf("Developer error: Analysis type not set to MeshStructure for element %d\n", feaMesh->element[i].elementID); |
12347 | return CAPS_BADVALUE-311; |
12348 | } |
12349 | |
12350 | // Matching proptery id |
12351 | if (feaMesh->element[i].analysisData != NULL((void*)0)) { |
12352 | feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData; |
12353 | |
12354 | if (feaData->propertyID != feaProperty[propertyIndex].propertyID) continue; |
12355 | |
12356 | } else { |
12357 | printf("Developer error: No 'feaData' set on element %d\n", feaMesh->element[i].elementID); |
12358 | return CAPS_BADVALUE-311; |
12359 | |
12360 | } |
12361 | |
12362 | // if (feaMesh->element[i].markerID != feaProperty[propertyIndex].propertyID) continue; |
12363 | // |
12364 | // feaData = (feaMeshDataStruct *) feaMesh->element[i].analysisData; |
12365 | // if (feaData->propertyID != feaProperty[propertyIndex].propertyID) { |
12366 | // printf("Developer error: Property ID mismatch between element \"markerID\" (%d) and feaData \"propertyID\" (%d) for element %d\n", |
12367 | // feaData->propertyID, feaProperty[propertyIndex].propertyID, feaMesh->element[i].elementID); |
12368 | // return CAPS_BADVALUE; |
12369 | // } |
12370 | |
12371 | |
12372 | if (feaProperty[propertyIndex].propertyType == ConcentratedMass && |
12373 | feaMesh->element[i].elementType == Node) { |
12374 | |
12375 | feaData->elementSubType = ConcentratedMassElement; |
12376 | } |
12377 | |
12378 | if (feaProperty[propertyIndex].propertyType == Bar && |
12379 | feaMesh->element[i].elementType == Line) { |
12380 | |
12381 | feaData->elementSubType = BarElement; |
12382 | } |
12383 | |
12384 | if (feaProperty[propertyIndex].propertyType == Beam && |
12385 | feaMesh->element[i].elementType == Line) { |
12386 | |
12387 | feaData->elementSubType = BeamElement; |
12388 | } |
12389 | |
12390 | if (feaProperty[propertyIndex].propertyType == Shear && |
12391 | feaMesh->element[i].elementType == Quadrilateral){ |
12392 | |
12393 | feaData->elementSubType = ShearElement; |
12394 | } |
12395 | |
12396 | if (feaProperty[propertyIndex].propertyType == Membrane && |
12397 | feaMesh->element[i].elementType == Quadrilateral){ |
12398 | |
12399 | feaData->elementSubType = MembraneElement; |
12400 | } |
12401 | |
12402 | // Only need to set these if the zOffset is needed based on mesh_writeNASTRAN |
12403 | if ( ( feaProperty[propertyIndex].propertyType == Shell || feaProperty[propertyIndex].propertyType == Composite ) && |
12404 | feaProperty[propertyIndex].zOffsetRel != 0.0 && |
12405 | ( feaMesh->element[i].elementType == Quadrilateral || |
12406 | feaMesh->element[i].elementType == Triangle || |
12407 | feaMesh->element[i].elementType == Triangle_6 || |
12408 | feaMesh->element[i].elementType == Quadrilateral_8)) { |
12409 | |
12410 | feaData->elementSubType = ShellElement; |
12411 | } |
12412 | } |
12413 | } |
12414 | |
12415 | return CAPS_SUCCESS0; |
12416 | } |
12417 | |
12418 | // Create connections for gluing - Connections are appended |
12419 | int fea_glueMesh(void *aimInfo, |
12420 | meshStruct *mesh, |
12421 | int connectionID, |
12422 | /*@unused@*/ int connectionType, |
12423 | int dofDependent, |
12424 | char *slaveName, |
12425 | int numMasterName, |
12426 | char *masterName[], |
12427 | mapAttrToIndexStruct *attrMap, |
12428 | int maxNumMaster, |
12429 | double searchRadius, |
12430 | int *numConnect, |
12431 | feaConnectionStruct *feaConnect[]) { |
12432 | |
12433 | // Input parameters |
12434 | //double exactTol=1E-9; |
12435 | //int weigthing = 1; // 1=linear |
12436 | |
12437 | int masterWeight = 1; |
12438 | int masterComponent = 123; |
12439 | |
12440 | int status; |
12441 | int i, masterIndex, slaveIndex, distIndex, attrIndex; |
12442 | |
12443 | int numMaster; |
12444 | |
12445 | int *glueConn=NULL((void*)0); |
12446 | double *glueDist=NULL((void*)0); |
12447 | |
12448 | double dist, maxDist; |
12449 | |
12450 | feaMeshDataStruct *feaData, *feaDataMaster; |
12451 | |
12452 | // int numConnect; |
12453 | // feaConnectionStruct *feaConnect; |
12454 | |
12455 | |
12456 | // maps from nodeID to mesh->node index |
12457 | // mesh_nodeID2Array(nasMesh, &n2a); |
12458 | |
12459 | printf("\tCreating glue connections\n"); |
12460 | |
12461 | if (searchRadius <=0) { |
12462 | printf("\tSearch radius must be greater than 0 when gluing, current value = %g\n", searchRadius); |
12463 | status = CAPS_BADVALUE-311; |
12464 | goto cleanup; |
12465 | } |
12466 | |
12467 | status = array_allocIntegerVector(maxNumMaster, -1, &glueConn); |
12468 | if (status != CAPS_SUCCESS0) goto cleanup; |
12469 | |
12470 | status = array_allocDoubleVector(maxNumMaster, 1E9, &glueDist); |
12471 | if (status != CAPS_SUCCESS0) goto cleanup; |
12472 | |
12473 | for (slaveIndex = 0; slaveIndex < mesh->numNode; slaveIndex++) { |
12474 | |
12475 | feaData = (feaMeshDataStruct *) mesh->node[slaveIndex].analysisData; |
12476 | |
12477 | status = get_mapAttrToIndexIndex(attrMap, (const char *) slaveName, &attrIndex); |
12478 | if (status == CAPS_NOTFOUND-303) { |
12479 | printf("\tName %s not found in attribute map of capsConnect!!!!\n", slaveName); |
12480 | continue; |
12481 | } else if (status != CAPS_SUCCESS0) return status; |
12482 | |
12483 | if (feaData->connectIndex != attrIndex) continue; |
12484 | |
12485 | // We have a slave at this point |
12486 | |
12487 | // printf("Slave - node ID %d\n", mesh->node[slaveIndex].nodeID); |
12488 | |
12489 | status = array_setDoubleVectorValue(maxNumMaster, 1E9, &glueDist); |
12490 | if (status != CAPS_SUCCESS0) goto cleanup; |
12491 | |
12492 | status = array_setIntegerVectorValue(maxNumMaster, -1, &glueConn); |
12493 | if (status != CAPS_SUCCESS0) goto cleanup; |
12494 | |
12495 | for (masterIndex = 0; masterIndex < mesh->numNode; masterIndex++) { |
12496 | |
12497 | if (slaveIndex == masterIndex) continue; |
12498 | |
12499 | feaDataMaster = (feaMeshDataStruct *) mesh->node[masterIndex].analysisData; |
12500 | |
12501 | for (i = 0; i < numMasterName; i++) { |
12502 | status = get_mapAttrToIndexIndex(attrMap, (const char *) masterName[i], &attrIndex); |
12503 | if (status == CAPS_NOTFOUND-303) { |
12504 | printf("\tName %s not found in attribute map of capsConnect!!!!\n", masterName[i]); |
12505 | continue; |
12506 | } else if (status != CAPS_SUCCESS0) return status; |
12507 | |
12508 | if (feaDataMaster->connectIndex != attrIndex) continue; |
12509 | |
12510 | break; |
12511 | } |
12512 | |
12513 | if (i >= numMasterName) continue; |
12514 | |
12515 | // We have a potential master at this point |
12516 | |
12517 | dist = dist_DoubleVal(mesh->node[masterIndex].xyz, mesh->node[slaveIndex].xyz); |
12518 | |
12519 | //printf("dist = %f (radius = %f), masterIndex %d\n", dist, searchRadius, masterIndex); |
12520 | |
12521 | if ( dist > searchRadius) continue; |
12522 | AIM_NOTNULL(glueDist, aimInfo, status){ if (glueDist == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 12522, __func__, 1, "%s == NULL!", "glueDist" ); goto cleanup; } }; |
12523 | |
12524 | status = array_maxDoubleValue(maxNumMaster, glueDist, &distIndex, &maxDist); |
12525 | if (status != CAPS_SUCCESS0) goto cleanup; |
12526 | |
12527 | //printf("dist = %f, maxdist = %e (index = %d)\n", dist, maxDist, distIndex); |
12528 | |
12529 | if (dist < maxDist) { |
12530 | glueDist[distIndex] = dist; |
12531 | glueConn[distIndex] = masterIndex; |
12532 | } |
12533 | } // End of master loop |
12534 | |
12535 | // How many masters were found |
12536 | numMaster = 0; |
12537 | for (i = 0; i < maxNumMaster; i++) { |
12538 | if (glueDist[i] > searchRadius) continue; // Nothing was every set |
12539 | numMaster += 1; |
12540 | } |
12541 | |
12542 | if (numMaster <= 0) { |
12543 | printf("\tWarning: no masters were found for slave node (id = %d, slave name = %s)!\n", mesh->node[slaveIndex].nodeID, slaveName); |
12544 | } else { |
12545 | AIM_NOTNULL(glueConn, aimInfo, status){ if (glueConn == ((void*)0)) { status = -307; aim_status(aimInfo , status, "feaUtils.c", 12545, __func__, 1, "%s == NULL!", "glueConn" ); goto cleanup; } }; |
12546 | // Create and set connections |
12547 | status = fea_setConnection(slaveName, |
12548 | RigidBodyInterpolate, |
12549 | connectionID, |
12550 | mesh->numElement, |
12551 | dofDependent, |
12552 | 0.0, |
12553 | 0.0, |
12554 | 0.0, |
12555 | 0, |
12556 | 0, |
12557 | mesh->node[slaveIndex].nodeID, |
12558 | masterWeight, |
12559 | masterComponent, |
12560 | numMaster, glueConn, |
12561 | numConnect,feaConnect); |
12562 | if (status != CAPS_SUCCESS0) goto cleanup; |
12563 | } |
12564 | // |
12565 | // *numConnect += 1; |
12566 | // |
12567 | // (*feaConnect) = (feaConnectionStruct *) EG_reall((*feaConnect),*numConnect*sizeof(feaConnectionStruct)); |
12568 | // if ((*feaConnect) == NULL) { |
12569 | // *numConnect = 0; |
12570 | // status = EGADS_MALLOC; |
12571 | // goto cleanup; |
12572 | // } |
12573 | // |
12574 | // status = initiate_feaConnectionStruct(&(*feaConnect)[*numConnect-1]); |
12575 | // if (status != CAPS_SUCCESS) goto cleanup; |
12576 | // |
12577 | // (*feaConnect)[*numConnect-1].name = (char *) EG_alloc((strlen(slaveName) + 1)*sizeof(char)); |
12578 | // if ((*feaConnect)[*numConnect-1].name == NULL) { |
12579 | // status = EGADS_MALLOC; |
12580 | // goto cleanup; |
12581 | // } |
12582 | // |
12583 | // memcpy((*feaConnect)[*numConnect-1].name, slaveName, strlen(slaveName)*sizeof(char)); |
12584 | // (*feaConnect)[*numConnect-1].name[strlen(slaveName)] = '\0'; |
12585 | // |
12586 | // (*feaConnect)[*numConnect-1].connectionID = connectionID; // ConnectionTuple index |
12587 | // (*feaConnect)[*numConnect-1].connectionType = connectionType; |
12588 | // |
12589 | // (*feaConnect)[*numConnect-1].elementID = *numConnect + mesh->numElement; |
12590 | // |
12591 | // (*feaConnect)[*numConnect-1].dofDependent = dofDependent; |
12592 | // |
12593 | // (*feaConnect)[*numConnect-1].connectivity[1] = mesh->node[slaveIndex].nodeID; // Dependent |
12594 | // (*feaConnect)[*numConnect-1].numMaster = numMaster; // Independent |
12595 | // |
12596 | // (*feaConnect)[*numConnect-1].masterIDSet = (int *) EG_alloc(numMaster*sizeof(int)); // [numMaster] |
12597 | // if ((*feaConnect)[*numConnect-1].masterIDSet == NULL) { |
12598 | // status = EGADS_MALLOC; |
12599 | // goto cleanup; |
12600 | // } |
12601 | // (*feaConnect)[*numConnect-1].masterWeighting = (double *) EG_alloc(numMaster*sizeof(double));; // [numMaster] |
12602 | // if ((*feaConnect)[*numConnect-1].masterWeighting == NULL) { |
12603 | // status = EGADS_MALLOC; |
12604 | // goto cleanup; |
12605 | // } |
12606 | // |
12607 | // (*feaConnect)[*numConnect-1].masterComponent =(int *) EG_alloc(numMaster*sizeof(int));; // [numMaster] |
12608 | // if ((*feaConnect)[*numConnect-1].masterComponent == NULL) { |
12609 | // status = EGADS_MALLOC; |
12610 | // goto cleanup; |
12611 | // } |
12612 | // |
12613 | // printf("\tMasters (%d)", numMaster); |
12614 | // |
12615 | // // Master values; |
12616 | // numMaster = 0; |
12617 | // for (i = 0; i < maxNumMaster; i++) { |
12618 | // if (glueDist[i] > searchRadius) continue; // Nothing was every set |
12619 | // printf(" %d(%d)", mesh->node[glueConn[i]].nodeID, glueConn[i]); |
12620 | // (*feaConnect)[*numConnect-1].masterIDSet[numMaster] = mesh->node[glueConn[i]].nodeID; |
12621 | // (*feaConnect)[*numConnect-1].masterWeighting[numMaster] = masterWeight; |
12622 | // (*feaConnect)[*numConnect-1].masterComponent[numMaster] = masterComponent; |
12623 | // numMaster += 1; |
12624 | // } |
12625 | // printf("\n"); |
12626 | |
12627 | } // End of slave loop |
12628 | |
12629 | cleanup: |
12630 | if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_glueMesh, status = %d\n", status); |
12631 | |
12632 | if (glueDist != NULL((void*)0)) EG_free(glueDist); |
12633 | if (glueConn != NULL((void*)0)) EG_free(glueConn); |
12634 | |
12635 | return status; |
12636 | } |
12637 | |
12638 | //int fea_glueMesh2(meshStruct *meshIn, |
12639 | // |
12640 | // mapAttrToIndexStruct *attrMap) { |
12641 | // |
12642 | // // Input parameters |
12643 | // int numGlue=5; |
12644 | // double exactTol=1E-9; |
12645 | // double radiusOfInfluence = 0.1;//1E-3; |
12646 | // int weigthing = 1; // 1=linear |
12647 | // |
12648 | // int status; |
12649 | // int i, j, k, m, masterIndex, slaveIndex, distIndex; |
12650 | // int found; |
12651 | // |
12652 | // int numMesh; |
12653 | // meshStruct *mesh, *master, *slave, *search; |
12654 | // |
12655 | // int **glueConn=NULL; |
12656 | // double **glueDist=NULL; |
12657 | // |
12658 | // double *tempDist=NULL; |
12659 | // int *tempGlue=NULL; |
12660 | // int numNode = 0; |
12661 | // int *meshIndexStart=NULL; |
12662 | // |
12663 | // double dist, maxDist; |
12664 | // |
12665 | // feaMeshDataStruct *feaData; |
12666 | // |
12667 | //// maps from nodeID to mesh->node index |
12668 | //// mesh_nodeID2Array(nasMesh, &n2a); |
12669 | // |
12670 | // printf("Welcome to glueing!\n"); |
12671 | // numMesh = meshIn->numReferenceMesh; |
12672 | // mesh = meshIn->referenceMesh; |
12673 | // |
12674 | // printf("Start with allocation!\n"); |
12675 | // status = array_allocIntegerVector(numMesh, 0, &meshIndexStart); |
12676 | // if (status != CAPS_SUCCESS) goto cleanup; |
12677 | // |
12678 | // // Determine number of nodes in reference meshes - Remember capsIgnore may have already been applied |
12679 | // for (i=0; i < numMesh; i++) { |
12680 | // meshIndexStart[i] = numNode; |
12681 | // numNode += mesh[i].numNode; |
12682 | // } |
12683 | // |
12684 | // if (numNode != meshIn->numNode) { |
12685 | // printf("Inconsistent number of nodes determined!"); |
12686 | // status = CAPS_MISMATCH; |
12687 | // goto cleanup; |
12688 | // } |
12689 | // |
12690 | // // glueConn structure: |
12691 | // // glueConn[row][col] where [row] is node index and |
12692 | // // [row][0] : 1=master, 0=slave, -1=unused |
12693 | // // [row][1:numGlue+1] : nearest node indices, -1=unused |
12694 | // status = array_allocIntegerMatrix(numNode, numGlue+1, -1, &glueConn); |
12695 | // if (status != CAPS_SUCCESS) goto cleanup; |
12696 | // |
12697 | // // glueDist structure: |
12698 | // // glueDist[row][col] where [row] is node index and |
12699 | // // [row][0:numGlue] : distance to nearest node indices found in glueConn[row][1:numGlue+1] |
12700 | // status = array_allocDoubleMatrix(numNode, numGlue, -1, &glueDist); |
12701 | // if (status != CAPS_SUCCESS) goto cleanup; |
12702 | // |
12703 | // status = array_allocIntegerVector(numGlue, 0, &tempGlue); |
12704 | // if (status != CAPS_SUCCESS) goto cleanup; |
12705 | // |
12706 | // status = array_allocDoubleVector(numGlue, 0, &tempDist); |
12707 | // if (status != CAPS_SUCCESS) goto cleanup; |
12708 | // |
12709 | // printf("Done with allocation!\n"); |
12710 | // |
12711 | // // Lets mark all slaves |
12712 | // // |
12713 | // |
12714 | // int attrIndex; |
12715 | // int numSlave=1; |
12716 | // char slaveName[] = "slave"; |
12717 | // int numMasterName; |
12718 | // char **masterName; |
12719 | // |
12720 | // for (i = 0; i < numNode; i++) { |
12721 | // |
12722 | // feaData = (feaMeshDataStruct *) meshIn->node[i].analysisData; |
12723 | // |
12724 | // for (j = 0; j < numSlave; j++) { |
12725 | // status = get_mapAttrToIndexIndex(attrMap, (const char *) slaveName, &attrIndex); |
12726 | // if (status == CAPS_NOTFOUND) { |
12727 | // printf("\tName %s not found in attribute map of capsConnect!!!!\n", slaveName); |
12728 | // continue; |
12729 | // } else if (status != CAPS_SUCCESS) return status; |
12730 | // |
12731 | // |
12732 | // if (feaData->connectIndex != attrIndex) continue; |
12733 | // |
12734 | // glueConn[i][0] = 0; |
12735 | // break; |
12736 | // } |
12737 | // |
12738 | // if (glueConn[i][0] != 0) continue; |
12739 | // |
12740 | // status = string_toStringDynamicArray('["master"]', &numMasterName, &masterName); |
12741 | // if (status != CAPS_SUCCESS); goto cleanup; |
12742 | // |
12743 | // for (k = 0; k < numNode; k++) { |
12744 | // |
12745 | // if (i == k) continue; |
12746 | // for (m = 0; m < numMasterName; m++) { |
12747 | // |
12748 | // } |
12749 | // } |
12750 | // |
12751 | // |
12752 | // (void) string_freeArray(numMasterName, &masterName); |
12753 | // masterName = NULL; |
12754 | // numMasterName = 0; |
12755 | // } |
12756 | // |
12757 | // |
12758 | // // for (i = 0; i < numMesh; i++) { // THIS IS MOSTLY correct - error in master slave relation of RBE3 elements |
12759 | //// master = &mesh[i]; |
12760 | //// |
12761 | ////// printf("Master Mesh %d (of %d)\n", i, numMesh); |
12762 | //// //Exhaustive search |
12763 | //// for (masterIndex = 0; masterIndex < master->numNode; masterIndex++) { |
12764 | //// |
12765 | ////// printf("master index %d (of %d)\n", masterIndex, master->numNode); |
12766 | //// // Slaves may be promoted to masters, but cannot be slaves to multiple masters |
12767 | //// //if (glueConn[masterIndex+meshIndexStart[masterIndex]][0] != 0) continue; |
12768 | //// |
12769 | //// status = array_setDoubleVectorValue(numGlue, 1E9, &tempDist); |
12770 | //// if (status != CAPS_SUCCESS) goto cleanup; |
12771 | //// |
12772 | //// status = array_setIntegerVectorValue(numGlue, -1, &tempGlue); |
12773 | //// if (status != CAPS_SUCCESS) goto cleanup; |
12774 | //// |
12775 | //// for (j = 0; j < numMesh; j++) { |
12776 | //// |
12777 | //// if (i == j) continue; |
12778 | //// |
12779 | //// slave = &mesh[j]; |
12780 | //// |
12781 | //// for (slaveIndex = 0; slaveIndex < slave->numNode; slaveIndex++) { |
12782 | //// |
12783 | //// // Slaves cannot have multiple masters - FALSE |
12784 | //// if (glueConn[slaveIndex+meshIndexStart[j]][0] == 0) continue; |
12785 | //// |
12786 | //// // Make sure master slave relation doesn't already exist |
12787 | //// found = (int) false; |
12788 | //// for (k =1; k < numGlue+1; k++) { |
12789 | //// if (masterIndex+meshIndexStart[i] == glueConn[slaveIndex+meshIndexStart[j]][k]){ |
12790 | //// found = (int) true; |
12791 | //// break; |
12792 | //// } |
12793 | //// } |
12794 | //// |
12795 | //// if (found == (int) true) continue; |
12796 | //// |
12797 | ////// printf("glueConn %d\n", glueConn[slaveIndex+meshIndexStart[j]][0]); |
12798 | //// |
12799 | //// dist = dist_DoubleVal(master->node[masterIndex].xyz, slave->node[slaveIndex].xyz); |
12800 | //// |
12801 | ////// printf("dist = %f (radius = %f)\n", dist, radiusOfInfluence); |
12802 | //// |
12803 | //// if ( dist > radiusOfInfluence) continue; |
12804 | //// |
12805 | //// status = array_maxDoubleValue(numGlue, tempDist, &distIndex, &maxDist); |
12806 | //// if (status != CAPS_SUCCESS) goto cleanup; |
12807 | //// |
12808 | //// //printf("dist = %f, maxdist = %e (index = %d)\n", dist, maxDist, distIndex); |
12809 | //// |
12810 | //// if (dist < maxDist) { |
12811 | //// tempDist[distIndex] = dist; |
12812 | //// tempGlue[distIndex] = slaveIndex + meshIndexStart[j] ; |
12813 | //// } |
12814 | //// } |
12815 | //// } |
12816 | //// |
12817 | //// if (tempDist[0] > radiusOfInfluence) continue; // Nothing was every set |
12818 | //// |
12819 | //// // glueConn structure: |
12820 | //// // glueConn[row][col] where [row] is node index and |
12821 | //// // [row][0] : 1=master, 0=slave, -1=unused |
12822 | //// // [row][1:numGlue+1] : nearest node indices, -1=unused |
12823 | //// |
12824 | //// // glueDist[row][col] where [row] is node index and |
12825 | //// // [row][0:numGlue] : distance to nearest node indices found in glueConn[row][1:numGlue+1] |
12826 | //// |
12827 | //// glueConn[masterIndex+meshIndexStart[i]][0] = 1; //Mark as Master |
12828 | //// distIndex = 0; |
12829 | //// for (j = 0; j < numGlue; j++) { |
12830 | //// if (tempDist[j] > radiusOfInfluence) continue; // Nothing was every set |
12831 | //// |
12832 | //// glueDist[masterIndex+meshIndexStart[i]][distIndex] = tempDist[j]; // Distances for a master |
12833 | //// glueConn[masterIndex+meshIndexStart[i]][distIndex+1] = tempGlue[j]; // Glue connections/slaves for a master |
12834 | //// |
12835 | //// // Mark the masters slave's as slaves - A slave can become a master to another slave, |
12836 | //// // but it can not be a slave to another master |
12837 | //// if (glueConn[tempGlue[j]][0] < 0) glueConn[tempGlue[j]][0] = 0; |
12838 | //// |
12839 | //// distIndex +=1; |
12840 | //// } |
12841 | //// |
12842 | //// printf("Set %d : %d: ",masterIndex+meshIndexStart[i], glueConn[masterIndex+meshIndexStart[i]][0]); |
12843 | //// for(j = 0; j < numGlue; j++) { |
12844 | //// printf("%d ", glueConn[masterIndex+meshIndexStart[i]][j+1]); |
12845 | //// } |
12846 | //// printf("\n"); |
12847 | //// } |
12848 | //// } |
12849 | //// |
12850 | //// for (i = 0; i < numNode;i++) { |
12851 | //// if (glueConn[i][0] < 0) continue; |
12852 | //// printf("Node %d : %d : ", i, glueConn[i][0]); |
12853 | //// for(j = 0; j < numGlue; j++) { |
12854 | ////// printf("%d (%.2f)", glueConn[i][j+1], glueDist[i][j]); |
12855 | //// printf("%d ", glueConn[i][j+1]); |
12856 | //// } |
12857 | //// printf("\n"); |
12858 | //// } |
12859 | //// // Finished getting all my glue |
12860 | // |
12861 | // cleanup: |
12862 | // if (status != CAPS_SUCCESS) printf("\tPremature exit in fea_glueMesh, status = %d\n", status); |
12863 | // |
12864 | // if (tempDist != NULL) EG_free(tempDist); |
12865 | // if (tempGlue != NULL) EG_free(tempGlue); |
12866 | // if (meshIndexStart != NULL) EG_free(meshIndexStart); |
12867 | // |
12868 | // if (glueConn != NULL) (void) array_freeIntegerMatrix(numNode, numGlue, &glueConn); |
12869 | // |
12870 | // if (glueDist != NULL) (void) array_freeDoubleMatrix(numNode, numGlue, &glueDist); |
12871 | // |
12872 | // (void) string_freeArray(numMasterName, &masterName); |
12873 | // masterName = NULL; |
12874 | // |
12875 | // return status; |
12876 | //} |
12877 | |
12878 | // Create a default analysis structure based on previous inputs |
12879 | int fea_createDefaultAnalysis(void *aimInfo, feaProblemStruct *feaProblem, const char *analysisType) { |
12880 | |
12881 | int status; |
12882 | int i; |
12883 | |
12884 | capsTuple *tupleVal; |
12885 | |
12886 | char *json=NULL((void*)0); |
12887 | int maxSize=2048; |
12888 | |
12889 | if (feaProblem == NULL((void*)0)) return CAPS_NULLVALUE-307; |
12890 | |
12891 | if (feaProblem->numAnalysis != 0 || feaProblem->feaAnalysis != NULL((void*)0)) { |
12892 | // Destroy our analysis structures coming in if aren't 0 and NULL already |
12893 | for (i = 0; i < feaProblem->numAnalysis; i++) { |
12894 | status = destroy_feaAnalysisStruct(&feaProblem->feaAnalysis[i]); |
12895 | if (status != CAPS_SUCCESS0) return status; |
12896 | } |
12897 | |
12898 | if (feaProblem->feaAnalysis != NULL((void*)0)) EG_free(feaProblem->feaAnalysis); |
12899 | feaProblem->feaAnalysis = NULL((void*)0); |
12900 | feaProblem->numAnalysis = 0; |
12901 | } |
12902 | |
12903 | tupleVal = (capsTuple *) EG_alloc(1*sizeof(capsTuple)); |
12904 | if (tupleVal == NULL((void*)0)) { |
12905 | status = EGADS_MALLOC-4; |
12906 | goto cleanup; |
12907 | } |
12908 | tupleVal[0].name = NULL((void*)0); |
12909 | tupleVal[0].value = NULL((void*)0); |
12910 | |
12911 | json = (char *) EG_alloc(maxSize*sizeof(char)); |
12912 | if (json == NULL((void*)0)) { |
12913 | status = EGADS_MALLOC-4; |
12914 | goto cleanup; |
12915 | } |
12916 | |
12917 | strcpy(json,"{\"analysisType\":\""); |
12918 | if (strcasecmp(analysisType, "Optimization") == 0) strcat(json,"Static"); |
12919 | else strcat(json, analysisType); |
12920 | strcat(json,"\""); |
12921 | |
12922 | if (feaProblem->numLoad != 0) { |
12923 | strcat(json,",\"analysisLoad\":["); |
12924 | for (i = 0; i < feaProblem->numLoad; i++) { |
12925 | if (i != 0) strcat(json,","); |
12926 | strcat(json,"\""); |
12927 | strcat(json,feaProblem->feaLoad[i].name); |
12928 | strcat(json,"\""); |
12929 | } |
12930 | strcat(json, "]"); |
12931 | } |
12932 | |
12933 | if (feaProblem->numConstraint != 0) { |
12934 | strcat(json,",\"analysisConstraint\":["); |
12935 | for (i = 0; i < feaProblem->numConstraint; i++) { |
12936 | if (i != 0) strcat(json,","); |
12937 | strcat(json,"\""); |
12938 | strcat(json,feaProblem->feaConstraint[i].name); |
12939 | strcat(json,"\""); |
12940 | } |
12941 | strcat(json, "]"); |
12942 | } |
12943 | |
12944 | if (feaProblem->numSupport != 0) { |
12945 | strcat(json,",\"analysisSupport\":["); |
12946 | for (i = 0; i < feaProblem->numSupport; i++) { |
12947 | if (i != 0) strcat(json,","); |
12948 | strcat(json,"\""); |
12949 | strcat(json,feaProblem->feaSupport[i].name); |
12950 | strcat(json,"\""); |
12951 | } |
12952 | strcat(json, "]"); |
12953 | } |
12954 | |
12955 | if (feaProblem->numDesignConstraint != 0) { |
12956 | strcat(json,",\"analysisDesignConstraint\":["); |
12957 | for (i = 0; i < feaProblem->numDesignConstraint; i++) { |
12958 | if (i != 0) strcat(json,","); |
12959 | strcat(json,"\""); |
12960 | strcat(json,feaProblem->feaDesignConstraint[i].name); |
12961 | strcat(json,"\""); |
12962 | } |
12963 | strcat(json, "]"); |
12964 | } |
12965 | |
12966 | strcat(json,"}"); |
12967 | |
12968 | tupleVal[0].name = EG_strdup("Default"); |
12969 | tupleVal[0].value = json; |
12970 | |
12971 | //printf("Default analysis tuple - %s\n", tupleVal[0].value); |
12972 | |
12973 | status = fea_getAnalysis(aimInfo, |
12974 | 1, |
12975 | tupleVal, |
12976 | feaProblem); |
12977 | if (status != CAPS_SUCCESS0) goto cleanup; |
12978 | |
12979 | // feaProblem->numAnalysis = 1; |
12980 | // feaProblem->feaAnalysis = (feaAnalysisStruct *) EG_alloc(feaProblem->numAnalysis*sizeof(feaAnalysisStruct)); |
12981 | // if (feaProblem->feaAnalysis == NULL) return EGADS_MALLOC; |
12982 | // |
12983 | // feaAnalysis=&feaProblem->feaAnalysis[0]; |
12984 | // status = initiate_feaAnalysisStruct(feaAnalysis); |
12985 | // if (status != CAPS_SUCCESS) return status; |
12986 | // |
12987 | // |
12988 | // feaAnalysis->name = (char *) EG_alloc(((strlen(name)) + 1)*sizeof(char)); |
12989 | // if (feaProblem->feaAnalysis->name == NULL) return EGADS_MALLOC; |
12990 | // |
12991 | // memcpy(feaAnalysis->name, name, strlen(name)*sizeof(char)); |
12992 | // feaAnalysis->name[strlen(name)] = '\0'; |
12993 | // |
12994 | // feaAnalysis->analysisID = 1; |
12995 | |
12996 | |
12997 | status = CAPS_SUCCESS0; |
12998 | goto cleanup; |
12999 | |
13000 | cleanup: |
13001 | if (status != CAPS_SUCCESS0) printf("\tPremature exit in fea_createDefaultAnalysis, status = %d\n", status); |
13002 | |
13003 | if (tupleVal != NULL((void*)0)) { |
13004 | if (tupleVal[0].name != NULL((void*)0)) EG_free(tupleVal[0].name); |
13005 | if (tupleVal[0].value != NULL((void*)0)) EG_free(tupleVal[0].value); |
13006 | EG_free(tupleVal); |
13007 | } |
13008 | |
13009 | return status; |
13010 | } |
13011 | |
13012 | // Setup the default flutter velocities if not specified |
13013 | int fea_defaultFlutterVelocity(feaAnalysisStruct *feaAnalysis) { |
13014 | int i; |
13015 | |
13016 | int defaultNum = 23; |
13017 | double velocity=0, dv=1, vmin=0, vmax=0; |
13018 | |
13019 | if (feaAnalysis->numFlutterVel == 0) { |
13020 | AIM_FREE(feaAnalysis->flutterVel){ EG_free(feaAnalysis->flutterVel); feaAnalysis->flutterVel = ((void*)0); }; |
13021 | |
13022 | feaAnalysis->numFlutterVel = defaultNum; |
13023 | feaAnalysis->flutterVel = EG_alloc(feaAnalysis->numFlutterVel*sizeof(double)); |
13024 | if (feaAnalysis->flutterVel == NULL((void*)0)) { |
13025 | return EGADS_MALLOC-4; |
13026 | } |
13027 | |
13028 | velocity = sqrt(2*feaAnalysis->dynamicPressure/feaAnalysis->density); |
13029 | vmin = velocity / 2.0; |
13030 | vmax = 2 * velocity; |
13031 | dv = (vmax - vmin) / (double) (feaAnalysis->numFlutterVel-3); |
13032 | |
13033 | for (i = 0; i < feaAnalysis->numFlutterVel-2; i++) { |
13034 | feaAnalysis->flutterVel[i+1] = vmin + (double) i * dv; |
13035 | } |
13036 | |
13037 | feaAnalysis->flutterVel[0] = velocity/10; |
13038 | feaAnalysis->flutterVel[feaAnalysis->numFlutterVel-1] = velocity*10; |
13039 | } |
13040 | |
13041 | return CAPS_SUCCESS0; |
13042 | } |