freealg 0.7.17__py3-none-any.whl → 0.7.18__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.
- freealg/__init__.py +8 -6
- freealg/__version__.py +1 -1
- freealg/_algebraic_form/_branch_points.py +18 -18
- freealg/_algebraic_form/_continuation_algebraic.py +13 -13
- freealg/_algebraic_form/_cusp.py +15 -15
- freealg/_algebraic_form/_cusp_wrap.py +6 -6
- freealg/_algebraic_form/_decompress.py +16 -16
- freealg/_algebraic_form/_decompress4.py +31 -31
- freealg/_algebraic_form/_decompress5.py +23 -23
- freealg/_algebraic_form/_decompress6.py +13 -13
- freealg/_algebraic_form/_decompress7.py +15 -15
- freealg/_algebraic_form/_decompress8.py +17 -17
- freealg/_algebraic_form/_decompress9.py +18 -18
- freealg/_algebraic_form/_decompress_new.py +17 -17
- freealg/_algebraic_form/_decompress_new_2.py +57 -57
- freealg/_algebraic_form/_decompress_util.py +10 -10
- freealg/_algebraic_form/_decompressible.py +292 -0
- freealg/_algebraic_form/_edge.py +10 -10
- freealg/_algebraic_form/_homotopy4.py +9 -9
- freealg/_algebraic_form/_homotopy5.py +9 -9
- freealg/_algebraic_form/_support.py +19 -19
- freealg/_algebraic_form/algebraic_form.py +262 -468
- freealg/_base_form.py +401 -0
- freealg/_free_form/__init__.py +1 -4
- freealg/_free_form/_density_util.py +1 -1
- freealg/_free_form/_plot_util.py +3 -511
- freealg/_free_form/free_form.py +8 -367
- freealg/_util.py +59 -11
- freealg/distributions/__init__.py +2 -1
- freealg/distributions/_base_distribution.py +163 -0
- freealg/distributions/_chiral_block.py +137 -11
- freealg/distributions/_compound_poisson.py +141 -47
- freealg/distributions/_deformed_marchenko_pastur.py +138 -33
- freealg/distributions/_deformed_wigner.py +98 -9
- freealg/distributions/_fuss_catalan.py +269 -0
- freealg/distributions/_kesten_mckay.py +4 -130
- freealg/distributions/_marchenko_pastur.py +8 -196
- freealg/distributions/_meixner.py +4 -130
- freealg/distributions/_wachter.py +4 -130
- freealg/distributions/_wigner.py +10 -127
- freealg/visualization/__init__.py +2 -2
- freealg/visualization/{_rgb_hsv.py → _domain_coloring.py} +37 -29
- freealg/visualization/_plot_util.py +513 -0
- {freealg-0.7.17.dist-info → freealg-0.7.18.dist-info}/METADATA +1 -1
- freealg-0.7.18.dist-info/RECORD +74 -0
- freealg-0.7.17.dist-info/RECORD +0 -69
- /freealg/{_free_form/_sample.py → _sample.py} +0 -0
- /freealg/{_free_form/_support.py → _support.py} +0 -0
- {freealg-0.7.17.dist-info → freealg-0.7.18.dist-info}/WHEEL +0 -0
- {freealg-0.7.17.dist-info → freealg-0.7.18.dist-info}/licenses/AUTHORS.txt +0 -0
- {freealg-0.7.17.dist-info → freealg-0.7.18.dist-info}/licenses/LICENSE.txt +0 -0
- {freealg-0.7.17.dist-info → freealg-0.7.18.dist-info}/top_level.txt +0 -0
|
@@ -64,14 +64,14 @@ def build_time_grid(sizes, n0, min_n_times=0):
|
|
|
64
64
|
# eval P partials
|
|
65
65
|
# ===============
|
|
66
66
|
|
|
67
|
-
def eval_P_partials(z, m,
|
|
67
|
+
def eval_P_partials(z, m, coeffs):
|
|
68
68
|
"""
|
|
69
69
|
Evaluate P(z,m) and its partial derivatives dP/dz and dP/dm.
|
|
70
70
|
|
|
71
|
-
This assumes P is represented by `
|
|
71
|
+
This assumes P is represented by `coeffs` in the monomial basis
|
|
72
72
|
|
|
73
73
|
P(z, m) = sum_{j=0..s} a_j(z) * m^j,
|
|
74
|
-
a_j(z) = sum_{i=0..deg_z}
|
|
74
|
+
a_j(z) = sum_{i=0..deg_z} coeffs[i, j] * z^i.
|
|
75
75
|
|
|
76
76
|
The function returns P, dP/dz, dP/dm with broadcasting over z and m.
|
|
77
77
|
|
|
@@ -81,7 +81,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
81
81
|
First argument to P.
|
|
82
82
|
m : complex or array_like of complex
|
|
83
83
|
Second argument to P. Must be broadcast-compatible with `z`.
|
|
84
|
-
|
|
84
|
+
coeffs : ndarray, shape (deg_z+1, s+1)
|
|
85
85
|
Coefficient matrix for P in the monomial basis.
|
|
86
86
|
|
|
87
87
|
Returns
|
|
@@ -103,14 +103,14 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
103
103
|
--------
|
|
104
104
|
.. code-block:: python
|
|
105
105
|
|
|
106
|
-
P, Pz, Pm = eval_P_partials(1.0 + 1j, 0.2 + 0.3j,
|
|
106
|
+
P, Pz, Pm = eval_P_partials(1.0 + 1j, 0.2 + 0.3j, coeffs)
|
|
107
107
|
"""
|
|
108
108
|
|
|
109
109
|
z = numpy.asarray(z, dtype=complex)
|
|
110
110
|
m = numpy.asarray(m, dtype=complex)
|
|
111
111
|
|
|
112
|
-
deg_z = int(
|
|
113
|
-
s = int(
|
|
112
|
+
deg_z = int(coeffs.shape[0] - 1)
|
|
113
|
+
s = int(coeffs.shape[1] - 1)
|
|
114
114
|
|
|
115
115
|
if (z.ndim == 0) and (m.ndim == 0):
|
|
116
116
|
zz = complex(z)
|
|
@@ -120,7 +120,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
120
120
|
ap = numpy.empty(s + 1, dtype=complex)
|
|
121
121
|
|
|
122
122
|
for j in range(s + 1):
|
|
123
|
-
c =
|
|
123
|
+
c = coeffs[:, j]
|
|
124
124
|
|
|
125
125
|
val = 0.0 + 0.0j
|
|
126
126
|
for i in range(deg_z, -1, -1):
|
|
@@ -160,10 +160,10 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
160
160
|
Pm = numpy.zeros(zz.size, dtype=complex)
|
|
161
161
|
|
|
162
162
|
for j in range(s + 1):
|
|
163
|
-
aj = zp @
|
|
163
|
+
aj = zp @ coeffs[:, j]
|
|
164
164
|
P += aj * mp[:, j]
|
|
165
165
|
|
|
166
|
-
ajp = dzp @
|
|
166
|
+
ajp = dzp @ coeffs[:, j]
|
|
167
167
|
Pz += ajp * mp[:, j]
|
|
168
168
|
|
|
169
169
|
if j >= 1:
|
|
@@ -176,7 +176,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
176
176
|
# fd solve w
|
|
177
177
|
# ==========
|
|
178
178
|
|
|
179
|
-
# def fd_solve_w(z, t,
|
|
179
|
+
# def fd_solve_w(z, t, coeffs, w_init, max_iter=50, tol=1e-12,
|
|
180
180
|
# armijo=1e-4, min_lam=1e-6, w_min=1e-14):
|
|
181
181
|
# """
|
|
182
182
|
# Solve for w = m(t,z) from the implicit FD equation using damped Newton.
|
|
@@ -197,7 +197,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
197
197
|
# Query point in the complex plane.
|
|
198
198
|
# t : float
|
|
199
199
|
# Time parameter (tau = exp(t)).
|
|
200
|
-
#
|
|
200
|
+
# coeffs : ndarray
|
|
201
201
|
# Coefficients defining P(zeta,y) in the monomial basis.
|
|
202
202
|
# w_init : complex
|
|
203
203
|
# Initial guess for w.
|
|
@@ -231,7 +231,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
231
231
|
# .. code-block:: python
|
|
232
232
|
#
|
|
233
233
|
# w, ok = fd_solve_w(
|
|
234
|
-
# z=0.5 + 1e-6j, t=2.0,
|
|
234
|
+
# z=0.5 + 1e-6j, t=2.0, coeffs=coeffs, w_init=m1_fn(0.5 + 1e-6j),
|
|
235
235
|
# max_iter=50, tol=1e-12
|
|
236
236
|
# )
|
|
237
237
|
# """
|
|
@@ -255,7 +255,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
255
255
|
# zeta = z + alpha / w
|
|
256
256
|
# y = tau * w
|
|
257
257
|
#
|
|
258
|
-
# F, Pz, Py = eval_P_partials(zeta, y,
|
|
258
|
+
# F, Pz, Py = eval_P_partials(zeta, y, coeffs)
|
|
259
259
|
# F = complex(F)
|
|
260
260
|
# Pz = complex(Pz)
|
|
261
261
|
# Py = complex(Py)
|
|
@@ -285,7 +285,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
285
285
|
# zeta_new = z + alpha / w_new
|
|
286
286
|
# y_new = tau * w_new
|
|
287
287
|
#
|
|
288
|
-
# F_new = eval_P_partials(zeta_new, y_new,
|
|
288
|
+
# F_new = eval_P_partials(zeta_new, y_new, coeffs)[0]
|
|
289
289
|
# F_new = complex(F_new)
|
|
290
290
|
#
|
|
291
291
|
# if abs(F_new) <= (1.0 - armijo * lam) * F_abs:
|
|
@@ -298,10 +298,10 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
298
298
|
# if not ok:
|
|
299
299
|
# return w, False
|
|
300
300
|
#
|
|
301
|
-
# F_end = eval_P_partials(z + alpha / w, tau * w,
|
|
301
|
+
# F_end = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
|
|
302
302
|
# return w, (abs(F_end) <= 10.0 * tol)
|
|
303
303
|
|
|
304
|
-
# def fd_solve_w(z, t,
|
|
304
|
+
# def fd_solve_w(z, t, coeffs, w_init, max_iter=50, tol=1e-12,
|
|
305
305
|
# armijo=1e-4, min_lam=1e-6, w_min=1e-14):
|
|
306
306
|
# """
|
|
307
307
|
# Solve for w = m(t,z) from the implicit FD equation using damped Newton.
|
|
@@ -322,7 +322,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
322
322
|
# Query point in the complex plane.
|
|
323
323
|
# t : float
|
|
324
324
|
# Time parameter (tau = exp(t)).
|
|
325
|
-
#
|
|
325
|
+
# coeffs : ndarray
|
|
326
326
|
# Coefficients defining P(zeta,y) in the monomial basis.
|
|
327
327
|
# w_init : complex
|
|
328
328
|
# Initial guess for w.
|
|
@@ -356,7 +356,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
356
356
|
# .. code-block:: python
|
|
357
357
|
#
|
|
358
358
|
# w, ok = fd_solve_w(
|
|
359
|
-
# z=0.5 + 1e-6j, t=2.0,
|
|
359
|
+
# z=0.5 + 1e-6j, t=2.0, coeffs=coeffs, w_init=m1_fn(0.5 + 1e-6j),
|
|
360
360
|
# max_iter=50, tol=1e-12
|
|
361
361
|
# )
|
|
362
362
|
# """
|
|
@@ -383,7 +383,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
383
383
|
# # zeta = z + alpha / w
|
|
384
384
|
# # y = tau * w
|
|
385
385
|
# #
|
|
386
|
-
# # F, Pz, Py = eval_P_partials(zeta, y,
|
|
386
|
+
# # F, Pz, Py = eval_P_partials(zeta, y, coeffs)
|
|
387
387
|
# # F = complex(F)
|
|
388
388
|
# # Pz = complex(Pz)
|
|
389
389
|
# # Py = complex(Py)
|
|
@@ -413,7 +413,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
413
413
|
# # zeta_new = z + alpha / w_new
|
|
414
414
|
# # y_new = tau * w_new
|
|
415
415
|
# #
|
|
416
|
-
# # F_new = eval_P_partials(zeta_new, y_new,
|
|
416
|
+
# # F_new = eval_P_partials(zeta_new, y_new, coeffs)[0]
|
|
417
417
|
# # F_new = complex(F_new)
|
|
418
418
|
# #
|
|
419
419
|
# # if abs(F_new) <= (1.0 - armijo * lam) * F_abs:
|
|
@@ -439,7 +439,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
439
439
|
# # P(z + beta/y, y) = 0, beta = tau - 1.
|
|
440
440
|
# # Multiply by y^deg_z to clear denominators and get a polynomial in y.
|
|
441
441
|
#
|
|
442
|
-
# a = numpy.asarray(
|
|
442
|
+
# a = numpy.asarray(coeffs, dtype=numpy.complex128)
|
|
443
443
|
# deg_z = a.shape[0] - 1
|
|
444
444
|
# deg_m = a.shape[1] - 1
|
|
445
445
|
#
|
|
@@ -502,16 +502,16 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
502
502
|
# w = complex(best)
|
|
503
503
|
#
|
|
504
504
|
# # final residual check
|
|
505
|
-
# F_end = eval_P_partials(z + alpha / w, tau * w,
|
|
505
|
+
# F_end = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
|
|
506
506
|
# return w, (abs(F_end) <= 1e3 * tol)
|
|
507
507
|
#
|
|
508
508
|
# # -------------------
|
|
509
509
|
#
|
|
510
510
|
#
|
|
511
|
-
# F_end = eval_P_partials(z + alpha / w, tau * w,
|
|
511
|
+
# F_end = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
|
|
512
512
|
# return w, (abs(F_end) <= 10.0 * tol)
|
|
513
513
|
|
|
514
|
-
def fd_solve_w(z, t,
|
|
514
|
+
def fd_solve_w(z, t, coeffs, w_init, max_iter=50, tol=1e-12,
|
|
515
515
|
armijo=1e-4, min_lam=1e-6, w_min=1e-14):
|
|
516
516
|
"""
|
|
517
517
|
Damped Newton solve for w from F_t(z,w)=P(z+alpha/w, tau*w)=0.
|
|
@@ -547,7 +547,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
|
|
|
547
547
|
zeta = z + alpha / w
|
|
548
548
|
y = tau * w
|
|
549
549
|
|
|
550
|
-
F, Pz, Py = eval_P_partials(zeta, y,
|
|
550
|
+
F, Pz, Py = eval_P_partials(zeta, y, coeffs)
|
|
551
551
|
F = complex(F)
|
|
552
552
|
Pz = complex(Pz)
|
|
553
553
|
Py = complex(Py)
|
|
@@ -579,7 +579,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
|
|
|
579
579
|
lam *= 0.5
|
|
580
580
|
continue
|
|
581
581
|
|
|
582
|
-
F_new = eval_P_partials(z + alpha / w_new, tau * w_new,
|
|
582
|
+
F_new = eval_P_partials(z + alpha / w_new, tau * w_new, coeffs)[0]
|
|
583
583
|
F_new = complex(F_new)
|
|
584
584
|
|
|
585
585
|
# Armijo-like sufficient decrease on residual norm
|
|
@@ -594,7 +594,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
|
|
|
594
594
|
return w, False
|
|
595
595
|
|
|
596
596
|
# if max_iter hit, accept only if residual is reasonably small
|
|
597
|
-
F_end = eval_P_partials(z + alpha / w, tau * w,
|
|
597
|
+
F_end = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
|
|
598
598
|
F_end = complex(F_end)
|
|
599
599
|
return w, (abs(F_end) <= 10.0 * tol)
|
|
600
600
|
|
|
@@ -604,7 +604,7 @@ def fd_solve_w(z, t, a_coeffs, w_init, max_iter=50, tol=1e-12,
|
|
|
604
604
|
# NEW FUNCTION
|
|
605
605
|
# ============
|
|
606
606
|
|
|
607
|
-
def fd_candidates_w(z, t,
|
|
607
|
+
def fd_candidates_w(z, t, coeffs, w_min=1e-14):
|
|
608
608
|
"""
|
|
609
609
|
Return candidate roots w solving P(z + alpha/w, tau*w)=0 with Im(w)>0 (if Im(z)>0).
|
|
610
610
|
"""
|
|
@@ -613,7 +613,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
613
613
|
alpha = 1.0 - 1.0 / tau
|
|
614
614
|
want_pos_imag = (z.imag > 0.0)
|
|
615
615
|
|
|
616
|
-
a = numpy.asarray(
|
|
616
|
+
a = numpy.asarray(coeffs, dtype=numpy.complex128)
|
|
617
617
|
deg_z = a.shape[0] - 1
|
|
618
618
|
deg_m = a.shape[1] - 1
|
|
619
619
|
|
|
@@ -651,7 +651,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
651
651
|
# residual filter (optional but helps)
|
|
652
652
|
# -------------
|
|
653
653
|
# TEST
|
|
654
|
-
# F = eval_P_partials(z + alpha / w, tau * w,
|
|
654
|
+
# F = eval_P_partials(z + alpha / w, tau * w, coeffs)[0]
|
|
655
655
|
# if abs(F) < 1e-6:
|
|
656
656
|
# cands.append(complex(w))
|
|
657
657
|
# ---------------
|
|
@@ -666,7 +666,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
666
666
|
# decompress newton old
|
|
667
667
|
# =====================
|
|
668
668
|
|
|
669
|
-
# def decompress_newton_old(z_list, t_grid,
|
|
669
|
+
# def decompress_newton_old(z_list, t_grid, coeffs, w0_list=None,
|
|
670
670
|
# dt_max=0.1, sweep=True, time_rel_tol=5.0,
|
|
671
671
|
# max_iter=50, tol=1e-12, armijo=1e-4,
|
|
672
672
|
# min_lam=1e-6, w_min=1e-14):
|
|
@@ -679,7 +679,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
679
679
|
# Query points z (typically x + 1j*eta with eta > 0).
|
|
680
680
|
# t_grid : array_like of float
|
|
681
681
|
# Strictly increasing time grid.
|
|
682
|
-
#
|
|
682
|
+
# coeffs : ndarray
|
|
683
683
|
# Coefficients defining P(zeta,y) in the monomial basis used by eval_P.
|
|
684
684
|
# w0_list : array_like of complex
|
|
685
685
|
# Initial values at t_grid[0] (typically m0(z_list) on the physical
|
|
@@ -731,7 +731,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
731
731
|
#
|
|
732
732
|
# t_grid = numpy.linspace(0.0, 4.0, 2)
|
|
733
733
|
# W, ok = fd_evolve_on_grid(
|
|
734
|
-
# z_query, t_grid,
|
|
734
|
+
# z_query, t_grid, coeffs, w0_list=w0_list,
|
|
735
735
|
# dt_max=0.1, sweep=True, time_rel_tol=5.0,
|
|
736
736
|
# max_iter=50, tol=1e-12, armijo=1e-4, min_lam=1e-6, w_min=1e-14
|
|
737
737
|
# )
|
|
@@ -780,7 +780,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
780
780
|
# # Independent solves: each point uses previous-time seed only.
|
|
781
781
|
# for iz in range(nz):
|
|
782
782
|
# w, success = fd_solve_w(
|
|
783
|
-
# z_list[iz], t,
|
|
783
|
+
# z_list[iz], t, coeffs, w_prev[iz],
|
|
784
784
|
# max_iter=max_iter, tol=tol, armijo=armijo,
|
|
785
785
|
# min_lam=min_lam, w_min=w_min
|
|
786
786
|
# )
|
|
@@ -794,7 +794,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
794
794
|
# i0 = int(numpy.argmax(numpy.abs(numpy.imag(w_prev))))
|
|
795
795
|
#
|
|
796
796
|
# w0, ok0 = fd_solve_w(
|
|
797
|
-
# z_list[i0], t,
|
|
797
|
+
# z_list[i0], t, coeffs, w_prev[i0],
|
|
798
798
|
# max_iter=max_iter, tol=tol, armijo=armijo,
|
|
799
799
|
# min_lam=min_lam, w_min=w_min
|
|
800
800
|
# )
|
|
@@ -808,14 +808,14 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
808
808
|
# def solve_with_choice(iz, w_neighbor):
|
|
809
809
|
# # First try neighbor-seeded Newton (spatial continuity).
|
|
810
810
|
# w_a, ok_a = fd_solve_w(
|
|
811
|
-
# z_list[iz], t,
|
|
811
|
+
# z_list[iz], t, coeffs, w_neighbor,
|
|
812
812
|
# max_iter=max_iter, tol=tol, armijo=armijo,
|
|
813
813
|
# min_lam=min_lam, w_min=w_min
|
|
814
814
|
# )
|
|
815
815
|
#
|
|
816
816
|
# # Always keep a time-consistent fallback candidate.
|
|
817
817
|
# w_b, ok_b = fd_solve_w(
|
|
818
|
-
# z_list[iz], t,
|
|
818
|
+
# z_list[iz], t, coeffs, w_prev[iz],
|
|
819
819
|
# max_iter=max_iter, tol=tol, armijo=armijo,
|
|
820
820
|
# min_lam=min_lam, w_min=w_min
|
|
821
821
|
# )
|
|
@@ -865,7 +865,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
865
865
|
# decompress newton
|
|
866
866
|
# =================
|
|
867
867
|
|
|
868
|
-
# def decompress_newton(z_list, t_grid,
|
|
868
|
+
# def decompress_newton(z_list, t_grid, coeffs, w0_list=None,
|
|
869
869
|
# dt_max=0.1, sweep=True, time_rel_tol=5.0,
|
|
870
870
|
# active_imag_eps=None, sweep_pad=20,
|
|
871
871
|
# max_iter=50, tol=1e-12, armijo=1e-4,
|
|
@@ -879,7 +879,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
879
879
|
# Query points z (typically x + 1j*eta with eta > 0), ordered along x.
|
|
880
880
|
# t_grid : array_like of float
|
|
881
881
|
# Strictly increasing time grid.
|
|
882
|
-
#
|
|
882
|
+
# coeffs : ndarray
|
|
883
883
|
# Coefficients defining P(zeta,y) in the monomial basis.
|
|
884
884
|
# w0_list : array_like of complex
|
|
885
885
|
# Initial values at t_grid[0] (typically m0(z_list) on the physical
|
|
@@ -945,14 +945,14 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
945
945
|
# # def solve_with_choice(iz, w_seed):
|
|
946
946
|
# # # Neighbor-seeded candidate (spatial continuity)
|
|
947
947
|
# # w_a, ok_a = fd_solve_w(
|
|
948
|
-
# # z_list[iz], t,
|
|
948
|
+
# # z_list[iz], t, coeffs, w_seed,
|
|
949
949
|
# # max_iter=max_iter, tol=tol, armijo=armijo,
|
|
950
950
|
# # min_lam=min_lam, w_min=w_min
|
|
951
951
|
# # )
|
|
952
952
|
# #
|
|
953
953
|
# # # Time-seeded candidate (time continuation)
|
|
954
954
|
# # w_b, ok_b = fd_solve_w(
|
|
955
|
-
# # z_list[iz], t,
|
|
955
|
+
# # z_list[iz], t, coeffs, w_prev[iz],
|
|
956
956
|
# # max_iter=max_iter, tol=tol, armijo=armijo,
|
|
957
957
|
# # min_lam=min_lam, w_min=w_min
|
|
958
958
|
# # )
|
|
@@ -981,7 +981,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
981
981
|
# # TEST
|
|
982
982
|
# # def solve_with_choice(iz, w_seed):
|
|
983
983
|
# # # candidate roots at this (t,z)
|
|
984
|
-
# # cands = fd_candidates_w(z_list[iz], t,
|
|
984
|
+
# # cands = fd_candidates_w(z_list[iz], t, coeffs, w_min=w_min)
|
|
985
985
|
# #
|
|
986
986
|
# # # ---------------------
|
|
987
987
|
# # # TEST
|
|
@@ -996,7 +996,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
996
996
|
# # if len(cands) == 0:
|
|
997
997
|
# # # fallback to your existing single-root solver
|
|
998
998
|
# # w, success = fd_solve_w(
|
|
999
|
-
# # z_list[iz], t,
|
|
999
|
+
# # z_list[iz], t, coeffs, w_prev[iz],
|
|
1000
1000
|
# # max_iter=max_iter, tol=tol, armijo=armijo,
|
|
1001
1001
|
# # min_lam=min_lam, w_min=w_min
|
|
1002
1002
|
# # )
|
|
@@ -1026,14 +1026,14 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
1026
1026
|
# def solve_with_choice(iz, w_neighbor):
|
|
1027
1027
|
# # Neighbor-seeded Newton (spatial continuity).
|
|
1028
1028
|
# w_a, ok_a = fd_solve_w(
|
|
1029
|
-
# z_list[iz], t,
|
|
1029
|
+
# z_list[iz], t, coeffs, w_neighbor,
|
|
1030
1030
|
# max_iter=max_iter, tol=tol, armijo=armijo,
|
|
1031
1031
|
# min_lam=min_lam, w_min=w_min
|
|
1032
1032
|
# )
|
|
1033
1033
|
#
|
|
1034
1034
|
# # Time-seeded Newton (time continuity).
|
|
1035
1035
|
# w_b, ok_b = fd_solve_w(
|
|
1036
|
-
# z_list[iz], t,
|
|
1036
|
+
# z_list[iz], t, coeffs, w_prev[iz],
|
|
1037
1037
|
# max_iter=max_iter, tol=tol, armijo=armijo,
|
|
1038
1038
|
# min_lam=min_lam, w_min=w_min
|
|
1039
1039
|
# )
|
|
@@ -1092,7 +1092,7 @@ def fd_candidates_w(z, t, a_coeffs, w_min=1e-14):
|
|
|
1092
1092
|
# # problems.
|
|
1093
1093
|
# for iz in range(nz):
|
|
1094
1094
|
# w, success = fd_solve_w(
|
|
1095
|
-
# z_list[iz], t,
|
|
1095
|
+
# z_list[iz], t, coeffs, w_prev[iz],
|
|
1096
1096
|
# max_iter=max_iter, tol=tol, armijo=armijo,
|
|
1097
1097
|
# min_lam=min_lam, w_min=w_min
|
|
1098
1098
|
# )
|
|
@@ -1286,7 +1286,7 @@ def eval_row_by_z_homotopy(
|
|
|
1286
1286
|
z_targets,
|
|
1287
1287
|
w_seed_targets,
|
|
1288
1288
|
R,
|
|
1289
|
-
|
|
1289
|
+
coeffs,
|
|
1290
1290
|
w_anchor,
|
|
1291
1291
|
*,
|
|
1292
1292
|
steps=80,
|
|
@@ -1353,13 +1353,13 @@ def eval_row_by_z_homotopy(
|
|
|
1353
1353
|
z = z0 + s * (zA - z0)
|
|
1354
1354
|
|
|
1355
1355
|
w_new, ok_new = fd_solve_w(
|
|
1356
|
-
z, t,
|
|
1356
|
+
z, t, coeffs, w,
|
|
1357
1357
|
max_iter=max_iter, tol=tol, armijo=armijo,
|
|
1358
1358
|
min_lam=min_lam, w_min=w_min
|
|
1359
1359
|
)
|
|
1360
1360
|
|
|
1361
1361
|
if not ok_new:
|
|
1362
|
-
cands = fd_candidates_w(z, t,
|
|
1362
|
+
cands = fd_candidates_w(z, t, coeffs, w_min=w_min)
|
|
1363
1363
|
if cands:
|
|
1364
1364
|
w_new = _pick(cands, z, w)
|
|
1365
1365
|
ok_new = (w_new is not None)
|
|
@@ -1376,13 +1376,13 @@ def eval_row_by_z_homotopy(
|
|
|
1376
1376
|
z = zA + s * (zB - zA)
|
|
1377
1377
|
|
|
1378
1378
|
w_new, ok_new = fd_solve_w(
|
|
1379
|
-
z, t,
|
|
1379
|
+
z, t, coeffs, w,
|
|
1380
1380
|
max_iter=max_iter, tol=tol, armijo=armijo,
|
|
1381
1381
|
min_lam=min_lam, w_min=w_min
|
|
1382
1382
|
)
|
|
1383
1383
|
|
|
1384
1384
|
if not ok_new:
|
|
1385
|
-
cands = fd_candidates_w(z, t,
|
|
1385
|
+
cands = fd_candidates_w(z, t, coeffs, w_min=w_min)
|
|
1386
1386
|
if cands:
|
|
1387
1387
|
w_new = _pick(cands, z, w)
|
|
1388
1388
|
ok_new = (w_new is not None)
|
|
@@ -1396,7 +1396,7 @@ def eval_row_by_z_homotopy(
|
|
|
1396
1396
|
|
|
1397
1397
|
if not ok:
|
|
1398
1398
|
# fallback at zT: prefer continuity to the provided per-z time seed
|
|
1399
|
-
cands = fd_candidates_w(zT, t,
|
|
1399
|
+
cands = fd_candidates_w(zT, t, coeffs, w_min=w_min)
|
|
1400
1400
|
if cands:
|
|
1401
1401
|
w_out[k] = _pick(cands, zT, w_seed_targets[k])
|
|
1402
1402
|
ok_out[k] = (w_out[k] is not None)
|
|
@@ -1412,7 +1412,7 @@ def eval_row_by_z_homotopy(
|
|
|
1412
1412
|
def decompress_newton(
|
|
1413
1413
|
z_list,
|
|
1414
1414
|
t_grid,
|
|
1415
|
-
|
|
1415
|
+
coeffs,
|
|
1416
1416
|
w0_list=None,
|
|
1417
1417
|
*,
|
|
1418
1418
|
R=400.0,
|
|
@@ -1474,7 +1474,7 @@ def decompress_newton(
|
|
|
1474
1474
|
|
|
1475
1475
|
zeta = z + alpha / w
|
|
1476
1476
|
y = tau * w
|
|
1477
|
-
F, Pz, Py = eval_P_partials(zeta, y,
|
|
1477
|
+
F, Pz, Py = eval_P_partials(zeta, y, coeffs)
|
|
1478
1478
|
F = complex(F)
|
|
1479
1479
|
if abs(F) <= tol:
|
|
1480
1480
|
return w, True
|
|
@@ -1502,7 +1502,7 @@ def decompress_newton(
|
|
|
1502
1502
|
|
|
1503
1503
|
zeta_new = z + alpha / w_new
|
|
1504
1504
|
y_new = tau * w_new
|
|
1505
|
-
F_new = complex(eval_P_partials(zeta_new, y_new,
|
|
1505
|
+
F_new = complex(eval_P_partials(zeta_new, y_new, coeffs)[0])
|
|
1506
1506
|
|
|
1507
1507
|
if abs(F_new) <= (1.0 - armijo * lam) * F_abs:
|
|
1508
1508
|
w = w_new
|
|
@@ -1516,7 +1516,7 @@ def decompress_newton(
|
|
|
1516
1516
|
# accept if residual not crazy
|
|
1517
1517
|
zeta = z + alpha / w
|
|
1518
1518
|
y = tau * w
|
|
1519
|
-
F_end = complex(eval_P_partials(zeta, y,
|
|
1519
|
+
F_end = complex(eval_P_partials(zeta, y, coeffs)[0])
|
|
1520
1520
|
return w, (abs(F_end) <= 1e3 * tol)
|
|
1521
1521
|
|
|
1522
1522
|
# -----------------------
|
|
@@ -64,14 +64,14 @@ def build_time_grid(sizes, n0, min_n_times=0):
|
|
|
64
64
|
# eval P partials
|
|
65
65
|
# ===============
|
|
66
66
|
|
|
67
|
-
def eval_P_partials(z, m,
|
|
67
|
+
def eval_P_partials(z, m, coeffs):
|
|
68
68
|
"""
|
|
69
69
|
Evaluate P(z,m) and its partial derivatives dP/dz and dP/dm.
|
|
70
70
|
|
|
71
|
-
This assumes P is represented by `
|
|
71
|
+
This assumes P is represented by `coeffs` in the monomial basis
|
|
72
72
|
|
|
73
73
|
P(z, m) = sum_{j=0..s} a_j(z) * m^j,
|
|
74
|
-
a_j(z) = sum_{i=0..deg_z}
|
|
74
|
+
a_j(z) = sum_{i=0..deg_z} coeffs[i, j] * z^i.
|
|
75
75
|
|
|
76
76
|
The function returns P, dP/dz, dP/dm with broadcasting over z and m.
|
|
77
77
|
|
|
@@ -81,7 +81,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
81
81
|
First argument to P.
|
|
82
82
|
m : complex or array_like of complex
|
|
83
83
|
Second argument to P. Must be broadcast-compatible with `z`.
|
|
84
|
-
|
|
84
|
+
coeffs : ndarray, shape (deg_z+1, s+1)
|
|
85
85
|
Coefficient matrix for P in the monomial basis.
|
|
86
86
|
|
|
87
87
|
Returns
|
|
@@ -103,14 +103,14 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
103
103
|
--------
|
|
104
104
|
.. code-block:: python
|
|
105
105
|
|
|
106
|
-
P, Pz, Pm = eval_P_partials(1.0 + 1j, 0.2 + 0.3j,
|
|
106
|
+
P, Pz, Pm = eval_P_partials(1.0 + 1j, 0.2 + 0.3j, coeffs)
|
|
107
107
|
"""
|
|
108
108
|
|
|
109
109
|
z = numpy.asarray(z, dtype=complex)
|
|
110
110
|
m = numpy.asarray(m, dtype=complex)
|
|
111
111
|
|
|
112
|
-
deg_z = int(
|
|
113
|
-
s = int(
|
|
112
|
+
deg_z = int(coeffs.shape[0] - 1)
|
|
113
|
+
s = int(coeffs.shape[1] - 1)
|
|
114
114
|
|
|
115
115
|
if (z.ndim == 0) and (m.ndim == 0):
|
|
116
116
|
zz = complex(z)
|
|
@@ -120,7 +120,7 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
120
120
|
ap = numpy.empty(s + 1, dtype=complex)
|
|
121
121
|
|
|
122
122
|
for j in range(s + 1):
|
|
123
|
-
c =
|
|
123
|
+
c = coeffs[:, j]
|
|
124
124
|
|
|
125
125
|
val = 0.0 + 0.0j
|
|
126
126
|
for i in range(deg_z, -1, -1):
|
|
@@ -160,10 +160,10 @@ def eval_P_partials(z, m, a_coeffs):
|
|
|
160
160
|
Pm = numpy.zeros(zz.size, dtype=complex)
|
|
161
161
|
|
|
162
162
|
for j in range(s + 1):
|
|
163
|
-
aj = zp @
|
|
163
|
+
aj = zp @ coeffs[:, j]
|
|
164
164
|
P += aj * mp[:, j]
|
|
165
165
|
|
|
166
|
-
ajp = dzp @
|
|
166
|
+
ajp = dzp @ coeffs[:, j]
|
|
167
167
|
Pz += ajp * mp[:, j]
|
|
168
168
|
|
|
169
169
|
if j >= 1:
|