Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/improve2gen.cpp
3206 views
1
#include <mystdlib.h>
2
3
#include "meshing.hpp"
4
#include <opti.hpp>
5
6
namespace netgen
7
{
8
9
class ImprovementRule
10
{
11
public:
12
ARRAY<Element2d> oldels;
13
ARRAY<Element2d> newels;
14
ARRAY<INDEX_2> deledges;
15
ARRAY<int> incelsonnode;
16
ARRAY<int> reused;
17
int bonus;
18
int onp;
19
};
20
21
22
void MeshOptimize2d :: GenericImprove (Mesh & mesh)
23
{
24
if (!faceindex)
25
{
26
if (writestatus)
27
PrintMessage (3, "Generic Improve");
28
29
for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++)
30
GenericImprove (mesh);
31
32
faceindex = 0;
33
}
34
35
// int j, k, l, ri;
36
int np = mesh.GetNP();
37
int ne = mesh.GetNSE();
38
// SurfaceElementIndex sei;
39
40
41
// for (SurfaceElementIndex sei = 0; sei < ne; sei++)
42
// {
43
// const Element2d & el = mesh[sei];
44
// (*testout) << "element " << sei << ": " <<flush;
45
// for(int j=0; j<el.GetNP(); j++)
46
// (*testout) << el[j] << " " << flush;
47
// (*testout) << "IsDeleted() " << el.IsDeleted()<< endl;
48
// }
49
50
bool ok;
51
int olddef, newdef;
52
53
ARRAY<ImprovementRule*> rules;
54
ARRAY<SurfaceElementIndex> elmap;
55
ARRAY<int> elrot;
56
ARRAY<PointIndex> pmap;
57
ARRAY<PointGeomInfo> pgi;
58
59
int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();
60
61
ImprovementRule * r1;
62
63
// 2 triangles to quad
64
r1 = new ImprovementRule;
65
r1->oldels.Append (Element2d (1, 2, 3));
66
r1->oldels.Append (Element2d (3, 2, 4));
67
r1->newels.Append (Element2d (1, 2, 4, 3));
68
r1->deledges.Append (INDEX_2 (2,3));
69
r1->onp = 4;
70
r1->bonus = 2;
71
rules.Append (r1);
72
73
// 2 quad to 1 quad
74
r1 = new ImprovementRule;
75
r1->oldels.Append (Element2d (1, 2, 3, 4));
76
r1->oldels.Append (Element2d (4, 3, 2, 5));
77
r1->newels.Append (Element2d (1, 2, 5, 4));
78
r1->deledges.Append (INDEX_2 (2, 3));
79
r1->deledges.Append (INDEX_2 (3, 4));
80
r1->onp = 5;
81
r1->bonus = 0;
82
rules.Append (r1);
83
84
// swap quads
85
r1 = new ImprovementRule;
86
r1->oldels.Append (Element2d (1, 2, 3, 4));
87
r1->oldels.Append (Element2d (3, 2, 5, 6));
88
r1->newels.Append (Element2d (1, 6, 3, 4));
89
r1->newels.Append (Element2d (1, 2, 5, 6));
90
r1->deledges.Append (INDEX_2 (2, 3));
91
r1->onp = 6;
92
r1->bonus = 0;
93
rules.Append (r1);
94
95
// three quads to 2
96
r1 = new ImprovementRule;
97
r1->oldels.Append (Element2d (1, 2, 3, 4));
98
r1->oldels.Append (Element2d (2, 5, 6, 3));
99
r1->oldels.Append (Element2d (3, 6, 7, 4));
100
r1->newels.Append (Element2d (1, 2, 5, 4));
101
r1->newels.Append (Element2d (4, 5, 6, 7));
102
r1->deledges.Append (INDEX_2 (2, 3));
103
r1->deledges.Append (INDEX_2 (3, 4));
104
r1->deledges.Append (INDEX_2 (3, 6));
105
r1->onp = 7;
106
r1->bonus = -1;
107
rules.Append (r1);
108
109
// quad + 2 connected trigs to quad
110
r1 = new ImprovementRule;
111
r1->oldels.Append (Element2d (1, 2, 3, 4));
112
r1->oldels.Append (Element2d (2, 5, 3));
113
r1->oldels.Append (Element2d (3, 5, 4));
114
r1->newels.Append (Element2d (1, 2, 5, 4));
115
r1->deledges.Append (INDEX_2 (2, 3));
116
r1->deledges.Append (INDEX_2 (3, 4));
117
r1->deledges.Append (INDEX_2 (3, 5));
118
r1->onp = 5;
119
r1->bonus = 0;
120
rules.Append (r1);
121
122
// quad + 2 non-connected trigs to quad (a and b)
123
r1 = new ImprovementRule;
124
r1->oldels.Append (Element2d (1, 2, 3, 4));
125
r1->oldels.Append (Element2d (2, 6, 3));
126
r1->oldels.Append (Element2d (1, 4, 5));
127
r1->newels.Append (Element2d (1, 3, 4, 5));
128
r1->newels.Append (Element2d (1, 2, 6, 3));
129
r1->deledges.Append (INDEX_2 (1, 4));
130
r1->deledges.Append (INDEX_2 (2, 3));
131
r1->onp = 6;
132
r1->bonus = 0;
133
rules.Append (r1);
134
135
r1 = new ImprovementRule;
136
r1->oldels.Append (Element2d (1, 2, 3, 4));
137
r1->oldels.Append (Element2d (2, 6, 3));
138
r1->oldels.Append (Element2d (1, 4, 5));
139
r1->newels.Append (Element2d (1, 2, 4, 5));
140
r1->newels.Append (Element2d (4, 2, 6, 3));
141
r1->deledges.Append (INDEX_2 (1, 4));
142
r1->deledges.Append (INDEX_2 (2, 3));
143
r1->onp = 6;
144
r1->bonus = 0;
145
rules.Append (r1);
146
147
// two quad + trig -> one quad + trig
148
r1 = new ImprovementRule;
149
r1->oldels.Append (Element2d (1, 2, 3, 4));
150
r1->oldels.Append (Element2d (2, 5, 6, 3));
151
r1->oldels.Append (Element2d (4, 3, 6));
152
r1->newels.Append (Element2d (1, 2, 6, 4));
153
r1->newels.Append (Element2d (2, 5, 6));
154
r1->deledges.Append (INDEX_2 (2, 3));
155
r1->deledges.Append (INDEX_2 (3, 4));
156
r1->deledges.Append (INDEX_2 (3, 6));
157
r1->onp = 6;
158
r1->bonus = -1;
159
rules.Append (r1);
160
161
// swap quad + trig (a and b)
162
r1 = new ImprovementRule;
163
r1->oldels.Append (Element2d (1, 2, 3, 4));
164
r1->oldels.Append (Element2d (2, 5, 3));
165
r1->newels.Append (Element2d (2, 5, 3, 4));
166
r1->newels.Append (Element2d (1, 2, 4));
167
r1->deledges.Append (INDEX_2 (2, 3));
168
r1->onp = 5;
169
r1->bonus = 0;
170
rules.Append (r1);
171
172
r1 = new ImprovementRule;
173
r1->oldels.Append (Element2d (1, 2, 3, 4));
174
r1->oldels.Append (Element2d (2, 5, 3));
175
r1->newels.Append (Element2d (1, 2, 5, 3));
176
r1->newels.Append (Element2d (1, 3, 4));
177
r1->deledges.Append (INDEX_2 (2, 3));
178
r1->onp = 5;
179
r1->bonus = 0;
180
rules.Append (r1);
181
182
183
// 2 quads to quad + 2 trigs
184
r1 = new ImprovementRule;
185
r1->oldels.Append (Element2d (1, 2, 3, 4));
186
r1->oldels.Append (Element2d (3, 2, 5, 6));
187
r1->newels.Append (Element2d (1, 5, 6, 4));
188
r1->newels.Append (Element2d (1, 2, 5));
189
r1->newels.Append (Element2d (4, 6, 3));
190
r1->deledges.Append (INDEX_2 (2, 3));
191
r1->onp = 6;
192
r1->bonus = 0;
193
// rules.Append (r1);
194
195
196
197
198
ARRAY<int> mapped(rules.Size());
199
ARRAY<int> used(rules.Size());
200
used = 0;
201
mapped = 0;
202
203
204
205
for (int ri = 0; ri < rules.Size(); ri++)
206
{
207
ImprovementRule & rule = *rules[ri];
208
rule.incelsonnode.SetSize (rule.onp);
209
rule.reused.SetSize (rule.onp);
210
211
for (int j = 1; j <= rule.onp; j++)
212
{
213
rule.incelsonnode.Elem(j) = 0;
214
rule.reused.Elem(j) = 0;
215
}
216
217
for (int j = 1; j <= rule.oldels.Size(); j++)
218
{
219
const Element2d & el = rule.oldels.Elem(j);
220
for (int k = 1; k <= el.GetNP(); k++)
221
rule.incelsonnode.Elem(el.PNum(k))--;
222
}
223
224
for (int j = 1; j <= rule.newels.Size(); j++)
225
{
226
const Element2d & el = rule.newels.Elem(j);
227
for (int k = 1; k <= el.GetNP(); k++)
228
{
229
rule.incelsonnode.Elem(el.PNum(k))++;
230
rule.reused.Elem(el.PNum(k)) = 1;
231
}
232
}
233
}
234
235
236
237
238
TABLE<int,PointIndex::BASE> elonnode(np);
239
ARRAY<int,PointIndex::BASE> nelonnode(np);
240
TABLE<SurfaceElementIndex> nbels(ne);
241
242
nelonnode = -4;
243
244
for (SurfaceElementIndex sei = 0; sei < ne; sei++)
245
{
246
const Element2d & el = mesh[sei];
247
248
if (el.GetIndex() == faceindex && !el.IsDeleted())
249
{
250
for (int j = 0; j < el.GetNP(); j++)
251
elonnode.Add (el[j], sei);
252
}
253
if(!el.IsDeleted())
254
{
255
for (int j = 0; j < el.GetNP(); j++)
256
nelonnode[el[j]]++;
257
}
258
}
259
260
for (SurfaceElementIndex sei = 0; sei < ne; sei++)
261
{
262
const Element2d & el = mesh[sei];
263
if (el.GetIndex() == faceindex && !el.IsDeleted())
264
{
265
for (int j = 0; j < el.GetNP(); j++)
266
{
267
for (int k = 0; k < elonnode[el[j]].Size(); k++)
268
{
269
int nbel = elonnode[el[j]] [k];
270
bool inuse = false;
271
for (int l = 0; l < nbels[sei].Size(); l++)
272
if (nbels[sei][l] == nbel)
273
inuse = true;
274
if (!inuse)
275
nbels.Add (sei, nbel);
276
}
277
}
278
}
279
}
280
281
282
for (int ri = 0; ri < rules.Size(); ri++)
283
{
284
const ImprovementRule & rule = *rules[ri];
285
286
elmap.SetSize (rule.oldels.Size());
287
elrot.SetSize (rule.oldels.Size());
288
pmap.SetSize (rule.onp);
289
pgi.SetSize (rule.onp);
290
291
292
for (SurfaceElementIndex sei = 0; sei < ne; sei++)
293
{
294
if (multithread.terminate)
295
break;
296
if (mesh[sei].IsDeleted()) continue;
297
298
elmap[0] = sei;
299
FlatArray<SurfaceElementIndex> neighbours = nbels[sei];
300
301
for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++)
302
{
303
const Element2d & el0 = mesh[sei];
304
const Element2d & rel0 = rule.oldels[0];
305
306
if (el0.GetIndex() != faceindex) continue;
307
if (el0.IsDeleted()) continue;
308
if (el0.GetNP() != rel0.GetNP()) continue;
309
310
311
pmap = -1;
312
313
for (int k = 0; k < el0.GetNP(); k++)
314
{
315
pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1);
316
pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1);
317
}
318
319
ok = 1;
320
for (int i = 1; i < elmap.Size(); i++)
321
{
322
// try to find a mapping for reference-element i
323
324
const Element2d & rel = rule.oldels[i];
325
bool possible = 0;
326
327
for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++)
328
{
329
const Element2d & el = mesh[neighbours[elmap[i]]];
330
if (el.IsDeleted()) continue;
331
if (el.GetNP() != rel.GetNP()) continue;
332
333
for (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++)
334
{
335
possible = 1;
336
337
for (int k = 0; k < rel.GetNP(); k++)
338
if (pmap.Elem(rel[k]) != -1 &&
339
pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1))
340
possible = 0;
341
342
if (possible)
343
{
344
for (int k = 0; k < el.GetNP(); k++)
345
{
346
pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1);
347
pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1);
348
}
349
break;
350
}
351
}
352
if (possible) break;
353
}
354
355
if (!possible)
356
{
357
ok = 0;
358
break;
359
}
360
361
elmap[i] = neighbours[elmap[i]];
362
}
363
364
for(int i=0; ok && i<rule.deledges.Size(); i++)
365
{
366
ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()),
367
pmap.Elem(rule.deledges[i].I2()));
368
}
369
370
371
372
373
if (!ok) continue;
374
375
mapped[ri]++;
376
377
olddef = 0;
378
for (int j = 1; j <= pmap.Size(); j++)
379
olddef += sqr (nelonnode[pmap.Get(j)]);
380
olddef += rule.bonus;
381
382
newdef = 0;
383
for (int j = 1; j <= pmap.Size(); j++)
384
if (rule.reused.Get(j))
385
newdef += sqr (nelonnode[pmap.Get(j)] +
386
rule.incelsonnode.Get(j));
387
388
if (newdef > olddef)
389
continue;
390
391
// calc metric badness
392
double bad1 = 0, bad2 = 0;
393
Vec<3> n;
394
395
SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1));
396
GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n);
397
398
for (int j = 1; j <= rule.oldels.Size(); j++)
399
bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n);
400
401
// check new element:
402
for (int j = 1; j <= rule.newels.Size(); j++)
403
{
404
const Element2d & rnel = rule.newels.Get(j);
405
Element2d nel(rnel.GetNP());
406
for (int k = 1; k <= rnel.GetNP(); k++)
407
nel.PNum(k) = pmap.Get(rnel.PNum(k));
408
409
bad2 += nel.CalcJacobianBadness (mesh.Points(), n);
410
}
411
412
if (bad2 > 1e3) continue;
413
414
if (newdef == olddef && bad2 > bad1) continue;
415
416
417
// generate new element:
418
for (int j = 1; j <= rule.newels.Size(); j++)
419
{
420
const Element2d & rnel = rule.newels.Get(j);
421
Element2d nel(rnel.GetNP());
422
nel.SetIndex (faceindex);
423
for (int k = 1; k <= rnel.GetNP(); k++)
424
{
425
nel.PNum(k) = pmap.Get(rnel.PNum(k));
426
nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k));
427
}
428
429
mesh.AddSurfaceElement(nel);
430
}
431
432
for (int j = 0; j < rule.oldels.Size(); j++)
433
mesh.DeleteSurfaceElement ( elmap[j] );
434
435
for (int j = 1; j <= pmap.Size(); j++)
436
nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j);
437
438
used[ri]++;
439
}
440
}
441
}
442
443
mesh.Compress();
444
445
for (int ri = 0; ri < rules.Size(); ri++)
446
{
447
PrintMessage (5, "rule ", ri+1, " ",
448
mapped[ri], "/", used[ri], " mapped/used");
449
}
450
}
451
452
453
454
455
}
456
457