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();
std::vector< std::unique_ptr< MultiAppCoordTransform > > _to_transforms
void assemble_l2(EquationSystems &es, const std::string &system_name)
std::unique_ptr< FEGenericBase< Real > > build(const unsigned int dim, const FEType &fet)
std::vector< libMesh::EquationSystems * > _to_es
const libMesh::FEType & feType() const
Get the type of finite element object.
const unsigned int invalid_uint
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 ...
MooseEnum _current_direction
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.
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
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
unsigned int number() const
Get variable number coming from libMesh.
AuxVariableName _to_var_name
std::map< processor_id_type, std::map< std::pair< unsigned int, unsigned int >, unsigned int > > _cached_index_map
void resize(const unsigned int n)
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
std::vector< libMesh::BoundingBox > getFromBoundingBoxes()
Return the bounding boxes of all the "from" domains, including all the domains not local to this proc...
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
const std::vector< VariableName > _from_var_names
Name of variables transferring from.
std::vector< FEProblemBase * > _to_problems
NumericVector< Number > * rhs
const Parallel::Communicator & comm() const
Order default_quadrature_order() const
virtual void postExecute()
Add some extra work if necessary after execute().
This class provides an interface for common operations on field variables of both FE and FV types wit...
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
virtual void solve() override
const T_sys & get_system(std::string_view name) const
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
registerMooseObject("MooseApp", MultiAppProjectionTransfer)
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...
std::vector< unsigned int > _to_local2global_map
Given local app index, returns global app index.
unsigned int variable_number(std::string_view var) const
void assembleL2(libMesh::EquationSystems &es, const std::string &system_name)
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
uint8_t processor_id_type
processor_id_type n_processors() const
unsigned int number() const
const std::string & name() const
Get the name of the class.
const T & get(std::string_view) const
Project values from one domain to another.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
bool _compute_matrix
True, if we need to recompute the projection matrix.
virtual libMesh::EquationSystems & es() override
const std::vector< AuxVariableName > _to_var_names
Name of variables transferring to.
std::unique_ptr< NumericVector< Number > > solution
std::vector< unsigned int > getFromsPerProc()
Return the number of "from" domains that each processor owns.
Transfers variables on possibly different meshes while conserving a user defined property (Postproces...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
static InputParameters validParams()
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
virtual void execute() override
Execute the transfer.
unsigned int getGlobalSourceAppIndex(unsigned int i_from) const
Return the global app index from the local index in the "from-multiapp" transfer direction.
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
static const libMesh::Number OutOfMeshValue
std::map< processor_id_type, std::vector< libMesh::Point > > _cached_qps
MultiAppProjectionTransfer(const InputParameters ¶meters)
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
T & set(const std::string &)
const MeshBase & get_mesh() const
void resize(const unsigned int new_m, const unsigned int new_n)
unsigned int mesh_dimension() const
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
static InputParameters validParams()
std::unique_ptr< NumericVector< Number > > current_local_solution
static void addBBoxFactorParam(InputParameters ¶ms)
Add the bounding box factor parameter to the supplied input parameters.
void projectSolution(unsigned int to_problem)
friend void assemble_l2(libMesh::EquationSystems &es, const std::string &system_name)
virtual void set(const numeric_index_type i, const T value)=0
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
unsigned int _proj_var_num
Having one projection variable number seems weird, but there is always one variable in every system b...
virtual System & add_system(std::string_view system_type, std::string_view name)
processor_id_type processor_id() const
SystemBase & sys()
Get the system this variable is part of.
std::vector< libMesh::LinearImplicitSystem * > _proj_sys
const DofMap & get_dof_map() const
const SparseMatrix< Number > & get_system_matrix() const
std::vector< FEProblemBase * > _from_problems
std::vector< MooseMesh * > _to_meshes
VariableName _from_var_name
This values are used if a derived class only supports one variable.