File: | abaqus/abaqusAIM.c |
Warning: | line 1096, column 13 Value stored to 'status' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * CAPS: Computational Aircraft Prototype Syntheses |
3 | * |
4 | * Abaqus AIM |
5 | * |
6 | * Written by Dr. Ryan Durscher AFRL/RQVC |
7 | * |
8 | * * Copyright 2014-2023, Massachusetts Institute of Technology |
9 | * Licensed under The GNU Lesser General Public License, version 2.1 |
10 | * See http://www.opensource.org/licenses/lgpl-2.1.php |
11 | * |
12 | */ |
13 | |
14 | /*! \mainpage Introduction |
15 | * |
16 | * \section overviewAbaqus Abaqus AIM Overview |
17 | * A module in the Computational Aircraft Prototype Syntheses (CAPS) has been developed to interact (primarily |
18 | * through input files) with the finite element structural solver Abaqus \cite Abaqus. |
19 | * |
20 | * Current issues include: |
21 | * - A thorough bug testing needs to be undertaken. |
22 | * |
23 | * An outline of the AIM's inputs, outputs and attributes are provided in \ref aimInputsAbaqus and |
24 | * \ref aimOutputsAbaqus and \ref attributeAbaqus, respectively. |
25 | * |
26 | * Details of the AIM's shareable data structures are outlined in \ref sharableDataAbaqus if |
27 | * connecting this AIM to other AIMs in a parent-child like manner. |
28 | * |
29 | * Details of the AIM's automated data transfer capabilities are outlined in \ref dataTransferAbaqus |
30 | * |
31 | */ |
32 | |
33 | /* \section abaqusExamples Examples |
34 | * Example problems using the Abaqus AIM may be found at \ref examplesAbaqus . |
35 | * - \ref abaqusSingleLoadEx |
36 | * - \ref abaqusMultipleLoadEx |
37 | * - \ref abaqusModalEx |
38 | * - \ref abaqusOptEx |
39 | * - \ref abaqusCompositeEx |
40 | * - \ref abaqusCompOptimizationEx |
41 | */ |
42 | |
43 | /*! \page attributeAbaqus Abaqus AIM attributes |
44 | * The following list of attributes are required for the Abaqus AIM inside the geometry input. |
45 | * |
46 | * - <b> capsGroup</b> This is a name assigned to any geometric body. This body could be a solid, surface, face, wire, edge or node. |
47 | * Recall that a string in ESP starts with a $. For example, attribute <c>capsGroup $Wing</c>. |
48 | * |
49 | * - <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> |
50 | * attribute to allow the user to define a local area to apply a load on without adding multiple <c>capsGroup</c> attributes. |
51 | * Recall that a string in ESP starts with a $. For example, attribute <c>capsLoad $force</c>. |
52 | * |
53 | * - <b> capsConstraint</b> This is a name assigned to any geometric body where a constraint/boundary condition is applied. |
54 | * This attribute was separated from the <c>capsGroup</c> attribute to allow the user to define a local area to apply a boundary condition |
55 | * without adding multiple <c>capsGroup</c> attributes. Recall that a string in ESP starts with a $. For example, attribute <c>capsConstraint $fixed</c>. |
56 | * |
57 | * - <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 |
58 | * a finite element model. The capsIgnore attribute allows a body (or entity) to be in the geometry and ignored by the AIM. For example, |
59 | * because of limitations in OpenCASCADE a situation where two edges are overlapping may occur; capsIgnore allows the user to only |
60 | * pay attention to one of the overlapping edges. |
61 | * |
62 | */ |
63 | |
64 | /* - <b> capsConnect</b> This is a name assigned to any geometric body where the user wishes to create |
65 | * "fictitious" connections such as springs, dampers, and/or rigid body connections to. The user must manually specify |
66 | * the connection between two <c>capsConnect</c> entities using the "Connect" tuple (see \ref aimInputsAbaqus). |
67 | * Recall that a string in ESP starts with a $. For example, attribute <c>capsConnect $springStart</c>. |
68 | * |
69 | * - <b> capsConnectLink</b> Similar to <c>capsConnect</c>, this is a name assigned to any geometric body where |
70 | * the user wishes to create "fictitious" connections to. A connection is automatically made if a <c>capsConnectLink</c> |
71 | * matches a <c>capsConnect</c> group. Again further specifics of the connection are input using the "Connect" |
72 | * tuple (see \ref aimInputsAbaqus). Recall that a string in ESP starts with a $. |
73 | * For example, attribute <c>capsConnectLink $springEnd</c>. |
74 | * |
75 | * - <b> capsBound </b> This is used to mark surfaces on the structural grid in which data transfer with an external |
76 | * solver will take place. See \ref dataTransferAbaqus for additional details. |
77 | * |
78 | * |
79 | */ |
80 | |
81 | #include <string.h> |
82 | #include <math.h> |
83 | #include "capsTypes.h" |
84 | #include "aimUtil.h" |
85 | |
86 | #include "meshUtils.h" // Meshing utilities |
87 | #include "miscUtils.h" // Miscellaneous utilities |
88 | #include "vlmUtils.h" // Vortex lattice method utilities |
89 | #include "feaUtils.h" // FEA utilities |
90 | #include "abaqusUtils.h" // Abaqus utilities |
91 | |
92 | #ifdef WIN32 |
93 | #define getcwd _getcwd |
94 | #define snprintf _snprintf |
95 | #define strcasecmp stricmp |
96 | #define PATH_MAX4096 _MAX_PATH |
97 | #else |
98 | #include <unistd.h> |
99 | #include <limits.h> |
100 | #endif |
101 | |
102 | //#define DEBUG |
103 | |
104 | enum aimInputs |
105 | { |
106 | Proj_Name = 1, /* index is 1-based */ |
107 | Property, |
108 | Material, |
109 | Constraint, |
110 | Load, |
111 | Analysix, |
112 | Analysis_Type, |
113 | Support, |
114 | Connect, |
115 | Mesh_Morph, |
116 | Mesh, |
117 | NUMINPUT = Mesh /* Total number of inputs */ |
118 | }; |
119 | |
120 | #define NUMOUTPUT0 0 |
121 | |
122 | typedef struct { |
123 | |
124 | // Project name |
125 | char *projectName; // Project name |
126 | |
127 | feaUnitsStruct units; // units system |
128 | |
129 | feaProblemStruct feaProblem; |
130 | |
131 | // Attribute to index map |
132 | mapAttrToIndexStruct attrMap; |
133 | |
134 | // Attribute to constraint index map |
135 | mapAttrToIndexStruct constraintMap; |
136 | |
137 | // Attribute to load index map |
138 | mapAttrToIndexStruct loadMap; |
139 | |
140 | // Attribute to transfer map |
141 | mapAttrToIndexStruct transferMap; |
142 | |
143 | // Attribute to connect map |
144 | mapAttrToIndexStruct connectMap; |
145 | |
146 | // Attribute to response map |
147 | mapAttrToIndexStruct responseMap; |
148 | |
149 | // Mesh holders |
150 | int numMesh; |
151 | meshStruct *feaMesh; |
152 | |
153 | } aimStorage; |
154 | |
155 | |
156 | static int initiate_aimStorage(void *aimInfo, aimStorage *abaqusInstance) { |
157 | |
158 | int status; |
159 | |
160 | // Set initial values for abaqusInstance |
161 | abaqusInstance->projectName = NULL((void*)0); |
162 | |
163 | status = initiate_feaUnitsStruct(&abaqusInstance->units); |
164 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 164, __func__, 0); goto cleanup; }; |
165 | |
166 | // Container for attribute to index map |
167 | status = initiate_mapAttrToIndexStruct(&abaqusInstance->attrMap); |
168 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 168, __func__, 0); goto cleanup; }; |
169 | |
170 | // Container for attribute to constraint index map |
171 | status = initiate_mapAttrToIndexStruct(&abaqusInstance->constraintMap); |
172 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 172, __func__, 0); goto cleanup; }; |
173 | |
174 | // Container for attribute to load index map |
175 | status = initiate_mapAttrToIndexStruct(&abaqusInstance->loadMap); |
176 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 176, __func__, 0); goto cleanup; }; |
177 | |
178 | // Container for transfer to index map |
179 | status = initiate_mapAttrToIndexStruct(&abaqusInstance->transferMap); |
180 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 180, __func__, 0); goto cleanup; }; |
181 | |
182 | // Container for connect to index map |
183 | status = initiate_mapAttrToIndexStruct(&abaqusInstance->connectMap); |
184 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 184, __func__, 0); goto cleanup; }; |
185 | |
186 | // Container for response to index map |
187 | status = initiate_mapAttrToIndexStruct(&abaqusInstance->responseMap); |
188 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 188, __func__, 0); goto cleanup; }; |
189 | |
190 | status = initiate_feaProblemStruct(&abaqusInstance->feaProblem); |
191 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 191, __func__, 0); goto cleanup; }; |
192 | |
193 | // Mesh holders |
194 | abaqusInstance->numMesh = 0; |
195 | abaqusInstance->feaMesh = NULL((void*)0); |
196 | |
197 | cleanup: |
198 | return status; |
199 | } |
200 | |
201 | static int destroy_aimStorage(aimStorage *abaqusInstance) { |
202 | |
203 | int status; |
204 | int i; |
205 | |
206 | status = destroy_feaUnitsStruct(&abaqusInstance->units); |
207 | if (status != CAPS_SUCCESS0) |
208 | printf("Error: Status %d during destroy_feaUnitsStruct!\n", status); |
209 | |
210 | // Attribute to index map |
211 | status = destroy_mapAttrToIndexStruct(&abaqusInstance->attrMap); |
212 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); |
213 | |
214 | // Attribute to constraint index map |
215 | status = destroy_mapAttrToIndexStruct(&abaqusInstance->constraintMap); |
216 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); |
217 | |
218 | // Attribute to load index map |
219 | status = destroy_mapAttrToIndexStruct(&abaqusInstance->loadMap); |
220 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); |
221 | |
222 | // Transfer to index map |
223 | status = destroy_mapAttrToIndexStruct(&abaqusInstance->transferMap); |
224 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); |
225 | |
226 | // Connect to index map |
227 | status = destroy_mapAttrToIndexStruct(&abaqusInstance->connectMap); |
228 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); |
229 | |
230 | // Response to index map |
231 | status = destroy_mapAttrToIndexStruct(&abaqusInstance->responseMap); |
232 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_mapAttrToIndexStruct!\n", status); |
233 | |
234 | // Cleanup meshes |
235 | if (abaqusInstance->feaMesh != NULL((void*)0)) { |
236 | |
237 | for (i = 0; i < abaqusInstance->numMesh; i++) { |
238 | status = destroy_meshStruct(&abaqusInstance->feaMesh[i]); |
239 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_meshStruct!\n", status); |
240 | } |
241 | |
242 | EG_free(abaqusInstance->feaMesh); |
243 | } |
244 | |
245 | abaqusInstance->feaMesh = NULL((void*)0); |
246 | abaqusInstance->numMesh = 0; |
247 | |
248 | // Destroy FEA problem structure |
249 | status = destroy_feaProblemStruct(&abaqusInstance->feaProblem); |
250 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during destroy_feaProblemStruct!\n", status); |
251 | |
252 | // NULL projetName |
253 | abaqusInstance->projectName = NULL((void*)0); |
254 | |
255 | return CAPS_SUCCESS0; |
256 | } |
257 | |
258 | static int checkAndCreateMesh(void* aimInfo, aimStorage *abaqusInstance) |
259 | { |
260 | // Function return flag |
261 | int status = CAPS_SUCCESS0; |
262 | |
263 | status = fea_createMesh(aimInfo, |
264 | NULL((void*)0), |
265 | 0, |
266 | 0, |
267 | (int)false0, |
268 | &abaqusInstance->attrMap, |
269 | &abaqusInstance->constraintMap, |
270 | &abaqusInstance->loadMap, |
271 | &abaqusInstance->transferMap, |
272 | &abaqusInstance->connectMap, |
273 | &abaqusInstance->responseMap, |
274 | NULL((void*)0), |
275 | &abaqusInstance->numMesh, |
276 | &abaqusInstance->feaMesh, |
277 | &abaqusInstance->feaProblem ); |
278 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 278, __func__, 0); goto cleanup; }; |
279 | |
280 | cleanup: |
281 | return status; |
282 | } |
283 | |
284 | /* ********************** Exposed AIM Functions ***************************** */ |
285 | |
286 | int aimInitialize(int inst, /*@unused@*/ const char *unitSys, void *aimInfo, |
287 | /*@unused@*/ void **instStore, /*@unused@*/ int *major, |
288 | /*@unused@*/ int *minor, int *nIn, int *nOut, |
289 | int *nFields, char ***fnames, int **franks, int **fInOut) |
290 | { |
291 | int status = CAPS_SUCCESS0; |
292 | int i; |
293 | int *ints=NULL((void*)0); |
294 | char **strs=NULL((void*)0); |
295 | |
296 | aimStorage *abaqusInstance=NULL((void*)0); |
297 | |
298 | #ifdef DEBUG |
299 | printf("\n abaqusAIM/aimInitialize ngIn = %d!\n", ngIn); |
300 | #endif |
301 | |
302 | /* specify the number of analysis input and out "parameters" */ |
303 | *nIn = NUMINPUT; |
304 | *nOut = NUMOUTPUT0; |
305 | if (inst == 1) return CAPS_SUCCESS0; |
306 | |
307 | /* specify the field variables this analysis can generate */ |
308 | *nFields = 4; |
309 | |
310 | /* specify the name of each field variable */ |
311 | AIM_ALLOC(strs, *nFields, char *, aimInfo, status){ if (strs != ((void*)0)) { status = -4; aim_status(aimInfo, status , "abaqusAIM.c", 311, __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, "abaqusAIM.c" , 311, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "strs", memorysize, "char *"); goto cleanup; } }; |
312 | |
313 | strs[0] = EG_strdup("Displacement"); |
314 | strs[1] = EG_strdup("EigenVector"); |
315 | strs[2] = EG_strdup("EigenVector_*"); |
316 | strs[3] = EG_strdup("Pressure"); |
317 | for (i = 0; i < *nFields; i++) |
318 | if (strs[i] == NULL((void*)0)) { status = EGADS_MALLOC-4; goto cleanup; } |
319 | *fnames = strs; |
320 | |
321 | /* specify the dimension of each field variable */ |
322 | AIM_ALLOC(ints, *nFields, int, aimInfo, status){ if (ints != ((void*)0)) { status = -4; aim_status(aimInfo, status , "abaqusAIM.c", 322, __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, "abaqusAIM.c", 322, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "ints", memorysize , "int"); goto cleanup; } }; |
323 | ints[0] = 3; |
324 | ints[1] = 3; |
325 | ints[2] = 3; |
326 | ints[3] = 1; |
327 | *franks = ints; |
328 | ints = NULL((void*)0); |
329 | |
330 | /* specify if a field is an input field or output field */ |
331 | AIM_ALLOC(ints, *nFields, int, aimInfo, status){ if (ints != ((void*)0)) { status = -4; aim_status(aimInfo, status , "abaqusAIM.c", 331, __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, "abaqusAIM.c", 331, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "ints", memorysize , "int"); goto cleanup; } }; |
332 | |
333 | ints[0] = FieldOut; |
334 | ints[1] = FieldOut; |
335 | ints[2] = FieldOut; |
336 | ints[3] = FieldIn; |
337 | *fInOut = ints; |
338 | ints = NULL((void*)0); |
339 | |
340 | // Allocate abaqusInstance |
341 | AIM_ALLOC(abaqusInstance, 1, aimStorage, aimInfo, status){ if (abaqusInstance != ((void*)0)) { status = -4; aim_status (aimInfo, status, "abaqusAIM.c", 341, __func__, 1, "AIM_ALLOC: %s != NULL" , "abaqusInstance"); goto cleanup; } size_t memorysize = 1; abaqusInstance = (aimStorage *) EG_alloc(memorysize*sizeof(aimStorage)); if (abaqusInstance == ((void*)0)) { status = -4; aim_status(aimInfo , status, "abaqusAIM.c", 341, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "abaqusInstance", memorysize, "aimStorage"); goto cleanup; } }; |
342 | *instStore = abaqusInstance; |
343 | |
344 | // Initialize instance storage |
345 | (void) initiate_aimStorage(aimInfo, abaqusInstance); |
346 | |
347 | cleanup: |
348 | if (status != CAPS_SUCCESS0) { |
349 | /* release all possibly allocated memory on error */ |
350 | if (*fnames != NULL((void*)0)) |
351 | for (i = 0; i < *nFields; i++) AIM_FREE((*fnames)[i]){ EG_free((*fnames)[i]); (*fnames)[i] = ((void*)0); }; |
352 | AIM_FREE(*franks){ EG_free(*franks); *franks = ((void*)0); }; |
353 | AIM_FREE(*fInOut){ EG_free(*fInOut); *fInOut = ((void*)0); }; |
354 | AIM_FREE(*fnames){ EG_free(*fnames); *fnames = ((void*)0); }; |
355 | AIM_FREE(*instStore){ EG_free(*instStore); *instStore = ((void*)0); }; |
356 | *nFields = 0; |
357 | } |
358 | |
359 | return status; |
360 | } |
361 | |
362 | int aimInputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, |
363 | int index, char **ainame, capsValue *defval) |
364 | { |
365 | |
366 | /*! \page aimInputsAbaqus AIM Inputs |
367 | * The following list outlines the Abaqus inputs along with their default value available |
368 | * through the AIM interface. Unless noted these values will be not be linked to |
369 | * any parent AIMs with variables of the same name. |
370 | */ |
371 | |
372 | int status = CAPS_SUCCESS0; |
373 | |
374 | #ifdef DEBUG |
375 | printf(" abaqusAIM/aimInputs instance = %d index = %d!\n", inst, index); |
376 | #endif |
377 | |
378 | *ainame = NULL((void*)0); |
379 | |
380 | // Abaqus Inputs |
381 | if (index == Proj_Name) { |
382 | *ainame = EG_strdup("Proj_Name"); |
383 | defval->type = String; |
384 | defval->nullVal = NotNull; |
385 | defval->vals.string = EG_strdup("abaqus_CAPS"); |
386 | defval->lfixed = Change; |
387 | |
388 | /*! \page aimInputsAbaqus |
389 | * - <B> Proj_Name = "Abaqus_CAPS"</B> <br> |
390 | * This corresponds to the project name used for file naming. |
391 | */ |
392 | |
393 | } else if (index == Property) { |
394 | *ainame = EG_strdup("Property"); |
395 | defval->type = Tuple; |
396 | defval->nullVal = IsNull; |
397 | //defval->units = NULL; |
398 | defval->lfixed = Change; |
399 | defval->vals.tuple = NULL((void*)0); |
400 | defval->dim = Vector; |
401 | |
402 | /*! \page aimInputsAbaqus |
403 | * - <B> Property = NULL</B> <br> |
404 | * Property tuple used to input property information for the model, see \ref feaProperty for additional details. |
405 | */ |
406 | } else if (index == Material) { |
407 | *ainame = EG_strdup("Material"); |
408 | defval->type = Tuple; |
409 | defval->nullVal = IsNull; |
410 | //defval->units = NULL; |
411 | defval->lfixed = Change; |
412 | defval->vals.tuple = NULL((void*)0); |
413 | defval->dim = Vector; |
414 | |
415 | /*! \page aimInputsAbaqus |
416 | * - <B> Material = NULL</B> <br> |
417 | * Material tuple used to input material information for the model, see \ref feaMaterial for additional details. |
418 | */ |
419 | } else if (index == Constraint) { |
420 | *ainame = EG_strdup("Constraint"); |
421 | defval->type = Tuple; |
422 | defval->nullVal = IsNull; |
423 | //defval->units = NULL; |
424 | defval->lfixed = Change; |
425 | defval->vals.tuple = NULL((void*)0); |
426 | defval->dim = Vector; |
427 | |
428 | /*! \page aimInputsAbaqus |
429 | * - <B> Constraint = NULL</B> <br> |
430 | * Constraint tuple used to input constraint information for the model, see \ref feaConstraint for additional details. |
431 | */ |
432 | } else if (index == Load) { |
433 | *ainame = EG_strdup("Load"); |
434 | defval->type = Tuple; |
435 | defval->nullVal = IsNull; |
436 | //defval->units = NULL; |
437 | defval->lfixed = Change; |
438 | defval->vals.tuple = NULL((void*)0); |
439 | defval->dim = Vector; |
440 | |
441 | /*! \page aimInputsAbaqus |
442 | * - <B> Load = NULL</B> <br> |
443 | * Load tuple used to input load information for the model, see \ref feaLoad for additional details. |
444 | */ |
445 | } else if (index == Analysix) { |
446 | *ainame = EG_strdup("Analysis"); |
447 | defval->type = Tuple; |
448 | defval->nullVal = IsNull; |
449 | //defval->units = NULL; |
450 | defval->lfixed = Change; |
451 | defval->vals.tuple = NULL((void*)0); |
452 | defval->dim = Vector; |
453 | |
454 | /*! \page aimInputsAbaqus |
455 | * - <B> Analysis = NULL</B> <br> |
456 | * Analysis tuple used to input analysis/case information for the model, see \ref feaAnalysis for additional details. |
457 | */ |
458 | } else if (index == Analysis_Type) { |
459 | *ainame = EG_strdup("Analysis_Type"); |
460 | defval->type = String; |
461 | defval->nullVal = NotNull; |
462 | defval->vals.string = EG_strdup("Modal"); |
463 | defval->lfixed = Change; |
464 | |
465 | /*! \page aimInputsAbaqus |
466 | * - <B> Analysis_Type = "Modal"</B> <br> |
467 | * Type of analysis to generate files for, options include "Modal", "Static". |
468 | */ |
469 | } else if (index == Support) { |
470 | *ainame = EG_strdup("Support"); |
471 | defval->type = Tuple; |
472 | defval->nullVal = IsNull; |
473 | //defval->units = NULL; |
474 | defval->lfixed = Change; |
475 | defval->vals.tuple = NULL((void*)0); |
476 | defval->dim = Vector; |
477 | |
478 | /* \page aimInputsAbaqus |
479 | * - <B> Support = NULL</B> <br> |
480 | * Support tuple used to input support information for the model, see \ref feaSupport for additional details. |
481 | */ |
482 | } else if (index == Connect) { |
483 | *ainame = EG_strdup("Connect"); |
484 | defval->type = Tuple; |
485 | defval->nullVal = IsNull; |
486 | //defval->units = NULL; |
487 | defval->lfixed = Change; |
488 | defval->vals.tuple = NULL((void*)0); |
489 | defval->dim = Vector; |
490 | |
491 | /* \page aimInputsAbaqus |
492 | * - <B> Connect = NULL</B> <br> |
493 | * Connect tuple used to define connection to be made in the, see \ref feaConnection for additional details. |
494 | */ |
495 | |
496 | } else if (index == Mesh_Morph) { |
497 | *ainame = EG_strdup("Mesh_Morph"); |
498 | defval->type = Boolean; |
499 | defval->lfixed = Fixed; |
500 | defval->vals.integer = (int) false0; |
501 | defval->dim = Scalar; |
502 | defval->nullVal = NotNull; |
503 | |
504 | /*! \page aimInputsAbaqus |
505 | * - <B> Mesh_Morph = False</B> <br> |
506 | * Project previous surface mesh onto new geometry. |
507 | */ |
508 | |
509 | } else if (index == Mesh) { |
510 | *ainame = AIM_NAME(Mesh)EG_strdup("Mesh"); |
511 | defval->type = PointerMesh; |
512 | defval->dim = Vector; |
513 | defval->lfixed = Change; |
514 | defval->sfixed = Change; |
515 | defval->vals.AIMptr = NULL((void*)0); |
516 | defval->nullVal = IsNull; |
517 | |
518 | /*! \page aimInputsAbaqus |
519 | * - <B>Mesh = NULL</B> <br> |
520 | * A Mesh link. |
521 | */ |
522 | |
523 | } else { |
524 | AIM_ERROR(aimInfo, "Unknown input index %d", index){ aim_message(aimInfo, CERROR, 0 , "abaqusAIM.c", 524, __func__ , "Unknown input index %d", index); }; |
525 | status = CAPS_BADINDEX-304; |
526 | goto cleanup; |
527 | } |
528 | |
529 | AIM_NOTNULL(*ainame, aimInfo, status){ if (*ainame == ((void*)0)) { status = -307; aim_status(aimInfo , status, "abaqusAIM.c", 529, __func__, 1, "%s == NULL!", "*ainame" ); goto cleanup; } }; |
530 | |
531 | cleanup: |
532 | if (status != CAPS_SUCCESS0) AIM_FREE(*ainame){ EG_free(*ainame); *ainame = ((void*)0); }; |
533 | return status; |
534 | } |
535 | |
536 | |
537 | // ********************** AIM Function Break ***************************** |
538 | int aimUpdateState(void *instStore, void *aimInfo, |
539 | capsValue *aimInputs) |
540 | { |
541 | int status; // Function return status |
542 | int i; |
543 | |
544 | // Analysis information |
545 | const char *analysisType = NULL((void*)0); |
546 | |
547 | aimStorage *abaqusInstance; |
548 | |
549 | abaqusInstance = (aimStorage *) instStore; |
550 | AIM_NOTNULL(aimInputs, aimInfo, status){ if (aimInputs == ((void*)0)) { status = -307; aim_status(aimInfo , status, "abaqusAIM.c", 550, __func__, 1, "%s == NULL!", "aimInputs" ); goto cleanup; } }; |
551 | |
552 | if (aimInputs[Mesh-1].nullVal == IsNull && |
553 | aimInputs[Mesh_Morph-1].vals.integer == (int) false0) { |
554 | AIM_ANALYSISIN_ERROR(aimInfo, Mesh, "'Mesh' input must be linked to an output 'Surface_Mesh'"){ aim_message(aimInfo, CERROR, Mesh, "abaqusAIM.c", 554, __func__ , "'Mesh' input must be linked to an output 'Surface_Mesh'"); }; |
555 | status = CAPS_BADVALUE-311; |
556 | goto cleanup; |
557 | } |
558 | |
559 | // Get project name |
560 | abaqusInstance->projectName = aimInputs[Proj_Name-1].vals.string; |
561 | |
562 | // Analysis type |
563 | analysisType = aimInputs[Analysis_Type-1].vals.string; |
564 | |
565 | // Get FEA mesh if we don't already have one |
566 | if (aim_newGeometry(aimInfo) == CAPS_SUCCESS0) { |
567 | |
568 | status = checkAndCreateMesh(aimInfo, abaqusInstance); |
569 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 569, __func__, 0); goto cleanup; }; |
570 | } |
571 | |
572 | // Note: Setting order is important here. |
573 | // 1. Materials should be set before properties. |
574 | // 2. Coordinate system should be set before mesh and loads |
575 | // 3. Mesh should be set before loads, constraints, supports, and connections |
576 | // 4. Constraints and loads should be set before analysis |
577 | // 5. Optimization should be set after properties, but before analysis |
578 | |
579 | // Set material properties |
580 | if (aimInputs[Material-1].nullVal == NotNull) { |
581 | status = fea_getMaterial(aimInfo, |
582 | aimInputs[Material-1].length, |
583 | aimInputs[Material-1].vals.tuple, |
584 | &abaqusInstance->units, |
585 | &abaqusInstance->feaProblem.numMaterial, |
586 | &abaqusInstance->feaProblem.feaMaterial); |
587 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 587, __func__, 0); goto cleanup; }; |
588 | } else printf("Material tuple is NULL - No materials set\n"); |
589 | |
590 | // Set property properties |
591 | if (aimInputs[Property-1].nullVal == NotNull) { |
592 | status = fea_getProperty(aimInfo, |
593 | aimInputs[Property-1].length, |
594 | aimInputs[Property-1].vals.tuple, |
595 | &abaqusInstance->attrMap, |
596 | &abaqusInstance->units, |
597 | &abaqusInstance->feaProblem); |
598 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 598, __func__, 0); goto cleanup; }; |
599 | |
600 | |
601 | // Assign element "subtypes" based on properties set |
602 | status = fea_assignElementSubType(abaqusInstance->feaProblem.numProperty, |
603 | abaqusInstance->feaProblem.feaProperty, |
604 | &abaqusInstance->feaProblem.feaMesh); |
605 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 605, __func__, 0); goto cleanup; }; |
606 | |
607 | } else printf("Property tuple is NULL - No properties set\n"); |
608 | |
609 | // Set constraint properties |
610 | if (aimInputs[Constraint-1].nullVal == NotNull) { |
611 | status = fea_getConstraint(aimInfo, |
612 | aimInputs[Constraint-1].length, |
613 | aimInputs[Constraint-1].vals.tuple, |
614 | &abaqusInstance->constraintMap, |
615 | &abaqusInstance->feaProblem); |
616 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 616, __func__, 0); goto cleanup; }; |
617 | } else printf("Constraint tuple is NULL - No constraints applied\n"); |
618 | |
619 | // Set support properties |
620 | if (aimInputs[Support-1].nullVal == NotNull) { |
621 | status = fea_getSupport(aimInputs[Support-1].length, |
622 | aimInputs[Support-1].vals.tuple, |
623 | &abaqusInstance->constraintMap, |
624 | &abaqusInstance->feaProblem); |
625 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 625, __func__, 0); goto cleanup; }; |
626 | } else printf("Support tuple is NULL - No supports applied\n"); |
627 | |
628 | // Set connection properties |
629 | if (aimInputs[Connect-1].nullVal == NotNull) { |
630 | status = fea_getConnection(aimInfo, |
631 | aimInputs[aim_getIndex(aimInfo, "Connect", ANALYSISIN)-1].length, |
632 | aimInputs[aim_getIndex(aimInfo, "Connect", ANALYSISIN)-1].vals.tuple, |
633 | &abaqusInstance->connectMap, |
634 | &abaqusInstance->feaProblem); |
635 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 635, __func__, 0); goto cleanup; }; |
636 | } else printf("Connect tuple is NULL - Using defaults\n"); |
637 | |
638 | // Set load properties |
639 | if (aimInputs[Load-1].nullVal == NotNull) { |
640 | status = fea_getLoad(aimInfo, |
641 | aimInputs[Load-1].length, |
642 | aimInputs[Load-1].vals.tuple, |
643 | &abaqusInstance->loadMap, |
644 | &abaqusInstance->feaProblem); |
645 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 645, __func__, 0); goto cleanup; }; |
646 | |
647 | // Loop through loads to see if any of them are supposed to be from an external source |
648 | for (i = 0; i < abaqusInstance->feaProblem.numLoad; i++) { |
649 | |
650 | if (abaqusInstance->feaProblem.feaLoad[i].loadType == PressureExternal) { |
651 | |
652 | // Transfer external pressures from the AIM discrObj |
653 | status = fea_transferExternalPressure(aimInfo, |
654 | &abaqusInstance->feaProblem.feaMesh, |
655 | &abaqusInstance->feaProblem.feaLoad[i]); |
656 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 656, __func__, 0); goto cleanup; }; |
657 | |
658 | } // End PressureExternal if |
659 | } // End load for loop |
660 | } else printf("Load tuple is NULL - No loads applied\n"); |
661 | |
662 | // Set analysis settings |
663 | if (aimInputs[Analysix-1].nullVal == NotNull) { |
664 | status = fea_getAnalysis(aimInfo, |
665 | aimInputs[Analysix-1].length, |
666 | aimInputs[Analysix-1].vals.tuple, |
667 | &abaqusInstance->feaProblem); |
668 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 668, __func__, 0); goto cleanup; }; |
669 | } else { |
670 | printf("Analysis tuple is NULL\n"); // Its ok to not have an analysis tuple we will just create one |
671 | |
672 | status = fea_createDefaultAnalysis(aimInfo, &abaqusInstance->feaProblem, analysisType); |
673 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 673, __func__, 0); goto cleanup; }; |
674 | } |
675 | |
676 | cleanup: |
677 | return status; |
678 | } |
679 | |
680 | |
681 | // ********************** AIM Function Break ***************************** |
682 | int aimPreAnalysis(const void *instStore, void *aimInfo, capsValue *aimInputs) |
683 | { |
684 | |
685 | int i; // Indexing |
686 | |
687 | int status; // Status return |
688 | |
689 | int *tempIntegerArray = NULL((void*)0); // Temporary array to store a list of integers |
690 | |
691 | // Optimization Information |
692 | //char *objectiveMinMax = NULL, *objectiveResp = NULL; |
693 | |
694 | // File format information |
695 | //char *tempString = NULL, *delimiter = NULL; |
696 | |
697 | // File IO |
698 | char filename[PATH_MAX4096]; // Output file name |
699 | FILE *fp = NULL((void*)0); // Output file pointer |
700 | |
701 | const aimStorage *abaqusInstance; |
702 | |
703 | abaqusInstance = (const aimStorage *) instStore; |
704 | AIM_NOTNULL(aimInputs, aimInfo, status){ if (aimInputs == ((void*)0)) { status = -307; aim_status(aimInfo , status, "abaqusAIM.c", 704, __func__, 1, "%s == NULL!", "aimInputs" ); goto cleanup; } }; |
705 | |
706 | // Write Abaqus Mesh |
707 | status = mesh_writeAbaqus(aimInfo, |
708 | abaqusInstance->projectName, |
709 | 1, |
710 | &abaqusInstance->feaProblem.feaMesh, |
711 | 1.0); // Scale factor for coordinates |
712 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 712, __func__, 0); goto cleanup; }; |
713 | |
714 | // Write Abaqus input file |
715 | snprintf(filename, PATH_MAX4096, "%s.inp", abaqusInstance->projectName); |
716 | |
717 | printf("\nWriting Abaqus instruction file....\n"); |
718 | fp = aim_fopen(aimInfo, filename, "w"); |
719 | |
720 | if (fp == NULL((void*)0)) { |
721 | printf("Unable to open file: %s\n", filename); |
722 | status = CAPS_IOERR-332; |
723 | goto cleanup; |
724 | } |
725 | |
726 | // Heading |
727 | fprintf(fp, "*HEADING\n"); |
728 | fprintf(fp, "CAPS generated problem for Abaqus\n"); |
729 | |
730 | |
731 | /* |
732 | // Analysis type |
733 | analysisType = aimInputs[aim_getIndex(aimInfo, "Analysis_Type", ANALYSISIN)-1].vals.string; |
734 | |
735 | if (strcasecmp(analysisType, "Modal") == 0) fprintf(fp, "SOL 3\n"); |
736 | else if(strcasecmp(analysisType, "Static") == 0) fprintf(fp, "SOL 1\n"); |
737 | else if(strcasecmp(analysisType, "Craig-Bampton") == 0) fprintf(fp, "SOL 31\n"); |
738 | else { |
739 | printf("Unrecognized \"Analysis_Type\", %s, defaulting to \"Modal\" analysis\n", analysisType); |
740 | analysisType = "Modal"; |
741 | fprintf(fp, "SOL 3\n"); |
742 | } |
743 | */ |
744 | |
745 | // Model definition |
746 | fprintf(fp, "**\n**Model Definition\n**\n"); |
747 | |
748 | // Include mesh file |
749 | //fprintf(fp, "*PART, name=TEST\n"); |
750 | fprintf(fp,"*INCLUDE, INPUT=%s_Mesh.inp\n", abaqusInstance->projectName); |
751 | |
752 | // Write all sets |
753 | status = abaqus_writeAllSets(fp, &abaqusInstance->feaProblem); |
754 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 754, __func__, 0); goto cleanup; }; |
755 | |
756 | // Properties |
757 | fprintf(fp, "**\n**Properties\n**\n"); |
758 | printf("Writing properties\n"); |
759 | for (i = 0; i < abaqusInstance->feaProblem.numProperty; i++) { |
760 | status = abaqus_writePropertyCard(fp, &abaqusInstance->feaProblem.feaProperty[i]); |
761 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 761, __func__, 0); goto cleanup; }; |
762 | } |
763 | //fprintf(fp, "*END PART\n"); |
764 | |
765 | // Materials |
766 | fprintf(fp, "**\n**Materials\n**\n"); |
767 | printf("Writing materials\n"); |
768 | for (i = 0; i < abaqusInstance->feaProblem.numMaterial; i++) { |
769 | status = abaqus_writeMaterialCard(fp, &abaqusInstance->feaProblem.feaMaterial[i]); |
770 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 770, __func__, 0); goto cleanup; }; |
771 | } |
772 | // Constraints |
773 | fprintf(fp, "**\n**Constraints\n**\n"); |
774 | printf("Writing constraints\n"); |
775 | for (i = 0; i < abaqusInstance->feaProblem.numConstraint; i++) { |
776 | status = abaqus_writeConstraintCard(fp, &abaqusInstance->feaProblem.feaConstraint[i]); |
777 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 777, __func__, 0); goto cleanup; }; |
778 | } |
779 | |
780 | // Loads |
781 | /* |
782 | printf("Writing loads\n") |
783 | status = abaqus_writeLoadADDCard(fp, &abaqusInstance->feaProblem); |
784 | AIM_STATUS(aimInfo, status); |
785 | */ |
786 | |
787 | // Analysis Cards - Eigenvalue included |
788 | fprintf(fp, "**\n**Steps\n**\n"); |
789 | printf("Writing analysis (steps)\n"); |
790 | for (i = 0; i < abaqusInstance->feaProblem.numAnalysis; i++) { |
791 | status = abaqus_writeAnalysisCard(fp, abaqusInstance->feaProblem.numLoad, |
792 | abaqusInstance->feaProblem.feaLoad, |
793 | &abaqusInstance->feaProblem.feaAnalysis[i], |
794 | &abaqusInstance->feaProblem.feaMesh); |
795 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 795, __func__, 0); goto cleanup; }; |
796 | |
797 | if (i < abaqusInstance->feaProblem.numAnalysis-1) fprintf(fp, "**\n"); |
798 | } |
799 | |
800 | //fprintf(fp, "*RESTART, WRITE, FREQUENCY=1\n"); |
801 | //fprintf(fp, "*OUTPUT, FIELD\n"); |
802 | |
803 | |
804 | // // Testing |
805 | // int arr[18] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}; |
806 | // char **string; |
807 | // string = (char **) EG_alloc(3*sizeof(char)); |
808 | // string[0] = EG_strdup("a"); |
809 | // string[1] = EG_strdup("b"); |
810 | // string[2] = EG_strdup("c"); |
811 | // |
812 | // status = abaqus_writeNodeSet(fp, "test1", 18, arr, 0, NULL); |
813 | // AIM_STATUS(aimInfo, status); |
814 | // status = abaqus_writeNodeSet(fp, "test2", 15, arr, 3, string); |
815 | // AIM_STATUS(aimInfo, status); |
816 | // |
817 | // status = abaqus_writeElementSet(fp, "test3", 18, arr, 0, NULL); |
818 | // AIM_STATUS(aimInfo, status); |
819 | // status = abaqus_writeElementSet(fp, "test4", 15, arr, 3, string); |
820 | // AIM_STATUS(aimInfo, status); |
821 | // |
822 | |
823 | status = CAPS_SUCCESS0; |
824 | |
825 | cleanup: |
826 | |
827 | AIM_FREE(tempIntegerArray){ EG_free(tempIntegerArray); tempIntegerArray = ((void*)0); }; |
828 | |
829 | if (fp != NULL((void*)0)) fclose(fp); |
830 | |
831 | return status; |
832 | } |
833 | |
834 | |
835 | // ********************** AIM Function Break ***************************** |
836 | /* no longer optional and needed for restart */ |
837 | int aimPostAnalysis(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, |
838 | /*@unused@*/ int restart, /*@unused@*/ capsValue *inputs) |
839 | { |
840 | int status; |
841 | int i; |
842 | size_t stringLength; |
843 | capsValue val, *analysisType; |
844 | char *filename = NULL((void*)0); // File to open |
845 | char extFIL[] = ".fil"; |
846 | |
847 | double **dataMatrix = NULL((void*)0); |
848 | int numElement = 0; |
849 | int *elementIDs = NULL((void*)0); |
850 | double *elemData = NULL((void*)0); |
851 | |
852 | //#define WRITE_VONMISES_VTK |
853 | #ifdef WRITE_VONMISES_VTK |
854 | capsValue vonMises; |
855 | #endif |
856 | |
857 | FILE *fp = NULL((void*)0); // File pointer |
858 | aimStorage *abaqusInstance; |
859 | |
860 | #ifdef DEBUG |
861 | printf(" astrosAIM/aimPostAnalysis!\n"); |
862 | #endif |
863 | abaqusInstance = (aimStorage *) instStore; |
864 | |
865 | // check that the mystran *.F06 file was created |
866 | stringLength = strlen(abaqusInstance->projectName) + strlen(extFIL)+1; |
867 | AIM_ALLOC(filename, stringLength, char, aimInfo, status){ if (filename != ((void*)0)) { status = -4; aim_status(aimInfo , status, "abaqusAIM.c", 867, __func__, 1, "AIM_ALLOC: %s != NULL" , "filename"); goto cleanup; } size_t memorysize = stringLength ; filename = (char *) EG_alloc(memorysize*sizeof(char)); if ( filename == ((void*)0)) { status = -4; aim_status(aimInfo, status , "abaqusAIM.c", 867, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "filename", memorysize, "char"); goto cleanup; } }; |
868 | |
869 | // Open mystran *.F06 file |
870 | snprintf(filename, stringLength, "%s%s", abaqusInstance->projectName, extFIL); |
871 | |
872 | fp = aim_fopen(aimInfo, filename, "r"); |
873 | if (fp == NULL((void*)0)) { |
874 | AIM_ERROR(aimInfo, "Cannot open Output file: %s!", filename){ aim_message(aimInfo, CERROR, 0 , "abaqusAIM.c", 874, __func__ , "Cannot open Output file: %s!", filename); }; |
875 | status = CAPS_IOERR-332; |
876 | goto cleanup; |
877 | } |
878 | |
879 | status = aim_getValue(aimInfo, Analysis_Type, ANALYSISIN, &analysisType); |
880 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 880, __func__, 0); goto cleanup; }; |
881 | |
882 | // Static analysis - only |
883 | if (strcasecmp(analysisType->vals.string, "Static") == 0) { |
884 | |
885 | status = aim_initValue(&val); |
886 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 886, __func__, 0); goto cleanup; }; |
887 | |
888 | /* read stress */ |
889 | status = abaqus_readFIL(aimInfo, filename, 1, &numElement, &dataMatrix); |
890 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 890, __func__, 0); goto cleanup; }; |
891 | AIM_NOTNULL(dataMatrix, aimInfo, status){ if (dataMatrix == ((void*)0)) { status = -307; aim_status(aimInfo , status, "abaqusAIM.c", 891, __func__, 1, "%s == NULL!", "dataMatrix" ); goto cleanup; } }; |
892 | |
893 | AIM_ALLOC(elementIDs, numElement, int, aimInfo, status){ if (elementIDs != ((void*)0)) { status = -4; aim_status(aimInfo , status, "abaqusAIM.c", 893, __func__, 1, "AIM_ALLOC: %s != NULL" , "elementIDs"); goto cleanup; } size_t memorysize = numElement ; elementIDs = (int *) EG_alloc(memorysize*sizeof(int)); if ( elementIDs == ((void*)0)) { status = -4; aim_status(aimInfo, status , "abaqusAIM.c", 893, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "elementIDs", memorysize, "int"); goto cleanup; } }; |
894 | AIM_ALLOC(elemData, numElement, double, aimInfo, status){ if (elemData != ((void*)0)) { status = -4; aim_status(aimInfo , status, "abaqusAIM.c", 894, __func__, 1, "AIM_ALLOC: %s != NULL" , "elemData"); goto cleanup; } size_t memorysize = numElement ; elemData = (double *) EG_alloc(memorysize*sizeof(double)); if (elemData == ((void*)0)) { status = -4; aim_status(aimInfo, status , "abaqusAIM.c", 894, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "elemData", memorysize, "double"); goto cleanup; } }; |
895 | |
896 | for (i = 0; i < numElement; i++) { |
897 | elementIDs[i] = (int)dataMatrix[i][0]; |
898 | elemData[i] = dataMatrix[i][1]; |
899 | } |
900 | AIM_FREE(dataMatrix){ EG_free(dataMatrix); dataMatrix = ((void*)0); }; |
901 | |
902 | status = mesh_gridAvg(aimInfo, &abaqusInstance->feaProblem.feaMesh, |
903 | numElement, elementIDs, 1, elemData, |
904 | &val.vals.reals); |
905 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 905, __func__, 0); goto cleanup; }; |
906 | |
907 | val.dim = Vector; |
908 | val.type = Double; |
909 | val.nrow = abaqusInstance->feaProblem.feaMesh.numNode; |
910 | val.ncol = 1; |
911 | val.length = val.nrow*val.ncol; |
912 | |
913 | #ifdef WRITE_VONMISES_VTK |
914 | vonMises = val; |
915 | #endif |
916 | |
917 | /* create the dynamic output */ |
918 | status = aim_makeDynamicOutput(aimInfo, "vonMises_Grid", &val); |
919 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 919, __func__, 0); goto cleanup; }; |
920 | |
921 | status = mesh_writeVTK(aimInfo, "vonMises", |
922 | 1, |
923 | &abaqusInstance->feaProblem.feaMesh, |
924 | 1.0); |
925 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 925, __func__, 0); goto cleanup; }; |
926 | |
927 | #ifdef WRITE_VONMISES_VTK |
928 | int numGridPoint; |
929 | double **dispMatrix = NULL((void*)0); |
930 | |
931 | rewind(fp); |
932 | status = abaqus_readFIL(aimInfo, filename, 0, &numGridPoint, &dispMatrix); |
933 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "abaqusAIM.c", 933, __func__, 0); goto cleanup; }; |
934 | |
935 | fp = aim_fopen(aimInfo, "vonMises.vtk","a"); |
936 | if (fp == NULL((void*)0)) { |
937 | AIM_ERROR(aimInfo, "Cannot open Output file: vonMises.vtk!"){ aim_message(aimInfo, CERROR, 0 , "abaqusAIM.c", 937, __func__ , "Cannot open Output file: vonMises.vtk!"); }; |
938 | status = CAPS_IOERR-332; |
939 | goto cleanup; |
940 | } |
941 | |
942 | fprintf(fp,"POINT_DATA %d\n", vonMises.length); |
943 | fprintf(fp,"SCALARS vonMises float 1\n"); |
944 | fprintf(fp,"LOOKUP_TABLE default\n"); |
945 | for (i = 0; i < vonMises.length; i++) |
946 | fprintf(fp,"%le\n", vonMises.vals.reals[i]); |
947 | |
948 | fprintf(fp,"SCALARS disp float 3\n"); |
949 | fprintf(fp,"LOOKUP_TABLE default\n"); |
950 | for (i = 0; i < numGridPoint; i++) |
951 | fprintf(fp,"%le %le %le\n", dispMatrix[i][2], dispMatrix[i][3], dispMatrix[i][4]); |
952 | |
953 | for (i = 0; i < numGridPoint; i++) { |
954 | AIM_FREE(dispMatrix[i]){ EG_free(dispMatrix[i]); dispMatrix[i] = ((void*)0); }; |
955 | } |
956 | AIM_FREE(dispMatrix){ EG_free(dispMatrix); dispMatrix = ((void*)0); }; |
957 | #endif |
958 | } |
959 | |
960 | status = CAPS_SUCCESS0; |
961 | |
962 | cleanup: |
963 | AIM_FREE(filename){ EG_free(filename); filename = ((void*)0); }; // Free filename allocation |
964 | if (fp != NULL((void*)0)) fclose(fp); |
965 | |
966 | AIM_FREE(elementIDs){ EG_free(elementIDs); elementIDs = ((void*)0); }; |
967 | AIM_FREE(dataMatrix){ EG_free(dataMatrix); dataMatrix = ((void*)0); }; |
968 | AIM_FREE(elemData){ EG_free(elemData); elemData = ((void*)0); }; |
969 | |
970 | return status; |
971 | } |
972 | |
973 | |
974 | // ********************** AIM Function Break ***************************** |
975 | // Set Abaqus output variables |
976 | int aimOutputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimStruc, |
977 | /*@unused@*/ int index, /*@unused@*/ char **aoname, /*@unused@*/ capsValue *form) |
978 | { |
979 | |
980 | /*! \page aimOutputsAbaqus AIM Outputs |
981 | * The following list outlines the Abaqus outputs available through the AIM interface. |
982 | * |
983 | * None to date. |
984 | */ |
985 | |
986 | #ifdef DEBUG |
987 | printf(" abaqusAIM/aimOutputs index = %d!\n", index); |
988 | #endif |
989 | |
990 | return CAPS_SUCCESS0; |
991 | } |
992 | |
993 | |
994 | // ********************** AIM Function Break ***************************** |
995 | // Calculate Abaqus output |
996 | int aimCalcOutput(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, /*@unused@*/ int index, |
997 | /*@unused@*/ capsValue *val) |
998 | { |
999 | |
1000 | return CAPS_SUCCESS0; |
1001 | } |
1002 | |
1003 | void aimCleanup(void *instStore) |
1004 | { |
1005 | int status; // Returning status |
1006 | |
1007 | aimStorage *abaqusInstance; |
1008 | |
1009 | #ifdef DEBUG |
1010 | printf(" abaqusAIM/aimCleanup!\n"); |
1011 | #endif |
1012 | abaqusInstance = (aimStorage *) instStore; |
1013 | |
1014 | status = destroy_aimStorage(abaqusInstance); |
1015 | if (status != CAPS_SUCCESS0) printf("Error: Status %d during clean up of instance\n", status); |
1016 | |
1017 | AIM_FREE(abaqusInstance){ EG_free(abaqusInstance); abaqusInstance = ((void*)0); }; |
1018 | |
1019 | } |
1020 | |
1021 | /************************************************************************/ |
1022 | // CAPS transferring functions |
1023 | |
1024 | |
1025 | int aimTransfer(capsDiscr *discr, const char *dataName, int numPoint, |
1026 | int dataRank, double *dataVal, /*@unused@*/ char **units) |
1027 | { |
1028 | |
1029 | /*! \page dataTransferAbaqus Abaqus Data Transfer |
1030 | * |
1031 | * The Nastran AIM has the ability to transfer displacements from the AIM and pressure |
1032 | * distributions to the AIM using the conservative and interpolative data transfer schemes in CAPS. |
1033 | * |
1034 | * \section dataTransferAbaqus Data transfer from Abaqus |
1035 | * |
1036 | * <ul> |
1037 | * <li> <B>"Displacement"</B> </li> <br> |
1038 | * Retrieves nodal displacements from the *.fil file. |
1039 | * </ul> |
1040 | * |
1041 | * \section dataTransferAbaqus Data transfer to Abaqus |
1042 | * <ul> |
1043 | * <li> <B>"Pressure"</B> </li> <br> |
1044 | * Writes appropriate load cards using the provided pressure distribution. |
1045 | * </ul> |
1046 | * |
1047 | */ |
1048 | |
1049 | int status; // Function return status |
1050 | int i, j, dataPoint; // Indexing |
1051 | aimStorage *abaqusInstance; |
1052 | |
1053 | char *extFIL= ".fil"; |
1054 | |
1055 | // FIL data variables |
1056 | int numGridPoint = 0; |
1057 | int numEigenVector = 0; |
1058 | |
1059 | double **dataMatrix = NULL((void*)0); |
1060 | |
1061 | // Specific EigenVector to use |
1062 | int eigenVectorIndex = 0; |
1063 | |
1064 | // Variables used in global node mapping |
1065 | int bIndex, globalNodeID; |
1066 | |
1067 | // Filename stuff |
1068 | char filename[PATH_MAX4096]; |
1069 | // FILE *fp; // File pointer |
1070 | |
1071 | #ifdef DEBUG |
1072 | printf(" abaqusAIM/aimTransfer name = %s instance = %d npts = %d/%d!\n", dataName, discr->instance, numPoint, dataRank); |
1073 | #endif |
1074 | abaqusInstance = (aimStorage *) discr->instStore; |
1075 | |
1076 | if (strcasecmp(dataName, "Displacement") != 0){// && |
1077 | //strncmp(dataName, "EigenVector", 11) != 0) { |
1078 | |
1079 | printf("Unrecognized data transfer variable - %s\n", dataName); |
1080 | return CAPS_NOTFOUND-303; |
1081 | } |
1082 | |
1083 | status = aim_file(discr->aInfo, abaqusInstance->projectName, filename); |
1084 | AIM_STATUS(discr->aInfo, status)if (status != 0) { aim_status(discr->aInfo, status, "abaqusAIM.c" , 1084, __func__, 0); goto cleanup; }; |
1085 | strcat(filename, extFIL); |
1086 | |
1087 | if (strcasecmp(dataName, "Displacement") == 0) { |
1088 | |
1089 | if (dataRank != 3) { |
1090 | |
1091 | printf("Invalid rank for dataName \"%s\" - excepted a rank of 3!!!\n", dataName); |
1092 | status = CAPS_BADRANK-301; |
1093 | |
1094 | } else { |
1095 | |
1096 | status = abaqus_readFIL(discr->aInfo, filename, 0, &numGridPoint, &dataMatrix); |
Value stored to 'status' is never read | |
1097 | } |
1098 | |
1099 | } else if (strncmp(dataName, "EigenVector", 11) == 0) { // NOT SUPPOSED TO BE IMPLEMENTED YET |
1100 | |
1101 | // Which EigenVector do we want ? |
1102 | for (i = 0; i < strlen(dataName); i++) { |
1103 | if (dataName[i] == '_' ) break; |
1104 | } |
1105 | |
1106 | if (i == strlen(dataName)) { |
1107 | eigenVectorIndex = 1; |
1108 | } else { |
1109 | |
1110 | status = sscanf(dataName, "EigenVector_%d", &eigenVectorIndex); |
1111 | if (status != 1) { |
1112 | printf("Unable to determine which EigenVector to use - Defaulting the first EigenVector!!!\n"); |
1113 | eigenVectorIndex = 1; |
1114 | } |
1115 | } |
1116 | |
1117 | if (dataRank != 3) { |
1118 | |
1119 | printf("Invalid rank for dataName \"%s\" - excepted a rank of 3!!!\n", dataName); |
1120 | status = CAPS_BADRANK-301; |
1121 | |
1122 | } else { |
1123 | |
1124 | // NEED A FUNCTION TO RETRIEVE EIGEN-VECTORS |
1125 | } |
1126 | |
1127 | |
1128 | |
1129 | } else { |
1130 | |
1131 | status = CAPS_NOTFOUND-303; |
1132 | } |
1133 | |
1134 | // Check EigenVector range |
1135 | if (strncmp(dataName, "EigenVector", 11) == 0) { |
1136 | if (eigenVectorIndex > numEigenVector) { |
1137 | printf("Only %d EigenVectors found but index %d requested!\n", numEigenVector, eigenVectorIndex); |
1138 | status = CAPS_RANGEERR-326; |
1139 | goto cleanup; |
1140 | } |
1141 | |
1142 | if (eigenVectorIndex < 1) { |
1143 | printf("For EigenVector_X notation, X must be >= 1, currently X = %d\n", eigenVectorIndex); |
1144 | status = CAPS_RANGEERR-326; |
1145 | goto cleanup; |
1146 | } |
1147 | |
1148 | } |
1149 | if (dataMatrix == NULL((void*)0)) { |
1150 | status = CAPS_NULLVALUE-307; |
1151 | AIM_STATUS(discr->aInfo, status)if (status != 0) { aim_status(discr->aInfo, status, "abaqusAIM.c" , 1151, __func__, 0); goto cleanup; }; |
1152 | } |
1153 | |
1154 | for (i = 0; i < numPoint; i++) { |
1155 | |
1156 | bIndex = discr->tessGlobal[2*i ]; |
1157 | globalNodeID = discr->tessGlobal[2*i+1] + |
1158 | discr->bodys[bIndex-1].globalOffset; |
1159 | |
1160 | if (strcasecmp(dataName, "Displacement") == 0) { |
1161 | |
1162 | for (dataPoint = 0; dataPoint < numGridPoint; dataPoint++) { |
1163 | if ((int) dataMatrix[dataPoint][0] == globalNodeID) break; |
1164 | } |
1165 | |
1166 | if (dataPoint == numGridPoint) { |
1167 | printf("Unable to locate global ID = %d in the data matrix\n", globalNodeID); |
1168 | status = CAPS_NOTFOUND-303; |
1169 | goto cleanup; |
1170 | } |
1171 | |
1172 | dataVal[dataRank*i+0] = dataMatrix[dataPoint][1]; // T1 |
1173 | dataVal[dataRank*i+1] = dataMatrix[dataPoint][2]; // T2 |
1174 | dataVal[dataRank*i+2] = dataMatrix[dataPoint][3]; // T3 |
1175 | |
1176 | } else if (strncmp(dataName, "EigenVector", 11) == 0) { // NEED A FUNCTION TO RETRIEVE EIGEN-VECTORS |
1177 | |
1178 | |
1179 | for (dataPoint = 0; dataPoint < numGridPoint; dataPoint++) { |
1180 | if ((int) dataMatrix[eigenVectorIndex - 1][8*dataPoint + 0] == globalNodeID) break; |
1181 | } |
1182 | |
1183 | if (dataPoint == numGridPoint) { |
1184 | printf("Unable to locate global ID = %d in the data matrix\n", globalNodeID); |
1185 | status = CAPS_NOTFOUND-303; |
1186 | goto cleanup; |
1187 | } |
1188 | |
1189 | dataVal[dataRank*i+0] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 2]; // T1 |
1190 | dataVal[dataRank*i+1] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 3]; // T2 |
1191 | dataVal[dataRank*i+2] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 4]; // T3 |
1192 | //dataVal[dataRank*i+3] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 5]; // R1 - Don't use rotations |
1193 | //dataVal[dataRank*i+4] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 6]; // R2 |
1194 | //dataVal[dataRank*i+5] = dataMatrix[eigenVectorIndex- 1][8*dataPoint + 7]; // R3 |
1195 | |
1196 | } |
1197 | } |
1198 | |
1199 | status = CAPS_SUCCESS0; |
1200 | goto cleanup; |
1201 | |
1202 | cleanup: |
1203 | // Free data matrix |
1204 | if (dataMatrix != NULL((void*)0)) { |
1205 | j = 0; |
1206 | if (strcasecmp(dataName, "Displacement") == 0) j = numGridPoint; |
1207 | else if (strncmp(dataName, "EigenVector", 11) == 0) j = numEigenVector; |
1208 | |
1209 | for (i = 0; i < j; i++) { |
1210 | if (dataMatrix[i] != NULL((void*)0)) AIM_FREE(dataMatrix[i]){ EG_free(dataMatrix[i]); dataMatrix[i] = ((void*)0); }; |
1211 | } |
1212 | AIM_FREE(dataMatrix){ EG_free(dataMatrix); dataMatrix = ((void*)0); }; |
1213 | } |
1214 | |
1215 | return status; |
1216 | } |
1217 | |
1218 | int aimDiscr(char *tname, capsDiscr *discr) { |
1219 | |
1220 | int status; // Function return status |
1221 | int i; |
1222 | ego *tess = NULL((void*)0); |
1223 | capsValue *valMesh; |
1224 | aimStorage *abaqusInstance; |
1225 | |
1226 | abaqusInstance = (aimStorage *) discr->instStore; |
1227 | |
1228 | #ifdef DEBUG |
1229 | printf(" abaqusAIM/aimDiscr: tname = %s, instance = %d!\n", tname, iIndex); |
1230 | #endif |
1231 | |
1232 | if (tname == NULL((void*)0)) return CAPS_NOTFOUND-303; |
1233 | |
1234 | status = aim_getValue(discr->aInfo, Mesh, ANALYSISIN, &valMesh); |
1235 | AIM_STATUS(discr->aInfo, status)if (status != 0) { aim_status(discr->aInfo, status, "abaqusAIM.c" , 1235, __func__, 0); goto cleanup; }; |
1236 | |
1237 | if (valMesh->nullVal == IsNull) { |
1238 | AIM_ANALYSISIN_ERROR(discr->aInfo, Mesh, "'Mesh' input must be linked to an output 'Surface_Mesh'"){ aim_message(discr->aInfo, CERROR, Mesh, "abaqusAIM.c", 1238 , __func__, "'Mesh' input must be linked to an output 'Surface_Mesh'" ); }; |
1239 | status = CAPS_BADVALUE-311; |
1240 | goto cleanup; |
1241 | } |
1242 | |
1243 | // Check and generate/retrieve the mesh |
1244 | status = checkAndCreateMesh(discr->aInfo, abaqusInstance); |
1245 | AIM_STATUS(discr->aInfo, status)if (status != 0) { aim_status(discr->aInfo, status, "abaqusAIM.c" , 1245, __func__, 0); goto cleanup; }; |
1246 | |
1247 | AIM_ALLOC(tess, abaqusInstance->numMesh, ego, discr->aInfo, status){ if (tess != ((void*)0)) { status = -4; aim_status(discr-> aInfo, status, "abaqusAIM.c", 1247, __func__, 1, "AIM_ALLOC: %s != NULL" , "tess"); goto cleanup; } size_t memorysize = abaqusInstance ->numMesh; tess = (ego *) EG_alloc(memorysize*sizeof(ego)) ; if (tess == ((void*)0)) { status = -4; aim_status(discr-> aInfo, status, "abaqusAIM.c", 1247, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "tess", memorysize, "ego"); goto cleanup; } }; |
1248 | for (i = 0; i < abaqusInstance->numMesh; i++) { |
1249 | tess[i] = abaqusInstance->feaMesh[i].egadsTess; |
1250 | } |
1251 | |
1252 | status = mesh_fillDiscr(tname, &abaqusInstance->attrMap, abaqusInstance->numMesh, tess, discr); |
1253 | AIM_STATUS(discr->aInfo, status)if (status != 0) { aim_status(discr->aInfo, status, "abaqusAIM.c" , 1253, __func__, 0); goto cleanup; }; |
1254 | |
1255 | #ifdef DEBUG |
1256 | printf(" abaqusAIM/aimDiscr: Instance = %d, Finished!!\n", iIndex); |
1257 | #endif |
1258 | |
1259 | status = CAPS_SUCCESS0; |
1260 | |
1261 | cleanup: |
1262 | AIM_FREE(tess){ EG_free(tess); tess = ((void*)0); }; |
1263 | |
1264 | return status; |
1265 | } |
1266 | |
1267 | void aimFreeDiscrPtr(void *ptr) |
1268 | { |
1269 | // Extra information to store into the discr void pointer - just a int array |
1270 | EG_free(ptr); |
1271 | } |
1272 | |
1273 | int aimLocateElement(capsDiscr *discr, double *params, double *param, |
1274 | int *bIndex, int *eIndex, double *bary) |
1275 | { |
1276 | #ifdef DEBUG |
1277 | printf(" abaqusAIM/aimLocateElement instance = %d!\n", discr->instance); |
1278 | #endif |
1279 | |
1280 | return aim_locateElement(discr, params, param, bIndex, eIndex, bary); |
1281 | } |
1282 | |
1283 | int aimInterpolation(capsDiscr *discr, const char *name, |
1284 | int bIndex, int eIndex, double *bary, |
1285 | int rank, double *data, double *result) |
1286 | { |
1287 | #ifdef DEBUG |
1288 | printf(" abaqusAIM/aimInterpolation %s instance = %d!\n", name, discr->instance); |
1289 | #endif |
1290 | |
1291 | return aim_interpolation(discr, name, bIndex, eIndex, bary, rank, data, |
1292 | result); |
1293 | } |
1294 | |
1295 | |
1296 | int aimInterpolateBar(capsDiscr *discr, const char *name, |
1297 | int bIndex, int eIndex, double *bary, |
1298 | int rank, double *r_bar, double *d_bar) |
1299 | { |
1300 | #ifdef DEBUG |
1301 | printf(" abaqusAIM/aimInterpolateBar %s instance = %d!\n", name, discr->instance); |
1302 | #endif |
1303 | |
1304 | return aim_interpolateBar(discr, name, bIndex, eIndex, bary, rank, r_bar, |
1305 | d_bar); |
1306 | } |
1307 | |
1308 | |
1309 | int aimIntegration(capsDiscr *discr, const char *name,int bIndex, int eIndex, |
1310 | int rank, double *data, double *result) |
1311 | { |
1312 | #ifdef DEBUG |
1313 | printf(" abaqusAIM/aimIntegration %s instance = %d!\n", name, discr->instance); |
1314 | #endif |
1315 | |
1316 | return aim_integration(discr, name, bIndex, eIndex, rank, data, result); |
1317 | } |
1318 | |
1319 | |
1320 | int aimIntegrateBar(capsDiscr *discr, const char *name, int bIndex, int eIndex, |
1321 | int rank, double *r_bar, double *d_bar) |
1322 | { |
1323 | #ifdef DEBUG |
1324 | printf(" abaqusAIM/aimIntegrateBar %s instance = %d!\n", name, discr->instance); |
1325 | #endif |
1326 | |
1327 | return aim_integrateBar(discr, name, bIndex, eIndex, rank, r_bar, d_bar); |
1328 | } |