Chaste Commit::29c3c4ab2bee00ddd311a035a1e522c03cbe928a
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 "Warnings.hpp"
46#include "VtkMeshWriter.hpp"
47
48#include <boost/shared_ptr.hpp>
49
59template<unsigned ELEMENT_DIM, unsigned SPACE_DIM=ELEMENT_DIM, unsigned PROBLEM_DIM=1>
61 : public AbstractAssemblerSolverHybrid<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NORMAL>,
62 public AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>
63{
64private:
65
68
71
73 std::vector<AbstractOdeSystemForCoupledPdeSystem*> mOdeSystemsAtNodes;
74
76 std::vector<double> mInterpolatedOdeStateVariables;
77
79 boost::shared_ptr<AbstractIvpOdeSolver> mpOdeSolver;
80
87
90
92 out_stream mpVtkMetaFile;
93
99
104
115 c_matrix<double, PROBLEM_DIM*(ELEMENT_DIM+1), PROBLEM_DIM*(ELEMENT_DIM+1)> ComputeMatrixTerm(
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,
122
133 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> ComputeVectorTerm(
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,
140
145
153 void IncrementInterpolatedQuantities(double phiI, const Node<SPACE_DIM>* pNode);
154
163 void InitialiseForSolve(Vec initialSolution=NULL);
164
173 void SetupLinearSystem(Vec currentSolution, bool computeMatrix);
174
175public:
176
189 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes=std::vector<AbstractOdeSystemForCoupledPdeSystem*>(),
190 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver=boost::shared_ptr<AbstractIvpOdeSolver>());
191
197
204 void PrepareForSetupLinearSystem(Vec currentPdeSolution);
205
213 void SetOutputDirectory(std::string outputDirectory, bool clearDirectory=false);
214
220 void SetSamplingTimeStep(double samplingTimeStep);
221
227
234 void WriteVtkResultsToFile(Vec solution, unsigned numTimeStepsElapsed);
235
243};
244
246// Implementation
248
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,
257{
258 double timestep_inverse = PdeSimulationTime::GetPdeTimeStepInverse();
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));
260
261 // Loop over PDEs and populate matrix_term
262 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
263 {
264 double this_dudt_coefficient = mpPdeSystem->ComputeDuDtCoefficientFunction(rX, 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);
267
268 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
269 {
270 for (unsigned j=0; j<ELEMENT_DIM+1; j++)
271 {
272 matrix_term(i*PROBLEM_DIM + pde_index, j*PROBLEM_DIM + pde_index) = this_stiffness_matrix(i,j);
273 }
274 }
275 }
276 return matrix_term;
277}
278
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,
287{
288 double timestep_inverse = PdeSimulationTime::GetPdeTimeStepInverse();
289 c_vector<double, PROBLEM_DIM*(ELEMENT_DIM+1)> vector_term;
290 vector_term = zero_vector<double>(PROBLEM_DIM*(ELEMENT_DIM+1));
291
292 // Loop over PDEs and populate vector_term
293 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
294 {
295 double this_dudt_coefficient = mpPdeSystem->ComputeDuDtCoefficientFunction(rX, 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;
299
300 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
301 {
302 vector_term(i*PROBLEM_DIM + pde_index) = this_vector_term(i);
303 }
304 }
305
306 return vector_term;
307}
308
309template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
311{
312 mInterpolatedOdeStateVariables.clear();
313
314 if (mOdeSystemsPresent)
315 {
316 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
317 mInterpolatedOdeStateVariables.resize(num_state_variables, 0.0);
318 }
319}
320
321template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
323{
324 if (mOdeSystemsPresent)
325 {
326 unsigned num_state_variables = mOdeSystemsAtNodes[0]->GetNumberOfStateVariables();
327
328 for (unsigned i=0; i<num_state_variables; i++)
329 {
330 mInterpolatedOdeStateVariables[i] += phiI * mOdeSystemsAtNodes[pNode->GetIndex()]->rGetStateVariables()[i];
331 }
332 }
333}
334
335template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
337{
338 if (this->mpLinearSystem == NULL)
339 {
340 unsigned preallocation = mpMesh->CalculateMaximumContainingElementsPerProcess() + ELEMENT_DIM;
341 if (ELEMENT_DIM > 1)
342 {
343 // Highest connectivity is closed
344 preallocation--;
345 }
346 preallocation *= PROBLEM_DIM;
347
348 /*
349 * Use the current solution (ie the initial solution) as the
350 * template in the alternative constructor of LinearSystem.
351 * This is to avoid problems with VecScatter.
352 */
353 this->mpLinearSystem = new LinearSystem(initialSolution, preallocation);
354 }
355
356 assert(this->mpLinearSystem);
357 this->mpLinearSystem->SetMatrixIsSymmetric(true);
358 this->mpLinearSystem->SetKspType("cg");
359}
360
361template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
363{
364 this->SetupGivenLinearSystem(currentSolution, computeMatrix, this->mpLinearSystem);
365}
366
367template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
372 std::vector<AbstractOdeSystemForCoupledPdeSystem*> odeSystemsAtNodes,
373 boost::shared_ptr<AbstractIvpOdeSolver> pOdeSolver)
374 : AbstractAssemblerSolverHybrid<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM, NORMAL>(pMesh, pBoundaryConditions),
375 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>(pMesh),
376 mpMesh(pMesh),
377 mpPdeSystem(pPdeSystem),
378 mOdeSystemsAtNodes(odeSystemsAtNodes),
379 mpOdeSolver(pOdeSolver),
380 mSamplingTimeStep(DOUBLE_UNSET),
381 mOdeSystemsPresent(false),
382 mClearOutputDirectory(false)
383{
384 this->mpBoundaryConditions = pBoundaryConditions;
385
386 /*
387 * If any ODE systems are passed in to the constructor, then we aren't just
388 * solving a coupled PDE system, in which case the number of ODE system objects
389 * must match the number of nodes in the finite element mesh.
390 */
391 if (!mOdeSystemsAtNodes.empty())
392 {
393 mOdeSystemsPresent = true;
394 assert(mOdeSystemsAtNodes.size() == mpMesh->GetNumNodes());
395
396 /*
397 * In this case, if an ODE solver is not explicitly passed into the
398 * constructor, then we create a default solver.
399 */
400 if (!mpOdeSolver)
401 {
402 mpOdeSolver.reset(new CvodeAdaptor);
403 }
404 }
405}
406
407template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
409{
410 if (mOdeSystemsPresent)
411 {
412 for (unsigned i=0; i<mOdeSystemsAtNodes.size(); i++)
413 {
414 delete mOdeSystemsAtNodes[i];
415 }
416 }
417}
418
419template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
421{
422 if (mOdeSystemsPresent)
423 {
424 double time = PdeSimulationTime::GetTime();
425 double next_time = PdeSimulationTime::GetNextTime();
427
428 ReplicatableVector soln_repl(currentPdeSolution);
429 std::vector<double> current_soln_this_node(PROBLEM_DIM);
430
431 // Loop over nodes
432 for (unsigned node_index=0; node_index<mpMesh->GetNumNodes(); node_index++)
433 {
434 // Store the current solution to the PDE system at this node
435 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
436 {
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;
439 }
440
441 // Pass it into the ODE system at this node
442 mOdeSystemsAtNodes[node_index]->SetPdeSolution(current_soln_this_node);
443
444 // Solve ODE system at this node
445 mpOdeSolver->SolveAndUpdateStateVariable(mOdeSystemsAtNodes[node_index], time, next_time, dt);
446 }
447 }
448}
449
450template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
452{
453 mClearOutputDirectory = clearDirectory;
454 this->mOutputDirectory = outputDirectory;
455}
456
457template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
459{
460 assert(samplingTimeStep >= this->mIdealTimeStep);
461 mSamplingTimeStep = samplingTimeStep;
462}
463
464template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
466{
467 // A number of methods must have been called prior to this method
468 if (this->mOutputDirectory == "")
469 {
470 EXCEPTION("SetOutputDirectory() must be called prior to SolveAndWriteResultsToFile()");
471 }
472 if (this->mTimesSet == false)
473 {
474 EXCEPTION("SetTimes() must be called prior to SolveAndWriteResultsToFile()");
475 }
476 if (this->mIdealTimeStep <= 0.0)
477 {
478 EXCEPTION("SetTimeStep() must be called prior to SolveAndWriteResultsToFile()");
479 }
480 if (mSamplingTimeStep == DOUBLE_UNSET)
481 {
482 EXCEPTION("SetSamplingTimeStep() must be called prior to SolveAndWriteResultsToFile()");
483 }
484 if (!this->mInitialCondition)
485 {
486 EXCEPTION("SetInitialCondition() must be called prior to SolveAndWriteResultsToFile()");
487 }
488
489 // Create a .pvd output file
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";
495
496 // Write initial condition to VTK
497 Vec initial_condition = this->mInitialCondition;
498 WriteVtkResultsToFile(initial_condition, 0);
499
500 // The helper class TimeStepper deals with issues such as small final timesteps so we don't have to
501 TimeStepper stepper(this->mTstart, this->mTend, mSamplingTimeStep);
502
503 // Main time loop
504 while (!stepper.IsTimeAtEnd())
505 {
506 // Reset start and end times
507 this->SetTimes(stepper.GetTime(), stepper.GetNextTime());
508
509 // Solve the system up to the new end time
510 Vec soln = this->Solve();
511
512 // Reset the initial condition for the next timestep
513 if (this->mInitialCondition != initial_condition)
514 {
515 PetscTools::Destroy(this->mInitialCondition);
516 }
517 this->mInitialCondition = soln;
518
519 // Move forward in time
520 stepper.AdvanceOneTimeStep();
521
522 // Write solution to VTK
523 WriteVtkResultsToFile(soln, stepper.GetTotalTimeStepsTaken());
524 }
525
526 // Restore saved initial condition to avoid user confusion!
527 if (this->mInitialCondition != initial_condition)
528 {
529 PetscTools::Destroy(this->mInitialCondition);
530 }
531 this->mInitialCondition = initial_condition;
532
533 // Close .pvd output file
534 *mpVtkMetaFile << " </Collection>\n";
535 *mpVtkMetaFile << "</VTKFile>\n";
536 mpVtkMetaFile->close();
537}
538
539template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
541{
542 // Create a new VTK file for this time step
543 std::stringstream time;
544 time << numTimeStepsElapsed;
545 VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(this->mOutputDirectory, "results_"+time.str(), false);
546
547 /*
548 * We first loop over PDEs. For each PDE we store the solution
549 * at each node in a vector, then pass this vector to the mesh
550 * writer.
551 */
552 ReplicatableVector solution_repl(solution);
553 unsigned num_nodes = mpMesh->GetNumNodes();
554 for (unsigned pde_index=0; pde_index<PROBLEM_DIM; pde_index++)
555 {
556 // Store the solution of this PDE at each node
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++)
560 {
561 pde_index_data[node_index] = solution_repl[PROBLEM_DIM*node_index + pde_index];
562 }
563
564 // Add this data to the mesh writer
565 std::stringstream data_name;
566 data_name << "PDE variable " << pde_index;
567 mesh_writer.AddPointData(data_name.str(), pde_index_data);
568 }
569
570 if (mOdeSystemsPresent)
571 {
572 /*
573 * We cannot loop over ODEs like PDEs, since the solutions are not
574 * stored in one place. Therefore we build up a large 'vector of
575 * vectors', then pass each component of this vector to the mesh
576 * writer.
577 */
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++)
582 {
583 ode_data[ode_index].resize(num_nodes, 0.0);
584 }
585
586 for (unsigned node_index=0; node_index<num_nodes; node_index++)
587 {
588 std::vector<double> all_odes_this_node = mOdeSystemsAtNodes[node_index]->rGetStateVariables();
589 for (unsigned i=0; i<num_odes; i++)
590 {
591 ode_data[i][node_index] = all_odes_this_node[i];
592 }
593 }
594
595 for (unsigned ode_index=0; ode_index<num_odes; ode_index++)
596 {
597 std::vector<double> ode_index_data = ode_data[ode_index];
598
599 // Add this data to the mesh writer
600 std::stringstream data_name;
601 data_name << "ODE variable " << ode_index;
602 mesh_writer.AddPointData(data_name.str(), ode_index_data);
603 }
604 }
605
606 mesh_writer.WriteFilesUsingMesh(*mpMesh);
607 *mpVtkMetaFile << " <DataSet timestep=\"";
608 *mpVtkMetaFile << numTimeStepsElapsed;
609 *mpVtkMetaFile << "\" group=\"\" part=\"0\" file=\"results_";
610 *mpVtkMetaFile << numTimeStepsElapsed;
611 *mpVtkMetaFile << ".vtu\"/>\n";
612}
613
614template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
619
620#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)