Skip to content

Commit 6559e26

Browse files
bernadett92matthewtownson
authored andcommitted
fall back to least squares solver when Cholesky fails for infinite phasescreen
1 parent 659f03d commit 6559e26

File tree

2 files changed

+14
-6
lines changed

2 files changed

+14
-6
lines changed

aotools/turbulence/infinitephasescreen.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,14 @@ def makeAMatrix(self):
143143
Calculates the "A" matrix, that uses the existing data to find a new
144144
component of the new phase vector.
145145
"""
146-
# Cholsky solve can fail - if so do brute force inversion
147146
try:
148147
cf = linalg.cho_factor(self.cov_mat_zz)
149148
inv_cov_zz = linalg.cho_solve(cf, numpy.identity(self.cov_mat_zz.shape[0]))
149+
self.A_mat = self.cov_mat_xz.dot(inv_cov_zz)
150150
except linalg.LinAlgError:
151-
# print("Cholesky solve failed. Performing SVD inversion...")
152-
# inv_cov_zz = numpy.linalg.pinv(self.cov_mat_zz)
153-
raise linalg.LinAlgError("Could not invert Covariance Matrix to for A and B Matrices. Try with a larger pixel scale or smaller L0")
154-
155-
self.A_mat = self.cov_mat_xz.dot(inv_cov_zz)
151+
print("Cholesky solve failed. Performing least squares inversion...")
152+
inv_cov_zz = numpy.linalg.lstsq(self.cov_mat_zz, numpy.identity(self.cov_mat_zz.shape[0]), rcond=1e-8)
153+
self.A_mat = self.cov_mat_xz.dot(inv_cov_zz[0])
156154

157155
def makeBMatrix(self):
158156
"""

test/test_infinitephasescreen.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from aotools.turbulence import infinitephasescreen
2+
import numpy as np
23

34
def testVKInitScreen():
45

@@ -9,6 +10,15 @@ def testVKAddRow():
910
scrn = infinitephasescreen.PhaseScreenVonKarman(128, 4./64, 0.2, 50, n_columns=4)
1011
scrn.add_row()
1112

13+
def testLeastSquaresSolver():
14+
airmass = 1.0 / np.cos(30.0 / 180. * np.pi)
15+
r0 = 0.9759 * 0.5 / (0.7 * 4.848) * airmass ** (-3. / 5.)
16+
r0wavelength = r0 * (500 / 500.0) ** (6. / 5.)
17+
screen = infinitephasescreen.PhaseScreenVonKarman(120, 1./120, r0wavelength, 50, 1, n_columns=2)
18+
mean_scrn = np.sqrt(np.mean(screen.scrn**2))
19+
for i in range(500):
20+
screen.add_row()
21+
assert(0.5 <= mean_scrn/np.sqrt(np.mean(screen.scrn**2)) <= 1.5)
1222

1323

1424
# Test of Kolmogoroc screen

0 commit comments

Comments
 (0)