Beispiel #1
0
    void CpGrid::createCartesian(const array<int, 3>& dims,
				 const array<double, 3>& cellsize)
    {
	// Make the grdecl format arrays.
	// Pillar coords.
	std::vector<double> coord;
	coord.reserve(6*(dims[0] + 1)*(dims[1] + 1));
	double bot = 0.0;
	double top = dims[2]*cellsize[2];
	// i runs fastest for the pillars.
	for (int j = 0; j < dims[1] + 1; ++j) {
	    double y = j*cellsize[1];
	    for (int i = 0; i < dims[0] + 1; ++i) {
		double x = i*cellsize[0];
		double pillar[6] = { x, y, bot, x, y, top };
		coord.insert(coord.end(), pillar, pillar + 6);
	    }
	}
	std::vector<double> zcorn(8*dims[0]*dims[1]*dims[2]);
	const int num_per_layer = 4*dims[0]*dims[1];
	double* offset = &zcorn[0];
	for (int k = 0; k < dims[2]; ++k) {
	    double zlow = k*cellsize[2];
	    std::fill(offset, offset + num_per_layer, zlow);
	    offset += num_per_layer;
	    double zhigh = (k+1)*cellsize[2];
	    std::fill(offset, offset + num_per_layer, zhigh);
	    offset += num_per_layer;
	}
	std::vector<int> actnum(dims[0]*dims[1]*dims[2], 1);

	// Process them.
	grdecl g;
	g.dims[0] = dims[0];
	g.dims[1] = dims[1];
	g.dims[2] = dims[2];
	g.coord = &coord[0];
	g.zcorn = &zcorn[0];
	g.actnum = &actnum[0];
	processEclipseFormat(g, 0.0, false, false);
    }
    void CpGridData::processEclipseFormat(const Opm::EclipseGrid& ecl_grid, bool periodic_extension, bool turn_normals, bool clip_z,
                                          const std::vector<double>& poreVolume)
    {
        std::vector<double> coordData;
        ecl_grid.exportCOORD(coordData);

        std::vector<int> actnumData;
        ecl_grid.exportACTNUM(actnumData);

        // Mutable because grdecl::zcorn is non-const.
        auto zcornData = getSanitizedZCORN(ecl_grid, actnumData);

        // Make input struct for processing code.
        grdecl g;
        g.dims[0] = ecl_grid.getNX();
        g.dims[1] = ecl_grid.getNY();
        g.dims[2] = ecl_grid.getNZ();
        g.coord = &coordData[0];
        g.zcorn = &zcornData[0];

        g.actnum = actnumData.empty() ? nullptr : &actnumData[0];

        // Possibly process MINPV
        if (!poreVolume.empty() && (ecl_grid.getMinpvMode() != Opm::MinpvMode::ModeEnum::Inactive)) {
            Opm::MinpvProcessor mp(g.dims[0], g.dims[1], g.dims[2]);
            // Currently the pinchProcessor is not used and only opmfil is supported
            //bool opmfil = ecl_grid.getMinpvMode() == Opm::MinpvMode::OpmFIL;
            bool opmfil = true;
            size_t cells_modified = mp.process(poreVolume, ecl_grid.getMinpvValue(), actnumData, opmfil, zcornData.data());
            if (cells_modified > 0) {
                this->zcorn = zcornData;
            }
        }

        // this variable is only required because getCellZvals() needs
        // a coord_t instead of a plain integer pointer...
        coord_t logicalCartesianSize;
        for (int axisIdx = 0; axisIdx < 3; ++axisIdx)
            logicalCartesianSize[axisIdx] = g.dims[axisIdx];

        // Handle zcorn clipping. The g variable points to the data in
        // the clipped_zcorn variable, i.e. clipped_zcorn must remain
        // in scope.
        std::vector<double> clipped_zcorn;
        if (clip_z) {
            double minz_top = 1e100;
            double maxz_bot = -1e100;
            for (int i = 0; i < g.dims[0]; ++i) {
                for (int j = 0; j < g.dims[1]; ++j) {
                    coord_t logicalCartesianCoord;
                    logicalCartesianCoord[0] = i;
                    logicalCartesianCoord[1] = j;

                    logicalCartesianCoord[2] = 0;
                    std::array<double, 8> cellz_bot = getCellZvals(logicalCartesianCoord, logicalCartesianSize, &zcornData[0]);

                    logicalCartesianCoord[2] = g.dims[2] - 1;
                    std::array<double, 8> cellz_top = getCellZvals(logicalCartesianCoord, logicalCartesianSize, &zcornData[0]);

                    for (int dd = 0; dd < 4; ++dd) {
                        minz_top = std::min(cellz_top[dd+4], minz_top);
                        maxz_bot = std::max(cellz_bot[dd], maxz_bot);
                    }
                }
            }
            if (minz_top <= maxz_bot) {
                OPM_THROW(std::runtime_error, "Grid cannot be clipped to a shoe-box (in z): Would be empty afterwards.");
            }
            int num_zcorn = zcornData.size();
            clipped_zcorn.resize(num_zcorn);
            for (int i = 0; i < num_zcorn; ++i) {
                clipped_zcorn[i] = std::max(maxz_bot, std::min(minz_top, g.zcorn[i]));
            }
            g.zcorn = &clipped_zcorn[0];
            this->zcorn = clipped_zcorn;
        }

        // Get z_tolerance.
        const double z_tolerance = ecl_grid.isPinchActive() ?
            ecl_grid.getPinchThresholdThickness() : 0.0;

        if (periodic_extension) {
            // Extend grid periodically with one layer of cells in the (i, j) directions.
            std::vector<double> new_coord;
            std::vector<double> new_zcorn;
            std::vector<int> new_actnum;
            grdecl new_g;
            addOuterCellLayer(g, new_coord, new_zcorn, new_actnum, new_g);
            // Make the grid.
            processEclipseFormat(new_g, z_tolerance, true, turn_normals);
        } else {
            // Make the grid.
            processEclipseFormat(g, z_tolerance, false, turn_normals);
        }
    }