Skip to content

model_soil

ModelSoil

ModelSoil(
    static_env: StaticEnvSoil,
    scenario: DataFrame[ScenarioSchemaSoil],
)

Bases: Model[ModelSoilRunOptions, StateSoil, ScenarioSchemaSoil]

ModelSoil is used to compute temperature of underground power cables using the finite differences methodology.

A 1D approach is taken to modelling the environment and the cables, pipes and soil within it. The finite differences computations are fast and efficient.

In most cases the model is used by instantiating it using a StaticEnvSoil and a valid scenario and calling the run() method. >> model = ModelSoil(environment, scenario) >> result = model.run()

N.B. the column names of 'scenario' should be as follows 'load_circuit_1' contains the load (in A) of the 'circuit_1' object of static_env and column 'ambient_temperature' contains the ambient temperature (in degrees Celsius).

Parameters:

Name Type Description Default
static_env StaticEnvSoil

A StaticEnvSoil instance containing the soil thermal parameters and information of cables, lying configuration

required
scenario DataFrame[ScenarioSchemaSoil]

A pandera DataFrame[ScenarioSchemaSoil] containing the dynamic data i.e. loads of the cable circuits and the soil temperature

required

Attributes:

Name Type Description
mirror_cables_with_soil

A dict containing the mirror cables with soil for each cable in the environment

logarithmic_soil_gridpoint_density

The density of grid points in the soil layers, this is used to compute the number of grid points in the soil layers based on their thickness. The default value is 20 grid points per factor 2 increase in soil layer thickness. For a cable with radius of 3.1 cm and a soil layer radius 1 m, this would result in 100 grid points in the soil layer.

minimal_soil_radius

The minimal soil radius around a cable. For deeply buried cables, the soil radius is set to 2.5 times the cable depth, this parameter sets a lower bound to prevent very small soil layers for shallow cables.

Source code in cable_thermal_model/model/model_soil.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def __init__(self, static_env: StaticEnvSoil, scenario: DataFrame[ScenarioSchemaSoil]):
    """To initialize a ModelSoil instance two inputs are required: a static environment and a scenario dataframe.

    N.B. the column names of 'scenario' should be as follows 'load_circuit_1' contains the load (in A) of the
    'circuit_1' object of static_env and column 'ambient_temperature' contains the ambient temperature (in degrees
    Celsius).

    Args:
        static_env: A StaticEnvSoil instance containing the soil thermal parameters and information of cables,
                    lying configuration
        scenario:   A pandera DataFrame[ScenarioSchemaSoil] containing the dynamic data i.e. loads of the
                    cable circuits and the soil temperature

    Attributes:
        mirror_cables_with_soil:            A dict containing the mirror cables with soil for each cable in the
                                            environment
        logarithmic_soil_gridpoint_density: The density of grid points in the soil layers, this is used to compute
                                            the number of grid points in the soil layers based on their thickness.
                                            The default value is 20 grid points per factor 2 increase in soil layer
                                            thickness. For a cable with radius of 3.1 cm and a soil layer radius
                                            1 m,
                                            this would result in 100 grid points in the soil layer.
        minimal_soil_radius:                The minimal soil radius around a cable. For deeply buried cables, the
                                            soil radius is set to 2.5 times the cable depth, this parameter sets
                                            a lower bound to prevent very small soil layers for shallow cables.

    """
    if not isinstance(static_env, StaticEnvSoil):
        raise ValueError(
            f"Can not use model {self.__class__.__name__} if static "
            "environment is not an environment in soil. Please use "
            "ModelAir instead."
        )

    # Set up cables
    self.mirror_cables_with_soil: dict[CableKey, PosCable] = {}
    self.logarithmic_soil_gridpoint_density: float = 20
    self.minimal_soil_radius: float = 5.0

    super().__init__(static_env=static_env, scenario=scenario)

get_temp

get_temp(
    x: float,
    y: float,
    time_sec: float,
    solutions: dict[CableKey, ndarray],
) -> float

This method computes the temperature at a given point and time in the environment.

Parameters:

Name Type Description Default
x float

x-coordinate of point

required
y float

y-coordinate of point

required
time_sec float

time in seconds at which to evaluate the temperature

required
solutions dict[CableKey, ndarray]

overwrites time_sec and uses this dictionary of solutions for the cables to compute the temperature inside the environment.

required

Returns:

Name Type Description
float float

Temperature in degrees Celsius.

Source code in cable_thermal_model/model/model_soil.py
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
def get_temp(self, x: float, y: float, time_sec: float, solutions: dict[CableKey, np.ndarray]) -> float:
    """This method computes the temperature at a given point and time in the environment.

    Args:
        x (float): x-coordinate of point
        y (float): y-coordinate of point
        time_sec (float): time in seconds at which to evaluate the temperature
        solutions (dict[CableKey, np.ndarray]): overwrites time_sec and uses this dictionary of
            solutions for the cables to compute the temperature inside the environment.

    Returns:
        float: Temperature in degrees Celsius.

    """
    time_grid = (self.scenario.index - self.scenario.index[0]).total_seconds()
    time_idx = np.nonzero(time_grid >= time_sec)[0][0]
    temp = self.scenario.ambient_temperature[time_idx]
    for key, cable in self.cables.items():
        dist = np.sqrt((x - cable.x) ** 2 + (y - cable.y) ** 2)
        temp += self._compute_temp_contribution(cable, dist, solutions[key], is_mirror_cable=False)

    for key, mirror_cable in self.mirror_cables_with_soil.items():
        dist = np.sqrt((x - mirror_cable.x) ** 2 + (y - mirror_cable.y) ** 2)
        temp += self._compute_temp_contribution(mirror_cable, dist, solutions[key], is_mirror_cable=True)

    return temp