File: | refine/refineAIM.c |
Warning: | line 1289, column 18 3rd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * CAPS: Computational Aircraft Prototype Syntheses | |||
3 | * | |||
4 | * refine AIM | |||
5 | * | |||
6 | * * Copyright 2014-2023, Massachusetts Institute of Technology | |||
7 | * Licensed under The GNU Lesser General Public License, version 2.1 | |||
8 | * See http://www.opensource.org/licenses/lgpl-2.1.php | |||
9 | * | |||
10 | */ | |||
11 | ||||
12 | /*!\mainpage Introduction | |||
13 | * | |||
14 | * \section overviewRefine refine AIM Overview | |||
15 | * A module in the Computational Aircraft Prototype Syntheses (CAPS) has been developed to interact with the | |||
16 | * unstructured mesh adaptation software <a href="https://github.com/nasa/refine">refine</a>. | |||
17 | * | |||
18 | * An outline of the AIM's inputs and outputs are provided in \ref aimInputsRefine and \ref aimOutputsRefine, respectively. | |||
19 | * | |||
20 | * The refine AIM can automatically execute ref, with details provided in \ref aimExecuteRefine. | |||
21 | * | |||
22 | */ | |||
23 | ||||
24 | #include <string.h> | |||
25 | #include <math.h> | |||
26 | #include "aimUtil.h" | |||
27 | #include "aimMesh.h" | |||
28 | ||||
29 | #include "meshUtils.h" // Collection of helper functions for meshing | |||
30 | #include "miscUtils.h" // Collection of helper functions for miscellaneous analysis | |||
31 | ||||
32 | #include "libMeshbWriter.h" | |||
33 | #include "libMeshb/sources/libmeshb7.h" | |||
34 | ||||
35 | #define EXPORT_MESHB_VERTEX_ID(1) (1) | |||
36 | #define EXPORT_MESHB_2D_ID(1) (1) | |||
37 | #define EXPORT_MESHB_3D_ID(0) (0) | |||
38 | #define EXPORT_MESHB_VERTEX_3(10000000) (10000000) | |||
39 | #define EXPORT_MESHB_VERTEX_4(200000000) (200000000) | |||
40 | ||||
41 | ||||
42 | #ifdef WIN32 | |||
43 | /* needs Advapi32.lib & Ws2_32.lib */ | |||
44 | #include <Windows.h> | |||
45 | #define strcasecmp stricmp | |||
46 | #define snprintf _snprintf | |||
47 | #define access _access | |||
48 | #define F_OK0 0 | |||
49 | #else | |||
50 | #include <unistd.h> | |||
51 | #endif | |||
52 | ||||
53 | //#define DEBUG | |||
54 | ||||
55 | #define CROSS(a,b,c)a[0] = (b[1]*c[2]) - (b[2]*c[1]); a[1] = (b[2]*c[0]) - (b[0]* c[2]); a[2] = (b[0]*c[1]) - (b[1]*c[0]) a[0] = (b[1]*c[2]) - (b[2]*c[1]);\ | |||
56 | a[1] = (b[2]*c[0]) - (b[0]*c[2]);\ | |||
57 | a[2] = (b[0]*c[1]) - (b[1]*c[0]) | |||
58 | #define DOT(a,b)(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) | |||
59 | ||||
60 | enum aimInputs | |||
61 | { | |||
62 | inref = 1, /* index is 1-based */ | |||
63 | inComplexity, | |||
64 | inPasses, | |||
65 | inMesh, | |||
66 | inScalarFieldFile, | |||
67 | inHessianFieldFile, | |||
68 | inMetricFieldFile, | |||
69 | NUMINPUT = inMetricFieldFile /* Total number of inputs */ | |||
70 | }; | |||
71 | ||||
72 | enum aimOutputs | |||
73 | { | |||
74 | outMesh = 1, /* index is 1-based */ | |||
75 | outxyz, | |||
76 | NUMOUT = outxyz /* Total number of outputs */ | |||
77 | }; | |||
78 | ||||
79 | static char egadsFileName[] = "refine_in.egads"; | |||
80 | static char refine_out[] = "refine_out.meshb"; | |||
81 | static char refInput[] = "refInput.txt"; | |||
82 | static char metricFileName[] = "metric.solb"; | |||
83 | ||||
84 | ||||
85 | typedef struct { | |||
86 | int npts; | |||
87 | double *xyz; | |||
88 | double *t; | |||
89 | int *ivp; // volume node index | |||
90 | } edgeData; | |||
91 | ||||
92 | ||||
93 | typedef struct { | |||
94 | int npts; | |||
95 | double *xyz; | |||
96 | double *uv; | |||
97 | int ntri; | |||
98 | int *tris; | |||
99 | int *ivp; // volume node index | |||
100 | } faceData; | |||
101 | ||||
102 | ||||
103 | typedef struct { | |||
104 | double **rvec; | |||
105 | ego *surfaces; | |||
106 | ego body; | |||
107 | ego *faces; | |||
108 | ego *edges; | |||
109 | ego *nodes; | |||
110 | int nfaces; | |||
111 | int nedges; | |||
112 | int nnodes; | |||
113 | ||||
114 | edgeData *tedges; | |||
115 | faceData *tfaces; | |||
116 | } bodyData; | |||
117 | ||||
118 | ||||
119 | typedef struct { | |||
120 | int ivp; // global index into volume vertexes | |||
121 | int egadsType; // egads type, NODE, EDGE, FACE | |||
122 | int egadsID; // type-index | |||
123 | double param[2]; // parametric coordinates of the vertex | |||
124 | } srfVertex; | |||
125 | ||||
126 | ||||
127 | typedef struct { | |||
128 | // Mesh reference obtained from meshing AIM | |||
129 | aimMeshRef *meshRefIn; | |||
130 | ||||
131 | aimMeshRef meshRefOut; | |||
132 | ||||
133 | // Attribute to index map | |||
134 | mapAttrToIndexStruct groupMap; | |||
135 | ||||
136 | int *faceID; | |||
137 | ||||
138 | } aimStorage; | |||
139 | ||||
140 | ||||
141 | static int | |||
142 | readlibMeshb(void *aimInfo, aimStorage *refineInstance, aimMesh *mesh); | |||
143 | ||||
144 | ||||
145 | static int initiate_bodyData(int numBody, bodyData *bodydata) | |||
146 | { | |||
147 | int i; | |||
148 | ||||
149 | for (i = 0; i < numBody; i++) { | |||
150 | bodydata[i].rvec = NULL((void*)0); | |||
151 | bodydata[i].surfaces = NULL((void*)0); | |||
152 | bodydata[i].faces = NULL((void*)0); | |||
153 | bodydata[i].edges = NULL((void*)0); | |||
154 | bodydata[i].nodes = NULL((void*)0); | |||
155 | bodydata[i].nfaces = 0; | |||
156 | bodydata[i].nedges = 0; | |||
157 | bodydata[i].nnodes = 0; | |||
158 | bodydata[i].tedges = NULL((void*)0); | |||
159 | bodydata[i].tfaces = NULL((void*)0); | |||
160 | } | |||
161 | ||||
162 | return CAPS_SUCCESS0; | |||
163 | } | |||
164 | ||||
165 | static int destroy_bodyData(int numBody, bodyData *bodydata) | |||
166 | { | |||
167 | int i, j; | |||
168 | ||||
169 | if (bodydata == NULL((void*)0)) return CAPS_SUCCESS0; | |||
170 | ||||
171 | for (i = 0; i < numBody; i++) { | |||
172 | for (j = 0; j < bodydata[i].nfaces; j++) { | |||
173 | if (bodydata[i].surfaces != NULL((void*)0)) | |||
174 | if (bodydata[i].surfaces[j+bodydata[i].nfaces] != NULL((void*)0)) | |||
175 | EG_deleteObject(bodydata[i].surfaces[j+bodydata[i].nfaces]); | |||
176 | if (bodydata[i].rvec != NULL((void*)0)) | |||
177 | EG_free(bodydata[i].rvec[j]); | |||
178 | } | |||
179 | EG_free(bodydata[i].nodes); | |||
180 | EG_free(bodydata[i].edges); | |||
181 | EG_free(bodydata[i].faces); | |||
182 | EG_free(bodydata[i].surfaces); | |||
183 | EG_free(bodydata[i].rvec); | |||
184 | ||||
185 | if (bodydata[i].tedges != NULL((void*)0)) { | |||
186 | for (j = 0; j < bodydata[i].nedges; j++) { | |||
187 | EG_free(bodydata[i].tedges[j].xyz); | |||
188 | EG_free(bodydata[i].tedges[j].t); | |||
189 | EG_free(bodydata[i].tedges[j].ivp); | |||
190 | } | |||
191 | EG_free(bodydata[i].tedges); | |||
192 | } | |||
193 | ||||
194 | if (bodydata[i].tfaces != NULL((void*)0)) { | |||
195 | for (j = 0; j < bodydata[i].nfaces; j++) { | |||
196 | EG_free(bodydata[i].tfaces[j].xyz); | |||
197 | EG_free(bodydata[i].tfaces[j].uv); | |||
198 | EG_free(bodydata[i].tfaces[j].tris); | |||
199 | EG_free(bodydata[i].tfaces[j].ivp); | |||
200 | } | |||
201 | EG_free(bodydata[i].tfaces); | |||
202 | } | |||
203 | } | |||
204 | ||||
205 | return CAPS_SUCCESS0; | |||
206 | } | |||
207 | ||||
208 | ||||
209 | static int initiate_aimStorage(aimStorage *refineInstance) | |||
210 | { | |||
211 | ||||
212 | int status = CAPS_SUCCESS0; | |||
213 | ||||
214 | refineInstance->meshRefIn = NULL((void*)0); | |||
215 | ||||
216 | // Mesh reference passed to solver | |||
217 | status = aim_initMeshRef(&refineInstance->meshRefOut, aimUnknownMeshType); | |||
218 | if (status != CAPS_SUCCESS0) return status; | |||
219 | ||||
220 | status = initiate_mapAttrToIndexStruct(&refineInstance->groupMap); | |||
221 | if (status != CAPS_SUCCESS0) return status; | |||
222 | ||||
223 | refineInstance->faceID = NULL((void*)0); | |||
224 | ||||
225 | return CAPS_SUCCESS0; | |||
226 | } | |||
227 | ||||
228 | ||||
229 | static int destroy_aimStorage(aimStorage *refineInstance) | |||
230 | { | |||
231 | int status; // Function return status | |||
232 | ||||
233 | refineInstance->meshRefIn = NULL((void*)0); | |||
234 | ||||
235 | // Free the meshRef | |||
236 | aim_freeMeshRef(&refineInstance->meshRefOut); | |||
237 | ||||
238 | status = destroy_mapAttrToIndexStruct(&refineInstance->groupMap); | |||
239 | if (status != CAPS_SUCCESS0) | |||
240 | printf("Status = %d, refineAIM attributeMap group cleanup!!!\n", status); | |||
241 | ||||
242 | AIM_FREE(refineInstance->faceID){ EG_free(refineInstance->faceID); refineInstance->faceID = ((void*)0); }; | |||
243 | ||||
244 | return status; | |||
245 | } | |||
246 | ||||
247 | ||||
248 | /****************** exposed AIM entry points -- Analysis **********************/ | |||
249 | ||||
250 | /* aimInitialize: Initialization Information for the AIM */ | |||
251 | int | |||
252 | aimInitialize(int inst, /*@unused@*/ const char *unitSys, void *aimInfo, | |||
253 | /*@unused@*/ void **instStore, /*@unused@*/ int *major, | |||
254 | /*@unused@*/ int *minor, int *nIn, int *nOut, | |||
255 | int *nFields, char ***fnames, int **franks, int **fInOut) | |||
256 | { | |||
257 | int i, status = CAPS_SUCCESS0; | |||
258 | aimStorage *refineInstance = NULL((void*)0); | |||
259 | ||||
260 | /* specify the number of analysis inputs defined in aimInputs | |||
261 | * and the number of analysis outputs defined in aimOutputs */ | |||
262 | *nIn = NUMINPUT; | |||
263 | *nOut = NUMOUT; | |||
264 | ||||
265 | /* return if "query" only */ | |||
266 | if (inst == -1) return CAPS_SUCCESS0; | |||
267 | ||||
268 | /* specify the field variables this analysis can generate and consume */ | |||
269 | *nFields = 0; | |||
270 | ||||
271 | /* specify the name of each field variable */ | |||
272 | *fnames = NULL((void*)0); | |||
273 | ||||
274 | /* specify the rank of each field variable */ | |||
275 | *franks = NULL((void*)0); | |||
276 | ||||
277 | /* specify if a field is an input field or output field */ | |||
278 | *fInOut = NULL((void*)0); | |||
279 | ||||
280 | /* setup our AIM specific state */ | |||
281 | AIM_ALLOC(refineInstance, 1, aimStorage, aimInfo, status){ if (refineInstance != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 281, __func__, 1, "AIM_ALLOC: %s != NULL" , "refineInstance"); goto cleanup; } size_t memorysize = 1; refineInstance = (aimStorage *) EG_alloc(memorysize*sizeof(aimStorage)); if (refineInstance == ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 281, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "refineInstance", memorysize, "aimStorage"); goto cleanup; } }; | |||
282 | *instStore = refineInstance; | |||
283 | ||||
284 | status = initiate_aimStorage(refineInstance); | |||
285 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 285, __func__, 0); goto cleanup; }; | |||
286 | ||||
287 | status = CAPS_SUCCESS0; | |||
288 | ||||
289 | cleanup: | |||
290 | if (status != CAPS_SUCCESS0) { | |||
291 | /* release all possibly allocated memory on error */ | |||
292 | if (*fnames != NULL((void*)0)) | |||
293 | for (i = 0; i < *nFields; i++) AIM_FREE((*fnames)[i]){ EG_free((*fnames)[i]); (*fnames)[i] = ((void*)0); }; | |||
294 | AIM_FREE(*franks){ EG_free(*franks); *franks = ((void*)0); }; | |||
295 | AIM_FREE(*fInOut){ EG_free(*fInOut); *fInOut = ((void*)0); }; | |||
296 | AIM_FREE(*fnames){ EG_free(*fnames); *fnames = ((void*)0); }; | |||
297 | AIM_FREE(*instStore){ EG_free(*instStore); *instStore = ((void*)0); }; | |||
298 | *nFields = 0; | |||
299 | } | |||
300 | ||||
301 | return status; | |||
302 | } | |||
303 | ||||
304 | ||||
305 | // ********************** AIM Function Break ***************************** | |||
306 | /* aimInputs: Input Information for the AIM */ | |||
307 | int | |||
308 | aimInputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, int index, | |||
309 | char **ainame, capsValue *defval) | |||
310 | { | |||
311 | int status = CAPS_SUCCESS0; | |||
312 | ||||
313 | /*! \page aimInputsRefine AIM Inputs | |||
314 | * The following list outlines the refine inputs along with their default value available | |||
315 | * through the AIM interface. | |||
316 | */ | |||
317 | ||||
318 | /* fill in the required members based on the index */ | |||
319 | if (index == inref) { | |||
320 | *ainame = AIM_NAME(ref)EG_strdup("ref"); | |||
321 | defval->type = String; | |||
322 | defval->lfixed = Fixed; | |||
323 | AIM_STRDUP(defval->vals.string, "ref", aimInfo, status){ if (defval->vals.string != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 323, __func__, 1, "AIM_STRDUP: %s != NULL!" , "defval->vals.string"); goto cleanup; } defval->vals. string = EG_strdup("ref"); if (defval->vals.string == ((void *)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c" , 323, __func__, 2, "AIM_STRDUP: %s %s", "defval->vals.string" , "ref"); goto cleanup; } }; | |||
324 | ||||
325 | /*! \page aimInputsRefine | |||
326 | * - <B>ref = "ref"</B> <br> | |||
327 | * refine executable | |||
328 | */ | |||
329 | ||||
330 | } else if (index == inPasses) { | |||
331 | *ainame = AIM_NAME(Passes)EG_strdup("Passes"); | |||
332 | defval->type = Integer; | |||
333 | defval->dim = Scalar; | |||
334 | defval->vals.integer = 30; | |||
335 | ||||
336 | /*! \page aimInputsRefine | |||
337 | * - <B> Passes = 30</B> <br> | |||
338 | * Number of refine internal adaptation iterations | |||
339 | */ | |||
340 | ||||
341 | } else if (index == inMesh) { | |||
342 | *ainame = AIM_NAME(Mesh)EG_strdup("Mesh"); | |||
343 | defval->type = PointerMesh; | |||
344 | defval->nrow = 1; | |||
345 | defval->lfixed = Fixed; | |||
346 | defval->vals.AIMptr = NULL((void*)0); | |||
347 | defval->nullVal = IsNull; | |||
348 | AIM_STRDUP(defval->meshWriter, MESHWRITER, aimInfo, status){ if (defval->meshWriter != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 348, __func__, 1, "AIM_STRDUP: %s != NULL!" , "defval->meshWriter"); goto cleanup; } defval->meshWriter = EG_strdup("libMeshbWriter"); if (defval->meshWriter == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c" , 348, __func__, 2, "AIM_STRDUP: %s %s", "defval->meshWriter" , "libMeshbWriter"); goto cleanup; } }; | |||
349 | ||||
350 | /*! \page aimInputsRefine | |||
351 | * - <B>Mesh = NULL</B> <br> | |||
352 | * An Area_Mesh or Volume_Mesh link for mesh adaptation | |||
353 | */ | |||
354 | ||||
355 | } else if (index == inComplexity) { | |||
356 | *ainame = AIM_NAME(Complexity)EG_strdup("Complexity"); | |||
357 | defval->type = Double; | |||
358 | defval->dim = Scalar; | |||
359 | defval->nullVal = IsNull; | |||
360 | ||||
361 | /*! \page aimInputsRefine | |||
362 | * - <B> Complexity = NULL</B> <br> | |||
363 | * Must be specified in combination with a ScalarFieldFile or HessianFieldFile. <br> | |||
364 | * Cannot be specified in combination with MetricFieldFile. <br> | |||
365 | * Complexity is approximately half the target number of vertices. | |||
366 | */ | |||
367 | ||||
368 | } else if (index == inScalarFieldFile) { | |||
369 | *ainame = AIM_NAME(ScalarFieldFile)EG_strdup("ScalarFieldFile"); | |||
370 | defval->type = String; | |||
371 | defval->lfixed = Fixed; | |||
372 | defval->dim = Scalar; | |||
373 | defval->nullVal = IsNull; | |||
374 | ||||
375 | /*! \page aimInputsRefine | |||
376 | * - <B> ScalarFieldFile = NULL</B> <br> | |||
377 | * Scalar field file for constructing the multi-scale metric. <br> | |||
378 | * Only one of ScalarFieldFile, HessianFieldFile, or MetricFieldFile may be specified | |||
379 | */ | |||
380 | ||||
381 | } else if (index == inHessianFieldFile) { | |||
382 | *ainame = AIM_NAME(HessianFieldFile)EG_strdup("HessianFieldFile"); | |||
383 | defval->type = String; | |||
384 | defval->lfixed = Fixed; | |||
385 | defval->dim = Scalar; | |||
386 | defval->nullVal = IsNull; | |||
387 | ||||
388 | /*! \page aimInputsRefine | |||
389 | * - <B> HessianFieldFile = NULL</B> <br> | |||
390 | * Hessian field file for constructing the multi-scale metric. <br> | |||
391 | * Only one of ScalarFieldFile, HessianFieldFile, or MetricFieldFile may be specified | |||
392 | */ | |||
393 | ||||
394 | } else if (index == inMetricFieldFile) { | |||
395 | *ainame = AIM_NAME(MetricFieldFile)EG_strdup("MetricFieldFile"); | |||
396 | defval->type = String; | |||
397 | defval->lfixed = Fixed; | |||
398 | defval->dim = Scalar; | |||
399 | defval->nullVal = IsNull; | |||
400 | ||||
401 | /*! \page aimInputsRefine | |||
402 | * - <B> MetricFieldFile = NULL</B> <br> | |||
403 | * Metric field file. <br> | |||
404 | * Only one of ScalarFieldFile, HessianFieldFile, or MetricFieldFile may be specified | |||
405 | */ | |||
406 | ||||
407 | } else { | |||
408 | status = CAPS_BADINDEX-304; | |||
409 | AIM_STATUS(aimInfo, status, "Unknown input index %d!", index)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 409, __func__, 2, "Unknown input index %d!", index); goto cleanup ; }; | |||
410 | } | |||
411 | ||||
412 | AIM_NOTNULL(*ainame, aimInfo, status){ if (*ainame == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 412, __func__, 1, "%s == NULL!", "*ainame" ); goto cleanup; } }; | |||
413 | ||||
414 | cleanup: | |||
415 | return status; | |||
416 | } | |||
417 | ||||
418 | ||||
419 | // ********************** AIM Function Break ***************************** | |||
420 | /* aimUpdateState: The always the first call in the execution sequence */ | |||
421 | int | |||
422 | aimUpdateState(void *instStore, void *aimInfo, capsValue *inputs) | |||
423 | { | |||
424 | int nBody, status = CAPS_SUCCESS0; | |||
425 | const char *intents; | |||
426 | ego *bodies; | |||
427 | ||||
428 | char aimFile[PATH_MAX4096]; | |||
429 | ||||
430 | const char *groupName = NULL((void*)0); | |||
431 | aimStorage *refineInstance; | |||
432 | ||||
433 | int nFaces, iface, cID; | |||
434 | ego *faces=NULL((void*)0); | |||
435 | ||||
436 | refineInstance = (aimStorage *) instStore; | |||
437 | ||||
438 | if (inputs[inMesh-1].nullVal == IsNull && | |||
439 | aim_isFile(aimInfo, refine_out) != CAPS_SUCCESS0) { | |||
440 | AIM_ANALYSISIN_ERROR(aimInfo, inMesh, "'Mesh' input must be linked to generate the initial mesh!"){ aim_message(aimInfo, CERROR, inMesh, "refineAIM.c", 440, __func__ , "'Mesh' input must be linked to generate the initial mesh!" ); }; | |||
441 | status = CAPS_BADVALUE-311; | |||
442 | goto cleanup; | |||
443 | } | |||
444 | ||||
445 | if ( aim_isFile(aimInfo, refine_out) == CAPS_SUCCESS0 && | |||
446 | inputs[inScalarFieldFile-1 ].nullVal == IsNull && | |||
447 | inputs[inHessianFieldFile-1].nullVal == IsNull && | |||
448 | inputs[inMetricFieldFile-1 ].nullVal == IsNull ) { | |||
449 | AIM_ERROR(aimInfo, "One of ScalarFieldFile, HessianFieldFile, or MetricFieldFile must be specified"){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 449, __func__ , "One of ScalarFieldFile, HessianFieldFile, or MetricFieldFile must be specified" ); }; | |||
450 | status = CAPS_BADVALUE-311; | |||
451 | goto cleanup; | |||
452 | } | |||
453 | ||||
454 | if (( inputs[inScalarFieldFile-1 ].nullVal != IsNull && | |||
455 | (inputs[inHessianFieldFile-1].nullVal != IsNull || | |||
456 | inputs[inMetricFieldFile-1 ].nullVal != IsNull)) || | |||
457 | ( inputs[inHessianFieldFile-1].nullVal != IsNull && | |||
458 | (inputs[inScalarFieldFile-1 ].nullVal != IsNull || | |||
459 | inputs[inMetricFieldFile-1 ].nullVal != IsNull)) || | |||
460 | ( inputs[inMetricFieldFile-1 ].nullVal != IsNull && | |||
461 | (inputs[inHessianFieldFile-1].nullVal != IsNull || | |||
462 | inputs[inScalarFieldFile-1 ].nullVal != IsNull)) ) { | |||
463 | AIM_ERROR(aimInfo, "Only one of ScalarFieldFile, HessianFieldFile, or MetricFieldFile may be specified"){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 463, __func__ , "Only one of ScalarFieldFile, HessianFieldFile, or MetricFieldFile may be specified" ); }; | |||
464 | status = CAPS_BADVALUE-311; | |||
465 | goto cleanup; | |||
466 | } | |||
467 | ||||
468 | if (inputs[inMesh-1].nullVal == IsNull && | |||
469 | inputs[inComplexity-1].nullVal == IsNull && | |||
470 | inputs[inScalarFieldFile-1].nullVal != IsNull) { | |||
471 | AIM_ANALYSISIN_ERROR(aimInfo, inComplexity, "Complexity must be specified along with ScalarFieldFile"){ aim_message(aimInfo, CERROR, inComplexity, "refineAIM.c", 471 , __func__, "Complexity must be specified along with ScalarFieldFile" ); }; | |||
472 | status = CAPS_BADVALUE-311; | |||
473 | goto cleanup; | |||
474 | } | |||
475 | ||||
476 | if (inputs[inMesh-1].nullVal == IsNull && | |||
477 | inputs[inComplexity-1].nullVal == IsNull && | |||
478 | inputs[inHessianFieldFile-1].nullVal != IsNull) { | |||
479 | AIM_ANALYSISIN_ERROR(aimInfo, inComplexity, "Complexity must be specified along with HessianFieldFile"){ aim_message(aimInfo, CERROR, inComplexity, "refineAIM.c", 479 , __func__, "Complexity must be specified along with HessianFieldFile" ); }; | |||
480 | status = CAPS_BADVALUE-311; | |||
481 | goto cleanup; | |||
482 | } | |||
483 | ||||
484 | status = aim_getBodies(aimInfo, &intents, &nBody, &bodies); | |||
485 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 485, __func__, 0); goto cleanup; }; | |||
486 | if (nBody != 1) { | |||
487 | AIM_ERROR(aimInfo, "refine only supports a single body: numBody = %d", nBody){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 487, __func__ , "refine only supports a single body: numBody = %d", nBody); }; | |||
488 | status = CAPS_BADVALUE-311; | |||
489 | goto cleanup; | |||
490 | } | |||
491 | ||||
492 | if (inputs[inMesh-1].nullVal == NotNull) { | |||
493 | // Get mesh | |||
494 | refineInstance->meshRefIn = (aimMeshRef *) inputs[inMesh-1].vals.AIMptr; | |||
495 | ||||
496 | // Get attribute to index mapping | |||
497 | status = create_MeshRefToIndexMap(aimInfo, refineInstance->meshRefIn, &refineInstance->groupMap); | |||
498 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 498, __func__, 0); goto cleanup; }; | |||
499 | } else { | |||
500 | refineInstance->meshRefIn = NULL((void*)0); | |||
501 | } | |||
502 | ||||
503 | // clear the previous mesh | |||
504 | aim_freeMeshRef(&refineInstance->meshRefOut); | |||
505 | ||||
506 | status = aim_file(aimInfo, "refine_out", aimFile); | |||
507 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 507, __func__, 0); goto cleanup; }; | |||
508 | AIM_STRDUP(refineInstance->meshRefOut.fileName, aimFile, aimInfo, status){ if (refineInstance->meshRefOut.fileName != ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 508, __func__, 1, "AIM_STRDUP: %s != NULL!", "refineInstance->meshRefOut.fileName" ); goto cleanup; } refineInstance->meshRefOut.fileName = EG_strdup (aimFile); if (refineInstance->meshRefOut.fileName == ((void *)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c" , 508, __func__, 2, "AIM_STRDUP: %s %s", "refineInstance->meshRefOut.fileName" , aimFile); goto cleanup; } }; | |||
509 | ||||
510 | ||||
511 | status = EG_getBodyTopos(bodies[0], NULL((void*)0), FACE23, &nFaces, &faces); | |||
512 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 512, __func__, 0); goto cleanup; }; | |||
513 | ||||
514 | AIM_FREE(refineInstance->faceID){ EG_free(refineInstance->faceID); refineInstance->faceID = ((void*)0); }; | |||
515 | AIM_ALLOC(refineInstance->faceID, nFaces, int, aimInfo, status){ if (refineInstance->faceID != ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 515, __func__, 1, "AIM_ALLOC: %s != NULL", "refineInstance->faceID"); goto cleanup ; } size_t memorysize = nFaces; refineInstance->faceID = ( int *) EG_alloc(memorysize*sizeof(int)); if (refineInstance-> faceID == ((void*)0)) { status = -4; aim_status(aimInfo, status , "refineAIM.c", 515, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "refineInstance->faceID", memorysize, "int"); goto cleanup ; } }; | |||
516 | ||||
517 | for (iface = 0; iface < nFaces; iface++) { | |||
518 | ||||
519 | // Look for component/boundary ID for attribute mapper based on capsGroup | |||
520 | status = retrieve_CAPSGroupAttr(faces[iface], &groupName); | |||
521 | if (status != CAPS_SUCCESS0) { | |||
522 | AIM_ERROR(aimInfo, "No capsGroup attribute found on Face %d, unable to assign a boundary index value",{ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 523, __func__ , "No capsGroup attribute found on Face %d, unable to assign a boundary index value" , iface+1); } | |||
523 | iface+1){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 523, __func__ , "No capsGroup attribute found on Face %d, unable to assign a boundary index value" , iface+1); }; | |||
524 | print_AllAttr( aimInfo, faces[iface] ); | |||
525 | goto cleanup; | |||
526 | } | |||
527 | ||||
528 | /*@-nullpass@*/ | |||
529 | status = get_mapAttrToIndexIndex(&refineInstance->groupMap, groupName, &cID); | |||
530 | AIM_STATUS(aimInfo, status, "Unable to retrieve boundary index from capsGroup: %s",if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 531, __func__, 2, "Unable to retrieve boundary index from capsGroup: %s" , groupName); goto cleanup; } | |||
531 | groupName)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 531, __func__, 2, "Unable to retrieve boundary index from capsGroup: %s" , groupName); goto cleanup; }; | |||
532 | /*@+nullpass@*/ | |||
533 | ||||
534 | refineInstance->faceID[iface] = cID; | |||
535 | } | |||
536 | ||||
537 | cleanup: | |||
538 | AIM_FREE(faces){ EG_free(faces); faces = ((void*)0); }; | |||
539 | return status; | |||
540 | } | |||
541 | ||||
542 | ||||
543 | // ********************** AIM Function Break ***************************** | |||
544 | /* aimPreAnalysis: Parse Inputs, Generate Input File(s) */ | |||
545 | int | |||
546 | aimPreAnalysis(/*@unused@*/ const void *instStore, void *aimInfo, | |||
547 | capsValue *inputs) | |||
548 | { | |||
549 | int i, status = CAPS_SUCCESS0; | |||
550 | ||||
551 | int nBody=0; | |||
552 | const char *intents; | |||
553 | ego *bodies=NULL((void*)0); | |||
554 | ||||
555 | ego *bodyCopy=NULL((void*)0), context=NULL((void*)0), model=NULL((void*)0); | |||
556 | ||||
557 | // Output filename | |||
558 | char refine_in[PATH_MAX4096]; | |||
559 | char aimEgadsFile[PATH_MAX4096]; | |||
560 | char aimFile[PATH_MAX4096]; | |||
561 | char relPath[PATH_MAX4096]; | |||
562 | char command[PATH_MAX4096]; | |||
563 | FILE *fp = NULL((void*)0); | |||
564 | ||||
565 | const aimStorage *refineInstance; | |||
566 | ||||
567 | refineInstance = (const aimStorage *) instStore; | |||
568 | ||||
569 | if (refineInstance->meshRefIn != NULL((void*)0)) { | |||
570 | /* create a symbolic link to the file name*/ | |||
571 | snprintf(refine_in, PATH_MAX4096, "%s%s", refineInstance->meshRefIn->fileName, MESHEXTENSION".meshb"); | |||
572 | status = aim_symLink(aimInfo, refine_in, refine_out); | |||
573 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 573, __func__, 0); goto cleanup; }; | |||
574 | } else { | |||
575 | ||||
576 | if (aim_isFile(aimInfo, refine_out) != CAPS_SUCCESS0) { | |||
577 | AIM_ERROR(aimInfo, "'%s' does not exist!", refine_out){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 577, __func__ , "'%s' does not exist!", refine_out); }; | |||
578 | status = CAPS_IOERR-332; | |||
579 | goto cleanup; | |||
580 | } | |||
581 | ||||
582 | if (inputs[inScalarFieldFile-1].nullVal == NotNull) { | |||
583 | ||||
584 | if (access(inputs[inScalarFieldFile-1].vals.string, F_OK0) != 0) { | |||
585 | AIM_ERROR(aimInfo, "'%s' does not exist!", inputs[inScalarFieldFile-1].vals.string){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 585, __func__ , "'%s' does not exist!", inputs[inScalarFieldFile-1].vals.string ); }; | |||
586 | status = CAPS_IOERR-332; | |||
587 | goto cleanup; | |||
588 | } | |||
589 | ||||
590 | snprintf(refine_in, PATH_MAX4096, "refine_in%s", MESHEXTENSION".meshb"); | |||
591 | ||||
592 | // copy over refine_out to refine_in | |||
593 | status = aim_file(aimInfo, refine_out, aimFile); | |||
594 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 594, __func__, 0); goto cleanup; }; | |||
595 | status = aim_cpFile(aimInfo, aimFile, refine_in); | |||
596 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 596, __func__, 0); goto cleanup; }; | |||
597 | ||||
598 | // remove refine_out | |||
599 | status = aim_rmFile(aimInfo, refine_out); | |||
600 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 600, __func__, 0); goto cleanup; }; | |||
601 | ||||
602 | // compute multiscale metric field | |||
603 | snprintf(command, PATH_MAX4096, | |||
604 | "%s multiscale %s %s %le %s > multiscaleOut.txt", | |||
605 | inputs[inref-1].vals.string, | |||
606 | refine_in, | |||
607 | inputs[inScalarFieldFile-1].vals.string, | |||
608 | inputs[inComplexity-1].vals.real, | |||
609 | metricFileName ); | |||
610 | ||||
611 | status = aim_system(aimInfo, NULL((void*)0), command); | |||
612 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 612, __func__, 0); goto cleanup; }; | |||
613 | ||||
614 | } else if (inputs[inHessianFieldFile-1].nullVal == NotNull) { | |||
615 | ||||
616 | if (access(inputs[inHessianFieldFile-1].vals.string, F_OK0) != 0) { | |||
617 | AIM_ERROR(aimInfo, "'%s' does not exist!", inputs[inHessianFieldFile-1].vals.string){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 617, __func__ , "'%s' does not exist!", inputs[inHessianFieldFile-1].vals.string ); }; | |||
618 | status = CAPS_IOERR-332; | |||
619 | goto cleanup; | |||
620 | } | |||
621 | ||||
622 | snprintf(refine_in, PATH_MAX4096, "refine_in%s", MESHEXTENSION".meshb"); | |||
623 | ||||
624 | // copy over refine_out to refine_in | |||
625 | status = aim_file(aimInfo, refine_out, aimFile); | |||
626 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 626, __func__, 0); goto cleanup; }; | |||
627 | status = aim_cpFile(aimInfo, aimFile, refine_in); | |||
628 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 628, __func__, 0); goto cleanup; }; | |||
629 | ||||
630 | // remove refine_out | |||
631 | status = aim_rmFile(aimInfo, refine_out); | |||
632 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 632, __func__, 0); goto cleanup; }; | |||
633 | ||||
634 | // compute multiscale metric field | |||
635 | snprintf(command, PATH_MAX4096, | |||
636 | "%s multiscale %s %s %le %s --hessian > multiscaleOut.txt", | |||
637 | inputs[inref-1].vals.string, | |||
638 | refine_in, | |||
639 | inputs[inHessianFieldFile-1].vals.string, | |||
640 | inputs[inComplexity-1].vals.real, | |||
641 | metricFileName ); | |||
642 | ||||
643 | status = aim_system(aimInfo, NULL((void*)0), command); | |||
644 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 644, __func__, 0); goto cleanup; }; | |||
645 | ||||
646 | } else if (inputs[inMetricFieldFile-1].nullVal == NotNull) { | |||
647 | ||||
648 | if (access(inputs[inMetricFieldFile-1].vals.string, F_OK0) != 0) { | |||
649 | AIM_ERROR(aimInfo, "'%s' does not exist!", inputs[inMetricFieldFile-1].vals.string){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 649, __func__ , "'%s' does not exist!", inputs[inMetricFieldFile-1].vals.string ); }; | |||
650 | status = CAPS_IOERR-332; | |||
651 | goto cleanup; | |||
652 | } | |||
653 | ||||
654 | // get the relative path | |||
655 | aim_relPath(aimInfo, inputs[inMetricFieldFile-1].vals.string, metricFileName, relPath); | |||
656 | ||||
657 | if (strncmp(relPath, metricFileName, PATH_MAX4096) != 0) { | |||
658 | // Simply create a link to the file | |||
659 | status = aim_symLink(aimInfo, relPath, metricFileName); | |||
660 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 660, __func__, 0); goto cleanup; }; | |||
661 | } | |||
662 | ||||
663 | } else { | |||
664 | AIM_ERROR(aimInfo, "Developer error!"){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 664, __func__ , "Developer error!"); }; | |||
665 | status = CAPS_NOTIMPLEMENT-334; | |||
666 | goto cleanup; | |||
667 | } | |||
668 | } | |||
669 | ||||
670 | status = aim_getBodies(aimInfo, &intents, &nBody, &bodies); | |||
671 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 671, __func__, 0); goto cleanup; }; | |||
672 | ||||
673 | AIM_ALLOC(bodyCopy, nBody, ego, aimInfo, status){ if (bodyCopy != ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 673, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodyCopy"); goto cleanup; } size_t memorysize = nBody; bodyCopy = (ego *) EG_alloc(memorysize*sizeof(ego)); if (bodyCopy == ( (void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c" , 673, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "bodyCopy" , memorysize, "ego"); goto cleanup; } }; | |||
674 | for (i = 0; i < nBody; i++) bodyCopy[i] = NULL((void*)0); | |||
675 | ||||
676 | // Get context | |||
677 | status = EG_getContext(bodies[0], &context); | |||
678 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 678, __func__, 0); goto cleanup; }; | |||
679 | ||||
680 | // Make a copy of the bodies | |||
681 | for (i = 0; i < nBody; i++) { | |||
682 | status = EG_copyObject(bodies[i], NULL((void*)0), &bodyCopy[i]); | |||
683 | if (status != EGADS_SUCCESS0) goto cleanup; | |||
684 | } | |||
685 | ||||
686 | // Create a model from the copied bodies | |||
687 | status = EG_makeTopology(context, NULL((void*)0), MODEL26, 0, NULL((void*)0), nBody, bodyCopy, | |||
688 | NULL((void*)0), &model); | |||
689 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 689, __func__, 0); goto cleanup; }; | |||
690 | AIM_NOTNULL(model, aimInfo, status){ if (model == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 690, __func__, 1, "%s == NULL!", "model" ); goto cleanup; } }; | |||
691 | ||||
692 | status = aim_file(aimInfo, egadsFileName, aimEgadsFile); | |||
693 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 693, __func__, 0); goto cleanup; }; | |||
694 | ||||
695 | //printf("Writing egads file '%s'....\n", aimEgadsFile); | |||
696 | remove(aimEgadsFile); | |||
697 | status = EG_saveModel(model, aimEgadsFile); | |||
698 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 698, __func__, 0); goto cleanup; }; | |||
699 | ||||
700 | fp = aim_fopen(aimInfo, refInput, "w"); | |||
701 | if (fp == NULL((void*)0)) { | |||
702 | AIM_ERROR(aimInfo, "Cannot open %s", refInput){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 702, __func__ , "Cannot open %s", refInput); }; | |||
703 | status = CAPS_IOERR-332; | |||
704 | goto cleanup; | |||
705 | } | |||
706 | ||||
707 | fprintf(fp, | |||
708 | " adapt refine_in.meshb --metric %s --egads %s -s %d -x refine_out.meshb", | |||
709 | metricFileName, | |||
710 | egadsFileName, | |||
711 | inputs[inPasses-1].vals.integer); | |||
712 | ||||
713 | cleanup: | |||
714 | ||||
715 | if (model != NULL((void*)0)) { | |||
716 | EG_deleteObject(model); | |||
717 | } else { | |||
718 | if (bodyCopy != NULL((void*)0)) { | |||
719 | for (i = 0; i < nBody; i++) { | |||
720 | if (bodyCopy[i] != NULL((void*)0)) { | |||
721 | (void) EG_deleteObject(bodyCopy[i]); | |||
722 | } | |||
723 | } | |||
724 | } | |||
725 | } | |||
726 | AIM_FREE(bodyCopy){ EG_free(bodyCopy); bodyCopy = ((void*)0); }; | |||
727 | if (fp != NULL((void*)0)) fclose(fp); | |||
728 | ||||
729 | return status; | |||
730 | } | |||
731 | ||||
732 | ||||
733 | // ********************** AIM Function Break ***************************** | |||
734 | /* aimExecute: runs the Analysis & specifies the AIM does the execution */ | |||
735 | int | |||
736 | aimExecute(/*@unused@*/ const void *instStor, /*@unused@*/ void *aimInfo, | |||
737 | int *state) | |||
738 | { | |||
739 | /*! \page aimExecuteRefine AIM Execution | |||
740 | * | |||
741 | * If auto execution is enabled when creating an refine AIM, | |||
742 | * the AIM will execute refine just-in-time with the command line: | |||
743 | * | |||
744 | * \code{.sh} | |||
745 | * ref $(< refInput.txt) > refOutput.txt | |||
746 | * \endcode | |||
747 | * | |||
748 | * where preAnalysis generated the file "refInput.txt" which contains commandline arguments for ref. | |||
749 | * | |||
750 | * The refine analysis directory is assumed to contain a metric.meshb file. This file will | |||
751 | * be generated automatically with preAnalysis using ScalarFieldFile or HessianFieldFile inputs, or | |||
752 | * can be generated manually via system calls to refine and setting MetricFieldFile. | |||
753 | * | |||
754 | * The analysis can be also be explicitly executed with caps_execute in the C-API | |||
755 | * or via Analysis.runAnalysis in the pyCAPS API. | |||
756 | * | |||
757 | * Calling preAnalysis and postAnalysis is NOT allowed when auto execution is enabled. | |||
758 | * | |||
759 | * Auto execution can also be disabled when creating an refine AIM object. | |||
760 | * In this mode, caps_execute and Analysis.runAnalysis can be used to run the analysis, | |||
761 | * or refine can be executed by calling preAnalysis, system call, and posAnalysis as demonstrated | |||
762 | * below with a pyCAPS example: | |||
763 | * | |||
764 | * \code{.py} | |||
765 | * print ("\n\preAnalysis......") | |||
766 | * refine.preAnalysis() | |||
767 | * | |||
768 | * print ("\n\nRunning......") | |||
769 | * refine.system("ref $(< refInput.txt) > refOutput.txt"); # Run via system call | |||
770 | * | |||
771 | * print ("\n\postAnalysis......") | |||
772 | * refine.postAnalysis() | |||
773 | * \endcode | |||
774 | */ | |||
775 | ||||
776 | int status = CAPS_SUCCESS0; | |||
777 | char command[PATH_MAX4096]; | |||
778 | capsValue *ref; | |||
779 | ||||
780 | *state = 0; | |||
781 | ||||
782 | if (aim_isFile(aimInfo, metricFileName) != CAPS_SUCCESS0) | |||
783 | return CAPS_SUCCESS0; | |||
784 | ||||
785 | status = aim_getValue(aimInfo, inref, ANALYSISIN, &ref); | |||
786 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 786, __func__, 0); goto cleanup; }; | |||
787 | ||||
788 | // execute refine adapt in serial | |||
789 | snprintf(command, PATH_MAX4096, | |||
790 | "%s $(< %s) > refOutput.txt", | |||
791 | ref->vals.string, refInput); | |||
792 | ||||
793 | status = aim_system(aimInfo, NULL((void*)0), command); | |||
794 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 794, __func__, 0); goto cleanup; }; | |||
795 | ||||
796 | cleanup: | |||
797 | return status; | |||
798 | } | |||
799 | ||||
800 | ||||
801 | // ********************** AIM Function Break ***************************** | |||
802 | /* aimPostAnalysis: Perform any processing after the Analysis is run */ | |||
803 | int | |||
804 | aimPostAnalysis(void *instStore, void *aimInfo, | |||
805 | /*@unused@*/ int restart, /*@unused@*/ capsValue *inputs) | |||
806 | { | |||
807 | int status = CAPS_SUCCESS0; | |||
808 | aimMesh mesh; | |||
809 | aimStorage *refineInstance; | |||
810 | ||||
811 | refineInstance = (aimStorage *) instStore; | |||
812 | ||||
813 | /*@-immediatetrans@*/ | |||
814 | mesh.meshData = NULL((void*)0); | |||
815 | mesh.meshRef = &refineInstance->meshRefOut; | |||
816 | /*@+immediatetrans@*/ | |||
817 | ||||
818 | //Only read the surface tessellation | |||
819 | status = readlibMeshb(aimInfo, refineInstance, &mesh); | |||
820 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 820, __func__, 0); goto cleanup; }; | |||
821 | ||||
822 | status = aim_freeMeshData(mesh.meshData); | |||
823 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 823, __func__, 0); goto cleanup; }; | |||
824 | AIM_FREE(mesh.meshData){ EG_free(mesh.meshData); mesh.meshData = ((void*)0); }; | |||
825 | ||||
826 | cleanup: | |||
827 | return status; | |||
828 | } | |||
829 | ||||
830 | ||||
831 | // ********************** AIM Function Break ***************************** | |||
832 | /* aimOutputs: Output Information for the AIM */ | |||
833 | int | |||
834 | aimOutputs(/*@unused@*/ void *instStore, /*@unused@*/ void *aimInfo, | |||
835 | /*@unused@*/ int index, char **aoname, capsValue *form) | |||
836 | { | |||
837 | int status = CAPS_SUCCESS0; | |||
838 | #ifdef DEBUG | |||
839 | printf(" skeletonAIM/aimOutputs instance = %d index = %d!\n", | |||
840 | aim_getInstance(aimInfo), index); | |||
841 | #endif | |||
842 | ||||
843 | /*! \page aimOutputsRefine AIM Outputs | |||
844 | * List of available outputs from the refine AIM | |||
845 | */ | |||
846 | ||||
847 | if (index == outMesh) { | |||
848 | ||||
849 | *aoname = AIM_NAME(Mesh)EG_strdup("Mesh"); | |||
850 | form->type = PointerMesh; | |||
851 | form->dim = Scalar; | |||
852 | form->lfixed = Fixed; | |||
853 | form->sfixed = Fixed; | |||
854 | form->vals.AIMptr = NULL((void*)0); | |||
855 | form->nullVal = IsNull; | |||
856 | ||||
857 | /*! \page aimOutputsRefine | |||
858 | * - <B> Mesh </B> <br> | |||
859 | * The output Area_Mesh or Volume_Mesh for a link | |||
860 | */ | |||
861 | ||||
862 | } else if (index == outxyz) { | |||
863 | ||||
864 | *aoname = AIM_NAME(xyz)EG_strdup("xyz"); | |||
865 | form->type = Double; | |||
866 | form->dim = Array2D; | |||
867 | ||||
868 | /*! \page aimOutputsRefine | |||
869 | * - <B> xyz </B> <br> | |||
870 | * Grid coordinates. Useful for constructing scalar, hessian, or metric fields | |||
871 | */ | |||
872 | ||||
873 | } else { | |||
874 | status = CAPS_BADINDEX-304; | |||
875 | AIM_STATUS(aimInfo, status, "Unknown output index %d!", index)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 875, __func__, 2, "Unknown output index %d!", index); goto cleanup ; }; | |||
876 | } | |||
877 | ||||
878 | AIM_NOTNULL(*aoname, aimInfo, status){ if (*aoname == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 878, __func__, 1, "%s == NULL!", "*aoname" ); goto cleanup; } }; | |||
879 | ||||
880 | cleanup: | |||
881 | return status; | |||
882 | } | |||
883 | ||||
884 | ||||
885 | // ********************** AIM Function Break ***************************** | |||
886 | /* aimCalcOutput: Calculate/Retrieve Output Information */ | |||
887 | int | |||
888 | aimCalcOutput(void *instStore, void *aimInfo, | |||
889 | int index, capsValue *val) | |||
890 | { | |||
891 | int i, j, status = CAPS_SUCCESS0; | |||
892 | aimStorage *refineInstance; | |||
893 | aimMesh mesh; | |||
894 | ||||
895 | refineInstance = (aimStorage *) instStore; | |||
896 | ||||
897 | ||||
898 | if (outMesh == index) { | |||
899 | ||||
900 | status = aim_queryMeshes( aimInfo, outMesh, &refineInstance->meshRefOut ); | |||
901 | if (status > 0) { | |||
902 | /*@-immediatetrans@*/ | |||
903 | mesh.meshData = NULL((void*)0); | |||
904 | mesh.meshRef = &refineInstance->meshRefOut; | |||
905 | /*@+immediatetrans@*/ | |||
906 | ||||
907 | status = readlibMeshb(aimInfo, refineInstance, &mesh); | |||
908 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 908, __func__, 0); goto cleanup; }; | |||
909 | ||||
910 | status = aim_writeMeshes(aimInfo, outMesh, &mesh); | |||
911 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 911, __func__, 0); goto cleanup; }; | |||
912 | ||||
913 | status = aim_freeMeshData(mesh.meshData); | |||
914 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 914, __func__, 0); goto cleanup; }; | |||
915 | AIM_FREE(mesh.meshData){ EG_free(mesh.meshData); mesh.meshData = ((void*)0); }; | |||
916 | } | |||
917 | else | |||
918 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 918, __func__, 0); goto cleanup; }; | |||
919 | ||||
920 | /*@-immediatetrans@*/ | |||
921 | // Return the volume mesh references | |||
922 | val->nrow = 1; | |||
923 | val->vals.AIMptr = &refineInstance->meshRefOut; | |||
924 | /*@+immediatetrans@*/ | |||
925 | ||||
926 | } else if (index == outxyz) { | |||
927 | ||||
928 | /*@-immediatetrans@*/ | |||
929 | mesh.meshData = NULL((void*)0); | |||
930 | mesh.meshRef = &refineInstance->meshRefOut; | |||
931 | /*@+immediatetrans@*/ | |||
932 | ||||
933 | status = readlibMeshb(aimInfo, refineInstance, &mesh); | |||
934 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 934, __func__, 0); goto cleanup; }; | |||
935 | ||||
936 | AIM_ALLOC(val->vals.reals, mesh.meshData->dim*mesh.meshData->nVertex, double, aimInfo, status){ if (val->vals.reals != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 936, __func__, 1, "AIM_ALLOC: %s != NULL" , "val->vals.reals"); goto cleanup; } size_t memorysize = mesh .meshData->dim*mesh.meshData->nVertex; val->vals.reals = (double *) EG_alloc(memorysize*sizeof(double)); if (val-> vals.reals == ((void*)0)) { status = -4; aim_status(aimInfo, status , "refineAIM.c", 936, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "val->vals.reals", memorysize, "double"); goto cleanup; } }; | |||
937 | val->nrow = mesh.meshData->nVertex; | |||
938 | val->ncol = mesh.meshData->dim; | |||
939 | ||||
940 | for (i = 0; i < mesh.meshData->nVertex; i++) { | |||
941 | for (j = 0; j < mesh.meshData->dim; j++) { | |||
942 | val->vals.reals[mesh.meshData->dim*i+j] = mesh.meshData->verts[i][j]; | |||
943 | } | |||
944 | } | |||
945 | ||||
946 | status = aim_freeMeshData(mesh.meshData); | |||
947 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 947, __func__, 0); goto cleanup; }; | |||
948 | AIM_FREE(mesh.meshData){ EG_free(mesh.meshData); mesh.meshData = ((void*)0); }; | |||
949 | ||||
950 | } else { | |||
951 | ||||
952 | status = CAPS_BADINDEX-304; | |||
953 | AIM_STATUS(aimInfo, status, "Unknown output index %d!", index)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 953, __func__, 2, "Unknown output index %d!", index); goto cleanup ; }; | |||
954 | ||||
955 | } | |||
956 | ||||
957 | cleanup: | |||
958 | return status; | |||
959 | } | |||
960 | ||||
961 | ||||
962 | // ********************** AIM Function Break ***************************** | |||
963 | /* aimCleanup: Free up the AIMs storage */ | |||
964 | void aimCleanup(/*@unused@*/ void *instStore) | |||
965 | { | |||
966 | aimStorage *refineInstance = NULL((void*)0); | |||
967 | ||||
968 | /* clean up any allocated data */ | |||
969 | ||||
970 | refineInstance = (aimStorage *) instStore; | |||
971 | if (refineInstance == NULL((void*)0)) return; | |||
972 | ||||
973 | destroy_aimStorage(refineInstance); | |||
974 | AIM_FREE(refineInstance){ EG_free(refineInstance); refineInstance = ((void*)0); }; | |||
975 | } | |||
976 | ||||
977 | ||||
978 | // ********************** AIM Function Break ***************************** | |||
979 | static void swapd(double *xp, double *yp) | |||
980 | { | |||
981 | double temp = *xp; | |||
982 | *xp = *yp; | |||
983 | *yp = temp; | |||
984 | } | |||
985 | ||||
986 | static void swapi(int *xp, int *yp) | |||
987 | { | |||
988 | int temp = *xp; | |||
989 | *xp = *yp; | |||
990 | *yp = temp; | |||
991 | } | |||
992 | ||||
993 | ||||
994 | // ********************** AIM Function Break ***************************** | |||
995 | // A function to implement bubble sort | |||
996 | static void | |||
997 | bubbleSortEdge(edgeData *tedge) | |||
998 | { | |||
999 | ||||
1000 | int i, j; | |||
1001 | for (i = 0; i < tedge->npts-1; i++) | |||
1002 | // Last i elements are already in place | |||
1003 | for (j = 0; j < tedge->npts-i-1; j++) | |||
1004 | if (tedge->t[j] > tedge->t[j+1]) { | |||
1005 | swapd(&tedge->t[j] , &tedge->t[j+1] ); | |||
1006 | swapd(&tedge->xyz[3*j+0], &tedge->xyz[3*(j+1)+0]); | |||
1007 | swapd(&tedge->xyz[3*j+1], &tedge->xyz[3*(j+1)+1]); | |||
1008 | swapd(&tedge->xyz[3*j+2], &tedge->xyz[3*(j+1)+2]); | |||
1009 | swapi(&tedge->ivp[j] , &tedge->ivp[j+1] ); | |||
1010 | } | |||
1011 | } | |||
1012 | ||||
1013 | ||||
1014 | static void | |||
1015 | bubbleSortFace(faceData *tface) | |||
1016 | { | |||
1017 | ||||
1018 | int i, j; | |||
1019 | for (i = 0; i < tface->npts-1; i++) | |||
1020 | // Last i elements are already in place | |||
1021 | for (j = 0; j < tface->npts-i-1; j++) | |||
1022 | if (tface->ivp[j] > tface->ivp[j+1]) { | |||
1023 | swapd(&tface->uv[2*j+0] , &tface->uv[2*(j+1)+0] ); | |||
1024 | swapd(&tface->uv[2*j+1] , &tface->uv[2*(j+1)+1] ); | |||
1025 | swapd(&tface->xyz[3*j+0], &tface->xyz[3*(j+1)+0]); | |||
1026 | swapd(&tface->xyz[3*j+1], &tface->xyz[3*(j+1)+1]); | |||
1027 | swapd(&tface->xyz[3*j+2], &tface->xyz[3*(j+1)+2]); | |||
1028 | swapi(&tface->ivp[j] , &tface->ivp[j+1] ); | |||
1029 | } | |||
1030 | } | |||
1031 | ||||
1032 | ||||
1033 | static int | |||
1034 | faceIndex(const int ivp, faceData *tface) | |||
1035 | { | |||
1036 | int i0 = 0; | |||
1037 | int i1 = tface->npts/2; | |||
1038 | int i2 = tface->npts; | |||
1039 | ||||
1040 | while(tface->ivp[i1] != ivp) { | |||
1041 | if (ivp > tface->ivp[i1]) { | |||
1042 | i0 = i1; | |||
1043 | i1 = (i1 + i2)/2; | |||
1044 | } else { | |||
1045 | i2 = i1; | |||
1046 | i1 = (i0 + i1)/2; | |||
1047 | } | |||
1048 | } | |||
1049 | ||||
1050 | return i1+1; | |||
1051 | } | |||
1052 | ||||
1053 | // ********************** AIM Function Break ***************************** | |||
1054 | static int | |||
1055 | readlibMeshb(void *aimInfo, aimStorage *refineInstance, aimMesh *mesh) | |||
1056 | { | |||
1057 | int status = CAPS_SUCCESS0; | |||
1058 | ||||
1059 | char attrname[128]; | |||
1060 | int nBody=0, nLine=0, nTri=0, nTet=0; | |||
1061 | int i, j, elementIndex, nPoint, igroup, iglobal, nglobal; | |||
| ||||
1062 | int elem[4], ivp, id, npts, ntri, iedge, iface; | |||
1063 | int meshVersion, nEdgeVerts, nFaceVerts, *faceGroups=NULL((void*)0), *edgeGroups=NULL((void*)0), tetGroup; | |||
1064 | int oclass, mtype, *faceVertID=NULL((void*)0), *face_tris; | |||
1065 | double reference, t, uv[2], double_gref; | |||
1066 | double result[18]; | |||
1067 | double *face_uv = NULL((void*)0), *face_xyz = NULL((void*)0); | |||
1068 | double v1[3], v2[3], faceNormal[3], triNormal[3], ndot; | |||
1069 | const int *tris = NULL((void*)0), *tric = NULL((void*)0), *ptype = NULL((void*)0), *pindex = NULL((void*)0); | |||
1070 | const double *pxyz = NULL((void*)0), *puv = NULL((void*)0); | |||
1071 | enum aimMeshElem elementTopo; | |||
1072 | char filename[PATH_MAX4096]; | |||
1073 | int64_t fileID=0; | |||
1074 | aimMeshData *meshData = NULL((void*)0); | |||
1075 | bodyData bodydata; | |||
1076 | const char *intents; | |||
1077 | ego *bodies, body, tess, ref, prev, next; | |||
1078 | ||||
1079 | if (mesh == NULL((void*)0)) return CAPS_NULLOBJ-309; | |||
1080 | if (mesh->meshRef == NULL((void*)0)) return CAPS_NULLOBJ-309; | |||
1081 | if (mesh->meshRef->fileName == NULL((void*)0)) return CAPS_NULLOBJ-309; | |||
1082 | ||||
1083 | status = initiate_bodyData(1, &bodydata); | |||
1084 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1084, __func__, 0); goto cleanup; }; | |||
1085 | ||||
1086 | status = aim_getBodies(aimInfo, &intents, &nBody, &bodies); | |||
1087 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1087, __func__, 0); goto cleanup; }; | |||
1088 | ||||
1089 | body = bodies[0]; | |||
1090 | ||||
1091 | status = EG_getBodyTopos(body, NULL((void*)0), NODE20, &bodydata.nnodes, NULL((void*)0)); | |||
1092 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1092, __func__, 0); goto cleanup; }; | |||
1093 | ||||
1094 | status = EG_getBodyTopos(body, NULL((void*)0), EDGE21, &bodydata.nedges, &bodydata.edges); | |||
1095 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1095, __func__, 0); goto cleanup; }; | |||
1096 | ||||
1097 | status = EG_getBodyTopos(body, NULL((void*)0), FACE23, &bodydata.nfaces, &bodydata.faces); | |||
1098 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1098, __func__, 0); goto cleanup; }; | |||
1099 | ||||
1100 | status = aim_freeMeshData(mesh->meshData); | |||
1101 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1101, __func__, 0); goto cleanup; }; | |||
1102 | AIM_FREE(mesh->meshData){ EG_free(mesh->meshData); mesh->meshData = ((void*)0); }; | |||
1103 | ||||
1104 | AIM_ALLOC(meshData, 1, aimMeshData, aimInfo, status){ if (meshData != ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 1104, __func__, 1, "AIM_ALLOC: %s != NULL" , "meshData"); goto cleanup; } size_t memorysize = 1; meshData = (aimMeshData *) EG_alloc(memorysize*sizeof(aimMeshData)); if (meshData == ((void*)0)) { status = -4; aim_status(aimInfo, status , "refineAIM.c", 1104, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "meshData", memorysize, "aimMeshData"); goto cleanup; } }; | |||
1105 | status = aim_initMeshData(meshData); | |||
1106 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1106, __func__, 0); goto cleanup; }; | |||
1107 | ||||
1108 | snprintf(filename, PATH_MAX4096, "%s%s", mesh->meshRef->fileName, MESHEXTENSION".meshb"); | |||
1109 | ||||
1110 | fileID = GmfOpenMesh(filename, GmfRead1, &meshVersion, &meshData->dim); | |||
1111 | ||||
1112 | if (fileID == 0) { | |||
1113 | AIM_ERROR(aimInfo, "Cannot open file: %s\n", filename){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 1113, __func__ , "Cannot open file: %s\n", filename); }; | |||
1114 | status = CAPS_IOERR-332; | |||
1115 | goto cleanup; | |||
1116 | } | |||
1117 | ||||
1118 | AIM_ALLOC(edgeGroups, bodydata.nedges, int, aimInfo, status){ if (edgeGroups != ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 1118, __func__, 1, "AIM_ALLOC: %s != NULL" , "edgeGroups"); goto cleanup; } size_t memorysize = bodydata .nedges; edgeGroups = (int *) EG_alloc(memorysize*sizeof(int) ); if (edgeGroups == ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 1118, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "edgeGroups", memorysize, "int"); goto cleanup; } }; | |||
1119 | AIM_ALLOC(faceGroups, bodydata.nfaces, int, aimInfo, status){ if (faceGroups != ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 1119, __func__, 1, "AIM_ALLOC: %s != NULL" , "faceGroups"); goto cleanup; } size_t memorysize = bodydata .nfaces; faceGroups = (int *) EG_alloc(memorysize*sizeof(int) ); if (faceGroups == ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 1119, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "faceGroups", memorysize, "int"); goto cleanup; } }; | |||
1120 | for (i = 0; i < bodydata.nedges; i++) edgeGroups[i] = -1; | |||
1121 | for (i = 0; i < bodydata.nfaces; i++) faceGroups[i] = -1; | |||
1122 | tetGroup = -1; | |||
1123 | ||||
1124 | meshData->nVertex = GmfStatKwd(fileID, GmfVertices); | |||
1125 | AIM_ALLOC(meshData->verts, meshData->nVertex, aimMeshCoords, aimInfo, status){ if (meshData->verts != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1125, __func__, 1, "AIM_ALLOC: %s != NULL" , "meshData->verts"); goto cleanup; } size_t memorysize = meshData ->nVertex; meshData->verts = (aimMeshCoords *) EG_alloc (memorysize*sizeof(aimMeshCoords)); if (meshData->verts == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c" , 1125, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "meshData->verts" , memorysize, "aimMeshCoords"); goto cleanup; } }; | |||
1126 | ||||
1127 | status = GmfGotoKwd(fileID, GmfVertices); | |||
1128 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1128, __func__, 0); goto cleanup; }; } | |||
1129 | ||||
1130 | // Real nodal coordinates | |||
1131 | if (meshData->dim == 2) { | |||
1132 | for (i = 0; i < meshData->nVertex; i++) { | |||
1133 | status = GmfGetLin(fileID, GmfVertices, &meshData->verts[i][0], | |||
1134 | &meshData->verts[i][1], &reference); | |||
1135 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1135, __func__, 0); goto cleanup; }; } | |||
1136 | } | |||
1137 | ||||
1138 | // read elements | |||
1139 | ||||
1140 | nLine = GmfStatKwd(fileID, GmfEdges); | |||
1141 | nTri = GmfStatKwd(fileID, GmfTriangles); | |||
1142 | ||||
1143 | meshData->nTotalElems = nLine + nTri; | |||
1144 | ||||
1145 | } else { | |||
1146 | for (i = 0; i < meshData->nVertex; i++) { | |||
1147 | status = GmfGetLin(fileID, GmfVertices, &meshData->verts[i][0], | |||
1148 | &meshData->verts[i][1], | |||
1149 | &meshData->verts[i][2], &reference); | |||
1150 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1150, __func__, 0); goto cleanup; }; } | |||
1151 | } | |||
1152 | ||||
1153 | // read elements | |||
1154 | ||||
1155 | nTri = GmfStatKwd(fileID, GmfTriangles); | |||
1156 | nTet = GmfStatKwd(fileID, GmfTetrahedra); | |||
1157 | ||||
1158 | meshData->nTotalElems = nTri + nTet; | |||
1159 | ||||
1160 | } | |||
1161 | ||||
1162 | ||||
1163 | // allocate the element map that maps back to the original element numbering | |||
1164 | AIM_ALLOC(meshData->elemMap, meshData->nTotalElems, aimMeshIndices, aimInfo, status){ if (meshData->elemMap != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1164, __func__, 1, "AIM_ALLOC: %s != NULL" , "meshData->elemMap"); goto cleanup; } size_t memorysize = meshData->nTotalElems; meshData->elemMap = (aimMeshIndices *) EG_alloc(memorysize*sizeof(aimMeshIndices)); if (meshData ->elemMap == ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 1164, __func__, 3, "AIM_ALLOC: %s size %zu type %s" , "meshData->elemMap", memorysize, "aimMeshIndices"); goto cleanup; } }; | |||
1165 | ||||
1166 | /* Start of element index */ | |||
1167 | elementIndex = 0; | |||
1168 | ||||
1169 | if (meshData->dim
| |||
1170 | ||||
1171 | // Elements Line | |||
1172 | status = GmfGotoKwd(fileID, GmfEdges); | |||
1173 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1173, __func__, 0); goto cleanup; }; } | |||
1174 | ||||
1175 | nPoint = 2; | |||
1176 | elementTopo = aimLine; | |||
1177 | for (i = 0; i < nLine; i++) { | |||
1178 | ||||
1179 | /* read the element and group */ | |||
1180 | status = GmfGetLin(fileID, GmfEdges, &elem[0], | |||
1181 | &elem[1], &igroup); | |||
1182 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1182, __func__, 0); goto cleanup; }; } | |||
1183 | ||||
1184 | if (igroup <= 0) { | |||
1185 | AIM_ERROR(aimInfo, "Group must be a positive number: %d!", igroup){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 1185, __func__ , "Group must be a positive number: %d!", igroup); }; | |||
1186 | status = CAPS_IOERR-332; | |||
1187 | goto cleanup; | |||
1188 | } | |||
1189 | igroup -= 1; // make zero based | |||
1190 | ||||
1191 | /* add the group if necessary */ | |||
1192 | if (edgeGroups[igroup] == -1) { | |||
1193 | status = aim_addMeshElemGroup(aimInfo, NULL((void*)0), igroup, elementTopo, 1, nPoint, meshData); | |||
1194 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1194, __func__, 0); goto cleanup; }; | |||
1195 | edgeGroups[igroup] = meshData->nElemGroup-1; | |||
1196 | } | |||
1197 | igroup = edgeGroups[igroup]; | |||
1198 | ||||
1199 | /* add the element to the group */ | |||
1200 | status = aim_addMeshElem(aimInfo, 1, &meshData->elemGroups[igroup]); | |||
1201 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1201, __func__, 0); goto cleanup; }; | |||
1202 | ||||
1203 | /* set the element connectivity */ | |||
1204 | for (j = 0; j < nPoint; j++) | |||
1205 | meshData->elemGroups[igroup].elements[nPoint*(meshData->elemGroups[igroup].nElems-1) + j] = elem[j]; | |||
1206 | ||||
1207 | meshData->elemMap[elementIndex][0] = igroup; | |||
1208 | meshData->elemMap[elementIndex][1] = meshData->elemGroups[igroup].nElems-1; | |||
1209 | ||||
1210 | elementIndex += 1; | |||
1211 | } | |||
1212 | } | |||
1213 | ||||
1214 | AIM_ALLOC(bodydata.tfaces, bodydata.nfaces, faceData, aimInfo, status){ if (bodydata.tfaces != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1214, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tfaces"); goto cleanup; } size_t memorysize = bodydata .nfaces; bodydata.tfaces = (faceData *) EG_alloc(memorysize*sizeof (faceData)); if (bodydata.tfaces == ((void*)0)) { status = -4 ; aim_status(aimInfo, status, "refineAIM.c", 1214, __func__, 3 , "AIM_ALLOC: %s size %zu type %s", "bodydata.tfaces", memorysize , "faceData"); goto cleanup; } }; | |||
1215 | for (j = 0; j
| |||
1216 | bodydata.tfaces[j].npts = 0; | |||
1217 | bodydata.tfaces[j].xyz = NULL((void*)0); | |||
1218 | bodydata.tfaces[j].uv = NULL((void*)0); | |||
1219 | bodydata.tfaces[j].ntri = 0; | |||
1220 | bodydata.tfaces[j].tris = NULL((void*)0); | |||
1221 | bodydata.tfaces[j].ivp = NULL((void*)0); | |||
1222 | } | |||
1223 | ||||
1224 | /* Elements triangles */ | |||
1225 | status = GmfGotoKwd(fileID, GmfTriangles); | |||
1226 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1226, __func__, 0); goto cleanup; }; } | |||
1227 | ||||
1228 | nPoint = 3; | |||
1229 | elementTopo = aimTri; | |||
1230 | for (i = 0; i < nTri; i++) { | |||
1231 | ||||
1232 | /* read the element and group */ | |||
1233 | status = GmfGetLin(fileID, GmfTriangles, &elem[0], | |||
1234 | &elem[1], | |||
1235 | &elem[2], &igroup); | |||
1236 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1236, __func__, 0); goto cleanup; }; } | |||
1237 | ||||
1238 | if (igroup <= 0) { | |||
1239 | AIM_ERROR(aimInfo, "Group must be a positive number: %d!", igroup){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 1239, __func__ , "Group must be a positive number: %d!", igroup); }; | |||
1240 | status = CAPS_IOERR-332; | |||
1241 | goto cleanup; | |||
1242 | } | |||
1243 | igroup -= 1; // make zero based | |||
1244 | ||||
1245 | ntri = bodydata.tfaces[igroup].ntri; | |||
1246 | AIM_REALL(bodydata.tfaces[igroup].tris, 3*(ntri+1), int, aimInfo, status){ size_t memorysize = 3*(ntri+1); bodydata.tfaces[igroup].tris = (int *) EG_reall(bodydata.tfaces[igroup].tris, memorysize* sizeof(int)); if (bodydata.tfaces[igroup].tris == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1246 , __func__, 3, "AIM_REALL: %s size %zu type %s", "bodydata.tfaces[igroup].tris" , memorysize, "int"); goto cleanup; } }; | |||
1247 | bodydata.tfaces[igroup].tris[3*ntri+0] = elem[0]; | |||
1248 | bodydata.tfaces[igroup].tris[3*ntri+1] = elem[1]; | |||
1249 | bodydata.tfaces[igroup].tris[3*ntri+2] = elem[2]; | |||
1250 | bodydata.tfaces[igroup].ntri++; | |||
1251 | ||||
1252 | igroup = refineInstance->faceID[igroup]-1; | |||
1253 | ||||
1254 | /* add the group if necessary */ | |||
1255 | if (faceGroups[igroup] == -1) { | |||
1256 | status = aim_addMeshElemGroup(aimInfo, NULL((void*)0), igroup+1, elementTopo, 1, nPoint, meshData); | |||
1257 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1257, __func__, 0); goto cleanup; }; | |||
1258 | faceGroups[igroup] = meshData->nElemGroup-1; | |||
1259 | } | |||
1260 | igroup = faceGroups[igroup]; | |||
1261 | ||||
1262 | /* add the element to the group */ | |||
1263 | status = aim_addMeshElem(aimInfo, 1, &meshData->elemGroups[igroup]); | |||
1264 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1264, __func__, 0); goto cleanup; }; | |||
1265 | ||||
1266 | /* set the element connectivity */ | |||
1267 | for (j = 0; j < nPoint; j++) | |||
1268 | meshData->elemGroups[igroup].elements[nPoint*(meshData->elemGroups[igroup].nElems-1) + j] = elem[j]; | |||
1269 | ||||
1270 | meshData->elemMap[elementIndex][0] = igroup; | |||
1271 | meshData->elemMap[elementIndex][1] = meshData->elemGroups[igroup].nElems-1; | |||
1272 | ||||
1273 | elementIndex += 1; | |||
1274 | } | |||
1275 | ||||
1276 | // If the surface mesh has been processed, read Tets | |||
1277 | if (mesh->meshRef->maps != NULL((void*)0)) { | |||
1278 | ||||
1279 | if (mesh->meshRef->type == aimVolumeMesh) { | |||
1280 | // Elements Tetrahedral | |||
1281 | status = GmfGotoKwd(fileID, GmfTetrahedra); | |||
1282 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1282, __func__, 0); goto cleanup; }; } | |||
1283 | ||||
1284 | nPoint = 4; | |||
1285 | elementTopo = aimTet; | |||
1286 | ||||
1287 | /* add the group tetGroup */ | |||
1288 | if (tetGroup == -1) { | |||
1289 | status = aim_addMeshElemGroup(aimInfo, NULL((void*)0), igroup, elementTopo, 1, nPoint, meshData); | |||
| ||||
1290 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1290, __func__, 0); goto cleanup; }; | |||
1291 | tetGroup = meshData->nElemGroup-1; | |||
1292 | } | |||
1293 | igroup = tetGroup; | |||
1294 | ||||
1295 | /* add the element to the group */ | |||
1296 | status = aim_addMeshElem(aimInfo, nTet, &meshData->elemGroups[igroup]); | |||
1297 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1297, __func__, 0); goto cleanup; }; | |||
1298 | ||||
1299 | for (i = 0; i < nTet; i++) { | |||
1300 | ||||
1301 | /* read the element and group */ | |||
1302 | status = GmfGetLin(fileID, GmfTetrahedra, &elem[0], | |||
1303 | &elem[1], | |||
1304 | &elem[2], | |||
1305 | &elem[3], &igroup); | |||
1306 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1306, __func__, 0); goto cleanup; }; } | |||
1307 | ||||
1308 | if (igroup != 0) { | |||
1309 | AIM_ERROR(aimInfo, "Tetrahedra group must be 0: %d!", igroup){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 1309, __func__ , "Tetrahedra group must be 0: %d!", igroup); }; | |||
1310 | status = CAPS_IOERR-332; | |||
1311 | goto cleanup; | |||
1312 | } | |||
1313 | ||||
1314 | igroup = tetGroup; | |||
1315 | ||||
1316 | /* set the element connectivity */ | |||
1317 | for (j = 0; j < nPoint; j++) | |||
1318 | meshData->elemGroups[igroup].elements[nPoint*(meshData->elemGroups[igroup].nElems-1) + j] = elem[j]; | |||
1319 | ||||
1320 | meshData->elemMap[elementIndex][0] = igroup; | |||
1321 | meshData->elemMap[elementIndex][1] = meshData->elemGroups[igroup].nElems-1; | |||
1322 | ||||
1323 | elementIndex += 1; | |||
1324 | } | |||
1325 | } | |||
1326 | ||||
1327 | } else { | |||
1328 | // generate tessellation | |||
1329 | ||||
1330 | // read parametric coordinates | |||
1331 | ||||
1332 | AIM_ALLOC(bodydata.tedges, bodydata.nedges, edgeData, aimInfo, status){ if (bodydata.tedges != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1332, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tedges"); goto cleanup; } size_t memorysize = bodydata .nedges; bodydata.tedges = (edgeData *) EG_alloc(memorysize*sizeof (edgeData)); if (bodydata.tedges == ((void*)0)) { status = -4 ; aim_status(aimInfo, status, "refineAIM.c", 1332, __func__, 3 , "AIM_ALLOC: %s size %zu type %s", "bodydata.tedges", memorysize , "edgeData"); goto cleanup; } }; | |||
1333 | for (j = 0; j < bodydata.nedges; j++) { | |||
1334 | bodydata.tedges[j].npts = 0; | |||
1335 | bodydata.tedges[j].xyz = NULL((void*)0); | |||
1336 | bodydata.tedges[j].t = NULL((void*)0); | |||
1337 | bodydata.tedges[j].ivp = NULL((void*)0); | |||
1338 | } | |||
1339 | ||||
1340 | // Read EDGEs | |||
1341 | nEdgeVerts = GmfStatKwd(fileID, GmfVerticesOnGeometricEdges); | |||
1342 | status = GmfGotoKwd(fileID, GmfVerticesOnGeometricEdges); | |||
1343 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1343, __func__, 0); goto cleanup; }; } | |||
1344 | ||||
1345 | // first count points on each edge | |||
1346 | for (j = 0; j < nEdgeVerts; j++) { | |||
1347 | status = GmfGetLin(fileID, GmfVerticesOnGeometricEdges, | |||
1348 | &ivp, | |||
1349 | &id, | |||
1350 | &t, | |||
1351 | &double_gref); // refine abuse of dist | |||
1352 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1352, __func__, 0); goto cleanup; }; } | |||
1353 | ||||
1354 | if (id <= 0 || id > bodydata.nedges) { | |||
1355 | AIM_ERROR(aimInfo, "Edge ID %d is out of range [1, %d]", id, bodydata.nedges){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 1355, __func__ , "Edge ID %d is out of range [1, %d]", id, bodydata.nedges); }; | |||
1356 | status = CAPS_IOERR-332; | |||
1357 | goto cleanup; | |||
1358 | } | |||
1359 | bodydata.tedges[id-1].npts++; | |||
1360 | } | |||
1361 | ||||
1362 | for (j = 0; j < bodydata.nedges; j++) { | |||
1363 | npts = bodydata.tedges[j].npts; | |||
1364 | AIM_ALLOC(bodydata.tedges[j].xyz, 3*npts, double, aimInfo, status){ if (bodydata.tedges[j].xyz != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1364, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tedges[j].xyz"); goto cleanup; } size_t memorysize = 3*npts; bodydata.tedges[j].xyz = (double *) EG_alloc(memorysize *sizeof(double)); if (bodydata.tedges[j].xyz == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1364 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "bodydata.tedges[j].xyz" , memorysize, "double"); goto cleanup; } }; | |||
1365 | AIM_ALLOC(bodydata.tedges[j].t , npts, double, aimInfo, status){ if (bodydata.tedges[j].t != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1365, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tedges[j].t"); goto cleanup; } size_t memorysize = npts; bodydata.tedges[j].t = (double *) EG_alloc(memorysize* sizeof(double)); if (bodydata.tedges[j].t == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1365, __func__ , 3, "AIM_ALLOC: %s size %zu type %s", "bodydata.tedges[j].t" , memorysize, "double"); goto cleanup; } }; | |||
1366 | AIM_ALLOC(bodydata.tedges[j].ivp, npts, int , aimInfo, status){ if (bodydata.tedges[j].ivp != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1366, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tedges[j].ivp"); goto cleanup; } size_t memorysize = npts; bodydata.tedges[j].ivp = (int *) EG_alloc(memorysize *sizeof(int)); if (bodydata.tedges[j].ivp == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1366, __func__ , 3, "AIM_ALLOC: %s size %zu type %s", "bodydata.tedges[j].ivp" , memorysize, "int"); goto cleanup; } }; | |||
1367 | bodydata.tedges[j].npts = 0; | |||
1368 | } | |||
1369 | ||||
1370 | status = GmfGotoKwd(fileID, GmfVerticesOnGeometricEdges); | |||
1371 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1371, __func__, 0); goto cleanup; }; } | |||
1372 | ||||
1373 | // read the data | |||
1374 | for (j = 0; j < nEdgeVerts; j++) { | |||
1375 | status = GmfGetLin(fileID, GmfVerticesOnGeometricEdges, | |||
1376 | &ivp, | |||
1377 | &id, | |||
1378 | &t, | |||
1379 | &double_gref); // refine abuse of dist | |||
1380 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1380, __func__, 0); goto cleanup; }; } | |||
1381 | ||||
1382 | npts = bodydata.tedges[id-1].npts; | |||
1383 | ||||
1384 | bodydata.tedges[id-1].t[npts] = t; | |||
1385 | ||||
1386 | bodydata.tedges[id-1].xyz[3*npts+0] = meshData->verts[ivp-1][0]; | |||
1387 | bodydata.tedges[id-1].xyz[3*npts+1] = meshData->verts[ivp-1][1]; | |||
1388 | bodydata.tedges[id-1].xyz[3*npts+2] = meshData->verts[ivp-1][2]; | |||
1389 | ||||
1390 | bodydata.tedges[id-1].ivp[npts] = ivp; | |||
1391 | ||||
1392 | bodydata.tedges[id-1].npts++; | |||
1393 | } | |||
1394 | ||||
1395 | for (j = 0; j < bodydata.nedges; j++) { | |||
1396 | bubbleSortEdge(&bodydata.tedges[j]); | |||
1397 | } | |||
1398 | ||||
1399 | ||||
1400 | // Count face points first | |||
1401 | nFaceVerts = GmfStatKwd(fileID, GmfVerticesOnGeometricTriangles); | |||
1402 | status = GmfGotoKwd(fileID, GmfVerticesOnGeometricTriangles); | |||
1403 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1403, __func__, 0); goto cleanup; }; } | |||
1404 | ||||
1405 | for (j = 0; j < nFaceVerts; j++) { | |||
1406 | ||||
1407 | status = GmfGetLin(fileID, GmfVerticesOnGeometricTriangles, | |||
1408 | &ivp, | |||
1409 | &id, | |||
1410 | &uv[0], &uv[1], | |||
1411 | &double_gref); // refine abuse of dist | |||
1412 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1412, __func__, 0); goto cleanup; }; } | |||
1413 | ||||
1414 | if (id <= 0 || id > bodydata.nfaces) { | |||
1415 | AIM_ERROR(aimInfo, "Face ID %d is out of range [1, %d]", id, bodydata.nfaces){ aim_message(aimInfo, CERROR, 0 , "refineAIM.c", 1415, __func__ , "Face ID %d is out of range [1, %d]", id, bodydata.nfaces); }; | |||
1416 | status = CAPS_IOERR-332; | |||
1417 | goto cleanup; | |||
1418 | } | |||
1419 | bodydata.tfaces[id-1].npts++; | |||
1420 | } | |||
1421 | ||||
1422 | for (j = 0; j < bodydata.nfaces; j++) { | |||
1423 | npts = bodydata.tfaces[j].npts; | |||
1424 | AIM_ALLOC(bodydata.tfaces[j].xyz , 3*npts, double, aimInfo, status){ if (bodydata.tfaces[j].xyz != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1424, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tfaces[j].xyz"); goto cleanup; } size_t memorysize = 3*npts; bodydata.tfaces[j].xyz = (double *) EG_alloc(memorysize *sizeof(double)); if (bodydata.tfaces[j].xyz == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1424 , __func__, 3, "AIM_ALLOC: %s size %zu type %s", "bodydata.tfaces[j].xyz" , memorysize, "double"); goto cleanup; } }; | |||
1425 | AIM_ALLOC(bodydata.tfaces[j].uv , 2*npts, double, aimInfo, status){ if (bodydata.tfaces[j].uv != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1425, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tfaces[j].uv"); goto cleanup; } size_t memorysize = 2*npts; bodydata.tfaces[j].uv = (double *) EG_alloc(memorysize *sizeof(double)); if (bodydata.tfaces[j].uv == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1425, __func__ , 3, "AIM_ALLOC: %s size %zu type %s", "bodydata.tfaces[j].uv" , memorysize, "double"); goto cleanup; } }; | |||
1426 | AIM_ALLOC(bodydata.tfaces[j].ivp , npts, int , aimInfo, status){ if (bodydata.tfaces[j].ivp != ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1426, __func__, 1, "AIM_ALLOC: %s != NULL" , "bodydata.tfaces[j].ivp"); goto cleanup; } size_t memorysize = npts; bodydata.tfaces[j].ivp = (int *) EG_alloc(memorysize *sizeof(int)); if (bodydata.tfaces[j].ivp == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1426, __func__ , 3, "AIM_ALLOC: %s size %zu type %s", "bodydata.tfaces[j].ivp" , memorysize, "int"); goto cleanup; } }; | |||
1427 | bodydata.tfaces[j].npts = 0; | |||
1428 | } | |||
1429 | ||||
1430 | status = GmfGotoKwd(fileID, GmfVerticesOnGeometricTriangles); | |||
1431 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1431, __func__, 0); goto cleanup; }; } | |||
1432 | ||||
1433 | // read the data | |||
1434 | for (j = 0; j < nFaceVerts; j++) { | |||
1435 | status = GmfGetLin(fileID, GmfVerticesOnGeometricTriangles, | |||
1436 | &ivp, | |||
1437 | &id, | |||
1438 | &uv[0], &uv[1], | |||
1439 | &double_gref); // refine abuse of dist | |||
1440 | if (status <= 0) { status = CAPS_IOERR-332; AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1440, __func__, 0); goto cleanup; }; } | |||
1441 | ||||
1442 | npts = bodydata.tfaces[id-1].npts; | |||
1443 | ||||
1444 | bodydata.tfaces[id-1].uv[2*npts+0] = uv[0]; | |||
1445 | bodydata.tfaces[id-1].uv[2*npts+1] = uv[1]; | |||
1446 | ||||
1447 | bodydata.tfaces[id-1].xyz[3*npts+0] = meshData->verts[ivp-1][0]; | |||
1448 | bodydata.tfaces[id-1].xyz[3*npts+1] = meshData->verts[ivp-1][1]; | |||
1449 | bodydata.tfaces[id-1].xyz[3*npts+2] = meshData->verts[ivp-1][2]; | |||
1450 | ||||
1451 | bodydata.tfaces[id-1].ivp[npts] = ivp; | |||
1452 | ||||
1453 | bodydata.tfaces[id-1].npts++; | |||
1454 | } | |||
1455 | ||||
1456 | for (j = 0; j < bodydata.nfaces; j++) { | |||
1457 | bubbleSortFace(&bodydata.tfaces[j]); | |||
1458 | // get the face triangulation | |||
1459 | for (i = 0; i < bodydata.tfaces[j].ntri; i++) { | |||
1460 | bodydata.tfaces[j].tris[3*i+0] = faceIndex(bodydata.tfaces[j].tris[3*i+0], &bodydata.tfaces[j]); | |||
1461 | bodydata.tfaces[j].tris[3*i+1] = faceIndex(bodydata.tfaces[j].tris[3*i+1], &bodydata.tfaces[j]); | |||
1462 | bodydata.tfaces[j].tris[3*i+2] = faceIndex(bodydata.tfaces[j].tris[3*i+2], &bodydata.tfaces[j]); | |||
1463 | } | |||
1464 | } | |||
1465 | ||||
1466 | // Allocate surfaceMesh from number of bodies | |||
1467 | AIM_ALLOC(mesh->meshRef->maps, 1, aimMeshTessMap, aimInfo, status){ if (mesh->meshRef->maps != ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1467, __func__, 1 , "AIM_ALLOC: %s != NULL", "mesh->meshRef->maps"); goto cleanup; } size_t memorysize = 1; mesh->meshRef->maps = (aimMeshTessMap *) EG_alloc(memorysize*sizeof(aimMeshTessMap )); if (mesh->meshRef->maps == ((void*)0)) { status = - 4; aim_status(aimInfo, status, "refineAIM.c", 1467, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "mesh->meshRef->maps" , memorysize, "aimMeshTessMap"); goto cleanup; } }; | |||
1468 | mesh->meshRef->nmap = 1; | |||
1469 | mesh->meshRef->maps[0].tess = NULL((void*)0); | |||
1470 | mesh->meshRef->maps[0].map = NULL((void*)0); | |||
1471 | ||||
1472 | // Build up the body tessellation object | |||
1473 | status = EG_initTessBody(body, &tess); | |||
1474 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1474, __func__, 0); goto cleanup; }; | |||
1475 | AIM_NOTNULL(tess, aimInfo, status){ if (tess == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 1475, __func__, 1, "%s == NULL!", "tess" ); goto cleanup; } }; | |||
1476 | ||||
1477 | for ( iedge = 0; iedge < bodydata.nedges; iedge++ ) { | |||
1478 | ||||
1479 | // Check if the edge is degenerate | |||
1480 | if (bodydata.edges[iedge]->mtype == DEGENERATE5) continue; | |||
1481 | ||||
1482 | status = EG_setTessEdge(tess, iedge+1, bodydata.tedges[iedge].npts, | |||
1483 | bodydata.tedges[iedge].xyz, | |||
1484 | bodydata.tedges[iedge].t); | |||
1485 | AIM_STATUS(aimInfo, status, "Failed to set tessellation on Edge %d!", iedge+1)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1485, __func__, 2, "Failed to set tessellation on Edge %d!", iedge+1); goto cleanup; }; | |||
1486 | ||||
1487 | // Add the unique indexing of the edge tessellation | |||
1488 | snprintf(attrname, 128, "edgeVertID_%d",iedge+1); | |||
1489 | status = EG_attributeAdd(tess, attrname, ATTRINT1, | |||
1490 | bodydata.tedges[iedge].npts, | |||
1491 | bodydata.tedges[iedge].ivp, NULL((void*)0), NULL((void*)0)); | |||
1492 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1492, __func__, 0); goto cleanup; }; | |||
1493 | } | |||
1494 | ||||
1495 | for (iface = 0; iface < bodydata.nfaces; iface++) { | |||
1496 | ||||
1497 | ntri = bodydata.tfaces[iface].ntri; | |||
1498 | ||||
1499 | face_tris = bodydata.tfaces[iface].tris; | |||
1500 | face_uv = bodydata.tfaces[iface].uv; | |||
1501 | face_xyz = bodydata.tfaces[iface].xyz; | |||
1502 | ||||
1503 | AIM_NOTNULL(face_tris, aimInfo, status){ if (face_tris == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 1503, __func__, 1, "%s == NULL!", "face_tris" ); goto cleanup; } }; | |||
1504 | AIM_NOTNULL(face_uv , aimInfo, status){ if (face_uv == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 1504, __func__, 1, "%s == NULL!", "face_uv" ); goto cleanup; } }; | |||
1505 | AIM_NOTNULL(face_xyz , aimInfo, status){ if (face_xyz == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 1505, __func__, 1, "%s == NULL!", "face_xyz" ); goto cleanup; } }; | |||
1506 | ||||
1507 | // check the normals of the elements match the geometry normals | |||
1508 | // only need to check one element per face to decide for all | |||
1509 | elem[0] = face_tris[0]-1; | |||
1510 | elem[1] = face_tris[1]-1; | |||
1511 | elem[2] = face_tris[2]-1; | |||
1512 | ||||
1513 | // get the uv centroid | |||
1514 | uv[0] = (face_uv[2*elem[0]+0] + face_uv[2*elem[1]+0] + face_uv[2*elem[2]+0])/3.; | |||
1515 | uv[1] = (face_uv[2*elem[0]+1] + face_uv[2*elem[1]+1] + face_uv[2*elem[2]+1])/3.; | |||
1516 | ||||
1517 | // get the normal of the face | |||
1518 | status = EG_evaluate(bodydata.faces[iface], uv, result); | |||
1519 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1519, __func__, 0); goto cleanup; }; | |||
1520 | ||||
1521 | // use cross dX/du x dX/dv to get geometry normal | |||
1522 | v1[0] = result[3]; v1[1] = result[4]; v1[2] = result[5]; | |||
1523 | v2[0] = result[6]; v2[1] = result[7]; v2[2] = result[8]; | |||
1524 | CROSS(faceNormal, v1, v2)faceNormal[0] = (v1[1]*v2[2]) - (v1[2]*v2[1]); faceNormal[1] = (v1[2]*v2[0]) - (v1[0]*v2[2]); faceNormal[2] = (v1[0]*v2[1]) - (v1[1]*v2[0]); | |||
1525 | ||||
1526 | // get mtype=SFORWARD or mtype=SREVERSE for the face to get topology normal | |||
1527 | status = EG_getInfo(bodydata.faces[iface], &oclass, &mtype, &ref, &prev, &next); | |||
1528 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1528, __func__, 0); goto cleanup; }; | |||
1529 | faceNormal[0] *= mtype; | |||
1530 | faceNormal[1] *= mtype; | |||
1531 | faceNormal[2] *= mtype; | |||
1532 | ||||
1533 | // get the normal of the mesh triangle | |||
1534 | v1[0] = face_xyz[3*elem[1]+0] - face_xyz[3*elem[0]+0]; | |||
1535 | v1[1] = face_xyz[3*elem[1]+1] - face_xyz[3*elem[0]+1]; | |||
1536 | v1[2] = face_xyz[3*elem[1]+2] - face_xyz[3*elem[0]+2]; | |||
1537 | ||||
1538 | v2[0] = face_xyz[3*elem[2]+0] - face_xyz[3*elem[0]+0]; | |||
1539 | v2[1] = face_xyz[3*elem[2]+1] - face_xyz[3*elem[0]+1]; | |||
1540 | v2[2] = face_xyz[3*elem[2]+2] - face_xyz[3*elem[0]+2]; | |||
1541 | ||||
1542 | CROSS(triNormal, v1, v2)triNormal[0] = (v1[1]*v2[2]) - (v1[2]*v2[1]); triNormal[1] = ( v1[2]*v2[0]) - (v1[0]*v2[2]); triNormal[2] = (v1[0]*v2[1]) - ( v1[1]*v2[0]); | |||
1543 | ||||
1544 | // get the dot product between the triangle and face normals | |||
1545 | ndot = DOT(faceNormal,triNormal)(faceNormal[0]*triNormal[0] + faceNormal[1]*triNormal[1] + faceNormal [2]*triNormal[2]); | |||
1546 | ||||
1547 | // if the normals are opposite, swap all triangles | |||
1548 | if (ndot < 0) { | |||
1549 | // swap two vertices to reverse the normal | |||
1550 | for (i = 0; i < ntri; i++) { | |||
1551 | swapi(&face_tris[3*i+0], &face_tris[3*i+2]); | |||
1552 | } | |||
1553 | } | |||
1554 | ||||
1555 | status = EG_setTessFace(tess, | |||
1556 | iface+1, | |||
1557 | bodydata.tfaces[iface].npts, | |||
1558 | face_xyz, | |||
1559 | face_uv, | |||
1560 | ntri, | |||
1561 | face_tris); | |||
1562 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1562, __func__, 0); goto cleanup; }; | |||
1563 | ||||
1564 | ||||
1565 | // The points get reindexed to be consistent with loops in EG_setTessFace | |||
1566 | // This uses the new triangulation to map that index change. | |||
1567 | status = EG_getTessFace(tess, iface+1, &npts, &pxyz, &puv, &ptype, | |||
1568 | &pindex, &ntri, &tris, &tric); | |||
1569 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1569, __func__, 0); goto cleanup; }; | |||
1570 | AIM_NOTNULL(tris, aimInfo, status){ if (tris == ((void*)0)) { status = -307; aim_status(aimInfo , status, "refineAIM.c", 1570, __func__, 1, "%s == NULL!", "tris" ); goto cleanup; } }; | |||
1571 | ||||
1572 | AIM_ALLOC(faceVertID, npts, int, aimInfo, status){ if (faceVertID != ((void*)0)) { status = -4; aim_status(aimInfo , status, "refineAIM.c", 1572, __func__, 1, "AIM_ALLOC: %s != NULL" , "faceVertID"); goto cleanup; } size_t memorysize = npts; faceVertID = (int *) EG_alloc(memorysize*sizeof(int)); if (faceVertID == ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c" , 1572, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "faceVertID" , memorysize, "int"); goto cleanup; } }; | |||
1573 | ||||
1574 | for (i = 0; i < ntri; i++) { | |||
1575 | for (j = 0; j < 3; j++) { | |||
1576 | faceVertID[tris[3*i+j]-1] = bodydata.tfaces[iface].ivp[face_tris[3*i+j]-1]; | |||
1577 | } | |||
1578 | } | |||
1579 | ||||
1580 | // Add the unique indexing of the tessellation | |||
1581 | snprintf(attrname, 128, "faceVertID_%d",iface+1); | |||
1582 | status = EG_attributeAdd(tess, attrname, ATTRINT1, | |||
1583 | bodydata.tfaces[iface].npts, | |||
1584 | faceVertID, NULL((void*)0), NULL((void*)0)); | |||
1585 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1585, __func__, 0); goto cleanup; }; | |||
1586 | ||||
1587 | // replace the shuffled volume ID's | |||
1588 | AIM_FREE(bodydata.tfaces[iface].ivp){ EG_free(bodydata.tfaces[iface].ivp); bodydata.tfaces[iface] .ivp = ((void*)0); }; | |||
1589 | bodydata.tfaces[iface].ivp = faceVertID; | |||
1590 | faceVertID = NULL((void*)0); | |||
1591 | } | |||
1592 | ||||
1593 | // finalize the tessellation | |||
1594 | status = EG_statusTessBody(tess, &body, &i, &nglobal); | |||
1595 | AIM_STATUS(aimInfo, status, "Tessellation object was not built correctly!!!")if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1595, __func__, 1, "Tessellation object was not built correctly!!!" ); goto cleanup; }; | |||
1596 | ||||
1597 | // Create the map from the tessellation global vertex index to the volume mesh vertex index | |||
1598 | AIM_ALLOC(mesh->meshRef->maps[0].map, nglobal, int, aimInfo, status){ if (mesh->meshRef->maps[0].map != ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1598, __func__ , 1, "AIM_ALLOC: %s != NULL", "mesh->meshRef->maps[0].map" ); goto cleanup; } size_t memorysize = nglobal; mesh->meshRef ->maps[0].map = (int *) EG_alloc(memorysize*sizeof(int)); if (mesh->meshRef->maps[0].map == ((void*)0)) { status = - 4; aim_status(aimInfo, status, "refineAIM.c", 1598, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "mesh->meshRef->maps[0].map" , memorysize, "int"); goto cleanup; } }; | |||
1599 | ||||
1600 | for (iface = 0; iface < bodydata.nfaces; iface++) { | |||
1601 | status = EG_getTessFace(tess, iface+1, &npts, &pxyz, &puv, &ptype, | |||
1602 | &pindex, &ntri, &tris, &tric); | |||
1603 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1603, __func__, 0); goto cleanup; }; | |||
1604 | ||||
1605 | /* construct global vertex indices */ | |||
1606 | for (i = 0; i < npts; i++) { | |||
1607 | status = EG_localToGlobal(tess, iface+1, i+1, &iglobal); | |||
1608 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1608, __func__, 0); goto cleanup; }; | |||
1609 | mesh->meshRef->maps[0].map[iglobal-1] = bodydata.tfaces[iface].ivp[i]; | |||
1610 | } | |||
1611 | } | |||
1612 | ||||
1613 | // save the tessellation with caps | |||
1614 | status = aim_newTess(aimInfo, tess); | |||
1615 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1615, __func__, 0); goto cleanup; }; | |||
1616 | ||||
1617 | /*@-kepttrans@*/ | |||
1618 | // reference the surface mesh object | |||
1619 | mesh->meshRef->maps[0].tess = tess; | |||
1620 | tess = NULL((void*)0); | |||
1621 | /*@+kepttrans@*/ | |||
1622 | ||||
1623 | AIM_ALLOC(mesh->meshRef->bnds, refineInstance->groupMap.numAttribute, aimMeshBnd, aimInfo, status){ if (mesh->meshRef->bnds != ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1623, __func__, 1 , "AIM_ALLOC: %s != NULL", "mesh->meshRef->bnds"); goto cleanup; } size_t memorysize = refineInstance->groupMap.numAttribute ; mesh->meshRef->bnds = (aimMeshBnd *) EG_alloc(memorysize *sizeof(aimMeshBnd)); if (mesh->meshRef->bnds == ((void *)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c" , 1623, __func__, 3, "AIM_ALLOC: %s size %zu type %s", "mesh->meshRef->bnds" , memorysize, "aimMeshBnd"); goto cleanup; } }; | |||
1624 | mesh->meshRef->nbnd = refineInstance->groupMap.numAttribute; | |||
1625 | for (i = 0; i < mesh->meshRef->nbnd; i++) { | |||
1626 | status = aim_initMeshBnd(mesh->meshRef->bnds + i); | |||
1627 | AIM_STATUS(aimInfo, status)if (status != 0) { aim_status(aimInfo, status, "refineAIM.c", 1627, __func__, 0); goto cleanup; }; | |||
1628 | } | |||
1629 | ||||
1630 | for (i = 0; i < mesh->meshRef->nbnd; i++) { | |||
1631 | AIM_STRDUP(mesh->meshRef->bnds[i].groupName, refineInstance->groupMap.attributeName[i], aimInfo, status){ if (mesh->meshRef->bnds[i].groupName != ((void*)0)) { status = -4; aim_status(aimInfo, status, "refineAIM.c", 1631 , __func__, 1, "AIM_STRDUP: %s != NULL!", "mesh->meshRef->bnds[i].groupName" ); goto cleanup; } mesh->meshRef->bnds[i].groupName = EG_strdup (refineInstance->groupMap.attributeName[i]); if (mesh-> meshRef->bnds[i].groupName == ((void*)0)) { status = -4; aim_status (aimInfo, status, "refineAIM.c", 1631, __func__, 2, "AIM_STRDUP: %s %s" , "mesh->meshRef->bnds[i].groupName", refineInstance-> groupMap.attributeName[i]); goto cleanup; } }; | |||
1632 | mesh->meshRef->bnds[i].ID = refineInstance->groupMap.attributeIndex[i]; | |||
1633 | } | |||
1634 | } | |||
1635 | ||||
1636 | mesh->meshData = meshData; | |||
1637 | meshData = NULL((void*)0); | |||
1638 | ||||
1639 | status = CAPS_SUCCESS0; | |||
1640 | ||||
1641 | cleanup: | |||
1642 | if (status != CAPS_SUCCESS0) { | |||
1643 | aim_freeMeshData(meshData); | |||
1644 | AIM_FREE(meshData){ EG_free(meshData); meshData = ((void*)0); }; | |||
1645 | } | |||
1646 | ||||
1647 | if (fileID != 0) GmfCloseMesh(fileID); | |||
1648 | ||||
1649 | destroy_bodyData(1, &bodydata); | |||
1650 | ||||
1651 | AIM_FREE(faceGroups){ EG_free(faceGroups); faceGroups = ((void*)0); }; | |||
1652 | AIM_FREE(edgeGroups){ EG_free(edgeGroups); edgeGroups = ((void*)0); }; | |||
1653 | ||||
1654 | return status; | |||
1655 | } | |||
1656 |