Postprocessor System
A PostProcessor object in MOOSE is a C++ object that computes a single scalar (Real
) value, typically the value computed is an aggregation of data from a simulation. For example, the maximum value of a variable (see ElementExtremeValue). The value compute may be coupled to other systems via the getPostprocessorValue
method available in most MOOSE objects.
MOOSE includes a large number of postprocessors within the framework, the complete list is provided in Available Objects list section.
Example Input File
The following input file snippet demonstrates the use of the ElementExtremeValue to compute the minimum and maximum of the solution variable "u".
[Postprocessors]
[max]
type = ElementExtremeValue
variable = u
[]
[min]
type = ElementExtremeValue
variable = u
value_type = min
[]
[]
(test/tests/postprocessors/element_extreme_value/element_extreme_value.i)This snippet is a part of a test that may be executed using the MOOSE test application as follows.
cd ~/projects/moose/test
make -j8
cd tests/postprocessors/element_extreme_value
~/projects/moose/test/moose_test-opt -i element_extreme_value.i
The data from this calculation is reported in the terminal output by default and if Exodus output is enabled the values will automatically be included in the output file. It is also possible to export the data to a comma separated value (csv) file by enabling the CSV object within the Outputs block.
Postprocessor Values:
+----------------+----------------+----------------+
| time | max | min |
+----------------+----------------+----------------+
| 0.000000e+00 | 0.000000e+00 | 0.000000e+00 |
| 1.000000e+00 | 9.788675e-01 | 2.113249e-02 |
+----------------+----------------+----------------+
Coupling Example Code
The values computed within a Postprocessor object may be used within other objects that inherit from the PostprocessorInterface, which is nearly every system within MOOSE. For example, the the PostprocessorNeumannBC object allows for a Neumann boundary condition to be set to a value computed from a postprocessor; this object will be used as example to demonstrate how coupling is performed.
To understand how the coupling is coded it is beneficial to first see how the coupling is defined via the input file. The following input file snippet shows that a PointValue postprocessor is created and named "right_pp" and the PostprocessorNeumannBC uses this value to set the boundary condition.
[Postprocessors]
[right_pp]
type = PointValue
point = '0.5 0.5 0'
variable = aux
execute_on = 'initial'
[]
[]
[BCs]
[left]
type = DirichletBC
variable = u
boundary = left
value = 0
[]
[right]
type = PostprocessorNeumannBC
variable = u
boundary = right
postprocessor = right_pp
[]
[]
(test/tests/bcs/pp_neumann/pp_neumann.i)This first step of coding this type of coupling begins by adding the necessary input file syntax to the object that requires a postprocessor value, PostprocessorNeumannBC in this example. In all MOOSE objects input file syntax is governed by the validParams function of an object. To add the ability to couple a postprocessor, simply add a new parameter using the PostprocessorName
type, as shown below. Notice, that the add parameters call includes a default value that makes the use of the postprocessor optional.
#include "PostprocessorNeumannBC.h"
registerMooseObject("MooseApp", PostprocessorNeumannBC);
defineLegacyParams(PostprocessorNeumannBC);
InputParameters
(framework/src/bcs/PostprocessorNeumannBC.C)The actual postprocessor value must be assigned to a member variable of the class, thus in the header a member variable must be created, which should always be a constant reference to a PostprocessorValue
type. Since this is a reference it must be initialized, this occurs in the source file by calling the getPostprocessorValue
method and providing the name used in the validParams function. The following snippets show declaration of the reference in the header and the initialization of this reference in the source file. The _value
member variable is then available for use anywhere inside the object, for the case of the boundary condition it is utilized in the computation of the residual.
const PostprocessorValue & _value;
(framework/include/bcs/PostprocessorNeumannBC.h)PostprocessorNeumannBC::validParams()
{
InputParameters params = IntegratedBC::validParams();
params.addParam<PostprocessorName>(
"postprocessor", 0.0, "The postprocessor to use for value of the gradient on the boundary.");
return params;
}
(framework/src/bcs/PostprocessorNeumannBC.C)Coupling to other values
Just as Postprocessor values can be used in other objects, Postprocessors themselves can couple to Functions and Scalar Variables. See the following example that couples a scalar variable into a Postprocessor:
[Postprocessors]
[./totalFlux]
type = ScalarCoupledPostprocessor
variable = u
coupled_scalar = scalar_variable
boundary = left
[../]
[]
(test/tests/postprocessors/scalar_coupled_postprocessor/scalar_coupled_postprocessor_test.i)Creating a Postprocessor
Object
In general, every Postprocessor object has two methods that must be defined "execute" and "getValue".
First, consider the execute method. This method is called by MOOSE at different time depending on the type of postprocessor object. Therefore, when creating a Postprocessor object the new object should inherit from one of the following C++ classes:
GeneralPostprocessor: "execute" is called once on each execution flag.
NodalPostprocessor: "execute" is called for each node within the mesh on each execution flag.
ElementalPostprocessor: "execute" is called for each element within the mesh on each execution flag.
InternalSidePostprocessor: "execute" is called for each side, that is not on a boundary, within the mesh on each execution flag.
SidePostprocessor: "execute" is called for each side, that is on a boundary, within the mesh on each execution flag.
The use of execution flags is discussed in the Execute On section.
The getValue method is responsible for returning the value of the postprocessor object, this value is what is used by all objects that are coupled to the postprocessor. In some cases the necessary communication is performed within this method, but in general this following is preferred.
Parallel Considerations
When creating a postprocessor it is often necessary to perform some parallel communication to ensure that the value being computed is correct across processes and threads. Three additional methods exists for making this process as simple as possible.
initialize
: This is called prior to the execution of the postprocessor and should be used to setup the object to be in a known state. It is important to point out that execution in this context includes all calls to the execute method. For example, for aNodalPostprocessor
object the initialize method is called and then the execute method is called for all nodes.finalize
: This is called after the execution of the postprocessor and is intended to perform communication to prepare the object for the call to the getValue method.threadJoin
: This is called after the execution of the postprocessor and is intended to perform aggregation for shared memory parallelism.
To understand the use of these methods the AverageNodalVariableValue postprocessor shall be used as an example. As the name suggests this postprocessor computes the average of the value of a variable at the nodes. To perform this calculation the variable values from each node are summed as is the number of values within the execute method. Then the getValue method returns the average by returning the sum divided by the count. The following snippet shows the these two methods: the _u[_qp]
is the value of the variable at the current node that comes from a shared base class and _sum
and _n
are a member variables defined within class for performing the calculation.
void
AverageNodalVariableValue::execute()
{
_sum += _u[_qp];
_n++;
}
Real
AverageNodalVariableValue::getValue()
{
return _sum / _n;
}
(framework/src/postprocessors/AverageNodalVariableValue.C)In parallel, the calls to the execute method occur on each process or thread on a subset of the domain, in this case nodes. Therefore, the computed values must be combined to get the actual summations required to compute the average value. The first step is to setup the state of this calculation within the initialize method, which in this example sets the _sum
and _n
member variables to zero.
void
AverageNodalVariableValue::initialize()
{
_sum = 0;
_n = 0;
}
(framework/src/postprocessors/AverageNodalVariableValue.C)After the aforementioned execute method is called for each node the computed values for _sum
and _n
must be aggregated from across processes to the root processes. For this problem a gather operation is required to collect the values computed on all processes to the root process. This is accomplished via the gatherSum
method.
void
AverageNodalVariableValue::finalize()
{
gatherSum(_sum);
gatherSum(_n);
}
(framework/src/postprocessors/AverageNodalVariableValue.C)Of course, the type of communication necessary depends on the calculation being performed. The UserObject base class includes helper methods for common parallel communications functions.
The initialize and finalize methods are utilized to aggregate for message passing (MPI) based parallelism. For shared memory parallelism the theadJoin method is used. This method is called, like finalize, after execution is complete and includes a single argument. This argument is a reference to a UserObject, which is a base class of Postprocessor objects. The purpose of this method is to enable the aggregation for the Postprocessor objects that were executed on other threads to the object on the root thread. For the AverageNodalVariableValue postprocessor the values for _sum
and _n
on the root process object are updated to include the these same values from the other threads.
void
AverageNodalVariableValue::threadJoin(const UserObject & y)
{
const AverageNodalVariableValue & pps = static_cast<const AverageNodalVariableValue &>(y);
_sum += pps._sum;
_n += pps._n;
}
(framework/src/postprocessors/AverageNodalVariableValue.C)Execute On...
Postprocessor objects inherit from the SetupInterface (execute_on) that allows the objects to execute and varying and multiple times during a simulation, such as during initialization and at the end of each time step. Refer to the SetupInterface (execute_on) for additional information.
Using Old and Older values
MOOSE maintains previously computed values in the postprocessor system for using lagged information in a computation. Both the previous time step's value and the value computed two steps back may be retrieved. One reason you might use older values is to break cyclic dependencies. MOOSE does not consider a dependence on an old value when considering the order of evaluation among objects with dependencies.
Available Objects
- Moose App
- AreaPostprocessorComputes the "area" or dimension - 1 "volume" of a given boundary or boundaries in your mesh.
- AverageElementSize
- AverageNodalVariableValueComputes the average value of a field by sampling all nodal solutions on the domain or within a subdomain
- AxisymmetricCenterlineAverageValueComputes the average value of a variable on a sideset located along the centerline of an axisymmetric model.
- ChangeOverTimePostprocessorComputes the change or relative change in a post-processor value over a timestep or the entire transient
- ChangeOverTimestepPostprocessorComputes the change or relative change in a post-processor value over a timestep or the entire transient
- CumulativeValuePostprocessor
- DifferencePostprocessor
- ElementAverageSecondTimeDerivativeComputes the element averaged second derivative of variable
- ElementAverageTimeDerivativeComputes a volume integral of the time derivative of a given variable
- ElementAverageValue
- ElementExtremeValueFinds either the min or max elemental value of a a variable over the domain.
- ElementH1Error
- ElementH1SemiError
- ElementIntegralArrayVariablePostprocessorIntegral of one component of an array variable.
- ElementIntegralMaterialProperty
- ElementIntegralVariablePostprocessor
- ElementL2DifferenceComputes the element-wise L2 difference between the current variable and a coupled variable.
- ElementL2Error
- ElementL2Norm
- ElementVectorL2ErrorComputes the Vector L2 difference of up to three variables simultaneously (normally x, y, z)
- ElementW1pError
- ElementalVariableValueOutputs an elemental variable value at a particular location
- EmptyPostprocessor
- ExecutionerAttributeReporter
- FindValueOnLineFind a specific target value along a sampling line. The variable values along the line should change monotonically. The target value is searched using a bisection algorithm.
- FunctionElementIntegralIntegrates a function over elements
- FunctionSideIntegral
- FunctionValuePostprocessorComputes the value of a supplied function at a single point (scalable)
- GreaterThanLessThanPostprocessor
- InterfaceAverageVariableValuePostprocessorComputes the average value of a variable on an interface. Note that this cannot be used on the centerline of an axisymmetric model.
- InterfaceIntegralVariableValuePostprocessorAdd access to variables and their gradient on an interface.
- LinearCombinationPostprocessor
- MemoryUsageMemory usage statistics for the running simulation.
- NodalExtremeValue
- NodalL2Error
- NodalL2Norm
- NodalMaxValue
- NodalProxyMaxValue
- NodalSumComputes the sum of all of the nodal values of the specified variable. Note: This object sets the default "unique_node_execute" flag to true to avoid double counting nodes between shared blocks.
- NodalVariableValueOutputs values of a nodal variable at a particular location
- NumDOFsReturn the number of Degrees of freedom from either the NL, Aux or both systems.
- NumElemsReturn the number of active or total elements in the simulation.
- NumLinearIterations
- NumNodesReturns the total number of nodes in a simulation (works with DistributedMesh)
- NumNonlinearIterationsOutputs the number of nonlinear iterations
- NumPicardIterations
- NumRelationshipManagersReturn the number of relationship managers active.
- NumResidualEvaluations
- NumVarsReturn the number of variables from either the NL, Aux, or both systems.
- PercentChangePostprocessor
- PerfGraphDataRetrieves timing information from the PerfGraph.
- PerformanceDataProvides programmatic access to Performance Log Data
- PointValue
- PostprocessorComparisonCompares two post-processors and produces a boolean value
- ReceiverReports the value stored in this processor, which is usually filled in by another object. The Receiver does not compute its own value.
- RelativeDifferencePostprocessorComputes the absolute value of the relative difference between 2 post-processor values.
- RelativeSolutionDifferenceNormComputes the relative norm of the solution difference of two consecutive time steps.
- Residual
- ScalarL2Error
- ScalarVariable
- ScalePostprocessorScales a post-processor by a value
- SideAverageValueComputes the average value of a variable on a sideset. Note that this cannot be used on the centerline of an axisymmetric model.
- SideFluxAverageComputes the integral of the flux over the specified boundary
- SideFluxIntegralComputes the integral of the flux over the specified boundary
- SideIntegralVariablePostprocessor
- TimeExtremeValueA postprocessor for reporting the extreme value of another postprocessor over time.
- TimestepSizeReports the timestep size
- TotalVariableValue
- VariableInnerProduct
- VariableResidualComputes the Residual of a single variable in the solution vector.
- VectorPostprocessorComparisonCompares two vector post-processors of equal size and produces a boolean value
- VolumePostprocessorComputes the volume of a specified block
- Heat Conduction App
- ConvectiveHeatTransferSideIntegralComputes the total convective heat transfer across a boundary.
- GrayLambertSurfaceRadiationPPThis postprocessor allows to extract radiosity, heat flux density, and temperature from the GrayLambertSurfaceRadiationBase object.
- HomogenizedThermalConductivityPostprocessor for asymptotic expansion homogenization for thermal conductivity
- ThermalConductivityComputes the average value of a variable on a sideset. Note that this cannot be used on the centerline of an axisymmetric model.
- ViewFactorPPThis postprocessor allows to extract view factors from ViewFactor userobjects.
- Rdg App
- BoundaryFluxPostprocessorComputes the side integral of a flux entry from a BoundaryFluxBase user object
- Contact App
- ContactDOFSetSizeOutputs the number of dofs greater than a tolerance threshold indicating mechanical contact
- Navier Stokes App
- INSExplicitTimestepSelectorPostprocessor that computes the minimum value of h_min/|u|, where |u| is coupled in as an aux variable.
- NSEntropyErrorComputes entropy error.
- VolumetricFlowRateComputes the volumetric flow rate through a boundary.
- Porous Flow App
- PorousFlowFluidMassCalculates the mass of a fluid component in a region
- PorousFlowHeatEnergyCalculates the sum of heat energy of fluid phase(s) and/or the porous skeleton in a region
- PorousFlowPlotQuantityExtracts the value from the PorousFlowSumQuantity UserObject
- Misc App
- InternalVolumeComputes the volume of an enclosed area by performing an integral over a user-supplied boundary.
- Tensor Mechanics App
- AsymptoticExpansionHomogenizationElasticConstantsPostprocessor for asymptotic expansion homogenization for elasticity
- CavityPressurePostprocessorInterfaces with the CavityPressureUserObject to store the initial number of moles of a gas contained within an internal volume.
- CrackFrontDataDetermines which nodes are along the crack front
- CriticalTimeStepComputes and reports the critical time step for the explicit solver.
- InteractionIntegralComputes the interaction integral for fracture
- JIntegralCalculates the J-integral at a specified point along the crack front
- Mass
- MaterialTensorIntegralThis postprocessor computes an element integral of a component of a material tensor as specified by the user-supplied indices
- MaterialTimeStepPostprocessorThis postprocessor estimates a timestep that reduces the increment change in a material property below a given threshold.
- MixedModeEquivalentKComputes the mixed-mode stress intensity factor given the , , and stress intensity factors
- TorqueReactionTorqueReaction calculates the torque in 2D and 3Dabout a user-specified axis of rotation centeredat a user-specied origin.
- Phase Field App
- AverageGrainVolumeCalculate average grain area in a polycrystal
- DiscreteNucleationDataOutput diagnostic data on a DiscreteNucleationInserter
- DiscreteNucleationTimeStepReturn a time step limit for nucleation event to be used by IterationAdaptiveDT
- FauxGrainTrackerFake grain tracker object for cases where the number of grains is equal to the number of order parameters.
- FeatureFloodCountThe object is able to find and count "connected components" in any solution field or number of solution fields. A primary example would be to count "bubbles".
- FeatureVolumeFraction
- GrainBoundaryAreaCalculate total grain boundary length in 2D and area in 3D
- GrainTrackerGrain Tracker object for running reduced order parameter simulations without grain coalescence.
- GrainTrackerElasticityGrain Tracker object for running reduced order parameter simulations without grain coalescence.
- PFCElementEnergyIntegral
- PolycrystalCirclesPolycrystal circles generated from a vector input or read from a file
- PolycrystalEBSDObject for setting up a polycrystal structure from an EBSD Datafile
- PolycrystalHexPerturbed hexagonal polycrystal
- PolycrystalVoronoiRandom Voronoi tessellation polycrystal (used by PolycrystalVoronoiAction)
- Peridynamics App
- NodalDisplacementDifferenceL2NormPDClass for computing the L2 norm of the difference between displacements and their analytic solutions
- NodalFunctionsL2NormPDClass for computing the L2 norm of functions
- NodalVariableIntegralPDClass for calculating the domain integral of nodal variables
- Level Set App
- LevelSetCFLConditionCompute the minimum timestep from the Courant-Friedrichs-Lewy (CFL) condition for the level-set equation.
- LevelSetVolumeCompute the area or volume of the region inside or outside of a level set contour.
- Chemical Reactions App
- TotalMineralVolumeFractionTotal volume fraction of coupled mineral species