wrfrun 0.1.8__py3-none-any.whl → 0.2.0__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.
Files changed (53) hide show
  1. wrfrun/cli.py +131 -0
  2. wrfrun/core/base.py +52 -19
  3. wrfrun/core/config.py +257 -170
  4. wrfrun/core/error.py +8 -1
  5. wrfrun/core/replay.py +1 -1
  6. wrfrun/core/server.py +91 -71
  7. wrfrun/data.py +14 -16
  8. wrfrun/extension/goos_sst/__init__.py +5 -5
  9. wrfrun/extension/goos_sst/core.py +4 -1
  10. wrfrun/extension/goos_sst/res/Vtable.ERA_GOOS_SST +1 -1
  11. wrfrun/extension/goos_sst/res/__init__.py +17 -0
  12. wrfrun/extension/goos_sst/utils.py +21 -5
  13. wrfrun/extension/littler/__init__.py +57 -1
  14. wrfrun/extension/littler/{utils.py → core.py} +329 -43
  15. wrfrun/extension/utils.py +24 -22
  16. wrfrun/model/__init__.py +24 -1
  17. wrfrun/model/plot.py +259 -36
  18. wrfrun/model/utils.py +19 -9
  19. wrfrun/model/wrf/__init__.py +41 -0
  20. wrfrun/model/wrf/core.py +229 -101
  21. wrfrun/model/wrf/exec_wrap.py +49 -35
  22. wrfrun/model/wrf/geodata.py +2 -1
  23. wrfrun/model/wrf/namelist.py +78 -4
  24. wrfrun/model/wrf/{_metgrid.py → utils.py} +38 -3
  25. wrfrun/model/wrf/vtable.py +9 -5
  26. wrfrun/res/__init__.py +22 -7
  27. wrfrun/res/config/config.template.toml +57 -0
  28. wrfrun/res/{config.toml.template → config/wrf.template.toml} +7 -46
  29. wrfrun/res/run.template.sh +10 -0
  30. wrfrun/res/scheduler/lsf.template +5 -0
  31. wrfrun/res/{job_scheduler → scheduler}/pbs.template +1 -1
  32. wrfrun/res/{job_scheduler → scheduler}/slurm.template +2 -1
  33. wrfrun/run.py +39 -27
  34. wrfrun/scheduler/__init__.py +35 -0
  35. wrfrun/scheduler/env.py +44 -0
  36. wrfrun/scheduler/lsf.py +49 -0
  37. wrfrun/scheduler/pbs.py +50 -0
  38. wrfrun/scheduler/script.py +72 -0
  39. wrfrun/scheduler/slurm.py +50 -0
  40. wrfrun/scheduler/utils.py +14 -0
  41. wrfrun/utils.py +8 -3
  42. wrfrun/workspace/__init__.py +38 -0
  43. wrfrun/workspace/core.py +94 -0
  44. wrfrun/workspace/wrf.py +165 -0
  45. {wrfrun-0.1.8.dist-info → wrfrun-0.2.0.dist-info}/METADATA +3 -2
  46. wrfrun-0.2.0.dist-info/RECORD +62 -0
  47. wrfrun-0.2.0.dist-info/entry_points.txt +3 -0
  48. wrfrun/model/wrf/_ndown.py +0 -39
  49. wrfrun/pbs.py +0 -86
  50. wrfrun/res/run.sh.template +0 -16
  51. wrfrun/workspace.py +0 -88
  52. wrfrun-0.1.8.dist-info/RECORD +0 -51
  53. {wrfrun-0.1.8.dist-info → wrfrun-0.2.0.dist-info}/WHEEL +0 -0
wrfrun/model/wrf/core.py CHANGED
@@ -1,40 +1,67 @@
1
+ """
2
+ wrfrun.model.wrf.core
3
+ #####################
4
+
5
+ Core implementation of WRF model. All ``Executable`` of WPS / WRF model are defined here.
6
+
7
+ If you prefer function interfaces, please see :doc:`function wrapper </api/model.wrf.exec_wrap>` for these ``Executable``.
8
+
9
+ .. autosummary::
10
+ :toctree: generated/
11
+
12
+ GeoGrid
13
+ LinkGrib
14
+ UnGrib
15
+ MetGrid
16
+ Real
17
+ WRF
18
+ DFI
19
+ NDown
20
+ """
21
+
1
22
  from os import listdir
2
23
  from os.path import abspath, basename, exists
3
24
  from shutil import copyfile, move, rmtree
4
- from typing import Optional
25
+ from typing import Optional, Union
5
26
 
6
- from wrfrun.core import ExecutableBase, FileConfigDict, InputFileError, NamelistIDError, WRFRUNConfig, WRFRUNExecDB
27
+ from wrfrun.core import ExecutableBase, FileConfigDict, InputFileError, NamelistIDError, WRFRUNConfig, WRFRUNExecDB, get_wrfrun_config
7
28
  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
29
+ from wrfrun.workspace.wrf import get_wrf_workspace_path
30
+ from .namelist import (get_ungrib_out_dir_path, get_ungrib_out_prefix, prepare_dfi_namelist, prepare_wps_namelist, prepare_wrf_namelist, prepare_wrfda_namelist,
31
+ set_metgrid_fg_names, set_ungrib_out_prefix)
32
+ from .utils import process_after_ndown, reconcile_namelist_metgrid
11
33
  from .vtable import VtableFiles
12
34
  from ..base import NamelistName
13
35
 
14
36
 
15
- def _check_namelist_preparation():
16
- if len(WRFRUNConfig.get_namelist("wps")) == 0:
37
+ def _check_and_prepare_namelist():
38
+ """
39
+ This function check if namelists needed by WPS/WRF have been loaded,
40
+ and prepare namelist if check fails.
41
+ """
42
+ wrfrun_config = get_wrfrun_config()
43
+ if not wrfrun_config.check_namelist("wps"):
17
44
  prepare_wps_namelist()
18
45
 
19
- if len(WRFRUNConfig.get_namelist("wrf")) == 0:
46
+ if not wrfrun_config.check_namelist("wrf"):
20
47
  prepare_wrf_namelist()
21
48
 
22
- if len(WRFRUNConfig.get_namelist("wrfda")) == 0:
49
+ if not wrfrun_config.check_namelist("wrfda"):
23
50
  prepare_wrfda_namelist()
24
51
 
25
52
 
26
53
  class GeoGrid(ExecutableBase):
27
54
  """
28
- Execute "geogrid.exe".
55
+ ``Executable`` for "geogrid.exe".
29
56
  """
30
57
 
31
58
  def __init__(self, geogrid_tbl_file: Optional[str] = None, core_num: Optional[int] = None):
32
59
  """
33
- Execute "geogrid.exe".
60
+ ``Executable`` for "geogrid.exe".
34
61
 
35
62
  :param geogrid_tbl_file: Custom GEOGRID.TBL file path. Defaults to None.
36
63
  :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``.
64
+ :param core_num: An positive integer number. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
38
65
  :type core_num: int
39
66
  """
40
67
  if isinstance(core_num, int) and core_num <= 0:
@@ -51,17 +78,18 @@ class GeoGrid(ExecutableBase):
51
78
  mpi_cmd = "mpirun"
52
79
  mpi_core_num = core_num
53
80
 
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)
81
+ super().__init__(name="geogrid", cmd="./geogrid.exe", work_path=get_wrf_workspace_path('wps'), mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
55
82
 
56
83
  self.geogrid_tbl_file = geogrid_tbl_file
57
84
 
58
- _check_namelist_preparation()
85
+ _check_and_prepare_namelist()
59
86
 
60
87
  def generate_custom_config(self):
61
88
  """
62
- Get and store namelist.
63
- :return:
64
- :rtype:
89
+ Store custom configs, including:
90
+
91
+ 1. Namelist settings.
92
+ 2. Path of custom TBL file.
65
93
  """
66
94
  self.custom_config.update(
67
95
  {
@@ -71,6 +99,9 @@ class GeoGrid(ExecutableBase):
71
99
  )
72
100
 
73
101
  def load_custom_config(self):
102
+ """
103
+ Load custom configs.
104
+ """
74
105
  WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wps")
75
106
  self.geogrid_tbl_file = self.custom_config["geogrid_tbl_file"]
76
107
 
@@ -81,14 +112,18 @@ class GeoGrid(ExecutableBase):
81
112
  if not WRFRUNConfig.IS_IN_REPLAY:
82
113
  if self.geogrid_tbl_file is not None:
83
114
  tbl_file: FileConfigDict = {
84
- "file_path": self.geogrid_tbl_file, "save_path": f"{WRFRUNConfig.WPS_WORK_PATH}/geogrid",
115
+ "file_path": self.geogrid_tbl_file, "save_path": f"{get_wrf_workspace_path('wps')}/geogrid",
85
116
  "save_name": "GEOGRID.TBL", "is_data": False, "is_output": False
86
117
  }
87
118
  self.add_input_files(tbl_file)
88
119
 
89
120
  super().before_exec()
90
121
 
91
- WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WPS_WORK_PATH}/{NamelistName.WPS}", "wps")
122
+ WRFRUNConfig.write_namelist(f"{get_wrf_workspace_path('wps')}/{NamelistName.WPS}", "wps")
123
+
124
+ # print debug logs
125
+ logger.debug("Namelist settings of 'geogrid':")
126
+ logger.debug(WRFRUNConfig.get_namelist("wps"))
92
127
 
93
128
  def after_exec(self):
94
129
  if not WRFRUNConfig.IS_IN_REPLAY:
@@ -102,26 +137,28 @@ class GeoGrid(ExecutableBase):
102
137
 
103
138
  class LinkGrib(ExecutableBase):
104
139
  """
105
- Run command: "./link_grib.csh".
140
+ ``Executable`` for "./link_grib.csh".
106
141
  """
107
142
 
108
143
  def __init__(self, grib_dir_path: str):
109
144
  """
110
- Execute "link_grib.csh".
145
+ ``Executable`` for "link_grib.csh".
111
146
 
112
- :param grib_dir_path: GRIB data path. Absolute path is recommended.
147
+ :param grib_dir_path: GRIB data directory path. Absolute path is recommended.
113
148
  :type grib_dir_path: str
114
149
  """
115
150
  self._link_grib_input_path = "./input_grib_data_dir"
116
151
 
117
- super().__init__(name="link_grib", cmd=["./link_grib.csh", f"{self._link_grib_input_path}/*", "."], work_path=WRFRUNConfig.WPS_WORK_PATH)
152
+ super().__init__(name="link_grib", cmd=["./link_grib.csh", f"{self._link_grib_input_path}/*", "."], work_path=get_wrf_workspace_path('wps'))
118
153
  self.grib_dir_path = grib_dir_path
119
154
 
120
155
  def generate_custom_config(self):
121
- self.class_config["class_args"] = (self.grib_dir_path,)
156
+ """
157
+ Store custom configs, including:
122
158
 
123
- def replay(self):
124
- self()
159
+ 1. Positional arguments of this ``Executable``.
160
+ """
161
+ self.class_config["class_args"] = (self.grib_dir_path,)
125
162
 
126
163
  def before_exec(self):
127
164
  if not WRFRUNConfig.IS_IN_REPLAY:
@@ -133,7 +170,7 @@ class LinkGrib(ExecutableBase):
133
170
  logger.error(f"GRIB file directory not found: {_grib_dir_path}")
134
171
  raise FileNotFoundError(f"GRIB file directory not found: {_grib_dir_path}")
135
172
 
136
- save_path = f"{WRFRUNConfig.WPS_WORK_PATH}/{self._link_grib_input_path}"
173
+ save_path = f"{get_wrf_workspace_path('wps')}/{self._link_grib_input_path}"
137
174
  save_path = WRFRUNConfig.parse_resource_uri(save_path)
138
175
  if exists(save_path):
139
176
  rmtree(save_path)
@@ -141,7 +178,7 @@ class LinkGrib(ExecutableBase):
141
178
  for _file in listdir(_grib_dir_path):
142
179
  _file_config: FileConfigDict = {
143
180
  "file_path": f"{_grib_dir_path}/{_file}",
144
- "save_path": f"{WRFRUNConfig.WPS_WORK_PATH}/{self._link_grib_input_path}",
181
+ "save_path": f"{get_wrf_workspace_path('wps')}/{self._link_grib_input_path}",
145
182
  "save_name": _file, "is_data": True, "is_output": False,
146
183
  }
147
184
  self.add_input_files(_file_config)
@@ -151,43 +188,56 @@ class LinkGrib(ExecutableBase):
151
188
 
152
189
  class UnGrib(ExecutableBase):
153
190
  """
154
- Execute "ungrib.exe".
191
+ ``Executable`` for "ungrib.exe".
155
192
  """
156
193
 
157
194
  def __init__(self, vtable_file: Optional[str] = None, input_data_path: Optional[str] = None):
158
195
  """
159
- Execute "ungrib.exe".
196
+ ``Executable`` for "ungrib.exe".
160
197
 
161
- :param vtable_file: Path of the Vtable file "ungrib.exe" used.
198
+ :param vtable_file: Path of the Vtable file.
199
+ Defaults to :attr:`VtableFiles.ERA_PL <vtable.VtableFiles.ERA_PL>`.
162
200
  :type vtable_file: str
163
- :param input_data_path: Path of the directory stores input GRIB2 files.
201
+ :param input_data_path: Directory path of input GRIB files.
202
+ Defaults to ``input_data_path`` set in user's config file.
164
203
  :type input_data_path: str
165
204
  """
166
- super().__init__(name="ungrib", cmd="./ungrib.exe", work_path=WRFRUNConfig.WPS_WORK_PATH)
205
+ super().__init__(name="ungrib", cmd="./ungrib.exe", work_path=get_wrf_workspace_path('wps'))
167
206
 
168
207
  self.vtable_file = vtable_file
169
208
  self.input_data_path = input_data_path
170
209
 
171
- _check_namelist_preparation()
210
+ _check_and_prepare_namelist()
172
211
 
173
212
  def call_link_grib(self):
174
213
  """
175
- Execute "link_grib.csh" if needed.
176
-
177
- :return:
178
- :rtype:
214
+ Call :class:`LinkGrib` if needed.
179
215
  """
180
216
  if self.input_data_path is None:
181
217
  self.input_data_path = WRFRUNConfig.get_input_data_path()
182
218
 
183
219
  LinkGrib(self.input_data_path)()
184
220
 
221
+ def set_ungrib_output_prefix(self, prefix="FILE") -> "UnGrib":
222
+ """
223
+ This method is the same as :func:`set_ungrib_output_prefix <wrfrun.model.wrf.namelist.set_ungrib_output_prefix>`.
224
+ ``wrfrun`` provide this method to avoid changing namelist before loading it.
225
+
226
+ :param prefix: Prefix of outputs.
227
+ :type prefix: str
228
+ :return: This instance itself.
229
+ :rtype: UnGrib
230
+ """
231
+ prefix = basename(prefix)
232
+ set_ungrib_out_prefix(prefix)
233
+ return self
234
+
185
235
  def generate_custom_config(self):
186
236
  """
187
- Get and store namelist.
237
+ Store custom configs, including:
188
238
 
189
- :return:
190
- :rtype:
239
+ 1. Namelist settings.
240
+ 2. Path of used VTable file.
191
241
  """
192
242
  self.custom_config.update(
193
243
  {
@@ -197,12 +247,12 @@ class UnGrib(ExecutableBase):
197
247
  )
198
248
 
199
249
  def load_custom_config(self):
250
+ """
251
+ Load custom configs.
252
+ """
200
253
  self.vtable_file = self.custom_config["vtable_file"]
201
254
  WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wps")
202
255
 
203
- def replay(self):
204
- super().__call__()
205
-
206
256
  def before_exec(self):
207
257
  WRFRUNConfig.check_wrfrun_context(True)
208
258
  WRFRUNConfig.WRFRUN_WORK_STATUS = "ungrib"
@@ -213,7 +263,7 @@ class UnGrib(ExecutableBase):
213
263
 
214
264
  _file_config: FileConfigDict = {
215
265
  "file_path": self.vtable_file,
216
- "save_path": WRFRUNConfig.WPS_WORK_PATH,
266
+ "save_path": get_wrf_workspace_path('wps'),
217
267
  "save_name": "Vtable",
218
268
  "is_data": False,
219
269
  "is_output": False
@@ -222,11 +272,15 @@ class UnGrib(ExecutableBase):
222
272
 
223
273
  super().before_exec()
224
274
 
225
- WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WPS_WORK_PATH}/{NamelistName.WPS}", "wps")
275
+ WRFRUNConfig.write_namelist(f"{get_wrf_workspace_path('wps')}/{NamelistName.WPS}", "wps")
276
+
277
+ # print debug logs
278
+ logger.debug("Namelist settings of 'ungrib':")
279
+ logger.debug(WRFRUNConfig.get_namelist("wps"))
226
280
 
227
281
  def after_exec(self):
228
282
  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())
283
+ self.add_output_files(output_dir=get_ungrib_out_dir_path(), save_path=self._output_save_path, startswith=get_ungrib_out_prefix())
230
284
  self.add_output_files(save_path=self._log_save_path, outputs=["ungrib.log", "namelist.wps"])
231
285
 
232
286
  super().after_exec()
@@ -241,18 +295,20 @@ class UnGrib(ExecutableBase):
241
295
 
242
296
  class MetGrid(ExecutableBase):
243
297
  """
244
- Execute "metgrid.exe".
298
+ ``Executable`` of "metgrid.exe".
245
299
  """
246
300
 
247
301
  def __init__(self, geogrid_data_path: Optional[str] = None, ungrib_data_path: Optional[str] = None, core_num: Optional[int] = None):
248
302
  """
249
- Execute "metgrid.exe".
303
+ ``Executable`` of "metgrid.exe".
250
304
 
251
- :param geogrid_data_path: Directory path of outputs from geogrid.exe. If None, tries to use the output path specified by config file.
305
+ :param geogrid_data_path: Directory path of :class:`GeoGrid` outputs.
306
+ If is ``None``, try to use the output path specified by config file.
252
307
  :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.
308
+ :param ungrib_data_path: Directory path of :class:`UnGrib` outputs.
309
+ If is ``None``, try to use the output path specified by config file.
254
310
  :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``.
311
+ :param core_num: An positive integer number. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
256
312
  :type core_num: int
257
313
  """
258
314
  if isinstance(core_num, int) and core_num <= 0:
@@ -269,18 +325,34 @@ class MetGrid(ExecutableBase):
269
325
  mpi_cmd = "mpirun"
270
326
  mpi_core_num = core_num
271
327
 
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)
328
+ super().__init__(name="metgrid", cmd="./metgrid.exe", work_path=get_wrf_workspace_path('wps'), mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
273
329
 
274
330
  self.geogrid_data_path = geogrid_data_path
275
331
  self.ungrib_data_path = ungrib_data_path
276
332
 
277
- _check_namelist_preparation()
333
+ _check_and_prepare_namelist()
334
+
335
+ def set_metgrid_fg_names(self, fg_names: Union[str, list[str]] = "FILE") -> "MetGrid":
336
+ """
337
+ This method
338
+ :param fg_names: ``fg_name`` of metgrid, a single prefix string or a string list.
339
+ :type fg_names: str | list
340
+ :return: This instance itself.
341
+ :rtype: MetGrid
342
+ """
343
+ if isinstance(fg_names, str):
344
+ fg_names = [fg_names, ]
345
+ fg_names = [basename(x) for x in fg_names]
346
+ set_metgrid_fg_names(fg_names)
347
+ return self
278
348
 
279
349
  def generate_custom_config(self):
280
350
  """
281
- Get and store namelist.
282
- :return:
283
- :rtype:
351
+ Store custom configs, including:
352
+
353
+ 1. Directory path of :class:`GeoGrid` outputs.
354
+ 2. Directory path of :class:`UnGrib` outputs.
355
+ 3. Namelist settings.
284
356
  """
285
357
  self.custom_config.update(
286
358
  {
@@ -291,6 +363,9 @@ class MetGrid(ExecutableBase):
291
363
  )
292
364
 
293
365
  def load_custom_config(self):
366
+ """
367
+ Load custom configs.
368
+ """
294
369
  self.geogrid_data_path = self.custom_config["geogrid_data_path"]
295
370
  self.ungrib_data_path = self.custom_config["ungrib_data_path"]
296
371
  WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wps")
@@ -302,7 +377,7 @@ class MetGrid(ExecutableBase):
302
377
  if not WRFRUNConfig.IS_IN_REPLAY and not WRFRUNConfig.FAKE_SIMULATION_MODE:
303
378
  # check input of metgrid.exe
304
379
  # 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))
380
+ file_list = listdir(WRFRUNConfig.parse_resource_uri(get_wrf_workspace_path('wps')))
306
381
 
307
382
  if "geo_em.d01.nc" not in file_list:
308
383
 
@@ -319,14 +394,14 @@ class MetGrid(ExecutableBase):
319
394
  for _file in geogrid_file_list:
320
395
  _file_config = {
321
396
  "file_path": f"{self.geogrid_data_path}/{_file}",
322
- "save_path": WRFRUNConfig.WPS_WORK_PATH,
397
+ "save_path": get_wrf_workspace_path('wps'),
323
398
  "save_name": _file,
324
399
  "is_data": True,
325
400
  "is_output": True
326
401
  }
327
402
  self.add_input_files(_file_config)
328
403
 
329
- ungrib_output_dir = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.get_ungrib_out_dir_path())
404
+ ungrib_output_dir = WRFRUNConfig.parse_resource_uri(get_ungrib_out_dir_path())
330
405
  if basename(ungrib_output_dir) not in file_list or len(listdir(ungrib_output_dir)) == 0:
331
406
 
332
407
  if self.ungrib_data_path is None:
@@ -343,7 +418,7 @@ class MetGrid(ExecutableBase):
343
418
  for _file in ungrib_file_list:
344
419
  _file_config: FileConfigDict = {
345
420
  "file_path": f"{self.ungrib_data_path}/{_file}",
346
- "save_path": WRFRUNConfig.get_ungrib_out_dir_path(),
421
+ "save_path": get_ungrib_out_dir_path(),
347
422
  "save_name": _file,
348
423
  "is_data": True,
349
424
  "is_output": True
@@ -352,7 +427,11 @@ class MetGrid(ExecutableBase):
352
427
 
353
428
  super().before_exec()
354
429
 
355
- WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WPS_WORK_PATH}/{NamelistName.WPS}", "wps")
430
+ WRFRUNConfig.write_namelist(f"{get_wrf_workspace_path('wps')}/{NamelistName.WPS}", "wps")
431
+
432
+ # print debug logs
433
+ logger.debug("Namelist settings of 'metgrid':")
434
+ logger.debug(WRFRUNConfig.get_namelist("wps"))
356
435
 
357
436
  def after_exec(self):
358
437
  if not WRFRUNConfig.IS_IN_REPLAY:
@@ -366,16 +445,17 @@ class MetGrid(ExecutableBase):
366
445
 
367
446
  class Real(ExecutableBase):
368
447
  """
369
- Execute "real.exe".
448
+ ``Executable`` of "real.exe".
370
449
  """
371
450
 
372
451
  def __init__(self, metgrid_data_path: Optional[str] = None, core_num: Optional[int] = None):
373
452
  """
374
- Execute "real.exe".
453
+ ``Executable`` of "real.exe".
375
454
 
376
- :param metgrid_data_path: Path of the directory stores outputs from "metgrid.exe".
455
+ :param metgrid_data_path: Directory path of :class:`MetGrid` outputs.
456
+ If is ``None``, try to use the workspace path or output path in the config file.
377
457
  :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``.
458
+ :param core_num: An positive integer number. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
379
459
  :type core_num: int
380
460
  """
381
461
  if isinstance(core_num, int) and core_num <= 0:
@@ -392,13 +472,19 @@ class Real(ExecutableBase):
392
472
  mpi_cmd = "mpirun"
393
473
  mpi_core_num = core_num
394
474
 
395
- _check_namelist_preparation()
475
+ _check_and_prepare_namelist()
396
476
 
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)
477
+ super().__init__(name="real", cmd="./real.exe", work_path=get_wrf_workspace_path('wrf'), mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
398
478
 
399
479
  self.metgrid_data_path = metgrid_data_path
400
480
 
401
481
  def generate_custom_config(self):
482
+ """
483
+ Store custom configs, including:
484
+
485
+ 1. Namelist settings.
486
+ 2. Directory path of :class:`MetGrid` outputs.
487
+ """
402
488
  self.custom_config["metgrid_data_path"] = self.metgrid_data_path
403
489
  self.custom_config.update(
404
490
  {
@@ -408,6 +494,9 @@ class Real(ExecutableBase):
408
494
  )
409
495
 
410
496
  def load_custom_config(self):
497
+ """
498
+ Load custom configs.
499
+ """
411
500
  self.metgrid_data_path = self.custom_config["metgrid_data_path"]
412
501
  WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wrf")
413
502
 
@@ -426,7 +515,7 @@ class Real(ExecutableBase):
426
515
  for _file in file_list:
427
516
  _file_config: FileConfigDict = {
428
517
  "file_path": f"{self.metgrid_data_path}/{_file}",
429
- "save_path": WRFRUNConfig.WRF_WORK_PATH,
518
+ "save_path": get_wrf_workspace_path('wrf'),
430
519
  "save_name": _file,
431
520
  "is_data": True,
432
521
  "is_output": True
@@ -435,7 +524,11 @@ class Real(ExecutableBase):
435
524
 
436
525
  super().before_exec()
437
526
 
438
- WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "wrf")
527
+ WRFRUNConfig.write_namelist(f"{get_wrf_workspace_path('wrf')}/{NamelistName.WRF}", "wrf")
528
+
529
+ # print debug logs
530
+ logger.debug("Namelist settings of 'real':")
531
+ logger.debug(WRFRUNConfig.get_namelist("wrf"))
439
532
 
440
533
  def after_exec(self):
441
534
  if not WRFRUNConfig.IS_IN_REPLAY:
@@ -449,20 +542,20 @@ class Real(ExecutableBase):
449
542
 
450
543
  class WRF(ExecutableBase):
451
544
  """
452
- Execute "wrf.exe".
545
+ ``Executable`` of "wrf.exe".
453
546
  """
454
547
 
455
548
  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
549
  """
457
- Execute "wrf.exe"
550
+ ``Executable`` of "wrf.exe"
458
551
 
459
- :param input_file_dir_path: Path of the directory that stores input data for "wrf.exe".
552
+ :param input_file_dir_path: Directory path of input data.
460
553
  :type input_file_dir_path: str
461
- :param restart_file_dir_path: Path of the directory that stores restart files for "wrf.exe".
554
+ :param restart_file_dir_path: Directory path of restart files.
462
555
  :type restart_file_dir_path: str
463
- :param save_restarts: If saving restart files from "wrf.exe". Defaults to False.
556
+ :param save_restarts: If saving restart files. Defaults to False.
464
557
  :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``.
558
+ :param core_num: An positive integer number. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
466
559
  :type core_num: int
467
560
  """
468
561
  if isinstance(core_num, int) and core_num <= 0:
@@ -479,15 +572,22 @@ class WRF(ExecutableBase):
479
572
  mpi_cmd = "mpirun"
480
573
  mpi_core_num = core_num
481
574
 
482
- _check_namelist_preparation()
575
+ _check_and_prepare_namelist()
483
576
 
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)
577
+ super().__init__(name="wrf", cmd="./wrf.exe", work_path=get_wrf_workspace_path('wrf'), mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
485
578
 
486
579
  self.input_file_dir_path = input_file_dir_path
487
580
  self.restart_file_dir_path = restart_file_dir_path
488
581
  self.save_restarts = save_restarts
489
582
 
490
583
  def generate_custom_config(self):
584
+ """
585
+ Store custom configs, including:
586
+
587
+ 1. Directory path of input datas.
588
+ 2. Directory path of restart files.
589
+ 3. Namelist settings.
590
+ """
491
591
  self.custom_config.update(
492
592
  {
493
593
  "input_file_dir_path": self.input_file_dir_path,
@@ -497,6 +597,9 @@ class WRF(ExecutableBase):
497
597
  )
498
598
 
499
599
  def load_custom_config(self):
600
+ """
601
+ Load custom configs.
602
+ """
500
603
  self.input_file_dir_path = self.custom_config["input_file_dir_path"]
501
604
  self.restart_file_dir_path = self.custom_config["restart_file_dir_path"]
502
605
  WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wrf")
@@ -530,7 +633,7 @@ class WRF(ExecutableBase):
530
633
  for _file in file_list:
531
634
  _file_config: FileConfigDict = {
532
635
  "file_path": f"{self.input_file_dir_path}/{_file}",
533
- "save_path": WRFRUNConfig.WRF_WORK_PATH,
636
+ "save_path": get_wrf_workspace_path('wrf'),
534
637
  "save_name": _file,
535
638
  "is_data": True,
536
639
  "is_output": is_output
@@ -552,7 +655,7 @@ class WRF(ExecutableBase):
552
655
  for _file in file_list:
553
656
  _file_config: FileConfigDict = {
554
657
  "file_path": f"{self.restart_file_dir_path}/{_file}",
555
- "save_path": WRFRUNConfig.WRF_WORK_PATH,
658
+ "save_path": get_wrf_workspace_path('wrf'),
556
659
  "save_name": _file,
557
660
  "is_data": True,
558
661
  "is_output": False
@@ -561,7 +664,11 @@ class WRF(ExecutableBase):
561
664
 
562
665
  super().before_exec()
563
666
 
564
- WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "wrf")
667
+ WRFRUNConfig.write_namelist(f"{get_wrf_workspace_path('wrf')}/{NamelistName.WRF}", "wrf")
668
+
669
+ # print debug logs
670
+ logger.debug("Namelist settings of 'wrf':")
671
+ logger.debug(WRFRUNConfig.get_namelist("wrf"))
565
672
 
566
673
  def after_exec(self):
567
674
  if not WRFRUNConfig.IS_IN_REPLAY:
@@ -578,18 +685,18 @@ class WRF(ExecutableBase):
578
685
 
579
686
  class DFI(ExecutableBase):
580
687
  """
581
- Execute "wrf.exe" to run DFI.
688
+ ``Executable`` to run DFI.
582
689
  """
583
690
 
584
691
  def __init__(self, input_file_dir_path: Optional[str] = None, update_real_output=True, core_num: Optional[int] = None):
585
692
  """
586
- Execute "wrf.exe" to run DFI.
693
+ ``Executable`` to run DFI.
587
694
 
588
- :param input_file_dir_path: Path of the directory that stores input data for "wrf.exe".
695
+ :param input_file_dir_path: Directory path of input data.
589
696
  :type input_file_dir_path: str
590
- :param update_real_output: If update the corresponding file in real.exe output directory.
697
+ :param update_real_output: If update corresponding files in :class:`Real` outputs.
591
698
  :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``.
699
+ :param core_num: An positive integer number. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
593
700
  :type core_num: int
594
701
  """
595
702
  if isinstance(core_num, int) and core_num <= 0:
@@ -606,12 +713,19 @@ class DFI(ExecutableBase):
606
713
  mpi_cmd = "mpirun"
607
714
  mpi_core_num = core_num
608
715
 
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)
716
+ super().__init__(name="dfi", cmd="./wrf.exe", work_path=get_wrf_workspace_path('wrf'), mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
610
717
 
611
718
  self.input_file_dir_path = input_file_dir_path
612
719
  self.update_real_output = update_real_output
613
720
 
614
721
  def generate_custom_config(self):
722
+ """
723
+ Store custom configs, including:
724
+
725
+ 1. Directory path of input datas.
726
+ 2. If update corresponding files in :class:`Real` outputs.
727
+ 3. Namelist settings.
728
+ """
615
729
  self.custom_config.update(
616
730
  {
617
731
  "input_file_dir_path": self.input_file_dir_path,
@@ -621,6 +735,9 @@ class DFI(ExecutableBase):
621
735
  )
622
736
 
623
737
  def load_custom_config(self):
738
+ """
739
+ Load custom configs.
740
+ """
624
741
  self.input_file_dir_path = self.custom_config["input_file_dir_path"]
625
742
  self.update_real_output = self.custom_config["update_real_output"]
626
743
 
@@ -650,7 +767,7 @@ class DFI(ExecutableBase):
650
767
  for _file in file_list:
651
768
  _file_config: FileConfigDict = {
652
769
  "file_path": f"{self.input_file_dir_path}/{_file}",
653
- "save_path": WRFRUNConfig.WRF_WORK_PATH,
770
+ "save_path": get_wrf_workspace_path('wrf'),
654
771
  "save_name": _file,
655
772
  "is_data": True,
656
773
  "is_output": is_output
@@ -664,7 +781,7 @@ class DFI(ExecutableBase):
664
781
  prepare_dfi_namelist()
665
782
 
666
783
  super().before_exec()
667
- WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "dfi")
784
+ WRFRUNConfig.write_namelist(f"{get_wrf_workspace_path('wrf')}/{NamelistName.WRF}", "dfi")
668
785
 
669
786
  def after_exec(self):
670
787
  if not WRFRUNConfig.IS_IN_REPLAY:
@@ -686,21 +803,21 @@ class DFI(ExecutableBase):
686
803
 
687
804
  class NDown(ExecutableBase):
688
805
  """
689
- Execute "ndown.exe".
806
+ ``Executable`` of "ndown.exe".
690
807
  """
691
808
 
692
809
  def __init__(self, wrfout_file_path: str, real_output_dir_path: Optional[str] = None, update_namelist=True, core_num: Optional[int] = None):
693
810
  """
694
- Execute "ndown.exe".
811
+ ``Executable`` of "ndown.exe".
695
812
 
696
813
  :param wrfout_file_path: wrfout file path.
697
814
  :type wrfout_file_path: str
698
- :param real_output_dir_path: Path of the directory that contains output of "real.exe".
815
+ :param real_output_dir_path: Directory path of :class:`Real` outputs.
699
816
  :type real_output_dir_path: str
700
- :param update_namelist: If update wrf's namelist for the final integral.
817
+ :param update_namelist: If update namelist settings for the final integral.
701
818
  :type update_namelist: bool
702
- :param core_num:
703
- :type core_num:
819
+ :param core_num: An positive integer number. ``mpirun`` will be used to execute geogrid.exe if ``core_num != None``.
820
+ :type core_num: int
704
821
  """
705
822
  if isinstance(core_num, int) and core_num <= 0:
706
823
  logger.warning(f"`core_num` should be greater than 0")
@@ -716,15 +833,23 @@ class NDown(ExecutableBase):
716
833
  mpi_cmd = "mpirun"
717
834
  mpi_core_num = core_num
718
835
 
719
- _check_namelist_preparation()
836
+ _check_and_prepare_namelist()
720
837
 
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)
838
+ super().__init__(name="ndown", cmd="./ndown.exe", work_path=get_wrf_workspace_path('wrf'), mpi_use=mpi_use, mpi_cmd=mpi_cmd, mpi_core_num=mpi_core_num)
722
839
 
723
840
  self.wrfout_file_path = wrfout_file_path
724
841
  self.real_output_dir_path = real_output_dir_path
725
842
  self.update_namelist = update_namelist
726
843
 
727
844
  def generate_custom_config(self):
845
+ """
846
+ Store custom configs, including:
847
+
848
+ 1. Positional arguments of this ``Executable``.
849
+ 2. Directory path of :class:`Real` outputs.
850
+ 3. If update namelist settings.
851
+ 4. Namelist settings.
852
+ """
728
853
  self.class_config["class_args"] = (self.wrfout_file_path,)
729
854
  self.custom_config.update(
730
855
  {
@@ -735,9 +860,12 @@ class NDown(ExecutableBase):
735
860
  )
736
861
 
737
862
  def load_custom_config(self):
863
+ """
864
+ Load custom configs.
865
+ """
738
866
  self.real_output_dir_path = self.custom_config["real_output_dir_path"]
739
867
  self.update_namelist = self.custom_config["update_namelist"]
740
- WRFRUNConfig.update_namelist(self.custom_config["namelist"])
868
+ WRFRUNConfig.update_namelist(self.custom_config["namelist"], "wrf")
741
869
 
742
870
  def before_exec(self):
743
871
  WRFRUNConfig.check_wrfrun_context(True)
@@ -756,14 +884,14 @@ class NDown(ExecutableBase):
756
884
 
757
885
  wrfndi_file_config: FileConfigDict = {
758
886
  "file_path": f"{self.real_output_dir_path}/wrfinput_d02",
759
- "save_path": WRFRUNConfig.WRF_WORK_PATH,
887
+ "save_path": get_wrf_workspace_path('wrf'),
760
888
  "save_name": "wrfndi_d02",
761
889
  "is_data": True,
762
890
  "is_output": is_output
763
891
  }
764
892
  wrfout_file_config: FileConfigDict = {
765
893
  "file_path": self.wrfout_file_path,
766
- "save_path": WRFRUNConfig.WRF_WORK_PATH,
894
+ "save_path": get_wrf_workspace_path('wrf'),
767
895
  "save_name": "wrfout_d01",
768
896
  "is_data": True,
769
897
  "is_output": False
@@ -773,7 +901,7 @@ class NDown(ExecutableBase):
773
901
 
774
902
  super().before_exec()
775
903
 
776
- WRFRUNConfig.write_namelist(f"{WRFRUNConfig.WRF_WORK_PATH}/{NamelistName.WRF}", "wrf")
904
+ WRFRUNConfig.write_namelist(f"{get_wrf_workspace_path('wrf')}/{NamelistName.WRF}", "wrf")
777
905
 
778
906
  def after_exec(self):
779
907
  self.add_output_files(save_path=self._log_save_path, startswith="rsl.", outputs="namelist.input")