From 31128a4be4006b2fb3499f5ec2f439ac9c8a3993 Mon Sep 17 00:00:00 2001
From: Tomas Jakubec <jakubto1@fjfi.cvut.cz>
Date: Thu, 3 Oct 2019 11:02:31 +0200
Subject: [PATCH] The DBGVAR now can write almost every varible. Moreover it
 recognizes whether the varible is iterable and then writes the content of the
 container.

---
 Unstructured_mesh/MeshNativeType.h           |  14 +-
 Unstructured_mesh/Unstructured_mesh.pro      |   1 +
 Unstructured_mesh/Unstructured_mesh.pro.user |   2 +-
 Unstructured_mesh/VTKMeshReader.h            | 162 +++++++++++++++++++
 Unstructured_mesh/main.cpp                   | 126 ++++++++-------
 debug/consolelogger.h                        | 105 ++++++++++++
 debug/debug.h                                |   3 +-
 7 files changed, 355 insertions(+), 58 deletions(-)
 create mode 100644 debug/consolelogger.h

diff --git a/Unstructured_mesh/MeshNativeType.h b/Unstructured_mesh/MeshNativeType.h
index 12ea173..278a80f 100644
--- a/Unstructured_mesh/MeshNativeType.h
+++ b/Unstructured_mesh/MeshNativeType.h
@@ -9,11 +9,23 @@ struct MeshNativeType{
 template<>
 struct MeshNativeType<2>{
     enum ElementType{
-        LINE = 1,
+        LINE = 200,
         TRIANGLE,
         QUAD,
         POLYGON
     };
 };
 
+template<>
+struct MeshNativeType<3>{
+    enum ElementType{
+        TETRA = 300,
+        HEXAHEDRON,
+        WEDGE,
+        PYRAMID,
+        N_PYRAMID,
+        POLYHEDRON
+    };
+};
+
 #endif // MESHNATIVETYPE_H
diff --git a/Unstructured_mesh/Unstructured_mesh.pro b/Unstructured_mesh/Unstructured_mesh.pro
index bde7506..8f975f8 100644
--- a/Unstructured_mesh/Unstructured_mesh.pro
+++ b/Unstructured_mesh/Unstructured_mesh.pro
@@ -8,6 +8,7 @@ SOURCES += \
     ../debug/debug.cpp
 
 HEADERS += \
+    ../debug/consolelogger.h \
     CellBoundaryConnection.h \
     CellConnection.h \
     ComputationalySignificantElement.h \
diff --git a/Unstructured_mesh/Unstructured_mesh.pro.user b/Unstructured_mesh/Unstructured_mesh.pro.user
index d7e2a68..617ffdf 100644
--- a/Unstructured_mesh/Unstructured_mesh.pro.user
+++ b/Unstructured_mesh/Unstructured_mesh.pro.user
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 4.10.0, 2019-10-01T16:36:35. -->
+<!-- Written by QtCreator 4.10.0, 2019-10-02T13:13:57. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
diff --git a/Unstructured_mesh/VTKMeshReader.h b/Unstructured_mesh/VTKMeshReader.h
index cfdd4ce..09b3d5d 100644
--- a/Unstructured_mesh/VTKMeshReader.h
+++ b/Unstructured_mesh/VTKMeshReader.h
@@ -180,4 +180,166 @@ public:
 };
 
 
+template<typename IndexType, typename Real, unsigned int... Reserve>
+class VTKMeshReader<3, IndexType, Real, Reserve...> : public MeshReader<3, IndexType, Real>{
+    using reader = MeshReader<3, IndexType, Real>;
+    std::map<int, typename reader::type::ElementType> TypeConversionTable{
+        {10, reader::type::ElementType::TETRA},
+        {11, reader::type::ElementType::HEXAHEDRON},
+        {12, reader::type::ElementType::HEXAHEDRON},
+        {13, reader::type::ElementType::WEDGE},
+        {14, reader::type::ElementType::PYRAMID},
+    };
+
+    std::unordered_map<std::string, IndexType> edges;
+    std::unordered_map<std::string, IndexType> faces;
+
+    MeshDataContainer<typename reader::type::ElementType, 3> cellTypes;
+    // file indexing
+    //
+
+    //
+    //MeshDataContainer<IndexType>
+public:
+    VTKMeshReader() = default;
+    VTKMeshReader(const MeshElements<3, IndexType, Real, Reserve...>&){}
+
+    MeshDataContainer<typename reader::type::ElementType, 3> getCellTypes() {
+        return cellTypes;
+    }
+
+    void loadPoints(std::istream& ist, MeshElements<3, IndexType, Real, Reserve...>& mesh){
+        IndexType numPoints;
+        ist >> numPoints;
+        Real dummy = 0;
+        mesh.getVertices().resize(numPoints);
+        ist.ignore(20, '\n');
+        for (IndexType vertIndex = 0; vertIndex < numPoints; vertIndex++) {
+            mesh.getVertices().at(vertIndex).setIndex(vertIndex);
+            ist >> mesh.getVertices().at(vertIndex)[0];
+            ist >> mesh.getVertices().at(vertIndex)[1];
+            ist >> mesh.getVertices().at(vertIndex)[2];
+        }
+    }
+
+    void loadCells(std::istream& ist, MeshElements<3, IndexType, Real, Reserve...>& mesh){
+        IndexType numCells;
+        ist >> numCells;
+        mesh.getCells().resize(numCells);
+        // Skip the total number of numbers
+        ist.ignore(50, '\n');
+        for (IndexType cellIndex = 0; cellIndex < numCells; cellIndex++) {
+            mesh.getCells().at(cellIndex).setIndex(cellIndex);
+            IndexType numVert;
+            ist >> numVert;
+
+            std::vector<IndexType> vertices(numVert);
+            for(IndexType j = 0; j < numVert; j++){
+                ist >> vertices.at(j);
+            }
+
+            IndexType prevEdge = INVALID_INDEX(IndexType);
+            for(IndexType j = 0; j < numVert; j++){
+                IndexType iA = vertices.at(j), iB = vertices.at((j+1)%numVert);
+                std::string edgeKey = iA < iB ? std::to_string(iA) +";"+ std::to_string(iB) : std::to_string(iB) +";"+ std::to_string(iA);
+                typename std::unordered_map<std::string, IndexType>::iterator edgeIt = edges.find(edgeKey);
+
+                IndexType edgeIndex = IndexType();
+
+                if (edgeIt == edges.end()){
+
+                    edgeIndex = mesh.getEdges().size();
+                    mesh.getEdges().push_back({});
+                    mesh.getEdges().at(edgeIndex).setVertexAIndex(iA);
+                    mesh.getEdges().at(edgeIndex).setVertexBIndex(iB);
+                    mesh.getEdges().at(edgeIndex).setIndex(edgeIndex);
+
+                    mesh.getEdges().at(edgeIndex).setCellLeftIndex(cellIndex);
+                } else {
+                    edgeIndex = edgeIt->second;
+                    mesh.getEdges().at(edgeIt->second).setCellRightIndex(cellIndex);
+                }
+
+                if (prevEdge != INVALID_INDEX(IndexType)){
+                    mesh.getEdges().at(prevEdge).setNextBElem(edgeIndex, cellIndex);
+                }
+
+                if (j == 0){
+                    mesh.getCells().at(cellIndex).setBoundaryElementIndex(edgeIndex);
+                }
+                if (j == numVert - 1) {
+                    mesh.getEdges().at(edgeIndex).setNextBElem(mesh.getCells().at(cellIndex).getBoundaryElementIndex(), cellIndex);
+                }
+                prevEdge = edgeIndex;
+            }
+
+        }
+    }
+
+
+    void loadCellTypes(std::istream& ist, MeshElements<3, IndexType, Real, Reserve...>& mesh){
+        IndexType numCells;
+        ist >> numCells;
+        cellTypes.alocateData(mesh);
+        for (IndexType i = 0; i < numCells; i++) {
+            int vtkType = 0;
+            ist >> vtkType;
+            typename std::map<int, typename reader::type::ElementType>::iterator typeIt = TypeConversionTable.find(vtkType);
+            if (typeIt != TypeConversionTable.end()){
+                cellTypes.template getDataByPos<0>().at(i) = typeIt->second;
+            } else {
+                std::runtime_error("unsuported cell type");
+            }
+        }
+    }
+
+
+    void loadFromStream(std::istream& ist,MeshElements<3, IndexType, Real, Reserve...>& mesh){
+        ist.seekg(ist.beg);
+        // Ignore first row "# vtk DataFile Version 2.0"
+        ist.ignore(1024, '\n');
+        // Ignore name of the data set
+        ist.ignore(1024, '\n');
+        // ASCII or BINARY
+        std::string buf;
+        std::getline(ist, buf);
+        if (buf != "ASCII"){
+            throw std::runtime_error("ASCII expected but got " + buf);
+        }
+
+        ist >> buf;
+        if (buf != "DATASET"){
+            throw std::runtime_error("the keyword DATASET expected");
+        }
+
+        ist >> buf;
+        if (buf != "UNSTRUCTURED_GRID"){
+            throw std::runtime_error("only unstructured grid is supported but got " + buf);
+        }
+
+
+        ist >> buf;
+        if (buf == "POINTS") {
+            loadPoints(ist, mesh);
+        }
+
+        ist >> buf;
+        if (buf == "CELLS") {
+            loadCells(ist, mesh);
+        }
+
+        ist >> buf;
+        if (buf == "CELL_TYPES") {
+            loadCellTypes(ist, mesh);
+        }
+
+    }
+
+    MeshElements<3, IndexType, Real, Reserve...> loadFromStream(std::istream& ist){
+        MeshElements<3, IndexType, Real, Reserve...> resultMesh;
+        loadFromStream(ist, resultMesh);
+        return resultMesh;
+    }
+};
+
 #endif // VTKMESHREADER_H
diff --git a/Unstructured_mesh/main.cpp b/Unstructured_mesh/main.cpp
index 9f8eda1..8ba4a9f 100644
--- a/Unstructured_mesh/main.cpp
+++ b/Unstructured_mesh/main.cpp
@@ -5,6 +5,7 @@
 #include "VTKMeshReader.h"
 #include "VTKMeshWriter.h"
 #include <fstream>
+#include <list>
 using namespace std;
 
 
@@ -311,19 +312,19 @@ void testMesh2D() {
     DBGMSG("cell boundary iterator test");
 
     for(auto i : cell.getSubelements()){
-        DBGVAR(i)
+        DBGVAR(i);
     }
 
 
     for(auto i : mesh.getElement<2>(1).getSubelements()){
-        DBGVAR(i)
+        DBGVAR(i);
     }
 
     DBGMSG("cell vertices using iterator");
     for(size_t i = 0; i < mesh.getCells().size(); i++){
         for(auto j : mesh.getElement<2>(i).getSubelements()){
             auto e = mesh.getElement<1>(j);
-            DBGVAR(e.getElement().getVertexAIndex(), e.getElement().getVertexBIndex())
+            DBGVAR(e.getElement().getVertexAIndex(), e.getElement().getVertexBIndex());
         }
     }
 
@@ -332,9 +333,9 @@ void testMesh2D() {
     DBGMSG("vertices of cells in 2D");
     for (auto& cell : mesh.getCells()){
         std::set<size_t>& _set = vertices.at(cell);
-        DBGVAR(cell.getIndex())
+        DBGVAR(cell.getIndex());
         for (size_t index: _set){
-            DBGVAR(index)
+            DBGVAR(index);
         }
     }
 
@@ -344,11 +345,11 @@ void testMesh2D() {
 
     auto& faceCent = centers.getDataByDim<1>();
     for(auto& center : faceCent) {
-        DBGVAR(center)
+        DBGVAR(center);
     }
     DBGMSG("cellCenter");
     for(sit::Cell& cell : mesh.getCells()){
-        DBGVAR(centers.getDataByDim<2>().at(cell.getIndex()))
+        DBGVAR(centers.getDataByDim<2>().at(cell.getIndex()));
     }
 
 
@@ -358,11 +359,11 @@ void testMesh2D() {
 
 
     for(double edgeM :measures.getDataByDim<1>()) {
-        DBGVAR(edgeM)
+        DBGVAR(edgeM);
     }
 
     for(double cellM :measures.getDataByDim<2>()) {
-        DBGVAR(cellM)
+        DBGVAR(cellM);
     }
 
 
@@ -371,14 +372,14 @@ void testMesh2D() {
 
     auto normals = ComputeFaceNormals(mesh);
     for(auto& edge : mesh.getEdges()){
-        DBGVAR(edge.getIndex(),normals.at(edge))
+        DBGVAR(edge.getIndex(),normals.at(edge));
     }
 
     DBGMSG("2D cells distances");
 
     auto distances = ComputeCellsDistance(mesh);
     for(auto& edge : mesh.getEdges()){
-        DBGVAR(edge.getIndex(),distances.at(edge))
+        DBGVAR(edge.getIndex(),distances.at(edge));
     }
 
 }
@@ -391,21 +392,21 @@ void testMesh2DLoadAndWrite(){
     DBGMSG("load from vtk file test");
     VTKMeshReader<2, size_t, double> reader;
     ifstream ifst("Test_obdelnik.vtk");
-    DBGVAR(bool(ifst))
+    DBGVAR(bool(ifst));
     reader.loadFromStream(ifst, mesh);
 
-    DBGVAR(mesh.getVertices().size(), mesh.getVertices().at(4),mesh.getCells().size())
+    DBGVAR(mesh.getVertices().size(), mesh.getVertices().at(4),mesh.getCells().size());
 
 
     DBGMSG("mesh apply test");
     temp1::MeshRun<2, 2, 0, 2,false, true>::run(mesh,size_t(4), size_t(4), [](unsigned int S, unsigned int T, size_t ori, size_t i){
-        DBGVAR(S,T,ori,i)
+        DBGVAR(S,T,ori,i);
     });
 
     mesh.initializeCenters();
     auto normals = mesh.computeFaceNormals();
     auto measures = mesh.computeElementMeasures();
-    DBGVAR(normals.getDataByPos<0>().at(0), measures.getDataByDim<2>().at(100), measures.getDataByDim<1>().at(100), mesh.getCells().at(100).getCenter())
+    DBGVAR(normals.getDataByPos<0>().at(0), measures.getDataByDim<2>().at(100), measures.getDataByDim<1>().at(100), mesh.getCells().at(100).getCenter());
 
     VTKMeshWriter<2,size_t, double> writer;
     ofstream ofst("test_mesh_export.vtk");
@@ -422,11 +423,11 @@ void testMesh3D() {
     size_t tmp_face = mesh3.getCells().at(0).getBoundaryElementIndex();
 
     do {
-        DBGVAR(tmp_face)
+        DBGVAR(tmp_face);
         for (auto& sube : mesh3.getFaces().at(tmp_face).getSubelements()) {
-            DBGVAR(sube.index)
+            DBGVAR(sube.index);
             if (sube.index != INVALID_INDEX(size_t) ){
-                DBGVAR(sube.index, mesh3.getVertices().at(mesh3.getEdges().at(sube.index).getVertexAIndex()),mesh3.getVertices().at(mesh3.getEdges().at(sube.index).getVertexBIndex()))
+                DBGVAR(sube.index, mesh3.getVertices().at(mesh3.getEdges().at(sube.index).getVertexAIndex()),mesh3.getVertices().at(mesh3.getEdges().at(sube.index).getVertexBIndex()));
             }
         }
 
@@ -438,7 +439,7 @@ void testMesh3D() {
     DBGMSG("Iterator wrapper test");
     sit3::MeshElementWrap<2> elem(&mesh3, mesh3.getFaces().at(0));
     for(auto i : elem.getSubelements()){
-        DBGVAR(i.index)
+        DBGVAR(i.index);
     }
 
 
@@ -451,11 +452,11 @@ void testMesh3D() {
 
 
     //cont.getDataByDim<3>().resize(20);
-    DBGVAR(cont.getDataByPos<1>().size())
+    DBGVAR(cont.getDataByPos<1>().size());
 
-    DBGVAR(cont.getDataByPos<0>().size())
+    DBGVAR(cont.getDataByPos<0>().size());
 
-    DBGVAR(cont.getDataByDim<3>().size())
+    DBGVAR(cont.getDataByDim<3>().size());
 
 
     DBGMSG("faceCenters");
@@ -467,26 +468,26 @@ void testMesh3D() {
 
     for(auto& face : mesh3.getFaces()) {
         face.setCenter(centers.template getDataByDim<2>().at(face.getIndex()));
-        DBGVAR(face.getCenter())
+        DBGVAR(face.getCenter());
     }
     DBGMSG("cellCenter");
     for(auto& cell : mesh3.getCells()) {
         cell.setCenter(centers.template getDataByDim<3>().at(cell.getIndex()));
-        DBGVAR(cell.getCenter())
+        DBGVAR(cell.getCenter());
     }
 
     DBGMSG("measure computation");
 
     auto measures = ComputeMeasures(mesh3);
     for(double edgeM : measures.getDataByDim<1>()) {
-        DBGVAR(edgeM)
+        DBGVAR(edgeM);
     }
     for(double faceM : measures.getDataByDim<2>()) {
-        DBGVAR(faceM)
+        DBGVAR(faceM);
     }
 
     for(double cellM : measures.getDataByDim<3>()) {
-        DBGVAR(cellM)
+        DBGVAR(cellM);
     }
 
 
@@ -494,25 +495,25 @@ void testMesh3D() {
 
     auto normals = mesh3.computeFaceNormals();
     for(auto& face : mesh3.getFaces()){
-        DBGVAR(face.getIndex(),normals.at(face))
+        DBGVAR(face.getIndex(),normals.at(face));
     }
 
     DBGMSG("mesh apply test");
     temp1::MeshApply<3, 2, 3>::apply(mesh3, [](unsigned int S, unsigned int T, size_t ori, size_t i){
-        DBGVAR(S,T,ori,i)
+        DBGVAR(S,T,ori,i);
     });
     DBGMSG("mesh apply test");
     temp1::MeshApply<2, 3, 3>::apply(mesh3,[](unsigned int S, unsigned int T, size_t ori, size_t i){
-        DBGVAR(S,T,ori,i)
+        DBGVAR(S,T,ori,i);
     });
 
 
     DBGMSG("connection test");
     auto con = temp1::MeshConnections<3,0>::connections(mesh3);
     for (auto& cell : mesh3.getCells()){
-        DBGVAR(cell.getIndex())
+        DBGVAR(cell.getIndex());
         for(size_t i : con[cell]){
-            DBGVAR(i)
+            DBGVAR(i);
         }
     }
 
@@ -520,22 +521,22 @@ void testMesh3D() {
     DBGMSG("connection test oposite");
     auto con1 = temp1::MeshConnections<0,3>::connections(mesh3);
     for (auto& vert : mesh3.getVertices()){
-        DBGVAR(vert.getIndex())
+        DBGVAR(vert.getIndex());
         for(size_t i : con1[vert]){
-            DBGVAR(i)
+            DBGVAR(i);
         }
     }
 
     DBGMSG("face to vertex colouring");
     auto colours = temp1::ColourMesh<2,0>::colour(mesh3);
     for (auto& face : mesh3.getFaces()){
-        DBGVAR(face.getIndex(), colours.at(face))
+        DBGVAR(face.getIndex(), colours.at(face));
     }
 
     DBGMSG("vertex to face colouring");
     auto colours1 = temp1::ColourMesh<0,2>::colour(mesh3);
     for (auto& vert : mesh3.getVertices()){
-        DBGVAR(vert.getIndex(), colours1.at(vert))
+        DBGVAR(vert.getIndex(), colours1.at(vert));
     }
 }
 
@@ -551,26 +552,26 @@ void test3DMeshDeformedPrisms() {
 
     for(auto& face : mesh3.getFaces()) {
         face.setCenter(centers[face]);
-        DBGVAR(face.getCenter())
+        DBGVAR(face.getCenter());
     }
     DBGMSG("cellCenter");
     for(auto& cell : mesh3.getCells()) {
         cell.setCenter(centers[cell]);
-        DBGVAR(cell.getCenter())
+        DBGVAR(cell.getCenter());
     }
 
     DBGMSG("measure computation");
 
     auto measures = ComputeMeasures(mesh3);
     for(double edgeM : measures.getDataByDim<1>()) {
-        DBGVAR(edgeM)
+        DBGVAR(edgeM);
     }
     for(double faceM : measures.getDataByDim<2>()) {
-        DBGVAR(faceM)
+        DBGVAR(faceM);
     }
 
     for(double cellM : measures.getDataByDim<3>()) {
-        DBGVAR(cellM)
+        DBGVAR(cellM);
     }
 }
 
@@ -595,25 +596,25 @@ void testMeshDataContainer() {
     }
 
     for(auto& v : mesh3.getVertices()){
-        DBGVAR(container.at(v))
+        DBGVAR(container.at(v));
     }
 
     MeshDataContainer<std::tuple<int, double, char, int>, 3, 2, 0, 2> containerIni(mesh3,3, 42.15, 'a', 15);
 
     for (auto& val : containerIni.getDataByPos<0>()){
-        DBGVAR(val)
+        DBGVAR(val);
     }
 
     for (auto& val : containerIni.getDataByPos<1>()){
-        DBGVAR(val)
+        DBGVAR(val);
     }
 
     for (auto& val : containerIni.getDataByPos<2>()){
-        DBGVAR(val)
+        DBGVAR(val);
     }
 
     for (auto& val : containerIni.getDataByPos<3>()){
-        DBGVAR(val)
+        DBGVAR(val);
     }
 }
 
@@ -622,10 +623,10 @@ class ClassA
  {
    public:
       ClassA (std::integer_sequence<unsigned int,Is...>)
-      {DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...})) }
+      {DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...})); }
 
       static void fun (std::index_sequence<Is...>)
-      {DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...})) }
+      {DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...})); }
 
  };
 
@@ -638,7 +639,7 @@ class ClassB
    public:
       ClassB (const std::integer_sequence<unsigned int, Is...>, Tuple t)
       {std::tuple_element_t<0,Tuple> typ = 0;
-          DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...}), std::get<0>(t), typ) }
+          DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...}), std::get<0>(t), typ); }
 
  };
 
@@ -651,12 +652,12 @@ class ClassC<std::integer_sequence<unsigned int,Is...>, std::tuple<Types...>>
    public:
       ClassC (const std::integer_sequence<unsigned int, Is...>, std::tuple<Types...>)
       {std::tuple_element_t<0,std::tuple<Types...>> typ = 0;
-          DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...}), typ) }
+          DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...}), typ); }
 
       ClassC () {
           std::tuple_element_t<0,std::tuple<Types...>> typ = 42.15;
           std::tuple_element_t<1,std::tuple<Types...>> typ2 = 42.15;
-          DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...}), typ, typ2)
+          DBGVAR(sizeof... (Is), std::get<0>(std::array<size_t, sizeof...(Is)>{Is...}), typ, typ2);
       }
  };
 
@@ -679,17 +680,32 @@ void testTemplate() {
 }
 
 
-
+void testDebug() {
+    double r = 42.15;
+    int i = 15;
+    char c = 42;
+    bool b = false;
+    std::list<int> list = {1,2,3};
+    std::vector<std::list<int>> vec(5, list);
+    std::map<std::string, size_t> m{
+        {"prvni", 1},
+        {"druhy", 2},
+        {"treti", 3}
+    };
+    ConsoleLogger::writeVar(__LINE__, __FILE__, "r", r, "i", i, "c", c, "list", list, "vec", vec, "b", b, "map", m);
+    DBGVAR(r, i, c, list, vec, b, m);
+}
 
 
 int main()
 {
     //testMesh2D();
-    testMesh2DLoadAndWrite();
-    //testMesh3D();
+    //testMesh2DLoadAndWrite();
+    testMesh3D();
     //test3DMeshDeformedPrisms();
     //testMeshDataContainer();
     //testTemplate();
-    UnstructuredMesh<5, size_t, double, 6,5,4> m;
+    //UnstructuredMesh<5, size_t, double, 6,5,4> m;
     //m.ComputeElementMeasures();
+
 }
diff --git a/debug/consolelogger.h b/debug/consolelogger.h
new file mode 100644
index 0000000..32bd751
--- /dev/null
+++ b/debug/consolelogger.h
@@ -0,0 +1,105 @@
+#ifndef CONSOLELOGGER_H
+#define CONSOLELOGGER_H
+#include <iostream>
+#include <fstream>
+#include <string>
+
+/**
+ * @brief The ConsoleLogger class
+ */
+class ConsoleLogger {
+
+    static void _writeWar(...)
+    {
+        std::cerr << "variable is not exportable" << std::endl;
+    }
+
+
+    template<typename T>
+    static auto _writeWar(const T& b)
+      -> typename std::enable_if<std::is_class<
+            typename std::remove_reference<decltype(std::cerr << b)>::type>::value &&
+            !std::is_same<T, bool>::value
+         >::type
+    {
+        std::cerr << b;
+    }
+
+
+
+    static void _writeWar(const bool& b)
+    {
+        std::cerr << (b == true ? "true" : "false");
+    }
+
+    template<typename T1, typename T2>
+    static auto _writeWar(const std::pair<T1,T2>& b)
+    {
+        _writeWar(b.first);
+        std::cerr << " => ";
+        _writeWar(b.second);
+    }
+
+    template<typename T>
+    static auto _writeWar(const T &list)
+      -> typename std::enable_if<std::is_class<
+             decltype(std::declval<const T&>().begin())>::value &&
+             !std::is_same<T, std::string>::value
+         >::type
+    {
+        auto it = list.begin();
+        std::cerr << "[ ";
+        while (it != list.end()){
+            _writeWar(*it);
+            if (++it == list.end()){
+                std::cerr << " ]";
+            } else {
+                std::cerr << ", ";
+            }
+        }
+    }
+
+public:
+
+
+
+    template<typename VAR_NAME, typename VAR, typename ... REST>
+    static void writeVar(VAR_NAME name, VAR value, REST ... rest){
+
+        writeVar(name, value);
+        writeVar(rest...);
+    }
+
+
+    template<typename VAR_NAME, typename VAR>
+    static void writeVar(VAR_NAME name, VAR value){
+
+        std::cerr << "variable " << name << " has value: " << value;
+    }
+
+
+
+    template<typename VAR_NAME, typename VAR, typename ... REST>
+    static void writeVar(int line, const char* cppFile, VAR_NAME name, VAR value, REST ... rest){
+
+        writeVar(line, cppFile, name, value);
+        writeVar(line, cppFile,  rest...);
+    }
+
+    template<typename VAR_NAME, typename VAR>
+    static void writeVar(int line, const char* cppFile, VAR_NAME name, VAR value){
+
+#ifdef __linux__
+        std::cerr << "In file " << cppFile << " at line " << line << " variable \033[0;33m" << name << "\033[0m has value of \033[0;31m";
+        _writeWar(value);
+        std::cerr << "\033[0m\n";
+#else
+        std::cerr << "In file " << cppFile << " at line " << line << " variable " << name << " has value of ";
+        _writeWar(value);
+        std::cerr << "\n";
+#endif
+    }
+
+};
+
+#endif // CONSOLELOGGER_H
diff --git a/debug/debug.h b/debug/debug.h
index 422695c..0ebe551 100644
--- a/debug/debug.h
+++ b/debug/debug.h
@@ -75,6 +75,7 @@
 #ifndef UNDEBUG
 #include <iostream>
 #include "htmllogger.h"
+#include "consolelogger.h"
 #include <stdexcept>
 /*
 ** Macros intended for sending
@@ -109,7 +110,7 @@ __LINE__ << " variable " << #var \
 #define SINGLE_DBGVAR_SC(var) SINGLE_DBGVAR(var);
 
 
-#define DBGVAR(...) FOR_EACH(SINGLE_DBGVAR_SC, __VA_ARGS__)
+#define DBGVAR(...) ConsoleLogger::writeVar(__LINE__, __FILE__ FOR_EACH(STRVAR, __VA_ARGS__))
 #define DBGVARCOND(condition, ...) if(condition) {DBGVAR(__VA_ARGS__)}
 
 #ifdef __linux__
-- 
GitLab