20#include "libmesh/dof_map.h"
21#include "libmesh/linear_implicit_system.h"
22#include "libmesh/mesh_function.h"
23#include "libmesh/mesh_tools.h"
24#include "libmesh/numeric_vector.h"
25#include "libmesh/parallel_algebra.h"
26#include "libmesh/quadrature_gauss.h"
27#include "libmesh/sparse_matrix.h"
28#include "libmesh/string_to_enum.h"
50 "Perform a projection between a master and sub-application mesh of a field variable.");
53 params.
addParam<
MooseEnum>(
"proj_type", proj_type,
"The type of the projection.");
55 params.
addParam<
bool>(
"fixed_meshes",
57 "Set to true when the meshes are not changing (ie, "
58 "no movement or adaptivity). This will cache some "
59 "information to speed up the transfer.");
71 _proj_type(getParam<
MooseEnum>(
"proj_type")),
72 _compute_matrix(true),
73 _fixed_meshes(getParam<bool>(
"fixed_meshes")),
77 paramError(
"variable",
" Support single to-variable only ");
80 paramError(
"source_variable",
" Support single from-variable only ");
90 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
96 FEType fe_type = to_problem
132 std::vector<Real> & final_evals = *es.
parameters.
get<std::vector<Real> *>(
"final_evals");
133 std::map<dof_id_type, unsigned int> & element_map =
134 *es.
parameters.
get<std::map<dof_id_type, unsigned int> *>(
"element_map");
138 std::unique_ptr<FEBase> fe(
FEBase::build(to_mesh.mesh_dimension(), fe_type));
139 QGauss qrule(to_mesh.mesh_dimension(), fe_type.default_quadrature_order());
140 fe->attach_quadrature_rule(&qrule);
144 std::vector<dof_id_type> dof_indices;
145 const std::vector<Real> & JxW = fe->get_JxW();
146 const std::vector<std::vector<Real>> & phi = fe->get_phi();
149 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
154 Ke.
resize(dof_indices.size(), dof_indices.size());
155 Fe.
resize(dof_indices.size());
157 for (
unsigned int qp = 0; qp < qrule.
n_points(); qp++)
159 Real meshfun_eval = 0.;
160 if (element_map.find(elem->id()) != element_map.end())
163 meshfun_eval = final_evals[element_map[elem->id()] + qp];
167 for (
unsigned int i = 0; i < phi.size(); i++)
170 Fe(i) += JxW[qp] * (meshfun_eval * phi[i][qp]);
173 for (
unsigned int j = 0; j < phi.size(); j++)
176 Ke(i, j) += JxW[qp] * (phi[i][qp] * phi[j][qp]);
182 system_matrix.add_matrix(Ke, dof_indices);
192 "MultiAppProjectionTransfer::execute()", 5,
"Transferring variables through projection");
233 std::map<processor_id_type, std::vector<Point>> outgoing_qps;
234 std::map<processor_id_type, std::map<std::pair<unsigned int, unsigned int>,
unsigned int>>
241 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
244 const auto to_global_num =
253 fe->attach_quadrature_rule(&qrule);
254 const std::vector<Point> & xyz = fe->get_xyz();
256 unsigned int from0 = 0;
258 from0 += froms_per_proc[i_proc], i_proc++)
260 for (
const auto & elem :
261 as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
266 for (
unsigned int i_from = 0; i_from < froms_per_proc[i_proc] && !qp_hit; i_from++)
268 for (
unsigned int qp = 0; qp < qrule.
n_points() && !qp_hit; qp++)
271 if (bboxes[from0 + i_from].contains_point((*
_to_transforms[to_global_num])(qpt)))
281 std::pair<unsigned int, unsigned int> key(i_to, elem->id());
282 element_index_map[i_proc][key] = outgoing_qps[i_proc].size();
283 for (
unsigned int qp = 0; qp < qrule.
n_points(); qp++)
286 outgoing_qps[i_proc].push_back((*
_to_transforms[to_global_num])(qpt));
307 std::vector<BoundingBox> local_bboxes(froms_per_proc[
processor_id()]);
310 unsigned int local_start = 0;
313 local_start += froms_per_proc[i_proc];
316 for (
unsigned int i_from = 0; i_from < froms_per_proc[
processor_id()]; i_from++)
317 local_bboxes[i_from] = bboxes[local_start + i_from];
321 std::vector<MeshFunction> local_meshfuns;
322 for (
unsigned int i_from = 0; i_from <
_from_problems.size(); i_from++)
330 local_meshfuns.emplace_back(
332 local_meshfuns.back().init();
338 std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> outgoing_evals_ids;
342 std::map<processor_id_type, std::vector<Point>> incoming_qps;
345 auto qps_action_functor = [&incoming_qps](
processor_id_type pid,
const std::vector<Point> & qps)
348 auto & incoming_qps_from_pid = incoming_qps[pid];
350 incoming_qps_from_pid.reserve(incoming_qps_from_pid.size() + qps.size());
351 std::copy(qps.begin(), qps.end(), std::back_inserter(incoming_qps_from_pid));
354 Parallel::push_parallel_vector_data(
comm(), outgoing_qps, qps_action_functor);
365 outgoing_evals_ids[pid].resize(qps.second.size(),
368 for (
unsigned int qp = 0; qp < qps.second.size(); qp++)
370 Point qpt = qps.second[qp];
374 for (
unsigned int i_from = 0; i_from <
_from_problems.size(); i_from++)
376 if (local_bboxes[i_from].contains_point(qpt))
378 outgoing_evals_ids[pid][qp].first = (local_meshfuns[i_from])(
392 std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> incoming_evals_ids;
394 auto evals_action_functor =
396 const std::vector<std::pair<Real, unsigned int>> & evals)
399 auto & incoming_evals_ids_for_pid = incoming_evals_ids[pid];
401 incoming_evals_ids_for_pid.reserve(incoming_evals_ids_for_pid.size() + evals.size());
402 std::copy(evals.begin(), evals.end(), std::back_inserter(incoming_evals_ids_for_pid));
405 Parallel::push_parallel_vector_data(
comm(), outgoing_evals_ids, evals_action_functor);
407 std::vector<std::vector<Real>> final_evals(
_to_problems.size());
408 std::vector<std::map<dof_id_type, unsigned int>> trimmed_element_maps(
_to_problems.size());
410 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
419 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
423 bool element_is_evaled =
false;
424 std::vector<Real> evals(qrule.
n_points(), 0.);
426 for (
unsigned int qp = 0; qp < qrule.
n_points(); qp++)
429 for (
auto & values_ids : incoming_evals_ids)
436 std::map<std::pair<unsigned int, unsigned int>,
unsigned int> & map =
437 element_index_map[pid];
438 std::pair<unsigned int, unsigned int> key(i_to, elem->id());
439 if (map.find(key) == map.end())
441 unsigned int qp0 = map[key];
446 if (values_ids.second[qp0 + qp].second >= lowest_app_rank)
455 element_is_evaled =
true;
456 evals[qp] = values_ids.second[qp0 + qp].first;
462 if (element_is_evaled)
464 trimmed_element_maps[i_to][elem->id()] = final_evals[i_to].size();
465 for (
unsigned int qp = 0; qp < qrule.
n_points(); qp++)
466 final_evals[i_to].push_back(evals[qp]);
477 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
479 _to_es[i_to]->parameters.set<std::vector<Real> *>(
"final_evals") = &final_evals[i_to];
480 _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>(
"element_map") =
481 &trimmed_element_maps[i_to];
483 _to_es[i_to]->parameters.set<std::vector<Real> *>(
"final_evals") = NULL;
484 _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>(
"element_map") = NULL;
518 for (
const auto & node : to_mesh.local_node_ptr_range())
520 for (
unsigned int comp = 0; comp < node->n_comp(to_sys.
number(), to_var.
number()); comp++)
524 to_solution->
set(to_index, (*ls.
solution)(proj_index));
527 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
528 for (
unsigned int comp = 0; comp < elem->n_comp(to_sys.
number(), to_var.
number()); comp++)
532 to_solution->
set(to_index, (*ls.
solution)(proj_index));
535 to_solution->
close();
registerMooseObject("MooseApp", MultiAppProjectionTransfer)
void assemble_l2(EquationSystems &es, const std::string &system_name)
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual libMesh::EquationSystems & es() override
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
const std::string & name() const
Get the name of the class.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
const libMesh::FEType & feType() const
Get the type of finite element object.
SystemBase & sys()
Get the system this variable is part of.
unsigned int number() const
Get variable number coming from libMesh.
This class provides an interface for common operations on field variables of both FE and FV types wit...
Transfers variables on possibly different meshes while conserving a user defined property (Postproces...
VariableName _from_var_name
This values are used if a derived class only supports one variable.
const std::vector< VariableName > _from_var_names
Name of variables transferring from.
const std::vector< AuxVariableName > _to_var_names
Name of variables transferring to.
static InputParameters validParams()
virtual void postExecute()
Add some extra work if necessary after execute().
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup.
AuxVariableName _to_var_name
Project values from one domain to another.
bool _compute_matrix
True, if we need to recompute the projection matrix.
std::map< processor_id_type, std::map< std::pair< unsigned int, unsigned int >, unsigned int > > _cached_index_map
void assembleL2(libMesh::EquationSystems &es, const std::string &system_name)
void projectSolution(unsigned int to_problem)
std::vector< libMesh::LinearImplicitSystem * > _proj_sys
unsigned int _proj_var_num
Having one projection variable number seems weird, but there is always one variable in every system b...
std::map< processor_id_type, std::vector< libMesh::Point > > _cached_qps
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup.
MultiAppProjectionTransfer(const InputParameters ¶meters)
friend void assemble_l2(libMesh::EquationSystems &es, const std::string &system_name)
virtual void execute() override
Execute the transfer.
static InputParameters validParams()
std::vector< unsigned int > _to_local2global_map
Given local app index, returns global app index.
unsigned int getGlobalSourceAppIndex(unsigned int i_from) const
Return the global app index from the local index in the "from-multiapp" transfer direction.
static void addBBoxFactorParam(InputParameters ¶ms)
Add the bounding box factor parameter to the supplied input parameters.
std::vector< FEProblemBase * > _from_problems
std::vector< unsigned int > getFromsPerProc()
Return the number of "from" domains that each processor owns.
std::vector< libMesh::BoundingBox > getFromBoundingBoxes()
Return the bounding boxes of all the "from" domains, including all the domains not local to this proc...
std::vector< FEProblemBase * > _to_problems
std::vector< MooseMesh * > _to_meshes
Point getPointInSourceAppFrame(const Point &p, unsigned int local_i_from, const std::string &phase) const
Get the source app point from a point in the reference frame.
std::vector< libMesh::EquationSystems * > _to_es
std::vector< std::unique_ptr< MultiAppCoordTransform > > _to_transforms
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
static const libMesh::Number OutOfMeshValue
MooseEnum _current_direction
void resize(const unsigned int new_m, const unsigned int new_n)
void resize(const unsigned int n)
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
void constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
const MeshBase & get_mesh() const
virtual System & add_system(std::string_view system_type, std::string_view name)
const T_sys & get_system(std::string_view name) const
NumericVector< Number > * rhs
std::unique_ptr< FEGenericBase< Real > > build(const unsigned int dim, const FEType &fet)
Order default_quadrature_order() const
const SparseMatrix< Number > & get_system_matrix() const
virtual void solve() override
unsigned int mesh_dimension() const
virtual void set(const numeric_index_type i, const T value)=0
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
T & set(const std::string &)
const T & get(std::string_view) const
unsigned int n_points() const
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
std::unique_ptr< NumericVector< Number > > current_local_solution
const FEType & variable_type(const unsigned int i) const
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
std::unique_ptr< NumericVector< Number > > solution
unsigned int variable_number(std::string_view var) const
const DofMap & get_dof_map() const
unsigned int number() const
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
const unsigned int invalid_uint
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type