148 lines
5.6 KiB
Python
148 lines
5.6 KiB
Python
import argparse
|
|
from matplotlib import pyplot as plt
|
|
from math import floor
|
|
|
|
|
|
class ProfileHeights:
|
|
|
|
bobbin_train_segment_types = {165: 0.38, 210: 0.248, 225: 0.354648} # Key = Spulenzug-Typ - Value = Gewicht
|
|
|
|
def __init__(self,
|
|
cross_section_type,
|
|
datum,
|
|
width,
|
|
thickness,
|
|
ap_positions=None,
|
|
beam_length=2000,
|
|
min_ap_distance=200,
|
|
yield_strength=235,
|
|
segment_type=165,
|
|
bobbin_mass=4,
|
|
column_distance=3.6,
|
|
):
|
|
|
|
self.cross_section_type = cross_section_type
|
|
self.datum = datum
|
|
self.width = width
|
|
self.thickness = thickness
|
|
self.ap_positions = ap_positions
|
|
self.beam_length = beam_length
|
|
self.min_ap_distance = min_ap_distance
|
|
self.yield_strength = yield_strength
|
|
self.segment_type = segment_type
|
|
self.bobbin_mass = bobbin_mass
|
|
self.column_distance = column_distance
|
|
|
|
def ap_position_check(self):
|
|
# Überprüft, ob alle AP's den zulässigen Mindestabstand zueinander einhalten
|
|
|
|
if not [abs(new_pos - old_pos) < self.min_ap_distance for old_pos, new_pos in zip(self.ap_positions, self.ap_positions[1:])]:
|
|
raise ValueError(f"Abstände zwischen ")
|
|
else:
|
|
return True
|
|
|
|
def ap_amount(self):
|
|
return floor(self.beam_length / self.min_ap_distance)
|
|
|
|
def individual_ap_positions(self):
|
|
# Funktion gibt Einzelabstände der AP-Profile zur Säule zurück
|
|
|
|
# Fall 1: Es wurden keine Einzelabstände zur Säule definiert. Abstand zwischen AP's = zulässiger Mindestabstand
|
|
# Fall 2: Es wurden individuelle AP-Abstände definiert.
|
|
|
|
if self.ap_positions is None:
|
|
return [ap_count * self.min_ap_distance for ap_count in range(1, self.ap_amount() + 1)]
|
|
elif self.ap_position_check():
|
|
return self.ap_positions
|
|
|
|
def force_per_ap_meter(self):
|
|
if self.bobbin_mass > 4:
|
|
raise ValueError(f"Gewicht der Spulen darf max. 4 kg betragen!")
|
|
else:
|
|
column_rows = 2
|
|
location_factor = 9.81 # m/s^2
|
|
ap_weight_per_meter = 1.88
|
|
|
|
total_bobbin_mass = self.bobbin_mass * (1000 / self.segment_type)
|
|
mass = total_bobbin_mass + 2 * self.bobbin_train_segment_types[self.segment_type] + ap_weight_per_meter
|
|
|
|
return mass * location_factor * self.column_distance / column_rows
|
|
|
|
def ref_moment_of_resistance(self, current_beam_length, ap_column_distances, force_per_rail):
|
|
# Funktion berechnet Widerstandsmoment für die aktuelle Trägerlänge
|
|
|
|
total_column_distance = 0
|
|
for ap_column_distance in ap_column_distances:
|
|
if current_beam_length >= ap_column_distance:
|
|
total_column_distance += ap_column_distance
|
|
else:
|
|
break
|
|
|
|
safety_factor = 1.7
|
|
bend_moment = force_per_rail * total_column_distance
|
|
allowed_bend_stress = (self.yield_strength * 1.2) / safety_factor
|
|
|
|
return bend_moment / allowed_bend_stress
|
|
|
|
def recalculated_moment_of_resistance(self, height):
|
|
# Berechnet das Widerstandsmoment mit der derzeitigen Profilhöhe für verschiedene Querschnitts-Arten
|
|
|
|
inner_width = self.width - 2 * self.thickness
|
|
inner_height = height - 2 * self.thickness
|
|
bar_width = self.width - self.thickness
|
|
|
|
# 1. Widerstandsmoment-Berechnung für idealisiertes rechteckiges Hohlprofil:
|
|
if self.cross_section_type == "hohlprofil":
|
|
return (self.width * height ** 3 - inner_width * inner_height ** 3) / (6 * height)
|
|
|
|
# 2. Widerstandsmoment-Berechnung für idealisiertes IPE-Profil / C-Profil:
|
|
elif self.cross_section_type in ["c", "ipe"]:
|
|
return (self.width * height ** 3 - bar_width * inner_height ** 3) / (6 * height)
|
|
|
|
def datum_reference(self):
|
|
# Legt fest, ob die notwendige Profilhöhe im Plot in Abhängigkeit von jedem Millimeter der Gesamtlänge [l]
|
|
# des Trägers oder der Trägerlänge an der Stelle jedes AP-Profils [n] dargestellt werden soll.
|
|
|
|
if self.datum == "l":
|
|
return list(range(self.min_ap_distance, self.beam_length + 1))
|
|
|
|
elif self.datum == "n":
|
|
return self.individual_ap_positions()
|
|
|
|
def height_calculation(self):
|
|
|
|
start_height = 2 * self.thickness
|
|
|
|
beam_lengths = self.datum_reference()
|
|
ap_column_distance = self.individual_ap_positions()
|
|
force_per_ap_meter = self.force_per_ap_meter()
|
|
|
|
heights = []
|
|
lengths = []
|
|
moment_of_resistances = []
|
|
recalculated_moment_of_resistance = 0
|
|
|
|
for count, beam_length in enumerate(beam_lengths):
|
|
reference_moment_of_resistance = self.ref_moment_of_resistance(beam_length, ap_column_distance, force_per_ap_meter)
|
|
|
|
while recalculated_moment_of_resistance < reference_moment_of_resistance:
|
|
recalculated_moment_of_resistance = self.recalculated_moment_of_resistance(start_height)
|
|
start_height += 0.01
|
|
|
|
moment_of_resistances.append(reference_moment_of_resistance)
|
|
heights.append(start_height)
|
|
lengths.append(beam_length)
|
|
|
|
return heights, lengths
|
|
|
|
|
|
a = ProfileHeights(cross_section_type="hohlprofil", datum="l", width=50, thickness=2.5)
|
|
|
|
ya_heights, xa_lengths = a.height_calculation()
|
|
plt.plot(xa_lengths, ya_heights)
|
|
|
|
plt.xlabel("Länge des Trägers in mm")
|
|
plt.ylabel("Benötigte Querschnittshöhe des Trägers in mm")
|
|
plt.grid(True)
|
|
plt.show()
|