27 #include "libmesh/mesh_communication.h" 28 #include "libmesh/partitioner.h" 29 #include "libmesh/dof_map.h" 30 #include "libmesh/boundary_info.h" 34 libMesh::System& sys):
35 libMesh::System::Constraint (),
37 _strong_discontinuity (false),
38 _negative_level_set_subdomain_offset (0),
39 _inactive_subdomain_offset (0),
40 _level_set_boundary_id (0),
59 bool strong_discontinuity,
61 unsigned int negative_level_set_subdomain_offset,
62 unsigned int inactive_subdomain_offset,
63 unsigned int level_set_boundary_id) {
68 libmesh_assert(
_mesh.is_replicated());
72 if (strong_discontinuity) {
73 #ifndef LIBMESH_ENABLE_UNIQUE_ID 74 libmesh_assert(
false);
80 libMesh::MeshBase::element_iterator
81 e_it =
_mesh.active_local_elements_begin(),
82 e_end =
_mesh.active_local_elements_end();
86 if (
_mesh.is_replicated()) {
88 e_it =
_mesh.active_elements_begin(),
89 e_end =
_mesh.active_elements_end();
95 std::vector<libMesh::Elem*>
98 for ( ; e_it != e_end; e_it++) {
100 libMesh::Elem* elem = *e_it;
102 intersect.
init(phi, *elem, time,
_mesh.max_elem_id(),
_mesh.max_node_id());
109 elems_to_partition.push_back(elem);
117 mesh_changed =
false;
119 for (
unsigned int i=0; i<elems_to_partition.size(); i++) {
121 libMesh::Elem* elem = elems_to_partition[i];
123 intersect.
init(phi, *elem, time,
_mesh.max_elem_id(),
_mesh.max_node_id());
129 negative_level_set_subdomain_offset,
130 level_set_boundary_id,
137 negative_level_set_subdomain_offset,
138 level_set_boundary_id,
147 _old_elems.push_back(std::make_pair(elem, elem->subdomain_id()));
148 elem->subdomain_id() += inactive_subdomain_offset;
155 if (strong_discontinuity) {
157 level_set_boundary_id,
161 _old_elems.push_back(std::make_pair(elem, elem->subdomain_id()));
162 elem->subdomain_id() += inactive_subdomain_offset;
166 _old_elems.push_back(std::make_pair(elem, elem->subdomain_id()));
167 elem->subdomain_id() += negative_level_set_subdomain_offset;
175 _old_elems.push_back(std::make_pair(elem, elem->subdomain_id()));
176 elem->subdomain_id() += negative_level_set_subdomain_offset;
183 _mesh.comm().max(mesh_changed);
187 _mesh.update_parallel_id_counts();
189 if (mesh_changed && !
_mesh.is_replicated())
191 libMesh::MeshCommunication().make_elems_parallel_consistent (
_mesh);
192 libMesh::MeshCommunication().make_new_nodes_parallel_consistent (
_mesh);
194 _mesh.libmesh_assert_valid_parallel_ids();
201 if (mesh_changed &&
_mesh.is_replicated() &&
202 (
_mesh.unpartitioned_elements_begin() ==
203 _mesh.unpartitioned_elements_end()))
204 libMesh::Partitioner::set_node_processor_ids(
_mesh);
207 _mesh.prepare_for_use(
false);
226 for (
unsigned int i=0; i<
_old_elems.size(); i++)
231 for (
unsigned int i=0; i<
_new_elems.size(); i++) {
244 for (
unsigned int i=0; i<
_new_nodes.size(); i++)
249 mesh_changed =
false;
253 _mesh.comm().max(mesh_changed);
257 _mesh.update_parallel_id_counts();
261 _mesh.prepare_for_use();
264 if (mesh_changed && !
_mesh.is_serial()) {
266 libMesh::MeshCommunication().make_nodes_parallel_consistent (
_mesh);
269 MeshTools::libmesh_assert_valid_procids<Node>(
_mesh);
294 libMesh::DofMap& dof_map =
_system.get_dof_map();
296 libMesh::MeshBase::const_element_iterator el =
297 _system.get_mesh().active_local_elements_begin();
298 const libMesh::MeshBase::const_element_iterator end_el =
299 _system.get_mesh().active_local_elements_end();
301 const libMesh::dof_id_type
302 first_dof = dof_map.first_dof(
_mesh.comm().rank()),
303 last_dof = dof_map.end_dof(
_mesh.comm().rank());
305 std::vector<libMesh::dof_id_type>
308 for ( ; el != end_el; ++el) {
310 const libMesh::Elem* elem = *el;
315 dof_map.dof_indices(elem, dof_indices);
318 for (
unsigned int i=0; i<dof_indices.size(); i++) {
320 if ((dof_indices[i] >= first_dof || dof_indices[i] < last_dof) &&
321 !dof_map.is_constrained_dof(dof_indices[i])) {
323 libMesh::DofConstraintRow c_row;
324 dof_map.add_constraint_row(dof_indices[i], c_row,
true);
331 std::set<std::pair<const libMesh::Node*, std::pair<const libMesh::Node*, const libMesh::Node*>>>::iterator
346 for ( ; n_it != n_end; n_it++) {
348 const std::pair<const libMesh::Node*, std::pair<const libMesh::Node*, const libMesh::Node*>>
353 p = *v.first - *v.second.first;
356 p = *v.second.second - *v.second.first;
362 for (
unsigned int i=0; i<
_system.n_vars(); i++) {
367 dof_map.dof_indices(v.first, dof_indices, i);
368 libmesh_assert_equal_to(dof_indices.size(), 1);
369 dof_node = dof_indices[0];
373 dof_map.dof_indices(v.second.first, dof_indices, i);
374 libmesh_assert_equal_to(dof_indices.size(), 1);
375 dof_b_node1 = dof_indices[0];
379 dof_map.dof_indices(v.second.second, dof_indices, i);
380 libmesh_assert_equal_to(dof_indices.size(), 1);
381 dof_b_node2 = dof_indices[0];
384 if ((dof_node >= first_dof || dof_node < last_dof) &&
385 !dof_map.is_constrained_dof(dof_node)) {
392 libMesh::DofConstraintRow c_row;
393 c_row[dof_b_node1] = (1.-d);
394 c_row[dof_b_node2] = d;
396 dof_map.add_constraint_row(dof_node, c_row,
true);
406 unsigned int negative_level_set_subdomain_offset,
407 unsigned level_set_boundary_id,
411 const std::vector<const libMesh::Elem*>& elems) {
415 std::map<const libMesh::Node*, const libMesh::Node*>
416 intersection_object_to_mesh_node_map;
418 std::vector<std::tuple<const libMesh::Node*, libMesh::Elem*, unsigned int>>
419 interior_node_association;
421 for (
unsigned int i=0; i<elems.size(); i++) {
439 if ((sub_e == &e) && positive_phi)
continue;
442 *child = libMesh::Elem::build(sub_e->type()).release();
445 for (
unsigned int j=0; j<sub_e->n_nodes(); j++) {
448 *sub_e_node = sub_e->node_ptr(j);
453 child->set_node(j) =
const_cast<libMesh::Node*
>(sub_e_node);
456 intersection_object_to_mesh_node_map[sub_e_node] = sub_e_node;
463 interior_node_association.push_back
464 (std::tuple<const libMesh::Node*, libMesh::Elem*, unsigned int>(sub_e_node, child, j));
470 std::pair<const libMesh::Node*, const libMesh::Node*>
475 strong_discontinuity,
479 child->set_node(j) = child_node;
483 _hanging_node.insert(std::make_pair(child_node, bounding_nodes));
486 intersection_object_to_mesh_node_map[sub_e_node] = child_node;
492 child->set_p_level(e.p_level());
493 child->set_p_refinement_flag(e.p_refinement_flag());
494 child->set_n_systems(e.n_systems());
498 if (child->type() == e.type())
499 child->subdomain_id() = e.subdomain_id();
501 child->subdomain_id() = e.subdomain_id()+1;
507 child->subdomain_id() += negative_level_set_subdomain_offset;
511 #if (LIBMESH_MAJOR_VERSION == 1 && LIBMESH_MINOR_VERSION >= 5) 512 libmesh_assert_equal_to (child->n_extra_integers(),
513 e.n_extra_integers());
514 for (
unsigned int j=0; j != e.n_extra_integers(); ++j)
515 child->set_extra_integer(j, e.get_extra_integer(j));
517 _mesh.add_elem(child);
520 _mesh.boundary_info->add_side(child,
522 level_set_boundary_id);
529 for (
unsigned int i=0; i<interior_node_association.size(); i++) {
532 *sub_e_node = std::get<0>(interior_node_association[i]);
535 *child = std::get<1>(interior_node_association[i]);
538 node_num = std::get<2>(interior_node_association[i]);
540 std::pair<const libMesh::Node*, const libMesh::Node*>
546 libmesh_assert(intersection_object_to_mesh_node_map.count(bounding_nodes.first));
547 libmesh_assert(intersection_object_to_mesh_node_map.count(bounding_nodes.second));
548 bounding_nodes.first = intersection_object_to_mesh_node_map[bounding_nodes.first];
549 bounding_nodes.second = intersection_object_to_mesh_node_map[bounding_nodes.second];
553 strong_discontinuity,
558 child->set_node(node_num) = child_node;
567 unsigned level_set_boundary_id,
573 std::set<libMesh::Node*>
583 std::unique_ptr<libMesh::Elem> side(e.side_ptr(i));
584 for (
unsigned int j=0; j<side->n_nodes(); j++)
585 side_nodes.insert(side->node_ptr(j));
589 libmesh_assert(
false);
594 *child = libMesh::Elem::build(e.type()).release();
597 for (
unsigned int j=0; j<e.n_nodes(); j++) {
600 *e_node = e.node_ptr(j);
602 if (!side_nodes.count(e_node))
603 child->set_node(j) = e_node;
606 std::pair<const libMesh::Node*, const libMesh::Node*>
607 bounding_nodes = std::make_pair(e_node, e_node);
615 child->set_node(j) = child_node;
621 child->set_p_level(e.p_level());
622 child->set_p_refinement_flag(e.p_refinement_flag());
623 child->set_n_systems(e.n_systems());
627 if (child->type() == e.type())
628 child->subdomain_id() = e.subdomain_id() + negative_level_set_subdomain_offset;
630 child->subdomain_id() = e.subdomain_id()+1 + negative_level_set_subdomain_offset;
634 #if (LIBMESH_MAJOR_VERSION == 1 && LIBMESH_MINOR_VERSION >= 5) 635 libmesh_assert_equal_to (child->n_extra_integers(),
636 e.n_extra_integers());
638 for (
unsigned int j=0; j != e.n_extra_integers(); ++j)
639 child->set_extra_integer(j, e.get_extra_integer(j));
641 _mesh.add_elem(child);
650 bool strong_disontinuity,
652 unsigned int processor_id,
653 const std::pair<const libMesh::Node*, const libMesh::Node*>& bounding_nodes) {
658 id1 = std::min(bounding_nodes.first->id(), bounding_nodes.second->id()),
659 id2 = std::max(bounding_nodes.first->id(), bounding_nodes.second->id());
661 std::pair<libMesh::Node*, libMesh::Node*>&
666 if (!strong_disontinuity) {
668 if (node_pair.first) {
669 libmesh_assert_equal_to(node_pair.first, node_pair.second);
670 return node_pair.first;
676 node_pair.first =
_mesh.add_point(p, libMesh::DofObject::invalid_id, processor_id);
679 libmesh_assert(node_pair.first);
681 node_pair.first->processor_id() = libMesh::DofObject::invalid_processor_id;
682 node_pair.second = node_pair.first;
684 return node_pair.first;
692 return node_pair.first;
697 node_pair.first =
_mesh.add_point(p, libMesh::DofObject::invalid_id, processor_id);
700 libmesh_assert(node_pair.first);
702 node_pair.first->processor_id() = libMesh::DofObject::invalid_processor_id;
704 return node_pair.first;
709 if (node_pair.second)
710 return node_pair.second;
715 node_pair.second =
_mesh.add_point(p, libMesh::DofObject::invalid_id, processor_id);
718 libmesh_assert(node_pair.second);
720 node_pair.second->processor_id() = libMesh::DofObject::invalid_processor_id;
722 return node_pair.second;
unsigned int edge_on_boundary() const
bool process_mesh(const MAST::FieldFunction< Real > &phi, bool strong_discontinuity, Real time, unsigned int negative_level_set_subdomain_offset, unsigned int inactive_subdomain_offset, unsigned int level_set_boundary_id)
unsigned int _level_set_boundary_id
libMesh::System & _system
const std::vector< const libMesh::Elem * > & get_sub_elems_positive_phi() const
virtual void constrain()
provides implementation of the libMesh::System::Constraint::constrain() virtual method ...
unsigned int get_side_on_interface(const libMesh::Elem &e) const
std::vector< std::pair< libMesh::Elem *, unsigned int > > _old_elems
std::vector< libMesh::Node * > _new_nodes
MAST::LevelSet2DIntersectionMode get_intersection_mode() const
std::set< unsigned int > _negative_level_set_ids
MAST::SubElemNodeMap * _node_map
bool if_node_is_new(const libMesh::Node &node) const
identifies if the node from the subelements is a new node or an existing node from the parent element...
bool if_elem_on_negative_phi() const
bool if_hanging_node(const libMesh::Node *n) const
The case of two adjacent edges results in a new node on an edge that is not coincident with the level...
std::pair< const libMesh::Node *, const libMesh::Node * > get_bounding_nodes_for_node(const libMesh::Node &node) const
for new nodes required to create the subelements this method returns the nodes on an edge that bound ...
SubElemMeshRefinement(libMesh::MeshBase &mesh, libMesh::System &sys)
bool _strong_discontinuity
void init(const MAST::FieldFunction< Real > &phi, const libMesh::Elem &e, const Real t, unsigned int max_elem_id, unsigned int max_node_id)
std::vector< libMesh::Elem * > _new_elems
libMesh::Node * _add_node(const libMesh::Point &p, bool strong_disontinuity, bool positive_phi, unsigned int processor_id, const std::pair< const libMesh::Node *, const libMesh::Node *> &bounding_nodes)
bool if_intersection_through_elem() const
bool if_interior_node(const libMesh::Node &node) const
identifies if the new node is on an edge along the level-set method in the interior of the element (a...
bool has_side_on_interface(const libMesh::Elem &e) const
unsigned int node_on_boundary() const
const std::vector< const libMesh::Elem * > & get_sub_elems_negative_phi() const
std::pair< libMesh::Node *, libMesh::Node * > & add(libMesh::dof_id_type bracket_node1, libMesh::dof_id_type bracket_node2)
void _process_negative_element(unsigned int negative_level_set_subdomain_offset, unsigned level_set_boundary_id, libMesh::Elem &e, MAST::LevelSetIntersection &intersect)
std::set< std::pair< const libMesh::Node *, std::pair< const libMesh::Node *, const libMesh::Node * > > > _hanging_node
libMesh::MeshBase & _mesh
unsigned int _negative_level_set_subdomain_offset
virtual ~SubElemMeshRefinement()
void _process_sub_elements(bool strong_discontinuity, unsigned int negative_level_set_subdomain_offset, unsigned int level_set_boundary_id, libMesh::Elem &e, MAST::LevelSetIntersection &intersect, bool positive_phi, const std::vector< const libMesh::Elem *> &elems)
void clear()
clears the data structures
unsigned int _inactive_subdomain_offset