feectools 0.1.3__tar.gz → 0.1.5__tar.gz

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 (109) hide show
  1. {feectools-0.1.3 → feectools-0.1.5}/AUTHORS +8 -6
  2. {feectools-0.1.3 → feectools-0.1.5}/LICENSE +1 -1
  3. {feectools-0.1.3/feectools.egg-info → feectools-0.1.5}/PKG-INFO +2 -2
  4. {feectools-0.1.3 → feectools-0.1.5}/README.md +1 -1
  5. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/bsplines.py +5 -4
  6. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/bsplines_kernels.py +6 -0
  7. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/tests/test_bsplines.py +5 -2
  8. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/tests/test_bsplines_pyccel.py +5 -0
  9. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/basic.py +6 -2
  10. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/blocking_data_exchanger.py +6 -2
  11. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/mpi.py +2 -2
  12. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/partition.py +6 -0
  13. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/petsc.py +6 -2
  14. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/tests/test_cart_1d.py +6 -3
  15. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/tests/test_multicart_2d.py +5 -1
  16. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/tests/test_partition.py +5 -3
  17. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/utilities.py +6 -2
  18. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/grid.py +5 -4
  19. feectools-0.1.5/feectools/fem/lst_preconditioner.py +292 -0
  20. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/analytical_profiles_1d.py +6 -4
  21. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/analytical_profiles_base.py +5 -3
  22. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/splines_error_bounds.py +6 -3
  23. feectools-0.1.5/feectools/fem/tests/test_dirichlet_projectors.py +517 -0
  24. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/test_spline_histopolation.py +5 -0
  25. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/test_spline_interpolation.py +8 -9
  26. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/test_splines.py +6 -3
  27. feectools-0.1.5/feectools/fem/tests/test_tensor.py +232 -0
  28. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/test_vector_spaces.py +5 -2
  29. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/utilities.py +5 -3
  30. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/direct_solvers.py +31 -6
  31. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/stencil.py +30 -25
  32. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_fft.py +6 -1
  33. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_stencil_interface_matrix.py +6 -4
  34. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_stencil_vector.py +15 -12
  35. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_stencil_vector_space.py +9 -4
  36. feectools-0.1.5/feectools/linalg/tests/utilities.py +89 -0
  37. {feectools-0.1.3 → feectools-0.1.5}/feectools/utilities/quadratures.py +8 -8
  38. {feectools-0.1.3 → feectools-0.1.5}/feectools/utilities/utils.py +6 -4
  39. feectools-0.1.5/feectools/version.py +35 -0
  40. {feectools-0.1.3 → feectools-0.1.5/feectools.egg-info}/PKG-INFO +2 -2
  41. {feectools-0.1.3 → feectools-0.1.5}/feectools.egg-info/SOURCES.txt +4 -1
  42. {feectools-0.1.3 → feectools-0.1.5}/pyproject.toml +13 -1
  43. feectools-0.1.3/feectools/version.py +0 -1
  44. feectools-0.1.3/setup.py +0 -47
  45. {feectools-0.1.3 → feectools-0.1.5}/feectools/__init__.py +0 -0
  46. {feectools-0.1.3 → feectools-0.1.5}/feectools/accelerate/__init__.py +0 -0
  47. {feectools-0.1.3 → feectools-0.1.5}/feectools/accelerate/accelerate.py +0 -0
  48. {feectools-0.1.3 → feectools-0.1.5}/feectools/accelerate/compile_psydac.mk +0 -0
  49. {feectools-0.1.3 → feectools-0.1.5}/feectools/api/__init__.py +0 -0
  50. {feectools-0.1.3 → feectools-0.1.5}/feectools/api/essential_bc.py +0 -0
  51. {feectools-0.1.3 → feectools-0.1.5}/feectools/api/fem_bilinear_form.py +0 -0
  52. {feectools-0.1.3 → feectools-0.1.5}/feectools/api/fem_common.py +0 -0
  53. {feectools-0.1.3 → feectools-0.1.5}/feectools/api/fem_sum_form.py +0 -0
  54. {feectools-0.1.3 → feectools-0.1.5}/feectools/api/settings.py +0 -0
  55. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/__init__.py +0 -0
  56. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/field_evaluation_kernels.py +0 -0
  57. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/tests/__init__.py +0 -0
  58. {feectools-0.1.3 → feectools-0.1.5}/feectools/core/tests/test_bsplines_kernel.py +0 -0
  59. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/__init__.py +0 -0
  60. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/cart.py +0 -0
  61. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/interface_data_exchanger.py +0 -0
  62. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/nonblocking_data_exchanger.py +0 -0
  63. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/tests/__init__.py +0 -0
  64. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/tests/test_cart_2d.py +0 -0
  65. {feectools-0.1.3 → feectools-0.1.5}/feectools/ddm/tests/test_cart_3d.py +0 -0
  66. {feectools-0.1.3 → feectools-0.1.5}/feectools/feec/__init__.py +0 -0
  67. {feectools-0.1.3 → feectools-0.1.5}/feectools/feec/derivatives.py +0 -0
  68. {feectools-0.1.3 → feectools-0.1.5}/feectools/feec/dof_kernels.py +0 -0
  69. {feectools-0.1.3 → feectools-0.1.5}/feectools/feec/global_geometric_projectors.py +0 -0
  70. {feectools-0.1.3 → feectools-0.1.5}/feectools/feec/hodge.py +0 -0
  71. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/__init__.py +0 -0
  72. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/basic.py +0 -0
  73. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/partitioning.py +0 -0
  74. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/projectors.py +0 -0
  75. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/splines.py +0 -0
  76. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tensor.py +0 -0
  77. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/__init__.py +0 -0
  78. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/tests/test_splines_par.py +0 -0
  79. {feectools-0.1.3 → feectools-0.1.5}/feectools/fem/vector.py +0 -0
  80. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/__init__.py +0 -0
  81. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/basic.py +0 -0
  82. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/block.py +0 -0
  83. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/fft.py +0 -0
  84. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kernels/__init__.py +0 -0
  85. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kernels/axpy_kernels.py +0 -0
  86. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kernels/inner_kernels.py +0 -0
  87. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kernels/matvec_kernels.py +0 -0
  88. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kernels/stencil2IJV_kernels.py +0 -0
  89. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kernels/stencil2coo_kernels.py +0 -0
  90. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kernels/transpose_kernels.py +0 -0
  91. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/kron.py +0 -0
  92. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/solvers.py +0 -0
  93. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/sparse.py +0 -0
  94. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/stencil_dot_kernels.py +0 -0
  95. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/stencil_transpose_kernels.py +0 -0
  96. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/__init__.py +0 -0
  97. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_block.py +0 -0
  98. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_kron_stencil_matrix.py +0 -0
  99. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_linalg.py +0 -0
  100. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_matrix_free.py +0 -0
  101. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/tests/test_solvers.py +0 -0
  102. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/topetsc.py +0 -0
  103. {feectools-0.1.3 → feectools-0.1.5}/feectools/linalg/utilities.py +0 -0
  104. {feectools-0.1.3 → feectools-0.1.5}/feectools/utilities/__init__.py +0 -0
  105. {feectools-0.1.3 → feectools-0.1.5}/feectools.egg-info/dependency_links.txt +0 -0
  106. {feectools-0.1.3 → feectools-0.1.5}/feectools.egg-info/entry_points.txt +0 -0
  107. {feectools-0.1.3 → feectools-0.1.5}/feectools.egg-info/requires.txt +0 -0
  108. {feectools-0.1.3 → feectools-0.1.5}/feectools.egg-info/top_level.txt +0 -0
  109. {feectools-0.1.3 → feectools-0.1.5}/setup.cfg +0 -0
@@ -2,21 +2,23 @@ Maintainers
2
2
  -----------
3
3
  * Yaman Güçlü <yaman.guclu@gmail.com> (original author, project lead)
4
4
  * Martin Campos Pinto <martin.campos-pinto@ipp.mpg.de>
5
- * Ahmed Ratnani <ratnaniahmed@gmail.com> (original author)
6
5
 
7
6
  Contributors
8
7
  ------------
8
+ * Ahmed Ratnani (original author)
9
9
  * Said Hadjout (original author)
10
+ * Jalal Lakhlili (original author)
11
+ * Frederik Schnack
10
12
  * Julian Owezarek
13
+ * Elena Moral Sánchez
11
14
  * Antoine Lavandier
12
15
  * Tom Caruso
13
- * Elena Moral Sánchez
14
16
  * Paul Rigor
15
- * Frederik Schnack
16
17
  * David Schneller
17
18
  * Valentin Carlier
18
19
  * Stefan Possanner
19
- * Jalal Lakhlili (original author)
20
- * William Barham
21
- * Max Lindqvist
22
20
  * Emily Bourne
21
+ * Max Lindqvist
22
+ * William Barham
23
+ * Anushka Singh
24
+ * Alisa Kirkinskaia
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2018-2023, Psydac Developers.
3
+ Copyright (c) 2018-2026, PSYDAC Developers.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: feectools
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Slimmed-down fork of Psydac (https://github.com/pyccel/psydac) with less functionality and fewer dependencies.
5
5
  Author-email: Psydac development team <psydac@googlegroups.com>
6
6
  Maintainer-email: Stefan Possanner <stefan.possanner@ipp.mpg.de>, Max Lindqvist <max.lindqvist@ipp.mpg.de>, Yaman Güçlü <yaman.guclu@gmail.com>, Martin Campos Pinto <martin.campos-pinto@ipp.mpg.de>, Ahmed Ratnani <ratnaniahmed@gmail.com>
7
7
  License: MIT License
8
8
 
9
- Copyright (c) 2018-2023, Psydac Developers.
9
+ Copyright (c) 2018-2026, PSYDAC Developers.
10
10
 
11
11
  Permission is hereby granted, free of charge, to any person obtaining a copy
12
12
  of this software and associated documentation files (the "Software"), to deal
@@ -6,4 +6,4 @@ The latest version can be installed with
6
6
  ```
7
7
  pip install -U feectools
8
8
  ```
9
- See the [Struphy documentation](https://struphy-hub.github.io/struphy/index.html) for details on how to use.
9
+ See the [Struphy documentation](https://struphy-hub.github.io/struphy/index.html) for details on how to use.
@@ -1,7 +1,8 @@
1
- # coding: utf-8
2
- #
3
- # Copyright 2018 Yaman Güçlü
4
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
5
6
  """
6
7
  Basic module that provides the means for evaluating the B-Splines basis
7
8
  functions and their derivatives. In order to simplify automatic Fortran code
@@ -1,3 +1,9 @@
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
6
+
1
7
  # This file holds the pyccelisable versions of the functions in bsplines.py
2
8
  # This will be changed once pyccel can return arrays and can get out=None arguments
3
9
  # like Numpy functions.
@@ -1,5 +1,8 @@
1
- #coding: utf-8
2
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
3
6
  import pytest
4
7
  import numpy as np
5
8
 
@@ -1,3 +1,8 @@
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
1
6
  import numpy as np
2
7
  import pytest
3
8
 
@@ -1,7 +1,11 @@
1
- # coding: utf-8
2
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
3
6
  from abc import ABC, abstractmethod
4
7
 
8
+
5
9
  __all__ = ('CartDataExchanger',)
6
10
  #===============================================================================
7
11
  class CartDataExchanger(ABC):
@@ -1,11 +1,15 @@
1
- # coding: utf-8
2
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
3
6
  import numpy as np
4
7
  from feectools.ddm.mpi import mpi as MPI
5
8
 
6
9
  from .cart import CartDecomposition, find_mpi_type
7
10
  from .basic import CartDataExchanger
8
11
 
12
+
9
13
  __all__ = ('BlockingCartDataExchanger',)
10
14
 
11
15
  class BlockingCartDataExchanger(CartDataExchanger):
@@ -84,8 +84,8 @@ try:
84
84
  from mpi4py import MPI
85
85
 
86
86
  _comm = MPI.COMM_WORLD
87
- rank = _comm.Get_rank()
88
- size = _comm.Get_size()
87
+ # rank = _comm.Get_rank()
88
+ # size = _comm.Get_size()
89
89
  mpi_enabled = True
90
90
  except ImportError:
91
91
  # mpi4py not installed
@@ -1,8 +1,14 @@
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
1
6
  import numpy as np
2
7
  import numpy.ma as ma
3
8
 
4
9
  from sympy.ntheory import factorint
5
10
 
11
+
6
12
  __all__ = ('compute_dims', 'partition_procs_per_patch')
7
13
 
8
14
  #==============================================================================
@@ -1,7 +1,11 @@
1
- # coding: utf-8
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
6
+ from itertools import product
2
7
 
3
8
  import numpy as np
4
- from itertools import product
5
9
 
6
10
  from .cart import CartDecomposition
7
11
 
@@ -1,5 +1,8 @@
1
- # Contents of test_cart_1d.py
2
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
3
6
  import numpy as np
4
7
 
5
8
  from feectools.ddm.blocking_data_exchanger import BlockingCartDataExchanger
@@ -111,7 +114,7 @@ def run_cart_1d( data_exchanger_type, verbose=False ):
111
114
  import pytest
112
115
 
113
116
  @pytest.mark.parametrize( 'data_exchanger_type', [BlockingCartDataExchanger, NonBlockingCartDataExchanger] )
114
- @pytest.mark.parallel
117
+ @pytest.mark.mpi
115
118
  def test_cart_1d( data_exchanger_type ):
116
119
 
117
120
  namespace = run_cart_1d( data_exchanger_type )
@@ -1,4 +1,8 @@
1
- # File test_multicart_2d.py
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
2
6
 
3
7
  #===============================================================================
4
8
  # TEST MultiCartDecomposition in 2D
@@ -1,3 +1,8 @@
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
1
6
  import pytest
2
7
 
3
8
  from feectools.ddm.partition import compute_dims
@@ -119,6 +124,3 @@ if __name__ == '__main__':
119
124
  # test_partition_2d_dims_mask(10, [58, 64], [True, False])
120
125
 
121
126
  test_partition_3d_dims_mask(10, [32, 64, 128], [True, False, True])
122
-
123
-
124
-
@@ -1,10 +1,14 @@
1
- # coding: utf-8
2
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
3
6
  from .cart import CartDecomposition, InterfaceCartDecomposition
4
7
  from .blocking_data_exchanger import BlockingCartDataExchanger
5
8
  from .nonblocking_data_exchanger import NonBlockingCartDataExchanger
6
9
  from .interface_data_exchanger import InterfaceCartDataExchanger
7
10
 
11
+
8
12
  __all__ = ('get_data_exchanger',)
9
13
 
10
14
  def get_data_exchanger(cart, dtype, *, coeff_shape=(), assembly=False, axis=None, shape=None, blocking=True):
@@ -1,7 +1,8 @@
1
- # coding: utf-8
2
- #
3
- # Copyright 2018 Yaman Güçlü
4
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
5
6
  import numpy as np
6
7
 
7
8
  from feectools.core.bsplines import elements_spans
@@ -0,0 +1,292 @@
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
6
+ from functools import lru_cache
7
+ from scipy.sparse import dia_matrix
8
+ import numpy as np
9
+
10
+ from sympde.topology import elements_of, Line, ScalarFunctionSpace
11
+ from sympde.topology.datatype import SpaceType
12
+ from sympde.expr import integral, BilinearForm
13
+
14
+ from psydac.linalg.basic import IdentityOperator, LinearOperator
15
+ from psydac.linalg.block import BlockVectorSpace, BlockLinearOperator
16
+ from psydac.linalg.direct_solvers import BandedSolver
17
+ from psydac.linalg.kron import KroneckerLinearSolver, KroneckerStencilMatrix
18
+ from psydac.linalg.stencil import StencilVectorSpace
19
+ from psydac.fem.projectors import DirichletProjector
20
+
21
+
22
+ @lru_cache
23
+ def construct_LST_preconditioner(M, domain_h, fem_space, hom_bc=False, kind=None):
24
+ """
25
+ LST (Loli, Sangalli, Tani) preconditioners [1] are mass matrix preconditioners of the form
26
+ pc = D_inv_sqrt @ D_log_sqrt @ M_log_kron_solver @ D_log_sqrt @ D_inv_sqrt, where
27
+
28
+ D_inv_sqrt is the diagonal matrix of the square roots of the inverse diagonal entries of the mass matrix M,
29
+ D_log_sqrt is the diagonal matrix of the square roots of the diagonal entries of the mass matrix on the logical domain,
30
+ M_log_kron_solver is the Kronecker Solver of the mass matrix on the logical domain.
31
+
32
+ These preconditioners work very well even on complex domains as numerical experiments have shown.
33
+ Upon choosing hom_bc=True, a preconditioner for the modified mass matrix M_0 is returned.
34
+ M_0 is a mass matrix of the form
35
+ M_0 = DP @ M @ DP + (I - DP)
36
+ where DP and I are the corresponding DirichletProjector and IdentityOperator.
37
+ See examples/vector_potential_3d.
38
+
39
+ Parameters
40
+ ----------
41
+ M : psydac.linalg.stencil.StencilMatrix | psydac.linalg.block.BlockLinearOperator
42
+ Mass matrix corresponding to fem_space
43
+
44
+ domain_h : psydac.cad.geometry.Geometry
45
+ discretized physical domain used to discretize fem_space
46
+
47
+ fem_space : psydac.fem.basic.FemSpace
48
+ discretized Scalar- or VectorFunctionSpace. M is the corresponding mass matrix
49
+
50
+ hom_bc : bool
51
+ If True, return LST preconditioner for modified M_0 = DP @ M @ DP + (I - DP) mass matrix.
52
+ The argument M in that case remains the same (M, not M_0). DP and I are DirichletProjector and IdentityOperator.
53
+ Default: False.
54
+
55
+ kind : str | None
56
+ Optional. Must be passed if fem_space has no kind. Must match the kind of fem_space if fem_space has a kind.
57
+ Relevant as we must know whether M is a H1, Hcurl, Hdiv or L2 mass matrix.
58
+
59
+ Returns
60
+ -------
61
+ psydac.linalg.stencil.StencilMatrix | psydac.linalg.block.BlockLinearOperator
62
+ LST preconditioner for M (hom_bc=False) or M_0 (hom_b=True).
63
+
64
+ References
65
+ ----------
66
+ [1] Gabriele Loli, Giancarlo Sangalli, Mattia Tani. “Easy and efficient preconditioning of the isogeometric mass
67
+ matrix”. In: Computers & Mathematics with Applications 116 (2022), pp. 245–264
68
+ """
69
+
70
+ # to avoid circular import
71
+ from psydac.api.discretization import discretize
72
+
73
+ dim = fem_space.ldim
74
+ # In 1D one can solve the linear system directly (instead of using this preconditioner)
75
+ assert dim in (2, 3)
76
+
77
+ if hom_bc == True:
78
+ def toarray_1d(A):
79
+ """
80
+ Obtain a numpy array representation of a (1D) LinearOperator (which has not implemented toarray()).
81
+
82
+ We fill an empty numpy array row by row by repeatedly applying unit vectors
83
+ to the transpose of A. In order to obtain those unit vectors in Stencil format,
84
+ we make use of an auxiliary function that takes periodicity into account.
85
+ """
86
+
87
+ assert isinstance(A, LinearOperator)
88
+ W = A.codomain
89
+ assert isinstance(W, StencilVectorSpace)
90
+
91
+ def get_unit_vector_1d(v, periodic, n1, npts1, pads1):
92
+
93
+ v *= 0.0
94
+ v._data[pads1+n1] = 1.
95
+
96
+ if periodic:
97
+ if n1 < pads1:
98
+ v._data[-pads1+n1] = 1.
99
+ if n1 >= npts1-pads1:
100
+ v._data[n1-npts1+pads1] = 1.
101
+
102
+ return v
103
+
104
+ periods = W.periods
105
+ periodic = periods[0]
106
+
107
+ w = W.zeros()
108
+ At = A.T
109
+
110
+ A_arr = np.zeros(A.shape, dtype=A.dtype)
111
+
112
+ npts1, = W.npts
113
+ pads1, = W.pads
114
+ for n1 in range(npts1):
115
+ e_n1 = get_unit_vector_1d(w, periodic, n1, npts1, pads1)
116
+ A_n1 = At @ e_n1
117
+ A_arr[n1, :] = A_n1.toarray()
118
+
119
+ return A_arr
120
+
121
+ def M_0_1d_to_bandsolver(A):
122
+ """
123
+ Converts the M0_0_1d StencilMatrix to a BandedSolver.
124
+
125
+ Closely resembles BandedSolver.from_stencil_mat_1d,
126
+ the difference being that M0_0_1d neither has a
127
+ remove_spurious_entries() nor a toarray() function.
128
+
129
+ """
130
+
131
+ dmat = dia_matrix(toarray_1d(A), dtype=A.dtype)
132
+ la = abs(dmat.offsets.min())
133
+ ua = dmat.offsets.max()
134
+ cmat = dmat.tocsr()
135
+
136
+ A_bnd = np.zeros((1+ua+2*la, cmat.shape[1]), A.dtype)
137
+
138
+ for i,j in zip(*cmat.nonzero()):
139
+ A_bnd[la+ua+i-j, j] = cmat[i,j]
140
+
141
+ return BandedSolver(ua, la, A_bnd)
142
+
143
+ domain = domain_h.domain
144
+
145
+ ncells, = domain_h.ncells.values()
146
+ degree = fem_space.degree
147
+ periodic, = domain_h.periodic.values()
148
+
149
+ V_cs = fem_space.coeff_space
150
+
151
+ logical_domain = domain.logical_domain
152
+
153
+ # ----- Compute D_inv_sqrt
154
+
155
+ D_inv_sqrt = M.diagonal(inverse=True, sqrt=True)
156
+
157
+ # ----- Compute M_log_kron_solver
158
+
159
+ logical_domain_1d_x = Line('L', bounds=logical_domain.bounds1)
160
+ logical_domain_1d_y = Line('L', bounds=logical_domain.bounds2)
161
+ if dim == 3:
162
+ logical_domain_1d_z = Line('L', bounds=logical_domain.bounds3)
163
+
164
+ logical_domain_1d_list = [logical_domain_1d_x, logical_domain_1d_y]
165
+ if dim == 3:
166
+ logical_domain_1d_list += [logical_domain_1d_z]
167
+
168
+ # We gather the 1D mass matrices.
169
+ # Those will be used to obtain D_log_sqrt using the new
170
+ # diagonal function for KroneckerStencilMatrices.
171
+ M_1d_solvers = [[],[]]
172
+ Ms_1d = [[],[]]
173
+ if dim == 3:
174
+ M_1d_solvers += [[]]
175
+ Ms_1d += [[]]
176
+
177
+ # Mark 1D 'h1' spaces built using B-splines.
178
+ # 1D spaces for which (i, j) \notin keys are 'l2' spaces built using M-splines.
179
+ fem_space_kind = fem_space.symbolic_space.kind.name
180
+
181
+ if kind is not None:
182
+ if isinstance(kind, str):
183
+ kind = kind.lower()
184
+ assert(kind in ['h1', 'hcurl', 'hdiv', 'l2'])
185
+ elif isinstance(kind, SpaceType):
186
+ kind = kind.name
187
+ else:
188
+ raise TypeError(f'Expecting kind {kind} to be a str or of SpaceType')
189
+
190
+ # If fem_space has a kind, it must be compatible with kind
191
+ if fem_space_kind != 'undefined':
192
+ assert fem_space_kind == kind, f'fem_space and space_kind are not compatible.'
193
+ else:
194
+ kind = fem_space_kind
195
+
196
+ if kind == 'h1':
197
+ keys = ((0, 0), (1, 0), (2, 0))
198
+ elif kind == 'hcurl':
199
+ keys = ((0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1))
200
+ elif kind == 'hdiv':
201
+ keys = ((0, 0), (1, 1), (2, 2))
202
+ elif kind == 'l2':
203
+ keys = ()
204
+ else:
205
+ raise ValueError(f'kind {kind} must be either h1, hcurl, hdiv or l2.')
206
+
207
+ for i, (ncells_1d, periodic_1d, logical_domain_1d) in enumerate(zip(ncells, periodic, logical_domain_1d_list)):
208
+
209
+ logical_domain_1d_h = discretize(logical_domain_1d, ncells=[ncells_1d, ], periodic=[periodic_1d, ])
210
+
211
+ degrees_1d = [degree_dir[i] for degree_dir in degree] if isinstance(fem_space.coeff_space, BlockVectorSpace) else [degree[i], ]
212
+
213
+ for j, d in enumerate(degrees_1d):
214
+
215
+ kind_1d = 'h1' if (i, j) in keys else 'l2'
216
+ basis = 'B' if (i, j) in keys else 'M'
217
+
218
+ if basis == 'M':
219
+ d += 1
220
+
221
+ V_1d = ScalarFunctionSpace('V', logical_domain_1d, kind =kind_1d)
222
+ Vh_1d = discretize(V_1d, logical_domain_1d_h, degree=[d,], basis=basis)
223
+
224
+ u, v = elements_of(V_1d, names='u, v')
225
+ a_1d = BilinearForm((u, v), integral(logical_domain_1d, u*v))
226
+ ah_1d = discretize(a_1d, logical_domain_1d_h, (Vh_1d, Vh_1d))
227
+ M_1d = ah_1d.assemble()
228
+ Ms_1d[j].append(M_1d)
229
+
230
+ if (hom_bc == True) and ((i, j) in keys):
231
+ DP = DirichletProjector(Vh_1d, space_kind='h1')
232
+ if DP.bcs != ():
233
+ I = IdentityOperator(Vh_1d.coeff_space)
234
+ M_0_1d = DP @ M_1d @ DP + (I - DP)
235
+
236
+ M_0_1d_solver = M_0_1d_to_bandsolver(M_0_1d)
237
+ M_1d_solvers[j].append(M_0_1d_solver)
238
+ else:
239
+ M_1d_solver = BandedSolver.from_stencil_mat_1d(M_1d)
240
+ M_1d_solvers[j].append(M_1d_solver)
241
+ else:
242
+ M_1d_solver = BandedSolver.from_stencil_mat_1d(M_1d)
243
+ M_1d_solvers[j].append(M_1d_solver)
244
+
245
+ if isinstance(V_cs, StencilVectorSpace):
246
+ M_log_kron_solver = KroneckerLinearSolver(V_cs, V_cs, M_1d_solvers[0])
247
+
248
+ else:
249
+ M_0_log_kron_solver = KroneckerLinearSolver(V_cs[0], V_cs[0], M_1d_solvers[0])
250
+ M_1_log_kron_solver = KroneckerLinearSolver(V_cs[1], V_cs[1], M_1d_solvers[1])
251
+ if dim == 3:
252
+ M_2_log_kron_solver = KroneckerLinearSolver(V_cs[2], V_cs[2], M_1d_solvers[2])
253
+
254
+ if dim == 2:
255
+ blocks = [[M_0_log_kron_solver, None],
256
+ [None, M_1_log_kron_solver]]
257
+ else:
258
+ blocks = [[M_0_log_kron_solver, None, None],
259
+ [None, M_1_log_kron_solver, None],
260
+ [None, None, M_2_log_kron_solver]]
261
+
262
+ M_log_kron_solver = BlockLinearOperator (V_cs, V_cs, blocks)
263
+
264
+ # ----- Compute D_log_sqrt
265
+
266
+ if isinstance(V_cs, StencilVectorSpace):
267
+ M_log = KroneckerStencilMatrix(V_cs, V_cs, *Ms_1d[0])
268
+
269
+ D_log_sqrt = M_log.diagonal (inverse=False, sqrt=True)
270
+
271
+ else:
272
+ M_0_log = KroneckerStencilMatrix(V_cs[0], V_cs[0], *Ms_1d[0])
273
+ M_1_log = KroneckerStencilMatrix(V_cs[1], V_cs[1], *Ms_1d[1])
274
+ if dim == 3:
275
+ M_2_log = KroneckerStencilMatrix(V_cs[2], V_cs[2], *Ms_1d[2])
276
+
277
+ if dim == 2:
278
+ blocks = [[M_0_log, None],
279
+ [None, M_1_log]]
280
+ else:
281
+ blocks = [[M_0_log, None, None],
282
+ [None, M_1_log, None],
283
+ [None, None, M_2_log]]
284
+
285
+ M_log = BlockLinearOperator(V_cs, V_cs, blocks=blocks)
286
+ D_log_sqrt = M_log.diagonal(inverse=False, sqrt=True)
287
+
288
+ # --------------------------------
289
+
290
+ M_pc = D_inv_sqrt @ D_log_sqrt @ M_log_kron_solver @ D_log_sqrt @ D_inv_sqrt
291
+
292
+ return M_pc
@@ -1,13 +1,15 @@
1
- # coding: utf-8
2
- # Copyright 2018 Yaman Güçlü
3
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
4
6
  import math
5
7
  import numpy as np
6
8
 
7
9
  from feectools.fem.tests.analytical_profiles_base import AnalyticalProfile
8
10
  from feectools.fem.tests.utilities import horner, falling_factorial
9
11
 
10
- __all__ = ('AnalyticalProfile_1d_cos', 'AnalyticalProfile1D_Poly')
12
+ __all__ = ('AnalyticalProfile1D_Cos', 'AnalyticalProfile1D_Poly')
11
13
 
12
14
  #===============================================================================
13
15
  class AnalyticalProfile1D_Cos( AnalyticalProfile ):
@@ -1,6 +1,8 @@
1
- # coding: utf-8
2
- # Copyright 2018 Yaman Güçlü
3
-
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
4
6
  from abc import ABCMeta, abstractmethod
5
7
 
6
8
  __all__ = ('AnalyticalProfile',)
@@ -1,6 +1,9 @@
1
- # coding: utf-8
2
- # Copyright 2018 Yaman Güçlü
3
- #
1
+ #---------------------------------------------------------------------------#
2
+ # This file is part of PSYDAC which is released under MIT License. See the #
3
+ # LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4
+ # for full license details. #
5
+ #---------------------------------------------------------------------------#
6
+
4
7
  # This file is the Python translation of a Selalib Fortran module:
5
8
  # 'selalib/src/splines/tests/m_splines_error_bounds.F90'
6
9