Reference documentation for deal.II version 9.4.1
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Protected Attributes | Private Attributes | List of all members
Algorithms::ThetaTimestepping< VectorType > Class Template Reference

#include <deal.II/algorithms/theta_timestepping.h>

Inheritance diagram for Algorithms::ThetaTimestepping< VectorType >:
[legend]

Public Member Functions

 ThetaTimestepping (OperatorBase &op_explicit, OperatorBase &op_implicit)
 
virtual void operator() (AnyData &out, const AnyData &in) override
 
virtual void notify (const Event &) override
 
void set_output (OutputOperator< VectorType > &output)
 
void parse_parameters (ParameterHandler &param)
 
double current_time () const
 
double theta () const
 
double theta (double new_theta)
 
const TimestepDataexplicit_data () const
 
const TimestepDataimplicit_data () const
 
TimestepControltimestep_control ()
 
void clear_events ()
 

Static Public Member Functions

static void declare_parameters (ParameterHandler &param)
 

Protected Attributes

Event notifications
 

Private Attributes

TimestepControl control
 
double vtheta
 
bool adaptive
 
TimestepData d_explicit
 
TimestepData d_implicit
 
SmartPointer< OperatorBase, ThetaTimestepping< VectorType > > op_explicit
 
SmartPointer< OperatorBase, ThetaTimestepping< VectorType > > op_implicit
 
SmartPointer< OutputOperator< VectorType >, ThetaTimestepping< VectorType > > output
 

Subscriptor functionality

Classes derived from Subscriptor provide a facility to subscribe to this object. This is mostly used by the SmartPointer class.

std::atomic< unsigned intcounter
 
std::map< std::string, unsigned intcounter_map
 
std::vector< std::atomic< bool > * > validity_pointers
 
const std::type_info * object_info
 
void subscribe (std::atomic< bool > *const validity, const std::string &identifier="") const
 
void unsubscribe (std::atomic< bool > *const validity, const std::string &identifier="") const
 
unsigned int n_subscriptions () const
 
template<typename StreamType >
void list_subscribers (StreamType &stream) const
 
void list_subscribers () const
 
template<class Archive >
void serialize (Archive &ar, const unsigned int version)
 
static ::ExceptionBaseExcInUse (int arg1, std::string arg2, std::string arg3)
 
static ::ExceptionBaseExcNoSubscriber (std::string arg1, std::string arg2)
 
using map_value_type = decltype(counter_map)::value_type
 
using map_iterator = decltype(counter_map)::iterator
 
static std::mutex mutex
 
void check_no_subscribers () const noexcept
 

Detailed Description

template<typename VectorType>
class Algorithms::ThetaTimestepping< VectorType >

Application class performing the theta timestepping scheme.

The theta scheme is an abstraction of implicit and explicit Euler schemes, the Crank-Nicholson scheme and linear combinations of those. The choice of the actual scheme is controlled by the parameter theta as follows.

For fixed theta, the Crank-Nicholson scheme is the only second order scheme. Nevertheless, further stability may be achieved by choosing theta larger than ½, thereby introducing a first order error term. In order to avoid a loss of convergence order, the adaptive theta scheme can be used, where theta=½+c dt.

Assume that we want to solve the equation u' + F(u) = 0 with a step size k. A step of the theta scheme can be written as

\[ M u_{n+1} + \theta k F(u_{n+1}) = M u_n - (1-\theta)k F(u_n). \]

Here, M is the mass matrix. We see, that the right hand side amounts to an explicit Euler step with modified step size in weak form (up to inversion of M). The left hand side corresponds to an implicit Euler step with modified step size (right hand side given). Thus, the implementation of the theta scheme will use two Operator objects, one for the explicit, one for the implicit part. Each of these will use its own TimestepData to account for the modified step sizes (and different times if the problem is not autonomous). Note that once the explicit part has been computed, the left hand side actually constitutes a linear or nonlinear system which has to be solved.

Usage AnyData

ThetaTimestepping uses AnyData for communicating vectors and time step information. With outer or inner Operator objects. It does not use itself the input vectors provided, but forwards them to the explicit and implicit operators.

Vector data

The explicit Operator op_explicit receives in its input in first place the vector "Previous iterate", which is the solution value after the previous timestep. It is followed by all vectors provided to ThetaTimestepping::operator() as input argument. op_explicit is supposed to write its result into the first position of its output argument, labeled "Result".

The implicit Operator op_implicit receives the result of op_explicit in its first input vector labeled "Previous time". It is followed by all vectors provided to ThetaTimestepping::operator() as input argument. The output of op_implicit is directly written into the output argument given to ThetaTimestepping.

Scalar data

Since the introduction of AnyData, ThetaTimestepping is able to communicate the current time step information through AnyData as well. Therefore, the AnyData objects handed as input to op_explicit and op_implicit contain two entries of type const double* named "Time" and "Timestep". Note that "Time" refers to the time at the beginning of the current step for op_explicit and at the end for op_implicit, respectively.

Usage of ThetaTimestepping

The use ThetaTimestepping is more complicated than for instance Newton, since the inner operators will usually need to access the TimeStepData. Thus, we have a circular dependency of information, and we include the following example for its use.

First, we define the two operators used by ThetaTimestepping and call them Implicit and Explicit. They both share the public interface of Operator, and additionally provide storage for the matrices to be used and a pointer to TimestepData. Note that we do not use a SmartPointer here, since the TimestepData will be destroyed before the operator.

class Explicit : public OperatorBase
{
public:
Explicit(const FullMatrix<double> &matrix);
void operator()(AnyData &out, const AnyData &in);
private:
};
class Implicit : public OperatorBase
{
public:
Implicit(const FullMatrix<double> &matrix);
void operator()(AnyData &out, const AnyData &in);
private:
};

These operators will be implemented after the main program. But let us look first at how they get used. First, let us define a matrix to be used for our system and also an OutputOperator in order to write the data of each timestep to a file.

int main()
{
FullMatrix<double> matrix(2);
matrix(0, 0) = 0.;
matrix(1, 1) = 0.;
matrix(0, 1) = 3.14;
matrix(1, 0) = -3.14;
out.initialize_stream(std::cout);
void initialize_stream(std::ostream &stream)

Now we create objects for the implicit and explicit parts of the steps as well as the ThetaTimestepping itself. We initialize the timestepping with the output operator in order to be able to see the output in every step.

Explicit op_explicit(matrix);
Implicit op_implicit(matrix);
solver.set_output(out);
SmartPointer< OperatorBase, ThetaTimestepping< VectorType > > op_implicit
SmartPointer< OperatorBase, ThetaTimestepping< VectorType > > op_explicit

The next step is providing the vectors to be used. value is filled with the initial value and is also the vector where the solution at each timestep will be. Because the interface of Operator has to be able to handle several vectors, we need to store it in an AnyData object. Since our problem has no additional parameters, the input AnyData object remains empty.

Vector<double> value(2);
value(0) = 1.;
AnyData indata;
AnyData outdata;
outdata.add(&value, "value");
void add(type entry, const std::string &name)
Add a new data object.
Definition: any_data.h:432
Definition: vector.h:109

Finally, we are ready to tell the solver, that we are starting at the initial timestep and run it.

solver.notify(Events::initial);
solver(outdata, indata);
}
const Event initial
Definition: event.cc:65

Besides the main function, we need to define the members functions of the implicit and explicit operators. First the constructor, which simply copies the system matrix into the member pointer for later use.

Explicit::Explicit(const FullMatrix<double> &M)
: matrix(&M)
{
m.reinit(M.m(), M.n());
}
size_type n() const
size_type m() const

Now we need to study the application of the implicit and explicit operator. We assume that the pointer matrix points to the matrix created in the main program (the constructor did this for us). Here, we first get the time step size from the AnyData object that was provided as input. Then, if we are in the first step or if the timestep has changed, we fill the local matrix \(m\), such that with the given matrix \(M\), it becomes

\[ m = I - \Delta t M. \]

After we have worked off the notifications, we clear them, such that the matrix is only generated when necessary.

void Explicit::operator()(AnyData &out, const AnyData &in)
{
const double timestep = *in.read_ptr<double>("Timestep");
{
m.equ(-timestep, *matrix);
for (unsigned int i = 0; i < m.m(); ++i)
m(i, i) += 1.;
}
bool test(const Event &event) const
Definition: event.h:186
void clear()
Definition: event.cc:50
const type * read_ptr(const std::string &name) const
Dedicated read only access by name for pointer data.
Definition: any_data.h:385
const Event new_timestep_size
Definition: event.cc:69

Now we multiply the input vector with the new matrix and store on output.

m.vmult(*out.entry<Vector<double> *>(0),
*in.read_ptr<Vector<double>>("Previous iterate"));
}
type entry(const std::string &name)
Access to stored data object by name.
Definition: any_data.h:351

The code for the implicit operator is almost the same, except that we change the sign in front of the timestep and use the inverse of the matrix.

Implicit::Implicit(const FullMatrix<double> &M)
: matrix(&M)
{
m.reinit(M.m(), M.n());
}
void Implicit::operator()(AnyData &out, const AnyData &in)
{
const double timestep = *in.read_ptr<double>("Timestep");
if (this->notifications.test(Events::initial) ||
this->notifications.test(Events::new_timestep_size))
{
m.equ(timestep, *matrix);
for (unsigned int i = 0; i < m.m(); ++i)
m(i, i) += 1.;
m.gauss_jordan();
}
this->notifications.clear();
m.vmult(*out.entry<Vector<double> *>(0),
*in.read_ptr<Vector<double>>("Previous time"));
}

Definition at line 287 of file theta_timestepping.h.

Constructor & Destructor Documentation

◆ ThetaTimestepping()

template<typename VectorType >
Algorithms::ThetaTimestepping< VectorType >::ThetaTimestepping ( OperatorBase op_explicit,
OperatorBase op_implicit 
)

Constructor, receiving the two operators stored in op_explicit and op_implicit. For their meaning, see the description of those variables.

Member Function Documentation

◆ operator()()

template<typename VectorType >
virtual void Algorithms::ThetaTimestepping< VectorType >::operator() ( AnyData out,
const AnyData in 
)
overridevirtual

The timestepping scheme.

Parameters
inis ignored by ThetaTimestepping, but is merged into the AnyData objects used as input for the operators op_explicit and op_implicit.
outin its first argument must contain a pointer to a VectorType instance, which contains the initial value when the operator is called. It contains the final value when the operator returns.

Implements Algorithms::OperatorBase.

◆ notify()

template<typename VectorType >
virtual void Algorithms::ThetaTimestepping< VectorType >::notify ( const Event )
overridevirtual

Register an event triggered by an outer iteration.

Reimplemented from Algorithms::OperatorBase.

◆ set_output()

template<typename VectorType >
void Algorithms::ThetaTimestepping< VectorType >::set_output ( OutputOperator< VectorType > &  output)
inline

Define an operator which will output the result in each step. Note that no output will be generated without this.

Definition at line 463 of file theta_timestepping.h.

◆ declare_parameters()

template<typename VectorType >
static void Algorithms::ThetaTimestepping< VectorType >::declare_parameters ( ParameterHandler param)
static

Declare parameters in a parameter handler.

◆ parse_parameters()

template<typename VectorType >
void Algorithms::ThetaTimestepping< VectorType >::parse_parameters ( ParameterHandler param)

Read the parameters in the ParameterHandler.

◆ current_time()

template<typename VectorType >
double Algorithms::ThetaTimestepping< VectorType >::current_time
inline

The current time in the timestepping scheme.

Definition at line 489 of file theta_timestepping.h.

◆ theta() [1/2]

template<typename VectorType >
double Algorithms::ThetaTimestepping< VectorType >::theta
inline

The weight between implicit and explicit part.

Definition at line 471 of file theta_timestepping.h.

◆ theta() [2/2]

template<typename VectorType >
double Algorithms::ThetaTimestepping< VectorType >::theta ( double  new_theta)
inline

Set a new weight and return the old

Definition at line 479 of file theta_timestepping.h.

◆ explicit_data()

template<typename VectorType >
const TimestepData & Algorithms::ThetaTimestepping< VectorType >::explicit_data
inline

The data handed to the op_explicit time stepping operator.

The time in here is the time at the beginning of the current step, the time step is (1-theta) times the actual time step.

Definition at line 440 of file theta_timestepping.h.

◆ implicit_data()

template<typename VectorType >
const TimestepData & Algorithms::ThetaTimestepping< VectorType >::implicit_data
inline

The data handed to the op_implicit time stepping operator.

The time in here is the time at the beginning of the current step, the time step is theta times the actual time step.

Definition at line 448 of file theta_timestepping.h.

◆ timestep_control()

template<typename VectorType >
TimestepControl & Algorithms::ThetaTimestepping< VectorType >::timestep_control
inline

Allow access to the control object.

Definition at line 456 of file theta_timestepping.h.

◆ clear_events()

void Algorithms::OperatorBase::clear_events ( )
inherited

Clear all notifications.

Definition at line 49 of file operator.cc.

Member Data Documentation

◆ control

template<typename VectorType >
TimestepControl Algorithms::ThetaTimestepping< VectorType >::control
private

The object controlling the time step size and computing the new time in each step.

Definition at line 383 of file theta_timestepping.h.

◆ vtheta

template<typename VectorType >
double Algorithms::ThetaTimestepping< VectorType >::vtheta
private

The control parameter theta in the range [0,1]. It defaults to 0.5.

Definition at line 389 of file theta_timestepping.h.

◆ adaptive

template<typename VectorType >
bool Algorithms::ThetaTimestepping< VectorType >::adaptive
private

Use adaptive theta if true. Not yet implemented.

Definition at line 393 of file theta_timestepping.h.

◆ d_explicit

template<typename VectorType >
TimestepData Algorithms::ThetaTimestepping< VectorType >::d_explicit
private

The data for the explicit part of the scheme.

Definition at line 398 of file theta_timestepping.h.

◆ d_implicit

template<typename VectorType >
TimestepData Algorithms::ThetaTimestepping< VectorType >::d_implicit
private

The data for the implicit part of the scheme.

Definition at line 403 of file theta_timestepping.h.

◆ op_explicit

template<typename VectorType >
SmartPointer<OperatorBase, ThetaTimestepping<VectorType> > Algorithms::ThetaTimestepping< VectorType >::op_explicit
private

The operator computing the explicit part of the scheme. This will receive in its input data the value at the current time with name "Current time solution". It should obtain the current time and time step size from explicit_data().

Its return value is \( Mu+cF(u) \), where \(u\) is the current state vector, \(M\) the mass matrix, \(F\) the operator in space and \(c\) is the adjusted time step size \((1-\theta) \Delta t\).

Definition at line 416 of file theta_timestepping.h.

◆ op_implicit

template<typename VectorType >
SmartPointer<OperatorBase, ThetaTimestepping<VectorType> > Algorithms::ThetaTimestepping< VectorType >::op_implicit
private

The operator solving the implicit part of the scheme. It will receive in its input data the vector "Previous time". Information on the timestep should be obtained from implicit_data().

Its return value is the solution u of Mu-cF(u)=f, where f is the dual space vector found in the "Previous time" entry of the input data, M the mass matrix, F the operator in space and c is the adjusted time step size \( \theta \Delta t\)

Definition at line 428 of file theta_timestepping.h.

◆ output

template<typename VectorType >
SmartPointer<OutputOperator<VectorType>, ThetaTimestepping<VectorType> > Algorithms::ThetaTimestepping< VectorType >::output
private

The operator writing the output in each time step

Definition at line 434 of file theta_timestepping.h.

◆ notifications

Event Algorithms::OperatorBase::notifications
protectedinherited

Accumulate events here. If any of those is set, the function solve() of a terminal application must take care of reassembling the matrix.

Definition at line 97 of file operator.h.


The documentation for this class was generated from the following file: