paint-brush
So erstellen Sie mit Python und Viktor eine Web-App zum Entwerfen von Stahlgrundplattenvon@kamalsamaila
526 Lesungen
526 Lesungen

So erstellen Sie mit Python und Viktor eine Web-App zum Entwerfen von Stahlgrundplatten

von Kamal samaila18m2024/05/06
Read on Terminal Reader

Zu lang; Lesen

Dieser Artikel führt Sie durch die Erstellung einer Python-basierten Anwendung zum Entwerfen von Stahlgrundplatten, die für die sichere Übertragung von Stützenlasten auf Fundamente unerlässlich sind. Er behandelt die Berechnung von Grundplattenfläche, -dicke, Betontragfähigkeit und zusätzlicher Breite mithilfe der T-Stummel-Methode. Der Python-Code wird dann mithilfe des Viktor SDK in eine Web-App umgewandelt, sodass Ingenieure Parameter eingeben und 3D-Modelle der Struktur visualisieren können. Dieses effiziente Tool verbessert die Genauigkeit von Grundplattenentwürfen und erleichtert Vor-Ort-Prüfungen über Mobilgeräte, wodurch der Bauablauf optimiert wird.
featured image - So erstellen Sie mit Python und Viktor eine Web-App zum Entwerfen von Stahlgrundplatten
Kamal samaila HackerNoon profile picture

Einführung

Um die Konstruktionskräfte sicher auf das Fundament zu übertragen, werden Stahlgrundplatten unter Stahlstützen platziert.


Wenn Stahlstützen mit kleinem Querschnitt schwere Lasten tragen, kann die direkte Belastung des Fundaments zu Durchstanzversagen führen. Daher ist es wichtig, eine Grundplatte unter der Stütze zu verwenden, um die Last auf eine größere Fläche zu verteilen.


Dieser Artikel bietet eine Anleitung zum Erstellen einer Anwendung zum Entwurf von Grundplatten mit Python unter Nutzung der im CSV-Format gespeicherten geometrischen Eigenschaften von Stahl.


Mithilfe der Anwendung können Ingenieure problemlos die erforderliche Fläche, Dicke, Betontragfähigkeit und zusätzliche Breite der Grundplatte ermitteln.


Darüber hinaus können wir durch die Nutzung des Viktor SDK unsere Python-Implementierung nahtlos in eine Webanwendung umwandeln.


Dieses SDK bietet die Möglichkeit, unsere Struktur in einer 3D-Ansicht zu visualisieren. Lassen Sie uns direkt eintauchen und aktiv werden!

Grundprinzip für die Gestaltung der Grundplatte

Bei der Grundplattenkonstruktion wird für Axialkräfte die äquivalente T-Stummel-Methode verwendet, bei der für T-Stummel unter Druck eine „effektive Fläche“ berechnet wird und für T-Stummel unter Zug die Biegung der Grundplatte beurteilt wird. Horizontale große und/oder kleine Scherkräfte sind zulässig, aber keine Momente, d. h. eine stiftgebundene Grundplattenkonstruktion.

Als Erstes haben wir die Tragfähigkeit des Stützbetons berechnet, fjd.

Die Bemessungstragfähigkeit fjd zwischen der Unterseite der Grundplatte und dem Bettungsmaterial im Vergussraum ergibt sich aus:


fjd = βj * α * fcd

Wo


βj = Materialkoeffizient der Fundamentfuge = (2/3)


α = ein Koeffizient, der die Verteilung der konzentrierten Kraft innerhalb des Fundaments berücksichtigt


fcd = Bemessungswert der Betondruckfestigkeit = αcc * fck / ɣc


αcc = Koeffizient für Langzeiteffekte


fck = charakteristische Zylinderfestigkeit von Beton


ɣc = Teilsicherheitsbeiwert für Beton

Der zweite Schritt besteht darin, die erforderliche Grundplattenfläche zu berechnen. Diese ergibt sich aus der folgenden Formel:

Areq = Ned / fjd

Wobei Ned die Bruchlast der Stahlstütze ist.

Der dritte Schritt besteht darin, c zu berechnen, den Kragbalken, der über die effektive Fläche hinausragt:

C wird mit der folgenden Formel berechnet:

Aeff = 4 *( c**2) + Pcol * c + Acol


Daher lösen Sie nach c.


Und schließlich berechnen wir die Dicke der Grundplatte, tp:

tp = c * (3 * fjd * Ym0 / _Seite_fy)**0,50

Python-Implementierung des Baseplate-Design-Workflows

 # Partial factor of resistance of cross-sections whatever the class is as per EN 1993-1-1. Ym0 = 1.0 # Compute foundation bearing strength which is typically concrete #βj is the foundation joint material coefficient, typically taken as 0.67 as per clause 6.2.5(7) in EN 1993-1-8. beta_j=0.67 #α is a coefficient of diffusion of the vertical load being applied to the foundation. Conservatively this can be taken as 1.5 alpha= 1.5 # αcc is the coefficient that allows for long-term effects on the compressive strength of concrete vs applied actions. Taken as 0.85 in the UK National Annex -> on page # Define alpha_cc # Define gamma_c # define fck # γc is the partial factor of safety of concrete. Taken as 1.5 in the UK National Annex -> on page fjd = beta_j*alpha* (alpha_cc*fck )/gamma_c # Compute the area of the baseplate required Areq = (Ned *1000)/ fjd #Ned is the Ultimate load def calculate_c(Pcol, Acol, Areq): # """ # This function calculates the value of c for the given equation: # Areq = 4 * c^2 + P_col * c + A_col # Args: # Perimeter_of_section: Perimeter of the column section (mm) # Area_of_section: Area of the column section (mm²) # Areq: Required area of the baseplate (mm²) # Returns: # The value of c (mm) # """ a = 4 b = Pcol c = Acol-Areq # Assuming Areq is already calculated discriminant = b**2 - 4 * a * c c1 = (-b + (discriminant)**0.5) / (2 * a) c2 = (-b - (discriminant)**0.5) / (2 * a) return max(c1, c2) c = calculate_c(Pcol,Acol,Areq) # Compute the thickness of the baseplate (tp) tp = c * (3 * fjd* Ym0 / _page_fy)**0.50

Schließlich wird der Python-Code in eine Webanwendung für die Grundplattenkonstruktion umgewandelt

Eingang

Meine endgültige Anwendung benötigt Eingabefunktionen, mit denen der Benutzer die folgenden Parameter angeben kann:

Dies wird mithilfe der Parametrisierungsklasse aus dem Viktor SDK erreicht.

 class Parametrization(ViktorParametrization): input = Tab("Input") input.profile_type = OptionField( "Profile type", options=["IPE", "HEA", "HEB"], default="IPE", variant="radio-inline", flex=80, ) input.nl1 = LineBreak() input.profile = AutocompleteField( "Profile", options=get_profile_types, default="IPE240", description="The source of profile properties can be found [here](https://eurocodeapplied.com/design/en1993/ipe-hea-heb-hem-design-properties)", ) # input.steel_class = OptionField( # "Steel class", options=["S235", "S275", "S355"], default="S235" # ) input.fck = NumberField('Fck', default=25, suffix="MPa") input.Design_load = NumberField('Design_load', default=1000, suffix="KN") input.acc = NumberField('Concrete coeff(acc)', default=0.85) input.yc = NumberField('Partial factor of safety for concrete', default=1.5) input.steel_class = NumberField('steel_class', default=255, suffix="MPa")


Ausgabe

Nach der Berechnung wurde die Datenansichtsmethode aus dem Viktor SDK verwendet, um dem Benutzer das Berechnungsergebnis anzuzeigen.

 @DataView("Output", duration_guess=1) def Compute_output(self, params: Munch, **kwargs): Ym0, beta_j, alpha, fjd, Areq, c, tp = self.calculate_plate_geom(params) data = DataGroup( DataItem("ultimate load ", params.input.Design_load, suffix="KN"), DataItem("beta_j", 0.67), DataItem("alpha", 1.5), DataItem("Bearing capacity of concrete support(fjd) ", round(fjd), suffix="MPa"), DataItem("Areq ", round(Areq), suffix="mm2"), DataItem(" c", round(c), suffix="mm"), DataItem("Thickness of plate", round(tp), suffix="mm"), ) return DataResult(data)

Wo:

Tragfähigkeit von Beton (Fjd)

Erforderliche Stahlfläche (Areq)

Zusätzlicher Überstand der Grundplatte (c)

Dicke der Grundplatte

Abschließend wird ein 3D-Modell der Stahlstütze, der Grundplatte und des tragenden Betonfundaments erstellt.

Innerhalb der Controllerklasse wurde eine get_3dview-Methode definiert, die mit @GeometryView dekoriert ist.


Die Methode get_3dview definiert die Logik zum Erstellen des 3D-Modells und gibt schließlich das GeometryResult-Objekt zurück, das die erstellte Stahlstütze, Grundplatte und Betonstütze enthält.


Die Logik ist im folgenden Code enthalten:

 @GeometryView("3D baseplate View", duration_guess=1) def get_3dView(self, params: Munch, **kwargs): """Create geometry for column, base-plate and add a concrete slab underneath""" Ym0, beta_j, alpha, fjd, Areq, c, tp = self.calculate_plate_geom(params) concrete_thickness = 15 * tp steel = Material(color=Color(95, 158, 240), metalness=1) concrete = Material(metalness=0, roughness=1, opacity=0.6) h = self.get_profile_property(params.input.profile_type, params.input.profile, "Depth") b = self.get_profile_property(params.input.profile_type, params.input.profile, "Width") tw = self.get_profile_property(params.input.profile_type, params.input.profile, "Web thickness") tf = self.get_profile_property(params.input.profile_type, params.input.profile, "Flange thickness") r = self.get_profile_property(params.input.profile_type, params.input.profile, "Root radius") beam_profile = self.get_beam_profile(h, b, tw, tf, r) beam = Extrusion(beam_profile, Line(Point(0, 0, tp), Point(0, 0, 3 * h)), material=steel) base_plate = SquareBeam(sqrt(Areq), sqrt(Areq), tp, material=steel) # TODO: This area doesn't seem sufficient for large column sizes base_plate.translate((0, 0, tp / 2)) concrete_plate = SquareBeam(6 * h, 6 * h, concrete_thickness, material=concrete) concrete_plate.translate((0, 0, -concrete_thickness / 2)) return GeometryResult([beam, base_plate, concrete_plate]) 


Den vollständigen Code finden Sie unten:

 from math import sqrt # import plotly.express as px from pathlib import Path from typing import List import numpy as np import pandas as pd from munch import Munch from viktor import ViktorController, Color from viktor.geometry import Point, Extrusion, Line, Material, SquareBeam from viktor.parametrization import ( ViktorParametrization, OptionField, Text, Tab, AutocompleteField, LineBreak, NumberField ) # from viktor.external.spreadsheet import SpreadsheetCalculation, SpreadsheetCalculationInput from viktor.views import DataGroup, DataItem, DataResult, DataView, GeometryView, GeometryResult def get_profile_types(params: Munch, **kwargs): try: file_path = ( Path(__file__).parent / "profiles" / f"steel-profiles-{params.input.profile_type}.csv" ) df = pd.read_csv(file_path, header=[2], skiprows=[3, 4, 5]) return df["Profile"].values.tolist() except FileNotFoundError: return ["IPE80", "IPE100", "HEA100", "HEA120", "HEB100", "HEB120"] def calculate_c(Pcol, Acol, Areq): # """ # This function calculates the value of c for the given equation: # Areq = 4 * c^2 + P_col * c + A_col # Args: # Perimeter_of_section: Perimeter of the column section (mm) # Area_of_section: Area of the column section (mm²) # Areq: Required area of the baseplate (mm²) # Returns: # The value of c (mm) # """ a = 4 b = Pcol c = Acol - Areq # Assuming Areq is already calculated discriminant = b ** 2 - 4 * a * c c1 = (-b + (discriminant) ** 0.5) / (2 * a) c2 = (-b - (discriminant) ** 0.5) / (2 * a) return max(c1, c2) class Parametrization(ViktorParametrization): info = Tab("Info") info.text_01 = Text( """## Welcome to baseplate design app! """ ) input = Tab("Input") input.profile_type = OptionField( "Profile type", options=["IPE", "HEA", "HEB"], default="IPE", variant="radio-inline", flex=80, ) input.nl1 = LineBreak() input.profile = AutocompleteField( "Profile", options=get_profile_types, default="IPE240", description="The source of profile properties can be found [here](https://eurocodeapplied.com/design/en1993/ipe-hea-heb-hem-design-properties)", ) # input.steel_class = OptionField( # "Steel class", options=["S235", "S275", "S355"], default="S235" # ) input.fck = NumberField('Fck', default=25, suffix="MPa") input.Design_load = NumberField('Design_load', default=1000, suffix="KN") input.acc = NumberField('Concrete coeff(acc)', default=0.85) input.yc = NumberField('Partial factor of safety for concrete', default=1.5) input.steel_class = NumberField('steel_class', default=255, suffix="MPa") class Controller(ViktorController): label = 'My Entity Type' parametrization = Parametrization @DataView("profile geometrical Properties", duration_guess=1) def display_geometrical_properties(self, params: Munch, **kwargs): """Initiates the process of rendering an image of the bending moments of the structure, as well as a view of a few key values related to the bending moments.""" # results = self.calculate_allowable_bending_moment( # params.input.profile_type, params.input.profile # ) results = self.get_geometrical_properties( params.input.profile_type, params.input.profile ) data = DataGroup( DataItem("Depth", results["Depth"], suffix="mm"), DataItem("Width", results["Width"], suffix="mm"), DataItem("Thickness_of_web", results["Thickeness_of_web"], suffix="mm"), DataItem("Thickness_of_flange", results["Thickeness_of_flange"], suffix="mm"), DataItem("Area_col", results["Area_col"], suffix="mm2"), DataItem("Perimeter_col", results["Perimeter_col"], suffix="mm"), ) return DataResult(data) def calculate_plate_geom(self, params, **kwargs): results = self.get_geometrical_properties( params.input.profile_type, params.input.profile ) # Partial factor of resistance of cross-sections whatever the class is as per EN 1993-1-1. Ym0 = 1.0 # Compute ultimate load (Ned) -> on page # Compute foundation bearing strength which is typically concrete # βj is the foundation joint material coefficient, typically taken as 0.67 as per clause 6.2.5(7) in EN 1993-1-8. beta_j = 0.67 # α is a coefficient of diffusion of the vertical load being applied to the foundation. Conservatively this can be taken as 1.5 alpha = 1.5 # αcc is the coefficient that allows for long term effects on the compressive strength of concrete vs applied actions. Taken as 0.85 in the UK National Annex -> on page # γc is the partial factor of safety of concrete. Taken as 1.5 in the UK National Annex -> on page fjd = beta_j * alpha * (params.input.acc * params.input.fck) / params.input.yc # Compute area of baseplate required Areq = (params.input.Design_load * 1000) / fjd c = calculate_c(results["Perimeter_col"], results["Area_col"], Areq) # Compute the thickness of baseplate (tp) tp = c * (3 * fjd * Ym0 / params.input.steel_class) ** 0.50 return Ym0, beta_j, alpha, fjd, Areq, c, tp @DataView("Output", duration_guess=1) def Compute_output(self, params: Munch, **kwargs): Ym0, beta_j, alpha, fjd, Areq, c, tp = self.calculate_plate_geom(params) data = DataGroup( DataItem("ultimate load ", params.input.Design_load, suffix="KN"), DataItem("beta_j", 0.67), DataItem("alpha", 1.5), DataItem("Bearing capacity of concrete support(fjd) ", round(fjd), suffix="MPa"), DataItem("Areq ", round(Areq), suffix="mm2"), DataItem(" c", round(c), suffix="mm"), DataItem("Thickness of plate", round(tp), suffix="mm"), ) return DataResult(data) @staticmethod def get_beam_profile(h, b, tw, tf, r) -> List[Point]: """Generates the points which make up the chosen profile for the column cross-section""" # Get points for top flange points = [ Point(-b / 2, (h / 2) - tf), Point(-b / 2, h / 2), Point(b / 2, h / 2), Point(b / 2, (h / 2) - tf), ] # Get curve for top right angles = np.linspace(np.pi / 2, np.pi, 10) x = r * np.cos(angles) + tw / 2 + r y = r * np.sin(angles) + h / 2 - tf - r for _x, _y in zip(x, y): points.append(Point(_x, _y)) # Get curve for bottom right angles = np.linspace(-np.pi, -np.pi / 2, 10) x = r * np.cos(angles) + tw / 2 + r y = r * np.sin(angles) - h / 2 + tf + r for _x, _y in zip(x, y): points.append(Point(_x, _y)) # Get points for bottom flange points.extend([ Point(b / 2, - (h / 2) + tf), Point(b / 2, -h / 2), Point(-b / 2, -h / 2), Point(-b / 2, -(h / 2) + tf), ]) # Get curve for bottom left angles = np.linspace(1.5 * np.pi, 2 * np.pi, 10) x = r * np.cos(angles) - tw / 2 - r y = r * np.sin(angles) - h / 2 + tf + r for _x, _y in zip(x, y): points.append(Point(_x, _y)) # Get curve for top left angles = np.linspace(0, np.pi/2, 10) x = r * np.cos(angles) - tw / 2 - r y = r * np.sin(angles) + h / 2 - tf - r for _x, _y in zip(x, y): points.append(Point(_x, _y)) # Repeat the first point to close the profile points.append(Point(-b / 2, (h / 2) - tf)) return points @GeometryView("3D baseplate View", duration_guess=1) def get_3dView(self, params: Munch, **kwargs): """Create geometry for column, base-plate and add a concrete slab underneath""" Ym0, beta_j, alpha, fjd, Areq, c, tp = self.calculate_plate_geom(params) concrete_thickness = 15 * tp steel = Material(color=Color(95, 158, 240), metalness=1) concrete = Material(metalness=0, roughness=1, opacity=0.6) h = self.get_profile_property(params.input.profile_type, params.input.profile, "Depth") b = self.get_profile_property(params.input.profile_type, params.input.profile, "Width") tw = self.get_profile_property(params.input.profile_type, params.input.profile, "Web thickness") tf = self.get_profile_property(params.input.profile_type, params.input.profile, "Flange thickness") r = self.get_profile_property(params.input.profile_type, params.input.profile, "Root radius") beam_profile = self.get_beam_profile(h, b, tw, tf, r) beam = Extrusion(beam_profile, Line(Point(0, 0, tp), Point(0, 0, 3 * h)), material=steel) base_plate = SquareBeam(sqrt(Areq), sqrt(Areq), tp, material=steel) # TODO: This area doesn't seem sufficient for large column sizes base_plate.translate((0, 0, tp / 2)) concrete_plate = SquareBeam(6 * h, 6 * h, concrete_thickness, material=concrete) concrete_plate.translate((0, 0, -concrete_thickness / 2)) return GeometryResult([beam, base_plate, concrete_plate]) @staticmethod def get_profile_property( profile_type: str, profile: str, property_name: str ) -> float: """Retrieve the profile properties based on the profile type, profile and property :param profile_type: One of the following profile types: HEA, HEB or IPE. :param profile: Profile name, eg IPE80 (IPE was given as profile_type) :param property_name: The name of the property, eg Weight """ file_path = ( Path(__file__).parent / "profiles" / f"steel-profiles-{profile_type}.csv" ) df = pd.read_csv(file_path, header=[2], skiprows=[3, 4, 5]) return df.loc[df["Profile"] == profile, property_name].item() @staticmethod def get_geometrical_properties( profile_type: str, profile: str ): """Calculates the allowable bending moment based on the given parameters. :param profile_type: One of the following profile types: HEA, HEB or IPE. :param profile: Profile name, eg IPE80 (IPE was given as profile_type) :param steel_class: The steel class, eg S235 :return: A dict with the moment of inertia, profile height, yield strength and allowable bending moment. """ file_path = ( Path(__file__).parent / "profiles" / f"steel-profiles-{profile_type}.csv" ) df = pd.read_csv(file_path, header=[2], skiprows=[3, 4, 5]) Depth = df.loc[df["Profile"] == profile, "Depth"].item() Width = df.loc[df["Profile"] == profile, "Width"].item() Thickeness_of_web = df.loc[df["Profile"] == profile, "Web thickness"].item() Thickeness_of_flange = df.loc[df["Profile"] == profile, "Flange thickness"].item() Area_col = df.loc[df["Profile"] == profile, "Area"].item() Perimeter_col = df.loc[df["Profile"] == profile, "Perimeter"].item() Perimeter_col = Perimeter_col * 1000 return { "Depth": Depth, "Width": Width, "Thickeness_of_web": Thickeness_of_web, "Thickeness_of_flange": Thickeness_of_flange, "Area_col": Area_col, "Perimeter_col": Perimeter_col }


Abschluss

Ich stoße immer wieder auf das Problem, die Dicke der Grundplatte und die erforderliche Nutzfläche überprüfen zu müssen, die vorhanden sein muss, damit die Stützenlasten wirksam auf das Fundament übertragen werden können.


Die Verwendung eines Python-Skripts, das mir bei solchen Prüfungen helfen kann, und die Konvertierung des Skripts in eine gemeinsam nutzbare und leicht zugängliche Webanwendung mithilfe des Viktor SDK war einfach und hat den Arbeitsablauf beim Grundplattendesign effizienter gemacht.


Durch die Erstellung dieser Art von technischer Anwendung können Sie auf Ihrer Baustelle nur mit Ihrem Mobiltelefon sicherer arbeiten und die Konstruktionsgenauigkeit von Strukturelementen wie Grundplatten überprüfen, bevor diese hergestellt und platziert werden.