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 "Warnings.hpp"
46#include "VtkMeshWriter.hpp"
48#include <boost/shared_ptr.hpp>
59template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM=ELEMENT_DIM,
unsigned PROBLEM_DIM=1>
116 c_vector<double, ELEMENT_DIM+1>& rPhi,
117 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
119 c_vector<double,PROBLEM_DIM>& rU,
120 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
134 c_vector<double, ELEMENT_DIM+1>& rPhi,
135 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
137 c_vector<double,PROBLEM_DIM>& rU,
138 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU,
189 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes=std::vector<AbstractOdeSystemForCoupledPdeSystem*>(),
190 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver=boost::shared_ptr<AbstractIvpOdeSolver>());
249template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
251 c_vector<double, ELEMENT_DIM+1>& rPhi,
252 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
254 c_vector<double,PROBLEM_DIM>& rU,
255 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
259 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));
262 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
265 c_matrix<double, SPACE_DIM, SPACE_DIM> this_pde_diffusion_term = mpPdeSystem->
ComputeDiffusionTerm(rX, pde_index, pElement);
266 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);
268 for (
unsigned i=0; i<ELEMENT_DIM+1; i++)
270 for (
unsigned j=0; j<ELEMENT_DIM+1; j++)
272 matrix_term(i*PROBLEM_DIM + pde_index, j*PROBLEM_DIM + pde_index) = this_stiffness_matrix(i,j);
279template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
281 c_vector<double, ELEMENT_DIM+1>& rPhi,
282 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
284 c_vector<double,PROBLEM_DIM>& rU,
285 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU,
289 c_vector<
double, PROBLEM_DIM*(ELEMENT_DIM+1)> vector_term;
290 vector_term = zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
293 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
296 double this_source_term = mpPdeSystem->
ComputeSourceTerm(rX, rU, mInterpolatedOdeStateVariables, pde_index);
297 c_vector<double, ELEMENT_DIM+1> this_vector_term;
298 this_vector_term = (this_source_term + timestep_inverse*this_dudt_coefficient*rU(pde_index))* rPhi;
300 for (
unsigned i=0; i<ELEMENT_DIM+1; i++)
302 vector_term(i*PROBLEM_DIM + pde_index) = this_vector_term(i);
309template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
312 mInterpolatedOdeStateVariables.clear();
314 if (mOdeSystemsPresent)
316 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
317 mInterpolatedOdeStateVariables.resize(num_state_variables, 0.0);
321template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
324 if (mOdeSystemsPresent)
326 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
328 for (
unsigned i=0; i<num_state_variables; i++)
330 mInterpolatedOdeStateVariables[i] += phiI * mOdeSystemsAtNodes[pNode->
GetIndex()]->rGetStateVariables()[i];
335template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
338 if (this->mpLinearSystem == NULL)
346 preallocation *= PROBLEM_DIM;
353 this->mpLinearSystem =
new LinearSystem(initialSolution, preallocation);
356 assert(this->mpLinearSystem);
357 this->mpLinearSystem->SetMatrixIsSymmetric(
true);
358 this->mpLinearSystem->SetKspType(
"cg");
361template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
364 this->SetupGivenLinearSystem(currentSolution, computeMatrix, this->mpLinearSystem);
367template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
372 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes,
373 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver)
377 mpPdeSystem(pPdeSystem),
378 mOdeSystemsAtNodes(odeSystemsAtNodes),
379 mpOdeSolver(pOdeSolver),
381 mOdeSystemsPresent(false),
382 mClearOutputDirectory(false)
407template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
410 if (mOdeSystemsPresent)
412 for (
unsigned i=0; i<mOdeSystemsAtNodes.size(); i++)
414 delete mOdeSystemsAtNodes[i];
419template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
422 if (mOdeSystemsPresent)
429 std::vector<double> current_soln_this_node(PROBLEM_DIM);
432 for (
unsigned node_index=0; node_index<mpMesh->
GetNumNodes(); node_index++)
435 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
437 double current_soln_this_pde_this_node = soln_repl[PROBLEM_DIM*node_index + pde_index];
438 current_soln_this_node[pde_index] = current_soln_this_pde_this_node;
442 mOdeSystemsAtNodes[node_index]->SetPdeSolution(current_soln_this_node);
445 mpOdeSolver->SolveAndUpdateStateVariable(mOdeSystemsAtNodes[node_index], time, next_time, dt);
450template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
453 mClearOutputDirectory = clearDirectory;
454 this->mOutputDirectory = outputDirectory;
457template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
460 assert(samplingTimeStep >= this->mIdealTimeStep);
461 mSamplingTimeStep = samplingTimeStep;
464template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
468 if (this->mOutputDirectory ==
"")
470 EXCEPTION(
"SetOutputDirectory() must be called prior to SolveAndWriteResultsToFile()");
472 if (this->mTimesSet ==
false)
474 EXCEPTION(
"SetTimes() must be called prior to SolveAndWriteResultsToFile()");
476 if (this->mIdealTimeStep <= 0.0)
478 EXCEPTION(
"SetTimeStep() must be called prior to SolveAndWriteResultsToFile()");
482 EXCEPTION(
"SetSamplingTimeStep() must be called prior to SolveAndWriteResultsToFile()");
484 if (!this->mInitialCondition)
486 EXCEPTION(
"SetInitialCondition() must be called prior to SolveAndWriteResultsToFile()");
490 OutputFileHandler output_file_handler(this->mOutputDirectory, mClearOutputDirectory);
491 mpVtkMetaFile = output_file_handler.
OpenOutputFile(
"results.pvd");
492 *mpVtkMetaFile <<
"<?xml version=\"1.0\"?>\n";
493 *mpVtkMetaFile <<
"<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
494 *mpVtkMetaFile <<
" <Collection>\n";
497 Vec initial_condition = this->mInitialCondition;
498 WriteVtkResultsToFile(initial_condition, 0);
501 TimeStepper stepper(this->mTstart, this->mTend, mSamplingTimeStep);
510 Vec soln = this->Solve();
513 if (this->mInitialCondition != initial_condition)
517 this->mInitialCondition = soln;
527 if (this->mInitialCondition != initial_condition)
531 this->mInitialCondition = initial_condition;
534 *mpVtkMetaFile <<
" </Collection>\n";
535 *mpVtkMetaFile <<
"</VTKFile>\n";
536 mpVtkMetaFile->close();
539template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
543 std::stringstream time;
544 time << numTimeStepsElapsed;
554 for (
unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
557 std::vector<double> pde_index_data;
558 pde_index_data.resize(num_nodes, 0.0);
559 for (
unsigned node_index=0; node_index<num_nodes; node_index++)
561 pde_index_data[node_index] = solution_repl[PROBLEM_DIM*node_index + pde_index];
565 std::stringstream data_name;
566 data_name <<
"PDE variable " << pde_index;
567 mesh_writer.
AddPointData(data_name.str(), pde_index_data);
570 if (mOdeSystemsPresent)
578 std::vector<std::vector<double> > ode_data;
579 unsigned num_odes = mOdeSystemsAtNodes[0]->rGetStateVariables().size();
580 ode_data.resize(num_odes);
581 for (
unsigned ode_index=0; ode_index<num_odes; ode_index++)
583 ode_data[ode_index].resize(num_nodes, 0.0);
586 for (
unsigned node_index=0; node_index<num_nodes; node_index++)
588 std::vector<double> all_odes_this_node = mOdeSystemsAtNodes[node_index]->rGetStateVariables();
589 for (
unsigned i=0; i<num_odes; i++)
591 ode_data[i][node_index] = all_odes_this_node[i];
595 for (
unsigned ode_index=0; ode_index<num_odes; ode_index++)
597 std::vector<double> ode_index_data = ode_data[ode_index];
600 std::stringstream data_name;
601 data_name <<
"ODE variable " << ode_index;
602 mesh_writer.
AddPointData(data_name.str(), ode_index_data);
607 *mpVtkMetaFile <<
" <DataSet timestep=\"";
608 *mpVtkMetaFile << numTimeStepsElapsed;
609 *mpVtkMetaFile <<
"\" group=\"\" part=\"0\" file=\"results_";
610 *mpVtkMetaFile << numTimeStepsElapsed;
611 *mpVtkMetaFile <<
".vtu\"/>\n";
614template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM,
unsigned PROBLEM_DIM>
617 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)