diff --git a/DESCRIPTION b/DESCRIPTION
index 9cc1085ddba8483cb7b8ad6fde2b48d6b9e148f1..7c6f9ed0ba65cd4d1964b7384849763c59011bed 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -23,5 +23,8 @@ Imports:
     tibble,
     R6,
     stringr,
-    readr
+    readr,
+    assertthat,
+    crayon,
+    snakecase
 RoxygenNote: 7.1.1
diff --git a/NAMESPACE b/NAMESPACE
index ad776bcc042535c0ece05efa7ec5ad15a0160e50..b2796f95a168485bd05d6cc3aee8a605c0e16335 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,7 +1,8 @@
 # Generated by roxygen2: do not edit by hand
 
-export(export_xml_to_file)
-export(gml_data_to_xml)
+export(input_add_vtu_appended_data)
+export(input_add_vtu_obj)
+export(input_add_vtu_unstructured_grid)
 export(points_to_xml)
 export(polylines_to_xml)
 export(surfaces_to_xml)
diff --git a/R/accepted_input.R b/R/accepted_input.R
new file mode 100644
index 0000000000000000000000000000000000000000..3d2d951c92047422be1fa6caacbb72d853752406
--- /dev/null
+++ b/R/accepted_input.R
@@ -0,0 +1,4 @@
+#This is a helper script providing an overview of some accepted input parameters.
+
+#============================== .vtu ================================
+vtu_appended_data_valid_encoding_types <- list("binary", "base64")
\ No newline at end of file
diff --git a/R/analyse_xml.R b/R/analyse_xml.R
new file mode 100644
index 0000000000000000000000000000000000000000..0327e8b35d57dbbf349cdab1f6c1ddf91523d517
--- /dev/null
+++ b/R/analyse_xml.R
@@ -0,0 +1,294 @@
+#This is a helper function which can be used to combat missing documentation.
+
+#Benchmark HydroMechanics:
+#analyse_xml("D:\\Programme\\OpenGeoSys\\ogs-master-Tests-Data-HydroMechanics/", "\\.vtu$", "VTKFile")
+
+#Personal playground:
+#analyse_xml("./inst/extdata/flow_free_expansion/playground/", "\\.vtu$", "VTKFile")
+
+#' analyse_xml
+#' @description This is a helper function which can be used to combat missing documentation. It looks
+#'  for files in a path which match the given pattern and then attempts to parse them as XML.
+#'  For each occurence of the specified element, it documents its attributes and direct children and prints a little
+#'  summary of its findings at the end.
+#' @param path A path
+#' @param pattern A regex pattern
+#' @param element_name The name of the XML element to look for
+analyse_xml <- function(path, pattern, element_name) {
+
+    xml_files <- list.files(path = path, pattern = pattern, recursive = TRUE)
+
+    #Think about input...
+
+    files_found <- length(xml_files)
+
+    valid_files_count <- 0
+    valid_files_names <- character()
+
+    invalid_files_count <- 0
+    invalid_files_names <- character()
+
+    total_matches <- 0
+
+    attribute_name_counts <- list()
+    child_exists_counts <- list()
+    child_total_counts <- list()
+
+
+
+    if(length(xml_files) == 0) {
+        stop(paste("No files found for defined pattern ", pattern), call. = FALSE)
+    }
+
+    for(i in seq_len(length(xml_files))){
+        #If there's invalid XML somewhere comment out the following for debugging:
+
+        skip_to_next <- FALSE
+
+        out<- tryCatch(
+            {
+                xml_doc <- xml2::read_xml(paste(path, xml_files[[i]], sep = ""), encoding="ISO-8859-1")
+            },
+
+            error = function(cond){
+                invalid_files_count <<- invalid_files_count + 1
+                invalid_files_names <<- c(invalid_files_names, basename(xml_files[[i]]))
+                skip_to_next <<- TRUE
+            }
+        )
+
+        if(skip_to_next){
+            next
+        }
+
+        valid_files_count <- valid_files_count + 1
+        valid_files_names <- c(valid_files_names, basename(xml_files[[i]]))
+
+        doc_matches <- xml2::xml_find_all(xml_doc, paste("//", element_name, sep = ""))
+        total_matches <- total_matches + length(doc_matches)
+
+        #Get attribute names and counts
+        for (j in seq_len(length(doc_matches))){
+            attr_names <- names(xml2::xml_attrs(doc_matches[[j]]))
+
+            for(k in seq_len(length(attr_names))) {
+                if(!attr_names[[k]] %in% names(attribute_name_counts)) {
+                    attribute_name_counts[[attr_names[[k]]]] <- 1
+                }else{
+                    attribute_name_counts[[attr_names[[k]]]] <- attribute_name_counts[[attr_names[[k]]]] + 1
+                }
+            }
+        }
+
+        #Get child names and counts
+        for (j in seq_len(length(doc_matches))){
+            children <- xml2::xml_children(doc_matches[[j]])
+
+            first_found <- list()
+
+            for(k in seq_len(length(children))) {
+
+                child_name <- xml2::xml_name(children[[k]])
+
+                if(!child_name %in% first_found){
+
+                    first_found <- c(first_found, child_name)
+
+
+                    if(!child_name %in% names(child_exists_counts)) {
+                        child_exists_counts[[child_name]] <- 1
+                    }else{
+                        child_exists_counts[[child_name]] <- child_exists_counts[[child_name]] + 1
+                    }
+                }
+
+                if(!child_name %in% names(child_total_counts)) {
+                    child_total_counts[[child_name]] <- 1
+                }else{
+                    child_total_counts[[child_name]] <- child_total_counts[[child_name]] + 1
+                }
+            }
+        }
+    }
+
+    if(invalid_files_count > 0) {
+        cat("I skipped ", invalid_files_count, " malformed XML files matching your search pattern:\n", sep = "")
+        for(i in seq_len(length(invalid_files_names))){
+            cat(invalid_files_names[[i]], "\n")
+        }
+    }
+
+    cat("\nI parsed ", valid_files_count, " valid XML files matching your search pattern:\n", sep = "")
+
+    for(i in seq_len(length(valid_files_names))){
+        cat(valid_files_names[[i]], "\n")
+    }
+
+    cat("\nIn total, I found ", total_matches, " elements named ", element_name, ".\n", sep = "")
+
+    #List attributes
+
+    if(length(attribute_name_counts) > 0) {
+        cat("\nThese are the attributes I found:\n")
+
+        attr_name_count_vector <- unlist(attribute_name_counts, use.names=FALSE)
+        attr_name_occ_vector <- unlist(lapply(attribute_name_counts, function(x){round((x / total_matches), 2)}))
+
+        attr_df <- data.frame(names(attribute_name_counts),
+                              attr_name_count_vector,
+                              attr_name_occ_vector)
+
+        names(attr_df) <- c("name", "occ", "P(occ)")
+        rownames(attr_df) <- seq(1, length(attribute_name_counts))
+
+        print(attr_df)
+    }
+
+    #List child elements
+
+    if(length(child_exists_counts) > 0) {
+
+        cat("\nThese are the child elements I found:\n")
+
+        child_ex_count_vector <- unlist(child_exists_counts, use.names=FALSE)
+        child_ex_occ_vector <- unlist(lapply(child_exists_counts, function(x){round((x / total_matches), 2)}))
+
+        child_tot_count_vector <- unlist(child_total_counts, use.names=FALSE)
+        child_tot_occ_vector <- unlist(lapply(child_total_counts, function(x){round((x / total_matches), 2)}))
+
+        child_df <- data.frame(names(child_exists_counts),
+                               child_ex_count_vector,
+                               child_ex_occ_vector,
+                               child_tot_count_vector,
+                               child_tot_occ_vector)
+
+        names(child_df) <- c("name", "ex_occ", "P(occ)", "total", "total_mean")
+        rownames(child_df) <- seq(1, length(child_exists_counts))
+
+        print(child_df)
+    }
+
+    #Think about output...
+    return(invisible())
+}
+
+
+#Experimental stuff
+generate_from_element <- function(element_name, attrs, children) {
+
+
+}
+
+generate_class_from_element <- function(element_name, class_name = NULL) {
+
+    #Generate name of new class from element name if class_name is not specified
+    if(is.null(class_name)){
+        class_name <- snakecase::to_any_case(element_name, "snake")
+    }
+
+
+    generated_class <- structure(list(), class = class_name)
+
+    return(generated_class)
+}
+
+generate_validator_from_element <- function() {
+
+}
+
+
+#cat(generate_as_node_from_element("DataArray", c("SexyAttr")))
+
+#'generate_as_node_from_element
+#'@description Generates a method for the generic function as_node based on an XML element
+#'@param element_name The name of the XML element to base the function on
+#'@param attrs Optional: A list of element attributes
+#'@param children Optional: A list of element children
+generate_as_node_from_element <- function(element_name,
+                                          attrs = NULL, opt_attrs = NULL,
+                                          children = NULL, opt_children = NULL) {
+
+    attrs_snake_names <- sapply(attrs, snakecase::to_any_case, case = "snake")
+    children_snake_names <- sapply(children, snakecase::to_any_case, case = "snake")
+
+    element_snake_name <- snakecase::to_any_case(element_name, "snake")
+
+    f_name <- paste0("as_node.", element_snake_name)
+
+    #Is the attribute optional?
+    optional = TRUE
+
+    #Is the child a parent itself?
+    is_parent = TRUE
+
+    func_str <- paste0(f_name, " <- function(obj) {\n")
+
+    node_name <- paste0(element_snake_name, "_node")
+
+    func_str <- paste0(func_str, "\t", node_name, " <- list(", element_name," = structure(list())\n")
+
+    #Add attributes
+    for(i in seq_len(length(attrs))){
+        nattr <- attrs_snake_names[[i]]
+        attr <- attrs[[i]]
+
+        if(attr %in% opt_attrs) {
+            func_str <- paste0(func_str, "\t", node_name, " <- add_opt_attr(", node_name,
+                               ", obj$", nattr, ", '", attr, "')\n")
+        }else{
+            func_str <- paste0(func_str, "\t", "attributes(", node_name,")[['", attr, "']] <- obj$",
+                               nattr, "\n")
+        }
+    }
+
+    #Add children
+    for(i in seq_len(length(children))){
+        child_snake <- children_snake_names[[i]]
+        child <- children[[i]]
+
+
+        if(child %in% opt_children) {
+            if(is_parent){
+                func_str <- paste0(func_str, "\t", node_name, " <- add_opt_child(", node_name,
+                                   ", obj$", child_snake, ", '", child, "')\n")
+            }else{
+                func_str <- paste0(func_str, "\t", node_name, " <- add_opt_child(", node_name,
+                                   ", obj$", child_snake, ")\n")
+            }
+        }else{
+            #...(WIP)
+        }
+    }
+
+    func_str <- paste0(func_str, "\t", "return(", node_name, ")\n")
+
+    func_str <- paste0(func_str, "}")
+
+    return(invisible(func_str))
+}
+
+#============================== HELPERS FOR analyse_xml ================================
+
+#'get_optional
+#'@description Helper function to get optional attributes or children from a vector of names and a
+#' vector of occurrence probabilities
+#' @param name_counts
+#' @param occurence_probabilities
+get_optional <- function(names, occurence_probabilities){
+    optional <- character()
+
+    for(i in seq_len(length(names))) {
+        if(occurence_probabilities[[i]] != 1) {
+            optional <- c(optional, names[[i]])
+        }
+    }
+
+    return(optional)
+}
+
+
+#'
+#'@description ...
+child_is_parent <- function() {
+
+}
diff --git a/R/create_gml_R6.R b/R/create_gml_R6.R
deleted file mode 100644
index e08168aacb8ece4df8ed93a9228a074eaf3c42be..0000000000000000000000000000000000000000
--- a/R/create_gml_R6.R
+++ /dev/null
@@ -1,702 +0,0 @@
-#This script contains a lot of R6 classes describing various .gml elements.
-
-#You can't build a complete .gml file from this (yet?)!!! Refer to the functions in create_gml instead.
-#The aforementioned functions are also way more practical to create a .gml file.
-#This script was really more of an exercise for getting used to handling XML data and R6 classes.
-
-#============================== Class export functionality ================================
-
-#' Creates a .gml XML file based on an GML object
-#' @param gml_object The specified GML object (of class GMLObject)
-#' @param file_name The name of the file the XML will be written to
-#' @return WIP
-# @examples
-# create_gml_from_obj(GMLPrefabCube$new(), "cube_1x1x1_new.gml")
-# create_gml_from_obj(GMLPrefabSquare$new(), "square_1x1_new.gml")
-create_gml_from_obj <- function(gml_object, file_name) {
-    doc <- xml2::as_xml_document(gml_object$as_node())
-    xml2::write_xml(doc, file_name, options = "format", encoding="ISO-8859-1")
-}
-
-
-#============================== OpenGeoSysGLI wrapper class ================================
-
-#' Class representing a GML object
-#'
-#' @param input_file_name An XML (.xml or, in the case of OpenGeoSys, .prj) file
-#' @return The encoding of the input file
-#'Class describing an entire GML object with a reference file name, points, polylines and surfaces
-GMLObject <- R6::R6Class("GMLObject",
-                         public = list(
-                             initialize = function(name = NULL, points = NULL, polylines = NULL, surfaces = NULL,
-                                                   xmlns_xsi = "http://www.w3.org/2001/XMLSchema-instance",
-                                                   xmlns_ogs = "http://www.opengeosys.org") {
-                                 stopifnot(is.character(xmlns_xsi), length(xmlns_xsi) == 1)
-                                 stopifnot(is.character(xmlns_ogs), length(xmlns_ogs) == 1)
-                                 stopifnot(is.character(name), length(name) == 1)
-                                 stopifnot(checkmate::checkList(points, types = "GMLPoints"), TRUE)
-                                 stopifnot(checkmate::checkList(polylines, types = "GMLPolylines"), TRUE)
-                                 stopifnot(checkmate::checkList(surfaces, types = "GMLSurfaces"), TRUE)
-
-                                 #(add more checks here)
-
-                                 private$.xmlns_xsi <- xmlns_xsi
-                                 private$.xmlns_ogs <- xmlns_ogs
-                                 private$.name <- name
-                                 private$.points <- points
-                                 private$.polylines <- polylines
-                                 private$.surfaces <- surfaces
-                             },
-
-                             as_node = function(...) {
-                                 return(list(OpenGeoSysGLI = structure(list(c(list(name = private$.name),
-                                                                              private$.points$as_node(),
-                                                                              private$.polylines$as_node(),
-                                                                              private$.surfaces$as_node())),
-                                                                       "xmlns:xsi" = private$.xmlns_xsi,
-                                                                       "xmlns:ogs" = private$.xmlns_ogs)))
-                             }
-                         ),
-
-                         active = list(
-                             xmlns_xsi = function(value) {
-                                 if (missing(value)) {
-                                     private$.xmlns_xsi
-                                 } else {
-                                     stop("`$xmlns_xsi` is read only", call. = FALSE)
-                                 }
-                             },
-
-                             xmlns_ogs = function(value) {
-                                 if (missing(value)) {
-                                     private$.xmlns_ogs
-                                 } else {
-                                     stop("`$xmlns_ogs` is read only", call. = FALSE)
-                                 }
-                             },
-
-                             name = function(value) {
-                                 if (missing(value)) {
-                                     private$.name
-                                 } else {
-                                     stop("`$name` is read only", call. = FALSE)
-                                 }
-                             },
-
-                             points = function(value) {
-                                 if (missing(value)) {
-                                     private$.points
-                                 } else {
-                                     stop("`$points` is read only", call. = FALSE)
-                                 }
-                             },
-
-                             polylines = function(value) {
-                                 if (missing(value)) {
-                                     private$.polylines
-                                 } else {
-                                     stop("`$polylines` is read only", call. = FALSE)
-                                 }
-                             },
-
-                             surfaces = function(value) {
-                                 if (missing(value)) {
-                                     private$.surfaces
-                                 } else {
-                                     stop("`$surfaces` is read only", call. = FALSE)
-                                 }
-                             }
-                         ),
-
-                         private = list(
-                             .xmlns_xsi = NULL,
-                             .xmlns_ogs = NULL,
-                             .name = NULL,
-                             .points = NULL,
-                             .polylines = NULL,
-                             .surfaces = NULL
-                         )
-)
-
-
-#============================== Point & Points ================================
-
-
-#'Class describing a single point
-#'
-GMLPoint <- R6::R6Class("GMLPoint",
-                        public = list(
-
-                            initialize = function(id = 0, coordinates = c(0, 0, 0), is_origin = FALSE) {
-                                stopifnot(is.numeric(id), length(id) == 1)
-                                stopifnot(is.numeric(coordinates), length(coordinates) > 0)
-                                stopifnot(is.logical(is_origin), length(is_origin) == 1)
-
-                                private$.id <- id
-                                private$.coordinates <- coordinates
-                                private$.dim <- length(private$.coordinates)
-                                private$.is_origin <- is_origin
-                            },
-
-                            as_list = function(...) {
-                                point_list <- list(id = private$.id,
-                                                   x = private$.coordinates[1], y = private$.coordinates[2], z = private$.coordinates[3])
-
-                                if(private$.is_origin){
-                                    point_list <- c(point_list, name = "origin")
-                                }
-
-                                return(point_list)
-                            },
-
-                            as_node = function(...){
-                                if(private$.is_origin){
-                                    return(list(point = structure(list(), id = private$.id,
-                                                                  x = private$.coordinates[1], y = private$.coordinates[2], z = private$.coordinates[3],
-                                                                  name = "origin")))
-                                }else{
-                                    return(list(point = structure(list(), id = private$.id,
-                                                                  x = private$.coordinates[1], y = private$.coordinates[2], z = private$.coordinates[3])))
-                                }
-                            },
-
-                            print = function(...) {
-                                cat("GMLPoint: \n")
-                                cat("  ID: ", private$.id, "\n", sep = "")
-                                cat("  Coordinates:  ", private$.coordinates,"\n", sep = "\t")
-                                cat("  Dimension:  ", private$.dim, "\n", sep = "")
-                                cat("  Is origin:  ", private$.is_origin, "\n", sep = "")
-
-                                invisible(self)
-                            }
-                        ),
-
-                        active = list(
-                            id = function(value) {
-                                if (missing(value)) {
-                                    private$.id
-                                } else {
-                                    stop("`$id` is read only", call. = FALSE)
-                                }
-                            },
-
-                            coordinates = function(value) {
-                                if (missing(value)) {
-                                    private$.coordinates
-                                } else {
-                                    stop("`$coordinates` is read only", call. = FALSE)
-                                }
-                            },
-
-                            dim = function(value) {
-                                if (missing(value)) {
-                                    private$.dim
-                                } else {
-                                    stop("`$dim` is read only", call. = FALSE)
-                                }
-                            },
-
-                            is_origin = function(value) {
-                                if (missing(value)) {
-                                    private$.is_origin
-                                } else {
-                                    stop("`$is_origin` is read only", call. = FALSE)
-                                }
-                            }
-                        ),
-
-                        private = list(
-                            .id = NULL,
-                            .coordinates = NULL,
-                            .dim = NULL,
-                            .is_origin = NULL
-                        )
-)
-
-
-#'Class describing a set of points
-#'
-GMLPoints <- R6::R6Class("GMLPoints",
-                         public = list(
-                             initialize = function(gml_points) {
-                                 stopifnot(checkmate::checkList(gml_points, types = "GMLPoint"), TRUE)
-                                 private$.ids <- self$validate_ids(gml_points)
-                                 self$validate_dim(gml_points)
-                                 self$validate_coordinates(gml_points)
-
-                                 private$.gml_points <- gml_points
-                             },
-
-                             validate_ids = function(gml_points){
-                                 ids = vector()
-
-                                 for(i in 1:length(gml_points)){
-                                     if(is.element(gml_points[[i]]$id, ids)){
-                                         stop("Duplicate point IDs detected", call. = FALSE)
-                                     }else{
-                                         ids <- c(ids, gml_points[[i]]$id)
-                                     }
-                                 }
-                                 return(ids)
-                             },
-
-                             validate_dim = function(gml_points) {
-                                 for(i in 2:length(gml_points)){
-                                     if(gml_points[[1]]$dim != gml_points[[i]]$dim){
-                                         stop("Point dimensions not eqal to each other", call. = FALSE)
-                                     }
-                                 }
-                             },
-
-                             validate_coordinates = function(gml_points) {
-                                 for(i in 1:(length(gml_points)-1)){
-                                     for(j in (i+1):length(gml_points)){
-                                         if(identical(gml_points[[i]]$coordinates, gml_points[[j]]$coordinates)){
-                                             stop("Overlapping points (with the same coordinates) detected", call. = FALSE)
-                                         }
-                                     }
-                                 }
-                             },
-
-                             as_list = function(...) {
-                                 points_list <- list()
-
-                                 for(i in 1:length(private$.gml_points)){
-                                     points_list <- c(points_list, list(point=private$.gml_points[[i]]$as_list()))
-                                 }
-
-                                 return(points_list)
-                             },
-
-                             as_node = function(...) {
-                                 points_node <- list(points = list())
-
-                                 for(i in 1:length(private$.gml_points)){
-                                     points_node[[1]] <- c(points_node[[1]], private$.gml_points[[i]]$as_node())
-                                 }
-
-                                 return(points_node)
-                             },
-
-                             print = function(...) {
-                                 cat("GMLPoints: \n")
-                                 cat("", "id", "x", "y", "z", "name", "\n", sep = "\t")
-                                 for(i in 1:length(private$.gml_points)) {
-                                     point_list <- private$.gml_points[[i]]$as_list()
-                                     cat("", unlist(point_list),  "\n", sep = "\t")
-                                 }
-                                 invisible(self)
-                             }
-
-                         ),
-
-                         active = list(
-                             ids = function(value) {
-                                 if (missing(value)) {
-                                     private$.ids
-                                 } else {
-                                     stop("`$ids` is read only", call. = FALSE)
-                                 }
-                             },
-
-                             gml_points = function(value) {
-                                 if (missing(value)) {
-                                     private$.gml_points
-                                 } else {
-                                     stop("`$gml_points` is read only", call. = FALSE)
-                                 }
-                             }
-                         ),
-
-                         private = list(
-                             .ids = NULL,
-                             .gml_points = NULL
-                         )
-)
-
-
-#============================== Polyline & Polylines ================================
-
-
-#'Class describing a single polyline
-GMLPolyline <- R6::R6Class("GMLPolyline",
-                           public = list(
-
-                               initialize = function(id = 0, name = "front_left", point1 = 0, point2 = 1) {
-                                   stopifnot(is.numeric(id), length(id) == 1)
-                                   stopifnot(is.character(name), length(name) == 1)
-                                   stopifnot(is.numeric(point1), length(point1) == 1)
-                                   stopifnot(is.numeric(point2), length(point2) == 1)
-                                   stopifnot(point1 != point2)
-
-                                   private$.id <- id
-                                   private$.name <- name
-                                   private$.point1 <- point1
-                                   private$.point2 <- point2
-                               },
-
-                               as_node = function(...) {
-                                   return(list(polyline = structure(list(pnt = list(private$.point1), pnt = list(private$.point2)),
-                                                                    id = private$.id, name = private$.name)))
-                               },
-
-                               print = function(...) {
-                                   cat("GMLPolyline: \n")
-                                   cat("  ID: ", private$.id, "\n", sep = "")
-                                   cat("  Name:  ", private$.name,"\n",sep = "")
-                                   cat("  Point 1:  ", private$.point1, "\n", sep = "")
-                                   cat("  Point 2:  ", private$.point2, "\n", sep = "")
-                                   invisible(self)
-                               }
-                           ),
-
-                           active = list(
-                               id = function(value) {
-                                   if (missing(value)) {
-                                       private$.id
-                                   } else {
-                                       stop("`$id` is read only", call. = FALSE)
-                                   }
-                               },
-
-                               name = function(value) {
-                                   if (missing(value)) {
-                                       private$.name
-                                   } else {
-                                       stop("`$name` is read only", call. = FALSE)
-                                   }
-                               },
-
-                               point1 = function(value) {
-                                   if (missing(value)) {
-                                       private$.point1
-                                   } else {
-                                       stop("`$point1` is read only", call. = FALSE)
-                                   }
-                               },
-
-                               point2 = function(value) {
-                                   if (missing(value)) {
-                                       private$.point2
-                                   } else {
-                                       stop("`$point2` is read only", call. = FALSE)
-                                   }
-                               }
-                           ),
-
-                           private = list(
-                               .id = NULL,
-                               .name = NULL,
-                               .point1 = NULL,
-                               .point2 = NULL
-                           )
-)
-
-
-#'Class describing a set of polylines
-#'
-GMLPolylines <- R6::R6Class("GMLPolylines",
-                            public = list(
-                                initialize = function(gml_polylines) {
-                                    stopifnot(checkmate::checkList(gml_polylines, types = "GMLPolyline"), TRUE)
-                                    self$validate_polylines(gml_polylines)
-
-                                    private$.ids <- self$validate_ids(gml_polylines)
-                                    private$.gml_polylines <- gml_polylines
-                                },
-
-                                validate_ids = function(gml_polylines){
-                                    ids = vector()
-
-                                    for(i in 1:length(gml_polylines)){
-                                        if(is.element(gml_polylines[[i]]$id, ids)){
-                                            stop("Duplicate polyline IDs detected", call. = FALSE)
-                                        }else{
-                                            ids <- c(ids, gml_polylines[[i]]$id)
-                                        }
-                                    }
-                                    return(ids)
-                                },
-
-                                validate_polylines = function(gml_polylines) {
-                                    for(i in 1:(length(gml_polylines)-1)){
-                                        for(j in (i+1):length(gml_polylines)) {
-                                            if((gml_polylines[[i]]$point1 == gml_polylines[[j]]$point1 &&
-                                                gml_polylines[[i]]$point2 == gml_polylines[[j]]$point2) ||
-                                               (gml_polylines[[i]]$point1 == gml_polylines[[j]]$point2 &&
-                                                gml_polylines[[i]]$point2 == gml_polylines[[j]]$point1)
-                                            ){
-                                                stop("Overlapping polylines detected", call. = FALSE)
-                                            }
-                                        }
-                                    }
-                                },
-
-                                as_node = function(...){
-                                    polylines_node <- list(polylines = list())
-
-                                    for(i in 1:length(private$.gml_polylines)){
-                                        polylines_node[[1]] <- c(polylines_node[[1]], private$.gml_polylines[[i]]$as_node())
-                                    }
-
-                                    return(polylines_node)
-                                }
-                            ),
-
-                            active = list(
-                                ids = function(value) {
-                                    if (missing(value)) {
-                                        private$.ids
-                                    } else {
-                                        stop("`$ids` is read only", call. = FALSE)
-                                    }
-                                },
-
-                                gml_polylines = function(value) {
-                                    if (missing(value)) {
-                                        private$.gml_polylines
-                                    } else {
-                                        stop("`$gml_polylines` is read only", call. = FALSE)
-                                    }
-                                }
-                            ),
-
-                            private = list(
-                                .ids = NULL,
-                                .gml_polylines = NULL
-                            )
-)
-
-
-#============================== Surface & Surfaces ================================
-
-
-#'Class describing a single surface element (using 3 point IDs)
-GMLSurfaceElement <- R6::R6Class("GMLSurfaceElement",
-                                 public = list(
-                                     initialize = function(p1 = 0, p2 = 1, p3 = 2) {
-                                         stopifnot(is.numeric(p1), length(p1) == 1)
-                                         stopifnot(is.numeric(p2), length(p2) == 1)
-                                         stopifnot(is.numeric(p3), length(p3) == 1)
-                                         stopifnot(p1 != p2, p1 != p3, p2 != p3)
-
-                                         private$.p1 <- p1
-                                         private$.p2 <- p2
-                                         private$.p3 <- p3
-                                     },
-
-                                     as_list = function(...) {
-                                         return(list(p1 = private$.p1, p2 = private$.p2, p3 = private$.p3))
-                                     },
-
-                                     as_node = function(...){
-                                         return(list(element = structure(list(), p1 = private$.p1, p2 = private$.p2, p3 = private$.p3)))
-                                     }
-                                 ),
-
-                                 active = list(
-                                     p1 = function(value) {
-                                         if (missing(value)) {
-                                             private$.p1
-                                         } else {
-                                             stop("`$p1` is read only", call. = FALSE)
-                                         }
-                                     },
-
-                                     p2 = function(value) {
-                                         if (missing(value)) {
-                                             private$.p2
-                                         } else {
-                                             stop("`$p2` is read only", call. = FALSE)
-                                         }
-                                     },
-
-                                     p3 = function(value) {
-                                         if (missing(value)) {
-                                             private$.p3
-                                         } else {
-                                             stop("`$p3` is read only", call. = FALSE)
-                                         }
-                                     }
-                                 ),
-
-                                 private = list(
-                                     .p1 = NULL,
-                                     .p2 = NULL,
-                                     .p3 = NULL
-                                 )
-)
-
-
-#'Class describing a single surface (using 2 GMLSurfaceElements)
-GMLSurface <- R6::R6Class("GMLSurface",
-                          public = list(
-
-                              initialize = function(id = 0, name = "left",
-                                                    gml_surface_element1 = GMLSurfaceElement$new(),
-                                                    gml_surface_element2 = GMLSurfaceElement$new(p3 = 3)) {
-                                  stopifnot(is.numeric(id), length(id) == 1)
-                                  stopifnot(is.character(name), length(name) == 1)
-
-                                  #check type of surface elements??
-
-                                  self$validate_elements(gml_surface_element1, gml_surface_element2)
-
-                                  private$.id <- id
-                                  private$.name <- name
-                                  private$.element1 <- gml_surface_element1
-                                  private$.element2 <- gml_surface_element2
-                              },
-
-                              validate_elements = function (gml_surface_element1, gml_surface_element2) {
-                                  elem_list1 <- gml_surface_element1$as_list()
-                                  elem_list2 <- gml_surface_element2$as_list()
-                                  equal_count <- 0
-
-                                  for(i in 1:length(elem_list1)) {
-                                      for(j in 1:length(elem_list2)) {
-                                          if(elem_list1[[i]] == elem_list2[[j]]) {
-                                              equal_count <- equal_count + 1
-                                              break
-                                          }
-                                      }
-                                  }
-
-                                  if(equal_count != 2) {
-                                      stop("Invalid surface detected", call. = FALSE)
-                                  }
-                              },
-
-                              as_node = function() {
-                                  return(list(surface = structure(c(private$.element1$as_node(), private$.element2$as_node()),
-                                                                  id = private$.id, name = private$.name)))
-                              }
-                          ),
-
-                          active = list(
-                              id = function(value) {
-                                  if (missing(value)) {
-                                      private$.id
-                                  } else {
-                                      stop("`id` is read only", call. = FALSE)
-                                  }
-                              },
-
-                              name = function(value) {
-                                  if (missing(value)) {
-                                      private$.name
-                                  } else {
-                                      stop("`name` is read only", call. = FALSE)
-                                  }
-                              },
-
-                              element1 = function(value) {
-                                  if (missing(value)) {
-                                      private$.element1
-                                  } else {
-                                      stop("`element1` is read only", call. = FALSE)
-                                  }
-                              },
-
-                              element2 = function(value) {
-                                  if (missing(value)) {
-                                      private$.element2
-                                  } else {
-                                      stop("`$element2` is read only", call. = FALSE)
-                                  }
-                              }
-                          ),
-
-                          private = list(
-                              .id = NULL,
-                              .name = NULL,
-                              .element1 = NULL,
-                              .element2 = NULL
-                          )
-)
-
-
-#'Class describing a set of surfaces
-GMLSurfaces <- R6::R6Class("GMLSurfaces",
-                           public = list(
-
-                               initialize = function(gml_surfaces) {
-                                   stopifnot(checkmate::checkList(gml_surfaces, types = "GMLSurface"), TRUE)
-                                   private$.ids <- self$validate_ids(gml_surfaces)
-                                   #validation of surfaces is a bit more difficult, there is no method for it yet!
-
-                                   private$.gml_surfaces <- gml_surfaces
-                               },
-
-                               validate_ids = function(gml_surfaces){
-                                   ids = vector()
-
-                                   for(i in 1:length(gml_surfaces)){
-                                       if(is.element(gml_surfaces[[i]]$id, ids)){
-                                           stop("Duplicate surface IDs detected", call. = FALSE)
-                                       }else{
-                                           ids <- c(ids, gml_surfaces[[i]]$id)
-                                       }
-                                   }
-                                   return(ids)
-                               },
-
-                               as_node = function(...){
-                                   surfaces_node <- list(surfaces = list())
-
-                                   for(i in 1:length(private$.gml_surfaces)){
-                                       surfaces_node[[1]] <- c(surfaces_node[[1]], private$.gml_surfaces[[i]]$as_node())
-                                   }
-
-                                   return(surfaces_node)
-                               }
-                           ),
-
-                           active = list(
-                               ids = function(value) {
-                                   if (missing(value)) {
-                                       private$.ids
-                                   } else {
-                                       stop("`ids` is read only", call. = FALSE)
-                                   }
-                               },
-
-                               gml_surfaces = function(value) {
-                                   if (missing(value)) {
-                                       private$.gml_surfaces
-                                   } else {
-                                       stop("`gml_surfaces` is read only", call. = FALSE)
-                                   }
-                               }
-                           ),
-
-                           private = list(
-                               .ids = NULL,
-                               .gml_surfaces = NULL
-                           )
-)
-
-#============================== Shared functions ================================
-
-#Helper function to check for the existence of identical objects in a list
-# @param object_list The list to check for duplicates
-# @param object_name Which objects the list consists of (for better error messages)
-# @param warn_only Should function throw error or only a warning?
-# @examples
-# check_for_duplicates(list(3, 0, 4), "point IDs")
-# check_for_duplicates(list(0, 0), "point IDs")
-# check_for_duplicates(list("no", "this", "is", "patrick"), "point names")
-# check_for_duplicates(list("no", "this", "is", "patrick", "patrick"), "point names", TRUE)
-check_for_duplicates <- function(object_list, object_name = NA, warn_only = FALSE) {
-    for(i in 1:(length(object_list)-1)) {
-        for(j in (i+1):length(object_list)) {
-            if(object_list[[i]] == object_list[[j]]) {
-                if(warn_only){
-                    warning(c("Duplicate ", object_name, " detected"), call. = FALSE)
-                }else{
-                    stop(c("Duplicate ", object_name, " detected"), call. = FALSE)
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/R/create_vtu.R b/R/create_vtu.R
deleted file mode 100644
index 1befbdeb701ebbd27c5953dbda01fe064d069a31..0000000000000000000000000000000000000000
--- a/R/create_vtu.R
+++ /dev/null
@@ -1,16 +0,0 @@
-#This script contains various functions to turn data for a .vtu file into the correct XML format
-
-vtu_data_to_xml <- function() {
-
-
-}
-
-
-
-vtu_piece_to_xml <- function(n_points, n_cells, point_data, cell_data, points, cells) {
-    piece_node <- list(piece = structure(list(),
-                                         NumberOfPoints = 0,
-                                         NumberOfCells = 0))
-    return(xml2::as_xml_document(piece_node))
-}
-
diff --git a/R/create_gml.R b/R/export_gml.R
similarity index 65%
rename from R/create_gml.R
rename to R/export_gml.R
index 4fa6a13b19941381f266440fb97fcb84cbc48c6c..f9265d9162f4b07ab81b5d1e675f6985b3e31f21 100644
--- a/R/create_gml.R
+++ b/R/export_gml.R
@@ -1,38 +1,31 @@
 #This script contains various functions to turn data for a .gml file into the correct XML format
 
-#' Export function
-#' @param xml_data The .gml data (already in XML friendly format)
-#' @param file_name The name of the .gml file to be written
-# @examples
-# export_xml_to_file(my_gml)
-#' @export
-export_xml_to_file <- function(xml_data, file_name) {
-  doc <- xml2::as_xml_document(xml_data)
-  xml2::write_xml(doc, file_name, options = "format", encoding="ISO-8859-1")
-  invisible()
-}
-
 
-#' Wrapper function to create a XML document based on the user input data
-#' @param geo_name The name of the geometry specified by the user
-#' @param points_tibble A tibble containing points
-#' @param polylines_list A list containing polylines
-#' @param surfaces_list A list containing surfaces
+#' Wrapper function to create a .gml XML document based on the user input data
+#' @param gml_obj A gml class object
 #' @return A XML document ready for export to a file
 # @examples (WIP)
-#' @export
-gml_data_to_xml <- function(geo_name, points_tibble, polylines_list, surfaces_list) {
+gml_data_to_xml <- function(gml_obj) {
 
-  #data_node <- xml2::read_xml('<OpenGeoSysGLI xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogs="http://www.opengeosys.org"/>')
+  validate_gml_data(gml_obj)
 
   data_node <- xml2::xml_new_root(.value = "OpenGeoSysGLI",
                     "xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance",
                     "xmlns:ogs" = "http://www.opengeosys.org")
 
-  xml2::xml_add_child(data_node, xml2::as_xml_document(list(name = list(geo_name))))
-  xml2::xml_add_child(data_node, points_to_xml(points_tibble))
-  xml2::xml_add_child(data_node, polylines_to_xml(polylines_list))
-  xml2::xml_add_child(data_node, surfaces_to_xml(surfaces_list))
+  xml2::xml_add_child(data_node, xml2::as_xml_document(list(name = list(gml_obj$geometry_name))))
+
+  if(!is.null(gml_obj$points)){
+    xml2::xml_add_child(data_node, points_to_xml(gml_obj$points))
+  }
+
+  if(!is.null(gml_obj$polylines)){
+    xml2::xml_add_child(data_node, polylines_to_xml(gml_obj$polylines))
+  }
+
+  if(!is.null(gml_obj$surfaces)){
+    xml2::xml_add_child(data_node, surfaces_to_xml(gml_obj$surfaces))
+  }
 
   return(data_node)
 }
@@ -70,21 +63,21 @@ points_to_xml <- function(point_tibble) {
 }
 
 #' Turns a list of polylines into an XML node
-#' @param polyline_list The specified list
+#' @param polylines A list of polylines
 #' @return An XML node containing the polylines
 #' @examples
 #' my_list <- list(list(name = "front_left", c(0, 1)), list(name = "front_right", c(4, 5)))
 #' polylines_node <- polylines_to_xml(my_list)
 #' @export
-polylines_to_xml <- function(polyline_list) {
+polylines_to_xml <- function(polylines) {
   polylines_node <- list(polylines = list())
 
-  for(i in 1:length(polyline_list)){
+  for(i in 1:length(polylines)){
 
     pnt_list <- list()
 
-    for(j in 1:length(polyline_list[[i]][[2]])) {
-      pnt_list <- c(pnt_list, list(pnt = list(polyline_list[[i]][[2]][[j]])))
+    for(j in 1:length(polylines[[i]][[2]])) {
+      pnt_list <- c(pnt_list, list(pnt = list(polylines[[i]][[2]][[j]])))
     }
 
     polylines_node[[1]] <- c(polylines_node[[1]], list(polyline = structure(pnt_list,
@@ -96,27 +89,27 @@ polylines_to_xml <- function(polyline_list) {
 }
 
 #' Turns a list of surfaces into an XML node
-#' @param surfaces_list The specified list
+#' @param surfaces A list of surfaces
 #' @return An XML node containing the surfaces
 #' @examples
 #' my_list <- list(list(name = "left", c(0, 1, 2), c(0, 3, 2)),
 #' list(name = "right", c(4, 6, 5), c(4, 6, 7)))
 #' surfaces_node <- surfaces_to_xml(my_list)
 #' @export
-surfaces_to_xml <- function(surfaces_list) {
+surfaces_to_xml <- function(surfaces) {
   surfaces_node <- list(surfaces = list())
 
-  for(i in 1:length(surfaces_list)){
+  for(i in 1:length(surfaces)){
     surfaces_node[[1]] <- c(surfaces_node[[1]], list(surface = structure(c(list(element = structure(list(),
-                                                                                                    p1 = surfaces_list[[i]][[2]][[1]],
-                                                                                                    p2 = surfaces_list[[i]][[2]][[2]],
-                                                                                                    p3 = surfaces_list[[i]][[2]][[3]])),
+                                                                                                    p1 = surfaces[[i]][[2]][[1]],
+                                                                                                    p2 = surfaces[[i]][[2]][[2]],
+                                                                                                    p3 = surfaces[[i]][[2]][[3]])),
                                                                            list(element = structure(list(),
-                                                                                                    p1 = surfaces_list[[i]][[3]][[1]],
-                                                                                                    p2 = surfaces_list[[i]][[3]][[2]],
-                                                                                                    p3 = surfaces_list[[i]][[3]][[3]]))),
+                                                                                                    p1 = surfaces[[i]][[3]][[1]],
+                                                                                                    p2 = surfaces[[i]][[3]][[2]],
+                                                                                                    p3 = surfaces[[i]][[3]][[3]]))),
                                                                          id = (i-1),
-                                                                         name = surfaces_list[[i]][[1]])))
+                                                                         name = surfaces[[i]][[1]])))
   }
 
   return(xml2::as_xml_document(surfaces_node))
diff --git a/R/export_prj.R b/R/export_prj.R
new file mode 100644
index 0000000000000000000000000000000000000000..018bc798051f7150a0ed6d3229ec1d244c0f9d7e
--- /dev/null
+++ b/R/export_prj.R
@@ -0,0 +1,85 @@
+#This script contains various functions to turn data for a .prj file into the correct XML format
+
+#' Wrapper function to create a .prj XML document based on the user input data
+#' @param prj_obj .
+prj_data_to_xml <- function(prj_obj) {
+
+    data_node <- xml2::xml_new_root(.value = "OpenGeoSysProject")
+
+    xml2::xml_add_child(data_node, adopt_nodes("processes", prj_obj$processes))
+    xml2::xml_add_child(data_node, adopt_nodes("media", prj_obj$media))
+    xml2::xml_add_child(data_node, adopt_nodes("time_loop", prj_obj$time_loop))
+    xml2::xml_add_child(data_node, adopt_nodes("parameters", prj_obj$parameters))
+    xml2::xml_add_child(data_node, adopt_nodes("process_variables", prj_obj$process_variables))
+    xml2::xml_add_child(data_node, adopt_nodes("nonlinear_solvers", prj_obj$nonlinear_solvers))
+    xml2::xml_add_child(data_node, adopt_nodes("linear_solvers", prj_obj$linear_solvers))
+
+    return(data_node)
+}
+
+#============================== processes ================================
+
+#Implementation for class r2ogs6_process
+as_node.r2ogs6_prj_process <- function(obj){
+
+    process_node <- list(process = structure(list(name = obj$name,
+                                                  type = obj$type,
+                                                  integration_order = obj$integration_order,
+                                                  dimension = obj$dimension,
+                                                  constitutive_relation = list(type = obj$cr_type,
+                                                                               youngs_modulus = obj$cr_youngs_modulus,
+                                                                               poissons_ratio = obj$cr_poissons_ratio),
+                                                  process_variables = list(displacement = obj$pv_displacement,
+                                                                           pressure = obj$pv_pressure),
+                                                  secondary_variables = list(),
+                                                  specific_body_force = obj$specific_body_force)))
+    return(process_node)
+}
+
+
+#'Method for coercing an r2ogs6_prj_property class object into the structure expected by xml2
+as_node.r2ogs6_prj_property <- function(obj) {
+    return(list(property = list(name = obj$name, type = obj$type)))
+}
+
+
+#============================== media ================================
+
+
+#'Method for coercing an r2ogs_prj_medium_phase class object into the structure expected by xml2
+as_node.r2ogs6_prj_medium_phase <- function(obj) {
+    medium_phase_node <- list(phase = list(type = obj$type),
+                              adopt_nodes("properties", obj$properties))
+    return(medium_phase_node)
+}
+
+
+as_node.r2ogs6_prj_medium <- function(obj) {
+
+    medium_node <- list(medium = list(phases = list(), properties = list()))
+
+    for(i in 1:length(obj$phases)){
+        medium_node[[1]] <- c(medium_node[[1]][[1]], as_node(obj$phases[[i]]))
+    }
+
+    for(i in 1:length(obj$properties)){
+        medium_node[[1]] <- c(medium_node[[1]][[2]], as_node(obj$properties[[i]]))
+    }
+
+    return(medium_node)
+}
+
+
+#============================== time_loop ================================
+
+
+#============================== parameters ================================
+
+
+#============================== process_variables ================================
+
+
+#============================== nonlinear_solvers ================================
+
+
+#============================== linear_solvers ================================
\ No newline at end of file
diff --git a/R/export_vtu.R b/R/export_vtu.R
new file mode 100644
index 0000000000000000000000000000000000000000..9d618fb6c93d4814a13cecdf646bf333429e935b
--- /dev/null
+++ b/R/export_vtu.R
@@ -0,0 +1,75 @@
+#This script contains various functions to turn data for a .vtu file into the correct XML format
+
+
+#' Wrapper function to create a .vtu XML document based on the user input data
+#' @param vtu_obj A vtu class object
+#' @return A XML document ready for export to a file
+# @examples (WIP)
+vtu_data_to_xml <- function(vtu_obj) {
+
+    validate_vtu_data(vtu_obj)
+
+    data_node <- list(VTKFile = structure(list(),
+                                          type = vtu_obj$type,
+                                          version = vtu_obj$version,
+                                          byte_order = vtu_obj$byte_order,
+                                          header_type = vtu_obj$header_type))
+
+    data_node <- add_opt_attr(data_node, vtu_obj$compressor, "compressor")
+
+    #Add all the data here... (WIP)
+
+}
+
+
+vtu_unstructured_grid_to_xml <- function() {
+
+    unstructured_grid_node <- list(UnstructuredGrid = list())
+
+    field_data_xml <- adopt_nodes("FieldData", field_data_data_arrays)
+
+}
+
+#'(WIP, change input parameter to piece!!)
+#'@param piece A list consisting of lists of data_array class objects
+vtu_piece_to_xml <- function(number_of_points, number_of_cells, point_data, cell_data, points, cells) {
+
+    piece_node <- list(piece = structure(list(adopt_nodes("PointData", point_data),
+                                              adopt_nodes("CellData", cell_data),
+                                              adopt_nodes("Points", points),
+                                              adopt_nodes("Cells", cells)),
+                                         NumberOfPoints = number_of_points,
+                                         NumberOfCells = number_of_cells))
+
+    return(xml2::as_xml_document(piece_node))
+}
+
+
+#(WIP)
+vtu_data_array_to_xml <- function(data_array) {
+    data_array_node <- list(DataArray = structure(list(),
+                                                  type,
+                                                  Name,
+                                                  format,
+                                                  rangeMin,
+                                                  rangeMax))
+
+
+    if(1){
+
+    }
+
+    return(xml2::as_xml_document(data_array_node))
+}
+
+#'vtu_appended_data_to_xml
+#'@name vtu_appended_data_to_xml
+#'(WIP)
+#'@param appended_data A list object consisting of 2 elements named 'data' and 'encoding'
+#'
+vtu_appended_data_to_xml <- function(appended_data) {
+
+    return(list(AppendedData = structure(list(appended_data[[data]]),
+                                         encoding = appended_data[[encoding]])))
+}
+
diff --git a/R/generics.R b/R/generics.R
new file mode 100644
index 0000000000000000000000000000000000000000..0574d12b0e9b7b958ebac4669c15d9a0c8582400
--- /dev/null
+++ b/R/generics.R
@@ -0,0 +1,8 @@
+
+
+
+#'S3 generic function, use to turn class data into XML friendly format
+#'@param obj A class object (must have implementation for as_node)
+as_node <- function(obj) {
+    UseMethod("as_node")
+}
\ No newline at end of file
diff --git a/R/input_add_gml.R b/R/input_add_gml.R
new file mode 100644
index 0000000000000000000000000000000000000000..19cead3ed9ef3f1d035ddbce6208beaba7c8f137
--- /dev/null
+++ b/R/input_add_gml.R
@@ -0,0 +1,86 @@
+# Functions for adding .gml data
+# input: ogs6 class object
+# output: updated ogs6 class object
+
+#'Class describing the gml file and any parameters defined in one
+new_gml <- function(geometry_name = NULL,
+                    points = NULL,
+                    polylines = NULL,
+                    surfaces = NULL) {
+
+    structure(
+        list(geometry_name = geometry_name,
+             points = points,
+             polylines = polylines,
+             surfaces = surfaces),
+
+        class = "gml")
+}
+
+
+#'Adds an empty gml class object to a ogs6 class object input list
+#'@param ogs6_obj The ogs6 object the gml class object should be added to
+#'@param geometry_name The name of the geometry specified by the gml class object
+input_add_gml_obj <- function(ogs6_obj, geometry_name) {
+
+    if(!is.character(geometry_name)){
+        stop("'geometry_name' is not of type character()", call. = FALSE)
+    }
+
+    if("gml_obj" %in% names(ogs6_obj$sim_input)){
+        stop("ogs6_obj already has a gml object attached to it.", call. = FALSE)
+    }else{
+        ogs6_obj$add_sim_io_input("gml_obj", new_gml(geometry_name = geometry_name))
+    }
+}
+
+
+#'Adds gml points to a ogs6 class object
+#'@param ogs6_obj A ogs6 class object
+#'@param gml_points A tibble of gml points
+input_add_gml_points <- function(ogs6_obj, gml_points) {
+
+    validate_points(gml_points)
+
+    check_for_obj_of_name(ogs6_obj, "gml_obj")
+
+    if(!is.null(ogs6_obj$sim_input[["gml_obj"]]$gml_points)){
+        stop("There are already points defined for the gml object", call. = FALSE)
+    }else{
+        ogs6_obj$set_sim_input_obj_param("gml_obj", "gml_points", gml_points)
+    }
+}
+
+
+#'Adds gml polylines to a ogs6 class object
+#'@param ogs6_obj A ogs6 class object
+#'@param gml_polylines A list of gml polylines
+input_add_gml_polylines <- function(ogs6_obj, gml_polylines) {
+
+    validate_polylines(gml_polylines)
+
+    check_for_obj_of_name(ogs6_obj, "gml_obj")
+
+    if(!is.null(ogs6_obj$sim_input[["gml_obj"]]$gml_polylines)){
+        stop("There are already polylines defined for the gml object", call. = FALSE)
+    }else{
+        ogs6_obj$set_sim_input_obj_param("gml_obj", "gml_polylines", gml_polylines)
+    }
+}
+
+
+#'Adds gml surfaces to a ogs6 class object
+#'@param ogs6_obj A ogs6 class object
+#'@param gml_surfaces A list of gml surfaces
+input_add_gml_surfaces <- function(ogs6_obj, gml_surfaces) {
+
+    validate_surfaces(gml_surfaces)
+
+    check_for_obj_of_name(ogs6_obj, "gml_obj")
+
+    if(!is.null(ogs6_obj$sim_input[["gml_obj"]]$gml_surfaces)){
+        stop("There are already surfaces defined for the gml object", call. = FALSE)
+    }else{
+        ogs6_obj$set_sim_io_input_obj_param("gml_obj", "gml_surfaces", gml_surfaces)
+    }
+}
\ No newline at end of file
diff --git a/R/input_add_prj.R b/R/input_add_prj.R
new file mode 100644
index 0000000000000000000000000000000000000000..882e70493b5e9189f53c224fa1f587ef91e296ba
--- /dev/null
+++ b/R/input_add_prj.R
@@ -0,0 +1,135 @@
+#This script contains various S3 classes, methods and functions to turn data for a .prj file into
+#the correct XML format. (WIP!!!)
+
+
+#============================== Functions to be exported ================================
+
+
+
+
+#============================== processes classes and methods ================================
+
+
+#S3 class representing a .prj process element
+#'@param name The process name
+#'@param type The process type
+#'@param integration_order ...
+#'@param dimension ...
+#'@param constitutive_relation ...
+#'@param process_variables ...
+#'@param secondary_variables A list of secondary variables
+#'@param specific_body_force The specific body force
+new_r2ogs_prj_process <- function(name, type, integration_order, dimension, constitutive_relation,
+                                   process_variables, secondary_variables, specific_body_force) {
+    #validating functions here
+
+    structure(
+        list(
+            name = name,
+            type = type,
+            integration_order = integration_order,
+            dimension = dimension,
+            constitutive_relation = constitutive_relation,
+            process_variables = process_variables,
+            secondary_variables = secondary_variables,
+            specific_body_force = specific_body_force,
+        ),
+        class = "r2ogs_prj_process"
+    )
+}
+
+
+
+
+
+#============================== media classes and methods ================================
+
+new_r2ogs_prj_property <- function(name = character(), type = character(), value = double()){
+    #Validate...
+
+
+    structure(
+        list(
+            name = name,
+            type = type,
+            value = value
+        ),
+        class = "r2ogs6_prj_property"
+    )
+}
+
+
+
+
+#'Defines a .prj medium phase element
+#'@param type A string specifying the medium type (valid types: ...)
+#'@param properties A list of properties (see ?r2ogs6_property for more info)
+new_r2ogs6_prj_medium_phase <- function(type = character(), properties = list()) {
+
+    stopifnot(is.character(type), length(type) == 1)
+
+    structure(
+        list(
+            type = type,
+            properties = properties
+        ),
+        class = "r2ogs6_prj_medium_phase"
+    )
+}
+
+
+
+
+#'
+#'@param phases A list of medium phases
+#'@param properties A list of medium properties
+new_r2ogs6_prj_medium <- function(phases = list(), properties = list()) {
+    #Validate
+
+    stopifnot(is.list(phases))
+    stopifnot(is.list(properties))
+
+    structure(
+        list(
+            phases = phases,
+            properties = properties
+        ),
+        class = "r2ogs6_prj_medium"
+    )
+}
+
+
+
+
+#============================== time_loop classes and methods ================================
+
+#============================== parameters classes and methods ================================
+
+
+new_r2ogs6_prj_parameter <- function(name = character(), type = character(), value = double()) {
+    #Validate
+
+    structure(
+        list(
+            name = name,
+            type = type,
+            value = value
+        ),
+        class = "r2ogs6_prj_parameter"
+    )
+}
+
+
+
+#============================== process_variables classes and methods ================================
+
+
+#============================== nonlinear_solvers classes and methods ================================
+
+#============================== linear_solvers classes and methods ================================
+
+
+
+
+
+
diff --git a/R/input_add_vtu.R b/R/input_add_vtu.R
new file mode 100644
index 0000000000000000000000000000000000000000..867713cf2c030cac69d3987e7dc98ffa146cf822
--- /dev/null
+++ b/R/input_add_vtu.R
@@ -0,0 +1,151 @@
+# Functions for adding .vtu data
+# input: ogs6 class object
+# output: updated ogs6 class object
+
+#'new_vtu
+#'@description S3 class constructor, returns S3 class describing the .vtu file and any parameters defined in it
+#'@param type The type of the vtu file (e. g. "UnstructuredGrid")
+#'@param version The version of the .vtu file (e. g. 1.0)
+#'@param byte_order Either "LittleEndian" or "BigEndian"
+#'@param header_type The header type (e. g. "UInt32")
+#'@param compressor Optional: The compressor to be used
+new_vtu <- function(type,
+                    version,
+                    byte_order,
+                    header_type,
+                    compressor = NULL) {
+
+    assertthat::assert_that(assertthat::is.string(type))
+    assertthat::assert_that(is.double(version))
+    assertthat::assert_that(assertthat::is.string(byte_order))
+    assertthat::assert_that(assertthat::is.string(header_type))
+
+    if(!is.null(compressor)){
+        assertthat::assert_that(assertthat::is.string(compressor))
+    }
+
+    structure(
+        list(unstructured_grid = NULL,
+             appended_data = NULL),
+
+        type = type,
+        version = version,
+        byte_order = byte_order,
+        header_type = header_type,
+        compressor = compressor,
+        class = "vtu")
+}
+
+#'new_data_array
+#'@description S3 class constructor, returns S3 class describing a .vtu DataArray element
+#'@param type
+#'@param name
+#'@param format
+#'@param range_min
+#'@param range_max
+#'@param number_of_components
+#'@param number_of_tuples
+#'@param offset
+#'@param data
+new_data_array <- function(type, name, format, range_min, range_max,
+                           number_of_components = NULL, number_of_tuples = NULL,
+                           offset = NULL, data = NULL) {
+    structure(
+        list(type,
+             name,
+             format,
+             range_min,
+             range_max,
+             offset,
+             number_of_components,
+             number_of_tuples,
+             data),
+        class = "data_array"
+    )
+}
+
+#'as_node.data_array
+#'@description Implementation of the generic function as_node for data_array class objects
+as_node.data_array <- function(obj) {
+
+    data_array_node <- list(DataArray = structure(list(), type = obj$type, Name = obj$name))
+
+    data_array_node <- add_opt_child(data_array_node, obj$data)
+
+    data_array_node <- add_opt_attr(data_array_node, obj$number_of_components, "NumberOfComponents")
+    data_array_node <- add_opt_attr(data_array_node, obj$number_of_tuples, "NumberOfTuples")
+
+    attributes(data_array_node)[["format"]] <- obj$format
+    attributes(data_array_node)[["RangeMin"]] <- obj$range_min
+    attributes(data_array_node)[["RangeMax"]] <- obj$range_max
+
+    data_array_node <- add_opt_attr(data_array_node, obj$offset, "offset")
+
+    return(data_array_node)
+}
+
+
+#'input_add_vtu_obj
+#'@description Adds an empty vtu class object to a ogs6 class object input.
+#'@param ogs6_obj The ogs6 object the vtu class object should be added to
+#'@param type The type of the .vtu file (e. g. "UnstructuredGrid")
+#'@param version The version of the .vtu file (e. g. 1.0)
+#'@param byte_order Either "LittleEndian" or "BigEndian"
+#'@param header_type The header type (e. g. "UInt32")
+#'@param compressor Optional: The compressor to be used
+#'@export
+input_add_vtu_obj <- function(ogs6_obj, type, version, byte_order, header_type, compressor = NULL) {
+
+    if("vtu_obj" %in% names(ogs6_obj$sim_input)){
+        stop("ogs6_obj already has a vtu object attached to it.", call. = FALSE)
+    }else{
+        ogs6_obj$add_sim_input("vtu_obj", new_vtu(type = type,
+                                                  version = version,
+                                                  byte_order = byte_order,
+                                                  header_type = header_type,
+                                                  compressor = compressor))
+    }
+}
+
+
+#'input_add_vtu_unstructured_grid
+#'@description Adds .vtu UnstructuredGrid to a ogs6 class object
+#'@param ogs6_obj The ogs6 object the .vtu UnstructuredGrid should be added to
+#'@param piece A Piece (WIP)
+#'@param field_data FieldData (WIP)
+#'@export
+input_add_vtu_unstructured_grid <- function(ogs6_obj, piece, field_data = NULL) {
+
+    #validator missing...
+
+    check_for_obj_of_name(ogs6_obj, "vtu_obj")
+
+    #...
+    set_sim_input_obj_param("vtu_obj", "unstructured_grid", list(field_data = field_data,
+                                                                 piece = piece))
+}
+
+
+#'input_add_vtu_appended_data
+#'@description Adds .vtu AppendedData to a ogs6 class object
+#'@param ogs6_obj The ogs6 object the .vtu AppendedData should be added to
+#'@param encoding How the AppendedData is encoded
+#'@param data The actual data in the specified encoding
+#'@export
+input_add_vtu_appended_data <- function(ogs6_obj, encoding, data) {
+
+    #validator missing...
+
+    check_for_obj_of_name(ogs6_obj, "vtu_obj")
+
+    assertthat::assert_that(assertthat::is.string(encoding))
+    assertthat::assert_that(assertthat::is.string(data))
+
+    if(!(encoding %in% vtu_appended_data_valid_encoding_types)) {
+        stop("Invalid encoding for vtu appended data. For an overview of valid
+             types refer to ?vtu_appended_data_valid_encoding_types", call. = FALSE)
+    }
+
+    set_sim_input_obj_param("vtu_obj", "appended_data", list(encoding = encoding,
+                                                             data = data))
+}
\ No newline at end of file
diff --git a/R/ogs6.R b/R/ogs6.R
new file mode 100644
index 0000000000000000000000000000000000000000..201b068a5db53f6ad1a900075e281a2019f86f69
--- /dev/null
+++ b/R/ogs6.R
@@ -0,0 +1,145 @@
+
+
+#============================== R6 ================================
+
+#'Constructor for the OGS6 base class
+OGS6 <- R6::R6Class("OGS6",
+  public = list(
+
+    initialize = function(sim_name,
+                          sim_id,
+                          sim_path) {
+
+      # Basic validation
+      assertthat::assert_that(assertthat::is.string(sim_name))
+      assertthat::assert_that(is.integer(sim_id))
+      assertthat::assert_that(assertthat::is.string(sim_path))
+
+        private$.sim_input <- list()
+        private$.sim_output <- list()
+
+        private$.sim_name <- sim_name
+        private$.sim_id <- sim_id
+        private$.sim_path <- sim_path
+    },
+
+    add_sim_input = function(name, value) {
+        private$.sim_input[[name]] <- value
+    },
+
+    set_sim_input_obj_param = function(obj_name, obj_param_name, value) {
+        private$.sim_input[[obj_name]]$obj_param_name <- value
+    },
+
+    add_sim_output = function(name, value) {
+        private$.sim_output[[name]] <- value
+    }
+
+  ),
+
+  active = list(
+      sim_input = function(value) {
+          if (missing(value)) {
+              private$.sim_input
+          } else {
+              stop("To modify `$sim_input`, use set_sim_input().", call. = FALSE)
+          }
+      },
+
+      sim_output = function(value) {
+        if (missing(value)) {
+          private$.sim_output
+        } else {
+          stop("To modify `$sim_output`, use set_sim_output().", call. = FALSE)
+        }
+      },
+
+      sim_name = function(value) {
+          if (missing(value)) {
+              private$.sim_name
+          } else {
+              stop("`$sim_name` is read only", call. = FALSE)
+          }
+      },
+
+      sim_id = function(value) {
+          if (missing(value)) {
+              private$.sim_id
+          } else {
+              stop("`$sim_id` is read only", call. = FALSE)
+          }
+      },
+
+      sim_path = function(value) {
+          if (missing(value)) {
+              private$.sim_path
+          } else {
+              stop("`$sim_path` is read only", call. = FALSE)
+          }
+      }
+
+  ),
+
+  private = list(
+      .sim_input = NULL,
+      .sim_output = NULL,
+      .sim_name = NULL,
+      .sim_id = NULL,
+      .sim_path = NULL
+  )
+)
+
+
+
+
+#============================== S3 ================================
+
+#'Constructor for the ogs6 base class
+#'
+#'@param sim_io ...
+#'@param sim_name A string value representing the simulation name
+#'@param sim_id An integer value representing the simulation ID
+#'@param sim_path A string value describing the path where the IO files will be saved
+new_ogs6 <- function(sim_io = list(input = list(), output = list()),
+                     sim_name = character(),
+                     sim_id = integer(),
+                     sim_path = character()) {
+
+    # Basic validation
+    if (!is.character(sim_name)) {
+        stop("'sim_name' has to be of type character", call. = FALSE)
+    }
+
+    if (!is.integer(sim_id)) {
+        stop("'sim_id' has to be of type integer", call. = FALSE)
+    }
+
+    if (!is.character(sim_path)) {
+        stop("'sim_path' has to be of type character", call. = FALSE)
+    }
+
+    structure(
+        sim_io,
+        sim_name = sim_name,
+        sim_id = sim_id,
+        sim_path = sim_path,
+        class = "ogs6"
+    )
+}
+
+#' Validating functions for an ogs6 class object (to be run before a simulation is started)
+validate_ogs6 <- function(ogs6_obj) {
+
+
+    if (!class(ogs6_obj) == "ogs6") {
+        stop("ogs6_obj is not of class 'ogs6' ", call. = FALSE)
+    }
+    if (is.null(x$input)) {
+        stop("'input' list missing.", call. = FALSE)
+    }
+    if (is.null(x$output)) {
+        stop("'output' list missing.", call. = FALSE)
+    }
+
+}
+
diff --git a/R/user_input.R b/R/user_input.R
index 2acfb732eca53f089217751a101e2e1a60472fc2..7c317fb675e2b5984345340c71732b355aca943b 100644
--- a/R/user_input.R
+++ b/R/user_input.R
@@ -1,67 +1,179 @@
 #This is where the user defines his data.
 
-#============================== Data for GML file ================================
-
-#Specify some data (source: HydroComponent Benchmarks -> IdealGas -> flow_free_expansion -> cube_1x1x1.gml)
-
-#The name of the desired geometry (will become first XML child under root)
-geo_name <- "cube_1x1x1_geometry"
-
-#Some points (will become second XML child under root)
-my_gml_points <- tibble::tibble(x = c(0, 0, 0, 0, 1, 1, 1, 1),
-                            y = c(0, 0, 1, 1, 0, 0, 1, 1),
-                            z = c(0, 1, 1, 0, 0, 1, 1, 0),
-                            name = c("origin", rep("", 7)))
-
-#Some polylines (will become third XML child under root)
-my_gml_polylines <- list(list(name = "front_left", c(0, 1)),
-                     list(name = "front_right", c(4, 5)),
-                     list(name = "front_bottom", c(0, 4)),
-                     list(name = "front_top", c(1, 5)),
-                     list(name = "bottom_left", c(0, 3)),
-                     list(name = "bottom_right", c(4, 7)),
-                     list(name = "top_left", c(1, 2)),
-                     list(name = "top_right", c(5, 6)),
-                     list(name = "back_left", c(2, 3)),
-                     list(name = "back_right", c(6, 7)),
-                     list(name = "back_bottom", c(3, 7)),
-                     list(name = "back_top", c(2, 6)))
-
-#Some surfaces (will become fourth XML child under root)
-my_gml_surfaces <- list(list(name = "left", c(0, 1, 2), c(0, 3, 2)),
-                    list(name = "right", c(4, 6, 5), c(4, 6, 7)),
-                    list(name = "top", c(1, 2, 5), c(5, 2, 6)),
-                    list(name = "bottom", c(0, 3, 4), c(4, 3, 7)),
-                    list(name = "front", c(0, 1, 4), c(4, 1, 5)),
-                    list(name = "back", c(2, 3, 6), c(6, 3, 7)))
-
-
-#============================== Data for VTU file ================================
-
-
-my_vtk_specification <- list(type="UnstructuredGrid",
-                             version="0.1",
-                             byte_order="LittleEndian",
-                             header_type="UInt32",
-                             compressor="vtkZLibDataCompressor")
-
-
-
-my_vtk_pieces <- list()
+
+#============================== SET UP SIMULATION OBJECT ================================
+
+# my_ogs6_obj <- new_ogs6( sim_io = list(input = list(), output = list()),
+#                          sim_name = "my_sim",
+#                          sim_id = 1L,
+#                          sim_path = "simulations/")
+
+
+my_ogs6_obj <- OGS6$new( sim_name = "my_sim",
+                         sim_id = 1L,
+                         sim_path = "simulations/")
+
+
+#============================== ADD .gml DATA ================================
+
+#(source: HydroComponent Benchmarks -> IdealGas -> flow_free_expansion -> cube_1x1x1.gml)
+
+# #Add gml object and give it a name
+# input_add_gml_obj(my_ogs6_obj, "cube_1x1x1_geometry")
+#
+
+
+
+# #Add some points
+input_add_gml_points(my_ogs6_obj, tibble::tibble(x = c(0, 0, 0, 0, 1, 1, 1, 1),
+                                                 y = c(0, 0, 1, 1, 0, 0, 1, 1),
+                                                 z = c(0, 1, 1, 0, 0, 1, 1, 0),
+                                                 name = c("origin", rep("", 7))))
+#
+# #Add some polylines
+# input_add_gml_polylines(my_ogs6_obj, list(list(name = "front_left", c(0, 1)),
+#                                           list(name = "front_right", c(4, 5)),
+#                                           list(name = "front_bottom", c(0, 4)),
+#                                           list(name = "front_top", c(1, 5)),
+#                                           list(name = "bottom_left", c(0, 3)),
+#                                           list(name = "bottom_right", c(4, 7)),
+#                                           list(name = "top_left", c(1, 2)),
+#                                           list(name = "top_right", c(5, 6)),
+#                                           list(name = "back_left", c(2, 3)),
+#                                           list(name = "back_right", c(6, 7)),
+#                                           list(name = "back_bottom", c(3, 7)),
+#                                           list(name = "back_top", c(2, 6))))
+#
+# #Add some surfaces
+# input_add_gml_surfaces(my_ogs6_obj, list(list(name = "left", c(0, 1, 2), c(0, 3, 2)),
+#                                          list(name = "right", c(4, 6, 5), c(4, 6, 7)),
+#                                          list(name = "top", c(1, 2, 5), c(5, 2, 6)),
+#                                          list(name = "bottom", c(0, 3, 4), c(4, 3, 7)),
+#                                          list(name = "front", c(0, 1, 4), c(4, 1, 5)),
+#                                          list(name = "back", c(2, 3, 6), c(6, 3, 7))))
+
+
+#============================== ADD .vtu DATA ================================
+
+#(source: HydroComponent Benchmarks -> IdealGas -> flow_free_expansion -> cube_1x1x1.vtu)
+
+# #Add vtu object and give it a name
+# input_add_vtu_obj(my_ogs6_obj, list(type="UnstructuredGrid",
+#                              version="0.1",
+#                              byte_order="LittleEndian",
+#                              header_type="UInt32",
+#                              compressor="vtkZLibDataCompressor"))
+#
+# #Add an unstructured grid to the vtu object
+# input_add_vtu_unstructured_grid(my_ogs6_obj, list())
+#
+# #Add appended data to the vtu object
+# input_add_vtu_appended_data(my_ogs6_obj, encoding = "", data = "")
+#
+# #... (WIP)
+
+
+#============================== ADD .prj DATA ================================
+
+#There is no documentation for the constructors (yet), but with classes instead of just lists,
+#the user could get way more info (also, I can build some nice validator friends)
+
+
+#Define processes (refer to ?new_r2ogs6_process for info on valid arguments)
+# processes <- list(new_r2ogs_prj_process(name = "HM",
+#                                  type = "HYDRO_MECHANICS",
+#                                  integration_order = 3,
+#                                  dimension = 3,
+#                                  constitutive_relation = list(type = "LinearElasticIsotropic",
+#                                                               youngs_modulus = "E",
+#                                                               poissons_ratio = "nu"),
+#                                  process_variables = list(displacement = "displacement",
+#                                                           pressure = "pressure"),
+#                                  secondary_variables = list(stub = 0),
+#                                  specific_body_force = c(0, 0, 0))
+#                   )
+
+
+#Define media (refer to ?new_r2ogs6_prj_medium for info on valid arguments)
+media <- list(new_r2ogs6_prj_medium(phases = list(phase = list(type = "Gas",
+                                                       properties = list(property = list(name = "viscosity",
+                                                                                         type = "Constant",
+                                                                                         value = 1e-5)))
+                                                  ),
+                                    properties = list(property = list(name = "reference_temperature",
+                                                              type = "Constant",
+                                                              value = 293.15)
+                                                      )
+                            )
+              )
+
+
+time_loop <- list(processes = list(),
+                  output = list(type = "VTK",
+                                prefix = "",
+                                timesteps = list(),
+                                variables = list(),
+                                suffix = "_ts_{:timestep}_t_{:time}")
+                  )
+
+
+#Define parameters (refer to ?new_r2ogs6_parameter for info on valid arguments)
+parameters <- list(new_r2ogs6_prj_parameter(name = "E",
+                                    type = "Constant",
+                                    value = 10e9)
+                   )
+
+
+#Define process variables
+process_variables <- list(process_variable = list(name = "displacement",
+                                                  components = 3,
+                                                  order = 2,
+                                                  initial_condition = "displacement0",
+                                                  boundary_conditions = list(boundary_condition = list()))
+                          )
+
+
+#Define nonlinear solvers
+nonlinear_solvers <- list(nonlinear_solver = list(name = "basic_newton",
+                                                  type = "Newton",
+                                                  max_iter = 50,
+                                                  linear_solver = "general_linear_solver")
+                          )
+
+
+linear_solvers <- list(linear_solver = list(name = "general_linear_solver",
+                                            lis = "-i bicgstab -p ilu -tol 1e-16 -maxiter 10000",
+                                            eigen = list(solver_type = "BiCGSTAB",
+                                                         precon_type = "ILUT",
+                                                         max_iteration_step = 10000,
+                                                         error_tolerance = 1e-16))
+                       )
+
 
 
+#============================== Execution (to be moved to another file later!) ================================
+
+#============================== .gml ================================
+
+#Call ogs6 object validator functions
+#...
+
+# #Now export all necessary files
+# my_gml_xml <- gml_data_to_xml(geo_name, my_gml_points, my_gml_polylines, my_gml_surfaces)
+#
+#
+# #Let's export that as a new .gml XML file
+# export_xml_to_file(my_gml_xml, "test.gml")
 
+#Now the .gml XML file should be in the r2ogs6 folder (not a perfect location but ok for a little test)
 
-#============================== Execution ================================
+#The only thing missing from the new file compared to the original is the stylesheet declaration...
+#I haven't found a way to add that one yet, but it should also be possible somehow
 
-#Turn GML data into XML structure
-my_gml_xml <- gml_data_to_xml(geo_name, my_gml_points, my_gml_polylines, my_gml_surfaces)
 
+#============================== RUN SIMULATION ================================
 
-#Let's export that as a new .gml XML file
-export_xml_to_file(my_gml_xml, "my_experimental_cube.gml")
+#Calls ogs6 object validator functions, exports all necessary files and starts OpenGeoSys6
 
-#Now the .gml XML file should be in the r2ogs6 folder (not a perfect location but ok for a little test)
+#run_simulation(my_ogs6_obj)
 
-#The only thing missing from the new file compared to the original is the stylesheet declaration...
-#I haven't found a way to add that one yet, but it should also be possible somehow
\ No newline at end of file
diff --git a/R/utils.R b/R/utils.R
index de33ec35a9f10f0ecd4cafb29c407740304df284..bc95e153aebdc43378bb3473c4caf7b2cde1c64c 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -1,7 +1,3 @@
-
-default_xml_version <- "1.0"
-default_xml_encoding <- "ISO-8859-1"
-
 #============================== GENERAL UTILITY (copy playground) ================================
 
 ###Stub
@@ -23,51 +19,129 @@ default_xml_encoding <- "ISO-8859-1"
 #   )
 # )
 
-#============================== XML UTILITY FUNCTIONS ================================
 
-#' Reads the encoding of an XML file
-#'
-#' @param input_file_name An XML (.xml or, in the case of OpenGeoSys, .prj) file
-#' @return The encoding of the input file
+#============================== VALIDATION UTILITY ================================
+
+#'check_for_obj_of_name
+#'@description Checks if a object with the given name was already defined for a ogs6 object and if not,
+#' tells user to initialize one
+#'@param ogs6_obj The ogs6 object to check
+#'@param obj_name The name of the object to check for
+check_for_obj_of_name <- function(ogs6_obj, obj_name) {
+
+  if(!obj_name %in% names(ogs6_obj$sim_input)){
+    stop(paste("There is no object named ", obj_name," for your ogs6 object yet.\n
+               You can initialize one by calling input_add_", obj_name ,
+               "() (read up on the required parameters)"),
+         call. = FALSE)
+    }
+}
+
+
+#============================== XML UTILITY ================================
+
+
+#' export_xml_to_file
+#' @description Export function
+#' @param xml_data The data to be exported (already in XML friendly format)
+#' @param file_name The name of the file to be written
 # @examples
-# input_file_encoding <- get_xml_encoding("file.xml")
-# input_file_encoding <- get_xml_encoding("file.prj")
-get_xml_encoding <- function(input_file_name) {
-  input_file <- file(input_file_name, "r")
-  first_line <- readLines(input_file, n=1)
-  close(input_file)
-  decl <- stringr::str_split(first_line, '"', simplify = TRUE)
+# export_xml_to_file(...)
+export_xml_to_file <- function(xml_data, file_name) {
+  doc <- xml2::as_xml_document(xml_data)
+  xml2::write_xml(doc, file_name, options = "format", encoding="ISO-8859-1")
+  invisible()
+}
 
-  xml_encoding <- default_xml_encoding
 
-  if(length(decl) == 5 && decl[1] == "<?xml version=" && decl[3] == " encoding=" && decl[5]=="?>"){
-    xml_encoding <- decl[4]
-    cat(paste("Valid XML declaration in first line of input file found.\nDetected encoding ", xml_encoding))
+#' adopt_nodes
+#' @description A helper function for creating parent nodes using the generic function as_node
+#' @param parent_name The name of the new parent node
+#' @param objs A list of class objects (class must have method for generic function as_node)
+adopt_nodes <- function(parent_name, objs) {
+  parent_node <- list(parent_name = list())
 
-  }else{
-    cat("XML declaration not as expected. Example for valid declaration:\n")
-    cat('<?xml version="1.0" encoding="UTF-8"?>\n')
-    cat(paste("I will use my default value of XML encoding ",  default_xml_encoding, ".\n"))
+  for(i in 1:length(objs)) {
+    parent_node <- c(parent_node[[1]], as_node(objs[[i]]))
+  }
 
+  return(xml2::as_xml_document(parent_node))
+}
+
+#'add_opt_attr
+#'@description Adds an optional attribute to a node attribute list
+#'@param node The node the optional attribute should be added to
+#'@param obj_parameter The value of the attribute to be added
+#'@param attr_name The name of the attribute to be added
+add_opt_attr <- function(node, obj_parameter, attr_name) {
+  if(!is.null(obj_parameter)) {
+    attributes(node[[1]])[[attr_name]] <- obj_parameter
   }
-  return(xml_encoding)
+
+  return(node)
 }
 
 
-#' Creates a template project file based on the XML structure and attributes of an existing project file.
-#' @param existing_prj An existing .prj file to use as a template for the structure and attributes
-#' @param template_prj The path where the template should be saved
-#' @return The newly created template project file
-# @examples
-# blank_prj_file <- create_template_prj("file.prj")
-create_template_prj <- function(existing_prj, template_prj) {
-  xml_input <- xml2::read_xml(existing_prj)
+#'add_opt_child
+#'@description Adds an optional child to a node child list
+#'@param node The node the optional child should be added to
+#'@param obj_parameter The value of the child to be added
+#'@param child_name Optional: If it's a child node instead of just a value, the name of the child to be added
+add_opt_child <- function(node, obj_parameter, child_name = NULL) {
+
+  if(!is.null(obj_parameter)) {
+    if(!is.null(child_name) && length(node[[1]]) == length(names(node[[1]]))) {
+      node[[1]] <- c(node[[1]], list(child_name = obj_parameter))
+    }else if(length(node[[1]]) == 0) {
+      node[[1]] <- list(obj_parameter)
+    }else{
+      stop(paste("You're trying to add a value (an unnamed child node) to a node
+                 which already has a value."), call. = FALSE)
+    }
 
-  #Empty text nodes
-  text_nodes<-xml2::xml_find_all(xml_input, "//text()")
-  xml2::xml_set_text(text_nodes, "")
+  }
 
-  xml2::write_xml(xml_input, template_prj, options = "format", encoding=get_xml_encoding(existing_prj))
+  return(node)
 }
 
 
+
+
+#================================Test if S3 object in R6 class inherits reference semantics
+
+# A <- R6::R6Class("A",
+#   public = list(
+#
+#       b_obj = NULL,
+#
+#       initialize = function(b_obj) {
+#           self$b_obj <- b_obj
+#         }
+#   )
+# )
+#
+# b <- function(x){
+#     structure(x,
+#               class = "b")
+# }
+#
+# mod_func_a <- function(a_obj){
+#     a_obj$b_obj$x <- 100
+# }
+#
+# a_obj <- A$new(b(42))
+#
+# mod_func_a(a_obj)
+#
+# a_obj$b_obj$x
+#
+#
+# mod_func_b <- function(b_obj){
+#     b_obj$x <- 100
+# }
+#
+# b_obj <- b(42)
+#
+# mod_func_b(b_obj)
+#
+# b_obj
diff --git a/R/validate_gml.R b/R/validate_gml.R
index 33111c96de89496e2c392d797630d05b15287137..beff91f04adb03fbbe0f5d8ba641f52c73903eb4 100644
--- a/R/validate_gml.R
+++ b/R/validate_gml.R
@@ -1,17 +1,41 @@
 #This script contains various functions to verify data for a .gml file (WIP)
 
-# @export
-validate_gml_data <- function(gml_geometry_name, gml_points = NA, gml_polylines = NA, gml_surfaces = NA) {
+#' validate_gml_data
+#'
+#' @name validate_gml_data
+#' @description Checks if the defined gml class object isn't empty
+#' @param gml_obj A gml class object
+validate_gml_data <- function(gml_obj) {
 
-    validate_points(gml_points)
-    validate_polylines(gml_polylines)
-    validate_surfaces(gml_surfaces)
+    null_count <- 0
+
+    if(is.null(gml_obj$points)){
+        null_count <- null_count + 1
+    }
+
+    if(is.null(gml_obj$polylines)){
+        null_count <- null_count + 1
+    }
+
+    if(is.null(gml_obj$surfaces)){
+        null_count <- null_count + 1
+    }
+
+    if(null_count == 3){
+        stop(paste("Defined .gml object only has a name. Consider adding some points,
+                    polylines and surfaces."), call. = FALSE)
+    }
+
+    #More extensive checks... (WIP)
 }
 
-#'Checks if the input is a tibble, if this tibble has the right number of elements,
-#' if those elements are named correctly, if the lists in the tibble are of the same length and
-#' if there is any overlapping points or duplicate point names
-#' @param gml_points A tibble with 3 vectors named 'x', 'y' and 'z' (and an optional 'name' vector)
+
+#'validate_points
+#'
+#'@name validate_points
+#'@description Checks if the input is a tibble, if this tibble has the right number of elements,
+#' if those elements are named correctly and if there are any overlapping points or duplicate point names
+#'@param gml_points A tibble with 3 vectors named 'x', 'y' and 'z' (and an optional 'name' vector)
 validate_points <- function(gml_points) {
 
     if(!(inherits(gml_points, "tbl_df") && inherits(gml_points, "tbl") &&
@@ -28,6 +52,10 @@ validate_points <- function(gml_points) {
         stop(paste(gml_points, " column names do not fit to 'x, y, z, (name)' "), call. = FALSE)
     }
 
+    if(!is.numeric(gml_points$x) || !is.numeric(gml_points$y) || !is.numeric(gml_points$z)){
+        stop(paste(gml_points, "'x, y, z' columns must be numeric vectors"), call. = FALSE)
+    }
+
     has_names <- (length(gml_points) == 4)
 
     #Find overlapping points and duplicate names
@@ -51,16 +79,123 @@ validate_points <- function(gml_points) {
     return(invisible(gml_points))
 }
 
-
+#'validate_polylines
+#'
+#'@name validate_polylines
+#'@description Checks if the input is a list, if this list consists of other lists and
+#' if those child lists have the correct structure (length of 2, first element is a string named
+#' 'name', second element is a numeric vector)
+#'@param gml_polylines A list consisting of other lists
 validate_polylines <- function(gml_polylines) {
 
-    if(!(inherits(gml_polylines, "list"))){
-        stop(paste(gml_polylines, " is not of class 'list' "), call. = FALSE)
+    if(!(inherits(gml_polylines, "list"))) {
+        stop(paste("gml_polylines object is not of class 'list' "), call. = FALSE)
     }
 
-}
+    for(i in 1:length(gml_polylines)){
+        if(!(inherits(gml_polylines[[i]], "list"))) {
+            stop(paste("At least one element of gml_polylines is not of class 'list' "), call. = FALSE)
+        }
+
+        if(length(gml_polylines[[i]]) != 2) {
+            stop(paste("At least one element of gml_polylines has incorrect length
+                       (expected list of length 2)"), call. = FALSE)
+        }
 
+        if(names(gml_polylines[[i]])[[1]] != "name" || !is.character(gml_polylines[[i]][[1]])) {
+            stop(paste("First element of gml_polylines (list) element must be
+                       a character string named 'name' "), call. = FALSE)
+        }
+
+        if(!is.numeric(gml_polylines[[i]][[2]])) {
+            stop(paste("Second element of gml_polylines (list) element must be
+                       a numeric vector"), call. = FALSE)
+        }
 
+        #Check for duplicate points / polylines?
+    }
+
+    return(invisible(gml_polylines))
+}
+
+#'validate_surfaces
+#'
+#'@name validate_surfaces
+#'@description Checks if the input is a list, if this list consists of other lists and
+#' if those child lists have the correct structure (length of 3, first element is a string named
+#' 'name', second and third element are numeric vectors)
+#'@param gml_surfaces A list consisting of other lists
 validate_surfaces <- function(gml_surfaces) {
 
+    if(!(inherits(gml_surfaces, "list"))) {
+        stop(paste("gml_surfaces object is not of class 'list'"), call. = FALSE)
+    }
+
+    for(i in 1:length(gml_surfaces)){
+        if(!(inherits(gml_surfaces[[i]], "list"))) {
+            stop(paste("At least one element of gml_surfaces is not of class 'list'"), call. = FALSE)
+        }
+
+        if(length(gml_surfaces[[i]]) != 3) {
+            stop(paste("At least one element of gml_surfaces has incorrect length
+                       (expected list of length 3)"), call. = FALSE)
+        }
+
+        if(names(gml_surfaces[[i]])[[1]] != "name" || !is.character(gml_surfaces[[i]][[1]])) {
+            stop(paste("First element of gml_surfaces (list) element must be
+                       a character string named 'name'"), call. = FALSE)
+        }
+
+        if(!is.numeric(gml_surfaces[[i]][[2]]) || !is.numeric(gml_surfaces[[i]][[3]]) ||
+           length(gml_surfaces[[i]][[2]]) != 3 || length(gml_surfaces[[i]][[3]]) != 3) {
+            stop(paste("Second and third element of gml_surfaces (list) element must be
+                       a numeric vector of length 3"), call. = FALSE)
+        }
+
+
+        validate_surface_elements(gml_surfaces[[i]][[2]], gml_surfaces[[i]][[3]])
+
+
+        #Check for duplicate points / surfaces?
+    }
+
+    return(invisible(gml_surfaces))
+
+}
+
+
+#'validate_surface_elements
+#'
+#'@name validate_surface_elements
+#'@description Helper function, checks if two numerical vectors of length 3 (two surface elements)
+#' each consist of 3 different elements and also have exactly 2 matching elements between them
+#' which means they describe a valid surface. You can think of the two vectors as two triangles,
+#' and the two triangles together form a square which is our surface.
+#'@param gml_surface_element_1 A numerical vector of length 3
+#'@param gml_surface_element_2 A numerical vector of length 3
+validate_surface_elements = function (gml_surface_element_1, gml_surface_element_2) {
+
+    if(gml_surface_element_1[[1]] == gml_surface_element_1[[2]] ||
+       gml_surface_element_1[[1]] == gml_surface_element_1[[3]] ||
+       gml_surface_element_1[[2]] == gml_surface_element_1[[3]] ||
+       gml_surface_element_2[[1]] == gml_surface_element_2[[2]] ||
+       gml_surface_element_2[[1]] == gml_surface_element_2[[3]] ||
+       gml_surface_element_2[[2]] == gml_surface_element_2[[3]]) {
+        stop("A surface element must consist of 3 different points", call. = FALSE)
+    }
+
+    equal_count <- 0
+
+    for(i in 1:length(gml_surface_element_1)) {
+        for(j in 1:length(gml_surface_element_2)) {
+            if(gml_surface_element_1[[i]] == gml_surface_element_2[[j]]) {
+                equal_count <- equal_count + 1
+                break
+            }
+        }
+    }
+
+    if(equal_count != 2) {
+        stop("Invalid surface detected", call. = FALSE)
+    }
 }
\ No newline at end of file
diff --git a/inst/extdata/flow_free_expansion/HM_flow_free_expansion.pdf b/inst/extdata/flow_free_expansion/HM_flow_free_expansion.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..68cf031c6feb9ff176dab619151fc482c260ac9f
Binary files /dev/null and b/inst/extdata/flow_free_expansion/HM_flow_free_expansion.pdf differ
diff --git a/inst/extdata/flow_free_expansion/cube_1x1x1.gml b/inst/extdata/flow_free_expansion/cube_1x1x1.gml
new file mode 100644
index 0000000000000000000000000000000000000000..30798907a4ff4deadfa89d9700b19cf6be741ad2
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/cube_1x1x1.gml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml-stylesheet type="text/xsl" href="OpenGeoSysGLI.xsl"?>
+
+<OpenGeoSysGLI xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogs="http://www.opengeosys.org">
+    <name>cube_1x1x1_geometry</name>
+    <points>
+        <point id="0" x="0" y="0" z="0" name="origin"/>
+        <point id="1" x="0" y="0" z="1"/>
+        <point id="2" x="0" y="1" z="1"/>
+        <point id="3" x="0" y="1" z="0"/>
+
+        <point id="4" x="1" y="0" z="0"/>
+        <point id="5" x="1" y="0" z="1"/>
+        <point id="6" x="1" y="1" z="1"/>
+        <point id="7" x="1" y="1" z="0"/>
+    </points>
+
+    <polylines>
+        <polyline id="0" name="front_left">
+            <pnt>0</pnt>
+            <pnt>1</pnt>
+        </polyline>
+        <polyline id="1" name="front_right">
+            <pnt>4</pnt>
+            <pnt>5</pnt>
+        </polyline>
+        <polyline id="2" name="front_bottom">
+            <pnt>0</pnt>
+            <pnt>4</pnt>
+        </polyline>
+        <polyline id="3" name="front_top">
+            <pnt>1</pnt>
+            <pnt>5</pnt>
+        </polyline>
+        <polyline id="4" name="bottom_left">
+            <pnt>0</pnt>
+            <pnt>3</pnt>
+        </polyline>
+        <polyline id="5" name="bottom_right">
+            <pnt>4</pnt>
+            <pnt>7</pnt>
+        </polyline>
+        <polyline id="6" name="top_left">
+            <pnt>1</pnt>
+            <pnt>2</pnt>
+        </polyline>
+        <polyline id="7" name="top_right">
+            <pnt>5</pnt>
+            <pnt>6</pnt>
+        </polyline>
+        <polyline id="8" name="back_left">
+            <pnt>2</pnt>
+            <pnt>3</pnt>
+        </polyline>
+        <polyline id="9" name="back_right">
+            <pnt>6</pnt>
+            <pnt>7</pnt>
+        </polyline>
+        <polyline id="10" name="back_bottom">
+            <pnt>3</pnt>
+            <pnt>7</pnt>
+        </polyline>
+        <polyline id="11" name="back_top">
+            <pnt>2</pnt>
+            <pnt>6</pnt>
+        </polyline>
+    </polylines>
+
+    <surfaces>
+        <surface id="0" name="left"><!-- x=0 -->
+            <element p1="0" p2="1" p3="2"/>
+            <element p1="0" p2="3" p3="2"/>
+        </surface>
+        <surface id="1" name="right"><!-- x=1 -->
+            <element p1="4" p2="6" p3="5"/>
+            <element p1="4" p2="6" p3="7"/>
+        </surface>
+        <surface id="2" name="top"><!-- z=1 -->
+            <element p1="1" p2="2" p3="5"/>
+            <element p1="5" p2="2" p3="6"/>
+        </surface>
+        <surface id="3" name="bottom"><!-- z=0 -->
+            <element p1="0" p2="3" p3="4"/>
+            <element p1="4" p2="3" p3="7"/>
+        </surface>
+        <surface id="4" name="front"><!-- y=0 -->
+            <element p1="0" p2="1" p3="4"/>
+            <element p1="4" p2="1" p3="5"/>
+        </surface>
+        <surface id="5" name="back"><!-- y=1 -->
+            <element p1="2" p2="3" p3="6"/>
+            <element p1="6" p2="3" p3="7"/>
+        </surface>
+    </surfaces>
+</OpenGeoSysGLI>
diff --git a/inst/extdata/flow_free_expansion/cube_1x1x1.vtu b/inst/extdata/flow_free_expansion/cube_1x1x1.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..55950288636a9b5e53a178171c3bef91b92024f1
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/cube_1x1x1.vtu
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian" header_type="UInt32">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="8"                    NumberOfCells="1"                   >
+      <PointData>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="1.7320508076"         offset="0"                   />
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin=""                     RangeMax=""                     offset="264"                 />
+        <DataArray type="Int64" Name="offsets" format="appended" RangeMin=""                     RangeMax=""                     offset="356"                 />
+        <DataArray type="UInt8" Name="types" format="appended" RangeMin=""                     RangeMax=""                     offset="372"                 />
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+  <AppendedData encoding="base64">
+   _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPw==QAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAFAAAAAAAAAAcAAAAAAAAABgAAAAAAAAA=CAAAAAgAAAAAAAAAAQAAAAw=
+  </AppendedData>
+</VTKFile>
diff --git a/inst/extdata/flow_free_expansion/cube_1x1x1_quad.vtu b/inst/extdata/flow_free_expansion/cube_1x1x1_quad.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..cfbcf9127aabe8e535d6a7765c9de04abd9782fb
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/cube_1x1x1_quad.vtu
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian" header_type="UInt32">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="20"                   NumberOfCells="1"                   >
+      <PointData>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="1.7320508076"         offset="0"                   />
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin=""                     RangeMax=""                     offset="648"                 />
+        <DataArray type="Int64" Name="offsets" format="appended" RangeMin=""                     RangeMax=""                     offset="868"                 />
+        <DataArray type="UInt8" Name="types" format="appended" RangeMin=""                     RangeMax=""                     offset="884"                 />
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+  <AppendedData encoding="base64">
+   _4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAAAAAAAAAAAADgPwAAAAAAAAAAAAAAAAAA4D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADgPwAAAAAAAOA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAOA/AAAAAAAA8D8AAAAAAAAAAAAAAAAAAOA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAADgPwAAAAAAAPA/AAAAAAAA4D8AAAAAAAAAAAAAAAAAAPA/AAAAAAAA4D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADgPw==oAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAFAAAAAAAAAAcAAAAAAAAABgAAAAAAAAAMAAAAAAAAABEAAAAAAAAADgAAAAAAAAAJAAAAAAAAAA0AAAAAAAAAEgAAAAAAAAAPAAAAAAAAAAoAAAAAAAAACAAAAAAAAAAQAAAAAAAAABMAAAAAAAAACwAAAAAAAAA=CAAAABQAAAAAAAAAAQAAABk=
+  </AppendedData>
+</VTKFile>
diff --git a/inst/extdata/flow_free_expansion/flow_free_expansion.prj b/inst/extdata/flow_free_expansion/flow_free_expansion.prj
new file mode 100644
index 0000000000000000000000000000000000000000..291ec5cce836f341e0247f33d3aebbc5b274269d
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/flow_free_expansion.prj
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<OpenGeoSysProject>
+    <mesh>cube_1x1x1_quad.vtu</mesh>
+    <geometry>cube_1x1x1.gml</geometry>
+    <processes>
+        <process>
+            <name>HM</name>
+            <type>HYDRO_MECHANICS</type>
+            <integration_order>3</integration_order>
+            <dimension>3</dimension>
+            <constitutive_relation>
+                <type>LinearElasticIsotropic</type>
+                <youngs_modulus>E</youngs_modulus>
+                <poissons_ratio>nu</poissons_ratio>
+            </constitutive_relation>
+            <process_variables>
+                <displacement>displacement</displacement>
+                <pressure>pressure</pressure>
+            </process_variables>
+            <secondary_variables>
+                <secondary_variable internal_name="sigma_xx" output_name="sigma_xx"/>
+                <secondary_variable internal_name="sigma_yy" output_name="sigma_yy"/>
+                <secondary_variable internal_name="sigma_zz" output_name="sigma_zz"/>
+                <secondary_variable internal_name="sigma_xy" output_name="sigma_xy"/>
+                <secondary_variable internal_name="epsilon_xx" output_name="epsilon_xx"/>
+                <secondary_variable internal_name="epsilon_yy" output_name="epsilon_yy"/>
+                <secondary_variable internal_name="epsilon_zz" output_name="epsilon_zz"/>
+                <secondary_variable internal_name="epsilon_xy" output_name="epsilon_xy"/>
+                <secondary_variable internal_name="velocity" output_name="velocity"/>
+            </secondary_variables>
+            <specific_body_force>0 0 0</specific_body_force>
+        </process>
+    </processes>
+    <media>
+        <medium>
+            <phases>
+                <phase>
+                    <type>Gas</type>
+                    <properties>
+                        <property>
+                            <name>viscosity</name>
+                            <type>Constant</type>
+                            <value>1e-5</value>
+                        </property>
+                        <property>
+                            <name>density</name>
+                            <type>IdealGasLaw</type>
+                        </property>
+                        <property>
+                            <name>molar_mass</name>
+                            <type>Constant</type>
+                            <value>0.028964397787206768</value>
+                        </property>
+                    </properties>
+                </phase>
+                <phase>
+                    <type>Solid</type>
+                    <properties>
+                        <property>
+                            <name>porosity</name>
+                            <type>Constant</type>
+                            <value>0.3</value>
+                        </property>
+                        <property>
+                            <name>density</name>
+                            <type>Constant</type>
+                            <value>1.43e3</value>
+                        </property>
+                        <property>
+                            <name>biot_coefficient</name>
+                            <type>Constant</type>
+                            <value>0.6</value>
+                        </property>
+                    </properties>
+                </phase>
+            </phases>
+            <properties>
+                <property>
+                    <name>reference_temperature</name>
+                    <type>Constant</type>
+                    <value>293.15</value>
+                </property>
+                <property>
+                    <name>permeability</name>
+                    <type>Constant</type>
+                    <value>1e-5</value>
+                </property>
+            </properties>
+        </medium>
+    </media>
+    <time_loop>
+        <processes>
+            <process ref="HM">
+                <nonlinear_solver>basic_newton</nonlinear_solver>
+                <convergence_criterion>
+                    <type>DeltaX</type>
+                    <norm_type>NORM2</norm_type>
+                    <reltol>1e-8</reltol>
+                </convergence_criterion>
+                <time_discretization>
+                    <type>BackwardEuler</type>
+                </time_discretization>
+                <time_stepping>
+                    <type>FixedTimeStepping</type>
+                    <t_initial>0</t_initial>
+                    <t_end>10000</t_end>
+                    <timesteps>
+                        <pair>
+                            <repeat>1000</repeat>
+                            <delta_t>10</delta_t>
+                        </pair>
+                    </timesteps>
+                </time_stepping>
+            </process>
+        </processes>
+        <output>
+            <type>VTK</type>
+            <prefix>flow_free_expansion_pcs_{:process_id}</prefix>
+            <timesteps>
+                <pair>
+                    <repeat>1</repeat>
+                    <each_steps>1000</each_steps>
+                </pair>
+            </timesteps>
+            <variables>
+                <variable>displacement</variable>
+                <variable>pressure</variable>
+                <variable>sigma_xx</variable>
+                <variable>sigma_yy</variable>
+                <variable>sigma_zz</variable>
+                <variable>sigma_xy</variable>
+                <variable>epsilon_xx</variable>
+                <variable>epsilon_yy</variable>
+                <variable>epsilon_zz</variable>
+                <variable>epsilon_xy</variable>
+                <variable>velocity</variable>
+            </variables>
+            <suffix>_ts_{:timestep}_t_{:time}</suffix>
+        </output>
+    </time_loop>
+    <parameters>
+        <!-- Mechanics -->
+        <parameter>
+            <name>E</name>
+            <type>Constant</type>
+            <value>10e9</value>
+        </parameter>
+        <parameter>
+            <name>nu</name>
+            <type>Constant</type>
+            <value>.3</value>
+        </parameter>
+        <!-- Model parameters -->
+        <parameter>
+            <name>displacement0</name>
+            <type>Constant</type>
+            <values>0 0 0</values>
+        </parameter>
+        <parameter>
+            <name>pressure0</name>
+            <type>Constant</type>
+            <values>1e5</values>
+        </parameter>
+        <!-- pressure-load = -alpha_b * p0 -->
+        <parameter>
+            <name>pressure_load</name>
+            <type>Constant</type>
+            <values>-0.6e5</values>
+        </parameter>
+        <parameter>
+            <name>zero</name>
+            <type>Constant</type>
+            <value>0</value>
+        </parameter>
+        <parameter>
+            <name>flux_in</name>
+            <type>Constant</type>
+            <value>1e-4</value>
+        </parameter>
+    </parameters>
+    <process_variables>
+        <process_variable>
+            <name>displacement</name>
+            <components>3</components>
+            <order>2</order>
+            <initial_condition>displacement0</initial_condition>
+            <boundary_conditions>
+                <boundary_condition>
+                    <geometrical_set>cube_1x1x1_geometry</geometrical_set>
+                    <geometry>front</geometry>
+                    <type>Dirichlet</type>
+                    <component>1</component>
+                    <parameter>zero</parameter>
+                </boundary_condition>
+                <boundary_condition>
+                    <geometrical_set>cube_1x1x1_geometry</geometrical_set>
+                    <geometry>left</geometry>
+                    <type>Dirichlet</type>
+                    <component>0</component>
+                    <parameter>zero</parameter>
+                </boundary_condition>
+                <boundary_condition>
+                    <geometrical_set>cube_1x1x1_geometry</geometrical_set>
+                    <geometry>bottom</geometry>
+                    <type>Dirichlet</type>
+                    <component>2</component>
+                    <parameter>zero</parameter>
+                </boundary_condition>
+                <boundary_condition>
+                    <geometrical_set>cube_1x1x1_geometry</geometrical_set>
+                    <geometry>back</geometry>
+                    <type>Neumann</type>
+                    <component>1</component>
+                    <parameter>pressure_load</parameter>
+                </boundary_condition>
+                <boundary_condition>
+                    <geometrical_set>cube_1x1x1_geometry</geometrical_set>
+                    <geometry>right</geometry>
+                    <type>Neumann</type>
+                    <component>0</component>
+                    <parameter>pressure_load</parameter>
+                </boundary_condition>
+                <boundary_condition>
+                    <geometrical_set>cube_1x1x1_geometry</geometrical_set>
+                    <geometry>top</geometry>
+                    <type>Neumann</type>
+                    <component>2</component>
+                    <parameter>pressure_load</parameter>
+                </boundary_condition>
+            </boundary_conditions>
+        </process_variable>
+        <process_variable>
+            <name>pressure</name>
+            <components>1</components>
+            <order>1</order>
+            <initial_condition>pressure0</initial_condition>
+            <boundary_conditions>
+                <boundary_condition>
+                    <geometrical_set>cube_1x1x1_geometry</geometrical_set>
+                    <geometry>left</geometry>
+                    <type>Neumann</type>
+                    <component>0</component>
+                    <parameter>flux_in</parameter>
+                </boundary_condition>
+            </boundary_conditions>
+        </process_variable>
+    </process_variables>
+    <nonlinear_solvers>
+        <nonlinear_solver>
+            <name>basic_newton</name>
+            <type>Newton</type>
+            <max_iter>50</max_iter>
+            <linear_solver>general_linear_solver</linear_solver>
+        </nonlinear_solver>
+    </nonlinear_solvers>
+    <linear_solvers>
+        <linear_solver>
+            <name>general_linear_solver</name>
+            <lis>-i bicgstab -p ilu -tol 1e-16 -maxiter 10000</lis>
+            <eigen>
+                <solver_type>BiCGSTAB</solver_type>
+                <precon_type>ILUT</precon_type>
+                <max_iteration_step>10000</max_iteration_step>
+                <error_tolerance>1e-16</error_tolerance>
+            </eigen>
+        </linear_solver>
+    </linear_solvers>
+</OpenGeoSysProject>
diff --git a/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0.pvd b/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0.pvd
new file mode 100644
index 0000000000000000000000000000000000000000..3977b2f9af840386de2302d59a0d90f39a2a7a93
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0.pvd
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<VTKFile type="Collection" version="0.1" byte_order="LittleEndian" compressor="vtkZLibDataCompressor">
+  <Collection>
+    <DataSet timestep="0" group="" part="0" file="flow_free_expansion_pcs_0_ts_0_t_0.000000.vtu"/>
+    <DataSet timestep="10000" group="" part="0" file="flow_free_expansion_pcs_0_ts_1000_t_10000.000000.vtu"/>
+  </Collection>
+</VTKFile>
diff --git a/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0_ts_0_t_0.000000.vtu b/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0_ts_0_t_0.000000.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..2b88d139ae0ed40790ac66502c906b6a4389510d
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0_ts_0_t_0.000000.vtu
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64" compressor="vtkZLibDataCompressor">
+  <UnstructuredGrid>
+    <FieldData>
+      <DataArray type="Int8" Name="IntegrationPointMetaData" NumberOfTuples="166" format="appended" RangeMin="34"                   RangeMax="125"                  offset="0"                   />
+      <DataArray type="Int8" Name="OGS_VERSION" NumberOfTuples="20" format="appended" RangeMin="45"                   RangeMax="103"                  offset="176"                 />
+      <DataArray type="Float64" Name="epsilon_ip" NumberOfComponents="6" NumberOfTuples="27" format="appended" RangeMin="0"                    RangeMax="0"                    offset="260"                 />
+      <DataArray type="Float64" Name="sigma_ip" NumberOfComponents="6" NumberOfTuples="27" format="appended" RangeMin="0"                    RangeMax="0"                    offset="332"                 />
+    </FieldData>
+    <Piece NumberOfPoints="20"                   NumberOfCells="1"                   >
+      <PointData>
+        <DataArray type="Float64" Name="HydraulicFlow" format="appended" RangeMin="0"                    RangeMax="0"                    offset="404"                 />
+        <DataArray type="Float64" Name="NodalForces" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="0"                    offset="464"                 />
+        <DataArray type="Float64" Name="displacement" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="0"                    offset="528"                 />
+        <DataArray type="Float64" Name="epsilon_xx" format="appended" RangeMin="0"                    RangeMax="0"                    offset="592"                 />
+        <DataArray type="Float64" Name="epsilon_xy" format="appended" RangeMin="0"                    RangeMax="0"                    offset="652"                 />
+        <DataArray type="Float64" Name="epsilon_yy" format="appended" RangeMin="0"                    RangeMax="0"                    offset="712"                 />
+        <DataArray type="Float64" Name="epsilon_zz" format="appended" RangeMin="0"                    RangeMax="0"                    offset="772"                 />
+        <DataArray type="Float64" Name="pressure" format="appended" RangeMin="0"                    RangeMax="100000"               offset="832"                 />
+        <DataArray type="Float64" Name="pressure_interpolated" format="appended" RangeMin="100000"               RangeMax="100000"               offset="904"                 />
+        <DataArray type="Float64" Name="sigma_xx" format="appended" RangeMin="0"                    RangeMax="0"                    offset="972"                 />
+        <DataArray type="Float64" Name="sigma_xy" format="appended" RangeMin="0"                    RangeMax="0"                    offset="1032"                />
+        <DataArray type="Float64" Name="sigma_yy" format="appended" RangeMin="0"                    RangeMax="0"                    offset="1092"                />
+        <DataArray type="Float64" Name="sigma_zz" format="appended" RangeMin="0"                    RangeMax="0"                    offset="1152"                />
+        <DataArray type="Float64" Name="velocity" NumberOfComponents="3" format="appended" RangeMin="1.0362684928e-12"     RangeMax="4.203568835e-11"      offset="1212"                />
+      </PointData>
+      <CellData>
+        <DataArray type="Float64" Name="permeability" NumberOfComponents="6" format="appended" RangeMin="1.7320508076e-05"     RangeMax="1.7320508076e-05"     offset="1644"                />
+        <DataArray type="Float64" Name="principal_stress_values" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="0"                    offset="1720"                />
+        <DataArray type="Float64" Name="principal_stress_vector_1" NumberOfComponents="3" format="appended" RangeMin="1"                    RangeMax="1"                    offset="1780"                />
+        <DataArray type="Float64" Name="principal_stress_vector_2" NumberOfComponents="3" format="appended" RangeMin="1"                    RangeMax="1"                    offset="1848"                />
+        <DataArray type="Float64" Name="principal_stress_vector_3" NumberOfComponents="3" format="appended" RangeMin="1"                    RangeMax="1"                    offset="1912"                />
+      </CellData>
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="1.7320508076"         offset="1976"                />
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin=""                     RangeMax=""                     offset="2104"                />
+        <DataArray type="Int64" Name="offsets" format="appended" RangeMin=""                     RangeMax=""                     offset="2212"                />
+        <DataArray type="UInt8" Name="types" format="appended" RangeMin=""                     RangeMax=""                     offset="2272"                />
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+  <AppendedData encoding="base64">
+   _AQAAAAAAAAAAgAAAAAAAAKYAAAAAAAAAYwAAAAAAAAA=eF6FzDEKgDAMheG7ZO7k4NCriISoUQI2KWkdRLy7XV10fO+H7wLRyptTFVPM1haSO50F4nC9ovnCDrELoJQYIhTZEqFkaM+RJna0FWdL2ZS1NqC/ww/Bucjewicy3g8l5D0kAQAAAAAAAAAAgAAAAAAAABQAAAAAAAAAHAAAAAAAAAA=eF4z0zPWM9I1NjPVTU9Os0xOMTOySAEAMNgFJA==AQAAAAAAAAAAgAAAAAAAABAFAAAAAAAAEwAAAAAAAAA=eF5jYBgFo2AUjIJRAAIABRAAAQ==AQAAAAAAAAAAgAAAAAAAABAFAAAAAAAAEwAAAAAAAAA=eF5jYBgFo2AUjIJRAAIABRAAAQ==AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAOABAAAAAAAADgAAAAAAAAA=eF5jYBgFwxkAAAHgAAE=AQAAAAAAAAAAgAAAAAAAAOABAAAAAAAADgAAAAAAAAA=eF5jYBgFwxkAAAHgAAE=AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAEwAAAAAAAAA=eF5jYACCrB8ODJTQNAQAcCoNEQ==AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAEgAAAAAAAAA=eF5jYACCrB8ODIOUBgD3nyCpAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAADAAAAAAAAAA=eF5jYBjcAAAAoAABAQAAAAAAAAAAgAAAAAAAAOABAAAAAAAAIQEAAAAAAAA=eF5jYICAhfM/zzhVE7E3Ilt2n03Rlr1QYQYOvvZzDJ3dey3rL817dHQXXDwUqp6jgTH5tPRxW5g4F0y9mJirY+IcuLiN3Ooj7bND9p65NWvZ0lyE+W0rVsg1b2/f+8Ji4srzrTvh4iug6rliDA7yciHMnwRVfzFcYfHcYoT59s066uu2Ru2VUY4x+piPML8E6s4ZXs9M3mkXwtV7QM1/U3mHdfqTIrh4GtQcoXcSk94IIewNCAUB1b2958rfLI5fCxe/EQIRD5oyjW3nNIR4AlT97S9fddnLtsLdwwBV/2XiswU1UQjxf0fyJ8z/175X8Y6hyk1VRDizQsPzeoGLfO7ihXDzW6HhsMYs2bLpFkL8B9QcFXPpkvysObYAxDKfSA==AQAAAAAAAAAAgAAAAAAAADAAAAAAAAAAFgAAAAAAAAA=eF77lPG4Y+uPJ3af0GgGHAAAZjoQvQ==AQAAAAAAAAAAgAAAAAAAABgAAAAAAAAACwAAAAAAAAA=eF5jYMAOAAAYAAE=AQAAAAAAAAAAgAAAAAAAABgAAAAAAAAAEAAAAAAAAAA=eF5jYACBD/YMaAAAFScBMA==AQAAAAAAAAAAgAAAAAAAABgAAAAAAAAADwAAAAAAAAA=eF5jYEAGH+xhLAALrwEwAQAAAAAAAAAAgAAAAAAAABgAAAAAAAAADgAAAAAAAAA=eF5jYMAGPtgDAAI3ATA=AQAAAAAAAAAAgAAAAAAAAOABAAAAAAAAPwAAAAAAAAA=eF5jYMAHPtjjlcaQh/GJ1YdLPy51uGh08ABNHJ2PLo7L3gdoNDpAF0fXh24uujguf6CrI9YedPqBPQBopCndAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAMAAAAAAAAAA=eF4txUkCgBAAAECpiKLt/391MHOZEKbFq6M3785Ovvy6u7j58+3qw49/nx4uqAC/AQAAAAAAAAAAgAAAAAAAAAgAAAAAAAAACwAAAAAAAAA=eF4TYYAAAACoABU=AQAAAAAAAAAAgAAAAAAAAAEAAAAAAAAACQAAAAAAAAA=eF6TBAAAGgAa
+  </AppendedData>
+</VTKFile>
diff --git a/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0_ts_1000_t_10000.000000.vtu b/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0_ts_1000_t_10000.000000.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..6f56001791722b2f7fd792e0db84610d8ac5346c
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/flow_free_expansion_pcs_0_ts_1000_t_10000.000000.vtu
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64" compressor="vtkZLibDataCompressor">
+  <UnstructuredGrid>
+    <FieldData>
+      <DataArray type="Int8" Name="IntegrationPointMetaData" NumberOfTuples="166" format="appended" RangeMin="34"                   RangeMax="125"                  offset="0"                   />
+      <DataArray type="Int8" Name="OGS_VERSION" NumberOfTuples="20" format="appended" RangeMin="45"                   RangeMax="103"                  offset="176"                 />
+      <DataArray type="Float64" Name="epsilon_ip" NumberOfComponents="6" NumberOfTuples="27" format="appended" RangeMin="1.1659775813e-05"     RangeMax="1.1659775814e-05"     offset="260"                 />
+      <DataArray type="Float64" Name="sigma_ip" NumberOfComponents="6" NumberOfTuples="27" format="appended" RangeMin="291494.39533"         RangeMax="291494.39534"         offset="1576"                />
+    </FieldData>
+    <Piece NumberOfPoints="20"                   NumberOfCells="1"                   >
+      <PointData>
+        <DataArray type="Float64" Name="HydraulicFlow" format="appended" RangeMin="-3.0029926662e-10"    RangeMax="2.4999948271e-05"     offset="2880"                />
+        <DataArray type="Float64" Name="NodalForces" NumberOfComponents="3" format="appended" RangeMin="8660.2540378"         RangeMax="28284.271248"         offset="3028"                />
+        <DataArray type="Float64" Name="displacement" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="1.1659775813e-05"     offset="3348"                />
+        <DataArray type="Float64" Name="epsilon_xx" format="appended" RangeMin="6.7317747044e-06"     RangeMax="6.7317747049e-06"     offset="3620"                />
+        <DataArray type="Float64" Name="epsilon_xy" format="appended" RangeMin="-8.9736613229e-17"    RangeMax="3.7491046973e-21"     offset="3784"                />
+        <DataArray type="Float64" Name="epsilon_yy" format="appended" RangeMin="6.7317747044e-06"     RangeMax="6.7317747047e-06"     offset="4056"                />
+        <DataArray type="Float64" Name="epsilon_zz" format="appended" RangeMin="6.7317747044e-06"     RangeMax="6.7317747047e-06"     offset="4228"                />
+        <DataArray type="Float64" Name="pressure" format="appended" RangeMin="0"                    RangeMax="380490.6127"          offset="4396"                />
+        <DataArray type="Float64" Name="pressure_interpolated" format="appended" RangeMin="380490.61268"         RangeMax="380490.6127"          offset="4492"                />
+        <DataArray type="Float64" Name="sigma_xx" format="appended" RangeMin="168294.36761"         RangeMax="168294.36762"         offset="4604"                />
+        <DataArray type="Float64" Name="sigma_xy" format="appended" RangeMin="-4.8810282873e-07"    RangeMax="2.0392441191e-11"     offset="4764"                />
+        <DataArray type="Float64" Name="sigma_yy" format="appended" RangeMin="168294.36761"         RangeMax="168294.36762"         offset="5036"                />
+        <DataArray type="Float64" Name="sigma_zz" format="appended" RangeMin="168294.36761"         RangeMax="168294.36762"         offset="5208"                />
+        <DataArray type="Float64" Name="velocity" NumberOfComponents="3" format="appended" RangeMin="1.1058101093e-05"     RangeMax="1.1058351392e-05"     offset="5380"                />
+      </PointData>
+      <CellData>
+        <DataArray type="Float64" Name="permeability" NumberOfComponents="6" format="appended" RangeMin="1.7320508076e-05"     RangeMax="1.7320508076e-05"     offset="5920"                />
+        <DataArray type="Float64" Name="principal_stress_values" NumberOfComponents="3" format="appended" RangeMin="291494.39534"         RangeMax="291494.39534"         offset="5996"                />
+        <DataArray type="Float64" Name="principal_stress_vector_1" NumberOfComponents="3" format="appended" RangeMin="1"                    RangeMax="1"                    offset="6072"                />
+        <DataArray type="Float64" Name="principal_stress_vector_2" NumberOfComponents="3" format="appended" RangeMin="1"                    RangeMax="1"                    offset="6160"                />
+        <DataArray type="Float64" Name="principal_stress_vector_3" NumberOfComponents="3" format="appended" RangeMin="1"                    RangeMax="1"                    offset="6244"                />
+      </CellData>
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="1.7320508076"         offset="6332"                />
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin=""                     RangeMax=""                     offset="6460"                />
+        <DataArray type="Int64" Name="offsets" format="appended" RangeMin=""                     RangeMax=""                     offset="6568"                />
+        <DataArray type="UInt8" Name="types" format="appended" RangeMin=""                     RangeMax=""                     offset="6628"                />
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+  <AppendedData encoding="base64">
+   _AQAAAAAAAAAAgAAAAAAAAKYAAAAAAAAAYwAAAAAAAAA=eF6FzDEKgDAMheG7ZO7k4NCriISoUQI2KWkdRLy7XV10fO+H7wLRyptTFVPM1haSO50F4nC9ovnCDrELoJQYIhTZEqFkaM+RJna0FWdL2ZS1NqC/ww/Bucjewicy3g8l5D0kAQAAAAAAAAAAgAAAAAAAABQAAAAAAAAAHAAAAAAAAAA=eF4z0zPWM9I1NjPVTU9Os0xOMTOySAEAMNgFJA==AQAAAAAAAAAAgAAAAAAAABAFAAAAAAAAugMAAAAAAAA=eF5VkW1MU2cYhhd0FMuHdAKlyrbCSq2r0u4km1MPUIqARTRSVikapZQVFjZmKdIeAlZSsqY0UeLIQTFR12DiiBkiTELhmahAWsmkmk3ZpI1hQx2Bsbko+xCJTZ/XH/t15eS+cj/3mxPbyhXJaX+G9h3kZsIfyu7c97AMzOjjr7qfbIc51inpaGfgxZNVodyfiN4wi7z0xllJUSMDvwtvBB5nC+jnXjs7fuMw5HIxr1mBzI+IDDFn05EOx1gjRD+PvquZLKTTpbLHKQUW4PyF/ROkd5DcmS7jtoiDfXlaz22PLJE+023ZbLIyEJ6NPrSh10W4Wp8qut5QC/y6mYfK46n0tmXnaKK1FpLV6F+zo3cqBvdUJLgMf4zUgVhTOZctUdA+flJvcsAMxWS/guw2knc8WpzlCHZaILXmJLXUX0gnqHXehNFGEJL+dtJ7ldy59Ivv39IpM2hXyP/RRSno+/zZCeVYHfTp0I/jos8j5FJayc+iesgsTegz6UV0oDVP0iuphy5DdCgv8qKXTvjMHfOInbXCiDRck7rwMWyxXzAJgt/LtqhQTk2j5+fg99xg2WTP+iY4wiYyvj0lYFv4bu0uXg0MaTAff4b+0Tz87miyDF88agNVvK2tYIsKMjOEJczGcuA2R/2vV0LuHNR0swPBvunqVabS/SWwbWFNwXjwHu8E5usE6L9FmPWFYX/FZSNMistnjlH50DB/oUfcawTZAfQjxOjFFCL7z6akjdw0QfprkevVYxQ4j20YHvlND9+T/VVk913yDqbz3AuDtBwufrbr9PZ9KvhSGx8ht9qAIv1c0ssnd6paAnFhD/Uwb3R93TNBwaEqRa3HawKDFP3de9HbS6iLyofDswbY+lHah9SvYcD6X7e3zhuApmNxfwT+t6ccZMdE7oD7bzuc5CjnMmKNkFzJ3Lm2aIewuNWhvEyBXn8ckvr00IaVWQ5IW9rJ381WQMq5D95+wDOD3BWD/Q3oMcnIlffEQ82dTrgVqePblvWwGLsUOL1DDdGkf4D0VpI77V9ZHdQaM2y66dA2BPtzmwffc2U6QPgAc837yIOEU5EpaapcM7QMtcnO+IpBfN5zhZ9jhpxPMFdqkXveRYbJnm61T1lA2OTb6O4rgDdZ0+V1XYWQQfbrye4k8o7bvIopnUoNn/84mnTlPz2csCsGBC4nKF71k958cqd46dtwf7Cvm+Ou39EZ7B/75nzxTxZYu4j/x0x2WwkP/Nlc7VMWQfUtlVR+SgT3HGq9N6sIXgLssgX9AQAAAAAAAAAAgAAAAAAAABAFAAAAAAAAsAMAAAAAAAA=eF490X9Q03UYB3AsGh1JCo30VJrRjUkoTVBjKl+Yu9MdbniHHhNMNwwWw6zvGLIj22Juk9YktgXM4wDb1BsEgoWYevmMNcn+ALmYMxUbRuEqfow8yR9H1o7nc/71uu+9P/d+ns/nu+P9wEyaOZK/ehfKJe62FJ9YGnkUWp5yttCePDAdmo25Hv7emo35rBAdK0adxd8GRVNGmPKyahlfJlGh3mpXqf0I7C/A/JYEzbGh/w4I9be9JvBz2e7XHkip6yX65ffuGIBP+qdI7xSZk9Ftdvsbj8Di55kbPW1s6sHwC2+nh4zwaBHm4j2ohPhNy7Jxc7kOxtflBlrE6VTcWMedUxU6KFiFedVBNGBG5yImDV0aPdwInpfEzYgoN7/uoLbKAGVk/01k7wC5h+mr7shHIwbQLRSLUi9JKe3L2yR135tgD+n3k95SMicvd6xnQm2AJcmt5StBRLEZmsqAVg+FAsztTvQ4kaWJ6txgCL//4474RH4atZ9593JbzVGQvHp3Ph+6ODqvj3hGUdbp7DJD7qmdzZugHIb7Mzemh78PDGC+pg0dOIuqPZ7J6NAx2JxhC9V3yIG3as5FW7Xg+xHzvB60sR/dzvyFec1igd3N9oiaxnxYIIiKPZaifNZ/k/RyyZwMk4yz1qaFpFJVYXSvHHzL1xoywvP+qMJccRyVEVe8uI/dNa4BXeaS9747JAHNxGctjKAGkpSYc1pRrwst+mGwkuOrBnmdJ3vNUDa4JP4zf03TcIPs7yB7v0Pu8Z/4H1njm0oo5bFjY87lQ1am4qWP6izP+vtIbwKZs4JVoqudoEHkYLCsP2eDui86eutwNTjkmFvbURuRke1iCU+o4PVKV8L0n4uh+NyFkUVOFexr/XU+h3v439zEW/6rUTus9UDTHlVM/8ew4PMP3qAt9TC9Hs+vG8Rzai9aJlBquRca4DfnduFqXgXEjjTlV3n1EGLi+Tgfnot0o+u7OfLfb9vhwJaLhe8+p4S2ofQcrVQGT0j/J6RXQOYERlOE7Vf0sFcXvLYr3D/Y3tR6/3wDWPswr2lCzcSZ+ERKcV8PyeyR1JN5JTD60Pi15G89zDVgrrChrE/Rq/6VzeK9RjA9pk3BngKY/KIXdjqkMEv2jyB7x5N7LLucYH9LJoPkOOfCuac0CJYGH166aYcnpP8V0kuTOR+qxzZ0OqXQl/iTM/V0ARzmprArCo0gLCHvqEIPE89u5hlqs4pgG+/KNF+ZBjlZQ7MOqgj+B6zqg3s=AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAATQAAAAAAAAA=eF57fkI49rLZL7uWfT6rXi/6spd1+r/EO0D+Ar4ij1jxo3uzp4S+BfF52maGXHd9ulf1lHDsfSD/wmfVJ2y+J2wZwOBHPa1oAF8DM6Y=AQAAAAAAAAAAgAAAAAAAAOABAAAAAAAAzgAAAAAAAAA=eF5jcGFgYOjYfMCj8v///+2bD4RBaREGsLjDi3aI/A0ofUufEUxzQOWXPICol4DyWaC0SiJUH1T9CjR1MPMNoOqkoPyEW6jmi6DRDFBaDEo/2QSiLztwVUNosDxDw94Xm1D4tmxQ+Vt3QO6AiSfYsoHNuXzgClQcxofIN9lC6I22Pzgh+v9wIpnrsGnvrBcQfRzI+hoW2LJA+SteINu3Zi8DVBwm/+8/WP6A2mJkdZvh6iD8Fls5qDwLsnhDsS0TmnkwPlh+wpa9AN0rojg=AQAAAAAAAAAAgAAAAAAAAOABAAAAAAAAqQAAAAAAAAA=eF5jYMAOLKK4VQxs7tjhkGaoWMmLIn/tBg+Yf+UDJ1591VB9n6HqYeKX0PSpuUHUyULpYm0+MK0pzgWmJaE0uvn8dSD1Z+DiYmh8GJDygogHlaD6wxvKV4HKu2TxYNXPEcyHIi6gCfHPmyCI+D8NVP/tkhIAi3MzQcQ5oPTpQtRwXhzOBVZ3Diq+BMqHyeu8hehTzICIT+KDhIM4VHwdlK8MlQcA7/5ZjQ==AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAWgAAAAAAAAA=eF5zqOJVMbC5Y6dvxQmmBc/yg+mDTyB8Xih/P5TPxCUEptl9ucD0498Q/cx/IHRjmACYLoPSVlHcEHU3eMD0fShdpM0Hpvc85wDTK6D0yWaIPaehNADSATeqAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAqwAAAAAAAAA=eF4BoABf/wAAcidkCaK7lR59m5t6ibwW7smyZN2ZvASiC/qNj4e8gIFsNmnLsbuylYhhvMSGvDGNCKTYRZW84gwahUvpgrwAgj20Y7SxO/fEXvjWZ4O8tsPDIyHfgbyH3bdF0/GWvGRWDq+MG3C8F06UJjzRaLytkvSsPnqQvF+4sbbhjIm8PtNzrVJ5hrwfdcq/PA6CvPpzL+uCb4G82tqrhmFSgrw9MlXkAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAXgAAAAAAAAA=eF6bEcSrYmBzx657HxeY9mPgA9NOypxgmtUPIi+0EyJvYwfhB5VC5C/5QPgdKyG0nBuE3jAbQpek8IDp52EQevZbbjAtuxZCdxyDmHvmA8Q8HXEI/3MYhA8A06E0bA==AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAXQAAAAAAAAA=eF6bF8SrYmBzx65+HxeYtvGD8F13Qvg+DHxg2lSZE0zz2UHktUoh/KqVEP53Hwi9bTaEVnSD0LUpPGB6zltuiHg4hM+4FsJ/9AFiTt4xiH07wiB8DXEIHwDbCDNxAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAJgAAAAAAAAA=eF5bUJRWrGUp7tjakwym56Px50H5bVD+Aii/BcpnoDEAAK6+FR4=AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAMwAAAAAAAAA=eF5bUJRWrGUp7tjakwym56Px50H5bVD+Aii/BU09TBydP+l/Cl4aZm4rGg0zHwA07zbIAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAVgAAAAAAAAA=eF67sujBB6NuFsc3UvfAtP+Kh2B6rziE7wblH4Pyi1Mfgen/UL7jY4j+ECj9+TRE/SMovav2PphO+wuhS6D0yiiI+qybd8F0EJQ2vw+hvaA0ACHWT9k=AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAqwAAAAAAAAA=eF4BoABf/wCAml+c16a9x3iDBDgikL6uwLJ4xWCgvl9FRF6N1o2+AOGf+R2Jtr2pMwg2stWMviDteObK8Jq+urclcCvzh74ARLA/9mu2PTO/kRBuk4i+CBaK1Baihr4sQb9+zA6dvkJAY60xZnS+ojEqPvBtb75r5lqBHt6UvlGizkTKLZC+B7/32jB2jL5wIaWAv92Gvqc0lYe7FIa+gLErHww0h74eGFHzAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAXgAAAAAAAAA=eF57NvPBB6NuFsebhffAtLLjQzCd9eYumFaThPCd3CHy04Ig/NXPIfJMeyD6H16A0EEyEPkUfQgdu/M+mA55AKEPnYDQx09D6HYXiLnbRCC0EQOEtr4KMR8AKnxLyQ==AQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAXgAAAAAAAAA=eF57PfPBB6NuFscbhffAtJ/kQzBd5A7hCzpC+Plv7oLp6UEQ/o7nEP61CxD96nsgdJE+RN5PBkJH7bwPpneegNARDyD0hdMQepsIxJ45LhDa4CrEXFsGCB8AbDxMYA==AQAAAAAAAAAAgAAAAAAAAOABAAAAAAAAdAEAAAAAAAA=eF5b/nzFmusGz+3OKO3YuWXubduEY0azp695absHKu7mrrkg4OcW2yWWt6IllDfs3VRiO/kUUHwzVL3MQRW1k5zn9u6Eih+Aqv98pDfm+Icntn9Mc68fBYqXup5pdZv2am9NlnDi3rUvbRnNIOKc/im8e+9dtg2LWv/oievqvT8PMdq9AIpnQdULcR7PdNE9t1fqMERcDqreLDNP6e3HJ7YrgjkaTwPFC5Yvj3gfe2GvylzJiSxLX9p+dpabexkovgfqTp3jhTLHC5fZiu15mHQBKJ4CNX9L8PqAj/eX2Yat+f7vFlA8EWpO5eQ/NxQFz+3dDg2HOauAQGu7bdPNiAW8L2/Y/oD6ayVUnLn7wbNL327YboGGwwKouBr/bk19kR17v0P9dRgqvslzDr/U3e17d0Ld/9rPf+M967O28pX1O+x11+x9CHV/EzQ8J1mbvJjDvMxWBup+Vmg4KEP9lQB1/3GoOednlwSZvHxiCwB6oPz2AQAAAAAAAAAAgAAAAAAAADAAAAAAAAAAFgAAAAAAAAA=eF77lPG4Y+uPJ3af0GgGHAAAZjoQvQ==AQAAAAAAAAAAgAAAAAAAABgAAAAAAAAAFwAAAAAAAAA=eF4Tr73/waibxTFqDoQO2AGhAY0zCwY=AQAAAAAAAAAAgAAAAAAAABgAAAAAAAAAIAAAAAAAAAA=eF47ejH+VfbpJ/u/qUxZ+tjo4f7LZuJnTgNpAMXyD0o=AQAAAAAAAAAAgAAAAAAAABgAAAAAAAAAHAAAAAAAAAA=eF5jYIAA971y2/oWPNvff/OK2LoFz+wBTigJcQ==AQAAAAAAAAAAgAAAAAAAABgAAAAAAAAAHwAAAAAAAAA=eF57prLYvz/ohf2bTN/bHRl39y+XrRZOANIAoAQMxA==AQAAAAAAAAAAgAAAAAAAAOABAAAAAAAAPwAAAAAAAAA=eF5jYMAHPtjjlcaQh/GJ1YdLPy51uGh08ABNHJ2PLo7L3gdoNDpAF0fXh24uujguf6CrI9YedPqBPQBopCndAQAAAAAAAAAAgAAAAAAAAKAAAAAAAAAAMAAAAAAAAAA=eF4txUkCgBAAAECpiKLt/391MHOZEKbFq6M3785Ovvy6u7j58+3qw49/nx4uqAC/AQAAAAAAAAAAgAAAAAAAAAgAAAAAAAAACwAAAAAAAAA=eF4TYYAAAACoABU=AQAAAAAAAAAAgAAAAAAAAAEAAAAAAAAACQAAAAAAAAA=eF6TBAAAGgAa
+  </AppendedData>
+</VTKFile>
diff --git a/inst/extdata/flow_free_expansion/playground/cube_1x1x1.vtu b/inst/extdata/flow_free_expansion/playground/cube_1x1x1.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..b4406389b89a5e563d119e7e219e72d597c57b69
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/playground/cube_1x1x1.vtu
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian" header_type="UInt32">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="8"                    NumberOfCells="1"                   >
+      <PointData>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="1.7320508076"         offset="0"                   />
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin=""                     RangeMax=""                     offset="264"                 />
+        <DataArray type="Int64" Name="offsets" format="appended" RangeMin=""                     RangeMax=""                     offset="356"                 />
+        <DataArray type="UInt8" Name="types" format="appended" RangeMin=""                     RangeMax=""                     offset="372"                 />
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+</VTKFile>
diff --git a/inst/extdata/flow_free_expansion/playground/cube_1x1x1_quad.vtu b/inst/extdata/flow_free_expansion/playground/cube_1x1x1_quad.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..cfbcf9127aabe8e535d6a7765c9de04abd9782fb
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/playground/cube_1x1x1_quad.vtu
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian" header_type="UInt32">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="20"                   NumberOfCells="1"                   >
+      <PointData>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0"                    RangeMax="1.7320508076"         offset="0"                   />
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin=""                     RangeMax=""                     offset="648"                 />
+        <DataArray type="Int64" Name="offsets" format="appended" RangeMin=""                     RangeMax=""                     offset="868"                 />
+        <DataArray type="UInt8" Name="types" format="appended" RangeMin=""                     RangeMax=""                     offset="884"                 />
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+  <AppendedData encoding="base64">
+   _4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAAAAAAAAAAAADgPwAAAAAAAAAAAAAAAAAA4D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADgPwAAAAAAAOA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAOA/AAAAAAAA8D8AAAAAAAAAAAAAAAAAAOA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAADgPwAAAAAAAPA/AAAAAAAA4D8AAAAAAAAAAAAAAAAAAPA/AAAAAAAA4D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADgPw==oAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAFAAAAAAAAAAcAAAAAAAAABgAAAAAAAAAMAAAAAAAAABEAAAAAAAAADgAAAAAAAAAJAAAAAAAAAA0AAAAAAAAAEgAAAAAAAAAPAAAAAAAAAAoAAAAAAAAACAAAAAAAAAAQAAAAAAAAABMAAAAAAAAACwAAAAAAAAA=CAAAABQAAAAAAAAAAQAAABk=
+  </AppendedData>
+</VTKFile>
diff --git a/inst/extdata/flow_free_expansion/playground/x_quad_with_half_hole_q.vtu b/inst/extdata/flow_free_expansion/playground/x_quad_with_half_hole_q.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..015f24c1db451ef532eb97a2f7645eddfe0a5fe5
--- /dev/null
+++ b/inst/extdata/flow_free_expansion/playground/x_quad_with_half_hole_q.vtu
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian" header_type="UInt32">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="3479"                 NumberOfCells="1114"                >
+      <PointData>
+      </PointData>
+      <CellData>
+        <DataArray type="Int32" Name="MaterialIDs" format="appended" RangeMin="0"                    RangeMax="0"                    offset="0"                   />
+      </CellData>
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="2.2980352443"         RangeMax="55.901699437"         offset="5948"                />
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="appended" RangeMin=""                     RangeMax=""                     offset="117284"              />
+        <DataArray type="Int64" Name="offsets" format="appended" RangeMin=""                     RangeMax=""                     offset="212352"              />
+        <DataArray type="UInt8" Name="types" format="appended" RangeMin=""                     RangeMax=""                     offset="224240"              />
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+</VTKFile>
diff --git a/man/GMLObject.Rd b/man/GMLObject.Rd
deleted file mode 100644
index 2e77fd7378e4e134b157a30a3429ecfbe89e80c8..0000000000000000000000000000000000000000
--- a/man/GMLObject.Rd
+++ /dev/null
@@ -1,65 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLObject}
-\alias{GMLObject}
-\title{Class representing a GML object}
-\value{
-The encoding of the input file
-Class describing an entire GML object with a reference file name, points, polylines and surfaces
-}
-\description{
-Class representing a GML object
-
-Class representing a GML object
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLObject$new()}}
-\item \href{#method-as_node}{\code{GMLObject$as_node()}}
-\item \href{#method-clone}{\code{GMLObject$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLObject$new(
-  name = NULL,
-  points = NULL,
-  polylines = NULL,
-  surfaces = NULL,
-  xmlns_xsi = "http://www.w3.org/2001/XMLSchema-instance",
-  xmlns_ogs = "http://www.opengeosys.org"
-)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLObject$as_node(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLObject$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/GMLPoint.Rd b/man/GMLPoint.Rd
deleted file mode 100644
index 9fff6578d3fd00ca648f4f7ac0bb26f54dfb3287..0000000000000000000000000000000000000000
--- a/man/GMLPoint.Rd
+++ /dev/null
@@ -1,74 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLPoint}
-\alias{GMLPoint}
-\title{Class describing a single point}
-\description{
-Class describing a single point
-
-Class describing a single point
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLPoint$new()}}
-\item \href{#method-as_list}{\code{GMLPoint$as_list()}}
-\item \href{#method-as_node}{\code{GMLPoint$as_node()}}
-\item \href{#method-print}{\code{GMLPoint$print()}}
-\item \href{#method-clone}{\code{GMLPoint$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoint$new(id = 0, coordinates = c(0, 0, 0), is_origin = FALSE)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_list"></a>}}
-\if{latex}{\out{\hypertarget{method-as_list}{}}}
-\subsection{Method \code{as_list()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoint$as_list(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoint$as_node(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-print"></a>}}
-\if{latex}{\out{\hypertarget{method-print}{}}}
-\subsection{Method \code{print()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoint$print(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoint$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/GMLPoints.Rd b/man/GMLPoints.Rd
deleted file mode 100644
index 2b84e1ac081a24e653d8ca5b81c7f40acc4300df..0000000000000000000000000000000000000000
--- a/man/GMLPoints.Rd
+++ /dev/null
@@ -1,104 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLPoints}
-\alias{GMLPoints}
-\title{Class describing a set of points}
-\description{
-Class describing a set of points
-
-Class describing a set of points
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLPoints$new()}}
-\item \href{#method-validate_ids}{\code{GMLPoints$validate_ids()}}
-\item \href{#method-validate_dim}{\code{GMLPoints$validate_dim()}}
-\item \href{#method-validate_coordinates}{\code{GMLPoints$validate_coordinates()}}
-\item \href{#method-as_list}{\code{GMLPoints$as_list()}}
-\item \href{#method-as_node}{\code{GMLPoints$as_node()}}
-\item \href{#method-print}{\code{GMLPoints$print()}}
-\item \href{#method-clone}{\code{GMLPoints$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$new(gml_points)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-validate_ids"></a>}}
-\if{latex}{\out{\hypertarget{method-validate_ids}{}}}
-\subsection{Method \code{validate_ids()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$validate_ids(gml_points)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-validate_dim"></a>}}
-\if{latex}{\out{\hypertarget{method-validate_dim}{}}}
-\subsection{Method \code{validate_dim()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$validate_dim(gml_points)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-validate_coordinates"></a>}}
-\if{latex}{\out{\hypertarget{method-validate_coordinates}{}}}
-\subsection{Method \code{validate_coordinates()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$validate_coordinates(gml_points)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_list"></a>}}
-\if{latex}{\out{\hypertarget{method-as_list}{}}}
-\subsection{Method \code{as_list()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$as_list(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$as_node(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-print"></a>}}
-\if{latex}{\out{\hypertarget{method-print}{}}}
-\subsection{Method \code{print()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$print(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPoints$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/GMLPolyline.Rd b/man/GMLPolyline.Rd
deleted file mode 100644
index b3283acecbc592fefbd14ac0637e8615eb19805a..0000000000000000000000000000000000000000
--- a/man/GMLPolyline.Rd
+++ /dev/null
@@ -1,64 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLPolyline}
-\alias{GMLPolyline}
-\title{Class describing a single polyline}
-\description{
-Class describing a single polyline
-
-Class describing a single polyline
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLPolyline$new()}}
-\item \href{#method-as_node}{\code{GMLPolyline$as_node()}}
-\item \href{#method-print}{\code{GMLPolyline$print()}}
-\item \href{#method-clone}{\code{GMLPolyline$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolyline$new(id = 0, name = "front_left", point1 = 0, point2 = 1)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolyline$as_node(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-print"></a>}}
-\if{latex}{\out{\hypertarget{method-print}{}}}
-\subsection{Method \code{print()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolyline$print(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolyline$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/GMLPolylines.Rd b/man/GMLPolylines.Rd
deleted file mode 100644
index 071ed9bdf6d7422d46592bcdce81f36377caa80d..0000000000000000000000000000000000000000
--- a/man/GMLPolylines.Rd
+++ /dev/null
@@ -1,74 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLPolylines}
-\alias{GMLPolylines}
-\title{Class describing a set of polylines}
-\description{
-Class describing a set of polylines
-
-Class describing a set of polylines
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLPolylines$new()}}
-\item \href{#method-validate_ids}{\code{GMLPolylines$validate_ids()}}
-\item \href{#method-validate_polylines}{\code{GMLPolylines$validate_polylines()}}
-\item \href{#method-as_node}{\code{GMLPolylines$as_node()}}
-\item \href{#method-clone}{\code{GMLPolylines$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolylines$new(gml_polylines)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-validate_ids"></a>}}
-\if{latex}{\out{\hypertarget{method-validate_ids}{}}}
-\subsection{Method \code{validate_ids()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolylines$validate_ids(gml_polylines)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-validate_polylines"></a>}}
-\if{latex}{\out{\hypertarget{method-validate_polylines}{}}}
-\subsection{Method \code{validate_polylines()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolylines$validate_polylines(gml_polylines)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolylines$as_node(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLPolylines$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/GMLSurface.Rd b/man/GMLSurface.Rd
deleted file mode 100644
index de15661365c46fa65482e25bb3470b2d4adb8701..0000000000000000000000000000000000000000
--- a/man/GMLSurface.Rd
+++ /dev/null
@@ -1,69 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLSurface}
-\alias{GMLSurface}
-\title{Class describing a single surface (using 2 GMLSurfaceElements)}
-\description{
-Class describing a single surface (using 2 GMLSurfaceElements)
-
-Class describing a single surface (using 2 GMLSurfaceElements)
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLSurface$new()}}
-\item \href{#method-validate_elements}{\code{GMLSurface$validate_elements()}}
-\item \href{#method-as_node}{\code{GMLSurface$as_node()}}
-\item \href{#method-clone}{\code{GMLSurface$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurface$new(
-  id = 0,
-  name = "left",
-  gml_surface_element1 = GMLSurfaceElement$new(),
-  gml_surface_element2 = GMLSurfaceElement$new(p3 = 3)
-)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-validate_elements"></a>}}
-\if{latex}{\out{\hypertarget{method-validate_elements}{}}}
-\subsection{Method \code{validate_elements()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurface$validate_elements(gml_surface_element1, gml_surface_element2)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurface$as_node()}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurface$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/GMLSurfaceElement.Rd b/man/GMLSurfaceElement.Rd
deleted file mode 100644
index 3a5c05b7b8e51bca2c1c6813263da84b5abef82f..0000000000000000000000000000000000000000
--- a/man/GMLSurfaceElement.Rd
+++ /dev/null
@@ -1,64 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLSurfaceElement}
-\alias{GMLSurfaceElement}
-\title{Class describing a single surface element (using 3 point IDs)}
-\description{
-Class describing a single surface element (using 3 point IDs)
-
-Class describing a single surface element (using 3 point IDs)
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLSurfaceElement$new()}}
-\item \href{#method-as_list}{\code{GMLSurfaceElement$as_list()}}
-\item \href{#method-as_node}{\code{GMLSurfaceElement$as_node()}}
-\item \href{#method-clone}{\code{GMLSurfaceElement$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaceElement$new(p1 = 0, p2 = 1, p3 = 2)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_list"></a>}}
-\if{latex}{\out{\hypertarget{method-as_list}{}}}
-\subsection{Method \code{as_list()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaceElement$as_list(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaceElement$as_node(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaceElement$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/GMLSurfaces.Rd b/man/GMLSurfaces.Rd
deleted file mode 100644
index 8440c35ca8934679c65e349d65bc1a52d35e1f46..0000000000000000000000000000000000000000
--- a/man/GMLSurfaces.Rd
+++ /dev/null
@@ -1,64 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{GMLSurfaces}
-\alias{GMLSurfaces}
-\title{Class describing a set of surfaces}
-\description{
-Class describing a set of surfaces
-
-Class describing a set of surfaces
-}
-\section{Methods}{
-\subsection{Public methods}{
-\itemize{
-\item \href{#method-new}{\code{GMLSurfaces$new()}}
-\item \href{#method-validate_ids}{\code{GMLSurfaces$validate_ids()}}
-\item \href{#method-as_node}{\code{GMLSurfaces$as_node()}}
-\item \href{#method-clone}{\code{GMLSurfaces$clone()}}
-}
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-new"></a>}}
-\if{latex}{\out{\hypertarget{method-new}{}}}
-\subsection{Method \code{new()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaces$new(gml_surfaces)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-validate_ids"></a>}}
-\if{latex}{\out{\hypertarget{method-validate_ids}{}}}
-\subsection{Method \code{validate_ids()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaces$validate_ids(gml_surfaces)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-as_node"></a>}}
-\if{latex}{\out{\hypertarget{method-as_node}{}}}
-\subsection{Method \code{as_node()}}{
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaces$as_node(...)}\if{html}{\out{</div>}}
-}
-
-}
-\if{html}{\out{<hr>}}
-\if{html}{\out{<a id="method-clone"></a>}}
-\if{latex}{\out{\hypertarget{method-clone}{}}}
-\subsection{Method \code{clone()}}{
-The objects of this class are cloneable with this method.
-\subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{GMLSurfaces$clone(deep = FALSE)}\if{html}{\out{</div>}}
-}
-
-\subsection{Arguments}{
-\if{html}{\out{<div class="arguments">}}
-\describe{
-\item{\code{deep}}{Whether to make a deep clone.}
-}
-\if{html}{\out{</div>}}
-}
-}
-}
diff --git a/man/OGS6.Rd b/man/OGS6.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..a2fc85348197f180659afacf9ccfba04d14c6d10
--- /dev/null
+++ b/man/OGS6.Rd
@@ -0,0 +1,74 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ogs6.R
+\name{OGS6}
+\alias{OGS6}
+\title{Constructor for the OGS6 base class}
+\description{
+Constructor for the OGS6 base class
+
+Constructor for the OGS6 base class
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-new}{\code{OGS6$new()}}
+\item \href{#method-add_sim_input}{\code{OGS6$add_sim_input()}}
+\item \href{#method-set_sim_input_obj_param}{\code{OGS6$set_sim_input_obj_param()}}
+\item \href{#method-add_sim_output}{\code{OGS6$add_sim_output()}}
+\item \href{#method-clone}{\code{OGS6$clone()}}
+}
+}
+\if{html}{\out{<hr>}}
+\if{html}{\out{<a id="method-new"></a>}}
+\if{latex}{\out{\hypertarget{method-new}{}}}
+\subsection{Method \code{new()}}{
+\subsection{Usage}{
+\if{html}{\out{<div class="r">}}\preformatted{OGS6$new(sim_name, sim_id, sim_path)}\if{html}{\out{</div>}}
+}
+
+}
+\if{html}{\out{<hr>}}
+\if{html}{\out{<a id="method-add_sim_input"></a>}}
+\if{latex}{\out{\hypertarget{method-add_sim_input}{}}}
+\subsection{Method \code{add_sim_input()}}{
+\subsection{Usage}{
+\if{html}{\out{<div class="r">}}\preformatted{OGS6$add_sim_input(name, value)}\if{html}{\out{</div>}}
+}
+
+}
+\if{html}{\out{<hr>}}
+\if{html}{\out{<a id="method-set_sim_input_obj_param"></a>}}
+\if{latex}{\out{\hypertarget{method-set_sim_input_obj_param}{}}}
+\subsection{Method \code{set_sim_input_obj_param()}}{
+\subsection{Usage}{
+\if{html}{\out{<div class="r">}}\preformatted{OGS6$set_sim_input_obj_param(obj_name, obj_param_name, value)}\if{html}{\out{</div>}}
+}
+
+}
+\if{html}{\out{<hr>}}
+\if{html}{\out{<a id="method-add_sim_output"></a>}}
+\if{latex}{\out{\hypertarget{method-add_sim_output}{}}}
+\subsection{Method \code{add_sim_output()}}{
+\subsection{Usage}{
+\if{html}{\out{<div class="r">}}\preformatted{OGS6$add_sim_output(name, value)}\if{html}{\out{</div>}}
+}
+
+}
+\if{html}{\out{<hr>}}
+\if{html}{\out{<a id="method-clone"></a>}}
+\if{latex}{\out{\hypertarget{method-clone}{}}}
+\subsection{Method \code{clone()}}{
+The objects of this class are cloneable with this method.
+\subsection{Usage}{
+\if{html}{\out{<div class="r">}}\preformatted{OGS6$clone(deep = FALSE)}\if{html}{\out{</div>}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{<div class="arguments">}}
+\describe{
+\item{\code{deep}}{Whether to make a deep clone.}
+}
+\if{html}{\out{</div>}}
+}
+}
+}
diff --git a/man/add_opt_attr.Rd b/man/add_opt_attr.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f5c04bc530408fc8c24bac434f232b69d9a712b8
--- /dev/null
+++ b/man/add_opt_attr.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{add_opt_attr}
+\alias{add_opt_attr}
+\title{add_opt_attr}
+\usage{
+add_opt_attr(node, obj_parameter, attr_name)
+}
+\arguments{
+\item{node}{The node the optional attribute should be added to}
+
+\item{obj_parameter}{The value of the attribute to be added}
+
+\item{attr_name}{The name of the attribute to be added}
+}
+\description{
+Adds an optional attribute to a node attribute list
+}
diff --git a/man/add_opt_child.Rd b/man/add_opt_child.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..4ebcceb6b7f7413ed3e3f8f2c4780e255f203daf
--- /dev/null
+++ b/man/add_opt_child.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{add_opt_child}
+\alias{add_opt_child}
+\title{add_opt_child}
+\usage{
+add_opt_child(node, obj_parameter, child_name = NULL)
+}
+\arguments{
+\item{node}{The node the optional child should be added to}
+
+\item{obj_parameter}{The value of the child to be added}
+
+\item{child_name}{Optional: If it's a child node instead of just a value, the name of the child to be added}
+}
+\description{
+Adds an optional child to a node child list
+}
diff --git a/man/adopt_nodes.Rd b/man/adopt_nodes.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..a939fd692977fbba347c5c163904253afb1e7ee8
--- /dev/null
+++ b/man/adopt_nodes.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{adopt_nodes}
+\alias{adopt_nodes}
+\title{adopt_nodes}
+\usage{
+adopt_nodes(parent_name, objs)
+}
+\arguments{
+\item{parent_name}{The name of the new parent node}
+
+\item{objs}{A list of class objects (class must have method for generic function as_node)}
+}
+\description{
+A helper function for creating parent nodes using the generic function as_node
+}
diff --git a/man/analyse_xml.Rd b/man/analyse_xml.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..bfde46e9cf174a47d5268a806ca7804bb02f0b59
--- /dev/null
+++ b/man/analyse_xml.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/analyse_xml.R
+\name{analyse_xml}
+\alias{analyse_xml}
+\title{analyse_xml}
+\usage{
+analyse_xml(path, pattern, element_name)
+}
+\arguments{
+\item{path}{A path}
+
+\item{pattern}{A regex pattern}
+
+\item{element_name}{The name of the XML element to look for}
+}
+\description{
+This is a helper function which can be used to combat missing documentation. It looks
+ for files in a path which match the given pattern and then attempts to parse them as XML.
+ For each occurence of the specified element, it documents its attributes and direct children and prints a little
+ summary of its findings at the end.
+}
diff --git a/man/as_node.Rd b/man/as_node.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..d3e317926bb397e58acbc288aaca16354e09fa0d
--- /dev/null
+++ b/man/as_node.Rd
@@ -0,0 +1,14 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/generics.R
+\name{as_node}
+\alias{as_node}
+\title{S3 generic function, use to turn class data into XML friendly format}
+\usage{
+as_node(obj)
+}
+\arguments{
+\item{obj}{A class object (must have implementation for as_node)}
+}
+\description{
+S3 generic function, use to turn class data into XML friendly format
+}
diff --git a/man/as_node.data_array.Rd b/man/as_node.data_array.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f4cd30866e926eb7e1b9034a2985f1191100e35e
--- /dev/null
+++ b/man/as_node.data_array.Rd
@@ -0,0 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_vtu.R
+\name{as_node.data_array}
+\alias{as_node.data_array}
+\title{as_node.data_array}
+\usage{
+\method{as_node}{data_array}(obj)
+}
+\description{
+Implementation of the generic function as_node for data_array class objects
+}
diff --git a/man/as_node.r2ogs6_prj_medium_phase.Rd b/man/as_node.r2ogs6_prj_medium_phase.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..4093e1e9c693bbd6bbad3a388379e9247dd23c23
--- /dev/null
+++ b/man/as_node.r2ogs6_prj_medium_phase.Rd
@@ -0,0 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/export_prj.R
+\name{as_node.r2ogs6_prj_medium_phase}
+\alias{as_node.r2ogs6_prj_medium_phase}
+\title{Method for coercing an r2ogs_prj_medium_phase class object into the structure expected by xml2}
+\usage{
+\method{as_node}{r2ogs6_prj_medium_phase}(obj)
+}
+\description{
+Method for coercing an r2ogs_prj_medium_phase class object into the structure expected by xml2
+}
diff --git a/man/as_node.r2ogs6_prj_property.Rd b/man/as_node.r2ogs6_prj_property.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..9d0ae028e887efce97f82326ce8144679e509bcf
--- /dev/null
+++ b/man/as_node.r2ogs6_prj_property.Rd
@@ -0,0 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/export_prj.R
+\name{as_node.r2ogs6_prj_property}
+\alias{as_node.r2ogs6_prj_property}
+\title{Method for coercing an r2ogs6_prj_property class object into the structure expected by xml2}
+\usage{
+\method{as_node}{r2ogs6_prj_property}(obj)
+}
+\description{
+Method for coercing an r2ogs6_prj_property class object into the structure expected by xml2
+}
diff --git a/man/check_for_obj_of_name.Rd b/man/check_for_obj_of_name.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..6a45903c85bf9cd655e7a3da111cc91348f0ea25
--- /dev/null
+++ b/man/check_for_obj_of_name.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{check_for_obj_of_name}
+\alias{check_for_obj_of_name}
+\title{check_for_obj_of_name}
+\usage{
+check_for_obj_of_name(ogs6_obj, obj_name)
+}
+\arguments{
+\item{ogs6_obj}{The ogs6 object to check}
+
+\item{obj_name}{The name of the object to check for}
+}
+\description{
+Checks if a object with the given name was already defined for a ogs6 object and if not,
+tells user to initialize one
+}
diff --git a/man/create_gml_from_obj.Rd b/man/create_gml_from_obj.Rd
deleted file mode 100644
index 5e83857d3bf806fca63153b7f60f3bcc908af9d8..0000000000000000000000000000000000000000
--- a/man/create_gml_from_obj.Rd
+++ /dev/null
@@ -1,19 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml_R6.R
-\name{create_gml_from_obj}
-\alias{create_gml_from_obj}
-\title{Creates a .gml XML file based on an GML object}
-\usage{
-create_gml_from_obj(gml_object, file_name)
-}
-\arguments{
-\item{gml_object}{The specified GML object (of class GMLObject)}
-
-\item{file_name}{The name of the file the XML will be written to}
-}
-\value{
-WIP
-}
-\description{
-Creates a .gml XML file based on an GML object
-}
diff --git a/man/create_template_prj.Rd b/man/create_template_prj.Rd
deleted file mode 100644
index a83651b3f10c215e20c5dbdf7926944155f2df19..0000000000000000000000000000000000000000
--- a/man/create_template_prj.Rd
+++ /dev/null
@@ -1,19 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/utils.R
-\name{create_template_prj}
-\alias{create_template_prj}
-\title{Creates a template project file based on the XML structure and attributes of an existing project file.}
-\usage{
-create_template_prj(existing_prj, template_prj)
-}
-\arguments{
-\item{existing_prj}{An existing .prj file to use as a template for the structure and attributes}
-
-\item{template_prj}{The path where the template should be saved}
-}
-\value{
-The newly created template project file
-}
-\description{
-Creates a template project file based on the XML structure and attributes of an existing project file.
-}
diff --git a/man/export_xml_to_file.Rd b/man/export_xml_to_file.Rd
index 8aa952faca91bfea7617cf221aa91226407bd1db..81750afb5cc66d2c4c370470f146491482ddc28f 100644
--- a/man/export_xml_to_file.Rd
+++ b/man/export_xml_to_file.Rd
@@ -1,15 +1,15 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml.R
+% Please edit documentation in R/utils.R
 \name{export_xml_to_file}
 \alias{export_xml_to_file}
-\title{Export function}
+\title{export_xml_to_file}
 \usage{
 export_xml_to_file(xml_data, file_name)
 }
 \arguments{
-\item{xml_data}{The .gml data (already in XML friendly format)}
+\item{xml_data}{The data to be exported (already in XML friendly format)}
 
-\item{file_name}{The name of the .gml file to be written}
+\item{file_name}{The name of the file to be written}
 }
 \description{
 Export function
diff --git a/man/generate_as_node_from_element.Rd b/man/generate_as_node_from_element.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..2ebc47d3d7a635cdbcf870d462f39f7a5f2ca030
--- /dev/null
+++ b/man/generate_as_node_from_element.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/analyse_xml.R
+\name{generate_as_node_from_element}
+\alias{generate_as_node_from_element}
+\title{generate_as_node_from_element}
+\usage{
+generate_as_node_from_element(element_name, attrs = NULL, children = NULL)
+}
+\arguments{
+\item{element_name}{The name of the XML element to base the function on}
+
+\item{attrs}{Optional: A list of element attributes}
+
+\item{children}{Optional: A list of element children}
+}
+\description{
+Generates a method for the generic function as_node based on an XML element
+}
diff --git a/man/get_xml_encoding.Rd b/man/get_xml_encoding.Rd
deleted file mode 100644
index c179376d755a0e52f8752ed84737178c39ed10b5..0000000000000000000000000000000000000000
--- a/man/get_xml_encoding.Rd
+++ /dev/null
@@ -1,17 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/utils.R
-\name{get_xml_encoding}
-\alias{get_xml_encoding}
-\title{Reads the encoding of an XML file}
-\usage{
-get_xml_encoding(input_file_name)
-}
-\arguments{
-\item{input_file_name}{An XML (.xml or, in the case of OpenGeoSys, .prj) file}
-}
-\value{
-The encoding of the input file
-}
-\description{
-Reads the encoding of an XML file
-}
diff --git a/man/gml_data_to_xml.Rd b/man/gml_data_to_xml.Rd
index 919404a797f323c77c899b08c87ef6edfebbaf9c..5713afd5f23031373c2bc3383e57c865750199de 100644
--- a/man/gml_data_to_xml.Rd
+++ b/man/gml_data_to_xml.Rd
@@ -1,23 +1,17 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml.R
+% Please edit documentation in R/export_gml.R
 \name{gml_data_to_xml}
 \alias{gml_data_to_xml}
-\title{Wrapper function to create a XML document based on the user input data}
+\title{Wrapper function to create a .gml XML document based on the user input data}
 \usage{
-gml_data_to_xml(geo_name, points_tibble, polylines_list, surfaces_list)
+gml_data_to_xml(gml_obj)
 }
 \arguments{
-\item{geo_name}{The name of the geometry specified by the user}
-
-\item{points_tibble}{A tibble containing points}
-
-\item{polylines_list}{A list containing polylines}
-
-\item{surfaces_list}{A list containing surfaces}
+\item{gml_obj}{A gml class object}
 }
 \value{
 A XML document ready for export to a file
 }
 \description{
-Wrapper function to create a XML document based on the user input data
+Wrapper function to create a .gml XML document based on the user input data
 }
diff --git a/man/input_add_gml_obj.Rd b/man/input_add_gml_obj.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..4316ca68a0f9128693bbcd674471392bb9fddcbd
--- /dev/null
+++ b/man/input_add_gml_obj.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_gml.R
+\name{input_add_gml_obj}
+\alias{input_add_gml_obj}
+\title{Adds an empty gml class object to a ogs6 class object input list}
+\usage{
+input_add_gml_obj(ogs6_obj, geometry_name)
+}
+\arguments{
+\item{ogs6_obj}{The ogs6 object the gml class object should be added to}
+
+\item{geometry_name}{The name of the geometry specified by the gml class object}
+}
+\description{
+Adds an empty gml class object to a ogs6 class object input list
+}
diff --git a/man/input_add_gml_points.Rd b/man/input_add_gml_points.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..ccd4ab15230639560e4b92fe7ea592b09ddca7cc
--- /dev/null
+++ b/man/input_add_gml_points.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_gml.R
+\name{input_add_gml_points}
+\alias{input_add_gml_points}
+\title{Adds gml points to a ogs6 class object}
+\usage{
+input_add_gml_points(ogs6_obj, gml_points)
+}
+\arguments{
+\item{ogs6_obj}{A ogs6 class object}
+
+\item{gml_points}{A tibble of gml points}
+}
+\description{
+Adds gml points to a ogs6 class object
+}
diff --git a/man/input_add_gml_polylines.Rd b/man/input_add_gml_polylines.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..6258d91e53279f97e10b0fc72e140fd1519e1d25
--- /dev/null
+++ b/man/input_add_gml_polylines.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_gml.R
+\name{input_add_gml_polylines}
+\alias{input_add_gml_polylines}
+\title{Adds gml polylines to a ogs6 class object}
+\usage{
+input_add_gml_polylines(ogs6_obj, gml_polylines)
+}
+\arguments{
+\item{ogs6_obj}{A ogs6 class object}
+
+\item{gml_polylines}{A list of gml polylines}
+}
+\description{
+Adds gml polylines to a ogs6 class object
+}
diff --git a/man/input_add_gml_surfaces.Rd b/man/input_add_gml_surfaces.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..389611e26e202349fedb279cf055717fdf800fe8
--- /dev/null
+++ b/man/input_add_gml_surfaces.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_gml.R
+\name{input_add_gml_surfaces}
+\alias{input_add_gml_surfaces}
+\title{Adds gml surfaces to a ogs6 class object}
+\usage{
+input_add_gml_surfaces(ogs6_obj, gml_surfaces)
+}
+\arguments{
+\item{ogs6_obj}{A ogs6 class object}
+
+\item{gml_surfaces}{A list of gml surfaces}
+}
+\description{
+Adds gml surfaces to a ogs6 class object
+}
diff --git a/man/input_add_vtu_appended_data.Rd b/man/input_add_vtu_appended_data.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..822f2cc11d0dc66c73660bf2660b31cf2f935286
--- /dev/null
+++ b/man/input_add_vtu_appended_data.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_vtu.R
+\name{input_add_vtu_appended_data}
+\alias{input_add_vtu_appended_data}
+\title{input_add_vtu_appended_data}
+\usage{
+input_add_vtu_appended_data(ogs6_obj, encoding, data)
+}
+\arguments{
+\item{ogs6_obj}{The ogs6 object the .vtu AppendedData should be added to}
+
+\item{encoding}{How the AppendedData is encoded}
+
+\item{data}{The actual data in the specified encoding}
+}
+\description{
+Adds .vtu AppendedData to a ogs6 class object
+}
diff --git a/man/input_add_vtu_obj.Rd b/man/input_add_vtu_obj.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..dfda2b6d9eb9ea4f44fb8df6b68b744042532c65
--- /dev/null
+++ b/man/input_add_vtu_obj.Rd
@@ -0,0 +1,31 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_vtu.R
+\name{input_add_vtu_obj}
+\alias{input_add_vtu_obj}
+\title{input_add_vtu_obj}
+\usage{
+input_add_vtu_obj(
+  ogs6_obj,
+  type,
+  version,
+  byte_order,
+  header_type,
+  compressor = NULL
+)
+}
+\arguments{
+\item{ogs6_obj}{The ogs6 object the vtu class object should be added to}
+
+\item{type}{The type of the .vtu file (e. g. "UnstructuredGrid")}
+
+\item{version}{The version of the .vtu file (e. g. 1.0)}
+
+\item{byte_order}{Either "LittleEndian" or "BigEndian"}
+
+\item{header_type}{The header type (e. g. "UInt32")}
+
+\item{compressor}{Optional: The compressor to be used}
+}
+\description{
+Adds an empty vtu class object to a ogs6 class object input.
+}
diff --git a/man/input_add_vtu_unstructured_grid.Rd b/man/input_add_vtu_unstructured_grid.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..53a479c1a8865bff3712a21e90b05e95dc265c8a
--- /dev/null
+++ b/man/input_add_vtu_unstructured_grid.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_vtu.R
+\name{input_add_vtu_unstructured_grid}
+\alias{input_add_vtu_unstructured_grid}
+\title{input_add_vtu_unstructured_grid}
+\usage{
+input_add_vtu_unstructured_grid(ogs6_obj, piece, field_data = NULL)
+}
+\arguments{
+\item{ogs6_obj}{The ogs6 object the .vtu UnstructuredGrid should be added to}
+
+\item{piece}{A Piece (WIP)}
+
+\item{field_data}{FieldData (WIP)}
+}
+\description{
+Adds .vtu UnstructuredGrid to a ogs6 class object
+}
diff --git a/man/new_data_array.Rd b/man/new_data_array.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..6d01975320c0c4a976eab02b537885f4e33f7693
--- /dev/null
+++ b/man/new_data_array.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_vtu.R
+\name{new_data_array}
+\alias{new_data_array}
+\title{new_data_array}
+\usage{
+new_data_array(
+  type,
+  name,
+  format,
+  range_min,
+  range_max,
+  number_of_components = NULL,
+  number_of_tuples = NULL,
+  offset = NULL,
+  data = NULL
+)
+}
+\description{
+S3 class constructor, returns S3 class describing a .vtu DataArray element
+}
diff --git a/man/new_gml.Rd b/man/new_gml.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..6a1d6cec3937f2f4c29e517c0431e382ee7d3a30
--- /dev/null
+++ b/man/new_gml.Rd
@@ -0,0 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_gml.R
+\name{new_gml}
+\alias{new_gml}
+\title{Class describing the gml file and any parameters defined in one}
+\usage{
+new_gml(geometry_name = NULL, points = NULL, polylines = NULL, surfaces = NULL)
+}
+\description{
+Class describing the gml file and any parameters defined in one
+}
diff --git a/man/new_ogs6.Rd b/man/new_ogs6.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..dd3a9112b935d488bfd2be5c68bf5afc838b850a
--- /dev/null
+++ b/man/new_ogs6.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ogs6.R
+\name{new_ogs6}
+\alias{new_ogs6}
+\title{Constructor for the ogs6 base class}
+\usage{
+new_ogs6(
+  sim_io = list(input = list(), output = list()),
+  sim_name = character(),
+  sim_id = integer(),
+  sim_path = character()
+)
+}
+\arguments{
+\item{sim_io}{...}
+
+\item{sim_name}{A string value representing the simulation name}
+
+\item{sim_id}{An integer value representing the simulation ID}
+
+\item{sim_path}{A string value describing the path where the IO files will be saved}
+}
+\description{
+Constructor for the ogs6 base class
+}
diff --git a/man/new_r2ogs6_prj_medium_phase.Rd b/man/new_r2ogs6_prj_medium_phase.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f42ff0a1c37d0bd83e515f500376c48a46f46c9b
--- /dev/null
+++ b/man/new_r2ogs6_prj_medium_phase.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_prj.R
+\name{new_r2ogs6_prj_medium_phase}
+\alias{new_r2ogs6_prj_medium_phase}
+\title{Defines a .prj medium phase element}
+\usage{
+new_r2ogs6_prj_medium_phase(type = character(), properties = list())
+}
+\arguments{
+\item{type}{A string specifying the medium type (valid types: ...)}
+
+\item{properties}{A list of properties (see ?r2ogs6_property for more info)}
+}
+\description{
+Defines a .prj medium phase element
+}
diff --git a/man/new_vtu.Rd b/man/new_vtu.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..74156edbecc54e67392443ee3ffc1eb3152a13cb
--- /dev/null
+++ b/man/new_vtu.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/input_add_vtu.R
+\name{new_vtu}
+\alias{new_vtu}
+\title{new_vtu}
+\usage{
+new_vtu(type, version, byte_order, header_type, compressor = NULL)
+}
+\arguments{
+\item{type}{The type of the vtu file (e. g. "UnstructuredGrid")}
+
+\item{version}{The version of the .vtu file (e. g. 1.0)}
+
+\item{byte_order}{Either "LittleEndian" or "BigEndian"}
+
+\item{header_type}{The header type (e. g. "UInt32")}
+
+\item{compressor}{Optional: The compressor to be used}
+}
+\description{
+S3 class constructor, returns S3 class describing the .vtu file and any parameters defined in it
+}
diff --git a/man/points_to_xml.Rd b/man/points_to_xml.Rd
index 3028ad0f44121cb6b084a15b4e556fb415e91467..25f9a3d8bf348c6552279161ddbd672d58217825 100644
--- a/man/points_to_xml.Rd
+++ b/man/points_to_xml.Rd
@@ -1,5 +1,5 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml.R
+% Please edit documentation in R/export_gml.R
 \name{points_to_xml}
 \alias{points_to_xml}
 \title{Turns a tibble of points into an XML node}
diff --git a/man/polylines_to_xml.Rd b/man/polylines_to_xml.Rd
index 153a155fffe42d4469a7766235cab8d5fd5a28fc..0ab088a225d9b569ac920ff5a5c15239b5435cd6 100644
--- a/man/polylines_to_xml.Rd
+++ b/man/polylines_to_xml.Rd
@@ -1,13 +1,13 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml.R
+% Please edit documentation in R/export_gml.R
 \name{polylines_to_xml}
 \alias{polylines_to_xml}
 \title{Turns a list of polylines into an XML node}
 \usage{
-polylines_to_xml(polyline_list)
+polylines_to_xml(polylines)
 }
 \arguments{
-\item{polyline_list}{The specified list}
+\item{polylines}{A list of polylines}
 }
 \value{
 An XML node containing the polylines
diff --git a/man/prj_data_to_xml.Rd b/man/prj_data_to_xml.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..4c7e129e37a2fbf48c9fbd207b5e18d257e9a3c8
--- /dev/null
+++ b/man/prj_data_to_xml.Rd
@@ -0,0 +1,14 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/export_prj.R
+\name{prj_data_to_xml}
+\alias{prj_data_to_xml}
+\title{Wrapper function to create a .prj XML document based on the user input data}
+\usage{
+prj_data_to_xml(prj_obj)
+}
+\arguments{
+\item{prj_obj}{.}
+}
+\description{
+Wrapper function to create a .prj XML document based on the user input data
+}
diff --git a/man/surfaces_to_xml.Rd b/man/surfaces_to_xml.Rd
index 0715a6674f8faab5fc230e458a73919ec27e8fd3..c0a376a23ff17385708b1be8b69a3bbd119e41dc 100644
--- a/man/surfaces_to_xml.Rd
+++ b/man/surfaces_to_xml.Rd
@@ -1,13 +1,13 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/create_gml.R
+% Please edit documentation in R/export_gml.R
 \name{surfaces_to_xml}
 \alias{surfaces_to_xml}
 \title{Turns a list of surfaces into an XML node}
 \usage{
-surfaces_to_xml(surfaces_list)
+surfaces_to_xml(surfaces)
 }
 \arguments{
-\item{surfaces_list}{The specified list}
+\item{surfaces}{A list of surfaces}
 }
 \value{
 An XML node containing the surfaces
diff --git a/man/validate_gml_data.Rd b/man/validate_gml_data.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f26bf31d8383f612ff5509e2bfa906b9e6cea5aa
--- /dev/null
+++ b/man/validate_gml_data.Rd
@@ -0,0 +1,14 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/validate_gml.R
+\name{validate_gml_data}
+\alias{validate_gml_data}
+\title{validate_gml_data}
+\usage{
+validate_gml_data(gml_obj)
+}
+\arguments{
+\item{gml_obj}{A gml class object}
+}
+\description{
+Checks if the defined gml class object isn't empty
+}
diff --git a/man/validate_ogs6.Rd b/man/validate_ogs6.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..81ae71869a2d7d3b4c192a88947aa3af415339dd
--- /dev/null
+++ b/man/validate_ogs6.Rd
@@ -0,0 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ogs6.R
+\name{validate_ogs6}
+\alias{validate_ogs6}
+\title{Validating functions for an ogs6 class object (to be run before a simulation is started)}
+\usage{
+validate_ogs6(ogs6_obj)
+}
+\description{
+Validating functions for an ogs6 class object (to be run before a simulation is started)
+}
diff --git a/man/validate_points.Rd b/man/validate_points.Rd
index f7819198cb1510d6ab0511840598843d86c6dc0c..2c0ab7fe925e42378a78391d1d10bec41f5291e7 100644
--- a/man/validate_points.Rd
+++ b/man/validate_points.Rd
@@ -2,9 +2,7 @@
 % Please edit documentation in R/validate_gml.R
 \name{validate_points}
 \alias{validate_points}
-\title{Checks if the input is a tibble, if this tibble has the right number of elements,
-if those elements are named correctly, if the lists in the tibble are of the same length and
-if there is any overlapping points or duplicate point names}
+\title{validate_points}
 \usage{
 validate_points(gml_points)
 }
@@ -13,6 +11,5 @@ validate_points(gml_points)
 }
 \description{
 Checks if the input is a tibble, if this tibble has the right number of elements,
-if those elements are named correctly, if the lists in the tibble are of the same length and
-if there is any overlapping points or duplicate point names
+if those elements are named correctly and if there are any overlapping points or duplicate point names
 }
diff --git a/man/validate_polylines.Rd b/man/validate_polylines.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..78fdd47299c91f881f409251e5b4a95acf672cdc
--- /dev/null
+++ b/man/validate_polylines.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/validate_gml.R
+\name{validate_polylines}
+\alias{validate_polylines}
+\title{validate_polylines}
+\usage{
+validate_polylines(gml_polylines)
+}
+\arguments{
+\item{gml_polylines}{A list consisting of other lists}
+}
+\description{
+Checks if the input is a list, if this list consists of other lists and
+if those child lists have the correct structure (length of 2, first element is a string named
+'name', second element is a numeric vector)
+}
diff --git a/man/validate_surface_elements.Rd b/man/validate_surface_elements.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..3720ee714a0106f3bace3c1714155c485676353a
--- /dev/null
+++ b/man/validate_surface_elements.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/validate_gml.R
+\name{validate_surface_elements}
+\alias{validate_surface_elements}
+\title{validate_surface_elements}
+\usage{
+validate_surface_elements(gml_surface_element_1, gml_surface_element_2)
+}
+\arguments{
+\item{gml_surface_element_1}{A numerical vector of length 3}
+
+\item{gml_surface_element_2}{A numerical vector of length 3}
+}
+\description{
+Helper function, checks if two numerical vectors of length 3 (two surface elements)
+each consist of 3 different elements and also have exactly 2 matching elements between them
+which means they describe a valid surface. You can think of the two vectors as two triangles,
+and the two triangles together form a square which is our surface.
+}
diff --git a/man/validate_surfaces.Rd b/man/validate_surfaces.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..9baad4855002908407083047f6d3f14d31e059b0
--- /dev/null
+++ b/man/validate_surfaces.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/validate_gml.R
+\name{validate_surfaces}
+\alias{validate_surfaces}
+\title{validate_surfaces}
+\usage{
+validate_surfaces(gml_surfaces)
+}
+\arguments{
+\item{gml_surfaces}{A list consisting of other lists}
+}
+\description{
+Checks if the input is a list, if this list consists of other lists and
+if those child lists have the correct structure (length of 3, first element is a string named
+'name', second and third element are numeric vectors)
+}
diff --git a/man/vtu_appended_data_to_xml-open-paren-WIP-close-paren.Rd b/man/vtu_appended_data_to_xml-open-paren-WIP-close-paren.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..08012d7936ab58787e7b2dbcf5c9f606bafe92fa
--- /dev/null
+++ b/man/vtu_appended_data_to_xml-open-paren-WIP-close-paren.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/export_vtu.R
+\name{vtu_appended_data_to_xml
+(WIP)}
+\alias{vtu_appended_data_to_xml
+(WIP)}
+\alias{vtu_appended_data_to_xml}
+\title{vtu_appended_data_to_xml}
+\usage{
+vtu_appended_data_to_xml(appended_data)
+}
+\arguments{
+\item{appended_data}{A list object consisting of 2 elements named 'data' and 'encoding'}
+}
+\description{
+vtu_appended_data_to_xml
+}
diff --git a/man/vtu_data_to_xml.Rd b/man/vtu_data_to_xml.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..9fb16efc13bffb807cbb7333a8b8890dd1788735
--- /dev/null
+++ b/man/vtu_data_to_xml.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/export_vtu.R
+\name{vtu_data_to_xml}
+\alias{vtu_data_to_xml}
+\title{Wrapper function to create a .vtu XML document based on the user input data}
+\usage{
+vtu_data_to_xml(vtu_obj)
+}
+\arguments{
+\item{vtu_obj}{A vtu class object}
+}
+\value{
+A XML document ready for export to a file
+}
+\description{
+Wrapper function to create a .vtu XML document based on the user input data
+}
diff --git a/man/vtu_piece_to_xml.Rd b/man/vtu_piece_to_xml.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..cc11b2b814d81956a21e9f04ba0161a30e5416bd
--- /dev/null
+++ b/man/vtu_piece_to_xml.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/export_vtu.R
+\name{vtu_piece_to_xml}
+\alias{vtu_piece_to_xml}
+\title{(WIP, change input parameter to piece!!)}
+\usage{
+vtu_piece_to_xml(
+  number_of_points,
+  number_of_cells,
+  point_data,
+  cell_data,
+  points,
+  cells
+)
+}
+\arguments{
+\item{piece}{A list consisting of lists of data_array class objects}
+}
+\description{
+(WIP, change input parameter to piece!!)
+}
diff --git a/my_experimental_cube.gml b/test.gml
similarity index 100%
rename from my_experimental_cube.gml
rename to test.gml
diff --git a/tests/testthat/test-create_gml.R b/tests/testthat/test-create_gml.R
deleted file mode 100644
index db42d82832af6897a68796ba0e0015e9e133a607..0000000000000000000000000000000000000000
--- a/tests/testthat/test-create_gml.R
+++ /dev/null
@@ -1,95 +0,0 @@
-test_that("GMLPoint object is initialized correctly", {
-  gml_point <- GMLPoint$new(1, c(2, 3, 4), TRUE)
-
-  expect_equal(gml_point$id, 1)
-  expect_equal(gml_point$coordinates, c(2, 3, 4))
-  expect_equal(gml_point$dim, 3)
-  expect_equal(gml_point$is_origin, TRUE)
-
-  expect_equal(gml_point$as_list(), list(id = 1, x = 2, y = 3, z = 4, name = "origin"))
-  expect_equal(gml_point$as_node(), list(point = structure(list(), id = 1,
-                                                           x = 2, y = 3, z = 4, name = "origin")))
-})
-
-test_that("GMLPoints object is initialized correctly", {
-  gml_point_1 <- GMLPoint$new(is_origin = TRUE)
-  gml_point_2 <- GMLPoint$new(1, c(0, 0, 1))
-  gml_points <- GMLPoints$new(c(gml_point_1, gml_point_2))
-
-  expect_equal(gml_points$ids, c(gml_point_1$id, gml_point_2$id))
-  expect_equal(gml_points$as_list(), list(point = gml_point_1$as_list(), point = gml_point_2$as_list()))
-  expect_equal(gml_points$as_node(), list(points = c(gml_point_1$as_node(), gml_point_2$as_node())))
-})
-
-
-test_that("GMLPolyline object is initialized correctly", {
-  gml_polyline <- GMLPolyline$new(0, "my_line", 1, 2)
-
-  expect_equal(gml_polyline$id, 0)
-  expect_equal(gml_polyline$name, "my_line")
-  expect_equal(gml_polyline$point1, 1)
-  expect_equal(gml_polyline$point2, 2)
-
-  expect_equal(gml_polyline$as_node(), list(polyline = structure(list(pnt = list(1), pnt = list(2)),
-                                                                 id = 0, name = "my_line")))
-})
-
-test_that("GMLPolylines object is initialized correctly", {
-  gml_polyline_1 <- GMLPolyline$new(0, "line_1", 1, 2)
-  gml_polyline_2 <- GMLPolyline$new(1, "line_2", 1, 3)
-  gml_polyline_3 <- GMLPolyline$new(1, "line_3", 1, 3)
-  gml_polylines <- GMLPolylines$new(c(gml_polyline_1, gml_polyline_2))
-
-  expect_equal(gml_polylines$ids, c(gml_polyline_1$id, gml_polyline_2$id))
-  expect_equal(gml_polylines$gml_polylines, c(gml_polyline_1, gml_polyline_2))
-
-  expect_error(gml_polylines$validate_ids(c(gml_polyline_2, gml_polyline_3)))
-  expect_error(gml_polylines$validate_polylines(c(gml_polyline_2, gml_polyline_3)))
-  expect_equal(gml_polylines$as_node(), list(polylines = c(gml_polyline_1$as_node(), gml_polyline_2$as_node())))
-})
-
-
-test_that("GMLSurfaceElement object is initialized correctly", {
-  gml_surface_element <- GMLSurfaceElement$new(0, 1, 3)
-
-  expect_equal(gml_surface_element$p1, 0)
-  expect_equal(gml_surface_element$p2, 1)
-  expect_equal(gml_surface_element$p3, 3)
-
-  expect_error(GMLSurfaceElement$new(0, 0, 3))
-  expect_equal(gml_surface_element$as_list(), list(p1 = 0, p2 = 1, p3 = 3))
-  expect_equal(gml_surface_element$as_node(), list(element = structure(list(), p1 = 0, p2 = 1, p3 = 3)))
-})
-
-test_that("GMLSurface object is initialized correctly", {
-  gml_surface_element_1 <- GMLSurfaceElement$new(0, 1, 3)
-  gml_surface_element_2 <- GMLSurfaceElement$new(1, 3, 2)
-  gml_surface_element_3 <- GMLSurfaceElement$new(3, 0, 1)
-  gml_surface <- GMLSurface$new(0, "my_surface", gml_surface_element_1, gml_surface_element_2)
-
-  expect_equal(gml_surface$id, 0)
-  expect_equal(gml_surface$name, "my_surface")
-  expect_equal(gml_surface$element1, gml_surface_element_1)
-  expect_equal(gml_surface$element2, gml_surface_element_2)
-
-  expect_error(GMLSurface$new(0, "my_surface", gml_surface_element_1, gml_surface_element_3))
-  expect_equal(gml_surface$as_node(), list(surface =
-                                                     structure(c(gml_surface_element_1$as_node(),
-                                                                 gml_surface_element_2$as_node()),
-                                                               id = 0, name = "my_surface")))
-})
-
-test_that("GMLSurfaces object is initialized correctly", {
-  gml_surface_element_1 <- GMLSurfaceElement$new(0, 1, 3)
-  gml_surface_element_2 <- GMLSurfaceElement$new(1, 3, 2)
-  gml_surface_element_3 <- GMLSurfaceElement$new(4, 5, 6)
-  gml_surface_element_4 <- GMLSurfaceElement$new(5, 6, 7)
-  gml_surface_1 <- GMLSurface$new(0, "surface_1", gml_surface_element_1, gml_surface_element_2)
-  gml_surface_2 <- GMLSurface$new(1, "surface_2", gml_surface_element_3, gml_surface_element_4)
-  gml_surface_3 <- GMLSurface$new(1, "surface_3", gml_surface_element_3, gml_surface_element_4)
-  gml_surfaces <- GMLSurfaces$new(c(gml_surface_1, gml_surface_2))
-
-  expect_equal(gml_surfaces$ids, c(gml_surface_1$id, gml_surface_2$id))
-  expect_error(gml_surfaces$validate_ids(c(gml_surface_2, gml_surface_3)))
-  expect_equal(gml_surfaces$as_node(), list(surfaces = c(gml_surface_1$as_node(), gml_surface_2$as_node())))
-})
diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R
index 0e8f85b17e67274e5d513045dfd1647acd5cbd0d..c2aa95b2cf41ed5532a711c64b6c7ee6d6c29d26 100644
--- a/tests/testthat/test-utils.R
+++ b/tests/testthat/test-utils.R
@@ -1,19 +1,42 @@
 
-test_that("get_xml_encoding returns valid XML encoding", {
-  expect_equal(get_xml_encoding(system.file("extdata", "flow_free_expansion.prj", package = "r2ogs6")), "ISO-8859-1")
+test_that("add_opt_attr adds an optional attribute to a node list", {
+
+    test_node_1 <- list(test = structure(list()))
+
+    test_node_1 <- add_opt_attr(test_node_1, 42, "meaning_of_life")
+
+    expect_equal(attributes(test_node_1[[1]])[["meaning_of_life"]], 42)
+
+    test_node_1 <- add_opt_attr(test_node_1, NULL, "null")
+    expect_equal(length(attributes(test_node_1[[1]])), 1)
+
 })
-#> Test passed
 
-test_that("create_blank_prj writes .prj file with empty XML text nodes", {
-  template_file <- system.file("extdata", "flow_free_expansion_template.prj", package = "r2ogs6")
-  create_template_prj(system.file("extdata", "flow_free_expansion.prj", package = "r2ogs6"), template_file)
 
-  xml_templ <- xml2::read_xml(template_file)
+test_that("add_opt_child adds an optional child to a node list", {
+
+    test_node_1 <- list(test = structure(list(), attr_1 = "hi", attr_2 = "there"))
+    test_node_2 <- list(test = structure(list(), attr_1 = "hi", attr_2 = "there"))
+
+    test_node_1 <- add_opt_child(test_node_1, 42)
+
+    expect_equal(test_node_1[[1]][[1]], 42)
 
-  #Get text nodes
-  text_nodes<-xml2::xml_find_all(xml_templ, "//text()")
+    expect_error(add_opt_child(test_node_1, 42))
+    expect_error(add_opt_child(test_node_1, 42, "number"))
+
+
+    test_node_2 <- add_opt_child(test_node_2, 42, "number")
+    test_node_2 <- add_opt_child(test_node_2, 42, "number")
+    test_node_2 <- add_opt_child(test_node_2, NULL, "null")
+
+
+    expect_equal(length(test_node_2[[1]]), 2)
+    expect_equal(length(names(test_node_2[[1]])), 2)
+
+    expect_error(add_opt_child(test_node_2, 42))
 
-  #There should not be any text left in the text nodes
-  expect_equal(xml2::xml_text(text_nodes), character(0))
 })
-#> Test passed
+
+
+
diff --git a/tests/testthat/test-validate_gml.R b/tests/testthat/test-validate_gml.R
index 2ad65b7565cab5dc0c4bb9450eb2bfb67ae82ec9..71e5ffc945dcbbf20a59947d2825ced050040b25 100644
--- a/tests/testthat/test-validate_gml.R
+++ b/tests/testthat/test-validate_gml.R
@@ -1,4 +1,4 @@
-test_that("validate_points function checks ...", {
+test_that("validate_points function checks if ...", {
 
     point_list <- list(x = c(0, 0), y = c(1, 1), z = c(0, 1))
 
@@ -22,3 +22,42 @@ test_that("validate_points function checks ...", {
     expect_invisible(validate_points(point_tibble_val))
     expect_invisible(validate_points(point_tibble_val_2))
 })
+
+
+test_that("validate_polylines function checks if...", {
+
+    polyline_tibble <- tibble::tibble(name = "tibble", polyline = c(c(1, 2)))
+
+    #Check class (should expect a list, not a tibble)
+    expect_error(validate_polylines(polyline_tibble))
+
+    polyline_list_inv_0 <- list(name = "missing_polyline_list", c(1,2))
+    polyline_list_inv_1 <- list(list(name = "wrong_length", c(0, 1, 2), c(1, 2)))
+    polyline_list_inv_2 <- list(list(name = 42, c(1, 2)))
+    polyline_list_inv_3 <- list(list(name = "wrong_points", c("this", "should", "fail")))
+
+    expect_error(validate_polylines(polyline_list_inv_0))
+    expect_error(validate_polylines(polyline_list_inv_1))
+    expect_error(validate_polylines(polyline_list_inv_2))
+    expect_error(validate_polylines(polyline_list_inv_3))
+
+    polyline_list_val_0 <- list(list(name = "cool", c(1, 2)))
+    polyline_list_val_1 <- list(list(name = "also cool", c(1, 2, 4, 5, 1)))
+
+    expect_invisible(validate_polylines(polyline_list_val_0))
+    expect_invisible(validate_polylines(polyline_list_val_1))
+
+    #...(WIP)
+
+})
+
+
+test_that("validate_surfaces function checks if...", {
+
+    surface_tibble <- tibble::tibble(name = "tibble", surface = c(c(0, 1, 2), c(1, 2, 3)))
+
+    #Check class (should expect a list, not a tibble)
+    expect_error(validate_surfaces(surface_tibble))
+
+    #...(WIP)
+})
\ No newline at end of file