Internal Volume
Overview
An important feature in a fuel performance code is the ability to compute the internal or void volume enclosed by a finite element mesh. This is necessary for computing the plenum/gap volume, for example.
The procedure is as follows. where is a field, is the normal of the surface (), is the volume of the domain, and is the surface of the domain.
We choose giving
The integral becomes
Computing the volume reduces to a surface integral of the x-coordinate times the x-component of the normal vector.
Demonstration
As a demonstration, we take an axisymmetric mesh composed of two elements along the centerline, one above the other. The height of each element, , is . The initial radius, , is 1. This gives
In a second step, the right face of one of the elements is translated to = 1.5380168369562588. The other node on the right side is left unchanged. This volume is then
Table 1: Comparison of the Bison computed internal volume to the analytical solution.
| Step | Analytical | Bison | Error (%) |
|---|---|---|---|
| 1 | 1.0 | 1.0 | 0.0 |
| 2 | 2.0 | 2.0 | 0.0 |
Input Syntax
The InternalVolume feature is written to compute internal or void volumes as positive. In the example shown here, where the volume of a solid object is computed, the volume will be reported as a negative value. We use a scale_factor of -1 in the input file shown below to have the volume reported as a positive value.
#
# Volume Test
#
# This test is designed to compute the volume of a space when displacements
# are imposed.
#
# The mesh is composed of one block (1) with two elements. The mesh is
# such that the initial volume is 1. One element face is displaced to
# produce a final volume of 2.
#
# r1
# +----+ -
# | | |
# +----+ h V1 = pi * h * r1^2
# | | |
# +----+ -
#
# becomes
#
# +----+
# | \
# +------+ v2 = pi * h/2 * ( r2^2 + 1/3 * ( r2^2 + r2*r1 + r1^2 ) )
# | |
# +------+
# r2
#
# r1 = 1
# r2 = 1.5380168369562588
# h = 1/pi
#
# Note: Because the InternalVolume PP computes cavity volumes as positive,
# the volumes reported are negative.
#
[GlobalParams<<<{"href": "../../../syntax/GlobalParams/index.html"}>>>]
displacements = 'disp_x disp_y'
[]
[Mesh<<<{"href": "../../../syntax/Mesh/index.html"}>>>]
coord_type = RZ
[mesh]
type = GeneratedMeshGenerator<<<{"description": "Create a line, square, or cube mesh with uniformly spaced or biased elements.", "href": "../../../source/meshgenerators/GeneratedMeshGenerator.html"}>>>
dim<<<{"description": "The dimension of the mesh to be generated"}>>> = 2
nx<<<{"description": "Number of elements in the X direction"}>>> = 1
ny<<<{"description": "Number of elements in the Y direction"}>>> = 2
xmin<<<{"description": "Lower X Coordinate of the generated mesh"}>>> = 0
ymin<<<{"description": "Lower Y Coordinate of the generated mesh"}>>> = 0
xmax<<<{"description": "Upper X Coordinate of the generated mesh"}>>> = 1
ymax<<<{"description": "Upper Y Coordinate of the generated mesh"}>>> = 0.3183098861837907
[]
[surface]
type = SideSetsFromBoundingBoxGenerator<<<{"description": "Defines new sidesets using currently-defined sideset IDs inside or outside of a bounding box.", "href": "../../../source/meshgenerators/SideSetsFromBoundingBoxGenerator.html"}>>>
input<<<{"description": "The mesh we want to modify"}>>> = mesh
bottom_left<<<{"description": "The bottom left point (in x,y,z with spaces in-between)."}>>> = '-0.1 -0.1 0.0'
top_right<<<{"description": "The bottom left point (in x,y,z with spaces in-between)."}>>> = '1.1 0.16 0.0'
included_boundaries<<<{"description": "A set of boundary names or ids whose sides will be included in the new sidesets. A side is only added if it also belongs to one of these boundaries."}>>> = right
boundary_new<<<{"description": "Boundary on specified block within the bounding box to assign"}>>> = pull
[]
# This test uses ElementalVariableValue postprocessors on specific
# elements, so element numbering needs to stay unchanged
allow_renumbering = false
[]
[Functions<<<{"href": "../../../syntax/Functions/index.html"}>>>]
[disp_x]
type = PiecewiseLinear<<<{"description": "Linearly interpolates between pairs of x-y data", "href": "../../../source/functions/PiecewiseLinear.html"}>>>
x<<<{"description": "The abscissa values"}>>> = '0. 1.'
y<<<{"description": "The ordinate values"}>>> = '0. 0.5380168369562588'
[]
[]
[Variables<<<{"href": "../../../syntax/Variables/index.html"}>>>]
[disp_x]
order<<<{"description": "Specifies the order of the FE shape function to use for this variable (additional orders not listed are allowed)"}>>> = FIRST
family<<<{"description": "Specifies the family of FE shape functions to use for this variable"}>>> = LAGRANGE
[]
[disp_y]
order<<<{"description": "Specifies the order of the FE shape function to use for this variable (additional orders not listed are allowed)"}>>> = FIRST
family<<<{"description": "Specifies the family of FE shape functions to use for this variable"}>>> = LAGRANGE
[]
[]
[AuxVariables<<<{"href": "../../../syntax/AuxVariables/index.html"}>>>]
[volumetric_strain]
order<<<{"description": "Specifies the order of the FE shape function to use for this variable (additional orders not listed are allowed)"}>>> = CONSTANT
family<<<{"description": "Specifies the family of FE shape functions to use for this variable"}>>> = MONOMIAL
[]
[]
[Physics<<<{"href": "../../../syntax/Physics/index.html"}>>>/SolidMechanics<<<{"href": "../../../syntax/Physics/SolidMechanics/index.html"}>>>/QuasiStatic<<<{"href": "../../../syntax/Physics/SolidMechanics/QuasiStatic/index.html"}>>>]
[all]
volumetric_locking_correction<<<{"description": "Flag to correct volumetric locking"}>>> = false
decomposition_method<<<{"description": "Methods to calculate the finite strain and rotation increments"}>>> = EigenSolution
incremental<<<{"description": "Use incremental or total strain (if not explicitly specified this defaults to incremental for finite strain and total for small strain)"}>>> = true
strain<<<{"description": "Strain formulation"}>>> = FINITE
[]
[]
[AuxKernels<<<{"href": "../../../syntax/AuxKernels/index.html"}>>>]
[fred]
type = RankTwoScalarAux<<<{"description": "Compute a scalar property of a RankTwoTensor", "href": "../../../source/auxkernels/RankTwoScalarAux.html"}>>>
rank_two_tensor<<<{"description": "The rank two material tensor name"}>>> = total_strain
variable<<<{"description": "The name of the variable that this object applies to"}>>> = volumetric_strain
scalar_type<<<{"description": "Type of scalar output"}>>> = VolumetricStrain
execute_on<<<{"description": "The list of flag(s) indicating when this object should be executed. For a description of each flag, see https://mooseframework.inl.gov/source/interfaces/SetupInterface.html."}>>> = timestep_end
[]
[]
[BCs<<<{"href": "../../../syntax/NuclearMaterials/BCs/index.html"}>>>]
[no_x]
type = DirichletBC<<<{"description": "Imposes the essential boundary condition $u=g$, where $g$ is a constant, controllable value.", "href": "../../../source/bcs/DirichletBC.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = disp_x
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = 'left top'
value<<<{"description": "Value of the BC"}>>> = 0.0
[]
[no_y]
type = DirichletBC<<<{"description": "Imposes the essential boundary condition $u=g$, where $g$ is a constant, controllable value.", "href": "../../../source/bcs/DirichletBC.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = disp_y
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = 'left top pull'
value<<<{"description": "Value of the BC"}>>> = 0.0
[]
[x]
type = FunctionDirichletBC<<<{"description": "Imposes the essential boundary condition $u=g(t,\\vec{x})$, where $g$ is a (possibly) time and space-dependent MOOSE Function.", "href": "../../../source/bcs/FunctionDirichletBC.html"}>>>
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = pull
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = disp_x
function<<<{"description": "The forcing function."}>>> = disp_x
[]
[]
[Materials<<<{"href": "../../../syntax/Materials/index.html"}>>>]
[elasticity_tensor]
type = ComputeIsotropicElasticityTensor<<<{"description": "Compute a constant isotropic elasticity tensor.", "href": "../../../source/materials/ComputeIsotropicElasticityTensor.html"}>>>
youngs_modulus<<<{"description": "Young's modulus of the material."}>>> = 1e6
poissons_ratio<<<{"description": "Poisson's ratio for the material."}>>> = 0.3
[]
[stress]
type = ComputeFiniteStrainElasticStress<<<{"description": "Compute stress using elasticity for finite strains", "href": "../../../source/materials/ComputeFiniteStrainElasticStress.html"}>>>
[]
[]
[Executioner<<<{"href": "../../../syntax/Executioner/index.html"}>>>]
type = Transient
solve_type = PJFNK
start_time = 0.0
dt = 1.0
end_time = 1.0
[]
[Postprocessors<<<{"href": "../../../syntax/Postprocessors/index.html"}>>>]
[bison_internalVolume]
type = InternalVolume<<<{"description": "Computes the volume of an enclosed area by performing an integral over a user-supplied boundary.", "href": "../../../source/postprocessors/InternalVolume.html"}>>>
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = 'bottom right top'
execute_on<<<{"description": "The list of flag(s) indicating when this object should be executed. For a description of each flag, see https://mooseframework.inl.gov/source/interfaces/SetupInterface.html."}>>> = 'initial timestep_end'
scale_factor<<<{"description": "A scale factor to be applied to the internal volume calculation"}>>> = -1
[]
[analytical_internalVolume]
type = ParsedPostprocessor<<<{"description": "Computes a parsed expression with post-processors", "href": "../../../source/postprocessors/ParsedPostprocessor.html"}>>>
pp_names<<<{"description": "Post-processors arguments"}>>> = ''
use_t<<<{"description": "Make time (t) variable available in the function expression."}>>> = true
expression<<<{"description": "function expression"}>>> = 'if(t>0,2,1)'
execute_on<<<{"description": "The list of flag(s) indicating when this object should be executed. For a description of each flag, see https://mooseframework.inl.gov/source/interfaces/SetupInterface.html."}>>> = 'initial timestep_end'
[]
[error]
type = ParsedPostprocessor<<<{"description": "Computes a parsed expression with post-processors", "href": "../../../source/postprocessors/ParsedPostprocessor.html"}>>>
expression<<<{"description": "function expression"}>>> = '(bison_internalVolume-analytical_internalVolume)/analytical_internalVolume*100'
pp_names<<<{"description": "Post-processors arguments"}>>> = 'bison_internalVolume analytical_internalVolume'
execute_on<<<{"description": "The list of flag(s) indicating when this object should be executed. For a description of each flag, see https://mooseframework.inl.gov/source/interfaces/SetupInterface.html."}>>> = 'initial timestep_end'
[]
[volStrain0]
type = ElementalVariableValue<<<{"description": "Outputs an elemental variable value at a particular location", "href": "../../../source/postprocessors/ElementalVariableValue.html"}>>>
elementid<<<{"description": "The ID of the element where we monitor"}>>> = 0
variable<<<{"description": "The variable to be monitored"}>>> = volumetric_strain
[]
[volStrain1]
type = ElementalVariableValue<<<{"description": "Outputs an elemental variable value at a particular location", "href": "../../../source/postprocessors/ElementalVariableValue.html"}>>>
elementid<<<{"description": "The ID of the element where we monitor"}>>> = 1
variable<<<{"description": "The variable to be monitored"}>>> = volumetric_strain
[]
[]
[Outputs<<<{"href": "../../../syntax/Outputs/index.html"}>>>]
csv<<<{"description": "Output the scalar variable and postprocessors to a *.csv file using the default CSV output."}>>> = true
[](assessment/verification/Other/internal_volume/rz.i)