wrfrun 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wrfrun/__init__.py +3 -0
- wrfrun/core/__init__.py +5 -0
- wrfrun/core/base.py +680 -0
- wrfrun/core/config.py +717 -0
- wrfrun/core/error.py +80 -0
- wrfrun/core/replay.py +113 -0
- wrfrun/core/server.py +212 -0
- wrfrun/data.py +418 -0
- wrfrun/extension/__init__.py +1 -0
- wrfrun/extension/littler/__init__.py +1 -0
- wrfrun/extension/littler/utils.py +599 -0
- wrfrun/extension/utils.py +66 -0
- wrfrun/model/__init__.py +7 -0
- wrfrun/model/base.py +14 -0
- wrfrun/model/plot.py +54 -0
- wrfrun/model/utils.py +34 -0
- wrfrun/model/wrf/__init__.py +6 -0
- wrfrun/model/wrf/_metgrid.py +71 -0
- wrfrun/model/wrf/_ndown.py +39 -0
- wrfrun/model/wrf/core.py +805 -0
- wrfrun/model/wrf/exec_wrap.py +101 -0
- wrfrun/model/wrf/geodata.py +301 -0
- wrfrun/model/wrf/namelist.py +377 -0
- wrfrun/model/wrf/scheme.py +311 -0
- wrfrun/model/wrf/vtable.py +65 -0
- wrfrun/pbs.py +86 -0
- wrfrun/plot/__init__.py +1 -0
- wrfrun/plot/wps.py +188 -0
- wrfrun/res/__init__.py +22 -0
- wrfrun/res/config.toml.template +136 -0
- wrfrun/res/extension/plotgrids.ncl +216 -0
- wrfrun/res/job_scheduler/pbs.template +6 -0
- wrfrun/res/job_scheduler/slurm.template +6 -0
- wrfrun/res/namelist/namelist.input.da_wrfvar.template +261 -0
- wrfrun/res/namelist/namelist.input.dfi.template +260 -0
- wrfrun/res/namelist/namelist.input.real.template +256 -0
- wrfrun/res/namelist/namelist.input.wrf.template +256 -0
- wrfrun/res/namelist/namelist.wps.template +44 -0
- wrfrun/res/namelist/parame.in.template +11 -0
- wrfrun/res/run.sh.template +16 -0
- wrfrun/run.py +264 -0
- wrfrun/utils.py +257 -0
- wrfrun/workspace.py +88 -0
- wrfrun-0.1.7.dist-info/METADATA +67 -0
- wrfrun-0.1.7.dist-info/RECORD +46 -0
- wrfrun-0.1.7.dist-info/WHEEL +4 -0
wrfrun/model/wrf/core.py
ADDED
|
@@ -0,0 +1,805 @@
|
|
|
1
|
+
from os import listdir
|
|
2
|
+
from os.path import abspath, basename, exists
|
|
3
|
+
from shutil import copyfile, move, rmtree
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from wrfrun.core import ExecutableBase, FileConfigDict, InputFileError, NamelistError, WRFRUNConfig, WRFRUNExecDB
|
|
7
|
+
from wrfrun.utils import logger
|
|
8
|
+
from ._metgrid import reconcile_namelist_metgrid
|
|
9
|
+
from ._ndown import process_after_ndown
|
|
10
|
+
from .namelist import prepare_dfi_namelist, prepare_wps_namelist, prepare_wrf_namelist, prepare_wrfda_namelist
|
|
11
|
+
from .vtable import VtableFiles
|
|
12
|
+
from ..base import NamelistName
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _check_namelist_preparation():
|
|
16
|
+
if len(WRFRUNConfig.get_namelist("wps")) == 0:
|
|
17
|
+
prepare_wps_namelist()
|
|
18
|
+
|
|
19
|
+
if len(WRFRUNConfig.get_namelist("wrf")) == 0:
|
|
20
|
+
prepare_wrf_namelist()
|
|
21
|
+
|
|
22
|
+
if len(WRFRUNConfig.get_namelist("wrfda")) == 0:
|
|
23
|
+
prepare_wrfda_namelist()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class GeoGrid(ExecutableBase):
|
|
27
|
+
"""
|
|
28
|
+
Execute "geogrid.exe".
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, geogrid_tbl_file: Optional[str] = None, core_num: Optional[int] = None):
|
|
32
|
+
"""
|
|
33
|
+
Execute "geogrid.exe".
|
|
34
|
+
|
|
35
|
+
:param geogrid_tbl_file: Custom GEOGRID.TBL file path. Defaults to None.
|
|
36
|
+
:type geogrid_tbl_file: str
|
|
37
|
+
:param core_num: An positive integer number of used core numbers. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
|
|
38
|
+
:type core_num: int
|
|
39
|
+
"""
|
|
40
|
+
if isinstance(core_num, int) and core_num <= 0:
|
|
41
|
+
logger.warning(f"`core_num` should be greater than 0")
|
|
42
|
+
core_num = None
|
|
43
|
+
|
|
44
|
+
if core_num is None:
|
|
45
|
+
mpi_use = False
|
|
46
|
+
mpi_cmd = None
|
|
47
|
+
mpi_core_num = core_num
|
|
48
|
+
|
|
49
|
+
else:
|
|
50
|
+
mpi_use = True
|
|
51
|
+
mpi_cmd = "mpirun"
|
|
52
|
+
mpi_core_num = core_num
|
|
53
|
+
|
|
54
|
+
super().__init__(name="geogrid", cmd="./geogrid.exe", work_path=WRFRUNConfig.WPS_WORK_PATH, mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
|
|
55
|
+
|
|
56
|
+
self.geogrid_tbl_file = geogrid_tbl_file
|
|
57
|
+
|
|
58
|
+
_check_namelist_preparation()
|
|
59
|
+
|
|
60
|
+
def generate_custom_config(self):
|
|
61
|
+
"""
|
|
62
|
+
Get and store namelist.
|
|
63
|
+
:return:
|
|
64
|
+
:rtype:
|
|
65
|
+
"""
|
|
66
|
+
self.custom_config.update(
|
|
67
|
+
{
|
|
68
|
+
"namelist": WRFRUNConfig.get_namelist("wps"),
|
|
69
|
+
"geogrid_tbl_file": self.geogrid_tbl_file
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def load_custom_config(self):
|
|
74
|
+
WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wps")
|
|
75
|
+
self.geogrid_tbl_file = self.custom_config["geogrid_tbl_file"]
|
|
76
|
+
|
|
77
|
+
def before_exec(self):
|
|
78
|
+
WRFRUNConfig.check_wrfrun_context(True)
|
|
79
|
+
WRFRUNConfig.WRFRUN_WORK_STATUS = "geogrid"
|
|
80
|
+
|
|
81
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
82
|
+
if self.geogrid_tbl_file is not None:
|
|
83
|
+
tbl_file: FileConfigDict = {
|
|
84
|
+
"file_path": self.geogrid_tbl_file, "save_path": f"{WRFRUNConfig.WPS_WORK_PATH}/geogrid",
|
|
85
|
+
"save_name": "GEOGRID.TBL", "is_data": False, "is_output": False
|
|
86
|
+
}
|
|
87
|
+
self.add_input_files(tbl_file)
|
|
88
|
+
|
|
89
|
+
super().before_exec()
|
|
90
|
+
|
|
91
|
+
WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WPS_WORK_PATH}/{NamelistName.WPS}", "wps")
|
|
92
|
+
|
|
93
|
+
def after_exec(self):
|
|
94
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
95
|
+
self.add_output_files(save_path=self._log_save_path, startswith="geogrid.log", outputs=NamelistName.WPS)
|
|
96
|
+
self.add_output_files(save_path=self._output_save_path, startswith="geo_em")
|
|
97
|
+
|
|
98
|
+
super().after_exec()
|
|
99
|
+
|
|
100
|
+
logger.info(f"All geogrid output files have been copied to {WRFRUNConfig.parse_resource_uri(self._output_save_path)}")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class LinkGrib(ExecutableBase):
|
|
104
|
+
"""
|
|
105
|
+
Run command: "./link_grib.csh".
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
def __init__(self, grib_dir_path: str):
|
|
109
|
+
"""
|
|
110
|
+
Execute "link_grib.csh".
|
|
111
|
+
|
|
112
|
+
:param grib_dir_path: GRIB data path. Absolute path is recommended.
|
|
113
|
+
:type grib_dir_path: str
|
|
114
|
+
"""
|
|
115
|
+
self._link_grib_input_path = "./input_grib_data_dir"
|
|
116
|
+
|
|
117
|
+
super().__init__(name="link_grib", cmd=["./link_grib.csh", f"{self._link_grib_input_path}/*", "."], work_path=WRFRUNConfig.WPS_WORK_PATH)
|
|
118
|
+
self.grib_dir_path = grib_dir_path
|
|
119
|
+
|
|
120
|
+
def generate_custom_config(self):
|
|
121
|
+
self.class_config["class_args"] = (self.grib_dir_path,)
|
|
122
|
+
|
|
123
|
+
def replay(self):
|
|
124
|
+
self()
|
|
125
|
+
|
|
126
|
+
def before_exec(self):
|
|
127
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
128
|
+
|
|
129
|
+
logger.debug(f"Input data are: {self.grib_dir_path}")
|
|
130
|
+
_grib_dir_path = abspath(self.grib_dir_path)
|
|
131
|
+
|
|
132
|
+
if not exists(_grib_dir_path):
|
|
133
|
+
logger.error(f"GRIB file directory not found: {_grib_dir_path}")
|
|
134
|
+
raise FileNotFoundError(f"GRIB file directory not found: {_grib_dir_path}")
|
|
135
|
+
|
|
136
|
+
save_path = f"{WRFRUNConfig.WPS_WORK_PATH}/{self._link_grib_input_path}"
|
|
137
|
+
save_path = WRFRUNConfig.parse_resource_uri(save_path)
|
|
138
|
+
if exists(save_path):
|
|
139
|
+
rmtree(save_path)
|
|
140
|
+
|
|
141
|
+
for _file in listdir(_grib_dir_path):
|
|
142
|
+
_file_config: FileConfigDict = {
|
|
143
|
+
"file_path": f"{_grib_dir_path}/{_file}",
|
|
144
|
+
"save_path": f"{WRFRUNConfig.WPS_WORK_PATH}/{self._link_grib_input_path}",
|
|
145
|
+
"save_name": _file, "is_data": True, "is_output": False,
|
|
146
|
+
}
|
|
147
|
+
self.add_input_files(_file_config)
|
|
148
|
+
|
|
149
|
+
super().before_exec()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class UnGrib(ExecutableBase):
|
|
153
|
+
"""
|
|
154
|
+
Execute "ungrib.exe".
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
def __init__(self, vtable_file: Optional[str] = None, input_data_path: Optional[str] = None):
|
|
158
|
+
"""
|
|
159
|
+
Execute "ungrib.exe".
|
|
160
|
+
|
|
161
|
+
:param vtable_file: Path of the Vtable file "ungrib.exe" used.
|
|
162
|
+
:type vtable_file: str
|
|
163
|
+
:param input_data_path: Path of the directory stores input GRIB2 files.
|
|
164
|
+
:type input_data_path: str
|
|
165
|
+
"""
|
|
166
|
+
super().__init__(name="ungrib", cmd="./ungrib.exe", work_path=WRFRUNConfig.WPS_WORK_PATH)
|
|
167
|
+
|
|
168
|
+
self.vtable_file = vtable_file
|
|
169
|
+
self.input_data_path = input_data_path
|
|
170
|
+
|
|
171
|
+
_check_namelist_preparation()
|
|
172
|
+
|
|
173
|
+
def call_link_grib(self):
|
|
174
|
+
"""
|
|
175
|
+
Execute "link_grib.csh" if needed.
|
|
176
|
+
|
|
177
|
+
:return:
|
|
178
|
+
:rtype:
|
|
179
|
+
"""
|
|
180
|
+
if self.input_data_path is None:
|
|
181
|
+
self.input_data_path = WRFRUNConfig.get_input_data_path()
|
|
182
|
+
|
|
183
|
+
LinkGrib(self.input_data_path)()
|
|
184
|
+
|
|
185
|
+
def generate_custom_config(self):
|
|
186
|
+
"""
|
|
187
|
+
Get and store namelist.
|
|
188
|
+
|
|
189
|
+
:return:
|
|
190
|
+
:rtype:
|
|
191
|
+
"""
|
|
192
|
+
self.custom_config.update(
|
|
193
|
+
{
|
|
194
|
+
"namelist": WRFRUNConfig.get_namelist("wps"),
|
|
195
|
+
"vtable_file": self.vtable_file
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def load_custom_config(self):
|
|
200
|
+
self.vtable_file = self.custom_config["vtable_file"]
|
|
201
|
+
WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wps")
|
|
202
|
+
|
|
203
|
+
def replay(self):
|
|
204
|
+
super().__call__()
|
|
205
|
+
|
|
206
|
+
def before_exec(self):
|
|
207
|
+
WRFRUNConfig.check_wrfrun_context(True)
|
|
208
|
+
WRFRUNConfig.WRFRUN_WORK_STATUS = "ungrib"
|
|
209
|
+
|
|
210
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
211
|
+
if self.vtable_file is None:
|
|
212
|
+
self.vtable_file = VtableFiles.ERA_PL
|
|
213
|
+
|
|
214
|
+
_file_config: FileConfigDict = {
|
|
215
|
+
"file_path": self.vtable_file,
|
|
216
|
+
"save_path": WRFRUNConfig.WPS_WORK_PATH,
|
|
217
|
+
"save_name": "Vtable",
|
|
218
|
+
"is_data": False,
|
|
219
|
+
"is_output": False
|
|
220
|
+
}
|
|
221
|
+
self.add_input_files(_file_config)
|
|
222
|
+
|
|
223
|
+
super().before_exec()
|
|
224
|
+
|
|
225
|
+
WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WPS_WORK_PATH}/{NamelistName.WPS}", "wps")
|
|
226
|
+
|
|
227
|
+
def after_exec(self):
|
|
228
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
229
|
+
self.add_output_files(output_dir=WRFRUNConfig.get_ungrib_out_dir_path(), save_path=self._output_save_path, startswith=WRFRUNConfig.get_ungrib_out_prefix())
|
|
230
|
+
self.add_output_files(save_path=self._log_save_path, outputs=["ungrib.log", "namelist.wps"])
|
|
231
|
+
|
|
232
|
+
super().after_exec()
|
|
233
|
+
|
|
234
|
+
logger.info(f"All ungrib output files have been copied to {WRFRUNConfig.parse_resource_uri(self._output_save_path)}")
|
|
235
|
+
|
|
236
|
+
def __call__(self):
|
|
237
|
+
self.call_link_grib()
|
|
238
|
+
|
|
239
|
+
super().__call__()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class MetGrid(ExecutableBase):
|
|
243
|
+
"""
|
|
244
|
+
Execute "metgrid.exe".
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
def __init__(self, geogrid_data_path: Optional[str] = None, ungrib_data_path: Optional[str] = None, core_num: Optional[int] = None):
|
|
248
|
+
"""
|
|
249
|
+
Execute "metgrid.exe".
|
|
250
|
+
|
|
251
|
+
:param geogrid_data_path: Directory path of outputs from geogrid.exe. If None, tries to use the output path specified by config file.
|
|
252
|
+
:type geogrid_data_path: str
|
|
253
|
+
:param ungrib_data_path: Directory path of outputs from ungrib.exe. If None, tries to use the output path specified by config file.
|
|
254
|
+
:type ungrib_data_path: str
|
|
255
|
+
:param core_num: An positive integer number of used core numbers. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
|
|
256
|
+
:type core_num: int
|
|
257
|
+
"""
|
|
258
|
+
if isinstance(core_num, int) and core_num <= 0:
|
|
259
|
+
logger.warning(f"`core_num` should be greater than 0")
|
|
260
|
+
core_num = None
|
|
261
|
+
|
|
262
|
+
if core_num is None:
|
|
263
|
+
mpi_use = False
|
|
264
|
+
mpi_cmd = None
|
|
265
|
+
mpi_core_num = core_num
|
|
266
|
+
|
|
267
|
+
else:
|
|
268
|
+
mpi_use = True
|
|
269
|
+
mpi_cmd = "mpirun"
|
|
270
|
+
mpi_core_num = core_num
|
|
271
|
+
|
|
272
|
+
super().__init__(name="metgrid", cmd="./metgrid.exe", work_path=WRFRUNConfig.WPS_WORK_PATH, mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
|
|
273
|
+
|
|
274
|
+
self.geogrid_data_path = geogrid_data_path
|
|
275
|
+
self.ungrib_data_path = ungrib_data_path
|
|
276
|
+
|
|
277
|
+
_check_namelist_preparation()
|
|
278
|
+
|
|
279
|
+
def generate_custom_config(self):
|
|
280
|
+
"""
|
|
281
|
+
Get and store namelist.
|
|
282
|
+
:return:
|
|
283
|
+
:rtype:
|
|
284
|
+
"""
|
|
285
|
+
self.custom_config.update(
|
|
286
|
+
{
|
|
287
|
+
"geogrid_data_path": self.geogrid_data_path,
|
|
288
|
+
"ungrib_data_path": self.ungrib_data_path,
|
|
289
|
+
"namelist": WRFRUNConfig.get_namelist("wps"),
|
|
290
|
+
}
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
def load_custom_config(self):
|
|
294
|
+
self.geogrid_data_path = self.custom_config["geogrid_data_path"]
|
|
295
|
+
self.ungrib_data_path = self.custom_config["ungrib_data_path"]
|
|
296
|
+
WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wps")
|
|
297
|
+
|
|
298
|
+
def before_exec(self):
|
|
299
|
+
WRFRUNConfig.check_wrfrun_context(True)
|
|
300
|
+
WRFRUNConfig.WRFRUN_WORK_STATUS = "metgrid"
|
|
301
|
+
|
|
302
|
+
if not WRFRUNConfig.IS_IN_REPLAY and not WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
303
|
+
# check input of metgrid.exe
|
|
304
|
+
# try to search input files in the output path if workspace is clear.
|
|
305
|
+
file_list = listdir(WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WPS_WORK_PATH))
|
|
306
|
+
|
|
307
|
+
if "geo_em.d01.nc" not in file_list:
|
|
308
|
+
|
|
309
|
+
if self.geogrid_data_path is None:
|
|
310
|
+
self.geogrid_data_path = f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/geogrid"
|
|
311
|
+
geogrid_data_path = WRFRUNConfig.parse_resource_uri(self.geogrid_data_path)
|
|
312
|
+
|
|
313
|
+
if not exists(geogrid_data_path) or "geo_em.d01.nc" not in listdir(geogrid_data_path):
|
|
314
|
+
logger.error(f"Can't find geogrid outputs in WPS_WORK_PATH and your outputs directory, which is essential to run metgrid")
|
|
315
|
+
raise FileNotFoundError(f"Can't find geogrid outputs in WPS_WORK_PATH and your outputs directory, which is essential to run metgrid")
|
|
316
|
+
|
|
317
|
+
else:
|
|
318
|
+
geogrid_file_list = [x for x in listdir(geogrid_data_path) if x.startswith("geo_em.d")]
|
|
319
|
+
for _file in geogrid_file_list:
|
|
320
|
+
_file_config = {
|
|
321
|
+
"file_path": f"{self.geogrid_data_path}/{_file}",
|
|
322
|
+
"save_path": WRFRUNConfig.WPS_WORK_PATH,
|
|
323
|
+
"save_name": _file,
|
|
324
|
+
"is_data": True,
|
|
325
|
+
"is_output": True
|
|
326
|
+
}
|
|
327
|
+
self.add_input_files(_file_config)
|
|
328
|
+
|
|
329
|
+
ungrib_output_dir = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.get_ungrib_out_dir_path())
|
|
330
|
+
if basename(ungrib_output_dir) not in file_list or len(listdir(ungrib_output_dir)) == 0:
|
|
331
|
+
|
|
332
|
+
if self.ungrib_data_path is None:
|
|
333
|
+
self.ungrib_data_path = f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/ungrib"
|
|
334
|
+
|
|
335
|
+
ungrib_data_path = WRFRUNConfig.parse_resource_uri(self.ungrib_data_path)
|
|
336
|
+
|
|
337
|
+
if not exists(ungrib_data_path) or len(listdir(ungrib_data_path)) == 0:
|
|
338
|
+
logger.error(f"Can't find ungrib outputs in WPS_WORK_PATH and your outputs directory, which is essential to run metgrid")
|
|
339
|
+
raise FileNotFoundError(f"Can't find ungrib outputs in WPS_WORK_PATH and your outputs directory, which is essential to run metgrid")
|
|
340
|
+
|
|
341
|
+
else:
|
|
342
|
+
ungrib_file_list = [x for x in listdir(ungrib_data_path)]
|
|
343
|
+
for _file in ungrib_file_list:
|
|
344
|
+
_file_config: FileConfigDict = {
|
|
345
|
+
"file_path": f"{self.ungrib_data_path}/{_file}",
|
|
346
|
+
"save_path": WRFRUNConfig.get_ungrib_out_dir_path(),
|
|
347
|
+
"save_name": _file,
|
|
348
|
+
"is_data": True,
|
|
349
|
+
"is_output": True
|
|
350
|
+
}
|
|
351
|
+
self.add_input_files(_file_config)
|
|
352
|
+
|
|
353
|
+
super().before_exec()
|
|
354
|
+
|
|
355
|
+
WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WPS_WORK_PATH}/{NamelistName.WPS}", "wps")
|
|
356
|
+
|
|
357
|
+
def after_exec(self):
|
|
358
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
359
|
+
self.add_output_files(save_path=self._log_save_path, startswith="metgrid.log", outputs="namelist.wps")
|
|
360
|
+
self.add_output_files(save_path=self._output_save_path, startswith="met_em")
|
|
361
|
+
|
|
362
|
+
super().after_exec()
|
|
363
|
+
|
|
364
|
+
logger.info(f"All metgrid output files have been copied to {WRFRUNConfig.parse_resource_uri(self._output_save_path)}")
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
class Real(ExecutableBase):
|
|
368
|
+
"""
|
|
369
|
+
Execute "real.exe".
|
|
370
|
+
"""
|
|
371
|
+
|
|
372
|
+
def __init__(self, metgrid_data_path: Optional[str] = None, core_num: Optional[int] = None):
|
|
373
|
+
"""
|
|
374
|
+
Execute "real.exe".
|
|
375
|
+
|
|
376
|
+
:param metgrid_data_path: Path of the directory stores outputs from "metgrid.exe".
|
|
377
|
+
:type metgrid_data_path: str
|
|
378
|
+
:param core_num: An positive integer number of used core numbers. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
|
|
379
|
+
:type core_num: int
|
|
380
|
+
"""
|
|
381
|
+
if isinstance(core_num, int) and core_num <= 0:
|
|
382
|
+
logger.warning(f"`core_num` should be greater than 0")
|
|
383
|
+
core_num = None
|
|
384
|
+
|
|
385
|
+
if core_num is None:
|
|
386
|
+
mpi_use = False
|
|
387
|
+
mpi_cmd = None
|
|
388
|
+
mpi_core_num = core_num
|
|
389
|
+
|
|
390
|
+
else:
|
|
391
|
+
mpi_use = True
|
|
392
|
+
mpi_cmd = "mpirun"
|
|
393
|
+
mpi_core_num = core_num
|
|
394
|
+
|
|
395
|
+
_check_namelist_preparation()
|
|
396
|
+
|
|
397
|
+
super().__init__(name="real", cmd="./real.exe", work_path=WRFRUNConfig.WRF_WORK_PATH, mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
|
|
398
|
+
|
|
399
|
+
self.metgrid_data_path = metgrid_data_path
|
|
400
|
+
|
|
401
|
+
def generate_custom_config(self):
|
|
402
|
+
self.custom_config["metgrid_data_path"] = self.metgrid_data_path
|
|
403
|
+
self.custom_config.update(
|
|
404
|
+
{
|
|
405
|
+
"namelist": WRFRUNConfig.get_namelist("wrf"),
|
|
406
|
+
"metgrid_data_path": self.metgrid_data_path
|
|
407
|
+
}
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
def load_custom_config(self):
|
|
411
|
+
self.metgrid_data_path = self.custom_config["metgrid_data_path"]
|
|
412
|
+
WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wrf")
|
|
413
|
+
|
|
414
|
+
def before_exec(self):
|
|
415
|
+
WRFRUNConfig.check_wrfrun_context(True)
|
|
416
|
+
WRFRUNConfig.WRFRUN_WORK_STATUS = "real"
|
|
417
|
+
|
|
418
|
+
if not WRFRUNConfig.IS_IN_REPLAY and not WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
419
|
+
if self.metgrid_data_path is None:
|
|
420
|
+
self.metgrid_data_path = f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/metgrid"
|
|
421
|
+
|
|
422
|
+
metgrid_data_path = WRFRUNConfig.parse_resource_uri(self.metgrid_data_path)
|
|
423
|
+
reconcile_namelist_metgrid(metgrid_data_path)
|
|
424
|
+
|
|
425
|
+
file_list = [x for x in listdir(metgrid_data_path) if x.startswith("met_em")]
|
|
426
|
+
for _file in file_list:
|
|
427
|
+
_file_config: FileConfigDict = {
|
|
428
|
+
"file_path": f"{self.metgrid_data_path}/{_file}",
|
|
429
|
+
"save_path": WRFRUNConfig.WRF_WORK_PATH,
|
|
430
|
+
"save_name": _file,
|
|
431
|
+
"is_data": True,
|
|
432
|
+
"is_output": True
|
|
433
|
+
}
|
|
434
|
+
self.add_input_files(_file_config)
|
|
435
|
+
|
|
436
|
+
super().before_exec()
|
|
437
|
+
|
|
438
|
+
WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "wrf")
|
|
439
|
+
|
|
440
|
+
def after_exec(self):
|
|
441
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
442
|
+
self.add_output_files(save_path=self._output_save_path, startswith=("wrfbdy", "wrfinput", "wrflow"))
|
|
443
|
+
self.add_output_files(save_path=self._log_save_path, startswith="rsl.", outputs="namelist.input")
|
|
444
|
+
|
|
445
|
+
super().after_exec()
|
|
446
|
+
|
|
447
|
+
logger.info(f"All real output files have been copied to {WRFRUNConfig.parse_resource_uri(self._output_save_path)}")
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class WRF(ExecutableBase):
|
|
451
|
+
"""
|
|
452
|
+
Execute "wrf.exe".
|
|
453
|
+
"""
|
|
454
|
+
|
|
455
|
+
def __init__(self, input_file_dir_path: Optional[str] = None, restart_file_dir_path: Optional[str] = None, save_restarts=False, core_num: Optional[int] = None):
|
|
456
|
+
"""
|
|
457
|
+
Execute "wrf.exe"
|
|
458
|
+
|
|
459
|
+
:param input_file_dir_path: Path of the directory that stores input data for "wrf.exe".
|
|
460
|
+
:type input_file_dir_path: str
|
|
461
|
+
:param restart_file_dir_path: Path of the directory that stores restart files for "wrf.exe".
|
|
462
|
+
:type restart_file_dir_path: str
|
|
463
|
+
:param save_restarts: If saving restart files from "wrf.exe". Defaults to False.
|
|
464
|
+
:type save_restarts: bool
|
|
465
|
+
:param core_num: An positive integer number of used core numbers. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
|
|
466
|
+
:type core_num: int
|
|
467
|
+
"""
|
|
468
|
+
if isinstance(core_num, int) and core_num <= 0:
|
|
469
|
+
logger.warning(f"`core_num` should be greater than 0")
|
|
470
|
+
core_num = None
|
|
471
|
+
|
|
472
|
+
if core_num is None:
|
|
473
|
+
mpi_use = False
|
|
474
|
+
mpi_cmd = None
|
|
475
|
+
mpi_core_num = core_num
|
|
476
|
+
|
|
477
|
+
else:
|
|
478
|
+
mpi_use = True
|
|
479
|
+
mpi_cmd = "mpirun"
|
|
480
|
+
mpi_core_num = core_num
|
|
481
|
+
|
|
482
|
+
_check_namelist_preparation()
|
|
483
|
+
|
|
484
|
+
super().__init__(name="wrf", cmd="./wrf.exe", work_path=WRFRUNConfig.WRF_WORK_PATH, mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
|
|
485
|
+
|
|
486
|
+
self.input_file_dir_path = input_file_dir_path
|
|
487
|
+
self.restart_file_dir_path = restart_file_dir_path
|
|
488
|
+
self.save_restarts = save_restarts
|
|
489
|
+
|
|
490
|
+
def generate_custom_config(self):
|
|
491
|
+
self.custom_config.update(
|
|
492
|
+
{
|
|
493
|
+
"input_file_dir_path": self.input_file_dir_path,
|
|
494
|
+
"restart_file_dir_path": self.restart_file_dir_path,
|
|
495
|
+
"namelist": WRFRUNConfig.get_namelist("wrf")
|
|
496
|
+
}
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
def load_custom_config(self):
|
|
500
|
+
self.input_file_dir_path = self.custom_config["input_file_dir_path"]
|
|
501
|
+
self.restart_file_dir_path = self.custom_config["restart_file_dir_path"]
|
|
502
|
+
WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wrf")
|
|
503
|
+
|
|
504
|
+
def before_exec(self):
|
|
505
|
+
WRFRUNConfig.check_wrfrun_context(True)
|
|
506
|
+
# help wrfrun to make sure the input file is from real or ndown.
|
|
507
|
+
last_work_status = WRFRUNConfig.WRFRUN_WORK_STATUS
|
|
508
|
+
if last_work_status not in ["real", "ndown"]:
|
|
509
|
+
last_work_status = ""
|
|
510
|
+
WRFRUNConfig.WRFRUN_WORK_STATUS = "wrf"
|
|
511
|
+
|
|
512
|
+
if not WRFRUNConfig.IS_IN_REPLAY and not WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
513
|
+
if self.input_file_dir_path is None:
|
|
514
|
+
if last_work_status == "":
|
|
515
|
+
# assume we already have outputs from real.exe.
|
|
516
|
+
self.input_file_dir_path = f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/real"
|
|
517
|
+
is_output = False
|
|
518
|
+
else:
|
|
519
|
+
self.input_file_dir_path = f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/{last_work_status}"
|
|
520
|
+
is_output = True
|
|
521
|
+
|
|
522
|
+
else:
|
|
523
|
+
is_output = False
|
|
524
|
+
|
|
525
|
+
input_file_dir_path = WRFRUNConfig.parse_resource_uri(self.input_file_dir_path)
|
|
526
|
+
|
|
527
|
+
if exists(input_file_dir_path):
|
|
528
|
+
file_list = [x for x in listdir(input_file_dir_path) if x != "logs"]
|
|
529
|
+
|
|
530
|
+
for _file in file_list:
|
|
531
|
+
_file_config: FileConfigDict = {
|
|
532
|
+
"file_path": f"{self.input_file_dir_path}/{_file}",
|
|
533
|
+
"save_path": WRFRUNConfig.WRF_WORK_PATH,
|
|
534
|
+
"save_name": _file,
|
|
535
|
+
"is_data": True,
|
|
536
|
+
"is_output": is_output
|
|
537
|
+
}
|
|
538
|
+
self.add_input_files(_file_config)
|
|
539
|
+
|
|
540
|
+
if WRFRUNConfig.get_model_config("wrf")["restart_mode"]:
|
|
541
|
+
if self.restart_file_dir_path is None:
|
|
542
|
+
logger.error("You need to specify the restart file if you want to restart WRF.")
|
|
543
|
+
raise InputFileError("You need to specify the restart file if you want to restart WRF.")
|
|
544
|
+
|
|
545
|
+
restart_file_dir_path = WRFRUNConfig.parse_resource_uri(self.restart_file_dir_path)
|
|
546
|
+
|
|
547
|
+
if not exists(restart_file_dir_path):
|
|
548
|
+
logger.error(f"Restart files not found: {restart_file_dir_path}")
|
|
549
|
+
raise FileNotFoundError(f"Restart files not found: {restart_file_dir_path}")
|
|
550
|
+
|
|
551
|
+
file_list = [x for x in listdir(restart_file_dir_path) if x.startswith("wrfrst")]
|
|
552
|
+
for _file in file_list:
|
|
553
|
+
_file_config: FileConfigDict = {
|
|
554
|
+
"file_path": f"{self.restart_file_dir_path}/{_file}",
|
|
555
|
+
"save_path": WRFRUNConfig.WRF_WORK_PATH,
|
|
556
|
+
"save_name": _file,
|
|
557
|
+
"is_data": True,
|
|
558
|
+
"is_output": False
|
|
559
|
+
}
|
|
560
|
+
self.add_input_files(_file_config)
|
|
561
|
+
|
|
562
|
+
super().before_exec()
|
|
563
|
+
|
|
564
|
+
WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "wrf")
|
|
565
|
+
|
|
566
|
+
def after_exec(self):
|
|
567
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
568
|
+
self.add_output_files(save_path=self._log_save_path, startswith="rsl.", outputs="namelist.input")
|
|
569
|
+
self.add_output_files(save_path=self._output_save_path, startswith="wrfout")
|
|
570
|
+
if self.save_restarts:
|
|
571
|
+
restart_save_path = f"{self._output_save_path}/restart"
|
|
572
|
+
self.add_output_files(save_path=restart_save_path, startswith="wrfrst", no_file_error=False)
|
|
573
|
+
|
|
574
|
+
super().after_exec()
|
|
575
|
+
|
|
576
|
+
logger.info(f"All wrf output files have been copied to {WRFRUNConfig.parse_resource_uri(self._output_save_path)}")
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
class DFI(ExecutableBase):
|
|
580
|
+
"""
|
|
581
|
+
Execute "wrf.exe" to run DFI.
|
|
582
|
+
"""
|
|
583
|
+
|
|
584
|
+
def __init__(self, input_file_dir_path: Optional[str] = None, update_real_output=True, core_num: Optional[int] = None):
|
|
585
|
+
"""
|
|
586
|
+
Execute "wrf.exe" to run DFI.
|
|
587
|
+
|
|
588
|
+
:param input_file_dir_path: Path of the directory that stores input data for "wrf.exe".
|
|
589
|
+
:type input_file_dir_path: str
|
|
590
|
+
:param update_real_output: If update the corresponding file in real.exe output directory.
|
|
591
|
+
:type update_real_output: bool
|
|
592
|
+
:param core_num: An positive integer number of used core numbers. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
|
|
593
|
+
:type core_num: int
|
|
594
|
+
"""
|
|
595
|
+
if isinstance(core_num, int) and core_num <= 0:
|
|
596
|
+
logger.warning(f"`core_num` should be greater than 0")
|
|
597
|
+
core_num = None
|
|
598
|
+
|
|
599
|
+
if core_num is None:
|
|
600
|
+
mpi_use = False
|
|
601
|
+
mpi_cmd = None
|
|
602
|
+
mpi_core_num = core_num
|
|
603
|
+
|
|
604
|
+
else:
|
|
605
|
+
mpi_use = True
|
|
606
|
+
mpi_cmd = "mpirun"
|
|
607
|
+
mpi_core_num = core_num
|
|
608
|
+
|
|
609
|
+
super().__init__(name="dfi", cmd="./wrf.exe", work_path=WRFRUNConfig.WRF_WORK_PATH, mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
|
|
610
|
+
|
|
611
|
+
self.input_file_dir_path = input_file_dir_path
|
|
612
|
+
self.update_real_output = update_real_output
|
|
613
|
+
|
|
614
|
+
def generate_custom_config(self):
|
|
615
|
+
self.custom_config.update(
|
|
616
|
+
{
|
|
617
|
+
"input_file_dir_path": self.input_file_dir_path,
|
|
618
|
+
"update_real_output": self.update_real_output,
|
|
619
|
+
"namelist": WRFRUNConfig.get_namelist("dfi")
|
|
620
|
+
}
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
def load_custom_config(self):
|
|
624
|
+
self.input_file_dir_path = self.custom_config["input_file_dir_path"]
|
|
625
|
+
self.update_real_output = self.custom_config["update_real_output"]
|
|
626
|
+
|
|
627
|
+
if not WRFRUNConfig.register_custom_namelist_id("dfi"):
|
|
628
|
+
logger.error("Can't register namelist for DFI.")
|
|
629
|
+
raise NamelistError("Can't register namelist for DFI.")
|
|
630
|
+
WRFRUNConfig.update_namelist(self.custom_config["namelist"], "dfi")
|
|
631
|
+
|
|
632
|
+
def before_exec(self):
|
|
633
|
+
WRFRUNConfig.check_wrfrun_context(True)
|
|
634
|
+
WRFRUNConfig.WRFRUN_WORK_STATUS = "dfi"
|
|
635
|
+
|
|
636
|
+
if not WRFRUNConfig.IS_IN_REPLAY and not WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
637
|
+
# prepare config
|
|
638
|
+
if self.input_file_dir_path is None:
|
|
639
|
+
self.input_file_dir_path = f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/real"
|
|
640
|
+
is_output = True
|
|
641
|
+
|
|
642
|
+
else:
|
|
643
|
+
is_output = False
|
|
644
|
+
|
|
645
|
+
input_file_dir_path = WRFRUNConfig.parse_resource_uri(self.input_file_dir_path)
|
|
646
|
+
|
|
647
|
+
if exists(input_file_dir_path):
|
|
648
|
+
file_list = [x for x in listdir(input_file_dir_path) if x != "logs"]
|
|
649
|
+
|
|
650
|
+
for _file in file_list:
|
|
651
|
+
_file_config: FileConfigDict = {
|
|
652
|
+
"file_path": f"{self.input_file_dir_path}/{_file}",
|
|
653
|
+
"save_path": WRFRUNConfig.WRF_WORK_PATH,
|
|
654
|
+
"save_name": _file,
|
|
655
|
+
"is_data": True,
|
|
656
|
+
"is_output": is_output
|
|
657
|
+
}
|
|
658
|
+
self.add_input_files(_file_config)
|
|
659
|
+
|
|
660
|
+
if not WRFRUNConfig.register_custom_namelist_id("dfi"):
|
|
661
|
+
logger.error("Can't register namelist for DFI.")
|
|
662
|
+
raise NamelistError("Can't register namelist for DFI.")
|
|
663
|
+
|
|
664
|
+
prepare_dfi_namelist()
|
|
665
|
+
|
|
666
|
+
super().before_exec()
|
|
667
|
+
WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "dfi")
|
|
668
|
+
|
|
669
|
+
def after_exec(self):
|
|
670
|
+
if not WRFRUNConfig.IS_IN_REPLAY:
|
|
671
|
+
self.add_output_files(save_path=self._log_save_path, startswith="rsl.", outputs="namelist.input")
|
|
672
|
+
self.add_output_files(save_path=self._output_save_path, startswith="wrfinput_initialized_")
|
|
673
|
+
|
|
674
|
+
super().after_exec()
|
|
675
|
+
|
|
676
|
+
parsed_output_save_path = WRFRUNConfig.parse_resource_uri(self._output_save_path)
|
|
677
|
+
if self.update_real_output and not WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
678
|
+
real_dir_path = WRFRUNConfig.parse_resource_uri(self.input_file_dir_path)
|
|
679
|
+
|
|
680
|
+
move(f"{real_dir_path}/wrfinput_d01", f"{real_dir_path}/wrfinput_d01_before_dfi")
|
|
681
|
+
copyfile(f"{parsed_output_save_path}/wrfinput_initialized_d01", f"{real_dir_path}/wrfinput_d01")
|
|
682
|
+
logger.info(f"Replace real.exe output 'wrfinput_d01' with outputs, old file has been renamed as 'wrfinput_d01_before_dfi'")
|
|
683
|
+
|
|
684
|
+
logger.info(f"All DFI output files have been copied to {parsed_output_save_path}")
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
class NDown(ExecutableBase):
|
|
688
|
+
"""
|
|
689
|
+
Execute "ndown.exe".
|
|
690
|
+
"""
|
|
691
|
+
|
|
692
|
+
def __init__(self, wrfout_file_path: str, real_output_dir_path: Optional[str] = None, update_namelist=True, core_num: Optional[int] = None):
|
|
693
|
+
"""
|
|
694
|
+
Execute "ndown.exe".
|
|
695
|
+
|
|
696
|
+
:param wrfout_file_path: wrfout file path.
|
|
697
|
+
:type wrfout_file_path: str
|
|
698
|
+
:param real_output_dir_path: Path of the directory that contains output of "real.exe".
|
|
699
|
+
:type real_output_dir_path: str
|
|
700
|
+
:param update_namelist: If update wrf's namelist for the final integral.
|
|
701
|
+
:type update_namelist: bool
|
|
702
|
+
:param core_num:
|
|
703
|
+
:type core_num:
|
|
704
|
+
"""
|
|
705
|
+
if isinstance(core_num, int) and core_num <= 0:
|
|
706
|
+
logger.warning(f"`core_num` should be greater than 0")
|
|
707
|
+
core_num = None
|
|
708
|
+
|
|
709
|
+
if core_num is None:
|
|
710
|
+
mpi_use = False
|
|
711
|
+
mpi_cmd = None
|
|
712
|
+
mpi_core_num = core_num
|
|
713
|
+
|
|
714
|
+
else:
|
|
715
|
+
mpi_use = True
|
|
716
|
+
mpi_cmd = "mpirun"
|
|
717
|
+
mpi_core_num = core_num
|
|
718
|
+
|
|
719
|
+
_check_namelist_preparation()
|
|
720
|
+
|
|
721
|
+
super().__init__(name="ndown", cmd="./ndown.exe", work_path=WRFRUNConfig.WRF_WORK_PATH, mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
|
|
722
|
+
|
|
723
|
+
self.wrfout_file_path = wrfout_file_path
|
|
724
|
+
self.real_output_dir_path = real_output_dir_path
|
|
725
|
+
self.update_namelist = update_namelist
|
|
726
|
+
|
|
727
|
+
def generate_custom_config(self):
|
|
728
|
+
self.class_config["class_args"] = (self.wrfout_file_path,)
|
|
729
|
+
self.custom_config.update(
|
|
730
|
+
{
|
|
731
|
+
"real_output_dir_path": self.real_output_dir_path,
|
|
732
|
+
"update_namelist": self.update_namelist,
|
|
733
|
+
"namelist": WRFRUNConfig.get_namelist("wrf"),
|
|
734
|
+
}
|
|
735
|
+
)
|
|
736
|
+
|
|
737
|
+
def load_custom_config(self):
|
|
738
|
+
self.real_output_dir_path = self.custom_config["real_output_dir_path"]
|
|
739
|
+
self.update_namelist = self.custom_config["update_namelist"]
|
|
740
|
+
WRFRUNConfig.update_namelist(self.custom_config["namelist"])
|
|
741
|
+
|
|
742
|
+
def before_exec(self):
|
|
743
|
+
WRFRUNConfig.check_wrfrun_context(True)
|
|
744
|
+
WRFRUNConfig.WRFRUN_WORK_STATUS = "ndown"
|
|
745
|
+
|
|
746
|
+
# we need to make sure time_control.io_form_auxinput2 is 2.
|
|
747
|
+
# which means the format of input stream 2 is NetCDF.
|
|
748
|
+
WRFRUNConfig.update_namelist({"time_control": {"io_form_auxinput2": 2}}, "wrf")
|
|
749
|
+
|
|
750
|
+
if self.real_output_dir_path is None:
|
|
751
|
+
self.real_output_dir_path = f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/real"
|
|
752
|
+
is_output = True
|
|
753
|
+
|
|
754
|
+
else:
|
|
755
|
+
is_output = False
|
|
756
|
+
|
|
757
|
+
wrfndi_file_config: FileConfigDict = {
|
|
758
|
+
"file_path": f"{self.real_output_dir_path}/wrfinput_d02",
|
|
759
|
+
"save_path": WRFRUNConfig.WRF_WORK_PATH,
|
|
760
|
+
"save_name": "wrfndi_d02",
|
|
761
|
+
"is_data": True,
|
|
762
|
+
"is_output": is_output
|
|
763
|
+
}
|
|
764
|
+
wrfout_file_config: FileConfigDict = {
|
|
765
|
+
"file_path": self.wrfout_file_path,
|
|
766
|
+
"save_path": WRFRUNConfig.WRF_WORK_PATH,
|
|
767
|
+
"save_name": "wrfout_d01",
|
|
768
|
+
"is_data": True,
|
|
769
|
+
"is_output": False
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
self.add_input_files([wrfndi_file_config, wrfout_file_config])
|
|
773
|
+
|
|
774
|
+
super().before_exec()
|
|
775
|
+
|
|
776
|
+
WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "wrf")
|
|
777
|
+
|
|
778
|
+
def after_exec(self):
|
|
779
|
+
self.add_output_files(save_path=self._log_save_path, startswith="rsl.", outputs="namelist.input")
|
|
780
|
+
self.add_output_files(save_path=self._output_save_path, outputs=["wrfinput_d02", "wrfbdy_d02"])
|
|
781
|
+
# also save other outputs of real.exe, so WRF can directly use them.
|
|
782
|
+
self.add_output_files(output_dir=f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/real", save_path=self._output_save_path,
|
|
783
|
+
startswith="wrflowinp_", no_file_error=False)
|
|
784
|
+
|
|
785
|
+
super().after_exec()
|
|
786
|
+
|
|
787
|
+
parsed_output_save_path = WRFRUNConfig.parse_resource_uri(self._output_save_path)
|
|
788
|
+
|
|
789
|
+
move(f"{parsed_output_save_path}/wrfinput_d02", f"{parsed_output_save_path}/wrfinput_d01")
|
|
790
|
+
move(f"{parsed_output_save_path}/wrfbdy_d02", f"{parsed_output_save_path}/wrfbdy_d01")
|
|
791
|
+
|
|
792
|
+
logger.info(f"All ndown output files have been copied to {parsed_output_save_path}")
|
|
793
|
+
|
|
794
|
+
if self.update_namelist:
|
|
795
|
+
process_after_ndown()
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
class_list = [GeoGrid, LinkGrib, UnGrib, MetGrid, Real, WRF, NDown]
|
|
799
|
+
class_id_list = ["geogrid", "link_grib", "ungrib", "metgrid", "real", "wrf", "ndown"]
|
|
800
|
+
|
|
801
|
+
for _class, _id in zip(class_list, class_id_list):
|
|
802
|
+
if not WRFRUNExecDB.is_registered(_id):
|
|
803
|
+
WRFRUNExecDB.register_exec(_id, _class)
|
|
804
|
+
|
|
805
|
+
__all__ = ["GeoGrid", "LinkGrib", "UnGrib", "MetGrid", "Real", "WRF", "DFI", "NDown"]
|