Path: blob/devel/ElmerGUI/netgen/libsrc/meshing/curvedelems_new.cpp
3206 views
#include <mystdlib.h>12#include "meshing.hpp"3#ifdef CURVEDELEMS_NEW45#include "../general/autodiff.hpp"678namespace netgen9{1011// bool rational = true;12131415static void ComputeGaussRule (int n, ARRAY<double> & xi, ARRAY<double> & wi)16{17xi.SetSize (n);18wi.SetSize (n);1920int m = (n+1)/2;21double p1, p2, p3;22double pp, z, z1;23for (int i = 1; i <= m; i++)24{25z = cos ( M_PI * (i - 0.25) / (n + 0.5));26while(1)27{28p1 = 1; p2 = 0;29for (int j = 1; j <= n; j++)30{31p3 = p2; p2 = p1;32p1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j;33}34// p1 is legendre polynomial3536pp = n * (z*p1-p2) / (z*z - 1);37z1 = z;38z = z1-p1/pp;3940if (fabs (z - z1) < 1e-14) break;41}4243xi[i-1] = 0.5 * (1 - z);44xi[n-i] = 0.5 * (1 + z);45wi[i-1] = wi[n-i] = 1.0 / ( (1 - z * z) * pp * pp);46}47}48495051// compute edge bubbles up to order n, x \in (-1, 1)52static void CalcEdgeShape (int n, double x, double * shape)53{54double p1 = x, p2 = -1, p3 = 0;55for (int j=2; j<=n; j++)56{57p3=p2; p2=p1;58p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;59shape[j-2] = p1;60}61}6263static void CalcEdgeDx (int n, double x, double * dshape)64{65double p1 = x, p2 = -1, p3 = 0;66double p1dx = 1, p2dx = 0, p3dx = 0;6768for (int j=2; j<=n; j++)69{70p3=p2; p2=p1;71p3dx = p2dx; p2dx = p1dx;7273p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;74p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j;7576dshape[j-2] = p1dx;77}78}7980static void CalcEdgeShapeDx (int n, double x, double * shape, double * dshape)81{82double p1 = x, p2 = -1, p3 = 0;83double p1dx = 1, p2dx = 0, p3dx = 0;8485for (int j=2; j<=n; j++)86{87p3=p2; p2=p1;88p3dx = p2dx; p2dx = p1dx;8990p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;91p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j;9293shape[j-2] = p1;94dshape[j-2] = p1dx;95}96}9798// compute L_i(x/t) * t^i99static void CalcScaledEdgeShape (int n, double x, double t, double * shape)100{101double p1 = x, p2 = -1, p3 = 0;102for (int j=0; j<=n-2; j++)103{104p3=p2; p2=p1;105p1=( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2);106shape[j] = p1;107}108}109110template <int DIST>111static void CalcScaledEdgeShapeDxDt (int n, double x, double t, double * dshape)112{113double p1 = x, p2 = -1, p3 = 0;114double p1dx = 1, p1dt = 0;115double p2dx = 0, p2dt = 0;116double p3dx = 0, p3dt = 0;117118for (int j=0; j<=n-2; j++)119{120p3=p2; p3dx=p2dx; p3dt = p2dt;121p2=p1; p2dx=p1dx; p2dt = p1dt;122123p1 = ( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2);124p1dx = ( (2*j+1) * (x * p2dx + p2) - t*t*(j-1) * p3dx) / (j+2);125p1dt = ( (2*j+1) * x * p2dt - (j-1)* (t*t*p3dt+2*t*p3)) / (j+2);126127// shape[j] = p1;128dshape[DIST*j ] = p1dx;129dshape[DIST*j+1] = p1dt;130}131}132133134template <class Tx, class Tres>135static void LegendrePolynomial (int n, Tx x, Tres * values)136{137switch (n)138{139case 0:140values[0] = 1;141break;142case 1:143values[0] = 1;144values[1] = x;145break;146147default:148149if (n < 0) return;150151Tx p1 = 1.0, p2 = 0.0, p3;152153values[0] = 1.0;154for (int j=1; j<=n; j++)155{156p3 = p2; p2 = p1;157p1 = ((2.0*j-1.0)*x*p2 - (j-1.0)*p3) / j;158values[j] = p1;159}160}161}162163template <class Tx, class Tt, class Tres>164static void ScaledLegendrePolynomial (int n, Tx x, Tt t, Tres * values)165{166switch (n)167{168case 0:169values[0] = 1.0;170break;171172case 1:173values[0] = 1.0;174values[1] = x;175break;176177default:178179if (n < 0) return;180181Tx p1 = 1.0, p2 = 0.0, p3;182values[0] = 1.0;183for (int j=1; j<=n; j++)184{185p3 = p2; p2 = p1;186p1 = ((2.0*j-1.0)*x*p2 - t*t*(j-1.0)*p3) / j;187values[j] = p1;188}189}190}191192193194template <class S, class T>195inline void JacobiPolynomial (int n, S x, double alpha, double beta, T * values)196{197S p1 = 1.0, p2 = 0.0, p3;198199if (n >= 0)200p2 = values[0] = 1.0;201if (n >= 1)202p1 = values[1] = 0.5 * (2*(alpha+1)+(alpha+beta+2)*(x-1));203204for (int i = 1; i < n; i++)205{206p3 = p2; p2=p1;207p1 =2081.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *209(210( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) +211(2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)212* p2213- 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * p3214);215values[i+1] = p1;216}217}218219220221222template <class S, class St, class T>223inline void ScaledJacobiPolynomial (int n, S x, St t, double alpha, double beta, T * values)224{225/*226S p1 = 1.0, p2 = 0.0, p3;227228if (n >= 0) values[0] = 1.0;229*/230231S p1 = 1.0, p2 = 0.0, p3;232233if (n >= 0)234p2 = values[0] = 1.0;235if (n >= 1)236p1 = values[1] = 0.5 * (2*(alpha+1)*t+(alpha+beta+2)*(x-t));237238for (int i=1; i < n; i++)239{240p3 = p2; p2=p1;241p1 =2421.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *243(244( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) * t +245(2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)246* p2247- 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * t * t * p3248);249values[i+1] = p1;250}251}252253254255256257// compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1258template <class Tx, class Ty, class Ts>259static void CalcTrigShape (int n, Tx x, Ty y, Ts * shape)260{261if (n < 3) return;262Tx hx[50], hy[50*50];263// ScaledLegendrePolynomial (n-3, 2*x-1, 1-y, hx);264ScaledJacobiPolynomial (n-3, x, 1-y, 2, 2, hx);265266267// LegendrePolynomial (n-3, 2*y-1, hy);268for (int ix = 0; ix <= n-3; ix++)269// JacobiPolynomial (n-3, 2*y-1, 0, 0, hy+50*ix);270JacobiPolynomial (n-3, 2*y-1, 2*ix+5, 2, hy+50*ix);271272int ii = 0;273Tx bub = (1+x-y)*y*(1-x-y);274for (int iy = 0; iy <= n-3; iy++)275for (int ix = 0; ix <= n-3-iy; ix++)276shape[ii++] = bub * hx[ix]*hy[iy+50*ix];277}278279280281static void CalcTrigShapeDxDy (int n, double x, double y, double * dshape)282{283if (n < 3) return;284285AutoDiff<2> adx(x, 0);286AutoDiff<2> ady(y, 1);287AutoDiff<2> res[2000];288CalcTrigShape (n, adx, ady, &res[0]);289int ndof = (n-1)*(n-2)/2;290for (int i = 0; i < ndof; i++)291{292dshape[2*i] = res[i].DValue(0);293dshape[2*i+1] = res[i].DValue(1);294}295296/*297if (n < 3) return;298299int ndof = (n-1)*(n-2)/2;300double h1[1000], h2[1000];301double eps = 1e-4;302303CalcTrigShape (n, x+eps, y, h1);304CalcTrigShape (n, x-eps, y, h2);305306for (int i = 0; i < ndof; i++)307dshape[2*i] = (h1[i]-h2[i])/(2*eps);308309CalcTrigShape (n, x, y+eps, h1);310CalcTrigShape (n, x, y-eps, h2);311312for (int i = 0; i < ndof; i++)313dshape[2*i+1] = (h1[i]-h2[i])/(2*eps);314*/315}316317318319320321322323324// compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1325template <class Tx, class Ty, class Tt, class Tr>326static void CalcScaledTrigShape (int n, Tx x, Ty y, Tt t, Tr * shape)327{328if (n < 3) return;329330Tx hx[50], hy[50*50];331// ScaledLegendrePolynomial (n-3, (2*x-1), t-y, hx);332ScaledJacobiPolynomial (n-3, x, t-y, 2, 2, hx);333334// ScaledLegendrePolynomial (n-3, (2*y-1), t, hy);335for (int ix = 0; ix <= n-3; ix++)336ScaledJacobiPolynomial (n-3, 2*y-1, t, 2*ix+5, 2, hy+50*ix);337338339int ii = 0;340Tx bub = (t+x-y)*y*(t-x-y);341for (int iy = 0; iy <= n-3; iy++)342for (int ix = 0; ix <= n-3-iy; ix++)343shape[ii++] = bub * hx[ix]*hy[iy+50*ix];344}345346347// compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1348static void CalcScaledTrigShapeDxDyDt (int n, double x, double y, double t, double * dshape)349{350if (n < 3) return;351AutoDiff<3> adx(x, 0);352AutoDiff<3> ady(y, 1);353AutoDiff<3> adt(t, 2);354AutoDiff<3> res[2000];355CalcScaledTrigShape (n, adx, ady, adt, &res[0]);356double dshape1[6000];357int ndof = (n-1)*(n-2)/2;358for (int i = 0; i < ndof; i++)359{360dshape[3*i] = res[i].DValue(0);361dshape[3*i+1] = res[i].DValue(1);362dshape[3*i+2] = res[i].DValue(2);363}364365/*366if (n < 3) return;367double hvl[1000], hvr[1000];368int nd = (n-1)*(n-2)/2;369370double eps = 1e-6;371372CalcScaledTrigShape (n, x-eps, y, t, hvl);373CalcScaledTrigShape (n, x+eps, y, t, hvr);374for (int i = 0; i < nd; i++)375dshape[3*i] = (hvr[i]-hvl[i])/(2*eps);376377CalcScaledTrigShape (n, x, y-eps, t, hvl);378CalcScaledTrigShape (n, x, y+eps, t, hvr);379for (int i = 0; i < nd; i++)380dshape[3*i+1] = (hvr[i]-hvl[i])/(2*eps);381382CalcScaledTrigShape (n, x, y, t-eps, hvl);383CalcScaledTrigShape (n, x, y, t+eps, hvr);384for (int i = 0; i < nd; i++)385dshape[3*i+2] = (hvr[i]-hvl[i])/(2*eps);386*/387388/*389for (int i = 0; i < 3*nd; i++)390if (fabs (dshape[i]-dshape1[i]) > 1e-8 * fabs(dshape[i]) + 1e-6)391{392cerr393cerr << "big difference: " << dshape1[i] << " != " << dshape[i] << endl;394}395*/396}397398399400401402CurvedElements :: CurvedElements (const Mesh & amesh)403: mesh (amesh)404{405order = 1;406rational = 0;407}408409410CurvedElements :: ~CurvedElements()411{412;413}414415416void CurvedElements :: BuildCurvedElements(Refinement * ref, int aorder,417bool arational)418{419order = aorder;420ishighorder = 0;421422if (mesh.coarsemesh)423{424mesh.coarsemesh->GetCurvedElements().BuildCurvedElements (ref, aorder, arational);425order = aorder;426rational = arational;427ishighorder = (order > 1);428return;429}430431PrintMessage (1, "Curve elements, order = ", aorder);432if (rational) PrintMessage (1, "curved elements with rational splines");433434const_cast<Mesh&> (mesh).UpdateTopology();435const MeshTopology & top = mesh.GetTopology();436437438rational = arational;439440ARRAY<int> edgenrs;441442edgeorder.SetSize (top.GetNEdges());443faceorder.SetSize (top.GetNFaces());444445edgeorder = 1;446faceorder = 1;447448if (rational)449{450edgeweight.SetSize (top.GetNEdges());451edgeweight = 1.0;452}453454455if (aorder <= 1) return;456457458if (rational) aorder = 2;459460461if (mesh.GetDimension() == 3)462for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)463{464top.GetSurfaceElementEdges (i+1, edgenrs);465for (int j = 0; j < edgenrs.Size(); j++)466edgeorder[edgenrs[j]-1] = aorder;467faceorder[top.GetSurfaceElementFace (i+1)-1] = aorder;468}469for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++)470edgeorder[top.GetSegmentEdge (i+1)-1] = aorder;471472if (rational)473{474edgeorder = 2;475faceorder = 1;476}477478479edgecoeffsindex.SetSize (top.GetNEdges()+1);480int nd = 0;481for (int i = 0; i < top.GetNEdges(); i++)482{483edgecoeffsindex[i] = nd;484nd += max (0, edgeorder[i]-1);485}486edgecoeffsindex[top.GetNEdges()] = nd;487488edgecoeffs.SetSize (nd);489edgecoeffs = Vec<3> (0,0,0);490491492facecoeffsindex.SetSize (top.GetNFaces()+1);493nd = 0;494for (int i = 0; i < top.GetNFaces(); i++)495{496facecoeffsindex[i] = nd;497if (top.GetFaceType(i+1) == TRIG)498nd += max (0, (faceorder[i]-1)*(faceorder[i]-2)/2);499else500nd += max (0, sqr(faceorder[i]-1));501}502facecoeffsindex[top.GetNFaces()] = nd;503504facecoeffs.SetSize (nd);505facecoeffs = Vec<3> (0,0,0);506507508if (!ref || aorder <= 1)509{510order = aorder;511return;512}513514ARRAY<double> xi, weight;515516ComputeGaussRule (aorder+4, xi, weight); // on (0,1)517518PrintMessage (3, "Curving edges");519520if (mesh.GetDimension() == 3 || rational)521for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)522{523SetThreadPercent(double(i)/mesh.GetNSE()*100.);524const Element2d & el = mesh[i];525top.GetSurfaceElementEdges (i+1, edgenrs);526for (int j = 0; j < edgenrs.Size(); j++)527edgenrs[j]--;528const ELEMENT_EDGE * edges = MeshTopology::GetEdges (el.GetType());529530for (int i2 = 0; i2 < edgenrs.Size(); i2++)531{532PointIndex pi1 = edges[i2][0]-1;533PointIndex pi2 = edges[i2][1]-1;534535bool swap = el[pi1] > el[pi2];536537Point<3> p1 = mesh[el[pi1]];538Point<3> p2 = mesh[el[pi2]];539540int order1 = edgeorder[edgenrs[i2]];541int ndof = max (0, order1-1);542543if (rational && order1 >= 2)544{545Point<3> pm = Center (p1, p2);546547int surfnr = mesh.GetFaceDescriptor(el.GetIndex()).SurfNr();548549Vec<3> n1 = ref -> GetNormal (p1, surfnr, el.GeomInfoPi(edges[i2][0]));550Vec<3> n2 = ref -> GetNormal (p2, surfnr, el.GeomInfoPi(edges[i2][1]));551552// p3 = pm + alpha1 n1 + alpha2 n2553554Mat<2> mat, inv;555Vec<2> rhs, sol;556557mat(0,0) = n1*n1;558mat(0,1) = mat(1,0) = n1*n2;559mat(1,1) = n2*n2;560561rhs(0) = n1 * (p1-pm);562rhs(1) = n2 * (p2-pm);563564565Point<3> p3;566567if (fabs (Det (mat)) > 1e-10)568{569CalcInverse (mat, inv);570sol = inv * rhs;571572p3 = pm + sol(0) * n1 + sol(1) * n2;573}574else575p3 = pm;576577edgecoeffs[edgecoeffsindex[edgenrs[i2]]] = Vec<3> (p3);578579580double wold = 1, w = 1, dw = 0.1;581double dold = 1e99;582while (fabs (dw) > 1e-12)583{584Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);585v05 /= 1 + (w-1) * 0.5;586Point<3> p05 (v05), pp05(v05);587ref -> ProjectToSurface (pp05, surfnr, el.GeomInfoPi(edges[i2][0]));588double d = Dist (pp05, p05);589590if (d < dold)591{592dold = d;593wold = w;594w += dw;595}596else597{598dw *= -0.7;599w = wold + dw;600}601}602603edgeweight[edgenrs[i2]] = w;604continue;605}606607Vector shape(ndof);608DenseMatrix mat(ndof, ndof), inv(ndof, ndof),609rhs(ndof, 3), sol(ndof, 3);610611rhs = 0.0;612mat = 0.0;613for (int j = 0; j < xi.Size(); j++)614{615Point<3> p;616Point<3> pp;617PointGeomInfo ppgi;618619if (swap)620{621p = p1 + xi[j] * (p2-p1);622ref -> PointBetween (p1, p2, xi[j],623mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(),624el.GeomInfoPi(edges[i2][0]),625el.GeomInfoPi(edges[i2][1]),626pp, ppgi);627}628else629{630p = p2 + xi[j] * (p1-p2);631ref -> PointBetween (p2, p1, xi[j],632mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(),633el.GeomInfoPi(edges[i2][1]),634el.GeomInfoPi(edges[i2][0]),635pp, ppgi);636}637638Vec<3> dist = pp - p;639640CalcEdgeShape (order1, 2*xi[j]-1, &shape(0));641642for (int k = 0; k < ndof; k++)643for (int l = 0; l < ndof; l++)644mat(k,l) += weight[j] * shape(k) * shape(l);645646for (int k = 0; k < ndof; k++)647for (int l = 0; l < 3; l++)648rhs(k,l) += weight[j] * shape(k) * dist(l);649}650651CalcInverse (mat, inv);652Mult (inv, rhs, sol);653654655656int first = edgecoeffsindex[edgenrs[i2]];657for (int j = 0; j < ndof; j++)658for (int k = 0; k < 3; k++)659edgecoeffs[first+j](k) = sol(j,k);660}661}662663664665for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++)666{667SetThreadPercent(double(i)/mesh.GetNSeg()*100.);668const Segment & seg = mesh[i];669PointIndex pi1 = mesh[i].p1;670PointIndex pi2 = mesh[i].p2;671672bool swap = (pi1 > pi2);673674Point<3> p1 = mesh[pi1];675Point<3> p2 = mesh[pi2];676677int segnr = top.GetSegmentEdge (i+1)-1;678679int order1 = edgeorder[segnr];680int ndof = max (0, order1-1);681682683if (rational)684{685Vec<3> tau1 = ref -> GetTangent (p1, seg.surfnr2, seg.surfnr1, seg.epgeominfo[0]);686Vec<3> tau2 = ref -> GetTangent (p2, seg.surfnr2, seg.surfnr1, seg.epgeominfo[1]);687// p1 + alpha1 tau1 = p2 + alpha2 tau2;688689Mat<3,2> mat;690Mat<2,3> inv;691Vec<3> rhs;692Vec<2> sol;693for (int j = 0; j < 3; j++)694{695mat(j,0) = tau1(j);696mat(j,1) = -tau2(j);697rhs(j) = p2(j)-p1(j);698}699CalcInverse (mat, inv);700sol = inv * rhs;701702Point<3> p3 = p1+sol(0) * tau1;703edgecoeffs[edgecoeffsindex[segnr]] = Vec<3> (p3);704705706// double dopt = 1e99;707// double wopt = 0;708// for (double w = 0; w <= 2; w += 0.0001)709// {710// Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);711// v05 /= 1 + (w-1) * 0.5;712// Point<3> p05 (v05), pp05(v05);713// ref -> ProjectToEdge (pp05, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]);714// double d = Dist (pp05, p05);715// if (d < dopt)716// {717// wopt = w;718// dopt = d;719// }720// }721722double wold = 1, w = 1, dw = 0.1;723double dold = 1e99;724while (fabs (dw) > 1e-12)725{726Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2);727v05 /= 1 + (w-1) * 0.5;728Point<3> p05 (v05), pp05(v05);729ref -> ProjectToEdge (pp05, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]);730double d = Dist (pp05, p05);731732if (d < dold)733{734dold = d;735wold = w;736w += dw;737}738else739{740dw *= -0.7;741w = wold + dw;742}743// *testout << "w = " << w << ", dw = " << dw << endl;744}745746// cout << "wopt = " << w << ", dopt = " << dold << endl;747edgeweight[segnr] = w;748749// cout << "p1 = " << p1 << ", tau1 = " << tau1 << ", alpha1 = " << sol(0) << endl;750// cout << "p2 = " << p2 << ", tau2 = " << tau2 << ", alpha2 = " << -sol(1) << endl;751// cout << "p+alpha tau = " << p1 + sol(0) * tau1752// << " =?= " << p2 +sol(1) * tau2 << endl;753754}755756else757758{759760Vector shape(ndof);761DenseMatrix mat(ndof, ndof), inv(ndof, ndof),762rhs(ndof, 3), sol(ndof, 3);763764rhs = 0.0;765mat = 0.0;766for (int j = 0; j < xi.Size(); j++)767{768Point<3> p;769770Point<3> pp;771EdgePointGeomInfo ppgi;772773if (swap)774{775p = p1 + xi[j] * (p2-p1);776ref -> PointBetween (p1, p2, xi[j],777seg.surfnr2, seg.surfnr1,778seg.epgeominfo[0], seg.epgeominfo[1],779pp, ppgi);780}781else782{783p = p2 + xi[j] * (p1-p2);784ref -> PointBetween (p2, p1, xi[j],785seg.surfnr2, seg.surfnr1,786seg.epgeominfo[1], seg.epgeominfo[0],787pp, ppgi);788}789790Vec<3> dist = pp - p;791792CalcEdgeShape (order1, 2*xi[j]-1, &shape(0));793794for (int k = 0; k < ndof; k++)795for (int l = 0; l < ndof; l++)796mat(k,l) += weight[j] * shape(k) * shape(l);797798for (int k = 0; k < ndof; k++)799for (int l = 0; l < 3; l++)800rhs(k,l) += weight[j] * shape(k) * dist(l);801}802803804CalcInverse (mat, inv);805Mult (inv, rhs, sol);806807int first = edgecoeffsindex[segnr];808for (int j = 0; j < ndof; j++)809for (int k = 0; k < 3; k++)810edgecoeffs[first+j](k) = sol(j,k);811}812}813814815816817PrintMessage (3, "Curving faces");818819if (mesh.GetDimension() == 3)820for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++)821{822SetThreadPercent(double(i)/mesh.GetNSE()*100.);823const Element2d & el = mesh[i];824int facenr = top.GetSurfaceElementFace (i+1)-1;825826if (el.GetType() == TRIG && order >= 3)827{828int fnums[] = { 0, 1, 2 };829if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);830if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);831if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);832833int order1 = faceorder[facenr];834int ndof = max (0, (order1-1)*(order1-2)/2);835836Vector shape(ndof);837DenseMatrix mat(ndof, ndof), inv(ndof, ndof),838rhs(ndof, 3), sol(ndof, 3);839840rhs = 0.0;841mat = 0.0;842843for (int jx = 0; jx < xi.Size(); jx++)844for (int jy = 0; jy < xi.Size(); jy++)845{846double y = xi[jy];847double x = (1-y) * xi[jx];848double lami[] = { x, y, 1-x-y };849double wi = weight[jx]*weight[jy]*(1-y);850851Point<2> xii (x, y);852Point<3> p1, p2;853CalcSurfaceTransformation (xii, i, p1);854p2 = p1;855ref -> ProjectToSurface (p2, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr());856857Vec<3> dist = p2-p1;858859CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]],8601-lami[fnums[1]]-lami[fnums[0]], &shape(0));861862for (int k = 0; k < ndof; k++)863for (int l = 0; l < ndof; l++)864mat(k,l) += wi * shape(k) * shape(l);865866for (int k = 0; k < ndof; k++)867for (int l = 0; l < 3; l++)868rhs(k,l) += wi * shape(k) * dist(l);869}870871// *testout << "mat = " << endl << mat << endl;872// CalcInverse (mat, inv);873// Mult (inv, rhs, sol);874875for (int i = 0; i < ndof; i++)876for (int j = 0; j < 3; j++)877sol(i,j) = rhs(i,j) / mat(i,i); // Orthogonal basis !878879int first = facecoeffsindex[facenr];880for (int j = 0; j < ndof; j++)881for (int k = 0; k < 3; k++)882facecoeffs[first+j](k) = sol(j,k);883}884}885886PrintMessage (3, "Complete");887888889// compress edge and face tables890int newbase = 0;891for (int i = 0; i < edgeorder.Size(); i++)892{893bool curved = 0;894int oldbase = edgecoeffsindex[i];895nd = edgecoeffsindex[i+1] - edgecoeffsindex[i];896897for (int j = 0; j < nd; j++)898if (edgecoeffs[oldbase+j].Length() > 1e-12)899curved = 1;900if (rational) curved = 1;901902if (curved && newbase != oldbase)903for (int j = 0; j < nd; j++)904edgecoeffs[newbase+j] = edgecoeffs[oldbase+j];905906edgecoeffsindex[i] = newbase;907if (!curved) edgeorder[i] = 1;908if (curved) newbase += nd;909}910edgecoeffsindex.Last() = newbase;911912913newbase = 0;914for (int i = 0; i < faceorder.Size(); i++)915{916bool curved = 0;917int oldbase = facecoeffsindex[i];918nd = facecoeffsindex[i+1] - facecoeffsindex[i];919920for (int j = 0; j < nd; j++)921if (facecoeffs[oldbase+j].Length() > 1e-12)922curved = 1;923924if (curved && newbase != oldbase)925for (int j = 0; j < nd; j++)926facecoeffs[newbase+j] = facecoeffs[oldbase+j];927928facecoeffsindex[i] = newbase;929if (!curved) faceorder[i] = 1;930if (curved) newbase += nd;931}932facecoeffsindex.Last() = newbase;933934ishighorder = (order > 1);935// (*testout) << "edgecoeffs = " << endl << edgecoeffs << endl;936// (*testout) << "facecoeffs = " << endl << facecoeffs << endl;937}938939940941942943944945946947948// *********************** Transform edges *****************************949950951bool CurvedElements :: IsSegmentCurved (SegmentIndex elnr) const952{953if (mesh.coarsemesh)954{955const HPRefElement & hpref_el =956(*mesh.hpelements) [mesh[elnr].hp_elnr];957958return mesh.coarsemesh->GetCurvedElements().IsSegmentCurved (hpref_el.coarse_elnr);959}960961SegmentInfo info;962info.elnr = elnr;963info.order = order;964info.ndof = info.nv = 2;965if (info.order > 1)966{967const MeshTopology & top = mesh.GetTopology();968info.edgenr = top.GetSegmentEdge (elnr+1)-1;969info.ndof += edgeorder[info.edgenr]-1;970}971972return (info.ndof > info.nv);973}974975976977978979void CurvedElements ::980CalcSegmentTransformation (double xi, SegmentIndex elnr,981Point<3> * x, Vec<3> * dxdxi, bool * curved)982{983if (mesh.coarsemesh)984{985const HPRefElement & hpref_el =986(*mesh.hpelements) [mesh[elnr].hp_elnr];987988// xi umrechnen989double lami[2] = { xi, 1-xi };990double dlami[2] = { 1, -1 };991992double coarse_xi = 0;993double trans = 0;994for (int i = 0; i < 2; i++)995{996coarse_xi += hpref_el.param[i][0] * lami[i];997trans += hpref_el.param[i][0] * dlami[i];998}9991000mesh.coarsemesh->GetCurvedElements().CalcSegmentTransformation (coarse_xi, hpref_el.coarse_elnr, x, dxdxi, curved);1001if (dxdxi) *dxdxi *= trans;10021003return;1004}100510061007Vector shapes, dshapes;1008ARRAY<Vec<3> > coefs;10091010SegmentInfo info;1011info.elnr = elnr;1012info.order = order;1013info.ndof = info.nv = 2;10141015if (info.order > 1)1016{1017const MeshTopology & top = mesh.GetTopology();1018info.edgenr = top.GetSegmentEdge (elnr+1)-1;1019info.ndof += edgeorder[info.edgenr]-1;1020}10211022CalcElementShapes (info, xi, shapes);1023GetCoefficients (info, coefs);10241025*x = 0;1026for (int i = 0; i < shapes.Size(); i++)1027*x += shapes(i) * coefs[i];102810291030if (dxdxi)1031{1032CalcElementDShapes (info, xi, dshapes);10331034*dxdxi = 0;1035for (int i = 0; i < shapes.Size(); i++)1036for (int j = 0; j < 3; j++)1037(*dxdxi)(j) += dshapes(i) * coefs[i](j);1038}10391040if (curved)1041*curved = (info.order > 1);10421043// cout << "Segment, |x| = " << Abs2(Vec<3> (*x) ) << endl;1044}10451046104710481049void CurvedElements ::1050CalcElementShapes (SegmentInfo & info, double xi, Vector & shapes) const1051{1052if (rational && info.order == 2)1053{1054shapes.SetSize(3);1055double w = edgeweight[info.edgenr];1056shapes(0) = xi*xi;1057shapes(1) = (1-xi)*(1-xi);1058shapes(2) = 2*w*xi*(1-xi);1059shapes *= 1.0 / (1 + (w-1) *2*xi*(1-xi));1060return;1061}106210631064shapes.SetSize(info.ndof);1065shapes(0) = xi;1066shapes(1) = 1-xi;10671068if (info.order >= 2)1069{1070if (mesh[info.elnr].p1 > mesh[info.elnr].p2)1071xi = 1-xi;1072CalcEdgeShape (edgeorder[info.edgenr], 2*xi-1, &shapes(2));1073}1074}10751076void CurvedElements ::1077CalcElementDShapes (SegmentInfo & info, double xi, Vector & dshapes) const1078{1079if (rational && info.order == 2)1080{1081dshapes.SetSize(3);1082double wi = edgeweight[info.edgenr];1083double shapes[3];1084shapes[0] = xi*xi;1085shapes[1] = (1-xi)*(1-xi);1086shapes[2] = 2*wi*xi*(1-xi);1087double w = 1 + (wi-1) *2*xi*(1-xi);1088double dw = (wi-1) * (2 - 4*xi);10891090dshapes(0) = 2*xi;1091dshapes(1) = 2*(xi-1);1092dshapes(2) = 2*wi*(1-2*xi);10931094for (int j = 0;j < 3; j++)1095dshapes(j) = dshapes(j) / w - shapes[j] * dw / (w*w);1096return;1097}1098109911001101110211031104dshapes.SetSize(info.ndof);1105dshapes = 0;1106dshapes(0) = 1;1107dshapes(1) = -1;11081109// int order = edgeorder[info.edgenr];11101111if (info.order >= 2)1112{1113double fac = 2;1114if (mesh[info.elnr].p1 > mesh[info.elnr].p2)1115{1116xi = 1-xi;1117fac *= -1;1118}1119CalcEdgeDx (edgeorder[info.edgenr], 2*xi-1, &dshapes(2));1120for (int i = 2; i < dshapes.Size(); i++)1121dshapes(i) *= fac;1122}11231124// ??? not implemented ????1125}11261127void CurvedElements ::1128GetCoefficients (SegmentInfo & info, ARRAY<Vec<3> > & coefs) const1129{1130const Segment & el = mesh[info.elnr];11311132coefs.SetSize(info.ndof);11331134coefs[0] = Vec<3> (mesh[el.p1]);1135coefs[1] = Vec<3> (mesh[el.p2]);11361137if (info.order >= 2)1138{1139int first = edgecoeffsindex[info.edgenr];1140int next = edgecoeffsindex[info.edgenr+1];1141for (int i = 0; i < next-first; i++)1142coefs[i+2] = edgecoeffs[first+i];1143}1144}11451146114711481149115011511152115311541155115611571158// ********************** Transform surface elements *******************115911601161bool CurvedElements :: IsSurfaceElementCurved (SurfaceElementIndex elnr) const1162{1163if (mesh.coarsemesh)1164{1165const HPRefElement & hpref_el =1166(*mesh.hpelements) [mesh[elnr].hp_elnr];11671168return mesh.coarsemesh->GetCurvedElements().IsSurfaceElementCurved (hpref_el.coarse_elnr);1169}11701171const Element2d & el = mesh[elnr];1172ELEMENT_TYPE type = el.GetType();11731174SurfaceElementInfo info;1175info.elnr = elnr;1176info.order = order;1177info.ndof = info.nv = (type == TRIG) ? 3 : 4;1178if (info.order > 1)1179{1180const MeshTopology & top = mesh.GetTopology();11811182top.GetSurfaceElementEdges (elnr+1, info.edgenrs);1183for (int i = 0; i < info.edgenrs.Size(); i++)1184info.edgenrs[i]--;1185info.facenr = top.GetSurfaceElementFace (elnr+1)-1;11861187for (int i = 0; i < info.edgenrs.Size(); i++)1188info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];1189info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];1190}11911192return (info.ndof > info.nv);1193}11941195void CurvedElements ::1196CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr,1197Point<3> * x, Mat<3,2> * dxdxi, bool * curved)1198{1199if (mesh.coarsemesh)1200{1201const HPRefElement & hpref_el =1202(*mesh.hpelements) [mesh[elnr].hp_elnr];12031204// xi umrechnen1205double lami[4];1206FlatVector vlami(4, lami);1207vlami = 0;1208mesh[elnr].GetShapeNew (xi, vlami);12091210Mat<2,2> trans;1211Mat<3,2> dxdxic;1212if (dxdxi)1213{1214MatrixFixWidth<2> dlami(4);1215dlami = 0;1216mesh[elnr].GetDShapeNew (xi, dlami);12171218trans = 0;1219for (int k = 0; k < 2; k++)1220for (int l = 0; l < 2; l++)1221for (int i = 0; i < hpref_el.np; i++)1222trans(l,k) += hpref_el.param[i][l] * dlami(i, k);1223}12241225Point<2> coarse_xi(0,0);1226for (int i = 0; i < hpref_el.np; i++)1227for (int j = 0; j < 2; j++)1228coarse_xi(j) += hpref_el.param[i][j] * lami[i];12291230mesh.coarsemesh->GetCurvedElements().CalcSurfaceTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic, curved);12311232if (dxdxi)1233*dxdxi = dxdxic * trans;12341235return;1236}1237123812391240Vector shapes;1241DenseMatrix dshapes;1242ARRAY<Vec<3> > coefs;12431244const Element2d & el = mesh[elnr];1245ELEMENT_TYPE type = el.GetType();12461247SurfaceElementInfo info;1248info.elnr = elnr;1249info.order = order;1250info.ndof = info.nv = (type == TRIG) ? 3 : 4;1251if (info.order > 1)1252{1253const MeshTopology & top = mesh.GetTopology();12541255top.GetSurfaceElementEdges (elnr+1, info.edgenrs);1256for (int i = 0; i < info.edgenrs.Size(); i++)1257info.edgenrs[i]--;1258info.facenr = top.GetSurfaceElementFace (elnr+1)-1;125912601261bool firsttry = true;1262bool problem = false;12631264while(firsttry || problem)1265{1266problem = false;12671268for (int i = 0; !problem && i < info.edgenrs.Size(); i++)1269{1270if(info.edgenrs[i]+1 >= edgecoeffsindex.Size())1271problem = true;1272else1273info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];1274}1275if(info.facenr+1 >= facecoeffsindex.Size())1276problem = true;1277else1278info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];12791280if(problem && !firsttry)1281throw NgException("something wrong with curved elements");12821283if(problem)1284BuildCurvedElements(NULL,order,rational);12851286firsttry = false;1287}1288}12891290CalcElementShapes (info, xi, shapes);1291GetCoefficients (info, coefs);12921293*x = 0;1294for (int i = 0; i < coefs.Size(); i++)1295*x += shapes(i) * coefs[i];12961297if (dxdxi)1298{1299CalcElementDShapes (info, xi, dshapes);13001301*dxdxi = 0;1302for (int i = 0; i < coefs.Size(); i++)1303for (int j = 0; j < 3; j++)1304for (int k = 0; k < 2; k++)1305(*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j);1306}13071308if (curved)1309*curved = (info.ndof > info.nv);131013111312// cout.precision(12);1313// cout << "face, |x| = " << Abs2(Vec<3> (*x) )/sqr(M_PI) << endl;1314}13151316131713181319void CurvedElements ::1320CalcElementShapes (SurfaceElementInfo & info, const Point<2> & xi, Vector & shapes) const1321{1322const Element2d & el = mesh[info.elnr];13231324shapes.SetSize(info.ndof);1325shapes = 0;13261327if (rational && info.order >= 2)1328{1329shapes.SetSize(6);1330double w = 1;1331double lami[3] = { xi(0), xi(1), 1-xi(0)-xi(1) };1332for (int j = 0; j < 3; j++)1333shapes(j) = lami[j] * lami[j];13341335const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);1336for (int j = 0; j < 3; j++)1337{1338double wi = edgeweight[info.edgenrs[j]];1339shapes(j+3) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];1340w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];1341}13421343shapes *= 1.0 / w;1344return;1345}13461347switch (el.GetType())1348{1349case TRIG:1350{1351shapes(0) = xi(0);1352shapes(1) = xi(1);1353shapes(2) = 1-xi(0)-xi(1);13541355if (info.order == 1) return;13561357int ii = 3;1358const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);13591360for (int i = 0; i < 3; i++)1361{1362int eorder = edgeorder[info.edgenrs[i]];1363if (eorder >= 2)1364{1365int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;1366if (el[vi1] > el[vi2]) swap (vi1, vi2);13671368CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));1369ii += eorder-1;1370}1371}13721373int forder = faceorder[info.facenr];1374if (forder >= 3)1375{1376int fnums[] = { 0, 1, 2 };1377if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);1378if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);1379if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);13801381CalcTrigShape (forder,1382shapes(fnums[1])-shapes(fnums[0]),13831-shapes(fnums[1])-shapes(fnums[0]), &shapes(ii));1384}1385break;1386}13871388case QUAD:1389{1390shapes(0) = (1-xi(0))*(1-xi(1));1391shapes(1) = xi(0) *(1-xi(1));1392shapes(2) = xi(0) * xi(1) ;1393shapes(3) = (1-xi(0))* xi(1) ;13941395if (info.order == 1) return;13961397double mu[4] = {13981 - xi(0) + 1 - xi(1),1399xi(0) + 1 - xi(1),1400xi(0) + xi(1),14011 - xi(0) + xi(1),1402};14031404int ii = 4;1405const ELEMENT_EDGE * edges = MeshTopology::GetEdges (QUAD);14061407for (int i = 0; i < 4; i++)1408{1409int eorder = edgeorder[info.edgenrs[i]];1410if (eorder >= 2)1411{1412int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;1413if (el[vi1] > el[vi2]) swap (vi1, vi2);14141415CalcEdgeShape (eorder, mu[vi1]-mu[vi2], &shapes(ii));1416double lame = shapes(vi1)+shapes(vi2);1417for (int j = 0; j < order-1; j++)1418shapes(ii+j) *= lame;1419ii += eorder-1;1420}1421}14221423for (int i = ii; i < info.ndof; i++)1424shapes(i) = 0;14251426break;1427}1428};1429}143014311432void CurvedElements ::1433CalcElementDShapes (SurfaceElementInfo & info, const Point<2> & xi, DenseMatrix & dshapes) const1434{1435const Element2d & el = mesh[info.elnr];1436ELEMENT_TYPE type = el.GetType();14371438double lami[4];14391440dshapes.SetSize(info.ndof,2);1441dshapes = 0;14421443// *testout << "calcelementdshapes, info.ndof = " << info.ndof << endl;14441445if (rational && info.order >= 2)1446{1447double w = 1;1448double dw[2] = { 0, 0 };144914501451lami[0] = xi(0); lami[1] = xi(1); lami[2] = 1-xi(0)-xi(1);1452double dlami[3][2] = { { 1, 0 }, { 0, 1 }, { -1, -1 }};1453double shapes[6];14541455for (int j = 0; j < 3; j++)1456{1457shapes[j] = lami[j] * lami[j];1458dshapes(j,0) = 2 * lami[j] * dlami[j][0];1459dshapes(j,1) = 2 * lami[j] * dlami[j][1];1460}14611462const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);1463for (int j = 0; j < 3; j++)1464{1465double wi = edgeweight[info.edgenrs[j]];14661467shapes[j+3] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];1468for (int k = 0; k < 2; k++)1469dshapes(j+3,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +1470lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);14711472w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];1473for (int k = 0; k < 2; k++)1474dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +1475lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);1476}1477// shapes *= 1.0 / w;1478dshapes *= 1.0 / w;1479for (int i = 0; i < 6; i++)1480for (int j = 0; j < 2; j++)1481dshapes(i,j) -= shapes[i] * dw[j] / (w*w);1482return;1483}148414851486148714881489switch (type)1490{1491case TRIG:1492{1493dshapes(0,0) = 1;1494dshapes(1,1) = 1;1495dshapes(2,0) = -1;1496dshapes(2,1) = -1;14971498if (info.order == 1) return;14991500// *testout << "info.order = " << info.order << endl;150115021503lami[0] = xi(0);1504lami[1] = xi(1);1505lami[2] = 1-xi(0)-xi(1);15061507int ii = 3;1508const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG);15091510for (int i = 0; i < 3; i++)1511{1512int eorder = edgeorder[info.edgenrs[i]];1513if (eorder >= 2)1514{1515int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;1516if (el[vi1] > el[vi2]) swap (vi1, vi2);15171518CalcScaledEdgeShapeDxDt<2> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0));15191520Mat<2,2> trans;1521for (int j = 0; j < 2; j++)1522{1523trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j);1524trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j);1525}15261527for (int j = 0; j < eorder-1; j++)1528{1529double ddx = dshapes(ii+j,0);1530double ddt = dshapes(ii+j,1);1531dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);1532dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);1533}15341535ii += eorder-1;1536}1537}15381539int forder = faceorder[info.facenr];1540// *testout << "forder = " << forder << endl;1541if (forder >= 3)1542{1543int fnums[] = { 0, 1, 2 };1544if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);1545if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);1546if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);15471548CalcTrigShapeDxDy (forder,1549lami[fnums[1]]-lami[fnums[0]],15501-lami[fnums[1]]-lami[fnums[0]], &dshapes(ii,0));15511552int nd = (forder-1)*(forder-2)/2;1553Mat<2,2> trans;1554for (int j = 0; j < 2; j++)1555{1556trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j);1557trans(1,j) = -dshapes(fnums[1],j)-dshapes(fnums[0],j);1558}15591560for (int j = 0; j < nd; j++)1561{1562double ddx = dshapes(ii+j,0);1563double ddt = dshapes(ii+j,1);1564dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);1565dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);1566}1567}15681569break;1570}1571case QUAD:1572{1573dshapes(0,0) = -(1-xi(1));1574dshapes(0,1) = -(1-xi(0));1575dshapes(1,0) = (1-xi(1));1576dshapes(1,1) = -xi(0);1577dshapes(2,0) = xi(1);1578dshapes(2,1) = xi(0);1579dshapes(3,0) = -xi(1);1580dshapes(3,1) = (1-xi(0));15811582if (info.order == 1) return;15831584double shapes[4] = {1585(1-xi(0))*(1-xi(1)),1586xi(0) *(1-xi(1)),1587xi(0) * xi(1) ,1588(1-xi(0))* xi(1)1589};15901591double mu[4] = {15921 - xi(0) + 1 - xi(1),1593xi(0) + 1 - xi(1),1594xi(0) + xi(1),15951 - xi(0) + xi(1),1596};15971598double dmu[4][2] = {1599{ -1, -1 },1600{ 1, -1 },1601{ 1, 1 },1602{ -1, 1 } };16031604// double hshapes[20], hdshapes[20];1605ArrayMem<double, 20> hshapes(order+1), hdshapes(order+1);16061607int ii = 4;1608const ELEMENT_EDGE * edges = MeshTopology::GetEdges (QUAD);16091610for (int i = 0; i < 4; i++)1611{1612int eorder = edgeorder[info.edgenrs[i]];1613if (eorder >= 2)1614{1615int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;1616if (el[vi1] > el[vi2]) swap (vi1, vi2);16171618CalcEdgeShapeDx (eorder, mu[vi1]-mu[vi2], &hshapes[0], &hdshapes[0]);16191620double lame = shapes[vi1]+shapes[vi2];1621double dlame[2] = {1622dshapes(vi1, 0) + dshapes(vi2, 0),1623dshapes(vi1, 1) + dshapes(vi2, 1) };16241625for (int j = 0; j < eorder-1; j++)1626for (int k = 0; k < 2; k++)1627dshapes(ii+j, k) =1628lame * hdshapes[j] * (dmu[vi1][k]-dmu[vi2][k])1629+ dlame[k] * hshapes[j];16301631ii += eorder-1;1632}1633}16341635/*1636*testout << "quad, dshape = " << endl << dshapes << endl;1637for (int i = 0; i < 2; i++)1638{1639Point<2> xil = xi, xir = xi;1640Vector shapesl(dshapes.Height()), shapesr(dshapes.Height());1641xil(i) -= 1e-6;1642xir(i) += 1e-6;1643CalcElementShapes (info, xil, shapesl);1644CalcElementShapes (info, xir, shapesr);16451646for (int j = 0; j < dshapes.Height(); j++)1647dshapes(j,i) = 1.0 / 2e-6 * (shapesr(j)-shapesl(j));1648}16491650*testout << "quad, num dshape = " << endl << dshapes << endl;1651*/1652break;1653}1654};1655}1656165716581659void CurvedElements ::1660GetCoefficients (SurfaceElementInfo & info, ARRAY<Vec<3> > & coefs) const1661{1662const Element2d & el = mesh[info.elnr];16631664coefs.SetSize (info.ndof);1665// coefs = Vec<3> (0,0,0);16661667for (int i = 0; i < info.nv; i++)1668coefs[i] = Vec<3> (mesh[el[i]]);16691670if (info.order == 1) return;16711672int ii = info.nv;16731674for (int i = 0; i < info.edgenrs.Size(); i++)1675{1676int first = edgecoeffsindex[info.edgenrs[i]];1677int next = edgecoeffsindex[info.edgenrs[i]+1];1678for (int j = first; j < next; j++, ii++)1679coefs[ii] = edgecoeffs[j];1680}16811682int first = facecoeffsindex[info.facenr];1683int next = facecoeffsindex[info.facenr+1];1684for (int j = first; j < next; j++, ii++)1685coefs[ii] = facecoeffs[j];1686}16871688168916901691169216931694// ********************** Transform volume elements *******************169516961697bool CurvedElements :: IsElementCurved (ElementIndex elnr) const1698{1699if (mesh.coarsemesh)1700{1701const HPRefElement & hpref_el =1702(*mesh.hpelements) [mesh[elnr].hp_elnr];17031704return mesh.coarsemesh->GetCurvedElements().IsElementCurved (hpref_el.coarse_elnr);1705}17061707const Element & el = mesh[elnr];1708ELEMENT_TYPE type = el.GetType();17091710ElementInfo info;1711info.elnr = elnr;1712info.order = order;1713info.ndof = info.nv = MeshTopology::GetNVertices (type);1714if (info.order > 1)1715{1716const MeshTopology & top = mesh.GetTopology();17171718info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);1719for (int i = 0; i < info.nedges; i++)1720info.edgenrs[i]--;17211722info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);1723for (int i = 0; i < info.nfaces; i++)1724info.facenrs[i]--;17251726for (int i = 0; i < info.nedges; i++)1727info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];1728for (int i = 0; i < info.nfaces; i++)1729info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];1730}17311732return (info.ndof > info.nv);1733}1734173517361737173817391740void CurvedElements ::1741CalcElementTransformation (Point<3> xi, ElementIndex elnr,1742Point<3> * x, Mat<3,3> * dxdxi, // bool * curved,1743void * buffer, bool valid)1744{1745if (mesh.coarsemesh)1746{1747const HPRefElement & hpref_el =1748(*mesh.hpelements) [mesh[elnr].hp_elnr];17491750// xi umrechnen1751double lami[8];1752FlatVector vlami(8, lami);1753vlami = 0;1754mesh[elnr].GetShapeNew (xi, vlami);17551756Mat<3,3> trans, dxdxic;1757if (dxdxi)1758{1759MatrixFixWidth<3> dlami(8);1760dlami = 0;1761mesh[elnr].GetDShapeNew (xi, dlami);17621763trans = 0;1764for (int k = 0; k < 3; k++)1765for (int l = 0; l < 3; l++)1766for (int i = 0; i < hpref_el.np; i++)1767trans(l,k) += hpref_el.param[i][l] * dlami(i, k);1768}17691770Point<3> coarse_xi(0,0,0);1771for (int i = 0; i < hpref_el.np; i++)1772for (int j = 0; j < 3; j++)1773coarse_xi(j) += hpref_el.param[i][j] * lami[i];17741775mesh.coarsemesh->GetCurvedElements().CalcElementTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic /* , curved */);17761777if (dxdxi)1778*dxdxi = dxdxic * trans;17791780return;1781}178217831784Vector shapes;1785MatrixFixWidth<3> dshapes;17861787const Element & el = mesh[elnr];1788ELEMENT_TYPE type = el.GetType();17891790ElementInfo hinfo;1791ElementInfo & info = (buffer) ? *static_cast<ElementInfo*> (buffer) : hinfo;179217931794if (!valid)1795{1796info.elnr = elnr;1797info.order = order;1798info.ndof = info.nv = MeshTopology::GetNVertices (type);1799if (info.order > 1)1800{1801const MeshTopology & top = mesh.GetTopology();18021803info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);1804for (int i = 0; i < info.nedges; i++)1805info.edgenrs[i]--;18061807info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);1808for (int i = 0; i < info.nfaces; i++)1809info.facenrs[i]--;18101811for (int i = 0; i < info.nedges; i++)1812info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];1813for (int i = 0; i < info.nfaces; i++)1814info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];1815}1816}18171818CalcElementShapes (info, xi, shapes);18191820Vec<3> * coefs = (info.ndof <= 10) ?1821&info.hcoefs[0] : new Vec<3> [info.ndof];18221823if (info.ndof > 10 || !valid)1824GetCoefficients (info, coefs);18251826if (x)1827{1828*x = 0;1829for (int i = 0; i < shapes.Size(); i++)1830*x += shapes(i) * coefs[i];1831}18321833if (dxdxi)1834{1835if (valid && info.order == 1 && info.nv == 4) // a linear tet1836{1837*dxdxi = info.hdxdxi;1838}1839else1840{1841CalcElementDShapes (info, xi, dshapes);18421843*dxdxi = 0;1844for (int i = 0; i < shapes.Size(); i++)1845for (int j = 0; j < 3; j++)1846for (int k = 0; k < 3; k++)1847(*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j);18481849info.hdxdxi = *dxdxi;1850}1851}18521853// *testout << "curved_elements, dshapes = " << endl << dshapes << endl;18541855// if (curved) *curved = (info.ndof > info.nv);18561857if (info.ndof > 10) delete [] coefs;1858}18591860186118621863void CurvedElements :: CalcElementShapes (ElementInfo & info, const Point<3> & xi, Vector & shapes) const1864{1865const Element & el = mesh[info.elnr];18661867if (rational && info.order >= 2)1868{1869shapes.SetSize(10);1870double w = 1;1871double lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };1872for (int j = 0; j < 4; j++)1873shapes(j) = lami[j] * lami[j];18741875const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);1876for (int j = 0; j < 6; j++)1877{1878double wi = edgeweight[info.edgenrs[j]];1879shapes(j+4) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];1880w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];1881}18821883shapes *= 1.0 / w;1884return;1885}18861887shapes.SetSize(info.ndof);18881889switch (el.GetType())1890{1891case TET:1892{1893shapes(0) = xi(0);1894shapes(1) = xi(1);1895shapes(2) = xi(2);1896shapes(3) = 1-xi(0)-xi(1)-xi(2);18971898if (info.order == 1) return;18991900int ii = 4;1901const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);1902for (int i = 0; i < 6; i++)1903{1904int eorder = edgeorder[info.edgenrs[i]];1905if (eorder >= 2)1906{1907int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;1908if (el[vi1] > el[vi2]) swap (vi1, vi2);19091910CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));1911ii += eorder-1;1912}1913}1914const ELEMENT_FACE * faces = MeshTopology::GetFaces (TET);1915for (int i = 0; i < 4; i++)1916{1917int forder = faceorder[info.facenrs[i]];1918if (forder >= 3)1919{1920int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };1921if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);1922if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);1923if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);19241925CalcScaledTrigShape (forder,1926shapes(fnums[1])-shapes(fnums[0]), shapes(fnums[2]),1927shapes(fnums[0])+shapes(fnums[1])+shapes(fnums[2]), &shapes(ii));1928ii += (forder-1)*(forder-2)/2;1929// CalcScaledEdgeShape (forder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii));1930// ii += forder-1;1931}1932}193319341935break;1936}1937case PRISM:1938{1939double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) };1940double lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) };1941for (int i = 0; i < 6; i++)1942shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) );1943for (int i = 6; i < info.ndof; i++)1944shapes(i) = 0;19451946if (info.order == 1) return;194719481949int ii = 6;1950const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PRISM);1951for (int i = 0; i < 6; i++) // horizontal edges1952{1953int eorder = edgeorder[info.edgenrs[i]];1954if (eorder >= 2)1955{1956int vi1 = (edges[i][0]-1) % 3, vi2 = (edges[i][1]-1) % 3;1957if (el[vi1] > el[vi2]) swap (vi1, vi2);19581959CalcScaledEdgeShape (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapes(ii));1960double facz = (i < 3) ? (1-xi(2)) : xi(2);1961for (int j = 0; j < eorder-1; j++)1962shapes(ii+j) *= facz;19631964ii += eorder-1;1965}1966}19671968for (int i = 6; i < 9; i++) // vertical edges1969{1970int eorder = edgeorder[info.edgenrs[i]];1971if (eorder >= 2)1972{1973int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);1974if (el[vi1] > el[vi2]) swap (vi1, vi2);19751976double bubz = lamiz[vi1]*lamiz[vi2];1977double polyz = lamiz[vi1] - lamiz[vi2];1978double bubxy = lami[(vi1)%3];19791980for (int j = 0; j < eorder-1; j++)1981{1982shapes(ii+j) = bubxy * bubz;1983bubz *= polyz;1984}1985ii += eorder-1;1986}1987}19881989// FACE SHAPES1990const ELEMENT_FACE * faces = MeshTopology::GetFaces (PRISM);1991for (int i = 0; i < 2; i++)1992{1993int forder = faceorder[info.facenrs[i]];1994if ( forder < 3 ) continue;1995int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };1996if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);1997if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]);1998if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);19992000CalcTrigShape (forder,2001lami[fav[2]]-lami[fav[1]], lami[fav[0]],2002&shapes(ii));20032004int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1);2005for ( int j = 0; j < ndf; j++ )2006shapes(ii+j) *= lamiz[fav[1]];2007ii += ndf;2008}2009break;2010}20112012case PYRAMID:2013{2014shapes = 0.0;2015double x = xi(0);2016double y = xi(1);2017double z = xi(2);20182019if (z == 1.) z = 1-1e-10;2020shapes[0] = (1-z-x)*(1-z-y) / (1-z);2021shapes[1] = x*(1-z-y) / (1-z);2022shapes[2] = x*y / (1-z);2023shapes[3] = (1-z-x)*y / (1-z);2024shapes[4] = z;20252026if (info.order == 1) return;20272028int ii = 5;2029const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PYRAMID);2030for (int i = 0; i < 4; i++) // horizontal edges2031{2032int eorder = edgeorder[info.edgenrs[i]];2033if (eorder >= 2)2034{2035int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);2036if (el[vi1] > el[vi2]) swap (vi1, vi2);20372038CalcScaledEdgeShape (eorder, shapes[vi1]-shapes[vi2], shapes[vi1]+shapes[vi2], &shapes(ii));2039double fac = (shapes[vi1]+shapes[vi2]) / (1-z);2040for (int j = 0; j < eorder-1; j++)2041shapes(ii+j) *= fac;20422043ii += eorder-1;2044}2045}2046204720482049break;2050}20512052case HEX:2053{2054shapes = 0.0;2055double x = xi(0);2056double y = xi(1);2057double z = xi(2);20582059shapes[0] = (1-x)*(1-y)*(1-z);2060shapes[1] = x *(1-y)*(1-z);2061shapes[2] = x * y *(1-z);2062shapes[3] = (1-x)* y *(1-z);2063shapes[4] = (1-x)*(1-y)*(z);2064shapes[5] = x *(1-y)*(z);2065shapes[6] = x * y *(z);2066shapes[7] = (1-x)* y *(z);2067break;2068}2069};2070}207120722073void CurvedElements ::2074CalcElementDShapes (ElementInfo & info, const Point<3> & xi, MatrixFixWidth<3> & dshapes) const2075{2076const Element & el = mesh[info.elnr];20772078dshapes.SetSize(info.ndof);2079dshapes = 0.0;2080208120822083if (rational && info.order >= 2)2084{2085double w = 1;2086double dw[3] = { 0, 0, 0 };20872088double lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };2089double dlami[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, -1, -1 }};2090double shapes[10];20912092for (int j = 0; j < 4; j++)2093{2094shapes[j] = lami[j] * lami[j];2095dshapes(j,0) = 2 * lami[j] * dlami[j][0];2096dshapes(j,1) = 2 * lami[j] * dlami[j][1];2097dshapes(j,2) = 2 * lami[j] * dlami[j][2];2098}20992100const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);2101for (int j = 0; j < 6; j++)2102{2103double wi = edgeweight[info.edgenrs[j]];21042105shapes[j+4] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1];2106for (int k = 0; k < 3; k++)2107dshapes(j+4,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +2108lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);21092110w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1];2111for (int k = 0; k < 3; k++)2112dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] +2113lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]);2114}2115// shapes *= 1.0 / w;2116dshapes *= 1.0 / w;2117for (int i = 0; i < 10; i++)2118for (int j = 0; j < 3; j++)2119dshapes(i,j) -= shapes[i] * dw[j] / (w*w);2120return;2121}21222123switch (el.GetType())2124{2125case TET:2126{2127dshapes(0,0) = 1;2128dshapes(1,1) = 1;2129dshapes(2,2) = 1;2130dshapes(3,0) = -1;2131dshapes(3,1) = -1;2132dshapes(3,2) = -1;21332134if (info.order == 1) return;21352136double lami[] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) };2137int ii = 4;2138const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET);2139for (int i = 0; i < 6; i++)2140{2141int eorder = edgeorder[info.edgenrs[i]];2142if (eorder >= 2)2143{2144int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1;2145if (el[vi1] > el[vi2]) swap (vi1, vi2);21462147CalcScaledEdgeShapeDxDt<3> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0));21482149Mat<2,3> trans;2150for (int j = 0; j < 3; j++)2151{2152trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j);2153trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j);2154}21552156for (int j = 0; j < order-1; j++)2157{2158double ddx = dshapes(ii+j,0);2159double ddt = dshapes(ii+j,1);2160dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);2161dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);2162dshapes(ii+j,2) = ddx * trans(0,2) + ddt * trans(1,2);2163}21642165ii += eorder-1;2166}2167}21682169const ELEMENT_FACE * faces = MeshTopology::GetFaces (TET);2170for (int i = 0; i < 4; i++)2171{2172int forder = faceorder[info.facenrs[i]];2173if (forder >= 3)2174{2175int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };2176if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);2177if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]);2178if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);21792180CalcScaledTrigShapeDxDyDt (forder,2181lami[fnums[1]]-lami[fnums[0]],2182lami[fnums[2]], lami[fnums[0]]+lami[fnums[1]]+lami[fnums[2]],2183&dshapes(ii,0));21842185Mat<3,3> trans;2186for (int j = 0; j < 3; j++)2187{2188trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j);2189trans(1,j) = dshapes(fnums[2],j);2190trans(2,j) = dshapes(fnums[0],j)+dshapes(fnums[1],j)+dshapes(fnums[2],j);2191}21922193int nfd = (forder-1)*(forder-2)/2;2194for (int j = 0; j < nfd; j++)2195{2196double ddx = dshapes(ii+j,0);2197double ddy = dshapes(ii+j,1);2198double ddt = dshapes(ii+j,2);2199dshapes(ii+j,0) = ddx * trans(0,0) + ddy * trans(1,0) + ddt * trans(2,0);2200dshapes(ii+j,1) = ddx * trans(0,1) + ddy * trans(1,1) + ddt * trans(2,1);2201dshapes(ii+j,2) = ddx * trans(0,2) + ddy * trans(1,2) + ddt * trans(2,2);2202}22032204ii += nfd;2205}2206}22072208break;2209}2210case PRISM:2211{2212double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) };2213double lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) };2214double dlamiz[6] = { -1, -1, -1, 1, 1, 1 };2215double dlami[6][2] =2216{ { 1, 0, },2217{ 0, 1, },2218{ -1, -1 },2219{ 1, 0, },2220{ 0, 1, },2221{ -1, -1 } };2222for (int i = 0; i < 6; i++)2223{2224// shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) );2225dshapes(i,0) = dlami[i%3][0] * ( (i < 3) ? (1-xi(2)) : xi(2) );2226dshapes(i,1) = dlami[i%3][1] * ( (i < 3) ? (1-xi(2)) : xi(2) );2227dshapes(i,2) = lami[i%3] * ( (i < 3) ? -1 : 1 );2228}22292230int ii = 6;22312232if (info.order == 1) return;223322342235const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PRISM);2236for (int i = 0; i < 6; i++) // horizontal edges2237{2238int order = edgeorder[info.edgenrs[i]];2239if (order >= 2)2240{2241int vi1 = (edges[i][0]-1) % 3, vi2 = (edges[i][1]-1) % 3;2242if (el[vi1] > el[vi2]) swap (vi1, vi2);22432244Vector shapei(order+1);2245CalcScaledEdgeShapeDxDt<3> (order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0) );2246CalcScaledEdgeShape(order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapei(0) );22472248Mat<2,2> trans;2249for (int j = 0; j < 2; j++)2250{2251trans(0,j) = dlami[vi1][j]-dlami[vi2][j];2252trans(1,j) = dlami[vi1][j]+dlami[vi2][j];2253}22542255for (int j = 0; j < order-1; j++)2256{2257double ddx = dshapes(ii+j,0);2258double ddt = dshapes(ii+j,1);2259dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);2260dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);2261}2262226322642265double facz = (i < 3) ? (1-xi(2)) : xi(2);2266double dfacz = (i < 3) ? (-1) : 1;2267for (int j = 0; j < order-1; j++)2268{2269dshapes(ii+j,0) *= facz;2270dshapes(ii+j,1) *= facz;2271dshapes(ii+j,2) = shapei(j) * dfacz;2272}22732274ii += order-1;2275}2276}2277for (int i = 6; i < 9; i++) // vertical edges2278{2279int eorder = edgeorder[info.edgenrs[i]];2280if (eorder >= 2)2281{2282int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1);2283if (el[vi1] > el[vi2]) swap (vi1, vi2);22842285double bubz = lamiz[vi1] * lamiz[vi2];2286double dbubz = dlamiz[vi1]*lamiz[vi2] + lamiz[vi1]*dlamiz[vi2];2287double polyz = lamiz[vi1] - lamiz[vi2];2288double dpolyz = dlamiz[vi1] - dlamiz[vi2];2289double bubxy = lami[(vi1)%3];2290double dbubxydx = dlami[(vi1)%3][0];2291double dbubxydy = dlami[(vi1)%3][1];22922293for (int j = 0; j < eorder-1; j++)2294{2295dshapes(ii+j,0) = dbubxydx * bubz;2296dshapes(ii+j,1) = dbubxydy * bubz;2297dshapes(ii+j,2) = bubxy * dbubz;22982299dbubz = bubz * dpolyz + dbubz * polyz;2300bubz *= polyz;2301}2302ii += eorder-1;2303}2304}230523062307if (info.order == 2) return;2308// FACE SHAPES2309const ELEMENT_FACE * faces = MeshTopology::GetFaces (PRISM);2310for (int i = 0; i < 2; i++)2311{2312int forder = faceorder[info.facenrs[i]];2313if ( forder < 3 ) continue;2314int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1);23152316int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 };2317if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);2318if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]);2319if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]);23202321MatrixFixWidth<2> dshapei(ndf);2322Vector shapei(ndf);23232324CalcTrigShapeDxDy (forder,2325lami[fav[2]]-lami[fav[1]], lami[fav[0]],2326&dshapei(0,0));2327CalcTrigShape (forder, lami[fav[2]]-lami[fav[1]], lami[fav[0]],2328&shapei(0));23292330Mat<2,2> trans;2331for (int j = 0; j < 2; j++)2332{2333trans(0,j) = dlami[fav[2]][j]-dlami[fav[1]][j];2334trans(1,j) = dlami[fav[0]][j];2335}23362337for (int j = 0; j < order-1; j++)2338{2339double ddx = dshapes(ii+j,0);2340double ddt = dshapes(ii+j,1);2341dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0);2342dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1);2343}23442345for ( int j = 0; j < ndf; j++ )2346{2347dshapes(ii+j,0) *= lamiz[fav[1]];2348dshapes(ii+j,1) *= lamiz[fav[1]];2349dshapes(ii+j,2) = shapei(j) * dlamiz[fav[1]];2350}2351ii += ndf;2352}23532354break;23552356}23572358case PYRAMID:2359{2360dshapes = 0.0;2361double x = xi(0);2362double y = xi(1);2363double z = xi(2);23642365if (z == 1.) z = 1-1e-10;2366double z1 = 1-z;2367double z2 = z1*z1;23682369dshapes(0,0) = -(z1-y)/z1;2370dshapes(0,1) = -(z1-x)/z1;2371dshapes(0,2) = ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2;23722373dshapes(1,0) = (z1-y)/z1;2374dshapes(1,1) = -x/z1;2375dshapes(1,2) = (-x*z1+x*(z1-y))/z2;23762377dshapes(2,0) = y/z1;2378dshapes(2,1) = x/z1;2379dshapes(2,2) = x*y/z2;23802381dshapes(3,0) = -y/z1;2382dshapes(3,1) = (z1-x)/z1;2383dshapes(3,2) = (-y*z1+y*(z1-x))/z2;23842385dshapes(4,0) = 0;2386dshapes(4,1) = 0;2387dshapes(4,2) = 1;2388/* old:2389vdshape[0] = Vec<3>( -(z1-y)/z1, -(z1-x)/z1, ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2 );2390vdshape[1] = Vec<3>( (z1-y)/z1, -x/z1, (-x*z1+x*(z1-y))/z2 );2391vdshape[2] = Vec<3>( y/z1, x/z1, x*y/z2 );2392vdshape[3] = Vec<3>( -y/z1, (z1-x)/z1, (-y*z1+y*(z1-x))/z2 );2393vdshape[4] = Vec<3>( 0, 0, 1 );2394*/2395break;2396}23972398case HEX:2399{2400dshapes = 0.0;24012402double x = xi(0);2403double y = xi(1);2404double z = xi(2);24052406// shapes[0] = (1-x)*(1-y)*(1-z);2407dshapes(0,0) = - (1-y)*(1-z);2408dshapes(0,1) = (1-x) * (-1) * (1-z);2409dshapes(0,2) = (1-x) * (1-y) * (-1);24102411// shapes[1] = x *(1-y)*(1-z);2412dshapes(1,0) = (1-y)*(1-z);2413dshapes(1,1) = -x * (1-z);2414dshapes(1,2) = -x * (1-y);24152416// shapes[2] = x * y *(1-z);2417dshapes(2,0) = y * (1-z);2418dshapes(2,1) = x * (1-z);2419dshapes(2,2) = -x * y;24202421// shapes[3] = (1-x)* y *(1-z);2422dshapes(3,0) = -y * (1-z);2423dshapes(3,1) = (1-x) * (1-z);2424dshapes(3,2) = -(1-x) * y;24252426// shapes[4] = (1-x)*(1-y)*z;2427dshapes(4,0) = - (1-y)*z;2428dshapes(4,1) = (1-x) * (-1) * z;2429dshapes(4,2) = (1-x) * (1-y) * 1;24302431// shapes[5] = x *(1-y)*z;2432dshapes(5,0) = (1-y)*z;2433dshapes(5,1) = -x * z;2434dshapes(5,2) = x * (1-y);24352436// shapes[6] = x * y *z;2437dshapes(6,0) = y * z;2438dshapes(6,1) = x * z;2439dshapes(6,2) = x * y;24402441// shapes[7] = (1-x)* y *z;2442dshapes(7,0) = -y * z;2443dshapes(7,1) = (1-x) * z;2444dshapes(7,2) = (1-x) * y;24452446break;2447}2448}24492450/*2451DenseMatrix dshapes2 (info.ndof, 3);2452Vector shapesl(info.ndof);2453Vector shapesr(info.ndof);24542455double eps = 1e-6;2456for (int i = 0; i < 3; i++)2457{2458Point<3> xl = xi;2459Point<3> xr = xi;24602461xl(i) -= eps;2462xr(i) += eps;2463CalcElementShapes (info, xl, shapesl);2464CalcElementShapes (info, xr, shapesr);24652466for (int j = 0; j < info.ndof; j++)2467dshapes2(j,i) = (shapesr(j)-shapesl(j)) / (2*eps);2468}2469(*testout) << "dshapes = " << endl << dshapes << endl;2470(*testout) << "dshapes2 = " << endl << dshapes2 << endl;2471dshapes2 -= dshapes;2472(*testout) << "diff = " << endl << dshapes2 << endl;2473*/2474}2475247624772478void CurvedElements ::2479GetCoefficients (ElementInfo & info, Vec<3> * coefs) const2480{2481// cout << "getcoeffs, info.elnr = " << info.elnr << endl;2482// cout << "getcoeffs, info.nv = " << info.nv << endl;24832484const Element & el = mesh[info.elnr];24852486/*2487coefs.SetSize (info.ndof);2488coefs = Vec<3> (0,0,0);2489*/2490/*2491for (int i = 0; i < info.ndof; i++)2492coefs[i] = Vec<3> (0,0,0);2493*/2494for (int i = 0; i < info.nv; i++)2495coefs[i] = Vec<3> (mesh[el[i]]);24962497if (info.order == 1) return;24982499int ii = info.nv;25002501for (int i = 0; i < info.nedges; i++)2502{2503int first = edgecoeffsindex[info.edgenrs[i]];2504int next = edgecoeffsindex[info.edgenrs[i]+1];2505for (int j = first; j < next; j++, ii++)2506coefs[ii] = edgecoeffs[j];2507}2508for (int i = 0; i < info.nfaces; i++)2509{2510int first = facecoeffsindex[info.facenrs[i]];2511int next = facecoeffsindex[info.facenrs[i]+1];2512for (int j = first; j < next; j++, ii++)2513coefs[ii] = facecoeffs[j];2514}2515}25162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547void CurvedElements ::2548CalcMultiPointSegmentTransformation (ARRAY<double> * xi, SegmentIndex segnr,2549ARRAY<Point<3> > * x,2550ARRAY<Vec<3> > * dxdxi)2551{2552;2553}25542555void CurvedElements ::2556CalcMultiPointSurfaceTransformation (ARRAY< Point<2> > * xi, SurfaceElementIndex elnr,2557ARRAY< Point<3> > * x,2558ARRAY< Mat<3,2> > * dxdxi)2559{2560if (mesh.coarsemesh)2561{2562const HPRefElement & hpref_el =2563(*mesh.hpelements) [mesh[elnr].hp_elnr];25642565// xi umrechnen2566double lami[4];2567FlatVector vlami(4, lami);25682569ArrayMem<Point<2>, 50> coarse_xi (xi->Size());25702571for (int pi = 0; pi < xi->Size(); pi++)2572{2573vlami = 0;2574mesh[elnr].GetShapeNew ( (*xi)[pi], vlami);25752576Point<2> cxi(0,0);2577for (int i = 0; i < hpref_el.np; i++)2578for (int j = 0; j < 2; j++)2579cxi(j) += hpref_el.param[i][j] * lami[i];25802581coarse_xi[pi] = cxi;2582}25832584mesh.coarsemesh->GetCurvedElements().2585CalcMultiPointSurfaceTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi);258625872588Mat<2,2> trans;2589Mat<3,2> dxdxic;2590if (dxdxi)2591{2592MatrixFixWidth<2> dlami(4);2593dlami = 0;25942595for (int pi = 0; pi < xi->Size(); pi++)2596{2597mesh[elnr].GetDShapeNew ( (*xi)[pi], dlami);25982599trans = 0;2600for (int k = 0; k < 2; k++)2601for (int l = 0; l < 2; l++)2602for (int i = 0; i < hpref_el.np; i++)2603trans(l,k) += hpref_el.param[i][l] * dlami(i, k);26042605dxdxic = (*dxdxi)[pi];2606(*dxdxi)[pi] = dxdxic * trans;2607}2608}26092610return;2611}261226132614261526162617Vector shapes;2618DenseMatrix dshapes;2619ARRAY<Vec<3> > coefs;262026212622const Element2d & el = mesh[elnr];2623ELEMENT_TYPE type = el.GetType();26242625SurfaceElementInfo info;2626info.elnr = elnr;2627info.order = order;2628info.ndof = info.nv = (type == TRIG) ? 3 : 4;2629if (info.order > 1)2630{2631const MeshTopology & top = mesh.GetTopology();26322633top.GetSurfaceElementEdges (elnr+1, info.edgenrs);2634for (int i = 0; i < info.edgenrs.Size(); i++)2635info.edgenrs[i]--;2636info.facenr = top.GetSurfaceElementFace (elnr+1)-1;26372638for (int i = 0; i < info.edgenrs.Size(); i++)2639info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];2640info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];2641}26422643GetCoefficients (info, coefs);26442645if (x)2646{2647for (int j = 0; j < xi->Size(); j++)2648{2649CalcElementShapes (info, (*xi)[j], shapes);2650(*x)[j] = 0;2651for (int i = 0; i < coefs.Size(); i++)2652(*x)[j] += shapes(i) * coefs[i];2653}2654}26552656if (dxdxi)2657{2658for (int ip = 0; ip < xi->Size(); ip++)2659{2660CalcElementDShapes (info, (*xi)[ip], dshapes);26612662(*dxdxi)[ip] = 0;2663for (int i = 0; i < coefs.Size(); i++)2664for (int j = 0; j < 3; j++)2665for (int k = 0; k < 2; k++)2666(*dxdxi)[ip](j,k) += dshapes(i,k) * coefs[i](j);2667}2668}2669}26702671void CurvedElements ::2672CalcMultiPointElementTransformation (ARRAY< Point<3> > * xi, ElementIndex elnr,2673ARRAY< Point<3> > * x,2674ARRAY< Mat<3,3> > * dxdxi)2675{2676if (mesh.coarsemesh)2677{2678const HPRefElement & hpref_el =2679(*mesh.hpelements) [mesh[elnr].hp_elnr];26802681// xi umrechnen2682double lami[8];2683FlatVector vlami(8, lami);268426852686ArrayMem<Point<3>, 50> coarse_xi (xi->Size());26872688for (int pi = 0; pi < xi->Size(); pi++)2689{2690vlami = 0;2691mesh[elnr].GetShapeNew ( (*xi)[pi], vlami);26922693Point<3> cxi(0,0,0);2694for (int i = 0; i < hpref_el.np; i++)2695for (int j = 0; j < 3; j++)2696cxi(j) += hpref_el.param[i][j] * lami[i];26972698coarse_xi[pi] = cxi;2699}27002701mesh.coarsemesh->GetCurvedElements().2702CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi);270327042705Mat<3,3> trans, dxdxic;2706if (dxdxi)2707{2708MatrixFixWidth<3> dlami(8);2709dlami = 0;27102711for (int pi = 0; pi < xi->Size(); pi++)2712{2713mesh[elnr].GetDShapeNew ( (*xi)[pi], dlami);27142715trans = 0;2716for (int k = 0; k < 3; k++)2717for (int l = 0; l < 3; l++)2718for (int i = 0; i < hpref_el.np; i++)2719trans(l,k) += hpref_el.param[i][l] * dlami(i, k);27202721dxdxic = (*dxdxi)[pi];2722(*dxdxi)[pi] = dxdxic * trans;2723}2724}27252726return;2727}272827292730273127322733273427352736Vector shapes;2737MatrixFixWidth<3> dshapes;273827392740const Element & el = mesh[elnr];2741ELEMENT_TYPE type = el.GetType();27422743ElementInfo info;2744info.elnr = elnr;2745info.order = order;2746info.ndof = info.nv = MeshTopology::GetNVertices (type);2747if (info.order > 1)2748{2749const MeshTopology & top = mesh.GetTopology();27502751info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);2752for (int i = 0; i < info.nedges; i++)2753info.edgenrs[i]--;27542755info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);2756for (int i = 0; i < info.nfaces; i++)2757info.facenrs[i]--;27582759for (int i = 0; i < info.nedges; i++)2760info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];2761for (int i = 0; i < info.nfaces; i++)2762info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];2763// info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];2764}27652766ARRAY<Vec<3> > coefs(info.ndof);2767GetCoefficients (info, &coefs[0]);2768if (x)2769{2770for (int j = 0; j < xi->Size(); j++)2771{2772CalcElementShapes (info, (*xi)[j], shapes);2773(*x)[j] = 0;2774for (int i = 0; i < coefs.Size(); i++)2775(*x)[j] += shapes(i) * coefs[i];2776}2777}2778if (dxdxi)2779{2780for (int ip = 0; ip < xi->Size(); ip++)2781{2782CalcElementDShapes (info, (*xi)[ip], dshapes);27832784(*dxdxi)[ip] = 0;2785for (int i = 0; i < coefs.Size(); i++)2786for (int j = 0; j < 3; j++)2787for (int k = 0; k < 3; k++)2788(*dxdxi)[ip](j,k) += dshapes(i,k) * coefs[i](j);2789}2790}2791}27922793279427952796void CurvedElements ::2797CalcMultiPointElementTransformation (ElementIndex elnr, int n,2798const double * xi, int sxi,2799double * x, int sx,2800double * dxdxi, int sdxdxi)2801{2802if (mesh.coarsemesh)2803{2804const HPRefElement & hpref_el =2805(*mesh.hpelements) [mesh[elnr].hp_elnr];28062807// xi umrechnen2808double lami[8];2809FlatVector vlami(8, lami);281028112812ArrayMem<double, 100> coarse_xi (3*n);28132814for (int pi = 0; pi < n; pi++)2815{2816vlami = 0;2817Point<3> pxi;2818for (int j = 0; j < 3; j++)2819pxi(j) = xi[pi*sxi+j];28202821mesh[elnr].GetShapeNew ( pxi, vlami);28222823Point<3> cxi(0,0,0);2824for (int i = 0; i < hpref_el.np; i++)2825for (int j = 0; j < 3; j++)2826cxi(j) += hpref_el.param[i][j] * lami[i];28272828for (int j = 0; j < 3; j++)2829coarse_xi[3*pi+j] = cxi(j);2830}28312832mesh.coarsemesh->GetCurvedElements().2833CalcMultiPointElementTransformation (hpref_el.coarse_elnr, n,2834&coarse_xi[0], 3,2835x, sx,2836dxdxi, sdxdxi);28372838Mat<3,3> trans, dxdxic;2839if (dxdxi)2840{2841MatrixFixWidth<3> dlami(8);2842dlami = 0;28432844for (int pi = 0; pi < n; pi++)2845{2846Point<3> pxi;2847for (int j = 0; j < 3; j++)2848pxi(j) = xi[pi*sxi+j];28492850mesh[elnr].GetDShapeNew (pxi, dlami);28512852trans = 0;2853for (int k = 0; k < 3; k++)2854for (int l = 0; l < 3; l++)2855for (int i = 0; i < hpref_el.np; i++)2856trans(l,k) += hpref_el.param[i][l] * dlami(i, k);28572858Mat<3> mat_dxdxic, mat_dxdxi;2859for (int j = 0; j < 3; j++)2860for (int k = 0; k < 3; k++)2861mat_dxdxic(j,k) = dxdxi[pi*sdxdxi+3*j+k];28622863mat_dxdxi = mat_dxdxic * trans;28642865for (int j = 0; j < 3; j++)2866for (int k = 0; k < 3; k++)2867dxdxi[pi*sdxdxi+3*j+k] = mat_dxdxi(j,k);28682869// dxdxic = (*dxdxi)[pi];2870// (*dxdxi)[pi] = dxdxic * trans;2871}2872}2873return;2874}287528762877287828792880288128822883Vector shapes;2884MatrixFixWidth<3> dshapes;288528862887const Element & el = mesh[elnr];2888ELEMENT_TYPE type = el.GetType();28892890ElementInfo info;2891info.elnr = elnr;2892info.order = order;2893info.ndof = info.nv = MeshTopology::GetNVertices (type);2894if (info.order > 1)2895{2896const MeshTopology & top = mesh.GetTopology();28972898info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0);2899for (int i = 0; i < info.nedges; i++)2900info.edgenrs[i]--;29012902info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0);2903for (int i = 0; i < info.nfaces; i++)2904info.facenrs[i]--;29052906for (int i = 0; i < info.nedges; i++)2907info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];2908for (int i = 0; i < info.nfaces; i++)2909info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]];2910// info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];2911}29122913ARRAY<Vec<3> > coefs(info.ndof);2914GetCoefficients (info, &coefs[0]);2915if (x)2916{2917for (int j = 0; j < n; j++)2918{2919Point<3> xij, xj;2920for (int k = 0; k < 3; k++)2921xij(k) = xi[j*sxi+k];29222923CalcElementShapes (info, xij, shapes);2924xj = 0;2925for (int i = 0; i < coefs.Size(); i++)2926xj += shapes(i) * coefs[i];29272928for (int k = 0; k < 3; k++)2929x[j*sx+k] = xj(k);2930}2931}2932if (dxdxi)2933{2934for (int ip = 0; ip < n; ip++)2935{2936Point<3> xij;2937for (int k = 0; k < 3; k++)2938xij(k) = xi[ip*sxi+k];29392940CalcElementDShapes (info, xij, dshapes);29412942Mat<3> dxdxij;2943dxdxij = 0.0;2944for (int i = 0; i < coefs.Size(); i++)2945for (int j = 0; j < 3; j++)2946for (int k = 0; k < 3; k++)2947dxdxij(j,k) += dshapes(i,k) * coefs[i](j);294829492950for (int j = 0; j < 3; j++)2951for (int k = 0; k < 3; k++)2952dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k);2953}2954}2955}2956295729582959296029612962296329642965};296629672968#endif296929702971