//----------------------------------------------------------------------------
//	Copyright (C) 2002, 2003, 2004 Humboldt-Universitaet zu Berlin
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 of the License, or (at your option) any later version.
//
//	This library is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//	Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public
//	License along with this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//----------------------------------------------------------------------------
/**	\file ODESolver.h

 \author Michael Fiedler

 \date created at 2008/11/21

 \brief Declaration of ODESolver

 \since 3.0
 */

#ifndef ODEMX_ODESOLVER_INCLUDED
#define ODEMX_ODESOLVER_INCLUDED

#include <odemx/base/continuous/VariableContainer.h>

namespace odemx {
	namespace base {
		namespace continuous {

			/** Choice which error is checked while integration
			 */
			enum ErrorType {
				absolute, relative
			};

			class Monitor;

			class VariableContainer;

			/** \class ODESolver

				\ingroup base

				\brief abstract class for implementing a solver

				This class specifies the structure of an solver as seen by the monitor.

				\sa Monitor, GSLSolver

				\since 3.0
			 */
			class ODESolver {
			public:
				/// destruction
				virtual ~ODESolver();

				/** \brief gives an VariableContainer suitable for this Solver
					\param size
						initial size of VariableContainer
				 */
				virtual VariableContainer* getVariableContainer(int size) = 0;

				/** \brief makes one integration step for monitor
					\param time
						internal time of assigned monitor plus \p time is the time from which to do the step
				 */
				virtual void makeStep(double time) = 0;

				/** \brief initialize the solver

					\note this is also called if monitor has changed
				 */
				virtual void init() = 0;

				/** \name assigned Monitor

					@{
				 */
				/** \brief set assigned Monitor
				 */
				void setMonitor(Monitor* monitor);

				/** \brief gives assigned Monitor
				 */
				Monitor* getMonitor();
				//@}

				/** \name solving Parameters

					@{
				 */
				/** \brief sets the error limit for integration
				 */
				void setErrorLimit(double maxError);

				/** \brief returns the error limit for integration
				 */
				double getErrorLimit(); // added by Sascha

				/** \brief sets the type of error which will be checked
					\param type
						is 'absolute' or 'relative'
				 */
				void setErrorType(ErrorType type);

				/** \brief sets the interval for the step length of one integration step
					\param min
						lower bound on step length
					\param max
						upper bound on step length
				 */
				void setStepLength(double min, double max);

				/** \brief gives the size of the last step done
				 */
				double getStepLength();
				//@}

			protected:
				/** pointer to Monitor which will be integrated
				 */
				Monitor* monitor;

				/** \brief gives derivatives of the system described by the assigned monitor

				 evaluates all equations of all continuous process as one function
				 as sum of partial functions at time internalTime + time
				 */
				void evalF(double time);

				/** \brief gives jacbian of the system described in assigned monitor

				 evaluates all jacobian of all continuous process as one matrix
				 as sum of partial matrices at time internalTime + time
				 */
				void evalJacobian(double time);

				/** \brief gives the variables of the assigned Monitor
				 */
				VariableContainer* getVariableContainerOfMonitor();

				/** errorType which will be checked after each step to optimize step length
				 */
				ErrorType errorType;

				/** errorLimit which will be checked after each step to optimize step length
				 */
				double errorLimit;

				/** minimum step length allowed by user
				 */
				double minStep;

				/** maximum step length allowed by user
				 */
				double maxStep;

				/** step length of last step
				 */
				double lastStep;

				friend class Monitor;
			};
		}
	}
}

#endif

