Skip to content

Commit

Permalink
Add sqrt option to diagonal method of stencil/block matrices (#434)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Yaman Güçlü <yaman.guclu@gmail.com>
  • Loading branch information
max-models and yguclu committed Oct 1, 2024
1 parent 6fc53bb commit 2dc2297
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
9 changes: 7 additions & 2 deletions psydac/linalg/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,18 @@ def __sub__(self, M):
#--------------------------------------
# New properties/methods
#--------------------------------------
def diagonal(self, *, inverse = False, out = None):
def diagonal(self, *, inverse = False, sqrt = False, out = None):
"""Get the coefficients on the main diagonal as another BlockLinearOperator object.
Parameters
----------
inverse : bool
If True, get the inverse of the diagonal. (Default: False).
Can be combined with sqrt to get the inverse square root.
sqrt : bool
If True, get the square root of the diagonal. (Default: False).
Can be combined with inverse to get the inverse square root.
out : BlockLinearOperator
If provided, write the diagonal entries into this matrix. (Default: None).
Expand Down Expand Up @@ -815,7 +820,7 @@ def diagonal(self, *, inverse = False, out = None):
# Store the diagonal (or its inverse) into `out`
for i, j in self.nonzero_block_indices:
if i == j:
out[i, i] = self[i, i].diagonal(inverse = inverse, out = out[i, i])
out[i, i] = self[i, i].diagonal(inverse = inverse, sqrt = sqrt, out = out[i, i])

return out

Expand Down
10 changes: 9 additions & 1 deletion psydac/linalg/stencil.py
Original file line number Diff line number Diff line change
Expand Up @@ -1372,14 +1372,19 @@ def _exchange_assembly_data_serial(self):
self._data[idx_to] += self._data[idx_from]

# ...
def diagonal(self, *, inverse = False, out = None):
def diagonal(self, *, inverse = False, sqrt = False, out = None):
"""
Get the coefficients on the main diagonal as a StencilDiagonalMatrix object.
Parameters
----------
inverse : bool
If True, get the inverse of the diagonal. (Default: False).
Can be combined with sqrt to get the inverse square root.
sqrt : bool
If True, get the square root of the diagonal. (Default: False).
Can be combined with inverse to get the inverse square root.
out : StencilDiagonalMatrix
If provided, write the diagonal entries into this matrix. (Default: None).
Expand Down Expand Up @@ -1418,6 +1423,9 @@ def diagonal(self, *, inverse = False, out = None):
else:
data = diag.copy()

if sqrt:
np.sqrt(data, out=data)

# If needed create a new StencilDiagonalMatrix object
if out is None:
out = StencilDiagonalMatrix(V, W, data)
Expand Down
6 changes: 6 additions & 0 deletions psydac/linalg/tests/test_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,12 @@ def test_inverse_transpose_interaction(n1, n2, p1, p2, P1=False, P2=False):
### -1,T & T,-1 --- -1,T,T --- -1,T,-1 --- T,-1,-1 --- T,-1,T (the combinations I test)
###

# Square root test
scaled_matrix = B * np.random.random() # Ensure the diagonal elements != 1
diagonal_values = scaled_matrix.diagonal(sqrt=False).toarray()
sqrt_diagonal_values = scaled_matrix.diagonal(sqrt=True).toarray()
assert np.array_equal(sqrt_diagonal_values, np.sqrt(diagonal_values))

tol = 1e-5
C = inverse(B, 'cg', tol=tol)
P = B.diagonal(inverse=True)
Expand Down

0 comments on commit 2dc2297

Please sign in to comment.