Parameter Distributions
By default a realization obtained by an instance of Model will have degenerate distributions of all blob parameters. For any interesting application this is not enough.
In order to provide the highest possible flexibility for setting blob parameters this is done by a separate class, which
should implement BlobFactory. An implementation is provided by DefaultBlobFactory which allows to easily set independent distributions of any blob parameters to a wide range of distribution families.
DefaultBlobFactory
We can use DefaultBlobFactory class in order to change the distribution functions of the following blob parameters:
Amplitudes
widths in x and y
velocities in x and y
pulse shape in x and y
blob alignment and tilt
The distributions for these parameters are set with the *_dist arguments. The following distribution functions are implemented:
“exp” |
exponential distribution with mean 1 |
“gamma” |
gamma distribution with |
“normal” |
normal distribution with zero mean and |
“uniform” |
uniform distribution with mean 1 and |
“ray” |
Rayleight distribution with mean 1 |
“deg” |
degenerate distribution at |
“zeros” |
array of zeros |
As you can see, some of these distributions require an additional free_parameter to specify the distribution.
This is done by the *_parameter arguments.
Let’s take a look at an example. Let’s assume we want to sample the blob amplitudes from normal distribution with 5 as the scale parameter. We chose the defualt distributions for all other blob parameters. We would set up the Model as follows:
from blobmodel import DefaultBlobFactory, DistributionEnum, Model
my_blob_factory = DefaultBlobFactory(A_dist=DistributionEnum.normal, A_parameter=5)
bm = Model(
Nx=10,
Ny=10,
Lx=10,
Ly=10,
dt=0.1,
T=20,
blob_factory=my_blob_factory,
t_drain=100,
num_blobs=100,
)
ds = bm.make_realization()
CustomBlobFactory
But what if you want to use a distribution function that is not implemented? Or maybe you even want to change the initial position and arrival time of each blob?
In this case you can use the CustomBlobFactory class to define all blob parameters individually. An example could look like this:
from blobmodel import BlobFactory, AbstractBlobShape, Blob, Model
import numpy as np
class CustomBlobFactory(BlobFactory):
def __init__(self) -> None:
pass
def sample_blobs(
self,
Ly: float,
T: float,
num_blobs: int,
blob_shape: AbstractBlobShape,
t_drain: float,
) -> list[Blob]:
# set custom parameter distributions
amp = np.linspace(0.01, 1, num=num_blobs)
width = np.linspace(0.01, 1, num=num_blobs)
vx = np.linspace(0.01, 1, num=num_blobs)
vy = np.linspace(0.01, 1, num=num_blobs)
posx = np.zeros(num_blobs)
posy = np.random.uniform(low=0.0, high=Ly, size=num_blobs)
t_init = np.random.uniform(low=0, high=T, size=num_blobs)
# sort blobs by _t_init
t_init = np.sort(t_init)
return [
Blob(
blob_id=i,
blob_shape=blob_shape,
amplitude=amp[i],
width_prop=width[i],
width_perp=width[i],
v_x=vx[i],
v_y=vy[i],
pos_x=posx[i],
pos_y=posy[i],
t_init=t_init[i],
t_drain=t_drain,
)
for i in range(num_blobs)
]
def is_one_dimensional(self) -> bool:
return False
bf = CustomBlobFactory()
tmp = Model(
Nx=10,
Ny=10,
Lx=2,
Ly=2,
dt=0.1,
T=10,
t_drain=2,
periodic_y=True,
num_blobs=10,
blob_factory=bf,
)
ds = tmp.make_realization()
By assigning an array like to the variables amp, width, vx, vy, posx, posy and t_init we can exactly define every single blob parameter of every single blob.
Note
When using CustomBlobFactory it is your responsibility to make sure all blob variables have the correct dimensions. Also, if you wish to normalize the parameters you have to do this manually.