Source code for pyvibracore.input.impact_force_properties

from __future__ import annotations

from copy import deepcopy
from dataclasses import dataclass
from typing import Dict, List, Literal

import numpy as np
from pygef.cpt import CPTData

from .constants import SHEETPILE_REFERENCE_PROFILES

CustomInterval = 0.5
UnitWeightWater = 9.81


@dataclass(frozen=True)
class VibrationSource:
    """

    Attributes
    -----------
    areaShaftSpecific: float
        Specific shaft area of the single sheet pile (1 sheet) per unit length [m^2/m].
    areaTipSpecific: float
        Specific tip area of the single sheet pile (1 sheet) [m^2].
    amountOfSheetPiles: int = 1
        Number of sheets
            - push = 1
            - vibrate = 2
    slotResistanceSpecific: float
        Specific sheet pile slot resistance [kN/m] based on CUR 166 6th edition.
        for new sheet piles:
            - push = 5
            - vibrate = 10
    sheetPileName: str = "User defined"
        Sheet pile name
    """

    areaShaftSpecific: float
    areaTipSpecific: float
    slotResistanceSpecific: float
    amountOfSheetPiles: int = 1
    sheetPileName: str = "User defined"

    @classmethod
    def from_sheet_pile_name(
        cls,
        name: str,
        amount_of_sheet_piles: int = 1,
        slot_resistance_specific: float = 10.0,
    ) -> "VibrationSource":
        """

        Parameters
        ----------
        name: str
            Sheet pile name
        amount_of_sheet_piles: int = 1
            Number of sheets
        slot_resistance_specific: float = 10
            Specific sheet pile slot resistance [kN/m] based on CUR 166 6th edition.
        Returns
        -------
        VibrationSource
        """
        props = next(
            (item for item in SHEETPILE_REFERENCE_PROFILES if item["label"] == name),
            None,
        )
        if props is None:
            raise ValueError(
                f"{name} is not a valid sheet pile name. "
                "Please specify the areaShaftSpecific and areaTipSpecific in the "
                "main class or update the SHEETPILE_REFERENCE_PROFILES table."
            )

        return cls(
            areaShaftSpecific=props.get("area_shaft_specific"),  # type: ignore
            areaTipSpecific=props.get("area_tip_specific"),  # type: ignore
            amountOfSheetPiles=amount_of_sheet_piles,
            slotResistanceSpecific=slot_resistance_specific,
            sheetPileName=name,
        )


[docs]def create_multi_cpt_impact_force_payload( cptdata_objects: List[CPTData], classify_tables: Dict[str, dict], vibration_source: VibrationSource, friction_strategy: Literal["CPTFrictionStrategy", "SlipFrictionStrategy"], drive_strategy: Literal["vibrate", "push"], installation_level_offset: float, groundwater_level_offset: None | float = None, zeta: float = 0.6, ) -> dict: """ Creates a dictionary with the payload content for the VibraCore endpoint "/impact-force/calculation/multi" This dictionary can be passed directly to `nuclei.client.call_endpoint()`. Parameters ---------- cptdata_objects: A list of pygef.CPTData objects classify_tables: A dictionary, mapping `CPTData.alias` values to dictionary with the resulting response of a call to CPTCore `classify/*` information, containing the following keys: - geotechnicalSoilName: Sequence[str] Geotechnical Soil Name related to the ISO - lowerBoundary: Sequence[float] Lower boundary of the layer [m] - upperBoundary: Sequence[float] Upper boundary of the layer [m] - color: Sequence[str] Hex color code - mainComponent: Sequence[Literal["rocks", "gravel", "sand", "silt", "clay", "peat"]] Main soil component - cohesion: Sequence[float] Cohesion of the layer [kPa] - gamma_sat: Sequence[float] Saturated unit weight [kN/m^3] - gamma_unsat: Sequence[float] Unsaturated unit weight [kN/m^3] - phi: Sequence[float] Phi [degrees] - undrainedShearStrength: Sequence[float] Undrained shear strength [kPa] vibration_source: VibrationSource Vibration source object friction_strategy: Literal["CPTFrictionStrategy", "SlipFrictionStrategy"] Defines the strategy on how to compute the sleeve friction: - CPTFrictionStrategy The CPT Friction Strategy takes the sleeve friction provided by the cpt. Note that this method is only valid when the sleeve friction is provided within the cpt object. - SlipFrictionStrategy The Slip Friction Strategy calculated the sleeve friction based on the gamma, gamma saturation, phi and the undrained shear strength. To use this methode the values must be provided within the cpt object. drive_strategy: Literal["vibrate", "push"] Defines the strategy on how to compute the impact force: - vibrate The vibration strategy calculates the impact force based on a vibration installation method. - push The push strategy calculates the impact force based on a push installation method. installation_level_offset: float Installation level of the sheet pile [m w.r.t REF] groundwater_level_offset: float, optional Groundwater level for all cpts. if None groundwater level of cpt is used. if no groundwater level is set in the cpt we will take one meter below surface level [m w.r.t REF] zeta: float = 0.6 verknedingsfactor [-], used in the push drive strategy based on CUR 166 6th edition. Returns ------- payload: dict """ payload = { "soilProperties": [ { "cptObject": { "coneResistance": cpt.data.get_column("coneResistance") .clip(lower_bound=0, upper_bound=1e10) .to_list(), "depthOffset": cpt.data.get_column("depthOffset").to_list(), "localFriction": cpt.data.get_column("localFriction") .clip(lower_bound=0, upper_bound=1e10) .to_list(), "name": cpt.alias, "verticalPositionOffset": cpt.delivered_vertical_position_offset, "x": cpt.delivered_location.x, "y": cpt.delivered_location.y, }, "customInterval": CustomInterval, "groundwaterLevelOffset": groundwater_level_offset or cpt.groundwater_level_offset or cpt.delivered_vertical_position_offset - 1, "layerTable": { "gamma_sat": classify_tables[cpt.alias].get("gamma_sat"), "gamma_unsat": classify_tables[cpt.alias].get("gamma_unsat"), "phi": classify_tables[cpt.alias].get("phi"), "soilcode": classify_tables[cpt.alias].get("mainComponent"), "undrainedShearStrength": classify_tables[cpt.alias].get( "undrainedShearStrength" ), "upperBoundary": ( cpt.delivered_vertical_position_offset - np.array(classify_tables[cpt.alias].get("upperBoundary")) ).tolist(), }, "unitWeightWater": UnitWeightWater, } for cpt in cptdata_objects ], "vibrationSource": { "areaShaftSpecific": vibration_source.areaShaftSpecific, "areaTipSpecific": vibration_source.areaTipSpecific, "numSheets": vibration_source.amountOfSheetPiles, "sheetPileName": vibration_source.sheetPileName, "slotResistanceSpecific": vibration_source.slotResistanceSpecific, }, "frictionStrategy": friction_strategy, "impactForceCalculation": { "driveStrategy": drive_strategy, "installationLevel": installation_level_offset, "zeta": zeta, }, } return payload
[docs]def create_multi_cpt_impact_force_report_payload( multi_cpt_payload: dict, project_name: str, project_id: str, author: str, ) -> dict: """ Creates a dictionary with the payload content for the VibraCore endpoint "/impact-force/report" This dictionary can be passed directly to `nuclei.client.call_endpoint()`. Parameters ---------- multi_cpt_payload: The result of a call to `create_multi_cpt_impact_force_payload()` project_name: The name of the project. project_id: The identifier (code) of the project. author: The author of the report. Returns ------- payload: dict """ payload = deepcopy(multi_cpt_payload) payload.update( dict( reportProperties=dict( author=author, projectNumber=project_id, projectName=project_name, ), ) ) return payload
[docs]def create_single_cpt_impact_force_payload(multi_cpt_payload: dict, name: str) -> dict: """ Creates a dictionary with the payload content for the VibraCore endpoint "/impact-force/calculation/single" This dictionary can be passed directly to `nuclei.client.call_endpoint()`. Parameters ---------- multi_cpt_payload: dict The result of a call to `create_multi_cpt_impact_force_payload()` name: str CPT name Returns ------- payload: dict """ payload = deepcopy(multi_cpt_payload) props = next( ( item for item in payload["soilProperties"] if item["cptObject"]["name"] == name ), None, ) if props is None: raise ValueError(f"{name} is not a valid CPT name.") payload.update(dict(soilProperties=props)) return payload