Chaste Commit::6e4f5fe395bca70eb7641cf6e0e87f450383ca5a
LinearParabolicPdeSystemWithCoupledOdeSystemSolver.hpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35#ifndef LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_
36#define LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_
37
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"
48
49#include <boost/shared_ptr.hpp>
50
60template<unsigned ELEMENT_DIM, unsigned SPACE_DIM=ELEMENT_DIM, unsigned PROBLEM_DIM=1>
62 : public AbstractAssemblerSolverHybrid<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NORMAL>,
63 public AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>
64{
65private:
66
69
72
74 std::vector<AbstractOdeSystemForCoupledPdeSystem*> mOdeSystemsAtNodes;
75
77 std::vector<double> mInterpolatedOdeStateVariables;
78
80 boost::shared_ptr<AbstractIvpOdeSolver> mpOdeSolver;
81
88
91
93 out_stream mpVtkMetaFile;
94
100
105
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,
123
134 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> ComputeVectorTerm(
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,
141
146
154 void IncrementInterpolatedQuantities(double phiI, const Node<SPACE_DIM>* pNode);
155
164 void InitialiseForSolve(Vec initialSolution=NULL);
165
174 void SetupLinearSystem(Vec currentSolution, bool computeMatrix);
175
176public:
177
190 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes=std::vector<AbstractOdeSystemForCoupledPdeSystem*>(),
191 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver=boost::shared_ptr<AbstractIvpOdeSolver>());
192
198
205 void PrepareForSetupLinearSystem(Vec currentPdeSolution);
206
214 void SetOutputDirectory(std::string outputDirectory, bool clearDirectory=false);
215
221 void SetSamplingTimeStep(double samplingTimeStep);
222
228
235 void WriteVtkResultsToFile(Vec solution, unsigned numTimeStepsElapsed);
236
244};
245
247// Implementation
249
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,
258{
259 double timestep_inverse = PdeSimulationTime::GetPdeTimeStepInverse();
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));
261
262 // Loop over PDEs and populate matrix_term
263 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
264 {
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 = 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
269 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
270 {
271 for (unsigned j=0; j<ELEMENT_DIM+1; j++)
272 {
273 matrix_term(i*PROBLEM_DIM + pde_index, j*PROBLEM_DIM + pde_index) = this_stiffness_matrix(i,j);
274 }
275 }
276 }
277 return matrix_term;
278}
279
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,
288{
289 double timestep_inverse = PdeSimulationTime::GetPdeTimeStepInverse();
290 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> vector_term;
291 vector_term = zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
292
293 // Loop over PDEs and populate vector_term
294 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
295 {
296 double this_dudt_coefficient = mpPdeSystem->ComputeDuDtCoefficientFunction(rX, 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;
300
301 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
302 {
303 vector_term(i*PROBLEM_DIM + pde_index) = this_vector_term(i);
304 }
305 }
306
307 return vector_term;
308}
309
310template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
312{
313 mInterpolatedOdeStateVariables.clear();
314
315 if (mOdeSystemsPresent)
316 {
317 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
318 mInterpolatedOdeStateVariables.resize(num_state_variables, 0.0);
319 }
320}
321
322template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
324{
325 if (mOdeSystemsPresent)
326 {
327 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
328
329 for (unsigned i=0; i<num_state_variables; i++)
330 {
331 mInterpolatedOdeStateVariables[i] += phiI * mOdeSystemsAtNodes[pNode->GetIndex()]->rGetStateVariables()[i];
332 }
333 }
334}
335
336template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
338{
339 if (this->mpLinearSystem == NULL)
340 {
341 unsigned preallocation = mpMesh->CalculateMaximumContainingElementsPerProcess() + ELEMENT_DIM;
342 if (ELEMENT_DIM > 1)
343 {
344 // Highest connectivity is closed
345 preallocation--;
346 }
347 preallocation *= PROBLEM_DIM;
348
349 /*
350 * Use the current solution (ie the initial solution) as the
351 * template in the alternative constructor of LinearSystem.
352 * This is to avoid problems with VecScatter.
353 */
354 this->mpLinearSystem = new LinearSystem(initialSolution, preallocation);
355 }
356
357 assert(this->mpLinearSystem);
358 this->mpLinearSystem->SetMatrixIsSymmetric(true);
359 this->mpLinearSystem->SetKspType("cg");
360}
361
362template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
364{
365 this->SetupGivenLinearSystem(currentSolution, computeMatrix, this->mpLinearSystem);
366}
367
368template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
373 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes,
374 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver)
375 : AbstractAssemblerSolverHybrid<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NORMAL>(pMesh, pBoundaryConditions),
376 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>(pMesh),
377 mpMesh(pMesh),
378 mpPdeSystem(pPdeSystem),
379 mOdeSystemsAtNodes(odeSystemsAtNodes),
380 mpOdeSolver(pOdeSolver),
381 mSamplingTimeStep(DOUBLE_UNSET),
382 mOdeSystemsPresent(false),
383 mClearOutputDirectory(false)
384{
385 this->mpBoundaryConditions = pBoundaryConditions;
386
387 /*
388 * If any ODE systems are passed in to the constructor, then we aren't just
389 * solving a coupled PDE system, in which case the number of ODE system objects
390 * must match the number of nodes in the finite element mesh.
391 */
392 if (!mOdeSystemsAtNodes.empty())
393 {
394 mOdeSystemsPresent = true;
395 assert(mOdeSystemsAtNodes.size() == mpMesh->GetNumNodes());
396
397 /*
398 * In this case, if an ODE solver is not explicitly passed into the
399 * constructor, then we create a default solver.
400 */
401 if (!mpOdeSolver)
402 {
403#ifdef CHASTE_CVODE
404 mpOdeSolver.reset(new CvodeAdaptor);
405#else
406 mpOdeSolver.reset(new BackwardEulerIvpOdeSolver(mOdeSystemsAtNodes[0]->GetNumberOfStateVariables()));
407#endif //CHASTE_CVODE
408 }
409 }
410}
411
412template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
414{
415 if (mOdeSystemsPresent)
416 {
417 for (unsigned i=0; i<mOdeSystemsAtNodes.size(); i++)
418 {
419 delete mOdeSystemsAtNodes[i];
420 }
421 }
422}
423
424template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
426{
427 if (mOdeSystemsPresent)
428 {
429 double time = PdeSimulationTime::GetTime();
430 double next_time = PdeSimulationTime::GetNextTime();
432
433 ReplicatableVector soln_repl(currentPdeSolution);
434 std::vector<double> current_soln_this_node(PROBLEM_DIM);
435
436 // Loop over nodes
437 for (unsigned node_index=0; node_index<mpMesh->GetNumNodes(); node_index++)
438 {
439 // Store the current solution to the PDE system at this node
440 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
441 {
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;
444 }
445
446 // Pass it into the ODE system at this node
447 mOdeSystemsAtNodes[node_index]->SetPdeSolution(current_soln_this_node);
448
449 // Solve ODE system at this node
450 mpOdeSolver->SolveAndUpdateStateVariable(mOdeSystemsAtNodes[node_index], time, next_time, dt);
451 }
452 }
453}
454
455template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
457{
458 mClearOutputDirectory = clearDirectory;
459 this->mOutputDirectory = outputDirectory;
460}
461
462template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
464{
465 assert(samplingTimeStep >= this->mIdealTimeStep);
466 mSamplingTimeStep = samplingTimeStep;
467}
468
469template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
471{
472 // A number of methods must have been called prior to this method
473 if (this->mOutputDirectory == "")
474 {
475 EXCEPTION("SetOutputDirectory() must be called prior to SolveAndWriteResultsToFile()");
476 }
477 if (this->mTimesSet == false)
478 {
479 EXCEPTION("SetTimes() must be called prior to SolveAndWriteResultsToFile()");
480 }
481 if (this->mIdealTimeStep <= 0.0)
482 {
483 EXCEPTION("SetTimeStep() must be called prior to SolveAndWriteResultsToFile()");
484 }
485 if (mSamplingTimeStep == DOUBLE_UNSET)
486 {
487 EXCEPTION("SetSamplingTimeStep() must be called prior to SolveAndWriteResultsToFile()");
488 }
489 if (!this->mInitialCondition)
490 {
491 EXCEPTION("SetInitialCondition() must be called prior to SolveAndWriteResultsToFile()");
492 }
493
494#ifdef CHASTE_VTK
495 // Create a .pvd output file
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";
501
502 // Write initial condition to VTK
503 Vec initial_condition = this->mInitialCondition;
504 WriteVtkResultsToFile(initial_condition, 0);
505
506 // The helper class TimeStepper deals with issues such as small final timesteps so we don't have to
507 TimeStepper stepper(this->mTstart, this->mTend, mSamplingTimeStep);
508
509 // Main time loop
510 while (!stepper.IsTimeAtEnd())
511 {
512 // Reset start and end times
513 this->SetTimes(stepper.GetTime(), stepper.GetNextTime());
514
515 // Solve the system up to the new end time
516 Vec soln = this->Solve();
517
518 // Reset the initial condition for the next timestep
519 if (this->mInitialCondition != initial_condition)
520 {
521 PetscTools::Destroy(this->mInitialCondition);
522 }
523 this->mInitialCondition = soln;
524
525 // Move forward in time
526 stepper.AdvanceOneTimeStep();
527
528 // Write solution to VTK
529 WriteVtkResultsToFile(soln, stepper.GetTotalTimeStepsTaken());
530 }
531
532 // Restore saved initial condition to avoid user confusion!
533 if (this->mInitialCondition != initial_condition)
534 {
535 PetscTools::Destroy(this->mInitialCondition);
536 }
537 this->mInitialCondition = initial_condition;
538
539 // Close .pvd output file
540 *mpVtkMetaFile << " </Collection>\n";
541 *mpVtkMetaFile << "</VTKFile>\n";
542 mpVtkMetaFile->close();
543#else //CHASTE_VTK
544// LCOV_EXCL_START // We only test this in weekly builds
545 WARNING("VTK is not installed and is required for this functionality");
546// LCOV_EXCL_STOP
547#endif //CHASTE_VTK
548}
549
550template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
552{
553#ifdef CHASTE_VTK
554
555 // Create a new VTK file for this time step
556 std::stringstream time;
557 time << numTimeStepsElapsed;
558 VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(this->mOutputDirectory, "results_"+time.str(), false);
559
560 /*
561 * We first loop over PDEs. For each PDE we store the solution
562 * at each node in a vector, then pass this vector to the mesh
563 * writer.
564 */
565 ReplicatableVector solution_repl(solution);
566 unsigned num_nodes = mpMesh->GetNumNodes();
567 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
568 {
569 // Store the solution of this PDE at each node
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++)
573 {
574 pde_index_data[node_index] = solution_repl[PROBLEM_DIM*node_index + pde_index];
575 }
576
577 // Add this data to the mesh writer
578 std::stringstream data_name;
579 data_name << "PDE variable " << pde_index;
580 mesh_writer.AddPointData(data_name.str(), pde_index_data);
581 }
582
583 if (mOdeSystemsPresent)
584 {
585 /*
586 * We cannot loop over ODEs like PDEs, since the solutions are not
587 * stored in one place. Therefore we build up a large 'vector of
588 * vectors', then pass each component of this vector to the mesh
589 * writer.
590 */
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++)
595 {
596 ode_data[ode_index].resize(num_nodes, 0.0);
597 }
598
599 for (unsigned node_index=0; node_index<num_nodes; node_index++)
600 {
601 std::vector<double> all_odes_this_node = mOdeSystemsAtNodes[node_index]->rGetStateVariables();
602 for (unsigned i=0; i<num_odes; i++)
603 {
604 ode_data[i][node_index] = all_odes_this_node[i];
605 }
606 }
607
608 for (unsigned ode_index=0; ode_index<num_odes; ode_index++)
609 {
610 std::vector<double> ode_index_data = ode_data[ode_index];
611
612 // Add this data to the mesh writer
613 std::stringstream data_name;
614 data_name << "ODE variable " << ode_index;
615 mesh_writer.AddPointData(data_name.str(), ode_index_data);
616 }
617 }
618
619 mesh_writer.WriteFilesUsingMesh(*mpMesh);
620 *mpVtkMetaFile << " <DataSet timestep=\"";
621 *mpVtkMetaFile << numTimeStepsElapsed;
622 *mpVtkMetaFile << "\" group=\"\" part=\"0\" file=\"results_";
623 *mpVtkMetaFile << numTimeStepsElapsed;
624 *mpVtkMetaFile << ".vtu\"/>\n";
625#endif // CHASTE_VTK
626}
627
628template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
633
634#endif /*LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_*/
const double DOUBLE_UNSET
Definition Exception.hpp:57
#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
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 SetOutputDirectory(std::string outputDirectory, bool clearDirectory=false)
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)
AbstractLinearParabolicPdeSystemForCoupledOdeSystem< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > * mpPdeSystem
Definition Node.hpp:59
unsigned GetIndex() const
Definition Node.cpp:158
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 GetTime()
static double GetNextTime()
static void Destroy(Vec &rVec)
bool IsTimeAtEnd() const
unsigned GetTotalTimeStepsTaken() const
double GetTime() 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)