35 #ifndef LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_
36 #define LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_
38 #include "AbstractAssemblerSolverHybrid.hpp"
39 #include "AbstractDynamicLinearPdeSolver.hpp"
40 #include "AbstractLinearParabolicPdeSystemForCoupledOdeSystem.hpp"
41 #include "TetrahedralMesh.hpp"
42 #include "BoundaryConditionsContainer.hpp"
43 #include "AbstractOdeSystemForCoupledPdeSystem.hpp"
44 #include "CvodeAdaptor.hpp"
45 #include "BackwardEulerIvpOdeSolver.hpp"
46 #include "Warnings.hpp"
47 #include "VtkMeshWriter.hpp"
49 #include <boost/shared_ptr.hpp>
60 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM=ELEMENT_DIM,
unsigned PROBLEM_DIM=1>
116 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1)>
ComputeMatrixTerm(
117 c_vector<double, ELEMENT_DIM+1>& rPhi,
118 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
120 c_vector<double,PROBLEM_DIM>& rU,
121 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
135 c_vector<double, ELEMENT_DIM+1>& rPhi,
136 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
138 c_vector<double,PROBLEM_DIM>& rU,
139 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU,
190 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes=std::vector<AbstractOdeSystemForCoupledPdeSystem*>(),
191 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver=boost::shared_ptr<AbstractIvpOdeSolver>());
250 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
252 c_vector<double, ELEMENT_DIM+1>& rPhi,
253 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
255 c_vector<double,PROBLEM_DIM>& rU,
256 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
260 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1)> matrix_term = zero_matrix<double>(PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1));
263 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
265 double this_dudt_coefficient = mpPdeSystem->ComputeDuDtCoefficientFunction(rX, pde_index);
266 c_matrix<double, SPACE_DIM, SPACE_DIM> this_pde_diffusion_term = mpPdeSystem->ComputeDiffusionTerm(rX, pde_index, pElement);
267 c_matrix<double, 1*(ELEMENT_DIM+1), 1*(ELEMENT_DIM+1)> this_stiffness_matrix =
268 prod(trans(rGradPhi), c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>(prod(this_pde_diffusion_term, rGradPhi)) )
269 + timestep_inverse * this_dudt_coefficient * outer_prod(rPhi, rPhi);
271 for (
unsigned i=0; i<ELEMENT_DIM+1; i++)
273 for (
unsigned j=0; j<ELEMENT_DIM+1; j++)
275 matrix_term(i*PROBLEM_DIM + pde_index, j*PROBLEM_DIM + pde_index) = this_stiffness_matrix(i,j);
282 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
284 c_vector<double, ELEMENT_DIM+1>& rPhi,
285 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
287 c_vector<double,PROBLEM_DIM>& rU,
288 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU,
292 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> vector_term = zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
295 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
297 double this_dudt_coefficient = mpPdeSystem->ComputeDuDtCoefficientFunction(rX, pde_index);
298 double this_source_term = mpPdeSystem->ComputeSourceTerm(rX, rU, mInterpolatedOdeStateVariables, pde_index);
299 c_vector<double, ELEMENT_DIM+1> this_vector_term = (this_source_term + timestep_inverse*this_dudt_coefficient*rU(pde_index))* rPhi;
301 for (
unsigned i=0; i<ELEMENT_DIM+1; i++)
303 vector_term(i*PROBLEM_DIM + pde_index) = this_vector_term(i);
311 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
314 mInterpolatedOdeStateVariables.clear();
316 if (mOdeSystemsPresent)
318 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
319 mInterpolatedOdeStateVariables.resize(num_state_variables, 0.0);
323 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
326 if (mOdeSystemsPresent)
328 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
330 for (
unsigned i=0; i<num_state_variables; i++)
332 mInterpolatedOdeStateVariables[i] += phiI * mOdeSystemsAtNodes[pNode->
GetIndex()]->rGetStateVariables()[i];
337 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
340 if (this->mpLinearSystem == NULL)
342 unsigned preallocation = mpMesh->CalculateMaximumContainingElementsPerProcess() + ELEMENT_DIM;
348 preallocation *= PROBLEM_DIM;
355 this->mpLinearSystem =
new LinearSystem(initialSolution, preallocation);
358 assert(this->mpLinearSystem);
359 this->mpLinearSystem->SetMatrixIsSymmetric(
true);
360 this->mpLinearSystem->SetKspType(
"cg");
363 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
366 this->SetupGivenLinearSystem(currentSolution, computeMatrix, this->mpLinearSystem);
369 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
374 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes,
375 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver)
379 mpPdeSystem(pPdeSystem),
380 mOdeSystemsAtNodes(odeSystemsAtNodes),
381 mpOdeSolver(pOdeSolver),
383 mOdeSystemsPresent(false),
384 mClearOutputDirectory(false)
408 #endif //CHASTE_CVODE
413 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
416 if (mOdeSystemsPresent)
418 for (
unsigned i=0; i<mOdeSystemsAtNodes.size(); i++)
420 delete mOdeSystemsAtNodes[i];
425 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
428 if (mOdeSystemsPresent)
435 std::vector<double> current_soln_this_node(PROBLEM_DIM);
438 for (
unsigned node_index=0; node_index<mpMesh->GetNumNodes(); node_index++)
441 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
443 double current_soln_this_pde_this_node = soln_repl[PROBLEM_DIM*node_index + pde_index];
444 current_soln_this_node[pde_index] = current_soln_this_pde_this_node;
448 mOdeSystemsAtNodes[node_index]->SetPdeSolution(current_soln_this_node);
451 mpOdeSolver->SolveAndUpdateStateVariable(mOdeSystemsAtNodes[node_index], time, next_time, dt);
456 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
459 mClearOutputDirectory = clearDirectory;
460 this->mOutputDirectory = outputDirectory;
463 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
466 assert(samplingTimeStep >= this->mIdealTimeStep);
467 mSamplingTimeStep = samplingTimeStep;
470 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
474 if (this->mOutputDirectory ==
"")
476 EXCEPTION(
"SetOutputDirectory() must be called prior to SolveAndWriteResultsToFile()");
478 if (this->mTimesSet ==
false)
480 EXCEPTION(
"SetTimes() must be called prior to SolveAndWriteResultsToFile()");
482 if (this->mIdealTimeStep <= 0.0)
484 EXCEPTION(
"SetTimeStep() must be called prior to SolveAndWriteResultsToFile()");
488 EXCEPTION(
"SetSamplingTimeStep() must be called prior to SolveAndWriteResultsToFile()");
490 if (!this->mInitialCondition)
492 EXCEPTION(
"SetInitialCondition() must be called prior to SolveAndWriteResultsToFile()");
497 OutputFileHandler output_file_handler(this->mOutputDirectory, mClearOutputDirectory);
498 mpVtkMetaFile = output_file_handler.
OpenOutputFile(
"results.pvd");
499 *mpVtkMetaFile <<
"<?xml version=\"1.0\"?>\n";
500 *mpVtkMetaFile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
501 *mpVtkMetaFile <<
" <Collection>\n";
504 Vec initial_condition = this->mInitialCondition;
505 WriteVtkResultsToFile(initial_condition, 0);
508 TimeStepper stepper(this->mTstart, this->mTend, mSamplingTimeStep);
517 Vec soln = this->Solve();
520 if (this->mInitialCondition != initial_condition)
524 this->mInitialCondition = soln;
534 if (this->mInitialCondition != initial_condition)
538 this->mInitialCondition = initial_condition;
541 *mpVtkMetaFile <<
" </Collection>\n";
542 *mpVtkMetaFile <<
"</VTKFile>\n";
543 mpVtkMetaFile->close();
545 #define COVERAGE_IGNORE // We only test this in weekly builds
546 WARNING(
"VTK is not installed and is required for this functionality");
547 #undef COVERAGE_IGNORE
551 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
557 std::stringstream time;
558 time << numTimeStepsElapsed;
567 unsigned num_nodes = mpMesh->GetNumNodes();
568 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
571 std::vector<double> pde_index_data;
572 pde_index_data.resize(num_nodes, 0.0);
573 for (
unsigned node_index=0; node_index<num_nodes; node_index++)
575 pde_index_data[node_index] = solution_repl[PROBLEM_DIM*node_index + pde_index];
579 std::stringstream data_name;
580 data_name <<
"PDE variable " << pde_index;
581 mesh_writer.
AddPointData(data_name.str(), pde_index_data);
584 if (mOdeSystemsPresent)
592 std::vector<std::vector<double> > ode_data;
593 unsigned num_odes = mOdeSystemsAtNodes[0]->rGetStateVariables().size();
594 ode_data.resize(num_odes);
595 for (
unsigned ode_index=0; ode_index<num_odes; ode_index++)
597 ode_data[ode_index].resize(num_nodes, 0.0);
600 for (
unsigned node_index=0; node_index<num_nodes; node_index++)
602 std::vector<double> all_odes_this_node = mOdeSystemsAtNodes[node_index]->rGetStateVariables();
603 for (
unsigned i=0; i<num_odes; i++)
605 ode_data[i][node_index] = all_odes_this_node[i];
609 for (
unsigned ode_index=0; ode_index<num_odes; ode_index++)
611 std::vector<double> ode_index_data = ode_data[ode_index];
614 std::stringstream data_name;
615 data_name <<
"ODE variable " << ode_index;
616 mesh_writer.AddPointData(data_name.str(), ode_index_data);
620 mesh_writer.WriteFilesUsingMesh(*mpMesh);
621 *mpVtkMetaFile <<
" <DataSet timestep=\"";
622 *mpVtkMetaFile << numTimeStepsElapsed;
623 *mpVtkMetaFile <<
"\" group=\"\" part=\"0\" file=\"results_";
624 *mpVtkMetaFile << numTimeStepsElapsed;
625 *mpVtkMetaFile <<
".vtu\"/>\n";
629 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
632 return mOdeSystemsAtNodes[index];
void PrepareForSetupLinearSystem(Vec currentPdeSolution)
void InitialiseForSolve(Vec initialSolution=NULL)
c_vector< double, PROBLEM_DIM *(ELEMENT_DIM+1)> ComputeVectorTerm(c_vector< double, ELEMENT_DIM+1 > &rPhi, c_matrix< double, SPACE_DIM, ELEMENT_DIM+1 > &rGradPhi, ChastePoint< SPACE_DIM > &rX, c_vector< double, PROBLEM_DIM > &rU, c_matrix< double, PROBLEM_DIM, SPACE_DIM > &rGradU, Element< ELEMENT_DIM, SPACE_DIM > *pElement)
bool mClearOutputDirectory
void SetSamplingTimeStep(double samplingTimeStep)
LinearParabolicPdeSystemWithCoupledOdeSystemSolver(TetrahedralMesh< ELEMENT_DIM, SPACE_DIM > *pMesh, AbstractLinearParabolicPdeSystemForCoupledOdeSystem< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > *pPdeSystem, BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > *pBoundaryConditions, std::vector< AbstractOdeSystemForCoupledPdeSystem * > odeSystemsAtNodes=std::vector< AbstractOdeSystemForCoupledPdeSystem * >(), boost::shared_ptr< AbstractIvpOdeSolver > pOdeSolver=boost::shared_ptr< AbstractIvpOdeSolver >())
void ResetInterpolatedQuantities()
#define EXCEPTION(message)
~LinearParabolicPdeSystemWithCoupledOdeSystemSolver()
AbstractOdeSystemForCoupledPdeSystem * GetOdeSystemAtNode(unsigned index)
void AdvanceOneTimeStep()
const double DOUBLE_UNSET
c_matrix< double, PROBLEM_DIM *(ELEMENT_DIM+1), PROBLEM_DIM *(ELEMENT_DIM+1)> ComputeMatrixTerm(c_vector< double, ELEMENT_DIM+1 > &rPhi, c_matrix< double, SPACE_DIM, ELEMENT_DIM+1 > &rGradPhi, ChastePoint< SPACE_DIM > &rX, c_vector< double, PROBLEM_DIM > &rU, c_matrix< double, PROBLEM_DIM, SPACE_DIM > &rGradU, Element< ELEMENT_DIM, SPACE_DIM > *pElement)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
void SetOutputDirectory(std::string outputDirectory, bool clearDirectory=false)
static double GetNextTime()
BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > * mpBoundaryConditions
unsigned GetTotalTimeStepsTaken() const
static double GetPdeTimeStepInverse()
AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * mpMesh
static double GetPdeTimeStep()
void SetupLinearSystem(Vec currentSolution, bool computeMatrix)
std::vector< double > mInterpolatedOdeStateVariables
void IncrementInterpolatedQuantities(double phiI, const Node< SPACE_DIM > *pNode)
unsigned GetIndex() const
double GetNextTime() const
std::vector< AbstractOdeSystemForCoupledPdeSystem * > mOdeSystemsAtNodes
boost::shared_ptr< AbstractIvpOdeSolver > mpOdeSolver
void WriteVtkResultsToFile()
void AddPointData(std::string name, std::vector< double > data)
void SolveAndWriteResultsToFile()
AbstractLinearParabolicPdeSystemForCoupledOdeSystem< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > * mpPdeSystem