From fd0e96de2964d92b893ecdcaafc5a0c3d6633ca2 Mon Sep 17 00:00:00 2001
From: rinkk <karsten.rink@ufz.de>
Date: Thu, 1 Mar 2018 12:24:48 +0100
Subject: [PATCH] added data structures and read method for fem-conditions in
 data explorer

---
 .../DataHolderLib/BoundaryCondition.h         |  29 +++++
 Applications/DataHolderLib/Condition.cpp      |  73 ++++++++++++
 Applications/DataHolderLib/Condition.h        |  83 ++++++++++++++
 Applications/DataHolderLib/InitialCondition.h |  39 +++++++
 Applications/DataHolderLib/Project.h          |  16 +++
 Applications/DataHolderLib/SourceTerm.h       |  29 +++++
 .../FileIO/XmlIO/OpenGeoSysProject.xsd        | 107 ++++++++++++------
 Tests/FileIO_Qt/TestQtPrjInterface.cpp        |  77 +++++++++++++
 scripts/cmake/CompilerSetup.cmake             |   3 +-
 9 files changed, 418 insertions(+), 38 deletions(-)
 create mode 100644 Applications/DataHolderLib/BoundaryCondition.h
 create mode 100644 Applications/DataHolderLib/Condition.cpp
 create mode 100644 Applications/DataHolderLib/Condition.h
 create mode 100644 Applications/DataHolderLib/InitialCondition.h
 create mode 100644 Applications/DataHolderLib/SourceTerm.h
 create mode 100644 Tests/FileIO_Qt/TestQtPrjInterface.cpp

diff --git a/Applications/DataHolderLib/BoundaryCondition.h b/Applications/DataHolderLib/BoundaryCondition.h
new file mode 100644
index 00000000000..90a62a8b77a
--- /dev/null
+++ b/Applications/DataHolderLib/BoundaryCondition.h
@@ -0,0 +1,29 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2018, 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 "Applications/DataHolderLib/Condition.h"
+
+namespace DataHolderLib
+{
+
+class BoundaryCondition : public DataHolderLib::Condition
+{
+public:
+    BoundaryCondition(std::string const process_var, std::string const param_name, ConditionType type)
+    : Condition(process_var, param_name, type)
+    {}
+
+private:
+
+};
+
+
+} // namespace
diff --git a/Applications/DataHolderLib/Condition.cpp b/Applications/DataHolderLib/Condition.cpp
new file mode 100644
index 00000000000..564a0e05b0b
--- /dev/null
+++ b/Applications/DataHolderLib/Condition.cpp
@@ -0,0 +1,73 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2018, 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 "Condition.h"
+
+namespace DataHolderLib
+{
+
+Condition::Condition(std::string const process_var, std::string const param_name, ConditionType type)
+: _type(type), _process_var(process_var), _param_name(param_name)
+{};
+
+Condition::Condition(Condition const& c)
+: _base_type(c.getBaseObjType()), _type(c.getType()),
+  _process_var(c.getProcessVarName()), _param_name(c.getParamName()),
+  _base_obj_name(c.getBaseObjName()), _obj_name(c.getObjName())
+{}
+
+void Condition::setMesh(std::string const mesh_name)
+{
+    _base_type = BaseObjType::MESH;
+    _base_obj_name = mesh_name;
+    _obj_name = "";
+}
+
+void Condition::setGeoObject(std::string geo_name, std::string obj_name)
+{
+    _base_type = BaseObjType::GEOMETRY;
+    _base_obj_name = geo_name;
+    _obj_name = obj_name;
+}
+
+ConditionType Condition::convertStringToType(std::string const& str)
+{
+    if ( str == "Dirichlet")
+        return ConditionType::DIRICHLET;
+    else if (str == "NonlinearDirichlet")
+        return ConditionType::NONLINEARDIRICHLET;
+    else if (str == "Neumann")
+        return ConditionType::NEUMANN;
+    else if (str == "NonuniformNeumann")
+        return ConditionType::NONLINEARNEUMANN;
+    else if (str == "Robin")
+        return ConditionType::ROBIN;
+
+    return ConditionType::NONE;
+}
+
+std::string Condition::convertTypeToString(ConditionType type)
+{
+    if (type == ConditionType::DIRICHLET)
+        return "Dirichlet";
+    else if (type == ConditionType::NONLINEARDIRICHLET)
+        return "NonlinearDirichlet";
+    else if (type == ConditionType::NEUMANN)
+        return "Neumann";
+    else if (type == ConditionType::NONLINEARDIRICHLET)
+        return "NonlinearNeumann";
+    else if (type == ConditionType::ROBIN)
+        return "Robin";
+
+    return "";
+}
+
+
+} // namespace
diff --git a/Applications/DataHolderLib/Condition.h b/Applications/DataHolderLib/Condition.h
new file mode 100644
index 00000000000..b14a21b72d5
--- /dev/null
+++ b/Applications/DataHolderLib/Condition.h
@@ -0,0 +1,83 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2018, 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 <string>
+
+namespace DataHolderLib
+{
+
+enum class BaseObjType
+{
+    MESH = 0,
+    GEOMETRY = 1
+};
+
+enum class ConditionType
+{
+    NONE = 0,
+    DIRICHLET,
+    NONLINEARDIRICHLET,
+    NEUMANN,
+    NONLINEARNEUMANN,
+    ROBIN
+};
+
+enum class ParameterType
+{
+    NONE,
+    CONSTANT,
+    FUNCTION
+};
+
+class Condition
+{
+public:
+    Condition(std::string const process_var, std::string const param_name, ConditionType type);
+
+    Condition(Condition const& c);
+
+    ~Condition() {};
+
+    /// Returns the name of the associated process variable
+    std::string const getProcessVarName() const { return _process_var; }
+
+    std::string const getParamName() const { return _param_name; }
+
+    /// Is the condition set a geometry or on a mesh
+    BaseObjType getBaseObjType() const { return _base_type; }
+
+    ///Returns the name of the base object (i.e. geometry or mesh)
+    std::string getBaseObjName() const { return _base_obj_name; }
+
+    ///Returns the name of the geometric object
+    std::string const getObjName() const { return _obj_name; }
+
+    ConditionType getType() const { return _type; }
+
+    void setMesh(std::string const mesh_name);
+
+    virtual void setGeoObject(std::string geo_name, std::string obj_name);
+
+    static std::string convertTypeToString(ConditionType type);
+
+    static ConditionType convertStringToType(std::string const& type_str);
+
+private:
+    BaseObjType _base_type;
+    ConditionType _type;
+    std::string _process_var;
+    std::string _param_name;
+    std::string _base_obj_name;
+    std::string _obj_name;
+};
+
+} // namespace
diff --git a/Applications/DataHolderLib/InitialCondition.h b/Applications/DataHolderLib/InitialCondition.h
new file mode 100644
index 00000000000..e5d4147eafd
--- /dev/null
+++ b/Applications/DataHolderLib/InitialCondition.h
@@ -0,0 +1,39 @@
+/**
+ * \file
+ * \author Karsten Rink
+ * \date   2010-02-04
+ * \brief  Definition of the Color class.
+ *
+ * \copyright
+ * Copyright (c) 2012-2018, 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 <array>
+#include <map>
+#include <string>
+
+namespace DataHolderLib
+{
+using Color = std::array<unsigned char, 4>;
+
+Color createColor(unsigned char r, unsigned char g, unsigned char b);
+
+Color createColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+
+/// Returns a random RGB colour.
+Color getRandomColor();
+
+/// Uses a color-lookup-table (in form of a map) to return a colour for a specified name. If the name is not
+/// in the colortable a new entry is created with the new name and a random colour.
+Color const getColor(const std::string &id, std::map<std::string, DataHolderLib::Color> &colors);
+
+/// Convenience function to use the getColor method with numbers as identifiers.
+Color const getColor(double id, std::map<std::string, DataHolderLib::Color> &colors);
+} // namespace
diff --git a/Applications/DataHolderLib/Project.h b/Applications/DataHolderLib/Project.h
index 8ee2edc1056..d9d9b850120 100644
--- a/Applications/DataHolderLib/Project.h
+++ b/Applications/DataHolderLib/Project.h
@@ -15,6 +15,10 @@
 
 #include "MeshLib/Mesh.h"
 
+#include "Applications/DataHolderLib/BoundaryCondition.h"
+
+#include "Applications/DataHolderLib/SourceTerm.h"
+
 //namespace MeshLib {
 //    class Mesh;
 //}
@@ -59,6 +63,14 @@ public:
     /// false otherwise.
     bool removeMesh(const std::string &name);
 
+    void addBoundaryCondition(BoundaryCondition bc) { _boundary_conditions.push_back(bc); }
+
+    std::vector<BoundaryCondition> const getBoundaryConditions() const { return _boundary_conditions; }
+
+    void addSourceTerm(SourceTerm bc) { _source_terms.push_back(bc); }
+
+    std::vector<SourceTerm> const getSourceTerms() const { return _source_terms; }
+
 private:
     /// Checks if a mesh with the same name exists and provides a unique name in
     /// case of already existing mesh. Returns true if the mesh name is unique.
@@ -77,6 +89,10 @@ private:
 
     GeoLib::GEOObjects _geoObjects;
     std::vector<std::unique_ptr<MeshLib::Mesh>> _mesh_vec;
+
+    std::vector<BoundaryCondition> _boundary_conditions;
+
+    std::vector<SourceTerm> _source_terms;
 };
 
 } // namespace
diff --git a/Applications/DataHolderLib/SourceTerm.h b/Applications/DataHolderLib/SourceTerm.h
new file mode 100644
index 00000000000..13a74df460b
--- /dev/null
+++ b/Applications/DataHolderLib/SourceTerm.h
@@ -0,0 +1,29 @@
+/**
+* \copyright
+* Copyright (c) 2012-2018, 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 "Applications/DataHolderLib/Condition.h"
+
+namespace DataHolderLib
+{
+
+    class SourceTerm : public DataHolderLib::Condition
+    {
+    public:
+        SourceTerm(std::string const process_var, std::string const param_name, ConditionType type)
+        : Condition(process_var, param_name, type)
+        {}
+
+    private:
+
+    };
+
+
+} // namespace
diff --git a/Applications/FileIO/XmlIO/OpenGeoSysProject.xsd b/Applications/FileIO/XmlIO/OpenGeoSysProject.xsd
index f721a815f9d..c39b190b12c 100644
--- a/Applications/FileIO/XmlIO/OpenGeoSysProject.xsd
+++ b/Applications/FileIO/XmlIO/OpenGeoSysProject.xsd
@@ -2,56 +2,89 @@
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
   <!-- OpenGeoSysProject schema; initial implementation: Karsten Rink, 2010-08-20 -->
+  <xs:element name="name" type="xs:string" />
 
-  <!-- object containing just a source file definition -->
-  <xs:complexType name="projectElement">
+  <!-- definition of processes -->
+  <xs:complexType name="processType">
     <xs:sequence>
-    <xs:element name="file" type="xs:string" minOccurs="1" maxOccurs="1" />
+      <xs:element ref="name" minOccurs="1" maxOccurs="1" />
+      <xs:element name="type" type="xs:string" minOccurs="1" maxOccurs="1" />
+      <xs:element name="integration_order" minOccurs="1" maxOccurs="1" />
+      <xs:element name="process_variables" minOccurs="1" maxOccurs="1" />
+      <xs:element name="secondary_variables" minOccurs="0" maxOccurs="1" />
     </xs:sequence>
   </xs:complexType>
 
-  <!-- object containing a required reference to a geometry file -->
-  <xs:complexType name="geoElement">
-    <xs:complexContent>
-      <xs:extension base="projectElement">
-        <xs:sequence>
-          <xs:element name="geoReference" type="xs:string"/>
-        </xs:sequence>
-      </xs:extension>
-    </xs:complexContent>
+  <xs:complexType name="parameterType">
+    <xs:sequence>
+      <xs:element ref="name"  minOccurs="1" maxOccurs="1" />
+      <xs:element name="type" type="xs:string" minOccurs="1" maxOccurs="1" />
+      <xs:element name="value" minOccurs="0" maxOccurs="1" />
+      <xs:element name="field_name" type="xs:string" minOccurs="0" maxOccurs="1" />
+    </xs:sequence>
   </xs:complexType>
 
-  <!-- msh-object with optional geometry- and texture-reference -->
-  <xs:complexType name="mshElement">
-    <xs:complexContent>
-      <xs:extension base="projectElement">
-        <xs:sequence>
-          <xs:element name="geoReference" type="xs:string" minOccurs="0" />
-          <xs:element name="texture" type="xs:string" minOccurs="0" />
-        </xs:sequence>
-      </xs:extension>
-    </xs:complexContent>
+  <xs:complexType name="conditionType">
+    <xs:sequence>
+      <xs:element name="geometrical_set" type="xs:string" minOccurs="1" maxOccurs="1" />
+      <xs:element name="geometry" type="xs:string" minOccurs="1" maxOccurs="1" />
+      <xs:element name="type" type="xs:string" minOccurs="1" maxOccurs="1" />
+      <xs:element name="field_name" type="xs:string" minOccurs="0" maxOccurs="1" />
+      <xs:element name="mesh" type="xs:string" minOccurs="0" maxOccurs="1" />
+      <xs:element name="parameter" type="xs:string" minOccurs="0" maxOccurs="1" />
+    </xs:sequence>
   </xs:complexType>
 
+  <xs:complexType name="conditionListType">
+    <xs:sequence>
+      <xs:element name="boundary_condition" type="conditionType" minOccurs="0" maxOccurs="unbounded" />
+    </xs:sequence>
+  </xs:complexType>
 
+  <xs:complexType name="pvariableType">
+    <xs:sequence>
+      <xs:element ref="name"/>
+	  <xs:element name="components" type="xs:nonNegativeInteger" minOccurs="1" maxOccurs="1" />
+	  <xs:element name="order" type="xs:nonNegativeInteger" minOccurs="1" maxOccurs="1" />
+      <xs:element name="initial_condition" type="xs:string" minOccurs="0" maxOccurs="1" />
+      <xs:element name="boundary_conditions" type="conditionListType" minOccurs="0" maxOccurs="1" />
+	  <xs:element name="source_terms" type="conditionListType" minOccurs="0" maxOccurs="1" />
+    </xs:sequence>
+  </xs:complexType>
+  
   <!-- definition of file content -->
   <xs:element name="OpenGeoSysProject">
     <xs:complexType>
-      <xs:sequence>
-        <xs:element name="geo" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-        <xs:element name="msh" type="mshElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="cnd" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="mfp" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="mmp" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="msp" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="np"  type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="out" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="pcs" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="sim" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="tim" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="fct" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-    <xs:element name="stn" type="projectElement" minOccurs="0" maxOccurs="unbounded" />
-      </xs:sequence>
+      <xs:all>
+        <xs:element name="mesh" minOccurs="0">
+          <xs:complexType>
+            <xs:simpleContent>
+              <xs:extension base="xs:string">
+                <xs:attribute name="axially_symmetric" type="xs:boolean"/>
+              </xs:extension>
+            </xs:simpleContent>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="geometry" type="xs:string" minOccurs="0"/>
+        <xs:element name="processes" minOccurs="0"/> <!--ignore-->
+        <xs:element name="time_loop" minOccurs="0"/> <!--ignore-->
+        <xs:element name="parameters" minOccurs="0">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="parameter" type="parameterType" minOccurs="1" maxOccurs="unbounded" />
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="process_variables" minOccurs="0">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="process_variable" type="pvariableType" minOccurs="1" maxOccurs="unbounded" />
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="nonlinear_solvers" minOccurs="0"/> <!--ignore-->
+        <xs:element name="linear_solvers" minOccurs="0"/> <!--ignore-->
+      </xs:all>
     </xs:complexType>
   </xs:element>
 
diff --git a/Tests/FileIO_Qt/TestQtPrjInterface.cpp b/Tests/FileIO_Qt/TestQtPrjInterface.cpp
new file mode 100644
index 00000000000..66c928ecde1
--- /dev/null
+++ b/Tests/FileIO_Qt/TestQtPrjInterface.cpp
@@ -0,0 +1,77 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2018, 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 <cstdio>
+
+#include "gtest/gtest.h"
+
+#include "BaseLib/BuildInfo.h"
+#include "Applications/FileIO/XmlIO/Qt/XmlPrjInterface.h"
+#include "Applications/DataHolderLib/Project.h"
+#include "Applications/DataHolderLib/BoundaryCondition.h"
+#include "Applications/DataHolderLib/SourceTerm.h"
+#include "GeoLib/GEOObjects.h"
+
+
+TEST(TestQtPrjInterface, QtXmlPrjReader)
+{
+    typedef struct 
+    {
+        std::string const file_name;
+        std::size_t n_geo;
+        std::size_t n_mesh;
+        std::size_t n_bc;
+        std::size_t n_st;
+    } TestParams;
+
+    std::vector<TestParams> test_files;
+
+    std::string name = BaseLib::BuildInfo::data_path + "/Elliptic/nonuniform_bc_Groundwaterflow/neumann_nonuniform.prj";
+    test_files.push_back({ name, 1, 1, 2, 0 });
+    name = BaseLib::BuildInfo::data_path + "/Elliptic/nonuniform_bc_Groundwaterflow/neumann_nonuniform.prj";
+    test_files.push_back({ name, 1, 1, 2, 0 });
+
+    for (std::size_t i=0; i<test_files.size(); ++i)
+    {
+        DataHolderLib::Project project;
+        FileIO::XmlPrjInterface xml(project);
+        int result = xml.readFile(QString::fromStdString(test_files[i].file_name));
+        EXPECT_EQ(1, result);
+
+        std::vector<std::string> geo_names;
+        project.getGEOObjects().getGeometryNames(geo_names);
+        EXPECT_EQ(test_files[i].n_geo, geo_names.size());
+        EXPECT_EQ(test_files[i].n_mesh, project.getMeshObjects().size());
+
+        std::vector<DataHolderLib::BoundaryCondition> const bcs = project.getBoundaryConditions();
+        EXPECT_EQ(test_files[i].n_bc, bcs.size());
+        for (DataHolderLib::BoundaryCondition bc : bcs)
+        {
+            EXPECT_FALSE(bc.getProcessVarName().empty());
+            EXPECT_FALSE(bc.getParamName().empty());
+            EXPECT_FALSE(DataHolderLib::ConditionType::NONE == bc.getType());
+            EXPECT_FALSE(bc.getBaseObjName().empty());
+            if (bc.getBaseObjType() == DataHolderLib::BaseObjType::GEOMETRY)
+                EXPECT_FALSE(bc.getObjName().empty());
+        }
+
+        std::vector<DataHolderLib::SourceTerm> const sts = project.getSourceTerms();
+        EXPECT_EQ(test_files[i].n_st, sts.size());
+        for (DataHolderLib::SourceTerm st : sts)
+        {
+            EXPECT_FALSE(st.getProcessVarName().empty());
+            EXPECT_FALSE(st.getParamName().empty());
+            EXPECT_FALSE(DataHolderLib::ConditionType::NONE == st.getType());
+            EXPECT_FALSE(st.getBaseObjName().empty());
+            if (st.getBaseObjType() == DataHolderLib::BaseObjType::GEOMETRY)
+                EXPECT_FALSE(st.getObjName().empty());
+        }
+    }
+}
diff --git a/scripts/cmake/CompilerSetup.cmake b/scripts/cmake/CompilerSetup.cmake
index bbcd1272cab..083922fb0e8 100644
--- a/scripts/cmake/CompilerSetup.cmake
+++ b/scripts/cmake/CompilerSetup.cmake
@@ -135,7 +135,8 @@ if(WIN32)
             /wd4267 /wd4996 /bigobj")
         set(CMAKE_CXX_FLAGS_RELWITHDEBINFO  "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} \
             /ZI /Od /Ob0")
-
+        set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}  /ignore:4099")
+        
         DisableCompilerFlag(DEBUG /RTC1)
     # cygwin
     else()
-- 
GitLab