Skip to content
Snippets Groups Projects
Commit ca386533 authored by Franck Pérignon's avatar Franck Pérignon
Browse files

Update odesolvers. Work arrya + fix tests + doc + pep8 things

parent 5ffe076f
No related branches found
No related tags found
No related merge requests found
......@@ -22,14 +22,18 @@ inside an HySoP module. It's only a review of all the methods
that can be imported by final user.
"""
import hysop.numerics.integrators.runge_kutta2 as runge_kutta2
RK2 = runge_kutta2.RK2
import hysop.numerics.integrators.runge_kutta3 as runge_kutta3
RK3 = runge_kutta3.RK3
import hysop.numerics.integrators.runge_kutta4 as runge_kutta4
RK4 = runge_kutta4.RK4
import hysop.numerics.integrators.euler as euler
Euler = euler.Euler
import hysop.numerics.odesolvers as odesolvers
RK2 = odesolvers.RK2
"""Runge-Kutta 2 integration"""
RK3 = odesolvers.RK3
"""Runge-Kutta 3 integration"""
RK4 = odesolvers.RK4
"""Runge-Kutta 4 integration"""
Euler = odesolvers.Euler
"""Euler integration"""
# Remesh
import hysop.numerics.remeshing as remesh
......
"""
@package hysop.numerics.integrators
ODE integrators.
\todo write a proper doc with the list of available solvers
and their param (optim and so on)
optim value :
- None : no work, no result, no guess
- LEVEL1 : result as input/output, no work, no guess
- LEVEL2 : result as input/output, work as input, no guess.
- WITH_GUESS : LEVEL1 + LEVEL2 + first eval of rhs in result.
Length of work list depends on integrator's type :
- RK4 : work must be at least of length 2*nb_components
- RK3 : work must be at least of length nb_components
- RK2 :
- Euler :
Work can be used to give extra parameters.
"""
# -*- coding: utf-8 -*-
"""
@file euler.py
Forward Euler method.
"""
from hysop.numerics.integrators.odesolver import ODESolver
import numpy as np
class Euler(ODESolver):
"""
ODESolver implementation for solving an equation system
with forward Euler method.
y'(t) = f(t,y)
y(t_{n+1}) = y(t_n) + dt*f(y(t_n))
"""
def __init__(self, nb_components, work, topo, f=None, optim=None):
"""
@param f function f(t,y,f_work) : Right hand side of the equation to
solve.
@param nb_Components : number of components of the input field
@param optim : to choose the level of optimization (memory management).
Default = None. See hysop.numerics.integrators for details.
"""
ODESolver.__init__(self, nb_components, work, topo, f=f, optim=optim)
@staticmethod
def getWorkLengths(nb_components, domain_dim=None):
"""
Compute the number of required work arrays for this method.
@param nb_components : number of components of the
@param domain_dim : dimension of the domain
fields on which this method operates.
@return length of list of work arrays of reals.
"""
return nb_components
def _core(self, t, y, dt, result):
"""
Computational core for Euler
Highest level of optimization : result and self.work
must be provided and work must contain a first evaluation of
f(t,y)
optim = WITH_GUESS
"""
assert len(result) == self._nb_components
# result = f(t, y)
# result = y + dt * work0
# result = y + work0
[np.add(y[i], self.work[i] * dt, result[i])
for i in xrange(self._nb_components)]
return result
"""
@file odesolver.py
Abstract class for time integrators.
"""
from abc import ABCMeta, abstractmethod
from hysop.numerics.method import NumMethod
from hysop.constants import WITH_GUESS
from hysop.numerics.update_ghosts import UpdateGhosts
import hysop.tools.numpywrappers as npw
class ODESolver(NumMethod):
"""
Abstract description for ODE solvers.
Solve the system :
\f[ \frac{dy(t)}{dt} = f(t,y) \f]
"""
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self, nb_components, work, topo, f=None, optim=None):
"""
@param nb_components: number of components of the right-hand side.
@param work : a list of numpy arrays used as work space.
@param f : function f(t, y, f_work), right hand side of the equation
to solve. f must have this signature.
@remark - y argument in function f must be a list of numpy arrays
@remark - work argument in function f is to pass a list working
numpy arrays to the function. user-defined f function must have this
argument even if it unused in f.
@remark - f function must return a list of numpy arrays.
@param optim : to choose the level of optimization (memory management).
Default = None. See hysop.numerics.integrators for details.
"""
## RHS.
self.f = f
if f is None:
self.f = lambda t, y, work: [npw.zeros_like(y[i])
for i in xrange(nb_components)]
if optim is None:
self._fcall = self._basic
elif optim is WITH_GUESS:
self._fcall = self._core
self._nb_components = nb_components
self.work = work
# Length of work arrays (float and int)
lwork = self.getWorkLengths(nb_components)
assert len(self.work) == lwork, 'Wrong length for work arrays list.'
self._memshape = tuple(topo.mesh.resolution)
print topo.mesh
for wk in self.work:
assert wk.shape == tuple(self._memshape)
# Allocate buffers for ghost points synchronization.
self._synchronize = UpdateGhosts(topo, self._nb_components)
def __call__(self, t, y, dt, result):
"""
@param t : current time.
@param y : position at time t.
\remark - y arg must be a list of numpy arrays.
@param dt : time step.
@param result : a predefined list of numpy arrays to solve the result
@return y at t+dt.
"""
return self._fcall(t, y, dt, result)
def _basic(self, t, y, dt, result):
"""
self.work is used as temp. array to compute the rhs.
result provided as input arg.
result may be equal to y.
"""
self.work[:self._nb_components] = \
self.f(t, y, self.work[:self._nb_components])
return self._core(t, y, dt, result)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment