paint-brush
Как создать веб-приложение для проектирования стальной опорной пластины с помощью Python и Viktorк@kamalsamaila
660 чтения
660 чтения

Как создать веб-приложение для проектирования стальной опорной пластины с помощью Python и Viktor

к Kamal samaila18m2024/05/06
Read on Terminal Reader

Слишком долго; Читать

В этой статье вы узнаете, как создать приложение на основе Python для проектирования стальных опорных плит, необходимых для безопасной передачи нагрузок от колонн на фундамент. В нем рассматривается расчет площади опорной плиты, ее толщины, несущей способности бетона и дополнительной ширины с использованием метода Т-образного выступа. Код Python затем преобразуется в веб-приложение с помощью Victor SDK, что позволяет инженерам вводить параметры и визуализировать 3D-модели конструкции. Этот эффективный инструмент повышает точность проектирования опорных плит и облегчает проверку на месте с помощью мобильных устройств, оптимизируя рабочий процесс строительства.
featured image - Как создать веб-приложение для проектирования стальной опорной пластины с помощью Python и Viktor
Kamal samaila HackerNoon profile picture

Введение

Стальные опорные плиты размещаются под стальными колоннами для безопасной передачи расчетных усилий на фундамент.


Когда стальные колонны несут большие нагрузки с небольшим поперечным сечением, прямое приложение нагрузок к фундаменту может привести к разрушению пробивки. Таким образом, крайне важно использовать опорную плиту под колонной, чтобы распределить нагрузку на большую площадь.


В этой статье представлено руководство по созданию приложения для проектирования опорной плиты с использованием Python с использованием геометрических свойств стали, хранящихся в формате CSV.


Приложение поможет инженерам легко определить необходимую площадь опорной плиты, ее толщину, несущую способность бетона и дополнительную ширину.


Более того, используя Victor SDK, мы можем легко преобразовать нашу реализацию Python в веб-приложение.


Этот SDK предлагает возможность визуализировать нашу структуру в 3D. Давайте приступим к делу и начнем действовать!

Основной принцип проектирования опорной плиты

При проектировании опорной плиты используется эквивалентный метод Т-образных патрубков для расчета осевых сил, при котором «эффективная площадь» рассчитывается для Т-образных патрубков при сжатии, а изгиб опорной плиты оценивается для Т-образных патрубков при растяжении. Допускаются большие и/или незначительные горизонтальные сдвиги, но без моментов, т. е. конструкция с закрепленным основанием.

Первое, что мы рассчитали – это несущая способность несущего бетона fjd.

Расчетная несущая способность fjd между нижней стороной опорной плиты и подстилочным материалом в пространстве для цементного раствора определяется по формуле:


fjd = βj * α * fcd

где


βj = коэффициент материала шва фундамента = (2/3)


α = коэффициент, учитывающий диффузию сосредоточенной силы внутри фундамента.


fcd = расчетное значение прочности бетона на сжатие = αcc * fck / ɣc


αcc = коэффициент долгосрочных эффектов


fck = характеристическая прочность бетона в цилиндре


ɣc = частичный коэффициент безопасности для бетона

Второй шаг — вычислить необходимую площадь опорной плиты, которая определяется по формуле:

Areq = Нед / fjd

Где Ned — предельная нагрузка на стальную колонну.

Третий шаг — вычислить c, который представляет собой выступ кантилевера эффективной площади:

C рассчитывается по следующей формуле:

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


Следовательно, вы решаете для c.


И, наконец, вычисляем толщину опорной плиты tp:

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

Реализация рабочего процесса проектирования базовой платы на Python

 # 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

Наконец, превращение кода Python в веб-приложение для проектирования базовой платы

Вход

Моему окончательному приложению потребуются функции ввода, где пользователь может указать следующие параметры:

Это достигается с помощью класса параметризации из Victor SDK.

 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")


Выход

После расчета для отображения результата расчета пользователю использовался метод просмотра данных из Victor SDK.

 @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)

где:

Несущая способность бетона (Fjd)

Требуемая площадь стали (Areq)

Дополнительный выступ опорной плиты(c)

Толщина опорной плиты

Наконец, создается 3D-модель стальной колонны, опорной плиты и несущего бетонного фундамента.

Метод get_3dview был определен внутри класса контроллера, украшенного @GeometryView.


Метод get_3dview определяет логику создания 3D-модели и, наконец, возвращает объект GeometryResult, содержащий созданную стальную колонну, опорную плиту и бетонную опору.


Логика содержится в коде ниже:

 @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]) 


Полный код можно найти ниже:

 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 }


Заключение

Я всегда сталкиваюсь с проблемой проверки толщины опорной плиты и необходимой эффективной площади, которую следует предусмотреть, чтобы нагрузки от колонны могли эффективно передаваться на фундамент.


Использование сценария Python, который может помочь мне в таких проверках, и преобразование сценария в совместно используемое и легкодоступное веб-приложение с помощью Victor SDK оказалось простым и повысило эффективность рабочего процесса проектирования базовой платы.


Создание такого типа инженерного приложения позволит вам чувствовать себя уверенно на строительной площадке, используя только свой мобильный телефон, и иметь возможность проверять точность проектирования конструктивных элементов, таких как опорные плиты, прежде чем они будут изготовлены и установлены.