Mass computation and conservation
The total fluid mass of species within a volume is (1) It must be checked that MOOSE calculates this correctly, using the PorousFlowFluidMass postprocessor, in order that mass-balances be correct, and also because this quantity is used in a number of other tests.
Single-phase, single-component fluid
A 1D model with , and with three elements of size 1 is created with the following properties:
Parameter | Value |
---|---|
Constant fluid bulk modulus | Pa |
Fluid density at zero pressure | kg.m |
Van Genuchten | 0.5 |
Van Genuchten | Pa |
Porosity | 0.1 |
The porepressure is set at .
# checking that the mass postprocessor correctly calculates the mass
# 1phase, 1component, constant porosity
[Mesh]
type = GeneratedMesh
dim = 1
nx = 3
xmin = -1
xmax = 1
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[pp]
[]
[]
[ICs]
[pinit]
type = FunctionIC
function = x
variable = pp
[]
[]
[Kernels]
[mass0]
type = PorousFlowMassTimeDerivative
fluid_component = 0
variable = pp
[]
[]
[UserObjects]
[dictator]
type = PorousFlowDictator
porous_flow_vars = 'pp'
number_fluid_phases = 1
number_fluid_components = 1
[]
[pc]
type = PorousFlowCapillaryPressureVG
m = 0.5
alpha = 1
[]
[]
[FluidProperties]
[simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 1
density0 = 1
thermal_expansion = 0
[]
[]
[Materials]
[temperature]
type = PorousFlowTemperature
[]
[ppss]
type = PorousFlow1PhaseP
porepressure = pp
capillary_pressure = pc
[]
[massfrac]
type = PorousFlowMassFraction
[]
[simple_fluid]
type = PorousFlowSingleComponentFluid
fp = simple_fluid
phase = 0
[]
[porosity]
type = PorousFlowPorosityConst
porosity = 0.1
[]
[]
[Postprocessors]
[total_mass]
type = PorousFlowFluidMass
[]
[]
[Preconditioning]
[andy]
type = SMP
full = true
petsc_options_iname = '-ksp_type -pc_type -snes_atol -snes_rtol -snes_max_it'
petsc_options_value = 'bcgs bjacobi 1 1 10000'
[]
[]
[Executioner]
type = Transient
solve_type = Newton
dt = 1
end_time = 1
[]
[Outputs]
execute_on = 'timestep_end'
file_base = mass01
csv = true
[]
(modules/porous_flow/test/tests/mass_conservation/mass01.i)Recall that in PorousFlow, mass is lumped to the nodes. Therefore, the integral above is evaluated at the nodes, and a sum of the results is outputted as the PorousFlowFluidMass postprocessor. Using the properties given above, this yields:
Density | Saturation | Nodal mass | ||
---|---|---|---|---|
-1 | -1 | 0.367879441 | 0.707106781 | 0.008671002 |
-0.333333333 | -0.333333333 | 0.716531311 | 0.948683298 | 0.02265871 |
-0.333333333 | -0.333333333 | 0.716531311 | 0.948683298 | 0.02265871 |
0.333333333 | 0.333333333 | 1.395612425 | 1 | 0.046520414 |
0.333333333 | 0.333333333 | 1.395612425 | 1 | 0.046520414 |
1 | 1 | 2.718281828 | 1 | 0.090609394 |
- | - | - | Total | 0.237638643 |
MOOSE also gives the total mass as 0.237638643\,kg.
Single-phase, two-components
This is similar to the previous section, but has two fluid components. The mass fraction is fixed at
# checking that the mass postprocessor correctly calculates the mass
# 1phase, 2component, constant porosity
[Mesh]
type = GeneratedMesh
dim = 1
nx = 3
xmin = -1
xmax = 1
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[pp]
[]
[mass_frac_comp0]
[]
[]
[ICs]
[pinit]
type = FunctionIC
function = x
variable = pp
[]
[minit]
type = FunctionIC
function = 'x*x'
variable = mass_frac_comp0
[]
[]
[Kernels]
[mass0]
type = PorousFlowMassTimeDerivative
fluid_component = 0
variable = pp
[]
[mass1]
type = PorousFlowMassTimeDerivative
fluid_component = 1
variable = mass_frac_comp0
[]
[]
[UserObjects]
[dictator]
type = PorousFlowDictator
porous_flow_vars = 'pp mass_frac_comp0'
number_fluid_phases = 1
number_fluid_components = 2
[]
[pc]
type = PorousFlowCapillaryPressureVG
m = 0.5
alpha = 1
[]
[]
[FluidProperties]
[simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 1
density0 = 1
thermal_expansion = 0
[]
[]
[Materials]
[temperature]
type = PorousFlowTemperature
[]
[ppss]
type = PorousFlow1PhaseP
porepressure = pp
capillary_pressure = pc
[]
[massfrac]
type = PorousFlowMassFraction
mass_fraction_vars = 'mass_frac_comp0'
[]
[simple_fluid]
type = PorousFlowSingleComponentFluid
fp = simple_fluid
phase = 0
[]
[porosity]
type = PorousFlowPorosityConst
porosity = 0.1
[]
[]
[Postprocessors]
[total_mass_0]
type = PorousFlowFluidMass
[]
[total_mass_1]
type = PorousFlowFluidMass
fluid_component = 1
[]
[]
[Preconditioning]
[andy]
type = SMP
full = true
petsc_options_iname = '-ksp_type -pc_type -snes_atol -snes_rtol -snes_max_it'
petsc_options_value = 'bcgs bjacobi 1 1 10000'
[]
[]
[Executioner]
type = Transient
solve_type = Newton
dt = 1
end_time = 1
[]
[Outputs]
execute_on = 'timestep_end'
file_base = mass02
csv = true
[]
(modules/porous_flow/test/tests/mass_conservation/mass02.i)Density | Saturation | Nodal mass | Nodal mass | |||
---|---|---|---|---|---|---|
-1 | -1 | 0.367879441 | 0.707106781 | 1 | 0.008671 | 0 |
-0.333333333 | -0.333333333 | 0.716531311 | 0.948683298 | 0.111111 | 0.00251763 | 0.02014108 |
-0.333333333 | -0.333333333 | 0.716531311 | 0.948683298 | 0.111111 | 0.00251763 | 0.02014108 |
0.333333333 | 0.333333333 | 1.395612425 | 1 | 0.111111 | 0.00516893 | 0.04135148 |
0.333333333 | 0.333333333 | 1.395612425 | 1 | 0.111111 | 0.00516893 | 0.04135148 |
1 | 1 | 2.718281828 | 1 | 1 | 0.09060939 | 0 |
- | - | - | - | Total | 0.11465353 | 0.12298511 |
MOOSE produces the expected answer.
Two-phase, two-components
A 1D model with two elements from is created, with two phases (0 and 1), and two fluid components (0 and 1). The phase densities are calculated using a constant bulk modulus fluid with bulk modulus of 1 Pa. The density at zero pressure is 1 kg.m for phase 0, and 0.1 kg.m for phase 1. The porepressure of phase 0 is held fixed at 1 Pa, and a constant capillary pressure of 0 is specified so that the pressure of phase 1 is also 1 Pa. This results in phase densities of kg.m for phase 0, and kg.m for phase 1.
Saturation of phase 1 varies linearly as , while porosity is 0.1 throughout. The mass fraction of species 0 in fluid phase 0 is specified as 0.3, while the mass fraction of species 0 in phase 1 is 0.55.
# Checking that the mass postprocessor correctly calculates the mass
# of each component in each phase, as well as the total mass of each
# component in all phases.
# 2phase, 2component, constant porosity
[Mesh]
type = GeneratedMesh
dim = 1
nx = 2
xmin = 0
xmax = 1
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[pp]
[]
[sat]
[]
[]
[AuxVariables]
[massfrac_ph0_sp0]
initial_condition = 0.3
[]
[massfrac_ph1_sp0]
initial_condition = 0.55
[]
[]
[ICs]
[pinit]
type = ConstantIC
value = 1
variable = pp
[]
[satinit]
type = FunctionIC
function = 1-x
variable = sat
[]
[]
[Kernels]
[mass0]
type = PorousFlowMassTimeDerivative
fluid_component = 0
variable = pp
[]
[mass1]
type = PorousFlowMassTimeDerivative
fluid_component = 1
variable = sat
[]
[]
[UserObjects]
[dictator]
type = PorousFlowDictator
porous_flow_vars = 'pp sat'
number_fluid_phases = 2
number_fluid_components = 2
[]
[pc]
type = PorousFlowCapillaryPressureConst
pc = 0
[]
[]
[FluidProperties]
[simple_fluid0]
type = SimpleFluidProperties
bulk_modulus = 1
density0 = 1
thermal_expansion = 0
[]
[simple_fluid1]
type = SimpleFluidProperties
bulk_modulus = 1
density0 = 0.1
thermal_expansion = 0
[]
[]
[Materials]
[temperature]
type = PorousFlowTemperature
[]
[ppss]
type = PorousFlow2PhasePS
phase0_porepressure = pp
phase1_saturation = sat
capillary_pressure = pc
[]
[massfrac]
type = PorousFlowMassFraction
mass_fraction_vars = 'massfrac_ph0_sp0 massfrac_ph1_sp0'
[]
[simple_fluid0]
type = PorousFlowSingleComponentFluid
fp = simple_fluid0
phase = 0
[]
[simple_fluid1]
type = PorousFlowSingleComponentFluid
fp = simple_fluid1
phase = 1
[]
[porosity]
type = PorousFlowPorosityConst
porosity = 0.1
[]
[]
[Postprocessors]
[comp0_phase0_mass]
type = PorousFlowFluidMass
fluid_component = 0
phase = 0
[]
[comp0_phase1_mass]
type = PorousFlowFluidMass
fluid_component = 0
phase = 1
[]
[comp0_total_mass]
type = PorousFlowFluidMass
fluid_component = 0
[]
[comp0_total_mass2]
type = PorousFlowFluidMass
fluid_component = 0
phase = '0 1'
[]
[comp1_phase0_mass]
type = PorousFlowFluidMass
fluid_component = 1
phase = 0
[]
[comp1_phase1_mass]
type = PorousFlowFluidMass
fluid_component = 1
phase = 1
[]
[comp1_total_mass]
type = PorousFlowFluidMass
fluid_component = 1
[]
[comp1_total_mass2]
type = PorousFlowFluidMass
fluid_component = 1
phase = '0 1'
[]
[]
[Executioner]
type = Transient
solve_type = Newton
nl_abs_tol = 1e-16
dt = 1
end_time = 1
[]
[Outputs]
execute_on = 'timestep_end'
file_base = mass05
csv = true
[]
(modules/porous_flow/test/tests/mass_conservation/mass05.i)It is simple to calculate the total mass of each component in each phase using Eq. (1), the results of which are
Species | Phase | Total mass Eq. (1) | Total mass (MOOSE) |
---|---|---|---|
0 | 0 | 0.04077423 | 0.04077423 |
0 | 1 | 0.007475275 | 0.007475275 |
0 | all | 0.04824950 | 0.04824950 |
1 | 0 | 0.09513986 | 0.09513986 |
1 | 1 | 0.006116134 | 0.006116134 |
1 | all | 0.10125560 | 0.1012560 |
Constant fluid source
A fluid source of kg.m.s is introduced into a single element, and the PorousFlowFluidMass postprocessor is used to record the fluid mass as a function of time:
# checking that the mass postprocessor correctly calculates the mass
# 1phase, 1component, constant porosity, with a constant fluid source
[Mesh]
type = GeneratedMesh
dim = 3
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[pp]
initial_condition = -0.5
[]
[]
[Kernels]
[mass0]
type = PorousFlowMassTimeDerivative
fluid_component = 0
variable = pp
[]
[source]
type = BodyForce
variable = pp
value = 0.1 # kg/m^3/s
[]
[]
[UserObjects]
[dictator]
type = PorousFlowDictator
porous_flow_vars = 'pp'
number_fluid_phases = 1
number_fluid_components = 1
[]
[pc]
type = PorousFlowCapillaryPressureVG
m = 0.5
alpha = 1
[]
[]
[FluidProperties]
[simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 1
density0 = 1
thermal_expansion = 0
[]
[]
[Materials]
[temperature]
type = PorousFlowTemperature
[]
[ppss]
type = PorousFlow1PhaseP
porepressure = pp
capillary_pressure = pc
[]
[massfrac]
type = PorousFlowMassFraction
[]
[simple_fluid]
type = PorousFlowSingleComponentFluid
fp = simple_fluid
phase = 0
[]
[porosity]
type = PorousFlowPorosityConst
porosity = 0.1
[]
[]
[Postprocessors]
[porepressure]
type = PointValue
point = '0 0 0'
variable = pp
execute_on = 'initial timestep_end'
[]
[total_mass]
type = PorousFlowFluidMass
execute_on = 'initial timestep_end'
[]
[]
[Preconditioning]
[andy]
type = SMP
full = true
petsc_options_iname = '-ksp_type -pc_type -snes_atol -snes_rtol -snes_max_it'
petsc_options_value = 'gmres bjacobi 1E-12 1E-20 10000'
[]
[]
[Executioner]
type = Transient
solve_type = Newton
dt = 1
end_time = 10
[]
[Outputs]
execute_on = 'initial timestep_end'
file_base = mass03
csv = true
[]
(modules/porous_flow/test/tests/mass_conservation/mass03.i)Mass conservation in a deforming material
A single unit element, with roller BCs on its sides and bottom, is compressed at a uniform rate: Here is the vertical displacement and is time. There is no fluid flow and the material's boundaries are impermeable. Fluid mass conservation is checked.
# The sample is a single unit element, with roller BCs on the sides
# and bottom. A constant displacement is applied to the top: disp_z = -0.01*t.
# There is no fluid flow.
# Fluid mass conservation is checked.
#
# Under these conditions
# porepressure = porepressure(t=0) - (Fluid bulk modulus)*log(1 - 0.01*t)
# stress_xx = (bulk - 2*shear/3)*disp_z/L (remember this is effective stress)
# stress_zz = (bulk + 4*shear/3)*disp_z/L (remember this is effective stress)
# where L is the height of the sample (L=1 in this test)
#
# Parameters:
# Bulk modulus = 2
# Shear modulus = 1.5
# fluid bulk modulus = 0.5
# initial porepressure = 0.1
#
# Desired output:
# zdisp = -0.01*t
# p0 = 0.1 - 0.5*log(1-0.01*t)
# stress_xx = stress_yy = -0.01*t
# stress_zz = -0.04*t
#
# Regarding the "log" - it comes from preserving fluid mass
[Mesh]
type = GeneratedMesh
dim = 3
nx = 1
ny = 1
nz = 1
xmin = -0.5
xmax = 0.5
ymin = -0.5
ymax = 0.5
zmin = -0.5
zmax = 0.5
[]
[GlobalParams]
displacements = 'disp_x disp_y disp_z'
PorousFlowDictator = dictator
block = 0
[]
[Variables]
[disp_x]
[]
[disp_y]
[]
[disp_z]
[]
[porepressure]
initial_condition = 0.1
[]
[]
[BCs]
[confinex]
type = DirichletBC
variable = disp_x
value = 0
boundary = 'left right'
[]
[confiney]
type = DirichletBC
variable = disp_y
value = 0
boundary = 'bottom top'
[]
[basefixed]
type = DirichletBC
variable = disp_z
value = 0
boundary = back
[]
[top_velocity]
type = FunctionDirichletBC
variable = disp_z
function = -0.01*t
boundary = front
[]
[]
[Kernels]
[grad_stress_x]
type = StressDivergenceTensors
variable = disp_x
component = 0
[]
[grad_stress_y]
type = StressDivergenceTensors
variable = disp_y
component = 1
[]
[grad_stress_z]
type = StressDivergenceTensors
variable = disp_z
component = 2
[]
[poro_x]
type = PorousFlowEffectiveStressCoupling
biot_coefficient = 0.3
variable = disp_x
component = 0
[]
[poro_y]
type = PorousFlowEffectiveStressCoupling
biot_coefficient = 0.3
variable = disp_y
component = 1
[]
[poro_z]
type = PorousFlowEffectiveStressCoupling
biot_coefficient = 0.3
component = 2
variable = disp_z
[]
[poro_vol_exp]
type = PorousFlowMassVolumetricExpansion
variable = porepressure
fluid_component = 0
[]
[mass0]
type = PorousFlowMassTimeDerivative
fluid_component = 0
variable = porepressure
[]
[]
[AuxVariables]
[stress_xx]
order = CONSTANT
family = MONOMIAL
[]
[stress_xy]
order = CONSTANT
family = MONOMIAL
[]
[stress_xz]
order = CONSTANT
family = MONOMIAL
[]
[stress_yy]
order = CONSTANT
family = MONOMIAL
[]
[stress_yz]
order = CONSTANT
family = MONOMIAL
[]
[stress_zz]
order = CONSTANT
family = MONOMIAL
[]
[]
[AuxKernels]
[stress_xx]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_xx
index_i = 0
index_j = 0
[]
[stress_xy]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_xy
index_i = 0
index_j = 1
[]
[stress_xz]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_xz
index_i = 0
index_j = 2
[]
[stress_yy]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_yy
index_i = 1
index_j = 1
[]
[stress_yz]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_yz
index_i = 1
index_j = 2
[]
[stress_zz]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_zz
index_i = 2
index_j = 2
[]
[]
[FluidProperties]
[simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 0.5
density0 = 1
thermal_expansion = 0
viscosity = 1
[]
[]
[Materials]
[temperature]
type = PorousFlowTemperature
[]
[elasticity_tensor]
type = ComputeElasticityTensor
C_ijkl = '1 1.5'
# bulk modulus is lambda + 2*mu/3 = 1 + 2*1.5/3 = 2
fill_method = symmetric_isotropic
[]
[strain]
type = ComputeSmallStrain
[]
[stress]
type = ComputeLinearElasticStress
[]
[vol_strain]
type = PorousFlowVolumetricStrain
[]
[eff_fluid_pressure]
type = PorousFlowEffectiveFluidPressure
[]
[ppss]
type = PorousFlow1PhaseP
porepressure = porepressure
capillary_pressure = pc
[]
[massfrac]
type = PorousFlowMassFraction
[]
[simple_fluid]
type = PorousFlowSingleComponentFluid
fp = simple_fluid
phase = 0
[]
[porosity]
type = PorousFlowPorosityConst
porosity = 0.1
[]
[permeability]
type = PorousFlowPermeabilityConst
permeability = '0.5 0 0 0 0.5 0 0 0 0.5'
[]
[]
[UserObjects]
[dictator]
type = PorousFlowDictator
porous_flow_vars = 'porepressure disp_x disp_y disp_z'
number_fluid_phases = 1
number_fluid_components = 1
[]
[pc]
type = PorousFlowCapillaryPressureVG
m = 0.5
alpha = 1
[]
[]
[Postprocessors]
[p0]
type = PointValue
outputs = 'console csv'
execute_on = 'initial timestep_end'
point = '0 0 0'
variable = porepressure
[]
[zdisp]
type = PointValue
outputs = csv
point = '0 0 0.5'
use_displaced_mesh = false
variable = disp_z
[]
[stress_xx]
type = PointValue
outputs = csv
point = '0 0 0'
variable = stress_xx
[]
[stress_yy]
type = PointValue
outputs = csv
point = '0 0 0'
variable = stress_yy
[]
[stress_zz]
type = PointValue
outputs = csv
point = '0 0 0'
variable = stress_zz
[]
[fluid_mass]
type = PorousFlowFluidMass
fluid_component = 0
execute_on = 'initial timestep_end'
outputs = 'console csv'
[]
[]
[Preconditioning]
[andy]
type = SMP
full = true
petsc_options_iname = '-ksp_type -pc_type -snes_atol -snes_rtol -snes_max_it'
petsc_options_value = 'bcgs bjacobi 1E-14 1E-8 10000'
[]
[]
[Executioner]
type = Transient
solve_type = Newton
start_time = 0
end_time = 10
dt = 2
[]
[Outputs]
execute_on = 'initial timestep_end'
file_base = mass04
[csv]
type = CSV
[]
[]
(modules/porous_flow/test/tests/mass_conservation/mass04.i)Note the use_displaced_mesh = true
option in the PorousFlowFluidMass postprocessor: it is necessary to correctly compute the mass.
Under these conditions Here is the fluid porepressure, which is at ; is the fluid bulk modulus; is the effective stress; is the drained bulk modulus of the material; is the shear modulus of the material; and is the height of the sample.
PorousFlow produces these results exactly, and, importantly, conserves fluid mass.
Similar tests are run in "RZ" coordinates.
Mass conservation in a deformable material with a source
A single unit element, with roller BCs on its sides and bottom, is injected with fluid at rate kg.s. Its top is free to move.
# The sample is a single unit element, with roller BCs on the sides and bottom.
# The top is free to move and fluid is injected at a constant rate of 1kg/s
# There is no fluid flow.
# Fluid mass conservation is checked.
# Under these conditions the fluid mass should increase at 1kg/s
# The porepressure should increase: rho0 * exp(P/bulk) = rho * exp(P0/bulk) + 1*t
# The stress_zz should be exactly biot * P since total stress is zero
[Mesh]
type = GeneratedMesh
dim = 3
nx = 1
ny = 1
nz = 1
xmin = -0.5
xmax = 0.5
ymin = -0.5
ymax = 0.5
zmin = -0.5
zmax = 0.5
[]
[GlobalParams]
displacements = 'disp_x disp_y disp_z'
PorousFlowDictator = dictator
block = 0
[]
[Variables]
[disp_x]
[]
[disp_y]
[]
[disp_z]
[]
[porepressure]
initial_condition = 0.1
[]
[]
[BCs]
[confinex]
type = DirichletBC
variable = disp_x
value = 0
boundary = 'left right'
[]
[confiney]
type = DirichletBC
variable = disp_y
value = 0
boundary = 'bottom top'
[]
[basefixed]
type = DirichletBC
variable = disp_z
value = 0
boundary = back
[]
[]
[Kernels]
[grad_stress_x]
type = StressDivergenceTensors
variable = disp_x
component = 0
[]
[grad_stress_y]
type = StressDivergenceTensors
variable = disp_y
component = 1
[]
[grad_stress_z]
type = StressDivergenceTensors
variable = disp_z
component = 2
[]
[poro_x]
type = PorousFlowEffectiveStressCoupling
biot_coefficient = 0.3
variable = disp_x
component = 0
[]
[poro_y]
type = PorousFlowEffectiveStressCoupling
biot_coefficient = 0.3
variable = disp_y
component = 1
[]
[poro_z]
type = PorousFlowEffectiveStressCoupling
biot_coefficient = 0.3
component = 2
variable = disp_z
[]
[poro_vol_exp]
type = PorousFlowMassVolumetricExpansion
variable = porepressure
fluid_component = 0
[]
[mass0]
type = PorousFlowMassTimeDerivative
fluid_component = 0
variable = porepressure
[]
[]
[DiracKernels]
[inject]
type = PorousFlowPointSourceFromPostprocessor
point = '0 0 0'
mass_flux = 1.0
variable = porepressure
[]
[]
[AuxVariables]
[stress_xx]
order = CONSTANT
family = MONOMIAL
[]
[stress_xy]
order = CONSTANT
family = MONOMIAL
[]
[stress_xz]
order = CONSTANT
family = MONOMIAL
[]
[stress_yy]
order = CONSTANT
family = MONOMIAL
[]
[stress_yz]
order = CONSTANT
family = MONOMIAL
[]
[stress_zz]
order = CONSTANT
family = MONOMIAL
[]
[]
[AuxKernels]
[stress_xx]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_xx
index_i = 0
index_j = 0
[]
[stress_xy]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_xy
index_i = 0
index_j = 1
[]
[stress_xz]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_xz
index_i = 0
index_j = 2
[]
[stress_yy]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_yy
index_i = 1
index_j = 1
[]
[stress_yz]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_yz
index_i = 1
index_j = 2
[]
[stress_zz]
type = RankTwoAux
rank_two_tensor = stress
variable = stress_zz
index_i = 2
index_j = 2
[]
[]
[FluidProperties]
[simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 0.5
density0 = 1
thermal_expansion = 0
viscosity = 1
[]
[]
[Materials]
[temperature]
type = PorousFlowTemperature
[]
[elasticity_tensor]
type = ComputeElasticityTensor
C_ijkl = '1 1.5'
# bulk modulus is lambda + 2*mu/3 = 1 + 2*1.5/3 = 2
fill_method = symmetric_isotropic
[]
[strain]
type = ComputeSmallStrain
[]
[stress]
type = ComputeLinearElasticStress
[]
[vol_strain]
type = PorousFlowVolumetricStrain
[]
[eff_fluid_pressure]
type = PorousFlowEffectiveFluidPressure
[]
[ppss]
type = PorousFlow1PhaseP
porepressure = porepressure
capillary_pressure = pc
[]
[massfrac]
type = PorousFlowMassFraction
[]
[simple_fluid]
type = PorousFlowSingleComponentFluid
fp = simple_fluid
phase = 0
[]
[porosity]
type = PorousFlowPorosityConst
porosity = 0.1
[]
[permeability]
type = PorousFlowPermeabilityConst
permeability = '0.5 0 0 0 0.5 0 0 0 0.5'
[]
[]
[UserObjects]
[dictator]
type = PorousFlowDictator
porous_flow_vars = 'porepressure disp_x disp_y disp_z'
number_fluid_phases = 1
number_fluid_components = 1
[]
[pc]
type = PorousFlowCapillaryPressureVG
m = 0.5
alpha = 1
[]
[]
[Postprocessors]
[p0]
type = PointValue
outputs = 'console csv'
execute_on = 'initial timestep_end'
point = '0 0 0'
variable = porepressure
[]
[zdisp]
type = PointValue
outputs = csv
point = '0 0 0.5'
use_displaced_mesh = false
variable = disp_z
[]
[stress_xx]
type = PointValue
outputs = csv
point = '0 0 0'
variable = stress_xx
[]
[stress_yy]
type = PointValue
outputs = csv
point = '0 0 0'
variable = stress_yy
[]
[stress_zz]
type = PointValue
outputs = csv
point = '0 0 0'
variable = stress_zz
[]
[fluid_mass]
type = PorousFlowFluidMass
fluid_component = 0
execute_on = 'initial timestep_end'
outputs = 'console csv'
[]
[]
[Preconditioning]
[andy]
type = SMP
full = true
petsc_options_iname = '-ksp_type -pc_type -snes_atol -snes_rtol -snes_max_it'
petsc_options_value = 'bcgs bjacobi 1E-14 1E-8 10000'
[]
[]
[Executioner]
type = Transient
solve_type = Newton
start_time = 0
end_time = 10
dt = 2
[]
[Outputs]
execute_on = 'initial timestep_end'
[csv]
type = CSV
[]
[]
(modules/porous_flow/test/tests/mass_conservation/mass11.i)Under these conditions the fluid mass should increase at rate , and the porepressure should increase accordingly. The total stress should be zero since the top is free to move, so the effective stress should be . MOOSE produces these results exactly.
Similar tests are run in "RZ" coordinates.
Mass computation with a saturation threshold in multi-component, multi-phase fluids
The PorousFlowFluidMass postprocessor may be used to compute the total mass of each component in each phase, as well as the total mass of each component in all phases. Furthermore, a saturation threshold may be set to only count the fluid above the threshold.
# Checking that the mass postprocessor correctly calculates the mass
# of each component in each phase, as well as the total mass of each
# component in all phases. Also tests that optional saturation threshold
# gives the correct mass
# 2phase, 2component, constant porosity
# saturation_threshold set to 0.6 for phase 1
[Mesh]
type = GeneratedMesh
dim = 1
nx = 10
xmin = 0
xmax = 1
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[pp]
[]
[sat]
[]
[]
[AuxVariables]
[massfrac_ph0_sp0]
initial_condition = 1
[]
[massfrac_ph1_sp0]
initial_condition = 0
[]
[]
[ICs]
[pinit]
type = ConstantIC
value = 1
variable = pp
[]
[satinit]
type = FunctionIC
function = 1-x
variable = sat
[]
[]
[Kernels]
[mass0]
type = PorousFlowMassTimeDerivative
fluid_component = 0
variable = pp
[]
[mass1]
type = PorousFlowMassTimeDerivative
fluid_component = 1
variable = sat
[]
[]
[UserObjects]
[dictator]
type = PorousFlowDictator
porous_flow_vars = 'pp sat'
number_fluid_phases = 2
number_fluid_components = 2
[]
[pc]
type = PorousFlowCapillaryPressureConst
pc = 0
[]
[]
[FluidProperties]
[simple_fluid0]
type = SimpleFluidProperties
bulk_modulus = 1
density0 = 1
thermal_expansion = 0
[]
[simple_fluid1]
type = SimpleFluidProperties
bulk_modulus = 1
density0 = 0.1
thermal_expansion = 0
[]
[]
[Materials]
[temperature]
type = PorousFlowTemperature
[]
[ppss]
type = PorousFlow2PhasePS
phase0_porepressure = pp
phase1_saturation = sat
capillary_pressure = pc
[]
[massfrac]
type = PorousFlowMassFraction
mass_fraction_vars = 'massfrac_ph0_sp0 massfrac_ph1_sp0'
[]
[simple_fluid0]
type = PorousFlowSingleComponentFluid
fp = simple_fluid0
phase = 0
[]
[simple_fluid1]
type = PorousFlowSingleComponentFluid
fp = simple_fluid1
phase = 1
[]
[porosity]
type = PorousFlowPorosityConst
porosity = 0.1
[]
[]
[Postprocessors]
[comp0_phase0_mass]
type = PorousFlowFluidMass
fluid_component = 0
phase = 0
[]
[comp0_phase1_mass]
type = PorousFlowFluidMass
fluid_component = 0
phase = 1
[]
[comp0_total_mass]
type = PorousFlowFluidMass
fluid_component = 0
[]
[comp1_phase0_mass]
type = PorousFlowFluidMass
fluid_component = 1
phase = 0
[]
[comp1_phase1_mass]
type = PorousFlowFluidMass
fluid_component = 1
phase = 1
[]
[comp1_total_mass]
type = PorousFlowFluidMass
fluid_component = 1
[]
[comp1_phase1_threshold_mass]
type = PorousFlowFluidMass
fluid_component = 1
phase = 1
saturation_threshold = 0.6
[]
[]
[Executioner]
type = Transient
solve_type = Newton
nl_abs_tol = 1e-16
dt = 1
end_time = 1
[]
[Outputs]
execute_on = 'timestep_end'
file_base = mass06
csv = true
[]
(modules/porous_flow/test/tests/mass_conservation/mass06.i)