void KernelDiffusionSolver::writePixelValue(Point3D pt,float value, unsigned int coarseGrainFactor,ConcentrationField_t & _concentrationField){ if(fieldDim.x==1||fieldDim.y==1||fieldDim.z==1){//2D case if(fieldDim.x==1){ for (unsigned int y=pt.y ; y < pt.y+coarseGrainFactor ; ++y) for (unsigned int z=pt.z ; z < pt.z+coarseGrainFactor ; ++z){ _concentrationField.setDirectSwap(1,y+1,z+1,value); } }else if (fieldDim.y==1){ for (unsigned int x=pt.x ; x < pt.x+coarseGrainFactor ; ++x) for (unsigned int z=pt.z ; z < pt.z+coarseGrainFactor ; ++z){ _concentrationField.setDirectSwap(x+1,1,z+1,value); } }else if (fieldDim.z==1){ for (unsigned int x=pt.x ; x < pt.x+coarseGrainFactor ; ++x) for (unsigned int y=pt.y ; y < pt.y+coarseGrainFactor ; ++y){ _concentrationField.setDirectSwap(x+1,y+1,1,value); } } }else{//3D case for (unsigned int x=pt.x ; x < pt.x+coarseGrainFactor ; ++x) for (unsigned int y=pt.y ; y < pt.y+coarseGrainFactor ; ++y) for (unsigned int z=pt.z ; z < pt.z+coarseGrainFactor ; ++z){ _concentrationField.setDirectSwap(x+1,y+1,z+1,value); } } }
void DiffusionSolverFE_CPU_Implicit::diffuseSingleFieldImpl(ConcentrationField_t &concentrationField, DiffusionData &diffData) { // OPTIMIZATIONS - Maciej Swat // In addition to using contiguous array with scratch area being interlaced with concentration vector further optimizations are possible // In the most innner loop iof the FE solver one can replace maxNeighborIndex with hard coded number. Also instead of // Using boundary strategy to get offset array it is best to hard code offsets and access them directly // The downside is that in such a case one woudl have to write separate diffuseSingleField functions fdor 2D, 3D and for hex and square lattices. // However speedups may be worth extra effort. //cerr<<"shiftArray="<<concentrationField.getShiftArray()<<" shiftSwap="<<concentrationField.getShiftSwap()<<endl; //hard coded offsets for 3D square lattice //Point3D offsetArray[6]; //offsetArray[0]=Point3D(0,0,1); //offsetArray[1]=Point3D(0,1,0); //offsetArray[2]=Point3D(1,0,0); //offsetArray[3]=Point3D(0,0,-1); //offsetArray[4]=Point3D(0,-1,0); //offsetArray[5]=Point3D(-1,0,0); /// 'n' denotes neighbor ///this is the diffusion equation ///C_{xx}+C_{yy}+C_{zz}=(1/a)*C_{t} ///a - diffusivity - diffConst ///Finite difference method: ///T_{0,\delta \tau}=F*\sum_{i=1}^N T_{i}+(1-N*F)*T_{0} ///N - number of neighbors ///will have to double check this formula //HAVE TO WATCH OUT FOR SHARED/PRIVATE VARIABLES //cerr<<"Diffusion step"<<endl; //DiffusionData & diffData = diffSecrFieldTuppleVec[idx].diffData; //float diffConst=diffConstVec[idx]; //float decayConst=decayConstVec[idx]; //if(diffConst==0.0 && decayConst==0.0){ // return; //skip solving of the equation if diffusion and decay constants are 0 //} Automaton *automaton=potts->getAutomaton(); ConcentrationField_t * concentrationFieldPtr = &concentrationField; std::set<unsigned char>::iterator end_sitr=diffData.avoidTypeIdSet.end(); std::set<unsigned char>::iterator end_sitr_decay=diffData.avoidDecayInIdSet.end(); bool avoidMedium=false; bool avoidDecayInMedium=false; //the assumption is that medium has type ID 0 if(diffData.avoidTypeIdSet.find(automaton->getTypeId("Medium")) != end_sitr){ avoidMedium=true; } if(diffData.avoidDecayInIdSet.find(automaton->getTypeId("Medium")) != end_sitr_decay){ avoidDecayInMedium=true; } if(diffData.useBoxWatcher){ unsigned x_min=1,x_max=fieldDim.x+1; unsigned y_min=1,y_max=fieldDim.y+1; unsigned z_min=1,z_max=fieldDim.z+1; Dim3D minDimBW; Dim3D maxDimBW; Point3D minCoordinates=*(boxWatcherSteppable->getMinCoordinatesPtr()); Point3D maxCoordinates=*(boxWatcherSteppable->getMaxCoordinatesPtr()); //cerr<<"FLEXIBLE DIFF SOLVER maxCoordinates="<<maxCoordinates<<" minCoordinates="<<minCoordinates<<endl; x_min=minCoordinates.x+1; x_max=maxCoordinates.x+1; y_min=minCoordinates.y+1; y_max=maxCoordinates.y+1; z_min=minCoordinates.z+1; z_max=maxCoordinates.z+1; minDimBW=Dim3D(x_min,y_min,z_min); maxDimBW=Dim3D(x_max,y_max,z_max); pUtils->calculateFESolverPartitionWithBoxWatcher(minDimBW,maxDimBW); } //managing number of threads has to be done BEFORE parallel section otherwise undefined behavior will occur pUtils->prepareParallelRegionFESolvers(diffData.useBoxWatcher); Dim3D minDim; Dim3D maxDim; if(diffData.useBoxWatcher){ minDim=pUtils->getFESolverPartitionWithBoxWatcher(0).first; maxDim=pUtils->getFESolverPartitionWithBoxWatcher(0).second; }else{ minDim=pUtils->getFESolverPartition(0).first; maxDim=pUtils->getFESolverPartition(0).second; } EigenRealVector implicitSolution(h_celltype_field->getArraySize()), b(h_celltype_field->getArraySize()); for (int z = minDim.z; z < maxDim.z; z++) for (int y = minDim.y; y < maxDim.y; y++) for (int x = minDim.x; x < maxDim.x; x++){ b[flatExtInd(x,y,z, fieldDim)]=concentrationField.getDirect(x,y,z); } Implicit(concentrationField, diffData, b, implicitSolution); //Copying solution back to main concentration array for (int z = minDim.z; z < maxDim.z; z++) for (int y = minDim.y; y < maxDim.y; y++) for (int x = minDim.x; x < maxDim.x; x++){ float impl=std::max(Real_t(0.f), implicitSolution[flatExtInd(x,y,z, fieldDim)]); concentrationField.setDirectSwap(x,y,z, impl); } concentrationField.swapArrays(); //CheckConcentrationField(concentrationField); }