libMesh/libmesh: coverage diff

Base 739e36 Head #4283 f95625
Total Total +/- New
Rate 65.00% 65.04% +0.03% 90.91%
Hits 76957 77039 +82 60
Misses 41434 41417 -17 6
Filename Stmts Miss Cover
include/ghosting/disconnected_neighbor_coupling.h +6 +3 +50.00%
src/base/dof_map.C 0 -6 +0.47%
src/ghosting/disconnected_neighbor_coupling.C +22 +3 +86.36%
src/mesh/boundary_info.C 0 -13 +0.82%
src/mesh/distributed_mesh.C 0 -2 +0.25%
src/mesh/mesh_base.C +16 0 +0.22%
src/mesh/mesh_refinement.C +2 -2 +0.33%
src/mesh/unstructured_mesh.C +19 0 +0.46%
TOTAL +65 -17 +0.03%
code
coverage unchanged
code
coverage increased
code
coverage decreased
+
line added or modified

include/ghosting/disconnected_neighbor_coupling.h

17  
18  
19  
20 +
21  
22  
23  
24  
25 +
26  
27 +
28 +
29  
30 +
31 +
32  
33  
34  
 * user-defined disconnected interfaces,
 * such as cohesive zone boundaries.
 */
class DisconnectedNeighborCoupling : public GhostingFunctor
{
public:
  using DisconnectedMap = std::unordered_map<const Elem *, const Elem *>;

  DisconnectedNeighborCoupling(const MeshBase & mesh) :
    GhostingFunctor(mesh),
    _dof_coupling(nullptr)
  {}

  virtual std::unique_ptr<GhostingFunctor> clone () const override
  { return std::make_unique<DisconnectedNeighborCoupling>(*this); }

  virtual void operator() (const MeshBase::const_element_iterator & range_begin,
                           const MeshBase::const_element_iterator & range_end,

src/base/dof_map.C

1884  
1885  
1886  
1887  
1888  
1889  
1890  
1891  
1892  
1893  
1894  
  this->prepare_send_list();
}

void DofMap::set_implicit_neighbor_dofs(bool implicit_neighbor_dofs)
{
  _implicit_neighbor_dofs_initialized = true;
  _implicit_neighbor_dofs = implicit_neighbor_dofs;
}

void DofMap::set_verify_dirichlet_bc_consistency(bool val)
{
1925  
1926  
1927  
1928  
1929  
1930  
1931  
1932  
1933  
1934  
1935  
  // has been called.
  if (_implicit_neighbor_dofs_initialized)
    {
      implicit_neighbor_dofs = _implicit_neighbor_dofs;

      // Again, if the user explicitly says implicit_neighbor_dofs = false,
      // then we return here.
      if (!implicit_neighbor_dofs)
        return false;
    }

src/ghosting/disconnected_neighbor_coupling.C

8  
9  
10  
11 +
12  
13  
14  
15  
16  
17 +
18 +
19 +
20 +
21  
22 +
23  
24  
25 +
26 +
27 +
28  
29  
30 +
31 +
32  
33 +
34  
35 +
36 +
37  
38 +
39  
40 +
41  
42 +
43 +
44  
45 +
46 +
47  
48 +
49 +
50  
51  
52  
namespace libMesh
{

void DisconnectedNeighborCoupling::operator()(
    const MeshBase::const_element_iterator & range_begin,
    const MeshBase::const_element_iterator & range_end,
    processor_id_type p,
    map_type & coupled_elements)
{
  libmesh_assert(_mesh);
  auto * db = _mesh->get_disconnected_boundaries();
  if (!db)
    return;

  std::unique_ptr<PointLocatorBase> point_locator = _mesh->sub_point_locator();

  // Primary ghosting: elements in range_begin...range_end
  for (const auto & elem : as_range(range_begin, range_end))
    if (elem->processor_id() != p)
      coupled_elements.emplace(elem, _dof_coupling);

  // Also ghost their disconnected neighbors
  for (const auto & elem : as_range(range_begin, range_end))
    for (auto s : elem->side_index_range())
    {
      for (const auto & [id, boundary_ptr] : *db)
      {
        if (!_mesh->get_boundary_info().has_boundary_id(elem, s, id))
          continue;

        unsigned int neigh_side = invalid_uint;
        const Elem * neigh =
            db->neighbor(id, *point_locator, elem, s, &neigh_side);

        if (!neigh || neigh == remote_elem)
          continue;

        if (neigh->processor_id() != p)
          coupled_elements.emplace(neigh, _dof_coupling);
      }
    }
}


} // namespace libMesh

src/mesh/boundary_info.C

2322  
2323  
2324  
2325  
2326  
2327  
2328  
2329 +
2330  
2331  
2332  
2333  
2334  
2335  
2336  
2337  
2338  
2339  
2340  
2341  
2342  
2343  
2344  
2345  
2346  
2347  
2348  
2349  
2350  
        {
          // If we're on this external boundary then we share this
          // external boundary id
          if (elem->neighbor_ptr(side) == nullptr)
            return side;

          // Internal boundary case
          const Elem * p = elem;

#ifdef LIBMESH_ENABLE_AMR
          // If we're on an internal boundary then we need to be sure
          // it's the same internal boundary as our top_parent
          while (p != nullptr)
          {
            const Elem * parent = p->parent();
            if (parent && !parent->is_child_on_side(parent->which_child_am_i(p), side))
              break;
            p = parent;
          }
#else
          // do not forget to return the internal boundary when AMR is disabled
          return side;
#endif
          // We're on that side of our top_parent; return it
          if (!p)
            return side;
        }
        // Otherwise we need to check if the child's ancestors have something on
        // the side of the child
2388  
2389  
2390  
2391  
2392  
2393  
2394  

  // if we get here, we found elem in the data structure but not
  // the requested boundary id, so return the default value
  return libMesh::invalid_uint;
}


2429  
2430  
2431  
2432  
2433  
2434  
2435  
2436  
2437  
2438  
2439  
2440  
2441  
2442  
2443  
2444  
2445  

#ifdef LIBMESH_ENABLE_AMR

          while (p != nullptr)
          {
            const Elem * parent = p->parent();
            if (parent && !parent->is_child_on_side(parent->which_child_am_i(p), side))
              break;
            p = parent;
          }
#endif
          // We're on that side of our top_parent; return it
          if (!p)
            returnval.push_back(side);
        }
        // Otherwise we trust what we got and return the side
        else

src/mesh/distributed_mesh.C

1537  
1538  
1539  
1540  
1541  
1542  
1543  
1544  
1545  
1546  
1547  
1548  
1549  
1550  
                      sender_could_become_owner)
                    {
                      if (it != repartitioned_node_pids.end() &&
                          pid < it->second)
                        it->second = pid;
                      else
                        repartitioned_node_pids[n] = pid;
                    }
                  else
                    if (it == repartitioned_node_pids.end())
                      repartitioned_node_pids[n] =
                        DofObject::invalid_processor_id;

                  repartitioned_node_sets_to_push[pid].insert(n);

src/mesh/mesh_base.C

1960  
1961  
1962  
1963 +
1964  
1965  
1966  
1967  
1968 +
1969 +
1970  
1971  
1972 +
1973 +
1974  
1975 +
1976 +
1977 +
1978 +
1979  
1980  
1981 +
1982 +
1983 +
1984  
1985 +
1986  
1987 +
1988  
1989  
1990 +
1991  
1992 +
1993  
1994  
1995  
  /**
   * Register a pair of boundaries as disconnected boundaries.
   */
  void MeshBase::add_disconnected_boundaries(const boundary_id_type b1,
                                             const boundary_id_type b2,
                                             const RealVectorValue & translation)
    {
      // Lazily allocate the container the first time it’s needed
      if (!_disconnected_boundary_pairs)
        _disconnected_boundary_pairs = std::make_unique<PeriodicBoundaries>();

      // Create forward and inverse boundary mappings
      PeriodicBoundary forward(translation);
      PeriodicBoundary inverse(translation * -1.0);

      forward.myboundary       = b1;
      forward.pairedboundary   = b2;
      inverse.myboundary       = b2;
      inverse.pairedboundary   = b1;

      // Add both directions into the container
      _disconnected_boundary_pairs->emplace(b1, forward.clone());
      _disconnected_boundary_pairs->emplace(b2, inverse.clone());
    }

  PeriodicBoundaries * MeshBase::get_disconnected_boundaries()
    {
      return _disconnected_boundary_pairs.get();
    }

  const PeriodicBoundaries * MeshBase::get_disconnected_boundaries() const
    {
      return _disconnected_boundary_pairs.get();
    }
#endif

src/mesh/mesh_refinement.C

694  
695  
696  
697 +
698  
699 +
700  
701  
702  
  //
  // For safety, refinement is disabled while disconnected boundaries are
  // present.
  if (_mesh.get_disconnected_boundaries())
    {
      libmesh_error_msg(
        "Mesh contains disconnected boundary interfaces; refinement is disabled.\n"
        "MeshRefinement::refine_elements() cannot proceed because disconnected\n"
        "boundaries may produce invalid neighbor relations. Please remove or\n"
1291  
1292  
1293  
1294  
1295  
1296  
1297  
1298  
                              if (neighbor->p_level() < my_p_level &&
                                  neighbor->p_refinement_flag() != Elem::REFINE)
                                {
                                  neighbor->set_p_refinement_flag(Elem::REFINE);
                                  level_one_satisfied = false;
                                  compatible_with_coarsening = false;
                                }
                              if (neighbor->p_level() == my_p_level &&

src/mesh/unstructured_mesh.C

1001  
1002  
1003  
1004 +
1005  
1006 +
1007  
1008  
1009 +
1010  
1011 +
1012  
1013 +
1014  
1015  
1016 +
1017 +
1018 +
1019  
1020 +
1021  
1022 +
1023 +
1024  
1025  
1026  
1027 +
1028  
1029 +
1030  
1031 +
1032 +
1033 +
1034  
1035  
1036  
1037 +
1038  
1039  
1040 +
1041 +
1042  
1043  
1044  

#ifdef LIBMESH_ENABLE_PERIODIC
  // Get the disconnected boundaries object (from periodic BCs)
  auto * db = this->get_disconnected_boundaries();

  if (db)
    {
      // Obtain a point locator
      std::unique_ptr<PointLocatorBase> point_locator = this->sub_point_locator();

      for (const auto & element : this->element_ptr_range())
        {
          for (auto ms : element->side_index_range())
            {
              // Skip if this side already has a valid neighbor (including remote neighbors)
              if (element->neighbor_ptr(ms) != nullptr &&
                  element->neighbor_ptr(ms) != remote_elem)
                continue;

              for (const auto & [id, boundary_ptr] : *db)
                {
                  if (!this->get_boundary_info().has_boundary_id(element, ms, id))
                    continue;

                  unsigned int neigh_side;
                  const Elem * neigh =
                    db->neighbor(id, *point_locator, element, ms, &neigh_side);

                  if (neigh && neigh != remote_elem && neigh != element)
                    {
                      auto neigh_changeable = this->elem_ptr(neigh->id());
                      element->set_neighbor(ms, neigh_changeable);
                      neigh_changeable->set_neighbor(neigh_side, element);
                    }
                }
            }
        }

      // Ghost the disconnected elements
      this->add_ghosting_functor(std::make_unique<DisconnectedNeighborCoupling>(*this));
    }
#endif // LIBMESH_ENABLE_PERIODIC

#ifdef LIBMESH_ENABLE_AMR