Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/curvedelems_new.cpp
3206 views
1
#include <mystdlib.h>
2
3
#include "meshing.hpp"
4
#ifdef CURVEDELEMS_NEW
5
6
#include "../general/autodiff.hpp"
7
8
9
namespace netgen
10
{
11
12
// bool rational = true;
13
14
15
16
static void ComputeGaussRule (int n, ARRAY<double> & xi, ARRAY<double> & wi)
17
{
18
xi.SetSize (n);
19
wi.SetSize (n);
20
21
int m = (n+1)/2;
22
double p1, p2, p3;
23
double pp, z, z1;
24
for (int i = 1; i <= m; i++)
25
{
26
z = cos ( M_PI * (i - 0.25) / (n + 0.5));
27
while(1)
28
{
29
p1 = 1; p2 = 0;
30
for (int j = 1; j <= n; j++)
31
{
32
p3 = p2; p2 = p1;
33
p1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j;
34
}
35
// p1 is legendre polynomial
36
37
pp = n * (z*p1-p2) / (z*z - 1);
38
z1 = z;
39
z = z1-p1/pp;
40
41
if (fabs (z - z1) < 1e-14) break;
42
}
43
44
xi[i-1] = 0.5 * (1 - z);
45
xi[n-i] = 0.5 * (1 + z);
46
wi[i-1] = wi[n-i] = 1.0 / ( (1 - z * z) * pp * pp);
47
}
48
}
49
50
51
52
// compute edge bubbles up to order n, x \in (-1, 1)
53
static void CalcEdgeShape (int n, double x, double * shape)
54
{
55
double p1 = x, p2 = -1, p3 = 0;
56
for (int j=2; j<=n; j++)
57
{
58
p3=p2; p2=p1;
59
p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;
60
shape[j-2] = p1;
61
}
62
}
63
64
static void CalcEdgeDx (int n, double x, double * dshape)
65
{
66
double p1 = x, p2 = -1, p3 = 0;
67
double p1dx = 1, p2dx = 0, p3dx = 0;
68
69
for (int j=2; j<=n; j++)
70
{
71
p3=p2; p2=p1;
72
p3dx = p2dx; p2dx = p1dx;
73
74
p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;
75
p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j;
76
77
dshape[j-2] = p1dx;
78
}
79
}
80
81
static void CalcEdgeShapeDx (int n, double x, double * shape, double * dshape)
82
{
83
double p1 = x, p2 = -1, p3 = 0;
84
double p1dx = 1, p2dx = 0, p3dx = 0;
85
86
for (int j=2; j<=n; j++)
87
{
88
p3=p2; p2=p1;
89
p3dx = p2dx; p2dx = p1dx;
90
91
p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;
92
p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j;
93
94
shape[j-2] = p1;
95
dshape[j-2] = p1dx;
96
}
97
}
98
99
// compute L_i(x/t) * t^i
100
static void CalcScaledEdgeShape (int n, double x, double t, double * shape)
101
{
102
double p1 = x, p2 = -1, p3 = 0;
103
for (int j=0; j<=n-2; j++)
104
{
105
p3=p2; p2=p1;
106
p1=( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2);
107
shape[j] = p1;
108
}
109
}
110
111
template <int DIST>
112
static void CalcScaledEdgeShapeDxDt (int n, double x, double t, double * dshape)
113
{
114
double p1 = x, p2 = -1, p3 = 0;
115
double p1dx = 1, p1dt = 0;
116
double p2dx = 0, p2dt = 0;
117
double p3dx = 0, p3dt = 0;
118
119
for (int j=0; j<=n-2; j++)
120
{
121
p3=p2; p3dx=p2dx; p3dt = p2dt;
122
p2=p1; p2dx=p1dx; p2dt = p1dt;
123
124
p1 = ( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2);
125
p1dx = ( (2*j+1) * (x * p2dx + p2) - t*t*(j-1) * p3dx) / (j+2);
126
p1dt = ( (2*j+1) * x * p2dt - (j-1)* (t*t*p3dt+2*t*p3)) / (j+2);
127
128
// shape[j] = p1;
129
dshape[DIST*j ] = p1dx;
130
dshape[DIST*j+1] = p1dt;
131
}
132
}
133
134
135
template <class Tx, class Tres>
136
static void LegendrePolynomial (int n, Tx x, Tres * values)
137
{
138
switch (n)
139
{
140
case 0:
141
values[0] = 1;
142
break;
143
case 1:
144
values[0] = 1;
145
values[1] = x;
146
break;
147
148
default:
149
150
if (n < 0) return;
151
152
Tx p1 = 1.0, p2 = 0.0, p3;
153
154
values[0] = 1.0;
155
for (int j=1; j<=n; j++)
156
{
157
p3 = p2; p2 = p1;
158
p1 = ((2.0*j-1.0)*x*p2 - (j-1.0)*p3) / j;
159
values[j] = p1;
160
}
161
}
162
}
163
164
template <class Tx, class Tt, class Tres>
165
static void ScaledLegendrePolynomial (int n, Tx x, Tt t, Tres * values)
166
{
167
switch (n)
168
{
169
case 0:
170
values[0] = 1.0;
171
break;
172
173
case 1:
174
values[0] = 1.0;
175
values[1] = x;
176
break;
177
178
default:
179
180
if (n < 0) return;
181
182
Tx p1 = 1.0, p2 = 0.0, p3;
183
values[0] = 1.0;
184
for (int j=1; j<=n; j++)
185
{
186
p3 = p2; p2 = p1;
187
p1 = ((2.0*j-1.0)*x*p2 - t*t*(j-1.0)*p3) / j;
188
values[j] = p1;
189
}
190
}
191
}
192
193
194
195
template <class S, class T>
196
inline void JacobiPolynomial (int n, S x, double alpha, double beta, T * values)
197
{
198
S p1 = 1.0, p2 = 0.0, p3;
199
200
if (n >= 0)
201
p2 = values[0] = 1.0;
202
if (n >= 1)
203
p1 = values[1] = 0.5 * (2*(alpha+1)+(alpha+beta+2)*(x-1));
204
205
for (int i = 1; i < n; i++)
206
{
207
p3 = p2; p2=p1;
208
p1 =
209
1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *
210
(
211
( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) +
212
(2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)
213
* p2
214
- 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * p3
215
);
216
values[i+1] = p1;
217
}
218
}
219
220
221
222
223
template <class S, class St, class T>
224
inline void ScaledJacobiPolynomial (int n, S x, St t, double alpha, double beta, T * values)
225
{
226
/*
227
S p1 = 1.0, p2 = 0.0, p3;
228
229
if (n >= 0) values[0] = 1.0;
230
*/
231
232
S p1 = 1.0, p2 = 0.0, p3;
233
234
if (n >= 0)
235
p2 = values[0] = 1.0;
236
if (n >= 1)
237
p1 = values[1] = 0.5 * (2*(alpha+1)*t+(alpha+beta+2)*(x-t));
238
239
for (int i=1; i < n; i++)
240
{
241
p3 = p2; p2=p1;
242
p1 =
243
1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *
244
(
245
( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) * t +
246
(2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)
247
* p2
248
- 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * t * t * p3
249
);
250
values[i+1] = p1;
251
}
252
}
253
254
255
256
257
258
// compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1
259
template <class Tx, class Ty, class Ts>
260
static void CalcTrigShape (int n, Tx x, Ty y, Ts * shape)
261
{
262
if (n < 3) return;
263
Tx hx[50], hy[50*50];
264
// ScaledLegendrePolynomial (n-3, 2*x-1, 1-y, hx);
265
ScaledJacobiPolynomial (n-3, x, 1-y, 2, 2, hx);
266
267
268
// LegendrePolynomial (n-3, 2*y-1, hy);
269
for (int ix = 0; ix <= n-3; ix++)
270
// JacobiPolynomial (n-3, 2*y-1, 0, 0, hy+50*ix);
271
JacobiPolynomial (n-3, 2*y-1, 2*ix+5, 2, hy+50*ix);
272
273
int ii = 0;
274
Tx bub = (1+x-y)*y*(1-x-y);
275
for (int iy = 0; iy <= n-3; iy++)
276
for (int ix = 0; ix <= n-3-iy; ix++)
277
shape[ii++] = bub * hx[ix]*hy[iy+50*ix];
278
}
279
280
281
282
static void CalcTrigShapeDxDy (int n, double x, double y, double * dshape)
283
{
284
if (n < 3) return;
285
286
AutoDiff<2> adx(x, 0);
287
AutoDiff<2> ady(y, 1);
288
AutoDiff<2> res[2000];
289
CalcTrigShape (n, adx, ady, &res[0]);
290
int ndof = (n-1)*(n-2)/2;
291
for (int i = 0; i < ndof; i++)
292
{
293
dshape[2*i] = res[i].DValue(0);
294
dshape[2*i+1] = res[i].DValue(1);
295
}
296
297
/*
298
if (n < 3) return;
299
300
int ndof = (n-1)*(n-2)/2;
301
double h1[1000], h2[1000];
302
double eps = 1e-4;
303
304
CalcTrigShape (n, x+eps, y, h1);
305
CalcTrigShape (n, x-eps, y, h2);
306
307
for (int i = 0; i < ndof; i++)
308
dshape[2*i] = (h1[i]-h2[i])/(2*eps);
309
310
CalcTrigShape (n, x, y+eps, h1);
311
CalcTrigShape (n, x, y-eps, h2);
312
313
for (int i = 0; i < ndof; i++)
314
dshape[2*i+1] = (h1[i]-h2[i])/(2*eps);
315
*/
316
}
317
318
319
320
321
322
323
324
325
// compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1
326
template <class Tx, class Ty, class Tt, class Tr>
327
static void CalcScaledTrigShape (int n, Tx x, Ty y, Tt t, Tr * shape)
328
{
329
if (n < 3) return;
330
331
Tx hx[50], hy[50*50];
332
// ScaledLegendrePolynomial (n-3, (2*x-1), t-y, hx);
333
ScaledJacobiPolynomial (n-3, x, t-y, 2, 2, hx);
334
335
// ScaledLegendrePolynomial (n-3, (2*y-1), t, hy);
336
for (int ix = 0; ix <= n-3; ix++)
337
ScaledJacobiPolynomial (n-3, 2*y-1, t, 2*ix+5, 2, hy+50*ix);
338
339
340
int ii = 0;
341
Tx bub = (t+x-y)*y*(t-x-y);
342
for (int iy = 0; iy <= n-3; iy++)
343
for (int ix = 0; ix <= n-3-iy; ix++)
344
shape[ii++] = bub * hx[ix]*hy[iy+50*ix];
345
}
346
347
348
// compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1
349
static void CalcScaledTrigShapeDxDyDt (int n, double x, double y, double t, double * dshape)
350
{
351
if (n < 3) return;
352
AutoDiff<3> adx(x, 0);
353
AutoDiff<3> ady(y, 1);
354
AutoDiff<3> adt(t, 2);
355
AutoDiff<3> res[2000];
356
CalcScaledTrigShape (n, adx, ady, adt, &res[0]);
357
double dshape1[6000];
358
int ndof = (n-1)*(n-2)/2;
359
for (int i = 0; i < ndof; i++)
360
{
361
dshape[3*i] = res[i].DValue(0);
362
dshape[3*i+1] = res[i].DValue(1);
363
dshape[3*i+2] = res[i].DValue(2);
364
}
365
366
/*
367
if (n < 3) return;
368
double hvl[1000], hvr[1000];
369
int nd = (n-1)*(n-2)/2;
370
371
double eps = 1e-6;
372
373
CalcScaledTrigShape (n, x-eps, y, t, hvl);
374
CalcScaledTrigShape (n, x+eps, y, t, hvr);
375
for (int i = 0; i < nd; i++)
376
dshape[3*i] = (hvr[i]-hvl[i])/(2*eps);
377
378
CalcScaledTrigShape (n, x, y-eps, t, hvl);
379
CalcScaledTrigShape (n, x, y+eps, t, hvr);
380
for (int i = 0; i < nd; i++)
381
dshape[3*i+1] = (hvr[i]-hvl[i])/(2*eps);
382
383
CalcScaledTrigShape (n, x, y, t-eps, hvl);
384
CalcScaledTrigShape (n, x, y, t+eps, hvr);
385
for (int i = 0; i < nd; i++)
386
dshape[3*i+2] = (hvr[i]-hvl[i])/(2*eps);
387
*/
388
389
/*
390
for (int i = 0; i < 3*nd; i++)
391
if (fabs (dshape[i]-dshape1[i]) > 1e-8 * fabs(dshape[i]) + 1e-6)
392
{
393
cerr
394
cerr << "big difference: " << dshape1[i] << " != " << dshape[i] << endl;
395
}
396
*/
397
}
398
399
400
401
402
403
CurvedElements :: CurvedElements (const Mesh & amesh)
404
: mesh (amesh)
405
{
406
order = 1;
407
rational = 0;
408
}
409
410
411
CurvedElements :: ~CurvedElements()
412
{
413
;
414
}
415
416
417
void CurvedElements :: BuildCurvedElements(Refinement * ref, int aorder,
418
bool arational)
419
{
420
order = aorder;
421
ishighorder = 0;
422
423
if (mesh.coarsemesh)
424
{
425
mesh.coarsemesh->GetCurvedElements().BuildCurvedElements (ref, aorder, arational);
426
order = aorder;
427
rational = arational;
428
ishighorder = (order > 1);
429
return;
430
}
431
432
PrintMessage (1, "Curve elements, order = ", aorder);
433
if (rational) PrintMessage (1, "curved elements with rational splines");
434
435
const_cast<Mesh&> (mesh).UpdateTopology();
436
const MeshTopology & top = mesh.GetTopology();
437
438
439
rational = arational;
440
441
ARRAY<int> edgenrs;
442
443
edgeorder.SetSize (top.GetNEdges());
444
faceorder.SetSize (top.GetNFaces());
445
446
edgeorder = 1;
447
faceorder = 1;
448
449
if (rational)
450
{
451
edgeweight.SetSize (top.GetNEdges());
452
edgeweight = 1.0;
453
}
454
455
456
if (aorder <= 1) return;
457
458
459
if (rational) aorder = 2;
460
461
462
if (mesh.GetDimension() == 3)
463
for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)
464
{
465
top.GetSurfaceElementEdges (i+1, edgenrs);
466
for (int j = 0; j < edgenrs.Size(); j++)
467
edgeorder[edgenrs[j]-1] = aorder;
468
faceorder[top.GetSurfaceElementFace (i+1)-1] = aorder;
469
}
470
for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++)
471
edgeorder[top.GetSegmentEdge (i+1)-1] = aorder;
472
473
if (rational)
474
{
475
edgeorder = 2;
476
faceorder = 1;
477
}
478
479
480
edgecoeffsindex.SetSize (top.GetNEdges()+1);
481
int nd = 0;
482
for (int i = 0; i < top.GetNEdges(); i++)
483
{
484
edgecoeffsindex[i] = nd;
485
nd += max (0, edgeorder[i]-1);
486
}
487
edgecoeffsindex[top.GetNEdges()] = nd;
488
489
edgecoeffs.SetSize (nd);
490
edgecoeffs = Vec<3> (0,0,0);
491
492
493
facecoeffsindex.SetSize (top.GetNFaces()+1);
494
nd = 0;
495
for (int i = 0; i < top.GetNFaces(); i++)
496
{
497
facecoeffsindex[i] = nd;
498
if (top.GetFaceType(i+1) == TRIG)
499
nd += max (0, (faceorder[i]-1)*(faceorder[i]-2)/2);
500
else
501
nd += max (0, sqr(faceorder[i]-1));
502
}
503
facecoeffsindex[top.GetNFaces()] = nd;
504
505
facecoeffs.SetSize (nd);
506
facecoeffs = Vec<3> (0,0,0);
507
508
509
if (!ref || aorder <= 1)
510
{
511
order = aorder;
512
return;
513
}
514
515
ARRAY<double> xi, weight;
516
517
ComputeGaussRule (aorder+4, xi, weight); // on (0,1)
518
519
PrintMessage (3, "Curving edges");
520
521
if (mesh.GetDimension() == 3 || rational)
522
for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)
523
{
524
SetThreadPercent(double(i)/mesh.GetNSE()*100.);
525
const Element2d & el = mesh[i];
526
top.GetSurfaceElementEdges (i+1, edgenrs);
527
for (int j = 0; j < edgenrs.Size(); j++)
528
edgenrs[j]--;
529
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (el.GetType());
530
531
for (int i2 = 0; i2 < edgenrs.Size(); i2++)
532
{
533
PointIndex pi1 = edges[i2][0]-1;
534
PointIndex pi2 = edges[i2][1]-1;
535
536
bool swap = el[pi1] > el[pi2];
537
538
Point<3> p1 = mesh[el[pi1]];
539
Point<3> p2 = mesh[el[pi2]];
540
541
int order1 = edgeorder[edgenrs[i2]];
542
int ndof = max (0, order1-1);
543
544
if (rational && order1 >= 2)
545
{
546
Point<3> pm = Center (p1, p2);
547
548
int surfnr = mesh.GetFaceDescriptor(el.GetIndex()).SurfNr();
549
550
Vec<3> n1 = ref -> GetNormal (p1, surfnr, el.GeomInfoPi(edges[i2][0]));
551
Vec<3> n2 = ref -> GetNormal (p2, surfnr, el.GeomInfoPi(edges[i2][1]));
552
553
// p3 = pm + alpha1 n1 + alpha2 n2
554
555
Mat<2> mat, inv;
556
Vec<2> rhs, sol;
557
558
mat(0,0) = n1*n1;
559
mat(0,1) = mat(1,0) = n1*n2;
560
mat(1,1) = n2*n2;
561
562
rhs(0) = n1 * (p1-pm);
563
rhs(1) = n2 * (p2-pm);
564
565
566
Point<3> p3;
567
568
if (fabs (Det (mat)) > 1e-10)
569
{
570
CalcInverse (mat, inv);
571
sol = inv * rhs;
572
573
p3 = pm + sol(0) * n1 + sol(1) * n2;
574
}
575
else
576
p3 = pm;
577
578
edgecoeffs[edgecoeffsindex[edgenrs[i2]]] = Vec<3> (p3);
579
580
581
double wold = 1, w = 1, dw = 0.1;
582
double dold = 1e99;
583
while (fabs (dw) > 1e-12)
584
{
585
Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);
586
v05 /= 1 + (w-1) * 0.5;
587
Point<3> p05 (v05), pp05(v05);
588
ref -> ProjectToSurface (pp05, surfnr, el.GeomInfoPi(edges[i2][0]));
589
double d = Dist (pp05, p05);
590
591
if (d < dold)
592
{
593
dold = d;
594
wold = w;
595
w += dw;
596
}
597
else
598
{
599
dw *= -0.7;
600
w = wold + dw;
601
}
602
}
603
604
edgeweight[edgenrs[i2]] = w;
605
continue;
606
}
607
608
Vector shape(ndof);
609
DenseMatrix mat(ndof, ndof), inv(ndof, ndof),
610
rhs(ndof, 3), sol(ndof, 3);
611
612
rhs = 0.0;
613
mat = 0.0;
614
for (int j = 0; j < xi.Size(); j++)
615
{
616
Point<3> p;
617
Point<3> pp;
618
PointGeomInfo ppgi;
619
620
if (swap)
621
{
622
p = p1 + xi[j] * (p2-p1);
623
ref -> PointBetween (p1, p2, xi[j],
624
mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(),
625
el.GeomInfoPi(edges[i2][0]),
626
el.GeomInfoPi(edges[i2][1]),
627
pp, ppgi);
628
}
629
else
630
{
631
p = p2 + xi[j] * (p1-p2);
632
ref -> PointBetween (p2, p1, xi[j],
633
mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(),
634
el.GeomInfoPi(edges[i2][1]),
635
el.GeomInfoPi(edges[i2][0]),
636
pp, ppgi);
637
}
638
639
Vec<3> dist = pp - p;
640
641
CalcEdgeShape (order1, 2*xi[j]-1, &shape(0));
642
643
for (int k = 0; k < ndof; k++)
644
for (int l = 0; l < ndof; l++)
645
mat(k,l) += weight[j] * shape(k) * shape(l);
646
647
for (int k = 0; k < ndof; k++)
648
for (int l = 0; l < 3; l++)
649
rhs(k,l) += weight[j] * shape(k) * dist(l);
650
}
651
652
CalcInverse (mat, inv);
653
Mult (inv, rhs, sol);
654
655
656
657
int first = edgecoeffsindex[edgenrs[i2]];
658
for (int j = 0; j < ndof; j++)
659
for (int k = 0; k < 3; k++)
660
edgecoeffs[first+j](k) = sol(j,k);
661
}
662
}
663
664
665
666
for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++)
667
{
668
SetThreadPercent(double(i)/mesh.GetNSeg()*100.);
669
const Segment & seg = mesh[i];
670
PointIndex pi1 = mesh[i].p1;
671
PointIndex pi2 = mesh[i].p2;
672
673
bool swap = (pi1 > pi2);
674
675
Point<3> p1 = mesh[pi1];
676
Point<3> p2 = mesh[pi2];
677
678
int segnr = top.GetSegmentEdge (i+1)-1;
679
680
int order1 = edgeorder[segnr];
681
int ndof = max (0, order1-1);
682
683
684
if (rational)
685
{
686
Vec<3> tau1 = ref -> GetTangent (p1, seg.surfnr2, seg.surfnr1, seg.epgeominfo[0]);
687
Vec<3> tau2 = ref -> GetTangent (p2, seg.surfnr2, seg.surfnr1, seg.epgeominfo[1]);
688
// p1 + alpha1 tau1 = p2 + alpha2 tau2;
689
690
Mat<3,2> mat;
691
Mat<2,3> inv;
692
Vec<3> rhs;
693
Vec<2> sol;
694
for (int j = 0; j < 3; j++)
695
{
696
mat(j,0) = tau1(j);
697
mat(j,1) = -tau2(j);
698
rhs(j) = p2(j)-p1(j);
699
}
700
CalcInverse (mat, inv);
701
sol = inv * rhs;
702
703
Point<3> p3 = p1+sol(0) * tau1;
704
edgecoeffs[edgecoeffsindex[segnr]] = Vec<3> (p3);
705
706
707
// double dopt = 1e99;
708
// double wopt = 0;
709
// for (double w = 0; w <= 2; w += 0.0001)
710
// {
711
// Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);
712
// v05 /= 1 + (w-1) * 0.5;
713
// Point<3> p05 (v05), pp05(v05);
714
// ref -> ProjectToEdge (pp05, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]);
715
// double d = Dist (pp05, p05);
716
// if (d < dopt)
717
// {
718
// wopt = w;
719
// dopt = d;
720
// }
721
// }
722
723
double wold = 1, w = 1, dw = 0.1;
724
double dold = 1e99;
725
while (fabs (dw) > 1e-12)
726
{
727
Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);
728
v05 /= 1 + (w-1) * 0.5;
729
Point<3> p05 (v05), pp05(v05);
730
ref -> ProjectToEdge (pp05, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]);
731
double d = Dist (pp05, p05);
732
733
if (d < dold)
734
{
735
dold = d;
736
wold = w;
737
w += dw;
738
}
739
else
740
{
741
dw *= -0.7;
742
w = wold + dw;
743
}
744
// *testout << "w = " << w << ", dw = " << dw << endl;
745
}
746
747
// cout << "wopt = " << w << ", dopt = " << dold << endl;
748
edgeweight[segnr] = w;
749
750
// cout << "p1 = " << p1 << ", tau1 = " << tau1 << ", alpha1 = " << sol(0) << endl;
751
// cout << "p2 = " << p2 << ", tau2 = " << tau2 << ", alpha2 = " << -sol(1) << endl;
752
// cout << "p+alpha tau = " << p1 + sol(0) * tau1
753
// << " =?= " << p2 +sol(1) * tau2 << endl;
754
755
}
756
757
else
758
759
{
760
761
Vector shape(ndof);
762
DenseMatrix mat(ndof, ndof), inv(ndof, ndof),
763
rhs(ndof, 3), sol(ndof, 3);
764
765
rhs = 0.0;
766
mat = 0.0;
767
for (int j = 0; j < xi.Size(); j++)
768
{
769
Point<3> p;
770
771
Point<3> pp;
772
EdgePointGeomInfo ppgi;
773
774
if (swap)
775
{
776
p = p1 + xi[j] * (p2-p1);
777
ref -> PointBetween (p1, p2, xi[j],
778
seg.surfnr2, seg.surfnr1,
779
seg.epgeominfo[0], seg.epgeominfo[1],
780
pp, ppgi);
781
}
782
else
783
{
784
p = p2 + xi[j] * (p1-p2);
785
ref -> PointBetween (p2, p1, xi[j],
786
seg.surfnr2, seg.surfnr1,
787
seg.epgeominfo[1], seg.epgeominfo[0],
788
pp, ppgi);
789
}
790
791
Vec<3> dist = pp - p;
792
793
CalcEdgeShape (order1, 2*xi[j]-1, &shape(0));
794
795
for (int k = 0; k < ndof; k++)
796
for (int l = 0; l < ndof; l++)
797
mat(k,l) += weight[j] * shape(k) * shape(l);
798
799
for (int k = 0; k < ndof; k++)
800
for (int l = 0; l < 3; l++)
801
rhs(k,l) += weight[j] * shape(k) * dist(l);
802
}
803
804
805
CalcInverse (mat, inv);
806
Mult (inv, rhs, sol);
807
808
int first = edgecoeffsindex[segnr];
809
for (int j = 0; j < ndof; j++)
810
for (int k = 0; k < 3; k++)
811
edgecoeffs[first+j](k) = sol(j,k);
812
}
813
}
814
815
816
817
818
PrintMessage (3, "Curving faces");
819
820
if (mesh.GetDimension() == 3)
821
for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)
822
{
823
SetThreadPercent(double(i)/mesh.GetNSE()*100.);
824
const Element2d & el = mesh[i];
825
int facenr = top.GetSurfaceElementFace (i+1)-1;
826
827
if (el.GetType() == TRIG && order >= 3)
828
{
829
int fnums[] = { 0, 1, 2 };
830
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
831
if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);
832
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
833
834
int order1 = faceorder[facenr];
835
int ndof = max (0, (order1-1)*(order1-2)/2);
836
837
Vector shape(ndof);
838
DenseMatrix mat(ndof, ndof), inv(ndof, ndof),
839
rhs(ndof, 3), sol(ndof, 3);
840
841
rhs = 0.0;
842
mat = 0.0;
843
844
for (int jx = 0; jx < xi.Size(); jx++)
845
for (int jy = 0; jy < xi.Size(); jy++)
846
{
847
double y = xi[jy];
848
double x = (1-y) * xi[jx];
849
double lami[] = { x, y, 1-x-y };
850
double wi = weight[jx]*weight[jy]*(1-y);
851
852
Point<2> xii (x, y);
853
Point<3> p1, p2;
854
CalcSurfaceTransformation (xii, i, p1);
855
p2 = p1;
856
ref -> ProjectToSurface (p2, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr());
857
858
Vec<3> dist = p2-p1;
859
860
CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]],
861
1-lami[fnums[1]]-lami[fnums[0]], &shape(0));
862
863
for (int k = 0; k < ndof; k++)
864
for (int l = 0; l < ndof; l++)
865
mat(k,l) += wi * shape(k) * shape(l);
866
867
for (int k = 0; k < ndof; k++)
868
for (int l = 0; l < 3; l++)
869
rhs(k,l) += wi * shape(k) * dist(l);
870
}
871
872
// *testout << "mat = " << endl << mat << endl;
873
// CalcInverse (mat, inv);
874
// Mult (inv, rhs, sol);
875
876
for (int i = 0; i < ndof; i++)
877
for (int j = 0; j < 3; j++)
878
sol(i,j) = rhs(i,j) / mat(i,i); // Orthogonal basis !
879
880
int first = facecoeffsindex[facenr];
881
for (int j = 0; j < ndof; j++)
882
for (int k = 0; k < 3; k++)
883
facecoeffs[first+j](k) = sol(j,k);
884
}
885
}
886
887
PrintMessage (3, "Complete");
888
889
890
// compress edge and face tables
891
int newbase = 0;
892
for (int i = 0; i < edgeorder.Size(); i++)
893
{
894
bool curved = 0;
895
int oldbase = edgecoeffsindex[i];
896
nd = edgecoeffsindex[i+1] - edgecoeffsindex[i];
897
898
for (int j = 0; j < nd; j++)
899
if (edgecoeffs[oldbase+j].Length() > 1e-12)
900
curved = 1;
901
if (rational) curved = 1;
902
903
if (curved && newbase != oldbase)
904
for (int j = 0; j < nd; j++)
905
edgecoeffs[newbase+j] = edgecoeffs[oldbase+j];
906
907
edgecoeffsindex[i] = newbase;
908
if (!curved) edgeorder[i] = 1;
909
if (curved) newbase += nd;
910
}
911
edgecoeffsindex.Last() = newbase;
912
913
914
newbase = 0;
915
for (int i = 0; i < faceorder.Size(); i++)
916
{
917
bool curved = 0;
918
int oldbase = facecoeffsindex[i];
919
nd = facecoeffsindex[i+1] - facecoeffsindex[i];
920
921
for (int j = 0; j < nd; j++)
922
if (facecoeffs[oldbase+j].Length() > 1e-12)
923
curved = 1;
924
925
if (curved && newbase != oldbase)
926
for (int j = 0; j < nd; j++)
927
facecoeffs[newbase+j] = facecoeffs[oldbase+j];
928
929
facecoeffsindex[i] = newbase;
930
if (!curved) faceorder[i] = 1;
931
if (curved) newbase += nd;
932
}
933
facecoeffsindex.Last() = newbase;
934
935
ishighorder = (order > 1);
936
// (*testout) << "edgecoeffs = " << endl << edgecoeffs << endl;
937
// (*testout) << "facecoeffs = " << endl << facecoeffs << endl;
938
}
939
940
941
942
943
944
945
946
947
948
949
// *********************** Transform edges *****************************
950
951
952
bool CurvedElements :: IsSegmentCurved (SegmentIndex elnr) const
953
{
954
if (mesh.coarsemesh)
955
{
956
const HPRefElement & hpref_el =
957
(*mesh.hpelements) [mesh[elnr].hp_elnr];
958
959
return mesh.coarsemesh->GetCurvedElements().IsSegmentCurved (hpref_el.coarse_elnr);
960
}
961
962
SegmentInfo info;
963
info.elnr = elnr;
964
info.order = order;
965
info.ndof = info.nv = 2;
966
if (info.order > 1)
967
{
968
const MeshTopology & top = mesh.GetTopology();
969
info.edgenr = top.GetSegmentEdge (elnr+1)-1;
970
info.ndof += edgeorder[info.edgenr]-1;
971
}
972
973
return (info.ndof > info.nv);
974
}
975
976
977
978
979
980
void CurvedElements ::
981
CalcSegmentTransformation (double xi, SegmentIndex elnr,
982
Point<3> * x, Vec<3> * dxdxi, bool * curved)
983
{
984
if (mesh.coarsemesh)
985
{
986
const HPRefElement & hpref_el =
987
(*mesh.hpelements) [mesh[elnr].hp_elnr];
988
989
// xi umrechnen
990
double lami[2] = { xi, 1-xi };
991
double dlami[2] = { 1, -1 };
992
993
double coarse_xi = 0;
994
double trans = 0;
995
for (int i = 0; i < 2; i++)
996
{
997
coarse_xi += hpref_el.param[i][0] * lami[i];
998
trans += hpref_el.param[i][0] * dlami[i];
999
}
1000
1001
mesh.coarsemesh->GetCurvedElements().CalcSegmentTransformation (coarse_xi, hpref_el.coarse_elnr, x, dxdxi, curved);
1002
if (dxdxi) *dxdxi *= trans;
1003
1004
return;
1005
}
1006
1007
1008
Vector shapes, dshapes;
1009
ARRAY<Vec<3> > coefs;
1010
1011
SegmentInfo info;
1012
info.elnr = elnr;
1013
info.order = order;
1014
info.ndof = info.nv = 2;
1015
1016
if (info.order > 1)
1017
{
1018
const MeshTopology & top = mesh.GetTopology();
1019
info.edgenr = top.GetSegmentEdge (elnr+1)-1;
1020
info.ndof += edgeorder[info.edgenr]-1;
1021
}
1022
1023
CalcElementShapes (info, xi, shapes);
1024
GetCoefficients (info, coefs);
1025
1026
*x = 0;
1027
for (int i = 0; i < shapes.Size(); i++)
1028
*x += shapes(i) * coefs[i];
1029
1030
1031
if (dxdxi)
1032
{
1033
CalcElementDShapes (info, xi, dshapes);
1034
1035
*dxdxi = 0;
1036
for (int i = 0; i < shapes.Size(); i++)
1037
for (int j = 0; j < 3; j++)
1038
(*dxdxi)(j) += dshapes(i) * coefs[i](j);
1039
}
1040
1041
if (curved)
1042
*curved = (info.order > 1);
1043
1044
// cout << "Segment, |x| = " << Abs2(Vec<3> (*x) ) << endl;
1045
}
1046
1047
1048
1049
1050
void CurvedElements ::
1051
CalcElementShapes (SegmentInfo & info, double xi, Vector & shapes) const
1052
{
1053
if (rational && info.order == 2)
1054
{
1055
shapes.SetSize(3);
1056
double w = edgeweight[info.edgenr];
1057
shapes(0) = xi*xi;
1058
shapes(1) = (1-xi)*(1-xi);
1059
shapes(2) = 2*w*xi*(1-xi);
1060
shapes *= 1.0 / (1 + (w-1) *2*xi*(1-xi));
1061
return;
1062
}
1063
1064
1065
shapes.SetSize(info.ndof);
1066
shapes(0) = xi;
1067
shapes(1) = 1-xi;
1068
1069
if (info.order >= 2)
1070
{
1071
if (mesh[info.elnr].p1 > mesh[info.elnr].p2)
1072
xi = 1-xi;
1073
CalcEdgeShape (edgeorder[info.edgenr], 2*xi-1, &shapes(2));
1074
}
1075
}
1076
1077
void CurvedElements ::
1078
CalcElementDShapes (SegmentInfo & info, double xi, Vector & dshapes) const
1079
{
1080
if (rational && info.order == 2)
1081
{
1082
dshapes.SetSize(3);
1083
double wi = edgeweight[info.edgenr];
1084
double shapes[3];
1085
shapes[0] = xi*xi;
1086
shapes[1] = (1-xi)*(1-xi);
1087
shapes[2] = 2*wi*xi*(1-xi);
1088
double w = 1 + (wi-1) *2*xi*(1-xi);
1089
double dw = (wi-1) * (2 - 4*xi);
1090
1091
dshapes(0) = 2*xi;
1092
dshapes(1) = 2*(xi-1);
1093
dshapes(2) = 2*wi*(1-2*xi);
1094
1095
for (int j = 0;j < 3; j++)
1096
dshapes(j) = dshapes(j) / w - shapes[j] * dw / (w*w);
1097
return;
1098
}
1099
1100
1101
1102
1103
1104
1105
dshapes.SetSize(info.ndof);
1106
dshapes = 0;
1107
dshapes(0) = 1;
1108
dshapes(1) = -1;
1109
1110
// int order = edgeorder[info.edgenr];
1111
1112
if (info.order >= 2)
1113
{
1114
double fac = 2;
1115
if (mesh[info.elnr].p1 > mesh[info.elnr].p2)
1116
{
1117
xi = 1-xi;
1118
fac *= -1;
1119
}
1120
CalcEdgeDx (edgeorder[info.edgenr], 2*xi-1, &dshapes(2));
1121
for (int i = 2; i < dshapes.Size(); i++)
1122
dshapes(i) *= fac;
1123
}
1124
1125
// ??? not implemented ????
1126
}
1127
1128
void CurvedElements ::
1129
GetCoefficients (SegmentInfo & info, ARRAY<Vec<3> > & coefs) const
1130
{
1131
const Segment & el = mesh[info.elnr];
1132
1133
coefs.SetSize(info.ndof);
1134
1135
coefs[0] = Vec<3> (mesh[el.p1]);
1136
coefs[1] = Vec<3> (mesh[el.p2]);
1137
1138
if (info.order >= 2)
1139
{
1140
int first = edgecoeffsindex[info.edgenr];
1141
int next = edgecoeffsindex[info.edgenr+1];
1142
for (int i = 0; i < next-first; i++)
1143
coefs[i+2] = edgecoeffs[first+i];
1144
}
1145
}
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
// ********************** Transform surface elements *******************
1160
1161
1162
bool CurvedElements :: IsSurfaceElementCurved (SurfaceElementIndex elnr) const
1163
{
1164
if (mesh.coarsemesh)
1165
{
1166
const HPRefElement & hpref_el =
1167
(*mesh.hpelements) [mesh[elnr].hp_elnr];
1168
1169
return mesh.coarsemesh->GetCurvedElements().IsSurfaceElementCurved (hpref_el.coarse_elnr);
1170
}
1171
1172
const Element2d & el = mesh[elnr];
1173
ELEMENT_TYPE type = el.GetType();
1174
1175
SurfaceElementInfo info;
1176
info.elnr = elnr;
1177
info.order = order;
1178
info.ndof = info.nv = (type == TRIG) ? 3 : 4;
1179
if (info.order > 1)
1180
{
1181
const MeshTopology & top = mesh.GetTopology();
1182
1183
top.GetSurfaceElementEdges (elnr+1, info.edgenrs);
1184
for (int i = 0; i < info.edgenrs.Size(); i++)
1185
info.edgenrs[i]--;
1186
info.facenr = top.GetSurfaceElementFace (elnr+1)-1;
1187
1188
for (int i = 0; i < info.edgenrs.Size(); i++)
1189
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
1190
info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];
1191
}
1192
1193
return (info.ndof > info.nv);
1194
}
1195
1196
void CurvedElements ::
1197
CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr,
1198
Point<3> * x, Mat<3,2> * dxdxi, bool * curved)
1199
{
1200
if (mesh.coarsemesh)
1201
{
1202
const HPRefElement & hpref_el =
1203
(*mesh.hpelements) [mesh[elnr].hp_elnr];
1204
1205
// xi umrechnen
1206
double lami[4];
1207
FlatVector vlami(4, lami);
1208
vlami = 0;
1209
mesh[elnr].GetShapeNew (xi, vlami);
1210
1211
Mat<2,2> trans;
1212
Mat<3,2> dxdxic;
1213
if (dxdxi)
1214
{
1215
MatrixFixWidth<2> dlami(4);
1216
dlami = 0;
1217
mesh[elnr].GetDShapeNew (xi, dlami);
1218
1219
trans = 0;
1220
for (int k = 0; k < 2; k++)
1221
for (int l = 0; l < 2; l++)
1222
for (int i = 0; i < hpref_el.np; i++)
1223
trans(l,k) += hpref_el.param[i][l] * dlami(i, k);
1224
}
1225
1226
Point<2> coarse_xi(0,0);
1227
for (int i = 0; i < hpref_el.np; i++)
1228
for (int j = 0; j < 2; j++)
1229
coarse_xi(j) += hpref_el.param[i][j] * lami[i];
1230
1231
mesh.coarsemesh->GetCurvedElements().CalcSurfaceTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic, curved);
1232
1233
if (dxdxi)
1234
*dxdxi = dxdxic * trans;
1235
1236
return;
1237
}
1238
1239
1240
1241
Vector shapes;
1242
DenseMatrix dshapes;
1243
ARRAY<Vec<3> > coefs;
1244
1245
const Element2d & el = mesh[elnr];
1246
ELEMENT_TYPE type = el.GetType();
1247
1248
SurfaceElementInfo info;
1249
info.elnr = elnr;
1250
info.order = order;
1251
info.ndof = info.nv = (type == TRIG) ? 3 : 4;
1252
if (info.order > 1)
1253
{
1254
const MeshTopology & top = mesh.GetTopology();
1255
1256
top.GetSurfaceElementEdges (elnr+1, info.edgenrs);
1257
for (int i = 0; i < info.edgenrs.Size(); i++)
1258
info.edgenrs[i]--;
1259
info.facenr = top.GetSurfaceElementFace (elnr+1)-1;
1260
1261
1262
bool firsttry = true;
1263
bool problem = false;
1264
1265
while(firsttry || problem)
1266
{
1267
problem = false;
1268
1269
for (int i = 0; !problem && i < info.edgenrs.Size(); i++)
1270
{
1271
if(info.edgenrs[i]+1 >= edgecoeffsindex.Size())
1272
problem = true;
1273
else
1274
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
1275
}
1276
if(info.facenr+1 >= facecoeffsindex.Size())
1277
problem = true;
1278
else
1279
info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];
1280
1281
if(problem && !firsttry)
1282
throw NgException("something wrong with curved elements");
1283
1284
if(problem)
1285
BuildCurvedElements(NULL,order,rational);
1286
1287
firsttry = false;
1288
}
1289
}
1290
1291
CalcElementShapes (info, xi, shapes);
1292
GetCoefficients (info, coefs);
1293
1294
*x = 0;
1295
for (int i = 0; i < coefs.Size(); i++)
1296
*x += shapes(i) * coefs[i];
1297
1298
if (dxdxi)
1299
{
1300
CalcElementDShapes (info, xi, dshapes);
1301
1302
*dxdxi = 0;
1303
for (int i = 0; i < coefs.Size(); i++)
1304
for (int j = 0; j < 3; j++)
1305
for (int k = 0; k < 2; k++)
1306
(*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j);
1307
}
1308
1309
if (curved)
1310
*curved = (info.ndof > info.nv);
1311
1312
1313
// cout.precision(12);
1314
// cout << "face, |x| = " << Abs2(Vec<3> (*x) )/sqr(M_PI) << endl;
1315
}
1316
1317
1318
1319
1320
void CurvedElements ::
1321
CalcElementShapes (SurfaceElementInfo & info, const Point<2> & xi, Vector & shapes) const
1322
{
1323
const Element2d & el = mesh[info.elnr];
1324
1325
shapes.SetSize(info.ndof);
1326
shapes = 0;
1327
1328
if (rational && info.order >= 2)
1329
{
1330
shapes.SetSize(6);
1331
double w = 1;
1332
double lami[3] = { xi(0), xi(1), 1-xi(0)-xi(1) };
1333
for (int j = 0; j < 3; j++)
1334
shapes(j) = lami[j] * lami[j];
1335
1336
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);
1337
for (int j = 0; j < 3; j++)
1338
{
1339
double wi = edgeweight[info.edgenrs[j]];
1340
shapes(j+3) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];
1341
w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];
1342
}
1343
1344
shapes *= 1.0 / w;
1345
return;
1346
}
1347
1348
switch (el.GetType())
1349
{
1350
case TRIG:
1351
{
1352
shapes(0) = xi(0);
1353
shapes(1) = xi(1);
1354
shapes(2) = 1-xi(0)-xi(1);
1355
1356
if (info.order == 1) return;
1357
1358
int ii = 3;
1359
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);
1360
1361
for (int i = 0; i < 3; i++)
1362
{
1363
int eorder = edgeorder[info.edgenrs[i]];
1364
if (eorder >= 2)
1365
{
1366
int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;
1367
if (el[vi1] > el[vi2]) swap (vi1, vi2);
1368
1369
CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));
1370
ii += eorder-1;
1371
}
1372
}
1373
1374
int forder = faceorder[info.facenr];
1375
if (forder >= 3)
1376
{
1377
int fnums[] = { 0, 1, 2 };
1378
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
1379
if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);
1380
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
1381
1382
CalcTrigShape (forder,
1383
shapes(fnums[1])-shapes(fnums[0]),
1384
1-shapes(fnums[1])-shapes(fnums[0]), &shapes(ii));
1385
}
1386
break;
1387
}
1388
1389
case QUAD:
1390
{
1391
shapes(0) = (1-xi(0))*(1-xi(1));
1392
shapes(1) = xi(0) *(1-xi(1));
1393
shapes(2) = xi(0) * xi(1) ;
1394
shapes(3) = (1-xi(0))* xi(1) ;
1395
1396
if (info.order == 1) return;
1397
1398
double mu[4] = {
1399
1 - xi(0) + 1 - xi(1),
1400
xi(0) + 1 - xi(1),
1401
xi(0) + xi(1),
1402
1 - xi(0) + xi(1),
1403
};
1404
1405
int ii = 4;
1406
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (QUAD);
1407
1408
for (int i = 0; i < 4; i++)
1409
{
1410
int eorder = edgeorder[info.edgenrs[i]];
1411
if (eorder >= 2)
1412
{
1413
int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;
1414
if (el[vi1] > el[vi2]) swap (vi1, vi2);
1415
1416
CalcEdgeShape (eorder, mu[vi1]-mu[vi2], &shapes(ii));
1417
double lame = shapes(vi1)+shapes(vi2);
1418
for (int j = 0; j < order-1; j++)
1419
shapes(ii+j) *= lame;
1420
ii += eorder-1;
1421
}
1422
}
1423
1424
for (int i = ii; i < info.ndof; i++)
1425
shapes(i) = 0;
1426
1427
break;
1428
}
1429
};
1430
}
1431
1432
1433
void CurvedElements ::
1434
CalcElementDShapes (SurfaceElementInfo & info, const Point<2> & xi, DenseMatrix & dshapes) const
1435
{
1436
const Element2d & el = mesh[info.elnr];
1437
ELEMENT_TYPE type = el.GetType();
1438
1439
double lami[4];
1440
1441
dshapes.SetSize(info.ndof,2);
1442
dshapes = 0;
1443
1444
// *testout << "calcelementdshapes, info.ndof = " << info.ndof << endl;
1445
1446
if (rational && info.order >= 2)
1447
{
1448
double w = 1;
1449
double dw[2] = { 0, 0 };
1450
1451
1452
lami[0] = xi(0); lami[1] = xi(1); lami[2] = 1-xi(0)-xi(1);
1453
double dlami[3][2] = { { 1, 0 }, { 0, 1 }, { -1, -1 }};
1454
double shapes[6];
1455
1456
for (int j = 0; j < 3; j++)
1457
{
1458
shapes[j] = lami[j] * lami[j];
1459
dshapes(j,0) = 2 * lami[j] * dlami[j][0];
1460
dshapes(j,1) = 2 * lami[j] * dlami[j][1];
1461
}
1462
1463
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);
1464
for (int j = 0; j < 3; j++)
1465
{
1466
double wi = edgeweight[info.edgenrs[j]];
1467
1468
shapes[j+3] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];
1469
for (int k = 0; k < 2; k++)
1470
dshapes(j+3,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +
1471
lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);
1472
1473
w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];
1474
for (int k = 0; k < 2; k++)
1475
dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +
1476
lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);
1477
}
1478
// shapes *= 1.0 / w;
1479
dshapes *= 1.0 / w;
1480
for (int i = 0; i < 6; i++)
1481
for (int j = 0; j < 2; j++)
1482
dshapes(i,j) -= shapes[i] * dw[j] / (w*w);
1483
return;
1484
}
1485
1486
1487
1488
1489
1490
switch (type)
1491
{
1492
case TRIG:
1493
{
1494
dshapes(0,0) = 1;
1495
dshapes(1,1) = 1;
1496
dshapes(2,0) = -1;
1497
dshapes(2,1) = -1;
1498
1499
if (info.order == 1) return;
1500
1501
// *testout << "info.order = " << info.order << endl;
1502
1503
1504
lami[0] = xi(0);
1505
lami[1] = xi(1);
1506
lami[2] = 1-xi(0)-xi(1);
1507
1508
int ii = 3;
1509
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);
1510
1511
for (int i = 0; i < 3; i++)
1512
{
1513
int eorder = edgeorder[info.edgenrs[i]];
1514
if (eorder >= 2)
1515
{
1516
int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;
1517
if (el[vi1] > el[vi2]) swap (vi1, vi2);
1518
1519
CalcScaledEdgeShapeDxDt<2> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0));
1520
1521
Mat<2,2> trans;
1522
for (int j = 0; j < 2; j++)
1523
{
1524
trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j);
1525
trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j);
1526
}
1527
1528
for (int j = 0; j < eorder-1; j++)
1529
{
1530
double ddx = dshapes(ii+j,0);
1531
double ddt = dshapes(ii+j,1);
1532
dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);
1533
dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);
1534
}
1535
1536
ii += eorder-1;
1537
}
1538
}
1539
1540
int forder = faceorder[info.facenr];
1541
// *testout << "forder = " << forder << endl;
1542
if (forder >= 3)
1543
{
1544
int fnums[] = { 0, 1, 2 };
1545
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
1546
if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);
1547
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
1548
1549
CalcTrigShapeDxDy (forder,
1550
lami[fnums[1]]-lami[fnums[0]],
1551
1-lami[fnums[1]]-lami[fnums[0]], &dshapes(ii,0));
1552
1553
int nd = (forder-1)*(forder-2)/2;
1554
Mat<2,2> trans;
1555
for (int j = 0; j < 2; j++)
1556
{
1557
trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j);
1558
trans(1,j) = -dshapes(fnums[1],j)-dshapes(fnums[0],j);
1559
}
1560
1561
for (int j = 0; j < nd; j++)
1562
{
1563
double ddx = dshapes(ii+j,0);
1564
double ddt = dshapes(ii+j,1);
1565
dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);
1566
dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);
1567
}
1568
}
1569
1570
break;
1571
}
1572
case QUAD:
1573
{
1574
dshapes(0,0) = -(1-xi(1));
1575
dshapes(0,1) = -(1-xi(0));
1576
dshapes(1,0) = (1-xi(1));
1577
dshapes(1,1) = -xi(0);
1578
dshapes(2,0) = xi(1);
1579
dshapes(2,1) = xi(0);
1580
dshapes(3,0) = -xi(1);
1581
dshapes(3,1) = (1-xi(0));
1582
1583
if (info.order == 1) return;
1584
1585
double shapes[4] = {
1586
(1-xi(0))*(1-xi(1)),
1587
xi(0) *(1-xi(1)),
1588
xi(0) * xi(1) ,
1589
(1-xi(0))* xi(1)
1590
};
1591
1592
double mu[4] = {
1593
1 - xi(0) + 1 - xi(1),
1594
xi(0) + 1 - xi(1),
1595
xi(0) + xi(1),
1596
1 - xi(0) + xi(1),
1597
};
1598
1599
double dmu[4][2] = {
1600
{ -1, -1 },
1601
{ 1, -1 },
1602
{ 1, 1 },
1603
{ -1, 1 } };
1604
1605
// double hshapes[20], hdshapes[20];
1606
ArrayMem<double, 20> hshapes(order+1), hdshapes(order+1);
1607
1608
int ii = 4;
1609
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (QUAD);
1610
1611
for (int i = 0; i < 4; i++)
1612
{
1613
int eorder = edgeorder[info.edgenrs[i]];
1614
if (eorder >= 2)
1615
{
1616
int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;
1617
if (el[vi1] > el[vi2]) swap (vi1, vi2);
1618
1619
CalcEdgeShapeDx (eorder, mu[vi1]-mu[vi2], &hshapes[0], &hdshapes[0]);
1620
1621
double lame = shapes[vi1]+shapes[vi2];
1622
double dlame[2] = {
1623
dshapes(vi1, 0) + dshapes(vi2, 0),
1624
dshapes(vi1, 1) + dshapes(vi2, 1) };
1625
1626
for (int j = 0; j < eorder-1; j++)
1627
for (int k = 0; k < 2; k++)
1628
dshapes(ii+j, k) =
1629
lame * hdshapes[j] * (dmu[vi1][k]-dmu[vi2][k])
1630
+ dlame[k] * hshapes[j];
1631
1632
ii += eorder-1;
1633
}
1634
}
1635
1636
/*
1637
*testout << "quad, dshape = " << endl << dshapes << endl;
1638
for (int i = 0; i < 2; i++)
1639
{
1640
Point<2> xil = xi, xir = xi;
1641
Vector shapesl(dshapes.Height()), shapesr(dshapes.Height());
1642
xil(i) -= 1e-6;
1643
xir(i) += 1e-6;
1644
CalcElementShapes (info, xil, shapesl);
1645
CalcElementShapes (info, xir, shapesr);
1646
1647
for (int j = 0; j < dshapes.Height(); j++)
1648
dshapes(j,i) = 1.0 / 2e-6 * (shapesr(j)-shapesl(j));
1649
}
1650
1651
*testout << "quad, num dshape = " << endl << dshapes << endl;
1652
*/
1653
break;
1654
}
1655
};
1656
}
1657
1658
1659
1660
void CurvedElements ::
1661
GetCoefficients (SurfaceElementInfo & info, ARRAY<Vec<3> > & coefs) const
1662
{
1663
const Element2d & el = mesh[info.elnr];
1664
1665
coefs.SetSize (info.ndof);
1666
// coefs = Vec<3> (0,0,0);
1667
1668
for (int i = 0; i < info.nv; i++)
1669
coefs[i] = Vec<3> (mesh[el[i]]);
1670
1671
if (info.order == 1) return;
1672
1673
int ii = info.nv;
1674
1675
for (int i = 0; i < info.edgenrs.Size(); i++)
1676
{
1677
int first = edgecoeffsindex[info.edgenrs[i]];
1678
int next = edgecoeffsindex[info.edgenrs[i]+1];
1679
for (int j = first; j < next; j++, ii++)
1680
coefs[ii] = edgecoeffs[j];
1681
}
1682
1683
int first = facecoeffsindex[info.facenr];
1684
int next = facecoeffsindex[info.facenr+1];
1685
for (int j = first; j < next; j++, ii++)
1686
coefs[ii] = facecoeffs[j];
1687
}
1688
1689
1690
1691
1692
1693
1694
1695
// ********************** Transform volume elements *******************
1696
1697
1698
bool CurvedElements :: IsElementCurved (ElementIndex elnr) const
1699
{
1700
if (mesh.coarsemesh)
1701
{
1702
const HPRefElement & hpref_el =
1703
(*mesh.hpelements) [mesh[elnr].hp_elnr];
1704
1705
return mesh.coarsemesh->GetCurvedElements().IsElementCurved (hpref_el.coarse_elnr);
1706
}
1707
1708
const Element & el = mesh[elnr];
1709
ELEMENT_TYPE type = el.GetType();
1710
1711
ElementInfo info;
1712
info.elnr = elnr;
1713
info.order = order;
1714
info.ndof = info.nv = MeshTopology::GetNVertices (type);
1715
if (info.order > 1)
1716
{
1717
const MeshTopology & top = mesh.GetTopology();
1718
1719
info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);
1720
for (int i = 0; i < info.nedges; i++)
1721
info.edgenrs[i]--;
1722
1723
info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);
1724
for (int i = 0; i < info.nfaces; i++)
1725
info.facenrs[i]--;
1726
1727
for (int i = 0; i < info.nedges; i++)
1728
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
1729
for (int i = 0; i < info.nfaces; i++)
1730
info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];
1731
}
1732
1733
return (info.ndof > info.nv);
1734
}
1735
1736
1737
1738
1739
1740
1741
void CurvedElements ::
1742
CalcElementTransformation (Point<3> xi, ElementIndex elnr,
1743
Point<3> * x, Mat<3,3> * dxdxi, // bool * curved,
1744
void * buffer, bool valid)
1745
{
1746
if (mesh.coarsemesh)
1747
{
1748
const HPRefElement & hpref_el =
1749
(*mesh.hpelements) [mesh[elnr].hp_elnr];
1750
1751
// xi umrechnen
1752
double lami[8];
1753
FlatVector vlami(8, lami);
1754
vlami = 0;
1755
mesh[elnr].GetShapeNew (xi, vlami);
1756
1757
Mat<3,3> trans, dxdxic;
1758
if (dxdxi)
1759
{
1760
MatrixFixWidth<3> dlami(8);
1761
dlami = 0;
1762
mesh[elnr].GetDShapeNew (xi, dlami);
1763
1764
trans = 0;
1765
for (int k = 0; k < 3; k++)
1766
for (int l = 0; l < 3; l++)
1767
for (int i = 0; i < hpref_el.np; i++)
1768
trans(l,k) += hpref_el.param[i][l] * dlami(i, k);
1769
}
1770
1771
Point<3> coarse_xi(0,0,0);
1772
for (int i = 0; i < hpref_el.np; i++)
1773
for (int j = 0; j < 3; j++)
1774
coarse_xi(j) += hpref_el.param[i][j] * lami[i];
1775
1776
mesh.coarsemesh->GetCurvedElements().CalcElementTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic /* , curved */);
1777
1778
if (dxdxi)
1779
*dxdxi = dxdxic * trans;
1780
1781
return;
1782
}
1783
1784
1785
Vector shapes;
1786
MatrixFixWidth<3> dshapes;
1787
1788
const Element & el = mesh[elnr];
1789
ELEMENT_TYPE type = el.GetType();
1790
1791
ElementInfo hinfo;
1792
ElementInfo & info = (buffer) ? *static_cast<ElementInfo*> (buffer) : hinfo;
1793
1794
1795
if (!valid)
1796
{
1797
info.elnr = elnr;
1798
info.order = order;
1799
info.ndof = info.nv = MeshTopology::GetNVertices (type);
1800
if (info.order > 1)
1801
{
1802
const MeshTopology & top = mesh.GetTopology();
1803
1804
info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);
1805
for (int i = 0; i < info.nedges; i++)
1806
info.edgenrs[i]--;
1807
1808
info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);
1809
for (int i = 0; i < info.nfaces; i++)
1810
info.facenrs[i]--;
1811
1812
for (int i = 0; i < info.nedges; i++)
1813
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
1814
for (int i = 0; i < info.nfaces; i++)
1815
info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];
1816
}
1817
}
1818
1819
CalcElementShapes (info, xi, shapes);
1820
1821
Vec<3> * coefs = (info.ndof <= 10) ?
1822
&info.hcoefs[0] : new Vec<3> [info.ndof];
1823
1824
if (info.ndof > 10 || !valid)
1825
GetCoefficients (info, coefs);
1826
1827
if (x)
1828
{
1829
*x = 0;
1830
for (int i = 0; i < shapes.Size(); i++)
1831
*x += shapes(i) * coefs[i];
1832
}
1833
1834
if (dxdxi)
1835
{
1836
if (valid && info.order == 1 && info.nv == 4) // a linear tet
1837
{
1838
*dxdxi = info.hdxdxi;
1839
}
1840
else
1841
{
1842
CalcElementDShapes (info, xi, dshapes);
1843
1844
*dxdxi = 0;
1845
for (int i = 0; i < shapes.Size(); i++)
1846
for (int j = 0; j < 3; j++)
1847
for (int k = 0; k < 3; k++)
1848
(*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j);
1849
1850
info.hdxdxi = *dxdxi;
1851
}
1852
}
1853
1854
// *testout << "curved_elements, dshapes = " << endl << dshapes << endl;
1855
1856
// if (curved) *curved = (info.ndof > info.nv);
1857
1858
if (info.ndof > 10) delete [] coefs;
1859
}
1860
1861
1862
1863
1864
void CurvedElements :: CalcElementShapes (ElementInfo & info, const Point<3> & xi, Vector & shapes) const
1865
{
1866
const Element & el = mesh[info.elnr];
1867
1868
if (rational && info.order >= 2)
1869
{
1870
shapes.SetSize(10);
1871
double w = 1;
1872
double lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };
1873
for (int j = 0; j < 4; j++)
1874
shapes(j) = lami[j] * lami[j];
1875
1876
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);
1877
for (int j = 0; j < 6; j++)
1878
{
1879
double wi = edgeweight[info.edgenrs[j]];
1880
shapes(j+4) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];
1881
w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];
1882
}
1883
1884
shapes *= 1.0 / w;
1885
return;
1886
}
1887
1888
shapes.SetSize(info.ndof);
1889
1890
switch (el.GetType())
1891
{
1892
case TET:
1893
{
1894
shapes(0) = xi(0);
1895
shapes(1) = xi(1);
1896
shapes(2) = xi(2);
1897
shapes(3) = 1-xi(0)-xi(1)-xi(2);
1898
1899
if (info.order == 1) return;
1900
1901
int ii = 4;
1902
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);
1903
for (int i = 0; i < 6; i++)
1904
{
1905
int eorder = edgeorder[info.edgenrs[i]];
1906
if (eorder >= 2)
1907
{
1908
int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;
1909
if (el[vi1] > el[vi2]) swap (vi1, vi2);
1910
1911
CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));
1912
ii += eorder-1;
1913
}
1914
}
1915
const ELEMENT_FACE * faces = MeshTopology::GetFaces (TET);
1916
for (int i = 0; i < 4; i++)
1917
{
1918
int forder = faceorder[info.facenrs[i]];
1919
if (forder >= 3)
1920
{
1921
int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };
1922
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
1923
if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);
1924
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
1925
1926
CalcScaledTrigShape (forder,
1927
shapes(fnums[1])-shapes(fnums[0]), shapes(fnums[2]),
1928
shapes(fnums[0])+shapes(fnums[1])+shapes(fnums[2]), &shapes(ii));
1929
ii += (forder-1)*(forder-2)/2;
1930
// CalcScaledEdgeShape (forder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));
1931
// ii += forder-1;
1932
}
1933
}
1934
1935
1936
break;
1937
}
1938
case PRISM:
1939
{
1940
double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) };
1941
double lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) };
1942
for (int i = 0; i < 6; i++)
1943
shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) );
1944
for (int i = 6; i < info.ndof; i++)
1945
shapes(i) = 0;
1946
1947
if (info.order == 1) return;
1948
1949
1950
int ii = 6;
1951
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PRISM);
1952
for (int i = 0; i < 6; i++) // horizontal edges
1953
{
1954
int eorder = edgeorder[info.edgenrs[i]];
1955
if (eorder >= 2)
1956
{
1957
int vi1 = (edges[i][0]-1) % 3, vi2 = (edges[i][1]-1) % 3;
1958
if (el[vi1] > el[vi2]) swap (vi1, vi2);
1959
1960
CalcScaledEdgeShape (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapes(ii));
1961
double facz = (i < 3) ? (1-xi(2)) : xi(2);
1962
for (int j = 0; j < eorder-1; j++)
1963
shapes(ii+j) *= facz;
1964
1965
ii += eorder-1;
1966
}
1967
}
1968
1969
for (int i = 6; i < 9; i++) // vertical edges
1970
{
1971
int eorder = edgeorder[info.edgenrs[i]];
1972
if (eorder >= 2)
1973
{
1974
int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);
1975
if (el[vi1] > el[vi2]) swap (vi1, vi2);
1976
1977
double bubz = lamiz[vi1]*lamiz[vi2];
1978
double polyz = lamiz[vi1] - lamiz[vi2];
1979
double bubxy = lami[(vi1)%3];
1980
1981
for (int j = 0; j < eorder-1; j++)
1982
{
1983
shapes(ii+j) = bubxy * bubz;
1984
bubz *= polyz;
1985
}
1986
ii += eorder-1;
1987
}
1988
}
1989
1990
// FACE SHAPES
1991
const ELEMENT_FACE * faces = MeshTopology::GetFaces (PRISM);
1992
for (int i = 0; i < 2; i++)
1993
{
1994
int forder = faceorder[info.facenrs[i]];
1995
if ( forder < 3 ) continue;
1996
int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };
1997
if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);
1998
if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]);
1999
if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);
2000
2001
CalcTrigShape (forder,
2002
lami[fav[2]]-lami[fav[1]], lami[fav[0]],
2003
&shapes(ii));
2004
2005
int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1);
2006
for ( int j = 0; j < ndf; j++ )
2007
shapes(ii+j) *= lamiz[fav[1]];
2008
ii += ndf;
2009
}
2010
break;
2011
}
2012
2013
case PYRAMID:
2014
{
2015
shapes = 0.0;
2016
double x = xi(0);
2017
double y = xi(1);
2018
double z = xi(2);
2019
2020
if (z == 1.) z = 1-1e-10;
2021
shapes[0] = (1-z-x)*(1-z-y) / (1-z);
2022
shapes[1] = x*(1-z-y) / (1-z);
2023
shapes[2] = x*y / (1-z);
2024
shapes[3] = (1-z-x)*y / (1-z);
2025
shapes[4] = z;
2026
2027
if (info.order == 1) return;
2028
2029
int ii = 5;
2030
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PYRAMID);
2031
for (int i = 0; i < 4; i++) // horizontal edges
2032
{
2033
int eorder = edgeorder[info.edgenrs[i]];
2034
if (eorder >= 2)
2035
{
2036
int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);
2037
if (el[vi1] > el[vi2]) swap (vi1, vi2);
2038
2039
CalcScaledEdgeShape (eorder, shapes[vi1]-shapes[vi2], shapes[vi1]+shapes[vi2], &shapes(ii));
2040
double fac = (shapes[vi1]+shapes[vi2]) / (1-z);
2041
for (int j = 0; j < eorder-1; j++)
2042
shapes(ii+j) *= fac;
2043
2044
ii += eorder-1;
2045
}
2046
}
2047
2048
2049
2050
break;
2051
}
2052
2053
case HEX:
2054
{
2055
shapes = 0.0;
2056
double x = xi(0);
2057
double y = xi(1);
2058
double z = xi(2);
2059
2060
shapes[0] = (1-x)*(1-y)*(1-z);
2061
shapes[1] = x *(1-y)*(1-z);
2062
shapes[2] = x * y *(1-z);
2063
shapes[3] = (1-x)* y *(1-z);
2064
shapes[4] = (1-x)*(1-y)*(z);
2065
shapes[5] = x *(1-y)*(z);
2066
shapes[6] = x * y *(z);
2067
shapes[7] = (1-x)* y *(z);
2068
break;
2069
}
2070
};
2071
}
2072
2073
2074
void CurvedElements ::
2075
CalcElementDShapes (ElementInfo & info, const Point<3> & xi, MatrixFixWidth<3> & dshapes) const
2076
{
2077
const Element & el = mesh[info.elnr];
2078
2079
dshapes.SetSize(info.ndof);
2080
dshapes = 0.0;
2081
2082
2083
2084
if (rational && info.order >= 2)
2085
{
2086
double w = 1;
2087
double dw[3] = { 0, 0, 0 };
2088
2089
double lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };
2090
double dlami[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, -1, -1 }};
2091
double shapes[10];
2092
2093
for (int j = 0; j < 4; j++)
2094
{
2095
shapes[j] = lami[j] * lami[j];
2096
dshapes(j,0) = 2 * lami[j] * dlami[j][0];
2097
dshapes(j,1) = 2 * lami[j] * dlami[j][1];
2098
dshapes(j,2) = 2 * lami[j] * dlami[j][2];
2099
}
2100
2101
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);
2102
for (int j = 0; j < 6; j++)
2103
{
2104
double wi = edgeweight[info.edgenrs[j]];
2105
2106
shapes[j+4] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];
2107
for (int k = 0; k < 3; k++)
2108
dshapes(j+4,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +
2109
lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);
2110
2111
w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];
2112
for (int k = 0; k < 3; k++)
2113
dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +
2114
lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);
2115
}
2116
// shapes *= 1.0 / w;
2117
dshapes *= 1.0 / w;
2118
for (int i = 0; i < 10; i++)
2119
for (int j = 0; j < 3; j++)
2120
dshapes(i,j) -= shapes[i] * dw[j] / (w*w);
2121
return;
2122
}
2123
2124
switch (el.GetType())
2125
{
2126
case TET:
2127
{
2128
dshapes(0,0) = 1;
2129
dshapes(1,1) = 1;
2130
dshapes(2,2) = 1;
2131
dshapes(3,0) = -1;
2132
dshapes(3,1) = -1;
2133
dshapes(3,2) = -1;
2134
2135
if (info.order == 1) return;
2136
2137
double lami[] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };
2138
int ii = 4;
2139
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);
2140
for (int i = 0; i < 6; i++)
2141
{
2142
int eorder = edgeorder[info.edgenrs[i]];
2143
if (eorder >= 2)
2144
{
2145
int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;
2146
if (el[vi1] > el[vi2]) swap (vi1, vi2);
2147
2148
CalcScaledEdgeShapeDxDt<3> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0));
2149
2150
Mat<2,3> trans;
2151
for (int j = 0; j < 3; j++)
2152
{
2153
trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j);
2154
trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j);
2155
}
2156
2157
for (int j = 0; j < order-1; j++)
2158
{
2159
double ddx = dshapes(ii+j,0);
2160
double ddt = dshapes(ii+j,1);
2161
dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);
2162
dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);
2163
dshapes(ii+j,2) = ddx * trans(0,2) + ddt * trans(1,2);
2164
}
2165
2166
ii += eorder-1;
2167
}
2168
}
2169
2170
const ELEMENT_FACE * faces = MeshTopology::GetFaces (TET);
2171
for (int i = 0; i < 4; i++)
2172
{
2173
int forder = faceorder[info.facenrs[i]];
2174
if (forder >= 3)
2175
{
2176
int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };
2177
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
2178
if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);
2179
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
2180
2181
CalcScaledTrigShapeDxDyDt (forder,
2182
lami[fnums[1]]-lami[fnums[0]],
2183
lami[fnums[2]], lami[fnums[0]]+lami[fnums[1]]+lami[fnums[2]],
2184
&dshapes(ii,0));
2185
2186
Mat<3,3> trans;
2187
for (int j = 0; j < 3; j++)
2188
{
2189
trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j);
2190
trans(1,j) = dshapes(fnums[2],j);
2191
trans(2,j) = dshapes(fnums[0],j)+dshapes(fnums[1],j)+dshapes(fnums[2],j);
2192
}
2193
2194
int nfd = (forder-1)*(forder-2)/2;
2195
for (int j = 0; j < nfd; j++)
2196
{
2197
double ddx = dshapes(ii+j,0);
2198
double ddy = dshapes(ii+j,1);
2199
double ddt = dshapes(ii+j,2);
2200
dshapes(ii+j,0) = ddx * trans(0,0) + ddy * trans(1,0) + ddt * trans(2,0);
2201
dshapes(ii+j,1) = ddx * trans(0,1) + ddy * trans(1,1) + ddt * trans(2,1);
2202
dshapes(ii+j,2) = ddx * trans(0,2) + ddy * trans(1,2) + ddt * trans(2,2);
2203
}
2204
2205
ii += nfd;
2206
}
2207
}
2208
2209
break;
2210
}
2211
case PRISM:
2212
{
2213
double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) };
2214
double lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) };
2215
double dlamiz[6] = { -1, -1, -1, 1, 1, 1 };
2216
double dlami[6][2] =
2217
{ { 1, 0, },
2218
{ 0, 1, },
2219
{ -1, -1 },
2220
{ 1, 0, },
2221
{ 0, 1, },
2222
{ -1, -1 } };
2223
for (int i = 0; i < 6; i++)
2224
{
2225
// shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) );
2226
dshapes(i,0) = dlami[i%3][0] * ( (i < 3) ? (1-xi(2)) : xi(2) );
2227
dshapes(i,1) = dlami[i%3][1] * ( (i < 3) ? (1-xi(2)) : xi(2) );
2228
dshapes(i,2) = lami[i%3] * ( (i < 3) ? -1 : 1 );
2229
}
2230
2231
int ii = 6;
2232
2233
if (info.order == 1) return;
2234
2235
2236
const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PRISM);
2237
for (int i = 0; i < 6; i++) // horizontal edges
2238
{
2239
int order = edgeorder[info.edgenrs[i]];
2240
if (order >= 2)
2241
{
2242
int vi1 = (edges[i][0]-1) % 3, vi2 = (edges[i][1]-1) % 3;
2243
if (el[vi1] > el[vi2]) swap (vi1, vi2);
2244
2245
Vector shapei(order+1);
2246
CalcScaledEdgeShapeDxDt<3> (order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0) );
2247
CalcScaledEdgeShape(order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapei(0) );
2248
2249
Mat<2,2> trans;
2250
for (int j = 0; j < 2; j++)
2251
{
2252
trans(0,j) = dlami[vi1][j]-dlami[vi2][j];
2253
trans(1,j) = dlami[vi1][j]+dlami[vi2][j];
2254
}
2255
2256
for (int j = 0; j < order-1; j++)
2257
{
2258
double ddx = dshapes(ii+j,0);
2259
double ddt = dshapes(ii+j,1);
2260
dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);
2261
dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);
2262
}
2263
2264
2265
2266
double facz = (i < 3) ? (1-xi(2)) : xi(2);
2267
double dfacz = (i < 3) ? (-1) : 1;
2268
for (int j = 0; j < order-1; j++)
2269
{
2270
dshapes(ii+j,0) *= facz;
2271
dshapes(ii+j,1) *= facz;
2272
dshapes(ii+j,2) = shapei(j) * dfacz;
2273
}
2274
2275
ii += order-1;
2276
}
2277
}
2278
for (int i = 6; i < 9; i++) // vertical edges
2279
{
2280
int eorder = edgeorder[info.edgenrs[i]];
2281
if (eorder >= 2)
2282
{
2283
int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);
2284
if (el[vi1] > el[vi2]) swap (vi1, vi2);
2285
2286
double bubz = lamiz[vi1] * lamiz[vi2];
2287
double dbubz = dlamiz[vi1]*lamiz[vi2] + lamiz[vi1]*dlamiz[vi2];
2288
double polyz = lamiz[vi1] - lamiz[vi2];
2289
double dpolyz = dlamiz[vi1] - dlamiz[vi2];
2290
double bubxy = lami[(vi1)%3];
2291
double dbubxydx = dlami[(vi1)%3][0];
2292
double dbubxydy = dlami[(vi1)%3][1];
2293
2294
for (int j = 0; j < eorder-1; j++)
2295
{
2296
dshapes(ii+j,0) = dbubxydx * bubz;
2297
dshapes(ii+j,1) = dbubxydy * bubz;
2298
dshapes(ii+j,2) = bubxy * dbubz;
2299
2300
dbubz = bubz * dpolyz + dbubz * polyz;
2301
bubz *= polyz;
2302
}
2303
ii += eorder-1;
2304
}
2305
}
2306
2307
2308
if (info.order == 2) return;
2309
// FACE SHAPES
2310
const ELEMENT_FACE * faces = MeshTopology::GetFaces (PRISM);
2311
for (int i = 0; i < 2; i++)
2312
{
2313
int forder = faceorder[info.facenrs[i]];
2314
if ( forder < 3 ) continue;
2315
int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1);
2316
2317
int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };
2318
if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);
2319
if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]);
2320
if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);
2321
2322
MatrixFixWidth<2> dshapei(ndf);
2323
Vector shapei(ndf);
2324
2325
CalcTrigShapeDxDy (forder,
2326
lami[fav[2]]-lami[fav[1]], lami[fav[0]],
2327
&dshapei(0,0));
2328
CalcTrigShape (forder, lami[fav[2]]-lami[fav[1]], lami[fav[0]],
2329
&shapei(0));
2330
2331
Mat<2,2> trans;
2332
for (int j = 0; j < 2; j++)
2333
{
2334
trans(0,j) = dlami[fav[2]][j]-dlami[fav[1]][j];
2335
trans(1,j) = dlami[fav[0]][j];
2336
}
2337
2338
for (int j = 0; j < order-1; j++)
2339
{
2340
double ddx = dshapes(ii+j,0);
2341
double ddt = dshapes(ii+j,1);
2342
dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);
2343
dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);
2344
}
2345
2346
for ( int j = 0; j < ndf; j++ )
2347
{
2348
dshapes(ii+j,0) *= lamiz[fav[1]];
2349
dshapes(ii+j,1) *= lamiz[fav[1]];
2350
dshapes(ii+j,2) = shapei(j) * dlamiz[fav[1]];
2351
}
2352
ii += ndf;
2353
}
2354
2355
break;
2356
2357
}
2358
2359
case PYRAMID:
2360
{
2361
dshapes = 0.0;
2362
double x = xi(0);
2363
double y = xi(1);
2364
double z = xi(2);
2365
2366
if (z == 1.) z = 1-1e-10;
2367
double z1 = 1-z;
2368
double z2 = z1*z1;
2369
2370
dshapes(0,0) = -(z1-y)/z1;
2371
dshapes(0,1) = -(z1-x)/z1;
2372
dshapes(0,2) = ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2;
2373
2374
dshapes(1,0) = (z1-y)/z1;
2375
dshapes(1,1) = -x/z1;
2376
dshapes(1,2) = (-x*z1+x*(z1-y))/z2;
2377
2378
dshapes(2,0) = y/z1;
2379
dshapes(2,1) = x/z1;
2380
dshapes(2,2) = x*y/z2;
2381
2382
dshapes(3,0) = -y/z1;
2383
dshapes(3,1) = (z1-x)/z1;
2384
dshapes(3,2) = (-y*z1+y*(z1-x))/z2;
2385
2386
dshapes(4,0) = 0;
2387
dshapes(4,1) = 0;
2388
dshapes(4,2) = 1;
2389
/* old:
2390
vdshape[0] = Vec<3>( -(z1-y)/z1, -(z1-x)/z1, ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2 );
2391
vdshape[1] = Vec<3>( (z1-y)/z1, -x/z1, (-x*z1+x*(z1-y))/z2 );
2392
vdshape[2] = Vec<3>( y/z1, x/z1, x*y/z2 );
2393
vdshape[3] = Vec<3>( -y/z1, (z1-x)/z1, (-y*z1+y*(z1-x))/z2 );
2394
vdshape[4] = Vec<3>( 0, 0, 1 );
2395
*/
2396
break;
2397
}
2398
2399
case HEX:
2400
{
2401
dshapes = 0.0;
2402
2403
double x = xi(0);
2404
double y = xi(1);
2405
double z = xi(2);
2406
2407
// shapes[0] = (1-x)*(1-y)*(1-z);
2408
dshapes(0,0) = - (1-y)*(1-z);
2409
dshapes(0,1) = (1-x) * (-1) * (1-z);
2410
dshapes(0,2) = (1-x) * (1-y) * (-1);
2411
2412
// shapes[1] = x *(1-y)*(1-z);
2413
dshapes(1,0) = (1-y)*(1-z);
2414
dshapes(1,1) = -x * (1-z);
2415
dshapes(1,2) = -x * (1-y);
2416
2417
// shapes[2] = x * y *(1-z);
2418
dshapes(2,0) = y * (1-z);
2419
dshapes(2,1) = x * (1-z);
2420
dshapes(2,2) = -x * y;
2421
2422
// shapes[3] = (1-x)* y *(1-z);
2423
dshapes(3,0) = -y * (1-z);
2424
dshapes(3,1) = (1-x) * (1-z);
2425
dshapes(3,2) = -(1-x) * y;
2426
2427
// shapes[4] = (1-x)*(1-y)*z;
2428
dshapes(4,0) = - (1-y)*z;
2429
dshapes(4,1) = (1-x) * (-1) * z;
2430
dshapes(4,2) = (1-x) * (1-y) * 1;
2431
2432
// shapes[5] = x *(1-y)*z;
2433
dshapes(5,0) = (1-y)*z;
2434
dshapes(5,1) = -x * z;
2435
dshapes(5,2) = x * (1-y);
2436
2437
// shapes[6] = x * y *z;
2438
dshapes(6,0) = y * z;
2439
dshapes(6,1) = x * z;
2440
dshapes(6,2) = x * y;
2441
2442
// shapes[7] = (1-x)* y *z;
2443
dshapes(7,0) = -y * z;
2444
dshapes(7,1) = (1-x) * z;
2445
dshapes(7,2) = (1-x) * y;
2446
2447
break;
2448
}
2449
}
2450
2451
/*
2452
DenseMatrix dshapes2 (info.ndof, 3);
2453
Vector shapesl(info.ndof);
2454
Vector shapesr(info.ndof);
2455
2456
double eps = 1e-6;
2457
for (int i = 0; i < 3; i++)
2458
{
2459
Point<3> xl = xi;
2460
Point<3> xr = xi;
2461
2462
xl(i) -= eps;
2463
xr(i) += eps;
2464
CalcElementShapes (info, xl, shapesl);
2465
CalcElementShapes (info, xr, shapesr);
2466
2467
for (int j = 0; j < info.ndof; j++)
2468
dshapes2(j,i) = (shapesr(j)-shapesl(j)) / (2*eps);
2469
}
2470
(*testout) << "dshapes = " << endl << dshapes << endl;
2471
(*testout) << "dshapes2 = " << endl << dshapes2 << endl;
2472
dshapes2 -= dshapes;
2473
(*testout) << "diff = " << endl << dshapes2 << endl;
2474
*/
2475
}
2476
2477
2478
2479
void CurvedElements ::
2480
GetCoefficients (ElementInfo & info, Vec<3> * coefs) const
2481
{
2482
// cout << "getcoeffs, info.elnr = " << info.elnr << endl;
2483
// cout << "getcoeffs, info.nv = " << info.nv << endl;
2484
2485
const Element & el = mesh[info.elnr];
2486
2487
/*
2488
coefs.SetSize (info.ndof);
2489
coefs = Vec<3> (0,0,0);
2490
*/
2491
/*
2492
for (int i = 0; i < info.ndof; i++)
2493
coefs[i] = Vec<3> (0,0,0);
2494
*/
2495
for (int i = 0; i < info.nv; i++)
2496
coefs[i] = Vec<3> (mesh[el[i]]);
2497
2498
if (info.order == 1) return;
2499
2500
int ii = info.nv;
2501
2502
for (int i = 0; i < info.nedges; i++)
2503
{
2504
int first = edgecoeffsindex[info.edgenrs[i]];
2505
int next = edgecoeffsindex[info.edgenrs[i]+1];
2506
for (int j = first; j < next; j++, ii++)
2507
coefs[ii] = edgecoeffs[j];
2508
}
2509
for (int i = 0; i < info.nfaces; i++)
2510
{
2511
int first = facecoeffsindex[info.facenrs[i]];
2512
int next = facecoeffsindex[info.facenrs[i]+1];
2513
for (int j = first; j < next; j++, ii++)
2514
coefs[ii] = facecoeffs[j];
2515
}
2516
}
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
void CurvedElements ::
2549
CalcMultiPointSegmentTransformation (ARRAY<double> * xi, SegmentIndex segnr,
2550
ARRAY<Point<3> > * x,
2551
ARRAY<Vec<3> > * dxdxi)
2552
{
2553
;
2554
}
2555
2556
void CurvedElements ::
2557
CalcMultiPointSurfaceTransformation (ARRAY< Point<2> > * xi, SurfaceElementIndex elnr,
2558
ARRAY< Point<3> > * x,
2559
ARRAY< Mat<3,2> > * dxdxi)
2560
{
2561
if (mesh.coarsemesh)
2562
{
2563
const HPRefElement & hpref_el =
2564
(*mesh.hpelements) [mesh[elnr].hp_elnr];
2565
2566
// xi umrechnen
2567
double lami[4];
2568
FlatVector vlami(4, lami);
2569
2570
ArrayMem<Point<2>, 50> coarse_xi (xi->Size());
2571
2572
for (int pi = 0; pi < xi->Size(); pi++)
2573
{
2574
vlami = 0;
2575
mesh[elnr].GetShapeNew ( (*xi)[pi], vlami);
2576
2577
Point<2> cxi(0,0);
2578
for (int i = 0; i < hpref_el.np; i++)
2579
for (int j = 0; j < 2; j++)
2580
cxi(j) += hpref_el.param[i][j] * lami[i];
2581
2582
coarse_xi[pi] = cxi;
2583
}
2584
2585
mesh.coarsemesh->GetCurvedElements().
2586
CalcMultiPointSurfaceTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi);
2587
2588
2589
Mat<2,2> trans;
2590
Mat<3,2> dxdxic;
2591
if (dxdxi)
2592
{
2593
MatrixFixWidth<2> dlami(4);
2594
dlami = 0;
2595
2596
for (int pi = 0; pi < xi->Size(); pi++)
2597
{
2598
mesh[elnr].GetDShapeNew ( (*xi)[pi], dlami);
2599
2600
trans = 0;
2601
for (int k = 0; k < 2; k++)
2602
for (int l = 0; l < 2; l++)
2603
for (int i = 0; i < hpref_el.np; i++)
2604
trans(l,k) += hpref_el.param[i][l] * dlami(i, k);
2605
2606
dxdxic = (*dxdxi)[pi];
2607
(*dxdxi)[pi] = dxdxic * trans;
2608
}
2609
}
2610
2611
return;
2612
}
2613
2614
2615
2616
2617
2618
Vector shapes;
2619
DenseMatrix dshapes;
2620
ARRAY<Vec<3> > coefs;
2621
2622
2623
const Element2d & el = mesh[elnr];
2624
ELEMENT_TYPE type = el.GetType();
2625
2626
SurfaceElementInfo info;
2627
info.elnr = elnr;
2628
info.order = order;
2629
info.ndof = info.nv = (type == TRIG) ? 3 : 4;
2630
if (info.order > 1)
2631
{
2632
const MeshTopology & top = mesh.GetTopology();
2633
2634
top.GetSurfaceElementEdges (elnr+1, info.edgenrs);
2635
for (int i = 0; i < info.edgenrs.Size(); i++)
2636
info.edgenrs[i]--;
2637
info.facenr = top.GetSurfaceElementFace (elnr+1)-1;
2638
2639
for (int i = 0; i < info.edgenrs.Size(); i++)
2640
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
2641
info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];
2642
}
2643
2644
GetCoefficients (info, coefs);
2645
2646
if (x)
2647
{
2648
for (int j = 0; j < xi->Size(); j++)
2649
{
2650
CalcElementShapes (info, (*xi)[j], shapes);
2651
(*x)[j] = 0;
2652
for (int i = 0; i < coefs.Size(); i++)
2653
(*x)[j] += shapes(i) * coefs[i];
2654
}
2655
}
2656
2657
if (dxdxi)
2658
{
2659
for (int ip = 0; ip < xi->Size(); ip++)
2660
{
2661
CalcElementDShapes (info, (*xi)[ip], dshapes);
2662
2663
(*dxdxi)[ip] = 0;
2664
for (int i = 0; i < coefs.Size(); i++)
2665
for (int j = 0; j < 3; j++)
2666
for (int k = 0; k < 2; k++)
2667
(*dxdxi)[ip](j,k) += dshapes(i,k) * coefs[i](j);
2668
}
2669
}
2670
}
2671
2672
void CurvedElements ::
2673
CalcMultiPointElementTransformation (ARRAY< Point<3> > * xi, ElementIndex elnr,
2674
ARRAY< Point<3> > * x,
2675
ARRAY< Mat<3,3> > * dxdxi)
2676
{
2677
if (mesh.coarsemesh)
2678
{
2679
const HPRefElement & hpref_el =
2680
(*mesh.hpelements) [mesh[elnr].hp_elnr];
2681
2682
// xi umrechnen
2683
double lami[8];
2684
FlatVector vlami(8, lami);
2685
2686
2687
ArrayMem<Point<3>, 50> coarse_xi (xi->Size());
2688
2689
for (int pi = 0; pi < xi->Size(); pi++)
2690
{
2691
vlami = 0;
2692
mesh[elnr].GetShapeNew ( (*xi)[pi], vlami);
2693
2694
Point<3> cxi(0,0,0);
2695
for (int i = 0; i < hpref_el.np; i++)
2696
for (int j = 0; j < 3; j++)
2697
cxi(j) += hpref_el.param[i][j] * lami[i];
2698
2699
coarse_xi[pi] = cxi;
2700
}
2701
2702
mesh.coarsemesh->GetCurvedElements().
2703
CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi);
2704
2705
2706
Mat<3,3> trans, dxdxic;
2707
if (dxdxi)
2708
{
2709
MatrixFixWidth<3> dlami(8);
2710
dlami = 0;
2711
2712
for (int pi = 0; pi < xi->Size(); pi++)
2713
{
2714
mesh[elnr].GetDShapeNew ( (*xi)[pi], dlami);
2715
2716
trans = 0;
2717
for (int k = 0; k < 3; k++)
2718
for (int l = 0; l < 3; l++)
2719
for (int i = 0; i < hpref_el.np; i++)
2720
trans(l,k) += hpref_el.param[i][l] * dlami(i, k);
2721
2722
dxdxic = (*dxdxi)[pi];
2723
(*dxdxi)[pi] = dxdxic * trans;
2724
}
2725
}
2726
2727
return;
2728
}
2729
2730
2731
2732
2733
2734
2735
2736
2737
Vector shapes;
2738
MatrixFixWidth<3> dshapes;
2739
2740
2741
const Element & el = mesh[elnr];
2742
ELEMENT_TYPE type = el.GetType();
2743
2744
ElementInfo info;
2745
info.elnr = elnr;
2746
info.order = order;
2747
info.ndof = info.nv = MeshTopology::GetNVertices (type);
2748
if (info.order > 1)
2749
{
2750
const MeshTopology & top = mesh.GetTopology();
2751
2752
info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);
2753
for (int i = 0; i < info.nedges; i++)
2754
info.edgenrs[i]--;
2755
2756
info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);
2757
for (int i = 0; i < info.nfaces; i++)
2758
info.facenrs[i]--;
2759
2760
for (int i = 0; i < info.nedges; i++)
2761
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
2762
for (int i = 0; i < info.nfaces; i++)
2763
info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];
2764
// info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];
2765
}
2766
2767
ARRAY<Vec<3> > coefs(info.ndof);
2768
GetCoefficients (info, &coefs[0]);
2769
if (x)
2770
{
2771
for (int j = 0; j < xi->Size(); j++)
2772
{
2773
CalcElementShapes (info, (*xi)[j], shapes);
2774
(*x)[j] = 0;
2775
for (int i = 0; i < coefs.Size(); i++)
2776
(*x)[j] += shapes(i) * coefs[i];
2777
}
2778
}
2779
if (dxdxi)
2780
{
2781
for (int ip = 0; ip < xi->Size(); ip++)
2782
{
2783
CalcElementDShapes (info, (*xi)[ip], dshapes);
2784
2785
(*dxdxi)[ip] = 0;
2786
for (int i = 0; i < coefs.Size(); i++)
2787
for (int j = 0; j < 3; j++)
2788
for (int k = 0; k < 3; k++)
2789
(*dxdxi)[ip](j,k) += dshapes(i,k) * coefs[i](j);
2790
}
2791
}
2792
}
2793
2794
2795
2796
2797
void CurvedElements ::
2798
CalcMultiPointElementTransformation (ElementIndex elnr, int n,
2799
const double * xi, int sxi,
2800
double * x, int sx,
2801
double * dxdxi, int sdxdxi)
2802
{
2803
if (mesh.coarsemesh)
2804
{
2805
const HPRefElement & hpref_el =
2806
(*mesh.hpelements) [mesh[elnr].hp_elnr];
2807
2808
// xi umrechnen
2809
double lami[8];
2810
FlatVector vlami(8, lami);
2811
2812
2813
ArrayMem<double, 100> coarse_xi (3*n);
2814
2815
for (int pi = 0; pi < n; pi++)
2816
{
2817
vlami = 0;
2818
Point<3> pxi;
2819
for (int j = 0; j < 3; j++)
2820
pxi(j) = xi[pi*sxi+j];
2821
2822
mesh[elnr].GetShapeNew ( pxi, vlami);
2823
2824
Point<3> cxi(0,0,0);
2825
for (int i = 0; i < hpref_el.np; i++)
2826
for (int j = 0; j < 3; j++)
2827
cxi(j) += hpref_el.param[i][j] * lami[i];
2828
2829
for (int j = 0; j < 3; j++)
2830
coarse_xi[3*pi+j] = cxi(j);
2831
}
2832
2833
mesh.coarsemesh->GetCurvedElements().
2834
CalcMultiPointElementTransformation (hpref_el.coarse_elnr, n,
2835
&coarse_xi[0], 3,
2836
x, sx,
2837
dxdxi, sdxdxi);
2838
2839
Mat<3,3> trans, dxdxic;
2840
if (dxdxi)
2841
{
2842
MatrixFixWidth<3> dlami(8);
2843
dlami = 0;
2844
2845
for (int pi = 0; pi < n; pi++)
2846
{
2847
Point<3> pxi;
2848
for (int j = 0; j < 3; j++)
2849
pxi(j) = xi[pi*sxi+j];
2850
2851
mesh[elnr].GetDShapeNew (pxi, dlami);
2852
2853
trans = 0;
2854
for (int k = 0; k < 3; k++)
2855
for (int l = 0; l < 3; l++)
2856
for (int i = 0; i < hpref_el.np; i++)
2857
trans(l,k) += hpref_el.param[i][l] * dlami(i, k);
2858
2859
Mat<3> mat_dxdxic, mat_dxdxi;
2860
for (int j = 0; j < 3; j++)
2861
for (int k = 0; k < 3; k++)
2862
mat_dxdxic(j,k) = dxdxi[pi*sdxdxi+3*j+k];
2863
2864
mat_dxdxi = mat_dxdxic * trans;
2865
2866
for (int j = 0; j < 3; j++)
2867
for (int k = 0; k < 3; k++)
2868
dxdxi[pi*sdxdxi+3*j+k] = mat_dxdxi(j,k);
2869
2870
// dxdxic = (*dxdxi)[pi];
2871
// (*dxdxi)[pi] = dxdxic * trans;
2872
}
2873
}
2874
return;
2875
}
2876
2877
2878
2879
2880
2881
2882
2883
2884
Vector shapes;
2885
MatrixFixWidth<3> dshapes;
2886
2887
2888
const Element & el = mesh[elnr];
2889
ELEMENT_TYPE type = el.GetType();
2890
2891
ElementInfo info;
2892
info.elnr = elnr;
2893
info.order = order;
2894
info.ndof = info.nv = MeshTopology::GetNVertices (type);
2895
if (info.order > 1)
2896
{
2897
const MeshTopology & top = mesh.GetTopology();
2898
2899
info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);
2900
for (int i = 0; i < info.nedges; i++)
2901
info.edgenrs[i]--;
2902
2903
info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);
2904
for (int i = 0; i < info.nfaces; i++)
2905
info.facenrs[i]--;
2906
2907
for (int i = 0; i < info.nedges; i++)
2908
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
2909
for (int i = 0; i < info.nfaces; i++)
2910
info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];
2911
// info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];
2912
}
2913
2914
ARRAY<Vec<3> > coefs(info.ndof);
2915
GetCoefficients (info, &coefs[0]);
2916
if (x)
2917
{
2918
for (int j = 0; j < n; j++)
2919
{
2920
Point<3> xij, xj;
2921
for (int k = 0; k < 3; k++)
2922
xij(k) = xi[j*sxi+k];
2923
2924
CalcElementShapes (info, xij, shapes);
2925
xj = 0;
2926
for (int i = 0; i < coefs.Size(); i++)
2927
xj += shapes(i) * coefs[i];
2928
2929
for (int k = 0; k < 3; k++)
2930
x[j*sx+k] = xj(k);
2931
}
2932
}
2933
if (dxdxi)
2934
{
2935
for (int ip = 0; ip < n; ip++)
2936
{
2937
Point<3> xij;
2938
for (int k = 0; k < 3; k++)
2939
xij(k) = xi[ip*sxi+k];
2940
2941
CalcElementDShapes (info, xij, dshapes);
2942
2943
Mat<3> dxdxij;
2944
dxdxij = 0.0;
2945
for (int i = 0; i < coefs.Size(); i++)
2946
for (int j = 0; j < 3; j++)
2947
for (int k = 0; k < 3; k++)
2948
dxdxij(j,k) += dshapes(i,k) * coefs[i](j);
2949
2950
2951
for (int j = 0; j < 3; j++)
2952
for (int k = 0; k < 3; k++)
2953
dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k);
2954
}
2955
}
2956
}
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
};
2967
2968
2969
#endif
2970
2971