//----------------------------------------------------------------------------
//	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 VariableContainer.h

 \author Michael Fiedler

 \date created at 2008/11/21

 \brief Declaration of VariableContainer

 \since 3.0
 */

#ifndef ODEMX_VARIABLECONTAINER_INCLUDED
#define ODEMX_VARIABLECONTAINER_INCLUDED

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

namespace odemx {
	namespace base {
		namespace continuous {

			/** \class VariableContainer

				\ingroup base

				\brief abstract class for implementing memory handling of an solver

				\sa ODESolver, Monitor

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

				/** \brief adapt the numbers of variables which can be stored in the container
					\param newSize
						new size of container

					\note old content is preserved as long it fits in \p newSize, everything over will be truncated
				 */
				virtual void adaptSizeTo(int newSize) = 0;

				/** \name Variables

				 variable are for holding values while derivatives, jacobi and DfDt are for calculating

				 @{
				 */
				/** \brief set all variables to 0.0
				 */
				virtual void nullVariables() = 0;

				/** \brief set value of one variable
					\param num
						index of variable to set \p value
				 */
				virtual void setVariable(int num, double value) = 0;

				/** \brief get value of one variable
					\param num
						index of variable to get
				 */
				virtual double getVariable(int num) = 0;
				//@}

				/** \name temporary values

					these values are used will calculating intermediate steps

				 @{
				 */
				/** \brief set all temporary variables to 0.0
				 */
				virtual void nullValues() = 0;

				/** \brief set values of temporary variables to these ones of corresponding variables
				 */
				virtual void copyVariablesToValues() = 0;

				/** \brief set value of one temporary variable
					\param num
						index of variable to set \p value
				 */
				virtual void setValue(int num, double value) = 0;

				/** \brief get value of one temporary variable
					\param num
						index of variable to get
				 */
				virtual double getValue(int num) = 0;
				//@}

				/** \name derivatives

					@{
				 */
				/** \brief set all derivate values to 0.0
				 */
				virtual void nullDerivatives() = 0;

				/** \brief set value of one derivate variable
					\param num
						index of variable to set \p value
				 */
				virtual void setDerivative(int num, double value) = 0;

				/** \brief add to value of one derivate variable
					\param num
						index of variable to add \p value
				 */
				virtual void addToDerivative(int num, double value) = 0;

				/** \brief get value of one variable from the derivates-array, where num is the index
					\param num
						index of variable to get
				 */
				virtual double getDerivative(int num) = 0;
				//@}

				/** \name jacobi

					@{
				 */
				/** \brief set all jacobian values to 0.0
				 */
				virtual void nullJacobi() = 0;

				/** \brief set value of one jacobian variable

					set variable(\p i ,\p j ) to \p value
				 */
				virtual void setJacobi(int i, int j, double value) = 0;

				/**  \brief set value of one jacobian variable

					add \p value to variable(\p i ,\p j )
				 */
				virtual void addToJacobi(int i, int j, double value) = 0;

				/** \brief get value of one jacobian variable

					\return variable(\p i ,\p j )
				 */
				virtual double getJacobi(int i, int j) = 0;
				//@}

				/** \name DfDt

					right hand side derived by time

				 @{
				 */
				/** \brief set all derived components to 0.0
				 */
				virtual void nullDfDt() = 0;

				/** \brief set value of one derived component
					\param num
						index of derived component to set \p value
				 */
				virtual void setDfDt(int num, double value) = 0;

				/** \brief add to value of one derived component
					\param num
						index of derived component to add \p value
				 */
				virtual void addToDfDt(int num, double value) = 0;

				/** \brief get value of one derived component
					\param num
						index of derived component to get
				 */
				virtual double getDfDt(int num) = 0;
				//@}
			};
		}
	}
}
#endif
