// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- // vi: set et ts=4 sw=4 sts=4: /* This file is part of the Open Porous Media project (OPM). OPM 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. OPM 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 OPM. If not, see . Consult the COPYING file in the top-level source directory of this module for the precise wording of the license and the list of copyright holders. */ /*! * \file * \copydoc Ewoms::EclBaseGridManager */ #ifndef EWOMS_ECL_BASE_GRID_MANAGER_HH #define EWOMS_ECL_BASE_GRID_MANAGER_HH #include #include #include #include #include #include #include #include #include #include #if HAVE_MPI #include #endif // HAVE_MPI #include #include #include namespace Ewoms { template class EclBaseGridManager; namespace Properties { NEW_TYPE_TAG(EclBaseGridManager); // declare the properties required by the for the ecl grid manager NEW_PROP_TAG(Grid); NEW_PROP_TAG(EquilGrid); NEW_PROP_TAG(Scalar); NEW_PROP_TAG(EclDeckFileName); SET_STRING_PROP(EclBaseGridManager, EclDeckFileName, "ECLDECK.DATA"); } // namespace Properties /*! * \ingroup EclBlackOilSimulator * * \brief Helper class for grid instantiation of ECL file-format using problems. */ template class EclBaseGridManager : public BaseGridManager { typedef BaseGridManager ParentType; typedef typename GET_PROP_TYPE(TypeTag, GridManager) Implementation; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator; public: typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; protected: static const int dimension = Grid::dimension; public: /*! * \brief Register all run-time parameters for the grid manager. */ static void registerParameters() { EWOMS_REGISTER_PARAM(TypeTag, std::string, EclDeckFileName, "The name of the file which contains the ECL deck to be simulated"); } /*! * \brief Create the grid for problem data files which use the ECL file format. * * This is the file format used by the commercial ECLiPSE simulator. Usually it uses * a cornerpoint description of the grid. */ EclBaseGridManager(Simulator& simulator) : ParentType(simulator) { int myRank = 0; #if HAVE_MPI MPI_Comm_rank(MPI_COMM_WORLD, &myRank); #endif std::string fileName = EWOMS_GET_PARAM(TypeTag, std::string, EclDeckFileName); // compute the base name of the input file name const char directorySeparator = '/'; long int i; for (i = fileName.size(); i >= 0; -- i) if (fileName[i] == directorySeparator) break; std::string baseName = fileName.substr(i + 1, fileName.size()); // remove the extension from the input file for (i = baseName.size(); i >= 0; -- i) if (baseName[i] == '.') break; std::string rawCaseName; if (i < 0) rawCaseName = baseName; else rawCaseName = baseName.substr(0, i); // transform the result to ALL_UPPERCASE caseName_ = rawCaseName; std::transform(caseName_.begin(), caseName_.end(), caseName_.begin(), ::toupper); if (myRank == 0) std::cout << "Reading the deck file '" << fileName << "'" << std::endl; if( ! simulator.simulatorParameter().first ) { Opm::Parser parser; typedef std::pair ParseModePair; typedef std::vector ParseModePairs; ParseModePairs tmp; tmp.push_back(ParseModePair(Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputError::IGNORE)); tmp.push_back(ParseModePair(Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputError::WARN)); tmp.push_back(ParseModePair(Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputError::WARN)); tmp.push_back(ParseModePair(Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputError::WARN)); Opm::ParseContext parseContext(tmp); deck_.reset( new Opm::Deck(parser.parseFile(fileName , parseContext)) ); eclState_.reset(new Opm::EclipseState(deck(), parseContext)); } else { deck_ = simulator.simulatorParameter().first; assert( simulator.simulatorParameter().second ); eclState_ = simulator.simulatorParameter().second; } asImp_().createGrids_(); asImp_().finalizeInit_(); } /*! * \brief Return a pointer to the parsed ECL deck */ const Opm::Deck& deck() const { return *deck_; } Opm::Deck& deck() { return *deck_; } /*! * \brief Return a pointer to the internalized ECL deck */ const Opm::EclipseState& eclState() const { return *eclState_; } Opm::EclipseState& eclState() { return *eclState_; } /*! * \brief Returns the name of the case. * * i.e., the all-uppercase version of the file name from which the * deck is loaded with the ".DATA" suffix removed. */ const std::string& caseName() const { return caseName_; } /*! * \brief Returns the number of logically Cartesian cells in each direction */ const std::array& cartesianDimensions() const { return asImp_().cartesianIndexMapper().cartesianDimensions(); } /*! * \brief Returns the overall number of cells of the logically Cartesian grid */ int cartesianSize() const { return asImp_().cartesianIndexMapper().cartesianSize(); } /*! * \brief Returns the overall number of cells of the logically EquilCartesian grid */ int equilCartesianSize() const { return asImp_().equilCartesianIndexMapper().cartesianSize(); } /*! * \brief Returns the Cartesian cell id for identifaction with ECL data */ unsigned cartesianIndex(unsigned compressedCellIdx) const { return asImp_().cartesianIndexMapper().cartesianIndex(compressedCellIdx); } /*! * \brief Return the index of the cells in the logical Cartesian grid */ unsigned cartesianIndex(const std::array& coords) const { unsigned cartIndex = coords[0]; int factor = cartesianDimensions()[0]; for (unsigned i = 1; i < dimension; ++i) { cartIndex += coords[i]*factor; factor *= cartesianDimensions()[i]; } return cartIndex; } /*! * \brief Extract Cartesian index triplet (i,j,k) of an active cell. * * \param [in] cellIdx Active cell index. * \param [out] ijk Cartesian index triplet */ void cartesianCoordinate(unsigned cellIdx, std::array& ijk) const { return asImp_().cartesianIndexMapper().cartesianCoordinate(cellIdx, ijk); } /*! * \brief Returns the Cartesian cell id given an element index for the grid used for equilibration */ unsigned equilCartesianIndex(unsigned compressedEquilCellIdx) const { return asImp_().equilCartesianIndexMapper().cartesianIndex(compressedEquilCellIdx); } /*! * \brief Extract Cartesian index triplet (i,j,k) of an active cell of the grid used for EQUIL. * * \param [in] cellIdx Active cell index. * \param [out] ijk Cartesian index triplet */ void equilCartesianCoordinate(unsigned cellIdx, std::array& ijk) const { return asImp_().equilCartesianIndexMapper().cartesianCoordinate(cellIdx, ijk); } /*! * \brief Return the names of the wells which do not penetrate any cells on the local * process. * * This is a kludge around the fact that for distributed grids, not all wells are * seen by all proccesses. */ std::unordered_set defunctWellNames() const { return std::unordered_set(); } private: Implementation& asImp_() { return *static_cast(this); } const Implementation& asImp_() const { return *static_cast(this); } std::string caseName_; std::shared_ptr deck_; std::shared_ptr eclState_; }; } // namespace Ewoms #endif