wrfrun 0.1.8__py3-none-any.whl → 0.1.9__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/cli.py +128 -0
- wrfrun/core/base.py +8 -5
- wrfrun/core/config.py +81 -150
- wrfrun/core/replay.py +1 -1
- wrfrun/core/server.py +81 -78
- wrfrun/extension/goos_sst/__init__.py +5 -5
- wrfrun/extension/goos_sst/core.py +4 -1
- wrfrun/extension/goos_sst/res/Vtable.ERA_GOOS_SST +1 -1
- wrfrun/extension/goos_sst/res/__init__.py +17 -0
- wrfrun/extension/goos_sst/utils.py +21 -5
- wrfrun/extension/littler/__init__.py +57 -1
- wrfrun/extension/littler/{utils.py → core.py} +326 -40
- wrfrun/extension/utils.py +22 -21
- wrfrun/model/__init__.py +24 -1
- wrfrun/model/plot.py +253 -35
- wrfrun/model/utils.py +17 -8
- wrfrun/model/wrf/__init__.py +41 -0
- wrfrun/model/wrf/core.py +215 -99
- wrfrun/model/wrf/exec_wrap.py +49 -35
- wrfrun/model/wrf/namelist.py +79 -4
- wrfrun/model/wrf/{_metgrid.py → utils.py} +36 -2
- wrfrun/model/wrf/vtable.py +2 -1
- wrfrun/res/__init__.py +8 -5
- wrfrun/res/config/config.template.toml +50 -0
- wrfrun/res/{config.toml.template → config/wrf.template.toml} +7 -46
- wrfrun/res/run.template.sh +10 -0
- wrfrun/res/scheduler/lsf.template +5 -0
- wrfrun/res/{job_scheduler → scheduler}/pbs.template +1 -1
- wrfrun/res/{job_scheduler → scheduler}/slurm.template +2 -1
- wrfrun/run.py +19 -23
- wrfrun/scheduler/__init__.py +35 -0
- wrfrun/scheduler/env.py +44 -0
- wrfrun/scheduler/lsf.py +47 -0
- wrfrun/scheduler/pbs.py +48 -0
- wrfrun/scheduler/script.py +70 -0
- wrfrun/scheduler/slurm.py +48 -0
- wrfrun/scheduler/utils.py +14 -0
- wrfrun/utils.py +8 -3
- wrfrun/workspace/__init__.py +38 -0
- wrfrun/workspace/core.py +92 -0
- wrfrun/workspace/wrf.py +121 -0
- {wrfrun-0.1.8.dist-info → wrfrun-0.1.9.dist-info}/METADATA +3 -2
- wrfrun-0.1.9.dist-info/RECORD +62 -0
- wrfrun-0.1.9.dist-info/entry_points.txt +3 -0
- wrfrun/model/wrf/_ndown.py +0 -39
- wrfrun/pbs.py +0 -86
- wrfrun/res/run.sh.template +0 -16
- wrfrun/workspace.py +0 -88
- wrfrun-0.1.8.dist-info/RECORD +0 -51
- {wrfrun-0.1.8.dist-info → wrfrun-0.1.9.dist-info}/WHEEL +0 -0
wrfrun/cli.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
from os import makedirs
|
|
4
|
+
from os.path import abspath, dirname, exists
|
|
5
|
+
from shutil import copyfile
|
|
6
|
+
|
|
7
|
+
import tomli
|
|
8
|
+
import tomli_w
|
|
9
|
+
|
|
10
|
+
from .core import WRFRUNConfig
|
|
11
|
+
from .res import CONFIG_MAIN_TOML_TEMPLATE, CONFIG_WRF_TOML_TEMPLATE
|
|
12
|
+
from .utils import logger
|
|
13
|
+
|
|
14
|
+
MODEL_MAP = {
|
|
15
|
+
"wrf": CONFIG_WRF_TOML_TEMPLATE
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _entry_init(args: argparse.Namespace):
|
|
20
|
+
"""
|
|
21
|
+
Initialize a wrfrun project.
|
|
22
|
+
|
|
23
|
+
:param args: Arguments namespace.
|
|
24
|
+
:type args: argparse.Namespace
|
|
25
|
+
"""
|
|
26
|
+
args = vars(args)
|
|
27
|
+
|
|
28
|
+
project_name = args["name"]
|
|
29
|
+
models = args["models"]
|
|
30
|
+
|
|
31
|
+
if exists(project_name):
|
|
32
|
+
logger.error(f"{project_name} already exists.")
|
|
33
|
+
exit(1)
|
|
34
|
+
|
|
35
|
+
makedirs(f"{project_name}/configs")
|
|
36
|
+
makedirs(f"{project_name}/data")
|
|
37
|
+
|
|
38
|
+
copyfile(WRFRUNConfig.parse_resource_uri(CONFIG_MAIN_TOML_TEMPLATE), f"{project_name}/config.toml")
|
|
39
|
+
|
|
40
|
+
if models is not None:
|
|
41
|
+
for _model in models:
|
|
42
|
+
src_path = WRFRUNConfig.parse_resource_uri(MODEL_MAP[_model])
|
|
43
|
+
copyfile(src_path, f"{project_name}/configs/{_model}.toml")
|
|
44
|
+
|
|
45
|
+
logger.info(f"Created project {project_name}.")
|
|
46
|
+
logger.info(f"Use command `wrfrun add MODEL_NAME` to add a new model to project.")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _entry_model(args: argparse.Namespace):
|
|
50
|
+
"""
|
|
51
|
+
Manage models used by wrfrun project.
|
|
52
|
+
|
|
53
|
+
:param args: Arguments namespace.
|
|
54
|
+
:type args: argparse.Namespace
|
|
55
|
+
"""
|
|
56
|
+
args = vars(args)
|
|
57
|
+
new_models = args["add"]
|
|
58
|
+
config_path = args["config"]
|
|
59
|
+
|
|
60
|
+
if not exists(config_path):
|
|
61
|
+
logger.error(f"Can't find '{config_path}', initialize this project first.")
|
|
62
|
+
exit(1)
|
|
63
|
+
|
|
64
|
+
model_config_map = {
|
|
65
|
+
"wrf": CONFIG_WRF_TOML_TEMPLATE
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for _new_model in new_models:
|
|
69
|
+
if _new_model not in model_config_map:
|
|
70
|
+
logger.error(f"Unknow model type: '{_new_model}'")
|
|
71
|
+
exit(1)
|
|
72
|
+
|
|
73
|
+
config_dir_path = f"{abspath(dirname(config_path))}/configs"
|
|
74
|
+
|
|
75
|
+
if not exists(config_dir_path):
|
|
76
|
+
makedirs(config_dir_path)
|
|
77
|
+
|
|
78
|
+
with open(config_path, "rb") as f:
|
|
79
|
+
main_config = tomli.load(f)
|
|
80
|
+
|
|
81
|
+
for _new_model in new_models:
|
|
82
|
+
if _new_model not in main_config["model"]:
|
|
83
|
+
main_config["model"][_new_model] = {
|
|
84
|
+
"note": "Config of this model is generated by wrfrun cli command. DO NOT ADD CUSTOM CONFIG IN THIS SECTION because they may be overwrite by wrfrun cli tools.",
|
|
85
|
+
"use": True,
|
|
86
|
+
"include": f"./configs/{_new_model}.toml"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
else:
|
|
90
|
+
if not ("use" in main_config["model"] and main_config["model"]["use"]):
|
|
91
|
+
main_config["model"][_new_model] = {
|
|
92
|
+
"note": "Config of this model is generated by wrfrun cli command. DO NOT ADD CUSTOM CONFIG IN THIS SECTION because they may be overwrite by wrfrun cli tools.",
|
|
93
|
+
"use": True,
|
|
94
|
+
"include": f"./configs/{_new_model}.toml"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for _new_model in new_models:
|
|
98
|
+
copyfile(WRFRUNConfig.parse_resource_uri(model_config_map[_new_model]), f"{config_dir_path}/{_new_model}.toml")
|
|
99
|
+
|
|
100
|
+
with open(config_path, "wb") as f:
|
|
101
|
+
tomli_w.dump(main_config, f)
|
|
102
|
+
|
|
103
|
+
logger.info(f"Added models: {new_models}")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def main_entry():
|
|
107
|
+
"""
|
|
108
|
+
CLI entry point.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
args_parser = argparse.ArgumentParser()
|
|
112
|
+
subparsers = args_parser.add_subparsers(title="Subcommands", description="Valid Subcommands", help="Subcommands")
|
|
113
|
+
|
|
114
|
+
init_parser = subparsers.add_parser("init", help="Initialize a wrfrun project.", add_help=True)
|
|
115
|
+
init_parser.add_argument("-n", "--name", type=str, required=True, help="Name of the wrfrun project.")
|
|
116
|
+
init_parser.add_argument("--models", nargs="*", type=str, help="List of models to use.", choices=["wrf"])
|
|
117
|
+
init_parser.set_defaults(func=_entry_init)
|
|
118
|
+
|
|
119
|
+
model_parser = subparsers.add_parser("model", help="Manage models used by wrfrun project.", add_help=True)
|
|
120
|
+
model_parser.add_argument("-c", "--config", type=str, default="config.toml", help="Path of the main config file.")
|
|
121
|
+
model_parser.add_argument("-a", "--add", nargs="+", required=True, type=str, help="Add models to the project.")
|
|
122
|
+
model_parser.set_defaults(func=_entry_model)
|
|
123
|
+
|
|
124
|
+
args = args_parser.parse_args(args=None if sys.argv[1:] else ["--help"])
|
|
125
|
+
args.func(args)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
__all__ = ["main_entry"]
|
wrfrun/core/base.py
CHANGED
|
@@ -20,7 +20,7 @@ Executable
|
|
|
20
20
|
**********
|
|
21
21
|
|
|
22
22
|
While ``wrfrun`` aims to provide Python interfaces to various Numerical Weather Prediction model,
|
|
23
|
-
it is important to provide a clear standard about how should
|
|
23
|
+
it is important to provide a clear standard about how should an external executable file be implemented in ``wrfrun``.
|
|
24
24
|
``wrfrun`` provides a class called :class:`ExecutableBase`, which is the parent class for all ``Executable`` classes.
|
|
25
25
|
It not only provide the method to execute external programs,
|
|
26
26
|
but also:
|
|
@@ -154,7 +154,9 @@ class InputFileType(Enum):
|
|
|
154
154
|
|
|
155
155
|
class FileConfigDict(TypedDict):
|
|
156
156
|
"""
|
|
157
|
-
This dict is used to store information about the file, including its path,
|
|
157
|
+
This dict is used to store information about the file, including its path,
|
|
158
|
+
the path it will be copied or moved to, its new name, etc.
|
|
159
|
+
This dict contains following keys:
|
|
158
160
|
|
|
159
161
|
.. py:attribute:: file_path
|
|
160
162
|
:type: str
|
|
@@ -174,7 +176,8 @@ class FileConfigDict(TypedDict):
|
|
|
174
176
|
.. py:attribute:: is_data
|
|
175
177
|
:type: bool
|
|
176
178
|
|
|
177
|
-
If the file is data. If not, ``wrfrun`` will treat it as a config file,
|
|
179
|
+
If the file is data. If not, ``wrfrun`` will treat it as a config file,
|
|
180
|
+
and always save it to ``.replay`` file when recording the simulation.
|
|
178
181
|
|
|
179
182
|
.. py:attribute:: is_output
|
|
180
183
|
:type: bool
|
|
@@ -300,7 +303,7 @@ class _ExecutableConfigRecord:
|
|
|
300
303
|
self.save_path = save_path
|
|
301
304
|
self.include_data = include_data
|
|
302
305
|
|
|
303
|
-
self.work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.
|
|
306
|
+
self.work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_REPLAY)
|
|
304
307
|
self.content_path = f"{self.work_path}/config_and_data"
|
|
305
308
|
check_path(self.content_path)
|
|
306
309
|
|
|
@@ -348,7 +351,7 @@ class _ExecutableConfigRecord:
|
|
|
348
351
|
self._name_count[name] = 1
|
|
349
352
|
index = 1
|
|
350
353
|
|
|
351
|
-
data_save_uri = f"{WRFRUNConfig.
|
|
354
|
+
data_save_uri = f"{WRFRUNConfig.WRFRUN_WORKSPACE_REPLAY}/{name}/{index}"
|
|
352
355
|
data_save_path = f"{self.content_path}/{name}/{index}"
|
|
353
356
|
makedirs(data_save_path)
|
|
354
357
|
|
wrfrun/core/config.py
CHANGED
|
@@ -22,15 +22,16 @@ Users can use the global variable ``WRFRUNConfig``, which is the instance of thi
|
|
|
22
22
|
|
|
23
23
|
from copy import deepcopy
|
|
24
24
|
from os import environ, makedirs
|
|
25
|
-
from os.path import abspath,
|
|
25
|
+
from os.path import abspath, dirname, exists
|
|
26
26
|
from shutil import copyfile
|
|
27
|
+
from sys import platform
|
|
27
28
|
from typing import Optional, Tuple, Union
|
|
28
29
|
|
|
29
30
|
import f90nml
|
|
30
31
|
import tomli
|
|
31
32
|
import tomli_w
|
|
32
33
|
|
|
33
|
-
from .error import
|
|
34
|
+
from .error import ModelNameError, NamelistError, NamelistIDError, ResourceURIError, WRFRunContextError
|
|
34
35
|
from ..utils import logger
|
|
35
36
|
|
|
36
37
|
|
|
@@ -110,7 +111,7 @@ class _WRFRunResources:
|
|
|
110
111
|
|
|
111
112
|
For example, you can get the real path of ``wrfrun`` workspace with this method:
|
|
112
113
|
|
|
113
|
-
>>> workspace_path = f"{WRFRUNConfig.
|
|
114
|
+
>>> workspace_path = f"{WRFRUNConfig.WRFRUN_WORKSPACE_ROOT}/WPS" # ":WRFRUN_WORKSPACE_PATH:/WPS"
|
|
114
115
|
>>> real_path = WRFRUNConfig.parse_resource_uri(workspace_path) # should be a valid path like: "/home/syize/.config/wrfrun/workspace/WPS"
|
|
115
116
|
|
|
116
117
|
"""
|
|
@@ -146,41 +147,42 @@ class _WRFRunConstants:
|
|
|
146
147
|
These variables are related to ``wrfrun`` installation environments, configuration files and more.
|
|
147
148
|
They are defined either directly or mapped using URIs to ensure consistent access across all components.
|
|
148
149
|
"""
|
|
149
|
-
#
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
# check system
|
|
151
|
+
if platform != "linux":
|
|
152
|
+
logger.debug(f"Not Linux system!")
|
|
153
|
+
|
|
154
|
+
# set temporary dir path
|
|
155
|
+
self._WRFRUN_TEMP_PATH = "./tmp/wrfrun"
|
|
156
|
+
user_home_path = "./tmp/wrfrun"
|
|
157
|
+
|
|
158
|
+
else:
|
|
159
|
+
|
|
160
|
+
# the path we may need to store temp files,
|
|
161
|
+
# don't worry, it will be deleted once the system reboots
|
|
162
|
+
self._WRFRUN_TEMP_PATH = "/tmp/wrfrun"
|
|
163
|
+
user_home_path = f"{environ['HOME']}"
|
|
152
164
|
|
|
153
165
|
# WRF may need a large disk space to store output, we can't run wrf in /tmp,
|
|
154
166
|
# so we will create a folder in $HOME/.config to run wrf.
|
|
155
167
|
# we need to check if we're running as a root user
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
logger.warning(f"User's home path is '{USER_HOME_PATH}', which means you are running this program as a root user")
|
|
168
|
+
if user_home_path in ["/", "/root", ""]:
|
|
169
|
+
logger.warning(f"User's home path is '{user_home_path}', which means you are running this program as a root user")
|
|
159
170
|
logger.warning("It's not recommended to use wrfrun as a root user")
|
|
160
|
-
logger.warning("Set
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
self._WRFRUN_HOME_PATH = f"{USER_HOME_PATH}/.config/wrfrun"
|
|
164
|
-
self._WRFRUN_REPLAY_WORK_PATH = f"{self._WRFRUN_HOME_PATH}/replay"
|
|
171
|
+
logger.warning("Set user_home_path as /root")
|
|
172
|
+
user_home_path = "/root"
|
|
165
173
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
self.
|
|
169
|
-
self.
|
|
170
|
-
self.
|
|
174
|
+
self._WRFRUN_HOME_PATH = f"{user_home_path}/.config/wrfrun"
|
|
175
|
+
# workspace root path
|
|
176
|
+
self._WRFRUN_WORKSPACE_ROOT = f"{self._WRFRUN_HOME_PATH}/workspace"
|
|
177
|
+
self._WRFRUN_WORKSPACE_MODEL = f"{self._WRFRUN_WORKSPACE_ROOT}/model"
|
|
178
|
+
self._WRFRUN_WORKSPACE_REPLAY = f"{self._WRFRUN_WORKSPACE_ROOT}/replay"
|
|
171
179
|
|
|
172
180
|
# record WRF progress status
|
|
173
|
-
self.
|
|
181
|
+
self._WRFRUN_WORK_STATUS = ""
|
|
174
182
|
|
|
175
183
|
# record context status
|
|
176
184
|
self._WRFRUN_CONTEXT_STATUS = False
|
|
177
185
|
|
|
178
|
-
# WRFDA is not necessary
|
|
179
|
-
self.USE_WRFDA: bool = False
|
|
180
|
-
|
|
181
|
-
# output directory of ungrib
|
|
182
|
-
self._UNGRIB_OUT_DIR = "./outputs"
|
|
183
|
-
|
|
184
186
|
self._WRFRUN_OUTPUT_PATH = ":WRFRUN_OUTPUT_PATH:"
|
|
185
187
|
self._WRFRUN_RESOURCE_PATH = ":WRFRUN_RESOURCE_PATH:"
|
|
186
188
|
|
|
@@ -203,22 +205,20 @@ class _WRFRunConstants:
|
|
|
203
205
|
return {
|
|
204
206
|
self.WRFRUN_TEMP_PATH: self._WRFRUN_TEMP_PATH,
|
|
205
207
|
self.WRFRUN_HOME_PATH: self._WRFRUN_HOME_PATH,
|
|
206
|
-
self.
|
|
207
|
-
self.
|
|
208
|
-
self.
|
|
209
|
-
self.WRFDA_WORK_PATH: self._WRFDA_WORK_PATH,
|
|
210
|
-
self.WRFRUN_REPLAY_WORK_PATH: self._WRFRUN_REPLAY_WORK_PATH,
|
|
208
|
+
self.WRFRUN_WORKSPACE_ROOT: self._WRFRUN_WORKSPACE_ROOT,
|
|
209
|
+
self.WRFRUN_WORKSPACE_MODEL: self._WRFRUN_WORKSPACE_MODEL,
|
|
210
|
+
self.WRFRUN_WORKSPACE_REPLAY: self._WRFRUN_WORKSPACE_REPLAY,
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
@property
|
|
214
|
-
def
|
|
214
|
+
def WRFRUN_WORKSPACE_REPLAY(self) -> str:
|
|
215
215
|
"""
|
|
216
|
-
Path (URI) to store related files of ``wrfrun``
|
|
216
|
+
Path (URI) to store related files of ``wrfrun`` replay functionality.
|
|
217
217
|
|
|
218
218
|
:return: URI.
|
|
219
219
|
:rtype: str
|
|
220
220
|
"""
|
|
221
|
-
return ":
|
|
221
|
+
return ":WRFRUN_WORKSPACE_REPLAY:"
|
|
222
222
|
|
|
223
223
|
@property
|
|
224
224
|
def WRFRUN_TEMP_PATH(self) -> str:
|
|
@@ -241,44 +241,24 @@ class _WRFRunConstants:
|
|
|
241
241
|
return ":WRFRUN_HOME_PATH:"
|
|
242
242
|
|
|
243
243
|
@property
|
|
244
|
-
def
|
|
245
|
-
"""
|
|
246
|
-
Path of the workspace, in which ``wrfrun`` runs NWP models.
|
|
247
|
-
|
|
248
|
-
:return: URI
|
|
249
|
-
:rtype: str
|
|
250
|
-
"""
|
|
251
|
-
return ":WRFRUN_WORKSPACE_PATH:"
|
|
252
|
-
|
|
253
|
-
@property
|
|
254
|
-
def WPS_WORK_PATH(self) -> str:
|
|
244
|
+
def WRFRUN_WORKSPACE_ROOT(self) -> str:
|
|
255
245
|
"""
|
|
256
|
-
|
|
246
|
+
Path of the root workspace.
|
|
257
247
|
|
|
258
248
|
:return: URI
|
|
259
249
|
:rtype: str
|
|
260
250
|
"""
|
|
261
|
-
return ":
|
|
251
|
+
return ":WRFRUN_WORKSPACE_ROOT:"
|
|
262
252
|
|
|
263
253
|
@property
|
|
264
|
-
def
|
|
254
|
+
def WRFRUN_WORKSPACE_MODEL(self) -> str:
|
|
265
255
|
"""
|
|
266
|
-
|
|
256
|
+
Path of the model workspace, in which ``wrfrun`` runs numerical models.
|
|
267
257
|
|
|
268
258
|
:return: URI
|
|
269
259
|
:rtype: str
|
|
270
260
|
"""
|
|
271
|
-
return ":
|
|
272
|
-
|
|
273
|
-
@property
|
|
274
|
-
def WRFDA_WORK_PATH(self) -> str:
|
|
275
|
-
"""
|
|
276
|
-
Workspace in which ``wrfrun`` runs WRFDA.
|
|
277
|
-
|
|
278
|
-
:return: URI
|
|
279
|
-
:rtype: str
|
|
280
|
-
"""
|
|
281
|
-
return ":WRFRUN_WRFDA_WORK_PATH:"
|
|
261
|
+
return ":WRFRUN_WORKSPACE_MODEL:"
|
|
282
262
|
|
|
283
263
|
@property
|
|
284
264
|
def WRFRUN_WORK_STATUS(self) -> str:
|
|
@@ -291,7 +271,7 @@ class _WRFRunConstants:
|
|
|
291
271
|
:return: A string reflect the current work progress.
|
|
292
272
|
:rtype: str
|
|
293
273
|
"""
|
|
294
|
-
return self.
|
|
274
|
+
return self._WRFRUN_WORK_STATUS
|
|
295
275
|
|
|
296
276
|
@WRFRUN_WORK_STATUS.setter
|
|
297
277
|
def WRFRUN_WORK_STATUS(self, value: str):
|
|
@@ -306,29 +286,7 @@ class _WRFRunConstants:
|
|
|
306
286
|
"""
|
|
307
287
|
if not isinstance(value, str):
|
|
308
288
|
value = str(value)
|
|
309
|
-
self.
|
|
310
|
-
|
|
311
|
-
@property
|
|
312
|
-
def UNGRIB_OUT_DIR(self) -> str:
|
|
313
|
-
"""
|
|
314
|
-
Output directory path of ``ungrib.exe``.
|
|
315
|
-
|
|
316
|
-
:return: URI
|
|
317
|
-
:rtype: str
|
|
318
|
-
"""
|
|
319
|
-
return self._UNGRIB_OUT_DIR
|
|
320
|
-
|
|
321
|
-
@UNGRIB_OUT_DIR.setter
|
|
322
|
-
def UNGRIB_OUT_DIR(self, value: str):
|
|
323
|
-
"""
|
|
324
|
-
Set the output directory path of ``ungrib.exe``.
|
|
325
|
-
|
|
326
|
-
:param value: A real path or a URI represents the directory path of ``ungrib.exe``'s output.
|
|
327
|
-
:type value: str
|
|
328
|
-
"""
|
|
329
|
-
if not isinstance(value, str):
|
|
330
|
-
value = str(value)
|
|
331
|
-
self._UNGRIB_OUT_DIR = value
|
|
289
|
+
self._WRFRUN_WORK_STATUS = value
|
|
332
290
|
|
|
333
291
|
@property
|
|
334
292
|
def WRFRUN_OUTPUT_PATH(self) -> str:
|
|
@@ -394,9 +352,6 @@ class _WRFRunNamelist:
|
|
|
394
352
|
If you want to use a new ``namelist_id`` other than the defaults to store namelist,
|
|
395
353
|
you can register a new ``namelist_id`` with :meth:`_WRFRunNamelist.register_custom_namelist_id`.
|
|
396
354
|
"""
|
|
397
|
-
self._wps_namelist = {}
|
|
398
|
-
self._wrf_namelist = {}
|
|
399
|
-
self._wrfda_namelist = {}
|
|
400
355
|
self._namelist_dict = {}
|
|
401
356
|
self._namelist_id_list = ("param", "geog_static_data", "wps", "wrf", "wrfda")
|
|
402
357
|
|
|
@@ -570,6 +525,21 @@ class _WRFRunNamelist:
|
|
|
570
525
|
|
|
571
526
|
self._namelist_dict.pop(namelist_id)
|
|
572
527
|
|
|
528
|
+
def check_namelist(self, namelist_id: str) -> bool:
|
|
529
|
+
"""
|
|
530
|
+
Check if a namelist has been registered and loaded.
|
|
531
|
+
|
|
532
|
+
:param namelist_id: Registered ``namelist_id``.
|
|
533
|
+
:type namelist_id: str
|
|
534
|
+
:return: ``True`` if it is registered and loaded, else ``False``.
|
|
535
|
+
:rtype: bool
|
|
536
|
+
"""
|
|
537
|
+
if namelist_id in self._namelist_id_list and self._namelist_dict:
|
|
538
|
+
return True
|
|
539
|
+
|
|
540
|
+
else:
|
|
541
|
+
return False
|
|
542
|
+
|
|
573
543
|
|
|
574
544
|
class WRFRunConfig(_WRFRunConstants, _WRFRunNamelist, _WRFRunResources):
|
|
575
545
|
"""
|
|
@@ -654,6 +624,30 @@ class WRFRunConfig(_WRFRunConstants, _WRFRunNamelist, _WRFRunResources):
|
|
|
654
624
|
with open(config_path, "rb") as f:
|
|
655
625
|
self._config = tomli.load(f)
|
|
656
626
|
|
|
627
|
+
config_dir_path = abspath(dirname(config_path))
|
|
628
|
+
|
|
629
|
+
# merge model config.
|
|
630
|
+
keys_list = list(self._config["model"].keys())
|
|
631
|
+
for model_key in keys_list:
|
|
632
|
+
|
|
633
|
+
# skip the key that isn't model.
|
|
634
|
+
if model_key == "debug_level":
|
|
635
|
+
continue
|
|
636
|
+
|
|
637
|
+
if "use" not in self._config["model"][model_key]:
|
|
638
|
+
continue
|
|
639
|
+
|
|
640
|
+
if self._config["model"][model_key]["use"]:
|
|
641
|
+
include_file = self._config["model"][model_key]["include"]
|
|
642
|
+
if include_file[0] != "/":
|
|
643
|
+
include_file = f"{config_dir_path}/{include_file}"
|
|
644
|
+
|
|
645
|
+
with open(include_file, "rb") as f:
|
|
646
|
+
self._config["model"][model_key] = tomli.load(f)
|
|
647
|
+
|
|
648
|
+
else:
|
|
649
|
+
self._config["model"].pop(model_key)
|
|
650
|
+
|
|
657
651
|
# register URI for output directory.
|
|
658
652
|
output_path = abspath(self["output_path"])
|
|
659
653
|
self.register_resource_uri(self.WRFRUN_OUTPUT_PATH, output_path)
|
|
@@ -752,69 +746,6 @@ class WRFRunConfig(_WRFRunConstants, _WRFRunNamelist, _WRFRunResources):
|
|
|
752
746
|
"""
|
|
753
747
|
return self["core_num"]
|
|
754
748
|
|
|
755
|
-
def get_ungrib_out_dir_path(self) -> str:
|
|
756
|
-
"""
|
|
757
|
-
Get the output directory of ungrib output (WRF intermediate file).
|
|
758
|
-
|
|
759
|
-
:return: URI path.
|
|
760
|
-
:rtype: str
|
|
761
|
-
"""
|
|
762
|
-
wif_prefix = self.get_namelist("wps")["ungrib"]["prefix"]
|
|
763
|
-
wif_path = f"{self.WPS_WORK_PATH}/{dirname(wif_prefix)}"
|
|
764
|
-
|
|
765
|
-
return wif_path
|
|
766
|
-
|
|
767
|
-
def get_ungrib_out_prefix(self) -> str:
|
|
768
|
-
"""
|
|
769
|
-
Get the prefix string of ungrib output (WRF intermediate file).
|
|
770
|
-
|
|
771
|
-
:return: Prefix string of ungrib output (WRF intermediate file).
|
|
772
|
-
:rtype: str
|
|
773
|
-
"""
|
|
774
|
-
wif_prefix = self.get_namelist("wps")["ungrib"]["prefix"]
|
|
775
|
-
wif_prefix = basename(wif_prefix)
|
|
776
|
-
return wif_prefix
|
|
777
|
-
|
|
778
|
-
def set_ungrib_out_prefix(self, prefix: str):
|
|
779
|
-
"""
|
|
780
|
-
Set the prefix string of ungrib output (WRF intermediate file).
|
|
781
|
-
|
|
782
|
-
:param prefix: Prefix string of ungrib output (WRF intermediate file).
|
|
783
|
-
:type prefix: str
|
|
784
|
-
"""
|
|
785
|
-
self.update_namelist(
|
|
786
|
-
{
|
|
787
|
-
"ungrib": {"prefix": f"{self.UNGRIB_OUT_DIR}/{prefix}"}
|
|
788
|
-
}, "wps"
|
|
789
|
-
)
|
|
790
|
-
|
|
791
|
-
def get_metgrid_fg_names(self) -> list[str]:
|
|
792
|
-
"""
|
|
793
|
-
Get prefix strings from "fg_name" in namelist "metgrid" section.
|
|
794
|
-
|
|
795
|
-
:return: Prefix strings list.
|
|
796
|
-
:rtype: list
|
|
797
|
-
"""
|
|
798
|
-
fg_names = self.get_namelist("wps")["metgrid"]["fg_name"]
|
|
799
|
-
fg_names = [basename(x) for x in fg_names]
|
|
800
|
-
return fg_names
|
|
801
|
-
|
|
802
|
-
def set_metgrid_fg_names(self, prefix: Union[str, list[str]]):
|
|
803
|
-
"""
|
|
804
|
-
Set prefix strings of "fg_name" in namelist "metgrid" section.
|
|
805
|
-
|
|
806
|
-
:param prefix: Prefix strings list.
|
|
807
|
-
:type prefix: str | list
|
|
808
|
-
"""
|
|
809
|
-
if isinstance(prefix, str):
|
|
810
|
-
prefix = [prefix, ]
|
|
811
|
-
fg_names = [f"{self.UNGRIB_OUT_DIR}/{x}" for x in prefix]
|
|
812
|
-
self.update_namelist(
|
|
813
|
-
{
|
|
814
|
-
"metgrid": {"fg_name": fg_names}
|
|
815
|
-
}, "wps"
|
|
816
|
-
)
|
|
817
|
-
|
|
818
749
|
def write_namelist(self, save_path: str, namelist_id: str, overwrite=True):
|
|
819
750
|
"""
|
|
820
751
|
Write namelist values of a ``namelist_id`` to a file.
|
wrfrun/core/replay.py
CHANGED
|
@@ -124,7 +124,7 @@ def replay_config_generator(replay_config_file: str) -> Generator[tuple[str, Exe
|
|
|
124
124
|
:rtype: Generator
|
|
125
125
|
"""
|
|
126
126
|
logger.info(f"Loading replay resources from: {replay_config_file}")
|
|
127
|
-
work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.
|
|
127
|
+
work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_REPLAY)
|
|
128
128
|
|
|
129
129
|
unpack_archive(replay_config_file, work_path, "zip")
|
|
130
130
|
|