12 #include "MooseConfig.h" 19 #include "libmesh/dof_object.h" 21 #include "metaphysicl/parallel_dualnumber.h" 22 #include "metaphysicl/parallel_semidynamicsparsenumberarray.h" 26 #include "libmesh/data_type.h" 27 #include "libmesh/parallel_algebra.h" 32 #include <unordered_map> 44 LIBMESH_DIM * LIBMESH_DIM)
75 const Parallel::Communicator & communicator,
76 const bool send_data_back)
82 using Datum = std::pair<dof_id_type, T>;
83 std::unordered_map<processor_id_type, std::vector<Datum>> push_data;
85 for (
auto & pr : dof_map)
87 const auto *
const dof_object = pr.first;
88 const auto proc_id = dof_object->processor_id();
89 if (proc_id == our_proc_id)
92 push_data[proc_id].push_back(std::make_pair(dof_object->id(), std::move(pr.second)));
95 const auto & lm_mesh =
mesh.getMesh();
96 std::unordered_map<processor_id_type, std::vector<const DofObject *>>
97 pid_to_dof_object_for_sending_back;
100 [nodal, our_proc_id, &lm_mesh, &dof_map, &pid_to_dof_object_for_sending_back, send_data_back](
103 mooseAssert(pid != our_proc_id,
"We do not send messages to ourself here");
106 for (
auto & pr : sent_data)
108 const auto dof_id = pr.first;
109 const auto *
const dof_object =
110 nodal ?
static_cast<const DofObject *
>(lm_mesh.node_ptr(dof_id))
111 : static_cast<const DofObject *>(lm_mesh.elem_ptr(dof_id));
112 mooseAssert(dof_object,
"This should be non-null");
115 pid_to_dof_object_for_sending_back[pid].push_back(dof_object);
117 dof_map[dof_object][0] += pr.second[0];
118 dof_map[dof_object][1] += pr.second[1];
128 std::unordered_map<processor_id_type, std::vector<Datum>> push_back_data;
130 for (
const auto & [pid, dof_objects] : pid_to_dof_object_for_sending_back)
132 auto & pid_send_data = push_back_data[pid];
133 pid_send_data.reserve(dof_objects.size());
134 for (
const DofObject *
const dof_object : dof_objects)
136 const auto & [tangent_one, tangent_two] = libmesh_map_find(dof_map, dof_object);
137 pid_send_data.push_back({dof_object->id(), {tangent_one, tangent_two}});
141 auto sent_back_action_functor =
142 [nodal, our_proc_id, &lm_mesh, &dof_map](
const processor_id_type libmesh_dbg_var(pid),
143 const std::vector<Datum> & sent_data)
145 mooseAssert(pid != our_proc_id,
"We do not send messages to ourself here");
148 for (
auto & [dof_id, tangents] : sent_data)
150 const auto *
const dof_object =
151 nodal ?
static_cast<const DofObject *
>(lm_mesh.node_ptr(dof_id))
152 : static_cast<const DofObject *>(lm_mesh.elem_ptr(dof_id));
153 mooseAssert(dof_object,
"This should be non-null");
154 auto & [our_tangent_one, our_tangent_two] = dof_map[dof_object];
155 our_tangent_one = tangents[0];
156 our_tangent_two = tangents[1];
172 communicateR2T(std::unordered_map<const DofObject *, ADRankTwoTensor> & dof_map_adr2t,
175 const Parallel::Communicator & communicator,
176 const bool send_data_back)
182 using Datum = std::pair<dof_id_type, ADRankTwoTensor>;
183 std::unordered_map<processor_id_type, std::vector<Datum>> push_data;
185 for (
auto & pr : dof_map_adr2t)
187 const auto *
const dof_object = pr.first;
188 const auto proc_id = dof_object->processor_id();
189 if (proc_id == our_proc_id)
192 push_data[proc_id].push_back(std::make_pair(dof_object->id(), std::move(pr.second)));
195 const auto & lm_mesh =
mesh.getMesh();
196 std::unordered_map<processor_id_type, std::vector<const DofObject *>>
197 pid_to_dof_object_for_sending_back;
199 auto action_functor =
204 &pid_to_dof_object_for_sending_back,
205 send_data_back](
const processor_id_type pid,
const std::vector<Datum> & sent_data)
207 mooseAssert(pid != our_proc_id,
"We do not send messages to ourself here");
210 for (
auto & pr : sent_data)
212 const auto dof_id = pr.first;
213 const auto *
const dof_object =
214 nodal ?
static_cast<const DofObject *
>(lm_mesh.node_ptr(dof_id))
215 : static_cast<const DofObject *>(lm_mesh.elem_ptr(dof_id));
216 mooseAssert(dof_object,
"This should be non-null");
219 pid_to_dof_object_for_sending_back[pid].push_back(dof_object);
223 dof_map_adr2t[dof_object](i,
j) += pr.second(i,
j);
233 std::unordered_map<processor_id_type, std::vector<Datum>> push_back_data;
235 for (
const auto & [pid, dof_objects] : pid_to_dof_object_for_sending_back)
237 auto & pid_send_data = push_back_data[pid];
238 pid_send_data.reserve(dof_objects.size());
239 for (
const DofObject *
const dof_object : dof_objects)
241 const auto & r2t = libmesh_map_find(dof_map_adr2t, dof_object);
242 pid_send_data.push_back({dof_object->id(), r2t});
246 auto sent_back_action_functor =
247 [nodal, our_proc_id, &lm_mesh, &dof_map_adr2t](
const processor_id_type libmesh_dbg_var(pid),
248 const std::vector<Datum> & sent_data)
250 mooseAssert(pid != our_proc_id,
"We do not send messages to ourself here");
253 for (
auto & [dof_id, r2t_sent] : sent_data)
255 const auto *
const dof_object =
256 nodal ?
static_cast<const DofObject *
>(lm_mesh.node_ptr(dof_id))
257 : static_cast<const DofObject *>(lm_mesh.elem_ptr(dof_id));
258 mooseAssert(dof_object,
"This should be non-null");
259 auto & r2t = dof_map_adr2t[dof_object];
267 template <
typename T>
272 const Parallel::Communicator & communicator,
273 const bool send_data_back)
279 using Datum = std::tuple<dof_id_type, T>;
280 std::unordered_map<processor_id_type, std::vector<Datum>> push_data;
282 for (
auto & pr : dof_to_adreal)
284 const auto *
const dof_object = pr.first;
285 const auto proc_id = dof_object->processor_id();
286 if (proc_id == our_proc_id)
289 push_data[proc_id].push_back(std::make_tuple(dof_object->id(), std::move(pr.second)));
292 const auto & lm_mesh =
mesh.getMesh();
293 std::unordered_map<processor_id_type, std::vector<const DofObject *>>
294 pid_to_dof_object_for_sending_back;
296 auto action_functor =
301 &pid_to_dof_object_for_sending_back,
302 send_data_back](
const processor_id_type pid,
const std::vector<Datum> & sent_data)
304 mooseAssert(pid != our_proc_id,
"We do not send messages to ourself here");
307 for (
auto & [dof_id, weighted_gap] : sent_data)
309 const auto *
const dof_object =
310 nodal ?
static_cast<const DofObject *
>(lm_mesh.node_ptr(dof_id))
311 : static_cast<const DofObject *>(lm_mesh.elem_ptr(dof_id));
312 mooseAssert(dof_object,
"This should be non-null");
314 pid_to_dof_object_for_sending_back[pid].push_back(dof_object);
315 auto & our_adreal = dof_to_adreal[dof_object];
316 our_adreal += weighted_gap;
326 std::unordered_map<processor_id_type, std::vector<Datum>> push_back_data;
328 for (
const auto & [pid, dof_objects] : pid_to_dof_object_for_sending_back)
330 auto & pid_send_data = push_back_data[pid];
331 pid_send_data.reserve(dof_objects.size());
332 for (
const DofObject *
const dof_object : dof_objects)
334 const auto & our_adreal = libmesh_map_find(dof_to_adreal, dof_object);
335 pid_send_data.push_back(std::make_tuple(dof_object->id(), our_adreal));
339 auto sent_back_action_functor =
340 [nodal, our_proc_id, &lm_mesh, &dof_to_adreal](
const processor_id_type libmesh_dbg_var(pid),
341 const std::vector<Datum> & sent_data)
343 mooseAssert(pid != our_proc_id,
"We do not send messages to ourself here");
346 for (
auto & [dof_id, adreal] : sent_data)
348 const auto *
const dof_object =
349 nodal ?
static_cast<const DofObject *
>(lm_mesh.node_ptr(dof_id))
350 : static_cast<const DofObject *>(lm_mesh.elem_ptr(dof_id));
351 mooseAssert(dof_object,
"This should be non-null");
352 auto & our_adreal = dof_to_adreal[dof_object];
371 std::unordered_map<
const DofObject *, std::pair<ADReal, Real>> & dof_to_weighted_gap,
375 const Parallel::Communicator & communicator,
376 bool send_data_back);
StandardType(const ADRankTwoTensor *example=nullptr)
DualNumber< Real, DNDerivativeType, true > ADReal
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
uint8_t processor_id_type
void libmesh_ignore(const Args &...)
static const bool is_fixed_type
DIE A HORRIBLE DEATH HERE typedef MPI_Comm communicator
IntRange< T > make_range(T beg, T end)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")