geone 1.2.10__py311-none-manylinux_2_35_x86_64.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.
- geone/__init__.py +30 -0
- geone/_version.py +6 -0
- geone/blockdata.py +232 -0
- geone/covModel.py +9725 -0
- geone/customcolors.py +490 -0
- geone/deesse_core/__init__.py +5 -0
- geone/deesse_core/_deesse.so +0 -0
- geone/deesse_core/deesse.py +2445 -0
- geone/deesseinterface.py +10181 -0
- geone/geosclassic_core/__init__.py +5 -0
- geone/geosclassic_core/_geosclassic.so +0 -0
- geone/geosclassic_core/geosclassic.py +1422 -0
- geone/geosclassicinterface.py +12336 -0
- geone/grf.py +5440 -0
- geone/img.py +6456 -0
- geone/imgplot.py +1367 -0
- geone/imgplot3d.py +1822 -0
- geone/multiGaussian.py +309 -0
- geone/pgs.py +1171 -0
- geone/randProcess.py +1122 -0
- geone/tools.py +762 -0
- geone-1.2.10.dist-info/LICENSE +58 -0
- geone-1.2.10.dist-info/METADATA +276 -0
- geone-1.2.10.dist-info/RECORD +26 -0
- geone-1.2.10.dist-info/WHEEL +5 -0
- geone-1.2.10.dist-info/top_level.txt +1 -0
geone/pgs.py
ADDED
|
@@ -0,0 +1,1171 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
# -------------------------------------------------------------------------
|
|
5
|
+
# Python module: 'pgs.py'
|
|
6
|
+
# author: Julien Straubhaar
|
|
7
|
+
# date: may-2022
|
|
8
|
+
# -------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
Module for plurig-Gaussian simulations in 1D, 2D and 3D.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
from geone import covModel as gcm
|
|
16
|
+
from geone import multiGaussian
|
|
17
|
+
|
|
18
|
+
# ----------------------------------------------------------------------------
|
|
19
|
+
def pluriGaussianSim_unconditional(cov_model_T1, cov_model_T2, flag_value,
|
|
20
|
+
dimension, spacing=None, origin=None,
|
|
21
|
+
algo_T1='fft', params_T1={},
|
|
22
|
+
algo_T2='fft', params_T2={},
|
|
23
|
+
nreal=1,
|
|
24
|
+
full_output=True,
|
|
25
|
+
verbose=4):
|
|
26
|
+
"""
|
|
27
|
+
Generates unconditional pluri-Gaussian simulations.
|
|
28
|
+
|
|
29
|
+
The simulated variable Z at a point x is defined as
|
|
30
|
+
|
|
31
|
+
* Z(x) = flag_value(T1(x), T2(x))
|
|
32
|
+
|
|
33
|
+
where
|
|
34
|
+
|
|
35
|
+
* T1, T2 are two multi-Gaussian random fields (latent fields)
|
|
36
|
+
* `flag_value` is a function of two variables defining the final value \
|
|
37
|
+
(given as a "flag")
|
|
38
|
+
|
|
39
|
+
Z and T1, T2 are fields in 1D, 2D or 3D.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
cov_model_T1 : :class:`geone.CovModel.CovModel<d>D`
|
|
44
|
+
covariance model for T1, in 1D or 2D or 3D (same space dimension for T1 and T2);
|
|
45
|
+
note: if `algo_T1='deterministic'`, `cov_model_T1` can be `None` (unused)
|
|
46
|
+
|
|
47
|
+
cov_model_T2 : :class:`geone.CovModel.CovModel<d>D`
|
|
48
|
+
covariance model for T2, in 1D or 2D or 3D (same space dimension for T1 and T2);
|
|
49
|
+
note: if `algo_T2='deterministic'`, `cov_model_T2` can be `None` (unused)
|
|
50
|
+
|
|
51
|
+
flag_value : function (`callable`)
|
|
52
|
+
function of tow arguments (xi, yi) that returns the "flag_value" at
|
|
53
|
+
location (xi, yi)
|
|
54
|
+
|
|
55
|
+
dimension : [sequence of] int(s)
|
|
56
|
+
number of cells along each axis, for simulation in:
|
|
57
|
+
|
|
58
|
+
- 1D: `dimension=nx`
|
|
59
|
+
- 2D: `dimension=(nx, ny)`
|
|
60
|
+
- 3D: `dimension=(nx, ny, nz)`
|
|
61
|
+
|
|
62
|
+
spacing : [sequence of] float(s), optional
|
|
63
|
+
cell size along each axis, for simulation in:
|
|
64
|
+
|
|
65
|
+
- 1D: `spacing=sx`
|
|
66
|
+
- 2D: `spacing=(sx, sy)`
|
|
67
|
+
- 3D: `spacing=(sx, sy, sz)`
|
|
68
|
+
|
|
69
|
+
by default (`None`): 1.0 along each axis
|
|
70
|
+
|
|
71
|
+
origin : [sequence of] float(s), optional
|
|
72
|
+
origin of the grid ("corner of the first cell"), for simulation in:
|
|
73
|
+
|
|
74
|
+
- 1D: `origin=ox`
|
|
75
|
+
- 2D: `origin=(ox, oy)`
|
|
76
|
+
- 3D: `origin=(ox, oy, oz)`
|
|
77
|
+
|
|
78
|
+
by default (`None`): 0.0 along each axis
|
|
79
|
+
|
|
80
|
+
algo_T1 : str {'fft', 'classic', 'deterministic'}, default: 'fft'
|
|
81
|
+
defines the algorithm used for T1:
|
|
82
|
+
|
|
83
|
+
- 'fft': algorithm based on circulant embedding and FFT, function \
|
|
84
|
+
called for <d>D (d = 1, 2, or 3): 'geone.grf.grf<d>D'
|
|
85
|
+
- 'classic': "classic" algorithm, based on the resolution of \
|
|
86
|
+
kriging system considered points in a search ellipsoid, function called \
|
|
87
|
+
for <d>D (d = 1, 2, or 3): \
|
|
88
|
+
'geone.geoscalassicinterface.simulate<d>D'
|
|
89
|
+
- 'deterministic': use a deterministic field, given by `param_T1['mean']`
|
|
90
|
+
|
|
91
|
+
algo_T2 : str {'fft', 'classic', 'deterministic'}, default: 'fft'
|
|
92
|
+
defines the algorithm used for T2 (see `algo_T1` for detail)
|
|
93
|
+
|
|
94
|
+
params_T1 : dict
|
|
95
|
+
keyword arguments (additional parameters) to be passed to the function
|
|
96
|
+
that is called (according to `algo_T1` and space dimension) for simulation
|
|
97
|
+
of T1
|
|
98
|
+
|
|
99
|
+
params_T2 : dict
|
|
100
|
+
keyword arguments (additional parameters) to be passed to the function
|
|
101
|
+
that is called (according to `algo_T2` and space dimension) for simulation
|
|
102
|
+
of T2
|
|
103
|
+
|
|
104
|
+
nreal : int, default: 1
|
|
105
|
+
number of realization(s)
|
|
106
|
+
|
|
107
|
+
full_output : bool, default: True
|
|
108
|
+
- if `True`: simulation(s) of Z, T1, and T2 are retrieved in output
|
|
109
|
+
- if `False`: simulation(s) of Z only is retrieved in output
|
|
110
|
+
|
|
111
|
+
verbose : int, default: 2
|
|
112
|
+
verbose mode, higher implies more printing (info)
|
|
113
|
+
|
|
114
|
+
Returns
|
|
115
|
+
-------
|
|
116
|
+
Z : ndarray
|
|
117
|
+
array of shape
|
|
118
|
+
|
|
119
|
+
- for 1D: (nreal, nx)
|
|
120
|
+
- for 2D: (nreal, ny, nx)
|
|
121
|
+
- for 3D: (nreal, nz, ny, nx)
|
|
122
|
+
|
|
123
|
+
Z[k] is the k-th realization of Z
|
|
124
|
+
|
|
125
|
+
T1 : ndarray, optional
|
|
126
|
+
array of shape
|
|
127
|
+
|
|
128
|
+
- for 1D: (nreal, nx)
|
|
129
|
+
- for 2D: (nreal, ny, nx)
|
|
130
|
+
- for 3D: (nreal, nz, ny, nx)
|
|
131
|
+
|
|
132
|
+
T1[k] is the k-th realization of T1;
|
|
133
|
+
returned if `full_output=True`
|
|
134
|
+
|
|
135
|
+
T2 : ndarray, optional
|
|
136
|
+
array of shape
|
|
137
|
+
|
|
138
|
+
- for 1D: (nreal, nx)
|
|
139
|
+
- for 2D: (nreal, ny, nx)
|
|
140
|
+
- for 3D: (nreal, nz, ny, nx)
|
|
141
|
+
|
|
142
|
+
T2[k] is the k-th realization of T2;
|
|
143
|
+
returned if `full_output=True`
|
|
144
|
+
"""
|
|
145
|
+
fname = 'pluriGaussianSim_unconditional'
|
|
146
|
+
|
|
147
|
+
if full_output:
|
|
148
|
+
out = None, None, None
|
|
149
|
+
else:
|
|
150
|
+
out = None
|
|
151
|
+
|
|
152
|
+
if not callable(flag_value):
|
|
153
|
+
if verbose > 0:
|
|
154
|
+
print(f"ERROR ({fname}): `flag_value` invalid, should be a function (callable) of two arguments")
|
|
155
|
+
return out
|
|
156
|
+
|
|
157
|
+
if algo_T1 not in ('fft', 'FFT', 'classic', 'CLASSIC', 'deterministic', 'DETERMINISTIC'):
|
|
158
|
+
if verbose > 0:
|
|
159
|
+
print(f"ERROR ({fname}): `algo_T1` invalid, should be 'fft' (default) or 'classic' or 'deterministic'")
|
|
160
|
+
return out
|
|
161
|
+
|
|
162
|
+
if algo_T2 not in ('fft', 'FFT', 'classic', 'CLASSIC', 'deterministic', 'DETERMINISTIC'):
|
|
163
|
+
if verbose > 0:
|
|
164
|
+
print(f"ERROR ({fname}): `algo_T2` invalid, should be 'fft' (default) or 'classic' or 'deterministic'")
|
|
165
|
+
return out
|
|
166
|
+
|
|
167
|
+
# Ignore covariance model if 'algo' is deterministic for T1, T2
|
|
168
|
+
if algo_T1 in ('deterministic', 'DETERMINISTIC'):
|
|
169
|
+
cov_model_T1 = None
|
|
170
|
+
|
|
171
|
+
if algo_T2 in ('deterministic', 'DETERMINISTIC'):
|
|
172
|
+
cov_model_T2 = None
|
|
173
|
+
|
|
174
|
+
# Set space dimension (of grid) according to covariance model for T1
|
|
175
|
+
d = 0
|
|
176
|
+
if cov_model_T1 is None:
|
|
177
|
+
if algo_T1 not in ('deterministic', 'DETERMINISTIC'):
|
|
178
|
+
if verbose > 0:
|
|
179
|
+
print(f"ERROR ({fname}): `cov_model_T1` is None, then `algo_T1` must be 'deterministic'")
|
|
180
|
+
return out
|
|
181
|
+
elif isinstance(cov_model_T1, gcm.CovModel1D):
|
|
182
|
+
d = 1
|
|
183
|
+
elif isinstance(cov_model_T1, gcm.CovModel2D):
|
|
184
|
+
d = 2
|
|
185
|
+
elif isinstance(cov_model_T1, gcm.CovModel3D):
|
|
186
|
+
d = 3
|
|
187
|
+
else:
|
|
188
|
+
if verbose > 0:
|
|
189
|
+
print(f"ERROR ({fname}): `cov_model_T1` invalid, should be a class: <geone.covModel.CovModel1D>, <geone.covModel.CovModel2D>, or <geone.covModel.CovModel3D>")
|
|
190
|
+
return out
|
|
191
|
+
|
|
192
|
+
if cov_model_T2 is None:
|
|
193
|
+
if algo_T2 not in ('deterministic', 'DETERMINISTIC'):
|
|
194
|
+
if verbose > 0:
|
|
195
|
+
print(f"ERROR ({fname}): `cov_model_T2` is None, then `algo_T2` must be 'deterministic'")
|
|
196
|
+
return out
|
|
197
|
+
# if d == 0:
|
|
198
|
+
# if verbose > 0:
|
|
199
|
+
# print(f"ERROR ({fname}): `cov_model_T1` and `cov_model_T2` are None, at least one covariance model is required")
|
|
200
|
+
# return out
|
|
201
|
+
elif (d == 1 and not isinstance(cov_model_T2, gcm.CovModel1D)) or (d == 2 and not isinstance(cov_model_T2, gcm.CovModel2D)) or (d == 3 and not isinstance(cov_model_T2, gcm.CovModel3D)):
|
|
202
|
+
if verbose > 0:
|
|
203
|
+
print(f"ERROR ({fname}): `cov_model_T1` and `cov_model_T2` not compatible (dimension differs)")
|
|
204
|
+
return out
|
|
205
|
+
|
|
206
|
+
if d == 0:
|
|
207
|
+
# Set space dimension (of grid) according to 'dimension'
|
|
208
|
+
if hasattr(dimension, '__len__'):
|
|
209
|
+
d = len(dimension)
|
|
210
|
+
else:
|
|
211
|
+
d = 1
|
|
212
|
+
|
|
213
|
+
# Check argument 'dimension'
|
|
214
|
+
if hasattr(dimension, '__len__') and len(dimension) != d:
|
|
215
|
+
if verbose > 0:
|
|
216
|
+
print(f"ERROR ({fname}): `dimension` of incompatible length")
|
|
217
|
+
return out
|
|
218
|
+
|
|
219
|
+
if d == 1:
|
|
220
|
+
grid_size = dimension
|
|
221
|
+
else:
|
|
222
|
+
grid_size = np.prod(dimension)
|
|
223
|
+
|
|
224
|
+
# Check (or set) argument 'spacing'
|
|
225
|
+
if spacing is None:
|
|
226
|
+
if d == 1:
|
|
227
|
+
spacing = 1.0
|
|
228
|
+
else:
|
|
229
|
+
spacing = tuple(np.ones(d))
|
|
230
|
+
else:
|
|
231
|
+
if hasattr(spacing, '__len__') and len(spacing) != d:
|
|
232
|
+
if verbose > 0:
|
|
233
|
+
print(f"ERROR ({fname}): `spacing` of incompatible length")
|
|
234
|
+
return out
|
|
235
|
+
|
|
236
|
+
# Check (or set) argument 'origin'
|
|
237
|
+
if origin is None:
|
|
238
|
+
if d == 1:
|
|
239
|
+
origin = 0.0
|
|
240
|
+
else:
|
|
241
|
+
origin = tuple(np.zeros(d))
|
|
242
|
+
else:
|
|
243
|
+
if hasattr(origin, '__len__') and len(origin) != d:
|
|
244
|
+
if verbose > 0:
|
|
245
|
+
print(f"ERROR ({fname}): `origin` of incompatible length")
|
|
246
|
+
return out
|
|
247
|
+
|
|
248
|
+
# if not cov_model_T1.is_stationary(): # prevent calculation if covariance model is not stationary
|
|
249
|
+
# if verbose > 0:
|
|
250
|
+
# print(f"ERROR ({fname}): `cov_model_T1` is not stationary")
|
|
251
|
+
|
|
252
|
+
# if not cov_model_T2.is_stationary(): # prevent calculation if covariance model is not stationary
|
|
253
|
+
# if verbose > 0:
|
|
254
|
+
# print(f"ERROR ({fname}): `cov_model_T2` is not stationary")
|
|
255
|
+
|
|
256
|
+
# Set default parameter 'verbose' for params_T1, params_T2
|
|
257
|
+
if 'verbose' not in params_T1.keys():
|
|
258
|
+
params_T1['verbose'] = 0
|
|
259
|
+
if 'verbose' not in params_T2.keys():
|
|
260
|
+
params_T2['verbose'] = 0
|
|
261
|
+
|
|
262
|
+
# Generate T1
|
|
263
|
+
if cov_model_T1 is not None:
|
|
264
|
+
sim_T1 = multiGaussian.multiGaussianRun(cov_model_T1, dimension, spacing, origin,
|
|
265
|
+
mode='simulation', algo=algo_T1, output_mode='array',
|
|
266
|
+
**params_T1, nreal=nreal)
|
|
267
|
+
else:
|
|
268
|
+
sim_T1 = np.array([params_T1['mean'].reshape(1,*dimension[::-1]) for _ in range(nreal)])
|
|
269
|
+
# -> sim_T1: nd-array of shape
|
|
270
|
+
# (nreal_T, dimension) (for T1 in 1D)
|
|
271
|
+
# (nreal_T, dimension[1], dimension[0]) (for T1 in 2D)
|
|
272
|
+
# (nreal_T, dimension[2], dimension[1], dimension[0]) (for T1 in 3D)
|
|
273
|
+
if sim_T1 is None:
|
|
274
|
+
if verbose > 0:
|
|
275
|
+
print(f'ERROR ({fname}): simulation of T1 failed')
|
|
276
|
+
return out
|
|
277
|
+
#
|
|
278
|
+
# Generate T2
|
|
279
|
+
if cov_model_T2 is not None:
|
|
280
|
+
sim_T2 = multiGaussian.multiGaussianRun(cov_model_T2, dimension, spacing, origin,
|
|
281
|
+
mode='simulation', algo=algo_T2, output_mode='array',
|
|
282
|
+
**params_T2, nreal=nreal)
|
|
283
|
+
else:
|
|
284
|
+
sim_T2 = np.array([params_T2['mean'].reshape(1,*dimension[::-1]) for _ in range(nreal)])
|
|
285
|
+
# -> sim_T2: nd-array of shape
|
|
286
|
+
# (nreal_T, dimension) (for T2 in 1D)
|
|
287
|
+
# (nreal_T, dimension[1], dimension[0]) (for T2 in 2D)
|
|
288
|
+
# (nreal_T, dimension[2], dimension[1], dimension[0]) (for T2 in 3D)
|
|
289
|
+
if sim_T2 is None:
|
|
290
|
+
if verbose > 0:
|
|
291
|
+
print(f'ERROR ({fname}): simulation of T2 failed')
|
|
292
|
+
return out
|
|
293
|
+
|
|
294
|
+
# Generate Z
|
|
295
|
+
if verbose > 2:
|
|
296
|
+
print('PLURIGAUSSIANSIM_UNCONDITIONAL: retrieving Z...')
|
|
297
|
+
Z = flag_value(sim_T1, sim_T2)
|
|
298
|
+
# Z = np.asarray(Z).reshape(len(Z), *np.atleast_1d(dimension)[::-1])
|
|
299
|
+
|
|
300
|
+
if full_output:
|
|
301
|
+
return Z, sim_T1, sim_T2
|
|
302
|
+
else:
|
|
303
|
+
return Z
|
|
304
|
+
# ----------------------------------------------------------------------------
|
|
305
|
+
|
|
306
|
+
# ----------------------------------------------------------------------------
|
|
307
|
+
def pluriGaussianSim(cov_model_T1, cov_model_T2, flag_value,
|
|
308
|
+
dimension, spacing=None, origin=None,
|
|
309
|
+
x=None, v=None,
|
|
310
|
+
algo_T1='fft', params_T1={},
|
|
311
|
+
algo_T2='fft', params_T2={},
|
|
312
|
+
accept_init=0.25, accept_pow=2.0,
|
|
313
|
+
mh_iter_min=100, mh_iter_max=200,
|
|
314
|
+
ntry_max=1,
|
|
315
|
+
retrieve_real_anyway=False,
|
|
316
|
+
nreal=1,
|
|
317
|
+
full_output=True,
|
|
318
|
+
verbose=4):
|
|
319
|
+
"""
|
|
320
|
+
Generates (conditional) pluri-Gaussian simulations.
|
|
321
|
+
|
|
322
|
+
The simulated variable Z at a point x is defined as
|
|
323
|
+
|
|
324
|
+
* Z(x) = flag_value(T1(x), T2(x))
|
|
325
|
+
|
|
326
|
+
where
|
|
327
|
+
|
|
328
|
+
* T1, T2 are two multi-Gaussian random fields (latent fields)
|
|
329
|
+
* `flag_value` is a function of two variables defining the final value \
|
|
330
|
+
(given as a "flag")
|
|
331
|
+
|
|
332
|
+
Z and T1, T2 are fields in 1D, 2D or 3D.
|
|
333
|
+
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
cov_model_T1 : :class:`geone.CovModel.CovModel<d>D`
|
|
337
|
+
covariance model for T1, in 1D or 2D or 3D (same space dimension for T1 and T2);
|
|
338
|
+
note: if `algo_T1='deterministic'`, `cov_model_T1` can be `None` (unused)
|
|
339
|
+
|
|
340
|
+
cov_model_T2 : :class:`geone.CovModel.CovModel<d>D`
|
|
341
|
+
covariance model for T2, in 1D or 2D or 3D (same space dimension for T1 and T2);
|
|
342
|
+
note: if `algo_T2='deterministic'`, `cov_model_T2` can be `None` (unused)
|
|
343
|
+
|
|
344
|
+
flag_value : function (`callable`)
|
|
345
|
+
function of tow arguments (xi, yi) that returns the "flag_value" at
|
|
346
|
+
location (xi, yi)
|
|
347
|
+
|
|
348
|
+
dimension : [sequence of] int(s)
|
|
349
|
+
number of cells along each axis, for simulation in:
|
|
350
|
+
|
|
351
|
+
- 1D: `dimension=nx`
|
|
352
|
+
- 2D: `dimension=(nx, ny)`
|
|
353
|
+
- 3D: `dimension=(nx, ny, nz)`
|
|
354
|
+
|
|
355
|
+
spacing : [sequence of] float(s), optional
|
|
356
|
+
cell size along each axis, for simulation in:
|
|
357
|
+
|
|
358
|
+
- 1D: `spacing=sx`
|
|
359
|
+
- 2D: `spacing=(sx, sy)`
|
|
360
|
+
- 3D: `spacing=(sx, sy, sz)`
|
|
361
|
+
|
|
362
|
+
by default (`None`): 1.0 along each axis
|
|
363
|
+
|
|
364
|
+
origin : [sequence of] float(s), optional
|
|
365
|
+
origin of the grid ("corner of the first cell"), for simulation in:
|
|
366
|
+
|
|
367
|
+
- 1D: `origin=ox`
|
|
368
|
+
- 2D: `origin=(ox, oy)`
|
|
369
|
+
- 3D: `origin=(ox, oy, oz)`
|
|
370
|
+
|
|
371
|
+
by default (`None`): 0.0 along each axis
|
|
372
|
+
|
|
373
|
+
x : array-like of floats, optional
|
|
374
|
+
data points locations (float coordinates), for simulation in:
|
|
375
|
+
|
|
376
|
+
- 1D: 1D array-like of floats
|
|
377
|
+
- 2D: 2D array-like of floats of shape (n, 2)
|
|
378
|
+
- 3D: 2D array-like of floats of shape (n, 3)
|
|
379
|
+
|
|
380
|
+
note: if one point (n=1), a float in 1D, a 1D array of shape (2,) in 2D,
|
|
381
|
+
a 1D array of shape (3,) in 3D, is accepted
|
|
382
|
+
|
|
383
|
+
v : 1D array-like of floats, optional
|
|
384
|
+
data values at `x` (`v[i]` is the data value at `x[i]`)
|
|
385
|
+
|
|
386
|
+
algo_T1 : str {'fft', 'classic', 'deterministic'}, default: 'fft'
|
|
387
|
+
defines the algorithm used for T1:
|
|
388
|
+
|
|
389
|
+
- 'fft': algorithm based on circulant embedding and FFT, function \
|
|
390
|
+
called for <d>D (d = 1, 2, or 3): 'geone.grf.grf<d>D'
|
|
391
|
+
- 'classic': "classic" algorithm, based on the resolution of \
|
|
392
|
+
kriging system considered points in a search ellipsoid, function called \
|
|
393
|
+
for <d>D (d = 1, 2, or 3): \
|
|
394
|
+
'geone.geoscalassicinterface.simulate<d>D'
|
|
395
|
+
- 'deterministic': use a deterministic field, given by `param_T1['mean']`
|
|
396
|
+
|
|
397
|
+
algo_T2 : str {'fft', 'classic', 'deterministic'}, default: 'fft'
|
|
398
|
+
defines the algorithm used for T2 (see `algo_T1` for detail)
|
|
399
|
+
|
|
400
|
+
params_T1 : dict
|
|
401
|
+
keyword arguments (additional parameters) to be passed to the function
|
|
402
|
+
that is called (according to `algo_T1` and space dimension) for simulation
|
|
403
|
+
of T1
|
|
404
|
+
|
|
405
|
+
params_T2 : dict
|
|
406
|
+
keyword arguments (additional parameters) to be passed to the function
|
|
407
|
+
that is called (according to `algo_T2` and space dimension) for simulation
|
|
408
|
+
of T2
|
|
409
|
+
|
|
410
|
+
accept_init : float, default: 0.25
|
|
411
|
+
initial acceptation probability
|
|
412
|
+
(see parameters `mh_iter_min`, `mh_iter_max`)
|
|
413
|
+
|
|
414
|
+
accept_pow : float, default: 2.0
|
|
415
|
+
power for computing acceptation probability
|
|
416
|
+
(see parameters `mh_iter_min`, `mh_iter_max`)
|
|
417
|
+
|
|
418
|
+
mh_iter_min : int, default: 100
|
|
419
|
+
see parameter `mh_iter_max`
|
|
420
|
+
|
|
421
|
+
mh_iter_max : int, default: 200
|
|
422
|
+
`mh_iter_min` and `mh_iter_max` are the number of iterations
|
|
423
|
+
(min and max) for Metropolis-Hasting algorithm
|
|
424
|
+
(for conditional simulation) when updating T1 and T2 at conditioning
|
|
425
|
+
locations at iteration `nit` (in 0, ..., `mh_iter_max-1`):
|
|
426
|
+
|
|
427
|
+
* if `nit < mh_iter_min`: for any k:
|
|
428
|
+
- simulate new candidate at `x[k]`: `(T1(x[k]), T2(x[k]))`
|
|
429
|
+
- if `flag_value(T1(x[k]), T2(x[k])=v[k]` (conditioning ok): \
|
|
430
|
+
accept the new candidate
|
|
431
|
+
- else (conditioning not ok): \
|
|
432
|
+
accept the new candidate with probability
|
|
433
|
+
* p = `accept_init * (1 - 1/mh_iter_min)**accept_pow`
|
|
434
|
+
|
|
435
|
+
* if nit >= mh_iter_min:
|
|
436
|
+
- if conditioning ok at every `x[k]`: stop and exit the loop,
|
|
437
|
+
- else: for any k:
|
|
438
|
+
- if conditioning ok at `x[k]`: skip
|
|
439
|
+
- else:
|
|
440
|
+
* simulate new candidate at `x[k]`: `(T1(x[k]), T2(x[k]))`
|
|
441
|
+
* if `flag_value(T1(x[k]), T2(x[k])=v[k]` (conditioning ok): \
|
|
442
|
+
accept the new candidate
|
|
443
|
+
* else (conditioning not ok): \
|
|
444
|
+
reject the new candidate
|
|
445
|
+
|
|
446
|
+
ntry_max : int, default: 1
|
|
447
|
+
number of trial(s) per realization before giving up if something goes
|
|
448
|
+
wrong
|
|
449
|
+
|
|
450
|
+
retrieve_real_anyway : bool, default: False
|
|
451
|
+
if after `ntry_max` trial(s) a conditioning data is not honoured, then
|
|
452
|
+
the realization is:
|
|
453
|
+
|
|
454
|
+
- retrieved, if `retrieve_real_anyway=True`
|
|
455
|
+
- not retrieved (missing realization), if `retrieve_real_anyway=False`
|
|
456
|
+
|
|
457
|
+
nreal : int, default: 1
|
|
458
|
+
number of realization(s)
|
|
459
|
+
|
|
460
|
+
full_output : bool, default: True
|
|
461
|
+
- if `True`: simulation(s) of Z, T1, T2, and `n_cond_ok` are \
|
|
462
|
+
retrieved in output
|
|
463
|
+
- if `False`: simulation(s) of Z only is retrieved in output
|
|
464
|
+
|
|
465
|
+
verbose : int, default: 2
|
|
466
|
+
verbose mode, higher implies more printing (info)
|
|
467
|
+
|
|
468
|
+
Returns
|
|
469
|
+
-------
|
|
470
|
+
Z : ndarray
|
|
471
|
+
array of shape
|
|
472
|
+
|
|
473
|
+
- for 1D: (nreal, nx)
|
|
474
|
+
- for 2D: (nreal, ny, nx)
|
|
475
|
+
- for 3D: (nreal, nz, ny, nx)
|
|
476
|
+
|
|
477
|
+
Z[k] is the k-th realization of Z
|
|
478
|
+
|
|
479
|
+
T1 : ndarray, optional
|
|
480
|
+
array of shape
|
|
481
|
+
|
|
482
|
+
- for 1D: (nreal, nx)
|
|
483
|
+
- for 2D: (nreal, ny, nx)
|
|
484
|
+
- for 3D: (nreal, nz, ny, nx)
|
|
485
|
+
|
|
486
|
+
T1[k] is the k-th realization of T1;
|
|
487
|
+
returned if `full_output=True`
|
|
488
|
+
|
|
489
|
+
T2 : ndarray, optional
|
|
490
|
+
array of shape
|
|
491
|
+
|
|
492
|
+
- for 1D: (nreal, nx)
|
|
493
|
+
- for 2D: (nreal, ny, nx)
|
|
494
|
+
- for 3D: (nreal, nz, ny, nx)
|
|
495
|
+
|
|
496
|
+
T2[k] is the k-th realization of T2;
|
|
497
|
+
returned if `full_output=True`
|
|
498
|
+
|
|
499
|
+
n_cond_ok : list of 1D array
|
|
500
|
+
list of length `nreal`
|
|
501
|
+
|
|
502
|
+
- n_cond_ok[k]: 1D array of ints
|
|
503
|
+
number of conditioning locations honoured at each iteration of the
|
|
504
|
+
Metropolis-Hasting algorithm for the k-th realization, in particular
|
|
505
|
+
`len(n_cond_ok[k])` is the number of iteration done,
|
|
506
|
+
`n_cond_ok[k][-1]` is the number of conditioning locations honoured
|
|
507
|
+
at the end;
|
|
508
|
+
|
|
509
|
+
returned if `full_output=True`
|
|
510
|
+
"""
|
|
511
|
+
fname = 'pluriGaussianSim'
|
|
512
|
+
|
|
513
|
+
if full_output:
|
|
514
|
+
out = None, None, None, None
|
|
515
|
+
else:
|
|
516
|
+
out = None
|
|
517
|
+
|
|
518
|
+
if not callable(flag_value):
|
|
519
|
+
if verbose > 0:
|
|
520
|
+
print(f"ERROR ({fname}): `flag_value` invalid, should be a function (callable) of two arguments")
|
|
521
|
+
return out
|
|
522
|
+
|
|
523
|
+
if algo_T1 not in ('fft', 'FFT', 'classic', 'CLASSIC', 'deterministic', 'DETERMINISTIC'):
|
|
524
|
+
if verbose > 0:
|
|
525
|
+
print(f"ERROR ({fname}): `algo_T1` invalid, should be 'fft' (default) or 'classic' or 'deterministic'")
|
|
526
|
+
return out
|
|
527
|
+
|
|
528
|
+
if algo_T2 not in ('fft', 'FFT', 'classic', 'CLASSIC', 'deterministic', 'DETERMINISTIC'):
|
|
529
|
+
if verbose > 0:
|
|
530
|
+
print(f"ERROR ({fname}): `algo_T2` invalid, should be 'fft' (default) or 'classic' or 'deterministic'")
|
|
531
|
+
return out
|
|
532
|
+
|
|
533
|
+
# Ignore covariance model if 'algo' is deterministic for T1, T2
|
|
534
|
+
if algo_T1 in ('deterministic', 'DETERMINISTIC'):
|
|
535
|
+
cov_model_T1 = None
|
|
536
|
+
|
|
537
|
+
if algo_T2 in ('deterministic', 'DETERMINISTIC'):
|
|
538
|
+
cov_model_T2 = None
|
|
539
|
+
|
|
540
|
+
# Set space dimension (of grid) according to covariance model for T1
|
|
541
|
+
d = 0
|
|
542
|
+
if cov_model_T1 is None:
|
|
543
|
+
if algo_T1 not in ('deterministic', 'DETERMINISTIC'):
|
|
544
|
+
if verbose > 0:
|
|
545
|
+
print(f"ERROR ({fname}): `cov_model_T1` is None, then `algo_T1` must be 'deterministic'")
|
|
546
|
+
return out
|
|
547
|
+
elif isinstance(cov_model_T1, gcm.CovModel1D):
|
|
548
|
+
d = 1
|
|
549
|
+
elif isinstance(cov_model_T1, gcm.CovModel2D):
|
|
550
|
+
d = 2
|
|
551
|
+
elif isinstance(cov_model_T1, gcm.CovModel3D):
|
|
552
|
+
d = 3
|
|
553
|
+
else:
|
|
554
|
+
if verbose > 0:
|
|
555
|
+
print(f"ERROR ({fname}): `cov_model_T1` invalid, should be a class: <geone.covModel.CovModel1D>, <geone.covModel.CovModel2D>, or <geone.covModel.CovModel3D>")
|
|
556
|
+
return out
|
|
557
|
+
|
|
558
|
+
if cov_model_T2 is None:
|
|
559
|
+
if algo_T2 not in ('deterministic', 'DETERMINISTIC'):
|
|
560
|
+
if verbose > 0:
|
|
561
|
+
print(f"ERROR ({fname}): `cov_model_T2` is None, then `algo_T2` must be 'deterministic'")
|
|
562
|
+
return out
|
|
563
|
+
# if d == 0:
|
|
564
|
+
# if verbose > 0:
|
|
565
|
+
# print(f"ERROR ({fname}): `cov_model_T1` and `cov_model_T2` are None, at least one covariance model is required")
|
|
566
|
+
# return out
|
|
567
|
+
elif (d == 1 and not isinstance(cov_model_T2, gcm.CovModel1D)) or (d == 2 and not isinstance(cov_model_T2, gcm.CovModel2D)) or (d == 3 and not isinstance(cov_model_T2, gcm.CovModel3D)):
|
|
568
|
+
if verbose > 0:
|
|
569
|
+
print(f"ERROR ({fname}): `cov_model_T1` and `cov_model_T2` not compatible (dimension differs)")
|
|
570
|
+
return out
|
|
571
|
+
|
|
572
|
+
if d == 0:
|
|
573
|
+
# Set space dimension (of grid) according to 'dimension'
|
|
574
|
+
if hasattr(dimension, '__len__'):
|
|
575
|
+
d = len(dimension)
|
|
576
|
+
else:
|
|
577
|
+
d = 1
|
|
578
|
+
|
|
579
|
+
# Check argument 'dimension'
|
|
580
|
+
if hasattr(dimension, '__len__') and len(dimension) != d:
|
|
581
|
+
if verbose > 0:
|
|
582
|
+
print(f"ERROR ({fname}): `dimension` of incompatible length")
|
|
583
|
+
return out
|
|
584
|
+
|
|
585
|
+
if d == 1:
|
|
586
|
+
grid_size = dimension
|
|
587
|
+
else:
|
|
588
|
+
grid_size = np.prod(dimension)
|
|
589
|
+
|
|
590
|
+
# Check (or set) argument 'spacing'
|
|
591
|
+
if spacing is None:
|
|
592
|
+
if d == 1:
|
|
593
|
+
spacing = 1.0
|
|
594
|
+
else:
|
|
595
|
+
spacing = tuple(np.ones(d))
|
|
596
|
+
else:
|
|
597
|
+
if hasattr(spacing, '__len__') and len(spacing) != d:
|
|
598
|
+
if verbose > 0:
|
|
599
|
+
print(f"ERROR ({fname}): `spacing` of incompatible length")
|
|
600
|
+
return out
|
|
601
|
+
|
|
602
|
+
# Check (or set) argument 'origin'
|
|
603
|
+
if origin is None:
|
|
604
|
+
if d == 1:
|
|
605
|
+
origin = 0.0
|
|
606
|
+
else:
|
|
607
|
+
origin = tuple(np.zeros(d))
|
|
608
|
+
else:
|
|
609
|
+
if hasattr(origin, '__len__') and len(origin) != d:
|
|
610
|
+
if verbose > 0:
|
|
611
|
+
print(f"ERROR ({fname}): `origin` of incompatible length")
|
|
612
|
+
return out
|
|
613
|
+
|
|
614
|
+
# if not cov_model_T1.is_stationary(): # prevent calculation if covariance model is not stationary
|
|
615
|
+
# if verbose > 0:
|
|
616
|
+
# print(f"ERROR ({fname}): `cov_model_T1` is not stationary")
|
|
617
|
+
|
|
618
|
+
# if not cov_model_T2.is_stationary(): # prevent calculation if covariance model is not stationary
|
|
619
|
+
# if verbose > 0:
|
|
620
|
+
# print(f"ERROR ({fname}): `cov_model_T2` is not stationary")
|
|
621
|
+
|
|
622
|
+
# Compute meshgrid over simulation domain if needed (see below)
|
|
623
|
+
if ('mean' in params_T1.keys() and callable(params_T1['mean'])) or ('var' in params_T1.keys() and callable(params_T1['var'])) \
|
|
624
|
+
or ('mean' in params_T2.keys() and callable(params_T2['mean'])) or ('var' in params_T2.keys() and callable(params_T2['var'])):
|
|
625
|
+
if d == 1:
|
|
626
|
+
xi = origin + spacing*(0.5+np.arange(dimension)) # x-coordinate of cell center
|
|
627
|
+
elif d == 2:
|
|
628
|
+
xi = origin[0] + spacing[0]*(0.5+np.arange(dimension[0])) # x-coordinate of cell center
|
|
629
|
+
yi = origin[1] + spacing[1]*(0.5+np.arange(dimension[1])) # y-coordinate of cell center
|
|
630
|
+
yyi, xxi = np.meshgrid(yi, xi, indexing='ij')
|
|
631
|
+
elif d == 3:
|
|
632
|
+
xi = origin[0] + spacing[0]*(0.5+np.arange(dimension[0])) # x-coordinate of cell center
|
|
633
|
+
yi = origin[1] + spacing[1]*(0.5+np.arange(dimension[1])) # y-coordinate of cell center
|
|
634
|
+
zi = origin[2] + spacing[2]*(0.5+np.arange(dimension[2])) # z-coordinate of cell center
|
|
635
|
+
zzi, yyi, xxi = np.meshgrid(zi, yi, xi, indexing='ij')
|
|
636
|
+
|
|
637
|
+
# Set mean_T1 (as array) from params_T1
|
|
638
|
+
if 'mean' not in params_T1.keys():
|
|
639
|
+
mean_T1 = np.array([0.0])
|
|
640
|
+
else:
|
|
641
|
+
mean_T1 = params_T1['mean']
|
|
642
|
+
if mean_T1 is None:
|
|
643
|
+
mean_T1 = np.array([0.0])
|
|
644
|
+
elif callable(mean_T1):
|
|
645
|
+
if d == 1:
|
|
646
|
+
mean_T1 = mean_T1(xi).reshape(-1) # replace function 'mean_T1' by its evaluation on the grid
|
|
647
|
+
elif d == 2:
|
|
648
|
+
mean_T1 = mean_T1(xxi, yyi).reshape(-1) # replace function 'mean_T1' by its evaluation on the grid
|
|
649
|
+
elif d == 3:
|
|
650
|
+
mean_T1 = mean_T1(xxi, yyi, zzi).reshape(-1) # replace function 'mean_T1' by its evaluation on the grid
|
|
651
|
+
else:
|
|
652
|
+
mean_T1 = np.asarray(mean_T1).reshape(-1)
|
|
653
|
+
if mean_T1.size not in (1, grid_size):
|
|
654
|
+
if verbose > 0:
|
|
655
|
+
print(f"ERROR ({fname}): 'mean' parameter for T1 (in `params_T1`) has incompatible size")
|
|
656
|
+
return out
|
|
657
|
+
|
|
658
|
+
# Set var_T1 (as array) from params_T1, if given
|
|
659
|
+
var_T1 = None
|
|
660
|
+
if 'var' in params_T1.keys():
|
|
661
|
+
var_T1 = params_T1['var']
|
|
662
|
+
if var_T1 is not None:
|
|
663
|
+
if callable(var_T1):
|
|
664
|
+
if d == 1:
|
|
665
|
+
var_T1 = var_T1(xi).reshape(-1) # replace function 'var_T1' by its evaluation on the grid
|
|
666
|
+
elif d == 2:
|
|
667
|
+
var_T1 = var_T1(xxi, yyi).reshape(-1) # replace function 'var_T1' by its evaluation on the grid
|
|
668
|
+
elif d == 3:
|
|
669
|
+
var_T1 = var_T1(xxi, yyi, zzi).reshape(-1) # replace function 'var_T1' by its evaluation on the grid
|
|
670
|
+
else:
|
|
671
|
+
var_T1 = np.asarray(var_T1).reshape(-1)
|
|
672
|
+
if var_T1.size not in (1, grid_size):
|
|
673
|
+
if verbose > 0:
|
|
674
|
+
print(f"ERROR ({fname}): 'var' parameter for T1 (in `params_T1`) has incompatible size")
|
|
675
|
+
return out
|
|
676
|
+
|
|
677
|
+
# Set mean_T2 (as array) from params_T2
|
|
678
|
+
if 'mean' not in params_T2.keys():
|
|
679
|
+
mean_T2 = np.array([0.0])
|
|
680
|
+
else:
|
|
681
|
+
mean_T2 = params_T2['mean']
|
|
682
|
+
if mean_T2 is None:
|
|
683
|
+
mean_T2 = np.array([0.0])
|
|
684
|
+
elif callable(mean_T2):
|
|
685
|
+
if d == 1:
|
|
686
|
+
mean_T2 = mean_T2(xi).reshape(-1) # replace function 'mean_T2' by its evaluation on the grid
|
|
687
|
+
elif d == 2:
|
|
688
|
+
mean_T2 = mean_T2(xxi, yyi).reshape(-1) # replace function 'mean_T2' by its evaluation on the grid
|
|
689
|
+
elif d == 3:
|
|
690
|
+
mean_T2 = mean_T2(xxi, yyi, zzi).reshape(-1) # replace function 'mean_T2' by its evaluation on the grid
|
|
691
|
+
else:
|
|
692
|
+
mean_T2 = np.asarray(mean_T2).reshape(-1)
|
|
693
|
+
if mean_T2.size not in (1, grid_size):
|
|
694
|
+
if verbose > 0:
|
|
695
|
+
print(f"ERROR ({fname}): 'mean' parameter for T2 (in `params_T2`) has incompatible size")
|
|
696
|
+
return out
|
|
697
|
+
|
|
698
|
+
# Set var_T2 (as array) from params_T2, if given
|
|
699
|
+
var_T2 = None
|
|
700
|
+
if 'var' in params_T2.keys():
|
|
701
|
+
var_T2 = params_T2['var']
|
|
702
|
+
if var_T2 is not None:
|
|
703
|
+
if callable(var_T2):
|
|
704
|
+
if d == 1:
|
|
705
|
+
var_T2 = var_T2(xi).reshape(-1) # replace function 'var_T2' by its evaluation on the grid
|
|
706
|
+
elif d == 2:
|
|
707
|
+
var_T2 = var_T2(xxi, yyi).reshape(-1) # replace function 'var_T2' by its evaluation on the grid
|
|
708
|
+
elif d == 3:
|
|
709
|
+
var_T2 = var_T2(xxi, yyi, zzi).reshape(-1) # replace function 'var_T2' by its evaluation on the grid
|
|
710
|
+
else:
|
|
711
|
+
var_T2 = np.asarray(var_T2).reshape(-1)
|
|
712
|
+
if var_T2.size not in (1, grid_size):
|
|
713
|
+
if verbose > 0:
|
|
714
|
+
print(f"ERROR ({fname}): 'var' parameter for T2 (in `params_T2`) has incompatible size")
|
|
715
|
+
return out
|
|
716
|
+
|
|
717
|
+
# Note: format of data (x, v) not checked !
|
|
718
|
+
|
|
719
|
+
if x is None:
|
|
720
|
+
if v is not None:
|
|
721
|
+
if verbose > 0:
|
|
722
|
+
print(f"ERROR ({fname}): `x` is not given (None) but `v` is given (not None)")
|
|
723
|
+
return out
|
|
724
|
+
#
|
|
725
|
+
else:
|
|
726
|
+
# Preparation for conditional case
|
|
727
|
+
if v is None:
|
|
728
|
+
if verbose > 0:
|
|
729
|
+
print(f"ERROR ({fname}): `x` is given (not None) but `v` is not given (None)")
|
|
730
|
+
return out
|
|
731
|
+
#
|
|
732
|
+
x = np.asarray(x, dtype='float').reshape(-1, d) # cast in d-dimensional array if needed
|
|
733
|
+
v = np.asarray(v, dtype='float').reshape(-1) # cast in 1-dimensional array if needed
|
|
734
|
+
if len(v) != x.shape[0]:
|
|
735
|
+
if verbose > 0:
|
|
736
|
+
print(f"ERROR ({fname}): length of `v` is not valid")
|
|
737
|
+
return out
|
|
738
|
+
#
|
|
739
|
+
# Compute
|
|
740
|
+
# indc: node index of conditioning node (nearest node),
|
|
741
|
+
# rounded to lower index if between two grid node and index is positive
|
|
742
|
+
indc_f = (x-origin)/spacing
|
|
743
|
+
indc = indc_f.astype(int)
|
|
744
|
+
indc = indc - 1 * np.all((indc == indc_f, indc > 0), axis=0)
|
|
745
|
+
if d == 1:
|
|
746
|
+
indc = 1 * indc[:, 0] # multiply by 1.0 makes a copy of the array !
|
|
747
|
+
elif d == 2:
|
|
748
|
+
indc = indc[:, 0] + dimension[0] * indc[:, 1]
|
|
749
|
+
elif d == 3:
|
|
750
|
+
indc = indc[:, 0] + dimension[0] * (indc[:, 1] + dimension[1] * indc[:, 2])
|
|
751
|
+
indc_unique, indc_inv = np.unique(indc, return_inverse=True)
|
|
752
|
+
if len(indc_unique) != len(x):
|
|
753
|
+
if np.any([len(np.unique(v[indc_inv==j])) > 1 for j in range(len(indc_unique))]):
|
|
754
|
+
if verbose > 0:
|
|
755
|
+
print(f'ERROR ({fname}): more than one conditioning point fall in a same grid cell and have different conditioning values')
|
|
756
|
+
return out
|
|
757
|
+
else:
|
|
758
|
+
if verbose > 1:
|
|
759
|
+
print(f'WARNING ({fname}): more than one conditioning point fall in a same grid cell with same conditioning value (consistent)')
|
|
760
|
+
x = np.array([x[indc_inv==j][0] for j in range(len(indc_unique))])
|
|
761
|
+
v = np.array([v[indc_inv==j][0] for j in range(len(indc_unique))])
|
|
762
|
+
#
|
|
763
|
+
# Number of conditioning points
|
|
764
|
+
npt = x.shape[0]
|
|
765
|
+
#
|
|
766
|
+
# Get index in mean_T1 for each conditioning point
|
|
767
|
+
x_mean_T1_grid_ind = None
|
|
768
|
+
if mean_T1.size == 1:
|
|
769
|
+
x_mean_T1_grid_ind = np.zeros(npt, dtype='int')
|
|
770
|
+
else:
|
|
771
|
+
indc_f = (x-origin)/spacing
|
|
772
|
+
indc = indc_f.astype(int)
|
|
773
|
+
indc = indc - 1 * np.all((indc == indc_f, indc > 0), axis=0)
|
|
774
|
+
if d == 1:
|
|
775
|
+
x_mean_T1_grid_ind = 1 * indc[:, 0] # multiply by 1.0 makes a copy of the array !
|
|
776
|
+
elif d == 2:
|
|
777
|
+
x_mean_T1_grid_ind = indc[:, 0] + dimension[0] * indc[:, 1]
|
|
778
|
+
elif d == 3:
|
|
779
|
+
x_mean_T1_grid_ind = indc[:, 0] + dimension[0] * (indc[:, 1] + dimension[1] * indc[:, 2])
|
|
780
|
+
#
|
|
781
|
+
# Get index in var_T1 (if not None) for each conditioning point
|
|
782
|
+
if var_T1 is not None:
|
|
783
|
+
if var_T1.size == 1:
|
|
784
|
+
x_var_T1_grid_ind = np.zeros(npt, dtype='int')
|
|
785
|
+
else:
|
|
786
|
+
if x_mean_T1_grid_ind is not None:
|
|
787
|
+
x_var_T1_grid_ind = x_mean_T1_grid_ind
|
|
788
|
+
else:
|
|
789
|
+
indc_f = (x-origin)/spacing
|
|
790
|
+
indc = indc_f.astype(int)
|
|
791
|
+
indc = indc - 1 * np.all((indc == indc_f, indc > 0), axis=0)
|
|
792
|
+
if d == 1:
|
|
793
|
+
x_var_T1_grid_ind = 1 * indc[:, 0] # multiply by 1.0 makes a copy of the array !
|
|
794
|
+
elif d == 2:
|
|
795
|
+
x_var_T1_grid_ind = indc[:, 0] + dimension[0] * indc[:, 1]
|
|
796
|
+
elif d == 3:
|
|
797
|
+
x_var_T1_grid_ind = indc[:, 0] + dimension[0] * (indc[:, 1] + dimension[1] * indc[:, 2])
|
|
798
|
+
#
|
|
799
|
+
# Get index in mean_T2 for each conditioning point
|
|
800
|
+
x_mean_T2_grid_ind = None
|
|
801
|
+
if mean_T2.size == 1:
|
|
802
|
+
x_mean_T2_grid_ind = np.zeros(npt, dtype='int')
|
|
803
|
+
else:
|
|
804
|
+
indc_f = (x-origin)/spacing
|
|
805
|
+
indc = indc_f.astype(int)
|
|
806
|
+
indc = indc - 1 * np.all((indc == indc_f, indc > 0), axis=0)
|
|
807
|
+
if d == 1:
|
|
808
|
+
x_mean_T2_grid_ind = 1 * indc[:, 0] # multiply by 1.0 makes a copy of the array !
|
|
809
|
+
elif d == 2:
|
|
810
|
+
x_mean_T2_grid_ind = indc[:, 0] + dimension[0] * indc[:, 1]
|
|
811
|
+
elif d == 3:
|
|
812
|
+
x_mean_T2_grid_ind = indc[:, 0] + dimension[0] * (indc[:, 1] + dimension[1] * indc[:, 2])
|
|
813
|
+
#
|
|
814
|
+
# Get index in var_T2 (if not None) for each conditioning point
|
|
815
|
+
if var_T2 is not None:
|
|
816
|
+
if var_T2.size == 1:
|
|
817
|
+
x_var_T2_grid_ind = np.zeros(npt, dtype='int')
|
|
818
|
+
else:
|
|
819
|
+
if x_mean_T2_grid_ind is not None:
|
|
820
|
+
x_var_T2_grid_ind = x_mean_T2_grid_ind
|
|
821
|
+
else:
|
|
822
|
+
indc_f = (x-origin)/spacing
|
|
823
|
+
indc = indc_f.astype(int)
|
|
824
|
+
indc = indc - 1 * np.all((indc == indc_f, indc > 0), axis=0)
|
|
825
|
+
if d == 1:
|
|
826
|
+
x_var_T2_grid_ind = 1 * indc[:, 0] # multiply by 1.0 makes a copy of the array !
|
|
827
|
+
elif d == 2:
|
|
828
|
+
x_var_T2_grid_ind = indc[:, 0] + dimension[0] * indc[:, 1]
|
|
829
|
+
elif d == 3:
|
|
830
|
+
x_var_T2_grid_ind = indc[:, 0] + dimension[0] * (indc[:, 1] + dimension[1] * indc[:, 2])
|
|
831
|
+
#
|
|
832
|
+
# Get covariance function for T1, T2 and Y, and their evaluation at 0
|
|
833
|
+
if cov_model_T1 is not None:
|
|
834
|
+
cov_func_T1 = cov_model_T1.func() # covariance function
|
|
835
|
+
cov0_T1 = cov_func_T1(np.zeros(d))
|
|
836
|
+
if cov_model_T2 is not None:
|
|
837
|
+
cov_func_T2 = cov_model_T2.func() # covariance function
|
|
838
|
+
cov0_T2 = cov_func_T2(np.zeros(d))
|
|
839
|
+
#
|
|
840
|
+
if cov_model_T1 is not None:
|
|
841
|
+
# Set kriging matrix for T1 (mat_T1) of order npt, "over every conditioining point"
|
|
842
|
+
mat_T1 = np.ones((npt, npt))
|
|
843
|
+
for i in range(npt-1):
|
|
844
|
+
# lag between x[i] and x[j], j=i+1, ..., npt-1
|
|
845
|
+
h = x[(i+1):] - x[i]
|
|
846
|
+
cov_h_T1 = cov_func_T1(h)
|
|
847
|
+
mat_T1[i, (i+1):npt] = cov_h_T1
|
|
848
|
+
mat_T1[(i+1):npt, i] = cov_h_T1
|
|
849
|
+
mat_T1[i, i] = cov0_T1
|
|
850
|
+
#
|
|
851
|
+
mat_T1[-1,-1] = cov0_T1
|
|
852
|
+
#
|
|
853
|
+
if var_T1 is not None:
|
|
854
|
+
varUpdate = np.sqrt(var_T1[x_var_T1_grid_ind]/cov0_T1)
|
|
855
|
+
mat_T1 = varUpdate*(mat_T1.T*varUpdate).T
|
|
856
|
+
#
|
|
857
|
+
if cov_model_T2 is not None:
|
|
858
|
+
# Set kriging matrix for T2 (mat_T2) of order npt, "over every conditioining point"
|
|
859
|
+
mat_T2 = np.ones((npt, npt))
|
|
860
|
+
for i in range(npt-1):
|
|
861
|
+
# lag between x[i] and x[j], j=i+1, ..., npt-1
|
|
862
|
+
h = x[(i+1):] - x[i]
|
|
863
|
+
cov_h_T2 = cov_func_T2(h)
|
|
864
|
+
mat_T2[i, (i+1):npt] = cov_h_T2
|
|
865
|
+
mat_T2[(i+1):npt, i] = cov_h_T2
|
|
866
|
+
mat_T2[i, i] = cov0_T2
|
|
867
|
+
#
|
|
868
|
+
mat_T2[-1,-1] = cov0_T2
|
|
869
|
+
#
|
|
870
|
+
if var_T2 is not None:
|
|
871
|
+
varUpdate = np.sqrt(var_T2[x_var_T2_grid_ind]/cov0_T2)
|
|
872
|
+
mat_T2 = varUpdate*(mat_T2.T*varUpdate).T
|
|
873
|
+
|
|
874
|
+
# Set (again if given) default parameter 'mean' and 'var' for T1, T2
|
|
875
|
+
if cov_model_T1 is not None:
|
|
876
|
+
params_T1['mean'] = mean_T1
|
|
877
|
+
params_T1['var'] = var_T1
|
|
878
|
+
else:
|
|
879
|
+
if mean_T1.size == grid_size:
|
|
880
|
+
params_T1['mean'] = mean_T1.reshape(*dimension[::-1])
|
|
881
|
+
else:
|
|
882
|
+
params_T1['mean'] = mean_T1 * np.ones(dimension[::-1])
|
|
883
|
+
if cov_model_T2 is not None:
|
|
884
|
+
params_T2['mean'] = mean_T2
|
|
885
|
+
params_T2['var'] = var_T2
|
|
886
|
+
else:
|
|
887
|
+
if mean_T2.size == grid_size:
|
|
888
|
+
params_T2['mean'] = mean_T2.reshape(*dimension[::-1])
|
|
889
|
+
else:
|
|
890
|
+
params_T2['mean'] = mean_T2 * np.ones(dimension[::-1])
|
|
891
|
+
|
|
892
|
+
# Set default parameter 'verbose' for params_T1, params_T2
|
|
893
|
+
if 'verbose' not in params_T1.keys():
|
|
894
|
+
params_T1['verbose'] = 0
|
|
895
|
+
if 'verbose' not in params_T2.keys():
|
|
896
|
+
params_T2['verbose'] = 0
|
|
897
|
+
|
|
898
|
+
# Initialization for output
|
|
899
|
+
Z = []
|
|
900
|
+
if full_output:
|
|
901
|
+
T1 = []
|
|
902
|
+
T2 = []
|
|
903
|
+
n_cond_ok = []
|
|
904
|
+
|
|
905
|
+
for ireal in range(nreal):
|
|
906
|
+
# Generate ireal-th realization
|
|
907
|
+
if verbose > 2:
|
|
908
|
+
print('PLURIGAUSSIANSIM: simulation {} of {}...'.format(ireal+1, nreal))
|
|
909
|
+
for ntry in range(ntry_max):
|
|
910
|
+
sim_ok = True
|
|
911
|
+
nhd_ok = [] # to be appended for full output...
|
|
912
|
+
if verbose > 3 and ntry > 0:
|
|
913
|
+
print(' ... new trial ({} of {}) for simulation {} of {}...'.format(ntry+1, ntry_max, ireal+1, nreal))
|
|
914
|
+
if x is None:
|
|
915
|
+
# Unconditional case
|
|
916
|
+
# ------------------
|
|
917
|
+
# Generate T1 (one real)
|
|
918
|
+
if cov_model_T1 is not None:
|
|
919
|
+
sim_T1 = multiGaussian.multiGaussianRun(cov_model_T1, dimension, spacing, origin,
|
|
920
|
+
mode='simulation', algo=algo_T1, output_mode='array',
|
|
921
|
+
**params_T1, nreal=1)
|
|
922
|
+
else:
|
|
923
|
+
sim_T1 = params_T1['mean'].reshape(1,*dimension[::-1])
|
|
924
|
+
# -> sim_T1: nd-array of shape
|
|
925
|
+
# (1, dimension) (for T1 in 1D)
|
|
926
|
+
# (1, dimension[1], dimension[0]) (for T1 in 2D)
|
|
927
|
+
# (1, dimension[2], dimension[1], dimension[0]) (for T1 in 3D)
|
|
928
|
+
if sim_T1 is None:
|
|
929
|
+
sim_ok = False
|
|
930
|
+
if verbose > 3:
|
|
931
|
+
print(' ... simulation of T1 failed')
|
|
932
|
+
continue
|
|
933
|
+
#
|
|
934
|
+
# Generate T2 (one real)
|
|
935
|
+
if cov_model_T2 is not None:
|
|
936
|
+
sim_T2 = multiGaussian.multiGaussianRun(cov_model_T2, dimension, spacing, origin,
|
|
937
|
+
mode='simulation', algo=algo_T2, output_mode='array',
|
|
938
|
+
**params_T2, nreal=1)
|
|
939
|
+
else:
|
|
940
|
+
sim_T2 = params_T2['mean'].reshape(1,*dimension[::-1])
|
|
941
|
+
# -> sim_T2: nd-array of shape
|
|
942
|
+
# (1, dimension) (for T2 in 1D)
|
|
943
|
+
# (1, dimension[1], dimension[0]) (for T2 in 2D)
|
|
944
|
+
# (1, dimension[2], dimension[1], dimension[0]) (for T2 in 3D)
|
|
945
|
+
if sim_T2 is None:
|
|
946
|
+
sim_ok = False
|
|
947
|
+
if verbose > 3:
|
|
948
|
+
print(' ... simulation of T2 failed')
|
|
949
|
+
continue
|
|
950
|
+
#
|
|
951
|
+
else:
|
|
952
|
+
# Conditional case
|
|
953
|
+
# ----------------
|
|
954
|
+
v_T = np.zeros((npt, 2))
|
|
955
|
+
# Initialize: unconditional simulation of T1 at x (values in v_T[:,0])
|
|
956
|
+
ind = np.random.permutation(npt)
|
|
957
|
+
for j, k in enumerate(ind):
|
|
958
|
+
if cov_model_T1 is not None:
|
|
959
|
+
# Simulate value at x[k] (= x[ind[j]]), conditionally to the previous ones
|
|
960
|
+
# Solve the kriging system (for T1)
|
|
961
|
+
try:
|
|
962
|
+
w = np.linalg.solve(
|
|
963
|
+
mat_T1[ind[:j], :][:, ind[:j]], # kriging matrix
|
|
964
|
+
mat_T1[ind[:j], ind[j]], # second member
|
|
965
|
+
)
|
|
966
|
+
except:
|
|
967
|
+
sim_ok = False
|
|
968
|
+
break
|
|
969
|
+
|
|
970
|
+
# Mean (kriged) value at x[k]
|
|
971
|
+
mu_T1_k = mean_T1[x_mean_T1_grid_ind[k]] + (v_T[ind[:j], 0] - mean_T1[x_mean_T1_grid_ind[ind[:j]]]).dot(w)
|
|
972
|
+
# Standard deviation (of kriging) at x[k]
|
|
973
|
+
std_T1_k = np.sqrt(np.maximum(0, cov0_T1 - np.dot(w, mat_T1[ind[:j], ind[j]])))
|
|
974
|
+
# Draw value in N(mu_T1_k, std_T1_k^2)
|
|
975
|
+
v_T[k, 0] = np.random.normal(loc=mu_T1_k, scale=std_T1_k)
|
|
976
|
+
else:
|
|
977
|
+
v_T[k, 0] = mean_T1[x_mean_T1_grid_ind[k]]
|
|
978
|
+
|
|
979
|
+
if not sim_ok:
|
|
980
|
+
sim_ok = False
|
|
981
|
+
if verbose > 3:
|
|
982
|
+
print(' ... unable to solve kriging system (for T1, initialization)')
|
|
983
|
+
continue
|
|
984
|
+
|
|
985
|
+
# Initialize: unconditional simulation of T2 at x (values in v_T[:,1])
|
|
986
|
+
ind = np.random.permutation(npt)
|
|
987
|
+
for j, k in enumerate(ind):
|
|
988
|
+
if cov_model_T2 is not None:
|
|
989
|
+
# Simulate value at x[k] (= x[ind[j]]), conditionally to the previous ones
|
|
990
|
+
# Solve the kriging system (for T2)
|
|
991
|
+
try:
|
|
992
|
+
w = np.linalg.solve(
|
|
993
|
+
mat_T2[ind[:j], :][:, ind[:j]], # kriging matrix
|
|
994
|
+
mat_T2[ind[:j], ind[j]], # second member
|
|
995
|
+
)
|
|
996
|
+
except:
|
|
997
|
+
sim_ok = False
|
|
998
|
+
break
|
|
999
|
+
|
|
1000
|
+
# Mean (kriged) value at x[k]
|
|
1001
|
+
mu_T2_k = mean_T2[x_mean_T2_grid_ind[k]] + (v_T[ind[:j], 1] - mean_T2[x_mean_T2_grid_ind[ind[:j]]]).dot(w)
|
|
1002
|
+
# Standard deviation (of kriging) at x[k]
|
|
1003
|
+
std_T2_k = np.sqrt(np.maximum(0, cov0_T2 - np.dot(w, mat_T2[ind[:j], ind[j]])))
|
|
1004
|
+
# Draw value in N(mu_T2_k, std_T2_k^2)
|
|
1005
|
+
v_T[k, 1] = np.random.normal(loc=mu_T2_k, scale=std_T2_k)
|
|
1006
|
+
else:
|
|
1007
|
+
v_T[k, 1] = mean_T2[x_mean_T2_grid_ind[k]]
|
|
1008
|
+
|
|
1009
|
+
if not sim_ok:
|
|
1010
|
+
sim_ok = False
|
|
1011
|
+
if verbose > 3:
|
|
1012
|
+
print(' ... unable to solve kriging system (for T2, initialization)')
|
|
1013
|
+
continue
|
|
1014
|
+
|
|
1015
|
+
# Update simulated values v_T at x using Metropolis-Hasting (MH) algorithm
|
|
1016
|
+
v_T_k_new = np.zeros(2)
|
|
1017
|
+
stop_mh = False
|
|
1018
|
+
for nit in range(mh_iter_max):
|
|
1019
|
+
#hd_ok = np.array([flag_value(v_T[k, 0], v_T[k, 1]) == v[k] for k in range(npt)])
|
|
1020
|
+
hd_ok = flag_value(v_T[:, 0], v_T[:, 1]) == v
|
|
1021
|
+
nhd_ok.append(np.sum(hd_ok))
|
|
1022
|
+
if nit >= mh_iter_min:
|
|
1023
|
+
if nhd_ok[-1] == npt:
|
|
1024
|
+
stop_mh = True
|
|
1025
|
+
break
|
|
1026
|
+
else:
|
|
1027
|
+
# Set acceptation probability for bad case
|
|
1028
|
+
p_accept = accept_init * np.power(1.0 - nit/mh_iter_min, accept_pow)
|
|
1029
|
+
if verbose > 4:
|
|
1030
|
+
print(' ... sim {} of {}: MH iter {} of {}, {}...'.format(ireal+1, nreal, nit+1, mh_iter_min, mh_iter_max))
|
|
1031
|
+
ind = np.random.permutation(npt)
|
|
1032
|
+
for k in ind:
|
|
1033
|
+
if nit >= mh_iter_min and hd_ok[k]:
|
|
1034
|
+
#print('skip')
|
|
1035
|
+
continue
|
|
1036
|
+
#
|
|
1037
|
+
# Sequence of indexes without k
|
|
1038
|
+
indmat = np.hstack((np.arange(k), np.arange(k+1, npt)))
|
|
1039
|
+
# Simulate possible new value v_T_new at x[k], conditionally to all the ohter ones
|
|
1040
|
+
#
|
|
1041
|
+
if cov_model_T1 is not None:
|
|
1042
|
+
# Solve the kriging system for T1
|
|
1043
|
+
try:
|
|
1044
|
+
w = np.linalg.solve(
|
|
1045
|
+
mat_T1[indmat, :][:, indmat], # kriging matrix
|
|
1046
|
+
mat_T1[indmat, k], # second member
|
|
1047
|
+
)
|
|
1048
|
+
except:
|
|
1049
|
+
sim_ok = False
|
|
1050
|
+
if verbose > 3:
|
|
1051
|
+
print(' ... unable to solve kriging system (for T1)')
|
|
1052
|
+
break
|
|
1053
|
+
#
|
|
1054
|
+
# Mean (kriged) value at x[k]
|
|
1055
|
+
mu_T1_k = mean_T1[x_mean_T1_grid_ind[k]] + (v_T[indmat, 0] - mean_T1[x_mean_T1_grid_ind[indmat]]).dot(w)
|
|
1056
|
+
# Standard deviation (of kriging) at x[k]
|
|
1057
|
+
std_T1_k = np.sqrt(np.maximum(0, cov0_T1 - np.dot(w, mat_T1[indmat, k])))
|
|
1058
|
+
# Draw value in N(mu, std^2)
|
|
1059
|
+
v_T_k_new[0] = np.random.normal(loc=mu_T1_k, scale=std_T1_k)
|
|
1060
|
+
else:
|
|
1061
|
+
v_T_k_new[0] = mean_T1[x_mean_T1_grid_ind[k]]
|
|
1062
|
+
#
|
|
1063
|
+
# Solve the kriging system for T2
|
|
1064
|
+
if cov_model_T2 is not None:
|
|
1065
|
+
try:
|
|
1066
|
+
w = np.linalg.solve(
|
|
1067
|
+
mat_T2[indmat, :][:, indmat], # kriging matrix
|
|
1068
|
+
mat_T2[indmat, k], # second member
|
|
1069
|
+
)
|
|
1070
|
+
except:
|
|
1071
|
+
sim_ok = False
|
|
1072
|
+
if verbose > 3:
|
|
1073
|
+
print(' ... unable to solve kriging system (for T2)')
|
|
1074
|
+
break
|
|
1075
|
+
#
|
|
1076
|
+
# Mean (kriged) value at x[k]
|
|
1077
|
+
mu_T2_k = mean_T2[x_mean_T2_grid_ind[k]] + (v_T[indmat, 1] - mean_T2[x_mean_T2_grid_ind[indmat]]).dot(w)
|
|
1078
|
+
# Standard deviation (of kriging) at x[k]
|
|
1079
|
+
std_T2_k = np.sqrt(np.maximum(0, cov0_T2 - np.dot(w, mat_T2[indmat, k])))
|
|
1080
|
+
# Draw value in N(mu, std^2)
|
|
1081
|
+
v_T_k_new[1] = np.random.normal(loc=mu_T2_k, scale=std_T2_k)
|
|
1082
|
+
else:
|
|
1083
|
+
v_T_k_new[1] = mean_T2[x_mean_T2_grid_ind[k]]
|
|
1084
|
+
#
|
|
1085
|
+
# Accept or not the new candidate
|
|
1086
|
+
if flag_value(v_T_k_new[0], v_T_k_new[1]) == v[k]:
|
|
1087
|
+
# Accept the new candidate
|
|
1088
|
+
v_T[k] = v_T_k_new
|
|
1089
|
+
elif nit < mh_iter_min and np.random.random() < p_accept:
|
|
1090
|
+
# Accept the new candidate
|
|
1091
|
+
v_T[k] = v_T_k_new
|
|
1092
|
+
|
|
1093
|
+
if not sim_ok:
|
|
1094
|
+
break
|
|
1095
|
+
|
|
1096
|
+
if not sim_ok:
|
|
1097
|
+
continue
|
|
1098
|
+
|
|
1099
|
+
if not stop_mh:
|
|
1100
|
+
hd_ok = flag_value(v_T[:, 0], v_T[:, 1]) == v
|
|
1101
|
+
nhd_ok.append(np.sum(hd_ok))
|
|
1102
|
+
if nhd_ok[-1] != npt:
|
|
1103
|
+
# sim_ok kept to True
|
|
1104
|
+
if verbose > 3:
|
|
1105
|
+
print(' ... conditioning failed')
|
|
1106
|
+
if ntry < ntry_max - 1 or not retrieve_real_anyway:
|
|
1107
|
+
continue
|
|
1108
|
+
|
|
1109
|
+
# Generate T1 conditional to (x, v_T[:, 0]) (one real)
|
|
1110
|
+
if cov_model_T1 is not None:
|
|
1111
|
+
sim_T1 = multiGaussian.multiGaussianRun(cov_model_T1, dimension, spacing, origin, x=x, v=v_T[:, 0],
|
|
1112
|
+
mode='simulation', algo=algo_T1, output_mode='array',
|
|
1113
|
+
**params_T1, nreal=1)
|
|
1114
|
+
else:
|
|
1115
|
+
sim_T1 = params_T1['mean'].reshape(1,*dimension[::-1])
|
|
1116
|
+
# -> sim_T1: nd-array of shape
|
|
1117
|
+
# (1, dimension) (for T1 in 1D)
|
|
1118
|
+
# (1, dimension[1], dimension[0]) (for T1 in 2D)
|
|
1119
|
+
# (1, dimension[2], dimension[1], dimension[0]) (for T1 in 3D)
|
|
1120
|
+
if sim_T1 is None:
|
|
1121
|
+
sim_ok = False
|
|
1122
|
+
if verbose > 3:
|
|
1123
|
+
print(' ... conditional simulation of T1 failed')
|
|
1124
|
+
continue
|
|
1125
|
+
#
|
|
1126
|
+
# Generate T2 conditional to (x, v_T[:, 1]) (one real)
|
|
1127
|
+
if cov_model_T2 is not None:
|
|
1128
|
+
sim_T2 = multiGaussian.multiGaussianRun(cov_model_T2, dimension, spacing, origin, x=x, v=v_T[:, 1],
|
|
1129
|
+
mode='simulation', algo=algo_T2, output_mode='array',
|
|
1130
|
+
**params_T2, nreal=1)
|
|
1131
|
+
else:
|
|
1132
|
+
sim_T2 = params_T2['mean'].reshape(1,*dimension[::-1])
|
|
1133
|
+
# -> sim_T2: nd-array of shape
|
|
1134
|
+
# (1, dimension) (for T2 in 1D)
|
|
1135
|
+
# (1, dimension[1], dimension[0]) (for T2 in 2D)
|
|
1136
|
+
# (1, dimension[2], dimension[1], dimension[0]) (for T2 in 3D)
|
|
1137
|
+
if sim_T2 is None:
|
|
1138
|
+
sim_ok = False
|
|
1139
|
+
if verbose > 3:
|
|
1140
|
+
print(' ... conditional simulation of T2 failed')
|
|
1141
|
+
continue
|
|
1142
|
+
|
|
1143
|
+
# Generate Z (one real)
|
|
1144
|
+
if sim_ok:
|
|
1145
|
+
if x is not None:
|
|
1146
|
+
if nhd_ok[-1] != npt:
|
|
1147
|
+
if not retrieve_real_anyway:
|
|
1148
|
+
break
|
|
1149
|
+
else:
|
|
1150
|
+
if verbose > 1:
|
|
1151
|
+
print(f'WARNING ({fname}): realization does not honoured all data, but retrieved anyway')
|
|
1152
|
+
Z_real = flag_value(sim_T1[0], sim_T2[0])
|
|
1153
|
+
Z.append(Z_real)
|
|
1154
|
+
if full_output:
|
|
1155
|
+
T1.append(sim_T1[0])
|
|
1156
|
+
T2.append(sim_T2[0])
|
|
1157
|
+
n_cond_ok.append(np.asarray(nhd_ok))
|
|
1158
|
+
break
|
|
1159
|
+
|
|
1160
|
+
# Get Z
|
|
1161
|
+
if verbose > 1 and len(Z) < nreal:
|
|
1162
|
+
print(f'WARNING ({fname}): some realization failed (missing)')
|
|
1163
|
+
Z = np.asarray(Z).reshape(len(Z), *np.atleast_1d(dimension)[::-1])
|
|
1164
|
+
|
|
1165
|
+
if full_output:
|
|
1166
|
+
T1 = np.asarray(T1).reshape(len(T1), *np.atleast_1d(dimension)[::-1])
|
|
1167
|
+
T2 = np.asarray(T2).reshape(len(T2), *np.atleast_1d(dimension)[::-1])
|
|
1168
|
+
return Z, T1, T2, n_cond_ok
|
|
1169
|
+
else:
|
|
1170
|
+
return Z
|
|
1171
|
+
# ----------------------------------------------------------------------------
|