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>
60template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM=ELEMENT_DIM,
unsigned PROBLEM_DIM=1>
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>());
250template<
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++)
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 = prod(trans(rGradPhi), c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>(prod(this_pde_diffusion_term, rGradPhi)) ) + timestep_inverse * this_dudt_coefficient * outer_prod(rPhi, rPhi);
269 for (
unsigned i=0; i<ELEMENT_DIM+1; i++)
271 for (
unsigned j=0; j<ELEMENT_DIM+1; j++)
273 matrix_term(i*PROBLEM_DIM + pde_index, j*PROBLEM_DIM + pde_index) = this_stiffness_matrix(i,j);
280template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
282 c_vector<double, ELEMENT_DIM+1>& rPhi,
283 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
285 c_vector<double,PROBLEM_DIM>& rU,
286 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU,
290 c_vector<
double, PROBLEM_DIM*(ELEMENT_DIM+1)> vector_term;
291 vector_term = zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
294 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
297 double this_source_term = mpPdeSystem->
ComputeSourceTerm(rX, rU, mInterpolatedOdeStateVariables, pde_index);
298 c_vector<double, ELEMENT_DIM+1> this_vector_term;
299 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);
310template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
313 mInterpolatedOdeStateVariables.clear();
315 if (mOdeSystemsPresent)
317 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
318 mInterpolatedOdeStateVariables.resize(num_state_variables, 0.0);
322template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
325 if (mOdeSystemsPresent)
327 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
329 for (
unsigned i=0; i<num_state_variables; i++)
331 mInterpolatedOdeStateVariables[i] += phiI * mOdeSystemsAtNodes[pNode->
GetIndex()]->rGetStateVariables()[i];
336template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
339 if (this->mpLinearSystem == NULL)
347 preallocation *= PROBLEM_DIM;
354 this->mpLinearSystem =
new LinearSystem(initialSolution, preallocation);
357 assert(this->mpLinearSystem);
358 this->mpLinearSystem->SetMatrixIsSymmetric(
true);
359 this->mpLinearSystem->SetKspType(
"cg");
362template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
365 this->SetupGivenLinearSystem(currentSolution, computeMatrix, this->mpLinearSystem);
368template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
373 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes,
374 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver)
378 mpPdeSystem(pPdeSystem),
379 mOdeSystemsAtNodes(odeSystemsAtNodes),
380 mpOdeSolver(pOdeSolver),
382 mOdeSystemsPresent(false),
383 mClearOutputDirectory(false)
412template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
415 if (mOdeSystemsPresent)
417 for (
unsigned i=0; i<mOdeSystemsAtNodes.size(); i++)
419 delete mOdeSystemsAtNodes[i];
424template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
427 if (mOdeSystemsPresent)
434 std::vector<double> current_soln_this_node(PROBLEM_DIM);
437 for (
unsigned node_index=0; node_index<mpMesh->
GetNumNodes(); node_index++)
440 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
442 double current_soln_this_pde_this_node = soln_repl[PROBLEM_DIM*node_index + pde_index];
443 current_soln_this_node[pde_index] = current_soln_this_pde_this_node;
447 mOdeSystemsAtNodes[node_index]->SetPdeSolution(current_soln_this_node);
450 mpOdeSolver->SolveAndUpdateStateVariable(mOdeSystemsAtNodes[node_index], time, next_time, dt);
455template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
458 mClearOutputDirectory = clearDirectory;
459 this->mOutputDirectory = outputDirectory;
462template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
465 assert(samplingTimeStep >= this->mIdealTimeStep);
466 mSamplingTimeStep = samplingTimeStep;
469template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
473 if (this->mOutputDirectory ==
"")
475 EXCEPTION(
"SetOutputDirectory() must be called prior to SolveAndWriteResultsToFile()");
477 if (this->mTimesSet ==
false)
479 EXCEPTION(
"SetTimes() must be called prior to SolveAndWriteResultsToFile()");
481 if (this->mIdealTimeStep <= 0.0)
483 EXCEPTION(
"SetTimeStep() must be called prior to SolveAndWriteResultsToFile()");
487 EXCEPTION(
"SetSamplingTimeStep() must be called prior to SolveAndWriteResultsToFile()");
489 if (!this->mInitialCondition)
491 EXCEPTION(
"SetInitialCondition() must be called prior to SolveAndWriteResultsToFile()");
496 OutputFileHandler output_file_handler(this->mOutputDirectory, mClearOutputDirectory);
497 mpVtkMetaFile = output_file_handler.
OpenOutputFile(
"results.pvd");
498 *mpVtkMetaFile <<
"<?xml version=\"1.0\"?>\n";
499 *mpVtkMetaFile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
500 *mpVtkMetaFile <<
" <Collection>\n";
503 Vec initial_condition = this->mInitialCondition;
504 WriteVtkResultsToFile(initial_condition, 0);
507 TimeStepper stepper(this->mTstart, this->mTend, mSamplingTimeStep);
516 Vec soln = this->Solve();
519 if (this->mInitialCondition != initial_condition)
523 this->mInitialCondition = soln;
533 if (this->mInitialCondition != initial_condition)
537 this->mInitialCondition = initial_condition;
540 *mpVtkMetaFile <<
" </Collection>\n";
541 *mpVtkMetaFile <<
"</VTKFile>\n";
542 mpVtkMetaFile->close();
545 WARNING(
"VTK is not installed and is required for this functionality");
550template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
556 std::stringstream time;
557 time << numTimeStepsElapsed;
567 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
570 std::vector<double> pde_index_data;
571 pde_index_data.resize(num_nodes, 0.0);
572 for (
unsigned node_index=0; node_index<num_nodes; node_index++)
574 pde_index_data[node_index] = solution_repl[PROBLEM_DIM*node_index + pde_index];
578 std::stringstream data_name;
579 data_name <<
"PDE variable " << pde_index;
580 mesh_writer.
AddPointData(data_name.str(), pde_index_data);
583 if (mOdeSystemsPresent)
591 std::vector<std::vector<double> > ode_data;
592 unsigned num_odes = mOdeSystemsAtNodes[0]->rGetStateVariables().size();
593 ode_data.resize(num_odes);
594 for (
unsigned ode_index=0; ode_index<num_odes; ode_index++)
596 ode_data[ode_index].resize(num_nodes, 0.0);
599 for (
unsigned node_index=0; node_index<num_nodes; node_index++)
601 std::vector<double> all_odes_this_node = mOdeSystemsAtNodes[node_index]->rGetStateVariables();
602 for (
unsigned i=0; i<num_odes; i++)
604 ode_data[i][node_index] = all_odes_this_node[i];
608 for (
unsigned ode_index=0; ode_index<num_odes; ode_index++)
610 std::vector<double> ode_index_data = ode_data[ode_index];
613 std::stringstream data_name;
614 data_name <<
"ODE variable " << ode_index;
615 mesh_writer.
AddPointData(data_name.str(), ode_index_data);
620 *mpVtkMetaFile <<
" <DataSet timestep=\"";
621 *mpVtkMetaFile << numTimeStepsElapsed;
622 *mpVtkMetaFile <<
"\" group=\"\" part=\"0\" file=\"results_";
623 *mpVtkMetaFile << numTimeStepsElapsed;
624 *mpVtkMetaFile <<
".vtu\"/>\n";
628template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
631 return mOdeSystemsAtNodes[index];
const double DOUBLE_UNSET
#define EXCEPTION(message)
BoundaryConditionsContainer< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > * mpBoundaryConditions
virtual double ComputeSourceTerm(const ChastePoint< SPACE_DIM > &rX, c_vector< double, PROBLEM_DIM > &rU, std::vector< double > &rOdeSolution, unsigned pdeIndex)=0
virtual c_matrix< double, SPACE_DIM, SPACE_DIM > ComputeDiffusionTerm(const ChastePoint< SPACE_DIM > &rX, unsigned pdeIndex, Element< ELEMENT_DIM, SPACE_DIM > *pElement=NULL)=0
virtual double ComputeDuDtCoefficientFunction(const ChastePoint< SPACE_DIM > &rX, unsigned pdeIndex)=0
virtual unsigned GetNumNodes() const
unsigned CalculateMaximumContainingElementsPerProcess() const
void SolveAndWriteResultsToFile()
AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * mpMesh
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()
void IncrementInterpolatedQuantities(double phiI, const Node< SPACE_DIM > *pNode)
std::vector< AbstractOdeSystemForCoupledPdeSystem * > mOdeSystemsAtNodes
void PrepareForSetupLinearSystem(Vec currentPdeSolution)
boost::shared_ptr< AbstractIvpOdeSolver > mpOdeSolver
void SetOutputDirectory(std::string outputDirectory, bool clearDirectory=false)
void SetupLinearSystem(Vec currentSolution, bool computeMatrix)
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)
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)
void SetSamplingTimeStep(double samplingTimeStep)
std::vector< double > mInterpolatedOdeStateVariables
AbstractOdeSystemForCoupledPdeSystem * GetOdeSystemAtNode(unsigned index)
void InitialiseForSolve(Vec initialSolution=NULL)
~LinearParabolicPdeSystemWithCoupledOdeSystemSolver()
void WriteVtkResultsToFile()
AbstractLinearParabolicPdeSystemForCoupledOdeSystem< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > * mpPdeSystem
bool mClearOutputDirectory
unsigned GetIndex() const
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static double GetPdeTimeStep()
static double GetPdeTimeStepInverse()
static double GetNextTime()
unsigned GetTotalTimeStepsTaken() const
void AdvanceOneTimeStep()
double GetNextTime() const
void AddPointData(std::string name, std::vector< double > data)
void WriteFilesUsingMesh(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, bool keepOriginalElementIndexing=true)