From 09adc15b4b39714087219c87811b6f37a4675c50 Mon Sep 17 00:00:00 2001
From: Thomas Fetzer <thomas.fetzer@iws.uni-stuttgart.de>
Date: Tue, 24 May 2016 09:30:18 +0200
Subject: [PATCH] [material] Add gstatrandomfield header

This is based on the existing version of gstatrandompermeabilityfield from dumux-devel.
It uses the better integration of gstat and should be able to not only generate permeability fields.
---
 .../spatialparams/gstatrandomfield.hh         | 203 ++++++++++++++++++
 1 file changed, 203 insertions(+)
 create mode 100644 dumux/material/spatialparams/gstatrandomfield.hh

diff --git a/dumux/material/spatialparams/gstatrandomfield.hh b/dumux/material/spatialparams/gstatrandomfield.hh
new file mode 100644
index 0000000000..8fa5a8216a
--- /dev/null
+++ b/dumux/material/spatialparams/gstatrandomfield.hh
@@ -0,0 +1,203 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Creating random fields using gstat
+ */
+#ifndef DUMUX_GSTAT_RANDOM_FIELD_HH
+#define DUMUX_GSTAT_RANDOM_FIELD_HH
+
+#if !HAVE_GSTAT
+#warning Gstat has not been found by CMake, please set the variable GSTAT_EXECUTABLE manually.
+// #define GSTAT_EXECUTABLE PATH
+#endif
+
+#include <iostream>
+
+#include <dune/grid/common/mcmgmapper.hh>
+#include <dune/grid/io/file/vtk/common.hh>
+#include <dune/grid/io/file/vtk/vtkwriter.hh>
+#include <dune/geometry/referenceelements.hh>
+#include <dune/istl/bvector.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \brief Creating random fields using gstat
+ *
+ * gstat is an open source software tool which can (among other things) generate
+ * geostatistical random fields (see <a href="www.gstat.org">www.gstat.org</a>).
+ *
+ * To use this class, unpack and install the zipped gstat tarball from the website
+ * or use the script installexternal.sh provided with dumux.
+ */
+template<class GridView, class Scalar>
+class GstatRandomField
+{
+    enum { dim = GridView::dimension,
+           dimWorld = GridView::dimensionworld};
+
+    typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > DataVector;
+    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    typedef typename GridView::Traits::template Codim<0>::EntityPointer ElementPointer;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::IndexSet IndexSet;
+    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, Dune::MCMGElementLayout> ElementMapper;
+
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+public:
+    /*!\brief Constructor.
+     *
+     * Creates a new field with random variables, if desired.
+     * Otherwise creates a data field from already available data.
+     *
+     * For the a rand field generation three files are necessary.
+     * A \a gstatControlFile in which all commands and in/output files for gstat are specified.
+     * A \a gstatInputFile contains all coordinates (cell centers) of the grid, so that
+     * gstat can perform its random realization. The filename must be same as in the gstatControlFile.
+     * A \a gstatOutputFile in which gstat writes the random values to this file.
+     * The filename must be same as in the gstatControlFile.
+     *
+     * \param gridView the used gridView
+     * \param gstatControlFile name of control file for gstat
+     * \param gstatInputFile name of input file for gstat
+     * \param gstatOutputFile name of the gstat output file
+     * \param createNew set true to create a new field
+     */
+    GstatRandomField(const GridView& gridView,
+                     const std::string gstatControlFile,
+                     const std::string gstatInputFile = "gstatInput.txt",
+                     const std::string gstatOutputFile = "permeab.dat",
+                     const bool createNew = true)
+    : gridView_(gridView),
+      data_(gridView.size(0)),
+      powField_(false),
+      elementMapper_(gridView)
+    {
+        ElementIterator eItEnd = gridView_.template end<0>();
+
+#if HAVE_GSTAT
+        if (createNew)
+        {
+            std::ofstream gstatInput(gstatInputFile);
+            for (ElementIterator eIt = gridView_.template begin<0>(); eIt != eItEnd; ++eIt)
+            {
+                // get global coordinates of cell centers
+                const GlobalPosition& globalPos = eIt->geometry().center();
+
+                for (int dimIdx = 0; dimIdx < dim; dimIdx++)
+                {
+                    gstatInput << globalPos[dimIdx] << " " << std::flush;
+                }
+                gstatInput << std::endl;
+            }
+            gstatInput.close();
+
+            std::string syscom;
+            syscom = GSTAT_EXECUTABLE;
+            syscom += " ";
+            syscom += gstatControlFile;
+
+            if (!gstatInput.good())
+            {
+                DUNE_THROW(Dune::IOError,
+                           "Reading the gstat control file: " << gstatControlFile << " failed." << std::endl);
+            }
+
+            if (system(syscom.c_str()))
+            {
+                DUNE_THROW(Dune::IOError, "Executing gstat failed.");
+            }
+        }
+#endif
+
+        std::ifstream gstatOutput(gstatOutputFile);
+        if (!gstatOutput.good())
+        {
+            DUNE_THROW(Dune::IOError,
+                        "Reading from file: " << gstatOutputFile << " failed." << std::endl);
+        }
+
+        std::string line;
+        std::getline(gstatOutput, line);
+
+        Scalar dummy1, dummy2, dummy3, dataValue;
+        for (ElementIterator eIt = gridView_.template begin<0>(); eIt != eItEnd; ++eIt)
+        {
+            std::getline(gstatOutput, line);
+            std::istringstream curLine(line);
+            if (dim == 1)
+                curLine >> dummy1 >> dataValue;
+            else if (dim == 2)
+                curLine >> dummy1 >> dummy2 >> dataValue;
+            else // dim = 3
+                curLine >> dummy1 >> dummy2 >> dummy3 >> dataValue;
+            data_[elementMapper_.index(*eIt)] = dataValue;
+        }
+        gstatOutput.close();
+    }
+
+    //! \brief Use the input as an exponent
+    void createPowField()
+    {
+        for (unsigned int i = 0; i < data_.size(); ++i)
+        {
+            data_[i] = std::pow(10.0, data_[i]);
+        }
+        powField_ = true;
+    }
+
+    //! \brief Return an entry of the data vector
+    Scalar data(const Element& e)
+    {
+        return data_[elementMapper_.index(e)];
+    }
+
+    //! \brief Write the data to a vtk file
+    void writeVtk(const std::string vtkName,
+                  const std::string dataName = "data") const
+    {
+        Dune::VTKWriter<GridView> vtkwriter(gridView_);
+        vtkwriter.addCellData(data_, dataName);
+
+        DataVector logPerm(data_.size());
+        if (powField_)
+        {
+            for (unsigned int i = 0; i < data_.size(); ++i)
+            {
+                logPerm[i] = std::log10(data_[i]);
+            }
+            vtkwriter.addCellData(logPerm, "logarithm of " + dataName);
+        }
+        vtkwriter.write(vtkName, Dune::VTK::OutputType::ascii);
+    }
+
+private:
+    const GridView& gridView_;
+    DataVector data_;
+    bool powField_;
+    ElementMapper elementMapper_;
+};
+
+}
+
+#endif
-- 
GitLab