00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include"group-mobility.h"
00031 #include<node-core.h>
00032 #include<rng.h>
00033
00034
00035
00036
00037 static class GroupMobPositionClass : public TclClass {
00038 public:
00039 GroupMobPositionClass() : TclClass("Position/GroupMob") {}
00040 TclObject* create(int, const char*const*) {
00041 return (new GroupMobPosition());
00042 }
00043 } class_groupmobposition;
00044
00045
00046 void UpdatePosTimer::expire(Event *e)
00047 {
00048 module->update(Scheduler::instance().clock());
00049 }
00050
00051
00052
00053 GroupMobPosition::GroupMobPosition() :
00054 Position(),
00055 xFieldWidth_(0),
00056 yFieldWidth_(0),
00057 alpha_(0),
00058 speedMean_(0),
00059 sigmaSpeed_(0),
00060 speedM_(0),
00061 speedS_(0),
00062 eta_(0),
00063 charge_(0),
00064 memoryM_(0),
00065 memoryS_(0),
00066 bound_(REBOUNCE),
00067 updateTime_(0),
00068 debug_(0),
00069 speed_(0),
00070 leader_(0),
00071 updateTmr_(this)
00072 {
00073 bind("xFieldWidth_", &xFieldWidth_);
00074 bind("yFieldWidth_", &yFieldWidth_);
00075 bind("alpha_", &alpha_);
00076 bind("updateTime_", &updateTime_);
00077 bind("speedMean_",&speedMean_);
00078 bind("sigmaSpeed_",&sigmaSpeed_);
00079 bind("speedM_",&speedM_);
00080 bind("speedS_",&speedS_);
00081 bind("eta_",&eta_);
00082 bind("charge_",&charge_);
00083 bind("memoryM_",&memoryM_);
00084 bind("memoryS_",&memoryS_);
00085 bind("thetaMax_",&thetaMax_);
00086 bind("debug_", &debug_);
00087 }
00088
00089 GroupMobPosition::~GroupMobPosition()
00090 {
00091 }
00092
00093
00094 int GroupMobPosition::command(int argc, const char*const* argv)
00095 {
00096 Tcl& tcl = Tcl::instance();
00097 if (argc == 2)
00098 {
00099 if(strcasecmp(argv[1], "move") == 0)
00100 {
00101 if (updateTime_<0)
00102 {
00103 fprintf(stderr,"Error GroupMobPosition(constructor) updateTime_ <= 0");
00104 return TCL_ERROR;
00105 }
00106 speed_ = speedMean_;
00107 steps_ = memoryM_;
00108 gammaOld_ = RNG::defaultrng()->uniform_double() * (2*pi);
00109 updateTmr_.resched(updateTime_);
00110 return TCL_OK;
00111 }
00112 else if(strcasecmp(argv[1], "stop") == 0)
00113 {
00114 updateTmr_.cancel();
00115 return TCL_OK;
00116 }
00117 }
00118 else if(argc == 3)
00119 {
00120 if(strcasecmp(argv[1], "bound") == 0)
00121 {
00122 if (strcasecmp(argv[2],"SPHERIC")==0)
00123 bound_ = SPHERIC;
00124 else
00125 {
00126 if (strcasecmp(argv[2],"THOROIDAL")==0)
00127 bound_ = THOROIDAL;
00128 else
00129 {
00130 if (strcasecmp(argv[2],"HARDWALL")==0)
00131 bound_ = HARDWALL;
00132 else
00133 {
00134 if (strcasecmp(argv[2],"REBOUNCE")==0)
00135 bound_ = REBOUNCE;
00136 else
00137 {
00138 fprintf(stderr,"GMPosition::command(%s), unrecognized bound_ type (%s)\n",argv[1],argv[2]);
00139 exit(1);
00140 }
00141 }
00142 }
00143 }
00144 return TCL_OK;
00145 }
00146 else if(strcasecmp(argv[1], "leader") == 0)
00147 {
00148 Position* lead = (Position *)TclObject::lookup(argv[2]);
00149 leader_ = lead;
00150 return TCL_OK;
00151 }
00152 }
00153 return Position::command(argc, argv);
00154 }
00155
00156
00157 double GroupMobPosition::getX()
00158 {
00159 return (x_);
00160 }
00161
00162 double GroupMobPosition::getY()
00163 {
00164 return (y_);
00165 }
00166
00167
00168 double GroupMobPosition::distance(Position* pos1, Position* pos2)
00169 {
00170 double xdiff,ydiff;
00171 double dist;
00172
00173 xdiff = pos1->getX() - pos2->getX();
00174 ydiff = pos1->getY() - pos2->getY();
00175
00176
00177 if(bound_==SPHERIC){
00178 xdiff = (fabs(xdiff)<((xFieldWidth_)/2))? xdiff : (xFieldWidth_-fabs(xdiff));
00179 ydiff = (fabs(ydiff)<((yFieldWidth_)/2))? ydiff : (yFieldWidth_-fabs(ydiff));
00180 }
00181
00182 return (sqrt(xdiff*xdiff + ydiff*ydiff));
00183 }
00184
00185
00186 double GroupMobPosition::mirror_posx(double xnode, double xleader)
00187 {
00188
00189 double d, dref;
00190
00191 d = fabs(xnode - xleader);
00192 dref = (xFieldWidth_)/2.;
00193
00194
00195
00196
00197
00198
00199 if ( (d>dref) && (bound_==SPHERIC) )
00200 return ( xleader - (xFieldWidth_)*(sgn(xleader-xnode)) );
00201
00202 return xleader;
00203 }
00204
00205 double GroupMobPosition::mirror_posy(double ynode, double yleader)
00206 {
00207
00208 double d, dref;
00209
00210 d = fabs(ynode - yleader);
00211 dref = (yFieldWidth_)/2.;
00212
00213
00214
00215
00216
00217
00218 if ( (d>dref) && (bound_==SPHERIC) )
00219 return ( yleader - (yFieldWidth_)*(sgn(yleader-ynode)) );
00220
00221 return yleader;
00222 }
00223
00224
00225 double GroupMobPosition::MobGaussian(double avrg, double sigma)
00226 {
00227
00228 double x1, x2, w, y1;
00229 static double y2;
00230 static int use_last = 0;
00231
00232 if(sigma==0.0)
00233 return(avrg);
00234
00235 if (use_last) {
00236 y1 = y2;
00237 use_last = 0;
00238 }
00239 else {
00240 do {
00241 x1 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00242 x2 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00243 w = x1 * x1 + x2 * x2;
00244 } while ( w >= 1.0 );
00245
00246 w = sqrt( (-2.0 * log( w ) ) / w );
00247 y1 = x1 * w;
00248 y2 = x2 * w;
00249 use_last = 1;
00250 }
00251 if(y1*sigma+avrg<0.0)
00252 return(0.0);
00253 else
00254 return ((double)(y1*sigma+avrg));
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 void GroupMobPosition::update(double now)
00282 {
00283 if (debug_>10) printf("old pos (%f,%f)...", getX(), getY());
00284 double alpha,speed,gamma,rho,delta;
00285 int rmem;
00286 double newx,newy,xPrec,yPrec;
00287 double ro;
00288
00289 speed_ = speed_*(1.-eta_) +
00290 eta_*MobGaussian(speedMean_, sigmaSpeed_);
00291 rho = speed_ * updateTime_;
00292
00293 gamma = gammaOld_;
00294 if (steps_>=1) steps_--;
00295 else
00296 {
00297 rmem = (int)((RNG::defaultrng()->uniform_double()*2*memoryS_)-memoryS_);
00298 steps_ = (int)((rmem<memoryM_)?0:memoryM_+rmem);
00299 delta = (RNG::defaultrng()->uniform_double()*thetaMax_);
00300 gamma += 2*delta-thetaMax_;
00301 gammaOld_ = gamma;
00302 }
00303
00304 if (gamma>pi) gamma -= 2*pi;
00305 if (gamma<pi) gamma += 2*pi;
00306
00307
00308 x_ += rho*cos(gamma);
00309 y_ += rho*sin(gamma);
00310
00311
00312 if (leader_!=0)
00313 {
00314 double cx,cy,dist;
00315 double charge_g=0.8;
00316 double charge_l=0.8;
00317
00318 cx = mirror_posx(x_,leader_->getX());
00319 cy = mirror_posy(y_,leader_->getY());
00320
00321 dist = distance(leader_,this);
00322 if ((alpha_>0)&&(dist<1)) dist =1;
00323 rho = updateTime_*MobGaussian(speedM_,speedS_)*charge_*((GroupMobPosition*)leader_)->getCharge()*pow(dist,-alpha_);
00324
00325 if (cx-x_==0) gamma = pi/2*sgn((cy-y_));
00326 else gamma = atan((cy-y_)/(cx-x_));
00327 if ((cx-x_)<=0.0) gamma += (y_-cy)>=0.0?pi:-pi;
00328
00329 x_ += rho*cos(gamma);
00330 y_ += rho*sin(gamma);
00331
00332 }
00333
00334
00335
00336 xPrec= xprec_;
00337 yPrec= yprec_;
00338 newx = x_;
00339 newy = y_;
00340
00341
00342 if ((newy>yFieldWidth_) || (newy<0)){
00343 switch (bound_) {
00344 case SPHERIC: yPrec -=yFieldWidth_*(sgn(newy));
00345 newy -=yFieldWidth_*(sgn(newy));
00346 break;
00347 case THOROIDAL: xPrec = (xFieldWidth_/2) + xPrec - newx;
00348 yPrec = (yFieldWidth_/2) + yPrec - newy;
00349 newx = xFieldWidth_/2;
00350 newy = yFieldWidth_/2;
00351 break;
00352 case HARDWALL: newy=newy<0?0:yFieldWidth_; break;
00353 case REBOUNCE: if (newy>yFieldWidth_){
00354 newy = 2*yFieldWidth_ - newy;
00355 yPrec = 2*yFieldWidth_ - yPrec;
00356 }else{
00357 newy = 0 - newy;
00358 yPrec = 0 - yPrec;
00359 }
00360
00361 gammaOld_ *= -1;
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 break;
00372 }
00373 }
00374 if ((newx>xFieldWidth_) || (newx<0)){
00375 switch (bound_) {
00376 case SPHERIC: xPrec -=xFieldWidth_*(sgn(newx));
00377 newx -=xFieldWidth_*(sgn(newx));
00378 break;
00379 case THOROIDAL: xPrec = (xFieldWidth_/2) + xPrec - newx;
00380 yPrec = (yFieldWidth_/2) + yPrec - newy;
00381 newx = xFieldWidth_/2;
00382 newy = yFieldWidth_/2;
00383 break;
00384 case HARDWALL: newx=newx<0?0:xFieldWidth_; break;
00385 case REBOUNCE: if (newx>xFieldWidth_){
00386 newx = 2*xFieldWidth_ - newx;
00387 xPrec = 2*xFieldWidth_ - xPrec;
00388 }else{
00389 newx = 0 - newx;
00390 xPrec = 0 - xPrec;
00391 }
00392 if (newy==yPrec){
00393 if (newx>xPrec)
00394 gammaOld_ = 0;
00395 else
00396 gammaOld_ = pi;
00397 }else{
00398 if (newy>yPrec)
00399 gammaOld_ = pi - gammaOld_;
00400 else
00401 gammaOld_ = -pi - gammaOld_;
00402 }
00403 break;
00404 }
00405 }
00406
00407
00408 if ((newx<0.0)||(newx>xFieldWidth_)|| (newy<0.0)||(newy>yFieldWidth_))
00409 {
00410 puts("[GroupMobPosition::update] Errate position! Abort!");
00411 exit(1);
00412 }
00413
00414 x_ = newx;
00415 y_ = newy;
00416 if (debug_>10) printf("new pos (%f,%f)\n", x_, y_);
00417 updateTmr_.resched(updateTime_);
00418
00419
00420
00421
00422
00423
00424
00425 }