From 3475b545388ce7fdabae13fda34e8305416b0de6 Mon Sep 17 00:00:00 2001
From: renchao_lu <renchao.lu@gmail.com>
Date: Sun, 30 May 2021 18:45:50 +0200
Subject: [PATCH] [PL/Stokes] create Stokes flow process.

---
 Applications/ApplicationsLib/ProjectData.cpp  |  24 +++
 .../StokesFlow/CreateStokesFlowProcess.cpp    | 164 ++++++++++++++++++
 .../StokesFlow/CreateStokesFlowProcess.h      |  45 +++++
 3 files changed, 233 insertions(+)
 create mode 100644 ProcessLib/StokesFlow/CreateStokesFlowProcess.cpp
 create mode 100644 ProcessLib/StokesFlow/CreateStokesFlowProcess.h

diff --git a/Applications/ApplicationsLib/ProjectData.cpp b/Applications/ApplicationsLib/ProjectData.cpp
index 7c05d1c596c..f5c400293ad 100644
--- a/Applications/ApplicationsLib/ProjectData.cpp
+++ b/Applications/ApplicationsLib/ProjectData.cpp
@@ -74,6 +74,9 @@
 #ifdef OGS_BUILD_PROCESS_LIQUIDFLOW
 #include "ProcessLib/LiquidFlow/CreateLiquidFlowProcess.h"
 #endif
+#ifdef OGS_BUILD_PROCESS_STOKESFLOW
+#include "ProcessLib/StokesFlow/CreateStokesFlowProcess.h"
+#endif
 
 #ifdef OGS_BUILD_PROCESS_THERMORICHARDSMECHANICS
 #include "ProcessLib/ThermoRichardsMechanics/CreateThermoRichardsMechanicsProcess.h"
@@ -635,6 +638,27 @@ void ProjectData::parseProcesses(
         }
         else
 #endif
+#ifdef OGS_BUILD_PROCESS_STOKESFLOW
+            if (type == "StokesFlow")
+        {
+            switch (_mesh_vec[0]->getDimension())
+            {
+                case 2:
+                    process =
+                        ProcessLib::StokesFlow::createStokesFlowProcess<2>(
+                            name, *_mesh_vec[0], std::move(jacobian_assembler),
+                            _process_variables, _parameters, integration_order,
+                            process_config, _media);
+                    break;
+                default:
+                    OGS_FATAL(
+                        "StokesFlow process does not support given "
+                        "dimension {:d}",
+                        _mesh_vec[0]->getDimension());
+            }
+        }
+        else
+#endif
 #ifdef OGS_BUILD_PROCESS_TES
             if (type == "TES")
         {
diff --git a/ProcessLib/StokesFlow/CreateStokesFlowProcess.cpp b/ProcessLib/StokesFlow/CreateStokesFlowProcess.cpp
new file mode 100644
index 00000000000..34c43e6c181
--- /dev/null
+++ b/ProcessLib/StokesFlow/CreateStokesFlowProcess.cpp
@@ -0,0 +1,164 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "CreateStokesFlowProcess.h"
+#include "StokesFlowProcess.h"
+
+#include "MaterialLib/MPL/CreateMaterialSpatialDistributionMap.h"
+#include "ProcessLib/Output/CreateSecondaryVariables.h"
+#include "ProcessLib/Utils/ProcessUtils.h"
+
+namespace ProcessLib
+{
+namespace StokesFlow
+{
+namespace
+{
+void checkMPLProperties(
+    MeshLib::Mesh const& mesh,
+    MaterialPropertyLib::MaterialSpatialDistributionMap const& media_map)
+{
+    std::array const required_properties_liquid_phase = {
+        MaterialPropertyLib::PropertyType::viscosity};
+
+    for (auto const& element : mesh.getElements())
+    {
+        auto const element_id = element->getID();
+        auto const& medium = *media_map.getMedium(element_id);
+
+        // check if liquid phase definition and the corresponding properties
+        // exist
+        auto const& liquid_phase = medium.phase("AqueousLiquid");
+        checkRequiredProperties(liquid_phase, required_properties_liquid_phase);
+    }
+}
+}  // namespace
+
+template <int GlobalDim>
+std::unique_ptr<Process> createStokesFlowProcess(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media)
+{
+    //! \ogs_file_param{prj__processes__process__type}
+    config.checkConfigParameter("type", "StokesFlow");
+
+    DBUG("Create StokesFlowProcess.");
+
+    auto const coupling_scheme =
+        //! \ogs_file_param{prj__processes__process__StokesFlow__coupling_scheme}
+        config.getConfigParameter<std::string>("coupling_scheme",
+                                               "monolithic_scheme");
+    const bool use_monolithic_scheme = (coupling_scheme != "staggered");
+
+    // Process variable.
+    //! \ogs_file_param{prj__processes__process__StokesFlow__process_variables}
+    auto const pv_config = config.getConfigSubtree("process_variables");
+
+    std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>
+        process_variables;
+
+    // Collect all process variables in a vector before allocation
+    // liquid_velocity first, pressure then
+    auto const collected_process_variables = findProcessVariables(
+        variables, pv_config,
+        {//! \ogs_file_param_special{prj__processes__process__StokesFlow__process_variables__liquid_velocity}
+         "liquid_velocity",
+         //! \ogs_file_param_special{prj__processes__process__StokesFlow__process_variables__pressure}
+         "pressure"});
+
+    // Check number of components for each process variable
+    auto const variable_v = collected_process_variables[0];
+    if (variable_v.get().getNumberOfGlobalComponents() != GlobalDim)
+    {
+        OGS_FATAL(
+            "Number of components of the process variable '{:s}' is different "
+            "from the global dimension: got {:d}, expected {:d}",
+            variable_v.get().getName(),
+            variable_v.get().getNumberOfGlobalComponents(),
+            GlobalDim);
+    }
+
+    auto const variable_p = collected_process_variables[1];
+    if (variable_p.get().getNumberOfGlobalComponents() != 1)
+    {
+        OGS_FATAL(
+            "Pressure process variable '{:s}' is not a scalar variable but has "
+            "{:d} components.",
+            variable_p.get().getName(),
+            variable_p.get().getNumberOfGlobalComponents());
+    }
+
+    // Allocate the collected process variables into a two-dimensional vector,
+    // depending on what coupling scheme is adopted
+    if (use_monolithic_scheme)  // monolithic scheme.
+    {
+        process_variables.push_back(std::move(collected_process_variables));
+    }
+    else  // staggered scheme.
+    {
+        OGS_FATAL(
+            "The staggered coupling scheme for StokesFlowProcess is not "
+            "implemented.");
+    }
+
+    // Specific body force
+    Eigen::VectorXd specific_body_force = Eigen::VectorXd::Zero(GlobalDim);
+    auto const b =
+        //! \ogs_file_param{prj__processes__process__StokesFlow__specific_body_force}
+        config.getConfigParameter<std::vector<double>>("specific_body_force");
+    if (b.size() != GlobalDim)
+    {
+        OGS_FATAL(
+            "The size of the specific body force vector does not match the "
+            "global dimension. Vector size is {:d}, global "
+            "dimension is {:d}",
+            b.size(), GlobalDim);
+    }
+    std::copy_n(b.data(), b.size(), specific_body_force.data());
+
+    auto media_map =
+        MaterialPropertyLib::createMaterialSpatialDistributionMap(media, mesh);
+
+    DBUG("Check the media properties of StokesFlow process ...");
+    checkMPLProperties(mesh, *media_map);
+    DBUG("Media properties verified.");
+
+    StokesFlowProcessData process_data{std::move(media_map),
+                                       std::move(specific_body_force)};
+
+    SecondaryVariableCollection secondary_variables;
+
+    ProcessLib::createSecondaryVariables(config, secondary_variables);
+
+    return std::make_unique<StokesFlowProcess<GlobalDim>>(
+        std::move(name), mesh, std::move(jacobian_assembler), parameters,
+        integration_order, std::move(process_variables),
+        std::move(process_data), std::move(secondary_variables),
+        use_monolithic_scheme);
+}
+
+template std::unique_ptr<Process> createStokesFlowProcess<2>(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+}  // namespace StokesFlow
+}  // namespace ProcessLib
diff --git a/ProcessLib/StokesFlow/CreateStokesFlowProcess.h b/ProcessLib/StokesFlow/CreateStokesFlowProcess.h
new file mode 100644
index 00000000000..72fab5edc55
--- /dev/null
+++ b/ProcessLib/StokesFlow/CreateStokesFlowProcess.h
@@ -0,0 +1,45 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "ProcessLib/Process.h"
+
+namespace MaterialPropertyLib
+{
+class Medium;
+}
+
+namespace ProcessLib::StokesFlow
+{
+template <int GlobalDim>
+std::unique_ptr<Process> createStokesFlowProcess(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+extern template std::unique_ptr<Process> createStokesFlowProcess<2>(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+}  // namespace StokesFlow
-- 
GitLab