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/plot.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from os import chdir, getcwd
|
|
2
|
+
from os.path import abspath, exists
|
|
3
|
+
from shutil import copyfile, move
|
|
4
|
+
|
|
5
|
+
from wrfrun.core import WRFRUNConfig
|
|
6
|
+
from wrfrun.res import EXT_NCL_PLOT_SCRIPT
|
|
7
|
+
from wrfrun.utils import call_subprocess, check_path, logger
|
|
8
|
+
from .wrf.namelist import prepare_wps_namelist
|
|
9
|
+
from .base import NamelistName
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def plot_domain_area():
|
|
13
|
+
"""Generate namelist and plot domain area with WRF NCL script.
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
prepare_wps_namelist()
|
|
17
|
+
|
|
18
|
+
# get save path
|
|
19
|
+
save_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_OUTPUT_PATH)
|
|
20
|
+
|
|
21
|
+
# check
|
|
22
|
+
check_path(save_path)
|
|
23
|
+
|
|
24
|
+
# conver to absolute path
|
|
25
|
+
save_path = abspath(save_path)
|
|
26
|
+
save_path = f"{save_path}/wps_show_dom.png"
|
|
27
|
+
|
|
28
|
+
# record original path
|
|
29
|
+
origin_path = getcwd()
|
|
30
|
+
|
|
31
|
+
# enter WPS WORK PATH
|
|
32
|
+
chdir(WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WPS_WORK_PATH))
|
|
33
|
+
|
|
34
|
+
# save namelist
|
|
35
|
+
WRFRUNConfig.write_namelist(f"./{NamelistName.WPS}", "wps", overwrite=True)
|
|
36
|
+
|
|
37
|
+
# copy plot script and plot
|
|
38
|
+
copyfile(WRFRUNConfig.parse_resource_uri(EXT_NCL_PLOT_SCRIPT), f"./plotgrids.ncl")
|
|
39
|
+
call_subprocess(["ncl", "./plotgrids.ncl"], print_output=True)
|
|
40
|
+
|
|
41
|
+
# save image
|
|
42
|
+
# we need to check image file, because sometimes ncl doesn't return error code
|
|
43
|
+
if not exists("./wps_show_dom.png"):
|
|
44
|
+
logger.error(f"Fail to plot domain with NCL. Check the log above")
|
|
45
|
+
raise FileNotFoundError
|
|
46
|
+
move("./wps_show_dom.png", save_path)
|
|
47
|
+
|
|
48
|
+
logger.info(f"The image of domain area has been saved to {save_path}")
|
|
49
|
+
|
|
50
|
+
# go back
|
|
51
|
+
chdir(origin_path)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = ["plot_domain_area"]
|
wrfrun/model/utils.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from os import listdir
|
|
2
|
+
from shutil import move
|
|
3
|
+
|
|
4
|
+
from ..core import WRFRUNConfig
|
|
5
|
+
from ..utils import check_path, logger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def clear_model_logs():
|
|
9
|
+
"""
|
|
10
|
+
This function can automatically collect WRF log files and save them to ``output_path``.
|
|
11
|
+
This function is used inside the wrfrun package.
|
|
12
|
+
If you want to do something about the log files, check the corresponding code of interface functions in ``wrfrun.model.run``.
|
|
13
|
+
|
|
14
|
+
:return:
|
|
15
|
+
:rtype:
|
|
16
|
+
"""
|
|
17
|
+
work_status = WRFRUNConfig.WRFRUN_WORK_STATUS
|
|
18
|
+
work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRF_WORK_PATH)
|
|
19
|
+
|
|
20
|
+
log_files = [x for x in listdir(work_path) if x.startswith("rsl.")]
|
|
21
|
+
|
|
22
|
+
if len(log_files) > 0:
|
|
23
|
+
logger.warning(f"Found unprocessed log files of {work_status}")
|
|
24
|
+
|
|
25
|
+
log_save_path = f"{WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_OUTPUT_PATH)}/{work_status}/logs"
|
|
26
|
+
check_path(log_save_path)
|
|
27
|
+
|
|
28
|
+
for _file in log_files:
|
|
29
|
+
move(f"{work_path}/{_file}", f"{log_save_path}/{_file}")
|
|
30
|
+
|
|
31
|
+
logger.warning(f"Unprocessed log files of {work_status} has been saved to {log_save_path}, check it")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
__all__ = ["clear_model_logs"]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from os import listdir
|
|
2
|
+
from os.path import exists
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
from xarray import open_dataset
|
|
6
|
+
|
|
7
|
+
from wrfrun.core import WRFRUNConfig
|
|
8
|
+
from wrfrun.utils import logger
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_metgrid_levels(nc_file: str) -> Dict[str, int]:
|
|
12
|
+
"""Read metgrid output file and get metgrid levels, land cat and metgrid soil levels
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
nc_file (str): Output nc file path
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
Dict[str, int]: {num_metgrid_levels: number, num_land_cat: number, num_metgrid_soil_level: number}
|
|
19
|
+
"""
|
|
20
|
+
# check file
|
|
21
|
+
if not exists(nc_file):
|
|
22
|
+
logger.error(f"File {nc_file} not exists")
|
|
23
|
+
raise FileNotFoundError
|
|
24
|
+
|
|
25
|
+
# read data
|
|
26
|
+
dataset = open_dataset(nc_file)
|
|
27
|
+
|
|
28
|
+
# read variables
|
|
29
|
+
num_metgrid_levels = dataset["num_metgrid_levels"].size
|
|
30
|
+
num_land_cat = dataset.attrs["NUM_LAND_CAT"]
|
|
31
|
+
num_metgrid_soil_levels = dataset.attrs["NUM_METGRID_SOIL_LEVELS"]
|
|
32
|
+
|
|
33
|
+
return dict(
|
|
34
|
+
num_metgrid_levels=num_metgrid_levels,
|
|
35
|
+
num_land_cat=num_land_cat,
|
|
36
|
+
num_metgrid_soil_levels=num_metgrid_soil_levels
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def reconcile_namelist_metgrid(metgrid_path: str):
|
|
41
|
+
"""
|
|
42
|
+
There are some settings in WRF namelist that are affected by metgrid output, for example, ``num_metgrid_levels``.
|
|
43
|
+
Namelist should be checked and modified before be used by WRF.
|
|
44
|
+
|
|
45
|
+
:param metgrid_path: The path store output from metgrid.exe.
|
|
46
|
+
If it is None, the default output path will be used.
|
|
47
|
+
:type metgrid_path: str
|
|
48
|
+
:return:
|
|
49
|
+
:rtype:
|
|
50
|
+
"""
|
|
51
|
+
logger.info(f"Checking values in WRF namelist and metgrid output ...")
|
|
52
|
+
metgrid_output_name = [x for x in listdir(metgrid_path) if x.endswith(".nc")]
|
|
53
|
+
metgrid_output_name.sort()
|
|
54
|
+
metgrid_output_name = metgrid_output_name[0]
|
|
55
|
+
|
|
56
|
+
metgrid_levels = get_metgrid_levels(f"{metgrid_path}/{metgrid_output_name}")
|
|
57
|
+
|
|
58
|
+
update_values = {
|
|
59
|
+
"domains": {
|
|
60
|
+
"num_metgrid_levels": metgrid_levels["num_metgrid_levels"],
|
|
61
|
+
"num_metgrid_soil_levels": metgrid_levels["num_metgrid_soil_levels"],
|
|
62
|
+
},
|
|
63
|
+
"physics": {
|
|
64
|
+
"num_land_cat": metgrid_levels["num_land_cat"]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
WRFRUNConfig.update_namelist(update_values, "wrf")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
__all__ = ["get_metgrid_levels", "reconcile_namelist_metgrid"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from wrfrun.core import WRFRUNConfig
|
|
2
|
+
from wrfrun.utils import logger
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def process_after_ndown():
|
|
6
|
+
"""
|
|
7
|
+
After running ndown.exe, namelist settings are supposed to be changed,
|
|
8
|
+
so WRF can simulate a higher resolution domain according to `WRF User's Guide <https://www2.mmm.ucar.edu/wrf/users/wrf_users_guide/build/html/running_wrf.html#wrf-nesting>`_.
|
|
9
|
+
`wrfrun` provide this function to help you change these settings which have multiple values for each domain.
|
|
10
|
+
The first value will be removed to ensure the value of higher resolution domain is the first value.
|
|
11
|
+
|
|
12
|
+
:return:
|
|
13
|
+
"""
|
|
14
|
+
namelist_data = WRFRUNConfig.get_namelist("wrf")
|
|
15
|
+
|
|
16
|
+
for section in namelist_data:
|
|
17
|
+
if section in ["bdy_control", "namelist_quilt"]:
|
|
18
|
+
continue
|
|
19
|
+
|
|
20
|
+
for key in namelist_data[section]:
|
|
21
|
+
if key in ["grid_id", "parent_id", "i_parent_start", "j_parent_start", "parent_grid_ratio", "parent_time_step_ratio", "eta_levels"]:
|
|
22
|
+
continue
|
|
23
|
+
|
|
24
|
+
if isinstance(namelist_data[section][key], list):
|
|
25
|
+
|
|
26
|
+
if len(namelist_data[section][key]) > 1:
|
|
27
|
+
namelist_data[section][key] = namelist_data[section][key][1:]
|
|
28
|
+
|
|
29
|
+
namelist_data["domains"]["max_dom"] = 1
|
|
30
|
+
|
|
31
|
+
time_ratio = namelist_data["domains"]["parent_time_step_ratio"][1]
|
|
32
|
+
namelist_data["domains"]["time_step"] = namelist_data["domains"]["time_step"] // time_ratio
|
|
33
|
+
|
|
34
|
+
WRFRUNConfig.update_namelist(namelist_data, "wrf")
|
|
35
|
+
|
|
36
|
+
logger.info(f"Update namelist after running ndown.exe")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
__all__ = ["process_after_ndown"]
|