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
feectools/ddm/basic.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
__all__ = ('CartDataExchanger',)
|
|
6
|
+
#===============================================================================
|
|
7
|
+
class CartDataExchanger(ABC):
|
|
8
|
+
"""
|
|
9
|
+
Type that takes care of updating the ghost regions (padding) of a
|
|
10
|
+
multi-dimensional array distributed according to the given Cartesian
|
|
11
|
+
decomposition of a tensor-product grid of coefficients.
|
|
12
|
+
|
|
13
|
+
Each coefficient in the decomposed grid may have multiple components,
|
|
14
|
+
contiguous in memory.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
cart : feectools.ddm.CartDecomposition
|
|
19
|
+
Object that contains all information about the Cartesian decomposition
|
|
20
|
+
of a tensor-product grid of coefficients.
|
|
21
|
+
|
|
22
|
+
dtype : [type | str | numpy.dtype | mpi4py.MPI.Datatype]
|
|
23
|
+
Datatype of single coefficient (if scalar) or of each of its
|
|
24
|
+
components (if vector).
|
|
25
|
+
|
|
26
|
+
coeff_shape : [tuple(int) | list(int)]
|
|
27
|
+
Shape of a single coefficient, if this is multi-dimensional
|
|
28
|
+
(optional: by default, we assume scalar coefficients).
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
#---------------------------------------------------------------------------
|
|
33
|
+
# Public interface
|
|
34
|
+
#---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def prepare_communications(self, u):
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def start_update_ghost_regions( self, array, requests ):
|
|
42
|
+
"""
|
|
43
|
+
Update ghost regions in a numpy array with dimensions compatible with
|
|
44
|
+
CartDecomposition (and coeff_shape) provided at initialization.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
array : numpy.ndarray
|
|
49
|
+
Multidimensional array corresponding to local subdomain in
|
|
50
|
+
decomposed tensor grid, including padding.
|
|
51
|
+
|
|
52
|
+
requests : tuple|None
|
|
53
|
+
The requests of the communications.
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def end_update_ghost_regions( self, array, requests ):
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def start_exchange_assembly_data( self, array ):
|
|
63
|
+
"""
|
|
64
|
+
Update ghost regions after the assembly algorithm in a numpy array
|
|
65
|
+
with dimensions compatible with CartDecomposition (and coeff_shape)
|
|
66
|
+
provided at initialization.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
array : numpy.ndarray
|
|
71
|
+
Multidimensional array corresponding to local subdomain in
|
|
72
|
+
decomposed tensor grid, including padding.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def end_exchange_assembly_data( self, array ):
|
|
77
|
+
pass
|
|
78
|
+
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from feectools.ddm.mpi import mpi as MPI
|
|
5
|
+
|
|
6
|
+
from .cart import CartDecomposition, find_mpi_type
|
|
7
|
+
from .basic import CartDataExchanger
|
|
8
|
+
|
|
9
|
+
__all__ = ('BlockingCartDataExchanger',)
|
|
10
|
+
|
|
11
|
+
class BlockingCartDataExchanger(CartDataExchanger):
|
|
12
|
+
"""
|
|
13
|
+
Type that takes care of updating the ghost regions (padding) of a
|
|
14
|
+
multi-dimensional array distributed according to the given Cartesian
|
|
15
|
+
decomposition of a tensor-product grid of coefficients.
|
|
16
|
+
|
|
17
|
+
Each coefficient in the decomposed grid may have multiple components,
|
|
18
|
+
contiguous in memory.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
cart : feectools.ddm.CartDecomposition
|
|
23
|
+
Object that contains all information about the Cartesian decomposition
|
|
24
|
+
of a tensor-product grid of coefficients.
|
|
25
|
+
|
|
26
|
+
dtype : [type | str | numpy.dtype | mpi4py.MPI.Datatype]
|
|
27
|
+
Datatype of single coefficient (if scalar) or of each of its
|
|
28
|
+
components (if vector).
|
|
29
|
+
|
|
30
|
+
coeff_shape : [tuple(int) | list(int)]
|
|
31
|
+
Shape of a single coefficient, if this is multi-dimensional
|
|
32
|
+
(optional: by default, we assume scalar coefficients).
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
def __init__( self, cart, dtype, *, coeff_shape=(), assembly=False, axis=None, shape=None ):
|
|
36
|
+
|
|
37
|
+
self._send_types, self._recv_types = self._create_buffer_types(
|
|
38
|
+
cart, dtype, coeff_shape=coeff_shape )
|
|
39
|
+
|
|
40
|
+
self._cart = cart
|
|
41
|
+
self._comm = cart.comm_cart
|
|
42
|
+
self._axis = axis
|
|
43
|
+
|
|
44
|
+
if assembly:
|
|
45
|
+
self._assembly_send_types, self._assembly_recv_types = self._create_assembly_buffer_types(
|
|
46
|
+
cart, dtype, coeff_shape=coeff_shape, axis=axis, shape=shape)
|
|
47
|
+
|
|
48
|
+
#---------------------------------------------------------------------------
|
|
49
|
+
# Public interface
|
|
50
|
+
#---------------------------------------------------------------------------
|
|
51
|
+
def get_send_type( self, *args ):
|
|
52
|
+
direction = args[0]
|
|
53
|
+
disp = args[1]
|
|
54
|
+
return self._send_types[direction, disp]
|
|
55
|
+
|
|
56
|
+
# ...
|
|
57
|
+
def get_recv_type( self, *args ):
|
|
58
|
+
direction = args[0]
|
|
59
|
+
disp = args[1]
|
|
60
|
+
return self._recv_types[direction, disp]
|
|
61
|
+
|
|
62
|
+
# ...
|
|
63
|
+
def get_assembly_send_type( self,*args ):
|
|
64
|
+
direction = args[0]
|
|
65
|
+
disp = args[1]
|
|
66
|
+
return self._assembly_send_types[direction, disp]
|
|
67
|
+
|
|
68
|
+
# ...
|
|
69
|
+
def get_assembly_recv_type( self, *args ):
|
|
70
|
+
direction = args[0]
|
|
71
|
+
disp = args[1]
|
|
72
|
+
return self._assembly_recv_types[direction, disp]
|
|
73
|
+
|
|
74
|
+
# ...
|
|
75
|
+
def prepare_communications(self, u):
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
# ...
|
|
79
|
+
def start_update_ghost_regions( self, array, requests ):
|
|
80
|
+
|
|
81
|
+
assert isinstance( array, np.ndarray )
|
|
82
|
+
|
|
83
|
+
# Shortcuts
|
|
84
|
+
cart = self._cart
|
|
85
|
+
comm = self._comm
|
|
86
|
+
|
|
87
|
+
# Choose non-negative invertible function tag(disp) >= 0
|
|
88
|
+
# NOTES:
|
|
89
|
+
# . different values of disp must return different tags!
|
|
90
|
+
# . tag at receiver must match message tag at sender
|
|
91
|
+
tag = lambda disp: 42+disp
|
|
92
|
+
|
|
93
|
+
for direction in range( self._cart.ndim ):
|
|
94
|
+
# Requests' handles
|
|
95
|
+
requests = []
|
|
96
|
+
|
|
97
|
+
# Start receiving data (MPI_IRECV)
|
|
98
|
+
for disp in [-1,1]:
|
|
99
|
+
info = cart.get_shift_info( direction, disp )
|
|
100
|
+
recv_typ = self.get_recv_type ( direction, disp )
|
|
101
|
+
recv_buf = (array, 1, recv_typ)
|
|
102
|
+
recv_req = comm.Irecv( recv_buf, info['rank_source'], tag(disp) )
|
|
103
|
+
requests.append( recv_req )
|
|
104
|
+
|
|
105
|
+
# Start sending data (MPI_ISEND)
|
|
106
|
+
for disp in [-1,1]:
|
|
107
|
+
info = cart.get_shift_info( direction, disp )
|
|
108
|
+
send_typ = self.get_send_type ( direction, disp )
|
|
109
|
+
send_buf = (array, 1, send_typ)
|
|
110
|
+
send_req = comm.Isend( send_buf, info['rank_dest'], tag(disp) )
|
|
111
|
+
requests.append( send_req )
|
|
112
|
+
|
|
113
|
+
# Wait for end of data exchange (MPI_WAITALL)
|
|
114
|
+
MPI.Request.Waitall( requests )
|
|
115
|
+
|
|
116
|
+
def end_update_ghost_regions(self, array, requests ):
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
# ...
|
|
120
|
+
def start_exchange_assembly_data( self, array ):
|
|
121
|
+
|
|
122
|
+
assert isinstance( array, np.ndarray )
|
|
123
|
+
|
|
124
|
+
# Shortcuts
|
|
125
|
+
cart = self._cart
|
|
126
|
+
comm = self._comm
|
|
127
|
+
gcomm = comm
|
|
128
|
+
ndim = cart.ndim
|
|
129
|
+
|
|
130
|
+
# Choose non-negative invertible function tag(disp) >= 0
|
|
131
|
+
# NOTES:
|
|
132
|
+
# . different values of disp must return different tags!
|
|
133
|
+
# . tag at receiver must match message tag at sender
|
|
134
|
+
tag = lambda disp: 42+disp
|
|
135
|
+
|
|
136
|
+
# Requests' handles
|
|
137
|
+
|
|
138
|
+
for direction in range( ndim ):
|
|
139
|
+
if direction == self._axis: continue
|
|
140
|
+
if self._axis is not None: comm = cart.subcomm[direction]
|
|
141
|
+
|
|
142
|
+
# Start receiving data (MPI_IRECV)
|
|
143
|
+
disp = 1
|
|
144
|
+
info = cart.get_shift_info( direction, disp )
|
|
145
|
+
recv_typ = self.get_assembly_recv_type ( direction, disp )
|
|
146
|
+
rank_source = info['rank_source']
|
|
147
|
+
|
|
148
|
+
if self._axis is not None:
|
|
149
|
+
rank_source = gcomm.group.Translate_ranks(np.array([rank_source]), comm.group)[0]
|
|
150
|
+
|
|
151
|
+
recv_buf = (array, 1, recv_typ)
|
|
152
|
+
recv_req = comm.Irecv( recv_buf, rank_source, tag(disp) )
|
|
153
|
+
|
|
154
|
+
# Start sending data (MPI_ISEND)
|
|
155
|
+
send_typ = self.get_assembly_send_type ( direction, disp )
|
|
156
|
+
rank_dest = info['rank_dest']
|
|
157
|
+
|
|
158
|
+
if self._axis is not None:
|
|
159
|
+
rank_dest = gcomm.group.Translate_ranks(np.array([rank_dest]), comm.group)[0]
|
|
160
|
+
|
|
161
|
+
send_buf = (array, 1, send_typ)
|
|
162
|
+
send_req = comm.Isend( send_buf, rank_dest, tag(disp) )
|
|
163
|
+
|
|
164
|
+
# Wait for end of data exchange (MPI_WAITALL)
|
|
165
|
+
MPI.Request.Waitall( [recv_req, send_req] )
|
|
166
|
+
|
|
167
|
+
if disp == 1:
|
|
168
|
+
info = cart.get_shift_info( direction, disp )
|
|
169
|
+
pads = [0]*ndim
|
|
170
|
+
pads[direction] = cart._pads[direction]*cart._shifts[direction]
|
|
171
|
+
idx_from = tuple(slice(s,s+b) for s,b in zip(info['recv_starts'],info['buf_shape']))
|
|
172
|
+
idx_to = tuple(slice(s+p,s+b+p) for s,b,p in zip(info['recv_starts'],info['buf_shape'],pads))
|
|
173
|
+
array[idx_to] += array[idx_from]
|
|
174
|
+
else:
|
|
175
|
+
info = cart.get_shift_info( direction, disp )
|
|
176
|
+
pads = [0]*ndim
|
|
177
|
+
pads[direction] = cart._pads[direction]*cart._shifts[direction]
|
|
178
|
+
idx_from = tuple(slice(s,s+b) for s,b in zip(info['recv_starts'],info['buf_shape']))
|
|
179
|
+
idx_to = tuple(slice(s-p,s+b-p) for s,b,p in zip(info['recv_starts'],info['buf_shape'],pads))
|
|
180
|
+
array[idx_to] += array[idx_from]
|
|
181
|
+
|
|
182
|
+
def end_exchange_assembly_data( self, array ):
|
|
183
|
+
pass
|
|
184
|
+
|
|
185
|
+
#---------------------------------------------------------------------------
|
|
186
|
+
# Private methods
|
|
187
|
+
#---------------------------------------------------------------------------
|
|
188
|
+
@staticmethod
|
|
189
|
+
def _create_buffer_types( cart, dtype, *, coeff_shape=() ):
|
|
190
|
+
"""
|
|
191
|
+
Create MPI subarray datatypes for updating the ghost regions (padding)
|
|
192
|
+
of a multi-dimensional array distributed according to the given Cartesian
|
|
193
|
+
decomposition of a tensor-product grid of coefficients.
|
|
194
|
+
|
|
195
|
+
MPI requires a subarray datatype for accessing non-contiguous slices of
|
|
196
|
+
a multi-dimensional array; this is a typical situation when updating the
|
|
197
|
+
ghost regions.
|
|
198
|
+
|
|
199
|
+
Each coefficient in the decomposed grid may have multiple components,
|
|
200
|
+
contiguous in memory.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
cart : feectools.ddm.CartDecomposition
|
|
205
|
+
Object that contains all information about the Cartesian decomposition
|
|
206
|
+
of a tensor-product grid of coefficients.
|
|
207
|
+
|
|
208
|
+
dtype : [type | str | numpy.dtype | mpi4py.MPI.Datatype]
|
|
209
|
+
Datatype of single coefficient (if scalar) or of each of its
|
|
210
|
+
components (if vector).
|
|
211
|
+
|
|
212
|
+
coeff_shape : [tuple(int) | list(int)]
|
|
213
|
+
Shape of a single coefficient, if this is multidimensional
|
|
214
|
+
(optional: by default, we assume scalar coefficients).
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
send_types : dict
|
|
219
|
+
Dictionary of MPI subarray datatypes for SEND BUFFERS, accessed
|
|
220
|
+
through the integer pair (direction, displacement) as key;
|
|
221
|
+
'direction' takes values from 0 to ndim, 'disp' is -1 or +1.
|
|
222
|
+
|
|
223
|
+
recv_types : dict
|
|
224
|
+
Dictionary of MPI subarray datatypes for RECEIVE BUFFERS, accessed
|
|
225
|
+
through the integer pair (direction, displacement) as key;
|
|
226
|
+
'direction' takes values from 0 to ndim, 'disp' is -1 or +1.
|
|
227
|
+
|
|
228
|
+
"""
|
|
229
|
+
assert isinstance( cart, CartDecomposition )
|
|
230
|
+
|
|
231
|
+
mpi_type = find_mpi_type( dtype )
|
|
232
|
+
|
|
233
|
+
# Possibly, each coefficient could have multiple components
|
|
234
|
+
coeff_shape = list( coeff_shape )
|
|
235
|
+
coeff_start = [0] * len( coeff_shape )
|
|
236
|
+
|
|
237
|
+
data_shape = list( cart.shape ) + coeff_shape
|
|
238
|
+
send_types = {}
|
|
239
|
+
recv_types = {}
|
|
240
|
+
|
|
241
|
+
for direction in range( cart.ndim ):
|
|
242
|
+
for disp in [-1, 1]:
|
|
243
|
+
info = cart.get_shift_info( direction, disp )
|
|
244
|
+
|
|
245
|
+
buf_shape = list( info[ 'buf_shape' ] ) + coeff_shape
|
|
246
|
+
send_starts = list( info['send_starts'] ) + coeff_start
|
|
247
|
+
recv_starts = list( info['recv_starts'] ) + coeff_start
|
|
248
|
+
|
|
249
|
+
send_types[direction,disp] = mpi_type.Create_subarray(
|
|
250
|
+
sizes = data_shape ,
|
|
251
|
+
subsizes = buf_shape ,
|
|
252
|
+
starts = send_starts,
|
|
253
|
+
).Commit()
|
|
254
|
+
|
|
255
|
+
recv_types[direction,disp] = mpi_type.Create_subarray(
|
|
256
|
+
sizes = data_shape ,
|
|
257
|
+
subsizes = buf_shape ,
|
|
258
|
+
starts = recv_starts,
|
|
259
|
+
).Commit()
|
|
260
|
+
|
|
261
|
+
return send_types, recv_types
|
|
262
|
+
|
|
263
|
+
# ...
|
|
264
|
+
@staticmethod
|
|
265
|
+
def _create_assembly_buffer_types( cart, dtype, *, coeff_shape=(), axis=None, shape=None ):
|
|
266
|
+
"""
|
|
267
|
+
Create MPI subarray datatypes for updating the ghost regions (padding)
|
|
268
|
+
of a multi-dimensional array distributed according to the given Cartesian
|
|
269
|
+
decomposition of a tensor-product grid of coefficients.
|
|
270
|
+
MPI requires a subarray datatype for accessing non-contiguous slices of
|
|
271
|
+
a multi-dimensional array; this is a typical situation when updating the
|
|
272
|
+
ghost regions.
|
|
273
|
+
Each coefficient in the decomposed grid may have multiple components,
|
|
274
|
+
contiguous in memory.
|
|
275
|
+
|
|
276
|
+
Parameters
|
|
277
|
+
----------
|
|
278
|
+
cart : feectools.ddm.CartDecomposition
|
|
279
|
+
Object that contains all information about the Cartesian decomposition
|
|
280
|
+
of a tensor-product grid of coefficients.
|
|
281
|
+
|
|
282
|
+
dtype : [type | str | numpy.dtype | mpi4py.MPI.Datatype]
|
|
283
|
+
Datatype of single coefficient (if scalar) or of each of its
|
|
284
|
+
components (if vector).
|
|
285
|
+
|
|
286
|
+
coeff_shape : [tuple(int) | list(int)]
|
|
287
|
+
Shape of a single coefficient, if this is multidimensional
|
|
288
|
+
(optional: by default, we assume scalar coefficients).
|
|
289
|
+
|
|
290
|
+
axis: int,optional
|
|
291
|
+
The axis of which we don't update the ghost regions.
|
|
292
|
+
|
|
293
|
+
shape:
|
|
294
|
+
the shape of data when axis is not None
|
|
295
|
+
|
|
296
|
+
Returns
|
|
297
|
+
-------
|
|
298
|
+
send_types : dict
|
|
299
|
+
Dictionary of MPI subarray datatypes for SEND BUFFERS, accessed
|
|
300
|
+
through the integer pair (direction, displacement) as key;
|
|
301
|
+
'direction' takes values from 0 to ndim, 'disp' is -1 or +1.
|
|
302
|
+
|
|
303
|
+
recv_types : dict
|
|
304
|
+
Dictionary of MPI subarray datatypes for RECEIVE BUFFERS, accessed
|
|
305
|
+
through the integer pair (direction, displacement) as key;
|
|
306
|
+
'direction' takes values from 0 to ndim, 'disp' is -1 or +1.
|
|
307
|
+
"""
|
|
308
|
+
assert isinstance( cart, CartDecomposition )
|
|
309
|
+
|
|
310
|
+
mpi_type = find_mpi_type( dtype )
|
|
311
|
+
|
|
312
|
+
# Possibly, each coefficient could have multiple components
|
|
313
|
+
coeff_shape = list( coeff_shape )
|
|
314
|
+
coeff_start = [0] * len( coeff_shape )
|
|
315
|
+
|
|
316
|
+
data_shape = list( cart.shape ) + coeff_shape
|
|
317
|
+
send_types = {}
|
|
318
|
+
recv_types = {}
|
|
319
|
+
|
|
320
|
+
if axis is not None:
|
|
321
|
+
data_shape[axis] = shape[axis]
|
|
322
|
+
|
|
323
|
+
for direction in range( cart.ndim ):
|
|
324
|
+
for disp in [-1, 1]:
|
|
325
|
+
info = cart.get_shift_info( direction, disp )
|
|
326
|
+
|
|
327
|
+
buf_shape = list( info[ 'buf_shape' ] ) + coeff_shape
|
|
328
|
+
send_starts = list( info['send_assembly_starts'] ) + coeff_start
|
|
329
|
+
recv_starts = list( info['recv_assembly_starts'] ) + coeff_start
|
|
330
|
+
if direction == axis:continue
|
|
331
|
+
if axis is not None:
|
|
332
|
+
buf_shape[axis] = shape[axis]
|
|
333
|
+
send_starts[axis] = 0
|
|
334
|
+
recv_starts[axis] = 0
|
|
335
|
+
|
|
336
|
+
send_types[direction,disp] = mpi_type.Create_subarray(
|
|
337
|
+
sizes = data_shape ,
|
|
338
|
+
subsizes = buf_shape ,
|
|
339
|
+
starts = send_starts,
|
|
340
|
+
).Commit()
|
|
341
|
+
|
|
342
|
+
recv_types[direction,disp] = mpi_type.Create_subarray(
|
|
343
|
+
sizes = data_shape ,
|
|
344
|
+
subsizes = buf_shape ,
|
|
345
|
+
starts = recv_starts,
|
|
346
|
+
).Commit()
|
|
347
|
+
|
|
348
|
+
return send_types, recv_types
|