Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmergrid/src/egextra.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
/* --------------------: egextra.c :--------------------------
27
28
These functions provide the user of the program information
29
about how the mesh was created and what the resulting sparse
30
matrix will be alike and also present the results of the
31
calculations in various ways. These subroutines don't affect
32
the operation and results of the program and can thus be
33
omitted if not needed.
34
*/
35
36
#include <stdio.h>
37
#include <stddef.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <ctype.h>
41
#include <float.h>
42
#include <math.h>
43
#include <stdarg.h>
44
#include <limits.h>
45
#include <unistd.h>
46
#include <sys/stat.h>
47
48
#include "egutils.h"
49
#include "egdef.h"
50
#include "egtypes.h"
51
#include "egmesh.h"
52
#include "egnative.h"
53
#include "egextra.h"
54
#include "egparallel.h"
55
56
57
#define GETLINE ioptr=fgets(line,MAXLINESIZE,in)
58
static char *ioptr;
59
60
61
int SaveCellInfo(struct GridType *grid,struct CellType *cell,
62
char *prefix,int info)
63
/* Save some (int) values for each cell in structure CellType.
64
The resulting matrix may be used to check that the division to
65
subcells is as wanted.
66
*/
67
{
68
int i;
69
FILE *out;
70
char filename[MAXFILESIZE];
71
72
AddExtension(prefix,filename,"cell");
73
out = fopen(filename,"w");
74
75
fprintf(out,"%-6s %-6s %-6s %-6s %-6s %-6s %-6s %-6s %-6s\n",
76
"1st","2nd","last","level","center","mat","xlin","ylin","num");
77
for(i=1;i<=grid->nocells;i++) {
78
fprintf(out,"%-6d %-6d %-6d %-6d %-6d %-6d %-6d %-6d %-6d\n",
79
cell[i].left1st,cell[i].left2nd,cell[i].leftlast,
80
cell[i].levelwidth,cell[i].leftcenter,
81
cell[i].material,cell[i].xlinear,cell[i].ylinear,cell[i].numbering);
82
}
83
fclose(out);
84
85
if(info) printf("The cell information was saved to file %s.\n",filename);
86
87
return(0);
88
}
89
90
91
92
int SaveBoundary(struct FemType *data,struct BoundaryType *bound,
93
char *prefix,int info)
94
/* This function saves the given boundary to an ascii-file.
95
The data is saved in format [x1 x2 y1 y2 v1 v2].
96
*/
97
{
98
int i,k,sideelemtype;
99
FILE *out;
100
char filename[MAXFILESIZE];
101
int sideind[MAXNODESD1];
102
103
if(!bound->created) {
104
printf("SaveBoundary: You tried to save a nonexistent boundary.\n");
105
return(1);
106
}
107
if(bound->nosides == 0) return(0);
108
109
AddExtension(prefix,filename,"bound");
110
out = fopen(filename,"w");
111
112
for(i=1; i <= bound->nosides; i++) {
113
114
GetElementSide(bound->parent[i],bound->side[i],bound->normal[i],data,sideind,&sideelemtype);
115
116
fprintf(out,"%-12.4le %-12.4le %-12.4le %-12.4le\n",
117
data->x[sideind[0]],data->x[sideind[1]],
118
data->y[sideind[0]],data->y[sideind[1]]);
119
}
120
121
fclose(out);
122
123
if(info) printf("Boundary information was saved to file %s.\n",filename);
124
125
return(0);
126
}
127
128
129
int CreateBoundaryChain(struct FemType *data,struct BoundaryType *bound,int info)
130
{
131
int i,sideind[MAXNODESD1],sideind2[MAXNODESD1];
132
int size,indfirst,indsecond,side,setchain,sideelemtype;
133
134
if(bound->created == FALSE) {
135
if(info) printf("CreateBoundaryChain: boundary not created!\n");
136
return(1);
137
}
138
if(bound->nosides < 2) {
139
if(info) printf("CreateBoundaryChain: there must be at least 2 sides!\n");
140
return(2);
141
}
142
if(bound->echain == TRUE) {
143
if(0) printf("CreateBoundaryChain: chain already exists!\n");
144
return(3);
145
}
146
147
setchain = FALSE;
148
restart:
149
/* First determine the way that the chain starts. */
150
GetElementSide(bound->parent[1],bound->side[1],bound->normal[1],data,sideind,&sideelemtype);
151
GetElementSide(bound->parent[2],bound->side[2],bound->normal[2],data,sideind2,&sideelemtype);
152
if(sideind[1] == sideind2[0]) {
153
indfirst = sideind[0];
154
indsecond = sideind[1];
155
}
156
else if(sideind[0] == sideind2[1]) {
157
indfirst = sideind[1];
158
indsecond = sideind[0];
159
}
160
else {
161
printf("CreateBoundaryChain: Impossible case!\n");
162
indfirst = sideind[0];
163
indsecond = sideind[1];
164
}
165
166
if(setchain) {
167
bound->chain[0] = indfirst;
168
bound->chain[1] = indsecond;
169
}
170
size = 1;
171
side = 1;
172
173
/* The chain is followed in positive direction while successful,
174
if not the direction is changed and so on... */
175
for(;;) {
176
for(i=side+1;i<=bound->nosides;i++) {
177
GetElementSide(bound->parent[i],bound->side[i],bound->normal[i],data,sideind,&sideelemtype);
178
if(sideind[0] == indsecond) {
179
indsecond = sideind[1];
180
goto jump;
181
}
182
else if(sideind[1] == indsecond) {
183
indsecond = sideind[0];
184
goto jump;
185
}
186
}
187
188
for(i=side-1;i>=1;i--) {
189
GetElementSide(bound->parent[i],bound->side[i],bound->normal[i],data,sideind,&sideelemtype);
190
if(sideind[0] == indsecond) {
191
indsecond = sideind[1];
192
goto jump;
193
}
194
else if(sideind[1] == indsecond) {
195
indsecond = sideind[0];
196
goto jump;
197
}
198
}
199
goto theend;
200
201
jump:
202
size++;
203
if(setchain)
204
bound->chain[size] = indsecond;
205
side = i;
206
if(indsecond == indfirst) goto theend;
207
}
208
209
theend:
210
if(setchain == FALSE) {
211
if(size != bound->nosides)
212
printf("CreateBoundaryChain: the boundary is not continuous (%d vs. %d)\n",
213
size,bound->nosides);
214
else
215
printf("CreateBoundaryChain: the boundary is continuous with %d nodes.\n",size+1);
216
bound->chain = Ivector(0,size);
217
bound->echain = TRUE;
218
bound->chainsize = size;
219
setchain = TRUE;
220
goto restart;
221
}
222
return(0);
223
}
224
225
226
int SaveBoundariesChain(struct FemType *data,struct BoundaryType *bound,
227
char *prefix,int info)
228
/* This function saves the given boundary to an ascii-file.
229
The data is saved in format [x y v].
230
This may be used particularly for boundaries that
231
are continues i.e. the element sides constitute a full chain.
232
*/
233
{
234
int i,j,k,ind,length,col;
235
FILE *out;
236
char filename[MAXFILESIZE];
237
char filename2[MAXFILESIZE];
238
239
for(j=0;j<MAXBOUNDARIES;j++)
240
if(bound[j].created && bound[j].nosides >0) {
241
242
CreateBoundaryChain(data,&bound[j],info);
243
length = bound[j].chainsize;
244
if(length < 2) continue;
245
246
sprintf(filename,"%s%d%s",prefix,j,".side");
247
out = fopen(filename,"w");
248
249
for(i=0;i<=length;i++) {
250
ind = bound[j].chain[i];
251
fprintf(out,"%-10.4le %-10.4le %-6d ",
252
data->x[ind],data->y[ind],ind);
253
for(k=0;k<MAXDOFS;k++) {
254
if(data->edofs[k] == 1)
255
fprintf(out,"%-10.4le ",data->dofs[k][ind]);
256
if(data->edofs[k] == 2)
257
fprintf(out,"%-10.4le %-10.4le ",
258
data->dofs[k][2*ind-1],data->dofs[k][2*ind]);
259
}
260
261
fprintf(out,"\n");
262
}
263
fclose(out);
264
265
sprintf(filename2,"%s%d%s",prefix,j,".sidetxt");
266
out = fopen(filename2,"w");
267
fprintf(out,"Degrees of freedom in file %s are as follows:\n",filename);
268
if(bound->coordsystem == COORD_CART2) {
269
fprintf(out,"col1: X coordinate\n");
270
fprintf(out,"col2: Y coordinate\n");
271
}
272
else if(bound->coordsystem == COORD_AXIS) {
273
fprintf(out,"col1: R coordinate\n");
274
fprintf(out,"col2: Z coordinate\n");
275
}
276
else if(bound->coordsystem == COORD_POLAR) {
277
fprintf(out,"col1: R coordinate\n");
278
fprintf(out,"col2: F coordinate\n");
279
}
280
fprintf(out,"col3: node indices\n");
281
col = 3;
282
for(k=0;k<MAXDOFS;k++) {
283
if(data->edofs[k] == 1)
284
fprintf(out,"col%d: %s\n",++col,data->dofname[k]);
285
if(data->edofs[k] == 2) {
286
fprintf(out,"col%d: %s1\n",++col,data->dofname[k]);
287
fprintf(out,"col%d: %s2\n",++col,data->dofname[k]);
288
}
289
}
290
fclose(out);
291
292
if(info) printf("Boundary info was saved to files %s and %s.\n",
293
filename,filename2);
294
}
295
296
return(0);
297
}
298
299
300
301
int SaveBoundaryForm(struct FemType *data,struct CellType *cell,
302
char* prefix,int info)
303
/* Saves the form of the boundary as given by function GetSideInfo
304
in form [x,y,index].
305
*/
306
{
307
int sideknots,elemno,side,more,elemind[2],sideelemtype;
308
int no,sideind[MAXNODESD1];
309
FILE *out;
310
char filename[MAXFILESIZE];
311
312
if(data->created == FALSE) {
313
printf("SaveBoundaryForm: structure FemType not created\n");
314
return(1);
315
}
316
317
sideknots = 0;
318
more = FALSE;
319
320
AddExtension(prefix,filename,"boundary");
321
out = fopen(filename,"w");
322
323
/* Go through all pairs of points and save them into a matrix. */
324
for(no=1; no <= data->nocells; no++)
325
for(side=0; side < 4; side++)
326
if(cell[no].material != cell[no].boundary[side]) {
327
elemno = 0;
328
do {
329
elemno++;
330
sideknots++;
331
more = GetSideInfo(cell,no,side,elemno,elemind);
332
GetElementSide(elemind[0],side,1,data,sideind,&sideelemtype);
333
334
fprintf(out,"%-12.4le %-12.4le %-12.4le %-12.4le\n",
335
data->x[sideind[0]],data->x[sideind[1]],
336
data->y[sideind[0]],data->y[sideind[1]]);
337
} while(more);
338
}
339
340
fclose(out);
341
342
if(info) printf("%d boundaries between materials were saved to file %s.\n",
343
sideknots,filename);
344
return(0);
345
}
346
347
348
int SaveBoundaryLine(struct FemType *data,int direction,
349
Real c0,char* prefix,int info)
350
/* Saves the nodes forming a vertical or a horizontal line.
351
The format is [x y v1 v2 v3 ...].
352
*/
353
{
354
int k,no,points;
355
FILE *out;
356
char filename[MAXFILESIZE];
357
Real c,c1,eps;
358
359
if(data->created == FALSE) {
360
printf("SaveBoundaryLine: structure FemType not created\n");
361
return(1);
362
}
363
364
eps = 1.0e-6;
365
points = 0;
366
367
AddExtension(prefix,filename,"line");
368
out = fopen(filename,"w");
369
370
/* Go through all pairs of points and save them into amatrix. */
371
372
c1 = data->x[1];
373
for(no=1; no <= data->noknots; no++) {
374
if(direction > 0)
375
c = data->x[no];
376
else
377
c = data->y[no];
378
if(fabs(c-c0) < fabs(c1-c0))
379
c1 = c;
380
}
381
for(no=1; no <= data->noknots; no++) {
382
if(direction > 0)
383
c = data->x[no];
384
else
385
c = data->y[no];
386
if(fabs(c-c1) < eps) {
387
if(direction > 0)
388
fprintf(out,"%-12.7le %-12.7le ",c,data->y[no]);
389
else
390
fprintf(out,"%-12.7le %-12.7le ",data->x[no],c);
391
for(k=0;k<MAXDOFS;k++) {
392
if(data->edofs[k] == 1)
393
fprintf(out,"%-12.7le ",data->dofs[k][no]);
394
if(data->edofs[k] == 2)
395
fprintf(out,"%-12.7le %-12.7le ",
396
data->dofs[k][2*no-1],data->dofs[k][2*no]);
397
}
398
fprintf(out,"\n");
399
points++;
400
}
401
}
402
if(info) printf("Line (c=%.3lg) with %d nodes was saved to file %s.\n",
403
c1,points,filename);
404
405
fclose(out);
406
407
return(0);
408
}
409
410
411
int SaveSubcellForm(struct FemType *data,struct CellType *cell,
412
char* prefix,int info)
413
/* Saves the form of the boundary as given by function GetSideInfo
414
in form [x,y,index].
415
*/
416
{
417
int more,sideknots,elemno,elemind[2],side,i;
418
int no,sideind[MAXNODESD1],nosidenodes,sidelemtype;
419
FILE *out;
420
char filename[MAXFILESIZE];
421
422
sideknots = 0;
423
more = FALSE;
424
425
if(data->created == FALSE) {
426
printf("SaveSubcellForm: structure FemType not created\n");
427
return(1);
428
}
429
430
AddExtension(prefix,filename,"subcell");
431
out = fopen(filename,"w");
432
433
/* Go through all pairs of points and save them into amatrix. */
434
for(no=1; no <= data->nocells; no++)
435
for(side=0; side < 4; side++)
436
if(cell[no].boundary[side]) {
437
elemno = 0;
438
do {
439
elemno++;
440
sideknots++;
441
more = GetSideInfo(cell,no,side,elemno,elemind);
442
GetElementSide(elemind[0],side,1,data,sideind,&sidelemtype);
443
nosidenodes = sidelemtype%100;
444
for(i=0;i<nosidenodes;i++)
445
fprintf(out,"%-12.4le %-12.4le %-8d\n",
446
data->x[sideind[i]],data->y[sideind[i]],sideind[i]);
447
} while(more);
448
}
449
fclose(out);
450
451
if(info) printf("There are %d sideknots in the elements.\n",sideknots);
452
if(info) printf("The positions of the sideknots were saved in file %s.\n",filename);
453
454
return(0);
455
}
456
457
458
459
460
int InspectElement(struct FemType *data,int idx)
461
{
462
int elemtype,nonodes,i,j,k;
463
Real *x,*y,*z;
464
Real ds,minds,xc,yc,zc;
465
Real x0,y0,z0;
466
int ii,jj,mini,minj,kk;
467
468
elemtype = data->elementtypes[idx];
469
printf("Inspecting element %d of type %d\n",idx,elemtype);
470
471
nonodes = elemtype % 100;
472
x = data->x;
473
y = data->y;
474
z = data->z;
475
476
for(k=0;k<nonodes;k++) {
477
kk = data->topology[idx][k];
478
x0 = x[kk];
479
y0 = y[kk];
480
z0 = z[kk];
481
mini = -1;
482
minj = -1;
483
minds = 1.0e20;
484
485
for(i=0;i<nonodes;i++) {
486
ii = data->topology[idx][i];
487
for(j=i+1;j<nonodes;j++) {
488
jj = data->topology[idx][j];
489
xc = (x[ii]+x[jj])/2;
490
yc = (y[ii]+y[jj])/2;
491
zc = (z[ii]+z[jj])/2;
492
ds = sqrt( pow(x0-xc,2) + pow(y0-yc,2) + pow(z0-zc,2) );
493
if( mini == -1 || ds < minds) {
494
mini = i;
495
minj = j;
496
minds = ds;
497
}
498
}
499
}
500
501
printf("k=%d mini=%d minj=%d ds=%.3le\n",k+1,mini+1,minj+1,minds);
502
}
503
504
return(0);
505
}
506
507
508
int LoadSolutionElmer(struct FemType *data,int results,char *prefix,int info)
509
/* This procedure reads the solution in a form that is understood
510
by the programs ElmerPost, created
511
by Juha Ruokolainen at CSC - IT Center for Science Ltd..
512
This procedure is not by far general.
513
*/
514
{
515
int noknots,noelements,novctrs,open;
516
int timesteps,i,j,k,grp;
517
Real r;
518
FILE *in;
519
char line[MAXLINESIZE],filename[MAXFILESIZE],text[MAXNAMESIZE];
520
int iostat;
521
522
AddExtension(prefix,filename,"ep");
523
if ((in = fopen(filename,"r")) == NULL) {
524
printf("LoadSolutionElmer: The opening of the Elmer-file %s wasn't successful!\n",
525
filename);
526
return(1);
527
}
528
else
529
printf("Loading Elmer data from %s\n",filename);
530
531
InitializeKnots(data);
532
533
GETLINE;
534
sscanf(line,"%d %d %d %d",&noknots,&noelements,&novctrs,&timesteps);
535
536
data->dim = 3;
537
data->maxnodes = MAXNODESD2;
538
data->noknots = noknots;
539
data->noelements = noelements;
540
data->timesteps = timesteps;
541
542
if(timesteps > 1)
543
printf("LoadSolutionElmer: The subroutine may crash with %d timesteps\n",
544
timesteps);
545
if(timesteps < 1) timesteps = 1;
546
547
if(info) printf("Allocating for %d knots and %d elements.\n",
548
noknots,noelements);
549
AllocateKnots(data);
550
551
if(results) {
552
if(timesteps > 1)
553
data->times = Rvector(0,timesteps-1);
554
for(i=1;i<=novctrs;i++) {
555
sprintf(text,"var%d",i);
556
CreateVariable(data,i,timesteps,0.0,text,FALSE);
557
}
558
}
559
560
if(info) printf("Reading %d coordinates.\n",noknots);
561
for(i=1; i <= noknots; i++) {
562
GETLINE;
563
sscanf(line,"%le %le %le",
564
&(data->x[i]),&(data->y[i]),&(data->z[i]));
565
}
566
567
if(info) printf("Reading %d element topologies.\n",noelements);
568
569
grp = 0;
570
open = FALSE;
571
for(i=1; i <= noelements; i++) {
572
iostat = fscanf(in,"%s",text);
573
if(strstr(text,"#group")) {
574
grp++;
575
printf("Starting a new element group\n");
576
iostat = fscanf(in,"%s",text);
577
iostat = fscanf(in,"%s",text);
578
open = TRUE;
579
}
580
if(strstr(text,"#end")) {
581
printf("Ending an element group\n");
582
iostat = fscanf(in,"%s",text);
583
open = FALSE;
584
}
585
iostat = fscanf(in,"%d",&(data->elementtypes[i]));
586
data->material[i] = grp;
587
for(j=0;j< data->elementtypes[i]%100 ;j++) {
588
iostat = fscanf(in,"%d",&(data->topology[i][j]));
589
data->topology[i][j] += 1;
590
}
591
}
592
if(open) {
593
do {
594
iostat = fscanf(in,"%s",text);
595
} while (!strstr(text,"#end"));
596
iostat = fscanf(in,"%s",text);
597
printf("Ending an element group\n");
598
open = FALSE;
599
}
600
601
if(results == 0)
602
return(0);
603
604
if(info) printf("Reading %d degrees of freedom for %d knots.\n",
605
novctrs,noknots);
606
if (timesteps <= 1) {
607
for(i=1; i <= noknots; i++)
608
for(j=1;j <= novctrs;j++)
609
iostat = fscanf(in,"%le",&(data->dofs[j][i]));
610
}
611
else for(k=0;k<timesteps;k++) {
612
iostat = fscanf(in,"%s",text);
613
if(iostat < 0) goto end;
614
iostat = fscanf(in,"%d",&i);
615
iostat = fscanf(in,"%d",&j);
616
iostat = fscanf(in,"%le",&r);
617
618
if(0) printf("Loading steps i=%d j=%d k=%d r=%.3lg\n",i,j,k,r);
619
620
for(i=1; i <= noknots; i++)
621
for(j=1;j <= novctrs;j++)
622
iostat = fscanf(in,"%le",&(data->dofs[j][k*noknots+i]));
623
}
624
625
end:
626
data->timesteps = timesteps;
627
628
fclose(in);
629
630
return(0);
631
}
632
633
634
635
int SaveSolutionElmer(struct FemType *data,struct BoundaryType *bound,
636
int nobound,char *prefix,int decimals,int info)
637
/* This procedure saves the solution in a form that is understood
638
by the programs Funcs and ElmerPost, created
639
by Juha Ruokolainen at CSC - IT Center for Science Ltd..
640
*/
641
{
642
int material,noknots,noelements,bulkelems,novctrs,sideelems,sideelemtype,elemtype,boundtype;
643
char filename[MAXFILESIZE],outstyle[MAXFILESIZE];
644
int i,j,k,l,nodesd1,timesteps,nodesd2;
645
int ind[MAXNODESD1];
646
Real *rpart;
647
FILE *out;
648
649
if(!data->created) {
650
printf("SaveSolutionElmer: You tried to save points that were never created.\n");
651
return(1);
652
}
653
654
/* Make a variable showing the owner partition */
655
if(data->partitionexist) {
656
l = 0;
657
do l++; while (data->edofs[l]);
658
CreateVariable(data,l,1,0.0,"Partition",FALSE);
659
rpart = data->dofs[l];
660
for(i=1;i<=data->noknots;i++)
661
rpart[i] = 1.0 * data->nodepart[i];
662
}
663
664
if(data->variables == 0) {
665
printf("SaveSolutionElmer: there are no dofs to save!\n");
666
return(2);
667
}
668
669
sideelems = 0;
670
if(nobound) {
671
for(i=0;i<nobound;i++) {
672
if(bound[i].created) sideelems += bound[i].nosides;
673
}
674
}
675
676
noknots = data->noknots;
677
bulkelems = data->noelements;
678
if(nobound)
679
noelements = bulkelems + sideelems;
680
else
681
noelements = bulkelems;
682
timesteps = data->timesteps;
683
if(timesteps < 1) timesteps = 1;
684
685
novctrs = 0;
686
for(i=0;i<MAXDOFS;i++) {
687
if(data->edofs[i] == 1) novctrs += 1;
688
if(data->edofs[i] == 2) novctrs += 3;
689
if(data->edofs[i] == 3) novctrs += 3;
690
}
691
692
AddExtension(prefix,filename,"ep");
693
if(info) printf("Saving ElmerPost data to %s.\n",filename);
694
695
out = fopen(filename,"w");
696
if(out == NULL) {
697
printf("opening of file was not successful\n");
698
return(3);
699
}
700
701
fprintf(out,"%d %d %d %d",noknots,noelements,novctrs,timesteps);
702
703
for(i=0; i<MAXDOFS; i++) {
704
if(data->edofs[i] == 1)
705
fprintf(out," scalar: %s",data->dofname[i]);
706
else if(data->edofs[i] > 1)
707
fprintf(out," vector: %s",data->dofname[i]);
708
}
709
fprintf(out,"\n");
710
711
if(info) printf("Saving %d node coordinates.\n",noknots);
712
713
sprintf(outstyle,"%%.%dg %%.%dg %%.%dg\n",decimals,decimals,decimals);
714
for(i=1; i <= noknots; i++)
715
fprintf(out,outstyle,data->x[i],data->y[i],data->z[i]);
716
717
printf("Saving %d bulk element topologies.\n",bulkelems);
718
719
for(i=1;i<=bulkelems;i++) {
720
elemtype = data->elementtypes[i];
721
material = data->material[i];
722
723
if(data->bodynamesexist)
724
fprintf(out,"body_%d_%s %d ",material,data->bodyname[material],elemtype);
725
else if(elemtype/100 > 4)
726
fprintf(out,"vol%d %d ",material,elemtype);
727
else if(elemtype/100 > 2)
728
fprintf(out,"surf%d %d ",material,elemtype);
729
else if(elemtype/100 > 1)
730
fprintf(out,"line%d %d ",material,elemtype);
731
else
732
fprintf(out,"pnt%d %d ",material,elemtype);
733
734
nodesd2 = data->elementtypes[i]%100;
735
for(j=0;j<nodesd2;j++)
736
fprintf(out,"%d ",data->topology[i][j]-1);
737
fprintf(out,"\n");
738
}
739
740
if(nobound) {
741
printf("Saving %d side element topologies.\n",sideelems);
742
for(j=0;j<nobound;j++) {
743
if(bound[j].created == FALSE) continue;
744
745
for(i=1;i<=bound[j].nosides;i++) {
746
747
GetBoundaryElement(i,&bound[j],data,ind,&sideelemtype);
748
749
boundtype = bound[j].types[i];
750
751
if(data->boundarynamesexist)
752
fprintf(out,"bc_%d_%s %d ",boundtype,data->boundaryname[boundtype],sideelemtype);
753
else if(sideelemtype/100 > 2)
754
fprintf(out,"bcside%d %d ",boundtype,sideelemtype);
755
else if(sideelemtype/100 > 1)
756
fprintf(out,"bcline%d %d ",boundtype,sideelemtype);
757
else
758
fprintf(out,"bcpnt%d %d ",boundtype,sideelemtype);
759
760
nodesd1 = sideelemtype%100;
761
for(k=0;k<nodesd1;k++)
762
fprintf(out,"%d ",ind[k]-1);
763
fprintf(out,"\n");
764
}
765
}
766
}
767
768
printf("Saving %d degrees of freedom for each knot.\n",novctrs);
769
for(k=0;k<timesteps;k++) {
770
for(i=1;i<=noknots;i++){
771
for(j=0;j<MAXDOFS;j++) {
772
if(data->edofs[j] == 1)
773
fprintf(out,"%.6lg ",data->dofs[j][k*noknots+i]);
774
if(data->edofs[j] == 2)
775
fprintf(out,"%.6lg %.6lg 0.0 ",
776
data->dofs[j][2*(k*noknots+i)-1],data->dofs[j][2*(k*noknots+i)]);
777
if(data->edofs[j] == 3)
778
fprintf(out,"%.6lg %.6lg %.6lg ",
779
data->dofs[j][3*(k*noknots+i)-2],
780
data->dofs[j][3*(k*noknots+i)-1],
781
data->dofs[j][3*(k*noknots+i)]);
782
}
783
fprintf(out,"\n");
784
}
785
}
786
fclose(out);
787
788
return(0);
789
}
790
791
int SaveSizeInfo(struct FemType *data,struct BoundaryType *bound,
792
char *prefix,int info)
793
{
794
int nosides,j;
795
FILE *out;
796
char filename[MAXFILESIZE];
797
798
if(!data->created) {
799
printf("You tried to save points that were never created.\n");
800
return(1);
801
}
802
803
nosides = 0;
804
for(j=0;j < MAXBOUNDARIES;j++) {
805
if(bound[j].created == FALSE) continue;
806
nosides += bound[j].nosides;
807
}
808
809
AddExtension(prefix,filename,"size");
810
if(info) printf("Saving size info into file %s.\n",filename);
811
812
out = fopen(filename,"w");
813
fprintf(out,"%d\n",data->noknots);
814
fprintf(out,"%d\n",data->noelements);
815
fprintf(out,"%d\n",nosides);
816
fprintf(out,"%d\n",data->nopartitions);
817
818
fclose(out);
819
820
return(0);
821
}
822
823
int MeshPieces(struct FemType *data,int nomesh,int nomeshes,int info)
824
{
825
int i,j,k,n;
826
int MinIndex,MaxIndex,NoPieces,NoCorners,Loop,Ready;
827
int *MeshPiece=NULL,*PiecePerm=NULL;
828
// Indexes only needs to hold the max number of dofs per element
829
int Indexes[100];
830
831
if(nomeshes > 1) {
832
printf("Calculate Mesh Pieces in mesh[%d] of [%d] meshes:\n",nomesh,nomeshes);
833
} else {
834
printf("Calculate Mesh Pieces in mesh:\n");
835
}
836
837
n = data->noknots;
838
MeshPiece = Ivector(1,n);
839
for(i=1;i<=n;i++) MeshPiece[i] = 0;
840
841
/* Only set the piece for the nodes that are used by some element
842
For others the marker will remain zero. */
843
for(i=1; i<=data->noelements; i++) {
844
NoCorners = data->elementtypes[i]%100;
845
for(j=0; j<NoCorners; j++) {
846
MeshPiece[data->topology[i][j]] = 1;
847
}
848
}
849
850
j = 0;
851
for(i=1; i<=n; i++) {
852
if(MeshPiece[i] > 0) {
853
j++;
854
MeshPiece[i] = j;
855
}
856
}
857
if( n > j) {
858
printf("Number of non-body (hanging) nodes in mesh is %d\n", n-j );
859
printf("Consider running ElmerGrid with -autoclean command\n");
860
}
861
862
/* We go through the elements and set all the piece indexes to minimum index
863
until the mesh is unchanged. Thereafter the whole piece will have the minimum index
864
of the piece. */
865
Ready = FALSE;
866
Loop = 0;
867
868
while(!Ready) {
869
Ready = TRUE;
870
for(i=1; i<=data->noelements; i++) {
871
MaxIndex = 0;
872
MinIndex = n;
873
874
NoCorners = data->elementtypes[i]%100;
875
for(j=0; j<NoCorners; j++) {
876
Indexes[j] = data->topology[i][j];
877
}
878
for(j=0; j<NoCorners; j++) {
879
for(k=0; k<NoCorners; k++) {
880
if(MaxIndex < MeshPiece[Indexes[k]] )
881
MaxIndex = MeshPiece[Indexes[k]];
882
if(MinIndex >= MeshPiece[Indexes[k]] )
883
MinIndex = MeshPiece[Indexes[k]];
884
}
885
if(MaxIndex > MinIndex) {
886
MeshPiece[Indexes[j]] = MinIndex;
887
Ready = FALSE;
888
}
889
}
890
}
891
Loop++;
892
}
893
/* printf("Mesh coloring loops: %d\n",Loop); */
894
895
MaxIndex = 0;
896
for(i=1; i<=n; i++)
897
if(MeshPiece[i] > MaxIndex) MaxIndex = MeshPiece[i];
898
899
/* Compute the true number of different pieces */
900
if(MaxIndex == 1) {
901
NoPieces = 1;
902
} else {
903
NoPieces = 0;
904
PiecePerm = Ivector(1,MaxIndex);
905
for(i=1;i<=MaxIndex;i++)
906
PiecePerm[i] = 0;
907
908
for(i=1; i<=n; i++) {
909
j = MeshPiece[i];
910
if( j == 0) continue;
911
if(PiecePerm[j] == 0) {
912
NoPieces++;
913
PiecePerm[j] = NoPieces;
914
}
915
}
916
free_Ivector(PiecePerm,1,MaxIndex);
917
}
918
if(NoPieces == 1) {
919
printf("There is a single piece in the mesh, so the mesh is conforming.\n");
920
} else {
921
printf("Number of separate pieces in mesh is %d\n", NoPieces);
922
printf("The mesh is non-conforming. If not expecting a non-conforming\n");
923
printf("mesh, then refer to the Elmer User Forum for help.\n");
924
}
925
free_Ivector(MeshPiece,1,n);
926
return(0);
927
}
928
929
int SaveElmerInputFemBem(struct FemType *data,struct BoundaryType *bound,
930
char *prefix,int decimals,int info)
931
/* Saves the mesh in a form that may be used as input
932
in Elmer calculations. Tailored to work with FEM/BEM coupling,
933
or other problems with mixed dimension of bulk elements.
934
*/
935
{
936
int noknots,noelements,material,sumsides,elemtype,fail,nobulkelements,bctype;
937
int sideelemtype,nodesd1,nodesd2,newtype,elemdim,maxelemdim,cdstat;
938
int i,j,k,l,bulktypes[MAXELEMENTTYPE+1],sidetypes[MAXELEMENTTYPE+1],tottypes;
939
int ind[MAXNODESD1],bodyperm[MAXBODIES],bcperm[MAXBCS];
940
FILE *out;
941
char filename[MAXFILESIZE], outstyle[MAXFILESIZE];
942
char directoryname[MAXFILESIZE];
943
944
if(!data->created) {
945
printf("You tried to save points that were never created.\n");
946
return(1);
947
}
948
949
if(data->nodeconnectexist) smallerror("Connectivity data is not saved in the FEM/BEM version");
950
if(data->nopartitions > 1) smallerror("Partitioning data is not saved in the FEM/BEM version");
951
952
noelements = data->noelements;
953
noknots = data->noknots;
954
sumsides = 0;
955
956
for(i=0;i<=MAXELEMENTTYPE;i++)
957
bulktypes[i] = sidetypes[i] = 0;
958
959
sprintf(directoryname,"%s",prefix);
960
961
if(info) printf("Saving mesh in ElmerSolver format to directory %s.\n",
962
directoryname);
963
964
cdstat = chdir(directoryname);
965
if(cdstat) {
966
#ifdef MINGW32
967
fail = mkdir(directoryname);
968
#else
969
fail = mkdir(directoryname,0750);
970
#endif
971
if(fail) {
972
printf("Could not create a result directory!\n");
973
return(1);
974
}
975
else {
976
cdstat = chdir(directoryname);
977
}
978
}
979
else {
980
printf("Reusing an existing directory\n");
981
}
982
983
sprintf(filename,"%s","mesh.nodes");
984
out = fopen(filename,"w");
985
986
if(info) printf("Saving %d coordinates to %s.\n",noknots,filename);
987
if(out == NULL) {
988
printf("opening of file was not successful\n");
989
return(2);
990
}
991
992
sprintf(outstyle,"%%d %%d %%.%dg %%.%dg %%.%dg\n",decimals,decimals,decimals);
993
for(i=1; i <= noknots; i++)
994
fprintf(out,outstyle,i,-1,data->x[i],data->y[i],data->z[i]);
995
fclose(out);
996
997
998
sprintf(filename,"%s","mesh.elements");
999
out = fopen(filename,"w");
1000
if(out == NULL) {
1001
printf("opening of file was not successful\n");
1002
return(3);
1003
}
1004
1005
maxelemdim = GetMaxElementDimension(data);
1006
nobulkelements = 0;
1007
1008
for(i=0;i<MAXBODIES;i++) bodyperm[i] = FALSE;
1009
for(i=1;i<=noelements;i++) {
1010
elemtype = data->elementtypes[i];
1011
elemdim = GetElementDimension(elemtype);
1012
material = data->material[i];
1013
1014
if(elemdim == maxelemdim)
1015
bodyperm[material] = 1;
1016
else
1017
bodyperm[material] = -1;
1018
}
1019
j = 0;
1020
k = 0;
1021
for(i=0;i<MAXBODIES;i++) {
1022
if(bodyperm[i] > 0) bodyperm[i] = ++j;
1023
if(bodyperm[i] < 0) bodyperm[i] = --k;
1024
}
1025
1026
1027
for(i=1;i<=noelements;i++) {
1028
elemtype = data->elementtypes[i];
1029
1030
elemdim = GetElementDimension(elemtype);
1031
if(elemdim < maxelemdim) continue;
1032
1033
nobulkelements++;
1034
material = data->material[i];
1035
material = bodyperm[material];
1036
fprintf(out,"%d %d %d",i,material,elemtype);
1037
1038
bulktypes[elemtype] += 1;
1039
nodesd2 = elemtype%100;
1040
for(j=0;j < nodesd2;j++)
1041
fprintf(out," %d",data->topology[i][j]);
1042
fprintf(out,"\n");
1043
}
1044
fclose(out);
1045
1046
if(info) printf("Saving %d (of %d) body elements to mesh.boundary\n",nobulkelements,noelements);
1047
1048
1049
sprintf(filename,"%s","mesh.boundary");
1050
out = fopen(filename,"w");
1051
if(out == NULL) {
1052
printf("opening of file was not successful\n");
1053
return(4);
1054
}
1055
1056
sumsides = 0;
1057
newtype = 0;
1058
for(i=0;i<MAXBCS;i++) bcperm[i] = 0;
1059
for(j=0;j < MAXBOUNDARIES;j++) {
1060
if(bound[j].created == FALSE) continue;
1061
for(i=1; i <= bound[j].nosides; i++)
1062
bcperm[bound[j].types[i]] = TRUE;
1063
}
1064
j = 0;
1065
for(i=0;i<MAXBCS;i++)
1066
if(bcperm[i]) bcperm[i] = ++j;
1067
newtype = j;
1068
1069
1070
/* Save normal boundaries */
1071
for(j=0;j < MAXBOUNDARIES;j++) {
1072
if(bound[j].created == FALSE) continue;
1073
if(bound[j].nosides == 0) continue;
1074
1075
for(i=1; i <= bound[j].nosides; i++) {
1076
GetElementSide(bound[j].parent[i],bound[j].side[i],bound[j].normal[i],data,ind,&sideelemtype);
1077
sumsides++;
1078
material = bound[j].types[i];
1079
material = bcperm[material];
1080
1081
fprintf(out,"%d %d %d %d %d",
1082
sumsides,material,bound[j].parent[i],bound[j].parent2[i],sideelemtype);
1083
1084
sidetypes[sideelemtype] += 1;
1085
1086
nodesd1 = sideelemtype % 100;
1087
for(l=0;l<nodesd1;l++)
1088
fprintf(out," %d",ind[l]);
1089
fprintf(out,"\n");
1090
}
1091
}
1092
1093
1094
for(i=1;i<=noelements;i++) {
1095
elemtype = data->elementtypes[i];
1096
1097
elemdim = GetElementDimension(elemtype);
1098
if(elemdim == maxelemdim) continue;
1099
1100
sumsides++;
1101
1102
material = data->material[i];
1103
bctype = abs(bodyperm[material]) + newtype;
1104
1105
fprintf(out,"%d %d 0 0 %d",sumsides,bctype,elemtype);
1106
sidetypes[elemtype] += 1;
1107
nodesd1 = elemtype%100;
1108
for(l=0;l<nodesd1;l++)
1109
fprintf(out," %d",data->topology[i][l]);
1110
fprintf(out,"\n");
1111
}
1112
1113
fclose(out);
1114
if(info) printf("Saving %d boundary elements to mesh.boundary\n",sumsides);
1115
1116
1117
tottypes = 0;
1118
for(i=0;i<=MAXELEMENTTYPE;i++)
1119
if(bulktypes[i] || sidetypes[i]) tottypes++;
1120
1121
sprintf(filename,"%s","mesh.header");
1122
out = fopen(filename,"w");
1123
if(info) printf("Saving header info with %d elementtypes to %s.\n",tottypes,filename);
1124
if(out == NULL) {
1125
printf("opening of file was not successful\n");
1126
return(4);
1127
}
1128
fprintf(out,"%-6d %-6d %-6d\n",
1129
noknots,nobulkelements,sumsides);
1130
fprintf(out,"%-6d\n",tottypes);
1131
for(i=0;i<=MAXELEMENTTYPE;i++)
1132
if(bulktypes[i] || sidetypes[i])
1133
fprintf(out,"%-6d %-6d\n",i,bulktypes[i]+sidetypes[i]);
1134
fclose(out);
1135
1136
if(info) printf("Body and boundary numbers were permutated\n");
1137
1138
if(data->boundarynamesexist || data->bodynamesexist) {
1139
sprintf(filename,"%s","mesh.names");
1140
out = fopen(filename,"w");
1141
if(info) printf("Saving names info to %s.\n",filename);
1142
if(out == NULL) {
1143
printf("opening of file was not successful\n");
1144
return(5);
1145
}
1146
1147
if(data->bodynamesexist) {
1148
fprintf(out,"! ----- names for bodies -----\n");
1149
for(i=1;i<MAXBODIES;i++)
1150
if(bodyperm[i] > 0) fprintf(out,"$ %s = %d\n",data->bodyname[i],bodyperm[i]);
1151
}
1152
if(data->boundarynamesexist) {
1153
fprintf(out,"! ----- names for boundaries -----\n");
1154
/* The reordered numbering of the original BCs */
1155
for(i=1;i<MAXBCS;i++) {
1156
if(bcperm[i])
1157
fprintf(out,"$ %s = %d\n",data->boundaryname[i],bcperm[i]);
1158
}
1159
/* Numbering of bodies that are actually saved as boundaries */
1160
for(i=1;i<MAXBODIES;i++)
1161
if(bodyperm[i] < 0)
1162
fprintf(out,"$ %s = %d\n",data->bodyname[i],abs(bodyperm[i])+newtype);
1163
}
1164
fclose(out);
1165
}
1166
1167
cdstat = chdir("..");
1168
1169
return(0);
1170
}
1171
1172
1173
1174
void InspectVector(Real *vector,int first,int last,Real *min,
1175
Real *max,int *mini,int *maxi)
1176
/* Returns the value and position of the smallest and largest element
1177
in vector[first,last].
1178
*/
1179
{
1180
int i;
1181
*min = vector[first];
1182
*mini = first;
1183
*max = vector[first];
1184
*maxi = first;
1185
1186
for(i=first+1;i<=last;i++) {
1187
if (vector[i]>*max) {
1188
*max=vector[i];
1189
*maxi=i;
1190
}
1191
if (vector[i]<*min) {
1192
*min=vector[i];
1193
*mini=i;
1194
}
1195
}
1196
}
1197
1198
1199
int Steepest(Real *vector,int first,int last)
1200
/* Finds the position where vector is at its steepest */
1201
{
1202
int i,steep;
1203
Real aid,sub=0.0;
1204
1205
steep = -1;
1206
for(i=first;i<last;i++) {
1207
aid=fabs(vector[i+1]-vector[i]);
1208
if ( aid > sub) {
1209
sub=aid;
1210
steep=i;
1211
}
1212
}
1213
return(steep);
1214
}
1215
1216
1217
Real MeanVector(Real *vector,int first,int last)
1218
/* Calculates the mean of vector[first,last] */
1219
{
1220
Real sum=0.0;
1221
int i;
1222
1223
for(i=first;i<=last;i++)
1224
sum += vector[i];
1225
1226
return(sum/(last-first+1));
1227
}
1228
1229
1230
1231
Real AbsMeanVector(Real *vector,int first,int last)
1232
/* Calculates the absolute mean of vector[first,last] */
1233
{
1234
Real sum=0.0;
1235
int i;
1236
1237
for(i=first;i<=last;i++)
1238
sum += fabs(vector[i]);
1239
1240
return(sum/(last-first+1));
1241
}
1242
1243
1244
Real DifferVector(Real *vector1,Real *vector2,int first,int last)
1245
/* Calculates the mean of the relative difference of two vectors */
1246
{
1247
Real sum=0.0, eps=1.0E-50;
1248
int i,n;
1249
1250
for (i=first;i<=last;i++) {
1251
if ( fabs(vector1[i]+vector2[i]) > eps)
1252
sum += fabs(2*(vector1[i]-vector2[i])/(vector1[i]+vector2[i]));
1253
}
1254
n=last-first+1;
1255
1256
return ( sum/(Real)(n) );
1257
}
1258
1259
1260
void ReformVector(Real *vector1,int n1,Real *vector2,int n2)
1261
/* Adjusts the values of a vector to another vector with a different number
1262
of elements
1263
*/
1264
{
1265
int i1,i2;
1266
Real x1,d1;
1267
1268
for(i2=0;i2<n2;i2++) {
1269
x1=(n1)*((Real)(i2)/(Real)(n2));
1270
i1=(int)(x1);
1271
d1=x1-(Real)(i1);
1272
vector2[i2]=d1*vector1[i1+1]+(1.0-d1)*vector1[i1];
1273
}
1274
vector2[n2]=vector1[n1];
1275
}
1276
1277
1278
1279
void AdjustVector(Real max,Real min,Real *vector,int first,int last)
1280
/* Scales the values of a vector to range [min,max] using a linear model. */
1281
{
1282
int i;
1283
Real oldmax,oldmin;
1284
1285
oldmax=vector[first];
1286
oldmin=oldmax;
1287
for(i=first+1;i<=last;i++) {
1288
if (oldmax < vector[i])
1289
oldmax=vector[i];
1290
if (oldmin > vector[i])
1291
oldmin=vector[i];
1292
}
1293
for(i=first;i<=last;i++)
1294
vector[i]=(max-min)*(vector[i]-oldmin)/(oldmax-oldmin)+min;
1295
}
1296
1297
1298
1299
int ReadRealVector(Real *vector,int first,int last,char *filename)
1300
/* Reads a Real vector from an ascii-file with a given name. */
1301
{
1302
int i,iostat;
1303
FILE *in;
1304
Real num;
1305
1306
if ((in = fopen(filename,"r")) == NULL) {
1307
printf("The opening of the real vector file '%s' wasn't successful !\n",filename);
1308
return(1);
1309
}
1310
for(i=first;i<=last;i++) {
1311
iostat = fscanf(in,"%le\n",&num);
1312
vector[i]=num;
1313
}
1314
fclose(in);
1315
1316
return(0);
1317
}
1318
1319
1320
1321
void SaveRealVector(Real *vector,int first,int last,char *filename)
1322
/* Saves an Real vector to an ascii-file with a given name. */
1323
{
1324
int i;
1325
FILE *out;
1326
1327
out = fopen(filename,"w");
1328
for (i=first;i<=last;i++) {
1329
fprintf(out,"%.6le",vector[i]);
1330
fprintf(out,"\n");
1331
}
1332
fclose(out);
1333
}
1334
1335
1336
1337
int ReadIntegerVector(int *vector,int first,int last,char *filename)
1338
{
1339
int i,iostat;
1340
FILE *in;
1341
int num;
1342
1343
if ((in = fopen(filename,"r")) == NULL) {
1344
printf("The opening of the int vector file '%s' wasn't successful !\n",filename);
1345
return(1);
1346
}
1347
for(i=first;i<=last;i++) {
1348
iostat = fscanf(in,"%d\n",&num);
1349
vector[i]=num;
1350
}
1351
fclose(in);
1352
1353
return(0);
1354
}
1355
1356
1357
1358
void SaveIntegerVector(int *vector,int first,int last,char *filename)
1359
{
1360
int i;
1361
FILE *out;
1362
1363
out = fopen(filename,"w");
1364
for (i=first;i<=last;i++) {
1365
fprintf(out,"%d",vector[i]);
1366
fprintf(out,"\n");
1367
}
1368
fclose(out);
1369
}
1370
1371
1372
1373
int ReadRealMatrix(Real **matrix,int row_first,int row_last,
1374
int col_first,int col_last,char *filename)
1375
{
1376
int i,j,iostat;
1377
FILE *in;
1378
Real num;
1379
1380
if ((in = fopen(filename,"r")) == NULL) {
1381
printf("The opening of the real matrix file '%s' wasn't successful!\n",filename);
1382
return(1);
1383
}
1384
1385
for(j=row_first;j<=row_last;j++) {
1386
for(i=col_first;i<=col_last;i++) {
1387
iostat = fscanf(in,"%le\n",&num);
1388
matrix[j][i]=num;
1389
}
1390
}
1391
fclose(in);
1392
1393
return(0);
1394
}
1395
1396
1397
1398
void SaveRealMatrix(Real **matrix,int row_first,int row_last,
1399
int col_first,int col_last,char *filename)
1400
{
1401
int i,j;
1402
FILE *out;
1403
1404
out = fopen(filename,"w");
1405
for (j=row_first;j<=row_last;j++) {
1406
for (i=col_first;i<=col_last;i++) {
1407
fprintf(out,"%-14.6lg",matrix[j][i]);
1408
fprintf(out,"\t");
1409
}
1410
fprintf(out,"\n");
1411
}
1412
fclose(out);
1413
}
1414
1415
1416
1417
int ReadIntegerMatrix(int **matrix,int row_first,int row_last,
1418
int col_first,int col_last,char *filename)
1419
{
1420
int i,j,iostat;
1421
FILE *in;
1422
int num;
1423
1424
if ((in = fopen(filename,"r")) == NULL) {
1425
printf("The opening of the int matrix file '%s' wasn't successful!\n",filename);
1426
return(FALSE);
1427
}
1428
1429
for(j=row_first;j<=row_last;j++) {
1430
for(i=col_first;i<=col_last;i++) {
1431
iostat = fscanf(in,"%d\n",&num);
1432
matrix[j][i]=num;
1433
}
1434
}
1435
fclose(in);
1436
1437
return(TRUE);
1438
}
1439
1440
1441
1442
void SaveIntegerMatrix(int **matrix,int row_first,int row_last,
1443
int col_first,int col_last,char *filename)
1444
{
1445
int i,j;
1446
FILE *out;
1447
1448
out = fopen(filename,"w");
1449
for (j=row_first;j<=row_last;j++) {
1450
for (i=col_first;i<=col_last;i++) {
1451
fprintf(out,"%-8d",matrix[j][i]);
1452
fprintf(out,"\t");
1453
}
1454
fprintf(out,"\n");
1455
}
1456
fclose(out);
1457
}
1458
1459
1460
void SaveNonZeros(Real **matrix,int row_first,int row_last,
1461
int col_first,int col_last,char *filename)
1462
/* Saves the nonzero elements in an file. */
1463
{
1464
int i,j;
1465
FILE *out;
1466
Real nearzero=1.0e-20;
1467
1468
out = fopen(filename,"w");
1469
for (j=row_first;j<=row_last;j++)
1470
for (i=col_first;i<=col_last;i++)
1471
if (fabs(matrix[j][i]) > nearzero)
1472
fprintf(out,"%d\t %d\t %-12.6le\n",j,i,matrix[j][i]);
1473
1474
fclose(out);
1475
}
1476
1477
1478
int EchoFile(char *filename)
1479
#define LINELENGTH 100
1480
{
1481
FILE *in;
1482
char line[LINELENGTH];
1483
1484
if((in = fopen(filename,"r")) == NULL) {
1485
printf("Could not open file '%s'.\n",filename);
1486
return(1);
1487
}
1488
1489
while(fgets(line,LINELENGTH,in) != NULL)
1490
printf("%s",line);
1491
1492
fclose(in);
1493
return(0);
1494
}
1495
1496
1497
1498
int SetDiscontinuousPoints(struct FemType *data,struct PointType *point,
1499
int material)
1500
/* Create secondary point for a given point.
1501
The variable that is used to set up the boundary must not
1502
have any previously defined Dirichlet points.
1503
*/
1504
{
1505
int i,ind,corner,*order=NULL;
1506
int parent,new;
1507
int newsuccess;
1508
1509
if(point->nopoints == FALSE) {
1510
printf("SetDiscontinuousPoint: No points exists!\n");
1511
return(0);
1512
}
1513
1514
order = Ivector(1,data->noknots);
1515
for(i=1;i<=data->noknots;i++)
1516
order[i] = i;
1517
1518
1519
/* Find the number of new nodes */
1520
new = 0;
1521
for(i=0;i<point->nopoints;i++) {
1522
parent = point->parent[i];
1523
corner = point->corner[i];
1524
ind = data->topology[parent][corner];
1525
if(order[ind] >= 0) {
1526
new++;
1527
order[ind] = -new;
1528
}
1529
}
1530
1531
if(new == 0)
1532
return(0);
1533
1534
newsuccess = CreateNewNodes(data,order,material,new);
1535
1536
return(newsuccess);
1537
}
1538
1539
1540