From 85609c7a20c0e7ff66d918c9faf1367caf518bc5 Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de> Date: Mon, 13 Nov 2017 13:56:31 +0100 Subject: [PATCH] [NavierStokesNC][test] Make test_channel work again * Does not pass yet --- .../staggerednc/channeltestproblem.hh | 107 +++++---- test/freeflow/staggerednc/test_channel.cc | 210 +++++++++++++++++- 2 files changed, 256 insertions(+), 61 deletions(-) diff --git a/test/freeflow/staggerednc/channeltestproblem.hh b/test/freeflow/staggerednc/channeltestproblem.hh index f0dfab82ab..6f63c5c46e 100644 --- a/test/freeflow/staggerednc/channeltestproblem.hh +++ b/test/freeflow/staggerednc/channeltestproblem.hh @@ -24,13 +24,13 @@ #ifndef DUMUX_CHANNEL_NC_TEST_PROBLEM_HH #define DUMUX_CHANNEL_NC_TEST_PROBLEM_HH -#include <dumux/implicit/staggered/properties.hh> -#include <dumux/freeflow/staggerednc/model.hh> -#include <dumux/implicit/problem.hh> +#include <dumux/freeflow/staggered/problem.hh> +#include <dumux/discretization/staggered/properties.hh> #include <dumux/material/components/simpleh2o.hh> - #include <dumux/material/fluidsystems/h2oair.hh> +#include <dumux/freeflow/staggerednc/properties.hh> + namespace Dumux { template <class TypeTag> @@ -80,7 +80,6 @@ SET_BOOL_PROP(ChannelNCTestProblem, EnableGlobalFluxVariablesCache, true); SET_BOOL_PROP(ChannelNCTestProblem, EnableGlobalVolumeVariablesCache, true); // Enable gravity -SET_BOOL_PROP(ChannelNCTestProblem, ProblemEnableGravity, true); SET_BOOL_PROP(ChannelNCTestProblem, UseMoles, true); // #if ENABLE_NAVIERSTOKES @@ -97,14 +96,13 @@ SET_BOOL_PROP(ChannelNCTestProblem, EnableInertiaTerms, true); template <class TypeTag> class ChannelNCTestProblem : public NavierStokesProblem<TypeTag> { - typedef NavierStokesProblem<TypeTag> ParentType; - - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + using ParentType = NavierStokesProblem<TypeTag>; + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); // copy some indices for convenience - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + using Indices = typename GET_PROP_TYPE(TypeTag, Indices); enum { // Grid and world dimension dim = GridView::dimension, @@ -126,17 +124,15 @@ class ChannelNCTestProblem : public NavierStokesProblem<TypeTag> transportCompIdx = 1/*FluidSystem::wCompIdx*/ }; - typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; + using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GridView::Intersection Intersection; + using Element = typename GridView::template Codim<0>::Entity; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); + using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; using CellCenterPrimaryVariables = typename GET_PROP_TYPE(TypeTag, CellCenterPrimaryVariables); using FacePrimaryVariables = typename GET_PROP_TYPE(TypeTag, FacePrimaryVariables); @@ -145,20 +141,17 @@ class ChannelNCTestProblem : public NavierStokesProblem<TypeTag> using InitialValues = typename GET_PROP_TYPE(TypeTag, BoundaryValues); using SourceValues = typename GET_PROP_TYPE(TypeTag, BoundaryValues); + using TimeLoopPtr = std::shared_ptr<CheckPointTimeLoop<Scalar>>; + using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + public: - ChannelNCTestProblem(TimeManager &timeManager, const GridView &gridView) - : ParentType(timeManager, gridView) + ChannelNCTestProblem(std::shared_ptr<const FVGridGeometry> fvGridGeometry) + : ParentType(fvGridGeometry), eps_(1e-6) { - name_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, - std::string, - Problem, - Name); - - inletVelocity_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, - Scalar, - Problem, - InletVelocity); + inletVelocity_ = getParam<Scalar>("Problem.InletVelocity"); FluidSystem::init(); + deltaP_.resize(this->fvGridGeometry().numCellCenterDofs()); } /*! @@ -166,15 +159,6 @@ public: */ // \{ - /*! - * \brief The problem name. - * - * This is used as a prefix for files generated by the simulation. - */ - std::string name() const - { - return name_; - } bool shouldWriteRestartFile() const { @@ -257,10 +241,8 @@ public: { BoundaryValues values = initialAtPos(globalPos); - const Scalar time = this->timeManager().time() + this->timeManager().timeStepSize(); - // give the system some time so that the pressure can equilibrate, then start the injection of the tracer - if(isInlet(globalPos) && time > 20.0) + if(isInlet(globalPos) && time() >= 20.0) { values[transportCompIdx] = 1e-3; #if NONISOTHERMAL @@ -293,8 +275,8 @@ public: #endif // parabolic velocity profile - values[velocityXIdx] = inletVelocity_*(globalPos[1] - this->bBoxMin()[1])*(this->bBoxMax()[1] - globalPos[1]) - / (0.25*(this->bBoxMax()[1] - this->bBoxMin()[1])*(this->bBoxMax()[1] - this->bBoxMin()[1])); + values[velocityXIdx] = inletVelocity_*(globalPos[1] - this->fvGridGeometry().bBoxMin()[1])*(this->fvGridGeometry().bBoxMax()[1] - globalPos[1]) + / (0.25*(this->fvGridGeometry().bBoxMax()[1] - this->fvGridGeometry().bBoxMin()[1])*(this->fvGridGeometry().bBoxMax()[1] - this->fvGridGeometry().bBoxMin()[1])); values[velocityYIdx] = 0.0; @@ -304,29 +286,41 @@ public: /*! * \brief Adds additional VTK output data to the VTKWriter. Function is called by the output module on every write. */ - template<class VtkOutputModule> - void addVtkOutputFields(VtkOutputModule& outputModule) const + void calculateDeltaP(const GridVariables& gridVariables, const SolutionVector& sol) { - auto& deltaP = outputModule.createScalarField("deltaP", 0); - - for (const auto& element : elements(this->gridView())) + for (const auto& element : elements(this->fvGridGeometry().gridView())) { - auto fvGeometry = localView(this->model().fvGridGeometry()); + auto fvGeometry = localView(this->fvGridGeometry()); fvGeometry.bindElement(element); for (auto&& scv : scvs(fvGeometry)) { auto ccDofIdx = scv.dofIndex(); - auto elemVolVars = localView(this->model().curGlobalVolVars()); - elemVolVars.bind(element, fvGeometry, this->model().curSol()); + auto elemVolVars = localView(gridVariables.curGridVolVars()); + elemVolVars.bind(element, fvGeometry, sol); - deltaP[ccDofIdx] = elemVolVars[scv].pressure() - 1.1e5; + deltaP_[ccDofIdx] = elemVolVars[scv].pressure() - 1.1e5; } } } + auto& getDeltaP() const + { return deltaP_; } + // \} + void setTimeLoop(TimeLoopPtr timeLoop) + { + timeLoop_ = timeLoop; + // if(inletVelocity_ > eps_) + timeLoop_->setCheckPoint({20.0}); + } + + Scalar time() const + { + return timeLoop_->time(); + } + private: bool isInlet(const GlobalPosition& globalPos) const @@ -336,17 +330,18 @@ private: bool isOutlet(const GlobalPosition& globalPos) const { - return globalPos[0] > this->bBoxMax()[0] - eps_; + return globalPos[0] > this->fvGridGeometry().bBoxMax()[0] - eps_; } bool isWall(const GlobalPosition& globalPos) const { - return globalPos[0] > eps_ || globalPos[0] < this->bBoxMax()[0] - eps_; + return globalPos[0] > eps_ || globalPos[0] < this->fvGridGeometry().bBoxMax()[0] - eps_; } - const Scalar eps_{1e-6}; + const Scalar eps_; Scalar inletVelocity_; - std::string name_; + TimeLoopPtr timeLoop_; + std::vector<Scalar> deltaP_; }; } //end namespace diff --git a/test/freeflow/staggerednc/test_channel.cc b/test/freeflow/staggerednc/test_channel.cc index ab0ed70cf8..0e0d0cc4c8 100644 --- a/test/freeflow/staggerednc/test_channel.cc +++ b/test/freeflow/staggerednc/test_channel.cc @@ -21,9 +21,36 @@ * * \brief Test for the staggered grid multi-component (Navier-)Stokes model */ -#include <config.h> + #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 "channeltestproblem.hh" -#include <dumux/common/start.hh> + +#include <dumux/common/propertysystem.hh> +#include <dumux/common/parameters.hh> +#include <dumux/common/valgrind.hh> +#include <dumux/common/dumuxmessage.hh> +#include <dumux/common/defaultusagemessage.hh> + +#include <dumux/linear/seqsolverbackend.hh> +#include <dumux/nonlinear/newtonmethod.hh> +#include <dumux/nonlinear/newtoncontroller.hh> + +#include <dumux/assembly/staggeredfvassembler.hh> +#include <dumux/assembly/diffmethod.hh> +#include <dumux/implicit/staggered/newtoncontroller.hh> + +#include <dumux/discretization/methods.hh> + +#include <dumux/io/vtkoutputmodule.hh> /*! * \brief Provides an interface for customizing error messages associated with @@ -57,8 +84,181 @@ void usage(const char *progName, const std::string &errorMsg) } } -int main(int argc, char** argv) +int main(int argc, char** argv) try +{ + using namespace Dumux; + + // define the type tag for this problem + using TypeTag = TTAG(ChannelNCTestProblem); + + // 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 (initial and boundary conditions) + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + auto problem = std::make_shared<Problem>(fvGridGeometry); + + // get some time loop parameters + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + const auto tEnd = getParam<Scalar>("TimeLoop.TEnd"); + const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions"); + const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize"); + auto dt = getParam<Scalar>("TimeLoop.DtInitial"); + + // check if we are about to restart a previously interrupted simulation + Scalar restartTime = 0; + if (Parameters::getTree().hasKey("Restart") || Parameters::getTree().hasKey("TimeLoop.Restart")) + restartTime = getParam<Scalar>("TimeLoop.Restart"); + + // instantiate time loop + auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(restartTime, dt, tEnd); + timeLoop->setMaxTimeStepSize(maxDt); + problem->setTimeLoop(timeLoop); + + // the solution vector + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using DofTypeIndices = typename GET_PROP(TypeTag, DofTypeIndices); + typename DofTypeIndices::CellCenterIdx cellCenterIdx; + typename DofTypeIndices::FaceIdx faceIdx; + const auto numDofsCellCenter = leafGridView.size(0); + const auto numDofsFace = leafGridView.size(1); + SolutionVector x; + x[cellCenterIdx].resize(numDofsCellCenter); + x[faceIdx].resize(numDofsFace); + problem->applyInitialSolution(x); + auto xOld = x; + + // the grid variables + using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry); + gridVariables->init(x, xOld); + + // intialize the vtk output module + using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); + VtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); + VtkOutputFields::init(vtkWriter); //! Add model specific output fields + vtkWriter.addField(problem->getDeltaP(), "deltaP"); + 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, timeLoop); + + // the linear solver + using LinearSolver = Dumux::UMFPackBackend<TypeTag>; + auto linearSolver = std::make_shared<LinearSolver>(); + + // the non-linear solver + using NewtonController = StaggeredNewtonController<TypeTag>; + using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>; + auto newtonController = std::make_shared<NewtonController>(leafGridView.comm(), timeLoop); + NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver); + + // time loop + timeLoop->start(); do + { + // set previous solution for storage evaluations + assembler->setPreviousSolution(xOld); + + // try solving the non-linear system + for (int i = 0; i < maxDivisions; ++i) + { + // linearize & solve + auto converged = nonLinearSolver.solve(x); + + if (converged) + break; + + if (!converged && i == maxDivisions-1) + DUNE_THROW(Dune::MathError, + "Newton solver didn't converge after " + << maxDivisions + << " time-step divisions. dt=" + << timeLoop->timeStepSize() + << ".\nThe solutions of the current and the previous time steps " + << "have been saved to restart files."); + } + + // make the new solution the old solution + xOld = x; + gridVariables->advanceTimeStep(); + + // advance to the time loop to the next step + timeLoop->advanceTimeStep(); + + problem->calculateDeltaP(*gridVariables, x); + + // write vtk output + vtkWriter.write(timeLoop->time()); + + // report statistics of this time step + timeLoop->reportTimeStep(); + + // set new dt as suggested by newton controller + timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize())); + + } while (!timeLoop->finished()); + + timeLoop->finalize(leafGridView.comm()); + + //////////////////////////////////////////////////////////// + // 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 (...) { - typedef TTAG(ChannelNCTestProblem) ProblemTypeTag; - return Dumux::start<ProblemTypeTag>(argc, argv, usage); + std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; + return 4; } -- GitLab