Skip to content

abstract_cable

CableConductorProperties

Bases: BaseModel

This dataclass is responsible for storing physical cable conductor properties.

Relevant sizes, materials and other physical properties not addressed at a layer level will be stored in this dataclass.

Attributes:

Name Type Description
number_of_conductors CableConductorCount

A CableConductorCount object representing the number of conductors in the cable.

shape CableConductorShape

A CableConductorShape object representing the shape of the cable's conductors.

material CableConductorMaterial

A CableConductorMaterial object representing the material of the cable's conductors.

surface_type CableConductorSurfaceType

A CableConductorSurfaceType object representing the surface type of the cable's conductors.

CableConductorType

Bases: BaseModel

A backup dataclass for the original ConductorType class used for CableSpecParser.

TODO: CableSpecParser should be updated to use the CableConductorProperties class instead of this one.

WeightedScreenImpedance

Bases: BaseModel

Weighted screen impedance data for multi-cable circuit loss calculations.

CableLayerProperties

Bases: BaseModel

A dataclass aimed at supplying cable layered properties.

This dataclass holds the physical properties for a single cable layer.

Attributes:

Name Type Description
layer CableLayer

The type of cable layer this object represents.

inner_radius float

The inner radius of the cable layer (in meters).

outer_radius float

The outer radius of the cable layer (in meters).

rho float

The thermal resistivity value of the layer (in mK/W).

capacity float

The thermal capacity of the layer (in J/(m³K)).

electric_rho float

The electric resistivity value of the layer (in Ohm·m).

alpha float

The electrical resistivity temperature coefficient of the layer.

epsilon float

The relative permittivity value of the layer.

tan_delta float

The dissipation factor value of the layer.

CableLayerMetrics

Bases: BaseModel

The dataclass holding the remaining physical properties of a cable.

After the CableConductorProperties and CableLayerProperties dataclasses, this dataclass holds the remaining physical properties remaining for a cable.

Notes

It may be good idea to change the name and / or the contents of this class in the nearby future. As of now there is no proper identity for this class, outside of serving as a method of preventing a large number of AbstractCable class properties from having to be defined within that class itself.

Attributes:

Name Type Description
conductor_centers list[tuple[float, float]]

A list of (x,y) locations indicating the position of each conductor, relative to the cable's center.

conductor_cross_section float

A float value representing the conductor's cross-section in meters squared (m2).

conductor_virtual_cross_section float

A float value representing a virtual cross-section in meters squared (m2), which can be used to compute an IEC compatible conductor resistance.

conductor_equivalent_outer_diameter float

An optional float value representing the outer diameter of an equivalent solid conductor with the same central duct as the original situation (in mm). Used to represent the conductor situation as a single solid conductor in situations with multiple conductors.

conductor_distance float

An optional float, applicable for situations with three conductors, where this value represents distance between the conductor centers.

screen_cross_section float | None

A float representing the cable screen's cross-section size.

screen_loss_type CableScreenLossType | None

A CableScreenLossType object representing the type of screen loss the cable has. This value is used to determine the proper method for calculating the screen loss.

armour_cross_section float | None

A float representing the cross-section size of the cable's armour.

diameter_over_stranded_conductors float

A float representing the cable's diagonal spanning the conductors' outermost borders.

nominal_phase_voltage float

A float representing the cable's phase voltage.

sector_radius float

An optional float representing cable sector radius.

outer_radius float

A float representing the cable's outer radius.

core_to_sector_distance float

An optional float representing the distance from the cable's core to its sector.

original_insulation_thickness float

An optional float representing the original t1 value of the cable.

load_series ndarray

An optional np.ndarray representing the cable's load series.

pipe Pipe

An optional Pipe object representing the cable's pipe, if there is one.

CableConvectionParams

Bases: BaseModel

Convection parameters used to model heat transfer in air-installed cables.

AbstractCable

AbstractCable(
    conductor: CableConductorProperties,
    layer_properties: dict[
        CableLayer, CableLayerProperties
    ],
    layer_metrics: CableLayerMetrics,
    cable_type: CableType,
)

The Abstract base class for cables.

This class represents all physical qualities of a single cable, outside of those specific to FD cables. Abstract cables will be extended by the FDCable class.

Attributes:

Name Type Description
conductor CableConductorProperties

A CableConductorProperties object containing the cable's intended conductor properties.

layer_properties CableLayerProperties

A CableLayerProperties object containing the cable's intended layer properties.

layer_metrics CableLayerMetrics

A CableLayerMetrics object containing the cable's intended layer metrics values.

cable_type CableType

A CableType object containing the cable's intended type.

Parameters:

Name Type Description Default
conductor CableConductorProperties

Conductor properties of the cable.

required
layer_properties dict[CableLayer, CableLayerProperties]

Mapping of cable layers to their properties.

required
layer_metrics CableLayerMetrics

Geometric and calculated metrics for the cable layers.

required
cable_type CableType

The type of the cable.

required
Source code in cable_thermal_model/model/cables/abstract_cable.py
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
def __init__(
    self,
    conductor: CableConductorProperties,
    layer_properties: dict[CableLayer, CableLayerProperties],
    layer_metrics: CableLayerMetrics,
    cable_type: CableType,
):
    """Initialize an abstract cable with its conductor, layer, and metric properties.

    Args:
        conductor (CableConductorProperties): Conductor properties of the cable.
        layer_properties (dict[CableLayer, CableLayerProperties]): Mapping of cable layers to their properties.
        layer_metrics (CableLayerMetrics): Geometric and calculated metrics for the cable layers.
        cable_type (CableType): The type of the cable.

    """
    if not isinstance(conductor, CableConductorProperties):
        raise TypeError(
            f"Expected [conductor] to be of type [CableConductorProperties], but got [{type(conductor)}]"
        )
    self.conductor = conductor

    if not isinstance(layer_properties, dict):
        raise TypeError(f"Expected [layer_properties] to be of type dict, but got [{type(layer_properties)}]")
    self.layer_properties = layer_properties

    if not isinstance(layer_metrics, CableLayerMetrics):
        raise TypeError(
            f"Expected [layer_metrics] to be of type [CableLayerMetrics], but got [{type(layer_metrics)}]"
        )
    self.layer_metrics = layer_metrics

    if not isinstance(cable_type, CableType):
        raise TypeError(f"Expected [cable_type] to be of type [CableType], but got [{type(cable_type)}]")
    self.cable_type = cable_type

    if self.conductor.number_of_conductors == CableConductorCount.Three:
        distance = self.layer_metrics.conductor_distance

        if not distance:
            raise MissingAttributeException(
                "Trying to instantiate 3-core cable without specified conductor distance."
            )

        y_dif = distance * 3**0.5 / 2
        y_centerA = distance / 3**0.5
        y_centerBC = y_centerA - y_dif
        centerA = (0, y_centerA)
        centerB = (-distance / 2, y_centerBC)
        centerC = (distance / 2, y_centerBC)
        self.layer_metrics.conductor_centers = [centerA, centerB, centerC]

    self.weighted_screen_impedance: WeightedScreenImpedance | None = None

layers property

layers: list[CableLayer]

A shorthand method for retrieving the list of layers of the cable.

layer_count property

layer_count: int

A shorthand method for retrieving the number of layers of the cable.

non_soil_layer_count property

non_soil_layer_count: int

A shorthand method for retrieving the number of layers of the cable, excluding the soil layer.

omega property

omega: float

Angular frequency at 50 Hz in rad/s.

electric_rho_screen property

electric_rho_screen: float

Electrical resistivity of the screen layer in Ohm·m.

alpha_screen property

alpha_screen: float

Temperature coefficient of electrical resistivity for the screen layer.

c property

c: float

Distance between the conductors in a three-core cable.

d property

d: float

Average diameter of the earth screen layer.

s property

s: float

Centre-to-centre distance between conductors in metres.

Ft property

Ft: float

Armour loss factor (1 when no armour is present).

X property

X: float

Reactance factor for proximity effect calculations.

Xm property

Xm: float

Mutual reactance factor used in screen loss calculations.

get_ac_resistance_conductor

get_ac_resistance_conductor(Tc: float, s: float) -> float

Computes the AC resistance of the conductor based on its temperature and distance to other conductors.

Parameters:

Name Type Description Default
Tc float

The conductor temperature in degrees Celsius.

required
s float

The distance between the conductors in meters.

required

Returns:

Name Type Description
float float

The AC resistance of the conductor in Ohm/m.

Source code in cable_thermal_model/model/cables/abstract_cable.py
336
337
338
339
340
341
342
343
344
345
346
347
348
def get_ac_resistance_conductor(self, Tc: float, s: float) -> float:
    """Computes the AC resistance of the conductor based on its temperature and distance to other conductors.

    Args:
        Tc (float): The conductor temperature in degrees Celsius.
        s (float): The distance between the conductors in meters.

    Returns:
        float: The AC resistance of the conductor in Ohm/m.

    """
    Rdc = self.get_dc_resistance_conductor(Tc)
    return self._get_ac_resistance_conductor_from_dc_resistance(Rdc, s)

get_skin_effect_factor

get_skin_effect_factor(Rdc: float) -> float

Compute skin effect factor y_s from DC resistance.

Parameters:

Name Type Description Default
Rdc float

The DC resistance of the conductor in Ohm/m at the operating temperature.

required

Returns:

Name Type Description
float float

The skin effect factor y_s.

References
  • IEC 60287-1-1 - section 5.1.3
Source code in cable_thermal_model/model/cables/abstract_cable.py
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
def get_skin_effect_factor(self, Rdc: float) -> float:
    """Compute skin effect factor y_s from DC resistance.

    Args:
        Rdc (float): The DC resistance of the conductor in Ohm/m at the operating temperature.

    Returns:
        float: The skin effect factor y_s.

    References:
        - IEC 60287-1-1 - section 5.1.3

    """
    x_coefficient = self._calculate_x_coefficient(Rdc)
    k_s, _ = self._select_k_s_and_k_p()
    x_s = (x_coefficient * k_s) ** 0.5
    return type(self)._calculate_y_s_from_x_s(x_s=x_s)

get_proximity_effect_factor

get_proximity_effect_factor(Rdc: float, s: float) -> float

Compute proximity effect factor y_p from DC resistance.

Parameters:

Name Type Description Default
Rdc float

The DC resistance of the conductor in Ohm/m at the operating temperature.

required
s float

The distance between the conductors in meters.

required

Returns:

Name Type Description
float float

The proximity effect factor y_p.

References
  • IEC 60287-1-1 - section 5.1.5
Source code in cable_thermal_model/model/cables/abstract_cable.py
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
def get_proximity_effect_factor(self, Rdc: float, s: float) -> float:
    """Compute proximity effect factor y_p from DC resistance.

    Args:
        Rdc (float): The DC resistance of the conductor in Ohm/m at the operating temperature.
        s (float): The distance between the conductors in meters.

    Returns:
        float: The proximity effect factor y_p.

    References:
        - IEC 60287-1-1 - section 5.1.5

    """
    x_coefficient = self._calculate_x_coefficient(Rdc)
    _, k_p = self._select_k_s_and_k_p()

    conductor_diameter = 2 * self.layer_metrics.conductor_radius_original
    x_p = (x_coefficient * k_p) ** 0.5
    if x_p > self._X_P_THRESHOLD:
        logger.warning(
            f"The value for [x_p] is greater than [{self._X_P_THRESHOLD}]. Faults may occur when calculating [y_p]!"
        )

    if self.conductor.shape in [CableConductorShape.Round, CableConductorShape.Hollow]:
        return self._calculate_y_p_from_x_p(d=conductor_diameter, s=s, x_p=x_p, factor=1.0)

    if self.conductor.shape == CableConductorShape.Sector:
        return self._calculate_y_p_from_x_p(d=conductor_diameter, s=conductor_diameter + s, x_p=x_p, factor=2 / 3)

    raise ValueError(f"Conductor shape [{self.conductor.shape}] not recognized. Cannot calculate [y_p].")

get_dc_resistance_conductor

get_dc_resistance_conductor(Tc: float) -> float

Computes the DC resistance of the conductor at a given conductor temperature.

Parameters:

Name Type Description Default
Tc float

The conductor temperature in degrees Celsius.

required

Returns:

Name Type Description
float float

The DC resistance of the conductor in Ohm/m.

Source code in cable_thermal_model/model/cables/abstract_cable.py
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
def get_dc_resistance_conductor(self, Tc: float) -> float:
    """Computes the DC resistance of the conductor at a given conductor temperature.

    Args:
        Tc (float): The conductor temperature in degrees Celsius.

    Returns:
        float: The DC resistance of the conductor in Ohm/m.

    """
    return (
        self.layer_properties[CableLayer.Conductor].electric_rho
        / self.layer_metrics.conductor_virtual_cross_section
        * (1 + self.layer_properties[CableLayer.Conductor].alpha * (Tc - ELECTRIC_RESISTANCE_REFERENCE_TEMPERATURE))
    )

get_heat_generation_conductor_and_screen

get_heat_generation_conductor_and_screen(
    load: float,
    conductor_temperature: float,
    screen_temperature: float,
    temperature_dependent_electric_resistance: bool,
    ac_current: bool,
) -> tuple[float, float]

Calculates the heat generation in the conductor based on the load and resistance.

In W/m.

Parameters:

Name Type Description Default
ac_current bool

Whether to use AC resistance (skin/proximity effects) or only DC resistance.

required
load float

The load in Amperes.

required
conductor_temperature float

The temperature of the conductor in degrees Celsius.

required
screen_temperature float

The temperature of the screen in degrees Celsius.

required
temperature_dependent_electric_resistance bool

Whether to use temperature-dependent electric resistance.

required

Raises:

Type Description
ValueError

If AC resistance is requested but conductor distance is not set.

Returns:

Type Description
tuple[float, float]

tuple[float, float]: A tuple containing the heat generation in the conductor and the screen respectively in W/m.

Source code in cable_thermal_model/model/cables/abstract_cable.py
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
def get_heat_generation_conductor_and_screen(
    self,
    load: float,
    conductor_temperature: float,
    screen_temperature: float,
    temperature_dependent_electric_resistance: bool,
    ac_current: bool,
) -> tuple[float, float]:
    """Calculates the heat generation in the conductor based on the load and resistance.

    In W/m.

    Args:
        ac_current (bool): Whether to use AC resistance (skin/proximity effects) or only DC resistance.
        load (float): The load in Amperes.
        conductor_temperature (float): The temperature of the conductor in degrees Celsius.
        screen_temperature (float): The temperature of the screen in degrees Celsius.
        temperature_dependent_electric_resistance (bool): Whether to use temperature-dependent electric resistance.

    Raises:
        ValueError:
            If AC resistance is requested but conductor distance is not set.

    Returns:
        tuple[float, float]: A tuple containing the heat generation in the
            conductor and the screen respectively in W/m.

    """
    heat_generation_conductor = self.get_heat_generation_conductor(
        ac_current=ac_current,
        load=load,
        conductor_temperature=conductor_temperature,
        temperature_dependent_electric_resistance=temperature_dependent_electric_resistance,
    )

    heat_generation_screen = (
        self.get_heat_generation_screen(
            heat_generation_conductor=heat_generation_conductor,
            screen_temperature=screen_temperature,
            conductor_temperature=conductor_temperature,
            temperature_dependent_electric_resistance=temperature_dependent_electric_resistance,
        )
        if ac_current
        else 0.0
    )

    return heat_generation_conductor, heat_generation_screen

get_heat_generation_conductor

get_heat_generation_conductor(
    ac_current: bool,
    load: float,
    conductor_temperature: float,
    temperature_dependent_electric_resistance: bool,
) -> float

Calculates the heat generation in the conductor based on the load and resistance.

In W/m.

Parameters:

Name Type Description Default
ac_current bool

Whether to use AC resistance (skin/proximity effects) or only DC resistance.

required
load float

The load in Amperes.

required
conductor_temperature float

The temperature of the conductor in degrees Celsius.

required
temperature_dependent_electric_resistance bool

Whether to use temperature-dependent electric resistance.

required

Raises:

Type Description
ValueError

If AC resistance is requested but conductor distance is not set.

Returns:

Name Type Description
float float

The heat generation in the conductor in W/m.

Source code in cable_thermal_model/model/cables/abstract_cable.py
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
def get_heat_generation_conductor(
    self,
    ac_current: bool,
    load: float,
    conductor_temperature: float,
    temperature_dependent_electric_resistance: bool,
) -> float:
    """Calculates the heat generation in the conductor based on the load and resistance.

    In W/m.

    Args:
        ac_current (bool): Whether to use AC resistance (skin/proximity effects) or only DC resistance.
        load (float): The load in Amperes.
        conductor_temperature (float): The temperature of the conductor in degrees Celsius.
        temperature_dependent_electric_resistance (bool): Whether to use temperature-dependent electric resistance.

    Raises:
        ValueError:
            If AC resistance is requested but conductor distance is not set.

    Returns:
        float: The heat generation in the conductor in W/m.

    """
    resistance_conductor = self.get_dc_resistance_conductor(
        Tc=(
            conductor_temperature
            if temperature_dependent_electric_resistance
            else ELECTRIC_RESISTANCE_REFERENCE_TEMPERATURE
        )
    )
    if ac_current:
        distance_conductor = self.layer_metrics.conductor_distance
        if distance_conductor is None:
            raise ValueError(
                "Conductor distance has not been set, cannot compute AC resistance factor for conductor."
            )
        resistance_conductor = self._get_ac_resistance_conductor_from_dc_resistance(
            Rdc=resistance_conductor,
            s=distance_conductor,
        )

    return load**2 * resistance_conductor * self.conductor.number_of_conductors.value

get_heat_generation_screen

get_heat_generation_screen(
    heat_generation_conductor: float,
    screen_temperature: float,
    conductor_temperature: float,
    temperature_dependent_electric_resistance: bool,
) -> float

Calculates the heat generation in the screen based on the conductor heat generation and screen loss factor.

In W/m.

Parameters:

Name Type Description Default
heat_generation_conductor float

The heat generation in the conductor in W/m.

required
screen_temperature float

The temperature of the screen in degrees Celsius.

required
conductor_temperature float

The temperature of the conductor in degrees Celsius.

required
temperature_dependent_electric_resistance bool

Whether to use temperature-dependent electric resistance.

required

Returns:

Name Type Description
float float

The heat generation in the screen in W/m.

Source code in cable_thermal_model/model/cables/abstract_cable.py
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
def get_heat_generation_screen(
    self,
    heat_generation_conductor: float,
    screen_temperature: float,
    conductor_temperature: float,
    temperature_dependent_electric_resistance: bool,
) -> float:
    """Calculates the heat generation in the screen based on the conductor heat generation and screen loss factor.

    In W/m.

    Args:
        heat_generation_conductor (float): The heat generation in the conductor in W/m.
        screen_temperature (float): The temperature of the screen in degrees Celsius.
        conductor_temperature (float): The temperature of the conductor in degrees Celsius.
        temperature_dependent_electric_resistance (bool): Whether to use temperature-dependent electric resistance.

    Returns:
        float: The heat generation in the screen in W/m.

    """
    return heat_generation_conductor * self.get_cable_screen_loss_factor(
        Ts=screen_temperature
        if temperature_dependent_electric_resistance
        else ELECTRIC_RESISTANCE_REFERENCE_TEMPERATURE,
        Tc=conductor_temperature
        if temperature_dependent_electric_resistance
        else ELECTRIC_RESISTANCE_REFERENCE_TEMPERATURE,
    )

get_cable_screen_loss_factor

get_cable_screen_loss_factor(Ts: float, Tc: float) -> float

Returns the screen loss factor for the cable.

THe screen loss factor describes the ratio of heat generated in the screen relative to the conductor.

The screen loss factor describes what proportion of the heat generation in the conductor will be generated in the screen layer. For example, if the factor is 0, no heat will be generated in the screen layer by inductance. If the factor is 0.5 and 100 W/m is generated in the conductor, then 50 W/m will be generated in the screen.

Parameters:

Name Type Description Default
Ts float

The screen temperature in degrees Celsius.

required
Tc float

The conductor temperature in degrees Celsius.

required

Returns:

Name Type Description
float float

Screen loss factor (ratio of loss in the screen relative to the conductor).

Source code in cable_thermal_model/model/cables/abstract_cable.py
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
def get_cable_screen_loss_factor(self, Ts: float, Tc: float) -> float:
    """Returns the screen loss factor for the cable.

    THe screen loss factor describes the ratio
    of heat generated in the screen relative to the conductor.

    The screen loss factor describes what proportion of the heat
    generation in the conductor will be generated in the screen layer.
    For example, if the factor is 0, no heat will be generated in the
    screen layer by inductance. If the factor is 0.5 and 100 W/m is
    generated in the conductor, then 50 W/m will be generated in the
    screen.

    Args:
        Ts (float): The screen temperature in degrees Celsius.
        Tc (float): The conductor temperature in degrees Celsius.

    Returns:
        float: Screen loss factor (ratio of loss in the screen relative to the conductor).

    """
    if self.layer_metrics.screen_loss_type is None:
        raise ValueError("Screen loss method is not set.")
    screen_loss_function = getattr(self, self.layer_metrics.screen_loss_type.value)
    return screen_loss_function(Tc, Ts)

get_dielectric_loss_for_cable

get_dielectric_loss_for_cable() -> float

Computes dielectric losses per conductor using permittivity and tan(delta) of the insulation material.

This function checks first whether the dielectric loss can be neglected based on the cable configuration. If so, it returns 0. Otherwise, it computes the dielectric loss using the compute_dielectric_loss_per_conductor function.

Returns:

Name Type Description
float float

Dielectric losses per conductor in W/m.

References
  • NEN-IEC 60287-1-1 (2023) - [section 5.2]
Source code in cable_thermal_model/model/cables/abstract_cable.py
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
def get_dielectric_loss_for_cable(self) -> float:
    """Computes dielectric losses per conductor using permittivity and tan(delta) of the insulation material.

    This function checks first whether the dielectric loss can be neglected based on the cable configuration.
    If so, it returns 0. Otherwise, it computes the dielectric loss using the compute_dielectric_loss_per_conductor
    function.

    Returns:
        float: Dielectric losses per conductor in W/m.

    References:
        - NEN-IEC 60287-1-1 (2023) - [section 5.2]

    """
    if self.conductor.number_of_conductors == CableConductorCount.Three:
        # According to [section 5.2] in NEN-IEC 60287-1-1 (2023), the dielectric loss can be neglected for
        # unscreened multicore cables. Screened multicore cables are not supported by the model (yet).
        # Therefore, always return 0 when the number of conductors is 3. Also return 0 when the
        # neglect_dielectric_loss flag is set in the layer metrics.
        return 0.0

    dielectric_loss_per_conductor = self._compute_dielectric_loss_per_conductor()
    # The dielectric losses are multiplied by the amount of conductors in the cable.
    return dielectric_loss_per_conductor * self.conductor.number_of_conductors.value