示例#1
0
文件: well1.py 项目: ABV-Hub/xtgeo
    def geometrics(self):
        """Compute some well geometrical arrays MD, INCL, AZI, as logs.

        These are kind of quasi measurements hence the logs will named
        with a Q in front as Q_MDEPTH, Q_INCL, and Q_AZI.

        These logs will be added to the dataframe. If the mdlogname
        attribute does not exist in advance, it will be set to 'Q_MDEPTH'.

        Returns:
            False if geometrics cannot be computed

        """
        if self._df.size < 3:
            logger.warning(
                "Cannot compute geometrics for %s. Too few  "
                "trajectory points",
                self.name,
            )
            return False

        # extract numpies from XYZ trajetory logs
        ptr_xv = self.get_carray("X_UTME")
        ptr_yv = self.get_carray("Y_UTMN")
        ptr_zv = self.get_carray("Z_TVDSS")

        # get number of rows in pandas
        nlen = self.nrow

        ptr_md = _cxtgeo.new_doublearray(nlen)
        ptr_incl = _cxtgeo.new_doublearray(nlen)
        ptr_az = _cxtgeo.new_doublearray(nlen)

        ier = _cxtgeo.well_geometrics(nlen, ptr_xv, ptr_yv, ptr_zv, ptr_md,
                                      ptr_incl, ptr_az, 0)

        if ier != 0:
            sys.exit(-9)

        dnumpy = self._convert_carr_double_np(ptr_md)
        self._df["Q_MDEPTH"] = pd.Series(dnumpy, index=self._df.index)

        dnumpy = self._convert_carr_double_np(ptr_incl)
        self._df["Q_INCL"] = pd.Series(dnumpy, index=self._df.index)

        dnumpy = self._convert_carr_double_np(ptr_az)
        self._df["Q_AZI"] = pd.Series(dnumpy, index=self._df.index)

        if not self._mdlogname:
            self._mdlogname = "Q_MDEPTH"

        # delete tmp pointers
        _cxtgeo.delete_doublearray(ptr_xv)
        _cxtgeo.delete_doublearray(ptr_yv)
        _cxtgeo.delete_doublearray(ptr_zv)
        _cxtgeo.delete_doublearray(ptr_md)
        _cxtgeo.delete_doublearray(ptr_incl)
        _cxtgeo.delete_doublearray(ptr_az)

        return True
示例#2
0
def copy(self):
    """Copy a grid instance (C pointers) and other props.

    Returns:
        A new instance (attached grid properties will also be unique)
    """

    other = self.__class__()

    ntot = self.ncol * self.nrow * self.nlay
    ncoord = (self.ncol + 1) * (self.nrow + 1) * 2 * 3
    nzcorn = self.ncol * self.nrow * (self.nlay + 1) * 4

    new_p_coord_v = _cxtgeo.new_doublearray(ncoord)
    new_p_zcorn_v = _cxtgeo.new_doublearray(nzcorn)
    new_p_actnum_v = _cxtgeo.new_intarray(ntot)

    _cxtgeo.grd3d_copy(
        self.ncol,
        self.nrow,
        self.nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        new_p_coord_v,
        new_p_zcorn_v,
        new_p_actnum_v,
        0,
        XTGDEBUG,
    )

    other._p_coord_v = new_p_coord_v
    other._p_zcorn_v = new_p_zcorn_v
    other._p_actnum_v = new_p_actnum_v

    other._ncol = self.ncol
    other._nrow = self.nrow
    other._nlay = self.nlay

    if isinstance(self.subgrids, dict):
        other.subgrids = deepcopy(self.subgrids)

    # copy attached properties
    if self._props:
        other._props = self._props.copy()
        logger.info("Other vs self props %s vs %s", other._props, self._props)

    if self._filesrc is not None and "(copy)" not in self._filesrc:
        other._filesrc = self._filesrc + " (copy)"
    elif self._filesrc is not None:
        other._filesrc = self._filesrc

    return other
示例#3
0
def create_box(
    self,
    dimension=(10, 12, 6),
    origin=(10.0, 20.0, 1000.0),
    oricenter=False,
    increment=(100, 150, 5),
    rotation=30.0,
    flip=1,
):
    """Create a shoebox grid from cubi'sh spec"""

    self._ncol, self._nrow, self._nlay = dimension
    ntot = self.ncol * self.nrow * self.nlay
    ncoord = (self.ncol + 1) * (self.nrow + 1) * 2 * 3
    nzcorn = self.ncol * self.nrow * (self.nlay + 1) * 4

    self._p_actnum_v = _cxtgeo.new_intarray(ntot)
    self._p_coord_v = _cxtgeo.new_doublearray(ncoord)
    self._p_zcorn_v = _cxtgeo.new_doublearray(nzcorn)

    option = 0
    if oricenter:
        option = 1

    _cxtgeo.grd3d_from_cube(
        self.ncol,
        self.nrow,
        self.nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        origin[0],
        origin[1],
        origin[2],
        increment[0],
        increment[1],
        increment[2],
        rotation,
        flip,
        option,
        XTGDEBUG,
    )

    self._actnum_indices = None
    self._filesrc = None
    self._props = None
    self._subgrids = None
    self._roxgrid = None
    self._roxindexer = None
    self._tmp = {}
示例#4
0
def get_dxdy(self, names=("dX", "dY"), asmasked=False):
    """Get dX, dY as properties"""
    ntot = self._ncol * self._nrow * self._nlay
    dx = GridProperty(
        ncol=self._ncol,
        nrow=self._nrow,
        nlay=self._nlay,
        values=np.zeros(ntot, dtype=np.float64),
        name=names[0],
        discrete=False,
    )
    dy = GridProperty(
        ncol=self._ncol,
        nrow=self._nrow,
        nlay=self._nlay,
        values=np.zeros(ntot, dtype=np.float64),
        name=names[1],
        discrete=False,
    )

    ptr_dx_v = _cxtgeo.new_doublearray(self.ntotal)
    ptr_dy_v = _cxtgeo.new_doublearray(self.ntotal)

    option1 = 0
    option2 = 0

    if asmasked:
        option1 = 1

    _cxtgeo.grd3d_calc_dxdy(
        self._ncol,
        self._nrow,
        self._nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        ptr_dx_v,
        ptr_dy_v,
        option1,
        option2,
        XTGDEBUG,
    )

    _gridprop_lowlevel.update_values_from_carray(dx, ptr_dx_v, np.float64, delete=True)
    _gridprop_lowlevel.update_values_from_carray(dy, ptr_dy_v, np.float64, delete=True)

    # return the property objects
    return dx, dy
示例#5
0
    def _convert_np_carr_double(self, np_array):
        """Convert numpy 1D array to C array, assuming double type."""
        carr = _cxtgeo.new_doublearray(self.nrow)

        _cxtgeo.swig_numpy_to_carr_1d(np_array, carr)

        return carr
示例#6
0
def get_xyz_cell_corners(self, ijk=(1, 1, 1), activeonly=True, zerobased=False):
    """Get X Y Z cell corners for one cell."""
    i, j, k = ijk

    shift = 0
    if zerobased:
        shift = 1

    if activeonly:
        actnum = self.get_actnum()
        iact = actnum.values3d[i - 1 + shift, j - 1 + shift, k - 1 + shift]
        if iact == 0:
            return None

    pcorners = _cxtgeo.new_doublearray(24)

    _cxtgeo.grd3d_corners(
        i + shift,
        j + shift,
        k + shift,
        self.ncol,
        self.nrow,
        self.nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        pcorners,
        XTGDEBUG,
    )

    cornerlist = []
    for i in range(24):
        cornerlist.append(_cxtgeo.doublearray_getitem(pcorners, i))

    clist = tuple(cornerlist)
    return clist
示例#7
0
def get_carr_double(self):
    """Return the SWIG Carray object"""

    carr = _cxtgeo.new_doublearray(self.ncol * self.nrow)

    _cxtgeo.swig_numpy_to_carr_1d(self.get_values1d(), carr)

    return carr
示例#8
0
def convert_np_carr_double(xyz, np_array):  # pragma: no cover
    """Convert numpy 1D array to C array, assuming double type."""

    carr = _cxtgeo.new_doublearray(xyz.nrow)

    _cxtgeo.swig_numpy_to_carr_1d(np_array, carr)

    return carr
示例#9
0
def update_carray(self, undef=None, discrete=None, dtype=None, order="F"):
    """Copy (update) values from numpy to SWIG, 1D array, returns a pointer
    to SWIG C array. If discrete is defined as True or False, force
    the SWIG array to be of that kind.

    Note that dtype will "override" current datatype if set. The resulting
    carray will be in Fortran order, unless order is specified as 'C'
    """

    dstatus = self._isdiscrete
    if discrete is not None:
        dstatus = bool(discrete)

    if undef is None:
        undef = xtgeo.UNDEF
        if dstatus:
            undef = xtgeo.UNDEF_INT

    logger.debug("Entering conversion from numpy to C array ...")

    values = self._values.copy()

    if not dtype:
        if dstatus:
            values = values.astype(np.int32)
        else:
            values = values.astype(np.float64)
    else:
        values = values.astype(dtype)

    values = ma.filled(values, undef)

    if order == "F":
        values = np.asfortranarray(values)
        values1d = np.ravel(values, order="K")

    if values1d.dtype == "float64" and dstatus and not dtype:
        values1d = values1d.astype("int32")
        logger.debug("Casting has been done")

    if values1d.dtype == "float64":
        logger.debug("Convert to carray (double)")
        carray = _cxtgeo.new_doublearray(self.ntotal)
        _cxtgeo.swig_numpy_to_carr_1d(values1d, carray)
    elif values1d.dtype == "float32":
        logger.debug("Convert to carray (float)")
        carray = _cxtgeo.new_floatarray(self.ntotal)
        _cxtgeo.swig_numpy_to_carr_f1d(values1d, carray)
    elif values1d.dtype == "int32":
        logger.debug("Convert to carray (int32)")
        carray = _cxtgeo.new_intarray(self.ntotal)
        _cxtgeo.swig_numpy_to_carr_i1d(values1d, carray)
    else:
        raise RuntimeError(
            "Unsupported dtype, probable bug in {}".format(__name__))
    return carray
示例#10
0
def test_x_interp_map_nodes(xcoords, ycoords, zcoords, xval, yval, method, zexpected):

    xv = _cxtgeo.new_doublearray(4)
    yv = _cxtgeo.new_doublearray(4)
    zv = _cxtgeo.new_doublearray(4)

    for num, xvalue in enumerate(xcoords):
        _cxtgeo.doublearray_setitem(xv, num, xvalue)
    for num, yvalue in enumerate(ycoords):
        _cxtgeo.doublearray_setitem(yv, num, yvalue)
    for num, zvalue in enumerate(zcoords):
        _cxtgeo.doublearray_setitem(zv, num, zvalue)

    zresult = _cxtgeo.x_interp_map_nodes(xv, yv, zv, xval, yval, method)

    if isinstance(zexpected, list):
        assert zresult in zexpected
    else:
        assert zresult == zexpected
示例#11
0
def get_cell_volume(self,
                    ijk=(1, 1, 1),
                    activeonly=True,
                    zerobased=False,
                    precision=2):
    """Get bulk cell volume for one cell."""
    self._xtgformat1()

    i, j, k = ijk

    if precision not in (1, 2, 4):
        raise ValueError(
            "The precision key has an invalid entry, use 1, 2, or 4")

    shift = 0
    if zerobased:
        shift = 1

    if activeonly:
        actnum = self.get_actnum()
        iact = actnum.values3d[i - 1 + shift, j - 1 + shift, k - 1 + shift]
        if iact == 0:
            return None

    pcorners = _cxtgeo.new_doublearray(24)

    if self._xtgformat == 1:
        logger.info("Use xtgformat 1...")
        _cxtgeo.grd3d_corners(
            i + shift,
            j + shift,
            k + shift,
            self.ncol,
            self.nrow,
            self.nlay,
            self._coordsv,
            self._zcornsv,
            pcorners,
        )
    else:
        logger.info("Use xtgformat 2...")
        _cxtgeo.grdcp3d_corners(
            i + shift - 1,
            j + shift - 1,
            k + shift - 1,
            self.ncol,
            self.nrow,
            self.nlay,
            self._coordsv,
            self._zcornsv,
            pcorners,
        )

    cellvol = _cxtgeo.x_hexahedron_volume(pcorners, 24, precision)
    return cellvol
示例#12
0
def get_xyz_cell_corners(self,
                         ijk=(1, 1, 1),
                         activeonly=True,
                         zerobased=False):
    """Get X Y Z cell corners for one cell."""
    self._xtgformat1()

    i, j, k = ijk

    shift = 0
    if zerobased:
        shift = 1

    if activeonly:
        actnum = self.get_actnum()
        iact = actnum.values3d[i - 1 + shift, j - 1 + shift, k - 1 + shift]
        if iact == 0:
            return None

    pcorners = _cxtgeo.new_doublearray(24)

    if self._xtgformat == 1:
        logger.info("Use xtgformat 1...")
        _cxtgeo.grd3d_corners(
            i + shift,
            j + shift,
            k + shift,
            self.ncol,
            self.nrow,
            self.nlay,
            self._coordsv,
            self._zcornsv,
            pcorners,
        )
    else:
        logger.info("Use xtgformat 2...")
        _cxtgeo.grdcp3d_corners(
            i + shift - 1,
            j + shift - 1,
            k + shift - 1,
            self.ncol,
            self.nrow,
            self.nlay,
            self._coordsv,
            self._zcornsv,
            pcorners,
        )

    cornerlist = []
    for i in range(24):
        cornerlist.append(_cxtgeo.doublearray_getitem(pcorners, i))

    clist = tuple(cornerlist)
    return clist
示例#13
0
def reduce_to_one_layer(self):
    """Reduce the grid to one single layer.

    This can be useful for algorithms that need to test if a point is within
    the full grid.

    Example::

        >>> from xtgeo.grid3d import Grid
        >>> gf = Grid('gullfaks2.roff')
        >>> gf.nlay
        47
        >>> gf.reduce_to_one_layer()
        >>> gf.nlay
        1

    """

    # need new pointers in C (not for coord)

    ptr_new_num_act = _cxtgeo.new_intpointer()

    nnum = (1 + 1) * 4
    ptr_new_zcorn_v = _cxtgeo.new_doublearray(self.ncol * self.nrow * nnum)

    ptr_new_actnum_v = _cxtgeo.new_intarray(self.ncol * self.nrow * 1)

    _cxtgeo.grd3d_reduce_onelayer(
        self.ncol,
        self.nrow,
        self.nlay,
        self._p_zcorn_v,
        ptr_new_zcorn_v,
        self._p_actnum_v,
        ptr_new_actnum_v,
        ptr_new_num_act,
        0,
        XTGDEBUG,
    )

    self._nlay = 1
    self._p_zcorn_v = ptr_new_zcorn_v
    self._p_actnum_v = ptr_new_actnum_v
    self._props = None
    self._subgrids = None
示例#14
0
def get_dz(self, name="dZ", flip=True, asmasked=True):
    """Get dZ as property"""
    ntot = (self._ncol, self._nrow, self._nlay)

    dzv = GridProperty(
        ncol=self._ncol,
        nrow=self._nrow,
        nlay=self._nlay,
        values=np.zeros(ntot, dtype=np.float64),
        name=name,
        discrete=False,
    )

    ptr_dz_v = _cxtgeo.new_doublearray(self.ntotal)

    nflip = 1
    if not flip:
        nflip = -1

    option = 0
    if asmasked:
        option = 1

    _cxtgeo.grd3d_calc_dz(
        self._ncol,
        self._nrow,
        self._nlay,
        self._p_zcorn_v,
        self._p_actnum_v,
        ptr_dz_v,
        nflip,
        option,
        XTGDEBUG,
    )

    _gridprop_lowlevel.update_values_from_carray(dzv, ptr_dz_v, np.float64, delete=True)
    # return the property object

    logger.info("DZ mean value: %s", dzv.values.mean())

    return dzv
示例#15
0
def test_grd3d_points_ijk_cells_nivec():
    with pytest.raises(
            xtgeo.XTGeoCLibError,
            match=r"nivec != njvec or nivec != nkvec",
    ):
        carr = [_cxtgeo.new_doublearray(1) for _ in range(4)]
        [_cxtgeo.swig_numpy_to_carr_1d(np.array([1.0]), arr) for arr in carr]

        _cxtgeo.grd3d_points_ijk_cells(
            np.array([1.0], dtype=np.float64),
            np.array([0.0], dtype=np.float64),
            np.array([1.0], dtype=np.float64),
            1,
            1,
            0.0,
            0.0,
            0.0,
            0.0,
            0.0,
            1,
            carr[0],
            carr[1],
            carr[2],
            carr[3],
            1,
            1,
            1,
            np.array([0.0], dtype=np.float32),
            np.array([1.0], dtype=np.float32),
            np.array([1], dtype=np.int32),
            np.array([0.0], dtype=np.float64),
            1,
            2,
            1,
            1,
        )
示例#16
0
def import_ecl_grdecl(self, gfile):

    # make a temporary file
    fds, tmpfile = mkstemp(prefix="tmpxtgeo")
    os.close(fds)

    with open(gfile) as oldfile, open(tmpfile, "w") as newfile:
        for line in oldfile:
            if not (re.search(r"^--", line) or re.search(r"^\s+$", line)):
                newfile.write(line)

    newfile.close()
    oldfile.close()

    # find ncol nrow nz
    mylist = []
    found = False
    with open(tmpfile) as xfile:
        for line in xfile:
            if found:
                logger.info(line)
                mylist = line.split()
                break
            if re.search(r"^SPECGRID", line):
                found = True

    if not found:
        logger.error("SPECGRID not found. Nothing imported!")
        return
    xfile.close()

    self._ncol, self._nrow, self._nlay = int(mylist[0]), int(mylist[1]), int(
        mylist[2])

    logger.info("NX NY NZ in grdecl file: %s %s %s", self._ncol, self._nrow,
                self._nlay)

    ntot = self._ncol * self._nrow * self._nlay
    ncoord = (self._ncol + 1) * (self._nrow + 1) * 2 * 3
    nzcorn = self._ncol * self._nrow * (self._nlay + 1) * 4

    logger.info("Reading...")

    ptr_num_act = _cxtgeo.new_intpointer()
    self._p_coord_v = _cxtgeo.new_doublearray(ncoord)
    self._p_zcorn_v = _cxtgeo.new_doublearray(nzcorn)
    self._p_actnum_v = _cxtgeo.new_intarray(ntot)

    _cxtgeo.grd3d_import_grdecl(
        self._ncol,
        self._nrow,
        self._nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        ptr_num_act,
        tmpfile,
        XTGDEBUG,
    )

    # remove tmpfile
    os.remove(tmpfile)

    nact = _cxtgeo.intpointer_value(ptr_num_act)

    logger.info("Number of active cells: %s", nact)
    self._subgrids = None
示例#17
0
def refine_vertically(self, rfactor, zoneprop=None):
    """Refine vertically, proportionally

    See details in caller.
    """
    rfactord = OrderedDict()

    # case 1 rfactor as scalar value.
    if isinstance(rfactor, int):
        if self.subgrids:
            subgrids = self.get_subgrids()
            for i, _ in enumerate(self.subgrids.keys()):
                rfactord[i + 1] = rfactor
        else:
            rfactord[0] = rfactor
            subgrids = OrderedDict()
            subgrids[1] = self.nlay

    # case 2 rfactor is a dict
    else:
        rfactord = OrderedDict(sorted(rfactor.items()))  # redefined to ordered
        # 2a: zoneprop is present
        if zoneprop is not None:
            oldsubgrids = None
            if self.subgrids:
                oldsubgrids = self.get_subgrids()

            subgrids = self.subgrids_from_zoneprop(zoneprop)

            if oldsubgrids:
                if subgrids.values() != oldsubgrids.values():
                    xtg.warn("ISSUES!!!")

        # 2b: zoneprop is not present
        elif zoneprop is None and self.subgrids:
            subgrids = self.get_subgrids()

        elif zoneprop is None and not self.subgrids:
            raise ValueError("You gave in a dict, but no zoneprops and "
                             "subgrids are not preesent in the grid")
        else:
            raise ValueError("Some major unexpected issue in routine...")

    if len(subgrids) != len(rfactord):
        raise RuntimeError("Subgrids and refinements: different definition!")

    self.set_subgrids(subgrids)

    # Now, based on dict, give a value per subgrid for key, val in rfactor
    newsubgrids = OrderedDict()
    newnlay = 0
    for (_x, rfi), (snam, sran) in zip(rfactord.items(), subgrids.items()):
        newsubgrids[snam] = sran * rfi
        newnlay += newsubgrids[snam]

    logger.debug("New layers: %s", newnlay)

    # rfac is an array with length nlay; has N refinements per single K layer
    rfac = _cxtgeo.new_intarray(self.nlay)

    totvector = []
    for (_tmp1, rfi), (_tmp2, arr) in zip(rfactord.items(),
                                          self.subgrids.items()):
        for _elem in range(len(arr)):
            totvector.append(rfi)
    for inn, rfi in enumerate(totvector):
        _cxtgeo.intarray_setitem(rfac, inn, rfi)

    ref_num_act = _cxtgeo.new_intpointer()
    ref_p_zcorn_v = _cxtgeo.new_doublearray(self.ncol * self.nrow *
                                            (newnlay + 1) * 4)
    ref_p_actnum_v = _cxtgeo.new_intarray(self.ncol * self.nrow * newnlay)

    ier = _cxtgeo.grd3d_refine_vert(
        self.ncol,
        self.nrow,
        self.nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        newnlay,
        ref_p_zcorn_v,
        ref_p_actnum_v,
        ref_num_act,
        rfac,
        0,
        XTGDEBUG,
    )

    if ier != 0:
        raise RuntimeError("An error occured in the C routine "
                           "grd3d_refine_vert, code {}".format(ier))

    # update instance:
    self._nlay = newnlay
    self._p_zcorn_v = ref_p_zcorn_v
    self._p_actnum_v = ref_p_actnum_v
    if self.subgrids is None or len(self.subgrids) <= 1:
        self.subgrids = None
    else:
        self.set_subgrids(newsubgrids)

    return self
示例#18
0
def _convert_to_xtgeo_grid(self, rox, roxgrid, corners):
    """Convert from RMS API to XTGeo API"""

    # pylint: disable=too-many-statements

    logger.info("Converting to XTGeo internals...")
    logger.info("Call the ROXAPI grid indexer")
    indexer = roxgrid.grid_indexer

    ncol, nrow, nlay = indexer.dimensions
    ntot = ncol * nrow * nlay

    # update other attributes
    self._ncol = ncol
    self._nrow = nrow
    self._nlay = nlay

    if corners is None:
        logger.info("Asked for dimensions_only: No geometry read!")
        return

    logger.info("Get active cells")
    mybuffer = np.ndarray(indexer.dimensions, dtype=np.int32)

    mybuffer.fill(0)

    logger.info("Get cell numbers")
    cellno = indexer.get_cell_numbers_in_range((0, 0, 0), indexer.dimensions)

    logger.info("Reorder...")
    ijk = indexer.get_indices(cellno)

    iind = ijk[:, 0]
    jind = ijk[:, 1]
    kind = ijk[:, 2]

    pvalues = np.ones(len(cellno))
    pvalues[cellno] = 1
    mybuffer[iind, jind, kind] = pvalues[cellno]

    actnum = mybuffer

    if rox.version_required("1.3"):
        logger.info("Handedness (new) %s", indexer.ijk_handedness)
    else:
        logger.info("Handedness (old) %s", indexer.handedness)

    corners = corners.ravel(order="K")
    actnum = actnum.ravel(order="K")

    logger.info("Convert to C pointers...")

    nnum = ncol * nrow * nlay * 24
    ccorners = _cxtgeo.new_doublearray(nnum)
    ntot = ncol * nrow * nlay
    cactnum = _cxtgeo.new_intarray(ntot)
    ncoord = (ncol + 1) * (nrow + 1) * 2 * 3
    nzcorn = ncol * nrow * (nlay + 1) * 4

    self._p_coord_v = _cxtgeo.new_doublearray(ncoord)
    self._p_zcorn_v = _cxtgeo.new_doublearray(nzcorn)
    self._p_actnum_v = _cxtgeo.new_intarray(ntot)

    _cxtgeo.swig_numpy_to_carr_1d(corners, ccorners)
    _cxtgeo.swig_numpy_to_carr_i1d(actnum, cactnum)

    # next task is to convert geometry to cxtgeo internal format
    logger.info("Run XTGeo C code...")
    _cxtgeo.grd3d_conv_roxapi_grid(
        ncol,
        nrow,
        nlay,
        ntot,
        cactnum,
        ccorners,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        XTGDEBUG,
    )
    logger.info("Run XTGeo C code... done")

    _cxtgeo.delete_doublearray(ccorners)
    _cxtgeo.delete_intarray(cactnum)
    logger.info("Converting to XTGeo internals... done")

    # subgrids
    if len(indexer.zonation) > 1:
        logger.debug("Zonation length (N subzones) is %s",
                     len(indexer.zonation))
        subz = OrderedDict()
        for inum, zrange in indexer.zonation.items():
            logger.debug("inum: %s, zrange: %s", inum, zrange)
            zname = roxgrid.zone_names[inum]
            logger.debug("zname is: %s", zname)
            zra = [nn + 1 for ira in zrange for nn in ira]  # nested lists
            subz[zname] = zra

        self.subgrids = subz
示例#19
0
def _import_roff_v1(self, pfile, name):
    """Import ROFF format, version 1"""
    # pylint: disable=too-many-locals

    # there is a todo here to get it more robust for various cases,
    # e.g. that a ROFF file may contain both a grid an numerous
    # props

    logger.info("Looking for %s in file %s", name, pfile)

    ptr_ncol = _cxtgeo.new_intpointer()
    ptr_nrow = _cxtgeo.new_intpointer()
    ptr_nlay = _cxtgeo.new_intpointer()
    ptr_ncodes = _cxtgeo.new_intpointer()
    ptr_type = _cxtgeo.new_intpointer()

    ptr_idum = _cxtgeo.new_intpointer()
    ptr_ddum = _cxtgeo.new_doublepointer()

    # read with mode 0, to scan for ncol, nrow, nlay and ndcodes, and if
    # property is found...
    ier, _codenames = _cxtgeo.grd3d_imp_prop_roffbin(
        pfile,
        0,
        ptr_type,
        ptr_ncol,
        ptr_nrow,
        ptr_nlay,
        ptr_ncodes,
        name,
        ptr_idum,
        ptr_ddum,
        ptr_idum,
        0,
        XTGDEBUG,
    )

    if ier == -1:
        msg = "Cannot find property name {}".format(name)
        logger.warning(msg)
        raise SystemExit("Error from ROFF import")

    self._ncol = _cxtgeo.intpointer_value(ptr_ncol)
    self._nrow = _cxtgeo.intpointer_value(ptr_nrow)
    self._nlay = _cxtgeo.intpointer_value(ptr_nlay)
    self._ncodes = _cxtgeo.intpointer_value(ptr_ncodes)

    ptype = _cxtgeo.intpointer_value(ptr_type)

    ntot = self._ncol * self._nrow * self._nlay

    if self._ncodes <= 1:
        self._ncodes = 1
        self._codes = {0: "undef"}

    logger.debug("Number of codes: %s", self._ncodes)

    # allocate

    if ptype == 1:  # float, assign to double
        ptr_pval_v = _cxtgeo.new_doublearray(ntot)
        ptr_ival_v = _cxtgeo.new_intarray(1)
        self._isdiscrete = False
        self._dtype = "float64"

    elif ptype > 1:
        ptr_pval_v = _cxtgeo.new_doublearray(1)
        ptr_ival_v = _cxtgeo.new_intarray(ntot)
        self._isdiscrete = True
        self._dtype = "int32"

    # number of codes and names
    ptr_ccodes_v = _cxtgeo.new_intarray(self._ncodes)

    # NB! note the SWIG trick to return modified char values; use cstring.i
    # inn the config and %cstring_bounded_output(char *p_codenames_v, NN);
    # Then the argument for *p_codevalues_v in C is OMITTED here!

    ier, cnames = _cxtgeo.grd3d_imp_prop_roffbin(
        pfile,
        1,
        ptr_type,
        ptr_ncol,
        ptr_nrow,
        ptr_nlay,
        ptr_ncodes,
        name,
        ptr_ival_v,
        ptr_pval_v,
        ptr_ccodes_v,
        0,
        XTGDEBUG,
    )

    if self._isdiscrete:
        _gridprop_lowlevel.update_values_from_carray(self,
                                                     ptr_ival_v,
                                                     np.int32,
                                                     delete=True)
    else:
        _gridprop_lowlevel.update_values_from_carray(self,
                                                     ptr_pval_v,
                                                     np.float64,
                                                     delete=True)

    # now make dictionary of codes
    if self._isdiscrete:
        cnames = cnames.replace(";", "")
        cname_list = cnames.split("|")
        cname_list.pop()  # some rubbish as last entry
        ccodes = []
        for ino in range(0, self._ncodes):
            ccodes.append(_cxtgeo.intarray_getitem(ptr_ccodes_v, ino))

        self._codes = dict(zip(ccodes, cname_list))

    self._name = name
示例#20
0
def get_xyz_corners(self, names=("X_UTME", "Y_UTMN", "Z_TVDSS")):
    """Get X Y Z cell corners for all cells (as 24 GridProperty objects)"""
    ntot = (self._ncol, self._nrow, self._nlay)

    grid_props = []

    for i in range(0, 8):
        xname = names[0] + str(i)
        yname = names[1] + str(i)
        zname = names[2] + str(i)
        x = GridProperty(
            ncol=self._ncol,
            nrow=self._nrow,
            nlay=self._nlay,
            values=np.zeros(ntot, dtype=np.float64),
            name=xname,
            discrete=False,
        )

        y = GridProperty(
            ncol=self._ncol,
            nrow=self._nrow,
            nlay=self._nlay,
            values=np.zeros(ntot, dtype=np.float64),
            name=yname,
            discrete=False,
        )

        z = GridProperty(
            ncol=self._ncol,
            nrow=self._nrow,
            nlay=self._nlay,
            values=np.zeros(ntot, dtype=np.float64),
            name=zname,
            discrete=False,
        )

        grid_props.append(x)
        grid_props.append(y)
        grid_props.append(z)

    ptr_coord = []
    for i in range(24):
        some = _cxtgeo.new_doublearray(self.ntotal)
        ptr_coord.append(some)

    for i, va in enumerate(ptr_coord):
        logger.debug("SWIG object %s   %s", i, va)

    option = 0

    # note, fool the argument list to unpack ptr_coord with * ...
    _cxtgeo.grd3d_get_all_corners(self._ncol, self._nrow, self._nlay,
                                  self._coordsv, self._zcornsv, self._actnumsv,
                                  *(ptr_coord + [option]))

    for i in range(0, 24, 3):

        _gridprop_lowlevel.update_values_from_carray(grid_props[i],
                                                     ptr_coord[i],
                                                     np.float64,
                                                     delete=True)

        _gridprop_lowlevel.update_values_from_carray(grid_props[i + 1],
                                                     ptr_coord[i + 1],
                                                     np.float64,
                                                     delete=True)

        _gridprop_lowlevel.update_values_from_carray(grid_props[i + 2],
                                                     ptr_coord[i + 2],
                                                     np.float64,
                                                     delete=True)

    # return the 24 objects (x1, y1, z1, ... x8, y8, z8)
    return tuple(grid_props)
示例#21
0
def make_hybridgrid(grid, **kwargs):
    """Make hybrid grid.

    It changes the grid geometry status of the object.

    Input:
        grid (object): A grid object
        TODO region (object): A region parameter (property object)
        etc...
    """

    nhdiv = kwargs.get("nhdiv")
    toplevel = kwargs.get("toplevel")
    bottomlevel = kwargs.get("bottomlevel")
    region = kwargs.get("region", None)
    region_number = kwargs.get("region_number", None)

    logger.debug("nhdiv: %s", nhdiv)
    logger.debug("toplevel: %s", toplevel)
    logger.debug("bottomlevel: %s", bottomlevel)
    logger.debug("region: %s", region)
    logger.debug("region_number: %s", region_number)

    xtg_verbose_level = xtg.syslevel

    newnlay = grid.nlay * 2 + nhdiv

    hyb_num_act = _cxtgeo.new_intpointer()
    hyb_p_zcorn_v = _cxtgeo.new_doublearray(grid.ncol * grid.nrow *
                                            (newnlay + 1) * 4)
    hyb_p_actnum_v = _cxtgeo.new_intarray(grid.ncol * grid.nrow * newnlay)

    if region is None:
        _cxtgeo.grd3d_convert_hybrid(
            grid.ncol,
            grid.nrow,
            grid.nlay,
            grid._p_coord_v,
            grid._p_zcorn_v,
            grid._p_actnum_v,
            newnlay,
            hyb_p_zcorn_v,
            hyb_p_actnum_v,
            hyb_num_act,
            toplevel,
            bottomlevel,
            nhdiv,
            xtg_verbose_level,
        )
    else:

        region.discrete_to_continuous()

        carray_reg = _gridprop_lowlevel.update_carray(region)

        _cxtgeo.grd3d_convert_hybrid2(
            grid.ncol,
            grid.nrow,
            grid.nlay,
            grid._p_coord_v,
            grid._p_zcorn_v,
            grid._p_actnum_v,
            newnlay,
            hyb_p_zcorn_v,
            hyb_p_actnum_v,
            hyb_num_act,
            toplevel,
            bottomlevel,
            nhdiv,
            carray_reg,
            region_number,
            xtg_verbose_level,
        )

        _gridprop_lowlevel.delete_carray(region, carray_reg)

    grid._nlay = newnlay
    grid._p_zcorn_v = hyb_p_zcorn_v
    grid._p_actnum_v = hyb_p_actnum_v

    return grid
示例#22
0
def crop(self, spec, props=None):  # pylint: disable=too-many-locals
    """Do cropping of geometry (and properties).

    If props is 'all' then all properties assosiated (linked) to then
    grid are also cropped, and the instances are updated.

    Args:
        spec (tuple): A nested tuple on the form ((i1, i2), (j1, j2), (k1, k2))
            where 1 represents start number, and 2 reperesent end. The range
            is inclusive for both ends, and the number start index is 1 based.
        props (list or str): None is default, while properties can be listed.
            If 'all', then all GridProperty objects which are linked to the
            Grid instance are updated.

    Returns:
        The instance is updated (cropped)
    """

    (ic1, ic2), (jc1, jc2), (kc1, kc2) = spec

    if (
        ic1 < 1
        or ic2 > self.ncol
        or jc1 < 1
        or jc2 > self.nrow
        or kc1 < 1
        or kc2 > self.nlay
    ):

        raise ValueError("Boundary for tuples not matching grid" "NCOL, NROW, NLAY")

    oldnlay = self._nlay

    # compute size of new cropped grid
    nncol = ic2 - ic1 + 1
    nnrow = jc2 - jc1 + 1
    nnlay = kc2 - kc1 + 1

    ntot = nncol * nnrow * nnlay
    ncoord = (nncol + 1) * (nnrow + 1) * 2 * 3
    nzcorn = nncol * nnrow * (nnlay + 1) * 4

    new_num_act = _cxtgeo.new_intpointer()
    new_p_coord_v = _cxtgeo.new_doublearray(ncoord)
    new_p_zcorn_v = _cxtgeo.new_doublearray(nzcorn)
    new_p_actnum_v = _cxtgeo.new_intarray(ntot)

    _cxtgeo.grd3d_crop_geometry(
        self.ncol,
        self.nrow,
        self.nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        new_p_coord_v,
        new_p_zcorn_v,
        new_p_actnum_v,
        ic1,
        ic2,
        jc1,
        jc2,
        kc1,
        kc2,
        new_num_act,
        0,
        XTGDEBUG,
    )

    self._p_coord_v = new_p_coord_v
    self._p_zcorn_v = new_p_zcorn_v
    self._p_actnum_v = new_p_actnum_v

    self._ncol = nncol
    self._nrow = nnrow
    self._nlay = nnlay

    if isinstance(self.subgrids, dict):
        newsub = OrderedDict()
        # easier to work with numpies than lists
        newarr = np.array(range(1, oldnlay + 1))
        newarr[newarr < kc1] = 0
        newarr[newarr > kc2] = 0
        newaxx = newarr.copy() - kc1 + 1
        for sub, arr in self.subgrids.items():
            arrx = np.array(arr)
            arrxmap = newaxx[arrx[0] - 1 : arrx[-1]]
            arrxmap = arrxmap[arrxmap > 0]
            if arrxmap.size > 0:
                newsub[sub] = arrxmap.astype(np.int32).tolist()

        self.subgrids = newsub

    # crop properties
    if props is not None:
        if props == "all":
            props = self.props

        for prop in props:
            logger.info("Crop %s", prop.name)
            prop.crop(spec)
示例#23
0
def import_ecl_bgrdecl(self, gfile):
    """Import binary files with GRDECL layout"""

    local_fhandle = False
    fhandle = gfile
    if isinstance(gfile, str):
        local_fhandle = True
        gfile = xtgeo._XTGeoCFile(gfile)
        fhandle = gfile.fhandle

    # scan file for properties; these have similar binary format as e.g. EGRID
    logger.info("Make kwlist by scanning")
    kwlist = utils.scan_keywords(fhandle,
                                 fformat="xecl",
                                 maxkeys=1000,
                                 dataframe=False,
                                 dates=False)
    bpos = {}
    needkwlist = ["SPECGRID", "COORD", "ZCORN", "ACTNUM"]
    optkwlist = ["MAPAXES"]
    for name in needkwlist + optkwlist:
        bpos[name] = -1  # initially

    for kwitem in kwlist:
        kwname, kwtype, kwlen, kwbyte = kwitem
        if kwname == "SPECGRID":
            # read grid geometry record:
            specgrid = eclbin_record(fhandle, "SPECGRID", kwlen, kwtype,
                                     kwbyte)
            ncol, nrow, nlay = specgrid[0:3].tolist()
            logger.info("%s %s %s", ncol, nrow, nlay)
        elif kwname in needkwlist:
            bpos[kwname] = kwbyte
        elif kwname == "MAPAXES":  # not always present
            bpos[kwname] = kwbyte

    self._ncol = ncol
    self._nrow = nrow
    self._nlay = nlay

    logger.info("Grid dimensions in binary GRDECL file: %s %s %s", ncol, nrow,
                nlay)

    # allocate dimensions:
    ntot = self._ncol * self._nrow * self._nlay
    ncoord = (self._ncol + 1) * (self._nrow + 1) * 2 * 3
    nzcorn = self._ncol * self._nrow * (self._nlay + 1) * 4

    self._p_coord_v = _cxtgeo.new_doublearray(ncoord)
    self._p_zcorn_v = _cxtgeo.new_doublearray(nzcorn)
    self._p_actnum_v = _cxtgeo.new_intarray(ntot)
    p_nact = _cxtgeo.new_longpointer()

    ier = _cxtgeo.grd3d_imp_ecl_egrid(
        fhandle,
        self._ncol,
        self._nrow,
        self._nlay,
        bpos["MAPAXES"],
        bpos["COORD"],
        bpos["ZCORN"],
        bpos["ACTNUM"],
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        p_nact,
        0,
    )

    if ier == -1:
        raise RuntimeError("Error code -1 from _cxtgeo.grd3d_imp_ecl_egrid")

    self._nactive = _cxtgeo.longpointer_value(p_nact)

    if local_fhandle:
        gfile.close(cond=local_fhandle)
示例#24
0
def report_zone_mismatch(  # pylint: disable=too-many-statements
    self,
    well=None,
    zonelogname="ZONELOG",
    zoneprop=None,
    onelayergrid=None,
    zonelogrange=(0, 9999),
    zonelogshift=0,
    depthrange=None,
    option=0,
    perflogname=None,
):
    """Reports well to zone mismatch; this works together with a Well object."""

    this = inspect.currentframe().f_code.co_name

    # first do some trimming of the well dataframe
    if not well or not isinstance(well, Well):
        msg = "No well object in <{}> or invalid object; " "returns no result".format(
            this)
        xtg.warn(msg)
        return None

    if not well.zonelogname:
        msg = ("Asked for zone log <{}> but no such in <{}> for well {}; "
               "return None".format(zonelogname, this, well.wellname))
        xtg.warn(msg)
        # warnings.warn(UserWarning(msg))
        return None

        # qperf = True
    if perflogname == "None" or perflogname is None:
        # qperf = False
        pass
    else:
        if perflogname not in well.lognames:
            msg = ("Asked for perf log <{}> but no such in <{}> for well {}; "
                   "return None".format(perflogname, this, well.wellname))
            xtg.warn(msg)
            # warnings.warn(UserWarning(msg))
            return None

    logger.info("Process well object for %s...", well.wellname)
    df = well.dataframe.copy()

    if depthrange:
        logger.info("Filter depth...")
        df = df[df.Z_TVDSS > depthrange[0]]
        df = df[df.Z_TVDSS < depthrange[1]]
        df = df.copy()

    logger.info("Adding zoneshift %s", zonelogshift)
    if zonelogshift != 0:
        df[zonelogname] += zonelogshift

    logger.info("Filter ZONELOG...")
    df = df[df[zonelogname] > zonelogrange[0]]
    df = df[df[zonelogname] < zonelogrange[1]]
    df = df.copy()

    if perflogname:
        logger.info("Filter PERF...")
        df[perflogname].fillna(-999, inplace=True)
        df = df[df[perflogname] > 0]
        df = df.copy()

    df.reset_index(drop=True, inplace=True)
    well.dataframe = df

    # get the relevant well log C arrays...
    ptr_xc = well.get_carray("X_UTME")
    ptr_yc = well.get_carray("Y_UTMN")
    ptr_zc = well.get_carray("Z_TVDSS")
    ptr_zo = well.get_carray(zonelogname)

    nval = well.nrow

    ptr_results = _cxtgeo.new_doublearray(10)

    ptr_zprop = _gridprop_lowlevel.update_carray(zoneprop)

    cstatus = _cxtgeo.grd3d_rpt_zlog_vs_zon(
        self._ncol,
        self._nrow,
        self._nlay,
        self._coordsv,
        self._zcornsv,
        self._actnumsv,
        ptr_zprop,
        nval,
        ptr_xc,
        ptr_yc,
        ptr_zc,
        ptr_zo,
        zonelogrange[0],
        zonelogrange[1],
        onelayergrid._zcornsv,
        onelayergrid._actnumsv,
        ptr_results,
        option,
    )

    _gridprop_lowlevel.delete_carray(zoneprop, ptr_zprop)

    if cstatus == 0:
        logger.debug("OK well")
    elif cstatus == 2:
        msg = "Well {} have no zonation?".format(well.wellname)
        warnings.warn(msg, UserWarning)
    else:
        msg = "Something is rotten with {}".format(well.wellname)
        raise SystemExit(msg)

    # extract the report
    perc = _cxtgeo.doublearray_getitem(ptr_results, 0)
    tpoi = _cxtgeo.doublearray_getitem(ptr_results, 1)
    mpoi = _cxtgeo.doublearray_getitem(ptr_results, 2)

    # returns percent match, then total numbers of well counts for zone,
    # then match count. perc = mpoi/tpoi
    return (perc, int(tpoi), int(mpoi))
示例#25
0
def import_ecl_egrid(self, gfile):
    """Import, private to this routine."""

    eclfile = xtgeo._XTGeoCFile(gfile)

    # scan file for property
    logger.info("Make kwlist by scanning")
    kwlist = utils.scan_keywords(eclfile.fhandle,
                                 fformat="xecl",
                                 maxkeys=1000,
                                 dataframe=False,
                                 dates=False)
    bpos = {}
    for name in ("COORD", "ZCORN", "ACTNUM", "MAPAXES"):
        bpos[name] = -1  # initially

    self._dualporo = False
    for kwitem in kwlist:
        kwname, kwtype, kwlen, kwbyte = kwitem
        if kwname == "FILEHEAD":
            # read FILEHEAD record:
            filehead = eclbin_record(eclfile.fhandle, "FILEHEAD", kwlen,
                                     kwtype, kwbyte)
            dualp = filehead[5].tolist()
            logger.info("Dual porosity flag is %s", dualp)
            if dualp == 1:
                self._dualporo = True
                self._dualperm = False
            elif dualp == 2:
                self._dualporo = True
                self._dualperm = True
        elif kwname == "GRIDHEAD":
            # read GRIDHEAD record:
            gridhead = eclbin_record(eclfile.fhandle, "GRIDHEAD", kwlen,
                                     kwtype, kwbyte)
            ncol, nrow, nlay = gridhead[1:4].tolist()
            logger.info("%s %s %s", ncol, nrow, nlay)
        elif kwname in ("COORD", "ZCORN", "ACTNUM"):
            bpos[kwname] = kwbyte
        elif kwname == "MAPAXES":  # not always present
            bpos[kwname] = kwbyte

    self._ncol = ncol
    self._nrow = nrow
    self._nlay = nlay

    logger.info("Grid dimensions in EGRID file: %s %s %s", ncol, nrow, nlay)

    # allocate dimensions:
    ntot = self._ncol * self._nrow * self._nlay
    ncoord = (self._ncol + 1) * (self._nrow + 1) * 2 * 3
    nzcorn = self._ncol * self._nrow * (self._nlay + 1) * 4

    self._p_coord_v = _cxtgeo.new_doublearray(ncoord)
    self._p_zcorn_v = _cxtgeo.new_doublearray(nzcorn)
    self._p_actnum_v = _cxtgeo.new_intarray(ntot)
    p_nact = _cxtgeo.new_longpointer()

    option = 0
    if self._dualporo:
        option = 1

    ier = _cxtgeo.grd3d_imp_ecl_egrid(
        eclfile.fhandle,
        self._ncol,
        self._nrow,
        self._nlay,
        bpos["MAPAXES"],
        bpos["COORD"],
        bpos["ZCORN"],
        bpos["ACTNUM"],
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        p_nact,
        option,
    )

    if ier == -1:
        raise RuntimeError("Error code -1 from _cxtgeo.grd3d_imp_ecl_egrid")

    self._nactive = _cxtgeo.longpointer_value(p_nact)

    # in case of DUAL PORO/PERM ACTNUM will be 0..3; need to convert
    if self._dualporo:
        self._dualactnum = self.get_actnum(name="DUALACTNUM")
        acttmp = self._dualactnum.copy()
        acttmp.values[acttmp.values >= 1] = 1
        self.set_actnum(acttmp)

    eclfile.close()
示例#26
0
def get_xyz(self, names=("X_UTME", "Y_UTMN", "Z_TVDSS"), asmasked=True):
    """Get X Y Z as properties... May be issues with asmasked vs activeonly here"""

    ntot = self.ntotal

    x = GridProperty(
        ncol=self._ncol,
        nrow=self._nrow,
        nlay=self._nlay,
        values=np.zeros(ntot, dtype=np.float64),
        name=names[0],
        discrete=False,
    )

    y = GridProperty(
        ncol=self._ncol,
        nrow=self._nrow,
        nlay=self._nlay,
        values=np.zeros(ntot, dtype=np.float64),
        name=names[1],
        discrete=False,
    )

    z = GridProperty(
        ncol=self._ncol,
        nrow=self._nrow,
        nlay=self._nlay,
        values=np.zeros(ntot, dtype=np.float64),
        name=names[2],
        discrete=False,
    )

    ptr_x_v = _cxtgeo.new_doublearray(self.ntotal)
    ptr_y_v = _cxtgeo.new_doublearray(self.ntotal)
    ptr_z_v = _cxtgeo.new_doublearray(self.ntotal)

    option = 0
    if asmasked:
        option = 1

    _cxtgeo.grd3d_calc_xyz(
        self._ncol,
        self._nrow,
        self._nlay,
        self._p_coord_v,
        self._p_zcorn_v,
        self._p_actnum_v,
        ptr_x_v,
        ptr_y_v,
        ptr_z_v,
        option,
        XTGDEBUG,
    )

    _gridprop_lowlevel.update_values_from_carray(x, ptr_x_v, np.float64, delete=True)
    _gridprop_lowlevel.update_values_from_carray(y, ptr_y_v, np.float64, delete=True)
    _gridprop_lowlevel.update_values_from_carray(z, ptr_z_v, np.float64, delete=True)

    # Note: C arrays are deleted in the update_values_from_carray()

    return x, y, z