18#include "libmesh/parallel_eigen.h"
26static std::vector<dof_id_type>
29 std::vector<dof_id_type> key = ids;
30 std::sort(key.begin(), key.end());
31 key.erase(std::unique(key.begin(), key.end()), key.end());
40 MooseEnum orders(
"CONSTANT FIRST SECOND THIRD FOURTH");
42 "patch_polynomial_order",
44 "Polynomial order used in least squares fitting of material property "
45 "over the local patch of elements connected to a given node");
51 rm_params.
set<
bool>(
"use_point_neighbors") =
true;
52 rm_params.
set<
unsigned short>(
"layers") = 1;
63 _patch_polynomial_order(
64 static_cast<unsigned
int>(getParam<
MooseEnum>(
"patch_polynomial_order"))),
65 _multi_index(
MathUtils::multiIndex(_mesh.dimension(), _patch_polynomial_order)),
66 _q(_multi_index.size()),
67 _distributed_mesh(_mesh.isDistributedMesh()),
68 _proc_ids(n_processors())
75 const std::vector<dof_id_type> & elem_ids)
const
88 RealEigenVector coef = RealEigenVector::Zero(
_q);
91 mooseError(
"There are not enough sample points to recover the nodal value, try reducing the "
92 "polynomial order or using a higher-order quadrature scheme.");
95 RealEigenMatrix A = RealEigenMatrix::Zero(
_q,
_q);
96 RealEigenVector b = RealEigenVector::Zero(
_q);
97 for (
auto elem_id : elem_ids_reduced)
104 " is not in the block. "
105 "Please use nodalPatchRecovery with elements in the block only.");
107 if (
_Ae.find(elem_id) ==
_Ae.end())
108 mooseError(
"Missing entry for elem_id = ", elem_id,
" in _Ae.");
109 if (
_be.find(elem_id) ==
_be.end())
110 mooseError(
"Missing entry for elem_id = ", elem_id,
" in _be.");
112 A += libmesh_map_find(
_Ae, elem_id);
113 b += libmesh_map_find(
_be, elem_id);
117 coef = A.completeOrthogonalDecomposition().solve(b);
144 RealEigenVector p(
_q);
150 for (
unsigned int c = 0; c <
_multi_index[r].size(); c++)
152 polynomial *= q_point(c);
174 RealEigenMatrix Ae = RealEigenMatrix::Zero(
_q,
_q);
175 RealEigenVector be = RealEigenVector::Zero(
_q);
179 Ae += p * p.transpose();
193 _Ae.insert(npr._Ae.begin(), npr._Ae.end());
194 _be.insert(npr._be.begin(), npr._be.end());
206std::unordered_map<processor_id_type, std::vector<dof_id_type>>
209 std::unordered_map<processor_id_type, std::vector<dof_id_type>> query_ids;
211 typedef std::pair<processor_id_type, dof_id_type> PidElemPair;
212 std::unordered_map<processor_id_type, std::vector<PidElemPair>> push_data;
214 for (
const auto & entry : specific_elems)
223 for (processor_id_type pid = 0; pid <
n_processors(); ++pid)
225 push_data[pid].push_back(std::make_pair(elem->processor_id(), elem->id()));
235 [&](
const processor_id_type,
const std::vector<PidElemPair> & received_data)
237 for (
const auto & [pid,
id] : received_data)
238 query_ids[pid].push_back(
id);
241 Parallel::push_parallel_vector_data(
_mesh.
comm(), push_data, push_receiver);
247std::unordered_map<processor_id_type, std::vector<dof_id_type>>
250 std::unordered_map<processor_id_type, std::vector<dof_id_type>> query_ids;
252 typedef std::pair<processor_id_type, dof_id_type> PidElemPair;
253 std::unordered_map<processor_id_type, std::vector<PidElemPair>> push_data;
277 const std::unordered_map<processor_id_type, std::vector<dof_id_type>> & query_ids)
279 typedef std::pair<RealEigenMatrix, RealEigenVector> AbPair;
282 auto gather_data = [
this](
const processor_id_type ,
283 const std::vector<dof_id_type> & elem_ids,
284 std::vector<AbPair> & ab_pairs)
286 for (
const auto & elem_id : elem_ids)
287 ab_pairs.emplace_back(libmesh_map_find(
_Ae, elem_id), libmesh_map_find(
_be, elem_id));
291 auto act_on_data = [
this](
const processor_id_type ,
292 const std::vector<dof_id_type> & elem_ids,
293 const std::vector<AbPair> & ab_pairs)
295 for (
const auto i : index_range(elem_ids))
297 const auto elem_id = elem_ids[i];
298 const auto & [Ae, be] = ab_pairs[i];
305 libMesh::Parallel::pull_parallel_vector_data<AbPair>(
312 std::unordered_map<processor_id_type, std::vector<dof_id_type>> & query_ids)
const
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
static std::vector< dof_id_type > removeDuplicateEntries(const std::vector< dof_id_type > &ids)
void ErrorVector unsigned int
bool hasBlocks(const SubdomainName &name) const
Test if the supplied block name is valid for this object.
static InputParameters validParams()
const QBase *const & _qrule
const Elem *const & _current_elem
The current element pointer (available during execute())
const MooseArray< Point > & _q_point
const libMesh::ConstElemRange & getEvaluableElementRange()
In general, {evaluable elements} >= {local elements} U {algebraic ghosting elements}.
unsigned int size() const
The number of elements that can currently be stored in the array.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
virtual unsigned int dimension() const
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
virtual Elem * elemPtr(const dof_id_type i)
NodalPatchRecoveryBase(const InputParameters ¶meters)
const RealEigenVector getCachedCoefficients(const std::vector< dof_id_type > &elem_ids)
Compute coefficients, using cached values if available, and store any newly computed coefficients in ...
void execute() override
Execute method.
std::vector< dof_id_type > _cached_elem_ids
Cache for least-squares coefficients used in nodal patch recovery.
static InputParameters validParams()
void threadJoin(const UserObject &) override
Must override.
std::vector< int > _proc_ids
The processor IDs vector in the running.
void addToQuery(const libMesh::Elem *elem, std::unordered_map< processor_id_type, std::vector< dof_id_type > > &query_ids) const
Adds an element to the map provided in query_ids if it belongs to a different processor.
std::map< dof_id_type, RealEigenMatrix > _Ae
The element-level A matrix.
RealEigenVector evaluateBasisFunctions(const Point &q_point) const
Compute the P vector at a given point i.e.
std::unordered_map< processor_id_type, std::vector< dof_id_type > > gatherRequestList()
Builds a query map of element IDs that require data from other processors.
void initialize() override
Called before execute() is ever called so that data can be cleared.
void syncHelper(const std::unordered_map< processor_id_type, std::vector< dof_id_type > > &query_ids)
Helper function to perform the actual communication of _Ae and _be.
const std::vector< std::vector< unsigned int > > _multi_index
Multi-index table for a polynomial basis.
std::map< dof_id_type, RealEigenVector > _be
The element-level b vector.
RealEigenVector _cached_coef
void finalize() override
Finalize.
const unsigned int _q
Number of basis functions.
bool _distributed_mesh
Whether the mesh is distributed.
const RealEigenVector getCoefficients(const std::vector< dof_id_type > &elem_ids) const
Compute coefficients without reading or writing cached values The coefficients returned by this funct...
virtual Real nodalPatchRecovery(const Point &p, const std::vector< dof_id_type > &elem_ids) const
Solve the least-squares problem.
virtual Real computeValue()=0
Compute the quantity to recover using nodal patch recovery.
void sync()
Synchronizes local matrices and vectors (_Ae, _be) across processors.
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
Base class for user-specific data.
processor_id_type processor_id() const
subdomain_id_type subdomain_id() const
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const