feectools 0.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.
- feectools/__init__.py +0 -0
- feectools/accelerate/__init__.py +0 -0
- feectools/accelerate/accelerate.py +220 -0
- feectools/accelerate/compile_psydac.mk +52 -0
- feectools/api/__init__.py +0 -0
- feectools/api/essential_bc.py +122 -0
- feectools/api/fem_bilinear_form.py +2226 -0
- feectools/api/fem_common.py +286 -0
- feectools/api/fem_sum_form.py +123 -0
- feectools/api/settings.py +82 -0
- feectools/core/__init__.py +11 -0
- feectools/core/bsplines.py +1107 -0
- feectools/core/bsplines_kernels.py +1349 -0
- feectools/core/field_evaluation_kernels.py +5015 -0
- feectools/core/tests/__init__.py +0 -0
- feectools/core/tests/test_bsplines.py +263 -0
- feectools/core/tests/test_bsplines_kernel.py +40 -0
- feectools/core/tests/test_bsplines_pyccel.py +752 -0
- feectools/ddm/__init__.py +3 -0
- feectools/ddm/basic.py +78 -0
- feectools/ddm/blocking_data_exchanger.py +348 -0
- feectools/ddm/cart.py +1835 -0
- feectools/ddm/interface_data_exchanger.py +122 -0
- feectools/ddm/mpi.py +109 -0
- feectools/ddm/nonblocking_data_exchanger.py +331 -0
- feectools/ddm/partition.py +207 -0
- feectools/ddm/petsc.py +112 -0
- feectools/ddm/tests/__init__.py +0 -0
- feectools/ddm/tests/test_cart_1d.py +138 -0
- feectools/ddm/tests/test_cart_2d.py +164 -0
- feectools/ddm/tests/test_cart_3d.py +158 -0
- feectools/ddm/tests/test_multicart_2d.py +173 -0
- feectools/ddm/tests/test_partition.py +124 -0
- feectools/ddm/utilities.py +24 -0
- feectools/feec/__init__.py +0 -0
- feectools/feec/derivatives.py +780 -0
- feectools/feec/dof_kernels.py +210 -0
- feectools/feec/global_geometric_projectors.py +1073 -0
- feectools/feec/hodge.py +148 -0
- feectools/fem/__init__.py +0 -0
- feectools/fem/basic.py +465 -0
- feectools/fem/grid.py +181 -0
- feectools/fem/partitioning.py +344 -0
- feectools/fem/projectors.py +160 -0
- feectools/fem/splines.py +559 -0
- feectools/fem/tensor.py +1393 -0
- feectools/fem/tests/__init__.py +0 -0
- feectools/fem/tests/analytical_profiles_1d.py +100 -0
- feectools/fem/tests/analytical_profiles_base.py +34 -0
- feectools/fem/tests/splines_error_bounds.py +155 -0
- feectools/fem/tests/test_spline_histopolation.py +120 -0
- feectools/fem/tests/test_spline_interpolation.py +182 -0
- feectools/fem/tests/test_splines.py +184 -0
- feectools/fem/tests/test_splines_par.py +46 -0
- feectools/fem/tests/test_vector_spaces.py +150 -0
- feectools/fem/tests/utilities.py +47 -0
- feectools/fem/vector.py +729 -0
- feectools/linalg/__init__.py +0 -0
- feectools/linalg/basic.py +1386 -0
- feectools/linalg/block.py +1451 -0
- feectools/linalg/direct_solvers.py +201 -0
- feectools/linalg/fft.py +258 -0
- feectools/linalg/kernels/__init__.py +0 -0
- feectools/linalg/kernels/axpy_kernels.py +57 -0
- feectools/linalg/kernels/inner_kernels.py +100 -0
- feectools/linalg/kernels/matvec_kernels.py +206 -0
- feectools/linalg/kernels/stencil2IJV_kernels.py +227 -0
- feectools/linalg/kernels/stencil2coo_kernels.py +179 -0
- feectools/linalg/kernels/transpose_kernels.py +263 -0
- feectools/linalg/kron.py +911 -0
- feectools/linalg/solvers.py +1914 -0
- feectools/linalg/sparse.py +114 -0
- feectools/linalg/stencil.py +2923 -0
- feectools/linalg/stencil_dot_kernels.py +317 -0
- feectools/linalg/stencil_transpose_kernels.py +372 -0
- feectools/linalg/tests/__init__.py +0 -0
- feectools/linalg/tests/test_block.py +1588 -0
- feectools/linalg/tests/test_fft.py +106 -0
- feectools/linalg/tests/test_kron_stencil_matrix.py +114 -0
- feectools/linalg/tests/test_linalg.py +1065 -0
- feectools/linalg/tests/test_matrix_free.py +128 -0
- feectools/linalg/tests/test_solvers.py +213 -0
- feectools/linalg/tests/test_stencil_interface_matrix.py +379 -0
- feectools/linalg/tests/test_stencil_vector.py +1036 -0
- feectools/linalg/tests/test_stencil_vector_space.py +440 -0
- feectools/linalg/topetsc.py +522 -0
- feectools/linalg/utilities.py +200 -0
- feectools/utilities/__init__.py +0 -0
- feectools/utilities/quadratures.py +113 -0
- feectools/utilities/utils.py +166 -0
- feectools/version.py +1 -0
- feectools-0.1.0.dist-info/METADATA +66 -0
- feectools-0.1.0.dist-info/RECORD +98 -0
- feectools-0.1.0.dist-info/WHEEL +5 -0
- feectools-0.1.0.dist-info/entry_points.txt +3 -0
- feectools-0.1.0.dist-info/licenses/AUTHORS +22 -0
- feectools-0.1.0.dist-info/licenses/LICENSE +21 -0
- feectools-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1036 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from feectools.ddm.mpi import mpi as MPI
|
|
7
|
+
from feectools.linalg.stencil import StencilVectorSpace, StencilVector, StencilMatrix
|
|
8
|
+
from feectools.linalg.utilities import array_to_psydac, petsc_to_psydac
|
|
9
|
+
from feectools.ddm.cart import DomainDecomposition, CartDecomposition
|
|
10
|
+
|
|
11
|
+
# TODO : test update ghost region interface
|
|
12
|
+
# TODO : add test exchange_assembly_data
|
|
13
|
+
|
|
14
|
+
# ===============================================================================
|
|
15
|
+
def compute_global_starts_ends(domain_decomposition, npts):
|
|
16
|
+
ndims = len(npts)
|
|
17
|
+
global_starts = [None] * ndims
|
|
18
|
+
global_ends = [None] * ndims
|
|
19
|
+
|
|
20
|
+
for axis in range(ndims):
|
|
21
|
+
es = domain_decomposition.global_element_starts[axis]
|
|
22
|
+
ee = domain_decomposition.global_element_ends[axis]
|
|
23
|
+
|
|
24
|
+
global_ends[axis] = ee.copy()
|
|
25
|
+
global_ends[axis][-1] = npts[axis] - 1
|
|
26
|
+
global_starts[axis] = np.array([0] + (global_ends[axis][:-1] + 1).tolist())
|
|
27
|
+
|
|
28
|
+
return global_starts, global_ends
|
|
29
|
+
|
|
30
|
+
# ===============================================================================
|
|
31
|
+
# SERIAL TESTS
|
|
32
|
+
# ===============================================================================
|
|
33
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
34
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
35
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
36
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
37
|
+
@pytest.mark.parametrize('p2', [2])
|
|
38
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
39
|
+
@pytest.mark.parametrize('s2', [2])
|
|
40
|
+
def test_stencil_vector_2d_serial_init(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
41
|
+
# Create domain decomposition
|
|
42
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
43
|
+
|
|
44
|
+
# Partition the points
|
|
45
|
+
npts = [n1, n2]
|
|
46
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
47
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
48
|
+
|
|
49
|
+
# Create vector space and stencil vector
|
|
50
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
51
|
+
x = StencilVector(V)
|
|
52
|
+
|
|
53
|
+
# Test properties of the vector
|
|
54
|
+
assert x.space is V
|
|
55
|
+
assert x.dtype == dtype
|
|
56
|
+
assert x.starts == tuple(global_starts)
|
|
57
|
+
assert x.ends == tuple(global_ends)
|
|
58
|
+
assert x.pads == (p1, p2)
|
|
59
|
+
assert x._data.shape == (n1 + 2 * p1 * s1, n2 + 2 * p2 * s2)
|
|
60
|
+
assert x._data.dtype == dtype
|
|
61
|
+
assert not x.ghost_regions_in_sync
|
|
62
|
+
|
|
63
|
+
# ===============================================================================
|
|
64
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
65
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
66
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
67
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
68
|
+
@pytest.mark.parametrize('p2', [2])
|
|
69
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
70
|
+
@pytest.mark.parametrize('s2', [2])
|
|
71
|
+
def test_stencil_vector_2d_serial_copy(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
72
|
+
# Create domain decomposition
|
|
73
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
74
|
+
|
|
75
|
+
# Partition the points
|
|
76
|
+
npts = [n1, n2]
|
|
77
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
78
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
79
|
+
|
|
80
|
+
# Create vector space and stencil vector
|
|
81
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
82
|
+
x = StencilVector(V)
|
|
83
|
+
|
|
84
|
+
# Take random data, but determinize it
|
|
85
|
+
np.random.seed(2)
|
|
86
|
+
if dtype == complex:
|
|
87
|
+
x._data[:] = np.random.random(x._data.shape) + 1j * np.random.random(x._data.shape)
|
|
88
|
+
else:
|
|
89
|
+
x._data[:] = np.random.random(x._data.shape)
|
|
90
|
+
|
|
91
|
+
# Compute the copy
|
|
92
|
+
z = x.copy()
|
|
93
|
+
|
|
94
|
+
# Test the properties of the copy
|
|
95
|
+
assert isinstance(z, StencilVector)
|
|
96
|
+
assert z.space is V
|
|
97
|
+
assert z._data is not x._data
|
|
98
|
+
assert z.dtype == dtype
|
|
99
|
+
assert np.array_equal(x._data, z._data)
|
|
100
|
+
|
|
101
|
+
# ===============================================================================
|
|
102
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
103
|
+
@pytest.mark.parametrize('n1', [7, 15])
|
|
104
|
+
@pytest.mark.parametrize('n2', [8, 12])
|
|
105
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
106
|
+
@pytest.mark.parametrize('p2', [3])
|
|
107
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
108
|
+
@pytest.mark.parametrize('s2', [2])
|
|
109
|
+
def test_stencil_vector_2d_basic_ops(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
110
|
+
# Create domain decomposition
|
|
111
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
112
|
+
|
|
113
|
+
# Partition the points
|
|
114
|
+
npts = [n1, n2]
|
|
115
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
116
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
117
|
+
|
|
118
|
+
# Create vector space and stencil vector
|
|
119
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
120
|
+
M = StencilVector(V)
|
|
121
|
+
|
|
122
|
+
# take random data, but determinize it
|
|
123
|
+
np.random.seed(2)
|
|
124
|
+
if dtype == complex:
|
|
125
|
+
M._data[:] = np.random.random(M._data.shape) + 1j * np.random.random(M._data.shape)
|
|
126
|
+
else:
|
|
127
|
+
M._data[:] = np.random.random(M._data.shape)
|
|
128
|
+
|
|
129
|
+
# Test classical basic operation
|
|
130
|
+
assert (M * 2).dtype == dtype
|
|
131
|
+
assert np.array_equal((M * 2)._data, M._data * 2)
|
|
132
|
+
assert (M / 2).dtype == dtype
|
|
133
|
+
assert np.array_equal((M / 2)._data, M._data / 2)
|
|
134
|
+
assert (M + M).dtype == dtype
|
|
135
|
+
assert np.array_equal((M + M)._data, M._data + M._data)
|
|
136
|
+
assert (M - M).dtype == dtype
|
|
137
|
+
assert np.array_equal((M - M)._data, M._data - M._data)
|
|
138
|
+
|
|
139
|
+
M1 = M.copy()
|
|
140
|
+
M1 *= 2
|
|
141
|
+
M2 = M.copy()
|
|
142
|
+
M2 /= 2
|
|
143
|
+
M3 = M.copy()
|
|
144
|
+
M3 += M
|
|
145
|
+
M4 = M.copy()
|
|
146
|
+
M4 -= M
|
|
147
|
+
|
|
148
|
+
# test inplace operation
|
|
149
|
+
for (m, mex) in zip([M1, M2, M3, M4], [M._data * 2, M._data / 2, M._data + M._data, M._data - M._data]):
|
|
150
|
+
assert isinstance(m, StencilVector)
|
|
151
|
+
assert m.dtype == dtype
|
|
152
|
+
assert m.space is V
|
|
153
|
+
assert np.array_equal(m._data, mex)
|
|
154
|
+
|
|
155
|
+
# ===============================================================================
|
|
156
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
157
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
158
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
159
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
160
|
+
@pytest.mark.parametrize('p2', [1])
|
|
161
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
162
|
+
@pytest.mark.parametrize('s2', [1])
|
|
163
|
+
def test_stencil_vector_2d_serial_toarray(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
164
|
+
# Create domain decomposition
|
|
165
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
166
|
+
|
|
167
|
+
# Partition the points
|
|
168
|
+
npts = [n1, n2]
|
|
169
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
170
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
171
|
+
|
|
172
|
+
# Create vector space and stencil vector
|
|
173
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
174
|
+
x = StencilVector(V)
|
|
175
|
+
|
|
176
|
+
#Fill vector with some data
|
|
177
|
+
if dtype == complex:
|
|
178
|
+
f = lambda i1, i2: 10j * i1 + i2
|
|
179
|
+
else:
|
|
180
|
+
f = lambda i1, i2: 10 * i1 + i2
|
|
181
|
+
|
|
182
|
+
for i1 in range(n1):
|
|
183
|
+
for i2 in range(n2):
|
|
184
|
+
x[i1, i2] = f(i1,i2)
|
|
185
|
+
|
|
186
|
+
# Convert StencilVector into array (in serial only order has an impact)
|
|
187
|
+
xc = x.toarray()
|
|
188
|
+
xf = x.toarray(order='F')
|
|
189
|
+
|
|
190
|
+
# Create our exact arrays
|
|
191
|
+
zc = np.zeros((n1 * n2),dtype=dtype)
|
|
192
|
+
zf = np.zeros((n1 * n2),dtype=dtype)
|
|
193
|
+
for i1 in range(n1):
|
|
194
|
+
for i2 in range(n2):
|
|
195
|
+
zc[i1 * n2 + i2] = f(i1,i2)
|
|
196
|
+
zf[i1 + i2 * n1] = f(i1,i2)
|
|
197
|
+
|
|
198
|
+
# Verify toarray() with and without padding
|
|
199
|
+
for (x, z) in zip([xc, xf], [zc, zf]):
|
|
200
|
+
assert x.shape == (n1*n2,)
|
|
201
|
+
assert x.dtype == dtype
|
|
202
|
+
assert np.array_equal(xc, zc)
|
|
203
|
+
|
|
204
|
+
# ===============================================================================
|
|
205
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
206
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
207
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
208
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
209
|
+
@pytest.mark.parametrize('p2', [1])
|
|
210
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
211
|
+
@pytest.mark.parametrize('s2', [1])
|
|
212
|
+
def test_stencil_vector_2d_serial_math(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
213
|
+
# Create domain decomposition
|
|
214
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
215
|
+
|
|
216
|
+
# Partition the points
|
|
217
|
+
npts = [n1, n2]
|
|
218
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
219
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
220
|
+
|
|
221
|
+
# Create vector space and stencil vector
|
|
222
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
223
|
+
x = StencilVector(V)
|
|
224
|
+
y = StencilVector(V)
|
|
225
|
+
|
|
226
|
+
# take random data, but determinize it
|
|
227
|
+
np.random.seed(2)
|
|
228
|
+
if dtype == complex:
|
|
229
|
+
x._data[:] = np.random.random(x._data.shape) + 1j * np.random.random(x._data.shape)
|
|
230
|
+
else:
|
|
231
|
+
x._data[:] = np.random.random(x._data.shape)
|
|
232
|
+
|
|
233
|
+
y[:, :] = 42.0
|
|
234
|
+
|
|
235
|
+
# Compute new StencilVectors by basics operation
|
|
236
|
+
r1 = x + y
|
|
237
|
+
r2 = x - y
|
|
238
|
+
r3 = 2 * x
|
|
239
|
+
r4 = x * 2
|
|
240
|
+
xa = x.toarray()
|
|
241
|
+
ya = y.toarray()
|
|
242
|
+
|
|
243
|
+
# Create exact array
|
|
244
|
+
r1_exact = xa + ya
|
|
245
|
+
r2_exact = xa - ya
|
|
246
|
+
r3_exact = 2 * xa
|
|
247
|
+
r4_exact = xa * 2
|
|
248
|
+
|
|
249
|
+
# Compare value contain in StencilVector and exact array
|
|
250
|
+
for (r, rex) in zip([r1, r2, r3, r4], [r1_exact, r2_exact, r3_exact, r4_exact]):
|
|
251
|
+
assert isinstance(r, StencilVector)
|
|
252
|
+
assert r.space is V
|
|
253
|
+
assert r.dtype == dtype
|
|
254
|
+
assert np.array_equal(r.toarray(), rex)
|
|
255
|
+
|
|
256
|
+
# ===============================================================================
|
|
257
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
258
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
259
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
260
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
261
|
+
@pytest.mark.parametrize('p2', [1])
|
|
262
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
263
|
+
@pytest.mark.parametrize('s2', [1])
|
|
264
|
+
def test_stencil_vector_2d_serial_dot(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
265
|
+
# Create domain decomposition
|
|
266
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
267
|
+
|
|
268
|
+
# Partition the points
|
|
269
|
+
npts = [n1, n2]
|
|
270
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
271
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
272
|
+
|
|
273
|
+
# Create vector space and stencil vectors
|
|
274
|
+
V = StencilVectorSpace(C, dtype)
|
|
275
|
+
x = StencilVector(V)
|
|
276
|
+
y = StencilVector(V)
|
|
277
|
+
|
|
278
|
+
if dtype == complex:
|
|
279
|
+
f1 = lambda i1, i2: 100j * i1 + i2
|
|
280
|
+
f2 = lambda i1, i2: 10j* i2 - i1
|
|
281
|
+
else:
|
|
282
|
+
f1 = lambda i1, i2: 100 * i1 + i2
|
|
283
|
+
f2 = lambda i1, i2: 10 * i2 - i1
|
|
284
|
+
|
|
285
|
+
# Fill the vectors with data
|
|
286
|
+
for i1 in range(n1):
|
|
287
|
+
for i2 in range(n2):
|
|
288
|
+
x[i1, i2] = f1(i1,i2)
|
|
289
|
+
y[i1, i2] = f2(i1,i2)
|
|
290
|
+
|
|
291
|
+
# Create inner vector product (x,y) and (y,x)
|
|
292
|
+
z1 = x.inner(y)
|
|
293
|
+
z2 = y.inner(x)
|
|
294
|
+
|
|
295
|
+
# Exact value by Numpy dot and vdot
|
|
296
|
+
if dtype==complex:
|
|
297
|
+
z_exact = np.vdot(x.toarray(), y.toarray())
|
|
298
|
+
else:
|
|
299
|
+
z_exact = np.dot(x.toarray(), y.toarray())
|
|
300
|
+
|
|
301
|
+
# Compute axpy exact sol
|
|
302
|
+
if dtype == complex:
|
|
303
|
+
cst = 5j
|
|
304
|
+
else:
|
|
305
|
+
cst = 5
|
|
306
|
+
|
|
307
|
+
z3 = x + cst * y
|
|
308
|
+
x.mul_iadd(cst, y)
|
|
309
|
+
|
|
310
|
+
# Test exact value and symmetry of the scalar product
|
|
311
|
+
assert z1.dtype == dtype
|
|
312
|
+
assert z2.dtype == dtype
|
|
313
|
+
assert z1 == z_exact
|
|
314
|
+
assert z2 == z_exact.conjugate()
|
|
315
|
+
assert np.allclose(x._data, z3._data)
|
|
316
|
+
|
|
317
|
+
# ===============================================================================
|
|
318
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
319
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
320
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
321
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
322
|
+
@pytest.mark.parametrize('p2', [1])
|
|
323
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
324
|
+
@pytest.mark.parametrize('s2', [1])
|
|
325
|
+
def test_stencil_vector_2d_serial_conjugate(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
326
|
+
# Create domain decomposition
|
|
327
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
328
|
+
|
|
329
|
+
# Partition the points
|
|
330
|
+
npts = [n1, n2]
|
|
331
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
332
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
333
|
+
|
|
334
|
+
# Create vector space and stencil vector
|
|
335
|
+
V = StencilVectorSpace(C, dtype)
|
|
336
|
+
x = StencilVector(V)
|
|
337
|
+
|
|
338
|
+
# Fill the vector with data
|
|
339
|
+
if dtype == complex:
|
|
340
|
+
f = lambda i1, i2: 10j * i1 + i2
|
|
341
|
+
else:
|
|
342
|
+
f = lambda i1, i2: 10 * i1 + i2
|
|
343
|
+
|
|
344
|
+
for i1 in range(n1):
|
|
345
|
+
for i2 in range(n2):
|
|
346
|
+
x[i1, i2] = f(i1,i2)
|
|
347
|
+
|
|
348
|
+
# Create the conjugate of the vector
|
|
349
|
+
z1 = x.conjugate()
|
|
350
|
+
z2 = StencilVector(V)
|
|
351
|
+
x.conjugate(out=z2)
|
|
352
|
+
|
|
353
|
+
# Compute exact value with Numpy conjugate
|
|
354
|
+
z_exact = x._data.conjugate()
|
|
355
|
+
|
|
356
|
+
# Test the exact value
|
|
357
|
+
assert z1.dtype == dtype
|
|
358
|
+
assert np.array_equal(z1._data, z_exact)
|
|
359
|
+
assert np.array_equal(z2._data, z_exact)
|
|
360
|
+
|
|
361
|
+
# ===============================================================================
|
|
362
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
363
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
364
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
365
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
366
|
+
@pytest.mark.parametrize('p2', [1])
|
|
367
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
368
|
+
@pytest.mark.parametrize('s2', [1])
|
|
369
|
+
@pytest.mark.parametrize('P1', [True, False])
|
|
370
|
+
@pytest.mark.parametrize('P2', [True])
|
|
371
|
+
def test_stencil_vector_2d_serial_array_to_psydac(dtype, n1, n2, p1, p2, s1, s2, P1, P2):
|
|
372
|
+
# Create domain decomposition
|
|
373
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
374
|
+
|
|
375
|
+
# Partition the points
|
|
376
|
+
npts = [n1, n2]
|
|
377
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
378
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
379
|
+
|
|
380
|
+
# Create vector space and stencil vector
|
|
381
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
382
|
+
x = StencilVector(V)
|
|
383
|
+
|
|
384
|
+
# Fill the vector with data
|
|
385
|
+
|
|
386
|
+
if dtype == complex:
|
|
387
|
+
f = lambda i1, i2: 10j * i1 + i2
|
|
388
|
+
else:
|
|
389
|
+
f = lambda i1, i2: 10 * i1 + i2
|
|
390
|
+
for i1 in range(n1):
|
|
391
|
+
for i2 in range(n2):
|
|
392
|
+
x[i1, i2] = f(i1,i2)
|
|
393
|
+
|
|
394
|
+
# Convert vector to array
|
|
395
|
+
xa = x.toarray()
|
|
396
|
+
|
|
397
|
+
# Convert array to vector of V
|
|
398
|
+
v = array_to_psydac(xa, V)
|
|
399
|
+
|
|
400
|
+
# Test properties of v and data contained
|
|
401
|
+
assert v.space is V
|
|
402
|
+
assert v.dtype == dtype
|
|
403
|
+
assert v.starts == (0, 0)
|
|
404
|
+
assert v.ends == (n1 - 1, n2 - 1)
|
|
405
|
+
assert v.pads == (p1, p2)
|
|
406
|
+
assert v._data.shape == (n1 + 2 * p1 * s1, n2 + 2 * p2 * s2)
|
|
407
|
+
assert v._data.dtype == dtype
|
|
408
|
+
assert np.array_equal(xa, v.toarray())
|
|
409
|
+
|
|
410
|
+
# ===============================================================================
|
|
411
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
412
|
+
@pytest.mark.parametrize('n1', [1, 7])
|
|
413
|
+
@pytest.mark.parametrize('n2', [1, 5])
|
|
414
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
415
|
+
@pytest.mark.parametrize('p2', [1])
|
|
416
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
417
|
+
@pytest.mark.parametrize('s2', [1])
|
|
418
|
+
@pytest.mark.parametrize('P1', [True, False])
|
|
419
|
+
@pytest.mark.parametrize('P2', [True])
|
|
420
|
+
@pytest.mark.petsc
|
|
421
|
+
def test_stencil_vector_2d_serial_topetsc(dtype, n1, n2, p1, p2, s1, s2, P1, P2):
|
|
422
|
+
# Create domain decomposition
|
|
423
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
424
|
+
|
|
425
|
+
# Partition the points
|
|
426
|
+
npts = [n1, n2]
|
|
427
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
428
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
429
|
+
|
|
430
|
+
# Create vector space and stencil vector
|
|
431
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
432
|
+
x = StencilVector(V)
|
|
433
|
+
|
|
434
|
+
# Fill the vector with data
|
|
435
|
+
if dtype == complex:
|
|
436
|
+
f = lambda i1, i2: 10j * i1 + i2
|
|
437
|
+
else:
|
|
438
|
+
f = lambda i1, i2: 10 * i1 + i2
|
|
439
|
+
for i1 in range(n1):
|
|
440
|
+
for i2 in range(n2):
|
|
441
|
+
x[i1, i2] = f(i1,i2)
|
|
442
|
+
|
|
443
|
+
# Convert vector to PETSc.Vec
|
|
444
|
+
v = x.topetsc()
|
|
445
|
+
|
|
446
|
+
# Convert PETSc.Vec to StencilVector of V
|
|
447
|
+
v = petsc_to_psydac(v, V)
|
|
448
|
+
|
|
449
|
+
# Test properties of v and data contained
|
|
450
|
+
assert v.space is V
|
|
451
|
+
assert v.dtype == dtype
|
|
452
|
+
assert v.starts == (0, 0)
|
|
453
|
+
assert v.ends == (n1 - 1, n2 - 1)
|
|
454
|
+
assert v.pads == (p1, p2)
|
|
455
|
+
assert v._data.shape == (n1 + 2 * p1 * s1, n2 + 2 * p2 * s2)
|
|
456
|
+
assert v._data.dtype == dtype
|
|
457
|
+
assert np.array_equal(x.toarray(), v.toarray())
|
|
458
|
+
|
|
459
|
+
# ===============================================================================
|
|
460
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
461
|
+
@pytest.mark.parametrize('n1', [5, 7])
|
|
462
|
+
@pytest.mark.parametrize('n2', [5, 9])
|
|
463
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
464
|
+
@pytest.mark.parametrize('p2', [1])
|
|
465
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
466
|
+
@pytest.mark.parametrize('s2', [1])
|
|
467
|
+
@pytest.mark.parametrize('P1', [True, False])
|
|
468
|
+
@pytest.mark.parametrize('P2', [True])
|
|
469
|
+
def test_stencil_vector_2d_serial_update_ghost_region_interior(dtype, n1, n2, p1, p2, s1, s2, P1, P2):
|
|
470
|
+
# Create domain decomposition
|
|
471
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
472
|
+
|
|
473
|
+
# Partition the points
|
|
474
|
+
npts = [n1, n2]
|
|
475
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
476
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
477
|
+
|
|
478
|
+
# Create vector space and stencil vector
|
|
479
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
480
|
+
x = StencilVector(V)
|
|
481
|
+
|
|
482
|
+
# Fill vector with data
|
|
483
|
+
if dtype == complex:
|
|
484
|
+
f = lambda i1, i2: 10j * i1 + i2
|
|
485
|
+
else:
|
|
486
|
+
f = lambda i1, i2: 10 * i1 + i2
|
|
487
|
+
for i1 in range(n1):
|
|
488
|
+
for i2 in range(n2):
|
|
489
|
+
x[i1, i2] = f(i1,i2)
|
|
490
|
+
|
|
491
|
+
# Update the vector ghost region if the concerned domain is periodic
|
|
492
|
+
x.update_ghost_regions()
|
|
493
|
+
data = x._data
|
|
494
|
+
|
|
495
|
+
# Test if _sync properties was changed
|
|
496
|
+
assert x._sync
|
|
497
|
+
|
|
498
|
+
# Compare vectors ghost region to the exact value
|
|
499
|
+
if P1:
|
|
500
|
+
# Left region with corner
|
|
501
|
+
assert np.array_equal(data[0:p1 * s1, :], data[n1:n1 + p1 * s1, :])
|
|
502
|
+
# Right region with corner
|
|
503
|
+
assert np.array_equal(data[n1 + p1 * s1:n1 + 2 * p1 * s1, :], data[p1 * s1:2 * p1 * s1, :])
|
|
504
|
+
else:
|
|
505
|
+
# Left region with corner
|
|
506
|
+
assert np.array_equal(data[0:p1 * s1, :], np.zeros((p1 * s1, n2 + 2 * p2 * s2), dtype=dtype))
|
|
507
|
+
# Right region with corner
|
|
508
|
+
assert np.array_equal(data[n1 + p1 * s1:n1 + 2 * p1 * s1, :],
|
|
509
|
+
np.zeros((p1 * s1, n2 + 2 * p2 * s2), dtype=dtype))
|
|
510
|
+
if P2:
|
|
511
|
+
# Left region with corner
|
|
512
|
+
assert np.array_equal(data[:, 0:p2 * s2], data[:, n2:n2 + p2 * s2])
|
|
513
|
+
# Right region with corner
|
|
514
|
+
assert np.array_equal(data[:, n2 + p2 * s2:n2 + 2 * p2 * s2], data[:, p2 * s2:2 * p2 * s2])
|
|
515
|
+
else:
|
|
516
|
+
# Left region
|
|
517
|
+
assert np.array_equal(data[:, 0:p2 * s2], np.zeros((n1 + 2 * p1 * s1, p2 * s2), dtype=dtype))
|
|
518
|
+
# Right region with corner
|
|
519
|
+
assert np.array_equal(data[:, n2 + p2 * s2:n2 + 2 * p2 * s2],
|
|
520
|
+
np.zeros((n1 + 2 * p1 * s1, p2 * s2), dtype=dtype))
|
|
521
|
+
|
|
522
|
+
# ===============================================================================
|
|
523
|
+
# PARALLEL TESTS
|
|
524
|
+
# ===============================================================================
|
|
525
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
526
|
+
@pytest.mark.parametrize('n1', [12, 22])
|
|
527
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
528
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
529
|
+
@pytest.mark.parallel
|
|
530
|
+
def test_stencil_vector_1d_parallel_init(dtype, n1, p1, s1, P1=True):
|
|
531
|
+
|
|
532
|
+
comm = MPI.COMM_WORLD
|
|
533
|
+
|
|
534
|
+
# Create domain decomposition
|
|
535
|
+
D = DomainDecomposition([n1], periods=[P1], comm=comm)
|
|
536
|
+
|
|
537
|
+
# Partition the points
|
|
538
|
+
npts = [n1]
|
|
539
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
540
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1], shifts=[s1])
|
|
541
|
+
|
|
542
|
+
# Create vector space and stencil vector
|
|
543
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
544
|
+
x = StencilVector(V)
|
|
545
|
+
|
|
546
|
+
# Test properties of the vector
|
|
547
|
+
assert x.space is V
|
|
548
|
+
assert x.dtype == dtype
|
|
549
|
+
assert tuple(x.starts) == tuple(V.starts)
|
|
550
|
+
assert tuple(x.ends) == tuple(V.ends)
|
|
551
|
+
assert x.pads == (p1, )
|
|
552
|
+
assert x._data.shape == (V.ends[0]-V.starts[0]+1 + 2 * p1 * s1, )
|
|
553
|
+
assert x._data.dtype == dtype
|
|
554
|
+
assert not x.ghost_regions_in_sync
|
|
555
|
+
|
|
556
|
+
# ===============================================================================
|
|
557
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
558
|
+
@pytest.mark.parametrize('n1', [10, 15])
|
|
559
|
+
@pytest.mark.parametrize('n2', [6, 12])
|
|
560
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
561
|
+
@pytest.mark.parametrize('p2', [3])
|
|
562
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
563
|
+
@pytest.mark.parametrize('s2', [2])
|
|
564
|
+
@pytest.mark.parallel
|
|
565
|
+
def test_stencil_vector_2d_parallel_init(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
566
|
+
|
|
567
|
+
comm = MPI.COMM_WORLD
|
|
568
|
+
|
|
569
|
+
# Create domain decomposition
|
|
570
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2], comm=comm)
|
|
571
|
+
|
|
572
|
+
# Partition the points
|
|
573
|
+
npts = [n1, n2]
|
|
574
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
575
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
576
|
+
|
|
577
|
+
# Create vector space and stencil vector
|
|
578
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
579
|
+
x = StencilVector(V)
|
|
580
|
+
|
|
581
|
+
# Test properties of the vector
|
|
582
|
+
assert x.space is V
|
|
583
|
+
assert x.dtype == dtype
|
|
584
|
+
assert tuple(x.starts) == tuple(V.starts)
|
|
585
|
+
assert tuple(x.ends) == tuple(V.ends)
|
|
586
|
+
assert x.pads == (p1, p2)
|
|
587
|
+
assert x._data.shape == (V.ends[0]-V.starts[0]+1 + 2 * p1 * s1, V.ends[1]-V.starts[1]+1 + 2 * p2 * s2)
|
|
588
|
+
assert x._data.dtype == dtype
|
|
589
|
+
assert not x.ghost_regions_in_sync
|
|
590
|
+
|
|
591
|
+
# ===============================================================================
|
|
592
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
593
|
+
@pytest.mark.parametrize('n1', [20, 32])
|
|
594
|
+
@pytest.mark.parametrize('n2', [24, 40])
|
|
595
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
596
|
+
@pytest.mark.parametrize('p2', [2])
|
|
597
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
598
|
+
@pytest.mark.parametrize('s2', [2])
|
|
599
|
+
@pytest.mark.parametrize('P1', [True, False])
|
|
600
|
+
@pytest.mark.parametrize('P2', [True])
|
|
601
|
+
@pytest.mark.parallel
|
|
602
|
+
@pytest.mark.petsc
|
|
603
|
+
def test_stencil_vector_2d_parallel_topetsc(dtype, n1, n2, p1, p2, s1, s2, P1, P2):
|
|
604
|
+
|
|
605
|
+
comm = MPI.COMM_WORLD
|
|
606
|
+
|
|
607
|
+
# Create domain decomposition
|
|
608
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2], comm=comm)
|
|
609
|
+
|
|
610
|
+
# Partition the points
|
|
611
|
+
npts = [n1, n2]
|
|
612
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
613
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
614
|
+
|
|
615
|
+
# Create vector space and stencil vector
|
|
616
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
617
|
+
x = StencilVector(V)
|
|
618
|
+
|
|
619
|
+
# Fill the vector with data
|
|
620
|
+
if dtype == complex:
|
|
621
|
+
f = lambda i1, i2: 10j * i1 + i2
|
|
622
|
+
else:
|
|
623
|
+
f = lambda i1, i2: 10 * i1 + i2
|
|
624
|
+
|
|
625
|
+
# Initialize distributed 2D stencil vector
|
|
626
|
+
for i1 in range(V.starts[0], V.ends[0] + 1):
|
|
627
|
+
for i2 in range(V.starts[1], V.ends[1] + 1):
|
|
628
|
+
x[i1, i2] = f(i1,i2)
|
|
629
|
+
|
|
630
|
+
# Convert vector to PETSc.Vec
|
|
631
|
+
v = x.topetsc()
|
|
632
|
+
|
|
633
|
+
# Convert PETSc.Vec to StencilVector of V
|
|
634
|
+
v = petsc_to_psydac(v, V)
|
|
635
|
+
|
|
636
|
+
assert np.array_equal(x.toarray(), v.toarray())
|
|
637
|
+
|
|
638
|
+
# ===============================================================================
|
|
639
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
640
|
+
@pytest.mark.parametrize('n1', [20, 32])
|
|
641
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
642
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
643
|
+
@pytest.mark.parametrize('P1', [True, False])
|
|
644
|
+
@pytest.mark.parallel
|
|
645
|
+
@pytest.mark.petsc
|
|
646
|
+
def test_stencil_vector_1d_parallel_topetsc(dtype, n1, p1, s1, P1):
|
|
647
|
+
|
|
648
|
+
comm = MPI.COMM_WORLD
|
|
649
|
+
|
|
650
|
+
# Create domain decomposition
|
|
651
|
+
D = DomainDecomposition([n1], periods=[P1], comm=comm)
|
|
652
|
+
|
|
653
|
+
# Partition the points
|
|
654
|
+
npts = [n1]
|
|
655
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
656
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1], shifts=[s1])
|
|
657
|
+
|
|
658
|
+
# Create vector space and stencil vector
|
|
659
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
660
|
+
x = StencilVector(V)
|
|
661
|
+
|
|
662
|
+
# Fill the vector with data
|
|
663
|
+
if dtype == complex:
|
|
664
|
+
f = lambda i1: 10j * i1 + 3
|
|
665
|
+
else:
|
|
666
|
+
f = lambda i1: 10 * i1 + 3
|
|
667
|
+
|
|
668
|
+
# Initialize distributed 2D stencil vector
|
|
669
|
+
for i1 in range(V.starts[0], V.ends[0] + 1):
|
|
670
|
+
x[i1] = f(i1)
|
|
671
|
+
|
|
672
|
+
# Convert vector to PETSc.Vec
|
|
673
|
+
v = x.topetsc()
|
|
674
|
+
|
|
675
|
+
# Convert PETSc.Vec to StencilVector of V
|
|
676
|
+
v = petsc_to_psydac(v, V)
|
|
677
|
+
|
|
678
|
+
assert np.array_equal(x.toarray(), v.toarray())
|
|
679
|
+
|
|
680
|
+
# ===============================================================================
|
|
681
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
682
|
+
@pytest.mark.parametrize('n1', [20, 32])
|
|
683
|
+
@pytest.mark.parametrize('n2', [24, 40])
|
|
684
|
+
@pytest.mark.parametrize('n3', [7, 12])
|
|
685
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
686
|
+
@pytest.mark.parametrize('p2', [2])
|
|
687
|
+
@pytest.mark.parametrize('p3', [1])
|
|
688
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
689
|
+
@pytest.mark.parametrize('s2', [2])
|
|
690
|
+
@pytest.mark.parametrize('s3', [1])
|
|
691
|
+
@pytest.mark.parametrize('P1', [True, False])
|
|
692
|
+
@pytest.mark.parametrize('P2', [True])
|
|
693
|
+
@pytest.mark.parametrize('P3', [False])
|
|
694
|
+
|
|
695
|
+
@pytest.mark.parallel
|
|
696
|
+
@pytest.mark.petsc
|
|
697
|
+
def test_stencil_vector_3d_parallel_topetsc(dtype, n1, n2, n3, p1, p2, p3, s1, s2, s3, P1, P2, P3):
|
|
698
|
+
|
|
699
|
+
comm = MPI.COMM_WORLD
|
|
700
|
+
|
|
701
|
+
# Create domain decomposition
|
|
702
|
+
D = DomainDecomposition([n1, n2, n3], periods=[P1, P2, P3], comm=comm)
|
|
703
|
+
|
|
704
|
+
# Partition the points
|
|
705
|
+
npts = [n1, n2, n3]
|
|
706
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
707
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2, p3], shifts=[s1, s2, s3])
|
|
708
|
+
|
|
709
|
+
# Create vector space and stencil vector
|
|
710
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
711
|
+
x = StencilVector(V)
|
|
712
|
+
|
|
713
|
+
# Fill the vector with data
|
|
714
|
+
|
|
715
|
+
if dtype == complex:
|
|
716
|
+
f = lambda i1, i2, i3: 10j * i1 + i2 - i3
|
|
717
|
+
else:
|
|
718
|
+
f = lambda i1, i2, i3: 10 * i1 + i2 - i3
|
|
719
|
+
|
|
720
|
+
# Initialize distributed 2D stencil vector
|
|
721
|
+
for i1 in range(V.starts[0], V.ends[0] + 1):
|
|
722
|
+
for i2 in range(V.starts[1], V.ends[1] + 1):
|
|
723
|
+
for i3 in range(V.starts[2], V.ends[2] + 1):
|
|
724
|
+
x[i1, i2, i3] = f(i1, i2, i3)
|
|
725
|
+
|
|
726
|
+
# Convert vector to PETSc.Vec
|
|
727
|
+
v = x.topetsc()
|
|
728
|
+
|
|
729
|
+
# Convert PETSc.Vec to StencilVector of V
|
|
730
|
+
v = petsc_to_psydac(v, V)
|
|
731
|
+
|
|
732
|
+
assert np.array_equal(x.toarray(), v.toarray())
|
|
733
|
+
|
|
734
|
+
# ===============================================================================
|
|
735
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
736
|
+
@pytest.mark.parametrize('n1', [6, 15])
|
|
737
|
+
@pytest.mark.parametrize('n2', [10, 18])
|
|
738
|
+
@pytest.mark.parametrize('n3', [12])
|
|
739
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
740
|
+
@pytest.mark.parametrize('p2', [2])
|
|
741
|
+
@pytest.mark.parametrize('p3', [1])
|
|
742
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
743
|
+
@pytest.mark.parametrize('s2', [3])
|
|
744
|
+
@pytest.mark.parametrize('s3', [1])
|
|
745
|
+
@pytest.mark.parallel
|
|
746
|
+
def test_stencil_vector_3d_parallel_init(dtype, n1, n2, n3, p1, p2, p3, s1, s2, s3, P1=True, P2=False, P3=True):
|
|
747
|
+
|
|
748
|
+
comm = MPI.COMM_WORLD
|
|
749
|
+
|
|
750
|
+
# Create domain decomposition
|
|
751
|
+
D = DomainDecomposition([n1, n2, n3], periods=[P1, P2, P3], comm=comm)
|
|
752
|
+
|
|
753
|
+
# Partition the points
|
|
754
|
+
npts = [n1, n2, n3]
|
|
755
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
756
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2, p3], shifts=[s1, s2, s3])
|
|
757
|
+
|
|
758
|
+
# Create vector space and stencil vector
|
|
759
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
760
|
+
x = StencilVector(V)
|
|
761
|
+
|
|
762
|
+
# Test properties of the vector
|
|
763
|
+
assert x.space is V
|
|
764
|
+
assert x.dtype == dtype
|
|
765
|
+
assert tuple(x.starts) == tuple(V.starts)
|
|
766
|
+
assert tuple(x.ends) == tuple(V.ends)
|
|
767
|
+
assert x.pads == (p1, p2, p3)
|
|
768
|
+
assert x._data.shape == (V.ends[0]-V.starts[0]+1 + 2 * p1 * s1, V.ends[1]-V.starts[1]+1 + 2 * p2 * s2,
|
|
769
|
+
V.ends[2]-V.starts[2]+1 + 2 * p3 * s3)
|
|
770
|
+
assert x._data.dtype == dtype
|
|
771
|
+
assert not x.ghost_regions_in_sync
|
|
772
|
+
|
|
773
|
+
# ===============================================================================
|
|
774
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
775
|
+
@pytest.mark.parametrize('n1', [20, 32])
|
|
776
|
+
@pytest.mark.parametrize('n2', [24, 40])
|
|
777
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
778
|
+
@pytest.mark.parametrize('p2', [2])
|
|
779
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
780
|
+
@pytest.mark.parametrize('s2', [2])
|
|
781
|
+
@pytest.mark.parallel
|
|
782
|
+
def test_stencil_vector_2d_parallel_toarray(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
783
|
+
# Create domain decomposition
|
|
784
|
+
comm = MPI.COMM_WORLD
|
|
785
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2], comm=comm)
|
|
786
|
+
|
|
787
|
+
# Partition the points
|
|
788
|
+
npts = [n1, n2]
|
|
789
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
790
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
791
|
+
|
|
792
|
+
# Create vector space and stencil vector
|
|
793
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
794
|
+
x = StencilVector(V)
|
|
795
|
+
|
|
796
|
+
# Values in 2D grid (global indexing)
|
|
797
|
+
if dtype == complex:
|
|
798
|
+
f = lambda i1, i2: 100j * i1 + i2
|
|
799
|
+
else:
|
|
800
|
+
f = lambda i1, i2: 100 * i1 + i2
|
|
801
|
+
|
|
802
|
+
# Initialize distributed 2D stencil vector
|
|
803
|
+
for i1 in range(V.starts[0], V.ends[0] + 1):
|
|
804
|
+
for i2 in range(V.starts[1], V.ends[1] + 1):
|
|
805
|
+
x[i1, i2] = f(i1, i2)
|
|
806
|
+
|
|
807
|
+
x.update_ghost_regions()
|
|
808
|
+
|
|
809
|
+
assert x.dtype == dtype
|
|
810
|
+
|
|
811
|
+
# Construct local 2D array manually
|
|
812
|
+
z1 = np.zeros((n1, n2), dtype=dtype)
|
|
813
|
+
z2 = np.zeros((n2, n1), dtype=dtype)
|
|
814
|
+
for i1 in range(cart.starts[0], cart.ends[0] + 1):
|
|
815
|
+
for i2 in range(cart.starts[1], cart.ends[1] + 1):
|
|
816
|
+
z1[i1, i2] = f(i1, i2)
|
|
817
|
+
z2[i2, i1] = f(i1, i2)
|
|
818
|
+
|
|
819
|
+
# Verify toarray() without padding
|
|
820
|
+
xa1 = x.toarray()
|
|
821
|
+
xa2 = x.toarray(order="F")
|
|
822
|
+
za1 = z1.reshape(-1)
|
|
823
|
+
za2 = z2.reshape(-1)
|
|
824
|
+
|
|
825
|
+
assert xa1.dtype == dtype
|
|
826
|
+
assert xa1.shape == (n1 * n2,)
|
|
827
|
+
assert np.array_equal(xa1, za1)
|
|
828
|
+
assert np.array_equal(xa2, za2)
|
|
829
|
+
|
|
830
|
+
# # Verify toarray() with padding: internal region should not change
|
|
831
|
+
# xe = x.toarray(with_pads=True)
|
|
832
|
+
# xe = xe.reshape(n1, n2)
|
|
833
|
+
#
|
|
834
|
+
# assert xe.dtype == dtype
|
|
835
|
+
# assert xe.shape == (n1, n2)
|
|
836
|
+
# assert np.array_equal(xe, z1)
|
|
837
|
+
|
|
838
|
+
# ===============================================================================
|
|
839
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
840
|
+
@pytest.mark.parametrize('n1', [10, 17])
|
|
841
|
+
@pytest.mark.parametrize('n2', [13, 7])
|
|
842
|
+
@pytest.mark.parametrize('p1', [1, 2])
|
|
843
|
+
@pytest.mark.parametrize('p2', [1])
|
|
844
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
845
|
+
@pytest.mark.parametrize('s2', [1])
|
|
846
|
+
@pytest.mark.parametrize('P1', [True, False])
|
|
847
|
+
@pytest.mark.parametrize('P2', [True])
|
|
848
|
+
@pytest.mark.parallel
|
|
849
|
+
def test_stencil_vector_2d_parallel_array_to_psydac(dtype, n1, n2, p1, p2, s1, s2, P1, P2):
|
|
850
|
+
npts = [n1, n2]
|
|
851
|
+
|
|
852
|
+
comm = MPI.COMM_WORLD
|
|
853
|
+
|
|
854
|
+
# Create domain decomposition
|
|
855
|
+
D = DomainDecomposition(npts, periods=[P1, P2], comm=comm)
|
|
856
|
+
|
|
857
|
+
# Partition the points
|
|
858
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
859
|
+
C = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
860
|
+
|
|
861
|
+
# Create vector space and stencil vector
|
|
862
|
+
V = StencilVectorSpace(C, dtype=dtype)
|
|
863
|
+
x = StencilVector(V)
|
|
864
|
+
|
|
865
|
+
# Fill the vector with data
|
|
866
|
+
if dtype == complex:
|
|
867
|
+
f = lambda i1, i2: 10j * i1 + i2
|
|
868
|
+
else:
|
|
869
|
+
f = lambda i1, i2: 10 * i1 + i2
|
|
870
|
+
for i1 in range(V.starts[0], V.ends[0]+1):
|
|
871
|
+
for i2 in range(V.starts[1], V.ends[1]+1):
|
|
872
|
+
x[i1, i2] = f(i1, i2)
|
|
873
|
+
|
|
874
|
+
x.update_ghost_regions()
|
|
875
|
+
|
|
876
|
+
# Convert vector to array
|
|
877
|
+
xa = x.toarray()
|
|
878
|
+
|
|
879
|
+
# Apply array_to_psydac as left inverse of toarray
|
|
880
|
+
v_l_inv = array_to_psydac(xa, V)
|
|
881
|
+
|
|
882
|
+
# Apply array_to_psydac first, and toarray next
|
|
883
|
+
xa_r_inv = np.array(np.random.rand(xa.size), dtype=dtype)*xa # the vector must be distributed as xa
|
|
884
|
+
x_r_inv = array_to_psydac(xa_r_inv, V)
|
|
885
|
+
x_r_inv.update_ghost_regions()
|
|
886
|
+
va_r_inv = x_r_inv.toarray()
|
|
887
|
+
|
|
888
|
+
## Check that array_to_psydac is the inverse of .toarray():
|
|
889
|
+
# left inverse:
|
|
890
|
+
assert isinstance(v_l_inv, StencilVector)
|
|
891
|
+
assert v_l_inv.space is V
|
|
892
|
+
assert np.array_equal(x._data, v_l_inv._data)
|
|
893
|
+
# right inverse:
|
|
894
|
+
assert np.array_equal(xa_r_inv, va_r_inv)
|
|
895
|
+
|
|
896
|
+
# TODO: test that ghost regions have been properly copied to 'xe' array
|
|
897
|
+
# ===============================================================================
|
|
898
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
899
|
+
@pytest.mark.parametrize('n1', [6, 10])
|
|
900
|
+
@pytest.mark.parametrize('n2', [12, 15])
|
|
901
|
+
@pytest.mark.parametrize('p1', [1, 4])
|
|
902
|
+
@pytest.mark.parametrize('p2', [2])
|
|
903
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
904
|
+
@pytest.mark.parametrize('s2', [1])
|
|
905
|
+
@pytest.mark.parallel
|
|
906
|
+
def test_stencil_vector_2d_parallel_dot(dtype, n1, n2, p1, p2, s1, s2, P1=True, P2=False):
|
|
907
|
+
|
|
908
|
+
comm = MPI.COMM_WORLD
|
|
909
|
+
# Create domain decomposition
|
|
910
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2], comm=comm)
|
|
911
|
+
|
|
912
|
+
# Partition the points
|
|
913
|
+
npts = [n1, n2]
|
|
914
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
915
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
916
|
+
|
|
917
|
+
# Create vector space and stencil vectors
|
|
918
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
919
|
+
x = StencilVector(V)
|
|
920
|
+
y = StencilVector(V)
|
|
921
|
+
|
|
922
|
+
if dtype == complex:
|
|
923
|
+
f1 = lambda i1, i2: 100j * i1 + i2
|
|
924
|
+
f2 = lambda i1, i2: 10j * i2 - i1
|
|
925
|
+
else:
|
|
926
|
+
f1 = lambda i1, i2: 100 * i1 + i2
|
|
927
|
+
f2 = lambda i1, i2: 10 * i2 - i1
|
|
928
|
+
|
|
929
|
+
# Fill the vectors with data
|
|
930
|
+
for i1 in range(V.starts[0], V.ends[0] + 1):
|
|
931
|
+
for i2 in range(V.starts[1], V.ends[1] + 1):
|
|
932
|
+
x[i1, i2] = f1(i1,i2)
|
|
933
|
+
y[i1, i2] = f2(i1,i2)
|
|
934
|
+
|
|
935
|
+
# Create scalar product (x,y) and (y,x)
|
|
936
|
+
res1 = x.inner(y)
|
|
937
|
+
res2 = y.inner(x)
|
|
938
|
+
|
|
939
|
+
# Compute exact value with Numpy dot
|
|
940
|
+
if dtype==complex:
|
|
941
|
+
res_ex1 = comm.allreduce(np.vdot(x.toarray(), y.toarray()))
|
|
942
|
+
res_ex2 = comm.allreduce(np.vdot(y.toarray(), x.toarray()))
|
|
943
|
+
else:
|
|
944
|
+
res_ex1 = comm.allreduce(np.dot(x.toarray(), y.toarray()))
|
|
945
|
+
res_ex2 = res_ex1
|
|
946
|
+
|
|
947
|
+
# Compute axpy exact sol
|
|
948
|
+
if dtype == complex:
|
|
949
|
+
cst = 5j
|
|
950
|
+
else:
|
|
951
|
+
cst = 5
|
|
952
|
+
|
|
953
|
+
z3 = x + cst * y
|
|
954
|
+
x.mul_iadd(cst, y)
|
|
955
|
+
|
|
956
|
+
# Test exact value and symmetry of the scalar product
|
|
957
|
+
assert np.allclose(x._data, z3._data)
|
|
958
|
+
assert res1 == res_ex1
|
|
959
|
+
assert res2 == res_ex2
|
|
960
|
+
|
|
961
|
+
# ===============================================================================
|
|
962
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
963
|
+
@pytest.mark.parametrize('n1', [12, 24])
|
|
964
|
+
@pytest.mark.parametrize('n2', [9, 15])
|
|
965
|
+
@pytest.mark.parametrize('n3', [8])
|
|
966
|
+
@pytest.mark.parametrize('p1', [1, 3])
|
|
967
|
+
@pytest.mark.parametrize('p2', [1, 2])
|
|
968
|
+
@pytest.mark.parametrize('p3', [4])
|
|
969
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
970
|
+
@pytest.mark.parametrize('s2', [1, 2])
|
|
971
|
+
@pytest.mark.parametrize('s3', [1])
|
|
972
|
+
@pytest.mark.parallel
|
|
973
|
+
def test_stencil_vector_3d_parallel_dot(dtype, n1, n2, n3, p1, p2, p3, s1, s2, s3, P1=True, P2=False, P3=True):
|
|
974
|
+
|
|
975
|
+
comm = MPI.COMM_WORLD
|
|
976
|
+
# Create domain decomposition
|
|
977
|
+
D = DomainDecomposition([n1, n2, n3], periods=[P1, P2, P3], comm=comm)
|
|
978
|
+
|
|
979
|
+
# Partition the points
|
|
980
|
+
npts = [n1, n2, n3]
|
|
981
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts)
|
|
982
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2, p3], shifts=[s1, s2, s3])
|
|
983
|
+
|
|
984
|
+
# Create vector space and stencil vectors
|
|
985
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
986
|
+
x = StencilVector(V)
|
|
987
|
+
y = StencilVector(V)
|
|
988
|
+
|
|
989
|
+
# Fill the vectors with data
|
|
990
|
+
if dtype == complex:
|
|
991
|
+
f1 = lambda i1, i2, i3: 100 * i1 + i2+ 1j * i3
|
|
992
|
+
f2 = lambda i1, i2, i3: 10 * i3 - i1- 10j * i2
|
|
993
|
+
else:
|
|
994
|
+
f1 = lambda i1, i2, i3: 100 * i1 + i2+ i3
|
|
995
|
+
f2 = lambda i1, i2, i3: 10 * i3 - i1- i2
|
|
996
|
+
|
|
997
|
+
for i1 in range(V.starts[0], V.ends[0] + 1):
|
|
998
|
+
for i2 in range(V.starts[1], V.ends[1] + 1):
|
|
999
|
+
for i3 in range(V.starts[2], V.ends[2] + 1):
|
|
1000
|
+
x[i1, i2, i3] = f1(i1,i2,i3)
|
|
1001
|
+
x[i1, i2, i3] = f2(i1,i2,i3)
|
|
1002
|
+
|
|
1003
|
+
# Create scalar product (x,y) and (y,x)
|
|
1004
|
+
res1 = x.inner(y)
|
|
1005
|
+
res2 = y.inner(x)
|
|
1006
|
+
# Compute exact value with Numpy dot
|
|
1007
|
+
|
|
1008
|
+
if dtype == complex:
|
|
1009
|
+
res_ex1 = comm.allreduce(np.vdot(x.toarray(), y.toarray()))
|
|
1010
|
+
res_ex2 = comm.allreduce(np.vdot(y.toarray(), x.toarray()))
|
|
1011
|
+
else:
|
|
1012
|
+
res_ex1 = comm.allreduce(np.dot(x.toarray(), y.toarray()))
|
|
1013
|
+
res_ex2 = res_ex1
|
|
1014
|
+
|
|
1015
|
+
# Compute axpy exact sol
|
|
1016
|
+
if dtype == complex:
|
|
1017
|
+
cst = 5j
|
|
1018
|
+
else:
|
|
1019
|
+
cst = 5
|
|
1020
|
+
|
|
1021
|
+
z3 = x + cst * y
|
|
1022
|
+
x.mul_iadd(cst, y)
|
|
1023
|
+
|
|
1024
|
+
# Test exact value and symmetry of the scalar product
|
|
1025
|
+
assert np.allclose(x._data, z3._data)
|
|
1026
|
+
|
|
1027
|
+
assert res1 == res_ex1
|
|
1028
|
+
assert res2 == res_ex2
|
|
1029
|
+
|
|
1030
|
+
#===============================================================================
|
|
1031
|
+
# SCRIPT FUNCTIONALITY
|
|
1032
|
+
#===============================================================================
|
|
1033
|
+
if __name__ == "__main__":
|
|
1034
|
+
import sys
|
|
1035
|
+
|
|
1036
|
+
pytest.main(sys.argv)
|