Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmergrid/src/fempre.c
5247 views
1
/*
2
ElmerGrid - A simple mesh generation and manipulation utility
3
Copyright (C) 1995- , CSC - IT Center for Science Ltd.
4
5
Author: Peter Raback
6
Email: [email protected]
7
Address: CSC - IT Center for Science Ltd.
8
Keilaranta 14
9
02101 Espoo, Finland
10
11
This program is free software; you can redistribute it and/or
12
modify it under the terms of the GNU General Public License
13
as published by the Free Software Foundation; either version 2
14
of the License, or (at your option) any later version.
15
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
20
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software
23
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24
*/
25
26
/****************************************************************************
27
* *
28
* Elmergrid *
29
* *
30
* This program creates very easily a structured 2D meshes with BCs. *
31
* The element types include 4, 5, 8, 9, 12 and 16-node rectangles and *
32
* 3, 6 and 10-node triangles. There is also limited 3D functionality *
33
* with 8, 20 and 27-node cubes and 6-node prisms. *
34
* *
35
* The program may also be used as a mesh import and export utility. It *
36
* is able to read several different formats and writes mainly Elmer input *
37
* and output formats. The meshes may also be given some simple operations. *
38
* *
39
* Note: this software was initially part of my first fem implementation *
40
* the Pirfem code, then later called Quickmesh, and finally renamed to *
41
* ElmerGrid. The code has never been designed and with new features the *
42
* code has eventually become very dirty and does not present my view of *
43
* good programming. *
44
* *
45
****************************************************************************/
46
47
48
#include <stdio.h>
49
#include <stddef.h>
50
#include <stdlib.h>
51
#include <string.h>
52
#include <ctype.h>
53
#include <math.h>
54
55
#include "egutils.h"
56
#include "egdef.h"
57
#include "egtypes.h"
58
#include "egmesh.h"
59
#include "egextra.h"
60
#include "egnative.h"
61
#include "egparallel.h"
62
#include "egconvert.h"
63
#include "egexport.h"
64
65
#include "../config.h"
66
67
int main(int argc, char *argv[])
68
{
69
int i,j,k,l,inmethod,outmethod,info,errorstat;
70
int nogrids,nogrids0,nomeshes,nofile,dim,elementsredone=0;
71
int nodes3d,elements3d,showmem;
72
Real mergeeps;
73
char prefix[MAXFILESIZE];
74
struct GridType *grids;
75
struct CellType *cell[MAXCASES];
76
struct FemType data[MAXCASES];
77
struct BoundaryType *boundaries[MAXCASES];
78
struct ElmergridType eg;
79
80
showmem = TRUE;
81
82
printf("==================================================================\n");
83
printf("ElmerGrid mesh conversion and manipulation utility, Welcome!\n");
84
#ifdef ELMER_FEM_VERSION
85
/* Branch might not exist even though Revision would exist when git is in detached head state.
86
Heance check the branch for existance. */
87
#ifdef ELMER_FEM_BRANCH
88
printf("Version: %s-%s (Rev: %s, Compiled: %s)\n",ELMER_FEM_VERSION,ELMER_FEM_BRANCH,
89
ELMER_FEM_REVISION,ELMER_FEM_COMPILATIONDATE);
90
#else
91
printf("Version: %s (Rev: NA, Compiled: NA)\n",ELMER_FEM_VERSION);
92
#endif
93
#endif
94
printf("This program is free software licensed under GPL\n");
95
printf("==================================================================\n");
96
97
InitParameters(&eg);
98
99
grids = (struct GridType*)malloc((size_t) (MAXCASES)*sizeof(struct GridType));
100
InitGrid(grids);
101
info = TRUE;
102
103
if(argc <= 1) {
104
errorstat = LoadCommands(argv[1],&eg,grids,argc-1,info);
105
if(errorstat) {
106
Instructions();
107
Goodbye();
108
}
109
}
110
else if(argc == 2) {
111
errorstat = LoadCommands(argv[1],&eg,grids,argc-1,info);
112
if(errorstat) Goodbye();
113
}
114
else if(argc < 4) {
115
Instructions();
116
Goodbye();
117
}
118
else {
119
errorstat = InlineParameters(&eg,argc,argv,4,info);
120
if(errorstat) Goodbye();
121
}
122
123
124
if(!eg.outmethod || !eg.inmethod) {
125
printf("Please define the input and output formats\n");
126
}
127
if(eg.inmethod != 1) {
128
if(eg.outmethod == 1 || eg.outmethod == 8 || eg.outmethod == 9 || eg.outmethod == 10) {
129
printf("input of type %d can't create output of type %d\n",
130
eg.inmethod,eg.outmethod);
131
errorstat++;
132
Goodbye();
133
}
134
}
135
136
if(eg.timeron) timer_activate(eg.infofile);
137
138
/**********************************/
139
printf("\nElmergrid loading data:\n");
140
printf( "-----------------------\n");
141
142
dim = eg.dim;
143
nofile = 0;
144
nomeshes = 0;
145
nogrids = 0;
146
inmethod = eg.inmethod;
147
outmethod = eg.outmethod;
148
149
if(eg.nooverwrite && !eg.filerenamed) {
150
if( eg.partitions == 1 || eg.metis == 1 ) {
151
if(inmethod == outmethod) {
152
printf("Nothing to do, one partition, same input/output format and no overwriting allowed!\n");
153
Goodbye();
154
return(0);
155
}
156
}
157
}
158
159
read_another_file:
160
161
timer_show();
162
163
switch (inmethod) {
164
165
case 1:
166
nogrids0 = nogrids;
167
if(LoadElmergrid(&grids,&nogrids,eg.filesin[nofile],info) == 1) {
168
CreateExampleGrid(eg.dim,&grids,&nogrids,info);
169
SaveElmergrid(grids,nogrids,eg.filesin[nofile],info);
170
printf("Because file %s didn't exist, it was created for you.\n",eg.filesin[nofile]);
171
Goodbye();
172
}
173
LoadCommands(eg.filesin[nofile],&eg,grids,2,info);
174
for(k=nogrids0;k < nogrids;k++) {
175
SetElementDivision(&(grids[k]),eg.relh,info);
176
}
177
178
break;
179
180
case 2:
181
boundaries[nofile] = (struct BoundaryType*)
182
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
183
for(i=0;i<MAXBOUNDARIES;i++) {
184
boundaries[nofile][i].created = FALSE;
185
boundaries[nofile][i].nosides = 0;
186
}
187
if(LoadElmerInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],
188
!eg.usenames,info))
189
Goodbye();
190
191
192
nomeshes++;
193
break;
194
195
case 3:
196
if(LoadSolutionElmer(&(data[nofile]),TRUE,eg.filesin[nofile],info))
197
Goodbye();
198
nomeshes++;
199
break;
200
201
case 4:
202
boundaries[nofile] = (struct BoundaryType*)
203
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
204
if(LoadAnsysInput(&(data[0]),boundaries[0],eg.filesin[nofile],info))
205
Goodbye();
206
nomeshes++;
207
break;
208
209
case 5:
210
boundaries[nofile] = (struct BoundaryType*)
211
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
212
for(i=0;i<MAXBOUNDARIES;i++) {
213
boundaries[nofile][i].created = FALSE;
214
boundaries[nofile][i].nosides = 0;
215
}
216
if(LoadAbaqusInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
217
Goodbye();
218
nomeshes++;
219
break;
220
221
case 6:
222
if(LoadAbaqusOutput(&(data[nofile]),eg.filesin[nofile],TRUE))
223
Goodbye();
224
nomeshes++;
225
break;
226
227
case 7:
228
boundaries[nofile] = (struct BoundaryType*)
229
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
230
for(i=0;i<MAXBOUNDARIES;i++) {
231
boundaries[nofile][i].created = FALSE;
232
boundaries[nofile][i].nosides = 0;
233
}
234
if(LoadFidapInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
235
Goodbye();
236
237
eg.bulkorder = TRUE;
238
eg.boundorder = TRUE;
239
240
if(!eg.usenames) data[nofile].boundarynamesexist = data[nofile].bodynamesexist = FALSE;
241
242
nomeshes++;
243
break;
244
245
case 8:
246
boundaries[nofile] = (struct BoundaryType*)
247
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
248
for(i=0;i<MAXBOUNDARIES;i++) {
249
boundaries[nofile][i].created = FALSE;
250
boundaries[nofile][i].nosides = 0;
251
}
252
if (LoadUniversalMesh(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
253
Goodbye();
254
nomeshes++;
255
break;
256
257
case 9:
258
boundaries[nofile] = (struct BoundaryType*)
259
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
260
for(i=0;i<MAXBOUNDARIES;i++) {
261
boundaries[nofile][i].created = FALSE;
262
boundaries[nofile][i].nosides = 0;
263
}
264
if(LoadComsolMesh(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],info))
265
Goodbye();
266
nomeshes++;
267
break;
268
269
case 10:
270
boundaries[nofile] = (struct BoundaryType*)
271
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
272
for(i=0;i<MAXBOUNDARIES;i++) {
273
boundaries[nofile][i].created = FALSE;
274
boundaries[nofile][i].nosides = 0;
275
}
276
if(LoadFieldviewInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
277
Goodbye();
278
nomeshes++;
279
break;
280
281
case 11:
282
boundaries[nofile] = (struct BoundaryType*)
283
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
284
for(i=0;i<MAXBOUNDARIES;i++) {
285
boundaries[nofile][i].created = FALSE;
286
boundaries[nofile][i].nosides = 0;
287
}
288
if (LoadTriangleInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
289
Goodbye();
290
nomeshes++;
291
break;
292
293
case 12:
294
boundaries[nofile] = (struct BoundaryType*)
295
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
296
for(i=0;i<MAXBOUNDARIES;i++) {
297
boundaries[nofile][i].created = FALSE;
298
boundaries[nofile][i].nosides = 0;
299
}
300
if (LoadMeditInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
301
Goodbye();
302
nomeshes++;
303
break;
304
305
case 13:
306
boundaries[nofile] = (struct BoundaryType*)
307
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
308
for(i=0;i<MAXBOUNDARIES;i++) {
309
boundaries[nofile][i].created = FALSE;
310
boundaries[nofile][i].nosides = 0;
311
}
312
if (LoadGidInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
313
Goodbye();
314
nomeshes++;
315
break;
316
317
case 14:
318
boundaries[nofile] = (struct BoundaryType*)
319
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
320
data[nofile].dim = (eg.dim >= 1 && eg.dim <= 3) ? eg.dim : 3; /* default dim 3 with gmsh if not given! */
321
for(i=0;i<MAXBOUNDARIES;i++) {
322
boundaries[nofile][i].created = FALSE;
323
boundaries[nofile][i].nosides = 0;
324
}
325
326
if (LoadGmshInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],
327
eg.multidim,eg.dim,TRUE))
328
Goodbye();
329
nomeshes++;
330
break;
331
332
case 15:
333
if(info) printf("Partitioned solution is fused on-the-fly therefore no other operations may be performed.\n");
334
FuseSolutionElmerPartitioned(eg.filesin[nofile],eg.filesout[nofile],eg.decimals,eg.partjoin,
335
eg.saveinterval[0],eg.saveinterval[1],eg.saveinterval[2],info);
336
if(info) printf("Finishing with the fusion of partitioned Elmer solutions\n");
337
Goodbye();
338
break;
339
340
case 16:
341
boundaries[nofile] = (struct BoundaryType*)
342
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
343
for(i=0;i<MAXBOUNDARIES;i++) {
344
boundaries[nofile][i].created = FALSE;
345
boundaries[nofile][i].nosides = 0;
346
}
347
if (LoadFvcomMesh(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
348
Goodbye();
349
nomeshes++;
350
break;
351
352
case 17:
353
boundaries[nofile] = (struct BoundaryType*)
354
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
355
for(i=0;i<MAXBOUNDARIES;i++) {
356
boundaries[nofile][i].created = FALSE;
357
boundaries[nofile][i].nosides = 0;
358
}
359
if (LoadNastranInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
360
Goodbye();
361
nomeshes++;
362
break;
363
364
case 18:
365
boundaries[nofile] = (struct BoundaryType*)
366
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
367
for(i=0;i<MAXBOUNDARIES;i++) {
368
boundaries[nofile][i].created = FALSE;
369
boundaries[nofile][i].nosides = 0;
370
}
371
372
if(LoadCGsimMesh(&(data[nofile]),eg.filesin[nofile],info))
373
Goodbye();
374
nomeshes++;
375
break;
376
377
case 19:
378
boundaries[nofile] = (struct BoundaryType*)
379
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
380
for(i=0;i<MAXBOUNDARIES;i++) {
381
boundaries[nofile][i].created = FALSE;
382
boundaries[nofile][i].nosides = 0;
383
}
384
if (LoadGeoInput(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
385
Goodbye();
386
nomeshes++;
387
break;
388
389
case 20:
390
boundaries[nofile] = (struct BoundaryType*)
391
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
392
for(i=0;i<MAXBOUNDARIES;i++) {
393
boundaries[nofile][i].created = FALSE;
394
boundaries[nofile][i].nosides = 0;
395
}
396
if (LoadFluxMesh(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
397
Goodbye();
398
nomeshes++;
399
break;
400
401
case 21:
402
boundaries[nofile] = (struct BoundaryType*)
403
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
404
for(i=0;i<MAXBOUNDARIES;i++) {
405
boundaries[nofile][i].created = FALSE;
406
boundaries[nofile][i].nosides = 0;
407
}
408
if (LoadFluxMesh3D(&(data[nofile]),boundaries[nofile],eg.filesin[nofile],TRUE))
409
Goodbye();
410
nomeshes++;
411
break;
412
413
default:
414
Instructions();
415
Goodbye();
416
}
417
418
nofile++;
419
if(nofile < eg.nofilesin) {
420
printf("\nElmergrid loading data from another file:\n");
421
goto read_another_file;
422
}
423
424
/***********************************/
425
426
427
redoelements:
428
429
printf("\nElmergrid creating and manipulating meshes:\n");
430
printf( "-------------------------------------------\n");
431
timer_show();
432
433
434
if(nogrids > nomeshes && outmethod != 1) {
435
436
nomeshes = nogrids;
437
for(k=0;k<nogrids;k++) {
438
439
CreateCells(&(grids[k]),&(cell[k]),info);
440
CreateKnots(&(grids[k]),cell[k],&(data[k]),0,0);
441
442
boundaries[k] = (struct BoundaryType*)
443
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
444
445
for(j=0;j<MAXBOUNDARIES;j++) {
446
boundaries[k][j].created = FALSE;
447
boundaries[k][j].nosides = FALSE;
448
}
449
450
if(grids[k].noboundaries > 0) {
451
for(j=0;j<grids[k].noboundaries;j++) {
452
if(grids[k].boundsolid[j] < 4) {
453
CreateBoundary(cell[k],&(data[k]),&(boundaries[k][j]),
454
grids[k].boundext[j],grids[k].boundint[j],
455
1,grids[k].boundtype[j],info);
456
}
457
else {
458
CreatePoints(cell[k],&(data[k]),&(boundaries[k][j]),
459
grids[k].boundext[j],grids[k].boundint[j],
460
grids[k].boundsolid[j],grids[k].boundtype[j],info);
461
}
462
}
463
}
464
}
465
}
466
467
/* In some formats the dimension for curved 2D meshes seems to be set to 2.
468
This should fix the problem for all input types. */
469
if( data->dim < 3 ) {
470
data->dim = GetCoordinateDimension(data,info);
471
}
472
473
474
/* Make the discontinuous boundary needed, for example, in poor thermal conduction */
475
for(k=0;k<nomeshes;k++) {
476
if(!eg.discont) {
477
for(j=0;j<grids[k].noboundaries;j++)
478
if(grids[k].boundsolid[j] == 2) {
479
eg.discontbounds[eg.discont] = grids[k].boundtype[j];
480
eg.discont++;
481
}
482
}
483
if(eg.discont) {
484
for(i=1;i<=eg.discont;i++)
485
SetDiscontinuousBoundary(&(data[k]),boundaries[k],eg.discontbounds[i-1],2,info);
486
}
487
}
488
489
490
/* Divide quadrilateral meshes into triangular meshes */
491
for(k=0;k<nomeshes;k++)
492
if(nogrids && (eg.triangles || grids[k].triangles == TRUE)) {
493
Real criticalangle;
494
criticalangle = MAX(eg.triangleangle , grids[k].triangleangle);
495
ElementsToTriangles(&data[k],boundaries[k],criticalangle,info);
496
}
497
498
499
/* Make a boundary layer with two different methods */
500
if(eg.layers > 0)
501
for(k=0;k<nomeshes;k++)
502
CreateBoundaryLayer(&data[k],boundaries[k],eg.layers,
503
eg.layerbounds, eg.layernumber, eg.layerratios, eg.layerthickness,
504
eg.layerparents, eg.layermove, eg.layereps, info);
505
506
else if(eg.layers < 0)
507
for(k=0;k<nomeshes;k++)
508
CreateBoundaryLayerDivide(&data[k],boundaries[k],abs(eg.layers),
509
eg.layerbounds, eg.layernumber, eg.layerratios, eg.layerthickness,
510
eg.layerparents, info);
511
512
/* Take up the infor on rotation */
513
for(k=0;k<nogrids;k++)
514
if( grids[k].rotatecurve ) {
515
eg.rotatecurve = TRUE;
516
eg.curvezet = grids[k].curvezet;
517
eg.curverad = grids[k].curverad;
518
eg.curveangle = grids[k].curveangle;
519
}
520
521
522
if(outmethod != 1 && dim != 2 && eg.dim != 2) {
523
j = MAX(nogrids,1);
524
525
526
for(k=0;k<j;k++) {
527
if(grids[k].dimension == 3 || grids[k].rotate) {
528
529
boundaries[j] = (struct BoundaryType*)
530
malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType));
531
532
for(i=0;i<MAXBOUNDARIES;i++)
533
boundaries[j][i].created = FALSE;
534
535
CreateKnotsExtruded(&(data[k]),boundaries[k],&(grids[k]),
536
&(data[j]),boundaries[j],info);
537
538
if(nogrids) {
539
elements3d = MAX(eg.elements3d, grids[k].wantedelems3d);
540
nodes3d = MAX(eg.nodes3d, grids[k].wantednodes3d);
541
542
if(elements3d) {
543
if( abs(data[j].noelements - elements3d) / (1.0*elements3d) > 0.01 && elementsredone < 5 ) {
544
grids[k].wantedelems *= pow(1.0*elements3d / data[j].noelements, (2.0/3.0));
545
elementsredone++;
546
}
547
else elementsredone = 0;
548
}
549
else if(nodes3d) {
550
if( abs(data[j].noknots - nodes3d) / (1.0*nodes3d) > 0.01 && elementsredone < 5 ) {
551
grids[k].wantedelems *= pow(1.0*nodes3d / data[j].noknots, (2.0/3.0));
552
elementsredone++;
553
}
554
else elementsredone = 0;
555
}
556
557
if(elementsredone) {
558
nomeshes = 0;
559
for(i=0;i < nogrids;i++) SetElementDivision(&(grids[i]),eg.relh,info);
560
561
DestroyKnots(&data[j]);
562
DestroyKnots(&data[k]);
563
free(cell[k]);
564
565
if(info) printf("Iteration %d of elements number targeting %d in 2D\n",
566
elementsredone,grids[k].wantedelems);
567
goto redoelements;
568
}
569
}
570
571
data[k] = data[j];
572
boundaries[k] = boundaries[j];
573
}
574
}
575
}
576
577
/* If the original mesh was given in polar coordinates make the transformation into cartesian ones */
578
for(k=0;k<nomeshes;k++) {
579
if(eg.polar || data[k].coordsystem == COORD_POLAR) {
580
if(!eg.polar) eg.polarradius = grids[k].polarradius;
581
PolarCoordinates(&data[k],eg.polarradius,info);
582
}
583
}
584
585
/* If the original mesh was given in cylindrical coordinates make the transformation into cartesian ones */
586
for(k=0;k<nomeshes;k++) {
587
if(eg.cylinder || data[k].coordsystem == COORD_CYL) {
588
CylinderCoordinates(&data[k],info);
589
}
590
}
591
592
if(1) for(k=0;k<nomeshes;k++)
593
RotateTranslateScale(&data[k],&eg,info);
594
595
596
/* Rotate may apply to 2d and 3d geometries as well */
597
for(k=0;k<nomeshes;k++)
598
if(eg.rotatecurve)
599
CylindricalCoordinateCurve(&data[k],eg.curvezet,eg.curverad,eg.curveangle);
600
601
/* Unite meshes if there are several of them */
602
if(eg.unitemeshes) {
603
for(k=1;k<nomeshes;k++)
604
UniteMeshes(&data[0],&data[k],boundaries[0],boundaries[k],eg.unitenooverlap,info);
605
nomeshes = nogrids = 1;
606
}
607
608
if(eg.clone[0] || eg.clone[1] || eg.clone[2]) {
609
for(k=0;k<nomeshes;k++) {
610
CloneMeshes(&data[k],boundaries[k],eg.clone,eg.clonesize,eg.cloneinds,info);
611
}
612
}
613
614
if(eg.mirror[0] || eg.mirror[1] || eg.mirror[2]) {
615
for(k=0;k<nomeshes;k++) {
616
MirrorMeshes(&data[k],boundaries[k],eg.mirror,FALSE,eg.clonesize,eg.mirrorbc,info);
617
mergeeps = fabs(eg.clonesize[0]+eg.clonesize[1]+eg.clonesize[2]) * 1.0e-8;
618
MergeElements(&data[k],boundaries[k],eg.order,eg.corder,mergeeps,FALSE,TRUE);
619
}
620
}
621
622
/* Naming convection for the case of several meshes */
623
if(nomeshes > 1) {
624
strcpy(prefix,eg.filesout[0]);
625
for(k=0;k<nomeshes;k++)
626
sprintf(eg.filesout[k],"%s%d",prefix,k+1);
627
}
628
629
for(k=0;k<nomeshes;k++) {
630
if(nogrids && grids[k].reduceordermatmax) {
631
eg.reduce = TRUE;
632
eg.reducemat1 = grids[k].reduceordermatmin;
633
eg.reducemat2 = grids[k].reduceordermatmax;
634
}
635
if(eg.reduce)
636
ReduceElementOrder(&data[k],eg.reducemat1,eg.reducemat2);
637
}
638
639
for(k=0;k<nomeshes;k++)
640
if(eg.increase) IncreaseElementOrder(&data[k],TRUE);
641
642
for(k=0;k<nomeshes;k++) {
643
if(eg.merge)
644
MergeElements(&data[k],boundaries[k],eg.order,eg.corder,eg.cmerge,FALSE,TRUE);
645
else if(eg.order == 3)
646
#if USE_METIS
647
ReorderElementsMetis(&data[k],TRUE);
648
#else
649
printf("Cannot order nodes by Metis as it is not even compiled!\n");
650
#endif
651
else if(eg.order)
652
ReorderElements(&data[k],boundaries[k],eg.order,eg.corder,TRUE);
653
654
if(eg.isoparam)
655
IsoparametricElements(&data[k],boundaries[k],TRUE,info);
656
}
657
658
for(k=0;k<nomeshes;k++) {
659
if(eg.bulkbounds || eg.boundbounds)
660
SideAndBulkBoundaries(&data[k],boundaries[k],&eg,info);
661
#if 0
662
if(eg.bulkbounds || eg.boundbounds)
663
SeparateCartesianBoundaries(&data[k],boundaries[k],info);
664
#endif
665
}
666
667
if(0) for(k=0;k<nomeshes;k++)
668
RotateTranslateScale(&data[k],&eg,info);
669
670
if(eg.removelowdim)
671
for(k=0;k<nomeshes;k++)
672
RemoveLowerDimensionalBoundaries(&data[k],boundaries[k],info);
673
674
if(eg.removeintbcs)
675
for(k=0;k<nomeshes;k++)
676
RemoveInternalBoundaries(&data[k],boundaries[k],info);
677
678
if(eg.removeunused)
679
for(k=0;k<nomeshes;k++)
680
RemoveUnusedNodes(&data[k],info);
681
682
if(eg.boundorder || eg.bcoffset)
683
for(k=0;k<nomeshes;k++)
684
RenumberBoundaryTypes(&data[k],boundaries[k],eg.boundorder,eg.bcoffset,info);
685
686
if(eg.bulkorder)
687
for(k=0;k<nomeshes;k++)
688
RenumberMaterialTypes(&data[k],boundaries[k],info);
689
690
if(eg.sidemappings || eg.bulkmappings)
691
for(k=0;k<nomeshes;k++)
692
SideAndBulkMappings(&data[k],boundaries[k],&eg,info);
693
694
if(eg.coordinatemap[0] && eg.coordinatemap[1] && eg.coordinatemap[2] ) {
695
Real *tmpcoord[3];
696
697
if(info) printf("Mapping coordinates with [%d %d %d]\n",
698
eg.coordinatemap[0],eg.coordinatemap[1],eg.coordinatemap[2]);
699
for(k=0;k<nomeshes;k++) {
700
tmpcoord[0] = data[k].x;
701
tmpcoord[1] = data[k].y;
702
tmpcoord[2] = data[k].z;
703
704
data[k].x = tmpcoord[eg.coordinatemap[0]-1];
705
data[k].y = tmpcoord[eg.coordinatemap[1]-1];
706
data[k].z = tmpcoord[eg.coordinatemap[2]-1];
707
708
if(eg.coordinatemap[2] != 3) data[k].dim = 3;
709
}
710
}
711
712
713
for(k=0;k<nomeshes;k++) {
714
int partoptim, partbcoptim, partopt, fail, partdual;
715
716
if( eg.metis == 1 ) {
717
if(info) printf("One Metis partition requested, enforcing serial mode\n");
718
eg.metis = 0;
719
}
720
721
if( eg.partitions == 1 ) {
722
if(!eg.connect) {
723
if(info) printf("One geometric partition requested, enforcing serial mode\n");
724
eg.partitions = 0;
725
}
726
}
727
728
partoptim = eg.partoptim;
729
partbcoptim = eg.partbcoptim;
730
partdual = eg.partdual;
731
732
if(eg.partitions || eg.metis) {
733
printf("\nElmergrid partitioning meshes:\n");
734
printf( "------------------------------\n");
735
timer_show();
736
737
partopt = eg.partopt;
738
739
/* Make a connected boundary needed to enforce nodes to same partitioning */
740
for(i=1;i<=eg.connect;i++)
741
SetConnectedNodes(&(data[k]),boundaries[k],eg.connectbounds[i-1],eg.connectboundsset[i-1],info);
742
743
if(eg.periodicdim[0] || eg.periodicdim[1] || eg.periodicdim[2])
744
FindPeriodicNodes(&data[k],eg.periodicdim,info);
745
746
if(eg.partitions) {
747
if( partopt == -1 ) partopt = partdual;
748
if(partopt == 0)
749
PartitionSimpleElements(&data[k],&eg,boundaries[k],eg.partdim,eg.periodicdim,
750
eg.partorder,eg.partcorder,eg.parttol,info);
751
else if(partopt == 2)
752
PartitionSimpleElementsNonRecursive(&data[k],eg.partdim,eg.periodicdim,info);
753
else if(partopt == 3)
754
PartitionSimpleElementsRotational(&data[k],eg.partdim,eg.periodicdim,info);
755
else
756
PartitionSimpleNodes(&data[k],eg.partdim,eg.periodicdim,eg.partorder,
757
eg.partcorder,eg.parttol,info);
758
}
759
#if USE_METIS
760
if(eg.metis) {
761
if( partopt < 0 || partopt > 4 ) {
762
printf("Metis optional parameter should be in range [0,4], not %d\n",partopt);
763
bigerror("Cannot perform partitioning");
764
}
765
if( partopt <= 1 && eg.connect ) {
766
printf("Elemental Metis partition cannot deal with constraints!\n");
767
printf("Using Metis algorithms based on the dual graph\n");
768
partopt = 2;
769
}
770
771
if(partopt <= 1) {
772
if(!partdual) partdual = partopt;
773
fail = PartitionMetisMesh(&data[k],&eg,eg.metis,partdual,info);
774
}
775
else {
776
PartitionMetisGraph(&data[k],boundaries[k],&eg,eg.metis,partopt,partdual,info);
777
}
778
}
779
#endif
780
if(data[k].periodicexist)
781
FindPeriodicParents(&data[k],boundaries[k],info);
782
783
timer_show();
784
/* This is the only routine that affects the ownership of elements */
785
if( partbcoptim ) {
786
OptimizePartitioningAtBoundary(&data[k],boundaries[k],info);
787
}
788
789
OptimizePartitioning(&data[k],boundaries[k],!partoptim,eg.partbw,info);
790
791
if(data[k].periodicexist) {
792
free_Ivector(data[k].periodic,1,data[k].noknots);
793
data[k].periodicexist = FALSE;
794
}
795
if(info) printf("Partitioning routines finished!\n");
796
}
797
timer_show();
798
}
799
800
if(eg.timeron) {
801
if(info) printf("Saving size info for timing purposes\n");
802
for(k=0;k<nomeshes;k++)
803
SaveSizeInfo(&data[k],boundaries[k],eg.infofile,info);
804
}
805
806
if(info) for(k=0;k<nomeshes;k++)
807
BoundingBox(&data[k],k,nomeshes,info);
808
809
if(info) for(k=0;k<nomeshes;k++)
810
MeshPieces(&data[k],k,nomeshes,info);
811
812
if(eg.nosave) {
813
Goodbye();
814
return(0);
815
}
816
817
818
/********************************/
819
printf("\nElmergrid saving data with method %d:\n",outmethod);
820
printf( "-------------------------------------\n");
821
822
823
824
switch (outmethod) {
825
case 1:
826
SaveElmergrid(grids,nogrids,eg.filesout[0],info);
827
break;
828
829
case 2:
830
for(k=0;k<nomeshes;k++) {
831
if(data[k].nopartitions > 1)
832
SaveElmerInputPartitioned(&data[k],boundaries[k],eg.filesout[k],eg.decimals,
833
eg.binary,eg.parthalo,eg.parthypre,
834
MAX(eg.partbcz,eg.partbcr),eg.nooverwrite,info);
835
else
836
SaveElmerInput(&data[k],boundaries[k],eg.filesout[k],eg.decimals,eg.binary,
837
eg.nooverwrite,info);
838
}
839
break;
840
841
case 22:
842
843
for(k=0;k<nomeshes;k++) {
844
SaveElmerInputFemBem(&data[k],boundaries[k],eg.filesout[k],eg.decimals,info);
845
}
846
break;
847
848
849
case 3:
850
/* Create a variable so that when saving data in ElmerPost format there is something to visualize */
851
for(k=0;k<nomeshes;k++) {
852
if(data[k].variables == 0) {
853
CreateVariable(&data[k],1,1,0.0,"Number",FALSE);
854
for(i=1;i<=data[k].alldofs[1];i++)
855
data[k].dofs[1][i] = (Real)(i);
856
}
857
SaveSolutionElmer(&data[k],boundaries[k],eg.saveboundaries ? MAXBOUNDARIES:0,
858
eg.filesout[k],eg.decimals,info);
859
}
860
break;
861
862
case 4:
863
for(k=0;k<nomeshes;k++) {
864
SaveMeshGmsh(&data[k],boundaries[k],eg.saveboundaries ? MAXBOUNDARIES:0,
865
eg.filesout[k],eg.decimals,info);
866
}
867
break;
868
869
case 5:
870
for(k=0;k<nomeshes;k++) {
871
SaveMeshVtu(&data[k],boundaries[k],eg.saveboundaries ? MAXBOUNDARIES:0,
872
eg.filesout[k],eg.vtuone,info);
873
}
874
break;
875
876
case 6:
877
for(k=0;k<nomeshes;k++)
878
SaveAbaqusInput(&data[k],eg.filesout[k],info);
879
break;
880
881
case 7:
882
for(k=0;k<nomeshes;k++)
883
SaveFidapOutput(&data[k],eg.filesout[k],info,1,data[k].dofs[1]);
884
break;
885
886
887
/* Some obsolete special formats related to mapping, view factors etc. */
888
889
case 101:
890
for(k=0;k<nogrids;k++) {
891
for(i=0;i<grids[k].noboundaries;i++)
892
if(boundaries[k][i].created == TRUE) {
893
sprintf(prefix,"%s%d",eg.filesout[k],i+1);
894
SaveBoundary(&data[k],&boundaries[k][i],prefix,info);
895
}
896
}
897
break;
898
899
default:
900
Instructions();
901
break;
902
}
903
904
timer_show();
905
906
Goodbye();
907
return(0);
908
}
909
910