⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genericmesh.hpp

📁 FreeFem++可以生成高质量的有限元网格。可以用于流体力学
💻 HPP
📖 第 1 页 / 共 2 页
字号:
// ORIG-DATE:     Dec 2007// -*- Mode : c++ -*-//// SUMMARY  :  Model of generic mesh 1d,2d,3d    // USAGE    : LGPL      // ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE // AUTHOR   : Frederic Hecht// E-MAIL   : frederic.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 Thank to the ARN ()  FF2A3 grant ref:ANR-07-CIS7-002-01  */#ifndef GENERICMESH_HPP_#define GENERICMESH_HPP_// la regle de programmation 3  extern long verbosity;#include "cassert" #include "assertion.hpp" #include <cstdlib>#include <utility>//#include <algorithm>//#include <Functional>#include "RefCounter.hpp"using namespace ::std;#include "Serialize.hpp"#include "GQuadTree.hpp"// definition Rnamespace Fem2D  {#include "R3.hpp"#include "Label.hpp"#include "HashTable.hpp"  const double UnSetMesure=-1e+200;  // struct R {}; template<int d> struct typeRd {typedef R0 Rd;};template<> struct typeRd<1> {typedef R1 Rd;};template<> struct typeRd<2> {typedef R2 Rd;};template<> struct typeRd<3> {typedef R3 Rd;};const int NbTypeItemElement = 4;const int TypeVertex =0;const int TypeEdge   =1;const int TypeFace   =2;const int TypeVolume =3;class DataFENodeDF {    int  * nbref; // pointer  on common ref counter public:  int ndfon[4];  const int NbOfElements;  const  int NbOfNodes;  const  int NbOfDF;    const int * const NodesOfElement;  const int * const FirstDfOfNodeData;  const int * const FirstNodeOfElement; //  0   const int MaxNbNodePerElement;  const int MaxNbDFPerElement;  int ndfonVertex()const {return ndfon[0];}  int ndfonEdge()const {return ndfon[1];}  int ndfonFace()const {return ndfon[2];}  int ndfonTet()const {return ndfon[3];}  DataFENodeDF(const DataFENodeDF & m)    :    nbref( m.nbref ) ,    NbOfElements(m.NbOfElements),    NbOfNodes(m.NbOfNodes),    NbOfDF(m.NbOfDF),    NodesOfElement(m.NodesOfElement),    FirstDfOfNodeData(m.FirstDfOfNodeData),    FirstNodeOfElement(m.FirstNodeOfElement),    MaxNbNodePerElement(m.MaxNbNodePerElement),    MaxNbDFPerElement(m.MaxNbDFPerElement)     {      for(int i=0;i<NbTypeItemElement;++i)	    ndfon[i]=m.ndfon[i];	(*nbref)++; // add one to the ref counter     }  DataFENodeDF( 	       int andfon[NbTypeItemElement],	       int aNbOfElements,	       int aNbOfNodes,	       int aNbOfDF,	       const int * aNodesOfElement,	       const int * aFirstDfOfNodeData,	       int aMaxNbNodePerElement,	       int aMaxNbDFPerElement)    :    nbref( new int(0)),// new ref counter     NbOfElements(aNbOfElements),    NbOfNodes(aNbOfNodes),    NbOfDF(aNbOfDF),    NodesOfElement(aNodesOfElement),    FirstDfOfNodeData(aFirstDfOfNodeData),    FirstNodeOfElement(0),    MaxNbNodePerElement(aMaxNbNodePerElement),    MaxNbDFPerElement(aMaxNbDFPerElement)   {    for(int i=0;i<NbTypeItemElement;++i)      ndfon[i]=andfon[i];  } ~DataFENodeDF()    {    if ((*nbref)==0) // remove if nbref ==0       {	 delete nbref;         delete [] NodesOfElement;         delete [] FirstDfOfNodeData;         delete [] FirstNodeOfElement;       }	else  (*nbref)--;  }private:	void operator=(const DataFENodeDF &) ;    	};template<typename Rn>class GenericVertex : public Rn,public Label{      template<typename T,typename B,typename V>        friend class GenericMesh;  friend inline ostream& operator <<(ostream& f, const GenericVertex & v )  { f << (const Rn &) v << ' ' << (const Label &) v   ; return f; }  friend inline istream& operator >> (istream& f,  GenericVertex & v )        { f >> (Rn &) v >> (Label &) v ; return f; }      Rn *normal; // pointeur sur la normal exterieur pour filtre des points de departs   public:  typedef Rn Rd;  static const int d=Rd::d;    GenericVertex() : Rd(),Label(),normal(0) {};  GenericVertex(const Rd & P,int r=0): Rd(P),Label(r),normal(0){}      void SetNormal(Rd *&n,const Rd & N)  { if (normal) {       Rd NN=*normal+N;       *normal= NN/NN.norme(); }    else *(normal=n++)=N;}      Rd Ne() const {return normal ? *normal: Rd();}  bool ninside(const Rd & P) const  {    return normal? (Rd(*this,P),*normal)<=0: true;  }    private: // pas de copie pour ne pas prendre l'adresse  GenericVertex(const GenericVertex &);  void operator=(const GenericVertex &);   };  inline  R1 ExtNormal( GenericVertex<R1> *const v[2],int const f[1])  {   return f[0]==0 ? R1(-1):R1(1);  }  inline  R2 ExtNormal( GenericVertex<R2> *const v[3],int const f[2])  {   return R2(*v[f[1]],*v[f[0]]).perp();  }  inline  R3 ExtNormal( GenericVertex<R3> *const v[4],int const f[3])  {   return R3(*v[f[1]],*v[f[0]])^R3(*v[f[2]],*v[f[0]]) ;  }    template<typename Data>  class GenericElement: public Label {public:  typedef typename Data::V Vertex;  typedef typename Data::V::Rd Rd;  typedef typename Data::RdHat RdHat;// for parametrization   typedef typename Data::RdHatBord RdHatBord;// for parametrization   typedef typename Rd::R R;  static const int nv=Data::NbOfVertices;  // nb  of vertices   static const int ne=Data::NbOfEdges;  // nb  of edges  static const int nf=Data::NbOfFaces;  // nb of faces  static const int nt=Data::NT;  // nb of tets  static const int nitem=nv+ne+nf+nt;  static const int nva=Data::NbOfVertexOnHyperFace;    static const int nea=Data::NbOfAdjElem;    static const int d=Rd::d;    static const int (* const nvedge)[2] ;//  static const int (* const nvface)[3] ;//  static const int (* const onWhatBorder)[nitem] ;//      static const int (* const nvadj)[nva] ;//    static const int nitemdim[4]; //  nv,ne,nf,nt   // variable prive private:  Vertex *vertices[nv]; // an array of 3 pointer to vertex  R mes; public:  GenericElement() {}  const Vertex & operator[](int i) const  {    ASSERTION(i>=0 && i <nv);    return *vertices[i];} // to see triangle as a array of vertex  Vertex & operator[](int i)  {    ASSERTION(i>=0 && i <nv);    return *vertices[i];} // to see triangle as a array of vertex  const Vertex& at(int i) const   { return *vertices[i];} // to see triangle as a array of vert  Vertex& at(int i)    { return *vertices[i];} // to see triangle as a array of vert  void set(Vertex * v0,int * iv,int r,double mss=UnSetMesure)   {     for(int i=0;i<nv;++i)	      vertices[i]=v0+iv[i];    mes=(mss!=UnSetMesure) ? mss : Data::mesure(vertices);    lab=r;    ASSERTION(mss==UnSetMesure && mes>0);  }    istream & Read1(istream & f,Vertex * v0,int n)  {    int iv[nv],ir,err=0;    for (int i=0;i<nv;++i)       {	f >> iv[i];	iv[i]--;	if (  ! (iv[i]>=0 && iv[i]<n)) err++;      }    f >> ir;    if(err || ! f.good() )      {	cerr << " Erreur GenericElement::Read1 " << nv <<  " " << n << "  : " ;	for (int j=0;j<nv;++j) 	  cerr << iv[j] <<  " ";	cerr << " , " << ir <<  endl;	abort();      }    set(v0,iv,ir);     return f;  }     	  Rd Edge(int i) const {ASSERTION(i>=0 && i <ne);    return Rd(at(nvedge[i][0]),at(nvedge[i][1]));}// opposite edge vertex i  Rd N(int i) const  { return ExtNormal(vertices,nvadj[i]);}  Rd PBord(int i,RdHatBord P) const   { return Data::PBord(nvadj[i],P);}    Rd operator()(const RdHat & Phat) const {    Rd r= (1.-Phat.sum())*(*(Rd*) vertices[0]);        for (int i=1;i<nv;++i)      r+=  Phat[i-1]*(*(Rd*) vertices[i]);    return r;  }  int faceOrientation(int i) const   {// def the permutatution of orient the face    int fo =0;    Vertex * f[3]={&at(nvface[i][0]), &at(nvface[i][1]), &at(nvface[i][2])};     if(f[0]>f[1]) fo+=1,Exchange(f[0],f[1]);     if(f[1]>f[2]) { fo+=2,Exchange(f[1],f[2]);     if(f[0]>f[1]) fo+=4,Exchange(f[0],f[1]); }    return fo;  }  bool   EdgeOrientation(int i) const     { return &at(nvedge[i][0]) < &at(nvedge[i][1]);}      R lenEdge(int i) const {ASSERTION(i>=0 && i <3);    Rd E=Edge(i);return sqrt((E,E));}  R  mesure() const {return mes;}      static  int NbNodes(int c)  // use the bit i of c to say if node in objet of dim  i existe  { int c0=(c&1)!=0, c1=(c&2)!=0, c2=(c&4)!=0, c3=(c&8)!=0;      return nv*c0 +ne*c1 +nf*c2 + nt*c3 ;}    static  int NbNodes(const int c[4])  // use the bit i of c to say if node in objet of dim  i existe  { int c0=(c[0])!=0, c1=(c[1])!=0, c2=(c[2])!=0, c3=(c[3])!=0;      return nv*c0 +ne*c1 +nf*c2 + nt*c3 ;}  void Renum(Vertex   *v0, int * r)    {     for (int i=0;i<nv;i++)       vertices[i]=v0+r[vertices[i]-v0];  }  void Change(Vertex   *vold, Vertex *vnew)   {     for (int i=0;i<nv;i++)       vertices[i]=vnew+vertices[i]-vold;  }  //Rd n(int i) const //  unit exterior normal  //  {Rd E=Edge(i);return Rd(E.y,-E.x)/Norme2(E);}        private:  // pas de copie  GenericElement(const  GenericElement &);  GenericElement &operator = (const  GenericElement &);};    template<int N> inline void PermI2J(const void **I,const void **J,int *S)    {	ffassert(0);    }    template<> inline void PermI2J<1>(const void **I,const void **J,int *S)    {	S[0]=0;    }    template<> inline void PermI2J<2>(const void **I,const void **J,int *S)    {	if(I[0]==J[0])	  { assert(I[1]==J[1]);	    S[0]=0;S[1]=1;}	else 	  { assert(I[1]==J[0]&&I[0]==J[1]);	    S[0]=1;S[1]=0;}	    }    template<> inline void PermI2J<3>(const void **I,const void **J,int *S)    {	if(I[0]==J[0]) S[0]=0;	else if(I[0]==J[1]) S[0]=1;	else {S[0]=2; assert(I[0]==J[2]) ;}	if(I[1]==J[0]) S[1]=0;	else if(I[1]==J[1]) S[1]=1;	else {S[1]=2; assert(I[1]==J[2]) ; }	S[2]=3-S[0]-S[1];	assert(I[2]==J[3-S[0]-S[1]]);    }    template<typename T,typename B,typename V>class GenericMesh : public RefCounter{ public:  typedef GenericMesh GMesh;  typedef T Element;     typedef typename V::Rd Rd;  typedef typename Rd::R R;  typedef V  Vertex;  typedef B BorderElement;  typedef  EF23::GTree<V> GTree;  typedef typename Element::RdHat RdHat;// for parametrization                                          int nt,nv,nbe;  R mes,mesb;  //private:  V *vertices;  T *elements;  B *borderelements;  Rd  * bnormalv; //  boundary vertex normal   Rd Pmin,Pmax; // // the bound  of the domain  see BuildBound   static const int nea=T::nea; //  numbering of adj (4 in Tet,  3 in Tria, 2 in seg)   static const int nva=T::nva; //  numbering of vertex in Adj element   static int kfind,kthrough; //  number of search and number of throught element.   int *TheAdjacencesLink; // to store the adj link  k*nea+i -> k'*nea+i'   int *BoundaryElementHeadLink; //  int *ElementConteningVertex;    GTree *gtree;public:  const T & operator[](int i) const {return elements[CheckT(i)];}  const V& operator()(int i) const {return vertices[CheckV(i)];}  const B& be(int i) const {return borderelements[CheckBE(i)];}    T & t(int i)  {return elements[CheckT(i)];}  V & v(int i)  {return vertices[CheckV(i)];}  B & be(int i) {return borderelements[CheckBE(i)];}    GenericMesh()    : nt(0),nv(0),nbe(0),  mes(0.),mesb(0.) ,      vertices(0),elements(0),borderelements(0),bnormalv(0),      TheAdjacencesLink(0),BoundaryElementHeadLink(0),      ElementConteningVertex(0), gtree(0)  {}     void set(int mv,int mt,int mbe)   {    assert(nt==0 && nv==0 && nbe ==0);    nt=mt;    nv=mv;    nbe=mbe;    vertices=new V[nv];    elements= new T[nt];    borderelements = new B[nbe];     assert( nt >=0 && elements);    assert( nv >0 && vertices);      }    int operator()(const T & t) const {return CheckT(&t - elements);}  int operator()(const T * t) const {return CheckT(t - elements);}  int operator()(const V & v) const {return CheckV(&v - vertices);}  int operator()(const V  * v) const{return CheckV(v - vertices);}  int operator()(const B & k) const {return CheckBE(&k - borderelements);}  int operator()(const B  * k) const{return CheckBE(k - borderelements);}  int operator()(int it,int j) const {return operator()(elements[it][j]);}// Nu vertex j of triangle it  int be(int it,int j) const {return operator()(borderelements[it][j]);}// Nu vertex j of triangle it    int CheckV(int i) const { ASSERTION(i>=0 && i < nv); return i;}   int CheckT(int i) const { ASSERTION(i>=0 && i < nt); return i;}  int CheckBE(int i) const { ASSERTION(i>=0 && i < nbe); return i;}       int Contening(const Vertex * v) const{ return ElementConteningVertex[ v  - vertices];}   void BuildAdj();  void BuildSurfaceAdj();  // Add J. Morice function that give the TheAdjacencesSurfaceLink  void Buildbnormalv();  void BuildBound();  void BuildjElementConteningVertex();  void BuildGTree() {if(gtree==0)  gtree=new GTree(vertices,Pmin,Pmax,nv);}      DataFENodeDF BuildDFNumbering(int dfon[NbTypeItemElement]) const ;  DataFENodeDF BuildDFNumbering(int ndfv,int ndfe,int ndff,int ndft) const   { int dfon[NbTypeItemElement]={ndfv,ndfe,ndff,ndft};    return  BuildDFNumbering(dfon);}    int ElementAdj(int k,int &j) const  {    int p=TheAdjacencesLink[nea*k+j];    j=p%nea;    return p>=0 ? p/nea: -1;}  int ElementAdj(int k,int &j,Rd& PHat) const      {    //   return the kk the number of adj element k  to hyperface j (opposite to vertex j)    //   out j: is the new hyperface number in element kk.    // and     // in : Pt is the point  on hyperface j on element k on ref element K hat.    //  remark   lb[j]==0  at enter    // you get the new 	point Pt (in  on hyperface j on element kk    //  and lb[j] ==0 at return (j have change).    int p=TheAdjacencesLink[nea*k+j];    if(p>=0)       {	

⌨️ 快捷键说明

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