31 #ifndef OOMPH_REFINEABLE_TETGEN_MESH_TEMPLATE_CC    32 #define OOMPH_REFINEABLE_TETGEN_MESH_TEMPLATE_CC    36   #include <oomph-lib-config.h>    41 #include "../generic/sample_point_parameters.h"    42 #include "../generic/mesh_as_geometric_object.h"    43 #include "../generic/projection.h"    51 template <
class ELEMENT>
    58   t_start=TimingHelpers::timer();
    62   Vector<double> target_size(elem_error.size());
    63   double max_edge_ratio=this->compute_volume_target(elem_error,
    66   unsigned n=target_size.size();
    68   double min_size=DBL_MAX;
    69   for (
unsigned e=0;e<n;e++)
    71     if (target_size[e]>max_size) max_size=target_size[e];
    72     if (target_size[e]<min_size) min_size=target_size[e];
    75   oomph_info << 
"Maximum target size: " << max_size << std::endl;
    76   oomph_info << 
"Minimum target size: " << min_size << std::endl;
    77   oomph_info << 
"Number of elements to be refined "     78              << this->Nrefined << std::endl;
    79   oomph_info << 
"Number of elements to be unrefined "    80              << this->Nunrefined << std::endl;
    81   oomph_info << 
"Max edge ratio "<< max_edge_ratio << std::endl;
    83   double orig_max_size, orig_min_size;
    84   this->max_and_min_element_size(orig_max_size, orig_min_size);
    85   oomph_info << 
"Max/min element size in original mesh: "     86              << orig_max_size  << 
" "    87              << orig_min_size << std::endl;    
    90   oomph_info << 
"adapt: Time for getting volume targets                      : "    91              << TimingHelpers::timer()-t_start
    92              << 
" sec " << std::endl;
    96   if ( (Nrefined > 0) || (Nunrefined > this->max_keep_unrefined()) ||
    97        (max_edge_ratio > this->max_permitted_edge_ratio()) )
   100     if (! ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ) )
   103        << 
"Mesh regeneration triggered by edge ratio criterion\n";
   107     t_start=TimingHelpers::timer();
   111     SolidMesh* solid_mesh_pt=
dynamic_cast<SolidMesh*
>(
this);
   118     if (solid_mesh_pt!=0)
   120       throw OomphLibError(
"Solid RefineableTetgenMesh not done yet.",
   121                           OOMPH_CURRENT_FUNCTION,
   122                           OOMPH_EXCEPTION_LOCATION);
   133        (this->Outer_boundary_pt,
   134         this->Internal_surface_pt,
   136         this->Time_stepper_pt,
   137         this->Use_attributes,
   138         this->Corner_elements_must_be_split);
   143     oomph_info << 
"adapt: Time for building temp mesh                        : "   144                << TimingHelpers::timer()-t_start
   145                << 
" sec " << std::endl;
   150     tetgenio *tmp_new_tetgenio_pt = tmp_new_mesh_pt->
tetgenio_pt();
   155      bool use_eulerian_coords=
false;
   156      if (solid_mesh_pt!=0)
   158        use_eulerian_coords=
true;
   161 #ifdef OOMPH_HAS_CGAL   164      CGALSamplePointContainerParameters cgal_params(
this);
   165      if (use_eulerian_coords)
   167        cgal_params.enable_use_eulerian_coordinates_during_setup();
   169      MeshAsGeomObject* mesh_geom_obj_pt=
new MeshAsGeomObject(&cgal_params);
   173      std::ostringstream error_message;
   174      error_message << 
"Non-CGAL-based target size transfer not implemented.\n";
   175      throw OomphLibError(error_message.str(),
   176                          OOMPH_CURRENT_FUNCTION,
   177                          OOMPH_EXCEPTION_LOCATION);
   197     std::map<GeneralisedElement*,unsigned> element_number;
   198     unsigned nelem=this->nelement();
   199     for (
unsigned e=0;e<nelem;e++)
   201       element_number[this->element_pt(e)]=e;
   217       unsigned nelem=tmp_new_mesh_pt->nelement();
   221       Vector<double> new_transferred_target_size(nelem,0.0);
   222       for (
unsigned e=0;e<nelem;e++)
   224         ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->element_pt(e));
   225         unsigned nint=el_pt->integral_pt()->nweight();
   226         for (
unsigned ipt=0;ipt<nint;ipt++)
   230           for(
unsigned i=0;i<3;i++)
   232             s[i] = el_pt->integral_pt()->knot(ipt,i);
   236           el_pt->interpolated_x(s,x);
   242           GeomObject* geom_obj_pt=0;
   243           unsigned max_sample_points=5;
   244           dynamic_cast<CGALSamplePointContainer*
>(mesh_geom_obj_pt->
   245                                                   sample_point_container_pt())->
   246            limited_locate_zeta(x,max_sample_points,
   251             std::stringstream error_message;
   253              << 
"Limited locate zeta failed for zeta = [ "   254              << x[0] << 
" " << x[1] << 
" " << x[2] << 
" ]. Makes no sense!\n";
   255             throw OomphLibError(error_message.str(),
   256                                 OOMPH_CURRENT_FUNCTION,
   257                                 OOMPH_EXCEPTION_LOCATION);
   262             FiniteElement* fe_pt=
dynamic_cast<FiniteElement*
>(geom_obj_pt);
   266               std::stringstream error_message;
   268                << 
"Cast to FE for GeomObject returned by limited locate zeta failed for zeta = [ "   269                << x[0] << 
" " << x[1] << 
" " << x[2] << 
" ]. Makes no sense!\n";
   270               throw OomphLibError(error_message.str(),
   271                                   OOMPH_CURRENT_FUNCTION,
   272                                   OOMPH_EXCEPTION_LOCATION);
   278               double tg_size=target_size[element_number[fe_pt]];
   285               if (new_transferred_target_size[e]!=0.0)
   287                 new_transferred_target_size[e]=
   288                  std::min(new_transferred_target_size[e], 
   293                 new_transferred_target_size[e]=tg_size;
   303           std::ostringstream error_message;
   305            << 
"Non-CGAL-based target size transfer not implemented.\n";
   306           throw OomphLibError(error_message.str(),
   307                               OOMPH_CURRENT_FUNCTION,
   308                               OOMPH_EXCEPTION_LOCATION);
   355       const bool output_target_sizes=
false;
   356       if (output_target_sizes)
   358         unsigned length=new_transferred_target_size.size();
   359         for (
unsigned u = 0; u < length;u++)
   361           oomph_info << 
"Element" << u << 
",target size: "   362                      << new_transferred_target_size[u] << std::endl;
   369       unsigned n_ele_need_refinement_iter = 0;
   379       std::ofstream target_sizes_file; 
   381       sprintf(filename,
"target_sizes%i.dat",iter);
   382       if (output_target_sizes)
   384         target_sizes_file.open(filename);
   387       const unsigned nel_new=tmp_new_mesh_pt->nelement();
   388       Vector<double> new_target_size(nel_new);   
   389       for (
unsigned e=0;e<nel_new;e++)
   392         FiniteElement* f_ele_pt = tmp_new_mesh_pt->finite_element_pt(e);
   395         const double new_size=new_transferred_target_size[e];
   398           std::ostringstream error_stream;
   399           error_stream << 
"This shouldn't happen! Element whose centroid is at "   400                        <<  (f_ele_pt->node_pt(0)->x(0)+
   401                             f_ele_pt->node_pt(1)->x(0)+ 
   402                             f_ele_pt->node_pt(2)->x(0)+
   403                             f_ele_pt->node_pt(3)->x(0))/4.0 << 
" "   404                        << (f_ele_pt->node_pt(0)->x(1)+
   405                            f_ele_pt->node_pt(1)->x(1)+
   406                            f_ele_pt->node_pt(2)->x(1)+
   407                            f_ele_pt->node_pt(3)->x(1))/4.0 << 
" "   408                        << (f_ele_pt->node_pt(0)->x(2)+
   409                            f_ele_pt->node_pt(1)->x(2)+
   410                            f_ele_pt->node_pt(2)->x(2)+
   411                            f_ele_pt->node_pt(3)->x(2))/4.0 << 
" "   412                        << 
" has no target size assigned\n";
   413           throw OomphLibError(error_stream.str(),
   414                               OOMPH_CURRENT_FUNCTION,
   415                               OOMPH_EXCEPTION_LOCATION);
   421           new_target_size[e]=new_size;
   422           if (new_target_size[e]<f_ele_pt->size()/4.0)
   424             new_target_size[e]=f_ele_pt->size()/4.0;
   437           if (output_target_sizes)
   439             target_sizes_file << 
"ZONE N=4, E=1, F=FEPOINT, ET=TETRAHEDRON\n";
   440             for (
unsigned j=0;j<4;j++)
   442               target_sizes_file << f_ele_pt->node_pt(j)->x(0) << 
" "   443                                 << f_ele_pt->node_pt(j)->x(1) << 
" "   444                                 << f_ele_pt->node_pt(j)->x(2) << 
" "   446                                 << new_target_size[e] 
   449             target_sizes_file << 
"1 2 3 4\n"; 
   471           n_ele_need_refinement_iter++;
   479       if (output_target_sizes)
   481         target_sizes_file.close();   
   487          << 
"All size adjustments accommodated by max. permitted size"   488          << 
" reduction during iter " << iter << 
"\n";
   493          << 
"NOT all size adjustments accommodated by max. "   494          << 
"permitted size reduction  during iter " << iter << 
"\n";
   498       oomph_info << 
"\n\n\n==================================================\n"   499                  << 
"==================================================\n"   500                  << 
"==================================================\n"   501                  << 
"==================================================\n"   505       oomph_info << 
"adapt: Time for new_target_size[.]                      : "   506                  << TimingHelpers::timer()-t_start
   507                  << 
" sec " << std::endl;
   519       t_start=TimingHelpers::timer();
   523       if (solid_mesh_pt!=0)
   525         std::ostringstream error_message;
   527          << 
"RefineableSolidTetgenMesh not implemented yet.\n";
   528         throw OomphLibError(error_message.str(),
   529                             OOMPH_CURRENT_FUNCTION,
   530                             OOMPH_EXCEPTION_LOCATION);
   543           this->Outer_boundary_pt,
   544           this->Internal_surface_pt,
   545           this->Time_stepper_pt,
   546           this->Use_attributes);
   550       oomph_info << 
"adapt: Time for new_mesh_pt                            : "   551                  << TimingHelpers::timer()-t_start
   552                  << 
" sec " << std::endl;
   564         unsigned nnod=tmp_new_mesh_pt->nnode();
   565         if (nnod==new_mesh_pt->nnode())
   567           unsigned nel=tmp_new_mesh_pt->nelement();
   568           if (nel==new_mesh_pt->nelement())
   570             bool nodes_identical=
true;
   571             for (
unsigned j=0;j<nnod;j++)
   573               bool coords_identical=
true;
   574               for (
unsigned i=0;i<3;i++)
   576                 if (new_mesh_pt->node_pt(j)->x(i)!=
   577                     tmp_new_mesh_pt->node_pt(j)->x(i))
   579                   coords_identical=
false;
   582               if (!coords_identical)
   584                 nodes_identical=
false;                    
   597       delete tmp_new_mesh_pt;
   602         tmp_new_mesh_pt=new_mesh_pt;
   610     if (!Projection_is_disabled)
   613       t_start=TimingHelpers::timer();
   618       ProjectionProblem<ELEMENT>* project_problem_pt=
   619        new ProjectionProblem<ELEMENT>;
   620       project_problem_pt->mesh_pt()=new_mesh_pt;
   621       project_problem_pt->project(
this);
   622       delete project_problem_pt;
   626        << 
"adapt: Time for project soln onto new mesh                : "   627        << TimingHelpers::timer()-t_start
   628        << 
" sec " << std::endl;
   633     t_start=TimingHelpers::timer();
   640     unsigned nnod=nnode();
   641     for(
unsigned j=nnod;j>0;j--)  
   646     unsigned nel=nelement(); 
   647     for(
unsigned e=nel;e>0;e--)  
   649       delete Element_pt[e-1];  
   655     nnod=new_mesh_pt->nnode();
   656     Node_pt.resize(nnod);
   657     nel=new_mesh_pt->nelement();
   658     Element_pt.resize(nel);  
   659     for(
unsigned j=0;j<nnod;j++)
   661       Node_pt[j] = new_mesh_pt->node_pt(j);
   663     for(
unsigned e=0;e<nel;e++)
   665       Element_pt[e] = new_mesh_pt->element_pt(e);
   669     unsigned nbound=new_mesh_pt->nboundary();
   670     Boundary_element_pt.resize(nbound);
   671     Face_index_at_boundary.resize(nbound);
   672     Boundary_node_pt.resize(nbound);
   673     for (
unsigned b=0;b<nbound;b++)
   675       unsigned nel=new_mesh_pt->nboundary_element(b);
   676       Boundary_element_pt[b].resize(nel);
   677       Face_index_at_boundary[b].resize(nel);
   678       for (
unsigned e=0;e<nel;e++)
   680         Boundary_element_pt[b][e]=new_mesh_pt->boundary_element_pt(b,e);
   681         Face_index_at_boundary[b][e]=new_mesh_pt->face_index_at_boundary(b,e);
   683       unsigned nnod=new_mesh_pt->nboundary_node(b);
   684       Boundary_node_pt[b].resize(nnod);
   685       for (
unsigned j=0;j<nnod;j++)
   687         Boundary_node_pt[b][j]=new_mesh_pt->boundary_node_pt(b,j);
   692     unsigned n_region = new_mesh_pt->nregion();
   698       this->Region_element_pt.resize(n_region);
   699       this->Region_attribute.resize(n_region);
   700       for(
unsigned i=0;i<n_region;i++)
   703         this->Region_attribute[i] = new_mesh_pt->region_attribute(i);
   706         unsigned r=this->Region_attribute[i];
   707         unsigned n_region_element = new_mesh_pt->nregion_element(r);
   708         this->Region_element_pt[i].resize(n_region_element);
   709         for(
unsigned e=0;e<n_region_element;e++)
   711           this->Region_element_pt[i][e] = new_mesh_pt->region_element_pt(r,e);
   716       this->Boundary_region_element_pt.resize(nbound);
   717       this->Face_index_region_at_boundary.resize(nbound);
   720       for(
unsigned b=0;b<nbound;++b)
   723         for(
unsigned i=0;i<n_region;++i)
   725           unsigned r=this->Region_attribute[i];
   727           unsigned n_boundary_el_in_region = 
   728            new_mesh_pt->nboundary_element_in_region(b,r);
   729           if(n_boundary_el_in_region > 0)
   732             this->Boundary_region_element_pt[b][r].
   733              resize(n_boundary_el_in_region);
   734             this->Face_index_region_at_boundary[b][r].
   735              resize(n_boundary_el_in_region);
   738             for(
unsigned e=0;e<n_boundary_el_in_region;++e)
   740               this->Boundary_region_element_pt[b][r][e]
   741                = new_mesh_pt->boundary_element_in_region_pt(b,r,e);
   742               this->Face_index_region_at_boundary[b][r][e] 
   743                = new_mesh_pt->face_index_at_boundary_in_region(b,r,e);
   752     this->set_deep_copy_tetgenio_pt(new_mesh_pt->
tetgenio_pt());
   755     new_mesh_pt->flush_element_and_node_storage();
   762     oomph_info << 
"adapt: Time for moving nodes etc. to actual mesh          : "   763                << TimingHelpers::timer()-t_start
   764                << 
" sec " << std::endl;
   768     if (solid_mesh_pt!=0)
   771       std::stringstream error_message;
   773        << 
"Lagrangian coordinates are currently not projected but are\n"   774        << 
"are re-set during adaptation. This is not appropriate for\n"   775        << 
"real solid mechanics problems!\n";
   776       OomphLibWarning(error_message.str(),
   777                       OOMPH_CURRENT_FUNCTION,
   778                       OOMPH_EXCEPTION_LOCATION);
   781       dynamic_cast<SolidMesh*
>(
this)->set_lagrangian_nodal_coordinates();
   786     this->max_and_min_element_size(max_area, min_area);
   787     oomph_info << 
"Max/min element size in adapted mesh: "    789                << min_area << std::endl;    
   793     oomph_info << 
"Not enough benefit in adaptation.\n";
 
tetgenio *& tetgenio_pt()
Access to the triangulateio representation of the mesh. 
 
void adapt(const Vector< double > &elem_error)
Adapt mesh, based on elemental error provided.