template<int dim>
void MyClass<dim>::make_ball_mesh_2d(const Real radius, const int refine){
//generate a hyper_ball tria with center at (0,0), and radius = radius
const Real isCenter = 1e-3; //some small value
const types::manifold_id MFD_ID_SPH = 1;
GridGenerator::hyper_ball(tria, Point<dim>(), radius);
//set up post_refinement signal
//such that boundary indicators are refreshed after every refinement.
//Ref. parallel::distributed::Triangulation<> class
tria.signals.post_refinement.connect(std::bind(&MyClass<dim>::set_boundary_ids,
std::cref(*this),
std::ref(tria) ) );
//set manifold id to get spherical manifold description
tria.set_all_manifold_ids_on_boundary(MFD_ID_SPH);
tria.set_manifold(MFD_ID_SPH, spherical_mfd);
//set boundary ID
set_boundary_ids(tria);
const Point<dim> mesh_center;
const Real core_radius = 1.0 / 100.0 * radius;
const Real inner_radius = 1.0 / 50.0 * radius;
// Step 1: Shrink the inner cell
for (typename Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
cell != tria.end(); ++cell) {
if(cell->is_locally_owned()){
if (mesh_center.distance(cell->center()) < isCenter)
//cell center almost on the mesh_center
{
for (unsigned int v = 0;
v < GeometryInfo<dim>::vertices_per_cell;
++v)
cell->vertex(v) *= core_radius / mesh_center.distance(cell->vertex(v));
//the vertices of this cell now have a radius of core_radius.
}
}
}
//when cells are moved locally, all the MPI processes need to be notified
//by using void Triangulation< dim, spacedim >::communicate_locally_moved_vertices().
sync_moved_cells();
// Step 2: Refine all cells except the central one
for (typename Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
cell != tria.end(); ++cell) {
if(cell->is_locally_owned()){
if (mesh_center.distance(cell->center()) >= isCenter)
cell->set_refine_flag();
}
}
tria.execute_coarsening_and_refinement();
// Step 3: Resize the inner children of the outer cells
for (typename Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
cell != tria.end(); ++cell) {
if(cell->is_locally_owned()){
for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
{
const double dist = mesh_center.distance(cell->vertex(v));
if (dist > core_radius*1.0001 && dist < 0.9999*radius)
cell->vertex(v) *= inner_radius / dist;
}
}
}
sync_moved_cells();
// Step 4: Apply curved manifold description
for (typename Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
cell != tria.end(); ++cell) {
if(cell->is_locally_owned()){
bool is_in_inner_circle = false;
for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
if (mesh_center.distance(cell->vertex(v)) < inner_radius)
{
is_in_inner_circle = true;
break;
}
if (is_in_inner_circle == false)
cell->set_all_manifold_ids(MFD_ID_SPH);
}
}
tria.refine_global(refine);
return;
}
template<int dim>
void MyClass<dim>::set_boundary_ids(parallel::distributed::Triangulation<dim>& tria_) const {
for (typename Triangulation<dim>::active_cell_iterator
cell = tria_.begin_active();
cell != tria_.end();
++cell){
if(cell->is_locally_owned()){
for (unsigned int f = 0; f < GeometryInfo<dim>::faces_per_cell; ++f)
if (cell->face(f)->at_boundary())
cell->face(f)->set_all_boundary_ids(BD_INFTY);
}
}
return;
}
template<int dim>
void MyClass<dim>::sync_moved_cells(){
std::vector<bool> locally_owned_vertices = GridTools::get_locally_owned_vertices(tria);
tria.communicate_locally_moved_vertices(locally_owned_vertices);
return;
}