Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add power law strain/stress functions #226

Merged
merged 6 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ConstitutiveRelationships.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export param_info,
# add methods programmatically
for myType in (:LinearViscous, :LinearMeltViscosity, :ViscosityPartialMelt_Costa_etal_2009,
:DiffusionCreep, :DislocationCreep, :ConstantElasticity, :DruckerPrager, :ArrheniusType,
:GrainBoundarySliding, :PeierlsCreep, :NonLinearPeierlsCreep)
:GrainBoundarySliding, :PeierlsCreep, :NonLinearPeierlsCreep, :PowerlawViscous)
@eval begin
@inline compute_εII(a::$(myType), TauII, args) = compute_εII(a, TauII; args...)
@inline compute_εvol(a::$(myType), P, args) = compute_εvol(a, P; args...)
Expand Down
75 changes: 47 additions & 28 deletions src/CreepLaw/CreepLaw.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
where ``\\eta_0`` is the reference viscosity [Pa*s] at reference strain rate ``\\dot{\\varepsilon}_0``[1/s], and ``n`` the power law exponent [].
"""
@with_kw_noshow struct ArrheniusType{_T,U1,U2,U3} <: AbstractCreepLaw{_T}
η_0::GeoUnit{_T,U1} = 1.0NoUnits # Pre-exponential factor
η0::GeoUnit{_T,U1} = 1.0NoUnits # Pre-exponential factor
E_η::GeoUnit{_T,U2} = 23.03NoUnits # Activation energy (non-dimensional)
T_O::GeoUnit{_T,U3} = 1.0NoUnits # Offset temperature
T_η::GeoUnit{_T,U3} = 1.0NoUnits # Reference temperature at which viscosity is unity
Expand All @@ -215,10 +215,11 @@
Equation=L"\tau_{ij} = 2 \eta_0 exp( E_η/(T + T_O) + E_η/(T_η + T_O)) \dot{\varepsilon}_{ij}",
)
end

# Calculation routines for linear viscous rheologies
function compute_εII(a::ArrheniusType, TauII; T=one(precision(a)), kwargs...)
@unpack_val η_0, E_η, T_O, T_η = a
η = η_0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))
@unpack_val η0, E_η, T_O, T_η = a
η = η0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))
return (TauII / η) * 0.5
end

Expand All @@ -241,8 +242,8 @@
end

function dεII_dτII(a::ArrheniusType, TauII; T=one(precision(a)), kwargs...)
@unpack_val η_0, E_η, T_O, T_η = a
η = η_0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))
@unpack_val η0, E_η, T_O, T_η = a
η = η0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))
return 0.5 * inv(η)
end

Expand All @@ -252,9 +253,9 @@
Returns second invariant of the stress tensor given a 2nd invariant of strain rate tensor
"""
function compute_τII(a::ArrheniusType, EpsII; T=one(precision(a)), kwargs...)
@unpack_val η_0, E_η, T_O, T_η = a
@unpack_val η0, E_η, T_O, T_η = a

η = η_0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))
η = η0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))

return 2 * (η * EpsII)
end
Expand All @@ -274,8 +275,8 @@
end

function dτII_dεII(a::ArrheniusType, EpsII; T=one(precision(a)), kwargs...)
@unpack_val η_0, E_η, T_O, T_η = a
η = η_0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))
@unpack_val η0, E_η, T_O, T_η = a
η = η0 * exp(E_η / (T + T_O) - E_η / (T_η + T_O))

return 2 * η
end
Expand All @@ -284,7 +285,7 @@
function show(io::IO, g::ArrheniusType)
return print(
io,
"ArrheniusType: η_0 = $(Value(g.η_0)), E_η = $(Value(g.E_η)), T_O = $(Value(g.T_O)), T_η = $(Value(g.T_η))",
"ArrheniusType: η0 = $(Value(g.η0)), E_η = $(Value(g.E_η)), T_O = $(Value(g.T_O)), T_η = $(Value(g.T_η))",
)
end

Expand All @@ -300,33 +301,51 @@
where ``\\eta`` is the effective viscosity [Pa*s].
"""
@with_kw_noshow struct PowerlawViscous{T,U1,U2,U3} <: AbstractCreepLaw{T}
η0::GeoUnit{T,U1} = 1e18Pa * s # reference viscosity
n::GeoUnit{T,U2} = 2.0 * NoUnits # powerlaw exponent
ε0::GeoUnit{T,U3} = 1e-15 * 1 / s # reference strainrate
η0::GeoUnit{T,U1} = 1e18Pa * s # reference viscosity
n::GeoUnit{T,U2} = 2.0 * NoUnits # powerlaw exponent
ε0::GeoUnit{T,U3} = 1e-15/s # reference strainrate
end
PowerlawViscous(a...) = PowerlawViscous(convert.(GeoUnit, a)...)

# Print info
function show(io::IO, g::PowerlawViscous)
return print(io, "Powerlaw viscosity: η0=$(g.η0.val), n=$(g.n.val), ε0=$(g.ε0.val) ")
end
#-------------------------------------------------------------------------

#=
# add methods programmatically
#for myType in (:LinearViscous, :DiffusionCreep, :DislocationCreep, :ConstantElasticity)
for myType in (:LinearViscous, :DiffusionCreep, :DislocationCreep)

@eval begin
compute_εII(TauII, a::$(myType), args) = compute_εII(TauII, a; args...)
dεII_dτII(TauII, a::$(myType), args) = dεII_dτII(TauII, a; args...)
compute_τII(EpsII, a::$(myType), args) = compute_τII(EpsII, a; args...)
if Symbol($myType) !== :ConstantElasticity
dτII_dεII(EpsII, a::$(myType), args) = dτII_dεII(EpsII, a; args...)
end
end
# Calculation routines for linear viscous rheologies
function compute_εII(a::PowerlawViscous, TauII; kwargs...)
@unpack_val η0, n, ε0 = a

@pow EpsII = (TauII / η0)^(1/n) * ε0

return EpsII
end
=#

function dεII_dτII(a::PowerlawViscous, TauII; kwargs...)
@unpack_val η0, n, ε0 = a

Check warning on line 325 in src/CreepLaw/CreepLaw.jl

View check run for this annotation

Codecov / codecov/patch

src/CreepLaw/CreepLaw.jl#L324-L325

Added lines #L324 - L325 were not covered by tests

return @pow (TauII^((1 - n) / n)) / (n*(η0^(1 / n)))

Check warning on line 327 in src/CreepLaw/CreepLaw.jl

View check run for this annotation

Codecov / codecov/patch

src/CreepLaw/CreepLaw.jl#L327

Added line #L327 was not covered by tests
end

"""
compute_τII(s::PowerlawViscous, EpsII; kwargs...)

Returns second invariant of the stress tensor given a 2nd invariant of strain rate tensor
"""
function compute_τII(a::PowerlawViscous, EpsII; kwargs...)
@unpack_val η0, n, ε0 = a

τII = @pow ε0 * η0 * (EpsII / ε0)^n

return τII
end

function dτII_dεII(a::PowerlawViscous, EpsII; kwargs...)
@unpack_val η0, n, ε0 = a

Check warning on line 344 in src/CreepLaw/CreepLaw.jl

View check run for this annotation

Codecov / codecov/patch

src/CreepLaw/CreepLaw.jl#L343-L344

Added lines #L343 - L344 were not covered by tests

return @pow η0 * EpsII^(n - 1) * (1 / ε0)^n

Check warning on line 346 in src/CreepLaw/CreepLaw.jl

View check run for this annotation

Codecov / codecov/patch

src/CreepLaw/CreepLaw.jl#L346

Added line #L346 was not covered by tests
end
#-------------------------------------------------------------------------

# Help info for the calculation routines
"""
Expand Down
6 changes: 3 additions & 3 deletions src/MeltFraction/MeltingParameterization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ julia> T,phi,dϕdT = PlotMeltFraction(p,T=T);
The same but with smoothening:
```julia
julia> p_s = SmoothMelting(p=MeltingParam_4thOrder(), k_liq=0.21/K);
4th order polynomial melting curve: phi = -7.594512597174117e-10T^4 + 3.469192091489447e-6T^3 + -0.00592352980926T^2 + 4.482855645604745T + -1268.730161921053 963.15 K ≤ T ≤ 1270.15 K with smooth Heaviside function smoothening using k_sol=0.1 K⁻¹·⁰, k_liq=0.11 K⁻¹·
4th order polynomial melting curve: phi = -7.594512597174117e-10T^4 + 3.469192091489447e-6T^3 + -0.00592352980926T^2 + 4.482855645604745T + -1268.730161921053 963.15 K ≤ T ≤ 1270.15 K with smooth Heaviside function smoothening using k_sol=0.1 K⁻¹·⁰, k_liq=0.11 K⁻¹·
julia> T_s,phi_s,dϕdT_s = PlotMeltFraction(p_s,T=T);
```

Expand Down Expand Up @@ -767,7 +767,7 @@ end
Computation of melt fraction ϕ for the whole domain and all phases, in case an array with phase properties `MatParam` is provided, along with `P` and `T` arrays.
"""
compute_meltfraction(args::Vararg{Any,N}) where {N} =
clamp(compute_param(compute_meltfraction, args...), 0e0, 1e0)
clamp(compute_param(compute_meltfraction, args...), 0, 1)

"""
compute_meltfraction(ϕ::AbstractArray{<:AbstractFloat}, Phases::AbstractArray{<:Integer}, P::AbstractArray{<:AbstractFloat},T::AbstractArray{<:AbstractFloat}, MatParam::AbstractArray{<:AbstractMaterialParamsStruct})
Expand Down Expand Up @@ -802,4 +802,4 @@ This is employed, for example, in computing latent heat terms in an implicit man
"""
compute_dϕdT!(args::Vararg{Any,N}) where {N} = compute_param!(compute_dϕdT, args...)

end
end
110 changes: 55 additions & 55 deletions test/test_CreepLaw.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ using GeoParams

x1_ND = LinearViscous(; η=1e18Pa * s)
@test isDimensional(x1_ND) == true
x1_ND = nondimensionalize(x1_ND, CharUnits_GEO) # check that we can nondimensionalize all entries within the struct
x1_ND = nondimensionalize(x1_ND, CharUnits_GEO) # check that we can nondimensionalize all entries within the struct
@test isDimensional(x1_ND) == false
@test x1_ND.η * 1.0 == 0.1
x1_D = dimensionalize(x1_ND, CharUnits_GEO) # check that we can dimensionalize it again
Expand All @@ -53,14 +53,28 @@ using GeoParams
ε = [0.0; 0.0]
compute_τII!(ε, x1_ND, [1e0; 2.0], args)
@test ε == [0.2; 0.4] # vector input

# -------------------------------------------------------------------

# -------------------------------------------------------------------
# Define powerlaw viscous rheology
η0 = 10
n = 2.3
ε0 = 1
x2 = PowerlawViscous(; η0 = 10, n=2.3, ε0 = 1)

τII = 1e0
εII = 1e0

(τII / η0)^(1/n)
@test compute_τII(x2, τII) == η0 * εII^n
@test compute_εII(x2, εII) ≈ (τII / η0)^(1/n)

@test compute_viscosity_εII(x2, τII, (;)) == 5e0
@test compute_viscosity_τII(x2, εII, (;)) == 1.3606693841876538

x2 = PowerlawViscous()
x2 = nondimensionalize(x2, CharUnits_GEO)
@test NumValue(x2.ε0) == 0.001 # powerlaw
@test NumValue(x2.ε0) == 0.001 # powerlaw

# Given strainrate
compute_τII(x1, 1e-13 / s, args)
Expand Down Expand Up @@ -147,33 +161,26 @@ using GeoParams
@test ε ≈ [2.553516169022911e-6; 5.107032338045822e-6] # vector input

# With vector as input
T = Vector(800.0:1400)*K
η_basalt = zeros(size(T))*Pas
T = Vector(800.0:1400)*K
η_basalt = zeros(size(T))*Pas
η_rhyolite = zeros(size(T))*Pas

x_basalt = LinearMeltViscosity()
x_rhyolite = LinearMeltViscosity(A = -8.1590, B = 2.4050e+04K, T0 = -430.9606K) # Rhyolite

for i in eachindex(T)
args_D = (; T = T[i])
η_basalt[i] = compute_viscosity_τII(x_basalt, 1e6Pa, (; T=T[i]))
η_rhyolite[i] = compute_viscosity_τII(x_rhyolite, 1e6Pa, (; T=T[i]))
args_D = (; T = T[i])
η_basalt[i] = compute_viscosity_τII(x_basalt, 1e6Pa, (; T=T[i]))
η_rhyolite[i] = compute_viscosity_τII(x_rhyolite, 1e6Pa, (; T=T[i]))
end

#using Plots
#plot(ustrip.(T) .- 273.15, log10.(ustrip.(η_basalt)), xlabel="T [C]", ylabel="log10(η [Pas])", label="basalt")
#plot!(ustrip.(T) .- 273.15, log10.(ustrip.(η_rhyolite)), label="rhyolite")

args_D=(;T=1000K)
η_basalt1 = compute_viscosity_τII(x_basalt, 1e6Pa, args_D)
@test η_basalt1 ≈ 5.2471745814062805e9Pa*s

η_rhyolite1 = compute_viscosity_τII(x_rhyolite, 1e6Pa, args_D)
args_D = (;T=1000K)
η_basalt1 = compute_viscosity_τII(x_basalt, 1e6Pa, args_D)
@test η_basalt1 ≈ 5.2471745814062805e9Pa*s
η_rhyolite1 = compute_viscosity_τII(x_rhyolite, 1e6Pa, args_D)
@test η_rhyolite1 ≈ 4.445205243727607e8Pa*s
# -------------------------------------------------------------------

# Test effective viscosity of partially molten rocks -----------------

x1_D =ViscosityPartialMelt_Costa_etal_2009(η=LinearMeltViscosity(A = -8.1590, B = 2.4050e+04K, T0 = -430.9606K)) # Rhyolite
@test isDimensional(x1_D) == true
x1_ND = nondimensionalize(x1_D, CharUnits_GEO) # check that we can nondimensionalize all entries within the struct
Expand All @@ -186,71 +193,63 @@ using GeoParams
args_D = (; T = 700K, ϕ=0.5)
args_ND = (; T = nondimensionalize(700K, CharUnits_GEO), ϕ=0.5)

ε_D = compute_εII(x1_D, 1e6Pa, args_D)
@test ε_D 1.5692922423522311e-10 / s # dimensional input
ε_ND = compute_εII(x1_ND, nondimensionalize(1e6Pa, CharUnits_GEO), args_ND)
ε_D = compute_εII(x1_D, 1e6Pa, args_D)
@test ε_D 1.5692922423522311e-10 / s # dimensional input
ε_ND = compute_εII(x1_ND, nondimensionalize(1e6Pa, CharUnits_GEO), args_ND)
@test ε_ND ≈ 156.92922423522444 # non-dimensional
@test ε_ND*CharUnits_GEO.strainrate ≈ ε_D # check that non-dimensiional computations give the same results
@test ε_ND * CharUnits_GEO.strainrate ≈ ε_D # check that non-dimensiional computations give the same results

ε = [0.0; 0.0]
τ = [1e6; 2e6]
args_ND1 = (; T = 1000*ones(size(τ)), ϕ=0.5*ones(size(τ)))
compute_εII!(ε, x1_D, τ, args_ND1)
@test ε ≈ [0.0011248074556411618; 0.0022496149112823235] # vector input


# Given strainrate
@test compute_τII(x1_D, 1e-13 / s, args_D) ≈ 643.9044043803415Pa # dimensional input
@test compute_τII(x1_ND, 1e-13, args_ND) ≈ 5.64401178083053e-17 # non-dimensional
@test compute_τII(x1_ND, 1e-13, args_ND) ≈ 5.64401178083053e-17 # non-dimensional

ε = [0.0; 0.0]
compute_τII!(ε, x1_ND, [1e0; 2.0], args_ND1)
@test ε ≈ [3.65254588484434e-25, 7.305079089024537e-25] # vector input


x1_D = ViscosityPartialMelt_Costa_etal_2009()
args_D=(;T=1000K, ϕ=0.5)
ε_D = compute_εII(x1_D, 1e6Pa, args_D)
@test ustrip(ε_D) ≈ 3.4537433628446676e-6

η = compute_viscosity_τII(x1_D, 1e6Pa, args_D)
@test ustrip(η) ≈ 1.447704555523709e11
x1_D = ViscosityPartialMelt_Costa_etal_2009()
args_D = (;T=1000K, ϕ=0.5)
ε_D = compute_εII(x1_D, 1e6Pa, args_D)
@test ustrip(ε_D) ≈ 3.4537433628446676e-6
η = compute_viscosity_τII(x1_D, 1e6Pa, args_D)
@test ustrip(η) ≈ 1.447704555523709e11

@test dεII_dτII(x1_ND, 1e6, args_ND) ≈ 31884.63277076202
@test dτII_dεII(x1_ND, 1e-15, args_ND) ≈ 0.0005644011780830529

# -----

# ----
# Create plot
T = Vector(800.0:1400)*K
η_basalt = zeros(size(T))*Pas
η_basalt1 = zeros(size(T))*Pas
η_rhyolite = zeros(size(T))*Pas
ϕ_basalt = zeros(size(T))
ϕ_rhyolite = zeros(size(T))

x_basalt = ViscosityPartialMelt_Costa_etal_2009(η = LinearMeltViscosity())
x_rhyolite = ViscosityPartialMelt_Costa_etal_2009(η= LinearMeltViscosity(A = -8.1590, B = 2.4050e+04K, T0 = -430.9606K)) # Rhyolite

mf_basalt = MeltingParam_Smooth3rdOrder()
T = Vector(800.0:1400)*K
η_basalt = zeros(size(T))*Pas
η_basalt1 = zeros(size(T))*Pas
η_rhyolite = zeros(size(T))*Pas
ϕ_basalt = zeros(size(T))
ϕ_rhyolite = zeros(size(T))
x_basalt = ViscosityPartialMelt_Costa_etal_2009(η = LinearMeltViscosity())
x_rhyolite = ViscosityPartialMelt_Costa_etal_2009(η= LinearMeltViscosity(A = -8.1590, B = 2.4050e+04K, T0 = -430.9606K)) # Rhyolite
mf_basalt = MeltingParam_Smooth3rdOrder()
mf_rhyolite = MeltingParam_Smooth3rdOrder( a=3043.0, b=-10552.0, c=12204.9, d = -4709.0 )

εII = 1e-5/s;
for i in eachindex(T)
args_D = (; T = T[i])
ϕ_basalt[i] = compute_meltfraction(mf_basalt, (; T=T[i]/K))
η_basalt[i] = compute_viscosity_εII(x_basalt, εII, (; ϕ=ϕ_basalt[i], T=T[i]))

η_basalt1[i] = compute_viscosity_εII(x_basalt, 1e-3/s, (; ϕ=ϕ_basalt[i], T=T[i]))

args_D = (; T = T[i])
ϕ_basalt[i] = compute_meltfraction(mf_basalt, (; T=T[i]/K))
η_basalt[i] = compute_viscosity_εII(x_basalt, εII, (; ϕ=ϕ_basalt[i], T=T[i]))
η_basalt1[i] = compute_viscosity_εII(x_basalt, 1e-3/s, (; ϕ=ϕ_basalt[i], T=T[i]))
ϕ_rhyolite[i] = compute_meltfraction(mf_rhyolite, (; T=T[i]/K))
η_rhyolite[i] = compute_viscosity_εII(x_rhyolite, εII, (; ϕ=ϕ_rhyolite[i], T=T[i]))
η_rhyolite[i] = compute_viscosity_εII(x_rhyolite, εII, (; ϕ=ϕ_rhyolite[i], T=T[i]))

end
@test mean(η_rhyolite) ≈ 1.26143880075233e19Pas
@test mean(η_basalt) ≈ 5.822731206904198e24Pas
@test mean(η_basalt1) ≈ 8.638313729394237e21Pas
@test mean(η_rhyolite) ≈ 1.2614388007523279e19Pas
@test mean(η_basalt) ≈ 5.822731206904198e24Pas
@test mean(η_basalt1) ≈ 8.638313729394237e21Pas

#=
using Plots
Expand All @@ -269,3 +268,4 @@ using GeoParams


end