In this tutorial, we show how the use of SPDE for Varying Anisotropy in the Simulation process
%%javascript
IPython.OutputArea.prototype._should_scroll = function(lines) {
return false;
}
import gstlearn as gl
import gstlearn.plot as gp
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import random
import math
Defining some global parameters
#Extension of the simulation grid
nxmax = 500
nymax = 200
#Well Definition
nwell = 6
vlag = 3
#Anisotropy ratio
ratio=1.5
range=150
#Some seeds
seed1 = 34556643
seed2 = 244212
seednc = 432432
seedw = 2432145
# Color Scale
zlim = [-1.6, 2.5]
nostatKeys = ["A","R2"]
# Graphic scale
gp.setDefault(dims=[10,7])
Internal function
def make_well(db,res,nwell=nwell,vlag=vlag,seed=seedw):
nxmax = res.getNX(0)
indexes = gl.VectorHelper.sampleRanks(ntotal=nxmax, number=nwell, seed=seed, optSort=1)
x1 = np.ones(0)
x2 = np.ones(0)
for i in indexes:
bot = math.ceil(db[i,"W1"])
top = math.floor(db[i,"W2"])
temp = np.arange(bot, top, step=vlag)
x1 = np.concatenate((x1, i * np.ones(len(temp), dtype=int) + 0.2))
x2 = np.concatenate((x2, temp))
db_sample = gl.Db.createFromSamples(len(x1),gl.ELoadBy.COLUMN,np.concatenate((x1,x2)))
db_sample.setName("New.1","x1")
db_sample.setName("New.2","x2")
db_sample.setLocator("x1",gl.ELoc.X,0)
db_sample.setLocator("x2",gl.ELoc.X,1)
err = gl.migrate(res, db_sample, "*simu*")
return db_sample
Simulating the layer boundaries
db = gl.DbGrid.create(nx=nxmax)
model = gl.Model.createFromParam(gl.ECov.GAUSSIAN,range=200,space=gl.SpaceRN(1))
err = gl.simtub(None,dbout=db,model=model,nbtuba=1000,seed=seed1,namconv=gl.NamingConvention("W1"))
err = gl.simtub(None,dbout=db,model=model,nbtuba=1000,seed=seed2,namconv=gl.NamingConvention("W2"))
db["W1"]=db["W1"]-min(db["W1"])
db["W2"]=db["W2"]-min(db["W2"])
db["W2"]=db["W1"]+db["W2"]+1
db["W1"]=nymax*db["W1"]/max(db["W2"])
db["W2"]=nymax*db["W2"]/max(db["W2"])
db.display()
Data Base Grid Characteristics ============================== Data Base Summary ----------------- File is organized as a regular grid Space dimension = 1 Number of Columns = 4 Maximum Number of UIDs = 4 Total number of samples = 500 Grid characteristics: --------------------- Origin : 0.000 Mesh : 1.000 Number : 500 Variables --------- Column = 0 - Name = rank - Locator = NA Column = 1 - Name = x1 - Locator = x1 Column = 2 - Name = W1 - Locator = NA Column = 3 - Name = W2 - Locator = z1
Plotting the limits of the layer
ax = gp.grid1D(db,name="W1", color="blue")
ax = gp.grid1D(db,name="W2", color="green")
ax.decoration(title="Layer limits")
Creation of the varying anisotropy ("directed" by the two layers)
model = gl.Model.createFromParam(gl.ECov.BESSEL_K,range=range,param=1,space=gl.SpaceRN(2))
dbgrid = gl.DbGrid.create([nxmax,nymax])
ind = (dbgrid["x1"]).reshape(1,-1)[0].astype(int)
dbgrid["sel"] = (dbgrid["x2"] > db[ind,"W1"]) & (dbgrid["x2"] < db[ind,"W2"])
anglesi = np.arctan(db["W1"][1:]-db["W1"][:-1])/np.pi*180
angless = np.arctan(db["W2"][1:]-db["W2"][:-1])/np.pi*180
anglesi = np.insert(anglesi, 0, anglesi[0])
angless = np.insert(angless, 0, angless[0])
aniso = (dbgrid["x2"]-db[ind,"W1"]) / (db[ind,"W2"]-db[ind,"W1"])
aniso = anglesi[ind] + aniso * (angless[ind]-anglesi[ind])
ratio = ratio*(db[ind,"W2"]-db[ind,"W1"])/max(db["W2"]-db["W1"])
dbgrid.addColumns(aniso,"aniso")
dbgrid.addColumns(ratio,"ratio")
dbgrid.setLocator("sel",gl.ELoc.SEL)
dbgrid.setLocators(["aniso","ratio"],gl.ELoc.NOSTAT)
dbgrid.display()
Data Base Grid Characteristics ============================== Data Base Summary ----------------- File is organized as a regular grid Space dimension = 2 Number of Columns = 6 Maximum Number of UIDs = 6 Total number of samples = 100000 Number of active samples = 43700 Grid characteristics: --------------------- Origin : 0.000 0.000 Mesh : 1.000 1.000 Number : 500 200 Variables --------- Column = 0 - Name = rank - Locator = NA Column = 1 - Name = x1 - Locator = x1 Column = 2 - Name = x2 - Locator = x2 Column = 3 - Name = sel - Locator = sel Column = 4 - Name = aniso - Locator = nostat1 Column = 5 - Name = ratio - Locator = nostat2
ax = dbgrid.plot("aniso")
ax.decoration(title="Anisotropy Angle")
ax = dbgrid.plot("ratio")
ax.decoration(title="Anisotropy Ratio")
Display the anisotropy maps (on a coarser grid)
Creating the Meshing
mesh = gl.MeshETurbo.createFromGrid(dbgrid, mode=0)
Assigning non-stationarity to the Model
dbcoarse = dbgrid.coarsify([20,20])
nostat = gl.NoStatArray(nostatKeys, dbcoarse)
err = model.addNoStat(nostat)
model.display()
Model characteristics ===================== Space dimension = 2 Number of variable(s) = 1 Number of basic structure(s) = 1 Number of drift function(s) = 0 Number of drift equation(s) = 0 Covariance Part --------------- K-Bessel (Third Parameter = 1) - Sill = 1.000 - Range = 150.000 - Theo. Range = 43.301 Total Sill = 1.000 Non-Stationary Parameters ------------------------- Angle : GRF=1 Str=1 V#1=1 Range : GRF=1 Str=1 V#1=2
ax = gp.modelOnGrid(model=model, db=dbcoarse, scale=50)
ax = gp.grid1D(db,name="W1", color="blue")
ax = gp.grid1D(db,name="W2", color="green")
ax.decoration(title="Layer limits")
nostat = gl.NoStatArray(nostatKeys, dbgrid)
err = model.addNoStat(nostat)
spdeRes = gl.SPDE(model=model,domain=dbgrid,calcul=gl.ESPDECalcMode.SIMUNONCOND, mesh=mesh)
Process the simulation on the output grid and visualize the result (the resulting variable is stored in rank 'iuid' and name 'spde.simu'.
iuid = spdeRes.compute(dbgrid, namconv=gl.NamingConvention("spde",False))
ax = dbgrid.plot("spde.simu")
ax.decoration(title="Non conditional Simulation")
Creating a set of fictitious wells (extracted from the non-conditional simulation)
db_sample = make_well(db,dbgrid,nwell=nwell,vlag=vlag,seed=seedw)
/tmp/ipykernel_37275/3944551499.py:8: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.) /tmp/ipykernel_37275/3944551499.py:9: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
ax = gp.grid1D(db,name="W1", color="blue")
ax = gp.grid1D(db,name="W2", color="green")
ax = gp.point(db_sample, coorY_name="x2")
ax.decoration(title="Layer limits")
spdeRes = gl.SPDE(model=model,domain=dbgrid,data=db_sample,calcul=gl.ESPDECalcMode.KRIGING,mesh=mesh)
spdeRes.setNIterMax(5000)
iuid = spdeRes.compute(dbgrid, namconv=gl.NamingConvention("spde",False))
dbgrid.display()
ax = dbgrid.plot("spde.kriging")
ax.decoration(title="Kriging")
Data Base Grid Characteristics ============================== Data Base Summary ----------------- File is organized as a regular grid Space dimension = 2 Number of Columns = 8 Maximum Number of UIDs = 8 Total number of samples = 100000 Number of active samples = 43700 Grid characteristics: --------------------- Origin : 0.000 0.000 Mesh : 1.000 1.000 Number : 500 200 Variables --------- Column = 0 - Name = rank - Locator = NA Column = 1 - Name = x1 - Locator = x1 Column = 2 - Name = x2 - Locator = x2 Column = 3 - Name = sel - Locator = sel Column = 4 - Name = aniso - Locator = nostat1 Column = 5 - Name = ratio - Locator = nostat2 Column = 6 - Name = spde.simu - Locator = NA Column = 7 - Name = spde.kriging - Locator = z1
spdeRes = gl.SPDE(model=model,domain=dbgrid,data=db_sample,calcul=gl.ESPDECalcMode.SIMUCOND,mesh=mesh)
iuid = spdeRes.compute(dbgrid, namconv=gl.NamingConvention("spde",False))
dbgrid.display()
ax = dbgrid.plot("spde.condSimu")
ax.decoration(title="Conditional Simulation")
Data Base Grid Characteristics ============================== Data Base Summary ----------------- File is organized as a regular grid Space dimension = 2 Number of Columns = 9 Maximum Number of UIDs = 9 Total number of samples = 100000 Number of active samples = 43700 Grid characteristics: --------------------- Origin : 0.000 0.000 Mesh : 1.000 1.000 Number : 500 200 Variables --------- Column = 0 - Name = rank - Locator = NA Column = 1 - Name = x1 - Locator = x1 Column = 2 - Name = x2 - Locator = x2 Column = 3 - Name = sel - Locator = sel Column = 4 - Name = aniso - Locator = nostat1 Column = 5 - Name = ratio - Locator = nostat2 Column = 6 - Name = spde.simu - Locator = NA Column = 7 - Name = spde.kriging - Locator = NA Column = 8 - Name = spde.condSimu - Locator = z1