20#ifndef OPM_CORNERPOINTCHOPPER_HEADER_INCLUDED
21#define OPM_CORNERPOINTCHOPPER_HEADER_INCLUDED
23#include <opm/input/eclipse/Parser/Parser.hpp>
24#include <opm/input/eclipse/Units/UnitSystem.hpp>
25#include <opm/input/eclipse/Deck/Deck.hpp>
26#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
27#include <opm/input/eclipse/Deck/DeckRecord.hpp>
28#include <opm/input/eclipse/Deck/DeckItem.hpp>
44 deck_(parser_.parseFile(file)),
45 metricUnits_(
Opm::UnitSystem::newMETRIC())
47 const auto& specgridRecord = deck_[
"SPECGRID"].back().getRecord(0);
48 dims_[0] = specgridRecord.getItem(
"NX").get<
int >(0);
49 dims_[1] = specgridRecord.getItem(
"NY").get<
int >(0);
50 dims_[2] = specgridRecord.getItem(
"NZ").get<
int >(0);
52 int layersz = 8*dims_[0]*dims_[1];
53 const std::vector<double>& ZCORN = deck_[
"ZCORN"].back().getRawDoubleData();
54 botmax_ = *std::max_element(ZCORN.begin(), ZCORN.begin() + layersz/2);
55 topmin_ = *std::min_element(ZCORN.begin() + dims_[2]*layersz - layersz/2,
56 ZCORN.begin() + dims_[2]*layersz);
58 abszmax_ = *std::max_element(ZCORN.begin(), ZCORN.end());
59 abszmin_ = *std::min_element(ZCORN.begin(), ZCORN.end());
61 std::cout <<
"Parsed grdecl file with dimensions ("
62 << dims_[0] <<
", " << dims_[1] <<
", " << dims_[2] <<
")" << std::endl;
84 const std::pair<double, double>
zLimits()
const
86 return std::make_pair(botmax_, topmin_);
91 return std::make_pair(abszmin_, abszmax_);
96 int jmin,
int jlen,
int jmax,
97 double zmin,
double zlen,
double zmax)
100 std::cerr <<
"Error! imin < 0 (imin = " << imin <<
")\n";
101 throw std::runtime_error(
"Inconsistent user input.");
103 if (ilen > dims_[0]) {
104 std::cerr <<
"Error! ilen larger than grid (ilen = " << ilen <<
")\n";
105 throw std::runtime_error(
"Inconsistent user input.");
107 if (imax > dims_[0]) {
108 std::cerr <<
"Error! imax larger than input grid (imax = " << imax <<
")\n";
109 throw std::runtime_error(
"Inconsistent user input.");
112 std::cerr <<
"Error! jmin < 0 (jmin = " << jmin <<
")\n";
113 throw std::runtime_error(
"Inconsistent user input.");
115 if (jlen > dims_[1]) {
116 std::cerr <<
"Error! jlen larger than grid (jlen = " << jlen <<
")\n";
117 throw std::runtime_error(
"Inconsistent user input.");
119 if (jmax > dims_[1]) {
120 std::cerr <<
"Error! jmax larger than input grid (jmax = " << jmax <<
")\n";
121 throw std::runtime_error(
"Inconsistent user input.");
123 if (zmin < abszmin_) {
124 std::cerr <<
"Error! zmin ("<< zmin <<
") less than minimum ZCORN value ("<< abszmin_ <<
")\n";
125 throw std::runtime_error(
"Inconsistent user input.");
127 if (zmax > abszmax_) {
128 std::cerr <<
"Error! zmax ("<< zmax <<
") larger than maximal ZCORN value ("<< abszmax_ <<
")\n";
129 throw std::runtime_error(
"Inconsistent user input.");
131 if (zlen > (abszmax_ - abszmin_)) {
132 std::cerr <<
"Error! zlen ("<< zlen <<
") larger than maximal ZCORN (" << abszmax_ <<
") minus minimal ZCORN ("<< abszmin_ <<
")\n";
133 throw std::runtime_error(
"Inconsistent user input.");
137 void chop(
int imin,
int imax,
int jmin,
int jmax,
double zmin,
double zmax,
bool resettoorigin=
true)
139 new_dims_[0] = imax - imin;
140 new_dims_[1] = jmax - jmin;
143 const std::vector<double>& COORD = deck_[
"COORD"].back().getRawDoubleData();
144 int num_coord = COORD.size();
145 if (num_coord != 6*(dims_[0] + 1)*(dims_[1] + 1)) {
146 std::cerr <<
"Error! COORD size (" << COORD.size() <<
") not consistent with SPECGRID\n";
147 throw std::runtime_error(
"Inconsistent COORD and SPECGRID.");
149 int num_new_coord = 6*(new_dims_[0] + 1)*(new_dims_[1] + 1);
150 double x_correction = COORD[6*((dims_[0] + 1)*jmin + imin)];
151 double y_correction = COORD[6*((dims_[0] + 1)*jmin + imin) + 1];
152 new_COORD_.resize(num_new_coord, 1e100);
153 for (
int j = jmin;
j < jmax + 1; ++
j) {
154 for (
int i = imin; i < imax + 1; ++i) {
155 int pos = (dims_[0] + 1)*
j + i;
156 int new_pos = (new_dims_[0] + 1)*(
j-jmin) + (i-imin);
158 std::copy(COORD.begin() + 6*pos, COORD.begin() + 6*(pos + 1), new_COORD_.begin() + 6*new_pos);
161 new_COORD_[6*new_pos] -= x_correction;
162 new_COORD_[6*new_pos + 1] -= y_correction;
163 new_COORD_[6*new_pos + 2] = 0;
164 new_COORD_[6*new_pos + 3] -= x_correction;
165 new_COORD_[6*new_pos + 4] -= y_correction;
166 new_COORD_[6*new_pos + 5] = zmax-zmin;
175 int layersz = 8*dims_[0]*dims_[1];
176 const std::vector<double>& ZCORN = deck_[
"ZCORN"].back().getRawDoubleData();
177 int num_zcorn = ZCORN.size();
178 if (num_zcorn != layersz*dims_[2]) {
179 std::cerr <<
"Error! ZCORN size (" << ZCORN.size() <<
") not consistent with SPECGRID\n";
180 throw std::runtime_error(
"Inconsistent ZCORN and SPECGRID.");
183 zmin = std::max(zmin, botmax_);
186 std::cerr <<
"Error: zmin >= zmax (zmin = " << zmin <<
", zmax = " << zmax <<
")\n";
187 throw std::runtime_error(
"zmin >= zmax");
189 std::cout <<
"Chopping subsample, i: (" << imin <<
"--" << imax <<
") j: (" << jmin <<
"--" << jmax <<
") z: (" << zmin <<
"--" << zmax <<
")" << std::endl;
194 for (
int k = 0; k < dims_[2]; ++k) {
195 double layer_max = *std::max_element(ZCORN.begin() + k*layersz, ZCORN.begin() + (k + 1)*layersz);
196 if (layer_max > zmin) {
203 for (
int k = dims_[2]; k > 0; --k) {
204 double layer_min = *std::min_element(ZCORN.begin() + (k - 1)*layersz, ZCORN.begin() + k*layersz);
205 if (layer_min < zmax) {
210 new_dims_[2] = kmax - kmin;
213 double z_origin_correction = 0.0;
215 z_origin_correction = zmin;
217 new_ZCORN_.resize(8*new_dims_[0]*new_dims_[1]*new_dims_[2], 1e100);
218 new_to_old_cell_.resize(new_dims_[0]*new_dims_[1]*new_dims_[2], -1);
220 int delta[3] = { 1, 2*dims_[0], 4*dims_[0]*dims_[1] };
221 int new_delta[3] = { 1, 2*new_dims_[0], 4*new_dims_[0]*new_dims_[1] };
222 for (
int k = kmin; k < kmax; ++k) {
223 for (
int j = jmin;
j < jmax; ++
j) {
224 for (
int i = imin; i < imax; ++i) {
225 new_to_old_cell_[cellcount++] = dims_[0]*dims_[1]*k + dims_[0]*
j + i;
226 int old_ix = 2*(i*delta[0] +
j*delta[1] + k*delta[2]);
227 int new_ix = 2*((i-imin)*new_delta[0] + (
j-jmin)*new_delta[1] + (k-kmin)*new_delta[2]);
228 int old_indices[8] = { old_ix, old_ix + delta[0],
229 old_ix + delta[1], old_ix + delta[1] + delta[0],
230 old_ix + delta[2], old_ix + delta[2] + delta[0],
231 old_ix + delta[2] + delta[1], old_ix + delta[2] + delta[1] + delta[0] };
232 int new_indices[8] = { new_ix, new_ix + new_delta[0],
233 new_ix + new_delta[1], new_ix + new_delta[1] + new_delta[0],
234 new_ix + new_delta[2], new_ix + new_delta[2] + new_delta[0],
235 new_ix + new_delta[2] + new_delta[1], new_ix + new_delta[2] + new_delta[1] + new_delta[0] };
236 for (
int cc = 0; cc < 8; ++cc) {
237 new_ZCORN_[new_indices[cc]] =
std::min(zmax, std::max(zmin, ZCORN[old_indices[cc]])) - z_origin_correction;
243 filterIntegerField(
"ACTNUM", new_ACTNUM_);
244 filterDoubleField(
"PORO", new_PORO_);
245 filterDoubleField(
"NTG", new_NTG_);
246 filterDoubleField(
"SWCR", new_SWCR_);
247 filterDoubleField(
"SOWCR", new_SOWCR_);
248 filterDoubleField(
"PERMX", new_PERMX_);
249 filterDoubleField(
"PERMY", new_PERMY_);
250 filterDoubleField(
"PERMZ", new_PERMZ_);
251 filterIntegerField(
"SATNUM", new_SATNUM_);
259 Opm::DeckKeyword specGridKw(this->parser_.getKeyword(
"SPECGRID"));
260 Opm::DeckRecord specGridRecord;
262 auto nxItem = Opm::DeckItem(
"NX",
int());
263 auto nyItem = Opm::DeckItem(
"NY",
int());
264 auto nzItem = Opm::DeckItem(
"NZ",
int());
265 auto numresItem = Opm::DeckItem(
"NUMRES",
int());
266 auto coordTypeItem = Opm::DeckItem(
"COORD_TYPE", std::string());
268 nxItem.push_back(new_dims_[0]);
269 nyItem.push_back(new_dims_[1]);
270 nzItem.push_back(new_dims_[2]);
271 numresItem.push_back(1);
272 coordTypeItem.push_back(
"F");
274 specGridRecord.addItem(std::move(nxItem));
275 specGridRecord.addItem(std::move(nyItem));
276 specGridRecord.addItem(std::move(nzItem));
277 specGridRecord.addItem(std::move(numresItem));
278 specGridRecord.addItem(std::move(coordTypeItem));
280 specGridKw.addRecord(std::move(specGridRecord));
282 subDeck.addKeyword(std::move(specGridKw));
283 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"COORD"),
"Length", new_COORD_);
284 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"ZCORN"),
"Length", new_ZCORN_);
285 addIntKeyword_(
subDeck, this->parser_.getKeyword(
"ACTNUM"), new_ACTNUM_);
286 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"PORO"),
"1", new_PORO_);
287 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"NTG"),
"1", new_NTG_);
288 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"SWCR"),
"1", new_SWCR_);
289 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"SOWCR"),
"1", new_SOWCR_);
290 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"PERMX"),
"Permeability", new_PERMX_);
291 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"PERMY"),
"Permeability", new_PERMY_);
292 addDoubleKeyword_(
subDeck, this->parser_.getKeyword(
"PERMZ"),
"Permeability", new_PERMZ_);
293 addIntKeyword_(
subDeck, this->parser_.getKeyword(
"SATNUM"), new_SATNUM_);
299 std::ofstream out(filename.c_str());
301 std::cerr <<
"Could not open file " << filename <<
"\n";
302 throw std::runtime_error(
"Could not open output file.");
304 out <<
"SPECGRID\n" << new_dims_[0] <<
' ' << new_dims_[1] <<
' ' << new_dims_[2]
308 out.setf(std::ios::scientific);
310 outputField(out, new_COORD_,
"COORD", 3);
311 outputField(out, new_ZCORN_,
"ZCORN", 4);
312 outputField(out, new_ACTNUM_,
"ACTNUM");
313 outputField(out, new_PORO_,
"PORO", 4);
314 if (
hasNTG()) {outputField(out, new_NTG_,
"NTG", 4);}
315 if (
hasSWCR()) {outputField(out, new_SWCR_,
"SWCR", 4);}
316 if (
hasSOWCR()) {outputField(out, new_SOWCR_,
"SOWCR", 4);}
317 outputField(out, new_PERMX_,
"PERMX", 4);
318 outputField(out, new_PERMY_,
"PERMY", 4);
319 outputField(out, new_PERMZ_,
"PERMZ", 4);
320 outputField(out, new_SATNUM_,
"SATNUM");
322 bool hasNTG()
const {
return !new_NTG_.empty(); }
323 bool hasSWCR()
const {
return !new_SWCR_.empty(); }
324 bool hasSOWCR()
const {
return !new_SOWCR_.empty(); }
329 Opm::UnitSystem metricUnits_;
335 std::vector<double> new_COORD_;
336 std::vector<double> new_ZCORN_;
337 std::vector<int> new_ACTNUM_;
338 std::vector<double> new_PORO_;
339 std::vector<double> new_NTG_;
340 std::vector<double> new_SWCR_;
341 std::vector<double> new_SOWCR_;
342 std::vector<double> new_PERMX_;
343 std::vector<double> new_PERMY_;
344 std::vector<double> new_PERMZ_;
345 std::vector<int> new_SATNUM_;
348 std::vector<int> new_to_old_cell_;
351 void addDoubleKeyword_(Deck&
subDeck,
352 const ParserKeyword& keyword,
353 const std::string& dimensionString,
354 const std::vector<double>& data)
359 Opm::DeckKeyword dataKw(keyword);
360 Opm::DeckRecord dataRecord;
361 auto dimension = metricUnits_.parse(dimensionString);
362 auto dataItem = Opm::DeckItem(
"DATA",
double(), { dimension }, { dimension });
364 for (
size_t i = 0; i < data.size(); ++i) {
365 dataItem.push_back(data[i]);
368 dataRecord.addItem(std::move(dataItem));
369 dataKw.addRecord(std::move(dataRecord));
370 subDeck.addKeyword(std::move(dataKw));
373 void addIntKeyword_(Deck&
subDeck,
374 const ParserKeyword& keyword,
375 const std::vector<int>& data)
380 Opm::DeckKeyword dataKw(keyword);
381 Opm::DeckRecord dataRecord;
382 auto dataItem = Opm::DeckItem(
"DATA",
int());
384 for (
size_t i = 0; i < data.size(); ++i) {
385 dataItem.push_back(data[i]);
388 dataRecord.addItem(std::move(dataItem));
389 dataKw.addRecord(std::move(dataRecord));
390 subDeck.addKeyword(std::move(dataKw));
393 template <
typename T>
394 void outputField(std::ostream& os,
395 const std::vector<T>& field,
396 const std::string& keyword,
397 const typename std::vector<T>::size_type nl = 20)
399 if (field.empty())
return;
401 os << keyword <<
'\n';
403 typedef typename std::vector<T>::size_type sz_t;
405 const sz_t n = field.size();
406 for (sz_t i = 0; i < n; ++i) {
408 << (((i + 1) % nl == 0) ?
'\n' :
' ');
418 template <
typename T>
419 void filterField(
const std::vector<T>& field,
420 std::vector<T>& output_field)
422 int sz = new_to_old_cell_.size();
423 output_field.resize(sz);
424 for (
int i = 0; i < sz; ++i) {
425 output_field[i] = field[new_to_old_cell_[i]];
429 void filterDoubleField(
const std::string& keyword, std::vector<double>& output_field)
431 if (deck_.hasKeyword(keyword)) {
432 const std::vector<double>& field = deck_[keyword].back().getRawDoubleData();
433 filterField(field, output_field);
437 void filterIntegerField(
const std::string& keyword, std::vector<int>& output_field)
439 if (deck_.hasKeyword(keyword)) {
440 const std::vector<int>& field = deck_[keyword].back().getIntData();
441 filterField(field, output_field);
Definition: CornerpointChopper.hpp:40
void writeGrdecl(const std::string &filename)
Definition: CornerpointChopper.hpp:296
const int * newDimensions() const
Definition: CornerpointChopper.hpp:76
const std::pair< double, double > abszLimits() const
Definition: CornerpointChopper.hpp:89
bool hasNTG() const
Definition: CornerpointChopper.hpp:322
const std::pair< double, double > zLimits() const
Definition: CornerpointChopper.hpp:84
bool hasSWCR() const
Definition: CornerpointChopper.hpp:323
Opm::Deck subDeck()
Return a sub-deck with fields corresponding to the selected subset.
Definition: CornerpointChopper.hpp:255
const int * dimensions() const
Definition: CornerpointChopper.hpp:68
void verifyInscribedShoebox(int imin, int ilen, int imax, int jmin, int jlen, int jmax, double zmin, double zlen, double zmax)
Definition: CornerpointChopper.hpp:95
CornerPointChopper(const std::string &file)
Definition: CornerpointChopper.hpp:42
void chop(int imin, int imax, int jmin, int jmax, double zmin, double zmax, bool resettoorigin=true)
Definition: CornerpointChopper.hpp:137
bool hasSOWCR() const
Definition: CornerpointChopper.hpp:324
min[0]
Definition: elasticity_upscale_impl.hpp:146
int j
Definition: elasticity_upscale_impl.hpp:658
Definition: ImplicitAssembly.hpp:43