Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/Application/src/meshutils.cpp
3203 views
1
/*****************************************************************************
2
* *
3
* Elmer, A Finite Element Software for Multiphysical Problems *
4
* *
5
* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *
6
* *
7
* This program is free software; you can redistribute it and/or *
8
* modify it under the terms of the GNU General Public License *
9
* as published by the Free Software Foundation; either version 2 *
10
* of the License, or (at your option) any later version. *
11
* *
12
* This program is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU General Public License for more details. *
16
* *
17
* You should have received a copy of the GNU General Public License *
18
* along with this program (in file fem/GPL-2); if not, write to the *
19
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20
* Boston, MA 02110-1301, USA. *
21
* *
22
*****************************************************************************/
23
24
/*****************************************************************************
25
* *
26
* ElmerGUI meshutils *
27
* *
28
*****************************************************************************
29
* *
30
* Authors: Mikko Lyly, Juha Ruokolainen and Peter RÃ¥back *
31
* Email: [email protected] *
32
* Web: http://www.csc.fi/elmer *
33
* Address: CSC - IT Center for Science Ltd. *
34
* Keilaranta 14 *
35
* 02101 Espoo, Finland *
36
* *
37
* Original Date: 15 Mar 2008 *
38
* *
39
*****************************************************************************/
40
41
#include <QtCore>
42
#include <iostream>
43
#include <stdlib.h>
44
#include <cmath>
45
#include "meshutils.h"
46
using namespace std;
47
48
template <typename T>
49
T **AllocateDynamicArray(int nRows, int nCols) {
50
T **dynamicArray;
51
dynamicArray = new T*[nRows];
52
for( int i = 0 ; i < nRows ; i++ )
53
dynamicArray[i] = new T [nCols];
54
return dynamicArray;
55
}
56
57
template <typename T>
58
void FreeDynamicArray(T** dArray) {
59
delete [] *dArray;
60
delete [] dArray;
61
}
62
63
template <typename T>
64
T *AllocateDynamicVector(int nRows) {
65
T *dynamicArray;
66
dynamicArray = new T[nRows];
67
return dynamicArray;
68
}
69
70
template <typename T>
71
void FreeDynamicVector(T* dArray) {
72
delete [] dArray;
73
}
74
75
Meshutils::Meshutils()
76
{
77
}
78
79
80
Meshutils::~Meshutils()
81
{
82
}
83
84
85
// Clear mesh...
86
//-----------------------------------------------------------------------------
87
void Meshutils::clearMesh(mesh_t *mesh)
88
{
89
if(mesh == NULL)
90
return;
91
92
mesh->clear();
93
delete mesh;
94
95
cout << "Old mesh cleared" << endl;
96
cout.flush();
97
}
98
99
100
101
// Find surface elements for 3D elements when they are not provided
102
//----------------------------------------------------------------------------
103
void Meshutils::findSurfaceElements(mesh_t *mesh)
104
{
105
#define RESETENTRY1 \
106
h->node[0] = UNKNOWN; \
107
h->node[1] = UNKNOWN; \
108
h->element[0] = UNKNOWN; \
109
h->element[1] = UNKNOWN; \
110
h->index[0] = UNKNOWN; \
111
h->index[1] = UNKNOWN; \
112
h->next = NULL;
113
114
class hashEntry {
115
public:
116
int node[2];
117
int element[2];
118
int index[2];
119
int face;
120
hashEntry *next;
121
};
122
123
124
if(mesh->getElements() == 0) return;
125
126
int keys = mesh->getNodes();
127
hashEntry *hash = new hashEntry[keys];
128
129
bool found;
130
hashEntry *h;
131
132
for(int i=0; i<keys; i++) {
133
h = &hash[i];
134
RESETENTRY1;
135
}
136
137
// TODO: only 1st and 2nd order elements
138
139
static int familyfaces[9] = {0, 0, 0, 0, 0, 4, 5, 5, 6};
140
141
static int faceedges8[] = {4, 4, 4, 4, 4, 4};
142
static int facemap8[][8] = {{0,1,2,3,8,9,10,11}, {4,5,6,7,16,17,18,19}, {0,1,5,4,8,13,16,12}, {1,2,6,5,9,14,17,13}, {2,3,7,6,10,15,18,14}, {3,0,4,7,11,12,19,15}};
143
144
static int faceedges7[] = {3, 3, 4, 4, 4};
145
static int facemap7[][8] = {{0,1,2,6,7,8}, {3,4,5,12,13,14}, {0,1,4,3,6,10,12,9}, {1,2,5,4,7,11,13,10}, {2,0,3,5,8,9,14,11}};
146
147
static int faceedges6[] = {4, 3, 3, 3, 3};
148
static int facemap6[][8] = {{0,1,2,3,5,6,7,8}, {0,1,4,5,10,9}, {1,2,4,6,11,10}, {2,3,4,7,12,11}, {3,0,4,8,9,12}};
149
150
static int faceedges5[4] = {3, 3, 3, 3};
151
static int facemap5[][6] = {{0,1,2,4,5,6}, {0,1,3,4,8,7}, {1,2,3,5,9,8}, {2,0,3,6,7,9}};
152
153
154
for(int i=0; i < mesh->getElements(); i++) {
155
element_t *e = mesh->getElement(i);
156
157
int facenodes = 0;
158
int *facemap = NULL;
159
int n[4];
160
161
int family = e->getCode() / 100;
162
int faces = familyfaces[family];
163
164
for(int f=0; f<faces; f++) {
165
if(family == 5) {
166
facenodes = faceedges5[f];
167
facemap = &facemap5[f][0];
168
}
169
else if(family == 6) {
170
facenodes = faceedges6[f];
171
facemap = &facemap6[f][0];
172
}
173
else if(family == 7) {
174
facenodes = faceedges7[f];
175
facemap = &facemap7[f][0];
176
}
177
else if(family == 8) {
178
facenodes = faceedges8[f];
179
facemap = &facemap8[f][0];
180
}
181
182
for(int j=0; j < facenodes; j++)
183
n[j] = e->getNodeIndex(facemap[j]);
184
185
// Order indexes in an increasing order
186
for(int k=facenodes-1;k>0;k--) {
187
for(int j=0;j<k;j++) {
188
if(n[j] > n[j+1]) {
189
int tmp = n[j+1];
190
n[j+1] = n[j];
191
n[j] = tmp;
192
}
193
}
194
}
195
196
// three nodes define a face uniquely also for rectangles
197
h = &hash[n[0]];
198
found = false;
199
while(h->next) {
200
if((h->node[0] == n[1]) && (h->node[1] == n[2])) {
201
found = true;
202
break;
203
}
204
h = h->next;
205
}
206
207
if(!found) {
208
h->node[0] = n[1];
209
h->node[1] = n[2];
210
h->element[0] = i;
211
h->index[0] = e->getIndex();
212
h->face = f;
213
214
h->next = new hashEntry;
215
h = h->next;
216
RESETENTRY1;
217
} else {
218
h->index[1] = e->getIndex();
219
h->element[1] = i;
220
}
221
}
222
}
223
224
// count faces that have different materials at either sides:
225
int allsurfaces = 0;
226
int surfaces = 0;
227
int maxindex1 = 0;
228
int maxindex2 = 0;
229
for(int i=0; i<keys; i++) {
230
h = &hash[i];
231
while(h->next){
232
if(h->element[0] > UNKNOWN) allsurfaces++;
233
if(h->index[0] != h->index[1]) surfaces++;
234
if(h->index[0] > maxindex1) maxindex1 = h->index[0];
235
if(h->index[1] > maxindex2) maxindex2 = h->index[1];
236
h = h->next;
237
}
238
}
239
cout << "Found " << surfaces << " interface faces of " << allsurfaces << endl;
240
241
242
// Create a index table such that all combinations of materials
243
// get different BC index
244
//int indextable[maxindex1+1][maxindex2+1];
245
int **indextable = AllocateDynamicArray<int>(maxindex1+1, maxindex2+1);
246
int index1,index2;
247
for(int i=0;i<=maxindex1;i++)
248
for(int j=0;j<=maxindex2;j++)
249
indextable[i][j] = 0;
250
251
for(int i=0; i<keys; i++) {
252
h = &hash[i];
253
while(h->next){
254
if(h->index[0] != h->index[1]) {
255
index1 = h->index[0];
256
index2 = h->index[1];
257
if(index2 == -1) index2 = 0;
258
indextable[index1][index2] = 1;
259
}
260
h = h->next;
261
}
262
}
263
index1=0;
264
for(int i=0;i<=maxindex1;i++)
265
for(int j=0;j<=maxindex2;j++)
266
if(indextable[i][j]) indextable[i][j] = ++index1;
267
268
cout << "Boundaries were numbered up to index " << index1 << endl;
269
270
// Finally set the surfaces:
271
mesh->setSurfaces(surfaces);
272
mesh->newSurfaceArray(mesh->getSurfaces());
273
274
surfaces = 0;
275
for(int i=0; i<keys; i++) {
276
h = &hash[i];
277
278
while(h->next) {
279
if(h->index[0] != h->index[1]) {
280
surface_t *s = mesh->getSurface(surfaces);
281
282
s->setElements(1);
283
s->newElementIndexes(2);
284
s->setElementIndex(0, h->element[0]);
285
s->setElementIndex(1, h->element[1]);
286
if(s->getElementIndex(1) >= 0) s->setElements(2); // ?????
287
288
element_t *e = mesh->getElement(h->element[0]);
289
int code = e->getCode();
290
int family = code / 100;
291
int f = h->face;
292
293
int faceedges = 0;
294
int *facemap = NULL;
295
int degree = 1;
296
297
if(family == 5) {
298
faceedges = faceedges5[f];
299
if( code == 510) degree = 2;
300
facemap = &facemap5[f][0];
301
}
302
else if(family == 6) {
303
faceedges = faceedges6[f];
304
if( code == 613) degree = 2;
305
facemap = &facemap6[f][0];
306
}
307
else if(family == 7) {
308
faceedges = faceedges7[f];
309
if( code == 715) degree = 2;
310
facemap = &facemap7[f][0];
311
}
312
else if(family == 8) {
313
faceedges = faceedges8[f];
314
if( code == 820 ) degree = 2;
315
facemap = &facemap8[f][0];
316
}
317
318
int facenodes = degree * faceedges;
319
if (code == 827) facenodes = 9;
320
321
s->setNodes(facenodes);
322
s->setCode(100 * faceedges + facenodes);
323
s->newNodeIndexes(s->getNodes());
324
for(int j=0; j < s->getNodes(); j++)
325
s->setNodeIndex(j, e->getNodeIndex(facemap[j]));
326
327
index1 = h->index[0];
328
index2 = h->index[1];
329
if(index2 < 0) index2 = 0;
330
331
s->setIndex(indextable[index1][index2]);
332
333
s->setEdges(s->getNodes());
334
s->newEdgeIndexes(s->getEdges());
335
for(int j=0; j < s->getEdges(); j++)
336
s->setEdgeIndex(j, UNKNOWN);
337
338
s->setNature(PDE_BOUNDARY);
339
surfaces++;
340
}
341
h = h->next;
342
}
343
}
344
345
delete [] hash;
346
}
347
348
349
350
// Find parent elements for existing surfaces...
351
//----------------------------------------------------------------------------
352
void Meshutils::findEdgeElementParents(mesh_t *mesh)
353
{
354
#define RESETENTRY0 \
355
h->node[0] = UNKNOWN; \
356
h->node[1] = UNKNOWN; \
357
h->element[0] = UNKNOWN; \
358
h->element[1] = UNKNOWN; \
359
h->next = NULL;
360
361
class hashEntry {
362
public:
363
int node[2];
364
int element[2];
365
hashEntry *next;
366
};
367
368
int keys = mesh->getNodes();
369
hashEntry *hash = new hashEntry[keys];
370
371
bool found;
372
hashEntry *h;
373
374
for(int i=0; i<keys; i++) {
375
h = &hash[i];
376
RESETENTRY0;
377
}
378
379
// TODO: only tetrahedron at the moment
380
381
static int edgemap[][2] = {{0,1}, {1,2}, {2,0}};
382
383
for(int i = 0; i < mesh->getSurfaces(); i++) {
384
surface_t *s = mesh->getSurface(i);
385
386
for(int f = 0; f < 3; f++) {
387
int n0 = s->getNodeIndex(edgemap[f][0]);
388
int n1 = s->getNodeIndex(edgemap[f][1]);
389
390
if(n1 < n0) {
391
int tmp = n1;
392
n1 = n0;
393
n0 = tmp;
394
}
395
396
h = &hash[n0];
397
found = false;
398
while(h->next) {
399
if(h->node[0] == n1) {
400
found = true;
401
break;
402
}
403
h = h->next;
404
}
405
406
if(!found) {
407
h->node[0] = n1;
408
h->element[0] = i;
409
h->next = new hashEntry;
410
h = h->next;
411
RESETENTRY0;
412
} else {
413
h->element[1] = i;
414
}
415
}
416
}
417
418
// count faces:
419
int edges = 0;
420
for(int i = 0; i < keys; i++) {
421
h = &hash[i];
422
while((h = h->next) != NULL)
423
edges++;
424
}
425
426
cout << "Found total of " << edges << " edges" << endl;
427
428
// Finally find parents:
429
for(int i = 0; i < mesh->getEdges(); i++) {
430
edge_t *e = mesh->getEdge(i);
431
432
int n0 = e->getNodeIndex(0);
433
int n1 = e->getNodeIndex(1);
434
435
if(n1 < n0) {
436
int tmp = n1;
437
n1 = n0;
438
n0 = tmp;
439
}
440
441
h = &hash[n0];
442
while(h->next) {
443
if(h->node[0] == n1) {
444
445
// should we deallocate s->element if it exists?
446
e->setSurfaces(2);
447
e->newSurfaceIndexes(2);
448
449
e->setSurfaceIndex(0, h->element[0]);
450
e->setSurfaceIndex(1, h->element[1]);
451
}
452
h = h->next;
453
}
454
}
455
456
delete [] hash;
457
}
458
459
460
// Find parent elements for existing surfaces...
461
//----------------------------------------------------------------------------
462
void Meshutils::findSurfaceElementParents(mesh_t *mesh)
463
{
464
#define RESETENTRY0 \
465
h->node[0] = UNKNOWN; \
466
h->node[1] = UNKNOWN; \
467
h->element[0] = UNKNOWN; \
468
h->element[1] = UNKNOWN; \
469
h->next = NULL;
470
471
class hashEntry {
472
public:
473
int node[2];
474
int element[2];
475
hashEntry *next;
476
};
477
478
int keys = mesh->getNodes();
479
hashEntry *hash = new hashEntry[keys];
480
481
bool found;
482
hashEntry *h;
483
484
for(int i=0; i<keys; i++) {
485
h = &hash[i];
486
RESETENTRY0;
487
}
488
489
// TODO: only tetrahedron at the moment
490
491
static int facemap[][3] = {{0,1,2}, {0,1,3}, {0,2,3}, {1,2,3}};
492
493
for(int i=0; i < mesh->getElements(); i++) {
494
element_t *e = mesh->getElement(i);
495
496
for(int f=0; f<4; f++) {
497
int n0 = e->getNodeIndex(facemap[f][0]);
498
int n1 = e->getNodeIndex(facemap[f][1]);
499
int n2 = e->getNodeIndex(facemap[f][2]);
500
501
if(n2 < n1) {
502
int tmp = n2;
503
n2 = n1;
504
n1 = tmp;
505
}
506
507
if(n2 < n0) {
508
int tmp = n2;
509
n2 = n0;
510
n0 = tmp;
511
}
512
513
if(n1 < n0) {
514
int tmp = n1;
515
n1 = n0;
516
n0 = tmp;
517
}
518
519
h = &hash[n0];
520
found = false;
521
while(h->next) {
522
if((h->node[0] == n1) && (h->node[1] == n2)) {
523
found = true;
524
break;
525
}
526
h = h->next;
527
}
528
529
if(!found) {
530
h->node[0] = n1;
531
h->node[1] = n2;
532
h->element[0] = i;
533
h->next = new hashEntry;
534
h = h->next;
535
RESETENTRY0;
536
} else {
537
h->element[1] = i;
538
}
539
}
540
}
541
542
// count faces:
543
int faces = 0;
544
for(int i=0; i<keys; i++) {
545
h = &hash[i];
546
while((h = h->next) != NULL)
547
faces++;
548
}
549
550
cout << "Found total of " << faces << " faces" << endl;
551
552
// Finally find parents:
553
for(int i=0; i < mesh->getSurfaces(); i++) {
554
surface_t *s = mesh->getSurface(i);
555
556
int n0 = s->getNodeIndex(0);
557
int n1 = s->getNodeIndex(1);
558
int n2 = s->getNodeIndex(2);
559
560
if(n2 < n1) {
561
int tmp = n2;
562
n2 = n1;
563
n1 = tmp;
564
}
565
566
if(n2 < n0) {
567
int tmp = n2;
568
n2 = n0;
569
n0 = tmp;
570
}
571
572
if(n1 < n0) {
573
int tmp = n1;
574
n1 = n0;
575
n0 = tmp;
576
}
577
578
h = &hash[n0];
579
while(h->next) {
580
if((h->node[0] == n1) && (h->node[1] == n2)) {
581
582
// should we deallocate s->element if it exists?
583
s->setElements(2);
584
s->newElementIndexes(2);
585
586
s->setElementIndex(0, h->element[0]);
587
s->setElementIndex(1, h->element[1]);
588
}
589
h = h->next;
590
}
591
}
592
593
delete [] hash;
594
}
595
596
597
598
// Find points for edge elements...
599
//-----------------------------------------------------------------------------
600
void Meshutils::findEdgeElementPoints(mesh_t *mesh)
601
{
602
class hashEntry {
603
public:
604
int edges;
605
int *edge;
606
};
607
608
int keys = mesh->getNodes();
609
610
hashEntry *hash = new hashEntry[keys];
611
612
for(int i = 0; i < keys; i++) {
613
hashEntry *h = &hash[i];
614
h->edges = 0;
615
h->edge = NULL;
616
}
617
618
for(int i = 0; i < mesh->getEdges(); i++) {
619
edge_t *e = mesh->getEdge(i);
620
621
if(e->getNature() == PDE_BOUNDARY) {
622
for(int k = 0; k < 2; k++) {
623
int n = e->getNodeIndex(k);
624
625
hashEntry *h = &hash[n];
626
627
bool found = false;
628
for(int j = 0; j < h->edges; j++) {
629
if(h->edge[j] == i) {
630
found = true;
631
break;
632
}
633
}
634
635
if(!found) {
636
int *tmp = new int[h->edges+1];
637
for(int j = 0; j < h->edges; j++)
638
tmp[j] = h->edge[j];
639
tmp[h->edges] = i;
640
delete [] h->edge;
641
642
h->edges++;
643
h->edge = tmp;
644
}
645
}
646
}
647
}
648
649
// count points:
650
int count = 0;
651
for(int i = 0; i < keys; i++) {
652
hashEntry *h = &hash[i];
653
if(h->edges > 0)
654
count++;
655
}
656
657
cout << "Found " << count << " points on boundary edges" << endl;
658
cout.flush();
659
660
// delete old points, if any:
661
if(mesh->getPoints() > 0) {
662
cout << "Deleting old points and creating new" << endl;
663
cout.flush();
664
for(int i = 0; i < mesh->getPoints(); i++) {
665
mesh->getPoint(i)->deleteNodeIndexes();
666
mesh->getPoint(i)->deleteEdgeIndexes();
667
}
668
mesh->deletePointArray();
669
}
670
671
mesh->setPoints(count);
672
mesh->newPointArray(mesh->getPoints());
673
674
count = 0;
675
for(int i = 0; i < keys; i++) {
676
hashEntry *h = &hash[i];
677
678
if(h->edges > 0) {
679
point_t *p = mesh->getPoint(count++);
680
p->setNodes(1);
681
p->newNodeIndexes(1);
682
p->setNodeIndex(0, i);
683
p->setEdges(h->edges);
684
p->newEdgeIndexes(p->getEdges());
685
for(int j = 0; j < p->getEdges(); j++) {
686
p->setEdgeIndex(j, h->edge[j]);
687
}
688
p->setSharp(false);
689
}
690
}
691
692
// delete temp stuff
693
for(int i = 0; i < keys; i++) {
694
hashEntry *h = &hash[i];
695
if(h->edges > 0)
696
delete [] h->edge;
697
}
698
699
delete [] hash;
700
701
// Inverse map
702
cout << "Constructing inverse map from edges to points" << endl;
703
cout.flush();
704
705
for(int i=0; i < mesh->getPoints(); i++) {
706
point_t *p = mesh->getPoint(i);
707
708
for(int j=0; j < p->getEdges(); j++) {
709
int k = p->getEdgeIndex(j);
710
if ( k<0 ) continue;
711
712
edge_t *e = mesh->getEdge(k);
713
714
// allocate space for two points, if not yet done:
715
if(e->getPoints() < 2) {
716
e->setPoints(2);
717
e->newPointIndexes(2);
718
e->setPointIndex(0, -1);
719
e->setPointIndex(1, -1);
720
}
721
722
for(int r=0; r < e->getPoints(); r++) {
723
if(e->getPointIndex(r) < 0) {
724
e->setPointIndex(r, i);
725
break;
726
}
727
}
728
}
729
}
730
}
731
732
733
734
// Find edges for surface elements...
735
//-----------------------------------------------------------------------------
736
void Meshutils::findSurfaceElementEdges(mesh_t *mesh)
737
{
738
#define RESETENTRY \
739
h->surfaces = 0; \
740
h->surface = NULL; \
741
h->parentindex[0] = UNKNOWN; \
742
h->parentindex[1] = UNKNOWN; \
743
h->next = NULL;
744
745
int keys = mesh->getNodes();
746
747
class hashEntry {
748
public:
749
int nodes;
750
int *node;
751
int nature;
752
int index;
753
int surfaces;
754
int *surface;
755
int parentindex[2];
756
hashEntry *next;
757
};
758
759
hashEntry *hash = new hashEntry[keys];
760
761
bool found;
762
hashEntry *h;
763
764
for(int i=0; i<keys; i++) {
765
h = &hash[i];
766
RESETENTRY;
767
}
768
769
bool createindexes = ((!mesh->getEdges()) && (!mesh->getElements()));
770
771
// ????? should we test for mesh->edges ?????
772
// if ( mesh->edge && (mesh->getEdges() > 0) ) {
773
if ( mesh->getEdges() > 0 ) {
774
// add existing edges first:
775
for( int i=0; i<mesh->getEdges(); i++ )
776
{
777
edge_t *edge = mesh->getEdge(i);
778
int n0 = edge->getNodeIndex(0);
779
int n1 = edge->getNodeIndex(1);
780
781
int m = (n0<n1) ? n0 : n1;
782
int n = (n0<n1) ? n1 : n0;
783
784
h = &hash[m];
785
found = false;
786
while(h->next) {
787
if(h->node[0] == n) {
788
found = true;
789
break;
790
}
791
h = h->next;
792
}
793
794
if(!found) {
795
h->nodes = edge->getNodes() - 1;
796
h->node = new int[h->nodes];
797
h->node[0] = n;
798
for( int j=1; j<h->nodes; j++ )
799
{
800
h->node[j] = edge->getNodeIndex(j+1);
801
}
802
h->surfaces = edge->getSurfaces();
803
h->surface = new int[edge->getSurfaces()];
804
for( int j=0; j < edge->getSurfaces(); j++ ) {
805
h->surface[j] = edge->getSurfaceIndex(j);
806
}
807
h->index = edge->getIndex();
808
h->nature = edge->getNature();
809
h->next = new hashEntry;
810
h = h->next;
811
RESETENTRY;
812
}
813
}
814
815
mesh->setEdges(0);
816
mesh->deleteEdgeArray(); // delete [] mesh->edge;
817
}
818
819
820
static int triedgemap[][4] = { {0,1,3,6}, {1,2,4,7}, {2,0,5,8} };
821
static int quadedgemap[][4] = {{0,1,4,8}, {1,2,5,9}, {2,3,6,10}, {3,0,7,11}};
822
823
824
for(int i=0; i < mesh->getSurfaces(); i++) {
825
surface_t *s = mesh->getSurface(i);
826
827
// loop over edges
828
for(int e=0; e < s->getEdges(); e++) {
829
int n0, n1,nrest[2] = { -1,-1 };
830
if((int)(s->getCode() / 100) == 3) {
831
n0 = s->getNodeIndex(triedgemap[e][0]);
832
n1 = s->getNodeIndex(triedgemap[e][1]);
833
if ( s->getCode() >= 306) nrest[0] = s->getNodeIndex(triedgemap[e][2]);
834
if ( s->getCode() >= 309) nrest[1] = s->getNodeIndex(triedgemap[e][3]);
835
} else if((int)(s->getCode() / 100) == 4) {
836
n0 = s->getNodeIndex(quadedgemap[e][0]);
837
n1 = s->getNodeIndex(quadedgemap[e][1]);
838
// corrected 4.11.2008:
839
if ( s->getCode() >= 408) nrest[0] = s->getNodeIndex(quadedgemap[e][2]);
840
if ( s->getCode() >= 412) nrest[1] = s->getNodeIndex(quadedgemap[e][3]);
841
} else {
842
cout << "findBoundaryElementEdges: error: unknown element code" << endl;
843
exit(0);
844
}
845
846
int m = (n0<n1) ? n0 : n1;
847
int n = (n0<n1) ? n1 : n0;
848
849
h = &hash[m];
850
found = false;
851
while(h->next) {
852
if(h->node[0] == n) {
853
found = true;
854
break;
855
}
856
h = h->next;
857
}
858
859
if(!found) {
860
h->nodes = 1;
861
h->nodes += nrest[0] >=0 ? 1:0;
862
h->nodes += nrest[1] >=0 ? 1:0;
863
h->node = new int[h->nodes];
864
h->node[0] = n;
865
for( int j=1; j<h->nodes; j++ )
866
h->node[j] = nrest[j-1];
867
868
h->surfaces = 1;
869
h->surface = new int[1];
870
h->surface[0] = i;
871
h->parentindex[0] = s->getIndex();
872
h->index = UNKNOWN;
873
h->nature = PDE_UNKNOWN;
874
h->next = new hashEntry;
875
h = h->next;
876
RESETENTRY;
877
} else {
878
int *tmp = new int[h->surfaces];
879
880
found = false;
881
for(int j=0; j<h->surfaces; j++)
882
{
883
tmp[j] = h->surface[j];
884
if ( tmp[j] == i ) found = true;
885
}
886
if ( found ) {
887
delete [] tmp;
888
} else {
889
delete [] h->surface;
890
h->surface = new int[h->surfaces+1];
891
for(int j=0; j<h->surfaces; j++)
892
h->surface[j] = tmp[j];
893
h->surface[h->surfaces++] = i;
894
if( s->getIndex() < h->parentindex[0]) {
895
h->parentindex[1] = h->parentindex[0];
896
h->parentindex[0] = s->getIndex();
897
}
898
else {
899
h->parentindex[1] = s->getIndex();
900
}
901
delete [] tmp;
902
}
903
}
904
}
905
}
906
907
// count edges:
908
int edges = 0;
909
for(int i=0; i<keys; i++) {
910
h = &hash[i];
911
while((h = h->next) != NULL)
912
edges++;
913
}
914
915
916
917
cout << "Found " << edges << " edges on boundary" << endl;
918
919
mesh->setEdges(edges);
920
mesh->newEdgeArray(edges); // edge = new edge_t[edges];
921
922
if(createindexes) {
923
cout << "Creating edge indexes " << endl;
924
925
int maxindex1 = UNKNOWN;
926
int maxindex2 = UNKNOWN;
927
928
for(int i=0; i<keys; i++) {
929
h = &hash[i];
930
while(h->next){
931
if(h->parentindex[0] > maxindex1) maxindex1 = h->parentindex[0];
932
if(h->parentindex[1] > maxindex2) maxindex2 = h->parentindex[1];
933
h = h->next;
934
}
935
}
936
937
// Create a index table such that all combinations of materials
938
// get different BC index
939
//int indextable[maxindex1+2][maxindex2+2];
940
int **indextable = AllocateDynamicArray<int>(maxindex1+2, maxindex2+2);
941
int index1,index2;
942
for(int i=-1;i<=maxindex1;i++)
943
for(int j=-1;j<=maxindex2;j++)
944
indextable[i+1][j+1] = 0;
945
946
int edgebcs=0;
947
for(int i=0; i<keys; i++) {
948
h = &hash[i];
949
while(h->next){
950
if(h->parentindex[0] != h->parentindex[1]) {
951
index1 = h->parentindex[0];
952
index2 = h->parentindex[1];
953
indextable[index1+1][index2+1] = 1;
954
edgebcs += 1;
955
}
956
h = h->next;
957
}
958
}
959
960
index1=0;
961
for(int i=-1;i<=maxindex1;i++)
962
for(int j=-1;j<=maxindex2;j++)
963
if(indextable[i+1][j+1]) indextable[i+1][j+1] = ++index1;
964
965
cout << edgebcs << " boundary edges were numbered up to index " << index1 << endl;
966
967
for(int i=0; i<keys; i++) {
968
h = &hash[i];
969
while(h->next){
970
if(h->parentindex[0] != h->parentindex[1]) {
971
index1 = h->parentindex[0];
972
index2 = h->parentindex[1];
973
h->index = indextable[index1+1][index2+1];
974
h->nature = PDE_BOUNDARY;
975
}
976
h = h->next;
977
}
978
}
979
}
980
981
982
// Create edges:
983
edges = 0;
984
for(int i=0; i<keys; i++) {
985
h = &hash[i];
986
while(h->next) {
987
edge_t *e = mesh->getEdge(edges++);
988
989
e->setNature(h->nature);
990
e->setNodes(h->nodes + 1);
991
e->newNodeIndexes(e->getNodes());
992
e->setNodeIndex(0, i); // ?????
993
for( int j=1; j < e->getNodes(); j++ )
994
e->setNodeIndex(j, h->node[j-1]);
995
996
e->setCode(200 + e->getNodes());
997
998
e->setSurfaces(h->surfaces);
999
e->newSurfaceIndexes(max(e->getSurfaces(), 2));
1000
e->setSurfaceIndex(0, -1);
1001
e->setSurfaceIndex(1, -1);
1002
1003
for(int j=0; j < e->getSurfaces(); j++)
1004
e->setSurfaceIndex(j, h->surface[j]);
1005
1006
e->setSharp(false);
1007
1008
e->setIndex(h->index);
1009
e->setPoints(0);
1010
h = h->next;
1011
}
1012
}
1013
1014
delete [] hash;
1015
1016
// Inverse map
1017
for(int i=0; i < mesh->getEdges(); i++) {
1018
edge_t *e = mesh->getEdge(i);
1019
1020
for(int j=0; j < e->getSurfaces(); j++) {
1021
int k = e->getSurfaceIndex(j);
1022
if ( k< 0 ) continue;
1023
1024
surface_t *s = mesh->getSurface(k);
1025
1026
for(int r=0; r < s->getEdges(); r++) {
1027
if(s->getEdgeIndex(r) < 0) {
1028
s->setEdgeIndex(r, i);
1029
break;
1030
}
1031
}
1032
}
1033
}
1034
1035
#if 0
1036
cout << "*********************" << endl;
1037
for(int i=0; i<mesh->getEdges(); i++)
1038
cout << "Edge " << i << " nodes " << mesh->edge[i].node[0] << " "<< mesh->edge[i].node[0] << endl;
1039
1040
for(int i=0; i < mesh->getSurfaces(); i++)
1041
cout << "Surface " << i << " nodes "
1042
<< mesh->surface[i].node[0] << " "
1043
<< mesh->surface[i].node[1] << " "
1044
<< mesh->surface[i].node[2] << " "
1045
<< " Edges "
1046
<< mesh->surface[i].edge[0] << " "
1047
<< mesh->surface[i].edge[1] << " "
1048
<< mesh->surface[i].edge[2] << " "
1049
<< " Parents "
1050
<< mesh->surface[i].element[0] << " "
1051
<< mesh->surface[i].element[1] << " "
1052
<< endl;
1053
1054
cout.flush();
1055
#endif
1056
1057
}
1058
1059
1060
1061
1062
// Find sharp points for edge elements...
1063
//-----------------------------------------------------------------------------
1064
void Meshutils::findSharpPoints(mesh_t *mesh, double limit)
1065
{
1066
QREAL_OR_FLOAT t0[3], t1[3];
1067
1068
cout << "Limit: " << limit << " degrees" << endl;
1069
cout.flush();
1070
1071
double angle;
1072
int count = 0;
1073
point_t *point = NULL;
1074
edge_t *edge = NULL;
1075
Helpers *helpers = new Helpers;
1076
1077
for(int i=0; i < mesh->getPoints(); i++) {
1078
point = mesh->getPoint(i);
1079
1080
if(point->getEdges() == 2) {
1081
int n = point->getNodeIndex(0);
1082
1083
int e0 = point->getEdgeIndex(0);
1084
int e1 = point->getEdgeIndex(1);
1085
1086
edge = mesh->getEdge(e0);
1087
int n0 = edge->getNodeIndex(0);
1088
if(edge->getNodeIndex(1) != n)
1089
n0 = edge->getNodeIndex(1);
1090
1091
edge = mesh->getEdge(e1);
1092
int n1 = edge->getNodeIndex(0);
1093
if(edge->getNodeIndex(1) != n)
1094
n1 = edge->getNodeIndex(1);
1095
1096
// unit tangent from node to node0
1097
t0[0] = mesh->getNode(n0)->getX(0) - mesh->getNode(n)->getX(0);
1098
t0[1] = mesh->getNode(n0)->getX(1) - mesh->getNode(n)->getX(1);
1099
t0[2] = mesh->getNode(n0)->getX(2) - mesh->getNode(n)->getX(2);
1100
1101
// unit tangent from node to node1
1102
t1[0] = mesh->getNode(n1)->getX(0) - mesh->getNode(n)->getX(0);
1103
t1[1] = mesh->getNode(n1)->getX(1) - mesh->getNode(n)->getX(1);
1104
t1[2] = mesh->getNode(n1)->getX(2) - mesh->getNode(n)->getX(2);
1105
1106
helpers->normalize(t0);
1107
helpers->normalize(t1);
1108
1109
double cosofangle = t0[0]*t1[0] + t0[1]*t1[1] + t0[2]*t1[2];
1110
angle = acos(cosofangle) / MYPI * 180.0;
1111
} else {
1112
angle = 0.0;
1113
}
1114
1115
point->setSharp(false);
1116
if(sqrt(angle*angle) < (180.0-limit) ) {
1117
point->setSharp(true);
1118
count++;
1119
}
1120
}
1121
1122
cout << "Found " << count << " sharp points" << endl;
1123
delete helpers;
1124
}
1125
1126
1127
1128
// Find sharp edges for surface elements...
1129
//-----------------------------------------------------------------------------
1130
void Meshutils::findSharpEdges(mesh_t *mesh, double limit)
1131
{
1132
1133
cout << "Limit: " << limit << " degrees" << endl;
1134
cout.flush();
1135
1136
double angle;
1137
int count = 0;
1138
1139
for(int i=0; i<mesh->getEdges(); i++) {
1140
edge_t *edge = mesh->getEdge(i);
1141
1142
if(edge->getSurfaces() == 2) {
1143
int s0 = edge->getSurfaceIndex(0);
1144
int s1 = edge->getSurfaceIndex(1);
1145
double *n0 = mesh->getSurface(s0)->getNormalVec();
1146
double *n1 = mesh->getSurface(s1)->getNormalVec();
1147
double cosofangle = n0[0]*n1[0] + n0[1]*n1[1] + n0[2]*n1[2];
1148
cosofangle = std::abs(cosofangle);
1149
angle = acos(cosofangle) / MYPI * 180.0;
1150
} else {
1151
angle = 180.0;
1152
}
1153
1154
edge->setSharp(false);
1155
if(sqrt(angle*angle) > limit) {
1156
edge->setSharp(true);
1157
count++;
1158
}
1159
}
1160
1161
cout << "Found " << count << " sharp edges" << endl;
1162
}
1163
1164
1165
1166
// Divide edge by sharp points...
1167
//-----------------------------------------------------------------------------
1168
int Meshutils::divideEdgeBySharpPoints(mesh_t *mesh)
1169
{
1170
class Bc {
1171
public:
1172
void propagateIndex(mesh_t* mesh, int index, int i) {
1173
edge_t *edge = mesh->getEdge(i);
1174
1175
// index is ok
1176
if(!edge->getSelected() || (edge->getIndex() != UNKNOWN)
1177
|| (edge->getNature() != PDE_BOUNDARY)) return;
1178
1179
// set index
1180
edge->setIndex(index);
1181
1182
// propagate index
1183
for(int j=0; j < edge->getPoints(); j++) {
1184
int k = edge->getPointIndex(j);
1185
point_t *point = mesh->getPoint(k);
1186
1187
// skip sharp points
1188
if(!point->isSharp()) {
1189
for(int m = 0; m < point->getEdges(); m++) {
1190
int n = point->getEdgeIndex(m);
1191
propagateIndex(mesh, index, n);
1192
}
1193
}
1194
1195
}
1196
}
1197
};
1198
1199
1200
// reset bc-indices on edges:
1201
int index = 0;
1202
int count = 0;
1203
1204
for(int i=0; i < mesh->getEdges(); i++)
1205
{
1206
edge_t *edge = mesh->getEdge(i);
1207
if((edge->getNature() == PDE_BOUNDARY) && !edge->getSelected())
1208
index = max(index, edge->getIndex());
1209
}
1210
index++;
1211
1212
// int edge_index[index];
1213
int *edge_index = new int[index];
1214
1215
for( int i=0; i<index; i++ )
1216
edge_index[i] = UNKNOWN;
1217
1218
index = 0;
1219
for(int i=0; i < mesh->getEdges(); i++)
1220
{
1221
edge_t *edge = mesh->getEdge(i);
1222
if (edge->getNature() == PDE_BOUNDARY)
1223
{
1224
if ( edge->getSelected() ) {
1225
count++;
1226
edge->setIndex(UNKNOWN);
1227
} else {
1228
if ( edge_index[edge->getIndex()] == UNKNOWN )
1229
edge_index[edge->getIndex()] = ++index;
1230
edge->setIndex(edge_index[edge->getIndex()]);
1231
}
1232
}
1233
}
1234
1235
if ( count==0 ) {
1236
cout << "No boundary edges to divide." << endl;
1237
return 0;
1238
}
1239
1240
Bc *bc = new Bc;
1241
1242
// recursively determine boundary parts:
1243
for(int i=0; i < mesh->getEdges(); i++)
1244
{
1245
edge_t *edge = mesh->getEdge(i);
1246
if(edge->getSelected() && (edge->getIndex() == UNKNOWN) && (edge->getNature() == PDE_BOUNDARY))
1247
bc->propagateIndex(mesh, ++index, i);
1248
}
1249
index++;
1250
1251
// Create a hopefully mesh independent indexing of groupings to enable
1252
// reapplying merge/division operations after remeshing. The indices
1253
// are given based on group bounding box corner distances from a given
1254
// point. Fails if two groups have same bbox, which should not happen
1255
// often though (?)
1256
1257
//double xmin[index], ymin[index], zmin[index];
1258
//double xmax[index], ymax[index], zmax[index];
1259
//double xc = 0, yc = 0, zc = 0, dist[index];
1260
//int cc[index], order[index], sorder[index];
1261
//double g_xmin,g_xmax,g_ymin,g_ymax,g_zmin,g_zmax;
1262
1263
double *xmin = new double[index];
1264
double *ymin = new double[index];
1265
double *zmin = new double[index];
1266
double *xmax = new double[index];
1267
double *ymax = new double[index];
1268
double *zmax = new double[index];
1269
double xc = 0, yc = 0, zc = 0;
1270
double *dist = new double[index];
1271
int *cc = new int[index];
1272
int *order = new int[index];
1273
int *sorder = new int[index];
1274
double g_xmin,g_xmax,g_ymin,g_ymax,g_zmin,g_zmax;
1275
1276
for( int i=0; i<index; i++ )
1277
{
1278
cc[i] = 0;
1279
order[i] = i;
1280
xmin[i] = ymin[i] = zmin[i] = 1e20;
1281
xmax[i] = ymax[i] = zmax[i] = -1e20;
1282
}
1283
1284
for( int i=0; i<mesh->getEdges(); i++ )
1285
{
1286
edge_t *edge = mesh->getEdge(i);
1287
if (edge->getNature() == PDE_BOUNDARY) {
1288
int k = edge->getIndex();
1289
for( int j=0; j < edge->getNodes(); j++ ) {
1290
int n = edge->getNodeIndex(j);
1291
cc[k]++;
1292
xmin[k] = min(xmin[k], mesh->getNode(n)->getX(0));
1293
ymin[k] = min(ymin[k], mesh->getNode(n)->getX(1));
1294
zmin[k] = min(zmin[k], mesh->getNode(n)->getX(2));
1295
1296
xmax[k] = max(xmax[k], mesh->getNode(n)->getX(0));
1297
ymax[k] = max(ymax[k], mesh->getNode(n)->getX(1));
1298
zmax[k] = max(zmax[k], mesh->getNode(n)->getX(2));
1299
}
1300
}
1301
}
1302
1303
g_xmin = g_ymin = g_zmin = 1e20;
1304
g_xmax = g_ymax = g_zmax = -1e20;
1305
for( int i=0; i<index; i++)
1306
{
1307
g_xmin = min(xmin[i],g_xmin);
1308
g_ymin = min(ymin[i],g_ymin);
1309
g_zmin = min(zmin[i],g_zmin);
1310
1311
g_xmax = max(xmax[i],g_xmax);
1312
g_ymax = max(ymax[i],g_ymax);
1313
g_zmax = max(zmax[i],g_zmax);
1314
}
1315
1316
double g_scale = max(max(g_xmax-g_xmin,g_ymax-g_ymin),g_zmax-g_zmin);
1317
double g_xp = g_xmax + 32.1345 * g_scale;
1318
double g_yp = g_ymin - 5.3*MYPI * g_scale;
1319
double g_zp = g_zmax + 8.1234 * g_scale;
1320
1321
for( int i=0; i<index; i++ )
1322
{
1323
dist[i] = 0;
1324
if ( cc[i]>0 ) {
1325
for( int j=0; j<8; j++ ) {
1326
switch(j) {
1327
case 0: xc=xmin[i]; yc=ymin[i]; zc=zmin[i]; break;
1328
case 1: xc=xmax[i]; break;
1329
case 2: yc=xmax[i]; break;
1330
case 3: xc=xmin[i]; break;
1331
case 4: zc=zmax[i]; break;
1332
case 5: yc=ymin[i]; break;
1333
case 6: xc=xmax[i]; break;
1334
case 7: yc=ymax[i]; break;
1335
}
1336
dist[i] += (xc-g_xp)*(xc-g_xp);
1337
dist[i] += (yc-g_yp)*(yc-g_yp);
1338
dist[i] += (zc-g_zp)*(zc-g_zp);
1339
}
1340
}
1341
}
1342
1343
sort_index( index, dist, order );
1344
for( int i=0; i<index; i++ )
1345
sorder[order[i]] = i;
1346
1347
for( int i=0; i<mesh->getEdges(); i++ )
1348
if ( mesh->getEdge(i)->getNature() == PDE_BOUNDARY )
1349
mesh->getEdge(i)->setIndex(sorder[mesh->getEdge(i)->getIndex()]);
1350
1351
--index;
1352
cout << "Edge divided into " << index << " parts" << endl;
1353
1354
delete bc;
1355
1356
return index;
1357
}
1358
1359
1360
void Meshutils::sort_index(int n, double *a, int *b)
1361
{
1362
#if WITH_QT6
1363
vector<QPair<double, int>> list;
1364
1365
for(int i = 0; i < n; i++)
1366
list.push_back(qMakePair(a[i], b[i]));
1367
1368
sort(list.begin(), list.end());
1369
#else
1370
QList<QPair<double, int> > list;
1371
1372
for(int i = 0; i < n; i++)
1373
list << qMakePair(a[i], b[i]);
1374
1375
qSort(list);
1376
#endif
1377
for(int i = 0; i < n; i++) {
1378
a[i] = list[i].first;
1379
b[i] = list[i].second;
1380
}
1381
}
1382
1383
1384
// Divide surface by sharp edges...
1385
//-----------------------------------------------------------------------------
1386
int Meshutils::divideSurfaceBySharpEdges(mesh_t *mesh)
1387
{
1388
class Bc {
1389
public:
1390
void propagateIndex(mesh_t* mesh, int index, int i) {
1391
surface_t *surf = mesh->getSurface(i);
1392
1393
// index is ok
1394
if(!surf->getSelected() || (surf->getIndex() != UNKNOWN)
1395
|| (surf->getNature() != PDE_BOUNDARY) ) return;
1396
1397
// set index
1398
surf->setIndex(index);
1399
1400
// propagate index
1401
for(int j=0; j < surf->getEdges(); j++) {
1402
int k = surf->getEdgeIndex(j);
1403
edge_t *edge = mesh->getEdge(k);
1404
1405
// skip sharp edges
1406
if(!edge->isSharp()) {
1407
for(int m=0; m < edge->getSurfaces(); m++) {
1408
int n = edge->getSurfaceIndex(m);
1409
propagateIndex(mesh, index, n);
1410
}
1411
}
1412
}
1413
}
1414
};
1415
1416
// reset bc-indices:
1417
int count = 0;
1418
int index = 0;
1419
1420
for( int i=0; i<mesh->getSurfaces(); i++ )
1421
{
1422
surface_t *surf = mesh->getSurface(i);
1423
if( (surf->getNature() == PDE_BOUNDARY) && !surf->getSelected() )
1424
index = max(index, surf->getIndex());
1425
}
1426
index++;
1427
1428
// int surf_index[index];
1429
int *surf_index = new int[index];
1430
1431
for( int i=0; i<index; i++ )
1432
surf_index[i] = UNKNOWN;
1433
1434
index = 0;
1435
for(int i=0; i < mesh->getSurfaces(); i++)
1436
{
1437
surface_t *surf = mesh->getSurface(i);
1438
if (surf->getNature() == PDE_BOUNDARY) {
1439
if ( surf->getSelected() ) {
1440
count++;
1441
surf->setIndex(UNKNOWN);
1442
} else {
1443
if ( surf_index[surf->getIndex()] == UNKNOWN )
1444
surf_index[surf->getIndex()] = ++index;
1445
surf->setIndex(surf_index[surf->getIndex()]);
1446
}
1447
}
1448
}
1449
1450
if ( count==0 ) {
1451
cout << "No boundary surfaces to divide." << endl;
1452
return 0;
1453
}
1454
1455
1456
// recursively determine boundary parts:
1457
Bc *bc = new Bc;
1458
1459
for(int i=0; i < mesh->getSurfaces(); i++)
1460
{
1461
surface_t *surf = mesh->getSurface(i);
1462
if(surf->getSelected() && (surf->getIndex() == UNKNOWN) && (surf->getNature() == PDE_BOUNDARY))
1463
bc->propagateIndex(mesh, ++index, i);
1464
}
1465
index++;
1466
1467
// Create a hopefully mesh independent indexing of groupings to enable
1468
// reapplying merge/division operations after remeshing. The indices
1469
// are given based on group bounding box corner distances from a given
1470
// point. Fails if two groups have same bbox, which should not happen
1471
// often though (?)
1472
1473
//double xmin[index], ymin[index], zmin[index];
1474
//double xmax[index], ymax[index], zmax[index];
1475
//double xc = 0, yc = 0, zc = 0, dist[index];
1476
//int cc[index], order[index], sorder[index];
1477
//double g_xmin,g_xmax,g_ymin,g_ymax,g_zmin,g_zmax;
1478
1479
double *xmin = new double[index];
1480
double *ymin = new double[index];
1481
double *zmin = new double[index];
1482
double *xmax = new double[index];
1483
double *ymax = new double[index];
1484
double *zmax = new double[index];
1485
double xc = 0, yc = 0, zc = 0;
1486
double *dist = new double[index];
1487
int *cc = new int[index];
1488
int *order = new int[index];
1489
int *sorder = new int[index];
1490
double g_xmin,g_xmax,g_ymin,g_ymax,g_zmin,g_zmax;
1491
1492
for( int i=0; i<index; i++ )
1493
{
1494
cc[i] = 0;
1495
order[i] = i;
1496
xmin[i] = ymin[i] = zmin[i] = 1e20;
1497
xmax[i] = ymax[i] = zmax[i] = -1e20;
1498
}
1499
1500
for( int i=0; i < mesh->getSurfaces(); i++ )
1501
{
1502
surface_t *surf = mesh->getSurface(i);
1503
if ( mesh->getSurface(i)->getNature() == PDE_BOUNDARY ) {
1504
int k = surf->getIndex();
1505
for( int j=0; j < surf->getNodes(); j++ ) {
1506
int n = surf->getNodeIndex(j);
1507
cc[k]++;
1508
xmin[k] = min( xmin[k], mesh->getNode(n)->getX(0) );
1509
ymin[k] = min( ymin[k], mesh->getNode(n)->getX(1) );
1510
zmin[k] = min( zmin[k], mesh->getNode(n)->getX(2) );
1511
1512
xmax[k] = max( xmax[k], mesh->getNode(n)->getX(0) );
1513
ymax[k] = max( ymax[k], mesh->getNode(n)->getX(1) );
1514
zmax[k] = max( zmax[k], mesh->getNode(n)->getX(2) );
1515
}
1516
}
1517
}
1518
1519
g_xmin = g_ymin = g_zmin = 1e20;
1520
g_xmax = g_ymax = g_zmax = -1e20;
1521
for( int i=0; i<index; i++)
1522
{
1523
g_xmin = min(xmin[i],g_xmin);
1524
g_ymin = min(ymin[i],g_ymin);
1525
g_zmin = min(zmin[i],g_zmin);
1526
1527
g_xmax = max(xmax[i],g_xmax);
1528
g_ymax = max(ymax[i],g_ymax);
1529
g_zmax = max(zmax[i],g_zmax);
1530
}
1531
1532
double g_scale = max(max(g_xmax-g_xmin,g_ymax-g_ymin),g_zmax-g_zmin);
1533
double g_xp = g_xmax + 32.1345 * g_scale;
1534
double g_yp = g_ymin - 5.3*MYPI * g_scale;
1535
double g_zp = g_zmax + 8.1234 * g_scale;
1536
1537
for( int i=0; i<index; i++ )
1538
{
1539
dist[i] = 0;
1540
if ( cc[i]>0 ) {
1541
for( int j=0; j<8; j++ ) {
1542
switch(j) {
1543
case 0: xc=xmin[i]; yc=ymin[i]; zc=zmin[i]; break;
1544
case 1: xc=xmax[i]; break;
1545
case 2: yc=xmax[i]; break;
1546
case 3: xc=xmin[i]; break;
1547
case 4: zc=zmax[i]; break;
1548
case 5: yc=ymin[i]; break;
1549
case 6: xc=xmax[i]; break;
1550
case 7: yc=ymax[i]; break;
1551
}
1552
dist[i] += (xc-g_xp)*(xc-g_xp);
1553
dist[i] += (yc-g_yp)*(yc-g_yp);
1554
dist[i] += (zc-g_zp)*(zc-g_zp);
1555
}
1556
}
1557
}
1558
1559
sort_index( index, dist, order );
1560
for( int i=0; i<index; i++ )
1561
sorder[order[i]] = i;
1562
1563
for( int i=0; i < mesh->getSurfaces(); i++ )
1564
if ( mesh->getSurface(i)->getNature() == PDE_BOUNDARY )
1565
mesh->getSurface(i)->setIndex(sorder[mesh->getSurface(i)->getIndex()]);
1566
--index;
1567
1568
cout << "Surface divided into " << index << " parts" << endl;
1569
1570
delete bc;
1571
1572
return index;
1573
}
1574
1575
1576
1577
// Find surface element normals...
1578
//-----------------------------------------------------------------------------
1579
void Meshutils::findSurfaceElementNormals(mesh_t *mesh)
1580
{
1581
static QREAL_OR_FLOAT a[3], b[3], c[3];
1582
double center_surface[3], center_element[3], center_difference[3];
1583
Helpers *helpers = new Helpers;
1584
int u, v, w, e0, e1, i0, i1, bigger;
1585
1586
for(int i=0; i < mesh->getSurfaces(); i++) {
1587
surface_t *surface = mesh->getSurface(i);
1588
1589
u = surface->getNodeIndex(0);
1590
v = surface->getNodeIndex(1);
1591
1592
if((int)(surface->getCode() / 100) == 3) {
1593
w = surface->getNodeIndex(2);
1594
} else if((int)(surface->getCode() / 100) == 4) {
1595
w = surface->getNodeIndex(3);
1596
} else {
1597
cout << "findBoundaryElementNormals: error: unknown code" << endl;
1598
cout.flush();
1599
exit(0);
1600
}
1601
1602
// Calculate normal (modulo sign):
1603
a[0] = mesh->getNode(v)->getX(0) - mesh->getNode(u)->getX(0);
1604
a[1] = mesh->getNode(v)->getX(1) - mesh->getNode(u)->getX(1);
1605
a[2] = mesh->getNode(v)->getX(2) - mesh->getNode(u)->getX(2);
1606
1607
b[0] = mesh->getNode(w)->getX(0) - mesh->getNode(u)->getX(0);
1608
b[1] = mesh->getNode(w)->getX(1) - mesh->getNode(u)->getX(1);
1609
b[2] = mesh->getNode(w)->getX(2) - mesh->getNode(u)->getX(2);
1610
1611
helpers->crossProduct(a,b,c);
1612
helpers->normalize(c);
1613
1614
surface->setNormal(0, -c[0]);
1615
surface->setNormal(1, -c[1]);
1616
surface->setNormal(2, -c[2]);
1617
1618
// Determine sign:
1619
//----------------
1620
1621
// a) which parent element has bigger index?
1622
1623
e0 = surface->getElementIndex(0);
1624
e1 = surface->getElementIndex(1);
1625
1626
if( (e0<0) && (e1<0) ) {
1627
// both parents unknown
1628
bigger = -1;
1629
} else if(e1<0) {
1630
// e0 known, e1 unknown
1631
bigger = e0;
1632
} else if (e0<0) {
1633
// e0 unknown, e1 known
1634
bigger = e1;
1635
} else {
1636
// both parents known
1637
bigger = e0;
1638
i0 = mesh->getElement(e0)->getIndex();
1639
i1 = mesh->getElement(e1)->getIndex();
1640
if(i1 > i0)
1641
bigger = e1;
1642
}
1643
1644
// b) normal should point to the parent with smaller index:
1645
1646
if(bigger > -1) {
1647
1648
// Compute center point of the surface element:
1649
center_surface[0] = 0.0;
1650
center_surface[1] = 0.0;
1651
center_surface[2] = 0.0;
1652
1653
for(int i=0; i < surface->getNodes(); i++) {
1654
int j = surface->getNodeIndex(i);
1655
node_t *n = mesh->getNode(j);
1656
center_surface[0] += n->getX(0);
1657
center_surface[1] += n->getX(1);
1658
center_surface[2] += n->getX(2);
1659
}
1660
1661
center_surface[0] /= (double)(surface->getNodes());
1662
center_surface[1] /= (double)(surface->getNodes());
1663
center_surface[2] /= (double)(surface->getNodes());
1664
1665
element_t *e = mesh->getElement(bigger);
1666
1667
// compute center point of the parent element:
1668
center_element[0] = 0.0;
1669
center_element[1] = 0.0;
1670
center_element[2] = 0.0;
1671
1672
for(int i=0; i < e->getNodes(); i++) {
1673
int j = e->getNodeIndex(i);
1674
node_t *n = mesh->getNode(j);
1675
center_element[0] += n->getX(0);
1676
center_element[1] += n->getX(1);
1677
center_element[2] += n->getX(2);
1678
}
1679
1680
center_element[0] /= (double)(e->getNodes());
1681
center_element[1] /= (double)(e->getNodes());
1682
center_element[2] /= (double)(e->getNodes());
1683
1684
// difference of the centers:
1685
center_difference[0] = center_element[0] - center_surface[0];
1686
center_difference[1] = center_element[1] - center_surface[1];
1687
center_difference[2] = center_element[2] - center_surface[2];
1688
1689
// dot product must be negative
1690
double dp = center_difference[0]*c[0]
1691
+ center_difference[1]*c[1]
1692
+ center_difference[2]*c[2];
1693
1694
if(dp > 0.0) {
1695
surface->setNormal(0, -surface->getNormal(0));
1696
surface->setNormal(1, -surface->getNormal(1));
1697
surface->setNormal(2, -surface->getNormal(2));
1698
1699
// change orientation of the surface element:
1700
if(surface->getCode() == 303) {
1701
int tmp = surface->getNodeIndex(1);
1702
surface->setNodeIndex(1, surface->getNodeIndex(2));
1703
surface->setNodeIndex(2, tmp);
1704
1705
} else if(surface->getCode() == 404) {
1706
int tmp = surface->getNodeIndex(1);
1707
surface->setNodeIndex(1, surface->getNodeIndex(3));
1708
surface->setNodeIndex(3, tmp);
1709
1710
} else if(surface->getCode() == 306) {
1711
int tmp = surface->getNodeIndex(1);
1712
surface->setNodeIndex(1, surface->getNodeIndex(2));
1713
surface->setNodeIndex(2, tmp);
1714
tmp = surface->getNodeIndex(3);
1715
surface->setNodeIndex(3, surface->getNodeIndex(5));
1716
surface->setNodeIndex(5, tmp);
1717
1718
} else if(surface->getCode() == 408) {
1719
int tmp = surface->getNodeIndex(1);
1720
surface->setNodeIndex(1, surface->getNodeIndex(3));
1721
surface->setNodeIndex(3, tmp);
1722
tmp = surface->getNodeIndex(4);
1723
surface->setNodeIndex(4, surface->getNodeIndex(7));
1724
surface->setNodeIndex(7, tmp);
1725
tmp = surface->getNodeIndex(5);
1726
surface->setNodeIndex(5, surface->getNodeIndex(6));
1727
surface->setNodeIndex(6, tmp);
1728
1729
} else if(surface->getCode() == 409) {
1730
int tmp = surface->getNodeIndex(1);
1731
surface->setNodeIndex(1, surface->getNodeIndex(3));
1732
surface->setNodeIndex(3, tmp);
1733
tmp = surface->getNodeIndex(4);
1734
surface->setNodeIndex(4, surface->getNodeIndex(7));
1735
surface->setNodeIndex(7, tmp);
1736
tmp = surface->getNodeIndex(5);
1737
surface->setNodeIndex(5, surface->getNodeIndex(6));
1738
surface->setNodeIndex(6, tmp);
1739
1740
} else {
1741
cout << "findSurfaceElementNormals: error: unable to change element orientation" << endl;
1742
cout.flush();
1743
exit(0);
1744
}
1745
}
1746
}
1747
}
1748
1749
for( int i=0; i < mesh->getSurfaces(); i++ )
1750
{
1751
surface_t *surface = mesh->getSurface(i);
1752
int n = surface->getCode() / 100;
1753
for(int j=0; j<n; j++ )
1754
{
1755
surface->setVertexNormalVec(j, surface->getNormalVec());
1756
}
1757
}
1758
1759
1760
// List surfaces connected to nodes
1761
//class n_s_t {
1762
//public:
1763
//int index;
1764
//n_s_t *next;
1765
//} n_s[mesh->getNodes()];
1766
1767
class n_s_t {
1768
public:
1769
int index;
1770
n_s_t *next;
1771
};
1772
1773
n_s_t *n_s = new n_s_t[mesh->getNodes()];
1774
1775
for( int i=0; i<mesh->getNodes(); i++ )
1776
{
1777
n_s[i].index = -1;
1778
n_s[i].next = NULL;
1779
}
1780
1781
for( int i=0; i < mesh->getSurfaces(); i++ )
1782
{
1783
surface_t *surface = mesh->getSurface(i);
1784
int n = surface->getCode() / 100;
1785
1786
for( int j=0; j<n; j++ )
1787
{
1788
n_s_t *p = &n_s[surface->getNodeIndex(j)];
1789
if ( p->index >= 0 ) {
1790
n_s_t *q = new n_s_t;
1791
q->next = p->next;
1792
p->next = q;
1793
q->index = i;
1794
} else p->index = i;
1795
}
1796
}
1797
1798
// average normals over surfaces connected to vertices if
1799
// normals within the limit_angle:
1800
double limit_angle = cos(50.*3.14159/180.);
1801
1802
for( int i=0; i < mesh->getSurfaces(); i++ )
1803
{
1804
surface_t *surf1 = mesh->getSurface(i);
1805
int n = surf1->getCode() / 100;
1806
1807
for( int j=0; j<n; j++ )
1808
{
1809
n_s_t *p = &n_s[surf1->getNodeIndex(j)];
1810
for( ; p && p->index>=0; p=p->next )
1811
{
1812
if ( p->index == i ) continue;
1813
1814
surface_t *surf2 = mesh->getSurface(p->index);
1815
double s = 0.;
1816
1817
s += surf1->getNormal(0) * surf2->getNormal(0);
1818
s += surf1->getNormal(1) * surf2->getNormal(1);
1819
s += surf1->getNormal(2) * surf2->getNormal(2);
1820
if ( fabs(s) > limit_angle )
1821
{
1822
if ( s > 0 ) {
1823
surf1->addVertexNormalVec(j, surf2->getNormalVec());
1824
} else {
1825
surf1->subVertexNormalVec(j, surf2->getNormalVec());
1826
}
1827
}
1828
}
1829
}
1830
}
1831
1832
// delete lists:
1833
for( int i=0; i<mesh->getNodes(); i++ )
1834
{
1835
n_s_t *p=&n_s[i], *q;
1836
p = p->next;
1837
while( p )
1838
{
1839
q = p->next;
1840
delete p;
1841
p = q;
1842
}
1843
}
1844
1845
// And finally normalize:
1846
for( int i=0; i < mesh->getSurfaces(); i++ )
1847
{
1848
surface_t *surface = mesh->getSurface(i);
1849
int n = surface->getCode() / 100;
1850
1851
for(int j=0; j<n; j++ )
1852
{
1853
double* v = surface->getVertexNormalVec(j);
1854
double s = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
1855
if ( s != 0 ) {
1856
s = sqrt(s);
1857
v[0] /= s;
1858
v[1] /= s;
1859
v[2] /= s;
1860
}
1861
}
1862
}
1863
1864
1865
delete helpers;
1866
}
1867
1868
1869
1870
// Increase elementorder from 1 to 2
1871
//----------------------------------------------------------------------------
1872
void Meshutils::increaseElementOrder(mesh_t *mesh)
1873
{
1874
class hashEntry {
1875
public:
1876
int node1;
1877
int noedge;
1878
hashEntry *next;
1879
};
1880
1881
if((mesh->getElements() == 0) && (mesh->getSurfaces() == 0)) return;
1882
1883
int keys = mesh->getNodes();
1884
hashEntry *hash = new hashEntry[keys];
1885
hashEntry *h;
1886
1887
for(int i=0; i<keys; i++) {
1888
h = &hash[i];
1889
h->node1 = UNKNOWN;
1890
h->noedge = UNKNOWN;
1891
h->next = NULL;
1892
}
1893
1894
static int familylinnodes[9] = {0, 1, 2, 3, 4, 4, 5, 6, 8};
1895
static int familyedges[9] = {0, 0, 1, 3, 4, 6, 8, 9, 12};
1896
1897
static int edgemap8[][2] = {{0,1}, {1,2}, {2,3}, {3,0}, {0,4}, {1,5}, {2,6}, {3,7}, {4,5}, {5,6}, {6,7}, {7,4}};
1898
static int edgemap7[][2] = {{0,1}, {1,2}, {2,0}, {0,3}, {1,4}, {2,5}, {3,4}, {4,5}, {5,6}};
1899
static int edgemap6[][2] = {{0,1}, {1,2}, {2,3}, {3,0}, {0,4}, {1,4}, {2,4}, {3,4}};
1900
static int edgemap5[][2] = {{0,1}, {1,2}, {2,0}, {0,3}, {1,3}, {2,3}};
1901
static int edgemap4[][2] = {{0,1}, {1,2}, {2,3}, {3,0}};
1902
static int edgemap3[][2] = {{0,1}, {1,2}, {2,0}};
1903
static int edgemap2[][2] = {{0,1}};
1904
1905
1906
// First go through elements and find all new edges introduced by the 2nd order
1907
int noedges = 0;
1908
for(int i=0; i < mesh->getElements() + mesh->getSurfaces(); i++) {
1909
1910
element_t *e;
1911
if(i < mesh->getElements())
1912
e = mesh->getElement(i);
1913
else
1914
e = mesh->getSurface(i - mesh->getElements());
1915
1916
int *edgemap = NULL;
1917
int family = e->getCode() / 100;
1918
int edges = familyedges[family];
1919
1920
// Skip undetermined and nonlinear element
1921
if((e->getNodes() < 2) || (e->getNodes() > familylinnodes[family])) continue;
1922
1923
for(int f=0; f<edges; f++) {
1924
if(family == 3)
1925
edgemap = &edgemap3[f][0];
1926
else if(family == 4)
1927
edgemap = &edgemap4[f][0];
1928
if(family == 5)
1929
edgemap = &edgemap5[f][0];
1930
else if(family == 6)
1931
edgemap = &edgemap6[f][0];
1932
else if(family == 7)
1933
edgemap = &edgemap7[f][0];
1934
else if(family == 8)
1935
edgemap = &edgemap8[f][0];
1936
1937
int n0 = e->getNodeIndex(edgemap[0]);
1938
int n1 = e->getNodeIndex(edgemap[1]);
1939
1940
if(n0 < 0 || n1 < 0) continue;
1941
1942
// Order indexes in an increasing order
1943
if(n0 > n1) {
1944
int tmp = n0;
1945
n0 = n1;
1946
n1 = tmp;
1947
}
1948
1949
h = &hash[n0];
1950
bool found = false;
1951
while(h->next) {
1952
if(h->node1 == n1) {
1953
found = true;
1954
break;
1955
}
1956
h = h->next;
1957
}
1958
1959
if(!found) {
1960
h->node1 = n1;
1961
h->noedge = noedges;
1962
1963
h->next = new hashEntry;
1964
h = h->next;
1965
h->node1 = UNKNOWN;
1966
h->noedge = UNKNOWN;
1967
h->next = NULL;
1968
noedges++;
1969
}
1970
}
1971
}
1972
1973
cout << "Found " << noedges << " edges in the mesh " << endl;
1974
1975
if(noedges == 0) {
1976
return;
1977
delete [] hash;
1978
}
1979
1980
// Then redefine the mesh using the additional nodes
1981
int quadnodes = mesh->getNodes() + noedges;
1982
node_t *quadnode = new node_t[quadnodes];
1983
1984
// Copy linear nodes
1985
for(int i = 0; i < mesh->getNodes(); i++) {
1986
quadnode[i].setX(0, mesh->getNode(i)->getX(0));
1987
quadnode[i].setX(1, mesh->getNode(i)->getX(1));
1988
quadnode[i].setX(2, mesh->getNode(i)->getX(2));
1989
quadnode[i].setIndex(mesh->getNode(i)->getIndex());
1990
}
1991
1992
// Quadratic nodes are taken to be means of the linear nodes
1993
for(int i=0; i<keys; i++) {
1994
int j = 0;
1995
h = &hash[i];
1996
while(h->next){
1997
if(h->noedge > UNKNOWN) {
1998
j++;
1999
int n0 = i;
2000
int n1 = h->node1;
2001
int j = mesh->getNodes() + h->noedge;
2002
quadnode[j].setX(0, 0.5*(quadnode[n0].getX(0) + quadnode[n1].getX(0)));
2003
quadnode[j].setX(1, 0.5*(quadnode[n0].getX(1) + quadnode[n1].getX(1)));
2004
quadnode[j].setX(2, 0.5*(quadnode[n0].getX(2) + quadnode[n1].getX(2)));
2005
quadnode[j].setIndex(UNKNOWN);
2006
}
2007
h = h->next;
2008
}
2009
}
2010
mesh->deleteNodeArray();
2011
mesh->setNodeArray(quadnode);
2012
2013
cout << "Set " << quadnodes << " additional nodes" << endl;
2014
2015
2016
int tmpnode[27];
2017
2018
for(int i=0; i < mesh->getElements() + mesh->getSurfaces() + mesh->getEdges(); i++) {
2019
2020
element_t *e;
2021
if(i < mesh->getElements())
2022
e = mesh->getElement(i);
2023
else if (i < mesh->getElements() + mesh->getSurfaces())
2024
e = mesh->getSurface(i - mesh->getElements());
2025
else
2026
e = mesh->getEdge(i - mesh->getElements() - mesh->getSurfaces());
2027
2028
int *edgemap = NULL;
2029
int family = e->getCode() / 100;
2030
int edges = familyedges[family];
2031
2032
/* Not a linear element */
2033
if((e->getNodes() < 2) || (e->getNodes() > familylinnodes[family])) continue;
2034
2035
int linnodes = e->getNodes();
2036
for(int j=0;j<linnodes;j++)
2037
tmpnode[j] = e->getNodeIndex(j);
2038
2039
e->deleteNodeIndexes();
2040
e->setCode(e->getCode() + edges);
2041
e->setNodes(e->getNodes() + edges);
2042
e->newNodeIndexes(e->getNodes());
2043
for(int j=0;j<linnodes;j++)
2044
e->setNodeIndex(j, tmpnode[j]);
2045
2046
2047
for(int f=0; f<edges; f++) {
2048
2049
if(family == 2)
2050
edgemap = &edgemap2[f][0];
2051
if(family == 3)
2052
edgemap = &edgemap3[f][0];
2053
else if(family == 4)
2054
edgemap = &edgemap4[f][0];
2055
if(family == 5)
2056
edgemap = &edgemap5[f][0];
2057
else if(family == 6)
2058
edgemap = &edgemap6[f][0];
2059
else if(family == 7)
2060
edgemap = &edgemap7[f][0];
2061
else if(family == 8)
2062
edgemap = &edgemap8[f][0];
2063
2064
int n0 = e->getNodeIndex(edgemap[0]);
2065
int n1 = e->getNodeIndex(edgemap[1]);
2066
if((n0 < 0) || (n1 < 0)) continue;
2067
2068
// Order indexes in an increasing order
2069
if(n0 > n1) {
2070
int tmp = n0;
2071
n0 = n1;
2072
n1 = tmp;
2073
}
2074
2075
h = &hash[n0];
2076
bool found = false;
2077
while(h->next) {
2078
if(h->node1 == n1) {
2079
found = true;
2080
e->setNodeIndex(linnodes+f, h->noedge + mesh->getNodes());
2081
break;
2082
}
2083
h = h->next;
2084
}
2085
if(!found) {
2086
cout << "All edges should be found!? " << endl;
2087
}
2088
}
2089
}
2090
mesh->setNodes(quadnodes);
2091
2092
delete [] hash;
2093
}
2094
2095
2096
2097
// Decrease elementorder from >1 to 1
2098
//----------------------------------------------------------------------------
2099
void Meshutils::decreaseElementOrder(mesh_t *mesh)
2100
{
2101
if((mesh->getElements() == 0) && (mesh->getSurfaces() == 0)) return;
2102
2103
static int familylinnodes[9] = {0, 1, 2, 3, 4, 4, 5, 6, 8};
2104
2105
int *activenodes = new int[mesh->getNodes()];
2106
for(int i=0; i < mesh->getNodes(); i++)
2107
activenodes[i] = -1;
2108
2109
// int noedges = 0;
2110
for(int i=0; i < mesh->getElements() + mesh->getSurfaces(); i++) {
2111
2112
element_t *e;
2113
if(i < mesh->getElements())
2114
e = mesh->getElement(i);
2115
else
2116
e = mesh->getSurface(i - mesh->getElements());
2117
2118
int family = e->getCode() / 100;
2119
int linnodes = familylinnodes[family];
2120
2121
for(int j=0;j<linnodes;j++)
2122
activenodes[e->getNodeIndex(j)] = 0;
2123
}
2124
2125
int linnodes = 0;
2126
for(int i=0; i < mesh->getNodes(); i++)
2127
if(activenodes[i] > -1) activenodes[i] = linnodes++;
2128
2129
cout << "Setting " << linnodes << " linear nodes of the total " << mesh->getNodes() << " nodes" << endl;
2130
if(linnodes == mesh->getNodes()) return;
2131
2132
2133
// Copy linear nodes
2134
node_t *linnode = new node_t[linnodes];
2135
for(int i=0; i < mesh->getNodes(); i++) {
2136
int j = activenodes[i];
2137
if(j > -1) {
2138
linnode[j].setX(0, mesh->getNode(i)->getX(0));
2139
linnode[j].setX(1, mesh->getNode(i)->getX(1));
2140
linnode[j].setX(2, mesh->getNode(i)->getX(2));
2141
}
2142
}
2143
mesh->deleteNodeArray();
2144
mesh->setNodeArray(linnode);
2145
mesh->setNodes(linnodes);
2146
2147
int tmpnode[8];
2148
2149
for(int i=0; i < mesh->getElements() + mesh->getSurfaces() + mesh->getEdges(); i++) {
2150
2151
element_t *e;
2152
if(i < mesh->getElements())
2153
e = mesh->getElement(i);
2154
else if (i < mesh->getElements() + mesh->getSurfaces())
2155
e = mesh->getSurface(i - mesh->getElements());
2156
else
2157
e = mesh->getEdge(i - mesh->getElements() - mesh->getSurfaces());
2158
2159
int family = e->getCode() / 100;
2160
int linnodes = familylinnodes[family];
2161
2162
for(int j=0;j<linnodes;j++)
2163
tmpnode[j] = e->getNodeIndex(j);
2164
2165
e->deleteNodeIndexes();
2166
e->setCode(100*family + linnodes);
2167
e->setNodes(linnodes);
2168
e->newNodeIndexes(e->getNodes());
2169
2170
for(int j=0;j<linnodes;j++)
2171
e->setNodeIndex(j, activenodes[tmpnode[j]]);
2172
}
2173
}
2174
2175
// Clean up hanging sharp edges (for visualization)...
2176
//----------------------------------------------------------------------------
2177
int Meshutils::cleanHangingSharpEdges(mesh_t *mesh)
2178
{
2179
int count_total = 0;
2180
int count_removed = 0;
2181
2182
if(mesh->getEdges() == 0)
2183
return 0;
2184
2185
for(int i = 0; i < mesh->getEdges(); i++) {
2186
edge_t *edge = mesh->getEdge(i);
2187
if(edge->isSharp()) {
2188
count_total++;
2189
if(edge->getSurfaces() == 2) {
2190
// has two parents
2191
int i0 = edge->getSurfaceIndex(0);
2192
int i1 = edge->getSurfaceIndex(1);
2193
surface_t *s0 = NULL;
2194
surface_t *s1 = NULL;
2195
if(i0 >= 0)
2196
s0 = mesh->getSurface(i0);
2197
if(i1 >= 0)
2198
s1 = mesh->getSurface(i1);
2199
if((s0 != NULL) && (s1 != NULL)) {
2200
int index0 = s0->getIndex();
2201
int index1 = s1->getIndex();
2202
if(index0 == index1) {
2203
// remove
2204
count_removed++;
2205
edge->setSharp(false);
2206
}
2207
}
2208
}
2209
}
2210
}
2211
2212
return count_removed;
2213
}
2214
2215