00001
00002
00003 #include <CompuCell3D/Simulator.h>
00004 #include <CompuCell3D/Automaton/Automaton.h>
00005 #include <CompuCell3D/Potts3D/Potts3D.h>
00006 #include <CompuCell3D/Potts3D/CellInventory.h>
00007 #include <CompuCell3D/Field3D/WatchableField3D.h>
00008 #include <CompuCell3D/Field3D/Field3DImpl.h>
00009 #include <CompuCell3D/Field3D/Field3D.h>
00010 #include <BasicUtils/BasicClassGroup.h>
00011 #include <CompuCell3D/Field3D/Field3D.h>
00012
00013 #include <BasicUtils/BasicString.h>
00014 #include <BasicUtils/BasicException.h>
00015 #include <BasicUtils/BasicRandomNumberGenerator.h>
00016 #include <string>
00017 #include <cmath>
00018 #include <iostream>
00019 #include <fstream>
00020 #include <sstream>
00021
00022 using namespace CompuCell3D;
00023 using namespace std;
00024
00025 #define EXP_STL
00026 #include "ReactionDiffusionSolverFE_SavHog.h"
00028 ReactionDiffusionSolverFE_SavHog::ReactionDiffusionSolverFE_SavHog()
00029 : DiffusableVector<float>(),deltaX(1.0),deltaT(1.0)
00030 {
00031 imposeDiffusionBox=false;
00032 dumpFrequency=0;
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 }
00046 ReactionDiffusionSolverFE_SavHog::~ReactionDiffusionSolverFE_SavHog()
00047 {
00048
00049 }
00050
00051 void ReactionDiffusionSolverFE_SavHog::update(CC3DXMLElement *_xmlData, bool _fullInitFlag) {
00052
00053 fieldNameVector.clear();
00054
00055 if(_xmlData->findElement("DeltaX"))
00056 deltaX=_xmlData->getFirstElement("DeltaX")->getDouble();
00057
00058 if(_xmlData->findElement("DeltaT"))
00059 deltaT=_xmlData->getFirstElement("DeltaT")->getDouble();
00060
00061 if(_xmlData->findElement("DiffusionConstant"))
00062 diffConst=_xmlData->getFirstElement("DiffusionConstant")->getDouble();
00063
00064 if(_xmlData->findElement("DecayConstant"))
00065 decayConst=_xmlData->getFirstElement("DecayConstant")->getDouble();
00066
00067 if(_xmlData->findElement("MaxDiffusionZ"))
00068 maxDiffusionZ=_xmlData->getFirstElement("MaxDiffusionZ")->getUInt();
00069
00070 if(_xmlData->findElement("DumpResults"))
00071 dumpFrequency=_xmlData->getFirstElement("DumpResults")->getAttributeAsUInt("Frequency");
00072
00073 if(_xmlData->findElement("fFunctionParameters")){
00074 C1 = _xmlData->getFirstElement("fFunctionParameters")->getAttributeAsDouble("C1");
00075 C2 = _xmlData->getFirstElement("fFunctionParameters")->getAttributeAsDouble("C2");
00076 C3 = _xmlData->getFirstElement("fFunctionParameters")->getAttributeAsDouble("C3");
00077 a = _xmlData->getFirstElement("fFunctionParameters")->getAttributeAsDouble("a");
00078 }
00079
00080 if(_xmlData->findElement("epsFunctionParameters")){
00081 eps1 = _xmlData->getFirstElement("epsFunctionParameters")->getAttributeAsDouble("eps1");
00082 eps2 = _xmlData->getFirstElement("epsFunctionParameters")->getAttributeAsDouble("eps2");
00083 eps3 = _xmlData->getFirstElement("epsFunctionParameters")->getAttributeAsDouble("eps3");
00084 }
00085
00086 if(_xmlData->findElement("IntervalParameters")){
00087 c1 = _xmlData->getFirstElement("IntervalParameters")->getAttributeAsDouble("c1");
00088 c2 = _xmlData->getFirstElement("IntervalParameters")->getAttributeAsDouble("c2");
00089 }
00090
00091 if(_xmlData->findElement("RefractorinessParameters")){
00092 k = _xmlData->getFirstElement("RefractorinessParameters")->getAttributeAsDouble("k");
00093 b = _xmlData->getFirstElement("RefractorinessParameters")->getAttributeAsDouble("b");
00094 }
00095
00096 if(_xmlData->findElement("MinDiffusionBoxCorner")){
00097 minDiffusionBoxCorner.x = _xmlData->getFirstElement("MinDiffusionBoxCorner")->getAttributeAsUInt("x");
00098 minDiffusionBoxCorner.y = _xmlData->getFirstElement("MinDiffusionBoxCorner")->getAttributeAsUInt("y");
00099 minDiffusionBoxCorner.z = _xmlData->getFirstElement("MinDiffusionBoxCorner")->getAttributeAsUInt("z");
00100 }
00101 if(_xmlData->findElement("MaxDiffusionBoxCorner")){
00102 maxDiffusionBoxCorner.x = _xmlData->getFirstElement("MaxDiffusionBoxCorner")->getAttributeAsUInt("x");
00103 maxDiffusionBoxCorner.y = _xmlData->getFirstElement("MaxDiffusionBoxCorner")->getAttributeAsUInt("y");
00104 maxDiffusionBoxCorner.z = _xmlData->getFirstElement("MaxDiffusionBoxCorner")->getAttributeAsUInt("z");
00105 }
00106 if(_xmlData->findElement("NumberOfFields")){
00107 numberOfFields = _xmlData->getFirstElement("NumberOfFields")->getUInt();
00108 numberOfFieldsDeclared=true;
00109 }
00110
00111 CC3DXMLElementList fieldNameXMLVec=_xmlData->getElements("FieldName");
00112 for(unsigned i = 0 ; i < fieldNameXMLVec.size() ; ++i){
00113 fieldNameVector.push_back(fieldNameXMLVec[i]->getText());
00114 }
00115
00116
00117 ASSERT_OR_THROW("You are trying to define more field that you declared!",fieldNameVector.size()<=numberOfFields);
00118 ASSERT_OR_THROW("You need to declare how many fields you will be using.\n Use <NumberOfFields>N</NumberOfFields> syntax before listing any fields.\n N denotes number of fields",numberOfFieldsDeclared);
00119
00120 }
00121
00123 void ReactionDiffusionSolverFE_SavHog::init(Simulator *simulator, CC3DXMLElement *_xmlData) {
00124
00125
00126
00127
00128
00129
00130
00131
00132 simPtr=simulator;
00133 potts = simulator->getPotts();
00134 automaton=potts->getAutomaton();
00135
00136 update(_xmlData,true);
00137
00138
00140 cellInventoryPtr=& potts->getCellInventory();
00141
00143 cellFieldG=(WatchableField3D<CellG*> *)potts->getCellFieldG();
00144 fieldDim=cellFieldG->getDim();
00145
00146
00147 workFieldDim=Dim3D(fieldDim.x+2,fieldDim.y+2,fieldDim.z+2);
00148 allocateDiffusableFieldVector(3, workFieldDim);
00149 for (int i=0; i<fieldNameVector.size() ;++i){
00150
00151 concentrationFieldNameVector[i] = fieldNameVector[i];
00153
00154 simPtr->registerConcentrationField(concentrationFieldNameVector[i] , concentrationFieldVector[i]);
00155 }
00156 if(minDiffusionBoxCorner==maxDiffusionBoxCorner)
00157 imposeDiffusionBox=false;
00158 else
00159 imposeDiffusionBox=true;
00160
00162 diffusePtr=&ReactionDiffusionSolverFE_SavHog::diffuse;
00163 simulator->registerSteerableObject(this);
00164
00165
00166
00167 }
00168
00170 void ReactionDiffusionSolverFE_SavHog::start() {
00171
00172 dt_dx2=deltaT/(deltaX*deltaX);
00173 initializeConcentration();
00174
00175
00176 }
00177
00179
00180 void ReactionDiffusionSolverFE_SavHog::initializeConcentration(){
00181
00182
00183 BasicRandomNumberGenerator *rand = BasicRandomNumberGenerator::getInstance();
00184
00185
00186 CellInventory::cellInventoryIterator cInvItr;
00187
00188 CellG * cell;
00189 map<CellG *,float> concentrationMap;
00190 map<CellG *,float> refractorinessMap;
00191
00192 float concentrationMin=0.5;
00193 float concentrationMax=1.0;
00194
00195 float refractorinessMin=1.0;
00196 float refractorinessMax=2.0;
00197
00198 float randomConcentration;
00199 float randomRefractoriness;
00200
00201
00202 float x,y,z;
00203
00204 for(cInvItr=cellInventoryPtr->cellInventoryBegin() ; cInvItr !=cellInventoryPtr->cellInventoryEnd() ;++cInvItr ){
00205
00206 cell=*cInvItr;
00207 if(cell->type!=automaton->getTypeId("Ground") && cell->type!=automaton->getTypeId("Wall")){
00208
00209 randomConcentration=fabs(concentrationMax-concentrationMin)*rand->getRatio()+concentrationMin;
00210 randomRefractoriness=fabs(refractorinessMax-refractorinessMin)*rand->getRatio()+refractorinessMin;
00211
00212 concentrationMap.insert(make_pair(cell,randomConcentration));
00213 refractorinessMap.insert(make_pair(cell,randomRefractoriness));
00214 }
00215
00216 }
00217 Point3D pt;
00218 CellG * currentCellPtr;
00219 map<CellG *,float>::iterator concentrationMapItr;
00220 map<CellG *,float>::iterator refractorinessMapItr;
00221
00222 Array3D_t & concentrationArray0 = concentrationFieldVector[0]->getContainer();
00223 Array3D_t & concentrationArray1 = concentrationFieldVector[1]->getContainer();
00224
00225
00226
00227 for (int z = 1; z < workFieldDim.z-1; z++)
00228 for (int y = 1; y < workFieldDim.y-1; y++)
00229 for (int x = 1; x < workFieldDim.x-1; x++){
00230
00231 pt=Point3D(x-1,y-1,z-1);
00232
00233 currentCellPtr=cellFieldG->get(pt);
00234 if(!currentCellPtr) continue;
00235
00236
00237 if(currentCellPtr->type!=automaton->getTypeId("Autocycling"))continue;
00238
00239 concentrationMapItr=concentrationMap.find(currentCellPtr);
00240 if(concentrationMapItr!=concentrationMap.end()){
00241 concentrationArray0[x][y][z]=concentrationMapItr->second;
00242 }
00243
00244 refractorinessMapItr=refractorinessMap.find(currentCellPtr);
00245 if(refractorinessMapItr!=refractorinessMap.end()){
00246 concentrationArray1[x][y][z]=refractorinessMapItr->second;
00247 }
00248
00249
00250 }
00251
00252
00253
00254 }
00255
00257 void ReactionDiffusionSolverFE_SavHog::step(const unsigned int _currentStep) {
00258 currentStep=_currentStep;
00259
00260 (this->*diffusePtr)();
00261
00262 if(dumpFrequency && !(_currentStep % dumpFrequency )){
00263 dumpResults(_currentStep);
00264 }
00265
00266 }
00267
00269 void ReactionDiffusionSolverFE_SavHog::diffuse() {
00271
00275
00280
00281
00282 Point3D pt, n;
00283 unsigned int token = 0;
00284 double distance;
00285 CellG * currentCellPtr=0,*nCell=0;
00286
00287 short currentCellType=0;
00288 float concentrationSum=0.0;
00289 float updatedConcentration=0.0;
00290
00291 float currentRefract=0.0;
00292 float updatedRefract=0.0;
00293
00294 float currentConcentration=0.0;
00295 short neighborCounter=0;
00296
00297 unsigned char autocyclingType=automaton->getTypeId("Autocycling");
00298 unsigned char presporeType=automaton->getTypeId("Prespore");
00299 unsigned char prestalkType=automaton->getTypeId("Prestalk");
00300 unsigned char wallType=automaton->getTypeId("Wall");
00301
00302
00303
00304 float F;
00305
00306
00307 Array3D_t & concentrationArray0 = concentrationFieldVector[0]->getContainer();
00308 Array3D_t & concentrationArray1 = concentrationFieldVector[1]->getContainer();
00309 Array3D_t & scratchArray = concentrationFieldVector[2]->getContainer();
00310
00311
00312 F=diffConst;
00313
00314 for (int z = 1; z < workFieldDim.z-1; z++)
00315 for (int y = 1; y < workFieldDim.y-1; y++)
00316 for (int x = 1; x < workFieldDim.x-1; x++){
00317 pt=Point3D(x-1,y-1,z-1);
00318
00319 currentCellPtr=cellFieldG->get(pt);
00322 if(!currentCellPtr){
00323
00324 if(imposeDiffusionBox)
00325 if(!insideDiffusionBox(pt)) continue;
00326
00327 }
00328 updatedConcentration=0.0;
00329 updatedRefract=0.0;
00330 concentrationSum=0.0;
00331 neighborCounter=0;
00332
00334 const std::vector<Point3D> & offsetVecRef=boundaryStrategy->getOffsetVec(pt);
00335 for (int i = 0 ; i<=maxNeighborIndex ; ++i ){
00336 const Point3D & offset = offsetVecRef[i];
00337 n=pt+offset;
00338
00339
00340
00341 nCell = cellFieldG->get(n);
00342
00343 if(imposeDiffusionBox)
00344 if(!insideDiffusionBox(n) && !nCell) continue;
00345
00346 concentrationSum += concentrationArray0[x+offset.x][y+offset.y][z+offset.z];
00347 ++neighborCounter;
00348
00349 }
00350
00351 currentConcentration = concentrationArray0[x][y][z];
00352 currentRefract = concentrationArray1[x][y][z];
00353
00354 if(
00355 currentCellPtr &&
00356 (
00357 currentCellPtr->type==autocyclingType||
00358 currentCellPtr->type==presporeType||
00359 currentCellPtr->type==prestalkType
00360 )
00361
00362 ){
00363
00364 updatedConcentration = dt_dx2*F*(concentrationSum - neighborCounter*currentConcentration)
00365 -deltaT*(f(currentConcentration)+currentRefract)
00366 +currentConcentration;
00367 }
00368 else {
00369 if(currentCellPtr && currentCellPtr->type==wallType){
00370 updatedConcentration =currentConcentration;
00371 }else {
00372
00373 updatedConcentration = dt_dx2*F*(concentrationSum - neighborCounter*currentConcentration)
00374 +currentConcentration;
00375 }
00376
00377 }
00378
00379
00380 scratchArray[x][y][z]=updatedConcentration;
00381
00382
00384
00385 if(currentCellPtr && currentCellPtr->type==autocyclingType){
00386 updatedRefract = deltaT*eps(currentConcentration)*(k*currentConcentration-b-currentRefract)+currentRefract;
00387 concentrationArray1[x][y][z]=updatedRefract;
00388 }
00389 else if(currentCellPtr &&
00390 (currentCellPtr->type==prestalkType || currentCellPtr->type==presporeType ))
00391 {
00392 updatedRefract = deltaT*eps(currentConcentration)*(k*currentConcentration-currentRefract)+currentRefract;
00393 concentrationArray1[x][y][z]=updatedRefract;
00394 }
00395 else{
00396
00397 }
00398
00399 }
00401 scrarch2Concentration(concentrationFieldVector[2],concentrationFieldVector[0]);
00402
00403
00404 }
00406 void ReactionDiffusionSolverFE_SavHog::scrarch2Concentration( ConcentrationField_t *scratchField, ConcentrationField_t *concentrationField){
00407
00408 scratchField->switchContainersQuick(*(concentrationField));
00409
00410
00411 }
00412
00414 void ReactionDiffusionSolverFE_SavHog::outputField( std::ostream & _out, ConcentrationField_t *_concentrationField){
00415 Point3D pt;
00416 float tempValue;
00417
00418 for (pt.z = 0; pt.z < fieldDim.z; pt.z++)
00419 for (pt.y = 0; pt.y < fieldDim.y; pt.y++)
00420 for (pt.x = 0; pt.x < fieldDim.x; pt.x++){
00421 tempValue=_concentrationField->get(pt);
00422 _out<<pt<<" "<<tempValue<<endl;
00423 }
00424 }
00426
00427 void ReactionDiffusionSolverFE_SavHog::dumpResults(unsigned int _step){
00428 ofstream out;
00429 ostringstream fileNameActivator;
00430 fileNameActivator<<"Activator"<<_step<<".txt";
00431 out.open(fileNameActivator.str().c_str());
00432
00433 outputField(out,concentrationFieldVector[0]);
00434 out.close();
00435
00436 ostringstream fileNameInhibitor;
00437 fileNameInhibitor<<"Inhibitor"<<_step<<".txt";
00438 out.open(fileNameInhibitor.str().c_str());
00439
00440 outputField(out,concentrationFieldVector[1]);
00441
00442 out.close();
00443
00444 }
00445
00446 std::string ReactionDiffusionSolverFE_SavHog::toString(){
00447 return "ReactionDiffusionSolverFE_SavHog";
00448 }
00449
00450 std::string ReactionDiffusionSolverFE_SavHog::steerableName(){
00451 return toString();
00452 }
00453