Porous Flow Tutorial Page 06. Adding a tracer
On this Page we will depart from PorousFlowBasicTHM and use PorousFlowFullySaturated. This action employs mass lumping but no numerical stabilization by default. Therefore, the results will be slightly different than those achieved by PorousFlowBasicTHM
(no lumping or stabilization) and from the remainder of PorousFlow (mass lumping and either full upwinding or TVD stabilization).
The reason for using PorousFlowFullySaturated
is that it allows multi-component physics to be studied. Denoting the mass fraction by (where ), the fluid equations are (1) In this equation the fluid density, , is bracketed, because the user has the option of including it or not using the multiply_by_density
flag. The advantage of setting multiply_by_density = false
is that the equations become more linear, but it means that care must be taken when using other parts of PorousFlow. For instance, the PorousFlowMass
Postprocessor is measuring fluid mass, not fluid volume.
Tracers may now be incorporated into the simulation. A tracer_concentration
variable is defined, and set to initial conditions where it is 0.5 at the injection area, and zero elsewhere. Modifying the isothermal simulation of Page 01, PorousFlowFullySaturated
is provided with its name:
[Variables]
[./porepressure]
[../]
[./tracer_concentration]
[../]
[]
[ICs]
[./tracer_concentration]
type = FunctionIC
function = '0.5*if(x*x+y*y<1.01,1,0)'
variable = tracer_concentration
[../]
[]
[PorousFlowFullySaturated]
porepressure = porepressure
coupling_type = Hydro
gravity = '0 0 0'
fp = the_simple_fluid
mass_fraction_vars = tracer_concentration
[]
(modules/porous_flow/examples/tutorial/06.i)/opt/civet/build_0/moose/modules/porous_flow/examples/tutorial/06.i
# Darcy flow with a tracer
[Mesh]
[annular]
type = AnnularMeshGenerator
nr = 10
rmin = 1.0
rmax = 10
growth_r = 1.4
nt = 4
dmin = 0
dmax = 90
[]
[./make3D]
type = MeshExtruderGenerator
extrusion_vector = '0 0 12'
num_layers = 3
bottom_sideset = 'bottom'
top_sideset = 'top'
input = annular
[../]
[./shift_down]
type = TransformGenerator
transform = TRANSLATE
vector_value = '0 0 -6'
input = make3D
[../]
[./aquifer]
type = SubdomainBoundingBoxGenerator
block_id = 1
bottom_left = '0 0 -2'
top_right = '10 10 2'
input = shift_down
[../]
[./injection_area]
type = ParsedGenerateSideset
combinatorial_geometry = 'x*x+y*y<1.01'
included_subdomain_ids = 1
new_sideset_name = 'injection_area'
input = 'aquifer'
[../]
[./rename]
type = RenameBlockGenerator
old_block_id = '0 1'
new_block_name = 'caps aquifer'
input = 'injection_area'
[../]
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[./porepressure]
[../]
[./tracer_concentration]
[../]
[]
[ICs]
[./tracer_concentration]
type = FunctionIC
function = '0.5*if(x*x+y*y<1.01,1,0)'
variable = tracer_concentration
[../]
[]
[PorousFlowFullySaturated]
porepressure = porepressure
coupling_type = Hydro
gravity = '0 0 0'
fp = the_simple_fluid
mass_fraction_vars = tracer_concentration
[]
[BCs]
[./constant_injection_porepressure]
type = DirichletBC
variable = porepressure
value = 1E6
boundary = injection_area
[../]
[./constant_outer_porepressure]
type = DirichletBC
variable = porepressure
value = 0
boundary = rmax
[../]
[./injected_tracer]
type = DirichletBC
variable = tracer_concentration
value = 0.5
boundary = injection_area
[../]
[]
[Modules]
[./FluidProperties]
[./the_simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 2E9
viscosity = 1.0E-3
density0 = 1000.0
[../]
[../]
[]
[Materials]
[./porosity]
type = PorousFlowPorosity
porosity_zero = 0.1
[../]
[./permeability_aquifer]
type = PorousFlowPermeabilityConst
block = aquifer
permeability = '1E-14 0 0 0 1E-14 0 0 0 1E-14'
[../]
[./permeability_caps]
type = PorousFlowPermeabilityConst
block = caps
permeability = '1E-15 0 0 0 1E-15 0 0 0 1E-16'
[../]
[]
[Preconditioning]
active = basic
[./basic]
type = SMP
full = true
petsc_options = '-ksp_diagonal_scale -ksp_diagonal_scale_fix'
petsc_options_iname = '-pc_type -sub_pc_type -sub_pc_factor_shift_type -pc_asm_overlap'
petsc_options_value = ' asm lu NONZERO 2'
[../]
[./preferred_but_might_not_be_installed]
type = SMP
full = true
petsc_options_iname = '-pc_type -pc_factor_mat_solver_package'
petsc_options_value = ' lu mumps'
[../]
[]
[Executioner]
type = Transient
solve_type = Newton
end_time = 1E6
dt = 1E5
nl_rel_tol = 1E-14
[]
[Outputs]
exodus = true
[]
To encourage flow, rather than a rapid convergence to a more-or-less steady-state situation, the outer boundary is fixed to . The tracer concentration is fixed to 0.5 at the injection area.
[BCs]
[./constant_injection_porepressure]
type = DirichletBC
variable = porepressure
value = 1E6
boundary = injection_area
[../]
[./constant_outer_porepressure]
type = DirichletBC
variable = porepressure
value = 0
boundary = rmax
[../]
[./injected_tracer]
type = DirichletBC
variable = tracer_concentration
value = 0.5
boundary = injection_area
[../]
[]
(modules/porous_flow/examples/tutorial/06.i)/opt/civet/build_0/moose/modules/porous_flow/examples/tutorial/06.i
# Darcy flow with a tracer
[Mesh]
[annular]
type = AnnularMeshGenerator
nr = 10
rmin = 1.0
rmax = 10
growth_r = 1.4
nt = 4
dmin = 0
dmax = 90
[]
[./make3D]
type = MeshExtruderGenerator
extrusion_vector = '0 0 12'
num_layers = 3
bottom_sideset = 'bottom'
top_sideset = 'top'
input = annular
[../]
[./shift_down]
type = TransformGenerator
transform = TRANSLATE
vector_value = '0 0 -6'
input = make3D
[../]
[./aquifer]
type = SubdomainBoundingBoxGenerator
block_id = 1
bottom_left = '0 0 -2'
top_right = '10 10 2'
input = shift_down
[../]
[./injection_area]
type = ParsedGenerateSideset
combinatorial_geometry = 'x*x+y*y<1.01'
included_subdomain_ids = 1
new_sideset_name = 'injection_area'
input = 'aquifer'
[../]
[./rename]
type = RenameBlockGenerator
old_block_id = '0 1'
new_block_name = 'caps aquifer'
input = 'injection_area'
[../]
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[./porepressure]
[../]
[./tracer_concentration]
[../]
[]
[ICs]
[./tracer_concentration]
type = FunctionIC
function = '0.5*if(x*x+y*y<1.01,1,0)'
variable = tracer_concentration
[../]
[]
[PorousFlowFullySaturated]
porepressure = porepressure
coupling_type = Hydro
gravity = '0 0 0'
fp = the_simple_fluid
mass_fraction_vars = tracer_concentration
[]
[BCs]
[./constant_injection_porepressure]
type = DirichletBC
variable = porepressure
value = 1E6
boundary = injection_area
[../]
[./constant_outer_porepressure]
type = DirichletBC
variable = porepressure
value = 0
boundary = rmax
[../]
[./injected_tracer]
type = DirichletBC
variable = tracer_concentration
value = 0.5
boundary = injection_area
[../]
[]
[Modules]
[./FluidProperties]
[./the_simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 2E9
viscosity = 1.0E-3
density0 = 1000.0
[../]
[../]
[]
[Materials]
[./porosity]
type = PorousFlowPorosity
porosity_zero = 0.1
[../]
[./permeability_aquifer]
type = PorousFlowPermeabilityConst
block = aquifer
permeability = '1E-14 0 0 0 1E-14 0 0 0 1E-14'
[../]
[./permeability_caps]
type = PorousFlowPermeabilityConst
block = caps
permeability = '1E-15 0 0 0 1E-15 0 0 0 1E-16'
[../]
[]
[Preconditioning]
active = basic
[./basic]
type = SMP
full = true
petsc_options = '-ksp_diagonal_scale -ksp_diagonal_scale_fix'
petsc_options_iname = '-pc_type -sub_pc_type -sub_pc_factor_shift_type -pc_asm_overlap'
petsc_options_value = ' asm lu NONZERO 2'
[../]
[./preferred_but_might_not_be_installed]
type = SMP
full = true
petsc_options_iname = '-pc_type -pc_factor_mat_solver_package'
petsc_options_value = ' lu mumps'
[../]
[]
[Executioner]
type = Transient
solve_type = Newton
end_time = 1E6
dt = 1E5
nl_rel_tol = 1E-14
[]
[Outputs]
exodus = true
[]
The only other changes are that the PorousFlowConstantBiotModulus
Material
is now not needed, and that now a nodal porosity is needed in addition to the one evaluated at the quadpoints, since Eq. (1) is lumped to the nodes:
[Materials]
[./porosity]
type = PorousFlowPorosity
porosity_zero = 0.1
[../]
(modules/porous_flow/examples/tutorial/06.i)/opt/civet/build_0/moose/modules/porous_flow/examples/tutorial/06.i
# Darcy flow with a tracer
[Mesh]
[annular]
type = AnnularMeshGenerator
nr = 10
rmin = 1.0
rmax = 10
growth_r = 1.4
nt = 4
dmin = 0
dmax = 90
[]
[./make3D]
type = MeshExtruderGenerator
extrusion_vector = '0 0 12'
num_layers = 3
bottom_sideset = 'bottom'
top_sideset = 'top'
input = annular
[../]
[./shift_down]
type = TransformGenerator
transform = TRANSLATE
vector_value = '0 0 -6'
input = make3D
[../]
[./aquifer]
type = SubdomainBoundingBoxGenerator
block_id = 1
bottom_left = '0 0 -2'
top_right = '10 10 2'
input = shift_down
[../]
[./injection_area]
type = ParsedGenerateSideset
combinatorial_geometry = 'x*x+y*y<1.01'
included_subdomain_ids = 1
new_sideset_name = 'injection_area'
input = 'aquifer'
[../]
[./rename]
type = RenameBlockGenerator
old_block_id = '0 1'
new_block_name = 'caps aquifer'
input = 'injection_area'
[../]
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[./porepressure]
[../]
[./tracer_concentration]
[../]
[]
[ICs]
[./tracer_concentration]
type = FunctionIC
function = '0.5*if(x*x+y*y<1.01,1,0)'
variable = tracer_concentration
[../]
[]
[PorousFlowFullySaturated]
porepressure = porepressure
coupling_type = Hydro
gravity = '0 0 0'
fp = the_simple_fluid
mass_fraction_vars = tracer_concentration
[]
[BCs]
[./constant_injection_porepressure]
type = DirichletBC
variable = porepressure
value = 1E6
boundary = injection_area
[../]
[./constant_outer_porepressure]
type = DirichletBC
variable = porepressure
value = 0
boundary = rmax
[../]
[./injected_tracer]
type = DirichletBC
variable = tracer_concentration
value = 0.5
boundary = injection_area
[../]
[]
[Modules]
[./FluidProperties]
[./the_simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 2E9
viscosity = 1.0E-3
density0 = 1000.0
[../]
[../]
[]
[Materials]
[./porosity]
type = PorousFlowPorosity
porosity_zero = 0.1
[../]
[./permeability_aquifer]
type = PorousFlowPermeabilityConst
block = aquifer
permeability = '1E-14 0 0 0 1E-14 0 0 0 1E-14'
[../]
[./permeability_caps]
type = PorousFlowPermeabilityConst
block = caps
permeability = '1E-15 0 0 0 1E-15 0 0 0 1E-16'
[../]
[]
[Preconditioning]
active = basic
[./basic]
type = SMP
full = true
petsc_options = '-ksp_diagonal_scale -ksp_diagonal_scale_fix'
petsc_options_iname = '-pc_type -sub_pc_type -sub_pc_factor_shift_type -pc_asm_overlap'
petsc_options_value = ' asm lu NONZERO 2'
[../]
[./preferred_but_might_not_be_installed]
type = SMP
full = true
petsc_options_iname = '-pc_type -pc_factor_mat_solver_package'
petsc_options_value = ' lu mumps'
[../]
[]
[Executioner]
type = Transient
solve_type = Newton
end_time = 1E6
dt = 1E5
nl_rel_tol = 1E-14
[]
[Outputs]
exodus = true
[]
If multiply_by_density = true
then the arguments in Page 02 concerning the magnitude of the residual, and hence the size of the nonlinear absolute-tolerance must be modified. Specifically, the fluid residuals now get multiplied by the density (which is the default and most common use-case in PorousFlow). So in this problem, the fluid residual is approximately (since the fluid density is approximately 1000kg.m). The nl_abs_tol
is therefore
[Executioner]
type = Transient
solve_type = Newton
end_time = 1E6
dt = 1E5
nl_rel_tol = 1E-14
[]
(modules/porous_flow/examples/tutorial/06.i)/opt/civet/build_0/moose/modules/porous_flow/examples/tutorial/06.i
# Darcy flow with a tracer
[Mesh]
[annular]
type = AnnularMeshGenerator
nr = 10
rmin = 1.0
rmax = 10
growth_r = 1.4
nt = 4
dmin = 0
dmax = 90
[]
[./make3D]
type = MeshExtruderGenerator
extrusion_vector = '0 0 12'
num_layers = 3
bottom_sideset = 'bottom'
top_sideset = 'top'
input = annular
[../]
[./shift_down]
type = TransformGenerator
transform = TRANSLATE
vector_value = '0 0 -6'
input = make3D
[../]
[./aquifer]
type = SubdomainBoundingBoxGenerator
block_id = 1
bottom_left = '0 0 -2'
top_right = '10 10 2'
input = shift_down
[../]
[./injection_area]
type = ParsedGenerateSideset
combinatorial_geometry = 'x*x+y*y<1.01'
included_subdomain_ids = 1
new_sideset_name = 'injection_area'
input = 'aquifer'
[../]
[./rename]
type = RenameBlockGenerator
old_block_id = '0 1'
new_block_name = 'caps aquifer'
input = 'injection_area'
[../]
[]
[GlobalParams]
PorousFlowDictator = dictator
[]
[Variables]
[./porepressure]
[../]
[./tracer_concentration]
[../]
[]
[ICs]
[./tracer_concentration]
type = FunctionIC
function = '0.5*if(x*x+y*y<1.01,1,0)'
variable = tracer_concentration
[../]
[]
[PorousFlowFullySaturated]
porepressure = porepressure
coupling_type = Hydro
gravity = '0 0 0'
fp = the_simple_fluid
mass_fraction_vars = tracer_concentration
[]
[BCs]
[./constant_injection_porepressure]
type = DirichletBC
variable = porepressure
value = 1E6
boundary = injection_area
[../]
[./constant_outer_porepressure]
type = DirichletBC
variable = porepressure
value = 0
boundary = rmax
[../]
[./injected_tracer]
type = DirichletBC
variable = tracer_concentration
value = 0.5
boundary = injection_area
[../]
[]
[Modules]
[./FluidProperties]
[./the_simple_fluid]
type = SimpleFluidProperties
bulk_modulus = 2E9
viscosity = 1.0E-3
density0 = 1000.0
[../]
[../]
[]
[Materials]
[./porosity]
type = PorousFlowPorosity
porosity_zero = 0.1
[../]
[./permeability_aquifer]
type = PorousFlowPermeabilityConst
block = aquifer
permeability = '1E-14 0 0 0 1E-14 0 0 0 1E-14'
[../]
[./permeability_caps]
type = PorousFlowPermeabilityConst
block = caps
permeability = '1E-15 0 0 0 1E-15 0 0 0 1E-16'
[../]
[]
[Preconditioning]
active = basic
[./basic]
type = SMP
full = true
petsc_options = '-ksp_diagonal_scale -ksp_diagonal_scale_fix'
petsc_options_iname = '-pc_type -sub_pc_type -sub_pc_factor_shift_type -pc_asm_overlap'
petsc_options_value = ' asm lu NONZERO 2'
[../]
[./preferred_but_might_not_be_installed]
type = SMP
full = true
petsc_options_iname = '-pc_type -pc_factor_mat_solver_package'
petsc_options_value = ' lu mumps'
[../]
[]
[Executioner]
type = Transient
solve_type = Newton
end_time = 1E6
dt = 1E5
nl_rel_tol = 1E-14
[]
[Outputs]
exodus = true
[]
An animation of the results is shown in Figure 1.

Figure 1: Darcy flow vectors and tracer evolution in the borehole-aquifer-caprock system.
As you gain experience with PorousFlow, you will realise that this simulation contains several defects.