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 00036 template <class X> class DESS: public Atomic<X> 00037 { 00038 public: 00040 DESS(); 00046 virtual void evolve_func(double h) = 0; 00054 virtual double next_event_func(bool& is_event) = 0; 00059 virtual void discrete_action_func(const Bag<X>& xb) = 0; 00065 virtual void discrete_output_func(Bag<X>& yb) = 0; 00075 virtual void state_changed() = 0; 00077 void delta_int(); 00079 void delta_ext(double e, const Bag<X>& xb); 00081 void delta_conf(const Bag<X>& xb); 00083 void output_func(Bag<X>& yb); 00085 double ta(); 00087 virtual ~DESS(){} 00088 00089 private: 00090 // Time until the next event 00091 double sigma; 00092 // The phase can be step, event, or output 00093 enum { DESS_STEP, DESS_EVENT, DESS_OUTPUT } phase; 00094 // Empty bag for internal events 00095 Bag<X> empty_bag; 00096 // Temporary bag for discrete output values 00097 Bag<X> ytmp; 00098 }; 00099 00100 template <class X> 00101 DESS<X>::DESS() 00102 { 00103 sigma = 0.0; 00104 phase = DESS_STEP; 00105 } 00106 00107 template <class X> 00108 void DESS<X>::delta_int() 00109 { 00110 if (phase == DESS_OUTPUT) 00111 { 00112 ytmp.clear(); 00113 bool event = false; 00114 sigma = next_event_func(event); 00115 if (event) phase = DESS_EVENT; 00116 else phase = DESS_STEP; 00117 } 00118 else 00119 { 00120 // Evolve the continuous variables 00121 evolve_func(sigma); 00122 // Notify derived class of state change 00123 state_changed(); 00124 // If this is an internal discrete event 00125 if (phase == DESS_EVENT) 00126 { 00127 // Get the output 00128 discrete_output_func(ytmp); 00129 // Change the state 00130 discrete_action_func(empty_bag); 00131 // Notify derived class of the event 00132 state_changed(); 00133 phase = DESS_OUTPUT; 00134 sigma = 0.0; 00135 } 00136 // Otherwise, just schedule the next event or 00137 // integration step 00138 else 00139 { 00140 bool event = false; 00141 sigma = next_event_func(event); 00142 if (event) phase = DESS_EVENT; 00143 else phase = DESS_STEP; 00144 } 00145 } 00146 } 00147 00148 template <class X> 00149 void DESS<X>::delta_ext(double e, const Bag<X>& xb) 00150 { 00151 // Update the continuous variables 00152 evolve_func(e); 00153 // Notify the derived class 00154 state_changed(); 00155 // Apply the discrete state change function 00156 discrete_action_func(xb); 00157 // Notify the derived class again 00158 state_changed(); 00159 // Schedule the next step or event 00160 bool event = false; 00161 sigma = next_event_func(event); 00162 if (event) phase = DESS_EVENT; 00163 else phase = DESS_STEP; 00164 } 00165 00166 template <class X> 00167 void DESS<X>::delta_conf(const Bag<X>& xb) 00168 { 00169 // If it is not a state event, then this is just an input coinciding with 00170 // some book keeping operations 00171 if (phase == DESS_OUTPUT || phase == DESS_STEP) 00172 { 00173 ytmp.clear(); 00174 delta_ext(sigma,xb); 00175 } 00176 // Confluence of a state/time event an external input requires special 00177 // handling 00178 else if (phase == DESS_EVENT) 00179 { 00180 // Update the continuous variables 00181 evolve_func(sigma); 00182 // Notify the derived class 00183 state_changed(); 00184 // Compute the output 00185 discrete_output_func(ytmp); 00186 // Compute the discrete state change 00187 discrete_action_func(xb); 00188 // Notify the derived class 00189 state_changed(); 00190 // Send the output 00191 phase = DESS_OUTPUT; 00192 sigma = 0.0; 00193 } 00194 } 00195 00196 template <class X> 00197 void DESS<X>::output_func(Bag<X>& yb) 00198 { 00199 typename Bag<X>::iterator iter = ytmp.begin(); 00200 for (; iter != ytmp.end(); iter++) 00201 { 00202 yb.insert(*iter); 00203 } 00204 } 00205 00206 template <class X> 00207 double DESS<X>::ta() 00208 { 00209 return sigma; 00210 } 00211 00212 } // end of namespace 00213 00214 #endif