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
The MATLAB and Fortran codes look surprisingly similar. The subroutines do the following:
-
Lorenz_f.m
: Defines the Lorenz evolution rule$(\dot{X},\dot{Y},\dot{Z})={\bf f}(X,Y,Z)$ . -
steporbit.m
: Evaluate${\phi}^T({\bf x})$ , i.e. dondts_
timesteps according to${\bf f}$ , 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${\bf x}$ so far.relative_err
$=||{\bf F}({\bf x})|| / ||{\bf x}||$ . -
MAIN.m
: Set up initial guess${\bf x}_0$ 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.${\bf F}({\bf x})=\phi^T({\bf x})-{\bf x}$ . 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$\langle{\bf a}|{\bf b}\rangle$ . -
GMRESm.m
: Generalized minimized residual method. Section 3.2 of the notes. GMRES subroutine. -
GMREShook.m
: Calculate hookstep. Section 3.3 of the notes.
- The following data are points on the periodic orbits of figure 8 of the notes, taken from Viswanath (2003).
$Z=27$ 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.m
orPROGRAM MAIN
section 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_err
for the initial guess (iteration 0) with the final relative error. - Comment/uncomment other initial guesses
new_x
$={\bf x}_0$ , or experiment with your own. How do they affect the number of Newton iterations taken? Typically convergence takes$O(10)$ 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
$T$ , too short for a PO;$T$ is not permitted to change, otherwise$||{\bf \phi}^T({\bf x})-{\bf x}||$ could be reduced by simply taking$T\to 0$ . Check thatMAIN
can find the analytic equilibrium solution$(\pm\alpha,\pm\alpha,r-1)$ , where$\alpha=\sqrt{(r-1)\ b}$ .
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)
$=T$ (the period), andnew_x(2:end}
$={\bf x}$ (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
-
saveorbit
is called at the end of each Newton iteration. Add code here to save the current statenew_x
. - If your inner product corresponds to
$\langle{\bf a}|{\bf b}\rangle\ =\ {\bf a}^TW{\bf b}$ where$W$ is a diagonal matrix of positive weights, and here$T$ is the transpose, then pass${\bf x}'=W^\frac{1}{2}{\bf x}$ to the code. The existing functions that take inner products then need no modification. -
Parallel use with MPI+Fortran, the
NewtonHook
andGMRES
codes 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 thedotprod
function. To avoid all threads outputting information, setinfo=1
on rank 0, andinfo=0
on all other ranks.