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