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.