00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_
00036 #define LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_
00037
00038 #include "AbstractAssemblerSolverHybrid.hpp"
00039 #include "AbstractDynamicLinearPdeSolver.hpp"
00040 #include "AbstractLinearParabolicPdeSystemForCoupledOdeSystem.hpp"
00041 #include "TetrahedralMesh.hpp"
00042 #include "BoundaryConditionsContainer.hpp"
00043 #include "AbstractOdeSystemForCoupledPdeSystem.hpp"
00044 #include "CvodeAdaptor.hpp"
00045 #include "BackwardEulerIvpOdeSolver.hpp"
00046 #include "Warnings.hpp"
00047 #include "VtkMeshWriter.hpp"
00048
00049 #include <boost/shared_ptr.hpp>
00050
00060 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM=ELEMENT_DIM, unsigned PROBLEM_DIM=1>
00061 class LinearParabolicPdeSystemWithCoupledOdeSystemSolver
00062 : public AbstractAssemblerSolverHybrid<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NORMAL>,
00063 public AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>
00064 {
00065 private:
00066
00068 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* mpMesh;
00069
00071 AbstractLinearParabolicPdeSystemForCoupledOdeSystem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpPdeSystem;
00072
00074 std::vector<AbstractOdeSystemForCoupledPdeSystem*> mOdeSystemsAtNodes;
00075
00077 std::vector<double> mInterpolatedOdeStateVariables;
00078
00080 boost::shared_ptr<AbstractIvpOdeSolver> mpOdeSolver;
00081
00087 double mSamplingTimeStep;
00088
00090 bool mOdeSystemsPresent;
00091
00093 out_stream mpVtkMetaFile;
00094
00099 bool mClearOutputDirectory;
00100
00104 void WriteVtkResultsToFile();
00105
00116 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1)> ComputeMatrixTerm(
00117 c_vector<double, ELEMENT_DIM+1>& rPhi,
00118 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
00119 ChastePoint<SPACE_DIM>& rX,
00120 c_vector<double,PROBLEM_DIM>& rU,
00121 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00122 Element<ELEMENT_DIM, SPACE_DIM>* pElement);
00123
00134 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> ComputeVectorTerm(
00135 c_vector<double, ELEMENT_DIM+1>& rPhi,
00136 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
00137 ChastePoint<SPACE_DIM>& rX,
00138 c_vector<double,PROBLEM_DIM>& rU,
00139 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU,
00140 Element<ELEMENT_DIM, SPACE_DIM>* pElement);
00141
00145 void ResetInterpolatedQuantities();
00146
00154 void IncrementInterpolatedQuantities(double phiI, const Node<SPACE_DIM>* pNode);
00155
00164 void InitialiseForSolve(Vec initialSolution=NULL);
00165
00174 void SetupLinearSystem(Vec currentSolution, bool computeMatrix);
00175
00176 public:
00177
00187 LinearParabolicPdeSystemWithCoupledOdeSystemSolver(TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* pMesh,
00188 AbstractLinearParabolicPdeSystemForCoupledOdeSystem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* pPdeSystem,
00189 BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* pBoundaryConditions,
00190 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes=std::vector<AbstractOdeSystemForCoupledPdeSystem*>(),
00191 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver=boost::shared_ptr<AbstractIvpOdeSolver>());
00192
00197 ~LinearParabolicPdeSystemWithCoupledOdeSystemSolver();
00198
00205 void PrepareForSetupLinearSystem(Vec currentPdeSolution);
00206
00214 void SetOutputDirectory(std::string outputDirectory, bool clearDirectory=false);
00215
00221 void SetSamplingTimeStep(double samplingTimeStep);
00222
00227 void SolveAndWriteResultsToFile();
00228
00235 void WriteVtkResultsToFile(Vec solution, unsigned numTimeStepsElapsed);
00236
00243 AbstractOdeSystemForCoupledPdeSystem* GetOdeSystemAtNode(unsigned index);
00244 };
00245
00247
00249
00250 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00251 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1)> LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::ComputeMatrixTerm(
00252 c_vector<double, ELEMENT_DIM+1>& rPhi,
00253 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
00254 ChastePoint<SPACE_DIM>& rX,
00255 c_vector<double,PROBLEM_DIM>& rU,
00256 c_matrix<double, PROBLEM_DIM, SPACE_DIM>& rGradU,
00257 Element<ELEMENT_DIM, SPACE_DIM>* pElement)
00258 {
00259 double timestep_inverse = PdeSimulationTime::GetPdeTimeStepInverse();
00260 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));
00261
00262
00263 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
00264 {
00265 double this_dudt_coefficient = mpPdeSystem->ComputeDuDtCoefficientFunction(rX, pde_index);
00266 c_matrix<double, SPACE_DIM, SPACE_DIM> this_pde_diffusion_term = mpPdeSystem->ComputeDiffusionTerm(rX, pde_index, pElement);
00267 c_matrix<double, 1*(ELEMENT_DIM+1), 1*(ELEMENT_DIM+1)> this_stiffness_matrix =
00268 prod(trans(rGradPhi), c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>(prod(this_pde_diffusion_term, rGradPhi)) )
00269 + timestep_inverse * this_dudt_coefficient * outer_prod(rPhi, rPhi);
00270
00271 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
00272 {
00273 for (unsigned j=0; j<ELEMENT_DIM+1; j++)
00274 {
00275 matrix_term(i*PROBLEM_DIM + pde_index, j*PROBLEM_DIM + pde_index) = this_stiffness_matrix(i,j);
00276 }
00277 }
00278 }
00279 return matrix_term;
00280 }
00281
00282 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00283 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::ComputeVectorTerm(
00284 c_vector<double, ELEMENT_DIM+1>& rPhi,
00285 c_matrix<double, SPACE_DIM, ELEMENT_DIM+1>& rGradPhi,
00286 ChastePoint<SPACE_DIM>& rX,
00287 c_vector<double,PROBLEM_DIM>& rU,
00288 c_matrix<double,PROBLEM_DIM,SPACE_DIM>& rGradU,
00289 Element<ELEMENT_DIM, SPACE_DIM>* pElement)
00290 {
00291 double timestep_inverse = PdeSimulationTime::GetPdeTimeStepInverse();
00292 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> vector_term = zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
00293
00294
00295 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
00296 {
00297 double this_dudt_coefficient = mpPdeSystem->ComputeDuDtCoefficientFunction(rX, pde_index);
00298 double this_source_term = mpPdeSystem->ComputeSourceTerm(rX, rU, mInterpolatedOdeStateVariables, pde_index);
00299 c_vector<double, ELEMENT_DIM+1> this_vector_term = (this_source_term + timestep_inverse*this_dudt_coefficient*rU(pde_index))* rPhi;
00300
00301 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
00302 {
00303 vector_term(i*PROBLEM_DIM + pde_index) = this_vector_term(i);
00304 }
00305 }
00306
00307 return vector_term;
00308 }
00309
00310
00311 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00312 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::ResetInterpolatedQuantities()
00313 {
00314 mInterpolatedOdeStateVariables.clear();
00315
00316 if (mOdeSystemsPresent)
00317 {
00318 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
00319 mInterpolatedOdeStateVariables.resize(num_state_variables, 0.0);
00320 }
00321 }
00322
00323 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00324 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::IncrementInterpolatedQuantities(double phiI, const Node<SPACE_DIM>* pNode)
00325 {
00326 if (mOdeSystemsPresent)
00327 {
00328 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
00329
00330 for (unsigned i=0; i<num_state_variables; i++)
00331 {
00332 mInterpolatedOdeStateVariables[i] += phiI * mOdeSystemsAtNodes[pNode->GetIndex()]->rGetStateVariables()[i];
00333 }
00334 }
00335 }
00336
00337 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00338 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::InitialiseForSolve(Vec initialSolution)
00339 {
00340 if (this->mpLinearSystem == NULL)
00341 {
00342 unsigned preallocation = mpMesh->CalculateMaximumContainingElementsPerProcess() + ELEMENT_DIM;
00343 if (ELEMENT_DIM > 1)
00344 {
00345
00346 preallocation--;
00347 }
00348 preallocation *= PROBLEM_DIM;
00349
00350
00351
00352
00353
00354
00355 this->mpLinearSystem = new LinearSystem(initialSolution, preallocation);
00356 }
00357
00358 assert(this->mpLinearSystem);
00359 this->mpLinearSystem->SetMatrixIsSymmetric(true);
00360 this->mpLinearSystem->SetKspType("cg");
00361 }
00362
00363 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00364 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetupLinearSystem(Vec currentSolution, bool computeMatrix)
00365 {
00366 this->SetupGivenLinearSystem(currentSolution, computeMatrix, this->mpLinearSystem);
00367 }
00368
00369 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00370 LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::LinearParabolicPdeSystemWithCoupledOdeSystemSolver(
00371 TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* pMesh,
00372 AbstractLinearParabolicPdeSystemForCoupledOdeSystem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* pPdeSystem,
00373 BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* pBoundaryConditions,
00374 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes,
00375 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver)
00376 : AbstractAssemblerSolverHybrid<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NORMAL>(pMesh, pBoundaryConditions),
00377 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>(pMesh),
00378 mpMesh(pMesh),
00379 mpPdeSystem(pPdeSystem),
00380 mOdeSystemsAtNodes(odeSystemsAtNodes),
00381 mpOdeSolver(pOdeSolver),
00382 mSamplingTimeStep(DOUBLE_UNSET),
00383 mOdeSystemsPresent(false),
00384 mClearOutputDirectory(false)
00385 {
00386 this->mpBoundaryConditions = pBoundaryConditions;
00387
00388
00389
00390
00391
00392
00393 if (!mOdeSystemsAtNodes.empty())
00394 {
00395 mOdeSystemsPresent = true;
00396 assert(mOdeSystemsAtNodes.size() == mpMesh->GetNumNodes());
00397
00398
00399
00400
00401
00402 if (!mpOdeSolver)
00403 {
00404 #ifdef CHASTE_CVODE
00405 mpOdeSolver.reset(new CvodeAdaptor);
00406 #else
00407 mpOdeSolver.reset(new BackwardEulerIvpOdeSolver(mOdeSystemsAtNodes[0]->GetNumberOfStateVariables()));
00408 #endif //CHASTE_CVODE
00409 }
00410 }
00411 }
00412
00413 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00414 LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::~LinearParabolicPdeSystemWithCoupledOdeSystemSolver()
00415 {
00416 if (mOdeSystemsPresent)
00417 {
00418 for (unsigned i=0; i<mOdeSystemsAtNodes.size(); i++)
00419 {
00420 delete mOdeSystemsAtNodes[i];
00421 }
00422 }
00423 }
00424
00425 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00426 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::PrepareForSetupLinearSystem(Vec currentPdeSolution)
00427 {
00428 if (mOdeSystemsPresent)
00429 {
00430 double time = PdeSimulationTime::GetTime();
00431 double next_time = PdeSimulationTime::GetNextTime();
00432 double dt = PdeSimulationTime::GetPdeTimeStep();
00433
00434 ReplicatableVector soln_repl(currentPdeSolution);
00435 std::vector<double> current_soln_this_node(PROBLEM_DIM);
00436
00437
00438 for (unsigned node_index=0; node_index<mpMesh->GetNumNodes(); node_index++)
00439 {
00440
00441 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
00442 {
00443 double current_soln_this_pde_this_node = soln_repl[PROBLEM_DIM*node_index + pde_index];
00444 current_soln_this_node[pde_index] = current_soln_this_pde_this_node;
00445 }
00446
00447
00448 mOdeSystemsAtNodes[node_index]->SetPdeSolution(current_soln_this_node);
00449
00450
00451 mpOdeSolver->SolveAndUpdateStateVariable(mOdeSystemsAtNodes[node_index], time, next_time, dt);
00452 }
00453 }
00454 }
00455
00456 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00457 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetOutputDirectory(std::string outputDirectory, bool clearDirectory)
00458 {
00459 mClearOutputDirectory = clearDirectory;
00460 this->mOutputDirectory = outputDirectory;
00461 }
00462
00463 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00464 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetSamplingTimeStep(double samplingTimeStep)
00465 {
00466 assert(samplingTimeStep >= this->mIdealTimeStep);
00467 mSamplingTimeStep = samplingTimeStep;
00468 }
00469
00470 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00471 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SolveAndWriteResultsToFile()
00472 {
00473
00474 if (this->mOutputDirectory == "")
00475 {
00476 EXCEPTION("SetOutputDirectory() must be called prior to SolveAndWriteResultsToFile()");
00477 }
00478 if (this->mTimesSet == false)
00479 {
00480 EXCEPTION("SetTimes() must be called prior to SolveAndWriteResultsToFile()");
00481 }
00482 if (this->mIdealTimeStep <= 0.0)
00483 {
00484 EXCEPTION("SetTimeStep() must be called prior to SolveAndWriteResultsToFile()");
00485 }
00486 if (mSamplingTimeStep == DOUBLE_UNSET)
00487 {
00488 EXCEPTION("SetSamplingTimeStep() must be called prior to SolveAndWriteResultsToFile()");
00489 }
00490 if (!this->mInitialCondition)
00491 {
00492 EXCEPTION("SetInitialCondition() must be called prior to SolveAndWriteResultsToFile()");
00493 }
00494
00495 #ifdef CHASTE_VTK
00496
00497 OutputFileHandler output_file_handler(this->mOutputDirectory, mClearOutputDirectory);
00498 mpVtkMetaFile = output_file_handler.OpenOutputFile("results.pvd");
00499 *mpVtkMetaFile << "<?xml version=\"1.0\"?>\n";
00500 *mpVtkMetaFile << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">\n";
00501 *mpVtkMetaFile << " <Collection>\n";
00502
00503
00504 Vec initial_condition = this->mInitialCondition;
00505 WriteVtkResultsToFile(initial_condition, 0);
00506
00507
00508 TimeStepper stepper(this->mTstart, this->mTend, mSamplingTimeStep);
00509
00510
00511 while (!stepper.IsTimeAtEnd())
00512 {
00513
00514 this->SetTimes(stepper.GetTime(), stepper.GetNextTime());
00515
00516
00517 Vec soln = this->Solve();
00518
00519
00520 if (this->mInitialCondition != initial_condition)
00521 {
00522 PetscTools::Destroy(this->mInitialCondition);
00523 }
00524 this->mInitialCondition = soln;
00525
00526
00527 stepper.AdvanceOneTimeStep();
00528
00529
00530 WriteVtkResultsToFile(soln, stepper.GetTotalTimeStepsTaken());
00531 }
00532
00533
00534 if (this->mInitialCondition != initial_condition)
00535 {
00536 PetscTools::Destroy(this->mInitialCondition);
00537 }
00538 this->mInitialCondition = initial_condition;
00539
00540
00541 *mpVtkMetaFile << " </Collection>\n";
00542 *mpVtkMetaFile << "</VTKFile>\n";
00543 mpVtkMetaFile->close();
00544 #else //CHASTE_VTK
00545 #define COVERAGE_IGNORE // We only test this in weekly builds
00546 WARNING("VTK is not installed and is required for this functionality");
00547 #undef COVERAGE_IGNORE
00548 #endif //CHASTE_VTK
00549 }
00550
00551 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00552 void LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::WriteVtkResultsToFile(Vec solution, unsigned numTimeStepsElapsed)
00553 {
00554 #ifdef CHASTE_VTK
00555
00556
00557 std::stringstream time;
00558 time << numTimeStepsElapsed;
00559 VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(this->mOutputDirectory, "results_"+time.str(), false);
00560
00561
00562
00563
00564
00565
00566 ReplicatableVector solution_repl(solution);
00567 unsigned num_nodes = mpMesh->GetNumNodes();
00568 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
00569 {
00570
00571 std::vector<double> pde_index_data;
00572 pde_index_data.resize(num_nodes, 0.0);
00573 for (unsigned node_index=0; node_index<num_nodes; node_index++)
00574 {
00575 pde_index_data[node_index] = solution_repl[PROBLEM_DIM*node_index + pde_index];
00576 }
00577
00578
00579 std::stringstream data_name;
00580 data_name << "PDE variable " << pde_index;
00581 mesh_writer.AddPointData(data_name.str(), pde_index_data);
00582 }
00583
00584 if (mOdeSystemsPresent)
00585 {
00586
00587
00588
00589
00590
00591
00592 std::vector<std::vector<double> > ode_data;
00593 unsigned num_odes = mOdeSystemsAtNodes[0]->rGetStateVariables().size();
00594 ode_data.resize(num_odes);
00595 for (unsigned ode_index=0; ode_index<num_odes; ode_index++)
00596 {
00597 ode_data[ode_index].resize(num_nodes, 0.0);
00598 }
00599
00600 for (unsigned node_index=0; node_index<num_nodes; node_index++)
00601 {
00602 std::vector<double> all_odes_this_node = mOdeSystemsAtNodes[node_index]->rGetStateVariables();
00603 for (unsigned i=0; i<num_odes; i++)
00604 {
00605 ode_data[i][node_index] = all_odes_this_node[i];
00606 }
00607 }
00608
00609 for (unsigned ode_index=0; ode_index<num_odes; ode_index++)
00610 {
00611 std::vector<double> ode_index_data = ode_data[ode_index];
00612
00613
00614 std::stringstream data_name;
00615 data_name << "ODE variable " << ode_index;
00616 mesh_writer.AddPointData(data_name.str(), ode_index_data);
00617 }
00618 }
00619
00620 mesh_writer.WriteFilesUsingMesh(*mpMesh);
00621 *mpVtkMetaFile << " <DataSet timestep=\"";
00622 *mpVtkMetaFile << numTimeStepsElapsed;
00623 *mpVtkMetaFile << "\" group=\"\" part=\"0\" file=\"results_";
00624 *mpVtkMetaFile << numTimeStepsElapsed;
00625 *mpVtkMetaFile << ".vtu\"/>\n";
00626 #endif // CHASTE_VTK
00627 }
00628
00629 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00630 AbstractOdeSystemForCoupledPdeSystem* LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::GetOdeSystemAtNode(unsigned index)
00631 {
00632 return mOdeSystemsAtNodes[index];
00633 }
00634
00635 #endif