metric.h

来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C头文件 代码 · 共 226 行

H
226
字号
// -*- 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 */#ifndef TYPEMETRIX#define TYPEMETRIX MetricAnIso#endif//#include "R2.h"namespace bamg {typedef P2<double,double> D2;typedef P2xP2<double,double> D2xD2;class  MetricAnIso;class MatVVP2x2;class MetricIso;typedef TYPEMETRIX Metric;class MetricIso{  friend class MatVVP2x2;   Real4 h;public:  MetricIso(Real4 a): h(a){}  MetricIso(const MetricAnIso M);// {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));}  MetricIso(Real8 a11,Real8 a21,Real8 a22);// {*this=MetricAnIso(a11,a21,a22));}  MetricIso(): h(1) {}; //   MetricIso(const Real8  a[3],const  MetricIso m0,	   const  MetricIso m1,const  MetricIso m2 )    : h(hinterpole 	? (a[0]*m0.h+a[1]*m1.h+a[2]*m2.h)	: 1/sqrt(a[0]/(m0.h*m0.h)+a[1]/(m1.h*m1.h)+a[2]/(m2.h*m2.h))) {}    MetricIso(const Real8  a,const  MetricIso ma,	          const Real8  b,const  MetricIso mb)    : h(hinterpole	? a*ma.h+b*mb.h	:1/sqrt(a/(ma.h*ma.h)+b/(mb.h*mb.h))) {}  R2 Orthogonal(const R2 A)const {return R2(-h*A.y,h*A.x);}  R2 Orthogonal(const I2 A)const {return R2(-h*A.y,h*A.x);}//  D2 Orthogonal(const D2 A)const {return D2(-h*A.y,h*A.x);}  Real8 operator()(R2 x) const { return sqrt((x,x))/h;};  Real8 operator()(R2 x,R2 y) const { return ((x,y))/(h*h);};  int  IntersectWith(MetricIso M) {int r=0;if (M.h<h) r=1,h=M.h;return r;}  MetricIso operator*(Real8 c) const {return  MetricIso(h/c);}   MetricIso operator/(Real8 c) const {return  MetricIso(h*c);}  Real8 det() const {return 1./(h*h*h*h);}      operator D2xD2(){ return D2xD2(1/(h*h),0.,0.,1/(h*h));}  void     Box(Real4 & hx,Real4 & hy) { hx=h,hy=h;}  friend ostream& operator <<(ostream& f, const  MetricIso & M)  {f << " h=" << M.h<< ";" ;   return f;}#ifdef DRAWING  void Draw(R2 ) const;#endif};class MetricAnIso{ public:  friend class MatVVP2x2;  Real8 a11,a21,a22;  MetricAnIso(Real8 a): a11(1/(a*a)),a21(0),a22(1/(a*a)){}  MetricAnIso(Real8 a,Real8 b,Real8 c) :a11(a),a21(b),a22(c){}  MetricAnIso()  {}; //   MetricAnIso(const Real8  a[3],const  MetricAnIso m0,	      const  MetricAnIso m1,const  MetricAnIso m2 );  R2 mul(const R2 x)const {return R2(a11*x.x+a21*x.y,a21*x.x+a22*x.y);}  Real8 det() const {return a11*a22-a21*a21;}    R2 Orthogonal(const R2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}  R2 Orthogonal(const I2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}//  D2 Orthogonal(const D2 x){return D2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}  MetricAnIso( Real8  a,const  MetricAnIso ma,	       Real8  b,const  MetricAnIso mb);  int  IntersectWith(const MetricAnIso M);  MetricAnIso operator*(Real8 c) const {Real8 c2=c*c;return  MetricAnIso(a11*c2,a21*c2,a22*c2);}   MetricAnIso operator/(Real8 c) const {Real8 c2=1/(c*c);return  MetricAnIso(a11*c2,a21*c2,a22*c2);}   operator D2xD2(){ return D2xD2(a11,a21,a21,a22);}  Real8 operator()(R2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);};//  Real8 operator()(D2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);};  Real8 operator()(R2 x,R2 y) const { return x.x*y.x*a11+(x.x*x.y+x.y*y.x)*a21+x.y*y.y*a22;};  inline void  Box(Real4 &hx,Real4 &hy) const ;   friend ostream& operator <<(ostream& f, const  MetricAnIso & M)  {f << " mtr a11=" << M.a11 << " a21=a12=" << M.a21 << " a22=" << M.a22 << ";" ;   return f;}#ifdef DRAWING  void Draw(R2 ) const;#endif  MetricAnIso(const MatVVP2x2);};class MatVVP2x2 {  friend  class MetricAnIso;  friend  class MetricIso;public:  double lambda1,lambda2;  D2 v;  MatVVP2x2(double r1,double r2,const D2 vp1): lambda1(r1),lambda2(r2),v(vp1){}    void  Abs(){lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);}  void  pow(double p){lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);}  void  Min(double a) { lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;}  void  Max(double a) { lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;}  void Minh(double h) {Max(1.0/(h*h));}  void Maxh(double h) {Min(1.0/(h*h));}  void Isotrope() {lambda1=lambda2=bamg::Max(lambda1,lambda2);}  friend ostream& operator <<(ostream& f, const MatVVP2x2 & c)  { f << '{' << 1/sqrt(c.lambda1)<< ',' << 1/sqrt(c.lambda2) << ','<< c.v << '}' <<flush ; return f; }  friend istream& operator >>(istream& f,  MatVVP2x2 & c)  { f >> c.lambda1 >>c.lambda2 >> c.v.x >> c.v.y ;c.v /= Norme2(c.v); return f; }  MatVVP2x2(const MetricAnIso );  MatVVP2x2(const MetricIso M) :  lambda1(1/(M.h*M.h)),lambda2(1/(M.h*M.h)),v(1,0) {}  Real8 hmin() const {return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));}  Real8 hmax() const {return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));}  Real8 lmax() const {return bamg::Max3(lambda1,lambda2,1e-30);}  Real8 lmin() const {return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);}  Real8 Aniso2() const  { return lmax()/lmin();}  inline void BoundAniso2(const Real8 coef);  Real8 Aniso() const  { return sqrt( Aniso2());}  void BoundAniso(const Real8 c){ BoundAniso2(1/(c*c));}  void operator *=(double coef){ lambda1*=coef;lambda2*=coef;}};inline void  MatVVP2x2::BoundAniso2(const Real8 coef) {  if (coef<=1.00000000001)     if (lambda1 < lambda2)      lambda1 = bamg::Max(lambda1,lambda2*coef);    else      lambda2 = bamg::Max(lambda2,lambda1*coef);  else  // a verifier     if (lambda1 > lambda2)      lambda1 = bamg::Min(lambda1,lambda2*coef);    else      lambda2 = bamg::Min(lambda2,lambda1*coef);}void ReductionSimultanee( MetricAnIso M1,  MetricAnIso M2,double & l1,double & l2, D2xD2 & V) ;inline MetricAnIso::MetricAnIso(const MatVVP2x2 M)  { //     recompose M in: M = V^t lambda V   //     V = ( v,v^\perp)  //  where v^\perp = (-v_1,v_0)  double v00=M.v.x*M.v.x;  double v11=M.v.y*M.v.y;  double v01=M.v.x*M.v.y;  a11=v00*M.lambda1+v11*M.lambda2;  a21=v01*(M.lambda1-M.lambda2);  a22=v00*M.lambda2+v11*M.lambda1;}inline   void  MetricAnIso::Box(Real4 &hx,Real4 &hy) const {  Real8 d=  a11*a22-a21*a21;  hx = sqrt(a22/d);  hy = sqrt(a11/d);  //  cerr << " hx = " << hx << " hy =  " << hy << endl;}inline MetricIso::MetricIso(const MetricAnIso M)   {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));}  inline  MetricIso::MetricIso(Real8 a11,Real8 a21,Real8 a22)  {MatVVP2x2 vp(MetricAnIso(a11,a21,a22));h=1/sqrt(Max(vp.lambda1,vp.lambda2));}class SaveMetricInterpole {  friend  Real8 LengthInterpole(const MetricAnIso ,const  MetricAnIso , R2 );  friend Real8 abscisseInterpole(const MetricAnIso ,const  MetricAnIso , R2 ,Real8 ,int );  int opt;  Real8 lab;  Real8 L[1024],S[1024];};extern SaveMetricInterpole  LastMetricInterpole; // for optimization  Real8 LengthInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB); Real8 abscisseInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB,Real8 s,int optim=0);inline Real8 LengthInterpole(Real8 la,Real8 lb) {   return ( Abs(la - lb) < 1.0e-6*Max3(la,lb,1.0e-20) ) ?  (la+lb)/2  : la*lb*log(la/lb)/(la-lb);}inline Real8 abscisseInterpole(Real8 la,Real8 lb,Real8 lab,Real8 s){ return ( Abs(la - lb) <1.0e-6*Max3(la,lb,1.0e-20))  ? s : (exp(s*lab*(la-lb)/(la*lb))-1)*lb/(la-lb);}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?