13 #include <Eigen/Dense> 18 #include "libmesh/parallel_eigen.h" 26 static 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");
50 { rm_params.
set<
unsigned short>(
"layers") = 2; });
60 _patch_polynomial_order(
61 static_cast<unsigned
int>(getParam<
MooseEnum>(
"patch_polynomial_order"))),
63 _q(_multi_index.size()),
64 _distributed_mesh(_mesh.isDistributedMesh()),
65 _proc_ids(n_processors())
72 const std::vector<dof_id_type> & elem_ids)
const 88 mooseError(
"There are not enough sample points to recover the nodal value, try reducing the " 89 "polynomial order or using a higher-order quadrature scheme.");
94 for (
auto elem_id : elem_ids_reduced)
101 " is not in the block. " 102 "Please use nodalPatchRecovery with elements in the block only.");
104 if (
_Ae.find(elem_id) ==
_Ae.end())
105 mooseError(
"Missing entry for elem_id = ", elem_id,
" in _Ae.");
106 if (
_be.find(elem_id) ==
_be.end())
107 mooseError(
"Missing entry for elem_id = ", elem_id,
" in _be.");
109 A += libmesh_map_find(
_Ae, elem_id);
110 b += libmesh_map_find(
_be, elem_id);
114 coef = A.completeOrthogonalDecomposition().solve(b);
147 for (
unsigned int c = 0; c <
_multi_index[r].size(); c++)
176 Ae += p * p.transpose();
190 _Ae.insert(npr._Ae.begin(), npr._Ae.end());
191 _be.insert(npr._be.begin(), npr._be.end());
203 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
206 std::unordered_map<processor_id_type, std::vector<dof_id_type>> query_ids;
208 typedef std::pair<processor_id_type, dof_id_type> PidElemPair;
209 std::unordered_map<processor_id_type, std::vector<PidElemPair>> push_data;
211 for (
const auto & entry : specific_elems)
222 push_data[pid].push_back(std::make_pair(elem->processor_id(), elem->id()));
234 for (
const auto & [pid,
id] : received_data)
235 query_ids[pid].push_back(
id);
238 Parallel::push_parallel_vector_data(
_mesh.
comm(), push_data, push_receiver);
244 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
247 std::unordered_map<processor_id_type, std::vector<dof_id_type>> query_ids;
249 typedef std::pair<processor_id_type, dof_id_type> PidElemPair;
250 std::unordered_map<processor_id_type, std::vector<PidElemPair>> push_data;
274 const std::unordered_map<
processor_id_type, std::vector<dof_id_type>> & query_ids)
276 typedef std::pair<RealEigenMatrix, RealEigenVector> AbPair;
280 const std::vector<dof_id_type> & elem_ids,
281 std::vector<AbPair> & ab_pairs)
283 for (
const auto & elem_id : elem_ids)
284 ab_pairs.emplace_back(libmesh_map_find(
_Ae, elem_id), libmesh_map_find(
_be, elem_id));
289 const std::vector<dof_id_type> & elem_ids,
290 const std::vector<AbPair> & ab_pairs)
294 const auto elem_id = elem_ids[i];
295 const auto & [Ae, be] = ab_pairs[i];
302 libMesh::Parallel::pull_parallel_vector_data<AbPair>(
309 std::unordered_map<
processor_id_type, std::vector<dof_id_type>> & query_ids)
const 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.
std::vector< int > _proc_ids
The processor IDs vector in the running.
std::map< dof_id_type, RealEigenVector > _be
The element-level b vector.
static InputParameters validParams()
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.
void initialize() override
Called before execute() is ever called so that data can be cleared.
const MooseArray< Point > & _q_point
virtual Elem * elemPtr(const dof_id_type i)
static InputParameters validParams()
std::vector< dof_id_type > _cached_elem_ids
Cache for least-squares coefficients used in nodal patch recovery.
void sync()
Synchronizes local matrices and vectors (_Ae, _be) across processors.
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.
static std::vector< dof_id_type > removeDuplicateEntries(const std::vector< dof_id_type > &ids)
const Parallel::Communicator & comm() const
const Parallel::Communicator & _communicator
virtual Real nodalPatchRecovery(const Point &p, const std::vector< dof_id_type > &elem_ids) const
Solve the least-squares problem.
void execute() override
Execute method.
uint8_t processor_id_type
processor_id_type n_processors() const
unsigned int size() const
The number of elements that can currently be stored in the array.
virtual unsigned int dimension() const
Returns MeshBase::mesh_dimension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh me...
RealEigenVector _cached_coef
NodalPatchRecoveryBase(const InputParameters ¶meters)
const std::vector< std::vector< unsigned int > > _multi_index
Multi-index table for a polynomial basis.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
bool _distributed_mesh
Whether the mesh is distributed.
R polynomial(const C &c, const T x)
Evaluate a polynomial with the coefficients c at x.
virtual Real computeValue()=0
Compute the quantity to recover using nodal patch recovery.
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic > RealEigenMatrix
void finalize() override
Finalize.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
const QBase *const & _qrule
const Elem *const & _current_elem
The current element pointer (available during execute())
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
std::vector< std::vector< unsigned int > > multiIndex(unsigned int dim, unsigned int order)
generate a complete multi index table for given dimension and order i.e.
void threadJoin(const UserObject &) override
Must override.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
const libMesh::ConstElemRange & getEvaluableElementRange()
In general, {evaluable elements} >= {local elements} U {algebraic ghosting elements}.
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...
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.
bool hasBlocks(const SubdomainName &name) const
Test if the supplied block name is valid for this object.
processor_id_type processor_id() const
processor_id_type processor_id() const
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 ...
const unsigned int _q
Number of basis functions.
void ErrorVector unsigned int
auto index_range(const T &sizable)
Base class for user-specific data.