wrfrun 0.1.7__py3-none-any.whl → 0.1.9__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/cli.py +128 -0
- wrfrun/core/__init__.py +33 -0
- wrfrun/core/base.py +246 -75
- wrfrun/core/config.py +286 -236
- wrfrun/core/error.py +47 -17
- wrfrun/core/replay.py +65 -32
- wrfrun/core/server.py +139 -79
- wrfrun/data.py +10 -5
- wrfrun/extension/__init__.py +28 -0
- wrfrun/extension/goos_sst/__init__.py +67 -0
- wrfrun/extension/goos_sst/core.py +111 -0
- wrfrun/extension/goos_sst/res/Vtable.ERA_GOOS_SST +7 -0
- wrfrun/extension/goos_sst/res/__init__.py +26 -0
- wrfrun/extension/goos_sst/utils.py +97 -0
- wrfrun/extension/littler/__init__.py +57 -1
- wrfrun/extension/littler/{utils.py → core.py} +326 -40
- wrfrun/extension/utils.py +22 -21
- wrfrun/model/__init__.py +24 -1
- wrfrun/model/plot.py +253 -35
- wrfrun/model/utils.py +17 -8
- wrfrun/model/wrf/__init__.py +41 -0
- wrfrun/model/wrf/core.py +218 -102
- wrfrun/model/wrf/exec_wrap.py +49 -35
- wrfrun/model/wrf/namelist.py +82 -11
- wrfrun/model/wrf/scheme.py +85 -1
- wrfrun/model/wrf/{_metgrid.py → utils.py} +36 -2
- wrfrun/model/wrf/vtable.py +2 -1
- wrfrun/plot/wps.py +66 -58
- wrfrun/res/__init__.py +8 -5
- wrfrun/res/config/config.template.toml +50 -0
- wrfrun/res/{config.toml.template → config/wrf.template.toml} +10 -47
- wrfrun/res/run.template.sh +10 -0
- wrfrun/res/scheduler/lsf.template +5 -0
- wrfrun/res/{job_scheduler → scheduler}/pbs.template +1 -1
- wrfrun/res/{job_scheduler → scheduler}/slurm.template +2 -1
- wrfrun/run.py +19 -23
- wrfrun/scheduler/__init__.py +35 -0
- wrfrun/scheduler/env.py +44 -0
- wrfrun/scheduler/lsf.py +47 -0
- wrfrun/scheduler/pbs.py +48 -0
- wrfrun/scheduler/script.py +70 -0
- wrfrun/scheduler/slurm.py +48 -0
- wrfrun/scheduler/utils.py +14 -0
- wrfrun/utils.py +8 -3
- wrfrun/workspace/__init__.py +38 -0
- wrfrun/workspace/core.py +92 -0
- wrfrun/workspace/wrf.py +121 -0
- {wrfrun-0.1.7.dist-info → wrfrun-0.1.9.dist-info}/METADATA +4 -3
- wrfrun-0.1.9.dist-info/RECORD +62 -0
- wrfrun-0.1.9.dist-info/entry_points.txt +3 -0
- wrfrun/model/wrf/_ndown.py +0 -39
- wrfrun/pbs.py +0 -86
- wrfrun/res/run.sh.template +0 -16
- wrfrun/workspace.py +0 -88
- wrfrun-0.1.7.dist-info/RECORD +0 -46
- {wrfrun-0.1.7.dist-info → wrfrun-0.1.9.dist-info}/WHEEL +0 -0
wrfrun/core/base.py
CHANGED
|
@@ -1,4 +1,49 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wrfrun.core.base
|
|
3
|
+
################
|
|
4
|
+
|
|
5
|
+
Defines what :class:`ExecutableBase <Executable>` is, how it works and how ``wrfrun`` records simulations.
|
|
6
|
+
|
|
7
|
+
.. autosummary::
|
|
8
|
+
:toctree: generated/
|
|
9
|
+
|
|
10
|
+
check_subprocess_status
|
|
11
|
+
call_subprocess
|
|
12
|
+
InputFileType
|
|
13
|
+
FileConfigDict
|
|
14
|
+
ExecutableClassConfig
|
|
15
|
+
ExecutableConfig
|
|
16
|
+
_ExecutableConfigRecord
|
|
17
|
+
ExecutableBase
|
|
18
|
+
|
|
19
|
+
Executable
|
|
20
|
+
**********
|
|
21
|
+
|
|
22
|
+
While ``wrfrun`` aims to provide Python interfaces to various Numerical Weather Prediction model,
|
|
23
|
+
it is important to provide a clear standard about how should an external executable file be implemented in ``wrfrun``.
|
|
24
|
+
``wrfrun`` provides a class called :class:`ExecutableBase`, which is the parent class for all ``Executable`` classes.
|
|
25
|
+
It not only provide the method to execute external programs,
|
|
26
|
+
but also:
|
|
27
|
+
|
|
28
|
+
* Store all the information about the program (e.g., its inputs and outputs, its configuration).
|
|
29
|
+
* Provide the interface to import and export ``Executable``'s config.
|
|
30
|
+
* Support the ``replay`` functionality of ``wrfrun``.
|
|
31
|
+
|
|
32
|
+
If you want to use all the ``wrfrun``'s features, you **HAVE TO** implement your code with :class:`ExecutableBase`.
|
|
33
|
+
|
|
34
|
+
ExecConfigRecorder
|
|
35
|
+
******************
|
|
36
|
+
|
|
37
|
+
To be able to record the whole simulation, ``wrfrun`` introduces the global variable ``ExecConfigRecorder``,
|
|
38
|
+
which is an instance of class :class:`_ExecutableConfigRecord`.
|
|
39
|
+
``ExecConfigRecorder`` can store the config of any ``Executable`` in the correct order and export them to a JSON file,
|
|
40
|
+
enabling the precise replay of the simulation. Depending on the internal implementation of the ``Executable``,
|
|
41
|
+
the recorded config may even include the complete namelist values, Vtable config, and more.
|
|
42
|
+
Please check :meth:`ExecutableBase.generate_custom_config` for more details.
|
|
43
|
+
"""
|
|
44
|
+
|
|
1
45
|
import subprocess
|
|
46
|
+
from copy import deepcopy
|
|
2
47
|
from enum import Enum
|
|
3
48
|
from json import dumps
|
|
4
49
|
from os import chdir, getcwd, listdir, makedirs, remove, symlink
|
|
@@ -15,7 +60,8 @@ from ..utils import check_path, logger
|
|
|
15
60
|
|
|
16
61
|
def check_subprocess_status(status: subprocess.CompletedProcess):
|
|
17
62
|
"""
|
|
18
|
-
Check subprocess return code
|
|
63
|
+
Check subprocess return code.
|
|
64
|
+
An ``RuntimeError`` exception will be raised if ``return_code != 0``, and the ``stdout`` and ``stderr`` of the subprocess will be logged.
|
|
19
65
|
|
|
20
66
|
:param status: Status from subprocess.
|
|
21
67
|
:type status: CompletedProcess
|
|
@@ -39,7 +85,7 @@ def check_subprocess_status(status: subprocess.CompletedProcess):
|
|
|
39
85
|
|
|
40
86
|
def call_subprocess(command: list[str], work_path: Optional[str] = None, print_output=False):
|
|
41
87
|
"""
|
|
42
|
-
Execute the given command in system shell.
|
|
88
|
+
Execute the given command in the system shell.
|
|
43
89
|
|
|
44
90
|
:param command: A list contains the command and parameters to be executed.
|
|
45
91
|
:type command: list
|
|
@@ -48,8 +94,6 @@ def call_subprocess(command: list[str], work_path: Optional[str] = None, print_o
|
|
|
48
94
|
:type work_path: str | None
|
|
49
95
|
:param print_output: If print standard output and error in the logger.
|
|
50
96
|
:type print_output: bool
|
|
51
|
-
:return:
|
|
52
|
-
:rtype:
|
|
53
97
|
"""
|
|
54
98
|
if work_path is not None:
|
|
55
99
|
origin_path = getcwd()
|
|
@@ -88,9 +132,21 @@ def _json_default(obj):
|
|
|
88
132
|
|
|
89
133
|
class InputFileType(Enum):
|
|
90
134
|
"""
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
135
|
+
This class is an ``Enum`` class, providing the following values:
|
|
136
|
+
|
|
137
|
+
.. py:attribute:: WRFRUN_RES
|
|
138
|
+
:type: int
|
|
139
|
+
:value: 1
|
|
140
|
+
|
|
141
|
+
Indicating resource files are from the model or ``wrfrun``.
|
|
142
|
+
``wrfrun`` won't save these files when recording the simulation.
|
|
143
|
+
|
|
144
|
+
.. py:attribute:: CUSTOM_RES
|
|
145
|
+
:type: int
|
|
146
|
+
:value: 2
|
|
147
|
+
|
|
148
|
+
Indicating resource files are provided by the user.
|
|
149
|
+
``wrfrun`` will also save these files to ``.replay`` file when recording the simulation to ensure the simulation is replayable.
|
|
94
150
|
"""
|
|
95
151
|
WRFRUN_RES = 1
|
|
96
152
|
CUSTOM_RES = 2
|
|
@@ -98,7 +154,35 @@ class InputFileType(Enum):
|
|
|
98
154
|
|
|
99
155
|
class FileConfigDict(TypedDict):
|
|
100
156
|
"""
|
|
101
|
-
|
|
157
|
+
This dict is used to store information about the file, including its path,
|
|
158
|
+
the path it will be copied or moved to, its new name, etc.
|
|
159
|
+
This dict contains following keys:
|
|
160
|
+
|
|
161
|
+
.. py:attribute:: file_path
|
|
162
|
+
:type: str
|
|
163
|
+
|
|
164
|
+
A real file path or a valid URI which can be converted to a file path.
|
|
165
|
+
|
|
166
|
+
.. py:attribute:: save_path
|
|
167
|
+
:type: str
|
|
168
|
+
|
|
169
|
+
Save path of the file.
|
|
170
|
+
|
|
171
|
+
.. py:attribute:: save_name
|
|
172
|
+
:type: str
|
|
173
|
+
|
|
174
|
+
Save name of the file.
|
|
175
|
+
|
|
176
|
+
.. py:attribute:: is_data
|
|
177
|
+
:type: bool
|
|
178
|
+
|
|
179
|
+
If the file is data. If not, ``wrfrun`` will treat it as a config file,
|
|
180
|
+
and always save it to ``.replay`` file when recording the simulation.
|
|
181
|
+
|
|
182
|
+
.. py:attribute:: is_output
|
|
183
|
+
:type: bool
|
|
184
|
+
|
|
185
|
+
If the file is model's output. Output file will never be saved to ``.replay`` file.
|
|
102
186
|
"""
|
|
103
187
|
file_path: str
|
|
104
188
|
save_path: str
|
|
@@ -109,7 +193,17 @@ class FileConfigDict(TypedDict):
|
|
|
109
193
|
|
|
110
194
|
class ExecutableClassConfig(TypedDict):
|
|
111
195
|
"""
|
|
112
|
-
|
|
196
|
+
This dict is used to store arguments of ``Executable``'s ``__init__`` function.
|
|
197
|
+
|
|
198
|
+
.. py:attribute:: class_args
|
|
199
|
+
:type: tuple
|
|
200
|
+
|
|
201
|
+
Positional arguments of the class.
|
|
202
|
+
|
|
203
|
+
.. py:attribute:: class_kwargs
|
|
204
|
+
:type: dict
|
|
205
|
+
|
|
206
|
+
Keyword arguments of the class.
|
|
113
207
|
"""
|
|
114
208
|
# only list essential config
|
|
115
209
|
class_args: tuple
|
|
@@ -118,7 +212,57 @@ class ExecutableClassConfig(TypedDict):
|
|
|
118
212
|
|
|
119
213
|
class ExecutableConfig(TypedDict):
|
|
120
214
|
"""
|
|
121
|
-
|
|
215
|
+
This dict is used to store all configs of a :class:`ExecutableBase`.
|
|
216
|
+
|
|
217
|
+
.. py:attribute:: name
|
|
218
|
+
:type: str
|
|
219
|
+
|
|
220
|
+
Name of the executable. Each type of executable has a unique name.
|
|
221
|
+
|
|
222
|
+
.. py:attribute:: cmd
|
|
223
|
+
:type: str | list[str]
|
|
224
|
+
|
|
225
|
+
Command of the executable.
|
|
226
|
+
|
|
227
|
+
.. py:attribute:: work_path
|
|
228
|
+
:type: str | None
|
|
229
|
+
|
|
230
|
+
Work path of the executable.
|
|
231
|
+
|
|
232
|
+
.. py:attribute:: mpi_use
|
|
233
|
+
:type: bool
|
|
234
|
+
|
|
235
|
+
If the executable will use MPI.
|
|
236
|
+
|
|
237
|
+
.. py:attribute:: mpi_cmd
|
|
238
|
+
:type: str | None
|
|
239
|
+
|
|
240
|
+
Command name of the MPI.
|
|
241
|
+
|
|
242
|
+
.. py:attribute:: mpi_core_num
|
|
243
|
+
:type: int | None
|
|
244
|
+
|
|
245
|
+
Number of the CPU core to use with MPI.
|
|
246
|
+
|
|
247
|
+
.. py:attribute:: class_config
|
|
248
|
+
:type: ExecutableClassConfig | None
|
|
249
|
+
|
|
250
|
+
A dict stores arguments of ``Executable``'s ``__init__`` function.
|
|
251
|
+
|
|
252
|
+
.. py:attribute:: input_file_config
|
|
253
|
+
:type: list[FileConfigDict] | None
|
|
254
|
+
|
|
255
|
+
A list stores information about input files of the executable.
|
|
256
|
+
|
|
257
|
+
.. py:attribute:: output_file_config
|
|
258
|
+
:type: list[FileConfigDict] | None
|
|
259
|
+
|
|
260
|
+
A list stores information about output files of the executable.
|
|
261
|
+
|
|
262
|
+
.. py:attribute:: custom_config
|
|
263
|
+
:type: dict | None
|
|
264
|
+
|
|
265
|
+
A dict that can be used by subclass to store other configs.
|
|
122
266
|
"""
|
|
123
267
|
name: str
|
|
124
268
|
cmd: Union[str, list[str]]
|
|
@@ -134,17 +278,16 @@ class ExecutableConfig(TypedDict):
|
|
|
134
278
|
|
|
135
279
|
class _ExecutableConfigRecord:
|
|
136
280
|
"""
|
|
137
|
-
|
|
281
|
+
A class to helps store configs of various executables and exports them to a file.
|
|
138
282
|
"""
|
|
139
283
|
_instance = None
|
|
140
284
|
_initialized = False
|
|
141
285
|
|
|
142
286
|
def __init__(self, save_path: Optional[str] = None, include_data=False):
|
|
143
287
|
"""
|
|
144
|
-
Record executable configs and export them.
|
|
145
288
|
|
|
146
289
|
:param save_path: Save path of the exported config file.
|
|
147
|
-
:type save_path: str
|
|
290
|
+
:type save_path: str | None
|
|
148
291
|
:param include_data: If includes input data.
|
|
149
292
|
:type include_data: bool
|
|
150
293
|
"""
|
|
@@ -160,7 +303,7 @@ class _ExecutableConfigRecord:
|
|
|
160
303
|
self.save_path = save_path
|
|
161
304
|
self.include_data = include_data
|
|
162
305
|
|
|
163
|
-
self.work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.
|
|
306
|
+
self.work_path = WRFRUNConfig.parse_resource_uri(WRFRUNConfig.WRFRUN_WORKSPACE_REPLAY)
|
|
164
307
|
self.content_path = f"{self.work_path}/config_and_data"
|
|
165
308
|
check_path(self.content_path)
|
|
166
309
|
|
|
@@ -179,8 +322,8 @@ class _ExecutableConfigRecord:
|
|
|
179
322
|
"""
|
|
180
323
|
Reinitialize this instance.
|
|
181
324
|
|
|
182
|
-
:return:
|
|
183
|
-
:rtype:
|
|
325
|
+
:return: New instance.
|
|
326
|
+
:rtype: _ExecutableConfigRecord
|
|
184
327
|
"""
|
|
185
328
|
self._initialized = False
|
|
186
329
|
return _ExecutableConfigRecord(save_path, include_data)
|
|
@@ -191,8 +334,6 @@ class _ExecutableConfigRecord:
|
|
|
191
334
|
|
|
192
335
|
:param exported_config: Executable config.
|
|
193
336
|
:type exported_config: ExecutableConfig
|
|
194
|
-
:return:
|
|
195
|
-
:rtype:
|
|
196
337
|
"""
|
|
197
338
|
if not self.include_data:
|
|
198
339
|
self._recorded_config.append(exported_config)
|
|
@@ -210,7 +351,7 @@ class _ExecutableConfigRecord:
|
|
|
210
351
|
self._name_count[name] = 1
|
|
211
352
|
index = 1
|
|
212
353
|
|
|
213
|
-
data_save_uri = f"{WRFRUNConfig.
|
|
354
|
+
data_save_uri = f"{WRFRUNConfig.WRFRUN_WORKSPACE_REPLAY}/{name}/{index}"
|
|
214
355
|
data_save_path = f"{self.content_path}/{name}/{index}"
|
|
215
356
|
makedirs(data_save_path)
|
|
216
357
|
|
|
@@ -236,19 +377,13 @@ class _ExecutableConfigRecord:
|
|
|
236
377
|
|
|
237
378
|
def clear_records(self):
|
|
238
379
|
"""
|
|
239
|
-
Clean
|
|
240
|
-
|
|
241
|
-
:return:
|
|
242
|
-
:rtype:
|
|
380
|
+
Clean recorded configs.
|
|
243
381
|
"""
|
|
244
382
|
self._recorded_config = []
|
|
245
383
|
|
|
246
384
|
def export_replay_file(self):
|
|
247
385
|
"""
|
|
248
|
-
Save replay file to the
|
|
249
|
-
|
|
250
|
-
:return:
|
|
251
|
-
:rtype:
|
|
386
|
+
Save replay file to the save path.
|
|
252
387
|
"""
|
|
253
388
|
if len(self._recorded_config) == 0:
|
|
254
389
|
logger.warning("No replay config has been recorded.")
|
|
@@ -288,12 +423,37 @@ ExecConfigRecorder = _ExecutableConfigRecord()
|
|
|
288
423
|
class ExecutableBase:
|
|
289
424
|
"""
|
|
290
425
|
Base class for all executables.
|
|
426
|
+
|
|
427
|
+
.. py:attribute:: class_config
|
|
428
|
+
:type: ExecutableClassConfig
|
|
429
|
+
:value: {"class_args": (), "class_kwargs": {}}
|
|
430
|
+
|
|
431
|
+
A dict stores arguments of ``Executable``'s ``__init__`` function.
|
|
432
|
+
|
|
433
|
+
.. py:attribute:: custom_config
|
|
434
|
+
:type: dict
|
|
435
|
+
:value: {}
|
|
436
|
+
|
|
437
|
+
A dict that can be used by subclass to store custom configs.
|
|
438
|
+
|
|
439
|
+
.. py:attribute:: input_file_config
|
|
440
|
+
:type: list[FileConfigDict]
|
|
441
|
+
:value: []
|
|
442
|
+
|
|
443
|
+
A list stores information about input files of the executable.
|
|
444
|
+
|
|
445
|
+
.. py:attribute:: output_file_config
|
|
446
|
+
:type: list[FileConfigDict]
|
|
447
|
+
:value: []
|
|
448
|
+
|
|
449
|
+
A list stores information about output files of the executable.
|
|
450
|
+
|
|
291
451
|
"""
|
|
292
452
|
_instance = None
|
|
293
453
|
|
|
294
|
-
def __init__(self, name: str, cmd: Union[str, list[str]], work_path: str,
|
|
454
|
+
def __init__(self, name: str, cmd: Union[str, list[str]], work_path: str,
|
|
455
|
+
mpi_use=False, mpi_cmd: Optional[str] = None, mpi_core_num: Optional[int] = None):
|
|
295
456
|
"""
|
|
296
|
-
Base class for all executables.
|
|
297
457
|
|
|
298
458
|
:param name: Unique name to identify different executables.
|
|
299
459
|
:type name: str
|
|
@@ -338,19 +498,23 @@ class ExecutableBase:
|
|
|
338
498
|
|
|
339
499
|
def generate_custom_config(self):
|
|
340
500
|
"""
|
|
341
|
-
Generate custom configs.
|
|
501
|
+
Generate custom configs. This method should be overwritten in the child class,
|
|
502
|
+
and **MUST STORE THE CUSTOM CONFIG IN THE ATTRIBUTE** :attr:`ExecutableBase.custom_config`,
|
|
503
|
+
or it will do nothing except print a debug log.
|
|
342
504
|
|
|
343
|
-
|
|
344
|
-
|
|
505
|
+
You can export various configs in this method, like the complete namelist values of a NWP model binary,
|
|
506
|
+
or the path of Vtable file this executable will use.
|
|
507
|
+
|
|
508
|
+
If you overwrite this method to generate custom configs,
|
|
509
|
+
you also have to overwrite :meth:`ExecutableBase.load_custom_config` to load your custom configs.
|
|
345
510
|
"""
|
|
346
511
|
logger.debug(f"Method 'generate_custom_config' not implemented in '{self.name}'")
|
|
347
512
|
|
|
348
513
|
def load_custom_config(self):
|
|
349
514
|
"""
|
|
350
515
|
Load custom configs.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
:rtype:
|
|
516
|
+
This method should be overwritten in the child class to process the custom config stored in :attr:`ExecutableBase.custom_config`,
|
|
517
|
+
or it will do nothing except print a debug log.
|
|
354
518
|
"""
|
|
355
519
|
logger.debug(f"Method 'load_custom_config' not implemented in '{self.name}'")
|
|
356
520
|
|
|
@@ -370,20 +534,18 @@ class ExecutableBase:
|
|
|
370
534
|
"mpi_use": self.mpi_use,
|
|
371
535
|
"mpi_cmd": self.mpi_cmd,
|
|
372
536
|
"mpi_core_num": self.mpi_core_num,
|
|
373
|
-
"class_config": self.class_config,
|
|
374
|
-
"custom_config": self.custom_config,
|
|
375
|
-
"input_file_config": self.input_file_config,
|
|
376
|
-
"output_file_config": self.output_file_config
|
|
537
|
+
"class_config": deepcopy(self.class_config),
|
|
538
|
+
"custom_config": deepcopy(self.custom_config),
|
|
539
|
+
"input_file_config": deepcopy(self.input_file_config),
|
|
540
|
+
"output_file_config": deepcopy(self.output_file_config)
|
|
377
541
|
}
|
|
378
542
|
|
|
379
543
|
def load_config(self, config: ExecutableConfig):
|
|
380
544
|
"""
|
|
381
|
-
Load config from a dict.
|
|
545
|
+
Load executable config from a dict.
|
|
382
546
|
|
|
383
547
|
:param config: Config dict. It must contain some essential keys. Check ``ExecutableConfig`` for details.
|
|
384
548
|
:type config: ExecutableConfig
|
|
385
|
-
:return:
|
|
386
|
-
:rtype:
|
|
387
549
|
"""
|
|
388
550
|
if "name" not in config:
|
|
389
551
|
logger.error("A valid config is required. Please check ``ExecutableConfig``.")
|
|
@@ -398,10 +560,10 @@ class ExecutableBase:
|
|
|
398
560
|
self.mpi_use = config["mpi_use"]
|
|
399
561
|
self.mpi_cmd = config["mpi_cmd"]
|
|
400
562
|
self.mpi_core_num = config["mpi_core_num"]
|
|
401
|
-
self.class_config = config["class_config"]
|
|
402
|
-
self.custom_config = config["custom_config"]
|
|
403
|
-
self.input_file_config = config["input_file_config"]
|
|
404
|
-
self.output_file_config = config["output_file_config"]
|
|
563
|
+
self.class_config = deepcopy(config["class_config"])
|
|
564
|
+
self.custom_config = deepcopy(config["custom_config"])
|
|
565
|
+
self.input_file_config = deepcopy(config["input_file_config"])
|
|
566
|
+
self.output_file_config = deepcopy(config["output_file_config"])
|
|
405
567
|
|
|
406
568
|
self.load_custom_config()
|
|
407
569
|
|
|
@@ -409,23 +571,22 @@ class ExecutableBase:
|
|
|
409
571
|
"""
|
|
410
572
|
This method will be called when replay the simulation.
|
|
411
573
|
This method should take care every job that will be done when replaying the simulation.
|
|
412
|
-
|
|
413
|
-
:return:
|
|
414
|
-
:rtype:
|
|
574
|
+
By default, this method will call ``__call__`` method of the instance.
|
|
415
575
|
"""
|
|
416
576
|
logger.debug(f"Method 'replay' not implemented in '{self.name}', fall back to default action.")
|
|
417
577
|
self()
|
|
418
578
|
|
|
419
|
-
def add_input_files(self, input_files: Union[str, list[str], FileConfigDict, list[FileConfigDict]],
|
|
579
|
+
def add_input_files(self, input_files: Union[str, list[str], FileConfigDict, list[FileConfigDict]],
|
|
580
|
+
is_data=True, is_output=True):
|
|
420
581
|
"""
|
|
421
|
-
Add input files the
|
|
582
|
+
Add input files the executable will use.
|
|
422
583
|
|
|
423
584
|
You can give a single file path or a list contains files' path.
|
|
424
585
|
|
|
425
586
|
>>> self.add_input_files("data/custom_file")
|
|
426
587
|
>>> self.add_input_files(["data/custom_file_1", "data/custom_file_2"])
|
|
427
588
|
|
|
428
|
-
You can give more information with a ``FileConfigDict
|
|
589
|
+
You can give more information with a ``FileConfigDict``.
|
|
429
590
|
|
|
430
591
|
>>> file_dict: FileConfigDict = {
|
|
431
592
|
... "file_path": "data/custom_file.nc",
|
|
@@ -452,12 +613,14 @@ class ExecutableBase:
|
|
|
452
613
|
... }
|
|
453
614
|
>>> self.add_input_files([file_dict_1, file_dict_2])
|
|
454
615
|
|
|
455
|
-
|
|
616
|
+
Please check :class:`FileConfigDict` for more details.
|
|
617
|
+
|
|
618
|
+
:param input_files: Custom files.
|
|
456
619
|
:type input_files: str | list | dict
|
|
457
|
-
:param is_data: If
|
|
620
|
+
:param is_data: If it is a data file. This parameter will be overwritten by the value in ``input_files``.
|
|
458
621
|
:type is_data: bool
|
|
459
|
-
:
|
|
460
|
-
:
|
|
622
|
+
:param is_output: If it is an output from another executable. This parameter will be overwritten by the value in ``input_files``.
|
|
623
|
+
:type is_output: bool
|
|
461
624
|
"""
|
|
462
625
|
if isinstance(input_files, str):
|
|
463
626
|
self.input_file_config.append(
|
|
@@ -496,22 +659,39 @@ class ExecutableBase:
|
|
|
496
659
|
endswith: Union[None, str, tuple[str, ...]] = None, outputs: Union[None, str, list[str]] = None, no_file_error=True
|
|
497
660
|
):
|
|
498
661
|
"""
|
|
499
|
-
|
|
662
|
+
Find and save model's outputs to the output save path.
|
|
663
|
+
An ``OutputFileError`` exception will be raised if no file can be found and ``no_file_error==True``.
|
|
664
|
+
|
|
665
|
+
You can give the specific path of a file or multiple files.
|
|
666
|
+
|
|
667
|
+
>>> self.add_output_files(outputs="wrfout.d01")
|
|
668
|
+
>>> self.add_output_files(outputs=["wrfout.d01", "wrfout.d02"])
|
|
669
|
+
|
|
670
|
+
If you have too many outputs, but they have the same prefix or postfix, you can use ``startswith`` or ``endswith``.
|
|
671
|
+
|
|
672
|
+
>>> self.add_output_files(startswith="rsl.out.")
|
|
673
|
+
>>> self.add_output_files(endswith="log")
|
|
674
|
+
>>> self.add_output_files(startswith=("rsl", "wrfout"), endswith="log")
|
|
675
|
+
|
|
676
|
+
``startswith``, ``endswith`` and ``outputs`` can be used together.
|
|
500
677
|
|
|
501
|
-
|
|
678
|
+
``output_dir`` specify the search path of outputs, by default it is the work path of the executable.
|
|
679
|
+
You can change its value if the output path of the executable isn't its work path.
|
|
680
|
+
|
|
681
|
+
>>> self.add_output_files(output_dir=f"/absolute/dir/path", outputs=...)
|
|
682
|
+
|
|
683
|
+
:param output_dir: Search path of outputs.
|
|
502
684
|
:type output_dir: str
|
|
503
|
-
:param save_path:
|
|
685
|
+
:param save_path: New save path of outputs. By default, it is ``f"{WRFRUNConfig.WRFRUN_OUTPUT_PATH}/{self.name}"``.
|
|
504
686
|
:type save_path: str
|
|
505
687
|
:param startswith: Prefix string or prefix list of output files.
|
|
506
688
|
:type startswith: str | list
|
|
507
|
-
:param endswith: Postfix string or
|
|
689
|
+
:param endswith: Postfix string or postfix list of output files.
|
|
508
690
|
:type endswith: str | list
|
|
509
691
|
:param outputs: Files name list. All files in the list will be saved.
|
|
510
692
|
:type outputs: str | list
|
|
511
|
-
:param no_file_error: If True, an
|
|
693
|
+
:param no_file_error: If True, an OutputFileError will be raised if no output file can be found. Defaults to True.
|
|
512
694
|
:type no_file_error: bool
|
|
513
|
-
:return:
|
|
514
|
-
:rtype:
|
|
515
695
|
"""
|
|
516
696
|
if WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
517
697
|
return
|
|
@@ -567,10 +747,7 @@ class ExecutableBase:
|
|
|
567
747
|
|
|
568
748
|
def before_exec(self):
|
|
569
749
|
"""
|
|
570
|
-
Prepare input files.
|
|
571
|
-
|
|
572
|
-
:return:
|
|
573
|
-
:rtype:
|
|
750
|
+
Prepare input files before executing the external program.
|
|
574
751
|
"""
|
|
575
752
|
if WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
576
753
|
logger.info(f"We are in fake simulation mode, skip preparing input files for '{self.name}'")
|
|
@@ -603,10 +780,7 @@ class ExecutableBase:
|
|
|
603
780
|
|
|
604
781
|
def after_exec(self):
|
|
605
782
|
"""
|
|
606
|
-
Save outputs and logs.
|
|
607
|
-
|
|
608
|
-
:return:
|
|
609
|
-
:rtype:
|
|
783
|
+
Save outputs and logs after executing the external program.
|
|
610
784
|
"""
|
|
611
785
|
if WRFRUNConfig.FAKE_SIMULATION_MODE:
|
|
612
786
|
logger.info(f"We are in fake simulation mode, skip saving outputs for '{self.name}'")
|
|
@@ -639,9 +813,6 @@ class ExecutableBase:
|
|
|
639
813
|
def exec(self):
|
|
640
814
|
"""
|
|
641
815
|
Execute the given command.
|
|
642
|
-
|
|
643
|
-
:return:
|
|
644
|
-
:rtype:
|
|
645
816
|
"""
|
|
646
817
|
work_path = WRFRUNConfig.parse_resource_uri(self.work_path)
|
|
647
818
|
|
|
@@ -664,7 +835,7 @@ class ExecutableBase:
|
|
|
664
835
|
|
|
665
836
|
def __call__(self):
|
|
666
837
|
"""
|
|
667
|
-
Execute the given command
|
|
838
|
+
Execute the given command by calling ``before_exec``, ``exec`` and ``after_exec``.
|
|
668
839
|
|
|
669
840
|
:return:
|
|
670
841
|
:rtype:
|