diff --git a/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh b/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh index c906d0f6e94d4edf1ca4790bb0da3276786971f0..4050e7872263546fbc33299a2bfb3d48d380d1ad 100644 --- a/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh +++ b/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh @@ -90,7 +90,7 @@ class FreeFlowStaggeredGeometryHelper static constexpr int codimIntersection = 1; static constexpr int codimCommonEntity = 2; static constexpr int numFacetSubEntities = (dim == 2) ? 2 : 4; - static constexpr int numPairs = (dimWorld == 2) ? 2 : 4; + static constexpr int numPairs = 2 * (dimWorld - 1); public: @@ -376,6 +376,8 @@ private: }; Indices indices; + if (dim == 1) + return indices; switch(localFacetIdx) { diff --git a/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh b/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh index 5b9cafec19c37ed952fda7baba0fd2ad1fa8941e..e43857366c85f141f8c5f1bf1a0e5d3e8edb2a56 100644 --- a/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh +++ b/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh @@ -55,7 +55,7 @@ class FreeFlowStaggeredSubControlVolumeFace static const int dim = Geometry::mydimension; static const int dimworld = Geometry::coorddimension; - static constexpr int numPairs = (dimworld == 2) ? 2 : 4; + static constexpr int numPairs = 2 * (dimworld - 1); public: using GlobalPosition = typename T::GlobalPosition; diff --git a/test/freeflow/navierstokes/CMakeLists.txt b/test/freeflow/navierstokes/CMakeLists.txt index 6808d3f93ce7efb8ab4ec0e84d2f5dda1fda474e..6056f26f402b57379fdd8219829da90708993108 100644 --- a/test/freeflow/navierstokes/CMakeLists.txt +++ b/test/freeflow/navierstokes/CMakeLists.txt @@ -1,4 +1,5 @@ add_input_file_links() +dune_symlink_to_source_files(FILES convergence.sh) set(CMAKE_BUILD_TYPE Debug) add_executable(test_closedsystem EXCLUDE_FROM_ALL test_closedsystem.cc) @@ -80,6 +81,15 @@ dune_add_test(NAME test_stokes_donea ${CMAKE_CURRENT_BINARY_DIR}/test_donea-00001.vtu --command "${CMAKE_CURRENT_BINARY_DIR}/test_stokes_donea") +dune_add_test(NAME test_navierstokes_1d + SOURCES test_navierstokes_1d.cc + CMAKE_GUARD HAVE_UMFPACK + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/test_navierstokes_1d.vtp + ${CMAKE_CURRENT_BINARY_DIR}/test_navierstokes_1d-00001.vtp + --command "${CMAKE_CURRENT_BINARY_DIR}/test_navierstokes_1d") + dune_add_test(NAME test_navierstokes_kovasznay SOURCES test_kovasznay.cc CMAKE_GUARD HAVE_UMFPACK diff --git a/test/freeflow/navierstokes/convergence.sh b/test/freeflow/navierstokes/convergence.sh new file mode 100755 index 0000000000000000000000000000000000000000..945249cbff00987e0d99236f5cbd5878d25f5ae2 --- /dev/null +++ b/test/freeflow/navierstokes/convergence.sh @@ -0,0 +1,44 @@ +#! /bin/bash + +if [ $# -ne 3 ]; then + echo "usage: $0 EXECUTABLE_NAME DIMENSION NUM_REFINEMENT_STEPS" + exit +fi + +make $1 + +LOGFILE=logfile_$1.out +rm $LOGFILE +L2ERRORFILE=l2error_$1.txt + +if [ $2 == 1 ]; then +GRIDCELLS="4" +elif [ $2 == 2 ]; then +GRIDCELLS="4 4" +else +GRIDCELLS="4 4 4" +fi + +MAX=$3 +for (( i=0; i <= $MAX; ++i )); do + printf "refinement $i / $MAX " + ./$1 $1.input -Grid.Cells "$GRIDCELLS" -Grid.Refinement $i -Problem.PrintL2Error true &>> $LOGFILE + echo "done." +done + +grep "L2 error (abs/rel) for" $LOGFILE | tee $L2ERRORFILE +echo "reset; \ +set log x; \ +set log y; \ +set arrow from graph 0,1 to graph 1,0 nohead lc rgb 'gray'; \ +set arrow from graph 0,1 to graph 1,0.5 nohead lc rgb 'gray'" > $1.gp + +PLOT="plot '$L2ERRORFILE' u 6:17 w lp t 'pressure', '$L2ERRORFILE' u 6:23 w lp t 'velocity'" +if [ $2 == 2 ]; then +PLOT=$PLOT", '$L2ERRORFILE' u 6:29 w lp t 'velocity'" +elif [ $2 == 3 ]; then +PLOT=$PLOT", '$L2ERRORFILE' u 6:35 w lp t 'velocity'" +fi + +echo $PLOT >> $1.gp +gnuplot --persist $1.gp diff --git a/test/freeflow/navierstokes/doneatestproblem.hh b/test/freeflow/navierstokes/doneatestproblem.hh index bbd58ba1bdeb53432cdadba4f4ac5a8ef3798dc4..db0020715bc6b0ef1f30912f87a5b635b76b05d4 100644 --- a/test/freeflow/navierstokes/doneatestproblem.hh +++ b/test/freeflow/navierstokes/doneatestproblem.hh @@ -121,8 +121,8 @@ public: << std::setw(6) << numCellCenterDofs << " cc dofs and " << numFaceDofs << " face dofs (total: " << numCellCenterDofs + numFaceDofs << "): " << std::scientific << "L2(p) = " << l2error.first[Indices::pressureIdx] << " / " << l2error.second[Indices::pressureIdx] - << ", L2(vx) = " << l2error.first[Indices::velocityXIdx] << " / " << l2error.second[Indices::velocityXIdx] - << ", L2(vy) = " << l2error.first[Indices::velocityYIdx] << " / " << l2error.second[Indices::velocityYIdx] + << " , L2(vx) = " << l2error.first[Indices::velocityXIdx] << " / " << l2error.second[Indices::velocityXIdx] + << " , L2(vy) = " << l2error.first[Indices::velocityYIdx] << " / " << l2error.second[Indices::velocityYIdx] << std::endl; } } diff --git a/test/freeflow/navierstokes/kovasznaytestproblem.hh b/test/freeflow/navierstokes/kovasznaytestproblem.hh index 8927693ffae2bb769b38b5eb6d2325ba43a1a7e1..a3ce7237c0c141b9996bc00c5dcbf33bb2847061 100644 --- a/test/freeflow/navierstokes/kovasznaytestproblem.hh +++ b/test/freeflow/navierstokes/kovasznaytestproblem.hh @@ -127,8 +127,8 @@ public: << std::setw(6) << numCellCenterDofs << " cc dofs and " << numFaceDofs << " face dofs (total: " << numCellCenterDofs + numFaceDofs << "): " << std::scientific << "L2(p) = " << l2error.first[Indices::pressureIdx] << " / " << l2error.second[Indices::pressureIdx] - << ", L2(vx) = " << l2error.first[Indices::velocityXIdx] << " / " << l2error.second[Indices::velocityXIdx] - << ", L2(vy) = " << l2error.first[Indices::velocityYIdx] << " / " << l2error.second[Indices::velocityYIdx] + << " , L2(vx) = " << l2error.first[Indices::velocityXIdx] << " / " << l2error.second[Indices::velocityXIdx] + << " , L2(vy) = " << l2error.first[Indices::velocityYIdx] << " / " << l2error.second[Indices::velocityYIdx] << std::endl; } } diff --git a/test/freeflow/navierstokes/navierstokesanalyticproblem.hh b/test/freeflow/navierstokes/navierstokesanalyticproblem.hh new file mode 100644 index 0000000000000000000000000000000000000000..fa6ca53d978591da699bce9885f0105578dd99d7 --- /dev/null +++ b/test/freeflow/navierstokes/navierstokesanalyticproblem.hh @@ -0,0 +1,374 @@ +// -*- 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 + * \ingroup NavierStokesTests + * \brief Test for the 1-D Navier-Stokes model with an analytical solution + * + * \copydoc NavierStokesAnalyticProblem + */ +#ifndef DUMUX_DONEA_TEST_PROBLEM_HH +#define DUMUX_DONEA_TEST_PROBLEM_HH + +#include <dumux/material/components/constant.hh> +#include <dumux/material/fluidsystems/1pliquid.hh> + +#include <dumux/discretization/staggered/freeflow/properties.hh> +#include <dumux/freeflow/navierstokes/model.hh> +#include <dumux/freeflow/navierstokes/problem.hh> +#include "l2error.hh" + + +namespace Dumux +{ +template <class TypeTag> +class NavierStokesAnalyticProblem; + +namespace Properties +{ +NEW_TYPE_TAG(NavierStokesAnalyticTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, NavierStokes)); + +// the fluid system +SET_PROP(NavierStokesAnalyticTypeTag, FluidSystem) +{ + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using type = FluidSystems::OnePLiquid<Scalar, Components::Constant<1, Scalar> >; +}; + +// Set the grid type +SET_TYPE_PROP(NavierStokesAnalyticTypeTag, Grid, Dune::YaspGrid<1>); + +// Set the problem property +SET_TYPE_PROP(NavierStokesAnalyticTypeTag, Problem, Dumux::NavierStokesAnalyticProblem<TypeTag> ); + +SET_BOOL_PROP(NavierStokesAnalyticTypeTag, EnableFVGridGeometryCache, true); + +SET_BOOL_PROP(NavierStokesAnalyticTypeTag, EnableGridFluxVariablesCache, true); +SET_BOOL_PROP(NavierStokesAnalyticTypeTag, EnableGridVolumeVariablesCache, true); + +SET_BOOL_PROP(NavierStokesAnalyticTypeTag, EnableInertiaTerms, true); +SET_BOOL_PROP(NavierStokesAnalyticTypeTag, NormalizePressure, false); +} + +/*! + * \ingroup NavierStokesTests + * \brief Test for the 1-D Navier-Stokes model with an analytical solution + * + * The 1-D analytic solution is given by + * \f[ p = 2 - 2 \cdot x \f] + * \f[ v_\text{x} = 2 \cdot x^3 \f] + */ +template <class TypeTag> +class NavierStokesAnalyticProblem : public NavierStokesProblem<TypeTag> +{ + using ParentType = NavierStokesProblem<TypeTag>; + + using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits); + using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + + static constexpr auto dimWorld = GET_PROP_TYPE(TypeTag, GridView)::dimensionworld; + using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; + using DimVector = Dune::FieldVector<Scalar, dimWorld>; + using DimMatrix = Dune::FieldVector<Dune::FieldVector<Scalar, dimWorld>, dimWorld>; + +public: + NavierStokesAnalyticProblem(std::shared_ptr<const FVGridGeometry> fvGridGeometry) + : ParentType(fvGridGeometry), eps_(1e-6) + { + printL2Error_ = getParam<bool>("Problem.PrintL2Error"); + density_ = getParam<Scalar>("Problem.LiquidDensity"); + kinematicViscosity_ = getParam<Scalar>("Problem.LiquidKinematicViscosity"); + createAnalyticalSolution_(); + } + + /*! + * \name Problem parameters + */ + // \{ + + bool shouldWriteRestartFile() const + { + return false; + } + + void postTimeStep(const SolutionVector& curSol) const + { + if(printL2Error_) + { + using L2Error = NavierStokesTestL2Error<Scalar, ModelTraits, PrimaryVariables>; + const auto l2error = L2Error::calculateL2Error(*this, curSol); + const int numCellCenterDofs = this->fvGridGeometry().numCellCenterDofs(); + const int numFaceDofs = this->fvGridGeometry().numFaceDofs(); + std::cout << std::setprecision(8) << "** L2 error (abs/rel) for " + << std::setw(6) << numCellCenterDofs << " cc dofs and " << numFaceDofs << " face dofs (total: " << numCellCenterDofs + numFaceDofs << "): " + << std::scientific + << "L2(p) = " << l2error.first[Indices::pressureIdx] << " / " << l2error.second[Indices::pressureIdx] + << " , L2(vx) = " << l2error.first[Indices::velocityXIdx] << " / " << l2error.second[Indices::velocityXIdx] + << std::endl; + } + } + + /*! + * \brief Return the temperature within the domain in [K]. + * + * This problem assumes a temperature of 10 degrees Celsius. + */ + Scalar temperature() const + { return 298.0; } + + /*! + * \brief Return the sources within the domain. + * + * \param globalPos The global position + */ + NumEqVector sourceAtPos(const GlobalPosition &globalPos) const + { + NumEqVector source(0.0); + + // mass balance - term div(rho*v) + for (unsigned int dimIdx = 0; dimIdx < dimWorld; ++dimIdx) + { + source[Indices::conti0EqIdx] += dvdx(globalPos)[dimIdx][dimIdx]; + } + source[Indices::conti0EqIdx] *= density_; + + // momentum balance + for (unsigned int velIdx = 0; velIdx < dimWorld; ++velIdx) + { + for (unsigned int dimIdx = 0; dimIdx < dimWorld; ++dimIdx) + { + // inertia term + if (GET_PROP_VALUE(TypeTag, EnableInertiaTerms)) + source[Indices::velocity(velIdx)] += density_ * dv2dx(globalPos)[velIdx][dimIdx]; + + // viscous term (molecular) + source[Indices::velocity(velIdx)] -= density_ * kinematicViscosity_* dvdx2(globalPos)[velIdx][dimIdx]; + static bool enableUnsymmetrizedVelocityGradient = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), + "FreeFlow.EnableUnsymmetrizedVelocityGradient", false); + if (!enableUnsymmetrizedVelocityGradient) + source[Indices::velocity(velIdx)] -= density_ * kinematicViscosity_* dvdx2(globalPos)[dimIdx][velIdx]; + } + // pressure term + source[Indices::velocity(velIdx)] += dpdx(globalPos)[velIdx]; + + // gravity term + static bool enableGravity = getParam<bool>("Problem.EnableGravity"); + if (enableGravity) + { + source[Indices::velocity(velIdx)] -= density_ * this->gravity()[velIdx]; + } + } + + return source; + } + // \} + /*! + * \name Boundary conditions + */ + // \{ + + /*! + * \brief Specifies which kind of boundary condition should be + * used for which equation on a given boundary control volume. + * + * \param globalPos The position of the center of the finite volume + */ + BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const + { + BoundaryTypes values; + + // set Dirichlet values for the velocity and pressure everywhere + values.setDirichletCell(Indices::conti0EqIdx); + values.setDirichlet(Indices::momentumXBalanceIdx); + + return values; + } + + /*! + * \brief Return dirichlet boundary values at a given position + * + * \param globalPos The global position + */ + PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const + { + // use the values of the analytical solution + return analyticalSolution(globalPos); + } + + /*! + * \brief Return the analytical solution of the problem at a given position + * + * \param globalPos The global position + */ + PrimaryVariables analyticalSolution(const GlobalPosition& globalPos) const + { + PrimaryVariables values; + values[Indices::pressureIdx] = p(globalPos); + values[Indices::velocityXIdx] = v(globalPos); + return values; + } + + //! \brief The velocity + const DimVector v(const DimVector& globalPos) const + { + DimVector v(0.0); + v[0] = 2.0 * globalPos[0] * globalPos[0] * globalPos[0]; + return v; + } + + //! \brief The velocity gradient + const DimMatrix dvdx(const DimVector& globalPos) const + { + DimMatrix dvdx(0.0); + dvdx[0][0] = 6.0 * globalPos[0] * globalPos[0]; + return dvdx; + } + + //! \brief The gradient of the velocity squared (using product rule -> nothing to do here) + const DimMatrix dv2dx(const DimVector& globalPos) const + { + DimMatrix dv2dx; + for (unsigned int velIdx = 0; velIdx < dimWorld; ++velIdx) + { + for (unsigned int dimIdx = 0; dimIdx < dimWorld; ++dimIdx) + { + dv2dx[velIdx][dimIdx] = dvdx(globalPos)[velIdx][dimIdx] * v(globalPos)[dimIdx] + + dvdx(globalPos)[dimIdx][dimIdx] * v(globalPos)[velIdx]; + } + } + return dv2dx; + } + + //! \brief The gradient of the velocity gradient + const DimMatrix dvdx2(const DimVector& globalPos) const + { + DimMatrix dvdx2(0.0); + dvdx2[0][0] = 12.0 * globalPos[0]; + return dvdx2; + } + + //! \brief The pressure + const Scalar p(const DimVector& globalPos) const + { return 2.0 - 2.0 * globalPos[0]; } + + //! \brief The pressure gradient + const DimVector dpdx(const DimVector& globalPos) const + { + DimVector dpdx(0.0); + dpdx[0] = -2.0; + return dpdx; + } + + // \} + + /*! + * \name Volume terms + */ + // \{ + + /*! + * \brief Evaluate the initial value for a control volume. + * + * \param globalPos The global position + */ + PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const + { + return analyticalSolution(globalPos); + } + + /*! + * \brief Returns the analytical solution for the pressure + */ + auto& getAnalyticalPressureSolution() const + { + return analyticalPressure_; + } + + /*! + * \brief Returns the analytical solution for the velocity + */ + auto& getAnalyticalVelocitySolution() const + { + return analyticalVelocity_; + } + + /*! + * \brief Returns the analytical solution for the velocity at the faces + */ + auto& getAnalyticalVelocitySolutionOnFace() const + { + return analyticalVelocityOnFace_; + } + +private: + + /*! + * \brief Adds additional VTK output data to the VTKWriter. Function is called by the output module on every write. + */ + void createAnalyticalSolution_() + { + analyticalPressure_.resize(this->fvGridGeometry().numCellCenterDofs()); + analyticalVelocity_.resize(this->fvGridGeometry().numCellCenterDofs()); + analyticalVelocityOnFace_.resize(this->fvGridGeometry().numFaceDofs()); + + for (const auto& element : elements(this->fvGridGeometry().gridView())) + { + auto fvGeometry = localView(this->fvGridGeometry()); + fvGeometry.bindElement(element); + for (auto&& scv : scvs(fvGeometry)) + { + auto ccDofIdx = scv.dofIndex(); + auto ccDofPosition = scv.dofPosition(); + auto analyticalSolutionAtCc = analyticalSolution(ccDofPosition); + + // velocities on faces + for (auto&& scvf : scvfs(fvGeometry)) + { + const auto faceDofIdx = scvf.dofIndex(); + const auto faceDofPosition = scvf.center(); + const auto dirIdx = scvf.directionIndex(); + const auto analyticalSolutionAtFace = analyticalSolution(faceDofPosition); + analyticalVelocityOnFace_[faceDofIdx][dirIdx] = analyticalSolutionAtFace[Indices::velocity(dirIdx)]; + } + + analyticalPressure_[ccDofIdx] = analyticalSolutionAtCc[Indices::pressureIdx]; + + for(int dirIdx = 0; dirIdx < ModelTraits::dim(); ++dirIdx) + analyticalVelocity_[ccDofIdx][dirIdx] = analyticalSolutionAtCc[Indices::velocity(dirIdx)]; + } + } + } + + Scalar eps_; + bool printL2Error_; + Scalar density_; + Scalar kinematicViscosity_; + std::vector<Scalar> analyticalPressure_; + std::vector<GlobalPosition> analyticalVelocity_; + std::vector<GlobalPosition> analyticalVelocityOnFace_; +}; +} //end namespace + +#endif diff --git a/test/freeflow/navierstokes/test_navierstokes_1d.cc b/test/freeflow/navierstokes/test_navierstokes_1d.cc new file mode 100644 index 0000000000000000000000000000000000000000..4d8c4598ea6f7bec49abb8153b098e27f709c9eb --- /dev/null +++ b/test/freeflow/navierstokes/test_navierstokes_1d.cc @@ -0,0 +1,197 @@ +// -*- 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 for a 1-D staggered grid Navier-Stokes model + */ + +#include <config.h> + +#include <ctime> +#include <iostream> + +#include <dune/common/parallel/mpihelper.hh> +#include <dune/common/timer.hh> +#include <dune/grid/io/file/dgfparser/dgfexception.hh> +#include <dune/grid/io/file/vtk.hh> +#include <dune/istl/io.hh> + +#include <dumux/common/defaultusagemessage.hh> +#include <dumux/common/dumuxmessage.hh> +#include <dumux/common/properties.hh> +#include <dumux/common/parameters.hh> +#include <dumux/common/valgrind.hh> + +#include <dumux/assembly/staggeredfvassembler.hh> +#include <dumux/assembly/diffmethod.hh> +#include <dumux/discretization/methods.hh> +#include <dumux/io/staggeredvtkoutputmodule.hh> +#include <dumux/linear/seqsolverbackend.hh> +#include <dumux/nonlinear/newtonsolver.hh> + +#include "navierstokesanalyticproblem.hh" + +/*! + * \brief Provides an interface for customizing error messages associated with + * reading in parameters. + * + * \param progName The name of the program, that was tried to be started. + * \param errorMsg The error message that was issued by the start function. + * Comprises the thing that went wrong and a general help message. + */ +void usage(const char *progName, const std::string &errorMsg) +{ + if (errorMsg.size() > 0) { + std::string errorMessageOut = "\nUsage: "; + errorMessageOut += progName; + errorMessageOut += " [options]\n"; + errorMessageOut += errorMsg; + errorMessageOut += "\n\nThe list of mandatory arguments for this program is:\n" + "\t-TimeManager.TEnd End of the simulation [s] \n" + "\t-TimeManager.DtInitial Initial timestep size [s] \n"; + std::cout << errorMessageOut + << "\n"; + } +} + +int main(int argc, char** argv) try +{ + using namespace Dumux; + + // define the type tag for this problem + using TypeTag = TTAG(NavierStokesAnalyticTypeTag); + + // initialize MPI, finalize is done automatically on exit + const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); + + // print dumux start message + if (mpiHelper.rank() == 0) + DumuxMessage::print(/*firstCall=*/true); + + // parse command line arguments and input file + Parameters::init(argc, argv, usage); + + // try to create a grid (from the given grid file or the input file) + using GridCreator = typename GET_PROP_TYPE(TypeTag, GridCreator); + GridCreator::makeGrid(); + GridCreator::loadBalance(); + + //////////////////////////////////////////////////////////// + // run instationary non-linear problem on this grid + //////////////////////////////////////////////////////////// + + // we compute on the leaf grid view + const auto& leafGridView = GridCreator::grid().leafGridView(); + + // create the finite volume grid geometry + using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + auto fvGridGeometry = std::make_shared<FVGridGeometry>(leafGridView); + fvGridGeometry->update(); + + // the problem (boundary conditions) + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + auto problem = std::make_shared<Problem>(fvGridGeometry); + + // the solution vector + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + const auto numDofsCellCenter = leafGridView.size(0); + const auto numDofsFace = leafGridView.size(1); + SolutionVector x; + x[FVGridGeometry::cellCenterIdx()].resize(numDofsCellCenter); + x[FVGridGeometry::faceIdx()].resize(numDofsFace); + + // the grid variables + using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry); + gridVariables->init(x); + + // intialize the vtk output module + using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); + StaggeredVtkOutputModule<TypeTag, GET_PROP_VALUE(TypeTag, PhaseIdx)> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); + VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + vtkWriter.addField(problem->getAnalyticalPressureSolution(), "pressureExact"); + vtkWriter.addField(problem->getAnalyticalVelocitySolution(), "velocityExact"); + vtkWriter.addFaceField(problem->getAnalyticalVelocitySolutionOnFace(), "faceVelocityExact"); + vtkWriter.write(0.0); + + // the assembler with time loop for instationary problem + using Assembler = StaggeredFVAssembler<TypeTag, DiffMethod::numeric>; + auto assembler = std::make_shared<Assembler>(problem, fvGridGeometry, gridVariables); + + // the linear solver + using LinearSolver = Dumux::UMFPackBackend; + auto linearSolver = std::make_shared<LinearSolver>(); + + // the non-linear solver + using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>; + NewtonSolver nonLinearSolver(assembler, linearSolver); + + // linearize & solve + Dune::Timer timer; + nonLinearSolver.solve(x); + + // write vtk output + problem->postTimeStep(x); + vtkWriter.write(1.0); + + timer.stop(); + + const auto& comm = Dune::MPIHelper::getCollectiveCommunication(); + std::cout << "Simulation took " << timer.elapsed() << " seconds on " + << comm.size() << " processes.\n" + << "The cumulative CPU time was " << timer.elapsed()*comm.size() << " seconds.\n"; + + //////////////////////////////////////////////////////////// + // finalize, print dumux message to say goodbye + //////////////////////////////////////////////////////////// + + // print dumux end message + if (mpiHelper.rank() == 0) + { + Parameters::print(); + DumuxMessage::print(/*firstCall=*/false); + } + + return 0; +} // end main +catch (Dumux::ParameterException &e) +{ + std::cerr << std::endl << e << " ---> Abort!" << std::endl; + return 1; +} +catch (Dune::DGFException & e) +{ + std::cerr << "DGF exception thrown (" << e << + "). Most likely, the DGF file name is wrong " + "or the DGF file is corrupted, " + "e.g. missing hash at end of file or wrong number (dimensions) of entries." + << " ---> Abort!" << std::endl; + return 2; +} +catch (Dune::Exception &e) +{ + std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; + return 3; +} +catch (...) +{ + std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; + return 4; +} diff --git a/test/freeflow/navierstokes/test_navierstokes_1d.input b/test/freeflow/navierstokes/test_navierstokes_1d.input new file mode 100644 index 0000000000000000000000000000000000000000..2215feafa6a633f0d67f4421f21c26cfdda8926b --- /dev/null +++ b/test/freeflow/navierstokes/test_navierstokes_1d.input @@ -0,0 +1,18 @@ +[Grid] +UpperRight = 1 +Cells = 32 + +[Problem] +Name = test_navierstokes_1d +EnableGravity = false +PrintL2Error = true +LiquidKinematicViscosity = 1. +LiquidDensity = 1. + +[Newton] +MaxSteps = 10 +MaxRelativeShift = 1e-9 + +[Vtk] +WriteFaceData = false +AddVelocity = true diff --git a/test/references/test_navierstokes_1d.vtp b/test/references/test_navierstokes_1d.vtp new file mode 100644 index 0000000000000000000000000000000000000000..55ed9f74ae3516156328c29cd479a76e795d127c --- /dev/null +++ b/test/references/test_navierstokes_1d.vtp @@ -0,0 +1,72 @@ +<?xml version="1.0"?> +<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian"> + <PolyData> + <Piece NumberOfLines="32" NumberOfPoints="33"> + <CellData Scalars="p"> + <DataArray type="Float32" Name="p" NumberOfComponents="1" format="ascii"> + 1.96875 1.81039 1.74788 1.68538 1.62288 1.56038 1.49789 1.43542 1.37299 1.31061 1.2483 1.18611 + 1.12406 1.06219 1.00058 0.939263 0.878327 0.817848 0.757919 0.698646 0.640142 0.582539 0.525978 0.470617 + 0.416626 0.364194 0.313523 0.264835 0.218367 0.174376 0.133136 0.03125 + </DataArray> + <DataArray type="Float32" Name="rhoMolar" NumberOfComponents="1" format="ascii"> + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 + </DataArray> + <DataArray type="Float32" Name="rho" NumberOfComponents="1" format="ascii"> + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 + </DataArray> + <DataArray type="Float32" Name="velocity_component (m/s)" NumberOfComponents="1" format="ascii"> + 0.000771803 0.0017496 0.0025278 0.00422152 0.00719699 0.0118204 0.018458 0.0274759 0.0392404 0.0541178 0.0724741 0.0946756 + 0.121089 0.152079 0.188014 0.229258 0.276179 0.329142 0.388514 0.454661 0.527949 0.608744 0.697413 0.794322 + 0.899836 1.01432 1.13815 1.27168 1.41528 1.56932 1.73416 1.90966 + </DataArray> + <DataArray type="Float32" Name="process rank" NumberOfComponents="1" format="ascii"> + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + </DataArray> + <DataArray type="Float32" Name="pressureExact" NumberOfComponents="1" format="ascii"> + 1.96875 1.90625 1.84375 1.78125 1.71875 1.65625 1.59375 1.53125 1.46875 1.40625 1.34375 1.28125 + 1.21875 1.15625 1.09375 1.03125 0.96875 0.90625 0.84375 0.78125 0.71875 0.65625 0.59375 0.53125 + 0.46875 0.40625 0.34375 0.28125 0.21875 0.15625 0.09375 0.03125 + </DataArray> + <DataArray type="Float32" Name="velocityExact" NumberOfComponents="1" format="ascii"> + 7.62939e-06 0.000205994 0.000953674 0.00261688 0.00556183 0.0101547 0.0167618 0.0257492 0.0374832 0.05233 0.0706558 0.0928268 + 0.119209 0.150169 0.186073 0.227287 0.274178 0.32711 0.386452 0.452568 0.525826 0.60659 0.695229 0.792107 + 0.897591 1.01205 1.13584 1.26934 1.41291 1.56692 1.73173 1.90771 + </DataArray> + </CellData> + <Points> + <DataArray type="Float32" Name="Coordinates" NumberOfComponents="3" format="ascii"> + 0 0 0 0.03125 0 0 0.0625 0 0 0.09375 0 0 + 0.125 0 0 0.15625 0 0 0.1875 0 0 0.21875 0 0 + 0.25 0 0 0.28125 0 0 0.3125 0 0 0.34375 0 0 + 0.375 0 0 0.40625 0 0 0.4375 0 0 0.46875 0 0 + 0.5 0 0 0.53125 0 0 0.5625 0 0 0.59375 0 0 + 0.625 0 0 0.65625 0 0 0.6875 0 0 0.71875 0 0 + 0.75 0 0 0.78125 0 0 0.8125 0 0 0.84375 0 0 + 0.875 0 0 0.90625 0 0 0.9375 0 0 0.96875 0 0 + 1 0 0 + </DataArray> + </Points> + <Lines> + <DataArray type="Int32" Name="connectivity" NumberOfComponents="1" format="ascii"> + 0 1 1 2 2 3 3 4 4 5 5 6 + 6 7 7 8 8 9 9 10 10 11 11 12 + 12 13 13 14 14 15 15 16 16 17 17 18 + 18 19 19 20 20 21 21 22 22 23 23 24 + 24 25 25 26 26 27 27 28 28 29 29 30 + 30 31 31 32 + </DataArray> + <DataArray type="Int32" Name="offsets" NumberOfComponents="1" format="ascii"> + 2 4 6 8 10 12 14 16 18 20 22 24 + 26 28 30 32 34 36 38 40 42 44 46 48 + 50 52 54 56 58 60 62 64 + </DataArray> + </Lines> + </Piece> + </PolyData> +</VTKFile>