diff --git a/MeshLib/MeshGenerators/QuadraticMeshGenerator.cpp b/MeshLib/MeshGenerators/QuadraticMeshGenerator.cpp
index 5d6b68ccbe68d7fd59997eac57bba4439d519c74..27851860882e061581fef71be6689b7259ad6a9b 100644
--- a/MeshLib/MeshGenerators/QuadraticMeshGenerator.cpp
+++ b/MeshLib/MeshGenerators/QuadraticMeshGenerator.cpp
@@ -9,140 +9,133 @@
 
 #include "QuadraticMeshGenerator.h"
 
-#include "BaseLib/makeVectorUnique.h"
-
-#include "MeshLib/Node.h"
 #include "MeshLib/Elements/Element.h"
+#include "MeshLib/Elements/Hex.h"
 #include "MeshLib/Elements/Line.h"
-#include "MeshLib/Elements/Tri.h"
 #include "MeshLib/Elements/Quad.h"
-#include "MeshLib/Elements/Hex.h"
+#include "MeshLib/Elements/Tri.h"
 #include "MeshLib/MeshEditing/DuplicateMeshComponents.h"
-#include "MeshLib/Properties.h"
-#include "MeshLib/PropertyVector.h"
-
-namespace MeshLib
-{
-namespace
-{
+#include "MeshLib/Node.h"
 
-struct Edge
+/// Given an (linear) element divide all its edges by inserting a point in the
+/// middle and return a new element.
+template <typename QuadraticElement>
+std::unique_ptr<QuadraticElement> convertLinearToQuadratic(
+    MeshLib::Element const& e)
 {
-    Edge(std::size_t id1, std::size_t id2)
-        : _id1(std::min(id1, id2)), _id2(std::max(id1, id2))
-    {}
-
-    bool operator==(Edge const& r) const
+    auto const n_all_nodes = QuadraticElement::n_all_nodes;
+    auto const n_base_nodes = QuadraticElement::n_base_nodes;
+    assert(n_base_nodes == e.getNumberOfBaseNodes());
+
+    // Copy base nodes of element to the quadratic element new nodes'.
+    std::array<MeshLib::Node*, n_all_nodes> nodes;
+    for (int i = 0; i < n_base_nodes; i++)
+        nodes[i] = const_cast<MeshLib::Node*>(e.getNode(i));
+
+    // For each edge create a middle node.
+    int const number_of_edges = e.getNumberOfEdges();
+    for (int i = 0; i < number_of_edges; i++)
     {
-        return (_id1 == r._id1 && _id2 == r._id2);
-    }
-
-    std::size_t _id1;
-    std::size_t _id2;
+        auto const& a = *e.getEdgeNode(i, 0);
+        auto const& b = *e.getEdgeNode(i, 1);
 
-    std::size_t _edge_id = 0;
-};
+        nodes[n_base_nodes + i] = new MeshLib::Node(
+            (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
+    }
 
-bool operator< (Edge const& l, Edge const& r)
-{
-    return (l._id1 != r._id1) ? (l._id1 < r._id1) : l._id2 < r._id2;
+    return std::make_unique<QuadraticElement>(nodes, e.getID());
 }
 
-template <typename T_ELEMENT>
-T_ELEMENT* createQuadraticElement(
-    MeshLib::Element const* e, std::vector<Edge> const& vec_edges,
-    std::vector<MeshLib::Node*> const& vec_new_nodes,
-    const std::size_t n_mesh_base_nodes)
+/// Return a new quadratic element corresponding to the linear element's type.
+std::unique_ptr<MeshLib::Element> createQuadraticElement(
+    MeshLib::Element const& e)
 {
-    auto const n_all_nodes = T_ELEMENT::n_all_nodes;
-    auto const n_base_nodes = T_ELEMENT::n_base_nodes;
-    auto** nodes = new MeshLib::Node*[n_all_nodes];
-    for (unsigned i = 0; i < e->getNumberOfBaseNodes(); i++)
-        nodes[i] =
-            const_cast<MeshLib::Node*>(vec_new_nodes[e->getNode(i)->getID()]);
-    for (unsigned i = 0; i < e->getNumberOfEdges(); i++)
+    if (e.getCellType() == MeshLib::CellType::LINE2)
     {
-        auto itr = std::find(
-            vec_edges.begin(), vec_edges.end(),
-            Edge(e->getEdgeNode(i, 0)->getID(), e->getEdgeNode(i, 1)->getID()));
-        assert(itr != vec_edges.end());
-        nodes[n_base_nodes + i] =
-            vec_new_nodes[n_mesh_base_nodes + itr->_edge_id];
+        return convertLinearToQuadratic<MeshLib::Line3>(e);
+    }
+    if (e.getCellType() == MeshLib::CellType::TRI3)
+    {
+        return convertLinearToQuadratic<MeshLib::Tri6>(e);
+    }
+    if (e.getCellType() == MeshLib::CellType::QUAD4)
+    {
+        return convertLinearToQuadratic<MeshLib::Quad8>(e);
+    }
+    if (e.getCellType() == MeshLib::CellType::HEX8)
+    {
+        return convertLinearToQuadratic<MeshLib::Hex20>(e);
     }
-    return new T_ELEMENT(nodes);
-}
 
-} // no named namespace
+    OGS_FATAL("Mesh element type %s is not supported",
+              MeshLib::CellType2String(e.getCellType()).c_str());
+}
 
-std::unique_ptr<Mesh> createQuadraticOrderMesh(Mesh const& org_mesh)
+struct nodeByCoordinatesComparator
 {
-    std::vector<MeshLib::Node*> vec_new_nodes = MeshLib::copyNodeVector(org_mesh.getNodes());
-
-    // collect edges
-    std::vector<Edge> vec_edges;
-    for (MeshLib::Element const* e : org_mesh.getElements())
-    {
-        for (unsigned i=0; i<e->getNumberOfEdges(); i++)
-        {
-            auto node0 = e->getEdgeNode(i, 0);
-            auto node1 = e->getEdgeNode(i, 1);
-            vec_edges.emplace_back(node0->getID(), node1->getID());
-        }
-    }
-    BaseLib::makeVectorUnique(vec_edges);
-    for (std::size_t i=0; i<vec_edges.size(); i++)
-         vec_edges[i]._edge_id = i;
-    INFO("Found %d edges in the mesh", vec_edges.size());
-
-    // create mid-point nodes
-    double coords[3];
-    for (Edge const& edge : vec_edges)
+    bool operator()(MeshLib::Node* a, MeshLib::Node* b) const
     {
-        auto const& node0 = *vec_new_nodes[edge._id1];
-        auto const& node1 = *vec_new_nodes[edge._id2];
-        for (unsigned i=0; i<3; i++)
-            coords[i] = (node0[i] + node1[i]) * 0.5;
-        vec_new_nodes.push_back(new MeshLib::Node(coords));
+        return *a < *b;
     }
+};
+
+namespace MeshLib
+{
+std::unique_ptr<Mesh> createQuadraticOrderMesh(Mesh const& linear_mesh)
+{
+    // Clone the linear mesh nodes.
+    auto quadratic_mesh_nodes = MeshLib::copyNodeVector(linear_mesh.getNodes());
 
-    // create new elements with the quadratic nodes
-    std::vector<MeshLib::Element*> vec_new_eles;
-    for (MeshLib::Element const* e : org_mesh.getElements())
+    // Temporary container for unique quadratic nodes with O(log(n)) search.
+    std::set<MeshLib::Node*, nodeByCoordinatesComparator> unique_nodes;
+
+    // Create new elements with the quadratic nodes
+    std::vector<MeshLib::Element*> quadratic_elements;
+    auto const& linear_mesh_elements = linear_mesh.getElements();
+    for (MeshLib::Element const* e : linear_mesh_elements)
     {
-        if (e->getCellType() == MeshLib::CellType::LINE2)
-        {
-            vec_new_eles.push_back(createQuadraticElement<MeshLib::Line3>(
-                e, vec_edges, vec_new_nodes, org_mesh.getNumberOfNodes()));
-        }
-        else if (e->getCellType() == MeshLib::CellType::TRI3)
-        {
-            vec_new_eles.push_back(createQuadraticElement<MeshLib::Tri6>(
-                e, vec_edges, vec_new_nodes, org_mesh.getNumberOfNodes()));
-        }
-        else if (e->getCellType() == MeshLib::CellType::QUAD4)
-        {
-            vec_new_eles.push_back(createQuadraticElement<MeshLib::Quad8>(
-                e, vec_edges, vec_new_nodes, org_mesh.getNumberOfNodes()));
-        }
-        else if (e->getCellType() == MeshLib::CellType::HEX8)
+        auto quadratic_element = createQuadraticElement(*e);
+
+        // Replace the base nodes with cloned linear nodes.
+        int const number_base_nodes = quadratic_element->getNumberOfBaseNodes();
+        for (int i = 0; i < number_base_nodes; ++i)
         {
-            vec_new_eles.push_back(createQuadraticElement<MeshLib::Hex20>(
-                e, vec_edges, vec_new_nodes, org_mesh.getNumberOfNodes()));
+            quadratic_element->setNode(
+                i, quadratic_mesh_nodes[quadratic_element->getNodeIndex(i)]);
         }
-        else
+
+        // Make the new (middle-edge) nodes unique.
+        int const number_all_nodes = quadratic_element->getNumberOfNodes();
+        for (int i = number_base_nodes; i < number_all_nodes; ++i)
         {
-            OGS_FATAL("Mesh element type %s is not supported", MeshLib::CellType2String(e->getCellType()).c_str());
+            Node* original_node =
+                const_cast<Node*>(quadratic_element->getNode(i));
+
+            auto it = unique_nodes.insert(original_node);
+            if (!it.second)  // same node was already inserted before, no
+                             // insertion
+            {
+                // Replace the element's node with the unique node.
+                quadratic_element->setNode(i, *it.first);
+                // And delete the original node
+                delete original_node;
+            }
         }
+
+        quadratic_elements.push_back(quadratic_element.release());
     }
 
-    std::unique_ptr<MeshLib::Mesh> new_mesh(
-        new MeshLib::Mesh(org_mesh.getName(), vec_new_nodes, vec_new_eles,
-                          org_mesh.getProperties().excludeCopyProperties(
-                              std::vector<MeshLib::MeshItemType>(
-                                  1, MeshLib::MeshItemType::Node)),
-                          org_mesh.getNumberOfNodes()));
-    return new_mesh;
+    // Add the unique quadratic nodes to the cloned linear nodes.
+    quadratic_mesh_nodes.reserve(linear_mesh.getNodes().size() +
+                                 unique_nodes.size());
+    std::copy(unique_nodes.begin(), unique_nodes.end(),
+              std::back_inserter(quadratic_mesh_nodes));
+
+    return std::make_unique<MeshLib::Mesh>(
+        linear_mesh.getName(), quadratic_mesh_nodes, quadratic_elements,
+        linear_mesh.getProperties().excludeCopyProperties(
+            std::vector<MeshLib::MeshItemType>(1, MeshLib::MeshItemType::Node)),
+        linear_mesh.getNumberOfNodes());
 }
 
-} // namespace MeshLib
-
+}  // namespace MeshLib
diff --git a/Tests/MeshLib/TestQuadraticMesh.cpp b/Tests/MeshLib/TestQuadraticMesh.cpp
index 2beafb3c85d88a77003a465cf3551574f2af74cd..0e79acb6440b5ecb6c4861215708e8d56418707e 100644
--- a/Tests/MeshLib/TestQuadraticMesh.cpp
+++ b/Tests/MeshLib/TestQuadraticMesh.cpp
@@ -82,29 +82,31 @@ TEST(MeshLib, QuadraticOrderMesh_Quad)
             ASSERT_FALSE(mesh->isBaseNode(e->getNodeIndex(i)));
     }
 
-    auto isIn = [](MeshLib::Node const* node, std::initializer_list<std::size_t> list)
-    {
-        return list.end() != std::find(list.begin(), list.end(), node->getID());
-    };
-
-    for (MeshLib::Node const* node : mesh->getNodes())
-    {
-        if (isIn(node, {4}))
-        {
-            ASSERT_EQ(4u, node->getElements().size());
-            ASSERT_EQ(21u, node->getConnectedNodes().size());
-        }
-        else if (isIn(node, {0, 2, 6, 8, 9, 10, 11, 13, 15, 18, 19, 20}))
-        {
-            ASSERT_EQ(1u, node->getElements().size());
-            ASSERT_EQ(8u, node->getConnectedNodes().size());
-        }
-        else
-        {
-            ASSERT_EQ(2u, node->getElements().size());
-            ASSERT_EQ(13u, node->getConnectedNodes().size());
-        }
-    }
+    auto const& mesh_nodes = mesh->getNodes();
+
+    // Count nodes shared by four elements and also connected to all 21 other
+    // nodes.
+    ASSERT_EQ(1, std::count_if(mesh_nodes.begin(), mesh_nodes.end(),
+                               [](Node* const n) {
+                                   return (n->getElements().size() == 4) &&
+                                          (n->getConnectedNodes().size() == 21);
+                               }));
+
+    // Count nodes belonging to one element and also connected to all 8 other
+    // nodes of that corner element.
+    ASSERT_EQ(12, std::count_if(mesh_nodes.begin(), mesh_nodes.end(),
+                                [](Node* const n) {
+                                    return (n->getElements().size() == 1) &&
+                                           (n->getConnectedNodes().size() == 8);
+                                }));
+
+    // Count nodes shared by two elements and also connected to the 13 other
+    // nodes of the two elements.
+    ASSERT_EQ(8, std::count_if(mesh_nodes.begin(), mesh_nodes.end(),
+                               [](Node* const n) {
+                                   return (n->getElements().size() == 2) &&
+                                          (n->getConnectedNodes().size() == 13);
+                               }));
 }
 
 TEST(MeshLib, QuadraticOrderMesh_LineQuad)
@@ -159,32 +161,37 @@ TEST(MeshLib, QuadraticOrderMesh_LineQuad)
             ASSERT_FALSE(mesh->isBaseNode(e->getNodeIndex(i)));
     }
 
-    auto isIn = [](MeshLib::Node const* node, std::initializer_list<std::size_t> list)
-    {
-        return list.end() != std::find(list.begin(), list.end(), node->getID());
-    };
-
-    for (MeshLib::Node const* node : mesh->getNodes())
-    {
-        if (isIn(node, {4}))
-        {
-            ASSERT_EQ(6u, node->getElements().size());
-            ASSERT_EQ(21u, node->getConnectedNodes().size());
-        }
-        else if (isIn(node, {0, 2, 6, 8, 9, 10, 11, 13, 15, 18, 19, 20}))
-        {
-            ASSERT_EQ(1u, node->getElements().size());
-            ASSERT_EQ(8u, node->getConnectedNodes().size());
-        }
-        else if (isIn(node, {3, 5, 14, 16}))
-        {
-            ASSERT_EQ(3u, node->getElements().size());
-            ASSERT_EQ(13u, node->getConnectedNodes().size());
-        }
-        else
-        {
-            ASSERT_EQ(2u, node->getElements().size());
-            ASSERT_EQ(13u, node->getConnectedNodes().size());
-        }
-    }
+    auto const& mesh_nodes = mesh->getNodes();
+
+    // Count nodes shared by six elements and also connected to all 21 other
+    // nodes.
+    ASSERT_EQ(1, std::count_if(mesh_nodes.begin(), mesh_nodes.end(),
+                               [](Node* const n) {
+                                   return (n->getElements().size() == 6) &&
+                                          (n->getConnectedNodes().size() == 21);
+                               }));
+
+    // Count nodes belonging to one element and also connected to all 8 other
+    // nodes of that corner element.
+    ASSERT_EQ(12, std::count_if(mesh_nodes.begin(), mesh_nodes.end(),
+                                [](Node* const n) {
+                                    return (n->getElements().size() == 1) &&
+                                           (n->getConnectedNodes().size() == 8);
+                                }));
+
+    // Count nodes shared by three elements (quads and the line) and also
+    // connected to the 13 other nodes of the two elements.
+    ASSERT_EQ(4, std::count_if(mesh_nodes.begin(), mesh_nodes.end(),
+                               [](Node* const n) {
+                                   return (n->getElements().size() == 3) &&
+                                          (n->getConnectedNodes().size() == 13);
+                               }));
+
+    // Count nodes shared by two elements (quads) and also connected to the 13
+    // other nodes of the two elements.
+    ASSERT_EQ(4, std::count_if(mesh_nodes.begin(), mesh_nodes.end(),
+                               [](Node* const n) {
+                                   return (n->getElements().size() == 2) &&
+                                          (n->getConnectedNodes().size() == 13);
+                               }));
 }