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>
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 : " 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";
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 : " 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 165 if (use_eulerian_coords)
173 std::ostringstream error_message;
174 error_message <<
"Non-CGAL-based target size transfer not implemented.\n";
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();
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);
243 unsigned max_sample_points=5;
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";
256 OOMPH_CURRENT_FUNCTION,
257 OOMPH_EXCEPTION_LOCATION);
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";
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";
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();
389 for (
unsigned e=0;
e<nel_new;
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 " 403 f_ele_pt->
node_pt(3)->
x(0))/4.0 <<
" " 407 f_ele_pt->
node_pt(3)->
x(1))/4.0 <<
" " 411 f_ele_pt->
node_pt(3)->
x(2))/4.0 <<
" " 412 <<
" has no target size assigned\n";
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[.] : " 507 <<
" sec " << std::endl;
523 if (solid_mesh_pt!=0)
525 std::ostringstream error_message;
527 <<
"RefineableSolidTetgenMesh not implemented yet.\n";
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 : " 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();
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++)
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)
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 : " 628 <<
" sec " << std::endl;
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);
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++)
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++)
676 Boundary_element_pt[b].resize(nel);
677 Face_index_at_boundary[b].resize(nel);
678 for (
unsigned e=0;
e<nel;
e++)
684 Boundary_node_pt[b].resize(nnod);
685 for (
unsigned j=0;j<nnod;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++)
706 unsigned r=this->Region_attribute[
i];
708 this->Region_element_pt[
i].resize(n_region_element);
709 for(
unsigned e=0;
e<n_region_element;
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 =
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]
742 this->Face_index_region_at_boundary[b][r][
e]
752 this->set_deep_copy_tetgenio_pt(new_mesh_pt->
tetgenio_pt());
762 oomph_info <<
"adapt: Time for moving nodes etc. to actual mesh : " 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";
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";
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
unsigned nregion()
Return the number of regions specified by attributes.
FiniteElement * boundary_element_in_region_pt(const unsigned &b, const unsigned &r, const unsigned &e) const
Return pointer to the e-th element adjacent to boundary b in region r.
Helper object for dealing with the parameters used for the CGALSamplePointContainer objects...
A general Finite Element class.
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
CGAL-based SamplePointContainer.
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
void project(Mesh *base_mesh_pt, const bool &dont_project_positions=false)
Project from base into the problem's own mesh.
Mesh *& mesh_pt()
Return a pointer to the global mesh.
int face_index_at_boundary(const unsigned &b, const unsigned &e) const
For the e-th finite element on boundary b, return int to indicate the face_index of the face adjacent...
unsigned long nelement() const
Return number of elements in the mesh.
int face_index_at_boundary_in_region(const unsigned &b, const unsigned &r, const unsigned &e) const
Return face index of the e-th element adjacent to boundary b in region r.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
unsigned nboundary() const
Return number of boundaries.
tetgenio *& tetgenio_pt()
Access to the triangulateio representation of the mesh.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
double timer()
returns the time in seconds after some point in past
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
unsigned long nnode() const
Return number of nodes in the mesh.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
void adapt(const Vector< double > &elem_error)
Adapt mesh, based on elemental error provided.
void enable_use_eulerian_coordinates_during_setup()
double region_attribute(const unsigned &i)
Return the i-th region attribute (here only used as the (assumed to be unsigned) region id...
unsigned nregion_element(const unsigned &r)
Return the number of elements in region r.
void flush_element_and_node_storage()
Flush storage for elements and nodes by emptying the vectors that store the pointers to them...
FiniteElement * region_element_pt(const unsigned &r, const unsigned &e)
Return the e-th element in the r-th region.
unsigned nboundary_element_in_region(const unsigned &b, const unsigned &r) const
Return the number of elements adjacent to boundary b in region r.