Bug Summary

File:nastran/nastranAIM.c
Warning:line 1980, column 21
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name nastranAIM.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D REVISION=7.6 -I /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/ESP/LINUX64/include -I ../utils -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-dangling-else -Wno-parentheses -Wno-unused-result -Wno-format-truncation -fdebug-compilation-dir /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/CAPS/aim/nastran -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/scanCAPS/2022-04-21-160214-102256-1 -x c nastranAIM.c
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
117enum 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
154typedef 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
189static 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
240static 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
306static 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
389cleanup:
390 return status;
391}
392
393
394static 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
886cleanup:
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
909int 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
968cleanup:
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
984int 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
1400cleanup:
1401 if (status != CAPS_SUCCESS0) AIM_FREE(*ainame){ EG_free(*ainame); *ainame = ((void*)0); };
1402 return status;
1403}
1404
1405
1406// ********************** AIM Function Break *****************************
1407int 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;
1642cleanup:
1643 return status;
1644}
1645
1646int 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);
1
'feaLoad' initialized to a null pointer value
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; } }
;
2
Assuming 'aimInputs' is not equal to null
3
Taking false branch
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;
4
Assuming 'filename' is not equal to NULL
5
Taking false branch
1694
1695 strcpy(filename, nastranInstance->projectName);
1696
1697 if (nastranInstance->feaProblem.numLoad > 0) {
6
Assuming field 'numLoad' is <= 0
7
Taking false branch
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) {
8
Assuming 'status' is equal to CAPS_SUCCESS
9
Taking false branch
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)) {
10
Assuming 'fp' is not equal to NULL
11
Taking false branch
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;
12
Assuming 'status' is equal to CAPS_SUCCESS
13
Taking false branch
1743
1744 // Connections
1745 for (i = 0; i < nastranInstance->feaProblem.numConnect; i++) {
14
Assuming 'i' is >= field 'numConnect'
15
Loop condition is false. Execution continues on line 1756
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
15.1
'fp' is not equal to NULL
!= NULL((void*)0)) fclose(fp);
16
Taking true branch
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;
17
Assuming 'filename' is not equal to NULL
18
Taking false branch
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)) {
19
Assuming 'fp' is not equal to NULL
20
Taking false branch
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) {
21
Assuming field 'fileType' is not equal to FreeField
22
Taking false branch
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");
23
Taking true branch
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);
24
Assuming field 'numNode' is <= 10000
25
Taking false branch
1802 else fprintf(fp, "LINE=10000\n");
1803
1804
1805 // Set up the case information
1806 if (nastranInstance->feaProblem.numAnalysis == 0) {
26
Assuming field 'numAnalysis' is not equal to 0
27
Taking false branch
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) ||
28
Assuming the condition is false
30
Taking false branch
1823 (strcasecmp(analysisType, "Optimization") == 0)) {
29
Assuming the condition is false
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++) {
31
Assuming 'i' is < field 'numAnalysis'
32
Loop condition is true. Entering loop body
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) {
33
Assuming field 'analysisType' is not equal to Static
34
Taking false branch
1844 fprintf(fp,"\tANALYSIS = STATICS\n");
1845 } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == Modal) {
35
Assuming field 'analysisType' is not equal to Modal
36
Taking false branch
1846 fprintf(fp,"\tANALYSIS = MODES\n");
1847 } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == AeroelasticTrim) {
37
Assuming field 'analysisType' is not equal to AeroelasticTrim
38
Taking false branch
1848 fprintf(fp,"\tANALYSIS = SAERO\n");
1849 haveSubAeroelasticTrim = (int) true1;
1850 } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == AeroelasticFlutter) {
39
Assuming field 'analysisType' is not equal to AeroelasticFlutter
40
Taking false branch
1851 fprintf(fp,"\tANALYSIS = FLUTTER\n");
1852 haveSubAeroelasticFlutter = (int) true1;
1853 } else if (nastranInstance->feaProblem.feaAnalysis[i].analysisType == Optimization) {
41
Assuming field 'analysisType' is not equal to Optimization
42
Taking false branch
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) {
43
Assuming field 'numSupport' is equal to 0
44
Taking false branch
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) {
45
Assuming field 'numConstraint' is equal to 0
46
Taking false branch
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) {
47
Assuming field 'numConstraint' is not equal to 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
47.1
Field 'numConstraint' is equal to 0
== 0) {
48
Taking true branch
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
48.1
Field 'analysisType' is not equal to Modal
== Modal) {
49
Taking false branch
1898 fprintf(fp,"\tMETHOD = %d\n", nastranInstance->feaProblem.feaAnalysis[i].analysisID);
1899 }
1900
1901 if (nastranInstance->feaProblem.feaAnalysis[i].analysisType
49.1
Field 'analysisType' is not equal to AeroelasticFlutter
== AeroelasticFlutter) {
50
Taking false branch
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
50.1
Field 'analysisType' is not equal to AeroelasticTrim
== AeroelasticTrim) {
51
Taking false branch
1907 fprintf(fp,"\tTRIM = %d\n", nastranInstance->feaProblem.feaAnalysis[i].analysisID);
1908 }
1909
1910 if (nastranInstance->feaProblem.feaAnalysis[i].analysisType
51.1
Field 'analysisType' is not equal to AeroelasticTrim
== AeroelasticTrim ||
52
Taking false branch
1911 nastranInstance->feaProblem.feaAnalysis[i].analysisType
51.2
Field 'analysisType' is not equal to AeroelasticFlutter
== AeroelasticFlutter) {
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) {
53
Assuming field 'numLoad' is equal to 0
54
Assuming field 'numLoad' is not equal to 0
55
Taking true branch
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
55.1
Field 'numLoad' is not equal to 0
!= 0) {
56
Taking true branch
1963
1964 found = (int) false0;
1965
1966 for (k = 0; k < nastranInstance->feaProblem.numLoad; k++) {
57
Assuming 'k' is < field 'numLoad'
58
Loop condition is true. Entering loop body
1967
1968 if (nastranInstance->feaProblem.feaAnalysis[i].numLoad
58.1
Field 'numLoad' is equal to 0
!= 0) { // if loads specified in analysis
59
Taking false branch
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) {
60
Dereference of null pointer
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
2719cleanup:
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 */
2738int 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
2746int 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
2801int 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
2916void 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
2934int 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
2966cleanup:
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
2976int 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
3196cleanup:
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
3215void 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
3222int 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
3233int 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
3246int 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
3259int 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
3270int 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}