diff --git a/README.md b/README.md index 27a25558..18788655 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,18 @@ <img width="30%" src="images/logo.png" alt="ODE Test Problems" title="ODE Test Problems"> </p> + + ODE Test Problems (<code>OTP</code>) is an object-oriented Matlab/Octave package offering a broad range of initial value problems in the form of ordinary and differential-algebraic equations that can be used to test numerical methods such as time integration or data assimilation. It includes problems that are linear and nonlinear, homogeneous and nonhomogeneous, autonomous and nonautonomous, scalar and high-dimensional, stiff and nonstiff, and chaotic and nonchaotic. Many are real-world problems in chemistry, astrophysics, meteorology, and electrical engineering. <code>OTP</code> also supports partitioned ODEs for testing split, multirate, and other multimethods. Functions for plotting solutions and creating movies are available for all problems, and exact solutions are included when available. <code>OTP</code> is designed for ease of use —meaning that working with and modifying problems is simple and intuitive. <code>OTP</code> is actively under development. We are currently writing full documentation in order to release version <code>1.0.0</code>. </p> + + [](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/releases) [](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/blob/master/license.txt) [](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/actions/workflows/tests.yml) [](https://computationalsciencelaboratory.github.io/ODE-Test-Problems/) -ODE Test Problems (OTP) is an object-oriented MATLAB/Octave package offering a broad range of initial value problems in -the form of ordinary and differential-algebraic equations that can be used to test numerical methods such as time -integration or data assimilation. It includes problems that are linear and nonlinear, homogeneous and nonhomogeneous, -autonomous and nonautonomous, scalar and high-dimensional, stiff and nonstiff, and chaotic and nonchaotic. Many are -real-world problems in fields such as chemistry, astrophysics, meteorology, and electrical engineering. OTP also -supports partitioned ODEs for testing split, multirate, and other multimethods. Functions for plotting solutions and -creating movies are available for all problems, and exact solutions are included when available. OTP is designed for -ease of use meaning that working with and modifying problems is simple and intuitive. -OTP is actively under development. We are currently writing full documentation in order to release version 1.0.0 +https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/assets/5168326/e5496fee-46c0-4fb0-a42b-eb2e98374b4c + ## Installation @@ -76,3 +73,13 @@ problem.plotPhaseSpace(t, y, 'Title', 'The Circle of Life'); % Create a movie mov = problem.movie(t, y); ``` + + +## Further Reading + +`ODE Test Problems` documentation is maintained on [this page](https://computationalsciencelaboratory.github.io/ODE-Test-Problems). New feature requests and bug reports can be made through +[GitHub issues](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/issues). +We also accept pull requests that adhere to our +[contributing guide](docs/contrib.rst). An interactive tutorial on the main features of `OTP` is available in a Jupyter notebook [in the repository](/notebooks). + + diff --git a/images/animations/bouncingball-RandomTerrain.webm b/images/animations/bouncingball-RandomTerrain.webm new file mode 100644 index 00000000..caa47b00 Binary files /dev/null and b/images/animations/bouncingball-RandomTerrain.webm differ diff --git a/images/animations/lorenz63-Canonical.webm b/images/animations/lorenz63-Canonical.webm new file mode 100644 index 00000000..633e937e Binary files /dev/null and b/images/animations/lorenz63-Canonical.webm differ diff --git a/images/animations/nbody-OuterSolarSystem.webm b/images/animations/nbody-OuterSolarSystem.webm new file mode 100644 index 00000000..72ec25ed Binary files /dev/null and b/images/animations/nbody-OuterSolarSystem.webm differ diff --git a/images/animations/pendulum-Canonical.webm b/images/animations/pendulum-Canonical.webm new file mode 100644 index 00000000..0e1c497b Binary files /dev/null and b/images/animations/pendulum-Canonical.webm differ diff --git a/images/makeMovie.m b/images/makeMovie.m new file mode 100644 index 00000000..ee613531 --- /dev/null +++ b/images/makeMovie.m @@ -0,0 +1,154 @@ +function makeMovie() + + %% Set animation settings + + set(0,'DefaultAxesXMinorTick','on','DefaultAxesYMinorTick','on') + set(0,'DefaultAxesLineWidth', 2,'DefaultAxesFontName','Times',... + 'DefaultAxesFontSize',18,'DefaultAxesBox','on') + + ffmpegPath = {'/opt/homebrew/bin/ffmpeg'}; + + outputFormat = 'webm'; + targetTime = 20; + size = [300,300]; + mkdir('animations') + + %% KPR Animation + + problemName = 'bouncingball'; + presetName = 'RandomTerrain'; + + filename = strcat('animations/', problemName,'-', presetName); + + string = strcat(['otp.', problemName,'.presets.', presetName] ); + problem = eval(string); + problem.TimeSpan = [0,30]; + + sol = problem.solve('RelTol', 1e-8); + mov = problem.movie(sol, 'Save', filename, ... + 'TargetDuration',targetTime, ... + 'Size', size, ... + 'FrameRate', 15, ... + 'view', [0,90]); + + args = get_ffmpeg_args(outputFormat, filename); + + command = strjoin(strcat([ffmpegPath,' ' , args])); + system(command); + + + % Nbody animation + + + problemName = 'nbody'; + presetName = 'OuterSolarSystem'; + + filename = strcat('animations/', problemName,'-', presetName); + + string = strcat(['otp.', problemName,'.presets.', presetName] ); + problem = eval(string); + + sol = problem.solve('RelTol', 1e-4); + mov = problem.movie(sol, 'Save', filename, ... + 'TargetDuration',targetTime, ... + 'Size', size, ... + 'FrameRate', 15, ... + 'view', [60,30]); + + args = get_ffmpeg_args(outputFormat, filename); + + command = strjoin(strcat([ffmpegPath,' ' , args])); + system(command); + + + %% Pendulum animation + + + problemName = 'pendulum'; + presetName = 'Canonical'; + + + + filename = strcat('animations/', problemName,'-', presetName); + problem = otp.pendulum.presets.Canonical(4); + problem.Y0(1:4) = pi/3; + problem.Parameters.Masses = [1,1,3,3]'; + + + sol = problem.solve('RelTol', 1e-9); + mov = problem.movie(sol, 'Save', filename, ... + 'TargetDuration',targetTime, ... + 'Size', size, ... + 'FrameRate', 15, ... + 'view', [0,90]); + + args = get_ffmpeg_args(outputFormat, filename); + + command = strjoin(strcat([ffmpegPath,' ' , args])); + system(command); + + %% Lorenz63 animation + + + problemName = 'lorenz63'; + presetName = 'Canonical'; + + + + filename = strcat('animations/', problemName,'-', presetName); + string = strcat(['otp.', problemName,'.presets.', presetName] ); + problem = eval(string); + + + sol = problem.solve('RelTol', 1e-9); + problem.Y0 = sol.y(:,500); + problem.TimeSpan = [0,30]; + sol = problem.solve('RelTol', 1e-9); + mov = problem.movie(sol, 'Save', filename, ... + 'TargetDuration',targetTime, ... + 'Size', size, ... + 'FrameRate', 15, ... + 'view', [60,30]); + + + args = get_ffmpeg_args(outputFormat, filename); + + command = strjoin(strcat([ffmpegPath,' ' , args])); + system(command); +end + + +function [args] = get_ffmpeg_args(outputFormat, filename) + + % convert vido format if neccessary + switch outputFormat + case 'avi' + + case 'gif' + + args = strcat(['-i ' ... + filename,'.avi ' ... + ' -vf "fps=15,scale=500:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0' ... + ' '... + filename,'.gif']); + + case 'webm' + + args = strcat(['-i ' ... + filename,'.avi ' ... + '-c:v libvpx -quality best -crf 5 -b:v 1M -c:a libvorbis '... + filename,'.webm']); + + end +end + + + + + + + + + + +