diff --git a/CMakeLists.txt b/CMakeLists.txt index 24f6b03a09eff41cb2d9fc4bf431d0698bf65f1d..93bdf2cb985a6d7fc94e17bec6002661f95befa6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,7 +102,7 @@ set(GMSH_API Mesh/meshGEdge.h Mesh/meshGFace.h Mesh/meshGFaceOptimize.h Mesh/meshGFaceElliptic.h Mesh/meshPartition.h Mesh/meshGFaceDelaunayInsertion.h Mesh/simple3D.h Mesh/meshPartitionOptions.h Mesh/directions3D.h Mesh/yamakawa.h - Mesh/Voronoi3D.h Mesh/Levy3D.h Mesh/periodical.h + Mesh/Voronoi3D.h Mesh/Levy3D.h Mesh/periodical.h Mesh/meshMetric.h Numeric/mathEvaluator.h Solver/dofManager.h Solver/femTerm.h Solver/laplaceTerm.h Solver/elasticityTerm.h Solver/crossConfTerm.h Solver/orthogonalTerm.h diff --git a/Mesh/meshMetric.cpp b/Mesh/meshMetric.cpp index e52fd40b5c1b7665d7c14cc98e43016e2c96bd54..59de16224e6306d9e8f5d3f0cd1bb2f7a7b7ce99 100644 --- a/Mesh/meshMetric.cpp +++ b/Mesh/meshMetric.cpp @@ -105,13 +105,13 @@ void meshMetric::intersectMetrics() for (;it != _adj.end();it++) { MVertex *ver = it->first; _nodalMetrics[ver] = setOfMetrics[0][ver]; - _detMetric[ver] = setOfDetMetric[0][ver]; + // _detMetric[ver] = setOfDetMetric[0][ver]; _nodalSizes[ver] = setOfSizes[0][ver]; for (unsigned int i=1;i<setOfMetrics.size();i++){ _nodalMetrics[ver] = intersection_conserve_mostaniso(_nodalMetrics[ver],setOfMetrics[i][ver]); _nodalSizes[ver] = std::min(_nodalSizes[ver],setOfSizes[i][ver]); } - _detMetric[ver] = sqrt(_nodalMetrics[ver].determinant()); + // _detMetric[ver] = sqrt(_nodalMetrics[ver].determinant()); } needMetricUpdate=false; @@ -356,16 +356,20 @@ void meshMetric::computeMetricLevelSet() _hessian[ver] = hessian; setOfSizes[metricNumber].insert(std::make_pair(ver, std::min(std::min(1/sqrt(lambda1),1/sqrt(lambda2)),1/sqrt(lambda3)))); setOfMetrics[metricNumber].insert(std::make_pair(ver,metric)); - setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); + // setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); } } -void meshMetric::computeMetricHessian() +void meshMetric::computeMetricHessian( ) { int metricNumber = setOfMetrics.size(); + double _epsilonP = 1.; + double hminP = 1.e-12; + double hmaxP = 1.e+12; + for (v2t_cont::iterator it=_adj.begin(); it!=_adj.end(); it++) { MVertex *ver = it->first; @@ -381,10 +385,11 @@ void meshMetric::computeMetricHessian() fullMatrix<double> V(3,3); fullVector<double> S(3); H.eig(V,S); + - double lambda1 = std::min(std::max(fabs(S(0))/_epsilon,1./(hmax*hmax)),1./(hmin*hmin)); - double lambda2 = std::min(std::max(fabs(S(1))/_epsilon,1./(hmax*hmax)),1./(hmin*hmin)); - double lambda3 = (_dim == 3) ? std::min(std::max(fabs(S(2))/_epsilon,1./(hmax*hmax)),1./(hmin*hmin)) : 1.; + double lambda1 = std::min(std::max(fabs(S(0))/_epsilonP,1./(hmaxP*hmaxP)),1./(hminP*hminP)); + double lambda2 = std::min(std::max(fabs(S(1))/_epsilonP,1./(hmaxP*hmaxP)),1./(hminP*hminP)); + double lambda3 = (_dim == 3) ? std::min(std::max(fabs(S(2))/_epsilonP,1./(hmaxP*hmaxP)),1./(hminP*hminP)) : 1.; SVector3 t1 (V(0,0),V(1,0),V(2,0)); SVector3 t2 (V(0,1),V(1,1),V(2,1)); @@ -395,10 +400,12 @@ void meshMetric::computeMetricHessian() _hessian[ver] = H; setOfSizes[metricNumber].insert(std::make_pair(ver, std::min(std::min(1/sqrt(lambda1),1/sqrt(lambda2)),1/sqrt(lambda3)))); setOfMetrics[metricNumber].insert(std::make_pair(ver,metric)); - setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); + // setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); } + scaleMetric(_epsilon, setOfMetrics[metricNumber]); + } void meshMetric::computeMetricFrey() @@ -459,7 +466,7 @@ void meshMetric::computeMetricFrey() _hessian[ver] = hessian; setOfSizes[metricNumber].insert(std::make_pair(ver, std::min(std::min(1/sqrt(lambda1),1/sqrt(lambda2)),1/sqrt(lambda3)))); setOfMetrics[metricNumber].insert(std::make_pair(ver,metric)); - setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); + // setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); } } @@ -529,7 +536,7 @@ void meshMetric::computeMetricEigenDir() } _hessian[ver] = hessian; setOfMetrics[metricNumber].insert(std::make_pair(ver,metric)); - setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); + // setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); } @@ -557,7 +564,7 @@ void meshMetric::computeMetricIsoLinInterp() _hessian[ver] = H; setOfSizes[metricNumber].insert(std::make_pair(ver, lambda)); setOfMetrics[metricNumber].insert(std::make_pair(ver,H)); - setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(H.determinant()))); + // setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(H.determinant()))); } @@ -623,13 +630,76 @@ void meshMetric::computeMetricScaledHessian() SMetric3 metric(l1,l2,l3,*itT1,*itT2,*itT3); setOfSizes[metricNumber].insert(std::make_pair(ver, 1./sqrt(lMax))); setOfMetrics[metricNumber].insert(std::make_pair(ver,metric)); - setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); + // setOfDetMetric[metricNumber].insert(std::make_pair(ver,sqrt(metric.determinant()))); itL1++; itL2++; if (_dim == 3) itL3++; itT1++; itT2++; itT3++; } } + +// this function scales the mesh metric in order +// to reach a target number of elements +// We know that the number of elements in the final +// mesh will be (assuming M_e the metric at centroid of element e) +// N = \sum_e \sqrt {\det (M_e)} V_e +// where V_e is the volume of e +// assuming that N_{target} = K N, we have +// K N = K \sum_e \sqrt {\det (M_e)} V_e +// = \sum_e \sqrt {K^2 \det (M_e)} V_e +// = \sum_e \sqrt {\det (K^{2/d} M_e)} V_e +// where d is the dimension of the problem. +// This means that the metric should be scaled by K^{2/d} where +// K is N_target / N + +void meshMetric::scaleMetric( int nbElementsTarget, + nodalMetricTensor &nmt ) +{ + // compute N + double N = 0; + for (unsigned int i=0;i<_elements.size();i++){ + MElement *e = _elements[i]; + SMetric3 m1 = nmt[e->getVertex(0)]; + SMetric3 m2 = nmt[e->getVertex(1)]; + SMetric3 m3 = nmt[e->getVertex(2)]; + if (_dim == 2){ + SMetric3 m = interpolation(m1,m2,m3,0.3333,0.3333); + N += sqrt(m.determinant()) * e->getVolume() * 3.0; + // printf("%12.5E %12.5E\n",m.determinant(),e->getVolume()); + } + else{ + SMetric3 m4 = nmt[e->getVertex(3)]; + SMetric3 m = interpolation(m1,m2,m3,m4,0.25,0.25,0.25); + N += sqrt(m.determinant()) * e->getVolume() * 4.0; + } + } + double scale = pow ((double)nbElementsTarget/N,2.0/_dim); + // printf("%d elements --- %d element target --- %12.5E elements with the present metric\n", + // _elements.size(),nbElementsTarget,N); + // getchar(); + for (nodalMetricTensor::iterator it = nmt.begin(); it != nmt.end() ; ++it){ + if (_dim == 3){ + it->second *= scale; + } + else { + it->second(0,0) *= scale; + it->second(1,0) *= scale; + it->second(1,1) *= scale; + } + SMetric3 &m = it->second; + fullMatrix<double> V(3,3); + fullVector<double> S(3); + m.eig(V,S); + S(0) = std::min(std::max(S(0),1/(hmax*hmax)),1/(hmin*hmin)); + S(1) = std::min(std::max(S(1),1/(hmax*hmax)),1/(hmin*hmin)); + S(2) = std::min(std::max(S(2),1/(hmax*hmax)),1/(hmin*hmin)); + SVector3 t1 (V(0,0),V(1,0),V(2,0)); + SVector3 t2 (V(0,1),V(1,1),V(2,1)); + SVector3 t3 (V(0,2),V(1,2),V(2,2)); + m = SMetric3(S(0),S(1),S(2),t1,t2,t3); + } +} + void meshMetric::computeMetric() { //printf("%d elements are considered in the meshMetric \n",(int)_elements.size()); @@ -676,7 +746,9 @@ double meshMetric::operator() (double x, double y, double z, GEntity *ge) void meshMetric::operator() (double x, double y, double z, SMetric3 &metr, GEntity *ge) { - if (needMetricUpdate) intersectMetrics(); + if (needMetricUpdate) { + intersectMetrics(); + } if (!setOfMetrics.size()){ std::cout << "meshMetric::operator() : No metric defined ! " << std::endl; throw; diff --git a/Mesh/meshMetric.h b/Mesh/meshMetric.h index b2eed0f41b3de24fba8da470d8c1b796d685e991..3b0d014ac10487239fa017a544e0b133e13195ac 100644 --- a/Mesh/meshMetric.h +++ b/Mesh/meshMetric.h @@ -6,6 +6,7 @@ #ifndef _MESH_METRIC_H_ #define _MESH_METRIC_H_ + #include <map> #include <algorithm> #include "STensor3.h" @@ -41,15 +42,16 @@ class meshMetric: public Field { std::map<MVertex*,double> vals; std::map<MVertex*,SVector3> grads,dgrads[3]; + public: typedef std::map<MVertex*,SMetric3> nodalMetricTensor; typedef std::map<MVertex*,double> nodalField; - + private: nodalMetricTensor _nodalMetrics,_hessian; nodalField _nodalSizes, _detMetric; std::map<int,nodalMetricTensor> setOfMetrics; std::map<int,nodalField> setOfSizes; - std::map<int,nodalField> setOfDetMetric; + // std::map<int,nodalField> setOfDetMetric; public: meshMetric(std::vector<MElement*> elements); @@ -81,6 +83,10 @@ class meshMetric: public Field { if (needMetricUpdate) intersectMetrics(); return _nodalMetrics[v]; } + // this function scales the mesh metric in order + // to reach a target number of elements + void scaleMetric( int nbElementsTarget, + nodalMetricTensor &nmt ); void computeMetric(); void computeMetricLevelSet(); diff --git a/benchmarks/python/adaptivity.py b/benchmarks/python/adaptivity.py index e91fe8d861fec4080c29a9f78d34635e01b99cc4..7d624af1e5efaf12eb1223f2968fd3469c5f480e 100644 --- a/benchmarks/python/adaptivity.py +++ b/benchmarks/python/adaptivity.py @@ -19,13 +19,13 @@ def Adaptation ( gm , gm_adapt) : print "hello 3", myMap.size() pv = PView ('xcarre','NodeData', gm, myMap) pve = PViewEvaluator (pv) - lcMin = 0.00001 + lcMin = 0.001 lcMax = .1 - eps = 1.e-2 - nbIter = 4 + NBTARGET = 13000 + nbIter = 2 allDim = 1 - gm_adapt.adaptMesh([2], [pve], [[eps, lcMin, lcMax]], nbIter, allDim) + gm_adapt.adaptMesh([2], [pve], [[NBTARGET, lcMin, lcMax]], nbIter, allDim) print "hello 4" gm = GModel() @@ -38,6 +38,11 @@ gm_adapt.load('square.geo') gm_adapt2 = GModel() gm_adapt2.load('square.geo') +gm_adapt3 = GModel() +gm_adapt3.load('square.geo') + Adaptation ( gm , gm_adapt2) print "------------------------------------------------------------------------" Adaptation ( gm_adapt2 , gm_adapt) +print "------------------------------------------------------------------------" +Adaptation ( gm_adapt , gm_adapt3)