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