vortex-nwp 2.0.0b1__py3-none-any.whl → 2.1.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.
- vortex/__init__.py +75 -47
- vortex/algo/__init__.py +3 -2
- vortex/algo/components.py +944 -618
- vortex/algo/mpitools.py +802 -497
- vortex/algo/mpitools_templates/__init__.py +1 -0
- vortex/algo/serversynctools.py +34 -33
- vortex/config.py +19 -22
- vortex/data/__init__.py +9 -3
- vortex/data/abstractstores.py +593 -655
- vortex/data/containers.py +217 -162
- vortex/data/contents.py +65 -39
- vortex/data/executables.py +93 -102
- vortex/data/flow.py +40 -34
- vortex/data/geometries.py +228 -132
- vortex/data/handlers.py +436 -227
- vortex/data/outflow.py +15 -15
- vortex/data/providers.py +185 -163
- vortex/data/resources.py +48 -42
- vortex/data/stores.py +540 -417
- vortex/data/sync_templates/__init__.py +0 -0
- vortex/gloves.py +114 -87
- vortex/layout/__init__.py +1 -8
- vortex/layout/contexts.py +150 -84
- vortex/layout/dataflow.py +353 -202
- vortex/layout/monitor.py +264 -128
- vortex/nwp/__init__.py +5 -2
- vortex/nwp/algo/__init__.py +14 -5
- vortex/nwp/algo/assim.py +205 -151
- vortex/nwp/algo/clim.py +683 -517
- vortex/nwp/algo/coupling.py +447 -225
- vortex/nwp/algo/eda.py +437 -229
- vortex/nwp/algo/eps.py +403 -231
- vortex/nwp/algo/forecasts.py +416 -275
- vortex/nwp/algo/fpserver.py +683 -307
- vortex/nwp/algo/ifsnaming.py +205 -145
- vortex/nwp/algo/ifsroot.py +215 -122
- vortex/nwp/algo/monitoring.py +137 -76
- vortex/nwp/algo/mpitools.py +330 -190
- vortex/nwp/algo/odbtools.py +637 -353
- vortex/nwp/algo/oopsroot.py +454 -273
- vortex/nwp/algo/oopstests.py +90 -56
- vortex/nwp/algo/request.py +287 -206
- vortex/nwp/algo/stdpost.py +878 -522
- vortex/nwp/data/__init__.py +22 -4
- vortex/nwp/data/assim.py +125 -137
- vortex/nwp/data/boundaries.py +121 -68
- vortex/nwp/data/climfiles.py +193 -211
- vortex/nwp/data/configfiles.py +73 -69
- vortex/nwp/data/consts.py +426 -401
- vortex/nwp/data/ctpini.py +59 -43
- vortex/nwp/data/diagnostics.py +94 -66
- vortex/nwp/data/eda.py +50 -51
- vortex/nwp/data/eps.py +195 -146
- vortex/nwp/data/executables.py +440 -434
- vortex/nwp/data/fields.py +63 -48
- vortex/nwp/data/gridfiles.py +183 -111
- vortex/nwp/data/logs.py +250 -217
- vortex/nwp/data/modelstates.py +180 -151
- vortex/nwp/data/monitoring.py +72 -99
- vortex/nwp/data/namelists.py +254 -202
- vortex/nwp/data/obs.py +400 -308
- vortex/nwp/data/oopsexec.py +22 -20
- vortex/nwp/data/providers.py +90 -65
- vortex/nwp/data/query.py +71 -82
- vortex/nwp/data/stores.py +49 -36
- vortex/nwp/data/surfex.py +136 -137
- vortex/nwp/syntax/__init__.py +1 -1
- vortex/nwp/syntax/stdattrs.py +173 -111
- vortex/nwp/tools/__init__.py +2 -2
- vortex/nwp/tools/addons.py +22 -17
- vortex/nwp/tools/agt.py +24 -12
- vortex/nwp/tools/bdap.py +16 -5
- vortex/nwp/tools/bdcp.py +4 -1
- vortex/nwp/tools/bdm.py +3 -0
- vortex/nwp/tools/bdmp.py +14 -9
- vortex/nwp/tools/conftools.py +728 -378
- vortex/nwp/tools/drhook.py +12 -8
- vortex/nwp/tools/grib.py +65 -39
- vortex/nwp/tools/gribdiff.py +22 -17
- vortex/nwp/tools/ifstools.py +82 -42
- vortex/nwp/tools/igastuff.py +167 -143
- vortex/nwp/tools/mars.py +14 -2
- vortex/nwp/tools/odb.py +234 -125
- vortex/nwp/tools/partitioning.py +61 -37
- vortex/nwp/tools/satrad.py +27 -12
- vortex/nwp/util/async.py +83 -55
- vortex/nwp/util/beacon.py +10 -10
- vortex/nwp/util/diffpygram.py +174 -86
- vortex/nwp/util/ens.py +144 -63
- vortex/nwp/util/hooks.py +30 -19
- vortex/nwp/util/taskdeco.py +28 -24
- vortex/nwp/util/usepygram.py +278 -172
- vortex/nwp/util/usetnt.py +31 -17
- vortex/sessions.py +72 -39
- vortex/syntax/__init__.py +1 -1
- vortex/syntax/stdattrs.py +410 -171
- vortex/syntax/stddeco.py +31 -22
- vortex/toolbox.py +327 -192
- vortex/tools/__init__.py +11 -2
- vortex/tools/actions.py +110 -121
- vortex/tools/addons.py +111 -92
- vortex/tools/arm.py +42 -22
- vortex/tools/compression.py +72 -69
- vortex/tools/date.py +11 -4
- vortex/tools/delayedactions.py +242 -132
- vortex/tools/env.py +75 -47
- vortex/tools/folder.py +342 -171
- vortex/tools/grib.py +341 -162
- vortex/tools/lfi.py +423 -216
- vortex/tools/listings.py +109 -40
- vortex/tools/names.py +218 -156
- vortex/tools/net.py +655 -299
- vortex/tools/parallelism.py +93 -61
- vortex/tools/prestaging.py +55 -31
- vortex/tools/schedulers.py +172 -105
- vortex/tools/services.py +403 -334
- vortex/tools/storage.py +293 -358
- vortex/tools/surfex.py +24 -24
- vortex/tools/systems.py +1234 -643
- vortex/tools/targets.py +156 -100
- vortex/util/__init__.py +1 -1
- vortex/util/config.py +378 -327
- vortex/util/empty.py +2 -2
- vortex/util/helpers.py +56 -24
- vortex/util/introspection.py +18 -12
- vortex/util/iosponge.py +8 -4
- vortex/util/roles.py +4 -6
- vortex/util/storefunctions.py +39 -13
- vortex/util/structs.py +3 -3
- vortex/util/worker.py +29 -17
- vortex_nwp-2.1.0.dist-info/METADATA +67 -0
- vortex_nwp-2.1.0.dist-info/RECORD +144 -0
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info}/WHEEL +1 -1
- vortex/layout/appconf.py +0 -109
- vortex/layout/jobs.py +0 -1276
- vortex/layout/nodes.py +0 -1424
- vortex/layout/subjobs.py +0 -464
- vortex_nwp-2.0.0b1.dist-info/METADATA +0 -50
- vortex_nwp-2.0.0b1.dist-info/RECORD +0 -146
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info/licenses}/LICENSE +0 -0
- {vortex_nwp-2.0.0b1.dist-info → vortex_nwp-2.1.0.dist-info}/top_level.txt +0 -0
vortex/nwp/algo/monitoring.py
CHANGED
|
@@ -14,51 +14,63 @@ __all__ = []
|
|
|
14
14
|
logger = loggers.getLogger(__name__)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class OdbMonitoring(
|
|
17
|
+
class OdbMonitoring(
|
|
18
|
+
Parallel, odb.OdbComponentDecoMixin, drhook.DrHookDecoMixin
|
|
19
|
+
):
|
|
18
20
|
"""Compute monitoring statistics."""
|
|
19
21
|
|
|
20
22
|
_footprint = dict(
|
|
21
|
-
attr
|
|
22
|
-
kind
|
|
23
|
-
values
|
|
23
|
+
attr=dict(
|
|
24
|
+
kind=dict(
|
|
25
|
+
values=["monitoring"],
|
|
24
26
|
),
|
|
25
|
-
npool
|
|
26
|
-
default
|
|
27
|
-
optional
|
|
27
|
+
npool=dict(
|
|
28
|
+
default=1,
|
|
29
|
+
optional=True,
|
|
28
30
|
),
|
|
29
|
-
obs
|
|
30
|
-
values
|
|
31
|
+
obs=dict(
|
|
32
|
+
values=["all", "used"],
|
|
31
33
|
),
|
|
32
|
-
date
|
|
33
|
-
model=
|
|
34
|
-
cutoff
|
|
35
|
-
start
|
|
36
|
-
type
|
|
37
|
-
default
|
|
38
|
-
optional
|
|
34
|
+
date=a_date,
|
|
35
|
+
model=a_model,
|
|
36
|
+
cutoff=a_cutoff,
|
|
37
|
+
start=dict(
|
|
38
|
+
type=bool,
|
|
39
|
+
default=False,
|
|
40
|
+
optional=True,
|
|
39
41
|
),
|
|
40
|
-
cumul
|
|
41
|
-
type
|
|
42
|
-
default
|
|
43
|
-
optional
|
|
42
|
+
cumul=dict(
|
|
43
|
+
type=bool,
|
|
44
|
+
default=True,
|
|
45
|
+
optional=True,
|
|
44
46
|
),
|
|
45
|
-
extend
|
|
46
|
-
type
|
|
47
|
-
default
|
|
48
|
-
optional
|
|
47
|
+
extend=dict(
|
|
48
|
+
type=bool,
|
|
49
|
+
default=False,
|
|
50
|
+
optional=True,
|
|
49
51
|
),
|
|
50
|
-
stage
|
|
51
|
-
values
|
|
52
|
-
remap
|
|
53
|
-
info
|
|
52
|
+
stage=dict(
|
|
53
|
+
values=["can", "surf", "surface", "atm", "atmospheric"],
|
|
54
|
+
remap=dict(can="surf", surface="surf", atmospheric="atm"),
|
|
55
|
+
info="The processing stage of the ODB base.",
|
|
54
56
|
),
|
|
55
57
|
)
|
|
56
58
|
)
|
|
57
59
|
|
|
60
|
+
def _mpitool_attributes(self, opts):
|
|
61
|
+
conf_dict = super()._mpitool_attributes(opts)
|
|
62
|
+
conf_dict.update({"mplbased": True})
|
|
63
|
+
return conf_dict
|
|
64
|
+
|
|
58
65
|
def _fix_nam_macro(self, rh, macro, value):
|
|
59
66
|
"""Set a given namelist macro and issue a log message."""
|
|
60
67
|
rh.contents.setmacro(macro, value)
|
|
61
|
-
logger.info(
|
|
68
|
+
logger.info(
|
|
69
|
+
"Setup %s macro to %s in %s",
|
|
70
|
+
macro,
|
|
71
|
+
value,
|
|
72
|
+
rh.container.actualpath(),
|
|
73
|
+
)
|
|
62
74
|
|
|
63
75
|
def prepare(self, rh, opts):
|
|
64
76
|
"""Update some variables in the namelist and check the presence of the accumulated statistics file."""
|
|
@@ -69,31 +81,42 @@ class OdbMonitoring(Parallel, odb.OdbComponentDecoMixin, drhook.DrHookDecoMixin)
|
|
|
69
81
|
|
|
70
82
|
# Virtual upper-air observations database
|
|
71
83
|
obsatm_virt = [
|
|
72
|
-
x
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
x
|
|
85
|
+
for x in self.lookupodb(fatal=False)
|
|
86
|
+
if (
|
|
87
|
+
x.rh.resource.stage.startswith("matchup")
|
|
88
|
+
or x.rh.resource.stage.startswith("screening")
|
|
89
|
+
)
|
|
90
|
+
and x.rh.resource.part == "virtual"
|
|
75
91
|
]
|
|
76
92
|
|
|
77
93
|
# Single upper-air observations database
|
|
78
94
|
obsatm_single = [
|
|
79
|
-
x
|
|
80
|
-
|
|
95
|
+
x
|
|
96
|
+
for x in self.lookupodb(fatal=False)
|
|
97
|
+
if x.rh.resource.stage.startswith("matchup")
|
|
98
|
+
or x.rh.resource.stage.startswith("screening")
|
|
81
99
|
]
|
|
82
100
|
if len(obsatm_single) > 1:
|
|
83
101
|
obsatm_single = []
|
|
84
102
|
|
|
85
103
|
# Surface observations database
|
|
86
104
|
obssurf = [
|
|
87
|
-
x
|
|
88
|
-
|
|
89
|
-
|
|
105
|
+
x
|
|
106
|
+
for x in self.lookupodb(fatal=False)
|
|
107
|
+
if x.rh.resource.stage.startswith("canari")
|
|
108
|
+
and (
|
|
109
|
+
x.rh.resource.part == "surf" or x.rh.resource.part == "ground"
|
|
110
|
+
)
|
|
90
111
|
]
|
|
91
112
|
|
|
92
113
|
# One database at a time
|
|
93
|
-
if not (obsatm_virt or obsatm_single) and self.stage ==
|
|
94
|
-
raise ValueError(
|
|
95
|
-
|
|
96
|
-
|
|
114
|
+
if not (obsatm_virt or obsatm_single) and self.stage == "atm":
|
|
115
|
+
raise ValueError(
|
|
116
|
+
"Could not find any ODB matchup or screening ECMA database"
|
|
117
|
+
)
|
|
118
|
+
if not obssurf and self.stage == "surf":
|
|
119
|
+
raise ValueError("Could not find any ODB surface ECMA database")
|
|
97
120
|
|
|
98
121
|
# Set actual ODB paths
|
|
99
122
|
if obsatm_virt:
|
|
@@ -104,8 +127,12 @@ class OdbMonitoring(Parallel, odb.OdbComponentDecoMixin, drhook.DrHookDecoMixin)
|
|
|
104
127
|
ecma = obssurf.pop(0)
|
|
105
128
|
ecma_path = sh.path.abspath(ecma.rh.container.localpath())
|
|
106
129
|
self.odb.fix_db_path(ecma.rh.resource.layout, ecma_path)
|
|
107
|
-
self.env.IOASSIGN = sh.path.join(ecma_path,
|
|
108
|
-
logger.info(
|
|
130
|
+
self.env.IOASSIGN = sh.path.join(ecma_path, "IOASSIGN")
|
|
131
|
+
logger.info(
|
|
132
|
+
"Setting ODB env %s = %s.",
|
|
133
|
+
"IOASSIGN",
|
|
134
|
+
sh.path.join(ecma_path, "IOASSIGN"),
|
|
135
|
+
)
|
|
109
136
|
|
|
110
137
|
# Let ancestors handling most of the env setting
|
|
111
138
|
super().prepare(rh, opts)
|
|
@@ -113,69 +140,103 @@ class OdbMonitoring(Parallel, odb.OdbComponentDecoMixin, drhook.DrHookDecoMixin)
|
|
|
113
140
|
# Force to start a new accumulated statistics file if first day and first hour of the month
|
|
114
141
|
mnt_start = self.start
|
|
115
142
|
|
|
116
|
-
if
|
|
117
|
-
|
|
143
|
+
if (
|
|
144
|
+
not mnt_start
|
|
145
|
+
and int(self.date.day) == 1
|
|
146
|
+
and int(self.date.hh) == 0
|
|
147
|
+
and not self.extend
|
|
148
|
+
):
|
|
149
|
+
logger.info(
|
|
150
|
+
"First day and first hour of the month : force start attribute to True."
|
|
151
|
+
)
|
|
118
152
|
mnt_start = True
|
|
119
153
|
|
|
120
154
|
mnt_cumul = self.cumul
|
|
121
|
-
if self.cutoff ==
|
|
155
|
+
if self.cutoff == "production":
|
|
122
156
|
mnt_cumul = False
|
|
123
|
-
logger.info(
|
|
124
|
-
|
|
157
|
+
logger.info(
|
|
158
|
+
"No output accumulated statistics file will be produced because "
|
|
159
|
+
"cutoff = production : force cumul to False"
|
|
160
|
+
)
|
|
125
161
|
|
|
126
162
|
# Monitoring namelist
|
|
127
163
|
namrh = self.context.sequence.effective_inputs(
|
|
128
|
-
role=
|
|
129
|
-
kind=
|
|
164
|
+
role="Namelist",
|
|
165
|
+
kind="namelist",
|
|
166
|
+
)
|
|
130
167
|
if len(namrh) != 1:
|
|
131
|
-
logger.critical(
|
|
132
|
-
|
|
168
|
+
logger.critical(
|
|
169
|
+
"There must be exactly one namelist for monitoring. Stop."
|
|
170
|
+
)
|
|
171
|
+
raise ValueError(
|
|
172
|
+
"There must be exactly one namelist for monitoring. Stop."
|
|
173
|
+
)
|
|
133
174
|
namrh = namrh[0].rh
|
|
134
175
|
|
|
135
176
|
# Cumulated statistics file
|
|
136
177
|
cumulrh = self.context.sequence.effective_inputs(
|
|
137
|
-
role=
|
|
138
|
-
kind=
|
|
178
|
+
role="Cumulated monitoring statistics",
|
|
179
|
+
kind="accumulated_stats",
|
|
139
180
|
)
|
|
140
181
|
|
|
141
182
|
if len(cumulrh) > 1:
|
|
142
|
-
logger.critical(
|
|
143
|
-
|
|
183
|
+
logger.critical(
|
|
184
|
+
"There must be at most one accumulated statistics file.Stop."
|
|
185
|
+
)
|
|
186
|
+
raise ValueError(
|
|
187
|
+
"There must be one accumulated statistics file or none.Stop."
|
|
188
|
+
)
|
|
144
189
|
else:
|
|
145
190
|
if len(cumulrh) == 0:
|
|
146
191
|
if not mnt_start:
|
|
147
192
|
if mnt_cumul:
|
|
148
|
-
logger.critical(
|
|
149
|
-
|
|
193
|
+
logger.critical(
|
|
194
|
+
"There must be one input accumulated statistics file. Stop."
|
|
195
|
+
)
|
|
196
|
+
raise ValueError(
|
|
197
|
+
"There must be one input accumulated statistics file. Stop."
|
|
198
|
+
)
|
|
150
199
|
else:
|
|
151
|
-
logger.info(
|
|
152
|
-
|
|
200
|
+
logger.info(
|
|
201
|
+
"No input accumulated statistics file is necessary."
|
|
202
|
+
)
|
|
203
|
+
logger.info(
|
|
204
|
+
"No output accumulated statistics file will be produced."
|
|
205
|
+
)
|
|
153
206
|
else:
|
|
154
207
|
if mnt_cumul:
|
|
155
|
-
logger.info(
|
|
208
|
+
logger.info(
|
|
209
|
+
"No input accumulated statistics file. It will be created by the binary."
|
|
210
|
+
)
|
|
156
211
|
else:
|
|
157
|
-
logger.info(
|
|
212
|
+
logger.info(
|
|
213
|
+
"No output accumulated statistics file will be produced."
|
|
214
|
+
)
|
|
158
215
|
else:
|
|
159
216
|
cumulrh = cumulrh[0].rh
|
|
160
217
|
if not mnt_cumul:
|
|
161
|
-
logger.info(
|
|
218
|
+
logger.info(
|
|
219
|
+
"No input accumulated statistics file is necessary(start=False)."
|
|
220
|
+
)
|
|
162
221
|
cumulrh.container.clear()
|
|
163
222
|
else:
|
|
164
223
|
if mnt_start:
|
|
165
|
-
logger.info(
|
|
224
|
+
logger.info(
|
|
225
|
+
"No input accumulated statistics file is necessary (start=True)"
|
|
226
|
+
)
|
|
166
227
|
cumulrh.container.clear()
|
|
167
228
|
|
|
168
|
-
self._fix_nam_macro(namrh,
|
|
169
|
-
self._fix_nam_macro(namrh,
|
|
229
|
+
self._fix_nam_macro(namrh, "JOUR", int(self.date.ymd))
|
|
230
|
+
self._fix_nam_macro(namrh, "RES", int(self.date.hh))
|
|
170
231
|
|
|
171
|
-
self._fix_nam_macro(namrh,
|
|
172
|
-
self._fix_nam_macro(namrh,
|
|
232
|
+
self._fix_nam_macro(namrh, "LLADMON", mnt_cumul)
|
|
233
|
+
self._fix_nam_macro(namrh, "LLADAJ", mnt_cumul and not mnt_start)
|
|
173
234
|
|
|
174
|
-
self._fix_nam_macro(namrh,
|
|
235
|
+
self._fix_nam_macro(namrh, "LLFLAG", self.obs != "all")
|
|
175
236
|
|
|
176
|
-
self._fix_nam_macro(namrh,
|
|
177
|
-
self._fix_nam_macro(namrh,
|
|
178
|
-
self._fix_nam_macro(namrh,
|
|
237
|
+
self._fix_nam_macro(namrh, "LLARO", self.model == "arome")
|
|
238
|
+
self._fix_nam_macro(namrh, "LLVRP", self.model == "varpack")
|
|
239
|
+
self._fix_nam_macro(namrh, "LLCAN", self.stage == "surf")
|
|
179
240
|
|
|
180
241
|
if namrh.contents.dumps_needs_update:
|
|
181
242
|
namrh.contents.rewrite(namrh.container)
|
|
@@ -189,13 +250,13 @@ class OdbMonitoring(Parallel, odb.OdbComponentDecoMixin, drhook.DrHookDecoMixin)
|
|
|
189
250
|
allfiles = sh.ls()
|
|
190
251
|
for f in allfiles:
|
|
191
252
|
if self.system.path.getsize(f) == 0:
|
|
192
|
-
logger.info(
|
|
253
|
+
logger.info("Remove %s because size of %s is zero.", f, f)
|
|
193
254
|
sh.remove(f)
|
|
194
255
|
|
|
195
|
-
obspoint_out = sh.ls(
|
|
256
|
+
obspoint_out = sh.ls("point.*")
|
|
196
257
|
if obspoint_out:
|
|
197
|
-
dest =
|
|
198
|
-
logger.info(
|
|
258
|
+
dest = "obslocationpack"
|
|
259
|
+
logger.info("Creating an OBSLOCATION pack: %s", dest)
|
|
199
260
|
sh.mkdir(dest)
|
|
200
261
|
for fname in obspoint_out:
|
|
201
262
|
sh.mv(fname, dest)
|