package Math::Lsoda;
use 5.008_001;
use POSIX;
our $VERSION = '0.02';
our @ISA;
has equation => (
is => 'rw',
isa => 'CodeRef',
required => 1,
);
has initial => (
is => 'rw',
isa => 'ArrayRef',
required => 1,
);
has start => (
is => 'rw',
isa => 'Num',
default => 0,
);
has end => (
is => 'rw',
isa => 'Num',
default => 1,
);
has dt => (
is => 'rw',
isa => 'Num',
default => 0.1,
);
has relative_tolerance => (
is => 'rw',
isa => 'ArrayRef',
lazy_build => 1,
);
has absolute_tolerance => (
is => 'rw',
isa => 'ArrayRef',
lazy_build => 1,
);
has filename => (
is => 'rw',
isa => 'Str',
default => '',
);
__PACKAGE__->meta->make_immutable;
no Any::Moose;
eval {
require XSLoader;
XSLoader::load(__PACKAGE__, $VERSION);
1;
} or do {
require DynaLoader;
push @ISA, 'DynaLoader';
__PACKAGE__->bootstrap($VERSION);
};
sub run {
my $self = shift;
my $fh;
if($self->filename eq ''){
$fh = *STDOUT;
} else {
my $file = $self->filename;
open $fh, ">" . $file or die "$file: $!";
}
my $status = solve($self->equation, $self->initial, $self->start, $self->end, $self->dt, $self->relative_tolerance, $self->absolute_tolerance, $fh);
close $fh;
$status;
}
sub _build_relative_tolerance {
my $self = shift;
my $dim = @{$self->initial};
my @tol;
for ( 1 .. $dim ) {
push @tol, sqrt(DBL_EPSILON);
}
\@tol;
}
sub _build_absolute_tolerance {
my $self = shift;
my $dim = @{$self->initial};
my @tol;
for ( 1 .. $dim ) {
push @tol, sqrt(DBL_EPSILON);
}
\@tol;
}
1;
__END__
=head1 NAME
Math::Lsoda - Solve ordinary differential equation systems using lsoda.
=head1 SYNOPSIS
use Math::Lsoda;
Equation:
sub eqns {
my ($t, $x, $y) = @_;
@$y[0] = 1.0e+4 * @$x[1] * @$x[2] - 0.04 * @$x[0];
@$y[2] = 3.0e+7 * @$x[1] * @$x[1];
@$y[1] = -(@$y[0] + @$y[2]);
}
Solver:
my $solver = Math::Lsoda->new(equation => \&eqns,
initial => [1.0, 0.0, 0.0],
start => 0.0,
end => 100.0,
dt => 0.1,
relative_tolerance => [1.0e-4, 1.0e-8, 1.0e-4],
absolute_tolerance => [1.0e-6, 1.0e-10,1.0e-6],
filename => 'file.dat');
=head1 DESCRIPTION
Math::Lsoda is a numerical module used for solving ordinary differential equations.
The module is suitable for both stiff and non-stiff systems using the FORTRAN library odepack.
=head1 AUTHOR
Naoya Sato E<lt>synclover@gmail.comE<gt>
=head1 SEE ALSO
A. C. Hindmarsh, "ODEPACK, A Systematized Collection of ODE Solvers," in Scientific Computing, R. S. Stepleman et al., North-Holland, Amsterdam, 1983 pp. 55-64.
K. Radhakrishnan and A. C. Hindmarsh, "Description and Use of LSODE, the Livermore Solver for Ordinary Differential Equations," LLNL report UCRL-ID-113855, December 1993.
=head1 COPYRIGHT AND LICENSE
Copyright (c) 2010 Naoya Sato.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut