www.mooseframework.org
FeatureVolumeVectorPostprocessor.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
19 #include "libmesh/quadrature.h"
20 
22 
23 template <>
24 InputParameters
26 {
27  InputParameters params = validParams<GeneralVectorPostprocessor>();
28  params += validParams<BoundaryRestrictable>();
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),
50  MooseVariableDependencyInterface(),
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)),
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 {
70  addMooseVariableDependency(_vars);
71 
72  _is_boundary_restricted = boundaryRestricted();
73 
74  _coupled_sln.reserve(_vars.size());
75  for (auto & var : _feature_counter.getCoupledVars())
76  _coupled_sln.push_back(&var->sln());
77 }
78 
79 void
81 {
82 }
83 
84 void
86 {
87  const auto num_features = _feature_counter.getTotalFeatureCount();
88 
89  // Reset the variable index and intersect bounds vectors
90  _var_num.assign(num_features, -1); // Invalid
91  _intersects_bounds.assign(num_features, -1); // Invalid
92  _intersects_specified_bounds.assign(num_features, -1); // Invalid
93  _percolated.assign(num_features, -1); // Invalid
94  for (MooseIndex(num_features) feature_num = 0; feature_num < num_features; ++feature_num)
95  {
96  auto var_num = _feature_counter.getFeatureVar(feature_num);
97  if (var_num != FeatureFloodCount::invalid_id)
98  _var_num[feature_num] = var_num;
99 
100  _intersects_bounds[feature_num] =
101  static_cast<unsigned int>(_feature_counter.doesFeatureIntersectBoundary(feature_num));
102 
103  _intersects_specified_bounds[feature_num] = static_cast<unsigned int>(
105 
106  _percolated[feature_num] =
107  static_cast<unsigned int>(_feature_counter.isFeaturePercolated(feature_num));
108  }
109 
110  if (_output_centroids)
111  {
112  VectorPostprocessorValue & center_x = declareVector("centroid_x");
113  center_x.resize(num_features);
114  VectorPostprocessorValue & center_y = declareVector("centroid_y");
115  center_y.resize(num_features);
116  VectorPostprocessorValue & center_z = declareVector("centroid_z");
117  center_z.resize(num_features);
118 
119  for (MooseIndex(_var_num) feature_num = 0; feature_num < num_features; ++feature_num)
120  {
121  auto p = _feature_counter.featureCentroid(feature_num);
122  center_x[feature_num] = p(0);
123  center_y[feature_num] = p(1);
124  center_z[feature_num] = p(2);
125  }
126  }
127 
128  // Reset the volume vector
129  _feature_volumes.assign(num_features, 0);
130 
131  // Calculate coverage of a boundary if one has been supplied in the input file
133  {
134  const std::set<BoundaryID> supplied_bnd_ids = BoundaryRestrictable::boundaryIDs();
135  for (auto elem_it = _mesh.bndElemsBegin(), elem_end = _mesh.bndElemsEnd(); elem_it != elem_end;
136  ++elem_it)
137 
138  // loop over only boundaries supplied by user in boundary param
139  for (auto & supplied_bnd_id : supplied_bnd_ids)
140  if (((*elem_it)->_bnd_id) == supplied_bnd_id)
141  {
142  const auto & elem = (*elem_it)->_elem;
143  auto rank = processor_id();
144 
145  if (elem->processor_id() == rank)
146  {
147  _fe_problem.setCurrentSubdomainID(elem, 0);
148  _fe_problem.prepare(elem, 0);
149  _fe_problem.reinitElem(elem, 0);
150  _fe_problem.reinitElemFace(elem, (*elem_it)->_side, (*elem_it)->_bnd_id, 0);
151 
152  const auto & var_to_features = _feature_counter.getVarToFeatureVector(elem->id());
153 
154  accumulateBoundaryFaces(elem, var_to_features, num_features, (*elem_it)->_side);
155  }
156  }
157  }
158  else // If no boundary is supplied, calculate volumes of features as normal
159  for (const auto & elem : _mesh.getMesh().active_local_element_ptr_range())
160  {
161  _fe_problem.setCurrentSubdomainID(elem, 0);
162  _fe_problem.prepare(elem, 0);
163  _fe_problem.reinitElem(elem, 0);
164 
171  const auto & var_to_features = _feature_counter.getVarToFeatureVector(elem->id());
172 
173  accumulateVolumes(elem, var_to_features, num_features);
174  }
175 }
176 
177 void
179 {
180  // Do the parallel sum
181  _communicator.sum(_feature_volumes);
182 }
183 
184 Real
186 {
187  mooseAssert(feature_id < _feature_volumes.size(), "feature_id is out of range");
188  return _feature_volumes[feature_id];
189 }
190 
191 void
193  const Elem * elem,
194  const std::vector<unsigned int> & var_to_features,
195  std::size_t libmesh_dbg_var(num_features))
196 {
197  unsigned int dominant_feature_id = FeatureFloodCount::invalid_id;
198  Real max_var_value = std::numeric_limits<Real>::lowest();
199 
200  for (MooseIndex(var_to_features) var_index = 0; var_index < var_to_features.size(); ++var_index)
201  {
202  // Only sample "active" variables
203  if (var_to_features[var_index] != FeatureFloodCount::invalid_id)
204  {
205  auto feature_id = var_to_features[var_index];
206  mooseAssert(feature_id < num_features, "Feature ID out of range");
207  auto integral_value = computeIntegral(var_index);
208 
209  // Compute volumes in a simplistic but domain conservative fashion
211  {
212  if (integral_value > max_var_value)
213  {
214  // Update the current dominant feature and associated value
215  max_var_value = integral_value;
216  dominant_feature_id = feature_id;
217  }
218  }
219  // Solution based volume calculation (integral value)
220  else
221  _feature_volumes[feature_id] += integral_value;
222  }
223  }
224 
225  // Accumulate the entire element volume into the dominant feature. Do not use the integral value
226  if (_single_feature_per_elem && dominant_feature_id != FeatureFloodCount::invalid_id)
227  _feature_volumes[dominant_feature_id] += elem->volume();
228 }
229 
230 Real
232 {
233  Real sum = 0;
234 
235  for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
236  sum += _JxW[qp] * _coord[qp] * (*_coupled_sln[var_index])[qp];
237 
238  return sum;
239 }
240 
241 void
243  const Elem * elem,
244  const std::vector<unsigned int> & var_to_features,
245  std::size_t libmesh_dbg_var(num_features),
246  unsigned int side)
247 {
248  unsigned int dominant_feature_id = FeatureFloodCount::invalid_id;
249  Real max_var_value = std::numeric_limits<Real>::lowest();
250 
251  for (MooseIndex(var_to_features) var_index = 0; var_index < var_to_features.size(); ++var_index)
252  {
253  // Only sample "active" variables
254  if (var_to_features[var_index] != FeatureFloodCount::invalid_id)
255  {
256  auto feature_id = var_to_features[var_index];
257  mooseAssert(feature_id < num_features, "Feature ID out of range");
258  auto integral_value = computeFaceIntegral(var_index);
259 
261  {
262  if (integral_value > max_var_value)
263  {
264  // Update the current dominant feature and associated value
265  max_var_value = integral_value;
266  dominant_feature_id = feature_id;
267  }
268  }
269  // Solution based boundary area/length calculation (integral value)
270  else
271  _feature_volumes[feature_id] += integral_value;
272  }
273  }
274 
275  // Accumulate the boundary area/length into the dominant feature. Do not use the integral value
276  if (_single_feature_per_elem && dominant_feature_id != FeatureFloodCount::invalid_id)
277  _feature_volumes[dominant_feature_id] += elem->side_ptr(side)->volume();
278 }
279 
280 Real
282 {
283  Real sum = 0;
284  for (unsigned int qp = 0; qp < _qrule_face->n_points(); ++qp)
285  sum += _JxW_face[qp] * _coord[qp] * (*_coupled_sln[var_index])[qp];
286 
287  return sum;
288 }
FeatureVolumeVectorPostprocessor::_single_feature_per_elem
const bool _single_feature_per_elem
A Boolean indicating how the volume is calculated.
Definition: FeatureVolumeVectorPostprocessor.h:51
FeatureVolumeVectorPostprocessor::accumulateVolumes
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.
Definition: FeatureVolumeVectorPostprocessor.C:192
FeatureFloodCount::doesFeatureIntersectBoundary
virtual bool doesFeatureIntersectBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects any boundary.
Definition: FeatureFloodCount.C:828
FeatureFloodCount::getVarToFeatureVector
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.
Definition: FeatureFloodCount.C:701
FeatureFloodCount::featureCentroid
virtual Point featureCentroid(unsigned int feature_id) const
Returns the centroid of the designated feature (only supported without periodic boundaries)
Definition: FeatureFloodCount.C:900
FeatureVolumeVectorPostprocessor::execute
virtual void execute() override
Definition: FeatureVolumeVectorPostprocessor.C:85
FeatureVolumeVectorPostprocessor::_qrule
const QBase *const & _qrule
Definition: FeatureVolumeVectorPostprocessor.h:90
FeatureFloodCount::isFeaturePercolated
virtual bool isFeaturePercolated(unsigned int feature_id) const
Returns a Boolean indicating whether this feature is percolated (e.g.
Definition: FeatureFloodCount.C:874
FeatureFloodCount
This object will mark nodes or elements of continuous regions all with a unique number for the purpos...
Definition: FeatureFloodCount.h:44
FeatureFloodCount::getTotalFeatureCount
virtual std::size_t getTotalFeatureCount() const
Returns the total feature count (active and inactive ids, useful for sizing vectors)
Definition: FeatureFloodCount.C:798
FeatureVolumeVectorPostprocessor::getFeatureVolume
Real getFeatureVolume(unsigned int feature_id) const
Returns the volume for the given grain number.
Definition: FeatureVolumeVectorPostprocessor.C:185
FeatureVolumeVectorPostprocessor::_qrule_face
const QBase *const & _qrule_face
Definition: FeatureVolumeVectorPostprocessor.h:93
FeatureVolumeVectorPostprocessor::_JxW_face
const MooseArray< Real > & _JxW_face
Definition: FeatureVolumeVectorPostprocessor.h:94
validParams< FeatureVolumeVectorPostprocessor >
InputParameters validParams< FeatureVolumeVectorPostprocessor >()
Definition: FeatureVolumeVectorPostprocessor.C:25
FeatureVolumeVectorPostprocessor::finalize
virtual void finalize() override
Definition: FeatureVolumeVectorPostprocessor.C:178
FeatureFloodCount::getCoupledVars
const std::vector< MooseVariable * > & getCoupledVars() const
Returns a const vector to the coupled variable pointers.
Definition: FeatureFloodCount.h:98
FeatureVolumeVectorPostprocessor::_feature_volumes
VectorPostprocessorValue & _feature_volumes
Definition: FeatureVolumeVectorPostprocessor.h:58
FeatureVolumeVectorPostprocessor::_intersects_specified_bounds
VectorPostprocessorValue & _intersects_specified_bounds
Definition: FeatureVolumeVectorPostprocessor.h:60
FeatureVolumeVectorPostprocessor::_var_num
VectorPostprocessorValue & _var_num
Definition: FeatureVolumeVectorPostprocessor.h:57
FeatureFloodCount.h
FeatureFloodCount::getFeatureVar
virtual unsigned int getFeatureVar(unsigned int feature_id) const
Returns the variable representing the passed in feature.
Definition: FeatureFloodCount.C:809
FeatureVolumeVectorPostprocessor::_coupled_sln
std::vector< const VariableValue * > _coupled_sln
Definition: FeatureVolumeVectorPostprocessor.h:85
FeatureVolumeVectorPostprocessor::_output_centroids
const bool _output_centroids
Definition: FeatureVolumeVectorPostprocessor.h:52
FeatureFloodCount::doesFeatureIntersectSpecifiedBoundary
virtual bool doesFeatureIntersectSpecifiedBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list.
Definition: FeatureFloodCount.C:850
FeatureVolumeVectorPostprocessor::_feature_counter
const FeatureFloodCount & _feature_counter
A reference to the feature flood count object.
Definition: FeatureVolumeVectorPostprocessor.h:55
FeatureVolumeVectorPostprocessor::computeFaceIntegral
Real computeFaceIntegral(std::size_t var_index) const
Calculate the integral on the face if boundary is supplied as input.
Definition: FeatureVolumeVectorPostprocessor.C:281
FeatureVolumeVectorPostprocessor::_percolated
VectorPostprocessorValue & _percolated
Definition: FeatureVolumeVectorPostprocessor.h:61
FeatureVolumeVectorPostprocessor::_is_boundary_restricted
bool _is_boundary_restricted
Indicates whether the calculation should be run on volumes or area of a boundary.
Definition: FeatureVolumeVectorPostprocessor.h:64
FeatureVolumeVectorPostprocessor::accumulateBoundaryFaces
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.
Definition: FeatureVolumeVectorPostprocessor.C:242
FeatureFloodCount::invalid_id
static const unsigned int invalid_id
Definition: FeatureFloodCount.h:94
GrainTrackerInterface.h
FeatureVolumeVectorPostprocessor::initialize
virtual void initialize() override
Definition: FeatureVolumeVectorPostprocessor.C:80
registerMooseObject
registerMooseObject("PhaseFieldApp", FeatureVolumeVectorPostprocessor)
FeatureVolumeVectorPostprocessor
This VectorPostprocessor is intended to be used to calculate accurate volumes from the FeatureFloodCo...
Definition: FeatureVolumeVectorPostprocessor.h:33
FeatureVolumeVectorPostprocessor::computeIntegral
Real computeIntegral(std::size_t var_index) const
Calculate the integral value of the passed in variable (index)
Definition: FeatureVolumeVectorPostprocessor.C:231
FeatureVolumeVectorPostprocessor::_intersects_bounds
VectorPostprocessorValue & _intersects_bounds
Definition: FeatureVolumeVectorPostprocessor.h:59
FeatureVolumeVectorPostprocessor.h
FeatureVolumeVectorPostprocessor::_coord
const MooseArray< Real > & _coord
Definition: FeatureVolumeVectorPostprocessor.h:92
FeatureVolumeVectorPostprocessor::_vars
const std::vector< MooseVariableFEBase * > & _vars
Definition: FeatureVolumeVectorPostprocessor.h:84
FeatureVolumeVectorPostprocessor::FeatureVolumeVectorPostprocessor
FeatureVolumeVectorPostprocessor(const InputParameters &parameters)
Definition: FeatureVolumeVectorPostprocessor.C:47
FeatureVolumeVectorPostprocessor::_mesh
MooseMesh & _mesh
Definition: FeatureVolumeVectorPostprocessor.h:87
FeatureVolumeVectorPostprocessor::_JxW
const MooseArray< Real > & _JxW
Definition: FeatureVolumeVectorPostprocessor.h:91