Loading [MathJax]/extensions/tex2jax.js
https://mooseframework.inl.gov
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
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"
15 #include "GrainTrackerInterface.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 
84 void
86 {
87 }
88 
89 void
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 
115  if (_output_centroids)
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 
176 void
178 {
179  // Do the parallel sum
181 }
182 
183 Real
185 {
186  mooseAssert(feature_id < _feature_volumes.size(), "feature_id is out of range");
187  return _feature_volumes[feature_id];
188 }
189 
190 void
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 
229 Real
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 
240 void
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 
282 Real
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 }
virtual bnd_elem_iterator bndElemsEnd()
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.
This VectorPostprocessor is intended to be used to calculate accurate volumes from the FeatureFloodCo...
std::array< VectorPostprocessorValue *, 3 > _centroid
virtual bool boundaryRestricted() const
virtual void prepare(const Elem *elem, const THREAD_ID tid) override
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
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.
const std::vector< MooseVariableFEBase * > & _vars
const std::vector< MooseVariable * > & getCoupledVars() const
Returns a const vector to the coupled variable pointers.
Real getFeatureVolume(unsigned int feature_id) const
Returns the volume for the given grain number.
MeshBase & mesh
virtual bnd_elem_iterator bndElemsBegin()
virtual std::size_t getTotalFeatureCount() const
Returns the total feature count (active and inactive ids, useful for sizing vectors) ...
const Parallel::Communicator & _communicator
void addRequiredParam(const std::string &name, const std::string &doc_string)
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.
virtual bool isFeaturePercolated(unsigned int feature_id) const
Returns a Boolean indicating whether this feature is percolated (e.g.
void suppressParameter(const std::string &name)
registerMooseObject("PhaseFieldApp", FeatureVolumeVectorPostprocessor)
virtual unsigned int getFeatureVar(unsigned int feature_id) const
Returns the variable representing the passed in feature.
bool _is_boundary_restricted
Indicates whether the calculation should be run on volumes or area of a boundary. ...
MeshBase & getMesh()
virtual void reinitElem(const Elem *elem, const THREAD_ID tid) override
VectorPostprocessorValue & _intersects_specified_bounds
static InputParameters validParams()
Real elementVolume(const Elem *elem) const
This object will mark nodes or elements of continuous regions all with a unique number for the purpos...
const FeatureFloodCount & _feature_counter
A reference to the feature flood count object.
static const unsigned int invalid_id
std::vector< const VariableValue * > _coupled_sln
VectorPostprocessorValue & declareVector(const std::string &vector_name)
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid) override
static InputParameters validParams()
virtual bool doesFeatureIntersectSpecifiedBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list...
Real computeFaceIntegral(std::size_t var_index) const
Calculate the integral on the face if boundary is supplied as input.
void addMooseVariableDependency(MooseVariableFieldBase *var)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
FEProblemBase & _fe_problem
void addClassDescription(const std::string &doc_string)
void reinitElemFace(const Elem *elem, unsigned int side, BoundaryID, const THREAD_ID tid)
const bool _single_feature_per_elem
A Boolean indicating how the volume is calculated.
processor_id_type processor_id() const
Real computeIntegral(std::size_t var_index) const
Calculate the integral value of the passed in variable (index)
FeatureVolumeVectorPostprocessor(const InputParameters &parameters)
virtual const std::set< BoundaryID > & boundaryIDs() const
virtual bool doesFeatureIntersectBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects any boundary.
virtual Point featureCentroid(unsigned int feature_id) const
Returns the centroid of the designated feature (only supported without periodic boundaries) ...