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);
	
		
}