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/utils.py
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import subprocess
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from os import chdir, getcwd, makedirs
|
|
5
|
+
from os.path import exists
|
|
6
|
+
from shutil import rmtree
|
|
7
|
+
from time import time
|
|
8
|
+
from typing import Optional, List, Dict
|
|
9
|
+
|
|
10
|
+
from rich.logging import RichHandler
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def set_logger(logger_list: List[str], logger_level: Optional[Dict] = None):
|
|
14
|
+
"""
|
|
15
|
+
This function will replace all handlers of each logger in ``logger_list`` with RichHandler.
|
|
16
|
+
If there are some custom handlers in logger, they will be replaced too.
|
|
17
|
+
|
|
18
|
+
:param logger_list: A list contains loggers.
|
|
19
|
+
:type logger_list: list
|
|
20
|
+
:param logger_level: You can specify the log level in ``logger_level``, with the name of logger is the key, and the level of logger is the value.
|
|
21
|
+
Default if None, with which all loggers' level will be set to ``logging.WARNING``.
|
|
22
|
+
:type logger_level: list | None
|
|
23
|
+
:return:
|
|
24
|
+
:rtype:
|
|
25
|
+
"""
|
|
26
|
+
formatter = logging.Formatter(
|
|
27
|
+
"%(name)s :: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
|
|
28
|
+
)
|
|
29
|
+
# use rich handler
|
|
30
|
+
handler = RichHandler()
|
|
31
|
+
handler.setFormatter(formatter)
|
|
32
|
+
|
|
33
|
+
for logger_name in logger_list:
|
|
34
|
+
if logger_name in logging.root.manager.loggerDict:
|
|
35
|
+
_logger = logging.getLogger(logger_name)
|
|
36
|
+
for _handler in _logger.handlers:
|
|
37
|
+
_logger.removeHandler(_handler)
|
|
38
|
+
_logger.addHandler(handler)
|
|
39
|
+
|
|
40
|
+
if logger_level is not None and logger_name in logger_level:
|
|
41
|
+
_logger.setLevel(logger_level[logger_name])
|
|
42
|
+
else:
|
|
43
|
+
_logger.setLevel(logging.WARNING)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# init wrfrun logger
|
|
47
|
+
logger = logging.getLogger("wrfrun")
|
|
48
|
+
set_logger(["wrfrun", ], {"wrfrun": logging.DEBUG})
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def unify_logger_format():
|
|
52
|
+
"""
|
|
53
|
+
This function is only supposed to be used internally.
|
|
54
|
+
This function will replace all handlers of each logger with ``rich.logging.RichHandler``.
|
|
55
|
+
Use this carefully.
|
|
56
|
+
|
|
57
|
+
:return:
|
|
58
|
+
:rtype:
|
|
59
|
+
"""
|
|
60
|
+
set_logger(
|
|
61
|
+
["cdsapi", "cfgrib", "datapi"],
|
|
62
|
+
{
|
|
63
|
+
"cdsapi": logging.INFO,
|
|
64
|
+
"cfgrib": logging.ERROR,
|
|
65
|
+
"datapi": logging.INFO
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def check_path(*args, force=False):
|
|
71
|
+
"""Check and create all the path in *args
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
for _path in args:
|
|
77
|
+
if exists(_path) and force:
|
|
78
|
+
rmtree(_path)
|
|
79
|
+
if not exists(_path):
|
|
80
|
+
makedirs(_path)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def logger_add_file_handler(log_path: str):
|
|
84
|
+
"""Add file handler to logger
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
log_path (str): Folder to place log file
|
|
88
|
+
"""
|
|
89
|
+
# check log save path
|
|
90
|
+
check_path(log_path)
|
|
91
|
+
|
|
92
|
+
# add file handler
|
|
93
|
+
file_handler = logging.FileHandler(
|
|
94
|
+
f"{log_path}/{datetime.fromtimestamp(time()).strftime('%Y-%m-%d %H:%M:%S')}.log")
|
|
95
|
+
file_handler.setFormatter(logging.Formatter(
|
|
96
|
+
"%(asctime)s - %(name)s - %(levelname)s :: %(message)s", datefmt="%m-%d %H:%M:%S"))
|
|
97
|
+
logger.addHandler(file_handler)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def rectify_domain_size(point_num: int, nest_ratio: int) -> int:
|
|
101
|
+
"""Rectify domain size.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
point_num (int): Point number of one side.
|
|
105
|
+
nest_ratio (int): The nesting ratio relative to the domain’s parent.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
int: New size.
|
|
109
|
+
"""
|
|
110
|
+
# calculate remainder
|
|
111
|
+
point_num_mod = (point_num - 1) % nest_ratio
|
|
112
|
+
|
|
113
|
+
if point_num_mod == 0:
|
|
114
|
+
return point_num
|
|
115
|
+
|
|
116
|
+
if point_num_mod < nest_ratio / 2:
|
|
117
|
+
# # point_num_mod is closer to (nest_ratio - 1) than nest_ratio
|
|
118
|
+
point_num -= point_num_mod
|
|
119
|
+
else:
|
|
120
|
+
# # point_num_mod is closer to nest_ratio than (nest_ratio - 1)
|
|
121
|
+
point_num += (nest_ratio - point_num_mod)
|
|
122
|
+
|
|
123
|
+
return point_num
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _calculate_domain_shape(step: float, resolution: int, grid_resolution=110, nest_ratio=1) -> int:
|
|
127
|
+
"""Calculate domain shape based on its area
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
step (float): Length of the side. Unit: degree.
|
|
131
|
+
resolution (int): Resolution of domain. Unit: km.
|
|
132
|
+
grid_resolution (int, optional): Resolution of grid. Unit: km. Defaults to 110.
|
|
133
|
+
nest_ratio (int, optional): The nesting ratio relative to the domain’s parent.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
tuple[int, int]: (length of x, length of y)
|
|
137
|
+
"""
|
|
138
|
+
# calculate res based on doamin area and resolution
|
|
139
|
+
res = int(step * grid_resolution) // resolution
|
|
140
|
+
|
|
141
|
+
# rectify
|
|
142
|
+
|
|
143
|
+
return rectify_domain_size(res, nest_ratio=nest_ratio)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def calculate_domain_shape(lon_step: float, lat_step: float, resolution: int, grid_resolution=110, nest_ratio=1) -> tuple[int, int]:
|
|
147
|
+
"""Calculate domain shape based on its area
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
lon_step (float): Length in X direction. Unit: degree.
|
|
151
|
+
lat_step (float): Length in Y direction. Unit: degree.
|
|
152
|
+
resolution (int): Resolution of domain. Unit: km.
|
|
153
|
+
grid_resolution (int, optional): Resolution of grid. Unit: km. Defaults to 110.
|
|
154
|
+
nest_ratio (int, optional): The nesting ratio relative to the domain’s parent.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
tuple[int, int]: (length of x, length of y)
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
_calculate_domain_shape(
|
|
162
|
+
lon_step, resolution, grid_resolution=grid_resolution, nest_ratio=nest_ratio),
|
|
163
|
+
_calculate_domain_shape(
|
|
164
|
+
lat_step, resolution, grid_resolution=grid_resolution, nest_ratio=nest_ratio)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _check_domain_shape(point_num: int, nest_ratio: int) -> bool:
|
|
169
|
+
"""Check domain shape.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
point_num (int): Point number of one side.
|
|
173
|
+
nest_ratio (int): The nesting ratio relative to the domain’s parent.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
bool: True if pass check else False.
|
|
177
|
+
"""
|
|
178
|
+
if (point_num - 1) % nest_ratio != 0:
|
|
179
|
+
return False
|
|
180
|
+
else:
|
|
181
|
+
return True
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def check_domain_shape(x_point_num: int, y_point_num: int, nest_ratio: int) -> tuple[bool, bool]:
|
|
185
|
+
"""Check domain shape.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
x_point_num (int): Point number of X side.
|
|
189
|
+
y_point_num (int): Point number of Y side.
|
|
190
|
+
nest_ratio (int): The nesting ratio relative to the domain’s parent.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
tuple[bool, bool]: Tuple of bool. True if pass check else False
|
|
194
|
+
"""
|
|
195
|
+
return (
|
|
196
|
+
_check_domain_shape(x_point_num, nest_ratio=nest_ratio),
|
|
197
|
+
_check_domain_shape(y_point_num, nest_ratio=nest_ratio)
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def check_subprocess_status(status: subprocess.CompletedProcess):
|
|
202
|
+
"""Check subprocess return code and print log if their return code != 0
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
status (CompletedProcess): Status from subprocess.
|
|
206
|
+
"""
|
|
207
|
+
if status.returncode != 0:
|
|
208
|
+
# print command
|
|
209
|
+
command = status.args
|
|
210
|
+
logger.error(f"Failed to exec command: {command}")
|
|
211
|
+
|
|
212
|
+
# print log
|
|
213
|
+
logger.error(f"====== stdout ======")
|
|
214
|
+
logger.error(status.stdout.decode())
|
|
215
|
+
logger.error(f"====== ====== ======")
|
|
216
|
+
logger.error(f"====== stderr ======")
|
|
217
|
+
logger.error(status.stderr.decode())
|
|
218
|
+
logger.error(f"====== ====== ======")
|
|
219
|
+
|
|
220
|
+
# raise error
|
|
221
|
+
raise RuntimeError
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def call_subprocess(command: list[str], work_path: Optional[str] = None, print_output=False):
|
|
225
|
+
"""
|
|
226
|
+
Execute the given command in system shell.
|
|
227
|
+
|
|
228
|
+
:param command: A list contains the command and parameters to be executed.
|
|
229
|
+
:type command: list
|
|
230
|
+
:param work_path: The work path of the command.
|
|
231
|
+
If None, works in current directory.
|
|
232
|
+
:type work_path: str | None
|
|
233
|
+
:param print_output: If print standard output and error in the logger.
|
|
234
|
+
:type print_output: bool
|
|
235
|
+
:return:
|
|
236
|
+
:rtype:
|
|
237
|
+
"""
|
|
238
|
+
if work_path is not None:
|
|
239
|
+
origin_path = getcwd()
|
|
240
|
+
chdir(work_path)
|
|
241
|
+
else:
|
|
242
|
+
origin_path = None
|
|
243
|
+
|
|
244
|
+
status = subprocess.run(' '.join(command), shell=True, capture_output=True)
|
|
245
|
+
|
|
246
|
+
if origin_path is not None:
|
|
247
|
+
chdir(origin_path)
|
|
248
|
+
|
|
249
|
+
check_subprocess_status(status)
|
|
250
|
+
|
|
251
|
+
if print_output:
|
|
252
|
+
logger.info(status.stdout.decode())
|
|
253
|
+
logger.warning(status.stderr.decode())
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
__all__ = ["logger", "check_path", "logger_add_file_handler", "calculate_domain_shape", "rectify_domain_size", "check_domain_shape",
|
|
257
|
+
"check_subprocess_status", "call_subprocess", "set_logger", "unify_logger_format"]
|
wrfrun/workspace.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file contains functions to interact with WRF workspace
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from os import listdir, makedirs, symlink
|
|
6
|
+
from os.path import exists
|
|
7
|
+
|
|
8
|
+
from .core import WRFRUNConfig
|
|
9
|
+
from .utils import check_path, logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def prepare_workspace():
|
|
13
|
+
"""Initialize workspace
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
logger.info(f"Initialize workspace...")
|
|
17
|
+
|
|
18
|
+
# extract WRF path
|
|
19
|
+
wrf_config = WRFRUNConfig.get_model_config("wrf")
|
|
20
|
+
wps_path = wrf_config["wps_path"]
|
|
21
|
+
wrf_path = wrf_config["wrf_path"]
|
|
22
|
+
wrfda_path = wrf_config["wrfda_path"]
|
|
23
|
+
|
|
24
|
+
WRFRUN_TEMP_PATH = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_TEMP_PATH)
|
|
25
|
+
WORK_PATH = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_PATH)
|
|
26
|
+
REPLAY_WORK_PATH = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_REPLAY_WORK_PATH)
|
|
27
|
+
WPS_WORK_PATH = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WPS_WORK_PATH)
|
|
28
|
+
WRF_WORK_PATH = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRF_WORK_PATH)
|
|
29
|
+
WRFDA_WORK_PATH = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFDA_WORK_PATH)
|
|
30
|
+
output_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_OUTPUT_PATH)
|
|
31
|
+
|
|
32
|
+
# check folder
|
|
33
|
+
check_path(WRFRUN_TEMP_PATH)
|
|
34
|
+
check_path(REPLAY_WORK_PATH, force=True)
|
|
35
|
+
check_path(output_path)
|
|
36
|
+
|
|
37
|
+
if exists(wrfda_path):
|
|
38
|
+
WRFRUNConfig.USE_WRFDA = True
|
|
39
|
+
|
|
40
|
+
# create folder to run WPS, and WRF
|
|
41
|
+
# check the path
|
|
42
|
+
if not (exists(wps_path) and exists(wrf_path)):
|
|
43
|
+
logger.error(f"Your WPS or WRF path is wrong")
|
|
44
|
+
raise FileNotFoundError(f"Your WPS or WRF path is wrong")
|
|
45
|
+
|
|
46
|
+
# remove old file
|
|
47
|
+
if exists(WORK_PATH):
|
|
48
|
+
logger.info(f"Remove old files...")
|
|
49
|
+
check_path(WPS_WORK_PATH, f"{WPS_WORK_PATH}/outputs",
|
|
50
|
+
WRF_WORK_PATH, WRFDA_WORK_PATH, force=True)
|
|
51
|
+
logger.info(f"Link essential files...")
|
|
52
|
+
|
|
53
|
+
# link {wps_path}/*
|
|
54
|
+
# collect file except folder geogrid
|
|
55
|
+
file_list = [
|
|
56
|
+
x for x in listdir(wps_path) if x not in ["geogrid", "namelist.wps"]
|
|
57
|
+
]
|
|
58
|
+
for file in file_list:
|
|
59
|
+
symlink(f"{wps_path}/{file}", f"{WPS_WORK_PATH}/{file}")
|
|
60
|
+
|
|
61
|
+
# create folder geogrid and link default GEOGRID file
|
|
62
|
+
makedirs(f"{WPS_WORK_PATH}/geogrid")
|
|
63
|
+
symlink(
|
|
64
|
+
f"{wps_path}/geogrid/GEOGRID.TBL", f"{WPS_WORK_PATH}/geogrid/GEOGRID.TBL"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# # link {wrf_path}/run/*, except namelist.input
|
|
68
|
+
file_list = [x for x in listdir(
|
|
69
|
+
f"{wrf_path}/run") if not x.startswith("namelist")]
|
|
70
|
+
for file in file_list:
|
|
71
|
+
symlink(f"{wrf_path}/run/{file}", f"{WRF_WORK_PATH}/{file}")
|
|
72
|
+
|
|
73
|
+
if WRFRUNConfig.USE_WRFDA:
|
|
74
|
+
# # link {wrfda_path}/bin/*.exe
|
|
75
|
+
file_list = ["da_wrfvar.exe", "da_update_bc.exe"]
|
|
76
|
+
for file in file_list:
|
|
77
|
+
symlink(f"{wrfda_path}/var/build/{file}", f"{WRFDA_WORK_PATH}/{file}")
|
|
78
|
+
|
|
79
|
+
# # link {wrfda_path}/var/run/*
|
|
80
|
+
file_list = listdir(f"{wrfda_path}/var/run")
|
|
81
|
+
for file in file_list:
|
|
82
|
+
symlink(f"{wrfda_path}/var/run/{file}", f"{WRFDA_WORK_PATH}/{file}")
|
|
83
|
+
|
|
84
|
+
# # link {wrfda_path}/run/LANDUSE.TBL
|
|
85
|
+
symlink(f"{wrfda_path}/run/LANDUSE.TBL", f"{WRFDA_WORK_PATH}/LANDUSE.TBL")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
__all__ = ["prepare_workspace"]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: wrfrun
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: wrfrun is a comprehensive toolkit for managing and using WRF
|
|
5
|
+
Keywords: WRF
|
|
6
|
+
Author-Email: Syize <syizeliu@gmail.com>
|
|
7
|
+
Maintainer-Email: Syize <syizeliu@gmail.com>
|
|
8
|
+
License: GPL-3.0-or-later
|
|
9
|
+
Project-URL: homepage, https://github.com/Syize/wrfrun
|
|
10
|
+
Project-URL: repository, https://github.com/Syize/wrfrun
|
|
11
|
+
Project-URL: documentation, https://wrfrun.syize.cn
|
|
12
|
+
Project-URL: Bug Tracker, https://github.com/Syize/wrfrun/issues
|
|
13
|
+
Requires-Python: <3.13
|
|
14
|
+
Requires-Dist: numpy<2.0.0
|
|
15
|
+
Requires-Dist: xarray
|
|
16
|
+
Requires-Dist: netCDF4
|
|
17
|
+
Requires-Dist: rich
|
|
18
|
+
Requires-Dist: pandas
|
|
19
|
+
Requires-Dist: f90nml
|
|
20
|
+
Requires-Dist: cdsapi
|
|
21
|
+
Requires-Dist: matplotlib
|
|
22
|
+
Requires-Dist: Cartopy
|
|
23
|
+
Requires-Dist: wrf-python
|
|
24
|
+
Requires-Dist: cfgrib
|
|
25
|
+
Requires-Dist: tomli
|
|
26
|
+
Requires-Dist: tomli-w
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# wrfrun: A toolkit to control WRF
|
|
30
|
+
|
|
31
|
+
## What is wrfrun?
|
|
32
|
+
|
|
33
|
+
Using and managing WRF can be a tedious task. WRF's configuration file contains a large number of settings, which generally need to be configured separately for each simulation case, and the user usually needs to rely on other tools or scripts to manage the simulation of different cases, which causes a lot of inconvenience. In addition, the whole process of running the WRF model involves running many programs, which is very time-consuming to run manually and requires the use of scripts to automate certain processes.
|
|
34
|
+
|
|
35
|
+
`wrfrun` is a comprehensive toolkit for managing and using WRF. `wrfrun` wraps the WRF model so that the user only needs to call the corresponding Python function to run the corresponding part of the model. `wrfrun` avoids cluttering up the user's working directory with a lot of useless files by creating a temporary directory in which the WRF model would be run. `wrfrun` automatically saves mode configurations and wrfrun configurations, which makes it easier to manage the simulation and reproduction of different cases. `wrfrun` also provides more features through extensions, which help users to do related research better.
|
|
36
|
+
|
|
37
|
+
## Main Features
|
|
38
|
+
|
|
39
|
+
The following are the main features that wrfrun wants to achieve. These features have been basically realized, and are still under continuous improvement.
|
|
40
|
+
|
|
41
|
+
- Isolate the WRF runtime directory in a separate temporary directory.
|
|
42
|
+
- Automatic saving of mode output, logs and configurations.
|
|
43
|
+
- Provide an interface to run any part of the WRF model.
|
|
44
|
+
- Real-time parsing of WRF logs, feedback on simulation progress.
|
|
45
|
+
- Support for adding more functionality through extensions.
|
|
46
|
+
|
|
47
|
+
## Dependencies
|
|
48
|
+
|
|
49
|
+
You need to install `meson` and `ninja` at first, both of which can be installed using `pip`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install meson ninja
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Make sure the path `$HOME/.local/bin` has been added to your environment variable `PATH`.
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
Install using pip:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install wrfrun
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
Please check [Wiki](https://wrfrun.syize.cn).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
wrfrun-0.1.7.dist-info/METADATA,sha256=nrPBmS0UxcjIiCN9wLyL798-r3OKpirBJUPlWrzobw8,2912
|
|
2
|
+
wrfrun-0.1.7.dist-info/WHEEL,sha256=5J4neoE7k6LMgx4Fz1FHgBiO3YevhJGtNQ3muDrdLQM,75
|
|
3
|
+
wrfrun/__init__.py,sha256=l2zGk2qDWa3EXIlwvzqBYZHOU9273TN75Rmvx_7PAYM,58
|
|
4
|
+
wrfrun/data.py,sha256=AjkDSZqkLROnWLw9qDOBUctoQmJ3R1bkfjnPzLMjPfs,14751
|
|
5
|
+
wrfrun/pbs.py,sha256=gzRHbYqpU-c8lynu39TUKNvmPntvrPwfQVxK337yvjw,2454
|
|
6
|
+
wrfrun/run.py,sha256=0mvuI98gLjq1gP1eaLUZiU1LJMCjtL668aKZTwu3n2g,9114
|
|
7
|
+
wrfrun/utils.py,sha256=v3ZRu3Rd8-pZjo7I0PrJtgBN1zIBAt_nVPs0BP_DFwY,8118
|
|
8
|
+
wrfrun/workspace.py,sha256=5tWIIFxwAE4hkdg_wJALGDc3P0bfwb_IRTIyPIjN-tE,3105
|
|
9
|
+
wrfrun/core/__init__.py,sha256=bf9Fp6VS5i9xB10lazYBOkJapF2jnQpyiB6qucVjp0I,107
|
|
10
|
+
wrfrun/core/base.py,sha256=S9Mqr3LOpos0CP0TsFwtCQl0tLIObIhjX7VxjS0LRDY,23172
|
|
11
|
+
wrfrun/core/config.py,sha256=v7zdhAthlMmjv_BWINxkmgNHLvKZdzQhgM5B-Nlsl7M,23795
|
|
12
|
+
wrfrun/core/error.py,sha256=fCWVC4-GTyDH2obzu9-D_bzF8_uzqZoUi7Ffy0B5qoc,1324
|
|
13
|
+
wrfrun/core/replay.py,sha256=oyV9QppZG99GbAksQqoRxeBQ3jjXU-7YqkpxHRyfBvc,3229
|
|
14
|
+
wrfrun/core/server.py,sha256=KK_yj4J-5F_s-rKO5FK7e8WojsnuZMbhWtMceWYbaBY,6524
|
|
15
|
+
wrfrun/extension/__init__.py,sha256=alIDGBnxWH4JvP-UW-7N99seBBi0r1GV1h8f1ERFBec,21
|
|
16
|
+
wrfrun/extension/utils.py,sha256=OBIAlAXakbh1QhrF2BFlYAFV062ZfJjX0mYJkmcU_RI,2751
|
|
17
|
+
wrfrun/extension/littler/__init__.py,sha256=pG-YPVG0gJIJ6s4xcAz9S_CnUxpUcz33wl9eNUSgxGk,20
|
|
18
|
+
wrfrun/extension/littler/utils.py,sha256=TsN3GiAFszPWF7RNM_hYdARRY_OLL8mYm87UyZupUtU,21615
|
|
19
|
+
wrfrun/model/__init__.py,sha256=lQNNnh3evXZytLAjdnhlIEFWerP1L0XAgDAUQhqIRyE,119
|
|
20
|
+
wrfrun/model/base.py,sha256=WnVNu12ICJgThfZR7kK6_XLCQWVYFsHrdyAz8wl_YRc,218
|
|
21
|
+
wrfrun/model/plot.py,sha256=ATG5nl5kV8YfoeNFIPLCUnnIQIrfIFNGPb9d8raM6S0,1582
|
|
22
|
+
wrfrun/model/utils.py,sha256=Pyj9D9NMKw3wQcZcM7pJaLG09Vov447AxFKoVeZZU2s,1155
|
|
23
|
+
wrfrun/model/wrf/__init__.py,sha256=T3S1BD9QDoW4uq871QW4_8-2BvCRWYEecz71EcdbMaI,136
|
|
24
|
+
wrfrun/model/wrf/core.py,sha256=FEzRXUKK5dENxev3wR_GON5n1Zxq4Hj-Bs_BNP7P_ok,32134
|
|
25
|
+
wrfrun/model/wrf/exec_wrap.py,sha256=gIsGZDAjzRzxt24eo8t-laIK4UBiyKf_ysfAZLlE1og,3918
|
|
26
|
+
wrfrun/model/wrf/geodata.py,sha256=X9OUOm0__5NI7sl2z1F9_ur5wZ4P0HkpBNcRZQYKof0,9740
|
|
27
|
+
wrfrun/model/wrf/_metgrid.py,sha256=i2qILM_1LkdnBZqXXL3swVhMRvhFvq4bOcRPGI6kSzg,2248
|
|
28
|
+
wrfrun/model/wrf/namelist.py,sha256=t_JuWYj4oNNVwzTMKo6BNlv2LIq4t3JC7ZgVkaKfNbA,14923
|
|
29
|
+
wrfrun/model/wrf/_ndown.py,sha256=ZcWttGXiT5FzGCAohmbeNU6bi8GUOUleiTK0ivn2BaI,1548
|
|
30
|
+
wrfrun/model/wrf/scheme.py,sha256=F7HxoaNkkPpjkse5t9sGS3CJDvn_yBdHoaCG7WLdbqY,8524
|
|
31
|
+
wrfrun/model/wrf/vtable.py,sha256=0V4fo0Limnx4oJ2NByq_eHPzj8L4mnHNlrKL34Buw1A,2432
|
|
32
|
+
wrfrun/plot/__init__.py,sha256=9Kn0IgkX10sHEqHJwk7mZV-dP14XMNcvXN8znO89FIw,19
|
|
33
|
+
wrfrun/plot/wps.py,sha256=AQ1B6llNUrPU3PR8XKNLSzs_H-v60a0Wep-8Mcto6NM,5319
|
|
34
|
+
wrfrun/res/__init__.py,sha256=YBcVaM2EZZJkDDvyKdk-WZmcFQoTFENZKCwcIQzEf3I,1133
|
|
35
|
+
wrfrun/res/config.toml.template,sha256=aVXCSzhbV3P-MQCZOk2g-y0auRmqgr3jW920W3wks9g,4386
|
|
36
|
+
wrfrun/res/run.sh.template,sha256=ZN7k0a9ONOtZUQ67JiTva-0DNVJG5O7BdOXQ8-LCscs,247
|
|
37
|
+
wrfrun/res/extension/plotgrids.ncl,sha256=B0mvH1H1j_w7EEana9HmU1XJZtG0w9IccQ54zXpbQG0,7546
|
|
38
|
+
wrfrun/res/namelist/namelist.input.da_wrfvar.template,sha256=Cwc-XPu_spJeQte4duWrulPBOLRMEBtn0mIn0pgMmKY,4912
|
|
39
|
+
wrfrun/res/namelist/namelist.input.dfi.template,sha256=E7MVbIvMopkAM7xGUC4vniC1WOUVbIbdLfkTKHqzX_o,6591
|
|
40
|
+
wrfrun/res/namelist/namelist.input.real.template,sha256=DDUiArtBFmzBwVjkZW4NOrBR34eIOk1vV0VsyL0stsk,6214
|
|
41
|
+
wrfrun/res/namelist/namelist.input.wrf.template,sha256=myrKi79sQ8ABBsmQJkcgN0WLbWJdtMVPIjuAC1MTMuM,6213
|
|
42
|
+
wrfrun/res/namelist/namelist.wps.template,sha256=HlA7-SHs4C-cKRb3h6D0Kl1Y-5VSJ1Lw9hLiXWGAN0Q,1017
|
|
43
|
+
wrfrun/res/namelist/parame.in.template,sha256=vR8JSix20FAKGqj6jK8QuEAeWkGvg8_iptdVlzjPX6o,259
|
|
44
|
+
wrfrun/res/job_scheduler/pbs.template,sha256=m7eyvZkzQRpjs43CvSeZ1biHYNyEJJkgXt3IU5ZhCmg,148
|
|
45
|
+
wrfrun/res/job_scheduler/slurm.template,sha256=BrKL8DcHfpFfv0y0z7Qe_cqjwfzMyF-3V6vM72ehr9Y,312
|
|
46
|
+
wrfrun-0.1.7.dist-info/RECORD,,
|