Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Newton-Krylov solver #114

Merged
merged 63 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
2ed835f
Classic Newton implementation attempt. Not functional yet.
Simkern Sep 27, 2024
734431e
experimental
Simkern Sep 27, 2024
b5b4fc9
Newton-Krylov implemented. Testing using Roessler system.
Simkern Sep 28, 2024
08d7906
Cleanup unnecessary routines
Simkern Sep 28, 2024
d5eecbf
Added bisection, added dynamic tolerances + scheduler interface, adde…
Simkern Sep 30, 2024
af28a77
Updated Newton step bisection and added test for it
Simkern Sep 30, 2024
386802b
deployment
Simkern Sep 30, 2024
c2128ec
Update systems removing explicit procedure for BF update
Simkern Oct 1, 2024
c0a8c4a
Updated bisection to golden ratio search
Simkern Oct 1, 2024
b298763
small updates
Simkern Oct 1, 2024
b8295fd
First attempt to generalize Newton to abstract_linear_solver. Does no…
Simkern Oct 1, 2024
16f1c39
Created Roessler example structure. Typos.
Simkern Oct 2, 2024
d08414d
Newton with abstract linear solver functional.
Simkern Oct 2, 2024
53a8ea9
Merge branch 'newton' into roessler_PO
Simkern Oct 2, 2024
227ac94
Nonlinear solver for roessler
Simkern Oct 2, 2024
dbb3c8f
remove old files, small fix
Simkern Oct 2, 2024
26cccab
Working nonlinear Roessler
Simkern Oct 2, 2024
ce2530e
Cosmetics
Simkern Oct 3, 2024
74822de
Add Newton-Krylov exports
Simkern Oct 3, 2024
284c88c
Added comment regarding info flag in abstract linear solvers
Simkern Oct 3, 2024
21561dd
Added single GMRES from Newton to test
Simkern Oct 3, 2024
1236a1d
Cleanup and cross-check with test suite
Simkern Oct 3, 2024
c095465
Moved to the fypp framework for Newton. Updated the documentation.
Simkern Oct 3, 2024
9b3f489
Improved documentation
Simkern Oct 4, 2024
ee8c012
Added newton_opts. Fixed variable shadowing.
Simkern Oct 7, 2024
bc93f55
Added info flag handling for abstract linear solvers
Simkern Oct 7, 2024
d67a0ad
Added iteration counter to eval inputs to adapt, e.g. tolerances base…
Simkern Oct 7, 2024
ce158b3
Updated Newton exports
Simkern Oct 7, 2024
7dba3ec
Fixed typo in augmented Jacobian. Updated eval to new interface. Fixe…
Simkern Oct 7, 2024
1fcb1a0
Updated example. Added tolerance schedulers.
Simkern Oct 7, 2024
a3a3ac7
Refactoring and updates. Moved opts type def to Utils. Updated to new…
Simkern Oct 7, 2024
225d19d
Added sp version of fixed point test. Small fixes.
Simkern Oct 7, 2024
ac24a5a
Added Floquet operator and monodromy map.
Simkern Oct 8, 2024
5133994
Cleanup. Added computation of Floquet multipliers for PO.
Simkern Oct 8, 2024
721918d
fixed typo in print descriptor.
Simkern Oct 8, 2024
ba63b7a
Update main.f90
Simkern Oct 8, 2024
e0375ac
Updated tests removing verbosity flags in favor of logger calls. Upda…
Simkern Oct 8, 2024
0253a63
Cleanup and Updates to new interfaces.
Simkern Oct 8, 2024
9f95c05
Update to the new interfaces, cleanup, removal of verbosity etc.
Simkern Oct 8, 2024
b6a5902
Cleanup and fine tuning of logging functionality.
Simkern Oct 8, 2024
805da60
Updated tolerance logic. Update to new linear operator and eval inter…
Simkern Oct 8, 2024
10a3ae8
Deployment
Simkern Oct 8, 2024
559ea5e
Shortened too long lines.
Simkern Oct 8, 2024
aa55d66
Fixed typo
Simkern Oct 8, 2024
4c6edee
Fixed long line in Newton.
Simkern Oct 8, 2024
a4402dc
Update NewtonKrylov.fypp
Simkern Oct 8, 2024
c8d595a
Update NewtonKrylov.f90
Simkern Oct 8, 2024
0346edd
Freed up information level in logging prio. Added module/procedure in…
Simkern Oct 12, 2024
709e7ba
Add rand_basis standard function.
Simkern Oct 15, 2024
4bda227
Export rand_basis standard function.
Simkern Oct 15, 2024
ac982f4
Added OTD capability for the Roessler system
Simkern Oct 15, 2024
cf989bd
Updated Newton example. Fixed bugs. Added OTD section to Roessler exa…
Simkern Oct 15, 2024
ba463e0
Cleanup output and main file.
Simkern Oct 15, 2024
cc688e2
removed outpost of trace of Lr
Simkern Oct 15, 2024
59d8e33
First version. Runs but there is a problem
Simkern Oct 15, 2024
5f0f35b
Included FTLE computation. Expanded example to include clean comparis…
Simkern Oct 16, 2024
9a4b3f2
output improvement
Simkern Oct 16, 2024
b9d1838
Added projected modes + route to chaos. Reduced output frq.
Simkern Oct 17, 2024
aae3ec8
add safeguard in qr that caused a runtime error in some cases
Simkern Oct 17, 2024
473132d
Updates requested for pull to dev.
Simkern Oct 21, 2024
ee5a912
Updates and cleanup during code review.
Simkern Oct 21, 2024
edf70bf
Added complex system + jacobian exports
Simkern Oct 21, 2024
46d4e01
Used optval for tolerances.
Simkern Oct 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/roessler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Calculation of (unstable) periodic orbits in the Roessler system using a Newton-Krylov fixed point iteration
217 changes: 217 additions & 0 deletions example/roessler/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
program demo
use stdlib_linalg, only : eye, eigvals
use stdlib_io_npy, only : save_npy
use stdlib_sorting, only : sort
use stdlib_logger, only : information_level, warning_level, debug_level, error_level, none_level
use LightKrylov
use LightKrylov, only: wp => dp
use LightKrylov_Logger
use lightkrylov_IterativeSolvers, only: gmres_rdp
use LightKrylov_Utils
! Roessler
use Roessler
use Roessler_OTD
implicit none

character(len=128), parameter :: this_module = 'Example Roessler'

! Roessler system.
type(roessler_upo), allocatable :: sys
! State vectors
type(state_vector), allocatable :: bf, dx, residual, fp
! Position vectors
type(pos_vector), allocatable :: bfp
! OTD basis
type(pos_vector), allocatable :: OTD_in(:), OTD_out(:)

! Misc
type(newton_dp_opts) :: opts
type(gmres_dp_opts) :: gmres_opts
integer :: i, j, info
real(wp) :: rnorm, tol, Tend, t_FTLE, d
real(wp), dimension(npts, npts) :: M, Id
real(wp), dimension(npts) :: eval, vec
real(wp), dimension(npts, r) :: u, Lu
real(wp), dimension(r, r) :: Lr
! IO
character(len=20) :: fmt

write(fmt,*) '(A22,4(1X,F18.6))'

! Set up logging
call logger_setup()
call logger%configure(level=error_level, time_stamp=.false.)

! Initialize baseflow and perturbation state vectors
allocate(bf, dx, residual)
call bf%zero(); call dx%zero(); call residual%zero()

! Set tolerace
tol = 1e-12_wp

print *, '########################################################################################'
print '(A,E9.2,A)',' # Newton iteration with constant tolerance (tol=', tol, ') #'
print *, '########################################################################################'
print *, ''

call set_position((/ 0.0_wp, 6.1_wp, 1.3_wp /), bf) ! some initial guess
bf%T = 6.0_wp ! period guess
print '(A22,4(16X,A,2X))', ' ', 'X', 'Y', 'Z', 'T'
print fmt, 'Initial guess PO: ', bf%x, bf%y, bf%z, bf%T
print *,''

! Initialize system and Jacobian
sys = roessler_upo()
! Set Jacobian and baseflow
sys%jacobian = jacobian()
sys%jacobian%X = bf

opts = newton_dp_opts(maxiter=30, ifbisect=.false.)
call newton(sys, bf, info, tolerance=tol, options=opts, linear_solver=gmres_rdp, scheduler=constant_atol_dp)

call sys%eval(bf, residual, tol)
print *, ''
print '(A22,4(16X,A,2X))', ' ', 'X', 'Y', 'Z', 'T'
print fmt, 'Solution: ', bf%x, bf%y, bf%z, bf%T
print fmt, 'Solution residual: ', residual%x, residual%y, residual%z, residual%T
print *,''

print *, '########################################################################################'
print '(A,E9.2,A)',' # Newton iteration with dynamic tolerances (target=', tol, ') #'
print *, '########################################################################################'
print *, ''

call set_position((/ 0.0_wp, 6.1_wp, 1.3_wp /), bf) ! some initial guess
bf%T = 6.0_wp ! period guess
print '(A22,4(16X,A,2X))', ' ', 'X', 'Y', 'Z', 'T'
print fmt, 'Initial guess PO: ', bf%x, bf%y, bf%z, bf%T
print *,''
sys%jacobian%X = bf

call newton(sys, bf, info, tolerance=tol, options=opts, linear_solver=gmres_rdp, scheduler=dynamic_tol_dp)

call sys%eval(bf, residual, tol)
print *, ''
print '(A22,4(16X,A,2X))', ' ', 'X', 'Y', 'Z', 'T'
print fmt, 'Solution: ', bf%x, bf%y, bf%z, bf%T
print fmt, 'Solution residual: ', residual%x, residual%y, residual%z, residual%T
print *,''

print *, '########################################################################################'
print *, '# Monodromy matrix and floquet exponents #'
print *, '########################################################################################'
print *, ''

! Compute the stability of the orbit
sys%jacobian = floquet_operator()
sys%jacobian%X = bf ! <- periodic orbit

M = 0.0_wp
Id = eye(npts)
do i = 1, npts
call set_position(Id(:,i), dx)
call sys%jacobian%matvec(dx, residual)
call get_position(residual, M(:,i))
end do
eval = real(eigvals(M))
call sort(eval, reverse=.true.)
print *, 'Real part of the Floquet multipliers exp(T*mu) along the PO:'
print *, ''
do i = 1, npts
print '(4X,I1,": ",E14.6)', i, eval(i)
end do
print *, ''

print *, '########################################################################################'
print *, '# Optimally Time-Dependent (OTD) modes on fixed point #'
print *, '########################################################################################'
print *, ''
allocate(bfp); call bfp%zero()
! Set the baseflow to a fixed point
d = sqrt(c**2 - 4*a*b)
bfp%x = ( c - d)/ 2
bfp%y = (-c + d)/(2*a)
bfp%z = ( c - d)/(2*a)

! Compute OTD modes on the fixed point
allocate(OTD_in(r), OTD_out(r))
call zero_basis(OTD_in); call zero_basis(OTD_out)

! Initialize basis
call rand_basis(OTD_in, ifnorm=.false.)
call orthonormalize_basis(OTD_in)

! We need long enough to converge to the invariant tangent space
Tend = 5.0_wp
t_FTLE = 5.0_wp
call write_header()
call OTD_map(bfp, OTD_in, Tend, OTD_out, t_FTLE)
call rename(file, 'example/roessler/FP_OTD.txt')
! get baseflow
call get_pos(bfp, vec)
! get OTD basis vectors
u = 0.0_wp
Lu = 0.0_wp
do i = 1, r
call get_pos(OTD_out(i), u(:,i))
call linear_roessler(u(:,i), vec, Lu(:,i))
end do
! compute Lr
Lr = 0.0_wp
do i = 1, r
do j = 1, r
Lr(i,j) = dot_product(Lu(:,i), u(:,j))
end do
end do
eval = 0.0_wp
eval(1:r) = eigvals(Lr)
print '(*(A16,1X))', ' ', 'lambda_1', 'lambda_2'
print '(A16,1X,*(F16.9,1X))', 'Reference ', EV_ref
print *, ''
print '(A10,F6.3,1X,*(F16.9,1X))', 'OTD: t=', Tend, eval(1:r)
print *, ''
print *, '########################################################################################'
print *, '# Optimally Time-Dependent (OTD) modes on periodic orbit #'
print *, '########################################################################################'
print *, ''
! Now move to the periodic orbit
call get_position(bf, vec)
call set_pos(vec, bfp)

! Reinitialize basis
call rand_basis(OTD_in, ifnorm=.false.)
call orthonormalize_basis(OTD_in)

! We need long enough to converge to the invariant periodic tangent space
Tend = 30.0_wp*bf%T
t_FTLE = bf%T
call write_header(); call write_header_LE()
print '(*(A16,1X))', ' ', 'LE_1', 'LE_2'
print '(A16,1X,2(F16.9,1X),A16,1X,F16.9)', 'Reference ', LE_ref, 'Period T=', bf%T
call OTD_map(bfp, OTD_in, Tend, OTD_out, t_FTLE, if_rst=.true.)
call rename(file, 'example/roessler/PO_OTD.txt')
call rename(file_LE, 'example/roessler/PO_LE.txt')
print *, ''

print *, ''
print *, '########################################################################################'
print *, '# Optimally Time-Dependent (OTD) modes on Route to Chaos #'
print *, '########################################################################################'
print *, ''

! We use the old converged basis
call orthonormalize_basis(OTD_in)

! We need long enough for the orbit to return to the chaotic attractor
Tend = 60.0_wp*bf%T
t_FTLE = bf%T
call write_header(); call write_header_LE()
print '(*(A16,1X))', ' ', 'FTLE_1', 'FTLE_2'
print '(A16,1X,*(F16.9,1X))', 'Reference ', LE_ref
print *, ''
call OTD_map(bfp, OTD_in, Tend, OTD_out, t_FTLE, if_rst=.false.) ! we do not reset the bf!
call rename(file, 'example/roessler/PO-chaos_OTD.txt')
call rename(file_LE, 'example/roessler/PO-chaos_LE.txt')
print *, ''

end program demo
Loading
Loading