Tutorial 1: First Steps

Context

In this tutorial, we use a single-phase flow solver (see Singlephase Flow Solver) to solve for pressure propagation on a 10x10x10 cube mesh with anisotropic permeability values. The pressure source is the lowest-left corner element, and the pressure sink sits at the opposite top corner.

../../../../_images/source_sink.png

Objectives

At the end of this tutorial you will know:

  • the basic structure of XML input files used by GEOSX,
  • how to run GEOSX on a simple case requiring no external input files,
  • the basic syntax of a solver block for single-phase problems,
  • how to control output and visualize results.

Input file

GEOSX runs by reading user input information from one or more XML files. For this tutorial, we only need a single GEOSX input file located at:

inputFiles/singlePhaseFlow/3D_10x10x10_compressible_smoke.xml

Running GEOSX

If our XML input file is called my_input.xml, GEOSX runs this file by executing:

/path/to/geosx -i /path/to/my_input.xml

The -i flag indicates the path to the XML input file. To get help on what other command line input flags GEOSX supports, run geosx --help.

Input file structure

XML files store information in a tree-like structure using nested blocks of information called elements. In GEOSX, the root of this tree structure is the element called Problem. All elements in an XML file are defined by an opening tag (<ElementName>) and end by a corresponding closing tag (</ElementName>). Elements can have properties defined as attributes with key="value" pairs. A typical GEOSX input file contains the following tags:

XML validation tools

If you have not already done so, please use or enable an XML validation tool (see User Guide/Input Files/Input Validation). Such tools will help you identify common issues that may occur when working with XML files.

Note

Common errors come from the fact that XML is case-sensitive, and all opened tags must be properly closed.

Single-phase solver

GEOSX is a multiphysics simulator. To find the solution to different physical problems such as diffusion or mechanical deformation, GEOSX uses one or more physics solvers. The Solvers tag is used to define and parameterize these solvers. Different combinations of solvers can be applied in different regions of the domain at different moments of the simulation.

In this first example, we use one type of solver in the entire domain and for the entire duration of the simulation. The solver we are specifying here is a single-phase flow solver. In GEOSX, such a solver is created using a SinglePhaseFVM element. This type of solver is one among several cell-centered single-phase finite volume methods.

The XML block used to define this single-phase finite volume solver is shown here:

  <Solvers>
    <SinglePhaseFVM
      name="SinglePhaseFlow"
      logLevel="1"
      discretization="singlePhaseTPFA"
      targetRegions="{ mainRegion }">
      <NonlinearSolverParameters
        newtonTol="1.0e-6"
        newtonMaxIter="8"/>
      <LinearSolverParameters
        solverType="gmres"
	preconditionerType="amg" 
        krylovTol="1.0e-10"/>
    </SinglePhaseFVM>
  </Solvers>

Each type of solver has a specific set of parameters that are required and some parameters that are optional. Optional values are usually set with sensible default values.

name

First, we register a solver of type SinglePhaseFVM with a user-chosen name, here SinglePhaseFlow. This unique user-defined name can be almost anything. However, some symbols are known to cause issues in names : avoid commas, slashes, curly braces. GEOSX is case-sensitive: it makes a distinction between two SinglePhaseFVM solvers called mySolver and MySolver. Giving elements a name is a common practice in GEOSX: users need to give unique identifiers to objects they define. That name is the handle to this instance of a solver class.

logLevel

Then, we set a solver-specific level of console logging (logLevel set to 1 here). Notice that the value (1) is between double-quotes. This is a general convention for all attributes: we write key="value" regardless of the value type (integers, strings, lists, etc.).

For logLevel, higher values lead to more console output or intermediate results saved to files. When debugging, higher logLevel values is often convenient. In production runs, you may want to suppress most console output.

discretization

For solvers of the SinglePhaseFVM family, one required attribute is a discretization scheme. Here, we use a Two-Point Flux Approximation (TPFA) finite volume discretization scheme called singlePhaseTPFA. To know the list of admissible values of an attribute, please see GEOSX’s XML schema. This discretization type must know how to find permeability values that it uses internally to compute transmissibilities. The permeabilityNames attribute tells the solver the user-defined name (the handle) of the permeability values that will be defined elsewhere in the input file. Note that the order of attributes inside an element is not important.

fluidNames, solidNames, targetRegions

Here, we specify a collection of fluids, rocks, and target regions of the mesh on which the solver will apply. Curly brackets are used in GEOSX inputs to indicate collections of values (sets or lists). The curly brackets used here are necessary, even if the collection contains a single value. Commas are used to separate members of a set.

Nested elements

Finally, note that other XML elements can be nested inside the Solvers element. Here, we use specific XML elements to set values for numerical tolerances. The solver stops when numerical residuals are smaller than the specified tolerances (convergence is achieved) or when the maximum number of iterations allowed is exceeded (convergence not achieved).

Mesh

To solve this problem, we need to define a mesh for our numerical calculations. This is the role of the Mesh element.

There are two approaches to specifying meshes in GEOSX: internal or external.

  • The external approach allows to import mesh files created outside GEOSX, such as a corner-point grid or an unstructured grid representing complex shapes and structures.
  • The internal approach uses GEOSX’s built-in capability to create simple meshes from a small number of parameters. It does not require any external file information. The geometric complexity of internal meshes is limited, but many practical problems can be solved on such simple grids.

In this tutorial, to keep things self-contained, we use the internal mesh generator. We parameterize it with the InternalMesh element.

  <Mesh>
    <InternalMesh
        name="mesh"
        elementTypes="{ C3D8 }"
        xCoords="{ 0, 10 }"
        yCoords="{ 0, 10 }"
        zCoords="{ 0, 10 }"
        nx="{ 10 }"
        ny="{ 10 }"
        nz="{ 10 }"
        cellBlockNames="{ cellBlock }"/>
  </Mesh>

name

Just like for solvers, we register the InternalMesh element using a unique name attribute. Here the InternalMesh object is instantiated with the name mesh.

elementTypes

We specify the collection of elements types that this mesh contains. Tetrahedra, hexahedra, and wedges are examples of element types. If a mesh contains different types of elements (a hybrid mesh), we should indicate this here by listing all unique types of elements in curly brackets. Keeping things simple, our element collection has only one type of element: a C3D8 type representing a hexahedral element (linear 8-node brick).

A mesh can contain several geometrical types of elements. For numerical convenience, elements are aggregated by types into cellBlocks. Here, we only linear 8-node brick elements, so the entire domain is one object called cellBlock.

xCoords, yCoords, zCoords, nx, ny, nz

This specifies the spatial arrangement of the mesh elements. The mesh defined here goes from coordinate x=0 to x=10 in the x-direction, with nx=10 subdivisions along this segment. The same is true for the y-dimension and the z-dimension. Our mesh is a cube of 10x10x10=1,000 elements with a bounding box defined by corner coordinates (0,0,0) and (10,10,10).

../../../../_images/mesh12.png

Geometry

The Geometry tag allows users to capture subregions of a mesh and assign them a unique name. Here, we name two Box elements, one for the location of the source and one for the sink. Pressure values are assigned to these named regions elsewhere in the input file.

The pressure source is the element in the (0,0,0) corner of the domain, and the sink is the element in the (10,10,10) corner.

For an element to be inside a geometric region, it must have all its vertices strictly inside that region. Consequently, we need to extend the geometry limits a small amount beyond the actual coordinates of the elements to catch all vertices. Here, we use a safety padding of 0.01.

  <Geometry>
    <Box
      name="source"
      xMin="{ -0.01, -0.01, -0.01 }"
      xMax="{ 1.01, 1.01, 1.01 }"/>

    <Box
      name="sink"
      xMin="{ 8.99, 8.99, 8.99 }"
      xMax="{ 10.01, 10.01, 10.01 }"/>
  </Geometry>

There are several methods to achieve similar conditions (Dirichlet boundary condition on faces, etc.). The Box defined here is one of the simplest approaches.

../../../../_images/source_sink.png

Events

In GEOSX, we call Events anything that happens at a set time or frequency. Events are a central element for time-stepping in GEOSX, and a dedicated section just for events is necessary to give them the treatment they deserve.

For now, we focus on three simple events: the time at which we wish the simulation to end (maxTime), the times at which we want the solver to perform updates, and the times we wish to have simulation output values reported.

In GEOSX, all times are specified in seconds, so here maxTime=5000.0 means that the simulation will run from time 0 to time 5,000 seconds.

If we focus on the PeriodicEvent elements, we see :

  1. A periodic solver application: this event is named solverApplications. With the attribute forceDt=20, it tells the solver to compute results at 20-second time intervals. We know what this event does by looking at its target attribute: here, from time 0 to maxTime and with a forced time step of 20 seconds, we instruct GEOSX to call the solver registered as SinglePhaseFlow. Note the hierarchical structure of the target formulation, using ‘/’ to indicate a specific named instance (SinglePhaseFlow) of an element (Solvers). If the solver needs to take smaller time steps, it is allowed to do so, but it will have to compute results for every 20-second increment between time zero and maxTime regardless of possible intermediate time steps.
  2. An output event: this event is used for reporting purposes and instructs GEOSX to write out results at specific frequencies. Here, we need to see results at every 100-second increment. This event triggers a full application of solvers, even if solvers were not summoned by the previous event. In other words, an output event will force an application of solvers, possibly in addition to the periodic events requested directly.
  <Events maxTime="5000.0">
    <PeriodicEvent
        name="solverApplications"
        forceDt="20.0"
        target="/Solvers/SinglePhaseFlow"/>
    <PeriodicEvent
        name="outputs"
        timeFrequency="100.0"
        target="/Outputs/siloOutput"/>
  </Events>

Numerical methods

GEOSX comes with several useful numerical methods. In the Solvers elements, for instance, we had specified to use a two-point flux approximation as discretization scheme for the finite volume single-phase solver. Now to use this scheme, we need to supply more details in the NumericalMethods element.

  <NumericalMethods>
    <FiniteVolume>
      <TwoPointFluxApproximation
        name="singlePhaseTPFA"
        />
    </FiniteVolume>
  </NumericalMethods>

The fieldName attribute specifies which property will be used for flux computations, and also specifies that for Dirichlet boundary conditions, the pressure value at the element face is used. The coefficientName attribute is used for the stencil transmissibility computations.

Note that in GEOSX, there is a difference between physics solvers and numerical methods. Their parameterizations are thus independent. We can have multiple solvers using the same numerical scheme but with different tolerances, for instance.

Regions

In GEOSX, ElementsRegions are used to attach material properties to regions of elements. Here, we use only one CellElementRegion to represent the entire domain (user name: mainRegion). It contains all the blocks called cellBlock defined in the mesh section. We specify the materials contained in that region using a materialList. Several materials coexist in cellBlock, and we list them using their user-defined names: water, rockPorosity, and rockPerm, etc. What these names mean, and the physical properties that they are attached to are defined next.

  <ElementRegions>
    <CellElementRegion
      name="mainRegion"
      cellBlocks="{ cellBlock }"
      materialList="{ water, rock }"/>
  </ElementRegions>

Constitutive models

The Constitutive element attaches physical properties to all materials contained in the domain.

The physical properties of the materials defined as water, rockPorosity, and rockPerm are provided here, each material being derived from a different material type: CompressibleSinglePhaseFluid for the water, PressurePorosity for the rock porosity, and ConstantPermeability for rock permeability. The list of attributes differs between these constitutive materials.

  <Constitutive>
    <CompressibleSinglePhaseFluid
      name="water"
      defaultDensity="1000"
      defaultViscosity="0.001"
      referencePressure="0.0"
      compressibility="5e-10"
      viscosibility="0.0"/>

    <CompressibleSolidConstantPermeability
      name="rock"
      solidModelName="nullSolid"
      porosityModelName="rockPorosity"
      permeabilityModelName="rockPerm"/>

    <NullModel
      name="nullSolid"/>

    <PressurePorosity
      name="rockPorosity"
      defaultReferencePorosity="0.05"
      referencePressure="0.0"
      compressibility="1.0e-9"/>

    <ConstantPermeability
      name="rockPerm"
      permeabilityComponents="{ 1.0e-12, 1.0e-12, 1.0e-15 }"/>
  </Constitutive>

The names water, rockPorosity and rockPerm are defined by the user as handles to specific instances of physical materials. GEOSX uses S.I. units throughout, not field units. Pressures, for instance, are in Pascal, not psia. The x- and y-permeability are set to 1.0e-12 m2 corresponding to approximately to 1 Darcy.

We have used the handles water, rockPorosity and rockPerm in the input file in the ElementRegions section of the XML file, before the registration of these materials took place here, in Constitutive element.

Note

This highlights an important aspect of using XML in GEOSX: the order in which objects are registered and used in the XML file is not important.

Defining properties

In the FieldSpecifications section, properties such as source and sink pressures are set. GEOSX offers a lot of flexibility to specify field values through space and time.

Spatially, in GEOSX, all field specifications are associated to a target object on which the field values are mounted. This allows for a lot of freedom in defining fields: for instance, one can have volume property values attached to a subset of volume elements of the mesh, or surface properties attached to faces of a subset of elements.

For each FieldSpecification, we specify a name, a fieldName (this name is used by solvers or numerical methods), an objectPath, setNames and a scale. The ObjectPath is important and it reflects the internal class hierarchy of the code. Here, for the fieldName pressure, we assign the value defined by scale (5e6 Pascal) to one of the ElementRegions (class) called mainRegions (instance). More specifically, we target the elementSubRegions called cellBlock (this contains all the C3D8 elements, effectively all the domain). The setNames allows to use the elements defined in Geometry, or use everything in the object path (using the all).

  <FieldSpecifications>
    <FieldSpecification
      name="initialPressure"
      initialCondition="1"
      setNames="{ all }"
      objectPath="ElementRegions/mainRegion/cellBlock"
      fieldName="pressure"
      scale="5e6"/>

    <FieldSpecification
      name="sourceTerm"
      objectPath="ElementRegions/mainRegion/cellBlock"
      fieldName="pressure"
      scale="1e7"
      setNames="{ source }"/>

    <FieldSpecification
      name="sinkTerm"
      objectPath="ElementRegions/mainRegion/cellBlock"
      fieldName="pressure"
      scale="0.0"
      setNames="{ sink }"/>
  </FieldSpecifications>

The image below shows the pressures after the very first time step, with the domain initialized at 5 MPa, the sink at 0 MPa on the top right, and the source in the lower left corner at 10 MPa.

../../../../_images/initial_pressure.png

Output

In order to retrieve results from a simulation, we need to instantiate one or multiple Outputs.

Here, we define a single object of type Silo. Silo is a library and a format for reading and writing a wide variety of scientific data. Data in Silo format can be read by VisIt.

This Silo output object is called siloOutput. We had referred to this object already in the Events section: it was the target of a periodic event named outputs. You can verify that the Events section is using this object as a target. It does so by pointing to /Outputs/siloOutput.

  <Outputs>
    <Silo
      name="siloOutput"/>
  </Outputs>

GEOSX currently supports outputs that are readable by VisIt and Kitware’s Paraview, as well as other visualization tools. In this example, we only request a Silo format compatible with VisIt.

All elements are now in place to run GEOSX.

Running GEOSX

The command to run GEOSX is

path/to/geosx -i path/to/this/xml_file.xml

Note that all paths for files included in the XML file are relative to this XML file.

While running GEOSX, it logs status information on the console output with a verbosity that is controlled at the object level, and that can be changed using the logLevel flag.

The first few lines appearing to the console are indicating that the XML elements are read and registered correctly:

Adding Solver of type SinglePhaseFVM, named SinglePhaseFlow
Adding Mesh: InternalMesh, mesh
Adding Geometric Object: Box, source
Adding Geometric Object: Box, sink
Adding Event: PeriodicEvent, solverApplications
Adding Event: PeriodicEvent, outputs
Adding Output: Silo, siloOutput
Adding Object CellElementRegion named mainRegion from ObjectManager::Catalog.
  mainRegion/cellBlock/water is allocated with 1 quadrature points.
  mainRegion/cellBlock/rock is allocated with 1 quadrature points.
  mainRegion/cellBlock/rockPerm is allocated with 1 quadrature points.
  mainRegion/cellBlock/rockPorosity is allocated with 1 quadrature points.
  mainRegion/cellBlock/nullSolid is allocated with 1 quadrature points.

Then, we go into the execution of the simulation itself:

Time: 0s, dt:20s, Cycle: 0
    Attempt:  0, NewtonIter:  0
    ( R ) = ( 5.65e+00 ) ;
    Attempt:  0, NewtonIter:  1
    ( R ) = ( 2.07e-04 ) ;
    Last LinSolve(iter,res) = (  63, 8.96e-11 ) ;
    Attempt:  0, NewtonIter:  2
    ( R ) = ( 9.86e-11 ) ;
    Last LinSolve(iter,res) = (  70, 4.07e-11 ) ;

Each time iteration at every 20s interval is logged to console, until the end of the simulation at maxTime=5000:

Time: 4980s, dt:20s, Cycle: 249
    Attempt:  0, NewtonIter:  0
    ( R ) = ( 4.74e-09 ) ;
    Attempt:  0, NewtonIter:  1
    ( R ) = ( 2.05e-14 ) ;
    Last LinSolve(iter,res) = (  67, 5.61e-11 ) ;
SinglePhaseFlow: Newton solver converged in less than 4 iterations, time-step required will be doubled.
Cleaning up events
Umpire            HOST sum across ranks:   14.8 MB
Umpire            HOST         rank max:   14.8 MB
total time                         5.658s
initialization time                0.147s
run time                           3.289s

All newton iterations are logged along with corresponding nonlinear residuals for each time iteration. In turn, for each newton iteration, LinSolve provides the number of linear iterations and the final residual reached by the linear solver. Information on run times, initialization times, and maximum amounts of memory (high water mark) are given at the end of the simulation, if successful.

Congratulations on completing this first run!

Visualization

Here, we have requested results to be written in Silo, a format compatible with VisIt. To visualize results, open VisIt and directly load the database of simulation output files.

After a few time step, pressure between the source and sink are in equilibrium, as shown on the representation below.

../../../../_images/final_pressure.png

To go further

Feedback on this tutorial

This concludes the single-phase internal mesh tutorial. For any feedback on this tutorial, please submit a GitHub issue on the project’s GitHub page.

For more details