Skip to content

Porosity.jl : Introduction ​

Modeling ​

Modeling for all the functions can be done by calling the forward function on the rock physics models.

A very simple example is estimating log conductivity using SEO3, a temperature dependent conductivity law for olivine developed by Constable, 2003.

Construct the model by passing the needed arguments, here temperature.

julia
T = 1000 + 273.0
model_SEO3 = SEO3(T)
Model : SEO3
Temperature (K) : 1273.0

and then calling forward on it

julia
forward(model_SEO3, [])
Rock physics Response : RockphyCond
log₁₀ conductivity (S/m) : -4.0571856119909375

The [] argument is needed to make the interface consistent. It is not used anywhere, and you can pass any value to it.

You can pass a whole vector for temperature and get the result :

julia
T = (800:100:1200) .+ 273.0
model_SEO3 = SEO3(T)
forward(model_SEO3, [])
Rock physics Response : RockphyCond
log₁₀ conductivity (S/m) : [-5.306504142685108, -4.6390804189895904, -4.0571856119909375, -3.5353287988452404, -3.042294586618032]

Dimensions ​

Dimensions for all the rock physics types follow the broadcasting rule, that is, if there are two parameters, one with shape (11,1) and other with (1, 4) then the output/s will be of (11, 4). This is useful when you want to get the output for multiple values. You can obviously iterate, but broadcasting would be usually faster, e.g.:

julia
T = (600:100:1600) .+ 273.0
P = 2.0
dg = [1.0, 3.0, 10.0, 30.0]'
σ = 10e-3
ϕ = 0.015

m = HZK2011(T, P, dg, σ, ϕ)
resp = forward(m, []);
println("size of T : ", size(T))
println("size of broadcasted array (same as output): ", size(T .+ P .+ dg .+ σ .+ ϕ)) #
println("size of ϵ_rate : ", size(resp.ϵ_rate))
println("size of η : ", size(resp.η))
size of T : (11,)
size of broadcasted array (same as output): (11, 4)
size of ϵ_rate : (11, 4)
size of η : (11, 4)

Notice that the dimensions of T and dg were (11,1) and (1, 4) respectively and the output shapes are (11, 4).

Of course, simple broadcasting rules dictate that if T were of (11,1) (or (11,)) and so were dg, then the output would be (11, 1) (or (11,)), e.g.:

julia
T = (600:100:1600) .+ 273.0
P = 2.0 .+ zero(T) # same size as T
dg = collect(range(0.1; stop=30.0, length=length(T))) # same size as T
σ = 10e-3
ϕ = 0.015

m = HZK2011(T, P, dg, σ, ϕ)
resp = forward(m, []);

println("size of T : ", size(T))
println("size of P : ", size(P))
println("size of broadcasted array (same as output): ", size(T .+ P .+ dg .+ σ .+ ϕ))
println("size of ϵ_rate : ", size(resp.ϵ_rate))
println("size of η : ", size(resp.η))
size of T : (11,)
size of P : (11,)
size of broadcasted array (same as output): (11,)
size of ϵ_rate : (11,)
size of η : (11,)

Anelastic case ​

For anelastic types, one of the input arguments is frequency f. Make sure the f is of the size one more than the dimensions of other values. e.g.:

julia
T = (600:100:1400) .+ 273.0
P = 0.2
dg = 3.1
σ = 10.0 * 1.0f-3
ϕ = 0.0
ρ = 3300.0
T_solidus = 1100 + 273.0

f = 10 .^ -collect(range(-2, 4; length=100))'

m = premelt_anelastic(T, P, dg, σ, ϕ, ρ, 0.0, T_solidus, f)
resp = forward(m, [])

println("size of T : ", size(T))
println("size of P : ", size(P))
println("size of broadcasted array without f: ", size(T .+ P .+ dg .+ σ .+ ϕ .+ ρ .+
                                                      T_solidus))
println("size of f : ", size(f))
println("size of Qinv (one of the outputs, averaged over frequency) : ", size(resp.Qinv))
size of T : (9,)
size of P : ()
size of broadcasted array without f: (9,)
size of f : (1, 100)
size of Qinv (one of the outputs, averaged over frequency) : (9, 100)
julia
T = reshape((600:100:1400) .+ 273.0, :, 1, 1)
P = 0.2
dg = reshape(3.0:10.0, 1, :, 1)
σ = 10.0 * 1.0f-3
ϕ = 0.0
ρ = 3300.0
T_solidus = 1100 + 273.0

f = 10 .^ -reshape(collect(range(-2, 4; length=100)), 1, 1, :)

m = premelt_anelastic(T, P, dg, σ, ϕ, ρ, 0.0, T_solidus, f)
resp = forward(m, [])

println("size of T : ", size(T))
println("size of P : ", size(P))
println("size of broadcasted array without f (same as output): ",
    size(T .+ P .+ dg .+ σ .+ ϕ .+ ρ .+ T_solidus))
println("size of f : ", size(f))
println("size of Qinv (one of the outputs) : ", size(resp.Qinv))
println("size of Vave (one of the outputs, averaged over frequency) : ", size(resp.Vave))
size of T : (9, 1, 1)
size of P : ()
size of broadcasted array without f (same as output): (9, 8, 1)
size of f : (1, 1, 100)
size of Qinv (one of the outputs) : (9, 8, 100)
size of Vave (one of the outputs, averaged over frequency) : (9, 8)

Changing initial parameters ​

A lot of rock physics models have empirical constants on defined physical laws from lab experiments. The forward function has a keyword argument params which has default value for these constants. These default parameters can be observed by default_params function dispatched on the rock physics type, e.g.:

julia
default_ps_SEO3 = default_params(SEO3)
(S_bfe = 5.06f24, H_bfe = 0.357f0, S_bmg = 4.58f26, H_bmg = 0.752f0, S_ufe = 1.22f-5, H_ufe = 1.05f0, S_umg = 2.72f-6, H_umg = 1.09f0)

These default values are used by default for all the rock physics models. The forward function implicitly calls these default parameters

julia
T = 1000 + 273.0
m = SEO3(T)
forward(m, [])
Rock physics Response : RockphyCond
log₁₀ conductivity (S/m) : -4.0571856119909375

Above is same as :

julia
T = 1000 + 273.0
m = SEO3(T)
forward(m, [], default_ps_SEO3)
Rock physics Response : RockphyCond
log₁₀ conductivity (S/m) : -4.0571856119909375

If you want to use different values for certain laws, you need to create another params object, eg. Let's change S_bfe and S_bmg to different values :

julia
new_params_SEO3 = (; default_ps_SEO3..., S_bfe=1.06f24, S_umg=1.58f26)
(S_bfe = 1.06f24, H_bfe = 0.357f0, S_bmg = 4.58f26, H_bmg = 0.752f0, S_ufe = 1.22f-5, H_ufe = 1.05f0, S_umg = 1.58f26, H_umg = 1.09f0)

and then we should see a different output

julia
T = 1000 + 273.0
m = SEO3(T)
forward(m, [], new_params_SEO3)
Rock physics Response : RockphyCond
log₁₀ conductivity (S/m) : 27.104268999871497

Notice the change in outputs from forward. More complicated examples of changing initial parameters are presented in Andrade pseudospectral modeling and Extended Burgers modeling

In-place operations ​

We do not support in-place operations for rock physics models currently. The rock physics models are generally simple and fast, and the effort to make them allocation-free might not be substantial but watch this space in future for in-place (mutating) functions.