-
Notifications
You must be signed in to change notification settings - Fork 6
/
calculateBoundaryConditions.m
116 lines (107 loc) · 5.92 KB
/
calculateBoundaryConditions.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
function [AVAIL0, RHS, HeatMatrices, Precip, ForcingData] = calculateBoundaryConditions(BoundaryCondition, HeatMatrices, ForcingData, SoilVariables, InitialValues, ...
TimeProperties, SoilProperties, RHS, hN, KT, Delt_t, Evap, GroundwaterSettings)
%{
Determine the boundary condition for solving the soil moisture equation.
%}
ModelSettings = io.getModelSettings();
% n is the index of n_th item
n = ModelSettings.NN;
C4 = HeatMatrices.C4;
C4_a = HeatMatrices.C4_a;
Precip = InitialValues.Precip;
Precip_msr = ForcingData.Precip_msr;
Precipp = 0;
% Apply the bottom boundary condition called for by BoundaryCondition.NBChB
if ~GroundwaterSettings.GroundwaterCoupling % no Groundwater coupling
if BoundaryCondition.NBChB == 1 % Specify matric head at bottom to be ---BoundaryCondition.BChB;
RHS(1) = BoundaryCondition.BChB;
C4(1, 1) = 1;
RHS(2) = RHS(2) - C4(1, 2) * RHS(1);
C4(1, 2) = 0;
C4_a(1) = 0;
elseif BoundaryCondition.NBChB == 2 % Specify flux at bottom to be ---BoundaryCondition.BChB (Positive upwards);
RHS(1) = RHS(1) + BoundaryCondition.BChB;
elseif BoundaryCondition.NBChB == 3 % BoundaryCondition.NBChB=3, Gravity drainage at bottom--specify flux= hydraulic conductivity;
RHS(1) = RHS(1) - SoilVariables.KL_h(1, 1);
end
else % Groundwater coupling is activated, added by Mostafa
indxBotmLayer_R = GroundwaterSettings.indxBotmLayer_R;
indxBotm = GroundwaterSettings.indxBotmLayer; % index of bottom boundary layer after neglecting the saturated layers (from bottom to top)
soilThick = GroundwaterSettings.soilThick; % cumulative soil layers thickness
topLevel = GroundwaterSettings.topLevel;
headBotmLayer = GroundwaterSettings.headBotmLayer; % groundwater head at bottom layer, received from MODFLOW through BMI
RHS(indxBotm) = headBotmLayer - topLevel + soilThick(indxBotmLayer_R); % (RHS = zero at the end, need to check with Yijian and Lianyu)
if BoundaryCondition.NBChB == 1 % Specify matric head at bottom to be ---BoundaryCondition.BChB;
RHS(indxBotm) = headBotmLayer - topLevel + soilThick(indxBotmLayer_R);
C4(indxBotm, 1) = 1;
RHS(indxBotm + 1) = RHS(indxBotm + 1) - C4(indxBotm, 2) * RHS(indxBotm);
C4(indxBotm, 2) = 0;
C4_a(indxBotm) = 0;
elseif BoundaryCondition.NBChB == 2 % Specify flux at bottom to be ---BoundaryCondition.BChB (Positive upwards);
RHS(indxBotm) = RHS(indxBotm) + BoundaryCondition.BChB;
elseif BoundaryCondition.NBChB == 3 % BoundaryCondition.NBChB=3, Gravity drainage at bottom--specify flux= hydraulic conductivity;
RHS(indxBotm) = RHS(indxBotm) - SoilVariables.KL_h(indxBotm, 1);
end
end
% Apply the surface boundary condition called for by BoundaryCondition.NBCh
if BoundaryCondition.NBCh == 1 % Specified matric head at surface---equal to hN;
% h_SUR: Observed matric potential at surface. This variable
% is not calculated anywhere! see issue 98, item 6
RHS(n) = InitialValues.h_SUR(KT);
C4(n, 1) = 1;
RHS(n - 1) = RHS(n - 1) - C4(n - 1, 2) * RHS(n);
C4(n - 1, 2) = 0;
C4_a(n - 1) = 0;
elseif BoundaryCondition.NBCh == 2
if BoundaryCondition.NBChh == 1
RHS(n) = hN;
C4(n, 1) = 1;
RHS(n - 1) = RHS(n - 1) - C4(n - 1, 2) * RHS(n);
C4(n - 1, 2) = 0;
else
RHS(n) = RHS(n) - BoundaryCondition.BCh; % a specified matric head (saturation or dryness) was applied;
end
else % (BoundaryCondition.NBCh == 3, Specified atmospheric forcing)
% Calculate applied infiltration and infiltration excess runoff (Hortonian runoff), modified by Mostafa
Ks0 = SoilProperties.Ks0 / (3600 * 24); % saturated vertical hydraulic conductivity. unit conversion from cm/day to cm/sec
% Note: Ks0 is not adjusted by the fsat as in the CLM model (Check CLM document: https://doi.org/10.5065/D6N877R)
% Check applied infiltration doesn't exceed infiltration capacity
topThick = 5; % first 5 cm of the soil
satCap = SoilProperties.theta_s0 * topThick; % saturation capacity represented by saturated water content of the top 5 cm of the soil
actTheta = ModelSettings.DeltZ(end - 4:end - 1) * SoilVariables.Theta_UU(end - 4:end - 1, 1); % actual moisture of the top 5 cm of the soil
infCap = (satCap - actTheta) / TimeProperties.DELT; % (cm/sec)
infCap_min = min(Ks0, infCap);
% Infiltration excess runoff (Hortonian runoff). Note: Dunnian runoff is calculated in the +io/loadForcingData file
if Precip_msr(KT) > infCap_min
ForcingData.R_Hort(KT) = Precip_msr(KT) - infCap_min;
else
ForcingData.R_Hort(KT) = 0;
end
Precip(KT) = min(Precip_msr(KT), infCap_min);
ForcingData.applied_inf(KT) = Precip(KT); % applied infiltration after removing Hortonian runoff
if SoilVariables.Tss(KT) > 0
Precip(KT) = Precip(KT);
else
Precip(KT) = Precip(KT);
Precipp = Precipp + Precip(KT);
Precip(KT) = 0;
end
if SoilVariables.Tss(KT) > 0
AVAIL0 = Precip(KT) + Precipp + BoundaryCondition.DSTOR0 / Delt_t; % (cm/sec)
Precipp = 0;
else
AVAIL0 = Precip(KT) + BoundaryCondition.DSTOR0 / Delt_t;
end
if BoundaryCondition.NBChh == 1
RHS(n) = hN;
C4(n, 1) = 1;
RHS(n - 1) = RHS(n - 1) - C4(n - 1, 2) * RHS(n);
C4(n - 1, 2) = 0;
C4_a(n - 1) = 0;
else
RHS(n) = RHS(n) + AVAIL0 - Evap(KT);
end
end
HeatMatrices.C4 = C4;
HeatMatrices.C4_a = C4_a;
end