diff --git a/gempy/core/data/grid.py b/gempy/core/data/grid.py
index eb8768916..4500afd6c 100644
--- a/gempy/core/data/grid.py
+++ b/gempy/core/data/grid.py
@@ -254,7 +254,11 @@ def _update_values(self):
         if self.GridTypes.CENTERED in self.active_grids:
             if self.centered_grid is None: raise AttributeError('Centered grid is active but not defined')
             values.append(self.centered_grid.values)
-
+        
+        # make sure values is not empty
+        if len(values) == 0:
+            return self.values
+        
         self.values = np.concatenate(values)
 
         return self.values
diff --git a/test/test_modules/test_marching_cubes.py b/test/test_modules/test_marching_cubes.py
new file mode 100644
index 000000000..270aa6fa6
--- /dev/null
+++ b/test/test_modules/test_marching_cubes.py
@@ -0,0 +1,180 @@
+import numpy as np
+from gempy_engine.core.data.raw_arrays_solution import RawArraysSolution
+
+import gempy as gp
+from gempy.core.data.enumerators import ExampleModel
+from gempy.core.data.grid_modules import RegularGrid
+from gempy.optional_dependencies import require_gempy_viewer
+
+from skimage import measure
+
+PLOT = True
+
+def marching_cubes(block, elements, spacing, extent):
+    """
+        Extract the surface meshes using marching cubes
+        Args:
+            block (np.array): The block to extract the surface meshes from.
+            elements (list): IDs of unique structural elements in model
+            spacing (tuple): The spacing between grid points in the block.
+
+        Returns:
+            mc_vertices (list): Vertices of the surface meshes.
+            mc_edges (list): Edges of the surface meshes.
+        """
+
+    # Extract the surface meshes using marching cubes
+    mc_vertices = []
+    mc_edges = []
+    for i in range(0, len(elements)):
+        verts, faces, _, _ = measure.marching_cubes(block, i,
+                                                    spacing=spacing)
+        mc_vertices.append(verts + [extent[0], extent[2], extent[4]])
+        mc_edges.append(faces)
+    return mc_vertices, mc_edges
+
+
+def test_marching_cubes_implementation():
+    model = gp.generate_example_model(ExampleModel.COMBINATION, compute_model=False)
+
+    # Change the grid to only be the dense grid
+    dense_grid: RegularGrid = RegularGrid(
+        extent=model.grid.extent,
+        resolution=np.array([20, 20, 20])
+    )
+
+    model.grid.dense_grid = dense_grid
+    gp.set_active_grid(
+        grid=model.grid,
+        grid_type=[model.grid.GridTypes.DENSE],
+        reset=True
+    )
+
+    model.interpolation_options.evaluation_options.mesh_extraction = False  # * Not extracting the mesh with dual contouring
+    gp.compute_model(model)
+
+    # Assert
+    assert model.solutions.block_solution_type == RawArraysSolution.BlockSolutionType.DENSE_GRID
+    assert model.solutions.dc_meshes is None
+    arrays = model.solutions.raw_arrays  # * arrays is equivalent to gempy v2 solutions
+
+    assert arrays.scalar_field_matrix.shape == (3, 8_000)  # * 3 surfaces, 8000 points
+
+    # TODO: Maybe to complicated because it includes accounting for faults, multiple elements in groups
+    #  and transformation to real coordinates
+
+    # Empty lists to store vertices and edges
+    mc_vertices = []
+    mc_edges = []
+
+    # Boolean list of fault groups
+    faults = model.structural_frame.group_is_fault
+
+    # MC for faults, directly on fault block not on scalar field
+    if faults is not None:
+        # TODO: This should also use the scalar fields probably
+        for i in np.unique(model.solutions.raw_arrays.fault_block)[:-1]:
+            fault_block = model.solutions.raw_arrays.fault_block.reshape(model.grid.regular_grid.resolution)
+            verts, faces, _, _ = measure.marching_cubes(fault_block,
+                                                        i,
+                                                        spacing=(model.grid.regular_grid.dx,
+                                                                 model.grid.regular_grid.dy,
+                                                                 model.grid.regular_grid.dz))
+            mc_vertices.append(verts + [model.grid.regular_grid.extent[0],
+                                        model.grid.regular_grid.extent[2],
+                                        model.grid.regular_grid.extent[4]])
+            mc_edges.append(faces)
+    else:
+        pass
+
+    # Extract scalar field values for elements
+    scalar_values = model.solutions.raw_arrays.scalar_field_at_surface_points
+
+    # Get indices of non fault elements
+    if faults is not None:
+        false_indices = [i for i, fault in enumerate(faults) if not fault]
+    else:
+        false_indices = np.arange(len(model.structural_frame.structural_groups))
+
+    # Extract marching cubes for non fault elements
+    for idx in false_indices:
+
+        # Get correct scalar field for structural group
+        scalar_field = model.solutions.raw_arrays.scalar_field_matrix[idx].reshape(model.grid.regular_grid.resolution)
+
+        # Extract marching cubes for each scalar value for all elements of a group
+        for i in range(len(scalar_values[idx])):
+            verts, faces, _, _ = measure.marching_cubes(scalar_field, scalar_values[idx][i],
+                                                        spacing=(model.grid.regular_grid.dx,
+                                                                 model.grid.regular_grid.dy,
+                                                                 model.grid.regular_grid.dz))
+
+            mc_vertices.append(verts + [model.grid.regular_grid.extent[0],
+                                        model.grid.regular_grid.extent[2],
+                                        model.grid.regular_grid.extent[4]])
+            mc_edges.append(faces)
+
+    # Reorder everything correctly if faults exist
+    # TODO: All of the following is just complicated code to reorder the elements to match the order of the elements
+    #  in the structural frame, probably unnecessary in gempy strucuture
+    #
+    # if faults is not None:
+    #
+    #     # TODO: This is a very convoluted way to get a boolean list of faults per element
+    #     bool_list = np.zeros(4, dtype=bool)
+    #     for i in range(len(model.structural_frame.structural_groups)):
+    #         print(i)
+    #         if model.structural_frame.group_is_fault[i]:
+    #             for j in range(len(model.structural_frame.structural_groups[i].elements)):
+    #                 bool_list[i + j] = True
+    #         if not model.structural_frame.group_is_fault[i]:
+    #             for k in range(len(model.structural_frame.structural_groups[i].elements)):
+    #                 bool_list[i + k] = False
+    #
+    #     true_count = sum(bool_list)
+    #
+    #     # Split arr_list into two parts
+    #     true_elements_vertices = mc_vertices[:true_count]
+    #     false_elements_vertices = mc_vertices[true_count:]
+    #     true_elements_edges = mc_edges[:true_count]
+    #     false_elements_edges = mc_edges[true_count:]
+    #
+    #     # Create a new list to store reordered elements
+    #     mc_vertices = []
+    #     mc_edges = []
+    #
+    #     # Iterator for both true and false elements
+    #     true_idx, false_idx = 0, 0
+    #
+    #     # Populate reordered_list based on bool_list
+    #     for is_true in bool_list:
+    #         if is_true:
+    #             mc_vertices.append(true_elements_vertices[true_idx] + [model.grid.regular_grid.extent[0],
+    #                                                                    model.grid.regular_grid.extent[2],
+    #                                                                    model.grid.regular_grid.extent[4]])
+    #             mc_edges.append(true_elements_edges[true_idx])
+    #             true_idx += 1
+    #         else:
+    #             mc_vertices.append(false_elements_vertices[false_idx] + [model.grid.regular_grid.extent[0],
+    #                                                                      model.grid.regular_grid.extent[2],
+    #                                                                      model.grid.regular_grid.extent[4]])
+    #             mc_edges.append(false_elements_edges[false_idx])
+    #             false_idx += 1
+
+    if PLOT:
+        gpv = require_gempy_viewer()
+        # gtv: gpv.GemPyToVista = gpv.plot_3d(model, show_data=True, image=True)
+        import pyvista as pv
+        # pyvista_plotter: pv.Plotter = gtv.p
+
+        # TODO: This opens interactive window as of now
+        pyvista_plotter = pv.Plotter()
+
+        # Add the meshes to the plot
+        for i in range(len(mc_vertices)):
+            pyvista_plotter.add_mesh(
+                pv.PolyData(mc_vertices[i],
+                            np.insert(mc_edges[i], 0, 3, axis=1).ravel()),
+                color='blue')
+
+        pyvista_plotter.show()