// -*- 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 . * *****************************************************************************/ /*! * \file * * \brief The porous medium sub problem */ #ifndef DUMUX_DARCY2P2C_SUBPROBLEM_HH #define DUMUX_DARCY2P2C_SUBPROBLEM_HH #include #include #include #include namespace Dumux { /*! * \brief The porous medium sub problem */ template class PorousMediumSubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; using GridView = typename GetPropType::GridView; using Scalar = GetPropType; using PrimaryVariables = GetPropType; using NumEqVector = GetPropType; using BoundaryTypes = GetPropType; using VolumeVariables = GetPropType; using FVElementGeometry = typename GetPropType::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using FVGridGeometry = GetPropType; using ElementVolumeVariables = typename GetPropType::LocalView; using GridVariables = GetPropType; using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; using FluidSystem = GetPropType; // copy some indices for convenience using Indices = typename GetPropType::Indices; enum { // primary variable indices conti0EqIdx = Indices::conti0EqIdx, contiWEqIdx = Indices::conti0EqIdx + FluidSystem::H2OIdx, contiNEqIdx = Indices::conti0EqIdx + FluidSystem::AirIdx, pressureIdx = Indices::pressureIdx, switchIdx = Indices::switchIdx }; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; using DiffusionCoefficientAveragingType = typename StokesDarcyCouplingOptions::DiffusionCoefficientAveragingType; public: PorousMediumSubProblem(std::shared_ptr fvGridGeometry, std::shared_ptr couplingManager) : ParentType(fvGridGeometry, "Darcy"), eps_(1e-7), couplingManager_(couplingManager) { pressure_ = getParamFromGroup(this->paramGroup(), "Problem.Pressure"); initialSw_ = getParamFromGroup(this->paramGroup(), "Problem.Saturation"); temperature_ = getParamFromGroup(this->paramGroup(), "Problem.Temperature"); initialPhasePresence_ = getParamFromGroup(this->paramGroup(), "Problem.InitPhasePresence"); diffCoeffAvgType_ = StokesDarcyCouplingOptions::stringToEnum(DiffusionCoefficientAveragingType{}, getParamFromGroup(this->paramGroup(), "Problem.InterfaceDiffusionCoefficientAvg")); } /*! * \name Simulation steering */ // \{ template void postTimeStep(const SolutionVector& curSol, const GridVariables& gridVariables, const Scalar timeStepSize) { // compute the mass in the entire domain Scalar massWater = 0.0; // bulk elements for (const auto& element : elements(this->gridGeometry().gridView())) { auto fvGeometry = localView(this->gridGeometry()); fvGeometry.bindElement(element); auto elemVolVars = localView(gridVariables.curGridVolVars()); elemVolVars.bindElement(element, fvGeometry, curSol); for (auto&& scv : scvs(fvGeometry)) { const auto& volVars = elemVolVars[scv]; for(int phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) { massWater += volVars.massFraction(phaseIdx, FluidSystem::H2OIdx)*volVars.density(phaseIdx) * scv.volume() * volVars.saturation(phaseIdx) * volVars.porosity() * volVars.extrusionFactor(); } } } std::cout << "mass of water is: " << massWater << std::endl; } /*! * \brief Return the temperature within the domain in [K]. */ Scalar temperature() const { return temperature_; } // \} /*! * \name Boundary conditions */ // \{ /*! * \brief Specifies which kind of boundary condition should be * used for which equation on a given boundary control volume. * * \param element The element * \param scvf The boundary sub control volume face */ BoundaryTypes boundaryTypes(const Element &element, const SubControlVolumeFace &scvf) const { BoundaryTypes values; values.setAllNeumann(); if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) values.setAllCouplingNeumann(); return values; } /*! * \brief Evaluate the boundary conditions for a Dirichlet control volume. * * \param element The element for which the Dirichlet boundary condition is set * \param scvf The boundary subcontrolvolumeface * * For this method, the \a values parameter stores primary variables. */ PrimaryVariables dirichlet(const Element &element, const SubControlVolumeFace &scvf) const { PrimaryVariables values(0.0); values = initialAtPos(scvf.center()); return values; } /*! * \brief Evaluate the boundary conditions for a Neumann * control volume. * * \param element The element for which the Neumann boundary condition is set * \param fvGeomentry The fvGeometry * \param elemVolVars The element volume variables * \param scvf The boundary sub control volume face * */ NumEqVector neumann(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, const ElementFluxVariablesCache& elemFluxVarsCache, const SubControlVolumeFace& scvf) const { NumEqVector values(0.0); if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) { const auto massFlux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); for(int i = 0; i< massFlux.size(); ++i) values[i] = massFlux[i]; values[Indices::energyEqIdx] = couplingManager().couplingData().energyCouplingCondition(element, fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); } return values; } // \} /*! * \name Volume terms */ // \{ /*! * \brief Evaluate the source term for all phases within a given * sub-control-volume. * * \param element The element for which the source term is set * \param fvGeomentry The fvGeometry * \param elemVolVars The element volume variables * \param scv The subcontrolvolume * * For this method, the \a values variable stores the rate mass * of a component is generated or annihilate per volume * unit. Positive values mean that mass is created, negative ones * mean that it vanishes. */ NumEqVector source(const Element &element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, const SubControlVolume &scv) const { return NumEqVector(0.0); } // \} /*! * \brief Evaluate the initial value for a control volume. * * For this method, the \a priVars parameter stores primary * variables. */ PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { PrimaryVariables values(0.0); values.setState(initialPhasePresence_); values[pressureIdx] = pressure_ + 1. * this->spatialParams().gravity(globalPos)[1] * (globalPos[1] - this->gridGeometry().bBoxMax()[1]); values[switchIdx] = initialSw_; values[Indices::temperatureIdx] = temperature_; return values; } // \} /*! * \brief Set the coupling manager */ void setCouplingManager(std::shared_ptr cm) { couplingManager_ = cm; } /*! * \brief Get the coupling manager */ const CouplingManager& couplingManager() const { return *couplingManager_; } void setTimeLoop(TimeLoopPtr timeLoop) { timeLoop_ = timeLoop; } private: bool onLeftBoundary_(const GlobalPosition &globalPos) const { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; } bool onRightBoundary_(const GlobalPosition &globalPos) const { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; } bool onLowerBoundary_(const GlobalPosition &globalPos) const { return globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_; } bool onUpperBoundary_(const GlobalPosition &globalPos) const { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; } Scalar pressure_; Scalar initialSw_; Scalar temperature_; int initialPhasePresence_; TimeLoopPtr timeLoop_; Scalar eps_; std::shared_ptr couplingManager_; DiffusionCoefficientAveragingType diffCoeffAvgType_; }; } //end namespace dUMUX #endif