diff --git a/dumux/io/CMakeLists.txt b/dumux/io/CMakeLists.txt index 64e7dd84f325c880f3452c372b213e0babd218c6..4ca95d94126e6b3e9cb17cee801319aeb33818ca 100644 --- a/dumux/io/CMakeLists.txt +++ b/dumux/io/CMakeLists.txt @@ -3,6 +3,7 @@ install(FILES adaptivegridrestart.hh artgridcreator.hh +container.hh cpgridcreator.hh gnuplotinterface.hh gridcreator.hh diff --git a/dumux/io/container.hh b/dumux/io/container.hh new file mode 100644 index 0000000000000000000000000000000000000000..5f81750cd6caa4996423c5d74348dc1bb0875298 --- /dev/null +++ b/dumux/io/container.hh @@ -0,0 +1,69 @@ +// -*- 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 Free functions to write and read a sequence container to and from a file + * \note Reading should work for all sequence containers providing begin, end, and push_back + * (e.g. std::vector, std::deque, std::list), so not for e.g. std::array. + * Writing only needs begin and end member functions returning iterators. + */ +#ifndef DUMUX_IO_CONTAINER_HH +#define DUMUX_IO_CONTAINER_HH + +#include <iostream> +#include <fstream> + +namespace Dumux { + +/*! + * \brief Writes a container to file + * \param v The container, requires being() and end() method + * \param filename The filename to write to + * + * \usage std::vector<double>(5, 0.0) v; writeContainerToFile(v, "myvector.txt"); + */ +template<typename Container> +void writeContainerToFile(const Container& v, + const std::string& filename) +{ + std::ofstream outfile(filename, std::ios::out); + std::ostream_iterator<typename Container::value_type> it(outfile, "\n"); + std::copy(v.begin(),v.end(), it); +} + +/*! + * \brief Read a simple text file into a container + * \param filename The filename to write to + * \tparam Container The container type, requires being(), end(), push_back() method + * + * \usage auto v = readFileToContainer<std::vector<double>>("myvector.txt"); + */ +template<typename Container> +Container readFileToContainer(const std::string& filename) +{ + Container v; + std::ifstream infile(filename, std::ios::in); + std::istream_iterator<typename Container::value_type> it(infile); + std::copy(it, std::istream_iterator<typename Container::value_type>(), std::back_inserter(v)); + return v; +} + +} // end namespace Dumux + +#endif diff --git a/test/io/CMakeLists.txt b/test/io/CMakeLists.txt index 8194b9046a686c925e75a3bea16791219896195c..ad790477b5a6a8d445b5ef4a345ccdf8c84a1ac6 100644 --- a/test/io/CMakeLists.txt +++ b/test/io/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory("gnuplotinterface") -add_subdirectory("gridcreator") \ No newline at end of file +add_subdirectory("gridcreator") +add_subdirectory("container") diff --git a/test/io/container/CMakeLists.txt b/test/io/container/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fd7a6fde772ad55a612522e5721a6f4e3eb8c372 --- /dev/null +++ b/test/io/container/CMakeLists.txt @@ -0,0 +1,7 @@ +add_dumux_test(test_container_io test_container_io test_container_io.cc + ${CMAKE_CURRENT_BINARY_DIR}/test_container_io) + +#install sources +install(FILES +test_container_io.cc +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/test/io/container) diff --git a/test/io/container/test_container_io.cc b/test/io/container/test_container_io.cc new file mode 100644 index 0000000000000000000000000000000000000000..c5814c3f3e032b77ce3e6d56c9492de5a3b85c45 --- /dev/null +++ b/test/io/container/test_container_io.cc @@ -0,0 +1,116 @@ +// -*- 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 Test writing and reading sequence container to and from file + */ +#include <config.h> + +#include <algorithm> +#include <vector> +#include <list> +#include <deque> +#include <array> +#include <initializer_list> + +#include <dune/common/float_cmp.hh> +#include <dune/common/fvector.hh> +#include <dune/istl/bvector.hh> + +#include <dumux/io/container.hh> + +namespace Dumux { + +template<typename T> +bool testContainerIO(const T& c0) +{ + writeContainerToFile(c0, "container.txt"); + auto c1 = readFileToContainer<T>("container.txt"); + return std::equal(c0.begin(), c0.end(), c1.begin()); +} + +template<typename T> +bool testContainerIO(const std::initializer_list<typename T::value_type>& init) +{ + T c0(init); + writeContainerToFile(c0, "container.txt"); + auto c1 = readFileToContainer<T>("container.txt"); + return std::equal(c0.begin(), c0.end(), c1.begin()); +} + +template<typename T> +bool testContainerWriter(const T& c0) +{ + writeContainerToFile(c0, "container.txt"); + auto c1 = readFileToContainer<std::vector<std::decay_t<decltype(*c0.begin())>>>("container.txt"); + return std::equal(c0.begin(), c0.end(), c1.begin()); +} + +} // end namespace Dumux + +//////////////////////// +// the main function +//////////////////////// +int main() +{ + bool passed = true; + + // we can read and write into + // std::vector, std::list, std::deque + // we can even read and write containers of FieldVectors (very convenient!) + auto doublei = {5.3, 6.1, 7.2, 5.66, 2.89, 8.123}; + passed = passed && Dumux::testContainerIO<std::vector<double>>(doublei); + passed = passed && Dumux::testContainerIO<std::list<double>>(doublei); + passed = passed && Dumux::testContainerIO<std::deque<double>>(doublei); + if (!passed) return 1; + + auto inti = {5, 6, 7, 5, 2, 8}; + passed = passed && Dumux::testContainerIO<std::vector<int>>(inti); + passed = passed && Dumux::testContainerIO<std::list<int>>(inti); + passed = passed && Dumux::testContainerIO<std::deque<int>>(inti); + if (!passed) return 1; + + std::initializer_list<std::string> stringi = {"5", "6", "7", "5", "2", "8"}; + passed = passed && Dumux::testContainerIO<std::vector<std::string>>(stringi); + passed = passed && Dumux::testContainerIO<std::list<std::string>>(stringi); + passed = passed && Dumux::testContainerIO<std::deque<std::string>>(stringi); + if (!passed) return 1; + + auto fvector2i = {Dune::FieldVector<double, 2>(0.0), Dune::FieldVector<double, 2>(1.0), Dune::FieldVector<double, 2>(2.0)}; + passed = passed && Dumux::testContainerIO<std::vector<Dune::FieldVector<double, 2>>>(fvector2i); + passed = passed && Dumux::testContainerIO<std::list<Dune::FieldVector<double, 2>>>(fvector2i); + passed = passed && Dumux::testContainerIO<std::deque<Dune::FieldVector<double, 2>>>(fvector2i); + if (!passed) return 1; + + auto fvector3i = {Dune::FieldVector<double, 3>(0.0), Dune::FieldVector<double, 3>(1.0), Dune::FieldVector<double, 3>(2.0)}; + passed = passed && Dumux::testContainerIO<std::vector<Dune::FieldVector<double, 3>>>(fvector3i); + passed = passed && Dumux::testContainerIO<std::list<Dune::FieldVector<double, 3>>>(fvector3i); + passed = passed && Dumux::testContainerIO<std::deque<Dune::FieldVector<double, 3>>>(fvector3i); + if (!passed) return 1; + + // we can write also std::arrays (all container providing begin and end) + passed = passed && Dumux::testContainerWriter<std::array<double, 2>>(std::array<double, 2>{1.0, 2.0}); + passed = passed && Dumux::testContainerWriter<std::array<int, 2>>(std::array<int, 2>{1, 2}); + passed = passed && Dumux::testContainerWriter<std::array<std::string, 2>>(std::array<std::string, 2>{"1.0", "2.0"}); + passed = passed && Dumux::testContainerWriter<std::array<Dune::FieldVector<double, 3>, 2>>( + std::array<Dune::FieldVector<double, 3>, 2>{Dune::FieldVector<double, 3>(0.0), Dune::FieldVector<double, 3>(1.0)}); + if (!passed) return 1; + + return 0; +}