From 1b018da002d91a20f1f90e498eb9c1ce95b63cdd Mon Sep 17 00:00:00 2001
From: Dmitri Naumov <dmitri.naumov@ufz.de>
Date: Fri, 18 May 2018 14:36:46 +0200
Subject: [PATCH] [PL] Add getNodalElementValues for all Parameters.

---
 ProcessLib/Parameter/ConstantParameter.h    | 18 +++++++++
 ProcessLib/Parameter/MeshElementParameter.h | 23 ++++++++++-
 ProcessLib/Parameter/MeshNodeParameter.h    | 23 +++++++++++
 ProcessLib/Parameter/Parameter.h            | 42 +++++++++++++++++++++
 4 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/ProcessLib/Parameter/ConstantParameter.h b/ProcessLib/Parameter/ConstantParameter.h
index 330c38de124..0b1c0759260 100644
--- a/ProcessLib/Parameter/ConstantParameter.h
+++ b/ProcessLib/Parameter/ConstantParameter.h
@@ -46,6 +46,24 @@ struct ConstantParameter final : public Parameter<T>
         return _values;
     }
 
+    Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> getNodalValuesOnElement(
+        MeshLib::Element const& element, double const /*t*/) const override
+    {
+        auto const n_nodes = element.getNumberOfNodes();
+        Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> result(
+            n_nodes, getNumberOfComponents());
+
+        // Column vector of values, copied for each node.
+        auto const row_values =
+            Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> const>(
+                _values.data(), _values.size());
+        for (unsigned i = 0; i < n_nodes; ++i)
+        {
+            result.row(i) = row_values;
+        }
+        return result;
+    }
+
 private:
     std::vector<T> const _values;
 };
diff --git a/ProcessLib/Parameter/MeshElementParameter.h b/ProcessLib/Parameter/MeshElementParameter.h
index 2679b41af70..250b2a0a8ba 100644
--- a/ProcessLib/Parameter/MeshElementParameter.h
+++ b/ProcessLib/Parameter/MeshElementParameter.h
@@ -11,8 +11,6 @@
 
 #include "Parameter.h"
 
-#include "BaseLib/Error.h"
-
 namespace MeshLib
 {
 template <typename T>
@@ -57,6 +55,27 @@ struct MeshElementParameter final : public Parameter<T> {
         return _cache;
     }
 
+    Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> getNodalValuesOnElement(
+        MeshLib::Element const& element, double const t) const override
+    {
+        auto const n_nodes = element.getNumberOfNodes();
+        Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> result(
+            n_nodes, getNumberOfComponents());
+
+        // Column vector of values, copied for each node.
+        SpatialPosition x_position;
+        x_position.setElementID(element.getID());
+        auto const& values = this->operator()(t, x_position);
+        auto const row_values =
+            Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> const>(
+                values.data(), values.size());
+        for (unsigned i = 0; i < n_nodes; ++i)
+        {
+            result.row(i) = row_values;
+        }
+        return result;
+    }
+
 private:
     MeshLib::PropertyVector<T> const& _property;
     mutable std::vector<double> _cache;
diff --git a/ProcessLib/Parameter/MeshNodeParameter.h b/ProcessLib/Parameter/MeshNodeParameter.h
index 9920fbdebde..77c030933e9 100644
--- a/ProcessLib/Parameter/MeshNodeParameter.h
+++ b/ProcessLib/Parameter/MeshNodeParameter.h
@@ -12,6 +12,8 @@
 #include "Parameter.h"
 
 #include "BaseLib/Error.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/Node.h"
 
 namespace MeshLib
 {
@@ -57,6 +59,27 @@ struct MeshNodeParameter final : public Parameter<T> {
         return _cache;
     }
 
+    Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> getNodalValuesOnElement(
+        MeshLib::Element const& element, double const t) const override
+    {
+        auto const n_nodes = element.getNumberOfNodes();
+        Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> result(
+            n_nodes, getNumberOfComponents());
+
+        SpatialPosition x_position;
+        auto const nodes = element.getNodes();
+        for (unsigned i = 0; i < n_nodes; ++i)
+        {
+            x_position.setNodeID(nodes[i]->getID());
+            auto const& values = this->operator()(t, x_position);
+            result.row(i) =
+                Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> const>(
+                    values.data(), values.size());
+        }
+
+        return result;
+    }
+
 private:
     MeshLib::PropertyVector<T> const& _property;
     mutable std::vector<double> _cache;
diff --git a/ProcessLib/Parameter/Parameter.h b/ProcessLib/Parameter/Parameter.h
index 8826df2628b..32f6a47bf8a 100644
--- a/ProcessLib/Parameter/Parameter.h
+++ b/ProcessLib/Parameter/Parameter.h
@@ -13,6 +13,13 @@
 #include <memory>
 #include <utility>
 #include <vector>
+
+#include <Eigen/Dense>
+
+#include "BaseLib/Error.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/Node.h"
+
 #include "SpatialPosition.h"
 
 namespace BaseLib
@@ -72,6 +79,41 @@ struct Parameter : public ParameterBase
     //! Returns the parameter value at the given time and position.
     virtual std::vector<T> const& operator()(
         double const t, SpatialPosition const& pos) const = 0;
+
+    //! Returns a matrix of values for all nodes of the given element.
+    //
+    // The matrix is of the shape NxC, where N is the number of nodes and C is
+    // the number of components, such that subsequent multiplication with shape
+    // functions matrix from left (which is a row vector) results in a row
+    // vector of length C.
+    //
+    // The default implementation covers all cases, but the derived classes may
+    // provide faster implementations.
+    virtual Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
+    getNodalValuesOnElement(MeshLib::Element const& element,
+                            double const t) const
+    {
+        auto const n_nodes = static_cast<int>(element.getNumberOfNodes());
+        auto const n_components = getNumberOfComponents();
+        Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> result(n_nodes,
+                                                                n_components);
+
+        // Column vector of values, copied for each node.
+        SpatialPosition x_position;
+        auto const nodes = element.getNodes();
+        for (int i = 0; i < n_nodes; ++i)
+        {
+            x_position.setAll(
+                nodes[i]->getID(), element.getID(), boost::none, boost::none);
+            auto const& values = this->operator()(t, x_position);
+            auto const row_values =
+                Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> const>(
+                    values.data(), values.size());
+            result.row(i) = row_values;
+        }
+
+        return result;
+    }
 };
 
 //! Constructs a new ParameterBase from the given configuration.
-- 
GitLab