metric.cpp
来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C++ 代码 · 共 1,214 行 · 第 1/3 页
CPP
1,214 行
// -*- Mode : c++ -*-//// SUMMARY : // USAGE : // ORG : // AUTHOR : Frederic Hecht// E-MAIL : hecht@ann.jussieu.fr///* This file is part of Freefem++ Freefem++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Freefem++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Freefem++; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include <stdio.h>#include "Meshio.h"#include "Mesh2.h"namespace bamg {inline Real8 det3x3(Real8 A[3] ,Real8 B[3],Real8 C[3]){ return A[0] * ( B[1]*C[2]-B[2]*C[1]) - A[1] * ( B[0]*C[2]-B[2]*C[0]) + A[2] * ( B[0]*C[1]-B[1]*C[0]);}SaveMetricInterpole LastMetricInterpole;void ReductionSimultanee( MetricAnIso M1, MetricAnIso M2,double & l1,double & l2, D2xD2 & V) { double a11=M1.a11,a21=M1.a21,a22=M1.a22; double b11=M2.a11,b21=M2.a21,b22=M2.a22; // M1 v = l M2 v // (M1 - l M2) v =0 // det (M1 - l M2) =0 // det (M1 - l M2) = a l^2 + b l + c; // = (a11 - l * b11) * (a22 - l * b22) - (a21 - l * b21 ) ^2 // const double eps = 1.e-5; const double /*c11 = a11*a11,*/ c21= a21*a21; const double /*d11 = b11*b11,*/ d21= b21*b21; const double a=b11*b22 - d21; const double b=-a11*b22-a22*b11+2*a21*b21; const double c=-c21+a11*a22; const double bb = b*b,ac= a*c; const double delta = bb - 4 * ac; // const double kk=c11+c22+c21+d11+d21+d22; // modif F Hecht feb 1998 // cerr.precision(14); //cerr << bb << " " << ac << " " << bb << " " <<a << endl; // cerr << a11 << " " << a21 << " " << a22 << endl; //cerr << b11 << " " << b21 << " " << b22 << endl; if (bb + Abs(ac) < 1.0e-20 || (delta< 1.0E-4 * bb ) ) { // racine double; // cerr << "double " << endl ; if (Abs(a) < 1.e-30 ) l1 = l2 = 0; else l1=l2=-b/(2*a); V= D2xD2(1,0,0,1); } else { // cerr << " -- " << a << endl ; const double delta2 = sqrt(delta); l1= (-b - delta2)/(2*a); l2= (-b + delta2)/(2*a); // M1 v = l M2 v // ( (M1 - I M2) x,y) = (x,(M1 - I M2) y) \forall y // so Ker((M1 - I M2)) = Im((M1 - I M2))^\perp double v0 = a11-l1*b11, v1 = a21-l1*b21,v2 = a22 - l1*b22; double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; double vp1x,vp1y,vp2x,vp2y; if(s1 < s0) s0=sqrt(s0),vp1x=v1/s0,vp1y=-v0/s0; else s1=sqrt(s1),vp1x=v2/s1,vp1y=-v1/s1; v0 = a11-l2*b11, v1 = a21-l2*b21,v2 = a22 - l2*b22; s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; if(s1 < s0) s0=sqrt(s0),vp2x=v1/s0,vp2y=-v0/s0; else s1=sqrt(s1),vp2x=v2/s1,vp2y=-v1/s1;#ifdef DEBUG assert(Abs(vp1y)+Abs(vp2y)>0);#endif V=D2xD2(vp1x,vp2x,vp1y,vp2y); } return;}MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) ;MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) { D2xD2 M; double l1,l2; ReductionSimultanee(M1,M2,l1,l2,M); R2 v0(M.x.x,M.y.x); R2 v1(M.x.y,M.y.y); D2xD2 M_1(M.inv()); D2xD2 D(Max(M1(v0,v0),M2(v0,v0)),0,0,Max(M1(v1,v1),M2(v1,v1))); D2xD2 Mi(M_1.t()*D*M_1); return MetricAnIso(Mi.x.x,0.5*(Mi.x.y+Mi.y.x),Mi.y.y);}MetricAnIso::MetricAnIso(const Real8 a[3],const MetricAnIso m0, const MetricAnIso m1,const MetricAnIso m2 ){ MetricAnIso mab(a[0]*m0.a11 + a[1]*m1.a11 + a[2]*m2.a11, a[0]*m0.a21 + a[1]*m1.a21 + a[2]*m2.a21, a[0]*m0.a22 + a[1]*m1.a22 + a[2]*m2.a22); MatVVP2x2 vab(mab); R2 v1(vab.v.x,vab.v.y); R2 v2(-v1.y,v1.x); Real8 h1 = a[0] / m0(v1) + a[1] / m1(v1) + a[2] / m2(v1); Real8 h2 = a[0] / m0(v2) + a[1] / m1(v2) + a[2] / m2(v2); vab.lambda1 = 1 / (h1*h1); vab.lambda2 = 1 / (h2*h2); *this = vab;} MetricAnIso::MetricAnIso( Real8 a,const MetricAnIso ma, Real8 b,const MetricAnIso mb){ MetricAnIso mab(a*ma.a11+b*mb.a11,a*ma.a21+b*mb.a21,a*ma.a22+b*mb.a22); MatVVP2x2 vab(mab); R2 v1(vab.v.x,vab.v.y); R2 v2(-v1.y,v1.x); Real8 h1 = a / ma(v1) + b / mb(v1); Real8 h2 = a / ma(v2) + b / mb(v2); vab.lambda1 = 1 / (h1*h1); vab.lambda2 = 1 / (h2*h2); *this = vab;} MatVVP2x2::MatVVP2x2(const MetricAnIso M) { double a11=M.a11,a21=M.a21,a22=M.a22; const double eps = 1.e-5; double c11 = a11*a11, c22 = a22*a22, c21= a21*a21; double b=-a11-a22,c=-c21+a11*a22; double delta = b*b - 4 * c ; double n2=(c11+c22+c21); if ( n2 < 1e-30) lambda1=lambda2=0,v.x=1,v.y=0; else if (delta < eps*n2) { lambda1=lambda2=-b/2, v.x=1,v.y=0; } else { // --- construction de 2 vecteur dans (Im ( A - D(i) Id) ortogonal delta = sqrt(delta); lambda1 = (-b-delta)/2.0,lambda2 = (-b+delta)/2.0; double v0 = a11-lambda1, v1 = a21,v2 = a22 - lambda1; double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; if(s1 < s0) s0=sqrt(s0),v.x=v1/s0,v.y=-v0/s0; else s1=sqrt(s1),v.x=v2/s1,v.y=-v1/s1; };} int MetricAnIso::IntersectWith(const MetricAnIso M2) { //cerr << " - " << *this << M2 << endl; int r=0; MetricAnIso & M1 = *this; D2xD2 M; double l1,l2; ReductionSimultanee(*this,M2,l1,l2,M); // cerr << M << endl; R2 v1(M.x.x,M.y.x); R2 v2(M.x.y,M.y.y); double l11=M1(v1,v1); double l12=M1(v2,v2); double l21=M2(v1,v1); double l22=M2(v2,v2); if ( l11 < l21 ) r=1,l11=l21; if ( l12 < l22 ) r=1,l12=l22; // cerr << r << endl; if (r) { // change D2xD2 M_1(M.inv()); D2xD2 D(l11,0,0,l12); D2xD2 Mi(M_1.t()*D*M_1); a11=Mi.x.x; a21=0.5*(Mi.x.y+Mi.y.x); a22=Mi.y.y; } return r;}void Triangles::IntersectGeomMetric(const Real8 err=1,const int iso=0){ if(verbosity>1) cout << " -- IntersectGeomMetric geometric err=" << err << (iso ? " iso " : " aniso " ) << endl; Real8 ss[2]={0.00001,0.99999}; Real8 errC = 2*sqrt(2*err); Real8 hmax = Gh.MaximalHmax(); Real8 hmin = Gh.MinimalHmin(); Real8 maxaniso = 1e6; assert(hmax>0); SetVertexFieldOn(); if (errC > 1) errC = 1; for (Int4 i=0;i<nbe;i++) for (int j=0;j<2;j++) { Vertex V; VertexOnGeom GV; // cerr << Number(edges[i]) << " " << ss[j] << endl; Gh.ProjectOnCurve(edges[i],ss[j],V,GV); { GeometricalEdge * eg = GV; Real8 s = GV; R2 tg; // cerr << i << " " << j << " " << Number(V) << " on = " // << Gh.Number(eg) << " at s = " << s << " " << endl; Real8 R1= eg->R1tg(s,tg); // cerr << " R = " << 1/Max(R1,1e-20) << tg << " on x " // << V.r << errC/ Max(R1,1e-20) << " hold=" <<V.m(tg) << " " << endl; Real8 ht = hmax; if (R1>1.0e-20) { // err relative to the length of the edge ht = Min(Max(errC/R1,hmin),hmax); } Real8 hn = iso? ht : Min(hmax,ht*maxaniso); //cerr << ht << " " << hn << "m=" << edges[i][j].m << endl; assert(ht>0 && hn>0); MatVVP2x2 Vp(1/(ht*ht),1/(hn*hn),tg); //cerr << " : " ; Metric MVp(Vp); // cerr << " : " << MVp << endl; edges[i][j].m.IntersectWith(MVp); //cerr << " . " << endl; } } // the problem is for the vertex on vertex }/*void Triangles::BoundAnisotropy(Real8 anisomax){ if (verbosity > 1) cout << " -- BoundAnisotropy by " << anisomax << endl; Real8 h1=1.e30,h2=1e-30,rx=0; Real8 coef = 1./(anisomax*anisomax); Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30; for (Int4 i=0;i<nbv;i++) { MatVVP2x2 Vp(vertices[i]); h1=Min(h1,Vp.lmin()); h2=Max(h2,Vp.lmax()); rx = Max(rx,Vp.Aniso2()); Vp.BoundAniso2(coef); hn1=Min(hn1,Vp.lmin()); hn2=Max(hn2,Vp.lmax()); rnx = Max(rnx,Vp.Aniso2()); vertices[i].m = Vp; } if (verbosity>2) { cout << " input : Hmin = " << sqrt(1/h2) << " Hmax = " << sqrt(1/h1) << " factor of anisotropy max = " << sqrt(rx) << endl; cout << " output: Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) << " factor of anisotropy max = " << sqrt(rnx) << endl; }}*/void Triangles::BoundAnisotropy(Real8 anisomax,Real8 hminaniso){ double lminaniso = 1/ (Max(hminaniso*hminaniso,1e-100)); if (verbosity > 1) cout << " -- BoundAnisotropy by " << anisomax << endl; Real8 h1=1.e30,h2=1e-30,rx=0; Real8 coef = 1./(anisomax*anisomax); Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30; for (Int4 i=0;i<nbv;i++) { MatVVP2x2 Vp(vertices[i]); double lmax=Vp.lmax(); h1=Min(h1,Vp.lmin()); h2=Max(h2,Vp.lmax()); rx = Max(rx,Vp.Aniso2()); Vp *= Min(lminaniso,lmax)/lmax; Vp.BoundAniso2(coef); hn1=Min(hn1,Vp.lmin()); hn2=Max(hn2,Vp.lmax()); rnx = Max(rnx,Vp.Aniso2()); vertices[i].m = Vp; } if (verbosity>2) { cout << " input : Hmin = " << sqrt(1/h2) << " Hmax = " << sqrt(1/h1) << " factor of anisotropy max = " << sqrt(rx) << endl; cout << " output: Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) << " factor of anisotropy max = " << sqrt(rnx) << endl; }}void Triangles::IntersectConsMetric(const double * s,const Int4 nbsol,const int * typsols, const Real8 hmin1,const Real8 hmax1,const Real8 coef, const Real8 anisomax ,const Real8 CutOff,const int NbJacobi, const int DoNormalisation,const double power,const int choice){ // the array of solution s is store // sol0,sol1,...,soln on vertex 0 // sol0,sol1,...,soln on vertex 1 // etc. // choise = 0 => H is computed with green formule // otherwise => H is computed from P2 on 4T const int dim = 2; int sizeoftype[] = { 1, dim ,dim * (dim+1) / 2, dim * dim } ; // computation of the nb of field Int4 ntmp = 0; if (typsols) { for (Int4 i=0;i<nbsol;i++) ntmp += sizeoftype[typsols[i]]; } else ntmp = nbsol; // n is the total number of fields const Int4 n = ntmp; Int4 i,k,iA,iB,iC,iv; R2 O(0,0); int RelativeMetric = CutOff>1e-30; Real8 hmin = Max(hmin1,MinimalHmin()); Real8 hmax = Min(hmax1,MaximalHmax()); Real8 coef2 = 1/(coef*coef); if(verbosity>1) { cout << " -- Construction of Metric: Nb of field. " << n << " nbt = " << nbt << " nbv= " << nbv << " coef = " << coef << endl << " hmin = " << hmin << " hmax=" << hmax << " anisomax = " << anisomax << " Nb Jacobi " << NbJacobi << " Power = " << power ; if (RelativeMetric) cout << " RelativeErr with CutOff= " << CutOff << endl; else cout << " Absolute Err" <<endl; } double *ss=(double*)s;//, *ssiii = ss; double sA,sB,sC; Real8 *detT = new Real8[nbt]; Real8 *Mmass= new Real8[nbv]; Real8 *Mmassxx= new Real8[nbv]; Real8 *dxdx= new Real8[nbv]; Real8 *dxdy= new Real8[nbv]; Real8 *dydy= new Real8[nbv]; Real8 *workT= new Real8[nbt]; Real8 *workV= new Real8[nbv]; int *OnBoundary = new int[nbv]; for (iv=0;iv<nbv;iv++)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?