20 #include "libmesh/meshfree_interpolation.h"
21 #include "libmesh/system.h"
22 #include "libmesh/radial_basis_interpolation.h"
33 "Transfers the value to the target domain from the nearest node in the source domain.");
35 "num_points", 3,
"The number of nearest points to use for interpolation.");
37 "power", 2,
"The polynomial power to use for calculation of the decay in the interpolation.");
39 MooseEnum interp_type(
"inverse_distance radial_basis",
"inverse_distance");
40 params.
addParam<
MooseEnum>(
"interp_type", interp_type,
"The algorithm to use for interpolation.");
44 "Radius to use for radial_basis interpolation. If negative "
45 "then the radius is taken as the max distance between "
53 _num_points(getParam<unsigned int>(
"num_points")),
54 _power(getParam<Real>(
"power")),
55 _interp_type(getParam<
MooseEnum>(
"interp_type")),
56 _radius(getParam<Real>(
"radius"))
62 paramError(
"variable",
" Support single to-variable only ");
65 paramError(
"source_variable",
" Support single from-variable only ");
71 _console <<
"Beginning InterpolationTransfer " <<
name() << std::endl;
81 MeshBase * from_mesh = NULL;
89 System & from_sys = from_system_base.
system();
91 unsigned int from_sys_num = from_sys.number();
92 unsigned int from_var_num = from_sys.variable_number(from_var.
name());
94 auto & fe_type = from_sys.variable_type(from_var_num);
95 bool from_is_constant = fe_type.order == CONSTANT;
96 bool from_is_nodal = fe_type.family == LAGRANGE;
98 if (fe_type.order > FIRST && !from_is_nodal)
99 mooseError(
"We don't currently support second order or higher elemental variable ");
103 NumericVector<Number> & from_solution = *from_sys.solution;
105 InverseDistanceInterpolation<LIBMESH_DIM> * idi;
110 idi =
new InverseDistanceInterpolation<LIBMESH_DIM>(from_sys.comm(),
_num_points,
_power);
113 idi =
new RadialBasisInterpolation<LIBMESH_DIM>(from_sys.comm(),
_radius);
119 std::vector<Point> & src_pts(idi->get_source_points());
120 std::vector<Number> & src_vals(idi->get_source_vals());
122 std::vector<std::string> field_vars;
124 idi->set_field_variables(field_vars);
126 std::vector<std::string> vars;
131 for (
const auto & from_node : from_mesh->local_node_ptr_range())
134 if (from_node->n_comp(from_sys_num, from_var_num) == 0)
137 dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);
139 src_pts.push_back(*from_node);
140 src_vals.push_back(from_solution(from_dof));
145 std::vector<Point> points;
146 for (
const auto & from_elem :
147 as_range(from_mesh->local_elements_begin(), from_mesh->local_elements_end()))
150 if (from_elem->n_dofs(from_sys_num, from_var_num) < 1)
154 if (from_is_constant)
155 points.push_back(from_elem->centroid());
157 for (
auto & node : from_elem->node_ref_range())
158 points.push_back(node);
160 unsigned int n_comp = from_elem->n_comp(from_sys_num, from_var_num);
161 auto n_points = points.size();
163 if (n_points != n_comp)
166 " does not equal to number of variable components ",
169 unsigned int offset = 0;
170 for (
auto & point : points)
172 dof_id_type from_dof = from_elem->dof_number(from_sys_num, from_var_num, offset++);
173 src_pts.push_back(point);
174 src_vals.push_back(from_solution(from_dof));
180 idi->prepare_for_use();
182 for (
unsigned int i = 0; i <
_multi_app->numGlobalApps(); i++)
191 unsigned int sys_num = to_sys->number();
192 unsigned int var_num = to_sys->variable_number(
_to_var_name);
195 MeshBase * mesh = NULL;
198 mesh = &
_multi_app->appProblemBase(i).getDisplacedProblem()->mesh().getMesh();
200 mesh = &
_multi_app->appProblemBase(i).mesh().getMesh();
202 auto & to_fe_type = to_sys->variable_type(var_num);
203 bool to_is_constant = to_fe_type.order == CONSTANT;
204 bool to_is_nodal = to_fe_type.family == LAGRANGE;
206 if (to_fe_type.order > FIRST && !to_is_nodal)
207 mooseError(
"We don't currently support second order or higher elemental variable ");
211 for (
const auto & node : mesh->local_node_ptr_range())
213 Point actual_position = *node +
_multi_app->position(i);
215 if (node->n_dofs(sys_num, var_num) > 0)
217 std::vector<Point> pts;
218 std::vector<Number> vals;
220 pts.push_back(actual_position);
223 idi->interpolate_field_data(vars, pts, vals);
225 Real value = vals.front();
228 if (node->n_comp(from_sys_num, from_var_num) == 0)
231 dof_id_type dof = node->dof_number(sys_num, var_num, 0);
233 solution.set(dof, value);
239 std::vector<Point> points;
240 for (
auto & elem : as_range(mesh->local_elements_begin(), mesh->local_elements_end()))
243 if (elem->n_dofs(sys_num, var_num) < 1)
248 points.push_back(elem->centroid());
250 for (
auto & node : elem->node_ref_range())
251 points.push_back(node);
253 auto n_points = points.size();
254 unsigned int n_comp = elem->n_comp(sys_num, var_num);
256 if (n_points != n_comp)
259 " does not equal to number of variable components ",
262 unsigned int offset = 0;
263 for (
auto & point : points)
265 Point actual_position = point +
_multi_app->position(i);
267 std::vector<Point> pts;
268 std::vector<Number> vals;
270 pts.push_back(actual_position);
273 idi->interpolate_field_data(vars, pts, vals);
275 Real value = vals.front();
277 dof_id_type dof = elem->dof_number(sys_num, var_num, offset++);
279 solution.set(dof, value);
300 System & to_sys = to_system_base.
system();
302 NumericVector<Real> & to_solution = *to_sys.solution;
304 unsigned int to_sys_num = to_sys.number();
307 mooseAssert(to_sys.get_mesh().is_serial(),
308 "MultiAppInterpolationTransfer only works with ReplicatedMesh!");
310 unsigned int to_var_num = to_sys.variable_number(to_var.
name());
314 MeshBase * to_mesh = NULL;
321 auto & fe_type = to_sys.variable_type(to_var_num);
322 bool is_constant = fe_type.order == CONSTANT;
323 bool is_nodal = fe_type.family == LAGRANGE;
325 if (fe_type.order > FIRST && !is_nodal)
326 mooseError(
"We don't currently support second order or higher elemental variable ");
328 InverseDistanceInterpolation<LIBMESH_DIM> * idi;
333 idi =
new InverseDistanceInterpolation<LIBMESH_DIM>(to_sys.comm(),
_num_points,
_power);
336 idi =
new RadialBasisInterpolation<LIBMESH_DIM>(to_sys.comm(),
_radius);
342 std::vector<Point> & src_pts(idi->get_source_points());
343 std::vector<Number> & src_vals(idi->get_source_vals());
345 std::vector<std::string> field_vars;
347 idi->set_field_variables(field_vars);
349 std::vector<std::string> vars;
352 for (
unsigned int i = 0; i <
_multi_app->numGlobalApps(); i++)
361 from_problem.getVariable(0,
367 System & from_sys = from_system_base.
system();
368 unsigned int from_sys_num = from_sys.number();
370 unsigned int from_var_num = from_sys.variable_number(from_var.
name());
372 auto & from_fe_type = from_sys.variable_type(from_var_num);
373 bool from_is_constant = from_fe_type.order == CONSTANT;
374 bool from_is_nodal = from_fe_type.family == LAGRANGE;
376 if (from_fe_type.order > FIRST && !is_nodal)
377 mooseError(
"We don't currently support second order or higher elemental variable ");
380 NumericVector<Number> & from_solution = *from_sys.solution;
382 MeshBase * from_mesh = NULL;
385 from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh();
387 from_mesh = &from_problem.mesh().getMesh();
393 for (
const auto & from_node : from_mesh->local_node_ptr_range())
396 if (from_node->n_comp(from_sys_num, from_var_num) == 0)
399 dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);
401 src_pts.push_back(*from_node + app_position);
402 src_vals.push_back(from_solution(from_dof));
407 std::vector<Point> points;
408 for (
auto & from_element :
409 as_range(from_mesh->local_elements_begin(), from_mesh->local_elements_end()))
412 if (from_element->n_comp(from_sys_num, from_var_num) == 0)
418 if (from_is_constant)
419 points.push_back(from_element->centroid());
423 for (
auto & node : from_element->node_ref_range())
424 points.push_back(node);
426 auto n_points = points.size();
427 unsigned int n_comp = from_element->n_comp(from_sys_num, from_var_num);
428 unsigned int offset = 0;
430 if (n_points != n_comp)
433 " does not equal to number of variable components ",
436 for (
auto & point : points)
438 dof_id_type from_dof = from_element->dof_number(from_sys_num, from_var_num, offset++);
439 src_pts.push_back(point + app_position);
440 src_vals.push_back(from_solution(from_dof));
447 idi->prepare_for_use();
452 for (
auto & node : as_range(to_mesh->local_nodes_begin(), to_mesh->local_nodes_end()))
454 if (node->n_dofs(to_sys_num, to_var_num) > 0)
456 std::vector<Point> pts;
457 std::vector<Number> vals;
459 pts.push_back(*node);
462 idi->interpolate_field_data(vars, pts, vals);
464 Real value = vals.front();
467 dof_id_type dof = node->dof_number(to_sys_num, to_var_num, 0);
469 to_solution.set(dof, value);
475 std::vector<Point> points;
476 for (
auto & elem : as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
479 if (elem->n_comp(to_sys_num, to_var_num) == 0)
486 points.push_back(elem->centroid());
490 for (
auto & node : elem->node_ref_range())
491 points.push_back(node);
493 auto n_points = points.size();
494 unsigned int n_comp = elem->n_comp(to_sys_num, to_var_num);
496 if (n_points != n_comp)
499 " does not equal to number of variable components ",
502 unsigned int offset = 0;
503 for (
auto & point : points)
505 std::vector<Point> pts;
506 std::vector<Number> vals;
508 pts.push_back(point);
511 idi->interpolate_field_data(vars, pts, vals);
513 Real value = vals.front();
515 dof_id_type dof = elem->dof_number(to_sys_num, to_var_num, offset++);
517 to_solution.set(dof, value);
531 _console <<
"Finished InterpolationTransfer " <<
name() << std::endl;
539 const MeshBase::const_node_iterator & nodes_begin,
540 const MeshBase::const_node_iterator & nodes_end)
542 distance = std::numeric_limits<Real>::max();
543 Node * nearest = NULL;
545 for (
auto & node : as_range(nodes_begin, nodes_end))
547 Real current_distance = (p - *node).norm();
549 if (current_distance < distance)
551 distance = current_distance;