From 8da8a70ce0e14bd493dc7e8abdd2bc62c8e67242 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Wed, 3 Feb 2021 16:46:06 +0100
Subject: [PATCH] Begin discrete functions handling in the language

First tests with a crappy P0 functions
---
 CMakeLists.txt                             |  1 +
 src/CMakeLists.txt                         |  3 ++
 src/language/modules/SchemeModule.cpp      | 27 +++++++++++
 src/language/modules/SchemeModule.hpp      | 10 ++++
 src/scheme/CMakeLists.txt                  |  5 ++
 src/scheme/DiscreteFunctionInterpoler.cpp  | 55 ++++++++++++++++++++++
 src/scheme/DiscreteFunctionInterpoler.hpp  | 36 ++++++++++++++
 src/scheme/IDiscreteFunction.hpp           | 16 +++++++
 src/scheme/IDiscreteFunctionDescriptor.hpp | 41 ++++++++++++++++
 tests/CMakeLists.txt                       |  5 +-
 10 files changed, 198 insertions(+), 1 deletion(-)
 create mode 100644 src/scheme/CMakeLists.txt
 create mode 100644 src/scheme/DiscreteFunctionInterpoler.cpp
 create mode 100644 src/scheme/DiscreteFunctionInterpoler.hpp
 create mode 100644 src/scheme/IDiscreteFunction.hpp
 create mode 100644 src/scheme/IDiscreteFunctionDescriptor.hpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 45c69b7a0..97a94a4ef 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -528,6 +528,7 @@ target_link_libraries(
   PugsLanguageAlgorithms
   PugsMesh
   PugsAlgebra
+  PugsScheme
   PugsUtils
   PugsLanguageUtils
   kokkos
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1b21f79a7..e9c207b2f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,5 +15,8 @@ add_subdirectory(algebra)
 # Pugs mesh
 add_subdirectory(mesh)
 
+# Pugs mesh
+add_subdirectory(scheme)
+
 # Pugs output
 #add_subdirectory(output)
diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp
index 542690a4f..e691e248a 100644
--- a/src/language/modules/SchemeModule.cpp
+++ b/src/language/modules/SchemeModule.cpp
@@ -5,10 +5,13 @@
 #include <language/utils/TypeDescriptor.hpp>
 #include <mesh/Mesh.hpp>
 #include <scheme/DirichletBoundaryConditionDescriptor.hpp>
+#include <scheme/DiscreteFunctionInterpoler.hpp>
 #include <scheme/FourierBoundaryConditionDescriptor.hpp>
 #include <scheme/FreeBoundaryConditionDescriptor.hpp>
 #include <scheme/IBoundaryConditionDescriptor.hpp>
 #include <scheme/IBoundaryDescriptor.hpp>
+#include <scheme/IDiscreteFunction.hpp>
+#include <scheme/IDiscreteFunctionDescriptor.hpp>
 #include <scheme/NamedBoundaryDescriptor.hpp>
 #include <scheme/NeumannBoundaryConditionDescriptor.hpp>
 #include <scheme/NumberedBoundaryDescriptor.hpp>
@@ -18,9 +21,33 @@
 
 SchemeModule::SchemeModule()
 {
+  this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IDiscreteFunction>>);
+  this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IDiscreteFunctionDescriptor>>);
+
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IBoundaryDescriptor>>);
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IBoundaryConditionDescriptor>>);
 
+  this->_addBuiltinFunction("P0", std::make_shared<
+                                    BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunctionDescriptor>()>>(
+                                    []() -> std::shared_ptr<const IDiscreteFunctionDescriptor> {
+                                      return std::make_shared<DiscreteFunctionDescriptorP0>();
+                                    }
+
+                                    ));
+
+  this->_addBuiltinFunction(
+    "interpolate",
+    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
+      const IDiscreteFunction>(std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunctionDescriptor>,
+                               const FunctionSymbolId&)>>(
+      [](std::shared_ptr<const IMesh> mesh,
+         std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor,
+         const FunctionSymbolId& function_id) -> std::shared_ptr<const IDiscreteFunction> {
+        return DiscreteFunctionInterpoler{mesh, discrete_function_descriptor, function_id}.interpolate();
+      }
+
+      ));
+
   this->_addBuiltinFunction("boundaryName",
                             std::make_shared<
                               BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>(const std::string&)>>(
diff --git a/src/language/modules/SchemeModule.hpp b/src/language/modules/SchemeModule.hpp
index 96418b169..3cfbb254a 100644
--- a/src/language/modules/SchemeModule.hpp
+++ b/src/language/modules/SchemeModule.hpp
@@ -15,6 +15,16 @@ template <>
 inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IBoundaryConditionDescriptor>> =
   ASTNodeDataType::build<ASTNodeDataType::type_id_t>("boundary_condition");
 
+class IDiscreteFunction;
+template <>
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IDiscreteFunction>> =
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("Vh");
+
+class IDiscreteFunctionDescriptor;
+template <>
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IDiscreteFunctionDescriptor>> =
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("Vh_type");
+
 class SchemeModule : public BuiltinModule
 {
  public:
diff --git a/src/scheme/CMakeLists.txt b/src/scheme/CMakeLists.txt
new file mode 100644
index 000000000..1467393f2
--- /dev/null
+++ b/src/scheme/CMakeLists.txt
@@ -0,0 +1,5 @@
+# ------------------- Source files --------------------
+
+add_library(
+  PugsScheme
+  DiscreteFunctionInterpoler.cpp)
diff --git a/src/scheme/DiscreteFunctionInterpoler.cpp b/src/scheme/DiscreteFunctionInterpoler.cpp
new file mode 100644
index 000000000..55348a408
--- /dev/null
+++ b/src/scheme/DiscreteFunctionInterpoler.cpp
@@ -0,0 +1,55 @@
+#include <scheme/DiscreteFunctionInterpoler.hpp>
+
+#include <language/utils/InterpolateItemValue.hpp>
+#include <mesh/Connectivity.hpp>
+#include <mesh/Mesh.hpp>
+#include <mesh/MeshData.hpp>
+#include <mesh/MeshDataManager.hpp>
+#include <utils/Exceptions.hpp>
+
+template <typename DataType>
+class DiscreteFunctionP0 : public IDiscreteFunction
+{
+ private:
+  CellValue<DataType> m_cell_value;
+
+ public:
+  DiscreteFunctionP0(const CellValue<DataType>& cell_value) : m_cell_value{cell_value} {}
+  DiscreteFunctionP0(CellValue<DataType>&& cell_value) : m_cell_value{std::move(cell_value)} {}
+  ~DiscreteFunctionP0() = default;
+};
+
+template <size_t Dimension>
+std::shared_ptr<IDiscreteFunction>
+DiscreteFunctionInterpoler::_interpolate() const
+{
+  using MeshType       = Mesh<Connectivity<Dimension>>;
+  const MeshType& mesh = dynamic_cast<const MeshType&>(*m_mesh);
+
+  using MeshDataType      = MeshData<Dimension>;
+  MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(mesh);
+
+  return std::make_shared<DiscreteFunctionP0<double>>(
+    InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::cell>(m_function_id,
+                                                                                              mesh_data.xj()));
+}
+
+std::shared_ptr<IDiscreteFunction>
+DiscreteFunctionInterpoler::interpolate() const
+{
+  switch (m_mesh->dimension()) {
+  case 1: {
+    return this->_interpolate<1>();
+  }
+  case 2: {
+    return this->_interpolate<2>();
+  }
+  case 3: {
+    return this->_interpolate<3>();
+  }
+  default: {
+    throw UnexpectedError("invalid dimension");
+  }
+  }
+  return nullptr;
+}
diff --git a/src/scheme/DiscreteFunctionInterpoler.hpp b/src/scheme/DiscreteFunctionInterpoler.hpp
new file mode 100644
index 000000000..8f679c763
--- /dev/null
+++ b/src/scheme/DiscreteFunctionInterpoler.hpp
@@ -0,0 +1,36 @@
+#ifndef DISCRETE_FUNCTION_INTERPOLER_HPP
+#define DISCRETE_FUNCTION_INTERPOLER_HPP
+
+#include <language/utils/FunctionSymbolId.hpp>
+#include <mesh/IMesh.hpp>
+#include <scheme/IDiscreteFunction.hpp>
+#include <scheme/IDiscreteFunctionDescriptor.hpp>
+
+#include <memory>
+
+class DiscreteFunctionInterpoler
+{
+ private:
+  std::shared_ptr<const IMesh> m_mesh;
+  std::shared_ptr<const IDiscreteFunctionDescriptor> m_discrete_function_descriptor;
+  const FunctionSymbolId m_function_id;
+
+  template <size_t Dimension>
+  std::shared_ptr<IDiscreteFunction> _interpolate() const;
+
+ public:
+  std::shared_ptr<IDiscreteFunction> interpolate() const;
+
+  DiscreteFunctionInterpoler(const std::shared_ptr<const IMesh>& mesh,
+                             const std::shared_ptr<const IDiscreteFunctionDescriptor>& discrete_function_descriptor,
+                             const FunctionSymbolId& function_id)
+    : m_mesh{mesh}, m_discrete_function_descriptor{discrete_function_descriptor}, m_function_id{function_id}
+  {}
+
+  DiscreteFunctionInterpoler(const DiscreteFunctionInterpoler&) = delete;
+  DiscreteFunctionInterpoler(DiscreteFunctionInterpoler&&)      = delete;
+
+  ~DiscreteFunctionInterpoler() = default;
+};
+
+#endif   // DISCRETE_FUNCTION_INTERPOLER_HPP
diff --git a/src/scheme/IDiscreteFunction.hpp b/src/scheme/IDiscreteFunction.hpp
new file mode 100644
index 000000000..3eea07af9
--- /dev/null
+++ b/src/scheme/IDiscreteFunction.hpp
@@ -0,0 +1,16 @@
+#ifndef I_DISCRETE_FUNCTION_HPP
+#define I_DISCRETE_FUNCTION_HPP
+
+class IDiscreteFunction
+{
+ public:
+  IDiscreteFunction() = default;
+
+  IDiscreteFunction(const IDiscreteFunction&) = default;
+
+  IDiscreteFunction(IDiscreteFunction&&) noexcept = default;
+
+  virtual ~IDiscreteFunction() noexcept = default;
+};
+
+#endif   // I_DISCRETE_FUNCTION_HPP
diff --git a/src/scheme/IDiscreteFunctionDescriptor.hpp b/src/scheme/IDiscreteFunctionDescriptor.hpp
new file mode 100644
index 000000000..c2b795d6d
--- /dev/null
+++ b/src/scheme/IDiscreteFunctionDescriptor.hpp
@@ -0,0 +1,41 @@
+#ifndef I_DISCRETE_FUNCTION_DESCRIPTOR_HPP
+#define I_DISCRETE_FUNCTION_DESCRIPTOR_HPP
+
+enum class DiscreteFunctionDescriptorType
+{
+  P0
+};
+
+class IDiscreteFunctionDescriptor
+{
+ public:
+  virtual DiscreteFunctionDescriptorType type() const = 0;
+
+  IDiscreteFunctionDescriptor() noexcept = default;
+
+  IDiscreteFunctionDescriptor(const IDiscreteFunctionDescriptor&) = default;
+
+  IDiscreteFunctionDescriptor(IDiscreteFunctionDescriptor&&) noexcept = default;
+
+  virtual ~IDiscreteFunctionDescriptor() noexcept = default;
+};
+
+class DiscreteFunctionDescriptorP0 : public IDiscreteFunctionDescriptor
+{
+ public:
+  DiscreteFunctionDescriptorType
+  type() const final
+  {
+    return DiscreteFunctionDescriptorType::P0;
+  }
+
+  DiscreteFunctionDescriptorP0() noexcept = default;
+
+  DiscreteFunctionDescriptorP0(const DiscreteFunctionDescriptorP0& other) = default;
+
+  DiscreteFunctionDescriptorP0(DiscreteFunctionDescriptorP0&& other) noexcept = default;
+
+  ~DiscreteFunctionDescriptorP0() noexcept = default;
+};
+
+#endif   // I_DISCRETE_FUNCTION_DESCRIPTOR_HPP
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b2c9f5015..06518e70d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -113,6 +113,7 @@ target_link_libraries (unit_tests
   PugsLanguage
   PugsMesh
   PugsAlgebra
+  PugsScheme
   PugsUtils
   kokkos
   ${PARMETIS_LIBRARIES}
@@ -134,7 +135,9 @@ target_link_libraries (mpi_unit_tests
   PugsMesh
   PugsAlgebra
   PugsUtils
-  PugsLanguageUtils  PugsUtils
+  PugsLanguageUtils
+  PugsScheme
+  PugsUtils
   PugsAlgebra
   PugsMesh
   kokkos
-- 
GitLab