5050#include "libmesh/error_vector.h"
5151#include "libmesh/mesh_refinement.h"
5252#include "libmesh/kelly_error_estimator.h"
53+ // for distributed mesh editing
54+ #include "libmesh/parallel_ghost_sync.h"
5355
5456// Bring in everything from the libMesh namespace
5557using namespace libMesh ;
@@ -65,7 +67,7 @@ void assemble_func(EquationSystems & es, const std::string & system_name)
6567 std ::unique_ptr < FEBase > fe (FEBase ::build (dim , fe_type ));
6668 std ::unique_ptr < FEBase > inf_fe (FEBase ::build_InfFE (dim , fe_type ));
6769
68- const std ::vector < dof_id_type > charged_objects = es .parameters .get < std ::vector < dof_id_type > > ("charged_elem_id" );
70+ const std ::set < dof_id_type > charged_objects = es .parameters .get < std ::set < dof_id_type > > ("charged_elem_id" );
6971 const auto qrule = fe_type .default_quadrature_rule (/*dim = */ 3 , /*extra order = */ 3 );
7072
7173 fe -> attach_quadrature_rule (& * qrule );
@@ -115,7 +117,7 @@ void assemble_func(EquationSystems & es, const std::string & system_name)
115117
116118 Real rho ;
117119 // check if charged_objects contains elem->id(), we add the corresponding charge to the rhs vector
118- if (std :: find ( charged_objects .begin (), charged_objects . end (), elem -> id ()) != charged_objects . end ( ))
120+ if (charged_objects .count ( elem -> id ()))
119121 rho = 1. /elem -> volume ();
120122 else
121123 rho = 0 ;
@@ -178,6 +180,10 @@ int main (int argc, char** argv)
178180 // creation of an empty mesh-object
179181 Mesh mesh (init .comm (), dim );
180182
183+ // We're going to keep track of elements by id, so we don't want
184+ // even a DistributedMesh to renumber them.
185+ mesh .allow_renumbering (false);
186+
181187 // fill the meshes with a spherical grid of type HEX27 with radius r
182188 MeshTools ::Generation ::build_cube (mesh , /*nx= */ 5 , /*ny=*/ 5 , /*nz=*/ 3 ,
183189 /*xmin=*/ -5.2 , /*xmax=*/ 5.2 ,
@@ -205,31 +211,44 @@ int main (int argc, char** argv)
205211 elem -> neighbor_ptr (0 )-> subdomain_id ()= 2 ;
206212 }
207213
214+ // If we're on a distributed mesh then we might have missed some
215+ // ghosted base elements with remote infinite elements.
216+ if (!mesh .is_serial ())
217+ {
218+ SyncSubdomainIds sync_obj (mesh );
219+ Parallel ::sync_dofobject_data_by_id
220+ (mesh .comm (), mesh .elements_begin (), mesh .elements_end (),
221+ sync_obj );
222+ }
208223
209224 // Now we set the sources of the field: prism-shaped objects that are
210225 // determined here by containing certain points:
211- PointLocatorTree pt_lctr (mesh );
212- std ::vector < dof_id_type > charged_elem_ids (3 );
226+ auto p_pt_lctr = mesh .sub_point_locator ();
227+ auto & pt_lctr = * p_pt_lctr ;
228+ pt_lctr .enable_out_of_mesh_mode ();
229+
230+ std ::set < dof_id_type > charged_elem_ids ;
213231 {
214232 Point pt_0 (-3. ,-3.0 ,-1.5 );
215233 Point pt_1 (2. ,-2.6 ,-1.5 );
216234 Point pt_2 (2. , 3.1 , 1.7 );
217235 const Elem * elem_0 = pt_lctr (pt_0 );
218236 if (elem_0 )
219- charged_elem_ids [0 ]= elem_0 -> id ();
220- else
221- // this indicates some error which I don't know how to handle.
222- libmesh_not_implemented ();
237+ charged_elem_ids .insert (elem_0 -> id ());
223238 const Elem * elem_1 = pt_lctr (pt_1 );
224239 if (elem_1 )
225- charged_elem_ids [1 ]= elem_1 -> id ();
226- else
227- libmesh_not_implemented ();
240+ charged_elem_ids .insert (elem_1 -> id ());
228241 const Elem * elem_2 = pt_lctr (pt_2 );
229242 if (elem_2 )
230- charged_elem_ids [2 ]= elem_2 -> id ();
231- else
232- libmesh_not_implemented ();
243+ charged_elem_ids .insert (elem_2 -> id ());
244+
245+ // On a distributed mesh we might not have every point in a
246+ // semilocal element on every processor
247+ if (!mesh .is_serial ())
248+ mesh .comm ().set_union (charged_elem_ids );
249+
250+ // But we should have every point on *some* processor
251+ libmesh_assert_equal_to (charged_elem_ids .size (), 3 );
233252 }
234253
235254 // Create an equation systems object
@@ -238,7 +257,7 @@ int main (int argc, char** argv)
238257 // This is the only system added here.
239258 LinearImplicitSystem & eig_sys = eq_sys .add_system < LinearImplicitSystem > ("Poisson" ) ;
240259
241- eq_sys .parameters .set < std ::vector < dof_id_type > > ("charged_elem_id" )= charged_elem_ids ;
260+ eq_sys .parameters .set < std ::set < dof_id_type > > ("charged_elem_id" )= charged_elem_ids ;
242261
243262 //set the complete type of the variable
244263 FEType fe_type (SECOND , LAGRANGE , FOURTH , JACOBI_20_00 , CARTESIAN );
@@ -272,21 +291,31 @@ int main (int argc, char** argv)
272291 // in the refined mesh, find the elements that describe the
273292 // sources of gravitational field: Due to refinement, there are
274293 // successively more elements to account for the same object.
275- std ::vector < dof_id_type > charged_elem_child ( 0 ) ;
276- for (unsigned int j = 0 ; j < charged_elem_ids . size (); ++ j )
294+ std ::set < dof_id_type > charged_elem_children ;
295+ for (auto id : charged_elem_ids )
277296 {
278- Elem * charged_elem = mesh .elem_ptr (charged_elem_ids [j ]);
297+ Elem * charged_elem = mesh .query_elem_ptr (id );
298+ if (!charged_elem )
299+ {
300+ libmesh_assert (!mesh .is_serial ());
301+ continue ;
302+ }
303+
279304 if (charged_elem -> has_children ())
280305 {
281306 for (auto & child : charged_elem -> child_ref_range ())
282- charged_elem_child .push_back (child .id ());
307+ if (!child .is_remote ())
308+ charged_elem_children .insert (child .id ());
283309 }
284310 else
285- charged_elem_child . push_back (charged_elem -> id ());
311+ charged_elem_children . insert (charged_elem -> id ());
286312 }
287313
288- charged_elem_ids = charged_elem_child ;
289- eq_sys .parameters .set < std ::vector < dof_id_type > > ("charged_elem_id" )= charged_elem_ids ;
314+ charged_elem_ids = charged_elem_children ;
315+ if (!mesh .is_serial ())
316+ mesh .comm ().set_union (charged_elem_ids );
317+
318+ eq_sys .parameters .set < std ::set < dof_id_type > > ("charged_elem_id" )= charged_elem_ids ;
290319
291320 // re-assemble and than solve again.
292321 eig_sys .solve ();
0 commit comments