20 #ifndef OPM_CORNERPOINTCHOPPER_HEADER_INCLUDED
21 #define OPM_CORNERPOINTCHOPPER_HEADER_INCLUDED
24 #include <opm/parser/eclipse/Parser/Parser.hpp>
25 #include <opm/parser/eclipse/Parser/ParseMode.hpp>
26 #include <opm/parser/eclipse/Units/UnitSystem.hpp>
27 #include <opm/parser/eclipse/Deck/Deck.hpp>
28 #include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
29 #include <opm/parser/eclipse/Deck/DeckRecord.hpp>
30 #include <opm/parser/eclipse/Deck/DeckDoubleItem.hpp>
31 #include <opm/parser/eclipse/Deck/DeckIntItem.hpp>
32 #include <opm/parser/eclipse/Deck/DeckStringItem.hpp>
48 Opm::ParseMode parseMode;
49 Opm::ParserPtr parser(
new Opm::Parser());
50 deck_ = parser->parseFile(file , parseMode);
52 metricUnits_.reset(Opm::UnitSystem::newMETRIC());
54 Opm::DeckRecordConstPtr specgridRecord = deck_->getKeyword(
"SPECGRID")->getRecord(0);
55 dims_[0] = specgridRecord->getItem(
"NX")->getInt(0);
56 dims_[1] = specgridRecord->getItem(
"NY")->getInt(0);
57 dims_[2] = specgridRecord->getItem(
"NZ")->getInt(0);
59 int layersz = 8*dims_[0]*dims_[1];
60 const std::vector<double>& ZCORN = deck_->getKeyword(
"ZCORN")->getRawDoubleData();
61 botmax_ = *std::max_element(ZCORN.begin(), ZCORN.begin() + layersz/2);
62 topmin_ = *std::min_element(ZCORN.begin() + dims_[2]*layersz - layersz/2,
63 ZCORN.begin() + dims_[2]*layersz);
65 abszmax_ = *std::max_element(ZCORN.begin(), ZCORN.end());
66 abszmin_ = *std::min_element(ZCORN.begin(), ZCORN.end());
68 std::cout <<
"Parsed grdecl file with dimensions ("
69 << dims_[0] <<
", " << dims_[1] <<
", " << dims_[2] <<
")" << std::endl;
91 const std::pair<double, double>
zLimits()
const
93 return std::make_pair(botmax_, topmin_);
98 return std::make_pair(abszmin_, abszmax_);
103 int jmin,
int jlen,
int jmax,
104 double zmin,
double zlen,
double zmax)
107 std::cerr <<
"Error! imin < 0 (imin = " << imin <<
")\n";
108 throw std::runtime_error(
"Inconsistent user input.");
110 if (ilen > dims_[0]) {
111 std::cerr <<
"Error! ilen larger than grid (ilen = " << ilen <<
")\n";
112 throw std::runtime_error(
"Inconsistent user input.");
114 if (imax > dims_[0]) {
115 std::cerr <<
"Error! imax larger than input grid (imax = " << imax <<
")\n";
116 throw std::runtime_error(
"Inconsistent user input.");
119 std::cerr <<
"Error! jmin < 0 (jmin = " << jmin <<
")\n";
120 throw std::runtime_error(
"Inconsistent user input.");
122 if (jlen > dims_[1]) {
123 std::cerr <<
"Error! jlen larger than grid (jlen = " << jlen <<
")\n";
124 throw std::runtime_error(
"Inconsistent user input.");
126 if (jmax > dims_[1]) {
127 std::cerr <<
"Error! jmax larger than input grid (jmax = " << jmax <<
")\n";
128 throw std::runtime_error(
"Inconsistent user input.");
130 if (zmin < abszmin_) {
131 std::cerr <<
"Error! zmin ("<< zmin <<
") less than minimum ZCORN value ("<< abszmin_ <<
")\n";
132 throw std::runtime_error(
"Inconsistent user input.");
134 if (zmax > abszmax_) {
135 std::cerr <<
"Error! zmax ("<< zmax <<
") larger than maximal ZCORN value ("<< abszmax_ <<
")\n";
136 throw std::runtime_error(
"Inconsistent user input.");
138 if (zlen > (abszmax_ - abszmin_)) {
139 std::cerr <<
"Error! zlen ("<< zlen <<
") larger than maximal ZCORN (" << abszmax_ <<
") minus minimal ZCORN ("<< abszmin_ <<
")\n";
140 throw std::runtime_error(
"Inconsistent user input.");
144 void chop(
int imin,
int imax,
int jmin,
int jmax,
double zmin,
double zmax,
bool resettoorigin=
true)
146 new_dims_[0] = imax - imin;
147 new_dims_[1] = jmax - jmin;
150 const std::vector<double>& COORD = deck_->getKeyword(
"COORD")->getRawDoubleData();
151 int num_coord = COORD.size();
152 if (num_coord != 6*(dims_[0] + 1)*(dims_[1] + 1)) {
153 std::cerr <<
"Error! COORD size (" << COORD.size() <<
") not consistent with SPECGRID\n";
154 throw std::runtime_error(
"Inconsistent COORD and SPECGRID.");
156 int num_new_coord = 6*(new_dims_[0] + 1)*(new_dims_[1] + 1);
157 double x_correction = COORD[6*((dims_[0] + 1)*jmin + imin)];
158 double y_correction = COORD[6*((dims_[0] + 1)*jmin + imin) + 1];
159 new_COORD_.resize(num_new_coord, 1e100);
160 for (
int j = jmin; j < jmax + 1; ++j) {
161 for (
int i = imin; i < imax + 1; ++i) {
162 int pos = (dims_[0] + 1)*j + i;
163 int new_pos = (new_dims_[0] + 1)*(j-jmin) + (i-imin);
165 std::copy(COORD.begin() + 6*pos, COORD.begin() + 6*(pos + 1), new_COORD_.begin() + 6*new_pos);
168 new_COORD_[6*new_pos] -= x_correction;
169 new_COORD_[6*new_pos + 1] -= y_correction;
170 new_COORD_[6*new_pos + 2] = 0;
171 new_COORD_[6*new_pos + 3] -= x_correction;
172 new_COORD_[6*new_pos + 4] -= y_correction;
173 new_COORD_[6*new_pos + 5] = zmax-zmin;
182 int layersz = 8*dims_[0]*dims_[1];
183 const std::vector<double>& ZCORN = deck_->getKeyword(
"ZCORN")->getRawDoubleData();
184 int num_zcorn = ZCORN.size();
185 if (num_zcorn != layersz*dims_[2]) {
186 std::cerr <<
"Error! ZCORN size (" << ZCORN.size() <<
") not consistent with SPECGRID\n";
187 throw std::runtime_error(
"Inconsistent ZCORN and SPECGRID.");
190 zmin = std::max(zmin, botmax_);
191 zmax = std::min(zmax, topmin_);
193 std::cerr <<
"Error: zmin >= zmax (zmin = " << zmin <<
", zmax = " << zmax <<
")\n";
194 throw std::runtime_error(
"zmin >= zmax");
196 std::cout <<
"Chopping subsample, i: (" << imin <<
"--" << imax <<
") j: (" << jmin <<
"--" << jmax <<
") z: (" << zmin <<
"--" << zmax <<
")" << std::endl;
201 for (
int k = 0; k < dims_[2]; ++k) {
202 double layer_max = *std::max_element(ZCORN.begin() + k*layersz, ZCORN.begin() + (k + 1)*layersz);
203 if (layer_max > zmin) {
210 for (
int k = dims_[2]; k > 0; --k) {
211 double layer_min = *std::min_element(ZCORN.begin() + (k - 1)*layersz, ZCORN.begin() + k*layersz);
212 if (layer_min < zmax) {
217 new_dims_[2] = kmax - kmin;
220 double z_origin_correction = 0.0;
222 z_origin_correction = zmin;
224 new_ZCORN_.resize(8*new_dims_[0]*new_dims_[1]*new_dims_[2], 1e100);
225 new_to_old_cell_.resize(new_dims_[0]*new_dims_[1]*new_dims_[2], -1);
227 int delta[3] = { 1, 2*dims_[0], 4*dims_[0]*dims_[1] };
228 int new_delta[3] = { 1, 2*new_dims_[0], 4*new_dims_[0]*new_dims_[1] };
229 for (
int k = kmin; k < kmax; ++k) {
230 for (
int j = jmin; j < jmax; ++j) {
231 for (
int i = imin; i < imax; ++i) {
232 new_to_old_cell_[cellcount++] = dims_[0]*dims_[1]*k + dims_[0]*j + i;
233 int old_ix = 2*(i*delta[0] + j*delta[1] + k*delta[2]);
234 int new_ix = 2*((i-imin)*new_delta[0] + (j-jmin)*new_delta[1] + (k-kmin)*new_delta[2]);
235 int old_indices[8] = { old_ix, old_ix + delta[0],
236 old_ix + delta[1], old_ix + delta[1] + delta[0],
237 old_ix + delta[2], old_ix + delta[2] + delta[0],
238 old_ix + delta[2] + delta[1], old_ix + delta[2] + delta[1] + delta[0] };
239 int new_indices[8] = { new_ix, new_ix + new_delta[0],
240 new_ix + new_delta[1], new_ix + new_delta[1] + new_delta[0],
241 new_ix + new_delta[2], new_ix + new_delta[2] + new_delta[0],
242 new_ix + new_delta[2] + new_delta[1], new_ix + new_delta[2] + new_delta[1] + new_delta[0] };
243 for (
int cc = 0; cc < 8; ++cc) {
244 new_ZCORN_[new_indices[cc]] = std::min(zmax, std::max(zmin, ZCORN[old_indices[cc]])) - z_origin_correction;
250 filterIntegerField(
"ACTNUM", new_ACTNUM_);
251 filterDoubleField(
"PORO", new_PORO_);
252 filterDoubleField(
"NTG", new_NTG_);
253 filterDoubleField(
"SWCR", new_SWCR_);
254 filterDoubleField(
"SOWCR", new_SOWCR_);
255 filterDoubleField(
"PERMX", new_PERMX_);
256 filterDoubleField(
"PERMY", new_PERMY_);
257 filterDoubleField(
"PERMZ", new_PERMZ_);
258 filterIntegerField(
"SATNUM", new_SATNUM_);
264 Opm::DeckPtr
subDeck(
new Opm::Deck);
266 Opm::DeckKeywordPtr specGridKw(
new Opm::DeckKeyword(
"SPECGRID"));
267 Opm::DeckRecordPtr specGridRecord(
new Opm::DeckRecord());
269 Opm::DeckIntItemPtr nxItem(
new Opm::DeckIntItem(
"NX"));
270 Opm::DeckIntItemPtr nyItem(
new Opm::DeckIntItem(
"NY"));
271 Opm::DeckIntItemPtr nzItem(
new Opm::DeckIntItem(
"NZ"));
272 Opm::DeckIntItemPtr numresItem(
new Opm::DeckIntItem(
"NUMRES"));
273 Opm::DeckStringItemPtr coordTypeItem(
new Opm::DeckStringItem(
"COORD_TYPE"));
275 nxItem->push_back(new_dims_[0]);
276 nyItem->push_back(new_dims_[1]);
277 nzItem->push_back(new_dims_[2]);
278 numresItem->push_back(1);
279 coordTypeItem->push_back(
"F");
281 specGridRecord->addItem(nxItem);
282 specGridRecord->addItem(nyItem);
283 specGridRecord->addItem(nzItem);
284 specGridRecord->addItem(numresItem);
285 specGridRecord->addItem(coordTypeItem);
287 specGridKw->addRecord(specGridRecord);
289 subDeck->addKeyword(specGridKw);
290 addDoubleKeyword_(subDeck,
"COORD",
"Length", new_COORD_);
291 addDoubleKeyword_(subDeck,
"ZCORN",
"Length", new_ZCORN_);
292 addIntKeyword_(subDeck,
"ACTNUM", new_ACTNUM_);
293 addDoubleKeyword_(subDeck,
"PORO",
"1", new_PORO_);
294 addDoubleKeyword_(subDeck,
"NTG",
"1", new_NTG_);
295 addDoubleKeyword_(subDeck,
"SWCR",
"1", new_SWCR_);
296 addDoubleKeyword_(subDeck,
"SOWCR",
"1", new_SOWCR_);
297 addDoubleKeyword_(subDeck,
"PERMX",
"Permeability", new_PERMX_);
298 addDoubleKeyword_(subDeck,
"PERMY",
"Permeability", new_PERMY_);
299 addDoubleKeyword_(subDeck,
"PERMZ",
"Permeability", new_PERMZ_);
300 addIntKeyword_(subDeck,
"SATNUM", new_SATNUM_);
306 std::ofstream out(filename.c_str());
308 std::cerr <<
"Could not open file " << filename <<
"\n";
309 throw std::runtime_error(
"Could not open output file.");
311 out <<
"SPECGRID\n" << new_dims_[0] <<
' ' << new_dims_[1] <<
' ' << new_dims_[2]
315 out.setf(std::ios::scientific);
317 outputField(out, new_COORD_,
"COORD", 3);
318 outputField(out, new_ZCORN_,
"ZCORN", 4);
319 outputField(out, new_ACTNUM_,
"ACTNUM");
320 outputField(out, new_PORO_,
"PORO", 4);
321 if (
hasNTG()) {outputField(out, new_NTG_,
"NTG", 4);}
322 if (
hasSWCR()) {outputField(out, new_SWCR_,
"SWCR", 4);}
323 if (
hasSOWCR()) {outputField(out, new_SOWCR_,
"SOWCR", 4);}
324 outputField(out, new_PERMX_,
"PERMX", 4);
325 outputField(out, new_PERMY_,
"PERMY", 4);
326 outputField(out, new_PERMZ_,
"PERMZ", 4);
327 outputField(out, new_SATNUM_,
"SATNUM");
329 bool hasNTG()
const {
return !new_NTG_.empty(); }
330 bool hasSWCR()
const {
return !new_SWCR_.empty(); }
331 bool hasSOWCR()
const {
return !new_SOWCR_.empty(); }
334 Opm::DeckConstPtr deck_;
335 std::shared_ptr<Opm::UnitSystem> metricUnits_;
341 std::vector<double> new_COORD_;
342 std::vector<double> new_ZCORN_;
343 std::vector<int> new_ACTNUM_;
344 std::vector<double> new_PORO_;
345 std::vector<double> new_NTG_;
346 std::vector<double> new_SWCR_;
347 std::vector<double> new_SOWCR_;
348 std::vector<double> new_PERMX_;
349 std::vector<double> new_PERMY_;
350 std::vector<double> new_PERMZ_;
351 std::vector<int> new_SATNUM_;
354 std::vector<int> new_to_old_cell_;
356 void addDoubleKeyword_(Opm::DeckPtr
subDeck,
357 const std::string& keywordName,
358 const std::string& dimensionString,
359 const std::vector<double>& data)
364 Opm::DeckKeywordPtr dataKw(
new Opm::DeckKeyword(keywordName));
365 Opm::DeckRecordPtr dataRecord(
new Opm::DeckRecord());
366 Opm::DeckDoubleItemPtr dataItem(
new Opm::DeckDoubleItem(
"DATA"));
368 for (
size_t i = 0; i < data.size(); ++i) {
369 dataItem->push_back(data[i]);
372 std::shared_ptr<const Dimension> dimension = metricUnits_->parse(dimensionString);
373 dataItem->push_backDimension(dimension, dimension);
375 dataRecord->addItem(dataItem);
376 dataKw->addRecord(dataRecord);
377 subDeck->addKeyword(dataKw);
380 void addIntKeyword_(Opm::DeckPtr subDeck,
381 const std::string& keywordName,
382 const std::vector<int>& data)
387 Opm::DeckKeywordPtr dataKw(
new Opm::DeckKeyword(keywordName));
388 Opm::DeckRecordPtr dataRecord(
new Opm::DeckRecord());
389 Opm::DeckIntItemPtr dataItem(
new Opm::DeckIntItem(
"DATA"));
391 for (
size_t i = 0; i < data.size(); ++i) {
392 dataItem->push_back(data[i]);
395 dataRecord->addItem(dataItem);
396 dataKw->addRecord(dataRecord);
397 subDeck->addKeyword(dataKw);
400 template <
typename T>
401 void outputField(std::ostream& os,
402 const std::vector<T>& field,
403 const std::string& keyword,
404 const typename std::vector<T>::size_type nl = 20)
406 if (field.empty())
return;
408 os << keyword <<
'\n';
410 typedef typename std::vector<T>::size_type sz_t;
412 const sz_t n = field.size();
413 for (sz_t i = 0; i < n; ++i) {
415 << (((i + 1) % nl == 0) ?
'\n' :
' ');
425 template <
typename T>
426 void filterField(
const std::vector<T>& field,
427 std::vector<T>& output_field)
429 int sz = new_to_old_cell_.size();
430 output_field.resize(sz);
431 for (
int i = 0; i < sz; ++i) {
432 output_field[i] = field[new_to_old_cell_[i]];
436 void filterDoubleField(
const std::string& keyword, std::vector<double>& output_field)
438 if (deck_->hasKeyword(keyword)) {
439 const std::vector<double>& field = deck_->getKeyword(keyword)->getRawDoubleData();
440 filterField(field, output_field);
444 void filterIntegerField(
const std::string& keyword, std::vector<int>& output_field)
446 if (deck_->hasKeyword(keyword)) {
447 const std::vector<int>& field = deck_->getKeyword(keyword)->getIntData();
448 filterField(field, output_field);
459 #endif // OPM_CORNERPOINTCHOPPER_HEADER_INCLUDED
Opm::DeckConstPtr subDeck()
Return a sub-deck with fields corresponding to the selected subset.
Definition: CornerpointChopper.hpp:262
bool hasNTG() const
Definition: CornerpointChopper.hpp:329
Definition: AnisotropicEikonal.hpp:43
void chop(int imin, int imax, int jmin, int jmax, double zmin, double zmax, bool resettoorigin=true)
Definition: CornerpointChopper.hpp:144
bool hasSOWCR() const
Definition: CornerpointChopper.hpp:331
bool hasSWCR() const
Definition: CornerpointChopper.hpp:330
const int * dimensions() const
Definition: CornerpointChopper.hpp:75
void writeGrdecl(const std::string &filename)
Definition: CornerpointChopper.hpp:303
const std::pair< double, double > zLimits() const
Definition: CornerpointChopper.hpp:91
const std::pair< double, double > abszLimits() const
Definition: CornerpointChopper.hpp:96
void verifyInscribedShoebox(int imin, int ilen, int imax, int jmin, int jlen, int jmax, double zmin, double zlen, double zmax)
Definition: CornerpointChopper.hpp:102
Definition: CornerpointChopper.hpp:43
const int * newDimensions() const
Definition: CornerpointChopper.hpp:83
CornerPointChopper(const std::string &file)
Definition: CornerpointChopper.hpp:46