CEPS  24.01
Cardiac ElectroPhysiology Simulator
AbstractTimedPdeSolver.cpp
Go to the documentation of this file.
1 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  This file is part of CEPS.
3 
4  CEPS is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  CEPS is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with CEPS (see file LICENSE at root of project).
16  If not, see <https://www.gnu.org/licenses/>.
17 
18 
19  Copyright 2019-2024 Inria, Universite de Bordeaux
20 
21  Authors, in alphabetical order:
22 
23  Pierre-Elliott BECUE, Florian CARO, Yves COUDIERE(*), Andjela DAVIDOVIC,
24  Charlie DOUANLA-LONTSI, Marc FUENTES, Mehdi JUHOOR, Michael LEGUEBE(*),
25  Pauline MIGERDITICHAN, Valentin PANNETIER(*), Nejib ZEMZEMI.
26  * : currently active authors
27 
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
33 
35  AbstractPdeSolver (pb),
36  m_uNm ({}),
37  m_type ("FBE"),
38  m_rkType (""),
39  m_nbMultiSteps (1u),
40  m_timeStepper (nullptr),
41  m_regSourcesNm ({}),
42  m_lapSourcesNm ({}),
43  m_rkF ({}),
44  m_rkU ({}),
45  // m_scaleSystem (1./pb->getTimeStep()),
46  m_scaleSystem (1.),
47  m_cheatConvergence(true),
48  m_nbIterSnapshot (1)
49 {
50  m_timeStepper = ceps::getNew<TimeStepper>(pb->getStartTime(),pb->getEndTime(),pb->getTimeStep());
51 
52  m_nbIterSnapshot = std::max(CepsUInt(1U),CepsUInt(pb->getSnapshotTime()/pb->getTimeStep()));
53 
54  if (m_doOutput)
55  this->initializeWriter();
56  m_timeWriter = ceps::getNew<TimeWriter>(m_problem->getOutputFileBase()+"_probes.dat",
57  m_problem->getProbePoints(),
58  m_discretization);
59 
60 
61  if (pb->getParameters())
63 
64  m_doError = pb->hasAnalyticSolution();
65  if (m_doError)
66  enableErrorComputation();
67 
68  determineSolverType(m_type);
70 
71  // Matrix of derivative terms
72  m_dtMat = m_discretization->newDofMatrix();
73  // Vectors of footprint of diagonal of dtMat
74  m_timeDerEqsVec = m_discretization->newDofHaloVector();
75  m_noTimeDerEqsVec = m_discretization->newDofHaloVector();
76 }
77 
79 {
81 }
82 
83 void
85 {
86  CEPS_SAYS("Initialize assemblers for " << std::quoted(m_problem->getProblemName()));
87  this->initializeAssemblers();
89 
90  // Write initial step
91  this->output(m_uNm[0]);
92 
93  CEPS_SAYS(
94  "Now computing PDE solution ("+m_type+(m_nbMultiSteps>1?ceps::toString(m_nbMultiSteps):"")+"):"
95  );
96  if (ceps::isVerbose())
98 
99  while (not this->finished())
100  {
101 
103 
104  if (ceps::isProfiling())
105  getProfiler()->start("updateLS", "updating system and solving (" + m_problem->getProblemName() + ")");
106 
107  this->assembleAndSolve();
108 
109  if (ceps::isProfiling())
110  {
111  getProfiler()->stop("updateLS");
112  getProfiler()->logMemoryUsage("\"PDE solver - after "+ceps::toString(iter)+"th update\"");
113  }
114 
115  // Update time and write solutions
117 
118  if (ceps::isVerbose())
119  displayProgress();
120  this->output(m_uNp1);
121 
122  if (getTimedProblem()->canComputeErrorAtTime(m_timeStepper->getTime()))
124 
125  // Swap pointers on solutions at previous steps
126  DHVecPtr tmp = m_uNm.back();
127  for (CepsUInt k = m_nbMultiSteps-1; k>0;k--)
128  m_uNm[k] = m_uNm[k-1];
129  m_uNm[0] = m_uNp1;
130  m_uNp1 = tmp;
131 
132  }
133 
134  // Do a final output, even if it could be a duplicate of previous one
135  // (the finished method can be overloaded with something else)
136  this->output(m_uNm[0]);
137 
138  if (ceps::isVerbose())
139  std::cout << std::endl;
140 }
141 
142 void
144 {
145  m_type = p->getString("pde solver",m_type);
146 }
147 
148 CepsUInt
150 {
151  auto tpb = getTimedProblem();
152 
153  // Snapshots + initial guess and final output (in case it does not match with snapshot)
154  return 2 + CepsUInt(std::floor((tpb->getEndTime()-tpb->getStartTime())/
155  tpb->getSnapshotTime()));
156 }
157 
158 void
160 {
162  {
163  // Unknowns
164  for (Unknown* u: m_problem->getUnknowns())
165  m_writer->addScalarData(solution,u->getName(),u);
166 
167  // Reference solution if exists
169  {
170  auto uNp1 = m_discretization->newDofHaloVector();
173 
174  for (Unknown* u: m_problem->getUnknowns())
175  m_writer->addScalarData(uNp1, "Reference " + u->getName(), u);
176  }
177 
178  // Sources
179  for (auto [key, f] : *m_problem->getSourceTermManager()->getManager())
180  {
181  if (not key.starts_with("__"))
182  {
183  auto vec = m_discretization->newDofHaloVector();
184  addFieldValuesTo(*f, vec.get(), m_timeStepper->getTime());
186  m_writer->addScalarData(vec, key + " [" + u->getName() + "]", u);
187  }
188  }
189 
190  if (immediateWriting)
192  // m_writer->writeSolution(
193  // m_problem->getSpatialUnknowns(),solution,
194  // m_timeStepper->getNbTakenTimeSteps()
195  // );
196  }
197 
199  m_timeWriter->write(m_timeStepper->getTime(),solution);
200 }
201 
202 DHVecPtr
204 {
205  return DHVecPtr(ceps::getNew<DistributedHaloVector>(*m_uNp1));
206 }
207 
208 void
210 {
211  m_doError = true;
214  if (not m_problem->usesReferenceSolution())
215  dt = getTimedProblem()->getTimeStep();
216  m_errors = ceps::getNew<PdeErrorCalculator>(m_problem,dt);
217 }
218 
221 {
223  if (not m_doError)
224  return res;
225 
226  for (CepsUInt normt=0; normt<2; normt++)
227  for (CepsUInt norm =0; norm <3; norm ++)
228  {
229  res[0][normt][norm] = m_errors->getAbsoluteErrorCumulative(norm,normt);
230  res[1][normt][norm] = m_errors->getRelativeErrorCumulative(norm,normt);
231  }
232  for (CepsUInt norm =0; norm <3; norm ++)
233  {
234  res[0][2][norm] = m_errors->getAbsoluteErrorNow(norm);
235  res[1][2][norm] = m_errors->getRelativeErrorNow(norm);
236  }
237 
238  return res;
239 }
240 
241 // -----------------------------------------------------------------------------------------
242 
245 {
246  return ceps::runtimeCast<AbstractTimedPdeProblem*>(m_problem);
247 }
248 
249 void
251 {
252  if (ceps::isMaster())
253  {
255  CepsReal tStart = m_timeStepper->getStartTime();
256  CepsReal tEnd = m_timeStepper->getEndTime ();
257  CepsUInt done = (CepsUInt) std::floor((t-tStart)/(tEnd-tStart)*100);
258 
259  std::cout << "\r Simulation time : " << std::setw(10) << t << "/" << std::setw(10) << tEnd << " ms ("
260  << std::setw(3) << done << "%)" << std::flush;
261  }
262 }
263 
264 CepsBool
266 {
267  return m_timeStepper->atEnd();
268 }
269 
270 void
272 {
273  std::stringstream ss(opt);
274  ss >> m_type;
275 
276  if (m_type == "FBE")
277  {
278  m_nbMultiSteps = 1;
279  m_type = "SBDF";
280  }
281  else if (m_type == "SBDF")
282  {
283  m_nbMultiSteps = ceps::readInt(ss,"Unable to read the order of the SBDF method");
284  CEPS_ABORT_IF(m_nbMultiSteps > 4,"SBDF solvers of order larger than 4 are not implemented.");
285  }
286  // else if (m_type == "RK" or m_type == "RUNGE_KUTTA")
287  // {
288  // // The solver compatibility with ionic solvers was already checked in CardiacParameters class
289  // ss >> m_rkType;
290  // m_type = "RK";
291  // m_nbMultiSteps = 1; // not be confused with RK-substeps
292  // }
293  else if (m_type == "CN" or m_type=="Crank-Nicolson" or m_type=="Crank-Nicholson")
294  {
295  m_type = "CN";
296  m_nbMultiSteps = 2;
297  }
298  else
299  {
300  CEPS_ABORT ("Timed Pde Solver: Unknown solver type: "
301  << m_type << " .Valid types are\n"
302  << " - FBE (for single step Euler method)\n"
303  << " - SBDF <order> where order is an integer between 1 and 4\n"
304  // << " - RK <options> where options are the same as for the line\n"
305  << " - CN (or Crank-Nicolson)");
306  }
307  return;
308 
309 }
310 
311 void
313 {
314 
316  for (CepsUInt i=0;i<m_nbMultiSteps;i++)
318 
319  for (CepsUInt i=0;i<m_nbMultiSteps;i++)
321 
322  for (CepsUInt i=0;i<m_nbMultiSteps;i++)
324 
325 
326  // Allocate arrays for the RK method
327  // if (m_type=="RK")
328  // {
329  // RungeKuttaOdeSolver rks (m_RKType);
330  // for (CepsUInt k = 0U; k < rks.nSubSteps (); k++)
331  // {
332  // m_rkF.push_back(m_discretization->newDofHaloVector());
333  // m_rkU.push_back(m_discretization->newDofHaloVector());
334  // }
335  // }
336 
337 }
338 
339 
340 void
342 {
344  CepsReal time = m_timeStepper->getTime();
346 
347  // Assemble derivative matrix terms
348  if (iter == 0 or m_opAsb->isChangingBetweenTimes(time, time + dt))
349  {
351  m_opAsb->setMatrix(m_dtMat.get());
353  m_opAsb->setScaleFactor(1.0);
354  m_opAsb->assemble(time + dt);
355 
356  // I couldn't think of an easier way
357  m_dtMat->getDiagonalFootPrintAsDistributedVector(*m_timeDerEqsVec);
358  m_noTimeDerEqsVec->zero();
359  m_noTimeDerEqsVec->addScaled(*m_timeDerEqsVec, -1.0);
360  *m_noTimeDerEqsVec += 1.0;
361  }
362 
363  // Assemble operator matrix terms
364  if (iter == 0 or m_opAsb->isChangingBetweenTimes(time, time + dt))
365  {
367  m_opAsb->setMatrix(m_opMat.get());
369  m_opAsb->setScaleFactor(1.0);
370  m_opAsb->assemble(time + dt);
371  }
372 
373  // Assemble only the matrix terms of the Neumann and Robin BCs contributions
374  if (iter == 0 or m_bcAsb->isChangingBetweenTimes(time, time+dt))
375  {
377  m_bcAsb->setMatrix(m_bcMat.get());
378  }
379  else {
380  m_bcAsb->setMatrix(nullptr);
381  }
382 
383  // if (ceps::isNullPtr(m_bcVec.get()))
385  m_bcAsb->setVector(m_bcVec.get());
386  m_bcAsb->setScaleFactor(1.0);
387  m_bcAsb->assemble(time + dt);
388 
389  // Laplace source terms
390  if (m_hasLapSrc)
391  if (iter == 0 or m_bcAsb->isChangingBetweenTimes(time, time + dt))
392  {
395  m_lapSrcAsb->assemble(time);
396  }
397 
398  return;
399 }
400 
401 void
403 {
405 
406  // Regular source terms
407  if (m_hasRegSrc)
408  {
409  m_regSourcesNm[0]->zero();
410  // Update source terms and add them to the sources vectors at t^n
412  if (not src->hasOption(CepsSourceTermFlag::Laplace)
413  and not src->hasOption(CepsSourceTermFlag::Stimulation))
414  addFieldValuesTo(*src,m_regSourcesNm[0].get(),tn);
415  m_regSourcesNm[0]->finalize();
416 
417  CEPS_CHECK_IS_NAN(m_regSourcesNm[0]->dot(*m_regSourcesNm[0]), "source term contains NaN values");
418  }
419 
420  // Laplace source terms
421  if (m_hasLapSrc)
422  {
423  m_lapSourcesNm[0]->zero();
424  // Update source terms and add them to the sources vectors at t^n
426  if (src->hasOption(CepsSourceTermFlag::Laplace))
427  addFieldValuesTo(*src,m_lapSourcesNm[0].get(),tn);
428  m_lapSourcesNm[0]->finalize();
429 
430  CEPS_CHECK_IS_NAN(m_lapSourcesNm[0]->dot(*m_lapSourcesNm[0]), "laplace source term contains NaN values");
431  }
432 }
433 
434 void
436 {
437  if (m_hasRegSrc)
438  std::rotate(m_regSourcesNm.rbegin(),m_regSourcesNm.rbegin()+1,m_regSourcesNm.rend());
439 
440  if (m_hasLapSrc)
441  std::rotate(m_lapSourcesNm.rbegin(),m_lapSourcesNm.rbegin()+1,m_lapSourcesNm.rend());
442 }
443 
444 
445 
446 
@ Laplace
A source term that multiplies grad phi (for FE)
@ Stimulation
Apply cardiac specific treatment before adding.
@ TimeDerivative
Compute matrix of time derivatives.
@ SpatialOperator
Compute matrix of spatial operators.
#define CEPS_ABORT(message)
Stops the execution with a message. If testing is enabled, only throws a runtime_error.
#define CEPS_SAYS(message)
Writes a message in the debug log and in the terminal (stdio).
#define CEPS_CHECK_IS_NAN(value, message)
Check if a value is nan or inf.
#define CEPS_ABORT_IF(condition, message)
Stops the execution with a message if condition is true. If testing is enabled, only throws a runtime...
std::basic_string< CepsChar > CepsString
C++ format string.
Definition: CepsTypes.hpp:128
CepsArray< _Type, 2U > CepsArray2
C++ array, 2 elements.
Definition: CepsTypes.hpp:162
bool CepsBool
Booleans.
Definition: CepsTypes.hpp:124
std::make_unsigned_t< CepsInt > CepsUInt
Unsigned version on CepsInt.
Definition: CepsTypes.hpp:109
float CepsReal
Need single precision floating point.
Definition: CepsTypes.hpp:100
std::shared_ptr< DistributedHaloVector > DHVecPtr
Typedef for pointer on Distributed Halo CepsVector.
void addFieldValuesTo(ScalarField< _SupportType > &f, DistributedVector *vec, CepsReal t=0.)
Add values to a distributed vector. Exclusive to scalar fields. Field data may be evaluated on the fl...
void setMatrix(DistributedMatrix *mat)
The matrix to assemble.
void setScaleFactor(CepsReal scaleFactor)
Factor that multiplies all coefficients to put in linear system.
void setVector(DistributedVector *vec)
The vector to assemble.
void setAssemblingFlag(const CepsAssemblingFlag &value)
Part to assemble in an assembler, see values of CepsAssemblingFlag.
virtual void assemble(CepsReal t=0., CepsBool finalize=true)=0
The main routine to call to assemble linear system.
virtual CepsBool isChangingBetweenTimes(CepsReal t1, CepsReal t2) const
Tells if this assembler changes between the two times.
DHVecPtr newDofHaloVector() const
Get a new vector from the factory, with halo data.
void evaluateFunctionOnDofs(ceps::Function< CepsReal(CepsStandardArgs)> *func, DHVecPtr v, CepsReal t=0.) const
Fills vector v with values of function func at owned and halo dofs and time t.
DMatPtr newDofMatrix() const
Get a new matrix from the factory.
CepsVector< Unknown * > getSpatialUnknowns() const
A vector of all unknowns of pb defined on cells or points.
ScalarFunction * getAnalyticSolution() const
Pointer on analytic or refScalarFunction solution.
CepsBool hasAnalyticSolution() const
Tells if there is an analytic or reference solution.
SourceTermManager * getSourceTermManager() const
Get boundary condition manager.
CepsString getProblemName() const
Get the name of the problem.
CepsBool usesReferenceSolution() const
Tells if analytic solution and if it is loaded from files.
CepsReal getReferenceSolutionOutputPeriod() const
Output dt of reference.
const CepsVector< Unknown * > & getUnknowns() const
List of unknowns of the pb.
Base class for PDE solving.
virtual void initializeAssemblers()=0
Creates the right type of assemblers for LHS and BCs. Needs to be overriden.
VtkWriter * m_writer
Manages output.
AbstractAssembler * m_lapSrcAsb
Assembler for laplace source terms.
virtual void assembleAndSolve()=0
Main routine used during solving, perform one single step on time problem or solve directly in static...
DMatPtr m_bcMat
Matrix of boundary conditions.
CepsBool m_hasRegSrc
Flag telling if there are regular source terms.
AbstractDiscretization * m_discretization
Link to PDE discretization.
AbstractAssembler * m_bcAsb
Assembler for Robin and Neumann BCs.
PdeErrorCalculator * m_errors
Error computation.
CepsBool m_doOutput
Enables/disables outputs.
DMatPtr m_opMat
Matrix of operator.
TimeWriter * m_timeWriter
Writer for time dependant data (even for static problems...)
DVecPtr m_bcVec
Vector of boundary conditions.
AbstractAssembler * m_opAsb
Assembler for the operator matrix.
CepsBool m_hasLapSrc
Flag telling if there are Delta f source terms.
AbstractPdeProblem * m_problem
Link to PDE to solve.
CepsBool m_doError
Compute error wrt analytic solution or reference.
DMatPtr m_lapSrcMat
Matrix used for laplace source terms.
Astract Problem which does depend on time.
virtual void getInitialCondition(DHVecPtr v) const
Build vector from function pointed by m_initialCondition.
CepsReal getTimeStep() const
pde time step
virtual void allocateArrays()
Allocates the arrays with the correct number of multistep.
virtual void displayProgress() const
Tells time.
TimeStepper * m_timeStepper
Monitors time evolution.
DHVecPtr getSolution() const
Returns a copy of the distributed vector containing the current solution.
void determineSolverType(CepsString s)
Initialize the type from parameter string.
virtual void swapMultiStepPointers()
Swaps vectors of array pointers for next step (for multistep methods)
virtual CepsBool finished() const
Tells if simulation reached end time or, if enabled, all points have seen an AP.
void solve() override
Solves the all PDE (all iterations)
CepsVector< DHVecPtr > m_regSourcesNm
Sources at previous steps (if problem has source terms)
CepsString m_type
Numerical scheme descriptor.
DMatPtr m_dtMat
Matrix of time derivative of the system.
void enableErrorComputation()
Sets the comparison with analytic solution.
CepsVector< DHVecPtr > m_uNm
Solution vectors at different time steps. Several vectors are needed for multi-step methods....
CepsUInt m_nbMultiSteps
Maximum number of steps needed to compute next solution (eg CN:2)
DVecPtr m_timeDerEqsVec
Vector of 1 or 0, depending on whether the dof equation has a time derivative or not.
CepsVector< DHVecPtr > m_lapSourcesNm
Sources at previous steps (if problem has laplace source terms)
CepsUInt getExpectedNumberOfOutputs() const override
Number of files written.
virtual ~AbstractTimedPdeSolver()
Destructor.
AbstractTimedPdeSolver(AbstractTimedPdeProblem *pb)
Default constructor.
void setupWithParameters(InputParameters *params) override
Set attributes from input file. Parameters are passed as arguments in case one wants to use other par...
CepsUInt m_nbIterSnapshot
Output perdiodicity.
AbstractTimedPdeProblem * getTimedProblem() const
Returns a pointer with the appropriate type of pb.
void updateAssemblers() override
Update assemblers and recompute everything is needed.
CepsArray2< CepsArray3< CepsArray3< CepsReal > > > getErrors() const
Gets the currently computed errors. First index selects absolute(0) or relative(1) second index selec...
virtual void output(DHVecPtr solution, CepsBool immediateWriting=true)
Prints the solution.
DVecPtr m_noTimeDerEqsVec
The opposite version of m_timeDerEqsVec, such as m_timeDerEqsVec + m_noTimeDerEqsVec = vec(1)
DHVecPtr m_uNp1
Vectors of unknowns at time t^n+1.
virtual void fillSourceTermsVector(CepsReal tn)
Adds contributions from all source terms into m_regSourcesNm[0].
Profiler * getProfiler() const
Access to profiler.
Definition: CepsObject.cpp:46
Reads and stores simulation configuration.
CepsString getString(const keyType &key) const
Reads a CepsString from configuration.
CepsReal getAbsoluteErrorNow(CepsInt px) const
Get norm of difference at current time.
CepsReal getRelativeErrorNow(CepsInt px) const
Get relative norm of difference at current time.
CepsReal getAbsoluteErrorCumulative(CepsInt px, CepsInt pt) const
Get cumulated norm of difference.
CepsReal getRelativeErrorCumulative(CepsInt px, CepsInt pt) const
Get relative cumulated norm of difference.
void compute(DHVecPtr num, CepsReal time=0.)
Compute the error at current time and add to total.
void stop(CepsString lbl)
Stops the measure of a labeled chronometer.
void start(CepsString lbl, CepsString dspl="")
Creates or continue a labeled chronometer.
void logMemoryUsage(const CepsString &xtic)
Writes a line with memory usage in profiling log, xtic is used to describe what the program is curren...
void actualizeAll(CepsReal time)
Actualize all data inside.
Manager *const getManager() const
Get a map of all source terms.
CepsVector< ScalarSourceTerm * > asVector() const
Get a vector of all source terms.
Source term, essentially a ScalarField.
Definition: SourceTerm.hpp:50
CepsReal getTimeStep() const
Time step.
Definition: TimeStepper.cpp:95
virtual CepsReal getTime()
current simulation time
void takeOneStep()
Updates the number of steps taken (derived steppers may compute new time and time step here)
CepsBool atEnd()
Whether time stepper has reached the end time or not.
CepsUInt getNbTakenTimeSteps() const
Number of time steps performed until now.
CepsReal getEndTime() const
End time of simulation.
Definition: TimeStepper.cpp:89
CepsReal getStartTime() const
startTime start time of simulation
Definition: TimeStepper.cpp:83
CepsBool hasSomethingToWrite() const
Tells if some data must be written. If not, why bother ?
Definition: TimeWriter.cpp:66
void write(CepsReal t, DHVecPtr data)
Writes the content of data at indices set in constructor.
Definition: TimeWriter.cpp:82
A class used to defined an unknown of a PDE problem The unknown can be defined on a specific region,...
Definition: Unknown.hpp:45
void addScalarData(const DHVecPtr &v, const CepsVector< CepsString > &fieldNames, const CepsVector< Unknown * > &us)
Set multiple scalar fields to be output by this writer. addScalarData for several unknowns.
Definition: VtkWriter.cpp:101
void write(CepsReal time=0., CepsBool writeXmlEntry=true)
Write all stored data.
Definition: VtkWriter.cpp:176
constexpr CepsHash get(_Type const &i)
get a hash from a single value
CepsString toString(_Tp value)
Convert a given value to a string (input has to be compatible with std::to_string)
Definition: CepsString.hpp:409
CepsBool isVerbose()
Check if the verbosity is enabled on the master proc (always false on slave procs).
Definition: CepsFlags.cpp:263
const _Type & max(const CepsVector< _Type, _Alloc > &vec)
Returns the maximum of the vector, const version.
Definition: CepsVector.hpp:464
CepsInt readInt(std::istream &file, const CepsString &errorMessage="")
Reads an integral number from an istream, aborts if conversion fails advances the stream by 1 word.
Definition: CepsString.cpp:677
CepsBool isMaster()
Is calling process the master ?
CepsBool isProfiling()
Check if we are currently profiling on the master proc (always false on slave procs).
Definition: CepsFlags.cpp:257
void destroyObject(_Type &)
Destroy[delete] any type.
Definition: CepsMemory.hpp:116