36 #include "CellBasedPdeHandler.hpp"
37 #include "MeshBasedCellPopulationWithGhostNodes.hpp"
38 #include "NodeBasedCellPopulation.hpp"
39 #include "PottsBasedCellPopulation.hpp"
40 #include "VertexBasedCellPopulation.hpp"
41 #include "CaBasedCellPopulation.hpp"
42 #include "SimpleLinearEllipticSolver.hpp"
43 #include "CellBasedPdeSolver.hpp"
45 #include "VtkMeshWriter.hpp"
47 template<
unsigned DIM>
49 bool deleteMemberPointersInDestructor)
50 : mpCellPopulation(pCellPopulation),
51 mWriteAverageRadialPdeSolution(false),
52 mWriteDailyAverageRadialPdeSolution(false),
53 mAverageRadialSolutionVariableName(
""),
54 mSetBcsOnCoarseBoundary(true),
56 mpCoarsePdeMesh(NULL),
57 mDeleteMemberPointersInDestructor(deleteMemberPointersInDestructor)
64 template<
unsigned DIM>
73 if (mDeleteMemberPointersInDestructor)
75 for (
unsigned i=0; i<mPdeAndBcCollection.size(); i++)
77 delete mPdeAndBcCollection[i];
82 delete mpCoarsePdeMesh;
86 template<
unsigned DIM>
89 return mpCellPopulation;
92 template<
unsigned DIM>
95 return mpCoarsePdeMesh;
98 template<
unsigned DIM>
103 EXCEPTION(
"When adding more than one PDE to CellBasedPdeHandler set the dependent variable name using SetDependentVariableName(name).");
105 for (
unsigned i=0; i< mPdeAndBcCollection.size(); i++)
112 mPdeAndBcCollection.push_back(pPdeAndBc);
115 template<
unsigned DIM>
120 for (
unsigned i=0; i<mPdeAndBcCollection.size(); i++)
122 if (mPdeAndBcCollection[i]->rGetDependentVariableName() == rName)
124 return mPdeAndBcCollection[i]->GetSolution();
128 EXCEPTION(
"The PDE collection does not contain a PDE named " + rName);
132 assert(mPdeAndBcCollection.size()==1);
133 return mPdeAndBcCollection[0]->GetSolution();
137 template<
unsigned DIM>
140 if (mpCoarsePdeMesh == NULL)
142 EXCEPTION(
"InitialiseCellPdeElementMap() should only be called if mpCoarsePdeMesh is set up.");
145 mCellPdeElementMap.clear();
149 cell_iter != mpCellPopulation->End();
152 const ChastePoint<DIM>& r_position_of_cell = mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
153 unsigned elem_index = mpCoarsePdeMesh->GetContainingElementIndex(r_position_of_cell);
154 mCellPdeElementMap[*cell_iter] = elem_index;
158 template<
unsigned DIM>
163 cell_iter != mpCellPopulation->End();
166 const ChastePoint<DIM>& r_position_of_cell = mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
167 unsigned elem_index = mpCoarsePdeMesh->GetContainingElementIndexWithInitialGuess(r_position_of_cell, mCellPdeElementMap[*cell_iter]);
168 mCellPdeElementMap[*cell_iter] = elem_index;
172 template<
unsigned DIM>
184 UseCoarsePdeMesh(1, cuboid,
false);
188 if (PdeSolveNeedsCoarseMesh() && mpCoarsePdeMesh==NULL)
190 EXCEPTION(
"Trying to solve a PDE on a cell population that doesn't have a mesh. Try calling UseCoarsePdeMesh().");
193 if (mpCoarsePdeMesh != NULL)
195 InitialiseCellPdeElementMap();
206 if (mpCoarsePdeMesh != NULL)
208 mpVizPdeSolutionResultsFile = output_file_handler.
OpenOutputFile(
"results.vizcoarsepdesolution");
212 mpVizPdeSolutionResultsFile = output_file_handler.
OpenOutputFile(
"results.vizpdesolution");
215 if (mWriteAverageRadialPdeSolution)
217 mpAverageRadialPdeSolutionResultsFile = output_file_handler.
OpenOutputFile(
"radial_dist.dat");
221 mDirPath = outputDirectory;
226 template<
unsigned DIM>
232 mpVizPdeSolutionResultsFile->close();
233 if (mWriteAverageRadialPdeSolution)
236 mpAverageRadialPdeSolutionResultsFile->close();
241 template<
unsigned DIM>
244 if (mPdeAndBcCollection.empty())
246 EXCEPTION(
"mPdeAndBcCollection should be populated prior to calling UseCoarsePdeMesh().");
249 for (
unsigned pde_index=0; pde_index<mPdeAndBcCollection.size(); pde_index++)
251 if (mPdeAndBcCollection[pde_index]->HasAveragedSourcePde() ==
false && !
dynamic_cast<CaBasedCellPopulation<DIM>*
>(mpCellPopulation))
253 EXCEPTION(
"UseCoarsePdeMesh() should only be called if averaged-source PDEs are specified.");
265 mpCoarsePdeMesh->ConstructRegularSlabMesh(stepSize, meshCuboid.
GetWidth(0), meshCuboid.
GetWidth(1));
268 mpCoarsePdeMesh->ConstructRegularSlabMesh(stepSize, meshCuboid.
GetWidth(0), meshCuboid.
GetWidth(1), meshCuboid.
GetWidth(2));
274 if (centreOnCellPopulation)
277 c_vector<double,DIM> centre_of_coarse_mesh = zero_vector<double>(DIM);
278 for (
unsigned i=0; i<mpCoarsePdeMesh->GetNumNodes(); i++)
280 centre_of_coarse_mesh += mpCoarsePdeMesh->GetNode(i)->rGetLocation();
282 centre_of_coarse_mesh /= mpCoarsePdeMesh->GetNumNodes();
285 c_vector<double,DIM> centre_of_cell_population = mpCellPopulation->GetCentroidOfCellPopulation();
286 mpCoarsePdeMesh->Translate(centre_of_cell_population - centre_of_coarse_mesh);
296 c_vector<double,DIM> centre_of_coarse_mesh = zero_vector<double>(DIM);
297 for (
unsigned i=0; i<mpCoarsePdeMesh->GetNumNodes(); i++)
299 centre_of_coarse_mesh += mpCoarsePdeMesh->GetNode(i)->
rGetLocation();
301 centre_of_coarse_mesh /= mpCoarsePdeMesh->GetNumNodes();
303 mpCoarsePdeMesh->Translate(centre_of_cuboid - centre_of_coarse_mesh);
307 template<
unsigned DIM>
311 bool using_coarse_pde_mesh = (mpCoarsePdeMesh != NULL);
314 assert(!mPdeAndBcCollection.empty());
315 for (
unsigned pde_index=0; pde_index<mPdeAndBcCollection.size(); pde_index++)
317 assert(mPdeAndBcCollection[pde_index]);
318 assert(mPdeAndBcCollection[pde_index]->HasAveragedSourcePde() == using_coarse_pde_mesh ||
dynamic_cast<CaBasedCellPopulation<DIM>*
>(mpCellPopulation));
322 mpCellPopulation->Update();
326 if (using_coarse_pde_mesh)
328 p_mesh = mpCoarsePdeMesh;
337 for (
unsigned pde_index=0; pde_index<mPdeAndBcCollection.size(); pde_index++)
343 std::auto_ptr<BoundaryConditionsContainer<DIM,DIM,1> > p_bcc = ConstructBoundaryConditionsContainer(p_pde_and_bc, p_mesh);
346 PetscInt previous_solution_size = 0;
349 VecGetSize(p_pde_and_bc->
GetSolution(), &previous_solution_size);
353 bool is_previous_solution_size_correct = (previous_solution_size == (int)p_mesh->
GetNumNodes());
357 if (is_previous_solution_size_correct)
360 VecDuplicate(p_pde_and_bc->
GetSolution(), &initial_guess);
361 VecCopy(p_pde_and_bc->
GetSolution(), initial_guess);
367 if (!using_coarse_pde_mesh && p_pde_and_bc->
GetSolution())
369 assert(previous_solution_size != 0);
374 if (using_coarse_pde_mesh)
379 this->UpdateCellPdeElementMap();
392 if (is_previous_solution_size_correct)
394 p_pde_and_bc->
SetSolution(solver.Solve(initial_guess));
407 if (is_previous_solution_size_correct)
409 p_pde_and_bc->
SetSolution(solver.Solve(initial_guess));
423 cell_iter != mpCellPopulation->End();
426 unsigned node_index = mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
427 double solution_at_node = 0.0;
429 if (using_coarse_pde_mesh)
434 unsigned elem_index = mCellPdeElementMap[*cell_iter];
437 const ChastePoint<DIM>& node_location = mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
440 for (
unsigned i=0; i<DIM+1; i++)
443 solution_at_node += nodal_value * weights(i);
448 solution_at_node = solution_repl[node_index];
450 cell_iter->GetCellData()->SetItem(mPdeAndBcCollection[pde_index]->rGetDependentVariableName(), solution_at_node);
458 WritePdeSolution(p_time->
GetTime());
460 #define COVERAGE_IGNORE
461 if (!using_coarse_pde_mesh)
464 if (mWriteDailyAverageRadialPdeSolution)
471 WriteAverageRadialPdeSolution(p_time->
GetTime());
475 #undef COVERAGE_IGNORE
478 template<
unsigned DIM>
494 p_bcc->AddNeumannBoundaryCondition(*elem_iter, p_bc);
499 bool using_coarse_pde_mesh = (mpCoarsePdeMesh != NULL);
501 if (using_coarse_pde_mesh && !mSetBcsOnCoarseBoundary)
504 std::set<unsigned> coarse_element_indices_in_map;
506 cell_iter != mpCellPopulation->End();
509 coarse_element_indices_in_map.insert(mCellPdeElementMap[*cell_iter]);
513 std::set<unsigned> coarse_mesh_boundary_node_indices;
516 if (coarse_element_indices_in_map.find(i) == coarse_element_indices_in_map.end())
519 for (
unsigned j=0; j<DIM+1; j++)
522 coarse_mesh_boundary_node_indices.insert(node_index);
528 for (std::set<unsigned>::iterator iter = coarse_mesh_boundary_node_indices.begin();
529 iter != coarse_mesh_boundary_node_indices.end();
532 p_bcc->AddDirichletBoundaryCondition(pMesh->
GetNode(*iter), p_bc, 0,
false);
541 p_bcc->AddDirichletBoundaryCondition(*node_iter, p_bc);
549 template<
unsigned DIM>
553 unsigned old_element_index = mCellPdeElementMap[pCell];
556 std::set<unsigned> test_elements;
557 test_elements.insert(old_element_index);
559 Element<DIM,DIM>* p_element = mpCoarsePdeMesh->GetElement(old_element_index);
560 for (
unsigned local_index=0; local_index<DIM+1; local_index++)
562 std::set<unsigned> element_indices = p_element->
GetNode(local_index)->rGetContainingElementIndices();
563 for (std::set<unsigned>::iterator iter = element_indices.begin();
564 iter != element_indices.end();
567 test_elements.insert(*iter);
572 const ChastePoint<DIM>& r_cell_position = mpCellPopulation->GetLocationOfCellCentre(pCell);
573 unsigned new_element_index = mpCoarsePdeMesh->GetContainingElementIndex(r_cell_position,
false, test_elements);
576 mCellPdeElementMap[pCell] = new_element_index;
578 return new_element_index;
581 template<
unsigned DIM>
586 (*mpVizPdeSolutionResultsFile) << time <<
"\t";
591 if (DIM>1 && mpCoarsePdeMesh != NULL )
593 std::ostringstream time_string;
595 std::string results_file =
"pde_results_"+time_string.str();
600 for (
unsigned pde_index=0; pde_index<mPdeAndBcCollection.size(); pde_index++)
602 if (mpCoarsePdeMesh != NULL)
613 std::vector<double> pde_solution;
614 for (
unsigned i=0; i<mpCoarsePdeMesh->GetNumNodes(); i++)
616 pde_solution.push_back(solution_repl[i]);
625 for (
unsigned i=0; i<mpCoarsePdeMesh->GetNumNodes(); i++)
627 (*mpVizPdeSolutionResultsFile) << i <<
" ";
628 c_vector<double,DIM> location = mpCoarsePdeMesh->GetNode(i)->rGetLocation();
629 for (
unsigned k=0; k<DIM; k++)
631 (*mpVizPdeSolutionResultsFile) << location[k] <<
" ";
637 (*mpVizPdeSolutionResultsFile) << solution_repl[i] <<
" ";
649 cell_iter != mpCellPopulation->End();
652 unsigned node_index = mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
653 (*mpVizPdeSolutionResultsFile) << node_index <<
" ";
654 const c_vector<double,DIM>& position = mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
655 for (
unsigned i=0; i<DIM; i++)
657 (*mpVizPdeSolutionResultsFile) << position[i] <<
" ";
659 double solution = cell_iter->GetCellData()->GetItem(mPdeAndBcCollection[pde_index]->rGetDependentVariableName());
660 (*mpVizPdeSolutionResultsFile) << solution <<
" ";
664 (*mpVizPdeSolutionResultsFile) <<
"\n";
666 if (p_vtk_mesh_writer != NULL)
669 delete p_vtk_mesh_writer;
675 template<
unsigned DIM>
678 mAverageRadialSolutionVariableName = rName;
679 mWriteAverageRadialPdeSolution =
true;
680 mNumRadialIntervals = numRadialIntervals;
681 mWriteDailyAverageRadialPdeSolution = writeDailyResults;
684 template<
unsigned DIM>
687 mSetBcsOnCoarseBoundary = setBcsOnCoarseBoundary;
690 template<
unsigned DIM>
693 (*mpAverageRadialPdeSolutionResultsFile) << time <<
" ";
696 c_vector<double,DIM> centre = mpCellPopulation->GetCentroidOfCellPopulation();
699 std::map<double, CellPtr> radius_cell_map;
700 double max_distance_from_centre = 0.0;
702 cell_iter != mpCellPopulation->End();
705 double distance = norm_2(mpCellPopulation->GetLocationOfCellCentre(*cell_iter) - centre);
706 radius_cell_map[distance] = *cell_iter;
708 if (distance > max_distance_from_centre)
710 max_distance_from_centre = distance;
715 std::vector<double> radius_intervals;
716 for (
unsigned i=0; i<mNumRadialIntervals; i++)
718 double upper_radius = max_distance_from_centre*((
double) i+1)/((
double) mNumRadialIntervals);
719 radius_intervals.push_back(upper_radius);
723 double lower_radius = 0.0;
724 for (
unsigned i=0; i<mNumRadialIntervals; i++)
726 unsigned counter = 0;
727 double average_solution = 0.0;
729 for (std::map<double, CellPtr>::iterator iter = radius_cell_map.begin(); iter != radius_cell_map.end(); ++iter)
731 if (iter->first > lower_radius && iter->first <= radius_intervals[i])
733 average_solution += (iter->second)->GetCellData()->GetItem(mAverageRadialSolutionVariableName);
739 average_solution /= (
double) counter;
743 (*mpAverageRadialPdeSolutionResultsFile) << radius_intervals[i] <<
" " << average_solution <<
" ";
744 lower_radius = radius_intervals[i];
746 (*mpAverageRadialPdeSolutionResultsFile) <<
"\n";
749 template<
unsigned DIM>
752 double solution_at_point = 0.0;
754 unsigned pde_index = UINT_MAX;
757 for (
unsigned i=0; i<mPdeAndBcCollection.size(); i++)
759 if (mPdeAndBcCollection[i]->rGetDependentVariableName() == rVariable)
765 if (pde_index == UINT_MAX)
767 EXCEPTION(
"Tried to get the solution of a variable name: " + rVariable +
". There is no PDE with that variable.");
773 if (mpCoarsePdeMesh != NULL)
776 unsigned elem_index = mpCoarsePdeMesh->GetContainingElementIndex(
ChastePoint<DIM>(rPoint));
777 p_containing_element = mpCoarsePdeMesh->GetElement(elem_index);
785 p_containing_element = p_tetrahedral_mesh->
GetElement(elem_index);
793 for (
unsigned i=0; i<DIM+1; i++)
796 solution_at_point += nodal_value * weights(i);
805 return solution_at_point;
808 template<
unsigned DIM>
811 return mWriteAverageRadialPdeSolution;
814 template<
unsigned DIM>
817 return mWriteDailyAverageRadialPdeSolution;
820 template<
unsigned DIM>
823 return mSetBcsOnCoarseBoundary;
826 template<
unsigned DIM>
829 return mNumRadialIntervals;
832 template<
unsigned DIM>
835 std::string type = GetIdentifier();
837 *rParamsFile <<
"\t\t<" << type <<
">\n";
838 *rParamsFile <<
"\t\t<WriteAverageRadialPdeSolution>" << mWriteAverageRadialPdeSolution <<
"</WriteAverageRadialPdeSolution>\n";
839 *rParamsFile <<
"\t\t<WriteDailyAverageRadialPdeSolution>" << mWriteDailyAverageRadialPdeSolution <<
"</WriteDailyAverageRadialPdeSolution>\n";
840 *rParamsFile <<
"\t\t<SetBcsOnCoarseBoundary>" << mSetBcsOnCoarseBoundary <<
"</SetBcsOnCoarseBoundary>\n";
841 *rParamsFile <<
"\t\t<NumRadialIntervals>" << mNumRadialIntervals <<
"</NumRadialIntervals>\n";
842 *rParamsFile <<
"\t\t</" << type <<
">\n";
845 template<
unsigned DIM>
860 template class CellBasedPdeHandler<2>;
861 template class CellBasedPdeHandler<3>;
double GetPdeSolutionAtPoint(const c_vector< double, DIM > &rPoint, const std::string &rVariable)
bool GetWriteAverageRadialPdeSolution()
bool IsNeumannBoundaryCondition()
bool PdeSolveNeedsCoarseMesh()
c_vector< double, DIM > & rGetLocation()
void SetSolution(Vec solution)
BoundaryElementIterator GetBoundaryElementIteratorBegin() const
unsigned GetNumRadialIntervals()
unsigned GetNodeGlobalIndex(unsigned localIndex) const
virtual ~CellBasedPdeHandler()
void AddPdeAndBc(PdeAndBoundaryConditions< DIM > *pPdeAndBc)
void ConstructRegularSlabMesh(double spaceStep, double width, double height=0, double depth=0)
CellBasedPdeHandler(AbstractCellPopulation< DIM > *pCellPopulation, bool deleteMemberPointersInDestructor=false)
Node< SPACE_DIM > * GetNode(unsigned index) const
virtual unsigned GetNumElements() const
#define EXCEPTION(message)
static SimulationTime * Instance()
Element< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
virtual unsigned GetNumNodes() const
unsigned GetTimeStepsElapsed() const
bool HasAveragedSourcePde()
unsigned GetNumRealCells()
unsigned FindCoarseElementContainingCell(CellPtr pCell)
BoundaryNodeIterator GetBoundaryNodeIteratorBegin() const
double GetTimeStep() const
virtual void UseCoarsePdeMesh(double stepSize, ChasteCuboid< DIM > meshCuboid, bool centreOnCellPopulation=false)
void SetImposeBcsOnCoarseBoundary(bool setBcsOnCoarseBoundary)
void UpdateCellPdeElementMap()
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
void WriteFilesUsingMesh(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, bool keepOriginalElementIndexing=true)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
const ChastePoint< SPACE_DIM > & rGetUpperCorner() const
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
virtual void SolvePdeAndWriteResultsToFile(unsigned samplingTimestepMultiple)
void WriteAverageRadialPdeSolution(double time)
std::string & rGetDependentVariableName()
void OpenResultsFiles(std::string outputDirectory)
const unsigned UNSIGNED_UNSET
unsigned GetContainingElementIndex(const ChastePoint< SPACE_DIM > &rTestPoint, bool strict=false, std::set< unsigned > testElements=std::set< unsigned >(), bool onlyTryWithTestElements=false)
TetrahedralMesh< DIM, DIM > * GetCoarsePdeMesh()
AbstractCellPopulation< DIM > * mpCellPopulation
virtual void OutputParameters(out_stream &rParamsFile)
double GetWidth(unsigned rDimension) const
virtual std::auto_ptr< BoundaryConditionsContainer< DIM, DIM, 1 > > ConstructBoundaryConditionsContainer(PdeAndBoundaryConditions< DIM > *pPdeAndBc, TetrahedralMesh< DIM, DIM > *pMesh)
void SetWriteAverageRadialPdeSolution(const std::string &rName, unsigned numRadialIntervals=10, bool writeDailyResults=false)
AbstractBoundaryCondition< DIM > * GetBoundaryCondition() const
bool GetImposeBcsOnCoarseBoundary()
virtual void WritePdeSolution(double time)
BoundaryNodeIterator GetBoundaryNodeIteratorEnd() const
AbstractLinearEllipticPde< DIM, DIM > * GetPde()
virtual void WriteFilesUsingMesh(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, bool keepOriginalElementIndexing=true)
void SetUpSourceTermsForAveragedSourcePde(TetrahedralMesh< DIM, DIM > *pMesh, std::map< CellPtr, unsigned > *pCellPdeElementMap=NULL)
c_vector< double, SPACE_DIM+1 > CalculateInterpolationWeights(const ChastePoint< SPACE_DIM > &rTestPoint)
bool GetWriteDailyAverageRadialPdeSolution()
void InitialiseCellPdeElementMap()
void AddPointData(std::string name, std::vector< double > data)
const AbstractCellPopulation< DIM > * GetCellPopulation() const
BoundaryElementIterator GetBoundaryElementIteratorEnd() const
virtual Vec GetPdeSolution(const std::string &rName="")
const ChastePoint< SPACE_DIM > & rGetLowerCorner() const