27 #ifndef OOMPH_GMSH_TET_MESH_TEMPLATE_CC
28 #define OOMPH_GMSH_TET_MESH_TEMPLATE_CC
39 template<
class ELEMENT>
45 t_start = TimingHelpers::timer();
49 Vector<double> target_size(elem_error.size());
50 double max_edge_ratio =
51 this->compute_volume_target(elem_error, target_size);
53 unsigned n = target_size.size();
54 double max_size = 0.0;
55 double min_size = DBL_MAX;
56 for (
unsigned e = 0; e < n; e++)
58 if (target_size[e] > max_size) max_size = target_size[e];
59 if (target_size[e] < min_size) min_size = target_size[e];
62 oomph_info <<
"Maximum target size: " << max_size << std::endl;
63 oomph_info <<
"Minimum target size: " << min_size << std::endl;
64 oomph_info <<
"Number of elements to be refined " << this->Nrefined
66 oomph_info <<
"Number of elements to be unrefined " << this->Nunrefined
68 oomph_info <<
"Max edge ratio " << max_edge_ratio << std::endl;
70 double orig_max_size, orig_min_size;
71 this->max_and_min_element_size(orig_max_size, orig_min_size);
72 oomph_info <<
"Max/min element size in original mesh: " << orig_max_size
73 <<
" " << orig_min_size << std::endl;
77 <<
"adapt: Time for getting volume targets : "
78 << TimingHelpers::timer() - t_start <<
" sec " << std::endl;
82 if ((Nrefined > 0) || (Nunrefined > this->max_keep_unrefined()) ||
83 (max_edge_ratio > this->max_permitted_edge_ratio()))
85 if (!((Nrefined > 0) || (Nunrefined > max_keep_unrefined())))
87 oomph_info <<
"Mesh regeneration triggered by edge ratio criterion\n";
92 SolidMesh* solid_mesh_pt =
dynamic_cast<SolidMesh*
>(
this);
97 bool use_eulerian_coords =
false;
98 if (solid_mesh_pt != 0)
100 use_eulerian_coords =
true;
103 MeshAsGeomObject* mesh_geom_obj_pt = 0;
105 #ifdef OOMPH_HAS_CGAL
108 CGALSamplePointContainerParameters cgal_params(
this);
109 if (use_eulerian_coords)
111 cgal_params.enable_use_eulerian_coordinates_during_setup();
113 mesh_geom_obj_pt =
new MeshAsGeomObject(&cgal_params);
117 std::ostringstream error_message;
118 error_message <<
"Non-CGAL-based target size transfer not implemented.\n";
120 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
128 std::map<GeneralisedElement*, unsigned> element_number;
129 unsigned nelem = this->nelement();
130 for (
unsigned e = 0; e < nelem; e++)
132 element_number[this->element_pt(e)] = e;
136 Vector<std::pair<double, double>> min_and_max_coordinates =
137 mesh_geom_obj_pt->sample_point_container_pt()
138 ->min_and_max_coordinates();
142 (min_and_max_coordinates[0].second - min_and_max_coordinates[0].first);
144 (min_and_max_coordinates[1].second - min_and_max_coordinates[1].first);
146 (min_and_max_coordinates[2].second - min_and_max_coordinates[2].first);
149 this->Gmsh_parameters_pt->dx_for_target_size_transfer();
150 unsigned nx = unsigned(dx / dx_target);
151 unsigned ny = unsigned(dy / dx_target);
152 unsigned nz = unsigned(dz / dx_target);
160 std::string target_size_file_name =
161 this->Gmsh_parameters_pt->target_size_file_name();
163 std::ofstream target_size_file;
164 target_size_file.open(target_size_file_name.c_str());
165 target_size_file << min_and_max_coordinates[0].first <<
" "
166 << min_and_max_coordinates[1].first <<
" "
167 << min_and_max_coordinates[2].first <<
" " << std::endl;
168 target_size_file << dx <<
" " << dy <<
" " << dz << std::endl;
169 target_size_file << nx + 1 <<
" " << ny + 1 <<
" " << nz + 1 << std::endl;
174 this->Gmsh_parameters_pt->counter_for_filename_gmsh_size_transfer();
176 this->Gmsh_parameters_pt->stem_for_filename_gmsh_size_transfer();
177 std::ofstream latest_sizes_file;
178 bool doc_target_areas =
false;
179 if ((stem !=
"") && (counter >= 0))
181 doc_target_areas =
true;
182 std::string filename =
183 stem + oomph::StringConversion::to_string(counter) +
".dat";
184 latest_sizes_file.open(filename.c_str());
185 latest_sizes_file <<
"ZONE I=" << nx + 1 <<
", J=" << ny + 1
186 <<
", K=" << nz + 1 << std::endl;
187 this->Gmsh_parameters_pt->counter_for_filename_gmsh_size_transfer()++;
192 for (
unsigned i = 0; i <= nx; i++)
194 x[0] = min_and_max_coordinates[0].first + double(i) * dx;
195 for (
unsigned j = 0; j <= ny; j++)
197 x[1] = min_and_max_coordinates[1].first + double(j) * dy;
198 for (
unsigned k = 0; k <= nz; k++)
200 x[2] = min_and_max_coordinates[2].first + double(k) * dz;
205 GeomObject* geom_obj_pt = 0;
206 unsigned max_sample_points =
207 this->Gmsh_parameters_pt
208 ->max_sample_points_for_limited_locate_zeta_during_target_size_transfer();
210 #ifdef OOMPH_HAS_CGAL
212 dynamic_cast<CGALSamplePointContainer*
>(
213 mesh_geom_obj_pt->sample_point_container_pt())
214 ->limited_locate_zeta(x, max_sample_points, geom_obj_pt, s);
218 std::ostringstream error_message;
220 <<
"Non-CGAL-based target size transfer not implemented.\n";
221 throw OomphLibError(error_message.str(),
222 OOMPH_CURRENT_FUNCTION,
223 OOMPH_EXCEPTION_LOCATION);
231 if (geom_obj_pt == 0)
233 std::stringstream error_message;
234 error_message <<
"Limited locate zeta failed for zeta = [ "
235 << x[0] <<
" " << x[1] <<
" " << x[2]
236 <<
" ]. Makes no sense!\n";
237 throw OomphLibError(error_message.str(),
238 OOMPH_CURRENT_FUNCTION,
239 OOMPH_EXCEPTION_LOCATION);
245 FiniteElement* fe_pt =
dynamic_cast<FiniteElement*
>(geom_obj_pt);
250 std::stringstream error_message;
252 <<
"Cast to FE for GeomObject returned by limited "
253 <<
"locate zeta failed for zeta = [ " << x[0] <<
" " << x[1]
254 <<
" " << x[2] <<
" ]. Makes no sense!\n";
255 throw OomphLibError(error_message.str(),
256 OOMPH_CURRENT_FUNCTION,
257 OOMPH_EXCEPTION_LOCATION);
266 pow(target_size[element_number[fe_pt]], 1.0 / 3.0);
267 target_size_file << tg_size <<
" ";
270 if (doc_target_areas)
272 latest_sizes_file << x[0] <<
" " << x[1] <<
" " << x[2] <<
" "
273 << tg_size << std::endl;
281 target_size_file << std::endl;
284 target_size_file.close();
286 if (doc_target_areas)
288 latest_sizes_file.close();
292 bool use_mesh_grading_from_file =
true;
295 use_mesh_grading_from_file,
296 this->Time_stepper_pt);
306 t_start = TimingHelpers::timer();
309 ProjectionProblem<ELEMENT>* project_problem_pt = 0;
312 if (!this->Gmsh_parameters_pt->projection_is_disabled())
316 project_problem_pt =
new ProjectionProblem<ELEMENT>;
317 project_problem_pt->mesh_pt() = new_mesh_pt;
318 project_problem_pt->project(
this);
321 <<
"adapt: Time for project soln onto new mesh : "
322 << TimingHelpers::timer() - t_start <<
" sec " << std::endl;
325 t_start = TimingHelpers::timer();
329 unsigned nnod = nnode();
330 for (
unsigned j = nnod; j > 0; j--)
332 delete Node_pt[j - 1];
335 unsigned nel = nelement();
336 for (
unsigned e = nel; e > 0; e--)
338 delete Element_pt[e - 1];
339 Element_pt[e - 1] = 0;
344 nnod = new_mesh_pt->nnode();
345 Node_pt.resize(nnod);
346 nel = new_mesh_pt->nelement();
347 Element_pt.resize(nel);
348 for (
unsigned j = 0; j < nnod; j++)
350 Node_pt[j] = new_mesh_pt->node_pt(j);
352 for (
unsigned e = 0; e < nel; e++)
354 Element_pt[e] = new_mesh_pt->element_pt(e);
358 unsigned nbound = new_mesh_pt->nboundary();
359 Boundary_element_pt.resize(nbound);
360 Face_index_at_boundary.resize(nbound);
361 Boundary_node_pt.resize(nbound);
362 for (
unsigned b = 0; b < nbound; b++)
364 unsigned nel = new_mesh_pt->nboundary_element(b);
365 Boundary_element_pt[b].resize(nel);
366 Face_index_at_boundary[b].resize(nel);
367 for (
unsigned e = 0; e < nel; e++)
369 Boundary_element_pt[b][e] = new_mesh_pt->boundary_element_pt(b, e);
370 Face_index_at_boundary[b][e] =
371 new_mesh_pt->face_index_at_boundary(b, e);
373 unsigned nnod = new_mesh_pt->nboundary_node(b);
374 Boundary_node_pt[b].resize(nnod);
375 for (
unsigned j = 0; j < nnod; j++)
377 Boundary_node_pt[b][j] = new_mesh_pt->boundary_node_pt(b, j);
382 unsigned n_region = new_mesh_pt->nregion();
388 this->Region_element_pt.resize(n_region);
389 this->Region_attribute.resize(n_region);
390 for (
unsigned i = 0; i < n_region; i++)
393 this->Region_attribute[i] = new_mesh_pt->region_attribute(i);
396 unsigned r = this->Region_attribute[i];
397 unsigned n_region_element = new_mesh_pt->nregion_element(r);
398 this->Region_element_pt[i].resize(n_region_element);
399 for (
unsigned e = 0; e < n_region_element; e++)
401 this->Region_element_pt[i][e] =
402 new_mesh_pt->region_element_pt(r, e);
407 this->Boundary_region_element_pt.resize(nbound);
408 this->Face_index_region_at_boundary.resize(nbound);
411 for (
unsigned b = 0; b < nbound; ++b)
414 for (
unsigned i = 0; i < n_region; ++i)
416 unsigned r = this->Region_attribute[i];
418 unsigned n_boundary_el_in_region =
419 new_mesh_pt->nboundary_element_in_region(b, r);
420 if (n_boundary_el_in_region > 0)
423 this->Boundary_region_element_pt[b][r].resize(
424 n_boundary_el_in_region);
425 this->Face_index_region_at_boundary[b][r].resize(
426 n_boundary_el_in_region);
429 for (
unsigned e = 0; e < n_boundary_el_in_region; ++e)
431 this->Boundary_region_element_pt[b][r][e] =
432 new_mesh_pt->boundary_element_in_region_pt(b, r, e);
433 this->Face_index_region_at_boundary[b][r][e] =
434 new_mesh_pt->face_index_at_boundary_in_region(b, r, e);
444 new_mesh_pt->flush_element_and_node_storage();
448 delete project_problem_pt;
452 <<
"adapt: Time for moving nodes etc. to actual mesh : "
453 << TimingHelpers::timer() - t_start <<
" sec " << std::endl;
458 if (solid_mesh_pt != 0)
461 std::stringstream error_message;
463 <<
"Lagrangian coordinates are currently not projected but are\n"
464 <<
"are re-set during adaptation. This is not appropriate for\n"
465 <<
"real solid mechanics problems!\n";
466 OomphLibWarning(error_message.str(),
467 OOMPH_CURRENT_FUNCTION,
468 OOMPH_EXCEPTION_LOCATION);
471 dynamic_cast<SolidMesh*
>(
this)->set_lagrangian_nodal_coordinates();
476 this->max_and_min_element_size(max_area, min_area);
477 oomph_info <<
"Max/min element size in adapted mesh: " << max_area <<
" "
478 << min_area << std::endl;
482 oomph_info <<
"Not enough benefit in adaptation.\n";
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
void adapt(const Vector< double > &elem_error)
Adapt mesh, based on elemental error provided.
////////////////////////////////////////////////////////////////////// //////////////////////////////...