diff --git a/DESCRIPTION b/DESCRIPTION
index 087450f2..44a824bd 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Name: ODE Test Problems
-Version: 0.0.1
-Date: May 10, 2023
+Version: 0.2.0
+Date: November 7, 2023
depends: octave (>= 6.4.0)
Author: Steven Roberts, Andrey A. Popov, Arash Sarshar, Adrian Sandu
Maintainer: Steven Roberts
diff --git a/docs/conf.py b/docs/conf.py
index c5f19942..2ab3a739 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -26,6 +26,7 @@
primary_domain = 'mat'
matlab_src_dir = '../toolbox'
matlab_keep_package_prefix = False
+matlab_auto_link = 'basic'
autodoc_default_options = {
'member-order': 'bysource',
diff --git a/docs/generate_problem_rst.py b/docs/generate_problem_rst.py
index 1715723e..ae455dec 100644
--- a/docs/generate_problem_rst.py
+++ b/docs/generate_problem_rst.py
@@ -30,7 +30,7 @@
.. automodule:: +otp.{problem.parent.name}.+presets
''')
- for preset in problem.parent.glob('+presets/*.m'):
+ for preset in sorted(problem.parent.glob('+presets/*.m')):
stream.write(f'''
.. autoclass:: {preset.stem}
:members:
diff --git a/docs/references.bib b/docs/references.bib
index 141c7a39..728b7b8a 100644
--- a/docs/references.bib
+++ b/docs/references.bib
@@ -55,17 +55,16 @@ @Article{PR74
}
-@Article{Rob67,
+@Article{Rob66,
title={The Solution of a Set of Reaction Rate Equations},
author={Robertson, H.H.},
journal={Walsh, J., Ed., Numerical Analysis, An introduction},
- year={1967},
+ year={1966},
pages= {178--182},
- publisher = "Academic Press",
- address = "Cambridge, Massachusetts",
+ volume={178182},
+ publisher = {Academic Press}
}
-
@article{SLH70,
author = {Seinfeld, J. H. and Lapidus, Leon and Hwang, Myungkyu},
title = {Review of Numerical Integration Techniques for Stiff Ordinary Differential Equations},
@@ -105,5 +104,78 @@ @inproceedings{Lor96
volume={1},
number={1},
year={1996},
- organization={Reading}
+ organization={Reading},
+ doi={10.1017/CBO9780511617652.004}
}
+
+@article{PS19,
+ title={A Bayesian approach to multivariate adaptive localization in ensemble-based data assimilation with time-dependent extensions},
+ author={Popov, Andrey A and Sandu, Adrian},
+ journal={Nonlinear Processes in Geophysics},
+ volume={26},
+ number={2},
+ pages={109--122},
+ year={2019},
+ publisher={Copernicus Publications G{\"o}ttingen, Germany},
+ doi={10.5194/npg-26-109-2019}
+}
+
+@article{FN74,
+ author = {Field, Richard J. and Noyes, Richard M.},
+ title = "{Oscillations in chemical systems. {IV}. {L}imit cycle behavior in a model of a real chemical reaction}",
+ journal = {The Journal of Chemical Physics},
+ volume = {60},
+ number = {5},
+ pages = {1877-1884},
+ year = {1974},
+ issn = {0021-9606},
+ doi = {10.1063/1.1681288}
+}
+
+@incollection{EH76,
+ title = {Comparing Numerical Methods for the Solution of Stiff Systems of {ODE}s Arising in Chemistry},
+ editor = {L. LAPIDUS and W.E. SCHIESSER},
+ booktitle = {Numerical Methods for Differential Systems},
+ publisher = {Academic Press},
+ pages = {45-66},
+ year = {1976},
+ isbn = {978-0-12-436640-4},
+ doi = {10.1016/B978-0-12-436640-4.50008-3},
+ author = {W.H. Enright and T.E. Hull}
+}
+
+@article{GW82,
+ author = {Björn A. Gottwald and Gerhard Wanner},
+ title ={Comparison of Numerical Methods for Stiff Differential Equations in Biology and Chemistry},
+ journal = {SIMULATION},
+ volume = {38},
+ number = {2},
+ pages = {61-66},
+ year = {1982},
+ doi = {10.1177/003754978203800206}
+}
+
+
+@article{Asc89,
+author = {Ascher, Uri},
+title = {On Symmetric Schemes and Differential-Algebraic Equations},
+journal = {SIAM Journal on Scientific and Statistical Computing},
+volume = {10},
+number = {5},
+pages = {937-949},
+year = {1989},
+doi = {10.1137/0910054}
+}
+
+@article{Pet86,
+ author = {L. R. Petzold},
+ journal = {SIAM Journal on Numerical Analysis},
+ number = {4},
+ pages = {837--852},
+ publisher = {Society for Industrial and Applied Mathematics},
+ title = {Order Results for Implicit Runge-Kutta Methods Applied to Differential/ Algebraic Systems},
+ volume = {23},
+ year = {1986},
+ url = {https://www.jstor.org/stable/2157625}
+}
+
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 8f463ca3..26f58a86 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,9 +1,9 @@
sphinx==6.2.1
sphinx-autobuild==2021.3.14
-sphinx_rtd_theme==1.2.0
-sphinxcontrib-matlabdomain==0.18.0
+sphinx_rtd_theme==1.3.0
+sphinxcontrib-matlabdomain==0.20.2
sphinxcontrib-napoleon==0.7
sphinx-math-dollar==1.2.1
sphinxcontrib-bibtex==2.5.0
-myst-parser==1.0.0
-pyyaml==6.0
+myst-parser==2.0.0
+pyyaml==6.0.1
diff --git a/docs/structure/index.rst b/docs/structure/index.rst
index b5798d8c..0e555eaa 100644
--- a/docs/structure/index.rst
+++ b/docs/structure/index.rst
@@ -8,4 +8,6 @@ TODO
:maxdepth: 1
:glob:
- *
+ problem
+ rhs
+ parameters
diff --git a/docs/structure/parameters.rst b/docs/structure/parameters.rst
new file mode 100644
index 00000000..1cc3d570
--- /dev/null
+++ b/docs/structure/parameters.rst
@@ -0,0 +1,6 @@
+Parameters
+================================================================================
+
+.. automodule:: +otp
+.. autoclass:: Parameters
+ :members:
diff --git a/notebooks/quick-start.ipynb b/notebooks/quick-start.ipynb
index 00b490aa..73ac5a2b 100644
--- a/notebooks/quick-start.ipynb
+++ b/notebooks/quick-start.ipynb
@@ -181,6 +181,37 @@
"The parameters of a model are stored as properties in the problem object:"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\u001b[?2004l\n",
+ "problem =\n",
+ "\n",
+ " otp.lorenz63.presets.Canonical object with properties:\n",
+ "\n",
+ " Name: Lorenz Equations\n",
+ " NumVars: [1x1 double]\n",
+ " Parameters: [1x1 otp.lorenz63.Lorenz63Parameters]\n",
+ " RHS: [1x1 otp.RHS]\n",
+ " TimeSpan: [1x2 double]\n",
+ " Y0: [3x1 double]\n",
+ "\n",
+ "\u001b[?2004h"
+ ]
+ }
+ ],
+ "source": [
+ "problem"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 4,
@@ -528,7 +559,7 @@
},
{
"cell_type": "code",
- "execution_count": 45,
+ "execution_count": 5,
"metadata": {
"tags": []
},
@@ -552,7 +583,7 @@
},
{
"cell_type": "code",
- "execution_count": 51,
+ "execution_count": 8,
"metadata": {
"tags": []
},
@@ -569,6 +600,7 @@
"\u001b[?2004h\u001b[?2004l\n",
"\u001b[?2004h\u001b[?2004l\n",
"\u001b[?2004h\u001b[?2004l\n",
+ "\u001b[?2004h\u001b[?2004l\n",
"\u001b[?2004h"
]
},
@@ -591,9 +623,31 @@
"\n",
"\n",
"subplot(132); contourf(reshape(sol.y(:,end), dim_x, []), 10)\n",
- "axis('equal'); title(sprintf( 't = %1.1f' , sol.x(end))); xlabel('x'); ylabel('y')\n"
+ "axis('equal'); title(sprintf( 't = %1.1f' , sol.x(end))); xlabel('x'); ylabel('y')\n",
+ "\n",
+ "\n"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\u001b[?2004l\r",
+ "\r\n",
+ "error: print: no figure to print\r\n",
+ "error: called from\r\n",
+ " print at line 463 column 5\r\n",
+ "\u001b[?2004h"
+ ]
+ }
+ ],
+ "source": []
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -603,7 +657,7 @@
},
{
"cell_type": "code",
- "execution_count": 56,
+ "execution_count": 13,
"metadata": {
"tags": []
},
diff --git a/toolbox/+otp/+ascherlineardae/+presets/Canonical.m b/toolbox/+otp/+ascherlineardae/+presets/Canonical.m
index e7ec574d..d6f697b4 100644
--- a/toolbox/+otp/+ascherlineardae/+presets/Canonical.m
+++ b/toolbox/+otp/+ascherlineardae/+presets/Canonical.m
@@ -1,23 +1,21 @@
classdef Canonical < otp.ascherlineardae.AscherLinearDAEProblem
- %CANONICAL The problem formulation of the linear DAE from the literature
- %
- % See
- % Ascher, Uri. "On symmetric schemes and differential-algebraic equations."
- % SIAM journal on scientific and statistical computing 10.5 (1989): 937-949.
-
+ % The problem defined by Uri Ascher in :cite:p:`Asc89` (sec. 2) which uses time span $t ∈ [0, 1]$ and intial
+ % condition $[y_0, z_0]^T = [1, β]^T$.
+
methods
- function obj = Canonical(beta)
- tspan = [0.0; 1];
-
- if nargin < 1
- beta = 0.5;
- end
-
- params = otp.ascherlineardae.AscherLinearDAEParameters;
- params.Beta = beta;
-
- y0 = [1; beta];
+ function obj = Canonical(varargin)
+ % Create the Canonical Ascher Linear DAE problem object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. The accepted names are
+ %
+ % - ``Beta`` – Value of $β$.
+ params = otp.ascherlineardae.AscherLinearDAEParameters('Beta', 1, varargin{:});
+ y0 = [1; params.Beta];
+ tspan = [0.0; 1.0];
obj = obj@otp.ascherlineardae.AscherLinearDAEProblem(tspan, y0, params);
end
end
diff --git a/toolbox/+otp/+ascherlineardae/+presets/Petzold.m b/toolbox/+otp/+ascherlineardae/+presets/Petzold.m
new file mode 100644
index 00000000..14e9f89b
--- /dev/null
+++ b/toolbox/+otp/+ascherlineardae/+presets/Petzold.m
@@ -0,0 +1,15 @@
+classdef Petzold < otp.ascherlineardae.AscherLinearDAEProblem
+ % The Petzold DAE example :cite:p:`Pet86` as a special case of the Ascher linear DAE problem. This preset uses time
+ % span $t ∈ [0, 1]$ and $β = 0 $ with the initial condition $[y_0, z_0]^T = [1, 0]^T$.
+
+ methods
+ function obj = Petzold()
+ % Create the Petzold Ascher Linear DAE problem object.
+
+ params = otp.ascherlineardae.AscherLinearDAEParameters('Beta', 0);
+ y0 = [1; params.Beta];
+ tspan = [0.0; 1.0];
+ obj = obj@otp.ascherlineardae.AscherLinearDAEProblem(tspan, y0, params);
+ end
+ end
+end
diff --git a/toolbox/+otp/+ascherlineardae/+presets/Stiff.m b/toolbox/+otp/+ascherlineardae/+presets/Stiff.m
new file mode 100644
index 00000000..5e102971
--- /dev/null
+++ b/toolbox/+otp/+ascherlineardae/+presets/Stiff.m
@@ -0,0 +1,15 @@
+classdef Stiff < otp.ascherlineardae.AscherLinearDAEProblem
+ % The Stiff example from :cite:p:`Asc89`. A variant of the Ascher linear DAE problem which uses time span
+ % $t ∈ [0, 1]$ and $β = 100$ with the initial condition $[y_0, z_0]^T = [1, 100]^T$.
+
+ methods
+ function obj = Stiff()
+ % Create the stiff Ascher Linear DAE problem object.
+
+ params = otp.ascherlineardae.AscherLinearDAEParameters('Beta', 100);
+ y0 = [1; params.Beta];
+ tspan = [0.0; 1.0];
+ obj = obj@otp.ascherlineardae.AscherLinearDAEProblem(tspan, y0, params);
+ end
+ end
+end
diff --git a/toolbox/+otp/+ascherlineardae/AscherLinearDAEParameters.m b/toolbox/+otp/+ascherlineardae/AscherLinearDAEParameters.m
index ae660c65..3a64f2f6 100644
--- a/toolbox/+otp/+ascherlineardae/AscherLinearDAEParameters.m
+++ b/toolbox/+otp/+ascherlineardae/AscherLinearDAEParameters.m
@@ -1,7 +1,21 @@
-classdef AscherLinearDAEParameters
- %ASCHERLINEARDAEPARAMETERS
+classdef AscherLinearDAEParameters < otp.Parameters
+ % Parameters for Ascher Linear DAE problem
properties
- %Beta is an arbitrary scalar parameter
- Beta %MATLAB ONLY: (1,1) {mustBeNumeric} = 0.5
+ % A scalar parameter $β$ in the linear model. It affects the stifness of the problem.
+ Beta %MATLAB ONLY: (1,1) {mustBeNumeric} = 1
+ end
+
+ methods
+ function obj = AscherLinearDAEParameters(varargin)
+ % Create a Ascher Linear DAE parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
+ % value initializes that property.
+
+ obj = obj@otp.Parameters(varargin{:});
+ end
end
end
diff --git a/toolbox/+otp/+ascherlineardae/AscherLinearDAEProblem.m b/toolbox/+otp/+ascherlineardae/AscherLinearDAEProblem.m
index 34764a34..7ceea46b 100644
--- a/toolbox/+otp/+ascherlineardae/AscherLinearDAEProblem.m
+++ b/toolbox/+otp/+ascherlineardae/AscherLinearDAEProblem.m
@@ -1,8 +1,62 @@
classdef AscherLinearDAEProblem < otp.Problem
- %ASCHERLINEARDAEPROBLEM This is an Index-1 DAE problem
+ % A linear differential-algebraic problem with a time-dependant mass matrix.
%
+ % The Ascher linear DAE Problem :cite:p:`Asc89` is an index-1 differential-agebraic equation given by
+ %
+ % $$
+ % \begin{bmatrix}
+ % 1 & -t \\
+ % 0 & 0
+ % \end{bmatrix} \begin{bmatrix} y'(t) \\ z'(t) \end{bmatrix} = \begin{bmatrix}
+ % -1 & 1+t \\
+ % β & -1-β t
+ % \end{bmatrix} \begin{bmatrix} y(t) \\ z(t) \end{bmatrix} + \begin{bmatrix}
+ % 0 \\
+ % \sin(t)
+ % \end{bmatrix}.
+ % $$
+ %
+ % When the initial condition $y(0) = 1 , z(0) = β$ is used, the problem has the following closed-form solution:
+ %
+ % $$
+ % \begin{bmatrix} y(t)\\ z(t) \end{bmatrix} = \begin{bmatrix}
+ % t \sin(t) + (1 + β t) e^{-t}\\
+ % β e^{-t} + \sin(t)
+ % \end{bmatrix}.
+ % $$
+ %
+ % This DAE problem can be used to investigate the convergence of implcit time-stepping methods due to its stiffness
+ % and time-dependant mass matrix.
+ %
+ % Notes
+ % -----
+ % +---------------------+-----------------------------------------+
+ % | Type | DAE |
+ % +---------------------+-----------------------------------------+
+ % | Number of Variables | 2 |
+ % +---------------------+-----------------------------------------+
+ % | Stiff | possibly, depending on $β$ |
+ % +---------------------+-----------------------------------------+
+ %
+ % Example
+ % -------
+ % >>> problem = otp.ascherlineardae.presets.Canonical('Beta', 50);
+ % >>> t = linspace(0, 1);
+ % >>> sol = problem.solveExactly(t);
+ % >>> problem.plot(t, sol);
+
methods
function obj = AscherLinearDAEProblem(timeSpan, y0, parameters)
+ % Create an Ascher linear DAE problem object.
+ %
+ % Parameters
+ % ----------
+ % timeSpan : numeric(1, 2)
+ % The start and final time.
+ % y0 : numeric(2, 1)
+ % The initial condition.
+ % parameters : AscherLinearDAEParameters
+ % The parameters.
obj@otp.Problem('Ascher Linear DAE', 2, timeSpan, y0, parameters);
end
end
@@ -17,7 +71,15 @@ function onSettingsChanged(obj)
'MStateDependence', 'none', ...
'MassSingular', 'yes');
end
-
+
+ function label = internalIndex2label(~, index)
+ if index == 1
+ label = 'Differential';
+ else
+ label = 'Algebraic';
+ end
+ end
+
function y = internalSolveExactly(obj, t)
beta = obj.Parameters.Beta;
if ~isequal(obj.Y0, [1; beta])
@@ -35,4 +97,3 @@ function onSettingsChanged(obj)
end
end
end
-
diff --git a/toolbox/+otp/+cusp/+presets/Canonical.m b/toolbox/+otp/+cusp/+presets/Canonical.m
index 450cb77f..01900d0b 100644
--- a/toolbox/+otp/+cusp/+presets/Canonical.m
+++ b/toolbox/+otp/+cusp/+presets/Canonical.m
@@ -1,14 +1,14 @@
classdef Canonical < otp.cusp.CUSPProblem
- % The CUSP configuration from :cite:p:`HW96` (pp. 147-148) which uses time span $t \in [0, 1.1]$, $N = 32$ grid
- % cells, and initial conditions
+ % The CUSP configuration from :cite:p:`HW96` (pp. 147-148) which uses time span $t ∈ [0, 1.1]$, $N = 32$ grid cells,
+ % and initial conditions
%
% $$
% y_i(0) &= 0 ,\\
- % a_i(0) &= -2 \cos\left( \frac{2 i \pi}{N} \right), \\
- % b_i(0) &= 2 \sin\left( \frac{2 i \pi}{N} \right), \\
+ % a_i(0) &= -2 \cos\left( \frac{2 i π}{N} \right), \\
+ % b_i(0) &= 2 \sin\left( \frac{2 i π}{N} \right), \\
% $$
%
- % for $i = 1, \dots, N$. The parameters are $\varepsilon = 10^{-4}$ and $\sigma = \frac{1}{144}$.
+ % for $i = 1, …, N$. The parameters are $ε = 10^{-4}$ and $σ = \frac{1}{144}$.
methods
function obj = Canonical(varargin)
@@ -20,32 +20,24 @@
% A variable number of name-value pairs. The accepted names are
%
% - ``N`` – The number of cells in the spatial discretization.
- % - ``epsilon`` – Value of $\varepsilon$.
- % - ``sigma`` – Value of $\sigma$.
- %
- % Returns
- % -------
- % obj : CUSPProblem
- % The constructed problem.
+ % - ``epsilon`` – Value of $ε$.
+ % - ``sigma`` – Value of $σ$.
p = inputParser;
p.addParameter('N', 32);
- p.addParameter('epsilon', 1e-4);
- p.addParameter('sigma', 1/144);
p.parse(varargin{:});
- opts = p.Results;
-
- params = otp.cusp.CUSPParameters;
- params.Epsilon = opts.epsilon;
- params.Sigma = opts.sigma;
+ n = p.Results.N;
- ang = 2 * pi / opts.N * (1:opts.N).';
- y0 = zeros(opts.N, 1);
- a0 = -2*cos(ang);
- b0 = 2*sin(ang);
+ ang = 2 * pi * (1:n).' / n;
+ y0 = zeros(n, 1);
+ a0 = -2 * cos(ang);
+ b0 = 2 * sin(ang);
u0 = [y0; a0; b0];
tspan = [0; 1.1];
+
+ unmatched = namedargs2cell(p.Unmatched);
+ params = otp.cusp.CUSPParameters('Epsilon', 1e-4, 'Sigma', 1/144, unmatched{:});
obj = obj@otp.cusp.CUSPProblem(tspan, u0, params);
end
diff --git a/toolbox/+otp/+cusp/CUSPParameters.m b/toolbox/+otp/+cusp/CUSPParameters.m
index 15b966e9..a56986c9 100644
--- a/toolbox/+otp/+cusp/CUSPParameters.m
+++ b/toolbox/+otp/+cusp/CUSPParameters.m
@@ -1,11 +1,25 @@
-classdef CUSPParameters
+classdef CUSPParameters < otp.Parameters
% Parameters for the CUSP problem.
properties
- % The stiffness parameter $\varepsilon$ for the "cusp catastrophe" model.
+ % The stiffness parameter $ε$ for the "cusp catastrophe" model.
Epsilon %MATLAB ONLY: (1,1) {mustBeNumeric}
- % The diffusion coefficient $\sigma$ for all three variables.
+ % The diffusion coefficient $σ$ for all three variables.
Sigma %MATLAB ONLY: (1,1) {mustBeNumeric}
end
+
+ methods
+ function obj = CUSPParameters(varargin)
+ % Create a CUSP parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
+ % value initializes that property.
+
+ obj = obj@otp.Parameters(varargin{:});
+ end
+ end
end
diff --git a/toolbox/+otp/+cusp/CUSPProblem.m b/toolbox/+otp/+cusp/CUSPProblem.m
index 0794835c..d637351f 100644
--- a/toolbox/+otp/+cusp/CUSPProblem.m
+++ b/toolbox/+otp/+cusp/CUSPProblem.m
@@ -4,33 +4,32 @@
% The CUSP problem :cite:p:`HW96` (pp. 147-148) is the PDE
%
% $$
- % \frac{\partial y}{\partial t} &= -\frac{1}{\varepsilon} (y^3 + a y + b)
- % + \sigma \frac{\partial^2 y}{\partial x^2}, \\
- % \frac{\partial a}{\partial t} &= b + 0.07 v + \sigma \frac{\partial^2 a}{\partial x^2}, \\
- % \frac{\partial b}{\partial t} &= (1 - a^2) b - a - 0.4 y + 0.035 v + \sigma \frac{\partial^2 b}{\partial x^2},
+ % \frac{\partial y}{\partial t} &= -\frac{1}{ε} (y^3 + a y + b) + σ \frac{\partial^2 y}{\partial x^2}, \\
+ % \frac{\partial a}{\partial t} &= b + 0.07 v + σ \frac{\partial^2 a}{\partial x^2}, \\
+ % \frac{\partial b}{\partial t} &= (1 - a^2) b - a - 0.4 y + 0.035 v + σ \frac{\partial^2 b}{\partial x^2},
% $$
%
%
- % where $v = u / (u + 0.1)$ and $u = (y - 0.7)(y - 1.3)$. The spatial domain $x \in [0, 1]$ has period boundary
+ % where $v = u / (u + 0.1)$ and $u = (y - 0.7)(y - 1.3)$. The spatial domain $x ∈ [0, 1]$ has period boundary
% conditions. Discretization with second order finite difference on a grid with $N$ cells gives
%
% $$
- % y'_i &= -\frac{1}{\varepsilon} (y_i^3 + a_i y_i + b_i) + \sigma N^2 (y_{i-1} - 2 y_i + y_{i+1}) \\
- % a'_i &= b_i + 0.07 v_i + \sigma N^2 (a_{i-1} - 2 a_i + a_{i+1}) \\
- % b'_i &= (1 - a_i^2) b_i - a_i - 0.4 y_i + 0.035 v_i + \sigma N^2 (b_{i-1} - 2 b_i + b_{i+1}),
+ % y'_i &= -\frac{1}{ε} (y_i^3 + a_i y_i + b_i) + σ N^2 (y_{i-1} - 2 y_i + y_{i+1}) \\
+ % a'_i &= b_i + 0.07 v_i + σ N^2 (a_{i-1} - 2 a_i + a_{i+1}) \\
+ % b'_i &= (1 - a_i^2) b_i - a_i - 0.4 y_i + 0.035 v_i + σ N^2 (b_{i-1} - 2 b_i + b_{i+1}),
% $$
%
- % where $i = 1, \dots, N$. Values at cell indices $i=0, N+1$ are specificied by the periodic boundary conditions.
+ % where $i = 1, …, N$. Values at cell indices $i=0, N+1$ are specificied by the periodic boundary conditions.
%
% Notes
% -----
- % +---------------------+----------------------------------------------------------------------------+
- % | Type | PDE |
- % +---------------------+----------------------------------------------------------------------------+
- % | Number of Variables | arbitrary multiple of 3 |
- % +---------------------+----------------------------------------------------------------------------+
- % | Stiff | typically, depending on $\varepsilon$, $\sigma$, and number of grid points |
- % +---------------------+----------------------------------------------------------------------------+
+ % +---------------------+-------------------------------------------------------------+
+ % | Type | PDE |
+ % +---------------------+-------------------------------------------------------------+
+ % | Number of Variables | arbitrary multiple of 3 |
+ % +---------------------+-------------------------------------------------------------+
+ % | Stiff | typically, depending on $ε$, $σ$, and number of grid points |
+ % +---------------------+-------------------------------------------------------------+
%
% Example
% -------
@@ -44,7 +43,7 @@
end
properties (SetAccess = private)
- % Right-hand side containing the diffusion terms and the reaction terms multiplied by $\varepsilon^{-1}$.
+ % Right-hand side containing the diffusion terms and the reaction terms multiplied by $ε^{-1}$.
%
% This partition of the RHS is used in :cite:p:`JM17`.
%
@@ -53,7 +52,7 @@
% RHSNonstiff
RHSStiff
- % Right-hand side containing the reaction terms not scaled by $\varepsilon^{-1}$.
+ % Right-hand side containing the reaction terms not scaled by $ε^{-1}$.
%
% This partition of the RHS is used in :cite:p:`JM17`.
%
@@ -89,11 +88,7 @@
% The initial conditions.
% parameters : CUSPParameters
% The parameters.
- %
- % Returns
- % -------
- % obj : CUSPProblem
- % The constructed problem.
+
obj@otp.Problem('CUSP', [], timeSpan, y0, parameters);
end
end
diff --git a/toolbox/+otp/+lorenz63/+presets/Canonical.m b/toolbox/+otp/+lorenz63/+presets/Canonical.m
index 74ba5ba0..ca63c3e8 100644
--- a/toolbox/+otp/+lorenz63/+presets/Canonical.m
+++ b/toolbox/+otp/+lorenz63/+presets/Canonical.m
@@ -1,7 +1,6 @@
classdef Canonical < otp.lorenz63.Lorenz63Problem
- % Original Lorenz '63 preset presented in :cite:p:`Lor63`
- % which uses time span $t \in [0, 60]$, $\sigma = 10$, $\rho = 28$,
- % $\beta = 8/3$, and intial conditions $y_0 = [0, 1, 0]^T$.
+ % Original Lorenz '63 preset presented in :cite:p:`Lor63` which uses time span $t ∈ [0, 60]$, $σ = 10$, $ρ = 28$,
+ % $β = 8/3$, and intial conditions $y_0 = [0, 1, 0]^T$.
methods
function obj = Canonical(varargin)
@@ -12,31 +11,13 @@
% varargin
% A variable number of name-value pairs. The accepted names are
%
- % - ``sigma`` – Value of $\sigma$.
- % - ``rho`` – Value of $\rho$.
- % - ``beta`` – Value of $\beta$.
- %
- % Returns
- % -------
- % obj : Lorenz63Problem
- % The constructed problem.
-
- p = inputParser;
- p.addParameter('sigma', 10);
- p.addParameter('rho', 28);
- p.addParameter('beta', 8/3);
- p.parse(varargin{:});
- opts = p.Results;
-
- params = otp.lorenz63.Lorenz63Parameters;
-
- params.Sigma = opts.sigma;
- params.Rho = opts.rho;
- params.Beta = opts.beta;
+ % - ``Sigma`` – Value of $σ$.
+ % - ``Rho`` – Value of $ρ$.
+ % - ``Beta`` – Value of $β$.
y0 = [0; 1; 0];
tspan = [0 60];
-
+ params = otp.lorenz63.Lorenz63Parameters('Sigma', 10, 'Rho', 28, 'Beta', 8/3, varargin{:});
obj = obj@otp.lorenz63.Lorenz63Problem(tspan, y0, params);
end
end
diff --git a/toolbox/+otp/+lorenz63/+presets/LimitCycle.m b/toolbox/+otp/+lorenz63/+presets/LimitCycle.m
index 1453b675..9981ba47 100644
--- a/toolbox/+otp/+lorenz63/+presets/LimitCycle.m
+++ b/toolbox/+otp/+lorenz63/+presets/LimitCycle.m
@@ -1,25 +1,16 @@
classdef LimitCycle < otp.lorenz63.Lorenz63Problem
- % Lorenz '63 preset limit cycle, a non-chaotic preset, from :cite:p:`Str18`
- % which uses time span $t \in [0, 60]$, $\sigma = 10$, $\rho = 350$,
- % $\beta = 8/3$, and intial conditions $y_0 = [0, 1, 0]^T$.
+ % Lorenz '63 preset limit cycle, a non-chaotic preset, from :cite:p:`Str18` which uses time span $t ∈ [0, 60]$,
+ % $σ = 10$, $ρ = 350$, $β = 8/3$, and intial conditions $y_0 = [0, 1, 0]^T$.
methods
function obj = LimitCycle
- sigma = 10;
- rho = 350;
- beta = 8/3;
-
- params = otp.lorenz63.Lorenz63Parameters;
- params.Sigma = sigma;
- params.Rho = rho;
- params.Beta = beta;
+ % Create the LimitCycle Lorenz '63 problem object.
% We use Lorenz's initial conditions and timespan as Strogatz
% does not specify those in his book.
-
y0 = [0; 1; 0];
tspan = [0 60];
-
+ params = otp.lorenz63.Lorenz63Parameters('Sigma', 10, 'Rho', 350, 'Beta', 8/3);
obj = obj@otp.lorenz63.Lorenz63Problem(tspan, y0, params);
end
end
diff --git a/toolbox/+otp/+lorenz63/+presets/Surprise.m b/toolbox/+otp/+lorenz63/+presets/Surprise.m
index 27799f85..40236a0c 100644
--- a/toolbox/+otp/+lorenz63/+presets/Surprise.m
+++ b/toolbox/+otp/+lorenz63/+presets/Surprise.m
@@ -1,24 +1,15 @@
classdef Surprise < otp.lorenz63.Lorenz63Problem
- % Lorenz '63 preset 'surprise' from :cite:p:`Str18` which uses time span $t \in [0, 60]$,
- % $\sigma = 10$, $\rho = 100$, $\beta = 8/3$, and intial conditions $y_0 = [2, 1, 1]^T$.
+ % Lorenz '63 preset 'surprise' from :cite:p:`Str18` which uses time span $t ∈ [0, 60]$, $σ = 10$, $ρ = 100$,
+ % $β = 8/3$, and intial conditions $y_0 = [2, 1, 1]^T$.
methods
function obj = Surprise
-
- sigma = 10;
- rho = 100;
- beta = 8/3;
-
- params = otp.lorenz63.Lorenz63Parameters;
- params.Sigma = sigma;
- params.Rho = rho;
- params.Beta = beta;
+ % Create the Surprise Lorenz '63 problem object.
% Hand-picked initial conditions with the canonical timespan
-
y0 = [2; 1; 1];
tspan = [0 60];
-
+ params = otp.lorenz63.Lorenz63Parameters('Sigma', 10, 'Rho', 100, 'Beta', 8/3);
obj = obj@otp.lorenz63.Lorenz63Problem(tspan, y0, params);
end
end
diff --git a/toolbox/+otp/+lorenz63/Lorenz63Parameters.m b/toolbox/+otp/+lorenz63/Lorenz63Parameters.m
index 919869ec..9f4a8aa6 100644
--- a/toolbox/+otp/+lorenz63/Lorenz63Parameters.m
+++ b/toolbox/+otp/+lorenz63/Lorenz63Parameters.m
@@ -1,4 +1,4 @@
-classdef Lorenz63Parameters
+classdef Lorenz63Parameters < otp.Parameters
% Parameters for the Lorenz '63 problem.
properties
@@ -11,4 +11,18 @@
% A geometric factor.
Beta %MATLAB ONLY: (1, 1) {mustBeReal, mustBeFinite}
end
+
+ methods
+ function obj = Lorenz63Parameters(varargin)
+ % Create a Lorenz '63 parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
+ % value initializes that property.
+
+ obj = obj@otp.Parameters(varargin{:});
+ end
+ end
end
diff --git a/toolbox/+otp/+lorenz63/Lorenz63Problem.m b/toolbox/+otp/+lorenz63/Lorenz63Problem.m
index a60dace1..ebcf8b28 100644
--- a/toolbox/+otp/+lorenz63/Lorenz63Problem.m
+++ b/toolbox/+otp/+lorenz63/Lorenz63Problem.m
@@ -4,27 +4,24 @@
% The three variable Lorenz '63 problem :cite:p:`Lor63` of the form,
%
% $$
- % x' &= \sigma(y - x),\\
- % y' &= \rho x - y - xz,\\
- % z' &= xy - \beta z,
+ % x' &= σ(y - x),\\
+ % y' &= ρx - y - xz,\\
+ % z' &= xy - βz,
% $$
%
- % exhibits chaotic behavior for certain values of the parameters.
- % Here $x$ roughly corresponds to the rate of convection of a fluid,
- % $y$ corresponds to temperature variation in one direction,
- % and $z$ is temerature variation in the other direction.
- %
- % For a full problem description see :cite:p:`Str18`.
+ % exhibits chaotic behavior for certain values of the parameters. Here $x$ roughly corresponds to the rate of
+ % convection of a fluid, $y$ corresponds to temperature variation in one direction, and $z$ is temerature variation
+ % in the other direction. For a full problem description see :cite:p:`Str18`.
%
% Notes
% -----
- % +---------------------+-----------------------------------------------------------+
- % | Type | ODE |
- % +---------------------+-----------------------------------------------------------+
- % | Number of Variables | 3 |
- % +---------------------+-----------------------------------------------------------+
- % | Stiff | not typically, depending on $\sigma$, $\rho$, and $\beta$ |
- % +---------------------+-----------------------------------------------------------+
+ % +---------------------+-----------------------------------------------+
+ % | Type | ODE |
+ % +---------------------+-----------------------------------------------+
+ % | Number of Variables | 3 |
+ % +---------------------+-----------------------------------------------+
+ % | Stiff | not typically, depending on $σ$, $ρ$, and $β$ |
+ % +---------------------+-----------------------------------------------+
%
% Example
% -------
@@ -32,9 +29,9 @@
% >>> sol = problem.solve('MaxStep', 1e-3);
% >>> problem.plotPhaseSpace(sol);
%
- % See also
+ % See Also
% --------
- % :doc:`Lorenz '96 Problem `
+ % otp.lorenz96.Lorenz96Problem
methods
function obj = Lorenz63Problem(timeSpan, y0, parameters)
@@ -48,11 +45,7 @@
% The initial conditions.
% parameters : Lorenz63Parameters
% The parameters.
- %
- % Returns
- % -------
- % obj : Lorenz63Problem
- % The constructed problem.
+
obj@otp.Problem('Lorenz Equations', 3, timeSpan, y0, parameters);
end
end
@@ -64,12 +57,16 @@ function onSettingsChanged(obj)
beta = obj.Parameters.Beta;
obj.RHS = otp.RHS(@(t, y) otp.lorenz63.f(t, y, sigma, rho, beta), ...
- 'Jacobian', @(t, y) otp.lorenz63.jacobian(t, y, sigma, rho, beta), ...
- 'JacobianVectorProduct', @(t, y, v) otp.lorenz63.jacobianVectorProduct(t, y, v, sigma, rho, beta), ...
- 'JacobianAdjointVectorProduct', @(t, y, v) otp.lorenz63.jacobianAdjointVectorProduct(t, y, v, sigma, rho, beta), ...
- 'PartialDerivativeParameters', @(t, y) otp.lorenz63.partialDerivativeParameters(t, y, sigma, rho, beta), ...
- 'HessianVectorProduct', @(t, y, u, v) otp.lorenz63.hessianVectorProduct(t, y, u, v, sigma, rho, beta), ...
- 'HessianAdjointVectorProduct', @(t, y, u, v) otp.lorenz63.hessianAdjointVectorProduct(t, y, u, v, sigma, rho, beta), ...
+ 'Jacobian', @(t, y) otp.lorenz63.jacobian(t, y, sigma, rho, beta), ...
+ 'JacobianVectorProduct', @(t, y, v) otp.lorenz63.jacobianVectorProduct(t, y, v, sigma, rho, beta), ...
+ 'JacobianAdjointVectorProduct', ...
+ @(t, y, v) otp.lorenz63.jacobianAdjointVectorProduct(t, y, v, sigma, rho, beta), ...
+ 'PartialDerivativeParameters', ...
+ @(t, y) otp.lorenz63.partialDerivativeParameters(t, y, sigma, rho, beta), ...
+ 'HessianVectorProduct', ...
+ @(t, y, u, v) otp.lorenz63.hessianVectorProduct(t, y, u, v, sigma, rho, beta), ...
+ 'HessianAdjointVectorProduct', ...
+ @(t, y, u, v) otp.lorenz63.hessianAdjointVectorProduct(t, y, u, v, sigma, rho, beta), ...
'Vectorized', 'on');
end
diff --git a/toolbox/+otp/+lorenz96/+presets/Canonical.m b/toolbox/+otp/+lorenz96/+presets/Canonical.m
index 38c0b0fc..d1094e36 100644
--- a/toolbox/+otp/+lorenz96/+presets/Canonical.m
+++ b/toolbox/+otp/+lorenz96/+presets/Canonical.m
@@ -1,37 +1,35 @@
classdef Canonical < otp.lorenz96.Lorenz96Problem
- %CANONICAL This is the original problem presented in the literature.
- % The initial condition is a slight perturbation of a critical point.
- %
- % See:
- % Lorenz, E. N. (1996, September). Predictability: A problem partly solved.
- % In Proc. Seminar on predictability (Vol. 1, No. 1).
+ % Original Lorenz '96 preset presented in :cite:p:`Lor96` which uses time span $t ∈ [0, 720]$, $N = 40$, $F=8$, and
+ % initial conditions of $y_i = 8$ for all $i$ except for $y_{⌊N/2⌋}=8.008$.
+
methods
function obj = Canonical(varargin)
+ % Create the Canonical Lorenz '96 problem object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. The accepted names are
+ %
+ % - ``N`` – The size of the problem as a positive integer.
+ % - ``Forcing`` – The forcing as a scalar, vector of N constants, or as a function.
p = inputParser;
- p.addParameter('Size', 40, @isscalar);
- p.addParameter('Forcing', 8);
-
+ p.addParameter('N', 40);
p.parse(varargin{:});
-
- s = p.Results;
-
- n = s.Size;
-
- params = otp.lorenz96.Lorenz96Parameters;
- params.F = s.Forcing;
+ n = p.Results.N;
% We initialise the Lorenz96 model as in (Lorenz & Emanuel 1998)
-
y0 = 8*ones(n, 1);
-
y0(floor(n/2)) = 8.008;
% roughly ten years in system time
tspan = [0, 720];
+
+ unmatched = namedargs2cell(p.Unmatched);
+ params = otp.lorenz96.Lorenz96Parameters('F', 8, unmatched{:});
obj = obj@otp.lorenz96.Lorenz96Problem(tspan, y0, params);
-
end
end
end
diff --git a/toolbox/+otp/+lorenz96/+presets/PopovSandu.m b/toolbox/+otp/+lorenz96/+presets/PopovSandu.m
index f04fdada..b1beb936 100644
--- a/toolbox/+otp/+lorenz96/+presets/PopovSandu.m
+++ b/toolbox/+otp/+lorenz96/+presets/PopovSandu.m
@@ -1,39 +1,47 @@
classdef PopovSandu < otp.lorenz96.Lorenz96Problem
- %POPOVSANDU
- % Used in https://doi.org/10.5194/npg-26-109-2019
+ % A preset that has a cyclic forcing function that is different for every variable. This preset was created for
+ % :cite:p:`PS19`. This preset uses time span $t ∈ [0, 720]$, $N = 40$, and initial conditions of $y_i = 8$ for all
+ % $i$ except for $y_{⌊N/2⌋}=8.008$. The forcing as a function of time is given by
+ %
+ % $$
+ % f(t) = 8 + 4\cos(2 π ω (t+\text{mod}(i - 1, q)/q))
+ % $$
+ %
+ % where by default $q=4$ is the number of partitions, and $ω = 1$ is a forcing period of one time unit.
methods
function obj = PopovSandu(varargin)
+ % Create the PopovSandu Lorenz '96 problem object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. The accepted names are
+ %
+ % - ``N`` – The size of the problem as a positive integer.
+ % - ``Partitions`` – The number of partitions into which to divide the variables.
+ % - ``ForcingPeriod`` – The period of the forcing function in radians per unit time.
p = inputParser;
-
- p.addParameter('Size', 40, @isscalar);
- p.addParameter('Partitions', 4, @isscalar);
- p.addParameter('ForcingPeriod', 1, @isscalar); % default corresponds to 5 days
-
+ p.addParameter('N', 40);
+ p.addParameter('Partitions', 4);
+ p.addParameter('ForcingPeriod', 1); % default corresponds to 5 days
p.parse(varargin{:});
- s = p.Results;
-
- n = s.Size;
- q = s.Partitions;
- omega = s.ForcingPeriod;
-
- F = @(t) 8 + 4*cos(2*pi*omega*(t + mod((1:n) - 1, q)/q)).';
+ n = p.Results.N;
+ q = p.Results.Partitions;
+ omega = p.Results.ForcingPeriod;
- params = otp.lorenz96.Lorenz96Parameters;
- params.F = F;
+ params = otp.lorenz96.Lorenz96Parameters('F', @(t) 8 + 4*cos(2*pi*omega*(t + mod((1:n) - 1, q)/q)).');
% We initialise the Lorenz96 model as in (Lorenz & Emanuel 1998)
y0 = 8*ones(n, 1);
-
y0(floor(n/2)) = 8.008;
tspan = [0, 720]; % 3600 days
obj = obj@otp.lorenz96.Lorenz96Problem(tspan, y0, params);
-
end
end
end
diff --git a/toolbox/+otp/+lorenz96/Lorenz96Parameters.m b/toolbox/+otp/+lorenz96/Lorenz96Parameters.m
index c1e94338..4995b71c 100644
--- a/toolbox/+otp/+lorenz96/Lorenz96Parameters.m
+++ b/toolbox/+otp/+lorenz96/Lorenz96Parameters.m
@@ -1,10 +1,22 @@
-classdef Lorenz96Parameters
- %LORENZ96PARAMETERS User-configurable parameters for the Lorenz 96 problem
- %
- % See also otp.lorenz96.Lorenz96Problem
+classdef Lorenz96Parameters < otp.Parameters
+ % Parameters for the Lorenz '96 problem.
properties
- %F is a forcing function, scalar, or vector
+ % A forcing function, scalar, or vector.
F %MATLAB ONLY: {mustBeA(F, {'numeric','function_handle'})}
end
+
+ methods
+ function obj = Lorenz96Parameters(varargin)
+ % Create a Lorenz '96 parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
+ % value initializes that property.
+
+ obj = obj@otp.Parameters(varargin{:});
+ end
+ end
end
diff --git a/toolbox/+otp/+lorenz96/Lorenz96Problem.m b/toolbox/+otp/+lorenz96/Lorenz96Problem.m
index b8e26883..694c96db 100644
--- a/toolbox/+otp/+lorenz96/Lorenz96Problem.m
+++ b/toolbox/+otp/+lorenz96/Lorenz96Problem.m
@@ -1,7 +1,34 @@
classdef Lorenz96Problem < otp.Problem
- %LORENZ96PROBLEM The Lorenz 96 model is a classic model for testing data assimilation techniques.
+ % A chaotic system modeling nonlinear transfer of a dimensionless quantity along a cyclic one dimensional domain.
%
- % See also otp.loren96.Lorenz96Parameters
+ % The $N$ variable dynamics :cite:p:`Lor96` are represented by the equation,
+ %
+ % $$
+ % y_i' = -y_{i-1} (y_{i-2} - y_{i+1}) - y_i + f(t), \qquad i = 1, …, N,
+ % $$
+ %
+ % where $y_0 = y_N$, $y_{-1} = y_{N - 1}$, and $y_{N + 1} = y_2$, exhibits chaotic behavior for certain pairs of
+ % values of the dimension $N$ and forcing function $f$.
+ %
+ % Notes
+ % -----
+ % +---------------------+---------------------------------------------+
+ % | Type | ODE |
+ % +---------------------+---------------------------------------------+
+ % | Number of Variables | $N$ for any postive integer four or greater |
+ % +---------------------+---------------------------------------------+
+ % | Stiff | no |
+ % +---------------------+---------------------------------------------+
+ %
+ % Example
+ % -------
+ % >>> problem = otp.lorenz96.presets.Canonical('Forcing', @(t) 8 + 4*sin(t));
+ % >>> sol = problem.solve();
+ % >>> problem.movie(sol);
+ %
+ % See Also
+ % --------
+ % otp.lorenz63.Lorenz63Problem
properties (SetAccess = private)
DistanceFunction
@@ -9,6 +36,17 @@
methods
function obj = Lorenz96Problem(timeSpan, y0, parameters)
+ % Create a Lorenz '96 problem object.
+ %
+ % Parameters
+ % ----------
+ % timeSpan : numeric(1, 2)
+ % The start and final time.
+ % y0 : numeric(:, 1)
+ % The initial conditions.
+ % parameters : Lorenz96Parameters
+ % The parameters.
+
obj@otp.Problem('Lorenz 96', [], timeSpan, y0, parameters);
end
end
@@ -37,7 +75,7 @@
'Vectorized', 'on');
% We also provide a canonical distance function as is standard for
- % localisation in Data Assimilation. This is heavily tied to this
+ % localization in Data Assimilation. This is heavily tied to this
% problem.
obj.DistanceFunction = @(t, y, i, j) otp.lorenz96.distanceFunction(t, y, i, j);
diff --git a/toolbox/+otp/+oregonator/+presets/Canonical.m b/toolbox/+otp/+oregonator/+presets/Canonical.m
index fa6bd123..fbbb273e 100644
--- a/toolbox/+otp/+oregonator/+presets/Canonical.m
+++ b/toolbox/+otp/+oregonator/+presets/Canonical.m
@@ -1,10 +1,31 @@
classdef Canonical < otp.oregonator.OregonatorProblem
+ % The Oregonator configuration used in :cite:p:`HW96` (p. 144) called OREGO. It uses time span $t ∈ [0, 360]$,
+ % initial condition $y_0 = [1, 2, 3]^T$, and parameters
+ %
+ % $$
+ % f &= 1, \\
+ % q &= 8.375 \times 10^{-6}, \\
+ % s &= 77.27, \\
+ % w &= 0.1610.
+ % $$
+
methods
- function obj = Canonical
+ function obj = Canonical(varargin)
+ % Create the Canonical Oregonator problem object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. The accepted names are
+ %
+ % - ``f`` – Value of $f$.
+ % - ``q`` – Value of $q$.
+ % - ``s`` – Value of $s$.
+ % - ``w`` – Value of $w$.
+
tspan = [0, 360];
y0 = [1; 2; 3];
- params = otp.oregonator.OregonatorParameters;
-
+ params = otp.oregonator.OregonatorParameters('F', 1, 'Q', 8.375e-6, 'S', 77.27, 'W', 0.1610, varargin{:});
obj = obj@otp.oregonator.OregonatorProblem(tspan, y0, params);
end
end
diff --git a/toolbox/+otp/+oregonator/+presets/EnrightHull.m b/toolbox/+otp/+oregonator/+presets/EnrightHull.m
new file mode 100644
index 00000000..c8a4cdde
--- /dev/null
+++ b/toolbox/+otp/+oregonator/+presets/EnrightHull.m
@@ -0,0 +1,23 @@
+classdef EnrightHull < otp.oregonator.OregonatorProblem
+ % The Oregonator configuration used in problem CHM 9 of :cite:p:`EH76`. It uses time span $t ∈ [0, 300]$, initial
+ % condition $y_0 = [4, 1.1, 4]^T$, and parameters
+ %
+ % $$
+ % f &= 1, \\
+ % q &= 8.375 \times 10^{-6}, \\
+ % s &= 77.27, \\
+ % w &= 0.1610.
+ % $$
+
+ methods
+ function obj = EnrightHull
+ % Create the EnrightHull Oregonator problem object.
+
+ tspan = [0, 300];
+ y0 = [4; 1.1; 4];
+ params = otp.oregonator.OregonatorParameters('F', 1, 'Q', 8.375e-6, 'S', 77.27, 'W', 0.1610);
+
+ obj = obj@otp.oregonator.OregonatorProblem(tspan, y0, params);
+ end
+ end
+end
\ No newline at end of file
diff --git a/toolbox/+otp/+oregonator/+presets/GottwaldWanner.m b/toolbox/+otp/+oregonator/+presets/GottwaldWanner.m
new file mode 100644
index 00000000..7bee036c
--- /dev/null
+++ b/toolbox/+otp/+oregonator/+presets/GottwaldWanner.m
@@ -0,0 +1,25 @@
+classdef GottwaldWanner < otp.oregonator.OregonatorProblem
+ % The Oregonator configuration from :cite:p:`GW82` which uses time span $t ∈ [0, 302.85805]$, initial condition
+ % $y_0 = [4, 1.331391, 2.852348]^T$, and parameters
+ %
+ % $$
+ % f &= 1, \\
+ % q &= 8.375 \times 10^{-6}, \\
+ % s &= 77.27, \\
+ % w &= 0.1610.
+ % $$
+ %
+ % The initial condition lies on a stable limit cycle, and the time span is chosen to be one period.
+
+ methods
+ function obj = GottwaldWanner
+ % Create the GottwaldWanner Oregonator problem object.
+
+ tspan = [0, 302.85805];
+ y0 = [4; 1.331391; 2.852348];
+ params = otp.oregonator.OregonatorParameters('F', 1, 'Q', 8.375e-6, 'S', 77.27, 'W', 0.1610);
+
+ obj = obj@otp.oregonator.OregonatorProblem(tspan, y0, params);
+ end
+ end
+end
\ No newline at end of file
diff --git a/toolbox/+otp/+oregonator/OregonatorParameters.m b/toolbox/+otp/+oregonator/OregonatorParameters.m
index 87ba9d5d..d5014b50 100644
--- a/toolbox/+otp/+oregonator/OregonatorParameters.m
+++ b/toolbox/+otp/+oregonator/OregonatorParameters.m
@@ -1,4 +1,31 @@
-classdef OregonatorParameters
- %OREGONATORPARAMETERS
+classdef OregonatorParameters < otp.Parameters
+ % Parameters for the Oregonator problem.
+ properties
+ % The stoichiometric factor $f$.
+ F %MATLAB ONLY: (1, 1) {mustBeReal, mustBeFinite}
+
+ % The reaction constant $q$.
+ Q %MATLAB ONLY: (1, 1) {mustBeReal, mustBeFinite}
+
+ % The reaction constant $s$.
+ S %MATLAB ONLY: (1, 1) {mustBeReal, mustBeFinite}
+
+ % The reaction constant $w$.
+ W %MATLAB ONLY: (1, 1) {mustBeReal, mustBeFinite}
+ end
+
+ methods
+ function obj = OregonatorParameters(varargin)
+ % Create a Oregonator parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
+ % value initializes that property.
+
+ obj = obj@otp.Parameters(varargin{:});
+ end
+ end
end
diff --git a/toolbox/+otp/+oregonator/OregonatorProblem.m b/toolbox/+otp/+oregonator/OregonatorProblem.m
index 7126f048..e2a6e49d 100644
--- a/toolbox/+otp/+oregonator/OregonatorProblem.m
+++ b/toolbox/+otp/+oregonator/OregonatorProblem.m
@@ -1,25 +1,88 @@
classdef OregonatorProblem < otp.Problem
+ % A periodic, three-variable model for the Belousov–Zhabotinsky reaction.
+ %
+ % The Oregonator chemical reaction :cite:p:`FN74` is given by
+ %
+ %
+ % $$
+ % \ce{
+ % A + Y &-> X + P \\
+ % X + Y &-> 2P \\
+ % A + X &-> 2X + 2Z \\
+ % 2X &-> A + P \\
+ % B + Z &-> 1/2 $f$ Y.
+ % }
+ % $$
+ %
+ % Species $\ce{A = BrO3-}$, $\ce{B = CH2(COOH)2}$, and $\ce{P = HOBr}$ or $\ce{BrCH(COOH)2}$ are assumed to be
+ % constant. The dynamic concentrations of intermediate species $\ce{X = HBrO2}$, $\ce{Y = Br-}$, and
+ % $\ce{Z = Ce(IV)}$ can be modeled by an ODE in three variables. Field and Noyes :cite:p:`FN74` proposed the
+ % nondimensionalized form
+ %
+ % $$
+ % α' &= s(η - η α + α - q α^2), \\
+ % η' &= s^{-1}(-η - η α + f ρ), \\
+ % ρ' &= w (α - ρ),
+ % $$
+ %
+ % where $α$, $η$, and $ρ$ are scaled concentrations of $\ce{X}$, $\ce{Y}$, and $\ce{Z}$, respectively.
+ %
+ % Notes
+ % -----
+ % +---------------------+------------------------------------------------+
+ % | Type | ODE |
+ % +---------------------+------------------------------------------------+
+ % | Number of Variables | 3 |
+ % +---------------------+------------------------------------------------+
+ % | Stiff | typically, depending on $f$, $q$, $s$, and $w$ |
+ % +---------------------+------------------------------------------------+
+ %
+ % Example
+ % -------
+ % >>> problem = otp.oregonator.presets.Canonical;
+ % >>> sol = problem.solve();
+ % >>> problem.plotPhaseSpace(sol, 'Vars', [2, 3]);
+
methods
function obj = OregonatorProblem(timeSpan, y0, parameters)
+ % Create a Oregonator problem object.
+ %
+ % Parameters
+ % ----------
+ % timeSpan : numeric(1, 2)
+ % The start and final time.
+ % y0 : numeric(3, 1)
+ % The initial conditions.
+ % parameters : OregonatorParameters
+ % The parameters.
+
obj@otp.Problem('Oregonator', 3, timeSpan, y0, parameters);
end
end
methods (Access = protected)
function onSettingsChanged(obj)
- obj.RHS = otp.RHS(@otp.oregonator.f, ...
- 'Jacobian', @otp.oregonator.jacobian, ...
+ f = obj.Parameters.F;
+ q = obj.Parameters.Q;
+ s = obj.Parameters.S;
+ w = obj.Parameters.W;
+
+ obj.RHS = otp.RHS(@(t, y) otp.oregonator.f(t, y, f, q, s, w), ...
+ 'Jacobian', @(t, y) otp.oregonator.jacobian(t, y, f, q, s, w), ...
'Vectorized', 'on');
end
function fig = internalPlot(obj, t, y, varargin)
- fig = internalPlot@otp.Problem(obj, t, y, ...
- 'yscale', 'log', varargin{:});
+ fig = internalPlot@otp.Problem(obj, t, y, 'yscale', 'log', varargin{:});
+ end
+
+ function fig = internalPlotPhaseSpace(obj, t, y, varargin)
+ fig = internalPlotPhaseSpace@otp.Problem(obj, t, y, 'xscale', 'log', 'yscale', 'log', 'zscale', 'log', ...
+ varargin{:});
end
function mov = internalMovie(obj, t, y, varargin)
- mov = internalMovie@otp.Problem(obj, t, y, ...
- 'yscale', 'log', varargin{:});
+ mov = internalMovie@otp.Problem(obj, t, y, 'yscale', 'log', varargin{:});
end
end
end
diff --git a/toolbox/+otp/+oregonator/f.m b/toolbox/+otp/+oregonator/f.m
index 98b7a787..ebc53002 100644
--- a/toolbox/+otp/+oregonator/f.m
+++ b/toolbox/+otp/+oregonator/f.m
@@ -1,12 +1,12 @@
-function dy = f(~, y)
+function dy = f(~, y, f, q, s, w)
y1 = y(1, :);
y2 = y(2, :);
y3 = y(3, :);
dy = [ ...
- 77.27 * (y2 + y1 .* (1 - 8.375e-6 * y1 - y2)); ...
- (y3 - (1 + y1) .* y2) / 77.27; ...
- 0.161 * (y1 - y3)];
+ s * (y2 + y1 .* (1 - q * y1 - y2)); ...
+ (f * y3 - (1 + y1) .* y2) / s; ...
+ w * (y1 - y3)];
end
diff --git a/toolbox/+otp/+oregonator/jacobian.m b/toolbox/+otp/+oregonator/jacobian.m
index ea9f3fc4..ad3992df 100644
--- a/toolbox/+otp/+oregonator/jacobian.m
+++ b/toolbox/+otp/+oregonator/jacobian.m
@@ -1,11 +1,11 @@
-function J = jacobian(~, y)
+function J = jacobian(~, y, f, q, s, w)
y1 = y(1);
y2 = y(2);
J = [ ...
- 77.27 * (1 - y2 - 1.675e-5 * y1), 77.27 * (1 - y1), 0; ...
- -y2 / 77.27, -(1 + y1) / 77.27, 1 / 77.27; ...
- 0.161, 0, -0.161];
+ s * (1 - 2 * q * y1 - y2), s * (1 - y1), 0; ...
+ -y2 / s, -(1 + y1) / s, f / s; ...
+ w, 0, -w];
end
diff --git a/toolbox/+otp/+protherorobinson/+presets/Canonical.m b/toolbox/+otp/+protherorobinson/+presets/Canonical.m
index ede364da..0171bc71 100644
--- a/toolbox/+otp/+protherorobinson/+presets/Canonical.m
+++ b/toolbox/+otp/+protherorobinson/+presets/Canonical.m
@@ -1,47 +1,30 @@
classdef Canonical < otp.protherorobinson.ProtheroRobinsonProblem
% The Prothero–Robinson configuration from :cite:p:`PR74` (p. 159) based on :cite:p:`SLH70` (p. 272). It uses time
- % span $t \in [0, 15]$, initial condition $y(0) = \phi(0)$, and parameters
+ % span $t ∈ [0, 15]$, initial condition $y(0) = φ(0)$, and parameters
%
% $$
- % \lambda &= -200, \\
- % \phi(t) &= 10 - (10 + t) e^{-t}.
+ % λ &= -200, \\
+ % φ(t) &= 10 - (10 + t) e^{-t}.
% $$
methods
- function obj = Canonical(lambda, phi, dphi)
+ function obj = Canonical(varargin)
% Create the Canonical Prothero–Robinson problem object.
%
% Parameters
% ----------
- %
- % lambda : numeric(1, 1), default=-200
- % The stiffness parameter and eigenvalue of the Jacobian $\lambda$.
- % phi : function_handle, default=@(t)10-(10+t).*exp(-t)
- % The exact solution.
- % dphi : function_handle, default=@(t)(9+t).*exp(-t)
- % The time derivative of $\phi(t)$.
+ % varargin
+ % A variable number of name-value pairs. The accepted names are
%
- % Returns
- % -------
- % obj : ProtheroRobinsonProblem
- % The constructed problem
- if nargin < 1 || isempty(lambda)
- lambda = -200;
- end
- if nargin < 2 || isempty(phi)
- phi = @(t) 10 - (10 + t) .* exp(-t);
- dphi = @(t) (9 + t) .* exp(-t);
- end
+ % - ``Lambda`` – The stiffness parameter and eigenvalue of the Jacobian $λ$.
+ % - ``Phi`` – The exact solution.
+ % - ``DPhi`` – The time derivative of $φ(t)$.
- params = otp.protherorobinson.ProtheroRobinsonParameters;
- params.Lambda = lambda;
- params.Phi = phi;
- params.DPhi = dphi;
+ params = otp.protherorobinson.ProtheroRobinsonParameters('Lambda', -200, ...
+ 'Phi', @(t) 10 - (10 + t) .* exp(-t), 'DPhi', @(t) (9 + t) .* exp(-t), varargin{:});
tspan = [0, 15];
- y0 = phi(tspan(1));
-
+ y0 = params.Phi(tspan(1));
obj = obj@otp.protherorobinson.ProtheroRobinsonProblem(tspan, y0, params);
end
-
end
end
\ No newline at end of file
diff --git a/toolbox/+otp/+protherorobinson/ProtheroRobinsonParameters.m b/toolbox/+otp/+protherorobinson/ProtheroRobinsonParameters.m
index 02c61931..25756a70 100644
--- a/toolbox/+otp/+protherorobinson/ProtheroRobinsonParameters.m
+++ b/toolbox/+otp/+protherorobinson/ProtheroRobinsonParameters.m
@@ -1,13 +1,27 @@
-classdef ProtheroRobinsonParameters
+classdef ProtheroRobinsonParameters < otp.Parameters
% Parameters for the Prothero–Robinson problem.
properties
- % The stiffness parameter and eigenvalue of the Jacobian $\lambda$.
+ % The stiffness parameter and eigenvalue of the Jacobian $λ$.
Lambda %MATLAB ONLY: (1,1) {mustBeFinite} = -1
- % The function $\phi(t)$.
+ % The function $φ(t)$.
Phi %MATLAB ONLY: {mustBeA(Phi, 'function_handle')} = @sin
- % The time derivative of $\phi(t)$.
+ % The time derivative of $φ(t)$.
DPhi %MATLAB ONLY: {mustBeA(DPhi, 'function_handle')} = @cos
end
+
+ methods
+ function obj = ProtheroRobinsonParameters(varargin)
+ % Create a Prothero–Robinson parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
+ % value initializes that property.
+
+ obj = obj@otp.Parameters(varargin{:});
+ end
+ end
end
diff --git a/toolbox/+otp/+protherorobinson/ProtheroRobinsonProblem.m b/toolbox/+otp/+protherorobinson/ProtheroRobinsonProblem.m
index 22db1b5f..298445e0 100644
--- a/toolbox/+otp/+protherorobinson/ProtheroRobinsonProblem.m
+++ b/toolbox/+otp/+protherorobinson/ProtheroRobinsonProblem.m
@@ -3,21 +3,21 @@
%
% The Prothero–Robinson problem :cite:p:`PR74` is the linear ODE
%
- % $$y' = \lambda (y - \phi(t)) + \phi'(t).$$
+ % $$y' = λ (y - φ(t)) + φ'(t).$$
%
% This simple problem is used to test for order reduction and S-stability of time-stepping schemes. With initial
- % condition $y(t_0) = \phi(t_0)$, the exact solution is $y(t) = \phi(t)$ independent of $\lambda$. Therefore, any
+ % condition $y(t_0) = φ(t_0)$, the exact solution is $y(t) = φ(t)$ independent of $λ$. Therefore, any
% errors introduced by the numerical scheme can be measured easily.
%
% Notes
% -----
- % +---------------------+-----------------------------------+
- % | Type | ODE |
- % +---------------------+-----------------------------------+
- % | Number of Variables | 1 |
- % +---------------------+-----------------------------------+
- % | Stiff | typically, depending on $\lambda$ |
- % +---------------------+-----------------------------------+
+ % +---------------------+-----------------------------+
+ % | Type | ODE |
+ % +---------------------+-----------------------------+
+ % | Number of Variables | 1 |
+ % +---------------------+-----------------------------+
+ % | Stiff | typically, depending on $λ$ |
+ % +---------------------+-----------------------------+
%
% Example
% -------
@@ -37,11 +37,7 @@
% The initial conditions.
% parameters : ProtheroRobinsonParameters
% The parameters.
- %
- % Returns
- % -------
- % obj : ProtheroRobinsonProblem
- % The constructed problem.
+
obj@otp.Problem('Prothero–Robinson', [], timeSpan, y0, parameters);
end
end
diff --git a/toolbox/+otp/+robertson/+presets/Canonical.m b/toolbox/+otp/+robertson/+presets/Canonical.m
index bf921bc9..fbc97da5 100644
--- a/toolbox/+otp/+robertson/+presets/Canonical.m
+++ b/toolbox/+otp/+robertson/+presets/Canonical.m
@@ -1,33 +1,29 @@
classdef Canonical < otp.robertson.RobertsonProblem
- % The original configuration :cite:p:`Rob67` with $t \in [0, 40]$, $y_0 = [1, 0, 0]^T$, and parameters
+ % The original configuration :cite:p:`Rob66` with $t ∈ [0, 40]$, $y_0 = [1, 0, 0]^T$, and parameters
%
% $$
- % K_1 &= 4\times 10^{-2}, \\
- % K_2 &= 3\times 10^7, \\
- % K_3 &= 10^4.
+ % k_1 &= 4 \times 10^{-2}, \\
+ % k_2 &= 3 \times 10^7, \\
+ % k_3 &= 10^4.
% $$
+
methods
- function obj = Canonical
+ function obj = Canonical(varargin)
% Create the Canonical Robertson problem object.
%
% Parameters
% ----------
+ % varargin
+ % A variable number of name-value pairs. The accepted names are
%
- % Returns
- % -------
- % obj : RobertsonProblem
- % The constructed problem.
-
- params = otp.robertson.RobertsonParameters;
- params.K1 = 0.04;
- params.K2 = 3e7;
- params.K3 = 1e4;
+ % - ``K1`` – Value of $k_1$.
+ % - ``K2`` – Value of $k_2$.
+ % - ``K3`` – Value of $k_3$.
y0 = [1; 0; 0];
tspan = [0, 40];
-
+ params = otp.robertson.RobertsonParameters('K1', 0.04, 'K2', 3e7, 'K3', 1e4, varargin{:});
obj = obj@otp.robertson.RobertsonProblem(tspan, y0, params);
end
-
end
end
diff --git a/toolbox/+otp/+robertson/+presets/ROBER.m b/toolbox/+otp/+robertson/+presets/ROBER.m
index 291da496..a77d054a 100644
--- a/toolbox/+otp/+robertson/+presets/ROBER.m
+++ b/toolbox/+otp/+robertson/+presets/ROBER.m
@@ -2,28 +2,15 @@
% The Robertson configuration from :cite:p:`HW96` (p. 144). This differs from :class:`Canonical` only in the time
% span which is extended to $[0, 10^{11}]$. This presents a challenge for numerical integrators to preserve solution
% positivity.
+
methods
function obj = ROBER
% Create the ROBER Robertson problem object.
- %
- % Parameters
- % ----------
- %
- % Returns
- % -------
- % obj : RobertsonProblem
- % The constructed problem.
-
- params = otp.robertson.RobertsonParameters;
- params.K1 = 0.04;
- params.K2 = 3e7;
- params.K3 = 1e4;
y0 = [1; 0; 0];
- tspan = [0; 1e11];
-
+ tspan = [0, 1e11];
+ params = otp.robertson.RobertsonParameters('K1', 0.04, 'K2', 3e7, 'K3', 1e4);
obj = obj@otp.robertson.RobertsonProblem(tspan, y0, params);
end
-
end
end
diff --git a/toolbox/+otp/+robertson/RobertsonParameters.m b/toolbox/+otp/+robertson/RobertsonParameters.m
index a98905ef..6ed8e2cc 100644
--- a/toolbox/+otp/+robertson/RobertsonParameters.m
+++ b/toolbox/+otp/+robertson/RobertsonParameters.m
@@ -1,11 +1,25 @@
-classdef RobertsonParameters
+classdef RobertsonParameters < otp.Parameters
% Parameters for the Robertson problem.
properties
- % The reaction rate $K_1$.
+ % The reaction rate $k_1$.
K1 %MATLAB ONLY: (1, 1) {mustBeReal, mustBeNonnegative}
- % The reaction rate $K_2$.
+ % The reaction rate $k_2$.
K2 %MATLAB ONLY: (1, 1) {mustBeReal, mustBeNonnegative}
- % The reaction rate $K_3$.
+ % The reaction rate $k_3$.
K3 %MATLAB ONLY: (1, 1) {mustBeReal, mustBeNonnegative}
end
+
+ methods
+ function obj = RobertsonParameters(varargin)
+ % Create a Robertson parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
+ % value initializes that property.
+
+ obj = obj@otp.Parameters(varargin{:});
+ end
+ end
end
diff --git a/toolbox/+otp/+robertson/RobertsonProblem.m b/toolbox/+otp/+robertson/RobertsonProblem.m
index 64a7e186..8564a297 100644
--- a/toolbox/+otp/+robertson/RobertsonProblem.m
+++ b/toolbox/+otp/+robertson/RobertsonProblem.m
@@ -1,28 +1,27 @@
classdef RobertsonProblem < otp.Problem
% A simple, stiff chemical reaction.
%
- % The Robertson problem :cite:p:`Rob67` is a simple, stiff chemical reaction that
- % models the concentrations of chemical species $A$, $B$, and $C$
- % involved in the reactions
+ % The Robertson problem :cite:p:`Rob66` is a simple, stiff chemical reaction that models the concentrations of
+ % chemical species $\ce{A}$, $\ce{B}$, and $\ce{C}$ involved in the reactions
+ %
% $$
- % \begin{align*}
- % &A \rightarrow B &~~\text{at rate}~~ &K_1, \\
- % &B + B \rightarrow C + B &~~\text{at rate}~~ &K_2, \\
- % &B + C \rightarrow A + C &~~\text{at rate}~~ &K_3.
- % \end{align*}
+ % \ce{
+ % A &->[$k_1$] B \\
+ % B + B &->[$k_2$] C + B \\
+ % B + C &->[$k_3$] A + C
+ % }
% $$
+ %
% These correspond to the ODE system,
%
% $$
- % \begin{align*}
- % y_1' &= -K_1 y_1 + K_3 y_2 y_3, \\
- % y_2' &= K_1 y_1 - K_2 y_2^2 - K_3 y_2 y_3, \\
- % y_3' &= K_2 y_2^2.
- % \end{align*}
+ % y_1' &= -k_1 y_1 + k_3 y_2 y_3, \\
+ % y_2' &= k_1 y_1 - k_2 y_2^2 - k_3 y_2 y_3, \\
+ % y_3' &= k_2 y_2^2.
% $$
- % The reaction rates $K_1$, $K_2$, and $K_3$ often range from slow to very fast
- % which makes the problem challenging. This has made it a popular test for
- % implicit time-stepping schemes.
+ %
+ % The reaction rates $k_1$, $k_2$, and $k_3$ often range from slow to very fast which makes the problem challenging.
+ % This has made it a popular test for implicit time-stepping schemes.
%
% Notes
% -----
@@ -31,12 +30,11 @@
% +---------------------+-------------------------------------------------+
% | Number of Variables | 3 |
% +---------------------+-------------------------------------------------+
- % | Stiff | typically, depending on $K_1$, $K_2$, and $K_3$ |
+ % | Stiff | typically, depending on $k_1$, $k_2$, and $k_3$ |
% +---------------------+-------------------------------------------------+
%
% Example
% -------
- %
% >>> problem = otp.robertson.presets.Canonical;
% >>> problem.Parameters.K1 = 100;
% >>> problem.Parameters.K2 = 1000;
@@ -60,11 +58,7 @@
% The initial conditions.
% parameters : RobertsonParameters
% The parameters.
- %
- % Returns
- % -------
- % obj : RobertsonProblem
- % The constructed problem.
+
obj@otp.Problem('Robertson', 3, timeSpan, y0, parameters);
end
end
diff --git a/toolbox/+otp/Parameters.m b/toolbox/+otp/Parameters.m
new file mode 100644
index 00000000..6669afc2
--- /dev/null
+++ b/toolbox/+otp/Parameters.m
@@ -0,0 +1,28 @@
+classdef Parameters
+ % A superclass for the parameters of a differential equation.
+ %
+ % Subclasses of this class specify mutable properties associated with an :class:`otp.Problem`.
+ %
+ % See Also
+ % --------
+ % otp.Problem.Parameters
+
+ methods
+ function obj = Parameters(varargin)
+ % Create a parameters object.
+ %
+ % Parameters
+ % ----------
+ % varargin
+ % A variable number of name-value pairs. A name can be any property defined by a subclass, and the
+ % subsequent value initializes that property.
+ extras = struct(varargin{:});
+ fields = fieldnames(extras);
+
+ for i = 1:length(fields)
+ f = fields{i};
+ obj.(f) = extras.(f);
+ end
+ end
+ end
+end
diff --git a/toolbox/+otp/Problem.m b/toolbox/+otp/Problem.m
index 6168facc..19e8d6bb 100644
--- a/toolbox/+otp/Problem.m
+++ b/toolbox/+otp/Problem.m
@@ -34,7 +34,7 @@
Y0 %MATLAB ONLY: (:,1) {otp.utils.validation.mustBeNumerical}
% Additional variables to pass to the F function
- Parameters %MATLAB ONLY: (1,1)
+ Parameters %MATLAB ONLY: (1,1) otp.Parameters
% The dimension of the ODE
NumVars
diff --git a/toolbox/+otp/RHS.m b/toolbox/+otp/RHS.m
index 15e4d492..32324d92 100644
--- a/toolbox/+otp/RHS.m
+++ b/toolbox/+otp/RHS.m
@@ -30,6 +30,8 @@
%
% See Also
% --------
+ % otp.Problem.RHS
+ %
% odeset : https://www.mathworks.com/help/matlab/ref/odeset.html
properties (SetAccess = private)
@@ -291,7 +293,7 @@
% F : function_handle
% The function handle for $f$ in the differential equation $M(t, y) y' = f(t, y)$.
% varargin
- % A variable number of name-value pairs. A name can be any property of :class:`RHS`, and the subsequent
+ % A variable number of name-value pairs. A name can be any property of this class, and the subsequent
% value initializes that property.
%
% Warning
diff --git a/toolboxPackaging.prj b/toolboxPackaging.prj
index 6d548e06..355c9134 100644
--- a/toolboxPackaging.prj
+++ b/toolboxPackaging.prj
@@ -7,7 +7,7 @@
A MATLAB suite of initial value problems
${PROJECT_ROOT}/images/logo.png
- 0.0.1
+ 0.2.0
${PROJECT_ROOT}/ODE Test Problems.mltbx
@@ -44,7 +44,6 @@
-