wrfrun 0.1.9__py3-none-any.whl → 0.3.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.
- wrfrun/__init__.py +8 -3
- wrfrun/cli.py +74 -31
- wrfrun/core/__init__.py +27 -10
- wrfrun/core/_config.py +308 -0
- wrfrun/core/_constant.py +236 -0
- wrfrun/core/_exec_db.py +105 -0
- wrfrun/core/_namelist.py +287 -0
- wrfrun/core/_record.py +178 -0
- wrfrun/core/_resource.py +172 -0
- wrfrun/core/base.py +136 -380
- wrfrun/core/core.py +196 -0
- wrfrun/core/error.py +35 -2
- wrfrun/core/replay.py +10 -96
- wrfrun/core/server.py +74 -32
- wrfrun/core/type.py +171 -0
- wrfrun/data.py +312 -149
- wrfrun/extension/goos_sst/__init__.py +2 -2
- wrfrun/extension/goos_sst/core.py +9 -14
- wrfrun/extension/goos_sst/res/__init__.py +0 -1
- wrfrun/extension/goos_sst/utils.py +50 -44
- wrfrun/extension/littler/core.py +105 -88
- wrfrun/extension/utils.py +5 -3
- wrfrun/log.py +117 -0
- wrfrun/model/__init__.py +11 -7
- wrfrun/model/constants.py +52 -0
- wrfrun/model/palm/__init__.py +30 -0
- wrfrun/model/palm/core.py +145 -0
- wrfrun/model/palm/namelist.py +33 -0
- wrfrun/model/plot.py +99 -114
- wrfrun/model/type.py +116 -0
- wrfrun/model/utils.py +9 -19
- wrfrun/model/wrf/__init__.py +4 -9
- wrfrun/model/wrf/core.py +262 -165
- wrfrun/model/wrf/exec_wrap.py +13 -12
- wrfrun/model/wrf/geodata.py +116 -99
- wrfrun/model/wrf/log.py +103 -0
- wrfrun/model/wrf/namelist.py +92 -76
- wrfrun/model/wrf/plot.py +102 -0
- wrfrun/model/wrf/scheme.py +108 -52
- wrfrun/model/wrf/utils.py +39 -24
- wrfrun/model/wrf/vtable.py +42 -7
- wrfrun/plot/__init__.py +20 -0
- wrfrun/plot/wps.py +90 -73
- wrfrun/res/__init__.py +115 -5
- wrfrun/res/config/config.template.toml +15 -0
- wrfrun/res/config/palm.template.toml +23 -0
- wrfrun/run.py +121 -77
- wrfrun/scheduler/__init__.py +1 -0
- wrfrun/scheduler/lsf.py +4 -1
- wrfrun/scheduler/pbs.py +4 -1
- wrfrun/scheduler/script.py +19 -5
- wrfrun/scheduler/slurm.py +4 -1
- wrfrun/scheduler/utils.py +14 -2
- wrfrun/utils.py +88 -199
- wrfrun/workspace/__init__.py +8 -5
- wrfrun/workspace/core.py +21 -11
- wrfrun/workspace/palm.py +137 -0
- wrfrun/workspace/wrf.py +59 -14
- wrfrun-0.3.0.dist-info/METADATA +240 -0
- wrfrun-0.3.0.dist-info/RECORD +78 -0
- wrfrun/core/config.py +0 -767
- wrfrun/model/base.py +0 -14
- wrfrun-0.1.9.dist-info/METADATA +0 -68
- wrfrun-0.1.9.dist-info/RECORD +0 -62
- {wrfrun-0.1.9.dist-info → wrfrun-0.3.0.dist-info}/WHEEL +0 -0
- {wrfrun-0.1.9.dist-info → wrfrun-0.3.0.dist-info}/entry_points.txt +0 -0
wrfrun/log.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.log
|
|
3
|
+
##########
|
|
4
|
+
|
|
5
|
+
.. autosummary::
|
|
6
|
+
:toctree: generated/
|
|
7
|
+
|
|
8
|
+
get_wrfrun_rich_console
|
|
9
|
+
logger_add_file_handler
|
|
10
|
+
set_logger
|
|
11
|
+
unify_logger_format
|
|
12
|
+
|
|
13
|
+
``wrfrun`` submodule to manage logs. This submodule only take care of ``wrfrun``'s log.
|
|
14
|
+
|
|
15
|
+
For functions and classes which parse numerical models' log, please check :doc:`model </api/model>`.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import logging
|
|
19
|
+
from datetime import datetime
|
|
20
|
+
from os import environ
|
|
21
|
+
from time import time
|
|
22
|
+
from typing import Dict, List, Optional
|
|
23
|
+
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
from rich.logging import RichHandler
|
|
26
|
+
|
|
27
|
+
from .utils import check_path
|
|
28
|
+
|
|
29
|
+
WRFRUN_RICH_CONSOLE = Console()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def set_logger(logger_list: List[str], logger_level: Optional[Dict] = None):
|
|
33
|
+
"""
|
|
34
|
+
This function will replace all handlers of each logger in ``logger_list`` with RichHandler.
|
|
35
|
+
|
|
36
|
+
If there are some custom handlers in logger, they will be replaced too.
|
|
37
|
+
|
|
38
|
+
:param logger_list: A list contains loggers.
|
|
39
|
+
:type logger_list: list
|
|
40
|
+
:param logger_level: You can specify the log level in ``logger_level``, with the name of logger is the key,
|
|
41
|
+
and the level of logger is the value.
|
|
42
|
+
Default if None, with which all loggers' level will be set to ``logging.WARNING``.
|
|
43
|
+
:type logger_level: list | None
|
|
44
|
+
"""
|
|
45
|
+
formatter = logging.Formatter("%(name)s :: %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
|
46
|
+
# use rich handler
|
|
47
|
+
handler = RichHandler(console=WRFRUN_RICH_CONSOLE)
|
|
48
|
+
handler.setFormatter(formatter)
|
|
49
|
+
|
|
50
|
+
for logger_name in logger_list:
|
|
51
|
+
if logger_name in logging.root.manager.loggerDict:
|
|
52
|
+
_logger = logging.getLogger(logger_name)
|
|
53
|
+
for _handler in _logger.handlers:
|
|
54
|
+
_logger.removeHandler(_handler)
|
|
55
|
+
_logger.addHandler(handler)
|
|
56
|
+
|
|
57
|
+
if logger_level is not None and logger_name in logger_level:
|
|
58
|
+
_logger.setLevel(logger_level[logger_name])
|
|
59
|
+
else:
|
|
60
|
+
_logger.setLevel(logging.WARNING)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def unify_logger_format():
|
|
64
|
+
"""
|
|
65
|
+
This function is only supposed to be used internally.
|
|
66
|
+
|
|
67
|
+
This function will replace all handlers of each logger with ``rich.logging.RichHandler``.
|
|
68
|
+
Use this carefully.
|
|
69
|
+
"""
|
|
70
|
+
set_logger(
|
|
71
|
+
["cdsapi", "cfgrib", "datapi"],
|
|
72
|
+
{"cdsapi": logging.INFO, "cfgrib": logging.ERROR, "datapi": logging.INFO},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# init wrfrun logger
|
|
77
|
+
logger = logging.getLogger("wrfrun")
|
|
78
|
+
# check environment variables and set logger level
|
|
79
|
+
if "WRFRUN_DEBUG_MODE" in environ and environ["WRFRUN_DEBUG_MODE"]:
|
|
80
|
+
_logger_level = logging.DEBUG
|
|
81
|
+
_debug_mode = True
|
|
82
|
+
else:
|
|
83
|
+
_logger_level = logging.INFO
|
|
84
|
+
_debug_mode = False
|
|
85
|
+
set_logger(["wrfrun"], {"wrfrun": _logger_level})
|
|
86
|
+
logger.debug(f"DEBUG MODE: {_debug_mode}")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def logger_add_file_handler(log_path: str):
|
|
90
|
+
"""
|
|
91
|
+
Set log file of logger.
|
|
92
|
+
|
|
93
|
+
:param log_path: Log file path.
|
|
94
|
+
:type log_path: str
|
|
95
|
+
"""
|
|
96
|
+
# check log save path
|
|
97
|
+
check_path(log_path)
|
|
98
|
+
|
|
99
|
+
# add file handler
|
|
100
|
+
file_handler = logging.FileHandler(f"{log_path}/{datetime.fromtimestamp(time()).strftime('%Y-%m-%d %H:%M:%S')}.log")
|
|
101
|
+
file_handler.setFormatter(
|
|
102
|
+
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s :: %(message)s", datefmt="%m-%d %H:%M:%S")
|
|
103
|
+
)
|
|
104
|
+
logger.addHandler(file_handler)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def get_wrfrun_rich_console() -> Console:
|
|
108
|
+
"""
|
|
109
|
+
Get ``rich.console.Console`` instance used in wrfrun.
|
|
110
|
+
|
|
111
|
+
:return: Console instance.
|
|
112
|
+
:rtype: Console
|
|
113
|
+
"""
|
|
114
|
+
return WRFRUN_RICH_CONSOLE
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
__all__ = ["set_logger", "unify_logger_format", "logger_add_file_handler", "logger", "get_wrfrun_rich_console"]
|
wrfrun/model/__init__.py
CHANGED
|
@@ -3,12 +3,14 @@ wrfrun.model
|
|
|
3
3
|
############
|
|
4
4
|
|
|
5
5
|
To be able to handle different numerical models,
|
|
6
|
-
``wrfrun`` implements various ``Executable`` for model's binary executable
|
|
6
|
+
``wrfrun`` implements various ``Executable`` for model's binary executable
|
|
7
|
+
based on :class:`ExecutableBase <wrfrun.core.base.ExecutableBase>`,
|
|
7
8
|
which are all placed in this module.
|
|
8
9
|
|
|
9
10
|
``wrfrun.model`` currently supports following numerical models:
|
|
10
11
|
|
|
11
12
|
========================================= ==========================================
|
|
13
|
+
:doc:`palm </api/model.palm>` Support for PALM
|
|
12
14
|
:doc:`wrf </api/model.wrf>` Support for WRF
|
|
13
15
|
========================================= ==========================================
|
|
14
16
|
|
|
@@ -16,15 +18,17 @@ which are all placed in this module.
|
|
|
16
18
|
:maxdepth: 1
|
|
17
19
|
:hidden:
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
constants <model.constants>
|
|
22
|
+
palm <model.palm>
|
|
21
23
|
plot <model.plot>
|
|
24
|
+
type <model.type>
|
|
22
25
|
utils <model.utils>
|
|
26
|
+
wrf <model.wrf>
|
|
23
27
|
"""
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
# just to register executables
|
|
30
|
+
from . import palm as _
|
|
31
|
+
from . import wrf as _
|
|
32
|
+
from .constants import *
|
|
26
33
|
from .plot import *
|
|
27
34
|
from .utils import *
|
|
28
|
-
|
|
29
|
-
# just to register executables
|
|
30
|
-
from . import wrf
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.model.constants
|
|
3
|
+
######################
|
|
4
|
+
|
|
5
|
+
Definition of constants used by models.
|
|
6
|
+
|
|
7
|
+
.. autosummary::
|
|
8
|
+
:toctree: generated/
|
|
9
|
+
|
|
10
|
+
NamelistName
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class NamelistName:
|
|
18
|
+
"""
|
|
19
|
+
Namelist file names.
|
|
20
|
+
|
|
21
|
+
.. py:attribute:: WPS
|
|
22
|
+
:type: str
|
|
23
|
+
:value: namelist.wps
|
|
24
|
+
|
|
25
|
+
WPS namelist file name.
|
|
26
|
+
|
|
27
|
+
.. py:attribute:: WRF
|
|
28
|
+
:type: str
|
|
29
|
+
:value: namelist.input
|
|
30
|
+
|
|
31
|
+
WRF namelist file name.
|
|
32
|
+
|
|
33
|
+
.. py:attribute:: WRFDA
|
|
34
|
+
:type: str
|
|
35
|
+
:value: namelist.input
|
|
36
|
+
|
|
37
|
+
WRFDA namelist file name.
|
|
38
|
+
|
|
39
|
+
.. py:attribute:: PALM
|
|
40
|
+
:type: str
|
|
41
|
+
:value: wrfrun_p3d
|
|
42
|
+
|
|
43
|
+
PALM namelist file name.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
WPS = "namelist.wps"
|
|
47
|
+
WRF = "namelist.input"
|
|
48
|
+
WRFDA = "namelist.input"
|
|
49
|
+
PALM = "wrfrun_p3d"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
__all__ = ["NamelistName"]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.model.palm
|
|
3
|
+
#################
|
|
4
|
+
|
|
5
|
+
Implementation of PALM model.
|
|
6
|
+
|
|
7
|
+
Submodules
|
|
8
|
+
**********
|
|
9
|
+
|
|
10
|
+
============================================ ==================================================================================
|
|
11
|
+
:doc:`core </api/model.palm.core>` Core implementation of PALM model.
|
|
12
|
+
:doc:`namelist </api/model.palm.namelist>` Functions to process PALM namelist files.
|
|
13
|
+
============================================ ==================================================================================
|
|
14
|
+
|
|
15
|
+
About the implementation of PALM
|
|
16
|
+
********************************
|
|
17
|
+
|
|
18
|
+
Since ``PALM`` provides a bash script ``palmrun`` to take care of the running of ``palm``,
|
|
19
|
+
``wrfrun`` just simply wraps the bash script.
|
|
20
|
+
|
|
21
|
+
.. toctree::
|
|
22
|
+
:maxdepth: 1
|
|
23
|
+
:hidden:
|
|
24
|
+
|
|
25
|
+
core <model.palm.core>
|
|
26
|
+
namelist <model.palm.namelist>
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from .core import *
|
|
30
|
+
from .namelist import *
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.model.palm.core
|
|
3
|
+
######################
|
|
4
|
+
|
|
5
|
+
Core implementation of PALM model. All ``Executable`` and function interface of PALM model are defined here.
|
|
6
|
+
|
|
7
|
+
.. autosummary::
|
|
8
|
+
:toctree: generated/
|
|
9
|
+
|
|
10
|
+
_check_and_prepare_namelist
|
|
11
|
+
PALMRun
|
|
12
|
+
palmrun
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from os.path import exists
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
from wrfrun.core import WRFRUN, ExecutableBase, ExecutableDB
|
|
19
|
+
from wrfrun.log import logger
|
|
20
|
+
from wrfrun.workspace.palm import get_palm_workspace_path
|
|
21
|
+
|
|
22
|
+
from ..constants import NamelistName
|
|
23
|
+
from .namelist import prepare_palm_namelist
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _check_and_prepare_namelist():
|
|
27
|
+
"""
|
|
28
|
+
Check if namelist of ``PALM`` has been loaded.
|
|
29
|
+
If not, call :func:`prepare_palm_namelist <wrfrun.model.palm.namelist.prepare_palm_namelist>` to load it.
|
|
30
|
+
"""
|
|
31
|
+
if not WRFRUN.config.check_namelist("palm"):
|
|
32
|
+
prepare_palm_namelist()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class PALMRun(ExecutableBase):
|
|
36
|
+
"""
|
|
37
|
+
``Executable`` for bash script "palmrun".
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(self, config_id: str = "default", core_num: Optional[int] = None):
|
|
41
|
+
"""
|
|
42
|
+
``Executable`` for bash script "palmrun".
|
|
43
|
+
|
|
44
|
+
:param config_id: Configuration identifier of ``PALM``, defaults to "default"
|
|
45
|
+
:type config_id: str, optional
|
|
46
|
+
:param core_num: CPU cores to use, defaults to None
|
|
47
|
+
:type core_num: Optional[int], optional
|
|
48
|
+
"""
|
|
49
|
+
if isinstance(core_num, int) and core_num <= 0:
|
|
50
|
+
logger.warning("`core_num` should be greater than 0")
|
|
51
|
+
core_num = None
|
|
52
|
+
|
|
53
|
+
mpi_use = False
|
|
54
|
+
mpi_cmd = None
|
|
55
|
+
mpi_core_num = None
|
|
56
|
+
|
|
57
|
+
cmd = f"./palmrun -r wrfrun -c {config_id} -a d3# -X {core_num} -v"
|
|
58
|
+
|
|
59
|
+
super().__init__("palmrun", cmd, get_palm_workspace_path(), mpi_use, mpi_cmd, mpi_core_num)
|
|
60
|
+
|
|
61
|
+
_check_and_prepare_namelist()
|
|
62
|
+
|
|
63
|
+
def generate_custom_config(self):
|
|
64
|
+
"""
|
|
65
|
+
Store custom configs, including:
|
|
66
|
+
|
|
67
|
+
* Namelist settings.
|
|
68
|
+
"""
|
|
69
|
+
self.custom_config.update({"namelist": WRFRUN.config.get_namelist("palm")})
|
|
70
|
+
|
|
71
|
+
def load_custom_config(self):
|
|
72
|
+
"""
|
|
73
|
+
Load custom configs, including:
|
|
74
|
+
|
|
75
|
+
* Namelist settings.
|
|
76
|
+
"""
|
|
77
|
+
WRFRUN.config.update_namelist(self.custom_config["namelist"], "palm")
|
|
78
|
+
|
|
79
|
+
def before_exec(self):
|
|
80
|
+
WRFRUN.config.check_wrfrun_context(True)
|
|
81
|
+
WRFRUN.config.WRFRUN_WORK_STATUS = "palm"
|
|
82
|
+
|
|
83
|
+
config = WRFRUN.config.get_model_config("palm")
|
|
84
|
+
|
|
85
|
+
if not WRFRUN.config.IS_IN_REPLAY:
|
|
86
|
+
# check if user provides topography files
|
|
87
|
+
if exists(config["topography_file"]):
|
|
88
|
+
self.add_input_files(
|
|
89
|
+
{
|
|
90
|
+
"file_path": config["topography_file"],
|
|
91
|
+
"save_path": get_palm_workspace_path("input"),
|
|
92
|
+
"save_name": "palmrun.topo",
|
|
93
|
+
"is_data": True,
|
|
94
|
+
"is_output": False,
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
super().before_exec()
|
|
99
|
+
|
|
100
|
+
WRFRUN.config.write_namelist(f"{get_palm_workspace_path('input')}/{NamelistName.PALM}", "palm")
|
|
101
|
+
|
|
102
|
+
# print debug logs
|
|
103
|
+
logger.debug("Namelist settings of 'palmrun':")
|
|
104
|
+
logger.debug(WRFRUN.config.get_namelist("palm"))
|
|
105
|
+
|
|
106
|
+
def after_exec(self):
|
|
107
|
+
if not WRFRUN.config.IS_IN_REPLAY:
|
|
108
|
+
self.add_output_files(
|
|
109
|
+
output_dir=get_palm_workspace_path("output"), save_path=self._output_save_path, startswith="wrfrun_"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
super().after_exec()
|
|
113
|
+
|
|
114
|
+
logger.info(f"All PALM output files have been copied to {WRFRUN.config.parse_resource_uri(self._output_save_path)}")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def palmrun():
|
|
118
|
+
"""
|
|
119
|
+
Function interface for :class:`PALMRun`.
|
|
120
|
+
|
|
121
|
+
Parameters needed to initialize :class:`PALMRun` is read from global variable :doc:`WRFRUN </api/core.core>`.
|
|
122
|
+
"""
|
|
123
|
+
config = WRFRUN.config.get_model_config("palm")
|
|
124
|
+
PALMRun(config["config_identifier"], WRFRUN.config.get_core_num())()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _exec_register_func(exec_db: ExecutableDB):
|
|
128
|
+
"""
|
|
129
|
+
Function to register ``Executable``.
|
|
130
|
+
|
|
131
|
+
:param exec_db: ``ExecutableDB`` instance.
|
|
132
|
+
:type exec_db: ExecutableDB
|
|
133
|
+
"""
|
|
134
|
+
class_list = [PALMRun]
|
|
135
|
+
class_id_list = ["palmrun"]
|
|
136
|
+
|
|
137
|
+
for _class, _id in zip(class_list, class_id_list):
|
|
138
|
+
if not exec_db.is_registered(_id):
|
|
139
|
+
exec_db.register_exec(_id, _class)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
WRFRUN.set_exec_db_register_func(_exec_register_func)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
__all__ = ["PALMRun", "palmrun"]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.model.palm.namelist
|
|
3
|
+
##########################
|
|
4
|
+
|
|
5
|
+
Functions to process namelist for ``PALM``.
|
|
6
|
+
|
|
7
|
+
.. autosummary::
|
|
8
|
+
:toctree: generated/
|
|
9
|
+
|
|
10
|
+
prepare_palm_namelist
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from os.path import exists
|
|
14
|
+
|
|
15
|
+
from wrfrun.core import WRFRUN
|
|
16
|
+
from wrfrun.log import logger
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def prepare_palm_namelist():
|
|
20
|
+
"""
|
|
21
|
+
This function loads user PALM namelist file and save it in :doc:`WRFRUN </api/core.core>`.
|
|
22
|
+
"""
|
|
23
|
+
palm_config = WRFRUN.config.get_model_config("palm")
|
|
24
|
+
namelist_file = palm_config["user_namelist"]
|
|
25
|
+
|
|
26
|
+
if not exists(namelist_file):
|
|
27
|
+
logger.error(f"Can't find PALM namelist: {namelist_file}")
|
|
28
|
+
raise FileNotFoundError(f"Can't find PALM namelist: {namelist_file}")
|
|
29
|
+
|
|
30
|
+
WRFRUN.config.read_namelist(namelist_file, "palm")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
__all__ = ["prepare_palm_namelist"]
|