2012-02-20 11:34:27 +01:00
|
|
|
/*
|
|
|
|
|
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
|
|
|
|
|
|
|
|
|
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 3 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-04-10 12:56:14 +02:00
|
|
|
#include "config.h"
|
2014-04-22 14:50:01 +02:00
|
|
|
|
2013-03-18 10:16:46 +01:00
|
|
|
#include <opm/core/grid/GridManager.hpp>
|
2012-02-20 11:34:27 +01:00
|
|
|
#include <opm/core/grid.h>
|
2012-04-11 11:27:45 +02:00
|
|
|
#include <opm/core/grid/cart_grid.h>
|
|
|
|
|
#include <opm/core/grid/cornerpoint_grid.h>
|
2014-08-25 15:20:41 +02:00
|
|
|
#include <opm/core/grid/MinpvProcessor.hpp>
|
2015-10-08 11:42:15 +02:00
|
|
|
#include <opm/common/ErrorMacros.hpp>
|
2016-01-24 23:09:47 +01:00
|
|
|
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
|
|
|
|
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
2016-01-20 14:12:04 +01:00
|
|
|
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
2014-08-21 14:21:21 +02:00
|
|
|
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
2014-01-24 11:58:20 +01:00
|
|
|
|
|
|
|
|
#include <array>
|
2012-08-09 14:28:13 +02:00
|
|
|
#include <algorithm>
|
|
|
|
|
#include <numeric>
|
2012-02-20 11:34:27 +01:00
|
|
|
|
|
|
|
|
namespace Opm
|
|
|
|
|
{
|
2014-08-25 15:20:41 +02:00
|
|
|
|
2012-02-20 11:34:27 +01:00
|
|
|
/// Construct a 3d corner-point grid from a deck.
|
2014-08-21 14:21:21 +02:00
|
|
|
GridManager::GridManager(Opm::EclipseGridConstPtr eclipseGrid)
|
|
|
|
|
: ug_(0)
|
|
|
|
|
{
|
2014-08-25 15:20:41 +02:00
|
|
|
initFromEclipseGrid(eclipseGrid, std::vector<double>());
|
2014-04-22 14:50:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-04-26 12:03:07 +02:00
|
|
|
GridManager::GridManager(Opm::DeckConstPtr deck)
|
2014-08-21 14:21:21 +02:00
|
|
|
: ug_(0)
|
2014-01-24 11:58:20 +01:00
|
|
|
{
|
2014-08-21 15:24:39 +02:00
|
|
|
auto eclipseGrid = std::make_shared<const Opm::EclipseGrid>(deck);
|
2014-08-25 15:20:41 +02:00
|
|
|
initFromEclipseGrid(eclipseGrid, std::vector<double>());
|
2014-01-24 11:58:20 +01:00
|
|
|
}
|
2012-02-20 11:34:27 +01:00
|
|
|
|
|
|
|
|
|
2014-08-25 15:20:41 +02:00
|
|
|
GridManager::GridManager(Opm::EclipseGridConstPtr eclipseGrid,
|
|
|
|
|
const std::vector<double>& poreVolumes)
|
|
|
|
|
: ug_(0)
|
|
|
|
|
{
|
|
|
|
|
initFromEclipseGrid(eclipseGrid, poreVolumes);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-20 11:34:27 +01:00
|
|
|
|
|
|
|
|
/// Construct a 2d cartesian grid with cells of unit size.
|
|
|
|
|
GridManager::GridManager(int nx, int ny)
|
|
|
|
|
{
|
2012-11-15 13:20:49 +01:00
|
|
|
ug_ = create_grid_cart2d(nx, ny, 1.0, 1.0);
|
2012-06-27 20:20:05 +02:00
|
|
|
if (!ug_) {
|
2013-08-28 13:59:03 +02:00
|
|
|
OPM_THROW(std::runtime_error, "Failed to construct grid.");
|
2012-06-27 20:20:05 +02:00
|
|
|
}
|
2012-02-20 11:34:27 +01:00
|
|
|
}
|
|
|
|
|
|
2012-11-15 13:20:49 +01:00
|
|
|
GridManager::GridManager(int nx, int ny,double dx, double dy)
|
|
|
|
|
{
|
|
|
|
|
ug_ = create_grid_cart2d(nx, ny, dx, dy);
|
|
|
|
|
if (!ug_) {
|
2013-08-28 13:59:03 +02:00
|
|
|
OPM_THROW(std::runtime_error, "Failed to construct grid.");
|
2012-11-15 13:20:49 +01:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-20 11:34:27 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Construct a 3d cartesian grid with cells of unit size.
|
|
|
|
|
GridManager::GridManager(int nx, int ny, int nz)
|
|
|
|
|
{
|
2012-06-27 20:20:05 +02:00
|
|
|
ug_ = create_grid_cart3d(nx, ny, nz);
|
|
|
|
|
if (!ug_) {
|
2013-08-28 13:59:03 +02:00
|
|
|
OPM_THROW(std::runtime_error, "Failed to construct grid.");
|
2012-06-27 20:20:05 +02:00
|
|
|
}
|
2012-02-20 11:34:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Construct a 3d cartesian grid with cells of size [dx, dy, dz].
|
|
|
|
|
GridManager::GridManager(int nx, int ny, int nz,
|
2012-04-11 12:35:19 +02:00
|
|
|
double dx, double dy, double dz)
|
2012-02-20 11:34:27 +01:00
|
|
|
{
|
2012-06-27 20:20:05 +02:00
|
|
|
ug_ = create_grid_hexa3d(nx, ny, nz, dx, dy, dz);
|
|
|
|
|
if (!ug_) {
|
2013-08-28 13:59:03 +02:00
|
|
|
OPM_THROW(std::runtime_error, "Failed to construct grid.");
|
2012-06-27 20:20:05 +02:00
|
|
|
}
|
2012-02-20 11:34:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-25 13:23:50 +02:00
|
|
|
/// Construct a grid from an input file.
|
|
|
|
|
/// The file format used is currently undocumented,
|
|
|
|
|
/// and is therefore only suited for internal use.
|
|
|
|
|
GridManager::GridManager(const std::string& input_filename)
|
|
|
|
|
{
|
|
|
|
|
ug_ = read_grid(input_filename.c_str());
|
|
|
|
|
if (!ug_) {
|
2013-08-28 13:59:03 +02:00
|
|
|
OPM_THROW(std::runtime_error, "Failed to read grid from file " << input_filename);
|
2012-10-25 13:23:50 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-20 11:34:27 +01:00
|
|
|
/// Destructor.
|
|
|
|
|
GridManager::~GridManager()
|
|
|
|
|
{
|
2012-06-27 20:20:05 +02:00
|
|
|
destroy_grid(ug_);
|
2012-02-20 11:34:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Access the managed UnstructuredGrid.
|
|
|
|
|
/// The method is named similarly to c_str() in std::string,
|
|
|
|
|
/// to make it clear that we are returning a C-compatible struct.
|
|
|
|
|
const UnstructuredGrid* GridManager::c_grid() const
|
|
|
|
|
{
|
2012-06-27 20:20:05 +02:00
|
|
|
return ug_;
|
2012-02-20 11:34:27 +01:00
|
|
|
}
|
|
|
|
|
|
2014-08-21 14:21:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Construct corner-point grid from EclipseGrid.
|
2014-08-25 15:20:41 +02:00
|
|
|
void GridManager::initFromEclipseGrid(Opm::EclipseGridConstPtr eclipseGrid,
|
|
|
|
|
const std::vector<double>& poreVolumes)
|
2014-01-24 11:58:20 +01:00
|
|
|
{
|
2014-08-21 14:21:21 +02:00
|
|
|
struct grdecl g;
|
|
|
|
|
std::vector<int> actnum;
|
|
|
|
|
std::vector<double> coord;
|
|
|
|
|
std::vector<double> zcorn;
|
|
|
|
|
std::vector<double> mapaxes;
|
|
|
|
|
|
|
|
|
|
g.dims[0] = eclipseGrid->getNX();
|
|
|
|
|
g.dims[1] = eclipseGrid->getNY();
|
|
|
|
|
g.dims[2] = eclipseGrid->getNZ();
|
|
|
|
|
|
|
|
|
|
eclipseGrid->exportMAPAXES( mapaxes );
|
|
|
|
|
eclipseGrid->exportCOORD( coord );
|
|
|
|
|
eclipseGrid->exportZCORN( zcorn );
|
|
|
|
|
eclipseGrid->exportACTNUM( actnum );
|
|
|
|
|
|
|
|
|
|
g.coord = coord.data();
|
|
|
|
|
g.zcorn = zcorn.data();
|
|
|
|
|
g.actnum = actnum.data();
|
|
|
|
|
g.mapaxes = mapaxes.data();
|
2014-01-24 11:58:20 +01:00
|
|
|
|
2015-02-12 16:04:41 +08:00
|
|
|
if (!poreVolumes.empty() && (eclipseGrid->getMinpvMode() != MinpvMode::ModeEnum::Inactive)) {
|
2014-08-25 15:20:41 +02:00
|
|
|
MinpvProcessor mp(g.dims[0], g.dims[1], g.dims[2]);
|
2015-02-12 16:04:41 +08:00
|
|
|
const double minpv_value = eclipseGrid->getMinpvValue();
|
2015-12-08 11:04:54 +01:00
|
|
|
// Currently the pinchProcessor is not used and only opmfil is supported
|
|
|
|
|
//bool opmfil = eclipseGrid->getMinpvMode() == MinpvMode::OpmFIL;
|
|
|
|
|
bool opmfil = true;
|
2015-10-19 15:22:26 +02:00
|
|
|
mp.process(poreVolumes, minpv_value, actnum, opmfil, zcorn.data());
|
2014-08-25 15:20:41 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-21 14:32:13 +02:00
|
|
|
const double z_tolerance = eclipseGrid->isPinchActive() ?
|
|
|
|
|
eclipseGrid->getPinchThresholdThickness() : 0.0;
|
|
|
|
|
ug_ = create_grid_cornerpoint(&g, z_tolerance);
|
2014-01-24 11:58:20 +01:00
|
|
|
if (!ug_) {
|
|
|
|
|
OPM_THROW(std::runtime_error, "Failed to construct grid.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 14:21:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-04-26 12:03:07 +02:00
|
|
|
void GridManager::createGrdecl(Opm::DeckConstPtr deck, struct grdecl &grdecl)
|
2014-01-24 11:58:20 +01:00
|
|
|
{
|
|
|
|
|
// Extract data from deck.
|
2014-04-26 12:03:07 +02:00
|
|
|
const std::vector<double>& zcorn = deck->getKeyword("ZCORN")->getSIDoubleData();
|
|
|
|
|
const std::vector<double>& coord = deck->getKeyword("COORD")->getSIDoubleData();
|
2014-01-24 11:58:20 +01:00
|
|
|
const int* actnum = NULL;
|
2014-04-26 12:03:07 +02:00
|
|
|
if (deck->hasKeyword("ACTNUM")) {
|
|
|
|
|
actnum = &(deck->getKeyword("ACTNUM")->getIntData()[0]);
|
2014-01-24 11:58:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::array<int, 3> dims;
|
2014-04-26 12:03:07 +02:00
|
|
|
if (deck->hasKeyword("DIMENS")) {
|
|
|
|
|
Opm::DeckKeywordConstPtr dimensKeyword = deck->getKeyword("DIMENS");
|
2014-01-24 11:58:20 +01:00
|
|
|
dims[0] = dimensKeyword->getRecord(0)->getItem(0)->getInt(0);
|
|
|
|
|
dims[1] = dimensKeyword->getRecord(0)->getItem(1)->getInt(0);
|
|
|
|
|
dims[2] = dimensKeyword->getRecord(0)->getItem(2)->getInt(0);
|
2014-04-26 12:03:07 +02:00
|
|
|
} else if (deck->hasKeyword("SPECGRID")) {
|
|
|
|
|
Opm::DeckKeywordConstPtr specgridKeyword = deck->getKeyword("SPECGRID");
|
2014-01-24 11:58:20 +01:00
|
|
|
dims[0] = specgridKeyword->getRecord(0)->getItem(0)->getInt(0);
|
|
|
|
|
dims[1] = specgridKeyword->getRecord(0)->getItem(1)->getInt(0);
|
|
|
|
|
dims[2] = specgridKeyword->getRecord(0)->getItem(2)->getInt(0);
|
|
|
|
|
} else {
|
|
|
|
|
OPM_THROW(std::runtime_error, "Deck must have either DIMENS or SPECGRID.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collect in input struct for preprocessing.
|
|
|
|
|
|
|
|
|
|
grdecl.zcorn = &zcorn[0];
|
|
|
|
|
grdecl.coord = &coord[0];
|
|
|
|
|
grdecl.actnum = actnum;
|
|
|
|
|
grdecl.dims[0] = dims[0];
|
|
|
|
|
grdecl.dims[1] = dims[1];
|
|
|
|
|
grdecl.dims[2] = dims[2];
|
|
|
|
|
|
2014-04-26 12:03:07 +02:00
|
|
|
if (deck->hasKeyword("MAPAXES")) {
|
|
|
|
|
Opm::DeckKeywordConstPtr mapaxesKeyword = deck->getKeyword("MAPAXES");
|
2014-01-24 11:58:20 +01:00
|
|
|
Opm::DeckRecordConstPtr mapaxesRecord = mapaxesKeyword->getRecord(0);
|
|
|
|
|
|
|
|
|
|
// memleak alert: here we need to make sure that C code
|
|
|
|
|
// can properly take ownership of the grdecl.mapaxes
|
|
|
|
|
// object. if it is not freed, it will result in a
|
|
|
|
|
// memleak...
|
|
|
|
|
double *cWtfMapaxes = static_cast<double*>(malloc(sizeof(double)*mapaxesRecord->size()));
|
|
|
|
|
for (unsigned i = 0; i < mapaxesRecord->size(); ++i)
|
|
|
|
|
cWtfMapaxes[i] = mapaxesRecord->getItem(i)->getSIDouble(0);
|
|
|
|
|
grdecl.mapaxes = cWtfMapaxes;
|
|
|
|
|
} else
|
|
|
|
|
grdecl.mapaxes = NULL;
|
|
|
|
|
|
|
|
|
|
}
|
2012-08-09 14:28:13 +02:00
|
|
|
|
2014-08-25 15:20:41 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-02-20 11:34:27 +01:00
|
|
|
} // namespace Opm
|