Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
Summa Actors
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Numerical_Simulations_Lab
Actors
Summa Actors
Commits
7d434e85
Commit
7d434e85
authored
2 years ago
by
Kyle
Browse files
Options
Downloads
Patches
Plain Diff
copied from summa non actors
parent
b207f014
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
build/source/engine/sundials/soil_utilsAddSundials.f90
+161
-170
161 additions, 170 deletions
build/source/engine/sundials/soil_utilsAddSundials.f90
with
161 additions
and
170 deletions
build/source/engine/sundials/soil_utilsAddSundials.f90
+
161
−
170
View file @
7d434e85
...
...
@@ -20,216 +20,207 @@
module
soil_utilsAddSundials_module
! data types
USE
nrtype
USE
multiconst
,
only
:
gravity
,
&
! acceleration of gravity (m s-2)
Tfreeze
,
&
! temperature at freezing (K)
LH_fus
,
&
! latent heat of fusion (J kg-1, or m2 s-2)
R_wv
! gas constant for water vapor (J kg-1 K-1; [J = Pa m3])
USE
soil_utils_module
,
only
:
matricHead
USE
soil_utils_module
,
only
:
dPsi_dTheta
USE
soil_utils_module
,
only
:
volFracLiq
USE
soil_utils_module
,
only
:
dTheta_dPsi
! privacy
! data types
USE
nrtype
USE
multiconst
,
only
:
gravity
,
&
! acceleration of gravity (m s-2)
Tfreeze
,
&
! temperature at freezing (K)
LH_fus
,
&
! latent heat of fusion (J kg-1, or m2 s-2)
R_wv
! gas constant for water vapor (J kg-1 K-1; [J = Pa m3])
USE
soil_utils_module
,
only
:
matricHead
USE
soil_utils_module
,
only
:
dPsi_dTheta
USE
soil_utils_module
,
only
:
volFracLiq
USE
soil_utils_module
,
only
:
dTheta_dPsi
! privacy
implicit
none
private
! routines to make public
public
::
liquidHeadSundials
public
::
d2Theta_dPsi2
public
::
d2Theta_dTk2
! constant parameters
real
(
rkind
),
parameter
::
verySmall
=
epsilon
(
1.0_rkind
)
! a very small number (used to avoid divide by zero)
contains
! ******************************************************************************************************************************
! public subroutine: compute the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
! ******************************************************************************************************************************
subroutine
liquidHeadSundials
(&
! input
matricHeadTotal
,&
! intent(in) : total water matric potential (m)
matricHeadTotalPrime
,&
! intent(in)
volFracLiq
,&
! intent(in) : volumetric fraction of liquid water (-)
volFracIce
,&
! intent(in) : volumetric fraction of ice (-)
vGn_alpha
,
vGn_n
,
theta_sat
,
theta_res
,
vGn_m
,&
! intent(in) : soil parameters
dVolTot_dPsi0
,&
! intent(in) : derivative in the soil water characteristic (m-1)
dTheta_dT
,&
! intent(in) : derivative in volumetric total water w.r.t. temperature (K-1)
tempPrime
,&
! intent(in)
volFracLiqPrime
,&
! intent(in)
volFracIcePrime
,&
! intent(in)
! output
matricHeadLiq
,&
! intent(out) : liquid water matric potential (m)
matricHeadLiqPrime
,&
! intent(out)
dPsiLiq_dPsi0
,&
! intent(out) : derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
dPsiLiq_dTemp
,&
! intent(out) : derivative in the liquid water matric potential w.r.t. temperature (m K-1)
err
,
message
)
! intent(out) : error control
! computes the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
implicit
none
private
! routines to make public
public
::
liquidHeadSundials
public
::
d2Theta_dPsi2
public
::
d2Theta_dTk2
! constant parameters
real
(
rkind
),
parameter
::
verySmall
=
epsilon
(
1.0_rkind
)
! a very small number (used to avoid divide by zero)
contains
! ******************************************************************************************************************************
! public subroutine: compute the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
! ******************************************************************************************************************************
subroutine
liquidHeadSundials
(&
! input
matricHeadTotal
,&
! intent(in) : total water matric potential (m)
matricHeadTotalPrime
,&
! intent(in)
volFracLiq
,&
! intent(in) : volumetric fraction of liquid water (-)
volFracIce
,&
! intent(in) : volumetric fraction of ice (-)
vGn_alpha
,
vGn_n
,
theta_sat
,
theta_res
,
vGn_m
,&
! intent(in) : soil parameters
dVolTot_dPsi0
,&
! intent(in) : derivative in the soil water characteristic (m-1)
dTheta_dT
,&
! intent(in) : derivative in volumetric total water w.r.t. temperature (K-1)
tempPrime
,&
! intent(in)
volFracLiqPrime
,&
! intent(in)
volFracIcePrime
,&
! intent(in)
! output
matricHeadLiq
,&
! intent(out) : liquid water matric potential (m)
matricHeadLiqPrime
,&
! intent(out)
dPsiLiq_dPsi0
,&
! intent(out) : derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
dPsiLiq_dTemp
,&
! intent(out) : derivative in the liquid water matric potential w.r.t. temperature (m K-1)
err
,
message
)
! intent(out) : error control
! computes the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
implicit
none
! input
real
(
rkind
),
intent
(
in
)
::
matricHeadTotal
! total water matric potential (m)
real
(
rkind
),
intent
(
in
)
::
matricHeadTotalPrime
real
(
rkind
),
intent
(
in
)
::
volFracLiq
! volumetric fraction of liquid water (-)
real
(
rkind
),
intent
(
in
)
::
volFracIce
! volumetric fraction of ice (-)
real
(
rkind
),
intent
(
in
)
::
vGn_alpha
,
vGn_n
,
theta_sat
,
theta_res
,
vGn_m
! soil parameters
real
(
rkind
),
intent
(
in
)
,
optional
::
dVolTot_dPsi0
! derivative in the soil water characteristic (m-1)
real
(
rkind
),
intent
(
in
)
,
optional
::
dTheta_dT
! derivative in volumetric total water w.r.t. temperature (K-1)
real
(
rkind
),
intent
(
in
)
::
TempPrime
real
(
rkind
),
intent
(
in
)
::
volFracLiqPrime
real
(
rkind
),
intent
(
in
)
::
volFracIcePrime
! output
real
(
rkind
),
intent
(
out
)
::
matricHeadLiq
! liquid water matric potential (m)
real
(
rkind
),
intent
(
out
)
::
matricHeadLiqPrime
real
(
rkind
),
intent
(
out
)
,
optional
::
dPsiLiq_dPsi0
! derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
real
(
rkind
),
intent
(
out
)
,
optional
::
dPsiLiq_dTemp
! derivative in the liquid water matric potential w.r.t. temperature (m K-1)
! output: error control
integer
(
i4b
),
intent
(
out
)
::
err
! error code
character
(
*
),
intent
(
out
)
::
message
! error message
! local
real
(
rkind
)
::
xNum
,
xDen
! temporary variables (numeratir, denominator)
real
(
rkind
)
::
effSat
! effective saturation (-)
real
(
rkind
)
::
dPsiLiq_dEffSat
! derivative in liquid water matric potential w.r.t. effective saturation (m)
real
(
rkind
)
::
dEffSat_dTemp
! derivative in effective saturation w.r.t. temperature (K-1)
real
(
rkind
)
::
dEffSat_dFracLiq
real
(
rkind
)
::
effSatPrime
! ------------------------------------------------------------------------------------------------------------------------------
! initialize error control
err
=
0
;
message
=
'liquidHeadSundials/'
! ** partially frozen soil
if
(
volFracIce
>
verySmall
.and.
matricHeadTotal
<
0._rkind
)
then
! check that ice exists and that the soil is unsaturated
! input
real
(
rkind
),
intent
(
in
)
::
matricHeadTotal
! total water matric potential (m)
real
(
rkind
),
intent
(
in
)
::
matricHeadTotalPrime
real
(
rkind
),
intent
(
in
)
::
volFracLiq
! volumetric fraction of liquid water (-)
real
(
rkind
),
intent
(
in
)
::
volFracIce
! volumetric fraction of ice (-)
real
(
rkind
),
intent
(
in
)
::
vGn_alpha
,
vGn_n
,
theta_sat
,
theta_res
,
vGn_m
! soil parameters
real
(
rkind
),
intent
(
in
)
,
optional
::
dVolTot_dPsi0
! derivative in the soil water characteristic (m-1)
real
(
rkind
),
intent
(
in
)
,
optional
::
dTheta_dT
! derivative in volumetric total water w.r.t. temperature (K-1)
real
(
rkind
),
intent
(
in
)
::
TempPrime
real
(
rkind
),
intent
(
in
)
::
volFracLiqPrime
real
(
rkind
),
intent
(
in
)
::
volFracIcePrime
! output
real
(
rkind
),
intent
(
out
)
::
matricHeadLiq
! liquid water matric potential (m)
real
(
rkind
),
intent
(
out
)
::
matricHeadLiqPrime
real
(
rkind
),
intent
(
out
)
,
optional
::
dPsiLiq_dPsi0
! derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
real
(
rkind
),
intent
(
out
)
,
optional
::
dPsiLiq_dTemp
! derivative in the liquid water matric potential w.r.t. temperature (m K-1)
! output: error control
integer
(
i4b
),
intent
(
out
)
::
err
! error code
character
(
*
),
intent
(
out
)
::
message
! error message
! local
real
(
rkind
)
::
xNum
,
xDen
! temporary variables (numeratir, denominator)
real
(
rkind
)
::
effSat
! effective saturation (-)
real
(
rkind
)
::
dPsiLiq_dEffSat
! derivative in liquid water matric potential w.r.t. effective saturation (m)
real
(
rkind
)
::
dEffSat_dTemp
! derivative in effective saturation w.r.t. temperature (K-1)
real
(
rkind
)
::
dEffSat_dFracLiq
real
(
rkind
)
::
effSatPrime
! ------------------------------------------------------------------------------------------------------------------------------
! initialize error control
err
=
0
;
message
=
'liquidHeadSundials/'
! ** partially frozen soil
if
(
volFracIce
>
verySmall
.and.
matricHeadTotal
<
0._rkind
)
then
! check that ice exists and that the soil is unsaturated
! -----
! - compute liquid water matric potential...
! ------------------------------------------
! - compute effective saturation
! NOTE: include ice content as part of the solid porosity - major effect of ice is to reduce the pore size; ensure that effSat=1 at saturation
! (from Zhao et al., J. Hydrol., 1997: Numerical analysis of simultaneous heat and mass transfer...)
xNum
=
volFracLiq
-
theta_res
xDen
=
theta_sat
-
volFracIce
-
theta_res
effSat
=
xNum
/
xDen
! effective saturation
! - matric head associated with liquid water
matricHeadLiq
=
matricHead
(
effSat
,
vGn_alpha
,
0._rkind
,
1._rkind
,
vGn_n
,
vGn_m
)
! argument is effective saturation, so theta_res=0 and theta_sat=1
if
(
effSat
<
1._rkind
.and.
effSat
>
0._rkind
)
then
effSatPrime
=
(
volFracLiqPrime
*
xDen
+
volFracIcePrime
*
xNum
)
/
xDen
**
2._rkind
matricHeadLiqPrime
=
-
(
1._rkind
/(
vGn_alpha
*
vGn_n
*
vGn_m
)
)
*
effSat
**
(
-1._rkind-1._rkind
/
vGn_m
)
*
(
effSat
**
(
-1._rkind
/
vGn_m
)
-
1._rkind
)
**
(
-1._rkind+1._rkind
/
vGn_n
)
*
effSatPrime
else
matricHeadLiqPrime
=
0._rkind
matricHeadLiqPrime
=
0._rkind
endif
! compute derivative in liquid water matric potential w.r.t. effective saturation (m)
if
(
present
(
dPsiLiq_dPsi0
)
.or.
present
(
dPsiLiq_dTemp
))
then
dPsiLiq_dEffSat
=
dPsi_dTheta
(
effSat
,
vGn_alpha
,
0._rkind
,
1._rkind
,
vGn_n
,
vGn_m
)
dPsiLiq_dEffSat
=
dPsi_dTheta
(
effSat
,
vGn_alpha
,
0._rkind
,
1._rkind
,
vGn_n
,
vGn_m
)
endif
! -----
! - compute derivative in the liquid water matric potential w.r.t. the total water matric potential...
! ----------------------------------------------------------------------------------------------------
! check if the derivative is desired
if
(
present
(
dPsiLiq_dTemp
))
then
! (check required input derivative is present)
if
(
.not.
present
(
dVolTot_dPsi0
))
then
message
=
trim
(
message
)//
'dVolTot_dPsi0 argument is missing'
err
=
20
;
return
endif
! (compute derivative in the liquid water matric potential w.r.t. the total water matric potential)
dPsiLiq_dPsi0
=
dVolTot_dPsi0
*
dPsiLiq_dEffSat
*
xNum
/(
xDen
**
2._rkind
)
! matricHeadLiqPrime = dPsiLiq_dPsi0 * matricHeadTotalPrime
! (check required input derivative is present)
if
(
.not.
present
(
dVolTot_dPsi0
))
then
message
=
trim
(
message
)//
'dVolTot_dPsi0 argument is missing'
err
=
20
;
return
endif
! (compute derivative in the liquid water matric potential w.r.t. the total water matric potential)
dPsiLiq_dPsi0
=
dVolTot_dPsi0
*
dPsiLiq_dEffSat
*
xNum
/(
xDen
**
2._rkind
)
endif
! if dPsiLiq_dTemp is desired
! -----
! - compute the derivative in the liquid water matric potential w.r.t. temperature...
! -----------------------------------------------------------------------------------
! check if the derivative is desired
if
(
present
(
dPsiLiq_dTemp
))
then
! (check required input derivative is present)
if
(
.not.
present
(
dTheta_dT
))
then
message
=
trim
(
message
)//
'dTheta_dT argument is missing'
err
=
20
;
return
endif
! (compute the derivative in the liquid water matric potential w.r.t. temperature)
dEffSat_dTemp
=
-
dTheta_dT
*
xNum
/(
xDen
**
2._rkind
)
+
dTheta_dT
/
xDen
dPsiLiq_dTemp
=
dPsiLiq_dEffSat
*
dEffSat_dTemp
! matricHeadLiqPrime = dPsiLiq_dTemp * tempPrime
! (check required input derivative is present)
if
(
.not.
present
(
dTheta_dT
))
then
message
=
trim
(
message
)//
'dTheta_dT argument is missing'
err
=
20
;
return
endif
! (compute the derivative in the liquid water matric potential w.r.t. temperature)
dEffSat_dTemp
=
-
dTheta_dT
*
xNum
/(
xDen
**
2._rkind
)
+
dTheta_dT
/
xDen
dPsiLiq_dTemp
=
dPsiLiq_dEffSat
*
dEffSat_dTemp
endif
! if dPsiLiq_dTemp is desired
! ** unfrozen soil
else
! (no ice)
! ** unfrozen soil
else
! (no ice)
matricHeadLiq
=
matricHeadTotal
matricHeadLiqPrime
=
matricHeadTotalPrime
if
(
present
(
dPsiLiq_dTemp
))
dPsiLiq_dPsi0
=
1._rkind
! derivative=1 because values are identical
if
(
present
(
dPsiLiq_dTemp
))
dPsiLiq_dTemp
=
0._rkind
! derivative=0 because no impact of temperature for unfrozen conditions
end
if
! (if ice exists)
end
subroutine
liquidHeadSundials
! ******************************************************************************************************************************
! public function d2Theta_dPsi2: compute the second derivative of the soil water characteristic (m-1)
! ******************************************************************************************************************************
function
d2Theta_dPsi2
(
psi
,
alpha
,
theta_res
,
theta_sat
,
n
,
m
)
implicit
none
real
(
rkind
),
intent
(
in
)
::
psi
! soil water suction (m)
real
(
rkind
),
intent
(
in
)
::
alpha
! scaling parameter (m-1)
real
(
rkind
),
intent
(
in
)
::
theta_res
! residual volumetric water content (-)
real
(
rkind
),
intent
(
in
)
::
theta_sat
! porosity (-)
real
(
rkind
),
intent
(
in
)
::
n
! vGn "n" parameter (-)
real
(
rkind
),
intent
(
in
)
::
m
! vGn "m" parameter (-)
real
(
rkind
)
::
d2Theta_dPsi2
! derivative of the soil water characteristic (m-1)
real
(
rkind
)
::
mult_fcn
real
(
rkind
)
::
mult_fcnp
if
(
psi
<
0._rkind
)
then
end
if
! (if ice exists)
end
subroutine
liquidHeadSundials
! ******************************************************************************************************************************
! public function d2Theta_dPsi2: compute the second derivative of the soil water characteristic (m-1)
! ******************************************************************************************************************************
function
d2Theta_dPsi2
(
psi
,
alpha
,
theta_res
,
theta_sat
,
n
,
m
)
implicit
none
real
(
rkind
),
intent
(
in
)
::
psi
! soil water suction (m)
real
(
rkind
),
intent
(
in
)
::
alpha
! scaling parameter (m-1)
real
(
rkind
),
intent
(
in
)
::
theta_res
! residual volumetric water content (-)
real
(
rkind
),
intent
(
in
)
::
theta_sat
! porosity (-)
real
(
rkind
),
intent
(
in
)
::
n
! vGn "n" parameter (-)
real
(
rkind
),
intent
(
in
)
::
m
! vGn "m" parameter (-)
real
(
rkind
)
::
d2Theta_dPsi2
! derivative of the soil water characteristic (m-1)
real
(
rkind
)
::
mult_fcn
real
(
rkind
)
::
mult_fcnp
if
(
psi
<
0._rkind
)
then
mult_fcn
=
(
-
m
*
n
*
alpha
*
(
alpha
*
psi
)
**
(
n
-1._rkind
))
*
(
1._rkind
+
(
psi
*
alpha
)
**
n
)
**
(
-1._rkind
)
mult_fcnp
=
-
m
*
n
*
alpha
*
(
n
-1._rkind
)
*
alpha
*
(
alpha
*
psi
)
**
(
n
-2._rkind
)
*
(
1._rkind
+
(
psi
*
alpha
)
**
n
)
**
(
-1._rkind
)
-
&
(
n
*
alpha
*
(
alpha
*
psi
)
**
(
n
-1._rkind
)
*
(
1._rkind
+
(
psi
*
alpha
)
**
n
)
**
(
-2._rkind
)
)
*
(
-
m
*
n
*
alpha
*
(
alpha
*
psi
)
**
(
n
-1._rkind
)
)
d2Theta_dPsi2
=
mult_fcn
*
dTheta_dPsi
(
psi
,
alpha
,
theta_res
,
theta_sat
,
n
,
m
)
+
&
mult_fcnp
*
(
volFracLiq
(
psi
,
alpha
,
theta_res
,
theta_sat
,
n
,
m
)
-
theta_res
)
else
else
d2Theta_dPsi2
=
0._rkind
end
if
end
function
d2Theta_dPsi2
! ******************************************************************************************************************************
! public function d2Theta_dTk2: differentiate the freezing curve w.r.t. temperature
! ******************************************************************************************************************************
function
d2Theta_dTk2
(
Tk
,
theta_res
,
theta_sat
,
alpha
,
n
,
m
)
implicit
none
real
(
rkind
),
intent
(
in
)
::
Tk
! temperature (K)
real
(
rkind
),
intent
(
in
)
::
theta_res
! residual liquid water content (-)
real
(
rkind
),
intent
(
in
)
::
theta_sat
! porosity (-)
real
(
rkind
),
intent
(
in
)
::
alpha
! vGn scaling parameter (m-1)
real
(
rkind
),
intent
(
in
)
::
n
! vGn "n" parameter (-)
real
(
rkind
),
intent
(
in
)
::
m
! vGn "m" parameter (-)
real
(
rkind
)
::
d2Theta_dTk2
! derivative of the freezing curve w.r.t. temperature (K-1)
! local variables
real
(
rkind
)
::
kappa
! constant (m K-1)
real
(
rkind
)
::
xtemp
! alpha*kappa*(Tk-Tfreeze) -- dimensionless variable (used more than once)
! compute kappa (m K-1)
kappa
=
LH_fus
/(
gravity
*
Tfreeze
)
! NOTE: J = kg m2 s-2
! define a tempory variable that is used more than once (-)
xtemp
=
alpha
*
kappa
*
(
Tk
-
Tfreeze
)
! differentiate the freezing curve w.r.t. temperature -- making use of the chain rule
d2Theta_dTk2
=
(
-
alpha
*
kappa
*
m
*
n
*
alpha
*
kappa
)
*
(
theta_sat
-
theta_res
)
*
(
(
n
-1
)
*
xtemp
**
(
n
-
2._rkind
)
*
(
1._rkind
+
xtemp
**
n
)
**
(
-
m
-
1._rkind
)
&
end
if
end
function
d2Theta_dPsi2
! ******************************************************************************************************************************
! public function d2Theta_dTk2: differentiate the freezing curve w.r.t. temperature
! ******************************************************************************************************************************
function
d2Theta_dTk2
(
Tk
,
theta_res
,
theta_sat
,
alpha
,
n
,
m
)
implicit
none
real
(
rkind
),
intent
(
in
)
::
Tk
! temperature (K)
real
(
rkind
),
intent
(
in
)
::
theta_res
! residual liquid water content (-)
real
(
rkind
),
intent
(
in
)
::
theta_sat
! porosity (-)
real
(
rkind
),
intent
(
in
)
::
alpha
! vGn scaling parameter (m-1)
real
(
rkind
),
intent
(
in
)
::
n
! vGn "n" parameter (-)
real
(
rkind
),
intent
(
in
)
::
m
! vGn "m" parameter (-)
real
(
rkind
)
::
d2Theta_dTk2
! derivative of the freezing curve w.r.t. temperature (K-1)
! local variables
real
(
rkind
)
::
kappa
! constant (m K-1)
real
(
rkind
)
::
xtemp
! alpha*kappa*(Tk-Tfreeze) -- dimensionless variable (used more than once)
! compute kappa (m K-1)
kappa
=
LH_fus
/(
gravity
*
Tfreeze
)
! NOTE: J = kg m2 s-2
! define a tempory variable that is used more than once (-)
xtemp
=
alpha
*
kappa
*
(
Tk
-
Tfreeze
)
! differentiate the freezing curve w.r.t. temperature -- making use of the chain rule
d2Theta_dTk2
=
(
-
alpha
*
kappa
*
m
*
n
*
alpha
*
kappa
)
*
(
theta_sat
-
theta_res
)
*
(
(
n
-1
)
*
xtemp
**
(
n
-
2._rkind
)
*
(
1._rkind
+
xtemp
**
n
)
**
(
-
m
-
1._rkind
)
&
+
n
*
(
-
m
-1
)
*
xtemp
**
(
2
*
n
-
2._rkind
)
*
(
1._rkind
+
xtemp
**
n
)
**
(
-
m
-
2._rkind
)
)
end
function
d2Theta_dTk2
end
module
soil_utilsAddSundials_module
\ No newline at end of file
end
function
d2Theta_dTk2
end
module
soil_utilsAddSundials_module
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment