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 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 factor timestepCutFactor = 0.1,
  • if the Newton solver fails to converge in newtonMaxIter = 10, GEOSX will cut the time step size by a factor timestepCutFactor = 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.

../../../../_images/egg_model.png
  <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:

pic1 pic2

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.

(Source code)

../../../../_images/Tutorial-1_01_002.png

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