From ae8b0b7179b14055a47d88b6c3cb71433e2ee99b Mon Sep 17 00:00:00 2001 From: Andreas Naumann <andreas.naumann@tu-dresden.de> Date: Tue, 25 May 2010 12:53:35 +0000 Subject: [PATCH] implicit meshes for scalar problems --- AMDiS/src/AMDiS.h | 1 + AMDiS/src/MathFunctions.h | 23 +++++++++ AMDiS/src/ProblemScal.cc | 106 ++++++++++++++++++++++++++++++++++++++ AMDiS/src/ProblemScal.h | 38 +++++++++++++- 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 AMDiS/src/MathFunctions.h diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h index 65dc56f9..a39c5a0a 100644 --- a/AMDiS/src/AMDiS.h +++ b/AMDiS/src/AMDiS.h @@ -1,5 +1,6 @@ #ifndef AMDIS_H #define AMDIS_H +#include "MathFunctions.h" #include "AbstractFunction.h" #include "AdaptInfo.h" #include "AdaptInstationary.h" diff --git a/AMDiS/src/MathFunctions.h b/AMDiS/src/MathFunctions.h new file mode 100644 index 00000000..356bfa20 --- /dev/null +++ b/AMDiS/src/MathFunctions.h @@ -0,0 +1,23 @@ +#ifndef AMDIS_MATHFUNCTIONS_H +#define AMDIS_MATHFUNCTIONS_H +namespace AMDiS { + //converts signed distance to phasefield + inline double Phi1(double r, double eps) { return 0.5*(1-tanh(3*r/eps)); } + inline double Phi2(double r, double eps) { return 0.5*(1+tanh(3*r/eps)); } + + //levelset: positive (1) in the set, negative (-1) outside, zero on the boundary + inline double LevelSet(double r) + { + if(r<0) + return 1; + if(r>0) + return -1; + return 0; + } + + //convert Phi1 to r + inline double Phi1ToR(double p1, double eps) { return atanh(1-2*p1)*eps/3; } + //convert Phi2 to r + inline double Phi2ToR(double p2, double eps) { return atanh(1+2*p2)*eps/3; } +} +#endif diff --git a/AMDiS/src/ProblemScal.cc b/AMDiS/src/ProblemScal.cc index 40d8ce4d..aaf4fefb 100644 --- a/AMDiS/src/ProblemScal.cc +++ b/AMDiS/src/ProblemScal.cc @@ -151,6 +151,111 @@ namespace AMDiS { rhs->getBoundaryManager()->addBoundaryCondition(periodic); } + void ProblemScal::readR(std::istream& inStream,double eps) { + readDofvec(inStream,r); + std::vector< double >& vecR=r->getVector(); + std::vector< double >& vecPhi1=phi1->getVector(); + std::vector< double >& vecPhi2=phi2->getVector(); + std::vector< double >& vecLevelSet=levelSet->getVector(); + + TEST_EXIT(vecR.size()!=vecPhi1.size() && vecPhi2.size()!=vecR.size())("something went wrong\n"); + for(int i=vecR.size()-1;i>=0;--i) { + vecPhi1[i]=Phi1(vecR[i],eps); + vecPhi2[i]=Phi2(vecR[i],eps); + vecLevelSet[i]=LevelSet(vecR[i]); + } + } + + void ProblemScal::readPhi1(istream& inStream,double eps) { + readDofvec(inStream,phi1); + std::vector< double >& vecR=r->getVector(); + std::vector< double >& vecPhi1=phi1->getVector(); + std::vector< double >& vecPhi2=phi2->getVector(); + std::vector< double >& vecLevelSet=levelSet->getVector(); + + TEST_EXIT(vecR.size()!=vecPhi1.size() && vecPhi2.size()!=vecR.size())("something went wrong\n"); + for(int i=vecR.size()-1;i>=0;--i) { + vecR[i]=Phi1ToR(vecPhi1[i],eps); + vecPhi2[i]=Phi2(vecR[i],eps); + vecLevelSet[i]=LevelSet(vecR[i]); + } + } + + void ProblemScal::readPhi2(istream& inStream,double eps) { + readDofvec(inStream,phi2); + std::vector< double >& vecR=r->getVector(); + std::vector< double >& vecPhi1=phi1->getVector(); + std::vector< double >& vecPhi2=phi2->getVector(); + std::vector< double >& vecLevelSet=levelSet->getVector(); + + TEST_EXIT(vecR.size()!=vecPhi1.size() && vecPhi2.size()!=vecR.size())("something went wrong\n"); + for(int i=vecR.size()-1;i>=0;--i) { + vecR[i]=Phi2ToR(vecPhi1[i],eps); + vecPhi1[i]=Phi1(vecR[i],eps); + vecLevelSet[i]=LevelSet(vecR[i]); + } + } + + void ProblemScal::readDofvec(std::istream& in, DOFVector< double >* vec) + { + long size = mesh->getNumberOfVertices(); + std::string buf; + getline(in, buf); + while(buf != "vertex values: solution") getline(in, buf); + for(long i=0; i<size; i++){ + in >> buf; + (*vec)[i] = atof(buf.c_str()); + } + } + + bool ProblemScal::createImplicitMesh() + { + std::string meshFilename(""); + GET_PARAMETER(0,name+"->implicit mesh->mesh file",&meshFilename); + //if no file name is given, there's no implicit mesh + if(meshFilename.length()==0) + return false; + std::string dofFilename(""); + GET_PARAMETER(0,name+"->implicit mesh->dof file",&dofFilename); + if(dofFilename.length()==0) + return false; + + double eps(-1); + GET_PARAMETER(0,name+"->implicit mesh->eps","%d",&eps); + if(eps<0) + return false; + int serType(-1); + GET_PARAMETER(0,name+"->implicit mesh->type","%d",&serType); + if(serType<0) + return false; + TEST_EXIT(mesh!=NULL)("the mesh was not created\n"); + std::ifstream inStream(meshFilename.c_str()); + mesh->deserialize(inStream); + inStream.close(); + //create the fespace with the correct admin + createFESpace(); + r=new DOFVector< double >(getFESpace(),"r"); + phi1=new DOFVector<double>(getFESpace(),"phi1"); + phi2=new DOFVector<double>(getFESpace(),"phi2"); + levelSet=new DOFVector< double >(getFESpace(),"levelSet"); + inStream.open(dofFilename.c_str()); + switch(serType) { + case 0: + readR(inStream,eps); + break; + case 1: + readPhi1(inStream,eps); + break; + case 2: + readPhi2(inStream,eps); + break; + default: + WARNING("unknown implicit mesh type\n"); + } + inStream.close(); + return true; + } + void ProblemScal::createMesh() { TEST_EXIT(Parameters::initialized())("parameters not initialized\n"); @@ -284,6 +389,7 @@ namespace AMDiS { if (!mesh) WARNING("no mesh created\n"); + createImplicitMesh(); // === create fespace === if (feSpace) { WARNING("feSpace already created\n"); diff --git a/AMDiS/src/ProblemScal.h b/AMDiS/src/ProblemScal.h index 55fb1ce0..eb694961 100644 --- a/AMDiS/src/ProblemScal.h +++ b/AMDiS/src/ProblemScal.h @@ -52,7 +52,11 @@ namespace AMDiS { useGetBound(true), refinementManager(NULL), coarseningManager(NULL), - info(10) + info(10), + r(NULL), + phi1(NULL), + phi2(NULL), + levelSet(NULL) {} /// Destructor @@ -66,6 +70,22 @@ namespace AMDiS { /// Used in \ref initialize(). virtual void createMesh(); + /// Used in \ref createMesh(). + /// @return: true if implicit mesh type is ok (see below) and false in all other cases + /// initfile entries: + /// name+"->implicit mesh->mesh file": name of serialized mesh + /// name+"->implicit mesh->dof file": name of serialized dofvector + /// name+"->implicit mesh->type": type of serialized dofvector. + /// type can be: + /// 0: dofvector is a signed distance r + /// 1: dofvector is a phasefield phi=0.5*(1-tanh(3*r/eps)) + /// 2: dofvector is a phasefield phi=0.5*(1+tanh(3*r/eps)) + /// assumes: + /// a) already created, but not yet initialized mesh + /// b) already created feSpace + virtual bool createImplicitMesh(); + void readDofvec(std::istream&, DOFVector< double >*); + /// Used in \ref initialize(). virtual void createFESpace(); @@ -364,6 +384,18 @@ namespace AMDiS { /// DOFVector for the right hand side DOFVector<double> *rhs; + /// DOFVector for a signed distance + DOFVector< double > *r; + + /// DOFVector for the phasefield function 0.5*(1-tanh(3*r/eps)) + DOFVector< double > *phi1; + + /// DOFVector for the phasefield function 0.5*(1+tanh(3*r/eps)) + DOFVector< double > *phi2; + + /// DOFVector for the levelset function (levelSet(x): x \in \Omega: 1, x \not \in Omega: -1, x \in \Gamma: 0) + DOFVector< double > *levelSet; + /// System matrix DOFMatrix *systemMatrix; @@ -389,6 +421,10 @@ namespace AMDiS { /// Info level. int info; + + void readR(std::istream&, double); + void readPhi1(std::istream&,double); + void readPhi2(std::istream&,double); }; } -- GitLab