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 const auto from_global_num =
380 outgoing_evals_ids[pid][qp].first =
383 outgoing_evals_ids[pid][qp].second = from_global_num;
394 std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> incoming_evals_ids;
396 auto evals_action_functor =
398 const std::vector<std::pair<Real, unsigned int>> & evals)
401 auto & incoming_evals_ids_for_pid = incoming_evals_ids[pid];
403 incoming_evals_ids_for_pid.reserve(incoming_evals_ids_for_pid.size() + evals.size());
404 std::copy(evals.begin(), evals.end(), std::back_inserter(incoming_evals_ids_for_pid));
407 Parallel::push_parallel_vector_data(
comm(), outgoing_evals_ids, evals_action_functor);
409 std::vector<std::vector<Real>> final_evals(
_to_problems.size());
410 std::vector<std::map<dof_id_type, unsigned int>> trimmed_element_maps(
_to_problems.size());
412 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
421 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
425 bool element_is_evaled =
false;
426 std::vector<Real> evals(qrule.n_points(), 0.);
428 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
431 for (
auto & values_ids : incoming_evals_ids)
438 std::map<std::pair<unsigned int, unsigned int>,
unsigned int> & map =
439 element_index_map[pid];
440 std::pair<unsigned int, unsigned int> key(i_to, elem->id());
441 if (map.find(key) == map.end())
443 unsigned int qp0 = map[key];
448 if (values_ids.second[qp0 + qp].second >= lowest_app_rank)
457 element_is_evaled =
true;
458 evals[qp] = values_ids.second[qp0 + qp].first;
464 if (element_is_evaled)
466 trimmed_element_maps[i_to][elem->id()] = final_evals[i_to].size();
467 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
468 final_evals[i_to].push_back(evals[qp]);
479 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
481 _to_es[i_to]->parameters.set<std::vector<Real> *>(
"final_evals") = &final_evals[i_to];
482 _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>(
"element_map") =
483 &trimmed_element_maps[i_to];
485 _to_es[i_to]->parameters.set<std::vector<Real> *>(
"final_evals") = NULL;
486 _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>(
"element_map") = NULL;
520 for (
const auto & node : to_mesh.local_node_ptr_range())
522 for (
unsigned int comp = 0; comp < node->n_comp(to_sys.
number(), to_var.
number()); comp++)
526 to_solution->
set(to_index, (*ls.
solution)(proj_index));
529 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
530 for (
unsigned int comp = 0; comp < elem->n_comp(to_sys.
number(), to_var.
number()); comp++)
534 to_solution->
set(to_index, (*ls.
solution)(proj_index));
537 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
MooseEnum _current_direction
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
const std::string & name() const override
Get the variable name.
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.
virtual const std::string & name() const
Get the name of the class.
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 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.
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 ...
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)
std::vector< std::unique_ptr< MultiAppCoordTransform > > _from_transforms
unsigned int mesh_dimension() const
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
std::vector< unsigned int > _from_local2global_map
Given local app index, returns global app index.
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.