Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/meshclass.cpp
3206 views
1
#include <mystdlib.h>
2
#include "meshing.hpp"
3
4
#ifdef PARALLEL
5
#include <parallel.hpp>
6
#endif
7
8
namespace netgen
9
{
10
11
Mesh :: Mesh ()
12
{
13
volelements.SetName ("vol elements");
14
surfelements.SetName ("surf elements");
15
points.SetName ("meshpoints");
16
17
boundaryedges = NULL;
18
surfelementht = NULL;
19
segmentht = NULL;
20
21
lochfunc = NULL;
22
mglevels = 1;
23
elementsearchtree = NULL;
24
elementsearchtreets = NextTimeStamp();
25
majortimestamp = timestamp = NextTimeStamp();
26
hglob = 1e10;
27
hmin = 0;
28
numvertices = -1;
29
dimension = 3;
30
31
topology = new MeshTopology (*this);
32
curvedelems = new CurvedElements (*this);
33
clusters = new AnisotropicClusters (*this);
34
ident = new Identifications (*this);
35
36
hpelements = NULL;
37
coarsemesh = NULL;
38
39
ps_startelement = 0;
40
41
geomtype = NO_GEOM;
42
43
bcnames.SetSize(0);
44
#ifdef PARALLEL
45
paralleltop = new ParallelMeshTopology (*this);
46
#endif
47
}
48
49
50
Mesh :: ~Mesh()
51
{
52
delete lochfunc;
53
delete boundaryedges;
54
delete surfelementht;
55
delete segmentht;
56
delete curvedelems;
57
delete clusters;
58
delete topology;
59
delete ident;
60
delete elementsearchtree;
61
62
delete coarsemesh;
63
delete hpelements;
64
65
for (int i = 0; i < materials.Size(); i++)
66
delete [] materials[i];
67
68
for(int i = 0; i < userdata_int.Size(); i++)
69
delete userdata_int[i];
70
for(int i = 0; i < userdata_double.Size(); i++)
71
delete userdata_double[i];
72
73
for (int i = 0; i < bcnames.Size(); i++ )
74
if ( bcnames[i] ) delete bcnames[i];
75
76
#ifdef PARALLEL
77
delete paralleltop;
78
#endif
79
}
80
81
82
Mesh & Mesh :: operator= (const Mesh & mesh2)
83
{
84
points = mesh2.points;
85
// eltyps = mesh2.eltyps;
86
segments = mesh2.segments;
87
surfelements = mesh2.surfelements;
88
volelements = mesh2.volelements;
89
lockedpoints = mesh2.lockedpoints;
90
facedecoding = mesh2.facedecoding;
91
dimension = mesh2.dimension;
92
93
bcnames.SetSize( mesh2.bcnames.Size() );
94
for ( int i = 0; i < mesh2.bcnames.Size(); i++ )
95
if ( mesh2.bcnames[i] ) bcnames[i] = new string ( *mesh2.bcnames[i] );
96
else bcnames[i] = 0;
97
98
return *this;
99
}
100
101
102
void Mesh :: DeleteMesh()
103
{
104
points.SetSize(0);
105
segments.SetSize(0);
106
surfelements.SetSize(0);
107
volelements.SetSize(0);
108
lockedpoints.SetSize(0);
109
surfacesonnode.SetSize(0);
110
111
delete boundaryedges;
112
boundaryedges = NULL;
113
114
openelements.SetSize(0);
115
facedecoding.SetSize(0);
116
117
delete ident;
118
ident = new Identifications (*this);
119
delete topology;
120
topology = new MeshTopology (*this);
121
delete curvedelems;
122
curvedelems = new CurvedElements (*this);
123
delete clusters;
124
clusters = new AnisotropicClusters (*this);
125
126
for ( int i = 0; i < bcnames.Size(); i++ )
127
if ( bcnames[i] ) delete bcnames[i];
128
129
#ifdef PARALLEL
130
delete paralleltop;
131
paralleltop = new ParallelMeshTopology (*this);
132
#endif
133
134
135
timestamp = NextTimeStamp();
136
}
137
138
139
140
PointIndex Mesh :: AddPoint (const Point3d & p, int layer)
141
{
142
NgLock lock(mutex);
143
lock.Lock();
144
145
timestamp = NextTimeStamp();
146
147
PointIndex pi = points.Size() + PointIndex::BASE;
148
points.Append ( MeshPoint (p, layer, INNERPOINT) );
149
150
#ifdef PARALLEL
151
points.Last().SetGhost(0);
152
#endif
153
154
lock.UnLock();
155
156
return pi;
157
}
158
159
PointIndex Mesh :: AddPoint (const Point3d & p, int layer, POINTTYPE type)
160
{
161
NgLock lock(mutex);
162
lock.Lock();
163
164
timestamp = NextTimeStamp();
165
166
PointIndex pi = points.Size() + PointIndex::BASE;
167
points.Append ( MeshPoint (p, layer, type) );
168
169
#ifdef PARALLEL
170
points.Last().SetGhost(0);
171
#endif
172
173
lock.UnLock();
174
175
return pi;
176
}
177
178
179
#ifdef PARALLEL
180
PointIndex Mesh :: AddPoint (const Point3d & p, bool isghost, int layer)
181
{
182
NgLock lock(mutex);
183
lock.Lock();
184
185
timestamp = NextTimeStamp();
186
187
PointIndex pi = points.Size() + PointIndex::BASE;
188
points.Append ( MeshPoint (p, layer, INNERPOINT) );
189
190
points.Last().SetGhost(isghost);
191
192
lock.UnLock();
193
194
return pi;
195
}
196
197
PointIndex Mesh :: AddPoint (const Point3d & p, bool isghost, int layer, POINTTYPE type)
198
{
199
NgLock lock(mutex);
200
lock.Lock();
201
202
timestamp = NextTimeStamp();
203
204
PointIndex pi = points.Size() + PointIndex::BASE;
205
points.Append ( MeshPoint (p, layer, type) );
206
207
points.Last().SetGhost(isghost);
208
209
lock.UnLock();
210
211
return pi;
212
}
213
214
#endif
215
216
217
218
SegmentIndex Mesh :: AddSegment (const Segment & s)
219
{
220
NgLock lock(mutex);
221
lock.Lock();
222
timestamp = NextTimeStamp();
223
224
int maxn = max2 (s.p1, s.p2);
225
maxn += 1-PointIndex::BASE;
226
227
/*
228
if (maxn > ptyps.Size())
229
{
230
int maxo = ptyps.Size();
231
ptyps.SetSize (maxn);
232
for (int i = maxo; i < maxn; i++)
233
ptyps[i] = INNERPOINT;
234
}
235
236
if (ptyps[s.p1] > EDGEPOINT) ptyps[s.p1] = EDGEPOINT;
237
if (ptyps[s.p2] > EDGEPOINT) ptyps[s.p2] = EDGEPOINT;
238
*/
239
240
if (maxn <= points.Size())
241
{
242
if (points[s.p1].Type() > EDGEPOINT)
243
points[s.p1].SetType (EDGEPOINT);
244
if (points[s.p2].Type() > EDGEPOINT)
245
points[s.p2].SetType (EDGEPOINT);
246
}
247
/*
248
else
249
{
250
cerr << "edge points nrs > points.Size" << endl;
251
}
252
*/
253
254
SegmentIndex si = segments.Size();
255
segments.Append (s);
256
257
lock.UnLock();
258
return si;
259
}
260
261
SurfaceElementIndex Mesh :: AddSurfaceElement (const Element2d & el)
262
{
263
NgLock lock(mutex);
264
lock.Lock();
265
timestamp = NextTimeStamp();
266
267
int maxn = el[0];
268
for (int i = 1; i < el.GetNP(); i++)
269
if (el[i] > maxn) maxn = el[i];
270
271
maxn += 1-PointIndex::BASE;
272
273
/*
274
if (maxn > ptyps.Size())
275
{
276
int maxo = ptyps.Size();
277
ptyps.SetSize (maxn);
278
for (i = maxo+PointIndex::BASE;
279
i < maxn+PointIndex::BASE; i++)
280
ptyps[i] = INNERPOINT;
281
282
}
283
*/
284
if (maxn <= points.Size())
285
{
286
for (int i = 0; i < el.GetNP(); i++)
287
if (points[el[i]].Type() > SURFACEPOINT)
288
points[el[i]].SetType(SURFACEPOINT);
289
}
290
/*
291
else
292
{
293
cerr << "surf points nrs > points.Size" << endl;
294
}
295
*/
296
297
SurfaceElementIndex si = surfelements.Size();
298
surfelements.Append (el);
299
300
if (el.index > facedecoding.Size())
301
cerr << "has no facedecoding: fd.size = " << facedecoding.Size() << ", ind = " << el.index << endl;
302
303
surfelements.Last().next = facedecoding[el.index-1].firstelement;
304
facedecoding[el.index-1].firstelement = si;
305
306
#ifdef PARALLEL
307
surfelements.Last().SetGhost ( el.IsGhost() );
308
#endif
309
310
lock.UnLock();
311
return si;
312
}
313
314
315
ElementIndex Mesh :: AddVolumeElement (const Element & el)
316
{
317
NgLock lock(mutex);
318
lock.Lock();
319
320
int maxn = el[0];
321
for (int i = 1; i < el.GetNP(); i++)
322
if (el[i] > maxn) maxn = el[i];
323
324
maxn += 1-PointIndex::BASE;
325
326
/*
327
if (maxn > ptyps.Size())
328
{
329
int maxo = ptyps.Size();
330
ptyps.SetSize (maxn);
331
for (i = maxo+PointIndex::BASE;
332
i < maxn+PointIndex::BASE; i++)
333
ptyps[i] = INNERPOINT;
334
}
335
*/
336
/*
337
if (maxn > points.Size())
338
{
339
cerr << "add vol element before point" << endl;
340
}
341
*/
342
343
int ve = volelements.Size();
344
345
volelements.Append (el);
346
volelements.Last().flags.illegal_valid = 0;
347
348
#ifdef PARALLEL
349
volelements.Last().SetGhost ( el.IsGhost() );
350
#endif
351
352
// while (volelements.Size() > eltyps.Size())
353
// eltyps.Append (FREEELEMENT);
354
355
timestamp = NextTimeStamp();
356
357
lock.UnLock();
358
return ve;
359
}
360
361
362
363
364
365
366
void Mesh :: Save (const string & filename) const
367
{
368
369
ofstream outfile(filename.c_str());
370
371
Save(outfile);
372
}
373
374
375
376
void Mesh :: Save (ostream & outfile) const
377
{
378
int i, j;
379
380
double scale = 1; // globflags.GetNumFlag ("scale", 1);
381
int inverttets = 0; // globflags.GetDefineFlag ("inverttets");
382
int invertsurf = 0; // globflags.GetDefineFlag ("invertsurfacemesh");
383
384
385
386
outfile << "mesh3d" << "\n";
387
388
outfile << "dimension\n" << GetDimension() << "\n";
389
390
outfile << "geomtype\n" << int(geomtype) << "\n";
391
392
393
outfile << "\n";
394
outfile << "# surfnr bcnr domin domout np p1 p2 p3"
395
<< "\n";
396
397
398
switch (geomtype)
399
{
400
case GEOM_STL:
401
outfile << "surfaceelementsgi" << "\n";
402
break;
403
case GEOM_OCC: case GEOM_ACIS:
404
outfile << "surfaceelementsuv" << "\n";
405
break;
406
default:
407
outfile << "surfaceelements" << "\n";
408
}
409
410
outfile << GetNSE() << "\n";
411
412
SurfaceElementIndex sei;
413
for (sei = 0; sei < GetNSE(); sei++)
414
{
415
if ((*this)[sei].GetIndex())
416
{
417
outfile.width(8);
418
outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).SurfNr()+1;
419
outfile.width(8);
420
outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();
421
outfile.width(8);
422
outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainIn();
423
outfile.width(8);
424
outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainOut();
425
}
426
else
427
outfile << " 0 0 0";
428
429
Element2d sel = (*this)[sei];
430
if (invertsurf)
431
sel.Invert();
432
433
outfile.width(8);
434
outfile << sel.GetNP();
435
436
for (j = 0; j < sel.GetNP(); j++)
437
{
438
outfile.width(8);
439
outfile << sel[j];
440
}
441
442
443
switch (geomtype)
444
{
445
case GEOM_STL:
446
for (j = 1; j <= sel.GetNP(); j++)
447
{
448
outfile.width(7);
449
outfile << " " << sel.GeomInfoPi(j).trignum;
450
}
451
break;
452
case GEOM_OCC: case GEOM_ACIS:
453
for (j = 1; j <= sel.GetNP(); j++)
454
{
455
outfile.width(7);
456
outfile << " " << sel.GeomInfoPi(j).u;
457
outfile << " " << sel.GeomInfoPi(j).v;
458
}
459
break;
460
default:
461
outfile << "\n";
462
}
463
464
465
outfile << endl;
466
}
467
468
outfile << "\n" << "\n";
469
outfile << "# matnr np p1 p2 p3 p4" << "\n";
470
outfile << "volumeelements" << "\n";
471
outfile << GetNE() << "\n";
472
473
for (ElementIndex ei = 0; ei < GetNE(); ei++)
474
{
475
outfile.width(8);
476
outfile << (*this)[ei].GetIndex();
477
outfile.width(8);
478
outfile << (*this)[ei].GetNP();
479
480
Element el = (*this)[ei];
481
if (inverttets)
482
el.Invert();
483
484
/*
485
for (j = 0; j < el.GetNP(); j++)
486
for (int k = 0; k < el.GetNP()-1; k++)
487
if (el[k] > el[k+1]) swap (el[k], el[k+1]);
488
*/
489
490
for (j = 0; j < el.GetNP(); j++)
491
{
492
outfile.width(8);
493
outfile << el[j];
494
}
495
outfile << "\n";
496
}
497
498
499
outfile << "\n" << "\n";
500
// outfile << " surf1 surf2 p1 p2" << "\n";
501
outfile << "# surfid 0 p1 p2 trignum1 trignum2 domin/surfnr1 domout/surfnr2 ednr1 dist1 ednr2 dist2 \n";
502
outfile << "edgesegmentsgi2" << "\n";
503
outfile << GetNSeg() << "\n";
504
505
for (i = 1; i <= GetNSeg(); i++)
506
{
507
const Segment & seg = LineSegment (i);
508
outfile.width(8);
509
outfile << seg.si; // 2D: bc number, 3D: wievielte Kante
510
outfile.width(8);
511
outfile << 0;
512
outfile.width(8);
513
outfile << seg.p1;
514
outfile.width(8);
515
outfile << seg.p2;
516
outfile << " ";
517
outfile.width(8);
518
outfile << seg.geominfo[0].trignum; // stl dreiecke
519
outfile << " ";
520
outfile.width(8);
521
outfile << seg.geominfo[1].trignum; // << endl; // stl dreieck
522
523
if (dimension == 3)
524
{
525
outfile << " ";
526
outfile.width(8);
527
outfile << seg.surfnr1+1;
528
outfile << " ";
529
outfile.width(8);
530
outfile << seg.surfnr2+1;
531
}
532
else
533
{
534
outfile << " ";
535
outfile.width(8);
536
outfile << seg.domin;
537
outfile << " ";
538
outfile.width(8);
539
outfile << seg.domout;
540
}
541
542
outfile << " ";
543
outfile.width(8);
544
outfile << seg.edgenr;
545
outfile << " ";
546
outfile.width(12);
547
outfile.precision(16);
548
outfile << seg.epgeominfo[0].dist; // splineparameter (2D)
549
outfile << " ";
550
outfile.width(8);
551
outfile.precision(16);
552
outfile << seg.epgeominfo[1].edgenr; // geometry dependent
553
outfile << " ";
554
outfile.width(12);
555
outfile << seg.epgeominfo[1].dist;
556
557
outfile << "\n";
558
}
559
560
561
outfile << "\n" << "\n";
562
outfile << "# X Y Z" << "\n";
563
outfile << "points" << "\n";
564
outfile << GetNP() << "\n";
565
outfile.precision(16);
566
outfile.setf (ios::fixed, ios::floatfield);
567
outfile.setf (ios::showpoint);
568
569
PointIndex pi;
570
for (pi = PointIndex::BASE;
571
pi < GetNP()+PointIndex::BASE; pi++)
572
{
573
outfile.width(22);
574
outfile << (*this)[pi](0)/scale << " ";
575
outfile.width(22);
576
outfile << (*this)[pi](1)/scale << " ";
577
outfile.width(22);
578
outfile << (*this)[pi](2)/scale << "\n";
579
}
580
581
if (ident -> GetMaxNr() > 0)
582
{
583
outfile << "identifications\n";
584
ARRAY<INDEX_2> identpairs;
585
int cnt = 0;
586
for (i = 1; i <= ident -> GetMaxNr(); i++)
587
{
588
ident -> GetPairs (i, identpairs);
589
cnt += identpairs.Size();
590
}
591
outfile << cnt << "\n";
592
for (i = 1; i <= ident -> GetMaxNr(); i++)
593
{
594
ident -> GetPairs (i, identpairs);
595
for (j = 1; j <= identpairs.Size(); j++)
596
{
597
outfile.width (8);
598
outfile << identpairs.Get(j).I1();
599
outfile.width (8);
600
outfile << identpairs.Get(j).I2();
601
outfile.width (8);
602
outfile << i << "\n";
603
}
604
}
605
606
outfile << "identificationtypes\n";
607
outfile << ident -> GetMaxNr() << "\n";
608
for (i = 1; i <= ident -> GetMaxNr(); i++)
609
{
610
int type = ident -> GetType(i);
611
outfile << " " << type;
612
}
613
outfile << "\n";
614
}
615
616
int cntmat = 0;
617
for (i = 1; i <= materials.Size(); i++)
618
if (materials.Get(i) && strlen (materials.Get(i)))
619
cntmat++;
620
621
if (cntmat)
622
{
623
outfile << "materials" << endl;
624
outfile << cntmat << endl;
625
for (i = 1; i <= materials.Size(); i++)
626
if (materials.Get(i) && strlen (materials.Get(i)))
627
outfile << i << " " << materials.Get(i) << endl;
628
}
629
630
631
int cntbcnames = 0;
632
for ( int ii = 0; ii < bcnames.Size(); ii++ )
633
if ( bcnames[ii] ) cntbcnames++;
634
635
if ( cntbcnames )
636
{
637
outfile << "\n\nbcnames" << endl << bcnames.Size() << endl;
638
for ( i = 0; i < bcnames.Size(); i++ )
639
outfile << i+1 << "\t" << GetBCName(i) << endl;
640
outfile << endl << endl;
641
}
642
643
/*
644
if ( GetDimension() == 2 )
645
{
646
for (i = 1; i <= GetNSeg(); i++)
647
{
648
const Segment & seg = LineSegment (i);
649
if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != "" )
650
{
651
bcprops.Append(seg.si);
652
cntbcnames++;
653
}
654
}
655
}
656
else
657
{
658
for (sei = 0; sei < GetNSE(); sei++)
659
{
660
if ((*this)[sei].GetIndex())
661
{
662
int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();
663
string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName();
664
if ( !bcprops.Contains(bcp) &&
665
name != "" )
666
{
667
bcprops.Append(bcp);
668
cntbcnames++;
669
}
670
}
671
}
672
}
673
674
bcprops.SetSize(0);
675
if ( cntbcnames )
676
{
677
outfile << "\nbcnames" << endl << cntbcnames << endl;
678
if ( GetDimension() == 2 )
679
{
680
for (i = 1; i <= GetNSeg(); i++)
681
{
682
const Segment & seg = LineSegment (i);
683
if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != "" )
684
{
685
bcprops.Append(seg.si);
686
outfile << seg.si << "\t" << seg.GetBCName() << endl;
687
}
688
}
689
}
690
else
691
{
692
for (sei = 0; sei < GetNSE(); sei++)
693
{
694
if ((*this)[sei].GetIndex())
695
{
696
int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();
697
string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName();
698
if ( !bcprops.Contains(bcp) &&
699
name != "" )
700
{
701
bcprops.Append(bcp);
702
outfile << bcp << "\t" << name << endl;
703
}
704
}
705
}
706
}
707
outfile << endl << endl;
708
}
709
*/
710
711
int cnt_sing = 0;
712
for (PointIndex pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++)
713
if ((*this)[pi].Singularity()>=1.) cnt_sing++;
714
715
if (cnt_sing)
716
{
717
outfile << "singular_points" << endl << cnt_sing << endl;
718
for (PointIndex pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++)
719
if ((*this)[pi].Singularity()>=1.)
720
outfile << int(pi) << "\t" << (*this)[pi].Singularity() << endl;
721
}
722
723
cnt_sing = 0;
724
for (SegmentIndex si = 0; si < GetNSeg(); si++)
725
if ( segments[si].singedge_left ) cnt_sing++;
726
if (cnt_sing)
727
{
728
outfile << "singular_edge_left" << endl << cnt_sing << endl;
729
for (SegmentIndex si = 0; si < GetNSeg(); si++)
730
if ( segments[si].singedge_left )
731
outfile << int(si) << "\t" << segments[si].singedge_left << endl;
732
}
733
734
cnt_sing = 0;
735
for (SegmentIndex si = 0; si < GetNSeg(); si++)
736
if ( segments[si].singedge_right ) cnt_sing++;
737
if (cnt_sing)
738
{
739
outfile << "singular_edge_right" << endl << cnt_sing << endl;
740
for (SegmentIndex si = 0; si < GetNSeg(); si++)
741
if ( segments[si].singedge_right )
742
outfile << int(si) << "\t" << segments[si].singedge_right << endl;
743
}
744
745
746
cnt_sing = 0;
747
for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)
748
if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular)
749
cnt_sing++;
750
751
if (cnt_sing)
752
{
753
outfile << "singular_face_inside" << endl << cnt_sing << endl;
754
for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)
755
if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular)
756
outfile << int(sei) << "\t" <<
757
GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular << endl;
758
}
759
760
cnt_sing = 0;
761
for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)
762
if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular) cnt_sing++;
763
if (cnt_sing)
764
{
765
outfile << "singular_face_outside" << endl << cnt_sing << endl;
766
for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)
767
if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular)
768
outfile << int(sei) << "\t"
769
<< GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular << endl;
770
}
771
772
773
}
774
775
776
777
void Mesh :: Load (const string & filename)
778
{
779
780
ifstream infile(filename.c_str());
781
if (!infile.good())
782
throw NgException ("mesh file not found");
783
784
Load(infile);
785
}
786
787
788
789
790
void Mesh :: Load (istream & infile)
791
{
792
793
char str[100];
794
int i, n;
795
796
double scale = 1; // globflags.GetNumFlag ("scale", 1);
797
int inverttets = 0; // globflags.GetDefineFlag ("inverttets");
798
int invertsurf = 0; // globflags.GetDefineFlag ("invertsurfacemesh");
799
800
801
facedecoding.SetSize(0);
802
803
bool endmesh = false;
804
805
while (infile.good() && !endmesh)
806
{
807
infile >> str;
808
809
if (strcmp (str, "dimension") == 0)
810
{
811
infile >> dimension;
812
}
813
814
if (strcmp (str, "geomtype") == 0)
815
{
816
int hi;
817
infile >> hi;
818
geomtype = GEOM_TYPE(hi);
819
}
820
821
822
if (strcmp (str, "surfaceelements") == 0 || strcmp (str, "surfaceelementsgi")==0 || strcmp (str, "surfaceelementsuv") == 0)
823
{
824
infile >> n;
825
PrintMessage (3, n, " surface elements");
826
for (i = 1; i <= n; i++)
827
{
828
int j;
829
int surfnr, bcp, domin, domout, nep, faceind = 0;
830
831
infile >> surfnr >> bcp >> domin >> domout;
832
surfnr--;
833
834
for (j = 1; j <= facedecoding.Size(); j++)
835
if (GetFaceDescriptor(j).SurfNr() == surfnr &&
836
GetFaceDescriptor(j).BCProperty() == bcp &&
837
GetFaceDescriptor(j).DomainIn() == domin &&
838
GetFaceDescriptor(j).DomainOut() == domout)
839
faceind = j;
840
841
if (!faceind)
842
{
843
faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0));
844
GetFaceDescriptor(faceind).SetBCProperty (bcp);
845
}
846
847
infile >> nep;
848
if (!nep) nep = 3;
849
850
Element2d tri(nep);
851
tri.SetIndex(faceind);
852
853
for (j = 1; j <= nep; j++)
854
infile >> tri.PNum(j);
855
856
if (strcmp (str, "surfaceelementsgi") == 0)
857
for (j = 1; j <= nep; j++)
858
infile >> tri.GeomInfoPi(j).trignum;
859
860
if (strcmp (str, "surfaceelementsuv") == 0)
861
for (j = 1; j <= nep; j++)
862
infile >> tri.GeomInfoPi(j).u >> tri.GeomInfoPi(j).v;
863
864
if (invertsurf)
865
tri.Invert();
866
867
AddSurfaceElement (tri);
868
}
869
}
870
871
872
if (strcmp (str, "volumeelements") == 0)
873
{
874
infile >> n;
875
PrintMessage (3, n, " volume elements");
876
for (i = 1; i <= n; i++)
877
{
878
Element el;
879
int hi, nep;
880
infile >> hi;
881
if (hi == 0) hi = 1;
882
el.SetIndex(hi);
883
infile >> nep;
884
el.SetNP(nep);
885
886
for (int j = 0; j < nep; j++)
887
infile >> (int&)(el[j]);
888
889
if (inverttets)
890
el.Invert();
891
892
AddVolumeElement (el);
893
}
894
}
895
896
897
if (strcmp (str, "edgesegments") == 0)
898
{
899
infile >> n;
900
for (i = 1; i <= n; i++)
901
{
902
Segment seg;
903
int hi;
904
infile >> seg.si >> hi >> seg.p1 >> seg.p2;
905
AddSegment (seg);
906
}
907
}
908
909
910
911
if (strcmp (str, "edgesegmentsgi") == 0)
912
{
913
infile >> n;
914
for (i = 1; i <= n; i++)
915
{
916
Segment seg;
917
int hi;
918
infile >> seg.si >> hi >> seg.p1 >> seg.p2
919
>> seg.geominfo[0].trignum
920
>> seg.geominfo[1].trignum;
921
AddSegment (seg);
922
}
923
}
924
925
if (strcmp (str, "edgesegmentsgi2") == 0)
926
{
927
int a;
928
infile >> a;
929
n=a;
930
931
PrintMessage (3, n, " curve elements");
932
933
for (i = 1; i <= n; i++)
934
{
935
Segment seg;
936
int hi;
937
infile >> seg.si >> hi >> seg.p1 >> seg.p2
938
>> seg.geominfo[0].trignum
939
>> seg.geominfo[1].trignum
940
>> seg.surfnr1 >> seg.surfnr2
941
>> seg.edgenr
942
>> seg.epgeominfo[0].dist
943
>> seg.epgeominfo[1].edgenr
944
>> seg.epgeominfo[1].dist;
945
946
seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr;
947
948
seg.domin = seg.surfnr1;
949
seg.domout = seg.surfnr2;
950
951
seg.surfnr1--;
952
seg.surfnr2--;
953
954
AddSegment (seg);
955
}
956
}
957
958
if (strcmp (str, "points") == 0)
959
{
960
infile >> n;
961
PrintMessage (3, n, " points");
962
for (i = 1; i <= n; i++)
963
{
964
Point3d p;
965
infile >> p.X() >> p.Y() >> p.Z();
966
p.X() *= scale;
967
p.Y() *= scale;
968
p.Z() *= scale;
969
AddPoint (p);
970
}
971
}
972
973
if (strcmp (str, "identifications") == 0)
974
{
975
infile >> n;
976
for (i = 1; i <= n; i++)
977
{
978
PointIndex pi1, pi2;
979
int ind;
980
infile >> pi1 >> pi2 >> ind;
981
ident -> Add (pi1, pi2, ind);
982
}
983
}
984
985
if (strcmp (str, "identificationtypes") == 0)
986
{
987
infile >> n;
988
for (i = 1; i <= n; i++)
989
{
990
int type;
991
infile >> type;
992
ident -> SetType(i,Identifications::ID_TYPE(type));
993
}
994
}
995
996
if (strcmp (str, "materials") == 0)
997
{
998
infile >> n;
999
for (i = 1; i <= n; i++)
1000
{
1001
int nr;
1002
string mat;
1003
infile >> nr >> mat;
1004
SetMaterial (nr, mat.c_str());
1005
}
1006
}
1007
1008
if ( strcmp (str, "bcnames" ) == 0 )
1009
{
1010
infile >> n;
1011
ARRAY<int,0> bcnrs(n);
1012
1013
SetNBCNames(n);
1014
for ( i = 1; i <= n; i++ )
1015
{
1016
string nextbcname;
1017
infile >> bcnrs[i-1] >> nextbcname;
1018
bcnames[bcnrs[i-1]-1] = new string(nextbcname);
1019
}
1020
1021
if ( GetDimension() == 2 )
1022
{
1023
for (i = 1; i <= GetNSeg(); i++)
1024
{
1025
Segment & seg = LineSegment (i);
1026
if ( seg.si <= n )
1027
seg.SetBCName (bcnames[seg.si-1]);
1028
else
1029
seg.SetBCName(0);
1030
}
1031
}
1032
else
1033
{
1034
for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)
1035
{
1036
if ((*this)[sei].GetIndex())
1037
{
1038
int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty();
1039
if ( bcp <= n )
1040
GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(bcnames[bcp-1]);
1041
else
1042
GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(0);
1043
1044
}
1045
}
1046
1047
}
1048
1049
1050
}
1051
1052
if (strcmp (str, "singular_points") == 0)
1053
{
1054
infile >> n;
1055
for (i = 1; i <= n; i++)
1056
{
1057
PointIndex pi;
1058
double s;
1059
infile >> pi;
1060
infile >> s;
1061
(*this)[pi].Singularity (s);
1062
}
1063
}
1064
1065
if (strcmp (str, "singular_edge_left") == 0)
1066
{
1067
infile >> n;
1068
for (i = 1; i <= n; i++)
1069
{
1070
SegmentIndex si;
1071
double s;
1072
infile >> si;
1073
infile >> s;
1074
(*this)[si].singedge_left = s;
1075
}
1076
}
1077
if (strcmp (str, "singular_edge_right") == 0)
1078
{
1079
infile >> n;
1080
for (i = 1; i <= n; i++)
1081
{
1082
SegmentIndex si;
1083
double s;
1084
infile >> si;
1085
infile >> s;
1086
(*this)[si].singedge_right = s;
1087
}
1088
}
1089
1090
if (strcmp (str, "singular_face_inside") == 0)
1091
{
1092
infile >> n;
1093
for (i = 1; i <= n; i++)
1094
{
1095
SurfaceElementIndex sei;
1096
double s;
1097
infile >> sei;
1098
infile >> s;
1099
GetFaceDescriptor((*this)[sei].GetIndex()).domin_singular = s;
1100
}
1101
}
1102
1103
if (strcmp (str, "singular_face_outside") == 0)
1104
{
1105
infile >> n;
1106
for (i = 1; i <= n; i++)
1107
{
1108
SurfaceElementIndex sei;
1109
double s;
1110
infile >> sei;
1111
infile >> s;
1112
GetFaceDescriptor((*this)[sei].GetIndex()).domout_singular = s;
1113
}
1114
}
1115
1116
if (strcmp (str, "endmesh") == 0)
1117
endmesh = true;
1118
1119
1120
1121
strcpy (str, "");
1122
}
1123
1124
CalcSurfacesOfNode ();
1125
// BuildConnectedNodes ();
1126
topology -> Update();
1127
clusters -> Update();
1128
1129
SetNextMajorTimeStamp();
1130
// PrintMemInfo (cout);
1131
1132
1133
#ifdef PARALLEL
1134
if ( ntasks > 1 )
1135
{
1136
// for parallel processing
1137
Distribute ();
1138
return;
1139
}
1140
#endif
1141
1142
}
1143
1144
1145
1146
1147
1148
void Mesh :: Merge (const string & filename, const int surfindex_offset)
1149
{
1150
ifstream infile(filename.c_str());
1151
if (!infile.good())
1152
throw NgException ("mesh file not found");
1153
1154
Merge(infile,surfindex_offset);
1155
1156
}
1157
1158
1159
1160
void Mesh :: Merge (istream & infile, const int surfindex_offset)
1161
{
1162
char str[100];
1163
int i, n;
1164
1165
1166
int inverttets = 0; // globflags.GetDefineFlag ("inverttets");
1167
1168
int oldnp = GetNP();
1169
int oldne = GetNSeg();
1170
int oldnd = GetNDomains();
1171
1172
for(SurfaceElementIndex si = 0; si < GetNSE(); si++)
1173
for(int j=1; j<=(*this)[si].GetNP(); j++) (*this)[si].GeomInfoPi(j).trignum = -1;
1174
1175
int max_surfnr = 0;
1176
for (i = 1; i <= GetNFD(); i++)
1177
max_surfnr = max2 (max_surfnr, GetFaceDescriptor(i).SurfNr());
1178
max_surfnr++;
1179
1180
if(max_surfnr < surfindex_offset) max_surfnr = surfindex_offset;
1181
1182
1183
bool endmesh = false;
1184
1185
while (infile.good() && !endmesh)
1186
{
1187
infile >> str;
1188
1189
if (strcmp (str, "surfaceelementsgi") == 0 || strcmp (str, "surfaceelements") == 0)
1190
{
1191
infile >> n;
1192
PrintMessage (3, n, " surface elements");
1193
for (i = 1; i <= n; i++)
1194
{
1195
int j;
1196
int surfnr, bcp, domin, domout, nep, faceind = 0;
1197
infile >> surfnr >> bcp >> domin >> domout;
1198
1199
surfnr--;
1200
1201
if(domin > 0) domin += oldnd;
1202
if(domout > 0) domout += oldnd;
1203
surfnr += max_surfnr;
1204
1205
1206
for (j = 1; j <= facedecoding.Size(); j++)
1207
if (GetFaceDescriptor(j).SurfNr() == surfnr &&
1208
GetFaceDescriptor(j).BCProperty() == bcp &&
1209
GetFaceDescriptor(j).DomainIn() == domin &&
1210
GetFaceDescriptor(j).DomainOut() == domout)
1211
faceind = j;
1212
1213
if (!faceind)
1214
{
1215
faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0));
1216
if(GetDimension() == 2) bcp++;
1217
GetFaceDescriptor(faceind).SetBCProperty (bcp);
1218
}
1219
1220
infile >> nep;
1221
if (!nep) nep = 3;
1222
1223
Element2d tri(nep);
1224
tri.SetIndex(faceind);
1225
1226
for (j = 1; j <= nep; j++)
1227
{
1228
infile >> tri.PNum(j);
1229
tri.PNum(j) = tri.PNum(j) + oldnp;
1230
}
1231
1232
1233
if (strcmp (str, "surfaceelementsgi") == 0)
1234
for (j = 1; j <= nep; j++)
1235
{
1236
infile >> tri.GeomInfoPi(j).trignum;
1237
tri.GeomInfoPi(j).trignum = -1;
1238
}
1239
1240
AddSurfaceElement (tri);
1241
}
1242
}
1243
1244
1245
if (strcmp (str, "edgesegments") == 0)
1246
{
1247
infile >> n;
1248
for (i = 1; i <= n; i++)
1249
{
1250
Segment seg;
1251
int hi;
1252
infile >> seg.si >> hi >> seg.p1 >> seg.p2;
1253
seg.p1 = seg.p1 + oldnp;
1254
seg.p2 = seg.p2 + oldnp;
1255
AddSegment (seg);
1256
}
1257
}
1258
1259
1260
1261
if (strcmp (str, "edgesegmentsgi") == 0)
1262
{
1263
infile >> n;
1264
for (i = 1; i <= n; i++)
1265
{
1266
Segment seg;
1267
int hi;
1268
infile >> seg.si >> hi >> seg.p1 >> seg.p2
1269
>> seg.geominfo[0].trignum
1270
>> seg.geominfo[1].trignum;
1271
seg.p1 = seg.p1 + oldnp;
1272
seg.p2 = seg.p2 + oldnp;
1273
AddSegment (seg);
1274
}
1275
}
1276
if (strcmp (str, "edgesegmentsgi2") == 0)
1277
{
1278
infile >> n;
1279
PrintMessage (3, n, " curve elements");
1280
1281
for (i = 1; i <= n; i++)
1282
{
1283
Segment seg;
1284
int hi;
1285
infile >> seg.si >> hi >> seg.p1 >> seg.p2
1286
>> seg.geominfo[0].trignum
1287
>> seg.geominfo[1].trignum
1288
>> seg.surfnr1 >> seg.surfnr2
1289
>> seg.edgenr
1290
>> seg.epgeominfo[0].dist
1291
>> seg.epgeominfo[1].edgenr
1292
>> seg.epgeominfo[1].dist;
1293
seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr;
1294
1295
seg.surfnr1--;
1296
seg.surfnr2--;
1297
1298
if(seg.surfnr1 >= 0) seg.surfnr1 = seg.surfnr1 + max_surfnr;
1299
if(seg.surfnr2 >= 0) seg.surfnr2 = seg.surfnr2 + max_surfnr;
1300
seg.p1 = seg.p1 +oldnp;
1301
seg.p2 = seg.p2 +oldnp;
1302
seg.edgenr = seg.edgenr + oldne;
1303
seg.epgeominfo[1].edgenr = seg.epgeominfo[1].edgenr + oldne;
1304
1305
AddSegment (seg);
1306
}
1307
}
1308
1309
if (strcmp (str, "volumeelements") == 0)
1310
{
1311
infile >> n;
1312
PrintMessage (3, n, " volume elements");
1313
for (i = 1; i <= n; i++)
1314
{
1315
Element el;
1316
int hi, nep;
1317
infile >> hi;
1318
if (hi == 0) hi = 1;
1319
el.SetIndex(hi+oldnd);
1320
infile >> nep;
1321
el.SetNP(nep);
1322
1323
for (int j = 0; j < nep; j++)
1324
{
1325
infile >> (int&)(el[j]);
1326
el[j] = el[j]+oldnp;
1327
}
1328
1329
if (inverttets)
1330
el.Invert();
1331
1332
AddVolumeElement (el);
1333
}
1334
}
1335
1336
1337
if (strcmp (str, "points") == 0)
1338
{
1339
infile >> n;
1340
PrintMessage (3, n, " points");
1341
for (i = 1; i <= n; i++)
1342
{
1343
Point3d p;
1344
infile >> p.X() >> p.Y() >> p.Z();
1345
AddPoint (p);
1346
}
1347
}
1348
1349
1350
if (strcmp (str, "endmesh") == 0)
1351
{
1352
endmesh = true;
1353
}
1354
1355
1356
if (strcmp (str, "materials") == 0)
1357
{
1358
infile >> n;
1359
for (i = 1; i <= n; i++)
1360
{
1361
int nr;
1362
string mat;
1363
infile >> nr >> mat;
1364
SetMaterial (nr+oldnd, mat.c_str());
1365
}
1366
}
1367
1368
1369
strcpy (str, "");
1370
}
1371
1372
CalcSurfacesOfNode ();
1373
1374
topology -> Update();
1375
clusters -> Update();
1376
1377
SetNextMajorTimeStamp();
1378
}
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
bool Mesh :: TestOk () const
1390
{
1391
for (ElementIndex ei = 0; ei < volelements.Size(); ei++)
1392
{
1393
for (int j = 0; j < 4; j++)
1394
if ( (*this)[ei][j] <= PointIndex::BASE-1)
1395
{
1396
(*testout) << "El " << ei << " has 0 nodes: ";
1397
for (int k = 0; k < 4; k++)
1398
(*testout) << (*this)[ei][k];
1399
break;
1400
}
1401
}
1402
CheckMesh3D (*this);
1403
return 1;
1404
}
1405
1406
void Mesh :: SetAllocSize(int nnodes, int nsegs, int nsel, int nel)
1407
{
1408
points.SetAllocSize(nnodes);
1409
segments.SetAllocSize(nsegs);
1410
surfelements.SetAllocSize(nsel);
1411
volelements.SetAllocSize(nel);
1412
}
1413
1414
1415
void Mesh :: BuildBoundaryEdges(void)
1416
{
1417
delete boundaryedges;
1418
1419
boundaryedges = new INDEX_2_CLOSED_HASHTABLE<int>
1420
(3 * (GetNSE() + GetNOpenElements()) + GetNSeg() + 1);
1421
1422
1423
for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++)
1424
{
1425
const Element2d & sel = surfelements[sei];
1426
if (sel.IsDeleted()) continue;
1427
1428
int si = sel.GetIndex();
1429
1430
for (int j = 0; j < sel.GetNP(); j++)
1431
{
1432
INDEX_2 i2;
1433
i2.I1() = sel.PNumMod(j+1);
1434
i2.I2() = sel.PNumMod(j+2);
1435
i2.Sort();
1436
if (sel.GetNP() <= 4)
1437
boundaryedges->Set (i2, 1);
1438
}
1439
}
1440
1441
1442
for (int i = 0; i < openelements.Size(); i++)
1443
{
1444
const Element2d & sel = openelements[i];
1445
for (int j = 0; j < sel.GetNP(); j++)
1446
{
1447
INDEX_2 i2;
1448
i2.I1() = sel.PNumMod(j+1);
1449
i2.I2() = sel.PNumMod(j+2);
1450
i2.Sort();
1451
boundaryedges->Set (i2, 1);
1452
1453
points[sel[j]].SetType(FIXEDPOINT);
1454
}
1455
}
1456
1457
for (int i = 0; i < GetNSeg(); i++)
1458
{
1459
const Segment & seg = segments[i];
1460
INDEX_2 i2(seg.p1, seg.p2);
1461
i2.Sort();
1462
1463
boundaryedges -> Set (i2, 2);
1464
//segmentht -> Set (i2, i);
1465
}
1466
1467
1468
}
1469
1470
void Mesh :: CalcSurfacesOfNode ()
1471
{
1472
int i, j, k;
1473
SurfaceElementIndex sei;
1474
1475
surfacesonnode.SetSize (GetNP());
1476
1477
delete boundaryedges;
1478
boundaryedges = NULL;
1479
1480
delete surfelementht;
1481
delete segmentht;
1482
1483
/*
1484
surfelementht = new INDEX_3_HASHTABLE<int> (GetNSE()/4 + 1);
1485
segmentht = new INDEX_2_HASHTABLE<int> (GetNSeg() + 1);
1486
*/
1487
1488
surfelementht = new INDEX_3_CLOSED_HASHTABLE<int> (3*GetNSE() + 1);
1489
segmentht = new INDEX_2_CLOSED_HASHTABLE<int> (3*GetNSeg() + 1);
1490
1491
for (sei = 0; sei < GetNSE(); sei++)
1492
{
1493
const Element2d & sel = surfelements[sei];
1494
if (sel.IsDeleted()) continue;
1495
1496
int si = sel.GetIndex();
1497
1498
for (j = 0; j < sel.GetNP(); j++)
1499
{
1500
PointIndex pi = sel[j];
1501
bool found = 0;
1502
for (k = 0; k < surfacesonnode[pi].Size(); k++)
1503
if (surfacesonnode[pi][k] == si)
1504
{
1505
found = 1;
1506
break;
1507
}
1508
1509
if (!found)
1510
surfacesonnode.Add (pi, si);
1511
1512
}
1513
}
1514
/*
1515
for (sei = 0; sei < GetNSE(); sei++)
1516
{
1517
const Element2d & sel = surfelements[sei];
1518
if (sel.IsDeleted()) continue;
1519
1520
INDEX_3 i3;
1521
i3.I1() = sel.PNum(1);
1522
i3.I2() = sel.PNum(2);
1523
i3.I3() = sel.PNum(3);
1524
i3.Sort();
1525
surfelementht -> PrepareSet (i3);
1526
}
1527
1528
surfelementht -> AllocateElements();
1529
*/
1530
for (sei = 0; sei < GetNSE(); sei++)
1531
{
1532
const Element2d & sel = surfelements[sei];
1533
if (sel.IsDeleted()) continue;
1534
1535
INDEX_3 i3;
1536
i3.I1() = sel.PNum(1);
1537
i3.I2() = sel.PNum(2);
1538
i3.I3() = sel.PNum(3);
1539
i3.Sort();
1540
surfelementht -> Set (i3, sei); // war das wichtig ??? sel.GetIndex());
1541
}
1542
1543
int np = GetNP();
1544
1545
if (dimension == 3)
1546
{
1547
for (PointIndex pi = PointIndex::BASE;
1548
pi < np+PointIndex::BASE; pi++)
1549
points[pi].SetType (INNERPOINT);
1550
1551
if (GetNFD() == 0)
1552
{
1553
for (sei = 0; sei < GetNSE(); sei++)
1554
{
1555
const Element2d & sel = surfelements[sei];
1556
if (sel.IsDeleted()) continue;
1557
for (j = 0; j < sel.GetNP(); j++)
1558
{
1559
PointIndex pi = SurfaceElement(sei)[j];
1560
points[pi].SetType(FIXEDPOINT);
1561
}
1562
}
1563
}
1564
else
1565
{
1566
for (sei = 0; sei < GetNSE(); sei++)
1567
{
1568
const Element2d & sel = surfelements[sei];
1569
if (sel.IsDeleted()) continue;
1570
for (j = 0; j < sel.GetNP(); j++)
1571
{
1572
PointIndex pi = sel[j];
1573
int ns = surfacesonnode[pi].Size();
1574
if (ns == 1)
1575
points[pi].SetType(SURFACEPOINT);
1576
if (ns == 2)
1577
points[pi].SetType(EDGEPOINT);
1578
if (ns >= 3)
1579
points[pi].SetType(FIXEDPOINT);
1580
}
1581
}
1582
}
1583
1584
for (i = 0; i < segments.Size(); i++)
1585
{
1586
const Segment & seg = segments[i];
1587
for (j = 1; j <= 2; j++)
1588
{
1589
PointIndex hi = (j == 1) ? seg.p1 : seg.p2;
1590
1591
if (points[hi].Type() == INNERPOINT ||
1592
points[hi].Type() == SURFACEPOINT)
1593
points[hi].SetType(EDGEPOINT);
1594
}
1595
}
1596
1597
1598
for (i = 0; i < lockedpoints.Size(); i++)
1599
points[lockedpoints[i]].SetType(FIXEDPOINT);
1600
}
1601
1602
1603
/*
1604
for (i = 0; i < openelements.Size(); i++)
1605
{
1606
const Element2d & sel = openelements[i];
1607
for (j = 0; j < sel.GetNP(); j++)
1608
{
1609
INDEX_2 i2;
1610
i2.I1() = sel.PNumMod(j+1);
1611
i2.I2() = sel.PNumMod(j+2);
1612
i2.Sort();
1613
boundaryedges->Set (i2, 1);
1614
1615
points[sel[j]].SetType(FIXEDPOINT);
1616
}
1617
}
1618
*/
1619
1620
// eltyps.SetSize (GetNE());
1621
// eltyps = FREEELEMENT;
1622
1623
for (i = 0; i < GetNSeg(); i++)
1624
{
1625
const Segment & seg = segments[i];
1626
INDEX_2 i2(seg.p1, seg.p2);
1627
i2.Sort();
1628
1629
//boundaryedges -> Set (i2, 2);
1630
segmentht -> Set (i2, i);
1631
}
1632
}
1633
1634
1635
void Mesh :: FixPoints (const BitArray & fixpoints)
1636
{
1637
if (fixpoints.Size() != GetNP())
1638
{
1639
cerr << "Mesh::FixPoints: sizes don't fit" << endl;
1640
return;
1641
}
1642
int np = GetNP();
1643
for (int i = 1; i <= np; i++)
1644
if (fixpoints.Test(i))
1645
{
1646
points.Elem(i).SetType (FIXEDPOINT);
1647
}
1648
}
1649
1650
1651
void Mesh :: FindOpenElements (int dom)
1652
{
1653
static int timer = NgProfiler::CreateTimer ("Mesh::FindOpenElements");
1654
static int timera = NgProfiler::CreateTimer ("Mesh::FindOpenElements A");
1655
static int timerb = NgProfiler::CreateTimer ("Mesh::FindOpenElements B");
1656
static int timerc = NgProfiler::CreateTimer ("Mesh::FindOpenElements C");
1657
static int timerd = NgProfiler::CreateTimer ("Mesh::FindOpenElements D");
1658
static int timere = NgProfiler::CreateTimer ("Mesh::FindOpenElements E");
1659
1660
NgProfiler::RegionTimer reg (timer);
1661
1662
int np = GetNP();
1663
int ne = GetNE();
1664
int nse = GetNSE();
1665
1666
ARRAY<int,PointIndex::BASE> numonpoint(np);
1667
1668
numonpoint = 0;
1669
1670
NgProfiler::StartTimer (timera);
1671
for (ElementIndex ei = 0; ei < ne; ei++)
1672
{
1673
const Element & el = (*this)[ei];
1674
if (dom == 0 || dom == el.GetIndex())
1675
{
1676
if (el.GetNP() == 4)
1677
{
1678
INDEX_4 i4(el[0], el[1], el[2], el[3]);
1679
i4.Sort();
1680
numonpoint[i4.I1()]++;
1681
numonpoint[i4.I2()]++;
1682
}
1683
else
1684
for (int j = 0; j < el.GetNP(); j++)
1685
numonpoint[el[j]]++;
1686
}
1687
}
1688
1689
TABLE<ElementIndex,PointIndex::BASE> elsonpoint(numonpoint);
1690
for (ElementIndex ei = 0; ei < ne; ei++)
1691
{
1692
const Element & el = (*this)[ei];
1693
if (dom == 0 || dom == el.GetIndex())
1694
{
1695
if (el.GetNP() == 4)
1696
{
1697
INDEX_4 i4(el[0], el[1], el[2], el[3]);
1698
i4.Sort();
1699
elsonpoint.Add (i4.I1(), ei);
1700
elsonpoint.Add (i4.I2(), ei);
1701
}
1702
else
1703
for (int j = 0; j < el.GetNP(); j++)
1704
elsonpoint.Add (el[j], ei);
1705
}
1706
}
1707
NgProfiler::StopTimer (timera);
1708
1709
1710
1711
1712
NgProfiler::StartTimer (timerb);
1713
1714
1715
1716
ARRAY<char, 1> hasface(GetNFD());
1717
1718
int i;
1719
for (i = 1; i <= GetNFD(); i++)
1720
{
1721
int domin = GetFaceDescriptor(i).DomainIn();
1722
int domout = GetFaceDescriptor(i).DomainOut();
1723
hasface[i] =
1724
dom == 0 && (domin != 0 || domout != 0) ||
1725
dom != 0 && (domin == dom || domout == dom);
1726
}
1727
1728
numonpoint = 0;
1729
for (SurfaceElementIndex sii = 0; sii < nse; sii++)
1730
{
1731
int ind = surfelements[sii].GetIndex();
1732
/*
1733
if (
1734
GetFaceDescriptor(ind).DomainIn() &&
1735
(dom == 0 || dom == GetFaceDescriptor(ind).DomainIn())
1736
||
1737
GetFaceDescriptor(ind).DomainOut() &&
1738
(dom == 0 || dom == GetFaceDescriptor(ind).DomainOut())
1739
)
1740
*/
1741
if (hasface[ind])
1742
{
1743
/*
1744
Element2d hel = surfelements[i];
1745
hel.NormalizeNumbering();
1746
numonpoint[hel[0]]++;
1747
*/
1748
const Element2d & hel = surfelements[sii];
1749
int mini = 0;
1750
for (int j = 1; j < hel.GetNP(); j++)
1751
if (hel[j] < hel[mini])
1752
mini = j;
1753
numonpoint[hel[mini]]++;
1754
}
1755
}
1756
1757
TABLE<SurfaceElementIndex,PointIndex::BASE> selsonpoint(numonpoint);
1758
for (SurfaceElementIndex sii = 0; sii < nse; sii++)
1759
{
1760
int ind = surfelements[sii].GetIndex();
1761
1762
/*
1763
if (
1764
GetFaceDescriptor(ind).DomainIn() &&
1765
(dom == 0 || dom == GetFaceDescriptor(ind).DomainIn())
1766
||
1767
GetFaceDescriptor(ind).DomainOut() &&
1768
(dom == 0 || dom == GetFaceDescriptor(ind).DomainOut())
1769
)
1770
*/
1771
if (hasface[ind])
1772
{
1773
/*
1774
Element2d hel = surfelements[i];
1775
hel.NormalizeNumbering();
1776
selsonpoint.Add (hel[0], i);
1777
*/
1778
const Element2d & hel = surfelements[sii];
1779
int mini = 0;
1780
for (int j = 1; j < hel.GetNP(); j++)
1781
if (hel[j] < hel[mini])
1782
mini = j;
1783
selsonpoint.Add (hel[mini], sii);
1784
}
1785
}
1786
1787
1788
NgProfiler::StopTimer (timerb);
1789
1790
int ii, j, k, l;
1791
PointIndex pi;
1792
SurfaceElementIndex sei;
1793
Element2d hel;
1794
1795
NgProfiler::RegionTimer regc (timerc);
1796
1797
1798
INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht(100);
1799
openelements.SetSize(0);
1800
1801
for (pi = PointIndex::BASE; pi < np+PointIndex::BASE; pi++)
1802
if (selsonpoint[pi].Size()+elsonpoint[pi].Size())
1803
{
1804
faceht.SetSize (2 * selsonpoint[pi].Size() + 4 * elsonpoint[pi].Size());
1805
1806
FlatArray<SurfaceElementIndex> row = selsonpoint[pi];
1807
for (ii = 0; ii < row.Size(); ii++)
1808
{
1809
hel = SurfaceElement(row[ii]);
1810
int ind = hel.GetIndex();
1811
1812
if (GetFaceDescriptor(ind).DomainIn() &&
1813
(dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) )
1814
{
1815
hel.NormalizeNumbering();
1816
if (hel.PNum(1) == pi)
1817
{
1818
INDEX_3 i3(hel[0], hel[1], hel[2]);
1819
INDEX_2 i2 (GetFaceDescriptor(ind).DomainIn(),
1820
(hel.GetNP() == 3)
1821
? PointIndex (PointIndex::BASE-1)
1822
: hel.PNum(4));
1823
faceht.Set (i3, i2);
1824
}
1825
}
1826
if (GetFaceDescriptor(ind).DomainOut() &&
1827
(dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) )
1828
{
1829
hel.Invert();
1830
hel.NormalizeNumbering();
1831
if (hel.PNum(1) == pi)
1832
{
1833
INDEX_3 i3(hel[0], hel[1], hel[2]);
1834
INDEX_2 i2 (GetFaceDescriptor(ind).DomainOut(),
1835
(hel.GetNP() == 3)
1836
? PointIndex (PointIndex::BASE-1)
1837
: hel.PNum(4));
1838
faceht.Set (i3, i2);
1839
}
1840
}
1841
}
1842
1843
1844
FlatArray<ElementIndex> rowel = elsonpoint[pi];
1845
for (ii = 0; ii < rowel.Size(); ii++)
1846
{
1847
const Element & el = VolumeElement(rowel[ii]);
1848
1849
if (dom == 0 || el.GetIndex() == dom)
1850
{
1851
for (j = 1; j <= el.GetNFaces(); j++)
1852
{
1853
el.GetFace (j, hel);
1854
hel.Invert();
1855
hel.NormalizeNumbering();
1856
1857
if (hel[0] == pi)
1858
{
1859
INDEX_3 i3(hel[0], hel[1], hel[2]);
1860
1861
if (faceht.Used (i3))
1862
{
1863
INDEX_2 i2 = faceht.Get(i3);
1864
if (i2.I1() == el.GetIndex())
1865
{
1866
i2.I1() = PointIndex::BASE-1;
1867
faceht.Set (i3, i2);
1868
}
1869
else
1870
{
1871
if (i2.I1() == 0)
1872
{
1873
PrintSysError ("more elements on face");
1874
(*testout) << "more elements on face!!!" << endl;
1875
(*testout) << "el = " << el << endl;
1876
(*testout) << "hel = " << hel << endl;
1877
(*testout) << "face = " << i3 << endl;
1878
(*testout) << "points = " << endl;
1879
for (int jj = 1; jj <= 3; jj++)
1880
(*testout) << "p = " << Point(i3.I(jj)) << endl;
1881
}
1882
}
1883
}
1884
else
1885
{
1886
hel.Invert();
1887
hel.NormalizeNumbering();
1888
INDEX_3 i3(hel[0], hel[1], hel[2]);
1889
INDEX_2 i2(el.GetIndex(),
1890
(hel.GetNP() == 3)
1891
? PointIndex (PointIndex::BASE-1)
1892
: hel[3]);
1893
faceht.Set (i3, i2);
1894
}
1895
}
1896
}
1897
}
1898
}
1899
for (i = 0; i < faceht.Size(); i++)
1900
if (faceht.UsedPos (i))
1901
{
1902
INDEX_3 i3;
1903
INDEX_2 i2;
1904
faceht.GetData (i, i3, i2);
1905
if (i2.I1() != PointIndex::BASE-1)
1906
{
1907
Element2d tri;
1908
tri.SetType ( (i2.I2() == PointIndex::BASE-1) ? TRIG : QUAD);
1909
for (l = 0; l < 3; l++)
1910
tri[l] = i3.I(l+1);
1911
tri.PNum(4) = i2.I2();
1912
tri.SetIndex (i2.I1());
1913
1914
// tri.Invert();
1915
1916
openelements.Append (tri);
1917
}
1918
}
1919
}
1920
1921
int cnt3 = 0;
1922
for (i = 0; i < openelements.Size(); i++)
1923
if (openelements[i].GetNP() == 3)
1924
cnt3++;
1925
1926
int cnt4 = openelements.Size() - cnt3;
1927
1928
1929
MyStr treequad;
1930
if (cnt4)
1931
treequad = MyStr(" (") + MyStr(cnt3) + MyStr (" + ") +
1932
MyStr(cnt4) + MyStr(")");
1933
1934
PrintMessage (5, openelements.Size(), treequad, " open elements");
1935
1936
BuildBoundaryEdges();
1937
1938
1939
NgProfiler::RegionTimer regd (timerd);
1940
1941
for (i = 1; i <= openelements.Size(); i++)
1942
{
1943
const Element2d & sel = openelements.Get(i);
1944
1945
if (boundaryedges)
1946
for (j = 1; j <= sel.GetNP(); j++)
1947
{
1948
INDEX_2 i2;
1949
i2.I1() = sel.PNumMod(j);
1950
i2.I2() = sel.PNumMod(j+1);
1951
i2.Sort();
1952
boundaryedges->Set (i2, 1);
1953
}
1954
1955
for (j = 1; j <= 3; j++)
1956
{
1957
int pi = sel.PNum(j);
1958
if (pi < points.Size()+PointIndex::BASE)
1959
points[pi].SetType (FIXEDPOINT);
1960
}
1961
}
1962
1963
1964
NgProfiler::RegionTimer rege (timere);
1965
1966
/*
1967
for (i = 1; i <= GetNSeg(); i++)
1968
{
1969
const Segment & seg = LineSegment(i);
1970
INDEX_2 i2(seg.p1, seg.p2);
1971
i2.Sort();
1972
1973
if (!boundaryedges->Used (i2))
1974
cerr << "WARNING: no boundedge, but seg edge: " << i2 << endl;
1975
1976
boundaryedges -> Set (i2, 2);
1977
segmentht -> Set (i2, i-1);
1978
}
1979
*/
1980
}
1981
1982
bool Mesh :: HasOpenQuads () const
1983
{
1984
int no = GetNOpenElements();
1985
for (int i = 0; i < no; i++)
1986
if (openelements[i].GetNP() == 4)
1987
return true;
1988
return false;
1989
}
1990
1991
1992
1993
1994
1995
void Mesh :: FindOpenSegments (int surfnr)
1996
{
1997
int i, j, k;
1998
1999
// new version, general elemetns
2000
// hash index: pnum1-2
2001
// hash data : surfnr, surfel-nr (pos) or segment nr(neg)
2002
INDEX_2_HASHTABLE<INDEX_2> faceht(4 * GetNSE()+GetNSeg()+1);
2003
2004
PrintMessage (5, "Test Opensegments");
2005
for (i = 1; i <= GetNSeg(); i++)
2006
{
2007
const Segment & seg = LineSegment (i);
2008
2009
if (surfnr == 0 || seg.si == surfnr)
2010
{
2011
INDEX_2 key(seg.p1, seg.p2);
2012
INDEX_2 data(seg.si, -i);
2013
2014
if (faceht.Used (key))
2015
{
2016
cerr << "ERROR: Segment " << seg << " already used" << endl;
2017
(*testout) << "ERROR: Segment " << seg << " already used" << endl;
2018
}
2019
2020
faceht.Set (key, data);
2021
}
2022
}
2023
2024
2025
for (i = 1; i <= GetNSeg(); i++)
2026
{
2027
const Segment & seg = LineSegment (i);
2028
2029
if (surfnr == 0 || seg.si == surfnr)
2030
{
2031
INDEX_2 key(seg.p2, seg.p1);
2032
if (!faceht.Used(key))
2033
{
2034
cerr << "ERROR: Segment " << seg << " brother not used" << endl;
2035
(*testout) << "ERROR: Segment " << seg << " brother not used" << endl;
2036
}
2037
}
2038
}
2039
2040
2041
for (i = 1; i <= GetNSE(); i++)
2042
{
2043
const Element2d & el = SurfaceElement(i);
2044
if (el.IsDeleted()) continue;
2045
2046
if (surfnr == 0 || el.GetIndex() == surfnr)
2047
{
2048
for (j = 1; j <= el.GetNP(); j++)
2049
{
2050
INDEX_2 seg (el.PNumMod(j), el.PNumMod(j+1));
2051
INDEX_2 data;
2052
2053
if (seg.I1() <= 0 || seg.I2() <= 0)
2054
cerr << "seg = " << seg << endl;
2055
2056
if (faceht.Used(seg))
2057
{
2058
data = faceht.Get(seg);
2059
if (data.I1() == el.GetIndex())
2060
{
2061
data.I1() = 0;
2062
faceht.Set (seg, data);
2063
}
2064
else
2065
{
2066
PrintSysError ("hash table si not fitting for segment: ",
2067
seg.I1(), "-", seg.I2(), " other = ",
2068
data.I2());
2069
}
2070
}
2071
else
2072
{
2073
Swap (seg.I1(), seg.I2());
2074
data.I1() = el.GetIndex();
2075
data.I2() = i;
2076
2077
faceht.Set (seg, data);
2078
}
2079
}
2080
}
2081
}
2082
2083
(*testout) << "open segments: " << endl;
2084
opensegments.SetSize(0);
2085
for (i = 1; i <= faceht.GetNBags(); i++)
2086
for (j = 1; j <= faceht.GetBagSize(i); j++)
2087
{
2088
INDEX_2 i2;
2089
INDEX_2 data;
2090
faceht.GetData (i, j, i2, data);
2091
if (data.I1()) // surfnr
2092
{
2093
Segment seg;
2094
seg.p1 = i2.I1();
2095
seg.p2 = i2.I2();
2096
seg.si = data.I1();
2097
2098
// find geomdata:
2099
if (data.I2() > 0)
2100
{
2101
// segment due to triangle
2102
const Element2d & el = SurfaceElement (data.I2());
2103
for (k = 1; k <= el.GetNP(); k++)
2104
{
2105
if (seg.p1 == el.PNum(k))
2106
seg.geominfo[0] = el.GeomInfoPi(k);
2107
if (seg.p2 == el.PNum(k))
2108
seg.geominfo[1] = el.GeomInfoPi(k);
2109
}
2110
2111
(*testout) << "trig seg: ";
2112
}
2113
else
2114
{
2115
// segment due to line
2116
const Segment & lseg = LineSegment (-data.I2());
2117
seg.geominfo[0] = lseg.geominfo[0];
2118
seg.geominfo[1] = lseg.geominfo[1];
2119
2120
(*testout) << "line seg: ";
2121
}
2122
2123
(*testout) << seg.p1 << " - " << seg.p2
2124
<< " len = " << Dist (Point(seg.p1), Point(seg.p2))
2125
<< endl;
2126
2127
opensegments.Append (seg);
2128
if (seg.geominfo[0].trignum <= 0 || seg.geominfo[1].trignum <= 0)
2129
{
2130
(*testout) << "Problem with open segment: " << seg << endl;
2131
}
2132
2133
}
2134
}
2135
2136
PrintMessage (3, opensegments.Size(), " open segments found");
2137
(*testout) << opensegments.Size() << " open segments found" << endl;
2138
2139
/*
2140
ptyps.SetSize (GetNP());
2141
for (i = 1; i <= ptyps.Size(); i++)
2142
ptyps.Elem(i) = SURFACEPOINT;
2143
2144
for (i = 1; i <= GetNSeg(); i++)
2145
{
2146
const Segment & seg = LineSegment (i);
2147
ptyps.Elem(seg.p1) = EDGEPOINT;
2148
ptyps.Elem(seg.p2) = EDGEPOINT;
2149
}
2150
for (i = 1; i <= GetNOpenSegments(); i++)
2151
{
2152
const Segment & seg = GetOpenSegment (i);
2153
ptyps.Elem(seg.p1) = EDGEPOINT;
2154
ptyps.Elem(seg.p2) = EDGEPOINT;
2155
}
2156
*/
2157
for (i = 1; i <= points.Size(); i++)
2158
points.Elem(i).SetType(SURFACEPOINT);
2159
2160
for (i = 1; i <= GetNSeg(); i++)
2161
{
2162
const Segment & seg = LineSegment (i);
2163
points[seg.p1].SetType(EDGEPOINT);
2164
points[seg.p2].SetType(EDGEPOINT);
2165
}
2166
for (i = 1; i <= GetNOpenSegments(); i++)
2167
{
2168
const Segment & seg = GetOpenSegment (i);
2169
points[seg.p1].SetType (EDGEPOINT);
2170
points[seg.p2].SetType (EDGEPOINT);
2171
}
2172
2173
2174
2175
/*
2176
2177
for (i = 1; i <= openelements.Size(); i++)
2178
{
2179
const Element2d & sel = openelements.Get(i);
2180
2181
if (boundaryedges)
2182
for (j = 1; j <= sel.GetNP(); j++)
2183
{
2184
INDEX_2 i2;
2185
i2.I1() = sel.PNumMod(j);
2186
i2.I2() = sel.PNumMod(j+1);
2187
i2.Sort();
2188
boundaryedges->Set (i2, 1);
2189
}
2190
2191
for (j = 1; j <= 3; j++)
2192
{
2193
int pi = sel.PNum(j);
2194
if (pi <= ptyps.Size())
2195
ptyps.Elem(pi) = FIXEDPOINT;
2196
}
2197
}
2198
*/
2199
}
2200
2201
2202
void Mesh :: RemoveOneLayerSurfaceElements ()
2203
{
2204
int i, j;
2205
int np = GetNP();
2206
2207
FindOpenSegments();
2208
BitArray frontpoints(np);
2209
2210
frontpoints.Clear();
2211
for (i = 1; i <= GetNOpenSegments(); i++)
2212
{
2213
const Segment & seg = GetOpenSegment(i);
2214
frontpoints.Set (seg.p1);
2215
frontpoints.Set (seg.p2);
2216
}
2217
2218
for (i = 1; i <= GetNSE(); i++)
2219
{
2220
Element2d & sel = surfelements.Elem(i);
2221
int remove = 0;
2222
for (j = 1; j <= sel.GetNP(); j++)
2223
if (frontpoints.Test(sel.PNum(j)))
2224
remove = 1;
2225
if (remove)
2226
sel.PNum(1) = 0;
2227
}
2228
2229
for (i = surfelements.Size(); i >= 1; i--)
2230
{
2231
if (surfelements.Elem(i).PNum(1) == 0)
2232
{
2233
surfelements.Elem(i) = surfelements.Last();
2234
surfelements.DeleteLast();
2235
}
2236
}
2237
2238
for (int i = 0; i < facedecoding.Size(); i++)
2239
facedecoding[i].firstelement = -1;
2240
for (int i = surfelements.Size()-1; i >= 0; i--)
2241
{
2242
int ind = surfelements[i].GetIndex();
2243
surfelements[i].next = facedecoding[ind-1].firstelement;
2244
facedecoding[ind-1].firstelement = i;
2245
}
2246
2247
2248
timestamp = NextTimeStamp();
2249
// Compress();
2250
}
2251
2252
2253
2254
2255
2256
void Mesh :: FreeOpenElementsEnvironment (int layers)
2257
{
2258
int i, j, k;
2259
PointIndex pi;
2260
const int large = 9999;
2261
ARRAY<int,PointIndex::BASE> dist(GetNP());
2262
2263
dist = large;
2264
2265
for (int i = 1; i <= GetNOpenElements(); i++)
2266
{
2267
const Element2d & face = OpenElement(i);
2268
for (j = 0; j < face.GetNP(); j++)
2269
dist[face[j]] = 1;
2270
}
2271
2272
for (k = 1; k <= layers; k++)
2273
for (i = 1; i <= GetNE(); i++)
2274
{
2275
const Element & el = VolumeElement(i);
2276
if (el[0] == -1 || el.IsDeleted()) continue;
2277
2278
int elmin = large;
2279
for (j = 0; j < el.GetNP(); j++)
2280
if (dist[el[j]] < elmin)
2281
elmin = dist[el[j]];
2282
2283
if (elmin < large)
2284
{
2285
for (j = 0; j < el.GetNP(); j++)
2286
if (dist[el[j]] > elmin+1)
2287
dist[el[j]] = elmin+1;
2288
}
2289
}
2290
2291
int cntfree = 0;
2292
for (i = 1; i <= GetNE(); i++)
2293
{
2294
Element & el = VolumeElement(i);
2295
if (el[0] == -1 || el.IsDeleted()) continue;
2296
2297
int elmin = large;
2298
for (j = 0; j < el.GetNP(); j++)
2299
if (dist[el[j]] < elmin)
2300
elmin = dist[el[j]];
2301
2302
el.flags.fixed = elmin > layers;
2303
// eltyps.Elem(i) = (elmin <= layers) ?
2304
// FREEELEMENT : FIXEDELEMENT;
2305
if (elmin <= layers)
2306
cntfree++;
2307
}
2308
2309
PrintMessage (5, "free: ", cntfree, ", fixed: ", GetNE()-cntfree);
2310
(*testout) << "free: " << cntfree << ", fixed: " << GetNE()-cntfree << endl;
2311
2312
for (pi = PointIndex::BASE;
2313
pi < GetNP()+PointIndex::BASE; pi++)
2314
{
2315
if (dist[pi] > layers+1)
2316
points[pi].SetType(FIXEDPOINT);
2317
}
2318
}
2319
2320
2321
2322
void Mesh :: SetLocalH (const Point3d & pmin, const Point3d & pmax, double grading)
2323
{
2324
Point3d c = Center (pmin, pmax);
2325
double d = max3 (pmax.X()-pmin.X(),
2326
pmax.Y()-pmin.Y(),
2327
pmax.Z()-pmin.Z());
2328
d /= 2;
2329
Point3d pmin2 = c - Vec3d (d, d, d);
2330
Point3d pmax2 = c + Vec3d (d, d, d);
2331
2332
2333
delete lochfunc;
2334
lochfunc = new LocalH (pmin2, pmax2, grading);
2335
}
2336
2337
void Mesh :: RestrictLocalH (const Point3d & p, double hloc)
2338
{
2339
if(hloc < hmin)
2340
hloc = hmin;
2341
2342
//cout << "restrict h in " << p << " to " << hloc << endl;
2343
if (!lochfunc)
2344
{
2345
PrintWarning("RestrictLocalH called, creating mesh-size tree");
2346
2347
Point3d boxmin, boxmax;
2348
GetBox (boxmin, boxmax);
2349
SetLocalH (boxmin, boxmax, 0.8);
2350
}
2351
2352
lochfunc -> SetH (p, hloc);
2353
}
2354
2355
void Mesh :: RestrictLocalHLine (const Point3d & p1,
2356
const Point3d & p2,
2357
double hloc)
2358
{
2359
if(hloc < hmin)
2360
hloc = hmin;
2361
2362
// cout << "restrict h along " << p1 << " - " << p2 << " to " << hloc << endl;
2363
int i;
2364
int steps = int (Dist (p1, p2) / hloc) + 2;
2365
Vec3d v(p1, p2);
2366
2367
for (i = 0; i <= steps; i++)
2368
{
2369
Point3d p = p1 + (double(i)/double(steps) * v);
2370
RestrictLocalH (p, hloc);
2371
}
2372
}
2373
2374
2375
void Mesh :: SetMinimalH (double h)
2376
{
2377
hmin = h;
2378
}
2379
2380
2381
void Mesh :: SetGlobalH (double h)
2382
{
2383
hglob = h;
2384
}
2385
2386
double Mesh :: MaxHDomain (int dom) const
2387
{
2388
if (maxhdomain.Size())
2389
return maxhdomain.Get(dom);
2390
else
2391
return 1e10;
2392
}
2393
2394
void Mesh :: SetMaxHDomain (const ARRAY<double> & mhd)
2395
{
2396
maxhdomain.SetSize(mhd.Size());
2397
for (int i = 1; i <= mhd.Size(); i++)
2398
maxhdomain.Elem(i) = mhd.Get(i);
2399
}
2400
2401
2402
double Mesh :: GetH (const Point3d & p) const
2403
{
2404
double hmin = hglob;
2405
if (lochfunc)
2406
{
2407
double hl = lochfunc->GetH (p);
2408
if (hl < hglob)
2409
hmin = hl;
2410
}
2411
return hmin;
2412
}
2413
2414
double Mesh :: GetMinH (const Point3d & pmin, const Point3d & pmax)
2415
{
2416
double hmin = hglob;
2417
if (lochfunc)
2418
{
2419
double hl = lochfunc->GetMinH (pmin, pmax);
2420
if (hl < hmin)
2421
hmin = hl;
2422
}
2423
return hmin;
2424
}
2425
2426
2427
2428
2429
2430
double Mesh :: AverageH (int surfnr) const
2431
{
2432
int i, j, n;
2433
double hi, hsum;
2434
double maxh = 0, minh = 1e10;
2435
2436
hsum = 0;
2437
n = 0;
2438
for (i = 1; i <= GetNSE(); i++)
2439
{
2440
const Element2d & el = SurfaceElement(i);
2441
if (surfnr == 0 || el.GetIndex() == surfnr)
2442
{
2443
for (j = 1; j <= 3; j++)
2444
{
2445
hi = Dist (Point (el.PNumMod(j)),
2446
Point (el.PNumMod(j+1)));
2447
2448
hsum += hi;
2449
2450
if (hi > maxh) maxh = hi;
2451
if (hi < minh) minh = hi;
2452
n++;
2453
}
2454
}
2455
}
2456
2457
PrintMessage (5, "minh = ", minh, " avh = ", (hsum/n), " maxh = ", maxh);
2458
return (hsum / n);
2459
}
2460
2461
2462
2463
void Mesh :: CalcLocalH ()
2464
{
2465
if (!lochfunc)
2466
{
2467
Point3d pmin, pmax;
2468
GetBox (pmin, pmax);
2469
SetLocalH (pmin, pmax, mparam.grading);
2470
}
2471
2472
PrintMessage (3,
2473
"CalcLocalH: ",
2474
GetNP(), " Points ",
2475
GetNE(), " Elements ",
2476
GetNSE(), " Surface Elements");
2477
2478
2479
int i;
2480
for (i = 0; i < GetNSE(); i++)
2481
{
2482
const Element2d & el = surfelements[i];
2483
int j;
2484
2485
if (el.GetNP() == 3)
2486
{
2487
double hel = -1;
2488
for (j = 1; j <= 3; j++)
2489
{
2490
const Point3d & p1 = points[el.PNumMod(j)];
2491
const Point3d & p2 = points[el.PNumMod(j+1)];
2492
2493
/*
2494
INDEX_2 i21(el.PNumMod(j), el.PNumMod(j+1));
2495
INDEX_2 i22(el.PNumMod(j+1), el.PNumMod(j));
2496
if (! identifiedpoints->Used (i21) &&
2497
! identifiedpoints->Used (i22) )
2498
*/
2499
if (!ident -> UsedSymmetric (el.PNumMod(j),
2500
el.PNumMod(j+1)))
2501
{
2502
double hedge = Dist (p1, p2);
2503
if (hedge > hel)
2504
hel = hedge;
2505
// lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2));
2506
// (*testout) << "trigseth, p1,2 = " << el.PNumMod(j) << ", " << el.PNumMod(j+1)
2507
// << " h = " << (2 * Dist(p1, p2)) << endl;
2508
}
2509
}
2510
2511
if (hel > 0)
2512
{
2513
const Point3d & p1 = points[el.PNum(1)];
2514
const Point3d & p2 = points[el.PNum(2)];
2515
const Point3d & p3 = points[el.PNum(3)];
2516
lochfunc->SetH (Center (p1, p2, p3), hel);
2517
}
2518
}
2519
else
2520
{
2521
{
2522
const Point3d & p1 = points[el.PNum(1)];
2523
const Point3d & p2 = points[el.PNum(2)];
2524
lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2));
2525
}
2526
{
2527
const Point3d & p1 = points[el.PNum(3)];
2528
const Point3d & p2 = points[el.PNum(4)];
2529
lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2));
2530
}
2531
}
2532
}
2533
2534
for (i = 0; i < GetNSeg(); i++)
2535
{
2536
const Segment & seg = segments[i];
2537
const Point3d & p1 = points[seg.p1];
2538
const Point3d & p2 = points[seg.p2];
2539
/*
2540
INDEX_2 i21(seg.p1, seg.p2);
2541
INDEX_2 i22(seg.p2, seg.p1);
2542
if (identifiedpoints)
2543
if (!identifiedpoints->Used (i21) && !identifiedpoints->Used (i22))
2544
*/
2545
if (!ident -> UsedSymmetric (seg.p1, seg.p2))
2546
{
2547
lochfunc->SetH (Center (p1, p2), Dist (p1, p2));
2548
}
2549
}
2550
/*
2551
cerr << "do vol" << endl;
2552
for (i = 1; i <= GetNE(); i++)
2553
{
2554
const Element & el = VolumeElement(i);
2555
if (el.GetType() == TET)
2556
{
2557
int j, k;
2558
for (j = 2; j <= 4; j++)
2559
for (k = 1; k < j; k++)
2560
{
2561
const Point3d & p1 = Point (el.PNum(j));
2562
const Point3d & p2 = Point (el.PNum(k));
2563
lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2));
2564
(*testout) << "set vol h to " << (2 * Dist (p1, p2)) << endl;
2565
2566
}
2567
}
2568
}
2569
*/
2570
2571
/*
2572
const char * meshsizefilename =
2573
globflags.GetStringFlag ("meshsize", NULL);
2574
if (meshsizefilename)
2575
{
2576
ifstream msf(meshsizefilename);
2577
if (msf)
2578
{
2579
int nmsp;
2580
msf >> nmsp;
2581
for (i = 1; i <= nmsp; i++)
2582
{
2583
Point3d pi;
2584
double hi;
2585
msf >> pi.X() >> pi.Y() >> pi.Z();
2586
msf >> hi;
2587
lochfunc->SetH (pi, hi);
2588
}
2589
}
2590
}
2591
*/
2592
// lochfunc -> Convexify();
2593
// lochfunc -> PrintMemInfo (cout);
2594
}
2595
2596
2597
void Mesh :: CalcLocalHFromPointDistances(void)
2598
{
2599
PrintMessage (3, "Calculating local h from point distances");
2600
2601
if (!lochfunc)
2602
{
2603
Point3d pmin, pmax;
2604
GetBox (pmin, pmax);
2605
2606
SetLocalH (pmin, pmax, mparam.grading);
2607
}
2608
2609
PointIndex i,j;
2610
double hl;
2611
2612
2613
for (i = PointIndex::BASE;
2614
i < GetNP()+PointIndex::BASE; i++)
2615
{
2616
for(j=i+1; j<GetNP()+PointIndex::BASE; j++)
2617
{
2618
const Point3d & p1 = points[i];
2619
const Point3d & p2 = points[j];
2620
hl = Dist(p1,p2);
2621
RestrictLocalH(p1,hl);
2622
RestrictLocalH(p2,hl);
2623
//cout << "restricted h at " << p1 << " and " << p2 << " to " << hl << endl;
2624
}
2625
}
2626
2627
2628
}
2629
2630
2631
void Mesh :: CalcLocalHFromSurfaceCurvature (double elperr)
2632
{
2633
PrintMessage (3, "Calculating local h from surface curvature");
2634
2635
if (!lochfunc)
2636
{
2637
Point3d pmin, pmax;
2638
GetBox (pmin, pmax);
2639
2640
SetLocalH (pmin, pmax, mparam.grading);
2641
}
2642
2643
2644
INDEX_2_HASHTABLE<int> edges(3 * GetNP() + 2);
2645
INDEX_2_HASHTABLE<int> bedges(GetNSeg() + 2);
2646
int i, j;
2647
2648
for (i = 1; i <= GetNSeg(); i++)
2649
{
2650
const Segment & seg = LineSegment(i);
2651
INDEX_2 i2(seg.p1, seg.p2);
2652
i2.Sort();
2653
bedges.Set (i2, 1);
2654
}
2655
for (i = 1; i <= GetNSE(); i++)
2656
{
2657
const Element2d & sel = SurfaceElement(i);
2658
if (!sel.PNum(1))
2659
continue;
2660
for (j = 1; j <= 3; j++)
2661
{
2662
INDEX_2 i2(sel.PNumMod(j), sel.PNumMod(j+1));
2663
i2.Sort();
2664
if (bedges.Used(i2)) continue;
2665
2666
if (edges.Used(i2))
2667
{
2668
int other = edges.Get(i2);
2669
2670
const Element2d & elother = SurfaceElement(other);
2671
2672
int pi3 = 1;
2673
while ( (sel.PNum(pi3) == i2.I1()) ||
2674
(sel.PNum(pi3) == i2.I2()))
2675
pi3++;
2676
pi3 = sel.PNum(pi3);
2677
2678
int pi4 = 1;
2679
while ( (elother.PNum(pi4) == i2.I1()) ||
2680
(elother.PNum(pi4) == i2.I2()))
2681
pi4++;
2682
pi4 = elother.PNum(pi4);
2683
2684
double rad = ComputeCylinderRadius (Point (i2.I1()),
2685
Point (i2.I2()),
2686
Point (pi3),
2687
Point (pi4));
2688
2689
RestrictLocalHLine (Point(i2.I1()), Point(i2.I2()), rad/elperr);
2690
2691
2692
/*
2693
(*testout) << "pi1,2, 3, 4 = " << i2.I1() << ", " << i2.I2() << ", " << pi3 << ", " << pi4
2694
<< " p1 = " << Point(i2.I1())
2695
<< ", p2 = " << Point(i2.I2())
2696
// << ", p3 = " << Point(pi3)
2697
// << ", p4 = " << Point(pi4)
2698
<< ", rad = " << rad << endl;
2699
*/
2700
}
2701
else
2702
edges.Set (i2, i);
2703
}
2704
}
2705
2706
2707
// Restrict h due to line segments
2708
2709
for (i = 1; i <= GetNSeg(); i++)
2710
{
2711
const Segment & seg = LineSegment(i);
2712
const Point3d & p1 = Point(seg.p1);
2713
const Point3d & p2 = Point(seg.p2);
2714
RestrictLocalH (Center (p1, p2), Dist (p1, p2));
2715
}
2716
2717
2718
2719
/*
2720
2721
2722
int i, j;
2723
int np = GetNP();
2724
int nseg = GetNSeg();
2725
int nse = GetNSE();
2726
2727
ARRAY<Vec3d> normals(np);
2728
BitArray linepoint(np);
2729
2730
linepoint.Clear();
2731
for (i = 1; i <= nseg; i++)
2732
{
2733
linepoint.Set (LineSegment(i).p1);
2734
linepoint.Set (LineSegment(i).p2);
2735
}
2736
2737
for (i = 1; i <= np; i++)
2738
normals.Elem(i) = Vec3d(0,0,0);
2739
2740
for (i = 1; i <= nse; i++)
2741
{
2742
Element2d & el = SurfaceElement(i);
2743
Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))),
2744
Vec3d (Point (el.PNum(1)), Point(el.PNum(3))));
2745
for (j = 1; j <= 3; j++)
2746
normals.Elem(el.PNum(j)) += nf;
2747
}
2748
2749
for (i = 1; i <= np; i++)
2750
normals.Elem(i) /= (1e-12 + normals.Elem(i).Length());
2751
2752
for (i = 1; i <= nse; i++)
2753
{
2754
Element2d & el = SurfaceElement(i);
2755
Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))),
2756
Vec3d (Point (el.PNum(1)), Point(el.PNum(3))));
2757
nf /= nf.Length();
2758
Point3d c = Center (Point(el.PNum(1)),
2759
Point(el.PNum(2)),
2760
Point(el.PNum(3)));
2761
2762
for (j = 1; j <= 3; j++)
2763
{
2764
if (!linepoint.Test (el.PNum(j)))
2765
{
2766
double dist = Dist (c, Point(el.PNum(j)));
2767
double dn = (nf - normals.Get(el.PNum(j))).Length();
2768
2769
RestrictLocalH (Point(el.PNum(j)), dist / (dn+1e-12) /elperr);
2770
}
2771
}
2772
}
2773
*/
2774
}
2775
2776
2777
void Mesh :: RestrictLocalH (resthtype rht, int nr, double loch)
2778
{
2779
int i;
2780
switch (rht)
2781
{
2782
case RESTRICTH_FACE:
2783
{
2784
for (i = 1; i <= GetNSE(); i++)
2785
{
2786
const Element2d & sel = SurfaceElement(i);
2787
if (sel.GetIndex() == nr)
2788
RestrictLocalH (RESTRICTH_SURFACEELEMENT, i, loch);
2789
}
2790
break;
2791
}
2792
case RESTRICTH_EDGE:
2793
{
2794
for (i = 1; i <= GetNSeg(); i++)
2795
{
2796
const Segment & seg = LineSegment(i);
2797
if (seg.edgenr == nr)
2798
RestrictLocalH (RESTRICTH_SEGMENT, i, loch);
2799
}
2800
break;
2801
}
2802
case RESTRICTH_POINT:
2803
{
2804
RestrictLocalH (Point (nr), loch);
2805
break;
2806
}
2807
2808
case RESTRICTH_SURFACEELEMENT:
2809
{
2810
const Element2d & sel = SurfaceElement(nr);
2811
Point3d p = Center (Point(sel.PNum(1)),
2812
Point(sel.PNum(2)),
2813
Point(sel.PNum(3)));
2814
RestrictLocalH (p, loch);
2815
break;
2816
}
2817
case RESTRICTH_SEGMENT:
2818
{
2819
const Segment & seg = LineSegment(nr);
2820
RestrictLocalHLine (Point (seg.p1), Point(seg.p2), loch);
2821
break;
2822
}
2823
}
2824
}
2825
2826
2827
void Mesh :: LoadLocalMeshSize (const char * meshsizefilename)
2828
{
2829
if (!meshsizefilename) return;
2830
2831
ifstream msf(meshsizefilename);
2832
2833
if (!msf) return;
2834
2835
PrintMessage (3, "Load local mesh-size");
2836
int nmsp, nmsl;
2837
msf >> nmsp;
2838
for (int i = 0; i < nmsp; i++)
2839
{
2840
Point3d pi;
2841
double hi;
2842
msf >> pi.X() >> pi.Y() >> pi.Z();
2843
msf >> hi;
2844
if (!msf.good())
2845
throw NgException ("problem in mesh-size file\n");
2846
RestrictLocalH (pi, hi);
2847
}
2848
msf >> nmsl;
2849
for (int i = 0; i < nmsl; i++)
2850
{
2851
Point3d p1, p2;
2852
double hi;
2853
msf >> p1.X() >> p1.Y() >> p1.Z();
2854
msf >> p2.X() >> p2.Y() >> p2.Z();
2855
msf >> hi;
2856
if (!msf.good())
2857
throw NgException ("problem in mesh-size file\n");
2858
RestrictLocalHLine (p1, p2, hi);
2859
}
2860
}
2861
2862
2863
2864
void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, int dom) const
2865
{
2866
if (points.Size() == 0)
2867
{
2868
pmin = pmax = Point3d(0,0,0);
2869
return;
2870
}
2871
2872
if (dom <= 0)
2873
{
2874
pmin = Point3d (1e10, 1e10, 1e10);
2875
pmax = Point3d (-1e10, -1e10, -1e10);
2876
2877
for (PointIndex pi = PointIndex::BASE;
2878
pi < GetNP()+PointIndex::BASE; pi++)
2879
{
2880
pmin.SetToMin ( (*this) [pi] );
2881
pmax.SetToMax ( (*this) [pi] );
2882
}
2883
}
2884
else
2885
{
2886
int j, nse = GetNSE();
2887
SurfaceElementIndex sei;
2888
2889
pmin = Point3d (1e10, 1e10, 1e10);
2890
pmax = Point3d (-1e10, -1e10, -1e10);
2891
for (sei = 0; sei < nse; sei++)
2892
{
2893
const Element2d & el = (*this)[sei];
2894
if (el.IsDeleted() ) continue;
2895
2896
if (dom == -1 || el.GetIndex() == dom)
2897
{
2898
for (j = 0; j < 3; j++)
2899
{
2900
pmin.SetToMin ( (*this) [el[j]] );
2901
pmax.SetToMax ( (*this) [el[j]] );
2902
}
2903
}
2904
}
2905
}
2906
2907
if (pmin.X() > 0.5e10)
2908
{
2909
pmin = pmax = Point3d(0,0,0);
2910
}
2911
}
2912
2913
2914
2915
2916
void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, POINTTYPE ptyp) const
2917
{
2918
if (points.Size() == 0)
2919
{
2920
pmin = pmax = Point3d(0,0,0);
2921
return;
2922
}
2923
2924
pmin = Point3d (1e10, 1e10, 1e10);
2925
pmax = Point3d (-1e10, -1e10, -1e10);
2926
2927
for (PointIndex pi = PointIndex::BASE;
2928
pi < GetNP()+PointIndex::BASE; pi++)
2929
if (points[pi].Type() <= ptyp)
2930
{
2931
pmin.SetToMin ( (*this) [pi] );
2932
pmax.SetToMax ( (*this) [pi] );
2933
}
2934
}
2935
2936
2937
2938
2939
double Mesh :: ElementError (int eli) const
2940
{
2941
const Element & el = volelements.Get(eli);
2942
return CalcTetBadness (points.Get(el[0]), points.Get(el[1]),
2943
points.Get(el[2]), points.Get(el[3]), -1);
2944
}
2945
2946
void Mesh :: AddLockedPoint (PointIndex pi)
2947
{
2948
lockedpoints.Append (pi);
2949
}
2950
2951
void Mesh :: ClearLockedPoints ()
2952
{
2953
lockedpoints.SetSize (0);
2954
}
2955
2956
2957
2958
void Mesh :: Compress ()
2959
{
2960
int i, j;
2961
ARRAY<int,PointIndex::BASE> op2np(GetNP());
2962
ARRAY<MeshPoint> hpoints;
2963
BitArrayChar<PointIndex::BASE> pused(GetNP());
2964
2965
/*
2966
(*testout) << "volels: " << endl;
2967
for (i = 1; i <= volelements.Size(); i++)
2968
{
2969
for (j = 1; j <= volelements.Get(i).GetNP(); j++)
2970
(*testout) << volelements.Get(i).PNum(j) << " ";
2971
(*testout) << endl;
2972
}
2973
(*testout) << "np: " << GetNP() << endl;
2974
*/
2975
2976
for (i = 0; i < volelements.Size(); i++)
2977
if (volelements[i][0] <= PointIndex::BASE-1 ||
2978
volelements[i].IsDeleted())
2979
{
2980
volelements.Delete(i);
2981
i--;
2982
}
2983
2984
2985
for (i = 0; i < surfelements.Size(); i++)
2986
if (surfelements[i].IsDeleted())
2987
{
2988
surfelements.Delete(i);
2989
i--;
2990
}
2991
2992
for (i = 0; i < segments.Size(); i++)
2993
if (segments[i].p1 <= PointIndex::BASE-1)
2994
{
2995
segments.Delete(i);
2996
i--;
2997
}
2998
2999
pused.Clear();
3000
for (i = 0; i < volelements.Size(); i++)
3001
{
3002
const Element & el = volelements[i];
3003
for (j = 0; j < el.GetNP(); j++)
3004
pused.Set (el[j]);
3005
}
3006
3007
for (i = 0; i < surfelements.Size(); i++)
3008
{
3009
const Element2d & el = surfelements[i];
3010
for (j = 0; j < el.GetNP(); j++)
3011
pused.Set (el[j]);
3012
}
3013
3014
for (i = 0; i < segments.Size(); i++)
3015
{
3016
const Segment & seg = segments[i];
3017
pused.Set (seg.p1);
3018
pused.Set (seg.p2);
3019
}
3020
3021
for (i = 0; i < openelements.Size(); i++)
3022
{
3023
const Element2d & el = openelements[i];
3024
for (j = 0; j < el.GetNP(); j++)
3025
pused.Set(el[j]);
3026
}
3027
3028
for (i = 0; i < lockedpoints.Size(); i++)
3029
pused.Set (lockedpoints[i]);
3030
3031
3032
/*
3033
// compress points doesnt work for identified points !
3034
if (identifiedpoints)
3035
{
3036
for (i = 1; i <= identifiedpoints->GetNBags(); i++)
3037
if (identifiedpoints->GetBagSize(i))
3038
{
3039
pused.Set ();
3040
break;
3041
}
3042
}
3043
*/
3044
// pused.Set();
3045
3046
3047
int npi = PointIndex::BASE-1;
3048
3049
for (i = PointIndex::BASE;
3050
i < points.Size()+PointIndex::BASE; i++)
3051
if (pused.Test(i))
3052
{
3053
npi++;
3054
op2np[i] = npi;
3055
hpoints.Append (points[i]);
3056
}
3057
else
3058
op2np[i] = -1;
3059
3060
3061
3062
points.SetSize(0);
3063
for (i = 0; i < hpoints.Size(); i++)
3064
points.Append (hpoints[i]);
3065
3066
3067
for (i = 1; i <= volelements.Size(); i++)
3068
{
3069
Element & el = VolumeElement(i);
3070
for (j = 0; j < el.GetNP(); j++)
3071
el[j] = op2np[el[j]];
3072
}
3073
3074
for (i = 1; i <= surfelements.Size(); i++)
3075
{
3076
Element2d & el = SurfaceElement(i);
3077
for (j = 0; j < el.GetNP(); j++)
3078
el[j] = op2np[el[j]];
3079
}
3080
3081
for (i = 0; i < segments.Size(); i++)
3082
{
3083
Segment & seg = segments[i];
3084
seg.p1 = op2np[seg.p1];
3085
seg.p2 = op2np[seg.p2];
3086
}
3087
3088
for (i = 1; i <= openelements.Size(); i++)
3089
{
3090
Element2d & el = openelements.Elem(i);
3091
for (j = 0; j < el.GetNP(); j++)
3092
el[j] = op2np[el[j]];
3093
}
3094
3095
3096
for (i = 0; i < lockedpoints.Size(); i++)
3097
lockedpoints[i] = op2np[lockedpoints[i]];
3098
3099
for (int i = 0; i < facedecoding.Size(); i++)
3100
facedecoding[i].firstelement = -1;
3101
for (int i = surfelements.Size()-1; i >= 0; i--)
3102
{
3103
int ind = surfelements[i].GetIndex();
3104
surfelements[i].next = facedecoding[ind-1].firstelement;
3105
facedecoding[ind-1].firstelement = i;
3106
}
3107
3108
3109
CalcSurfacesOfNode();
3110
3111
3112
// FindOpenElements();
3113
timestamp = NextTimeStamp();
3114
3115
/*
3116
(*testout) << "compress, done" << endl
3117
<< "np = " << points.Size()
3118
<< "ne = " << volelements.Size() << ", type.size = " << eltyps.Size()
3119
<< "volelements = " << volelements << endl;
3120
*/
3121
}
3122
3123
3124
int Mesh :: CheckConsistentBoundary () const
3125
{
3126
int nf = GetNOpenElements();
3127
INDEX_2_HASHTABLE<int> edges(nf+2);
3128
INDEX_2 i2, i2s, edge;
3129
int err = 0;
3130
3131
for (int i = 1; i <= nf; i++)
3132
{
3133
const Element2d & sel = OpenElement(i);
3134
3135
for (int j = 1; j <= sel.GetNP(); j++)
3136
{
3137
i2.I1() = sel.PNumMod(j);
3138
i2.I2() = sel.PNumMod(j+1);
3139
3140
int sign = (i2.I2() > i2.I1()) ? 1 : -1;
3141
i2.Sort();
3142
if (!edges.Used (i2))
3143
edges.Set (i2, 0);
3144
edges.Set (i2, edges.Get(i2) + sign);
3145
}
3146
}
3147
3148
for (int i = 1; i <= edges.GetNBags(); i++)
3149
for (int j = 1; j <= edges.GetBagSize(i); j++)
3150
{
3151
int cnt = 0;
3152
edges.GetData (i, j, i2, cnt);
3153
if (cnt)
3154
{
3155
PrintError ("Edge ", i2.I1() , " - ", i2.I2(), " multiple times in surface mesh");
3156
3157
(*testout) << "Edge " << i2 << " multiple times in surface mesh" << endl;
3158
i2s = i2;
3159
i2s.Sort();
3160
for (int k = 1; k <= nf; k++)
3161
{
3162
const Element2d & sel = OpenElement(k);
3163
for (int l = 1; l <= sel.GetNP(); l++)
3164
{
3165
edge.I1() = sel.PNumMod(l);
3166
edge.I2() = sel.PNumMod(l+1);
3167
edge.Sort();
3168
3169
if (edge == i2s)
3170
(*testout) << "edge of element " << sel << endl;
3171
}
3172
}
3173
3174
3175
err = 2;
3176
}
3177
}
3178
3179
return err;
3180
}
3181
3182
3183
3184
int Mesh :: CheckOverlappingBoundary ()
3185
{
3186
int i, j, k;
3187
3188
Point3d pmin, pmax;
3189
GetBox (pmin, pmax);
3190
Box3dTree setree(pmin, pmax);
3191
ARRAY<int> inters;
3192
3193
bool overlap = 0;
3194
bool incons_layers = 0;
3195
3196
3197
for (i = 1; i <= GetNSE(); i++)
3198
SurfaceElement(i).badel = 0;
3199
3200
3201
for (i = 1; i <= GetNSE(); i++)
3202
{
3203
const Element2d & tri = SurfaceElement(i);
3204
3205
Point3d tpmin (Point(tri[0]));
3206
Point3d tpmax (tpmin);
3207
3208
for (k = 1; k < tri.GetNP(); k++)
3209
{
3210
tpmin.SetToMin (Point (tri[k]));
3211
tpmax.SetToMax (Point (tri[k]));
3212
}
3213
Vec3d diag(tpmin, tpmax);
3214
3215
tpmax = tpmax + 0.1 * diag;
3216
tpmin = tpmin - 0.1 * diag;
3217
3218
setree.Insert (tpmin, tpmax, i);
3219
}
3220
3221
for (i = 1; i <= GetNSE(); i++)
3222
{
3223
const Element2d & tri = SurfaceElement(i);
3224
3225
Point3d tpmin (Point(tri[0]));
3226
Point3d tpmax (tpmin);
3227
3228
for (k = 1; k < tri.GetNP(); k++)
3229
{
3230
tpmin.SetToMin (Point (tri[k]));
3231
tpmax.SetToMax (Point (tri[k]));
3232
}
3233
3234
setree.GetIntersecting (tpmin, tpmax, inters);
3235
3236
for (j = 1; j <= inters.Size(); j++)
3237
{
3238
const Element2d & tri2 = SurfaceElement(inters.Get(j));
3239
3240
if ( (*this)[tri[0]].GetLayer() != (*this)[tri2[0]].GetLayer())
3241
continue;
3242
3243
if ( (*this)[tri[0]].GetLayer() != (*this)[tri[1]].GetLayer() ||
3244
(*this)[tri[0]].GetLayer() != (*this)[tri[2]].GetLayer())
3245
{
3246
incons_layers = 1;
3247
cout << "inconsistent layers in triangle" << endl;
3248
}
3249
3250
3251
const netgen::Point<3> *trip1[3], *trip2[3];
3252
for (k = 1; k <= 3; k++)
3253
{
3254
trip1[k-1] = &Point (tri.PNum(k));
3255
trip2[k-1] = &Point (tri2.PNum(k));
3256
}
3257
3258
if (IntersectTriangleTriangle (&trip1[0], &trip2[0]))
3259
{
3260
overlap = 1;
3261
PrintWarning ("Intersecting elements "
3262
,i, " and ", inters.Get(j));
3263
3264
(*testout) << "Intersecting: " << endl;
3265
(*testout) << "openelement " << i << " with open element " << inters.Get(j) << endl;
3266
3267
cout << "el1 = " << tri << endl;
3268
cout << "el2 = " << tri2 << endl;
3269
cout << "layer1 = " << (*this)[tri[0]].GetLayer() << endl;
3270
cout << "layer2 = " << (*this)[tri2[0]].GetLayer() << endl;
3271
3272
3273
for (k = 1; k <= 3; k++)
3274
(*testout) << tri.PNum(k) << " ";
3275
(*testout) << endl;
3276
for (k = 1; k <= 3; k++)
3277
(*testout) << tri2.PNum(k) << " ";
3278
(*testout) << endl;
3279
3280
for (k = 0; k <= 2; k++)
3281
(*testout) << *trip1[k] << " ";
3282
(*testout) << endl;
3283
for (k = 0; k <= 2; k++)
3284
(*testout) << *trip2[k] << " ";
3285
(*testout) << endl;
3286
3287
(*testout) << "Face1 = " << GetFaceDescriptor(tri.GetIndex()) << endl;
3288
(*testout) << "Face1 = " << GetFaceDescriptor(tri2.GetIndex()) << endl;
3289
3290
/*
3291
INDEX_3 i3(tri.PNum(1), tri.PNum(2), tri.PNum(3));
3292
i3.Sort();
3293
for (k = 1; k <= GetNSE(); k++)
3294
{
3295
const Element2d & el2 = SurfaceElement(k);
3296
INDEX_3 i3b(el2.PNum(1), el2.PNum(2), el2.PNum(3));
3297
i3b.Sort();
3298
if (i3 == i3b)
3299
{
3300
SurfaceElement(k).badel = 1;
3301
}
3302
}
3303
*/
3304
SurfaceElement(i).badel = 1;
3305
SurfaceElement(inters.Get(j)).badel = 1;
3306
}
3307
}
3308
}
3309
3310
// bug 'fix'
3311
if (incons_layers) overlap = 0;
3312
3313
return overlap;
3314
}
3315
3316
3317
int Mesh :: CheckVolumeMesh () const
3318
{
3319
PrintMessage (3, "Checking volume mesh");
3320
3321
int ne = GetNE();
3322
DenseMatrix dtrans(3,3);
3323
int i, j;
3324
3325
PrintMessage (5, "elements: ", ne);
3326
for (i = 1; i <= ne; i++)
3327
{
3328
Element & el = (Element&) VolumeElement(i);
3329
el.flags.badel = 0;
3330
int nip = el.GetNIP();
3331
for (j = 1; j <= nip; j++)
3332
{
3333
el.GetTransformation (j, Points(), dtrans);
3334
double det = dtrans.Det();
3335
if (det > 0)
3336
{
3337
PrintError ("Element ", i , " has wrong orientation");
3338
el.flags.badel = 1;
3339
}
3340
}
3341
}
3342
3343
return 0;
3344
}
3345
3346
3347
bool Mesh :: LegalTrig (const Element2d & el) const
3348
{
3349
return 1;
3350
if ( /* hp */ 1) // needed for old, simple hp-refinement
3351
{
3352
// trigs with 2 or more segments are illegal
3353
int i;
3354
int nseg = 0;
3355
3356
if (!segmentht)
3357
{
3358
cerr << "no segmentht allocated" << endl;
3359
return 0;
3360
}
3361
3362
// Point3d cp(0.5, 0.5, 0.5);
3363
for (i = 1; i <= 3; i++)
3364
{
3365
INDEX_2 i2(el.PNumMod (i), el.PNumMod (i+1));
3366
i2.Sort();
3367
if (segmentht -> Used (i2))
3368
nseg++;
3369
}
3370
if (nseg >= 2)
3371
return 0;
3372
}
3373
return 1;
3374
}
3375
3376
3377
3378
3379
///
3380
bool Mesh :: LegalTet2 (Element & el) const
3381
{
3382
// static int timer1 = NgProfiler::CreateTimer ("Legaltet2");
3383
3384
3385
// Test, whether 4 points have a common surface plus
3386
// at least 4 edges at the boundary
3387
3388
if(!boundaryedges)
3389
const_cast<Mesh *>(this)->BuildBoundaryEdges();
3390
3391
3392
// non-tets are always legal
3393
if (el.GetType() != TET)
3394
{
3395
el.SetLegal (1);
3396
return 1;
3397
}
3398
3399
POINTTYPE pointtype[4];
3400
for(int i = 0; i < 4; i++)
3401
pointtype[i] = (*this)[el[i]].Type();
3402
3403
3404
3405
// element has at least 2 inner points ---> legal
3406
int cnti = 0;
3407
for (int j = 0; j < 4; j++)
3408
if ( pointtype[j] == INNERPOINT)
3409
{
3410
cnti++;
3411
if (cnti >= 2)
3412
{
3413
el.SetLegal (1);
3414
return 1;
3415
}
3416
}
3417
3418
3419
3420
// which faces are boundary faces ?
3421
int bface[4];
3422
for (int i = 0; i < 4; i++)
3423
{
3424
bface[i] = surfelementht->Used (INDEX_3::Sort(el[gftetfacesa[i][0]],
3425
el[gftetfacesa[i][1]],
3426
el[gftetfacesa[i][2]]));
3427
}
3428
3429
int bedge[4][4];
3430
int segedge[4][4];
3431
static const int pi3map[4][4] = { { -1, 2, 1, 1 },
3432
{ 2, -1, 0, 0 },
3433
{ 1, 0, -1, 0 },
3434
{ 1, 0, 0, -1 } };
3435
3436
static const int pi4map[4][4] = { { -1, 3, 3, 2 },
3437
{ 3, -1, 3, 2 },
3438
{ 3, 3, -1, 1 },
3439
{ 2, 2, 1, -1 } };
3440
3441
3442
for (int i = 0; i < 4; i++)
3443
for (int j = 0; j < i; j++)
3444
{
3445
bool sege = false, be = false;
3446
3447
int pos = boundaryedges -> Position(INDEX_2::Sort(el[i], el[j]));
3448
if (pos)
3449
{
3450
be = true;
3451
if (boundaryedges -> GetData(pos) == 2)
3452
sege = true;
3453
}
3454
3455
segedge[j][i] = segedge[i][j] = sege;
3456
bedge[j][i] = bedge[i][j] = be;
3457
}
3458
3459
// two boundary faces and no edge is illegal
3460
for (int i = 0; i < 3; i++)
3461
for (int j = i+1; j < 4; j++)
3462
{
3463
if (bface[i] && bface[j])
3464
if (!segedge[pi3map[i][j]][pi4map[i][j]])
3465
{
3466
// 2 boundary faces withoud edge in between
3467
el.SetLegal (0);
3468
return 0;
3469
}
3470
}
3471
3472
// three boundary edges meeting in a Surface point
3473
for (int i = 0; i < 4; i++)
3474
{
3475
bool alledges = 1;
3476
if ( pointtype[i] == SURFACEPOINT)
3477
{
3478
bool alledges = 1;
3479
for (int j = 0; j < 4; j++)
3480
if (j != i && !bedge[i][j])
3481
{
3482
alledges = 0;
3483
break;
3484
}
3485
if (alledges)
3486
{
3487
// cout << "tet illegal due to unmarked node" << endl;
3488
el.SetLegal (0);
3489
return 0;
3490
}
3491
}
3492
}
3493
3494
3495
3496
for (int fnr = 0; fnr < 4; fnr++)
3497
if (!bface[fnr])
3498
for (int i = 0; i < 4; i++)
3499
if (i != fnr)
3500
{
3501
int pi1 = pi3map[i][fnr];
3502
int pi2 = pi4map[i][fnr];
3503
3504
if ( pointtype[i] == SURFACEPOINT)
3505
{
3506
// two connected edges on surface, but no face
3507
if (bedge[i][pi1] && bedge[i][pi2])
3508
{
3509
el.SetLegal (0);
3510
return 0;
3511
}
3512
}
3513
3514
if ( pointtype[i] == EDGEPOINT)
3515
{
3516
// connected surface edge and edge edge, but no face
3517
if (bedge[i][pi1] && segedge[i][pi2] ||
3518
bedge[i][pi2] && segedge[i][pi1])
3519
{
3520
el.SetLegal (0);
3521
return 0;
3522
}
3523
}
3524
3525
}
3526
3527
3528
el.SetLegal (1);
3529
return 1;
3530
3531
}
3532
3533
3534
3535
int Mesh :: GetNDomains() const
3536
{
3537
int ndom = 0;
3538
3539
for (int k = 0; k < facedecoding.Size(); k++)
3540
{
3541
if (facedecoding[k].DomainIn() > ndom)
3542
ndom = facedecoding[k].DomainIn();
3543
if (facedecoding[k].DomainOut() > ndom)
3544
ndom = facedecoding[k].DomainOut();
3545
}
3546
3547
return ndom;
3548
}
3549
3550
3551
3552
void Mesh :: SurfaceMeshOrientation ()
3553
{
3554
int i, j;
3555
int nse = GetNSE();
3556
3557
BitArray used(nse);
3558
used.Clear();
3559
INDEX_2_HASHTABLE<int> edges(nse+1);
3560
3561
bool haschanged = 0;
3562
3563
3564
const Element2d & tri = SurfaceElement(1);
3565
for (j = 1; j <= 3; j++)
3566
{
3567
INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1));
3568
edges.Set (i2, 1);
3569
}
3570
used.Set(1);
3571
3572
bool unused;
3573
do
3574
{
3575
bool changed;
3576
do
3577
{
3578
changed = 0;
3579
for (i = 1; i <= nse; i++)
3580
if (!used.Test(i))
3581
{
3582
Element2d & el = surfelements.Elem(i);
3583
int found = 0, foundrev = 0;
3584
for (j = 1; j <= 3; j++)
3585
{
3586
INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1));
3587
if (edges.Used(i2))
3588
foundrev = 1;
3589
swap (i2.I1(), i2.I2());
3590
if (edges.Used(i2))
3591
found = 1;
3592
}
3593
3594
if (found || foundrev)
3595
{
3596
if (foundrev)
3597
swap (el.PNum(2), el.PNum(3));
3598
3599
changed = 1;
3600
for (j = 1; j <= 3; j++)
3601
{
3602
INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1));
3603
edges.Set (i2, 1);
3604
}
3605
used.Set (i);
3606
}
3607
}
3608
if (changed)
3609
haschanged = 1;
3610
}
3611
while (changed);
3612
3613
3614
unused = 0;
3615
for (i = 1; i <= nse; i++)
3616
if (!used.Test(i))
3617
{
3618
unused = 1;
3619
const Element2d & tri = SurfaceElement(i);
3620
for (j = 1; j <= 3; j++)
3621
{
3622
INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1));
3623
edges.Set (i2, 1);
3624
}
3625
used.Set(i);
3626
break;
3627
}
3628
}
3629
while (unused);
3630
3631
if (haschanged)
3632
timestamp = NextTimeStamp();
3633
}
3634
3635
3636
void Mesh :: Split2Tets()
3637
{
3638
PrintMessage (1, "Split To Tets");
3639
bool has_prisms = 0;
3640
3641
int oldne = GetNE();
3642
for (int i = 1; i <= oldne; i++)
3643
{
3644
Element el = VolumeElement(i);
3645
3646
if (el.GetType() == PRISM)
3647
{
3648
// prism, to 3 tets
3649
3650
// make minimal node to node 1
3651
int minpi=0;
3652
PointIndex minpnum;
3653
minpnum = GetNP() + 1;
3654
3655
for (int j = 1; j <= 6; j++)
3656
{
3657
if (el.PNum(j) < minpnum)
3658
{
3659
minpnum = el.PNum(j);
3660
minpi = j;
3661
}
3662
}
3663
3664
if (minpi >= 4)
3665
{
3666
for (int j = 1; j <= 3; j++)
3667
swap (el.PNum(j), el.PNum(j+3));
3668
minpi -= 3;
3669
}
3670
3671
while (minpi > 1)
3672
{
3673
int hi = 0;
3674
for (int j = 0; j <= 3; j+= 3)
3675
{
3676
hi = el.PNum(1+j);
3677
el.PNum(1+j) = el.PNum(2+j);
3678
el.PNum(2+j) = el.PNum(3+j);
3679
el.PNum(3+j) = hi;
3680
}
3681
minpi--;
3682
}
3683
3684
/*
3685
version 1: edge from pi2 to pi6,
3686
version 2: edge from pi3 to pi5,
3687
*/
3688
3689
static const int ntets[2][12] =
3690
{ { 1, 4, 5, 6, 1, 2, 3, 6, 1, 2, 5, 6 },
3691
{ 1, 4, 5, 6, 1, 2, 3, 5, 3, 1, 5, 6 } };
3692
3693
const int * min2pi;
3694
3695
if (min2 (el.PNum(2), el.PNum(6)) <
3696
min2 (el.PNum(3), el.PNum(5)))
3697
{
3698
min2pi = &ntets[0][0];
3699
// (*testout) << "version 1 ";
3700
}
3701
else
3702
{
3703
min2pi = &ntets[1][0];
3704
// (*testout) << "version 2 ";
3705
}
3706
3707
3708
int firsttet = 1;
3709
for (int j = 1; j <= 3; j++)
3710
{
3711
Element nel(TET);
3712
for (int k = 1; k <= 4; k++)
3713
nel.PNum(k) = el.PNum(min2pi[4 * j + k - 5]);
3714
nel.SetIndex (el.GetIndex());
3715
3716
int legal = 1;
3717
for (int k = 1; k <= 3; k++)
3718
for (int l = k+1; l <= 4; l++)
3719
if (nel.PNum(k) == nel.PNum(l))
3720
legal = 0;
3721
3722
// (*testout) << nel << " ";
3723
if (legal)
3724
{
3725
if (firsttet)
3726
{
3727
VolumeElement(i) = nel;
3728
firsttet = 0;
3729
}
3730
else
3731
{
3732
AddVolumeElement(nel);
3733
}
3734
}
3735
}
3736
if (firsttet) cout << "no legal";
3737
(*testout) << endl;
3738
}
3739
3740
3741
3742
else if (el.GetType() == HEX)
3743
{
3744
// hex to A) 2 prisms or B) to 5 tets
3745
3746
// make minimal node to node 1
3747
int minpi=0;
3748
PointIndex minpnum;
3749
minpnum = GetNP() + 1;
3750
3751
for (int j = 1; j <= 8; j++)
3752
{
3753
if (el.PNum(j) < minpnum)
3754
{
3755
minpnum = el.PNum(j);
3756
minpi = j;
3757
}
3758
}
3759
3760
if (minpi >= 5)
3761
{
3762
for (int j = 1; j <= 4; j++)
3763
swap (el.PNum(j), el.PNum(j+4));
3764
minpi -= 4;
3765
}
3766
3767
while (minpi > 1)
3768
{
3769
int hi = 0;
3770
for (int j = 0; j <= 4; j+= 4)
3771
{
3772
hi = el.PNum(1+j);
3773
el.PNum(1+j) = el.PNum(2+j);
3774
el.PNum(2+j) = el.PNum(3+j);
3775
el.PNum(3+j) = el.PNum(4+j);
3776
el.PNum(4+j) = hi;
3777
}
3778
minpi--;
3779
}
3780
3781
3782
3783
static const int to_prisms[3][12] =
3784
{ { 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 6, 7 },
3785
{ 0, 1, 5, 3, 2, 6, 0, 5, 4, 3, 6, 7 },
3786
{ 0, 7, 4, 1, 6, 5, 0, 3, 7, 1, 2, 6 },
3787
};
3788
3789
const int * min2pi = 0;
3790
if (min2 (el[4], el[6]) < min2 (el[5], el[7]))
3791
min2pi = &to_prisms[0][0];
3792
else if (min2 (el[3], el[6]) < min2 (el[2], el[7]))
3793
min2pi = &to_prisms[1][0];
3794
else if (min2 (el[1], el[6]) < min2 (el[2], el[5]))
3795
min2pi = &to_prisms[2][0];
3796
3797
if (min2pi)
3798
{
3799
has_prisms = 1;
3800
for (int j = 0; j < 2; j++)
3801
{
3802
Element nel(PRISM);
3803
for (int k = 0; k < 6; k++)
3804
nel[k] = el[min2pi[6*j + k]];
3805
nel.SetIndex (el.GetIndex());
3806
3807
if (j == 0)
3808
VolumeElement(i) = nel;
3809
else
3810
AddVolumeElement(nel);
3811
}
3812
}
3813
else
3814
{
3815
// split to 5 tets
3816
3817
static const int to_tets[20] =
3818
{
3819
1, 2, 0, 5,
3820
3, 0, 2, 7,
3821
4, 5, 7, 0,
3822
6, 7, 5, 2,
3823
0, 2, 7, 5
3824
};
3825
3826
for (int j = 0; j < 5; j++)
3827
{
3828
Element nel(TET);
3829
for (int k = 0; k < 4; k++)
3830
nel[k] = el[to_tets[4*j + k]];
3831
nel.SetIndex (el.GetIndex());
3832
3833
if (j == 0)
3834
VolumeElement(i) = nel;
3835
else
3836
AddVolumeElement(nel);
3837
}
3838
3839
}
3840
}
3841
3842
3843
3844
3845
3846
else if (el.GetType() == PYRAMID)
3847
{
3848
// pyramid, to 2 tets
3849
3850
// cout << "pyramid: " << el << endl;
3851
3852
static const int ntets[2][8] =
3853
{ { 1, 2, 3, 5, 1, 3, 4, 5 },
3854
{ 1, 2, 4, 5, 4, 2, 3, 5 }};
3855
3856
const int * min2pi;
3857
3858
if (min2 (el[0], el[2]) < min2 (el[1], el[3]))
3859
min2pi = &ntets[0][0];
3860
else
3861
min2pi = &ntets[1][0];
3862
3863
bool firsttet = 1;
3864
for (int j = 0; j < 2; j++)
3865
{
3866
Element nel(TET);
3867
for (int k = 0; k < 4; k++)
3868
nel[k] = el[min2pi[4*j + k]-1];
3869
nel.SetIndex (el.GetIndex());
3870
3871
// cout << "pyramid-tet: " << nel << endl;
3872
3873
bool legal = 1;
3874
for (int k = 0; k < 3; k++)
3875
for (int l = k+1; l < 4; l++)
3876
if (nel[k] == nel[l])
3877
legal = 0;
3878
3879
if (legal)
3880
{
3881
(*testout) << nel << " ";
3882
if (firsttet)
3883
VolumeElement(i) = nel;
3884
else
3885
AddVolumeElement(nel);
3886
3887
firsttet = 0;
3888
}
3889
}
3890
if (firsttet) cout << "no legal";
3891
(*testout) << endl;
3892
}
3893
}
3894
3895
3896
int oldnse = GetNSE();
3897
for (int i = 1; i <= oldnse; i++)
3898
{
3899
Element2d el = SurfaceElement(i);
3900
if (el.GetNP() == 4)
3901
{
3902
(*testout) << "split el: " << el << " to ";
3903
3904
static const int ntris[2][6] =
3905
{ { 1, 2, 3, 1, 3, 4 },
3906
{ 1, 2, 4, 4, 2, 3 }};
3907
3908
const int * min2pi;
3909
3910
if (min2 (el.PNum(1), el.PNum(3)) <
3911
min2 (el.PNum(2), el.PNum(4)))
3912
min2pi = &ntris[0][0];
3913
else
3914
min2pi = &ntris[1][0];
3915
3916
for (int j = 0; j <6; j++)
3917
(*testout) << min2pi[j] << " ";
3918
3919
3920
int firsttri = 1;
3921
for (int j = 1; j <= 2; j++)
3922
{
3923
Element2d nel(3);
3924
for (int k = 1; k <= 3; k++)
3925
nel.PNum(k) = el.PNum(min2pi[3 * j + k - 4]);
3926
nel.SetIndex (el.GetIndex());
3927
3928
int legal = 1;
3929
for (int k = 1; k <= 2; k++)
3930
for (int l = k+1; l <= 3; l++)
3931
if (nel.PNum(k) == nel.PNum(l))
3932
legal = 0;
3933
3934
if (legal)
3935
{
3936
(*testout) << nel << " ";
3937
if (firsttri)
3938
{
3939
SurfaceElement(i) = nel;
3940
firsttri = 0;
3941
}
3942
else
3943
{
3944
AddSurfaceElement(nel);
3945
}
3946
}
3947
}
3948
(*testout) << endl;
3949
3950
}
3951
}
3952
3953
3954
if (has_prisms)
3955
3956
Split2Tets();
3957
3958
else
3959
{
3960
for (int i = 1; i <= GetNE(); i++)
3961
{
3962
Element & el = VolumeElement(i);
3963
const Point3d & p1 = Point (el.PNum(1));
3964
const Point3d & p2 = Point (el.PNum(2));
3965
const Point3d & p3 = Point (el.PNum(3));
3966
const Point3d & p4 = Point (el.PNum(4));
3967
3968
double vol = (Vec3d (p1, p2) *
3969
Cross (Vec3d (p1, p3), Vec3d(p1, p4)));
3970
if (vol > 0)
3971
swap (el.PNum(3), el.PNum(4));
3972
}
3973
3974
3975
3976
UpdateTopology();
3977
timestamp = NextTimeStamp();
3978
}
3979
}
3980
3981
void Mesh :: BuildElementSearchTree ()
3982
{
3983
if (elementsearchtreets == GetTimeStamp())
3984
return;
3985
3986
NgLock lock(mutex);
3987
lock.Lock();
3988
3989
PrintMessage (4, "Rebuild element searchtree");
3990
3991
if (elementsearchtree)
3992
delete elementsearchtree;
3993
elementsearchtree = NULL;
3994
3995
Box3d box;
3996
int i, j;
3997
int ne = GetNE();
3998
if (!ne)
3999
{
4000
lock.UnLock();
4001
return;
4002
}
4003
4004
box.SetPoint (Point (VolumeElement(1).PNum(1)));
4005
for (i = 1; i <= ne; i++)
4006
{
4007
const Element & el = VolumeElement(i);
4008
for (j = 1; j <= el.GetNP(); j++)
4009
box.AddPoint (Point (el.PNum(j)));
4010
}
4011
4012
box.Increase (1.01 * box.CalcDiam());
4013
elementsearchtree = new Box3dTree (box.PMin(), box.PMax());
4014
4015
4016
4017
for (i = 1; i <= ne; i++)
4018
{
4019
const Element & el = VolumeElement(i);
4020
box.SetPoint (Point (el.PNum(1)));
4021
for (j = 1; j <= el.GetNP(); j++)
4022
box.AddPoint (Point (el.PNum(j)));
4023
4024
elementsearchtree -> Insert (box.PMin(), box.PMax(), i);
4025
}
4026
4027
elementsearchtreets = GetTimeStamp();
4028
4029
lock.UnLock();
4030
}
4031
4032
4033
4034
bool Mesh :: PointContainedIn2DElement(const Point3d & p,
4035
double lami[3],
4036
const int element,
4037
bool consider3D) const
4038
{
4039
static Vec3d col1, col2, col3;
4040
static Vec3d rhs, sol;
4041
const double eps = 1e-6;
4042
4043
static ARRAY<Element2d> loctrigs;
4044
4045
4046
//SZ
4047
if(SurfaceElement(element).GetType()==QUAD)
4048
{
4049
const Element2d & el = SurfaceElement(element);
4050
4051
const Point3d & p1 = Point(el.PNum(1));
4052
const Point3d & p2 = Point(el.PNum(2));
4053
const Point3d & p3 = Point(el.PNum(3));
4054
const Point3d & p4 = Point(el.PNum(4));
4055
4056
// Coefficients of Bilinear Mapping from Ref-Elem to global Elem
4057
// X = a + b x + c y + d x y
4058
Vec3d a = p1;
4059
Vec3d b = p2 - a;
4060
Vec3d c = p4 - a;
4061
Vec3d d = p3 - a - b - c;
4062
4063
double dxb = d.X()*b.Y()-d.Y()*b.X();
4064
double dxc = d.X()*c.Y()-d.Y()*c.X();
4065
double dxa = d.X()*a.Y()-d.Y()*a.X();
4066
double dxp = d.X()*p.Y()-d.Y()*p.X();
4067
4068
double c0,c1,c2,rt;
4069
lami[2]=0.;
4070
double eps = 1.E-12;
4071
4072
if(fabs(d.X()) <= eps && fabs(d.Y())<= eps)
4073
{
4074
//Solve Linear System
4075
lami[0]=(c.Y()*(p.X()-a.X())-c.X()*(p.Y()-a.Y()))/
4076
(b.X()*c.Y() -b.Y()*c.X());
4077
lami[1]=(-b.Y()*(p.X()-a.X())+b.X()*(p.Y()-a.Y()))/
4078
(b.X()*c.Y() -b.Y()*c.X());
4079
}
4080
else
4081
if(fabs(dxb) <= eps)
4082
{
4083
lami[1] = (dxp-dxa)/dxc;
4084
if(fabs(b.X()-d.X()*lami[1])>=eps)
4085
lami[0] = (p.X()-a.X() - c.X()*lami[1])/(b.X()+d.X()*lami[1]);
4086
else
4087
lami[0] = (p.Y()-a.Y() - c.Y()*lami[1])/(b.Y()+d.Y()*lami[1]);
4088
}
4089
else
4090
if(fabs(dxc) <= eps)
4091
{
4092
lami[0] = (dxp-dxa)/dxb;
4093
if(fabs(c.X()-d.X()*lami[0])>=eps)
4094
lami[1] = (p.X()-a.X() - b.X()*lami[0])/(c.X()+d.X()*lami[0]);
4095
else
4096
lami[1] = (p.Y()-a.Y() - b.Y()*lami[0])/(c.Y()+d.Y()*lami[0]);
4097
}
4098
else //Solve quadratic equation
4099
{
4100
if(fabs(d.X()) >= eps)
4101
{
4102
c2 = d.X()*dxc;
4103
c1 = d.X()*dxc - c.X()*dxb - d.X()*(dxp-dxa);
4104
c0 = -b.X()*(dxp -dxa) - (a.X()-p.X())*dxb;
4105
}
4106
else
4107
{
4108
c2 = d.Y()*dxc;
4109
c1 = d.Y()*dxc - c.Y()*dxb - d.Y()*(dxp-dxa);
4110
c0 = -b.Y()*(dxp -dxa) - (a.Y()-p.Y())*dxb;
4111
}
4112
4113
double rt = c1*c1 - 4*c2*c0;
4114
if (rt < 0.) return false;
4115
lami[1] = (-c1 + sqrt(rt))/2/c2;
4116
if(lami[1]<=1. && lami[1]>=0.)
4117
{
4118
lami[0] = (dxp - dxa -dxc*lami[1])/dxb;
4119
if(lami[0]<=1. && lami[0]>=0.)
4120
return true;
4121
}
4122
4123
lami[1] = (-c1 - sqrt(rt))/2/c2;
4124
lami[0] = (dxp - dxa -dxc*lami[1])/dxb;
4125
}
4126
4127
if( lami[0] <= 1.+eps && lami[0] >= -eps && lami[1]<=1.+eps && lami[1]>=-eps)
4128
{
4129
if(consider3D)
4130
{
4131
Vec3d n = Cross(b,c);
4132
lami[2] = 0;
4133
for(int i=1; i<=3; i++)
4134
lami[2] +=(p.X(i)-a.X(i)-lami[0]*b.X(i)-lami[1]*c.X(i)) * n.X(i);
4135
if(lami[2] >= -eps && lami[2] <= eps)
4136
return true;
4137
}
4138
else
4139
return true;
4140
}
4141
4142
return false;
4143
4144
}
4145
else
4146
{
4147
// SurfaceElement(element).GetTets (loctets);
4148
loctrigs.SetSize(1);
4149
loctrigs.Elem(1) = SurfaceElement(element);
4150
4151
4152
4153
for (int j = 1; j <= loctrigs.Size(); j++)
4154
{
4155
const Element2d & el = loctrigs.Get(j);
4156
4157
4158
const Point3d & p1 = Point(el.PNum(1));
4159
const Point3d & p2 = Point(el.PNum(2));
4160
const Point3d & p3 = Point(el.PNum(3));
4161
/*
4162
Box3d box;
4163
box.SetPoint (p1);
4164
box.AddPoint (p2);
4165
box.AddPoint (p3);
4166
box.AddPoint (p4);
4167
if (!box.IsIn (p))
4168
continue;
4169
*/
4170
col1 = p2-p1;
4171
col2 = p3-p1;
4172
col3 = Cross(col1,col2);
4173
//col3 = Vec3d(0, 0, 1);
4174
rhs = p - p1;
4175
4176
int retval = SolveLinearSystem (col1, col2, col3, rhs, sol);
4177
4178
//(*testout) << "retval " << retval << endl;
4179
4180
//(*testout) << "col1 " << col1 << " col2 " << col2 << " col3 " << col3 << " rhs " << rhs << endl;
4181
//(*testout) << "sol " << sol << endl;
4182
4183
if (sol.X() >= -eps && sol.Y() >= -eps &&
4184
sol.X() + sol.Y() <= 1+eps)
4185
{
4186
if(!consider3D || (sol.Z() >= -eps && sol.Z() <= eps))
4187
{
4188
lami[0] = sol.X();
4189
lami[1] = sol.Y();
4190
lami[2] = sol.Z();
4191
4192
return true;
4193
}
4194
}
4195
}
4196
}
4197
4198
return false;
4199
4200
}
4201
4202
4203
4204
4205
bool Mesh :: PointContainedIn3DElement(const Point3d & p,
4206
double lami[3],
4207
const int element) const
4208
{
4209
//bool oldresult = PointContainedIn3DElementOld(p,lami,element);
4210
//(*testout) << "old result: " << oldresult
4211
// << " lam " << lami[0] << " " << lami[1] << " " << lami[2] << endl;
4212
4213
//if(!curvedelems->IsElementCurved(element-1))
4214
// return PointContainedIn3DElementOld(p,lami,element);
4215
4216
4217
const double eps = 1.e-4;
4218
const Element & el = VolumeElement(element);
4219
4220
netgen::Point<3> lam;
4221
4222
if (el.GetType() == TET)
4223
{
4224
lam = 0.25;
4225
}
4226
else if (el.GetType() == PRISM)
4227
{
4228
lam(0) = 0.33; lam(1) = 0.33; lam(2) = 0.5;
4229
}
4230
else if (el.GetType() == PYRAMID)
4231
{
4232
lam(0) = 0.4; lam(1) = 0.4; lam(2) = 0.2;
4233
}
4234
else if (el.GetType() == HEX)
4235
{
4236
lam = 0.5;
4237
}
4238
4239
4240
Vec<3> deltalam,rhs;
4241
netgen::Point<3> x;
4242
Mat<3,3> Jac,Jact;
4243
4244
double delta=1;
4245
4246
bool retval;
4247
4248
int i = 0;
4249
4250
const int maxits = 30;
4251
4252
while(delta > 1e-16 && i<maxits)
4253
{
4254
curvedelems->CalcElementTransformation(lam,element-1,x,Jac);
4255
4256
rhs = p-x;
4257
Jac.Solve(rhs,deltalam);
4258
4259
lam += deltalam;
4260
4261
delta = deltalam.Length2();
4262
4263
i++;
4264
//(*testout) << "pcie i " << i << " delta " << delta << " p " << p << " x " << x << " lam " << lam << endl;
4265
//<< "Jac " << Jac << endl;
4266
}
4267
4268
if(i==maxits)
4269
return false;
4270
4271
4272
for(i=0; i<3; i++)
4273
lami[i] = lam(i);
4274
4275
4276
4277
if (el.GetType() == TET)
4278
{
4279
retval = (lam(0) > -eps &&
4280
lam(1) > -eps &&
4281
lam(2) > -eps &&
4282
lam(0) + lam(1) + lam(2) < 1+eps);
4283
}
4284
else if (el.GetType() == PRISM)
4285
{
4286
retval = (lam(0) > -eps &&
4287
lam(1) > -eps &&
4288
lam(2) > -eps &&
4289
lam(2) < 1+eps &&
4290
lam(0) + lam(1) < 1+eps);
4291
}
4292
else if (el.GetType() == PYRAMID)
4293
{
4294
retval = (lam(0) > -eps &&
4295
lam(1) > -eps &&
4296
lam(2) > -eps &&
4297
lam(0) + lam(2) < 1+eps &&
4298
lam(1) + lam(2) < 1+eps);
4299
}
4300
else if (el.GetType() == HEX)
4301
{
4302
retval = (lam(0) > -eps && lam(0) < 1+eps &&
4303
lam(1) > -eps && lam(1) < 1+eps &&
4304
lam(2) > -eps && lam(2) < 1+eps);
4305
}
4306
else
4307
throw NgException("Da haun i wos vagessn");
4308
4309
return retval;
4310
}
4311
4312
4313
4314
bool Mesh :: PointContainedIn3DElementOld(const Point3d & p,
4315
double lami[3],
4316
const int element) const
4317
{
4318
4319
static Vec3d col1, col2, col3;
4320
static Vec3d rhs, sol;
4321
const double eps = 1.e-4;
4322
4323
static ARRAY<Element> loctets;
4324
4325
VolumeElement(element).GetTets (loctets);
4326
4327
for (int j = 1; j <= loctets.Size(); j++)
4328
{
4329
const Element & el = loctets.Get(j);
4330
4331
const Point3d & p1 = Point(el.PNum(1));
4332
const Point3d & p2 = Point(el.PNum(2));
4333
const Point3d & p3 = Point(el.PNum(3));
4334
const Point3d & p4 = Point(el.PNum(4));
4335
4336
Box3d box;
4337
box.SetPoint (p1);
4338
box.AddPoint (p2);
4339
box.AddPoint (p3);
4340
box.AddPoint (p4);
4341
if (!box.IsIn (p))
4342
continue;
4343
4344
col1 = p2-p1;
4345
col2 = p3-p1;
4346
col3 = p4-p1;
4347
rhs = p - p1;
4348
4349
SolveLinearSystem (col1, col2, col3, rhs, sol);
4350
4351
if (sol.X() >= -eps && sol.Y() >= -eps && sol.Z() >= -eps &&
4352
sol.X() + sol.Y() + sol.Z() <= 1+eps)
4353
{
4354
ARRAY<Element> loctetsloc;
4355
ARRAY<netgen::Point<3> > pointsloc;
4356
4357
VolumeElement(element).GetTetsLocal (loctetsloc);
4358
VolumeElement(element).GetNodesLocalNew (pointsloc);
4359
4360
const Element & le = loctetsloc.Get(j);
4361
4362
4363
Point3d pp =
4364
pointsloc.Get(le.PNum(1))
4365
+ sol.X() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(2)))
4366
+ sol.Y() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(3)))
4367
+ sol.Z() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(4))) ;
4368
4369
lami[0] = pp.X();
4370
lami[1] = pp.Y();
4371
lami[2] = pp.Z();
4372
return true;
4373
}
4374
}
4375
return false;
4376
}
4377
4378
4379
int Mesh :: GetElementOfPoint (const Point3d & p,
4380
double lami[3],
4381
bool build_searchtree,
4382
const int index,
4383
const bool allowindex) const
4384
{
4385
if(index != -1)
4386
{
4387
ARRAY<int> dummy(1);
4388
dummy[0] = index;
4389
return GetElementOfPoint(p,lami,&dummy,build_searchtree,allowindex);
4390
}
4391
else
4392
return GetElementOfPoint(p,lami,NULL,build_searchtree,allowindex);
4393
}
4394
4395
4396
4397
4398
int Mesh :: GetElementOfPoint (const Point3d & p,
4399
double lami[3],
4400
const ARRAY<int> * const indices,
4401
bool build_searchtree,
4402
const bool allowindex) const
4403
{
4404
if (dimension == 2)
4405
{
4406
int i, j;
4407
int ne;
4408
4409
4410
if(ps_startelement != 0 && ps_startelement <= GetNSE() && PointContainedIn2DElement(p,lami,ps_startelement))
4411
return ps_startelement;
4412
4413
ARRAY<int> locels;
4414
if (0)
4415
{
4416
elementsearchtree->GetIntersecting (p, p, locels);
4417
ne = locels.Size();
4418
}
4419
else
4420
ne = GetNSE();
4421
4422
for (i = 1; i <= ne; i++)
4423
{
4424
int ii;
4425
4426
if (0)
4427
ii = locels.Get(i);
4428
else
4429
ii = i;
4430
4431
if(ii == ps_startelement) continue;
4432
4433
if(indices != NULL && indices->Size() > 0)
4434
{
4435
bool contained = indices->Contains(SurfaceElement(ii).GetIndex());
4436
if((allowindex && !contained) || (!allowindex && contained)) continue;
4437
}
4438
4439
if(PointContainedIn2DElement(p,lami,ii)) return ii;
4440
4441
}
4442
return 0;
4443
}
4444
else
4445
4446
{
4447
int i, j;
4448
int ne;
4449
4450
if(ps_startelement != 0 && PointContainedIn3DElement(p,lami,ps_startelement))
4451
return ps_startelement;
4452
4453
ARRAY<int> locels;
4454
if (elementsearchtree || build_searchtree)
4455
{
4456
// update if necessary:
4457
const_cast<Mesh&>(*this).BuildElementSearchTree ();
4458
elementsearchtree->GetIntersecting (p, p, locels);
4459
ne = locels.Size();
4460
}
4461
else
4462
ne = GetNE();
4463
4464
for (i = 1; i <= ne; i++)
4465
{
4466
int ii;
4467
4468
if (elementsearchtree)
4469
ii = locels.Get(i);
4470
else
4471
ii = i;
4472
4473
if(ii == ps_startelement) continue;
4474
4475
if(indices != NULL && indices->Size() > 0)
4476
{
4477
bool contained = indices->Contains(VolumeElement(ii).GetIndex());
4478
if((allowindex && !contained) || (!allowindex && contained)) continue;
4479
}
4480
4481
4482
if(PointContainedIn3DElement(p,lami,ii))
4483
{
4484
ps_startelement = ii;
4485
return ii;
4486
}
4487
}
4488
4489
// Not found, try uncurved variant:
4490
for (i = 1; i <= ne; i++)
4491
{
4492
int ii;
4493
4494
if (elementsearchtree)
4495
ii = locels.Get(i);
4496
else
4497
ii = i;
4498
4499
if(indices != NULL && indices->Size() > 0)
4500
{
4501
bool contained = indices->Contains(VolumeElement(ii).GetIndex());
4502
if((allowindex && !contained) || (!allowindex && contained)) continue;
4503
}
4504
4505
4506
if(PointContainedIn3DElementOld(p,lami,ii))
4507
{
4508
ps_startelement = ii;
4509
(*testout) << "WARNING: found element of point " << p <<" only for uncurved mesh" << endl;
4510
return ii;
4511
}
4512
}
4513
4514
4515
return 0;
4516
}
4517
}
4518
4519
4520
4521
int Mesh :: GetSurfaceElementOfPoint (const Point3d & p,
4522
double lami[3],
4523
bool build_searchtree,
4524
const int index,
4525
const bool allowindex) const
4526
{
4527
if(index != -1)
4528
{
4529
ARRAY<int> dummy(1);
4530
dummy[0] = index;
4531
return GetSurfaceElementOfPoint(p,lami,&dummy,build_searchtree,allowindex);
4532
}
4533
else
4534
return GetSurfaceElementOfPoint(p,lami,NULL,build_searchtree,allowindex);
4535
}
4536
4537
4538
4539
4540
int Mesh :: GetSurfaceElementOfPoint (const Point3d & p,
4541
double lami[3],
4542
const ARRAY<int> * const indices,
4543
bool build_searchtree,
4544
const bool allowindex) const
4545
{
4546
if (dimension == 2)
4547
{
4548
throw NgException("GetSurfaceElementOfPoint not yet implemented for 2D meshes");
4549
}
4550
else
4551
{
4552
double vlam[3];
4553
int velement = GetElementOfPoint(p,vlam,NULL,build_searchtree,allowindex);
4554
4555
//(*testout) << "p " << p << endl;
4556
//(*testout) << "velement " << velement << endl;
4557
4558
ARRAY<int> faces;
4559
topology->GetElementFaces(velement,faces);
4560
4561
//(*testout) << "faces " << faces << endl;
4562
4563
for(int i=0; i<faces.Size(); i++)
4564
faces[i] = topology->GetFace2SurfaceElement(faces[i]);
4565
4566
//(*testout) << "surfel " << faces << endl;
4567
4568
for(int i=0; i<faces.Size(); i++)
4569
{
4570
if(faces[i] == 0)
4571
continue;
4572
4573
if(indices && indices->Size() != 0)
4574
{
4575
if(indices->Contains(SurfaceElement(faces[i]).GetIndex()) &&
4576
PointContainedIn2DElement(p,lami,faces[i],true))
4577
return faces[i];
4578
}
4579
else
4580
{
4581
if(PointContainedIn2DElement(p,lami,faces[i],true))
4582
{
4583
//(*testout) << "found point " << p << " in sel " << faces[i]
4584
// << ", lam " << lami[0] << ", " << lami[1] << ", " << lami[2] << endl;
4585
return faces[i];
4586
}
4587
}
4588
}
4589
4590
}
4591
4592
return 0;
4593
}
4594
4595
4596
void Mesh::GetIntersectingVolEls(const Point3d& p1, const Point3d& p2,
4597
ARRAY<int> & locels) const
4598
{
4599
elementsearchtree->GetIntersecting (p1, p2, locels);
4600
}
4601
4602
void Mesh :: SplitIntoParts()
4603
{
4604
int i, j, dom;
4605
int ne = GetNE();
4606
int np = GetNP();
4607
int nse = GetNSE();
4608
4609
BitArray surfused(nse);
4610
BitArray pused (np);
4611
4612
surfused.Clear();
4613
4614
dom = 0;
4615
4616
while (1)
4617
{
4618
int cntd = 1;
4619
4620
dom++;
4621
4622
pused.Clear();
4623
4624
int found = 0;
4625
for (i = 1; i <= nse; i++)
4626
if (!surfused.Test(i))
4627
{
4628
SurfaceElement(i).SetIndex (dom);
4629
for (j = 1; j <= 3; j++)
4630
pused.Set (SurfaceElement(i).PNum(j));
4631
found = 1;
4632
cntd = 1;
4633
surfused.Set(i);
4634
break;
4635
}
4636
4637
if (!found)
4638
break;
4639
4640
int change;
4641
do
4642
{
4643
change = 0;
4644
for (i = 1; i <= nse; i++)
4645
{
4646
int is = 0, isnot = 0;
4647
for (j = 1; j <= 3; j++)
4648
if (pused.Test(SurfaceElement(i).PNum(j)))
4649
is = 1;
4650
else
4651
isnot = 1;
4652
4653
if (is && isnot)
4654
{
4655
change = 1;
4656
for (j = 1; j <= 3; j++)
4657
pused.Set (SurfaceElement(i).PNum(j));
4658
}
4659
4660
if (is)
4661
{
4662
if (!surfused.Test(i))
4663
{
4664
surfused.Set(i);
4665
SurfaceElement(i).SetIndex (dom);
4666
cntd++;
4667
}
4668
}
4669
}
4670
4671
4672
for (i = 1; i <= ne; i++)
4673
{
4674
int is = 0, isnot = 0;
4675
for (j = 1; j <= 4; j++)
4676
if (pused.Test(VolumeElement(i).PNum(j)))
4677
is = 1;
4678
else
4679
isnot = 1;
4680
4681
if (is && isnot)
4682
{
4683
change = 1;
4684
for (j = 1; j <= 4; j++)
4685
pused.Set (VolumeElement(i).PNum(j));
4686
}
4687
4688
if (is)
4689
{
4690
VolumeElement(i).SetIndex (dom);
4691
}
4692
}
4693
}
4694
while (change);
4695
4696
PrintMessage (3, "domain ", dom, " has ", cntd, " surfaceelements");
4697
}
4698
4699
/*
4700
facedecoding.SetSize (dom);
4701
for (i = 1; i <= dom; i++)
4702
{
4703
facedecoding.Elem(i).surfnr = 0;
4704
facedecoding.Elem(i).domin = i;
4705
facedecoding.Elem(i).domout = 0;
4706
}
4707
*/
4708
ClearFaceDescriptors();
4709
for (i = 1; i <= dom; i++)
4710
AddFaceDescriptor (FaceDescriptor (0, i, 0, 0));
4711
CalcSurfacesOfNode();
4712
timestamp = NextTimeStamp();
4713
}
4714
4715
void Mesh :: SplitSeparatedFaces ()
4716
{
4717
PrintMessage (3, "SplitSeparateFaces");
4718
int fdi;
4719
int np = GetNP();
4720
4721
BitArray usedp(np);
4722
ARRAY<SurfaceElementIndex> els_of_face;
4723
4724
fdi = 1;
4725
while (fdi <= GetNFD())
4726
{
4727
GetSurfaceElementsOfFace (fdi, els_of_face);
4728
4729
if (els_of_face.Size() == 0) continue;
4730
4731
SurfaceElementIndex firstel = els_of_face[0];
4732
4733
usedp.Clear();
4734
for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++)
4735
usedp.Set (SurfaceElement(firstel).PNum(j));
4736
4737
bool changed;
4738
do
4739
{
4740
changed = false;
4741
4742
for (int i = 0; i < els_of_face.Size(); i++)
4743
{
4744
const Element2d & el = SurfaceElement(els_of_face[i]);
4745
4746
bool has = 0;
4747
bool hasno = 0;
4748
for (int j = 0; j < el.GetNP(); j++)
4749
{
4750
if (usedp.Test(el[j]))
4751
has = true;
4752
else
4753
hasno = true;
4754
}
4755
4756
if (has && hasno)
4757
changed = true;
4758
4759
if (has)
4760
for (int j = 0; j < el.GetNP(); j++)
4761
usedp.Set (el[j]);
4762
}
4763
}
4764
while (changed);
4765
4766
int nface = 0;
4767
for (int i = 0; i < els_of_face.Size(); i++)
4768
{
4769
Element2d & el = SurfaceElement(els_of_face[i]);
4770
4771
int hasno = 0;
4772
for (int j = 1; j <= el.GetNP(); j++)
4773
if (!usedp.Test(el.PNum(j)))
4774
hasno = 1;
4775
4776
if (hasno)
4777
{
4778
if (!nface)
4779
{
4780
FaceDescriptor nfd = GetFaceDescriptor(fdi);
4781
nface = AddFaceDescriptor (nfd);
4782
}
4783
4784
el.SetIndex (nface);
4785
}
4786
}
4787
4788
// reconnect list
4789
if (nface)
4790
{
4791
facedecoding[nface-1].firstelement = -1;
4792
facedecoding[fdi-1].firstelement = -1;
4793
4794
for (int i = 0; i < els_of_face.Size(); i++)
4795
{
4796
int ind = SurfaceElement(els_of_face[i]).GetIndex();
4797
SurfaceElement(els_of_face[i]).next = facedecoding[ind-1].firstelement;
4798
facedecoding[ind-1].firstelement = els_of_face[i];
4799
}
4800
}
4801
4802
fdi++;
4803
}
4804
4805
4806
/*
4807
fdi = 1;
4808
while (fdi <= GetNFD())
4809
{
4810
int firstel = 0;
4811
for (int i = 1; i <= GetNSE(); i++)
4812
if (SurfaceElement(i).GetIndex() == fdi)
4813
{
4814
firstel = i;
4815
break;
4816
}
4817
if (!firstel) continue;
4818
4819
usedp.Clear();
4820
for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++)
4821
usedp.Set (SurfaceElement(firstel).PNum(j));
4822
4823
int changed;
4824
do
4825
{
4826
changed = 0;
4827
for (int i = 1; i <= GetNSE(); i++)
4828
{
4829
const Element2d & el = SurfaceElement(i);
4830
if (el.GetIndex() != fdi)
4831
continue;
4832
4833
int has = 0;
4834
int hasno = 0;
4835
for (int j = 1; j <= el.GetNP(); j++)
4836
{
4837
if (usedp.Test(el.PNum(j)))
4838
has = 1;
4839
else
4840
hasno = 1;
4841
}
4842
if (has && hasno)
4843
changed = 1;
4844
4845
if (has)
4846
for (int j = 1; j <= el.GetNP(); j++)
4847
usedp.Set (el.PNum(j));
4848
}
4849
}
4850
while (changed);
4851
4852
int nface = 0;
4853
for (int i = 1; i <= GetNSE(); i++)
4854
{
4855
Element2d & el = SurfaceElement(i);
4856
if (el.GetIndex() != fdi)
4857
continue;
4858
4859
int hasno = 0;
4860
for (int j = 1; j <= el.GetNP(); j++)
4861
{
4862
if (!usedp.Test(el.PNum(j)))
4863
hasno = 1;
4864
}
4865
4866
if (hasno)
4867
{
4868
if (!nface)
4869
{
4870
FaceDescriptor nfd = GetFaceDescriptor(fdi);
4871
nface = AddFaceDescriptor (nfd);
4872
}
4873
4874
el.SetIndex (nface);
4875
}
4876
}
4877
fdi++;
4878
}
4879
*/
4880
}
4881
4882
4883
void Mesh :: GetSurfaceElementsOfFace (int facenr, ARRAY<SurfaceElementIndex> & sei) const
4884
{
4885
static int timer = NgProfiler::CreateTimer ("GetSurfaceElementsOfFace");
4886
NgProfiler::RegionTimer reg (timer);
4887
4888
/*
4889
sei.SetSize (0);
4890
for (SurfaceElementIndex i = 0; i < GetNSE(); i++)
4891
if ( (*this)[i].GetIndex () == facenr && (*this)[i][0] >= PointIndex::BASE &&
4892
!(*this)[i].IsDeleted() )
4893
sei.Append (i);
4894
4895
int size1 = sei.Size();
4896
*/
4897
4898
sei.SetSize(0);
4899
4900
SurfaceElementIndex si = facedecoding[facenr-1].firstelement;
4901
while (si != -1)
4902
{
4903
if ( (*this)[si].GetIndex () == facenr && (*this)[si][0] >= PointIndex::BASE &&
4904
!(*this)[si].IsDeleted() )
4905
{
4906
sei.Append (si);
4907
}
4908
4909
si = (*this)[si].next;
4910
}
4911
4912
/*
4913
// *testout << "with list = " << endl << sei << endl;
4914
4915
if (size1 != sei.Size())
4916
{
4917
cout << "size mismatch" << endl;
4918
exit(1);
4919
}
4920
*/
4921
}
4922
4923
4924
4925
4926
void Mesh :: CalcMinMaxAngle (double badellimit, double * retvalues)
4927
{
4928
int i, j;
4929
int lpi1, lpi2, lpi3, lpi4;
4930
double phimax = 0, phimin = 10;
4931
double facephimax = 0, facephimin = 10;
4932
int illegaltets = 0, negativetets = 0, badtets = 0;
4933
4934
for (i = 1; i <= GetNE(); i++)
4935
{
4936
int badel = 0;
4937
4938
Element & el = VolumeElement(i);
4939
4940
if (el.GetType() != TET)
4941
{
4942
VolumeElement(i).flags.badel = 0;
4943
continue;
4944
}
4945
4946
if (el.Volume(Points()) < 0)
4947
{
4948
badel = 1;
4949
negativetets++;
4950
}
4951
4952
4953
if (!LegalTet (el))
4954
{
4955
badel = 1;
4956
illegaltets++;
4957
(*testout) << "illegal tet: " << i << " ";
4958
for (j = 1; j <= el.GetNP(); j++)
4959
(*testout) << el.PNum(j) << " ";
4960
(*testout) << endl;
4961
}
4962
4963
4964
// angles between faces
4965
for (lpi1 = 1; lpi1 <= 3; lpi1++)
4966
for (lpi2 = lpi1+1; lpi2 <= 4; lpi2++)
4967
{
4968
lpi3 = 1;
4969
while (lpi3 == lpi1 || lpi3 == lpi2)
4970
lpi3++;
4971
lpi4 = 10 - lpi1 - lpi2 - lpi3;
4972
4973
const Point3d & p1 = Point (el.PNum(lpi1));
4974
const Point3d & p2 = Point (el.PNum(lpi2));
4975
const Point3d & p3 = Point (el.PNum(lpi3));
4976
const Point3d & p4 = Point (el.PNum(lpi4));
4977
4978
Vec3d n(p1, p2);
4979
n /= n.Length();
4980
Vec3d v1(p1, p3);
4981
Vec3d v2(p1, p4);
4982
4983
v1 -= (n * v1) * n;
4984
v2 -= (n * v2) * n;
4985
4986
double cosphi = (v1 * v2) / (v1.Length() * v2.Length());
4987
double phi = acos (cosphi);
4988
if (phi > phimax) phimax = phi;
4989
if (phi < phimin) phimin = phi;
4990
4991
if ((180/M_PI) * phi > badellimit)
4992
badel = 1;
4993
}
4994
4995
4996
// angles in faces
4997
for (j = 1; j <= 4; j++)
4998
{
4999
Element2d face;
5000
el.GetFace (j, face);
5001
for (lpi1 = 1; lpi1 <= 3; lpi1++)
5002
{
5003
lpi2 = lpi1 % 3 + 1;
5004
lpi3 = lpi2 % 3 + 1;
5005
5006
const Point3d & p1 = Point (el.PNum(lpi1));
5007
const Point3d & p2 = Point (el.PNum(lpi2));
5008
const Point3d & p3 = Point (el.PNum(lpi3));
5009
5010
Vec3d v1(p1, p2);
5011
Vec3d v2(p1, p3);
5012
double cosphi = (v1 * v2) / (v1.Length() * v2.Length());
5013
double phi = acos (cosphi);
5014
if (phi > facephimax) facephimax = phi;
5015
if (phi < facephimin) facephimin = phi;
5016
5017
if ((180/M_PI) * phi > badellimit)
5018
badel = 1;
5019
5020
}
5021
}
5022
5023
5024
VolumeElement(i).flags.badel = badel;
5025
if (badel) badtets++;
5026
}
5027
5028
if (!GetNE())
5029
{
5030
phimin = phimax = facephimin = facephimax = 0;
5031
}
5032
5033
if (!retvalues)
5034
{
5035
PrintMessage (1, "");
5036
PrintMessage (1, "between planes: phimin = ", (180/M_PI) * phimin,
5037
" phimax = ", (180/M_PI) *phimax);
5038
PrintMessage (1, "inside planes: phimin = ", (180/M_PI) * facephimin,
5039
" phimax = ", (180/M_PI) * facephimax);
5040
PrintMessage (1, "");
5041
}
5042
else
5043
{
5044
retvalues[0] = (180/M_PI) * facephimin;
5045
retvalues[1] = (180/M_PI) * facephimax;
5046
retvalues[2] = (180/M_PI) * phimin;
5047
retvalues[3] = (180/M_PI) * phimax;
5048
}
5049
PrintMessage (3, "negative tets: ", negativetets);
5050
PrintMessage (3, "illegal tets: ", illegaltets);
5051
PrintMessage (3, "bad tets: ", badtets);
5052
}
5053
5054
5055
int Mesh :: MarkIllegalElements ()
5056
{
5057
int cnt = 0;
5058
int i;
5059
5060
for (i = 1; i <= GetNE(); i++)
5061
{
5062
LegalTet (VolumeElement(i));
5063
5064
/*
5065
Element & el = VolumeElement(i);
5066
int leg1 = LegalTet (el);
5067
el.flags.illegal_valid = 0;
5068
int leg2 = LegalTet (el);
5069
5070
if (leg1 != leg2)
5071
{
5072
cerr << "legal differs!!" << endl;
5073
(*testout) << "legal differs" << endl;
5074
(*testout) << "elnr = " << i << ", el = " << el
5075
<< " leg1 = " << leg1 << ", leg2 = " << leg2 << endl;
5076
}
5077
5078
// el.flags.illegal = !LegalTet (el);
5079
*/
5080
cnt += VolumeElement(i).Illegal();
5081
}
5082
return cnt;
5083
}
5084
5085
// #ifdef NONE
5086
// void Mesh :: AddIdentification (int pi1, int pi2, int identnr)
5087
// {
5088
// INDEX_2 pair(pi1, pi2);
5089
// // pair.Sort();
5090
// identifiedpoints->Set (pair, identnr);
5091
// if (identnr > maxidentnr)
5092
// maxidentnr = identnr;
5093
// timestamp = NextTimeStamp();
5094
// }
5095
5096
// int Mesh :: GetIdentification (int pi1, int pi2) const
5097
// {
5098
// INDEX_2 pair(pi1, pi2);
5099
// if (identifiedpoints->Used (pair))
5100
// return identifiedpoints->Get(pair);
5101
// else
5102
// return 0;
5103
// }
5104
5105
// int Mesh :: GetIdentificationSym (int pi1, int pi2) const
5106
// {
5107
// INDEX_2 pair(pi1, pi2);
5108
// if (identifiedpoints->Used (pair))
5109
// return identifiedpoints->Get(pair);
5110
5111
// pair = INDEX_2 (pi2, pi1);
5112
// if (identifiedpoints->Used (pair))
5113
// return identifiedpoints->Get(pair);
5114
5115
// return 0;
5116
// }
5117
5118
5119
// void Mesh :: GetIdentificationMap (int identnr, ARRAY<int> & identmap) const
5120
// {
5121
// int i, j;
5122
5123
// identmap.SetSize (GetNP());
5124
// for (i = 1; i <= identmap.Size(); i++)
5125
// identmap.Elem(i) = 0;
5126
5127
// for (i = 1; i <= identifiedpoints->GetNBags(); i++)
5128
// for (j = 1; j <= identifiedpoints->GetBagSize(i); j++)
5129
// {
5130
// INDEX_2 i2;
5131
// int nr;
5132
// identifiedpoints->GetData (i, j, i2, nr);
5133
5134
// if (nr == identnr)
5135
// {
5136
// identmap.Elem(i2.I1()) = i2.I2();
5137
// }
5138
// }
5139
// }
5140
5141
5142
// void Mesh :: GetIdentificationPairs (int identnr, ARRAY<INDEX_2> & identpairs) const
5143
// {
5144
// int i, j;
5145
5146
// identpairs.SetSize(0);
5147
5148
// for (i = 1; i <= identifiedpoints->GetNBags(); i++)
5149
// for (j = 1; j <= identifiedpoints->GetBagSize(i); j++)
5150
// {
5151
// INDEX_2 i2;
5152
// int nr;
5153
// identifiedpoints->GetData (i, j, i2, nr);
5154
5155
// if (identnr == 0 || nr == identnr)
5156
// identpairs.Append (i2);
5157
// }
5158
// }
5159
// #endif
5160
5161
5162
5163
void Mesh :: InitPointCurve(double red, double green, double blue) const
5164
{
5165
pointcurves_startpoint.Append(pointcurves.Size());
5166
pointcurves_red.Append(red);
5167
pointcurves_green.Append(green);
5168
pointcurves_blue.Append(blue);
5169
}
5170
void Mesh :: AddPointCurvePoint(const Point3d & pt) const
5171
{
5172
pointcurves.Append(pt);
5173
}
5174
int Mesh :: GetNumPointCurves(void) const
5175
{
5176
return pointcurves_startpoint.Size();
5177
}
5178
int Mesh :: GetNumPointsOfPointCurve(int curve) const
5179
{
5180
if(curve == pointcurves_startpoint.Size()-1)
5181
return (pointcurves.Size() - pointcurves_startpoint.Last());
5182
else
5183
return (pointcurves_startpoint[curve+1]-pointcurves_startpoint[curve]);
5184
}
5185
5186
Point3d & Mesh :: GetPointCurvePoint(int curve, int n) const
5187
{
5188
return pointcurves[pointcurves_startpoint[curve]+n];
5189
}
5190
5191
void Mesh :: GetPointCurveColor(int curve, double & red, double & green, double & blue) const
5192
{
5193
red = pointcurves_red[curve];
5194
green = pointcurves_green[curve];
5195
blue = pointcurves_blue[curve];
5196
}
5197
5198
5199
void Mesh :: ComputeNVertices ()
5200
{
5201
int i, j, nv;
5202
int ne = GetNE();
5203
int nse = GetNSE();
5204
5205
numvertices = 0;
5206
for (i = 1; i <= ne; i++)
5207
{
5208
const Element & el = VolumeElement(i);
5209
nv = el.GetNV();
5210
for (j = 0; j < nv; j++)
5211
if (el[j] > numvertices)
5212
numvertices = el[j];
5213
}
5214
for (i = 1; i <= nse; i++)
5215
{
5216
const Element2d & el = SurfaceElement(i);
5217
nv = el.GetNV();
5218
for (j = 1; j <= nv; j++)
5219
if (el.PNum(j) > numvertices)
5220
numvertices = el.PNum(j);
5221
}
5222
5223
numvertices += 1- PointIndex::BASE;
5224
}
5225
5226
int Mesh :: GetNV () const
5227
{
5228
if (numvertices < 0)
5229
return GetNP();
5230
else
5231
return numvertices;
5232
}
5233
5234
void Mesh :: SetNP (int np)
5235
{
5236
points.SetSize(np);
5237
// ptyps.SetSize(np);
5238
5239
int mlold = mlbetweennodes.Size();
5240
mlbetweennodes.SetSize(np);
5241
if (np > mlold)
5242
for (int i = mlold+PointIndex::BASE;
5243
i < np+PointIndex::BASE; i++)
5244
{
5245
mlbetweennodes[i].I1() = PointIndex::BASE-1;
5246
mlbetweennodes[i].I2() = PointIndex::BASE-1;
5247
}
5248
5249
GetIdentifications().SetMaxPointNr (np + PointIndex::BASE-1);
5250
}
5251
5252
5253
/*
5254
void Mesh :: BuildConnectedNodes ()
5255
{
5256
if (PureTetMesh())
5257
{
5258
connectedtonode.SetSize(0);
5259
return;
5260
}
5261
5262
5263
int i, j, k;
5264
int np = GetNP();
5265
int ne = GetNE();
5266
TABLE<int> conto(np);
5267
for (i = 1; i <= ne; i++)
5268
{
5269
const Element & el = VolumeElement(i);
5270
5271
if (el.GetType() == PRISM)
5272
{
5273
for (j = 1; j <= 6; j++)
5274
{
5275
int n1 = el.PNum (j);
5276
int n2 = el.PNum ((j+2)%6+1);
5277
// if (n1 != n2)
5278
{
5279
int found = 0;
5280
for (k = 1; k <= conto.EntrySize(n1); k++)
5281
if (conto.Get(n1, k) == n2)
5282
{
5283
found = 1;
5284
break;
5285
}
5286
if (!found)
5287
conto.Add (n1, n2);
5288
}
5289
}
5290
}
5291
else if (el.GetType() == PYRAMID)
5292
{
5293
for (j = 1; j <= 4; j++)
5294
{
5295
int n1, n2;
5296
switch (j)
5297
{
5298
case 1: n1 = 1; n2 = 4; break;
5299
case 2: n1 = 4; n2 = 1; break;
5300
case 3: n1 = 2; n2 = 3; break;
5301
case 4: n1 = 3; n2 = 2; break;
5302
}
5303
5304
int found = 0;
5305
for (k = 1; k <= conto.EntrySize(n1); k++)
5306
if (conto.Get(n1, k) == n2)
5307
{
5308
found = 1;
5309
break;
5310
}
5311
if (!found)
5312
conto.Add (n1, n2);
5313
}
5314
}
5315
}
5316
5317
connectedtonode.SetSize(np);
5318
for (i = 1; i <= np; i++)
5319
connectedtonode.Elem(i) = 0;
5320
5321
for (i = 1; i <= np; i++)
5322
if (connectedtonode.Elem(i) == 0)
5323
{
5324
connectedtonode.Elem(i) = i;
5325
ConnectToNodeRec (i, i, conto);
5326
}
5327
5328
5329
5330
}
5331
5332
void Mesh :: ConnectToNodeRec (int node, int tonode,
5333
const TABLE<int> & conto)
5334
{
5335
int i, n2;
5336
// (*testout) << "connect " << node << " to " << tonode << endl;
5337
for (i = 1; i <= conto.EntrySize(node); i++)
5338
{
5339
n2 = conto.Get(node, i);
5340
if (!connectedtonode.Get(n2))
5341
{
5342
connectedtonode.Elem(n2) = tonode;
5343
ConnectToNodeRec (n2, tonode, conto);
5344
}
5345
}
5346
}
5347
*/
5348
5349
5350
bool Mesh :: PureTrigMesh (int faceindex) const
5351
{
5352
if (!faceindex)
5353
return !mparam.quad;
5354
5355
int i;
5356
for (i = 1; i <= GetNSE(); i++)
5357
if (SurfaceElement(i).GetIndex() == faceindex &&
5358
SurfaceElement(i).GetNP() != 3)
5359
return 0;
5360
return 1;
5361
}
5362
5363
bool Mesh :: PureTetMesh () const
5364
{
5365
for (ElementIndex ei = 0; ei < GetNE(); ei++)
5366
if (VolumeElement(ei).GetNP() != 4)
5367
return 0;
5368
return 1;
5369
}
5370
5371
void Mesh :: UpdateTopology()
5372
{
5373
topology->Update();
5374
clusters->Update();
5375
}
5376
5377
5378
void Mesh :: SetMaterial (int domnr, const char * mat)
5379
{
5380
if (domnr > materials.Size())
5381
{
5382
int olds = materials.Size();
5383
materials.SetSize (domnr);
5384
for (int i = olds; i < domnr; i++)
5385
materials[i] = 0;
5386
}
5387
materials.Elem(domnr) = new char[strlen(mat)+1];
5388
strcpy (materials.Elem(domnr), mat);
5389
}
5390
5391
const char * Mesh :: GetMaterial (int domnr) const
5392
{
5393
if (domnr <= materials.Size())
5394
return materials.Get(domnr);
5395
return 0;
5396
}
5397
5398
void Mesh ::SetNBCNames ( int nbcn )
5399
{
5400
if ( bcnames.Size() )
5401
for ( int i = 0; i < bcnames.Size(); i++)
5402
if ( bcnames[i] ) delete bcnames[i];
5403
bcnames.SetSize(nbcn);
5404
bcnames = 0;
5405
}
5406
5407
void Mesh ::SetBCName ( int bcnr, const string & abcname )
5408
{
5409
if ( bcnames[bcnr] ) delete bcnames[bcnr];
5410
if ( abcname != "default" )
5411
bcnames[bcnr] = new string ( abcname );
5412
else
5413
bcnames[bcnr] = 0;
5414
}
5415
5416
string Mesh ::GetBCName ( int bcnr ) const
5417
{
5418
if ( !bcnames.Size() )
5419
return "default";
5420
if ( bcnames[bcnr] )
5421
return *bcnames[bcnr];
5422
else
5423
return "default";
5424
}
5425
5426
void Mesh :: SetUserData(const char * id, ARRAY<int> & data)
5427
{
5428
if(userdata_int.Used(id))
5429
delete userdata_int.Get(id);
5430
5431
ARRAY<int> * newdata = new ARRAY<int>(data);
5432
5433
userdata_int.Set(id,newdata);
5434
}
5435
bool Mesh :: GetUserData(const char * id, ARRAY<int> & data, int shift) const
5436
{
5437
if(userdata_int.Used(id))
5438
{
5439
if(data.Size() < (*userdata_int.Get(id)).Size()+shift)
5440
data.SetSize((*userdata_int.Get(id)).Size()+shift);
5441
for(int i=0; i<(*userdata_int.Get(id)).Size(); i++)
5442
data[i+shift] = (*userdata_int.Get(id))[i];
5443
return true;
5444
}
5445
else
5446
{
5447
data.SetSize(0);
5448
return false;
5449
}
5450
}
5451
void Mesh :: SetUserData(const char * id, ARRAY<double> & data)
5452
{
5453
if(userdata_double.Used(id))
5454
delete userdata_double.Get(id);
5455
5456
ARRAY<double> * newdata = new ARRAY<double>(data);
5457
5458
userdata_double.Set(id,newdata);
5459
}
5460
bool Mesh :: GetUserData(const char * id, ARRAY<double> & data, int shift) const
5461
{
5462
if(userdata_double.Used(id))
5463
{
5464
if(data.Size() < (*userdata_double.Get(id)).Size()+shift)
5465
data.SetSize((*userdata_double.Get(id)).Size()+shift);
5466
for(int i=0; i<(*userdata_double.Get(id)).Size(); i++)
5467
data[i+shift] = (*userdata_double.Get(id))[i];
5468
return true;
5469
}
5470
else
5471
{
5472
data.SetSize(0);
5473
return false;
5474
}
5475
}
5476
5477
5478
5479
void Mesh :: PrintMemInfo (ostream & ost) const
5480
{
5481
ost << "Mesh Mem:" << endl;
5482
5483
ost << GetNP() << " Points, of size "
5484
<< sizeof (Point3d) << " + " << sizeof(POINTTYPE) << " = "
5485
<< GetNP() * (sizeof (Point3d) + sizeof(POINTTYPE)) << endl;
5486
5487
ost << GetNSE() << " Surface elements, of size "
5488
<< sizeof (Element2d) << " = "
5489
<< GetNSE() * sizeof(Element2d) << endl;
5490
5491
ost << GetNE() << " Volume elements, of size "
5492
<< sizeof (Element) << " = "
5493
<< GetNE() * sizeof(Element) << endl;
5494
5495
ost << "surfs on node:";
5496
surfacesonnode.PrintMemInfo (cout);
5497
5498
ost << "boundaryedges: ";
5499
if (boundaryedges)
5500
boundaryedges->PrintMemInfo (cout);
5501
5502
ost << "surfelementht: ";
5503
if (surfelementht)
5504
surfelementht->PrintMemInfo (cout);
5505
}
5506
}
5507
5508