https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FeatureVolumeVectorPostprocessor.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11
12// MOOSE includes
13#include "Assembly.h"
14#include "FeatureFloodCount.h"
16#include "MooseMesh.h"
17#include "MooseVariable.h"
18#include "SystemBase.h"
19
20#include "libmesh/quadrature.h"
21
23
26{
29
30 params.addRequiredParam<UserObjectName>("flood_counter",
31 "The FeatureFloodCount UserObject to get values from.");
32 params.addParam<bool>("single_feature_per_element",
33 false,
34 "Set this Boolean if you wish to use an element based volume where"
35 " the dominant order parameter determines the feature that accumulates the "
36 "entire element volume");
37 params.addParam<bool>("output_centroids", false, "Set to true to output the feature centroids");
38 params.addClassDescription("This object is designed to pull information from the data structures "
39 "of a \"FeatureFloodCount\" or derived object (e.g. individual "
40 "feature volumes)");
41
42 params.suppressParameter<bool>("contains_complete_history");
43
44 return params;
45}
46
48 const InputParameters & parameters)
49 : GeneralVectorPostprocessor(parameters),
51 BoundaryRestrictable(this, false),
52 _single_feature_per_elem(getParam<bool>("single_feature_per_element")),
53 _output_centroids(getParam<bool>("output_centroids")),
54 _feature_counter(getUserObject<FeatureFloodCount>("flood_counter")),
55 _var_num(declareVector("var_num")),
56 _feature_volumes(declareVector("feature_volumes")),
57 _intersects_bounds(declareVector("intersects_bounds")),
58 _intersects_specified_bounds(declareVector("intersects_specified_bounds")),
59 _percolated(declareVector("percolated")),
60 _vars(_feature_counter.getFECoupledVars()),
61 _mesh(_subproblem.mesh()),
62 _assembly(_subproblem.assembly(_tid, _sys.number())),
63 _q_point(_assembly.qPoints()),
64 _qrule(_assembly.qRule()),
65 _JxW(_assembly.JxW()),
66 _coord(_assembly.coordTransformation()),
67 _qrule_face(_assembly.qRuleFace()),
68 _JxW_face(_assembly.JxWFace())
69{
71
73
74 _coupled_sln.reserve(_vars.size());
75 for (auto & var : _feature_counter.getCoupledVars())
76 _coupled_sln.push_back(&var->sln());
77
78 const std::array<std::string, 3> suffix = {{"x", "y", "z"}};
80 for (unsigned int i = 0; i < 3; ++i)
81 _centroid[i] = &declareVector("centroid_" + suffix[i]);
82}
83
84void
88
89void
91{
92 const auto num_features = _feature_counter.getTotalFeatureCount();
93
94 // Reset the variable index and intersect bounds vectors
95 _var_num.assign(num_features, -1); // Invalid
96 _intersects_bounds.assign(num_features, -1); // Invalid
97 _intersects_specified_bounds.assign(num_features, -1); // Invalid
98 _percolated.assign(num_features, -1); // Invalid
99 for (MooseIndex(num_features) feature_num = 0; feature_num < num_features; ++feature_num)
100 {
101 auto var_num = _feature_counter.getFeatureVar(feature_num);
102 if (var_num != FeatureFloodCount::invalid_id)
103 _var_num[feature_num] = var_num;
104
105 _intersects_bounds[feature_num] =
106 static_cast<unsigned int>(_feature_counter.doesFeatureIntersectBoundary(feature_num));
107
108 _intersects_specified_bounds[feature_num] = static_cast<unsigned int>(
110
111 _percolated[feature_num] =
112 static_cast<unsigned int>(_feature_counter.isFeaturePercolated(feature_num));
113 }
114
116 {
117 for (std::size_t i = 0; i < 3; ++i)
118 _centroid[i]->resize(num_features);
119 for (std::size_t feature_num = 0; feature_num < num_features; ++feature_num)
120 {
121 auto p = _feature_counter.featureCentroid(feature_num);
122 for (std::size_t i = 0; i < 3; ++i)
123 (*_centroid[i])[feature_num] = p(i);
124 }
125 }
126
127 // Reset the volume vector
128 _feature_volumes.assign(num_features, 0);
129
130 // Calculate coverage of a boundary if one has been supplied in the input file
132 {
133 const std::set<BoundaryID> supplied_bnd_ids = BoundaryRestrictable::boundaryIDs();
134 for (auto elem_it = _mesh.bndElemsBegin(), elem_end = _mesh.bndElemsEnd(); elem_it != elem_end;
135 ++elem_it)
136
137 // loop over only boundaries supplied by user in boundary param
138 for (auto & supplied_bnd_id : supplied_bnd_ids)
139 if (((*elem_it)->_bnd_id) == supplied_bnd_id)
140 {
141 const auto & elem = (*elem_it)->_elem;
142 auto rank = processor_id();
143
144 if (elem->processor_id() == rank)
145 {
147 _fe_problem.prepare(elem, 0);
148 _fe_problem.reinitElem(elem, 0);
149 _fe_problem.reinitElemFace(elem, (*elem_it)->_side, 0);
150
151 const auto & var_to_features = _feature_counter.getVarToFeatureVector(elem->id());
152
153 accumulateBoundaryFaces(elem, var_to_features, num_features, (*elem_it)->_side);
154 }
155 }
156 }
157 else // If no boundary is supplied, calculate volumes of features as normal
158 for (const auto & elem : _mesh.getMesh().active_local_element_ptr_range())
159 {
161 _fe_problem.prepare(elem, 0);
162 _fe_problem.reinitElem(elem, 0);
163
170 const auto & var_to_features = _feature_counter.getVarToFeatureVector(elem->id());
171
172 accumulateVolumes(elem, var_to_features, num_features);
173 }
174}
175
176void
182
183Real
185{
186 mooseAssert(feature_id < _feature_volumes.size(), "feature_id is out of range");
187 return _feature_volumes[feature_id];
188}
189
190void
192 const Elem * elem,
193 const std::vector<unsigned int> & var_to_features,
194 std::size_t libmesh_dbg_var(num_features))
195{
196 unsigned int dominant_feature_id = FeatureFloodCount::invalid_id;
197 Real max_var_value = std::numeric_limits<Real>::lowest();
198
199 for (MooseIndex(var_to_features) var_index = 0; var_index < var_to_features.size(); ++var_index)
200 {
201 // Only sample "active" variables
202 if (var_to_features[var_index] != FeatureFloodCount::invalid_id)
203 {
204 auto feature_id = var_to_features[var_index];
205 mooseAssert(feature_id < num_features, "Feature ID out of range");
206 auto integral_value = computeIntegral(var_index);
207
208 // Compute volumes in a simplistic but domain conservative fashion
210 {
211 if (integral_value > max_var_value)
212 {
213 // Update the current dominant feature and associated value
214 max_var_value = integral_value;
215 dominant_feature_id = feature_id;
216 }
217 }
218 // Solution based volume calculation (integral value)
219 else
220 _feature_volumes[feature_id] += integral_value;
221 }
222 }
223
224 // Accumulate the entire element volume into the dominant feature. Do not use the integral value
225 if (_single_feature_per_elem && dominant_feature_id != FeatureFloodCount::invalid_id)
226 _feature_volumes[dominant_feature_id] += _assembly.elementVolume(elem);
227}
228
229Real
231{
232 Real sum = 0;
233
234 for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
235 sum += _JxW[qp] * _coord[qp] * (*_coupled_sln[var_index])[qp];
236
237 return sum;
238}
239
240void
242 const Elem * elem,
243 const std::vector<unsigned int> & var_to_features,
244 std::size_t libmesh_dbg_var(num_features),
245 unsigned int side)
246{
247 unsigned int dominant_feature_id = FeatureFloodCount::invalid_id;
248 Real max_var_value = std::numeric_limits<Real>::lowest();
249
250 for (MooseIndex(var_to_features) var_index = 0; var_index < var_to_features.size(); ++var_index)
251 {
252 // Only sample "active" variables
253 if (var_to_features[var_index] != FeatureFloodCount::invalid_id)
254 {
255 auto feature_id = var_to_features[var_index];
256 mooseAssert(feature_id < num_features, "Feature ID out of range");
257 auto integral_value = computeFaceIntegral(var_index);
258
260 {
261 if (integral_value > max_var_value)
262 {
263 // Update the current dominant feature and associated value
264 max_var_value = integral_value;
265 dominant_feature_id = feature_id;
266 }
267 }
268 // Solution based boundary area/length calculation (integral value)
269 else
270 _feature_volumes[feature_id] += integral_value;
271 }
272 }
273
274 // Accumulate the boundary area/length into the dominant feature. Do not use the integral value
275 if (_single_feature_per_elem && dominant_feature_id != FeatureFloodCount::invalid_id)
276 {
277 std::unique_ptr<const Elem> side_elem = elem->build_side_ptr(side);
278 _feature_volumes[dominant_feature_id] += _assembly.elementVolume(side_elem.get());
279 }
280}
281
282Real
284{
285 Real sum = 0;
286 for (unsigned int qp = 0; qp < _qrule_face->n_points(); ++qp)
287 sum += _JxW_face[qp] * _coord[qp] * (*_coupled_sln[var_index])[qp];
288
289 return sum;
290}
registerMooseObject("PhaseFieldApp", FeatureVolumeVectorPostprocessor)
const Real p
Real elementVolume(const Elem *elem) const
virtual bool boundaryRestricted() const
static InputParameters validParams()
virtual const std::set< BoundaryID > & boundaryIDs() const
virtual void reinitElem(const Elem *elem, const THREAD_ID tid) override
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid) override
virtual void prepare(const Elem *elem, const THREAD_ID tid) override
void reinitElemFace(const Elem *elem, unsigned int side, BoundaryID, const THREAD_ID tid)
This object will mark nodes or elements of continuous regions all with a unique number for the purpos...
virtual unsigned int getFeatureVar(unsigned int feature_id) const
Returns the variable representing the passed in feature.
virtual Point featureCentroid(unsigned int feature_id) const
Returns the centroid of the designated feature (only supported without periodic boundaries)
virtual bool doesFeatureIntersectBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects any boundary.
const std::vector< MooseVariable * > & getCoupledVars() const
Returns a const vector to the coupled variable pointers.
static const unsigned int invalid_id
virtual bool isFeaturePercolated(unsigned int feature_id) const
Returns a Boolean indicating whether this feature is percolated (e.g.
virtual std::size_t getTotalFeatureCount() const
Returns the total feature count (active and inactive ids, useful for sizing vectors)
virtual bool doesFeatureIntersectSpecifiedBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list.
virtual const std::vector< unsigned int > & getVarToFeatureVector(dof_id_type elem_id) const
Returns a list of active unique feature ids for a particular element.
This VectorPostprocessor is intended to be used to calculate accurate volumes from the FeatureFloodCo...
std::vector< const VariableValue * > _coupled_sln
void accumulateVolumes(const Elem *elem, const std::vector< unsigned int > &var_to_features, std::size_t num_features)
Add volume contributions to one or entries in the feature volume vector.
Real computeFaceIntegral(std::size_t var_index) const
Calculate the integral on the face if boundary is supplied as input.
Real computeIntegral(std::size_t var_index) const
Calculate the integral value of the passed in variable (index)
const std::vector< MooseVariableFEBase * > & _vars
std::array< VectorPostprocessorValue *, 3 > _centroid
bool _is_boundary_restricted
Indicates whether the calculation should be run on volumes or area of a boundary.
const bool _single_feature_per_elem
A Boolean indicating how the volume is calculated.
FeatureVolumeVectorPostprocessor(const InputParameters &parameters)
void accumulateBoundaryFaces(const Elem *elem, const std::vector< unsigned int > &var_to_features, std::size_t num_features, unsigned int side)
When boundary is supplied as input, compute coverage of that boundary by each feature.
const FeatureFloodCount & _feature_counter
A reference to the feature flood count object.
VectorPostprocessorValue & _intersects_specified_bounds
Real getFeatureVolume(unsigned int feature_id) const
Returns the volume for the given grain number.
static InputParameters validParams()
void suppressParameter(const std::string &name)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
MeshBase & getMesh()
virtual bnd_elem_iterator bndElemsBegin()
virtual bnd_elem_iterator bndElemsEnd()
void addMooseVariableDependency(MooseVariableFieldBase *var)
FEProblemBase & _fe_problem
VectorPostprocessorValue & declareVector(const std::string &vector_name)
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
MeshBase & mesh