Java implementation of the LSODA stiff ODE solver
This the Java implementation of the algorithm LSODA. The original algorithm can be accessed here. It can be used to solve the non-stiff and stiff ordinary differential equations (ODEs).
This Java version LSODA is ported from the C version of LSODA.
Generate the jar file with the following command:
mvn clean package
If you are using IntelliJ IDEA, you can generate the package through this IDE. See the details here.
Copy the generated jar file to the folder lib.
Open the Project Stucture and add this jar file in the Libraries.
Then add the Apache Commons Math dependency in pom.xml.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
Then you can use the package to calculate IVPs. Here is an example for integrating: y' = 12y. The integration interval is [0,2].
import org.apache.commons.math3.exception.DimensionMismatchException;
import org.apache.commons.math3.exception.MaxCountExceededException;
import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;
import odesolver.LSODA;
public class Main {
public static void main(String[] args){
// set the minimum and maximum step sizes, error tolerance and the maximum orders for the methods
LSODA lsoda = new LSODA(0,0.5,1.0e-6,1.0e-6,12, 5);
FirstOrderDifferentialEquations ode =
new FirstOrderDifferentialEquations() {
@Override
public int getDimension() {
return 1;
}
@Override
public void computeDerivatives(double t, double[] y, double[] ydot) throws MaxCountExceededException, DimensionMismatchException {
ydot[0] = -12*y[0]; // define the ODE
}
};
double[] y = {1}; // set the initial value
double t = 0;
double tout = 2; // set the integration interval
double[] result = new double[1]; // store the integration result
lsoda.integrate(ode,t,y,tout,result);
System.out.println(result[0]);
}
}
For more examples, users can refer to test/odesolver/StiffExamplesTest.java, which includes the stiff examples from the paper Comparing numerical methods for stiff systems of ODEs.
Furthermore, this implementation retains the original input parameters. If you wish to further configure the solver, you can invoke the following method:
package org.example;
import org.apache.commons.math3.exception.DimensionMismatchException;
import org.apache.commons.math3.exception.MaxCountExceededException;
import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;
import odesolver.LSODA;
public class Main {
public static void main(String[] args){
// create the object
LSODA lsoda = new LSODA(0,0.5,
1.0e-6,1.0e-6,12, 5);
FirstOrderDifferentialEquations ode = new FirstOrderDifferentialEquations() {
@Override
public int getDimension() {
return 1;
}
@Override
public void computeDerivatives(double t, double[] y, double[] ydot) throws MaxCountExceededException, DimensionMismatchException {
// define the ODE
// Analytical solution: y = sin^2 x + cos x
ydot[0] = 2*Math.cos(t)*Math.sin(t)-Math.sin(t);
}
};
double[] y = {1}; // initial value
double t = 0;
double tout = 10; // integration interval
lsoda.ode = ode;
// error tolerance
double[] rtol = {0,1.0e-6};
double[] atol = {0,1.0e-6};
lsoda.lsoda(1,y,t,tout,1, rtol,atol,1,1,1,0,1000,10,12,
5,0,0,0.5,0);
double analyticalRes = Math.sin(tout)*Math.sin(tout)+Math.cos(tout); // analytical solution
System.out.printf("Analytical solution: y1 = %.16e\n", analyticalRes);
System.out.printf("Numerical solution: y1 = %.16e\n", lsoda.y[1]);
}
}
More examples of using this calling method can be found in test/odesolver/ITaskAndContinuationTest.java.
For more detailed description and meaning of these parameters, users can refer to javadoc at this page and the original LSODE description.