]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Document DataPostprocessor for the case of complex-valued solutions. 8770/head
authorWolfgang Bangerth <bangerth@colostate.edu>
Tue, 17 Sep 2019 00:20:03 +0000 (18:20 -0600)
committerWolfgang Bangerth <bangerth@colostate.edu>
Tue, 24 Sep 2019 20:44:33 +0000 (14:44 -0600)
include/deal.II/numerics/data_postprocessor.h

index 9ddb3232f34fd79fa1624f5b1dbb428a53b9d7d5..9242a8830b2507762057785d32b35be14f0542fe 100644 (file)
@@ -218,7 +218,12 @@ namespace DataPostprocessorInputs
    * A structure that is used to pass information to
    * DataPostprocessor::evaluate_scalar_field(). It contains
    * the values and (if requested) derivatives of a scalar solution
-   * variable at the evaluation points on a cell or face.
+   * variable at the evaluation points on a cell or face. (This class
+   * is not used if a scalar solution is complex-valued, however,
+   * since in that case the real and imaginary parts are treated
+   * separately -- resulting in vector-valued inputs to data
+   * postprocessors, which are then passed to
+   * DataPostprocessor::evaluate_vector_field() instead.)
    *
    * Through the fields in the CommonInputs base class, this class also
    * makes available access to the locations of evaluations points,
@@ -276,6 +281,29 @@ namespace DataPostprocessorInputs
    * the values and (if requested) derivatives of a vector-valued solution
    * variable at the evaluation points on a cell or face.
    *
+   * This class is also used if the solution vector is complex-valued
+   * (whether it is scalar- or vector-valued is immaterial in that case)
+   * since in that case, the DataOut and related classes take apart the real
+   * and imaginary parts of a solution vector. In practice, that means that
+   * if a solution vector has $N$ vector components (i.e., there are
+   * $N$ functions that form the solution of the PDE you are dealing with;
+   * $N$ is not the size of the solution vector), then if the solution is
+   * real-valued the `solution_values` variable below will be an array
+   * with as many entries as there are evaluation points on a cell,
+   * and each entry is a vector of length $N$ representing the $N$
+   * solution functions evaluated at a point. On the other hand, if
+   * the solution is complex-valued (i.e., the vector passed to
+   * DataOut::build_patches() has complex-valued entries), then the
+   * `solution_values` member variable of this class will have $2N$
+   * entries for each evaluation point. The first $N$ of these entries
+   * represent the real parts of the solution, and the second $N$ entries
+   * correspond to the imaginary parts of the solution evaluated at the
+   * evaluation point. The same layout is used for the `solution_gradients`
+   * and `solution_hessians` fields: First the gradients/Hessians of
+   * the real components, then all the gradients/Hessians of the
+   * imaginary components. There is more information about the subject in the
+   * documentation of the DataPostprocessor class itself.
+   *
    * Through the fields in the CommonInputs base class, this class also
    * makes available access to the locations of evaluations points,
    * normal vectors (if appropriate), and which cell data is currently
@@ -422,8 +450,47 @@ namespace DataPostprocessorInputs
  * class.
  *
  *
+ * <h3>Complex-valued solutions</h3>
+ *
+ * There are PDEs whose solutions are complex-valued. For example, step-62
+ * solves a problem whose solution at each point consists of a complex number
+ * represented by a `std::complex<double>` variable. (step-29 also solves such
+ * a problem, but there we choose to represent the solution by two real-valued
+ * 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 real-valued 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 complex-valued.
+ *
+ * All of this has two implications:
+ * - If a solution vector is complex-valued, then this results in at least
+ *   two input components at each evaluation point. As a consequence, the
+ *   DataPostprocessor::evaluate_scalar_field() function is never called,
+ *   even if the underlying finite element had only a single solution
+ *   component. Instead, DataOut will *always* call
+ *   DataPostprocessor::evaluate_vector_field().
+ * - Implementations of the DataPostprocessor::evaluate_vector_field() in
+ *   derived classes must understand how the solution values are arranged
+ *   in the DataPostprocessorInputs::Vector objects they receive as input.
+ *   The rule here is: If the finite element has $N$ vector components
+ *   (including the case $N=1$, i.e., a scalar element), then the inputs
+ *   for complex-valued solution vectors will have $2N$ components. These
+ *   first contain the values (or gradients, or Hessians) of the real
+ *   parts of all solution components, and then the values (or gradients,
+ *   or Hessians) of the imaginary parts of all solution components.
+ *
+ *
  * @ingroup output
- * @author Tobias Leicht, 2007, Wolfgang Bangerth, 2016
+ * @author Tobias Leicht, 2007; Wolfgang Bangerth, 2016, 2019
  */
 template <int dim>
 class DataPostprocessor : public Subscriptor
@@ -452,8 +519,8 @@ public:
    *
    * 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. the finite element in use has only a single vector
-   * component.
+   * scalar data, i.e., if the finite element in use has only a single
+   * real-valued vector component.
    */
   virtual void
   evaluate_scalar_field(const DataPostprocessorInputs::Scalar<dim> &input_data,
@@ -462,7 +529,12 @@ public:
   /**
    * 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.
+   * 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 complex-valued. If the solution vector to be visualized
+   * is complex-valued (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.
    */
   virtual void
   evaluate_vector_field(const DataPostprocessorInputs::Vector<dim> &input_data,
@@ -528,7 +600,8 @@ public:
  *
  * All derived classes have to do is implement a constructor and overload
  * either DataPostprocessor::evaluate_scalar_field() or
- * DataPostprocessor::evaluate_vector_field().
+ * DataPostprocessor::evaluate_vector_field() as discussed in the
+ * DataPostprocessor class's documentation.
  *
  * An example of how this class can be used can be found in step-29.
  * An example of how the closely related DataPostprocessorVector
@@ -609,7 +682,8 @@ private:
  *
  * All derived classes have to do is implement a constructor and overload
  * either DataPostprocessor::evaluate_scalar_field() or
- * DataPostprocessor::evaluate_vector_field().
+ * DataPostprocessor::evaluate_vector_field() as discussed in the
+ * DataPostprocessor class's documentation.
  *
  * An example of how the closely related class DataPostprocessorScalar is used
  * can be found in step-29. An example of how the DataPostprocessorTensor
@@ -873,7 +947,8 @@ private:
  *
  * All derived classes have to do is implement a constructor and overload
  * either DataPostprocessor::evaluate_scalar_field() or
- * DataPostprocessor::evaluate_vector_field().
+ * DataPostprocessor::evaluate_vector_field() as discussed in the
+ * DataPostprocessor class's documentation.
  *
  * An example of how the closely related class DataPostprocessorScalar is used
  * can be found in step-29. An example of how the DataPostprocessorVector

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.