diff --git a/CMakeLists.txt b/CMakeLists.txt index 50377251b0e15ef18136b7d5eedc858e7906b6a2..c534812957ad9466a0f279c161120f9bdddcb790 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ option(ENABLE_MPI "Enable MPI parallelization" OFF) option(ENABLE_MSVC_STATIC_RUNTIME "Use static Visual C++ runtime" OFF) option(ENABLE_NATIVE_FILE_CHOOSER "Enable native file chooser in GUI" ON) option(ENABLE_NETGEN "Enable Netgen mesh generator" ON) +option(ENABLE_BAMG "Enable Bamg mesh generator" ON) option(ENABLE_OCC "Enable Open CASCADE geometrical models" ON) option(ENABLE_ACIS "Enable ACIS geometrical models" ON) option(ENABLE_OSMESA "Use OSMesa for offscreen rendering" OFF) @@ -495,6 +496,13 @@ if(ENABLE_NETGEN) add_definitions(-DNO_PARALLEL_THREADS) endif(ENABLE_NETGEN) +if(ENABLE_BAMG) + add_subdirectory(contrib/bamg) + include_directories(contrib/bamg contrib/bamg/bamglib) + set_config_option(HAVE_BAMG "Bamg") +endif(ENABLE_BAMG) + + if(ENABLE_TETGEN_NEW AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/TetgenNew/tetgen.h) add_subdirectory(contrib/TetgenNew) include_directories(contrib/TetgenNew) diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp index b44acf09066473c27d14e7ea12e49404a3d9e661..b9967b6b092c36d99c32b0295558328dbbf46d5b 100644 --- a/Common/CommandLine.cpp +++ b/Common/CommandLine.cpp @@ -511,6 +511,8 @@ void GetOptions(int argc, char *argv[]) CTX::instance()->mesh.algo2d = ALGO_2D_DELAUNAY; else if(!strncmp(argv[i], "front2d", 7) || !strncmp(argv[i], "frontal", 7)) CTX::instance()->mesh.algo2d = ALGO_2D_FRONTAL; + else if(!strncmp(argv[i], "bamg",4)) + CTX::instance()->mesh.algo2d = ALGO_2D_BAMG; else if(!strncmp(argv[i], "del3d", 5) || !strncmp(argv[i], "tetgen", 6)) CTX::instance()->mesh.algo2d = ALGO_3D_DELAUNAY; else if(!strncmp(argv[i], "front3d", 7) || !strncmp(argv[i], "netgen", 6)) diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in index ef67a45ae1bae295987620ed2f4bb0dc097ce57c..5728ace40ee1da111c5e373de05b24829670a7a6 100644 --- a/Common/GmshConfig.h.in +++ b/Common/GmshConfig.h.in @@ -9,6 +9,7 @@ #cmakedefine HAVE_64BIT_SIZE_T #cmakedefine HAVE_ACIS #cmakedefine HAVE_ANN +#cmakedefine HAVE_BAMG #cmakedefine HAVE_BLAS #cmakedefine HAVE_CHACO #cmakedefine HAVE_DLOPEN diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h index 948ad4c51fab398792f4cb01d05f352e4453d079..d4ebdd94fe4e44b5a8a4b1898ad6565997339b9a 100644 --- a/Common/GmshDefines.h +++ b/Common/GmshDefines.h @@ -147,6 +147,7 @@ #define ALGO_2D_MESHADAPT_OLD 4 #define ALGO_2D_DELAUNAY 5 #define ALGO_2D_FRONTAL 6 +#define ALGO_2D_BAMG 7 // 3D meshing algorithms (numbers should not be changed) #define ALGO_3D_DELAUNAY 1 diff --git a/Geo/OCCFace.cpp b/Geo/OCCFace.cpp index a72342ff450cb597b0469da7e7f437b1de3a7a54..828a68059b9b4a925f4cbb868ea2ab4a2234ae69 100644 --- a/Geo/OCCFace.cpp +++ b/Geo/OCCFace.cpp @@ -238,12 +238,13 @@ double OCCFace::curvatures(const SPoint2 ¶m, return -1.; } - *curvMax = std::max(fabs(prop.MinCurvature()), fabs(prop.MaxCurvature())); - *curvMin = std::min(fabs(prop.MinCurvature()), fabs(prop.MaxCurvature())); + *curvMax = prop.MaxCurvature(); + *curvMin = prop.MinCurvature(); gp_Dir dMax = gp_Dir(); gp_Dir dMin = gp_Dir(); prop.CurvatureDirections(dMax,dMin); + (*dirMax)[0] = dMax.X(); (*dirMax)[1] = dMax.Y(); (*dirMax)[2] = dMax.Z(); diff --git a/Geo/STensor3.h b/Geo/STensor3.h index 7301af82253b2c09a15e34119b3f935496f5ab20..e2c78844a4afe2e3a91a035f99974d8199233105 100644 --- a/Geo/STensor3.h +++ b/Geo/STensor3.h @@ -61,7 +61,8 @@ class SMetric3 { e(0,0) = t1(0); e(0,1) = t1(1); e(0,2) = t1(2); e(1,0) = t2(0); e(1,1) = t2(1); e(1,2) = t2(2); e(2,0) = t3(0); e(2,1) = t3(1); e(2,2) = t3(2); - e.invertInPlace(); + e.transposeInPlace(); + // e.invertInPlace(); fullMatrix<double> tmp(3,3); tmp(0,0) = l1 * e(0,0); diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp index 26138a3ed4d2b64865dcf85ca784f8298313fb38..76e1500b2182c3b817b6f3d8cea0f1f8fefb626d 100644 --- a/Mesh/BackgroundMesh.cpp +++ b/Mesh/BackgroundMesh.cpp @@ -81,6 +81,74 @@ static double max_surf_curvature(const GVertex *gv) return val; } +static SMetric3 metric_based_on_surface_curvature(const GFace *gf, double u, double v) +{ + if (gf->geomType() == GEntity::Plane)return SMetric3(1.e-6); + double cmax, cmin; + SVector3 dirMax,dirMin; + cmax = gf->curvatures(SPoint2(u, v),&dirMax, &dirMin, &cmax,&cmin); + if (cmin == 0)cmin =1.e-5; + if (cmax == 0)cmax =1.e-5; + double lambda2 = ((2 * M_PI) /( fabs(cmax) * CTX::instance()->mesh.minCircPoints ) ); + double lambda1 = ((2 * M_PI) /( fabs(cmin) * CTX::instance()->mesh.minCircPoints ) ); + SVector3 Z = crossprod(dirMax,dirMin); + + lambda1 = std::max(lambda1, CTX::instance()->mesh.lcMin); + lambda2 = std::max(lambda2, CTX::instance()->mesh.lcMin); + lambda1 = std::min(lambda1, CTX::instance()->mesh.lcMax); + lambda2 = std::min(lambda2, CTX::instance()->mesh.lcMax); + if (gf->tag() == 36 || gf->tag() == 62) + printf("%g %g -- %g %g -- %g %g %g -- %g %g %g -- %g %g %g -- %g %g\n",u,v,cmax,cmin, + dirMax.x(),dirMax.y(),dirMax.z(), + dirMin.x(),dirMin.y(),dirMin.z(), + Z.x(),Z.y(),Z.z(), + lambda1,lambda2); + + SMetric3 curvMetric (1./(lambda1*lambda1),1./(lambda2*lambda2),1.e-5, + dirMin, dirMax, Z ); + return curvMetric; +} + +static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u) +{ + SMetric3 mesh_size(1.e-05); + std::list<GFace *> faces = ge->faces(); + std::list<GFace *>::iterator it = faces.begin(); + int count = 0; + while(it != faces.end()){ + if ((*it)->geomType() != GEntity::CompoundSurface){ + SPoint2 par = ge->reparamOnFace((*it), u, 1); + SMetric3 m = metric_based_on_surface_curvature (*it, par.x(), par.y()); + if (!count) mesh_size = m; + else mesh_size = intersection ( mesh_size, m); + if ( ge->tag() == 197) + printf("edge %d face %d g %g %g -> %g %g %g\n",ge->tag(),(*it)->tag(), + m(0,0),m(1,1),m(2,2),mesh_size(0,0),mesh_size(1,1),mesh_size(2,2)); + count++; + } + ++it; + } + return mesh_size; +} + +static SMetric3 metric_based_on_surface_curvature(const GVertex *gv) +{ + SMetric3 mesh_size(1.e-5); + std::list<GEdge*> l_edges = gv->edges(); + for (std::list<GEdge*>::const_iterator ite = l_edges.begin(); + ite != l_edges.end(); ++ite){ + GEdge *_myGEdge = *ite; + Range<double> bounds = _myGEdge->parBounds(0); + if (gv == _myGEdge->getBeginVertex()) + mesh_size = intersection ( mesh_size, + metric_based_on_surface_curvature (_myGEdge, bounds.low())); + else + mesh_size = intersection ( mesh_size, + metric_based_on_surface_curvature (_myGEdge, bounds.high())); } + return mesh_size; +} + + // the mesh vertex is classified on a model vertex. we compute the // maximum of the curvature of model faces surrounding this point if // it is classified on a model edge, we do the same for all model @@ -116,6 +184,33 @@ static double LC_MVertex_CURV(GEntity *ge, double U, double V) return lc; } + +static SMetric3 LC_MVertex_CURV_ANISO(GEntity *ge, double U, double V) +{ + switch(ge->dim()){ + case 0: + { + SMetric3 m = metric_based_on_surface_curvature((const GVertex *)ge); + // printf("0d\n"); + return m; + } + break; + case 1: + { + SMetric3 m = metric_based_on_surface_curvature((const GEdge *)ge,U); + // printf("1d %g %g %g\n",m(0,0),m(1,1),m(2,2)); + return m; + } + break; + case 2: + { + return metric_based_on_surface_curvature((const GFace *)ge,U,V); + } + break; + } + Msg::Fatal("curvature control impossible to compute for a volume !"); +} + // compute the mesh size at a given vertex due to prescribed sizes at // mesh vertices static double LC_MVertex_PNTS(GEntity *ge, double U, double V) @@ -192,6 +287,9 @@ double BGM_MeshSize(GEntity *ge, double U, double V, // anisotropic version of the background field +// for now, only works with bamg in 2D, work +// in progress + SMetric3 BGM_MeshMetric(GEntity *ge, double U, double V, double X, double Y, double Z) @@ -201,40 +299,44 @@ SMetric3 BGM_MeshMetric(GEntity *ge, // lc from points double l2 = MAX_LC; - if(CTX::instance()->mesh.lcFromPoints && ge->dim() < 2) - l2 = LC_MVertex_PNTS(ge, U, V); + // if(CTX::instance()->mesh.lcFromPoints && ge->dim() < 2) + // l2 = LC_MVertex_PNTS(ge, U, V); // lc from curvature - double l3 = MAX_LC; + SMetric3 l3(1./(MAX_LC*MAX_LC)); if(CTX::instance()->mesh.lcFromCurvature && ge->dim() < 3) - l3 = LC_MVertex_CURV(ge, U, V); + l3 = LC_MVertex_CURV_ANISO(ge, U, V); // lc from fields - SMetric3 l4(MAX_LC); + SMetric3 l4(1./(MAX_LC*MAX_LC)); FieldManager *fields = GModel::current()->getFields(); if(fields->background_field > 0){ Field *f = fields->get(fields->background_field); if(f){ if (!f->isotropic()) (*f)(X, Y, Z, l4,ge); - else - l4 = SMetric3((*f)(X, Y, Z, ge)); + else{ + double L = (*f)(X, Y, Z, ge); + l4 = SMetric3(1/(L*L)); + } } } // take the minimum, then constrain by lcMin and lcMax - double lc = std::min(std::min(l1, l2), l3); + double lc = std::min(l1, l2); lc = std::max(lc, CTX::instance()->mesh.lcMin); lc = std::min(lc, CTX::instance()->mesh.lcMax); if(lc <= 0.){ - Msg::Error("Wrong mesh element size lc = %g (lcmin = %g, lcmax = %g)", + Msg::Error("Wrong mesh element size lc = %g (lcmin = %g, lcmax = %g)", lc, CTX::instance()->mesh.lcMin, CTX::instance()->mesh.lcMax); - lc = l1; + lc = l1; } - - SMetric3 LC(lc); - return intersection (l4, LC); + + SMetric3 LC(1./(lc*lc)); + SMetric3 m = intersection(intersection (l4, LC),l3); + // printf("%g %g %g %g %g %g\n",m(0,0),m(1,1),m(2,2),m(0,1),m(0,2),m(1,2)); + return m; // return lc * CTX::instance()->mesh.lcFactor; } diff --git a/Mesh/CMakeLists.txt b/Mesh/CMakeLists.txt index faa3cdb9f851a613232687d2e32f95bb4863f14b..ab0fc79380535c0c15db93b74067d21656836461 100644 --- a/Mesh/CMakeLists.txt +++ b/Mesh/CMakeLists.txt @@ -11,6 +11,7 @@ set(SRC meshGFace.cpp meshGFaceTransfinite.cpp meshGFaceExtruded.cpp + meshGFaceBamg.cpp meshGFaceBDS.cpp meshGFaceDelaunayInsertion.cpp meshGFaceLloyd.cpp diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp index 06cea7868f3fe2bc2d06f90f2e88d6d245bc4cbe..1a542e40a365496879a33fe200c8f1c573f2af40 100644 --- a/Mesh/meshGEdge.cpp +++ b/Mesh/meshGEdge.cpp @@ -11,6 +11,7 @@ #include "Numeric.h" #include "GmshMessage.h" #include "Context.h" +#include "STensor3.h" #define SQU(a) ((a)*(a)) @@ -98,9 +99,39 @@ static double F_Lc(GEdge *ge, double t) SVector3 der = ge->firstDer(t); const double d = norm(der); - return d / lc_here; + SMetric3 metric (1./(lc_here*lc_here)); + + // metric(0,0) = metric(0,0)*10000; + + double lSquared = dot (der,metric,der); + + return sqrt(lSquared); } +static double F_Lc_aniso(GEdge *ge, double t) +{ + GPoint p = ge->point(t); + SMetric3 lc_here; + + Range<double> bounds = ge->parBounds(0); + double t_begin = bounds.low(); + double t_end = bounds.high(); + + if(t == t_begin) + lc_here = BGM_MeshMetric(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z()); + else if(t == t_end) + lc_here = BGM_MeshMetric(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z()); + else + lc_here = BGM_MeshMetric(ge, t, 0, p.x(), p.y(), p.z()); + + SVector3 der = ge->firstDer(t); + + double lSquared = dot (der,lc_here,der); + + return sqrt(lSquared); +} + + static double F_Transfinite(GEdge *ge, double t_) { double length = ge->length(); @@ -325,7 +356,7 @@ void meshGEdge::operator() (GEdge *ge) N = ge->meshAttributes.nbPointsTransfinite; } else{ - if(CTX::instance()->mesh.lcIntegrationPrecision > 1.e-8){ + if(CTX::instance()->mesh.lcIntegrationPrecision > 1.e-2){ std::vector<IntPoint> lcPoints; Integration(ge, t_begin, t_end, F_Lc_usingInterpLcBis, lcPoints, CTX::instance()->mesh.lcIntegrationPrecision); @@ -333,8 +364,12 @@ void meshGEdge::operator() (GEdge *ge) a = Integration(ge, t_begin, t_end, F_Lc_usingInterpLc, Points, 1.e-8); } else{ - a = Integration(ge, t_begin, t_end, F_Lc, Points, - CTX::instance()->mesh.lcIntegrationPrecision); + if (CTX::instance()->mesh.algo2d == ALGO_2D_BAMG) + a = Integration(ge, t_begin, t_end, F_Lc_aniso, Points, + CTX::instance()->mesh.lcIntegrationPrecision); + else + a = Integration(ge, t_begin, t_end, F_Lc, Points, + CTX::instance()->mesh.lcIntegrationPrecision); } N = std::max(ge->minimumMeshSegments() + 1, (int)(a + 1.)); } diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index 72a71cba2a2f4e753b7ce2855c07660fe8e9ef3a..5345a11cbac9b28a5e9cbeb0f28250466cec9c63 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -9,6 +9,7 @@ #include "meshGFace.h" #include "meshGFaceBDS.h" #include "meshGFaceDelaunayInsertion.h" +#include "meshGFaceBamg.h" #include "meshGFaceQuadrilateralize.h" #include "meshGFaceOptimize.h" #include "DivideAndConquer.h" @@ -299,7 +300,8 @@ static void remeshUnrecoveredEdges(std::map<MVertex*, BDS_Point*> &recoverMapInv static bool algoDelaunay2D(GFace *gf) { - if(noSeam(gf) && (CTX::instance()->mesh.algo2d == ALGO_2D_DELAUNAY || + if(noSeam(gf) && (CTX::instance()->mesh.algo2d == ALGO_2D_DELAUNAY || + CTX::instance()->mesh.algo2d == ALGO_2D_BAMG || CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL)) return true; return false; @@ -824,8 +826,12 @@ static bool meshGenerator(GFace *gf, int RECUR_ITER, if(algoDelaunay2D(gf)){ if(CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) bowyerWatsonFrontal(gf); - else + else if(CTX::instance()->mesh.algo2d == ALGO_2D_DELAUNAY) + bowyerWatson(gf); + else { bowyerWatson(gf); + meshGFaceBamg(gf); + } for(int i = 0; i < CTX::instance()->mesh.nbSmoothing; i++) laplaceSmoothing(gf); } @@ -1378,8 +1384,10 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true) if(algoDelaunay2D(gf)){ if(CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) bowyerWatsonFrontal(gf); - else + else if(CTX::instance()->mesh.algo2d == ALGO_2D_DELAUNAY) bowyerWatson(gf); + else + meshGFaceBamg(gf); for(int i = 0; i < CTX::instance()->mesh.nbSmoothing; i++) laplaceSmoothing(gf); } @@ -1444,11 +1452,14 @@ void meshGFace::operator() (GFace *gf) } const char *algo = "Unknown"; - if(algoDelaunay2D(gf)) - algo = (CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) ? - "Frontal" : "Delaunay"; + if(CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) + algo = "Frontal"; + else if(CTX::instance()->mesh.algo2d == ALGO_2D_DELAUNAY) + algo = "Delaunay"; else if(CTX::instance()->mesh.algo2d == ALGO_2D_MESHADAPT_OLD) algo = "MeshAdapt (old)"; + else if(CTX::instance()->mesh.algo2d == ALGO_2D_BAMG) + algo = "Bamg"; else algo = "MeshAdapt"; @@ -1471,7 +1482,7 @@ void meshGFace::operator() (GFace *gf) (gf, debugSurface >= 0 || debugSurface == -100)) Msg::Error("Impossible to mesh face %d", gf->tag()); } - + Msg::Debug("Type %d %d triangles generated, %d internal vertices", gf->geomType(), gf->triangles.size(), gf->mesh_vertices.size()); diff --git a/Mesh/meshGFaceBamg.cpp b/Mesh/meshGFaceBamg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03e78f6e07cb82c91184bb24dfbe626177658af0 --- /dev/null +++ b/Mesh/meshGFaceBamg.cpp @@ -0,0 +1,214 @@ +#include <iostream> +#include "meshGFaceBamg.h" +#include "meshGFaceLloyd.h" +#include "GmshMessage.h" +#include "GFace.h" +#include "GModel.h" +#include "MVertex.h" +#include "MTriangle.h" +#include "MLine.h" +#include "GmshConfig.h" +#include "Context.h" +#include <list> +#include <map> +#include "BackgroundMesh.h" + +#ifdef HAVE_BAMG +long verbosity = 0; +#include "Mesh2d.hpp" +#include "Mesh2.h" +Mesh2 *Bamg(Mesh2 *Thh, double * args,double *mm11,double *mm12,double *mm22, bool); +//#include "bamg-gmsh.hpp" + +static void computeMeshMetricsForBamg (GFace *gf, + int numV, + Vertex2 *bamgVertices, + double *mm11, + double *mm12, + double *mm22, + int iter ){ + // char name[245]; + // sprintf(name,"bgmBamg-%d-%d.pos",gf->tag(),iter); + // if (iter < 2){ + // backgroundMesh::set(gf); + // backgroundMesh::current()->print(name, 0); + // } + + fullMatrix<double> J(2,3), JT(3,2),M(3,3),R(2,2),W(2,3); + for (int i=0;i<numV;++i){ + double u = bamgVertices[i][0]; + double v = bamgVertices[i][1]; + GPoint gp = gf->point(SPoint2(u,v)); + SMetric3 m = BGM_MeshMetric(gf,u,v,gp.x(),gp.y(),gp.z()); + + // compute the derivatives of the parametrization + Pair<SVector3, SVector3> der = gf->firstDer(SPoint2(u, v)); + + J(0,0) = JT(0,0) = der.first().x(); + J(0,1) = JT(1,0) = der.first().y(); + J(0,2) = JT(2,0) = der.first().z(); + J(1,0) = JT(0,1) = der.second().x(); + J(1,1) = JT(1,1) = der.second().y(); + J(1,2) = JT(2,1) = der.second().z(); + + m.getMat(M); + J.mult(M,W); + W.mult(JT,R); + bamg::Metric M1(R(0,0),R(1,0),R(1,1)); + mm11[i] = M1.a11; + mm12[i] = M1.a21; + mm22[i] = M1.a22; + } + + +} + +static void meshGFaceBamg_ ( GFace *gf , int iter, bool initialMesh){ + std::set<MVertex*> all; + std::map<int,MVertex*> recover; + for (int i=0;i<gf->triangles.size();i++){ + for (int j=0;j<3;j++)all.insert(gf->triangles[i]->getVertex(j)); + } + Vertex2 *bamgVertices = new Vertex2[all.size()]; + int index = 0; + for(std::set<MVertex*>::iterator it = all.begin(); it!=all.end(); ++it){ + if ((*it)->onWhat()->dim() < 2){ + SPoint2 p; + bool success = reparamMeshVertexOnFace(*it, gf, p); + bamgVertices[index][0] = p.x(); + bamgVertices[index][1] = p.y(); + bamgVertices[index].lab = index; + recover[index] = *it; + (*it)->setIndex(index++); + } + } + int nbFixedVertices = index; + for(std::set<MVertex*>::iterator it = all.begin(); it!=all.end(); ++it){ + // FIXME : SEAMS should have to be taken into account here !!! + if ((*it)->onWhat()->dim() >= 2){ + SPoint2 p; + bool success = reparamMeshVertexOnFace(*it, gf, p); + bamgVertices[index][0] = p.x(); + bamgVertices[index][1] = p.y(); + recover[index] = *it; + (*it)->setIndex(index++); + } + } + + Triangle2 *bamgTriangles = new Triangle2[gf->triangles.size()]; + for (int i=0;i<gf->triangles.size();i++){ + + int nodes [3] = {gf->triangles[i]->getVertex(0)->getIndex(), + gf->triangles[i]->getVertex(1)->getIndex(), + gf->triangles[i]->getVertex(2)->getIndex()}; + double u1(bamgVertices[nodes[0]][0]); + double u2(bamgVertices[nodes[1]][0]); + double u3(bamgVertices[nodes[2]][0]); + double v1(bamgVertices[nodes[0]][1]); + double v2(bamgVertices[nodes[1]][1]); + double v3(bamgVertices[nodes[2]][1]); + double sign = (u2-u1)*(v3-v1) - (u3-u1)*(v2-v1); + if (sign < 0){ + int temp = nodes[0]; + nodes[0] = nodes[1]; + nodes[1] = temp; + } + + bamgTriangles[i].init (bamgVertices,nodes,gf->tag()); + } + std::list<GEdge*> edges = gf->edges(); + int numEdges = 0; + for (std::list<GEdge*>::iterator it = edges.begin(); it != edges.end(); ++it){ + numEdges += (*it)->lines.size(); + } + + Seg *bamgBoundary = new Seg[numEdges]; + + int count = 0; + for (std::list<GEdge*>::iterator it = edges.begin(); it != edges.end(); ++it){ + for (int i=0; i<(*it)->lines.size();++i){ + int nodes [2] = {(*it)->lines[i]->getVertex(0)->getIndex(), + (*it)->lines[i]->getVertex(1)->getIndex()}; + bamgBoundary[count].init (bamgVertices,nodes,(*it)->tag()); + bamgBoundary[count++].lab = count; + } + } + Mesh2 bamgMesh ( all.size(), gf->triangles.size(), numEdges, + bamgVertices, bamgTriangles,bamgBoundary); + double *mm11 = new double [all.size()]; + double *mm12 = new double [all.size()]; + double *mm22 = new double [all.size()]; + double args[256]; + computeMeshMetricsForBamg (gf,all.size(),bamgVertices,mm11,mm12,mm22,iter); + for (int i=0;i<256;i++)args[i] = -1.1e100; + Mesh2 *refinedBamgMesh = 0; + try{ + refinedBamgMesh = Bamg (&bamgMesh, args, mm11,mm12,mm22, initialMesh); + Msg::Info ("bamg succeeded %d vertices %d triangles", + refinedBamgMesh->nv,refinedBamgMesh->nt); + } + catch(...){ + Msg::Error ("bamg failed"); + return ; + } + delete [] mm11; + delete [] mm12; + delete [] mm22; + std::map<int,MVertex*> yetAnother; + for (int i=0;i< refinedBamgMesh->nv;i++){ + Vertex2 &v = refinedBamgMesh->vertices[i]; + // printf("v.lab = %d\n",v.lab); + if (i >= nbFixedVertices){ + GPoint gp = gf->point(SPoint2(v[0],v[1])); + MFaceVertex *x = new MFaceVertex(gp.x(),gp.y(),gp.z(),gf,v[0],v[1]); + yetAnother[i] = x; + gf->mesh_vertices.push_back(x); + } + else { + yetAnother[i] = recover[i]; + } + } + + for (int i=0;i<gf->triangles.size();i++){ + delete gf->triangles[i]; + } + gf->triangles.clear(); + for (int i=0;i< refinedBamgMesh->nt;i++){ + Triangle2 &t = refinedBamgMesh->triangles[i]; + Vertex2 &v1 = t[0]; + Vertex2 &v2 = t[1]; + Vertex2 &v3 = t[2]; + gf->triangles.push_back(new MTriangle(yetAnother[(*refinedBamgMesh)(v1)], + yetAnother[(*refinedBamgMesh)(v2)], + yetAnother[(*refinedBamgMesh)(v3)] + )); + } + + + if (refinedBamgMesh)delete refinedBamgMesh; +} +void meshGFaceBamg ( GFace *gf ){ + + int nT = gf->triangles.size(); + // meshGFaceBamg_ ( gf , 0, true); + for (int i=1;i<14;i++){ + // char name[245]; + // sprintf(name,"hop%d.msh",i); + // GModel::current()->writeMSH(name); + meshGFaceBamg_ ( gf , i, false); + // sprintf(name,"hap%d.msh",i); + // GModel::current()->writeMSH(name); + + int nTnow = gf->triangles.size(); + if (fabs((double)(nTnow - nT)) < 0.01 * nT)break; + nT = nTnow; + } + // lloydAlgorithm lloyd (20); + // lloyd(gf); +} + +#else +void meshGFaceBamg ( GFace *gf ){ + Msg::Fatal("Gmsh msust be compiled with the Bidimensional Anisotropic Mesh Generator (Bamg) in order to support that option"); +} +#endif diff --git a/Mesh/meshGFaceBamg.h b/Mesh/meshGFaceBamg.h new file mode 100644 index 0000000000000000000000000000000000000000..dc57394256970a4303defc0f0249838f9e319267 --- /dev/null +++ b/Mesh/meshGFaceBamg.h @@ -0,0 +1,6 @@ +#ifndef _MESHGFACE_BAMG_ +#define _MESHGFACE_BAMG_ +class GFace; +void meshGFaceBamg ( GFace *gf ); + +#endif diff --git a/Numeric/fullMatrix.cpp b/Numeric/fullMatrix.cpp index 632e1a93ccc31f96f79ef6684025e50c7123a923..d6bc9400ebb9d55bd915b34fb0fc170447a2af19 100644 --- a/Numeric/fullMatrix.cpp +++ b/Numeric/fullMatrix.cpp @@ -259,7 +259,7 @@ bool fullMatrix<double>::invertInPlace() if(info == 0) return true; if(info > 0) - Msg::Error("U(%d,%d)=0 in matrix inversion", info, info); + Msg::Error("U(%d,%d)=0 in matrix in place inversion", info, info); else Msg::Error("Wrong %d-th argument in matrix inversion", -info); return false; diff --git a/benchmarks/2d/Square-01.geo b/benchmarks/2d/Square-01.geo index a31a52030be939cdfa67fc015b91fb62ce132f00..e6aab03099f01d00f9dce173efdc20436f26f101 100644 --- a/benchmarks/2d/Square-01.geo +++ b/benchmarks/2d/Square-01.geo @@ -1,8 +1,9 @@ -lc = .1; +fact = 100; +lc = .1 * fact; Point(1) = {0.0,0.0,0,lc}; -Point(2) = {1,0.0,0,lc}; -Point(3) = {1,1,0,lc}; -Point(4) = {0,1,0,lc}; +Point(2) = {1* fact,0.0,0,lc}; +Point(3) = {1* fact,1* fact,0,lc*.1}; +Point(4) = {0,1* fact,0,lc}; Line(1) = {3,2}; Line(2) = {2,1}; Line(3) = {1,4}; diff --git a/benchmarks/2d/naca12_2d.geo b/benchmarks/2d/naca12_2d.geo index 6baf8b1e2f6c2a3f617ea1ecab6b61bc1b7032e4..d5d5e3a6b666680d8d67bc61b5582083686c44d4 100644 --- a/benchmarks/2d/naca12_2d.geo +++ b/benchmarks/2d/naca12_2d.geo @@ -1,5 +1,5 @@ lc = 0.2 ; -lc2 = 1 ; +lc2 = 10 ; lc3 = 0.1 ; Point(1) = {1.000000e+00,0.000000e+00,0.000000e+00,lc3}; Point(2) = {9.997533e-01,0.000000e+00,-3.498543e-05,lc}; diff --git a/benchmarks/2d/square.geo b/benchmarks/2d/square.geo index f71192fde8f4f84386c89297a0f70bc6d6e96103..62bd5d191c4c25b5f0dddc76bf1bac1d3aa0abed 100644 --- a/benchmarks/2d/square.geo +++ b/benchmarks/2d/square.geo @@ -1,8 +1,9 @@ -lc=0.03; + +lc=0.3; Point(1) = {0, 0, 0,lc}; -Point(2) = {0, 1, 0,lc}; -Point(3) = {1, 1, 0,lc}; -Point(4) = {1, 0, 0,lc}; +Point(2) = {0, 1, 0,lc/1}; +Point(3) = {1, 1, 0,lc/1}; +Point(4) = {1, 0, 0,lc/1}; Line(1) = {2, 3}; Line(2) = {3, 4}; Line(3) = {4, 1}; diff --git a/benchmarks/2d/wing-splines.geo b/benchmarks/2d/wing-splines.geo index 55d9ee96ee923da62e5e15660fd00ced8e713681..a6eeab357b6fdb9c543f084781a70a7617c231cc 100644 --- a/benchmarks/2d/wing-splines.geo +++ b/benchmarks/2d/wing-splines.geo @@ -1,6 +1,7 @@ -scale = 1 ; -lc_wing = 0.1 * scale ; +scale = .01 ; + +lc_wing = 0.0001 * scale ; lc_box = 10 * scale ; Point(3895) = {1.177410e-02*scale,-2.768003e-03*scale,0,lc_wing}; @@ -513,29 +514,9 @@ Point(4268) = {1.114765e+00*scale,-1.246442e-01*scale,0,lc_wing}; Point(4291) = {1.120249e+00*scale,-1.301373e-01*scale,0,lc_wing}; Point(4336) = {1.122990e+00*scale,-1.328839e-01*scale,0,lc_wing}; -Point(11) = {4.552264e+01*scale,-2.254225e+01*scale,0,lc_box}; -Point(2233) = {4.552264e+01*scale,-1.129225e+01*scale,0,lc_box}; -Point(5) = {4.552264e+01*scale,-4.224671e-02*scale,0,lc_box}; -Point(2236) = {4.552264e+01*scale,1.120775e+01*scale,0,lc_box}; -Point(14) = {4.552264e+01*scale,2.245775e+01*scale,0,lc_box}; Point(2) = {4.552264e+01*scale,4.495775e+01*scale,0,lc_box}; -Point(15) = {2.302264e+01*scale,4.495775e+01*scale,0,lc_box}; -Point(2301) = {1.177264e+01*scale,4.495775e+01*scale,0,lc_box}; -Point(6) = {5.226384e-01*scale,4.495775e+01*scale,0,lc_box}; -Point(2304) = {-1.072736e+01*scale,4.495775e+01*scale,0,lc_box}; -Point(18) = {-2.197736e+01*scale,4.495775e+01*scale,0,lc_box}; Point(3) = {-4.447736e+01*scale,4.495775e+01*scale,0,lc_box}; -Point(19) = {-4.447736e+01*scale,2.245775e+01*scale,0,lc_box}; -Point(2240) = {-4.447736e+01*scale,1.120775e+01*scale,0,lc_box}; -Point(7) = {-4.447736e+01*scale,-4.224671e-02*scale,0,lc_box}; -Point(2243) = {-4.447736e+01*scale,-1.129225e+01*scale,0,lc_box}; -Point(22) = {-4.447736e+01*scale,-2.254225e+01*scale,0,lc_box}; Point(4) = {-4.447736e+01*scale,-4.504225e+01*scale,0,lc_box}; -Point(23) = {-2.197736e+01*scale,-4.504225e+01*scale,0,lc_box}; -Point(2317) = {-1.072736e+01*scale,-4.504225e+01*scale,0,lc_box}; -Point(8) = {5.226384e-01*scale,-4.504225e+01*scale,0,lc_box}; -Point(2297) = {1.177264e+01*scale,-4.504225e+01*scale,0,lc_box}; -Point(10) = {2.302264e+01*scale,-4.504225e+01*scale,0,lc_box}; Point(1) = {4.552264e+01*scale,-4.504225e+01*scale,0,lc_box}; //one @@ -612,7 +593,7 @@ Line Loop(405) = {10,11,12}; Plane Surface(406) = {403,404,401,405}; lc4 = lc_wing * 4; - +/* Point(4351) = {0.4,-0,0,lc4}; Point(4352) = {1.4,0,0,lc4}; Point(4353) = {0.4,-1,0,lc4}; @@ -622,4 +603,4 @@ Circle(407) = {4352,4351,4355}; Circle(408) = {4355,4351,4354}; Circle(409) = {4354,4351,4353}; Circle(410) = {4353,4351,4352}; - +*/ diff --git a/benchmarks/boolean/constraintSurface.lua b/benchmarks/boolean/constraintSurface.lua index 85dee40eb7ac9d72466d067663ce2bf46782b3e9..bf9aa6020d02325d1139395381502b7061e61d3b 100644 --- a/benchmarks/boolean/constraintSurface.lua +++ b/benchmarks/boolean/constraintSurface.lua @@ -3,30 +3,30 @@ g = GModel() v1 = g:addVertex(0, 0, 0, .1) v2 = g:addVertex(1, 0, 0, .1) v3 = g:addVertex(1, 1, 0, .1) -v4 = g:addVertex(0, 1, 1, .1) +v4 = g:addVertex(0, 3, 1, .1) v5 = g:addVertex(2, 3, 0, .1) v6 = g:addVertex(-2, 3, 0, .1) v7 = g:addVertex(-1, 3, 0, .1) -v11 = g:addVertex(2.5, 2.5, 0, .1) -v12 = g:addVertex(2.6, 2.5, 0, .1) -v13 = g:addVertex(2.6, 2.6, 0, .1) -v14 = g:addVertex(2.5, 2.6, 0, .1) +--v11 = g:addVertex(2.5, 2.5, 0, .1) +--v12 = g:addVertex(2.6, 2.5, 0, .1) +--v13 = g:addVertex(2.6, 2.6, 0, .1) +--v14 = g:addVertex(2.5, 2.6, 0, .1) e7 = g:addBezier (v2,v1, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}); -e8 = g:addLine (v2,v1); +--e8 = g:addLine (v2,v1); -v221 = g:addVertex(0, 0, 1, .1) -v121 = g:addVertex(1, 0, 1, .1) -e17 = g:addBezier (v121,v221, {{v3:x()+1,v3:y(),1},{v4:x(),v4:y(),1},{v5:x(),v5:y(),1},{v6:x(),v6:y(),1},{v7:x(),v7:y(),1}}); +v221 = g:addVertex(0, 0, 10, .1) +v121 = g:addVertex(1, 0, 10, .1) +e17 = g:addBezier (v121,v221, {{v3:x()+1,v3:y(),10},{v4:x(),v4:y()+2,10},{v5:x(),v5:y()-3,10},{v6:x(),v6:y(),10},{v7:x(),v7:y(),10}}); -e11 = g:addLine (v11,v12); -e12 = g:addLine (v12,v13); -e13 = g:addLine (v13,v14); -e14 = g:addLine (v14,v11); +--e11 = g:addLine (v11,v12); +--e12 = g:addLine (v12,v13); +--e13 = g:addLine (v13,v14); +--e14 = g:addLine (v14,v11); g:addRuledFaces ({{e7},{e17}}) -g:addFace ({e7,e8},{{0,0,0}}) -g:addFace ({e11,e12,e13,e14}) +--g:addFace ({e7,e8},{{0,0,0}}) +--g:addFace ({e11,e12,e13,e14}) diff --git a/benchmarks/boolean/cube1.lua b/benchmarks/boolean/cube1.lua index 72effd501f017fde744b17d4c5c392eeba8186e3..ad5499c9ff74a2b2929a13c0b8b8d757a5e20e22 100644 --- a/benchmarks/boolean/cube1.lua +++ b/benchmarks/boolean/cube1.lua @@ -4,7 +4,7 @@ g = GModel() v1 = g:addVertex(0, 0, 0, 1) v2 = g:addVertex(1, 0, 0, 1) e1 = g:addLine(v1, v2) -f1 = g:extrude(e1, {0,0,0}, {0,1,0}) +f1 = g:extrude(e1, {0,0,0}, {0,10,0}) r1 = g:extrude(f1, {0,0,0}, {0,0,1}) r1 = g:revolve(f1, {-.1,0,0}, {-.1,1,0}, 3.1415 / 2) diff --git a/benchmarks/boolean/nurbs.lua b/benchmarks/boolean/nurbs.lua index bd83cf472f7512f1952a742e085c6e325b5a3d1e..5c0b048e6ad369b88c188cdb2d366b3d664c0267 100644 --- a/benchmarks/boolean/nurbs.lua +++ b/benchmarks/boolean/nurbs.lua @@ -9,22 +9,22 @@ v5 = g:addVertex(2,1,0,.1); v6 = g:addVertex(2.5,-.05,0,.1); v7 = g:addVertex(1.5,-1,0,.1); -g:addLine(v1,v3); -g:addLine(v3,v4); -g:addLine(v4,v5); -g:addLine(v5,v6); -g:addLine(v6,v7); -g:addLine(v7,v2); +--g:addLine(v1,v3); +--g:addLine(v3,v4); +--g:addLine(v4,v5); +--g:addLine(v5,v6); +--g:addLine(v6,v7); +--g:addLine(v7,v2); --g:addNURBS (v1,v2, {{0.1,0.1,0},{0.2,0.1,0},{0.3,0.2,0},{0.4,0.6,0},{0.9,0.8,0}}, -- {0,0,0,0,0.25,0.5,0.75,1,1,1,1},{1,1,1,1,1,1,1},{4,1,1,1,1,1,4}); -g:addBezier (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}); -g:addNURBS (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}, - {0,0.25,0.5,0.75,1},{1,1,1,1,1,1,1},{4,1,1,1,4}); -g:addNURBS (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}, - {0,0.5,1},{1,1,1,1,1,1,1},{4,3,4}); +--g:addBezier (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}); +--g:addNURBS (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}, +-- {0,0.25,0.5,0.75,1},{1,1,1,1,1,1,1},{4,1,1,1,4}); +--g:addNURBS (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}, {0,0.5,1},{1,1,1,1,1,1,1},{4,3,4}); -g:addNURBS (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}, +e1 = g:addNURBS (v1,v2, {{v3:x(),v3:y(),0},{v4:x(),v4:y(),0},{v5:x(),v5:y(),0},{v6:x(),v6:y(),0},{v7:x(),v7:y(),0}}, {0,1/3.,2./3.,1},{1,1,1,1,1,1,1},{5,1,1,5}); +f1 = g:extrude(e1, {0,0,0}, {0,0,1}) diff --git a/contrib/bamg/CMakeLists.txt b/contrib/bamg/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..adfc2be32d650df0055a405d82643a5b2dd95d02 --- /dev/null +++ b/contrib/bamg/CMakeLists.txt @@ -0,0 +1,24 @@ +# Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle +# +# See the LICENSE.txt file for license information. Please report all +# bugs and problems to <gmsh@geuz.org>. + +set(SRC + Mesh2d.cpp + bamg-gmsh.cpp + bamglib/Mesh2.cpp + bamglib/MeshGeom.cpp + bamglib/MeshRead.cpp + bamglib/Metric.cpp + bamglib/R2.cpp + bamglib/MeshDraw.cpp + bamglib/MeshQuad.cpp + bamglib/Mesh2.cpp + bamglib/MeshWrite.cpp + bamglib/Meshio.cpp + bamglib/QuadTree.cpp + bamglib/SetOfE4.cpp +) + +file(GLOB_RECURSE HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.hpp) +append_gmsh_src(contrib/bamg "${SRC};${HDR}") diff --git a/contrib/bamg/Label.hpp b/contrib/bamg/Label.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5c6357ae14148cec3ea8dcc72f3beea594bca0e3 --- /dev/null +++ b/contrib/bamg/Label.hpp @@ -0,0 +1,15 @@ +#ifndef LABEL_HPP +#define LABEL_HPP + +class Label { // reference number for the physics + public: + int lab; + Label(int r=0):lab(r){} + bool onGamma() const { return lab;} + }; + inline ostream& operator <<(ostream& f,const Label & r ) + { f << r.lab ; return f; } + inline istream& operator >>(istream& f, Label & r ) + { f >> r.lab ; return f; } + +#endif diff --git a/contrib/bamg/Mesh2d.cpp b/contrib/bamg/Mesh2d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..315d404f54dde8fe1141e4fb53e48fbedca1be28 --- /dev/null +++ b/contrib/bamg/Mesh2d.cpp @@ -0,0 +1,48 @@ +#include <cassert> +#include <fstream> +#include <iostream> +#include "ufunction.hpp" +#include "Mesh2d.hpp" + +Mesh2::Mesh2(const char * filename) + : nv(0),nt(0),nbe(0), + area(0),peri(0), + vertices(0),triangles(0),borderelements(0) +{ // read the mesh + int i,iv[3],ir; + ifstream f(filename); + if(!f) {cerr << "Mesh2::Mesh2 Erreur openning " << filename<<endl;exit(1);} + cout << " Read On file \"" <<filename<<"\""<< endl; + f >> nv >> nt >> nbe ; + cout << " Nb of Vertex " << nv << " Nb of Triangle2s " << nt + << " Nb of Border Seg : " << nbe << endl; + assert(f.good() && (nt>0) && (nv>0) &&( nbe>0) ) ; + triangles = new Triangle2 [nt]; + vertices = new Vertex[nv]; + borderelements = new Seg[nbe]; + area=0; + assert(triangles && vertices && borderelements); + for (i=0;i<nv;i++) + { + f >> vertices[i]; + assert(f.good()); + } + for (i=0;i<nt;i++) + { + f >> iv[0] >> iv[1] >> iv[2] >> ir; + assert(f.good() && iv[0]>0 && iv[0]<=nv && iv[1]>0 && iv[1]<=nv && iv[2]>0 && iv[2]<=nv); + for (int v=0;v<3;++v) iv[v]--; + triangles[i].init(vertices,iv,ir); + area += triangles[i].area; + } + for (i=0;i<nbe;i++) + { + f >> iv[0] >> iv[1] >> ir; + assert(f.good() && iv[0]>0 && iv[0]<=nv && iv[1]>0 && iv[1]<=nv); + for (int v=0;v<2;++v) iv[v]--; + borderelements[i].init(vertices,iv,ir); + peri += borderelements[i].l; + } + + cout << " End of read: area = " << area << " perimeter: " << peri << endl; +} diff --git a/contrib/bamg/Mesh2d.hpp b/contrib/bamg/Mesh2d.hpp new file mode 100755 index 0000000000000000000000000000000000000000..4c54887ceae1b681c29dd92d291761e2b70705a8 --- /dev/null +++ b/contrib/bamg/Mesh2d.hpp @@ -0,0 +1,170 @@ +// la regle de programmation 3 +#include "assertion.hpp" +#include <cstdlib> +using namespace std; +// definition R +#include "Label.hpp" +#include "R2.hpp" + + +class Vertex2 : public R2,public Label { + friend ostream& operator <<(ostream& f, const Vertex2 & v ) + { f << (R2) v << ' ' << (Label &) v ; return f; } + friend istream& operator >> (istream& f, Vertex2 & v ) + { f >> (R2 &) v >> (Label &) v ; return f; } + public: + Vertex2() : R2(),Label(){}; + // Vertex2(R2 P,int r=0): R2(P),Label(r){} + private: // pas de copie pour ne pas perdre l'adresse + Vertex2(const Vertex2 &); + void operator=(const Vertex2 &); +}; + + + + + + + +class Triangle2: public Label { + // variable prive + Vertex2 *vertices[3]; // an array of 3 pointer to vertex + public: + R area; + Triangle2() :area() {vertices[0]=vertices[1]=vertices[2]=0;}; // constructor empty for array + Vertex2 & operator[](int i) const { + ASSERTION(i>=0 && i <3); + return *vertices[i];} // to see traingle as a array of vertex + Vertex2 * & operator()(int i) { + ASSERTION(i>=0 && i <3); + return vertices[i];} // to see traingle as a array of vertex + void init(Vertex2 * v0,int * iv,int r) + { vertices[0]=v0+iv[0]; + vertices[1]=v0+iv[1]; + vertices[2]=v0+iv[2]; + R2 AB(*vertices[0],*vertices[1]); + R2 AC(*vertices[0],*vertices[2]); + area = (AB^AC)*0.5; + lab=r; + ASSERTION(area>0); + } + R2 Edge(int i) const {ASSERTION(i>=0 && i <3); + return R2(*vertices[(i+1)%3],*vertices[(i+2)%3]);}// opposite edge vertex i + R2 H(int i) const { ASSERTION(i>=0 && i <3); + R2 E=Edge(i);return E.perp()/(2*area);} // heigth + + void Gradlambda(R2 * GradL) const + { + GradL[1]= H(1); + GradL[2]= H(2); + GradL[0]=-GradL[1]-GradL[2]; + } + + R lenEdge(int i) const {ASSERTION(i>=0 && i <3); + R2 E=Edge(i);return sqrt((E,E));} + + // Transformation: $\hat{K} \mapsto K$ + R2 operator()(const R2 & Phat) const { + const R2 &A =*vertices[0]; + const R2 &B =*vertices[1]; + const R2 &C =*vertices[2]; + return (1-Phat.x- Phat.y)* A + Phat.x *B +Phat.y*C ;} + + private: + Triangle2(const Triangle2 &); // pas de construction par copie + void operator=(const Triangle2 &);// pas affectation par copy + // Ajoute FH dernier cours ---- +public: + R mesure() const {return area;} + static const int nv=3; +}; + + + + + +// la classe pour le maillage du bord, ici des Segment: +class Seg: public Label { +public: + static const int nv=2; // the nomber of vertices +private: + Vertex2 *vertices[nv]; // an array of 2 pointer to vertex +public: + R l; // lhe lenght of the segment + + Seg() :l() {vertices[0]=vertices[1]=0;} // constructor empty for array + + Vertex2 & operator[](int i) const { + ASSERTION(i>=0 && i <nv); + return *vertices[i];} // to see the segment as a array of vertex + + void init(Vertex2 * v0,int * iv,int r) // the true constructor + { + vertices[0]=v0+iv[0]; + vertices[1]=v0+iv[1]; + R2 AB(*vertices[0],*vertices[1]); + l= AB.norme(); + lab=r; + ASSERTION(l>0); + } + + // Transformation: $[0,1] \mapsto K$ + R2 operator()(const R & Phat) const { + const R2 &A =*vertices[0]; + const R2 &B =*vertices[1]; + return (1-Phat)* A + Phat *B ;} + + R mesure() const {return l;} + +private: + Seg(const Seg &); // pas de construction par copie + void operator=(const Seg &);// pas affectation par copy +}; + + + + +class Mesh2 +{ +public: + typedef Triangle2 Element; + typedef Seg BorderElement; + typedef R2 Rd; + typedef Vertex2 Vertex; + int nv,nt, nbe; + R area,peri; + Vertex2 *vertices; + Triangle2 *triangles; + Seg * borderelements; + Triangle2 & operator[](int i) const {return triangles[CheckT(i)];} + Vertex2 & operator()(int i) const {return vertices[CheckV(i)];} + Seg & be(int i) const {return borderelements[CheckBE(i)];} // boundary element .. + Mesh2(const char * filename); // read on a file + Mesh2(int nnv,int nnt,int nnbe, Vertex2 *v,Triangle2 *t, Seg *b_e) + : nv(nnv),nt(nnt),nbe(nnbe),vertices(v),triangles(t),borderelements(b_e),area(0.),peri(0.) + { + for(int i=0;i<nt;++i) area += triangles[i].mesure(); + for(int i=0;i<nbe;++i) peri += borderelements[i].mesure(); + } + int operator()(const Triangle2 & t) const {return CheckT(&t - triangles);} + int operator()(const Triangle2 * t) const {return CheckT(t - triangles);} + int operator()(const Vertex2 & v) const {return CheckV(&v - vertices);} + int operator()(const Vertex2 * v) const{return CheckV(v - vertices);} + int operator()(const Seg & v) const {return CheckBE(&v - borderelements);} + int operator()(const Seg * v) const{return CheckBE(v - borderelements);} + int operator()(int it,int j) const {return (*this)(triangles[it][j]);}// Nu vertex j of triangle it + // to check the bound + 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;} + ~Mesh2() { + delete [] vertices; + delete [] triangles; + delete [] borderelements;} + private: + Mesh2(const Mesh2 &); // pas de construction par copie + void operator=(const Mesh2 &);// pas affectation par copy +}; + + + diff --git a/contrib/bamg/R2.hpp b/contrib/bamg/R2.hpp new file mode 100644 index 0000000000000000000000000000000000000000..98581dd13cd55e10005b0f528c35d99dacb3b279 --- /dev/null +++ b/contrib/bamg/R2.hpp @@ -0,0 +1,71 @@ +#ifndef R2_HPP +#define R2_HPP +#include <cmath> +#include <cstdlib> +#include <iostream> +// Definition de la class R2 +// sans compilation separe toute les fonctions +// sous defini dans ce R2.hpp avec des inline +// +// definition R (les nombres reals) +// remarque la fonction abort est defini dans +// #include <cstdlib> +typedef double R; + +// The class R2 +class R2 { +public: + typedef double R; + static const int d=2; + + R x,y; // declaration de membre + // les 3 constructeurs --- + R2 () :x(0.),y(0.) {} // rappel : x(0), y(0) sont initialiser via le constructeur de double + R2 (R a,R b):x(a),y(b) {} + R2 (const R2 & a,const R2 & b):x(b.x-a.x),y(b.y-a.y) {} + // le constucteur par defaut est inutile + R2 (const R2 & a) :x(a.x),y(a.y) {} + + // rappel les operator definis dans une class on un parametre + // cache qui est la classe elle meme (*this) + + // les operateurs affectation + // operateur affection (*this) = P est inutil par defaut il fait le travail correctement + R2 & operator=(const R2 & P) {x = P.x;y = P.y;return *this;} + // les autre operoteur affectations + R2 & operator+=(const R2 & P) {x += P.x;y += P.y;return *this;} + R2 & operator-=(const R2 & P) {x -= P.x;y -= P.y;return *this;} + // operateur binaire + - * , ^ / + R2 operator+(const R2 & P)const {return R2(x+P.x,y+P.y);} + R2 operator-(const R2 & P)const {return R2(x-P.x,y-P.y);} + R operator,(const R2 & P)const {return x*P.x+y*P.y;} // produit scalaire + R operator^(const R2 & P)const {return x*P.y-y*P.x;} // produit mixte + R2 operator*(R c)const {return R2(x*c,y*c);} + R2 operator/(R c)const {return R2(x/c,y/c);} + // operateur unaire + R2 operator-()const {return R2(-x,-y);} + R2 operator+()const {return *this;} + // un methode + R2 perp() const {return R2(-y,x);} // la perpendiculaire + // les operators tableau + // version qui peut modifie la class via l'adresse de x ou y + R & operator[](int i){ return (&x)[i];} + const R & operator[](int i) const { return (&x)[i];} + + + R norme() const { return std::sqrt(x*x+y*y);} + R norme2() const { return (x*x+y*y);} + +friend R2 operator*(R c,const R2 & P) {return P*c;} +friend R2 perp(const R2 & P) { return R2(-P.y,P.x) ; } +//inline R2 Perp(const R2 & P) { return P.perp(); } // autre ecriture de la fonction perp +friend R det(const R2 & A,const R2 & B,const R2 &C) { return R2(A,B)^R2(A,C);} + +friend std::ostream& operator <<(std::ostream& f, const R2 & P ) + { f << P.x << ' ' << P.y ; return f; } +friend std::istream& operator >>(std::istream& f, R2 & P) + { f >> P.x >> P.y ; return f; } +}; + +#endif + diff --git a/contrib/bamg/RNM.hpp b/contrib/bamg/RNM.hpp new file mode 100644 index 0000000000000000000000000000000000000000..053efd1d3b50892f6988602abfa0dc839f09021d --- /dev/null +++ b/contrib/bamg/RNM.hpp @@ -0,0 +1,1588 @@ +// ********** DO NOT REMOVE THIS BANNER ********** +// ORIG-DATE: 29 fev 2000 +// -*- Mode : c++ -*- +// +// SUMMARY : array modelisation +// USAGE : LGPL +// ORG : LJLL Universite Pierre et Marie Curie, Paris, FRANCE +// AUTHOR : Frederic Hecht +// E-MAIL : frederic.hecht@ann.jussieu.fr +// + +/* + + + + 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 + + + */ +#ifndef KNM_H_ +#define KNM_H_ +// version march 2010 FH. +// add iterator for compatibility with gmm++ +// ---------------------- +// une tentative qui ne marche pas +// de tableau constant +#include <complex> +#include <iostream> +#include <iomanip> +#include <cmath> +#include <cassert> + + +using namespace std; +#define const_R R + +#include <cstdlib> +inline void Check_Kn(const char * str,const char * file,int line) +{ + cerr << "CHECK_KN: " << str << " in file: " << file << ", line " << line <<endl; + assert(0); + abort(); +} + +#define K_bigassert(i) if (!(i)) Check_Kn(#i,__FILE__,__LINE__); +#define RNM_FATAL_ERROR(i) Check_Kn(i,__FILE__,__LINE__); +#ifdef CHECK_KN + +#define K_throwassert(i) if (!(i)) Check_Kn(#i,__FILE__,__LINE__); + +#else +#define K_throwassert(i) +#endif +// version du 29 fev 2000 +// correction for (... lj++,ui++ qui apelle le produit scalaire +// petite correction throwassert +// ajoute de operateur /= et *= sur des vecteurs +// suppression de constructeur qui pose de probleme +// correction oper += ... dans RNM_op.h ligne 56 change = en oper +// version de 25 nov 99 sans const R +// ajoute de '.' pour extraire une colonne, ou ligne , ... +// version du 22 nov 1999 cast to KN_<const R> +// version du 21 nov 1999 correction delete +// version du 13 nov 1999 +// version du 18 mars 99 +// F. Hecht +// attention les indexations les indexations peuvent changer +// puisque que l'on peut prendre la transposer d'une matrice +// tableau +// mais ils partent de 0 +// version corrigee du 15/11/98 +// version avec sous tableau --- mars 99 +// ------- +// remarque du 8 mars 99 FH +// class pour prendre des sous-tableau +// attention aux PB de continute dans les tableaux +// on a supposer que les tableaux multi indices pouvait est vue comme +// un tableau continue ce qui est generalement faux quand l'on en +// prend un sous tableau +// exemple: un tableau 3,5 est numerote comme: +// 0 3 6 9 12 +// 1 4 7 10 13 +// 2 5 8 11 14 +// step +// indexi n 1 +// indexj m n +// est le sous tableau 3,3 n'est pas numeroter consecutivement +// +// Donc la fonction IsVector1() nous dit si un tableau +// a un 2 ou 3 indices est ou non consecutif en memoire +// +// -- ajoute d'une classe VirtualMatrice +// pour modeliser le produit matrice vecteur +// x = A*v; via des fonctions virtuelle +// ---------------------------------- +// version du 6 mars 2001 FH +// --- initialisation -- +// -------------------------------- +// version du 9 oct 2001 FH +// ajoute de constructeur par defaut d'une vecteur +// + set , pour definir le vecteur +// ou l'affectation (bof bof) +// --------------------- +// version sep 2002 +// ajoute operateur >> pour KN<R> et KN_<R> +// -------------------- +// version april 2003 +// ajoute un gestion auto de +// la fonction InternalError pour les matriceVirtuel +// -------------------- +// version jan 2004 +// correction pour go ++ +// des operateur #= pour les matrices et tenseurs +// ---------------------- +// version feb 2004 +// v(i(:)) = w // i(1:10) +// w=u(i(:)) // +// version mars 2004 make small correction +// in ITAB operator problem if non type R a defi +// ------------------- +// Modif pour version avec les Complex mai 2004 +// (u,v) donne le produit complex utiliser dans le produit matrice vecteur +// (u,conj(v)) donne le produit hermitiene pour le gradient conjugue +// +// -- de fonction dans le cas real +// modif for g++ 4.0 and xlc++ mai 2005 +// adding some this-> +// mars 2007 +// correction in operator operation:b -1*c +// aout 2007, +// correct y = A*x ; when y is unset +// correct y += A*x ; when y is unset +// re-correct += sep 2007 +// add size of the matrix in VirtualMatrix class. +// mars 2010 add unset KNM case ... +// ---------------- +inline double conj(const double & x){return x;} +inline float conj(const float &x){return x;} +inline long conj(const long &x){return x;} +inline double real(const double &x){return x;} +inline float real(const float &x){return x;} + +namespace RNM +{ + template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;} + template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;} + template<class T> inline T Abs (const T &a){return a <0 ? -a : a;} + + template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;} + template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);} + template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);} + // specialisation cas complex --- + template<class T> + inline complex<T> Min(const complex<T> &a,complex<T> &b) + { return complex<T>(min(a.real(),b.real()),min(a.imag(),b.imag()));} + template<class T> + inline complex<T> Max(const complex<T> &a,const complex<T> &b) + { return complex<T>(max(a.real(),b.real()),max(a.imag(),b.imag()));} + + /*inline complex<double> Min(const complex<double> &a,complex<double> &b) + { return complex<double>(Min(real(a),real(b)),Min(imag(a),imag(b)));} + inline complex<double> Max(const complex<double> &a,const complex<double> &b) + { return complex<double>(Max(real(a),real(b)),Max(imag(a),imag(b)));} + */ +} +// ---- + +template<class R> class KNMK_ ; +template<class R> class KNM_ ; +template<class R> class KN_ ; +template<class R> class KN__iterator ; +template<class R> class KN__const_iterator ; +template<class R> class TKN_ ; // KN_ transpose +template<class R> class notKN_ ; // KN_ not +template<class R> class notnotKN_ ; // KN_ not not + +template<class R> class KNMK ; +template<class R> class KNM ; +template<class R> class KN ; + +template<class R> class conj_KN_ ; +template<class R> class Add_KN_; +template<class R> class Sub_KN_; +template<class R> class Mulc_KN_; +template<class R> class Add_Mulc_KN_; +template<class R> class Mul_KNM_KN_; +template<class R> class DotStar_KN_; +template<class R> class DotSlash_KN_; + +template<class R> class outProduct_KN_; +template<class R> class if_KN_; +template<class R> class if_arth_KN_; +template<class R> class ifnot_KN_; +template<class R,class I> class KN_ITAB; + +template<class R,typename A,typename B> class F_KN_; + + +#ifndef ffassert +#define ffassert assert +#endif + +// gestion des erreur interne -- +#ifndef InternalError +typedef void (* TypeofInternalErrorRoutine)(const char *) ; +static TypeofInternalErrorRoutine &InternalErrorRoutinePtr() +{ + static TypeofInternalErrorRoutine routine=0; + return routine; +} + +static void InternalError(const char * str) { + if (InternalErrorRoutinePtr() ) (*InternalErrorRoutinePtr())(str); + cerr << str; + exit(1); +} +inline void SetInternalErrorRoutine(TypeofInternalErrorRoutine f) +{ + InternalErrorRoutinePtr()=f; +} +#endif +// -- +template<class P,class Q> + struct PplusQ { const P & p;const Q & q; + PplusQ(const P & pp,const Q & qq) : p(pp),q(qq){} + }; + +template<class R> +struct VirtualMatrice { public: + int N,M; + VirtualMatrice(int nn,int mm): N(nn),M(mm) {} + VirtualMatrice(int nn): N(nn),M(nn) {} + // y += A x + virtual void addMatMul(const KN_<R> & x, KN_<R> & y) const =0; + virtual void addMatTransMul(const KN_<R> & , KN_<R> & ) const + { InternalError("VirtualMatrice::addMatTransMul not implemented "); } + virtual bool WithSolver() const {return false;} // by default no solver + virtual void Solve( KN_<R> & ,const KN_<R> & ) const + { InternalError("VirtualMatrice::solve not implemented "); } + +#ifdef VersionFreeFempp + virtual bool ChecknbLine (int n) const= 0; + virtual bool ChecknbColumn (int m) const =0; +#else + virtual bool ChecknbLine (int n) const {return true;} + virtual bool ChecknbColumn (int m) const {return true;} +#endif + struct plusAx { const VirtualMatrice * A; const KN_<R> x; + plusAx( const VirtualMatrice * B,const KN_<R> & y) :A(B),x(y) + { ffassert(B->ChecknbColumn(y.N())); } + }; + + plusAx operator*(const KN_<R> & x) const {return plusAx(this,x);} + + struct plusAtx { const VirtualMatrice * A; const KN_<R> x; + plusAtx( const VirtualMatrice * B,const KN_<R> & y) :A(B),x(y) + {ffassert(B->ChecknbLine(y.N()));} }; + + struct solveAxeqb { const VirtualMatrice * A; const KN_<R> b; + solveAxeqb( const VirtualMatrice * B,const KN_<R> & y) :A(B),b(y) + {ffassert(B->ChecknbColumn(y.N()));} }; + + virtual ~VirtualMatrice(){} +}; + + + +//template <class R> class MatriceCreuseMulKN_; +//template <class R> class MatriceCreuseDivKN_; + +class ShapeOfArray; + +class FromTo{ public: + long from,to; + FromTo(long i,long j):from(i),to(j) {K_throwassert(i<j);} + }; + +class SubArray{ public: + const long n,step,start; +// SubArray(char nn): n(-1),step(1),start(0) {} + explicit SubArray(long nn,long sta=0,long s=1): n(nn),step(s),start(sta) {} + SubArray(const FromTo& ft) : n(ft.to-ft.from+1),step(1),start(ft.from) {} + SubArray(const ShapeOfArray & ); // all + long end() const { return start+ step*n;} + long last() const { return start+ step*(n-1);} + long len1() const { return step*(n-1);} +}; + + +class ShapeOfArray{ protected: + public: + + long n; // n nb of item + long step; // step nb of between 2 item + long next; // the next array of same type in matrix for subarray + // by default no next ( in case of KN, and KNM -next is + // a counter of destruction (use in frefem++) + ShapeOfArray(const ShapeOfArray & s,long nn): n(s.n),step(s.n),next(nn) {} + ShapeOfArray(long nn): n(nn),step(1),next(-1) {} + + ShapeOfArray(long nn,long s): n(nn),step(s),next(-1) {} + + ShapeOfArray(long nn,long s,long nextt): n(nn),step(s),next(nextt) {} + + ShapeOfArray(const ShapeOfArray &old,const SubArray &sub) + : n(sub.n),step(old.step*sub.step),next(old.next) + { K_throwassert((sub.last())*old.step <= old.last());} // a constructor + + ShapeOfArray(const ShapeOfArray &old,long stepo,long start) + : n(old.n-start),step(old.step*stepo),next(old.next) + { K_throwassert(n>=0);} + + long end() const { return n*step;} + long last() const { return (n-1)*step;} + long constant() const { return step==0;} + long index(long k) const { K_throwassert( (k>=0) && ( (k <n) || !step) ); + return step*k;} + ShapeOfArray operator*(long stepp) const {return ShapeOfArray(n,step*stepp,next);} + bool SameShape(const ShapeOfArray & a) const + { return !step || !a.step || a.n == n ;} + long N(const ShapeOfArray & a) { return step ? n : a.n;} // size of 2 shape + + +// protected: + long operator[](long k) const { + //if( k<0 || ( k<n && !step) ) + // cout << "k,n,step=" << k << " " << n << " " << step << endl; + K_throwassert( (k>=0) && ( (k <n) || !step) ); + return step*k;} + void init(long nn,long s=1,long nextt=-1) { n=nn; step=s; next=nextt;} +}; + +ostream & operator<<(ostream & f,const ShapeOfArray & s); + +inline bool SameShape(const ShapeOfArray & a,const ShapeOfArray & b) + { return !a.step || !b.step || a.n == b.n ;} + +inline long N(const ShapeOfArray & a,const ShapeOfArray & b) + { K_throwassert(SameShape(a,b)); return a.step ? a.n : b.n ;} + +inline SubArray::SubArray(const ShapeOfArray & s) + :n(s.n),step(s.step),start(0) {} + + + +template<class R> +ostream & operator<<(ostream & f,const KN_<const_R> & v) ; + +template<class R> istream & operator>>(istream & f, KN_<R> & v); +template<class R> istream & operator>>(istream & f, KN<R> & v); + +template<class R> +class SetArray { public: + R o,step; + long n; + explicit SetArray(long nn,R oo=R(),R sstep=R(1)): o(oo),n(nn),step(sstep) {} + template<class K> SetArray(SetArray<K> sa): o(sa.o),n(sa.n),step(sa.step) {} + + R operator[](long i) const { return i <= n ? o + R(i)*step : R();} + long size() const {return n;} +}; + +// add for gmm++ march 2010 .... + template<typename T> struct KN__iterator { + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef KN__iterator<T> iterator; + private: + T* v; + long step; + public: + reference operator *() const { return *v; } + pointer operator->() const { return &(operator*()); } + + iterator &operator ++() { v += step; return *this; } + iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; } + iterator &operator --() { v -= step; return *this; } + iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; } + + bool operator ==(const iterator &i) const { return v == i.v; } + bool operator !=(const iterator &i) const { return !(v == i.v); } + + KN__iterator(T *vv,int s) : v(vv),step(s) {K_throwassert(v);} + friend class KN__const_iterator<T>; + }; + +template<typename T> struct KN__const_iterator { + typedef T value_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + typedef KN__const_iterator<T> iterator; + +private: + const T* v; + long step; +public: + + reference operator *() const { return *v; } + pointer operator->() const { return &(operator*()); } + + iterator &operator ++() { v += step; return *this; } + iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; } + iterator &operator --() { v -= step; return *this; } + iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; } + + bool operator ==(const iterator &i) const { return v == i.v; } + bool operator !=(const iterator &i) const { return !(v == i.v); } + + KN__const_iterator(const T *vv,int s) : v(vv),step(s) {K_throwassert(v);} + KN__const_iterator(const KN__const_iterator<T> & i) : v(i.v),step(i.step){} + +}; + + +template<class R> +class KN_: public ShapeOfArray { +protected: + R *v; +public: + typedef R K; // type of data + typedef KN__iterator<R> iterator; + typedef KN__const_iterator<R> const_iterator; + iterator end(){ return iterator(v+n*step,step);} + iterator begin(){ return iterator(v,step);} + const_iterator end() const { return const_iterator(v+n*step,step);} + const_iterator begin() const { return const_iterator(v,step);} + void clear() { *this=R();} + long N() const {return n;} + bool unset() const { return !v;} + void set(R * vv,int nn,int st=1,int nx=-1) {v=vv;n=nn;step=st;next=nx;} + long size() const{return step?n*step:n;} + operator R *() const {return v;} + KN_(const KN_<R> & u) :ShapeOfArray(u),v(u.v){} + KN_(const KN_<R> & U,const SubArray & sa) : ShapeOfArray(U,sa),v(U.v + U.index(sa.start)) {} + + KN_ operator()(const SubArray & sa) const { return KN_(*this,sa);} // sub array + + R & operator[](long i) const {return v[index(i)];} + R & operator()(long i) const {return v[index(i)];} + R & operator[](int i) const {return v[index(i)];} + R & operator()(int i) const {return v[index(i)];} + + R operator,(const KN_<const_R> & v) const; // dot product + + KN_& operator =(const SetArray<R> & u) ; + KN_& operator +=(const SetArray<R> & u) ; + KN_& operator -=(const SetArray<R> & u) ; + KN_& operator *=(const SetArray<R> & u) ; + KN_& operator /=(const SetArray<R> & u) ; + + KN_& operator =(const KN_<const_R> & u) ; + KN_& operator +=(const KN_<const_R> & u) ; + KN_& operator -=(const KN_<const_R> & u) ; + + KN_& operator *=(const KN_<const_R> & u) ; + KN_& operator /=(const KN_<const_R> & u) ; + + + KN_& operator = (const_R a) ; + KN_& operator +=(const_R a) ; + KN_& operator -=(const_R a) ; + KN_& operator /=(const_R a) ; + KN_& operator *=(const_R a) ; + + KN_& operator = (R* a) { return operator =(KN_<R>(a,n));} + KN_& operator += (R* a) { return operator+=(KN_<R>(a,n));} + KN_& operator -= (R* a) { return operator-=(KN_<R>(a,n));} + KN_& operator *= (R* a) { return operator*=(KN_<R>(a,n));} + KN_& operator /= (R* a) { return operator/=(KN_<R>(a,n));} + + + + R min() const ; + R max() const ; + R sum() const ; + double norm() const ; + double l2() const ; + double l1() const ; + double linfty() const ; + double lp(double p) const ; + + template<class T> long last(const T &) const; + template<class T> long first(const T &) const; + + void map(R (*f)(R )); // apply the f fonction a all element of the array + void map(R (*f)(const R& )); // apply the f fonction a all element of the array + + template<class T> + void set(R (*f)(const T& ),KN_<T> & u); // apply the f fonction a all element of the array u + + KN_& operator =(const DotStar_KN_<R> & u) ; + KN_& operator+=(const DotStar_KN_<R> & u) ; + KN_& operator-=(const DotStar_KN_<R> & u) ; + KN_& operator*=(const DotStar_KN_<R> & u) ; + KN_& operator/=(const DotStar_KN_<R> & u) ; + + KN_& operator =(const DotSlash_KN_<R> & u) ; + KN_& operator+=(const DotSlash_KN_<R> & u) ; + KN_& operator-=(const DotSlash_KN_<R> & u) ; + KN_& operator*=(const DotSlash_KN_<R> & u) ; + KN_& operator/=(const DotSlash_KN_<R> & u) ; + + KN_& operator =(const if_KN_<R> & u) ; + KN_& operator+=(const if_KN_<R> & u) ; + KN_& operator-=(const if_KN_<R> & u) ; + KN_& operator*=(const if_KN_<R> & u) ; + KN_& operator/=(const if_KN_<R> & u) ; + + KN_& operator =(const ifnot_KN_<R> & u) ; + KN_& operator+=(const ifnot_KN_<R> & u) ; + KN_& operator-=(const ifnot_KN_<R> & u) ; + KN_& operator*=(const ifnot_KN_<R> & u) ; + KN_& operator/=(const ifnot_KN_<R> & u) ; + + KN_& operator =(const Add_KN_<R> & u) ; + KN_& operator+=(const Add_KN_<R> & u) ; + KN_& operator-=(const Add_KN_<R> & u) ; + KN_& operator*=(const Add_KN_<R> & u) ; + KN_& operator/=(const Add_KN_<R> & u) ; + + template<class I,class T> KN_& operator = (const KN_ITAB<T,I> & u); + template<class I,class T> KN_& operator += (const KN_ITAB<T,I> & u); + template<class I,class T> KN_& operator -= (const KN_ITAB<T,I> & u); + template<class I,class T> KN_& operator *= (const KN_ITAB<T,I> & u); + template<class I,class T> KN_& operator /= (const KN_ITAB<T,I> & u); + + + KN_ITAB< KN_<R>,const KN_<int> > operator()(const KN_<int> &itab) ; + KN_ITAB< KN_<R>,const KN_<long> > operator()(const KN_<long> &itab) ; + KN_ITAB<const KN_<R>,const KN_<int> > operator()(const KN_<int> &itab) const ; + KN_ITAB<const KN_<R>,const KN_<long> > operator()(const KN_<long> &itab) const ; + + + + + + KN_& operator =(const Sub_KN_<R> & u) ; + KN_& operator-=(const Sub_KN_<R> & u) ; + KN_& operator+=(const Sub_KN_<R> & u) ; + KN_& operator*=(const Sub_KN_<R> & u) ; + KN_& operator/=(const Sub_KN_<R> & u) ; + + KN_& operator =(const Mulc_KN_<R> & u) ; + KN_& operator+=(const Mulc_KN_<R> & u) ; + KN_& operator-=(const Mulc_KN_<R> & u) ; + KN_& operator*=(const Mulc_KN_<R> & u) ; + KN_& operator/=(const Mulc_KN_<R> & u) ; + + KN_& operator =(const Add_Mulc_KN_<R> & u) ; + KN_& operator+=(const Add_Mulc_KN_<R> & u) ; + KN_& operator-=(const Add_Mulc_KN_<R> & u) ; + KN_& operator*=(const Add_Mulc_KN_<R> & u) ; + KN_& operator/=(const Add_Mulc_KN_<R> & u) ; + + KN_& operator =(const if_arth_KN_<R> & u) ; + KN_& operator+=(const if_arth_KN_<R> & u) ; + KN_& operator-=(const if_arth_KN_<R> & u) ; + KN_& operator*=(const if_arth_KN_<R> & u) ; + KN_& operator/=(const if_arth_KN_<R> & u) ; + + + KN_& operator =(const Mul_KNM_KN_<R> & u) ; + KN_& operator+=(const Mul_KNM_KN_<R> & u) ; + KN_& operator-=(const Mul_KNM_KN_<R> & u) ; + KN_& operator*=(const Mul_KNM_KN_<R> & u) ; + KN_& operator/=(const Mul_KNM_KN_<R> & u) ; + + // KN_& operator =(const MatriceCreuseMulKN_<R> & ) ; + // KN_& operator +=(const MatriceCreuseMulKN_<R> & ) ; + KN_& operator =(const typename VirtualMatrice<R>::plusAx & Ax) + {*this=R(); Ax.A->addMatMul(Ax.x,*this);return *this;} + KN_& operator =(const typename VirtualMatrice<R>::plusAtx & Ax) + {*this=R(); Ax.A->addMatTransMul(Ax.x,*this);return *this;} + KN_& operator +=(const typename VirtualMatrice<R>::plusAx & Ax) + { Ax.A->addMatMul(Ax.x,*this);return *this;} + KN_& operator +=(const typename VirtualMatrice<R>::plusAtx & Ax) + { Ax.A->addMatTransMul(Ax.x,*this);return *this;} + KN_& operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab) + {*this=R(); Ab.A->Solve(*this,Ab.b);return *this;} + + template<class A,class B,class C> KN_& operator = (const F_KN_<A,B,C> & u) ; + template<class A,class B,class C> KN_& operator += (const F_KN_<A,B,C> & u) ; + template<class A,class B,class C> KN_& operator -= (const F_KN_<A,B,C> & u) ; + template<class A,class B,class C> KN_& operator /= (const F_KN_<A,B,C> & u) ; + template<class A,class B,class C> KN_& operator *= (const F_KN_<A,B,C> & u) ; + + +// KN_& operator =(const MatriceCreuseDivKN_<R> &) ; + + friend ostream & operator<< <R>(ostream & f,const KN_<const_R> & v) ; + + KN_(R *u,const ShapeOfArray & s):ShapeOfArray(s),v(u){} + KN_(R *u,long nn,long s):ShapeOfArray(nn,s),v(u){} + KN_(R *u,long nn,long s,long nextt):ShapeOfArray(nn,s,nextt),v(u){} + KN_(R *u,long nn):ShapeOfArray(nn),v(u){} + + + TKN_<R> t() ; // transpose + const TKN_<R> t() const ; // transpose + notKN_<R> operator!() ; // not + const notKN_<R> operator!() const ; // not + + // operator KN<R> &(); + // operator const KN<R> &() const; + + private: + + KN_& operator++(){K_throwassert(next>=0);v += next;return *this;} // ++U + KN_& operator--(){K_throwassert(next>=0);v -= next;return *this;} // --U + KN_ operator++(int ){K_throwassert(next>=0); KN_ old=*this;v = v +next;return old;} // U++ + KN_ operator--(int ){K_throwassert(next>=0); KN_ old=*this;v = v -next;return old;} // U++ + + KN_(const KN_<R> & u,long offset) :ShapeOfArray(u),v(&u[offset]){} + KN_(const KN_<R> & u,const ShapeOfArray &sh,long startv=0) + :ShapeOfArray(sh*u.step),v(&u[startv]){} + KN_(const KN_<R> & u,long nnext,const ShapeOfArray &sh,long startv=0) + :ShapeOfArray(sh.n,sh.step*u.step,nnext),v(&u[startv]){ } + // Add for gmm++ compatibityly ................... + // iterator end() {return iterator(v,step) + + +// friend class KN_<R>; + friend class KNM_<R>; + friend class KNMK_<R>; + friend class KN<R>; + friend class KNM<R>; + friend class KNMK<R>; + +}; + +template<class R> +class KNM_: public KN_<R> { + public: + ShapeOfArray shapei; + ShapeOfArray shapej; + public: + long IsVector1() const { return (shapei.n*shapej.n) == this->n ;} + long N() const {return shapei.n;} + long M() const {return shapej.n;} + long size() const { return shapei.n*shapej.n;} + + KNM_(R* u,const ShapeOfArray & s, + const ShapeOfArray & si, + const ShapeOfArray & sj) + : KN_<R>(u,s),shapei(si),shapej(sj){} + KNM_(R* u,long n,long m) + : KN_<R>(u,ShapeOfArray(n*m)),shapei(n,1,n),shapej(m,n,1){} + KNM_(R* u,long n,long m,long s) + : KN_<R>(u,ShapeOfArray(n*m,s)),shapei(n,1,n),shapej(m,n,1){} + KNM_(KN_<R> u,long n,long m) + : KN_<R>(u,ShapeOfArray(m*n)),shapei(n,1,n),shapej(m,n,1){ } + + KNM_(const KN_<R> &u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset=0) + : KN_<R>(&u[offset],si.last()+sj.last()+1,u.step),shapei(si),shapej(sj) + {K_throwassert( offset>=0 && this->n+ (this->v-(R*)u) <= u.n);} + KNM_(const KN_<R> &u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset,long nnext) + : KN_<R>(&u[offset],si.last()+sj.last()+1,u.step,nnext),shapei(si),shapej(sj) + {K_throwassert( offset>=0 && this->n+ (this->v-(R*)u) <= u.n);} + + KNM_(KNM_<R> U,const SubArray & si,const SubArray & sj) + :KN_<R>(U,SubArray(U.ij(si.len1(),sj.len1())+1,U.ij(si.start,sj.start))), + shapei(U.shapei,si),shapej(U.shapej,sj){} + + KNM_(KNM_<R> U,const SubArray & sa,const SubArray & si,const SubArray & sj) + :KN_<R>(U,SubArray(sa)),shapei(U.shapei,si),shapej(U.shapej,sj){} + + KNM_(const KNM_<R> & u) + :KN_<R>(u),shapei(u.shapei),shapej(u.shapej) {} + + KNM_ operator()(const SubArray & sa,const SubArray & sb) const + { return KNM_(*this,sa,sb);} // sub array + + long ij(long i,long j) const + { return shapei.index(i)+shapej.index(j);} + long indexij(long i,long j) const + { return this->index(shapei.index(i)+shapej.index(j));} + R & operator()(long i,long j) const + { return this->v[indexij(i,j)];} + R & operator()(int i,int j) const + { return this->v[indexij(i,j)];} + + + KN_<R> operator()(const char,long j ) const // une colonne j ('.',j) + { return KN_<R>(&this->v[this->index(shapej.index(j))],shapei*this->step);} + KN_<R> operator()(long i ,const char) const // une ligne i (i,'.') + { return KN_<R>(&this->v[this->index(shapei.index(i))],shapej*this->step);} + KN_<R> operator()(const char,int j ) const // une colonne j ('.',j) + { return KN_<R>(&this->v[this->index(shapej.index(j))],shapei*this->step);} + KN_<R> operator()(int i ,const char) const // une ligne i (i,'.') + { return KN_<R>(&this->v[this->index(shapei.index(i))],shapej*this->step);} + KN_<R> operator()(const char,const char) const // tous + { return *this;} + KNM_<R> t() const + { return KNM_<R>(this->v,*this,shapej,shapei);} // before { return KNM_<R>(*this,shapej,shapei,v);} + + KNM_& operator =(const KNM_<const_R> & u) ; + KNM_& operator =(const_R a) ; + KNM_& operator+=(const_R a) ; + KNM_& operator-=(const_R a) ; + KNM_& operator/=(const_R a) ; + KNM_& operator*=(const_R a) ; + KNM_& operator+=(const KNM_<const_R> & u) ; + KNM_& operator-=(const KNM_<const_R> & u) ; + KNM_& operator*=(const KNM_<const_R> & u) ; + KNM_& operator/=(const KNM_<const_R> & u) ; + + KNM_ &operator =(const outProduct_KN_<R> &); + KNM_ &operator +=(const outProduct_KN_<R> &); + KNM_ &operator -=(const outProduct_KN_<R> &); + KNM_ &operator /=(const outProduct_KN_<R> &); // bofbof + KNM_ &operator *=(const outProduct_KN_<R> &); // bofbof + +private: + KNM_& operator++() {this->v += this->next;return *this;} // ++U + KNM_& operator--() {this->v -= this->next;return *this;} // ++U + KNM_ operator++(int ){KNM_<R> old=*this;this->v = this->v +this->next;return old;} // U++ + KNM_ operator--(int ){KNM_<R> old=*this;this->v = this->v -this->next;return old;} // U-- + + + friend class KN_<R>; +// friend class KNM_<R>; + friend class KNMK_<R>; + friend class KN<R>; + friend class KNM<R>; + friend class KNMK<R>; +}; + +template<class T,class I> +struct KN_ITAB +{ + KN_ITAB(const T &vv,const I &iindex) : v(vv),index(iindex) {} + T v; + I index; + KN_ITAB & operator=(const T & t); + KN_ITAB & operator+=(const T & t); + KN_ITAB & operator-=(const T & t); + KN_ITAB & operator*=(const T & t); + KN_ITAB & operator/=(const T & t); + typename T::R & operator[](long i){ return v[index[i]];} + const typename T::R & operator[](long i) const { return v[index[i]];} + long N() const { return index.N();} +}; + +template<class R> KN_ITAB<const KN_<R>,const KN_<int> > KN_<R>::operator()(const KN_<int> &itab) const { return KN_ITAB<const KN_<R>,const KN_<int> > (*this,itab);} +template<class R> KN_ITAB<const KN_<R>,const KN_<long> > KN_<R>::operator()(const KN_<long> &itab) const { return KN_ITAB<const KN_<R>,const KN_<long> > (*this,itab);} +template<class R> KN_ITAB< KN_<R>,const KN_<int> > KN_<R>::operator()(const KN_<int> &itab) { return KN_ITAB<KN_<R>,const KN_<int> > (*this,itab);} +template<class R> KN_ITAB< KN_<R>,const KN_<long> > KN_<R>::operator()(const KN_<long> &itab) { return KN_ITAB<KN_<R>,const KN_<long> > (*this,itab);} + + +template<class R> +struct TKN_:public KN_<R> { + TKN_(const KN_<R> &x) : KN_<R>(x) {} +}; + +template<class R> +struct notKN_:public KN_<R> { + notKN_(const KN_<R> &x) : KN_<R>(x) {} + notnotKN_<R> operator!() ; // not + const notnotKN_<R> operator!() const ; // not +}; + +template<class R> +struct notnotKN_:public KN_<R> { + notnotKN_(const notKN_<R> &x) : KN_<R>(x) {} + notKN_<R> operator!() ; // notnot + const notKN_<R> operator!() const ; // notnot +}; + +template<class R> +TKN_<R> KN_<R>::t() { return *this;} // transpose + +template<class R> +const TKN_<R> KN_<R>::t() const { return *this;} // transpose + +template<class R> +notKN_<R> KN_<R>::operator!() { return *this;} // not + +template<class R> +const notKN_<R> KN_<R>::operator!() const { return *this;} // not + +template<class R> +notnotKN_<R> notKN_<R>::operator!() { return *this;} // not + +template<class R> +const notnotKN_<R> notKN_<R>::operator!() const { return *this;} // not + + +template<class R> +struct outProduct_KN_ { + const KN_<R> a,b; + R c; + long N() const {return a.N(); } + long M() const {return b.N(); } + outProduct_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=(R)1) : a(aa),b(bb),c(cc) {} + outProduct_KN_(const KN_<R> * aa, const KN_<R> &bb,R cc=(R)1) : a(*aa),b(bb),c(cc) {} + outProduct_KN_(const KN_<R> * aa, const KN_<R> *bb,R cc=(R)1) : a(*aa),b(*bb),c(cc) {} + outProduct_KN_(const Mulc_KN_<R> & aa,const KN_<R> & bb) : a(aa.a),b(bb),c(aa.b) {} + outProduct_KN_ operator * (R cc) { return outProduct_KN_(a,b,c*cc);} +}; + +template<class R> +struct if_KN_ { + const KN_<R> & a,&b; + R c; + if_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=1.) : a(aa),b(bb),c(cc) {} + if_KN_ operator * (R cc) { return if_KN_(a,b,c*cc);} +}; + +template<class R> +struct ifnot_KN_ { + const KN_<R> & a,&b; + R c; + ifnot_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=1.) : a(aa),b(bb),c(cc) {} + ifnot_KN_ operator * (R cc) { return ifnot_KN_(a,b,c*cc);} +}; + + +template<class R> +outProduct_KN_<R> operator*(const KN_<R> &a,const TKN_<R> &b) +{ return outProduct_KN_<R>(a,b);} + +template<class R> +ifnot_KN_<R> operator*(const KN_<R> &a,const notKN_<R> &b) +{ return ifnot_KN_<R>(b,a);} + +template<class R> +ifnot_KN_<R> operator*(const KN_<R> &a,const notnotKN_<R> &b) +{ return if_KN_<R>(b,a);} + +template<class R> +ifnot_KN_<R> operator*(const notKN_<R> &b,const KN_<R> &a) +{ return ifnot_KN_<R>(b,a);} + +template<class R> +ifnot_KN_<R> operator*(const notnotKN_<R> &b,const KN_<R> & a) +{ return if_KN_<R>(b,a);} + + +template<class R> +R operator*(const TKN_<R> &a,const KN_<R> &b) +{ return (a,b);} + +template<class R> +class KNMK_: public KN_<R> { + friend class KNMK<R>; + public: + ShapeOfArray shapei; + ShapeOfArray shapej; + ShapeOfArray shapek; + public: + long IsVector1() const { return (shapei.n*shapej.n*shapek.n) == this->n ;} + long N() const {return shapei.n;} + long M() const {return shapej.n;} + long K() const {return shapek.n;} + long size() const { return shapei.n*shapej.n*shapek.n;} + KNMK_(const ShapeOfArray & s, + const ShapeOfArray & si, + const ShapeOfArray & sj, + const ShapeOfArray & sk, + R * u) + : KN_<R>(u,s),shapei(si),shapej(sj),shapek(sk){} + + KNMK_(R* u,long n,long m,long k) + : KN_<R>(u, ShapeOfArray(n*m*k)),shapei(n,1,n),shapej(m,n,1),shapek(k,n*m,n*m){}; + +// KNMK_(const KN_<R> & u,long n,long m,long k) +// : KN_<R>(ShapeOfArray(n*m*k)),shapei(n,1,n),shapekj(m,n,1),u), +// shapek(k,n*m,n*m){}; + + KNMK_(const KNMK_<R> &U,const SubArray & si,const SubArray & sj,const SubArray & sk) : + KN_<R>(U,SubArray(U.ijk(si.len1(),sj.len1(),sk.len1())+1, + U.ijk(si.start,sj.start,sk.start))), + shapei(U.shapei,si), + shapej(U.shapej,sj), + shapek(U.shapek,sk){} + + KNMK_(const KNMK_<R> & u) :KN_<R>(u),shapei(u.shapei),shapej(u.shapej),shapek(u.shapek) {} + + + long ijk(long i,long j,long k) const + { return shapei.index(i)+shapej.index(j)+shapek.index(k);} + long indexijk(long i,long j,long k) const + {return this->index(shapei.index(i)+shapej.index(j)+shapek.index(k));} + + R & operator()(long i,long j,long k) const {return this->v[indexijk(i,j,k)];} + R & operator()(int i,int j,int k) const {return this->v[indexijk(i,j,k)];} + +// pas de tableau suivant + KN_<R> operator()(const char ,long j,long k) const { // le tableau (.,j,k) + return KN_<R>(*this,-1,shapei,shapej[j]+shapek[k]);} + KN_<R> operator()(long i,const char ,long k) const { // le tableau (i,.,k) + return KN_<R>(*this,-1,shapej,shapei[i]+shapek[k]);} + KN_<R> operator()(long i,long j,const char ) const { // le tableau (i,j,.) + return KN_<R>(*this,-1,shapek,shapei[i]+shapej[j]);} + + KN_<R> operator()(const char ,int j,int k) const { // le tableau (.,j,k) + return KN_<R>(*this,-1,shapei,shapej[j]+shapek[k]);} + KN_<R> operator()(int i,const char ,int k) const { // le tableau (i,.,k) + return KN_<R>(*this,-1,shapej,shapei[i]+shapek[k]);} + KN_<R> operator()(int i,int j,const char ) const { // le tableau (i,j,.) + return KN_<R>(*this,-1,shapek,shapei[i]+shapej[j]);} +// + KNM_<R> operator()(const char ,const char ,long k) const { // le tableau (.,.,k) + return KNM_<R>(*this,shapei,shapej,shapek[k],shapek.next);} // step = n*m + //attention les suivants ne marche pas + KNM_<R> operator()(const char ,long j,const char ) const { // le tableau (.,j,.) + return KNM_<R>(*this,shapei,shapek,shapej[j],-1/*shapej.next*/);} // step = n + + KNM_<R> operator()(long i,const char ,const char ) const { // le tableau (i,.,.) + return KNM_<R>(*this,shapej,shapek,shapei[i],-1/*shapei.next*/);} // step = 1 + + KNM_<R> operator()(const char ,const char ,int k) const { // le tableau (.,.,k) + return KNM_<R>(*this,shapei,shapej,shapek[k],shapek.next);} // step = n*m + //attention les suivants ne marche pas + KNM_<R> operator()(const char ,int j,const char ) const { // le tableau (.,j,.) + return KNM_<R>(*this,shapei,shapek,shapej[j],-1/*shapej.next*/);} // step = n + + KNM_<R> operator()(int i,const char ,const char ) const { // le tableau (i,.,.) + return KNM_<R>(*this,shapej,shapek,shapei[i],-1/*shapei.next*/);} // step = 1 + + KNMK_& operator =(const KNMK_<const_R> & u) ; + KNMK_& operator+=(const KNMK_<const_R> & u) ; + KNMK_& operator-=(const KNMK_<const_R> & u) ; + KNMK_& operator/=(const KNMK_<const_R> & u) ; + KNMK_& operator*=(const KNMK_<const_R> & u) ; + KNMK_& operator =(const_R a) ; + KNMK_& operator+=(const_R a) ; + KNMK_& operator-=(const_R a) ; + KNMK_& operator/=(const_R a) ; + KNMK_& operator*=(const_R a) ; + + KNMK_ operator()(SubArray si,SubArray sj,SubArray sk) const + {return KNMK_(*this,si,sj,sk);} + + private: +// KNMK_& operator++(){v += next;return *this;} // ++U +// KNMK_& operator--(){v -= next;return *this;} // --U +// KNMK_ operator++(long ){KNMK_ old=*this;v = v +next;return old;} // U++ +// KNMK_ operator--(long ){KNMK_ old=*this;v = v -next;return old;} // U-- + + +friend class KNM_<R>; +friend class KN_<R>; + +}; + + + +template<class R> +class KN :public KN_<R> { public: + + typedef R K; + + // explicit KN(const R & u):KN_<R>(new R(uu),1,0) {} + KN() : KN_<R>(0,0) {} + KN(long nn) : KN_<R>(new R[nn],nn) {} + KN(long nn, R * p) : KN_<R>(new R[nn],nn) + { KN_<R>::operator=(KN_<R>(p,nn));} + KN(long nn,R (*f)(long i) ) : KN_<R>(new R[nn],nn) + {for(long i=0;i<this->n;i++) this->v[i]=f(i);} + KN(long nn,const R & a) : KN_<R>(new R[nn],nn) + { KN_<R>::operator=(a);} + KN(long nn,long s,const R a) : KN_<R>(new R[nn],nn,s) + { KN_<R>::operator=(a);} + template<class S> KN(const KN_<S> & s):KN_<R>(new R[s.n],s.n) + {for (long i=0;i<this->n;i++) this->v[i] = s[i];} + template<class S> KN(const KN_<S> & s,R (*f)(S )):KN_<R>(new R[s.n],s.n) + {for (long i=0;i<this->n;i++) this->v[i] = f(s[i]);} + KN(const KN<R> & u):KN_<R>(new R[u.n],u.n) + { KN_<R>::operator=(u);} + KN(bool ,KN<R> & u):KN_<R>(u) {u.v=0;u.n=0;}// remove copy for return of local KN. + + // explicit KN(const KN_<R> & u):KN_<R>(new R[u.n],u.n) + // { KN_<R>::operator=(u);} + + ~KN(){delete [] this->v;} + + void CheckSet() { if(!(this->n)) {cerr << "Error RNM set array\n";K_throwassert(0); exit(1);}} + KN& operator = (R* a) { CheckSet(); return operator =(KN_<R>(a,this->n));} + KN& operator += (R* a) { CheckSet(); return operator+=(KN_<R>(a,this->n));} + KN& operator -= (R* a) { CheckSet(); return operator-=(KN_<R>(a,this->n));} + KN& operator *= (R* a) { CheckSet(); return operator*=(KN_<R>(a,this->n));} + KN& operator /= (R* a) { CheckSet(); return operator/=(KN_<R>(a,this->n));} + + KN& operator =(const SetArray<R> & u) + { if(this->unset()) + this->set(new R[u.size()],u.size(),0,0); + KN_<R>::operator= (u); + return *this;} + KN& operator +=(const SetArray<R> & u) + { if(this->unset()) + this->set(new R[u.size()],u.size(),0,0); + KN_<R>::operator+= (u); + return *this;} + KN& operator -=(const SetArray<R> & u) + { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator-= (u);return *this;} + KN& operator *=(const SetArray<R> & u) + { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator*= (u);return *this;} + KN& operator /=(const SetArray<R> & u) + { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator/= (u);return *this;} + + KN& operator =(const_R a) + { if(this->unset()) this->set(new R[1],1,0,0); KN_<R>::operator= (a);return *this;} + KN& operator =(const KN_<R>& a) + { if(this->unset()) this->set(new R[a.N()],a.N()); KN_<R>::operator= (a);return *this;} + KN& operator =(const KN<R>& a) + { if(this->unset()) this->set(new R[a.N()],a.N()); KN_<R>::operator= (a);return *this;} + KN& operator =(const Add_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const DotStar_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const if_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const ifnot_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const DotSlash_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const Sub_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const Mulc_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const Add_Mulc_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + KN& operator =(const if_arth_KN_<R> & u) + { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;} + + + KN& operator =(const Mul_KNM_KN_<R> & u) + { if(this->unset()) this->set(new R[u.b.N()],u.b.N());KN_<R>::operator=(u);return *this;} +// KN& operator =(const MatriceCreuseMulKN_<R> & Ax) +// {if(this->unset()) this->set(new R[Ax.v.N()],Ax.v.N()); KN_<R>::operator=(Ax);return *this;} +// KN& operator +=(const MatriceCreuseMulKN_<R> & Ax) +// {if(this->unset()) this->set(new R[Ax.v.N()],Ax.v.N()); KN_<R>::operator+=(Ax);return *this;} +// KN& operator =(const MatriceCreuseDivKN_<R> & A1x) +// { if(this->unset()) this->set(new R[A1x.v.N()],A1x.v.N());KN_<R>::operator=(A1x);return *this;} + // correcton aout 2007 FH add N,M flied in VirtualMatrice + KN& operator =(const typename VirtualMatrice<R>::plusAx & Ax) + { if(this->unset() && Ax.A->N ) this->set(new R[Ax.A->N],Ax.A->N);KN_<R>::operator=(Ax);return *this;} + KN& operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab) + { if(this->unset()) this->set(new R[Ab.b.N()],Ab.b.N());KN_<R>::operator=(Ab);return *this;} + KN& operator +=(const typename VirtualMatrice<R>::plusAx & Ax) + { if(this->unset() && Ax.A->N) { + this->set(new R[Ax.A->N],Ax.A->N); + KN_<R>::operator=(R());} + KN_<R>::operator+=(Ax); + return *this;} + KN& operator =(const typename VirtualMatrice<R>::plusAtx & Ax) + { if(this->unset()&&Ax.A->M) this->set(new R[Ax.A->M],Ax.A->M);KN_<R>::operator=(Ax);return *this;} + KN& operator +=(const typename VirtualMatrice<R>::plusAtx & Ax) + { if(this->unset()&&Ax.A->M) { + this->set(new R[Ax.A->M],Ax.A->M); + KN_<R>::operator=(R());} + KN_<R>::operator+=(Ax); + return *this;} +// end correcton FH + template<class P,class Q> + KN& operator =(const PplusQ<P,Q> & PQ) + { *this=PQ.p; *this+=PQ.q;return *this; } + template<class P,class Q> + KN& operator +=(const PplusQ<P,Q> & PQ) + { *this+=PQ.p; *this+=PQ.q;return *this; } + + KN& operator -=(const_R a) + { KN_<R>::operator-=(a);return *this;} + KN& operator -=(const KN_<R>& a) + { KN_<R>::operator-= (a);return *this;} + KN& operator -=(const Add_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + KN& operator -=(const DotStar_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + KN& operator -=(const DotSlash_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + KN& operator -=(const Sub_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + KN& operator -=(const Mulc_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + KN& operator -=(const Add_Mulc_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + KN& operator -=(const if_arth_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + KN& operator -=(const Mul_KNM_KN_<R> & u) + { KN_<R>::operator-=(u);return *this;} + + KN& operator +=(const_R a) + { KN_<R>::operator += (a);return *this;} + KN& operator += (const KN_<R>& a) + { KN_<R>::operator+= (a);return *this;} + KN& operator +=(const Add_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + KN& operator +=(const DotStar_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + KN& operator +=(const DotSlash_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + KN& operator +=(const Sub_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + KN& operator +=(const Mulc_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + KN& operator +=(const Add_Mulc_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + KN& operator +=(const if_arth_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + KN& operator +=(const Mul_KNM_KN_<R> & u) + { KN_<R>::operator+=(u);return *this;} + + + KN& operator/=(const_R a) + { KN_<R>::operator/=(a);return *this;} + KN& operator /= (const KN_<R>& a) + { KN_<R>::operator/= (a);return *this;} + KN& operator /=(const Add_KN_<R> & u) + { KN_<R>::operator/=(u);return *this;} + KN& operator /=(const Sub_KN_<R> & u) + { KN_<R>::operator/=(u);return *this;} + KN& operator /=(const Mulc_KN_<R> & u) + { KN_<R>::operator/=(u);return *this;} + KN& operator /=(const Add_Mulc_KN_<R> & u) + { KN_<R>::operator/=(u);return *this;} + KN& operator /=(const if_arth_KN_<R> & u) + { KN_<R>::operator/=(u);return *this;} + + KN& operator /=(const Mul_KNM_KN_<R> & u) + { KN_<R>::operator/=(u);return *this;} + + KN& operator*=(const_R a) + { KN_<R>::operator*=(a);return *this;} + KN& operator*=(const KN_<const_R>& a) + { KN_<R>::operator*= (a);return *this;} + KN& operator *=(const Add_KN_<R> & u) + { KN_<R>::operator*=(u);return *this;} + KN& operator *=(const Sub_KN_<R> & u) + { KN_<R>::operator*=(u);return *this;} + KN& operator *=(const Mulc_KN_<R> & u) + { KN_<R>::operator*=(u);return *this;} + KN& operator *=(const Add_Mulc_KN_<R> & u) + { KN_<R>::operator*=(u);return *this;} + KN& operator *=(const if_arth_KN_<R> & u) + { KN_<R>::operator*=(u);return *this;} + KN& operator *=(const Mul_KNM_KN_<R> & u) + { KN_<R>::operator*=(u);return *this;} + + + template<class I,class T> KN& operator = (const KN_ITAB<T ,I> & ui) + { KN_<R>::operator =(ui); return *this;} + template<class I,class T> KN& operator += (const KN_ITAB<T ,I> & ui) + { KN_<R>::operator +=(ui); return *this;} + template<class I,class T> KN& operator -= (const KN_ITAB<T ,I> & ui) + { KN_<R>::operator -=(ui); return *this;} + template<class I,class T> KN& operator *= (const KN_ITAB<T ,I> & ui) + { KN_<R>::operator *=(ui); return *this;} + template<class I,class T> KN& operator /= (const KN_ITAB<T ,I> & ui) + { KN_<R>::operator /=(ui); return *this;} + + + // two opertor to cast to an array of constant +// operator KN_<const_R> & () +// { return * (KN_<const_R>*) this;} +// operator KN_<const_R> const & () const +// { return *(const KN_<const_R>*) this;} +// operator KN<const_R> & () +// { return (KN<const_R> &) *this;} +// operator KN<const_R> const & () const +// { return (const KN<const_R>& ) *this;} + void init(long nn) {this->n=nn;this->step=1;this->next=-1;this->v=new R[nn];} + void init() {this->n=0;this->step=1;this->next=-1;this->v=0;} + void init(const KN_<R> & a){init(a.N()); operator=(a);} + void resize(long nn) { + if ( nn != this->n) + { + R *vo=this->v; + long no=std::min(this->n,nn), so=this->step; + ShapeOfArray::init(nn); + this->v=new R[this->n]; + // copy + if(this->v && vo) + for(long i=0,j=0;j<no;i++,j+=so) + this->v[i]=vo[j]; + delete [] vo;} }// mars 2010 + void destroy(){assert(this->next<0); if(this->next++ ==-1) {delete [] this->v; this->v=0;this->n=0;}}// mars 2010 + void increment() {assert(this->next<0); this->next--;} +}; + +// Array with 2 indices +// --------------------- + +template<class R> +class KNM: public KNM_<R>{ public: + + KNM(long nn,long mm) + :KNM_<R>(new R[nn*mm],nn,mm){} + KNM(const KNM<R> & u) // PB si stepi ou stepj nulle + :KNM_<R>(new R[u.size()],u.N(),u.M()) + { KN_<R>::operator=(u);} + explicit KNM(const KNM_<R> & u) + :KNM_<R>(new R[u.size()],u.N(),u.M()) + { KNM_<R>::operator=(u);} + + ~KNM(){delete [] this->v;} + + KNM& operator=(const KNM_<const_R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator=(u);return *this;} + KNM& operator=(const_R a) + { if(this->unset()) RNM_FATAL_ERROR(" KNM operator=(double)"); KNM_<R>::operator=(a);return *this;} + KNM& operator+=(const_R a) + { if(this->unset()) RNM_FATAL_ERROR(" KNM operator+=(double)"); KNM_<R>::operator+=(a);return *this;} + KNM& operator-=(const_R a) + {if(this->unset()) RNM_FATAL_ERROR(" KNM operator-=(double)"); KNM_<R>::operator-=(a);return *this;} + KNM& operator/=(const_R a) + {if(this->unset()) RNM_FATAL_ERROR(" KNM operator/=(double)"); KNM_<R>::operator/=(a);return *this;} + KNM& operator*=(const_R a) + {if(this->unset()) RNM_FATAL_ERROR(" KNM operator*=(double)"); KNM_<R>::operator*=(a);return *this;} + KNM& operator+=(const KNM_<const_R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator+=(u);return *this;} + KNM& operator-=(const KNM_<const_R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator-=(u);return *this;} + + KNM& operator/=(const KNM_<const_R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator/=(u);return *this;} + KNM& operator*=(const KNM_<const_R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator*=(u);return *this;} + + + KNM &operator =(const outProduct_KN_<R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator =(u);return *this;} + KNM &operator +=(const outProduct_KN_<R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator+=(u);return *this;} + KNM &operator -=(const outProduct_KN_<R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator-=(u);return *this;} + KNM &operator /=(const outProduct_KN_<R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator/=(u);return *this;} + KNM &operator *=(const outProduct_KN_<R> & u) + { if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator*=(u);return *this;} + + + // two opertors to cast to un array of constant +// operator KNM_<const_R> & () +// { return * (KNM_<const_R>*) this;} +// operator KNM_<const_R> const & () const +// { return *(const KNM_<const_R>*) this;} + +// operator KNM<const_R> & () +// { return * (KNM<const_R>*) this;} +// operator KNM<const_R> const & () const +// { return *(const KNM<const_R>*) this;} + + void init() { // add mars 2010 ... + this->n=0;this->step=1;this->next=-1;this->v=0; + this->shapei.init(0); + this->shapej.init(0);} + + void init(long nn,long mm) { + ShapeOfArray::init(nn*mm); + this->shapei.init(nn,1,nn); + this->shapej.init(mm,nn,1), + this->v=new R[nn*mm];} + + void resize(long nn,long mm) { + long kk=nn*mm; + + long lso = this->size(); + long n = this->shapei.n; + long m = this->shapej.n; + + if( n !=nn && m != mm) + { + KNM_ <R> old(*this); + long no=std::min(n,nn); + long mo=std::min(m,mm); + R *vo=this->v; + + // new mat + ShapeOfArray::init(kk); + this->v=new R[this->n]; + this->shapei.init(nn,1,nn); + this->shapej.init(mm,nn,1); + + if(this->v && vo) // copy + (*this)(SubArray(no),SubArray(mo)) = old(SubArray(no),SubArray(mo)); + + delete []vo; + } + + } + void destroy(){assert(this->next<0); if(this->next++ ==-1) {delete [] this->v; this->v=0;this->n=0;}} + void increment() {assert(this->next<0); this->next--;} + +// void destroy(){delete [] this->v;this->n=0 ;} + +}; + +// Array with 3 indices +// --------------------- +template<class R> +class KNMK: public KNMK_<R>{ public: + + KNMK(long n,long m,long k) + :KNMK_<R>(new R[n*m*k],n,m,k){} + explicit KNMK(const KNMK_<R> & u) + :KNMK_<R>(new R[u.size()],u.N(),u.M(),u.K()) + { KNMK_<R>::operator=(u);} + KNMK(const KNMK<R> & u) + :KNMK_<R>(new R[u.size()],u.N(),u.M(),u.K()) + { KNMK_<R>::operator=(u);} + + ~KNMK(){delete [] this->v;} + + KNMK& operator=(const KNMK_<const_R> & u) + { KNMK_<R>::operator=(u);return *this;} + KNMK& operator=(const_R a) + { KNMK_<R>::operator=(a);return *this;} + KNMK& operator+=(const_R a) + { KNMK_<R>::operator+=(a);return *this;} + KNMK& operator-=(const_R a) + { KNMK_<R>::operator-=(a);return *this;} + KNMK& operator/=(const_R a) + { KNMK_<R>::operator/=(a);return *this;} + KNMK& operator*=(const_R a) + { KNMK_<R>::operator*=(a);return *this;} + KNMK& operator+=(const KNMK_<const_R> & u) + { KNMK_<R>::operator+=(u);return *this;} + // ici jd + KNMK& operator-=(const KNMK_<const_R> & u) + { KNMK_<R>::operator-=(u);return *this;} + KNMK& operator*=(const KNMK_<const_R> & u) + { KNMK_<R>::operator*=(u);return *this;} + KNMK& operator/=(const KNMK_<const_R> & u) + { KNMK_<R>::operator/=(u);return *this;} + +// two opertor to cast to un array of constant +// operator KNMK_<const_R> & () +// { return * (KNMK_<const_R>*) this;} +// operator KNMK_<const_R> const & () const +// { return *(const KNMK_<const_R>*) this;} + +// operator KNMK<const_R> & () +// { return * (KNMK<const_R>*) this;} +// operator KNMK<const_R> const & () const +// { return *(const KNMK<const_R>*) this;} +}; + +// ------------- optimization --------------------- +template<class R> +class conj_KN_{public: + const KN_<const_R> & a; + conj_KN_(const KN_<const_R> & aa) : a(aa){} +}; + + +inline const KN_<long> conj(const KN_<long> &a){ return a;} +inline const KN_<double> conj(const KN_<double> &a){ return a;} +inline const KN_<float> conj(const KN_<float> &a){ return a;} + +//template<class R> conj_KN_<R> conj(const KN<R> &a){ return a;} +template<class R> conj_KN_<R> conj(const KN_<R> &a){ return a;} + +template<class R> +class DotStar_KN_{public: + const KN_<const_R> a; const KN_<const_R> b; + DotStar_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) : a(aa),b(bb) {} + }; + + +template<class R> +class DotSlash_KN_{public: + const KN_<const_R> a; const KN_<const_R> b; + DotSlash_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) : a(aa),b(bb) {} + }; + +template<class R> +class Add_KN_{public: + const KN_<const_R> a; const KN_<const_R> b; + Add_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) + : a(aa),b(bb) { K_throwassert(SameShape(a,b));} + }; + +template<class R> +class Sub_KN_{public: + const KN_<const_R> a; const KN_<const_R> b; + Sub_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) + : a(aa),b(bb) { K_throwassert(SameShape(a,b));} + }; + +template<class R> +class Mulc_KN_ { public: + const KN_<const_R> a; const_R b; + Mulc_KN_(const KN_<const_R> & aa,const_R bb) : a(aa),b(bb) {} + Mulc_KN_(const Mulc_KN_<R> & aa,const_R bb) : a(aa.a),b(aa.b*bb) {} + Mulc_KN_ operator-() const {return Mulc_KN_(a,-b);} + outProduct_KN_<R> operator*(const TKN_<double> & bb) +{ return outProduct_KN_<R>(a,bb,b);} + + }; + +template<class R> +class Add_Mulc_KN_ { public: + const KN_<const_R> a,b; + const R ca,cb; + Add_Mulc_KN_(const Mulc_KN_<R> & aa,const Mulc_KN_<R> & bb) + : a(aa.a),b(bb.a),ca(aa.b),cb(bb.b) { K_throwassert(SameShape(a,b));} + Add_Mulc_KN_(const Mulc_KN_<R> & aa,const KN_<const_R> & bb,const R cbb) + : a(aa.a),b(bb),ca(aa.b),cb(cbb) { K_throwassert(SameShape(a,b));} + Add_Mulc_KN_(const KN_<const_R> & aa,const R caa,const KN_<const_R> & bb,const R cbb) + : a(aa),b(bb),ca(caa),cb(cbb) { K_throwassert(SameShape(a,b));} + }; + +template<class R> +class if_arth_KN_ { public: + const KN_<const_R> a,b,c; + if_arth_KN_(const KN_<R> & aa,const KN_<R> & bb,const KN_<R> & cc) + : a(aa),b(bb),c(cc){ K_throwassert(SameShape(a,b)&&SameShape(a,c));} + }; + + + +template<class R> +class Mul_KNM_KN_ { public: + const KNM_<const_R> &A; + const KN_<const_R> &b; + Mul_KNM_KN_(const KNM_<const_R> &aa,const KN_<const_R> &bb) + : A(aa),b(bb) {K_throwassert(SameShape(A.shapej,b));} +}; + + +ostream & operator<<(ostream & f,const ShapeOfArray & s); + +template<class R> ostream & operator<<(ostream & f,const KN_<const_R> & v); +template<class R> ostream & operator<<(ostream & f,const KNM_<const_R> & v); +template<class R> ostream & operator<<(ostream & f,const KNMK_<const_R> & v); +template<class R> inline ostream & operator<<(ostream & f,const KN<const_R> & v) + { return f << (const KN_<const_R> &) v;} +template<class R> inline ostream & operator<<(ostream & f,const KNM<const_R> & v) + { return f << (const KNM_<const_R> &) v;} +template<class R> inline ostream & operator<<(ostream & f,const KNMK<const_R> & v) + { return f << (const KNMK_<const_R> &) v;} + + +template<class R> inline Add_KN_<R> operator+(const KN_<const_R> &a,const KN_<const_R> &b) + { return Add_KN_<R>(a,b);} +template<class R> inline Sub_KN_<R> operator-(const KN_<const_R> &a,const KN_<const_R> &b) + { return Sub_KN_<R>(a,b);} +template<class R> inline Mulc_KN_<R> operator*(const KN_<const_R> &a,const R &b) + { return Mulc_KN_<R>(a,b);} +template<class R> inline Mulc_KN_<R> operator/(const KN_<const_R> &a,const R &b) + { return Mulc_KN_<R>(a,1/b);} +template<class R> inline Mulc_KN_<R> operator*(const R &b,const KN_<const_R> &a) + { return Mulc_KN_<R>(a,b);} +template<class R> inline Mulc_KN_<R> operator-(const KN_<const_R> &a) + { return Mulc_KN_<R>(a,-1);} + + + +template<class R> inline Add_Mulc_KN_<R> operator+(const Mulc_KN_<R>& a,const Mulc_KN_<R> &b) + { return Add_Mulc_KN_<R>(a,b);} +template<class R> inline Add_Mulc_KN_<R> operator-(const Mulc_KN_<R>& a,const Mulc_KN_<R> &b) + { return Add_Mulc_KN_<R>(a,b.a,-b.b);} + +template<class R> inline Add_Mulc_KN_<R> operator+(const Mulc_KN_<R>& a,const KN_<const_R> &b) + { return Add_Mulc_KN_<R>(a,b,R(1));} +template<class R> inline Add_Mulc_KN_<R> operator-(const Mulc_KN_<R>& a,const KN_<const_R> &b) + { return Add_Mulc_KN_<R>(a,b,R(-1));} + +template<class R> inline Add_Mulc_KN_<R> operator+(const KN_<const_R> & b,const Mulc_KN_<R>& a) + { return Add_Mulc_KN_<R>(a,b,R(1));} + +// modif FH mars 2007 +template<class R> inline Add_Mulc_KN_<R> operator-(const KN_<const_R> & a,const Mulc_KN_<R>& b) + { return Add_Mulc_KN_<R>(a,R(1),b.a,-b.b);}// modif FH mars 2007 + +template<class R> inline Mul_KNM_KN_<R> operator*(const KNM_<const_R> & A,const KN_<const_R> & b) + { return Mul_KNM_KN_<R>(A,b);} + + +template<class R> inline bool SameShape(const ShapeOfArray & a,const Add_Mulc_KN_<R> & b) + { return SameShape(a,b.a) ;} +template<class R> inline bool SameShape(const ShapeOfArray & a,const if_arth_KN_<R> & b) + { return SameShape(a,b.a) ;} +template<class R> inline bool SameShape(const ShapeOfArray & a,const Add_KN_<R> & b) + { return SameShape(a,b.a) ;} +template<class R> inline bool SameShape(const ShapeOfArray & a,const Sub_KN_<R> & b) + { return SameShape(a,b.a) ;} +template<class R> inline bool SameShape(const ShapeOfArray & a,const Mulc_KN_<R> & b) + { return SameShape(a,b.a) ;} +template<class R> inline bool SameShape(const ShapeOfArray & a,const DotStar_KN_<R> & b) + { return SameShape(a,b.a) ;} +template<class R> inline bool SameShape(const ShapeOfArray & a,const DotSlash_KN_<R> & b) + { return SameShape(a,b.a) ;} +template<class R> inline bool SameShape(const ShapeOfArray & a,const Mul_KNM_KN_<R> & b) + { return a.n==b.A.N() ;} + inline bool SameShape(const ShapeOfArray & ,const VirtualMatrice<double>::plusAx & ) + { return true ;} // pas de test car la matrice peut etre rectangulaire + inline bool SameShape(const ShapeOfArray & ,const VirtualMatrice<double>::plusAtx & ) + { return true ;} // pas de test car la matrice peut etre rectangulaire + inline bool SameShape(const ShapeOfArray & ,const VirtualMatrice<complex<double> >::plusAx & ) + { return true ;} // pas de test car la matrice peut etre rectangulaire + inline bool SameShape(const ShapeOfArray & ,const VirtualMatrice<complex<double> >::plusAtx & ) + { return true ;} // pas de test car la matrice peut etre rectangulaire + + inline bool SameShape(const ShapeOfArray & ,const double) + { return true;} + inline bool SameShape(const ShapeOfArray & ,const complex<double>) + { return true;} + inline bool SameShape(const ShapeOfArray & ,const complex<float>) + { return true;} + +template<class R> + inline bool SameShape(KNM<R>& m, const outProduct_KN_<R>& p) + { return p.a.N()>=m.N() && m.M()>=p.b.N(); } + +template<class R> inline long SameAdress(const KN_<R> &a, const KN_<R> &b) { return &a[0]==&b[0];} +// bof -bof +//template<class R> inline +// KN_<R>::operator KN<R> &() { return *(KN<R> *) (void *) this;} +//template<class R> inline +// KN_<R>::operator const KN<R> &() const { return *(const KN<R> *) ( const void *) this;} + +// operateur y=Ax-b ou y=Ax + b pour le GC +template<class R> + PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> > operator-(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B) + { return PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >(A,Mulc_KN_<R>(B,R(-1.)));} + +template<class R> + PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> > operator+(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B) + { return PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >(A,B);} + +template<class R> + PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> > operator-(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B) + { return PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >(A,Mulc_KN_<R>(B,R(-1.)));} + +template<class R> + PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> > operator+(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B) + { return PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >(A,B);} + + +template<class R> +KN_<R> diagonal(const KNM<R> & A) { + K_throwassert(A.N() == A.M()); + return KN_<R>(A,SubArray(A.N(),0,A.N()+1));} + +// to def inv permutation FH mars 2006 +class Inv_KN_long{ public: + KN_<long> t; + Inv_KN_long(const KN_<long> & v) + : t(v) {} + Inv_KN_long( KN_<long> const * & v) + : t(*v) {} + operator const KN_<long> & () const {return t;} +}; + + +template<class R,typename A,typename B=R> class F_KN_ +{ + public: + A (*f)(B); + KN_<R> a; + long N() const {return a.N();} + F_KN_( A (*ff)(B),const KN_<R> & aa): f(ff),a(aa) {} + A operator[](long i) const { return f(a[i]);} + bool check(long n) const { return n <= a.N() || a.constant(); } + bool constant() const {return a.constant();} +}; + +template<class R,typename A,typename B> +inline bool SameShape(const ShapeOfArray & a,const F_KN_<R,A,B> & b) + { return !a.step || b.constant() || a.n == b.N() ;} + +#include "RNM_tpl.hpp" +#ifdef K_throwassert +#undef K_throwassert +#endif +#endif diff --git a/contrib/bamg/RNM_op.hpp b/contrib/bamg/RNM_op.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c067e89821312d3bf5e0e83b09f27973bdb47cea --- /dev/null +++ b/contrib/bamg/RNM_op.hpp @@ -0,0 +1,157 @@ +// ********** DO NOT REMOVE THIS BANNER ********** +// ORIG-DATE: 29 fev 2000 +// -*- Mode : c++ -*- +// +// SUMMARY : array modelisation +// USAGE : LGPL +// ORG : LJLL Universite Pierre et Marie Curie, Paris, FRANCE +// AUTHOR : Frederic Hecht +// E-MAIL : frederic.hecht@ann.jussieu.fr +// + +/* + + + + 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 + + + */ + +template<class R> +KNM_<R> & KNM_<R>::operator oper (const outProduct_KN_<R> & u) +{ + // *this oper A* t B + K_throwassert (shapei.SameShape(u.a) && shapej.SameShape(u.b) ); + long n= N(), m= M(); + + R * ai(u.a),cc, c= u.c; + long stepi=u.a.step; + R * bj, *bb(u.b); + long stepj=u.b.step; + KN_<const_R> li((*this)(0,'.')); // first line + int stepij= li.step; + for (long i=0;i<n;i++,ai += stepi,++li) + { + cc= c * *ai; + R * mij = li; + bj = bb; + for (long j=0; j<m; j++, bj += stepj, mij += stepij ) + *mij oper cc * conj(*bj) ; + } + return *this; + } + + +template<class R> +template<class A,class B,class C> + KN_<R>& KN_<R>::operator oper (const F_KN_<A,B,C> & u) { + K_throwassert ( u.check(this->N()) ); + R * l(v); // first line + for (long i=0;i<n;i++,l += step) + *l oper u[i]; + return *this;} + +template<class R> +KN_<R>& KN_<R>::operator oper (const SetArray<R> & u) { + R * l(v); // first line + for (long i=0;i<n;i++,l += step) + *l oper u[i]; +return *this;} + + + +template<class R> + KN_<R>& KN_<R>::operator oper (const Mul_KNM_KN_<R> & u) { + K_throwassert (SameShape(u.A.shapei) && !constant()); + R * l(v); KN_<const_R> li(u.A(0,'.')); // first line + for (long i=0;i<n;i++,l += step,++li) + *l oper (li,u.b); + return *this;} + + +template<class R> + KN_<R>& KN_<R>::operator oper (const DotStar_KN_<R> & u) { + K_throwassert(u.a.N() == N() ); + long stepa(u.a.step),stepb(u.b.step); + R * l(v); const_R *aa(u.a), *bb(u.b); + for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb) + *l oper *aa * *bb; + return *this; + } +template<class R> + KN_<R>& KN_<R>::operator oper (const DotSlash_KN_<R> & u) { + K_throwassert(u.a.N() == N() ); + long stepa(u.a.step),stepb(u.b.step); + R * l(v); const_R *aa(u.a), *bb(u.b); + for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb) + *l oper *aa / *bb; + return *this; + } + + +template<class R> + KN_<R>& KN_<R>::operator oper (const Add_KN_<R> & u) { + K_throwassert(u.a.N() == N() ); + long stepa(u.a.step),stepb(u.b.step); + R * l(v); const_R *aa(u.a), *bb(u.b); + for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb) + *l oper *aa+*bb; + return *this; + } + +template<class R> + KN_<R>& KN_<R>::operator oper (const Sub_KN_<R> & u) { + K_throwassert(u.a.N() == N() ); + long stepa(u.a.step),stepb(u.b.step); + R * l(v); const_R *aa(u.a), *bb(u.b); + for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb) + *l oper *aa-*bb; + return *this; + } + +template<class R> + KN_<R>& KN_<R>::operator oper (const Mulc_KN_<R> & u) { + K_throwassert(u.a.N() == N() ); + long stepa(u.a.step); + R * l(v); const_R *aa(u.a),bb(u.b) ; + for (long i=0;i<n;i++,l += step, aa +=stepa) + *l oper *aa * bb; + return *this; + } + +template<class R> + KN_<R>& KN_<R>::operator oper (const Add_Mulc_KN_<R> & u) { + K_throwassert(u.a.N() == N() ); + const long stepa(u.a.step),stepb(u.b.step); + const R ca(u.ca),cb(u.cb); + R * l(v); + const R *aa(u.a),*bb(u.b); + for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb) + *l oper *aa*ca + *bb*cb; + return *this; + } + +template<class R> + KN_<R>& KN_<R>::operator oper (const if_arth_KN_<R> & u) { + K_throwassert(u.a.N() == N() ); + R zero=R(); + const long stepa(u.a.step),stepb(u.b.step),stepc(u.c.step); + R * l(v); + const R *aa(u.a),*bb(u.b),*cc(u.c); + for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb , cc += stepc) + *l oper ( (*aa != zero) ? *bb : *cc); + return *this; + } diff --git a/contrib/bamg/RNM_opc.hpp b/contrib/bamg/RNM_opc.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fdab0e8eadcc126c96a50b3db91e82f46c41a2f5 --- /dev/null +++ b/contrib/bamg/RNM_opc.hpp @@ -0,0 +1,108 @@ +// ********** DO NOT REMOVE THIS BANNER ********** +// ORIG-DATE: 29 fev 2000 +// -*- Mode : c++ -*- +// +// SUMMARY : array modelisation +// USAGE : LGPL +// ORG : LJLL Universite Pierre et Marie Curie, Paris, FRANCE +// AUTHOR : Frederic Hecht +// E-MAIL : frederic.hecht@ann.jussieu.fr +// + +/* + + + + 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 + + + */ + +template<class R> +inline KN_<R>& KN_<R>::operator oper (const_R a) { + R * l(v); + for (long i=0;i<n;i++,l += step) + *l oper a; + return *this; + } + +template<class R> +inline KNM_<R> & KNM_<R>::operator oper (const_R a) +{ + if(IsVector1() ) + KN_<R>::operator oper (a); + else { + KN_<R> lj(operator()('.',0)); // (.,.,O) + for (long j=0;j<M();++j,++lj) + lj oper a;} + return *this; +} + +template<class R> +inline KNMK_<R> & KNMK_<R>::operator oper (const_R a) +{ + if(IsVector1() ) + KN_<R>::operator oper (a); + else { + KNM_<R> lj(operator()('.','.',0)); // (.,.,O) + long j=K(); + while(j--) + {lj oper a;++lj;} + } + return *this; +} + +template<class R> +inline KN_<R>& KN_<R>::operator oper (const KN_<const_R> & u) { + K_throwassert(u.n == n); + R * l(v); + const R *r(u); + for (long i=0;i<n;i++,l += step, r += u.step) *l oper *r; + return *this; + } + +template<class R> +inline KNM_<R> & KNM_<R>::operator oper (const KNM_<const_R> & u) +{ + if(IsVector1() && u.IsVector1() ) + KN_<R>::operator oper(u); // modif FH jan 2004 + else { + KN_<R> lj(operator()('.',0)); // (.,O) + KN_<const_R> uj(u('.',0)); + long j=M(); + while ( j--) + { lj oper uj;++lj;++uj;} + } + return *this; +} + + +template<class R> +inline KNMK_<R> & KNMK_<R>::operator oper (const KNMK_<const_R> & u) +{ + if(IsVector1() && u.IsVector1() ) + KN_<R>::operator oper(u); // modif FH 2004 + else { + K_throwassert( K() == u.K()); + KNM_<R> lj(operator()('.','.',0)); // (.,O) + KNM_<const_R> uj(u('.','.',0)); + long j=K(); + while (j--) + { lj oper uj;++lj;++uj;} + } + return *this; +} + +#undef oper diff --git a/contrib/bamg/RNM_tpl.hpp b/contrib/bamg/RNM_tpl.hpp new file mode 100644 index 0000000000000000000000000000000000000000..02dfdb6488f0b097789ee04fc562515c7eb9b388 --- /dev/null +++ b/contrib/bamg/RNM_tpl.hpp @@ -0,0 +1,344 @@ +// ********** DO NOT REMOVE THIS BANNER ********** +// ORIG-DATE: 29 fev 2000 +// -*- Mode : c++ -*- +// +// SUMMARY : array modelisation +// USAGE : LGPL +// ORG : LJLL Universite Pierre et Marie Curie, Paris, FRANCE +// AUTHOR : Frederic Hecht +// E-MAIL : frederic.hecht@ann.jussieu.fr +// + +/* + + + + 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 + + + */ + +#ifndef RNM_tpl_ +#define RNM_tpl_ + +#include "RNM.hpp" + +// version du 22 nov 1999 +// Voila une debut de class vecteur + matrice +// les class avec termine avec un _ ne travail que sur +// un pointeur existant => pas de new et delete de pointeur +// la class correspondant sans de _ genere les pointeurs +// +// avec ses classes on peut prendre une ligne +// ou une colonne d'une matrice +// ----------------------- + +namespace RNM { + +template <class T> inline double norm(const T & x){return std::norm(x);} +inline double norm(double x){return x*x;} +inline double norm(float x){return x*x;} +inline long norm(long x){return x*x;} +inline int norm(int x){return x*x;} + +} + +template<class R> +void MatMul(KNM_<R> & ab, KNM_<R> & a, KNM_<R> & b){ + // attention ne marche que si les adresses ne sont pas les memes + long N= a.shapei.n; + long M= a.shapej.n; + K_throwassert(a.shapej.n == a.shapei.n); + K_throwassert(a.shapei.n == ab.shapei.n); + K_throwassert(b.shapej.n == ab.shapej.n); + K_throwassert(b.v != ab.v); + K_throwassert(a.v != ab.v); + KN_<R> ai =a(0); + for(long i=0;i<N;i++,++ai){ + KN_<R> bj=b[0]; + for(long j=0;j<M;j++,++bj) + ab(i,j) = (ai , bj) ;} +} + + + +inline ostream & operator<<(ostream & f,const ShapeOfArray & s) + { f << s.n ; + const int i10=10; + int prec=f.precision(); + if(prec<i10) f.precision(i10); + if(s.step != 1) + f << ":" << s.step ; + if (s.step*s.n != s.next ) + f << " n: " << setw(3) << s.next ; + f << ","; + if(prec<i10) f.precision(prec); + return f; + }; + + +template<class R> ostream & operator<<(ostream & f,const KN_<const_R> & v) + { //f << " KN_ : " << (ShapeOfArray) v << " " << (const_R *) v << " :\n\t" ; + f << v.N() << "\t\n\t" ; + const int i10=10; + int prec=f.precision(); + if(prec<i10) f.precision(i10); + for (long i=0;i<v.N();i++) + f << setw(3) << v[i] << ((i % 5) == 4 ? "\n\t" : "\t"); + if(prec<i10) f.precision(prec); + return f; + }; + +template<class R> istream & operator>>(istream & f, KN_<R> & v) + { + int n;char c; + f >> n; + ffassert(f.good()); + ffassert(n==v.N()); + while (f.get(c) && (c!='\n' && c!='\r' ) ) ; // eat until control (new line + + for (int i=0;i<n;i++) + { f >> v[i] ; + ffassert(f.good());} // modif FH main 2006 + return f; +} + +template<class R> istream & operator>>(istream & f, KN<R> & v) + { + int n;char c; + f >> n; + if (v.unset()) v.init(n); + cout << n << " == " << v.N() << endl; + ffassert(n==v.N()); + while (f.get(c) && (c!='\n' && c!='\r' ) ) ; // eat until control (new line + + for (int i=0;i<n;i++) + { + f >> v[i] ; + ffassert(f.good());}// modif FH main 2006 + return f; +} + + +template<class R> ostream & operator<<(ostream & f,const KNM_<const_R> & v) + { //f << " KNM_ "<<v.N()<<"x"<<v.M()<< ": " << (ShapeOfArray) v + //<< " i " << v.shapei + // << " j " << v.shapej + // << " " << &v(0,0) << " :\n\t"; + const int i10=10; + int prec=f.precision(); + if(prec<i10) f.precision(i10); + f << v.N()<<' '<<v.M() /*<< " n" << v.next<<" :"<< v.shapei.next << "," << v.shapej.next */<< "\t\n\t" ; + for (long i=0;i<v.N();i++) { + for (long j=0;j<v.M();j++) + f << " " << setw(3) << v(i,j); + f << "\n\t";} + if(prec<i10) f.precision(prec); + return f; + + }; + +template<class R> ostream & operator<<(ostream & f,const KNMK_<const_R> & v) + { //f << " KNM_" <<v.N()<<"x"<<v.M()<<"x"<<v.K()<< " : " << (ShapeOfArray) v + // << " i " << v.shapei + // << " j " << v.shapej + // << " k " << v.shapek << endl; + // << " " << (void *) & v(0,0,0) << "\n\t" ; + f << v.N()<< 'x' <<v.M()<< 'x'<<v.K() << "\t:\n\t" ; + const int i10=10; + int prec=f.precision(); + if(prec<i10) f.precision(i10); + for (long i=0;i<v.shapei.n;i++){ + for (long j=0;j<v.shapej.n;j++){ + for (long k=0;k<v.shapek.n;k++) + f << " " << setw(3) << v(i,j,k); + f << "\n\t";} + f << "\n\t";} + if(prec<i10) f.precision(prec); + return f; + + }; + +template<class R> + R KN_<R>::operator,(const KN_<const_R> & u) const { + K_throwassert(u.n == n); + R s=0; + R * l(v); + R *r(u.v); + for (long i=0;i<n;i++,l += step, r += u.step) s += *l * *r; + return s; + } + +template<class R> + R operator,(const KN_<const_R> & u,const conj_KN_<const_R> & vc) { + int n=u.n; + K_throwassert(n == vc.a.n); + R s=0; + R * l(u); + R *r(vc.a); + int stepl= u.step, stepr=vc.a.step; + for (long i=0;i<n;i++,l += stepl, r += stepr) s += *l * conj(*r); + return s; + } + +template<class R> + R operator,(const conj_KN_<const_R> & u,const KN_<const_R> & vc) { + int n=u.a.n; + K_throwassert(n == vc.n); + R s=0; + R * l(u.a); + R *r(vc); + int stepl= u.a.step, stepr=vc.step; + for (long i=0;i<n;i++,l += stepl, r += stepr) s += conj(*l) * (*r); + return s; + } + +template<class R> + R operator,(const KN<const_R> & u,const conj_KN_<const_R> & vc) { return ( (KN_<R>) u,vc);} +template<class R> + R operator,(const conj_KN_<const_R> & u,const KN<const_R> & vc) { return ( u, (KN_<R>) vc);} + + +template<class R> +R KN_<R>::min() const { + R minv = v[index(0)]; + for (long i=1;i<n;i++) + minv = RNM::Min(minv, v[index(i)]) ; + return minv; + } +template<class R> +R KN_<R>::max() const { + R maxv = v[index(0)]; + for (long i=1;i<n;i++) + maxv = RNM::Max(maxv ,v[index(i)]); + return maxv; + } + + + +template<class R> +R KN_<R>::sum() const { + R s = v[index(0)]; + for (long i=1;i<n;i++) + s += v[index(i)]; + // cout << " sum = " << s << endl; + return s; + } + +template<class R> +double KN_<R>::norm() const { + double s = 0.; + for (long i=0;i<n;i++) + s += RNM::norm(v[index(i)]); + return s; + } + +template<class R> +double KN_<R>::l2() const { + double s = 0.; + for (long i=0;i<n;i++) + s += RNM::norm(v[index(i)]); + return sqrt(s); + } +template<class R> +double KN_<R>::l1() const { + double s = 0.; + for (long i=0;i<n;i++) + s += std::abs(v[index(i)]); + return (s); + } +template<class R> +double KN_<R>::linfty() const { + double s = 0.; + for (long i=0;i<n;i++) + s = std::max( (double) std::abs(v[index(i)]),s); + return (s); + } +template<class R> +double KN_<R>::lp(double p) const { + if( p==1.) return l1(); + else if (p==2.) return l2(); + else if(p>1.e10) return linfty(); + else + { + double s = 0.; + for (long i=0;i<n;i++) + s = pow(std::max( (double) std::abs(v[index(i)]),s),p); + return pow(s,1./p); + } + } + +template<class R> template<class T> +long KN_<R>::last(const T & a) const { + for (long i=n;i-- >0;) + if (a(v[index(i)])) + return i; + return -1; + } + +template<class R> template<class T> +long KN_<R>::first(const T & a) const { + for (long i=0;i<n;i++) + if (a(v[index(i)])) return i; + return n; + } + + +template<class R> + void KN_<R>::map(R (*f)(R )) { + for (long i=0;i<n;i++) + { R & x(v[index(i)]); + x = f(x);} + + } + +template<class R> + void KN_<R>::map(R (*f)(const R& )) { + for (long i=0;i<n;i++) + { R & x(v[index(i)]); + x = f(x);} + + } + +template<class R> +template<class T> + void KN_<R>::set(R (*f)(const T& ),KN_<T> & u) + { + K_throwassert(N() == u.N()); + for (long i=0;i<n;i++) + { R & x(v[index(i)]); + v[index(i)]= f(u[i]);} + } + + + +///////////////// definition des operateurs d'affectation ///////////////////////// +#define oper = +#include "RNM_op.hpp" +#include "RNM_opc.hpp" +#define oper += +#include "RNM_op.hpp" +#include "RNM_opc.hpp" +#define oper -= +#include "RNM_op.hpp" +#include "RNM_opc.hpp" +#define oper *= +#include "RNM_op.hpp" +#include "RNM_opc.hpp" +#define oper /= +#include "RNM_op.hpp" +#include "RNM_opc.hpp" + +#endif diff --git a/contrib/bamg/assertion.hpp b/contrib/bamg/assertion.hpp new file mode 100755 index 0000000000000000000000000000000000000000..9894ab57e5e83ca7e3a813e37587ba733640abe4 --- /dev/null +++ b/contrib/bamg/assertion.hpp @@ -0,0 +1,14 @@ +#ifndef ASSERTION_HPP_ +#define ASSERTION_HPP_ +// to compile all assertion +//#define ASSERTION +// to remove all the assert +//#define NDEBUG +#ifndef ASSERTION +#define ASSERTION(i) ((void ) 0) +#else +#include <cassert> +#undef ASSERTION +#define ASSERTION(i) assert(i) +#endif +#endif diff --git a/contrib/bamg/bamg-gmsh.cpp b/contrib/bamg/bamg-gmsh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..710b1d0a042deb6db891d9565f8ce4a7bf75bd43 --- /dev/null +++ b/contrib/bamg/bamg-gmsh.cpp @@ -0,0 +1,578 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#include <iostream> +using namespace std; +#include <stdio.h> +#include <string.h> + + +#include "Mesh2.h" +#include "RNM.hpp" +#include "Mesh2d.hpp" +#include "bamg-gmsh.hpp" + +#include <set> +void ExecError(const char *s) { cout << s << endl;exit(1);} + + +Mesh2 *bamg2msh( bamg::Triangles* tTh,bool renumbering) +{ + using bamg::Triangles; + using bamg::Triangle; + using bamg::Vertex; + using bamg::TriangleAdjacent; + using bamg::EdgesVertexTriangle; + using bamg::Int4; + using bamg::VerticesOfTriangularEdge; + + bamg::Triangles & th (*tTh); + tTh->ReNumberingTheTriangleBySubDomain(!renumbering);// just compress + //tTh->NbRef++; + Int4 i,j,k=0; + int nv = tTh->nbv; + int nt = tTh->nbt - tTh->NbOutT; + int neb = tTh->nbe; + + int nbcrakev = 0; + tTh->ReMakeTriangleContainingTheVertex(); + Triangle2 * t = new Triangle2[nt] ; + Seg * b_e = new Seg[neb]; + + Vertex2 vbase; + Vertex2 *vb(&vbase); + if (verbosity>5) + cout << " -- Before cracking mesh: Nb Triangles = " << nt << " Nb of Vertices " << nv << endl; + for (int iv=0;iv<th.nbv;iv++) // vertex + { + // cout << iv << " : " ; + const Vertex & v(th[iv]); + int kk=0; // nb cracked + int kc=0; + int kkk =0; // nb triangle with same number + Triangle * tbegin = v.t; + Vertex2 * vv = vb+iv; + int i = v.vint; + assert(tbegin && (i >= 0 ) && (i <3)); + // turn around the vertex v + TriangleAdjacent ta(tbegin,EdgesVertexTriangle[i][0]);// previous edge + int k=0; + do { + int kv = VerticesOfTriangularEdge[ta][1]; + k++; + Triangle * tt (ta); + assert( &v == & (* tt)[kv] ); + if ( ta.Cracked() ) + { // cout << " || " ; + if ( kk == 0) tbegin=ta,kkk=0; // begin by a cracked edge => restart + if ( kkk ) { kc =1;vv = vb + nv++; kkk = 0; } // new vertex if use + kk++; + // number of cracked edge view + } + if ( tt->link ) { // if good triangles store the value + int it = th.Number(tt); + assert(it < nt); + //int iiv=vv-vb; + t[it](kv) = vv; + /* + cout << it << " " << kv << " "<< iiv << endl; + if (&th(it)[kv] != &th[iiv]) + cout << it << " " << kv << " "<< iiv << " != " << th.Number(th(it)[kv]) << endl ; + */ + kkk++; + } else if (kk) { // crack + boundary + if ( kkk ) { kc =1;vv = vb + nv++; kkk = 0; } // new vertex if use + } + + ta = Next(ta).Adj(); + } while ( (tbegin != ta)); + assert(k); + if (kc) nbcrakev++; + } + Vertex2 * v = new Vertex2[nv]; + // set the vertices -- + for (i=0;i<nt;i++) + { + for (j=0;j<3;j++) + { + assert( t[i](j) ); + int k = t[i](j) - vb; + t[i](j) = v+ k; + assert(k>=0 && k < nv); + Vertex & thv(th(i)[j]); + v[k].x = thv.r.x; + v[k].y = thv.r.y; + v[k].lab = thv.ref(); + } + } + // warning in cracked edges + // construction of the edges -- + + if (nbcrakev && verbosity>2) + cout << " -- Nb of craked vertices = " << nbcrakev << " Nb of created vertices " << nv - th.nbv << endl; + + + for (i=0;i<tTh->nbe;i++) + { + int ii[]={tTh->Number(tTh->edges[i][0]),tTh->Number(tTh->edges[i][1])}; + assert(ii[0]>=0 && ii[0] <nv); + assert(ii[1]>=0 && ii[1] <nv); + b_e[i].init(v,ii,tTh->edges[i].ref); + } + Int4 *reft = new Int4[tTh->nbt]; + //Int4 nbref = + tTh->ConsRefTriangle(reft); + for( i=0,k=0;i<tTh->nbt;i++) + if(tTh->triangles[i].link) + { + + R2 A(t[k][0]),B(t[k][1]),C(t[k][2]); + t[k].area = (( B-A)^(C-A))*0.5 ; + t[k].lab = tTh->subdomains[reft[i]].ref; // a faire + assert(k == i); + k++; + } + delete [] reft; + assert ( nt == k); + tTh->ReMakeTriangleContainingTheVertex(); + + if (verbosity) + cout << " -- mesh: Nb of Triangles = " << setw(6) << nt << ", Nb of Vertices " << nv << endl; + + { + Mesh2 *m = new Mesh2(nv,nt,neb,v,t,b_e); + // if (renumbering) m->renum(); + //< m->MakeQuadTree(); + return m; + } +} + + + +bamg::Triangles * msh2bamg(const Mesh2 & Th,double cutoffradian,long * reqedgeslab,int nreqedgeslab) + +{ + using namespace bamg; + Triangles *Tn=new Triangles(Th.nv); + Tn->nbv = Th.nv; + Tn->nbt = Th.nt; + Tn->nbe = Th.nbe; + Tn->name= new char[strlen("msh2bamg")+1]; + strcpy(Tn->name,"msh2bamg"); + // Tn->triangles = new Triangle [Tn->nbtx]; + assert(Tn->triangles); + // Tn->vertices = new Vertex [Tn->nbvx]; + // Tn->ordre = new (Vertex* [Tn->nbvx]); + Tn->edges = new Edge [Th.nbe]; + + Int4 i; + Metric Mid(1.); + for (i = 0; i < Th.nv; i++) + { + Tn->vertices[i].r.x = Th(i).x; + Tn->vertices[i].r.y = Th(i).y; + Tn->vertices[i].m=Mid; + Tn->vertices[i].ReferenceNumber = Th(i).lab; + } + + // Int4 i1 [nbt],i2 [nbt],i3 [nbt]; + for (i = 0; i < Th.nt; i++) + { + int i1 = Th(Th[i][0]); + int i2 = Th(Th[i][1]); + int i3 = Th(Th[i][2]); + Tn->triangles[i]= Triangle( Tn,i1 ,i2 ,i3 ); + Tn->triangles[i].color = Th[i].lab; + } + // Real8 cutoffradian = -1; + // add code un change boundary part ... frev 2009 JYU FH + set<int> labreq; + if(nreqedgeslab && verbosity) cout << " label of required edges " ; + for (int i=0; i <nreqedgeslab;++i) + { + if(verbosity) + cout << " " << reqedgeslab[i]; + labreq.insert(reqedgeslab[i]); + } + bamg::GeometricalEdge paszero; // add JYU fevr 2009 for required edge .... + if(nreqedgeslab && verbosity) cout << endl; + int k=0; + for (i = 0; i < Th.nbe; i++) + { + Tn->edges[i].v[0] = Tn->vertices + Th(Th.be(i)[0]); + Tn->edges[i].v[1] = Tn->vertices + Th(Th.be(i)[1]); + Tn->edges[i].ref = Th.be(i).lab; + Tn->edges[i].on = 0; + if( labreq.find( Tn->edges[i].ref) != labreq.end()) + { + k++; + Tn->edges[i].on = &paszero; + } + + } + if(verbosity)cout << " number of required edges : "<< k << endl; + + + Tn->ConsGeometry(cutoffradian); + Tn->Gh.AfterRead(); + Tn->SetIntCoor(); + Tn->FillHoleInMesh(); + return Tn; +} + + +bamg::Triangles * msh2bamg(const Mesh2 & Th,double cutoffradian, + int nbdfv, int * ndfv,int nbdfe, int * ndfe, + long * reqedgeslab,int nreqedgeslab) +{ + using namespace bamg; + Triangles *Tn=new Triangles(Th.nv); + KN<int> equiedges(Th.nbe); + for(int i=0;i<Th.nbe;i++) + equiedges[i]=2*i; + if(nbdfe !=0 ) + { + KN<int> kk(Th.nbe),kn(Th.nbe); + kk=0; + for(int i=0;i<Th.nbe;i++) + { + int df=ndfe[i]; + kk[df]++; + if(kk[df]==1) kn[df]=i; + else { + int k=kn[df],sens=0; + int di0=ndfv[Th(Th.be(i)[0])]; + int di1=ndfv[Th(Th.be(i)[1])]; + int dk0=ndfv[Th(Th.be(k)[0])]; + int dk1=ndfv[Th(Th.be(k)[1])]; + if ((di0==dk0) &&(di1==dk1) ) sens=0; + else if ((di1==dk0) &&(di0==dk1) ) sens=1; + else { + cout << "Error in periodic mesh " << di0 << " " << di1 << " <=> " << dk0 << " " << dk1 << endl; + ExecError("bug periodic mesh in ??? "); + } + equiedges[i]=2*k+sens; + + } + } + + }; // a faire pour les maillages periodique + + Tn->nbv = Th.nv; + Tn->nbt = Th.nt; + Tn->nbe = Th.nbe; + Tn->name= new char[strlen("msh2bamg")+1]; + strcpy(Tn->name,"msh2bamg"); + // Tn->triangles = new Triangle [Tn->nbtx]; + assert(Tn->triangles); + // Tn->vertices = new Vertex [Tn->nbvx]; + // Tn->ordre = new (Vertex* [Tn->nbvx]); + Tn->edges = new Edge [Th.nbe]; + + Int4 i; + Metric Mid(1.); + for (i = 0; i < Th.nv; i++) + { + Tn->vertices[i].r.x = Th(i).x; + Tn->vertices[i].r.y = Th(i).y; + Tn->vertices[i].ReferenceNumber = Th(i).lab; + Tn->vertices[i].m=Mid; + } + + // Int4 i1 [nbt],i2 [nbt],i3 [nbt]; + for (i = 0; i < Th.nt; i++) + { + int i1 = Th(Th[i][0]); + int i2 = Th(Th[i][1]); + int i3 = Th(Th[i][2]); + Tn->triangles[i]= Triangle( Tn,i1 ,i2 ,i3 ); + Tn->triangles[i].color = Th[i].lab; + } + + // add code un change boundary part ... frev 2009 JYU FH + set<int> labreq; + if(nreqedgeslab && verbosity) cout << " label of required edges " ; + for (int i=0; i <nreqedgeslab;++i) + { + if(verbosity) + cout << " " << reqedgeslab[i]; + labreq.insert(reqedgeslab[i]); + } + bamg::GeometricalEdge paszero; // add JYU fevr 2009 for required edge .... + if(nreqedgeslab && verbosity) cout << endl; + int k=0; + + for (i = 0; i < Th.nbe; i++) + { + Tn->edges[i].v[0] = Tn->vertices + Th(Th.be(i)[0]); + Tn->edges[i].v[1] = Tn->vertices + Th(Th.be(i)[1]); + Tn->edges[i].ref = Th.be(i).lab; + Tn->edges[i].on = 0; + if( labreq.find( Tn->edges[i].ref) != labreq.end()) + { + k++; + Tn->edges[i].on = &paszero; + } + } + // Real8 cutoffradian = -1; + Tn->ConsGeometry(cutoffradian,equiedges); + Tn->Gh.AfterRead(); + Tn->SetIntCoor(); + Tn->FillHoleInMesh(); + return Tn; +} + + +template<class T> T arg(int i,double *args,const T & d) +{ + return args[i]<= -1.e100 ? d: (T) args[i]; +} +Mesh2 *Bamg(Mesh2 *Thh, double * args,double *mm11,double *mm12,double *mm22, bool initialMesh) +{ + using namespace bamg; + using RNM::Min; + using RNM::Max; + using RNM::Abs; + + + Real8 err = arg(2,args,0.01); // coef in the metric + Real8 errg = Min(arg(3,args,0.01),err); + long nbsx = Max(100L,arg(4,args,900000L)); + long nbsmooth = arg(5,args,3L); + long nbjacobi = arg(6,args,0L) ; // if increased will be more smooth + const Real8 raison = arg(7,args,1.5); // 1.8 + const Real8 omega = arg(8,args,1.0) ; + bool iso = arg(9,args,false); + bool AbsError = arg(10,args,true); + Real8 CutOff = arg(11,args, 1.0e-6); + verbosity = arg(12,args, (long) verbosity); + bool inq = arg(13,args,false); + bool SplitEdgeWith2Boundary = arg(14,args,true); + double maxsubdiv = Max(Min( arg(15,args,10.0),10.0),0.1); + double anisomax = Max((double) arg(16,args,1.0e6),1.0); + bool rescaling = arg(17,args,true) ; + bool KeepBackVertices = arg(18,args,true) ; + int givenmetric = arg(19,args,false) ; + double powerM = arg(20,args,1.0) ; + double cutoffradian = arg(21,args,-1.0)* bamg::Pi/180. ; + bool split = arg(22,args,false) ; + bool nomeshgeneration = arg(23,args,false) ; + // the 24th param is metrix and is store at compilation time + // const E_Array * expmetrix = dynamic_cast<const E_Array *>(nargs[24]); + // the 25th param is periodic and it store at compilation time + // in nbcperiodic,periodic variable + // KN<long> reqedges0; + // list of label of required edges , for no adapattion on this part of the boundary. + // KN<long> reqedges ( nargs[26] ? GetAny< KN_<long> >( (*nargs[26])(stack) ): (KN_<long>)reqedges0); + + KN<long> reqedges(Thh->nbe); + for (int i=0;i<Thh->nbe;i++)reqedges[i]=Thh->be(i).lab; + + if(reqedges.N() && verbosity) + cout << " reqedges labels " << reqedges << endl; + // KN<double> *mm11=0, *mm12=0,* mm22=0; + + // using MeshPoint; + //using Mesh; + ffassert(Thh); + Triangles * oTh =0; + int nbcperiodic=0; + /* A change ... + if (nbcperiodic) { + KN<int> ndfv(Thh->nv); + KN<int> ndfe(Thh->nbe); + int nbdfv=0,nbdfe=0; + BuildPeriodic(nbcperiodic,periodic,*Thh,stack,nbdfv,ndfv,nbdfe,ndfe); + oTh = msh2bamg(*Thh,cutoffradian,nbdfv,ndfv,nbdfe,ndfe,reqedges,reqedges.N()); + } + else */ + oTh = msh2bamg(*Thh,cutoffradian,reqedges,reqedges.N()); + Triangles &Th(*oTh); + + // printf("COUCOUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU\n"); + // Th.Write("toto.mesh",bamg::Triangles::AutoMesh); + + + bool mtx=true; + KN_<double> m11(mm11,Thh->nv); + KN_<double> m12(mm12,Thh->nv); + KN_<double> m22(mm22,Thh->nv); + + Real8 hmax = 0.3*Th.MaximalHmax(); // final largest edge + Real8 hmin = Th.MinimalHmin(); // final smallest edge + + + Real8 coef =1; // a priori don't touch + // gestion des arguments + hmin = Max(hmin, arg(0,args,hmin)); + hmax = Min(hmax,arg(1,args,hmax)); + + + if (iso) anisomax=1; + if (verbosity>2) + { + cout << endl << endl; + cout << " \t\t ## adapt : nbsx = " << nbsx << ", err = " << err ; + cout << ", hmin = " << hmin << ", hmax = " << hmax <<endl; + cout << " \t\t ratio = " << raison << ", nbsmooth = " << nbsmooth ; + cout << ", omega = " << omega << ", coef = " << coef << ", iso = " << iso << endl; + cout << " \t\t AbsError =" << AbsError << ", CutOff = " << CutOff << ", nbjacobi = " << nbjacobi <<endl; + cout << " \t\t maxsubdiv = " << maxsubdiv << " splitpbedge = " << SplitEdgeWith2Boundary <<endl; + cout << " \t\t anisomax = " << anisomax << ", rescaling = " << rescaling << ", power = " << powerM + << ", KeepBackvertices = " << KeepBackVertices << " IsMetric = " << givenmetric + << endl << endl ; + } + + // + Th.ReMakeTriangleContainingTheVertex(); + /* + //MeshPoint* mp(MeshPointStack(stack)); + + Int4 i,iv; + int ksol =0; + for (i=0;i<nbsol;i++) + ksol += typesol[i]+1; // marche en 2d + + double * lessol = new double [Th.nbv*ksol]; + double *ss = lessol; + // be careful because renum -- + // the triangle was no renum + for ( iv=0;iv<Th.nbv;iv++) + Th[iv].color=1; // color + for (Int4 it = 0; it < Thh->nt; it++) + for (Int4 jt = 0; jt < 3; jt++) + { + bamg::Vertex & v= Th(it)[jt]; + // const Vertex & vf = (*Thh)[it][jt]; + if (&v && v.color) + { + v.color =0; // uncolor + mp->setP(Thh ,it,jt); + + ss = lessol + ksol* Th.Number(v); + for (int j =0; j < ksol; j++) + *ss++= GetAny<double>( (*sol[j])(stack) ); + + } + } + mp->unset(); + */ + // computation of the metric --- + // better thing -> create keyword in the language + // a faire F Hecht . + Metric Mhmax(hmax); + for (int iv=0;iv<Th.nbv;iv++) + Th[iv].m = Mhmax; + + if (mtx) + for (int iv=0;iv<Th.nbv;iv++) { + // if ( Max(m11[iv],m12[iv],m22[iv]) > hmax) + Th[iv].m.IntersectWith(MetricAnIso(m11[iv],m12[iv],m22[iv])); + } + /* + if ( givenmetric) + if (ksol == 1) + { + for (Int4 iv = 0,k=0; iv < Th.nbv ; iv++) + Th[iv].m.IntersectWith(Metric(lessol[k++])); + } + else if (ksol == 3) + { + for (Int4 iv = 0,k=0; iv < Th.nbv ; iv++, k += 3) + { + Metric MM(lessol[k],lessol[k+1],lessol[k+2]); + MatVVP2x2 vp(MM); + vp.Abs(); + Th[iv].m.IntersectWith(vp); + } + } + else + lgerror("Adapt mesh: ksol is wrong, IsMetric and ksol != 1 or 3"); + else + Th.IntersectConsMetric(lessol,nbsol,typesol,hmin,hmax,sqrt(err)*coef,anisomax,AbsError?0.0:CutOff,nbjacobi,rescaling,powerM,0); + + delete [] lessol; + */ + //Th.IntersectGeomMetric(errg,iso); + + Th.SmoothMetric(raison); + Th.MaxSubDivision(maxsubdiv); + Th.BoundAnisotropy(anisomax); + // end of metric's computation + if (mtx) + for (int iv=0;iv<Th.nbv;iv++) + { + m11[iv] = Th[iv].m.a11 ; + m22[iv] = Th[iv].m.a22 ; + m12[iv] = Th[iv].m.a21; + } + + Triangles* nTh = 0; + + // Th.Write("toto.msh",bamg::Triangles::AutoMesh); + + if (initialMesh){ + nTh= new Triangles(nbsx,Th.Gh); + } + else { + nTh= new Triangles(nbsx,Th,KeepBackVertices); // Adaption is here + } + + // nTh->Write("tata.mesh",bamg::Triangles::AutoMesh); + + + if (split) + nTh->SplitElement(1); // modif FH mai 2009 (thank J-M Mirebeau) : Th ->nTh + + if(SplitEdgeWith2Boundary) + nTh->SplitInternalEdgeWithBorderVertices(); + if(verbosity>3) + nTh->ShowHistogram(); + if (nbsmooth) + nTh->SmoothingVertex(nbsmooth,omega); + if(verbosity>2 && nbsmooth) + nTh->ShowHistogram(); + if(verbosity>0) + nTh->ShowRegulaty() ; + + inq=0; + Metric M(hmax); + for (int iv=0;iv < Th.nbv;iv++) + Th[iv].m = M; + + Mesh2 * g= bamg2msh(nTh,true); + + delete nTh; + delete oTh; + // Add2StackOfPtr2FreeRC(stack,g);// 07/2008 FH + + return g; + +} + + diff --git a/contrib/bamg/bamg-gmsh.hpp b/contrib/bamg/bamg-gmsh.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f567dda92c6917afe87fa6c2b3d949d516b2e049 --- /dev/null +++ b/contrib/bamg/bamg-gmsh.hpp @@ -0,0 +1,6 @@ +Mesh2 *bamg2msh( bamg::Triangles* tTh,bool renumbering); +bamg::Triangles * msh2bamg(const Mesh2 & Th,double cutoffradian,long * reqedgeslab,int nreqedgeslab); +bamg::Triangles * msh2bamg(const Mesh2 & Th,double cutoffradian, + int nbdfv, int * ndfv,int nbdfe, int * ndfe, + long * reqedgeslab,int nreqedgeslab); +Mesh2 *Bamg(Mesh2 *Thh, double * args,double *mm11,double *mm12,double *mm22); diff --git a/contrib/bamg/bamglib/Mesh2.cpp b/contrib/bamg/bamglib/Mesh2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f99240946710360457a804cd45a4e23cf87d081 --- /dev/null +++ b/contrib/bamg/bamglib/Mesh2.cpp @@ -0,0 +1,5177 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#ifdef __MWERKS__ +#ifdef __INTEL__ +//#pragma global_optimizer off +//#pragma inline_depth(0) +//#pragma optimization_level 2 +#endif +//#pragma inline_depth 0 +#endif +extern bool withrgraphique; +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <time.h> +#include <iostream> +using namespace std; + +#include "Mesh2.h" +#include "QuadTree.h" +#include "SetOfE4.h" + +namespace bamg { + + +#ifdef DEBUG1 +extern int SHOW ; // for debugging +int SHOW = 0; // for debugging + +#endif + +int Triangles::counter = 0; + +Triangles * CurrentTh =0; + +int hinterpole=1; + + +long NbUnSwap =0; +int ForDebugging = 0; +const Direction NoDirOfSearch = Direction(); +#ifndef NDEBUG +inline void MyAssert(int i,char*ex,char * file,long line) +{ + if( i) { + cerr << "Error Assert:" << ex << " in " << file << " line: " << line << endl; +#ifdef NOTFREEFEM + exit(1); +#else + throw(ErrorExec("exit",1000)); +#endif + } +} +#endif + +Int4 AGoodNumberPrimeWith(Int4 n) +{ + const Int4 BigPrimeNumber[] ={ 567890359L, + 567890431L, 567890437L, 567890461L, 567890471L, + 567890483L, 567890489L, 567890497L, 567890507L, + 567890591L, 567890599L, 567890621L, 567890629L , 0}; + + Int4 o = 0; + Int4 pi = BigPrimeNumber[1]; + for (int i=0; BigPrimeNumber[i]; i++) { + Int4 r = BigPrimeNumber[i] % n; + Int4 oo = Min(Min(r,n-r),Min(Abs(n-2*r),Abs(n-3*r))); + if ( o < oo) + o=oo,pi=BigPrimeNumber[i];} + // cout << " AGoodNumberPrimeWith " << n << " " <<pi << " "<< o << endl; + return pi; +} + +class Triangles; +void MeshError(int Err,Triangles *Th){ + cerr << " Fatal error in the meshgenerator " << Err << endl ; +#ifdef NOTFREEFEM + exit(1); +#else + throw(ErrorMesh("Bamg",Err,Th)); +#endif +} + + ostream& operator <<(ostream& f, const Triangle & ta) + { + if(CurrentTh) + f << "[" << CurrentTh->Number(ta) << "::" + << CurrentTh->Number(ta.ns[0]) << "," + << CurrentTh->Number(ta.ns[1]) << "," + << CurrentTh->Number(ta.ns[2]) << "," + << "{" << CurrentTh->Number(ta.at[0]) << " " << ta.aa[0] << "} " + << "{" << CurrentTh->Number(ta.at[1]) << " " << ta.aa[1] << "} " + << "{" << CurrentTh->Number(ta.at[2]) << " " << ta.aa[2] << "} " + << "]" ; + else + f << "[" + << ta.ns[0] << "," + << ta.ns[1] << "," + << ta.ns[2] << "," + << "{" << ta.at[0] << " " << ta.aa[0] << "} " + << "{" << ta.at[1] << " " << ta.aa[1] << "} " + << "{" << ta.at[2] << " " << ta.aa[2] << "} " + << "]" ; + return f;} + +void swap(Triangle *t1,Int1 a1, + Triangle *t2,Int1 a2, + Vertex *s1,Vertex *s2,Icoor2 det1,Icoor2 det2) +{ // swap + // -------------------------------------------------------------- + // Int1 a2=aa[a];// les 2 numero de l arete dans les 2 triangles + // + // sb sb + // / | \ / \ ! + // as1/ | \ /a2 \ ! + // / | \ / t2 \ ! + // s1 /t1 | t2 \s2 --> s1 /___as2___\s2 ! + // \ a1|a2 / \ as1 / + // \ | / \ t1 / + // \ | / as2 \ a1/ + // \ | / \ / + // sa sa + // ------------------------------------------------------------- + int as1 = NextEdge[a1]; + int as2 = NextEdge[a2]; + int ap1 = PreviousEdge[a1]; + int ap2 = PreviousEdge[a2]; +#ifdef DRAWING1 + couleur(0); + t1->Draw(); + t2->Draw(); +#endif +#ifdef DEBUG1 + t1->check(); + t2->check(); +#endif + (*t1)(VerticesOfTriangularEdge[a1][1]) = s2 ; // avant sb + (*t2)(VerticesOfTriangularEdge[a2][1]) = s1 ; // avant sa + // mise a jour des 2 adjacences externes + TriangleAdjacent taas1 = t1->Adj(as1), + taas2 = t2->Adj(as2), + tas1(t1,as1), tas2(t2,as2), + ta1(t1,a1),ta2(t2,a2); +#ifdef DEBUG + assert( ! ta1.Locked()); + assert( ! ta2.Locked()); +#endif + // externe haut gauche + taas1.SetAdj2(ta2, taas1.GetAllFlag_UnSwap()); + // externe bas droite + taas2.SetAdj2(ta1, taas2.GetAllFlag_UnSwap()); + // remove the Mark UnMarkSwap + t1->SetUnMarkUnSwap(ap1); + t2->SetUnMarkUnSwap(ap2); + // interne + tas1.SetAdj2(tas2); + + t1->det = det1; + t2->det = det2; + + t1->SetTriangleContainingTheVertex(); + t2->SetTriangleContainingTheVertex(); +#ifdef DEBUG1 + t1->check(); + t2->check(); +#endif +#ifdef DRAWING1 + couleur(1); + t1->Draw(); + t2->Draw(); +#endif +#ifdef DRAWING1 + if( CurrentTh) + CurrentTh->inquire(); +#endif + +} // end swap + + + + + +Int4 FindTriangle(Triangles &Th, Real8 x, Real8 y, double* a,int & inside) + { + CurrentTh=&Th; + assert(&Th); + I2 I = Th.toI2(R2(Min(Max(Th.pmin.x,x),Th.pmax.x),Min(Max(Th.pmin.y,y),Th.pmax.y))); + Icoor2 dete[3]; + Triangle & tb = *Th.FindTriangleContening(I,dete); + + if (tb.link) + { // internal point in a true triangles + a[0]= (Real8) dete[0]/ tb.det; + a[1]= (Real8) dete[1] / tb.det; + a[2] = (Real8) dete[2] / tb.det; + inside = 1; + return Th.Number(tb); + } + else + { + inside = 0; + double aa,bb; + TriangleAdjacent ta=CloseBoundaryEdgeV2(I,&tb,aa,bb); + int k = ta; + Triangle * tc = ta; + if (!tc->link) + { ta = ta.Adj(); + tc=ta; + k = ta; + Exchange(aa,bb); + assert(tc->link); + } + a[VerticesOfTriangularEdge[k][0]] = aa; + a[VerticesOfTriangularEdge[k][1]] = bb; + a[OppositeVertex[k]] = 1- aa -bb; + return Th.Number(tc); + } + } + + +TriangleAdjacent CloseBoundaryEdge(I2 A,Triangle *t, double &a,double &b) { +// + // cout << " - "; + int k=(*t)(0) ? (( (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1 )) : 0; + int dir=0; + assert(k>=0); + int kkk=0; + Icoor2 IJ_IA,IJ_AJ; + TriangleAdjacent edge(t,OppositeEdge[k]); + for (;;edge = dir >0 ? Next(Adj(Next(edge))) : Previous(Adj(Previous(edge)))) + { + + assert(kkk++<1000); + Vertex &vI = *edge.EdgeVertex(0); + Vertex &vJ = *edge.EdgeVertex(1); + I2 I=vI, J=vJ, IJ= J-I; + IJ_IA = (IJ ,(A-I)); + // cout << A << vI.i << vJ.i << edge << " " << IJ_IA << " dir " << dir <<endl; + if (IJ_IA<0) { + if (dir>0) {a=1;b=0;return edge;}// change of signe => I + else {dir=-1; + continue;}};// go in direction i + IJ_AJ = (IJ ,(J-A)); + if (IJ_AJ<0) { + if(dir<0) {a=0;b=1;return edge;} + else {dir = 1; + continue;}}// go in direction j + double IJ2 = IJ_IA + IJ_AJ; + assert(IJ2); + a= IJ_AJ/IJ2; + b= IJ_IA/IJ2; + // cout<< "CloseBoundaryEdge a = " << a << " b= " << b << endl; + return edge; + } +} + +TriangleAdjacent Triangle::FindBoundaryEdge(int i) const +{ + // turn around the vertex ns[i] also call s +#ifdef DEBUG + register Vertex * s = ns[i]; +#endif + Triangle *t = (Triangle *) this , *ttc; + int k=0,j = EdgesVertexTriangle[i][0],jc; + int exterieur = !link ; + + do + { + int exterieurp = exterieur; + k++; +#ifdef DEBUG + assert( s == & (*t)[VerticesOfTriangularEdge[j][1]] ); +#endif + ttc = t->at[j]; + exterieur = !ttc->link; + if (exterieur+exterieurp == 1) + return TriangleAdjacent(t,j); + jc = NextEdge[t->aa[j]&3]; + t = ttc; + j = NextEdge[jc]; + assert(k<2000); + } while ( (this!= t)); + return TriangleAdjacent(0,0); + +} + + +TriangleAdjacent CloseBoundaryEdgeV2(I2 C,Triangle *t, double &a,double &b) +{ + // walk around the vertex + // version 2 for remove the probleme if we fill the hole + //int bug=1; + // Triangle *torigine = t; + // restart: + // int dir=0; + assert(t->link == 0); + // to have a starting edges + // try the 3 edge bourna-- in case of internal hole + // and choice the best + // + // + // the probleme is in case of the fine and long internal hole + // for exemple neart the training edge of a wing + // + Vertex * s=0,*s1=0, *s0=0; + Icoor2 imax = MaxICoor22; + Icoor2 l0 = imax,l1 = imax; + double dd2 = imax;// infinity + TriangleAdjacent er; + int cas=-2; + for (int j=0;j<3;j++) + { + TriangleAdjacent ta=t->FindBoundaryEdge(j); + if (! (Triangle *) ta) continue; + s0 = ta.EdgeVertex(0); + s1 = ta.EdgeVertex(1); + I2 A = * s0; + I2 B = *ta.EdgeVertex(1); + I2 AB = B-A,AC=C-A,BC=B-C; + Icoor2 ACAC = (AC,AC), BCBC = (BC,BC); + Icoor2 AB2 = Norme2_2(AB); // ||AB||^2 + Icoor2 ABAC = (AB,AC); // AB.AC| + + double d2; + if ( ABAC < 0 ) // DIST A + { + if ( (d2=(double) ACAC) < dd2) + { + // cout << " A " << d2 << " " << dd2; + er = ta; + l0 = ACAC; + l1 = BCBC; + cas = 0; + s = s0; + } + } + else if (ABAC > AB2) // DIST B + { + if ( (d2=(double) BCBC) < dd2) + { + // cout << " B " << d2 << " " << dd2; + dd2 = d2; + er = Adj(ta); // other direction + l0 = BCBC; + l1 = ACAC; + cas = 1; + s = s1; + } + } + else // DIST AB + { + + double det_2 = (double) Det(AB,AC); + det_2 *= det_2; // square of area*2 of triangle ABC + d2 = det_2/ (double) AB2; // hauteur^2 in C of of triangle ABC + // cout << " AB " << d2 << " " << dd2 + // << " " << CurrentTh->Number(ta.EdgeVertex(0)) + // << " " << CurrentTh->Number(ta.EdgeVertex(1)) << " " ; + + if (d2 < dd2) + { + dd2 = d2; + er = ta; + l0 = (AC,AC); + l1 = (BC,BC); + s = 0; + cas = -1; + // cout << " ABAC " << ABAC << " ABAC " << ABAC + // << " AB2 " << AB2 << endl; + b = ((double) ABAC/(double) AB2); + a = 1 - b; + } + } + } + assert(cas !=-2); + // l1 = ||C s1|| , l0 = ||C s0|| + // where s0,s1 are the vertex of the edge er + + if ( s) + { + t=er; + TriangleAdjacent edge(er); + + int kkk=0; + int linkp = t->link == 0; + + Triangle * tt=t=edge=Adj(Previous(edge)); + // cout << CurrentTh->Number(t) << " " << linkp << endl; + do { // loop around vertex s + + assert(edge.EdgeVertex(0)==s && kkk++<10000); + + int link = tt->link == 0; + // cout << CurrentTh->Number(tt) << " " << link << " " << CurrentTh->Number(s) + // << " " << CurrentTh->Number(er.EdgeVertex(0)) + // << " " << CurrentTh->Number(er.EdgeVertex(1)) + // << " " << CurrentTh->Number(edge.EdgeVertex(0)) + // << " " << CurrentTh->Number(edge.EdgeVertex(1)) + // << endl; + if ((link + linkp) == 1) + { // a boundary edge + Vertex * st = edge.EdgeVertex(1); + I2 I=*st; + Icoor2 ll = Norme2_2 (C-I); + if (ll < l1) { // the other vertex is neart + s1=st; + l1=ll; + er = edge; + if(ll<l0) { // change of direction -- + s1=s; + l1=l0; + s=st; + l0=ll; + t=tt; + edge=Adj(edge); + link=linkp; + er = edge; + } + } + } + + linkp=link; + edge=Adj(Previous(edge)); + tt = edge; + } while (t!=tt); + + assert((Triangle *) er); + I2 A((I2)*er.EdgeVertex(0)); + I2 B((I2)*er.EdgeVertex(1)); + I2 AB=B-A,AC=C-A,CB=B-C; + double aa = (double) (AB,AC); + double bb = (double) (AB,CB); + // cout << " " << aa << " " << bb + // << " " << CurrentTh->Number(er.EdgeVertex(0)) + // << " " << CurrentTh->Number(er.EdgeVertex(1)) ; + if (aa<0) a=1,b=0; + else if(bb<0) a=0,b=1; + else + { + a = bb/(aa+bb); + b = aa/(aa+bb); + } + } + + // cout <<" return= " << CurrentTh->Number(er.EdgeVertex(0)) << " " + // << CurrentTh->Number(er.EdgeVertex(1)) << " " << a + // << " " << b <<" " << l0 << " " <<l1 <<endl; + return er; +} + + + +Metric Triangles::MetricAt (const R2 & A) const + { //if ((vertices <= &v) && (vertices < v+nbv)) return v.m; + I2 a = toI2(A); + Icoor2 deta[3]; + Triangle * t =FindTriangleContening(a,deta); + if (t->det <0) { // outside + double ba,bb; + TriangleAdjacent edge= CloseBoundaryEdge(a,t,ba,bb) ; + return Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));} + else { // inside + Real8 aa[3]; + Real8 s = deta[0]+deta[1]+deta[2]; + aa[0]=deta[0]/s; + aa[1]=deta[1]/s; + aa[2]=deta[2]/s; + return Metric(aa,(*t)[0],(*t)[1],(*t)[2]); + } + } + + +void ListofIntersectionTriangles::SplitEdge(const Triangles & Bh, + const R2 &A,const R2 &B,int nbegin) +{ // SplitEdge + // if(SHOW) cout << " splitedge " << A << B << " " << nbegin << endl; + Triangle *tbegin, *t; + + Icoor2 deta[3], deti,detj; + Real8 ba[3]; + int nbt =0,ifirst=-1,ilast; + int i0,i1,i2; + int ocut,i,j,k=-1; + // int OnAVertices =0; + Icoor2 dt[3]; + I2 a = Bh.toI2(A) ,b= Bh.toI2(B);// compute the Icoor a,b + I2 vi,vj; + int iedge =-1;// not a edge + + if(nbegin) {// optimisation + // we suppose knowing the starting triangle + t=tbegin=lIntTria[ilast=(Size-1)].t; + if (tbegin->det>=0) + ifirst = ilast;} + else {// not optimisation + init(); + t=tbegin = Bh.FindTriangleContening(a,deta); + // if(SHOW) cout <<t << " " << Real8(deta[0])/t->det<< " " << Real8(deta[1])/t->det + // << " " << Real8(deta[2])/t->det << endl; + if( t->det>=0) + ilast=NewItem(t,Real8(deta[0])/t->det,Real8(deta[1])/t->det,Real8(deta[2])/t->det); + else + {// find the nearest boundary edge of the vertex A + // find a edge or such normal projection a the edge IJ is on the edge + // <=> IJ.IA >=0 && IJ.AJ >=0 + ilast=ifirst; + double ba,bb; + TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb); + Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1); + NewItem(A,Metric(ba,v0,bb,v1)); + t=edge; + // test if the point b is in the same side + if (det(v0.i,v1.i,b)>=0) { + //cout << " All the edge " << A << B << endl; + TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb); + Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1); + NewItem(A,Metric(ba,v0,bb,v1)); + return; + } + } // find the nearest boundary edge of the vertex A + } // end not optimisation + if (t->det<0) { // outside departure + while (t->det <0) { // intersection boundary edge and a,b, + k=(*t)(0) ? (( (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1 )) : 0; + assert(k>=0); + ocut = OppositeEdge[k]; + i=VerticesOfTriangularEdge[ocut][0]; + j=VerticesOfTriangularEdge[ocut][1]; + vi=(*t)[i]; + vj=(*t)[j]; + deti = bamg::det(a,b,vi); + detj = bamg::det(a,b,vj); + // if(SHOW) { penthickness(3); +// Move(vi);Line(vj);CurrentTh->inquire();penthickness(1); +// cout << Bh.Number(tbegin) << " " << Bh.Number(t) << " i= " << i <<" j= " << j << " k=" << k +// << " deti= " << deti << " detj= " << detj +// << " v = " << Bh.Number((*t)[i]) << (*t)[i].r << " " << Bh.Number((*t)[j]) << (*t)[j].r << endl;} + if (deti>0) // go to i direction on gamma + ocut = PreviousEdge[ocut]; + else if (detj<=0) // go to j direction on gamma + ocut = NextEdge[ocut]; + TriangleAdjacent tadj =t->Adj(ocut); + t = tadj; + iedge= tadj; + if (t == tbegin) { // + double ba,bb; + if (verbosity>7) + cout << " SplitEdge: All the edge " << A << B << nbegin << det(vi,vj,b) + << " deti= " << deti << " detj=" <<detj << endl; + TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb); + Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1); + NewItem(A,Metric(ba,v0,bb,v1)); + return; + /* + cerr << nbegin << det(vi,vj,b) << " deti= " << deti << " detj=" <<detj << endl; + cerr << "SplitEdge on boucle A" << A << " B = " << B << endl; + +#ifdef DRAWING + reffecran(); + Bh.Draw(); + penthickness(5); + Move(A); + Line(B); + penthickness(1); + + Bh.inquire(); + penthickness(5); + Move(A); + Line(B); + penthickness(1); + Bh.inquire(); +#endif + MeshError(997);*/ + } + } // end while (t->det <0) + // theoriticaly we have: deti =<0 and detj>0 + + // computation of barycentric coor + // test if the point b is on size on t + // we revert vi,vj because vi,vj is def in Adj triangle + if ( det(vi,vj,b)>=0) { + if (verbosity>7) + cout << " SplitEdge: all AB outside " << A << B << endl; + t=tbegin; + Real8 ba,bb; + TriangleAdjacent edge=CloseBoundaryEdge(b,t,ba,bb); + NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1))); + return; + } + else + { + k = OppositeVertex[iedge]; + i=VerticesOfTriangularEdge[iedge][0]; + j=VerticesOfTriangularEdge[iedge][1]; + Real8 dij = detj-deti; + assert(i+j+k == 0 + 1 +2); + ba[j] = detj/dij; + ba[i] = -deti/dij; + ba[k] = 0; +// if(SHOW) cout << i << " " << j << " " << k << " " << ba[i] << " " << ba[j] << endl; + ilast=NewItem(t,ba[0],ba[1],ba[2]); } + } // outside departure + + + + // recherche the intersection of [a,b] with Bh Mesh. + // we know a triangle ta contening the vertex a + // we have 2 case for intersection [a,b] with a edge [A,B] of Bh + // 1) the intersection point is in ]A,B[ + // 2) is A or B + // first version --- + for (;;) { + // t->Draw(); + if (iedge < 0) { + i0 =0;i1=1;i2=2; + dt[0] =bamg::det(a,b,(*t)[0]); + dt[1] =bamg::det(a,b,(*t)[1]); + dt[2] =bamg::det(a,b,(*t)[2]);} + else { + i2 = iedge; + i0 = NextEdge[i2]; + i1 = NextEdge[i0]; + dt[VerticesOfTriangularEdge[iedge][0]] = detj;// we revert i,j because + dt[VerticesOfTriangularEdge[iedge][1]] = deti;// we take the Triangle by the other side + dt[iedge] = det(a,b,(*t)[OppositeVertex[iedge]]);} + + // so we have just to see the transition from - to + of the det0..2 on edge of t + // because we are going from a to b + if ((dt[i=VerticesOfTriangularEdge[i0][0]] < 0) && + ( dt[j=VerticesOfTriangularEdge[i0][1]] > 0)) + ocut =i0; + else if ((dt[i=VerticesOfTriangularEdge[i1][0]] < 0) && + (dt[j=VerticesOfTriangularEdge[i1][1]] > 0)) + ocut =i1; + else if ((dt[i=VerticesOfTriangularEdge[i2][0]] < 0) && + (dt[j=VerticesOfTriangularEdge[i2][1]] > 0)) + ocut =i2; + else if ((dt[i=VerticesOfTriangularEdge[i0][0]] == 0) && + ( dt[j=VerticesOfTriangularEdge[i0][1]] > 0)) + ocut =i0; + else if ((dt[i=VerticesOfTriangularEdge[i1][0]] == 0) && + (dt[j=VerticesOfTriangularEdge[i1][1]] > 0)) + ocut =i1; + else if ((dt[i=VerticesOfTriangularEdge[i2][0]] == 0) && + (dt[j=VerticesOfTriangularEdge[i2][1]] > 0)) + ocut =i2; + else if ((dt[i=VerticesOfTriangularEdge[i0][0]] < 0) && + ( dt[j=VerticesOfTriangularEdge[i0][1]] == 0)) + ocut =i0; + else if ((dt[i=VerticesOfTriangularEdge[i1][0]] < 0) && + (dt[j=VerticesOfTriangularEdge[i1][1]] == 0)) + ocut =i1; + else if ((dt[i=VerticesOfTriangularEdge[i2][0]] < 0) && + (dt[j=VerticesOfTriangularEdge[i2][1]] == 0)) + ocut =i2; + else { // On a edge (2 zero) + k =0; + if (dt[0]) ocut=0,k++; + if (dt[1]) ocut=1,k++; + if (dt[2]) ocut=2,k++; + if(k == 1) { + if (dt[ocut] >0) // triangle upper AB + ocut = NextEdge[ocut]; + i= VerticesOfTriangularEdge[ocut][0]; + j= VerticesOfTriangularEdge[ocut][1]; + } + else { + cerr << " Bug Split Edge " << endl; + cerr << " dt[0]= " << dt[0] + << " dt[1]= " << dt[1] + << " dt[2]= "<< dt[2] << endl; + cerr << i0 << " " << i1 << " " << i2 << endl; + cerr << " A = " << A << " B= " << B << endl; + cerr << " Triangle t = " << *t << endl; + cerr << (*t)[0] << (*t)[1] << (*t)[0] << endl; + cerr << " nbt = " << nbt << endl; + MeshError(100);}} + + k = OppositeVertex[ocut]; + + Icoor2 detbij = bamg::det((*t)[i],(*t)[j],b); + + + if (detbij >= 0) { //we find the triangle contening b + dt[0]=bamg::det((*t)[1],(*t)[2],b); + dt[1]=bamg::det((*t)[2],(*t)[0],b); + dt[2]=bamg::det((*t)[0],(*t)[1],b); +#ifdef DEBUG + assert(dt[0] >= 0); + assert(dt[1] >= 0); + assert(dt[2] >= 0); +#endif + Real8 dd = t->det; + NewItem(t,dt[0]/dd,dt[1]/dd,dt[2]/dd); + return ;} + else { // next triangle by adjacent by edge ocut + deti = dt[i]; + detj = dt[j]; + Real4 dij = detj-deti; + ba[i] = detj/dij; + ba[j] = -deti/dij; + ba[3-i-j ] = 0; + ilast=NewItem(t, ba[0],ba[1],ba[2]); + + TriangleAdjacent ta =t->Adj(ocut); + t = ta; + iedge= ta; + if (t->det <= 0) { + double ba,bb; + TriangleAdjacent edge=CloseBoundaryEdge(b,t,ba,bb); + NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1))); + // cout << " return " << ba << " " << bb << endl; + // ajoute le 03 frev 1997 par F. hecht + return; + } + }// we go outside of omega + } // for(;;) + + +} // routine SplitEdge + + +int ListofIntersectionTriangles::NewItem(Triangle * tt,Real8 d0,Real8 d1,Real8 d2) { + register int n; + R2 x(0,0); + if ( d0) x = (*tt)[0].r * d0; + if ( d1) x = x + (*tt)[1].r * d1; + if ( d2) x = x + (*tt)[2].r * d2; + // newer add same point + if(!Size || Norme2_2(lIntTria[Size-1].x-x)) { + if (Size==MaxSize) ReShape(); + lIntTria[Size].t=tt; + lIntTria[Size].bary[0]=d0; + lIntTria[Size].bary[1]=d1; + lIntTria[Size].bary[2]=d2; + lIntTria[Size].x = x; + Metric m0,m1,m2; + register Vertex * v; + if ((v=(*tt)(0))) m0 = v->m; + if ((v=(*tt)(1))) m1 = v->m; + if ((v=(*tt)(2))) m2 = v->m; + lIntTria[Size].m = Metric(lIntTria[Size].bary,m0,m1,m2); +#ifdef DEBUG1 + if(SHOW) { cout << "SHOW ++ NewItem =" << Size << x ; + cout << " " << d0 << " " << d1 << " " << d2 <<endl;} +#endif + n=Size++;} + else n=Size-1; + return n; +} +int ListofIntersectionTriangles::NewItem(R2 A,const Metric & mm) { + register int n; + if(!Size || Norme2_2(lIntTria[Size-1].x-A)) { + if (Size==MaxSize) ReShape(); + lIntTria[Size].t=0; + lIntTria[Size].x=A; + lIntTria[Size].m=mm; +#ifdef DEBUG1 + if (SHOW) cout << "SHOW ++ NewItem A" << Size << A << endl; +#endif + n=Size++; + } + else n=Size-1; + return n; +} + +Real8 ListofIntersectionTriangles::Length() +{ + // cout << " n= " << Size << ":" ; + assert(Size>0); + // computation of the length + R2 C; + Metric Mx,My; + int ii,jj; + R2 x,y,xy; + + SegInterpolation *SegI=lSegsI; + SegI=lSegsI; + lSegsI[NbSeg].last=Size;// improvement + + int EndSeg=Size; + + y = lIntTria[0].x; + Real8 sxy, s = 0; + lIntTria[0].s =0; + SegI->lBegin=s; + + for (jj=0,ii=1;ii<Size;jj=ii++) + { + // seg jj,ii + x=y; + y = lIntTria[ii].x; + xy = y-x; + Mx = lIntTria[ii].m; + My = lIntTria[jj].m; + // Real8 &sx= lIntTria[ii].sp; // previous seg + // Real8 &sy= lIntTria[jj].sn; // next seg + // sx = Mx(xy); + // sy = My(xy); + // sxy = (Mx(xy)+ My(xy))/2.0; + sxy = LengthInterpole(Mx,My,xy); + s += sxy; + lIntTria[ii].s = s; + if (ii == EndSeg) + SegI->lEnd=s, + SegI++, + EndSeg=SegI->last, + SegI->lBegin=s; + + // cout << ii << " " << jj << x<< y <<xy << s << lIntTria[ii].m ; + } + len = s; + SegI->lEnd=s; + + // cout << " len= " << s << endl; + return s; +} + +Int4 ListofIntersectionTriangles::NewPoints(Vertex * vertices,Int4 & nbv,Int4 nbvx) +{ + + const Int4 nbvold = nbv; + Real8 s = Length(); + if (s < 1.5 ) return 0; + ////////////////////// + int ii = 1 ; + R2 y,x; + Metric My,Mx ; + Real8 sx =0,sy; + int nbi = Max(2,(int) (s+0.5)); + Real8 sint = s/nbi; + Real8 si = sint; + + int EndSeg=Size; + SegInterpolation *SegI=0; + if (NbSeg) + SegI=lSegsI,EndSeg=SegI->last; + + for (int k=1;k<nbi;k++) + { + while ((ii < Size) && ( lIntTria[ii].s <= si )) + if (ii++ == EndSeg) + SegI++,EndSeg=SegI->last; + + int ii1=ii-1; + x =lIntTria[ii1].x; + sx =lIntTria[ii1].s; + Metric Mx=lIntTria[ii1].m; +#ifdef DEBUG + double lx = lIntTria[ii-1].sn; +#endif + y =lIntTria[ii].x; + sy =lIntTria[ii].s; + Metric My=lIntTria[ii].m; +#ifdef DEBUG + double ly =lIntTria[ii].sp; + assert( sx <= si); + assert( si <= sy); + assert( sy != sx); +#endif + + Real8 lxy = sy-sx; + Real8 cy = abscisseInterpole(Mx,My,y-x,(si-sx)/lxy); + + R2 C; + Real8 cx = 1-cy; + C = SegI ? SegI->F(si): x * cx + y *cy; + + si += sint; + if ( nbv<nbvx) { + vertices[nbv].r = C; + vertices[nbv++].m = Metric(cx,lIntTria[ii-1].m,cy,lIntTria[ii].m); + if((verbosity/100%10)==2) + cout << " -- Add point " << nbv-1 << " " << vertices[nbv-1] << " " << vertices[nbv-1].m << endl; + +#ifdef DEBUG + if(k>1) { + R2 AB = vertices[nbv-2].r - vertices[nbv-1].r ; + Real8 dp = LengthInterpole(vertices[nbv-2].m,vertices[nbv-1].m,AB); + if (dp > 1.6) { + cerr << "PB calcul new Int. points trop loin l=" << dp << " v=" << nbv-1 << " " << nbv-2 <<Mx<<My<<y-x << endl; + } + } +#endif + } + else return nbv-nbvold; + } + return nbv-nbvold; +} + +int SwapForForcingEdge(Vertex * & pva ,Vertex * & pvb , + TriangleAdjacent & tt1,Icoor2 & dets1, Icoor2 & detsa,Icoor2 & detsb, int & NbSwap) +{ // l'arete ta coupe l'arete pva pvb + // de cas apres le swap sa coupe toujours + // on cherche l'arete suivante + // on suppose que detsa >0 et detsb <0 + // attention la routine echange pva et pvb + + if(tt1.Locked()) return 0; // frontiere croise + + TriangleAdjacent tt2 = Adj(tt1); + Triangle *t1=tt1,*t2=tt2;// les 2 triangles adjacent + Int1 a1=tt1,a2=tt2;// les 2 numero de l arete dans les 2 triangles + assert ( a1 >= 0 && a1 < 3 ); + + Vertex & sa= (* t1)[VerticesOfTriangularEdge[a1][0]]; + Vertex & s1= (*t1)[OppositeVertex[a1]]; + Vertex & s2= (*t2)[OppositeVertex[a2]]; + + + Icoor2 dets2 = det(*pva,*pvb,s2); + +#ifdef DEBUG + Vertex & sb= (*t1)[VerticesOfTriangularEdge[a1][1]]; + Icoor2 wdets1 = det(*pva,*pvb,s1); + Icoor2 wdetsa = det(*pva,*pvb,sa); + Icoor2 wdetsb = det(*pva,*pvb,sb); + assert(wdets1 == dets1); + assert(wdetsa == detsa); + assert(wdetsb == detsb); +#endif + + Icoor2 det1=t1->det , det2=t2->det ; +#ifdef DEBUG + assert(det1>0 && det2 >0); + Icoor2 ddet1 = det((*t1)[0],(*t1)[1],(*t1)[2]); + Icoor2 ddet2 = det((*t2)[0],(*t2)[1],(*t2)[2]); + if ((det1 != ddet1) || (det2 != ddet2) ) + { + assert(det1 == ddet1); + assert(det2 == ddet2); + } + Icoor2 detvasasb = det(*pva,sa,sb); + Icoor2 detvbsasb = det(*pvb,sa,sb); + if ( CurrentTh && ! ( ( (detvasasb <= 0) && (detvbsasb >= 0)) || ( (detvasasb >= 0) && (detvbsasb <= 0)))) + { + cout << " detvasasb =" << detvasasb << "detvbsasb = " << detvbsasb + << " " << pva << " " << pvb << " " <<CurrentTh <<endl; +#ifdef DRAWING1 + reffecran(); + CurrentTh->Draw(); + penthickness(10); + pva->MoveTo();pvb->LineTo(); + penthickness(1); + CurrentTh->inquire(); +#endif + } + assert( ( (detvasasb <= 0) && (detvbsasb >= 0)) || ( (detvasasb >= 0) && (detvbsasb <= 0))); +#endif + + Icoor2 detT = det1+det2; + assert((det1>0 ) && (det2 > 0)); + assert ( (detsa < 0) && (detsb >0) ); // [a,b] cut infinite line va,bb + Icoor2 ndet1 = bamg::det(s1,sa,s2); + Icoor2 ndet2 = detT - ndet1; + + int ToSwap =0; //pas de swap + if ((ndet1 >0) && (ndet2 >0)) + { // on peut swaper + if ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0)) + ToSwap =1; + else // swap alleatoire + if (BinaryRand()) + ToSwap =2; + } +#ifdef DEBUG + if (ForDebugging) { + cerr << "swap = " << ToSwap << " ndet1 " << ndet1 << ", ndet2 " << ndet2 << "det1 " << det1 << " det2 " << det2 + << " if1 = " << ((ndet1 >0) && (ndet2 >0)) + << " if2 = " << ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0)) << endl; +#ifdef DRAWING + couleur(0); + t1->Draw(); + t2->Draw(); +#endif + } +#endif + if (ToSwap) NbSwap++, + bamg::swap(t1,a1,t2,a2,&s1,&s2,ndet1,ndet2); + +#ifdef DEBUG + if (ForDebugging) { +#ifdef DRAWING + couleur(4); + t1->Draw(); + t2->Draw(); + rattente(1); +#endif + } +#endif + int ret=1; + + if (dets2 < 0) {// haut + dets1 = ToSwap ? dets1 : detsa ; + detsa = dets2; + tt1 = Previous(tt2) ;} + else if (dets2 > 0){// bas + dets1 = ToSwap ? dets1 : detsb ; + detsb = dets2; + //xxxx tt1 = ToSwap ? tt1 : Next(tt2); + if(!ToSwap) tt1 = Next(tt2); + } + else { // changement de sens + if (ForDebugging) cout << "changement de sens" << endl; + ret = -1; + Exchange(pva,pvb); + Exchange(detsa,detsb); + Exchange(dets1,dets2); + Exchange(tt1,tt2); + dets1=-dets1; + dets2=-dets2; + detsa=-detsa; + detsb=-detsb; + + if (ToSwap) + if (dets2 < 0) {// haut + dets1 = (ToSwap ? dets1 : detsa) ; + detsa = dets2; + tt1 = Previous(tt2) ;} + else if (dets2 > 0){// bas + dets1 = (ToSwap ? dets1 : detsb) ; + detsb = dets2; + if(!ToSwap) tt1 = Next(tt2); + } + else {// on a fin ??? + tt1 = Next(tt2); + ret =0;} + + } + return ret; +} + +int ForceEdge(Vertex &a, Vertex & b,TriangleAdjacent & taret) +{ +#ifdef DEBUG + restart: // for debug +#endif + int NbSwap =0; + assert(a.t && b.t); // the 2 vertex is in a mesh + int k=0; + taret=TriangleAdjacent(0,0); // erreur + + TriangleAdjacent tta(a.t,EdgesVertexTriangle[a.vint][0]); + Vertex *v1, *v2 = tta.EdgeVertex(0),*vbegin =v2; + // we turn around a in the direct sens + + Icoor2 det2 = v2 ? det(*v2,a,b): -1 , det1; + if(v2) // normal case + det2 = det(*v2,a,b); + else { // no chance infini vertex try the next + tta= Previous(Adj(tta)); + v2 = tta.EdgeVertex(0); + vbegin =v2; + assert(v2); + det2 = det(*v2,a,b); + // cout << " No Change try the next" << endl; + } + +#ifdef DRAWING1 + a.MoveTo();b.LineTo(); +#endif + + while (v2 != &b) { + TriangleAdjacent tc = Previous(Adj(tta)); + v1 = v2; + v2 = tc.EdgeVertex(0); + det1 = det2; +#ifdef DEBUG + assert( v1 == tta.EdgeVertex(0)); + assert( &a == tc.EdgeVertex(1) ); +#endif + det2 = v2 ? det(*v2,a,b): det2; + + if((det1 < 0) && (det2 >0)) { + // try to force the edge + Vertex * va = &a, *vb = &b; + tc = Previous(tc); + assert ( v1 && v2); + Icoor2 detss = 0,l=0,ks; + // cout << "Real ForcingEdge " << *va << *vb << detss << endl; +#ifdef DEBUG + Icoor2 dettt1 = det(*v1,a,b); + Icoor2 dettt2 = det(*v2,a,b); + + if (!(dettt1==det1 && dettt2==det2)) + { + assert(ForDebugging==0); + ForDebugging=1; + goto restart; + } + +#endif + while ((ks=SwapForForcingEdge( va, vb, tc, detss, det1,det2,NbSwap))) + if(l++ > 10000000) { + cerr << " Loop in forcing Egde AB" + <<"\n vertex A " << a + <<"\n vertex B " << b + <<"\n nb de swap " << NbSwap + <<"\n nb of try swap too big = " << l << " gearter than " << 1000000 << endl; + + if ( CurrentTh ) + cerr << " vertex number " << CurrentTh->Number(a) << " " << CurrentTh->Number(b) << endl; +#ifdef DEBUG + ForDebugging = 1; +#endif +#ifdef DRAWING1 + if ( CurrentTh ) { + reffecran(); + couleur(6); + CurrentTh->Draw(); + couleur(1); + penthickness(10); + a.MoveTo();b.LineTo(); + penthickness(1); + CurrentTh->inquire(); + couleur(6); + l=0; + reffecran(); + while (ks=SwapForForcingEdge( va, vb, tc, detss, det1,det2,NbSwap) && (l++ < 1000)) + cerr << " " << CurrentTh->Number(tc.EdgeVertex(0))<<" " <<CurrentTh->Number(tc.EdgeVertex(1)) << " "; + } +#endif + MeshError(990); + } + Vertex *aa = tc.EdgeVertex(0), *bb = tc.EdgeVertex(1); + if (( aa == &a ) && (bb == &b) || (bb == &a ) && (aa == &b)) { + tc.SetLock(); + a.Optim(1,0); + b.Optim(1,0); + taret = tc; + return NbSwap; + } + else + { + taret = tc; + return -2; // error boundary is crossing +/* cerr << "Fatal Error boundary is crossing "; + if(CurrentTh) + { + cerr << " edge: [" << CurrentTh->Number(a) << ", " << CurrentTh->Number(b) << " ] and [ "; + cerr << CurrentTh->Number(aa) << " " << CurrentTh->Number(bb) << " ] " << endl; + } + MeshError(991); +*/ + } + } + tta = tc; + assert(k++<2000); + if ( vbegin == v2 ) return -1;// error + } + + tta.SetLock(); + taret=tta; + a.Optim(1,0); + b.Optim(1,0); + return NbSwap; +} + + +int Triangle::swap(Int2 a,int koption){ +#ifdef DEBUG + if(a &4 ) return 0;// arete lock + int munswap1 = a/4; + a &=3; +#else + if(a/4 !=0) return 0;// arete lock or MarkUnSwap +#endif + + register Triangle *t1=this,*t2=at[a];// les 2 triangles adjacent + register Int1 a1=a,a2=aa[a];// les 2 numero de l arete dans les 2 triangles +#ifdef DEBUG + if(a2 & 4) return 0; // arete lock + int munswap2 = a2/4; + a2 &= 3; +#else + if(a2/4 !=0) return 0; // arete lock or MarkUnSwap +#endif + + register Vertex *sa=t1->ns[VerticesOfTriangularEdge[a1][0]]; + register Vertex *sb=t1->ns[VerticesOfTriangularEdge[a1][1]]; + register Vertex *s1=t1->ns[OppositeVertex[a1]]; + register Vertex *s2=t2->ns[OppositeVertex[a2]]; + +#ifdef DEBUG + assert ( a >= 0 && a < 3 ); +#endif + + Icoor2 det1=t1->det , det2=t2->det ; + Icoor2 detT = det1+det2; + Icoor2 detA = Abs(det1) + Abs(det2); + Icoor2 detMin = Min(det1,det2); + + int OnSwap = 0; + // si 2 triangle infini (bord) => detT = -2; + if (sa == 0) {// les deux triangles sont frontieres + det2=bamg::det(s2->i,sb->i,s1->i); + OnSwap = det2 >0;} + else if (sb == 0) { // les deux triangles sont frontieres + det1=bamg::det(s1->i,sa->i,s2->i); + OnSwap = det1 >0;} + else if(( s1 != 0) && (s2 != 0) ) { + det1 = bamg::det(s1->i,sa->i,s2->i); + det2 = detT - det1; + OnSwap = (Abs(det1) + Abs(det2)) < detA; + + Icoor2 detMinNew=Min(det1,det2); + // if (detMin<0 && (Abs(det1) + Abs(det2) == detA)) OnSwap=BinaryRand();// just for test + if (! OnSwap &&(detMinNew>0)) { + OnSwap = detMin ==0; + if (! OnSwap) { + int kopt = koption; + while (1) + if(kopt) { + // critere de Delaunay pure isotrope + register Icoor2 xb1 = sb->i.x - s1->i.x, + x21 = s2->i.x - s1->i.x, + yb1 = sb->i.y - s1->i.y, + y21 = s2->i.y - s1->i.y, + xba = sb->i.x - sa->i.x, + x2a = s2->i.x - sa->i.x, + yba = sb->i.y - sa->i.y, + y2a = s2->i.y - sa->i.y; + register double + cosb12 = double(xb1*x21 + yb1*y21), + cosba2 = double(xba*x2a + yba*y2a) , + sinb12 = double(det2), + sinba2 = double(t2->det); + + + // angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2) + OnSwap = ((double) cosb12 * (double) sinba2) < ((double) cosba2 * (double) sinb12); +// if(CurrentTh) +// cout << "swap " << CurrentTh->Number(sa) << " " << CurrentTh->Number(sb) << " " ; +// cout << cosb12 << " " << sinba2 << " " << cosba2 << " " << sinb12 +// << " Onswap = " << OnSwap << endl; + break; + } + else + { + // critere de Delaunay anisotrope + Real8 som; + I2 AB=(I2) *sb - (I2) *sa; + I2 MAB2=((I2) *sb + (I2) *sa); + R2 MAB(MAB2.x*0.5,MAB2.y*0.5); + I2 A1=(I2) *s1 - (I2) *sa; + I2 D = (I2) * s1 - (I2) * sb ; + R2 S2(s2->i.x,s2->i.y); + R2 S1(s1->i.x,s1->i.y); + { + Metric M=s1->m; + R2 ABo = M.Orthogonal(AB); + R2 A1o = M.Orthogonal(A1); + // (A+B)+ x ABo = (S1+B)/2+ y A1 + // ABo x - A1o y = (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 + double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x); + double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2 + if (Abs(d) > dd*1.e-3) { + R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d)); + som = M(C - S2)/M(C - S1); + } else + {kopt=1;continue;} + + } + { + Metric M=s2->m; + R2 ABo = M.Orthogonal(AB); + R2 A1o = M.Orthogonal(A1); + // (A+B)+ x ABo = (S1+B)/2+ y A1 + // ABo x - A1o y = (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 + double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x); + double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2 + if(Abs(d) > dd*1.e-3) { + R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d)); + som += M(C - S2)/M(C - S1); + } else + {kopt=1;continue;} + } + OnSwap = som < 2; + break; + } + + } // OnSwap + } // (! OnSwap &&(det1 > 0) && (det2 > 0) ) + } +#ifdef DEBUG1 + if (OnSwap && ( munswap1 || munswap2)) { + cout << " erreur Mark unswap T " << CurrentTh->Number(t1) << " " << CurrentTh->Number(t2) << endl + << *t1 << endl + << *t2 << endl; + return 0; + } +#endif + if( OnSwap ) + bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2); + else { + NbUnSwap ++; + t1->SetMarkUnSwap(a1); + } + return OnSwap; +} + +Real8 Vertex::Smoothing(Triangles & Th,const Triangles & BTh,Triangle * & tstart ,Real8 omega) +{ +#ifdef DEBUG + register Int4 NbSwap =0; +#endif + register Vertex * s = this; + Vertex &vP = *s,vPsave=vP; + // if (vP.on) return 0;// Don't move boundary vertex + + register Triangle * tbegin= t , *tria = t , *ttc; + + register int k=0,kk=0,j = EdgesVertexTriangle[vint][0],jc; + R2 P(s->r),PNew(0,0); + // cout << BTh.quadtree << " " << BTh.quadtree->root << endl; + // assert(BTh.quadtree && BTh.quadtree->root); + do { + k++; + +#ifdef DEBUG + assert( s == & (*tria)[VerticesOfTriangularEdge[j][1]] ); + assert( tria->det >0); +#endif + if (!tria->Hidden(j)) + { + Vertex &vQ = (*tria)[VerticesOfTriangularEdge[j][0]]; + + R2 Q = vQ,QP(P-Q); + Real8 lQP = LengthInterpole(vP,vQ,QP); + PNew += Q+QP/Max(lQP,1e-20); + kk ++; + } + ttc = tria->TriangleAdj(j); + jc = NextEdge[tria->NuEdgeTriangleAdj(j)]; + tria = ttc; + j = NextEdge[jc]; + assert(k<2000); + } while ( tbegin != tria); + if (kk<4) return 0; + PNew = PNew/(Real8)kk; + R2 Xmove((PNew-P)*omega); + PNew = P+Xmove; + Real8 delta=Norme2_2(Xmove); + + + // + Icoor2 deta[3]; + I2 IBTh = BTh.toI2(PNew); + + tstart=BTh.FindTriangleContening(IBTh,deta,tstart); + + if (tstart->det <0) + { // outside + double ba,bb; + TriangleAdjacent edge= CloseBoundaryEdge(IBTh,tstart,ba,bb) ; + tstart = edge; + vP.m= Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1)); + } + else + { // inside + Real8 aa[3]; + Real8 s = deta[0]+deta[1]+deta[2]; + aa[0]=deta[0]/s; + aa[1]=deta[1]/s; + aa[2]=deta[2]/s; + vP.m = Metric(aa,(*tstart)[0],(*tstart)[1],(*tstart)[2]); + } + + // recompute the det of the triangle + vP.r = PNew; + + vP.i = Th.toI2(PNew); + + Vertex vPnew = vP; + + int ok=1; + int loop=1; + k=0; + while (ok) + { + ok =0; + do { + k++; + double detold = tria->det; + tria->det = bamg::det( (*tria)[0],(*tria)[1] ,(*tria)[2]); + if (loop) + { + Vertex *v0,*v1,*v2,*v3; + if (tria->det<0) ok =1; + else if (tria->Quadrangle(v0,v1,v2,v3)) + { + vP = vPsave; + Real8 qold =QuadQuality(*v0,*v1,*v2,*v3); + vP = vPnew; + Real8 qnew = QuadQuality(*v0,*v1,*v2,*v3); + if (qnew<qold) ok = 1; + } + else if ( (double)tria->det < detold/2 ) ok=1; + + } + tria->SetUnMarkUnSwap(0); + tria->SetUnMarkUnSwap(1); + tria->SetUnMarkUnSwap(2); + ttc = tria->TriangleAdj(j); + jc = NextEdge[tria->NuEdgeTriangleAdj(j)]; + tria = ttc; + j = NextEdge[jc]; + assert(k<2000); + } while ( tbegin != tria); + if (ok && loop) vP=vPsave; // no move + loop=0; + } + return delta; +} + + + + +void Triangles::Add( Vertex & s,Triangle * t, Icoor2 * det3) +{ + // ------------------------------------------- + // s2 + // ! + // /|\ ! + // / | \ ! + // / | \ ! + // tt1 / | \ tt0 ! + // / |s \ ! + // / . \ ! + // / . ` \ ! + // / . ` \ ! + // ---------------- ! + // s0 tt2 s1 + //-------------------------------------------- + + Triangle * tt[3]; // the 3 new Triangles + Vertex &s0 = (* t)[0], &s1=(* t)[1], &s2=(* t)[2]; + Icoor2 det3local[3]; + int infv = &s0 ? (( &s1 ? ( &s2 ? -1 : 2) : 1 )) : 0; + // infv = ordre of the infini vertex (null) + register int nbd0 =0; // number of zero det3 + register int izerodet=-1,iedge; // izerodet = egde contening the vertex s + Icoor2 detOld = t->det; + + if ( ( infv <0 ) && (detOld <0) || ( infv >=0 ) && (detOld >0) ) + { + cerr << " infv " << infv << " det = " << detOld << endl; + cerr << Number(s) << " "<< Number(s0) << " " + << Number(s1) << " " << Number(s2) << endl; + MeshError(3); + } + + // if det3 do not exist then constuct det3 + if (!det3) { + det3 = det3local; // alloc + if ( infv<0 ) { + det3[0]=bamg::det(s ,s1,s2); + det3[1]=bamg::det(s0,s ,s2); + det3[2]=bamg::det(s0,s1,s );} + else { + // one of &s1 &s2 &s0 is NULL so (&si || &sj) <=> !&sk + det3[0]= &s0 ? -1 : bamg::det(s ,s1,s2) ; + det3[1]= &s1 ? -1 : bamg::det(s0,s ,s2) ; + det3[2]= &s2 ? -1 : bamg::det(s0,s1,s ) ;}} + + + if (!det3[0]) izerodet=0,nbd0++; + if (!det3[1]) izerodet=1,nbd0++; + if (!det3[2]) izerodet=2,nbd0++; + + if (nbd0 >0 ) // point s on a egde or on a vertex + if (nbd0 == 1) { + iedge = OppositeEdge[izerodet]; + TriangleAdjacent ta = t->Adj(iedge); + +#ifdef DEBUG1 + cout << " the point " << Number(s) << " is the edge " << izerodet + << " of " << Number(t) << " det3 = " + << det3[0] << " " << det3[1] << " " << det3[2] << " " << endl; + cout << " ta = " << ta << "ta->det =" << ((Triangle*) ta)->det + << " "<< t->det<< endl; +#endif + + // the point is on the edge + // if the point is one the boundary + // add the point in outside part + if ( t->det >=0) { // inside triangle + if ((( Triangle *) ta)->det < 0 ) { + // add in outside triangle + Add(s,( Triangle *) ta); + return;} + }} + else { + cerr << " bug " << nbd0 <<endl; + cerr << " Bug double points in " << endl ; + cerr << " s = " << Number(s) << " " << s << endl; + cerr << " s0 = "<< Number(s0) << " " << s0 << endl; + cerr << " s1 = "<< Number(s1) << " " << s1 << endl; + cerr << " s2 = "<< Number(s2) << " " << s2 << endl; + MeshError(5,this);} + + // remove de MarkUnSwap edge + t->SetUnMarkUnSwap(0); + t->SetUnMarkUnSwap(1); + t->SetUnMarkUnSwap(2); + + tt[0]= t; + tt[1]= &triangles[nbt++]; + tt[2]= &triangles[nbt++]; + + if (nbt>nbtx) { + cerr << " No enougth triangles " << endl; + MeshError(999,this); + } + + *tt[1]= *tt[2]= *t; +// gestion of the link + tt[0]->link=tt[1]; + tt[1]->link=tt[2]; + + (* tt[0])(OppositeVertex[0])=&s; + (* tt[1])(OppositeVertex[1])=&s; + (* tt[2])(OppositeVertex[2])=&s; + + tt[0]->det=det3[0]; + tt[1]->det=det3[1]; + tt[2]->det=det3[2]; + + // update adj des triangles externe + tt[0]->SetAdjAdj(0); + tt[1]->SetAdjAdj(1); + tt[2]->SetAdjAdj(2); + // update des adj des 3 triangle interne + const int i0 = 0; + const int i1= NextEdge[i0]; + const int i2 = PreviousEdge[i0]; + + tt[i0]->SetAdj2(i2,tt[i2],i0); + tt[i1]->SetAdj2(i0,tt[i0],i1); + tt[i2]->SetAdj2(i1,tt[i1],i2); + + tt[0]->SetTriangleContainingTheVertex(); + tt[1]->SetTriangleContainingTheVertex(); + tt[2]->SetTriangleContainingTheVertex(); + + + // swap if the point s is on a edge + if(izerodet>=0) { + // cout << " the point s is on a edge =>swap " << iedge << " " << *tt[izerodet] << endl; + int rswap =tt[izerodet]->swap(iedge); + + if (!rswap) + { + cout << " Pb swap the point s is on a edge =>swap " << iedge << " " << *tt[izerodet] << endl; +#ifdef DRAWING + if( CurrentTh && withrgraphique) + { + reffecran(); + + DrawMark(s.r); + CurrentTh->inquire(); + DrawMark(s.r); + rattente(1); + } +#endif + } + assert(rswap); + } + +#ifdef DEBUG + tt[0]->check(); + tt[1]->check(); + tt[2]->check(); +#endif +#ifdef DRAWING1 + tt[0]->Draw(); + tt[1]->Draw(); + tt[2]->Draw(); +#endif + +} + + +Int4 Triangles::SplitInternalEdgeWithBorderVertices() +{ + Int4 NbSplitEdge=0; + SetVertexFieldOn(); + Int4 it; + Int4 nbvold=nbv; + for (it=0;it<nbt;it++) + { + Triangle &t=triangles[it]; + if (t.link) + for (int j=0;j<3;j++) + if(!t.Locked(j) && !t.Hidden(j)){ + Triangle &tt = *t.TriangleAdj(j); + if ( &tt && tt.link && it < Number(tt)) + { // an internal edge + Vertex &v0 = t[VerticesOfTriangularEdge[j][0]]; + Vertex &v1 = t[VerticesOfTriangularEdge[j][1]]; + if (v0.on && v1.on) + { + R2 P= ((R2) v0 + (R2) v1)*0.5; + if ( nbv<nbvx) { + vertices[nbv].r = P; + vertices[nbv++].m = Metric(0.5,v0.m,0.5,v1.m); + vertices[nbv].ReferenceNumber=0; + vertices[nbv].DirOfSearch = NoDirOfSearch ; + } + NbSplitEdge++; + if (verbosity>7) + cout <<" Internal edge with two vertices on boundary" + << Number(v0) << " " << Number(v1) << " by " << endl; + } + } + } + } + ReMakeTriangleContainingTheVertex(); + if (nbvold!=nbv) + { + Int4 iv = nbvold; + Int4 NbSwap = 0; + Icoor2 dete[3]; + for (Int4 i=nbvold;i<nbv;i++) + {// for all the new point + Vertex & vi = vertices[i]; + vi.i = toI2(vi.r); + vi.r = toR2(vi.i); + // if (!quadtree->ToClose(vi,seuil,hi,hj)) { + // a good new point + vi.ReferenceNumber=0; + vi.DirOfSearch =NoDirOfSearch; + // cout << " Add " << Number(vi) << " " << vi + // << " " << Number(vi) << " <--> " << Number(vi) <<endl; + Triangle *tcvi = FindTriangleContening(vi.i,dete); + if (tcvi && !tcvi->link) { + cout << i << " PB insert point " << Number(vi) << vi << Number(vi) + << " tcvi = " << tcvi << " " << tcvi->link << endl; + cout << (*tcvi)[1] << (*tcvi)[2] << endl; + tcvi = FindTriangleContening(vi.i,dete); + cout << (*tcvi)[1] << (*tcvi)[2] << endl; +#ifdef DRAWING1 + inquire(); + penthickness(5); + DrawMark(vi.r); + penthickness(1); + inquire(); +#endif + + MeshError(1001,this); + } + + + quadtree->Add(vi); +#ifdef DRAWING1 + DrawMark(vi.r); +#endif + assert (tcvi && tcvi->det >= 0) ;// internal + Add(vi,tcvi,dete); + NbSwap += vi.Optim(1); + iv++; + // } + } + if (verbosity>3) + { + cout << " Nb Of New Point " << iv ; + cout << " Nb swap = " << NbSwap << " to split internal edges with border vertices" ;} + + nbv = iv; + } + if (NbSplitEdge > nbv-nbvold) + cout << " Warning not enough vertices to split all internal edges " << endl + << " we lost " << NbSplitEdge - ( nbv-nbvold) << " Edges Sorry " << endl; + if (verbosity>2) + cout << "SplitInternalEdgeWithBorderVertices: Number of splited edge " << NbSplitEdge << endl; + return NbSplitEdge; +} +Int4 Triangles::InsertNewPoints(Int4 nbvold,Int4 & NbTSwap) + { + Real8 seuil= 1.414/2 ;// for two close point + Int4 i; + // insertion part --- + + const Int4 nbvnew = nbv-nbvold; + if (verbosity>5) + cout << " Try to Insert the " <<nbvnew<< " new points " << endl; + Int4 NbSwap=0; + Icoor2 dete[3]; + + // construction d'un ordre aleatoire + if (! nbvnew) + return 0; + if (nbvnew) { + const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv) ; + Int4 k3 = rand()%nbvnew ; + for (Int4 is3=0; is3<nbvnew; is3++) { + register Int4 j = nbvold +(k3 = (k3 + PrimeNumber)% nbvnew); + register Int4 i = nbvold+is3; + ordre[i]= vertices + j; + ordre[i]->ReferenceNumber=i; + } + // be carefull + Int4 iv = nbvold; + for (i=nbvold;i<nbv;i++) + {// for all the new point + Vertex & vi = *ordre[i]; + vi.i = toI2(vi.r); + vi.r = toR2(vi.i); + Real4 hx,hy; + vi.m.Box(hx,hy); + Icoor1 hi=(Icoor1) (hx*coefIcoor),hj=(Icoor1) (hy*coefIcoor); + if (!quadtree->ToClose(vi,seuil,hi,hj)) + { + // a good new point + Vertex & vj = vertices[iv]; + Int4 j = vj.ReferenceNumber; + assert( &vj== ordre[j]); + if(i!=j) + { // for valgring + Exchange(vi,vj); + Exchange(ordre[j],ordre[i]); + } + vj.ReferenceNumber=0; + // cout << " Add " << Number(vj) << " " << vj + // << " " << Number(vi) << " <--> " << Number(vj) <<endl; + Triangle *tcvj = FindTriangleContening(vj.i,dete); + if (tcvj && !tcvj->link) + { + cerr << i << " PB insert point " << Number(vj) << vj << Number(vi) + << " tcvj = " << tcvj << " " << tcvj->link << endl; + cerr << (*tcvj)[1] << (*tcvj)[2] << endl; + tcvj = FindTriangleContening(vj.i,dete); + cout << (*tcvj)[1] << (*tcvj)[2] << endl; +#ifdef DRAWING1 + inquire(); + penthickness(5); + DrawMark(vj.r); + penthickness(1); + + inquire(); +#endif + + MeshError(1001,this); + } + + + quadtree->Add(vj); +#ifdef DRAWING1 + DrawMark(vj.r); +#endif + assert (tcvj && tcvj->det >= 0) ;// internal + Add(vj,tcvj,dete); + NbSwap += vj.Optim(1); + iv++; + } + } + if (verbosity>3) { + cout << " Nb Of New Point " << iv << " Nb Of To close Points " << nbv-iv ; + cout << " Nb swap = " << NbSwap << " after " ;} + + nbv = iv; + } + +#ifdef DRAWING1 + inquire(); +#endif + + for (i=nbvold;i<nbv;i++) + NbSwap += vertices[i].Optim(1); + if (verbosity>3) + cout << " NbSwap = " << NbSwap << endl; + + + NbTSwap += NbSwap ; +#ifdef DEBUG +{ + Int4 NbErr=0; + Int4 i; + for (i=0;i<nbt;i++) + if (triangles[i].link) + { + double dd =Det(triangles[i][1].r-triangles[i][0].r,triangles[i][2].r-triangles[i][0].r); + if(dd <=0) + { + NbErr++; + cerr << " det triangle i " << i << " = " << triangles[i].det ; + cerr << " det triangle " << dd ; + cerr << " Les trois sommets " ; + cerr << Number(triangles[i][0]) << " " << Number(triangles[i][1]) << " " + << Number(triangles[i][2]) << endl; + cerr << "I2 " <<triangles[i][0].r << triangles[i][1].r << triangles[i][2].r << endl; + cerr << "R2 " << triangles[i][0].i << triangles[i][1].i << triangles[i][2].i << endl; + cerr << "I2-R2 =" <<toR2(triangles[i][0].i)-triangles[i][0].r + << toR2(triangles[i][1].i)-triangles[i][1].r + << toR2(triangles[i][2].i)-triangles[i][2].r << endl; + } + } + if(NbErr) { +#ifdef DRAWING + Int4 kkk=0; + // UnMarkUnSwapTriangle(); + // for (i=0;i<nbv;i++) + // kkk += vertices[i].Optim(0); + if(verbosity>3) + cout << " Nb of swap louche " << kkk << endl; + if(kkk) { + for (i=0;i<nbt;i++) + if (triangles[i].link) + { + double dd =Det(triangles[i][1].r-triangles[i][0].r,triangles[i][2].r-triangles[i][0].r); + if(dd <=0) + { + NbErr++; + cerr << " xxxdet triangle i " << i << " = " << triangles[i].det ; + cerr << " xxxdet triangle " << dd ; + cerr << " xxxLes trois sommets " ; + cerr << Number(triangles[i][0]) << " " << Number(triangles[i][1]) << " " + << Number(triangles[i][2]) << endl; + cerr << triangles[i][0].r << triangles[i][1].r << triangles[i][2].r << endl; + cerr << triangles[i][0].i << triangles[i][1].i << triangles[i][2].i << endl; + } + } } + inquire(); +#endif + // MeshError(11); + } + +} +#endif + return nbv-nbvold; + + } +void Triangles::NewPoints(Triangles & Bh,int KeepBackVertex) +{ // Triangles::NewPoints + Int4 nbtold(nbt),nbvold(nbv); + if (verbosity>2) + cout << " -- Triangles::NewPoints "; + if (verbosity>3)cout << " nbv (in) on Boundary = " << nbv <<endl; + Int4 i,k; + int j; + Int4 *first_np_or_next_t = new Int4[nbtx]; + Int4 NbTSwap =0; +// insert old point + nbtold = nbt; + + if (KeepBackVertex && (&Bh != this) && (nbv+Bh.nbv< nbvx)) + { + // Bh.SetVertexFieldOn(); + for (i=0;i<Bh.nbv;i++) + { + Vertex & bv = Bh[i]; + if (!bv.on) { + vertices[nbv].r = bv.r; + vertices[nbv++].m = bv.m;} + } + int nbv1=nbv; + Bh.ReMakeTriangleContainingTheVertex(); + InsertNewPoints(nbvold,NbTSwap) ; + if (verbosity>2) + cout << " (Nb of Points from background mesh = " + << nbv-nbvold << " / " << nbv1-nbvold << ")" << endl; + } + else + Bh.ReMakeTriangleContainingTheVertex(); + + Triangle *t; + // generation of the list of next Triangle + // at 1 time we test all the triangles + Int4 Headt =0,next_t; + for(i=0;i<nbt;i++) + first_np_or_next_t[i]=-(i+1); + // end list i >= nbt + // the list of test triangle is + // the next traingle on i is -first_np_or_next_t[i] + int iter=0; + // Big loop + do { + iter++; + nbtold = nbt; + nbvold = nbv; +#ifdef DRAWING1 + inquire(); +#endif + + // default size of IntersectionTriangle + + i=Headt; + next_t=-first_np_or_next_t[i]; + for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]) + { // for each triangle t + // we can change first_np_or_next_t[i] + // cout << " Do the triangle " << i << " Next_t=" << next_t << endl; + assert(i>=0 && i < nbt ); + first_np_or_next_t[i] = iter; + for(j=0;j<3;j++) + { // for each edge + TriangleAdjacent tj(t,j); + Vertex & vA = * tj.EdgeVertex(0); + Vertex & vB = * tj.EdgeVertex(1); + + if (!t->link) continue;// boundary + if (t->det <0) continue; + if (t->Locked(j)) continue; + + TriangleAdjacent tadjj = t->Adj(j); + Triangle * ta= tadjj; + + if (ta->det <0) continue; + + R2 A = vA; + R2 B = vB; + + k=Number(ta); + + if(first_np_or_next_t[k]==iter) // this edge is done before + continue; // next edge of the triangle + + //const Int4 NbvOld = nbv; + lIntTria.SplitEdge(Bh,A,B); + lIntTria.NewPoints(vertices,nbv,nbvx); + } // end loop for each edge + + }// for triangle + +#ifdef DRAWING1 + cout << " -------------------------------------------- " << endl; + inquire(); + reffecran(); + Draw(); + penthickness(2); +#endif + + if (!InsertNewPoints(nbvold,NbTSwap)) + break; + + for (i=nbtold;i<nbt;i++) + first_np_or_next_t[i]=iter; + + Headt = nbt; // empty list + for (i=nbvold;i<nbv;i++) + { // for all the triangle contening the vertex i + Vertex * s = vertices + i; + TriangleAdjacent ta(s->t, EdgesVertexTriangle[s->vint][1]); + Triangle * tbegin= (Triangle*) ta; + Int4 kt; + do { + kt = Number((Triangle*) ta); + if (first_np_or_next_t[kt]>0) + first_np_or_next_t[kt]=-Headt,Headt=kt; + assert( ta.EdgeVertex(0) == s); + ta = Next(Adj(ta)); + } while ( (tbegin != (Triangle*) ta)); + } + + } while (nbv!=nbvold); + + delete [] first_np_or_next_t; + + Int4 NbSwapf =0,NbSwp; + + // bofbof + + + NbSwp = NbSwapf; + for (i=0;i<nbv;i++) + NbSwapf += vertices[i].Optim(0); + /* + for (i=0;i<nbv;i++) + NbSwapf += vertices[i].Optim(0); + for (i=0;i<nbv;i++) + NbSwapf += vertices[i].Optim(0); + for (i=0;i<nbv;i++) + NbSwapf += vertices[i].Optim(0); + for (i=0;i<nbv;i++) + NbSwapf += vertices[i].Optim(0); + */ + NbTSwap += NbSwapf ; + if (verbosity>3) cout << " " ; + if (verbosity>2) + cout << " Nb Of Vertices =" << nbv << " Nb of triangles = " << nbt-NbOutT + << " NbSwap final = " << NbSwapf << " Nb Total Of Swap = " << NbTSwap << endl; + + +} + +void Triangles::NewPointsOld(Triangles & Bh) +{ // Triangles::NewPointsOld + Real8 seuil= 0.7 ;// for two neart point + if (verbosity>1) + cout << " begin : Triangles::NewPointsOld " << endl; + Int4 i,k; + int j; + Int4 BeginNewPoint[3]; + Int4 EndNewPoint[3]; +#ifdef TRACETRIANGLE + Int4 trace=0; +#endif + int step[3]; + Int4 *first_np_or_next_t = new Int4[nbtx]; + Int4 ColorEdge[3]; + Int4 color=-1; + Triangle *t; + // generation of the list of next Triangle + // at 1 time we test all the triangles + Int4 Headt =0,next_t; + for(i=0;i<nbt;i++) + first_np_or_next_t[i]=-(i+1); + // end list i >= nbt + // the list of test triangle is + // the next Triangle on i is -first_np_or_next_t[i] + Int4 nbtold,nbvold; + + // Big loop + do { + nbtold = nbt; + nbvold = nbv; +#ifdef DRAWING1 + inquire(); +#endif + + // default size of IntersectionTriangle + + i=Headt; + next_t=-first_np_or_next_t[i]; + for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]) + { // for each triangle t + // we can change first_np_or_next_t[i] +#ifdef TRACETRIANGLE + trace = TRACETRIANGLE <0 ? 1 : i == TRACETRIANGLE; +#endif + // cout << " Do the triangle " << i << " Next_t=" << next_t << endl; + assert(i>=0 && i < nbt ); + first_np_or_next_t[i] = nbv; // to save the fist new point of triangle + for(j=0;j<3;j++) + { // for each edge + TriangleAdjacent tj(t,j); + // color++;// the color is 3i+j + color = 3*i + j ;; + ColorEdge[j]=color; + BeginNewPoint[j]=nbv; + EndNewPoint[j]=nbv-1; + step[j]=1;// right sens + Vertex & vA = * tj.EdgeVertex(0); + Vertex & vB = * tj.EdgeVertex(1); + +#ifdef TRACETRIANGLE + if(trace) { + cout << " i " << Number(vA) <<" j "<< Number(vB) + << " " << t->Locked(j) ; + } +#endif + if (!t->link) continue;// boundary + if (t->det <0) continue; + if (t->Locked(j)) continue; + + TriangleAdjacent tadjj = t->Adj(j); + Triangle * ta= tadjj; + + if (ta->det <0) continue; + + R2 A = vA; + R2 B = vB; + + k=Number(ta); + // the 2 opposite vertices + const Vertex & vC1 = *tj.OppositeVertex(); + const Vertex & vC2 = *tadjj.OppositeVertex(); + +#ifdef TRACETRIANGLE + trace = trace || k == TRACETRIANGLE; + if(trace) { + cout << "Test Arete " << i << " AB = " << A << B + << "i " <<Number(vA)<< "j" <<Number(vB); + cout << " link" <<(int)t->link << " ta=" << Number( ta) + << " det " <<ta->det ; + cout << " hA = " <<vA.m.h << " hB = " <<vB.m.h ; + cout << " loc " << ta->Locked(j) << endl; + } +#endif + + if(first_np_or_next_t[k]>0) { // this edge is done before + // find the color of the edge and begin , end of newpoint + register int kk = t->NuEdgeTriangleAdj(j); + assert ((*t)(VerticesOfTriangularEdge[j][0]) == (*ta)(VerticesOfTriangularEdge[kk][1])); + assert ((*t)(VerticesOfTriangularEdge[j][1]) == (*ta)(VerticesOfTriangularEdge[kk][0])); + register Int4 kolor =3*k + kk; + ColorEdge[j]=kolor; + register Int4 kkk= 1; + step[j]=-1;// other sens + BeginNewPoint[j]=0; + EndNewPoint[j]=-1; // empty list + for (Int4 iv=first_np_or_next_t[k];iv<nbv;iv++) + if (vertices[iv].color > kolor) + break; // the color is passed + else if (vertices[iv].color == kolor) { + EndNewPoint[j]=iv; + if (kkk) // one time test + kkk=0,BeginNewPoint[j]=iv;} + continue; // next edge of the triangle + } // end if( k < i) + + +#ifdef DRAWING1 + penthickness(2); Move(A);Line(B); penthickness(1); +#endif + const Int4 NbvOld = nbv; + lIntTria.SplitEdge(Bh,A,B); + // Int4 NbvNp = + lIntTria.NewPoints(vertices,nbv,nbvx); + Int4 nbvNew=nbv; + nbv = NbvOld; + for (Int4 iv=NbvOld;iv<nbvNew;iv++) { + vertices[nbv].color = color; + vertices[nbv].ReferenceNumber=nbv;// circular link + R2 C = vertices[iv].r; + vertices[nbv].r = C; + vertices[nbv].m = vertices[iv].m ; + // test if the new point is not to close to the 2 opposite vertex + R2 CC1 = C-vC1 , CC2 = C-vC2; + if ( ( (vC1.m(CC1) + vertices[nbv].m(CC1)) > seuil) + && ( (vC2.m(CC2) + vertices[nbv].m(CC2)) > seuil) ) + nbv++; + } + + EndNewPoint[j] = nbv-1; + } // end loop for each edge + +#ifdef TRACETRIANGLE + if(trace) { + // verification des point cree + cout << "\n ------------ " << t->link << " " << t->det + << " b " << BeginNewPoint[0] << " " << BeginNewPoint[1] + << " " << BeginNewPoint[2] << " " + << " e " << EndNewPoint[0] << " " << EndNewPoint[1] + << " " << EndNewPoint[2] << " " + << " s " << step[0] << " " << step[1] << " " << step[2] << " " + << endl; + } +#endif + + if (!t->link) continue;// boundary + if (t->det<=0) continue;// outside + // continue; + for(int j0=0;j0<3;j0++) + for (Int4 i0= BeginNewPoint[j0]; i0 <= EndNewPoint[j0];i0++) + { + // find the neart point one the opposite edge + // to compute i1 + Vertex & vi0 = vertices[i0]; + int kstack = 0; + Int4 stack[10]; + // Int4 savRef[10]; + int j1 = j0; + while (j0 != (j1 = NextEdge[j1])) {//loop on the 2 other edge + // computation of the intersection of edge j1 and DOrto + // take the good sens + + if (BeginNewPoint[j1]> EndNewPoint[j1]) + continue; // + else if (EndNewPoint[j1] - BeginNewPoint[j1] <1) { + for (Int4 ii1= BeginNewPoint[j1];ii1<=EndNewPoint[j1];ii1++) + stack[kstack++] = ii1; + continue;} + + + int k0,k1; + if (step[j1]<0) k0=1,k1=0; // reverse + else k0=0,k1=1; + R2 V10 = (R2)(*t)[VerticesOfTriangularEdge[j1][k0]]; + R2 V11 = (R2)(*t)[VerticesOfTriangularEdge[j1][k1]]; + R2 D = V11-V10; + Real8 c0 = vi0.m(D,(R2) vi0); + + Real8 c10 = vi0.m(D,V10); + Real8 c11 = vi0.m(D,V11); + + Real8 s; + //cout << " --i0 = " << i0 << D << V10 << V11 << endl ; + //cout << " c10 " << c10 << " c0 " << c0 << " c11 " << c11 << endl; + if (( c10 < c0 ) && (c0 < c11)) + s = (c11-c0)/(c11-c10); + else if (( c11 < c0 ) && (c0 < c10)) + s = (c11-c0) /(c11-c10); + else break; + R2 VP = V10*s + V11*(1-s); + int sss = (c11-c10) >0 ? 1 : -1; +#ifdef DRAWING1 + penthickness(2); + Move((R2) vi0); + Line(VP); + penthickness(1); +#endif + // find the 2 point by dichotomie + //cout << " t =" << Number(t) << " c0 " << c0 ; + Int4 ii0 = BeginNewPoint[j1]; + Int4 ii1 = EndNewPoint[j1]; + Real8 ciii=-1,cii0=-1,cii1=-1 ; + if ( sss * ((cii0=vi0.m(D,(R2) vertices[ii0]))- c0) >0 ) + stack[kstack++] = ii0;//cout << " add+0 " << ii0; + else if ( sss * ((cii1= vi0.m(D ,(R2) vertices[ii1]))- c0) < 0 ) + stack[kstack++] = ii1;//cout << " add+1 " << ii1; + else { + while ((ii1-ii0)> 1) { + Int4 iii = (ii0+ii1)/2; + ciii = vi0.m( D ,(R2) vertices[iii]); + //cout << " (iii = " << iii << " " << ciii << ") "; + if ( sss * (ciii - c0) <0 ) ii0 = iii; + else ii1 = iii;} + stack[kstack++] = ii0;// cout << " add0 " << ii0; + if (ii1 != ii0) stack[kstack++] = ii1;//cout << " add1 " << ii1; + } +#ifdef DEBUG2 + cout << "ii1 = " << ii1 + << " ii0 = " << ii0 << endl; + cout << " cccc = " << cii0 << " " << ciii + << " " << cii1 << " sss=" << sss << endl; +#endif + if (kstack >5) // bug ? + cout << "NewPoints: bug????? " << kstack << " stack " << stack[kstack]<< endl; + } + + stack[kstack++] = -1; // to stop + Int4 i1; + kstack =0; + while( (i1=stack[kstack++]) >= 0) + { // the two parameter is i0 and i1 + assert(i1 < nbv && i1 >= 0); + assert(i0 < nbv && i0 >= 0); + assert(i1 != i0); + R2 v01 = (R2) vertices[i1]- (R2) vertices[i0]; + Real8 d01 = (vertices[i0].m(v01) + vertices[i1].m(v01)); + + +#ifdef DRAWING1 + Move(vertices[i0].r); + Line(vertices[i1].r); +#endif +#ifdef TRACETRIANGLE + if(trace) { + cout << "\n test j" << j <<" " << i0 + << " " << i1 << " d01=" << d01 <<endl;} +#endif + assert (i0 >= nbvold); + assert (i1 >= nbvold); + assert(i0 != i1); + if (d01 == 0) + break; + if ( d01 < seuil) + if (i1<nbvold) { + // remove all the points i0; + register Int4 ip,ipp; + for (ip=i0;i0 != (ipp = vertices[ip].ReferenceNumber);ip=ipp) + vertices[ip].ReferenceNumber = -1;// mark remove + vertices[ip].ReferenceNumber = -1;// mark remove + } + else { + // remove on of two points + register Int4 ip0, ip1, ipp0,ipp1; + register int kk0=1,kk1=1; + // count the number of common points to compute weight w0,w1 + for (ip0=i0;i0 != (ipp0 = vertices[ip0].ReferenceNumber);ip0=ipp0) kk0++; + for (ip1=i1;i1 != (ipp1 = vertices[ip1].ReferenceNumber);ip1=ipp1) kk1++; + + register Real8 w0 = ((Real8) kk0)/(kk0+kk1); + register Real8 w1 = ((Real8) kk1)/(kk0+kk1); + + // make a circular link + Exchange(vertices[i0].ReferenceNumber,vertices[i1].ReferenceNumber); + // the new coordinate + R2 C //= vertices[i0] ; + = vertices[i0].r *w0 + vertices[i1].r* w1; + +#ifdef TRACETRIANGLE + if(trace) { + cout << "\n ref = "<< vertices[i0].ref << " " <<vertices[i1].ref <<endl; + } +#endif +#ifdef DRAWING1 + Move(vertices[i0].r); + Line(vertices[i1].r); + DrawMark(C); +#endif + // update the new point points of the list + for (ip0=i0;i0 != (ipp0 = vertices[ip0].ReferenceNumber);ip0=ipp0) + vertices[ip0].r = C; + vertices[ip0].r = C; + } + } + } // for (i0= .... + }// for triangle + +#ifdef DRAWING1 + cout << " -------------------------------------------- " << endl; + inquire(); + reffecran(); + Draw(); + penthickness(2); +#endif + + // remove of all the double points + + Int4 ip,ipp,kkk=nbvold; + for (i=nbvold;i<nbv;i++) + if (vertices[i].ReferenceNumber>=0) {// good points + // cout <<" i = " << i ; + for (ip=i;i != (ipp = vertices[ip].ReferenceNumber);ip=ipp) + vertices[ip].ReferenceNumber = -1;// mark remove + vertices[ip].ReferenceNumber = -1;// mark remove + // cout << i << " ---> " << kkk << endl; + vertices[kkk] = vertices[i]; + vertices[kkk].i = toI2(vertices[kkk].r); +#ifdef DRAWING1 + DrawMark(vertices[kkk]); +#endif + vertices[kkk++].ReferenceNumber = 0; + + } +#ifdef DRAWING1 + penthickness(1); +#endif + + // insertion part --- + + const Int4 nbvnew = kkk-nbvold; + + cout << " Remove " << nbv - kkk << " to close vertex " ; + cout << " and Insert the " <<nbvnew<< " new points " << endl; + nbv = kkk; + Int4 NbSwap=0; + Icoor2 dete[3]; + + // construction d'un ordre aleatoire + if (! nbvnew) + break; + if (nbvnew) { + const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv) ; + Int4 k3 = rand()%nbvnew ; + for (Int4 is3=0; is3<nbvnew; is3++) + ordre[nbvold+is3]= &vertices[nbvold +(k3 = (k3 + PrimeNumber)% nbvnew)]; + + for (i=nbvold;i<nbv;i++) + { Vertex * vi = ordre[i]; + Triangle *tcvi = FindTriangleContening(vi->i,dete); + // Vertex * nv = quadtree->NearestVertex(vi->i.x,vi->i.y); + // cout << " Neart Vertex of " << Number(vi)<< vi->i << " is " + // << Number(nv) << nv->i << endl; + // Int4 kt = Number(tcvi); + // + + quadtree->Add(*vi); // +#ifdef DRAWING1 + DrawMark(vi->r); +#endif + assert (tcvi->det >= 0) ;// internal + Add(*vi,tcvi,dete),NbSwap += vi->Optim(1); + } + } + cout << " Nb swap = " << NbSwap << " after " ; +#ifdef DRAWING1 + inquire(); +#endif + + for (i=nbvold;i<nbv;i++) + NbSwap += vertices[i].Optim(1); + cout << NbSwap << endl; + + for (i=nbtold;i<nbt;i++) + first_np_or_next_t[i]=1; + + Headt = nbt; // empty list + for (i=nbvold;i<nbv;i++) + { // for all the triangle contening the vertex i + Vertex * s = vertices + i; + TriangleAdjacent ta(s->t, EdgesVertexTriangle[s->vint][1]); + Triangle * tbegin= (Triangle*) ta; + Int4 kt; + do { + kt = Number((Triangle*) ta); + if (first_np_or_next_t[kt]>0) + first_np_or_next_t[kt]=-Headt,Headt=kt; + assert( ta.EdgeVertex(0) == s); + ta = Next(Adj(ta)); + } while ( (tbegin != (Triangle*) ta)); + } + + + } while (nbv!=nbvold); + delete [] first_np_or_next_t; +#ifdef DEBUG + int nberr=0; + for (int it=0;it<nbt;it++) + if(triangles[it].det==0) + if(nberr++<10) cerr << "Bug Triangle nul" << it << triangles[it] << endl; + if(nberr) MeshError(992,this); +#endif + cout << " end : Triangles::NewPoints old nbv=" << nbv << endl; + +} + +void Triangles::Insert() +{ + if (verbosity>2) cout << " -- Insert initial " << nbv << " vertices " << endl ; + Triangles * OldCurrentTh =CurrentTh; + + CurrentTh=this; + double time0=CPUtime(),time1,time2,time3; + SetIntCoor(); + Int4 i; + for (i=0;i<nbv;i++) + ordre[i]= &vertices[i] ; + + // construction d'un ordre aleatoire + const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv) ; + Int4 k3 = rand()%nbv ; + for (int is3=0; is3<nbv; is3++) + ordre[is3]= &vertices[k3 = (k3 + PrimeNumber)% nbv]; + + + + + for (i=2 ; det( ordre[0]->i, ordre[1]->i, ordre[i]->i ) == 0;) + if ( ++i >= nbv) { + cerr << " All the vertices are aline " << endl; + MeshError(998,this); } + + // echange i et 2 dans ordre afin + // que les 3 premiers ne soit pas aligne + Exchange( ordre[2], ordre[i]); + + // on ajoute un point a l'infini pour construire le maillage + // afin d'avoir une definition simple des aretes frontieres + nbt = 2; + + + // on construit un maillage trivale forme + // d'une arete et de 2 triangles + // construit avec le 2 aretes orientes et + Vertex * v0=ordre[0], *v1=ordre[1]; + + triangles[0](0) = 0; // sommet pour infini + triangles[0](1) = v0; + triangles[0](2) = v1; + + triangles[1](0) = 0;// sommet pour infini + triangles[1](2) = v0; + triangles[1](1) = v1; + const int e0 = OppositeEdge[0]; + const int e1 = NextEdge[e0]; + const int e2 = PreviousEdge[e0]; + triangles[0].SetAdj2(e0, &triangles[1] ,e0); + triangles[0].SetAdj2(e1, &triangles[1] ,e2); + triangles[0].SetAdj2(e2, &triangles[1] ,e1); + + triangles[0].det = -1; // faux triangles + triangles[1].det = -1; // faux triangles + + triangles[0].SetTriangleContainingTheVertex(); + triangles[1].SetTriangleContainingTheVertex(); + + triangles[0].link=&triangles[1]; + triangles[1].link=&triangles[0]; + +#ifdef DEBUG + triangles[0].check(); + triangles[1].check(); +#endif + // nbtf = 2; + if ( !quadtree ) quadtree = new QuadTree(this,0); + quadtree->Add(*v0); + quadtree->Add(*v1); + + // on ajoute les sommets un Ã’ un + Int4 NbSwap=0; + + time1=CPUtime(); + + if (verbosity>3) cout << " -- Begin of insertion process " << endl; + + for (Int4 icount=2; icount<nbv; icount++) { + Vertex *vi = ordre[icount]; + // cout << " Insert " << Number(vi) << endl; + Icoor2 dete[3]; + Triangle *tcvi = FindTriangleContening(vi->i,dete); + quadtree->Add(*vi); + Add(*vi,tcvi,dete); + NbSwap += vi->Optim(1,0); +#ifdef DRAWING1 + inquire(); +#endif + + }// fin de boucle en icount + time2=CPUtime(); + if (verbosity>3) + cout << " NbSwap of insertion " << NbSwap + << " NbSwap/Nbv " << (float) NbSwap / (float) nbv + << " NbUnSwap " << NbUnSwap << " Nb UnSwap/Nbv " + << (float)NbUnSwap /(float) nbv + <<endl; + NbUnSwap = 0; + // construction d'un ordre aleatoire + // const int PrimeNumber= (nbv % 999983) ? 1000003: 999983 ; +#ifdef NBLOOPOPTIM + + k3 = rand()%nbv ; + for (int is4=0; is4<nbv; is4++) + ordre[is4]= &vertices[k3 = (k3 + PrimeNumber)% nbv]; + + double timeloop = time2 ; + for(int Nbloop=0;Nbloop<NBLOOPOPTIM;Nbloop++) + { + double time000 = timeloop; + Int4 NbSwap = 0; + for (int is1=0; is1<nbv; is1++) + NbSwap += ordre[is1]->Optim(0,0); + timeloop = CPUtime(); + if (verbosity>3) + cout << " Optim Loop "<<Nbloop<<" NbSwap: " << NbSwap + << " NbSwap/Nbv " << (float) NbSwap / (float) nbv + << " CPU=" << timeloop - time000 << " s, " + << " NbUnSwap/Nbv " << (float)NbUnSwap /(float) nbv + << endl; + NbUnSwap = 0; + if(!NbSwap) break; + } + ReMakeTriangleContainingTheVertex(); + // because we break the TriangleContainingTheVertex +#endif +#ifdef DEBUG + int nberr=0; + for (int it=0;it<nbt;it++) + if(triangles[it].det==0) + if(nberr++<10) cerr << "Bug Triangle nul" << it << triangles[it] << endl; + if(nberr) MeshError(991,this); +#endif + time3=CPUtime(); + if (verbosity>4) + cout << " init " << time1 - time0 << " initialisation, " + << time2 - time1 << "s, insert point " + << time3 -time2 << "s, optim " << endl + << " Init Total Cpu Time = " << time3 - time0 << "s " << endl; + +#ifdef DRAWING1 + inquire(); +#endif + CurrentTh=OldCurrentTh; +} + + +void Triangles::ForceBoundary() +{ + if (verbosity > 2) + cout << " -- ForceBoundary nb of edge " << nbe << endl; + int k=0; + Int4 nbfe=0,nbswp=0,Nbswap=0; + for (Int4 t = 0; t < nbt; t++) + if (!triangles[t].det) + k++,cerr << " det T" << t << " = " << 0 << endl; + if (k!=0) { + cerr << " ther is " << k << " triangles of mes = 0 " << endl; + MeshError(11,this);} + + TriangleAdjacent ta(0,0); + for (Int4 i = 0; i < nbe; i++) + { + nbswp = ForceEdge(edges[i][0],edges[i][1],ta); + + if ( nbswp < 0) k++; + else Nbswap += nbswp; + if (nbswp) nbfe++; + if ( nbswp < 0 && k < 5) + { + cerr << " Missing Edge " << i << " v0 = " << Number(edges[i][0]) << edges[i][0].r + <<" v1= " << Number(edges[i][1]) << edges[i][1].r << " " << edges[i].on->Cracked() << " " << (Triangle *) ta ; + if(ta.t) + { + Vertex *aa = ta.EdgeVertex(0), *bb = ta.EdgeVertex(1); + cerr << " crossing with [" << Number(aa) << ", " << Number(bb) << "]\n"; + } + else cerr << endl; + + } + if ( nbswp >=0 && edges[i].on->Cracked()) + ta.SetCracked(); + } + + + if (k!=0) { + cerr << " they is " << k << " lost edges " << endl; + cerr << " The boundary is crossing may be!" << endl; + MeshError(10,this); + } + for (Int4 j=0;j<nbv;j++) + Nbswap += vertices[j].Optim(1,0); + if (verbosity > 3) + cout << " Nb of inforced edge = " << nbfe << " Nb of Swap " << Nbswap << endl; + +} + +void Triangles::FindSubDomain(int OutSide=0) +{ + //#define DRAWING1 + + if (verbosity >2) + { + if (OutSide) + cout << " -- Find all external sub-domain "; + else + cout << " -- Find all internal sub-domain "; + if(verbosity>99) + { + + for(int i=0;i<nbt;++i) + cout << i<< " " << triangles[i] << endl; + } + + } + // if (verbosity > 4) cout << " OutSide=" << OutSide << endl; + short * HeapArete = new short[nbt]; + Triangle ** HeapTriangle = new Triangle* [nbt]; + Triangle *t,*t1; + Int4 k,it; + + for (Int4 itt=0;itt<nbt;itt++) + triangles[itt].link=0; // par defaut pas de couleur +#ifdef DRAWING1 + reffecran(); +#endif + + Int4 NbSubDomTot =0; + for ( it=0;it<nbt;it++) { + if ( ! triangles[it].link ) { + t = triangles + it; + NbSubDomTot++;; // new composante connexe + Int4 i = 0; // niveau de la pile + t->link = t ; // sd forme d'un triangle cicular link +#ifdef DRAWING1 + t->Draw(NbSubDomTot-1); +#endif + + + HeapTriangle[i] =t ; + HeapArete[i] = 3; + + while (i >= 0) // boucle sur la pile + { while ( HeapArete[i]--) // boucle sur les 3 aretes + { + int na = HeapArete[i]; + Triangle * tc = HeapTriangle[i]; // triangle courant + if( ! tc->Locked(na)) // arete non frontiere + { + Triangle * ta = tc->TriangleAdj(na) ; // næ triangle adjacent + if (ta->link == 0 ) // non deja chainer => on enpile + { + i++; +#ifdef DRAWING1 + ta->Draw(NbSubDomTot-1); +#endif + ta->link = t->link ; // on chaine les triangles + t->link = ta ; // d'un meme sous domaine + HeapArete[i] = 3; // pour les 3 triangles adjacents + HeapTriangle[i] = ta; + }} + } // deplie fin de boucle sur les 3 adjacences + i--; + } + } + } + + // supression de tous les sous domaine infini <=> contient le sommet NULL + it =0; + NbOutT = 0; + while (it<nbt) { + if (triangles[it].link) + { + if (!( triangles[it](0) && triangles[it](1) && triangles[it](2) )) + { + // infini triangle + NbSubDomTot --; + // cout << " triangle infini " << it << triangles[it] << endl; + t=&triangles[it]; + NbOutT--; // on fait un coup de trop. + while (t){ // cout << Number(t) << " " << endl; + NbOutT++; + t1=t; + t=t->link; + t1->link=0;}//while (t) + } + } + it++;} // end while (it<nbt) + if (nbt == NbOutT || !NbSubDomTot) + { + cout << "\n error : " << NbOutT << " " << NbSubDomTot <<" " << nbt << endl; + cerr << "Error: The boundary is not close => All triangles are outside " << endl; + MeshError(888,this); + } + + delete [] HeapArete; + delete [] HeapTriangle; + + + if (OutSide|| !Gh.subdomains || !Gh.NbSubDomains ) + { // No geom sub domain + Int4 i; + if (subdomains) delete [] subdomains; + subdomains = new SubDomain[ NbSubDomTot]; + NbSubDomains= NbSubDomTot; + for ( i=0;i<NbSubDomains;i++) { + subdomains[i].head=NULL; + subdomains[i].ref=i+1; + } + Int4 * mark = new Int4[nbt]; + for (it=0;it<nbt;it++) + mark[it]=triangles[it].link ? -1 : -2; + + it =0; + k = 0; + while (it<nbt) { + if (mark[it] == -1) { + t1 = & triangles[it]; + t = t1->link; + mark[it]=k; +#ifdef DRAWING1 + t1->Draw(k); +#endif + subdomains[k].head = t1; + // cout << " New -- " << Number(t1) << " " << it << endl; + do {// cout << " k " << k << " " << Number(t) << endl; + mark[Number(t)]=k; +#ifdef DRAWING1 + t->Draw(k); +#endif + t=t->link; + } while (t!=t1); +#ifdef DRAWING1 + t1->Draw(k); +#endif + mark[it]=k++;} + // else if(mark[it] == -2 ) triangles[it].Draw(999); + it++;} // end white (it<nbt) + assert(k== NbSubDomains); + if(OutSide) + { + // to remove all the sub domain by parity adjacents + // because in this case we have only the true boundary edge + // so teh boundary is manifold + Int4 nbk = NbSubDomains; + while (nbk) + for (it=0;it<nbt && nbk ;it++) + for (int na=0;na<3 && nbk ;na++) + { + Triangle *ta = triangles[it].TriangleAdj(na); + Int4 kl = ta ? mark[Number(ta)] : -2; + Int4 kr = mark[it]; + if(kr !=kl) { + //cout << kl << " " << kr << " rl " << subdomains[kl].ref + // << " rr " << subdomains[kr].ref ; + if (kl >=0 && subdomains[kl].ref <0 && kr >=0 && subdomains[kr].ref>=0) + nbk--,subdomains[kr].ref=subdomains[kl].ref-1; + if (kr >=0 && subdomains[kr].ref <0 && kl >=0 && subdomains[kl].ref>=0) + nbk--,subdomains[kl].ref=subdomains[kr].ref-1; + if(kr<0 && kl >=0 && subdomains[kl].ref>=0) + nbk--,subdomains[kl].ref=-1; + if(kl<0 && kr >=0 && subdomains[kr].ref>=0) + nbk--,subdomains[kr].ref=-1; + // cout << " after \t " + // << kl << subdomains[kl].ref << " rr " << kr + // << subdomains[kr].ref << endl; + } + } + // cout << subdomains[0].ref << subdomains[1].ref << endl; + Int4 j=0; + for ( i=0;i<NbSubDomains;i++) + if((-subdomains[i].ref) %2) { // good + //cout << " sudom ok = " << i << " " << subdomains[i].ref + // << " " << (-subdomains[i].ref) %2 << endl; + if(i != j) + Exchange(subdomains[i],subdomains[j]); + j++;} + else + { //cout << " remove sub domain " << i << endl; + t= subdomains[i].head; + while (t){// cout << Number(t) << " " << endl; + NbOutT++; + t1=t; + t=t->link; + t1->link=0;}//while (t) + } + + if(verbosity>4) + cout << " Number of remove sub domain (OutSideMesh) =" << NbSubDomains-j << endl; + NbSubDomains=j; + } + + delete [] mark; + + } + else + { // find the head for all sub domaine + if (Gh.NbSubDomains != NbSubDomains && subdomains) + delete [] subdomains, subdomains=0; + if (! subdomains ) + subdomains = new SubDomain[ Gh.NbSubDomains]; + NbSubDomains =Gh.NbSubDomains; + if(verbosity>4) + cout << " find the " << NbSubDomains << " sub domain " << endl; + Int4 err=0; + ReMakeTriangleContainingTheVertex(); + Int4 * mark = new Int4[nbt]; + Edge **GeometricalEdgetoEdge = MakeGeometricalEdgeToEdge(); + + for (it=0;it<nbt;it++) + mark[it]=triangles[it].link ? -1 : -2; + Int4 inew =0; + for (Int4 i=0;i<NbSubDomains;i++) + { + GeometricalEdge &eg = *Gh.subdomains[i].edge; + subdomains[i].ref = Gh.subdomains[i].ref; + int ssdlab = subdomains[i].ref; + // by carefull is not easy to find a edge create from a GeometricalEdge + // see routine MakeGeometricalEdgeToEdge + Edge &e = *GeometricalEdgetoEdge[Gh.Number(eg)]; + assert(&e); + Vertex * v0 = e(0),*v1 = e(1); + Triangle *t = v0->t; + int sens = Gh.subdomains[i].sens; + // test if ge and e is in the same sens + // cout << " geom edge = " << Gh.Number(eg) <<" @" << &eg << " ref = " << subdomains[i].ref + // << " ref edge =" << eg.ref << " sens " << sens ; + if (((eg[0].r-eg[1].r),(e[0].r-e[1].r))<0) + sens = -sens ; + subdomains[i].sens = sens; + subdomains[i].edge = &e; + // cout << " sens " << sens << " in geom " << eg[0].r << eg[1].r << " in mesh " << e[0].r << e[1].r << endl; + // cout << " v0 , v1 = " << Number(v0) << " " << Number(v1) << endl; + assert(t && sens); + + TriangleAdjacent ta(t,EdgesVertexTriangle[v0->vint][0]);// previous edges + + while (1) + { + assert( v0 == ta.EdgeVertex(1) ); + // cout << " recherche " << Number( ta.EdgeVertex(0)) << endl; + if (ta.EdgeVertex(0) == v1) { // ok we find the edge + if (sens>0) + subdomains[i].head=t=Adj(ta); + else + subdomains[i].head=t=ta; + //cout << " triangle =" << Number(t) << " = " << (*t)[0].r << (*t)[1].r << (*t)[2].r << endl; + if(t<triangles || t >= triangles+nbt || t->det < 0 + || t->link == 0) // Ajoute aout 200 + { + cerr << " Error in the def of sub domain "<<i + << " form border " << NbSubDomains - i << "/" << NbSubDomains + << ": Bad sens " << Gh.Number(eg) <<" "<< sens << endl; + err++; + break;} + Int4 it = Number(t); + if (mark[it] >=0) { + if(verbosity>10) + cerr << " Warning: the sub domain " << i << " ref = " << subdomains[i].ref + << " is previouly defined with " <<mark[it] << " ref = " << subdomains[mark[it]].ref + << " skip this def " << endl; + break;} + if(i != inew) + Exchange(subdomains[i],subdomains[inew]); + inew++; + Triangle *tt=t; + Int4 kkk=0; + do + { + kkk++; + assert(mark[Number(tt)]<0); +#ifdef DRAWING1 + tt->Draw(i); +#endif + mark[Number(tt)]=i; + tt=tt->link; + } while (tt!=t); + if(verbosity>7) + cout << " Nb de triangles dans le sous domaine " << i << " de ref " << subdomains[i].ref << " = " << kkk << endl; + break;} + ta = Previous(Adj(ta)); + if(t == (Triangle *) ta) { + err++; + cerr << " Error in the def of sub domain " << i + << " edge=" << Gh.Number(eg) << " " << sens << endl; + break;} + // cout << " NB of remove subdomain " << NbSubDomTot-NbSubDomains<< endl; + + } + + } + if (err) MeshError(777,this); + + if (inew < NbSubDomains) { + if (verbosity>5) + cout << " Warning: We remove " << NbSubDomains-inew << " SubDomains " << endl; + NbSubDomains=inew;} + + + for (it=0;it<nbt;it++) + if ( mark[it] ==-1 ) + NbOutT++,triangles[it].link =0; + delete [] GeometricalEdgetoEdge; + delete [] mark; + + } + +#ifdef DRAWING1 + inquire(); +#endif + NbOutT=0; + for (it=0;it<nbt;it++) + if(!triangles[it].link) NbOutT++; + if (verbosity> 4) + cout << " " ; + if (verbosity> 2) + cout << " Nb of Sub borned Domain = " << NbSubDomTot << " NbOutTriangles = " << NbOutT <<endl; +#ifdef DRAWING1 + inquire(); +#endif + + //#undef DRAWING1 + + +} +void Triangles::ReNumberingVertex(Int4 * renu) +{ + // warning be carfull because pointeur + // from on mesh to over mesh + // -- so do ReNumbering a the beginning + Vertex * ve = vertices+nbv; + Int4 it,ie,i; + + for ( it=0;it<nbt;it++) + triangles[it].ReNumbering(vertices,ve,renu); + + for ( ie=0;ie<nbe;ie++) + edges[ie].ReNumbering(vertices,ve,renu); + + for (i=0;i< NbVerticesOnGeomVertex;i++) + { + Vertex *v = VerticesOnGeomVertex[i].mv; + if (v>=vertices && v < ve) + VerticesOnGeomVertex[i].mv=vertices+renu[Number(v)]; + } + + for (i=0;i< NbVerticesOnGeomEdge;i++) + { + Vertex *v =VerticesOnGeomEdge[i].mv; + if (v>=vertices && v < ve) + VerticesOnGeomEdge[i].mv=vertices+renu[Number(v)]; + } + + for (i=0;i< NbVertexOnBThVertex;i++) + { + Vertex *v=VertexOnBThVertex[i].v; + if (v>=vertices && v < ve) + VertexOnBThVertex[i].v=vertices+renu[Number(v)]; + } + + for (i=0;i< NbVertexOnBThEdge;i++) + { + Vertex *v=VertexOnBThEdge[i].v; + if (v>=vertices && v < ve) + VertexOnBThEdge[i].v=vertices+renu[Number(v)]; + } + + // move the Vertices without a copy of the array + // be carefull not trivial code + Int4 j; + for ( it=0;it<nbv;it++) // for all sub cycles of the permutation renu + if (renu[it] >= 0) // a new sub cycle + { + i=it; + Vertex ti=vertices[i],tj; + while ( (j=renu[i]) >= 0) + { // i is old, and j is new + renu[i] = -1-renu[i]; // mark + tj = vertices[j]; // save new + vertices[j]= ti; // new <- old + i=j; // next + ti = tj; + } + } + if (quadtree) + { delete quadtree; + quadtree = new QuadTree(this); + } + for ( it=0;it<nbv;it++) + renu[i]= -renu[i]-1; + +} +void Triangles::ReNumberingTheTriangleBySubDomain(bool justcompress) + { + Int4 *renu= new Int4[nbt]; + register Triangle *t0,*t,*te=triangles+nbt; + register Int4 k=0,it,i,j; + + for ( it=0;it<nbt;it++) + renu[it]=-1; // outside triangle + for ( i=0;i<NbSubDomains;i++) + { + t=t0=subdomains[i].head; + assert(t0); // no empty sub domain + do { + Int4 kt = Number(t); + assert(kt>=0 && kt < nbt ); + assert(renu[kt]==-1); + renu[kt]=k++; + } + while (t0 != (t=t->link)); + } + if (verbosity>9) + cout << " number of inside triangles " << k << " nbt = " << nbt << endl; + // take is same numbering if possible + if(justcompress) + for ( k=0,it=0;it<nbt;it++) + if(renu[it] >=0 ) + renu[it]=k++; + + // put the outside triangles at the end + for ( it=0;it<nbt;it++) + if (renu[it]==-1) + renu[it]=k++; + + assert(k == nbt); + // do the change on all the pointeur + for ( it=0;it<nbt;it++) + triangles[it].ReNumbering(triangles,te,renu); + + for ( i=0;i<NbSubDomains;i++) + subdomains[i].head=triangles+renu[Number(subdomains[i].head)]; + + // move the Triangles without a copy of the array + // be carefull not trivial code + for ( it=0;it<nbt;it++) // for all sub cycles of the permutation renu + if (renu[it] >= 0) // a new sub cycle + { + i=it; + Triangle ti=triangles[i],tj; + while ( (j=renu[i]) >= 0) + { // i is old, and j is new + renu[i] = -1; // mark + tj = triangles[j]; // save new + triangles[j]= ti; // new <- old + i=j; // next + ti = tj; + } + } + delete [] renu; + nt = nbt - NbOutT; + +#ifdef DEBUG +// verif + for ( it=0;it<nbt;it++) + triangles[it].check(); +#endif + } +Int4 Triangles::ConsRefTriangle(Int4 *reft) const +{ + assert(reft); + register Triangle *t0,*t; + register Int4 k=0, num; + for (Int4 it=0;it<nbt;it++) + reft[it]=-1; // outside triangle + for (Int4 i=0;i<NbSubDomains;i++) + { + t=t0=subdomains[i].head; + assert(t0); // no empty sub domain + // register Int4 color=i+1;// because the color 0 is outside triangle + do { k++; + num = Number(t); + assert(num>=0 &&num < nbt); + reft[num]=i; + // cout << Number(t0) << " " <<Number(t)<< " " << i << endl; + } + while (t0 != (t=t->link)); + } + // NbOutT = nbt - k; + if (verbosity>5) + cout << " Nb of Sub Domain =" << NbSubDomains << " Nb of In Triangles " << k + << " Nbt = " << nbt << " Out Triangles = " << nbt - k << endl; + + return k; + +} + +/* +void Triangles::ConsLinkTriangle() +{ + for (Int4 i=0;i<NbSubDomains;i++) + subdomains[i].head=0; + register Triangle * t=triangles,*tend = triangles+nbt,*hst; + for (;t<tend;t++) + { + if (t->link) + { + register Int4 color = t->color-1; + assert(color<NbSubDomains && color>=0); + if (hst=subdomains[color].head) { + t->link=hst->link; + hst->link=t; } + else { + subdomains[color].head = t; + t->link=t;}// circular link + } + } + { + for (Int4 i=0;i<NbSubDomains;i++) + assert(subdomains[i].head); + } + +} +*/ +/* void Triangles::RandomInit() +{ + // Meshbegin = vertices; + // Meshend = vertices + nbvx; + nbv = nbvx; + for (int i = 0; i < nbv; i++) + { + vertices[i].r.x= rand(); + vertices[i].r.y= rand(); + vertices[i].ref = 0; + } +} +void Triangles::CubeInit(int n,int m) +{ + // nbvx = n*m; + // Meshbegin = vertices; + // Meshend = vertices + nbvx; + nbv = n*m; + assert(nbv <= nbvx); + int k =0; + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + { + vertices[k].r.x= i; + vertices[k].r.y= j; + vertices[k++].ref = 0; + } +} +*/ +Vertex * Triangles::NearestVertex(Icoor1 i,Icoor1 j) + { return quadtree->NearestVertex(i,j); } + + +void Triangles::PreInit(Int4 inbvx,char *fname) +{ + srand(19999999); + OnDisk =0; + NbRef=0; + // allocGeometry=0; + identity=0; + NbOfTriangleSearchFind =0; + NbOfSwapTriangle =0; + nbiv=0; + nbv=0; + nbvx=inbvx; + nbt=0; + NbOfQuad = 0; + nbtx=2*inbvx-2; + NbSubDomains=0; + NbVertexOnBThVertex=0; + NbVertexOnBThEdge=0; + VertexOnBThVertex=0; + VertexOnBThEdge=0; + + NbCrackedVertices=0; + NbCrackedEdges =0; + CrackedEdges =0; + nbe = 0; + name = fname ; + + if (inbvx) { + vertices=new Vertex[nbvx]; + assert(vertices); + ordre=new (Vertex* [nbvx]); + assert(ordre); + triangles=new Triangle[nbtx]; + assert(triangles);} + else { + vertices=0; + ordre=0; + triangles=0; + nbtx=0; + } + if ( name || inbvx) + { + time_t timer =time(0); + char buf[70]; + strftime(buf ,70,", Date: %y/%m/%d %H:%M %Ss",localtime(&timer)); + counter++; + char countbuf[30]; + sprintf(countbuf,"%d",counter); + int lg =0 ; + if (&BTh != this && BTh.name) + lg = strlen(BTh.name)+4; + identity = new char[ lg + strlen(buf) + strlen(countbuf)+ 2 + 10 + ( Gh.name ? strlen(Gh.name) + 4 : 0)]; + identity[0]=0; + if (lg) + strcat(strcat(strcat(identity,"B="),BTh.name),", "); + + if (Gh.name) + strcat(strcat(identity,"G="),Gh.name); + strcat(strcat(identity,";"),countbuf); + strcat(identity,buf); + // cout << "New MAILLAGE "<< identity << endl; + } + + quadtree=0; +// edgescomponante=0; + edges=0; + VerticesOnGeomVertex=0; + VerticesOnGeomEdge=0; + NbVerticesOnGeomVertex=0; + NbVerticesOnGeomEdge=0; +// nbMaxIntersectionTriangles=0; +// lIntTria; + subdomains=0; + NbSubDomains=0; +// Meshbegin = vertices; +// Meshend = vertices + nbvx; + if (verbosity>98) + cout << "Triangles::PreInit() " << nbvx << " " << nbtx + << " " << vertices + << " " << ordre << " " << triangles <<endl; + +} + +void Triangles::GeomToTriangles1(Int4 inbvx,int KeepBackVertices) +{ +//#define DRAWING1 + Gh.NbRef++;// add a ref to Gh + + +/************************************************************************* +// methode in 2 step +// 1 - compute the number of new edge to allocate +// 2 - construct the edge + remark: + in this part we suppose to have a background mesh with the same + geometry + + To construct the discretisation of the new mesh we have to + rediscretize the boundary of background Mesh + because we have only the pointeur from the background mesh to the geometry. + We need the abcisse of the background mesh vertices on geometry + so a vertex is + 0 on GeometricalVertex ; + 1 on GeometricalEdge + abcisse + 2 internal + + *************************************************************************/ + assert(&BTh.Gh == &Gh); + + // if(verbosity==100) Gh.Write("/tmp/gg.gmsh"); + BTh.NbRef++; // add a ref to BackGround Mesh + PreInit(inbvx); + BTh.SetVertexFieldOn(); +#ifdef DRAWING + if (withrgraphique) + { BTh.InitDraw(); + reffecran(); + CurrentTh = this;} +#endif + int * bcurve = new int[Gh.NbOfCurves]; // + + // we have 2 ways to make the loop + // 1) on the geometry + // 2) on the background mesh + // if you do the loop on geometry, we don't have the pointeur on background, + // and if you do the loop in background we have the pointeur on geometry + // so do the walk on background + // Int4 NbVerticesOnGeomVertex; + // VertexOnGeom * VerticesOnGeomVertex; + // Int4 NbVerticesOnGeomEdge; + // VertexOnGeom * VerticesOnGeomEdge; + + + NbVerticesOnGeomVertex=0; + NbVerticesOnGeomEdge=0; + //1 copy of the Required vertex + int i; + for ( i=0;i<Gh.nbv;i++) + if (Gh[i].Required()) NbVerticesOnGeomVertex++; + + VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex]; + VertexOnBThVertex = new VertexOnVertex[NbVerticesOnGeomVertex]; + // + if( NbVerticesOnGeomVertex >= nbvx) + { + cerr << " Too much vertices on geometry " << NbVerticesOnGeomVertex << " >= " << nbvx << endl; + MeshError(1,this); + } + assert(vertices); + for (i=0;i<Gh.nbv;i++) + if (Gh[i].Required()) {//Gh vertices Required + vertices[nbv] = Gh[i]; + vertices[nbv].i = I2(0,0); + Gh[i].to = vertices + nbv;// save Geom -> Th + VerticesOnGeomVertex[nbv]= VertexOnGeom(vertices[nbv],Gh[i]); + // cout << "--------- " <<Number(Gh[i].to) << " " << Gh[i].to << " " << i << endl; + nbv++;} + else Gh[i].to=0; + // + for (i=0;i<BTh.NbVerticesOnGeomVertex;i++) + { + VertexOnGeom & vog = BTh.VerticesOnGeomVertex[i]; + if (vog.IsRequiredVertex()) { + GeometricalVertex * gv = vog; + Vertex *bv = vog; + assert(gv->to);// use of Geom -> Th + VertexOnBThVertex[NbVertexOnBThVertex++] = VertexOnVertex(gv->to,bv); + gv->to->m = bv->m; // for taking the metrix of the background mesh + ;} + } + assert(NbVertexOnBThVertex == NbVerticesOnGeomVertex); +// new stuff FH with curve +// find the begin of the curve in BTh +{ + Gh.UnMarkEdges(); + int bfind=0; +/* + cout << " nb curves = " << Gh.NbOfCurves << endl; + for(int i=0;i<Gh.NbOfCurves ;i++) + { + cout << " Curve " << i << " begin e=" << Gh.Number(Gh.curves[i].be) << " k=" << Gh.curves[i].kb + << " end e= " << Gh.Number(Gh.curves[i].ee) << " k=" << Gh.curves[i].ke << endl; + }*/ + for (int i=0;i<Gh.NbOfCurves;i++) + { + bcurve[i]=-1; + } + + for (int iedge=0;iedge<BTh.nbe;iedge++) + { + Edge & ei = BTh.edges[iedge]; + for(int je=0;je<2;je++) // for the 2 extremites + if (!ei.on->Mark() && ei[je].on->IsRequiredVertex() ) + { + // a begin of curve + int nc = ei.on->CurveNumber; + + //cout << "curve " << nc << " v " << Gh.Number((GeometricalVertex *) *ei[je].on) << " " + // << " e " << " " << Gh.Number(ei.on) << " vc " << Gh.Number((*Gh.curves[nc].be)[Gh.curves[nc].kb]) << endl; + if( + ei.on==Gh.curves[nc].be && + (GeometricalVertex *) *ei[je].on == &(*Gh.curves[nc].be)[Gh.curves[nc].kb] // same extremity + ) + { + // cout << " find " << endl; + bcurve[nc]=iedge*2+je; + bfind++; + } + } + } + assert( bfind==Gh.NbOfCurves); +} +// method in 2 + 1 step +// 0.0) compute the length and the number of vertex to do allocation +// 1.0) recompute the length +// 1.1) compute the vertex + Int4 nbex=0,NbVerticesOnGeomEdgex=0; + for (int step=0; step <2;step++) + { + Int4 NbOfNewPoints=0; + Int4 NbOfNewEdge=0; + Int4 iedge; + Gh.UnMarkEdges(); +/* add Curve loop FH + // find a starting back groud edges to walk + for (iedge=0;iedge<BTh.nbe;iedge++) { + Edge & ei = BTh.edges[iedge]; + for(int jedge=0;jedge<2;jedge++) // for the 2 extremites + if (!ei.on->Mark() && ei[jedge].on->IsRequiredVertex() ) + { +*/ +// new code FH 2004 + Real8 L=0; + for (int icurve=0;icurve<Gh.NbOfCurves;icurve++) + { + iedge=bcurve[icurve]/2; + int jedge=bcurve[icurve]%2; + if( ! Gh.curves[icurve].master) continue; // we skip all equi curve + Edge & ei = BTh.edges[iedge]; + // warning: ei.on->Mark() can be change in + // loop for(jedge=0;jedge<2;jedge++) + // new curve + // good the find a starting edge + Real8 Lstep=0,Lcurve=0;// step between two points (phase==1) + Int4 NbCreatePointOnCurve=0;// Nb of new points on curve (phase==1) + + + // cout.precision(16); + for(int phase=0;phase<=step;phase++) + { + + for(Curve * curve= Gh.curves+icurve;curve;curve= curve->next) + { + + int icurveequi= Gh.Number(curve); + + if( phase == 0 && icurveequi != icurve) continue; + + int k0=jedge,k1; + Edge * pe= BTh.edges+iedge; + //GeometricalEdge *ong = ei.on; + int iedgeequi=bcurve[icurveequi]/2; + int jedgeequi=bcurve[icurveequi]%2; + + int k0equi=jedgeequi,k1equi; + Edge * peequi= BTh.edges+iedgeequi; + GeometricalEdge *ongequi = peequi->on; + + Real8 sNew=Lstep;// abcisse of the new points (phase==1) + L=0;// length of the curve + Int4 i=0;// index of new points on the curve + register GeometricalVertex * GA0 = *(*peequi)[k0equi].on; + Vertex *A0; + A0 = GA0->to; // the vertex in new mesh + Vertex *A1; + VertexOnGeom *GA1; + Edge * PreviousNewEdge = 0; + // cout << " --------------New Curve phase " << phase + // << "---------- A0=" << *A0 << ei[k0] <<endl; + assert (A0-vertices>=0 && A0-vertices <nbv); + if(ongequi->Required() ) + { + GeometricalVertex *GA1 = *(*peequi)[1-k0equi].on; + A1 = GA1->to; // + } + else + for(;;) + { + // assert(pe && BTh.Number(pe)>=0 && BTh.Number(pe)<=BTh.nbe); + Edge &ee=*pe; + Edge &eeequi=*peequi; + k1 = 1-k0; // next vertex of the edge + k1equi= 1 - k0equi; + + assert(pe && ee.on); + ee.on->SetMark(); + Vertex & v0=ee[0], & v1=ee[1]; + R2 AB= (R2) v1 - (R2) v0; + Real8 L0=L,LAB; + LAB = LengthInterpole(v0.m,v1.m,AB); + L+= LAB; + if (phase) {// computation of the new points + while ((i!=NbCreatePointOnCurve) && sNew <= L) { + // cout << " L0= " << L0 << " L " << L << " sN=" + // << sNew << " LAB=" << LAB << " NBPC =" <<NbCreatePointOnCurve<< " i " << i << endl; + assert (sNew >= L0); + assert(LAB); + + + assert(vertices && nbv<nbvx); + assert(edges && nbe < nbex); + assert(VerticesOnGeomEdge && NbVerticesOnGeomEdge < NbVerticesOnGeomEdgex); + // new vertex on edge + A1=vertices+nbv++; + GA1=VerticesOnGeomEdge+NbVerticesOnGeomEdge; + Edge *e = edges + nbe++; + Real8 se= (sNew-L0)/LAB; + assert(se>=0 && se < 1.000000001); +#ifdef DEBUG + se = abscisseInterpole(v0.m,v1.m,AB,se); // because code \ref(xxx) +#else + se = abscisseInterpole(v0.m,v1.m,AB,se,1); +#endif + assert(se>=0 && se <= 1); + //((k1==1) != (k1==k1equi)) + se = k1 ? se : 1. - se; + se = k1==k1equi ? se : 1. - se; + VertexOnBThEdge[NbVerticesOnGeomEdge++] = VertexOnEdge(A1,&eeequi,se); // save + ongequi = Gh.ProjectOnCurve(eeequi,se,*A1,*GA1); + A1->ReferenceNumber = eeequi.ref; + A1->DirOfSearch =NoDirOfSearch; + //cout << icurveequi << " " << i << " " << *A1 << endl; + e->on = ongequi; + e->v[0]= A0; + e->v[1]= A1; + if(verbosity>99) + cout << i << "+ New P "<< nbv-1 << " " <<sNew<< " L0=" << L0 + << " AB=" << LAB << " s=" << (sNew-L0)/LAB << " se= " + << se <<" B edge " << BTh.Number(ee) << " signe = " << k1 <<" " << A1->r <<endl; + +#ifdef DEBUG + // code \label(xxx) + R2 A1A0 = A1->r - A0->r; + Real8 dp = LengthInterpole(A0->m,A1->m,A1A0); + if (dp > 1.4) { + cerr << " PB new Points "<< nbv-1 ; + cerr << " AB=" << LAB << " s=" << (sNew-L0)/LAB << " se= " ; + cerr << se <<" B edge " << BTh.Number(ee) << " signe = " << k1 <<endl; + cerr << " PB calcul new on cuver points trop loin l=" << dp + << " v=" << nbv-1 << " " << nbv-2 << " Lcurve = " << Lcurve << AB <<v0.m<< v1.m <<endl; + } + +#endif + e->ref = eeequi.ref; + e->adj[0]=PreviousNewEdge; + + if (PreviousNewEdge) + PreviousNewEdge->adj[1] = e; + PreviousNewEdge = e; +#ifdef DRAWING1 + e->Draw(); + // A0->Draw(); + A1->m.Draw(*A1); + A1->Draw(Number(A1)); +#endif + A0=A1; + sNew += Lstep; + // cout << " sNew = " << sNew << " L = " << L + // << " ------" <<NbCreatePointOnCurve << " " << i << endl; + if (++i== NbCreatePointOnCurve) break; + } + + } + assert(ee.on->CurveNumber==ei.on->CurveNumber); + if(verbosity>98) cout << BTh.Number(ee) << " " << " on=" << *ee[k1].on << " "<< ee[k1].on->IsRequiredVertex() << endl; + if ( ee[k1].on->IsRequiredVertex()) { + assert(eeequi[k1equi].on->IsRequiredVertex()); + register GeometricalVertex * GA1 = *eeequi[k1equi].on; + A1=GA1->to;// the vertex in new mesh + assert (A1-vertices>=0 && A1-vertices <nbv); + break;} + if (!ee.adj[k1]) + {cerr << "Error adj edge " << BTh.Number(ee) << ", nbe = " << nbe + << " Gh.vertices " << Gh.vertices + << " k1 = " << k1 << " on=" << *ee[k1].on << endl; + cerr << ee[k1].on->gv-Gh.vertices << endl; + } + pe = ee.adj[k1]; // next edge + k0 = pe->Intersection(ee); + peequi= eeequi.adj[k1equi]; // next edge + k0equi=peequi->Intersection(eeequi); + }// for(;;) end of the curve + + + if (phase) // construction of the last edge + { + Edge *e = edges + nbe++; + if (verbosity>10) + cout << " Fin curve A1" << *A1 << " " << icurve << " <=> " << icurveequi <<"-----" << + NbCreatePointOnCurve << " == " <<i<<endl; + e->on = ongequi; + e->v[0]= A0; + e->v[1]= A1; + e->ref = peequi->ref; + e->adj[0]=PreviousNewEdge; + e->adj[1]=0; + if (PreviousNewEdge) + PreviousNewEdge->adj[1] = e; + PreviousNewEdge = e; + // cout << "Last new edge " << nbe << " " << " on " << Gh.Number(pe->on) + // << " of curve =" <<pe->on->CurveNumber <<endl; + + +#ifdef DRAWING1 + e->Draw(); + A1->Draw(); + A0->Draw(); + // inquire(); +#endif + assert(i==NbCreatePointOnCurve); + + } + } // end loop on equi curve + + if (!phase) { // + Int4 NbSegOnCurve = Max((Int4)(L+0.5),(Int4) 1);// nb of seg + Lstep = L/NbSegOnCurve; + Lcurve = L; + NbCreatePointOnCurve = NbSegOnCurve-1; + + for(Curve * curve= Gh.curves+icurve;curve;curve= curve->next) + { + NbOfNewEdge += NbSegOnCurve; + NbOfNewPoints += NbCreatePointOnCurve; + } + if(verbosity>5) + cout << icurve << " NbSegOnCurve = " << NbSegOnCurve << " Lstep=" + << Lstep <<" " << NbOfNewPoints<< " NBPC= " << NbCreatePointOnCurve <<endl; + // do'nt + // if(NbCreatePointOnCurve<1) break; + } + }//for(phase;;) +/* modif FH add Curve class + }}//for (iedge=0;iedge<BTh.nbe;iedge++) +*/ +// new code Curve class + } // end of curve loop +// end new code + // do the allocation + if(step==0) + { + //if(!NbOfNewPoints) break;// nothing ????? bug + if(nbv+NbOfNewPoints > nbvx) + { + cerr << " Too much vertices on geometry " << nbv+NbOfNewPoints << " >= " << nbvx << endl; + MeshError(3,this); + } + //cout << " NbOfNewEdge" << NbOfNewEdge << " NbOfNewPoints " << NbOfNewPoints << endl; + edges = new Edge[NbOfNewEdge]; + nbex = NbOfNewEdge; + if(NbOfNewPoints) { // + VerticesOnGeomEdge = new VertexOnGeom[NbOfNewPoints]; + NbVertexOnBThEdge =NbOfNewPoints; + VertexOnBThEdge = new VertexOnEdge[NbOfNewPoints]; + NbVerticesOnGeomEdgex = NbOfNewPoints; } + NbOfNewPoints =0; + NbOfNewEdge = 0; + } + } // for(step;;) + assert(nbe); + + delete [] bcurve; + + +#ifdef DRAWING1 + reffecran(); + InitDraw(); + Draw(); + inquire(); +#endif + + Insert(); + ForceBoundary(); + FindSubDomain(); + +#ifdef DRAWING1 + reffecran(); + Draw(); + inquire(); +#endif + // NewPointsOld(*this) ; +// BTh.ReMakeTriangleContainingTheVertex(); // FH change => put in NewPoints + // for (Int4 iv=0;iv<BTh.nbv;iv++) + // BTh[iv].i = toI2(BTh[iv].r); + NewPoints(BTh,KeepBackVertices) ; + CurrentTh = 0; +//#undef DRAWING1 +} + +void Triangles::GeomToTriangles0(Int4 inbvx) +{ + Gh.NbRef++;// add a ref to GH + + + Int4 i,NbOfCurves=0,NbNewPoints,NbEdgeCurve; + Real8 lcurve, lstep,s; +#ifdef DRAWING + if (withrgraphique) + { + Gh.InitDraw() ; + CurrentTh = this; } +#endif + + R2 AB; + GeometricalVertex *a,*b; + Vertex *va,*vb; + GeometricalEdge * e; + PreInit(inbvx); + int background = &BTh != this; + // int SameGeom = background && (&BTh.Gh == &Gh); + nbv = 0; + NbVerticesOnGeomVertex=0; + NbVerticesOnGeomEdge=0; + for (i=0;i<Gh.nbv;i++) + if (Gh[i].Required() && Gh[i].IsThe() ) NbVerticesOnGeomVertex++; + VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex]; +// + if( NbVerticesOnGeomVertex >= nbvx) + { + cerr << " Too much vertices on geometry " << NbVerticesOnGeomVertex << " >= " << nbvx << endl; + MeshError(1,this); + } + for (i=0;i<Gh.nbv;i++) + if (Gh[i].Required()&& Gh[i].IsThe() ) {//Gh vertices Required + if (nbv < nbvx) + vertices[nbv] = Gh[i]; + Gh[i].to = vertices + nbv;// save Geom -> Th + VerticesOnGeomVertex[nbv]= VertexOnGeom(*Gh[i].to,Gh[i]); + // cout << "--------- " <<Number(Gh[i].to) << " " << Gh[i].to << " " << i << endl; + nbv++; + } +// assert( Gh.nbv < nbvx); + + // Method in 2 step: 0 and 1 + // 1) compute de nb of edge + // 2) construct the edge + // generation of the curves + assert(! edges); +#ifdef DRAWING1 + reffecran(); +#endif +// 2 step +// --step=0 to compute the number of edges + alloc at end +// --step=1 to construct the edges + for (int step=0;step<2;step++) + {// for (int step=0;step<2;step++) + Int4 nbex = 0; + nbe = 0; + Int4 NbVerticesOnGeomEdge0=NbVerticesOnGeomEdge; + // cout << " -------------- step =" << step << endl; + Gh.UnMarkEdges(); + NbOfCurves = 0; + for (i=0;i<Gh.nbe;i++) { + GeometricalEdge & ei = Gh.edges[i]; + if (!ei.Dup()) // a good curve (not dup ) + for(int j=0;j<2;j++) + if (!ei.Mark() && ei[j].Required()) { + // warning ei.Mark() can be change in loop for(j=0;j<2;j++) + // cout << " New curve = " << NbOfCurves << endl; + Int4 nbvend =0; + + Edge * PreviousNewEdge=0; + + lstep = -1;//to do not create points + if(ei.Required()) + { + if (j==0) + if(step==0) + nbe++; + else + { + e = & ei; + a=ei(0)->The(); + b=ei(1)->The(); + assert(edges); + edges[nbe].v[0]=a->to; + edges[nbe].v[1]=b->to;; + edges[nbe].ref = e->ref; + edges[nbe].on = e; + edges[nbe].adj[0] = 0; + edges[nbe].adj[1] = 0; +#ifdef DRAWING1 + edges[nbe].Draw(); +#endif + nbe++;} + } + else + { // on curve ------ + for ( int kstep=0;kstep<= step;kstep++) + { // begin for ( int kstep=0;kstep<= step;kstep++) + // if 2nd step where 2 step + // -- 1 compute le length of the curve + // -- create the points and edge + PreviousNewEdge=0; + NbNewPoints=0; + NbEdgeCurve=0; + assert(nbvend < nbvx); + lcurve =0; + s = lstep; + int k=j; + e = & ei; + a=ei(k)->The(); + va = a->to; + e->SetMark(); + // cout << " New curve " ; + + // if SameGeo We have go in the background geometry + // to find the discretisation of the curve + + for(;;) + { + k = 1-k; + b= (*e)(k)->The(); + AB = b->r - a->r; + Metric MA = background ? BTh.MetricAt(a->r) :a->m ; + Metric MB = background ? BTh.MetricAt(b->r) :b->m ; + Real8 ledge = (MA(AB) + MB(AB))/2; + // + const int MaxSubEdge = 10; + int NbSubEdge = 1; + Real8 lSubEdge[MaxSubEdge]; + R2 A,B; + if (ledge < 1.5) + lSubEdge[0] = ledge; + else { + NbSubEdge = Min( MaxSubEdge, (int) (ledge +0.5)); + A= a->r; + Metric MAs =MA,MBs; + // cout << " lSubEdge old=" << ledge + // << " new " << A << MA << endl; + ledge = 0; + Real8 x =0, xstep= 1. / NbSubEdge; + for (int kk=0; kk < NbSubEdge; kk++,A=B,MAs=MBs ) { + x += xstep; + B = e->F(k ? x : 1-x); + MBs= background ? BTh.MetricAt(B) :Metric(1-x, MA, x ,MB); + AB = A-B; + lSubEdge[kk]= (ledge += (MAs(AB)+MBs(AB))/2); + // cout << " " << lSubEdge[kk] << " x " << x + // << " " << A << B << MA << MB<< endl ; + } + // cout << endl; + } + + Real8 lcurveb = lcurve+ ledge ; + while (lcurve<=s && s <= lcurveb && nbv < nbvend) + { + // New points + + // Real8 aa=(lcurveb-s)/ledge; + // Real8 bb=(s-lcurve)/ledge; + + Real8 ss = s-lcurve; + // 1) find the SubEdge containing ss by dichotomie + int kk0=-1,kk1=NbSubEdge-1,kkk; + Real8 ll0=0,ll1=ledge,llk; + while (kk1-kk0>1) + { + if (ss < (llk=lSubEdge[kkk=(kk0+kk1)/2])) + kk1=kkk,ll1=llk; + else + kk0=kkk,ll0=llk;} + assert(kk1 != kk0); + + Real8 sbb = (ss-ll0 )/(ll1-ll0); + Real8 bb = (kk1+sbb)/NbSubEdge, aa=1-bb; + + // new vertex on edge + vb = &vertices[nbv++]; + vb->m = Metric(aa,a->m,bb,b->m); + vb->ReferenceNumber = e->ref; + vb->DirOfSearch =NoDirOfSearch; + Real8 abcisse = k ? bb : aa; + vb->r = e->F( abcisse ); + VerticesOnGeomEdge[NbVerticesOnGeomEdge++]= VertexOnGeom(*vb,*e,abcisse); + + // to take in account the sens of the edge + + s += lstep; + edges[nbe].v[0]=va; + edges[nbe].v[1]=vb; + edges[nbe].ref = e->ref; + edges[nbe].on = e; + edges[nbe].adj[0] = PreviousNewEdge; + if(PreviousNewEdge) + PreviousNewEdge->adj[1] = &edges[nbe]; +#ifdef DRAWING1 + vb->Draw(); + edges[nbe].Draw(); +#endif + PreviousNewEdge = edges + nbe; + nbe++; +#ifdef DEBUG1 + cout << " new points " << nbv-1 << " " << vb->r ; + cout << " new edge " << nbe-1 << " " ; + cout << va << vb << " kk0 = " << kk0 + << " " << kk1 << " ss=" << ss ; + cout << " " << sbb << endl; + cout << " " << aa << va->r << bb << vb->r + <<" length=" << Norme(va->r-vb->r) << endl; + cout << " s " << s << " lstep= " << lstep + << " ledge= " << ledge + << " lcurve= " << lcurve << endl; +#endif + va = vb; + } + lcurve = lcurveb; + e->SetMark(); + // cout << e-Gh.edges << ", " << k << " " + // <<(*e)[k].r <<" " <<(*e)[1-k].r <<" " + // << lcurve<< ";; " ; + a=b; + if (b->Required() ) break; + int kprev=k; + k = e->SensAdj[kprev];// next vertices + e = e->Adj[kprev]; + assert(e); + }// for(;;) + vb = b->to; + // cout << endl; + NbEdgeCurve = Max((Int4) (lcurve +0.5), (Int4) 1); + NbNewPoints = NbEdgeCurve-1; + if(!kstep) + { NbVerticesOnGeomEdge0 += NbNewPoints; + NbOfCurves++;} + + nbvend=nbv+NbNewPoints; + + lstep = lcurve / NbEdgeCurve; + // cout <<"lstep " << lstep << " lcurve " + // << lcurve << " NbEdgeCurve " << NbEdgeCurve << " " <<NbVerticesOnGeomEdge0<<" " <<NbVerticesOnGeomEdge<<" step =" <<step<< endl; + } + // end of curve -- + if (edges) { // last edges of the curves + edges[nbe].v[0]=va; + edges[nbe].v[1]=vb; + edges[nbe].ref = e->ref; + edges[nbe].on = e; + edges[nbe].adj[0] = PreviousNewEdge; + edges[nbe].adj[1] = 0; + if(PreviousNewEdge) + PreviousNewEdge->adj[1] = & edges[nbe]; + + +#ifdef DRAWING1 + edges[nbe].Draw(); +#endif + nbe++;} + else + nbe += NbEdgeCurve; + } // end on curve --- + } // if (edges[i][j].Corner()) + } // for (i=0;i<nbe;i++) + if(!step) { + // cout << "edges " << edges << " VerticesOnGeomEdge " <<VerticesOnGeomEdge << endl; + assert(!edges); + assert(!VerticesOnGeomEdge); + edges = new Edge[nbex=nbe]; + if(NbVerticesOnGeomEdge0) + VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge0]; + assert(edges); + assert(VerticesOnGeomEdge || NbVerticesOnGeomEdge0 ==0); + // do the vertex on a geometrical vertex + NbVerticesOnGeomEdge0 = NbVerticesOnGeomEdge; + } + else + assert(NbVerticesOnGeomEdge == NbVerticesOnGeomEdge0); + // cout << " Nb of Curves = " << NbOfCurves << "nbe = " << nbe + // << "== " << nbex << " nbv = " << nbv << endl; + assert(nbex=nbe); + } // for (step=0;step<2;step++) + +#ifdef DRAWING1 + reffecran(); + InitDraw(); + Draw(); + inquire(); +#endif + + Insert(); + ForceBoundary(); + FindSubDomain(); + +#ifdef DRAWING1 + reffecran(); + Draw(); + inquire(); +#endif + // NewPointsOld(*this) ; + NewPoints(*this,0) ; + CurrentTh = 0; +} + +Edge** Triangles::MakeGeometricalEdgeToEdge() + { + assert(Gh.nbe); + Edge **e= new (Edge* [Gh.nbe]); + + Int4 i; + for ( i=0;i<Gh.nbe ; i++) + e[i]=NULL; + for ( i=0;i<nbe ; i++) + { + Edge * ei = edges+i; + GeometricalEdge *on = ei->on; + e[Gh.Number(on)] = ei; + } + for ( i=0;i<nbe ; i++) + for (int ii=0;ii<2;ii++) { + Edge * ei = edges+i; + GeometricalEdge *on = ei->on; + int j= ii; + while (!(*on)[j].Required()) { + // cout << i << " " << ii << " j= " << j << " curve = " + // << on->CurveNumber << " " << Gh.Number(on) << " on " << j + // << " s0 " << Gh.Number( (*on)[0]) << " s1 " << Gh.Number( (*on)[1]) + // << " -> " ; + Adj(on,j); // next geom edge + j=1-j; + // cout << Gh.Number(on) << " " << j << " e[ON] = " << e[Gh.Number(on)] + // << " s0 " << Gh.Number( (*on)[0]) << " s1 " << Gh.Number( (*on)[1]) << endl; + if (e[Gh.Number(on)]) break; // optimisation + e[Gh.Number(on)] = ei; + } + } + + int kk=0; + for ( i=0;i<Gh.nbe ; i++) + if (!e[i]) + if(kk++<10) { + cerr << " Bug -- the geometrical edge " << i << " is on no edge curve = " << Gh.edges[i].CurveNumber + << " s0 " << Gh.Number( Gh.edges[i][0]) << " s1 " << Gh.Number( Gh.edges[i][1]) << endl; + // assert( e[i]); + } + if(kk) MeshError(997,this); + + return e; + } + +Triangles::~Triangles() +{ + assert(NbRef<=0); + if (CurrentTh == this) CurrentTh=0; + if(verbosity>10) + cout << " ~Triangles "<< this <<" "<< identity << endl; + if(vertices) delete [] vertices; + if(edges) delete [] edges; + if(triangles) delete [] triangles; + if(quadtree) delete quadtree; + if(ordre) delete [] ordre; + if( subdomains) delete [] subdomains; + if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge; + if (VerticesOnGeomVertex) delete [] VerticesOnGeomVertex; + if (name) delete [] name; + if (identity) delete [] identity; + if (VertexOnBThVertex) delete [] VertexOnBThVertex; + if (VertexOnBThEdge) delete [] VertexOnBThEdge; + + if (&Gh) + { + if (Gh.NbRef>0) Gh.NbRef--; + else if (Gh.NbRef==0) delete &Gh; + } + if (&BTh && (&BTh != this)) + { + if (BTh.NbRef>0) BTh.NbRef--; + else if (BTh.NbRef==0) delete &BTh; + } + PreInit(0); // set all to zero + +} + +void Triangles::SetIntCoor(const char * strfrom) +{ + pmin = vertices[0].r; + pmax = vertices[0].r; + + // recherche des extrema des vertices pmin,pmax + Int4 i; + for (i=0;i<nbv;i++) { + pmin.x = Min(pmin.x,vertices[i].r.x); + pmin.y = Min(pmin.y,vertices[i].r.y); + pmax.x = Max(pmax.x,vertices[i].r.x); + pmax.y = Max(pmax.y,vertices[i].r.y); + } + R2 DD = (pmax-pmin)*0.05; + pmin = pmin-DD; + pmax = pmax+DD; + coefIcoor= (MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y)); + assert(coefIcoor >0); + + // generation of integer coord + for (i=0;i<nbv;i++) { + vertices[i].i = toI2(vertices[i].r); + } +#ifdef DRAWING + xGrafCoef = coefIcoor; + yGrafCoef = coefIcoor; + xGrafOffSet = pmin.x; + yGrafOffSet = pmin.y; +#ifdef DRAWING1 + rattente(1); +#endif +#endif + + // computation of the det + int Nberr=0; + for (i=0;i<nbt;i++) + { + Vertex & v0 = triangles[i][0]; + Vertex & v1 = triangles[i][1]; + Vertex & v2 = triangles[i][2]; + if ( &v0 && &v1 && &v2 ) // a good triangles; + { + triangles[i].det= det(v0,v1,v2); + if (triangles[i].det <=0 && Nberr++ <10) + { + if(Nberr==1) + if (strfrom) + cerr << "+++ Fatal Error " << strfrom << "(SetInCoor) Error : area of Triangle < 0 " << endl; + else + cerr << "+++ Fatal Error Triangle (in SetInCoor) area of Triangle < 0" << endl; + cerr << " Triangle " << i << " det (I2) = " << triangles[i].det ; + cerr << " (R2) " << Det(v1.r-v0.r,v2.r-v0.r); + cerr << "; The 3 vertices " << endl; + cerr << Number(v0) << " " << Number(v1) << " " + << Number(v2) << " : " ; + cerr << v0.r << v1.r << v2.r << " ; "; + cerr << v0.i << v1.i << v2.i << endl; + } + } + else + triangles[i].det= -1; // Null triangle; + } + if (Nberr) MeshError(899,this); + +} + +void Triangles::FillHoleInMesh() +{ + Triangles * OldCurrentTh =CurrentTh; + CurrentTh=this; + // Int4 NbTold = nbt; + // generation of the integer coor + { + + // double coef = coefIcoor; + // recherche des extrema des vertices pmin,pmax + Int4 i; + if(verbosity>2) + cout << " -- FillHoleInMesh: Nb of vertices =" << nbv + << " Pmin = "<< pmin << " Pmax = "<< pmax << endl; + + assert(ordre); + for (i=0;i<nbv;i++) + ordre[i]= 0 ; + + + NbSubDomains =0; + + // generation of the adjacence of the triangles + SetOfEdges4 * edge4= new SetOfEdges4(nbt*3,nbv); + Int4 * st = new Int4[nbt*3]; + for (i=0;i<nbt*3;i++) + st[i]=-1; + Int4 kk =0; + for (i=0;i<nbe;i++) + kk += (i == edge4->addtrie(Number(edges[i][0]),Number(edges[i][1]))); + if (kk != nbe) + { + cerr << " Some Double edge in the mesh, the number is " << kk-nbe << endl; + MeshError(1002,this); + } + for (i=0;i<nbt;i++) + for (int j=0;j<3;j++) + { + // Int4 i0,i1; + Int4 k =edge4->addtrie(Number(triangles[i][VerticesOfTriangularEdge[j][0]]), + Number(triangles[i][VerticesOfTriangularEdge[j][1]])); + Int4 invisible = triangles[i].Hidden(j); + if(st[k]==-1) + st[k]=3*i+j; + else if(st[k]>=0) { + assert( ! triangles[i].TriangleAdj(j) && !triangles[st[k] / 3].TriangleAdj((int) (st[k]%3))); + + triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3)); + if (invisible) triangles[i].SetHidden(j); + if (k<nbe) { + triangles[i].SetLocked(j); + } + st[k]=-2-st[k]; } + else { + cerr << " The edge (" + << Number(triangles[i][VerticesOfTriangularEdge[j][0]]) + << " , " + << Number(triangles[i][VerticesOfTriangularEdge[j][1]]) + << " ) is in more than 2 triangles " <<k <<endl; + cerr << " Edge " << j << " Of Triangle " << i << endl; + cerr << " Edge " << (-st[k]+2)%3 << " Of Triangle " << (-st[k]+2)/3 << endl; + cerr << " Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3)) + << " Of Triangle " << Number(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) << endl; + MeshError(9999,this);} + + + } + if(verbosity>5) { + cout << " On Mesh " << name << endl; + cout << " - The number of Vertices = " << nbv << endl; + cout << " - The number of Triangles = " << nbt << endl; + cout << " - The number of given edge = " << nbe << endl; + cout << " - The number of all edges = " << edge4->nb() << endl; + cout << " - The Euler number = 1-Nb Of Hole = " << nbt-edge4->nb()+nbv << endl; } + + + // check the consistant of edge[].adj and the geometrical required vertex + Int4 k=0; + for (i=0;i<edge4->nb();i++) + if (st[i] >=0) // edge alone + if (i < nbe) + { + Int4 i0=edge4->i(i);ordre[i0] = vertices+i0; + Int4 i1=edge4->j(i);ordre[i1] = vertices+i1; + } + else { + k++; + if (verbosity>20 && k <20) + { + Int4 i0=edge4->i(i); + Int4 i1=edge4->j(i); + cerr << " Lose boundary edges " << i << " : " << i0 << " " << i1 << endl; + } + } + + if(k != 0) { + if (verbosity>20) + { + cout << " The given edge are " << endl; + for (int i=0;i< nbe;i++) + cout << " Edge " << i << " : " << Number(edges[i][0]) << " " << Number(edges[i][1]) + << " " << edges[i].ref << endl; + } + cerr << k << " boundary edges are not defined as edges " << endl; + MeshError(9998,this); + } + // generation of the mesh with boundary points + Int4 nbvb = 0; + for (i=0;i<nbv;i++) + { + vertices[i].t=0; + vertices[i].vint=0; + if (ordre[i]) + ordre[nbvb++] = ordre[i]; + } + + Triangle *savetriangles= triangles; + Int4 savenbt=nbt; + Int4 savenbtx=nbtx; + SubDomain * savesubdomains = subdomains; + subdomains = 0; + + Int4 Nbtriafillhole = 2*nbvb; + Triangle * triafillhole =new Triangle[Nbtriafillhole]; + if (verbosity>9) + cout << " Nbtriafillhole triafillhole*" << triafillhole << endl; + triangles = triafillhole; + + nbt=2; + nbtx= Nbtriafillhole; + + for (i=2 ; det( ordre[0]->i, ordre[1]->i, ordre[i]->i ) == 0;) + if ( ++i >= nbvb) { + cerr << "FillHoleInMesh: All the vertices are aline " << nbvb << endl; + MeshError(998,this); } + Exchange( ordre[2], ordre[i]); + + Vertex * v0=ordre[0], *v1=ordre[1]; + + + triangles[0](0) = 0; // sommet pour infini + triangles[0](1) = v0; + triangles[0](2) = v1; + + triangles[1](0) = 0;// sommet pour infini + triangles[1](2) = v0; + triangles[1](1) = v1; + const int e0 = OppositeEdge[0]; + const int e1 = NextEdge[e0]; + const int e2 = PreviousEdge[e0]; + triangles[0].SetAdj2(e0, &triangles[1] ,e0); + triangles[0].SetAdj2(e1, &triangles[1] ,e2); + triangles[0].SetAdj2(e2, &triangles[1] ,e1); + + triangles[0].det = -1; // faux triangles + triangles[1].det = -1; // faux triangles + + triangles[0].SetTriangleContainingTheVertex(); + triangles[1].SetTriangleContainingTheVertex(); + + triangles[0].link=&triangles[1]; + triangles[1].link=&triangles[0]; + +#ifdef DEBUG + triangles[0].check(); + triangles[1].check(); +#endif + // nbtf = 2; + if ( !quadtree ) + delete quadtree; // ->ReInitialise(); + + quadtree = new QuadTree(this,0); + quadtree->Add(*v0); + quadtree->Add(*v1); + + // on ajoute les sommets un a un + Int4 NbSwap=0; + for (Int4 icount=2; icount<nbvb; icount++) { + + Vertex *vi = ordre[icount]; + // cout << " Add vertex " << Number(vi) << endl; + Icoor2 dete[3]; + Triangle *tcvi = FindTriangleContening(vi->i,dete); + quadtree->Add(*vi); + Add(*vi,tcvi,dete); + NbSwap += vi->Optim(1,1); + +#ifdef DRAWING2 + cout << Number(vi) << " " << NbSwap << endl; + reffecran(); + Draw(); + vi->Draw(); + inquire(); +#endif + }// end loop on icount +#ifdef DRAWING1 + inquire(); +#endif + + //Int4 nbtfillhole = nbt; + // inforce the boundary + TriangleAdjacent ta(0,0); + Int4 nbloss = 0,knbe=0; + for ( i = 0; i < nbe; i++) + if (st[i] >=0) // edge alone => on border ... FH oct 2009 + { + Vertex & a=edges[i][0], & b = edges[i][1]; + if (a.t && b.t) // le bug est la si maillage avec des bod non raffine 1. + { + knbe++; + if (ForceEdge(a,b,ta)<0) + nbloss++; + } + } + if(nbloss) + { + cerr << " we loss some " << nbloss << " " << " edges other " << knbe << endl; + MeshError(1100,this); + } + FindSubDomain(1); + // remove all the hole + // remove all the good sub domain + Int4 krm =0; + for (i=0;i<nbt;i++) + if (triangles[i].link) // remove triangles + { + krm++; + for (int j=0;j<3;j++) + { + TriangleAdjacent ta = triangles[i].Adj(j); + Triangle & tta = * (Triangle *) ta; + if(! tta.link) // edge between remove and not remove + { // change the link of ta; + int ja = ta; + Vertex *v0= ta.EdgeVertex(0); + Vertex *v1= ta.EdgeVertex(1); + Int4 k =edge4->addtrie(v0?Number(v0):nbv,v1? Number(v1):nbv); + assert(st[k] >=0); + tta.SetAdj2(ja,savetriangles + st[k] / 3,(int) (st[k]%3)); + ta.SetLock(); + st[k]=-2-st[k]; + } + } + } + Int4 NbTfillHoll =0; + for (i=0;i<nbt;i++) + if (triangles[i].link) { + triangles[i]=Triangle((Vertex *) NULL,(Vertex *) NULL,(Vertex *) NULL); + triangles[i].color=-1; + } + else + { + triangles[i].color= savenbt+ NbTfillHoll++; +#ifdef DEBUG + triangles[i].check(); +#endif + } + // cout << savenbt+NbTfillHoll << " " << savenbtx << endl; + assert(savenbt+NbTfillHoll <= savenbtx ); + // copy of the outside triangles in saveTriangles + for (i=0;i<nbt;i++) + if(triangles[i].color>=0) + { + savetriangles[savenbt]=triangles[i]; + savetriangles[savenbt].link=0; + savenbt++; + } + // gestion of the adj + k =0; + Triangle * tmax = triangles + nbt; + for (i=0;i<savenbt;i++) + { + Triangle & ti = savetriangles[i]; + for (int j=0;j<3;j++) + { + Triangle * ta = ti.TriangleAdj(j); + int aa = ti.NuEdgeTriangleAdj(j); + int lck = ti.Locked(j); + if (!ta) k++; // bug + else if ( ta >= triangles && ta < tmax) + { + ta= savetriangles + ta->color; + ti.SetAdj2(j,ta,aa); + if(lck) ti.SetLocked(j); + } + } + } + // OutSidesTriangles = triangles; + // Int4 NbOutSidesTriangles = nbt; + + // restore triangles; + nbt=savenbt; + nbtx=savenbtx; + delete [] triangles; + delete [] subdomains; + triangles = savetriangles; + subdomains = savesubdomains; + // cout << triangles << " <> " << OutSidesTriangles << endl; + /* k=0; + for (i=0;i<nbt;i++) + for (int j=0;j<3;j++) + if (!triangles[i].TriangleAdj(j)) + k++; + */ + if (k) { + cerr << "Error Nb of triangles edge alone = " << k << endl; + MeshError(9997,this); + } + FindSubDomain(); + // cout << " NbTOld = " << NbTold << " == " << nbt - NbOutT << " " << nbt << endl; + + // + + delete edge4; + delete [] st; + for (i=0;i<nbv;i++) + quadtree->Add(vertices[i]); + + SetVertexFieldOn(); + + for (i=0;i<nbe;i++) + if(edges[i].on) + for(int j=0;j<2;j++) + if (!edges[i].adj[j]) + if(!edges[i][j].on->IsRequiredVertex()) { + cerr << " Erreur adj et sommet requis edges [" << i << "][ " << j << "]= " + << Number(edges[i][j]) << " : " << " on = " << Gh.Number(edges[i].on) ; + if (edges[i][j].on->OnGeomVertex()) + cerr << " vertex " << Gh.Number(edges[i][j].on->gv); + else if (edges[i][j].on->OnGeomEdge()) + cerr << "Edges " << Gh.Number(edges[i][j].on->ge); + else + cerr << " = " << edges[i][j].on ; + cerr << endl; + } + +#ifdef DRAWING1 + InitDraw(); +#endif + + } + CurrentTh=OldCurrentTh; +} + +Triangles::Triangles(Triangles & Th,Geometry * pGh,Triangles * pBth,Int4 nbvxx) // COPY OPERATOR +: Gh(*(pGh?pGh:&Th.Gh)), BTh(*(pBth?pBth:this)) +{ + Gh.NbRef++; + nbvxx = Max(nbvxx,Th.nbv); + Int4 i; + // do all the allocation to be sure all the pointer existe + + char * cname = 0; + if (Th.name) + { + cname = new char[strlen(Th.name)+1]; + strcpy(cname,Th.name); + } + PreInit(nbvxx,cname);// to make the allocation + // copy of triangles + nt=Th.nt; + nbv = Th.nbv; + nbt = Th.nbt; + nbiv = Th.nbiv; + nbe = Th.nbe; + NbSubDomains = Th.NbSubDomains; + NbOutT = Th.NbOutT; + NbOfQuad = Th.NbOfQuad ; + NbOfSwapTriangle =0; + NbVerticesOnGeomVertex = Th.NbVerticesOnGeomVertex; + if(NbVerticesOnGeomVertex) + VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex]; + NbVerticesOnGeomEdge = Th.NbVerticesOnGeomEdge; + if (NbVerticesOnGeomEdge) + VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge] ; + if (& BTh == & Th.BTh) // same back ground + { + BTh.NbRef++; + NbVertexOnBThVertex = Th.NbVertexOnBThVertex; + if(NbVertexOnBThVertex) + VertexOnBThVertex = new VertexOnVertex[NbVertexOnBThVertex]; + NbVertexOnBThEdge = Th.NbVertexOnBThEdge; + if(NbVertexOnBThEdge) + VertexOnBThEdge = new VertexOnEdge[NbVertexOnBThEdge]; + } + else + { // no add on back ground mesh + BTh.NbRef++; + NbVertexOnBThVertex=0; + VertexOnBThVertex=0; + NbVertexOnBThEdge=0; + VertexOnBThEdge=0; + // assert (& BTh == this); // --- a voir + + } + + + if(nbe) + edges = new Edge[nbe]; + if(NbSubDomains) + subdomains = new SubDomain[NbSubDomains]; + pmin = Th.pmin; + pmax = Th.pmax; + coefIcoor = Th.coefIcoor; + for(i=0;i<nbt;i++) + triangles[i].Set(Th.triangles[i],Th,*this); + for(i=0;i<nbe;i++) + edges[i].Set(Th,i,*this); + for(i=0;i<nbv;i++) + vertices[i].Set(Th.vertices[i],Th,*this); + for(i=0;i<NbSubDomains;i++) + subdomains[i].Set(Th,i,*this); + for (i=0;i<NbVerticesOnGeomVertex;i++) + VerticesOnGeomVertex[i].Set(Th.VerticesOnGeomVertex[i],Th,*this); + for (i=0;i<NbVerticesOnGeomEdge;i++) + VerticesOnGeomEdge[i].Set(Th.VerticesOnGeomEdge[i],Th,*this); + quadtree=0; + + + // assert(!OutSidesTriangles); +} + +/** -- old with a bug we loss some time last swap + +Int4 Triangle::Optim(Int2 i,int koption) +{ + // turn in the positif sens around vertex s + register Int4 NbSwap =0; + register Vertex * s = ns[i]; + register Triangle * tbegin=0 , *t = this , *ttc; + register int k=0,j = EdgesVertexTriangle[i][0],jc; + tbegin=t; + do { + k++; +#ifdef DEBUG + assert( s == & (*t)[VerticesOfTriangularEdge[j][1]] ); +#endif +#ifdef DRAWING1 + t->Draw(); + DrawMark( s->r); +#endif + ttc = t->at[j]; + jc = NextEdge[t->aa[j]&3]; + cout << *t << " " << VerticesOfTriangularEdge[j][1] << "\n\t try swap " << * ttc << " " << jc ; + while ( ttc->swap(jc,koption)) { + NbSwap++,assert(k++<20000); + ttc = t->at[j]; + jc = NextEdge[t->aa[j]&3]; + cout << "\n\t s " << *ttc << " " << jc << endl; + } + cout << endl; + t = ttc; + j = NextEdge[jc]; + assert(k<20000); + } while ( (tbegin != t)); + + return NbSwap; +} +*/ +Int4 Triangle::Optim(Int2 i,int koption) +{ + // turne around in positif sens + Int4 NbSwap =0; +#ifdef DEBUG + Vertex * s = ns[i]; +#endif + Triangle *t = this; + int k=0,j =OppositeEdge[i]; + int jp = PreviousEdge[j]; + // initialise tp, jp the previous triangle & edge + Triangle *tp= at[jp]; + jp = aa[jp]&3; +#ifdef DEBUG + assert(tp->at[jp] == this); +#endif + do { +#ifdef DEBUG + assert(k++<20000); + assert( s == & (*t)[OppositeVertex[j]] ); +#endif + // cout << *t << " " << j << "\n\t try swap " ; + while (t->swap(j,koption)) + { + NbSwap++; + assert(k++<20000); + t= tp->at[jp]; // set unchange t qnd j for previous triangles + j= NextEdge[tp->aa[jp]&3]; + // cout << "\n\t s " << *t << " " << j << endl; +#ifdef DEBUG + assert( s == & (*t)[OppositeVertex[j]] ); +#endif + } + // end on this Triangle + tp = t; + jp = NextEdge[j]; + + t= tp->at[jp]; // set unchange t qnd j for previous triangles + j= NextEdge[tp->aa[jp]&3]; + + } while( t != this); + return NbSwap; +} + + void Triangles::SmoothingVertex(int nbiter,Real8 omega ) + { + // if quatree exist remove it end reconstruct + if (quadtree) delete quadtree; + quadtree=0; + ReMakeTriangleContainingTheVertex(); + Triangle vide; // a triangle to mark the boundary vertex + Triangle ** tstart= new Triangle* [nbv]; + Int4 i,j,k; + // attention si Background == Triangle alors on ne peut pas utiliser la rechech rapide + if ( this == & BTh) + for ( i=0;i<nbv;i++) + tstart[i]=vertices[i].t; + else + for ( i=0;i<nbv;i++) + tstart[i]=0; + for ( j=0;j<NbVerticesOnGeomVertex;j++ ) + tstart[ Number(VerticesOnGeomVertex[j].mv)]=&vide; + for ( k=0;k<NbVerticesOnGeomEdge;k++ ) + tstart[ Number(VerticesOnGeomEdge[k].mv)]=&vide; + if(verbosity>2) + cout << " -- SmoothingVertex: nb Iteration = " << nbiter << " Omega = " << omega << endl; + for (k=0;k<nbiter;k++) + { + Int4 i,NbSwap =0; + Real8 delta =0; + for ( i=0;i<nbv;i++) + if (tstart[i] != &vide) // not a boundary vertex + delta=Max(delta,vertices[i].Smoothing(*this,BTh,tstart[i],omega)); + if (!NbOfQuad) + for ( i=0;i<nbv;i++) + if (tstart[i] != &vide) // not a boundary vertex + NbSwap += vertices[i].Optim(1); + if (verbosity>3) + cout << " Move max = " << sqrt(delta) << " iteration = " + << k << " Nb of Swap = " << NbSwap << endl; + } + + delete [] tstart; + if (quadtree) quadtree= new QuadTree(this); + } +void Triangles::MakeQuadTree() +{ + if(verbosity>8) + cout << " MakeQuadTree" << endl; + if ( !quadtree ) quadtree = new QuadTree(this); + + +#ifdef DRAWING1 + quadtree->Draw(); + rattente(1); + reffecran(); + quadtree->Draw(); + rattente(1); +#endif + +} +void Triangles::ShowRegulaty() const// Add FH avril 2007 +{ + const Real8 sqrt32=sqrt(3.)*0.5; + const Real8 aireKh=sqrt32*0.5; + D2 Beq(1,0),Heq(0.5,sqrt32); + D2xD2 Br(D2xD2(Beq,Heq).t()); + D2xD2 B1r(Br.inv()); + /* D2xD2 BB = Br.t()*Br; + cout << " BB = " << BB << " " << Br*B1r << endl; + MetricAnIso MMM(BB.x.x,BB.x.y,BB.y.y); + MatVVP2x2 VMM(MMM); + cout << " " << VMM.lambda1 << " " << VMM.lambda2 << endl; + */ + double gammamn=1e100,hmin=1e100; + double gammamx=0,hmax=0; + double beta=1e100; + double beta0=0; + double alpha2=0; + double area=0,Marea=0; + // Real8 cf= Real8(coefIcoor); + // Real8 cf2= 6.*cf*cf; + int nt=0; + for (int it=0;it<nbt;it++) + if ( triangles[it].link) + { + nt++; + Triangle &K=triangles[it]; + Real8 area3= Area2((R2) K[0],(R2) K[1],(R2) K[2])/6.; + area+= area3; + D2xD2 B_Kt(K[0],K[1],K[2]); + D2xD2 B_K(B_Kt.t()); + D2xD2 B1K = Br*B_K.inv(); + D2xD2 BK = B_K*B1r; + D2xD2 B1B1 = B1K.t()*B1K; + MetricAnIso MK(B1B1.x.x,B1B1.x.y,B1B1.y.y); + MatVVP2x2 VMK(MK); + alpha2 = Max(alpha2,Max(VMK.lambda1/VMK.lambda2,VMK.lambda2/VMK.lambda1)); + // cout << B_K << " * " << B1r << " == " << BK << " " << B_K*B_K.inv() << endl; + Real8 betaK=0; + + for (int j=0;j<3;j++) + { + Real8 he= Norme2(R2(K[j],K[(j+1)%3])); + hmin=Min(hmin,he); + hmax=Max(hmax,he); + Vertex & v=K[j]; + D2xD2 M((MetricAnIso)v); + betaK += sqrt(M.det()); + + D2xD2 BMB = BK.t()*M*BK; + MetricAnIso M1(BMB.x.x,BMB.x.y,BMB.y.y); + MatVVP2x2 VM1(M1); + //cout << B_K <<" " << M << " " << he << " " << BMB << " " << VM1.lambda1 << " " << VM1.lambda2<< endl; + gammamn=Min3(gammamn,VM1.lambda1,VM1.lambda2); + gammamx=Max3(gammamx,VM1.lambda1,VM1.lambda2); + } + betaK *= area3;// 1/2 (somme sqrt(det))* area(K) + Marea+= betaK; + // cout << betaK << " " << area3 << " " << beta << " " << beta0 << " " << area3*3*3*3 <<endl; + beta=min(beta,betaK); + beta0=max(beta0,betaK); + } + area*=3; + gammamn=sqrt(gammamn); + gammamx=sqrt(gammamx); + cout << " -- adaptmesh Regulary: Nb triangles " << nt << " , h min " << hmin << " , h max " << hmax << endl; + cout << " area = " << area << " , M area = " << Marea << " , M area/( |Khat| nt) " << Marea/(aireKh*nt) << endl; + cout << " infiny-regulaty: min " << gammamn << " max " << gammamx << endl; + cout << " anisomax "<< sqrt(alpha2) << ", beta max = " << 1./sqrt(beta/aireKh) + << " min "<< 1./sqrt(beta0/aireKh) << endl; +} +void Triangles::ShowHistogram() const + { + + const Int4 kmax=10; + const Real8 llmin = 0.5,llmax=2; + const Real8 lmin=log(llmin),lmax=log(llmax),delta= kmax/(lmax-lmin); + Int4 histo[kmax+1]; + Int4 i,it,k, nbedges =0; + for (i=0;i<=kmax;i++) histo[i]=0; + for (it=0;it<nbt;it++) + if ( triangles[it].link) + { + + for (int j=0;j<3;j++) + { + Triangle *ta = triangles[it].TriangleAdj(j); + if ( !ta || !ta->link || Number(ta) >= it) + { + Vertex & vP = triangles[it][VerticesOfTriangularEdge[j][0]]; + Vertex & vQ = triangles[it][VerticesOfTriangularEdge[j][1]]; + if ( !& vP || !&vQ) continue; + R2 PQ = vQ.r - vP.r; + Real8 l = log(LengthInterpole(vP,vQ,PQ)); +#ifdef DRAWING2 + if (l>1.4) { + penthickness(3); + vP.MoveTo(),vQ.LineTo(); + penthickness(1); + cout << " l = " << l << Number(vP) << " edge = " << Number(vQ) << endl; + } +#endif + nbedges++; + k = (int) ((l - lmin)*delta); + k = Min(Max(k,0L),kmax); + histo[k]++; + } + } + } + cout << " -- Histogram of the unit mesh, nb of edges" << nbedges << endl <<endl; + + cout << " length of edge in | % of edge | Nb of edges " << endl; + cout << " ------------------- | ---------- | ----------- " << endl; + for (i=0;i<=kmax;i++) + { + cout << " " ; + cout.width(10); + if (i==0) cout << " 0 " ; + else cout << exp(lmin+i/delta) ; + cout.width(); cout << "," ; + cout.width(10); + if (i==kmax) cout << " +infty " ; + else cout << exp(lmin+(i+1)/delta) ; + cout.width();cout << " | " ; + + cout.precision(4); + cout.width(6); + cout << ((long) ((10000.0 * histo[i])/ nbedges))/100.0 ; + cout.width(); + cout.precision(); + cout << " | " << histo[i] <<endl; + } + cout << " ------------------- | ---------- | ----------- " << endl <<endl; + + } + +int Triangles::Crack() + { + assert(NbCrackedEdges ==0 || NbCrackedVertices >0); + for (int i=0;i<NbCrackedEdges;i++) + CrackedEdges[i].Crack(); + return NbCrackedEdges; + } + +int Triangles::UnCrack() +{ + assert(NbCrackedEdges ==0 || NbCrackedVertices >0); + for (int i=0;i<NbCrackedEdges;i++) + CrackedEdges[i].UnCrack(); + return NbCrackedEdges; +} + +int Triangles::CrackMesh() +{ + Triangles *CurrentThOld = CurrentTh; + // computed the number of cracked edge + int i,k; + for (k=i=0;i<nbe;i++) + if(edges[i].on->Cracked()) k++; + if( k==0) return 0; + CurrentTh = this; + cout << " Nb of Cracked Edges = " << k << endl; + NbCrackedEdges =k; + CrackedEdges = new CrackedEdge[k]; + // new edge + Edge * e = new Edge[ nbe + k]; + + // copy + for (i=0;i<nbe;i++) + e[i] = edges[i]; + delete edges; + edges = e; + + const int nbe0 = nbe; + for (k=i=0;i<nbe0;i++) // on double les arete cracked + if(edges[i].on->Cracked()) + { + e[nbe] = e[i]; + // return the edge + e[nbe].v[0] = e[i].v[1]; + e[nbe].v[1] = e[i].v[0]; + e[nbe].on = e[i].on->link ; // fqux + CrackedEdges[k++]=CrackedEdge(edges,i,nbe); + nbe++; + } + ReMakeTriangleContainingTheVertex() ; + // + int nbcrakev =0; + Vertex *vlast = vertices + nbv; + Vertex *vend = vertices + nbvx; // end of array + for (int iv=0;iv<nbv;iv++) // vertex + { + Vertex & v= vertices[iv]; + Vertex * vv = & v; + int kk=0; // nb cracked + int kc=0; + int kkk =0; // nb triangle with same number + Triangle * tbegin = v.t; + int i = v.vint; + assert(tbegin && (i >= 0 ) && (i <3)); + // turn around the vertex v + TriangleAdjacent ta(tbegin,EdgesVertexTriangle[i][0]);// previous edge + int k=0; + do { + int kv = VerticesOfTriangularEdge[ta][1]; + k++; + Triangle * tt (ta); + if ( ta.Cracked() ) + { + TriangleAdjacent tta=(ta.Adj()); + assert(tta.Cracked()); + if ( kk == 0) tbegin=ta,kkk=0; // begin by a cracked edge => restart + if ( kkk ) { kc =1;vv = vlast++; kkk = 0; } // new vertex if use + kk++;// number of cracked edge view + } + if ( tt->link ) { // if good triangles store the value + int it = Number(tt); + assert(it < nt); + (*tt)(kv)= vv; // Change the vertex of triangle + if(vv<vend) {*vv= v;vv->ReferenceNumber=iv;} // copy the vertex value + store the old vertex number in ref + // tt->SetTriangleContainingTheVertex(); + kkk++; + } else if (kk) { // crack + boundary + if ( kkk ) { kc =1;vv = vlast++; kkk = 0; } // new vertex if use + } + + ta = Next(ta).Adj(); + } while ( (tbegin != ta)); + assert(k); + if (kc) nbcrakev++; + } + + if ( nbcrakev ) + for (int iec =0;iec < NbCrackedEdges; iec ++) + CrackedEdges[iec].Set(); + + // set the ref + cout << " set the ref " << endl ; + NbCrackedVertices = nbcrakev; + // int nbvo = nbv; + nbv = vlast - vertices; + int nbnewv = nbv - nbv; // nb of new vrtices + if (nbcrakev && verbosity > 1 ) + cout << " Nb of craked vertices = " << nbcrakev << " Nb of created vertices " << nbnewv<< endl; + // all the new vertices are on geometry + // BOFBO-- A VOIR + if (nbnewv) + { // + Int4 n = nbnewv+NbVerticesOnGeomVertex; + Int4 i,j,k; + VertexOnGeom * vog = new VertexOnGeom[n]; + for ( i =0; i<NbVerticesOnGeomVertex;i++) + vog[i]=VerticesOnGeomVertex[i]; + delete [] VerticesOnGeomVertex; + VerticesOnGeomVertex = vog; + // loop on cracked edge + Vertex * LastOld = vertices + nbv - nbnewv; + for (int iec =0;iec < NbCrackedEdges; iec ++) + for (k=0;k<2;k++) + { + Edge & e = *( k ? CrackedEdges[iec].a.edge : CrackedEdges[iec].b.edge); + for (j=0;j<2;j++) + { + Vertex * v = e(j); + if ( v >= LastOld) + { // a new vertex + Int4 old = v->ReferenceNumber ; // the old same vertex + Int4 i = ( v - LastOld); + // if the old is on vertex => warning + // else the old is on edge => ok + vog[i] = vog[old]; + // vog[i].mv = v; + //g[i].ge = ; + //og[i].abcisse = ; + } + + } + } + + NbVerticesOnGeomVertex = n; + } + SetVertexFieldOn(); + + + if (vlast >= vend) + { + cerr << " Not enougth vertices to crack the mesh we need " << nbv << " vertices " << endl; + MeshError(555,this); + } + cout << " NbCrackedVertices " << NbCrackedVertices << endl; + CurrentTh = CurrentThOld; + return NbCrackedVertices; +} + +Triangles::Triangles(const Triangles & Tho,const int *flag ,const int *bb) + : Gh(*(new Geometry())), BTh(*this) +{ // truncature + // + + char cname[] = "trunc"; + + int i,k,itadj; + int kt=0; + int * kk = new int [Tho.nbv]; + Int4 * reft = new Int4[Tho.nbt]; + Int4 nbInT = Tho.ConsRefTriangle(reft); + Int4 * refv = new Int4[Tho.nbv]; + + for (i=0;i<Tho.nbv;i++) + kk[i]=-1; + for (i=0;i<Tho.nbv;i++) + refv[i]=0; + int nbNewBedge =0; + // int nbOldBedge =0; + for (i=0;i<Tho.nbt;i++) + if( reft[i] >=0 && flag[i]) + { + const Triangle & t = Tho.triangles[i]; + kt++; + kk[Tho.Number(t[0])]=1; + kk[Tho.Number(t[1])]=1; + kk[Tho.Number(t[2])]=1; + itadj=Tho.Number(t.TriangleAdj(0)); + if ( reft[itadj] >=0 && !flag[itadj]) + { nbNewBedge++; + refv[Tho.Number(t[VerticesOfTriangularEdge[0][0]])]=bb[i]; + refv[Tho.Number(t[VerticesOfTriangularEdge[0][1]])]=bb[i]; + } + itadj=Tho.Number(t.TriangleAdj(1)); + if ( reft[itadj] >=0 && !flag[itadj]) + { nbNewBedge++; + refv[Tho.Number(t[VerticesOfTriangularEdge[1][0]])]=bb[i]; + refv[Tho.Number(t[VerticesOfTriangularEdge[1][1]])]=bb[i];} + itadj=Tho.Number(t.TriangleAdj(2)); + if ( reft[itadj] >=0 && !flag[itadj]) + { nbNewBedge++; + refv[Tho.Number(t[VerticesOfTriangularEdge[2][0]])]=bb[i]; + refv[Tho.Number(t[VerticesOfTriangularEdge[2][1]])]=bb[i];} + } + k=0; + for (i=0;i<Tho.nbv;i++) + if (kk[i]>=0) + kk[i]=k++; + cout << " number of vertices " << k << " remove = " << Tho.nbv - k << endl; + cout << " number of triangles " << kt << " remove = " << nbInT-kt << endl; + cout << " number of New boundary edge " << nbNewBedge << endl; + Int4 inbvx =k; + PreInit(inbvx,cname); + for (i=0;i<Tho.nbv;i++) + if (kk[i]>=0) + { + vertices[nbv] = Tho.vertices[i]; + if (!vertices[nbv].ref()) + vertices[nbv].ReferenceNumber = refv[i]; + nbv++; + } + assert(inbvx == nbv); + for (i=0;i<Tho.nbt;i++) + if( reft[i] >=0 && flag[i]) + { + const Triangle & t = Tho.triangles[i]; + int i0 = Tho.Number(t[0]); + int i1 = Tho.Number(t[1]); + int i2 = Tho.Number(t[2]); + assert(i0>=0 && i1 >= 0 && i2 >= 0); + assert(i0<Tho.nbv && i1 <Tho.nbv && i2 <Tho.nbv); + // cout <<i<< " F" << flag[i] << " T " << nbt << " = " << kk[i0] << " " << kk[i1] << " " << kk[i2] ; + // cout << " OT " << i0 << " " << i1 << " " << i2 << " " << reft[i] << endl; + triangles[nbt] = Triangle(this,kk[i0],kk[i1],kk[i2]); + triangles[nbt].color = Tho.subdomains[reft[i]].ref; + nbt++; + } + assert(kt==nbt); + if (nbt ==0 && nbv ==0) { + cout << "Error all triangles was remove " << endl; + MeshError(999,this); + } + delete [] kk; + delete [] reft; + delete [] refv; + double cutoffradian = 10.0/180.0*Pi; + ConsGeometry(cutoffradian); + Gh.AfterRead(); + SetIntCoor(); + FillHoleInMesh(); + + assert(NbSubDomains); + assert(subdomains[0].head && subdomains[0].head->link); + +} + +Triangle * Triangles::FindTriangleContening(const I2 & B,Icoor2 dete[3], Triangle *tstart) const +{ // in: B + // out: t + // out : dete[3] + // t the triangle and s0,s1,s2 the 3 vertices of t + // in dete[3] = { det(B,s1,s2) , det(s0,B,s2), det(s0,s1,B)} + // with det(a,b,c ) = -1 if one of 3 vertices a,b,c is NULL + Triangle * t=0; + int j,jp,jn,jj; + if (tstart) + t=tstart; + else + { + assert(quadtree); + Vertex *a = quadtree->NearestVertex(B.x,B.y) ; + + if (! a || !a->t ) { + if (a) + {cerr << " Attention PB TriangleConteningTheVertex vertex number=" << Number(a) << endl; + cerr << "We forget a call to ReMakeTriangleContainingTheVertex" << endl;} + cerr << " Pb with " << B << toR2(B) << endl; + MeshError(7777); + } + assert(a>= vertices && a < vertices+nbv); +#ifdef DRAWING1 + a->Draw(); +#endif + // int k=0; + t = a->t; + assert(t>= triangles && t < triangles+nbt); + + } + Icoor2 detop ; + int kkkk =0; // number of test triangle + + while ( t->det < 0) + { // the initial triangles is outside + int k0=(*t)(0) ? (( (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1 )) : 0; + assert(k0>=0); // k0 the NULL vertex + int k1=NextVertex[k0],k2=PreviousVertex[k0]; + dete[k0]=det(B,(*t)[k1],(*t)[k2]); + dete[k1]=dete[k2]=-1; + if (dete[k0] > 0) // outside B + return t; + t = t->TriangleAdj(OppositeEdge[k0]); + assert(kkkk++ < 2); + } + + jj=0; + detop = det(*(*t)(VerticesOfTriangularEdge[jj][0]),*(*t)(VerticesOfTriangularEdge[jj][1]),B); + + while(t->det > 0 ) + { + assert( kkkk++ < 2000 ); + j= OppositeVertex[jj]; + +#ifdef DRAWING1 + t->Draw(); +#endif + dete[j] = detop; //det(*b,*s1,*s2); + jn = NextVertex[j]; + jp = PreviousVertex[j]; + dete[jp]= det(*(*t)(j),*(*t)(jn),B); + dete[jn] = t->det-dete[j] -dete[jp]; + +#ifdef DEBUG + const Vertex * s0 = (*t)(0); + const Vertex * s1 = (*t)(1); + const Vertex * s2 = (*t)(2); + assert(dete[0] == det(B ,*s1,*s2)); + assert(dete[1] == det(*s0,B ,*s2)); + assert(dete[2] == det(*s0,*s1,B )); + assert(t->det== (dete[0] + dete[1] +dete[2])); +#endif + // count the number k of dete <0 + int k=0,ii[3]; + if (dete[0] < 0 ) ii[k++]=0; + if (dete[1] < 0 ) ii[k++]=1; + if (dete[2] < 0 ) ii[k++]=2; + // 0 => ok + // 1 => go in way 1 + // 2 => two way go in way 1 or 2 randomly + + if (k==0) + break; + if (k == 2 && BinaryRand()) + Exchange(ii[0],ii[1]); + assert ( k < 3); + TriangleAdjacent t1 = t->Adj(jj=ii[0]); + if ((t1.det() < 0 ) && (k == 2)) + t1 = t->Adj(jj=ii[1]); + t=t1; + j=t1;// for optimisation we now the -det[OppositeVertex[j]]; + detop = -dete[OppositeVertex[jj]]; + jj = j; + } + + if (t->det<0) // outside triangle + dete[0]=dete[1]=dete[2]=-1,dete[OppositeVertex[jj]]=detop; + // NbOfTriangleSearchFind += kkkk; + return t; +} + +} + diff --git a/contrib/bamg/bamglib/Mesh2.h b/contrib/bamg/bamglib/Mesh2.h new file mode 100644 index 0000000000000000000000000000000000000000..4d02159a19ecf2d45d12187d58696d6d5d464214 --- /dev/null +++ b/contrib/bamg/bamglib/Mesh2.h @@ -0,0 +1,1492 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#include <stdlib.h> +#include <math.h> +#include <limits.h> +#include <time.h> +#if (defined(unix) || defined(__unix)) && !defined(__AIX) +#define SYSTIMES +#include <sys/times.h> +#include <unistd.h> +#endif +#ifdef DRAWING +#include "rgraph.hpp" +#endif + +extern long verbosity; +extern int SHOW; +#include "meshtype.h" + +#include "error.hpp" + + +#include "R2.h" + +namespace bamg { + + + +const double Pi = 3.14159265358979323846264338328; +const float fPi = 3.14159265358979323846264338328; + + +class MeshIstream; +class OFortranUnFormattedFile; +class IFortranUnFormattedFile; + +extern int hinterpole; + + +typedef P2<Icoor1,Icoor2> I2; + +inline int BinaryRand(){ +#ifdef RAND_MAX + const long HalfRandMax = RAND_MAX/2; + return rand() <HalfRandMax; +#else + return rand() & 16384; // 2^14 (for sun because RAND_MAX is not def in stdlib.h) +#endif + +} +typedef P2<Real8,Real8> R2; +typedef P2xP2<Int2,Int4> I2xI2; +typedef P2<Real4,Real8> R2xR2; + +} + +#include "Metric.h" + +namespace bamg { +inline float OppositeAngle(float a) + {return a<0 ? fPi + a :a - fPi ;} +inline double OppositeAngle(double a) + {return a<0 ? Pi + a :a - Pi ;} + +#ifdef DRAWING +extern Real4 xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet; +extern R2 GrafPMin,GrafPMax; +extern Real8 Grafh; +#endif + +Icoor2 inline det(const I2 &a,const I2 & b,const I2 &c) +{ + register Icoor2 bax = b.x - a.x ,bay = b.y - a.y; + register Icoor2 cax = c.x - a.x ,cay = c.y - a.y; + return bax*cay - bay*cax;} + + + +// def de numerotation dans un triangles +static const Int2 VerticesOfTriangularEdge[3][2] = {{1,2},{2,0},{0,1}}; +static const Int2 EdgesVertexTriangle[3][2] = {{1,2},{2,0},{0,1}}; +static const Int2 OppositeVertex[3] = {0,1,2}; +static const Int2 OppositeEdge[3] = {0,1,2}; +static const Int2 NextEdge[3] = {1,2,0}; +static const Int2 PreviousEdge[3] = {2,0,1}; +static const Int2 NextVertex[3] = {1,2,0}; +static const Int2 PreviousVertex[3] = {2,0,1}; + +Int4 AGoodNumberPrimeWith(Int4 n); + +// remark all the angle are in radian beetwen [-Pi,Pi] + + +class Geometry; +//static Geometry *NULLGeometry=0; +class Triangles; +class Triangle; +class QuadTree; +class GeometricalEdge; +class VertexOnGeom; +class VertexOnEdge; +///////////////////////////////////////////////////////////////////////////////////// +const int IsVertexOnGeom = 8; +const int IsVertexOnVertex = 16; +const int IsVertexOnEdge = 32; +///////////////////////////////////////////////////////////////////////////////////// +#ifndef NOTFREEFEM +class ErrorMesh : public Error +{ +public: + Triangles *Th; + ErrorMesh(const char * Text,int l,Triangles * TTh=0, const char *t2="") : + Error(MESH_ERROR,"Meshing error: ",Text,"\n number : ",l,", ",t2),Th(TTh) {} +}; +#endif + +class Direction { // + private: + Icoor1 dir; + public: + Direction(): dir(MaxICoor){}; // no direction set + Direction(Icoor1 i,Icoor1 j) { Icoor2 n2 = 2*(Abs(i)+Abs(j)); + Icoor2 r = MaxICoor* (Icoor2) i; + Icoor1 r1 = (Icoor1) (2*(r/ n2)); // odd number + dir = (j>0) ? r1 : r1+1; // odd -> j>0 even -> j<0 + } + int sens( Icoor1 i,Icoor1 j) { int r =1; + if (dir!= MaxICoor) { + Icoor2 x(dir/2),y1(MaxICoor/2-Abs(x)),y(dir%2?-y1:y1); + r = (x*i + y*j) >=0;} + return r;} +#ifdef DRAWING + void Draw() { + if (dir!= MaxICoor) { + Icoor2 x(dir/2),y1(MaxICoor/2-Abs(x)),y(dir%2?-y1:y1); + R2 D(x,y); + double eps = Grafh/Norme2(D)/20; + D = D*eps; + rmoveto(D.x,D.y); + } + } +#endif + + + + +}; +///////////////////////////////////////////////////////////////////////////////////// +class Vertex {public: + I2 i; // allow to use i.x, and i.y in long int (beware of scale and centering) + R2 r; // allow to use r.x, and r.y in double + Metric m; + Int4 ReferenceNumber; + Direction DirOfSearch; + union { + Triangle * t; // one triangle which contained the vertex + Int4 color; + Vertex * to;// use in geometry Vertex to now the Mesh Vertex associed + VertexOnGeom * on; // if vint 8; // set with Triangles::SetVertexFieldOn() + Vertex * onbv; // if vint == 16 on Background vertex Triangles::SetVertexFieldOnBTh() + VertexOnEdge * onbe; // if vint == 32 on Background edge + }; + Int1 vint; // the vertex number in triangle; varies between 0 and 2 in t + operator I2 () const {return i;} // operator de cast + operator const R2 & () const {return r;}// operator de cast +// operator R2 & () {return r;}// operator de cast + Real8 operator()(R2 x) const { return m(x);} + operator Metric () const {return m;}// operator de cast + Int4 Optim(int = 1,int =0); + // Vertex(){} + // ~Vertex(){} + Real8 Smoothing(Triangles & ,const Triangles & ,Triangle * & ,Real8 =1); + int ref() const { return ReferenceNumber;} + + friend ostream& operator <<(ostream& f, const Vertex & v) + {f << "(" << v.i << "," << v.r << MatVVP2x2(v.m) << ")" ; return f;} + inline void Set(const Vertex & rec,const Triangles &,Triangles &); + +#ifdef DRAWING + void Draw(Int4 =-1) const ; + void MoveTo() const { rmoveto(r.x,r.y); } + void LineTo() const { rlineto(r.x,r.y); } +#endif +}; + +double QuadQuality(const Vertex &,const Vertex &,const Vertex &,const Vertex &); + +// extern Vertex *Meshend , *Meshbegin; + +///////////////////////////////////////////////////////////////////////////////////// +class TriangleAdjacent { + friend ostream& operator <<(ostream& f, const TriangleAdjacent & ta) + {f << "{" << ta.t << "," << ((int) ta.a) << "}" ; + return f;} + +public: + Triangle * t; // le triangle + int a; // le numero de l arete + + TriangleAdjacent(Triangle * tt,int aa): t(tt),a(aa &3) {}; + TriangleAdjacent() {}; + + operator Triangle * () const {return t;} + operator Triangle & () const {return *t;} + operator int() const {return a;} + TriangleAdjacent & operator++() + { + a= NextEdge[a]; + return *this;} + TriangleAdjacent operator--() + { + a= PreviousEdge[a]; + return *this;} + inline TriangleAdjacent Adj() const ; + int swap(); + inline void SetAdj2(const TriangleAdjacent& , int =0); + inline Vertex * EdgeVertex(const int &) const ; + inline Vertex * OppositeVertex() const ; + inline Icoor2 & det() const; + inline int Locked() const ; + inline int GetAllFlag_UnSwap() const ; + inline void SetLock(); + inline int MarkUnSwap() const; + inline void SetMarkUnSwap(); + inline void SetCracked(); + inline int Cracked() const ; +};// end of Vertex class + + +///////////////////////////////////////////////////////////////////////////////////// +class Edge { public: + Vertex * v[2]; + Int4 ref; + GeometricalEdge * on; + Vertex & operator[](int i){return *v[i];}; + Vertex * operator()(int i){return v[i];}; + + void ReNumbering(Vertex *vb,Vertex *ve, Int4 *renu) + { + if (v[0] >=vb && v[0] <ve) v[0] = vb + renu[v[0]-vb]; + if (v[1] >=vb && v[1] <ve) v[1] = vb + renu[v[1]-vb]; + } + + const Vertex & operator[](int i) const { return *v[i];}; + R2 operator()(double t) const; // return the point + // on the curve edge a t in [0:1] + Edge * adj[2]; // the 2 adj edges if on the same curve + int Intersection(const Edge & e) const { + if (!(adj[0]==&e || adj[1]==&e)) + cerr << "Bug : Intersection " << (void*) &e << " " + << adj[0] << " " << adj[1] << endl; + assert(adj[0]==&e || adj[1]==&e); + return adj[0]==&e ? 0 : 1;} + Real8 MetricLength() const ; + inline void Set(const Triangles &,Int4,Triangles &); + +#ifdef DRAWING + void Draw(Int4 = -1) const ; +#endif +}; // end of Edge class + +///////////////////////////////////////////////////////////////////////////////////// +class GeometricalVertex :public Vertex { + int cas; + friend class Geometry; + GeometricalVertex * link; // link all the same GeometricalVertex circular (Crack) +public: + int Corner() const {return cas&4;} + int Required()const {return cas&6;}// a corner is required + void SetCorner(){ cas |= 4;} + void SetRequired(){ cas |= 2;} + void Set(){cas=0;} + GeometricalVertex() :cas(0), link(this) {}; + GeometricalVertex * The() { assert(link); return link;}// return a unique vertices + int IsThe() const { return link == this;} + +inline void Set(const GeometricalVertex & rec,const Geometry & Gh ,const Geometry & GhNew); + inline friend ostream& operator <<(ostream& f, const GeometricalVertex & s) + { f << s.r << "," << s.cas << ".";return f; } +}; + +///////////////////////////////////////////////////////////////////////////////////// +class GeometricalEdge { + public: + GeometricalVertex * v[2]; + Int4 ref; + Int4 CurveNumber; + R2 tg[2]; // the 2 tangente + // if tg[0] =0 => no continuite + GeometricalEdge * Adj [2]; + int SensAdj[2]; +// private: + int flag ; + public: + GeometricalEdge * link; // if Cracked() or Equi() + +// end of data + + GeometricalVertex & operator[](int i){return *v[i];}; + const GeometricalVertex & operator[](int i) const { return *v[i];}; + GeometricalVertex * operator()(int i){return v[i];}; + // inline void Set(const Geometry &,Int4,Geometry &); + + R2 F(Real8 theta) const ; // parametrization of the curve edge + Real8 R1tg(Real8 theta,R2 &t) const ; // 1/radius of curvature + tangente + int Cracked() const {return flag & 1;} + int Dup() const { return flag & 32;} + int Equi()const {return flag & 2;} + int ReverseEqui()const {return flag & 128;} + int TgA()const {return flag &4;} + int TgB()const {return flag &8;} + int Tg(int i) const{return i==0 ? TgA() : TgB();} + int Mark()const {return flag &16;} + int Required() { return flag & 64;} + void SetCracked() { flag |= 1;} + void SetDup() { flag |= 32;} // not a real edge + void SetEqui() { flag |= 2;} + void SetTgA() { flag|=4;} + void SetTgB() { flag|=8;} + void SetMark() { flag|=16;} + void SetUnMark() { flag &= 1007 /* 1023-16*/;} + void SetRequired() { flag |= 64;} + void SetReverseEqui() {flag |= 128;} + + inline void Set(const GeometricalEdge & rec,const Geometry & Th ,Geometry & ThNew); + +#ifdef DRAWING + void Draw(Int4 =-1); +#endif + +}; + +class Curve {public: + GeometricalEdge * be,*ee; // begin et end edge + int kb,ke; // begin vetex and end vertex + Curve *next; // next curve equi to this + bool master; // true => of equi curve point on this curve + inline void Set(const Curve & rec,const Geometry & Th ,Geometry & ThNew); + Curve() : be(0),ee(0),kb(0),ke(0),next(0),master(true) {} + void Reverse() { Exchange(be,ee); Exchange(kb,ke);} // revese the sens of the curse +}; + + + +///////////////////////////////////////////////////////////////////////////////////// +class Triangle { + friend class TriangleAdjacent; + friend ostream& operator <<(ostream& f, const Triangle & ta); + + + private: // les arete sont opposes a un sommet + Vertex * ns [3]; // 3 vertices if t is triangle, t[i] allowed by access function, (*t)[i] if pointer + Triangle * at [3]; // nu triangle adjacent + Int1 aa[3]; // les nu des arete dans le triangles (mod 4) + public: + Icoor2 det; // determinant du triangle (2 fois l aire des vertices entieres) + union { + Triangle * link ; + Int4 color; + }; + void SetDet() { + if(ns[0] && ns[1] && ns[2]) det = bamg::det(*ns[0],*ns[1],*ns[2]); + else det = -1; } + Triangle() {} + Triangle(Triangles *Th,Int4 i,Int4 j,Int4 k); + Triangle(Vertex *v0,Vertex *v1,Vertex *v2); + inline void Set(const Triangle &,const Triangles &,Triangles &); + inline int In(Vertex *v) const { return ns[0]==v || ns[1]==v || ns[2]==v ;} + TriangleAdjacent FindBoundaryEdge(int ) const; + + void ReNumbering(Triangle *tb,Triangle *te, Int4 *renu) + { + if (link >=tb && link <te) link = tb + renu[link -tb]; + if (at[0] >=tb && at[0] <te) at[0] = tb + renu[at[0]-tb]; + if (at[1] >=tb && at[1] <te) at[1] = tb + renu[at[1]-tb]; + if (at[2] >=tb && at[2] <te) at[2] = tb + renu[at[2]-tb]; + } + void ReNumbering(Vertex *vb,Vertex *ve, Int4 *renu) + { + if (ns[0] >=vb && ns[0] <ve) ns[0] = vb + renu[ns[0]-vb]; + if (ns[1] >=vb && ns[1] <ve) ns[1] = vb + renu[ns[1]-vb]; + if (ns[2] >=vb && ns[2] <ve) ns[2] = vb + renu[ns[2]-vb]; + } + + + const Vertex & operator[](int i) const {return *ns[i];}; + Vertex & operator[](int i) {return *ns[i];}; + + const Vertex * operator()(int i) const {return ns[i];}; + Vertex * & operator()(int i) {return ns[i];}; + + TriangleAdjacent Adj(int i) const // triangle adjacent + arete + { return TriangleAdjacent(at[i],aa[i]&3);}; + + Triangle * TriangleAdj(int i) const + {return at[i&3];} // triangle adjacent + arete + Int1 NuEdgeTriangleAdj(int i) const + {return aa[i&3]&3;} // Number of the adjacent edge in adj tria + + inline Real4 qualite() ; + + + void SetAdjAdj(Int1 a) + { a &= 3; + register Triangle *tt=at[a]; + aa [a] &= 55; // remove MarkUnSwap + register Int1 aatt = aa[a] & 3; + if(tt){ + tt->at[aatt]=this; + tt->aa[aatt]=a + (aa[a] & 60 ) ;}// Copy all the mark + } + + void SetAdj2(Int1 a,Triangle *t,Int1 aat) + { at[a]=t;aa[a]=aat; + if(t) {t->at[aat]=this;t->aa[aat]=a;} + } + + void SetTriangleContainingTheVertex() + { + if (ns[0]) (ns[0]->t=this,ns[0]->vint=0); + if (ns[1]) (ns[1]->t=this,ns[1]->vint=1); + if (ns[2]) (ns[2]->t=this,ns[2]->vint=2); + } + + int swap(Int2 a1,int=0); + Int4 Optim(Int2 a,int =0); + + int Locked(int a)const { return aa[a]&4;} + int Hidden(int a)const { return aa[a]&16;} + int Cracked(int a) const { return aa[a] & 32;} + // for optimisation + int GetAllflag(int a){return aa[a] & 1020;} + void SetAllFlag(int a,int f){aa[a] = (aa[a] &3) + (1020 & f);} + + void SetHidden(int a){ + register Triangle * t = at[a]; + if(t) t->aa[aa[a] & 3] |=16; + aa[a] |= 16;} + void SetCracked(int a){ + register Triangle * t = at[a]; + if(t) t->aa[aa[a] & 3] |=32; + aa[a] |= 32;} + + double QualityQuad(int a,int option=1) const; + Triangle * Quadrangle(Vertex * & v0,Vertex * & v1,Vertex * & v2,Vertex * & v3) const ; + + void SetLocked(int a){ + register Triangle * t = at[a]; + t->aa[aa[a] & 3] |=4; + aa[a] |= 4;} + + void SetMarkUnSwap(int a){ + register Triangle * t = at[a]; + t->aa[aa[a] & 3] |=8; + aa[a] |=8 ;} + + + void SetUnMarkUnSwap(int a){ + register Triangle * t = at[a]; + t->aa[aa[a] & 3] &=55; // 23 + 32 + aa[a] &=55 ;} + + + +#ifdef DEBUG + void inline checka(Int1 a); + void inline check(); +#endif + +#ifdef DRAWING + void Draw(Int4 i=-1) const; + int swapDRAW(Int2 a1); + +#endif + +}; // end of Triangle class + + + + +class ListofIntersectionTriangles { +///////////////////////////////////////////////////////////////////////////////////// +class IntersectionTriangles { +public: + Triangle *t; + Real8 bary[3]; // use if t != 0 + R2 x; + Metric m; + Real8 s;// abscisse curviline + Real8 sp; // len of the previous seg in m + Real8 sn;// len of the next seg in m +}; +///////////////////////////////////////////////////////////////////////////////////// +class SegInterpolation { + public: + GeometricalEdge * e; + Real8 sBegin,sEnd; // abscisse of the seg on edge parameter + Real8 lBegin,lEnd; // length abscisse set in ListofIntersectionTriangles::Length + int last;// last index in ListofIntersectionTriangles for this Sub seg of edge + R2 F(Real8 s){ + Real8 c01=lEnd-lBegin, c0=(lEnd-s)/c01, c1=(s-lBegin)/c01; + assert(lBegin<= s && s <=lEnd); + return e->F(sBegin*c0+sEnd*c1);} +}; + + int MaxSize; // + int Size; // + Real8 len; // + int state; + IntersectionTriangles * lIntTria; + int NbSeg; + int MaxNbSeg; + SegInterpolation * lSegsI; + public: + IntersectionTriangles & operator[](int i) {return lIntTria[i];} + operator int&() {return Size;} + ListofIntersectionTriangles(int n=256,int m=16) + : MaxSize(n), Size(0), len(-1),state(-1),lIntTria(new IntersectionTriangles[n]) , + NbSeg(0), MaxNbSeg(m), lSegsI(new SegInterpolation[m]) + { if (verbosity>9) + cout << " construct ListofIntersectionTriangles" + << MaxSize << " " << MaxNbSeg<< endl;}; + ~ListofIntersectionTriangles(){ + if (lIntTria) delete [] lIntTria,lIntTria=0; + if (lSegsI) delete [] lSegsI,lSegsI=0;} + void init(){state=0;len=0;Size=0;} + + int NewItem(Triangle * tt,Real8 d0,Real8 d1,Real8 d2); + int NewItem(R2,const Metric & ); + void NewSubSeg(GeometricalEdge *e,Real8 s0,Real8 s1) + { + if (NbSeg>=MaxNbSeg) { + int mneo= MaxNbSeg; + MaxNbSeg *= 2; + if (verbosity>3) + cout <<" reshape lSegsI from " << mneo << " to " + << MaxNbSeg <<endl; + SegInterpolation * lEn = new SegInterpolation[MaxNbSeg]; + assert(lSegsI && NbSeg < MaxNbSeg); + for (int i=0;i< NbSeg;i++) + lEn[i] = lSegsI[MaxNbSeg]; // copy old to new + delete [] lSegsI; // remove old + lSegsI = lEn; + } + if (NbSeg) + lSegsI[NbSeg-1].last=Size; + lSegsI[NbSeg].e=e; + lSegsI[NbSeg].sBegin=s0; + lSegsI[NbSeg].sEnd=s1; + NbSeg++; + } + +// void CopyMetric(int i,int j){ lIntTria[j].m=lIntTria[i].m;} +// void CopyMetric(const Metric & mm,int j){ lIntTria[j].m=mm;} + + void ReShape() { + register int newsize = MaxSize*2; + IntersectionTriangles * nw = new IntersectionTriangles[newsize]; + assert(nw); + for (int i=0;i<MaxSize;i++) // recopy + nw[i] = lIntTria[i]; + if(verbosity>3) + cout << " ListofIntersectionTriangles ReShape MaxSize " + << MaxSize << " -> " + << newsize << endl; + MaxSize = newsize; + delete [] lIntTria;// remove old + lIntTria = nw; // copy pointer + } + + void SplitEdge(const Triangles & ,const R2 &,const R2 &,int nbegin=0); + Real8 Length(); + Int4 NewPoints(Vertex *,Int4 & nbv,Int4 nbvx); +}; + + +///////////////////////////////////////////////////////////////////////////////////// +class GeometricalSubDomain { +public: + GeometricalEdge *edge; + int sens; // -1 or 1 + Int4 ref; + inline void Set(const GeometricalSubDomain &,const Geometry & ,const Geometry &); + +}; +///////////////////////////////////////////////////////////////////////////////////// +class SubDomain { +public: + Triangle * head; + Int4 ref; + int sens; // -1 or 1 + Edge * edge; // to geometrical + inline void Set(const Triangles &,Int4,Triangles &); + +}; +///////////////////////////////////////////////////////////////////////////////////// +class VertexOnGeom { public: + + Vertex * mv; + Real8 abscisse; + union{ + GeometricalVertex * gv; // if abscisse <0; + GeometricalEdge * ge; // if abscisse in [0..1] + }; + inline void Set(const VertexOnGeom&,const Triangles &,Triangles &); + int OnGeomVertex()const {return this? abscisse <0 :0;} + int OnGeomEdge() const {return this? abscisse >=0 :0;} + VertexOnGeom(): mv(0),abscisse(0){gv=0;} + VertexOnGeom(Vertex & m,GeometricalVertex &g) : mv(&m),abscisse(-1){gv=&g;} + // cout << " mv = " <<mv << " gv = " << gv << endl;} + VertexOnGeom(Vertex & m,GeometricalEdge &g,Real8 s) : mv(&m),abscisse(s){ge=&g;} + //cout << &g << " " << ge << endl;} + operator Vertex * () const {return mv;} + operator GeometricalVertex * () const {return gv;} + operator GeometricalEdge * () const {return ge;} +// operator Real8 & () {return abscisse;} + operator const Real8 & () const {return abscisse;} + int IsRequiredVertex(){ return this? (( abscisse<0 ? (gv?gv->Required():0):0 )) : 0;} + void SetOn(){mv->on=this;mv->vint=IsVertexOnGeom;} + friend ostream& operator <<(ostream& f, const VertexOnGeom & vog){ + f << vog.abscisse << " " << vog.mv << " " << vog.gv << " ; "; + if (vog.abscisse < 0) f << *vog.gv << " ;; " ; + // else f << *vog.ge << " ;; " ; + return f;} + inline void Set(const Triangles &,Int4,Triangles &); + +}; +///////////////////////////////////////////////////////////////////////////////////// +class VertexOnVertex {public: + Vertex * v, *bv; + VertexOnVertex(Vertex * w,Vertex *bw) :v(w),bv(bw){} + VertexOnVertex() {}; + inline void Set(const Triangles &,Int4,Triangles &); + void SetOnBTh(){v->onbv=bv;v->vint=IsVertexOnVertex;} +}; +///////////////////////////////////////////////////////////////////////////////////// +class VertexOnEdge {public: + Vertex * v; + Edge * be; + Real8 abcisse; + VertexOnEdge( Vertex * w, Edge *bw,Real8 s) :v(w),be(bw),abcisse(s) {} + VertexOnEdge(){} + inline void Set(const Triangles &,Int4,Triangles &); + void SetOnBTh(){v->onbe=this;v->vint=IsVertexOnEdge;} + Vertex & operator[](int i) const { return (*be)[i];} + operator Real8 () const { return abcisse;} + operator Vertex * () const { return v;} + operator Edge * () const { return be;} +}; + + inline TriangleAdjacent FindTriangleAdjacent(Edge &E); + inline Vertex * TheVertex(Vertex * a); // for remove crak in mesh +///////////////////////////////////////////////////////////////////////////////////// + +class CrackedEdge { // a small class to store on crack an uncrack information + friend class Triangles; + friend ostream& operator <<(ostream& f, const Triangles & Th) ; + class CrackedTriangle { + friend class Triangles; + friend class CrackedEdge; + friend ostream& operator <<(ostream& f, const Triangles & Th) ; + Triangle * t; // edge of triangle t + int i; // edge number of in triangle + Edge *edge; // the 2 edge + Vertex *New[2]; // new vertex number + CrackedTriangle() : t(0),i(0),edge(0) { New[0]=New[1]=0;} + CrackedTriangle(Edge * a) : t(0),i(0),edge(a) { New[0]=New[1]=0;} + void Crack(){ + Triangle & T(*t); + int i0=VerticesOfTriangularEdge[i][0]; + int i1=VerticesOfTriangularEdge[i][0]; + assert(New[0] && New[1]); + T(i0) = New[0]; + T(i1) = New[1];} + void UnCrack(){ + Triangle & T(*t); + int i0=VerticesOfTriangularEdge[i][0]; + int i1=VerticesOfTriangularEdge[i][0]; + assert(New[0] && New[1]); + T(i0) = TheVertex(T(i0)); + T(i1) = TheVertex(T(i1));} + void Set() { + TriangleAdjacent ta ( FindTriangleAdjacent(*edge)); + t = ta; + i = ta; + + New[0] = ta.EdgeVertex(0); + New[1] = ta.EdgeVertex(1); + // warning the ref + + } + + }; // end of class CrackedTriangle + public: + CrackedTriangle a,b; + CrackedEdge() :a(),b() {} + CrackedEdge(Edge * start, Int4 i,Int4 j) : a(start+i),b(start+j) {}; + CrackedEdge(Edge * e0, Edge * e1 ) : a(e0),b(e1) {}; + + void Crack() { a.Crack(); b.Crack();} + void UnCrack() { a.UnCrack(); b.UnCrack();} + void Set() { a.Set(), b.Set();} +}; + +///////////////////////////////////////////////////////////////////////////////////// + +class Triangles { +public: + + enum TypeFileMesh { + AutoMesh=0,BDMesh=1,NOPOMesh=2,amMesh=3,am_fmtMesh=4,amdbaMesh=5, + ftqMesh=6,mshMesh=7}; + + int static counter; // to kown the number of mesh in memory + int OnDisk; // true if on disk + Geometry & Gh; // Geometry + Triangles & BTh; // Background Mesh Bth==*this =>no background + + Int4 NbRef; // counter of ref on the this class if 0 we can delete + Int4 nbvx,nbtx; // nombre max de sommets , de triangles + + Int4 nt,nbv,nbt,nbiv,nbe; // nb of legal triangles, nb of vertex, of triangles, + // of initial vertices, of edges with reference, + Int4 NbOfQuad; // nb of quadrangle + + Int4 NbSubDomains; // + Int4 NbOutT; // Nb of oudeside triangle + Int4 NbOfTriangleSearchFind; + Int4 NbOfSwapTriangle; + char * name, *identity; + Vertex * vertices; // data of vertices des sommets + + Int4 NbVerticesOnGeomVertex; + VertexOnGeom * VerticesOnGeomVertex; + + Int4 NbVerticesOnGeomEdge; + VertexOnGeom * VerticesOnGeomEdge; + + Int4 NbVertexOnBThVertex; + VertexOnVertex *VertexOnBThVertex; + + Int4 NbVertexOnBThEdge; + VertexOnEdge *VertexOnBThEdge; + + + Int4 NbCrackedVertices; + + + Int4 NbCrackedEdges; + CrackedEdge *CrackedEdges; + + + R2 pmin,pmax; // extrema + Real8 coefIcoor; // coef to integer Icoor1; + + Triangle * triangles; + Edge * edges; + + QuadTree *quadtree; + Vertex ** ordre; + SubDomain * subdomains; + ListofIntersectionTriangles lIntTria; +// end of variable + + Triangles(Int4 i);//:BTh(*this),Gh(*new Geometry()){PreInit(i);} + + ~Triangles(); + Triangles(const char * ,Real8=-1) ; + + Triangles(Int4 nbvx,Triangles & BT,int keepBackVertices=1) + :Gh(BT.Gh),BTh(BT) { + try {GeomToTriangles1(nbvx,keepBackVertices);} + catch(...) { this->~Triangles(); throw; } } + + Triangles(Int4 nbvx,Geometry & G) + :Gh(G),BTh(*this){ + try { GeomToTriangles0(nbvx);} + catch(...) { this->~Triangles(); throw; } } + Triangles(Triangles &,Geometry * pGh=0,Triangles* pBTh=0,Int4 nbvxx=0 ); // COPY OPERATEUR + // Triangles(Triangles &){ cerr << " BUG call copy opretor of Triangles" << endl;MeshError(111);} + Triangles(const Triangles &,const int *flag,const int *bb); // truncature + + + void SetIntCoor(const char * from =0); + + // void RandomInit(); + // void CubeInit(int ,int); + + Real8 MinimalHmin() {return 2.0/coefIcoor;} + Real8 MaximalHmax() {return Max(pmax.x-pmin.x,pmax.y-pmin.y);} + const Vertex & operator[] (Int4 i) const { return vertices[i];}; + Vertex & operator[](Int4 i) { return vertices[i];}; + const Triangle & operator() (Int4 i) const { return triangles[i];}; + Triangle & operator()(Int4 i) { return triangles[i];}; + I2 toI2(const R2 & P) const { + return I2( (Icoor1) (coefIcoor*(P.x-pmin.x)) + ,(Icoor1) (coefIcoor*(P.y-pmin.y)) );} + R2 toR2(const I2 & P) const { + return R2( (double) P.x/coefIcoor+pmin.x, (double) P.y/coefIcoor+pmin.y);} + void Add( Vertex & s,Triangle * t,Icoor2 * =0) ; + void Insert(); + // void InsertOld(); + void ForceBoundary(); + void Heap(); + void FindSubDomain(int ); + Int4 ConsRefTriangle(Int4 *) const; + void ShowHistogram() const; + void ShowRegulaty() const; // Add FH avril 2007 +// void ConsLinkTriangle(); + + void ReMakeTriangleContainingTheVertex(); + void UnMarkUnSwapTriangle(); + void SmoothMetric(Real8 raisonmax) ; + void BoundAnisotropy(Real8 anisomax,double hminaniso= 1e-100) ; + void MaxSubDivision(Real8 maxsubdiv); + void WriteMetric(ostream &,int iso) ; + Edge** MakeGeometricalEdgeToEdge(); + void SetVertexFieldOn(); + void SetVertexFieldOnBTh(); + Int4 SplitInternalEdgeWithBorderVertices(); + void MakeQuadrangles(double costheta); + int SplitElement(int choice); + void MakeQuadTree(); + void NewPoints( Triangles &,int KeepBackVertex =1 ); + Int4 InsertNewPoints(Int4 nbvold,Int4 & NbTSwap) ; + void NewPointsOld( Triangles & ); + void NewPoints(int KeepBackVertex=1){ NewPoints(*this,KeepBackVertex);} + void ReNumberingTheTriangleBySubDomain(bool justcompress=false); + void ReNumberingVertex(Int4 * renu); + void SmoothingVertex(int =3,Real8=0.3); + Metric MetricAt (const R2 &) const; + GeometricalEdge * ProjectOnCurve( Edge & AB, Vertex & A, Vertex & B,Real8 theta, + Vertex & R,VertexOnEdge & BR,VertexOnGeom & GR); + + + void WriteElements(ostream& f,Int4 * reft ,Int4 nbInT) const; + + + Int4 Number(const Triangle & t) const { return &t - triangles;} + Int4 Number(const Triangle * t) const { return t - triangles;} + Int4 Number(const Vertex & t) const { return &t - vertices;} + Int4 Number(const Vertex * t) const { return t - vertices;} + Int4 Number(const Edge & t) const { return &t - edges;} + Int4 Number(const Edge * t) const { return t - edges;} + Int4 Number2(const Triangle * t) const { + // if(t>= triangles && t < triangles + nbt ) + return t - triangles; + // else return t - OutSidesTriangles; + } + + Vertex * NearestVertex(Icoor1 i,Icoor1 j) ; + Triangle * FindTriangleContening(const I2 & ,Icoor2 [3],Triangle *tstart=0) const; + void Write(const char * filename,const TypeFileMesh type = AutoMesh); + void Write_am_fmt(ostream &) const ; + void Write_am(ostream &) const ; + void Write_ftq(ostream &) const ; + void Write_nopo(ostream &) const ; + void Write_msh(ostream &) const ; + void Write_amdba(ostream &) const ; + + void Read(MeshIstream &,int version,Real8 cutoffradian); + void Read_am_fmt(MeshIstream &); + void Read_amdba(MeshIstream &); + void Read_am(MeshIstream &); + void Read_nopo(MeshIstream &); + void Read_ftq(MeshIstream &); + void Read_msh(MeshIstream &); + + void ReadMetric(const char * fmetrix,const Real8 hmin,const Real8 hmax,const Real8 coef); + void IntersectConsMetric(const double * s,const Int4 nbsol,const int * typsols, + const Real8 hmin,const Real8 hmax, const Real8 coef, + const Real8 anisomax,const Real8 CutOff=1.e-4,const int NbJacobi=1, + const int DoNormalisation=1, + const double power=1.0, + const int choise=0); + void IntersectGeomMetric(const Real8 err,const int iso); + + + int isCracked() const {return NbCrackedVertices != 0;} + int Crack(); + int UnCrack(); + +#ifdef DEBUG + void inline Check(); +#endif +#ifdef DRAWING + void Draw() const ; + void InitDraw() const ; + void inquire() ; +#endif + friend ostream& operator <<(ostream& f, const Triangles & Th); + void Write(const char * filename); + void ConsGeometry(Real8 =-1.0,int *equiedges=0); // construct a geometry if no geo + void FillHoleInMesh() ; + int CrackMesh(); + private: + void GeomToTriangles1(Int4 nbvx,int KeepBackVertices=1);// the real constructor mesh adaption + void GeomToTriangles0(Int4 nbvx);// the real constructor mesh generator + void PreInit(Int4,char * =0 ); + // + void Write_nop5(OFortranUnFormattedFile * f, + Int4 &lnop5,Int4 &nef,Int4 &lgpdn,Int4 ndsr) const ; + + +}; // End Class Triangles +///////////////////////////////////////////////////////////////////////////////////// +class Geometry { +public: + int OnDisk; + Int4 NbRef; // counter of ref on the this class if 0 we can delete + + char *name; + Int4 nbvx,nbtx; // nombre max de sommets , de Geometry + Int4 nbv,nbt,nbiv,nbe; // nombre de sommets, de Geometry, de sommets initiaux, + Int4 NbSubDomains; // + Int4 NbEquiEdges; + Int4 NbCrackedEdges; +// Int4 nbtf;// de triangle frontiere + Int4 NbOfCurves; + int empty(){return (nbv ==0) && (nbt==0) && (nbe==0) && (NbSubDomains==0); } + GeometricalVertex * vertices; // data of vertices des sommets + Triangle * triangles; + GeometricalEdge * edges; + QuadTree *quadtree; + GeometricalSubDomain *subdomains; + Curve *curves; + ~Geometry(); + Geometry(const Geometry & Gh); //Copy Operator + Geometry(int nbg,const Geometry ** ag); // intersection operator + + R2 pmin,pmax; // extrema + Real8 coefIcoor; // coef to integer Icoor1; + Real8 MaximalAngleOfCorner; + +// end of data + + + I2 toI2(const R2 & P) const { + return I2( (Icoor1) (coefIcoor*(P.x-pmin.x)) + ,(Icoor1) (coefIcoor*(P.y-pmin.y)) );} + + Real8 MinimalHmin() {return 2.0/coefIcoor;} + Real8 MaximalHmax() {return Max(pmax.x-pmin.x,pmax.y-pmin.y);} + void ReadGeometry(const char * ) ; + void ReadGeometry(MeshIstream & ,const char *) ; + + void EmptyGeometry(); + Geometry() {EmptyGeometry();}// empty Geometry + void AfterRead(); + Geometry(const char * filename) {EmptyGeometry();OnDisk=1;ReadGeometry(filename);AfterRead();} + + void ReadMetric(const char *,Real8 hmin,Real8 hmax,Real8 coef); + const GeometricalVertex & operator[] (Int4 i) const { return vertices[i];}; + GeometricalVertex & operator[](Int4 i) { return vertices[i];}; + const GeometricalEdge & operator() (Int4 i) const { return edges[i];}; + GeometricalEdge & operator()(Int4 i) { return edges[i];}; + Int4 Number(const GeometricalVertex & t) const { return &t - vertices;} + Int4 Number(const GeometricalVertex * t) const { return t - vertices;} + Int4 Number(const GeometricalEdge & t) const { return &t - edges;} + Int4 Number(const GeometricalEdge * t) const { return t - edges;} + Int4 Number(const Curve * c) const { return c - curves;} + + void UnMarkEdges() { + for (Int4 i=0;i<nbe;i++) edges[i].SetUnMark();} + + GeometricalEdge * ProjectOnCurve(const Edge & ,Real8,Vertex &,VertexOnGeom &) const ; + GeometricalEdge * Contening(const R2 P, GeometricalEdge * start) const; + friend ostream& operator <<(ostream& f, const Geometry & Gh); + void Write(const char * filename); + +#ifdef DEBUG + void inline Check(); +#endif +#ifdef DRAWING + void Draw() const ; + void InitDraw() const ; +#endif + +}; // End Class Geometry + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +/////////////////// END CLASS //////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +inline Triangles::Triangles(Int4 i) :Gh(*new Geometry()),BTh(*this){PreInit(i);} + +extern Triangles * CurrentTh; + +TriangleAdjacent CloseBoundaryEdge(I2 ,Triangle *, double &,double &) ; +TriangleAdjacent CloseBoundaryEdgeV2(I2 A,Triangle *t, double &a,double &b); + +Int4 FindTriangle(Triangles &Th, Real8 x, Real8 y, double* a,int & inside); + + + +inline Triangle * Triangle::Quadrangle(Vertex * & v0,Vertex * & v1,Vertex * & v2,Vertex * & v3) const +{ +// return the other triangle of the quad if a quad or 0 if not a quat + Triangle * t =0; + if (link) { + int a=-1; + if (aa[0] & 16 ) a=0; + if (aa[1] & 16 ) a=1; + if (aa[2] & 16 ) a=2; + if (a>=0) { + t = at[a]; + // if (t-this<0) return 0; + v2 = ns[VerticesOfTriangularEdge[a][0]]; + v0 = ns[VerticesOfTriangularEdge[a][1]]; + v1 = ns[OppositeEdge[a]]; + v3 = t->ns[OppositeEdge[aa[a]&3]]; + } + } + return t; +} + +inline double Triangle::QualityQuad(int a,int option) const +{ // first do the logique part + double q; + if (!link || aa[a] &4) + q= -1; + else { + Triangle * t = at[a]; + if (t-this<0) q= -1;// because we do 2 times + else if (!t->link ) q= -1; + else if (aa[0] & 16 || aa[1] & 16 || aa[2] & 16 || t->aa[0] & 16 || t->aa[1] & 16 || t->aa[2] & 16 ) + q= -1; + else if(option) + { + const Vertex & v2 = *ns[VerticesOfTriangularEdge[a][0]]; + const Vertex & v0 = *ns[VerticesOfTriangularEdge[a][1]]; + const Vertex & v1 = *ns[OppositeEdge[a]]; + const Vertex & v3 = * t->ns[OppositeEdge[aa[a]&3]]; + q = QuadQuality(v0,v1,v2,v3); // do the float part + } + else q= 1; + } + return q; +} + + +inline void Vertex::Set(const Vertex & rec,const Triangles & ,Triangles & ) + { + *this = rec; + } +inline void GeometricalVertex::Set(const GeometricalVertex & rec,const Geometry & ,const Geometry & ) + { + *this = rec; + } +inline void Edge::Set(const Triangles & Th ,Int4 i,Triangles & ThNew) + { + *this = Th.edges[i]; + v[0] = ThNew.vertices + Th.Number(v[0]); + v[1] = ThNew.vertices + Th.Number(v[1]); + if (on) + on = ThNew.Gh.edges+Th.Gh.Number(on); + if (adj[0]) adj[0] = ThNew.edges + Th.Number(adj[0]); + if (adj[1]) adj[1] = ThNew.edges + Th.Number(adj[1]); + + } +inline void GeometricalEdge::Set(const GeometricalEdge & rec,const Geometry & Gh ,Geometry & GhNew) + { + *this = rec; + v[0] = GhNew.vertices + Gh.Number(v[0]); + v[1] = GhNew.vertices + Gh.Number(v[1]); + if (Adj[0]) Adj[0] = GhNew.edges + Gh.Number(Adj[0]); + if (Adj[1]) Adj[1] = GhNew.edges + Gh.Number(Adj[1]); + } + +inline void Curve::Set(const Curve & rec,const Geometry & Gh ,Geometry & GhNew) +{ + *this = rec; + be = GhNew.edges + Gh.Number(be); + ee = GhNew.edges + Gh.Number(ee); + if(next) next= GhNew.curves + Gh.Number(next); +} + +inline void Triangle::Set(const Triangle & rec,const Triangles & Th ,Triangles & ThNew) + { + *this = rec; + if ( ns[0] ) ns[0] = ThNew.vertices + Th.Number(ns[0]); + if ( ns[1] ) ns[1] = ThNew.vertices + Th.Number(ns[1]); + if ( ns[2] ) ns[2] = ThNew.vertices + Th.Number(ns[2]); + if(at[0]) at[0] = ThNew.triangles + Th.Number(at[0]); + if(at[1]) at[1] = ThNew.triangles + Th.Number(at[1]); + if(at[2]) at[2] = ThNew.triangles + Th.Number(at[2]); + if (link >= Th.triangles && link < Th.triangles + Th.nbt) + link = ThNew.triangles + Th.Number(link); + } +inline void VertexOnVertex::Set(const Triangles & Th ,Int4 i,Triangles & ThNew) +{ + *this = Th.VertexOnBThVertex[i]; + v = ThNew.vertices + Th.Number(v); + +} +inline void SubDomain::Set(const Triangles & Th ,Int4 i,Triangles & ThNew) +{ + *this = Th.subdomains[i]; + assert( head - Th.triangles >=0 && head - Th.triangles < Th.nbt); + head = ThNew.triangles + Th.Number(head) ; + assert(edge - Th.edges >=0 && edge - Th.edges < Th.nbe); + edge = ThNew.edges+ Th.Number(edge); +} + inline void GeometricalSubDomain::Set(const GeometricalSubDomain & rec,const Geometry & Gh ,const Geometry & GhNew) +{ + *this = rec; + edge = Gh.Number(edge) + GhNew.edges; +} +inline void VertexOnEdge::Set(const Triangles & Th ,Int4 i,Triangles & ThNew) +{ + *this = Th.VertexOnBThEdge[i]; + v = ThNew.vertices + Th.Number(v); +} + +inline void VertexOnGeom::Set(const VertexOnGeom & rec,const Triangles & Th ,Triangles & ThNew) +{ + *this = rec; + mv = ThNew.vertices + Th.Number(mv); + if (gv) + if (abscisse < 0 ) + gv = ThNew.Gh.vertices + Th.Gh.Number(gv); + else + ge = ThNew.Gh.edges + Th.Gh.Number(ge); + +} +inline Real8 Edge::MetricLength() const + { + return LengthInterpole(v[0]->m,v[1]->m,v[1]->r - v[0]->r) ; + } + +inline void Triangles::ReMakeTriangleContainingTheVertex() + { + register Int4 i; + for ( i=0;i<nbv;i++) + { + vertices[i].vint = 0; + vertices[i].t=0; + } + for ( i=0;i<nbt;i++) + triangles[i].SetTriangleContainingTheVertex(); + } + +inline void Triangles::UnMarkUnSwapTriangle() + { + register Int4 i; + for ( i=0;i<nbt;i++) + for(int j=0;j<3;j++) + triangles[i].SetUnMarkUnSwap(j); + } + +inline void Triangles::SetVertexFieldOn() + { + for (Int4 i=0;i<nbv;i++) + vertices[i].on=0; + for (Int4 j=0;j<NbVerticesOnGeomVertex;j++ ) + VerticesOnGeomVertex[j].SetOn(); + for (Int4 k=0;k<NbVerticesOnGeomEdge;k++ ) + VerticesOnGeomEdge[k].SetOn(); + } +inline void Triangles::SetVertexFieldOnBTh() + { + for (Int4 i=0;i<nbv;i++) + vertices[i].on=0; + for (Int4 j=0;j<NbVertexOnBThVertex;j++ ) + VertexOnBThVertex[j].SetOnBTh(); + for (Int4 k=0;k<NbVertexOnBThEdge;k++ ) + VertexOnBThEdge[k].SetOnBTh(); + + } + +inline void TriangleAdjacent::SetAdj2(const TriangleAdjacent & ta, int l ) +{ // set du triangle adjacent + if(t) { + t->at[a]=ta.t; + t->aa[a]=ta.a|l;} + if(ta.t) { + ta.t->at[ta.a] = t ; + ta.t->aa[ta.a] = a| l ; + } +} + + +inline int TriangleAdjacent::Locked() const +{ return t->aa[a] &4;} +inline int TriangleAdjacent::Cracked() const +{ return t->aa[a] &32;} +inline int TriangleAdjacent::GetAllFlag_UnSwap() const +{ return t->aa[a] & 1012;} // take all flag except MarkUnSwap + +inline int TriangleAdjacent::MarkUnSwap() const +{ return t->aa[a] &8;} + +inline void TriangleAdjacent::SetLock(){ t->SetLocked(a);} + +inline void TriangleAdjacent::SetCracked() { t->SetCracked(a);} + +inline TriangleAdjacent TriangleAdjacent::Adj() const +{ return t->Adj(a);} + +inline Vertex * TriangleAdjacent::EdgeVertex(const int & i) const + {return t->ns[VerticesOfTriangularEdge[a][i]]; } +inline Vertex * TriangleAdjacent::OppositeVertex() const +{return t->ns[bamg::OppositeVertex[a]]; } +inline Icoor2 & TriangleAdjacent::det() const +{ return t->det;} +inline TriangleAdjacent Adj(const TriangleAdjacent & a) +{ return a.Adj();} + +inline TriangleAdjacent Next(const TriangleAdjacent & ta) +{ return TriangleAdjacent(ta.t,NextEdge[ta.a]);} + +inline TriangleAdjacent Previous(const TriangleAdjacent & ta) +{ return TriangleAdjacent(ta.t,PreviousEdge[ta.a]);} + +inline void Adj(GeometricalEdge * & on,int &i) + {int j=i;i=on->SensAdj[i];on=on->Adj[j];} + +inline Real4 qualite(const Vertex &va,const Vertex &vb,const Vertex &vc) +{ + Real4 ret; + I2 ia=va,ib=vb,ic=vc; + I2 ab=ib-ia,bc=ic-ib,ac=ic-ia; + Icoor2 deta=Det(ab,ac); + if (deta <=0) ret = -1; + else { + Real8 a = sqrt((Real8) (ac,ac)), + b = sqrt((Real8) (bc,bc)), + c = sqrt((Real8) (ab,ab)), + p = a+b+c; + Real8 h= Max(Max(a,b),c),ro=deta/p; + ret = ro/h;} + return ret; +} + + +inline Triangle::Triangle(Triangles *Th,Int4 i,Int4 j,Int4 k) { + Vertex *v=Th->vertices; + Int4 nbv = Th->nbv; + assert(i >=0 && j >=0 && k >=0); + assert(i < nbv && j < nbv && k < nbv); + ns[0]=v+i; + ns[1]=v+j; + ns[2]=v+k; + at[0]=at[1]=at[2]=0; + aa[0]=aa[1]=aa[2]=0; + det=0; +} + +inline Triangle::Triangle(Vertex *v0,Vertex *v1,Vertex *v2){ + ns[0]=v0; + ns[1]=v1; + ns[2]=v2; + at[0]=at[1]=at[2]=0; + aa[0]=aa[1]=aa[2]=0; + if (v0) det=0; + else { + det=-1; + link=NULL;}; +} + +inline Real4 Triangle::qualite() +{ + return det < 0 ? -1 : bamg::qualite(*ns[0],*ns[1],*ns[2]); +} + +Int4 inline Vertex::Optim(int i,int koption) +{ + Int4 ret=0; + if ( t && (vint >= 0 ) && (vint <3) ) + { + ret = t->Optim(vint,koption); + if(!i) + { + t =0; // for no future optime + vint= 0; } + } + return ret; +} + +Icoor2 inline det(const Vertex & a,const Vertex & b,const Vertex & c) +{ + register Icoor2 bax = b.i.x - a.i.x ,bay = b.i.y - a.i.y; + register Icoor2 cax = c.i.x - a.i.x ,cay = c.i.y - a.i.y; + return bax*cay - bay*cax;} + + +void swap(Triangle *t1,Int1 a1, + Triangle *t2,Int1 a2, + Vertex *s1,Vertex *s2,Icoor2 det1,Icoor2 det2); + + + +int inline TriangleAdjacent::swap() +{ return t->swap(a);} + + + +int SwapForForcingEdge(Vertex * & pva ,Vertex * & pvb , + TriangleAdjacent & tt1,Icoor2 & dets1, + Icoor2 & detsa,Icoor2 & detsb, int & nbswap); + +int ForceEdge(Vertex &a, Vertex & b,TriangleAdjacent & taret) ; + +// inline bofbof FH +inline TriangleAdjacent FindTriangleAdjacent(Edge &E) + { + Vertex * a = E.v[0]; + Vertex * b = E.v[1]; + + Triangle * t = a->t; + int i = a->vint; + TriangleAdjacent ta(t,EdgesVertexTriangle[i][0]); // Previous edge + assert(t && i>=0 && i < 3); + assert( a == (*t)(i)); + int k=0; + do { // turn around vertex in direct sens (trigo) + k++;assert(k< 20000); + // in no crack => ta.EdgeVertex(1) == a otherwise ??? + if (ta.EdgeVertex(1) == a && ta.EdgeVertex(0) == b) return ta; // find + ta = ta.Adj(); + if (ta.EdgeVertex(0) == a && ta.EdgeVertex(1) == b) return ta; // find + --ta; + } while (t != (Triangle *)ta); + assert(0); + return TriangleAdjacent(0,0);// error + } + +inline Vertex * TheVertex(Vertex * a) // give a unique vertex with smallest number +{ // in case on crack in mesh + Vertex * r(a), *rr; + Triangle * t = a->t; + int i = a->vint; + TriangleAdjacent ta(t,EdgesVertexTriangle[i][0]); // Previous edge + assert(t && i>=0 && i < 3); + assert( a == (*t)(i)); + int k=0; + do { // turn around vertex in direct sens (trigo) + k++;assert(k< 20000); + // in no crack => ta.EdgeVertex(1) == a + if ((rr=ta.EdgeVertex(0)) < r) r = rr; + ta = ta.Adj(); + if ((rr=ta.EdgeVertex(1)) < r) r =rr; + --ta; + } while (t != (Triangle*) ta); + return r; +} + +inline double CPUtime(){ +#ifdef SYSTIMES + struct tms buf; + if (times(&buf)!=-1) + return ((double)buf.tms_utime+(double)buf.tms_stime)/(long) sysconf(_SC_CLK_TCK); + else +#endif + return ((double) clock())/CLOCKS_PER_SEC; +} + +#ifdef DEBUG +void inline Triangle::checka(Int1 a) { + // verif de la coherence des adjacences de l arete a + a = a%4; + assert(a < 3 && a >= 0 ); + Triangle *t1=this,*t2=at[a]; + Int2 a1=a,a2=aa[a]%4; + + assert(a2 < 3 && a2 >= 0 ); + if (t2 && ( ((*t1).ns[VerticesOfTriangularEdge[a1][0]] != (*t2).ns[VerticesOfTriangularEdge[a2][1]]) + || ((*t1).ns[VerticesOfTriangularEdge[a1][1]] != (*t2).ns[VerticesOfTriangularEdge[a2][0]]))) + { + if (CurrentTh) cerr << " In Triangles beetween Triangle " << CurrentTh->Number(t1) << " and " + << CurrentTh->Number(t2) << endl; + cerr << "---- t1="<< t1 << " " << a1 <<", t2="<< t2 << " " << a2 << endl; + cerr <<"t1="<< t1 << " " << a1 << " " << t1->ns[VerticesOfTriangularEdge[a1][0]] + << " " << t1->ns[VerticesOfTriangularEdge[a1][1]] <<endl; + if (CurrentTh) + cerr <<"t1="<< t1 << " " << a1 << " " << CurrentTh->Number(t1->ns[VerticesOfTriangularEdge[a1][0]]) + << " " << CurrentTh->Number(t1->ns[VerticesOfTriangularEdge[a1][1]]) <<endl; + if (t2) cerr <<"t2="<< t2 << " " << a2 << " " + << t2->ns[VerticesOfTriangularEdge[a2][0]] + << " " << t2->ns[VerticesOfTriangularEdge[a2][1]] <<endl; + if (t2 &&CurrentTh) + cerr <<"t2="<< t2 << " " << a2 << " " + << CurrentTh->Number(t2->ns[VerticesOfTriangularEdge[a2][0]]) + << " " << CurrentTh->Number(t2->ns[VerticesOfTriangularEdge[a2][1]]) <<endl; + assert(0); + } + if (t2) assert(t1->aa[a1]/4 == t2->aa[a2]/4); // lock compatibite +} + + +void inline Triangle::check() { + Icoor2 det2=0; + // cout << " check " << this << endl; + int infv=ns[0] ? (( ns[1] ? ( ns[2] ? -1 : 2) : 1 )) : 0; + if (det<0) { + if (infv<0 ) + { if (CurrentTh) cerr << " In Triangles " << CurrentTh->Number(this) << endl; + cerr << " det = " << det << " and " << infv << endl; + MeshError(5); + }} + else if (infv>=0 ) + { if (CurrentTh) cerr << " In Triangles " << CurrentTh->Number(this) << endl; + cerr << " det = " << det << " and " << infv << endl; + MeshError(5); + } + + if (det >=0) + if( det != (det2=bamg::det(*ns[0],*ns[1],*ns[2]))) + { // penthickness(4);Draw(); + if (CurrentTh) cerr << " In Triangles" << CurrentTh->Number(this) + << endl; + cerr << *ns[0] << *ns[1] << " " << *ns[2] << " " << endl; + cerr << " Bug in triangle " << this + << ":" << det << " != " << det2 << endl; + MeshError(5); + } + checka(0); + checka(1); + checka(2); +// if (ns[0]) assert( ns[0] - Meshbegin >= 0 ); +// if (ns[0]) assert( Meshend - ns[0] >= 0 ); +// if (ns[1]) assert( ns[1] - Meshbegin >= 0 ); +// if (ns[1]) assert( Meshend - ns[1] >= 0 ); +// if (ns[2]) assert( ns[2] - Meshbegin >= 0 ); +// if (ns[2]) assert( Meshend - ns[2] >= 0 ); + assert(ns[0] != ns[2]); + assert(ns[1] != ns[2]); + assert(ns[0] != ns[1]); +} + + +#endif + + + + +#ifdef DRAWING +extern Real4 xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet; // R2 -> I2 transform +extern R2 Gpmin,Gpmax; +//extern Real8 Gh; +// cf routine ILineTo IMoveto + +extern void IMoveTo(long i,long j); +extern void ILineTo(long i,long j); +extern char Getxyc(long &i,long &j); +extern void Draw(float ,float ); +extern void Draw(long ,long ); +extern void DrawMark(R2 r); +//inline void DrawMark(D2 r) {DrawMark(R2(r.x,r.y));} +inline void Move(I2 x) {IMoveTo(x.x,x.y);} +inline void Move(R2 x) {rmoveto(x.x,x.y);} +//inline void Move(D2 x) {rmoveto(x.x,x.y);} +inline void Line(I2 x){ILineTo(x.x,x.y);} +inline void Line(R2 x) {rlineto(x.x,x.y);} +//inline void Line(D2 x) {rlineto(x.x,x.y);} +#endif + +} + + + + + + diff --git a/contrib/bamg/bamglib/MeshDraw.cpp b/contrib/bamg/bamglib/MeshDraw.cpp new file mode 100644 index 0000000000000000000000000000000000000000..58168072d393efa2d3530ae0b5f1be3acb9a736c --- /dev/null +++ b/contrib/bamg/bamglib/MeshDraw.cpp @@ -0,0 +1,808 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#ifdef DRAWING + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <time.h> +#include <iostream> +using namespace std; + +#include "Mesh2.h" +#include "QuadTree.h" +#include "SetOfE4.h" +extern bool withrgraphique; + + + +namespace bamg { +Real4 xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet; +R2 GrafPMin,GrafPMax; +Real8 Grafh=0; + + + +void IMoveTo(long i,long j) +{ if (!withrgraphique) return; + rmoveto(float(i)/xGrafCoef+xGrafOffSet ,float(j)/yGrafCoef+yGrafOffSet );} + +void ILineTo(long i,long j) +{ if (!withrgraphique) return; + rlineto(float(i)/xGrafCoef+xGrafOffSet ,float(j)/yGrafCoef+yGrafOffSet );} + + +void Triangles::Draw( ) const { + if (!withrgraphique) return; + showgraphic(); +// if (!init) InitDraw(); + Int4 i; +// for (i=0;i<nbv;i++) +// vertices[i].Draw(i); + for (i=0;i<nbe;i++) + edges[i].Draw(); + for (i=0;i<nbt;i++) + if (triangles[i].link) + triangles[i].Draw(-2); +// for (i=0;i<nbv;i++) +// ((Metric) vertices[i]).Draw(vertices[i]); + + // rattente(1); + +} + + +void Edge::Draw(Int4 i) const +{ + if (!withrgraphique) return; + if (InRecScreen(Min(v[0]->r.x,v[1]->r.x), + Max(v[0]->r.y,v[1]->r.y), + Min(v[0]->r.x,v[1]->r.x), + Max(v[0]->r.y,v[1]->r.y))) { + v[0]->MoveTo(); + v[1]->LineTo(); + R2 M= ((R2) *v[0] + (R2) * v[1])*0.5; + Move(M); + char VertexDraw_i10[20]; + if (i<0) + sprintf(VertexDraw_i10,"%p",this); + else + sprintf(VertexDraw_i10,"%ld",i); + if (i>=0) + plotstring(&VertexDraw_i10[0]); + + } +} +void Vertex::Draw(Int4 i) const +{ + if (!withrgraphique) return; + if (CurrentTh && i<0&& i != -2 ) + { + if (CurrentTh->vertices <= this && this < CurrentTh->vertices + CurrentTh->nbv) + i = CurrentTh->Number(this); + } + if (InPtScreen(r.x,r.y)) { + char VertexDraw_i10[20]; + if (i<0) + sprintf(VertexDraw_i10,"%p",this); + else + sprintf(VertexDraw_i10,"%ld",i); + + showgraphic(); + // float eps = (MaxICoor/yGrafCoef)/100; + DrawMark(r); + + if (i>=0) + plotstring(&VertexDraw_i10[0]); } +} + +void DrawMark(R2 r) +{ + if (!withrgraphique) return; + if (InPtScreen(r.x,r.y)) { + float eps = Grafh/100; + rmoveto(r.x+eps,r.y); + rlineto(r.x,r.y+eps); + rlineto(r.x-eps,r.y); + rlineto(r.x,r.y-eps); + rlineto(r.x+eps,r.y);} + +} +void Triangle::Draw(Int4 i ) const +{ + if (!withrgraphique) return; + // int cc=LaCouleur(); + if (CurrentTh && i<0 && i != -2) + { + if (CurrentTh->triangles <= this && this < CurrentTh->triangles + CurrentTh->nbt) + i = CurrentTh->Number(this); + } + char i10[20]; + if (i<0) sprintf(i10,"%p",this); + else sprintf(i10,"%ld",i); + showgraphic(); + + if (ns[0] == 0) { + if (InRecScreen(Min(ns[1]->r.x,ns[2]->r.x), + Min(ns[1]->r.y,ns[2]->r.y), + Max(ns[1]->r.x,ns[2]->r.x), + Max(ns[1]->r.y,ns[2]->r.y))) + { rmoveto(ns[1]->r.x,ns[1]->r.y); + rlineto(ns[2]->r.x,ns[2]->r.y); + rmoveto( (ns[1]->r.x + ns[2]->r.x)/2.0 + (ns[1]->r.y - ns[2]->r.y)*0.1, + (ns[1]->r.y + ns[2]->r.y)/2.0 - (ns[1]->r.x - ns[2]->r.x)*0.1 ); + if(i>=0) plotstring(&i10[0]); + }} + else + if (InRecScreen(Min3(ns[0]->r.x,ns[1]->r.x,ns[2]->r.x), + Min3(ns[0]->r.y,ns[1]->r.y,ns[2]->r.y), + Max3(ns[0]->r.x,ns[1]->r.x,ns[2]->r.x), + Max3(ns[0]->r.y,ns[1]->r.y,ns[2]->r.y))) { + { + const int i0=0 , j01=EdgesVertexTriangle[i0][1];// j01==2 + const int i1=VerticesOfTriangularEdge[j01][1], j12=EdgesVertexTriangle[i1][1];//i1=1,j12=0 + const int i2=VerticesOfTriangularEdge[j12][1], j20=EdgesVertexTriangle[i2][1];//i1=2,j20=1 + + rmoveto(ns[i0]->r.x,ns[i0]->r.y); + if(Hidden(j01)) rmoveto(ns[i1]->r.x,ns[i1]->r.y); else rlineto(ns[i1]->r.x,ns[i1]->r.y); + if(Hidden(j12)) rmoveto(ns[i2]->r.x,ns[i2]->r.y); else rlineto(ns[i2]->r.x,ns[i2]->r.y); + if(Hidden(j20)) rmoveto(ns[i0]->r.x,ns[i0]->r.y); else rlineto(ns[i0]->r.x,ns[i0]->r.y); + + rmoveto( (ns[0]->r.x + ns[1]->r.x + ns[2]->r.x)/3.0 , + (ns[0]->r.y + ns[1]->r.y + ns[2]->r.y)/3.0); + + } + + if(i>=0) plotstring(&i10[0]); + } + // LaCouleur(cc); +} + +void Triangles::InitDraw() const +{ + if (!withrgraphique) return; + couleur(1); + GrafPMin = vertices[0].r; + GrafPMax = vertices[0].r; + // recherche des extrema des vertices GrafPMin,GrafPMax + Int4 i; + for (i=0;i<nbv;i++) { + // GrafPMax = Max2(GrafPMax,vertices[i].r); + // GrafPMin = Min2(GrafPMin,vertices[i].r); + GrafPMin.x = Min(GrafPMin.x,vertices[i].r.x); + GrafPMin.y = Min(GrafPMin.y,vertices[i].r.y); + GrafPMax.x = Max(GrafPMax.x,vertices[i].r.x); + GrafPMax.y = Max(GrafPMax.y,vertices[i].r.y); + } + float hx = (GrafPMax.x-GrafPMin.x); + float hy = (GrafPMax.y-GrafPMin.y); + Grafh = Max(hx,hy)*0.55; + cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.5,Grafh); + +} +void Show(const char * s,int k=1) +{ + if (!withrgraphique) return; + if(k) { + couleur(1); + float xmin,xmax,ymin,ymax; + getcadre(xmin,xmax,ymin,ymax); + rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30); + plotstring(s); + // couleur(1); + } +} +void Triangles::inquire() +{ + if (! withrgraphique) return; + int PS=0; + cout << flush; + Triangles *OldCurrentTh=CurrentTh; + CurrentTh = this; + if (! Grafh ) InitDraw(); + unsigned char c; + int rd; + float x,y; + int setv =0; + Int4 nbtrel=0; + Int4 * reft = new Int4 [Max(nbt,1L)]; + if (NbSubDomains && subdomains[0].head) + nbtrel = ConsRefTriangle(reft); + else + for (Int4 kkk=0;kkk<nbt;kkk++) reft[kkk]=0; + // cout << "inquire **********************************************************************"<<endl ; + if (verbosity>2) + cout << "inquire: Nb de Triangle reel = " <<ConsRefTriangle(reft)<<endl; + + while (Show("Enter ? for help",PS==0), c=::Getxyc(x,y), ( c && c != 'F' && c != 'f') && c < 250 ) + { rd = 0; + couleur(1); + // cout << " #"<< c << "# " << (int) c << " xy=" << x << " "<< y <<endl ; + // penthickness(2); + if (c=='?') { int i=3; + reffecran(); + Show("enter a keyboard character in graphic window to do",i++); + i++; + Show("f or mouse click: to continue the process",i++); + Show("p: openPS file to save plot, P: close PS file ",i++); + Show("B: set backgound mesh has drawing mesh",i++); + Show("H: show histogramme",i++); + Show("i: initDraw",i++); + Show("+ or - : zoom + or -",i++); + Show("r: redraw , =: reinit the viewport ",i++); + Show("q: quit / abort / stop ",i++); + Show("Q: show quadtree",i++); + Show("g: show geometry",i++); + Show("d: show triangle with det = 0",i++); + Show("m: show all the metric",i++); + Show("V: show all the vertices",i++); + Show("T: show all the sub domain ref number",i++); + Show("V: show all the vertices",i++); + Show("D: Inforce the mesh to be Delaunay",i++); + Show("b: show all the boundary edges ref number",i++); + Show("k: find the triangle contening the point",i++); + Show("v,o,s : print the nearest vertex s=> draw metric o=> optim around (debug)",i++); + Show("t: find triangle contening the point with brute force",i++); + Show("e: find the nearest edge of triangle contening the point",i++); + Show("C: construct the in-circle in anistrope way",i++); + Show("n: show normal for find ",i++); + } + if (c=='p') openPS(0),PS=1; + if (c=='P') closePS(),PS=0; + if (c=='B') BTh.inquire(); + if ( c=='D') { + for(int iter=0;iter < 50;iter++) + { int k = 0; + for (Int4 icount=0; icount<nbv; icount++) { + k += vertices[icount].Optim(1,0); + } + if (k !=0) cout << " Bizarre le maillage n'est pas delaunay nbswap = " << k << endl; + else break; + } + rd =1; + } + + if (c=='H') ShowHistogram(); + if (c=='i') {InitDraw(); + } + if (c=='+') Grafh /= 2.,rd=1,cadreortho(x,y,Grafh); + if (c=='-') Grafh *= 2.,rd=1,cadreortho(x,y,Grafh); + if (c=='r') rd =1; + if (c=='Q') CurrentTh=0,MeshError(1); + if (c=='q' && quadtree) penthickness(2), + couleur(6), + quadtree->Draw(), + couleur(1), + penthickness(1); + if (c=='g') couleur(6),Gh.Draw(); + if (c=='n') { + for (int i=0;i<nbv;i++) + { + vertices[i].MoveTo(); + vertices[1].DirOfSearch.Draw();; + } + } + if (c=='d') + { + couleur(4); + for(int i=0;i<nbt;i++) + if(triangles[i].det == 0) { + triangles[i].Draw(); + cout << " Bizzare " << i << endl; + } + couleur(1); + + } + if (c=='m') {Int4 i; + couleur(2); + for (i=0;i<nbv;i++) + ((Metric) vertices[i]).Draw(vertices[i]); + couleur(1);} + if (c=='V') {Int4 i; + for (i=0;i<nbv;i++) + vertices[i].Draw(); } + if (c=='T') { + Int4 i; + for( i=0;i<nbt;i++) + if(reft[i]>=0) + { couleur(2+(reft[i])%6); + triangles[i].Draw(reft[i]); + couleur(1); + } + } + + if (c=='b') { + Int4 i; + reffecran(); + for (i=0;i<nbe;i++) + edges[i].Draw(edges[i].ref); + + } + if (c=='k') + { + if(!setv) ReMakeTriangleContainingTheVertex(); + R2 P(x,y); + I2 I = toI2(P); + Icoor2 dete[3]; + Triangle * tb = FindTriangleContening(I,dete); + penthickness(1); + tb->Draw(Number(tb)); + penthickness(1); + if(tb->link==0) { + double a,b; + TriangleAdjacent ta=CloseBoundaryEdgeV2(I,tb,a,b); + R2 A = *ta.EdgeVertex(0); + R2 B = *ta.EdgeVertex(1); + //Triangle * tt = ta; + // tt->Draw(Number(tt)); + penthickness(5); + // ta.EdgeVertex(0)->MoveTo(); + // ta.EdgeVertex(1)->LineTo(); + DrawMark(A*a+B*b); + penthickness(1); + } + } + if (c=='v' || c=='o' || c=='s' ) + { + couleur(3); + if(!setv) ReMakeTriangleContainingTheVertex(); + setv=1; + + R2 XY(x,y),P; + Real8 d; + Int4 i,j=0; + P = XY - vertices[0].r; + d = (P,P); + for (i=0;i<nbv;i++) { + P = XY - vertices[i].r; + Real8 dd = (P,P); + if(dd < d) { + j=i; + d=dd;}} + cout << " sommet " << j << "= " << vertices[j] << ", d = " << d << " " << vertices[j].m << endl; + vertices[j].Draw(j); + DrawMark(vertices[j].r); + if( c=='s') vertices[j].m.Draw(vertices[j]); + if (c=='o') cout << " Nb Swap = " << vertices[j].Optim(1) << endl; + couleur(1); + } + if (c=='t' || c=='c'||c=='e') { + couleur(4); + R2 XY(x,y); + Real8 a12,a02,a01; + for (Int4 i=0;i<nbt;i++) { + if(triangles[i].det<=0) continue; + // cout << " T = " << i << " " << triangles[i].det << " "; + // cout << Number(triangles[i][0]) << " " + // << Number(triangles[i][1]) << " " + // << Number(triangles[i][2]) << " "; + // cout << area2(triangles[i][0].r,triangles[i][1].r,triangles[i][2].r) << " " ; + // cout << area2(XY,triangles[i][1].r,triangles[i][2].r) << " " ; + // cout << area2(triangles[i][0].r,XY,triangles[i][2].r) << " " ; + // cout << area2(triangles[i][0].r,triangles[i][1].r,XY) << endl; + + if( (a12=Area2(XY,triangles[i][1].r,triangles[i][2].r)) < 0) continue; + if( (a02=Area2(triangles[i][0].r,XY,triangles[i][2].r)) < 0) continue; + if( (a01=Area2(triangles[i][0].r,triangles[i][1].r,XY)) < 0) continue; + if(c=='e'|| c=='E') { + int ie =0; + Real8 am = a12; + if(a02 < am) am=a02,ie=1; + if(a01 < am) am=a01,ie=2; + TriangleAdjacent tta(triangles+i,ie); + Vertex *v0 =tta.EdgeVertex(0); + Vertex *v1 =tta.EdgeVertex(1); + tta.EdgeVertex(0)->MoveTo(); + tta.EdgeVertex(1)->LineTo(); + cout << " Edge " << Number(tta.EdgeVertex(0)) << " " << Number(tta.EdgeVertex(1)) << endl; + for (Int4 k=0;k<nbe;k++) + if ( ( edges[k](0) == v0 && edges[k](1) == v1) || + ( edges[k](0) == v1 && edges[k](1) == v0) ) + cout << " Edge " << k << " on Geo = " << Gh.Number(edges[k].on)<< endl; + + + if(c=='e') { + triangles[i].SetUnMarkUnSwap(ie); + triangles[i].swapDRAW(ie);} + else if(c=='E') + { + ; + } + + break; + } + cout << " In triangle " << i << triangles[i]; + triangles[i].Draw(i); + if(c=='c') { + Vertex *s1=&triangles[i][0]; + Vertex *sa=&triangles[i][1]; + Vertex *sb=&triangles[i][2]; + D2 S1(s1->r.x,s1->r.y); + D2 SA(sa->r.x,sa->r.y); + D2 SB(sb->r.x,sb->r.y); + D2 AB= SB-SA; + D2 MAB2=SB + SA; + D2 M1A=(S1 + SA)*0.5; + D2 MAB(MAB2.x*0.5,MAB2.y*0.5); + D2 A1=S1-SA; + D2 D = S1 - SB ; + { + Metric M=s1->m; + D2 ABo = M.Orthogonal(AB); + D2 A1o = M.Orthogonal(A1); + penthickness(1); + Move(MAB); + Line(MAB+ABo); + Line(MAB-ABo); + Move(M1A); + Line(M1A+A1o); + Line(M1A-A1o); + penthickness(3); + + // (A+B)+ x ABo = (S1+B)/2+ y A1 + // ABo x - A1o y = (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 + double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x); + double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2 + cout << " d = " << d << " dd= " << dd << endl; + if (Abs(d) > dd*1.e-10) { + D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d)); + cout << C << s1->r <<sa->r <<sb->r << endl; + DrawMark(C); + cout << M << " l = "<< M(C-S1) << " lnew = 1 == " ; + //M.Draw(R2(C.x,C.y)); + M=M/M(C-S1); + cout << M(C-S1) << M << endl; + M.Draw(R2(C.x,C.y)); + } + + } + } + break; + } + cout << " fin recherche triangle " << endl; + couleur(1); + } + if (c=='='||c==249) { + rd=1; + float hx = (GrafPMax.x-GrafPMin.x); + float hy = (GrafPMax.y-GrafPMin.y); + Grafh = Max(hx,hy)*0.55; + cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.55,Grafh); + } + penthickness(1); + if (rd) + reffecran(),Draw(); + + } + // cout << endl; + delete [] reft; + CurrentTh = OldCurrentTh; + } +void Draw(float x,float y) +{ + if (!withrgraphique) return; + + if (InPtScreen(x,y)) { + float eps = Max(GrafPMax.x-GrafPMin.x,GrafPMax.y-GrafPMin.y)/100; + rmoveto(x+eps,y); + rlineto(x,y+eps); + rlineto(x-eps,y); + rlineto(x,y-eps); + rlineto(x+eps,y);} +} +char Getxyc(long &i,long &j) +{ + if (!withrgraphique) return 0; + + float x,y; + char c=::Getxyc(x,y); + i = (long)( (x - xGrafOffSet)*xGrafCoef); + j = (long)((y - yGrafOffSet)*yGrafCoef); + return c; +} + + +void Draw(long i,long j) +{ + if (!withrgraphique) return; + Draw(((float) i)/xGrafCoef+xGrafOffSet ,((float) j)/yGrafCoef+yGrafOffSet ); +} + +int Triangle::swapDRAW(Int2 a){ + int NbUnSwap=0; + if(a/4 !=0) {cout << a << "arete lock"<< a <<endl;return 0;}// arete lock or MarkUnSwap + + register Triangle *t1=this,*t2=at[a];// les 2 triangles adjacent + register Int1 a1=a,a2=aa[a];// les 2 numero de l arete dans les 2 triangles + + if(a2/4 !=0) {cout << a2 << "arete lock adj"<< a2 << endl; return 0;} // arete lock + + register Vertex *sa=t1->ns[VerticesOfTriangularEdge[a1][0]]; + register Vertex *sb=t1->ns[VerticesOfTriangularEdge[a1][1]]; + register Vertex *s1=t1->ns[OppositeVertex[a1]]; + register Vertex *s2=t2->ns[OppositeVertex[a2]]; + +#ifdef DEBUG + assert ( a >= 0 && a < 3 ); +#endif + + Icoor2 det1=t1->det , det2=t2->det ; + Icoor2 detT = det1+det2; + Icoor2 detA = Abs(det1) + Abs(det2); + Icoor2 detMin = Min(det1,det2); + + int OnSwap = 0; + // si 2 triangle infini (bord) => detT = -2; + if (sa == 0) {// les deux triangles sont frontieres + det2=bamg::det(s2->i,sb->i,s1->i); + OnSwap = det2 >0;} + else if (sb == 0) { // les deux triangles sont frontieres + det1=bamg::det(s1->i,sa->i,s2->i); + OnSwap = det1 >0;} + else if(( s1 != 0) && (s2 != 0) ) { + det1 = bamg::det(s1->i,sa->i,s2->i); + det2 = detT - det1; + OnSwap = (Abs(det1) + Abs(det2)) < detA; + Icoor2 detMinNew=Min(det1,det2); + cout << " detMin = " << detMin << " detMinNew " << detMinNew << endl; + if (! OnSwap &&(detMinNew>0)) { + OnSwap = detMin ==0; + if (! OnSwap) { + int kopt = 1; + while (1) + if(kopt) { + // critere de Delaunay pure + register Real8 xb1 = sb->i.x - s1->i.x, + x21 = s2->i.x - s1->i.x, + yb1 = sb->i.y - s1->i.y, + y21 = s2->i.y - s1->i.y, + xba = sb->i.x - sa->i.x, + x2a = s2->i.x - sa->i.x, + yba = sb->i.y - sa->i.y, + y2a = s2->i.y - sa->i.y, + cosb12 = xb1*x21 + yb1*y21 , + cosba2 = xba*x2a + yba*y2a , + sinb12 = det2, + sinba2 = t2->det, + //zsinba2 = t2->det; + + // angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2) + OnSwap = (cosb12 * sinba2) < (cosba2 * sinb12); + if(CurrentTh) + cout << "swap s1=" << CurrentTh->Number(sa) << " s2=" << CurrentTh->Number(sb) + << " t1= " << CurrentTh->Number(t1) << " t2=" << CurrentTh->Number(t2) << " " ; + + + cout << cosb12 << " " << sinba2 << " " << cosba2 << " " << sinb12 + << " Onswap = " << OnSwap << endl; + + break; + } + else + { + // critere de Delaunay pure + Real8 som; + I2 AB=(I2) *sb - (I2) *sa; + I2 MAB2=((I2) *sb + (I2) *sa); + D2 MAB(MAB2.x*0.5,MAB2.y*0.5); + I2 A1=(I2) *s1 - (I2) *sa; + I2 D = (I2) * s1 - (I2) * sb ; + D2 S2(s2->i.x,s2->i.y); + D2 S1(s1->i.x,s1->i.y); + D2 SA(sa->i.x,sa->i.y); + D2 SB(sb->i.x,sb->i.y); + DrawMark(s2->r); + DrawMark(s1->r); + DrawMark(sa->r); + DrawMark(sb->r); + { + Metric M=s1->m; + D2 ABo = M.Orthogonal(SB-SA); + D2 A1o = M.Orthogonal(S1-SA); + // (A+B)+ x ABo = (S1+B)/2+ y A1 + // ABo x - A1o y = (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 + double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x); + double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2 + if (Abs(d) > dd*1.e-3) { + D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d)); + cout << "M1 r2 =" << M(C - S2) << " r1 = " << M(C - S1) + << "ra = " << M(C - SA) << " rb = " << M(C-SB) ; + som = M(C - S2)/M(C - S1); + cout << " r1/r2 = " << som << endl; + } else + {kopt=1;continue;} + + } + { + Metric M=s2->m; + D2 ABo = M.Orthogonal(SB-SA); + D2 A1o = M.Orthogonal(S1-SA); + // (A+B)+ x ABo = (S1+B)/2+ y A1 + // ABo x - A1o y = (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 + double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x); + double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2 + cout << " d = " << Abs(d) << " dd " << dd << endl; + if(Abs(d) > dd*1.e-3) { + D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d)); + cout << "M2 r1 =" << M(C - S2) << " r2 = " << M(C - S1) + << "ra = " << M(C - SA) << " rb = " << M(C-SB) + << " r1/r2 = " << M(C - S2)/M(C - S1) << endl; + som += M(C - S2)/M(C - S1); + } else + {kopt=1;continue;} + } + { + Metric M=sa->m; + D2 ABo = M.Orthogonal(SB-SA); + D2 A1o = M.Orthogonal(S1-SA); + // (A+B)+ x ABo = (S1+B)/2+ y A1 + // ABo x - A1o y = (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 + double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x); + double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2 + cout << " d = " << Abs(d) << " dd " << dd << endl; + if(Abs(d) > dd*1.e-3) { + D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d)); + cout << "M2 r1 =" << M(C - S2) << " r2 = " << M(C - S1) + << "ra = " << M(C - SA) << " rb = " << M(C-SB) + << " r1/r2 = " << M(C - S2)/M(C - S1) << endl; + som += M(C - S2)/M(C - S1); + } else + {kopt=1;continue;} + } + { + Metric M=sb->m; + D2 ABo = M.Orthogonal(SB-SA); + D2 A1o = M.Orthogonal(S1-SA); + // (A+B)+ x ABo = (S1+B)/2+ y A1 + // ABo x - A1o y = (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 + double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x); + double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2 + cout << " d = " << Abs(d) << " dd " << dd << endl; + if(Abs(d) > dd*1.e-3) { + D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d)); + cout << "M2 r1 =" << M(C - S2) << " r2 = " << M(C - S1) + << "ra = " << M(C - SA) << " rb = " << M(C-SB) + << " r1/r2 = " << M(C - S2)/M(C - S1) << endl; + som += M(C - S2)/M(C - S1); + } else + {kopt=1;continue;} + } + cout << som << endl; + OnSwap = som < 4; + break; + } + + } // OnSwap + } // (! OnSwap &&(det1 > 0) && (det2 > 0) ) + } + cout << OnSwap << endl; + if( OnSwap ) { + couleur(0); + t1->Draw(); + t2->Draw(); + bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2); + couleur(1); + t1->Draw(); + t2->Draw(); + } + else { + NbUnSwap ++; + t1->SetMarkUnSwap(a1); + } + return OnSwap; +} + + + + +void GeometricalEdge::Draw(Int4 i) +{ + if (!withrgraphique) return; + + if (CurrentTh && i<0 && i != -2) + { + if (CurrentTh->Gh.edges <= this && this < CurrentTh->Gh.edges + CurrentTh->Gh.nbe) + i = CurrentTh->Gh.Number((this)); + } + + v[0]->MoveTo(); + R2 x,x50; + int k=0,k50=0; + for (int ii = 0;ii<100;ii++) { + x= F( Real4(ii)/100.0); + if(ii==50) x50=x,k50=1; + if (InPtScreen(x.x,x.y) ) + if(k) rlineto(x.x,x.y); + else k=1,rmoveto(x.x,x.y); + } + if (InPtScreen(v[1]->r.x,v[1]->r.y)) + v[1]->LineTo(); + + char VertexDraw_i10[20]; + if( k50) { + if (i<0) + sprintf(VertexDraw_i10,"Eg%p",this); + else + sprintf(VertexDraw_i10,"Eg%ld",i); + rmoveto(x50.x,x50.y); + plotstring(&VertexDraw_i10[0]); } + +} + +void Geometry::InitDraw() const +{ + GrafPMin = vertices[0].r; + GrafPMax = vertices[0].r; + // recherche des extrema des vertices GrafPMin,GrafPMax + Int4 i; + for (i=0;i<nbv;i++) { + // GrafPMax = Max2(GrafPMax,vertices[i].r); + // GrafPMin = Min2(GrafPMin,vertices[i].r); + GrafPMin.x = Min(GrafPMin.x,vertices[i].r.x); + GrafPMin.y = Min(GrafPMin.y,vertices[i].r.y); + GrafPMax.x = Max(GrafPMax.x,vertices[i].r.x); + GrafPMax.y = Max(GrafPMax.y,vertices[i].r.y); + } + float hx = (GrafPMax.x-GrafPMin.x); + float hy = (GrafPMax.y-GrafPMin.y); + Grafh = Max(hx,hy)*7/10; + if (withrgraphique) + cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.55,Grafh); + + +} + +void Geometry::Draw() const { + if (!withrgraphique) return; + + showgraphic(); + // InitDraw(); + Int4 i; + for (i=0;i<nbv;i++) + vertices[i].Draw(); + for (i=0;i<nbe;i++) + { + if(edges[i].Cracked()) couleur(4); + else couleur(6); + edges[i].Draw(i); + } + couleur(6); + for (i=0;i<nbv;i++) + if (vertices[i].Required()) { + char i10[40]; + sprintf(i10,"%ld:%d",i,vertices[i].Required()); + Move(vertices[i].r); + if(vertices[i].Corner()) couleur(2); + plotstring(i10); + if(vertices[i].Corner()) couleur(6); + } + // rattente(1); + } + +} +#endif diff --git a/contrib/bamg/bamglib/MeshGeom.cpp b/contrib/bamg/bamglib/MeshGeom.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44ee4ab83a0345f4dcf334f3f69e9d863cdd437e --- /dev/null +++ b/contrib/bamg/bamglib/MeshGeom.cpp @@ -0,0 +1,1186 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +// #define TRACETRIANGLE 3 +extern long verbosity ; +//#define strcasecmp strcmp +#include <cstdio> +#include <string.h> +#include <cmath> +#include <time.h> +#include <iostream> +using namespace std; + + +#include "Mesh2.h" +#include "QuadTree.h" +#include "SetOfE4.h" +namespace bamg { +void Triangles::ConsGeometry(Real8 cutoffradian,int *equiedges) // construct a geometry if no geo + { + // if equiedges existe taille nbe + // equiedges[i]/2 == i original + // equiedges[i]/2 = j => equivalence entre i et j => meme maillage + // equiedges[i]%2 : 0 meme sens , 1 pas meme sens + // + // -------------------------- + if (verbosity>1) + cout << " -- construction of the geometry from the 2d mesh " << endl; + if (nbt<=0 || nbv <=0 ) { MeshError(101);} + + // construction of the edges + // Triangles * OldCurrentTh =CurrentTh; + CurrentTh=this; + // Int4 NbTold = nbt; + // generation of the integer coor + // generation of the adjacence of the triangles + if (cutoffradian>=0) + Gh.MaximalAngleOfCorner = cutoffradian; + SetOfEdges4 * edge4= new SetOfEdges4(nbt*3,nbv); + Int4 * st = new Int4[nbt*3]; + Int4 i,k; + int j; + if (Gh.name) delete Gh.name; + Gh.name = new char [ name ? strlen(name) + 15 : 50 ]; + Gh.name[0]=0; + strcat(Gh.name,"cons from: "); + if (name) strcat(Gh.name,name); + else strcat(Gh.name," a mesh with no name"); + for (i=0;i<nbt*3;i++) + st[i]=-1; + Int4 kk =0; + + Int4 nbeold = nbe; + for (i=0;i<nbe;i++) + { + // cout << i << " " << Number(edges[i][0]) << " " << Number(edges[i][1]) << endl; + edge4->addtrie(Number(edges[i][0]),Number(edges[i][1])); + } + if (nbe != edge4->nb()) + { + cerr << " Some Double edge in the mesh, the number is " << nbe + << " nbe4=" << edge4->nb() << endl; + MeshError(1002); + } + for (i=0;i<nbt;i++) + for (j=0;j<3;j++) + { + // Int4 i0,i1; + Int4 k =edge4->addtrie(Number(triangles[i][VerticesOfTriangularEdge[j][0]]), + Number(triangles[i][VerticesOfTriangularEdge[j][1]])); + Int4 invisible = triangles[i].Hidden(j); + if(st[k]==-1) + st[k]=3*i+j; + else if(st[k]>=0) { + assert( ! triangles[i].TriangleAdj(j) && !triangles[st[k] / 3].TriangleAdj((int) (st[k]%3))); + + triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3)); + if (invisible) triangles[i].SetHidden(j); + if (k<nbe) { + triangles[i].SetLocked(j); + } + st[k]=-2-st[k]; } + else { + cerr << " The edge (" + << Number(triangles[i][VerticesOfTriangularEdge[j][0]]) + << " , " + << Number(triangles[i][VerticesOfTriangularEdge[j][1]]) + << " ) is in more than 2 triangles " <<k <<endl; + cerr << " Edge " << j << " Of Triangle " << i << endl; + cerr << " Edge " << (-st[k]+2)%3 << " Of Triangle " << (-st[k]+2)/3 << endl; + cerr << " Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3)) + << " Of Triangle " << Number(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) + << endl; + MeshError(9999);} + + + } + Int4 nbedges = edge4->nb(); // the total number of edges + delete edge4; + edge4 =0; + + if(verbosity>5) { + if (name) + cout << " On Mesh " << name << endl; + cout << " - The number of Vertices = " << nbv << endl; + cout << " - The number of Triangles = " << nbt << endl; + cout << " - The number of given edge = " << nbe << endl; + cout << " - The number of all edges = " << nbedges << endl; + cout << " - The Euler number = 1-Nb Of Hole = " << nbt-nbedges+nbv << endl; } + + + // check the consistant of edge[].adj and the geometrical required vertex + k=0; + kk=0; + Int4 it; + + for (i=0;i<nbedges;i++) + if (st[i] <-1) // edge internal + { + it = (-2-st[i])/3; + j = (int) ((-2-st[i])%3); + Triangle & tt = * triangles[it].TriangleAdj(j); + //cout << it << " c=" << triangles[it].color << " " << Number(tt) << " c=" << tt.color << endl; + if (triangles[it].color != tt.color|| i < nbeold) // Modif FH 06122055 // between 2 sub domai + k++; + } + else if (st[i] >=0) // edge alone + // if (i >= nbeold) + kk++; + + if(verbosity>4 && (k+kk) ) + cout << " Nb of ref edge " << kk+k << " (internal " << k << ")" + << " in file " << nbe << endl; + k += kk; + kk=0; + if (k) + { + + // if (nbe) { + // cerr << k << " boundary edges are not defined as edges " << endl; + // MeshError(9998); + // } + // construction of the edges + nbe = k; + Edge * edgessave = edges; + edges = new Edge[nbe]; + k =0; + // construction of the edges + if(verbosity>4) + cout << " Construction of the edges " << nbe << endl; + + for (i=0;i<nbedges;i++) + { + Int4 add= -1; + + if (st[i] <-1) // edge internal + { + it = (-2-st[i])/3; + j = (int) ((-2-st[i])%3); + Triangle & tt = * triangles[it].TriangleAdj(j); + if (triangles[it].color != tt.color || i < nbeold) // Modif FH 06122055 + add=k++; + } + else if (st[i] >=0) // edge alone + { + it = st[i]/3; + j = (int) (st[i]%3); + add=k++; + } + + if (add>=0 && add < nbe) + { + + edges[add].v[0] = &triangles[it][VerticesOfTriangularEdge[j][0]]; + edges[add].v[1] = &triangles[it][VerticesOfTriangularEdge[j][1]]; + edges[add].on=0; + if (i<nbeold) // in file edge // Modif FH 06122055 + { + edges[add].ref = edgessave[i].ref; + edges[add].on = edgessave[i].on; // HACK pour recuperer les aretes requise midf FH avril 2006 ???? + } + else + edges[add].ref = Min(edges[add].v[0]->ref(),edges[add].v[1]->ref()); // no a good choice + } + } + assert(k==nbe); + if (edgessave) delete [] edgessave; + } + + // construction of edges[].adj + for (i=0;i<nbv;i++) + vertices[i].color =0; + for (i=0;i<nbe;i++) + for (j=0;j<2;j++) + edges[i].v[j]->color++; + + for (i=0;i<nbv;i++) + vertices[i].color = (vertices[i].color ==2) ? -1 : -2; + for (i=0;i<nbe;i++) + for (j=0;j<2;j++) + { + Vertex *v=edges[i].v[j]; + Int4 i0=v->color,j0; + if(i0<0) + edges[i ].adj[ j ]=0; // Add FH Jan 2008 + if(i0==-1) + v->color=i*2+j; + else if (i0>=0) {// i and i0 edge are adjacent by the vertex v + j0 = i0%2; + i0 = i0/2; + assert( v == edges[i0 ].v[j0]); + edges[i ].adj[ j ] =edges +i0; + edges[i0].adj[ j0] =edges +i ; + assert(edges[i0].v[j0] == v); + // if(verbosity>8) + // cout << " edges adj " << i0 << " "<< j0 << " <--> " << i << " " << j << endl; + v->color = -3;} + } + // now reconstruct the sub domain info + assert(!NbSubDomains); + NbSubDomains=0; + + { + Int4 it; + // find all the sub domain + Int4 *colorT = new Int4[nbt]; + Triangle *tt,*t; + Int4 k; + for ( it=0;it<nbt;it++) + colorT[it]=-1; + for (it=0;it<nbt;it++) + { + if (colorT[it]<0) + { + colorT[it]=NbSubDomains; + Int4 level =1,j,jt,kolor=triangles[it].color; + st[0]=it; // stack + st[1]=0; + k=1; + while (level>0) + if( ( j=st[level]++) <3) + { + t = &triangles[st[level-1]]; + tt=t->TriangleAdj((int)j); + + if ( ! t->Locked(j) && tt && (colorT[jt = Number(tt)] == -1) && ( tt->color==kolor)) + { + colorT[jt]=NbSubDomains; + st[++level]=jt; + st[++level]=0; + k++; + } + } + else + level-=2; + if (verbosity>5) + cout << " Nb of triangles " << k << " of Subdomain " + << NbSubDomains << " " << kolor << endl; + NbSubDomains++; + } + } + if (verbosity> 3) + cout << " The Number of sub domain = " << NbSubDomains << endl; + + Int4 isd; + subdomains = new SubDomain[NbSubDomains]; + for (isd=0;isd<NbSubDomains;isd++) + { + subdomains[isd].head =0; + } + k=0; + for (it=0;it<nbt;it++) + for (int j=0;j<3;j++) + { + tt=triangles[it].TriangleAdj(j); + if ((!tt || triangles[it].Locked(j) || tt->color != triangles[it].color) && !subdomains[isd=colorT[it]].head) + { + subdomains[isd].head = triangles+it; + subdomains[isd].ref = triangles[it].color; + subdomains[isd].sens = j; // hack + subdomains[isd].edge = 0; + k++; + } + } + assert(k== NbSubDomains); + + delete [] colorT; + + + } + delete [] st; + // now make the geometry + // 1 compress the vertices + Int4 * colorV = new Int4[nbv]; + for (i=0;i<nbv;i++) + colorV[i]=-1; + for (i=0;i<nbe;i++) + for ( j=0;j<2;j++) + colorV[Number(edges[i][j])]=0; + k=0; + for (i=0;i<nbv;i++) + if(!colorV[i]) + colorV[i]=k++; + + Gh.nbv=k; + Gh.nbe = nbe; + Gh.vertices = new GeometricalVertex[k]; + Gh.edges = new GeometricalEdge[nbe]; + Gh.NbSubDomains = NbSubDomains; + Gh.subdomains = new GeometricalSubDomain[NbSubDomains]; + if (verbosity>3) + cout << " Nb of vertices = " << Gh.nbv << " Nb of edges = " << Gh.nbe << endl; + NbVerticesOnGeomVertex = Gh.nbv; + VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex]; + NbVerticesOnGeomEdge =0; + VerticesOnGeomEdge =0; + { + Int4 j; + for (i=0;i<nbv;i++) + if((j=colorV[i])>=0) + { + + Vertex & v = Gh.vertices[j]; + v = vertices[i]; + v.color =0; + VerticesOnGeomVertex[j] = VertexOnGeom(vertices[i], Gh.vertices[j]); + } + + } + edge4= new SetOfEdges4(nbe,nbv); + + Real4 * len = new Real4[Gh.nbv]; + for(i=0;i<Gh.nbv;i++) + len[i]=0; + + Gh.pmin = Gh.vertices[0].r; + Gh.pmax = Gh.vertices[0].r; + // recherche des extrema des vertices pmin,pmax + for (i=0;i<Gh.nbv;i++) { + Gh.pmin.x = Min(Gh.pmin.x,Gh.vertices[i].r.x); + Gh.pmin.y = Min(Gh.pmin.y,Gh.vertices[i].r.y); + Gh.pmax.x = Max(Gh.pmax.x,Gh.vertices[i].r.x); + Gh.pmax.y = Max(Gh.pmax.y,Gh.vertices[i].r.y); + } + + R2 DD05 = (Gh.pmax-Gh.pmin)*0.05; + Gh.pmin -= DD05; + Gh.pmax += DD05; + + Gh.coefIcoor= (MaxICoor)/(Max(Gh.pmax.x-Gh.pmin.x,Gh.pmax.y-Gh.pmin.y)); + assert(Gh.coefIcoor >0); + + Real8 hmin = HUGE_VAL; + int kreq=0; + for (i=0;i<nbe;i++) + { + Int4 i0 = Number(edges[i][0]); + Int4 i1 = Number(edges[i][1]); + Int4 j0 = colorV[i0]; + Int4 j1 = colorV[i1]; + + Gh.edges[i].v[0] = Gh.vertices + j0; + Gh.edges[i].v[1] = Gh.vertices + j1; + Gh.edges[i].flag = 0; + Gh.edges[i].tg[0]=R2(); + Gh.edges[i].tg[1]=R2(); + bool requis= edges[i].on; + if(requis) kreq++; + edges[i].on = Gh.edges + i; + if(equiedges && i < nbeold ) { + int j=equiedges[i]/2; + int sens=equiedges[i]%2; + if(i!=j && equiedges[i]>=0) { + if(verbosity>9) + cout << " Edges Equi " << i << " <=> " << j << " sens = " << sens << endl; + if( sens==0) + Gh.edges[i].SetEqui(); + else + Gh.edges[i].SetReverseEqui(); + Gh.edges[i].link= & Gh.edges[j]; + //assert(sens==0);// meme sens pour l'instant + } + + } + if(requis) { // correction fevr 2009 JYU ... + Gh.edges[i].v[0]->SetRequired(); + Gh.edges[i].v[1]->SetRequired(); + Gh.edges[i].SetRequired(); // fin modif ... + } + R2 x12 = Gh.vertices[j0].r-Gh.vertices[j1].r; + Real8 l12=Norme2(x12); + hmin = Min(hmin,l12); + + Gh.vertices[j1].color++; + Gh.vertices[j0].color++; + + len[j0]+= l12; + len[j1] += l12; + hmin = Min(hmin,l12); + + Gh.edges[i].ref = edges[i].ref; + + k = edge4->addtrie(i0,i1); + + assert(k == i); + + } + + + for (i=0;i<Gh.nbv;i++) + if (Gh.vertices[i].color > 0) + Gh.vertices[i].m= Metric(len[i] /(Real4) Gh.vertices[i].color); + else + Gh.vertices[i].m= Metric(hmin); + delete [] len; + for (i=0;i<NbSubDomains;i++) + { + Int4 it = Number(subdomains[i].head); + int j = subdomains[i].sens; + Int4 i0 = Number(triangles[it][VerticesOfTriangularEdge[j][0]]); + Int4 i1 = Number(triangles[it][VerticesOfTriangularEdge[j][1]]); + k = edge4->findtrie(i0,i1); + if(k>=0) + { + subdomains[i].sens = (vertices + i0 == edges[k].v[0]) ? 1 : -1; + subdomains[i].edge = edges+k; + Gh.subdomains[i].edge = Gh.edges + k; + Gh.subdomains[i].sens = subdomains[i].sens; + Gh.subdomains[i].ref = subdomains[i].ref; + } + else + MeshError(103); + } + + delete edge4; + delete [] colorV; + // -- unset adj + for (i=0;i<nbt;i++) + for ( j=0;j<3;j++) + triangles[i].SetAdj2(j,0,triangles[i].GetAllflag(j)); + +} + + +void Geometry::EmptyGeometry() // empty geometry + { + OnDisk=0; + NbRef=0; + name =0; + quadtree=0; + curves=0; + // edgescomponante=0; + triangles=0; + edges=0; + vertices=0; + NbSubDomains=0; + // nbtf=0; +// BeginOfCurve=0; + nbiv=nbv=nbvx=0; + nbe=nbt=nbtx=0; + NbOfCurves=0; +// BeginOfCurve=0; + subdomains=0; + MaximalAngleOfCorner = 10*Pi/180; + } + + + +Geometry::Geometry(const Geometry & Gh) + { Int4 i; + *this = Gh; + NbRef =0; + quadtree=0; + name = new char[strlen(Gh.name)+4]; + strcpy(name,"cp:"); + strcat(name,Gh.name); + vertices = nbv ? new GeometricalVertex[nbv] : NULL; + triangles = nbt ? new Triangle[nbt]:NULL; + edges = nbe ? new GeometricalEdge[nbe]:NULL; + curves= NbOfCurves ? new Curve[NbOfCurves]:NULL; + subdomains = NbSubDomains ? new GeometricalSubDomain[NbSubDomains]:NULL; + for (i=0;i<nbv;i++) + vertices[i].Set(Gh.vertices[i],Gh,*this); + for (i=0;i<nbe;i++) + edges[i].Set(Gh.edges[i],Gh,*this); + for (i=0;i<NbOfCurves;i++) + curves[i].Set(Gh.curves[i],Gh,*this); + for (i=0;i<NbSubDomains;i++) + subdomains[i].Set(Gh.subdomains[i],Gh,*this); + + // for (i=0;i<nbt;i++) + // triangles[i].Set(Gh.triangles[i],Gh,*this); + assert(!nbt); + } + + +GeometricalEdge* Geometry::Contening(const R2 P, GeometricalEdge * start) const +{ + GeometricalEdge* on =start,* pon=0; + // walk with the cos on geometry + // cout << P ; + int k=0; + while(pon != on) + { + pon = on; + assert(k++<100); + R2 A= (*on)[0]; + R2 B= (*on)[1]; + R2 AB = B-A; + R2 AP = P-A; + R2 BP = P-B; + // cout << ":: " << on - edges << " " << AB*AP << " " << AB*BP << " " << A << B << endl; + if ( (AB,AP) < 0) + on = on->Adj[0]; + else if ( (AB,BP) > 0) + on = on->Adj[1]; + else + return on; + } + return on; +} +GeometricalEdge* Geometry::ProjectOnCurve(const Edge & e,Real8 s,Vertex &V,VertexOnGeom &GV ) const + { + Real8 save_s=s; + int NbTry=0; +retry: + s=save_s; + GeometricalEdge * on = e.on; + assert(on); + assert( e[0].on && e[1].on); + const Vertex &v0=e[0],&v1=e[1]; + V.m = Metric(1.0-s, v0,s, v1); +#define MXE__LINE __LINE__+1 + const int mxe =100; + GeometricalEdge *ge[mxe+1]; + int sensge[mxe+1]; + Real8 lge[mxe+1]; + int bge=mxe/2,tge=bge; + ge[bge] = e.on; + sensge[bge]=1; + + R2 V0 = v0,V1=v1,V01=V1-V0; + VertexOnGeom vg0= *v0.on, vg1=*v1.on; + if(NbTry) cout << "bug: s==== " << s << " e=" << V0 << " " << V1 << endl; + + // GeometricalEdge * eg0 = e.on,* eg1 = e.on, *eg=NULL; + GeometricalEdge * eg0=on, *eg1=on; + R2 Ag=(R2) (*on)[0],Bg=(R2)(*on)[1],AB=Bg-Ag; + if(NbTry) cout <<" G edge= " << Ag << Bg << endl << " v edge" << V01 << " v geom " << AB << (V01,AB) <<endl; + int OppositeSens = (V01,AB) < 0; + int sens0=0,sens1=1; + if (OppositeSens) + s=1-s,Exchange(vg0,vg1),Exchange(V0,V1); + // find all the discretisation of the egde +#ifdef DEBUG + // we supposee edge on=[Ag,Bg] intersect edge [V0,V1]; + // => V0Ag.V0V1 > 0 || V0Bg.V0V1 >0 + // => V1Ag.V0V1 < 0 || V0Bg.V0V1 <0 + R2 V0V1 = V1-V0; + Real8 cos0A = ((Ag-V0),V0V1); + Real8 cos0B = ((Bg-V0),V0V1); + Real8 cos1A = ((Ag-V1),V0V1); + Real8 cos1B = ((Bg-V1),V0V1); + if ( (cos0A < 0 && cos0B <0) || (cos1A> 0 && cos1B >0)) + { + cerr << " Bug on pointer edge [" << V0 << " , " << V1 << " ] " + << " on geometrical edge " << Number(on) << " = [" << Ag << " , " << Bg << " ] " << endl; + cerr << cos0A << "> 0 || " << cos0B << " > 0 and "; + cerr << cos1A << "< 0 || " << cos1B << " < 0 " << endl; + + exit (1); + } + +#endif + if(NbTry) cout << "bug: edge = " << v0.r << " -> " << v1.r << endl + << "sg 0 = " << vg0 + << " on = " << Number(on) << ":" << Ag << Bg << "; " + << " sg 1= " << vg1 + << "--------------------------------------------" << endl; + while (eg0 != (GeometricalEdge*) vg0 && (*eg0)(sens0) != (GeometricalVertex*) vg0) + { + if (bge<=0) { + // int kkk; + // if (NbTry) cout <<"Read (int) to Show Sioux window", cin >> kkk ; + if(NbTry) + { + cerr << " -- Fatal Error: on the class triangles before call Geometry::ProjectOnCurve" << endl; + cerr << " The mesh of the Geometry is to fine: "; + cerr << " 1) a mesh edge contening more than "<< mxe/2 << " geometrical edges." << endl; + cerr << " 2) code bug : be sure that we call Triangles::SetVertexFieldOn() before " << endl; + cerr << " To solve the problem do a coarsening of the geometrical mesh " << endl; + cerr << " or change the constant value of mxe in " << __FILE__ << " line " << MXE__LINE << "( dangerous way )" << endl; + MeshError(222); + } + NbTry++; + goto retry;} + GeometricalEdge* tmpge = eg0; + if(NbTry) + cout << "bug: --Edge @" << Number(tmpge) << " = "<< Number(eg0) << ":" <<Number(eg0->Adj[0]) << "," << + Number(eg0->Adj[1]) <<"," ; + ge[--bge] =eg0 = eg0->Adj[sens0]; + assert(bge>=0 && bge <= mxe); + sens0 = 1-( sensge[bge] = tmpge->SensAdj[sens0]); + if(NbTry) + cout << "bug: Edge " << Number(eg0) << " "<< 1-sens0 << " S " + << Number((*eg0)[1-sens0]) <<":" << Number(eg0->Adj[0]) << "," + << Number(eg0->Adj[1]) <<"," << endl + <<Number(eg0)<< (*eg0)[sens0].r << "v = " << Number((*eg1)(sens0)) << " e = " << eg0 << endl; + } + if(NbTry) cout << Number((GeometricalEdge*) vg1) << " " << Number((GeometricalVertex*) vg1) << endl; + while (eg1 != (GeometricalEdge*) vg1 && (*eg1)(sens1) != (GeometricalVertex*) vg1) + { + if(tge>=mxe ) { + cerr << " --Fatal Error: on the class triangles before call Geometry::ProjectOnCurve" << endl; + NbTry++; + if (NbTry<2) goto retry; + cerr << " The mesh of the Geometry is to fine:" ; + cerr << " 1) a mesh edge contening more than "<< mxe/2 << " geometrical edges." << endl; + cerr << " 2) code bug : be sure that we call Triangles::SetVertexFieldOn() before " << endl; + cerr << " To solve the problem do a coarsening of the geometrical mesh " << endl; + cerr << " or change the constant value of mxe in " << __FILE__ << " line " << MXE__LINE << "( dangerous way )" << endl; + MeshError(223); + } + + GeometricalEdge* tmpge = eg1; + if(NbTry) + cout << "++Edge @" << tmpge << " = " << Number(eg1) <<"%" << Number(eg1->Adj[0]) << "," + << Number(eg1->Adj[1]) <<"," ; + ge[++tge] =eg1 = eg1->Adj[sens1]; + sensge[tge]= sens1 = 1-tmpge->SensAdj[sens1]; + assert(tge>=0 && tge <= mxe); + if(NbTry) + cout << " Edge " << Number(eg1) << " " << sens1 << " S " + <<Number((*eg1)[sens1]) <<"%"<< Number(eg1->Adj[0]) << "," << Number(eg1->Adj[1]) <<"," + <<Number(eg1)<< (*eg1)[sens1].r << "v = " << Number((*eg1)(sens1)) << " e = " << Number(eg1) << endl; + } + + if(NbTry) cout << endl; + + + if ( (*eg0)(sens0) == (GeometricalVertex*) vg0 ) + vg0 = VertexOnGeom( *(Vertex *) vg0,*eg0,sens0); + + if ( (*eg1)(sens1) == (GeometricalVertex*) vg1) + vg1 = VertexOnGeom( *(Vertex *) vg1,*eg1,sens1); + + Real8 sg; + // cout << " " << Number(on) << " " << Number(eg0) << " " << Number(eg1) << " " ; + if (eg0 == eg1) { + register Real8 s0= vg0,s1=vg1; + sg = s0 * (1.0-s) + s * s1; + // cout <<" s0=" << s0 << " s1=" << s1 + // << " s = " << s << " sens= " << OppositeSens << "\t\t sg = " << sg << endl ; + on=eg0;} + else { + R2 AA=V0,BB; + Real8 s0,s1; + + //cout << endl << "s= " << s << Number(eg0) << " " << (Real8) vg0 << " " + // << Number(eg1) << " " << (Real8) vg1 << V0 << V1 << " Interpol = " + // << V0*(1-s)+V1*s << ";;; " << endl; + int i=bge; + Real8 ll=0; + for(i=bge;i<tge;i++) + { + assert( i>=0 && i <= mxe); + BB = (*ge[i])[sensge[i]]; + lge[i]=ll += Norme2(AA-BB); + // cout << " ll " << i << BB << ll << " " <<sensge[i] <<" on = " << + // Number(ge[i]) << " sens= " << sensge[i] ; + AA=BB ;} + lge[tge]=ll+=Norme2(AA-V1); + // cout << " ll " << tge << " " << ll << sensge[tge] + // <<" on = " << Number(ge[tge]) << " sens= " << sensge[tge] << endl; + // search the geometrical edge + assert(s <= 1.0); + Real8 ls= s*ll; + on =0; + s0 = vg0; + s1= sensge[bge]; + Real8 l0=0,l1; + i=bge; + while ( (l1=lge[i]) < ls ) { + assert(i >= 0 && i <= mxe); + i++,s0=1-(s1=sensge[i]),l0=l1;} + on=ge[i]; + if (i==tge) + s1=vg1; + + s=(ls-l0)/(l1-l0); + // cout << "on =" << Number(on) << sens0 << sens1 << "s0 " << s0 << " s1 =" + // << s1 << " l0 =" << l0 << " ls= " << ls << " l1= " << l1 << " s= " << s; + sg = s0 * (1.0-s) + s * s1; + } + assert(on); + // assert(sg && sg-1); + V.r= on->F(sg); + // if (eg0 != eg1) + // cout << "----- sg = "<< sg << " Sens =" << OppositeSens << " Edge = " + // << Number(on) <<" V=" << V << endl; + GV=VertexOnGeom(V,*on,sg); + return on; + } + +void Geometry::AfterRead() + {// ----------------- + if (verbosity>20) + cout << "Geometry::AfterRead()" << nbv << " " << nbe << endl; + Int4 i,k=0; ; + int jj; // jj in [0,1] + Int4 * hv = new Int4 [ nbv]; + Int4 * ev = new Int4 [ 2 * nbe ]; + float * eangle = new float[ nbe ]; + { + double eps = 1e-20; + QuadTree quadtree; // to find same vertices + Vertex * v0 = vertices; + GeometricalVertex * v0g = (GeometricalVertex *) (void *) v0; + int k=0; + for (i=0;i<nbv;i++) + vertices[i].link = vertices +i; + for (i=0;i<nbv;i++) + { + vertices[i].i = toI2(vertices[i].r); // set integer coordinate + Vertex *v= quadtree.NearestVertex(vertices[i].i.x,vertices[i].i.y); + if( v && Norme1(v->r - vertices[i]) < eps ) + { // link v & vertices[i] + // vieille ruse pour recuperer j + GeometricalVertex * vg = (GeometricalVertex *) (void *) v; + int j = vg-v0g; + assert( v == & (Vertex &) vertices[j]); + vertices[i].link = vertices + j; + k++; + } + else quadtree.Add(vertices[i]); + } + if (k) { + cout << " Number of distinte vertices " << nbv - k << " Over " << nbv << endl; + //if (verbosity>10) + { + cout << " The duplicate vertex " << endl; + for (i=0;i<nbv;i++) + if (!vertices[i].IsThe()) + cout << " " << i << " and " << Number(vertices[i].The()) << endl; + MeshError(102); + //throw(ErrorExec("exit",1)); + } + } + + // verification of cracked edge + int err =0; + for (i=0;i<nbe;i++) + if (edges[i].Cracked() ) + { + // verification of crack + GeometricalEdge & e1=edges[i]; + GeometricalEdge & e2=*e1.link; + cerr << i << " " << e1[0].The() << " " << e2[0].The() << " " << e1[1].The() << " " << e2[1].The() << endl; + if ( e1[0].The() == e2[0].The() && e1[1].The() == e2[1].The() ) + { + } + else + if ( e1[0].The() == e2[1].The() && e1[1].The() == e2[0].The() ) + { + } + else + { + err++; + cerr << " Cracked edges with no same vertex " << &e1-edges << " " << &e2 -edges << endl; + } + } + else + { + // if (!edges[i][0].IsThe()) err++; + // if (!edges[i][1].IsThe()) err++; + } + if (err) + { + cerr << " Some vertex was not distint and not on cracked edge " << err<< endl; + MeshError(222); + } + } + if(verbosity>7) + for (i=0;i<nbv;i++) + if (vertices[i].Required()) + cout << " The geo vertices " << i << " is required" << endl; + + for (i=0;i<nbv;i++) + hv[i]=-1;// empty list + + for (i=0;i<nbe;i++) + { + R2 v10 = edges[i].v[1]->r - edges[i].v[0]->r; + Real8 lv10 = Norme2(v10); + if(lv10 == 0) { + cerr << "The length of " <<i<< "th Egde is 0 " << endl ; + MeshError(1);} + eangle[i] = atan2(v10.y,v10.x) ; // angle in [ -Pi,Pi ] + if(verbosity>9) + cout << " angle edge " << i <<" " << eangle[i]*180/Pi<< v10<<endl; + for (jj=0;jj<2;jj++) + { // generation of list + Int4 v = Number(edges[i].v[jj]); + ev[k] = hv[v]; + hv[v] = k++; + } + } + // bulle sort on the angle of edge + for (i=0;i<nbv;i++) { + int exch = 1,ord =0; + while (exch) { + exch = 0; + Int4 *p = hv + i, *po = p; + Int4 n = *p; + register float angleold = -1000 ; // angle = - infini + ord = 0; + while (n >=0) + { + ord++; + register Int4 i1= n /2; + register Int4 j1 = n % 2; + register Int4 *pn = ev + n; + float angle = j1 ? OppositeAngle(eangle[i1]): eangle[i1]; + n = *pn; + if (angleold > angle) // exch to have : po -> pn -> p + exch=1,*pn = *po,*po=*p,*p=n,po = pn; + else // to have : po -> p -> pn + angleold = angle, po = p,p = pn; + } + } // end while (exch) + + if (ord >= 1 ) + { /* + Int4 n = hv[i]; + while ( n >=0) + { Int4 i1 = n/2,j1 = n%2; + //float a = 180*(j1 ? OppositeAngle(eangle[i1]): eangle[i1])/Pi; + n = ev[n]; + } + */ + } + if(ord == 2) { // angulare test to find a corner + Int4 n1 = hv[i]; + Int4 n2 = ev[n1]; + Int4 i1 = n1 /2, i2 = n2/2; // edge number + Int4 j1 = n1 %2, j2 = n2%2; // vertex in the edge + float angle1= j1 ? OppositeAngle(eangle[i1]) : eangle[i1]; + float angle2= !j2 ? OppositeAngle(eangle[i2]) : eangle[i2]; + float da12 = Abs(angle2-angle1); + if(verbosity>9) + cout <<" check angle " << i << " " << i1 << " " << i2 << " " << 180*(da12)/Pi + << " " << 180*MaximalAngleOfCorner/Pi << vertices[i] << endl; + + if (( da12 >= MaximalAngleOfCorner ) + && (da12 <= 2*Pi -MaximalAngleOfCorner)) { + vertices[i].SetCorner() ; + if(verbosity>7) + cout << " The vertex " << i << " is a corner (angle) " + << 180*(da12)/ Pi<< " " << 180*MaximalAngleOfCorner/Pi << endl;} + // if the ref a changing then is SetRequired(); + + if (edges[i1].flag != edges[i2].flag || edges[i1].Required()) + { + vertices[i].SetRequired(); + if(verbosity>7) + cout << " The vertex " << i << " is Required the flag change (crack or equi, or require)" << endl;} + + if (edges[i1].ref != edges[i2].ref) { + vertices[i].SetRequired(); + if(verbosity>7) + cout << " The vertex " << i << " is Required ref" << endl;} + } ; + + if(ord != 2) { + vertices[i].SetCorner(); + if(verbosity>7) + cout << " the vertex " << i << " is a corner ordre = " << ord << endl; + } + // close the liste around the vertex + { Int4 no=-1, ne = hv[i]; + while ( ne >=0) + ne = ev[no=ne]; + if(no>=0) + ev[no] = hv[i]; + } // now the list around the vertex is circular + + } // end for (i=0;i<nbv;i++) + + k =0; + for (i=0;i<nbe;i++) + for (jj=0;jj<2;jj++){ + Int4 n1 = ev[k++]; + Int4 i1 = n1/2 ,j1=n1%2; + if( edges[i1].v[j1] != edges[i].v[jj]) + { cerr << " Bug Adj edge " << i << " " << jj << + " et " << i1 << " " << j1 << " k=" << k; + cerr << Number(edges[i].v[jj]) <<" <> " + << Number(edges[i1].v[j1]) <<endl; + cerr << "edge " << Number(edges[i].v[0]) << " " + << Number(edges[i].v[1]) << endl; + // cerr << "in file " <<filename <<endl; + MeshError(1); + } + edges[i1].Adj[j1] = edges + i; + edges[i1].SensAdj[j1] = jj; + if (verbosity>10) + cout << " edges. Adj " << i1 << " " << j1 << " <--- " << i << " " << jj << endl; + } + + // generation of all the tangente + for (i=0;i<nbe;i++) { + R2 AB = edges[i].v[1]->r -edges[i].v[0]->r; + Real8 lAB = Norme2(AB); // length of current edge AB + Real8 ltg2[2]; + ltg2[0]=0;ltg2[1]=0; + for (jj=0;jj<2;jj++) { + R2 tg = edges[i].tg[jj]; + Real8 ltg = Norme2(tg); // length of tg + if(ltg == 0) {// no tg + if( ! edges[i].v[jj]->Corner()) { // not a Corner + tg = edges[i].v[1-jj]->r + - edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r; + ltg = Norme2(tg); + tg = tg *(lAB/ltg),ltg=lAB; + /* + if(edges[i].ref >=4) + cout << " tg " << tg.x << " "<< tg.y << " " << edges[i].v[1-jj]->r << edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r << " y-y = " + << edges[i].v[1-jj]->r.y -edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r.y << endl; + */ + } + + //else ;// a Corner with no tangent => nothing to do + } // a tg + else + tg = tg *(lAB/ltg),ltg=lAB; + ltg2[jj] = ltg; + if ( (tg,AB) < 0) + tg = -tg; + //if(edges[i].ref >=4) cout << " tg = " << tg << endl; + edges[i].tg[jj] = tg; + } // for (jj=0;jj<2;jj++) + + if (ltg2[0]!=0) edges[i].SetTgA(); + if (ltg2[1]!=0) edges[i].SetTgB(); + } // for (i=0;i<nbe;i++) + + if(verbosity>7) + for (i=0;i<nbv;i++) + if (vertices[i].Required()) + cout << " The geo vertices " << i << " is required " << endl; + + for (int step=0;step<2;step++) + { + for (i=0;i<nbe;i++) + edges[i].SetUnMark(); + + NbOfCurves = 0; + Int4 nbgem=0; + for (int level=0;level < 2 && nbgem != nbe;level++) + for (i=0;i<nbe;i++) { + GeometricalEdge & ei = edges[i]; + for(jj=0;jj<2;jj++) + if (!ei.Mark() && (level || ei[jj].Required())) { + // warning ei.Mark() can be change in loop for(jj=0;jj<2;jj++) + int k0=jj,k1; + GeometricalEdge *e = & ei; + GeometricalVertex *a=(*e)(k0); // begin + if(curves) { + curves[NbOfCurves].be=e; + curves[NbOfCurves].kb=k0; + } + int nee=0; + for(;;) { + nee++; + k1 = 1-k0; // next vertex of the edge + e->SetMark(); + nbgem++; + e->CurveNumber=NbOfCurves; + if(curves) { + curves[NbOfCurves].ee=e; + curves[NbOfCurves].ke=k1; + } + + GeometricalVertex *b=(*e)(k1); + if (a == b || b->Required() ) break; + k0 = e->SensAdj[k1];// vertex in next edge + e = e->Adj[k1]; // next edge + + }// for(;;) + if(verbosity>10 && curves==0) cout << NbOfCurves <<" curve : nb edges= "<< nee<< endl; + NbOfCurves++; + if(level) { + if(verbosity>4) + cout << " Warning: Curve "<< NbOfCurves << " without required vertex " + << "so the vertex " << Number(a) << " become required " <<endl; + a->SetRequired(); + } + + }} + assert(nbgem && nbe); + + if(step==0) { + curves = new Curve[NbOfCurves]; + } + } + for(int i=0;i<NbOfCurves ;i++) + { + GeometricalEdge * be=curves[i].be, *eqbe=be->link; + //GeometricalEdge * ee=curves[i].ee, *eqee=be->link; + curves[i].master=true; + if(be->Equi() || be->ReverseEqui() ) + { + assert(eqbe); + int nc = eqbe->CurveNumber; + assert(i!=nc); + curves[i].next=curves[nc].next; + curves[i].master=false; + curves[nc].next=curves+i; + if(be->ReverseEqui()) + curves[i].Reverse(); + } + } + + if(verbosity>3) + cout << " End ReadGeometry: Number of curves in geometry is " << NbOfCurves <<endl; + if(verbosity>4) + for(int i=0;i<NbOfCurves ;i++) + { + cout << " Curve " << i << " begin e=" << Number(curves[i].be) << " k=" << curves[i].kb + << " end e= " << Number(curves[i].ee) << " k=" << curves[i].ke << endl; + } + delete []ev; + delete []hv; + delete []eangle; + +} +Geometry::~Geometry() +{ + assert(NbRef<=0); + if(verbosity>9) + cout << "DELETE ~Geometry "<< this << endl; + if(vertices) delete [] vertices;vertices=0; + if(edges) delete [] edges;edges=0; + // if(edgescomponante) delete [] edgescomponante; edgescomponante=0; + if(triangles) delete [] triangles;triangles=0; + if(quadtree) delete quadtree;quadtree=0; + if(curves) delete []curves;curves=0;NbOfCurves=0; + if(name) delete [] name;name=0; + if(subdomains) delete [] subdomains;subdomains=0; +// if(ordre) delete [] ordre; + EmptyGeometry(); + +} + +Real8 GeometricalEdge::R1tg(Real8 theta,R2 & t) const // 1/R of radius of cuvature +{ R2 A=v[0]->r,B=v[1]->r; + Real8 dca,dcb,dcta,dctb; + Real8 ddca,ddcb,ddcta,ddctb; + // Real8 t1 = 1 -theta; + // Real8 t1t1 = t1*t1; + Real8 tt = theta*theta; + assert( theta >=0); + assert( theta <=1); + if (TgA()) + if (TgB()) // interpolation d'hermite + { //cb = theta*theta*(3-2*theta); + dcb = 6*theta*(1-theta); + ddcb = 6*(1-2*theta); + //ca = 1-cb; + dca = -dcb; + ddca = -ddcb; + + // cta = (1-theta)*(1-theta)*theta; + dcta = (3*theta - 4)*theta + 1; + ddcta=6*theta-4; + + //ctb = (theta-1)*theta*theta ; + dctb = 3*tt - 2*theta; + ddctb = 6*theta-2; + } + else { // 1-t*t, t-t*t, t*t + Real8 t = theta; + // cb = t*t; + dcb = 2*t; + ddcb = 2; + //ca = 1-cb; + dca = -dcb; + ddca = -2; + // cta= t-cb; + dcta = 1-dcb; + ddcta = -ddcb; + // ctb =0; + dctb=0; + ddctb=0; + } + else + if (TgB()){ + Real8 t = 1-theta; + //ca = t*t; + dca = -2*t; + ddca = 2; + //cb = 1-ca; + dcb = -dca; + ddcb = -2; + //ctb= -t+ca; + dctb = 1+dca; + ddctb= ddca; + //cta=0; + dcta =0; + ddcta =0; + } + else {t=B-A;return 0;} // lagrange P1 + R2 d = A*dca + B*dcb + tg[0]* dcta + tg[1] * dctb; + + R2 dd = A*ddca + B*ddcb + tg[0]* ddcta + tg[1] * ddctb; + Real8 d2=(d,d); + Real8 sd2 = sqrt(d2); + t=d; + if(d2>1.0e-20) {t/=sd2;return Abs(Det(d,dd))/(d2*sd2);} + else return 0; + +} + + +R2 GeometricalEdge::F(Real8 theta) const // parametrization of the curve edge +{ R2 A=v[0]->r,B=v[1]->r; + Real8 ca,cb,cta,ctb; + assert( theta >=-1e-12); + assert( theta <=1+1e-12); + if (TgA()) + if (TgB()) // interpolation d'hermite + { cb = theta*theta*(3-2*theta); + ca = 1-cb; + cta = (1-theta)*(1-theta)*theta; + ctb = (theta-1)*theta*theta ; + // if(ref==4 || ref==5) + // cout << " FFF " << tg[0] << tg[1] << A << B << " => " << A*ca + B*cb + tg[0]* cta + tg[1] * ctb << endl; + } + else { // 1-t*t, t-t*t, t*t + Real8 t = theta; + cb = t*t; + ca = 1-cb; + cta= t-cb; + ctb=0; + } + else + if (TgB()){ + Real8 t = 1-theta; + ca = t*t; + cb = 1-ca; + ctb= -t+ca; + cta=0; + } + else { + ca =(1-theta),cb = theta,cta=ctb=0; // lagrange P1 + } + return A*ca + B*cb + tg[0]* cta + tg[1] * ctb; + +} + +} diff --git a/contrib/bamg/bamglib/MeshQuad.cpp b/contrib/bamg/bamglib/MeshQuad.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a890a38a874f2654cd32aa15e263069c91266306 --- /dev/null +++ b/contrib/bamg/bamglib/MeshQuad.cpp @@ -0,0 +1,943 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : hecht@ann.jussieu.fr +// +// ********** DO NOT REMOVE THIS BANNER ********** +/* + + 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 + */ + +// +// SUMMARY: Bamg: Bidimensional Anisotrope Mesh Generator +// RELEASE: 0 +// AUTHOR: F. Hecht, +// ORG : UMPC +// E-MAIL : Frederic.Hecht@Inria.fr +// +// ORIG-DATE: frev 98 +//--------------------------------------------------------- +// to make quad +// ------------------- + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <time.h> + +#include "Meshio.h" +#include "Mesh2.h" +#include "QuadTree.h" +#include "SetOfE4.h" + +namespace bamg { + +static const Direction NoDirOfSearch=Direction(); + +#ifdef __MWERKS__ +#pragma global_optimizer on +#pragma optimization_level 1 +//#pragma inline_depth 0 +#endif + +class DoubleAndInt4 { +public: double q; Int4 i3j; + int operator<(DoubleAndInt4 a){return q > a.q;} +};// to sort by decroissant + + + +template<class T> inline void HeapSort(T *c,long n) +{ + long l,j,r,i; + T crit; + c--; // on decale de 1 pour que le tableau commence a 1 + if( n <= 1) return; + l = n/2 + 1; + r = n; + while (1) { // label 2 + if(l <= 1 ) { // label 20 + crit = c[r]; + c[r--] = c[1]; + if ( r == 1 ) { c[1]=crit; return;} + } else crit = c[--l]; + j=l; + while (1) {// label 4 + i=j; + j=2*j; + if (j>r) {c[i]=crit;break;} // L8 -> G2 + if ((j<r) && (c[j] < c[j+1])) j++; // L5 + if (crit < c[j]) c[i]=c[j]; // L6+1 G4 + else {c[i]=crit;break;} //L8 -> G2 + } + } +} + +Triangle * swapTest(Triangle *t1,Int2 a); +// + + +double QuadQuality(const Vertex & a,const Vertex &b,const Vertex &c,const Vertex &d) +{ + // calcul de 4 angles -- + R2 A((R2)a),B((R2)b),C((R2)c),D((R2)d); + R2 AB(B-A),BC(C-B),CD(D-C),DA(A-D); + // Move(A),Line(B),Line(C),Line(D),Line(A); + const Metric & Ma = a; + const Metric & Mb = b; + const Metric & Mc = c; + const Metric & Md = d; + + double lAB=Norme2(AB); + double lBC=Norme2(BC); + double lCD=Norme2(CD); + double lDA=Norme2(DA); + AB /= lAB; BC /= lBC; CD /= lCD; DA /= lDA; + // version aniso + double cosDAB= Ma(DA,AB)/(Ma(DA)*Ma(AB)),sinDAB= Det(DA,AB); + double cosABC= Mb(AB,BC)/(Mb(AB)*Mb(BC)),sinABC= Det(AB,BC); + double cosBCD= Mc(BC,CD)/(Mc(BC)*Mc(CD)),sinBCD= Det(BC,CD); + double cosCDA= Md(CD,DA)/(Md(CD)*Md(DA)),sinCDA= Det(CD,DA); + double sinmin=Min(Min(sinDAB,sinABC),Min(sinBCD,sinCDA)); + // cout << A << B << C << D ; + // cout << " sinmin " << sinmin << " " << cosDAB << " " << cosABC << " " << cosBCD << " " << cosCDA << endl; + // rattente(1); + if (sinmin<=0) return sinmin; + return 1.0-Max(Max(Abs(cosDAB),Abs(cosABC)),Max(Abs(cosBCD),Abs(cosCDA))); +} + + GeometricalEdge * Triangles::ProjectOnCurve( Edge & BhAB, Vertex & vA, Vertex & vB, + Real8 theta, + Vertex & R,VertexOnEdge & BR,VertexOnGeom & GR) + +{ + void *pA=0,*pB=0; + Real8 tA=0,tB=0; + R2 A=vA,B=vB; + Vertex * pvA=&vA, * pvB=&vB; + if (vA.vint == IsVertexOnVertex) + { + // cout << " Debut vertex = " << BTh.Number(vA.onbv) ; + pA=vA.onbv; + } + else if (vA.vint == IsVertexOnEdge) + { + pA=vA.onbe->be; + tA=vA.onbe->abcisse; + // cout << " Debut edge = " << BTh.Number(vA.onbv) << " " << tA ; + + } + else + {cerr << "ProjectOnCurve On Vertex " << BTh.Number(vA) << " " << endl; + cerr << " forget call to SetVertexFieldOnBTh" << endl; + MeshError(-1); + } + + if (vB.vint == IsVertexOnVertex) + { + // cout << " Fin vertex = " << BTh.Number(vB.onbv) << endl; + pB=vB.onbv; + } + else if(vB.vint == IsVertexOnEdge) + { + pB=vB.onbe->be; + tB=vB.onbe->abcisse; + // cout << " Fin edge = " << BTh.Number(vB.onbe->be) << " " << tB ; + + } + else + {cerr << "ProjectOnCurve On Vertex " << BTh.Number(vB) << " " << endl; + cerr << " forget call to SetVertexFieldOnBTh" << endl; + MeshError(-1); + } + Edge * e = &BhAB; + assert( pA && pB && e); + // be carefull the back ground edge e is on same geom edge + // of the initiale edge def by the 2 vertex A B; + assert(e>=BTh.edges && e<BTh.edges+BTh.nbe);// Is a background Mesh; +// walk on BTh edge + //assert(0 /* not finish ProjectOnCurve with BackGround Mesh*/); +// 1 first find a back ground edge contening the vertex A +// 2 walk n back gound boundary to find the final vertex B + + +#ifdef DEBUG +// we suppose if the vertex A is on a background edge and +// the abcisse is 0 or 1 when the related point is not +// a end of curve <=> !IsRequiredVertex + if (vA.vint == IsVertexOnEdge) + if (tA<=0) + assert(! (*vA.onbe->be)[0].on->IsRequiredVertex()); + else if (tA>=1) + assert(!(*vA.onbe->be)[1].on->IsRequiredVertex()); +#endif + + if( vA.vint == IsVertexOnEdge) + { // find the start edge + e = vA.onbe->be; + + } + else if (vB.vint == IsVertexOnEdge) + { + theta = 1-theta; + Exchange(tA,tB); + Exchange(pA,pB); + Exchange(pvA,pvB); + Exchange(A,B); + e = vB.onbe->be; + + // cout << " EXCHANGE A et B) " << endl; + } + else + { // do the search by walking + assert(0 /* A FAIRE */); + } + + // find the direction of walking with sens of edge and pA,PB; + R2 AB=B-A; + + Real8 cosE01AB = (( (R2) (*e)[1] - (R2) (*e)[0] ) , AB); + int kkk=0; + int sens = (cosE01AB>0) ? 1 : 0; + + // Real8 l=0; // length of the edge AB + Real8 abscisse = -1; + + for (int cas=0;cas<2;cas++) + {// 2 times algo: + // 1 for computing the length l + // 2 for find the vertex + int iii; + Vertex *v0=pvA,*v1; + Edge *neee,*eee; + Real8 lg =0; // length of the curve + Real8 te0; + // we suppose take the curve's abcisse + // cout << kkk << " e = " << BTh.Number(e) << " v0= " + // << BTh.Number(v0) << " v1 = " << BTh.Number((*e)[sens]) << endl; + for ( eee=e,iii=sens,te0=tA; + eee && ((( void*) eee) != pB) && (( void*) (v1=&((*eee)[iii]))) != pB ; + neee = eee->adj[iii],iii = 1-neee->Intersection(*eee),eee = neee,v0=v1,te0=1-iii ) + { + // cout << kkk << " eee = " << BTh.Number(eee) << " v0= " + // << BTh.Number(v0) << " v1 = " << BTh.Number(v1) << endl; + + assert(kkk++<100); + assert(eee); + Real8 lg0 = lg; + Real8 dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0); + lg += dp; + if (cas && abscisse <= lg) + { // ok we find the geom edge + Real8 sss = (abscisse-lg0)/dp; + Real8 thetab = te0*(1-sss)+ sss*iii; + assert(thetab>=0 && thetab<=1); + BR = VertexOnEdge(&R,eee,thetab); + + // cout << Number(R) << " = " << thetab << " on " << BTh.Number(eee) + // << " = " << R << endl; + + return Gh.ProjectOnCurve(*eee,thetab,R,GR); + + } + } + // we find the end + if (v1 != pvB) + { + if (( void*) v1 == pB) + tB = iii; + + Real8 lg0 = lg; + assert(eee); + v1 = pvB; + Real8 dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0); + lg += dp; + abscisse = lg*theta; + if (abscisse <= lg && abscisse >= lg0 ) // small optimisation we know the lenght because end + { // ok we find the geom edge + Real8 sss = (abscisse-lg0)/dp; + Real8 thetab = te0*(1-sss)+ sss*tB; + assert(thetab>=0 && thetab<=1); + BR = VertexOnEdge(&R,eee,thetab); + + // cout << kkk << " eee = " << BTh.Number(eee) << " v0= " + // << BTh.Number(v0) << " " << te0 + // << " v1 = " << BTh.Number(v1) << " " << tB << endl; + + //out << Number(R) << " Opt = " << thetab << " on " << BTh.Number(eee) + // << " = " << R << endl; + + return Gh.ProjectOnCurve(*eee,thetab,R,GR); + } + } + abscisse = lg*theta; + + } + cerr << " Big Bug" << endl; + MeshError(678); + return 0; // just for the compiler + +} + + +void Triangles::MakeQuadrangles(double costheta) +{ + if (verbosity>2) + cout << " -- MakeQuadrangles costheta = " << costheta << endl; + if (verbosity>5) + cout << " (in) Nb of Quadrilaterals = " << NbOfQuad + << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 + << " Nb of outside triangles = " << NbOutT << endl; + + if (costheta >1) { + if (verbosity>5) + cout << " do nothing costheta >1 "<< endl; + return;} + + + Int4 nbqq = (nbt*3)/2; + DoubleAndInt4 *qq = new DoubleAndInt4[nbqq]; + + Int4 i,ij; + int j; + Int4 k=0; + for (i=0;i<nbt;i++) + for (j=0;j<3;j++) + if ((qq[k].q=triangles[i].QualityQuad(j))>=costheta) + qq[k++].i3j=i*3+j; +// sort qq + HeapSort(qq,k); + + Int4 kk=0; + for (ij=0;ij<k;ij++) + { + // cout << qq[ij].q << " " << endl; + i=qq[ij].i3j/3; + j=(int) (qq[ij].i3j%3); + // optisamition no float computation + if (triangles[i].QualityQuad(j,0) >=costheta) + triangles[i].SetHidden(j),kk++; + } + NbOfQuad = kk; + if (verbosity>2) + { + cout << " (out) Nb of Quadrilaterals = " << NbOfQuad + << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 + << " Nb of outside triangles = " << NbOutT << endl; + } + delete [] qq; +#ifdef DRAWING2 + Draw(); + inquire(); +#endif + +} +/* +Triangles::BThBoundary(Edge e,Real 8) const +{ + // pointeur of the background must be on + // + Edge be = e.on; +} +*/ +int Triangles::SplitElement(int choice) +{ + Direction NoDirOfSearch; + const int withBackground = &BTh != this && &BTh; + if (verbosity>2) + cout << " -- SplitElement " << (choice? " Q->4Q and T->4T " : " Q->4Q or T->3Q " ) << endl;; + if (verbosity>5) + cout << endl << " (in) Nb of Quadrilaterals = " << NbOfQuad + << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 + << " Nb of outside triangles = " << NbOutT << endl; + + ReNumberingTheTriangleBySubDomain(); +#ifdef DRAWING2 + Draw(); + inquire(); +#endif + //int nswap =0; + const Int4 nfortria( choice ? 4 : 6); + if(withBackground) + { + BTh.SetVertexFieldOn(); + SetVertexFieldOnBTh(); + } + else + BTh.SetVertexFieldOn(); + + Int4 newnbt=0,newnbv=0; + Int4 * kedge = 0; + Int4 newNbOfQuad=NbOfQuad; + Int4 * ksplit= 0, * ksplitarray=0; + Int4 kkk=0; + int ret =0; + if (nbvx<nbv+nbe) return 1;// + Triangles * OCurrentTh= CurrentTh; + CurrentTh = this; + // 1) create the new points by spliting the internal edges + // set the + Int4 nbvold = nbv; + Int4 nbtold = nbt; + Int4 NbOutTold = NbOutT; + Int4 NbEdgeOnGeom=0; + Int4 i; + + nbt = nbt - NbOutT; // remove all the the ouside triangles + Int4 nbtsave = nbt; + Triangle * lastT = triangles + nbt; + for (i=0;i<nbe;i++) + if(edges[i].on) NbEdgeOnGeom++; + Int4 newnbe=nbe+nbe; + // Int4 newNbVerticesOnGeomVertex=NbVerticesOnGeomVertex; + Int4 newNbVerticesOnGeomEdge=NbVerticesOnGeomEdge+NbEdgeOnGeom; + // Int4 newNbVertexOnBThVertex=NbVertexOnBThVertex; + Int4 newNbVertexOnBThEdge=withBackground ? NbVertexOnBThEdge+NbEdgeOnGeom:0; + + // do allocation for pointeur to the geometry and background + VertexOnGeom * newVerticesOnGeomEdge = new VertexOnGeom[newNbVerticesOnGeomEdge]; + VertexOnEdge *newVertexOnBThEdge = newNbVertexOnBThEdge ? new VertexOnEdge[newNbVertexOnBThEdge]:0; + if (NbVerticesOnGeomEdge) + memcpy(newVerticesOnGeomEdge,VerticesOnGeomEdge,sizeof(VertexOnGeom)*NbVerticesOnGeomEdge); + if (NbVertexOnBThEdge) + memcpy(newVertexOnBThEdge,VertexOnBThEdge,sizeof(VertexOnEdge)*NbVertexOnBThEdge); + Edge *newedges = new Edge [newnbe]; + // memcpy(newedges,edges,sizeof(Edge)*nbe); + SetOfEdges4 * edge4= new SetOfEdges4(nbe,nbv); +#ifdef DEBUG + for (i=0;i<nbt;i++) + triangles[i].check(); +#endif +#ifdef DRAWING2 + reffecran(); +#endif + Int4 k=nbv; + Int4 kk=0; + Int4 kvb = NbVertexOnBThEdge; + Int4 kvg = NbVerticesOnGeomEdge; + Int4 ie =0; + Edge ** edgesGtoB=0; + if (withBackground) + edgesGtoB= BTh.MakeGeometricalEdgeToEdge(); + Int4 ferr=0; + for (i=0;i<nbe;i++) + newedges[ie].on=0; + + for (i=0;i<nbe;i++) + { + GeometricalEdge *ong = edges[i].on; + + newedges[ie]=edges[i]; + newedges[ie].adj[0]=newedges+(edges[i].adj[0]-edges) ; + newedges[ie].adj[1]=newedges + ie +1; + R2 A = edges[i][0],B = edges[i][1]; + // cout << " ie = " << ie <<" v0 = " << Number(newedges[ie][0]) << endl; + + + kk += (i == edge4->addtrie(Number(edges[i][0]),Number(edges[i][1]))); + if (ong) // a geometrical edges + { + if (withBackground) + { + // walk on back ground mesh + // newVertexOnBThEdge[ibe++] = VertexOnEdge(vertices[k],bedge,absicsseonBedge); + // a faire -- difficile + // the first PB is to now a background edge between the 2 vertices + assert(edgesGtoB); + // cout << " ie = " << ie <<" v0 = " << Number(newedges[ie][0]) << endl; + ong= ProjectOnCurve(*edgesGtoB[Gh.Number(edges[i].on)], + edges[i][0],edges[i][1],0.5,vertices[k], + newVertexOnBThEdge[kvb], + newVerticesOnGeomEdge[kvg++]); + vertices[k].ReferenceNumber= edges[i].ref; + vertices[k].DirOfSearch = NoDirOfSearch; +; + // get the Info on background mesh + Real8 s = newVertexOnBThEdge[kvb]; + Vertex & bv0 = newVertexOnBThEdge[kvb][0]; + Vertex & bv1 = newVertexOnBThEdge[kvb][1]; + // compute the metrix of the new points + vertices[k].m = Metric(1-s,bv0,s,bv1); + kvb++; + // cout << " ie = " << ie <<" v0 = " << Number(newedges[ie][0]) << endl; + } + else + { + ong=Gh.ProjectOnCurve(edges[i], + 0.5,vertices[k],newVerticesOnGeomEdge[kvg++]); + // vertices[k].i = toI2( vertices[k].r); + vertices[k].ReferenceNumber = edges[i].ref; + vertices[k].DirOfSearch = NoDirOfSearch; + vertices[k].m = Metric(0.5,edges[i][0],0.5,edges[i][1]); + } + } + else // straigth line edge --- + { + vertices[k].r = ((R2) edges[i][0] + (R2) edges[i][1] )*0.5; + vertices[k].m = Metric(0.5,edges[i][0],0.5,edges[i][1]); + vertices[k].on = 0; + } + //vertices[k].i = toI2( vertices[k].r); + R2 AB = vertices[k].r; + R2 AA = (A+AB)*0.5; + R2 BB = (AB+B)*0.5; + vertices[k].ReferenceNumber = edges[i].ref; + vertices[k].DirOfSearch = NoDirOfSearch; + + newedges[ie].on = Gh.Contening(AA,ong); + newedges[ie++].v[1]=vertices+k; + + newedges[ie]=edges[i]; + newedges[ie].adj[0]=newedges + ie -1; + newedges[ie].adj[1]=newedges+(edges[i].adj[1]-edges) ; + newedges[ie].on = Gh.Contening(BB,ong); + newedges[ie++].v[0]=vertices+k; + // cout << " ie = " << ie-2 << " vm " << k << " v0 = " << Number(newedges[ie-2][0]) + // << " v1 = " << Number(newedges[ie-1][1]) + // << " ong =" << ong-Gh.edges + // << " on 0 =" << newedges[ie-2].on -Gh.edges << AA + // << " on 1 =" << newedges[ie-1].on -Gh.edges << BB + // << endl; + k++; + } +#ifdef DEBUG + assert(kvb == newNbVertexOnBThEdge); + // verif edge + { Vertex *v0 = vertices, *v1 = vertices+ k; + for (Int4 i=0;i<ie;i++) + { + assert( &newedges[i][0] >= v0 && &newedges[i][0] < v1); + assert( &newedges[i][1] >= v0 && &newedges[i][1] < v1); + } + } +#endif + if (edgesGtoB) delete [] edgesGtoB; + edgesGtoB=0; + + newnbv=k; + newNbVerticesOnGeomEdge=kvg; + if (newnbv> nbvx) goto Error;// bug + + nbv = k; + + + kedge = new Int4[3*nbt+1]; + ksplitarray = new Int4[nbt+1]; + ksplit = ksplitarray +1; // because ksplit[-1] == ksplitarray[0] + + for (i=0;i<3*nbt;i++) + kedge[i]=-1; + + // + + for (i=0;i<nbt;i++) + { + + Triangle & t = triangles[i]; + assert(t.link); + for(int j=0;j<3;j++) + { + const TriangleAdjacent ta = t.Adj(j); + const Triangle & tt = ta; + if (&tt >= lastT) + t.SetAdj2(j,0,0);// unset adj + const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]]; + const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]]; + Int4 ke =edge4->findtrie(Number(v0),Number(v1)); + if (ke>0) + { + Int4 ii = Number(tt); + int jj = ta; + Int4 ks = ke + nbvold; + kedge[3*i+j] = ks; + if (ii<nbt) // good triangle + kedge[3*ii+jj] = ks; + Vertex &A=vertices[ks]; + Real8 aa,bb,cc,dd; + if ((dd=Area2(v0.r,v1.r,A.r)) >=0) + { // warning PB roundoff error + if (t.link && ( (aa=Area2( A.r , t[1].r , t[2].r )) < 0.0 + || (bb=Area2( t[0].r , A.r , t[2].r )) < 0.0 + || (cc=Area2( t[0].r , t[1].r , A.r )) < 0.0)) + ferr++, cerr << " Error : " << ke + nbvold << " not in triangle " + << i << " In=" << !!t.link + << " " << aa << " " << bb << " " << cc << " " << dd << endl; + + } + + else + { + if (tt.link && ( (aa=Area2( A.r , tt[1].r , tt[2].r )) < 0 + || (bb=Area2( tt[0].r , A.r , tt[2].r )) < 0 + || (cc=Area2( tt[0].r , tt[1].r , A.r )) < 0)) + ferr++, cerr << " Warning : " << ke + nbvold << " not in triangle " << ii + << " In=" << !!tt.link + << " " << aa << " " << bb << " " << cc << " " << dd << endl; + + } + + } + } + } + if(ferr) + { + cerr << " Number of triangles with P2 interpolation Probleme " << ferr << endl;; + MeshError(9); + } + + for (i=0;i<nbt;i++) + { + ksplit[i]=1; // no split by default + const Triangle & t = triangles[ i]; + // cout << " Triangle " << i << " " << t << !!t.link << ":: " ; + int nbsplitedge =0; + int nbinvisible =0; + int invisibleedge=0; + int kkk[3]; + for (int j=0;j<3;j++) + { + if (t.Hidden(j)) invisibleedge=j,nbinvisible++; + + const TriangleAdjacent ta = t.Adj(j); + const Triangle & tt = ta; + + + const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]]; + const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]]; + // cout << " ke = " << kedge[3*i+j] << " " << Number(v0) << " " << Number(v1) << "/ "; + if ( kedge[3*i+j] < 0) + { + Int4 ke =edge4->findtrie(Number(v0),Number(v1)); + // cout << ":" << ke << "," << !!t.link << " " << &tt ; + if (ke<0) // new + { + if (&tt) // internal triangles all the boundary + { // new internal edges + Int4 ii = Number(tt); + int jj = ta; + + kedge[3*i+j]=k;// save the vertex number + kedge[3*ii+jj]=k; + if (k<nbvx) + { + vertices[k].r = ((R2) v0+(R2) v1 )/2; + //vertices[k].i = toI2( vertices[k].r); + vertices[k].ReferenceNumber=0; + vertices[k].DirOfSearch =NoDirOfSearch; + vertices[k].m = Metric(0.5,v0,0.5,v1); + } + k++; + kkk[nbsplitedge++]=j; + } // tt + else + cerr <<endl << " Bug " <<i<< " " << j << " t=" << t << endl; + + } // ke<0 + else + { // ke >=0 + kedge[3*i+j]=nbvold+ke; + kkk[nbsplitedge++]=j;// previously splited + } + } + else + kkk[nbsplitedge++]=j;// previously splited + + } + assert (nbinvisible<2); + // cout << " " << nbinvisible << " " << nbsplitedge << endl; + switch (nbsplitedge) { + case 0: ksplit[i]=10; newnbt++; break; // nosplit + case 1: ksplit[i]=20+kkk[0];newnbt += 2; break; // split in 2 + case 2: ksplit[i]=30+3-kkk[0]-kkk[1];newnbt += 3; break; // split in 3 + case 3: + if (nbinvisible) ksplit[i]=40+invisibleedge,newnbt += 4; + else ksplit[i]=10*nfortria,newnbt+=nfortria; + break; + } + assert(ksplit[i]>=40); + } + // now do the element split + newNbOfQuad = 4*NbOfQuad; + nbv = k; +#ifdef DRAWING2 + inquire(); +#endif +// cout << " Nbv = " << nbv << endl; + kkk = nbt; + ksplit[-1] = nbt; + // look on old true triangles + + for (i=0;i<nbtsave;i++) + { + // cout << "Triangle " << i << " " << ksplit[i] << ":" << triangles[i] + // << " ----------------------------------------------- " <<endl; + // Triangle * tc=0; + int nbmkadj=0; + Int4 mkadj [100]; + mkadj[0]=i; + Int4 kk=ksplit[i]/10; + int ke=(int) (ksplit[i]%10); + assert(kk<7 && kk >0); + + // def the numbering k (edge) i vertex + int k0 = ke; + int k1 = NextEdge[k0]; + int k2 = PreviousEdge[k0]; + int i0 = OppositeVertex[k0]; + int i1 = OppositeVertex[k1]; + int i2 = OppositeVertex[k2]; + + Triangle &t0=triangles[i]; + Vertex * v0=t0(i0); + Vertex * v1=t0(i1); + Vertex * v2=t0(i2); + + // cout << "nbmkadj " << nbmkadj << " it=" << i <<endl; + assert(nbmkadj< 10); + // -------------------------- + TriangleAdjacent ta0(t0.Adj(i0)),ta1(t0.Adj(i1)),ta2(t0.Adj(i2)); + // save the flag Hidden + int hid[]={t0.Hidden(0),t0.Hidden(1),t0.Hidden(2)}; + // un set all adj -- save Hidden flag -- + t0.SetAdj2(0,0,hid[0]); + t0.SetAdj2(1,0,hid[1]); + t0.SetAdj2(2,0,hid[2]); + // -- remake + switch (kk) { + case 1: break;// nothing + case 2: // + { + Triangle &t1=triangles[kkk++]; + t1=t0; + assert (kedge[3*i+i0]>=0); + Vertex * v3 = vertices + kedge[3*i+k0]; + + t0(i2) = v3; + t1(i1) = v3; + t0.SetAllFlag(k2,0); + t1.SetAllFlag(k1,0); + } + break; + case 3: // + { + Triangle &t1=triangles[kkk++]; + Triangle &t2=triangles[kkk++]; + t2=t1=t0; + assert (kedge[3*i+k1]>=0); + assert (kedge[3*i+k2]>=0); + + Vertex * v01 = vertices + kedge[3*i+k2]; + Vertex * v02 = vertices + kedge[3*i+k1]; + t0(i1) = v01; + t0(i2) = v02; + t1(i2) = v02; + t1(i0) = v01; + t2(i0) = v02; + t0.SetAllFlag(k0,0); + t1.SetAllFlag(k1,0); + t1.SetAllFlag(k0,0); + t2.SetAllFlag(k2,0); + } + break; + case 4: // + case 6: // split in 4 + { + Triangle &t1=triangles[kkk++]; + Triangle &t2=triangles[kkk++]; + Triangle &t3=triangles[kkk++]; + t3=t2=t1=t0; + assert(kedge[3*i+k0] >=0 && kedge[3*i+k1] >=0 && kedge[3*i+k2] >=0); + Vertex * v12 = vertices + kedge[3*i+k0]; + Vertex * v02 = vertices + kedge[3*i+k1]; + Vertex * v01 = vertices + kedge[3*i+k2]; + // cout << Number(t0(i0)) << " " << Number(t0(i1)) + // << " " << Number(t0(i2)) + // << " " << kedge[3*i+k0] + // << " " << kedge[3*i+k1] + // << " " << kedge[3*i+k2] << endl; + t0(i1) = v01; + t0(i2) = v02; + t0.SetAllFlag(k0,hid[k0]); + + t1(i0) = v01; + t1(i2) = v12; + t0.SetAllFlag(k1,hid[k1]); + + t2(i0) = v02; + t2(i1) = v12; + t2.SetAllFlag(k2,hid[k2]); + + t3(i0) = v12; + t3(i1) = v02; + t3(i2) = v01; + + t3.SetAllFlag(0,hid[0]); + t3.SetAllFlag(1,hid[1]); + t3.SetAllFlag(2,hid[2]); + + if ( kk == 6) + { + + Triangle &t4=triangles[kkk++]; + Triangle &t5=triangles[kkk++]; + + t4 = t3; + t5 = t3; + + t0.SetHidden(k0); + t1.SetHidden(k1); + t2.SetHidden(k2); + t3.SetHidden(0); + t4.SetHidden(1); + t5.SetHidden(2); + + if (nbv < nbvx ) + { + vertices[nbv].r = ((R2) *v01 + (R2) *v12 + (R2) *v02 ) / 3.0; + vertices[nbv].ReferenceNumber =0; + vertices[nbv].DirOfSearch =NoDirOfSearch; + //vertices[nbv].i = toI2(vertices[nbv].r); + Real8 a3[]={1./3.,1./3.,1./3.}; + vertices[nbv].m = Metric(a3,v0->m,v1->m,v2->m); + Vertex * vc = vertices +nbv++; + t3(i0) = vc; + t4(i1) = vc; + t5(i2) = vc; + + } + else + goto Error; + } + + } + break; + } + + // cout << " -- " << i << " " << nbmkadj << " " << kkk << " " << tc << endl; + // t0.SetDetf(); + // save all the new triangles + mkadj[nbmkadj++]=i; + Int4 jj; + if (t0.link) + for (jj=nbt;jj<kkk;jj++) + { + triangles[jj].link=t0.link; + t0.link= triangles+jj; + mkadj[nbmkadj++]=jj; + // triangles[jj].SetDet(); + } + // cout << " -- " << i << " " << nbmkadj << endl; + assert(nbmkadj<=13);// 13 = 6 + 4 + 3 + + if (kk==6) newNbOfQuad+=3; + // triangles[i].Draw(); + + for (jj=ksplit[i-1];jj<kkk;jj++) + // triangles[jj].SetDet(); + // triangles[jj].Draw(); + + + + nbt = kkk; + ksplit[i]= nbt; // save last adresse of the new triangles + kkk = nbt; + + } + +// cout << " nv = " << nbv << " nbt = " << nbt << endl; + for (i=0;i<nbv;i++) + vertices[i].m = vertices[i].m*2.; + // + if(withBackground) + for (i=0;i<BTh.nbv;i++) + BTh.vertices[i].m = BTh.vertices[i].m*2.; +#ifdef DRAWING2 + Draw(); + inquire(); +#endif + + + ret = 2; + if (nbt>= nbtx) goto Error; // bug + if (nbv>= nbvx) goto Error; // bug + // generation of the new triangles + + SetIntCoor("In SplitElement"); + + ReMakeTriangleContainingTheVertex(); + if(withBackground) + BTh.ReMakeTriangleContainingTheVertex(); + + delete [] edges; + edges = newedges; + nbe = newnbe; + NbOfQuad = newNbOfQuad; + + for (i=0;i<NbSubDomains;i++) + { + Int4 k = subdomains[i].edge- edges; + subdomains[i].edge = edges+2*k; // spilt all edge in 2 + } + + if (ksplitarray) delete [] ksplitarray; + if (kedge) delete [] kedge; + if (edge4) delete edge4; + if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge; + VerticesOnGeomEdge= newVerticesOnGeomEdge; + if(VertexOnBThEdge) delete [] VertexOnBThEdge; + VertexOnBThEdge = newVertexOnBThEdge; + NbVerticesOnGeomEdge = newNbVerticesOnGeomEdge; + NbVertexOnBThEdge=newNbVertexOnBThEdge; + // ReMakeTriangleContainingTheVertex(); + + FillHoleInMesh(); + +#ifdef DEBUG + for (i=0;i<nbt;i++) + triangles[i].check(); +#endif + + if (verbosity>2) + cout << " (out) Nb of Quadrilaterals = " << NbOfQuad + << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 + << " Nb of outside triangles = " << NbOutT << endl; + + CurrentTh=OCurrentTh; + return 0; //ok + + Error: + nbv = nbvold; + nbt = nbtold; + NbOutT = NbOutTold; + // cleaning memory --- + delete newedges; + if (ksplitarray) delete [] ksplitarray; + if (kedge) delete [] kedge; + if (newVerticesOnGeomEdge) delete [] newVerticesOnGeomEdge; + if (edge4) delete edge4; + if(newVertexOnBThEdge) delete [] newVertexOnBThEdge; + + + CurrentTh= OCurrentTh; + return ret; // ok +} + +} // end of namespcae bamg diff --git a/contrib/bamg/bamglib/MeshRead.cpp b/contrib/bamg/bamglib/MeshRead.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ade1afb6c17a5781d981c2e72f76561164f55b9b --- /dev/null +++ b/contrib/bamg/bamglib/MeshRead.cpp @@ -0,0 +1,1227 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <time.h> + +#include "Meshio.h" +#include "Mesh2.h" +#include "QuadTree.h" +#include "SetOfE4.h" +#ifdef __MWERKS__ +#pragma optimization_level 2 +//#pragma inline_depth 1 +#endif + +#ifdef DRAWING1 + extern bool withrgraphique ; +#endif + +namespace bamg { + +static const Direction NoDirOfSearch=Direction(); + +void Triangles::Read(MeshIstream & f_in,int Version,Real8 cutoffradian) +{ + Real8 hmin = HUGE_VAL;// the infinie value + // Real8 MaximalAngleOfCorner = 10*Pi/180;// + Int4 i; + Int4 dim=0; + Int4 hvertices =0; + Int4 ifgeom=0; + Metric M1(1); + if (verbosity>1) + cout << " -- ReadMesh " << f_in.CurrentFile << " Version = " << Version << endl; + int field=0; + int showfield=0; + while (f_in.cm()) + { + field=0; + char fieldname[256]; + if(f_in.eof()) break; + f_in.cm() >> fieldname ;; + if(f_in.eof()) break; + f_in.err() ; + if(verbosity>9) + cout << " " << fieldname << endl; + if (!strcmp(fieldname,"MeshVersionFormatted") ) + f_in >> Version ; + else if(!strcmp(fieldname,"End")) + break; + else if (!strcmp(fieldname,"Dimension")) + { + f_in >> dim ; + assert(dim ==2); + } + else if (!strcmp(fieldname,"Geometry")) + { + char * fgeom ; + f_in >> fgeom; + // if (cutoffradian>=0) => bug if change edit the file geometry + // Gh.MaximalAngleOfCorner = cutoffradian; + if (strlen(fgeom)) + Gh.ReadGeometry(fgeom); + else + { + // include geometry + f_in.cm(); + Gh.ReadGeometry(f_in,fgeom); + } + + Gh.AfterRead(); + ifgeom=1; + delete [] fgeom; + } + else if (!strcmp(fieldname,"Identifier")) + { + if (identity) delete [] identity; + f_in >> identity; + } + else if (!strcmp(fieldname,"hVertices")) + { hvertices =1; + Real4 h; + for (i=0;i< nbv;i++) { + f_in >> h ; + vertices[i].m = Metric(h);} + } + else if (!strcmp(fieldname,"Vertices")) + { + assert(dim ==2); + f_in >> nbv ; + if(verbosity>3) + cout << " Nb of Vertices = " << nbv << endl; + nbvx=nbv; + vertices=new Vertex[nbvx]; + assert(vertices); + ordre=new (Vertex* [nbvx]); + assert(ordre); + + nbiv = nbv; + for (i=0;i<nbv;i++) { + f_in >> + vertices[i].r.x >> + vertices[i].r.y >> + vertices[i].ReferenceNumber ; + vertices[i].DirOfSearch =NoDirOfSearch; + vertices[i].m=M1; + vertices[i].color =0;} + nbtx = 2*nbv-2; // for filling The Holes and quadrilaterals + triangles =new Triangle[nbtx]; + assert(triangles); + nbt =0; + } + else if (!strcmp(fieldname,"Triangles")) + { + if (dim !=2) + cerr << "ReadMesh: Dimension <> 2" <<endl , f_in.ShowIoErr(0); + if(! vertices || !triangles || !nbv ) + cerr << "ReadMesh:Triangles before Vertices" <<endl, + f_in.ShowIoErr(0); + int NbOfTria; + f_in >> NbOfTria ; + if(verbosity>3) + cout << " NbOfTria = " << NbOfTria << endl; + if (nbt+NbOfTria >= nbtx) + cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria = " + << nbt + NbOfTria<<" < 2*nbv-2 =" << nbtx << endl, + f_in.ShowIoErr(0); + // begintria = nbt; + for (i=0;i<NbOfTria;i++) + { + Int4 i1,i2,i3,iref; + Triangle & t = triangles[nbt++]; + f_in >> i1 >> i2 >> i3 >> iref ; + t = Triangle(this,i1-1,i2-1,i3-1); + t.color=iref; + } + // endtria=nbt; + } + else if (!strcmp(fieldname,"Quadrilaterals")) + { + + if (dim !=2) + cerr << "ReadMesh: Dimension <> 2" <<endl , f_in.ShowIoErr(0); + if(! vertices || !triangles || !nbv ) + cerr << "ReadMesh:Quadrilaterals before Vertices" <<endl, + f_in.ShowIoErr(0); + f_in >> NbOfQuad ; + if(verbosity>3) + cout << " NbOfQuad= " << NbOfQuad << endl; + if (nbt+2*NbOfQuad >= nbtx) + cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria = " + << nbt + 2*NbOfQuad <<" < 2*nbv-2 =" << nbtx << endl, + f_in.ShowIoErr(0); + // beginquad=nbt; + for (i=0;i<NbOfQuad;i++) + { + Int4 i1,i2,i3,i4,iref; + Triangle & t1 = triangles[nbt++]; + Triangle & t2 = triangles[nbt++]; + f_in >> i1 >> i2 >> i3 >> i4 >> iref ; + t1 = Triangle(this,i1-1,i2-1,i3-1); + t1.color=iref; + t2 = Triangle(this,i3-1,i4-1,i1-1); + t2.color=iref; + t1.SetHidden(OppositeEdge[1]); // two time because the adj was not created + t2.SetHidden(OppositeEdge[1]); + } + // endquad=nbt; + } + else if (!strcmp(fieldname,"VertexOnGeometricVertex")) + { + f_in >> NbVerticesOnGeomVertex ; + if(verbosity>5) + cout << " NbVerticesOnGeomVertex = " << NbVerticesOnGeomVertex << endl + << " Gh.vertices " << Gh.vertices << endl; + if( NbVerticesOnGeomVertex) + { + VerticesOnGeomVertex= new VertexOnGeom[NbVerticesOnGeomVertex] ; + if(verbosity>7) + cout << " VerticesOnGeomVertex = " << VerticesOnGeomVertex << endl + << " Gh.vertices " << Gh.vertices << endl; + assert(VerticesOnGeomVertex); + for (Int4 i0=0;i0<NbVerticesOnGeomVertex;i0++) + { + Int4 i1,i2; + //VertexOnGeom & v =VerticesOnGeomVertex[i0]; + f_in >> i1 >> i2 ; + VerticesOnGeomVertex[i0]=VertexOnGeom(vertices[i1-1],Gh.vertices[i2-1]); + } + } + } + else if (!strcmp(fieldname,"VertexOnGeometricEdge")) + { + f_in >> NbVerticesOnGeomEdge ; + if(verbosity>3) + cout << " NbVerticesOnGeomEdge = " << NbVerticesOnGeomEdge << endl; + if(NbVerticesOnGeomEdge) + { + VerticesOnGeomEdge= new VertexOnGeom[NbVerticesOnGeomEdge] ; + assert(VerticesOnGeomEdge); + for (Int4 i0=0;i0<NbVerticesOnGeomEdge;i0++) + { + Int4 i1,i2; + Real8 s; + //VertexOnGeom & v =VerticesOnGeomVertex[i0]; + f_in >> i1 >> i2 >> s; + VerticesOnGeomEdge[i0]=VertexOnGeom(vertices[i1-1],Gh.edges[i2-1],s); + } + } + } + else if (!strcmp(fieldname,"Edges")) + { + Int4 i,j, i1,i2; + f_in >> nbe ; + edges = new Edge[nbe]; + if(verbosity>5) + cout << " Record Edges: Nb of Edge " << nbe << " edges " << edges << endl; + assert(edges); + Real4 *len =0; + if (!hvertices) + { + len = new Real4[nbv]; + for(i=0;i<nbv;i++) + len[i]=0; + } + for (i=0;i<nbe;i++) + { + f_in >> i1 >> i2 >> edges[i].ref ; + + assert(i1 >0 && i2 >0); + assert(i1 <= nbv && i2 <= nbv); + i1--; + i2--; + edges[i].v[0]= vertices +i1; + edges[i].v[1]= vertices +i2; + edges[i].adj[0]=0; + edges[i].adj[1]=0; + + R2 x12 = vertices[i2].r-vertices[i1].r; + Real8 l12=sqrt( (x12,x12)); + if (!hvertices) { + vertices[i1].color++; + vertices[i2].color++; + len[i1]+= l12; + len[i2] += l12;} + hmin = Min(hmin,l12); + } + // definition the default of the given mesh size + if (!hvertices) + { + for (i=0;i<nbv;i++) + if (vertices[i].color > 0) + vertices[i].m= Metric(len[i] /(Real4) vertices[i].color); + else + vertices[i].m= Metric(hmin); + delete [] len; + } + if(verbosity>5) + cout << " hmin " << hmin << endl; + // construction of edges[].adj + for (i=0;i<nbv;i++) + vertices[i].color = (vertices[i].color ==2) ? -1 : -2; + for (i=0;i<nbe;i++) + for (j=0;j<2;j++) + { + Vertex *v=edges[i].v[j]; + Int4 i0=v->color,j0; + if(i0==-1) + v->color=i*2+j; + else if (i0>=0) {// i and i0 edge are adjacent by the vertex v + j0 = i0%2; + i0 = i0/2; + assert( v == edges[i0 ].v[j0]); + edges[i ].adj[ j ] =edges +i0; + edges[i0].adj[ j0] =edges +i ; + assert(edges[i0].v[j0] == v); + // if(verbosity>8) + // cout << " edges adj " << i0 << " "<< j0 << " <--> " << i << " " << j << endl; + v->color = -3;} + } + + } + +/* ne peut pas marche car il n'y a pas de flag dans les aretes du maillages + else if (!strcmp(fieldname,"RequiredEdges")) + { + int i,j,n; + f_in >> n ; + + for (i=0;i<n;i++) { + f_in >> j ; + assert( j <= nbe ); + assert( j > 0 ); + j--; + edges[j].SetRequired(); } + } +*/ + else if (!strcmp(fieldname,"EdgeOnGeometricEdge")) + { + assert(edges); + int i1,i2,i,j; + f_in >> i2 ; + if(verbosity>3) + cout << " Record EdgeOnGeometricEdge: Nb " << i2 <<endl; + for (i1=0;i1<i2;i1++) + { + f_in >> i >> j ; + if(!(i>0 && j >0 && i <= nbe && j <= Gh.nbe)) + { + cerr << " Record EdgeOnGeometricEdge i=" << i << " j = " << j; + cerr << " nbe = " << nbe << " Gh.nbe = " << Gh.nbe << endl; + cerr << " We must have : (i>0 && j >0 && i <= nbe && j <= Gh.nbe) "; + cerr << " Fatal error in file " << name << " line " << f_in.LineNumber << endl; + MeshError(1); + } + + + edges[i-1].on = Gh.edges + j-1; + } + // cout << "end EdgeOnGeometricEdge" << endl; + } + else if (!strcmp(fieldname,"SubDomain") || !strcmp(fieldname,"SubDomainFromMesh") ) + { + + f_in >> NbSubDomains ; + subdomains = new SubDomain [ NbSubDomains ]; + for (i=0;i< NbSubDomains;i++) + { Int4 i3,head,sens; + f_in >> i3 >> head >> sens >> subdomains[i].ref ; + assert (i3==3); + head --; + assert(head < nbt && head >=0); + subdomains[i].head = triangles+head; + } + } + else + { // unkown field + field = ++showfield; + if(showfield==1) // just to show one time + if (verbosity>5) + cout << " Warning we skip the field " << fieldname << " at line " << f_in.LineNumber << endl; + } + showfield=field; // just to show one time + } + + if (ifgeom==0) + { + if (verbosity) + cout << " ## Warning: Mesh without geometry we construct a geometry (theta =" + << cutoffradian*180/Pi << " degres )" << endl; + ConsGeometry(cutoffradian); + Gh.AfterRead(); + } +} + + + + +void Triangles::Read_am_fmt(MeshIstream & f_in) +{ + Metric M1(1); + + if (verbosity>1) + cout << " -- ReadMesh .am_fmt file " << f_in.CurrentFile << endl; + + Int4 i; + f_in.cm() >> nbv >> nbt ; + if (verbosity>3) + cout << " nbv = " << nbv << " nbt = " << nbt << endl; + f_in.eol() ;// + nbvx = nbv; + nbtx = 2*nbv-2; // for filling The Holes and quadrilaterals + triangles =new Triangle[nbtx]; + assert(triangles); + vertices=new Vertex[nbvx]; + ordre=new (Vertex* [nbvx]); + + for ( i=0;i<nbt;i++) + { + Int4 i1,i2,i3; + f_in >> i1 >> i2 >> i3 ; + triangles[i] = Triangle(this,i1-1,i2-1,i3-1); + } + f_in.eol() ;// + + for ( i=0;i<nbv;i++) + f_in >> vertices[i].r.x >> vertices[i].r.y, + vertices[i].m = M1,vertices[i].DirOfSearch =NoDirOfSearch; + + f_in.eol() ;// + + for ( i=0;i<nbt;i++) + f_in >> triangles[i].color; + f_in.eol() ;// + + for ( i=0;i<nbv;i++) + f_in >> vertices[i].ReferenceNumber; + + +} + +//////////////////////// + +void Triangles::Read_am(MeshIstream &ff) +{ + if (verbosity>1) + cout << " -- ReadMesh .am_fmt file " << ff.CurrentFile << endl; + Metric M1(1); + + IFortranUnFormattedFile f_in(ff); + + Int4 l=f_in.Record(); + assert(l==2*sizeof(Int4)); + f_in >> nbv >> nbt ; + l=f_in.Record(); + assert((size_t) l==nbt*sizeof(long)*4 + nbv*(2*sizeof(float)+sizeof(long))); + if (verbosity>3) + cout << " nbv = " << nbv << " nbt = " << nbt << endl; + + nbvx = nbv; + nbtx = 2*nbv-2; // for filling The Holes and quadrilaterals + triangles =new Triangle[nbtx]; + assert(triangles); + vertices=new Vertex[nbvx]; + ordre=new (Vertex* [nbvx]); + + + Int4 i; + for ( i=0;i<nbt;i++) { + long i1,i2,i3; + f_in >> i1 >> i2 >> i3 ; + triangles[i] = Triangle(this,i1-1,i2-1,i3-1); } + + for ( i=0;i<nbv;i++) { + float x,y; + f_in >> x >> y; + vertices[i].r.x =x; + vertices[i].r.y=y; + vertices[i].m=M1;} + + for ( i=0;i<nbt;i++) { + long i; + f_in >> i; + triangles[i].color=i;} + + for ( i=0;i<nbv;i++) { + long i; + f_in >> i; + vertices[i].ReferenceNumber=i;} +} + +////////////////////////////////// + +void Triangles::Read_nopo(MeshIstream & ff) +{ + + if (verbosity>1) + cout << " -- ReadMesh .nopo file " << ff.CurrentFile << endl; + IFortranUnFormattedFile f_in(ff); + + + Int4 l,i,j; + l=f_in.Record(); + l=f_in.Record(); + f_in >> i; + assert(i==32); + Int4 niveau,netat,ntacm; + + char titre[80+1], date[2*4+1], nomcre[6*4+1], typesd[5]; + f_in.read4(titre,20); + f_in.read4(date,2); + f_in.read4(nomcre,6); + f_in.read4(typesd,1); + + + f_in >> niveau>>netat>>ntacm; + if (strcmp("NOPO",typesd)) + { + cout << " where in record " << f_in.where() << " " << strcmp("NOPO",typesd) << endl; + cerr << " not a nopo file but `" << typesd <<"`"<< " len = " << strlen(typesd) << endl; + cerr << (int) typesd[0] << (int) typesd[1] << (int) typesd[2] << (int) typesd[3] << (int) typesd[4] << endl; + cout << " nomcre :" << nomcre << endl; + cout << " date :" << date << endl; + cout << " titre :" << titre<< endl; + MeshError(112); + } + if(verbosity>2) + cout << " nb de tableau associe : " << ntacm << " niveau =" << niveau << endl; + + for (i=0;i<ntacm;i++) + f_in.Record(); + + f_in.Record(); + f_in >> l; + assert(l == 27); + Int4 nop2[27]; + for (i=0;i<27;i++) + f_in >> nop2[i]; + Int4 ndim = nop2[0]; + Int4 ncopnp = nop2[3]; + Int4 ne = nop2[4]; + Int4 ntria = nop2[7]; + Int4 nquad = nop2[8]; + Int4 np = nop2[21]; + // Int4 nef = nop2[13]; + Metric M1(1); + if(verbosity>2) + cout << " ndim = " << ndim << " ncopnp= " << ncopnp << " ne = " << ne + << " ntri = " << ntria << " nquad = " << nquad << " np = " << np << endl; + nbv = np; + nbt = 2*nquad + ntria; + if (ne != nquad+ntria || ndim !=2 || ncopnp != 1 ) + { + cerr << " not only tria & quad in nopo mesh on dim != 2 ou ncopnp != 1 " << endl; + MeshError(113); + } + if( nop2[24]>=0) f_in.Record(); + NbOfQuad = nquad; + nbvx = nbv; + nbtx = 2*nbv-2; // for filling The Holes and quadrilaterals + triangles =new Triangle[nbtx]; + assert(triangles); + vertices=new Vertex[nbvx]; + ordre=new (Vertex* [nbvx]); + + + f_in >> l; + + if(verbosity>9) + cout << " Read cnop4 nb of float " << l << endl; + + assert(l==2*np); + for (i=0;i<np;i++) + { float x,y; + f_in >> x>> y; + vertices[i].r.x=x; + vertices[i].r.y=y; + vertices[i].m=M1; + vertices[i].DirOfSearch =NoDirOfSearch; + + } + f_in.Record(); + // lecture de nop5 bonjour les degats + f_in >> l; + if(verbosity>9) + cout << " Read nop5 nb of int4 " << l << endl; + Int4 k=0; + Int4 nbe4 = 3*ntria + 4*nquad; + // cout << " nbv = " << nbv << " nbe4 " << nbe4 << endl; + SetOfEdges4 * edge4= new SetOfEdges4(nbe4,nbv); + Int4 * refe = new Int4[nbe4]; + Int4 kr =0; + for (i=0;i<ne;i++) + { + // Int4 ng[4]={0,0,0,0}; + Int4 np[4],rv[4],re[4]; + Int4 ncge,nmae,ndsde,npo; + f_in >> ncge >> nmae >> ndsde >> npo ; + //cout << " element " << i << " " << ncge << " " + // << nmae <<" " << npo << endl; + if (ncge != 3 && ncge != 4) + { + cerr << " read nopo type element[" << i << "] =" + << ncge << " not 3 or 4 " << endl; + MeshError(115); + } + if (npo != 3 && npo != 4) + { + cerr << " read nopo element[" << i << "] npo = " + << npo << " not 3 or 4 " << endl; + MeshError(115); + } + + for( j=0;j<npo;j++) + {f_in >>np[j];np[j]--;} + + if (ncopnp !=1) + { + f_in >> npo; + if (npo != 3 || npo != 4) + { + cerr << " read nopo type element[" << i << "]= " + << ncge << " not 3 or 4 " << endl; + MeshError(115); + } + + for(j=0;j<npo;j++) + {f_in >>np[j];np[j]--;} + + } + if (nmae>0) + { + Int4 ining; // no ref + + f_in>>ining; + if (ining==1) + MeshError(116); + if (ining==2) + for (j=0;j<npo;j++) + f_in >>re[j]; + for (j=0;j<npo;j++) + f_in >>rv[j]; + + + // set the ref on vertex and the shift np of -1 to start at 0 + for (j=0;j<npo;j++) + vertices[np[j]].ReferenceNumber = rv[j]; + + if (ining==2) + for (j=0;j<npo;j++) + if (re[j]) + { + kr++; + Int4 i0 = np[j]; + Int4 i1 = np[(j+1)%npo]; + // cout << kr << " ref edge " << i0 << " " << i1 << " " << re[j] << endl; + refe[edge4->addtrie(i0,i1)]=re[j]; + } + } + + if (npo==3) + { // triangles + triangles[k] = Triangle(this,np[0],np[1],np[2]); + triangles[k].color = ndsde; + k++; + } + else if (npo==4) + { // quad + Triangle & t1 = triangles[k++]; + Triangle & t2 = triangles[k++]; + t1 = Triangle(this,np[0],np[1],np[2]); + t2 = Triangle(this,np[2],np[3],np[0]); + t1.SetHidden(OppositeEdge[1]); // two time because the adj was not created + t2.SetHidden(OppositeEdge[1]); + t1.color = ndsde; + t2.color = ndsde; + } + else + { + cerr << " read nopo type element =" << npo << " not 3 or 4 " << endl; + MeshError(114); + } + + + } + // cout << k << " == " << nbt << endl; + assert(k==nbt); + + nbe = edge4->nb(); + if (nbe) + { + if (verbosity>7) + cout << " Nb of ref edges = " << nbe << endl; + if (edges) + delete [] edges; + edges = new Edge[nbe]; + for (i=0;i<nbe;i++) + { + edges[i].v[0] = vertices + edge4->i(i); + edges[i].v[1] = vertices + edge4->j(i); + edges[i].ref = refe[i]; + // cout << i << " " << edge4->i(i) << " " << edge4->j(i) << endl; + } + if (verbosity>7) + cout << " Number of reference edge in the mesh = " << nbe << endl; + } + delete [] refe; + delete edge4; +} + void Triangles::Read_ftq(MeshIstream & f_in) +{ + // + if (verbosity>1) + cout << " -- ReadMesh .ftq file " << f_in.CurrentFile << endl; + + Int4 i,ne,nt,nq; + f_in.cm() >> nbv >> ne >> nt >> nq ; + if (verbosity>3) + cout << " nbv = " << nbv << " nbtra = " << nt << " nbquad = " << nq << endl; + nbt = nt+2*nq; + + + nbvx = nbv; + nbtx = 2*nbv-2; // for filling The Holes and quadrilaterals + triangles =new Triangle[nbtx]; + assert(triangles); + vertices=new Vertex[nbvx]; + ordre=new (Vertex* [nbvx]); + Int4 k=0; + + for ( i=0;i<ne;i++) + { + long ii,i1,i2,i3,i4,ref; + f_in >> ii; + if (ii==3) + { // triangles + f_in >> i1>> i2 >> i3 >> ref ; + triangles[k] = Triangle(this,i1-1,i2-1,i3-1); + triangles[k++].color = ref; + } + else if (ii==4) + { // quad + f_in >> i1>> i2 >> i3 >> i4 >> ref ; + Triangle & t1 = triangles[k++]; + Triangle & t2 = triangles[k++]; + t1 = Triangle(this,i1-1,i2-1,i3-1); + t1.color=ref; + t2 = Triangle(this,i3-1,i4-1,i1-1); + t2.color=ref; + t1.SetHidden(OppositeEdge[1]); // two time because the adj was not created + t2.SetHidden(OppositeEdge[1]); + } + else + { + cout << " read ftq type element =" << ii << " not 3 or 4 " << endl; + MeshError(111); + } + } + assert(k==nbt); + Metric M1(1); + for ( i=0;i<nbv;i++) + { + f_in >> vertices[i].r.x >> vertices[i].r.y >> vertices[i].ReferenceNumber; + vertices[i].DirOfSearch =NoDirOfSearch; + vertices[i].m = M1; + + } +} + +/////////////////////////////////////////////// + +void Triangles::Read_msh(MeshIstream &f_in) +{ + Metric M1(1.); + if (verbosity>1) + cout << " -- ReadMesh .msh file " << f_in.CurrentFile << endl; + + Int4 i; + f_in.cm() >> nbv >> nbt ; + while (f_in.in.peek()==' ') + f_in.in.get(); + if(isdigit(f_in.in.peek())) + f_in >> nbe; + if (verbosity>3) + cout << " nbv = " << nbv << " nbt = " << nbt << " nbe = " << nbe << endl; + nbvx = nbv; + nbtx = 2*nbv-2; // for filling The Holes and quadrilaterals + triangles =new Triangle[nbtx]; + assert(triangles); + vertices=new Vertex[nbvx]; + ordre=new (Vertex* [nbvx]); + edges = new Edge[nbe]; + for ( i=0;i<nbv;i++) + { + f_in >> vertices[i].r.x >> vertices[i].r.y >> vertices[i].ReferenceNumber; + vertices[i].on=0; + vertices[i].m=M1; + //if(vertices[i].ReferenceNumber>NbRef) NbRef=vertices[i].ReferenceNumber; + } + for ( i=0;i<nbt;i++) + { + Int4 i1,i2,i3,r; + f_in >> i1 >> i2 >> i3 >> r; + triangles[i] = Triangle(this,i1-1,i2-1,i3-1); + triangles[i].color = r; + } + for (i=0;i<nbe;i++) + { + Int4 i1,i2,r; + f_in >> i1 >> i2 >> r; + edges[i].v[0]= vertices +i1-1; + edges[i].v[1]= vertices +i2-1; + edges[i].adj[0]=0; + edges[i].adj[1]=0; + edges[i].ref = r; + edges[i].on=0; + } + +} + +////////////////////////////////////////////////// + +void Triangles::Read_amdba(MeshIstream &f_in ) +{ + Metric M1(1); + if (verbosity>1) + cout << " -- ReadMesh .amdba file " << f_in.CurrentFile << endl; + + Int4 i; + f_in.cm() >> nbv >> nbt ; + // if (verbosity>3) + cout << " nbv = " << nbv << " nbt = " << nbt << endl; + f_in.eol() ;// + nbvx = nbv; + nbtx = 2*nbv-2; // for filling The Holes and quadrilaterals + triangles =new Triangle[nbtx]; + assert(triangles); + vertices=new Vertex[nbvx]; + ordre=new (Vertex* [nbvx]); + Int4 j; + for ( i=0;i<nbv;i++) + { + f_in >> j ; + assert( j >0 && j <= nbv); + j--; + f_in >> vertices[j].r.x >> vertices[j].r.y >> vertices[j].ReferenceNumber; + vertices[j].m=M1; + vertices[j].DirOfSearch=NoDirOfSearch; + } + + for ( i=0;i<nbt;i++) + { + Int4 i1,i2,i3,ref; + f_in >> j ; + assert( j >0 && j <= nbt); + j--; + f_in >> i1 >> i2 >> i3 >> ref; + triangles[j] = Triangle(this,i1-1,i2-1,i3-1); + triangles[j].color =ref; + } + f_in.eol() ;// + + // cerr << " a faire " << endl; + //MeshError(888); +} + + +Triangles::Triangles(const char * filename,Real8 cutoffradian) +: Gh(*(new Geometry())), BTh(*this) +{ +#ifdef DRAWING1 + if (!withrgraphique) {initgraphique();withrgraphique=true;} +#endif + + // Int4 beginquad=0,begintria=0; + // Int4 endquad=0;endtria=0; + //int type_file=0; + + int lll = strlen(filename); + int am_fmt = !strcmp(filename + lll - 7,".am_fmt"); + int amdba = !strcmp(filename + lll - 6,".amdba"); + int am = !strcmp(filename + lll - 3,".am"); + int nopo = !strcmp(filename + lll - 5,".nopo"); + int msh = !strcmp(filename + lll - 4,".msh"); + int ftq = !strcmp(filename + lll - 4,".ftq"); + + // cout << " Lecture type :" << filename + lll - 7 <<":" <<am_fmt<< endl; + + char * cname = new char[lll+1]; + strcpy(cname,filename); + Int4 inbvx =0; + PreInit(inbvx,cname); + OnDisk = 1; + // allocGeometry = &Gh; // after Preinit ; + + MeshIstream f_in (filename); + + if (f_in.IsString("MeshVersionFormatted")) + { + int version ; + f_in >> version ; + Read(f_in,version,cutoffradian); + } + else { + if (am_fmt) Read_am_fmt(f_in); + else if (am) Read_am(f_in); + else if (amdba) Read_amdba(f_in); + else if (msh) Read_msh(f_in); + else if (nopo) Read_nopo(f_in); + else if (ftq) Read_ftq(f_in); + else + { + cerr << " Unkown type mesh " << filename << endl; + MeshError(2); + } + ConsGeometry(cutoffradian); + Gh.AfterRead(); + } + + SetIntCoor(); + FillHoleInMesh(); + // Make the quad --- + +} + +void Geometry::ReadGeometry(const char * filename) +{ + OnDisk = 1; + if(verbosity>1) + cout << " -- ReadGeometry " << filename << endl; + MeshIstream f_in (filename); + ReadGeometry(f_in,filename); +} + + + +void Geometry::ReadGeometry(MeshIstream & f_in,const char * filename) +{ + if(verbosity>1) + cout << " -- ReadGeometry " << filename << endl; + assert(empty()); + nbiv=nbv=nbvx=0; + nbe=nbt=nbtx=0; + NbOfCurves=0; + // BeginOfCurve=0; + name=new char [strlen(filename)+1]; + strcpy(name,filename); + Real8 Hmin = HUGE_VAL;// the infinie value +// Real8 MaximalAngleOfCorner = 10*Pi/180; ; + Int4 hvertices =0; + Int4 i; + Int4 Version,dim=0; + int field=0; + int showfield=0; + int NbErr=0; + + while (f_in.cm()) + { + field=0; + // warning ruse for on allocate fiedname at each time + char fieldname[256]; + f_in.cm() >> fieldname ; + f_in.err(); + if(f_in.eof()) break; +// cout << fieldname << " line " << LineNumber <<endl; + if (!strcmp(fieldname,"MeshVersionFormatted") ) + f_in >> Version ; + else if (!strcmp(fieldname,"End")) + break; + else if (!strcmp(fieldname,"end")) + break; + else if (!strcmp(fieldname,"Dimension")) + { + f_in >> dim ; + if(verbosity>5) + cout << " Geom Record Dimension dim = " << dim << endl; + assert(dim ==2); + } + else if (!strcmp(fieldname,"hVertices")) + { + if (nbv <=0) { + cerr<<"Error: the field Vertex is not found before hVertices " << filename<<endl; + NbErr++;} + if(verbosity>5) + cout << " Geom Record hVertices nbv=" << nbv << endl; + hvertices =1; + for (i=0;i< nbv;i++) + { + Real4 h; + f_in >> h ; + vertices[i].m = Metric(h); + } + } + else if (!strcmp(fieldname,"MetricVertices")) + { hvertices =1; + if (nbv <=0) { + cerr<<"Error: the field Vertex is not found before MetricVertices " << filename<<endl; + NbErr++;} + if(verbosity>5) + cout << " Geom Record MetricVertices nbv =" << nbv << endl; + for (i=0;i< nbv;i++) + { + Real4 a11,a21,a22; + f_in >> a11 >> a21 >> a22 ; + vertices[i].m = Metric(a11,a21,a22); + } + } + else if (!strcmp(fieldname,"h1h2VpVertices")) + { hvertices =1; + if (nbv <=0) { + cerr<<"Error: the field Vertex is not found before h1h2VpVertices " << filename<<endl; + NbErr++;} + if(verbosity>5) + cout << " Geom Record h1h2VpVertices nbv=" << nbv << endl; + + for (i=0;i< nbv;i++) + { + Real4 h1,h2,v1,v2; + f_in >> h1 >> h2 >>v1 >>v2 ; + vertices[i].m = Metric(MatVVP2x2(1/(h1*h1),1/(h2*h2),D2(v1,v2))); + } + } + else if (!strcmp(fieldname,"Vertices")) + { + assert(dim ==2); + f_in >> nbv ; + // if(LineError) break; + nbvx = nbv; + + vertices = new GeometricalVertex[nbvx]; + if(verbosity>5) + cout << " Geom Record Vertices nbv = " << nbv << "vertices = " << vertices<<endl; + assert(nbvx >= nbv); + nbiv = nbv; + for (i=0;i<nbv;i++) { + f_in >> vertices[i].r.x ; + // if(LineError) break; + f_in >> vertices[i].r.y ; + // if(LineError) break; + f_in >> vertices[i].ReferenceNumber ; + vertices[i].DirOfSearch=NoDirOfSearch; + // vertices[i].m.h = 0; + vertices[i].color =0; + vertices[i].Set();} + // if(LineError) break; + pmin = vertices[0].r; + pmax = vertices[0].r; + // recherche des extrema des vertices pmin,pmax + for (i=0;i<nbv;i++) { + pmin.x = Min(pmin.x,vertices[i].r.x); + pmin.y = Min(pmin.y,vertices[i].r.y); + pmax.x = Max(pmax.x,vertices[i].r.x); + pmax.y = Max(pmax.y,vertices[i].r.y); + } + + R2 DD05 = (pmax-pmin)*0.05; + pmin -= DD05; + pmax += DD05; + + coefIcoor= (MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y)); + assert(coefIcoor >0); + if (verbosity>5) { + cout << " Geom: min="<< pmin << "max ="<< pmax << " hmin = " << MinimalHmin() << endl;} + } + else if(!strcmp(fieldname,"MaximalAngleOfCorner")||!strcmp(fieldname,"AngleOfCornerBound")) + { + f_in >> MaximalAngleOfCorner; + + if(verbosity>5) + cout << " Geom Record MaximalAngleOfCorner " << MaximalAngleOfCorner <<endl; + MaximalAngleOfCorner *= Pi/180; + } + else if (!strcmp(fieldname,"Edges")) + { + if (nbv <=0) { + cerr<<"Error: the field edges is not found before MetricVertices " << filename<<endl; + NbErr++;} + else + { + int i1,i2; + R2 zero2(0,0); + f_in >> nbe ; + + edges = new GeometricalEdge[nbe]; + if(verbosity>5) + cout << " Record Edges: Nb of Edge " << nbe <<endl; + assert(edges); + assert (nbv >0); + Real4 *len =0; + if (!hvertices) + { + len = new Real4[nbv]; + for(i=0;i<nbv;i++) + len[i]=0; + } + + for (i=0;i<nbe;i++) + { + f_in >> i1 >> i2 >> edges[i].ref ; + + i1--;i2--; // for C index + edges[i].v[0]= vertices + i1; + edges[i].v[1]= vertices + i2; + R2 x12 = vertices[i2].r-vertices[i1].r; + Real8 l12=sqrt((x12,x12)); + edges[i].tg[0]=zero2; + edges[i].tg[1]=zero2; + edges[i].SensAdj[0] = edges[i].SensAdj[1] = -1; + edges[i].Adj[0] = edges[i].Adj[1] = 0; + edges[i].flag = 0; + if (!hvertices) + { + vertices[i1].color++; + vertices[i2].color++; + len[i1] += l12; + len[i2] += l12; + } + + Hmin = Min(Hmin,l12); + } + // definition the default of the given mesh size + if (!hvertices) + { + for (i=0;i<nbv;i++) + if (vertices[i].color > 0) + vertices[i].m= Metric(len[i] /(Real4) vertices[i].color); + else + vertices[i].m= Metric(Hmin); + delete [] len; + + if(verbosity>3) + cout << " Geom Hmin " << Hmin << endl; + } + + } + } + else if (!strcmp(fieldname,"EdgesTangence") ||!strcmp(fieldname,"TangentAtEdges") ) + { + int n,i,j,k; + R2 tg; + f_in >> n ; + + if(verbosity>5) + cout << " Record TangentAtEdges: Nb of Edge " << n <<endl; + + for (k=0;k<n;k++) + { + f_in >> i >> j ; + f_in >> tg.x >> tg.y ; + assert( i <= nbe ); + assert( i > 0 ); + assert ( j == 1 || j==2 ); + i--;j--;// for C index + edges[i].tg[j] = tg; + } + } + else if (!strcmp(fieldname,"Corners")) + { + int i,j,n; + f_in >> n ; + if(verbosity>5) + cout << " Record Corner: Nb of Corner " << n <<endl; + + for (i=0;i<n;i++) { + f_in >> j ; + assert( j <= nbv ); + assert( j > 0 ); + j--; + vertices[j].SetCorner(); + vertices[j].SetRequired(); } + } + else if (!strcmp(fieldname,"RequiredVertices")) + { + int i,j,n; + f_in >> n ; + + for (i=0;i<n;i++) { + f_in >> j ; + assert( j <= nbv ); + assert( j > 0 ); + j--; + vertices[j].SetRequired(); } + } + else if (!strcmp(fieldname,"RequiredEdges")) + { + int i,j,n; + f_in >> n ; + + for (i=0;i<n;i++) { + f_in >> j ; + assert( j <= nbe ); + assert( j > 0 ); + j--; + edges[j].SetRequired(); } + } + else if (!strcmp(fieldname,"SubDomain") || !strcmp(fieldname,"SubDomainFromGeom")) + { + f_in >> NbSubDomains ; + if (NbSubDomains>0) + { + subdomains = new GeometricalSubDomain[ NbSubDomains]; + Int4 i0,i1,i2,i3; + for (i=0;i<NbSubDomains;i++) + { + f_in >> i0 >>i1 + >> i2 >>i3 ; + + assert(i0 == 2); + assert(i1<=nbe && i1>0); + subdomains[i].edge=edges + (i1-1); + subdomains[i].sens = (int) i2; + subdomains[i].ref = i3; + } + } + } + else + { // unkown field + field = ++showfield; + if(showfield==1) // just to show one time + if (verbosity>3) + cout << " Warning we skip the field " << fieldname << " at line " << f_in.LineNumber << endl; + } + showfield=field; // just to show one time + } // while !eof() + // generation de la geometrie + // 1 construction des aretes + // construire des aretes en chaque sommets + + if (nbv <=0) { + cerr<<"Error: the field Vertex is not found in " << filename<<endl; + NbErr++;} + if(nbe <=0) { + cerr <<"Error: the field Edges is not found in "<< filename<<endl + ;NbErr++;} + if(NbErr) MeshError(1); + + +} + + +} // end of namespace bamg diff --git a/contrib/bamg/bamglib/MeshWrite.cpp b/contrib/bamg/bamglib/MeshWrite.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8547dea25bad60743c37601d00663bbdee2e55a2 --- /dev/null +++ b/contrib/bamg/bamglib/MeshWrite.cpp @@ -0,0 +1,947 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#include <cstdio> +#include <cstring> +#include <cmath> +#include <ctime> +#include "Meshio.h" +#include "Mesh2.h" +#include "QuadTree.h" +#include "SetOfE4.h" + + +namespace bamg { + +void Triangles::Write(const char * filename,const TypeFileMesh typein ) +{ + TypeFileMesh type = typein; + const char * gsuffix=".gmsh"; + int ls=0; + int lll = strlen(filename); + if (type==AutoMesh) + { + type = BDMesh; + if (!strcmp(filename + lll - (ls=7),".am_fmt")) type = am_fmtMesh; + else if (!strcmp(filename + lll - (ls=6),".amdba")) type = amdbaMesh; + else if (!strcmp(filename + lll - (ls=3),".am")) type = amMesh; + else if (!strcmp(filename + lll - (ls=5),".nopo")) type = NOPOMesh; + else if (!strcmp(filename + lll - (ls=4),".msh")) type = mshMesh; + else if (!strcmp(filename + lll - (ls=4),".ftq")) type = ftqMesh; + else if (!strcmp(filename + lll - (ls=7),".AM_FMT")) type = am_fmtMesh; + else if (!strcmp(filename + lll - (ls=6),".AMDBA")) type = amdbaMesh; + else if (!strcmp(filename + lll - (ls=3),".AM")) type = amMesh; + else if (!strcmp(filename + lll - (ls=5),".NOPO")) type = NOPOMesh; + else if (!strcmp(filename + lll - (ls=4),".MSH")) type = mshMesh; + else if (!strcmp(filename + lll - (ls=4),".FTQ")) type = ftqMesh; + else ls=0; + } + if (verbosity>1) + { + cout << " -- Writing the file " << filename << " of type " ; + switch (type) + { + case BDMesh : cout << " BD Mesh " ; break; + case NOPOMesh : cout << " NOPO " ; break; + case amMesh : cout << " am " ; break; + case am_fmtMesh : cout << " am_fmt " ; break; + case amdbaMesh : cout << " amdba " ; break; + case ftqMesh : cout << " ftq " ; break; + case mshMesh : cout << " msh " ; break; + default: + cerr << endl + << " Unkown type mesh file " << (int) type << " for Writing " << filename <<endl; + MeshError(1); + } + Int4 NbOfTria = nbt-2*NbOfQuad-NbOutT ; + if (NbOfTria) cout << " NbOfTria = " << NbOfTria; + if (NbOfQuad) cout << " NbOfQuad = " << NbOfQuad; + if (nbe) cout << " NbOfRefEdge = " << nbe ; + cout << endl; + + } + ofstream f(filename /*,ios::trunc*/); + f.precision(12); + + if (f) + switch (type) + { + case BDMesh : + { + if ( ! Gh.OnDisk) + { + delete [] Gh.name; + Gh.name = new char[lll+1+strlen(gsuffix)]; + strcpy(Gh.name,filename); + if (Gh.name[lll-ls-1]=='.') strcpy(Gh.name+lll-ls, gsuffix+1); + else strcpy(Gh.name+lll-ls,gsuffix); + cout << " write geo in " << Gh.name << endl; + ofstream f(Gh.name) ; + f << Gh ; + Gh.OnDisk=true; + } + f << *this ; + break; + } + case NOPOMesh : Write_nopo(f) ; break; + case amMesh : Write_am(f) ; break; + case am_fmtMesh : Write_am_fmt(f); break; + case amdbaMesh : Write_amdba(f) ; break; + case ftqMesh : Write_ftq(f) ; break; + case mshMesh : Write_msh(f) ; break; + default: + cerr << " Unkown type mesh file " << (int) type << " for Writing " << filename <<endl; + MeshError(1); + } + else + { + cerr << " Error openning file " << filename << endl; + MeshError(1); + } + if(verbosity>5) + cout << "end write" << endl; + +} +void Triangles::Write_nop5(OFortranUnFormattedFile * f, + Int4 &lnop5,Int4 &nef,Int4 &lgpdn,Int4 ndsr) const +{ + ndsr =0; + Int4 * reft = new Int4[nbt]; + //Int4 nbInT = ; + ConsRefTriangle(reft); + Int4 no5l[20]; + + Int4 i5 = 0; + Int4 i,j,k=0,l5; + // Int4 ining=0; + Int4 imax,imin; + + lgpdn = 0; + nef=0; + // construction of a liste linked of edge + Edge ** head = new Edge *[nbv]; + Edge ** link = new Edge * [nbe]; + for (i=0;i<nbv;i++) + head[i]=0; // empty liste + + for (i=0;i<nbe;i++) + { + j = Min(Number(edges[i][0]),Number(edges[i][1])); + link[i]=head[j]; + head[j]=edges +i; + } + for ( i=0;i<nbt;i++) + { + no5l[0] = 0; + Int4 kining=0; + Int4 ining=0; + Int4 nmae =0; + Int4 np=0; + l5 = 2; + Triangle & t = triangles[i]; + Triangle * ta; // + Vertex *v0,*v1,*v2,*v3; + if (reft[i]<0) continue; + ta = t.Quadrangle(v0,v1,v2,v3); + if (!ta) + { // a triangles + no5l[l5++] = Max(subdomains[reft[i]].ref,(Int4) 1); + np = 3; + no5l[l5++] = np; + no5l[0] = np; + no5l[l5++] = Number(triangles[i][0]) +1; + no5l[l5++] = Number(triangles[i][1]) +1; + no5l[l5++] = Number(triangles[i][2]) +1; + imax = Max3(no5l[l5-1],no5l[l5-2],no5l[l5-3]); + imin = Min3(no5l[l5-1],no5l[l5-2],no5l[l5-3]); + lgpdn = Max(lgpdn,imax-imin); + kining=l5++; + // ref of 3 edges + for (j=0;j<3;j++) + { + no5l[l5] = 0; + int i0 = (int) j; + int i1 = (i0+1) %3; + Int4 j1= no5l[4+i0]; + Int4 j2= no5l[4+i1]; + Int4 ji = Min(j1,j2)-1; + Int4 ja = j1+j2-2; + Edge * e=head[ji]; + while (e) + if(Number((*e)[0])+Number((*e)[1]) == ja) + { + no5l[l5] = e->ref; + break; + } + else + e = link[Number(e)]; + l5++; + } + if ( no5l[l5-1] || no5l[l5-2] || no5l[l5-3] ) + ining=2; + else + l5 -= 3; + + no5l[l5++] = triangles[i][0].ref(); + no5l[l5++] = triangles[i][1].ref(); + no5l[l5++] = triangles[i][2].ref(); + if (ining || no5l[l5-1] || no5l[l5-2] || no5l[l5-3] ) + ining= ining ? ining : 3; + else + l5 -= 3,ining=0; + + + } + else if ( &t<ta) + { + k++; + no5l[l5++] = Max(subdomains[reft[i]].ref,(Int4) 1); + np =4; + no5l[l5++] = np; + no5l[0] = np; + + no5l[l5++] = Number(v0) +1; + no5l[l5++] = Number(v1) +1; + no5l[l5++] = Number(v2) +1; + no5l[l5++] = Number(v3) +1; + + imax = Max(Max(no5l[l5-1],no5l[l5-2]),Max(no5l[l5-3],no5l[l5-4])); + imin = Min(Min(no5l[l5-1],no5l[l5-2]),Min(no5l[l5-3],no5l[l5-4])); + lgpdn = Max(lgpdn,imax-imin); + + + kining=l5++; + // ref of the 4 edges + // ref of 3 edges + for (j=0;j<4;j++) + { + no5l[l5] = 0; + int i0 = (int) j; + int i1 = (i0+1) %4; + Int4 j1= no5l[4+i0]; + Int4 j2= no5l[4+i1]; + Int4 ji = Min(j1,j2)-1; + Int4 ja = j1+j2-2; + Edge *e=head[ji]; + while (e) + if(Number((*e)[0])+Number((*e)[1]) == ja) + { + no5l[l5] = e->ref; + break; + } + else + e = link[Number(e)]; + l5++; + } + if ( no5l[l5-1] || no5l[l5-2] || no5l[l5-3] || no5l[l5-4] ) + ining=2; + else + l5 -= 4; + + no5l[l5++] = v0->ref(); + no5l[l5++] = v1->ref(); + no5l[l5++] = v2->ref(); + no5l[l5++] = v3->ref(); + if (ining || no5l[l5-1] || no5l[l5-2] || no5l[l5-3] || no5l[l5-4] ) + ining= ining ? ining : 3; + else + l5 -= 4; + + } + else l5=0; + + if (l5) + { + if (ining) + { + nef ++; + nmae = l5-kining; + no5l[kining] = ining; + } + else l5--; + no5l[1]=nmae; + // for all ref + for (j=kining+1;j<l5;j++) + { + no5l[j] = Abs(no5l[j]); + ndsr = Max(ndsr,no5l[j]); + } + + if (f && i < 10 && verbosity > 10) + { + cout << " e[ " << i << " @" << i5 << "]="; + for (j=0;j<l5;j++) + cout << " " << no5l[j]; + cout << endl; + } + + if (f) + for (j=0;j<l5;j++) + *f << no5l[j]; + i5 += l5; + } + } + if(verbosity>10) + cout << " fin write nopo 5 i5=" << i5 << " " << i5*4 << endl; + lnop5=i5; + lgpdn++; // add 1 + delete [] reft; + delete [] head; + delete [] link; + +} + +void Triangles::Write_nopo(ostream &ff) const + +{ + Int4 nef=0; + Int4 lpgdn=0; + Int4 ndsr=0; + Int4 i; + Int4 ndsd=1; + Int4 lnop5=0; + + OFortranUnFormattedFile f(ff); + + for (i=0;i<NbSubDomains ;i++) + ndsd=Max(ndsd,subdomains[i].ref); + + // to compute the lnop5,nef,lpgdn,ndsr parameter + Write_nop5(0,lnop5,nef,lpgdn,ndsr); + + f.Record(); + + f << Int4(13)<<Int4(6)<<Int4(32)<<Int4(0)<<Int4(27)<<Int4(0) ; + f << Int4(nbv+nbv) ; + f << lnop5; + f << Int4(1 )<<Int4(1)<<Int4(1 )<<Int4(1)<<Int4(2)<<Int4(1); + + f.Record(33*sizeof(Int4)); + + f << Int4(32) ; + + //char *c=identity; + time_t timer =time(0); + char buf[10]; + strftime(buf ,10,"%y/%m/%d",localtime(&timer)); + f.write4(identity,20); + f.write4(buf,2); + f.write4("created with BAMG",6); + f.write4("NOPO",1); + + + f << Int4(0) << Int4(1) << Int4(0) ; + f.Record(); + Int4 nbquad= NbOfQuad; + Int4 nbtria= nbt-NbOutT - 2*NbOfQuad; + + cout << " lnop5 = " << lnop5 << endl; + cout << " nbquad = " << nbquad << endl; + cout << " nbtrai = " << nbtria << endl; + cout << " lpgdn = " << lpgdn << endl; + cout << " nef = " << nef << endl; + cout << " np = " << nbv << endl; + cout << " ndsr = " << ndsr << endl; + f << Int4(27) + << Int4(2) << ndsr << ndsd << Int4(1) << nbtria+nbquad + << Int4(0) << Int4(0) << nbtria << nbquad << Int4(0) + << Int4(0) << Int4(0) << Int4(0) << nef << Int4(nbv) + << Int4(0) << Int4(0) << Int4(0) << Int4(0) << Int4(0) + << Int4(0) << nbv << Int4(2) << lpgdn << Int4(0) + << lnop5 << Int4(1) ; + f.Record(); + f << (Int4) 2*nbv; + for (i=0;i<nbv;i++) + f << (float) vertices[i].r.x << (float) vertices[i].r.y; + f.Record(); + f << lnop5; + Write_nop5(&f,lnop5,nef,lpgdn,ndsr); + // cout << "fin write nopo" << endl; +} + +void Triangles::Write_am_fmt(ostream &f) const +{ + Int4 i,j; + assert(this && nbt); + Int4 * reft = new Int4[nbt]; + Int4 nbInT = ConsRefTriangle(reft); + f.precision(12); + f << nbv << " " << nbInT << endl; + for (i=0;i<nbt;i++) + if(reft[i]>=0) + { + f << Number(triangles[i][0]) +1 << " " ; + f << Number(triangles[i][1]) +1 << " " ; + f << Number(triangles[i][2]) +1 << " " ; + f << endl; + } + for (i=0;i<nbv;i++) + f << vertices[i].r.x << " " << vertices[i].r.y << endl; + for (j=i=0;i<nbt;i++) + if (reft[i]>=0) + f << subdomains[reft[i]].ref << (j++%10 == 9 ? '\n' : ' '); + f << endl; + for (i=0;i<nbv;i++) + f << vertices[i].ref() << (i%10 == 9 ? '\n' : ' '); + f << endl; + delete [] reft; + + +} + +void Triangles::Write_am(ostream &ff) const +{ + OFortranUnFormattedFile f(ff); + Int4 i,j; + assert(this && nbt); + Int4 * reft = new Int4[nbt]; + Int4 nbInT = ConsRefTriangle(reft); + f.Record(); + f << nbv << nbInT ; + f.Record(); + for (i=0;i<nbt;i++) + if(reft[i]>=0) + { + f << Number(triangles[i][0]) +1 ; + f << Number(triangles[i][1]) +1 ; + f << Number(triangles[i][2]) +1 ; + } + for (i=0;i<nbv;i++) + { + float x= vertices[i].r.x; + float y= vertices[i].r.y; + f << x << y ; + } + for (j=i=0;i<nbt;i++) + if (reft[i]>=0) + f << subdomains[reft[i]].ref; + for (i=0;i<nbv;i++) + f << vertices[i].ref() ; + delete [] reft; +} + +void Triangles::Write_ftq(ostream &f) const +{ + + Int4 i; + assert(this && nbt); + Int4 * reft = new Int4[nbt]; + Int4 nbInT = ConsRefTriangle(reft); + f.precision(12); + Int4 nele = nbInT-NbOfQuad; + Int4 ntri = nbInT-2*NbOfQuad; + Int4 nqua = NbOfQuad; + + f << nbv << " " << nele << " " << ntri << " " << nqua << endl; + Int4 k=0; + for( i=0;i<nbt;i++) + { + Triangle & t = triangles[i]; + Triangle * ta; // + Vertex *v0,*v1,*v2,*v3; + if (reft[i]<0) continue; + ta = t.Quadrangle(v0,v1,v2,v3); + if (!ta) + { // a triangles + f << "3 " + << Number(triangles[i][0]) +1 << " " + << Number(triangles[i][1]) +1 << " " + << Number(triangles[i][2]) +1 << " " + << subdomains[reft[i]].ref << endl; + k++; + } + if ( &t<ta) + { + k++; + f << "4 " << Number(v0)+1 << " " << Number(v1)+1 << " " + << Number(v2)+1 << " " << Number(v3)+1 << " " + << subdomains[reft[i]].ref << endl; + } + } + assert(k == nele); + + for (i=0;i<nbv;i++) + f << vertices[i].r.x << " " << vertices[i].r.y + << " " << vertices[i].ref() << endl; + delete [] reft; + + +} +void Triangles::Write_msh(ostream &f) const +{ + Int4 i; + assert(this && nbt); + Int4 * reft = new Int4[nbt]; + Int4 nbInT = ConsRefTriangle(reft); + f.precision(12); + f << nbv << " " << nbInT << " " << nbe << endl; + + for (i=0;i<nbv;i++) + f << vertices[i].r.x << " " << vertices[i].r.y << " " + << vertices[i].ref() << endl; + + for (i=0;i<nbt;i++) + if(reft[i]>=0) + f << Number(triangles[i][0]) +1 << " " + << Number(triangles[i][1]) +1 << " " + << Number(triangles[i][2]) +1 << " " + << subdomains[reft[i]].ref << endl; + + + for (i=0;i<nbe;i++) + f << Number(edges[i][0]) +1 << " " << Number(edges[i][1]) +1 + << " " << edges[i].ref << endl; + + delete [] reft; + +} + +void Triangles::Write_amdba(ostream &f) const +{ + assert(this && nbt); + + Int4 i,j; + Int4 * reft = new Int4[nbt]; + Int4 nbInT = ConsRefTriangle(reft); + f << nbv << " " << nbInT << endl; + cout.precision(12); + for (i=0;i<nbv;i++) + f << i+1 << " " + << vertices[i].r.x + << " " << vertices[i].r.y + << " " << vertices[i].ref() << endl; + j=1; + for (i=0;i<nbt;i++) + if(reft[i]>=0) + f << j++ << " " + << Number(triangles[i][0]) +1 << " " + << Number(triangles[i][1]) +1 << " " + << Number(triangles[i][2]) +1 << " " + << subdomains[reft[i]].ref << endl ; + f << endl; + delete [] reft; + + +} + +void Triangles::Write(const char * filename) +{ + ofstream f(filename); + if (f) + { + if (name) delete name; + name = new char[strlen(filename)+1]; + strcpy(name,filename); + OnDisk =1; + f << *this; + } +} +void Triangles::WriteElements(ostream& f,Int4 * reft ,Int4 nbInT) const + { + const Triangles & Th= *this; + // do triangle and quad + if(verbosity>9) + cout << " In Triangles::WriteElements " << endl + << " Nb of In triangles " << nbInT-Th.NbOfQuad*2 << endl + << " Nb of Quadrilaterals " << Th.NbOfQuad << endl + << " Nb of in+out+quad triangles " << Th.nbt << " " << nbInT << endl; + + Int4 k=nbInT-Th.NbOfQuad*2; + Int4 num =0; + if (k>0) { + f << "\nTriangles\n"<< k << endl; + for(Int4 i=0;i<Th.nbt;i++) + { + Triangle & t = Th.triangles[i]; + if (reft[i]>=0 && !( t.Hidden(0) || t.Hidden(1) || t.Hidden(2) )) + { k--; + f << Th.Number(t[0])+1 << " " << Th.Number(t[1])+1 + << " " << Th.Number(t[2])+1 << " " << Th.subdomains[reft[i]].ref << endl; + reft[i] = ++num; + } + } + } + if (Th.NbOfQuad>0) { + f << "\nQuadrilaterals\n"<<Th.NbOfQuad << endl; + k = Th.NbOfQuad; + for(Int4 i=0;i<Th.nbt;i++) + { + Triangle & t = Th.triangles[i]; + Triangle * ta; // + Vertex *v0,*v1,*v2,*v3; + if (reft[i]<0) continue; + if ((ta=t.Quadrangle(v0,v1,v2,v3)) !=0 && &t<ta) + { + k--; + f << Th.Number(v0)+1 << " " << Th.Number(v1)+1 << " " + << Th.Number(v2)+1 << " " << Th.Number(v3)+1 << " " + << Th.subdomains[reft[i]].ref << endl; + reft[i] = ++num; + reft[Number(ta)] = num; + } + } + assert(k==0); + } + // warning reft is now the element number + } + +ostream& operator <<(ostream& f, const Triangles & Th) + { + // Th.FindSubDomain(); + // warning just on say the class is on the disk + // ((Triangles *) &Th)->OnDisk = 1; + + Int4 * reft = new Int4[Th.nbt]; + Int4 nbInT = Th.ConsRefTriangle(reft); + { + f << "MeshVersionFormatted 0" <<endl; + f << "\nDimension\n" << 2 << endl; + f << "\nIdentifier\n" ; + WriteStr(f,Th.identity); + f << "\n\nGeometry\n" ; + if( Th.Gh.OnDisk) + WriteStr(f,Th.Gh.name), f <<endl; + else + { // empty file name -> geom in same file + f << "\"\"" << endl << endl; + f << "# BEGIN of the include geometry file because geometry is not on the disk" + << Th.Gh << endl; + f << "End" << endl + << "# END of the include geometrie file because geometry is not on the disk" + << endl ; + } + } + { + f.precision(12); + f << "\nVertices\n" << Th.nbv <<endl; + for (Int4 i=0;i<Th.nbv;i++) + { + Vertex & v = Th.vertices[i]; + f << v.r.x << " " << v.r.y << " " << v.ref() << endl; + } + } + Int4 ie; + { + f << "\nEdges\n"<< Th.nbe << endl; + for(ie=0;ie<Th.nbe;ie++) + { + Edge & e = Th.edges[ie]; + f << Th.Number(e[0])+1 << " " << Th.Number(e[1])+1; + f << " " << e.ref <<endl; + } + if(Th.NbCrackedEdges) + { + f << "\nCrackedEdges\n"<< Th.NbCrackedEdges << endl; + for( ie=0;ie<Th.NbCrackedEdges;ie++) + { + Edge & e1 = *Th.CrackedEdges[ie].a.edge; + Edge & e2 = *Th.CrackedEdges[ie].b.edge; + f << Th.Number(e1)+1 << " " << Th.Number(e2)+1 <<endl;; + } + } + } + + Th.WriteElements(f,reft,nbInT); + { + f << "\nSubDomainFromMesh\n" << Th.NbSubDomains<< endl ; + for (Int4 i=0;i<Th.NbSubDomains;i++) + f << 3 << " " << reft[Th.Number(Th.subdomains[i].head)] << " " << 1 << " " + << Th.subdomains[i].ref << endl; + + } + if (Th.Gh.NbSubDomains) + { + f << "\nSubDomainFromGeom\n" << Th.Gh.NbSubDomains << endl ; + for (Int4 i=0;i<Th.NbSubDomains;i++) + { + f << 2 << " " << Th.Number(Th.subdomains[i].edge)+1 << " " + << Th.subdomains[i].sens << " " << Th.Gh.subdomains[i].ref << endl; + } + } + { + f << "\nVertexOnGeometricVertex\n"<< Th.NbVerticesOnGeomVertex << endl; + for (Int4 i0=0;i0<Th.NbVerticesOnGeomVertex;i0++) + { + VertexOnGeom & v =Th.VerticesOnGeomVertex[i0]; + assert(v.OnGeomVertex()) ; + f << " " << Th.Number(( Vertex *)v)+1 + << " " << Th.Gh.Number(( GeometricalVertex * )v)+1 + << endl; + } + } + { + f << "\nVertexOnGeometricEdge\n"<< Th.NbVerticesOnGeomEdge << endl; + for (Int4 i0=0;i0<Th.NbVerticesOnGeomEdge;i0++) + { + const VertexOnGeom & v =Th.VerticesOnGeomEdge[i0]; + assert(v.OnGeomEdge()) ; + f << " " << Th.Number((Vertex * )v)+1 ; + f << " " << Th.Gh.Number((const GeometricalEdge * )v)+1 ; + f << " " << (Real8 ) v << endl; + } + } + { + Int4 i0,k=0; + + for (i0=0;i0<Th.nbe;i0++) + if ( Th.edges[i0].on ) k++; + + f << "\nEdgeOnGeometricEdge\n"<< k << endl; + for (i0=0;i0<Th.nbe;i0++) + if ( Th.edges[i0].on ) + f << (i0+1) << " " << (1+Th.Gh.Number(Th.edges[i0].on)) << endl; + if (Th.NbCrackedEdges) + { + f << "\nCrackedEdges\n"<< Th.NbCrackedEdges << endl; + for(i0=0;i0< Th.NbCrackedEdges; i0++) + { + f << Th.Number(Th.CrackedEdges[i0].a.edge) << " " ; + f << Th.Number(Th.CrackedEdges[i0].b.edge) << endl; + } + } + } + if (&Th.BTh != &Th && Th.BTh.OnDisk && Th.BTh.name) + { + int *mark=new int[Th.nbv]; + Int4 i; + for (i=0;i<Th.nbv;i++) + mark[i]=-1; + f << "\nMeshSupportOfVertices\n" <<endl; + WriteStr(f,Th.BTh.name); + f <<endl; + f << "\nIdentityOfMeshSupport" << endl; + WriteStr(f,Th.BTh.identity); + f<<endl; + + f << "\nVertexOnSupportVertex" << endl; + f<< Th.NbVertexOnBThVertex << endl; + for(i=0;i<Th.NbVertexOnBThVertex;i++) { + const VertexOnVertex & vov = Th.VertexOnBThVertex[i]; + Int4 iv = Th.Number(vov.v); + mark[iv] =0; + f << iv+1<< " " << Th.BTh.Number(vov.bv)+1 << endl;} + + f << "\nVertexOnSupportEdge" << endl; + f << Th.NbVertexOnBThEdge << endl; + for(i=0;i<Th.NbVertexOnBThEdge;i++) { + const VertexOnEdge & voe = Th.VertexOnBThEdge[i]; + Int4 iv = Th.Number(voe.v); + // assert(mark[iv] == -1]); + mark[iv] = 1; + f << iv+1 << " " << Th.BTh.Number(voe.be)+1 << " " << voe.abcisse << endl;} + + f << "\nVertexOnSupportTriangle" << endl; + Int4 k = Th.nbv - Th.NbVertexOnBThEdge - Th.NbVertexOnBThVertex; + f << k << endl; + // Int4 kkk=0; + CurrentTh=&Th.BTh; + for (i=0;i<Th.nbv;i++) + if (mark[i] == -1) { + k--; + Icoor2 dete[3]; + I2 I = Th.BTh.toI2(Th.vertices[i].r); + Triangle * tb = Th.BTh.FindTriangleContening(I,dete); + if (tb->link) // a true triangle + { + Real8 aa= (Real8) dete[1]/ tb->det, bb= (Real8) dete[2] / tb->det; + f << i+1 << " " << Th.BTh.Number(tb)+1 << " " << aa << " " << bb << endl ; + } + else + { + double aa,bb,det[3]; + TriangleAdjacent ta=CloseBoundaryEdgeV2(I,tb,aa,bb); + int k = ta; + det[VerticesOfTriangularEdge[k][1]] =aa; + det[VerticesOfTriangularEdge[k][0]] = bb; + det[OppositeVertex[k]] = 1- aa -bb; + Triangle * tb = ta; + f << i+1 << Th.BTh.Number(tb)+1 << " " << det[1] << " " << det[2] <<endl; + } + } + assert(!k); + delete [] mark; + + + } + f << "\nEnd" << endl; + // Th.ConsLinkTriangle(); + delete [] reft; + return f; + +} + + + +void Geometry::Write(const char * filename) +{ + ofstream f(filename); + if (f) + { + if(verbosity>1) + cout << " -- write geometry in file " << filename << endl; + if (name) delete name; + name = new char[strlen(filename)+1]; + strcpy(name,filename); + OnDisk =1; + f << *this; + } +} + +ostream& operator <<(ostream& f, const Geometry & Gh) +{ + Int4 NbCorner=0; + { + f << "MeshVersionFormatted 0" <<endl; + f << "\nDimension\n" << 2 << endl; +// f << "\nIdentifier\n" ; +// WriteStr(f,Gh.identity); +// f <<endl; + } + int nbreqv=0; + { + + f.precision(12); + f << "\nVertices\n" << Gh.nbv <<endl; + for (Int4 i=0;i<Gh.nbv;i++) + { + GeometricalVertex & v = Gh.vertices[i]; + if (v.Required()) nbreqv++; + f << v.r.x << " " << v.r.y << " " << v.ref() << endl; + if (v.Corner()) NbCorner++; + } + } + + int nbcracked=0; + + { + int nbreq=0; + f << "\nEdges\n"<< Gh.nbe << endl; + for(Int4 ie=0;ie<Gh.nbe;ie++) + { + + GeometricalEdge & e = Gh.edges[ie]; + if (e.Required()) nbreq++; + if (e.Cracked()) { + Int4 ie1 = Gh.Number(e.link); + if (ie <= ie1) ++nbcracked;} + f << Gh.Number(e[0])+1 << " " << Gh.Number(e[1])+1; + f << " " << e.ref <<endl; + } + + if (nbcracked) + { + f << "\nCrackedEdges\n"<< nbcracked<< endl; + for(Int4 ie=0;ie<Gh.nbe;ie++) + { + GeometricalEdge & e = Gh.edges[ie]; + if (e.Cracked()) { + Int4 ie1 = Gh.Number(e.link); + if (ie <= ie1) f << ie+1 << " " << ie1+1<< endl; + } + } + } + if(nbreq) + { + f << "\nRequiredEdges\n"<< nbreq<< endl; + for(Int4 ie=0;ie<Gh.nbe;ie++) + { + GeometricalEdge & e = Gh.edges[ie]; + if (e.Required()) + f << ie+1 << endl; + } + } + + + + } + + f << "\nAngleOfCornerBound\n" + << Gh.MaximalAngleOfCorner*180/Pi << endl; + if (NbCorner) + { + f << "\nCorners\n" << NbCorner << endl; + for (Int4 i=0,j=0;i<Gh.nbv;i++) + { + GeometricalVertex & v = Gh.vertices[i]; + if (v.Corner()) + j++,f << Gh.Number(v)+1 << (j % 5 ? ' ' : '\n'); + } + + + } + + if(nbreqv) + { + f << "\nRequiredVertices\n"<< nbreqv<< endl; + for (Int4 j=0,i=0;i<Gh.nbv;i++) + { + GeometricalVertex & v = Gh.vertices[i]; + + if (v.Required()) + j++,f << i+1 << (j % 5 ? ' ' : '\n'); + } + f << endl; + } + + { + Int4 i; + f << "\nSubDomainFromGeom\n" ; + f << Gh.NbSubDomains<< endl; + for (i=0;i<Gh.NbSubDomains;i++) + f << "2 " << Gh.Number(Gh.subdomains[i].edge)+1 << " " << Gh.subdomains[i].sens + << " " << Gh.subdomains[i].ref << endl; + } + { + Int4 n=0,i; + + for(i=0;i< Gh.nbe;i++) + { + if(Gh.edges[i].TgA() && Gh.edges[i][0].Corner() ) + n++; + if(Gh.edges[i].TgB() && Gh.edges[i][1].Corner() ) + n++; + } + if (n) { + f << "TangentAtEdges " << n << endl; + for(i=0;i< Gh.nbe;i++) + { + if (Gh.edges[i].TgA() && Gh.edges[i][0].Corner() ) + f << i+1 << " 1 " << Gh.edges[i].tg[0].x + << " " << Gh.edges[i].tg[0].y << endl; + if (Gh.edges[i].TgB() && Gh.edges[i][1].Corner() ) + f << i+1 << " 2 " << Gh.edges[i].tg[1].x + << " " << Gh.edges[i].tg[1].y << endl; + } + + }} + // f << " Not Yet Implemented" << endl; + + return f; +} + + +} // end of namespace bamg diff --git a/contrib/bamg/bamglib/Meshgibbs.cpp b/contrib/bamg/bamglib/Meshgibbs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e9803afdbbb0077fb6e8babe6fe63dd625d15ba --- /dev/null +++ b/contrib/bamg/bamglib/Meshgibbs.cpp @@ -0,0 +1,1067 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <iostream> +#include <fstream> +using namespace std; +using namespace bamg; +#include "Mesh2.h" + +#define mmax(a,b)(a>b?a:b) +#define mmin(a,b)(a<b?a:b) +#define ffalse 0 +#define ttrue 1 + +/* -- translated by f2c (version of 23 May 1992 14:18:33). + You must link the resulting object file with the libraries: + -lF77 -lI77 -lm -lc (in that order) +*/ + + +#define integer long +#define logical long + +int gibbs1_(integer* n,integer* record,integer* ptvois); +int gibbs2_(integer* n,integer* record,integer* criter); +int gibbsa_(integer* n,integer* ptvois,integer* vois,integer* r,integer* m, + integer* nv,integer* nx,integer* ny,integer* nn,integer* w1,integer* w2, + integer* pfold,integer* pfnew,integer* impre,integer* nfout); +int gibbsb_(integer* x,integer* y,integer* n,integer* ptvois, + integer* vois,integer* nx,integer* ny,integer* nv,integer* nn,integer* m, + integer* wh,integer* wl,integer* r, integer* impre, integer* nfout); +int gibbsc_(integer* nz,integer* nv,integer* niveau,integer* n,integer* ); +int gibbsd_(integer* racine,integer* n,integer* ptvois,integer* + vois,integer* nv,integer* r,integer* niveau); +int gibbst_(integer* n,integer* p,integer* nv,integer* nn,integer* ptvois,integer* vois, + integer* m,integer* r,integer* new_,integer* option, + integer* pfnew,integer* impre,integer* nfout); + +/* Subroutine */ int gibbs1_(integer* n,integer* record,integer* ptvois) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + static integer crit, i, j, l, r, rec; + +/* ----------------------------------------------------------------------- + */ +/* routine appele par gibbs0 */ +/* ----------------------------------------------------------------------- + */ +/* but: trie record (ensemble de n sommet) telle que l'ordre des somm +*/ +/* soit croissant (ordre du sommet i est ptvois(i+1)-ptvois(i)) */ +/* ----------------------------------------------------------------------- + */ + + /* Parameter adjustments */ + --ptvois; + --record; + + /* Function Body */ + if (*n <= 1) { + return 0; + } + l = *n / 2 + 1; + r = *n; +L2: + if (l <= 1) { + goto L20; + } + --l; + rec = record[l]; + crit = ptvois[record[l] + 1] - ptvois[record[l]]; + goto L3; +L20: + rec = record[r]; + crit = ptvois[record[r] + 1] - ptvois[record[r]]; + record[r] = record[1]; + --r; + if (r == 1) { + goto L999; + } +L3: + j = l; +L4: + i = j; + j <<= 1; + if ((i__1 = j - r) < 0) { + goto L5; + } else if (i__1 == 0) { + goto L6; + } else { + goto L8; + } +L5: + if (ptvois[record[j] + 1] - ptvois[record[j]] < ptvois[record[j + 1] + 1] + - ptvois[record[j + 1]]) { + ++j; + } +L6: + if (crit >= ptvois[record[j] + 1] - ptvois[record[j]]) { + goto L8; + } + record[i] = record[j]; + goto L4; +L8: + record[i] = rec; + goto L2; +L999: + record[1] = rec; + return 0; +} /* gibbs1_ */ + +/* Subroutine */ int gibbs2_(integer* n,integer* record,integer* criter) +{ + static integer crit, i, j, l, r, rec; + + +/* trie record selon les valeurs de criter(record(.)) croissantes */ + + + /* Parameter adjustments */ + --criter; + --record; + + /* Function Body */ + if (*n <= 1) { + return 0; + } + l = *n / 2 + 1; + r = *n; +L2: + if (l <= 1) { + goto L20; + } + --l; + rec = record[l]; + crit = criter[rec]; + goto L3; +L20: + rec = record[r]; + crit = criter[rec]; + record[r] = record[1]; + --r; + if (r == 1) { + goto L999; + } +L3: + j = l; +L4: + i = j; + j <<= 1; + if (j - r < 0) { + goto L5; + } else if (j == r) { + goto L6; + } else { + goto L8; + } +L5: + if (criter[record[j]] < criter[record[j + 1]]) { + ++j; + } +L6: + if (crit >= criter[record[j]]) { + goto L8; + } + record[i] = record[j]; + goto L4; +L8: + record[i] = rec; + goto L2; +L999: + record[1] = rec; + return 0; +} /* gibbs2_ */ + +/* Subroutine */ +int gibbsa_(integer* n,integer* ptvois,integer* vois,integer* r,integer* m, + integer* nv,integer* nx,integer* ny,integer* nn,integer* w1,integer* w2, + integer* pfold,integer* pfnew,integer* impre,integer* nfout) +{ + /* System generated locals */ + integer i__1, i__2, i__3, i__4; + + /* Builtin functions */ + /* Subroutine */ int s_stop(); + + /* Local variables */ + static integer nbcc, degi, bold, bnew, i, j, k, p, degre, x, y, p1, p2; +/* extern Subroutine int gibbs1_();*/ + static integer pf; +/* extern Subroutine int gibbsb_(), gibbsd_(), gibbst_();*/ + static integer nbpass, niveau, pf1, option, old, new_, opt, new1; + +/* ----------------------------------------------------------------------- + */ +/* but: calculer une renumerotation des sommets d'un graphe defini par: +*/ +/* par la methode de gibbs */ +/* ----------------------------------------------------------------------- + */ +/* entree */ +/* -------- */ +/* n = nb de sommet du graphe */ +/* les voisins d'un sommet i ont pour numero : */ +/* ( vois(j) , j=ptvois(i),ptvois(i+1)-1 ) */ + +/* impre parametre d'impression */ +/* nfout numero du fichier pour impression */ + +/* sortie */ +/* ------ */ +/* r(1:n) tableau donnant la nouvelle numerotation: */ +/* r(i) = nouveau numero du sommet i */ +/* pfolf = ancien profile */ +/* pfnew = nouveau profile */ + +/* tableau de travail : */ +/* -------------------- */ +/* m(n) */ +/* nv(0:n+n) */ +/* nx(n) */ +/* ny(n) */ +/* nn(0:n) */ +/* w1(n) */ +/* w2(n) */ + +/* ----------------------------------------------------------------------- + */ +/* programmeur f. hecht le 3/02/1987 */ +/* ----------------------------------------------------------------------- + */ + +/* tri des voisins d'un sommet du graphe par degre croissant */ +/* --------------------------------------------------------------- */ + /* Parameter adjustments */ + --w2; + --w1; + --ny; + --nx; + --m; + --r; + --vois; + --ptvois; + + /* Function Body */ + p2 = ptvois[1] - 1; + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + p1 = p2 + 1; + p2 = ptvois[i + 1] - 1; + i__2 = p2 - p1 + 1; + gibbs1_(&i__2, &vois[p1], &ptvois[1]); +/* if(impre.le.-9) then */ +/* write (nfout,*) 'les voisin de ',i,'sont: ', (vois(j),j=p1,p +2) */ +/* endif */ +/* L10: */ + } + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + r[i] = 0; +/* L20: */ + } +/* boucle sur les composante connexe du graphe */ + new_ = 0; + nbcc = 0; +L30: + if (new_ < *n) { + ++nbcc; +/* recherche d'une racine y (un sommet non numerote) de degree m +ini */ + y = 0; + degre = *n + 1; + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + if (r[i] <= 0) { + degi = ptvois[i + 1] - ptvois[i]; + if (degi < degre) { + degre = degi; + y = i; + } + } +/* L40: */ + } + if (y == 0) { + return -3;/* s_stop("fatal erreur gibbs 2 : pb racine", 33L); */ + } + gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau); + nbpass = 0; +L50: + ++nbpass; + x = y; + p = niveau; + k = 0; + i__1 = nv[p + 1]; + for (i = nv[p] + 1; i <= i__1; ++i) { + ++k; + m[k] = nv[i]; +/* L60: */ + } + gibbs1_(&k, &m[1], &ptvois[1]); + i__1 = k; + for (i = 1; i <= i__1; ++i) { + y = m[i]; + gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau); + if (niveau > p) { + goto L50; + } +/* L70: */ + } + y = m[1]; +/* if(impre.lt.0) then */ +/* write(nfout,*) */ +/* + ' nb de pass pour trouver le pseudo diametre',nbpass */ +/* + ,' x=',x,',y=',y,' de la composante connexe ',nbcc */ + +/* write (nfout,*) ('-',i=1,78) */ +/* endif */ +/* optimisation de la descendance de la numerotation */ +/* ------------------------------------------------- */ + gibbsb_(&x, &y, n, &ptvois[1], &vois[1], &nx[1], &ny[1], nv, nn, &m[1] + , &w1[1], &w2[1], &r[1], impre, nfout); + +/* renumerotation de cuthill mac kee avec la meilleur des 4 option +s */ +/* -------------------------------------------------------------- +--- */ + pf = 1073741824; + option = -2; + new1 = new_; + for (opt = -2; opt <= 2; ++opt) { + new_ = new1; + if (opt != 0) { + gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], & + new_, &opt, &pf1, impre, nfout); + if (pf1 < pf) { + pf = pf1; + option = opt; + } + } +/* L80: */ + } +/* if(impre.ne.0) write (nfout,*) ' on a choisi l''option ', + */ +/* + option,', new =',new */ + new_ = new1; + gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], &new_, & + option, &pf1, impre, nfout); + goto L30; + } +/* if(impre.ne.0) write(nfout,*) */ +/* + ' nb de composante connexe du graphe =',nbcc */ +/* calcul du profile */ + *pfold = 0; + *pfnew = 0; + bnew = 0; + bold = 0; + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + old = i; + new_ = r[i]; + i__2 = ptvois[i + 1] - 1; + for (j = ptvois[i]; j <= i__2; ++j) { +/* Computing MIN */ + i__3 = old, i__4 = vois[j]; + old = mmin(i__3,i__4); +/* Computing MIN */ + i__3 = new_, i__4 = r[vois[j]]; + new_ = mmin(i__3,i__4); +/* L100: */ + } + *pfold = *pfold + i - old + 1; +/* Computing MAX */ + i__2 = bold, i__3 = i - old + 1; + bold = mmax(i__2,i__3); + *pfnew = *pfnew + r[i] - new_ + 1; +/* Computing MAX */ + i__2 = bnew, i__3 = r[i] - new_ + 1; + bnew = mmax(i__2,i__3); +/* L110: */ + } +/* if(impre.ne.0) then */ +/* write(nfout,*)'profile old = ',pfold,', profile new = ',pfnew + */ +/* write(nfout,*)'1/2 bande old = ',bold ,', 1/2 band new = ',bnew +*/ +/* endif */ +return 0; +} /* gibbsa_ */ + +/* Subroutine */ int gibbsb_(integer* x,integer* y,integer* n,integer* ptvois, +integer* vois,integer* nx,integer* ny,integer* nv,integer* nn,integer* m, +integer* wh,integer* wl,integer* r, integer* impre, integer* nfout) +{ + /* System generated locals */ + integer i__1, i__2; + + /* Local variables */ + static flag_; + static integer i, j, k, p, s, h0, i1, l0, i2; +/* extern Subroutine int gibbs1_(); */ + static integer lg; +/* extern Subroutine int gibbsd_(), gibbsc_();*/ + static integer niveau, mxcanx, mxcany, nbc; + +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + */ +/* ...................................................................... +*/ +/* attention on met la descente optimiser dans r <0 ou nulle */ +/* ....................................................................... + */ + /* Parameter adjustments */ + --r; + --m; + --ny; + --nx; + --vois; + --ptvois; + + /* Function Body */ + gibbsd_(y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau); + gibbsc_(&ny[1], nv, &niveau, n, &mxcany); + gibbsd_(x, n, &ptvois[1], &vois[1], nv, &r[1], &niveau); + p = niveau; + gibbsc_(&nx[1], nv, &niveau, n, &mxcanx); + flag_ = ffalse; + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + if (nx[i] + ny[i] == p) { + r[i] = -nx[i]; + } else if (nx[i] >= 0) { + flag_ = ttrue; + r[i] = -1073741824; + } else { + if (r[i] <= 0) { + r[i] = -1073741822; + } + } +/* L20: */ + } + if (flag_) { +/* calcul des composantes connexe du graphe sans les sommets de +nn */ +/* ------------------------------------------------------------ +--- */ + j = *n; + k = 0; + nbc = 0; + nv[nbc] = j; +L30: + ++k; + if (k <= *n) { + if (r[k] == -1073741824) { +/* recherche de la fermeture transitive partant de k + */ + ++nbc; + i = -1; + s = k; +L40: + ++i; + wl[i] = ptvois[s]; + wh[i] = ptvois[s + 1]; + ++j; + nv[j] = s; + r[s] = -1073741823; +L50: + if (i >= 0) { + if (wl[i] < wh[i]) { + s = vois[wl[i]]; + ++wl[i]; + if (r[s] == -1073741824) { + goto L40; + } + goto L50; + } + --i; + goto L50; + } + nv[nbc] = j; + m[nbc] = nbc; + } + goto L30; + } +/* if(impre.lt.0) write(nfout,*) */ +/* + ' nb de composante connexe du graphe reduit =',nbc */ + +/* --------------- fin de construction des composantes connexes------ +--- */ +/* nv(0)=n */ +/* if(impre.le.-10) write(nfout,5555)'nv(0:n+n) = ',(nv(i),i=0, +n+n) */ + gibbs1_(&nbc, &m[1], nv); +/* if(impre.le.-10)write(nfout,5555)'trie m =',(m(i),i=1,nbc) +*/ + i__1 = p; + for (i = 0; i <= i__1; ++i) { + nn[i] = 0; +/* L60: */ + } + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + j = -r[i]; + if (j >= 0 && j <= p) { + ++nn[j]; + } +/* L70: */ + } + +/* boucle sur les composante connexes par ordre croissantes */ +/* -------------------------------------------------------- */ + for (k = nbc; k >= 1; --k) { + i = m[k]; + i1 = nv[i - 1] + 1; + i2 = nv[i]; + lg = i2 - i1 + 1; +/* if(impre.le.-7) */ +/* + write(nfout,*) k,' composante ',i,',lg=',lg,',i1,i2 +=',i1,i2 */ +/* if(impre.le.-8) */ +/* + write (nfout,5555)' ',(nv(i),i=i1,i2) */ + h0 = 0; + l0 = 0; + i__1 = p; + for (j = 0; j <= i__1; ++j) { + wh[j] = nn[j]; + wl[j] = nn[j]; +/* L90: */ + } + i__1 = i2; + for (i = i1; i <= i__1; ++i) { + s = nv[i]; + ++wh[nx[s]]; + ++wl[p - ny[s]]; +/* L100: */ + } + i__1 = p; + for (j = 0; j <= i__1; ++j) { + if (wh[j] != nn[j]) { +/* Computing MAX */ + i__2 = wh[j]; + h0 = mmax(i__2,h0); + } + if (wl[j] != nn[j]) { +/* Computing MAX */ + i__2 = wl[j]; + l0 = mmax(i__2,l0); + } +/* L110: */ + } + if (h0 < l0 || h0 == l0 && mxcanx <= mxcany) { +/* if(impre.le.-2) write(nfout,*) */ +/* + ' h0 = ',h0,',l0 = ',l0,' ------- XXXX + --------' */ + i__1 = i2; + for (i = i1; i <= i__1; ++i) { + s = nv[i]; + r[s] = -nx[s]; + ++nn[-r[s]]; +/* L120: */ + } + } else { +/* if (impre.le.-2) write(nfout,*) */ +/* + ' h0 = ',h0,',l0 = ',l0,' ------- YYYY + --------' */ + i__1 = i2; + for (i = i1; i <= i__1; ++i) { + s = nv[i]; + r[s] = -p + ny[s]; + ++nn[-r[s]]; +/* L130: */ + } + } +/* L140: */ + } + } +/* on met les nouveaux niveaux de la descendance optimiser dans nn */ +/* ----------------------------------------------------------------- +*/ + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + if (r[i] > 0) { + nn[i] = -1; + } else if (r[i] == -1073741822) { + nn[i] = -2; + } else { + nn[i] = -r[i]; + } +/* L150: */ + } +/* if(impre.le.-10)write (nfout,5555)' nn(i)=',(nn(i),i=1,n) */ +/* 5555 format(' -------- ',a,/,5(15x,10(i5)/)) */ +return 0;} /* gibbsb_ */ + +/* Subroutine */ int gibbsc_(integer* nz,integer* nv,integer* niveau,integer* n,integer* mxz) +{ + /* System generated locals */ + integer i__1, i__2, i__3; + + /* Local variables */ + static integer i, j; + +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + */ + /* Parameter adjustments */ + --nz; + + /* Function Body */ + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + nz[i] = -1; +/* L10: */ + } + *mxz = 0; + i__1 = *niveau; + for (i = 0; i <= i__1; ++i) { +/* Computing MAX */ + i__2 = *mxz, i__3 = nv[i + 1] - nv[i]; + *mxz = mmax(i__2,i__3); + i__2 = nv[i + 1]; + for (j = nv[i] + 1; j <= i__2; ++j) { + nz[nv[j]] = i; +/* L20: */ + } + } +return 0;} /* gibbsc_ */ + +/* Subroutine */ int gibbsd_(integer* racine,integer* n,integer* ptvois,integer* vois,integer* nv,integer* r,integer* niveau) +{ + /* System generated locals */ + integer i__1, i__2; + + /* Local variables */ + static integer i, k, s, sv, stk, stk1, stk2; + +/* ----------------------------------------------------------------------- + */ +/* but construire la structure des descendant de racine du graphe */ +/* ----------------------------------------------------------------------- + */ +/* sortie : */ +/* -------- */ +/* nv est la structure des niveaux */ +/* les sommets du niveau (i =0,niveau_ sont defini par : */ +/* (nv(j),j=nv(i),nv(i+1)-1) */ + +/* le tableau r(i) n'est modifier que sur les sommets */ +/* de la composante connexe du graphe contenant la racine */ + +/* ----------------------------------------------------------------------- + */ + +/* on demark tout les sommets non remuneroter */ +/* -------------------------------------------------- */ + /* Parameter adjustments */ + --r; + --vois; + --ptvois; + + /* Function Body */ + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + if (r[i] < 0) { + r[i] = 0; + } +/* L10: */ + } + +/* initialisation */ + + stk = *n - 1; + nv[0] = stk; + stk2 = stk; + *niveau = 0; + ++stk; + nv[stk] = *racine; + r[*racine] = -1; +L20: + if (stk2 < stk) { + ++(*niveau); + stk1 = stk2 + 1; + nv[*niveau] = stk; + stk2 = stk; +/* print *,' ------- niveau =',niveau,' stk=',stk1,stk2 */ + i__1 = stk2; + for (k = stk1; k <= i__1; ++k) { + s = nv[k]; +/* print *,'----------------- s=',s */ + i__2 = ptvois[s + 1] - 1; + for (i = ptvois[s]; i <= i__2; ++i) { +/* pour tout les sommets (sv) voisin */ +/* d'un sommet (s) du niveau precedent */ + sv = vois[i]; +/* print *,' voisin =',sv */ +/* si le sommet n'est pas marque on le marque et + on l'ajout */ + if (r[sv] == 0) { + ++stk; + nv[stk] = sv; + r[sv] = -1; + } +/* L30: */ + } +/* L40: */ + } + goto L20; + } + --(*niveau); +/* call pnv(' gibbsd ',n,nv,niveau) */ +return 0;} /* gibbsd_ */ + + +/* Subroutine */ int gibbst_(integer* n,integer* p,integer* nv,integer* nn,integer* ptvois,integer* vois,integer* m,integer* r,integer* new_,integer* option, + integer* pfnew,integer* impre,integer* nfout) +{ + /* System generated locals */ + integer i__1, i__2, i__3, i__4, i__5; + + /* Local variables */ + static integer nbsc, bnew, knew, step, plus, i, j, k, s, debut, i1, i2; +/* extern Subroutine int gibbs2_();*/ + static integer fin; + + +/* construction de la stucture de niveau dans nv a partir de nn */ +/* ------------------------------------------------------------ */ + /* Parameter adjustments */ + --r; + --m; + --vois; + --ptvois; + + /* Function Body */ + nv[0] = *n; + i__1 = *p + 1; + for (i = 1; i <= i__1; ++i) { + nv[i] = 0; +/* L150: */ + } + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + if (nn[i] >= 0) { + ++nv[nn[i] + 1]; + } +/* L160: */ + } + i__1 = *p; + for (i = 0; i <= i__1; ++i) { + nv[i + 1] += nv[i]; +/* L170: */ + } + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + if (nn[i] >= 0) { + j = nn[i]; + ++nv[j]; + nv[nv[j]] = i; + } +/* L180: */ + } + for (i = *p; i >= 0; --i) { + nv[i + 1] = nv[i]; +/* L190: */ + } + nv[0] = *n; + nbsc = nv[*p + 1] - nv[0]; +/* --- fin de la construction ------------------------------------ */ + if (*option == -2) { + i__1 = *impre - 1; + } + i__1 = *n; + for (i = 1; i <= i__1; ++i) { + m[i] = *n * 3 + ptvois[i + 1] - ptvois[i]; +/* L10: */ + } + if ((((int)*option) == 1)||(((int)*option) == -1)) { + debut = 0; + fin = *p; + step = 1; + } else { + debut = *p; + fin = 0; + step = -1; + } + i__1 = fin; + i__2 = step; + for (i = debut; i__2 < 0 ? i >= i__1 : i <= i__1; i += i__2) { + i1 = nv[i] + 1; + i2 = nv[i + 1]; + i__3 = i2 - i1 + 1; + gibbs2_(&i__3, &nv[i1], &m[1]); + i__3 = i2; + for (j = i1; j <= i__3; ++j) { + s = nv[j]; + i__4 = ptvois[s + 1] - 1; + for (k = ptvois[s]; k <= i__4; ++k) { +/* Computing MIN */ + i__5 = m[vois[k]]; + m[vois[k]] = mmin(i__5,j); +/* L20: */ + } +/* L30: */ + } +/* L40: */ + } + if (*option > 0) { + knew = *new_; + plus = 1; + } else { + knew = *new_ + nbsc + 1; + plus = -1; + } + *new_ += nbsc; +/* if(option.gt.0) then */ +/* do 60 k = debut , fin , step */ +/* do 60 j = nv(k+1),nv(k)+1,-1 */ +/* knew = knew + plus */ +/* r(nv(j)) = knew */ +/* 60 continue */ +/* else */ + i__2 = fin; + i__1 = step; + for (k = debut; i__1 < 0 ? k >= i__2 : k <= i__2; k += i__1) { + i__3 = nv[k + 1]; + for (j = nv[k] + 1; j <= i__3; ++j) { + knew += plus; + r[nv[j]] = knew; +/* L70: */ + } + } +/* endif */ + *pfnew = 0; + bnew = 0; + i__3 = *n; + for (i = 1; i <= i__3; ++i) { + k = r[i]; + if (k > 0) { + i__1 = ptvois[i + 1] - 1; + for (j = ptvois[i]; j <= i__1; ++j) { + if (r[vois[j]] > 0) { +/* Computing MIN */ + i__2 = k, i__4 = r[vois[j]]; + k = mmin(i__2,i__4); + } +/* L100: */ + } + *pfnew = *pfnew + r[i] - k + 1; +/* Computing MAX */ + i__1 = bnew, i__2 = r[i] - k + 1; + bnew = mmax(i__1,i__2); + } +/* L110: */ + } +/* if(impre.lt.0.or.impre.gt.2) then */ +/* write(nfout,*) ' option =',option,', profile =',pfnew */ +/* + ,', 1/2 bande =',bnew,', new=',new,', nbss composante=',nbsc + */ +/* endif */ +return 0;} /* gibbst_ */ + +/* function */ +int Triangles::gibbsv (integer* ptvoi, + integer* vois,integer* lvois,integer* w,integer* v) +{ + /* System generated locals */ + integer i__2; + + /* Local variables */ + integer i, j, k, T, ss, iii, ptv, ptv1; + integer nbss = nbv; + /*--- Prepare les donees pour gibbsa en construisant ptvoi, vois, lvois - + ------------*/ + /* in */ + /* --- nbnt =3 pour des triangles 2D, */ + /* nbt = nb de triangle */ + /* nbss = nb de sommets */ + /* nsea = numeros de 3 sommets de chaque triangle (me) */ + /* out */ + /* --- ptvoi, vois, lvois, err */ + /* tableaux de travail w, v */ + /*----------------------------------------------------------------------- + ----------*/ + /* Parameter adjustments */ + --v; + --w; + --vois; + --ptvoi; + long nt = nbt-NbOutT; + /* Function Body */ + for (i = 1; i <= nbss; ++i) { + w[i] = -1; + ptvoi[i] = 0; } + ptvoi[nbss + 1] = 0; + for (i = 0; i < nt; ++i) + { + assert(triangles[i].link); + for (j = 0; j < 3; ++j) + { + ss = Number(triangles[i][j])+1; + ++ptvoi[ss + 1]; + w[ss] = 0; + } + } + + for (i = 1; i <= nbss; ++i) + ptvoi[i + 1] += ptvoi[i]; + + for (i = 0; i < nt; ++i) + if (triangles[i].link) + for (j = 0; j < 3; ++j) + { + ss = Number(triangles[i][j])+1; + ++ptvoi[ss]; + v[ptvoi[ss]] = i; + } + + ptv1 = 0; + iii = 1; + for (i = 1; i <= nbss; ++i) { + ptv = ptv1 + 1; + ptv1 = ptvoi[i]; + ptvoi[i] = iii; + i__2 = ptv1; + for (j = ptv; j <= i__2; ++j) { + T = v[j]; + for (k = 0; k < 3; ++k) { + ss = Number(triangles[T][k])+1; /* nsea[k + T * nsea_dim1]; */ + if (w[ss] != i) { + w[ss] = i; + if (iii > *lvois) return 2 ; + /* print*,'pas assez de place memoire' */ + + vois[iii] = ss; + ++iii;} + } + } + } + ptvoi[nbss + 1] = iii; + *lvois = iii - 1; + return 0; /* OK */ + return 0;} /* gibbsv_ */ + +int Triangles::gibbs() +/* -------- + renumber vertices by gibbs method; updates triangle and edge array + in: mesh + out: mesh + auxiliary arrays: ptvois,vois,r,m,nv,nx,ny,nn,w1,w2,f + all of size nv+1 except vois (10(nv+1)) and nv (2(nv+1)) + err = -1 : memory alloc pb; err = -3: fatal erreur gibbs 2 : pb racine +*/ +{ + long nv = nbv; + long nt = nbt-NbOutT; + long i, j, pfold, pfnew; + long* ptvois=NULL; + long* vois=NULL; + long* nn =NULL; + long* r =NULL; + long* m =NULL; + long* nnv =NULL; + long* nx =NULL; + long* ny =NULL; + long* w1 =NULL; + long* w2=NULL; + long nbvoisin = 10*nv; + long printint=0, iodev=6; + int err=0; + ptvois = new long[nv+1]; //(long*)calloc((long)(nv + 1) , sizeof(long)); + nn = new long[3*nt]; //(long*)calloc(3 * nt ,sizeof(long)); + vois = new long[nbvoisin+10]; //(long*)calloc((long)(nbvoisin + 10) , sizeof(long)); + r = new long[nv+1]; //(long*)calloc((long)(nv + 1) , sizeof(long)); + if((!ptvois)||(!nn)||(!vois)||(!r)) return -1; + err = gibbsv(ptvois,vois,&nbvoisin,r,nn) ; + delete [] nn; // free(nn); + if(err==0) + { + m = new long[nv+1]; + nn = new long[nv+1]; + nnv = new long[(nv+1)<<1]; + nx = new long[nv+1]; + ny = new long[nv+1]; + w1 = new long[nv+1]; + w2 = new long[nv+1]; + long lnv = nv; + err = gibbsa_ (&lnv, ptvois, vois, r, m, nnv, nx, ny, nn, w1, w2, &pfold, &pfnew, + &printint, &iodev); + delete [] m; + delete [] nnv; + delete [] nn; + delete [] nx; + delete [] ny; + delete [] w1; + delete [] w2; + } + + delete [] vois; + delete [] ptvois; + /* + if (err == 0 && (pfnew <= pfold)) + { + A<bVertex> f(nv); + for (i = 0; i < nv; ++i) + { f[i].x = v[i].x; + f[i].y = v[i].y; + f[i].where = v[i].where; + } + for (i = 0; i < nv; ++i) + { v[r[i] - 1].x = f[i].x; + v[r[i] - 1].y = f[i].y; + v[r[i] - 1].where = f[i].where; + } + + for (j = 0; j < nt; ++j) // updates triangle array + for (i = 0; i < 3; i++) + t[j].v[i] = &v[r[no(t[j].v[i])] - 1]; + + for (j = 0; j < ne; ++j) // updates edge array + { + e[j].in = &v[r[no(e[j].in)] - 1]; + e[j].out = &v[r[no(e[j].out)] - 1]; + } + f.destroy(); + if (!NumThinGrid) + { NumThinGrid= new int [nv]; + for (i=0;i<nv;i++) NumThinGrid[i]=i;// Same numbering + } + for (i=0;i<nv;i++) NumThinGrid[i]=r[NumThinGrid[i]]-1; + + } + */ + delete [] r; + return err; +} + +/* message d'erreur: *err = 2; print*,'pas assez de place memoire' */ diff --git a/contrib/bamg/bamglib/Meshio.cpp b/contrib/bamg/bamglib/Meshio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e7ac404e044541b8d68a630fec1543f6eb63dd8 --- /dev/null +++ b/contrib/bamg/bamglib/Meshio.cpp @@ -0,0 +1,373 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#include "meshtype.h" +#include "Meshio.h" +namespace bamg { + +const char *OFortranUnFormattedFile::unkown("unkown file name"); +void (*MeshIstreamErrorHandler)(ios & ) =0; +/////////////////////////////////////////////////////////// + void WriteStr(ostream & out,char * str) +{ + int i=0; + char c; + out << '"' ; + while (i++,c=*str++) { + if (i==70) + cout << " //\n",i=0; + if (c == '"') out << "\"\"" ; + else out << c ;} + out << '"' ; +} +/////////////////////////////////////////////////////////// +double * ReadbbFile(const char * file,long & nbsol,long & lsol,const int typesol,const int dim) +{ + + MeshIstream frbb(file); + int dimlu,typesollu; + long i; + double *sol =0; + frbb >> dimlu >> nbsol >> lsol >> typesollu ; + if(typesol != typesollu ) + { + cerr << " incorrect type of solution (read) " << typesollu << " != (wanted) " << typesol << endl; + cerr << " or dim of solution (read) " << dimlu << " != (wanted) " << dim << endl; + nbsol=0; + lsol=0; + } + else + { + sol = new double[lsol*nbsol]; + double *s=sol; + for( i=0;i<lsol;i++) + for (long j=0;j<nbsol;j++) + frbb >> *s++ ; + // frbb.close(); + } + + + return sol; +} + +/////////////////////////////////////////////////////////// +double * ReadBBFile(const char * file,long & nbsol,long & lsol,int *& typesols, + const int dim,const int typesol) +{ + + MeshIstream frbb(file); + int dimlu,typesollu; + typesols = 0; + long i,n=0; + double *sol =0; + int sizeoftype[] = { 1, dim ,dim * (dim+1) / 2, dim * dim } ; + // char * charoftype[] = { "Scalar" , "dim Vector" ,"dim x dim Sym-Matric","dim x dim Full-Matric" } ; + frbb >> dimlu >> nbsol ; + typesols = new int [nbsol] ; + for (i=0;i<nbsol;i++) + { + frbb >> typesols[i]; + typesols[i]--; + if (typesols[i]<0 || typesols[i]>= 4) + { + cerr << " Error reading BBFile the type solution " << i+1 << " is " << typesols[i]+1 + << " is not in [1..4] " << endl; + frbb.ShowIoErr(998); + nbsol=0; + lsol=0; + delete [] typesols; + typesols=0; + return 0; + } + n += sizeoftype[ typesols[i]]; + } + frbb >> lsol >> typesollu ; + if(typesol != typesollu ) + { + cerr << " incorrect type of solution (read) " << typesollu << " != (wanted) " << typesol << endl; + cerr << " or dim of solution (read) " << dimlu << " != (wanted) " << dim << endl; + frbb.ShowIoErr(999); + nbsol=0; + lsol=0; + } + else + { + if (verbosity> 5) + cout << " read BB file " << file << " with nbsol " << nbsol << " total nb of field = " << n << endl; + if (verbosity>9) + for (i=0;i<nbsol;i++) + cout << " the type of solution " << i+1 << " is " << sizeoftype[ typesols[i]] + << " and the number of sub-field are " << sizeoftype[ typesols[i]] << endl; + sol = new double[lsol*n]; + double *s=sol; + for( i=0;i<lsol;i++) + for (long j=0;j<n;j++) + frbb >> *s++ ; + // frbb.close(); + } + + + return sol; +} + + +void MeshIstream::ShowIoErr(int s) { + LineError = 1; + if (CurrentFile) + cerr << " In file " << CurrentFile ; + cerr << ", Erreur Lecture " << s << + ", good=" << (s & ios::goodbit) << + ", bad=" << (s & ios::badbit) << + ", fail=" << (s & ios::failbit) << + ", eof=" << (s & ios::eofbit) << " Line " << LineNumber << + endl; + if(!in.eof()) + { + in.clear(ios::goodbit); + int i=0; + char c; + cerr << " the next character :" ; + while (i++<80 && in.get(c) && (c != '\n' || i < 30 )) + cerr.put(c); + cerr << endl; + } + if (MeshIstreamErrorHandler) + MeshIstreamErrorHandler(in); + else + { + in.clear(ios::failbit); + } +} +int MeshIstream::IsString(const char* s) +{ + int n=0; + char c; + const char * ss = s; + while (in.get(c) && c ==' ') n++; // eat whitespace + if (in.good()) + while ( *ss && c == *ss && in.get(c) ) + ss++; + + if (*ss) { // no + if (verbosity>9) + cout << "IsString: not " << s << " " << n << " putback " << ss-s << " :" << c ; + if (in.good()) + in.putback(c),ss--; + while(ss-s>0) + { + cout << *ss ; + in.putback(*ss--); + }; + if (verbosity>9) + cout << ":"<< endl; + return 0;} + else return 1; +} + + char * MeshIstream::ReadStr() +{ + static char buf[1025]; + int instr=0,k=0; + char * b=buf, bb=0, *bend=buf+1023; + + for (b=buf;b<bend && in.get(*b);instr && b++) + { + int kold = k; + if(isspace(*b)) + { + if (*b == '\n') LineNumber++; + if (instr && !bb) break; + } + else if (*b == bb) + { + if(++k%2) b--; + } + else if( !instr) + { + instr =1; + if ((*b == '"') || (*b == '\'' ) ) + bb=*b--,k=0; + } + else + instr =1; + + if( k%2 && kold==k ) // even and fin + break; + } + *b=0; + in.clear(ios::goodbit); + // cout << " l = " << b-buf << " " ; + char * r = new char [b-buf+1]; + strcpy(r,buf); + return r ; +} +/////////////////////////////////////////////////////////// +OFortranUnFormattedFile::~OFortranUnFormattedFile() +{ + // save the last record + if (l==0) { // l rec no set -- + l=where(); + if (verbosity>9) + cout << " size of last record = " + << l << " n = " << nb_rec << " i= " << i << endl; + if (!f->good()) Error(3); + f->seekp(i-sizeof(long)); + if (!f->good()) Error(3); + f->write((char*)&l,sizeof(l)); + if (!f->good()) Error(3); + n=j; + } + + f->seekp(n); + if (!f->good()) Error(3); + f->write((char*) &l,sizeof(l)); + if (!f->good()) Error(3); + + if (f && to_close) { + if (verbosity>9) + cout << "delete OFortranUnFormattedFile " << file_name + << " @end = " << n << endl; + delete f;} f=0; +} + +IFortranUnFormattedFile::~IFortranUnFormattedFile() +{ + if (f && to_close) { + if (verbosity>9) + cout << " delete IFortranUnFormattedFile" << file_name + << " @end = " << n << endl; + delete f;} f=0; +} + +long IFortranUnFormattedFile::Record() +{ + nb_rec++; + n += sizeof(long); + f->seekg(n); + f->read((char*)&l,sizeof(l)); + if (!f->good()) Error(3); + i=j= n+sizeof(l); + n += l + sizeof(l) ; // end + if (verbosity>9) + cout << " Read rec end =" << n << " l= " << l + << " current= " << j << " begin= " << i << endl; + return l; +} + +long OFortranUnFormattedFile::Record(long ll) // +{ + if (j==4 && l==0) + { + l=ll; + f->seekp(0); + f->write((char*)&ll,sizeof(l)); + if (!f->good()) Error(3); + return 0; + } + if (n>=0) + { + if (l==0) + { // l rec no set -- + l=where(); + if (verbosity>9) + cout << " set len of rec " << nb_rec << " = " << l + << " @ " << i-sizeof(long) << endl; + + f->seekp(i-sizeof(long)); + f->write((char*)&l,sizeof(l)); + n=j; + } + f->seekp(n); + f->write((char*)&l,sizeof(l)); + if (!f->good()) Error(3); + } + else + f->seekp(0); + n += sizeof(long); + nb_rec++; + f->write((char*)&ll,sizeof(l)); + if (!f->good()) Error(3); + + l=ll; + n += sizeof(long); + j = n; + i = n; + n += l; + if (verbosity>9) + cout << " Write rec end =" << n << " l= " << l + << " current= " << j << " begin= " << i << endl; + return l; +} +void OFortranUnFormattedFile::Error(int err) +{ + cerr << "Fatal Error Output FortranUnFormattedFile " << endl; + if (err==0) + cerr << "-- Error openning "; + else if (err==1) + cerr<< "-- OverFlow write "; + else if (err==2) + cerr<< "-- Erreur write " ; + else if (err==3) + cerr<< "-- Erreur write record info " ; + else + cerr << " unkown err " << err ; + + cerr << " Record number = " << nb_rec << endl + << " read position in file " << j << " < " << n + << " = end on record " << endl; + cerr << " position in the record = " << where() + << " length of record = " << l <<endl; + cerr << " file = " << file_name<< endl ; + MeshError(900); + // throw(ErrorMesh("exit",1)); +} +void IFortranUnFormattedFile::Error(int err) +{ + cerr << "Fatal Error Input FortranUnFormattedFile " << endl; + if (err==0) + cerr << " Error openning "; + else if (err==1) + cerr<< " OverFlow read"; + else if (err==2) + cerr<< " Erreur read" ; + else if (err==3) + cerr<< " Erreur read record info " ; + else + cerr << " unkown err " << err ; + + cerr << " Record number = " << nb_rec << endl + << " read position in file " << j << " < " << n + << " = end on record " << endl; + cerr << " position in the record = " << where() + << " length of record = " << l <<endl; + cerr << " file = " << file_name<< endl ; + MeshError(900); + // throw(ErrorMesh("exit",1)); +} + +}// end of namespace bamg diff --git a/contrib/bamg/bamglib/Meshio.h b/contrib/bamg/bamglib/Meshio.h new file mode 100644 index 0000000000000000000000000000000000000000..7c12651075bdcfb8cf8b1c2dfd8a0d2e77598b57 --- /dev/null +++ b/contrib/bamg/bamglib/Meshio.h @@ -0,0 +1,245 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#include <cstdio> +#include <iostream> +#include <fstream> +#include "error.hpp" +#include <cstring> +#include <cstdlib> +#include <cctype> +using namespace std; +// PB compilo HP aCC +#if defined(__hpux) || defined(__SUNPRO_CC) +#define IOS_OPENMODE int +#else +#define IOS_OPENMODE ios::openmode +#endif +extern long verbosity ; + +namespace bamg { + + +extern void (*MeshIstreamErrorHandler)(ios & ); + +void WriteStr(ostream & out,char * str); + +double * ReadbbFile(const char * file,long & nbsol,long & lsol,const int dim=2,const int typesol=2); +double * ReadBBFile(const char * file,long & nbsol,long & lsol,int *& typesols,const int dim=2,const int typesol=2); +// solution at vertex (P1) + +union Char4orLong { char c[4]; long l;} ; + +class MeshIstream { +public: + istream & in ; + const char * CurrentFile; + // ifstream fin; + int LineNumber,LineError,opened; + + + istream & cm ()// mange les blancs et les commentaire + { + char c; + int cmm=0; + while ( in.get(c) && + ( isspace(c) ? + (( ( c=='\n'|| c==char(12) || c==char(15)) && (LineNumber++,cmm=0)),1) + : (cmm || (c=='#' && (cmm=1) )) ) + ) ((void ) 0); + if (in.good()) in.putback(c); + return in; + } + + // void rewind(){ fin.clear();fin.seekg(0);} + + void eol()// go to end of line + { + char c; + while ( in.get(c) && ( c!='\n') && ( c!='\r')) (void) 0; + } + void ShowIoErr(int ); + MeshIstream & err () + { + if ( ! in.good() ) ShowIoErr(in.rdstate()); + return *this; + } + // MeshIstream(istream & i): in(i),CurrentFile(0),LineNumber(1),LineError(0) {} + + MeshIstream(const char * file_name) + : in(*new ifstream(file_name)),CurrentFile(file_name), LineNumber(1),LineError(0) + { if (!in) {cerr << " Error Opening file " << file_name,CurrentFile=0;ShowIoErr(1);} + if(verbosity>4) cout << " Openfile : " << file_name << endl;err(); } + + /* // void close() + { + if (CurrentFile) { + if(verbosity>5) cout << " Closefile: " << CurrentFile << endl; + CurrentFile=0;in.close();} + } */ + int eof(){return in.eof();} + ~MeshIstream(){delete ∈} + int IsString(const char* s); + char * ReadStr(); + MeshIstream& operator>>(short& i) { cm() >> i ;return err();} + MeshIstream& operator>>(long& i) { cm() >> i ;return err();} + MeshIstream& operator>>(int& i) { cm() >> i ;return err();} + MeshIstream& operator>>(float& i) { cm() >> i ;return err();} + MeshIstream& operator>>(double& i) { cm() >> i ;return err();} + MeshIstream& operator>>(char * & i ) { i=ReadStr();return err();} + +}; +// Fortran unformatted file interface ---------- + +class IFortranUnFormattedFile { +// template<class T> friend IFortranUnFormattedFile & operator>>(IFortranUnFormattedFile &f,T & l); + istream * f; + long i,l,n,j,nb_rec; + const char * file_name; + int to_close; + public: + IFortranUnFormattedFile(char *name) + : f(new ifstream(name)),i(0),l(0),n((long)-sizeof(long)), + nb_rec(0),file_name(name), to_close(1) + { if(!*f) Error(0);} + + IFortranUnFormattedFile(MeshIstream & ff) + : f(&ff.in),i(0),l(0),n((long)-sizeof(long)),nb_rec(0), + file_name(ff.CurrentFile), to_close(0) + { if(! *f) Error(0);} + + ~IFortranUnFormattedFile(); + long Record(); + long where(){return j-i;} + void read4(char *c,int );// for the fortran 77 char4 + void read(char * p,const size_t lg); + void Error(int); +}; + +class OFortranUnFormattedFile { +// template<class T> friend OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const T & l); + ostream * f; + long i,l,n,j,nb_rec; + const static char * unkown; + const char * file_name; + int to_close; + public: + + OFortranUnFormattedFile(const char *name,IOS_OPENMODE mm=ios::trunc) + : f(new ofstream(name,mm)),i(0),l(0),n((long) -sizeof(long)),nb_rec(0),file_name(name), to_close(1) + { if(!*f) Error(0);} + OFortranUnFormattedFile(ostream &ff) + : f(&ff),i(0),l(0),n((long) -sizeof(long)),nb_rec(0),file_name(unkown), to_close(0) + { if(!*f) Error(0);} + + ~OFortranUnFormattedFile(); + + long Record(long ll=0); + long where(){return j-i;} + void write4(const char *c,int );// for the fortran 77 char4 + void write(const char * p,const size_t lg); + void Error(int ); +}; + +/// ---------- inline ------------------------- + +inline void IFortranUnFormattedFile::read(char * p,const size_t lg){ + f->read(p,lg); + j+=lg; + if (j>n) Error(1); + else if (!f->good()) Error(2) ; +} + +inline void OFortranUnFormattedFile::write(const char * p,const size_t lg){ + f->write(p,lg); + j+=lg; + if (l && j>n) Error(1); + else if (!f->good()) Error(2); +} + +template<class T> inline +IFortranUnFormattedFile & operator>>(IFortranUnFormattedFile &f,T & l) +{ + f.read((char *) &l,sizeof(l));return f; +} +/* bug sur sun +template inline + OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const T & l) + { + f.write((char *) &l,sizeof(l));return f; + } +on ex les template */ + +inline + OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const int & l) + { + f.write((char *) &l,sizeof(l));return f; + } +inline + OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const long & l) + { + f.write((char *) &l,sizeof(l));return f; + } +inline + OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const double & l) + { + f.write((char *) &l,sizeof(l));return f; + } +inline + OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const float & l) + { + f.write((char *) &l,sizeof(l));return f; + } + +inline void OFortranUnFormattedFile::write4(const char *c,int ll) +{ + int i,j; + Char4orLong ch4; + for ( i=0;i<ll;i++) + { + ch4.l=0; + for (j=0;j<4;j++) + ch4.c[j]=*c? *c++:' '; + *this << ch4.l; + } +} +inline void IFortranUnFormattedFile::read4(char *c,int ll) +{ + int i,j; + Char4orLong ch4; + + for ( i=0;i<ll;i++) + { + *this >> ch4.l; + for (j=0;j<4;j++) + *c++= ch4.c[j]; + } + *c=0;// end of string +} + +} diff --git a/contrib/bamg/bamglib/Metric.cpp b/contrib/bamg/bamglib/Metric.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f65141383d53d11c97466016659736b6c144d87a --- /dev/null +++ b/contrib/bamg/bamglib/Metric.cpp @@ -0,0 +1,1213 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#include <stdio.h> +#include "Meshio.h" +#include "Mesh2.h" + + +namespace bamg { + + +inline Real8 det3x3(Real8 A[3] ,Real8 B[3],Real8 C[3]) +{ return A[0] * ( B[1]*C[2]-B[2]*C[1]) + - A[1] * ( B[0]*C[2]-B[2]*C[0]) + + A[2] * ( B[0]*C[1]-B[1]*C[0]); +} + +SaveMetricInterpole LastMetricInterpole; + +void ReductionSimultanee( MetricAnIso M1, MetricAnIso M2,double & l1,double & l2, D2xD2 & V) +{ + double a11=M1.a11,a21=M1.a21,a22=M1.a22; + double b11=M2.a11,b21=M2.a21,b22=M2.a22; + // M1 v = l M2 v + // (M1 - l M2) v =0 + // det (M1 - l M2) =0 + // det (M1 - l M2) = a l^2 + b l + c; + // = (a11 - l * b11) * (a22 - l * b22) - (a21 - l * b21 ) ^2 + // const double eps = 1.e-5; + const double /*c11 = a11*a11,*/ c21= a21*a21; + const double /*d11 = b11*b11,*/ d21= b21*b21; + const double a=b11*b22 - d21; + const double b=-a11*b22-a22*b11+2*a21*b21; + const double c=-c21+a11*a22; + const double bb = b*b,ac= a*c; + const double delta = bb - 4 * ac; + // const double kk=c11+c22+c21+d11+d21+d22; + // modif F Hecht feb 1998 + // cerr.precision(14); + //cerr << bb << " " << ac << " " << bb << " " <<a << endl; + // cerr << a11 << " " << a21 << " " << a22 << endl; + //cerr << b11 << " " << b21 << " " << b22 << endl; + if (bb + Abs(ac) < 1.0e-20 || (delta< 1.0E-4 * bb ) ) + { + // racine double; + // cerr << "double " << endl ; + if (Abs(a) < 1.e-30 ) + l1 = l2 = 0; + else + l1=l2=-b/(2*a); + V= D2xD2(1,0,0,1); + } + else { + // cerr << " -- " << a << endl ; + const double delta2 = sqrt(delta); + l1= (-b - delta2)/(2*a); + l2= (-b + delta2)/(2*a); + // M1 v = l M2 v + // ( (M1 - I M2) x,y) = (x,(M1 - I M2) y) \forall y + // so Ker((M1 - I M2)) = Im((M1 - I M2))^\perp + double v0 = a11-l1*b11, v1 = a21-l1*b21,v2 = a22 - l1*b22; + double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; + double vp1x,vp1y,vp2x,vp2y; + + if(s1 < s0) + s0=sqrt(s0),vp1x=v1/s0,vp1y=-v0/s0; + else + s1=sqrt(s1),vp1x=v2/s1,vp1y=-v1/s1; + + v0 = a11-l2*b11, v1 = a21-l2*b21,v2 = a22 - l2*b22; + s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; + if(s1 < s0) + s0=sqrt(s0),vp2x=v1/s0,vp2y=-v0/s0; + else + s1=sqrt(s1),vp2x=v2/s1,vp2y=-v1/s1; +#ifdef DEBUG + assert(Abs(vp1y)+Abs(vp2y)>0); +#endif + V=D2xD2(vp1x,vp2x,vp1y,vp2y); + } + return; + +} + +MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) ; +MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) +{ + D2xD2 M; + double l1,l2; + ReductionSimultanee(M1,M2,l1,l2,M); + R2 v0(M.x.x,M.y.x); + R2 v1(M.x.y,M.y.y); + D2xD2 M_1(M.inv()); + D2xD2 D(Max(M1(v0,v0),M2(v0,v0)),0,0,Max(M1(v1,v1),M2(v1,v1))); + D2xD2 Mi(M_1.t()*D*M_1); + return MetricAnIso(Mi.x.x,0.5*(Mi.x.y+Mi.y.x),Mi.y.y); +} + +MetricAnIso::MetricAnIso(const Real8 a[3],const MetricAnIso m0, + const MetricAnIso m1,const MetricAnIso m2 ) +{ + MetricAnIso mab(a[0]*m0.a11 + a[1]*m1.a11 + a[2]*m2.a11, + a[0]*m0.a21 + a[1]*m1.a21 + a[2]*m2.a21, + a[0]*m0.a22 + a[1]*m1.a22 + a[2]*m2.a22); + + MatVVP2x2 vab(mab); + + R2 v1(vab.v.x,vab.v.y); + R2 v2(-v1.y,v1.x); + + Real8 h1 = a[0] / m0(v1) + a[1] / m1(v1) + a[2] / m2(v1); + Real8 h2 = a[0] / m0(v2) + a[1] / m1(v2) + a[2] / m2(v2); + + vab.lambda1 = 1 / (h1*h1); + vab.lambda2 = 1 / (h2*h2); + *this = vab; +} + + MetricAnIso::MetricAnIso( Real8 a,const MetricAnIso ma, + Real8 b,const MetricAnIso mb) +{ + MetricAnIso mab(a*ma.a11+b*mb.a11,a*ma.a21+b*mb.a21,a*ma.a22+b*mb.a22); + MatVVP2x2 vab(mab); + + R2 v1(vab.v.x,vab.v.y); + R2 v2(-v1.y,v1.x); + + + Real8 h1 = a / ma(v1) + b / mb(v1); + Real8 h2 = a / ma(v2) + b / mb(v2); + vab.lambda1 = 1 / (h1*h1); + vab.lambda2 = 1 / (h2*h2); + *this = vab; +} + + + + MatVVP2x2::MatVVP2x2(const MetricAnIso M) +{ + double a11=M.a11,a21=M.a21,a22=M.a22; + const double eps = 1.e-5; + double c11 = a11*a11, c22 = a22*a22, c21= a21*a21; + double b=-a11-a22,c=-c21+a11*a22; + double delta = b*b - 4 * c ; + double n2=(c11+c22+c21); + if ( n2 < 1e-30) + lambda1=lambda2=0,v.x=1,v.y=0; + else if (delta < eps*n2) + { + lambda1=lambda2=-b/2, v.x=1,v.y=0; + } + else + { // --- construction de 2 vecteur dans (Im ( A - D(i) Id) ortogonal + delta = sqrt(delta); + lambda1 = (-b-delta)/2.0,lambda2 = (-b+delta)/2.0; + double v0 = a11-lambda1, v1 = a21,v2 = a22 - lambda1; + double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2; + + if(s1 < s0) + s0=sqrt(s0),v.x=v1/s0,v.y=-v0/s0; + else + s1=sqrt(s1),v.x=v2/s1,v.y=-v1/s1; + }; +} + + + int MetricAnIso::IntersectWith(const MetricAnIso M2) +{ + //cerr << " - " << *this << M2 << endl; + int r=0; + MetricAnIso & M1 = *this; + D2xD2 M; + double l1,l2; + + ReductionSimultanee(*this,M2,l1,l2,M); + // cerr << M << endl; + R2 v1(M.x.x,M.y.x); + R2 v2(M.x.y,M.y.y); + double l11=M1(v1,v1); + double l12=M1(v2,v2); + double l21=M2(v1,v1); + double l22=M2(v2,v2); + if ( l11 < l21 ) r=1,l11=l21; + if ( l12 < l22 ) r=1,l12=l22; + // cerr << r << endl; + if (r) { // change + D2xD2 M_1(M.inv()); + D2xD2 D(l11,0,0,l12); + D2xD2 Mi(M_1.t()*D*M_1); + a11=Mi.x.x; + a21=0.5*(Mi.x.y+Mi.y.x); + a22=Mi.y.y; } + return r; +} +void Triangles::IntersectGeomMetric(const Real8 err=1,const int iso=0) + +{ + if(verbosity>1) + cout << " -- IntersectGeomMetric geometric err=" << err << (iso ? " iso " : " aniso " ) << endl; + Real8 ss[2]={0.00001,0.99999}; + Real8 errC = 2*sqrt(2*err); + Real8 hmax = Gh.MaximalHmax(); + Real8 hmin = Gh.MinimalHmin(); + Real8 maxaniso = 1e6; + assert(hmax>0); + SetVertexFieldOn(); + if (errC > 1) errC = 1; + for (Int4 i=0;i<nbe;i++) + for (int j=0;j<2;j++) + { + + Vertex V; + VertexOnGeom GV; + // cerr << Number(edges[i]) << " " << ss[j] << endl; + Gh.ProjectOnCurve(edges[i],ss[j],V,GV); + { + GeometricalEdge * eg = GV; + Real8 s = GV; + R2 tg; + // cerr << i << " " << j << " " << Number(V) << " on = " + // << Gh.Number(eg) << " at s = " << s << " " << endl; + Real8 R1= eg->R1tg(s,tg); + // cerr << " R = " << 1/Max(R1,1e-20) << tg << " on x " + // << V.r << errC/ Max(R1,1e-20) << " hold=" <<V.m(tg) << " " << endl; + Real8 ht = hmax; + if (R1>1.0e-20) + { // err relative to the length of the edge + ht = Min(Max(errC/R1,hmin),hmax); + } + Real8 hn = iso? ht : Min(hmax,ht*maxaniso); + //cerr << ht << " " << hn << "m=" << edges[i][j].m << endl; + assert(ht>0 && hn>0); + MatVVP2x2 Vp(1/(ht*ht),1/(hn*hn),tg); + //cerr << " : " ; + Metric MVp(Vp); + // cerr << " : " << MVp << endl; + edges[i][j].m.IntersectWith(MVp); + //cerr << " . " << endl; + } + + } + // the problem is for the vertex on vertex + +} +/* +void Triangles::BoundAnisotropy(Real8 anisomax) +{ + if (verbosity > 1) + cout << " -- BoundAnisotropy by " << anisomax << endl; + Real8 h1=1.e30,h2=1e-30,rx=0; + Real8 coef = 1./(anisomax*anisomax); + Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30; + for (Int4 i=0;i<nbv;i++) + { + + MatVVP2x2 Vp(vertices[i]); + + h1=Min(h1,Vp.lmin()); + h2=Max(h2,Vp.lmax()); + rx = Max(rx,Vp.Aniso2()); + + Vp.BoundAniso2(coef); + + hn1=Min(hn1,Vp.lmin()); + hn2=Max(hn2,Vp.lmax()); + rnx = Max(rnx,Vp.Aniso2()); + + + vertices[i].m = Vp; + + } + + if (verbosity>2) + { + cout << " input : Hmin = " << sqrt(1/h2) << " Hmax = " << sqrt(1/h1) + << " factor of anisotropy max = " << sqrt(rx) << endl; + cout << " output: Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) + << " factor of anisotropy max = " << sqrt(rnx) << endl; + } +} +*/ +void Triangles::BoundAnisotropy(Real8 anisomax,Real8 hminaniso) +{ + double lminaniso = 1/ (Max(hminaniso*hminaniso,1e-100)); + if (verbosity > 1) + cout << " -- BoundAnisotropy by " << anisomax << endl; + Real8 h1=1.e30,h2=1e-30,rx=0; + Real8 coef = 1./(anisomax*anisomax); + Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30; + for (Int4 i=0;i<nbv;i++) + { + + MatVVP2x2 Vp(vertices[i]); + double lmax=Vp.lmax(); + h1=Min(h1,Vp.lmin()); + h2=Max(h2,Vp.lmax()); + rx = Max(rx,Vp.Aniso2()); + + Vp *= Min(lminaniso,lmax)/lmax; + + Vp.BoundAniso2(coef); + + hn1=Min(hn1,Vp.lmin()); + hn2=Max(hn2,Vp.lmax()); + rnx = Max(rnx,Vp.Aniso2()); + + + vertices[i].m = Vp; + + } + + if (verbosity>2) + { + cout << " input : Hmin = " << sqrt(1/h2) << " Hmax = " << sqrt(1/h1) + << " factor of anisotropy max = " << sqrt(rx) << endl; + cout << " output: Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) + << " factor of anisotropy max = " << sqrt(rnx) << endl; + } +} +void Triangles::IntersectConsMetric(const double * s,const Int4 nbsol,const int * typsols, + const Real8 hmin1,const Real8 hmax1,const Real8 coef, + const Real8 anisomax ,const Real8 CutOff,const int NbJacobi, + const int DoNormalisation,const double power,const int choice) +{ // the array of solution s is store + // sol0,sol1,...,soln on vertex 0 + // sol0,sol1,...,soln on vertex 1 + // etc. + // choise = 0 => H is computed with green formule + // otherwise => H is computed from P2 on 4T + const int dim = 2; + + int sizeoftype[] = { 1, dim ,dim * (dim+1) / 2, dim * dim } ; + + // computation of the nb of field + Int4 ntmp = 0; + if (typsols) + { + for (Int4 i=0;i<nbsol;i++) + ntmp += sizeoftype[typsols[i]]; + } + else + ntmp = nbsol; + + // n is the total number of fields + + const Int4 n = ntmp; + + Int4 i,k,iA,iB,iC,iv; + R2 O(0,0); + int RelativeMetric = CutOff>1e-30; + Real8 hmin = Max(hmin1,MinimalHmin()); + Real8 hmax = Min(hmax1,MaximalHmax()); + Real8 coef2 = 1/(coef*coef); + + if(verbosity>1) + { + cout << " -- Construction of Metric: Nb of field. " << n << " nbt = " + << nbt << " nbv= " << nbv + << " coef = " << coef << endl + << " hmin = " << hmin << " hmax=" << hmax + << " anisomax = " << anisomax << " Nb Jacobi " << NbJacobi << " Power = " << power ; + if (RelativeMetric) + cout << " RelativeErr with CutOff= " << CutOff << endl; + else + cout << " Absolute Err" <<endl; + } + double *ss=(double*)s;//, *ssiii = ss; + + double sA,sB,sC; + + Real8 *detT = new Real8[nbt]; + Real8 *Mmass= new Real8[nbv]; + Real8 *Mmassxx= new Real8[nbv]; + Real8 *dxdx= new Real8[nbv]; + Real8 *dxdy= new Real8[nbv]; + Real8 *dydy= new Real8[nbv]; + Real8 *workT= new Real8[nbt]; + Real8 *workV= new Real8[nbv]; + int *OnBoundary = new int[nbv]; + for (iv=0;iv<nbv;iv++) + { + Mmass[iv]=0; + OnBoundary[iv]=0; + Mmassxx[iv]=0; + } + + for (i=0;i<nbt;i++) + if(triangles[i].link) // the real triangles + { + const Triangle &t=triangles[i]; + // coor of 3 vertices + R2 A=t[0]; + R2 B=t[1]; + R2 C=t[2]; + + + // number of the 3 vertices + iA = Number(t[0]); + iB = Number(t[1]); + iC = Number(t[2]); + + Real8 dett = bamg::Area2(A,B,C); + detT[i]=dett; + dett /= 6; + + // construction of on boundary + int nbb =0; + for(int j=0;j<3;j++) + { + Triangle *ta=t.Adj(j); + if ( ! ta || !ta->link) // no adj triangle => edge on boundary + OnBoundary[Number(t[VerticesOfTriangularEdge[j][0]])]=1, + OnBoundary[Number(t[VerticesOfTriangularEdge[j][1]])]=1, + nbb++; + } + + workT[i] = nbb; + Mmass[iA] += dett; + Mmass[iB] += dett; + Mmass[iC] += dett; + + if((nbb==0)|| !choice) + { + Mmassxx[iA] += dett; + Mmassxx[iB] += dett; + Mmassxx[iC] += dett; + } + } + else + workT[i]=-1; + +// for (Int4 kcount=0;kcount<n;kcount++,ss++) + for (Int4 nusol=0;nusol<nbsol;nusol++) + { //for all Solution + + Real8 smin=ss[0],smax=ss[0]; + + Real8 h1=1.e30,h2=1e-30,rx=0; + Real8 coef = 1./(anisomax*anisomax); + Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30; + int nbfield = typsols? sizeoftype[typsols[nusol]] : 1; + if (nbfield == 1) + for ( iv=0,k=0; iv<nbv; iv++,k+=n ) + { + dxdx[iv]=dxdy[iv]=dydy[iv]=0; + smin=Min(smin,ss[k]); + smax=Max(smax,ss[k]); + } + else + { + // cas vectoriel + for ( iv=0,k=0; iv<nbv; iv++,k+=n ) + { + double v=0; + for (int i=0;i<nbfield;i++) + v += ss[k+i]*ss[k+i]; + v = sqrt(v); + smin=Min(smin,v); + smax=Max(smax,v); + } + } + Real8 sdelta = smax-smin; + Real8 absmax=Max(Abs(smin),Abs(smax)); + Real8 cnorm = DoNormalisation ? coef2/sdelta : coef2; + + if(verbosity>2) + cout << " Solution " << nusol << " Min = " << smin << " Max = " + << smax << " Delta =" << sdelta << " cnorm = " << cnorm << " Nb of fields =" << nbfield << endl; + + + if ( sdelta < 1.0e-10*Max(absmax,1e-20) && (nbfield ==1)) + { + if (verbosity>2) + cout << " Solution " << nusol << " is constant. We skip. " + << " Min = " << smin << " Max = " << smax << endl; + continue; + } + + double *sf = ss; + for (Int4 nufield=0;nufield<nbfield;nufield++,ss++) + { + for ( iv=0,k=0; iv<nbv; iv++,k+=n ) + dxdx[iv]=dxdy[iv]=dydy[iv]=0; + for (i=0;i<nbt;i++) + if(triangles[i].link) + {// for real all triangles + // coor of 3 vertices + R2 A=triangles[i][0]; + R2 B=triangles[i][1]; + R2 C=triangles[i][2]; + + + // warning the normal is internal and the + // size is the length of the edge + R2 nAB = Orthogonal(B-A); + R2 nBC = Orthogonal(C-B); + R2 nCA = Orthogonal(A-C); + // remark : nAB + nBC + nCA == 0 + + // number of the 3 vertices + iA = Number(triangles[i][0]); + iB = Number(triangles[i][1]); + iC = Number(triangles[i][2]); + + // for the test of boundary edge + // the 3 adj triangles + Triangle *tBC = triangles[i].TriangleAdj(OppositeEdge[0]); + Triangle *tCA = triangles[i].TriangleAdj(OppositeEdge[1]); + Triangle *tAB = triangles[i].TriangleAdj(OppositeEdge[2]); + + // value of the P1 fonction on 3 vertices + sA = ss[iA*n]; + sB = ss[iB*n]; + sC = ss[iC*n]; + + R2 Grads = (nAB * sC + nBC * sA + nCA * sB ) /detT[i] ; + if(choice) + { + int nbb = 0; + Real8 dd = detT[i]; + Real8 lla,llb,llc,llf; + Real8 taa[3][3],bb[3]; + // construction of the trans of lin system + for (int j=0;j<3;j++) + { + int ie = OppositeEdge[j]; + TriangleAdjacent ta = triangles[i].Adj(ie); + Triangle *tt = ta; + if (tt && tt->link) + { + Vertex &v = *ta.OppositeVertex(); + R2 V = v; + Int4 iV = Number(v); + Real8 lA = bamg::Area2(V,B,C)/dd; + Real8 lB = bamg::Area2(A,V,C)/dd; + Real8 lC = bamg::Area2(A,B,V)/dd; + taa[0][j] = lB*lC; + taa[1][j] = lC*lA; + taa[2][j] = lA*lB; + //Real8 xx = V.x-V.y; + //Real8 yy = V.x + V.y; + //cout << " iv " << ss[iV*n] << " == " << (8*xx*xx+yy*yy) + // << " l = " << lA << " " << lB << " " << lC + // << " = " << lA+lB+lC << " " << V << " == " << A*lA+B*lB+C*lC << endl; + + lla = lA,llb=lB,llc=lC,llf=ss[iV*n] ; + + bb[j] = ss[iV*n] - ( sA*lA + sB*lB + sC*lC ) ; + } + else + { + nbb++; + taa[0][j]=0; + taa[1][j]=0; + taa[2][j]=0; + taa[j][j]=1; + bb[j]=0; + } + } + + // resolution of 3x3 lineaire system transpose + Real8 det33 = det3x3(taa[0],taa[1],taa[2]); + Real8 cBC = det3x3(bb,taa[1],taa[2]); + Real8 cCA = det3x3(taa[0],bb,taa[2]); + Real8 cAB = det3x3(taa[0],taa[1],bb); + + assert(det33); + // det33=1; + // verif + // cout << " " << (taa[0][0]*cBC + taa[1][0]*cCA + taa[2][0] * cAB)/det33 << " == " << bb[0] ; + // cout << " " << (taa[0][1]*cBC + taa[1][1]*cCA + taa[2][1] * cAB)/det33 << " == " << bb[1]; + // cout << " " << (taa[0][2]*cBC + taa[1][2]*cCA + taa[2][2] * cAB)/det33 << " == " << bb[2] + // << " -- " ; + //cout << lla*sA + llb*sB+llc*sC+ (lla*llb* cAB + llb*llc* cBC + llc*lla*cCA)/det33 + // << " == " << llf << endl; + // computation of the gradient in the element + + // H( li*lj) = grad li grad lj + grad lj grad lj + // grad li = njk / detT ; with i j k ={A,B,C) + Real8 Hxx = cAB * ( nBC.x*nCA.x) + cBC * ( nCA.x*nAB.x) + cCA * (nAB.x*nBC.x); + Real8 Hyy = cAB * ( nBC.y*nCA.y) + cBC * ( nCA.y*nAB.y) + cCA * (nAB.y*nBC.y); + Real8 Hxy = cAB * ( nBC.y*nCA.x) + cBC * ( nCA.y*nAB.x) + cCA * (nAB.y*nBC.x) + + cAB * ( nBC.x*nCA.y) + cBC * ( nCA.x*nAB.y) + cCA * (nAB.x*nBC.y); + Real8 coef = 1.0/(3*dd*det33); + Real8 coef2 = 2*coef; + // cout << " H = " << Hxx << " " << Hyy << " " << Hxy/2 << " coef2 = " << coef2 << endl; + Hxx *= coef2; + Hyy *= coef2; + Hxy *= coef2; + //cout << i << " H = " << 3*Hxx/dd << " " << 3*Hyy/dd << " " << 3*Hxy/(dd*2) << " nbb = " << nbb << endl; + if(nbb==0) + { + dxdx[iA] += Hxx; + dydy[iA] += Hyy; + dxdy[iA] += Hxy; + + dxdx[iB] += Hxx; + dydy[iB] += Hyy; + dxdy[iB] += Hxy; + + dxdx[iC] += Hxx; + dydy[iC] += Hyy; + dxdy[iC] += Hxy; + } + + } + else + { + + // if edge on boundary no contribution => normal = 0 + if ( ! tBC || ! tBC->link ) nBC = O; + if ( ! tCA || ! tCA->link ) nCA = O; + if ( ! tAB || ! tAB->link ) nAB = O; + + // remark we forgot a 1/2 because + // $\\int_{edge} w_i = 1/2 $ if $i$ is in edge + // 0 if not + // if we don't take the boundary + // dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x; + + dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x; + dxdx[iB] += ( nAB.x + nBC.x ) *Grads.x; + dxdx[iC] += ( nBC.x + nCA.x ) *Grads.x; + + // warning optimization (1) the divide by 2 is done on the metrix construction + dxdy[iA] += (( nCA.y + nAB.y ) *Grads.x + ( nCA.x + nAB.x ) *Grads.y) ; + dxdy[iB] += (( nAB.y + nBC.y ) *Grads.x + ( nAB.x + nBC.x ) *Grads.y) ; + dxdy[iC] += (( nBC.y + nCA.y ) *Grads.x + ( nBC.x + nCA.x ) *Grads.y) ; + + dydy[iA] += ( nCA.y + nAB.y ) *Grads.y; + dydy[iB] += ( nAB.y + nBC.y ) *Grads.y; + dydy[iC] += ( nBC.y + nCA.y ) *Grads.y; + } + + } // for real all triangles + Int4 kk=0; + for ( iv=0,k=0 ; iv<nbv; iv++,k+=n ) + if(Mmassxx[iv]>0) + { + dxdx[iv] /= 2*Mmassxx[iv]; + // warning optimization (1) on term dxdy[iv]*ci/2 + dxdy[iv] /= 4*Mmassxx[iv]; + dydy[iv] /= 2*Mmassxx[iv]; + // Compute the matrix with abs(eigen value) + Metric M(dxdx[iv], dxdy[iv], dydy[iv]); + MatVVP2x2 Vp(M); + //cout <<iv << " M = " << M << " aniso= " << Vp.Aniso() ; + Vp.Abs(); + M = Vp; + dxdx[iv] = M.a11; + dxdy[iv] = M.a21; + dydy[iv] = M.a22; + // cout << " (abs) iv M = " << M << " aniso= " << Vp.Aniso() <<endl; + } + else kk++; + + + // correction of second derivate + // by a laplacien + + Real8 *d2[3] = { dxdx, dxdy, dydy}; + Real8 *dd; + for (int xy = 0;xy<3;xy++) + { + dd = d2[xy]; + // do leat 2 iteration for boundary problem + for (int ijacobi=0;ijacobi<Max(NbJacobi,2);ijacobi++) + { + for (i=0;i<nbt;i++) + if(triangles[i].link) // the real triangles + { + // number of the 3 vertices + iA = Number(triangles[i][0]); + iB = Number(triangles[i][1]); + iC = Number(triangles[i][2]); + Real8 cc=3; + if(ijacobi==0) + cc = Max((Real8) ((Mmassxx[iA]>0)+(Mmassxx[iB]>0)+(Mmassxx[iC]>0)),1.); + workT[i] = (dd[iA]+dd[iB]+dd[iC])/cc; + } + for (iv=0;iv<nbv;iv++) + workV[iv]=0; + + for (i=0;i<nbt;i++) + if(triangles[i].link) // the real triangles + { + // number of the 3 vertices + iA = Number(triangles[i][0]); + iB = Number(triangles[i][1]); + iC = Number(triangles[i][2]); + Real8 cc = workT[i]*detT[i]; + workV[iA] += cc; + workV[iB] += cc; + workV[iC] += cc; + } + + for (iv=0;iv<nbv;iv++) + if( ijacobi<NbJacobi || OnBoundary[iv]) + dd[iv] = workV[iv]/(Mmass[iv]*6); + + + } + + + } + + // constuction of the metrix from the Hessian dxdx. dxdy,dydy + + Real8 rCutOff=CutOff*absmax;// relative cut off + + for ( iv=0,k=0 ; iv<nbv; iv++,k+=n ) + { // for all vertices + //{ + //Metric M(dxdx[iv], dxdy[iv], dydy[iv]); + // MatVVP2x2 Vp(M); + //cout << " iv M="<< M << " Vp = " << Vp << " aniso " << Vp.Aniso() << endl; + //} + MetricIso Miso; +// new code to compute ci --- + Real8 ci ; + if (RelativeMetric) + { // compute the norm of the solution + double xx =0,*sfk=sf+k; + for (int ifield=0;ifield<nbfield;ifield++,sfk++) + xx += *sfk* *sfk; + xx=sqrt(xx); + ci = coef2/Max(xx,rCutOff); + } + else ci = cnorm; + + // old +// Real8 ci = RelativeMetric ? coef2/(Max(Abs(ss[k]),rCutOff)) : cnorm ; + // modif F Hecht 101099 + Metric Miv(dxdx[iv]*ci, dxdy[iv]*ci, dydy[iv]*ci); + MatVVP2x2 Vp(Miv); + + Vp.Abs(); + if(power!=1.0) + Vp.pow(power); + + + + h1=Min(h1,Vp.lmin()); + h2=Max(h2,Vp.lmax()); + + Vp.Maxh(hmin); + Vp.Minh(hmax); + + rx = Max(rx,Vp.Aniso2()); + + Vp.BoundAniso2(coef); + + hn1=Min(hn1,Vp.lmin()); + hn2=Max(hn2,Vp.lmax()); + rnx = Max(rnx,Vp.Aniso2()); + + Metric MVp(Vp); + vertices[iv].m.IntersectWith(MVp); + }// for all vertices + if (verbosity>2) + { + cout << " Field " << nufield << " of solution " << nusol << endl; + cout << " before bounding : Hmin = " << sqrt(1/h2) << " Hmax = " + << sqrt(1/h1) << " factor of anisotropy max = " << sqrt(rx) << endl; + cout << " after bounding : Hmin = " << sqrt(1/hn2) << " Hmax = " + << sqrt(1/hn1) << " factor of anisotropy max = " << sqrt(rnx) << endl; + } + } // end of for all field + }// end for all solution + + delete [] detT; + delete [] Mmass; + delete [] dxdx; + delete [] dxdy; + delete [] dydy; + delete [] workT; + delete [] workV; + delete [] Mmassxx; + delete [] OnBoundary; + +} + + +void Triangles::ReadMetric(const char * fmetrix,const Real8 hmin1=1.0e-30,const Real8 hmax1=1.0e30,const Real8 coef=1) +{ + Real8 hmin = Max(hmin1,MinimalHmin()); + Real8 hmax = Min(hmax1,MaximalHmax()); + MeshIstream f_metrix(fmetrix); + Int4 k,j; + f_metrix >> k >> j ; + if(verbosity>1) + cout << " metrix: open " << fmetrix + << ", le coef = " << coef + << ", hmin = " << hmin + << ", hmax = " << hmax + << ( (j == 1)? " Iso " : " AnIso " )<< endl; + + if (k != nbv || !(j == 1 || j == 3)) + { + cerr << " Error Pb metrix " << k << " <> " + << nbv << " or 1 or 3 <> " << j << endl; + MeshError(1002); + } + + cout << " j = " << j << endl; + // Int4 nberr = 0; + for (Int4 iv=0;iv<nbv;iv++) + { + Real8 h; + if (j == 1) + { + f_metrix >> h ; + vertices[iv].m=Metric(Max(hmin,Min(hmax, h*coef))); + } + else if (j==3) + { + Real8 a,b,c; + f_metrix >> a >> b >> c ; + MetricAnIso M(a,b,c); + MatVVP2x2 Vp(M/coef); + + Vp.Maxh(hmin); + Vp.Minh(hmax); + vertices[iv].m = Vp; + + } + } + +} + +void Triangles::WriteMetric(ostream & f,int iso) +{ + if (iso) + { + f << nbv <<" " << 1 << endl ; + for (Int4 iv=0;iv<nbv;iv++) + { + MatVVP2x2 V=vertices[iv].m; + f << V.hmin() << endl; + } + } +else + { + f << nbv <<" " << 3 << endl ; + for (Int4 iv=0;iv<nbv;iv++) + f << vertices[iv].m.a11 << " " + << vertices[iv].m.a21 << " " + << vertices[iv].m.a22 << endl; + } +} +void Triangles::MaxSubDivision(Real8 maxsubdiv) +{ +const Real8 maxsubdiv2 = maxsubdiv*maxsubdiv; +#ifdef DRAWING2 + inquire(); +#endif + if(verbosity>1) + cout << " -- Limit the subdivision of a edges in the new mesh by " << maxsubdiv << endl ; + // for all the edges + // if the len of the edge is to long + Int4 it,nbchange=0; + Real8 lmax=0; + for (it=0;it<nbt;it++) + { + Triangle &t=triangles[it]; + for (int j=0;j<3;j++) + { + Triangle &tt = *t.TriangleAdj(j); + if ( ! &tt || it < Number(tt) && ( tt.link || t.link)) + { + Vertex &v0 = t[VerticesOfTriangularEdge[j][0]]; + Vertex &v1 = t[VerticesOfTriangularEdge[j][1]]; + R2 AB= (R2) v1-(R2) v0; + Metric M = v0; + Real8 l = M(AB,AB); + lmax = Max(lmax,l); + if(l> maxsubdiv2) + { R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M + Real8 lc = M(AC,AC); + D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC; + D2xD2 Rt1(Rt.inv()); + D2xD2 D(maxsubdiv2,0,0,lc); + D2xD2 MM = Rt1*D*Rt1.t(); +#ifdef DRAWING1 + v0.m.Draw(v0); +#endif + v0.m = M = MetricAnIso(MM.x.x,MM.y.x,MM.y.y); +#ifdef DRAWING1 + v0.m.Draw(v0); +#endif + // cout << " M(AB,AB) = " << M(AB,AB) << " == " << maxsubdiv + // << " M(AC,AC) = " << M(AC,AC) << " == " << lc << endl; + nbchange++; + } + M = v1; + l = M(AB,AB); + lmax = Max(lmax,l); + if(l> maxsubdiv2) + { R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M + Real8 lc = M(AC,AC); + D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC; + D2xD2 Rt1(Rt.inv()); + D2xD2 D(maxsubdiv2,0,0,lc); + D2xD2 MM = Rt1*D*Rt1.t(); +#ifdef DRAWING1 + v1.m.Draw(v1); +#endif + v1.m = M = MetricAnIso(MM.x.x,MM.y.x,MM.y.y); +#ifdef DRAWING1 + v1.m.Draw(v1); + inquire(); +#endif + // cout << " M(AB,AB) = " << M(AB,AB) << " == " << maxsubdiv + // << " M(AC,AC) = " << M(AC,AC) << " == " << lc << endl; + nbchange++; + } + + + } + } + } + if(verbosity>3) + cout << " Nb of metric change = " << nbchange + << " Max of the subdivision of a edges before change = " << sqrt(lmax) << endl; +#ifdef DRAWING2 + inquire(); +#endif + +} + +void Triangles::SmoothMetric(Real8 raisonmax) +{ + if(raisonmax<1.1) return; + if(verbosity > 1) + cout << " -- Triangles::SmoothMetric raisonmax = " << raisonmax << " " <<nbv <<endl; + ReMakeTriangleContainingTheVertex(); + Int4 i,j,kch,kk,ip; + Int4 *first_np_or_next_t0 = new Int4[nbv]; + Int4 *first_np_or_next_t1 = new Int4[nbv]; + Int4 Head0 =0,Head1=-1; + Real8 logseuil= log(raisonmax); + + for(i=0;i<nbv-1;i++) + first_np_or_next_t0[i]=i+1; + first_np_or_next_t0[nbv-1]=-1;// end; + for(i=0;i<nbv;i++) + first_np_or_next_t1[i]=-1; + kk=0; + while (Head0>=0&& kk++<100) { + kch=0; + for (i=Head0;i>=0;i=first_np_or_next_t0[ip=i],first_np_or_next_t0[ip]=-1) + { // pour tous les triangles autour du sommet s + // cout << kk << " i = " << i << " " << ip << endl; + register Triangle * t= vertices[i].t; + assert(t); + Vertex & vi = vertices[i]; + TriangleAdjacent ta(t,EdgesVertexTriangle[vertices[i].vint][0]); + Vertex *pvj0 = ta.EdgeVertex(0); + while (1) { + // cout << i << " " << Number(ta.EdgeVertex(0)) << " " + // << Number(ta.EdgeVertex(1)) << " ---> " ; + ta=Previous(Adj(ta)); + // cout << Number(ta.EdgeVertex(0)) << " " << Number(ta.EdgeVertex(1)) << endl; + assert(vertices+i == ta.EdgeVertex(1)); + Vertex & vj = *(ta.EdgeVertex(0)); + if ( &vj ) { + j= &vj-vertices; + assert(j>=0 && j < nbv); + R2 Aij = (R2) vj - (R2) vi; + Real8 ll = Norme2(Aij); + if (0) { + Real8 hi = ll/vi.m(Aij); + Real8 hj = ll/vj.m(Aij); + if(hi < hj) + { + Real8 dh=(hj-hi)/ll; + //cout << " dh = " << dh << endl; + if (dh>logseuil) { + vj.m.IntersectWith(vi.m/(1 +logseuil*ll/hi)); + if(first_np_or_next_t1[j]<0) + kch++,first_np_or_next_t1[j]=Head1,Head1=j; + } + } + } + else + { + Real8 li = vi.m(Aij); + //Real8 lj = vj.m(Aij); + // if ( i == 2 || j == 2) + // cout << " inter " << i << " " << j << " " << ((1 +logseuil*li)) << endl; + if( vj.m.IntersectWith(vi.m/(1 +logseuil*li)) ) + //if( vj.m.IntersectWith(vi.m*(lj/li/(1 +logseuil*lj))) ) + if(first_np_or_next_t1[j]<0) // if the metrix change + kch++,first_np_or_next_t1[j]=Head1,Head1=j; + } + } + if ( &vj == pvj0 ) break; + } + } + Head0 = Head1; + Head1 = -1; + Exchange(first_np_or_next_t0,first_np_or_next_t1); + if(verbosity>5) + cout << " Iteration " << kk << " Nb de vertices with change " << kch << endl; + } + if(verbosity>2 && verbosity < 5) + cout << " Nb of Loop " << kch << endl; + delete [] first_np_or_next_t0; + delete [] first_np_or_next_t1; +} + +void Geometry::ReadMetric(const char * fmetrix,Real8 hmin=1.0e-30,Real8 hmax=1.0e30,Real8 coef=1) +{ + hmin = Max(hmin,MinimalHmin()); + MeshIstream f_metrix(fmetrix); + Int4 k,j; + f_metrix >> k >> j ; + if(verbosity>1) + cout << " -- ReadMetric " << fmetrix + << ", coef = " << coef + << ", hmin = " << hmin + << ", hmax = " << hmax + << ( (j == 1)? " Iso " : " AnIso " ) << endl; + + if (k != nbv || !(j == 1 || j == 3)) { + cerr << " Error Pb metrix " << k << " <> " + << nbv << " or 1 or 3 <> " << j << endl; + MeshError(1003);} + + + // Int4 nberr = 0; + for (Int4 iv=0;iv<nbv;iv++) + { + Real8 h; + if (j == 1) + { + f_metrix >> h ; + vertices[iv].m=Metric(Max(hmin,Min(hmax, h*coef))); + } + else if (j==3) + { + Real8 a,b,c; + f_metrix >> a >> b >> c ; + MetricAnIso M(a,b,c); + MatVVP2x2 Vp(M/coef); + Vp.Maxh(hmin); + Vp.Minh(hmax); + vertices[iv].m = Vp; + } + } + +} + + +Real8 LengthInterpole(const MetricAnIso Ma,const MetricAnIso Mb, R2 AB) +{ + Real8 k=1./2.; + int level=0; + static int kkk=0; + static Metric Ms1[32],Ms2[32]; + static Real8 lMs1[32],lMs2[32]; + static double K[32]; + Real8 l=0,sss=0; + Ms1[level]=Ma; + Ms2[level]=Mb; + Real8 sa = Ma(AB); + Real8 sb = Mb(AB); + lMs1[level]=sa; + lMs2[level]=sb; + K[level]=k; + level++; + int i=0; + Real8 * L= LastMetricInterpole.L, *S = LastMetricInterpole.S; + Real8 sstop = 0.1; // Max(0.6,(sa+sb)/5000); + while (level) { + level--; + Metric M1=Ms1[level]; + Metric M2=Ms2[level]; + k=K[level]; + Real8 s1= lMs1[level]; + Real8 s2= lMs2[level]; + + Real8 s= (s1+s2)*k; +// if (level >20 && i < 2030-level) +// cout << " level " << level << " " << i << " " << s << " " << k <<endl; + if( s > sstop && level < 30 && i < 500-level ) { + Metric Mi(0.5,M1,0.5,M2); + Real8 si = Mi(AB); + if( Abs((s1+s2)-(si+si)) > s1*0.001) + { + k=k/2; + // we begin by the end to walk in the correct sens from a to b + // due to the stack + Ms1[level]=Mi; + Ms2[level]=M2; + lMs1[level]=si; + lMs2[level]=s2; + K[level]=k; + level++; + Ms1[level]=M1; + Ms2[level]=Mi; + lMs1[level]=s1; + lMs2[level]=si; + K[level]=k; + level++; + } + else + L[i]= l += s,S[i]=sss+=k,i++; + } + else + L[i]= l += s,S[i]=sss+=k,i++;//cout << i << " l = " << l << " sss = " << sss << endl; + } + // warning for optimisation S is in [0:0.5] not in [0:1] + assert(i<512); + LastMetricInterpole.lab=l; + LastMetricInterpole.opt=i; + if (i>200 && kkk++<10) + cout << "Warning LengthInterpole: ( i = " << i << " l = " << l << " sss " << sss << " ) " << sstop <<endl; + return l; +} + +Real8 abscisseInterpole(const MetricAnIso Ma,const MetricAnIso Mb, R2 AB,Real8 s,int optim) +{ + if(!optim) LengthInterpole(Ma,Mb,AB); + Real8 l = s* LastMetricInterpole.lab,r; + int j=LastMetricInterpole.opt-1,i=0,k; + + Real8 * L= LastMetricInterpole.L, *S = LastMetricInterpole.S; + // warning for optimisation S is the abcisse in [0:0.5] + // and L is le lenght + if(l<=L[0]) + r=2*S[0]*l/L[0]; + else if (l>=L[j]) + r=1; + else + { + while (j-i>1) + { + k= (i+j)/2; + if(l<=L[k]) + j=k;// l<=L[j] + else + i=k; // L[i]<l + }; + // cout << i << " " << j <<" " << L[i] << " " << L[j] << " " << S[i] << " " << S[j] << " l=" << l << endl; + if (i==j) + r = 2*S[i]; + else + r = 2*(S[i]*(L[j]-l)+ S[j]*(l-L[i]))/(L[j]-L[i]); + } + assert(r<=1 && r>=0); + return r ; + +} + + +#ifdef DRAWING + +void MetricAnIso::Draw(R2 c) const +{ + float x= c.x,y= c.y; + if (InPtScreen(x,y)) { + R2 X(cos(0.0),sin(0.0)); + X = X / operator()(X); + rmoveto(x+X.x,y+X.y); + + for (int i=1;i<=100;i++) + { double t= 2*Pi*i/100.0; + R2 X(cos(t),sin(t)); + X = X / Max(operator()(X),1.0e-5); + rlineto(x+X.x,y+X.y); } + } +} + +void MetricIso::Draw(R2 c) const +{ + float x= c.x,y= c.y; + if (InPtScreen(x,y)) { + rmoveto(x+h,y); + for (int i=1;i<=40;i++) + { double t= Pi*i/20.0; + rlineto(x+h*cos(t),y+h*sin(t)); } + } +} + + +#endif +} // end of namespace bamg diff --git a/contrib/bamg/bamglib/Metric.h b/contrib/bamg/bamglib/Metric.h new file mode 100644 index 0000000000000000000000000000000000000000..18bbf4d6d35287ba947f41167d3eeb2f5c4236ed --- /dev/null +++ b/contrib/bamg/bamglib/Metric.h @@ -0,0 +1,225 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#ifndef TYPEMETRIX +#define TYPEMETRIX MetricAnIso +#endif + +//#include "R2.h" +namespace bamg { + +typedef P2<double,double> D2; +typedef P2xP2<double,double> D2xD2; + +class MetricAnIso; +class MatVVP2x2; +class MetricIso; + +typedef TYPEMETRIX Metric; + + +class MetricIso{ + friend class MatVVP2x2; + Real4 h; +public: + MetricIso(Real4 a): h(a){} + MetricIso(const MetricAnIso M);// {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));} + MetricIso(Real8 a11,Real8 a21,Real8 a22);// {*this=MetricAnIso(a11,a21,a22));} + MetricIso(): h(1) {}; // + MetricIso(const Real8 a[3],const MetricIso m0, + const MetricIso m1,const MetricIso m2 ) + : h(hinterpole + ? (a[0]*m0.h+a[1]*m1.h+a[2]*m2.h) + : 1/sqrt(a[0]/(m0.h*m0.h)+a[1]/(m1.h*m1.h)+a[2]/(m2.h*m2.h))) {} + MetricIso(const Real8 a,const MetricIso ma, + const Real8 b,const MetricIso mb) + : h(hinterpole + ? a*ma.h+b*mb.h + :1/sqrt(a/(ma.h*ma.h)+b/(mb.h*mb.h))) {} + R2 Orthogonal(const R2 A)const {return R2(-h*A.y,h*A.x);} + R2 Orthogonal(const I2 A)const {return R2(-h*A.y,h*A.x);} +// D2 Orthogonal(const D2 A)const {return D2(-h*A.y,h*A.x);} + Real8 operator()(R2 x) const { return sqrt((x,x))/h;}; + Real8 operator()(R2 x,R2 y) const { return ((x,y))/(h*h);}; + int IntersectWith(MetricIso M) {int r=0;if (M.h<h) r=1,h=M.h;return r;} + MetricIso operator*(Real8 c) const {return MetricIso(h/c);} + MetricIso operator/(Real8 c) const {return MetricIso(h*c);} + Real8 det() const {return 1./(h*h*h*h);} + operator D2xD2(){ return D2xD2(1/(h*h),0.,0.,1/(h*h));} + void Box(Real4 & hx,Real4 & hy) { hx=h,hy=h;} + friend ostream& operator <<(ostream& f, const MetricIso & M) + {f << " h=" << M.h<< ";" ; return f;} + +#ifdef DRAWING + void Draw(R2 ) const; +#endif +}; + + +class MetricAnIso{ public: + friend class MatVVP2x2; + Real8 a11,a21,a22; + MetricAnIso(Real8 a): a11(1/(a*a)),a21(0),a22(1/(a*a)){} + MetricAnIso(Real8 a,Real8 b,Real8 c) :a11(a),a21(b),a22(c){} + MetricAnIso() {}; // + MetricAnIso(const Real8 a[3],const MetricAnIso m0, + const MetricAnIso m1,const MetricAnIso m2 ); + R2 mul(const R2 x)const {return R2(a11*x.x+a21*x.y,a21*x.x+a22*x.y);} + Real8 det() const {return a11*a22-a21*a21;} + R2 Orthogonal(const R2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);} + R2 Orthogonal(const I2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);} +// D2 Orthogonal(const D2 x){return D2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);} + MetricAnIso( Real8 a,const MetricAnIso ma, + Real8 b,const MetricAnIso mb); + int IntersectWith(const MetricAnIso M); + MetricAnIso operator*(Real8 c) const {Real8 c2=c*c;return MetricAnIso(a11*c2,a21*c2,a22*c2);} + MetricAnIso operator/(Real8 c) const {Real8 c2=1/(c*c);return MetricAnIso(a11*c2,a21*c2,a22*c2);} + operator D2xD2(){ return D2xD2(a11,a21,a21,a22);} + + Real8 operator()(R2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);}; +// Real8 operator()(D2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);}; + Real8 operator()(R2 x,R2 y) const { return x.x*y.x*a11+(x.x*x.y+x.y*y.x)*a21+x.y*y.y*a22;}; + inline void Box(Real4 &hx,Real4 &hy) const ; + friend ostream& operator <<(ostream& f, const MetricAnIso & M) + {f << " mtr a11=" << M.a11 << " a21=a12=" << M.a21 << " a22=" << M.a22 << ";" ; return f;} +#ifdef DRAWING + void Draw(R2 ) const; +#endif + MetricAnIso(const MatVVP2x2); +}; + + +class MatVVP2x2 +{ + friend class MetricAnIso; + friend class MetricIso; +public: + double lambda1,lambda2; + D2 v; + + + MatVVP2x2(double r1,double r2,const D2 vp1): lambda1(r1),lambda2(r2),v(vp1){} + + void Abs(){lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);} + void pow(double p){lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);} + void Min(double a) { lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;} + void Max(double a) { lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;} + + void Minh(double h) {Max(1.0/(h*h));} + void Maxh(double h) {Min(1.0/(h*h));} + void Isotrope() {lambda1=lambda2=bamg::Max(lambda1,lambda2);} + friend ostream& operator <<(ostream& f, const MatVVP2x2 & c) + { f << '{' << 1/sqrt(c.lambda1)<< ',' << 1/sqrt(c.lambda2) << ','<< c.v << '}' <<flush ; return f; } + friend istream& operator >>(istream& f, MatVVP2x2 & c) + { f >> c.lambda1 >>c.lambda2 >> c.v.x >> c.v.y ;c.v /= Norme2(c.v); return f; } + MatVVP2x2(const MetricAnIso ); + MatVVP2x2(const MetricIso M) : lambda1(1/(M.h*M.h)),lambda2(1/(M.h*M.h)),v(1,0) {} + Real8 hmin() const {return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));} + Real8 hmax() const {return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));} + Real8 lmax() const {return bamg::Max3(lambda1,lambda2,1e-30);} + Real8 lmin() const {return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);} + Real8 Aniso2() const { return lmax()/lmin();} + inline void BoundAniso2(const Real8 coef); + Real8 Aniso() const { return sqrt( Aniso2());} + void BoundAniso(const Real8 c){ BoundAniso2(1/(c*c));} + void operator *=(double coef){ lambda1*=coef;lambda2*=coef;} +}; + +inline void MatVVP2x2::BoundAniso2(const Real8 coef) +{ + if (coef<=1.00000000001) + if (lambda1 < lambda2) + lambda1 = bamg::Max(lambda1,lambda2*coef); + else + lambda2 = bamg::Max(lambda2,lambda1*coef); + else // a verifier + if (lambda1 > lambda2) + lambda1 = bamg::Min(lambda1,lambda2*coef); + else + lambda2 = bamg::Min(lambda2,lambda1*coef); +} + + + + +void ReductionSimultanee( MetricAnIso M1, MetricAnIso M2,double & l1,double & l2, D2xD2 & V) ; + +inline MetricAnIso::MetricAnIso(const MatVVP2x2 M) +{ + // recompose M in: M = V^t lambda V + // V = ( v,v^\perp) + // where v^\perp = (-v_1,v_0) + double v00=M.v.x*M.v.x; + double v11=M.v.y*M.v.y; + double v01=M.v.x*M.v.y; + a11=v00*M.lambda1+v11*M.lambda2; + a21=v01*(M.lambda1-M.lambda2); + a22=v00*M.lambda2+v11*M.lambda1; +} + + +inline void MetricAnIso::Box(Real4 &hx,Real4 &hy) const +{ + Real8 d= a11*a22-a21*a21; + hx = sqrt(a22/d); + hy = sqrt(a11/d); + // cerr << " hx = " << hx << " hy = " << hy << endl; +} + + +inline MetricIso::MetricIso(const MetricAnIso M) + {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));} + +inline MetricIso::MetricIso(Real8 a11,Real8 a21,Real8 a22) + {MatVVP2x2 vp(MetricAnIso(a11,a21,a22));h=1/sqrt(Max(vp.lambda1,vp.lambda2));} + + + +class SaveMetricInterpole { + friend Real8 LengthInterpole(const MetricAnIso ,const MetricAnIso , R2 ); + friend Real8 abscisseInterpole(const MetricAnIso ,const MetricAnIso , R2 ,Real8 ,int ); + int opt; + Real8 lab; + Real8 L[1024],S[1024]; +}; + +extern SaveMetricInterpole LastMetricInterpole; // for optimization + + + Real8 LengthInterpole(const MetricAnIso Ma,const MetricAnIso Mb, R2 AB); + Real8 abscisseInterpole(const MetricAnIso Ma,const MetricAnIso Mb, R2 AB,Real8 s,int optim=0); + + + +inline Real8 LengthInterpole(Real8 la,Real8 lb) +{ return ( Abs(la - lb) < 1.0e-6*Max3(la,lb,1.0e-20) ) ? (la+lb)/2 : la*lb*log(la/lb)/(la-lb);} + +inline Real8 abscisseInterpole(Real8 la,Real8 lb,Real8 lab,Real8 s) +{ return ( Abs(la - lb) <1.0e-6*Max3(la,lb,1.0e-20)) ? s : (exp(s*lab*(la-lb)/(la*lb))-1)*lb/(la-lb);} + +} diff --git a/contrib/bamg/bamglib/QuadTree.cpp b/contrib/bamg/bamglib/QuadTree.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44a22f2efedd88c0b861be8aa96f9c54b60380b5 --- /dev/null +++ b/contrib/bamg/bamglib/QuadTree.cpp @@ -0,0 +1,542 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#include <limits.h> +//#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "Meshio.h" +#include "Mesh2.h" +#include "QuadTree.h" + +namespace bamg { + +#define INTER_SEG(a,b,x,y) (((y) > (a)) && ((x) <(b))) +#define ABS(i) ((i)<0 ?-(i) :(i)) +#define MAX1(i,j) ((i)>(j) ?(i) :(j)) +#define NORM(i1,j1,i2,j2) MAX1(ABS((i1)-(j1)),ABS((i2)-(j2))) + +#define IJ(i,j,l) ( ( j & l) ? (( i & l) ? 3 : 2 ) :( ( i & l)? 1 : 0 )) +#define I_IJ(k,l) (( k&1) ? l : 0) +#define J_IJ(k,l) (( k&2) ? l : 0) + + +#ifdef DRAWING + +void QuadTree::Draw() +{ + QuadTreeBox * pb[ MaxDeep ]; + int pi[ MaxDeep ]; + Icoor1 ii[ MaxDeep ], jj [ MaxDeep]; + register int l=0; // level + register QuadTreeBox * b; + IntQuad hb = MaxISize; + if(!root) return; + // Int4 kkk =0; + pb[0]= root; + pi[0]= root->n>0 ?(int) root->n : 4 ; + ii[0]=jj[0]=0; + do{ + b= pb[l]; + + while (pi[l]--) + { + if (b->n>0) // Vertex QuadTreeBox none empty + { // + for (int k=0;k<b->n;k++) + { + I2 i2 = b->v[k]->i; + IMoveTo(i2.x,i2.y+50); + ILineTo(i2.x,i2.y-50); + IMoveTo(i2.x+50,i2.y); + ILineTo(i2.x-50,i2.y); + + assert(ii[l] <= i2.x); + assert(jj[l] <= i2.y); + assert(ii[l] +hb > i2.x); + assert(jj[l] +hb > i2.y); + + } + break; + } + else // Pointer QuadTreeBox + { + register int lll = pi[l]; + register QuadTreeBox *b0=b; + + if ((b=b->b[lll])) + { + hb >>=1 ; // div by 2 + register Icoor1 iii = ii[l]+I_IJ(lll,hb); + register Icoor1 jjj = jj[l]+J_IJ(lll,hb); + + pb[++l]= b; + pi[l]= 4; + ii[l]= iii; + jj[l]= jjj; + + IMoveTo(ii[l],jj[l]); + ILineTo(ii[l]+hb,jj[l]); + ILineTo(ii[l]+hb,jj[l]+hb); + ILineTo(ii[l] ,jj[l]+hb); + ILineTo(ii[l] ,jj[l]); + + + } + else + { + register Icoor1 iii = ii[l]+I_IJ(lll,hb/2); + register Icoor1 jjj = jj[l]+J_IJ(lll,hb/2); + b=b0; + + IMoveTo(iii, jjj); + ILineTo(iii+hb/2,jjj+hb/2); + IMoveTo(iii+hb/2,jjj); + ILineTo(iii ,jjj+hb/2); + + } + } + } + hb <<= 1; // mul by 2 + } while (l--); + +} + +#endif + +Vertex * QuadTree::NearestVertex(Icoor1 i,Icoor1 j) +{ + QuadTreeBox * pb[ MaxDeep ]; + int pi[ MaxDeep ]; + Icoor1 ii[ MaxDeep ], jj [ MaxDeep]; + register int l=0; // level + register QuadTreeBox * b; + IntQuad h=MaxISize,h0; + IntQuad hb = MaxISize; + Icoor1 i0=0,j0=0; + Icoor1 iplus( i<MaxISize?(i<0?0:i):MaxISize-1); + Icoor1 jplus( j<MaxISize?(j<0?0:j):MaxISize-1); + + Vertex *vn=0; + + // init for optimisation --- + b = root; + register Int4 n0; + if (!root->n) + return vn; // empty tree + + while( (n0 = b->n) < 0) + { + // search the non empty + // QuadTreeBox containing the point (i,j) + register Icoor1 hb2 = hb >> 1 ; + register int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j + register QuadTreeBox * b0= b->b[k]; + if ( ( b0 == 0) || (b0->n == 0) ) + break; // null box or empty => break + NbQuadTreeBoxSearch++; + b=b0; + i0 += I_IJ(k,hb2); // i orign of QuadTreeBox + j0 += J_IJ(k,hb2); // j orign of QuadTreeBox + hb = hb2; + } + + + if ( n0 > 0) + { + for(register int k=0;k<n0;k++) + { + I2 i2 = b->v[k]->i; + h0 = NORM(iplus,i2.x,jplus,i2.y); + if (h0 <h) { + h = h0; + vn = b->v[k];} + NbVerticesSearch++; + } + return vn; + } + // general case ----- + pb[0]= b; + pi[0]=b->n>0 ?(int) b->n : 4 ; + ii[0]=i0; + jj[0]=j0; + h=hb; + do { + b= pb[l]; + while (pi[l]--) + { + register int k = pi[l]; + + if (b->n>0) // Vertex QuadTreeBox none empty + { + NbVerticesSearch++; + I2 i2 = b->v[k]->i; + h0 = NORM(iplus,i2.x,jplus,i2.y); + if (h0 <h) + { + h = h0; + vn = b->v[k]; + } + } + else // Pointer QuadTreeBox + { + register QuadTreeBox *b0=b; + NbQuadTreeBoxSearch++; + if ((b=b->b[k])) + { + hb >>=1 ; // div by 2 + register Icoor1 iii = ii[l]+I_IJ(k,hb); + register Icoor1 jjj = jj[l]+J_IJ(k,hb); + + if (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) + { + pb[++l]= b; + pi[l]= b->n>0 ?(int) b->n : 4 ; + ii[l]= iii; + jj[l]= jjj; + + } + else + b=b0, hb <<=1 ; + } + else + b=b0; + } + } + hb <<= 1; // mul by 2 + } while (l--); + + return vn; +} + + + +Vertex * QuadTree::ToClose(Vertex & v,Real8 seuil,Icoor1 hx,Icoor1 hy) +{ + const Icoor1 i=v.i.x; + const Icoor1 j=v.i.y; + const R2 X(v.r); + const Metric Mx(v.m); + + QuadTreeBox * pb[ MaxDeep ]; + int pi[ MaxDeep ]; + Icoor1 ii[ MaxDeep ], jj [ MaxDeep]; + register int l=0; // level + register QuadTreeBox * b; + Icoor1 h=MaxISize; + Icoor1 hb = MaxISize; + Icoor1 i0=0,j0=0; + + // Vertex *vn=0; + + if (!root->n) + return 0; // empty tree + + // general case ----- + pb[0]=root; + pi[0]=root->n>0 ?(int) root->n : 4 ; + ii[0]=i0; + jj[0]=j0; + h=hb; + do { + b= pb[l]; + while (pi[l]--) + { + register int k = pi[l]; + + if (b->n>0) // Vertex QuadTreeBox none empty + { + NbVerticesSearch++; + I2 i2 = b->v[k]->i; + if ( ABS(i-i2.x) <hx && ABS(j-i2.y) <hy ) + { + R2 XY(X,b->v[k]->r); + Real8 dd; + // old code if( Mx(XY) + b->v[k]->m(XY) < seuil ) + if( (dd= LengthInterpole(Mx(XY), b->v[k]->m(XY))) < seuil ) + { + // cout << CurrentTh->Number(v) << "is To Close " + // << CurrentTh->Number( b->v[k]) << " l=" <<dd<<endl; + return b->v[k]; + } + } + } + else // Pointer QuadTreeBox + { + register QuadTreeBox *b0=b; + NbQuadTreeBoxSearch++; + if ((b=b->b[k])) + { + hb >>=1 ; // div by 2 + register long iii = ii[l]+I_IJ(k,hb); + register long jjj = jj[l]+J_IJ(k,hb); + + if (INTER_SEG(iii,iii+hb,i-hx,i+hx) && INTER_SEG(jjj,jjj+hb,j-hy,j+hy)) + { + pb[++l]= b; + pi[l]= b->n>0 ?(int) b->n : 4 ; + ii[l]= iii; + jj[l]= jjj; + + } + else + b=b0, hb <<=1 ; + } + else + b=b0; + } + } + hb <<= 1; // mul by 2 + } while (l--); + + return 0; +} + + +void QuadTree::Add( Vertex & w) +{ + QuadTreeBox ** pb , *b; + register long i=w.i.x, j=w.i.y,l=MaxISize; + pb = &root; + // cout << pb << " " << &root << endl; + while( (b=*pb) && (b->n<0)) + { + b->n--; + l >>= 1; + pb = &b->b[IJ(i,j,l)]; + } + if (b) { + if (b->n > 3 && b->v[3] == &w) return; + if (b->n > 2 && b->v[2] == &w) return; + if (b->n > 1 && b->v[1] == &w) return; + if (b->n > 0 && b->v[0] == &w) return; + } + assert(l); + while ((b= *pb) && (b->n == 4)) // the QuadTreeBox is full + { + Vertex *v4[4]; // copy of the QuadTreeBox vertices + + v4[0]= b->v[0]; + v4[1]= b->v[1]; + v4[2]= b->v[2]; + v4[3]= b->v[3]; + b->n = -b->n; // mark is pointer QuadTreeBox + b->b[0]=b->b[1]=b->b[2]=b->b[3]=0; // set empty QuadTreeBox ptr + l >>= 1; // div the size by 2 + for (register int k=0;k<4;k++) // for the 4 vertices find the sub QuadTreeBox ij + { + register int ij; + register QuadTreeBox * bb = b->b[ij=IJ(v4[k]->i.x,v4[k]->i.y,l)]; + if (!bb) + bb=b->b[ij]=NewQuadTreeBox(); // alloc the QuadTreeBox + // cout << bb << " " << k << " " << ij << endl; + bb->v[bb->n++] = v4[k]; + } + pb = &b->b[IJ(i,j,l)]; + } + if (!(b = *pb)) + b=*pb= NewQuadTreeBox(); // alloc the QuadTreeBox + // cout << b << " " << b->n << endl; + b->v[b->n++]=&w; // we add the vertex + NbVertices++; +} + +QuadTree::QuadTree(Triangles * t,long nbv) : + lenStorageQuadTreeBox(t->nbvx/8+10), + th(t), + NbQuadTreeBox(0), + NbVertices(0), + NbQuadTreeBoxSearch(0), + NbVerticesSearch(0) +{ + if (nbv == -1) nbv = t->nbv; + sb =new StorageQuadTreeBox(lenStorageQuadTreeBox); + root=NewQuadTreeBox(); + assert( MaxISize > MaxICoor); + for (Int4 i=0;i<nbv;i++) + Add(t->vertices[i]); +#ifdef DRAWING1 + Draw(); +#endif +} + +QuadTree::QuadTree() : + lenStorageQuadTreeBox(100), + th(0), + NbQuadTreeBox(0), + NbVertices(0), + NbQuadTreeBoxSearch(0), + NbVerticesSearch(0) +{ + sb =new StorageQuadTreeBox(lenStorageQuadTreeBox); + root=NewQuadTreeBox(); +} +QuadTree::StorageQuadTreeBox::StorageQuadTreeBox(long ll,StorageQuadTreeBox *nn) +{ + len = ll; + n = nn; + b = new QuadTreeBox[ll]; + for (int i = 0; i <ll;i++) + b[i].n =0,b[i].b[0]=b[i].b[1]=b[i].b[2]=b[i].b[3]=0; + bc =b; + be = b +ll; + assert(b); +} + +QuadTree::~QuadTree() +{ + delete sb; + root=0; +} + +ostream& operator <<(ostream& f, const QuadTree & qt) +{ + f << " the quadtree " << endl; + f << " NbQuadTreeBox = " << qt.NbQuadTreeBox + << " Nb Vertices = " << qt.NbVertices << endl; + f << " NbQuadTreeBoxSearch " << qt.NbQuadTreeBoxSearch + << " NbVerticesSearch " << qt.NbVerticesSearch << endl; + f << " SizeOf QuadTree" << qt.SizeOf() << endl; + // return dump(f,*qt.root); + return f; +} + +Vertex * QuadTree::NearestVertexWithNormal(Icoor1 i,Icoor1 j) +{ + QuadTreeBox * pb[ MaxDeep ]; + int pi[ MaxDeep ]; + Icoor1 ii[ MaxDeep ], jj [ MaxDeep]; + int l; // level + QuadTreeBox * b; + IntQuad h=MaxISize,h0; + IntQuad hb = MaxISize; + Icoor1 i0=0,j0=0; + Icoor1 iplus( i<MaxISize?(i<0?0:i):MaxISize-1); + Icoor1 jplus( j<MaxISize?(j<0?0:j):MaxISize-1); + + Vertex *vn=0; + + // init for optimisation --- + b = root; + register Int4 n0; + if (!root->n) + return vn; // empty tree + + while( (n0 = b->n) < 0) + { + // search the non empty + // QuadTreeBox containing the point (i,j) + register Icoor1 hb2 = hb >> 1 ; + register int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j + register QuadTreeBox * b0= b->b[k]; + if ( ( b0 == 0) || (b0->n == 0) ) + break; // null box or empty => break + NbQuadTreeBoxSearch++; + b=b0; + i0 += I_IJ(k,hb2); // i orign of QuadTreeBox + j0 += J_IJ(k,hb2); // j orign of QuadTreeBox + hb = hb2; + } + + + if ( n0 > 0) + { + for(register int k=0;k<n0;k++) + { + I2 i2 = b->v[k]->i; + // try if is in the right sens -- + h0 = NORM(iplus,i2.x,jplus,i2.y); + if (h0 <h) { + h = h0; + vn = b->v[k];} + NbVerticesSearch++; + } + if (vn) return vn; + } + // general case ----- + // INITIALISATION OF THE HEAP + l =0; // level + pb[0]= b; + pi[0]=b->n>0 ?(int) b->n : 4 ; + ii[0]=i0; + jj[0]=j0; + h=hb; + do { // walk on the tree + b= pb[l]; + while (pi[l]--) // loop on 4 element of the box + { + int k = pi[l]; + + if (b->n>0) // Vertex QuadTreeBox none empty + { + NbVerticesSearch++; + I2 i2 = b->v[k]->i; + // if good sens when try -- + + h0 = NORM(iplus,i2.x,jplus,i2.y); + if (h0 <h) + { + h = h0; + vn = b->v[k]; + } + } + else // Pointer QuadTreeBox + { + register QuadTreeBox *b0=b; + NbQuadTreeBoxSearch++; + if ((b=b->b[k])) + { + hb >>=1 ; // div by 2 + register Icoor1 iii = ii[l]+I_IJ(k,hb); + register Icoor1 jjj = jj[l]+J_IJ(k,hb); + + if (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) + { + pb[++l]= b; + pi[l]= b->n>0 ?(int) b->n : 4 ; + ii[l]= iii; + jj[l]= jjj; + + } + else + b=b0, hb <<=1 ; + } + else + b=b0; + } + } + hb <<= 1; // mul by 2 + } while (l--); + + return vn; +} + + +} // end of namespace bamg + diff --git a/contrib/bamg/bamglib/QuadTree.h b/contrib/bamg/bamglib/QuadTree.h new file mode 100644 index 0000000000000000000000000000000000000000..016698140798d01370d160ae3316ee46e72ff2db --- /dev/null +++ b/contrib/bamg/bamglib/QuadTree.h @@ -0,0 +1,111 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +namespace bamg { + +const int MaxDeep = 30; +typedef long IntQuad; +const IntQuad MaxISize = ( 1L << MaxDeep); + + +class Triangles; +class Vertex; + +class QuadTree { + public: + + class QuadTreeBox { + public: + + long n; // if n < 4 => Vertex else => QuadTreeBox; + union { + QuadTreeBox *b[4]; + Vertex * v[4]; + }; + + + }; // end class QuadTreeBox ///////////////// + + class StorageQuadTreeBox { + public: + QuadTreeBox *b,*bc,*be; + long len; + StorageQuadTreeBox *n; // next StorageQuadTreeBox + StorageQuadTreeBox(long ,StorageQuadTreeBox * =0); + ~StorageQuadTreeBox() + { //cout << "~StorageQuadTreeBox " << this << " n " << n << " b " << b << endl; + if(n) delete n; + delete [] b; + } + long SizeOf() const { + return len*sizeof(QuadTreeBox)+sizeof(StorageQuadTreeBox)+ (n?n->SizeOf():0); + } + }; // end class StorageQuadTreeBox + + StorageQuadTreeBox * sb; + + + long lenStorageQuadTreeBox; + +public: + QuadTreeBox * root; + Triangles *th; + long NbQuadTreeBox,NbVertices; + long NbQuadTreeBoxSearch,NbVerticesSearch; + Vertex * NearestVertex(Icoor1 i,Icoor1 j); + Vertex * NearestVertexWithNormal(Icoor1 i,Icoor1 j); // new version + Vertex * ToClose(Vertex & ,Real8 ,Icoor1,Icoor1); + long SizeOf() const {return sizeof(QuadTree)+sb->SizeOf();} + +#ifdef DRAWING + void Draw(); +#endif + + void Add( Vertex & w); + + QuadTreeBox* NewQuadTreeBox() + { + ///cout << "NewQuadTreeBox " << sb << " " << sb->bc << " " + //<< sb->be << " " <<lenStorageQuadTreeBox <<endl; + if(! (sb->bc<sb->be)) + sb=new StorageQuadTreeBox(lenStorageQuadTreeBox,sb); + + assert(sb && (sb->bc->n == 0)); + NbQuadTreeBox++; + return sb->bc++; + } + ~QuadTree(); + QuadTree(Triangles * t,long nbv=-1); + QuadTree(); + friend ostream& operator <<(ostream& f, const QuadTree & qt); + + + +}; +} +//#undef IJ diff --git a/contrib/bamg/bamglib/R2.cpp b/contrib/bamg/bamglib/R2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e79e4bf99129c13864cb3d7ec64a0c2ceee9f4d --- /dev/null +++ b/contrib/bamg/bamglib/R2.cpp @@ -0,0 +1,31 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#include <iostream> +using namespace std; +#include "R2.h" diff --git a/contrib/bamg/bamglib/R2.h b/contrib/bamg/bamglib/R2.h new file mode 100644 index 0000000000000000000000000000000000000000..cbb3df46e29723cecce546fb466e4ba70d9533e5 --- /dev/null +++ b/contrib/bamg/bamglib/R2.h @@ -0,0 +1,135 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +namespace bamg { +template <class R,class RR> class P2xP2; + +template <class R,class RR> +class P2 { + +public: + R x,y; + P2 () :x(0),y(0) {}; + P2 (R a,R b) :x(a),y(b) {} + P2 (P2 A,P2 B) : x(B.x-A.x),y(B.y-A.y) {} + P2<R,RR> operator+(const P2<R,RR> & cc) const {return P2<R,RR>(x+cc.x,y+cc.y);} + P2<R,RR> operator-(const P2<R,RR> & cc) const {return P2<R,RR>(x-cc.x,y-cc.y);} + P2<R,RR> operator-() const{return P2<R,RR>(-x,-y);} +// RR operator*(const P2<R,RR> & cc) const {return (RR) x* (RR) cc.x+(RR) y* (RR) cc.y;} // produit scalaire + RR operator,(const P2<R,RR> & cc) const {return (RR) x* (RR) cc.x+(RR) y* (RR) cc.y;} // produit scalaire + P2<R,RR> operator*(R cc) const {return P2<R,RR>(x*cc,y*cc);} + // P2<R,RR> operator*(RR cc) const {return P2<R,RR>((R)(x*cc),(R)(y*cc));} + P2<R,RR> operator/(R cc) const {return P2<R,RR>(x/cc,y/cc);} + P2<R,RR> operator+=(const P2<R,RR> & cc) {x += cc.x;y += cc.y;return *this;} + P2<R,RR> operator/=(const R r) {x /= r;y /= r;return *this;} + P2<R,RR> operator*=(const R r) {x *= r;y *= r;return *this;} + P2<R,RR> operator-=(const P2<R,RR> & cc) {x -= cc.x;y -= cc.y;return *this;} +// P2<R,RR> Orthogonal(const P2<R,RR> r) {return P2<R,RR>(-r.y,r.x);} + }; + +template <class R,class RR> +class P2xP2 { // x ligne 1 y ligne2 + + friend ostream& operator <<(ostream& f, const P2xP2<R,RR> & c) + { f << '[' << c.x << ',' << c.y << ']' <<flush ; return f; } + + friend P2<R,RR> operator*(P2<R,RR> c,P2xP2<R,RR> cc) + {return P2<R,RR>(c.x*cc.x.x + c.y*cc.y.x, c.x*cc.x.y + c.y*cc.y.y);} + + + public: + P2<R,RR> x,y; + P2xP2 (): x(),y() {} + P2xP2 (P2<R,RR> a,P2<R,RR> b): x(a),y(b) {} + P2xP2 (P2<R,RR> a,P2<R,RR> b,P2<R,RR> c ): x(b-a),y(c-a) {} + P2xP2 (R xx,R xy,R yx,R yy) :x(xx,xy),y(yx,yy) {} + P2<R,RR> operator*(const P2<R,RR> c) const {return P2<R,RR>(x.x*c.x + x.y*c.y, y.x*c.x + y.y*c.y);} + P2xP2<R,RR> operator*(P2xP2<R,RR> c) const + { return P2xP2<R,RR>(x.x*c.x.x + x.y*c.y.x, + x.x*c.x.y + x.y*c.y.y, + y.x*c.x.x + y.y*c.y.x, + y.x*c.x.y + y.y*c.y.y);} + RR det() const {return (RR) x.x* (RR) y.y - (RR) x.y * (RR) y.x;} + P2xP2<R,RR> inv() const + { RR d = (*this).det(); + return P2xP2<R,RR>((R)( y.y /d) ,(R)(-x.y/d),(R)( -y.x/d) ,(R)( x.x/d) ); + }; + P2xP2<R,RR> t() {return P2xP2<R,RR>(x.x,y.x,x.y,y.y);} //transposer + P2<R,RR>tx() {return P2<R,RR>(x.x,y.x);} + P2<R,RR>ty() {return P2<R,RR>(x.y,y.y);} + +}; + + + +//template <class R,class RR> // transposer +//inline P2xP2<R,RR> t(P2xP2<R,RR> m) +// {return P2xP2<R,RR>(m.x.x,m.y.x,m.x.y,m.y.y);} + +template <class R,class RR> +inline RR Det(const P2<R,RR> x,const P2<R,RR> y) { + return (RR) x.x * (RR) y.y - (RR) x.y * (RR) y.x ;} + +template <class R,class RR> +inline RR Area2 (const P2<R,RR> a,const P2<R,RR> b,const P2<R,RR> c) { + return Det(b-a,c-a) ;} + +template <class R,class RR> +inline R Norme1 (const P2<R,RR> x) { + return (Abs(x.x)+Abs(x.y)) ;} + +template <class R,class RR> +inline R NormeInfini (const P2<R,RR> x) { + return Max(Abs(x.x),Abs(x.y)) ;} + +template <class R,class RR> +inline RR Norme2_2 (const P2<R,RR> x) { + return (RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y ;} + +template <class R,class RR> +inline RR Norme2 (const P2<R,RR> x) { + return sqrt((RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y) ;} + +template <class R,class RR> +inline P2<R,RR> Orthogonal (const P2<R,RR> x) { + return P2<R,RR>(-x.y,x.x);} + +template <class R,class RR> +inline ostream& operator <<(ostream& f, const P2<R,RR> & c) + { f << '[' << c.x << ',' << c.y <<']' <<flush ; return f; } + + +/*template <class R,class RR> +inline P2<R,RR> Min2(P2<R,RR> x,P2<R,RR> y) + {return P2<R,RR>(Min(x.x,y.x),Min(x.y,y.y) ;} + +template <class R,class RR> +inline P2<R,RR> Max2(P2<R,RR> x,P2<R,RR> y) + {return P2<R,RR>(Max(x.x,y.x),Max(x.y,y.y) ;} +*/ +} diff --git a/contrib/bamg/bamglib/SetOfE4.cpp b/contrib/bamg/bamglib/SetOfE4.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c68b5ab26ba2e9208fc8d28a3127ac0e6cfdcd5f --- /dev/null +++ b/contrib/bamg/bamglib/SetOfE4.cpp @@ -0,0 +1,84 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#include <iostream> +using namespace std; +#include "meshtype.h" +#include "SetOfE4.h" + +namespace bamg { + + SetOfEdges4::SetOfEdges4(Int4 mmx,Int4 nnx) + {nx=nnx; + nbax=mmx; + NbOfEdges = 0; + tete= new Int4 [nx]; + Int4 i=nx; + while (i--) + tete[i] = -1;// vide + Edges =new Int4Edge[nbax]; + } + + Int4 SetOfEdges4::find(Int4 ii,Int4 jj) +{ + if (tete == 0 ) { + cerr <<"SetOfEdges4::find \nplus de tete de liste\n"; + MeshError(888);} + Int4 n = tete[ Abs( ii ) % nx ]; + + while (n >= 0) + if (ii == Edges[n].i && jj == Edges[n].j) + return n; + else n = Edges[n].next; + return -1; // n'existe pas +} + + Int4 SetOfEdges4::add(Int4 ii,Int4 jj) +{ + if (tete == 0 ) { + cerr << "SetOfEdges4::add\n plus de tete de liste \n" << endl; + MeshError(888);} + + Int4 h; + Int4 n = tete[ h = Abs( ii ) % nx ]; + while (n >= 0) + if (ii == Edges[n].i && jj == Edges[n].j) + return n; + else n = Edges[n].next; + if (nbax <=NbOfEdges ) { + cerr << " SetOfEdges4::add\noverflow de la pile " << nbax << " " << NbOfEdges << endl; + MeshError(888);} + + Edges[NbOfEdges].i=ii; + Edges[NbOfEdges].j=jj; + Edges[NbOfEdges].next= tete[h]; + tete[h] = NbOfEdges; + return NbOfEdges ++; +} + + +} // end of namespace bamg diff --git a/contrib/bamg/bamglib/SetOfE4.h b/contrib/bamg/bamglib/SetOfE4.h new file mode 100644 index 0000000000000000000000000000000000000000..5179ce9a911b4df270e1a88eda8dc6f0cbd0b80f --- /dev/null +++ b/contrib/bamg/bamglib/SetOfE4.h @@ -0,0 +1,64 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ + +#ifndef _SetOfEdge4_h +#define _SetOfEdge4_h + +namespace bamg { + +class SetOfEdges4 ; +class Int4Edge{ +friend class SetOfEdges4; +public: + Int4 i,j; + Int4 next; +}; + +class SetOfEdges4 { + Int4 nx,nbax,NbOfEdges; + Int4 * tete; + Int4Edge * Edges; + +public: + SetOfEdges4(Int4 ,Int4);// nb Edges mx , nb de sommet + ~SetOfEdges4() {// cout << " delete SetofArete " << endl ; + delete [] tete; delete [] Edges;} + Int4 add (Int4 ii,Int4 jj); + Int4 addtrie (Int4 ii,Int4 jj) {return ii <=jj ? add (ii,jj) : add (jj,ii) ;} + Int4 nb(){return NbOfEdges;} + Int4 find (Int4 ii,Int4 jj); + Int4 findtrie (Int4 ii,Int4 jj) {return ii <=jj ? find (ii,jj) : find (jj,ii) ;} + // inline void close(); + Int4 i(Int4 k){return Edges[k].i;} + Int4 j(Int4 k){return Edges[k].j;} + Int4 newarete(Int4 k){return NbOfEdges == k+1;} + Int4Edge & operator[](Int4 k){return Edges[k];} +}; +} + +#endif diff --git a/contrib/bamg/bamglib/error.hpp b/contrib/bamg/bamglib/error.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a87240be5d99c4eab9460fa2b81c69963d7c0aff --- /dev/null +++ b/contrib/bamg/bamglib/error.hpp @@ -0,0 +1,135 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#ifndef ERROR_H +#define ERROR_H +#include <cassert> +#include <string> +// #include "throwassert.hpp" +#include <exception> + +extern int TheCurrentLine; + +#if defined(__GNUC__) && __GNUC__+0 < 3 +#include <strstream.h> + typedef istrstream istringstream ; + typedef ostrstream ostringstream ; +#define ENDS << '\0' +#define OLDCPP 1 +#else +// car ostringstream n'est pas encore defin sous g++ +// +#include <sstream> +#define ENDS + +#endif + + using std::exception; + +//extern long mpirank; + +class Error : public exception +{ public: + enum CODE_ERROR { NONE, COMPILE_ERROR,EXEC_ERROR, MEM_ERROR,MESH_ERROR,ASSERT_ERROR,INTERNAL_ERROR, UNKNOWN }; + + +private: + std::string message; + const CODE_ERROR code; +protected: + Error(CODE_ERROR c,const char * t1,const char * t2,const char * t3=0, + int n=0,const char * t4=0,const char * t5=0,const char * t6=0, + const char * t7=0,const char * t8=0,const char * t9=0) + : message(),code(c) + { + using namespace std; + ostringstream mess; + if(t1) mess << t1; + if(t2) mess << t2; + if(t3) mess << t3 << n ; + if(t4) mess << t4; + if(t5) mess << t5; + if(t6) mess << t6; + if(t7) mess << t7; + if(t8) mess << t8; + if(t9) mess << t9; + message = mess.str(); + // extern void ShowDebugStack(); + //ShowDebugStack(); + if (c!=NONE) cerr << message << endl; // cerr << " at exec line " << TheCurrentLine << endl; + } +public: + virtual int errcode() const {return code;} + virtual const char * what() const throw () { return message.c_str(); } + virtual ~Error() throw () {} +}; + +class ErrorCompile : public Error +{ + public: + ErrorCompile(const char * Text,int l,const char * t2="") : + Error(COMPILE_ERROR,"Compile error : ",Text,"\n\tline number :",l,", ", t2) {} +}; + +class ErrorExec : public Error +{ + public: + ErrorExec(const char * Text,int l) : + Error(UNKNOWN,"Exec error : ",Text, "\n -- number :", l) {} +}; + +class ErrorInternal : public Error +{ + public: + ErrorInternal(const char * Text,int l,const char * t2="") : + Error(INTERNAL_ERROR,"Internal error : ",Text, "\n\tline :",l,", in file ", t2) {} +}; +class ErrorAssert : public Error +{ + public: + ErrorAssert(const char * Text,const char *file,const int line) : + Error(ASSERT_ERROR,"Assertion fail : (",Text, ")\n\tline :", line,", in file ",file) {} +}; + + +class ErrorMemory : public Error +{ public: + ErrorMemory(const char * Text,int l=0) : + Error(MEM_ERROR,"Memory Error : ",Text," number: ",l) {} +}; + +class ErrorExit : public Error +{ + int codeexit; +public: + ErrorExit(const char * ,int l) : + Error(NONE,"exit","(","",l,")"), codeexit(l) {} + // the exit code fo freefem++ is given by l + int errcode() const{return codeexit;} +}; + +#endif diff --git a/contrib/bamg/bamglib/meshtype.h b/contrib/bamg/bamglib/meshtype.h new file mode 100644 index 0000000000000000000000000000000000000000..4ab54460630a77565cce6f1244ae55caf4960ded --- /dev/null +++ b/contrib/bamg/bamglib/meshtype.h @@ -0,0 +1,71 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#ifndef MESHTYPE_H +#define MESHTYPE_H +#include <limits.h> +namespace bamg { +template<class T> inline T Square (const T &a) { return a*a;} +template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;} +template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;} +template<class T> inline T Abs (const T &a){return a <0 ? -a : a;} +template<class T> inline double Norme (const T &a){return sqrt(a*a);} +template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;} +// for pb on microsoft compiler +template<class T> inline T Max3 (const T &a,const T & b,const T & c){return Max(Max(a,b),c);} +template<class T> inline T Min3 (const T &a,const T & b,const T & c){return Min(Min(a,b),c);} + +typedef float Real4; +typedef double Real8; +typedef short Int1; +typedef short Int2; +typedef long Int4; + +#if LONG_BIT > 63 +// for alpha and silicon + typedef int Icoor1; + typedef long Icoor2; + const Icoor1 MaxICoor = 1073741823; // 2^30-1 + const Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ; + +#elif defined(BAMG_LONG_LONG) + typedef long Icoor1; + typedef long long Icoor2; + const Icoor1 MaxICoor = 1073741823;// 2^30-1 +// not a const due to a bug in hp compiler +#define MaxICoor22 2305843004918726658LL +//const Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ; +#else + typedef int Icoor1; + typedef double Icoor2; + const Icoor1 MaxICoor = 8388608; // 2^23 + const Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ; +#endif + class Triangles; +extern void MeshError(int Err,Triangles *Th=0) ; +} +#endif diff --git a/contrib/bamg/error.hpp b/contrib/bamg/error.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a87240be5d99c4eab9460fa2b81c69963d7c0aff --- /dev/null +++ b/contrib/bamg/error.hpp @@ -0,0 +1,135 @@ +// -*- Mode : c++ -*- +// +// SUMMARY : +// USAGE : +// ORG : +// AUTHOR : Frederic Hecht +// E-MAIL : 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 + */ +#ifndef ERROR_H +#define ERROR_H +#include <cassert> +#include <string> +// #include "throwassert.hpp" +#include <exception> + +extern int TheCurrentLine; + +#if defined(__GNUC__) && __GNUC__+0 < 3 +#include <strstream.h> + typedef istrstream istringstream ; + typedef ostrstream ostringstream ; +#define ENDS << '\0' +#define OLDCPP 1 +#else +// car ostringstream n'est pas encore defin sous g++ +// +#include <sstream> +#define ENDS + +#endif + + using std::exception; + +//extern long mpirank; + +class Error : public exception +{ public: + enum CODE_ERROR { NONE, COMPILE_ERROR,EXEC_ERROR, MEM_ERROR,MESH_ERROR,ASSERT_ERROR,INTERNAL_ERROR, UNKNOWN }; + + +private: + std::string message; + const CODE_ERROR code; +protected: + Error(CODE_ERROR c,const char * t1,const char * t2,const char * t3=0, + int n=0,const char * t4=0,const char * t5=0,const char * t6=0, + const char * t7=0,const char * t8=0,const char * t9=0) + : message(),code(c) + { + using namespace std; + ostringstream mess; + if(t1) mess << t1; + if(t2) mess << t2; + if(t3) mess << t3 << n ; + if(t4) mess << t4; + if(t5) mess << t5; + if(t6) mess << t6; + if(t7) mess << t7; + if(t8) mess << t8; + if(t9) mess << t9; + message = mess.str(); + // extern void ShowDebugStack(); + //ShowDebugStack(); + if (c!=NONE) cerr << message << endl; // cerr << " at exec line " << TheCurrentLine << endl; + } +public: + virtual int errcode() const {return code;} + virtual const char * what() const throw () { return message.c_str(); } + virtual ~Error() throw () {} +}; + +class ErrorCompile : public Error +{ + public: + ErrorCompile(const char * Text,int l,const char * t2="") : + Error(COMPILE_ERROR,"Compile error : ",Text,"\n\tline number :",l,", ", t2) {} +}; + +class ErrorExec : public Error +{ + public: + ErrorExec(const char * Text,int l) : + Error(UNKNOWN,"Exec error : ",Text, "\n -- number :", l) {} +}; + +class ErrorInternal : public Error +{ + public: + ErrorInternal(const char * Text,int l,const char * t2="") : + Error(INTERNAL_ERROR,"Internal error : ",Text, "\n\tline :",l,", in file ", t2) {} +}; +class ErrorAssert : public Error +{ + public: + ErrorAssert(const char * Text,const char *file,const int line) : + Error(ASSERT_ERROR,"Assertion fail : (",Text, ")\n\tline :", line,", in file ",file) {} +}; + + +class ErrorMemory : public Error +{ public: + ErrorMemory(const char * Text,int l=0) : + Error(MEM_ERROR,"Memory Error : ",Text," number: ",l) {} +}; + +class ErrorExit : public Error +{ + int codeexit; +public: + ErrorExit(const char * ,int l) : + Error(NONE,"exit","(","",l,")"), codeexit(l) {} + // the exit code fo freefem++ is given by l + int errcode() const{return codeexit;} +}; + +#endif diff --git a/contrib/bamg/main.cpp b/contrib/bamg/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b2c3fd2b564961cc44ad1c7e35c55d83e63d898 --- /dev/null +++ b/contrib/bamg/main.cpp @@ -0,0 +1,22 @@ +#include <iostream> +using namespace std; +#include "Mesh2.h" +#include "RNM.hpp" +#include "Mesh2d.hpp" +#include <set> +#include "bamg-gmsh.hpp" +long verbosity=1; +int main(int argc,const char ** argv) +{ + assert(argc>1); + Mesh2 Th(argv[1]); + KN<double> data(30); + data = -1e200; + int nv = Th.nv; + KN<double> m11(nv),m12(nv),m22(nv); + double h=0.01; + m11=1/(h*h); + m22=1/(h*h); + m12=0.; + +} diff --git a/contrib/bamg/ufunction.hpp b/contrib/bamg/ufunction.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dd2e1193108603355249999ecde8ad8ef32a9d13 --- /dev/null +++ b/contrib/bamg/ufunction.hpp @@ -0,0 +1,9 @@ + +// some usefull function +template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;} +template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;} +template<class T> inline T Abs (const T &a){return a <0 ? -a : a;} +template<class T> inline double Norme (const T &a){return sqrt(a*a);} +template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;} +template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);} +template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}