Exemplo n.º 1
0
def load_timevector_from_file(
    filename: str, startdate: datetime.date, file_starts_with_dates: bool
) -> TimeVector:
    """
    Load a timevector from a file, and clip dates that are  earlier than startdate.

    When the file does not start with a DATES keyword, we will never
    delete whatever comes before the first DATES. But if the first DATES
    predates startdate, then we delete it.

    Returns:
        opm.tools.TimeVector
    """
    tmpschedule = TimeVector(datetime.date(1900, 1, 1))
    if file_starts_with_dates:
        tmpschedule.load(filename)
        early_dates = [date for date in tmpschedule.dates if date.date() < startdate]
        if len(early_dates) > 1:
            logger.info("Clipping away dates: %s", str(early_dates[1:]))
            for date in early_dates:
                tmpschedule.delete(date)
    else:
        tmpschedule.load(filename, datetime_from_date(datetime.date(1900, 1, 1)))

        early_dates = [date for date in tmpschedule.dates if date.date() < startdate]
        if len(early_dates) > 1:
            logger.info("Clipping away dates: %s", str(early_dates[1:]))
            for date in early_dates:
                tmpschedule.delete(date)
    return tmpschedule
Exemplo n.º 2
0
def file_startswith_dates(filename):
    """Check if a sch file starts with DATES

    This information is sometimes needed to determine how to send
    calls off to opm.io.tools.TimeVector

    Args:
        filename (str): Filename to check

    Returns:
        True if the first statement/keyword is DATES
    """
    tmpschedule = TimeVector(datetime.date(1900, 1, 1))
    try:
        # Since the date is provided in the second arg here, this will fail if the
        # file starts with DATES
        tmpschedule.load(filename, datetime_from_date(datetime.date(1900, 1, 1)))
        return False
    except ValueError:
        return True
Exemplo n.º 3
0
def sch_file_nonempty(filename: str) -> bool:
    """Determine if a file (to be included) has any Eclipse
    keywords at all (excluding comments)

    Args:
        filename

    Returns:
        bool: False if the file is empty or has only comments.
    """
    # Implementation is by trial and error:
    try:
        tmpschedule = TimeVector(datetime.date(1900, 1, 1))
        tmpschedule.load(filename)
    except IndexError as err:
        if "Keyword index 0 is out of range" in str(err):
            # This is what we get from opm for empty files.
            return False

        # Try to workaround a non-explanatory error from opm-common:
        if "map::at" in str(err):
            logger.error("Error happened while parsing %s", filename)
            logger.error(
                "You have potentially used PATHS variables in INCLUDE statements?"
            )
            logger.error("This is not supported")
            raise SystemExit from err

        # Unknown error condition
        logger.error("Could not parse %s", filename)
        logger.error(err)
        raise SystemExit from err

    except ValueError:
        # This is where we get for files not starting with DATES,
        # but that means it is nonempty
        return True
    return True
Exemplo n.º 4
0
def sch_file_starts_with_dates_keyword(filename: str) -> bool:
    """Determine if a file (to be included) has
    DATES as its first keyword, or something else.

    We depend on knowing this in order to initialize
    the opm.tools.TimeVector object, and to be able
    to carefully handle whatever is in front of that DATES
    keyword (it is tricky, because we can't know for sure
    which date to anchor that to)

    Args:
        filename (str): Filename which will be opened and read.
    Returns:
        bool: true if first keyword is DATES
    """
    # Implementation is by trial and error:
    try:
        # Test if it has DATES
        tmpschedule = TimeVector(datetime.date(1900, 1, 1))
        tmpschedule.load(filename)
    except ValueError:
        return False
    return True
Exemplo n.º 5
0
def process_sch_config(conf) -> TimeVector:
    """Process a Schedule configuration into a opm.tools TimeVector

    Recognized keys in the configuration dict: files, startdate, startime,
    refdate, enddate, dategrid, insert

    Args:
        conf: Configuration dictionary for the schedule
            merges and inserts

    Returns:
        opm.io.TimeVector
    """
    # At least test code is calling this function with a dict as
    # config - convert it to a configsuite snapshot:
    if isinstance(conf, dict):
        conf = configsuite.ConfigSuite(
            conf, CONFIG_SCHEMA_V2, deduce_required=True
        ).snapshot

    # Rerun this to ensure error is caught (already done in transformation)
    datetime_from_date(conf.startdate)

    # Initialize the opm.tools.TimeVector class, which needs
    # a date to anchor to:
    schedule = TimeVector(conf.starttime)

    if conf.files is not None:
        for filename in conf.files:
            if sch_file_nonempty(filename):
                logger.info("Loading %s", filename)
            else:
                logger.warning("No Eclipse statements in %s, skipping", filename)
                continue

            file_starts_with_dates = sch_file_starts_with_dates_keyword(filename)
            timevector = load_timevector_from_file(
                filename, conf.startdate, file_starts_with_dates
            )
            if file_starts_with_dates:
                schedule.load_string(str(timevector))
            else:
                schedule.load_string(str(timevector), conf.starttime)

    if conf.insert is not None:
        logger.info("Processing %s insert statements", str(len(conf.insert)))
        for insert_statement in conf.insert:
            logger.debug(str(insert_statement))

            if insert_statement.substitute and insert_statement.template:
                filename = substitute(insert_statement)
                logger.debug("Produced file: %s", str(filename))
            elif insert_statement.template and not insert_statement.substitute:
                logger.error(
                    "Missing subsitute for template %s", insert_statement.template
                )
                continue
            elif insert_statement.filename:
                filename = insert_statement.filename
            elif not insert_statement.string:
                logger.error("Invalid insert statement: %s", str(insert_statement))

            # Which date to use for insertion?
            if insert_statement.date:
                date = datetime_from_date(insert_statement.date)
            elif insert_statement.days:
                date = datetime_from_date(conf.refdate) + datetime.timedelta(
                    days=insert_statement.days
                )
            else:
                logger.error("Could not determine date for insertion")
                logger.error("From data: %s", str(insert_statement))
                continue

            # Do the insertion:
            if date >= conf.starttime:
                if insert_statement.string is None:
                    if sch_file_nonempty(filename):
                        schedule.load(filename, date=date)
                    else:
                        logger.warning(
                            "No Eclipse statements in %s, skipping", filename
                        )
                else:
                    schedule.add_keywords(
                        datetime_from_date(date), [insert_statement.string]
                    )
            else:
                logger.warning("Ignoring inserts before startdate")

    if conf.enddate is None:
        enddate = schedule.dates[-1].date()
    else:
        enddate = conf.enddate  # datetime.date
        if not isinstance(enddate, datetime.date):
            raise TypeError(
                f"ERROR: enddate {conf.enddate} not in ISO-8601 format, "
                "must be YYYY-MM-DD"
            )

    # Clip anything that is beyond the enddate
    for date in schedule.dates:
        if date.date() > enddate:
            schedule.delete(date)

    # Ensure that the end-date is actually mentioned in the Schedule
    # so that we know Eclipse will actually simulate until this date
    if enddate not in [x.date() for x in schedule.dates]:
        schedule.add_keywords(datetime_from_date(enddate), [""])

    # Dategrid is added at the end, in order to support
    # an implicit end-date
    if conf.dategrid:
        dates = dategrid(conf.startdate, enddate, conf.dategrid)
        for _date in dates:
            schedule.add_keywords(datetime_from_date(_date), [""])

    return schedule