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.
Files changed (46) hide show
  1. wrfrun/__init__.py +3 -0
  2. wrfrun/core/__init__.py +5 -0
  3. wrfrun/core/base.py +680 -0
  4. wrfrun/core/config.py +717 -0
  5. wrfrun/core/error.py +80 -0
  6. wrfrun/core/replay.py +113 -0
  7. wrfrun/core/server.py +212 -0
  8. wrfrun/data.py +418 -0
  9. wrfrun/extension/__init__.py +1 -0
  10. wrfrun/extension/littler/__init__.py +1 -0
  11. wrfrun/extension/littler/utils.py +599 -0
  12. wrfrun/extension/utils.py +66 -0
  13. wrfrun/model/__init__.py +7 -0
  14. wrfrun/model/base.py +14 -0
  15. wrfrun/model/plot.py +54 -0
  16. wrfrun/model/utils.py +34 -0
  17. wrfrun/model/wrf/__init__.py +6 -0
  18. wrfrun/model/wrf/_metgrid.py +71 -0
  19. wrfrun/model/wrf/_ndown.py +39 -0
  20. wrfrun/model/wrf/core.py +805 -0
  21. wrfrun/model/wrf/exec_wrap.py +101 -0
  22. wrfrun/model/wrf/geodata.py +301 -0
  23. wrfrun/model/wrf/namelist.py +377 -0
  24. wrfrun/model/wrf/scheme.py +311 -0
  25. wrfrun/model/wrf/vtable.py +65 -0
  26. wrfrun/pbs.py +86 -0
  27. wrfrun/plot/__init__.py +1 -0
  28. wrfrun/plot/wps.py +188 -0
  29. wrfrun/res/__init__.py +22 -0
  30. wrfrun/res/config.toml.template +136 -0
  31. wrfrun/res/extension/plotgrids.ncl +216 -0
  32. wrfrun/res/job_scheduler/pbs.template +6 -0
  33. wrfrun/res/job_scheduler/slurm.template +6 -0
  34. wrfrun/res/namelist/namelist.input.da_wrfvar.template +261 -0
  35. wrfrun/res/namelist/namelist.input.dfi.template +260 -0
  36. wrfrun/res/namelist/namelist.input.real.template +256 -0
  37. wrfrun/res/namelist/namelist.input.wrf.template +256 -0
  38. wrfrun/res/namelist/namelist.wps.template +44 -0
  39. wrfrun/res/namelist/parame.in.template +11 -0
  40. wrfrun/res/run.sh.template +16 -0
  41. wrfrun/run.py +264 -0
  42. wrfrun/utils.py +257 -0
  43. wrfrun/workspace.py +88 -0
  44. wrfrun-0.1.7.dist-info/METADATA +67 -0
  45. wrfrun-0.1.7.dist-info/RECORD +46 -0
  46. 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,6 @@
1
+ from .core import *
2
+ from .exec_wrap import *
3
+ from .geodata import *
4
+ from .namelist import *
5
+ from .scheme import *
6
+ from .vtable import *
@@ -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"]