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,379 @@
|
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
import numpy as np
|
|
5
|
+
from random import random
|
|
6
|
+
|
|
7
|
+
from feectools.linalg.stencil import StencilVectorSpace, StencilVector, StencilMatrix, StencilInterfaceMatrix
|
|
8
|
+
from feectools.api.settings import *
|
|
9
|
+
from feectools.ddm.cart import DomainDecomposition, CartDecomposition
|
|
10
|
+
|
|
11
|
+
#===============================================================================
|
|
12
|
+
def compute_global_starts_ends(domain_decomposition, npts, pads):
|
|
13
|
+
ndims = len(npts)
|
|
14
|
+
global_starts = [None]*ndims
|
|
15
|
+
global_ends = [None]*ndims
|
|
16
|
+
|
|
17
|
+
for axis in range(ndims):
|
|
18
|
+
ee = domain_decomposition.global_element_ends [axis]
|
|
19
|
+
|
|
20
|
+
global_ends [axis] = ee.copy()
|
|
21
|
+
global_ends [axis][-1] = npts[axis]-1
|
|
22
|
+
global_starts[axis] = np.array([0] + (global_ends[axis][:-1]+1).tolist())
|
|
23
|
+
|
|
24
|
+
for s, e, p in zip(global_starts, global_ends, pads):
|
|
25
|
+
assert all(e - s + 1 >= p)
|
|
26
|
+
|
|
27
|
+
return tuple(global_starts), tuple(global_ends)
|
|
28
|
+
|
|
29
|
+
#===============================================================================
|
|
30
|
+
def get_minus_starts_ends(plus_starts, plus_ends, minus_npts, plus_npts, minus_axis, plus_axis,
|
|
31
|
+
minus_ext, plus_ext, minus_pads, plus_pads, minus_shifts, plus_shifts,
|
|
32
|
+
diff):
|
|
33
|
+
"""
|
|
34
|
+
Compute the coefficients needed by the minus patch in a given interface.
|
|
35
|
+
"""
|
|
36
|
+
starts = [max(0,s-m*p) for s,m,p in zip(plus_starts, minus_shifts, minus_pads)]
|
|
37
|
+
ends = [min(n,e+m*p) for e,n,m,p in zip(plus_ends, minus_npts, minus_shifts, minus_pads)]
|
|
38
|
+
starts[minus_axis] = 0 if minus_ext == -1 else ends[minus_axis]-minus_pads[minus_axis]
|
|
39
|
+
ends[minus_axis] = ends[minus_axis] if minus_ext == 1 else minus_pads[minus_axis]
|
|
40
|
+
return starts, ends
|
|
41
|
+
|
|
42
|
+
#------------------------------------------------------------------------------
|
|
43
|
+
def get_plus_starts_ends(minus_starts, minus_ends, minus_npts, plus_npts, minus_axis, plus_axis,
|
|
44
|
+
minus_ext, plus_ext, minus_pads, plus_pads, minus_shifts, plus_shifts,
|
|
45
|
+
diff):
|
|
46
|
+
"""
|
|
47
|
+
Compute the coefficients needed by the plus patch in a given interface.
|
|
48
|
+
"""
|
|
49
|
+
starts = [max(0,s-m*p) for s,m,p in zip(minus_starts, plus_shifts, plus_pads)]
|
|
50
|
+
ends = [min(n,e+m*p) for e,n,m,p in zip(minus_ends, plus_npts, plus_shifts, plus_pads)]
|
|
51
|
+
starts[plus_axis] = 0 if plus_ext == -1 else ends[plus_axis]-plus_pads[plus_axis]
|
|
52
|
+
ends[plus_axis] = ends[plus_axis] if plus_ext == 1 else plus_pads[plus_axis]
|
|
53
|
+
return starts, ends
|
|
54
|
+
|
|
55
|
+
# TODO : Add test about dot, div, transpose, toarray, tosparse, copy, basic operation, max, exchange_assembly_data, set_backend
|
|
56
|
+
# ===============================================================================
|
|
57
|
+
# SERIAL TESTS
|
|
58
|
+
# ===============================================================================
|
|
59
|
+
|
|
60
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
61
|
+
@pytest.mark.parametrize('axis', [0])
|
|
62
|
+
@pytest.mark.parametrize('ext', [-1, 1])
|
|
63
|
+
@pytest.mark.parametrize('n1', [7, 15])
|
|
64
|
+
@pytest.mark.parametrize('p1', [2, 4])
|
|
65
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
66
|
+
def test_stencil_interface_matrix_1d_serial_init(dtype, n1, p1, s1, axis, ext, P1=True):
|
|
67
|
+
# Create domain decomposition
|
|
68
|
+
D = DomainDecomposition([n1], periods=[P1])
|
|
69
|
+
|
|
70
|
+
# Partition the points
|
|
71
|
+
npts = [n1]
|
|
72
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts, [p1])
|
|
73
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1], shifts=[s1])
|
|
74
|
+
|
|
75
|
+
# Create a vector space V and a matrix M from V to V
|
|
76
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
77
|
+
V.set_interface(axis, ext, cart)
|
|
78
|
+
W = StencilVectorSpace(cart, dtype=dtype)
|
|
79
|
+
W.set_interface(axis, -ext, cart)
|
|
80
|
+
M = StencilInterfaceMatrix(V, W, global_starts, global_starts, axis, axis, ext, -ext)
|
|
81
|
+
|
|
82
|
+
# Check properties of this matrix
|
|
83
|
+
assert M.domain == V
|
|
84
|
+
assert M.codomain == W
|
|
85
|
+
assert M.dtype == dtype
|
|
86
|
+
assert M.domain_axis == axis
|
|
87
|
+
assert M.codomain_axis == axis
|
|
88
|
+
assert M.domain_ext == ext
|
|
89
|
+
assert M.codomain_ext == -ext
|
|
90
|
+
assert M.dim == 1
|
|
91
|
+
assert M.domain_start == (0,) * M.dim
|
|
92
|
+
assert M.codomain_start == (0,) * M.dim
|
|
93
|
+
assert M.flip == (1,) * M.dim
|
|
94
|
+
assert np.array_equal(M.permutation, [0])
|
|
95
|
+
assert M.pads == (p1,)
|
|
96
|
+
assert M.backend == None
|
|
97
|
+
assert M._data.shape == (p1 + 1 + 2 * p1 * s1, 1 + 2 * p1)
|
|
98
|
+
assert M.shape == (n1, n1)
|
|
99
|
+
|
|
100
|
+
# ===============================================================================
|
|
101
|
+
|
|
102
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
103
|
+
@pytest.mark.parametrize('axis1', [0, 1])
|
|
104
|
+
@pytest.mark.parametrize('axis2', [0, 1])
|
|
105
|
+
@pytest.mark.parametrize('ext1', [-1, 1])
|
|
106
|
+
@pytest.mark.parametrize('ext2', [-1, 1])
|
|
107
|
+
@pytest.mark.parametrize('n1', [7, 15])
|
|
108
|
+
@pytest.mark.parametrize('n2', [7, 15])
|
|
109
|
+
@pytest.mark.parametrize('p1', [2, 3])
|
|
110
|
+
@pytest.mark.parametrize('p2', [2, 3])
|
|
111
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
112
|
+
@pytest.mark.parametrize('s2', [1, 2])
|
|
113
|
+
def test_stencil_interface_matrix_2d_serial_init(dtype, n1, n2, p1, p2, s1, s2, axis1, axis2, ext1, ext2, P1=True,
|
|
114
|
+
P2=True):
|
|
115
|
+
# Create domain decomposition
|
|
116
|
+
D = DomainDecomposition([n1, n2], periods=[P1, P2])
|
|
117
|
+
|
|
118
|
+
# Partition the points
|
|
119
|
+
npts = [n1, n2]
|
|
120
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts, [p1, p2])
|
|
121
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2], shifts=[s1, s2])
|
|
122
|
+
|
|
123
|
+
# Create a vector space V and a matrix M from V to V
|
|
124
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
125
|
+
V.set_interface(axis1, ext1, cart)
|
|
126
|
+
W = StencilVectorSpace(cart, dtype=dtype)
|
|
127
|
+
W.set_interface(axis2, ext2, cart)
|
|
128
|
+
M = StencilInterfaceMatrix(V, W, global_starts, global_starts, axis1, axis2, ext1, ext2)
|
|
129
|
+
|
|
130
|
+
# Check properties of this matrix
|
|
131
|
+
assert M.domain == V
|
|
132
|
+
assert M.codomain == W
|
|
133
|
+
assert M.dtype == dtype
|
|
134
|
+
assert M.domain_axis == axis1
|
|
135
|
+
assert M.codomain_axis == axis2
|
|
136
|
+
assert M.domain_ext == ext1
|
|
137
|
+
assert M.codomain_ext == ext2
|
|
138
|
+
assert M.dim == 2
|
|
139
|
+
assert M.domain_start == (0,) * M.dim
|
|
140
|
+
assert M.codomain_start == (0,) * M.dim
|
|
141
|
+
assert M.flip == (1,) * M.dim
|
|
142
|
+
assert M.pads == (p1, p2)
|
|
143
|
+
assert M.backend == None
|
|
144
|
+
if axis2 == 0:
|
|
145
|
+
assert M._data.shape == (p1 + 1 + 2 * p1 * s1, n2 + 2 * p2 * s2, 1 + 2 * p1, 1 + 2 * p2)
|
|
146
|
+
elif axis2 == 1:
|
|
147
|
+
assert M._data.shape == (n1 + 2 * p1 * s1, p2 + 1 + 2 * p2 * s2, 1 + 2 * p1, 1 + 2 * p2)
|
|
148
|
+
if axis1 == axis2:
|
|
149
|
+
assert np.array_equal(M.permutation, [0, 1])
|
|
150
|
+
else:
|
|
151
|
+
assert np.array_equal(M.permutation, [1, 0])
|
|
152
|
+
assert M.shape == (n1 * n2, n1 * n2)
|
|
153
|
+
|
|
154
|
+
# ===============================================================================
|
|
155
|
+
|
|
156
|
+
@pytest.mark.parametrize('dtype', [float, complex])
|
|
157
|
+
@pytest.mark.parametrize('axis1', [0, 1, 2])
|
|
158
|
+
@pytest.mark.parametrize('axis2', [0, 1, 2])
|
|
159
|
+
@pytest.mark.parametrize('ext1', [-1, 1])
|
|
160
|
+
@pytest.mark.parametrize('ext2', [-1, 1])
|
|
161
|
+
@pytest.mark.parametrize('n1', [7, 15])
|
|
162
|
+
@pytest.mark.parametrize('n2', [7, 15])
|
|
163
|
+
@pytest.mark.parametrize('n3', [6])
|
|
164
|
+
@pytest.mark.parametrize('p1', [2, 3])
|
|
165
|
+
@pytest.mark.parametrize('p2', [2, 3])
|
|
166
|
+
@pytest.mark.parametrize('p3', [1])
|
|
167
|
+
@pytest.mark.parametrize('s1', [1, 2])
|
|
168
|
+
@pytest.mark.parametrize('s2', [1, 2])
|
|
169
|
+
@pytest.mark.parametrize('s3', [3])
|
|
170
|
+
def test_stencil_interface_matrix_3d_serial_init(dtype, n1, n2, n3, p1, p2, p3, s1, s2, s3, axis1, axis2,
|
|
171
|
+
ext1, ext2, P1=True, P2=True, P3=False):
|
|
172
|
+
# Create domain decomposition
|
|
173
|
+
D = DomainDecomposition([n1, n2, n3], periods=[P1, P2, P3])
|
|
174
|
+
|
|
175
|
+
# Partition the points
|
|
176
|
+
npts = [n1, n2, n3]
|
|
177
|
+
global_starts, global_ends = compute_global_starts_ends(D, npts, [p1, p2, p3])
|
|
178
|
+
cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1, p2, p3], shifts=[s1, s2, s3])
|
|
179
|
+
|
|
180
|
+
# Create a vector space V and a matrix M from V to V
|
|
181
|
+
V = StencilVectorSpace(cart, dtype=dtype)
|
|
182
|
+
V.set_interface(axis1, ext1, cart)
|
|
183
|
+
W = StencilVectorSpace(cart, dtype=dtype)
|
|
184
|
+
W.set_interface(axis2, ext2, cart)
|
|
185
|
+
M = StencilInterfaceMatrix(V, W, global_starts, global_starts, axis1, axis2, ext1, ext2)
|
|
186
|
+
|
|
187
|
+
# Check properties of this matrix
|
|
188
|
+
assert M.domain == V
|
|
189
|
+
assert M.codomain == W
|
|
190
|
+
assert M.dtype == dtype
|
|
191
|
+
assert M.domain_axis == axis1
|
|
192
|
+
assert M.codomain_axis == axis2
|
|
193
|
+
assert M.domain_ext == ext1
|
|
194
|
+
assert M.codomain_ext == ext2
|
|
195
|
+
assert M.dim == 3
|
|
196
|
+
assert M.domain_start == (0,) * M.dim
|
|
197
|
+
assert M.codomain_start == (0,) * M.dim
|
|
198
|
+
assert M.flip == (1,) * M.dim
|
|
199
|
+
assert M.pads == (p1, p2, p3)
|
|
200
|
+
assert M.backend == None
|
|
201
|
+
if axis2 == 0:
|
|
202
|
+
assert M._data.shape == (
|
|
203
|
+
p1 + 1 + 2 * p1 * s1, n2 + 2 * p2 * s2, n3 + 2 * p3 * s3, 1 + 2 * p1, 1 + 2 * p2, 1 + 2 * p3)
|
|
204
|
+
elif axis2 == 1:
|
|
205
|
+
assert M._data.shape == (
|
|
206
|
+
n1 + 2 * p1 * s1, p2 + 1 + 2 * p2 * s2, n3 + 2 * p3 * s3, 1 + 2 * p1, 1 + 2 * p2, 1 + 2 * p3)
|
|
207
|
+
elif axis2 == 2:
|
|
208
|
+
assert M._data.shape == (
|
|
209
|
+
n1 + 2 * p1 * s1, n2 + 2 * p2 * s2, p3 + 1 + 2 * p3 * s3, 1 + 2 * p1, 1 + 2 * p2, 1 + 2 * p3)
|
|
210
|
+
if axis1 == axis2:
|
|
211
|
+
assert np.array_equal(M.permutation, [0, 1, 2])
|
|
212
|
+
else:
|
|
213
|
+
permutation = [0, 1, 2]
|
|
214
|
+
permutation[axis1], permutation[axis2] = permutation[axis2], permutation[axis1]
|
|
215
|
+
assert np.array_equal(M.permutation, permutation)
|
|
216
|
+
assert M.shape == (n1 * n2 * n3, n1 * n2 * n3)
|
|
217
|
+
#===============================================================================
|
|
218
|
+
# Parallel TESTS
|
|
219
|
+
#===============================================================================
|
|
220
|
+
@pytest.mark.parametrize("n1,n2,p1,p2,expected", [(8,8,1,1, 827301207168.0),
|
|
221
|
+
(8,8,2,2, 4824719287396.0),
|
|
222
|
+
(8,8,3,3, 13615010842712.0),
|
|
223
|
+
(12,12,1,1, 3023467041788.0),
|
|
224
|
+
(12,12,2,2, 19555497680544.0),
|
|
225
|
+
(12,12,3,3, 62573623909332.0)])
|
|
226
|
+
@pytest.mark.parallel
|
|
227
|
+
def test_stencil_interface_matrix_2d_parallel_dot(n1, n2, p1, p2, expected):
|
|
228
|
+
|
|
229
|
+
from feectools.ddm.mpi import mpi as MPI
|
|
230
|
+
from feectools.ddm.cart import MultiPatchDomainDecomposition, CartDecomposition, create_interfaces_cart
|
|
231
|
+
from feectools.linalg.block import BlockVectorSpace, BlockVector, BlockLinearOperator
|
|
232
|
+
|
|
233
|
+
# Number of patches
|
|
234
|
+
N = 2
|
|
235
|
+
|
|
236
|
+
nc = [[n1-p1,n2-p2] for i in range(N)]
|
|
237
|
+
|
|
238
|
+
# Periodicity
|
|
239
|
+
P = [[False, False] for i in range(N)]
|
|
240
|
+
|
|
241
|
+
axis = 0
|
|
242
|
+
connectivity = {(0,1):((axis,1),(axis,-1))}
|
|
243
|
+
|
|
244
|
+
comm = MPI.COMM_WORLD
|
|
245
|
+
# Parallel info
|
|
246
|
+
|
|
247
|
+
domain_decomposition = MultiPatchDomainDecomposition(nc, P, comm=comm)
|
|
248
|
+
|
|
249
|
+
# Number of elements
|
|
250
|
+
n = [[n1,n2] for i in range(N)]
|
|
251
|
+
|
|
252
|
+
# Padding ('thickness' of ghost region)
|
|
253
|
+
p = [[p1,p2] for i in range(N)]
|
|
254
|
+
|
|
255
|
+
carts = []
|
|
256
|
+
for i in range(N):
|
|
257
|
+
global_starts = [None]*2
|
|
258
|
+
global_ends = [None]*2
|
|
259
|
+
for j in range(2):
|
|
260
|
+
es = domain_decomposition.domains[i].global_element_starts[j]
|
|
261
|
+
ee = domain_decomposition.domains[i].global_element_ends [j]
|
|
262
|
+
|
|
263
|
+
global_ends [j] = ee.copy()
|
|
264
|
+
global_ends [j][-1] = n[i][j]-1
|
|
265
|
+
global_starts[j] = np.array([0] + (global_ends[j][:-1]+1).tolist())
|
|
266
|
+
|
|
267
|
+
carts.append(CartDecomposition(
|
|
268
|
+
domain_decomposition = domain_decomposition.domains[i],
|
|
269
|
+
npts = n[i],
|
|
270
|
+
global_starts = global_starts,
|
|
271
|
+
global_ends = global_ends,
|
|
272
|
+
pads = p[i],
|
|
273
|
+
shifts = [1,1]))
|
|
274
|
+
carts = tuple(carts)
|
|
275
|
+
|
|
276
|
+
communication_info = (get_minus_starts_ends, get_plus_starts_ends)
|
|
277
|
+
interface_carts = create_interfaces_cart(domain_decomposition, carts, connectivity, communication_info=communication_info)
|
|
278
|
+
|
|
279
|
+
# Create vector spaces
|
|
280
|
+
Vs = [StencilVectorSpace( ci ) for ci in carts]
|
|
281
|
+
|
|
282
|
+
# Create the interface spaces
|
|
283
|
+
for i,j in connectivity:
|
|
284
|
+
|
|
285
|
+
if not carts[i].is_comm_null and not carts[j].is_comm_null:
|
|
286
|
+
cart_minus = carts[i]
|
|
287
|
+
cart_plus = carts[j]
|
|
288
|
+
elif (i,j) in interface_carts:
|
|
289
|
+
cart_minus = interface_carts[i,j]
|
|
290
|
+
cart_plus = interface_carts[i,j]
|
|
291
|
+
else:
|
|
292
|
+
continue
|
|
293
|
+
|
|
294
|
+
((axis_minus, ext_minus), (axis_plus , ext_plus)) = connectivity[i, j]
|
|
295
|
+
# set interface space for the minus space
|
|
296
|
+
|
|
297
|
+
Vs[i].set_interface(axis_minus, ext_minus, cart_minus)
|
|
298
|
+
|
|
299
|
+
# set interface space for the plus space
|
|
300
|
+
Vs[j].set_interface(axis_plus , ext_plus, cart_plus)
|
|
301
|
+
|
|
302
|
+
V = BlockVectorSpace(*Vs, connectivity=connectivity)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
# ...
|
|
306
|
+
# Fill in vector with some values, then update ghost regions
|
|
307
|
+
x = BlockVector( V )
|
|
308
|
+
for i,ci in enumerate(carts):
|
|
309
|
+
if ci.is_comm_null:continue
|
|
310
|
+
s1,s2 = ci.starts
|
|
311
|
+
e1,e2 = ci.ends
|
|
312
|
+
for i1 in range(s1,e1+1):
|
|
313
|
+
for i2 in range(s2,e2+1):
|
|
314
|
+
x[i][i1,i2] = 1
|
|
315
|
+
|
|
316
|
+
# ...
|
|
317
|
+
# Fill in the Matrix with some values
|
|
318
|
+
A = BlockLinearOperator( V, V )
|
|
319
|
+
|
|
320
|
+
# Fill-in pattern
|
|
321
|
+
fill_in = lambda i, i1, i2, k1, k2: 10000*i + 1000*i1 + 100*i2 + 10*abs(k1) + abs(k2)
|
|
322
|
+
|
|
323
|
+
for i,ci in enumerate(carts):
|
|
324
|
+
if ci.is_comm_null:continue
|
|
325
|
+
Aii = StencilMatrix( Vs[i], Vs[i])
|
|
326
|
+
s1,s2 = ci.starts
|
|
327
|
+
e1,e2 = ci.ends
|
|
328
|
+
# Fill in stencil matrix
|
|
329
|
+
for i1 in range(s1, e1+1):
|
|
330
|
+
for i2 in range(s2, e2+1):
|
|
331
|
+
for k1 in range(-p1, p1+1):
|
|
332
|
+
for k2 in range(-p2, p2+1):
|
|
333
|
+
Aii[i1, i2, k1, k2] = fill_in( i, i1, i2, k1, k2 )
|
|
334
|
+
|
|
335
|
+
Aii.remove_spurious_entries()
|
|
336
|
+
A[i,i] = Aii
|
|
337
|
+
|
|
338
|
+
# Fill in stencil interface matrix if the process is on the boundary
|
|
339
|
+
if not carts[0].is_comm_null and (not carts[1].is_comm_null or not interface_carts[0,1].is_comm_null):
|
|
340
|
+
s_d = 0
|
|
341
|
+
s_c = n[0][axis]-p[0][axis]-1-Vs[0].starts[axis]
|
|
342
|
+
A01 = StencilInterfaceMatrix(Vs[1], Vs[0], s_d, s_c, d_axis=axis, c_axis=axis, d_ext=-1, c_ext=1)
|
|
343
|
+
|
|
344
|
+
s1,s2 = carts[0].starts
|
|
345
|
+
e1,e2 = carts[0].ends
|
|
346
|
+
p1,p2 = Vs[0].pads
|
|
347
|
+
|
|
348
|
+
for i2 in range(s2, e2+1):
|
|
349
|
+
A01._data[2*p1,i2+p2-s2,0,p2] = -i2-1
|
|
350
|
+
|
|
351
|
+
A[0,1] = A01
|
|
352
|
+
|
|
353
|
+
if not carts[1].is_comm_null and (not carts[0].is_comm_null or not interface_carts[0,1].is_comm_null):
|
|
354
|
+
s_d = n[0][axis]-p[0][axis]-1-Vs[0].starts[axis]
|
|
355
|
+
s_c = 0
|
|
356
|
+
A10 = StencilInterfaceMatrix(Vs[0], Vs[1], s_d, s_c, d_axis=axis, c_axis=axis, d_ext=1, c_ext=-1)
|
|
357
|
+
|
|
358
|
+
s1,s2 = carts[1].starts
|
|
359
|
+
e1,e2 = carts[1].ends
|
|
360
|
+
p1,p2 = Vs[1].pads
|
|
361
|
+
for i2 in range(s2, e2+1):
|
|
362
|
+
A10._data[p1,i2+p2-s2,2*p1,p2] = -i2-1
|
|
363
|
+
|
|
364
|
+
A[1,0] = A10
|
|
365
|
+
|
|
366
|
+
A = A.T.T
|
|
367
|
+
# Updateh ghost regions and compute matrix-vector product
|
|
368
|
+
x.update_ghost_regions()
|
|
369
|
+
y = A.dot(x)
|
|
370
|
+
|
|
371
|
+
# Check the results
|
|
372
|
+
assert y.inner(y) == expected
|
|
373
|
+
|
|
374
|
+
#===============================================================================
|
|
375
|
+
# SCRIPT FUNCTIONALITY
|
|
376
|
+
#===============================================================================
|
|
377
|
+
if __name__ == "__main__":
|
|
378
|
+
import sys
|
|
379
|
+
pytest.main( sys.argv )
|