Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmergrid/src/egexport.c
3196 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
/* --------------------: egexport.c :-------------------------- */
27
28
#include <stdio.h>
29
#include <math.h>
30
#include <stdarg.h>
31
#include <stdlib.h>
32
#include <ctype.h>
33
#include <string.h>
34
/*#include <unistd.h>*/
35
36
#include "egutils.h"
37
#include "egdef.h"
38
#include "egtypes.h"
39
#include "egmesh.h"
40
#include "egexport.h"
41
42
43
int SaveAbaqusInput(struct FemType *data,char *prefix,int info)
44
/* Saves the grid in a format that can be read by ABAQUS
45
program designed for structural mechanics.
46
The elementtype is set to be that of thermal conduction.
47
*/
48
{
49
int noknots,noelements,nonodes;
50
char filename[MAXFILESIZE];
51
int i,j;
52
FILE *out;
53
54
noknots = data->noknots;
55
noelements = data->noelements;
56
nonodes = data->maxnodes;
57
58
if(nonodes != 4 && nonodes != 8) {
59
printf("SaveAbaqusInput: not designed for %d-node elements\n",nonodes);
60
return(1);
61
}
62
63
AddExtension(prefix,filename,"inp");
64
out = fopen(filename,"w");
65
66
if(info) printf("Saving ABAQUS data to %s.\n",filename);
67
68
fprintf(out,"*HEADING\n");
69
fprintf(out,"Abaqus input file created by ElmerGrid\n");
70
71
fprintf(out,"*NODE, SYSTEM=");
72
if(data->coordsystem == COORD_CART2) fprintf(out,"R\n");
73
else if(data->coordsystem == COORD_AXIS) fprintf(out,"C\n");
74
else if(data->coordsystem == COORD_POLAR) fprintf(out,"P\n");
75
76
for(i=1; i <= noknots; i++)
77
fprintf(out,"%8d, %12.4le, %12.4le, 0.0\n",i,data->x[i],data->y[i]);
78
79
fprintf(out,"*ELEMENT,TYPE=");
80
if(nonodes == 4) fprintf(out,"DC2D4 ");
81
else if(nonodes == 8) fprintf(out,"DC2D8 ");
82
else printf("SaveAbaqusInput: Not defined for %d-node elements\n",nonodes);
83
84
fprintf(out,",ELSET=SETTI1\n");
85
for(i=1;i<=noelements;i++) {
86
fprintf(out,"%8d, ",i);
87
for(j=1;j<nonodes;j++)
88
fprintf(out,"%6d, ",data->topology[i][j-1]);
89
fprintf(out,"%6d\n",data->topology[i][nonodes-1]);
90
}
91
92
fprintf(out,"*SOLID SECTION, ELSET=SETTI1, MATERIAL=MAT1\n");
93
94
fprintf(out,"*MATERIAL, NAME=MAT1\n");
95
fprintf(out,"*CONDUCTIVITY\n");
96
fprintf(out,"1.0\n");
97
98
fprintf(out,"*RESTART, WRITE, FREQUENCY=1\n");
99
fprintf(out,"*FILE FORMAT, ASCII\n");
100
101
fprintf(out,"*STEP\n");
102
fprintf(out,"*HEAT TRANSFER, STEADY STATE\n");
103
fprintf(out,"*END STEP\n");
104
105
fclose(out);
106
107
if(info) printf("Wrote the mesh in ABAQUS restart format.\n");
108
109
return(0);
110
}
111
112
113
int SaveFidapOutput(struct FemType *data,char *prefix,int info,
114
int vctrs,Real *vect1, ...)
115
/* This procedure saves the solution in a form that is understood by
116
the CFD program Fidap. The routine that reads this file seems
117
to be stupidly place-dependent. The best manual for this
118
subroutine is provided in the appendix E of FIDAP users manual.
119
*/
120
{
121
int noknots,noelements,dim,nonodes;
122
int i,j,no,nogroup,material,cellelem;
123
int elemcodes[MAT_MAXNUMBER+1],mat[MAT_MAXNUMBER+1];
124
FILE *out;
125
Real *dofs[MAXDOFS];
126
char filename[MAXFILESIZE];
127
va_list ap;
128
129
if(!data->created) {
130
printf("You tried to save points that were never created.\n");
131
return(1);
132
}
133
134
printf("Saving results in FIDAP neutral format.\n");
135
136
noknots = data->noknots;
137
noelements = data->noelements;
138
dim = data->dim;
139
140
if(vctrs > 3) {
141
printf("SaveSolutionFidap: Maximum of 3 d.o.f.\n");
142
vctrs = 3;
143
}
144
145
/* Read the list of pointers to vectors to be saved. */
146
if(vctrs > 0) {
147
va_start(ap,vect1);
148
dofs[1] = vect1;
149
for(i=2;i<=vctrs;i++)
150
dofs[i] = va_arg(ap,Real*);
151
va_end(ap);
152
}
153
154
/* Create groups by placing the same materials to same groups. */
155
nogroup = 0;
156
for(i=1;i<=MAT_MAXNUMBER;i++)
157
elemcodes[i] = mat[i] = 0;
158
for(j=1;j <= noelements;j++) {
159
material = data->material[j];
160
if(material > 0 && material<=MAT_MAXNUMBER) mat[material] += 1;
161
elemcodes[material] = data->elementtypes[j];
162
}
163
for(i=1;i<=MAT_MAXNUMBER;i++)
164
if(mat[i] > 0) nogroup++;
165
166
AddExtension(prefix,filename,"fidap");
167
out = fopen(filename,"w");
168
169
/* Control information */
170
fprintf(out,"** FIDAP NEUTRAL FILE\n");
171
fprintf(out,"Fidap input file created by ElmerGrid\n");
172
fprintf(out,"VERSION %7.2f\n",7.52); /* Fidap version */
173
fprintf(out," 1 Dec 96 12:00:00\n");
174
fprintf(out,"%15s%15s%15s%15s%15s\n","NO. OF NODES",
175
"NO. ELEMENTS","NO. ELT GROUPS","NDFCD","NDFVL");
176
fprintf(out,"%15d%15d%15d%15d%15d\n",noknots,noelements,nogroup,dim,dim);
177
fprintf(out,"%15s%15s%15s%15s\n",
178
"STEADY/TRANS","TURB. FLAG","FREE SURF FLAG","COMPR. FLAG");
179
fprintf(out,"%15d%15d%15d%15d\n",0,0,0,0);
180
fprintf(out,"%s\n","TEMPERATURE/SPECIES FLAGS");
181
fprintf(out,"%s\n"," 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0");
182
fprintf(out,"%s\n","PRESSURE FLAGS - IDCTS, IPENY MPDF");
183
fprintf(out,"%10d%10d%10d\n",0,0,1);
184
185
fprintf(out,"NODAL COORDINATES\n");
186
for(i=1; i <= noknots; i++)
187
fprintf(out,"%10d%20.10e%20.10e\n",i,data->y[i],data->x[i]);
188
189
/* Boundary and initial conditions */
190
fprintf(out,"BOUNDARY CONDITIONS\n");
191
fprintf(out,"%10d%10d%10d%20.10e\n",0,0,5,0.0);
192
193
fprintf(out,"ELEMENT GROUPS\n");
194
nogroup = 0;
195
for(no=1;no<=MAT_MAXNUMBER;no++)
196
if(mat[no] > 0) {
197
nonodes = elemcodes[no]%100;
198
nogroup++;
199
cellelem = mat[no];
200
fprintf(out,"GROUP: %5d ELEMENTS:%10d NODES: %10d GEOMETRY:%5d TYPE:%4d\n",
201
nogroup,cellelem,nonodes,1,1);
202
fprintf(out,"ENTITY NAME: %s%d\n","material",nogroup);
203
204
for(j=1;j <= noelements;j++) {
205
if(data->material[j] == no) {
206
fprintf(out,"%8d\n",j);
207
for(i=0;i < nonodes;i++)
208
fprintf(out,"%8d",data->topology[j][i]);
209
fprintf(out,"\n");
210
}
211
}
212
}
213
214
fprintf(out,"TIMESTEP: %5d TIME: %15.7le INCRMNT: %15.7le\n",1,1.0,1.0);
215
216
fprintf(out,"VELOCITY\n");
217
if(vctrs < 2)
218
for(i=1;i<=2*noknots;i++) {
219
fprintf(out,"%16.9e",0.0);
220
if(i%5==0) fprintf(out,"\n");
221
}
222
else
223
for(i=1;i<=2*noknots;i++) {
224
fprintf(out,"%16.9e",dofs[1][i]);
225
if((2*i-1)%5 == 0) fprintf(out,"\n");
226
fprintf(out,"%16.9e",dofs[2][i]);
227
if((2*i)%5 == 0) fprintf(out,"\n");
228
}
229
if((2*noknots)%5 != 0) fprintf(out,"\n");
230
231
fprintf(out,"TEMPERATURE\n");
232
233
if(vctrs == 2)
234
for(i=1;i<=noknots;i++) {
235
fprintf(out,"%16.9e",0.0);
236
if(i%5==0) fprintf(out,"\n");
237
}
238
else
239
for(i=1;i<=noknots;i++) {
240
fprintf(out,"%16.9e",dofs[vctrs][i]);
241
if(i%5==0) fprintf(out,"\n");
242
}
243
if(noknots%5 != 0) fprintf(out,"\n");
244
fprintf(out,"ENDOFTIMESTEP\n");
245
246
fclose(out);
247
if(info) printf("Results were saved in FIDAP neutral format to file %s.\n",filename);
248
249
return(0);
250
}
251
252
253
254
static int ElmerToGmshType(int elmertype)
255
{
256
int gmshtype = 0;
257
258
switch (elmertype) {
259
260
case 202:
261
gmshtype = 1;
262
break;
263
case 303:
264
gmshtype = 2;
265
break;
266
case 404:
267
gmshtype = 3;
268
break;
269
case 504:
270
gmshtype = 4;
271
break;
272
case 808:
273
gmshtype = 5;
274
break;
275
case 706:
276
gmshtype = 6;
277
break;
278
case 605:
279
gmshtype = 7;
280
break;
281
case 203:
282
gmshtype = 8;
283
break;
284
case 306:
285
gmshtype = 9;
286
break;
287
case 409:
288
gmshtype = 10;
289
break;
290
case 510:
291
gmshtype = 11;
292
break;
293
case 827:
294
gmshtype = 12;
295
break;
296
case 101:
297
gmshtype = 15;
298
break;
299
case 408:
300
gmshtype = 16;
301
break;
302
case 820:
303
gmshtype = 17;
304
break;
305
case 715:
306
gmshtype = 18;
307
break;
308
case 613:
309
gmshtype = 19;
310
break;
311
case 310:
312
gmshtype = 21;
313
break;
314
315
default:
316
printf("Elmer element %d does not have an Gmsh counterpart!\n",elmertype);
317
}
318
319
return(gmshtype);
320
}
321
322
323
324
325
static void ElmerToGmshIndx(int elemtype,int *topology)
326
{
327
int i=0,nodes=0,oldtopology[MAXNODESD2];
328
int reorder, *porder;
329
330
int order510[]={0,1,2,3,4,5,6,7,9,8};
331
int order613[]={0,1,2,3,4,5,8,10,6,7,9,11,12};
332
int order715[]={0,1,2,3,4,5,6,9,7,8,10,11,12,14,13};
333
int order820[]={0,1,2,3,4,5,6,7,8,11,12,9,10,12,14,15,16,18,19,17};
334
335
336
reorder = FALSE;
337
338
switch (elemtype) {
339
340
case 510:
341
reorder = TRUE;
342
porder = &order510[0];
343
break;
344
345
case 613:
346
reorder = TRUE;
347
porder = &order613[0];
348
break;
349
350
case 715:
351
reorder = TRUE;
352
porder = &order715[0];
353
break;
354
355
case 820:
356
reorder = TRUE;
357
porder = &order820[0];
358
break;
359
360
}
361
362
if( reorder ) {
363
nodes = elemtype % 100;
364
for(i=0;i<nodes;i++)
365
oldtopology[i] = topology[i];
366
for(i=0;i<nodes;i++)
367
topology[porder[i]] = oldtopology[i];
368
}
369
}
370
371
372
373
int SaveMeshGmsh(struct FemType *data,struct BoundaryType *bound,
374
int nobound,char *prefix,int decimals,int info)
375
/* This procedure saves the mesh in a format understood by Gmsh */
376
{
377
int material,noknots,noelements,bulkelems,sideelems,gmshtype,elemtype,boundtype;
378
int usedbody[MAXBODIES],usedbc[MAXBCS],nonames,physent;
379
char filename[MAXFILESIZE],outstyle[MAXFILESIZE];
380
int i,j,k,nodesd2,elemind;
381
int ind[MAXNODESD2];
382
FILE *out;
383
384
if(!data->created) {
385
printf("SaveMeshGmsh: You tried to save points that were never created.\n");
386
return(1);
387
}
388
389
/* Compute the number of boundary elements and register the minimum BC type */
390
sideelems = 0;
391
if(nobound) {
392
for(j=0;j<nobound;j++) {
393
if(bound[j].created)
394
sideelems += bound[j].nosides;
395
}
396
if(0) printf("number of boundary elements: %d\n",sideelems);
397
}
398
399
noknots = data->noknots;
400
bulkelems = data->noelements;
401
if(nobound)
402
noelements = bulkelems + sideelems;
403
else
404
noelements = bulkelems;
405
406
AddExtension(prefix,filename,"msh");
407
if(info) printf("Saving Gmsh mesh to %s.\n",filename);
408
409
out = fopen(filename,"w");
410
if(out == NULL) {
411
printf("opening of file was not successful\n");
412
return(3);
413
}
414
415
fprintf(out,"$MeshFormat\n");
416
fprintf(out,"2.2 0 %ld\n",sizeof(double));
417
fprintf(out,"$EndMeshFormat\n");
418
419
if(data->bodynamesexist || data->boundarynamesexist) {
420
for(i=0;i<MAXBODIES;i++)
421
usedbody[i] = 0;
422
for(i=0;i<MAXBCS;i++)
423
usedbc[i] = 0;
424
425
fprintf(out,"$PhysicalNames\n");
426
nonames = 0;
427
if(data->boundarynamesexist) {
428
for(j=0;j < MAXBOUNDARIES;j++) {
429
if(!bound[j].created) continue;
430
if(!bound[j].nosides) continue;
431
for(i=1; i <= bound[j].nosides; i++) {
432
GetBoundaryElement(i,&bound[j],data,ind,&elemtype);
433
k = bound[j].types[i];
434
if(k < MAXBCS) usedbc[k] = GetElementDimension(elemtype);
435
}
436
}
437
for(i=1;i<MAXBCS;i++)
438
if(data->boundaryname[i] && usedbc[i]) nonames++;
439
}
440
if(data->bodynamesexist) {
441
for(i=1;i<=noelements;i++) {
442
elemtype = data->elementtypes[i];
443
k = data->material[i];
444
if(k < MAXBODIES) usedbody[k] = GetElementDimension(elemtype);
445
}
446
for(i=1;i<MAXBODIES;i++)
447
if(data->bodyname[i] && usedbody[i]) nonames++;
448
}
449
fprintf(out,"%d\n",nonames);
450
if(data->boundarynamesexist) {
451
for(i=1;i<MAXBCS;i++) {
452
if(data->boundaryname[i] && usedbc[i])
453
fprintf(out,"%d %d \"%s\"\n",usedbc[i],i,data->boundaryname[i]);
454
}
455
}
456
if(data->bodynamesexist) {
457
for(i=1;i<MAXBODIES;i++) {
458
if(data->bodyname[i] && usedbody[i])
459
fprintf(out,"%d %d \"%s\"\n",usedbody[i],i,data->bodyname[i]);
460
}
461
}
462
fprintf(out,"$EndPhysicalNames\n");
463
}
464
465
if(info) printf("Saving %d node coordinates.\n",noknots);
466
fprintf(out,"$Nodes\n");
467
fprintf(out,"%d\n",noknots);
468
if(data->dim == 1) {
469
sprintf(outstyle,"%%d %%.%dg 0 0\n",decimals);
470
for(i=1; i <= noknots; i++)
471
fprintf(out,outstyle,i,data->x[i]);
472
}
473
else if(data->dim == 2) {
474
sprintf(outstyle,"%%d %%.%dg %%.%dg 0\n",decimals,decimals);
475
for(i=1; i <= noknots; i++)
476
fprintf(out,outstyle,i,data->x[i],data->y[i]);
477
}
478
else if(data->dim == 3) {
479
sprintf(outstyle,"%%d %%.%dg %%.%dg %%.%dg\n",decimals,decimals,decimals);
480
for(i=1; i <= noknots; i++)
481
fprintf(out,outstyle,i,data->x[i],data->y[i],data->z[i]);
482
}
483
fprintf(out,"$EndNodes\n");
484
485
486
printf("Saving %d element topologies.\n",bulkelems);
487
488
fprintf(out,"$Elements\n");
489
fprintf(out,"%d\n",bulkelems+sideelems);
490
for(i=1;i<=bulkelems;i++) {
491
elemtype = data->elementtypes[i];
492
material = data->material[i];
493
494
gmshtype = ElmerToGmshType( elemtype );
495
496
physent = 0;
497
if(data->bodynamesexist && material<MAXBODIES)
498
if(data->bodyname[material] && usedbody[material]) physent = material;
499
fprintf(out,"%d %d %d %d %d",i,gmshtype,2,physent,material);
500
501
nodesd2 = data->elementtypes[i]%100;
502
503
for(j=0;j<nodesd2;j++)
504
ind[j] = data->topology[i][j];
505
506
ElmerToGmshIndx(elemtype,ind);
507
508
for(j=0;j<nodesd2;j++)
509
fprintf(out," %d",ind[j]);
510
fprintf(out,"\n");
511
}
512
513
elemind = bulkelems;
514
if(nobound) {
515
for(j=0;j<nobound;j++) {
516
if(bound[j].created == FALSE) continue;
517
518
for(i=1;i<=bound[j].nosides;i++) {
519
520
GetBoundaryElement(i,&bound[j],data,ind,&elemtype);
521
boundtype = bound[j].types[i];
522
523
gmshtype = ElmerToGmshType( elemtype );
524
elemind += 1;
525
526
physent = 0;
527
if(data->boundarynamesexist && boundtype<MAXBCS)
528
if(data->boundaryname[boundtype] && usedbc[boundtype]) physent = boundtype;
529
fprintf(out,"%d %d %d %d %d",elemind,gmshtype,2,physent,boundtype);
530
nodesd2 = elemtype%100;
531
532
ElmerToGmshIndx(elemtype,ind);
533
534
for(k=0;k<nodesd2;k++)
535
fprintf(out," %d",ind[k]);
536
fprintf(out,"\n");
537
}
538
}
539
}
540
fprintf(out,"$EndElements\n");
541
542
543
#if 0
544
timesteps = data->timesteps;
545
if(timesteps < 1) timesteps = 1;
546
547
if(data->variables == 0) {
548
printf("SaveMeshGmsh: there are no dofs to save!\n");
549
return(2);
550
}
551
552
novctrs = 0;
553
for(i=0;i<MAXDOFS;i++) {
554
if(data->edofs[i] == 1) novctrs += 1;
555
if(data->edofs[i] == 2) novctrs += 3;
556
if(data->edofs[i] == 3) novctrs += 3;
557
}
558
559
if(data->partitionexist) {
560
l = 0;
561
do l++; while (data->edofs[l]);
562
CreateVariable(data,l,1,0.0,"Partition",FALSE);
563
rpart = data->dofs[l];
564
for(i=1;i<=data->noknots;i++)
565
rpart[i] = 1.0 * data->nodepart[i];
566
}
567
568
for(i=0; i<MAXDOFS; i++) {
569
if(data->edofs[i] == 1)
570
fprintf(out," scalar: %s",data->dofname[i]);
571
else if(data->edofs[i] > 1)
572
fprintf(out," vector: %s",data->dofname[i]);
573
}
574
fprintf(out,"\n");
575
576
printf("Saving %d degrees of freedom for each knot.\n",novctrs);
577
for(k=0;k<timesteps;k++) {
578
for(i=1;i<=noknots;i++){
579
for(j=0;j<MAXDOFS;j++) {
580
if(data->edofs[j] == 1)
581
fprintf(out,"%.6lg ",data->dofs[j][k*noknots+i]);
582
if(data->edofs[j] == 2)
583
fprintf(out,"%.6lg %.6lg 0.0 ",
584
data->dofs[j][2*(k*noknots+i)-1],data->dofs[j][2*(k*noknots+i)]);
585
if(data->edofs[j] == 3)
586
fprintf(out,"%.6lg %.6lg %.6lg ",
587
data->dofs[j][3*(k*noknots+i)-2],
588
data->dofs[j][3*(k*noknots+i)-1],
589
data->dofs[j][3*(k*noknots+i)]);
590
}
591
fprintf(out,"\n");
592
}
593
}
594
#endif
595
596
fclose(out);
597
598
printf("SaveMeshGmsh: All done\n");
599
600
return(0);
601
}
602
603
604
static int ElmerToVtkType(int elmertype)
605
{
606
int vtktype = 0;
607
608
switch (elmertype) {
609
610
case 101:
611
vtktype = 1;
612
case 202:
613
vtktype = 3;
614
break;
615
case 203:
616
vtktype = 21;
617
break;
618
case 204:
619
vtktype = 35;
620
break;
621
case 303:
622
vtktype = 5;
623
break;
624
case 306:
625
vtktype = 22;
626
break;
627
case 310:
628
vtktype = 69;
629
break;
630
case 404:
631
vtktype = 9;
632
break;
633
case 408:
634
vtktype = 23;
635
break;
636
case 409:
637
vtktype = 28;
638
break;
639
case 416:
640
vtktype = 70;
641
break;
642
case 504:
643
vtktype = 10;
644
break;
645
case 510:
646
vtktype = 24;
647
break;
648
case 605:
649
vtktype = 14;
650
break;
651
case 613:
652
vtktype = 27;
653
break;
654
case 706:
655
vtktype = 13;
656
break;
657
case 715:
658
vtktype = 26;
659
break;
660
case 808:
661
vtktype = 12;
662
break;
663
case 820:
664
vtktype = 25;
665
break;
666
case 827:
667
vtktype = 29;
668
break;
669
670
default:
671
printf("Elmer element %d does not have an Vtk counterpart!\n",elmertype);
672
}
673
674
return(vtktype);
675
}
676
677
678
679
static void ElmerToVtkIndx(int elemtype,int *topology)
680
{
681
int i=0,nodes=0,oldtopology[MAXNODESD2];
682
int reorder, *porder;
683
684
int order820[]={0,1,2,3,4,5,6,7,8,9,10,11,16,17,18,19,12,13,14,15};
685
int order827[]={0,1,2,3,4,5,6,7,8,9,10,11,16,17,18,19,12,13,14,15,23,21,20,22,24,25,26};
686
687
reorder = FALSE;
688
689
switch (elemtype) {
690
691
case 820:
692
reorder = TRUE;
693
porder = &order820[0];
694
break;
695
696
case 827:
697
reorder = TRUE;
698
porder = &order827[0];
699
break;
700
}
701
702
if( reorder ) {
703
nodes = elemtype % 100;
704
for(i=0;i<nodes;i++)
705
oldtopology[i] = topology[i];
706
for(i=0;i<nodes;i++)
707
topology[i] = oldtopology[porder[i]];
708
}
709
}
710
711
712
713
int SaveMeshVtu(struct FemType *data,struct BoundaryType *bound,
714
int nobound,char *prefix,int dummyzero,int info)
715
/* This procedure saves the mesh in the VTU format understood by Paraview and Visit, for example. */
716
{
717
int material,noknots,noelements,bulkelems,sideelems,vtktype,elemtype,boundtype;
718
char filename[MAXFILESIZE],outstyle[MAXFILESIZE];
719
int i,j,k,nodesd2,elemind,idoffset,di,maxbody,minbc;
720
int ind[MAXNODESD2];
721
int LittleEnd,PrecBits,elemoffset;
722
FILE *out;
723
724
/* If we create dummy zero node the real indexes start from one */
725
if( dummyzero )
726
di = 0;
727
else
728
di = 1;
729
730
731
if(!data->created) {
732
printf("SaveMeshVtk: You tried to save points that were never created.\n");
733
return(1);
734
}
735
736
/* Compute the number of boundary elements and register the minimum BC type */
737
sideelems = 0;
738
if(nobound) {
739
for(j=0;j<nobound;j++) {
740
if(bound[j].created)
741
sideelems += bound[j].nosides;
742
}
743
if(0) printf("number of boundary elements: %d\n",sideelems);
744
}
745
746
noknots = data->noknots;
747
bulkelems = data->noelements;
748
if(nobound)
749
noelements = bulkelems + sideelems;
750
else
751
noelements = bulkelems;
752
753
AddExtension(prefix,filename,"vtu");
754
if(info) printf("Saving VTU mesh to %s.\n",filename);
755
756
out = fopen(filename,"w");
757
if(out == NULL) {
758
printf("opening of file was not successful\n");
759
return(3);
760
}
761
762
maxbody = 0;
763
for(i=1;i<=bulkelems;i++)
764
maxbody = MAX( maxbody, data->material[i] );
765
minbc = 0;
766
for(j=0;j<nobound;j++) {
767
if(bound[j].created == FALSE) continue;
768
for(i=1;i<=bound[j].nosides;i++) {
769
boundtype = bound[j].types[i];
770
if( minbc == 0 )
771
minbc = boundtype;
772
else
773
minbc = MIN( minbc, boundtype );
774
}
775
}
776
777
idoffset = 0;
778
if( minbc !=0 && minbc <= maxbody ) {
779
idoffset = 100;
780
for(;;) {
781
if(maxbody > idoffset )
782
idoffset *= 10;
783
else
784
break;
785
}
786
printf("Setting offset for boundaries: %d\n",idoffset);
787
}
788
789
790
791
LittleEnd = FALSE;
792
PrecBits = 64; /* 32 for single precision */
793
794
795
if(info) printf("Saving Elmer mesh in ascii VTU format\n");
796
fprintf(out,"<?xml version=\"1.0\"?>\n");
797
if( LittleEnd )
798
fprintf(out,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n");
799
else
800
fprintf(out,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"BigEndian\">\n");
801
802
fprintf(out," <UnstructuredGrid>\n");
803
fprintf(out," <Piece NumberOfPoints=\"%d\" NumberOfCells=\"%d\">\n",noknots+dummyzero,noelements);
804
805
/* Write out the nodal indexes, this is mainly just on example */
806
fprintf(out," <PointData>\n");
807
if(0) { /* Here we as as floats - just for testing */
808
fprintf(out," <DataArray type=\"Float%d\" Name=\"NodeNumber\" NumberOfComponents=\"1\" format=\"ascii\">\n",PrecBits);
809
if( dummyzero ) fprintf(out,"%12.6le ",0.0);
810
for(i=1;i<=noknots;i++) fprintf(out,"%12.6le ",1.0*i);
811
}
812
else { /* And here as integers - what they really are */
813
fprintf(out," <DataArray type=\"Int32\" Name=\"NodeNumber\" NumberOfComponents=\"1\" format=\"ascii\">\n");
814
if( dummyzero ) fprintf(out,"%d ",0);
815
for(i=1;i<=noknots;i++) fprintf(out,"%d ",i);
816
}
817
fprintf(out,"\n");
818
fprintf(out," </DataArray>\n");
819
fprintf(out," </PointData>\n");
820
821
822
printf("Saving cell data (Element numbers and Geometry Ids).\n");
823
fprintf(out," <CellData>\n");
824
/* Write out the element indexes, this is mainly just on example */
825
if(0) { /* This as floats - just for testing */
826
fprintf(out," <DataArray type=\"Float%d\" Name=\"ElementNumber\" NumberOfComponents=\"1\" format=\"ascii\">\n",PrecBits);
827
for(i=1;i<=noelements;i++)
828
fprintf(out,"%12.6le ",1.0*i);
829
fprintf(out,"\n");
830
fprintf(out," </DataArray>\n");
831
}
832
else { /* This as integers - what they are */
833
fprintf(out," <DataArray type=\"Int32\" Name=\"ElementNumber\" NumberOfComponents=\"1\" format=\"ascii\">\n");
834
for(i=1;i<=noelements;i++)
835
fprintf(out,"%d ",i);
836
fprintf(out,"\n");
837
fprintf(out," </DataArray>\n");
838
}
839
840
/* Write out the geometry Ids */
841
fprintf(out," <DataArray type=\"Int32\" Name=\"GeometryIds\" NumberOfComponents=\"1\" format=\"ascii\">\n");
842
for(i=1;i<=bulkelems;i++)
843
fprintf(out,"%d ",data->material[i]);
844
845
if(nobound ) {
846
for(j=0;j<nobound;j++) {
847
if(bound[j].created == FALSE) continue;
848
for(i=1;i<=bound[j].nosides;i++) {
849
boundtype = bound[j].types[i];
850
fprintf(out,"%d ",idoffset + bound[j].types[i]);
851
}
852
}
853
}
854
fprintf(out,"\n");
855
fprintf(out," </DataArray>\n");
856
857
858
/* Write out the geometry Ids */
859
if(data->partitionexist) {
860
fprintf(out," <DataArray type=\"Int32\" Name=\"Partition\" NumberOfComponents=\"1\" format=\"ascii\">\n");
861
for(i=1;i<=bulkelems;i++)
862
fprintf(out,"%d ",data->elempart[i]);
863
864
if(nobound ) {
865
for(j=0;j<nobound;j++) {
866
if(bound[j].created == FALSE) continue;
867
for(i=1;i<=bound[j].nosides;i++) {
868
k = bound[j].parent[i];
869
if(k)
870
fprintf(out,"%d ",data->elempart[k]);
871
else
872
fprintf(out,"%d ",0);
873
}
874
}
875
}
876
fprintf(out,"\n");
877
fprintf(out," </DataArray>\n");
878
}
879
880
fprintf(out," </CellData>\n");
881
882
883
if(info) printf("Saving %d nodal coordinates\n",noknots);
884
fprintf(out," <Points>\n");
885
fprintf(out," <DataArray type=\"Float%d\" Name=\"ElementNumber\" NumberOfComponents=\"3\" format=\"ascii\">\n",PrecBits);
886
if( dummyzero ) {
887
if(info) printf("Creating dummy duplicate for first index to allow numbering from one\n");
888
fprintf(out,"%12.6le %12.6le %12.6le ",data->x[1],data->y[1],data->z[1]);
889
}
890
for(i=1;i<=noknots;i++)
891
fprintf(out,"%12.6le %12.6le %12.6le ",data->x[i],data->y[i],data->z[i]);
892
fprintf(out,"\n");
893
fprintf(out," </DataArray>\n");
894
fprintf(out," </Points>\n");
895
896
897
printf("Saving %d element topologies.\n",noelements);
898
fprintf(out," <Cells>\n");
899
900
901
fprintf(out," <DataArray type=\"Int32\" Name=\"connectivity\" NumberOfComponents=\"1\" format=\"ascii\">\n");
902
for(i=1;i<=bulkelems;i++) {
903
elemtype = data->elementtypes[i];
904
for(j=0;j<elemtype%100;j++)
905
ind[j] = data->topology[i][j];
906
ElmerToVtkIndx( elemtype, ind );
907
for(j=0;j<elemtype%100;j++)
908
fprintf(out,"%d ",ind[j]-di);
909
}
910
if(nobound ) {
911
for(j=0;j<nobound;j++) {
912
if(bound[j].created == FALSE) continue;
913
for(i=1;i<=bound[j].nosides;i++) {
914
/*GetElementSide(elemind2,side,1,data,&sideind2[0],&sideelemtype2); */
915
GetBoundaryElement(i,&bound[j],data,ind,&elemtype);
916
for(k=0;k<elemtype%100;k++)
917
fprintf(out,"%d ",ind[k]-di);
918
}
919
}
920
}
921
fprintf(out,"\n");
922
fprintf(out," </DataArray>\n");
923
924
925
fprintf(out," <DataArray type=\"Int32\" Name=\"offsets\" NumberOfComponents=\"1\" format=\"ascii\">\n");
926
elemoffset = 0;
927
for(i=1;i<=bulkelems;i++) {
928
elemtype = data->elementtypes[i];
929
elemoffset += elemtype % 100;
930
fprintf(out,"%d ",elemoffset );
931
}
932
if(nobound ) {
933
for(j=0;j<nobound;j++) {
934
if(bound[j].created == FALSE) continue;
935
for(i=1;i<=bound[j].nosides;i++) {
936
GetBoundaryElement(i,&bound[j],data,ind,&elemtype);
937
elemoffset += elemtype % 100;
938
fprintf(out,"%d ",elemoffset );
939
}
940
}
941
}
942
fprintf(out,"\n");
943
fprintf(out," </DataArray>\n");
944
945
946
fprintf(out," <DataArray type=\"Int32\" Name=\"types\" NumberOfComponents=\"1\" format=\"ascii\">\n");
947
for(i=1;i<=bulkelems;i++) {
948
elemtype = data->elementtypes[i];
949
vtktype = ElmerToVtkType( elemtype );
950
fprintf(out,"%d ",vtktype );
951
}
952
if(nobound ) {
953
for(j=0;j<nobound;j++) {
954
if(bound[j].created == FALSE) continue;
955
for(i=1;i<=bound[j].nosides;i++) {
956
GetBoundaryElement(i,&bound[j],data,ind,&elemtype);
957
vtktype = ElmerToVtkType( elemtype );
958
fprintf(out,"%d ",vtktype );
959
}
960
}
961
}
962
fprintf(out,"\n");
963
fprintf(out," </DataArray>\n");
964
965
966
fprintf(out," </Cells>\n");
967
fprintf(out," </Piece>\n");
968
fprintf(out," </UnstructuredGrid>\n");
969
fprintf(out,"</VTKFile>\n");
970
971
fclose(out);
972
973
if(info) printf("Saving of Elmer mesh to VTK format finished\n");
974
975
return(0);
976
}
977
978
979