Coverage for pySDC/projects/parallelSDC_reloaded/scripts/fig03_lorenz.py: 100%
102 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-15 06:23 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-15 06:23 +0000
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Created on Wed Jan 10 15:34:24 2024
6Figures with experiment on the Lorenz problem
7"""
9import os
10import numpy as np
11import scipy as sp
13from pySDC.projects.parallelSDC_reloaded.utils import solutionExact, getParamsSDC, solutionSDC, getParamsRK, plt
14from pySDC.helpers.testing import DataChecker
16data = DataChecker(__file__)
18PATH = '/' + os.path.join(*__file__.split('/')[:-1])
19SCRIPT = __file__.split('/')[-1].split('.')[0]
21symList = ['o', '^', 's', '>', '*', '<', 'p', '>'] * 10
23# SDC parameters
24nNodes = 4
25quadType = 'RADAU-RIGHT'
26nodeType = 'LEGENDRE'
27parEfficiency = 0.8 # 1/nNodes
29# -----------------------------------------------------------------------------
30# Trajectories (reference solution)
31# -----------------------------------------------------------------------------
32tEnd = 2
33nSteps = tEnd * 50
34tVals = np.linspace(0, tEnd, nSteps + 1)
35nPeriods = 2
37print(f"Computing exact solution up to t={tEnd} ...")
38uExact = solutionExact(tEnd, nSteps, "LORENZ", u0=(5, -5, 20))
40z = uExact[:, -1]
41idx = sp.signal.find_peaks(z)[0][nPeriods - 1]
42print(f'tEnd for {nPeriods} periods : {tVals[idx]}')
44figName = f"{SCRIPT}_traj"
45plt.figure(figName)
46me = 0.1
47plt.plot(tVals, uExact[:, 0], 's-', label="$x(t)$", markevery=me)
48plt.plot(tVals, uExact[:, 1], 'o-', label="$y(t)$", markevery=me)
49plt.plot(tVals, uExact[:, 2], '^-', label="$z(t)$", markevery=me)
50plt.vlines(tVals[idx], ymin=-20, ymax=40, linestyles="--", linewidth=1)
51plt.legend(loc="upper right")
52plt.xlabel("$t$")
53plt.ylabel("Trajectory")
54plt.gcf().set_size_inches(12, 3)
55plt.tight_layout()
56plt.savefig(f'{PATH}/{figName}.pdf')
58# -----------------------------------------------------------------------------
59# %% Convergence plots
60# -----------------------------------------------------------------------------
61tEnd = 1.24
62nStepsList = np.array([2, 5, 10, 20, 50, 100, 200, 500, 1000])
63dtVals = tEnd / nStepsList
65# The reference solution depends only on nSteps, so compute it once per nSteps
66# instead of once per (qDelta, nSteps).
67uRefs = {nSteps: solutionExact(tEnd, nSteps, "LORENZ", u0=(5, -5, 20)) for nSteps in nStepsList}
70def getError(uNum, uRef):
71 if uNum is None: # pragma: no cover
72 return np.inf
73 return np.linalg.norm(np.linalg.norm(uRef - uNum, np.inf, axis=-1), np.inf)
76config = ["PIC", "MIN-SR-NS"]
77for qDelta, sym in zip(config, symList, strict=False):
78 figName = f"{SCRIPT}_conv_{qDelta}"
79 plt.figure(figName)
81 for nSweeps in [1, 2, 3, 4, 5]:
82 params = getParamsSDC(quadType=quadType, numNodes=nNodes, nodeType=nodeType, qDeltaI=qDelta, nSweeps=nSweeps)
84 errors = []
86 for nSteps in nStepsList:
87 print(f' -- nSteps={nSteps} ...')
89 uRef = uRefs[nSteps]
91 uSDC, counters, parallel = solutionSDC(tEnd, nSteps, params, "LORENZ", u0=(5, -5, 20))
93 err = getError(uSDC, uRef)
94 errors.append(err)
96 # error VS dt
97 label = f"$K={nSweeps}$"
98 plt.loglog(dtVals, errors, sym + '-', label=f"$K={nSweeps}$")
99 data.storeAndCheck(f"{figName}_{label}", errors[1:])
101 x = dtVals[4:]
102 for k in [1, 2, 3, 4, 5, 6]:
103 plt.loglog(x, 1e4 * x**k, "--", color="gray", linewidth=0.8)
105 plt.gca().set(
106 xlabel=r"$\Delta{t}$",
107 ylabel=r"$L_\infty$ error",
108 ylim=(8.530627786509715e-12, 372.2781393394293),
109 )
110 plt.legend(loc="lower right")
111 plt.grid()
112 plt.tight_layout()
113 plt.savefig(f"{PATH}/{figName}.pdf")
116# -----------------------------------------------------------------------------
117# %% Error VS cost plots
118# -----------------------------------------------------------------------------
119def getCost(counters):
120 nNewton, nRHS, tComp = counters
121 return nNewton + nRHS
124minPrec = ["MIN-SR-NS", "MIN-SR-S", "MIN-SR-FLEX"]
126symList = ['^', '>', '<', 'o', 's', '*']
127config = [
128 [(*minPrec, "LU", "EE", "PIC"), 4],
129 [(*minPrec, "VDHS", "RK4", "ESDIRK43"), 4],
130 [(*minPrec, "PIC", "RK4", "ESDIRK43"), 5],
131]
134i = 0
135for qDeltaList, nSweeps in config:
136 figName = f"{SCRIPT}_cost_{i}"
137 i += 1
138 plt.figure(figName)
140 for qDelta, sym in zip(qDeltaList, symList, strict=False):
141 try:
142 params = getParamsRK(qDelta)
143 except KeyError:
144 params = getParamsSDC(
145 quadType=quadType, numNodes=nNodes, nodeType=nodeType, qDeltaI=qDelta, nSweeps=nSweeps
146 )
148 errors = []
149 costs = []
151 for nSteps in nStepsList:
152 uRef = uRefs[nSteps]
154 uSDC, counters, parallel = solutionSDC(tEnd, nSteps, params, "LORENZ", u0=(5, -5, 20))
156 err = getError(uSDC, uRef)
157 errors.append(err)
159 cost = getCost(counters)
160 if parallel:
161 assert qDelta != "EE", "wait, whaaat ??"
162 cost /= nNodes * parEfficiency
163 costs.append(cost)
165 # error VS cost
166 ls = '-' if qDelta.startswith("MIN-SR-") else "--"
167 plt.loglog(costs, errors, sym + ls, label=qDelta)
168 data.storeAndCheck(f"{figName}_{qDelta}", errors[2:], rtol=1e-2)
170 plt.gca().set(
171 xlabel="Cost",
172 ylabel=r"$L_\infty$ error",
173 ylim=(1e-10, 400),
174 xlim=(30, 20000),
175 )
176 plt.legend(loc="lower left")
177 plt.grid()
178 plt.tight_layout()
179 plt.savefig(f"{PATH}/{figName}.pdf")
181data.writeToJSON()