Chaste  Release::3.4
LinearParabolicPdeSystemWithCoupledOdeSystemSolver.hpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, 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 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF 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 
60 template<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 {
65 private:
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 
104  void WriteVtkResultsToFile();
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 
176 public:
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 
250 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
251 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1)> LinearParabolicPdeSystemWithCoupledOdeSystemSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::ComputeMatrixTerm(
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 =
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);
270 
271  for (unsigned i=0; i<ELEMENT_DIM+1; i++)
272  {
273  for (unsigned j=0; j<ELEMENT_DIM+1; j++)
274  {
275  matrix_term(i*PROBLEM_DIM + pde_index, j*PROBLEM_DIM + pde_index) = this_stiffness_matrix(i,j);
276  }
277  }
278  }
279  return matrix_term;
280 }
281 
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,
290 {
291  double timestep_inverse = PdeSimulationTime::GetPdeTimeStepInverse();
292  c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> vector_term = zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
293 
294  // Loop over PDEs and populate vector_term
295  for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
296  {
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;
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 
310 
311 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
313 {
314  mInterpolatedOdeStateVariables.clear();
315 
316  if (mOdeSystemsPresent)
317  {
318  unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
319  mInterpolatedOdeStateVariables.resize(num_state_variables, 0.0);
320  }
321 }
322 
323 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
325 {
326  if (mOdeSystemsPresent)
327  {
328  unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
329 
330  for (unsigned i=0; i<num_state_variables; i++)
331  {
332  mInterpolatedOdeStateVariables[i] += phiI * mOdeSystemsAtNodes[pNode->GetIndex()]->rGetStateVariables()[i];
333  }
334  }
335 }
336 
337 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
339 {
340  if (this->mpLinearSystem == NULL)
341  {
342  unsigned preallocation = mpMesh->CalculateMaximumContainingElementsPerProcess() + ELEMENT_DIM;
343  if (ELEMENT_DIM > 1)
344  {
345  // Highest connectivity is closed
346  preallocation--;
347  }
348  preallocation *= PROBLEM_DIM;
349 
350  /*
351  * Use the current solution (ie the initial solution) as the
352  * template in the alternative constructor of LinearSystem.
353  * This is to avoid problems with VecScatter.
354  */
355  this->mpLinearSystem = new LinearSystem(initialSolution, preallocation);
356  }
357 
358  assert(this->mpLinearSystem);
359  this->mpLinearSystem->SetMatrixIsSymmetric(true);
360  this->mpLinearSystem->SetKspType("cg");
361 }
362 
363 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
365 {
366  this->SetupGivenLinearSystem(currentSolution, computeMatrix, this->mpLinearSystem);
367 }
368 
369 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
374  std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes,
375  boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver)
376  : AbstractAssemblerSolverHybrid<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NORMAL>(pMesh, pBoundaryConditions),
377  AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>(pMesh),
378  mpMesh(pMesh),
379  mpPdeSystem(pPdeSystem),
380  mOdeSystemsAtNodes(odeSystemsAtNodes),
381  mpOdeSolver(pOdeSolver),
382  mSamplingTimeStep(DOUBLE_UNSET),
383  mOdeSystemsPresent(false),
384  mClearOutputDirectory(false)
385 {
386  this->mpBoundaryConditions = pBoundaryConditions;
387 
388  /*
389  * If any ODE systems are passed in to the constructor, then we aren't just
390  * solving a coupled PDE system, in which case the number of ODE system objects
391  * must match the number of nodes in the finite element mesh.
392  */
393  if (!mOdeSystemsAtNodes.empty())
394  {
395  mOdeSystemsPresent = true;
396  assert(mOdeSystemsAtNodes.size() == mpMesh->GetNumNodes());
397 
398  /*
399  * In this case, if an ODE solver is not explicitly passed into the
400  * constructor, then we create a default solver.
401  */
402  if (!mpOdeSolver)
403  {
404 #ifdef CHASTE_CVODE
405  mpOdeSolver.reset(new CvodeAdaptor);
406 #else
407  mpOdeSolver.reset(new BackwardEulerIvpOdeSolver(mOdeSystemsAtNodes[0]->GetNumberOfStateVariables()));
408 #endif //CHASTE_CVODE
409  }
410  }
411 }
412 
413 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
415 {
416  if (mOdeSystemsPresent)
417  {
418  for (unsigned i=0; i<mOdeSystemsAtNodes.size(); i++)
419  {
420  delete mOdeSystemsAtNodes[i];
421  }
422  }
423 }
424 
425 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
427 {
428  if (mOdeSystemsPresent)
429  {
430  double time = PdeSimulationTime::GetTime();
431  double next_time = PdeSimulationTime::GetNextTime();
432  double dt = PdeSimulationTime::GetPdeTimeStep();
433 
434  ReplicatableVector soln_repl(currentPdeSolution);
435  std::vector<double> current_soln_this_node(PROBLEM_DIM);
436 
437  // Loop over nodes
438  for (unsigned node_index=0; node_index<mpMesh->GetNumNodes(); node_index++)
439  {
440  // Store the current solution to the PDE system at this node
441  for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
442  {
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;
445  }
446 
447  // Pass it into the ODE system at this node
448  mOdeSystemsAtNodes[node_index]->SetPdeSolution(current_soln_this_node);
449 
450  // Solve ODE system at this node
451  mpOdeSolver->SolveAndUpdateStateVariable(mOdeSystemsAtNodes[node_index], time, next_time, dt);
452  }
453  }
454 }
455 
456 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
458 {
459  mClearOutputDirectory = clearDirectory;
460  this->mOutputDirectory = outputDirectory;
461 }
462 
463 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
465 {
466  assert(samplingTimeStep >= this->mIdealTimeStep);
467  mSamplingTimeStep = samplingTimeStep;
468 }
469 
470 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
472 {
473  // A number of methods must have been called prior to this method
474  if (this->mOutputDirectory == "")
475  {
476  EXCEPTION("SetOutputDirectory() must be called prior to SolveAndWriteResultsToFile()");
477  }
478  if (this->mTimesSet == false)
479  {
480  EXCEPTION("SetTimes() must be called prior to SolveAndWriteResultsToFile()");
481  }
482  if (this->mIdealTimeStep <= 0.0)
483  {
484  EXCEPTION("SetTimeStep() must be called prior to SolveAndWriteResultsToFile()");
485  }
486  if (mSamplingTimeStep == DOUBLE_UNSET)
487  {
488  EXCEPTION("SetSamplingTimeStep() must be called prior to SolveAndWriteResultsToFile()");
489  }
490  if (!this->mInitialCondition)
491  {
492  EXCEPTION("SetInitialCondition() must be called prior to SolveAndWriteResultsToFile()");
493  }
494 
495 #ifdef CHASTE_VTK
496  // Create a .pvd output file
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";
502 
503  // Write initial condition to VTK
504  Vec initial_condition = this->mInitialCondition;
505  WriteVtkResultsToFile(initial_condition, 0);
506 
507  // The helper class TimeStepper deals with issues such as small final timesteps so we don't have to
508  TimeStepper stepper(this->mTstart, this->mTend, mSamplingTimeStep);
509 
510  // Main time loop
511  while (!stepper.IsTimeAtEnd())
512  {
513  // Reset start and end times
514  this->SetTimes(stepper.GetTime(), stepper.GetNextTime());
515 
516  // Solve the system up to the new end time
517  Vec soln = this->Solve();
518 
519  // Reset the initial condition for the next timestep
520  if (this->mInitialCondition != initial_condition)
521  {
522  PetscTools::Destroy(this->mInitialCondition);
523  }
524  this->mInitialCondition = soln;
525 
526  // Move forward in time
527  stepper.AdvanceOneTimeStep();
528 
529  // Write solution to VTK
530  WriteVtkResultsToFile(soln, stepper.GetTotalTimeStepsTaken());
531  }
532 
533  // Restore saved initial condition to avoid user confusion!
534  if (this->mInitialCondition != initial_condition)
535  {
536  PetscTools::Destroy(this->mInitialCondition);
537  }
538  this->mInitialCondition = initial_condition;
539 
540  // Close .pvd output file
541  *mpVtkMetaFile << " </Collection>\n";
542  *mpVtkMetaFile << "</VTKFile>\n";
543  mpVtkMetaFile->close();
544 #else //CHASTE_VTK
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
548 #endif //CHASTE_VTK
549 }
550 
551 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
553 {
554 #ifdef CHASTE_VTK
555 
556  // Create a new VTK file for this time step
557  std::stringstream time;
558  time << numTimeStepsElapsed;
559  VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(this->mOutputDirectory, "results_"+time.str(), false);
560 
561  /*
562  * We first loop over PDEs. For each PDE we store the solution
563  * at each node in a vector, then pass this vector to the mesh
564  * writer.
565  */
566  ReplicatableVector solution_repl(solution);
567  unsigned num_nodes = mpMesh->GetNumNodes();
568  for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
569  {
570  // Store the solution of this PDE at each node
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++)
574  {
575  pde_index_data[node_index] = solution_repl[PROBLEM_DIM*node_index + pde_index];
576  }
577 
578  // Add this data to the mesh writer
579  std::stringstream data_name;
580  data_name << "PDE variable " << pde_index;
581  mesh_writer.AddPointData(data_name.str(), pde_index_data);
582  }
583 
584  if (mOdeSystemsPresent)
585  {
586  /*
587  * We cannot loop over ODEs like PDEs, since the solutions are not
588  * stored in one place. Therefore we build up a large 'vector of
589  * vectors', then pass each component of this vector to the mesh
590  * writer.
591  */
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++)
596  {
597  ode_data[ode_index].resize(num_nodes, 0.0);
598  }
599 
600  for (unsigned node_index=0; node_index<num_nodes; node_index++)
601  {
602  std::vector<double> all_odes_this_node = mOdeSystemsAtNodes[node_index]->rGetStateVariables();
603  for (unsigned i=0; i<num_odes; i++)
604  {
605  ode_data[i][node_index] = all_odes_this_node[i];
606  }
607  }
608 
609  for (unsigned ode_index=0; ode_index<num_odes; ode_index++)
610  {
611  std::vector<double> ode_index_data = ode_data[ode_index];
612 
613  // Add this data to the mesh writer
614  std::stringstream data_name;
615  data_name << "ODE variable " << ode_index;
616  mesh_writer.AddPointData(data_name.str(), ode_index_data);
617  }
618  }
619 
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";
626 #endif // CHASTE_VTK
627 }
628 
629 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
631 {
632  return mOdeSystemsAtNodes[index];
633 }
634 
635 #endif /*LINEARPARABOLICPDESYSTEMWITHCOUPLEDODESYSTEMSOLVER_HPP_*/
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)
Definition: Node.hpp:58
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 >())
double GetTime() const
#define EXCEPTION(message)
Definition: Exception.hpp:143
void AdvanceOneTimeStep()
bool IsTimeAtEnd() const
const double DOUBLE_UNSET
Definition: Exception.hpp:56
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()
static void Destroy(Vec &rVec)
Definition: PetscTools.hpp:351
static double GetPdeTimeStep()
unsigned GetIndex() const
Definition: Node.cpp:159
double GetNextTime() const
void AddPointData(std::string name, std::vector< double > data)
static double GetTime()
AbstractLinearParabolicPdeSystemForCoupledOdeSystem< ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM > * mpPdeSystem