deal.II version GIT relicensing-2171-g98af52917d 2024-11-23 14:40:00+00:00
\(\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 Types | Private Member Functions | Private Attributes | Static 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 >:
Inheritance graph
[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 ()
 
template<class Archive >
void serialize (Archive &ar, const unsigned int version)
 
EnableObserverPointer functionality

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

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
 

Static Public Member Functions

static void declare_parameters (ParameterHandler &param)
 
static ::ExceptionBaseExcInUse (int arg1, std::string arg2, std::string arg3)
 
static ::ExceptionBaseExcNoSubscriber (std::string arg1, std::string arg2)
 

Protected Attributes

Event notifications
 

Private Types

using map_value_type = decltype(counter_map)::value_type
 
using map_iterator = decltype(counter_map)::iterator
 

Private Member Functions

void check_no_subscribers () const noexcept
 

Private Attributes

TimestepControl control
 
double vtheta
 
bool adaptive
 
TimestepData d_explicit
 
TimestepData d_implicit
 
ObserverPointer< OperatorBase, ThetaTimestepping< VectorType > > op_explicit
 
ObserverPointer< OperatorBase, ThetaTimestepping< VectorType > > op_implicit
 
ObserverPointer< OutputOperator< VectorType >, ThetaTimestepping< VectorType > > output
 
std::atomic< unsigned intcounter
 
std::map< std::string, unsigned intcounter_map
 
std::vector< std::atomic< bool > * > validity_pointers
 
const std::type_info * object_info
 

Static Private Attributes

static std::mutex mutex
 

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-Nicolson 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-Nicolson 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 ObserverPointer 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);
ObserverPointer< OperatorBase, ThetaTimestepping< VectorType > > op_explicit
ObserverPointer< OperatorBase, ThetaTimestepping< VectorType > > op_implicit

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:430

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:64

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:185
const type * read_ptr(const std::string &name) const
Dedicated read only access by name for pointer data.
Definition any_data.h:383
const Event new_timestep_size
Definition event.cc:68

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:349

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 286 of file theta_timestepping.h.

Member Typedef Documentation

◆ map_value_type

using EnableObserverPointer::map_value_type = decltype(counter_map)::value_type
privateinherited

The data type used in counter_map.

Definition at line 238 of file enable_observer_pointer.h.

◆ map_iterator

using EnableObserverPointer::map_iterator = decltype(counter_map)::iterator
privateinherited

The iterator type used in counter_map.

Definition at line 243 of file enable_observer_pointer.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 462 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 ( ) const
inline

The current time in the timestepping scheme.

Definition at line 488 of file theta_timestepping.h.

◆ theta() [1/2]

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

The weight between implicit and explicit part.

Definition at line 470 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 478 of file theta_timestepping.h.

◆ explicit_data()

template<typename VectorType >
const TimestepData & Algorithms::ThetaTimestepping< VectorType >::explicit_data ( ) const
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 439 of file theta_timestepping.h.

◆ implicit_data()

template<typename VectorType >
const TimestepData & Algorithms::ThetaTimestepping< VectorType >::implicit_data ( ) const
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 447 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 455 of file theta_timestepping.h.

◆ clear_events()

void Algorithms::OperatorBase::clear_events ( )
inherited

Clear all notifications.

Definition at line 46 of file operator.cc.

◆ subscribe()

void EnableObserverPointer::subscribe ( std::atomic< bool > *const  validity,
const std::string &  identifier = "" 
) const
inherited

Subscribes a user of the object by storing the pointer validity. The subscriber may be identified by text supplied as identifier.

Definition at line 131 of file enable_observer_pointer.cc.

◆ unsubscribe()

void EnableObserverPointer::unsubscribe ( std::atomic< bool > *const  validity,
const std::string &  identifier = "" 
) const
inherited

Unsubscribes a user from the object.

Note
The identifier and the validity pointer must be the same as the one supplied to subscribe().

Definition at line 151 of file enable_observer_pointer.cc.

◆ n_subscriptions()

unsigned int EnableObserverPointer::n_subscriptions ( ) const
inlineinherited

Return the present number of subscriptions to this object. This allows to use this class for reference counted lifetime determination where the last one to unsubscribe also deletes the object.

Definition at line 322 of file enable_observer_pointer.h.

◆ list_subscribers() [1/2]

template<typename StreamType >
void EnableObserverPointer::list_subscribers ( StreamType &  stream) const
inlineinherited

List the subscribers to the input stream.

Definition at line 339 of file enable_observer_pointer.h.

◆ list_subscribers() [2/2]

void EnableObserverPointer::list_subscribers ( ) const
inherited

List the subscribers to deallog.

Definition at line 199 of file enable_observer_pointer.cc.

◆ serialize()

template<class Archive >
void EnableObserverPointer::serialize ( Archive &  ar,
const unsigned int  version 
)
inlineinherited

Read or write the data of this object to or from a stream for the purpose of serialization using the BOOST serialization library.

This function does not actually serialize any of the member variables of this class. The reason is that what this class stores is only who subscribes to this object, but who does so at the time of storing the contents of this object does not necessarily have anything to do with who subscribes to the object when it is restored. Consequently, we do not want to overwrite the subscribers at the time of restoring, and then there is no reason to write the subscribers out in the first place.

Definition at line 331 of file enable_observer_pointer.h.

◆ check_no_subscribers()

void EnableObserverPointer::check_no_subscribers ( ) const
privatenoexceptinherited

Check that there are no objects subscribing to this object. If this check passes then it is safe to destroy the current object. It this check fails then this function will either abort or print an error message to deallog (by using the AssertNothrow mechanism), but will not throw an exception.

Note
Since this function is just a consistency check it does nothing in release mode.
If this function is called when there is an uncaught exception then, rather than aborting, this function prints an error message to the standard error stream and returns.

Definition at line 53 of file enable_observer_pointer.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 382 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 388 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 392 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 397 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 402 of file theta_timestepping.h.

◆ op_explicit

template<typename VectorType >
ObserverPointer<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 415 of file theta_timestepping.h.

◆ op_implicit

template<typename VectorType >
ObserverPointer<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 427 of file theta_timestepping.h.

◆ output

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

The operator writing the output in each time step

Definition at line 433 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 96 of file operator.h.

◆ counter

std::atomic<unsigned int> EnableObserverPointer::counter
mutableprivateinherited

Store the number of objects which subscribed to this object. Initially, this number is zero, and upon destruction it shall be zero again (i.e. all objects which subscribed should have unsubscribed again).

The creator (and owner) of an object is counted in the map below if HE manages to supply identification.

We use the mutable keyword in order to allow subscription to constant objects also.

This counter may be read from and written to concurrently in multithreaded code: hence we use the std::atomic class template.

Definition at line 227 of file enable_observer_pointer.h.

◆ counter_map

std::map<std::string, unsigned int> EnableObserverPointer::counter_map
mutableprivateinherited

In this map, we count subscriptions for each different identification string supplied to subscribe().

Definition at line 233 of file enable_observer_pointer.h.

◆ validity_pointers

std::vector<std::atomic<bool> *> EnableObserverPointer::validity_pointers
mutableprivateinherited

In this vector, we store pointers to the validity bool in the ObserverPointer objects that subscribe to this class.

Definition at line 249 of file enable_observer_pointer.h.

◆ object_info

const std::type_info* EnableObserverPointer::object_info
mutableprivateinherited

Pointer to the typeinfo object of this object, from which we can later deduce the class name. Since this information on the derived class is neither available in the destructor, nor in the constructor, we obtain it in between and store it here.

Definition at line 257 of file enable_observer_pointer.h.

◆ mutex

std::mutex EnableObserverPointer::mutex
staticprivateinherited

A mutex used to ensure data consistency when accessing the mutable members of this class. This lock is used in the subscribe() and unsubscribe() functions, as well as in list_subscribers().

Definition at line 280 of file enable_observer_pointer.h.


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