Tutorial 5: Multiphase flow in the Egg model¶
Context
In this tutorial, we illustrate the concepts presented in Tutorial 4: Multiphase flow with wells using the three-dimensional Egg model. We show how to set up a water injection problem relying on a Dead-Oil thermodynamic model. The twelve wells (four producers and eight injectors) are placed according to the description of the original test case.
Objectives
In this tutorial, we re-use many GEOSX features already presented in Tutorial 4: Multiphase flow with wells, with a focus on:
- how to import an external mesh with embedded geological properties (permeability) in the GMSH format (
.msh
), - how to choose constitutive parameters matching those of the original test case,
- how to tune the time stepping strategy and the nonlinear solver parameters.
Input file
This tutorial is based on the XML file located at
src/coreComponents/physicsSolvers/fluidFlow/benchmarks/Egg/dead_oil_egg.xml
The mesh file corresponding to the Egg model is stored in the GEOSXDATA repository. Therefore, you must first download the GEOSXDATA repository in the same folder as the GEOSX repository to run this test case.
Note
GEOSXDATA is a separate repository in which we store large mesh files in order to keep the main GEOSX repository lightweight.
GEOSX input file¶
The XML file considered here follows the typical structure of the GEOSX input files:
Solvers¶
In this tutorial, we use the approach described in Tutorial 4: Multiphase flow with wells
to couple reservoir flow with wells.
That is, we define a coupling solver of type CompositionalMultiphaseReservoir
named coupledFlowAndWells
.
This coupling solver drives the simulation and is in charge of binding the following
single-physics solvers:
- the single-physics reservoir flow solver, a solver of type CompositionalMultiphaseFlow named
compositionalMultiphaseFlow
and documented at Compositional Multiphase Flow Solver, - the single-physics well solver, a solver of type CompositionalMultiphaseWell named
compositionalMultiphaseWell
and documented at Compositional Multiphase Well Solver.
The Solvers XML block is shown below.
The coupling solver points to the two single-physics solvers using the attributes
flowSolverName
and wellSolverName
.
We use the same names as in Tutorial 4: Multiphase flow with wells for simplicity, but
these names can be chosen by the user and are not imposed by GEOSX.
The flow solver is applied to the reservoir and the well solver is applied to the wells,
as specified by their respective targetRegions
attributes.
The solver information is specified in the NonlinearSolverParameters and LinearSolverParameters XML blocks. These blocks should be nested in the CompositionalMultiphaseReservoir XML block since the coupling solver drives the solution strategy. Note that any solver information specified in the single-physics XML blocks will not be taken into account.
Here, we instruct GEOSX to perform at least newtonMinIter = 1
Newton iterations and
at most newtonMaxIter = 10
. GEOSX will adjust the time step size as follows:
- if the Newton solver converges in
dtIncIterLimit x newtonMaxIter = 5
iterations or fewer, GEOSX will double the time step size for the next time step, - if the Newton solver converges in
dtCutIterLimit x newtonMaxIter = 8
iterations or more, GEOSX will reduce the time step size for the next time step by a factortimestepCutFactor = 0.1
, - if the Newton solver fails to converge in
newtonMaxIter = 10
, GEOSX will cut the time step size by a factortimestepCutFactor = 0.1
and restart from the previous converged time step.
The maximum number of time step cuts is specified by the attribute maxTimeStepCuts
.
Note that a backtracking line search can be activated by setting the attribute lineSearchAction
to 1 or 2.
If lineSearchAction = 1
, we accept the nonlinear iteration even if the line search does not reduce the residual norm.
If lineSearchAction = 1
, we cut the time step if the line search does not reduce the residual norm.
<Solvers>
<CompositionalMultiphaseReservoir
name="coupledFlowAndWells"
flowSolverName="compositionalMultiphaseFlow"
wellSolverName="compositionalMultiphaseWell"
logLevel="1"
initialDt="1e4"
targetRegions="{ reservoir, wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12 }">
<NonlinearSolverParameters
newtonTol="1.0e-4"
newtonMaxIter="10"
newtonMinIter="1"
dtCutIterLimit="0.9"
dtIncIterLimit="0.6"
timestepCutFactor="0.1"
maxTimeStepCuts="10"
lineSearchAction="None"/>
<!-- Note that the direct solver is going to be quite slow -->
<!-- This block will be updated when Hypre becomes the default -->
<LinearSolverParameters
solverType="direct"/>
</CompositionalMultiphaseReservoir>
<CompositionalMultiphaseFlow
name="compositionalMultiphaseFlow"
targetRegions="{ reservoir }"
discretization="fluidTPFA"
fluidNames="{ fluid }"
solidNames="{ rock }"
relPermNames="{ relperm }"
temperature="297.15"
maxCompFractionChange="0.5"
logLevel="1"
useMass="1"/>
<CompositionalMultiphaseWell
name="compositionalMultiphaseWell"
targetRegions="{ wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12 }"
fluidNames="{ fluid }"
relPermNames="{ relperm }"
wellTemperature="297.15"
maxCompFractionChange="0.5"
logLevel="1"
useMass="1">
<WellControls
name="wellControls1"
type="producer"
control="BHP"
targetBHP="3.9e7"
targetRate="1e9"/>
<WellControls
name="wellControls2"
type="producer"
control="BHP"
targetBHP="3.9e7"
targetRate="1e9"/>
<WellControls
name="wellControls3"
type="producer"
control="BHP"
targetBHP="3.9e7"
targetRate="1e9"/>
<WellControls
name="wellControls4"
type="producer"
control="BHP"
targetBHP="3.9e7"
targetRate="1e9"/>
<WellControls
name="wellControls5"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
<WellControls
name="wellControls6"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
<WellControls
name="wellControls7"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
<WellControls
name="wellControls8"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
<WellControls
name="wellControls9"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
<WellControls
name="wellControls10"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
<WellControls
name="wellControls11"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
<WellControls
name="wellControls12"
type="injector"
control="liquidRate"
targetBHP="5e8"
targetRate="8e0"
injectionStream="{ 0.0, 0.0, 1.0 }"/>
</CompositionalMultiphaseWell>
</Solvers>
Specifying a reservoir mesh and defining the geometry of the wells¶
The Mesh block consists of two parts:
- The reservoir mesh is described in the PAMELAMeshGenerator block,
- The wells are described in the InternalWell blocks, with one well per block.
The reservoir mesh is imported from a .msh
file that contains the mesh geometry
and also includes the permeability values in the x, y, and z directions.
These quantities must be specified using the metric unit system, i.e., in meters
for the well geometry and square meters for the permeability field.
We note that the mesh file only contains the active cells, so there is no keyword
needed in the XML file to define them.
As in Tutorial 4: Multiphase flow with wells, the geometry of the twelve wells is defined
internally using the description provided in the InternalWell XML blocks.
We remind the user that each block InternalWell must point to the reservoir mesh
(using the attribute meshName
), the corresponding well region (using
the attribute wellRegionName
), and the corresponding well control
(using the attribute wellControlName
).
Each well is defined using a vertical polyline going through the seven layers of the
mesh, with a perforation in each layer.
The well transmissibility factors employed to compute the perforation rates are calculated
internally using the Peaceman formulation.
The well placement implemented here follows the pattern of the original test case.
<Mesh>
<PAMELAMeshGenerator
name="mesh"
file="../../../../../../../GEOSXDATA/DataSets/Egg/egg.msh"
fieldsToImport="{ PERM }"
fieldNamesInGEOSX="{ permeability }"/>
<InternalWell
name="wellProducer1"
wellRegionName="wellRegion1"
wellControlsName="wellControls1"
meshName="mesh"
polylineNodeCoords="{ { 124, 340, 28 },
{ 124, 340, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="7">
<Perforation
name="producer1_perf1"
distanceFromHead="2"/>
<Perforation
name="producer1_perf2"
distanceFromHead="6"/>
<Perforation
name="producer1_perf3"
distanceFromHead="10"/>
<Perforation
name="producer1_perf4"
distanceFromHead="14"/>
<Perforation
name="producer1_perf5"
distanceFromHead="18"/>
<Perforation
name="producer1_perf6"
distanceFromHead="22"/>
<Perforation
name="producer1_perf7"
distanceFromHead="26"/>
</InternalWell>
<InternalWell
name="wellProducer2"
wellRegionName="wellRegion2"
wellControlsName="wellControls2"
meshName="mesh"
polylineNodeCoords="{ { 276, 316, 28 },
{ 276, 316, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="7">
<Perforation
name="producer2_perf1"
distanceFromHead="2"/>
<Perforation
name="producer2_perf2"
distanceFromHead="6"/>
<Perforation
name="producer2_perf3"
distanceFromHead="10"/>
<Perforation
name="producer2_perf4"
distanceFromHead="14"/>
<Perforation
name="producer2_perf5"
distanceFromHead="18"/>
<Perforation
name="producer2_perf6"
distanceFromHead="22"/>
<Perforation
name="producer2_perf7"
distanceFromHead="26"/>
</InternalWell>
<InternalWell
name="wellProducer3"
wellRegionName="wellRegion3"
wellControlsName="wellControls3"
meshName="mesh"
polylineNodeCoords="{ { 180, 124, 28 },
{ 180, 124, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="7">
<Perforation
name="producer3_perf1"
distanceFromHead="2"/>
<Perforation
name="producer3_perf2"
distanceFromHead="8"/>
<Perforation
name="producer3_perf3"
distanceFromHead="10"/>
<Perforation
name="producer3_perf4"
distanceFromHead="14"/>
<Perforation
name="producer3_perf5"
distanceFromHead="18"/>
<Perforation
name="producer3_perf6"
distanceFromHead="22"/>
<Perforation
name="producer3_perf7"
distanceFromHead="26"/>
</InternalWell>
<InternalWell
name="wellProducer4"
wellRegionName="wellRegion4"
wellControlsName="wellControls4"
meshName="mesh"
polylineNodeCoords="{ { 340, 140, 28 },
{ 340, 140, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="7">
<Perforation
name="producer4_perf1"
distanceFromHead="2"/>
<Perforation
name="producer4_perf2"
distanceFromHead="6"/>
<Perforation
name="producer4_perf3"
distanceFromHead="10"/>
<Perforation
name="producer4_perf4"
distanceFromHead="14"/>
<Perforation
name="producer4_perf5"
distanceFromHead="18"/>
<Perforation
name="producer4_perf6"
distanceFromHead="22"/>
<Perforation
name="producer4_perf7"
distanceFromHead="26"/>
</InternalWell>
<InternalWell
name="wellInjector1"
wellRegionName="wellRegion5"
wellControlsName="wellControls5"
meshName="mesh"
polylineNodeCoords="{ { 36, 452, 32 },
{ 36, 452, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector1_perf1"
distanceFromHead="6"/>
<Perforation
name="injector1_perf2"
distanceFromHead="10"/>
<Perforation
name="injector1_perf3"
distanceFromHead="14"/>
<Perforation
name="injector1_perf4"
distanceFromHead="18"/>
<Perforation
name="injector1_perf5"
distanceFromHead="22"/>
<Perforation
name="injector1_perf6"
distanceFromHead="26"/>
<Perforation
name="injector1_perf7"
distanceFromHead="30"/>
</InternalWell>
<InternalWell
name="wellInjector2"
wellRegionName="wellRegion6"
wellControlsName="wellControls6"
meshName="mesh"
polylineNodeCoords="{ { 236, 420, 32 },
{ 236, 420, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector2_perf1"
distanceFromHead="6"/>
<Perforation
name="injector2_perf2"
distanceFromHead="10"/>
<Perforation
name="injector2_perf3"
distanceFromHead="14"/>
<Perforation
name="injector2_perf4"
distanceFromHead="18"/>
<Perforation
name="injector2_perf5"
distanceFromHead="22"/>
<Perforation
name="injector2_perf6"
distanceFromHead="26"/>
<Perforation
name="injector2_perf7"
distanceFromHead="30"/>
</InternalWell>
<InternalWell
name="wellInjector3"
wellRegionName="wellRegion7"
wellControlsName="wellControls7"
meshName="mesh"
polylineNodeCoords="{ { 12, 276, 32 },
{ 12, 276, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector3_perf1"
distanceFromHead="6"/>
<Perforation
name="injector3_perf2"
distanceFromHead="10"/>
<Perforation
name="injector3_perf3"
distanceFromHead="14"/>
<Perforation
name="injector3_perf4"
distanceFromHead="18"/>
<Perforation
name="injector3_perf5"
distanceFromHead="22"/>
<Perforation
name="injector3_perf6"
distanceFromHead="26"/>
<Perforation
name="injector3_perf7"
distanceFromHead="30"/>
</InternalWell>
<InternalWell
name="wellInjector4"
wellRegionName="wellRegion8"
wellControlsName="wellControls8"
meshName="mesh"
polylineNodeCoords="{ { 212, 228, 32 },
{ 212, 228, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector4_perf1"
distanceFromHead="6"/>
<Perforation
name="injector4_perf2"
distanceFromHead="10"/>
<Perforation
name="injector4_perf3"
distanceFromHead="14"/>
<Perforation
name="injector4_perf4"
distanceFromHead="18"/>
<Perforation
name="injector4_perf5"
distanceFromHead="22"/>
<Perforation
name="injector4_perf6"
distanceFromHead="26"/>
<Perforation
name="injector4_perf7"
distanceFromHead="30"/>
</InternalWell>
<InternalWell
name="wellInjector5"
wellRegionName="wellRegion9"
wellControlsName="wellControls9"
meshName="mesh"
polylineNodeCoords="{ { 396, 276, 32 },
{ 396, 276, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector5_perf1"
distanceFromHead="6"/>
<Perforation
name="injector5_perf2"
distanceFromHead="10"/>
<Perforation
name="injector5_perf3"
distanceFromHead="14"/>
<Perforation
name="injector5_perf4"
distanceFromHead="18"/>
<Perforation
name="injector5_perf5"
distanceFromHead="22"/>
<Perforation
name="injector5_perf6"
distanceFromHead="26"/>
<Perforation
name="injector5_perf7"
distanceFromHead="30"/>
</InternalWell>
<InternalWell
name="wellInjector6"
wellRegionName="wellRegion10"
wellControlsName="wellControls10"
meshName="mesh"
polylineNodeCoords="{ { 60, 68, 32 },
{ 60, 68, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector6_perf1"
distanceFromHead="6"/>
<Perforation
name="injector6_perf2"
distanceFromHead="10"/>
<Perforation
name="injector6_perf3"
distanceFromHead="14"/>
<Perforation
name="injector6_perf4"
distanceFromHead="18"/>
<Perforation
name="injector6_perf5"
distanceFromHead="22"/>
<Perforation
name="injector6_perf6"
distanceFromHead="26"/>
<Perforation
name="injector6_perf7"
distanceFromHead="30"/>
</InternalWell>
<InternalWell
name="wellInjector7"
wellRegionName="wellRegion11"
wellControlsName="wellControls11"
meshName="mesh"
polylineNodeCoords="{ { 252, 12, 32 },
{ 252, 12, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector7_perf1"
distanceFromHead="6"/>
<Perforation
name="injector7_perf2"
distanceFromHead="10"/>
<Perforation
name="injector7_perf3"
distanceFromHead="14"/>
<Perforation
name="injector7_perf4"
distanceFromHead="18"/>
<Perforation
name="injector7_perf5"
distanceFromHead="22"/>
<Perforation
name="injector7_perf6"
distanceFromHead="26"/>
<Perforation
name="injector7_perf7"
distanceFromHead="30"/>
</InternalWell>
<InternalWell
name="wellInjector8"
wellRegionName="wellRegion12"
wellControlsName="wellControls12"
meshName="mesh"
polylineNodeCoords="{ { 452, 44, 32 },
{ 452, 44, 0 } }"
polylineSegmentConn="{ { 0, 1 } }"
radius="0.1"
numElementsPerSegment="8">
<Perforation
name="injector8_perf1"
distanceFromHead="6"/>
<Perforation
name="injector8_perf2"
distanceFromHead="10"/>
<Perforation
name="injector8_perf3"
distanceFromHead="14"/>
<Perforation
name="injector8_perf4"
distanceFromHead="18"/>
<Perforation
name="injector8_perf5"
distanceFromHead="22"/>
<Perforation
name="injector8_perf6"
distanceFromHead="26"/>
<Perforation
name="injector8_perf7"
distanceFromHead="30"/>
</InternalWell>
</Mesh>
Geometry tag¶
The Geometry XML block was used in the single-phase tutorials to specify boundary conditions. Since we use wells and assume no-flow boundary conditions in this tutorial, the Geometry block is not needed.
Specifying events¶
In the Events XML block, we specify four types of PeriodicEvents.
The periodic event named solverApplications
notifies GEOSX that the
coupled solver coupledFlowAndWells
has to be applied to its target
regions (here, reservoir and wells) at every time step.
The time stepping strategy has been fully defined in the CompositionalMultiphaseReservoir
coupling block using the initialDt
attribute and the NonlinearSolverParameters
nested block.
As in Tutorial 4: Multiphase flow with wells, we also define an output event
instructing GEOSX to write out .vtk
files at the time frequency specified
by the attribute timeFrequency
.
The target
attribute must point to the VTK sub-block of the Outputs
block (defined at the end of the XML file) by name (here, vtkOutput
).
We define the events involved in the collection and output of the well production rates following the procedure defined in Tasks Manager.
The time history collection events trigger the collection of the well rates at the desired frequency, while the time history output events trigger the output of the HDF5 files containing the time series.
These events point by name to the corresponding blocks of the Tasks and Outputs XML blocks, respectively. Here, these names are wellRateCollection1
and timeHistoryOutput1
.
<Events
maxTime="1.5e7">
<PeriodicEvent
name="vtk"
timeFrequency="2e6"
targetExactTimestep="1"
target="/Outputs/vtkOutput"/>
<PeriodicEvent
name="timeHistoryOutput1"
timeFrequency="1.5e7"
targetExactTimestep="1"
target="/Outputs/timeHistoryOutput1" />
<PeriodicEvent
name="timeHistoryOutput2"
timeFrequency="1.5e7"
targetExactTimestep="1"
target="/Outputs/timeHistoryOutput2" />
<PeriodicEvent
name="timeHistoryOutput3"
timeFrequency="1.5e7"
targetExactTimestep="1"
target="/Outputs/timeHistoryOutput3" />
<PeriodicEvent
name="timeHistoryOutput4"
timeFrequency="1.5e7"
targetExactTimestep="1"
target="/Outputs/timeHistoryOutput4" />
<PeriodicEvent
name="solverApplications"
target="/Solvers/coupledFlowAndWells"/>
<PeriodicEvent
name="timeHistoryCollection1"
timeFrequency="4e5"
targetExactTimestep="1"
target="/Tasks/wellRateCollection1" />
<PeriodicEvent
name="timeHistoryCollection2"
timeFrequency="4e5"
targetExactTimestep="1"
target="/Tasks/wellRateCollection2" />
<PeriodicEvent
name="timeHistoryCollection3"
timeFrequency="4e5"
targetExactTimestep="1"
target="/Tasks/wellRateCollection3" />
<PeriodicEvent
name="timeHistoryCollection4"
timeFrequency="4e5"
targetExactTimestep="1"
target="/Tasks/wellRateCollection4" />
</Events>
Defining Numerical Methods¶
In the NumericalMethods
XML block, we instruct GEOSX to use a TPFA finite-volume
numerical scheme.
This part is identical to the corresponding section of Tutorial 4: Multiphase flow with wells.
<NumericalMethods>
<FiniteVolume>
<TwoPointFluxApproximation
name="fluidTPFA"
fieldName="pressure"
coefficientName="permeability"/>
</FiniteVolume>
</NumericalMethods>
Defining reservoir and well regions¶
In this section of the input file, we follow the procedure already described in Tutorial 4: Multiphase flow with wells for the definition of the reservoir and well regions.
We associate a CellElementRegion named reservoir
to the reservoir mesh.
Since we have imported a mesh with one region consisting of hexahedral cells, we
must set the attribute cellBlocks
to DEFAULT_HEX
.
Note
If you use a name that is not DEFAULT_HEX
for this attribute, GEOSX will throw an error at the beginning of the simulation.
We also associate a WellElementRegion to each well. As the CellElementRegion,
it contains a materialList
that must point (by name) to the constitutive models
defined in the Constitutive XML block.
<ElementRegions>
<CellElementRegion
name="reservoir"
cellBlocks="{ DEFAULT_HEX }"
materialList="{ fluid, rock, relperm }"/>
<WellElementRegion
name="wellRegion1"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion2"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion3"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion4"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion5"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion6"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion7"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion8"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion9"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion10"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion11"
materialList="{ fluid, relperm }"/>
<WellElementRegion
name="wellRegion12"
materialList="{ fluid, relperm }"/>
</ElementRegions>
Defining material properties with constitutive laws¶
The CompositionalMultiphaseFlow physics solver relies on at least three types of constitutive models listed in the Constitutive XML block:
- a fluid model describing the thermodynamics behavior of the fluid mixture,
- a relative permeability model,
- a rock compressibility model.
All the parameters must be provided using the SI unit system.
Although the original Egg test case only involves two phases, the Dead-Oil model currently implemented in GEOSX requires the definition of three phases (oil, gas, and water). This is done in the BlackOilFluid XML block. The same is true for the relative permeability model introduced in the BrooksCoreyRelativePermeability block.
Note
The names and order of the phases listed for the attribute phaseNames
must be identical in the fluid model and the relative permeability model.
The rock compressibility is defined in the PoreVolumeCompressibleSolid block. The parameters of these three blocks have been chosen to match the original specifications of the Egg test case.
<Constitutive>
<BlackOilFluid
name="fluid"
fluidType="DeadOil"
phaseNames="{ oil, gas, water }"
surfaceDensities="{ 848.9, 0.9907, 1025.2 }"
componentMolarWeight="{ 114e-3, 16e-3, 18e-3 }"
tableFiles="{ pvdo.txt, pvdg.txt, pvtw.txt }"/>
<BrooksCoreyRelativePermeability
name="relperm"
phaseNames="{ oil, gas, water }"
phaseMinVolumeFraction="{ 0.1, 0.0, 0.2 }"
phaseRelPermExponent="{ 4.0, 2.0, 3.0 }"
phaseRelPermMaxValue="{ 0.8, 1.0, 0.75 }"/>
<PoreVolumeCompressibleSolid
name="rock"
referencePressure="0"
compressibility="1e-13"/>
</Constitutive>
Defining properties with the FieldSpecifications¶
We are ready to specify the reservoir initial conditions of the problem in the FieldSpecifications XML block. The well variables do not have to be initialized here since they will be defined internally.
The formulation of the CompositionalMultiphaseFlow physics solver (documented
at Compositional Multiphase Flow Solver) requires the definition of the initial pressure field
and initial global component fractions.
We define here a uniform pressure field that does not satisfy the hydrostatic equilibrium,
but a hydrostatic initialization of the pressure field is possible using Functions:.
For the initialization of the global component fractions, we remind the user that their component
attribute (here, 0, 1, or 2) is used to point to a specific entry of the phaseNames
attribute
in the BlackOilFluid block.
Note that we also define the uniform porosity field here since it is not included in the mesh file imported by the PAMELAMeshGenerator.
<FieldSpecifications>
<FieldSpecification
name="referencePorosity"
initialCondition="1"
setNames="{ all }"
objectPath="ElementRegions/reservoir/DEFAULT_HEX"
fieldName="referencePorosity"
scale="0.2"/>
<FieldSpecification
name="initialPressure"
initialCondition="1"
setNames="{ all }"
objectPath="ElementRegions/reservoir/DEFAULT_HEX"
fieldName="pressure"
scale="4e7"/>
<FieldSpecification
name="initialComposition_oil"
initialCondition="1"
setNames="{ all }"
objectPath="ElementRegions/reservoir/DEFAULT_HEX"
fieldName="globalCompFraction"
component="0"
scale="1.0"/>
<FieldSpecification
name="initialComposition_gas"
initialCondition="1"
setNames="{ all }"
objectPath="ElementRegions/reservoir/DEFAULT_HEX"
fieldName="globalCompFraction"
component="1"
scale="0.0"/>
<FieldSpecification
name="initialComposition_water"
initialCondition="1"
setNames="{ all }"
objectPath="ElementRegions/reservoir/DEFAULT_HEX"
fieldName="globalCompFraction"
component="2"
scale="0.0"/>
</FieldSpecifications>
Specifying the output formats¶
In this section, we request an output of the results in VTK format and an output of the rates for each producing well. Note that the name defined here must match the name used in the Events XML block to define the output frequency.
<Outputs>
<VTK
name="vtkOutput"/>
<TimeHistory
name="timeHistoryOutput1"
sources="{/Tasks/wellRateCollection1}"
filename="wellRateHistory1" />
<TimeHistory
name="timeHistoryOutput2"
sources="{/Tasks/wellRateCollection2}"
filename="wellRateHistory2" />
<TimeHistory
name="timeHistoryOutput3"
sources="{/Tasks/wellRateCollection3}"
filename="wellRateHistory3" />
<TimeHistory
name="timeHistoryOutput4"
sources="{/Tasks/wellRateCollection4}"
filename="wellRateHistory4" />
</Outputs>
Specifying tasks¶
In the Events block, we have defined four events requesting that a task periodically collects the rate for each producing well.
This task is defined here, in the PackCollection XML sub-block of the Tasks block.
The task contains the path to the object on which the field to collect is registered (here, a WellElementSubRegion
) and the name of the field (here, wellElementMixtureConnectionRate
).
The details of the history collection mechanism can be found in Tasks Manager.
<Tasks>
<PackCollection
name="wellRateCollection1"
objectPath="ElementRegions/wellRegion1/wellRegion1uniqueSubRegion"
fieldName="wellElementMixtureConnectionRate" />
<PackCollection
name="wellRateCollection2"
objectPath="ElementRegions/wellRegion2/wellRegion2uniqueSubRegion"
fieldName="wellElementMixtureConnectionRate" />
<PackCollection
name="wellRateCollection3"
objectPath="ElementRegions/wellRegion3/wellRegion3uniqueSubRegion"
fieldName="wellElementMixtureConnectionRate" />
<PackCollection
name="wellRateCollection4"
objectPath="ElementRegions/wellRegion4/wellRegion4uniqueSubRegion"
fieldName="wellElementMixtureConnectionRate" />
</Tasks>
All elements are now in place to run GEOSX.
Running GEOSX¶
The first few lines appearing to the console are indicating that the XML elements are read and registered correctly:
Adding Solver of type CompositionalMultiphaseReservoir, named coupledFlowAndWells
Adding Solver of type CompositionalMultiphaseFlow, named compositionalMultiphaseFlow
Adding Solver of type CompositionalMultiphaseWell, named compositionalMultiphaseWell
Adding Mesh: PAMELAMeshGenerator, mesh
Adding Mesh: InternalWell, wellProducer1
Adding Mesh: InternalWell, wellProducer2
Adding Mesh: InternalWell, wellProducer3
Adding Mesh: InternalWell, wellProducer4
Adding Mesh: InternalWell, wellInjector1
Adding Mesh: InternalWell, wellInjector2
Adding Mesh: InternalWell, wellInjector3
Adding Mesh: InternalWell, wellInjector4
Adding Mesh: InternalWell, wellInjector5
Adding Mesh: InternalWell, wellInjector6
Adding Mesh: InternalWell, wellInjector7
Adding Mesh: InternalWell, wellInjector8
Adding Event: PeriodicEvent, solverApplications
Adding Event: PeriodicEvent, vtk
Adding Output: VTK, vtkOutput
Adding Object CellElementRegion named reservoir from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion1 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion2 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion3 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion4 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion5 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion6 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion7 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion8 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion9 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion10 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion11 from ObjectManager::Catalog.
Adding Object WellElementRegion named wellRegion12 from ObjectManager::Catalog.
This is followed by the creation of the 18553 hexahedral cells of the imported mesh:
0 >>> **********************************************************************
0 >>> PAMELA Library Import tool
0 >>> **********************************************************************
0 >>> GMSH FORMAT IDENTIFIED
0 >>> *** Importing Gmsh mesh format...
0 >>> Reading nodes...
0 >>> Done0
0 >>> Reading elements...
0 >>> Reading element data...
0 >>> Number of nodes = 22227
0 >>> Number of triangles = 0
0 >>> Number of quadrilaterals = 0
0 >>> Number of tetrahedra = 0
0 >>> Number of hexahedra = 18553
0 >>> Number of pyramids = 0
0 >>> Number of prisms = 0
0 >>> *** Done
0 >>> *** Creating Polygons from Polyhedra...
0 >>> 59205 polygons have been created
0 >>> *** Done
0 >>> *** Perform partitioning...
0 >>> TRIVIAL partitioning...
0 >>> Ghost elements...
0 >>> Clean mesh...
0 >>> *** Done...
0 >>> Clean Adjacency...
0 >>> *** Done...
When Running simulation
is shown, we are done with the case set-up and
the code steps into the execution of the simulation itself:
Time: 0s, dt:10000s, Cycle: 0
Attempt: 0, NewtonIter: 0
( Rfluid ) = (3.58e+02) ; ( R ) = ( 2.23e+05 ) ;
Attempt: 0, NewtonIter: 1
( Rfluid ) = (9.69e-01) ; ( R ) = ( 3.09e+02 ) ;
Last LinSolve(iter,res) = ( 1, 2.22e-16 ) ;
Attempt: 0, NewtonIter: 2
( Rfluid ) = (8.89e-02) ; ( R ) = ( 2.48e+01 ) ;
Last LinSolve(iter,res) = ( 1, 2.22e-16 ) ;
Attempt: 0, NewtonIter: 3
( Rfluid ) = (1.82e-03) ; ( R ) = ( 4.73e-01 ) ;
Last LinSolve(iter,res) = ( 1, 2.22e-16 ) ;
Attempt: 0, NewtonIter: 4
( Rfluid ) = (7.46e-07) ; ( R ) = ( 1.67e-04 ) ;
Last LinSolve(iter,res) = ( 1, 2.22e-16 ) ;
Attempt: 0, NewtonIter: 5
( Rfluid ) = (2.02e-12) ; ( R ) = ( 3.65e-11 ) ;
Last LinSolve(iter,res) = ( 1, 2.22e-16 ) ;
coupledFlowAndWells: Newton solver converged in less than 6 iterations, time-step required will be doubled.
Visualization of results¶
A file compatible with Paraview is produced in this tutorial. It is found in the output folder, and usually has the extension .pvd. More details about this file format can be found here. We can load this file into Paraview directly and visualize results:
We have instructed GEOSX to output the time series of rates for each producer. The data contained in the corresponding hdf5 files can be extracted and plotted as shown below.
To go further¶
Feedback on this tutorial
This concludes the tutorial on setting up a Dead-Oil simulation in the Egg model. For any feedback on this tutorial, please submit a GitHub issue on the project’s GitHub page.
Next tutorial
In Tutorial 6: CO 2 injection into an unstructured grid, we learn how to run a more complex test case based on an unstructured mesh.
For more details
- A complete description of the reservoir flow solver is found here: Compositional Multiphase Flow Solver.
- The well solver is description at Compositional Multiphase Well Solver.
- The available constitutive models are listed at Constitutive Models.