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.
Files changed (98) hide show
  1. feectools/__init__.py +0 -0
  2. feectools/accelerate/__init__.py +0 -0
  3. feectools/accelerate/accelerate.py +220 -0
  4. feectools/accelerate/compile_psydac.mk +52 -0
  5. feectools/api/__init__.py +0 -0
  6. feectools/api/essential_bc.py +122 -0
  7. feectools/api/fem_bilinear_form.py +2226 -0
  8. feectools/api/fem_common.py +286 -0
  9. feectools/api/fem_sum_form.py +123 -0
  10. feectools/api/settings.py +82 -0
  11. feectools/core/__init__.py +11 -0
  12. feectools/core/bsplines.py +1107 -0
  13. feectools/core/bsplines_kernels.py +1349 -0
  14. feectools/core/field_evaluation_kernels.py +5015 -0
  15. feectools/core/tests/__init__.py +0 -0
  16. feectools/core/tests/test_bsplines.py +263 -0
  17. feectools/core/tests/test_bsplines_kernel.py +40 -0
  18. feectools/core/tests/test_bsplines_pyccel.py +752 -0
  19. feectools/ddm/__init__.py +3 -0
  20. feectools/ddm/basic.py +78 -0
  21. feectools/ddm/blocking_data_exchanger.py +348 -0
  22. feectools/ddm/cart.py +1835 -0
  23. feectools/ddm/interface_data_exchanger.py +122 -0
  24. feectools/ddm/mpi.py +109 -0
  25. feectools/ddm/nonblocking_data_exchanger.py +331 -0
  26. feectools/ddm/partition.py +207 -0
  27. feectools/ddm/petsc.py +112 -0
  28. feectools/ddm/tests/__init__.py +0 -0
  29. feectools/ddm/tests/test_cart_1d.py +138 -0
  30. feectools/ddm/tests/test_cart_2d.py +164 -0
  31. feectools/ddm/tests/test_cart_3d.py +158 -0
  32. feectools/ddm/tests/test_multicart_2d.py +173 -0
  33. feectools/ddm/tests/test_partition.py +124 -0
  34. feectools/ddm/utilities.py +24 -0
  35. feectools/feec/__init__.py +0 -0
  36. feectools/feec/derivatives.py +780 -0
  37. feectools/feec/dof_kernels.py +210 -0
  38. feectools/feec/global_geometric_projectors.py +1073 -0
  39. feectools/feec/hodge.py +148 -0
  40. feectools/fem/__init__.py +0 -0
  41. feectools/fem/basic.py +465 -0
  42. feectools/fem/grid.py +181 -0
  43. feectools/fem/partitioning.py +344 -0
  44. feectools/fem/projectors.py +160 -0
  45. feectools/fem/splines.py +559 -0
  46. feectools/fem/tensor.py +1393 -0
  47. feectools/fem/tests/__init__.py +0 -0
  48. feectools/fem/tests/analytical_profiles_1d.py +100 -0
  49. feectools/fem/tests/analytical_profiles_base.py +34 -0
  50. feectools/fem/tests/splines_error_bounds.py +155 -0
  51. feectools/fem/tests/test_spline_histopolation.py +120 -0
  52. feectools/fem/tests/test_spline_interpolation.py +182 -0
  53. feectools/fem/tests/test_splines.py +184 -0
  54. feectools/fem/tests/test_splines_par.py +46 -0
  55. feectools/fem/tests/test_vector_spaces.py +150 -0
  56. feectools/fem/tests/utilities.py +47 -0
  57. feectools/fem/vector.py +729 -0
  58. feectools/linalg/__init__.py +0 -0
  59. feectools/linalg/basic.py +1386 -0
  60. feectools/linalg/block.py +1451 -0
  61. feectools/linalg/direct_solvers.py +201 -0
  62. feectools/linalg/fft.py +258 -0
  63. feectools/linalg/kernels/__init__.py +0 -0
  64. feectools/linalg/kernels/axpy_kernels.py +57 -0
  65. feectools/linalg/kernels/inner_kernels.py +100 -0
  66. feectools/linalg/kernels/matvec_kernels.py +206 -0
  67. feectools/linalg/kernels/stencil2IJV_kernels.py +227 -0
  68. feectools/linalg/kernels/stencil2coo_kernels.py +179 -0
  69. feectools/linalg/kernels/transpose_kernels.py +263 -0
  70. feectools/linalg/kron.py +911 -0
  71. feectools/linalg/solvers.py +1914 -0
  72. feectools/linalg/sparse.py +114 -0
  73. feectools/linalg/stencil.py +2923 -0
  74. feectools/linalg/stencil_dot_kernels.py +317 -0
  75. feectools/linalg/stencil_transpose_kernels.py +372 -0
  76. feectools/linalg/tests/__init__.py +0 -0
  77. feectools/linalg/tests/test_block.py +1588 -0
  78. feectools/linalg/tests/test_fft.py +106 -0
  79. feectools/linalg/tests/test_kron_stencil_matrix.py +114 -0
  80. feectools/linalg/tests/test_linalg.py +1065 -0
  81. feectools/linalg/tests/test_matrix_free.py +128 -0
  82. feectools/linalg/tests/test_solvers.py +213 -0
  83. feectools/linalg/tests/test_stencil_interface_matrix.py +379 -0
  84. feectools/linalg/tests/test_stencil_vector.py +1036 -0
  85. feectools/linalg/tests/test_stencil_vector_space.py +440 -0
  86. feectools/linalg/topetsc.py +522 -0
  87. feectools/linalg/utilities.py +200 -0
  88. feectools/utilities/__init__.py +0 -0
  89. feectools/utilities/quadratures.py +113 -0
  90. feectools/utilities/utils.py +166 -0
  91. feectools/version.py +1 -0
  92. feectools-0.1.0.dist-info/METADATA +66 -0
  93. feectools-0.1.0.dist-info/RECORD +98 -0
  94. feectools-0.1.0.dist-info/WHEEL +5 -0
  95. feectools-0.1.0.dist-info/entry_points.txt +3 -0
  96. feectools-0.1.0.dist-info/licenses/AUTHORS +22 -0
  97. feectools-0.1.0.dist-info/licenses/LICENSE +21 -0
  98. 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)