Skip to content

Forcings .bc file

The forcings .bc files contain forcing data for point locations, for example time series input for a boundary condition. Various quantities and function types are supported.

The forcings file is represented by the classes below.

Model

Representation of a .bc file in various classes.

Most relevant classes are:

  • ForcingModel: toplevel class containing the whole .bc file contents.
  • ForcingBase subclasses: containing the actual data columns, for example: TimeSeries, HarmonicComponent, AstronomicComponent, HarmonicCorrection, AstronomicCorrection, Constant, T3D.

Astronomic (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with astronomic components data.

AstronomicCorrection (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with astronomic components correction data.

Constant (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with constant value data.

ForcingBase (DataBlockINIBasedModel) pydantic-model

The base class of a single [Forcing] block in a .bc forcings file.

Typically subclassed, for the specific types of forcing data, e.g, TimeSeries. This model is for example referenced under a ForcingModel.forcing[..].

__repr__(self) -> str special

Return repr(self).

Source code in hydrolib/core/io/bc/models.py
def __repr__(self) -> str:
    data = dict(self)
    data["datablock"] = "<omitted>"
    representable = BaseModel.construct(**data)
    return str(representable)

validate(v) classmethod

Try to initialize subclass based on the function field. This field is compared to each function field of the derived models of ForcingBase. The derived model with an equal function type will be initialized.

Exceptions:

Type Description
ValueError

When the given type is not a known structure type.

Source code in hydrolib/core/io/bc/models.py
@classmethod
def validate(cls, v):
    """Try to initialize subclass based on the `function` field.
    This field is compared to each `function` field of the derived models of `ForcingBase`.
    The derived model with an equal function type will be initialized.

    Raises:
        ValueError: When the given type is not a known structure type.
    """

    # should be replaced by discriminated unions once merged
    # https://github.com/samuelcolvin/pydantic/pull/2336
    if isinstance(v, dict):
        for c in cls.__subclasses__():
            if (
                c.__fields__.get("function").default.lower()
                == v.get("function", "").lower()
            ):
                v = c(**v)
                break
        else:
            raise ValueError(
                f"Function of {cls.__name__} with name={v.get('name', '')} and function={v.get('function', '')} is not recognized."
            )
    return v

ForcingData

Data type that selects from three different types of forcing data: * a scalar float constant * "realtime" keyword, indicating externally controlled. * A ForcingModel coming from a .bc file.

ForcingGeneral (INIGeneral) pydantic-model

[General] section with .bc file metadata.

ForcingModel (INIModel) pydantic-model

The overall model that contains the contents of one .bc forcings file.

This model is for example referenced under a ExtModel.boundary[..].forcingfile[..].

Harmonic (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with harmonic components data.

HarmonicCorrection (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with harmonic components correction data.

QHTable (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with Q-h table data.

QuantityUnitPair (BaseModel) pydantic-model

A .bc file header lines tuple containing a quantity name, its unit and optionally a vertical position index.

RealTime (str, Enum)

Enum class containing the valid value for the "realtime" reserved keyword for real-time controlled forcing data, e.g., for hydraulic structures.

This class is used inside the ForcingData Union, to force detection of the realtime keyword, prior to considering it a filename.

realtime

str: Realtime data source, externally provided

T3D (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with 3D timeseries data.

TimeInterpolation (str, Enum)

Enum class containing the valid values for the time interpolation.

block_from

str: Equal to that at the start of the time interval (latest specified time value).

block_to

str: Equal to that at the end of the time interval (upcoming specified time value).

linear

str: Linear interpolation between times.

TimeSeries (ForcingBase) pydantic-model

Subclass for a .bc file [Forcing] block with timeseries data.

VectorQUPValidation

Helper class with validator routines for VectorQuantityUnitPairs objects. To be called from other model classes.

process_vectordefinition_or_check_quantityunitpairs(vectordefs: Optional[List[str]], quantityunitpairs: List[Union[hydrolib.core.io.bc.models.QuantityUnitPair, hydrolib.core.io.bc.models.VectorQuantityUnitPairs]], number_of_element_repetitions: int = 1) -> None staticmethod

Processes the given vector definition header lines from a .bc file or, if absent, checks whether the existing VectorQuantityUnitPairs objects already have the correct vector length.

Parameters:

Name Type Description Default
vectordefs List[str]

List of vector definition values, e.g., ["vectorname:comp1,comp2,..compN", ...]

required
quantityunitpairs List[ScalarOrVectorQUP]

list of already parsed and constructed QuantityUnitPair objects, which may be modified in place with some packed VectorQuantityUnitPairs objects.

required
number_of_element_repetitions int

Number of times each vector element is expected to be present in the subsequent Quantity lines. Typically used for 3D quantities, using the number of vertical layers. Defaults to 1.

1
Source code in hydrolib/core/io/bc/models.py
@staticmethod
def process_vectordefinition_or_check_quantityunitpairs(
    vectordefs: Optional[List[str]],
    quantityunitpairs: List[ScalarOrVectorQUP],
    number_of_element_repetitions: int = 1,
) -> None:
    """Processes the given vector definition header lines from a .bc file
    or, if absent, checks whether the existing VectorQuantityUnitPairs
    objects already have the correct vector length.

    Args:
        vectordefs (List[str]): List of vector definition values, e.g.,
            ["vectorname:comp1,comp2,..compN", ...]
        quantityunitpairs (List[ScalarOrVectorQUP]): list of already parsed
            and constructed QuantityUnitPair objects, which may be modified
            in place with some packed VectorQuantityUnitPairs objects.
        number_of_element_repetitions (int, optional): Number of times each
            vector element is expected to be present in the subsequent
            Quantity lines. Typically used for 3D quantities, using the
            number of vertical layers. Defaults to 1."""

    if vectordefs is not None and not any(
        map(lambda qup: isinstance(qup, VectorQuantityUnitPairs), quantityunitpairs)
    ):
        # Vector definition line still must be processed and VectorQUPs still created.
        VectorQUPValidation.validate_vectordefinition_and_update_quantityunitpairs(
            vectordefs, quantityunitpairs, number_of_element_repetitions
        )
    else:
        # VectorQUPs already present; directly validate their vector length.
        for qup in quantityunitpairs:
            if isinstance(qup, VectorQuantityUnitPairs):
                VectorQUPValidation.validate_vectorlength(
                    qup, number_of_element_repetitions
                )

validate_vectordefinition_and_update_quantityunitpairs(vectordefs: Optional[List[str]], quantityunitpairs: List[Union[hydrolib.core.io.bc.models.QuantityUnitPair, hydrolib.core.io.bc.models.VectorQuantityUnitPairs]], number_of_element_repetitions: int = 1) -> None staticmethod

Validates the given vector definition header lines from a .bc file for a ForcingBase subclass and updates the existing QuantityUnitPair list by packing the vector elements into a VectorQuantityUnitPairs object for each vector definition.

Parameters:

Name Type Description Default
vectordefs List[str]

List of vector definition values, e.g., ["vectorname:comp1,comp2,..compN", ...]

required
quantityunitpairs List[ScalarOrVectorQUP]

list of already parsed and constructed QuantityUnitPair objects, which will be modified in place with some packed VectorQuantityUnitPairs objects.

required
number_of_element_repetitions int

Number of times each vector element is expected to be present in the subsequent Quantity lines. Typically used for 3D quantities, using the number of vertical layers. Defaults to 1.

1
Source code in hydrolib/core/io/bc/models.py
@staticmethod
def validate_vectordefinition_and_update_quantityunitpairs(
    vectordefs: Optional[List[str]],
    quantityunitpairs: List[ScalarOrVectorQUP],
    number_of_element_repetitions: int = 1,
) -> None:
    """Validates the given vector definition header lines from a .bc file
    for a ForcingBase subclass and updates the existing QuantityUnitPair list
    by packing the vector elements into a VectorQuantityUnitPairs object
    for each vector definition.

    Args:
        vectordefs (List[str]): List of vector definition values, e.g.,
            ["vectorname:comp1,comp2,..compN", ...]
        quantityunitpairs (List[ScalarOrVectorQUP]): list of already parsed
            and constructed QuantityUnitPair objects, which will be modified
            in place with some packed VectorQuantityUnitPairs objects.
        number_of_element_repetitions (int, optional): Number of times each
            vector element is expected to be present in the subsequent
            Quantity lines. Typically used for 3D quantities, using the
            number of vertical layers. Defaults to 1."""

    if vectordefs is None:
        return

    vectordefs = to_list(vectordefs)

    qup_iter = iter(quantityunitpairs)

    # Start a new list, to only keep the scalar QUPs, and add newly
    # created VectorQUPs.
    quantityunitpairs_with_vectors = []

    # If one quantity is "time", it must be the first one.
    if quantityunitpairs[0].quantity == "time":
        quantityunitpairs_with_vectors.append(quantityunitpairs[0])
        _ = next(qup_iter)

    # For each vector definition line, greedily find the quantity unit pairs
    # that form the vector elements, and pack them into a single VectorQuantityUnitPairs oject.
    for vectordef in vectordefs:
        vectorname, componentdefs = vectordef.split(":")
        componentnames = re.split(r"[, \t]", componentdefs)
        n_components = len(componentnames)

        vqu_pair = VectorQuantityUnitPairs(
            vectorname=vectorname, elementname=componentnames, quantityunitpair=[]
        )

        n_rep = 0
        for qu_pair in qup_iter:
            if qu_pair.quantity in componentnames:
                # This vector element found, store it.
                vqu_pair.quantityunitpair.append(qu_pair)
                n_rep += 1
                if n_rep == n_components * number_of_element_repetitions:
                    break
            else:
                # This quantity was no vector element being searched for
                # so keep it as a regular (scalar) QuantityUnitPair.
                quantityunitpairs_with_vectors.append(qu_pair)

        if VectorQUPValidation.validate_vectorlength(
            vqu_pair, number_of_element_repetitions
        ):
            # This VectorQuantityUnitPairs is now complete; add it to result list.
            quantityunitpairs_with_vectors.append(vqu_pair)

    quantityunitpairs[:] = quantityunitpairs_with_vectors

validate_vectorlength(vqu_pair: VectorQuantityUnitPairs, number_of_element_repetitions: int = 1) -> bool staticmethod

Checks whether the number of QuantityUnitPairs in a vector quantity matches exactly with number of vector elements in the definition and, optionally, the number of vertical layers.

Parameters:

Name Type Description Default
vqu_pair VectorQuantityUnitPairs

the vector quantity object to be checked.

required
number_of_element_repetitions int

Number of times each vector element is expected to be present in the subsequent Quantity lines. Typically used for 3D quantities, using the number of vertical layers. Defaults to 1.

1

Returns:

Type Description
bool

True if vqu_pair is valid. False return value is hidden because an exception will be raised.

Exceptions:

Type Description
ValueError

If number of QuantityUnitPair objects in vqu_pair is not equal to number of element names * number_of_element_repetitions.

Source code in hydrolib/core/io/bc/models.py
@staticmethod
def validate_vectorlength(
    vqu_pair: VectorQuantityUnitPairs,
    number_of_element_repetitions: int = 1,
) -> bool:
    """Checks whether the number of QuantityUnitPairs in a vector quantity
    matches exactly with number of vector elements in the definition and,
    optionally, the number of vertical layers.

    Args:
        vqu_pair (VectorQuantityUnitPairs): the vector quantity object to be checked.
        number_of_element_repetitions (int, optional): Number of times each
            vector element is expected to be present in the subsequent
            Quantity lines. Typically used for 3D quantities, using the
            number of vertical layers. Defaults to 1.

    Returns:
        bool: True if vqu_pair is valid. False return value is hidden because
            an exception will be raised.

    Raises:
        ValueError: If number of QuantityUnitPair objects in vqu_pair is not equal
            to number of element names * number_of_element_repetitions."""

    if not (
        valid := len(vqu_pair.quantityunitpair)
        == len(vqu_pair.elementname) * number_of_element_repetitions
    ):
        raise ValueError(
            f"Incorrect number of quantity unit pairs were found; should match the elements in vectordefinition for {vqu_pair.vectorname}"
            + (
                f", and {number_of_element_repetitions} vertical layers"
                if number_of_element_repetitions > 1
                else ""
            )
            + "."
        )

    return valid

VectorQuantityUnitPairs (BaseModel) pydantic-model

A subset of .bc file header lines containing a vector quantity definition, followed by all component quantity names, their unit and optionally their vertical position indexes.

__str__(self) -> str special

Return str(self).

Source code in hydrolib/core/io/bc/models.py
def __str__(self) -> str:
    return VectorQuantityUnitPairs._to_vectordefinition_string(
        self.vectorname, self.elementname
    )

VerticalInterpolation (str, Enum)

Enum class containing the valid values for the vertical position type, which defines what the numeric values for vertical position specification mean.

block

str: Equal to the value at the directly lower specified vertical position.

linear

str: Linear interpolation between vertical positions.

log

str: Logarithmic interpolation between vertical positions (e.g. vertical velocity profiles).

VerticalPositionType (str, Enum)

Enum class containing the valid values for the vertical position type.

percentage_bed

str: Percentage with respect to the water depth from the bed upward.

z_bed

str: Absolute distance from the bed upward.

z_datum

str: z-coordinate with respect to the reference level of the model.

z_surf

str: Absolute distance from the free surface downward.

Back to top