File: | nastran/nastranAIM.c |
Warning: | line 1972, column 29 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * CAPS: Computational Aircraft Prototype Syntheses | |||
3 | * | |||
4 | * Nastran AIM | |||
5 | * | |||
6 | * Written by Dr. Ryan Durscher and Dr. Ed Alyanak AFRL/RQVC | |||
7 | * | |||
8 | * This software has been cleared for public release on 05 Nov 2020, case number 88ABW-2020-3462. | |||
9 | */ | |||
10 | ||||
11 | /*! \mainpage Introduction | |||
12 | * | |||
13 | * \section overviewNastran Nastran AIM Overview | |||
14 | * A module in the Computational Aircraft Prototype Syntheses (CAPS) has been developed to interact (primarily | |||
15 | * through input files) with the finite element structural solver Nastran \cite Nastran. | |||
16 | * | |||
17 | * Current issues include: | |||
18 | * - A thorough bug testing needs to be undertaken. | |||
19 | * | |||
20 | * An outline of the AIM's inputs, outputs and attributes are provided in \ref aimInputsNastran and | |||
21 | * \ref aimOutputsNastran and \ref attributeNastran, respectively. | |||
22 | * | |||
23 | * Details of the AIM's automated data transfer capabilities are outlined in \ref dataTransferNastran | |||
24 | * | |||
25 | * \section nastranExamples Examples | |||
26 | * Example problems using the Nastran AIM may be found at \ref examplesNastran . | |||
27 | * - \ref nastranSingleLoadEx | |||
28 | * - \ref nastranMultipleLoadEx | |||
29 | * - \ref nastranModalEx | |||
30 | * - \ref nastranOptEx | |||
31 | * - \ref nastranCompositeEx | |||
32 | * - \ref nastranCompOptimizationEx | |||
33 | * | |||
34 | * \section clearanceNastran Clearance Statement | |||
35 | * This software has been cleared for public release on 05 Nov 2020, case number 88ABW-2020-3462. | |||
36 | */ | |||
37 | ||||
38 | /*! \page attributeNastran AIM attributes | |||
39 | * The following list of attributes are required for the Nastran AIM inside the geometry input. | |||
40 | * | |||
41 | * - <b> capsDiscipline</b> This attribute is a requirement if doing aeroelastic analysis within Nastran. capsDiscipline allows | |||
42 | * the AIM to determine which bodies are meant for structural analysis and which are used for aerodynamics. Options | |||
43 | * are: Structure and Aerodynamic (case insensitive). | |||
44 | * | |||
45 | * - <b> capsGroup</b> This is a name assigned to any geometric body to denote a property. This body could be a solid, surface, face, wire, edge or node. | |||
46 | * Recall that a string in ESP starts with a $. For example, attribute <c>capsGroup $Wing</c>. | |||
47 | * | |||
48 | * - <b> capsLoad</b> This is a name assigned to any geometric body where a load is applied. This attribute was separated from the <c>capsGroup</c> | |||
49 | * attribute to allow the user to define a local area to apply a load on without adding multiple <c>capsGroup</c> attributes. | |||
50 | * Recall that a string in ESP starts with a $. For example, attribute <c>capsLoad $force</c>. | |||
51 | * | |||
52 | * - <b> capsConstraint</b> This is a name assigned to any geometric body where a constraint/boundary condition is applied. | |||
53 | * This attribute was separated from the <c>capsGroup</c> attribute to allow the user to define a local area to apply a boundary condition | |||
54 | * without adding multiple <c>capsGroup</c> attributes. Recall that a string in ESP starts with a $. For example, attribute <c>capsConstraint $fixed</c>. | |||
55 | * | |||
56 | * - <b> capsIgnore</b> It is possible that there is a geometric body (or entity) that you do not want the Nastran AIM to pay attention to when creating | |||
57 | * a finite element model. The capsIgnore attribute allows a body (or entity) to be in the geometry and ignored by the AIM. For example, | |||
58 | * because of limitations in OpenCASCADE a situation where two edges are overlapping may occur; capsIgnore allows the user to only | |||
59 | * pay attention to one of the overlapping edges. | |||
60 | * | |||
61 | * - <b> capsConnect</b> This is a name assigned to any geometric body where the user wishes to create | |||
62 | * "fictitious" connections such as springs, dampers, and/or rigid body connections to. The user must manually specify | |||
63 | * the connection between two <c>capsConnect</c> entities using the "Connect" tuple (see \ref aimInputsNastran). | |||
64 | * Recall that a string in ESP starts with a $. For example, attribute <c>capsConnect $springStart</c>. | |||
65 | * | |||
66 | * - <b> capsConnectLink</b> Similar to <c>capsConnect</c>, this is a name assigned to any geometric body where | |||
67 | * the user wishes to create "fictitious" connections to. A connection is automatically made if a <c>capsConnectLink</c> | |||
68 | * matches a <c>capsConnect</c> group. Again further specifics of the connection are input using the "Connect" | |||
69 | * tuple (see \ref aimInputsNastran). Recall that a string in ESP starts with a $. | |||
70 | * For example, attribute <c>capsConnectLink $springEnd</c>. | |||
71 | * | |||
72 | * - <b> capsResponse</b> This is a name assigned to any geometric body that will be used to define design sensitivity | |||
73 | * responses for optimization. Specific information for the responses are input using the "Design_Response" tuple (see | |||
74 | * \ref aimInputsNastran). Recall that a string in ESP starts with a $. For examples, | |||
75 | * attribute <c>capsResponse $displacementNode</c>. | |||
76 | * | |||
77 | * - <b> capsBound </b> This is used to mark surfaces on the structural grid in which data transfer with an external | |||
78 | * solver will take place. See \ref dataTransferNastran for additional details. | |||
79 | * | |||
80 | * Internal Aeroelastic Analysis | |||
81 | * | |||
82 | * - <b> capsBound </b> This is used to mark surfaces on the structural grid in which a spline will be created between | |||
83 | * the structural and aero-loads. | |||
84 | * | |||
85 | * - <b> capsReferenceArea</b> [Optional: Default 1.0] Reference area to use when doing aeroelastic analysis. | |||
86 | * This attribute may exist on any aerodynamic cross-section. | |||
87 | * | |||
88 | * - <b> capsReferenceChord</b> [Optional: Default 1.0] Reference chord to use when doing aeroelastic analysis. | |||
89 | * This attribute may exist on any aerodynamic cross-section. | |||
90 | * | |||
91 | * - <b> capsReferenceSpan</b> [Optional: Default 1.0] Reference span to use when doing aeroelastic analysis. | |||
92 | * This attribute may exist on any aerodynamic cross-section. | |||
93 | * | |||
94 | */ | |||
95 | ||||
96 | #include <string.h> | |||
97 | #include <math.h> | |||
98 | #include "capsTypes.h" | |||
99 | #include "aimUtil.h" | |||
100 | ||||
101 | #include "meshUtils.h" // Meshing utilities | |||
102 | #include "miscUtils.h" // Miscellaneous utilities | |||
103 | #include "vlmUtils.h" // Vortex lattice method utilities | |||
104 | #include "vlmSpanSpace.h" | |||
105 | #include "feaUtils.h" // FEA utilities | |||
106 | #include "nastranUtils.h" // Nastran utilities | |||
107 | ||||
108 | #ifdef WIN32 | |||
109 | #define snprintf _snprintf | |||
110 | #define strcasecmp stricmp | |||
111 | #endif | |||
112 | ||||
113 | #define MXCHAR255 255 | |||
114 | ||||
115 | //#define DEBUG | |||
116 | ||||
117 | enum aimInputs | |||
118 | { | |||
119 | Proj_Name = 1, /* index is 1-based */ | |||
120 | Tess_Params, | |||
121 | Edge_Point_Min, | |||
122 | Edge_Point_Max, | |||
123 | Quad_Mesh, | |||
124 | Property, | |||
125 | Material, | |||
126 | Constraint, | |||
127 | Load, | |||
128 | Analysix, | |||
129 | Analysis_Type, | |||
130 | File_Format, | |||
131 | Mesh_File_Format, | |||
132 | Design_Variable, | |||
133 | Design_Variable_Relation, | |||
134 | Design_Constraint, | |||
135 | Design_Equation, | |||
136 | Design_Table, | |||
137 | Design_Response, | |||
138 | Design_Equation_Response, | |||
139 | Design_Opt_Param, | |||
140 | ObjectiveMinMax, | |||
141 | ObjectiveResponseType, | |||
142 | VLM_Surface, | |||
143 | VLM_Control, | |||
144 | Support, | |||
145 | Connect, | |||
146 | Parameter, | |||
147 | Mesh, | |||
148 | NUMINPUT = Mesh /* Total number of inputs */ | |||
149 | }; | |||
150 | ||||
151 | #define NUMOUTPUT7 7 | |||
152 | ||||
153 | ||||
154 | typedef struct { | |||
155 | ||||
156 | // Project name | |||
157 | char *projectName; // Project name | |||
158 | ||||
159 | feaUnitsStruct units; // units system | |||
160 | ||||
161 | feaProblemStruct feaProblem; | |||
162 | ||||
163 | // Attribute to index map | |||
164 | mapAttrToIndexStruct attrMap; | |||
165 | ||||
166 | // Attribute to constraint index map | |||
167 | mapAttrToIndexStruct constraintMap; | |||
168 | ||||
169 | // Attribute to load index map | |||
170 | mapAttrToIndexStruct loadMap; | |||
171 | ||||
172 | // Attribute to transfer map | |||
173 | mapAttrToIndexStruct transferMap; | |||
174 | ||||
175 | // Attribute to connect map | |||
176 | mapAttrToIndexStruct connectMap; | |||
177 | ||||
178 | // Attribute to response map | |||
179 | mapAttrToIndexStruct responseMap; | |||
180 | ||||
181 | // Mesh holders | |||
182 | int numMesh; | |||
183 | meshStruct *feaMesh; | |||
184 | ||||
185 | } aimStorage; | |||
186 | ||||
187 | ||||
188 | ||||
189 | static int initiate_aimStorage(aimStorage *nastranInstance) | |||
190 | { | |||
191 | ||||
192 | int status; | |||
193 | ||||
194 | // Set initial values for nastranInstance | |||
195 | nastranInstance->projectName = NULL((void*)0); | |||
196 | ||||
197 | /* | |||
198 | // Check to make sure data transfer is ok | |||
199 | nastranInstance->dataTransferCheck = (int) true; | |||
200 | */ | |||
201 | ||||
202 | status = initiate_feaUnitsStruct(&nastranInstance->units); | |||
203 | if (status != CAPS_SUCCESS0) return status; | |||
204 | ||||
205 | // Container for attribute to index map | |||
206 | status = initiate_mapAttrToIndexStruct(&nastranInstance->attrMap); | |||
207 | if (status != CAPS_SUCCESS0) return status; | |||
208 | ||||
209 | // Container for attribute to constraint index map | |||
210 | status = initiate_mapAttrToIndexStruct(&nastranInstance->constraintMap); | |||
211 | if (status != CAPS_SUCCESS0) return status; | |||
212 | ||||
213 | // Container for attribute to load index map | |||
214 | status = initiate_mapAttrToIndexStruct(&nastranInstance->loadMap); | |||
215 | if (status != CAPS_SUCCESS0) return status; | |||
216 | ||||
217 | // Container for transfer to index map | |||
218 | status = initiate_mapAttrToIndexStruct(&nastranInstance->transferMap); | |||
219 | if (status != CAPS_SUCCESS0) return status; | |||
220 | ||||
221 | // Container for connect to index map | |||
222 | status = initiate_mapAttrToIndexStruct(&nastranInstance->connectMap); | |||
223 | if (status != CAPS_SUCCESS0) return status; | |||
224 | ||||
225 | // Container for response to index map | |||
226 | status = initiate_mapAttrToIndexStruct(&nastranInstance->responseMap); | |||
227 | if (status != CAPS_SUCCESS0) return status; | |||
228 | ||||
229 | status = initiate_feaProblemStruct(&nastranInstance->feaProblem); | |||
230 | if (status != CAPS_SUCCESS0) return status; | |||
231 | ||||
232 | // Mesh holders | |||
233 | nastranInstance->numMesh = 0; | |||
234 | nastranInstance->feaMesh = NULL((void*)0); | |||
235 | ||||
236 | return CAPS_SUCCESS0; | |||
237 | } | |||
238 | ||||
239 | ||||
240 | static int destroy_aimStorage(aimStorage *nastranInstance) | |||
241 | { | |||
242 | int status; | |||
243 | int i; | |||
244 | ||||
245 | status = destroy_feaUnitsStruct(&nastranInstance->units); | |||
246 | if (status != CAPS_SUCCESS0) | |||
247 | printf("Error: Status %d during destroy_feaUnitsStruct!\n", status); | |||
248 | ||||
249 | // Attribute to index map | |||
250 | status = destroy_mapAttrToIndexStruct(&nastranInstance->attrMap); | |||
251 | if (status != CAPS_SUCCESS0) | |||
252 | printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); | |||
253 | ||||
254 | // Attribute to constraint index map | |||
255 | status = destroy_mapAttrToIndexStruct(&nastranInstance->constraintMap); | |||
256 | if (status != CAPS_SUCCESS0) | |||
257 | printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); | |||
258 | ||||
259 | // Attribute to load index map | |||
260 | status = destroy_mapAttrToIndexStruct(&nastranInstance->loadMap); | |||
261 | if (status != CAPS_SUCCESS0) | |||
262 | printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); | |||
263 | ||||
264 | // Transfer to index map | |||
265 | status = destroy_mapAttrToIndexStruct(&nastranInstance->transferMap); | |||
266 | if (status != CAPS_SUCCESS0) | |||
267 | printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); | |||
268 | ||||
269 | // Connect to index map | |||
270 | status = destroy_mapAttrToIndexStruct(&nastranInstance->connectMap); | |||
271 | if (status != CAPS_SUCCESS0) | |||
272 | printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); | |||
273 | ||||
274 | // Response to index map | |||
275 | status = destroy_mapAttrToIndexStruct(&nastranInstance->responseMap); | |||
276 | if (status != CAPS_SUCCESS0) | |||
277 | printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); | |||
278 | ||||
279 | // Cleanup meshes | |||
280 | if (nastranInstance->feaMesh != NULL((void*)0)) { | |||
281 | ||||
282 | for (i = 0; i < nastranInstance->numMesh; i++) { | |||
283 | status = destroy_meshStruct(&nastranInstance->feaMesh[i]); | |||
284 | if (status != CAPS_SUCCESS0) | |||
285 | printf("Error: Status %d during destroy_meshStruct!\n", status); | |||
286 | } | |||
287 | ||||
288 | EG_free(nastranInstance->feaMesh); | |||
289 | } | |||
290 | ||||
291 | nastranInstance->feaMesh = NULL((void*)0); | |||
292 | nastranInstance->numMesh = 0; | |||
293 | ||||
294 | // Destroy FEA problem structure | |||
295 | status = destroy_feaProblemStruct(&nastranInstance->feaProblem); | |||
296 | if (status != CAPS_SUCCESS0) | |||
297 | printf("Error: Status %d during destroy_feaProblemStruct!\n", status); | |||
298 | ||||
299 | // NULL projetName | |||
300 | nastranInstance->projectName = NULL((void*)0); | |||
301 | ||||
302 | return CAPS_SUCCESS0; | |||
303 | } | |||
304 | ||||
305 | ||||
306 | static int checkAndCreateMesh(void *aimInfo, aimStorage *nastranInstance) | |||
307 | { | |||
308 | // Function return flag | |||
309 | int status; | |||
310 | int i, remesh = (int)true1; | |||
311 | ||||
312 | // Meshing related variables | |||
313 | double tessParam[3] = {0.025, 0.001, 15}; | |||
314 | int edgePointMin = 2; | |||
315 | int edgePointMax = 50; | |||
316 | int quadMesh = (int) false0; | |||
317 | ||||
318 | // analysis input values | |||
319 | capsValue *TessParams; | |||
320 | capsValue *EdgePoint_Min; | |||
321 | capsValue *EdgePoint_Max; | |||
322 | capsValue *QuadMesh; | |||
323 | ||||
324 | for (i = 0; i < nastranInstance->numMesh; i++) { | |||
325 | remesh = remesh && (nastranInstance->feaMesh[i].egadsTess->oclass == EMPTY4); | |||
326 | } | |||
327 | if (remesh == (int) false0) return CAPS_SUCCESS0; | |||
328 | ||||
329 | // retrieve or create the mesh from fea_createMesh | |||
330 | status = aim_getValue(aimInfo, Tess_Params, ANALYSISIN, &TessParams); | |||
331 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 331, __func__, 0); goto cleanup; }; | |||
332 | ||||
333 | status = aim_getValue(aimInfo, Edge_Point_Min, ANALYSISIN, &EdgePoint_Min); | |||
334 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 334, __func__, 0); goto cleanup; }; | |||
335 | ||||
336 | status = aim_getValue(aimInfo, Edge_Point_Max, ANALYSISIN, &EdgePoint_Max); | |||
337 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 337, __func__, 0); goto cleanup; }; | |||
338 | ||||
339 | status = aim_getValue(aimInfo, Quad_Mesh, ANALYSISIN, &QuadMesh); | |||
340 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 340, __func__, 0); goto cleanup; }; | |||
341 | ||||
342 | if (TessParams != NULL((void*)0)) { | |||
343 | tessParam[0] = TessParams->vals.reals[0]; | |||
344 | tessParam[1] = TessParams->vals.reals[1]; | |||
345 | tessParam[2] = TessParams->vals.reals[2]; | |||
346 | } | |||
347 | ||||
348 | // Max and min number of points | |||
349 | if (EdgePoint_Min != NULL((void*)0) && EdgePoint_Min->nullVal != IsNull) { | |||
350 | edgePointMin = EdgePoint_Min->vals.integer; | |||
351 | if (edgePointMin < 2) { | |||
352 | AIM_ANALYSISIN_ERROR(aimInfo, Edge_Point_Min, "Edge_Point_Min = %d must be greater or equal to 2\n", edgePointMin){ aim_message(aimInfo, CERROR, Edge_Point_Min, "nastranAIM.c" , 352, __func__, "Edge_Point_Min = %d must be greater or equal to 2\n" , edgePointMin); }; | |||
353 | return CAPS_BADVALUE-311; | |||
354 | } | |||
355 | } | |||
356 | ||||
357 | if (EdgePoint_Max != NULL((void*)0) && EdgePoint_Max->nullVal != IsNull) { | |||
358 | edgePointMax = EdgePoint_Max->vals.integer; | |||
359 | if (edgePointMax < 2) { | |||
360 | AIM_ANALYSISIN_ERROR(aimInfo, Edge_Point_Max, "Edge_Point_Max = %d must be greater or equal to 2\n", edgePointMax){ aim_message(aimInfo, CERROR, Edge_Point_Max, "nastranAIM.c" , 360, __func__, "Edge_Point_Max = %d must be greater or equal to 2\n" , edgePointMax); }; | |||
361 | return CAPS_BADVALUE-311; | |||
362 | } | |||
363 | } | |||
364 | ||||
365 | if (edgePointMin >= 2 && edgePointMax >= 2 && edgePointMin > edgePointMax) { | |||
366 | AIM_ERROR (aimInfo, "Edge_Point_Max must be greater or equal Edge_Point_Min"){ aim_message(aimInfo, CERROR, 0 , "nastranAIM.c", 366, __func__ , "Edge_Point_Max must be greater or equal Edge_Point_Min"); }; | |||
367 | AIM_ADDLINE(aimInfo, "Edge_Point_Max = %d, Edge_Point_Min = %d\n",edgePointMax,edgePointMin){ aim_addLine(aimInfo, "Edge_Point_Max = %d, Edge_Point_Min = %d\n" ,edgePointMax,edgePointMin); }; | |||
368 | return CAPS_BADVALUE-311; | |||
369 | } | |||
370 | ||||
371 | if (QuadMesh != NULL((void*)0)) quadMesh = QuadMesh->vals.integer; | |||
372 | ||||
373 | status = fea_createMesh(aimInfo, | |||
374 | tessParam, | |||
375 | edgePointMin, | |||
376 | edgePointMax, | |||
377 | quadMesh, | |||
378 | &nastranInstance->attrMap, | |||
379 | &nastranInstance->constraintMap, | |||
380 | &nastranInstance->loadMap, | |||
381 | &nastranInstance->transferMap, | |||
382 | &nastranInstance->connectMap, | |||
383 | &nastranInstance->responseMap, | |||
384 | &nastranInstance->numMesh, | |||
385 | &nastranInstance->feaMesh, | |||
386 | &nastranInstance->feaProblem ); | |||
387 | if (status != CAPS_SUCCESS0) return status; | |||
388 | ||||
389 | cleanup: | |||
390 | return status; | |||
391 | } | |||
392 | ||||
393 | ||||
394 | static int createVLMMesh(void *aimInfo, aimStorage *nastranInstance, | |||
395 | capsValue *aimInputs) | |||
396 | { | |||
397 | ||||
398 | int projectionMethod = (int) true1; | |||
399 | ||||
400 | int status, status2; // Function return status | |||
401 | ||||
402 | int i, j, k, surfaceIndex = 0, sectionIndex, transferIndex; // Indexing | |||
403 | ||||
404 | // Bodies | |||
405 | const char *intents; | |||
406 | int numBody; // Number of Bodies | |||
407 | ego *bodies; | |||
408 | ||||
409 | // Aeroelastic information | |||
410 | int numVLMSurface = 0; | |||
411 | vlmSurfaceStruct *vlmSurface = NULL((void*)0); | |||
412 | int numSpanWise; | |||
413 | ||||
414 | int numVLMControl = 0; | |||
415 | vlmControlStruct *vlmControl = NULL((void*)0); | |||
416 | ||||
417 | feaAeroStruct *feaAeroTemp = NULL((void*)0); | |||
418 | ||||
419 | // Vector variables | |||
420 | double A[3], B[3], C[3], D[3], P[3], p[3], N[3], n[3], d_proj[3]; | |||
421 | ||||
422 | double *a, *b, *c, *d; | |||
423 | double apbArea, apcArea, cpdArea, bpdArea, Area; | |||
424 | ||||
425 | feaMeshDataStruct *feaData; | |||
426 | ||||
427 | // Get AIM bodies | |||
428 | status = aim_getBodies(aimInfo, &intents, &numBody, &bodies); | |||
429 | if (status != CAPS_SUCCESS0) return status; | |||
430 | ||||
431 | #ifdef DEBUG | |||
432 | printf(" nastranAIM/createVLMMesh nbody = %d!\n", numBody); | |||
433 | #endif | |||
434 | ||||
435 | if ((numBody <= 0) || (bodies == NULL((void*)0))) { | |||
436 | #ifdef DEBUG | |||
437 | printf(" nastranAIM/createVLMMesh No Bodies!\n"); | |||
438 | #endif | |||
439 | ||||
440 | return CAPS_SOURCEERR-330; | |||
441 | } | |||
442 | ||||
443 | // Get aerodynamic reference quantities | |||
444 | status = fea_retrieveAeroRef(numBody, bodies, | |||
445 | &nastranInstance->feaProblem.feaAeroRef); | |||
446 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
447 | ||||
448 | // Cleanup Aero storage first | |||
449 | if (nastranInstance->feaProblem.feaAero != NULL((void*)0)) { | |||
450 | ||||
451 | for (i = 0; i < nastranInstance->feaProblem.numAero; i++) { | |||
452 | status = destroy_feaAeroStruct(&nastranInstance->feaProblem.feaAero[i]); | |||
453 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
454 | } | |||
455 | ||||
456 | EG_free(nastranInstance->feaProblem.feaAero); | |||
457 | } | |||
458 | ||||
459 | nastranInstance->feaProblem.numAero = 0; | |||
460 | ||||
461 | // Get VLM surface information | |||
462 | if (aimInputs[VLM_Surface-1].nullVal != IsNull) { | |||
463 | ||||
464 | status = get_vlmSurface(aimInputs[VLM_Surface-1].length, | |||
465 | aimInputs[VLM_Surface-1].vals.tuple, | |||
466 | &nastranInstance->attrMap, | |||
467 | 0.0, // default Cspace | |||
468 | &numVLMSurface, | |||
469 | &vlmSurface); | |||
470 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
471 | ||||
472 | } else { | |||
473 | AIM_ERROR(aimInfo, "An analysis type of Aeroelastic set but no VLM_Surface tuple specified\n"){ aim_message(aimInfo, CERROR, 0 , "nastranAIM.c", 473, __func__ , "An analysis type of Aeroelastic set but no VLM_Surface tuple specified\n" ); }; | |||
474 | status = CAPS_NOTFOUND-303; | |||
475 | goto cleanup; | |||
476 | } | |||
477 | ||||
478 | // Get VLM control surface information | |||
479 | if (aimInputs[VLM_Control-1].nullVal == NotNull) { | |||
480 | ||||
481 | status = get_vlmControl(aimInfo, | |||
482 | aimInputs[VLM_Control-1].length, | |||
483 | aimInputs[VLM_Control-1].vals.tuple, | |||
484 | &numVLMControl, | |||
485 | &vlmControl); | |||
486 | ||||
487 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
488 | } | |||
489 | ||||
490 | printf("\nGetting FEA vortex lattice mesh\n"); | |||
491 | ||||
492 | status = vlm_getSections(aimInfo, | |||
493 | numBody, | |||
494 | bodies, | |||
495 | "Aerodynamic", | |||
496 | nastranInstance->attrMap, | |||
497 | vlmGENERIC, | |||
498 | numVLMSurface, | |||
499 | &vlmSurface); | |||
500 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
501 | if (vlmSurface == NULL((void*)0)) { | |||
502 | status = CAPS_NULLVALUE-307; | |||
503 | goto cleanup; | |||
504 | } | |||
505 | ||||
506 | for (i = 0; i < numVLMSurface; i++) { | |||
507 | ||||
508 | // Compute equal spacing | |||
509 | if (vlmSurface[i].NspanTotal > 0) | |||
510 | numSpanWise = vlmSurface[i].NspanTotal; | |||
511 | else if (vlmSurface[i].NspanSection > 0) | |||
512 | numSpanWise = (vlmSurface[i].numSection-1)*vlmSurface[i].NspanSection; | |||
513 | else { | |||
514 | AIM_ERROR(aimInfo , "Only one of numSpanTotal and numSpanPerSection can be non-zero!"){ aim_message(aimInfo, CERROR, 0 , "nastranAIM.c", 514, __func__ , "Only one of numSpanTotal and numSpanPerSection can be non-zero!" ); }; | |||
515 | AIM_ADDLINE(aimInfo, " numSpanTotal = %d", vlmSurface[i].NspanTotal){ aim_addLine(aimInfo, " numSpanTotal = %d", vlmSurface [i].NspanTotal); }; | |||
516 | AIM_ADDLINE(aimInfo, " numSpanPerSection = %d", vlmSurface[i].NspanSection){ aim_addLine(aimInfo, " numSpanPerSection = %d", vlmSurface [i].NspanSection); }; | |||
517 | status = CAPS_BADVALUE-311; | |||
518 | goto cleanup; | |||
519 | } | |||
520 | ||||
521 | status = vlm_equalSpaceSpanPanels(aimInfo, numSpanWise, | |||
522 | vlmSurface[i].numSection, | |||
523 | vlmSurface[i].vlmSection); | |||
524 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 524, __func__, 0); goto cleanup; }; | |||
525 | } | |||
526 | ||||
527 | // Split the surfaces that have more than 2 sections into a new surface | |||
528 | for (i = 0; i < numVLMSurface; i++) { | |||
529 | ||||
530 | if (vlmSurface->numSection < 2) { | |||
531 | AIM_ERROR(aimInfo, "Surface '%s' has less than two-sections!", vlmSurface[i].name){ aim_message(aimInfo, CERROR, 0 , "nastranAIM.c", 531, __func__ , "Surface '%s' has less than two-sections!", vlmSurface[i].name ); }; | |||
532 | status = CAPS_BADVALUE-311; | |||
533 | goto cleanup; | |||
534 | } | |||
535 | ||||
536 | status = get_mapAttrToIndexIndex(&nastranInstance->transferMap, | |||
537 | vlmSurface[i].name, | |||
538 | &transferIndex); | |||
539 | if (status == CAPS_NOTFOUND-303) { | |||
540 | printf("\tA corresponding capsBound name not found for \"%s\". Surface will be ignored!\n", | |||
541 | vlmSurface[i].name); | |||
542 | continue; | |||
543 | } else if (status != CAPS_SUCCESS0) goto cleanup; | |||
544 | ||||
545 | for (j = 0; j < vlmSurface[i].numSection-1; j++) { | |||
546 | ||||
547 | // Increment the number of Aero surfaces | |||
548 | nastranInstance->feaProblem.numAero += 1; | |||
549 | ||||
550 | surfaceIndex = nastranInstance->feaProblem.numAero - 1; | |||
551 | ||||
552 | // Allocate | |||
553 | if (nastranInstance->feaProblem.numAero == 1) { | |||
554 | ||||
555 | feaAeroTemp = (feaAeroStruct *) | |||
556 | EG_alloc(nastranInstance->feaProblem.numAero* | |||
557 | sizeof(feaAeroStruct)); | |||
558 | ||||
559 | } else { | |||
560 | ||||
561 | feaAeroTemp = (feaAeroStruct *) | |||
562 | EG_reall(nastranInstance->feaProblem.feaAero, | |||
563 | nastranInstance->feaProblem.numAero* | |||
564 | sizeof(feaAeroStruct)); | |||
565 | } | |||
566 | ||||
567 | if (feaAeroTemp == NULL((void*)0)) { | |||
568 | nastranInstance->feaProblem.numAero -= 1; | |||
569 | status = EGADS_MALLOC-4; | |||
570 | goto cleanup; | |||
571 | } | |||
572 | ||||
573 | nastranInstance->feaProblem.feaAero = feaAeroTemp; | |||
574 | ||||
575 | // Initiate feaAeroStruct | |||
576 | status = initiate_feaAeroStruct(&nastranInstance->feaProblem.feaAero[surfaceIndex]); | |||
577 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
578 | ||||
579 | // Get surface Name - copy from original surface | |||
580 | nastranInstance->feaProblem.feaAero[surfaceIndex].name = | |||
581 | EG_strdup(vlmSurface[i].name); | |||
582 | if (nastranInstance->feaProblem.feaAero[surfaceIndex].name == NULL((void*)0)) { | |||
583 | status = EGADS_MALLOC-4; | |||
584 | goto cleanup; | |||
585 | } | |||
586 | ||||
587 | // Get surface ID - Multiple by 1000 !! | |||
588 | nastranInstance->feaProblem.feaAero[surfaceIndex].surfaceID = | |||
589 | 1000*nastranInstance->feaProblem.numAero; | |||
590 | ||||
591 | // ADD something for coordinate systems | |||
592 | ||||
593 | // Sections aren't necessarily stored in order coming out of vlm_getSections, however sectionIndex is! | |||
594 | sectionIndex = vlmSurface[i].vlmSection[j].sectionIndex; | |||
595 | ||||
596 | // Populate vmlSurface structure | |||
597 | nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.Cspace = | |||
598 | vlmSurface[i].Cspace; | |||
599 | nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.Sspace = | |||
600 | vlmSurface[i].Sspace; | |||
601 | ||||
602 | // use the section span count for the sub-surface | |||
603 | nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.NspanTotal = | |||
604 | vlmSurface[i].vlmSection[sectionIndex].Nspan; | |||
605 | nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.Nchord = | |||
606 | vlmSurface[i].Nchord; | |||
607 | ||||
608 | // Copy section information | |||
609 | nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.numSection = 2; | |||
610 | ||||
611 | nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.vlmSection = | |||
612 | (vlmSectionStruct *) EG_alloc(2*sizeof(vlmSectionStruct)); | |||
613 | if (nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.vlmSection == NULL((void*)0)) { | |||
614 | status = EGADS_MALLOC-4; | |||
615 | goto cleanup; | |||
616 | } | |||
617 | ||||
618 | for (k = 0; k < nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.numSection; k++) { | |||
619 | ||||
620 | // Add k to section indexing variable j to get j and j+1 during iterations | |||
621 | ||||
622 | // Sections aren't necessarily stored in order coming out of vlm_getSections, however sectionIndex is! | |||
623 | sectionIndex = vlmSurface[i].vlmSection[j+k].sectionIndex; | |||
624 | ||||
625 | status = initiate_vlmSectionStruct(&nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.vlmSection[k]); | |||
626 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
627 | ||||
628 | // Copy the section data - This also copies the control data for the section | |||
629 | status = copy_vlmSectionStruct(&vlmSurface[i].vlmSection[sectionIndex], | |||
630 | &nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.vlmSection[k]); | |||
631 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
632 | ||||
633 | // Reset the sectionIndex that is keeping track of the section order. | |||
634 | nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface.vlmSection[k].sectionIndex = k; | |||
635 | } | |||
636 | ||||
637 | // transfer control surface data to sections | |||
638 | /*@-nullpass@*/ | |||
639 | status = get_ControlSurface(bodies, | |||
640 | numVLMControl, | |||
641 | vlmControl, | |||
642 | &nastranInstance->feaProblem.feaAero[surfaceIndex].vlmSurface); | |||
643 | /*@+nullpass@*/ | |||
644 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
645 | } | |||
646 | } | |||
647 | ||||
648 | if (nastranInstance->feaProblem.feaAero == NULL((void*)0)) { | |||
649 | status = CAPS_NULLVALUE-307; | |||
650 | goto cleanup; | |||
651 | } | |||
652 | // Determine which grid points are to be used for each spline | |||
653 | for (i = 0; i < nastranInstance->feaProblem.numAero; i++) { | |||
654 | ||||
655 | // Debug | |||
656 | //printf("\tDetermining grid points\n"); | |||
657 | ||||
658 | // Get the transfer index for this surface - it has already been checked to make sure the name is in the | |||
659 | // transfer index map | |||
660 | status = get_mapAttrToIndexIndex(&nastranInstance->transferMap, | |||
661 | nastranInstance->feaProblem.feaAero[i].name, | |||
662 | &transferIndex); | |||
663 | if (status != CAPS_SUCCESS0 ) goto cleanup; | |||
664 | ||||
665 | if (projectionMethod == (int) false0) { // Look for attributes | |||
666 | ||||
667 | for (j = 0; j < nastranInstance->feaProblem.feaMesh.numNode; j++) { | |||
668 | ||||
669 | if (nastranInstance->feaProblem.feaMesh.node[j].analysisType == | |||
670 | MeshStructure) { | |||
671 | feaData = (feaMeshDataStruct *) | |||
672 | nastranInstance->feaProblem.feaMesh.node[j].analysisData; | |||
673 | } else { | |||
674 | continue; | |||
675 | } | |||
676 | ||||
677 | if (feaData->transferIndex != transferIndex) continue; | |||
678 | if (feaData->transferIndex == CAPSMAGIC1234321) continue; | |||
679 | ||||
680 | ||||
681 | nastranInstance->feaProblem.feaAero[i].numGridID += 1; | |||
682 | k = nastranInstance->feaProblem.feaAero[i].numGridID; | |||
683 | ||||
684 | nastranInstance->feaProblem.feaAero[i].gridIDSet = (int *) | |||
685 | EG_reall(nastranInstance->feaProblem.feaAero[i].gridIDSet, | |||
686 | k*sizeof(int)); | |||
687 | ||||
688 | if (nastranInstance->feaProblem.feaAero[i].gridIDSet == NULL((void*)0)) { | |||
689 | status = EGADS_MALLOC-4; | |||
690 | goto cleanup; | |||
691 | } | |||
692 | ||||
693 | nastranInstance->feaProblem.feaAero[i].gridIDSet[k-1] = | |||
694 | nastranInstance->feaProblem.feaMesh.node[j].nodeID; | |||
695 | } | |||
696 | ||||
697 | } else { // Projection method | |||
698 | ||||
699 | ||||
700 | /* | |||
701 | * n = A X B Create a normal vector/ plane between A and B | |||
702 | * | |||
703 | * d_proj = C - (C * n)*n/ ||n||^2 , projection of point d on plane created by AxB | |||
704 | * | |||
705 | * p = D - (D * n)*n/ ||n||^2 , projection of point p on plane created by AxB | |||
706 | * | |||
707 | * (section 2) | |||
708 | * LE(c)---------------->TE(d) | |||
709 | * Grid Point -^ ^ -| | |||
710 | * |^ - - - | | |||
711 | * | - A - C - d_proj | |||
712 | * | D - - - | |||
713 | * | - - - (section 1 - | |||
714 | * p LE(a)----------B------->TE(b) | |||
715 | */ | |||
716 | ||||
717 | // Vector between section 2 and 1 | |||
718 | a = nastranInstance->feaProblem.feaAero[i].vlmSurface.vlmSection[0].xyzLE; | |||
719 | b = nastranInstance->feaProblem.feaAero[i].vlmSurface.vlmSection[0].xyzTE; | |||
720 | c = nastranInstance->feaProblem.feaAero[i].vlmSurface.vlmSection[1].xyzLE; | |||
721 | d = nastranInstance->feaProblem.feaAero[i].vlmSurface.vlmSection[1].xyzTE; | |||
722 | ||||
723 | // Debug | |||
724 | //printf("a = %f %f %f\n", a[0], a[1], a[2]); | |||
725 | //printf("b = %f %f %f\n", b[0], b[1], b[2]); | |||
726 | //printf("c = %f %f %f\n", c[0], c[1], c[2]); | |||
727 | //printf("d = %f %f %f\n", d[0], d[1], d[2]); | |||
728 | ||||
729 | // Vector between LE of section 1 and LE of section 2 | |||
730 | A[0] = c[0] - a[0]; | |||
731 | A[1] = c[1] - a[1]; | |||
732 | A[2] = c[2] - a[2]; | |||
733 | ||||
734 | // Vector between LE and TE of section 1 | |||
735 | B[0] = b[0] - a[0]; | |||
736 | B[1] = b[1] - a[1]; | |||
737 | B[2] = b[2] - a[2]; | |||
738 | ||||
739 | // Vector between LE of section 1 and TE of section 2 | |||
740 | C[0] = d[0] - a[0]; | |||
741 | C[1] = d[1] - a[1]; | |||
742 | C[2] = d[2] - a[2]; | |||
743 | ||||
744 | // Normal vector between A and B | |||
745 | cross_DoubleVal(A, B, N); | |||
746 | ||||
747 | // Normalize normal vector | |||
748 | n[0] = N[0]/sqrt(dot_DoubleVal(N, N)); | |||
749 | n[1] = N[1]/sqrt(dot_DoubleVal(N, N)); | |||
750 | n[2] = N[2]/sqrt(dot_DoubleVal(N, N)); | |||
751 | ||||
752 | //printf("n = %f %f %f\n", n[0], n[1], n[2]); | |||
753 | ||||
754 | // Projection of vector C on plane created by AxB | |||
755 | d_proj[0] = C[0] - dot_DoubleVal(C, n)*n[0] + a[0]; | |||
756 | d_proj[1] = C[1] - dot_DoubleVal(C, n)*n[1] + a[1]; | |||
757 | d_proj[2] = C[2] - dot_DoubleVal(C, n)*n[2] + a[2]; | |||
758 | ||||
759 | //printf("d_proj = %f %f %f\n", d_proj[0], d_proj[1], d_proj[2]); | |||
760 | ||||
761 | // Vector between LE of section 1 and TE of section 2 where the TE as been projected on A x B plane | |||
762 | C[0] = d_proj[0] - a[0]; | |||
763 | C[1] = d_proj[1] - a[1]; | |||
764 | C[2] = d_proj[2] - a[2]; | |||
765 | ||||
766 | // Area of the rectangle (first triangle) | |||
767 | cross_DoubleVal(A, C, N); | |||
768 | Area = 0.5*sqrt(N[0]*N[0] + N[1]*N[1] + N[2]*N[2]); | |||
769 | ||||
770 | // Area of the rectangle (second triangle) | |||
771 | cross_DoubleVal(C, B, N); | |||
772 | Area = 0.5*sqrt(N[0]*N[0] + N[1]*N[1] + N[2]*N[2]) + Area; | |||
773 | ||||
774 | // Debug | |||
775 | //printf("\tArea = %f\n",Area); | |||
776 | ||||
777 | for (j = 0; j < nastranInstance->feaProblem.feaMesh.numNode; j++) { | |||
778 | ||||
779 | if (nastranInstance->feaProblem.feaMesh.node[j].analysisType == | |||
780 | MeshStructure) { | |||
781 | feaData = (feaMeshDataStruct *) | |||
782 | nastranInstance->feaProblem.feaMesh.node[j].analysisData; | |||
783 | } else { | |||
784 | continue; | |||
785 | } | |||
786 | ||||
787 | if (feaData->transferIndex != transferIndex) continue; | |||
788 | if (feaData->transferIndex == CAPSMAGIC1234321) continue; | |||
789 | ||||
790 | D[0] = nastranInstance->feaProblem.feaMesh.node[j].xyz[0] - a[0]; | |||
791 | ||||
792 | D[1] = nastranInstance->feaProblem.feaMesh.node[j].xyz[1] - a[1]; | |||
793 | ||||
794 | D[2] = nastranInstance->feaProblem.feaMesh.node[j].xyz[2] - a[2]; | |||
795 | ||||
796 | // Projection of vector D on plane created by AxB | |||
797 | p[0] = D[0] - dot_DoubleVal(D, n)*n[0] + a[0]; | |||
798 | p[1] = D[1] - dot_DoubleVal(D, n)*n[1] + a[1]; | |||
799 | p[2] = D[2] - dot_DoubleVal(D, n)*n[2] + a[2]; | |||
800 | ||||
801 | // First triangle | |||
802 | A[0] = a[0] - p[0]; | |||
803 | A[1] = a[1] - p[1]; | |||
804 | A[2] = a[2] - p[2]; | |||
805 | ||||
806 | B[0] = b[0] - p[0]; | |||
807 | B[1] = b[1] - p[1]; | |||
808 | B[2] = b[2] - p[2]; | |||
809 | cross_DoubleVal(A, B, P); | |||
810 | apbArea = 0.5*sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]); | |||
811 | ||||
812 | // Second triangle | |||
813 | A[0] = a[0] - p[0]; | |||
814 | A[1] = a[1] - p[1]; | |||
815 | A[2] = a[2] - p[2]; | |||
816 | ||||
817 | B[0] = c[0] - p[0]; | |||
818 | B[1] = c[1] - p[1]; | |||
819 | B[2] = c[2] - p[2]; | |||
820 | cross_DoubleVal(A, B, P); | |||
821 | apcArea = 0.5*sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]); | |||
822 | ||||
823 | // Third triangle | |||
824 | A[0] = c[0] - p[0]; | |||
825 | A[1] = c[1] - p[1]; | |||
826 | A[2] = c[2] - p[2]; | |||
827 | ||||
828 | B[0] = d_proj[0] - p[0]; | |||
829 | B[1] = d_proj[1] - p[1]; | |||
830 | B[2] = d_proj[2] - p[2]; | |||
831 | cross_DoubleVal(A, B, P); | |||
832 | cpdArea = 0.5*sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]); | |||
833 | ||||
834 | // Fourth triangle | |||
835 | A[0] = b[0] - p[0]; | |||
836 | A[1] = b[1] - p[1]; | |||
837 | A[2] = b[2] - p[2]; | |||
838 | ||||
839 | B[0] = d_proj[0] - p[0]; | |||
840 | B[1] = d_proj[1] - p[1]; | |||
841 | B[2] = d_proj[2] - p[2]; | |||
842 | cross_DoubleVal(A, B, P); | |||
843 | bpdArea = 0.5*sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]); | |||
844 | ||||
845 | // Debug | |||
846 | //printf("Area of Triangle = %f\n", (apbArea + apcArea + cpdArea + bpdArea)); | |||
847 | //if (fabs(apbArea + apcArea + cpdArea + bpdArea - Area) > 1E-5) { | |||
848 | // printf("Point index %d\n", j); | |||
849 | // printf("\tAreas don't match - %f vs %f!!\n", Area, (apbArea + apcArea + cpdArea + bpdArea)); | |||
850 | // printf("\tPoint - %f %f %f\n", D[0] + a[0], D[1] + a[1], D[2] + a[2]); | |||
851 | // printf("\tPoint projection - %f %f %f\n", p[0], p[1], p[2]); | |||
852 | //} | |||
853 | ||||
854 | if (fabs(apbArea + apcArea + cpdArea + bpdArea - Area) > 1E-5) continue; | |||
855 | ||||
856 | nastranInstance->feaProblem.feaAero[i].numGridID += 1; | |||
857 | ||||
858 | if (nastranInstance->feaProblem.feaAero[i].numGridID == 1) { | |||
859 | nastranInstance->feaProblem.feaAero[i].gridIDSet = (int *) | |||
860 | EG_alloc(nastranInstance->feaProblem.feaAero[i].numGridID* | |||
861 | sizeof(int)); | |||
862 | } else { | |||
863 | nastranInstance->feaProblem.feaAero[i].gridIDSet = (int *) | |||
864 | EG_reall(nastranInstance->feaProblem.feaAero[i].gridIDSet, | |||
865 | nastranInstance->feaProblem.feaAero[i].numGridID* | |||
866 | sizeof(int)); | |||
867 | } | |||
868 | ||||
869 | if (nastranInstance->feaProblem.feaAero[i].gridIDSet == NULL((void*)0)) { | |||
870 | status = EGADS_MALLOC-4; | |||
871 | goto cleanup; | |||
872 | } | |||
873 | ||||
874 | nastranInstance->feaProblem.feaAero[i].gridIDSet[ | |||
875 | nastranInstance->feaProblem.feaAero[i].numGridID-1] = | |||
876 | nastranInstance->feaProblem.feaMesh.node[j].nodeID; | |||
877 | } | |||
878 | } | |||
879 | ||||
880 | printf("\tSurface %d: Number of points found for aero-spline = %d\n", | |||
881 | i+1, nastranInstance->feaProblem.feaAero[i].numGridID ); | |||
882 | } | |||
883 | ||||
884 | status = CAPS_SUCCESS0; | |||
885 | ||||
886 | cleanup: | |||
887 | ||||
888 | if (status != CAPS_SUCCESS0) | |||
889 | printf("\tcreateVLMMesh status = %d\n", status); | |||
890 | ||||
891 | if (vlmSurface != NULL((void*)0)) { | |||
892 | ||||
893 | for (i = 0; i < numVLMSurface; i++) { | |||
894 | status2 = destroy_vlmSurfaceStruct(&vlmSurface[i]); | |||
895 | if (status2 != CAPS_SUCCESS0) | |||
896 | printf("\tdestroy_vlmSurfaceStruct status = %d\n", status2); | |||
897 | } | |||
898 | } | |||
899 | ||||
900 | if (vlmSurface != NULL((void*)0)) EG_free(vlmSurface); | |||
901 | numVLMSurface = 0; | |||
902 | ||||
903 | return status; | |||
904 | } | |||
905 | ||||
906 | ||||
907 | /* ********************** Exposed AIM Functions ***************************** */ | |||
908 | ||||
909 | int aimInitialize(int inst, /*@unused@*/ const char *unitSys, void *aimInfo, | |||
910 | /*@unused@*/ void **instStore, /*@unused@*/ int *major, | |||
911 | /*@unused@*/ int *minor, int *nIn, int *nOut, | |||
912 | int *nFields, char ***fnames, int **franks, int **fInOut) | |||
913 | { | |||
914 | int *ints=NULL((void*)0), i, status = CAPS_SUCCESS0; | |||
915 | char **strs=NULL((void*)0); | |||
916 | ||||
917 | aimStorage *nastranInstance=NULL((void*)0); | |||
918 | ||||
919 | #ifdef DEBUG | |||
920 | printf("nastranAIM/aimInitialize instance = %d!\n", inst); | |||
921 | #endif | |||
922 | ||||
923 | /* specify the number of analysis input and out "parameters" */ | |||
924 | *nIn = NUMINPUT; | |||
925 | *nOut = NUMOUTPUT7; | |||
926 | if (inst == -1) return CAPS_SUCCESS0; | |||
927 | ||||
928 | /* specify the field variables this analysis can generate and consume */ | |||
929 | *nFields = 4; | |||
930 | ||||
931 | /* specify the name of each field variable */ | |||
932 | AIM_ALLOC(strs, *nFields, char *, aimInfo, status){ if (strs != ((void*)0)) { status = -4; aim_status(aimInfo, status , "nastranAIM.c", 932, __func__, 1, "AIM_ALLOC: %s != NULL", "strs" ); goto cleanup; } size_t memorysize = *nFields; strs = (char * *) EG_alloc(memorysize*sizeof(char *)); if (strs == ((void *)0)) { status = -4; aim_status(aimInfo, status, "nastranAIM.c" , 932, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "strs", memorysize, "char *"); goto cleanup; } }; | |||
933 | ||||
934 | strs[0] = EG_strdup("Displacement"); | |||
935 | strs[1] = EG_strdup("EigenVector"); | |||
936 | strs[2] = EG_strdup("EigenVector_#"); | |||
937 | strs[3] = EG_strdup("Pressure"); | |||
938 | for (i = 0; i < *nFields; i++) | |||
939 | if (strs[i] == NULL((void*)0)) { status = EGADS_MALLOC-4; goto cleanup; } | |||
940 | *fnames = strs; | |||
941 | ||||
942 | /* specify the dimension of each field variable */ | |||
943 | AIM_ALLOC(ints, *nFields, int, aimInfo, status){ if (ints != ((void*)0)) { status = -4; aim_status(aimInfo, status , "nastranAIM.c", 943, __func__, 1, "AIM_ALLOC: %s != NULL", "ints" ); goto cleanup; } size_t memorysize = *nFields; ints = (int * ) EG_alloc(memorysize*sizeof(int)); if (ints == ((void*)0)) { status = -4; aim_status(aimInfo, status, "nastranAIM.c", 943 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "ints", memorysize , "int"); goto cleanup; } }; | |||
944 | ints[0] = 3; | |||
945 | ints[1] = 3; | |||
946 | ints[2] = 3; | |||
947 | ints[3] = 1; | |||
948 | *franks = ints; | |||
949 | ints = NULL((void*)0); | |||
950 | ||||
951 | /* specify if a field is an input field or output field */ | |||
952 | AIM_ALLOC(ints, *nFields, int, aimInfo, status){ if (ints != ((void*)0)) { status = -4; aim_status(aimInfo, status , "nastranAIM.c", 952, __func__, 1, "AIM_ALLOC: %s != NULL", "ints" ); goto cleanup; } size_t memorysize = *nFields; ints = (int * ) EG_alloc(memorysize*sizeof(int)); if (ints == ((void*)0)) { status = -4; aim_status(aimInfo, status, "nastranAIM.c", 952 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "ints", memorysize , "int"); goto cleanup; } }; | |||
953 | ||||
954 | ints[0] = FieldOut; | |||
955 | ints[1] = FieldOut; | |||
956 | ints[2] = FieldOut; | |||
957 | ints[3] = FieldIn; | |||
958 | *fInOut = ints; | |||
959 | ints = NULL((void*)0); | |||
960 | ||||
961 | // Allocate nastranInstance | |||
962 | AIM_ALLOC(nastranInstance, 1, aimStorage, aimInfo, status){ if (nastranInstance != ((void*)0)) { status = -4; aim_status (aimInfo, status, "nastranAIM.c", 962, __func__, 1, "AIM_ALLOC: %s != NULL" , "nastranInstance"); goto cleanup; } size_t memorysize = 1; nastranInstance = (aimStorage *) EG_alloc(memorysize*sizeof(aimStorage)); if (nastranInstance == ((void*)0)) { status = -4; aim_status(aimInfo , status, "nastranAIM.c", 962, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "nastranInstance", memorysize, "aimStorage"); goto cleanup; } }; | |||
963 | *instStore = nastranInstance; | |||
964 | ||||
965 | // Initialize instance storage | |||
966 | (void) initiate_aimStorage(nastranInstance); | |||
967 | ||||
968 | cleanup: | |||
969 | if (status != CAPS_SUCCESS0) { | |||
970 | /* release all possibly allocated memory on error */ | |||
971 | if (*fnames != NULL((void*)0)) | |||
972 | for (i = 0; i < *nFields; i++) AIM_FREE((*fnames)[i]){ EG_free((*fnames)[i]); (*fnames)[i] = ((void*)0); }; | |||
973 | AIM_FREE(*franks){ EG_free(*franks); *franks = ((void*)0); }; | |||
974 | AIM_FREE(*fInOut){ EG_free(*fInOut); *fInOut = ((void*)0); }; | |||
975 | AIM_FREE(*fnames){ EG_free(*fnames); *fnames = ((void*)0); }; | |||
976 | AIM_FREE(*instStore){ EG_free(*instStore); *instStore = ((void*)0); }; | |||
977 | *nFields = 0; | |||
978 | } | |||
979 | ||||
980 | return status; | |||
981 | } | |||
982 | ||||
983 | ||||
984 | int aimInputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, | |||
985 | int index, char **ainame, capsValue *defval) | |||
986 | { | |||
987 | ||||
988 | /*! \page aimInputsNastran AIM Inputs | |||
989 | * The following list outlines the Nastran inputs along with their default value available | |||
990 | * through the AIM interface. Unless noted these values will be not be linked to | |||
991 | * any parent AIMs with variables of the same name. | |||
992 | */ | |||
993 | int status = CAPS_SUCCESS0; | |||
994 | ||||
995 | #ifdef DEBUG | |||
996 | printf(" nastranAIM/aimInputs index = %d!\n", index); | |||
997 | #endif | |||
998 | ||||
999 | *ainame = NULL((void*)0); | |||
1000 | ||||
1001 | // Nastran Inputs | |||
1002 | if (index == Proj_Name) { | |||
1003 | *ainame = EG_strdup("Proj_Name"); | |||
1004 | defval->type = String; | |||
1005 | defval->nullVal = NotNull; | |||
1006 | defval->vals.string = EG_strdup("nastran_CAPS"); | |||
1007 | defval->lfixed = Change; | |||
1008 | ||||
1009 | /*! \page aimInputsNastran | |||
1010 | * - <B> Proj_Name = "nastran_CAPS"</B> <br> | |||
1011 | * This corresponds to the project name used for file naming. | |||
1012 | */ | |||
1013 | ||||
1014 | } else if (index == Tess_Params) { | |||
1015 | *ainame = EG_strdup("Tess_Params"); | |||
1016 | defval->type = Double; | |||
1017 | defval->dim = Vector; | |||
1018 | defval->nrow = 3; | |||
1019 | defval->ncol = 1; | |||
1020 | defval->units = NULL((void*)0); | |||
1021 | defval->lfixed = Fixed; | |||
1022 | defval->vals.reals = (double *) EG_alloc(defval->nrow*sizeof(double)); | |||
1023 | if (defval->vals.reals != NULL((void*)0)) { | |||
1024 | defval->vals.reals[0] = 0.025; | |||
1025 | defval->vals.reals[1] = 0.001; | |||
1026 | defval->vals.reals[2] = 15.00; | |||
1027 | } else return EGADS_MALLOC-4; | |||
1028 | ||||
1029 | /*! \page aimInputsNastran | |||
1030 | * - <B> Tess_Params = [0.025, 0.001, 15.0]</B> <br> | |||
1031 | * Body tessellation parameters used when creating a boundary element model. | |||
1032 | * Tess_Params[0] and Tess_Params[1] get scaled by the bounding | |||
1033 | * box of the body. (From the EGADS manual) A set of 3 parameters that drive the EDGE discretization | |||
1034 | * and the FACE triangulation. The first is the maximum length of an EDGE segment or triangle side | |||
1035 | * (in physical space). A zero is flag that allows for any length. The second is a curvature-based | |||
1036 | * value that looks locally at the deviation between the centroid of the discrete object and the | |||
1037 | * underlying geometry. Any deviation larger than the input value will cause the tessellation to | |||
1038 | * be enhanced in those regions. The third is the maximum interior dihedral angle (in degrees) | |||
1039 | * between triangle facets (or Edge segment tangents for a WIREBODY tessellation), note that a | |||
1040 | * zero ignores this phase | |||
1041 | */ | |||
1042 | ||||
1043 | } else if (index == Edge_Point_Min) { | |||
1044 | *ainame = EG_strdup("Edge_Point_Min"); | |||
1045 | defval->type = Integer; | |||
1046 | defval->vals.integer = 2; | |||
1047 | defval->lfixed = Fixed; | |||
1048 | defval->nrow = 1; | |||
1049 | defval->ncol = 1; | |||
1050 | defval->nullVal = NotNull; | |||
1051 | ||||
1052 | /*! \page aimInputsNastran | |||
1053 | * - <B> Edge_Point_Min = 2</B> <br> | |||
1054 | * Minimum number of points on an edge including end points to use when creating a surface mesh (min 2). | |||
1055 | */ | |||
1056 | ||||
1057 | } else if (index == Edge_Point_Max) { | |||
1058 | *ainame = EG_strdup("Edge_Point_Max"); | |||
1059 | defval->type = Integer; | |||
1060 | defval->vals.integer = 50; | |||
1061 | defval->lfixed = Fixed; | |||
1062 | defval->nrow = 1; | |||
1063 | defval->ncol = 1; | |||
1064 | defval->nullVal = NotNull; | |||
1065 | ||||
1066 | /*! \page aimInputsNastran | |||
1067 | * - <B> Edge_Point_Max = 50</B> <br> | |||
1068 | * Maximum number of points on an edge including end points to use when creating a surface mesh (min 2). | |||
1069 | */ | |||
1070 | ||||
1071 | } else if (index == Quad_Mesh) { | |||
1072 | *ainame = EG_strdup("Quad_Mesh"); | |||
1073 | defval->type = Boolean; | |||
1074 | defval->vals.integer = (int) false0; | |||
1075 | ||||
1076 | /*! \page aimInputsNastran | |||
1077 | * - <B> Quad_Mesh = False</B> <br> | |||
1078 | * Create a quadratic mesh on four edge faces when creating the boundary element model. | |||
1079 | */ | |||
1080 | ||||
1081 | } else if (index == Property) { | |||
1082 | *ainame = EG_strdup("Property"); | |||
1083 | defval->type = Tuple; | |||
1084 | defval->nullVal = IsNull; | |||
1085 | //defval->units = NULL; | |||
1086 | defval->lfixed = Change; | |||
1087 | defval->vals.tuple = NULL((void*)0); | |||
1088 | defval->dim = Vector; | |||
1089 | ||||
1090 | /*! \page aimInputsNastran | |||
1091 | * - <B> Property = NULL</B> <br> | |||
1092 | * Property tuple used to input property information for the model, see \ref feaProperty for additional details. | |||
1093 | */ | |||
1094 | } else if (index == Material) { | |||
1095 | *ainame = EG_strdup("Material"); | |||
1096 | defval->type = Tuple; | |||
1097 | defval->nullVal = IsNull; | |||
1098 | //defval->units = NULL; | |||
1099 | defval->lfixed = Change; | |||
1100 | defval->vals.tuple = NULL((void*)0); | |||
1101 | defval->dim = Vector; | |||
1102 | ||||
1103 | /*! \page aimInputsNastran | |||
1104 | * - <B> Material = NULL</B> <br> | |||
1105 | * Material tuple used to input material information for the model, see \ref feaMaterial for additional details. | |||
1106 | */ | |||
1107 | } else if (index == Constraint) { | |||
1108 | *ainame = EG_strdup("Constraint"); | |||
1109 | defval->type = Tuple; | |||
1110 | defval->nullVal = IsNull; | |||
1111 | //defval->units = NULL; | |||
1112 | defval->lfixed = Change; | |||
1113 | defval->vals.tuple = NULL((void*)0); | |||
1114 | defval->dim = Vector; | |||
1115 | ||||
1116 | /*! \page aimInputsNastran | |||
1117 | * - <B> Constraint = NULL</B> <br> | |||
1118 | * Constraint tuple used to input constraint information for the model, see \ref feaConstraint for additional details. | |||
1119 | */ | |||
1120 | } else if (index == Load) { | |||
1121 | *ainame = EG_strdup("Load"); | |||
1122 | defval->type = Tuple; | |||
1123 | defval->nullVal = IsNull; | |||
1124 | //defval->units = NULL; | |||
1125 | defval->lfixed = Change; | |||
1126 | defval->vals.tuple = NULL((void*)0); | |||
1127 | defval->dim = Vector; | |||
1128 | ||||
1129 | /*! \page aimInputsNastran | |||
1130 | * - <B> Load = NULL</B> <br> | |||
1131 | * Load tuple used to input load information for the model, see \ref feaLoad for additional details. | |||
1132 | */ | |||
1133 | } else if (index == Analysix) { | |||
1134 | *ainame = EG_strdup("Analysis"); | |||
1135 | defval->type = Tuple; | |||
1136 | defval->nullVal = IsNull; | |||
1137 | //defval->units = NULL; | |||
1138 | defval->lfixed = Change; | |||
1139 | defval->vals.tuple = NULL((void*)0); | |||
1140 | defval->dim = Vector; | |||
1141 | ||||
1142 | /*! \page aimInputsNastran | |||
1143 | * - <B> Analysis = NULL</B> <br> | |||
1144 | * Analysis tuple used to input analysis/case information for the model, see \ref feaAnalysis for additional details. | |||
1145 | */ | |||
1146 | } else if (index == Analysis_Type) { | |||
1147 | *ainame = EG_strdup("Analysis_Type"); | |||
1148 | defval->type = String; | |||
1149 | defval->nullVal = NotNull; | |||
1150 | defval->vals.string = EG_strdup("Modal"); | |||
1151 | defval->lfixed = Change; | |||
1152 | ||||
1153 | /*! \page aimInputsNastran | |||
1154 | * - <B> Analysis_Type = "Modal"</B> <br> | |||
1155 | * Type of analysis to generate files for, options include "Modal", "Static", "AeroelasticTrim", "AeroelasticFlutter", and "Optimization". | |||
1156 | * Note: "Aeroelastic" and "StaticOpt" are still supported and refer to "AeroelasticTrim" and "Optimization". | |||
1157 | */ | |||
1158 | } else if (index == File_Format) { | |||
1159 | *ainame = EG_strdup("File_Format"); | |||
1160 | defval->type = String; | |||
1161 | defval->vals.string = EG_strdup("Small"); // Small, Large, Free | |||
1162 | defval->lfixed = Change; | |||
1163 | ||||
1164 | /*! \page aimInputsNastran | |||
1165 | * - <B> File_Format = "Small"</B> <br> | |||
1166 | * Formatting type for the bulk file. Options: "Small", "Large", "Free". | |||
1167 | */ | |||
1168 | ||||
1169 | } else if (index == Mesh_File_Format) { | |||
1170 | *ainame = EG_strdup("Mesh_File_Format"); | |||
1171 | defval->type = String; | |||
1172 | defval->vals.string = EG_strdup("Free"); // Small, Large, Free | |||
1173 | defval->lfixed = Change; | |||
1174 | ||||
1175 | /*! \page aimInputsNastran | |||
1176 | * - <B> Mesh_File_Format = "Small"</B> <br> | |||
1177 | * Formatting type for the mesh file. Options: "Small", "Large", "Free". | |||
1178 | */ | |||
1179 | ||||
1180 | } else if (index == Design_Variable) { | |||
1181 | *ainame = EG_strdup("Design_Variable"); | |||
1182 | defval->type = Tuple; | |||
1183 | defval->nullVal = IsNull; | |||
1184 | //defval->units = NULL; | |||
1185 | defval->lfixed = Change; | |||
1186 | defval->vals.tuple = NULL((void*)0); | |||
1187 | defval->dim = Vector; | |||
1188 | ||||
1189 | /*! \page aimInputsNastran | |||
1190 | * - <B> Design_Variable = NULL</B> <br> | |||
1191 | * The design variable tuple is used to input design variable information for the model optimization, see \ref feaDesignVariable for additional details. | |||
1192 | */ | |||
1193 | ||||
1194 | } else if (index == Design_Variable_Relation) { | |||
1195 | *ainame = EG_strdup("Design_Variable_Relation"); | |||
1196 | defval->type = Tuple; | |||
1197 | defval->nullVal = IsNull; | |||
1198 | //defval->units = NULL; | |||
1199 | defval->lfixed = Change; | |||
1200 | defval->vals.tuple = NULL((void*)0); | |||
1201 | defval->dim = Vector; | |||
1202 | ||||
1203 | /*! \page aimInputsNastran | |||
1204 | * - <B> Design_Variable_Relation = NULL</B> <br> | |||
1205 | * The design variable relation tuple is used to input design variable relation information for the model optimization, see \ref feaDesignVariableRelation for additional details. | |||
1206 | */ | |||
1207 | ||||
1208 | } else if (index == Design_Constraint) { | |||
1209 | *ainame = EG_strdup("Design_Constraint"); | |||
1210 | defval->type = Tuple; | |||
1211 | defval->nullVal = IsNull; | |||
1212 | //defval->units = NULL; | |||
1213 | defval->lfixed = Change; | |||
1214 | defval->vals.tuple = NULL((void*)0); | |||
1215 | defval->dim = Vector; | |||
1216 | ||||
1217 | /*! \page aimInputsNastran | |||
1218 | * - <B> Design_Constraint = NULL</B> <br> | |||
1219 | * The design constraint tuple is used to input design constraint information for the model optimization, see \ref feaDesignConstraint for additional details. | |||
1220 | */ | |||
1221 | ||||
1222 | } else if (index == Design_Equation) { | |||
1223 | *ainame = EG_strdup("Design_Equation"); | |||
1224 | defval->type = Tuple; | |||
1225 | defval->nullVal = IsNull; | |||
1226 | //defval->units = NULL; | |||
1227 | defval->lfixed = Change; | |||
1228 | defval->vals.tuple = NULL((void*)0); | |||
1229 | defval->dim = Vector; | |||
1230 | ||||
1231 | /*! \page aimInputsNastran | |||
1232 | * - <B> Design_Equation = NULL</B> <br> | |||
1233 | * The design equation tuple used to input information defining equations for use in design sensitivity, see \ref feaDesignEquation for additional details. | |||
1234 | */ | |||
1235 | ||||
1236 | } else if (index == Design_Table) { | |||
1237 | *ainame = EG_strdup("Design_Table"); | |||
1238 | defval->type = Tuple; | |||
1239 | defval->nullVal = IsNull; | |||
1240 | //defval->units = NULL; | |||
1241 | defval->lfixed = Change; | |||
1242 | defval->vals.tuple = NULL((void*)0); | |||
1243 | defval->dim = Vector; | |||
1244 | ||||
1245 | /*! \page aimInputsNastran | |||
1246 | * - <B> Design_Table = NULL</B> <br> | |||
1247 | * The design table tuple used to input table of real constants used in equations, see \ref feaDesignTable for additional details. | |||
1248 | */ | |||
1249 | ||||
1250 | } else if (index == Design_Response) { | |||
1251 | *ainame = EG_strdup("Design_Response"); | |||
1252 | defval->type = Tuple; | |||
1253 | defval->nullVal = IsNull; | |||
1254 | //defval->units = NULL; | |||
1255 | defval->lfixed = Change; | |||
1256 | defval->vals.tuple = NULL((void*)0); | |||
1257 | defval->dim = Vector; | |||
1258 | ||||
1259 | /*! \page aimInputsNastran | |||
1260 | * - <B> Design_Response = NULL</B> <br> | |||
1261 | * The design response tuple used to input design sensitivity response information, see \ref feaDesignResponse for additional details. | |||
1262 | */ | |||
1263 | ||||
1264 | } else if (index == Design_Equation_Response) { | |||
1265 | *ainame = EG_strdup("Design_Equation_Response"); | |||
1266 | defval->type = Tuple; | |||
1267 | defval->nullVal = IsNull; | |||
1268 | //defval->units = NULL; | |||
1269 | defval->lfixed = Change; | |||
1270 | defval->vals.tuple = NULL((void*)0); | |||
1271 | defval->dim = Vector; | |||
1272 | ||||
1273 | /*! \page aimInputsNastran | |||
1274 | * - <B> Design_Equation_Response = NULL</B> <br> | |||
1275 | * The design equation response tuple used to input design sensitivity equation response information, see \ref feaDesignEquationResponse for additional details. | |||
1276 | */ | |||
1277 | ||||
1278 | } else if (index == Design_Opt_Param) { | |||
1279 | *ainame = EG_strdup("Design_Opt_Param"); | |||
1280 | defval->type = Tuple; | |||
1281 | defval->nullVal = IsNull; | |||
1282 | //defval->units = NULL; | |||
1283 | defval->lfixed = Change; | |||
1284 | defval->vals.tuple = NULL((void*)0); | |||
1285 | defval->dim = Vector; | |||
1286 | ||||
1287 | /*! \page aimInputsNastran | |||
1288 | * - <B> Design_Opt_Param = NULL</B> <br> | |||
1289 | * The design optimization parameter tuple used to input parameters used in design optimization. | |||
1290 | */ | |||
1291 | ||||
1292 | } else if (index == ObjectiveMinMax) { | |||
1293 | *ainame = EG_strdup("ObjectiveMinMax"); | |||
1294 | defval->type = String; | |||
1295 | defval->nullVal = NotNull; | |||
1296 | defval->vals.string = EG_strdup("Max"); // Max, Min | |||
1297 | defval->lfixed = Change; | |||
1298 | ||||
1299 | /*! \page aimInputsNastran | |||
1300 | * - <B> ObjectiveMinMax = "Max"</B> <br> | |||
1301 | * Maximize or minimize the design objective during an optimization. Option: "Max" or "Min". | |||
1302 | */ | |||
1303 | ||||
1304 | } else if (index == ObjectiveResponseType) { | |||
1305 | *ainame = EG_strdup("ObjectiveResponseType"); | |||
1306 | defval->type = String; | |||
1307 | defval->nullVal = NotNull; | |||
1308 | defval->vals.string = EG_strdup("Weight"); // Weight | |||
1309 | defval->lfixed = Change; | |||
1310 | ||||
1311 | /*! \page aimInputsNastran | |||
1312 | * - <B> ObjectiveResponseType = "Weight"</B> <br> | |||
1313 | * Object response type (see Nastran manual). | |||
1314 | */ | |||
1315 | } else if (index == VLM_Surface) { | |||
1316 | *ainame = EG_strdup("VLM_Surface"); | |||
1317 | defval->type = Tuple; | |||
1318 | defval->nullVal = IsNull; | |||
1319 | //defval->units = NULL; | |||
1320 | defval->dim = Vector; | |||
1321 | defval->lfixed = Change; | |||
1322 | defval->vals.tuple = NULL((void*)0); | |||
1323 | ||||
1324 | /*! \page aimInputsNastran | |||
1325 | * - <B>VLM_Surface = NULL </B> <br> | |||
1326 | * Vortex lattice method tuple input. See \ref vlmSurface for additional details. | |||
1327 | */ | |||
1328 | } else if (index == VLM_Control) { | |||
1329 | *ainame = EG_strdup("VLM_Control"); | |||
1330 | defval->type = Tuple; | |||
1331 | defval->nullVal = IsNull; | |||
1332 | //defval->units = NULL; | |||
1333 | defval->dim = Vector; | |||
1334 | defval->lfixed = Change; | |||
1335 | defval->vals.tuple = NULL((void*)0); | |||
1336 | ||||
1337 | /*! \page aimInputsNastran | |||
1338 | * - <B>VLM_Control = NULL </B> <br> | |||
1339 | * Vortex lattice method control surface tuple input. See \ref vlmControl for additional details. | |||
1340 | */ | |||
1341 | } else if (index == Support) { | |||
1342 | *ainame = EG_strdup("Support"); | |||
1343 | defval->type = Tuple; | |||
1344 | defval->nullVal = IsNull; | |||
1345 | //defval->units = NULL; | |||
1346 | defval->lfixed = Change; | |||
1347 | defval->vals.tuple = NULL((void*)0); | |||
1348 | defval->dim = Vector; | |||
1349 | ||||
1350 | /*! \page aimInputsNastran | |||
1351 | * - <B> Support = NULL</B> <br> | |||
1352 | * Support tuple used to input support information for the model, see \ref feaSupport for additional details. | |||
1353 | */ | |||
1354 | } else if (index == Connect) { | |||
1355 | *ainame = EG_strdup("Connect"); | |||
1356 | defval->type = Tuple; | |||
1357 | defval->nullVal = IsNull; | |||
1358 | //defval->units = NULL; | |||
1359 | defval->lfixed = Change; | |||
1360 | defval->vals.tuple = NULL((void*)0); | |||
1361 | defval->dim = Vector; | |||
1362 | ||||
1363 | /*! \page aimInputsNastran | |||
1364 | * - <B> Connect = NULL</B> <br> | |||
1365 | * Connect tuple used to define connection to be made in the, see \ref feaConnection for additional details. | |||
1366 | */ | |||
1367 | } else if (index == Parameter) { | |||
1368 | *ainame = EG_strdup("Parameter"); | |||
1369 | defval->type = Tuple; | |||
1370 | defval->nullVal = IsNull; | |||
1371 | //defval->units = NULL; | |||
1372 | defval->lfixed = Change; | |||
1373 | defval->vals.tuple = NULL((void*)0); | |||
1374 | defval->dim = Vector; | |||
1375 | ||||
1376 | /*! \page aimInputsNastran | |||
1377 | * - <B> Parameter = NULL</B> <br> | |||
1378 | * Parameter tuple used to define PARAM entries. Note, entries are output exactly as inputed, that is, if the PARAM entry | |||
1379 | * requires an integer entry the user must input an integer! | |||
1380 | */ | |||
1381 | ||||
1382 | } else if (index == Mesh) { | |||
1383 | *ainame = AIM_NAME(Mesh)EG_strdup("Mesh"); | |||
1384 | defval->type = Pointer; | |||
1385 | defval->dim = Vector; | |||
1386 | defval->lfixed = Change; | |||
1387 | defval->sfixed = Change; | |||
1388 | defval->vals.AIMptr = NULL((void*)0); | |||
1389 | defval->nullVal = IsNull; | |||
1390 | AIM_STRDUP(defval->units, "meshStruct", aimInfo, status){ if (defval->units != ((void*)0)) { status = -4; aim_status (aimInfo, status, "nastranAIM.c", 1390, __func__, 1, "AIM_STRDUP: %s != NULL!" , "defval->units"); goto cleanup; } defval->units = EG_strdup ("meshStruct"); if (defval->units == ((void*)0)) { status = -4; aim_status(aimInfo, status, "nastranAIM.c", 1390, __func__ , 2, "AIM_STRDUP: %s %s", "defval->units", "meshStruct"); goto cleanup; } }; | |||
1391 | ||||
1392 | /*! \page aimInputsNastran | |||
1393 | * - <B>Mesh = NULL</B> <br> | |||
1394 | * A Mesh link. | |||
1395 | */ | |||
1396 | } | |||
1397 | ||||
1398 | AIM_NOTNULL(*ainame, aimInfo, status){ if (*ainame == ((void*)0)) { status = -307; aim_status(aimInfo , status, "nastranAIM.c", 1398, __func__, 1, "%s == NULL!", "*ainame" ); goto cleanup; } }; | |||
1399 | ||||
1400 | cleanup: | |||
1401 | if (status != CAPS_SUCCESS0) AIM_FREE(*ainame){ EG_free(*ainame); *ainame = ((void*)0); }; | |||
1402 | return status; | |||
1403 | } | |||
1404 | ||||
1405 | ||||
1406 | // ********************** AIM Function Break ***************************** | |||
1407 | int aimUpdateState(void *instStore, void *aimInfo, | |||
1408 | capsValue *aimInputs) | |||
1409 | { | |||
1410 | int status; // Function return status | |||
1411 | ||||
1412 | int found = (int)false0; | |||
1413 | int i; | |||
1414 | ||||
1415 | const char *analysisType = NULL((void*)0); | |||
1416 | const char *discipline = NULL((void*)0); | |||
1417 | ||||
1418 | const char *intents; | |||
1419 | int numBody; // Number of Bodies | |||
1420 | ego *bodies; | |||
1421 | ||||
1422 | aimStorage *nastranInstance; | |||
1423 | ||||
1424 | nastranInstance = (aimStorage *) instStore; | |||
1425 | AIM_NOTNULL(aimInputs, aimInfo, status){ if (aimInputs == ((void*)0)) { status = -307; aim_status(aimInfo , status, "nastranAIM.c", 1425, __func__, 1, "%s == NULL!", "aimInputs" ); goto cleanup; } }; | |||
1426 | ||||
1427 | ||||
1428 | // Get project name | |||
1429 | nastranInstance->projectName = aimInputs[Proj_Name-1].vals.string; | |||
1430 | ||||
1431 | // Analysis type | |||
1432 | analysisType = aimInputs[Analysis_Type-1].vals.string; | |||
1433 | ||||
1434 | // Get FEA mesh if we don't already have one | |||
1435 | if (aim_newGeometry(aimInfo) == CAPS_SUCCESS0) { | |||
1436 | ||||
1437 | status = checkAndCreateMesh(aimInfo, nastranInstance); | |||
1438 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
1439 | ||||
1440 | // Get Aeroelastic mesh | |||
1441 | if ((strcasecmp(analysisType, "Aeroelastic") == 0) || | |||
1442 | (strcasecmp(analysisType, "AeroelasticTrim") == 0) || | |||
1443 | (strcasecmp(analysisType, "AeroelasticFlutter") == 0) || | |||
1444 | (strcasecmp(analysisType, "Optimization") == 0)) { | |||
1445 | ||||
1446 | found = (int) true1; | |||
1447 | if (strcasecmp(analysisType, "Optimization") == 0) { // Is this aeroelastic optimization? | |||
1448 | found = (int) false0; | |||
1449 | ||||
1450 | status = aim_getBodies(aimInfo, &intents, &numBody, &bodies); | |||
1451 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1451, __func__, 0); goto cleanup; }; | |||
1452 | ||||
1453 | for (i = 0; i < numBody; i++) { | |||
1454 | status = retrieve_CAPSDisciplineAttr(bodies[i], &discipline); | |||
1455 | if ((status == CAPS_SUCCESS0) && (discipline != NULL((void*)0))) { | |||
1456 | if (strcasecmp(discipline, "Aerodynamic") == 0) { | |||
1457 | found = (int) true1; // We at least have aerodynamic bodies | |||
1458 | break; | |||
1459 | } | |||
1460 | } | |||
1461 | } | |||
1462 | } | |||
1463 | ||||
1464 | if (found == (int) true1) { | |||
1465 | status = createVLMMesh(aimInfo, nastranInstance, aimInputs); | |||
1466 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
1467 | } | |||
1468 | } | |||
1469 | } | |||
1470 | ||||
1471 | // Note: Setting order is important here. | |||
1472 | // 1. Materials should be set before properties. | |||
1473 | // 2. Coordinate system should be set before mesh and loads | |||
1474 | // 3. Mesh should be set before loads, constraints, supports, and connections | |||
1475 | // 4. Constraints and loads should be set before analysis | |||
1476 | // 5. Optimization should be set after properties, but before analysis | |||
1477 | ||||
1478 | // Set material properties | |||
1479 | if (aimInputs[Material-1].nullVal == NotNull) { | |||
1480 | status = fea_getMaterial(aimInfo, | |||
1481 | aimInputs[Material-1].length, | |||
1482 | aimInputs[Material-1].vals.tuple, | |||
1483 | &nastranInstance->units, | |||
1484 | &nastranInstance->feaProblem.numMaterial, | |||
1485 | &nastranInstance->feaProblem.feaMaterial); | |||
1486 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1486, __func__, 0); goto cleanup; }; | |||
1487 | } else printf("Material tuple is NULL - No materials set\n"); | |||
1488 | ||||
1489 | // Set property properties | |||
1490 | if (aimInputs[Property-1].nullVal == NotNull) { | |||
1491 | status = fea_getProperty(aimInfo, | |||
1492 | aimInputs[Property-1].length, | |||
1493 | aimInputs[Property-1].vals.tuple, | |||
1494 | &nastranInstance->attrMap, | |||
1495 | &nastranInstance->units, | |||
1496 | &nastranInstance->feaProblem); | |||
1497 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1497, __func__, 0); goto cleanup; }; | |||
1498 | ||||
1499 | ||||
1500 | // Assign element "subtypes" based on properties set | |||
1501 | status = fea_assignElementSubType(nastranInstance->feaProblem.numProperty, | |||
1502 | nastranInstance->feaProblem.feaProperty, | |||
1503 | &nastranInstance->feaProblem.feaMesh); | |||
1504 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1504, __func__, 0); goto cleanup; }; | |||
1505 | ||||
1506 | } else printf("Property tuple is NULL - No properties set\n"); | |||
1507 | ||||
1508 | // Set constraint properties | |||
1509 | if (aimInputs[Constraint-1].nullVal == NotNull) { | |||
1510 | status = fea_getConstraint(aimInputs[Constraint-1].length, | |||
1511 | aimInputs[Constraint-1].vals.tuple, | |||
1512 | &nastranInstance->constraintMap, | |||
1513 | &nastranInstance->feaProblem); | |||
1514 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1514, __func__, 0); goto cleanup; }; | |||
1515 | } else printf("Constraint tuple is NULL - No constraints applied\n"); | |||
1516 | ||||
1517 | // Set support properties | |||
1518 | if (aimInputs[Support-1].nullVal == NotNull) { | |||
1519 | status = fea_getSupport(aimInputs[Support-1].length, | |||
1520 | aimInputs[Support-1].vals.tuple, | |||
1521 | &nastranInstance->constraintMap, | |||
1522 | &nastranInstance->feaProblem); | |||
1523 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1523, __func__, 0); goto cleanup; }; | |||
1524 | } else printf("Support tuple is NULL - No supports applied\n"); | |||
1525 | ||||
1526 | // Set connection properties | |||
1527 | if (aimInputs[Connect-1].nullVal == NotNull) { | |||
1528 | status = fea_getConnection(aimInputs[Connect-1].length, | |||
1529 | aimInputs[Connect-1].vals.tuple, | |||
1530 | &nastranInstance->connectMap, | |||
1531 | &nastranInstance->feaProblem); | |||
1532 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1532, __func__, 0); goto cleanup; }; | |||
1533 | } else printf("Connect tuple is NULL - Using defaults\n"); | |||
1534 | ||||
1535 | // Set load properties | |||
1536 | if (aimInputs[Load-1].nullVal == NotNull) { | |||
1537 | status = fea_getLoad(aimInputs[Load-1].length, | |||
1538 | aimInputs[Load-1].vals.tuple, | |||
1539 | &nastranInstance->loadMap, | |||
1540 | &nastranInstance->feaProblem); | |||
1541 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1541, __func__, 0); goto cleanup; }; | |||
1542 | } else printf("Load tuple is NULL - No loads applied\n"); | |||
1543 | ||||
1544 | // Set design variables | |||
1545 | if (aimInputs[Design_Variable-1].nullVal == NotNull) { | |||
1546 | status = fea_getDesignVariable(aimInfo, | |||
1547 | (int)true1, | |||
1548 | aimInputs[Design_Variable-1].length, | |||
1549 | aimInputs[Design_Variable-1].vals.tuple, | |||
1550 | aimInputs[Design_Variable_Relation-1].length, | |||
1551 | aimInputs[Design_Variable_Relation-1].vals.tuple, | |||
1552 | &nastranInstance->attrMap, | |||
1553 | &nastranInstance->feaProblem); | |||
1554 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1554, __func__, 0); goto cleanup; }; | |||
1555 | } else printf("Design_Variable tuple is NULL - No design variables applied\n"); | |||
1556 | ||||
1557 | // Set design constraints | |||
1558 | if (aimInputs[Design_Constraint-1].nullVal == NotNull) { | |||
1559 | status = fea_getDesignConstraint(aimInputs[Design_Constraint-1].length, | |||
1560 | aimInputs[Design_Constraint-1].vals.tuple, | |||
1561 | &nastranInstance->feaProblem); | |||
1562 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1562, __func__, 0); goto cleanup; }; | |||
1563 | } else printf("Design_Constraint tuple is NULL - No design constraints applied\n"); | |||
1564 | ||||
1565 | // Set design equations | |||
1566 | if (aimInputs[Design_Equation-1].nullVal == NotNull) { | |||
1567 | status = fea_getDesignEquation(aimInputs[Design_Equation-1].length, | |||
1568 | aimInputs[Design_Equation-1].vals.tuple, | |||
1569 | &nastranInstance->feaProblem); | |||
1570 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1570, __func__, 0); goto cleanup; }; | |||
1571 | } else printf("Design_Equation tuple is NULL - No design equations applied\n"); | |||
1572 | ||||
1573 | // Set design table constants | |||
1574 | if (aimInputs[Design_Table-1].nullVal == NotNull) { | |||
1575 | status = fea_getDesignTable(aimInputs[Design_Table-1].length, | |||
1576 | aimInputs[Design_Table-1].vals.tuple, | |||
1577 | &nastranInstance->feaProblem); | |||
1578 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1578, __func__, 0); goto cleanup; }; | |||
1579 | } else printf("Design_Table tuple is NULL - No design table constants applied\n"); | |||
1580 | ||||
1581 | // Set design optimization parameters | |||
1582 | if (aimInputs[Design_Opt_Param-1].nullVal == NotNull) { | |||
1583 | status = fea_getDesignOptParam(aimInputs[Design_Opt_Param-1].length, | |||
1584 | aimInputs[Design_Opt_Param-1].vals.tuple, | |||
1585 | &nastranInstance->feaProblem); | |||
1586 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1586, __func__, 0); goto cleanup; }; | |||
1587 | } else printf("Design_Opt_Param tuple is NULL - No design optimization parameters applied\n"); | |||
1588 | ||||
1589 | // Set design responses | |||
1590 | if (aimInputs[Design_Response-1].nullVal == NotNull) { | |||
1591 | status = fea_getDesignResponse(aimInputs[Design_Response-1].length, | |||
1592 | aimInputs[Design_Response-1].vals.tuple, | |||
1593 | &nastranInstance->responseMap, | |||
1594 | &nastranInstance->feaProblem); | |||
1595 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1595, __func__, 0); goto cleanup; }; | |||
1596 | } else printf("Design_Response tuple is NULL - No design responses applied\n"); | |||
1597 | ||||
1598 | // Set design equation responses | |||
1599 | if (aimInputs[Design_Equation_Response-1].nullVal == NotNull) { | |||
1600 | status = fea_getDesignEquationResponse(aimInputs[Design_Equation_Response-1].length, | |||
1601 | aimInputs[Design_Equation_Response-1].vals.tuple, | |||
1602 | &nastranInstance->feaProblem); | |||
1603 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1603, __func__, 0); goto cleanup; }; | |||
1604 | } else printf("Design_Equation_Response tuple is NULL - No design equation responses applied\n"); | |||
1605 | ||||
1606 | // Set analysis settings | |||
1607 | if (aimInputs[Analysix-1].nullVal == NotNull) { | |||
1608 | status = fea_getAnalysis(aimInputs[Analysix-1].length, | |||
1609 | aimInputs[Analysix-1].vals.tuple, | |||
1610 | &nastranInstance->feaProblem); | |||
1611 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1611, __func__, 0); goto cleanup; }; // It ok to not have an analysis tuple | |||
1612 | } else { | |||
1613 | printf("Analysis tuple is NULL\n"); | |||
1614 | status = fea_createDefaultAnalysis(&nastranInstance->feaProblem, analysisType); | |||
1615 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1615, __func__, 0); goto cleanup; }; | |||
1616 | } | |||
1617 | ||||
1618 | ||||
1619 | // Set file format type | |||
1620 | if (strcasecmp(aimInputs[File_Format-1].vals.string, "Small") == 0) { | |||
1621 | nastranInstance->feaProblem.feaFileFormat.fileType = SmallField; | |||
1622 | } else if (strcasecmp(aimInputs[File_Format-1].vals.string, "Large") == 0) { | |||
1623 | nastranInstance->feaProblem.feaFileFormat.fileType = LargeField; | |||
1624 | } else if (strcasecmp(aimInputs[File_Format-1].vals.string, "Free") == 0) { | |||
1625 | nastranInstance->feaProblem.feaFileFormat.fileType = FreeField; | |||
1626 | } else { | |||
1627 | printf("Unrecognized \"File_Format\", valid choices are [Small, Large, or Free]. Reverting to default\n"); | |||
1628 | } | |||
1629 | ||||
1630 | // Set grid file format type | |||
1631 | if (strcasecmp(aimInputs[Mesh_File_Format-1].vals.string, "Small") == 0) { | |||
1632 | nastranInstance->feaProblem.feaFileFormat.gridFileType = SmallField; | |||
1633 | } else if (strcasecmp(aimInputs[Mesh_File_Format-1].vals.string, "Large") == 0) { | |||
1634 | nastranInstance->feaProblem.feaFileFormat.gridFileType = LargeField; | |||
1635 | } else if (strcasecmp(aimInputs[Mesh_File_Format-1].vals.string, "Free") == 0) { | |||
1636 | nastranInstance->feaProblem.feaFileFormat.gridFileType = FreeField; | |||
1637 | } else { | |||
1638 | printf("Unrecognized \"Mesh_File_Format\", valid choices are [Small, Large, or Free]. Reverting to default\n"); | |||
1639 | } | |||
1640 | ||||
1641 | status = CAPS_SUCCESS0; | |||
1642 | cleanup: | |||
1643 | return status; | |||
1644 | } | |||
1645 | ||||
1646 | int aimPreAnalysis(const void *instStore, void *aimInfo, capsValue *aimInputs) | |||
1647 | { | |||
1648 | ||||
1649 | int i, j, k, l; // Indexing | |||
1650 | ||||
1651 | int status; // Status return | |||
1652 | ||||
1653 | int found; // Boolean operator | |||
1654 | ||||
1655 | int *tempIntegerArray = NULL((void*)0); // Temporary array to store a list of integers | |||
1656 | ||||
1657 | // Analysis information | |||
1658 | int haveSubAeroelasticTrim = (int) false0; | |||
1659 | int haveSubAeroelasticFlutter = (int) false0; | |||
1660 | ||||
1661 | // Optimization Information | |||
1662 | char *objectiveMinMax = NULL((void*)0), *objectiveResp = NULL((void*)0); | |||
1663 | ||||
1664 | // Aeroelastic Information | |||
1665 | int numAEStatSurf = 0; | |||
1666 | //char **aeStatSurf = NULL; | |||
1667 | ||||
1668 | // File format information | |||
1669 | char *tempString = NULL((void*)0), *delimiter = NULL((void*)0); | |||
1670 | ||||
1671 | // File IO | |||
1672 | char *filename = NULL((void*)0); // Output file name | |||
1673 | FILE *fp = NULL((void*)0); // Output file pointer | |||
1674 | ||||
1675 | feaLoadStruct *feaLoad = NULL((void*)0); | |||
| ||||
1676 | int numThermalLoad=0; | |||
1677 | ||||
1678 | int numSetID; | |||
1679 | int tempID, *setID = NULL((void*)0); | |||
1680 | ||||
1681 | const char *analysisType = NULL((void*)0); | |||
1682 | ||||
1683 | const aimStorage *nastranInstance; | |||
1684 | ||||
1685 | nastranInstance = (const aimStorage *) instStore; | |||
1686 | AIM_NOTNULL(aimInputs, aimInfo, status){ if (aimInputs == ((void*)0)) { status = -307; aim_status(aimInfo , status, "nastranAIM.c", 1686, __func__, 1, "%s == NULL!", "aimInputs" ); goto cleanup; } }; | |||
1687 | ||||
1688 | // Analysis type | |||
1689 | analysisType = aimInputs[Analysis_Type-1].vals.string; | |||
1690 | ||||
1691 | // Write Nastran Mesh | |||
1692 | filename = EG_alloc(MXCHAR255 +1); | |||
1693 | if (filename == NULL((void*)0)) return EGADS_MALLOC-4; | |||
1694 | ||||
1695 | strcpy(filename, nastranInstance->projectName); | |||
1696 | ||||
1697 | if (nastranInstance->feaProblem.numLoad > 0) { | |||
1698 | AIM_ALLOC(feaLoad, nastranInstance->feaProblem.numLoad, feaLoadStruct, aimInfo, status){ if (feaLoad != ((void*)0)) { status = -4; aim_status(aimInfo , status, "nastranAIM.c", 1698, __func__, 1, "AIM_ALLOC: %s != NULL" , "feaLoad"); goto cleanup; } size_t memorysize = nastranInstance ->feaProblem.numLoad; feaLoad = (feaLoadStruct *) EG_alloc (memorysize*sizeof(feaLoadStruct)); if (feaLoad == ((void*)0) ) { status = -4; aim_status(aimInfo, status, "nastranAIM.c", 1698 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "feaLoad", memorysize , "feaLoadStruct"); goto cleanup; } }; | |||
1699 | for (i = 0; i < nastranInstance->feaProblem.numLoad; i++) initiate_feaLoadStruct(&feaLoad[i]); | |||
1700 | for (i = 0; i < nastranInstance->feaProblem.numLoad; i++) { | |||
1701 | status = copy_feaLoadStruct(aimInfo, &nastranInstance->feaProblem.feaLoad[i], &feaLoad[i]); | |||
1702 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1702, __func__, 0); goto cleanup; }; | |||
1703 | ||||
1704 | if (feaLoad[i].loadType == PressureExternal) { | |||
1705 | ||||
1706 | // Transfer external pressures from the AIM discrObj | |||
1707 | status = fea_transferExternalPressure(aimInfo, | |||
1708 | &nastranInstance->feaProblem.feaMesh, | |||
1709 | &feaLoad[i]); | |||
1710 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 1710, __func__, 0); goto cleanup; }; | |||
1711 | } | |||
1712 | } | |||
1713 | } | |||
1714 | ||||
1715 | status = mesh_writeNASTRAN(aimInfo, | |||
1716 | filename, | |||
1717 | 1, | |||
1718 | &nastranInstance->feaProblem.feaMesh, | |||
1719 | nastranInstance->feaProblem.feaFileFormat.gridFileType, | |||
1720 | 1.0); | |||
1721 | if (status != CAPS_SUCCESS0) { | |||
1722 | EG_free(filename); | |||
1723 | return status; | |||
1724 | } | |||
1725 | ||||
1726 | // Write Nastran subElement types not supported by mesh_writeNASTRAN | |||
1727 | strcat(filename, ".bdf"); | |||
1728 | fp = aim_fopen(aimInfo, filename, "a"); | |||
1729 | if (fp == NULL((void*)0)) { | |||
1730 | printf("Unable to open file: %s\n", filename); | |||
1731 | EG_free(filename); | |||
1732 | return CAPS_IOERR-332; | |||
1733 | } | |||
1734 | EG_free(filename); | |||
1735 | ||||
1736 | printf("Writing subElement types (if any) - appending mesh file\n"); | |||
1737 | status = nastran_writeSubElementCard(fp, | |||
1738 | &nastranInstance->feaProblem.feaMesh, | |||
1739 | nastranInstance->feaProblem.numProperty, | |||
1740 | nastranInstance->feaProblem.feaProperty, | |||
1741 | &nastranInstance->feaProblem.feaFileFormat); | |||
1742 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
1743 | ||||
1744 | // Connections | |||
1745 | for (i = 0; i < nastranInstance->feaProblem.numConnect; i++) { | |||
1746 | ||||
1747 | if (i == 0) { | |||
1748 | printf("Writing connection cards - appending mesh file\n"); | |||
1749 | } | |||
1750 | ||||
1751 | status = nastran_writeConnectionCard(fp, | |||
1752 | &nastranInstance->feaProblem.feaConnect[i], | |||
1753 | &nastranInstance->feaProblem.feaFileFormat); | |||
1754 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
1755 | } | |||
1756 | if (fp
| |||
1757 | fp = NULL((void*)0); | |||
1758 | ||||
1759 | // Write nastran input file | |||
1760 | filename = EG_alloc(MXCHAR255 +1); | |||
1761 | if (filename == NULL((void*)0)) return EGADS_MALLOC-4; | |||
1762 | strcpy(filename, nastranInstance->projectName); | |||
1763 | strcat(filename, ".dat"); | |||
1764 | ||||
1765 | printf("\nWriting Nastran instruction file....\n"); | |||
1766 | fp = aim_fopen(aimInfo, filename, "w"); | |||
1767 | if (fp == NULL((void*)0)) { | |||
1768 | AIM_ERROR(aimInfo, "Unable to open file: %s\n", filename){ aim_message(aimInfo, CERROR, 0 , "nastranAIM.c", 1768, __func__ , "Unable to open file: %s\n", filename); }; | |||
1769 | EG_free(filename); | |||
1770 | return CAPS_IOERR-332; | |||
1771 | } | |||
1772 | EG_free(filename); | |||
1773 | ||||
1774 | // define file format delimiter type | |||
1775 | if (nastranInstance->feaProblem.feaFileFormat.fileType == FreeField) { | |||
1776 | delimiter = ","; | |||
1777 | } else { | |||
1778 | delimiter = " "; | |||
1779 | } | |||
1780 | ||||
1781 | //////////////// Executive control //////////////// | |||
1782 | fprintf(fp, "ID CAPS generated Problem FOR Nastran\n"); | |||
1783 | ||||
1784 | // Analysis type | |||
1785 | if (strcasecmp(analysisType, "Modal") == 0) fprintf(fp, "SOL 3\n"); | |||
1786 | else if(strcasecmp(analysisType, "Static") == 0) fprintf(fp, "SOL 1\n"); | |||
1787 | else if(strcasecmp(analysisType, "Craig-Bampton") == 0) fprintf(fp, "SOL 31\n"); | |||
1788 | else if(strcasecmp(analysisType, "StaticOpt") == 0) fprintf(fp, "SOL 200\n"); | |||
1789 | else if(strcasecmp(analysisType, "Optimization") == 0) fprintf(fp, "SOL 200\n"); | |||
1790 | else if(strcasecmp(analysisType, "Aeroelastic") == 0) fprintf(fp, "SOL 144\n"); | |||
1791 | else if(strcasecmp(analysisType, "AeroelasticTrim") == 0) fprintf(fp, "SOL 144\n"); | |||
1792 | else if(strcasecmp(analysisType, "AeroelasticFlutter") == 0) fprintf(fp, "SOL 145\n"); | |||
1793 | else { | |||
1794 | AIM_ERROR(aimInfo, "Unrecognized \"Analysis_Type\", %s", analysisType){ aim_message(aimInfo, CERROR, 0 , "nastranAIM.c", 1794, __func__ , "Unrecognized \"Analysis_Type\", %s", analysisType); }; | |||
1795 | status = CAPS_BADVALUE-311; | |||
1796 | goto cleanup; | |||
1797 | } | |||
1798 | ||||
1799 | fprintf(fp, "CEND\n\n"); | |||
1800 | ||||
1801 | if (nastranInstance->feaProblem.feaMesh.numNode> 10000) fprintf(fp, "LINE=%d\n", nastranInstance->feaProblem.feaMesh.numNode*10); | |||
1802 | else fprintf(fp, "LINE=10000\n"); | |||
1803 | ||||
1804 | ||||
1805 | // Set up the case information | |||
1806 | if (nastranInstance->feaProblem.numAnalysis == 0) { | |||
1807 | printf("Error: No analyses in the feaProblem! (this shouldn't be possible)\n"); | |||
1808 | status = CAPS_BADVALUE-311; | |||
1809 | goto cleanup; | |||
1810 | } | |||
1811 | ||||
1812 | //////////////// Case control //////////////// | |||
1813 | ||||
1814 | // Write output request information | |||
1815 | fprintf(fp, "DISP (PRINT,PUNCH) = ALL\n"); // Output all displacements | |||
1816 | ||||
1817 | fprintf(fp, "STRE (PRINT,PUNCH) = ALL\n"); // Output all stress | |||
1818 | ||||
1819 | fprintf(fp, "STRA (PRINT,PUNCH) = ALL\n"); // Output all strain | |||
1820 | ||||
1821 | // Design objective information, SOL 200 only | |||
1822 | if ((strcasecmp(analysisType, "StaticOpt") == 0) || | |||
1823 | (strcasecmp(analysisType, "Optimization") == 0)) { | |||
1824 | ||||
1825 | objectiveMinMax = aimInputs[ObjectiveMinMax-1].vals.string; | |||
1826 | if (strcasecmp(objectiveMinMax, "Min") == 0) fprintf(fp, "DESOBJ(MIN) = 1\n"); | |||
1827 | else if(strcasecmp(objectiveMinMax, "Max") == 0) fprintf(fp, "DESOBJ(MAX) = 1\n"); | |||
1828 | else { | |||
1829 | printf("Unrecognized \"ObjectiveMinMax\", %s, defaulting to \"Min\"\n", objectiveMinMax); | |||
1830 | //objectiveMinMax = "Min"; | |||
1831 | fprintf(fp, "DESOBJ(MIN) = 1\n"); | |||
1832 | } | |||
1833 | ||||
1834 | } | |||
1835 | ||||
1836 | // Write sub-case information if multiple analysis tuples were provide - will always have at least 1 | |||
1837 | for (i = 0; i < nastranInstance->feaProblem.numAnalysis; i++) { | |||
1838 | //printf("SUBCASE = %d\n", i); | |||
1839 | ||||
1840 | fprintf(fp, "SUBCASE %d\n", i+1); | |||
1841 | fprintf(fp, "\tLABEL = %s\n", nastranInstance->feaProblem.feaAnalysis[i].name); | |||
1842 | ||||
1843 | if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == Static) { | |||
1844 | fprintf(fp,"\tANALYSIS = STATICS\n"); | |||
1845 | } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == Modal) { | |||
1846 | fprintf(fp,"\tANALYSIS = MODES\n"); | |||
1847 | } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == AeroelasticTrim) { | |||
1848 | fprintf(fp,"\tANALYSIS = SAERO\n"); | |||
1849 | haveSubAeroelasticTrim = (int) true1; | |||
1850 | } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == AeroelasticFlutter) { | |||
1851 | fprintf(fp,"\tANALYSIS = FLUTTER\n"); | |||
1852 | haveSubAeroelasticFlutter = (int) true1; | |||
1853 | } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == Optimization) { | |||
1854 | printf("\t *** WARNING :: INPUT TO ANALYSIS CASE INPUT analysisType should NOT be Optimization or StaticOpt - Defaulting to Static\n"); | |||
1855 | fprintf(fp,"\tANALYSIS = STATICS\n"); | |||
1856 | } | |||
1857 | ||||
1858 | // Write support for sub-case | |||
1859 | if (nastranInstance->feaProblem.feaAnalysis[i].numSupport != 0) { | |||
1860 | if (nastranInstance->feaProblem.feaAnalysis[i].numSupport > 1) { | |||
1861 | printf("\tWARNING: More than 1 support is not supported at this time for sub-cases!\n"); | |||
1862 | ||||
1863 | } else { | |||
1864 | fprintf(fp, "\tSUPORT1 = %d\n", nastranInstance->feaProblem.feaAnalysis[i].supportSetID[0]); | |||
1865 | } | |||
1866 | } | |||
1867 | ||||
1868 | // Write constraint for sub-case | |||
1869 | if (nastranInstance->feaProblem.numConstraint != 0) { | |||
1870 | fprintf(fp, "\tSPC = %d\n", nastranInstance->feaProblem.numConstraint+i+1); //TODO - change to i+1 to just i | |||
1871 | } | |||
1872 | ||||
1873 | // Issue some warnings regarding constraints if necessary | |||
1874 | if (nastranInstance->feaProblem.feaAnalysis[i].numConstraint == 0 && nastranInstance->feaProblem.numConstraint !=0) { | |||
1875 | ||||
1876 | printf("\tWarning: No constraints specified for case %s, assuming " | |||
1877 | "all constraints are applied!!!!\n", nastranInstance->feaProblem.feaAnalysis[i].name); | |||
1878 | ||||
1879 | } else if (nastranInstance->feaProblem.numConstraint
| |||
1880 | ||||
1881 | printf("\tWarning: No constraints specified for case %s!!!!\n", nastranInstance->feaProblem.feaAnalysis[i].name); | |||
1882 | } | |||
1883 | ||||
1884 | // // Write MPC for sub-case - currently only supported when we have RBE2 elements - see above for unification - TODO - investigate | |||
1885 | // for (j = 0; j < astrosInstance[iIndex].feaProblem.numConnect; j++) { | |||
1886 | // | |||
1887 | // if (astrosInstance[iIndex].feaProblem.feaConnect[j].connectionType == RigidBody) { | |||
1888 | // | |||
1889 | // if (addComma == (int) true) fprintf(fp,","); | |||
1890 | // | |||
1891 | // fprintf(fp, " MPC = %d ", astrosInstance[iIndex].feaProblem.feaConnect[j].connectionID); | |||
1892 | // addComma = (int) true; | |||
1893 | // break; | |||
1894 | // } | |||
1895 | // } | |||
1896 | ||||
1897 | if (nastranInstance->feaProblem.feaAnalysis[i].analysisType
| |||
1898 | fprintf(fp,"\tMETHOD = %d\n", nastranInstance->feaProblem.feaAnalysis[i].analysisID); | |||
1899 | } | |||
1900 | ||||
1901 | if (nastranInstance->feaProblem.feaAnalysis[i].analysisType
| |||
1902 | fprintf(fp,"\tMETHOD = %d\n", nastranInstance->feaProblem.feaAnalysis[i].analysisID); | |||
1903 | fprintf(fp,"\tFMETHOD = %d\n", 100+nastranInstance->feaProblem.feaAnalysis[i].analysisID); | |||
1904 | } | |||
1905 | ||||
1906 | if (nastranInstance->feaProblem.feaAnalysis[i].analysisType
| |||
1907 | fprintf(fp,"\tTRIM = %d\n", nastranInstance->feaProblem.feaAnalysis[i].analysisID); | |||
1908 | } | |||
1909 | ||||
1910 | if (nastranInstance->feaProblem.feaAnalysis[i].analysisType
| |||
1911 | nastranInstance->feaProblem.feaAnalysis[i].analysisType
| |||
1912 | ||||
1913 | if (nastranInstance->feaProblem.feaAnalysis[i].aeroSymmetryXY != NULL((void*)0)) { | |||
1914 | ||||
1915 | if(strcmp("SYM",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXY) == 0) { | |||
1916 | fprintf(fp,"\tAESYMXY = %s\n","SYMMETRIC"); | |||
1917 | } else if(strcmp("ANTISYM",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXY) == 0) { | |||
1918 | fprintf(fp,"\tAESYMXY = %s\n","ANTISYMMETRIC"); | |||
1919 | } else if(strcmp("ASYM",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXY) == 0) { | |||
1920 | fprintf(fp,"\tAESYMXY = %s\n","ASYMMETRIC"); | |||
1921 | } else if(strcmp("SYMMETRIC",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXY) == 0) { | |||
1922 | fprintf(fp,"\tAESYMXY = %s\n","SYMMETRIC"); | |||
1923 | } else if(strcmp("ANTISYMMETRIC",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXY) == 0) { | |||
1924 | fprintf(fp,"\tAESYMXY = %s\n","ANTISYMMETRIC"); | |||
1925 | } else if(strcmp("ASYMMETRIC",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXY) == 0) { | |||
1926 | fprintf(fp,"\tAESYMXY = %s\n","ASYMMETRIC"); | |||
1927 | } else { | |||
1928 | printf("\t*** Warning *** aeroSymmetryXY Input %s to nastranAIM not understood!\n",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXY ); | |||
1929 | } | |||
1930 | } | |||
1931 | ||||
1932 | if (nastranInstance->feaProblem.feaAnalysis[i].aeroSymmetryXZ != NULL((void*)0)) { | |||
1933 | ||||
1934 | if(strcmp("SYM",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXZ) == 0) { | |||
1935 | fprintf(fp,"\tAESYMXZ = %s\n","SYMMETRIC"); | |||
1936 | } else if(strcmp("ANTISYM",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXZ) == 0) { | |||
1937 | fprintf(fp,"\tAESYMXZ = %s\n","ANTISYMMETRIC"); | |||
1938 | } else if(strcmp("ASYM",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXZ) == 0) { | |||
1939 | fprintf(fp,"\tAESYMXZ = %s\n","ASYMMETRIC"); | |||
1940 | } else if(strcmp("SYMMETRIC",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXZ) == 0) { | |||
1941 | fprintf(fp,"\tAESYMXZ = %s\n","SYMMETRIC"); | |||
1942 | } else if(strcmp("ANTISYMMETRIC",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXZ) == 0) { | |||
1943 | fprintf(fp,"\tAESYMXZ = %s\n","ANTISYMMETRIC"); | |||
1944 | } else if(strcmp("ASYMMETRIC",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXZ) == 0) { | |||
1945 | fprintf(fp,"\tAESYMXZ = %s\n","ASYMMETRIC"); | |||
1946 | } else { | |||
1947 | printf("\t*** Warning *** aeroSymmetryXZ Input %s to nastranAIM not understood!\n",nastranInstance->feaProblem.feaAnalysis->aeroSymmetryXZ ); | |||
1948 | } | |||
1949 | ||||
1950 | } | |||
1951 | } | |||
1952 | ||||
1953 | // Issue some warnings regarding loads if necessary | |||
1954 | if (nastranInstance->feaProblem.feaAnalysis[i].numLoad == 0 && nastranInstance->feaProblem.numLoad !=0) { | |||
1955 | printf("\tWarning: No loads specified for case %s, assuming " | |||
1956 | "all loads are applied!!!!\n", nastranInstance->feaProblem.feaAnalysis[i].name); | |||
1957 | } else if (nastranInstance->feaProblem.numLoad == 0) { | |||
1958 | printf("\tWarning: No loads specified for case %s!!!!\n", nastranInstance->feaProblem.feaAnalysis[i].name); | |||
1959 | } | |||
1960 | ||||
1961 | // Write loads for sub-case | |||
1962 | if (nastranInstance->feaProblem.numLoad
| |||
1963 | ||||
1964 | found = (int) false0; | |||
1965 | ||||
1966 | for (k = 0; k < nastranInstance->feaProblem.numLoad; k++) { | |||
1967 | ||||
1968 | if (nastranInstance->feaProblem.feaAnalysis[i].numLoad
| |||
1969 | ||||
1970 | for (j = 0; j < nastranInstance->feaProblem.feaAnalysis[i].numLoad; j++) { // See if the load is in the loadSet | |||
1971 | ||||
1972 | if (feaLoad[k].loadID == nastranInstance->feaProblem.feaAnalysis[i].loadSetID[j]) break; | |||
| ||||
1973 | } | |||
1974 | ||||
1975 | if (j >= nastranInstance->feaProblem.feaAnalysis[i].numLoad) continue; // If it isn't in the loadSet move on | |||
1976 | } else { | |||
1977 | //pass | |||
1978 | } | |||
1979 | ||||
1980 | if (feaLoad[k].loadType == Thermal && numThermalLoad == 0) { | |||
1981 | ||||
1982 | fprintf(fp, "\tTemperature = %d\n", feaLoad[k].loadID); | |||
1983 | numThermalLoad += 1; | |||
1984 | if (numThermalLoad > 1) { | |||
1985 | printf("More than 1 Thermal load found - nastranAIM does NOT currently doesn't support multiple thermal loads in a given case!\n"); | |||
1986 | } | |||
1987 | ||||
1988 | continue; | |||
1989 | } | |||
1990 | ||||
1991 | found = (int) true1; | |||
1992 | } | |||
1993 | ||||
1994 | if (found == (int) true1) { | |||
1995 | fprintf(fp, "\tLOAD = %d\n", nastranInstance->feaProblem.numLoad+i+1); | |||
1996 | } | |||
1997 | } | |||
1998 | ||||
1999 | //if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == Optimization) { | |||
2000 | // Write objective function | |||
2001 | //fprintf(fp, "\tDESOBJ(%s) = %d\n", nastranInstance->feaProblem.feaAnalysis[i].objectiveMinMax, | |||
2002 | // nastranInstance->feaProblem.feaAnalysis[i].analysisID); | |||
2003 | // Write optimization constraints | |||
2004 | if (nastranInstance->feaProblem.feaAnalysis[i].numDesignConstraint != 0) { | |||
2005 | fprintf(fp, "\tDESSUB = %d\n", nastranInstance->feaProblem.numDesignConstraint+i+1); | |||
2006 | } | |||
2007 | //} | |||
2008 | ||||
2009 | // Write response spanning for sub-case | |||
2010 | if (nastranInstance->feaProblem.feaAnalysis[i].numDesignResponse != 0) { | |||
2011 | ||||
2012 | numSetID = nastranInstance->feaProblem.feaAnalysis[i].numDesignResponse; | |||
2013 | // setID = nastranInstance->feaProblem.feaAnalysis[i].designResponseSetID; | |||
2014 | setID = EG_alloc(numSetID * sizeof(int)); | |||
2015 | if (setID == NULL((void*)0)) { | |||
2016 | status = EGADS_MALLOC-4; | |||
2017 | goto cleanup; | |||
2018 | } | |||
2019 | ||||
2020 | for (j = 0; j < numSetID; j++) { | |||
2021 | tempID = nastranInstance->feaProblem.feaAnalysis[i].designResponseSetID[j]; | |||
2022 | setID[j] = tempID + 100000; | |||
2023 | } | |||
2024 | ||||
2025 | tempID = i+1; | |||
2026 | status = nastran_writeSetCard(fp, tempID, numSetID, setID); | |||
2027 | ||||
2028 | EG_free(setID); | |||
2029 | ||||
2030 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 2030, __func__, 0); goto cleanup; }; | |||
2031 | fprintf(fp, "\tDRSPAN = %d\n", tempID); | |||
2032 | } | |||
2033 | ||||
2034 | } | |||
2035 | ||||
2036 | // | |||
2037 | // // Check thermal load - currently only a single thermal load is supported - also it only works for the global level - no subcase | |||
2038 | // found = (int) false; | |||
2039 | // for (i = 0; i < nastranInstance->feaProblem.numLoad; i++) { | |||
2040 | // | |||
2041 | // if (feaLoad[i].loadType != Thermal) continue; | |||
2042 | // | |||
2043 | // if (found == (int) true) { | |||
2044 | // printf("More than 1 Thermal load found - nastranAIM does NOT currently doesn't support multiple thermal loads!\n"); | |||
2045 | // } | |||
2046 | // | |||
2047 | // found = (int) true; | |||
2048 | // | |||
2049 | // fprintf(fp, "TEMPERATURE = %d\n", feaLoad[i].loadID); | |||
2050 | // } | |||
2051 | // | |||
2052 | // // Design objective information, SOL 200 only | |||
2053 | // if ((strcasecmp(analysisType, "StaticOpt") == 0) || (strcasecmp(analysisType, "Optimization") == 0)) { | |||
2054 | // | |||
2055 | // objectiveMinMax = aimInputs[ObjectiveMinMax-1].vals.string; | |||
2056 | // if (strcasecmp(objectiveMinMax, "Min") == 0) fprintf(fp, "DESOBJ(MIN) = 1\n"); | |||
2057 | // else if(strcasecmp(objectiveMinMax, "Max") == 0) fprintf(fp, "DESOBJ(MAX) = 1\n"); | |||
2058 | // else { | |||
2059 | // printf("Unrecognized \"ObjectiveMinMax\", %s, defaulting to \"Min\"\n", objectiveMinMax); | |||
2060 | // objectiveMinMax = "Min"; | |||
2061 | // fprintf(fp, "DESOBJ(MIN) = 1\n"); | |||
2062 | // } | |||
2063 | // | |||
2064 | // } | |||
2065 | // | |||
2066 | // // Modal analysis - only | |||
2067 | // // If modal - we are only going to use the first analysis structure we come across that has its type as modal | |||
2068 | // if (strcasecmp(analysisType, "Modal") == 0) { | |||
2069 | // | |||
2070 | // // Look through analysis structures for a modal one | |||
2071 | // found = (int) false; | |||
2072 | // for (i = 0; i < nastranInstance->feaProblem.numAnalysis; i++) { | |||
2073 | // if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == Modal) { | |||
2074 | // found = (int) true; | |||
2075 | // break; | |||
2076 | // } | |||
2077 | // } | |||
2078 | // | |||
2079 | // // Write out analysis ID if a modal analysis structure was found | |||
2080 | // if (found == (int) true) { | |||
2081 | // fprintf(fp, "METHOD = %d\n", nastranInstance->feaProblem.feaAnalysis[i].analysisID); | |||
2082 | // } else { | |||
2083 | // printf("Warning: No eigenvalue analysis information specified in \"Analysis\" tuple, through " | |||
2084 | // "AIM input \"Analysis_Type\" is set to \"Modal\"!!!!\n"); | |||
2085 | // status = CAPS_NOTFOUND; | |||
2086 | // goto cleanup; | |||
2087 | // } | |||
2088 | // | |||
2089 | // // Write support for sub-case | |||
2090 | // if (nastranInstance->feaProblem.feaAnalysis[i].numSupport != 0) { | |||
2091 | // if (nastranInstance->feaProblem.feaAnalysis[i].numSupport > 1) { | |||
2092 | // printf("\tWARNING: More than 1 support is not supported at this time for sub-cases!\n"); | |||
2093 | // | |||
2094 | // } else { | |||
2095 | // fprintf(fp, "SUPORT1 = %d\n", nastranInstance->feaProblem.feaAnalysis[i].supportSetID[0]); | |||
2096 | // } | |||
2097 | // } | |||
2098 | // | |||
2099 | // // Write constraint for sub-case | |||
2100 | // if (nastranInstance->feaProblem.numConstraint != 0) { | |||
2101 | // fprintf(fp, "SPC = %d\n", nastranInstance->feaProblem.numConstraint+i+1); | |||
2102 | // } | |||
2103 | // | |||
2104 | // // Issue some warnings regarding constraints if necessary | |||
2105 | // if (nastranInstance->feaProblem.feaAnalysis[i].numConstraint == 0 && nastranInstance->feaProblem.numConstraint !=0) { | |||
2106 | // printf("\tWarning: No constraints specified for modal case %s, assuming " | |||
2107 | // "all constraints are applied!!!!\n", nastranInstance->feaProblem.feaAnalysis[i].name); | |||
2108 | // } else if (nastranInstance->feaProblem.numConstraint == 0) { | |||
2109 | // printf("\tWarning: No constraints specified for modal case %s!!!!\n", nastranInstance->feaProblem.feaAnalysis[i].name); | |||
2110 | // } | |||
2111 | // | |||
2112 | // } | |||
2113 | ||||
2114 | // } else { // If no sub-cases | |||
2115 | // | |||
2116 | // if (nastranInstance->feaProblem.numSupport != 0) { | |||
2117 | // if (nastranInstance->feaProblem.numSupport > 1) { | |||
2118 | // printf("\tWARNING: More than 1 support is not supported at this time for a given case!\n"); | |||
2119 | // } else { | |||
2120 | // fprintf(fp, "SUPORT1 = %d ", nastranInstance->feaProblem.numSupport+1); | |||
2121 | // } | |||
2122 | // } | |||
2123 | // | |||
2124 | // // Write constraint information | |||
2125 | // if (nastranInstance->feaProblem.numConstraint != 0) { | |||
2126 | // fprintf(fp, "SPC = %d\n", nastranInstance->feaProblem.numConstraint+1); | |||
2127 | // } else { | |||
2128 | // printf("\tWarning: No constraints specified for job!!!!\n"); | |||
2129 | // } | |||
2130 | // | |||
2131 | // // Write load card | |||
2132 | // if (nastranInstance->feaProblem.numLoad != 0) { | |||
2133 | // fprintf(fp, "LOAD = %d\n", nastranInstance->feaProblem.numLoad+1); | |||
2134 | // } else { | |||
2135 | // printf("\tWarning: No loads specified for job!!!!\n"); | |||
2136 | // } | |||
2137 | // | |||
2138 | // // What about an objective function if no analysis tuple? Do we need to add a new capsValue? | |||
2139 | // | |||
2140 | // // Write design constraints | |||
2141 | // if (nastranInstance->feaProblem.numDesignConstraint != 0) { | |||
2142 | // fprintf(fp, "\tDESSUB = %d\n", nastranInstance->feaProblem.numDesignConstraint+1); | |||
2143 | // } | |||
2144 | // } | |||
2145 | // } | |||
2146 | ||||
2147 | ||||
2148 | //////////////// Bulk data //////////////// | |||
2149 | fprintf(fp, "\nBEGIN BULK\n"); | |||
2150 | fprintf(fp, "$---1---|---2---|---3---|---4---|---5---|---6---|---7---|---8---|---9---|---10--|\n"); | |||
2151 | //PRINT PARAM ENTRIES IN BULK DATA | |||
2152 | ||||
2153 | if (aimInputs[Parameter-1].nullVal == NotNull) { | |||
2154 | for (i = 0; i < aimInputs[Parameter-1].length; i++) { | |||
2155 | fprintf(fp, "PARAM, %s, %s\n", aimInputs[Parameter-1].vals.tuple[i].name, | |||
2156 | aimInputs[Parameter-1].vals.tuple[i].value); | |||
2157 | } | |||
2158 | } | |||
2159 | ||||
2160 | fprintf(fp, "PARAM, %s\n", "POST, -1\n"); // Output OP2 file | |||
2161 | ||||
2162 | // Turn off auto SPC | |||
2163 | //fprintf(fp, "%-8s %7s %7s\n", "PARAM", "AUTOSPC", "N"); | |||
2164 | ||||
2165 | // Optimization Objective Response Response, SOL 200 only | |||
2166 | if (strcasecmp(analysisType, "StaticOpt") == 0 || strcasecmp(analysisType, "Optimization") == 0) { | |||
2167 | ||||
2168 | objectiveResp = aimInputs[ObjectiveResponseType-1].vals.string; | |||
2169 | if (strcasecmp(objectiveResp, "Weight") == 0) objectiveResp = "WEIGHT"; | |||
2170 | else { | |||
2171 | printf("\tUnrecognized \"ObjectiveResponseType\", %s, defaulting to \"Weight\"\n", objectiveResp); | |||
2172 | objectiveResp = "WEIGHT"; | |||
2173 | } | |||
2174 | ||||
2175 | fprintf(fp,"%-8s", "DRESP1"); | |||
2176 | ||||
2177 | tempString = convert_integerToString(1, 7, 1); | |||
2178 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "nastranAIM.c", 2178, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; | |||
2179 | fprintf(fp, "%s%s", delimiter, tempString); | |||
2180 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; | |||
2181 | ||||
2182 | fprintf(fp, "%s%7s", delimiter, objectiveResp); | |||
2183 | fprintf(fp, "%s%7s", delimiter, objectiveResp); | |||
2184 | ||||
2185 | ||||
2186 | fprintf(fp, "\n"); | |||
2187 | } | |||
2188 | ||||
2189 | // Write AEROS, AESTAT and AESURF cards | |||
2190 | if (strcasecmp(analysisType, "AeroelasticFlutter") == 0 || | |||
2191 | haveSubAeroelasticFlutter == (int) true1) { | |||
2192 | ||||
2193 | printf("\tWriting aero card\n"); | |||
2194 | status = nastran_writeAEROCard(fp, | |||
2195 | &nastranInstance->feaProblem.feaAeroRef, | |||
2196 | &nastranInstance->feaProblem.feaFileFormat); | |||
2197 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 2197, __func__, 0); goto cleanup; }; | |||
2198 | } | |||
2199 | ||||
2200 | // Write AEROS, AESTAT and AESURF cards | |||
2201 | if (strcasecmp(analysisType, "Aeroelastic") == 0 || | |||
2202 | strcasecmp(analysisType, "AeroelasticTrim") == 0 || | |||
2203 | haveSubAeroelasticTrim == (int) true1) { | |||
2204 | ||||
2205 | printf("\tWriting aeros card\n"); | |||
2206 | status = nastran_writeAEROSCard(fp, | |||
2207 | &nastranInstance->feaProblem.feaAeroRef, | |||
2208 | &nastranInstance->feaProblem.feaFileFormat); | |||
2209 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 2209, __func__, 0); goto cleanup; }; | |||
2210 | ||||
2211 | numAEStatSurf = 0; | |||
2212 | for (i = 0; i < nastranInstance->feaProblem.numAnalysis; i++) { | |||
2213 | ||||
2214 | if (nastranInstance->feaProblem.feaAnalysis[i].analysisType != AeroelasticTrim) continue; | |||
2215 | ||||
2216 | if (i == 0) printf("\tWriting aestat cards\n"); | |||
2217 | ||||
2218 | // Loop over rigid variables | |||
2219 | for (j = 0; j < nastranInstance->feaProblem.feaAnalysis[i].numRigidVariable; j++) { | |||
2220 | ||||
2221 | found = (int) false0; | |||
2222 | ||||
2223 | // Loop over previous rigid variables | |||
2224 | for (k = 0; k < i; k++) { | |||
2225 | for (l = 0; l < nastranInstance->feaProblem.feaAnalysis[k].numRigidVariable; l++) { | |||
2226 | ||||
2227 | // If current rigid variable was previous written - mark as found | |||
2228 | if (strcmp(nastranInstance->feaProblem.feaAnalysis[i].rigidVariable[j], | |||
2229 | nastranInstance->feaProblem.feaAnalysis[k].rigidVariable[l]) == 0) { | |||
2230 | found = (int) true1; | |||
2231 | break; | |||
2232 | } | |||
2233 | } | |||
2234 | } | |||
2235 | ||||
2236 | // If already found continue | |||
2237 | if (found == (int) true1) continue; | |||
2238 | ||||
2239 | // If not write out an aestat card | |||
2240 | numAEStatSurf += 1; | |||
2241 | ||||
2242 | fprintf(fp,"%-8s", "AESTAT"); | |||
2243 | ||||
2244 | tempString = convert_integerToString(numAEStatSurf, 7, 1); | |||
2245 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "nastranAIM.c", 2245, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; | |||
2246 | fprintf(fp, "%s%s", delimiter, tempString); | |||
2247 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; | |||
2248 | ||||
2249 | fprintf(fp, "%s%7s\n", delimiter, nastranInstance->feaProblem.feaAnalysis[i].rigidVariable[j]); | |||
2250 | } | |||
2251 | ||||
2252 | // Loop over rigid Constraints | |||
2253 | for (j = 0; j < nastranInstance->feaProblem.feaAnalysis[i].numRigidConstraint; j++) { | |||
2254 | ||||
2255 | found = (int) false0; | |||
2256 | ||||
2257 | // Loop over previous rigid constraints | |||
2258 | for (k = 0; k < i; k++) { | |||
2259 | for (l = 0; l < nastranInstance->feaProblem.feaAnalysis[k].numRigidConstraint; l++) { | |||
2260 | ||||
2261 | // If current rigid constraint was previous written - mark as found | |||
2262 | if (strcmp(nastranInstance->feaProblem.feaAnalysis[i].rigidConstraint[j], | |||
2263 | nastranInstance->feaProblem.feaAnalysis[k].rigidConstraint[l]) == 0) { | |||
2264 | found = (int) true1; | |||
2265 | break; | |||
2266 | } | |||
2267 | } | |||
2268 | } | |||
2269 | ||||
2270 | // If already found continue | |||
2271 | if (found == (int) true1) continue; | |||
2272 | ||||
2273 | // Make sure constraint isn't already in rigid variables too! | |||
2274 | for (k = 0; k < i; k++) { | |||
2275 | for (l = 0; l < nastranInstance->feaProblem.feaAnalysis[k].numRigidVariable; l++) { | |||
2276 | ||||
2277 | // If current rigid constraint was previous written - mark as found | |||
2278 | if (strcmp(nastranInstance->feaProblem.feaAnalysis[i].rigidConstraint[j], | |||
2279 | nastranInstance->feaProblem.feaAnalysis[k].rigidVariable[l]) == 0) { | |||
2280 | found = (int) true1; | |||
2281 | break; | |||
2282 | } | |||
2283 | } | |||
2284 | } | |||
2285 | ||||
2286 | // If already found continue | |||
2287 | if (found == (int) true1) continue; | |||
2288 | ||||
2289 | // If not write out an aestat card | |||
2290 | numAEStatSurf += 1; | |||
2291 | ||||
2292 | fprintf(fp,"%-8s", "AESTAT"); | |||
2293 | ||||
2294 | tempString = convert_integerToString(numAEStatSurf, 7, 1); | |||
2295 | AIM_NOTNULL(tempString, aimInfo, status){ if (tempString == ((void*)0)) { status = -307; aim_status(aimInfo , status, "nastranAIM.c", 2295, __func__, 1, "%s == NULL!", "tempString" ); goto cleanup; } }; | |||
2296 | fprintf(fp, "%s%s", delimiter, tempString); | |||
2297 | AIM_FREE(tempString){ EG_free(tempString); tempString = ((void*)0); }; | |||
2298 | ||||
2299 | fprintf(fp, "%s%7s\n", delimiter, nastranInstance->feaProblem.feaAnalysis[i].rigidConstraint[j]); | |||
2300 | } | |||
2301 | } | |||
2302 | ||||
2303 | fprintf(fp,"\n"); | |||
2304 | } | |||
2305 | ||||
2306 | // Analysis Cards - Eigenvalue and design objective included, as well as combined load, constraint, and design constraints | |||
2307 | for (i = 0; i < nastranInstance->feaProblem.numAnalysis; i++) { | |||
2308 | ||||
2309 | if (i == 0) printf("\tWriting analysis cards\n"); | |||
2310 | ||||
2311 | status = nastran_writeAnalysisCard(fp, | |||
2312 | &nastranInstance->feaProblem.feaAnalysis[i], | |||
2313 | &nastranInstance->feaProblem.feaFileFormat); | |||
2314 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 2314, __func__, 0); goto cleanup; }; | |||
2315 | ||||
2316 | if (nastranInstance->feaProblem.feaAnalysis[i].numLoad != 0) { | |||
2317 | ||||
2318 | // Create a temporary list of load IDs | |||
2319 | tempIntegerArray = (int *) EG_alloc(nastranInstance->feaProblem.feaAnalysis[i].numLoad*sizeof(int)); | |||
2320 | if (tempIntegerArray == NULL((void*)0)) { | |||
2321 | status = EGADS_MALLOC-4; | |||
2322 | goto cleanup; | |||
2323 | } | |||
2324 | ||||
2325 | k = 0; | |||
2326 | for (j = 0; j < nastranInstance->feaProblem.feaAnalysis[i].numLoad; j++) { | |||
2327 | for (l = 0; l < nastranInstance->feaProblem.numLoad; l++) { | |||
2328 | if (nastranInstance->feaProblem.feaAnalysis[i].loadSetID[j] == feaLoad[l].loadID) break; | |||
2329 | } | |||
2330 | if (feaLoad[l].loadType == Thermal) continue; | |||
2331 | tempIntegerArray[j] = feaLoad[l].loadID; | |||
2332 | k += 1; | |||
2333 | } | |||
2334 | ||||
2335 | tempIntegerArray = (int *) EG_reall(tempIntegerArray, k*sizeof(int)); | |||
2336 | if (tempIntegerArray == NULL((void*)0)) { | |||
2337 | status = EGADS_MALLOC-4; | |||
2338 | goto cleanup; | |||
2339 | } | |||
2340 | ||||
2341 | // Write combined load card | |||
2342 | printf("\tWriting load ADD cards\n"); | |||
2343 | status = nastran_writeLoadADDCard(fp, | |||
2344 | nastranInstance->feaProblem.numLoad+i+1, | |||
2345 | k, | |||
2346 | tempIntegerArray, | |||
2347 | feaLoad, | |||
2348 | &nastranInstance->feaProblem.feaFileFormat); | |||
2349 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2350 | ||||
2351 | // Free temporary load ID list | |||
2352 | EG_free(tempIntegerArray); | |||
2353 | tempIntegerArray = NULL((void*)0); | |||
2354 | ||||
2355 | } else { // If no loads for an individual analysis are specified assume that all loads should be applied | |||
2356 | ||||
2357 | if (nastranInstance->feaProblem.numLoad != 0) { | |||
2358 | ||||
2359 | // Create a temporary list of load IDs | |||
2360 | tempIntegerArray = (int *) EG_alloc(nastranInstance->feaProblem.numLoad*sizeof(int)); | |||
2361 | if (tempIntegerArray == NULL((void*)0)) { | |||
2362 | status = EGADS_MALLOC-4; | |||
2363 | goto cleanup; | |||
2364 | } | |||
2365 | ||||
2366 | k = 0; | |||
2367 | for (j = 0; j < nastranInstance->feaProblem.numLoad; j++) { | |||
2368 | if (feaLoad[j].loadType == Gravity) continue; | |||
2369 | tempIntegerArray[j] = feaLoad[j].loadID; | |||
2370 | k += 1; | |||
2371 | } | |||
2372 | ||||
2373 | AIM_ERROR(aimInfo, "Writing load ADD cards is not properly implemented!"){ aim_message(aimInfo, CERROR, 0 , "nastranAIM.c", 2373, __func__ , "Writing load ADD cards is not properly implemented!"); }; | |||
2374 | status = CAPS_NOTIMPLEMENT-334; | |||
2375 | goto cleanup; | |||
2376 | ||||
2377 | #ifdef FIX_tempIntegerArray_INIT | |||
2378 | // tempIntegerArray needs to be initialized!!! | |||
2379 | ||||
2380 | tempIntegerArray = (int *) EG_reall(tempIntegerArray, k*sizeof(int)); | |||
2381 | if (tempIntegerArray == NULL((void*)0)) { | |||
2382 | status = EGADS_MALLOC-4; | |||
2383 | goto cleanup; | |||
2384 | } | |||
2385 | ||||
2386 | //TOOO: eliminate load add card? | |||
2387 | // Write combined load card | |||
2388 | printf("\tWriting load ADD cards\n"); | |||
2389 | status = nastran_writeLoadADDCard(fp, | |||
2390 | nastranInstance->feaProblem.numLoad+i+1, | |||
2391 | k, | |||
2392 | tempIntegerArray, | |||
2393 | feaLoad, | |||
2394 | &nastranInstance->feaProblem.feaFileFormat); | |||
2395 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2396 | ||||
2397 | // Free temporary load ID list | |||
2398 | EG_free(tempIntegerArray); | |||
2399 | tempIntegerArray = NULL((void*)0); | |||
2400 | #endif | |||
2401 | } | |||
2402 | ||||
2403 | } | |||
2404 | ||||
2405 | if (nastranInstance->feaProblem.feaAnalysis[i].numConstraint != 0) { | |||
2406 | // Write combined constraint card | |||
2407 | printf("\tWriting constraint ADD cards\n"); | |||
2408 | status = nastran_writeConstraintADDCard(fp, | |||
2409 | nastranInstance->feaProblem.numConstraint+i+1, | |||
2410 | nastranInstance->feaProblem.feaAnalysis[i].numConstraint, | |||
2411 | nastranInstance->feaProblem.feaAnalysis[i].constraintSetID, | |||
2412 | &nastranInstance->feaProblem.feaFileFormat); | |||
2413 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 2413, __func__, 0); goto cleanup; }; | |||
2414 | ||||
2415 | } else { // If no constraints for an individual analysis are specified assume that all constraints should be applied | |||
2416 | ||||
2417 | if (nastranInstance->feaProblem.numConstraint != 0) { | |||
2418 | ||||
2419 | printf("\tWriting combined constraint cards\n"); | |||
2420 | ||||
2421 | // Create a temporary list of constraint IDs | |||
2422 | AIM_ALLOC(tempIntegerArray, nastranInstance->feaProblem.numConstraint, int, aimInfo, status){ if (tempIntegerArray != ((void*)0)) { status = -4; aim_status (aimInfo, status, "nastranAIM.c", 2422, __func__, 1, "AIM_ALLOC: %s != NULL" , "tempIntegerArray"); goto cleanup; } size_t memorysize = nastranInstance ->feaProblem.numConstraint; tempIntegerArray = (int *) EG_alloc (memorysize*sizeof(int)); if (tempIntegerArray == ((void*)0)) { status = -4; aim_status(aimInfo, status, "nastranAIM.c", 2422 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "tempIntegerArray" , memorysize, "int"); goto cleanup; } }; | |||
2423 | ||||
2424 | for (j = 0; j < nastranInstance->feaProblem.numConstraint; j++) { | |||
2425 | tempIntegerArray[j] = nastranInstance->feaProblem.feaConstraint[j].constraintID; | |||
2426 | } | |||
2427 | ||||
2428 | // Write combined constraint card | |||
2429 | status = nastran_writeConstraintADDCard(fp, | |||
2430 | nastranInstance->feaProblem.numConstraint+i+1, | |||
2431 | nastranInstance->feaProblem.numConstraint, | |||
2432 | tempIntegerArray, | |||
2433 | &nastranInstance->feaProblem.feaFileFormat); | |||
2434 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2435 | ||||
2436 | // Free temporary constraint ID list | |||
2437 | AIM_FREE(tempIntegerArray){ EG_free(tempIntegerArray); tempIntegerArray = ((void*)0); }; | |||
2438 | } | |||
2439 | } | |||
2440 | ||||
2441 | if (nastranInstance->feaProblem.feaAnalysis[i].numDesignConstraint != 0) { | |||
2442 | ||||
2443 | // Write combined design constraint card | |||
2444 | printf("\tWriting design constraint ADD cards\n"); | |||
2445 | status = nastran_writeDesignConstraintADDCard(fp, | |||
2446 | nastranInstance->feaProblem.numDesignConstraint+i+1, | |||
2447 | nastranInstance->feaProblem.feaAnalysis[i].numDesignConstraint, | |||
2448 | nastranInstance->feaProblem.feaAnalysis[i].designConstraintSetID, | |||
2449 | &nastranInstance->feaProblem.feaFileFormat); | |||
2450 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 2450, __func__, 0); goto cleanup; }; | |||
2451 | ||||
2452 | } else { // If no design constraints for an individual analysis are specified assume that all design constraints should be applied | |||
2453 | ||||
2454 | if (nastranInstance->feaProblem.numDesignConstraint != 0) { | |||
2455 | ||||
2456 | // Create a temporary list of design constraint IDs | |||
2457 | AIM_ALLOC(tempIntegerArray, nastranInstance->feaProblem.numDesignConstraint, int, aimInfo, status){ if (tempIntegerArray != ((void*)0)) { status = -4; aim_status (aimInfo, status, "nastranAIM.c", 2457, __func__, 1, "AIM_ALLOC: %s != NULL" , "tempIntegerArray"); goto cleanup; } size_t memorysize = nastranInstance ->feaProblem.numDesignConstraint; tempIntegerArray = (int * ) EG_alloc(memorysize*sizeof(int)); if (tempIntegerArray == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "nastranAIM.c" , 2457, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "tempIntegerArray" , memorysize, "int"); goto cleanup; } }; | |||
2458 | ||||
2459 | for (j = 0; j < nastranInstance->feaProblem.numDesignConstraint; j++) { | |||
2460 | tempIntegerArray[j] = nastranInstance->feaProblem.feaDesignConstraint[j].designConstraintID; | |||
2461 | } | |||
2462 | ||||
2463 | // Write combined design constraint card | |||
2464 | printf("\tWriting design constraint ADD cards\n"); | |||
2465 | status = nastran_writeDesignConstraintADDCard(fp, | |||
2466 | nastranInstance->feaProblem.numDesignConstraint+i+1, | |||
2467 | nastranInstance->feaProblem.numDesignConstraint, | |||
2468 | tempIntegerArray, | |||
2469 | &nastranInstance->feaProblem.feaFileFormat); | |||
2470 | // Free temporary design constraint ID list | |||
2471 | if (tempIntegerArray != NULL((void*)0)) EG_free(tempIntegerArray); | |||
2472 | tempIntegerArray = NULL((void*)0); | |||
2473 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "nastranAIM.c" , 2473, __func__, 0); goto cleanup; }; | |||
2474 | } | |||
2475 | ||||
2476 | } | |||
2477 | } | |||
2478 | ||||
2479 | ||||
2480 | // Loads | |||
2481 | for (i = 0; i < nastranInstance->feaProblem.numLoad; i++) { | |||
2482 | ||||
2483 | if (i == 0) printf("\tWriting load cards\n"); | |||
2484 | ||||
2485 | status = nastran_writeLoadCard(fp, | |||
2486 | &feaLoad[i], | |||
2487 | &nastranInstance->feaProblem.feaFileFormat); | |||
2488 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2489 | } | |||
2490 | ||||
2491 | // Constraints | |||
2492 | for (i = 0; i < nastranInstance->feaProblem.numConstraint; i++) { | |||
2493 | ||||
2494 | if (i == 0) printf("\tWriting constraint cards\n"); | |||
2495 | ||||
2496 | status = nastran_writeConstraintCard(fp, | |||
2497 | &nastranInstance->feaProblem.feaConstraint[i], | |||
2498 | &nastranInstance->feaProblem.feaFileFormat); | |||
2499 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2500 | } | |||
2501 | ||||
2502 | // Supports | |||
2503 | for (i = 0; i < nastranInstance->feaProblem.numSupport; i++) { | |||
2504 | ||||
2505 | if (i == 0) printf("\tWriting support cards\n"); | |||
2506 | j = (int) true1; | |||
2507 | status = nastran_writeSupportCard(fp, | |||
2508 | &nastranInstance->feaProblem.feaSupport[i], | |||
2509 | &nastranInstance->feaProblem.feaFileFormat, | |||
2510 | &j); | |||
2511 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2512 | } | |||
2513 | ||||
2514 | ||||
2515 | // Materials | |||
2516 | for (i = 0; i < nastranInstance->feaProblem.numMaterial; i++) { | |||
2517 | ||||
2518 | if (i == 0) printf("\tWriting material cards\n"); | |||
2519 | ||||
2520 | status = nastran_writeMaterialCard(fp, | |||
2521 | &nastranInstance->feaProblem.feaMaterial[i], | |||
2522 | &nastranInstance->feaProblem.feaFileFormat); | |||
2523 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2524 | } | |||
2525 | ||||
2526 | // Properties | |||
2527 | for (i = 0; i < nastranInstance->feaProblem.numProperty; i++) { | |||
2528 | ||||
2529 | if (i == 0) printf("\tWriting property cards\n"); | |||
2530 | ||||
2531 | status = nastran_writePropertyCard(fp, | |||
2532 | &nastranInstance->feaProblem.feaProperty[i], | |||
2533 | &nastranInstance->feaProblem.feaFileFormat); | |||
2534 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2535 | } | |||
2536 | ||||
2537 | // Coordinate systems | |||
2538 | // printf("DEBUG: Number of coord systems: %d\n", nastranInstance->feaProblem.numCoordSystem); | |||
2539 | for (i = 0; i < nastranInstance->feaProblem.numCoordSystem; i++) { | |||
2540 | ||||
2541 | if (i == 0) printf("\tWriting coordinate system cards\n"); | |||
2542 | ||||
2543 | status = nastran_writeCoordinateSystemCard(fp, | |||
2544 | &nastranInstance->feaProblem.feaCoordSystem[i], | |||
2545 | &nastranInstance->feaProblem.feaFileFormat); | |||
2546 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2547 | } | |||
2548 | ||||
2549 | // Optimization - design variables | |||
2550 | for( i = 0; i < nastranInstance->feaProblem.numDesignVariable; i++) { | |||
2551 | ||||
2552 | if (i == 0) printf("\tWriting design variable cards\n"); | |||
2553 | ||||
2554 | status = nastran_writeDesignVariableCard(fp, | |||
2555 | &nastranInstance->feaProblem.feaDesignVariable[i], | |||
2556 | &nastranInstance->feaProblem.feaFileFormat); | |||
2557 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2558 | } | |||
2559 | ||||
2560 | // Optimization - design variable relations | |||
2561 | for( i = 0; i < nastranInstance->feaProblem.numDesignVariableRelation; i++) { | |||
2562 | ||||
2563 | if (i == 0) printf("\tWriting design variable relation cards\n"); | |||
2564 | ||||
2565 | status = nastran_writeDesignVariableRelationCard(aimInfo, | |||
2566 | fp, | |||
2567 | &nastranInstance->feaProblem.feaDesignVariableRelation[i], | |||
2568 | &nastranInstance->feaProblem, | |||
2569 | &nastranInstance->feaProblem.feaFileFormat); | |||
2570 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2571 | } | |||
2572 | ||||
2573 | // Optimization - design constraints | |||
2574 | for( i = 0; i < nastranInstance->feaProblem.numDesignConstraint; i++) { | |||
2575 | ||||
2576 | if (i == 0) printf("\tWriting design constraints and responses cards\n"); | |||
2577 | ||||
2578 | status = nastran_writeDesignConstraintCard(fp, | |||
2579 | &nastranInstance->feaProblem.feaDesignConstraint[i], | |||
2580 | &nastranInstance->feaProblem.feaFileFormat); | |||
2581 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2582 | } | |||
2583 | ||||
2584 | // Optimization - design equations | |||
2585 | for( i = 0; i < nastranInstance->feaProblem.numEquation; i++) { | |||
2586 | ||||
2587 | if (i == 0) printf("\tWriting design equation cards\n"); | |||
2588 | ||||
2589 | status = nastran_writeDesignEquationCard(fp, | |||
2590 | &nastranInstance->feaProblem.feaEquation[i], | |||
2591 | &nastranInstance->feaProblem.feaFileFormat); | |||
2592 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2593 | } | |||
2594 | ||||
2595 | // Optimization - design table constants | |||
2596 | if (nastranInstance->feaProblem.feaDesignTable.numConstant > 0) | |||
2597 | printf("\tWriting design table card\n"); | |||
2598 | status = nastran_writeDesignTableCard(fp, | |||
2599 | &nastranInstance->feaProblem.feaDesignTable, | |||
2600 | &nastranInstance->feaProblem.feaFileFormat); | |||
2601 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2602 | ||||
2603 | // Optimization - design optimization parameters | |||
2604 | if (nastranInstance->feaProblem.feaDesignOptParam.numParam > 0) | |||
2605 | printf("\tWriting design optimization parameters card\n"); | |||
2606 | status = nastran_writeDesignOptParamCard(fp, | |||
2607 | &nastranInstance->feaProblem.feaDesignOptParam, | |||
2608 | &nastranInstance->feaProblem.feaFileFormat); | |||
2609 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2610 | ||||
2611 | // Optimization - design responses | |||
2612 | for( i = 0; i < nastranInstance->feaProblem.numDesignResponse; i++) { | |||
2613 | ||||
2614 | if (i == 0) printf("\tWriting design response cards\n"); | |||
2615 | ||||
2616 | status = nastran_writeDesignResponseCard(fp, | |||
2617 | &nastranInstance->feaProblem.feaDesignResponse[i], | |||
2618 | &nastranInstance->feaProblem.feaFileFormat); | |||
2619 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2620 | } | |||
2621 | ||||
2622 | // Optimization - design equation responses | |||
2623 | for( i = 0; i < nastranInstance->feaProblem.numEquationResponse; i++) { | |||
2624 | ||||
2625 | if (i == 0) printf("\tWriting design equation response cards\n"); | |||
2626 | ||||
2627 | status = nastran_writeDesignEquationResponseCard(fp, | |||
2628 | &nastranInstance->feaProblem.feaEquationResponse[i], | |||
2629 | &nastranInstance->feaProblem, | |||
2630 | &nastranInstance->feaProblem.feaFileFormat); | |||
2631 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2632 | } | |||
2633 | ||||
2634 | // Aeroelastic | |||
2635 | if (strcasecmp(analysisType, "Aeroelastic") == 0 || | |||
2636 | strcasecmp(analysisType, "AeroelasticTrim") == 0 || | |||
2637 | strcasecmp(analysisType, "AeroelasticFlutter") == 0 || | |||
2638 | haveSubAeroelasticTrim == (int) true1 || | |||
2639 | haveSubAeroelasticFlutter == (int) true1 ) { | |||
2640 | ||||
2641 | printf("\tWriting aeroelastic cards\n"); | |||
2642 | for (i = 0; i < nastranInstance->feaProblem.numAero; i++){ | |||
2643 | status = nastran_writeCAeroCard(fp, | |||
2644 | &nastranInstance->feaProblem.feaAero[i], | |||
2645 | &nastranInstance->feaProblem.feaFileFormat); | |||
2646 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2647 | ||||
2648 | status = nastran_writeAeroSplineCard(fp, | |||
2649 | &nastranInstance->feaProblem.feaAero[i], | |||
2650 | &nastranInstance->feaProblem.feaFileFormat); | |||
2651 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2652 | ||||
2653 | status = nastran_writeSet1Card(fp, | |||
2654 | &nastranInstance->feaProblem.feaAero[i], | |||
2655 | &nastranInstance->feaProblem.feaFileFormat); | |||
2656 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2657 | } | |||
2658 | ||||
2659 | ||||
2660 | // status = nastran_writeAeroCamberTwist(fp, | |||
2661 | // nastranInstance->feaProblem.numAero, | |||
2662 | // nastranInstance->feaProblem.feaAero, | |||
2663 | // &nastranInstance->feaProblem.feaFileFormat); | |||
2664 | // if (status != CAPS_SUCCESS) goto cleanup; | |||
2665 | } | |||
2666 | ||||
2667 | // Include mesh file | |||
2668 | fprintf(fp,"\nINCLUDE \'%s.bdf\'\n\n", nastranInstance->projectName); | |||
2669 | ||||
2670 | // End bulk data | |||
2671 | fprintf(fp,"ENDDATA\n"); | |||
2672 | ||||
2673 | fclose(fp); | |||
2674 | fp = NULL((void*)0); | |||
2675 | /* | |||
2676 | //////////////////////////////////////// | |||
2677 | printf("\n\n\nTESTING F06 READER\n\n"); | |||
2678 | ||||
2679 | // FO6 data variables | |||
2680 | int numGridPoint = 0; | |||
2681 | int numEigenVector = 0; | |||
2682 | double **dataMatrix = NULL; | |||
2683 | filename = (char *) EG_alloc((strlen(nastranInstance->projectName) + | |||
2684 | strlen(".f06") + 2)*sizeof(char)); | |||
2685 | ||||
2686 | sprintf(filename,"%s%s", nastranInstance->projectName, ".f06"); | |||
2687 | ||||
2688 | // Open file | |||
2689 | fp = aim_fopen(aimInfo, filename, "r"); | |||
2690 | if (filename != NULL) EG_free(filename); | |||
2691 | filename = NULL; | |||
2692 | ||||
2693 | if (fp == NULL) { | |||
2694 | printf("Unable to open file: %s\n", filename); | |||
2695 | ||||
2696 | return CAPS_IOERR; | |||
2697 | } | |||
2698 | ||||
2699 | status = nastran_readF06Displacement(fp, | |||
2700 | -9, | |||
2701 | &numGridPoint, | |||
2702 | &dataMatrix); | |||
2703 | ||||
2704 | for ( i = 0 ; i < numGridPoint ; i++) printf("dataMatrix = %f %f %f %f %f %f %f %f\n", | |||
2705 | dataMatrix[i][0], | |||
2706 | dataMatrix[i][1], | |||
2707 | dataMatrix[i][2], | |||
2708 | dataMatrix[i][3], | |||
2709 | dataMatrix[i][4], | |||
2710 | dataMatrix[i][5], | |||
2711 | dataMatrix[i][6], | |||
2712 | dataMatrix[i][7]); | |||
2713 | fclose(fp); | |||
2714 | /////////////////////////////////// | |||
2715 | */ | |||
2716 | ||||
2717 | status = CAPS_SUCCESS0; | |||
2718 | ||||
2719 | cleanup: | |||
2720 | if (status != CAPS_SUCCESS0) | |||
2721 | printf("\tPremature exit in nastranAIM preAnalysis, status = %d\n", | |||
2722 | status); | |||
2723 | ||||
2724 | for (i = 0; i < nastranInstance->feaProblem.numLoad; i++) { | |||
2725 | destroy_feaLoadStruct(&feaLoad[i]); | |||
2726 | } | |||
2727 | AIM_FREE(feaLoad){ EG_free(feaLoad); feaLoad = ((void*)0); }; | |||
2728 | ||||
2729 | AIM_FREE(tempIntegerArray){ EG_free(tempIntegerArray); tempIntegerArray = ((void*)0); }; | |||
2730 | ||||
2731 | if (fp != NULL((void*)0)) fclose(fp); | |||
2732 | ||||
2733 | return status; | |||
2734 | } | |||
2735 | ||||
2736 | ||||
2737 | /* no longer optional and needed for restart */ | |||
2738 | int aimPostAnalysis(/*@unused@*/ void *instStore, /*@unused@*/ void *aimStruc, | |||
2739 | /*@unused@*/ int restart, /*@unused@*/ capsValue *inputs) | |||
2740 | { | |||
2741 | return CAPS_SUCCESS0; | |||
2742 | } | |||
2743 | ||||
2744 | ||||
2745 | // Set Nastran output variables | |||
2746 | int aimOutputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimStruc, | |||
2747 | int index, char **aoname, capsValue *form) | |||
2748 | { | |||
2749 | /*! \page aimOutputsNastran AIM Outputs | |||
2750 | * The following list outlines the Nastran outputs available through the AIM interface. | |||
2751 | */ | |||
2752 | ||||
2753 | #ifdef DEBUG | |||
2754 | printf(" nastranAIM/aimOutputs index = %d!\n", index); | |||
2755 | #endif | |||
2756 | ||||
2757 | /*! \page aimOutputsNastran AIM Outputs | |||
2758 | * - <B>EigenValue</B> = List of Eigen-Values (\f$ \lambda\f$) after a modal solve. | |||
2759 | * - <B>EigenRadian</B> = List of Eigen-Values in terms of radians (\f$ \omega = \sqrt{\lambda}\f$ ) after a modal solve. | |||
2760 | * - <B>EigenFrequency</B> = List of Eigen-Values in terms of frequencies (\f$ f = \frac{\omega}{2\pi}\f$) after a modal solve. | |||
2761 | * - <B>EigenGeneralMass</B> = List of generalized masses for the Eigen-Values. | |||
2762 | * - <B>EigenGeneralStiffness</B> = List of generalized stiffness for the Eigen-Values. | |||
2763 | * - <B>Objective</B> = Final objective value for a design optimization case. | |||
2764 | * - <B>ObjectiveHistory</B> = List of objective value for the history of a design optimization case. | |||
2765 | */ | |||
2766 | ||||
2767 | if (index == 1) { | |||
2768 | *aoname = EG_strdup("EigenValue"); | |||
2769 | ||||
2770 | } else if (index == 2) { | |||
2771 | *aoname = EG_strdup("EigenRadian"); | |||
2772 | ||||
2773 | } else if (index == 3) { | |||
2774 | *aoname = EG_strdup("EigenFrequency"); | |||
2775 | ||||
2776 | } else if (index == 4) { | |||
2777 | *aoname = EG_strdup("EigenGeneralMass"); | |||
2778 | ||||
2779 | } else if (index == 5) { | |||
2780 | *aoname = EG_strdup("EigenGeneralStiffness"); | |||
2781 | ||||
2782 | } else if (index == 6) { | |||
2783 | *aoname = EG_strdup("Objective"); | |||
2784 | ||||
2785 | } else if (index == 7) { | |||
2786 | *aoname = EG_strdup("ObjectiveHistory"); | |||
2787 | } | |||
2788 | ||||
2789 | form->type = Double; | |||
2790 | form->units = NULL((void*)0); | |||
2791 | form->lfixed = Change; | |||
2792 | form->sfixed = Change; | |||
2793 | form->vals.reals = NULL((void*)0); | |||
2794 | form->vals.real = 0; | |||
2795 | ||||
2796 | return CAPS_SUCCESS0; | |||
2797 | } | |||
2798 | ||||
2799 | ||||
2800 | // Calculate Nastran output | |||
2801 | int aimCalcOutput(void *instStore, /*@unused@*/ void *aimInfo, int index, | |||
2802 | capsValue *val) | |||
2803 | { | |||
2804 | int status = CAPS_SUCCESS0; // Function return status | |||
2805 | ||||
2806 | int i; //Indexing | |||
2807 | ||||
2808 | int numData = 0; | |||
2809 | double *dataVector = NULL((void*)0); | |||
2810 | double **dataMatrix = NULL((void*)0); | |||
2811 | aimStorage *nastranInstance; | |||
2812 | ||||
2813 | char *filename = NULL((void*)0); // File to open | |||
2814 | char extF06[] = ".f06", extOP2[] = ".op2"; | |||
2815 | FILE *fp = NULL((void*)0); // File pointer | |||
2816 | ||||
2817 | nastranInstance = (aimStorage *) instStore; | |||
2818 | ||||
2819 | if (index <= 5) { | |||
2820 | filename = (char *) EG_alloc((strlen(nastranInstance->projectName) + | |||
2821 | strlen(extF06) +1)*sizeof(char)); | |||
2822 | if (filename == NULL((void*)0)) return EGADS_MALLOC-4; | |||
2823 | ||||
2824 | sprintf(filename, "%s%s", nastranInstance->projectName, extF06); | |||
2825 | ||||
2826 | fp = aim_fopen(aimInfo, filename, "r"); | |||
2827 | ||||
2828 | EG_free(filename); // Free filename allocation | |||
2829 | ||||
2830 | if (fp == NULL((void*)0)) { | |||
2831 | #ifdef DEBUG | |||
2832 | printf(" nastranAIM/aimCalcOutput Cannot open Output file!\n"); | |||
2833 | #endif | |||
2834 | return CAPS_IOERR-332; | |||
2835 | } | |||
2836 | ||||
2837 | status = nastran_readF06EigenValue(fp, &numData, &dataMatrix); | |||
2838 | if ((status == CAPS_SUCCESS0) && (dataMatrix != NULL((void*)0))) { | |||
2839 | ||||
2840 | val->nrow = numData; | |||
2841 | val->ncol = 1; | |||
2842 | val->length = val->nrow*val->ncol; | |||
2843 | if (val->length == 1) val->dim = Scalar; | |||
2844 | else val->dim = Vector; | |||
2845 | ||||
2846 | if (val->length == 1) { | |||
2847 | val->vals.real = dataMatrix[0][index-1]; | |||
2848 | } else { | |||
2849 | ||||
2850 | val->vals.reals = (double *) EG_alloc(val->length*sizeof(double)); | |||
2851 | if (val->vals.reals != NULL((void*)0)) { | |||
2852 | ||||
2853 | for (i = 0; i < val->length; i++) { | |||
2854 | ||||
2855 | val->vals.reals[i] = dataMatrix[i][index-1]; | |||
2856 | } | |||
2857 | ||||
2858 | } else status = EGADS_MALLOC-4; | |||
2859 | } | |||
2860 | } | |||
2861 | } else if (index == 6 || index == 7) { | |||
2862 | filename = (char *) EG_alloc((strlen(nastranInstance->projectName) + | |||
2863 | strlen(extOP2) +1)*sizeof(char)); | |||
2864 | if (filename == NULL((void*)0)) return EGADS_MALLOC-4; | |||
2865 | ||||
2866 | sprintf(filename, "%s%s", nastranInstance->projectName, extOP2); | |||
2867 | ||||
2868 | status = nastran_readOP2Objective(filename, &numData, &dataVector); | |||
2869 | ||||
2870 | EG_free(filename); // Free filename allocation | |||
2871 | ||||
2872 | if (status == CAPS_SUCCESS0 && dataVector != NULL((void*)0) && numData > 0) { | |||
2873 | ||||
2874 | if (index == 6) val->nrow = 1; | |||
2875 | else val->nrow = numData; | |||
2876 | ||||
2877 | val->ncol = 1; | |||
2878 | val->length = val->nrow*val->ncol; | |||
2879 | ||||
2880 | if (val->length == 1) val->dim = Scalar; | |||
2881 | else val->dim = Vector; | |||
2882 | ||||
2883 | if (val->length == 1) { | |||
2884 | val->vals.real = dataVector[numData-1]; | |||
2885 | } else { | |||
2886 | ||||
2887 | val->vals.reals = (double *) EG_alloc(val->length*sizeof(double)); | |||
2888 | if (val->vals.reals != NULL((void*)0)) { | |||
2889 | ||||
2890 | for (i = 0; i < val->length; i++) { | |||
2891 | ||||
2892 | val->vals.reals[i] = dataVector[i]; | |||
2893 | } | |||
2894 | ||||
2895 | } else status = EGADS_MALLOC-4; | |||
2896 | } | |||
2897 | } | |||
2898 | } | |||
2899 | ||||
2900 | // Restore the path we came in with | |||
2901 | if (fp != NULL((void*)0)) fclose(fp); | |||
2902 | ||||
2903 | if (dataMatrix != NULL((void*)0)) { | |||
2904 | for (i = 0; i < numData; i++) { | |||
2905 | if (dataMatrix[i] != NULL((void*)0)) EG_free(dataMatrix[i]); | |||
2906 | } | |||
2907 | EG_free(dataMatrix); | |||
2908 | } | |||
2909 | ||||
2910 | if (dataVector != NULL((void*)0)) EG_free(dataVector); | |||
2911 | ||||
2912 | return status; | |||
2913 | } | |||
2914 | ||||
2915 | ||||
2916 | void aimCleanup(void *instStore) | |||
2917 | { | |||
2918 | int status; // Returning status | |||
2919 | aimStorage *nastranInstance; | |||
2920 | ||||
2921 | #ifdef DEBUG | |||
2922 | printf(" nastranAIM/aimCleanup!\n"); | |||
2923 | #endif | |||
2924 | nastranInstance = (aimStorage *) instStore; | |||
2925 | ||||
2926 | status = destroy_aimStorage(nastranInstance); | |||
2927 | if (status != CAPS_SUCCESS0) | |||
2928 | printf("Error: Status %d during clean up of instance\n", status); | |||
2929 | ||||
2930 | EG_free(nastranInstance); | |||
2931 | } | |||
2932 | ||||
2933 | ||||
2934 | int aimDiscr(char *tname, capsDiscr *discr) | |||
2935 | { | |||
2936 | int status = CAPS_SUCCESS0; // Function return status | |||
2937 | int i; | |||
2938 | ego *tess = NULL((void*)0); | |||
2939 | aimStorage *nastranInstance; | |||
2940 | ||||
2941 | #ifdef DEBUG | |||
2942 | printf(" nastranAIM/aimDiscr: tname = %s!\n", tname); | |||
2943 | #endif | |||
2944 | if (tname == NULL((void*)0)) return CAPS_NOTFOUND-303; | |||
2945 | ||||
2946 | nastranInstance = (aimStorage *) discr->instStore; | |||
2947 | ||||
2948 | // Check and generate/retrieve the mesh | |||
2949 | status = checkAndCreateMesh(discr->aInfo, nastranInstance); | |||
2950 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2951 | ||||
2952 | AIM_ALLOC(tess, nastranInstance->numMesh, ego, discr->aInfo, status){ if (tess != ((void*)0)) { status = -4; aim_status(discr-> aInfo, status, "nastranAIM.c", 2952, __func__, 1, "AIM_ALLOC: %s != NULL" , "tess"); goto cleanup; } size_t memorysize = nastranInstance ->numMesh; tess = (ego *) EG_alloc(memorysize*sizeof(ego)) ; if (tess == ((void*)0)) { status = -4; aim_status(discr-> aInfo, status, "nastranAIM.c", 2952, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "tess", memorysize, "ego"); goto cleanup; } }; | |||
2953 | for (i = 0; i < nastranInstance->numMesh; i++) { | |||
2954 | tess[i] = nastranInstance->feaMesh[i].egadsTess; | |||
2955 | } | |||
2956 | ||||
2957 | status = mesh_fillDiscr(tname, &nastranInstance->attrMap, nastranInstance->numMesh, tess, discr); | |||
2958 | if (status != CAPS_SUCCESS0) goto cleanup; | |||
2959 | ||||
2960 | #ifdef DEBUG | |||
2961 | printf(" nastranAIM/aimDiscr: Instance = %d, Finished!!\n", iIndex); | |||
2962 | #endif | |||
2963 | ||||
2964 | status = CAPS_SUCCESS0; | |||
2965 | ||||
2966 | cleanup: | |||
2967 | if (status != CAPS_SUCCESS0) | |||
2968 | printf("\tPremature exit: function aimDiscr nastranAIM status = %d", | |||
2969 | status); | |||
2970 | ||||
2971 | AIM_FREE(tess){ EG_free(tess); tess = ((void*)0); }; | |||
2972 | return status; | |||
2973 | } | |||
2974 | ||||
2975 | ||||
2976 | int aimTransfer(capsDiscr *discr, const char *dataName, int numPoint, | |||
2977 | int dataRank, double *dataVal, /*@unused@*/ char **units) | |||
2978 | { | |||
2979 | ||||
2980 | /*! \page dataTransferNastran Nastran Data Transfer | |||
2981 | * | |||
2982 | * The Nastran AIM has the ability to transfer displacements and eigenvectors from the AIM and pressure | |||
2983 | * distributions to the AIM using the conservative and interpolative data transfer schemes in CAPS. | |||
2984 | * | |||
2985 | * \section dataFromNastran Data transfer from Nastran (FieldOut) | |||
2986 | * | |||
2987 | * <ul> | |||
2988 | * <li> <B>"Displacement"</B> </li> <br> | |||
2989 | * Retrieves nodal displacements from the *.f06 file. | |||
2990 | * </ul> | |||
2991 | * | |||
2992 | * <ul> | |||
2993 | * <li> <B>"EigenVector_#"</B> </li> <br> | |||
2994 | * Retrieves modal eigen-vectors from the *.f06 file, where "#" should be replaced by the | |||
2995 | * corresponding mode number for the eigen-vector (eg. EigenVector_3 would correspond to the third mode, | |||
2996 | * while EigenVector_6 would be the sixth mode). | |||
2997 | * </ul> | |||
2998 | * | |||
2999 | * \section dataToNastran Data transfer to Nastran (FieldIn) | |||
3000 | * <ul> | |||
3001 | * <li> <B>"Pressure"</B> </li> <br> | |||
3002 | * Writes appropriate load cards using the provided pressure distribution. | |||
3003 | * </ul> | |||
3004 | * | |||
3005 | */ | |||
3006 | ||||
3007 | int status; // Function return status | |||
3008 | int i, j, dataPoint, bIndex; // Indexing | |||
3009 | aimStorage *nastranInstance; | |||
3010 | ||||
3011 | char *extF06 = ".f06"; | |||
3012 | ||||
3013 | // FO6 data variables | |||
3014 | int numGridPoint = 0; | |||
3015 | int numEigenVector = 0; | |||
3016 | ||||
3017 | double **dataMatrix = NULL((void*)0); | |||
3018 | ||||
3019 | // Specific EigenVector to use | |||
3020 | int eigenVectorIndex = 0; | |||
3021 | ||||
3022 | // Variables used in global node mapping | |||
3023 | //int *storage; | |||
3024 | int globalNodeID; | |||
3025 | ||||
3026 | // Filename stuff | |||
3027 | char *filename = NULL((void*)0); | |||
3028 | FILE *fp; // File pointer | |||
3029 | ||||
3030 | #ifdef DEBUG | |||
3031 | printf(" nastranAIM/aimTransfer name = %s npts = %d/%d!\n", | |||
3032 | dataName, numPoint, dataRank); | |||
3033 | #endif | |||
3034 | nastranInstance = (aimStorage *) discr->instStore; | |||
3035 | ||||
3036 | //Get the appropriate parts of the tessellation to data | |||
3037 | //storage = (int *) discr->ptrm; | |||
3038 | //capsGroupList = &storage[0]; // List of boundary ID (attrMap) in the transfer | |||
3039 | ||||
3040 | if (strcasecmp(dataName, "Displacement") != 0 && | |||
3041 | strncmp(dataName, "EigenVector", 11) != 0) { | |||
3042 | ||||
3043 | printf("Unrecognized data transfer variable - %s\n", dataName); | |||
3044 | return CAPS_NOTFOUND-303; | |||
3045 | } | |||
3046 | ||||
3047 | filename = (char *) EG_alloc((strlen(nastranInstance->projectName) + | |||
3048 | strlen(extF06) + 1)*sizeof(char)); | |||
3049 | if (filename == NULL((void*)0)) return EGADS_MALLOC-4; | |||
3050 | sprintf(filename,"%s%s", nastranInstance->projectName, extF06); | |||
3051 | ||||
3052 | // Open file | |||
3053 | fp = aim_fopen(discr->aInfo, filename, "r"); | |||
3054 | if (fp == NULL((void*)0)) { | |||
3055 | printf("Unable to open file: %s\n", filename); | |||
3056 | if (filename != NULL((void*)0)) EG_free(filename); | |||
3057 | return CAPS_IOERR-332; | |||
3058 | } | |||
3059 | ||||
3060 | if (filename != NULL((void*)0)) EG_free(filename); | |||
3061 | filename = NULL((void*)0); | |||
3062 | ||||
3063 | if (strcasecmp(dataName, "Displacement") == 0) { | |||
3064 | ||||
3065 | if (dataRank != 3) { | |||
3066 | ||||
3067 | printf("Invalid rank for dataName \"%s\" - excepted a rank of 3!!!\n", | |||
3068 | dataName); | |||
3069 | status = CAPS_BADRANK-301; | |||
3070 | ||||
3071 | } else { | |||
3072 | ||||
3073 | status = nastran_readF06Displacement(fp, | |||
3074 | -1, | |||
3075 | &numGridPoint, | |||
3076 | &dataMatrix); | |||
3077 | fclose(fp); | |||
3078 | fp = NULL((void*)0); | |||
3079 | } | |||
3080 | ||||
3081 | } else if (strncmp(dataName, "EigenVector", 11) == 0) { | |||
3082 | ||||
3083 | // Which EigenVector do we want ? | |||
3084 | for (i = 0; i < strlen(dataName); i++) { | |||
3085 | if (dataName[i] == '_' ) break; | |||
3086 | } | |||
3087 | ||||
3088 | if (i == strlen(dataName)) { | |||
3089 | eigenVectorIndex = 1; | |||
3090 | } else { | |||
3091 | ||||
3092 | status = sscanf(dataName, "EigenVector_%d", &eigenVectorIndex); | |||
3093 | if (status != 1) { | |||
3094 | printf("Unable to determine which EigenVector to use - Defaulting the first EigenVector!!!\n"); | |||
3095 | eigenVectorIndex = 1; | |||
3096 | } | |||
3097 | } | |||
3098 | ||||
3099 | if (dataRank != 3) { | |||
3100 | ||||
3101 | printf("Invalid rank for dataName \"%s\" - excepted a rank of 3!!!\n", | |||
3102 | dataName); | |||
3103 | status = CAPS_BADRANK-301; | |||
3104 | ||||
3105 | } else { | |||
3106 | ||||
3107 | status = nastran_readF06EigenVector(fp, | |||
3108 | &numEigenVector, | |||
3109 | &numGridPoint, | |||
3110 | &dataMatrix); | |||
3111 | } | |||
3112 | ||||
3113 | fclose(fp); | |||
3114 | fp = NULL((void*)0); | |||
3115 | ||||
3116 | } else { | |||
3117 | ||||
3118 | status = CAPS_NOTFOUND-303; | |||
3119 | } | |||
3120 | ||||
3121 | AIM_STATUS(discr->aInfo, status)if (status != 0) { aim_status(discr->aInfo, status, "nastranAIM.c" , 3121, __func__, 0); goto cleanup; }; | |||
3122 | ||||
3123 | ||||
3124 | // Check EigenVector range | |||
3125 | if (strncmp(dataName, "EigenVector", 11) == 0) { | |||
3126 | if (eigenVectorIndex > numEigenVector) { | |||
3127 | printf("Only %d EigenVectors found but index %d requested!\n", | |||
3128 | numEigenVector, eigenVectorIndex); | |||
3129 | status = CAPS_RANGEERR-326; | |||
3130 | goto cleanup; | |||
3131 | } | |||
3132 | ||||
3133 | if (eigenVectorIndex < 1) { | |||
3134 | printf("For EigenVector_X notation, X must be >= 1, currently X = %d\n", | |||
3135 | eigenVectorIndex); | |||
3136 | status = CAPS_RANGEERR-326; | |||
3137 | goto cleanup; | |||
3138 | } | |||
3139 | ||||
3140 | } | |||
3141 | if (dataMatrix == NULL((void*)0)) { | |||
3142 | status = CAPS_NULLVALUE-307; | |||
3143 | goto cleanup; | |||
3144 | } | |||
3145 | ||||
3146 | for (i = 0; i < numPoint; i++) { | |||
3147 | ||||
3148 | bIndex = discr->tessGlobal[2*i ]; | |||
3149 | globalNodeID = discr->tessGlobal[2*i+1] + | |||
3150 | discr->bodys[bIndex-1].globalOffset; | |||
3151 | ||||
3152 | if (strcasecmp(dataName, "Displacement") == 0) { | |||
3153 | ||||
3154 | for (dataPoint = 0; dataPoint < numGridPoint; dataPoint++) { | |||
3155 | if ((int) dataMatrix[dataPoint][0] == globalNodeID) break; | |||
3156 | } | |||
3157 | ||||
3158 | if (dataPoint == numGridPoint) { | |||
3159 | printf("Unable to locate global ID = %d in the data matrix\n", | |||
3160 | globalNodeID); | |||
3161 | status = CAPS_NOTFOUND-303; | |||
3162 | goto cleanup; | |||
3163 | } | |||
3164 | ||||
3165 | dataVal[dataRank*i+0] = dataMatrix[dataPoint][2]; // T1 | |||
3166 | dataVal[dataRank*i+1] = dataMatrix[dataPoint][3]; // T2 | |||
3167 | dataVal[dataRank*i+2] = dataMatrix[dataPoint][4]; // T3 | |||
3168 | ||||
3169 | } else if (strncmp(dataName, "EigenVector", 11) == 0) { | |||
3170 | ||||
3171 | ||||
3172 | for (dataPoint = 0; dataPoint < numGridPoint; dataPoint++) { | |||
3173 | if ((int) dataMatrix[eigenVectorIndex - 1][8*dataPoint + 0] == | |||
3174 | globalNodeID) break; | |||
3175 | } | |||
3176 | ||||
3177 | if (dataPoint == numGridPoint) { | |||
3178 | printf("Unable to locate global ID = %d in the data matrix\n", | |||
3179 | globalNodeID); | |||
3180 | status = CAPS_NOTFOUND-303; | |||
3181 | goto cleanup; | |||
3182 | } | |||
3183 | ||||
3184 | dataVal[dataRank*i+0] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 2]; // T1 | |||
3185 | dataVal[dataRank*i+1] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 3]; // T2 | |||
3186 | dataVal[dataRank*i+2] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 4]; // T3 | |||
3187 | //dataVal[dataRank*i+3] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 5]; // R1 - Don't use rotations | |||
3188 | //dataVal[dataRank*i+4] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 6]; // R2 | |||
3189 | //dataVal[dataRank*i+5] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 7]; // R3 | |||
3190 | ||||
3191 | } | |||
3192 | } | |||
3193 | ||||
3194 | status = CAPS_SUCCESS0; | |||
3195 | ||||
3196 | cleanup: | |||
3197 | ||||
3198 | if (fp != NULL((void*)0)) fclose(fp); | |||
3199 | // Free data matrix | |||
3200 | if (dataMatrix != NULL((void*)0)) { | |||
3201 | j = 0; | |||
3202 | if (strcasecmp(dataName, "Displacement") == 0) j = numGridPoint; | |||
3203 | else if (strncmp(dataName, "EigenVector", 11) == 0) j = numEigenVector; | |||
3204 | ||||
3205 | for (i = 0; i < j; i++) { | |||
3206 | if (dataMatrix[i] != NULL((void*)0)) EG_free(dataMatrix[i]); | |||
3207 | } | |||
3208 | EG_free(dataMatrix); | |||
3209 | } | |||
3210 | ||||
3211 | return status; | |||
3212 | } | |||
3213 | ||||
3214 | ||||
3215 | void aimFreeDiscrPtr(void *ptr) | |||
3216 | { | |||
3217 | // Extra information to store into the discr void pointer - just a int array | |||
3218 | EG_free(ptr); | |||
3219 | } | |||
3220 | ||||
3221 | ||||
3222 | int aimLocateElement(capsDiscr *discr, double *params, double *param, | |||
3223 | int *bIndex, int *eIndex, double *bary) | |||
3224 | { | |||
3225 | #ifdef DEBUG | |||
3226 | printf(" nastranAIM/aimLocateElement !\n"); | |||
3227 | #endif | |||
3228 | ||||
3229 | return aim_locateElement(discr, params, param, bIndex, eIndex, bary); | |||
3230 | } | |||
3231 | ||||
3232 | ||||
3233 | int aimInterpolation(capsDiscr *discr, const char *name, | |||
3234 | int bIndex, int eIndex, double *bary, | |||
3235 | int rank, double *data, double *result) | |||
3236 | { | |||
3237 | #ifdef DEBUG | |||
3238 | printf(" nastranAIM/aimInterpolation %s!\n", name); | |||
3239 | #endif | |||
3240 | ||||
3241 | return aim_interpolation(discr, name, bIndex, eIndex, bary, rank, data, | |||
3242 | result); | |||
3243 | } | |||
3244 | ||||
3245 | ||||
3246 | int aimInterpolateBar(capsDiscr *discr, const char *name, | |||
3247 | int bIndex, int eIndex, double *bary, | |||
3248 | int rank, double *r_bar, double *d_bar) | |||
3249 | { | |||
3250 | #ifdef DEBUG | |||
3251 | printf(" nastranAIM/aimInterpolateBar %s!\n", name); | |||
3252 | #endif | |||
3253 | ||||
3254 | return aim_interpolateBar(discr, name, bIndex, eIndex, bary, rank, r_bar, | |||
3255 | d_bar); | |||
3256 | } | |||
3257 | ||||
3258 | ||||
3259 | int aimIntegration(capsDiscr *discr, const char *name,int bIndex, int eIndex, | |||
3260 | int rank, double *data, double *result) | |||
3261 | { | |||
3262 | #ifdef DEBUG | |||
3263 | printf(" nastranAIM/aimIntegration %s!\n", name); | |||
3264 | #endif | |||
3265 | ||||
3266 | return aim_integration(discr, name, bIndex, eIndex, rank, data, result); | |||
3267 | } | |||
3268 | ||||
3269 | ||||
3270 | int aimIntegrateBar(capsDiscr *discr, const char *name, int bIndex, int eIndex, | |||
3271 | int rank, double *r_bar, double *d_bar) | |||
3272 | { | |||
3273 | #ifdef DEBUG | |||
3274 | printf(" nastranAIM/aimIntegrateBar %s!\n", name); | |||
3275 | #endif | |||
3276 | ||||
3277 | return aim_integrateBar(discr, name, bIndex, eIndex, rank, r_bar, d_bar); | |||
3278 | } |