adevs

/home/rotten/Code/adevs-2.4.3/include/adevs_dess.h

00001 /***************
00002 Copyright (C) 2000-2006 by James Nutaro
00003 
00004 This library is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU Lesser General Public
00006 License as published by the Free Software Foundation; either
00007 version 2 of the License, or (at your option) any later version.
00008 
00009 This library is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public
00015 License along with this library; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 Bugs, comments, and questions can be sent to nutaro@gmail.com
00019 ***************/
00020 #ifndef _adevs_dess_h_
00021 #define _adevs_dess_h_
00022 #include "adevs_models.h"
00023 
00024 namespace adevs
00025 {
00026 
00038 template <class X> class DESS: public Atomic<X>
00039 {
00040         public:
00042                 DESS();
00048                 virtual void evolve_func(double h) = 0;
00056                 virtual double next_event_func(bool& is_event) = 0;
00061                 virtual void discrete_action_func(const Bag<X>& xb) = 0;
00067                 virtual void discrete_output_func(Bag<X>& yb) = 0;
00077                 virtual void state_changed() = 0;       
00079                 void delta_int();
00081                 void delta_ext(double e, const Bag<X>& xb);
00083                 void delta_conf(const Bag<X>& xb);
00085                 void output_func(Bag<X>& yb);
00087                 double ta();
00089                 virtual ~DESS(){}
00090 
00091         private:
00092                 // Time until the next event
00093                 double sigma;
00094                 // The phase can be step, event, or output
00095                 enum { DESS_STEP, DESS_EVENT, DESS_OUTPUT } phase;
00096                 // Empty bag for internal events
00097                 Bag<X> empty_bag;
00098                 // Temporary bag for discrete output values
00099                 Bag<X> ytmp;
00100 };
00101 
00102 template <class X>
00103 DESS<X>::DESS()
00104 {
00105         sigma = 0.0;
00106         phase = DESS_STEP;
00107 }
00108 
00109 template <class X>
00110 void DESS<X>::delta_int()
00111 {
00112         if (phase == DESS_OUTPUT)
00113         {
00114                 ytmp.clear();
00115                 bool event = false;
00116                 sigma = next_event_func(event);
00117                 if (event) phase = DESS_EVENT;
00118                 else phase = DESS_STEP;
00119         }
00120         else
00121         {
00122                 // Evolve the continuous variables
00123                 evolve_func(sigma);
00124                 // Notify derived class of state change
00125                 state_changed();
00126                 // If this is an internal discrete event
00127                 if (phase == DESS_EVENT)
00128                 {
00129                         // Get the output
00130                         discrete_output_func(ytmp);
00131                         // Change the state 
00132                         discrete_action_func(empty_bag);
00133                         // Notify derived class of the event
00134                         state_changed();
00135                         phase = DESS_OUTPUT;
00136                         sigma = 0.0;
00137                 }
00138                 // Otherwise, just schedule the next event or 
00139                 // integration step
00140                 else
00141                 {
00142                         bool event = false;
00143                         sigma = next_event_func(event);
00144                         if (event) phase = DESS_EVENT;
00145                         else phase = DESS_STEP;
00146                 }
00147         }
00148 }
00149 
00150 template <class X>
00151 void DESS<X>::delta_ext(double e, const Bag<X>& xb)
00152 {
00153         // Update the continuous variables
00154         evolve_func(e);
00155         // Notify the derived class
00156         state_changed();
00157         // Apply the discrete state change function
00158         discrete_action_func(xb);
00159         // Notify the derived class again
00160         state_changed();
00161         // Schedule the next step or event
00162         bool event = false;
00163         sigma = next_event_func(event);
00164         if (event) phase = DESS_EVENT;
00165         else phase = DESS_STEP;
00166 }
00167 
00168 template <class X>
00169 void DESS<X>::delta_conf(const Bag<X>& xb)
00170 {
00171         // If it is not a state event, then this is just an input coinciding with
00172         // some book keeping operations
00173         if (phase == DESS_OUTPUT || phase == DESS_STEP)
00174         {
00175                 ytmp.clear();
00176                 delta_ext(sigma,xb);
00177         }
00178         // Confluence of a state/time event an external input requires special
00179         // handling
00180         else if (phase == DESS_EVENT)
00181         {
00182                 // Update the continuous variables
00183                 evolve_func(sigma);
00184                 // Notify the derived class
00185                 state_changed();
00186                 // Compute the output
00187                 discrete_output_func(ytmp);
00188                 // Compute the discrete state change
00189                 discrete_action_func(xb);
00190                 // Notify the derived class
00191                 state_changed();
00192                 // Send the output
00193                 phase = DESS_OUTPUT;
00194                 sigma = 0.0;
00195         }
00196 }
00197 
00198 template <class X>
00199 void DESS<X>::output_func(Bag<X>& yb)
00200 {
00201         typename Bag<X>::iterator iter = ytmp.begin();
00202         for (; iter != ytmp.end(); iter++)
00203         {
00204                 yb.insert(*iter);
00205         }
00206 }
00207 
00208 template <class X>
00209 double DESS<X>::ta()
00210 {
00211         return sigma;
00212 }
00213 
00214 } // end of namespace
00215 
00216 #endif