Skip to content

Commit

Permalink
Merge branch 'master' into feature/gifs
Browse files Browse the repository at this point in the history
  • Loading branch information
elswit authored Sep 23, 2024
2 parents 8e68ff5 + 525812b commit d84aba7
Show file tree
Hide file tree
Showing 148 changed files with 2,680 additions and 1,398 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build Documentation
name: Documentation

on:
workflow_dispatch:
Expand All @@ -20,12 +20,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
python-version: 3.12
cache: 'pip'

- name: Install Python Packages
Expand All @@ -37,7 +37,7 @@ jobs:
run: make

- name: Upload Artifact
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v3
with:
path: ./docs/build

Expand All @@ -51,4 +51,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4
13 changes: 4 additions & 9 deletions .github/workflows/draft-pdf.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
name: draft-paper
name: Paper Draft
on:
workflow_dispatch:
pull_request:
branches: [master]
branches: [paper/**]
push:
branches: [paper]
paths: [paper/**]

jobs:
paper:
runs-on: ubuntu-latest
name: Paper Draft
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build draft PDF
uses: openjournals/openjournals-draft-action@master
with:
journal: joss
# This should be the path to the paper within your repo.
paper-path: paper/paper.md
- name: Upload
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v3
with:
name: paper
# This is the output path where Pandoc will write the compiled
# PDF. Note, this should be the same directory as the input
# paper.md
path: paper/paper.pdf
15 changes: 13 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@ on:

jobs:
octave:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-22.04]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install Octave
run: |
sudo apt-get update
sudo apt-get install -y octave
- name: Run OTP tests
run: octave --eval "addpath(genpath('.')); runalltests"

- name: Install OTP
run: octave --eval "OTP.install"

- name: Load OTP
run: octave --eval "pkg load 'ode test problems'"
163 changes: 64 additions & 99 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,171 +1,142 @@
# Contributing Guide

This guide provides instructions for submitting and formatting new code in `OTP`.
This guide provides instructions for submitting and formatting new code in OTP.

## Submitting Changes

Changes to `OTP` should be proposed as a pull request and undergo a review process before being merged. New code must be free of warnings and errors and adhere to the style guidelines (see also [The style guidelines](## Style guidelines)).
Changes to OTP should be proposed as a pull request and undergo a review process before being merged. New code must be free of warnings and errors and adhere to the [style guidelines](#style-guidelines).

## Creating a Problem

Each problem defines a package under `+otp` that contains all files used by the problem. To add a new test problem follow these steps:
Each problem defines a package under `+otp` that contains all files used by the problem. When creating a new problem we recommend duplicating an existing problem package, e.g., [Lorenz63](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/blob/master/toolbox/+otp/+lorenz63) or [Brusselator](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/blob/master/toolbox/+otp/+brusselator), then renaming and editing the contents as needed.

1. Check out the latest version of `OTP`:
To add a new test problem from scratch follow these steps:

1. Check out the latest version of OTP:

```bash
git clone https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems.git
cd ODE-Test-Problems/
```

2. Create a new folder in the `src/+opt/` directory. Follow the same naming conventions as the existing problems. Start the name with `+` to maintain the structure of the Matlab/Octave package. Also create a subfolder named `+presets` in the new problem folder:
2. Create a new folder in the `toolbox/+opt/` directory with a name that starts with `+` to indicate it is a package. Also create a subfolder named `+presets` in the new problem folder:

```bash
mkdir src/+opt/+newtest
mkdir src/+opt/+newtest/+presets
cd src/+opt/+newtest/
mkdir toolbox/+opt/+example
cd toolbox/+opt/+example
mkdir +presets
```

3. The minimal set of files needed inside the problem folder to set up a new test problem are:
* The right-hand-side function named as `f.m`
* The problem class to initialize problem objects and its methods and properties
* The parameters class defines the parameters of the new problem
* A `Canonical.m` preset inside the `+presets` subfolder to set the initial condition and parameters in your case

```bash
touch f.m
touch NewTestProblem.m
touch NewTestParameters.m
touch +presets/Canonical.m
```
3. The minimal set of files needed inside the problem folder to set up a new example problem are:
* The right-hand side (RHS) function named as `f.m`
* The problem class to specify properties, override plotting and solver options, and convert parameters into arguments for RHS functions
* The parameters class
* A `Canonical.m` preset inside the `+presets` subfolder to set standard initial condition and parameters.

## The Right-hand-side Structure
```bash
touch f.m ExampleProblem.m ExampleParameters.m +presets/Canonical.m
```

The right-hand-side structure provides various derivatives of the problem. They are implemented in separate function files. The right-hand-side function `f.m`, which is the time-derivative of the state `y` is defined as a function with at least two arguments `f(t,y)`. If the right-hand-side function needs other parameters they can also be passed to this function:
### The RHS Function

```Matlab
The RHS function `f.m`, which is the time-derivative of the state `y`, is defined as a function with at least two arguments. If parameters are needed, they can be added as arguments.

function dy = f(t, y, Param1, ...)
dy = ...
```matlab
function dy = f(t, y, param1, ...)
dy = ...
end
```

For more information about this formulation please refer to our [paper](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/blob/master/paper/paper.md).

## The Problem Class
Other functions associated with an `otp.RHS` like the Jacobian and mass matrix should be implemented in separate `.m` files with the same function signature as `f.m`.

A problem package must contain a class named `<Name>Problem.m` that is a subclass of `otp.Problem`. There are two
methods that must be implemented: the constructor and `onSettingsChanged`. Optionally, one can override functions such as `internalPlot` and `internalSolve` to provide problem-specific defaults. Partitioned problems can add custom right-hand-side functions
as class properties with private write access. The property name should start with `RHS`, e.g., `RHSStiff`.
### The Problem Class

The template for a new class of problems called `NewTest` looks like:
A problem package must contain a class named `<Name>Problem.m` that is a subclass of `otp.Problem`. There are two methods that must be implemented: the constructor and `onSettingsChanged`. Optionally, one can override functions such as `internalPlot` and `internalSolve` to provide problem-specific defaults. Partitioned problems can add custom RHS functions as class properties with private write access. The property name should start with `RHS`, e.g., `RHSStiff`.

```Matlab
classdef NewTestProblem < otp.Problem
A basic template for a new class of problems called `Example` looks like

```matlab
classdef ExampleProblem < otp.Problem
methods
function obj = NewTestProblem(timeSpan, y0, parameters)
[email protected]('New Test', [], timeSpan, y0, parameters);
function obj = ExampleProblem(timeSpan, y0, parameters)
[email protected]('Example', [], timeSpan, y0, parameters);
% The second argument specifies the number of variables in the problem is arbitrary
end
end
methods (Access=protected)
function onSettingsChanged(obj)
% Parameters are stored in the obj.Parameters structure. We can assign them to individual variables to be
% used in function calls
param1 = obj.Parameters.Param1;
% parameters are stored in the obj.Parameters structure
% We can assign them to individual variables
% to be used in function calls
Param1 = obj.Parameters.Param1; % ...
% set up the right-hand-side function wrapper
obj.RHS = otp.RHS(@(t, y) otp.newtest.f(t, y, Param1), 1:obj.NumVars);
% set up the RHS function wrapper
obj.RHS = otp.RHS(@(t, y) otp.example.f(t, y, param1));
end
% set up internal plot function
function fig = internalPlot(obj, t, y, varargin)
fig = [email protected](obj, t, y, ...
'xscale', 'log', 'yscale', 'log', varargin{:});
fig = [email protected](obj, t, y, 'xscale', 'log', 'yscale', 'log', varargin{:});
end
% set up internal movie function
function mov = internalMovie(obj, t, y, varargin)
mov = [email protected](obj, t, y, ...
'xscale', 'log', 'yscale', 'log', varargin{:});
mov = [email protected](obj, t, y,, 'xscale', 'log', 'yscale', 'log', varargin{:});
end
% set up internal solver
function sol = internalSolve(obj, varargin)
% Set tolerances due to the very small scales
sol = [email protected](obj, ...
'AbsTol', 1e-50, varargin{:});
sol = [email protected](obj, 'AbsTol', 1e-50, varargin{:});
end
end
end
```

## The Parameters Class

A problem package must also contain a class named `<Name>Parameters.m`. It only needs to provide public properties for each of the problem parameters; no constructor or methods are needed. Note that property validation is currently not supported in Octave. Therefore, we use a custom comment syntax that is parsed by the installer to optionally include validation. The following is an example of a parameter class with property validation:
### The Parameters Class

A problem package must also contain a class named `<Name>Parameters.m` that is a subclass of `otp.Parameters`. It needs to provide public properties for each of the problem parameters and a constructor which forwards arguments to the superclass constructor; no methods are needed. Note that property validation is currently not supported in Octave. Therefore, we use a custom comment syntax that is parsed by the installer to optionally include validation. The following is an example of a parameter class with property validation:

```Matlab
classdef NewTestParameters
%NewTestParameters
```matlab
classdef ExampleParameters
properties
Param1 %MATLAB ONLY: (1,1) {mustBeNumeric, mustBeReal, mustBeNonnegative}
Param1 %MATLAB ONLY: (1,1) {mustBeReal, mustBeNonnegative}
end
end
methods
function obj = ExampleParameters(varargin)
obj = [email protected](varargin{:});
end
end
end
```

## Adding presets

Within a problem package, there should be a subpackage named `+presets`. This contains subclasses of `<Name>Problem`
that specify the timespan, initial conditions, and parameters. Typically, only the constructor needs to be implemented
in a preset class.
### Adding presets

In our example, we add the `Canonical.m` preset inside the `+presets` subfolder containing:
Within a problem package, there should be a subpackage named `+presets`. This contains subclasses of `<Name>Problem` that specify the time span, initial conditions, and parameters. Typically, only the constructor needs to be implemented in a preset class.

```Matlab
In our example, we add a `Canonical.m` preset inside the `+presets` subfolder.

classdef Canonical < otp.newtest.NewTestProblem
```matlab
classdef Canonical < otp.example.ExampleProblem
methods
function obj = Canonical
params = otp.newtest.NewTestParameters;
params.Param1 = ...
function obj = Canonical(varargin)
y0 = ...
tspan = ...
obj = [email protected](tspan, y0, params);
% Specify a default value for Param1 which can be overridden by a name-value pair passed to this constructor
params = otp.example.ExampleParameters('Param1', pi, varargin{:});
obj = [email protected](tspan, y0, params);
end
end
end
```
## Copying the Problem Template

When creating a new problem, we
recommend duplicating an existing problem package, then renaming and editing the contents as needed.

[This is a minimal example of](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/tree/81cf4e473c34fe04d70280d0a78222a4c75fd775/src/%2Botp/%2Bnewtest) the completed test problem started in this tutorial. It implements the trivial ODE $y'(t) = 1, y(0) = 1$ and can be used as a template to implement simple test problems.


An example of a more sophisticated problem with implemented Jacobians is the [Lorenz63 problem](https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/blob/master/src/+otp/+lorenz63). For an example of split right-hand-side PDE, see [the Brusselator problem]( https://github.com/ComputationalScienceLaboratory/ODE-Test-Problems/blob/master/src/+otp/+brusselator).


## Style Guidelines

In order for this project to maintain a consistent coding style, the following conventions should be used. These
standards match those most commonly used in MATLAB's code and documentation.
In order for this project to maintain a consistent coding style, the following conventions should be used. These standards largely match those most commonly used in MATLAB's code and documentation.

### Line Formatting

Expand Down Expand Up @@ -205,8 +176,7 @@ car = struct('make', 'Ford', 'modelYear', 2020);

### Packages

Package names should be completely lowercase and start with a plus symbol. No capitalization or special character is
used to distinguish between words.
Package names should be completely lowercase and start with a plus symbol. No capitalization or special character is used to distinguish between words.

```matlab
% Example
Expand All @@ -216,8 +186,7 @@ help otp.utils.PhysicalConstants

### Classes

Class names and properties should be written in Pascal case. When the name contains an acronym, all letters should be
capitalized. Methods should be written in camel case.
Class names and properties should be written in Pascal case. When the name contains an acronym, all letters should be capitalized. Methods should be written in camel case.

```matlab
% Examples
Expand All @@ -239,7 +208,3 @@ classdef ODETestProblems
...
end
```


## Creating Documentation

4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Name: ODE Test Problems
Version: 0.0.1
Date: May 10, 2023
Version: 0.3.0
Date: March 26, 2024
depends: octave (>= 6.4.0)
Author: Steven Roberts, Andrey A. Popov, Arash Sarshar, Adrian Sandu
Maintainer: Steven Roberts
Expand Down
Loading

0 comments on commit d84aba7

Please sign in to comment.