wrfrun 0.1.8__py3-none-any.whl → 0.2.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.
Files changed (53) hide show
  1. wrfrun/cli.py +131 -0
  2. wrfrun/core/base.py +52 -19
  3. wrfrun/core/config.py +257 -170
  4. wrfrun/core/error.py +8 -1
  5. wrfrun/core/replay.py +1 -1
  6. wrfrun/core/server.py +91 -71
  7. wrfrun/data.py +14 -16
  8. wrfrun/extension/goos_sst/__init__.py +5 -5
  9. wrfrun/extension/goos_sst/core.py +4 -1
  10. wrfrun/extension/goos_sst/res/Vtable.ERA_GOOS_SST +1 -1
  11. wrfrun/extension/goos_sst/res/__init__.py +17 -0
  12. wrfrun/extension/goos_sst/utils.py +21 -5
  13. wrfrun/extension/littler/__init__.py +57 -1
  14. wrfrun/extension/littler/{utils.py → core.py} +329 -43
  15. wrfrun/extension/utils.py +24 -22
  16. wrfrun/model/__init__.py +24 -1
  17. wrfrun/model/plot.py +259 -36
  18. wrfrun/model/utils.py +19 -9
  19. wrfrun/model/wrf/__init__.py +41 -0
  20. wrfrun/model/wrf/core.py +229 -101
  21. wrfrun/model/wrf/exec_wrap.py +49 -35
  22. wrfrun/model/wrf/geodata.py +2 -1
  23. wrfrun/model/wrf/namelist.py +78 -4
  24. wrfrun/model/wrf/{_metgrid.py → utils.py} +38 -3
  25. wrfrun/model/wrf/vtable.py +9 -5
  26. wrfrun/res/__init__.py +22 -7
  27. wrfrun/res/config/config.template.toml +57 -0
  28. wrfrun/res/{config.toml.template → config/wrf.template.toml} +7 -46
  29. wrfrun/res/run.template.sh +10 -0
  30. wrfrun/res/scheduler/lsf.template +5 -0
  31. wrfrun/res/{job_scheduler → scheduler}/pbs.template +1 -1
  32. wrfrun/res/{job_scheduler → scheduler}/slurm.template +2 -1
  33. wrfrun/run.py +39 -27
  34. wrfrun/scheduler/__init__.py +35 -0
  35. wrfrun/scheduler/env.py +44 -0
  36. wrfrun/scheduler/lsf.py +49 -0
  37. wrfrun/scheduler/pbs.py +50 -0
  38. wrfrun/scheduler/script.py +72 -0
  39. wrfrun/scheduler/slurm.py +50 -0
  40. wrfrun/scheduler/utils.py +14 -0
  41. wrfrun/utils.py +8 -3
  42. wrfrun/workspace/__init__.py +38 -0
  43. wrfrun/workspace/core.py +94 -0
  44. wrfrun/workspace/wrf.py +165 -0
  45. {wrfrun-0.1.8.dist-info → wrfrun-0.2.0.dist-info}/METADATA +3 -2
  46. wrfrun-0.2.0.dist-info/RECORD +62 -0
  47. wrfrun-0.2.0.dist-info/entry_points.txt +3 -0
  48. wrfrun/model/wrf/_ndown.py +0 -39
  49. wrfrun/pbs.py +0 -86
  50. wrfrun/res/run.sh.template +0 -16
  51. wrfrun/workspace.py +0 -88
  52. wrfrun-0.1.8.dist-info/RECORD +0 -51
  53. {wrfrun-0.1.8.dist-info → wrfrun-0.2.0.dist-info}/WHEEL +0 -0
wrfrun/run.py CHANGED
@@ -4,15 +4,15 @@
4
4
 
5
5
  import sys
6
6
  import threading
7
- from os.path import abspath, dirname, exists
7
+ from os.path import abspath, dirname
8
8
  from typing import Optional, Tuple, Union
9
9
 
10
- from .core import ExecConfigRecorder, WRFRUNConfig, WRFRunBasicError, WRFRunServer, WRFRunServerHandler, replay_config_generator, stop_server
10
+ from .core import ExecConfigRecorder, WRFRUNConfig, init_wrfrun_config, WRFRunBasicError, WRFRunServer, WRFRunServerHandler, replay_config_generator, stop_server
11
11
  from .data import prepare_wps_input_data
12
- from .model import clear_model_logs, plot_domain_area
13
- from .pbs import in_pbs, prepare_pbs_script
12
+ from .model import clear_model_logs, generate_domain_area
13
+ from .scheduler import in_job_scheduler, prepare_scheduler_script
14
14
  from .utils import call_subprocess, logger, logger_add_file_handler
15
- from .workspace import prepare_workspace
15
+ from .workspace import prepare_workspace, check_workspace
16
16
 
17
17
 
18
18
  def confirm_model_area():
@@ -20,9 +20,9 @@ def confirm_model_area():
20
20
  Ask user to check domain area.
21
21
 
22
22
  """
23
- plot_domain_area()
23
+ generate_domain_area()
24
24
 
25
- if not in_pbs():
25
+ if not in_job_scheduler():
26
26
  # ask user
27
27
  logger.warning(f"Check the domain image, is it right?")
28
28
  answer = input("Is it right? [y/N]: ")
@@ -41,16 +41,29 @@ class WRFRun:
41
41
  _instance = None
42
42
  _initialized = False
43
43
 
44
- def __init__(self, config_file: str, init_workspace=True, start_server=False, pbs_mode=False, prepare_wps_data=False, wps_data_area: Optional[Tuple[int, int, int, int]] = None):
44
+ def __init__(
45
+ self, config_file: str, init_workspace=True,
46
+ start_server=False, submit_job=False, prepare_wps_data=False,
47
+ wps_data_area: Optional[Tuple[int, int, int, int]] = None,
48
+ skip_domain_confirm=False
49
+ ):
45
50
  """
46
51
  WRFRun, a context class to achieve some goals before and after running WRF, like save a copy of config file, start and close WRFRunServer.
47
52
 
48
53
  :param config_file: ``wrfrun`` config file's path.
54
+ :type config_file: str
49
55
  :param init_workspace: If True, clean old files in workspace and re-create it.
56
+ :type init_workspace: bool
50
57
  :param start_server: Whether to start WRFRunServer, defaults to True.
51
- :param pbs_mode: If commit this task to the PBS system, defaults to True.
58
+ :type start_server: bool
59
+ :param submit_job: If commit this task to the PBS system, defaults to True.
60
+ :type submit_job: bool
52
61
  :param prepare_wps_data: If True, download input datas for WPS first.
62
+ :type prepare_wps_data: bool
53
63
  :param wps_data_area: If ``prepare_wps_data==True``, you need to give the area range of input data so download function can download data from ERA5.
64
+ :type wps_data_area: tuple
65
+ :param skip_domain_confirm: If ``True``, skip domain confirm.
66
+ :type skip_domain_confirm: bool
54
67
  :return:
55
68
  """
56
69
  if self._initialized:
@@ -63,17 +76,18 @@ class WRFRun:
63
76
  self._ip = ""
64
77
  self._port = -1
65
78
 
66
- self._pbs_mode = pbs_mode
79
+ self._submit_job = submit_job
67
80
  self._init_workspace = init_workspace
68
81
  self._prepare_wps_data = prepare_wps_data
69
82
  self._wps_data_area = wps_data_area
83
+ self._skip_domain_confirm = skip_domain_confirm
70
84
  self._entry_file_path = abspath(sys.argv[0])
71
85
  self._entry_file_dir_path = dirname(self._entry_file_path)
72
86
  self._replay_configs = None
73
87
 
74
88
  # make sure we can read the config file, because sometimes the user may run the Python script in a different path.
75
89
  abs_config_path = f"{self._entry_file_dir_path}/{config_file}"
76
- WRFRUNConfig.load_wrfrun_config(abs_config_path)
90
+ init_wrfrun_config(abs_config_path)
77
91
 
78
92
  self._record_output_path = None
79
93
  self._record_include_data = False
@@ -89,35 +103,33 @@ class WRFRun:
89
103
 
90
104
  def __enter__(self):
91
105
  # check workspace
92
- check_list = [WRFRUNConfig.WPS_WORK_PATH, WRFRUNConfig.WRF_WORK_PATH, WRFRUNConfig.WRFDA_WORK_PATH]
93
- check_list = [WRFRUNConfig.parse_resource_uri(x) for x in check_list]
94
- for _path in check_list:
95
- if not exists(_path) and not self._init_workspace:
96
- logger.info(f"Force re-create workspace because it is broken.")
97
- self._init_workspace = True
98
- break
106
+ if not check_workspace():
107
+ logger.info(f"Force re-create workspace because it is broken.")
108
+ self._init_workspace = True
99
109
 
100
110
  # here is the condition we need to initialize workspace:
101
- # 1. pbs_mode = True and init_workspace = True, do prepare_workspace before committing the task to the PBS system.
102
- # 2. pbs_mode = False and init_workspace = True, do prepare_workspace.
103
- if self._pbs_mode and not in_pbs():
111
+ # 1. submit_job = True and init_workspace = True, do prepare_workspace before submitting the task to job scheduler.
112
+ # 2. submit_job = False and init_workspace = True, do prepare_workspace.
113
+ if self._submit_job and not in_job_scheduler():
104
114
  if self._init_workspace:
105
115
  prepare_workspace()
106
116
 
107
117
  # ask user before commit the task
108
- confirm_model_area()
118
+ if not self._skip_domain_confirm:
119
+ confirm_model_area()
109
120
 
110
- prepare_pbs_script(self._entry_file_path)
121
+ prepare_scheduler_script(self._entry_file_path)
111
122
 
112
123
  call_subprocess(["qsub", f"{self._entry_file_dir_path}/run.sh"])
113
124
  logger.info(f"Work has been submit to PBS system")
114
125
  exit(0)
115
126
 
116
- elif not self._pbs_mode:
127
+ elif not self._submit_job:
117
128
  if self._init_workspace:
118
129
  prepare_workspace()
119
130
 
120
- confirm_model_area()
131
+ if not self._skip_domain_confirm:
132
+ confirm_model_area()
121
133
 
122
134
  # save a copy of config to the output path
123
135
  WRFRUNConfig.save_wrfrun_config(f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/config.toml")
@@ -139,7 +151,7 @@ class WRFRun:
139
151
  else:
140
152
  prepare_wps_input_data(self._wps_data_area)
141
153
 
142
- logger.info(r"Enter wrfrun context")
154
+ logger.debug(r"Enter wrfrun context")
143
155
 
144
156
  return self
145
157
 
@@ -157,7 +169,7 @@ class WRFRun:
157
169
 
158
170
  clear_model_logs()
159
171
 
160
- logger.info(r"Exit wrfrun context")
172
+ logger.debug(r"Exit wrfrun context")
161
173
 
162
174
  def _start_wrfrun_server(self):
163
175
  """
@@ -0,0 +1,35 @@
1
+ """
2
+ wrfrun.scheduler
3
+ ################
4
+
5
+ ``wrfrun`` provides functions to help users take care of the job scheduler.
6
+
7
+ Submodules
8
+ **********
9
+
10
+ ======================================= ===========================================================
11
+ :doc:`env </api/scheduler.env>` Functions to manage environment variables in job scheduler.
12
+ :doc:`lsf </api/scheduler.lsf>` Scheduler interface for LSF job scheduler.
13
+ :doc:`pbs </api/scheduler.pbs>` Scheduler interface for PBS job scheduler.
14
+ :doc:`script </api/scheduler.script>` Generate shell scripts for job scheduler.
15
+ :doc:`slurm </api/scheduler.slurm>` Scheduler interface for Slurm job scheduler.
16
+ :doc:`utils </api/scheduler.utils>` Utility functions.
17
+ ======================================= ===========================================================
18
+
19
+ .. toctree::
20
+ :maxdepth: 1
21
+ :hidden:
22
+
23
+ env <scheduler.env>
24
+ lsf <scheduler.lsf>
25
+ pbs <scheduler.pbs>
26
+ slurm <scheduler.slurm>
27
+ utils <scheduler.utils>
28
+ """
29
+
30
+ from .env import *
31
+ from .lsf import *
32
+ from .pbs import *
33
+ from .script import *
34
+ from .slurm import *
35
+ from .utils import *
@@ -0,0 +1,44 @@
1
+ """
2
+ wrfrun.scheduler.env
3
+ ####################
4
+
5
+ Functions to manage environment variables in job scheduler.
6
+
7
+ .. autosummary::
8
+ :toctree: generated/
9
+
10
+ in_job_scheduler
11
+
12
+ How Does wrfrun Check If It Is In A Job Scheduler?
13
+ **************************************************
14
+
15
+ If you submit your task through ``wrfrun``, that is,
16
+ set ``submit_job = True`` in :class:`WRFRun <wrfrun.run.WRFRun>`,
17
+ an environment variable called ``WRFRUN_ENV_JOB_SCHEDULER`` will be set.
18
+ ``wrfrun`` will determine if it is in a job scheduler by checking if ``WRFRUN_ENV_JOB_SCHEDULER`` appears in environment.
19
+
20
+ If you submit your task by your own,
21
+ it is recommended that add ``WRFRUN_ENV_JOB_SCHEDULER`` to the environment,
22
+ which can ensure ``wrfrun`` works properly in the job scheduler.
23
+ """
24
+
25
+ from os import environ
26
+
27
+
28
+ def in_job_scheduler() -> bool:
29
+ """
30
+ Check if ``wrfrun`` runs in a job scheduler task.
31
+
32
+ This function checks the environment variable ``WRFRUN_ENV_JOB_SCHEDULER``
33
+ to determine if ``wrfrun`` is running in a job scheduler task.
34
+
35
+ :return: ``True`` if in a job scheduler task, else ``False``.
36
+ :rtype: bool
37
+ """
38
+ if "WRFRUN_ENV_JOB_SCHEDULER" in environ:
39
+ return True
40
+ else:
41
+ return False
42
+
43
+
44
+ __all__ = ["in_job_scheduler"]
@@ -0,0 +1,49 @@
1
+ """
2
+ wrfrun.scheduler.lsf
3
+ ####################
4
+
5
+ Scheduler interface for LSF system.
6
+
7
+ .. autosummary::
8
+ :toctree: generated/
9
+
10
+ lsf_generate_settings
11
+ """
12
+
13
+ from wrfrun.core import get_wrfrun_config
14
+ from wrfrun.res import SCHEDULER_LSF_TEMPLATE
15
+ from .utils import get_core_num
16
+
17
+
18
+ def lsf_generate_settings(scheduler_config: dict) -> str:
19
+ """
20
+ This function generate bash settings for LSF job scheduler.
21
+
22
+ :return: Generated settings.
23
+ :rtype: str
24
+ """
25
+ WRFRUNConfig = get_wrfrun_config()
26
+
27
+ # get log path and job scheduler config
28
+ log_path = WRFRUNConfig.get_log_path()
29
+
30
+ # get scheduler configs
31
+ stdout_log_path = f"{log_path}/lsf.log"
32
+ stderr_log_path = f"{log_path}/lsf.err"
33
+ node_num = scheduler_config["node_num"]
34
+ queue_name = scheduler_config["queue_name"]
35
+ core_num = get_core_num()
36
+
37
+ template_path = WRFRUNConfig.parse_resource_uri(SCHEDULER_LSF_TEMPLATE)
38
+ with open(template_path, "r") as f:
39
+ template = f.read()
40
+
41
+ return template.format(
42
+ STDOUT_LOG_PATH=stdout_log_path,
43
+ STDERR_LOG_PATH=stderr_log_path,
44
+ CORE_NUM=core_num * node_num,
45
+ QUEUE_NAME=queue_name,
46
+ )
47
+
48
+
49
+ __all__ = ["lsf_generate_settings"]
@@ -0,0 +1,50 @@
1
+ """
2
+ wrfrun.scheduler.pbs
3
+ ####################
4
+
5
+ Scheduler interface for PBS system.
6
+
7
+ .. autosummary::
8
+ :toctree: generated/
9
+
10
+ pbs_generate_settings
11
+ """
12
+
13
+ from wrfrun.core import get_wrfrun_config
14
+ from wrfrun.res import SCHEDULER_PBS_TEMPLATE
15
+ from .utils import get_core_num
16
+
17
+
18
+ def pbs_generate_settings(scheduler_config: dict) -> str:
19
+ """
20
+ This function generate bash settings for PBS job scheduler.
21
+
22
+ :return: Generated settings.
23
+ :rtype: str
24
+ """
25
+ WRFRUNConfig = get_wrfrun_config()
26
+
27
+ # get log path and job scheduler config
28
+ log_path = WRFRUNConfig.get_log_path()
29
+
30
+ # get scheduler configs
31
+ stdout_log_path = f"{log_path}/pbs.log"
32
+ stderr_log_path = f"{log_path}/pbs.err"
33
+ node_num = scheduler_config["node_num"]
34
+ queue_name = scheduler_config["queue_name"]
35
+ core_num = get_core_num()
36
+
37
+ template_path = WRFRUNConfig.parse_resource_uri(SCHEDULER_PBS_TEMPLATE)
38
+ with open(template_path, "r") as f:
39
+ template = f.read()
40
+
41
+ return template.format(
42
+ STDOUT_LOG_PATH=stdout_log_path,
43
+ STDERR_LOG_PATH=stderr_log_path,
44
+ NODE_NUM=node_num,
45
+ CORE_NUM=core_num,
46
+ QUEUE_NAME=queue_name,
47
+ )
48
+
49
+
50
+ __all__ = ["pbs_generate_settings"]
@@ -0,0 +1,72 @@
1
+ from os.path import abspath, dirname, exists
2
+
3
+ from wrfrun import get_wrfrun_config
4
+ from wrfrun.res import RUN_SH_TEMPLATE
5
+ from wrfrun.utils import logger
6
+ from .lsf import lsf_generate_settings
7
+ from .pbs import pbs_generate_settings
8
+ from .slurm import slurm_generate_settings
9
+
10
+
11
+ def prepare_scheduler_script(main_file_path: str):
12
+ """
13
+ Prepare the bash script to be submitted to job scheduler.
14
+
15
+ :param main_file_path: Path of the main entry file.
16
+ :type main_file_path: str
17
+ """
18
+ WRFRUNConfig = get_wrfrun_config()
19
+
20
+ # check main file path
21
+ if not exists(main_file_path):
22
+ logger.error(f"Wrong path of main entry file: {main_file_path}")
23
+ raise FileNotFoundError(f"Wrong path of main entry file: {main_file_path}")
24
+
25
+ # get absolute path of main entry file's parent directory
26
+ dir_path = abspath(dirname(main_file_path))
27
+
28
+ scheduler_configs = WRFRUNConfig.get_job_scheduler_config()
29
+
30
+ # generate scheduler settings
31
+ match scheduler_configs["job_scheduler"]:
32
+ case "lsf":
33
+ scheduler_settings = lsf_generate_settings(scheduler_configs)
34
+
35
+ case "pbs":
36
+ scheduler_settings = pbs_generate_settings(scheduler_configs)
37
+
38
+ case "slurm":
39
+ scheduler_settings = slurm_generate_settings(scheduler_configs)
40
+
41
+ case _:
42
+ logger.error(f"Unknown scheduler name: {scheduler_configs['job_scheduler']}")
43
+ raise ValueError(f"Unknown scheduler name: {scheduler_configs['job_scheduler']}")
44
+
45
+ # generate environment settings
46
+ env_settings = 'export WRFRUN_ENV_JOB_SCHEDULER=1\n'
47
+ if len(scheduler_configs["env_settings"]) > 0:
48
+ for key in scheduler_configs["env_settings"]:
49
+ env_settings += f"export {key}={scheduler_configs['env_settings'][key]}\n"
50
+
51
+ # generate command
52
+ exec_cmd = f"{scheduler_configs['python_interpreter']} {main_file_path}"
53
+
54
+ # generate shell script
55
+ shell_template_path = WRFRUNConfig.parse_resource_uri(RUN_SH_TEMPLATE)
56
+ with open(f"{dir_path}/run.sh", "w") as f:
57
+
58
+ with open(shell_template_path, "r") as f_template:
59
+ template = f_template.read()
60
+
61
+ template = template.format(
62
+ SCHEDULER_SETTINGS=scheduler_settings,
63
+ ENV_SETTINGS=env_settings,
64
+ WORK_COMMAND=exec_cmd,
65
+ )
66
+
67
+ f.write(template)
68
+
69
+ logger.info(f"Job scheduler script written to {dir_path}/run.sh")
70
+
71
+
72
+ __all__ = ["prepare_scheduler_script"]
@@ -0,0 +1,50 @@
1
+ """
2
+ wrfrun.scheduler.slurm
3
+ ######################
4
+
5
+ Scheduler interface for Slurm system.
6
+
7
+ .. autosummary::
8
+ :toctree: generated/
9
+
10
+ slurm_generate_settings
11
+ """
12
+
13
+ from wrfrun.core import get_wrfrun_config
14
+ from wrfrun.res import SCHEDULER_SLURM_TEMPLATE
15
+ from .utils import get_core_num
16
+
17
+
18
+ def slurm_generate_settings(scheduler_config: dict) -> str:
19
+ """
20
+ This function generate bash settings for Slurm job scheduler.
21
+
22
+ :return: Generated settings.
23
+ :rtype: str
24
+ """
25
+ WRFRUNConfig = get_wrfrun_config()
26
+
27
+ # get log path and job scheduler config
28
+ log_path = WRFRUNConfig.get_log_path()
29
+
30
+ # get scheduler configs
31
+ stdout_log_path = f"{log_path}/slurm.log"
32
+ stderr_log_path = f"{log_path}/slurm.err"
33
+ node_num = scheduler_config["node_num"]
34
+ queue_name = scheduler_config["queue_name"]
35
+ core_num = get_core_num()
36
+
37
+ template_path = WRFRUNConfig.parse_resource_uri(SCHEDULER_SLURM_TEMPLATE)
38
+ with open(template_path, "r") as f:
39
+ template = f.read()
40
+
41
+ return template.format(
42
+ STDOUT_LOG_PATH=stdout_log_path,
43
+ STDERR_LOG_PATH=stderr_log_path,
44
+ CORE_NUM=core_num,
45
+ NODE_NUM=node_num,
46
+ QUEUE_NAME=queue_name,
47
+ )
48
+
49
+
50
+ __all__ = ["slurm_generate_settings"]
@@ -0,0 +1,14 @@
1
+ from wrfrun.core import get_wrfrun_config
2
+
3
+
4
+ def get_core_num() -> int:
5
+ """
6
+ Get core number.
7
+
8
+ :return: Core number.
9
+ :rtype: int
10
+ """
11
+ return get_wrfrun_config()["core_num"]
12
+
13
+
14
+ __all__ = ["get_core_num"]
wrfrun/utils.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import subprocess
3
3
  from datetime import datetime
4
- from os import chdir, getcwd, makedirs
4
+ from os import chdir, getcwd, makedirs, environ
5
5
  from os.path import exists
6
6
  from shutil import rmtree
7
7
  from time import time
@@ -45,7 +45,12 @@ def set_logger(logger_list: List[str], logger_level: Optional[Dict] = None):
45
45
 
46
46
  # init wrfrun logger
47
47
  logger = logging.getLogger("wrfrun")
48
- set_logger(["wrfrun", ], {"wrfrun": logging.DEBUG})
48
+ # check environment variables and set logger level
49
+ if "WRFRUN_DEBUG_MODE" in environ and environ["WRFRUN_DEBUG_MODE"]:
50
+ _logger_level = logging.DEBUG
51
+ else:
52
+ _logger_level = logging.INFO
53
+ set_logger(["wrfrun", ], {"wrfrun": _logger_level})
49
54
 
50
55
 
51
56
  def unify_logger_format():
@@ -218,7 +223,7 @@ def check_subprocess_status(status: subprocess.CompletedProcess):
218
223
  logger.error(f"====== ====== ======")
219
224
 
220
225
  # raise error
221
- raise RuntimeError
226
+ raise RuntimeError(f"Failed to exec command: '{command}'. Please check the log above.")
222
227
 
223
228
 
224
229
  def call_subprocess(command: list[str], work_path: Optional[str] = None, print_output=False):
@@ -0,0 +1,38 @@
1
+ """
2
+ wrfrun.workspace
3
+ ################
4
+
5
+ Prepare ``workspace`` for ``wrfrun`` and numerical models.
6
+
7
+ Submodules
8
+ **********
9
+
10
+ ================================= ===========================================================
11
+ :doc:`core </api/workspace.core>` Core functions of this submodule.
12
+ :doc:`wrf </api/workspace.wrf>` Functions to prepare workspace for WPS/WRF model.
13
+ ================================= ===========================================================
14
+
15
+ Workspace
16
+ *********
17
+
18
+ ``workspace`` is a collection of several directories where ``wrfrun``, extensions and numerical model works.
19
+ These directories and their purpose are listed below.
20
+
21
+ =================================== ===========================================================
22
+ Director Path Purpose
23
+ =================================== ===========================================================
24
+ ``/tmp/wrfrun`` Store temporary files.
25
+ ``$HOME/.config/wrfrun`` Main work directory.
26
+ ``$HOME/.config/wrfrun/replay`` Work directory for :doc:`replay <wrfrun.core.replay>`.
27
+ ``$HOME/.config/wrfrun/model`` Work directory for numerical models.
28
+ =================================== ===========================================================
29
+
30
+ .. toctree::
31
+ :maxdepth: 1
32
+ :hidden:
33
+
34
+ core <workspace.core>
35
+ wrf <workspace.wrf>
36
+ """
37
+
38
+ from .core import *
@@ -0,0 +1,94 @@
1
+ """
2
+ wrfrun.workspace.core
3
+ #####################
4
+
5
+ Core functions to prepare ``wrfrun`` workspace.
6
+
7
+ .. autosummary::
8
+ :toctree: generated/
9
+
10
+ prepare_workspace
11
+ """
12
+
13
+ from os.path import exists
14
+ from shutil import rmtree
15
+
16
+ from wrfrun.core import get_wrfrun_config
17
+ from wrfrun.utils import check_path, logger
18
+ from .wrf import check_wrf_workspace, prepare_wrf_workspace
19
+
20
+
21
+ def prepare_workspace():
22
+ """
23
+ Initialize ``wrfrun`` workspace.
24
+
25
+ This function will check following paths,
26
+ and create them if them don't exist:
27
+
28
+ 1. ``/tmp/wrfrun``
29
+ 2. ``$HOME/.config/wrfrun``
30
+ 3. ``$HOME/.config/wrfrun/replay``
31
+ 4. ``$HOME/.config/wrfrun/model``
32
+
33
+ It will call other responding functions to initialize workspace for numerical models:
34
+
35
+ 1. :doc:`WPS/WRF model </api/workspace.wrf>`
36
+ """
37
+ WRFRUNConfig = get_wrfrun_config()
38
+ logger.info(f"Initialize main workspace.")
39
+
40
+ wrfrun_temp_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_TEMP_PATH)
41
+ workspace_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_ROOT)
42
+ replay_work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_REPLAY)
43
+ output_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_OUTPUT_PATH)
44
+
45
+ if exists(workspace_path):
46
+ logger.info(f"Remove old files in workspace.")
47
+ rmtree(workspace_path)
48
+
49
+ # check folder
50
+ check_path(wrfrun_temp_path)
51
+ check_path(replay_work_path)
52
+ check_path(output_path)
53
+
54
+ func_map = {
55
+ "wrf": prepare_wrf_workspace
56
+ }
57
+ model_configs = WRFRUNConfig["model"]
58
+
59
+ for model_name in model_configs:
60
+ func_map[model_name](model_configs[model_name])
61
+
62
+
63
+ def check_workspace() -> bool:
64
+ """
65
+ Check if workspace exists.
66
+
67
+ :return: ``True`` if workspace exists, ``False`` otherwise.
68
+ :rtype: bool
69
+ """
70
+ WRFRUNConfig = get_wrfrun_config()
71
+
72
+ wrfrun_temp_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_TEMP_PATH)
73
+ workspace_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_ROOT)
74
+ replay_work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_REPLAY)
75
+ output_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_OUTPUT_PATH)
76
+
77
+ flag = True
78
+ flag = flag & exists(wrfrun_temp_path) & exists(replay_work_path) & exists(output_path) & exists(workspace_path)
79
+
80
+ func_map = {
81
+ "wrf": check_wrf_workspace
82
+ }
83
+ model_configs = WRFRUNConfig["model"]
84
+
85
+ for model_name in model_configs:
86
+ if model_name == "debug_level":
87
+ continue
88
+
89
+ flag = flag & func_map[model_name](model_configs[model_name])
90
+
91
+ return True
92
+
93
+
94
+ __all__ = ["prepare_workspace", "check_workspace"]