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,106 @@
1
+ import pytest
2
+ import scipy.fft as scifft
3
+ import numpy as np
4
+
5
+ from feectools.ddm.mpi import mpi as MPI
6
+ from feectools.linalg.fft import *
7
+ from feectools.ddm.cart import DomainDecomposition, CartDecomposition
8
+ from feectools.linalg.stencil import StencilVector
9
+ #===============================================================================
10
+ def compute_global_starts_ends(domain_decomposition, npts):
11
+ ndims = len(npts)
12
+ global_starts = [None]*ndims
13
+ global_ends = [None]*ndims
14
+
15
+ for axis in range(ndims):
16
+ es = domain_decomposition.global_element_starts[axis]
17
+ ee = domain_decomposition.global_element_ends [axis]
18
+
19
+ global_ends [axis] = ee.copy()
20
+ global_ends [axis][-1] = npts[axis]-1
21
+ global_starts[axis] = np.array([0] + (global_ends[axis][:-1]+1).tolist())
22
+
23
+ return global_starts, global_ends
24
+ #===============================================================================
25
+ def decode_fft_type(ffttype):
26
+ if ffttype == 'fft':
27
+ return (complex, DistributedFFT, scifft.fftn)
28
+ elif ffttype == 'ifft':
29
+ return (complex, DistributedIFFT, scifft.ifftn)
30
+ elif ffttype == 'dct':
31
+ return (complex, DistributedDCT, scifft.dctn)
32
+ elif ffttype == 'idct':
33
+ return (complex, DistributedIDCT, scifft.idctn)
34
+ elif ffttype == 'dst':
35
+ return (complex, DistributedDST, scifft.dstn)
36
+ elif ffttype == 'idst':
37
+ return (complex, DistributedIDST, scifft.idstn)
38
+ else:
39
+ raise NotImplementedError()
40
+
41
+ def method_test(seed, comm, config, dtype, classtype, comparison, verbose=False):
42
+ np.random.seed(seed)
43
+
44
+ if comm is None:
45
+ rank = -1
46
+ else:
47
+ rank = comm.Get_rank()
48
+
49
+ npts, pads, periods = config
50
+
51
+ if verbose:
52
+ print(f'[{rank}] Test start', flush=True)
53
+
54
+ comm = MPI.COMM_WORLD
55
+ D = DomainDecomposition(npts, periods=periods, comm=comm)
56
+
57
+ # Partition the points
58
+ global_starts, global_ends = compute_global_starts_ends(D, npts)
59
+
60
+ cart = CartDecomposition(D, npts, global_starts, global_ends, pads=pads, shifts=[1]*len(pads))
61
+
62
+ # vector spaces
63
+ V = StencilVectorSpace(cart, dtype=dtype)
64
+ localslice = tuple([slice(s, e+1) for s, e in zip(V.starts, V.ends)])
65
+
66
+ if verbose:
67
+ print(f'[{rank}] Vector spaces built', flush=True)
68
+
69
+ if np.dtype(dtype).kind == 'c':
70
+ Y_glob = np.random.random(V.npts) + np.random.random(V.npts) * 1j
71
+ else:
72
+ Y_glob = np.random.random(V.npts)
73
+
74
+ # vector to solve for (Y)
75
+ Y = StencilVector(V)
76
+ Y[localslice] = Y_glob[localslice]
77
+ Y.update_ghost_regions()
78
+
79
+ if verbose:
80
+ print(f'[{rank}] Vector built', flush=True)
81
+
82
+ X_glob = comparison(Y_glob)
83
+
84
+ compare = classtype(V)
85
+ X = compare.dot(Y)
86
+
87
+ if verbose:
88
+ print(f'[{rank}] Functions have been run', flush=True)
89
+
90
+ assert np.allclose(X_glob[localslice], X[localslice], 1e-10, 1e-10)
91
+
92
+ @pytest.mark.parametrize( 'seed', [0, 2] )
93
+ @pytest.mark.parametrize( 'params', [([8], [2], [False]), ([8,9], [2,3], [False,True]), ([8,9,17], [2,3,7], [False,True,False])] )
94
+ @pytest.mark.parametrize( 'ffttype', ['fft', 'ifft', 'dct', 'idct', 'dst', 'idst'] )
95
+ def test_kron_fft_ser(seed, params, ffttype):
96
+ method_test(seed, None, params, *decode_fft_type(ffttype), verbose=False)
97
+
98
+ @pytest.mark.parametrize( 'seed', [0, 2] )
99
+ @pytest.mark.parametrize( 'params', [([16], [2], [False]), ([16,18], [2,3], [False,True]), ([16,18,37], [2,3,7], [False,True,False])] )
100
+ @pytest.mark.parametrize( 'ffttype', ['fft', 'ifft', 'dct', 'idct', 'dst', 'idst'] )
101
+ @pytest.mark.parallel
102
+ def test_kron_fft_par(seed, params, ffttype):
103
+ method_test(seed, MPI.COMM_WORLD, params, *decode_fft_type(ffttype), verbose=False)
104
+
105
+ if __name__ == '__main__':
106
+ method_test(0, MPI.COMM_WORLD, ([8,9,5], [2,3,7], [False,True,False]), *decode_fft_type('fft'), verbose=True)
@@ -0,0 +1,114 @@
1
+ from functools import reduce
2
+
3
+ import pytest
4
+ import numpy as np
5
+ from scipy.sparse import kron
6
+
7
+ from feectools.ddm.cart import DomainDecomposition, CartDecomposition
8
+ from feectools.linalg.stencil import StencilVectorSpace
9
+ from feectools.linalg.stencil import StencilVector
10
+ from feectools.linalg.stencil import StencilMatrix
11
+ from feectools.linalg.kron import KroneckerStencilMatrix
12
+ #===============================================================================
13
+ def compute_global_starts_ends(domain_decomposition, npts):
14
+ ndims = len(npts)
15
+ global_starts = [None]*ndims
16
+ global_ends = [None]*ndims
17
+
18
+ for axis in range(ndims):
19
+ ee = domain_decomposition.global_element_ends [axis]
20
+
21
+ global_ends [axis] = ee.copy()
22
+ global_ends [axis][-1] = npts[axis]-1
23
+ global_starts[axis] = np.array([0] + (global_ends[axis][:-1]+1).tolist())
24
+
25
+ return tuple(global_starts), tuple(global_ends)
26
+
27
+ #==============================================================================
28
+ @pytest.mark.parametrize('dtype', [float])
29
+ @pytest.mark.parametrize('npts', [(5, 7, 8)])
30
+ @pytest.mark.parametrize('pads', [(2, 3, 5)])
31
+ @pytest.mark.parametrize('periodic', [(True, False, False)])
32
+
33
+ def test_KroneckerStencilMatrix(dtype, npts, pads, periodic):
34
+
35
+ # Extract input parameters
36
+ n1, n2, n3 = npts
37
+ p1, p2, p3 = pads
38
+ P1, P2, P3 = periodic
39
+
40
+ # Define data type with a factor
41
+ if dtype==complex:
42
+ factor=1j
43
+ else:
44
+ factor=1
45
+
46
+ # Create domain decomposition
47
+ D = DomainDecomposition([n1-1,n2-1, n3-1], periods=[P1,P2,P3])
48
+
49
+ # Partition the points
50
+ global_starts, global_ends = compute_global_starts_ends(D, npts)
51
+
52
+ cart = CartDecomposition(D, npts, global_starts, global_ends, pads=[p1,p2,p3], shifts=[1,1,1])
53
+
54
+ # 3D vector space and element
55
+ W = StencilVectorSpace( cart, dtype=dtype)
56
+ w = StencilVector(W)
57
+
58
+ # 1D vector space
59
+
60
+ D1 = DomainDecomposition([n1-1], periods=[P1])
61
+ D2 = DomainDecomposition([n2-1], periods=[P2])
62
+ D3 = DomainDecomposition([n3-1], periods=[P3])
63
+
64
+ # Partition the points
65
+ global_starts1, global_ends1 = compute_global_starts_ends(D1, [n1])
66
+ global_starts2, global_ends2 = compute_global_starts_ends(D2, [n2])
67
+ global_starts3, global_ends3 = compute_global_starts_ends(D3, [n3])
68
+
69
+ cart1 = CartDecomposition(D1, [n1], global_starts1, global_ends1, pads=[p1], shifts=[1])
70
+ cart2 = CartDecomposition(D2, [n2], global_starts2, global_ends2, pads=[p2], shifts=[1])
71
+ cart3 = CartDecomposition(D3, [n3], global_starts3, global_ends3, pads=[p3], shifts=[1])
72
+
73
+ V1 = StencilVectorSpace( cart1, dtype=dtype )
74
+ V2 = StencilVectorSpace( cart2, dtype=dtype )
75
+ V3 = StencilVectorSpace( cart3, dtype=dtype )
76
+
77
+ # 1D stencil matrices
78
+ M1 = StencilMatrix(V1, V1)
79
+ M2 = StencilMatrix(V2, V2)
80
+ M3 = StencilMatrix(V3, V3)
81
+
82
+ # ...
83
+ # Fill in stencil matrix values
84
+ for k1 in range(-p1, p1+1):
85
+ M1[:, k1] = 10 + k1*factor
86
+
87
+ for k2 in range(-p2, p2+1):
88
+ M2[:, k2] = 20 + k2*factor
89
+
90
+ for k3 in range(-p3, p3+1):
91
+ M3[:, k3] = 40 + k3*factor
92
+
93
+ M1.remove_spurious_entries()
94
+ M2.remove_spurious_entries()
95
+ M3.remove_spurious_entries()
96
+ # ...
97
+
98
+ # Fill in vector values
99
+ w[:, :, :] = factor
100
+
101
+ # Create Kronecker matrix
102
+ M = KroneckerStencilMatrix(W, W, M1, M2, M3)
103
+
104
+ # Scipy sparse matrices used for comparison
105
+ M1_sp = M1.tosparse().tocsr()
106
+ M2_sp = M2.tosparse().tocsr()
107
+ M3_sp = M3.tosparse().tocsr()
108
+ M_sp = reduce(kron, (M1_sp, M2_sp, M3_sp)).tocsr()
109
+
110
+ # Test transpose
111
+ assert (M_sp.T - M.T.tosparse().tocsr()).count_nonzero() == 0
112
+
113
+ # Test dot product
114
+ assert np.array_equal(M_sp.dot(w.toarray()), M.dot(w).toarray())