📄 genericmesh.hpp
字号:
// 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 + -