From f2afbb85d0f7d3e941be1f3948c4b78173e29373 Mon Sep 17 00:00:00 2001
From: Brian Groenke <brian.groenke@awi.de>
Date: Wed, 15 Dec 2021 16:24:47 +0100
Subject: [PATCH] Fix freeW init bug and make porosity a state var

---
 src/Layers/soil.jl                          |  2 ++
 src/Physics/HeatConduction/heat.jl          | 18 ++++++------------
 src/Physics/HeatConduction/soil/sfcc.jl     |  6 +++---
 src/Physics/HeatConduction/soil/soilheat.jl | 18 +++++++++++++++---
 test/Physics/HeatConduction/sfcc_tests.jl   | 20 ++++++++++----------
 5 files changed, 36 insertions(+), 28 deletions(-)

diff --git a/src/Layers/soil.jl b/src/Layers/soil.jl
index cd00f5c5..57e597dd 100644
--- a/src/Layers/soil.jl
+++ b/src/Layers/soil.jl
@@ -67,11 +67,13 @@ end
 # Methods
 porosity(soil::Soil{T,<:SoilCharacteristicFractions}) where T = soilcomp(Val{:θp}(), soil.para)
 variables(::Soil) = (
+    Diagnostic(:θp, Float"1", OnGrid(Cells)), # porosity
     Diagnostic(:θw, Float"1", OnGrid(Cells)), # total water content (xice + saturated pore space)
     Diagnostic(:θm, Float"1", OnGrid(Cells)), # mineral content
     Diagnostic(:θo, Float"1", OnGrid(Cells)), # organic content
 )
 function initialcondition!(soil::Soil{T,<:SoilCharacteristicFractions}, state) where T
+    state.θp .= soilcomp(Val{:θp}(), soil.para)
     state.θw .= soilcomp(Val{:θw}(), soil.para)
     state.θm .= soilcomp(Val{:θm}(), soil.para)
     state.θo .= soilcomp(Val{:θo}(), soil.para)
diff --git a/src/Physics/HeatConduction/heat.jl b/src/Physics/HeatConduction/heat.jl
index e913691e..6ad85006 100644
--- a/src/Physics/HeatConduction/heat.jl
+++ b/src/Physics/HeatConduction/heat.jl
@@ -75,12 +75,6 @@ variables(heat::Heat{<:FreezeCurve,Temperature}) = (
     Diagnostic(:kc, Float"W/m/K", OnGrid(Cells)),
     Diagnostic(:θl, Float"1", OnGrid(Cells)),
 )
-""" Initial condition for heat conduction (all state configurations) on any subsurface layer. """
-function initialcondition!(layer::SubSurface, heat::Heat, state)
-    L = heat.L
-    heatcapacity!(layer, heat, state)
-    @. state.H = enthalpy(state.T, state.C, L, state.θl)
-end
 """ Diagonstic step for heat conduction (all state configurations) on any subsurface layer. """
 function diagnosticstep!(layer::SubSurface, heat::Heat, state)
     # Reset energy flux to zero; this is redundant when H is the prognostic variable
@@ -88,10 +82,10 @@ function diagnosticstep!(layer::SubSurface, heat::Heat, state)
     @. state.dH = zero(eltype(state.dH))
     # Evaluate the freeze curve (updates T, C, and θl)
     fc! = freezecurve(heat);
-    fc!(layer,heat,state)
+    fc!(layer, heat, state)
     # Update thermal conductivity
     thermalconductivity!(layer, heat, state)
-    # Harmonic mean of conductivities
+    # Harmonic mean of inner conductivities
     @inbounds let k = (@view state.k[2:end-1]),
         Δk = Δ(state.grids.k);
         harmonicmean!(k, state.kc, Δk)
@@ -144,7 +138,7 @@ Generic top interaction. Computes flux dH at top cell.
 function interact!(top::Top, bc::BoundaryProcess, sub::SubSurface, heat::Heat, stop, ssub)
     # thermal conductivity at boundary
     # assumes (1) k has already been computed, (2) surface conductivity = cell conductivity
-    @inbounds ssub.k[1] = ssub.k[2]
+    @inbounds ssub.k[1] = ssub.kc[1]
     # boundary flux
     @inbounds ssub.dH[1] += boundaryflux(bc, top, heat, sub, stop, ssub)
     return nothing # ensure no allocation
@@ -155,7 +149,7 @@ Generic bottom interaction. Computes flux dH at bottom cell.
 function interact!(sub::SubSurface, heat::Heat, bot::Bottom, bc::BoundaryProcess, ssub, sbot)
     # thermal conductivity at boundary
     # assumes (1) k has already been computed, (2) bottom conductivity = cell conductivity
-    @inbounds ssub.k[end] = ssub.k[end-1]
+    @inbounds ssub.k[end] = ssub.kc[end]
     # boundary flux
     @inbounds ssub.dH[end] += boundaryflux(bc, bot, heat, sub, sbot, ssub)
     return nothing # ensure no allocation
@@ -192,7 +186,7 @@ total water content (θw), and liquid water content (θl).
 """
 @inline function (fc::FreeWater)(layer::SubSurface, heat::Heat{FreeWater,Enthalpy}, state)
     @inline function enthalpyinv(H, C, L, θtot)
-        let θtot = max(1.0e-8,θtot),
+        let θtot = max(1.0e-8, θtot),
             Lθ = L*θtot,
             I_t = H > Lθ,
             I_f = H <= 0.0;
@@ -200,7 +194,7 @@ total water content (θw), and liquid water content (θl).
         end
     end
     @inline function freezethaw(H, L, θtot)
-        let θtot = max(1.0e-8,θtot),
+        let θtot = max(1.0e-8, θtot),
             Lθ = L*θtot,
             I_t = H > Lθ,
             I_c = (H > 0.0) && (H <= Lθ);
diff --git a/src/Physics/HeatConduction/soil/sfcc.jl b/src/Physics/HeatConduction/soil/sfcc.jl
index 23d4e01f..530905bf 100644
--- a/src/Physics/HeatConduction/soil/sfcc.jl
+++ b/src/Physics/HeatConduction/soil/sfcc.jl
@@ -93,7 +93,7 @@ end
 sfccparams(f::DallAmico, soil::Soil, heat::Heat, state) = (
     f.Tₘ,
     f.θres,
-    porosity(soil), # θ saturated = porosity
+    state.θp, # θ saturated = porosity
     state.θw, # total water content
     heat.L, # specific latent heat of fusion, L
     f.α,
@@ -129,7 +129,7 @@ end
 sfccparams(f::McKenzie, soil::Soil, heat::Heat, state) = (
     f.Tₘ,
     f.θres,
-    porosity(soil), # θ saturated = porosity
+    state.θp, # θ saturated = porosity
     state.θw, # total water content
     f.γ,
 )
@@ -154,7 +154,7 @@ end
 sfccparams(f::Westermann, soil::Soil, heat::Heat, state) = (
     f.Tₘ,
     f.θres,
-    porosity(soil), # θ saturated = porosity
+    state.θp, # θ saturated = porosity
     state.θw, # total water content
     f.δ,
 )
diff --git a/src/Physics/HeatConduction/soil/soilheat.jl b/src/Physics/HeatConduction/soil/soilheat.jl
index 667ebc25..c35eb9b3 100644
--- a/src/Physics/HeatConduction/soil/soilheat.jl
+++ b/src/Physics/HeatConduction/soil/soilheat.jl
@@ -26,11 +26,23 @@ end
 include("sfcc.jl")
 
 """ Initial condition for heat conduction (all state configurations) on soil layer. """
-function initialcondition!(soil::Soil, heat::Heat{<:SFCC}, state)
+function initialcondition!(soil::Soil, heat::Heat, state)
     initialcondition!(soil, state)
     L = heat.L
-    sfcc = freezecurve(heat)
-    state.θl .= sfcc.f.(state.T, sfccparams(sfcc.f, soil, heat, state)...)
+    fc! = freezecurve(heat)
+    fc!(soil, heat, state)
     heatcapacity!(soil, heat, state)
     @. state.H = enthalpy(state.T, state.C, L, state.θl)
 end
+""" Initial condition for heat conduction (all state configurations) with free water freeze curve on soil layer. """
+function initialcondition!(soil::Soil, heat::Heat{FreeWater}, state)
+    initialcondition!(soil, state)
+    L = heat.L
+    # initialize liquid water content based on temperature
+    @. state.θl = ifelse.(state.T > 0.0, 0.0, state.θp)
+    heatcapacity!(soil, heat, state)
+    @. state.H = enthalpy(state.T, state.C, L, state.θl)
+    # evaluate freeze curve
+    fc! = freezecurve(heat)
+    fc!(soil, heat, state)
+end
diff --git a/test/Physics/HeatConduction/sfcc_tests.jl b/test/Physics/HeatConduction/sfcc_tests.jl
index 76ae35a1..2916e4bc 100644
--- a/test/Physics/HeatConduction/sfcc_tests.jl
+++ b/test/Physics/HeatConduction/sfcc_tests.jl
@@ -36,7 +36,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -51,7 +51,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -66,7 +66,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -100,7 +100,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -113,7 +113,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -126,7 +126,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -163,7 +163,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 @inferred sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -176,7 +176,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 @inferred sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -189,7 +189,7 @@ using ComponentArrays
                     C = heatcapacity.(soil,θw,θl,θm,θo);
                    enthalpy.(T,C,L,θl) # compute enthalpy at "true" temperature
                 end
-                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+                state = (T=T,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
                 @inferred sfcc(soil, heat, state)
                 @test all(abs.(T.-(H .- L.*θl)./C) .<= tol)
             end
@@ -219,7 +219,7 @@ using ComponentArrays
             T_ .= T
             C = similar(C,eltype(p))
             θl = similar(θl,eltype(p))
-            state = (T=T_,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T))
+            state = (T=T_,C=C,Ceff=similar(C),H=H,θl=θl,θw=θw.+zero(T),θm=θm.+zero(T),θo=θo.+zero(T),θp=θp.+zero(T))
             SFCC(McKenzie(γ=Param(p.γ[1])))(soil, heat, state)
             state.T[1]
         end
-- 
GitLab