/home/nutarojj/adevs-2.3/include/adevs_par_simulator.h

00001 /***************
00002 Copyright (C) 2009 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_par_simulator_h_
00021 #define __adevs_par_simulator_h_
00022 #include "adevs_abstract_simulator.h"
00023 #include "adevs_msg_manager.h"
00024 #include "adevs_lp.h"
00025 #include "adevs_lp_graph.h"
00026 #include <cassert>
00027 #include <cstdlib>
00028 #include <iostream>
00029 #include <vector>
00030 
00031 namespace adevs
00032 {
00033 
00042 template <class X> class ParSimulator:
00043    public AbstractSimulator<X>  
00044 {
00045         public:
00056                 ParSimulator(Devs<X>* model, MessageManager<X>* msg_manager = NULL);
00063                 ParSimulator(Devs<X>* model, LpGraph& g, MessageManager<X>* msg_manager = NULL);
00065                 double nextEventTime();
00071                 void execUntil(double stop_time);
00077                 ~ParSimulator();
00078         private:
00079                 LogicalProcess<X>** lp;
00080                 int lp_count;
00081                 MessageManager<X>* msg_manager;
00082                 void init(Devs<X>* model);
00083                 void init_sim(Devs<X>* model, LpGraph& g);
00084 }; 
00085 
00086 template <class X>
00087 ParSimulator<X>::ParSimulator(Devs<X>* model, MessageManager<X>* msg_manager):
00088         AbstractSimulator<X>(),msg_manager(msg_manager)
00089 {
00090         // Create an all to all coupling
00091         lp_count = omp_get_max_threads();
00092         LpGraph g;
00093         for (int i = 0; i < lp_count; i++)
00094         {
00095                 for (int j = 0; j < lp_count; j++)
00096                 {
00097                         if (i != j)
00098                         {
00099                                 g.addEdge(i,j);
00100                                 g.addEdge(j,i);
00101                         }
00102                 }
00103         }
00104         init_sim(model,g);
00105 }
00106 
00107 template <class X>
00108 ParSimulator<X>::ParSimulator(Devs<X>* model, LpGraph& g, MessageManager<X>* msg_manager):
00109         AbstractSimulator<X>(),msg_manager(msg_manager)
00110 {
00111         init_sim(model,g);
00112 }
00113 
00114 template <class X>
00115 void ParSimulator<X>::init_sim(Devs<X>* model, LpGraph& g)
00116 {
00117         if (msg_manager == NULL) msg_manager = new NullMessageManager<X>();
00118         lp_count = omp_get_max_threads();
00119         lp = new LogicalProcess<X>*[lp_count];
00120         for (int i = 0; i < lp_count; i++)
00121         {
00122                 lp[i] = new LogicalProcess<X>(i,g.getI(i),g.getE(i),lp,this,msg_manager);
00123         }
00124         init(model);
00125 }
00126 
00127 template <class X>
00128 double ParSimulator<X>::nextEventTime()
00129 {
00130         Time tN = Time::Inf();
00131         for (int i = 0; i < lp_count; i++)
00132         {
00133                 if (lp[i]->getNextEventTime() < tN)
00134                         tN = lp[i]->getNextEventTime();
00135         }
00136         return tN.t;
00137 }
00138 
00139 template <class X>
00140 ParSimulator<X>::~ParSimulator<X>()
00141 {
00142         for (int i = 0; i < lp_count; i++)
00143                 delete lp[i];
00144         delete [] lp;
00145    delete msg_manager;  
00146 }
00147 
00148 template <class X>
00149 void ParSimulator<X>::execUntil(double tstop)
00150 {
00151         #pragma omp parallel
00152         {
00153                 lp[omp_get_thread_num()]->run(tstop);
00154         }
00155 }
00156 
00157 template <class X>
00158 void ParSimulator<X>::init(Devs<X>* model)
00159 {
00160         if (model->getProc() >= 0 && model->getProc() < lp_count)
00161         {
00162                 lp[model->getProc()]->addModel(model);
00163                 return;
00164         }
00165         Atomic<X>* a = model->typeIsAtomic();
00166         if (a != NULL)
00167         {
00168                 int lp_assign = a->getProc();
00169                 if (lp_assign < 0 || lp_assign >= lp_count)
00170                         lp_assign = ((long int)a)%lp_count;
00171                 lp[lp_assign]->addModel(a);
00172         }
00173         else
00174         {
00175                 Set<Devs<X>*> components;
00176                 model->typeIsNetwork()->getComponents(components);
00177                 typename Set<Devs<X>*>::iterator iter = components.begin();
00178                 for (; iter != components.end(); iter++)
00179                 {
00180                         init(*iter);
00181                 }
00182         }
00183 }
00184 
00185 } // end of namespace
00186 
00187 #endif

Generated on Tue Oct 6 20:46:41 2009 for adevs by  doxygen 1.4.7