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
1996 +
1997
1998 +
1999
2000 +
2001
2002
2003
2004
2005 +
2006 +
2007
2008
2009
2010 +
2011 +
2012 +
2013 +
2014
2015
2016 +
2017 +
2018
2019
2020
2021
2022 +
2023 +
2024 +
2025
2026 +
2027
2028 +
2029
2030 +
2031 +
2032
2033 +
2034 +
2035
2036
2037
2038 +
2039
2040 +
2041
2042 +
2043
2044 +
2045 +
2046
2047 +
2048
2049
2050
2051 +
2052
2053
2054 +
2055
2056 +
2057
2058
2059
2060
2061
2062 +
2063 +
2064
2065
2066
|
void MeshTools::Modification::interpolate_surface (MeshBase & mesh,
const Surface & surface,
std::set<std::size_t> ids,
bool use_boundary_nodes)
{
const bool is_serial = mesh.is_serial();
const processor_id_type mesh_pid = mesh.processor_id();
// We might have to move ghost nodes on a distributed mesh if their
// owners don't see a requisite element or boundary they're on.
std::unordered_set<dof_id_type> moved_ghost_nodes;
auto move_node = [& moved_ghost_nodes, & surface, is_serial, mesh_pid]
(Node & node) {
node = surface.closest_point(node);
if (!is_serial && node.processor_id() != mesh_pid)
moved_ghost_nodes.insert(node.id());
};
const bool no_ids = ids.empty();
const BoundaryInfo & boundary_info = mesh.get_boundary_info();
for (const auto & elem : mesh.active_element_ptr_range())
{
if (elem->mapping_type() != LAGRANGE_MAP)
libmesh_not_implemented();
if (use_boundary_nodes)
{
for (auto s : elem->side_index_range())
{
if (no_ids)
{
// If we're not using boundary ids, we're
// interpolating all external and no internal
// boundaries
if (elem->neighbor_ptr(s))
continue;
}
else
{
if (std::none_of(ids.begin(), ids.end(),
[&boundary_info,elem,s](std::size_t bcid)
{return boundary_info.has_boundary_id(elem, s, bcid);}))
continue;
}
for (auto n : elem->nodes_on_side(s))
move_node(elem->node_ref(n));
}
}
else
{
if (no_ids || ids.count(elem->subdomain_id()))
for (Node & node : elem->node_ref_range())
move_node(node);
}
}
if (!is_serial)
{
std::map<processor_id_type, std::vector<dof_id_type>> moved_nodes_map;
for (auto id : moved_ghost_nodes)
{
const Node & node = mesh.node_ref(id);
moved_nodes_map[node.processor_id()].push_back(node.id());
}
auto action_functor =
[& mesh, & surface]
(processor_id_type /* pid */,
const std::vector<dof_id_type> & my_moved_nodes)
{
for (auto id : my_moved_nodes)
{
Node & node = mesh.node_ref(id);
node = surface.closest_point(node);
}
};
// First get new node positions to their owners
Parallel::push_parallel_vector_data
(mesh.comm(), moved_nodes_map, action_functor);
// Then get node positions to anyone else with them ghosted
SyncNodalPositions sync_object(mesh);
Parallel::sync_dofobject_data_by_id
(mesh.comm(), mesh.nodes_begin(), mesh.nodes_end(),
sync_object);
}
// We haven't changed any topology, but just changing geometry could
// have invalidated a point locator.
mesh.clear_point_locator();
}
|