diff --git a/Mesh/Field.cpp b/Mesh/Field.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f257c75ad6c2a5131514c4ba64a667acaa338ac --- /dev/null +++ b/Mesh/Field.cpp @@ -0,0 +1,330 @@ +#include<fstream> +#include "math.h" +#include "Field.h" +#include "Gmsh.h" +#include "Context.h" +#include "GeoInterpolation.h" +#include "matheval.h" +#ifdef HAVE_MATH_EVAL +#include "matheval.h" +#endif +#define MAX_LC 1e22 +extern Context_T CTX; +FieldManager fields; + +void FieldManager::reset(){ + for(std::map<int,Field*>::iterator it=id_map.begin();it!=id_map.end();it++){ + delete it->second; + } + id_map.clear(); +} + +Field *FieldManager::get(int id){ + std::map<int,Field*>::iterator it=id_map.find(id); + if(it==id_map.end()){ + Msg(GERROR,"Field id %i does not exist.\n",id); + return NULL; + } + return it->second; +} +int FieldManager::insert(Field *field,int id){ + if(id==-1){ // get an automatic negative id starting from -1 + if(id_map.begin()!=id_map.end()){ + id=id_map.begin()->first-1; + } + } + if(id>0){ + if(id_map.find(id)!=id_map.end()){ + Msg(GERROR, "Field id %i is already defined, it will be deleted.\n"); + delete id_map[id]; + } + id_map[id]=field; + return id; + } +} + +/* StructuredField*/ +StructuredField::StructuredField(const char *filename){ + std::ifstream input(filename); + input.read((char*)o,3*sizeof(double)); + input.read((char*)d,3*sizeof(double)); + input.read((char*)n,3*sizeof(int)); + int nt=n[0]*n[1]*n[2]; + data=new double[nt]; + input.read((char*)data,nt*sizeof(double)); + input.close(); +} +StructuredField::~StructuredField(){ + delete []data; +} +double StructuredField::operator()(double x,double y,double z){ + //tri-linear + int id[2][3]; + double xi[3]; + double xyz[3]={x,y,z}; + for(int i=0;i<3;i++){ + id[0][i]=(int)floor((xyz[i]-o[i])/d[i]); + id[1][i]=id[0][i]+1; + id[0][i]=std::max(std::min(id[0][i],n[i]-1),0); + id[1][i]=std::max(std::min(id[1][i],n[i]-1),0); + xi[i]=xyz[i]-(o[i]+id[0][i]*d[i]); + xi[i]=std::max(std::min(xi[i],1.),0.); + } + double v=0; + for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++){ + v+=data[id[i][0]*n[1]*n[2]+id[j][1]*n[2]+id[j][2]] + *(i*xi[0]+(1-i)*(1-xi[0])) + *(j*xi[1]+(1-j)*(1-xi[1])) + *(k*xi[2]+(1-k)*(1-xi[2])); + } + return v; +} + +/*LatLonField*/ +double LatLonField::operator()(double x,double y,double z){ + return (*field)(asin(z/sqrt(x*x+y*y+z*z)),atan2(y,x),0); +} + +/*ThresholdField*/ +ThresholdField::ThresholdField(Field *_field, + double _dmin,double _dmax,double _lcmin,double _lcmax): + field(_field),dmin(_dmin),dmax(_dmax),lcmin(_lcmin),lcmax(_lcmax){ +} +double ThresholdField::operator()(double x,double y,double z){ + double r=((*field)(x,y,z)-dmin)/(dmax-dmin); + r=std::max(std::min(r,1.),0.); + double lc=lcmin*(1-r)+lcmax*r; + return lc; +} + +/*GradField*/ +GradField::GradField(Field *_field,int _kind,double _delta): + field(_field),kind(_kind),delta(_delta){ + if(delta<0) delta=CTX.lc/10000; +} +double GradField::operator()(double x,double y,double z){ + double gx,gy,gz; + switch(kind){ + case 0 : /* x */ + return ((*field)(x+delta/2,y,z)-(*field)(x-delta/2,y,z))/delta; + case 1 : /* y */ + return ((*field)(x,y+delta/2,z)-(*field)(x,y-delta/2,z))/delta; + case 2 : /* z */ + return ((*field)(x,y,z+delta/2)-(*field)(x,y,z-delta/2))/delta; + case 3 : /* max */ + gx=((*field)(x+delta/2,y,z)-(*field)(x-delta/2,y,z))/delta; + gy=((*field)(x,y+delta/2,z)-(*field)(x,y-delta/2,z))/delta; + gz=((*field)(x,y,z+delta/2)-(*field)(x,y,z-delta/2))/delta; + return sqrt(gx*gx+gy*gy+gz*gz); + default : + Msg(GERROR, "Unknown kind (%i) for GradField.",kind); + return 0; + } +} + +/*ParametricField*/ +ParametricField::ParametricField(Field *_field,const char *strX,const char *strY,const char *strZ):field(_field){ + char *sx=strdup(strX),*sy=strdup(strY),*sz=strdup(strZ); +#if !defined(HAVE_MATH_EVAL) + Msg(GERROR, "MathEval is not compiled in this version of Gmsh"); +#else + evalX = evaluator_create(sx); + evalY = evaluator_create(sy); + evalZ = evaluator_create(sz); +#endif +} +ParametricField::~ParametricField(){ +#if !defined(HAVE_MATH_EVAL) + Msg(GERROR, "MathEval is not compiled in this version of Gmsh"); +#else + evaluator_destroy(evalX); + evaluator_destroy(evalY); + evaluator_destroy(evalZ); +#endif +} +double ParametricField::operator()(double x,double y,double z){ +#if !defined(HAVE_MATH_EVAL) + Msg(GERROR, "MathEval is not compiled in this version of Gmsh"); +#else + static char *names[3] = {"x","y","z"}; + double values [3] = {x,y,z}; + const double nx = evaluator_evaluate(evalX, 3, names, values); + const double ny = evaluator_evaluate(evalY, 3, names, values); + const double nz = evaluator_evaluate(evalZ, 3, names, values); + return (*field)(x,y,z); +#endif +} + +/* FunctionField */ +FunctionField::FunctionField(std::list<Field*> *_list,const char *str):list(_list){ +#if !defined(HAVE_MATH_EVAL) + Msg(GERROR, "MathEval is not compiled in this version of Gmsh"); +#else + char *s=strdup(str); + eval = evaluator_create(s); + values=new double[3+list->size()]; + names=new char*[3+list->size()]; + names[0]=strdup("x"); + names[1]=strdup("y"); + names[2]=strdup("z"); + int p=3; + for(std::list<Field*>::iterator it=list->begin();it!=list->end();it++){ + asprintf(names+p,"f%i",p-3); + p++; + } +#endif +} +double FunctionField::operator()(double x,double y,double z){ +#if !defined(HAVE_MATH_EVAL) + Msg(GERROR, "MathEval is not compiled in this version of Gmsh"); +#else + values[0]=x; + values[1]=y; + values[2]=z; + int p=3; + for(std::list<Field*>::iterator it=list->begin();it!=list->end();it++){ + values[p]=(**it)(x,y,z); + p++; + } + return evaluator_evaluate(eval,p,names,values); +#endif +} +FunctionField::~FunctionField(){ +#if !defined(HAVE_MATH_EVAL) + Msg(GERROR, "MathEval is not compiled in this version of Gmsh"); +#else + int n=3+list->size(); + for(int i=0;i<n;i++){ + free(names[i]); + } + delete []names; + delete []values; + delete list; + evaluator_destroy(eval); +#endif +} + +/* PostViewField */ +double PostViewField::operator()(double x, double y, double z) { + double l = 0.; + double fact[9] = {0.001, 0.0025, 0.005, 0.0075, 0.01, 0.025, 0.05, 0.075, 0.1}; + if(!octree->searchScalar(x, y, z, &l, 0)){ + // try really hard to find an element around the point + for(int i = 0; i < 9; i++){ + double eps = CTX.lc * fact[i]; + if(octree->searchScalar(x + eps, y, z, &l, 0)) break; + if(octree->searchScalar(x - eps, y, z, &l, 0)) break; + if(octree->searchScalar(x, y + eps, z, &l, 0)) break; + if(octree->searchScalar(x, y - eps, z, &l, 0)) break; + if(octree->searchScalar(x, y, z + eps, &l, 0)) break; + if(octree->searchScalar(x, y, z - eps, &l, 0)) break; + if(octree->searchScalar(x + eps, y - eps, z - eps, &l, 0)) break; + if(octree->searchScalar(x + eps, y + eps, z - eps, &l, 0)) break; + if(octree->searchScalar(x - eps, y - eps, z - eps, &l, 0)) break; + if(octree->searchScalar(x - eps, y + eps, z - eps, &l, 0)) break; + if(octree->searchScalar(x + eps, y - eps, z + eps, &l, 0)) break; + if(octree->searchScalar(x + eps, y + eps, z + eps, &l, 0)) break; + if(octree->searchScalar(x - eps, y - eps, z + eps, &l, 0)) break; + if(octree->searchScalar(x - eps, y + eps, z + eps, &l, 0)) break; + } + } + if(l <= 0) return MAX_LC; + return l; +} + +PostViewField::PostViewField(Post_View *view){ + Msg(INFO, "Field from '%s'.", view->Name); + octree = new OctreePost(view); + view_num = view->Num; +} + +/* Min Field */ +MinField::MinField(){}; +double MinField::operator()(double x,double y,double z){ + if(size()==0){ + Msg(GERROR, "Requesting minimum of a void list of field."); + return 0; + } + iterator it=begin(); + double v=(**it++)(x,y,z); + while(it!=end()){ + v=std::min(v,(**it++)(x,y,z)); + } + return v; +} + +/* Attractor Field */ +#define maxpts 1 +void AttractorField::addPoint ( double X, double Y, double Z, double lc){ + attractorPoints.push_back(SPoint3(X,Y,Z)); +} +AttractorField::~AttractorField(){ +#ifdef HAVE_ANN_ + if(kdtree) delete kdtree; + if(zeronodes) annDeallocPts(zeronodes); + delete [] index; + delete [] dist; +#endif +} +AttractorField::AttractorField() +#ifdef HAVE_ANN_ + : kdtree (0), zeronodes(0) +#endif +{ +#ifdef HAVE_ANN_ + index = new ANNidx[maxpts]; + dist = new ANNdist[maxpts]; +#endif +} + +void AttractorField::buildFastSearchStructures(){ +#ifdef HAVE_ANN_ + if(zeronodes){ + annDeallocPts(zeronodes); + delete kdtree; + } + int totpoints = attractorPoints.size(); + if (totpoints) + zeronodes = annAllocPts(totpoints, 4); + int k = 0; + for (std::list <SPoint3>::iterator it2 = attractorPoints.begin(); + it2 != attractorPoints.end(); ++it2){ + zeronodes[k][0]=it2->x(); + zeronodes[k][1]=it2->y(); + zeronodes[k++][2]=it2->z(); + } + kdtree = new ANNkd_tree(zeronodes, totpoints, 3); +#endif +} + +double AttractorField::operator()(double X, double Y, double Z){ + double xyz[3] = {X, Y, Z}; + if(attractorPoints.size() == 1){ + SPoint3 p = *(attractorPoints.begin()); + return sqrt((p.x()-X)*(p.x()-X)+(p.y()-Y)*(p.y()-Y)+(p.z()-Z)*(p.z()-Z)); + } + else{ +#ifdef HAVE_ANN_ + kdtree->annkSearch(xyz, maxpts, index, dist); + return sqrt(dist[0]); +#else + Msg(GERROR,"GMSH should be compiled with ANN in order to enable attractors !"); +#endif + } +} +void AttractorField::addCurve(Curve *c, int N) { + for(int i = 0; i < N; i++){ + double u = (double)i / (N - 1); + Vertex V = InterpolateCurve (c, u, 0); + addPoint(V.Pos.X, V.Pos.Y, V.Pos.Z); + } +} +void AttractorField::addGEdge(GEdge *c, int N) { + for(int i = 0; i < N; i++){ + double u = (double)i / (N - 1); + Range<double> b = c->parBounds(0); + double t = b.low() + u * (b.high() - b.low()); + GPoint gp = c->point(t); + addPoint(gp.x(), gp.y(), gp.z()); + } +} diff --git a/Mesh/Field.h b/Mesh/Field.h new file mode 100644 index 0000000000000000000000000000000000000000..a4252db6aa2bcf61eb50f3eaa6d89a80b3bf85cf --- /dev/null +++ b/Mesh/Field.h @@ -0,0 +1,105 @@ +#ifndef FIELD_H_ +#define FIELD_H_ +#include<map> +#include<list> +#include "Views.h" +#ifdef HAVE_ANN_ +#include "ANN/ANN.h" +#endif +#include "Geo.h" +#include "GEdge.h" +#include "OctreePost.h" +class Field{ + public: + virtual double operator()(double x,double y,double z)=0; +}; +class FieldManager{ + std::map<int,Field*> id_map; + public: + void reset(); + int insert(Field *field,int id=-1 /* -1= automatic id */); /* return the id */ + Field *get(int id); +}; +extern FieldManager fields; + +class StructuredField:public Field{ + double o[3],d[3]; + int n[3]; + double *data; + public : + StructuredField(const char *filename); + virtual ~StructuredField(); + double operator()(double x,double y,double z); +}; +class LatLonField:public Field{ + Field *field; + public: + LatLonField(Field *_field):field(_field){}; + double operator()(double x,double y,double z); +}; +class ParametricField:public Field{ + void *evalX,*evalY,*evalZ; + Field *field; + public: + ParametricField(Field *_field,const char *strX,const char *strY,const char *strZ); + double operator()(double x,double y,double z); + ~ParametricField(); +}; +class ThresholdField:public Field{ + Field *field; + double dmin,dmax,lcmin,lcmax; + public: + ThresholdField(Field *field,double dmin,double dmax,double lcmin,double lcmax); + double operator()(double x,double y,double z); +}; +class GradField:public Field{ + Field *field; + int kind;/*0 x, 1 y, 2 z, 3 max */ + double delta; + public: + GradField(Field *field,int _kind=2,double _delta=-1); + double operator()(double x,double y,double z); +}; +class FunctionField:public Field{ + std::list<Field*> *list; + char **names; + double *values; + void *eval; + public: + FunctionField(std::list<Field*> *_list,const char *fct); + double operator()(double x,double y,double z); + ~FunctionField(); +}; +class PostViewField:public Field{ + OctreePost *octree; + int view_num; + public: + PostViewField(Post_View *view); + double operator()(double x,double y,double z); +}; +class MinField:public Field,public std::list<Field*>{ + public: + MinField(); + double operator()(double x,double y,double z); +}; + +class AttractorField:public Field{ + protected : +#ifdef HAVE_ANN_ + ANNkd_tree* kdtree; + ANNpointArray zeronodes; + ANNidxArray index; + ANNdistArray dist; +#endif + std::list <SPoint3> attractorPoints; +public : + AttractorField(); + virtual ~AttractorField(); + void addPoint ( double X, double Y, double Z, double lc = -1.0); + void buildFastSearchStructures() ; + void addGEdge(GEdge*, int); + void addCurve(Curve*, int); + double operator()(double X, double Y, double Z) ; +}; + +#endif