/////////////////////////////////////////////////////////////////////////////
// intg.cc
//
// SIMLIB version: 2.18
// Date: 2004-01-25
//
// Copyright (c) 1991-2004 Petr Peringer
//
// This library is licensed under GNU Library GPL. See the file COPYING.
//
//
// description: continuous system - integrator & status variables
//
// clas Integrator and Status implementation
//
////////////////////////////////////////////////////////////////////////////
// interface
#include "simlib.h"
#include "internal.h"
#include <cmath>
////////////////////////////////////////////////////////////////////////////
// implementation
SIMLIB_IMPLEMENTATION
int SIMLIB_ERRNO=0;
double SIMLIB_StepStartTime; // last step time
double SIMLIB_DeltaTime; // Time-SIMLIB_StepStartTime
double SIMLIB_OptStep; // optimal step
double SIMLIB_MinStep=1e-10; // minimal step
double SIMLIB_MaxStep=1; // max. step
double SIMLIB_StepSize; // actual step
double SIMLIB_AbsoluteError=0; // absolute error
double SIMLIB_RelativeError=0.001; // relative error
// step limits
const double &MinStep=SIMLIB_MinStep; // minimal integration step
const double &MaxStep=SIMLIB_MaxStep; // maximal integration step
const double &StepSize=SIMLIB_StepSize; // actual integration step
const double &OptStep=SIMLIB_OptStep; // optimal integration step
//const double &StepStartTime=SIMLIB_StepStartTime; // start of step
// error params
const double &AbsoluteError=SIMLIB_AbsoluteError; // max. abs. error of integration
const double &RelativeError=SIMLIB_RelativeError; // max. rel. error
bool SIMLIB_DynamicFlag = false; // in dynamic section
bool SIMLIB_ContractStepFlag = false; // requests shorter step
double SIMLIB_ContractStep = SIMLIB_MAXTIME; // requested step size
////////////////////////////////////////////////////////////////////////////
// ContractStep() -- contract step of integration
//
void ContractStep() {
SIMLIB_ContractStepFlag = true; // contract to default value (usually 1/2)
}
////////////////////////////////////////////////////////////////////////////
// ContractStep(time) -- contract step of integration to end step time
//
void ContractStep(double time)
{ // parameter is required end step time
SIMLIB_ContractStepFlag = true; // flag
double newCS = time - SIMLIB_StepStartTime;
if (newCS<SIMLIB_ContractStep)
SIMLIB_ContractStep = newCS; // can be only less
if (newCS<SIMLIB_MinStep)
SIMLIB_ContractStep = SIMLIB_MinStep; // minimum
}
////////////////////////////////////////////////////////////////////////////
// restart integration method
//
bool SIMLIB_ResetStatus = false; // restart flag
////////////////////////////////////////////////////////////////////////////
// SetStep -- set range of step
//
void SetStep(double _dtmin, double _dtmax)
{
SIMLIB_MinStep = _dtmin;
SIMLIB_MaxStep = _dtmax;
if (SIMLIB_MinStep>SIMLIB_MaxStep) SIMLIB_error(SetStepError);
// if (SIMLIB_MinStep/SIMLIB_MaxStep < 1e-12) SIMLIB_error(SetStepError2);
// if(MinStep/tend<1e-15) SIMLIB_error(InitMinStepError); // moznost chyby ???
dprintf(("SetStep: StepSize = %g .. %g ",SIMLIB_MinStep,SIMLIB_MaxStep));
}
////////////////////////////////////////////////////////////////////////////
// SetAccuracy -- set allowed error of integration method
//
void SetAccuracy(double _abserr, double _relerr)
{
SIMLIB_AbsoluteError = _abserr;
if(_relerr>1) _relerr=1; // 100% error is maximum
SIMLIB_RelativeError = _relerr;
if(SIMLIB_RelativeError<1e-14) SIMLIB_error(SetAccuracyError);
dprintf(("SetAccuracy: maxerror = %g + %g * X ",
SIMLIB_AbsoluteError,SIMLIB_RelativeError));
}
void SetAccuracy(double relerr)
{
SetAccuracy(0,relerr);
}
////////////////////////////////////////////////////////////////////////////
// SIMLIB_ContinueInit -- initialize continuous subsystem
//
void SIMLIB_ContinueInit()
{
SIMLIB_OptStep = SIMLIB_MaxStep; // initial step size
SIMLIB_StepStartTime = SIMLIB_Time;
SIMLIB_DeltaTime = 0.0;
if (IntegratorContainer::isAny()
|| StatusContainer::isAny()
|| Condition::isAny())
{ // ------------------- initialize status --------------------
IntegratorContainer::InitAll();
StatusContainer::InitAll();
Condition::InitAll(); // really needed ???
SIMLIB_Dynamic(); // initial state evaluation
SIMLIB_DynamicFlag = true;
Condition::TestAll(); // evaluate conditions
SIMLIB_DynamicFlag = false;
Condition::SetAll(); // set state
}
}
/*************************************************/
/***** Outline members of class Integrator *****/
/*************************************************/
////////////////////////////////////////////////////////////////////////////
// Integrator::CtrInit -- integrator initialization
//
void Integrator::CtrInit() {
if(SIMLIB_DynamicFlag) {
SIMLIB_error(CantCreateIntg); // can't in 'dynamic section' !!!
}
// put integrator into list & retain position of it
it_list=IntegratorContainer::Insert(this);
// dprintf(("constructor: Integrator[%p] #%d", this, Number));
SIMLIB_ResetStatus = true; //???????????????????????????????
}
////////////////////////////////////////////////////////////////////////////
// Integrator::Integrator -- integrator creation
//
Constant SIMLIB_Integrator_0input(0);
Integrator::Integrator() : input(SIMLIB_Integrator_0input)
{
dprintf(("Integrator[%p]::Integrator() #%d",
this, IntegratorContainer::Size()+1));
CtrInit();
initval = 0.0;
}
Integrator::Integrator(Input i, double initvalue) : input(i)
{
dprintf(("Integrator[%p]::Integrator(Input,%g) #%d",
this, initvalue, IntegratorContainer::Size()+1));
CtrInit();
initval = initvalue;
}
////////////////////////////////////////////////////////////////////////////
// Integrator::Integrator -- special copy constructor
//
Integrator::Integrator(Integrator &i, double initvalue) : input(i)
{
dprintf(("Integrator[%p]::Integrator(Integrator[%p],%g) #%d",
this, &i, initvalue, IntegratorContainer::Size()+1));
CtrInit();
initval = initvalue;
}
////////////////////////////////////////////////////////////////////////////
// Integrator::~Integrator -- remove integrator from list
//
Integrator::~Integrator()
{
dprintf(("destructor: Integrator[%p] #%d",
this, IntegratorContainer::Size()));
if(SIMLIB_DynamicFlag) {
SIMLIB_error(CantDestroyIntg); // can't in 'dynamic section' !!!
}
IntegratorContainer::Erase(it_list); // remove integrator from list
}
////////////////////////////////////////////////////////////////////////////
// Integrator::Init -- set initial value of integrator
//
void Integrator::Init(double initvalue) {
ss = initval = initvalue;
SIMLIB_ResetStatus = true; // if in simulation
}
////////////////////////////////////////////////////////////////////////////
// Integrator::Set -- set the integrator status value (step change)
//
void Integrator::Set(double value)
{
ss = value;
SIMLIB_ResetStatus = true; // always
}
////////////////////////////////////////////////////////////////////////////
// Integrator::Eval -- evaluate integrator input
//
void Integrator::Eval()
{
// dprintf(("START: Integrator[%p]::Eval()", this));
dd = InputValue();
// dprintf(("STOP: Integrator[%p]::Eval() %g ", this, dd));
}
////////////////////////////////////////////////////////////////////////////
// Integrator::Value -- integrator status (output value)
//
double Integrator::Value()
{
// dprintf(("Integrator[%p]::Value() = %g ", this, ss));
return ss;
}
/**********************************************************/
/***** Outline members of class IntegratorContainer *****/
/**********************************************************/
dlist<Integrator*>* IntegratorContainer::ListPtr=NULL; // list of integrators
////////////////////////////////////////////////////////////////////////////
// IntegratorContainer::Instance
// return pointer to list, also create list if it is not created
//
dlist<Integrator*>* IntegratorContainer::Instance(void)
{
dprintf(("IntegratorContainer::Instance()(%p)",ListPtr));
if(ListPtr==NULL) { // list is not created
ListPtr = new dlist<Integrator*>; // create it
dprintf(("created: %p", ListPtr));
}
return ListPtr;
} // Instance
////////////////////////////////////////////////////////////////////////////
// IntegratorContainer::Insert
// insert element into random (any) position in the container
//
IntegratorContainer::iterator IntegratorContainer::Insert(Integrator* ptr)
{
dprintf(("IntegratorContainer::Insert(%p)",ptr));
(void)Instance(); // create list if it is not created
return ListPtr->insert(ListPtr->end(),ptr); // insert element
} // Insert
////////////////////////////////////////////////////////////////////////////
// IntegratorContainer::Erase - exclude element from container
//
void IntegratorContainer::Erase(IntegratorContainer::iterator it)
{
dprintf(("IntegratorContainer::Erase(...)"));
if(ListPtr!=NULL) { // list is created
ListPtr->erase(it); // exclude element
}
} // Erase
////////////////////////////////////////////////////////////////////////////
// IntegratorContainer::NtoL
// save statuses of blocks -- Now to Last
//
void IntegratorContainer::NtoL()
{
dprintf(("IntegratorContainer::NtoL()"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator ip=ListPtr->begin(); ip!=end_it; ip++) {
(*ip)->Save();
}
}
} // NtoL
////////////////////////////////////////////////////////////////////////////
// IntegratorContainer::LtoN -- restore saved statuses
//
void IntegratorContainer::LtoN()
{
dprintf(("IntegratorContainer::LtoN)"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator ip=ListPtr->begin(); ip!=end_it; ip++) {
(*ip)->Restore();
}
}
} // LtoN
////////////////////////////////////////////////////////////////////////////
// IntegratorContainer::InitAll() -- initialize all integrators
//
void IntegratorContainer::InitAll()
{
dprintf(("IntegratorContainer::InitAll)"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator ip=ListPtr->begin(); ip!=end_it; ip++) {
(*ip)->SetState(0.0); // zero values
(*ip)->SetDiff(0.0);
(*ip)->Init();
}
}
} // InitAll
////////////////////////////////////////////////////////////////////////////
// static IntegratorContainer::EvaluateAll -- without loop detection
//
void IntegratorContainer::EvaluateAll()
{
dprintf(("IntegratorContainer::EvaluateAll)"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator ip=ListPtr->begin(); ip!=end_it; ip++) {
(*ip)->Eval(); // evaluate inputs ...
}
}
} // EvaluateAll
/*********************************************/
/***** Outline members of class Status *****/
/*********************************************/
////////////////////////////////////////////////////////////////////////////
// Status::CtrInit -- status variable initialization
//
void Status::CtrInit() {
if(SIMLIB_DynamicFlag) {
SIMLIB_error(CantCreateStatus); // can't in 'dynamic section' !!!
}
// put status into list & retain position of it
it_list=StatusContainer::Insert(this);
ValueOK = false; // important !!! ###
dprintf(("constructor: Status[%p] #%d", this, StatusContainer::Size()));
SIMLIB_ResetStatus = true; // ??????????
}
////////////////////////////////////////////////////////////////////////////
// Status::Status -- initialize status variable
//
Status::Status(Input i, double initvalue): aContiBlock1(i)
{
CtrInit();
initval = initvalue;
}
////////////////////////////////////////////////////////////////////////////
// Status::~Status -- remove status block from list
//
Status::~Status() {
dprintf(("destructor: Status[%p] #%d", this, StatusContainer::Size()));
if(SIMLIB_DynamicFlag) {
SIMLIB_error(CantDestroyStatus);
}
StatusContainer::Erase(it_list); // remove status variable from list
}
////////////////////////////////////////////////////////////////////////////
// Status::Init -- set initial value
//
void Status::Init(double initvalue)
{
st = initval = initvalue;
ValueOK = false; // important !!! ??? ###
}
////////////////////////////////////////////////////////////////////////////
// Status::Set -- set status value (step change)
//
void Status::Set(double value)
{
st = value;
ValueOK = false; // important !!!
}
////////////////////////////////////////////////////////////////////////////
// Restore -- restore saved status
//
void Status::Restore()
{
st = stl;
ValueOK = false; // important !!!
}
////////////////////////////////////////////////////////////////////////////
// virtual double Status::Value() -- value of status block
//
double Status::Value()
{
if(!ValueOK)
_Eval(); // if not, evaluate
return st; // return status
}
////////////////////////////////////////////////////////////////////////////
// virtual void Status::Eval() -- evaluate without loop detection ###
//
void Status::Eval()
{
st = InputValue(); // input ---> output
ValueOK = true;
}
/******************************************************/
/***** Outline members of class StatusContainer *****/
/******************************************************/
dlist<Status*>* StatusContainer::ListPtr=NULL; // list of status variables
////////////////////////////////////////////////////////////////////////////
// StatusContainer::Instance
// return pointer to list, also create list if it is not created
//
dlist<Status*>* StatusContainer::Instance(void)
{
dprintf(("StatusContainer::Instance()(%p)",ListPtr));
if(ListPtr==NULL) { // list is not created
ListPtr = new dlist<Status*>; // create it
dprintf(("created: %p", ListPtr));
}
return ListPtr;
} // Instance
////////////////////////////////////////////////////////////////////////////
// StatusContainer::Insert
// insert element into random (any) position in the container
//
StatusContainer::iterator StatusContainer::Insert(Status* ptr)
{
dprintf(("StatusContainer::Insert(%p)",ptr));
(void)Instance(); // create list if it is not created
return ListPtr->insert(ListPtr->end(),ptr); // insert element
} // Insert
////////////////////////////////////////////////////////////////////////////
// StatusContainer::Erase - exclude element from container
//
void StatusContainer::Erase(StatusContainer::iterator it)
{
dprintf(("StatusContainer::Erase(...)"));
if(ListPtr!=NULL) { // list is created
ListPtr->erase(it); // exclude element
}
} // Erase
////////////////////////////////////////////////////////////////////////////
// StatusContainer::NtoL
// save statuses of blocks -- Now to Last
//
void StatusContainer::NtoL()
{
dprintf(("StatusContainer::NtoL()"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator sp=ListPtr->begin(); sp!=end_it; sp++) {
(*sp)->Save();
}
}
} // NtoL
////////////////////////////////////////////////////////////////////////////
// StatusContainer::LtoN -- restore saved statuses
//
void StatusContainer::LtoN()
{
dprintf(("StatusContainer::LtoN)"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator sp=ListPtr->begin(); sp!=end_it; sp++) {
(*sp)->Restore();
}
}
} // LtoN
////////////////////////////////////////////////////////////////////////////
// StatusContainer::InitAll() -- initialize all status variables
//
void StatusContainer::InitAll()
{
dprintf(("StatusContainer::InitAll)"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator sp=ListPtr->begin(); sp!=end_it; sp++) {
(*sp)->SetState(0.0); // zero values
(*sp)->Init();
}
}
} // InitAll
////////////////////////////////////////////////////////////////////////////
// static StatusContainer::EvaluateAll -- with loop detection
//
void StatusContainer::EvaluateAll()
{
dprintf(("StatusContainer::EvaluateAll)"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator sp=ListPtr->begin(); sp!=end_it; sp++) {
(*sp)->_Eval(); // evaluate inputs with loop detection
}
}
} // EvaluateAll
////////////////////////////////////////////////////////////////////////////
// StatusContainer::ClearAllValueOK
// invalidate values of all status variables
//
void StatusContainer::ClearAllValueOK()
{
dprintf(("StatusContainer::EvaluateAll)"));
if(ListPtr!=NULL) { // list is created
iterator end_it=ListPtr->end();
for(iterator sp=ListPtr->begin(); sp!=end_it; sp++) {
(*sp)->SetValid(false); // invalidate values
}
}
} // EvaluateAll
// end
syntax highlighted by Code2HTML, v. 0.9.1