Tutorial and Adapting the code for your own use
February 21, 2023 · View on GitHub
Detailed notes can be found at https://doi.org/10.48550/arXiv.1908.06730 . The notes below are largely a repetition of Section 4.
The tutorial of Section 4 seeks periodic solutions of the Lorenz equations.
For an initial state , we say that is the result of time integration for a time . A periodic solution then satisfies . We set up the system to be solved as . If is an unknown, we must append an extra condition to , but in the case of an equilibrium we can select any fixed value for (typically for a non-dimensionalised system).
Code overview
The MATLAB and Fortran codes look surprisingly similar. The subroutines do the following:
Lorenz_f.m: Defines the Lorenz evolution rule .steporbit.m: Evaluate , i.e. dondts_timesteps according to , where the input vector is constructed as x(1)=T and x(2:4)=(X,Y,Z). The timestep size is dt=T/ndts_.saveorbit.m: Called at the end of each iteration Newton iteration, this saves best so far.relative_err.MAIN.m: Set up initial guess and call the 'black box'NewtonHook.m. NewtonHook subroutine
Other functions are called by NewtonHook.m and are unlikely to need changing for a problem of this type.
-
getrhs.m: Evaluate right-hand side, i.e. . See (3.11) of the linked document. -
multJ.m: Evaluate multiplication by the Jacobian. See (3.13) for the finite difference approximation. -
multJp.m: Preconditioner for multiplication, here an empty function. -
dotprd.m: Evaluate inner product . -
GMRESm.m: Generalized minimized residual method. Section 3.2 of the notes. GMRES subroutine. -
GMREShook.m: Calculate hookstep. Section 3.3 of the notes.
Tutorial
- The following data are points on the periodic orbits of figure 8 of the notes, taken from Viswanath (2003). in call cases.
Orbit X Y T
AB −13.763610682134 −19.578751942452 1.5586522107162
AAB −12.595115397689 −16.970525307084 2.3059072639399
AAAB −11.998523280062 −15.684254096883 3.0235837034339
AABB −12.915137970311 −17.673100172646 3.0842767758221
- Download the code and have a look at
MAIN.morPROGRAM MAINsection ofnewton_Lorenz.f90. - In MATLAB, run
>> MAIN(), or run your executable if you've compiled the Fortran version. They will produce the same result, except that the MATLAB version will also plot orbits corresponding to the initial guess (green) and the converged solution (blue). - Scroll back through the output, and compare
relative_errfor the initial guess (iteration 0) with the final relative error. - Comment/uncomment other initial guesses
new_x, or experiment with your own. How do they affect the number of Newton iterations taken? Typically convergence takes iterations, otherwise it will never converge. - Now let's find an equilibrium point of the system. Uncomment the initial guess and settings to calculate an equilibrium. Here we assume a short fixed , too short for a PO; is not permitted to change, otherwise could be reduced by simply taking .
Check that
MAINcan find the analytic equilibrium solution , where .
Adapting the code for your own use
See also NewtonHook subroutine and GMRES subroutine.
- Experiment with the above Template/Example first, to get used to how the code is set up. The initial guess is put in
new_x. - Note that at present,
new_x(1)(the period), andnew_x(2:end}(the state). - The place to start editing code is
steporbit. If you already have an existing timestepping code, it could do something as simple as call it externally via system calls:
function y = steporbit(ndts_,x)
persistent dt
if ndts_ ~= 1 % Set timestep size dt=T/ndts_
dt = x(1) / ndts_ ; % If only doing one step to calc \dot{x},
end % then use previously set dt.
a = x(2:end) ;
WRITE DATA TO FILES:
dt timestep size
ndts_ number of steps to take
a initial condition
LOAD STATE, TIMESTEP, SAVE STATE:
system('run_my_code.exe')
LOAD TIMESTEPPED STATE: --> a
y = zeros(size(x)) ;
y(2:end) = a ;
end
saveorbitis called at the end of each Newton iteration. Add code here to save the current statenew_x.- If your inner product corresponds to where is a diagonal matrix of positive weights, and here is the transpose, then pass to the code. The existing functions that take inner products then need no modification.
- Parallel use with MPI+Fortran, the
NewtonHookandGMREScodes do not need changing: Split vectors over threads and let each thread pass its section toNewtonHook. The only place where an MPI call is required is an MPI_Allreduce in thedotprodfunction. To avoid all threads outputting information, setinfo=1on rank 0, andinfo=0on all other ranks.