Skip to content

Commit c8ce385

Browse files
committed
wip: soil moisture profile model. commit will be rebased
1 parent cbf7cf0 commit c8ce385

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
from typing import Any, Dict, List, Literal, Union, Optional
2+
3+
from ngen.init_config import serializer_deserializer
4+
from pydantic import root_validator, Field
5+
6+
# from .value_unit_pair import ListUnitPair
7+
8+
# soil_params.smcmax = 0.439
9+
# soil_params.b = 5.25
10+
# soil_params.satpsi = 0.355
11+
# soil_z = (
12+
# 0.1,
13+
# 0.2,
14+
# 0.3,
15+
# 0.4,
16+
# 0.5,
17+
# 0.6,
18+
# 0.7,
19+
# 0.8,
20+
# 0.9,
21+
# 1.0,
22+
# 1.1,
23+
# 1.2,
24+
# 1.3,
25+
# 1.4,
26+
# 1.5,
27+
# 1.6,
28+
# 1.7,
29+
# 1.8,
30+
# 1.9,
31+
# 2.0,
32+
# )
33+
# soil_storage_model = conceptual
34+
# soil_storage_depth = 2.0
35+
36+
# soil_depth_layers="bmi" | "BMI"
37+
# soil_params.smcmax="bmi" | "BMI"
38+
# soil_params.b: double > 0
39+
# soil_params.satpsi: double
40+
# soil_storage_model="Conceptual" | "conceptual" | "layered" | "Layered" | "topmodel" | "TOPMODEL" | "TopModel"
41+
# soil_moisture_profile_option="Constant" | "constant" | "Linear" | "linear"
42+
# soil_storage_depth: double >0
43+
# water_table_depth: double
44+
# soil_moisture_fraction_depth: double
45+
# water_table_based_method: "deficit_based" | "flux_based"
46+
# verbosity: "high" | "low" | "none"
47+
48+
49+
# b_set
50+
# satpsi_set
51+
# smcmax_set
52+
# soil_depth_layers_set
53+
# soil_moisture_fraction_depth_set
54+
# soil_moisture_profile_option_set
55+
# soil_storage_model_depth_set
56+
# soil_storage_model_set
57+
# soil_z_set
58+
# water_table_based_method_set
59+
# water_table_depth_set
60+
61+
bmi = Literal["BMI", "bmi"]
62+
soil_storage_model = Literal[
63+
"Conceptual", "conceptual", "Layered", "layered", "TopModel", "topmodel", "TOPMODEL"
64+
]
65+
soil_moisture_profile_option = Literal["Constant", "constant", "Linear", "linear"]
66+
water_table_based_method = Literal["deficit_based", "flux_based"]
67+
68+
# soil_z_set
69+
# soil_depth_layers_set
70+
# smcmax_set
71+
# b_set
72+
# satpsi_set
73+
# soil_storage_model_set
74+
# soil_storage_model_depth_set
75+
# water_table_depth_set
76+
# water_table_based_method_set
77+
# soil_moisture_fraction_depth_set
78+
# soil_moisture_profile_option_set
79+
80+
81+
class SoilMoistureProfile(serializer_deserializer.IniSerializerDeserializer):
82+
soil_z: List[float]
83+
84+
# NOTE: can also be provided as list of floats.
85+
# Not sure if this is expected to always be provided via bmi
86+
# soil_depth_layers: Literal["BMI", "bmi"] = "BMI"
87+
soil_depth_layers: Union[List[float], bmi]
88+
89+
# soil_params.smcmax
90+
smcmax: Union[List[float], bmi]
91+
92+
# soil_params.b
93+
# b > 0
94+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L169C23-L169C23
95+
b: float = Field(gt=0)
96+
97+
# soil_params.satpsi
98+
satpsi: float
99+
100+
soil_storage_model: soil_storage_model
101+
soil_moisture_profile_option: Optional[soil_moisture_profile_option]
102+
103+
# soil_storage_depth > 0
104+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L199
105+
soil_storage_depth: Optional[float] = Field(None, gt=0)
106+
107+
# 6.0 default from:
108+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L294
109+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L298
110+
water_table_depth: float = Field(6.0, gte=0)
111+
112+
# 0.4 meter default from:
113+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L270
114+
soil_moisture_fraction_depth: float = 0.4 # in meters
115+
water_table_based_method: Optional[water_table_based_method]
116+
117+
# NOTE: this seems like it is optional. confirm this
118+
# NOTE: also not sure if this should be "none" by default
119+
verbosity: Optional[Literal["high", "low"]]
120+
121+
@root_validator(pre=True)
122+
@classmethod
123+
def _root_validator(cls, values: Dict[str, Any]):
124+
# soil_params.<var_name> _are_ supported, but deprecated.
125+
soil_params_mapping = (
126+
("soil_params.b", "b"),
127+
("soil_params.satpsi", "satpsi"),
128+
("soil_params.smcmax", "smcmax"),
129+
)
130+
# map from the deprecated names to the supported names _if_ only the deprecated name is provided
131+
for alt, actual in soil_params_mapping:
132+
if alt in values and actual not in values:
133+
values[actual] = values[alt]
134+
# delete is not required, pydantic will ignore the values.
135+
# del values[alt]
136+
return values
137+
138+
@root_validator()
139+
def _assert_invariants(cls, values: Dict[str, Any]):
140+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L273
141+
soil_storage_model = values["soil_storage_model"]
142+
soil_storage_depth = values.get("soil_storage_depth")
143+
if soil_storage_depth is None and soil_storage_model.lower() == "conceptual":
144+
raise ValueError(
145+
f"'soil_storage_depth' required for 'soil_storage_model': {soil_storage_model!r}"
146+
)
147+
148+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L286
149+
smp_opt = values.get("soil_moisture_profile_option")
150+
if soil_storage_model.lower() == "layered" and smp_opt is None:
151+
raise ValueError(
152+
f"'soil_moisture_profile_option' required for 'soil_storage_model': {soil_storage_model!r}"
153+
)
154+
155+
# https://github.com/NOAA-OWP/SoilMoistureProfiles/blob/832d5a70d632d9978dec40a480e970a6b59720c5/src/soil_moisture_profile.cxx#L313
156+
wtm = values.get("water_table_based_method")
157+
if soil_storage_model.lower() == "topmodel" and wtm is None:
158+
raise ValueError(
159+
f"'water_table_based_method' required for 'soil_storage_model': {soil_storage_model!r}"
160+
)
161+
162+
return values
163+
164+
class Config(serializer_deserializer.IniSerializerDeserializer.Config):
165+
no_section_headers: bool = True
166+
# extra space is not accounted for
167+
# TODO: get link
168+
space_around_delimiters: bool = False

0 commit comments

Comments
 (0)