deal.II version GIT relicensing2069gd7d5dbb18d 20241101 22:40:00+00:00

#include <deal.II/numerics/data_postprocessor.h>
Public Member Functions  
virtual  ~DataPostprocessor () override=default 
virtual void  evaluate_scalar_field (const DataPostprocessorInputs::Scalar< dim > &input_data, std::vector< Vector< double > > &computed_quantities) const 
virtual void  evaluate_vector_field (const DataPostprocessorInputs::Vector< dim > &input_data, std::vector< Vector< double > > &computed_quantities) const 
virtual std::vector< std::string >  get_names () const =0 
virtual std::vector< DataComponentInterpretation::DataComponentInterpretation >  get_data_component_interpretation () const 
virtual UpdateFlags  get_needed_update_flags () const =0 
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 ::ExceptionBase &  ExcInUse (int arg1, std::string arg2, std::string arg3) 
static ::ExceptionBase &  ExcNoSubscriber (std::string arg1, std::string arg2) 
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  
std::atomic< unsigned int >  counter 
std::map< std::string, unsigned int >  counter_map 
std::vector< std::atomic< bool > * >  validity_pointers 
const std::type_info *  object_info 
Static Private Attributes  
static std::mutex  mutex 
This class provides an interface to compute derived quantities from a solution that can then be output in graphical formats for visualization, using facilities such as the DataOut class.
For the (graphical) output of a FE solution one frequently wants to include derived quantities, which are calculated from the values of the solution and possibly the first and second derivatives of the solution. Examples are the calculation of Mach numbers from velocity and density in supersonic flow computations, or the computation of the magnitude of a complexvalued solution as demonstrated in step29 and step58 (where it is actually the square of the magnitude). Other uses are shown in step32 and step33. This class offers the interface to perform such postprocessing. Given the values and derivatives of the solution at those points where we want to generated output, the functions of this class can be overloaded to compute new quantities.
A data vector and an object of a class derived from the current one can be given to the DataOut::add_data_vector() function (and similarly for DataOutRotation and DataOutFaces). This will cause DataOut::build_patches() to compute the derived quantities instead of using the data provided by the data vector (typically the solution vector). Note that the DataPostprocessor object (i.e., in reality the object of your derived class) has to live until the DataOut object is destroyed as the latter keeps a pointer to the former and will complain if the object pointed to is destroyed while the latter still has a pointer to it. If both the data postprocessor and DataOut objects are local variables of a function (as they are, for example, in step29), then you can avoid this error by declaring the data postprocessor variable before the DataOut variable as objects are destroyed in reverse order of declaration.
In order not to perform needless calculations, DataPostprocessor has to provide information which input data is needed for the calculation of the derived quantities, i.e. whether it needs the values, the first derivative and/or the second derivative of the provided data. DataPostprocessor objects which are used in combination with a DataOutFaces object can also ask for the normal vectors at each point. The information which data is needed has to be provided via the UpdateFlags returned by the virtual function get_needed_update_flags(). It is your responsibility to use only those values which were updated in the calculation of derived quantities. The DataOut object will provide references to the requested data in the call to evaluate_scalar_field() or evaluate_vector_field() (DataOut decides which of the two functions to call depending on whether the finite element in use has only a single, or multiple vector components; note that this is only determined by the number of components in the finite element in use, and not by whether the data computed by a class derived from the current one is scalar or vector valued).
Furthermore, derived classes have to implement the get_names() function, where the number of output variables returned by the latter function has to match the size of the vector returned by the former. Furthermore, this number has to match the number of computed quantities, of course.
Deriving from the current class allows to implement very general postprocessors. For example, in the step32 program, we implement a postprocessor that takes a solution that consists of velocity, pressure and temperature (dim+2 components) and computes a variety of output quantities, some of which are vector valued and some of which are scalar. On the other hand, in step29 we implement a postprocessor that only computes the magnitude of a complex number given by a twocomponent finite element. It seems silly to have to implement four virtual functions for this (evaluate_scalar_field() or evaluate_vector_field(), get_names(), get_update_flags() and get_data_component_interpretation()).
To this end there are three classes DataPostprocessorScalar, DataPostprocessorVector, and DataPostprocessorTensor that are meant to be used if the output quantity is either a single scalar, a single vector (here used meaning to have exactly dim
components), or a single tensor (here used meaning to have exactly dim*dim
components). When using these classes, one only has to write a constructor that passes the name of the output variable and the update flags to the constructor of the base class and overload the function that actually computes the results.
The DataPostprocessorVector and DataPostprocessorTensor class documentations also contains a extensive examples of how they can be used. The step29 tutorial program contains an example of using the DataPostprocessorScalar class.
There are PDEs whose solutions are complexvalued. For example, step58 and step62 solve problems whose solutions at each point consists of a complex number represented by a std::complex<double>
variable. (step29 also solves such a problem, but there we choose to represent the solution by two realvalued fields.) In such cases, the vector that is handed to DataOut::build_patches() is of type Vector<std::complex<double>>
, or something essentially equivalent to this. The issue with this, as also discussed in the documentation of DataOut itself, is that the most widely used file formats for visualization (notably, the VTK and VTU formats) can not actually represent complex quantities. The only thing that can be stored in these data files are realvalued quantities.
As a consequence, DataOut is forced to take things apart into their real and imaginary parts, and both are output as separate quantities. This is the case for data that is written directly to a file by DataOut, but it is also the case for data that is first routed through DataPostprocessor objects (or objects of their derived classes): All these objects see is a collection of real values, even if the underlying solution vector was complexvalued.
All of this has two implications:
step58 provides an example of how this class (or, rather, the derived DataPostprocessorScalar class) is used in a complexvalued situation.
Definition at line 582 of file data_postprocessor.h.

privateinherited 
The data type used in counter_map.
Definition at line 238 of file enable_observer_pointer.h.

privateinherited 
The iterator type used in counter_map.
Definition at line 243 of file enable_observer_pointer.h.

overridevirtualdefault 
Destructor. This function doesn't actually do anything but is marked as virtual to ensure that data postprocessors can be destroyed through pointers to the base class.

virtual 
This is the main function which actually performs the postprocessing. The second argument is a reference to the postprocessed data which already has correct size and must be filled by this function.
The function takes the values, gradients, and higher derivatives of the solution at all evaluation points, as well as other data such as the cell, via the first argument. Not all of the member vectors of this argument will be filled with data – in fact, derivatives and other quantities will only be contain valid data if the corresponding flags are returned by an overridden version of the get_needed_update_flags() function (implemented in a user's derived class). Otherwise those vectors will be in an unspecified state.
This function is called when the finite element field that is being converted into graphical data by DataOut or similar classes represents scalar data, i.e., if the finite element in use has only a single realvalued vector component.
Reimplemented in DataPostprocessors::BoundaryIds< dim >.
Definition at line 48 of file data_postprocessor.cc.

virtual 
Same as the evaluate_scalar_field() function, but this function is called when the original data vector represents vector data, i.e., the finite element in use has multiple vector components. This function is also called if the finite element is scalar but the solution vector is complexvalued. If the solution vector to be visualized is complexvalued (whether scalar or not), then the input data contains first all real parts of the solution vector at each evaluation point, and then all imaginary parts.
Definition at line 59 of file data_postprocessor.cc.

pure virtual 
Return the vector of strings describing the names of the computed quantities.
Implemented in DataPostprocessorScalar< dim >, DataPostprocessorVector< dim >, and DataPostprocessorTensor< dim >.

virtual 
This function returns information about how the individual components of output files that consist of more than one data set are to be interpreted.
For example, if one has a finite element for the Stokes equations in 2d, representing components (u,v,p), one would like to indicate that the first two, u and v, represent a logical vector so that later on when we generate graphical output we can hand them off to a visualization program that will automatically know to render them as a vector field, rather than as two separate and independent scalar fields.
The default implementation of this function returns a vector of values DataComponentInterpretation::component_is_scalar, indicating that all output components are independent scalar fields. However, if a derived class produces data that represents vectors, it may return a vector that contains values DataComponentInterpretation::component_is_part_of_vector. In the example above, one would return a vector with components (DataComponentInterpretation::component_is_part_of_vector, DataComponentInterpretation::component_is_part_of_vector, DataComponentInterpretation::component_is_scalar) for (u,v,p).
Reimplemented in DataPostprocessorScalar< dim >, DataPostprocessorVector< dim >, and DataPostprocessorTensor< dim >.
Definition at line 70 of file data_postprocessor.cc.

pure virtual 
Return, which data has to be provided to compute the derived quantities. This has to be a combination of update_values
, update_gradients
, update_hessians
and update_quadrature_points
. Note that the flag update_quadrature_points
updates DataPostprocessorInputs::CommonInputs::evaluation_points. If the DataPostprocessor is to be used in combination with DataOutFaces, you may also ask for a update of normals via the update_normal_vectors
flag. The description of the flags can be found at UpdateFlags.
Implemented in DataPostprocessorScalar< dim >, DataPostprocessorVector< dim >, and DataPostprocessorTensor< dim >.

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.

inherited 
Unsubscribes a user from the object.
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.

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.

inlineinherited 
List the subscribers to the input stream
.
Definition at line 339 of file enable_observer_pointer.h.

inherited 
List the subscribers to deallog
.
Definition at line 199 of file enable_observer_pointer.cc.

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.

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.
Definition at line 53 of file enable_observer_pointer.cc.

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.

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.

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.

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.

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.