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