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" 29 #include "libmesh/default_coupling.h" 51 "Perform a projection between a master and sub-application mesh of a field variable.");
54 params.
addParam<
MooseEnum>(
"proj_type", proj_type,
"The type of the projection.");
56 params.
addParam<
bool>(
"fixed_meshes",
58 "Set to true when the meshes are not changing (ie, " 59 "no movement or adaptivity). This will cache some " 60 "information to speed up the transfer.");
72 _proj_type(getParam<
MooseEnum>(
"proj_type")),
73 _compute_matrix(true),
74 _fixed_meshes(getParam<bool>(
"fixed_meshes")),
78 paramError(
"variable",
" Support single to-variable only ");
81 paramError(
"source_variable",
" Support single from-variable only ");
91 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
97 FEType fe_type = to_problem
137 std::vector<Real> & final_evals = *es.
parameters.
get<std::vector<Real> *>(
"final_evals");
138 std::map<dof_id_type, unsigned int> & element_map =
139 *es.
parameters.
get<std::map<dof_id_type, unsigned int> *>(
"element_map");
143 std::unique_ptr<FEBase> fe(
FEBase::build(to_mesh.mesh_dimension(), fe_type));
144 QGauss qrule(to_mesh.mesh_dimension(), fe_type.default_quadrature_order());
145 fe->attach_quadrature_rule(&qrule);
149 std::vector<dof_id_type> dof_indices;
150 const std::vector<Real> & JxW = fe->get_JxW();
151 const std::vector<std::vector<Real>> & phi = fe->get_phi();
154 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
159 Ke.
resize(dof_indices.size(), dof_indices.size());
160 Fe.
resize(dof_indices.size());
162 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
164 Real meshfun_eval = 0.;
165 if (element_map.find(elem->id()) != element_map.end())
168 meshfun_eval = final_evals[element_map[elem->id()] + qp];
172 for (
unsigned int i = 0; i < phi.size(); i++)
175 Fe(i) += JxW[qp] * (meshfun_eval * phi[i][qp]);
178 for (
unsigned int j = 0; j < phi.size(); j++)
181 Ke(i, j) += JxW[qp] * (phi[i][qp] * phi[j][qp]);
187 system_matrix.add_matrix(Ke, dof_indices);
197 "MultiAppProjectionTransfer::execute()", 5,
"Transferring variables through projection");
238 std::map<processor_id_type, std::vector<Point>> outgoing_qps;
239 std::map<processor_id_type, std::map<std::pair<unsigned int, unsigned int>,
unsigned int>>
246 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
249 const auto to_global_num =
258 fe->attach_quadrature_rule(&qrule);
259 const std::vector<Point> & xyz = fe->get_xyz();
261 unsigned int from0 = 0;
263 from0 += froms_per_proc[i_proc], i_proc++)
265 for (
const auto & elem :
266 as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
271 for (
unsigned int i_from = 0; i_from < froms_per_proc[i_proc] && !qp_hit; i_from++)
273 for (
unsigned int qp = 0; qp < qrule.n_points() && !qp_hit; qp++)
276 if (bboxes[from0 + i_from].contains_point((*
_to_transforms[to_global_num])(qpt)))
286 std::pair<unsigned int, unsigned int> key(i_to, elem->id());
287 element_index_map[i_proc][key] = outgoing_qps[i_proc].size();
288 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
291 outgoing_qps[i_proc].push_back((*
_to_transforms[to_global_num])(qpt));
312 std::vector<BoundingBox> local_bboxes(froms_per_proc[
processor_id()]);
315 unsigned int local_start = 0;
318 local_start += froms_per_proc[i_proc];
321 for (
unsigned int i_from = 0; i_from < froms_per_proc[
processor_id()]; i_from++)
322 local_bboxes[i_from] = bboxes[local_start + i_from];
326 std::vector<MeshFunction> local_meshfuns;
327 for (
unsigned int i_from = 0; i_from <
_from_problems.size(); i_from++)
335 local_meshfuns.emplace_back(
337 local_meshfuns.back().init();
343 std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> outgoing_evals_ids;
347 std::map<processor_id_type, std::vector<Point>> incoming_qps;
350 auto qps_action_functor = [&incoming_qps](
processor_id_type pid,
const std::vector<Point> & qps)
353 auto & incoming_qps_from_pid = incoming_qps[pid];
355 incoming_qps_from_pid.reserve(incoming_qps_from_pid.size() + qps.size());
356 std::copy(qps.begin(), qps.end(), std::back_inserter(incoming_qps_from_pid));
359 Parallel::push_parallel_vector_data(
comm(), outgoing_qps, qps_action_functor);
370 outgoing_evals_ids[pid].resize(qps.second.size(),
373 for (
unsigned int qp = 0; qp < qps.second.size(); qp++)
375 Point qpt = qps.second[qp];
379 for (
unsigned int i_from = 0; i_from <
_from_problems.size(); i_from++)
381 if (local_bboxes[i_from].contains_point(qpt))
383 const auto from_global_num =
385 outgoing_evals_ids[pid][qp].first =
388 outgoing_evals_ids[pid][qp].second = from_global_num;
399 std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> incoming_evals_ids;
401 auto evals_action_functor =
403 const std::vector<std::pair<Real, unsigned int>> & evals)
406 auto & incoming_evals_ids_for_pid = incoming_evals_ids[pid];
408 incoming_evals_ids_for_pid.reserve(incoming_evals_ids_for_pid.size() + evals.size());
409 std::copy(evals.begin(), evals.end(), std::back_inserter(incoming_evals_ids_for_pid));
412 Parallel::push_parallel_vector_data(
comm(), outgoing_evals_ids, evals_action_functor);
414 std::vector<std::vector<Real>> final_evals(
_to_problems.size());
415 std::vector<std::map<dof_id_type, unsigned int>> trimmed_element_maps(
_to_problems.size());
417 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
426 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
430 bool element_is_evaled =
false;
431 std::vector<Real> evals(qrule.n_points(), 0.);
433 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
436 for (
auto & values_ids : incoming_evals_ids)
443 std::map<std::pair<unsigned int, unsigned int>,
unsigned int> & map =
444 element_index_map[pid];
445 std::pair<unsigned int, unsigned int> key(i_to, elem->id());
446 if (map.find(key) == map.end())
448 unsigned int qp0 = map[key];
453 if (values_ids.second[qp0 + qp].second >= lowest_app_rank)
462 element_is_evaled =
true;
463 evals[qp] = values_ids.second[qp0 + qp].first;
469 if (element_is_evaled)
471 trimmed_element_maps[i_to][elem->id()] = final_evals[i_to].size();
472 for (
unsigned int qp = 0; qp < qrule.n_points(); qp++)
473 final_evals[i_to].push_back(evals[qp]);
484 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); i_to++)
486 _to_es[i_to]->parameters.set<std::vector<Real> *>(
"final_evals") = &final_evals[i_to];
487 _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>(
"element_map") =
488 &trimmed_element_maps[i_to];
490 _to_es[i_to]->parameters.set<std::vector<Real> *>(
"final_evals") = NULL;
491 _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>(
"element_map") = NULL;
525 for (
const auto & node : to_mesh.local_node_ptr_range())
527 for (
unsigned int comp = 0; comp < node->n_comp(to_sys.
number(), to_var.
number()); comp++)
531 to_solution->
set(to_index, (*ls.
solution)(proj_index));
534 for (
const auto & elem : to_mesh.active_local_element_ptr_range())
535 for (
unsigned int comp = 0; comp < elem->n_comp(to_sys.
number(), to_var.
number()); comp++)
539 to_solution->
set(to_index, (*ls.
solution)(proj_index));
542 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.
DefaultCoupling & default_coupling()
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.
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
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.