diff --git a/src/geometry/mesh_sphere_intersector.hh b/src/geometry/mesh_sphere_intersector.hh index d9df19956..17c4fc1f5 100644 --- a/src/geometry/mesh_sphere_intersector.hh +++ b/src/geometry/mesh_sphere_intersector.hh @@ -1,101 +1,105 @@ /** * @file mesh_segment_intersector.hh * * @author Clement Roux-Langlois * * @date creation: Wed Jun 10 2015 * * @brief Computation of mesh intersection with sphere(s) * * @section LICENSE * * Copyright (©) 2010-2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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 3 of the License, or (at your option) any * later version. * * Akantu 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 Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SPHERE_INTERSECTOR_HH__ #define __AKANTU_MESH_SPHERE_INTERSECTOR_HH__ #include "aka_common.hh" #include "mesh_geom_intersector.hh" #include "mesh_geom_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /// Here, we know what kernel we have to use typedef Spherical SK; template class MeshSphereIntersector : public MeshGeomIntersector, SK::Sphere_3, SK> { /// Parent class type typedef MeshGeomIntersector, SK::Sphere_3, SK> parent_type; /// Result of intersection function type typedef typename IntersectionTypeHelper, K>, K::Segment_3>::intersection_type result_type; /// Pair of intersection points and element id typedef std::pair pair_type; public: /// Construct from mesh explicit MeshSphereIntersector(const Mesh & mesh); /// Destructor virtual ~MeshSphereIntersector(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the new_node_per_elem array AKANTU_GET_MACRO(NewNodePerElem, new_node_per_elem, const Array) public: /// Construct the primitive tree object virtual void constructData(); /** * @brief Computes the intersection of the mesh with a sphere * * @param query (sphere) to compute the intersections with the mesh */ virtual void computeIntersectionQuery(const SK::Sphere_3 & query); /// Build the IGFEM mesh virtual void buildResultFromQueryList(const std::list & query); /// Remove the additionnal nodes void removeAdditionnalNodes(); protected: - /// new node per element + /// new node per element (column 0: number of new nodes, then odd is the intersection node number and even the ID of the sintersected segment) Array new_node_per_elem; /// number of fem nodes in the initial mesh const UInt nb_nodes_fem; + + /// number of primitive in an element of the template type + const UInt nb_prim_by_el; + }; __END_AKANTU__ #include "mesh_sphere_intersector_tmpl.hh" #endif // __AKANTU_MESH_SPHERE_INTERSECTOR_HH__ diff --git a/src/geometry/mesh_sphere_intersector_tmpl.hh b/src/geometry/mesh_sphere_intersector_tmpl.hh index 85a7036ca..2561dcb6a 100644 --- a/src/geometry/mesh_sphere_intersector_tmpl.hh +++ b/src/geometry/mesh_sphere_intersector_tmpl.hh @@ -1,336 +1,363 @@ /** * @file mesh_sphere_intersector_tmpl.hh * * @author Clément Roux-Langlois * * @date creation: Wed june 10 2015 * @date last modification: Wed June 17 2015 * * @brief Computation of mesh intersection with spheres * * @section LICENSE * * Copyright (©) 2010-2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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 3 of the License, or (at your option) any * later version. * * Akantu 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 Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ #define __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" #include "tree_type_helper.hh" __BEGIN_AKANTU__ template MeshSphereIntersector::MeshSphereIntersector(const Mesh & mesh): parent_type(mesh), new_node_per_elem(0, 1 + 4*(dim-1)), - nb_nodes_fem(mesh.getNodes().getSize()) + nb_nodes_fem(mesh.getNodes().getSize()), + nb_prim_by_el(0) { this->constructData(); for(Mesh::type_iterator it = mesh.firstType(dim); it != mesh.lastType(dim); ++it){ #if defined(AKANTU_IGFEM) if(*it == _triangle_3){ // Addition of the igfem types in the mesh const_cast(this->mesh).addConnectivityType(_igfem_triangle_4, _not_ghost); const_cast(this->mesh).addConnectivityType(_igfem_triangle_4, _ghost); const_cast(this->mesh).addConnectivityType(_igfem_triangle_5, _not_ghost); const_cast(this->mesh).addConnectivityType(_igfem_triangle_5, _ghost); } else if( (*it != _triangle_3) && (*it != _igfem_triangle_4) && (*it != _igfem_triangle_5) ) AKANTU_DEBUG_ERROR("Not ready for mesh type " << *it); + + if( (type == _triangle_3) || (type == _igfem_triangle_4) || (type == _igfem_triangle_5) ){ + UInt & tmp = const_cast(this->nb_prim_by_el); + tmp = 3; + } + else + AKANTU_DEBUG_ERROR("Not ready for mesh type " << type); #else if( (*it != _triangle_3) ) AKANTU_DEBUG_ERROR("Not ready for mesh type " << *it); #endif } } template MeshSphereIntersector::~MeshSphereIntersector() {} template void MeshSphereIntersector::constructData() { this->new_node_per_elem.resize(this->mesh.getConnectivity(type).getSize()); this->new_node_per_elem.clear(); MeshGeomIntersector, SK::Sphere_3, SK>::constructData(); } template void MeshSphereIntersector::computeIntersectionQuery(const SK::Sphere_3 & query) { AKANTU_DEBUG_IN(); + Array connec_type_tmpl = this->mesh.getConnectivity(type); Array & nodes = const_cast &>(this->mesh.getNodes()); UInt nb_node = nodes.getSize() ; Real tol = 1e-10; typedef boost::variant sk_inter_res; TreeTypeHelper, Spherical>::const_iterator it = this->factory.getPrimitiveList().begin(), end= this->factory.getPrimitiveList().end(); NewNodesEvent new_nodes; for(; it!=end; ++it){ std::list s_results; CGAL::intersection(*it, query, std::back_inserter(s_results)); if(s_results.size()==1){ // just one point if (pair_type * pair = boost::get(&s_results.front())){ if(pair->second==1){ // not a point tangent to the sphere // Addition of the new node Vector new_node(dim, 0.0); SK::Circular_arc_point_3 arc_point = pair->first; new_node(0) = to_double(arc_point.x()); new_node(1) = to_double(arc_point.y()); bool is_on_mesh = false, is_new = true; - UInt n = nb_nodes_fem-1; + UInt n = nb_nodes_fem; + // check if we already compute this intersection for a neighboor element for(; n != nb_node; ++n){ if( ( pow((new_node(0)-nodes(n,0)),2) + pow((new_node(1)-nodes(n,1)),2) ) < pow(tol,2) ){ is_new = false; break; } } Real x1 = to_double(it->source().x()), y1 = to_double(it->source().y()), x2 = to_double(it->target().x()), y2 = to_double(it->target().y()), l = pow( pow((new_node(0)-x1),2) + pow((new_node(1)-y1),2), 1/2); + // Check if we are close from a node of the segment if( ( ( pow((new_node(0)-x1),2) + pow((new_node(1)-y1),2) ) < pow(l*tol,2) ) || ( ( pow((new_node(0)-x2),2) + pow((new_node(1)-y2),2) ) < pow(l*tol,2) ) ){ is_on_mesh = true; is_new = false; } if(is_new){ nodes.push_back(new_node); new_nodes.getList().push_back(nb_node); nb_node += 1 ; } if(!is_on_mesh){ new_node_per_elem(it->id(), 0) += 1; new_node_per_elem(it->id(), ( 2*new_node_per_elem(it->id(),0)) - 1 ) = n ; - new_node_per_elem(it->id(), 2*new_node_per_elem(it->id(),0) ) = it->segId() ; + new_node_per_elem(it->id(), 2*new_node_per_elem(it->id(),0) ) = it->segId(); + } + else{ + // if intersection is at a node, write node number (in el) in pennultimate position + if( ( pow((new_node(0)-x1),2) + pow((new_node(1)-y1),2) ) < pow(l*tol,2) ) + new_node_per_elem(it->id(), (new_node_per_elem.getNbComponent() - 2 ) ) + = it->segId()-1 ; + else + new_node_per_elem(it->id(), (new_node_per_elem.getNbComponent() - 2 ) ) + = it->segId() % this->nb_prim_by_el; } } } } } const_cast(this->mesh).sendEvent(new_nodes); AKANTU_DEBUG_OUT(); } template void MeshSphereIntersector::removeAdditionnalNodes() { AKANTU_DEBUG_IN(); RemovedNodesEvent remove_nodes(this->mesh); Array & nodes_removed = remove_nodes.getList(); Array & new_numbering = remove_nodes.getNewNumbering(); UInt nnod = 0; for(; nnod != nb_nodes_fem ; ++nnod){ new_numbering(nnod) = nnod ; } for(nnod = nb_nodes_fem ; nnod != this->mesh.getNodes().getSize(); ++nnod){ new_numbering(nnod) = UInt(-1) ; nodes_removed.push_back(nnod); } const_cast(this->mesh).sendEvent(remove_nodes); AKANTU_DEBUG_OUT(); } #if defined(AKANTU_IGFEM) template void MeshSphereIntersector::buildResultFromQueryList(const std::list & query_list) { AKANTU_DEBUG_IN(); this->computeIntersectionQueryList(query_list); Array connec_type_tmpl = this->mesh.getConnectivity(type); Array & connec_igfem_tri4 = const_cast &>(this->mesh.getConnectivity(_igfem_triangle_4)), & connec_igfem_tri5 = const_cast &>(this->mesh.getConnectivity(_igfem_triangle_5)), & connec_tri3 = const_cast &>(this->mesh.getConnectivity(_triangle_3)); Element element_tri3(_triangle_3, 0, _not_ghost, _ek_regular), element_tri4(_igfem_triangle_4, 0, _not_ghost, _ek_igfem), element_tri5(_igfem_triangle_5, 0, _not_ghost, _ek_igfem); NewElementsEvent new_elements; UInt n_new_el = 0; Array & new_elements_list = new_elements.getList() ; new_elements.getList().extendComponentsInterlaced(2, 1); RemovedElementsEvent remove_elem(this->mesh); remove_elem.getNewNumbering().alloc(connec_type_tmpl.getSize(), 1, type, _not_ghost); Array & new_numbering = remove_elem.getNewNumbering(type, _not_ghost); UInt new_nb_type_tmpl = 0; // Meter of the number of element (type) will we loop on elements for(UInt nel=0; nel != new_node_per_elem.getSize(); ++nel){ - if( (type != _triangle_3) && (new_node_per_elem(nel,0)==0) ){ + if( (type != _triangle_3) + && ( (new_node_per_elem(nel,0)==0) + || ( (new_node_per_elem(nel,0) == 1) + && ( ( (new_node_per_elem(nel,2)+1) % this->nb_prim_by_el ) + != new_node_per_elem(nel, new_node_per_elem.getNbComponent() - 2) ) ) ) ){ Element element_type_tmpl(type, 0, _not_ghost); new_elements_list.resize(n_new_el+1); Vector ctri3(3); ctri3(0) = connec_type_tmpl(nel,0); ctri3(1) = connec_type_tmpl(nel,1); ctri3(2) = connec_type_tmpl(nel,2); UInt nb_tri3 = connec_tri3.getSize(); connec_tri3.push_back(ctri3); element_tri3.element = nb_tri3; new_elements_list(n_new_el,0) = element_tri3; element_type_tmpl.element = nel; new_elements_list(n_new_el,1) = element_type_tmpl; new_numbering(nel) = UInt(-1); ++n_new_el; } - else if(new_node_per_elem(nel,0)!=0){ + else if( (new_node_per_elem(nel,0)!=0) + && !( (new_node_per_elem(nel,0) == 1) + && ( ( (new_node_per_elem(nel,2)+1) % this->nb_prim_by_el ) + != new_node_per_elem(nel, new_node_per_elem.getNbComponent() - 2) ) ) ){ Element element_type_tmpl(type, 0, _not_ghost); new_elements_list.resize(n_new_el+1); switch(new_node_per_elem(nel,0)){ case 1 :{ Vector ctri4(4); switch(new_node_per_elem(nel,2)){ case 1 : ctri4(0) = connec_type_tmpl(nel,2); ctri4(1) = connec_type_tmpl(nel,0); ctri4(2) = connec_type_tmpl(nel,1); break; case 2 : ctri4(0) = connec_type_tmpl(nel,0); ctri4(1) = connec_type_tmpl(nel,1); ctri4(2) = connec_type_tmpl(nel,2); break; case 3 : ctri4(0) = connec_type_tmpl(nel,1); ctri4(1) = connec_type_tmpl(nel,2); ctri4(2) = connec_type_tmpl(nel,0); break; default : AKANTU_DEBUG_ERROR("A triangle have only 3 segments not "<< new_node_per_elem(nel,2)); break; } ctri4(3) = new_node_per_elem(nel,1); UInt nb_tri4 = connec_igfem_tri4.getSize(); connec_igfem_tri4.push_back(ctri4); element_tri4.element = nb_tri4; //new_elements.getList().push_back(element_tri4); new_elements_list(n_new_el,0) = element_tri4; if(type == _igfem_triangle_4) - new_numbering.push_back(connec_igfem_tri4.getSize()-2); + new_numbering.push_back(connec_igfem_tri4.getSize()-2); break; } case 2 :{ Vector ctri5(5); if( (new_node_per_elem(nel,2)==1) && (new_node_per_elem(nel,4)==2) ){ ctri5(0) = connec_type_tmpl(nel,1); ctri5(1) = connec_type_tmpl(nel,2); ctri5(2) = connec_type_tmpl(nel,0); ctri5(3) = new_node_per_elem(nel,3); ctri5(4) = new_node_per_elem(nel,1); } else if((new_node_per_elem(nel,2)==1) && (new_node_per_elem(nel,4)==3)){ ctri5(0) = connec_type_tmpl(nel,0); ctri5(1) = connec_type_tmpl(nel,1); ctri5(2) = connec_type_tmpl(nel,2); ctri5(3) = new_node_per_elem(nel,1); ctri5(4) = new_node_per_elem(nel,3); } else if((new_node_per_elem(nel,2)==2) && (new_node_per_elem(nel,4)==3)){ ctri5(0) = connec_type_tmpl(nel,2); ctri5(1) = connec_type_tmpl(nel,0); ctri5(2) = connec_type_tmpl(nel,1); ctri5(3) = new_node_per_elem(nel,3); ctri5(4) = new_node_per_elem(nel,1); } else if((new_node_per_elem(nel,2)==2) && (new_node_per_elem(nel,4)==1)){ ctri5(0) = connec_type_tmpl(nel,1); ctri5(1) = connec_type_tmpl(nel,2); ctri5(2) = connec_type_tmpl(nel,0); ctri5(3) = new_node_per_elem(nel,1); ctri5(4) = new_node_per_elem(nel,3); } else if((new_node_per_elem(nel,2)==3) && (new_node_per_elem(nel,4)==1)){ ctri5(0) = connec_type_tmpl(nel,0); ctri5(1) = connec_type_tmpl(nel,1); ctri5(2) = connec_type_tmpl(nel,2); ctri5(3) = new_node_per_elem(nel,3); ctri5(4) = new_node_per_elem(nel,1); } else if((new_node_per_elem(nel,2)==3) && (new_node_per_elem(nel,4)==2)){ ctri5(0) = connec_type_tmpl(nel,2); ctri5(1) = connec_type_tmpl(nel,0); ctri5(2) = connec_type_tmpl(nel,1); ctri5(3) = new_node_per_elem(nel,1); ctri5(4) = new_node_per_elem(nel,3); } else{ AKANTU_DEBUG_ERROR("A triangle have only 3 segments not "<< new_node_per_elem(nel,2) << "and" << new_node_per_elem(nel,4)); } connec_igfem_tri5.push_back(ctri5); UInt nb_tri5 = connec_igfem_tri5.getSize(); element_tri5.element = nb_tri5; //new_elements.getList().push_back(element_tri5); new_elements_list(n_new_el,0) = element_tri5; if(type == _igfem_triangle_5){ new_numbering.push_back(new_nb_type_tmpl); ++new_nb_type_tmpl; } break; } default: AKANTU_DEBUG_ERROR("Igfem cannot add "<< new_node_per_elem(nel,0) << " nodes to triangles"); break; } element_type_tmpl.element = nel; new_elements_list(n_new_el,1) = element_type_tmpl; remove_elem.getList().push_back(element_type_tmpl); new_numbering(nel) = UInt(-1); ++n_new_el; } else{ new_numbering(nel) = new_nb_type_tmpl; ++new_nb_type_tmpl; } } if(n_new_el > 0){ const_cast(this->mesh).sendEvent(new_elements); const_cast(this->mesh).sendEvent(remove_elem); } AKANTU_DEBUG_OUT(); } #else template void MeshSphereIntersector::buildResultFromQueryList(const std::list & query_list) { AKANTU_DEBUG_TO_IMPLEMENT(); } #endif __END_AKANTU__ #endif // __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__