diff --git a/dune/gfe/cosseratvtkwriter.hh b/dune/gfe/cosseratvtkwriter.hh
index d814d73bb8e9552625f38cee5dedcc902719ec48..4fe9fffe1b0d05f7b1cf2b5f2e0290b86f747a0a 100644
--- a/dune/gfe/cosseratvtkwriter.hh
+++ b/dune/gfe/cosseratvtkwriter.hh
@@ -6,10 +6,15 @@
 #include <dune/grid/io/file/vtk/vtkwriter.hh>
 #include <dune/grid/io/file/vtk/pvtuwriter.hh>
 
+#include <dune/istl/bvector.hh>
+
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 #include <dune/functions/functionspacebases/interpolate.hh>
 #include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
 
+#include <dune/vtk/vtkwriter.hh>
+#include <dune/vtk/datacollectors/lagrangedatacollector.hh>
+
 #include <dune/gfe/vtkfile.hh>
 #include <dune/gfe/spaces/productmanifold.hh>
 #include <dune/gfe/spaces/realtuple.hh>
@@ -383,184 +388,63 @@ public:
     vtkFile.write(filename);
   }
 
-  /** \brief Write a configuration given with respect to a scalar function space basis
+  /** \brief Write a Cosserat configuration as VTK file
+   *
+   * The microrotation field will be represented as the three director fields
+   *
+   * \param directorBasis The basis that will be used to represent director fields
+   * \param order The polynomial order that the data will have in the VTK file
    */
-  template <typename DisplacementBasis, typename OrientationBasis>
-  static void writeMixed(const DisplacementBasis& displacementBasis,
-                         const std::vector<RealTuple<double,3> >& deformationConfiguration,
-                         const OrientationBasis& orientationBasis,
-                         const std::vector<Rotation<double,3> >& orientationConfiguration,
-                         const std::string& filename)
+  template <typename DisplacementFunction, typename DirectorBasis>
+  static void write(const GridView& gridView,
+                    const DisplacementFunction& displacement,
+                    const DirectorBasis& directorBasis,
+                    const std::vector<Rotation<double,3> >& orientationConfiguration,
+                    int order,
+                    const std::string& filename)
   {
-    assert(displacementBasis.size() == deformationConfiguration.size());
-    assert(orientationBasis.size()  == orientationConfiguration.size());
-    auto gridView = displacementBasis.gridView();
-
-    // Determine order of the displacement basis
-    auto localView = displacementBasis.localView();
-    localView.bind(*gridView.template begin<0>());
-    int order = localView.tree().finiteElement().localBasis().order();
-
-    // We only do P2 spaces at the moment
-    if (order != 2 and order != 3)
-    {
-      std::cout << "Warning: CosseratVTKWriter only supports P2 spaces -- skipping" << std::endl;
-      return;
-    }
-
-    std::vector<RealTuple<double,3> > displacementConfiguration = deformationConfiguration;
-
-    if (order == 3)
-    {
-      using namespace Dune::Functions::BasisFactory;
-
-      auto p2DeformationBasis = makeBasis(
-        gridView,
-        power<3>(
-          lagrange<2>(),
-          blockedInterleaved()
-          ));
-
-      // resample to 2nd order -- vtk can't do anything higher
-      std::vector<RealTuple<double,3> > p2DeformationConfiguration;
-
-      downsample(displacementBasis, displacementConfiguration,
-                 p2DeformationBasis, p2DeformationConfiguration);
-
-      displacementConfiguration = p2DeformationConfiguration;
-    }
-
-    std::string fullfilename = filename + ".vtu";
-
-    // Prepend rank and communicator size to the filename, if there are more than one process
-    if (gridView.comm().size() > 1)
-      fullfilename = getParallelPieceName(filename, "", gridView.comm().rank(), gridView.comm().size());
-
-    // Write the pvtu file that ties together the different parts
-    if (gridView.comm().size() > 1 && gridView.comm().rank()==0)
-    {
-      std::ofstream pvtuOutFile(getParallelName(filename, "", gridView.comm().size()));
-      Dune::VTK::PVTUWriter writer(pvtuOutFile, Dune::VTK::unstructuredGrid);
-
-      writer.beginMain();
-
-      //writer.beginPointData();
-      //writer.addArray<float>("director0", 3);
-      //writer.addArray<float>("director1", 3);
-      //writer.addArray<float>("director2", 3);
-      //writer.addArray<float>("zCoord", 1);
-      //writer.endPointData();
-
-      // dump point coordinates
-      writer.beginPoints();
-      writer.addArray("Coordinates", 3, Dune::VTK::Precision::float32);
-      writer.endPoints();
-
-      for (int i=0; i<gridView.comm().size(); i++)
-        writer.addPiece(getParallelPieceName(filename, "", i, gridView.comm().size()));
-
-      // finish main section
-      writer.endMain();
-    }
-
-    /////////////////////////////////////////////////////////////////////////////////
-    //  Write the actual vtu file
-    /////////////////////////////////////////////////////////////////////////////////
-
-    // Stupid: I can't directly get the number of Interior_Partition elements
-    size_t numElements = std::distance(gridView.template begin<0, Dune::Interior_Partition>(),
-                                       gridView.template end<0, Dune::Interior_Partition>());
-
-    std::ofstream outFile(fullfilename);
-
-    // Write header
-    outFile << "<?xml version=\"1.0\"?>" << std::endl;
-    outFile << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << std::endl;
-    outFile << "  <UnstructuredGrid>" << std::endl;
-    outFile << "    <Piece NumberOfCells=\"" << numElements << "\" NumberOfPoints=\"" << displacementConfiguration.size() << "\">" << std::endl;
-
-    // Write vertex coordinates
-    outFile << "      <Points>" << std::endl;
-    outFile << "        <DataArray type=\"Float32\" Name=\"Coordinates\" NumberOfComponents=\"3\" format=\"ascii\">" << std::endl;
-    for (size_t i=0; i<displacementConfiguration.size(); i++)
-      outFile << "          " << displacementConfiguration[i] << std::endl;
-    outFile << "        </DataArray>" << std::endl;
-    outFile << "      </Points>" << std::endl;
+    using namespace Dune;
+
+    // Create a writer object
+#if DUNE_VERSION_GTE(DUNE_VTK, 2, 10)
+    auto vtkWriter = Vtk::UnstructuredGridWriter(Vtk::LagrangeDataCollector(gridView,order));
+#else
+    Vtk::LagrangeDataCollector<GridView> dataCollector(gridView, order);
+    auto vtkWriter = VtkUnstructuredGridWriter(dataCollector);
+#endif
 
-    // Write elements
-    outFile << "      <Cells>" << std::endl;
+    // Attach the displacement field
+    vtkWriter.addPointData(displacement, Dune::VTK::FieldInfo("displacement", Dune::VTK::FieldInfo::Type::vector, 3));
 
-    outFile << "         <DataArray type=\"Int32\" Name=\"connectivity\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;
+    // Attach the director fields
+    BlockVector<FieldVector<double,3> > director0(orientationConfiguration.size());
+    BlockVector<FieldVector<double,3> > director1(orientationConfiguration.size());
+    BlockVector<FieldVector<double,3> > director2(orientationConfiguration.size());
 
-    for (const auto& element : elements(gridView, Dune::Partitions::interior))
+    for (size_t i=0; i<orientationConfiguration.size(); i++)
     {
-      localView.bind(element);
+      FieldMatrix<double,3,3> rotationMatrix;
+      orientationConfiguration[i].matrix(rotationMatrix);
 
-      outFile << "          ";
-      if (element.type().isQuadrilateral())
+      // Extract the directors, i.e., the columns of the matrix
+      for (size_t j=0; j<3; j++)
       {
-        outFile << localView.index(0) << " ";
-        outFile << localView.index(2) << " ";
-        outFile << localView.index(8) << " ";
-        outFile << localView.index(6) << " ";
-
-        outFile << localView.index(1) << " ";
-        outFile << localView.index(5) << " ";
-        outFile << localView.index(7) << " ";
-        outFile << localView.index(3) << " ";
-
-        outFile << std::endl;
+        director0[i][j] = rotationMatrix[j][0];
+        director1[i][j] = rotationMatrix[j][1];
+        director2[i][j] = rotationMatrix[j][2];
       }
     }
-    outFile << "         </DataArray>" << std::endl;
-
-    outFile << "         <DataArray type=\"Int32\" Name=\"offsets\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;
-    size_t offsetCounter = 0;
-    for (const auto& element : elements(gridView))
-    {
-      outFile << "          ";
-      if (element.type().isQuadrilateral())
-        offsetCounter += 8;
-      outFile << offsetCounter << std::endl;
-    }
-    outFile << "         </DataArray>" << std::endl;
-
-    outFile << "         <DataArray type=\"UInt8\" Name=\"types\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;
-    for (const auto& element : elements(gridView))
-    {
-      outFile << "          ";
-      if (element.type().isQuadrilateral())
-        outFile << "23" << std::endl;
-    }
-    outFile << "         </DataArray>" << std::endl;
-
-    outFile << "      </Cells>" << std::endl;
-#if 0
-    // Point data
-    outFile << "      <PointData Scalars=\"zCoord\" Vectors=\"director0\">" << std::endl;
-
-    // Z coordinate for better visualization of wrinkles
-    outFile << "        <DataArray type=\"Float32\" Name=\"zCoord\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;
-    for (size_t i=0; i<configuration.size(); i++)
-      outFile << "          " << configuration[i].r[2] << std::endl;
-    outFile << "        </DataArray>" << std::endl;
 
-    // The three director fields
-    for (size_t i=0; i<3; i++)
-    {
-      outFile << "        <DataArray type=\"Float32\" Name=\"director" << i <<"\" NumberOfComponents=\"3\" format=\"ascii\">" << std::endl;
-      for (size_t j=0; j<configuration.size(); j++)
-        outFile << "          " << configuration[j].q.director(i) << std::endl;
-      outFile << "        </DataArray>" << std::endl;
-    }
+    auto director0Function = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(directorBasis, director0);
+    auto director1Function = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(directorBasis, director1);
+    auto director2Function = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(directorBasis, director2);
 
-    outFile << "      </PointData>" << std::endl;
-#endif
-    // Write footer
-    outFile << "    </Piece>" << std::endl;
-    outFile << "  </UnstructuredGrid>" << std::endl;
-    outFile << "</VTKFile>" << std::endl;
+    vtkWriter.addPointData(director0Function, Dune::VTK::FieldInfo("director0", Dune::VTK::FieldInfo::Type::vector, 3));
+    vtkWriter.addPointData(director1Function, Dune::VTK::FieldInfo("director1", Dune::VTK::FieldInfo::Type::vector, 3));
+    vtkWriter.addPointData(director2Function, Dune::VTK::FieldInfo("director2", Dune::VTK::FieldInfo::Type::vector, 3));
 
+    // Write the file
+    vtkWriter.write(filename);
   }
 
 };
diff --git a/src/cosserat-continuum.cc b/src/cosserat-continuum.cc
index 6f5615415b5764b79eeed1b9d15c4312a7b5ffd2..7e8da0a22d454af7b8ede86dbb1461698b50d58d 100644
--- a/src/cosserat-continuum.cc
+++ b/src/cosserat-continuum.cc
@@ -252,7 +252,15 @@ int main (int argc, char *argv[]) try
       lagrange<displacementOrder>()
       ));
 
-  auto orientationPowerBasis = makeBasis(
+  // Vector-valued basis to represent directors
+  auto directorBasis = makeBasis(
+    gridView,
+    power<3>(
+      lagrange<rotationOrder>()
+      ));
+
+  // Matrix-valued basis for treating the microrotation as a matrix field
+  auto orientationMatrixBasis = makeBasis(
     gridView,
     power<3>(
       power<3>(
@@ -412,29 +420,35 @@ int main (int argc, char *argv[]) try
   ////////////////////////////////////////////////////////
 
   // Output initial iterate (of homotopy loop)
-  if (dim == 2 && dimworld == 2) {
-    CosseratVTKWriter<GridView>::writeMixed<DeformationFEBasis,OrientationFEBasis>(deformationFEBasis,x[_0],
-                                                                                   orientationFEBasis,x[_1],
-                                                                                   resultPath + "cosserat_homotopy_0_l" + std::to_string(numLevels));
+
+  // Compute the displacement from the deformation, because that's more easily visualized
+  // in ParaView
+  BlockVector<FieldVector<double,3> > displacement(x[_0].size());
+  for (size_t i=0; i<x[_0].size(); i++)
+  {
+    for (int j = 0; j < dimworld; j ++)
+      displacement[i][j] = x[_0][i][j] - identityDeformation[i][j];
+    for (int j = dimworld; j<3; j++)
+      displacement[i][j] = x[_0][i][j];
+  }
+
+  auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationPowerBasis, displacement);
+
+  if (dim == dimworld) {
+    CosseratVTKWriter<GridView>::write(gridView,
+                                       displacementFunction,
+                                       directorBasis,
+                                       x[_1],
+                                       std::max(LFE_ORDER, GFE_ORDER),
+                                       resultPath + "cosserat_homotopy_0_l" + std::to_string(numLevels));
   } else if (dim == 2 && dimworld == 3) {
 #if MIXED_SPACE
     CosseratVTKWriter<GridView>::write<DeformationFEBasis>(deformationFEBasis, x[_0], resultPath + "cosserat_homotopy_0_l" + std::to_string(numLevels));
 #else
     CosseratVTKWriter<GridView>::write<DeformationFEBasis>(deformationFEBasis, x, resultPath + "cosserat_homotopy_0_l" + std::to_string(numLevels));
 #endif
-  } else if (dim == 3 && dimworld == 3) {
-
-    BlockVector<FieldVector<double,dimworld> > displacement(x[_0].size());
-    for (size_t i=0; i<x[_0].size(); i++) {
-      for (int j = 0; j < 3; j ++)
-        displacement[i][j] = x[_0][i][j] - identityDeformation[i][j];
-    }
-
-    auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim> >(deformationPowerBasis, displacement);
-    SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(displacementOrder-1));
-    vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::scalar, dim));
-    vtkWriter.write(resultPath + "cosserat_homotopy_0_l" + std::to_string(numLevels));
   }
+
   for (int i=0; i<numHomotopySteps; i++) {
 
     double homotopyParameter = (i+1)*(1.0/numHomotopySteps);
@@ -489,7 +503,7 @@ int main (int argc, char *argv[]) try
     Dune::Functions::interpolate(deformationPowerBasis, ddV, deformationDirichletValues);
 
     BlockVector<FieldMatrix<double,3,3> > dOV;
-    Dune::Functions::interpolate(orientationPowerBasis, dOV, orientationDirichletValues);
+    Functions::interpolate(orientationMatrixBasis, dOV, orientationDirichletValues);
 
     for (std::size_t i = 0; i < compositeBasis.size({0}); i++) {
       FieldVector<double,3> x0i = x[_0][i].globalCoordinates();
@@ -731,31 +745,33 @@ int main (int argc, char *argv[]) try
 #endif
     }
     // Output result of each homotopy step
-    std::stringstream iAsAscii;
-    iAsAscii << i+1;
 
-    if (dim == 2 && dimworld == 2) {
-      CosseratVTKWriter<GridView>::writeMixed<DeformationFEBasis,OrientationFEBasis>(deformationFEBasis,x[_0],
-                                                                                     orientationFEBasis,x[_1],
-                                                                                     resultPath + "cosserat_homotopy_" + iAsAscii.str());
+    // Compute the displacement from the deformation, because that's more easily visualized
+    // in ParaView
+    BlockVector<FieldVector<double,3> > displacement(x[_0].size());
+    for (size_t i=0; i<x[_0].size(); i++)
+    {
+      for (int j = 0; j < dimworld; j ++)
+        displacement[i][j] = x[_0][i][j] - identityDeformation[i][j];
+      for (int j = dimworld; j<3; j++)
+        displacement[i][j] = x[_0][i][j];
+    }
+
+    auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,3> >(deformationPowerBasis, displacement);
+
+    if (dim == dimworld) {
+      CosseratVTKWriter<GridView>::write(gridView,
+                                         displacementFunction,
+                                         directorBasis,
+                                         x[_1],
+                                         std::max(LFE_ORDER, GFE_ORDER),
+                                         resultPath + "cosserat_homotopy_" + std::to_string(i+1) + "_l" + std::to_string(numLevels));
     } else if (dim == 2 && dimworld == 3) {
 #if MIXED_SPACE
       CosseratVTKWriter<GridView>::write<DeformationFEBasis>(deformationFEBasis, x[_0], resultPath + "cosserat_homotopy_" + std::to_string(i+1) + "_l" + std::to_string(numLevels));
 #else
       CosseratVTKWriter<GridView>::write<DeformationFEBasis>(deformationFEBasis, x, resultPath + "cosserat_homotopy_" + std::to_string(i+1) + "_l" + std::to_string(numLevels));
 #endif
-    } else if (dim == 3 && dimworld == 3) {
-
-      BlockVector<FieldVector<double,dimworld> > displacement(x[_0].size());
-      for (size_t i=0; i<x[_0].size(); i++) {
-        for (int j = 0; j < 3; j ++)
-          displacement[i][j] = x[_0][i][j] - identityDeformation[i][j];
-      }
-
-      auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim> >(deformationPowerBasis, displacement);
-      SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(displacementOrder-1));
-      vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::scalar, dim));
-      vtkWriter.write(resultPath + "cosserat_homotopy_" + std::to_string(i+1) + "_l" + std::to_string(numLevels));
     }
   }