Bug Summary

File:tetgenAIM.cpp
Warning:line 939, column 12
The left operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name tetgenAIM.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D REVISION=7.8 -I /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/ESP/LINUX64/include -I ../utils -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-dangling-else -Wno-parentheses -Wno-unused-result -Wno-format-truncation -fdeprecated-macro -fdebug-compilation-dir /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/CAPS/aim/tetgen -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/jenkins/workspace/ESP_Stanalizer/LINUX64/CAPS/scan-build/scanCAPS/2024-04-26-185936-18883-1 -x c++ tetgenAIM.cpp
1/*
2 * CAPS: Computational Aircraft Prototype Syntheses
3 *
4 * TetGen AIM
5 *
6 * Written by Dr. Ryan Durscher AFRL/RQVC
7 *
8 * This software has been cleared for public release on 05 Nov 2020, case number 88ABW-2020-3462.
9 */
10
11
12/*! \mainpage Introduction
13 *
14 * \section overviewTetGen TetGen AIM Overview
15 * A module in the Computational Aircraft Prototype Syntheses (CAPS) has been developed to interact with
16 * the open-source volume mesh generator, TetGen \cite Hang2015. TetGen is capable of generating exact constrained
17 * Delaunay tetrahedralizations, boundary conforming Delaunay meshes, and Voronoi partitions.
18 *
19 * An outline of the AIM's inputs and outputs are provided in \ref aimInputsTetGen and \ref aimOutputsTetGen, respectively.
20 *
21 * Current issues include:
22 * - The holes or seed points provided to TetGen by creating an taking the cnetroid of a tetrahedron from an 'empty' mesh.
23 * This is guaranteed to work with solid bodies, but sheet bodies with multiple segregated regions where some
24 * regions are holes require manual seed points to indicate the hole.
25 * - (<b>Important</b>) If Tetgen is allowed to added Steiner points (see "Preserve_Surf_Mesh" in \ref aimInputsTetGen)
26 * discrete data transfer will <b>NOT</b> be possible.
27 *
28 * \section tetgenInterface TetGen Interface
29 * In order to use TetGen, CAPS will automatically build the TetGen source code supplied in "library" mode. The directory
30 * in which the source code exists is set in the ESP configuration script. The C++ API is interfaced within the AIM
31 * through an interface function that takes the body tessellation and transfers the data to a "tetgenio" object
32 * in PLCs format (Piecewise Linear Complexes). After volume meshing is complete the mesh can be output in various
33 * mesh formats (see \ref aimInputsTetGen for additional details).
34 *
35 * \section clearanceTetgen Clearance Statement
36 * This software has been cleared for public release on 05 Nov 2020, case number 88ABW-2020-3462.
37 */
38
39#include <string.h>
40#include <math.h>
41#include "capsTypes.h"
42#include "aimUtil.h"
43#include "aimMesh.h"
44
45#include "meshUtils.h" // Collection of helper functions for meshing
46#include "miscUtils.h"
47#include "deprecateUtils.h"
48
49#include "tetgen_Interface.hpp" // Bring in TetGen 'interface' function
50
51#ifdef WIN32
52#define snprintf _snprintf
53#define strcasecmp stricmp
54#endif
55
56//#define DEBUG
57
58#define TETGENFILE"tetgen_%d" "tetgen_%d"
59
60enum aimInputs
61{
62 Proj_Name = 1, /* index is 1-based */
63 Preserve_Surf_Mesh,
64 Mesh_Verbose_Flag,
65 Mesh_Quiet_Flag,
66 Quality_Rad_Edge,
67 Quality_Angle,
68 Mesh_Format,
69 Mesh_Gen_Input_String,
70 Ignore_Surface_Mesh_Extraction,
71 Mesh_Tolerance,
72 Multiple_Mesh,
73 Regions,
74 Holes,
75 Surface_Mesh,
76 NUMINPUT = Surface_Mesh /* Total number of inputs */
77};
78
79enum aimOutputs
80{
81 NumberOfElement = 1, /* index is 1-based */
82 NumberOfNode,
83 Volume_Mesh,
84 NUMOUT = Volume_Mesh /* Total number of outputs */
85};
86
87#define NODATATRANSFER"noDataTransfer.%d" "noDataTransfer.%d"
88
89
90typedef struct {
91
92 // Container for mesh input
93 meshInputStruct meshInput;
94
95 // Attribute to index map
96 mapAttrToIndexStruct groupMap;
97
98 // Mesh references for link
99 int numMeshRef;
100 aimMeshRef *meshRef;
101
102} aimStorage;
103
104
105
106static int destroy_aimStorage(aimStorage *tetgenInstance)
107{
108
109 int i; // Indexing
110
111 int status; // Function return status
112
113 // Destroy meshInput
114 status = destroy_meshInputStruct(&tetgenInstance->meshInput);
115 if (status != CAPS_SUCCESS0)
116 printf("Status = %d, tetgenAIM meshInput cleanup!!!\n", status);
117
118 // Destroy attribute to index map
119 status = destroy_mapAttrToIndexStruct(&tetgenInstance->groupMap);
120 if (status != CAPS_SUCCESS0)
121 printf("Status = %d, tetgenAIM attrMap cleanup!!!\n", status);
122
123 // Free the meshRef
124 for (i = 0; i < tetgenInstance->numMeshRef; i++)
125 aim_freeMeshRef(&tetgenInstance->meshRef[i]);
126 AIM_FREE(tetgenInstance->meshRef){ EG_free(tetgenInstance->meshRef); tetgenInstance->meshRef
= __null; }
;
127 tetgenInstance->numMeshRef = 0;
128
129 return CAPS_SUCCESS0;
130}
131
132
133
134/* ********************** Exposed AIM Functions ***************************** */
135
136extern "C" int
137aimInitialize(int inst, /*@unused@*/ const char *unitSys, void *aimInfo,
138 /*@unused@*/ void **instStore, /*@unused@*/ int *major,
139 /*@unused@*/ int *minor, int *nIn, int *nOut,
140 int *nFields, char ***fnames, int **franks, int **fInOut)
141{
142 int status = CAPS_SUCCESS0; // Function status return
143
144 aimStorage *tetgenInstance = NULL__null;
145
146#ifdef DEBUG
147 printf("\n tetgenAIM/aimInitialize instance = %d!\n", inst);
148#endif
149
150 /* specify the number of analysis input and out "parameters" */
151 *nIn = NUMINPUT;
152 *nOut = NUMOUT;
153 if (inst == -1) return CAPS_SUCCESS0;
154
155 /* specify the field variables this analysis can generate and consume */
156 *nFields = 0;
157 *fnames = NULL__null;
158 *franks = NULL__null;
159 *fInOut = NULL__null;
160
161 // Allocate tetgenInstance
162 AIM_ALLOC(tetgenInstance, 1, aimStorage, aimInfo, status){ if (tetgenInstance != __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 162, __func__, 1, "AIM_ALLOC: %s != NULL"
, "tetgenInstance"); goto cleanup; } size_t memorysize = 1; tetgenInstance
= (aimStorage *) EG_alloc(memorysize*sizeof(aimStorage)); if
(tetgenInstance == __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 162, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "tetgenInstance", memorysize, "aimStorage"); goto cleanup; }
}
;
163 *instStore = tetgenInstance;
164
165 // Set initial values for tetgenInstance //
166
167 // Mesh reference passed to solver
168 tetgenInstance->numMeshRef = 0;
169 tetgenInstance->meshRef = NULL__null;
170
171 // Container for attribute to index map
172 status = initiate_mapAttrToIndexStruct(&tetgenInstance->groupMap);
173 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 173, __func__, 0); goto cleanup; }
;
174
175 // Container for mesh input
176 status = initiate_meshInputStruct(&tetgenInstance->meshInput);
177 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 177, __func__, 0); goto cleanup; }
;
178
179
180cleanup:
181 if (status != CAPS_SUCCESS0) AIM_FREE(*instStore){ EG_free(*instStore); *instStore = __null; };
182 return CAPS_SUCCESS0;
183}
184
185
186extern "C" int
187aimInputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, int index,
188 char **ainame, capsValue *defval)
189{
190 /*! \page aimInputsTetGen AIM Inputs
191 * The following list outlines the TetGen meshing options along with their default value available
192 * through the AIM interface.
193 */
194 int status = CAPS_SUCCESS0;
195
196#ifdef DEBUG
197 printf(" tetgenAIM/aimInputs index = %d!\n", index);
198#endif
199
200 // Meshing Inputs
201 if (index == Proj_Name) {
202 *ainame = EG_strdup("Proj_Name"); // If NULL a volume grid won't be written by the AIM
203 defval->type = String;
204 defval->nullVal = IsNull;
205 defval->vals.string = NULL__null;
206 //defval->vals.string = EG_strdup("CAPS");
207 defval->lfixed = Change;
208
209 /*! \page aimInputsTetGen
210 * - <B> Proj_Name = NULL</B> <br>
211 * Output name prefix for meshes to be written in formats specified by Mesh_Format.
212 * These meshes are not linked to any analysis, but may be useful exploring meshing parameters.
213 */
214
215 } else if (index == Mesh_Format) {
216 *ainame = EG_strdup("Mesh_Format");
217 defval->type = String;
218 defval->vals.string = NULL__null;
219 defval->nullVal = IsNull;
220 defval->dim = Vector;
221 defval->lfixed = Change;
222
223 /*! \page aimInputsTetGen
224 * \include{doc} Mesh_Format.dox
225 */
226
227 } else if (index == Preserve_Surf_Mesh) {
228 *ainame = EG_strdup("Preserve_Surf_Mesh");
229 defval->type = Boolean;
230 defval->vals.integer = true;
231
232 /*! \page aimInputsTetGen
233 * - <B> Preserve_Surf_Mesh = True</B> <br>
234 * Tells TetGen to preserve the surface mesh provided (i.e. do not add Steiner points on the surface). Discrete data transfer
235 * will <b>NOT</b> be possible if Steiner points are added.
236 */
237 } else if (index == Mesh_Verbose_Flag) {
238 *ainame = EG_strdup("Mesh_Verbose_Flag");
239 defval->type = Boolean;
240 defval->vals.integer = false;
241
242 /*! \page aimInputsTetGen
243 * - <B> Mesh_Verbose_Flag = False</B> <br>
244 * Verbose output from TetGen.
245 */
246 } else if (index == Mesh_Quiet_Flag) {
247 *ainame = EG_strdup("Mesh_Quiet_Flag");
248 defval->type = Boolean;
249 defval->vals.integer = false;
250
251 /*! \page aimInputsTetGen
252 * - <B> Mesh_Quiet_Flag = False</B> <br>
253 * Complete suppression of all TetGen output messages (not including errors).
254 */
255 } else if (index == Quality_Rad_Edge) {
256 *ainame = EG_strdup("Quality_Rad_Edge"); // TetGen specific parameters
257 defval->type = Double;
258 defval->vals.real = 1.5;
259
260 /*! \page aimInputsTetGen
261 * - <B> Quality_Rad_Edge = 1.5</B> <br>
262 * TetGen maximum radius-edge ratio.
263 */
264 } else if (index == Quality_Angle) {
265 *ainame = EG_strdup("Quality_Angle"); // TetGen specific parameters
266 defval->type = Double;
267 defval->vals.real = 0.0;
268
269 /*! \page aimInputsTetGen
270 * - <B> Quality_Angle = 0.0</B> <br>
271 * TetGen minimum dihedral angle (in degrees).
272 */
273
274 } else if (index == Mesh_Gen_Input_String) {
275 *ainame = EG_strdup("Mesh_Gen_Input_String");
276 defval->type = String;
277 defval->nullVal = IsNull;
278 defval->vals.string = NULL__null;
279 defval->lfixed = Change;
280
281 /*! \page aimInputsTetGen
282 * - <B> Mesh_Gen_Input_String = NULL</B> <br>
283 * Meshing program command line string (as if called in bash mode). Use this to specify more
284 * complicated options/use features of the mesher not currently exposed through other AIM input
285 * variables. Note that this is the exact string that will be provided to the volume mesher; no
286 * modifications will be made. If left NULL an input string will be created based on default values
287 * of the relevant AIM input variables. See \ref tetgenCommandLineInput for options to include
288 * in the input string.
289 */
290 } else if (index == Ignore_Surface_Mesh_Extraction) { // Deprecated
291 *ainame = EG_strdup("Ignore_Surface_Mesh_Extraction");
292 defval->type = Boolean;
293 defval->vals.integer = true;
294
295// /*! \page aimInputsTetGen
296// * - <B> Ignore_Surface_Mesh_Extraction = True</B> <br>
297// * If TetGen doesn't preserve the surface mesh provided (i.e. Steiner points are added) a simple search algorithm may be
298// * used to reconstruct a separate (not dependent on the volume mesh node numbering) representation of the surface mesh. In
299// * general, this has little use and can add a significant computational penalty. The default value of "True" is recommended.
300// */
301 } else if (index == Mesh_Tolerance) {
302 *ainame = EG_strdup("Mesh_Tolerance"); // TetGen specific parameters
303 defval->type = Double;
304 defval->vals.real = 1E-16;
305
306 /*! \page aimInputsTetGen
307 * - <B> Mesh_Tolerance = 1E-16</B> <br>
308 * Sets the tolerance for coplanar test in TetGen.
309 */
310 } else if (index == Multiple_Mesh) {
311 *ainame = EG_strdup("Multiple_Mesh");
312 defval->type = String;
313 AIM_STRDUP(defval->vals.string, "SingleDomain", aimInfo, status){ if (defval->vals.string != __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 313, __func__, 1, "AIM_STRDUP: %s != NULL!"
, "defval->vals.string"); goto cleanup; } defval->vals.
string = EG_strdup("SingleDomain"); if (defval->vals.string
== __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 313, __func__, 2, "AIM_STRDUP: %s %s", "defval->vals.string"
, "SingleDomain"); goto cleanup; } }
;
314
315 /*! \page aimInputsTetGen
316 * - <B> Multiple_Mesh = "SingleDomain"</B> <br>
317 * If "SingleDomain": Generate a single volume mesh file is assuming multiple
318 * bodies define a single computational domain (i.e. CFD)<br>
319 * <br>
320 * If "MultiFile": Generate a volume mesh file for each body.<br>
321 * <br>
322 * If "MultiDomain": Generate a single mesh file containing multiple volume meshes for each body.<br>
323 */
324
325 } else if (index == Regions) {
326 *ainame = EG_strdup("Regions");
327 defval->type = Tuple;
328 defval->nullVal = IsNull;
329 defval->dim = Vector;
330 defval->lfixed = Change;
331 defval->vals.tuple = NULL__null;
332
333 /*! \page aimInputsTetGen
334 * - <B>Regions = NULL</B><br>
335 * If this input is set, the volume mesh will be divided into regions,
336 * each bounded by surface mesh and identified by an interior `seed`
337 * point. If a seed appears in the `Regions` input, then its region
338 * will be meshed and the markers for all cells in the region will be
339 * set to the region's `id`. The markers for cells that fall outside
340 * of any user-defined region or hole will be numbered automatically.
341 * The input is a vector of tuples. The tuple keys are ignored and the
342 * tuple values are dictionaries; each requires an integer `id` entry
343 * and a 3-vector `seed` point. For example, from within a pyCAPS
344 * script,
345 *
346 * \code{.py}
347 * tetgen.input.Regions = {
348 * 'A': { 'id': 10, 'seed': [0, 0, 1] },
349 * 'B': { 'id': 20, 'seed': [0, 0, -1] }
350 * }
351 * \endcode
352 *
353 * Automatic hole detection will be disabled if one or both of the
354 * `Regions` and `Holes` inputs is not NULL.
355 */
356 } else if (index == Holes) {
357 *ainame = EG_strdup("Holes");
358 defval->type = Tuple;
359 defval->nullVal = IsNull;
360 defval->dim = Vector;
361 defval->lfixed = Change;
362 defval->vals.tuple = NULL__null;
363
364 /*! \page aimInputsTetGen
365 * - <B>Holes = NULL</B><br>
366 * If this input is set, the volume mesh will be divided into regions,
367 * each bounded by surface mesh and identified by an interior `seed`
368 * point. If a seed appears in the `Holes` input, then its region will
369 * not be meshed. The input is a vector of tuples. The tuple keys are
370 * ignored and the tuple values are dictionaries; each requires a
371 * 3-vector `seed` point. For example, from within a pyCAPS script,
372 *
373 * \code{.py}
374 * tetgen.input.Holes = {
375 * 'A': { 'seed': [ 1, 0, 0] },
376 * 'B': { 'seed': [-1, 0, 0] }
377 * }
378 * \endcode
379 *
380 * Automatic hole detection will be disabled if one or both of the
381 * `Regions` and `Holes` inputs is not NULL.
382 */
383
384 } else if (index == Surface_Mesh) {
385 *ainame = AIM_NAME(Surface_Mesh)EG_strdup("Surface_Mesh");
386 defval->type = PointerMesh;
387 defval->dim = Vector;
388 defval->lfixed = Change;
389 defval->sfixed = Fixed;
390 defval->vals.AIMptr = NULL__null;
391 defval->nullVal = IsNull;
392
393 /*! \page aimInputsTetGen
394 * - <B>Surface_Mesh = NULL</B> <br>
395 * A Surface_Mesh link.
396 */
397 }
398
399 AIM_NOTNULL(*ainame, aimInfo, status){ if (*ainame == __null) { status = -307; aim_status(aimInfo,
status, "tetgenAIM.cpp", 399, __func__, 1, "%s == NULL!", "*ainame"
); goto cleanup; } }
;
400
401cleanup:
402 if (status != CAPS_SUCCESS0) AIM_FREE(*ainame){ EG_free(*ainame); *ainame = __null; };
403 return status;
404}
405
406
407// ********************** AIM Function Break *****************************
408extern "C" int
409aimUpdateState(void *instStore, void *aimInfo, capsValue *aimInputs)
410{
411 int status; // Function return status
412
413 char aimFile[PATH_MAX4096];
414 char bodyNumberFile[128];
415
416 int MultiMesh, ibody;
417 aimMeshRef *surfaceMesh;
418
419 // Incoming bodies
420 const char *intents;
421 ego *bodies = NULL__null;
422 int numBody = 0;
423
424 aimStorage *tetgenInstance;
425
426 tetgenInstance = (aimStorage *) instStore;
427
428 // Cleanup previous aimStorage for the instance in case this is the second time through preAnalysis for the same instance
429 status = destroy_aimStorage(tetgenInstance);
430 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 430, __func__, 0); goto cleanup; }
;
431
432 // Get AIM bodies
433 status = aim_getBodies(aimInfo, &intents, &numBody, &bodies);
434 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 434, __func__, 0); goto cleanup; }
;
435
436#ifdef DEBUG
437 printf(" tetgenAIM/aimPreAnalysis numBody = %d!\n", numBody);
438#endif
439
440 if (numBody <= 0 || bodies == NULL__null) {
441 AIM_ERROR(aimInfo, "No Bodies!"){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 441, __func__
, "No Bodies!"); }
;
442 return CAPS_SOURCEERR-330;
443 }
444
445 if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "SingleDomain") != 0 &&
446 strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiFile") != 0 &&
447 strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiDomain") != 0) {
448 AIM_ERROR(aimInfo, "Multiple_Mesh = '%s' must be 'SingleDomain', 'MultiFile', or 'MultiDomain'", aimInputs[Multiple_Mesh-1].vals.string){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 448, __func__
, "Multiple_Mesh = '%s' must be 'SingleDomain', 'MultiFile', or 'MultiDomain'"
, aimInputs[Multiple_Mesh-1].vals.string); }
;
449 status = CAPS_BADVALUE-311;
450 goto cleanup;
451 }
452
453 // Get capsGroup name and index mapping
454 status = create_CAPSGroupAttrToIndexMap(numBody,
455 bodies,
456 -1, // Only search the face level of the EGADS body
457 &tetgenInstance->groupMap);
458 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 458, __func__, 0); goto cleanup; }
;
459
460
461 // Setup meshing input structure - mesher specific input gets set below before entering interface
462 tetgenInstance->meshInput.preserveSurfMesh = aimInputs[Preserve_Surf_Mesh-1].vals.integer;
463 tetgenInstance->meshInput.quiet = aimInputs[Mesh_Quiet_Flag-1].vals.integer;
464
465 // Set tetgen specific mesh inputs
466 tetgenInstance->meshInput.tetgenInput.meshQuality_rad_edge = aimInputs[Quality_Rad_Edge-1].vals.real;
467 tetgenInstance->meshInput.tetgenInput.meshQuality_angle = aimInputs[Quality_Angle-1].vals.real;
468 tetgenInstance->meshInput.tetgenInput.verbose = aimInputs[Mesh_Verbose_Flag-1].vals.integer;
469 tetgenInstance->meshInput.tetgenInput.ignoreSurfaceExtract = aimInputs[Ignore_Surface_Mesh_Extraction-1].vals.integer;
470 tetgenInstance->meshInput.tetgenInput.meshTolerance = aimInputs[Mesh_Tolerance-1].vals.real;
471
472 if (aimInputs[Regions-1].nullVal != IsNull) {
473 populate_regions(aimInfo,
474 &tetgenInstance->meshInput.tetgenInput.regions,
475 aimInputs[Regions-1].length,
476 aimInputs[Regions-1].vals.tuple);
477 }
478 if (aimInputs[Holes-1].nullVal != IsNull) {
479 populate_holes(&tetgenInstance->meshInput.tetgenInput.holes,
480 aimInputs[Holes-1].length,
481 aimInputs[Holes-1].vals.tuple);
482 }
483
484 if (aimInputs[Mesh_Gen_Input_String-1].nullVal != IsNull) {
485
486 AIM_STRDUP(tetgenInstance->meshInput.tetgenInput.meshInputString,{ if (tetgenInstance->meshInput.tetgenInput.meshInputString
!= __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 487, __func__, 1, "AIM_STRDUP: %s != NULL!", "tetgenInstance->meshInput.tetgenInput.meshInputString"
); goto cleanup; } tetgenInstance->meshInput.tetgenInput.meshInputString
= EG_strdup(aimInputs[Mesh_Gen_Input_String-1].vals.string);
if (tetgenInstance->meshInput.tetgenInput.meshInputString
== __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 487, __func__, 2, "AIM_STRDUP: %s %s", "tetgenInstance->meshInput.tetgenInput.meshInputString"
, aimInputs[Mesh_Gen_Input_String-1].vals.string); goto cleanup
; } }
487 aimInputs[Mesh_Gen_Input_String-1].vals.string, aimInfo, status){ if (tetgenInstance->meshInput.tetgenInput.meshInputString
!= __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 487, __func__, 1, "AIM_STRDUP: %s != NULL!", "tetgenInstance->meshInput.tetgenInput.meshInputString"
); goto cleanup; } tetgenInstance->meshInput.tetgenInput.meshInputString
= EG_strdup(aimInputs[Mesh_Gen_Input_String-1].vals.string);
if (tetgenInstance->meshInput.tetgenInput.meshInputString
== __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 487, __func__, 2, "AIM_STRDUP: %s %s", "tetgenInstance->meshInput.tetgenInput.meshInputString"
, aimInputs[Mesh_Gen_Input_String-1].vals.string); goto cleanup
; } }
;
488 }
489
490 status = populate_bndCondStruct_from_mapAttrToIndexStruct(&tetgenInstance->groupMap,
491 &tetgenInstance->meshInput.bndConds);
492 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 492, __func__, 0); goto cleanup; }
;
493
494
495 if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "SingleDomain") == 0) {
496 MultiMesh = 0;
497 } else if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiFile") == 0) {
498 MultiMesh = 1;
499 } else if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiDomain") == 0) {
500 MultiMesh = 2;
501 } else {
502 AIM_ERROR(aimInfo, "Developer error! Unknown Multiple_Mesh %s", aimInputs[Multiple_Mesh-1].vals.string){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 502, __func__
, "Developer error! Unknown Multiple_Mesh %s", aimInputs[Multiple_Mesh
-1].vals.string); }
;
503 status = CAPS_BADVALUE-311;
504 goto cleanup;
505 }
506
507 // Get mesh
508 surfaceMesh = (aimMeshRef *)aimInputs[Surface_Mesh-1].vals.AIMptr;
509
510 // Create/setup references
511 if (MultiMesh == 0 || MultiMesh == 2) {
512
513 AIM_ALLOC(tetgenInstance->meshRef, 1, aimMeshRef, aimInfo, status){ if (tetgenInstance->meshRef != __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 513, __func__, 1, "AIM_ALLOC: %s != NULL"
, "tetgenInstance->meshRef"); goto cleanup; } size_t memorysize
= 1; tetgenInstance->meshRef = (aimMeshRef *) EG_alloc(memorysize
*sizeof(aimMeshRef)); if (tetgenInstance->meshRef == __null
) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp",
513, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "tetgenInstance->meshRef"
, memorysize, "aimMeshRef"); goto cleanup; } }
;
514 tetgenInstance->numMeshRef = 1;
515
516 status = aim_initMeshRef(tetgenInstance->meshRef, aimVolumeMesh);
517 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 517, __func__, 0); goto cleanup; }
;
518
519 // set the filename without extensions where the grid is written for solvers
520 ibody = 0;
521 if (aimInputs[Proj_Name-1].nullVal != IsNull)
522 snprintf(bodyNumberFile, 128, "%s_%d", aimInputs[Proj_Name-1].vals.string, ibody);
523 else
524 snprintf(bodyNumberFile, 128, TETGENFILE"tetgen_%d", ibody);
525 status = aim_file(aimInfo, bodyNumberFile, aimFile);
526 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 526, __func__, 0); goto cleanup; }
;
527 AIM_STRDUP(tetgenInstance->meshRef[0].fileName, aimFile, aimInfo, status){ if (tetgenInstance->meshRef[0].fileName != __null) { status
= -4; aim_status(aimInfo, status, "tetgenAIM.cpp", 527, __func__
, 1, "AIM_STRDUP: %s != NULL!", "tetgenInstance->meshRef[0].fileName"
); goto cleanup; } tetgenInstance->meshRef[0].fileName = EG_strdup
(aimFile); if (tetgenInstance->meshRef[0].fileName == __null
) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp",
527, __func__, 2, "AIM_STRDUP: %s %s", "tetgenInstance->meshRef[0].fileName"
, aimFile); goto cleanup; } }
;
528
529 } else if (MultiMesh == 1) {
530
531 AIM_ALLOC(tetgenInstance->meshRef, surfaceMesh->nmap, aimMeshRef, aimInfo, status){ if (tetgenInstance->meshRef != __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 531, __func__, 1, "AIM_ALLOC: %s != NULL"
, "tetgenInstance->meshRef"); goto cleanup; } size_t memorysize
= surfaceMesh->nmap; tetgenInstance->meshRef = (aimMeshRef
*) EG_alloc(memorysize*sizeof(aimMeshRef)); if (tetgenInstance
->meshRef == __null) { status = -4; aim_status(aimInfo, status
, "tetgenAIM.cpp", 531, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "tetgenInstance->meshRef", memorysize, "aimMeshRef"); goto
cleanup; } }
;
532 tetgenInstance->numMeshRef = surfaceMesh->nmap;
533
534 for (ibody = 0; ibody < surfaceMesh->nmap; ibody++) {
535 status = aim_initMeshRef(&tetgenInstance->meshRef[ibody], aimVolumeMesh);
536 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 536, __func__, 0); goto cleanup; }
;
537 }
538
539 for (ibody = 0; ibody < surfaceMesh->nmap; ibody++) {
540 if (aimInputs[Proj_Name-1].nullVal != IsNull)
541 snprintf(bodyNumberFile, 128, "%s_%d", aimInputs[Proj_Name-1].vals.string, ibody);
542 else
543 snprintf(bodyNumberFile, 128, TETGENFILE"tetgen_%d", ibody);
544
545 status = aim_file(aimInfo, bodyNumberFile, aimFile);
546 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 546, __func__, 0); goto cleanup; }
;
547 AIM_STRDUP(tetgenInstance->meshRef[ibody].fileName, aimFile, aimInfo, status){ if (tetgenInstance->meshRef[ibody].fileName != __null) {
status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp", 547
, __func__, 1, "AIM_STRDUP: %s != NULL!", "tetgenInstance->meshRef[ibody].fileName"
); goto cleanup; } tetgenInstance->meshRef[ibody].fileName
= EG_strdup(aimFile); if (tetgenInstance->meshRef[ibody].
fileName == __null) { status = -4; aim_status(aimInfo, status
, "tetgenAIM.cpp", 547, __func__, 2, "AIM_STRDUP: %s %s", "tetgenInstance->meshRef[ibody].fileName"
, aimFile); goto cleanup; } }
;
548
549 AIM_ALLOC(tetgenInstance->meshRef[ibody].maps, 1, aimMeshTessMap, aimInfo, status){ if (tetgenInstance->meshRef[ibody].maps != __null) { status
= -4; aim_status(aimInfo, status, "tetgenAIM.cpp", 549, __func__
, 1, "AIM_ALLOC: %s != NULL", "tetgenInstance->meshRef[ibody].maps"
); goto cleanup; } size_t memorysize = 1; tetgenInstance->
meshRef[ibody].maps = (aimMeshTessMap *) EG_alloc(memorysize*
sizeof(aimMeshTessMap)); if (tetgenInstance->meshRef[ibody
].maps == __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 549, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "tetgenInstance->meshRef[ibody].maps"
, memorysize, "aimMeshTessMap"); goto cleanup; } }
;
550 tetgenInstance->meshRef[ibody].nmap = 1;
551 tetgenInstance->meshRef[ibody].maps[0].map = NULL__null;
552 tetgenInstance->meshRef[ibody].maps[0].tess = NULL__null;
553 }
554
555 }
556
557
558
559 status = CAPS_SUCCESS0;
560cleanup:
561 return status;
562}
563
564
565// ********************** AIM Function Break *****************************
566extern "C" int
567aimPreAnalysis(const void *instStore, void *aimInfo, capsValue *aimInputs)
568{
569 int i, j, elem, ibody; // Indexing
570
571 int status; // Return status
572
573 const aimStorage *tetgenInstance;
574
575 // Incoming bodies
576 const char *intents;
577 ego *bodies = NULL__null;
578 int numBody = 0;
579
580 // Container for surface mesh
581 int numSurfaceMesh = 0;
582 meshStruct *surfaceMesh = NULL__null;
583
584 aimMeshRef *meshRef = NULL__null;
585
586 // Container for volume mesh
587 int numVolumeMesh = 0;
588 meshStruct *volumeMesh = NULL__null;
589
590 // Attribute to index map
591 mapAttrToIndexStruct groupMap;
592 int lastAttr = 0;
593
594 // Meshing related variables
595 meshElementStruct *element;
596
597 double box[6], boxMax[6] = {0,0,0,0,0,0};
598 int bodyBoundingBox = 0;
599
600 int numElementCheck;
601 int MultiMesh = 0;
602
603 // File ouput
604 char bodyNumberFile[42];
605 //char filename[PATH_MAX];
606 FILE *fp;
1
'fp' declared without an initial value
607
608 status = initiate_mapAttrToIndexStruct(&groupMap);
609 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 609, __func__, 0); goto cleanup; }
;
2
Assuming 'status' is not equal to 0
3
Taking true branch
4
Control jumps to line 925
610
611 // Get AIM bodies
612 status = aim_getBodies(aimInfo, &intents, &numBody, &bodies);
613 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 613, __func__, 0); goto cleanup; }
;
614
615#ifdef DEBUG
616 printf(" tetgenAIM/aimPreAnalysis numBody = %d!\n", numBody);
617#endif
618
619 if (numBody <= 0 || bodies == NULL__null) {
620 AIM_ERROR(aimInfo, "No Bodies!"){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 620, __func__
, "No Bodies!"); }
;
621 return CAPS_SOURCEERR-330;
622 }
623 tetgenInstance = (const aimStorage *) instStore;
624
625 // remove previous meshes
626 for (ibody = 0; ibody < tetgenInstance->numMeshRef; ibody++) {
627 status = aim_deleteMeshes(aimInfo, &tetgenInstance->meshRef[ibody]);
628 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 628, __func__, 0); goto cleanup; }
;
629 }
630
631 // Get surface mesh
632 if (aimInputs[Surface_Mesh-1].nullVal == IsNull) {
633 AIM_ANALYSISIN_ERROR(aimInfo, Surface_Mesh, "'Surface_Mesh' input must be linked to an output 'Surface_Mesh'"){ aim_message(aimInfo, CERROR, Surface_Mesh, "tetgenAIM.cpp",
633, __func__, "'Surface_Mesh' input must be linked to an output 'Surface_Mesh'"
); }
;
634 status = CAPS_BADVALUE-311;
635 goto cleanup;
636 }
637
638 // Get mesh
639 meshRef = (aimMeshRef *)aimInputs[Surface_Mesh-1].vals.AIMptr;
640
641 if (meshRef->nmap != numBody) {
642 AIM_ANALYSISIN_ERROR(aimInfo, Surface_Mesh, "Number of linked surface meshes (%d) does not match the number of bodies (%d)\n",{ aim_message(aimInfo, CERROR, Surface_Mesh, "tetgenAIM.cpp",
643, __func__, "Number of linked surface meshes (%d) does not match the number of bodies (%d)\n"
, meshRef->nmap, numBody); }
643 meshRef->nmap, numBody){ aim_message(aimInfo, CERROR, Surface_Mesh, "tetgenAIM.cpp",
643, __func__, "Number of linked surface meshes (%d) does not match the number of bodies (%d)\n"
, meshRef->nmap, numBody); }
;
644 return CAPS_SOURCEERR-330;
645 }
646
647 AIM_ALLOC(surfaceMesh, meshRef->nmap, meshStruct, aimInfo, status){ if (surfaceMesh != __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 647, __func__, 1, "AIM_ALLOC: %s != NULL"
, "surfaceMesh"); goto cleanup; } size_t memorysize = meshRef
->nmap; surfaceMesh = (meshStruct *) EG_alloc(memorysize*sizeof
(meshStruct)); if (surfaceMesh == __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 647, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "surfaceMesh", memorysize, "meshStruct"); goto cleanup; } }
;
648 numSurfaceMesh = meshRef->nmap;
649
650 // Initiate surface meshes
651 for (i = 0; i < numBody; i++){
652 status = initiate_meshStruct(&surfaceMesh[i]);
653 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 653, __func__, 0); goto cleanup; }
;
654 }
655
656 for (i = 0; i < numBody; i++){
657 status = copy_mapAttrToIndexStruct( &tetgenInstance->groupMap,
658 &surfaceMesh[i].groupMap );
659 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 659, __func__, 0); goto cleanup; }
;
660
661 surfaceMesh[i].egadsTess = meshRef->maps[i].tess;
662 status = mesh_surfaceMeshEGADSTess(aimInfo, &surfaceMesh[i], (int)false);
663 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 663, __func__, 0); goto cleanup; }
;
664 }
665
666 if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "SingleDomain") == 0) {
667 MultiMesh = 0;
668 } else if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiFile") == 0) {
669 MultiMesh = 1;
670 } else if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiDomain") == 0) {
671 MultiMesh = 2;
672 } else {
673 AIM_ERROR(aimInfo, "Developer error! Unknown Multiple_Mesh %s", aimInputs[Multiple_Mesh-1].vals.string){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 673, __func__
, "Developer error! Unknown Multiple_Mesh %s", aimInputs[Multiple_Mesh
-1].vals.string); }
;
674 status = CAPS_BADVALUE-311;
675 goto cleanup;
676 }
677
678 // Create/setup volume meshes
679 if (MultiMesh == 0) {
680
681 // Determine which body is the bounding body based on size
682 bodyBoundingBox = 0;
683 if (numBody > 1) {
684
685 for (ibody = 0; ibody < numBody; ibody++) {
686
687 // Get bounding box for the body
688 status = EG_getBoundingBox(bodies[ibody], box);
689 if (status != EGADS_SUCCESS0) {
690 printf(" EG_getBoundingBox = %d\n\n", status);
691 return status;
692 }
693
694 // Just copy the box coordinates on the first go around
695 if (ibody == 0) {
696
697 memcpy(boxMax, box, sizeof(box));
698
699 // Set body as the bounding box (ie. farfield)
700 bodyBoundingBox = ibody;
701
702 // Else compare with the "max" box size
703 } else if (boxMax[0] >= box[0] &&
704 boxMax[1] >= box[1] &&
705 boxMax[2] >= box[2] &&
706 boxMax[3] <= box[3] &&
707 boxMax[4] <= box[4] &&
708 boxMax[5] <= box[5]) {
709
710 // If bigger copy coordinates
711 memcpy(boxMax, box, sizeof(box));
712
713 // Set body as the bounding box (ie. farfield)
714 bodyBoundingBox = ibody;
715 }
716 }
717 }
718
719 // Swap the surface element orientation so normals point out of the computational domain
720 for (ibody = 0; ibody < numBody; ibody++) {
721 if (ibody != bodyBoundingBox) {
722 // Swap two indices to reverse the normal vector of all elements on internal bodies
723 // so they point out of the domain
724 for (elem = 0; elem < surfaceMesh[ibody].numElement; elem++) {
725
726 element = surfaceMesh[ibody].element + elem;
727
728 // This should be valid for both Triangles and Quadrilaterals
729 i = element->connectivity[2];
730 element->connectivity[2] = element->connectivity[0];
731 element->connectivity[0] = i;
732 }
733 }
734 }
735
736 numVolumeMesh = 1;
737 AIM_ALLOC(volumeMesh, numVolumeMesh, meshStruct, aimInfo, status){ if (volumeMesh != __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 737, __func__, 1, "AIM_ALLOC: %s != NULL"
, "volumeMesh"); goto cleanup; } size_t memorysize = numVolumeMesh
; volumeMesh = (meshStruct *) EG_alloc(memorysize*sizeof(meshStruct
)); if (volumeMesh == __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 737, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "volumeMesh", memorysize, "meshStruct"); goto cleanup; } }
;
738
739 status = initiate_meshStruct(&volumeMesh[0]);
740 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 740, __func__, 0); goto cleanup; }
;
741
742 // Combine mesh - temporary store the combined mesh in the volume mesh
743 status = mesh_combineMeshStruct(aimInfo,
744 numSurfaceMesh,
745 surfaceMesh,
746 &volumeMesh[0]);
747 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 747, __func__, 0); goto cleanup; }
;
748
749 // Set reference meshes - All surfaces
750 volumeMesh[0].numReferenceMesh = numSurfaceMesh;
751 AIM_ALLOC(volumeMesh[0].referenceMesh, volumeMesh[0].numReferenceMesh, meshStruct, aimInfo, status){ if (volumeMesh[0].referenceMesh != __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 751, __func__, 1, "AIM_ALLOC: %s != NULL"
, "volumeMesh[0].referenceMesh"); goto cleanup; } size_t memorysize
= volumeMesh[0].numReferenceMesh; volumeMesh[0].referenceMesh
= (meshStruct *) EG_alloc(memorysize*sizeof(meshStruct)); if
(volumeMesh[0].referenceMesh == __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 751, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "volumeMesh[0].referenceMesh", memorysize, "meshStruct"); goto
cleanup; } }
;
752
753 for (ibody = 0; ibody < numSurfaceMesh; ibody++) {
754 volumeMesh[0].referenceMesh[ibody] = surfaceMesh[ibody];
755 }
756
757 // Report surface mesh
758 printf("Number of surface: nodes - %d, elements - %d\n",
759 volumeMesh[0].numNode, volumeMesh[0].numElement);
760
761 } else if (MultiMesh == 1) {
762
763 AIM_ALLOC(volumeMesh, numBody, meshStruct, aimInfo, status){ if (volumeMesh != __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 763, __func__, 1, "AIM_ALLOC: %s != NULL"
, "volumeMesh"); goto cleanup; } size_t memorysize = numBody;
volumeMesh = (meshStruct *) EG_alloc(memorysize*sizeof(meshStruct
)); if (volumeMesh == __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 763, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "volumeMesh", memorysize, "meshStruct"); goto cleanup; } }
;
764 numVolumeMesh = numBody;
765
766 for (ibody = 0; ibody < numVolumeMesh; ibody++) {
767 status = initiate_meshStruct(&volumeMesh[ibody]);
768 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 768, __func__, 0); goto cleanup; }
;
769
770 // Set reference mesh - One surface per body
771 volumeMesh[ibody].numReferenceMesh = 1;
772 AIM_ALLOC(volumeMesh[ibody].referenceMesh, volumeMesh[ibody].numReferenceMesh, meshStruct, aimInfo, status){ if (volumeMesh[ibody].referenceMesh != __null) { status = -
4; aim_status(aimInfo, status, "tetgenAIM.cpp", 772, __func__
, 1, "AIM_ALLOC: %s != NULL", "volumeMesh[ibody].referenceMesh"
); goto cleanup; } size_t memorysize = volumeMesh[ibody].numReferenceMesh
; volumeMesh[ibody].referenceMesh = (meshStruct *) EG_alloc(memorysize
*sizeof(meshStruct)); if (volumeMesh[ibody].referenceMesh == __null
) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp",
772, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "volumeMesh[ibody].referenceMesh"
, memorysize, "meshStruct"); goto cleanup; } }
;
773
774 volumeMesh[ibody].referenceMesh[0] = surfaceMesh[ibody];
775
776 // Report surface mesh
777 printf("Body %d number of surface: nodes - %d, elements - %d\n",
778 ibody+1, surfaceMesh[ibody].numNode, surfaceMesh[ibody].numElement);
779 }
780
781 } else if (MultiMesh == 2) {
782
783 numVolumeMesh = 1;
784 AIM_ALLOC(volumeMesh, numVolumeMesh, meshStruct, aimInfo, status){ if (volumeMesh != __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 784, __func__, 1, "AIM_ALLOC: %s != NULL"
, "volumeMesh"); goto cleanup; } size_t memorysize = numVolumeMesh
; volumeMesh = (meshStruct *) EG_alloc(memorysize*sizeof(meshStruct
)); if (volumeMesh == __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 784, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "volumeMesh", memorysize, "meshStruct"); goto cleanup; } }
;
785
786 status = initiate_meshStruct(&volumeMesh[0]);
787 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 787, __func__, 0); goto cleanup; }
;
788
789 // Set reference meshes
790 volumeMesh[0].numReferenceMesh = numBody;
791 AIM_ALLOC(volumeMesh[0].referenceMesh, volumeMesh[0].numReferenceMesh, meshStruct, aimInfo, status){ if (volumeMesh[0].referenceMesh != __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 791, __func__, 1, "AIM_ALLOC: %s != NULL"
, "volumeMesh[0].referenceMesh"); goto cleanup; } size_t memorysize
= volumeMesh[0].numReferenceMesh; volumeMesh[0].referenceMesh
= (meshStruct *) EG_alloc(memorysize*sizeof(meshStruct)); if
(volumeMesh[0].referenceMesh == __null) { status = -4; aim_status
(aimInfo, status, "tetgenAIM.cpp", 791, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "volumeMesh[0].referenceMesh", memorysize, "meshStruct"); goto
cleanup; } }
;
792
793 for (ibody = 0; ibody < numBody; ibody++) {
794 volumeMesh[0].referenceMesh[ibody] = surfaceMesh[ibody];
795
796 // Report surface mesh
797 printf("Body %d number of surface: nodes - %d, elements - %d\n",
798 ibody+1, surfaceMesh[ibody].numNode, surfaceMesh[ibody].numElement);
799 }
800
801 }
802
803 // Call tetgen volume mesh interface
804 if (MultiMesh == 0) {
805 printf("Getting volume mesh\n");
806
807 status = tetgen_VolumeMesh(aimInfo,
808 tetgenInstance->meshInput,
809 &tetgenInstance->groupMap,
810 tetgenInstance->meshRef[0].fileName,
811 1,
812 &volumeMesh[0],
813 &volumeMesh[0]);
814
815 if (status != CAPS_SUCCESS0) {
816 AIM_ERROR(aimInfo, "TetGen volume mesh failed!!!!"){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 816, __func__
, "TetGen volume mesh failed!!!!"); }
;
817 goto cleanup;
818 }
819
820 } else if (MultiMesh == 1) {
821
822 for (ibody = 0; ibody < numVolumeMesh; ibody++) {
823
824 // Call tetgen volume mesh interface for each body
825 printf("Getting volume mesh for body %d (of %d)\n", ibody+1, numBody);
826
827 // Get capsGroup name and index mapping
828 status = create_CAPSGroupAttrToIndexMap(1,
829 &bodies[ibody],
830 -1, // Only search the face level of the EGADS body
831 &groupMap);
832 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 832, __func__, 0); goto cleanup; }
;
833
834 for (i = 0; i < groupMap.numAttribute; i++) {
835 groupMap.attributeIndex[i] += lastAttr;
836 }
837
838 status = tetgen_VolumeMesh(aimInfo,
839 tetgenInstance->meshInput,
840 &groupMap,
841 tetgenInstance->meshRef[ibody].fileName,
842 1,
843 &volumeMesh[ibody].referenceMesh[0],
844 &volumeMesh[ibody]);
845
846 if (status != CAPS_SUCCESS0) {
847 AIM_ERROR(aimInfo, "TetGen volume mesh failed on body - %d!!!!", ibody+1){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 847, __func__
, "TetGen volume mesh failed on body - %d!!!!", ibody+1); }
;
848 goto cleanup;
849 }
850
851 lastAttr = groupMap.attributeIndex[groupMap.numAttribute-1];
852
853 status = destroy_mapAttrToIndexStruct(&groupMap);
854 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 854, __func__, 0); goto cleanup; }
;
855 }
856
857 } else if (MultiMesh == 2) {
858
859 printf("Getting volume mesh\n");
860
861 status = tetgen_VolumeMesh(aimInfo,
862 tetgenInstance->meshInput,
863 &tetgenInstance->groupMap,
864 tetgenInstance->meshRef[0].fileName,
865 volumeMesh[0].numReferenceMesh,
866 volumeMesh[0].referenceMesh,
867 &volumeMesh[0]);
868
869 if (status != CAPS_SUCCESS0) {
870 AIM_ERROR(aimInfo, "TetGen volume mesh failed!!!!"){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 870, __func__
, "TetGen volume mesh failed!!!!"); }
;
871 goto cleanup;
872 }
873 }
874
875 for (i = 0; i < numVolumeMesh; i++) {
876
877 // Check to make sure the volume mesher didn't add any unaccounted for points/faces
878 numElementCheck = 0;
879 for (j = 0; j < volumeMesh[i].numReferenceMesh; j++) {
880 numElementCheck += volumeMesh[i].referenceMesh[j].numElement;
881 }
882
883 if (volumeMesh[i].meshQuickRef.useStartIndex == (int) false &&
884 volumeMesh[i].meshQuickRef.useListIndex == (int) false) {
885
886 status = mesh_retrieveNumMeshElements(volumeMesh[i].numElement,
887 volumeMesh[i].element,
888 Triangle,
889 &volumeMesh[i].meshQuickRef.numTriangle);
890 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 890, __func__, 0); goto cleanup; }
;
891
892 status = mesh_retrieveNumMeshElements(volumeMesh[i].numElement,
893 volumeMesh[i].element,
894 Quadrilateral,
895 &volumeMesh[i].meshQuickRef.numQuadrilateral);
896 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 896, __func__, 0); goto cleanup; }
;
897
898 }
899
900 snprintf(bodyNumberFile, 42, NODATATRANSFER"noDataTransfer.%d", i);
901 status = aim_rmFile(aimInfo, bodyNumberFile);
902 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 902, __func__, 0); goto cleanup; }
;
903
904 if (numElementCheck != volumeMesh[i].meshQuickRef.numTriangle +
905 volumeMesh[i].meshQuickRef.numQuadrilateral) {
906
907 fp = aim_fopen(aimInfo, bodyNumberFile,"w");
908 if (fp == NULL__null) {
909 AIM_ERROR(aimInfo, "Failed to open '%s'", bodyNumberFile){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 909, __func__
, "Failed to open '%s'", bodyNumberFile); }
;
910 status = CAPS_IOERR-332;
911 goto cleanup;
912 }
913 fprintf(fp, "shucks...");
914 fclose(fp); fp = NULL__null;
915
916 printf("Volume mesher did not preserve surface elements - data transfer will NOT be possible.\n");
917 }
918 }
919
920 status = CAPS_SUCCESS0;
921
922cleanup:
923
924 // Destroy volumeMesh allocated arrays
925 if (volumeMesh
4.1
'volumeMesh' is equal to NULL
!= NULL__null) {
5
Taking false branch
926 for (i = 0; i < numVolumeMesh; i++) {
927 (void) destroy_meshStruct(&volumeMesh[i]);
928 }
929 AIM_FREE(volumeMesh){ EG_free(volumeMesh); volumeMesh = __null; };
930 }
931
932 for (i = 0; i < numSurfaceMesh; i++){
6
Loop condition is false. Execution continues on line 935
933 destroy_meshStruct(&surfaceMesh[i]);
934 }
935 AIM_FREE(surfaceMesh){ EG_free(surfaceMesh); surfaceMesh = __null; };
936
937 destroy_mapAttrToIndexStruct(&groupMap);
938
939 if (fp != NULL__null) fclose(fp);
7
The left operand of '!=' is a garbage value
940
941
942 return status;
943}
944
945
946/* the execution code from above should be moved here */
947extern "C" int
948aimExecute(/*@unused@*/ const void *instStore, /*@unused@*/ void *aimStruc, int *state)
949{
950 *state = 0;
951 return CAPS_SUCCESS0;
952}
953
954
955/* no longer optional and needed for restart */
956extern "C" int
957aimPostAnalysis(void *instStore, void *aimInfo,
958 int restart, capsValue *aimInputs)
959{
960 int status = CAPS_SUCCESS0;
961
962 // Incoming bodies
963 const char *intents;
964 ego *bodies = NULL__null;
965 int numBody = 0;
966
967 // Container for volume mesh
968 int numSurfaceMesh = 0;
969 aimMeshRef *surfaceMesh=NULL__null;
970
971 int i, j, ibody, nodeOffset;
972 int MultiMesh, numVolNode;
973
974 char volFile[PATH_MAX4096];
975 char bodyNumberFile[42];
976 FILE *fp = NULL__null;
977
978 int state, numSurfNode;
979 ego body;
980
981 aimStorage *tetgenInstance;
982 aimMesh mesh;
983
984 tetgenInstance = (aimStorage *) instStore;
985
986 // Get AIM bodies
987 status = aim_getBodies(aimInfo, &intents, &numBody, &bodies);
988 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 988, __func__, 0); goto cleanup; }
;
989
990 // Get mesh
991 surfaceMesh = (aimMeshRef *)aimInputs[Surface_Mesh-1].vals.AIMptr;
992 AIM_NOTNULL(surfaceMesh, aimInfo, status){ if (surfaceMesh == __null) { status = -307; aim_status(aimInfo
, status, "tetgenAIM.cpp", 992, __func__, 1, "%s == NULL!", "surfaceMesh"
); goto cleanup; } }
;
993 numSurfaceMesh = surfaceMesh->nmap;
994
995 if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "SingleDomain") == 0) {
996 MultiMesh = 0;
997 } else if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiFile") == 0) {
998 MultiMesh = 1;
999 } else if (strcasecmp(aimInputs[Multiple_Mesh-1].vals.string, "MultiDomain") == 0) {
1000 MultiMesh = 2;
1001 } else {
1002 AIM_ERROR(aimInfo, "Developer error! Unknown Multiple_Mesh %s", aimInputs[Multiple_Mesh-1].vals.string){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 1002, __func__
, "Developer error! Unknown Multiple_Mesh %s", aimInputs[Multiple_Mesh
-1].vals.string); }
;
1003 status = CAPS_BADVALUE-311;
1004 goto cleanup;
1005 }
1006
1007 // Create/setup mesh maps
1008 if (MultiMesh == 0 || MultiMesh == 2) {
1009
1010 ibody = 0;
1011
1012 if (MultiMesh == 2) {
1013 snprintf(volFile, PATH_MAX4096, "%s.txt", tetgenInstance->meshRef[0].fileName);
1014 fp = fopen(volFile, "r");
1015 if (fp == NULL__null) {
1016 AIM_ERROR(aimInfo, "Failed to open '%s'!", volFile){ aim_message(aimInfo, CERROR, 0 , "tetgenAIM.cpp", 1016, __func__
, "Failed to open '%s'!", volFile); }
;
1017 status = CAPS_IOERR-332;
1018 goto cleanup;
1019 }
1020 }
1021
1022 snprintf(bodyNumberFile, 42, NODATATRANSFER"noDataTransfer.%d", ibody);
1023 if (aim_isFile(aimInfo, bodyNumberFile) == CAPS_SUCCESS0) {
1024 // data transfer and sensitvities are not available
1025 tetgenInstance->meshRef[0].nmap = 0;
1026 tetgenInstance->meshRef[0].maps = NULL__null;
1027
1028 } else {
1029
1030 AIM_ALLOC(tetgenInstance->meshRef[0].maps, numSurfaceMesh, aimMeshTessMap, aimInfo, status){ if (tetgenInstance->meshRef[0].maps != __null) { status =
-4; aim_status(aimInfo, status, "tetgenAIM.cpp", 1030, __func__
, 1, "AIM_ALLOC: %s != NULL", "tetgenInstance->meshRef[0].maps"
); goto cleanup; } size_t memorysize = numSurfaceMesh; tetgenInstance
->meshRef[0].maps = (aimMeshTessMap *) EG_alloc(memorysize
*sizeof(aimMeshTessMap)); if (tetgenInstance->meshRef[0].maps
== __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1030, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "tetgenInstance->meshRef[0].maps"
, memorysize, "aimMeshTessMap"); goto cleanup; } }
;
1031 tetgenInstance->meshRef[0].nmap = numSurfaceMesh;
1032
1033 nodeOffset = 0;
1034 for (ibody = 0; ibody < numSurfaceMesh; ibody++) {
1035 tetgenInstance->meshRef[0].maps[ibody].tess = NULL__null;
1036 tetgenInstance->meshRef[0].maps[ibody].map = NULL__null;
1037
1038 tetgenInstance->meshRef[0].maps[ibody].tess = surfaceMesh->maps[ibody].tess;
1039
1040 status = EG_statusTessBody(surfaceMesh->maps[ibody].tess, &body, &state, &numSurfNode);
1041 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1041, __func__, 0); goto cleanup; }
;
1042
1043 AIM_ALLOC(tetgenInstance->meshRef[0].maps[ibody].map, numSurfNode, int, aimInfo, status){ if (tetgenInstance->meshRef[0].maps[ibody].map != __null
) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp",
1043, __func__, 1, "AIM_ALLOC: %s != NULL", "tetgenInstance->meshRef[0].maps[ibody].map"
); goto cleanup; } size_t memorysize = numSurfNode; tetgenInstance
->meshRef[0].maps[ibody].map = (int *) EG_alloc(memorysize
*sizeof(int)); if (tetgenInstance->meshRef[0].maps[ibody].
map == __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1043, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "tetgenInstance->meshRef[0].maps[ibody].map"
, memorysize, "int"); goto cleanup; } }
;
1044 for (i = 0; i < numSurfNode; i++)
1045 tetgenInstance->meshRef[0].maps[ibody].map[i] = nodeOffset + i+1;
1046
1047 if (MultiMesh == 0) {
1048 nodeOffset += numSurfNode;
1049 } else {
1050 fscanf(fp, "%d", &numVolNode);
1051 nodeOffset += numVolNode;
1052 }
1053 }
1054 }
1055
1056 } else if (MultiMesh == 1) {
1057
1058 for (ibody = 0; ibody < numBody; ibody++) {
1059 snprintf(bodyNumberFile, 42, NODATATRANSFER"noDataTransfer.%d", ibody);
1060 if (aim_isFile(aimInfo, bodyNumberFile) == CAPS_SUCCESS0) continue;
1061
1062 tetgenInstance->meshRef[ibody].maps[0].tess = surfaceMesh->maps[ibody].tess;
1063
1064 status = EG_statusTessBody(surfaceMesh->maps[ibody].tess, &body, &state, &numSurfNode);
1065 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1065, __func__, 0); goto cleanup; }
;
1066
1067 AIM_ALLOC(tetgenInstance->meshRef[ibody].maps[0].map, numSurfNode, int, aimInfo, status){ if (tetgenInstance->meshRef[ibody].maps[0].map != __null
) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp",
1067, __func__, 1, "AIM_ALLOC: %s != NULL", "tetgenInstance->meshRef[ibody].maps[0].map"
); goto cleanup; } size_t memorysize = numSurfNode; tetgenInstance
->meshRef[ibody].maps[0].map = (int *) EG_alloc(memorysize
*sizeof(int)); if (tetgenInstance->meshRef[ibody].maps[0].
map == __null) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1067, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "tetgenInstance->meshRef[ibody].maps[0].map"
, memorysize, "int"); goto cleanup; } }
;
1068 for (i = 0; i < numSurfNode; i++)
1069 tetgenInstance->meshRef[ibody].maps[0].map[i] = i+1;
1070 }
1071 }
1072
1073 for (i = 0; i < tetgenInstance->numMeshRef; i++) {
1074
1075 AIM_ALLOC(tetgenInstance->meshRef[i].bnds, tetgenInstance->groupMap.numAttribute, aimMeshBnd, aimInfo, status){ if (tetgenInstance->meshRef[i].bnds != __null) { status =
-4; aim_status(aimInfo, status, "tetgenAIM.cpp", 1075, __func__
, 1, "AIM_ALLOC: %s != NULL", "tetgenInstance->meshRef[i].bnds"
); goto cleanup; } size_t memorysize = tetgenInstance->groupMap
.numAttribute; tetgenInstance->meshRef[i].bnds = (aimMeshBnd
*) EG_alloc(memorysize*sizeof(aimMeshBnd)); if (tetgenInstance
->meshRef[i].bnds == __null) { status = -4; aim_status(aimInfo
, status, "tetgenAIM.cpp", 1075, __func__, 3, "AIM_ALLOC: %s size %zu type %s"
, "tetgenInstance->meshRef[i].bnds", memorysize, "aimMeshBnd"
); goto cleanup; } }
;
1076 tetgenInstance->meshRef[i].nbnd = tetgenInstance->groupMap.numAttribute;
1077 for (j = 0; j < tetgenInstance->meshRef[i].nbnd; j++) {
1078 status = aim_initMeshBnd(tetgenInstance->meshRef[i].bnds + j);
1079 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1079, __func__, 0); goto cleanup; }
;
1080 }
1081
1082 for (j = 0; j < tetgenInstance->meshRef[i].nbnd; j++) {
1083 AIM_STRDUP(tetgenInstance->meshRef[i].bnds[j].groupName, tetgenInstance->groupMap.attributeName[j], aimInfo, status){ if (tetgenInstance->meshRef[i].bnds[j].groupName != __null
) { status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp",
1083, __func__, 1, "AIM_STRDUP: %s != NULL!", "tetgenInstance->meshRef[i].bnds[j].groupName"
); goto cleanup; } tetgenInstance->meshRef[i].bnds[j].groupName
= EG_strdup(tetgenInstance->groupMap.attributeName[j]); if
(tetgenInstance->meshRef[i].bnds[j].groupName == __null) {
status = -4; aim_status(aimInfo, status, "tetgenAIM.cpp", 1083
, __func__, 2, "AIM_STRDUP: %s %s", "tetgenInstance->meshRef[i].bnds[j].groupName"
, tetgenInstance->groupMap.attributeName[j]); goto cleanup
; } }
;
1084 tetgenInstance->meshRef[i].bnds[j].ID = tetgenInstance->groupMap.attributeIndex[j];
1085 }
1086 }
1087
1088 for (i = 0; i < tetgenInstance->numMeshRef; i++) {
1089 status = aim_queryMeshes( aimInfo, Mesh_Format, ANALYSISIN, &tetgenInstance->meshRef[i] );
1090 if (status > 0) {
1091 mesh.meshData = NULL__null;
1092 mesh.meshRef = &tetgenInstance->meshRef[i];
1093
1094 status = aim_readBinaryUgrid(aimInfo, &mesh);
1095 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1095, __func__, 0); goto cleanup; }
;
1096
1097 status = aim_writeMeshes(aimInfo, Mesh_Format, ANALYSISIN, &mesh);
1098 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1098, __func__, 0); goto cleanup; }
;
1099
1100 status = aim_freeMeshData(mesh.meshData);
1101 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1101, __func__, 0); goto cleanup; }
;
1102 AIM_FREE(mesh.meshData){ EG_free(mesh.meshData); mesh.meshData = __null; };
1103 }
1104 else
1105 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1105, __func__, 0); goto cleanup; }
;
1106 }
1107
1108cleanup:
1109 if (fp != NULL__null) fclose(fp);
1110 return status;
1111}
1112
1113
1114extern "C" int
1115aimOutputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, int index,
1116 char **aoname, capsValue *form)
1117{
1118 /*! \page aimOutputsTetGen AIM Outputs
1119 * The following list outlines the TetGen AIM outputs available through the AIM interface.
1120 */
1121
1122 int status = CAPS_SUCCESS0;
1123
1124#ifdef DEBUG
1125 printf(" tetgenAIM/aimOutputs index = %d!\n", index);
1126#endif
1127 if (index == NumberOfElement) {
1128 *aoname = EG_strdup("NumberOfElement");
1129 form->type = Integer;
1130 form->vals.integer = 0;
1131
1132 /*! \page aimOutputsTetGen
1133 * - <B> NumberOfElement </B> <br>
1134 * Number of elements in the surface mesh
1135 */
1136
1137 } else if (index == NumberOfNode) {
1138 *aoname = EG_strdup("NumberOfNode");
1139 form->type = Integer;
1140 form->vals.integer = 0;
1141
1142 /*! \page aimOutputsTetGen
1143 * - <B> NumberOfNode </B> <br>
1144 * Number of vertices in the surface mesh
1145 */
1146
1147 } else if (index == Volume_Mesh) {
1148 *aoname = AIM_NAME(Volume_Mesh)EG_strdup("Volume_Mesh");
1149 form->type = PointerMesh;
1150 form->dim = Vector;
1151 form->lfixed = Change;
1152 form->sfixed = Fixed;
1153 form->vals.AIMptr = NULL__null;
1154 form->nullVal = IsNull;
1155
1156 /*! \page aimOutputsTetGen
1157 * - <B> Volume_Mesh </B> <br>
1158 * The volume mesh for a link
1159 */
1160
1161 } else {
1162 status = CAPS_BADINDEX-304;
1163 AIM_STATUS(aimInfo, status, "Unknown output index %d!", index)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1163, __func__, 2, "Unknown output index %d!", index); goto
cleanup; }
;
1164 }
1165
1166 AIM_NOTNULL(*aoname, aimInfo, status){ if (*aoname == __null) { status = -307; aim_status(aimInfo,
status, "tetgenAIM.cpp", 1166, __func__, 1, "%s == NULL!", "*aoname"
); goto cleanup; } }
;
1167
1168cleanup:
1169 if (status != CAPS_SUCCESS0) AIM_FREE(*aoname){ EG_free(*aoname); *aoname = __null; };
1170 return status;
1171}
1172
1173
1174extern "C" int
1175aimCalcOutput(void *instStore, void *aimInfo, int index, capsValue *val)
1176{
1177 int i, status = CAPS_SUCCESS0;
1178 int numElement, numNodes;
1179 int nVertex, nTri, nQuad, nTet, nPyramid, nPrism, nHex;
1180 aimStorage *tetgenInstance;
1181 aimMesh mesh;
1182
1183#ifdef DEBUG
1184 printf(" tetgenAIM/aimCalcOutput index = %d!\n", index);
1185#endif
1186 tetgenInstance = (aimStorage *) instStore;
1187
1188 if (NumberOfElement == index) {
1189
1190 // Count the total number of surface elements
1191 numElement = 0;
1192 for (i = 0; i < tetgenInstance->numMeshRef; i++) {
1193 status = aim_readBinaryUgridHeader(aimInfo, &tetgenInstance->meshRef[i],
1194 &nVertex, &nTri, &nQuad,
1195 &nTet, &nPyramid, &nPrism, &nHex);
1196 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1196, __func__, 0); goto cleanup; }
;
1197
1198 numElement += nTri + nQuad + nTet + nPyramid + nPrism + nHex;
1199 }
1200
1201 val->vals.integer = numElement;
1202
1203 } else if (NumberOfNode == index) {
1204
1205 // Count the total number of surface vertices
1206 numNodes = 0;
1207 for (i = 0; i < tetgenInstance->numMeshRef; i++) {
1208 status = aim_readBinaryUgridHeader(aimInfo, &tetgenInstance->meshRef[i],
1209 &nVertex, &nTri, &nQuad,
1210 &nTet, &nPyramid, &nPrism, &nHex);
1211 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1211, __func__, 0); goto cleanup; }
;
1212
1213 numNodes += nVertex;
1214 }
1215
1216 val->vals.integer = numNodes;
1217
1218 } else if (Volume_Mesh == index) {
1219
1220 for (i = 0; i < tetgenInstance->numMeshRef; i++) {
1221 status = aim_queryMeshes( aimInfo, Volume_Mesh, ANALYSISOUT, &tetgenInstance->meshRef[i] );
1222 if (status > 0) {
1223 mesh.meshData = NULL__null;
1224 mesh.meshRef = &tetgenInstance->meshRef[i];
1225
1226 status = aim_readBinaryUgrid(aimInfo, &mesh);
1227 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1227, __func__, 0); goto cleanup; }
;
1228
1229 status = aim_writeMeshes(aimInfo, Volume_Mesh, ANALYSISOUT, &mesh);
1230 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1230, __func__, 0); goto cleanup; }
;
1231
1232 status = aim_freeMeshData(mesh.meshData);
1233 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1233, __func__, 0); goto cleanup; }
;
1234 AIM_FREE(mesh.meshData){ EG_free(mesh.meshData); mesh.meshData = __null; };
1235 }
1236 else
1237 AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1237, __func__, 0); goto cleanup; }
;
1238 }
1239
1240 // Return the volume mesh references
1241 val->nrow = tetgenInstance->numMeshRef;
1242 val->vals.AIMptr = tetgenInstance->meshRef;
1243
1244 } else {
1245
1246 status = CAPS_BADINDEX-304;
1247 AIM_STATUS(aimInfo, status, "Unknown output index %d!", index)if (status != 0) { aim_status(aimInfo, status, "tetgenAIM.cpp"
, 1247, __func__, 2, "Unknown output index %d!", index); goto
cleanup; }
;
1248
1249 }
1250
1251cleanup:
1252
1253 return status;
1254}
1255
1256extern "C" void
1257aimCleanup(void *instStore)
1258{
1259 int status; // Function return status
1260 aimStorage *tetgenInstance;
1261
1262#ifdef DEBUG
1263 printf(" tetgenAIM/aimCleanup!\n");
1264#endif
1265 tetgenInstance = (aimStorage *) instStore;
1266
1267 status = destroy_aimStorage(tetgenInstance);
1268 if (status != CAPS_SUCCESS0)
1269 printf("Status = %d, tetgenAIM aimStorage cleanup!!!\n", status);
1270
1271 EG_free(tetgenInstance);
1272}