00001
00002 #include <CompuCell3D/Simulator.h>
00003 #include <CompuCell3D/Potts3D/Potts3D.h>
00004 #include <CompuCell3D/Field3D/Field3D.h>
00005 #include <CompuCell3D/Field3D/AdjacentNeighbor.h>
00006 #include <CompuCell3D/Automaton/Automaton.h>
00007 #include <BasicUtils/BasicClassGroup.h>
00008
00009
00010 using namespace CompuCell3D;
00011 using namespace std;
00012
00013 #define EXP_STL
00014 #include "ExternalPotentialPlugin.h"
00015
00016 namespace CompuCell3D {
00017
00019 ExternalPotentialPlugin::ExternalPotentialPlugin():lambdaVec(Coordinates3D<float>(0.,0.,0.)),xmlData(0)
00020 {}
00022 ExternalPotentialPlugin::~ExternalPotentialPlugin()
00023 {
00024 }
00026
00027 void ExternalPotentialPlugin::init(Simulator *_simulator, CC3DXMLElement *_xmlData){
00028
00029 xmlData=_xmlData;
00030 potts = _simulator->getPotts();
00031 cellFieldG=(WatchableField3D<CellG *> * )potts->getCellFieldG();
00032
00033
00034 potts->registerEnergyFunctionWithName(this,"ExternalPotential");
00035
00036 Dim3D fieldDim=potts->getCellFieldG()->getDim();
00037
00038
00039
00040
00041 adjNeighbor.initialize(fieldDim);
00042 adjNeighbor_ptr=&adjNeighbor;
00043
00044 if(potts->getBoundaryXName()=="Periodic"){
00045 adjNeighbor.setPeriodicX();
00046 }
00047 if(potts->getBoundaryYName()=="Periodic"){
00048 adjNeighbor.setPeriodicY();
00049 }
00050 if(potts->getBoundaryZName()=="Periodic"){
00051 adjNeighbor.setPeriodicZ();
00052 }
00053
00054 _simulator->registerSteerableObject(this);
00055
00056
00057
00058 }
00060
00061 void ExternalPotentialPlugin::extraInit(Simulator *_simulator){
00062
00063
00064
00065 update(xmlData,true);
00066 }
00067
00068
00070
00071
00072 void ExternalPotentialPlugin::update(CC3DXMLElement *_xmlData, bool _fullInitFlag){
00073
00074
00075 if(!_xmlData->getNumberOfChildren()){
00076 functionType=BYCELLID;
00077 }else{
00078 if(_xmlData->findElement("ExternalPotentialParameters"))
00079 functionType=BYCELLTYPE;
00080 else if (_xmlData->findElement("Lambda"))
00081 functionType=GLOBAL;
00082 else
00083 functionType=BYCELLID;
00084 }
00085
00086 Automaton *automaton=potts->getAutomaton();
00087 cerr<<"automaton="<<automaton<<endl;
00088
00089 switch(functionType){
00090 case BYCELLID:
00091
00092 changeEnergyFcnPtr=&ExternalPotentialPlugin::changeEnergyByCellId;
00093 break;
00094
00095 case BYCELLTYPE:
00096 {
00097 externalPotentialParamVector.clear();
00098 vector<int> typeIdVec;
00099 vector<ExternalPotentialParam> externalPotentialParamVectorTmp;
00100
00101 CC3DXMLElementList energyVec=_xmlData->getElements("ExternalPotentialParameters");
00102
00103 for (int i = 0 ; i<energyVec.size(); ++i){
00104 ExternalPotentialParam extPotentialParam;
00105
00106 extPotentialParam.lambdaVec.x=energyVec[i]->getAttributeAsDouble("x");
00107 extPotentialParam.lambdaVec.y=energyVec[i]->getAttributeAsDouble("y");
00108 extPotentialParam.lambdaVec.z=energyVec[i]->getAttributeAsDouble("z");
00109
00110 extPotentialParam.typeName=energyVec[i]->getAttribute("CellType");
00111 cerr<<"automaton="<<automaton<<endl;
00112 typeIdVec.push_back(automaton->getTypeId(extPotentialParam.typeName));
00113
00114 externalPotentialParamVectorTmp.push_back(extPotentialParam);
00115 }
00116 vector<int>::iterator pos=max_element(typeIdVec.begin(),typeIdVec.end());
00117 int maxTypeId=*pos;
00118 externalPotentialParamVector.assign(maxTypeId+1,ExternalPotentialParam());
00119 for (int i = 0 ; i < externalPotentialParamVectorTmp.size() ; ++i){
00120 externalPotentialParamVector[typeIdVec[i]]=externalPotentialParamVectorTmp[i];
00121 }
00122
00123
00124 changeEnergyFcnPtr=&ExternalPotentialPlugin::changeEnergyByCellType;
00125 }
00126 break;
00127
00128 case GLOBAL:
00129
00130 lambdaVec=Coordinates3D<float>(_xmlData->getFirstElement("Lambda")->getAttributeAsDouble("x"),
00131 _xmlData->getFirstElement("Lambda")->getAttributeAsDouble("y"),
00132 _xmlData->getFirstElement("Lambda")->getAttributeAsDouble("z")
00133 );
00134
00135 changeEnergyFcnPtr=&ExternalPotentialPlugin::changeEnergyGlobal;
00136 break;
00137
00138 default:
00139
00140 changeEnergyFcnPtr=&ExternalPotentialPlugin::changeEnergyByCellId;
00141 }
00142
00143 }
00144
00145
00146 double ExternalPotentialPlugin::changeEnergyGlobal(const Point3D &pt, const CellG *newCell,
00147 const CellG *oldCell)
00148 {
00149
00150
00151
00152 double deltaEnergyOld=0.0;
00153 double deltaEnergyNew=0.0;
00154 CellG *neighborPtr;
00155
00156 Dim3D fieldDim=cellFieldG->getDim();
00157
00158
00159 const vector<Point3D> & neighborsOffsetVec = adjNeighbor_ptr->getAdjFace2FaceNeighborOffsetVec(pt);
00160 unsigned int neighborSize=neighborsOffsetVec.size();
00161
00162 Point3D ptAdj;
00163
00164
00165
00166
00167 short prefferedCoordinate=pt.z+1;
00168
00169 Coordinates3D<short> deltaCoordinate(0,0,0);
00170
00172
00173
00174
00175
00176
00177 int counter=0;
00178 Point3D ptFlipNeighbor=potts->getFlipNeighbor();
00179 Point3D deltaFlip;
00180
00181 deltaFlip=pt;
00182 deltaFlip-=ptFlipNeighbor;
00183
00184 for(unsigned int i = 0 ; i < neighborSize ; ++i){
00185 ptAdj=pt;
00186 ptAdj+=neighborsOffsetVec[i];
00187
00188 if( cellFieldG->isValid(ptAdj) ){
00189 ++counter;
00190 neighborPtr=cellFieldG->get(ptAdj);
00191
00193 if( oldCell && neighborPtr!=oldCell){
00194
00195 deltaCoordinate.XRef()=(ptAdj.x-pt.x);
00196 deltaCoordinate.YRef()=(ptAdj.y-pt.y);
00197 deltaCoordinate.ZRef()=(ptAdj.z-pt.z);
00198
00199 if(fabs(static_cast<double>(deltaCoordinate.X()))>1){
00200
00201 deltaCoordinate.XRef()=
00202 ( deltaCoordinate.X()>0 ? -(deltaCoordinate.X()+1) % (fieldDim.x-1) :-(deltaCoordinate.X()-1) % (fieldDim.x-1) );
00203
00204
00205 }
00206
00207 if(fabs(static_cast<double>(deltaCoordinate.Y()))>1){
00208 deltaCoordinate.YRef()=
00209 ( deltaCoordinate.Y()>0 ? -(deltaCoordinate.Y()+1) % (fieldDim.y-1) :-(deltaCoordinate.Y()-1) % (fieldDim.y-1) );
00210 }
00211
00212
00213 if(fabs(static_cast<double>(deltaCoordinate.Z()))>1){
00214 deltaCoordinate.ZRef()=
00215 ( deltaCoordinate.Z()>0 ? -(deltaCoordinate.Z()+1) % (fieldDim.z-1) :-(deltaCoordinate.Z()-1) % (fieldDim.z-1) );
00216 }
00217 deltaEnergyOld+= deltaCoordinate.X()*lambdaVec.X()+
00218 deltaCoordinate.Y()*lambdaVec.Y()+
00219 deltaCoordinate.Z()*lambdaVec.Z();
00220
00221 }
00222
00224 if(newCell && neighborPtr!=newCell){
00225
00226 deltaCoordinate.XRef()=(ptAdj.x-pt.x);
00227 deltaCoordinate.YRef()=(ptAdj.y-pt.y);
00228 deltaCoordinate.ZRef()=(ptAdj.z-pt.z);
00229
00230 if(fabs(static_cast<double>(deltaCoordinate.X()))>1){
00231 deltaCoordinate.XRef()=
00232 ( deltaCoordinate.X()>0 ? -(deltaCoordinate.X()+1) % (fieldDim.x-1) :-(deltaCoordinate.X()-1) % (fieldDim.x-1) );
00233
00234 }
00235
00236 if(fabs(static_cast<double>(deltaCoordinate.Y()))>1){
00237 deltaCoordinate.YRef()=
00238 ( deltaCoordinate.Y()>0 ? -(deltaCoordinate.Y()+1) % (fieldDim.y-1) :-(deltaCoordinate.Y()-1) % (fieldDim.y-1) );
00239 }
00240
00241
00242 if(fabs(static_cast<double>(deltaCoordinate.Z()))>1){
00243 deltaCoordinate.ZRef()=
00244 ( deltaCoordinate.Z()>0 ? -(deltaCoordinate.Z()+1) % (fieldDim.z-1) :-(deltaCoordinate.Z()-1) % (fieldDim.z-1) );
00245 }
00246
00247 deltaEnergyNew+= deltaCoordinate.X()*lambdaVec.X()+
00248 deltaCoordinate.Y()*lambdaVec.Y()+
00249 deltaCoordinate.Z()*lambdaVec.Z();
00250
00251 }
00252
00253
00254 }
00255
00256 }
00257
00258
00259 return deltaEnergyNew-deltaEnergyOld;
00260
00261 }
00262
00263
00264 double ExternalPotentialPlugin::changeEnergyByCellType(const Point3D &pt, const CellG *newCell,
00265 const CellG *oldCell)
00266 {
00267
00268
00269
00270 double deltaEnergyOld=0.0;
00271 double deltaEnergyNew=0.0;
00272 CellG *neighborPtr;
00273
00274 Dim3D fieldDim=cellFieldG->getDim();
00275
00276
00277 const vector<Point3D> & neighborsOffsetVec = adjNeighbor_ptr->getAdjFace2FaceNeighborOffsetVec(pt);
00278 unsigned int neighborSize=neighborsOffsetVec.size();
00279
00280 Point3D ptAdj;
00281
00282
00283
00284
00285 short prefferedCoordinate=pt.z+1;
00286
00287 Coordinates3D<short> deltaCoordinate(0,0,0);
00288
00290
00291
00292
00293
00294
00295 int counter=0;
00296 Point3D ptFlipNeighbor=potts->getFlipNeighbor();
00297 Point3D deltaFlip;
00298
00299 deltaFlip=pt;
00300 deltaFlip-=ptFlipNeighbor;
00301
00302 for(unsigned int i = 0 ; i < neighborSize ; ++i){
00303 ptAdj=pt;
00304 ptAdj+=neighborsOffsetVec[i];
00305
00306 if( cellFieldG->isValid(ptAdj) ){
00307 ++counter;
00308 neighborPtr=cellFieldG->get(ptAdj);
00309
00311 if( oldCell && neighborPtr!=oldCell){
00312
00313 deltaCoordinate.XRef()=(ptAdj.x-pt.x);
00314 deltaCoordinate.YRef()=(ptAdj.y-pt.y);
00315 deltaCoordinate.ZRef()=(ptAdj.z-pt.z);
00316
00317 if(fabs(static_cast<double>(deltaCoordinate.X()))>1){
00318
00319 deltaCoordinate.XRef()=
00320 ( deltaCoordinate.X()>0 ? -(deltaCoordinate.X()+1) % (fieldDim.x-1) :-(deltaCoordinate.X()-1) % (fieldDim.x-1) );
00321
00322
00323 }
00324
00325 if(fabs(static_cast<double>(deltaCoordinate.Y()))>1){
00326 deltaCoordinate.YRef()=
00327 ( deltaCoordinate.Y()>0 ? -(deltaCoordinate.Y()+1) % (fieldDim.y-1) :-(deltaCoordinate.Y()-1) % (fieldDim.y-1) );
00328 }
00329
00330
00331 if(fabs(static_cast<double>(deltaCoordinate.Z()))>1){
00332 deltaCoordinate.ZRef()=
00333 ( deltaCoordinate.Z()>0 ? -(deltaCoordinate.Z()+1) % (fieldDim.z-1) :-(deltaCoordinate.Z()-1) % (fieldDim.z-1) );
00334 }
00335
00336 deltaEnergyOld+= deltaCoordinate.X()*externalPotentialParamVector[oldCell->type].lambdaVec.X()+
00337 deltaCoordinate.Y()*externalPotentialParamVector[oldCell->type].lambdaVec.Y()+
00338 deltaCoordinate.Z()*externalPotentialParamVector[oldCell->type].lambdaVec.Z();
00339
00340 }
00341
00343 if(newCell && neighborPtr!=newCell){
00344
00345 deltaCoordinate.XRef()=(ptAdj.x-pt.x);
00346 deltaCoordinate.YRef()=(ptAdj.y-pt.y);
00347 deltaCoordinate.ZRef()=(ptAdj.z-pt.z);
00348
00349 if(fabs(static_cast<double>(deltaCoordinate.X()))>1){
00350 deltaCoordinate.XRef()=
00351 ( deltaCoordinate.X()>0 ? -(deltaCoordinate.X()+1) % (fieldDim.x-1) :-(deltaCoordinate.X()-1) % (fieldDim.x-1) );
00352
00353 }
00354
00355 if(fabs(static_cast<double>(deltaCoordinate.Y()))>1){
00356 deltaCoordinate.YRef()=
00357 ( deltaCoordinate.Y()>0 ? -(deltaCoordinate.Y()+1) % (fieldDim.y-1) :-(deltaCoordinate.Y()-1) % (fieldDim.y-1) );
00358 }
00359
00360
00361 if(fabs(static_cast<double>(deltaCoordinate.Z()))>1){
00362 deltaCoordinate.ZRef()=
00363 ( deltaCoordinate.Z()>0 ? -(deltaCoordinate.Z()+1) % (fieldDim.z-1) :-(deltaCoordinate.Z()-1) % (fieldDim.z-1) );
00364 }
00365
00366 deltaEnergyNew+= deltaCoordinate.X()*externalPotentialParamVector[newCell->type].lambdaVec.X()+
00367 deltaCoordinate.Y()*externalPotentialParamVector[newCell->type].lambdaVec.Y()+
00368 deltaCoordinate.Z()*externalPotentialParamVector[newCell->type].lambdaVec.Z();
00369
00370 }
00371
00372
00373 }
00374
00375 }
00376
00377
00378 return deltaEnergyNew-deltaEnergyOld;
00379
00380 }
00381
00382 double ExternalPotentialPlugin::changeEnergyByCellId(const Point3D &pt, const CellG *newCell,
00383 const CellG *oldCell)
00384 {
00385
00386
00387
00388 double deltaEnergyOld=0.0;
00389 double deltaEnergyNew=0.0;
00390 CellG *neighborPtr;
00391
00392 Dim3D fieldDim=cellFieldG->getDim();
00393
00394
00395 const vector<Point3D> & neighborsOffsetVec = adjNeighbor_ptr->getAdjFace2FaceNeighborOffsetVec(pt);
00396 unsigned int neighborSize=neighborsOffsetVec.size();
00397
00398 Point3D ptAdj;
00399
00400
00401
00402
00403 short prefferedCoordinate=pt.z+1;
00404
00405 Coordinates3D<short> deltaCoordinate(0,0,0);
00406
00408
00409
00410
00411
00412
00413 int counter=0;
00414 Point3D ptFlipNeighbor=potts->getFlipNeighbor();
00415 Point3D deltaFlip;
00416
00417 deltaFlip=pt;
00418 deltaFlip-=ptFlipNeighbor;
00419
00420 for(unsigned int i = 0 ; i < neighborSize ; ++i){
00421 ptAdj=pt;
00422 ptAdj+=neighborsOffsetVec[i];
00423
00424 if( cellFieldG->isValid(ptAdj) ){
00425 ++counter;
00426 neighborPtr=cellFieldG->get(ptAdj);
00427
00429 if( oldCell && neighborPtr!=oldCell){
00430
00431 deltaCoordinate.XRef()=(ptAdj.x-pt.x);
00432 deltaCoordinate.YRef()=(ptAdj.y-pt.y);
00433 deltaCoordinate.ZRef()=(ptAdj.z-pt.z);
00434
00435 if(fabs(static_cast<double>(deltaCoordinate.X()))>1){
00436
00437 deltaCoordinate.XRef()=
00438 ( deltaCoordinate.X()>0 ? -(deltaCoordinate.X()+1) % (fieldDim.x-1) :-(deltaCoordinate.X()-1) % (fieldDim.x-1) );
00439
00440
00441 }
00442
00443 if(fabs(static_cast<double>(deltaCoordinate.Y()))>1){
00444 deltaCoordinate.YRef()=
00445 ( deltaCoordinate.Y()>0 ? -(deltaCoordinate.Y()+1) % (fieldDim.y-1) :-(deltaCoordinate.Y()-1) % (fieldDim.y-1) );
00446 }
00447
00448
00449 if(fabs(static_cast<double>(deltaCoordinate.Z()))>1){
00450 deltaCoordinate.ZRef()=
00451 ( deltaCoordinate.Z()>0 ? -(deltaCoordinate.Z()+1) % (fieldDim.z-1) :-(deltaCoordinate.Z()-1) % (fieldDim.z-1) );
00452 }
00453
00454 deltaEnergyOld+= deltaCoordinate.X()*oldCell->lambdaVecX+
00455 deltaCoordinate.Y()*oldCell->lambdaVecY+
00456 deltaCoordinate.Z()*oldCell->lambdaVecZ;
00457
00458 }
00459
00461 if(newCell && neighborPtr!=newCell){
00462
00463 deltaCoordinate.XRef()=(ptAdj.x-pt.x);
00464 deltaCoordinate.YRef()=(ptAdj.y-pt.y);
00465 deltaCoordinate.ZRef()=(ptAdj.z-pt.z);
00466
00467 if(fabs(static_cast<double>(deltaCoordinate.X()))>1){
00468 deltaCoordinate.XRef()=
00469 ( deltaCoordinate.X()>0 ? -(deltaCoordinate.X()+1) % (fieldDim.x-1) :-(deltaCoordinate.X()-1) % (fieldDim.x-1) );
00470
00471 }
00472
00473 if(fabs(static_cast<double>(deltaCoordinate.Y()))>1){
00474 deltaCoordinate.YRef()=
00475 ( deltaCoordinate.Y()>0 ? -(deltaCoordinate.Y()+1) % (fieldDim.y-1) :-(deltaCoordinate.Y()-1) % (fieldDim.y-1) );
00476 }
00477
00478
00479 if(fabs(static_cast<double>(deltaCoordinate.Z()))>1){
00480 deltaCoordinate.ZRef()=
00481 ( deltaCoordinate.Z()>0 ? -(deltaCoordinate.Z()+1) % (fieldDim.z-1) :-(deltaCoordinate.Z()-1) % (fieldDim.z-1) );
00482 }
00483
00484 deltaEnergyNew+= deltaCoordinate.X()*newCell->lambdaVecX+
00485 deltaCoordinate.Y()*newCell->lambdaVecY+
00486 deltaCoordinate.Z()*newCell->lambdaVecZ;
00487
00488 }
00489
00490
00491 }
00492
00493 }
00494
00495
00496 return deltaEnergyNew-deltaEnergyOld;
00497
00498 }
00499
00500
00501
00502 double ExternalPotentialPlugin::changeEnergy(const Point3D &pt, const CellG *newCell,
00503 const CellG *oldCell)
00504 {
00505
00506 return (this->*changeEnergyFcnPtr)(pt,newCell,oldCell);
00507
00508 }
00509
00510
00511
00513
00514
00515
00516 std::string ExternalPotentialPlugin::toString(){
00517 return "ExternalPotential";
00518 }
00519
00520
00521 std::string ExternalPotentialPlugin::steerableName(){
00522
00523 return toString();
00524 }
00526
00527
00528
00529 };