ourocode 1.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ourocode might be problematic. Click here for more details.

Files changed (53) hide show
  1. ourocode/__init__.py +0 -0
  2. ourocode/__version__.py +1 -0
  3. ourocode/data/caracteristique_meca_acier.csv +33 -0
  4. ourocode/data/caracteristique_meca_bois.csv +59 -0
  5. ourocode/data/carte_action_region.csv +36722 -0
  6. ourocode/data/coeff_psy.csv +13 -0
  7. ourocode/data/exploitation.csv +17 -0
  8. ourocode/data/gammaM.csv +14 -0
  9. ourocode/data/kdef.csv +11 -0
  10. ourocode/data/kfi.csv +10 -0
  11. ourocode/data/kmod.csv +16 -0
  12. ourocode/data/limite_fleche.csv +9 -0
  13. ourocode/data/qualite_acier.csv +18 -0
  14. ourocode/data/screenshot/C90_def.png +0 -0
  15. ourocode/data/screenshot/Kv_def.png +0 -0
  16. ourocode/data/screenshot/fleche.png +0 -0
  17. ourocode/data/screenshot/sign_convention.png +0 -0
  18. ourocode/data/section_boulon.csv +12 -0
  19. ourocode/data/vent/vent_Cp_toiture_isolee_1_versant.csv +22 -0
  20. ourocode/data/vent/vent_Cp_toiture_isolee_1_versant.png +0 -0
  21. ourocode/data/vent/vent_Cp_toiture_isolee_2_versants.csv +31 -0
  22. ourocode/data/vent/vent_Cp_toiture_isolee_2_versants.png +0 -0
  23. ourocode/data/vent/vent_Cpe_mur_verticaux.csv +11 -0
  24. ourocode/data/vent/vent_Cpe_mur_verticaux.png +0 -0
  25. ourocode/data/vent/vent_Cpe_toiture_1_versant.png +0 -0
  26. ourocode/data/vent/vent_Cpe_toiture_1_versant_0_degres.csv +13 -0
  27. ourocode/data/vent/vent_Cpe_toiture_1_versant_180_degres.csv +13 -0
  28. ourocode/data/vent/vent_Cpe_toiture_1_versant_90_degres.csv +13 -0
  29. ourocode/data/vent/vent_Cpe_toiture_2_versants.png +0 -0
  30. ourocode/data/vent/vent_Cpe_toiture_2_versants_0_degres.csv +21 -0
  31. ourocode/data/vent/vent_Cpe_toiture_2_versants_90_degres.csv +21 -0
  32. ourocode/data/vent/vent_Cpe_toiture_terrasse.csv +21 -0
  33. ourocode/data/vent/vent_Cpe_toiture_terrasse.png +0 -0
  34. ourocode/data/vent/vent_Ffr.png +0 -0
  35. ourocode/eurocode/A0_Projet.py +1408 -0
  36. ourocode/eurocode/EC0_Combinaison.py +1763 -0
  37. ourocode/eurocode/EC1_Exploitation.py +103 -0
  38. ourocode/eurocode/EC1_Neige.py +385 -0
  39. ourocode/eurocode/EC1_Vent.py +1388 -0
  40. ourocode/eurocode/EC3_Assemblage.py +466 -0
  41. ourocode/eurocode/EC3_Element_droit.py +302 -0
  42. ourocode/eurocode/EC5_Assemblage.py +1760 -0
  43. ourocode/eurocode/EC5_Element_droit.py +1740 -0
  44. ourocode/eurocode/EC5_Feu.py +922 -0
  45. ourocode/eurocode/EC8_Sismique.py +2 -0
  46. ourocode/eurocode/__init__.py +0 -0
  47. ourocode/eurocode/logical.py +83 -0
  48. ourocode/eurocode/objet.py +263 -0
  49. ourocode-1.6.0.dist-info/METADATA +331 -0
  50. ourocode-1.6.0.dist-info/RECORD +53 -0
  51. ourocode-1.6.0.dist-info/WHEEL +5 -0
  52. ourocode-1.6.0.dist-info/licenses/LICENSE +201 -0
  53. ourocode-1.6.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1740 @@
1
+ #! env\Scripts\python.exe
2
+ # Encoding in UTF-8 by Anthony PARISOT
3
+
4
+
5
+
6
+ # Code permettant le calcul des principaux coef. EC5 (EN 1995) ainsi que les calculs simple de vérification au
7
+ # élément droit.
8
+ from copy import deepcopy
9
+ import matplotlib.pyplot as plt
10
+
11
+ import math as mt
12
+ from math import sqrt, pi, cos, sin, radians
13
+ import numpy as np
14
+
15
+ import forallpeople as si
16
+ si.environment("structural")
17
+ from handcalcs.decorator import handcalc
18
+
19
+ from ourocode.eurocode.A0_Projet import Projet
20
+
21
+
22
+ # ================================ GLOBAL ==================================
23
+
24
+ class Barre(Projet):
25
+ LIST_SECTION = ["Rectangulaire","Circulaire"]
26
+ LIST_TYPE_B = ["Massif", "BLC", "LVL", "OSB 2", "OSB 3/4", "CP"]
27
+ CLASSE_WOOD = tuple(Projet._data_from_csv(Projet, "caracteristique_meca_bois.csv").index)[2:]
28
+ CS = ["1","2","3"]
29
+ CARACTERISTIQUE = tuple(Projet._data_from_csv(Projet, "caracteristique_meca_bois.csv").columns)
30
+ LOAD_TIME = tuple(Projet._data_from_csv(Projet, "kmod.csv").columns)[1:]
31
+ TYPE_ACTION = ("Fondamentales" ,"Accidentelles")
32
+ TYPE_BAT = ("Bâtiments courants", "Bâtiments agricoles et similaires")
33
+ TYPE_ELE = tuple(Projet._data_from_csv(Projet, "limite_fleche.csv").index.unique())
34
+ B90 = 0.25
35
+
36
+ def __init__(self, b:si.mm, h:si.mm, section: str=LIST_SECTION, Hi: int=12, Hf: int=12, classe: str=CLASSE_WOOD, cs: int=CS, effet_systeme: bool=("False", "True"), **kwargs):
37
+ """Classe qui définit les caractéristiques d'un élément droit.
38
+ Cette classe est hérité de la classe Projet du module A0_Projet.py.
39
+
40
+ Args:
41
+ b (int): largeur de pose de la pièce en mm
42
+ h (int): hauteur de pose de la pièce en mm
43
+ section (str, optional): Type de section. Defaults to "Rectangulaire".
44
+ Hi (int, optional): Humidité initiale de pose en %. Defaults to 12.
45
+ Hf (int, optional): Humidité finale de pose en %. Defaults to 12.
46
+ classe (str, optional): Classe mécanique du bois. Defaults to 'C24'.
47
+ cs (int, optional): Classe de service de l'élément. Defaults to 1.
48
+ effet_systeme: Détermine si l'effet système s'applique.
49
+ """
50
+ super().__init__(**kwargs)
51
+ self.b = b * si.mm
52
+ self.h = h * si.mm
53
+ self.section = section
54
+ self.Hi = Hi
55
+ self.Hf = Hf
56
+ self.classe = classe
57
+ self.cs = cs
58
+ self.effet_systeme = effet_systeme
59
+ self._sectionCalcul()
60
+
61
+
62
+ def _sectionCalcul(self):
63
+ """ Retourne la section de calcul en fonction de l'humidité de pose et celle d'utilisation avec pour argument:
64
+ Hi : Humidité de pose en %
65
+ Hf : Humidité finale en % selon AN Hf = 12%
66
+ B90 : Coefficient de correction de section selon AN B90 = 0.25 %
67
+ cote : Largeur ou hauteur de la section initiale en mm """
68
+ self.b_calcul = self.b * (1 - self.B90 / 100 * (self.Hi - self.Hf))
69
+ self.h_calcul = self.h * (1 - self.B90 / 100 * (self.Hi - self.Hf))
70
+
71
+
72
+ @property
73
+ def aire(self):
74
+ if self.section == __class__.LIST_SECTION[0]:
75
+ return self.b_calcul * self.h_calcul
76
+ else:
77
+ return mt.pi * (self.b_calcul/2)**2
78
+
79
+
80
+ @property
81
+ def inertie(self):
82
+ """ Retourne le moment quadratique d'une section rectangulaire en mm4 avec pour argument :
83
+ b ou d : Largeur ou diamètre de la poutre en mm
84
+ h : Hauteur de la poutre en mm """
85
+ if self.section == "Rectangulaire":
86
+ self.I_y = (self.b_calcul * self.h_calcul**3)/12
87
+ self.I_z = (self.h_calcul * self.b_calcul**3)/12
88
+ return [self.I_y, self.I_z]
89
+
90
+ elif hasattr(self, "Iy") and hasattr(self, "Iz"):
91
+ return [self.I_y * si.mm**4, self.I_z * si.mm**4]
92
+
93
+ else:
94
+ self.I_y = (mt.pi * self.b_calcul ** 4) / 64
95
+ self.I_z = self.I_y
96
+ return [self.I_y, self.I_z]
97
+
98
+
99
+ @property
100
+ def caract_meca(self):
101
+ """ Retourne les caractéristiques méca du bois sous forme de dataframe pandas """
102
+ data_csv_meca = self._data_from_csv("caracteristique_meca_bois.csv")
103
+ return data_csv_meca.loc[self.classe]
104
+
105
+
106
+ @property
107
+ def gamma_M_table(self):
108
+ """Retourne le tableau des gamma M pour le type de bois sélectionné
109
+ """
110
+ data_csv_gammaM = self._data_from_csv("gammaM.csv")
111
+ return data_csv_gammaM.loc[self.type_bois]
112
+
113
+
114
+ def _get_gamma_M(self, typecombi=TYPE_ACTION):
115
+ self.gamma_M = self.gamma_M_table.loc[typecombi]
116
+ return self.gamma_M
117
+
118
+
119
+ @property
120
+ def K_def(self):
121
+ data_csv_kdef = self._data_from_csv("kdef.csv")
122
+ kdef = float(data_csv_kdef.loc[self.type_bois][str(self.cs)])
123
+ if self.Hi > 20:
124
+ kdef += 1
125
+ return kdef
126
+
127
+
128
+ @property
129
+ def K_mod_table(self):
130
+ """ Retourne le tableau des Kmod du bois
131
+ """
132
+ data_csv_kmod = self._data_from_csv("kmod.csv")
133
+ data_kmod = data_csv_kmod.loc[self.type_bois]
134
+ return data_kmod.loc[data_kmod["CS"]==self.cs]
135
+
136
+
137
+ def _get_k_mod(self, loadtype=LOAD_TIME):
138
+ self.K_mod = self.K_mod_table[loadtype].iloc[0]
139
+ return self.K_mod
140
+
141
+
142
+ @property
143
+ def k_sys(self):
144
+ """Détermine le Ksys d'un élément si celui-ci permet une redistribution des charges continues.
145
+ """
146
+ if self.effet_systeme:
147
+ return 1.1
148
+ else:
149
+ return 1
150
+
151
+
152
+ @property
153
+ def type_bois(self):
154
+ if self.classe[0:1] == "C" or self.classe[0:1] == "D":
155
+ type_b = __class__.LIST_TYPE_B[0]
156
+ elif self.classe[0:2] == "GL":
157
+ type_b = __class__.LIST_TYPE_B[1]
158
+ elif self.classe[0:3] == "LVL":
159
+ type_b = __class__.LIST_TYPE_B[2]
160
+ elif self.classe[0:5] == "OSB/2":
161
+ type_b = __class__.LIST_TYPE_B[3]
162
+ elif self.classe[0:5] == "OSB/3" or self.classe[0:5] == "OSB/4":
163
+ type_b = __class__.LIST_TYPE_B[4]
164
+ else:
165
+ type_b = __class__.LIST_TYPE_B[5]
166
+
167
+ return type_b
168
+
169
+
170
+ def __convert_latex_ftyped(self, latex: str, type_caract: str):
171
+ end_index_rk = type_caract.find("k")
172
+ type_caract = type_caract[1:end_index_rk]
173
+ latex = latex.replace("f_{type_{Rd}", "f_{"+type_caract+"_{"+"d}")
174
+ latex = latex.replace("f_{type_{k}", "f_{"+type_caract+"_{"+"k}")
175
+ return latex
176
+
177
+
178
+ def _f_type_d(self,typeCarac=CARACTERISTIQUE[0:6], loadtype=LOAD_TIME, typecombi=TYPE_ACTION):
179
+ """Méthode donnant la résistance de calcul de l'élément fonction de la vérification
180
+
181
+ Args:
182
+ typeCarac (str, optional): Type de résistance caractéristique (flexion = "fm0k", compression = "fc0k" etc.). Defaults to "fm0k".
183
+ loadtype (str, optional): Durée de chargement (Permanente, Court terme etc.). Defaults to "Permanente".
184
+ typecombi (str, optional): Type de combinaison étudiée ("Fondamentales" ou " Accidentelles"). Defaults to "Fondamentales".
185
+
186
+ Returns:
187
+ float: Résistance de calcul en N/mm2 du type de vérification étudié.
188
+ """
189
+ gamma_M = self._get_gamma_M(typecombi)
190
+ K_mod = self._get_k_mod(loadtype)
191
+ f_type_k = float(self.caract_meca.loc[typeCarac]) * si.MPa
192
+
193
+ if typeCarac == "fm0k" and self.k_sys > 1:
194
+ k_sys = self.k_sys
195
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
196
+ def val():
197
+ f_type_Rd = k_sys * f_type_k * K_mod / gamma_M
198
+ return f_type_Rd
199
+ else:
200
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
201
+ def val():
202
+ f_type_Rd = f_type_k * K_mod / gamma_M
203
+ return f_type_Rd
204
+ value = val()
205
+ latex = self.__convert_latex_ftyped(value[0], typeCarac)
206
+ self.f_type_rd = value[1]
207
+ return (latex, value[1])
208
+
209
+
210
+ def _K_h(self):
211
+ """ Retourne le coef. Kh qui peut augmenter la resistance caractéristique fm,k et ft,k """
212
+ kh = {}
213
+ dim = {'y': self.h_calcul.value *10**3, 'z': self.b_calcul.value *10**3}
214
+
215
+ for cle, valeur in dim.items():
216
+ if self.type_bois == "Massif":
217
+ if valeur < 150:
218
+ kh[cle] = min((150 / valeur) ** 0.2, 1.3)
219
+ else :
220
+ kh[cle] = 1
221
+ elif self.type_bois == "BLC":
222
+ if valeur < 600:
223
+ kh[cle] = min((600 / valeur) ** 0.1, 1.1)
224
+ else :
225
+ kh[cle] = 1
226
+ else:
227
+ print("LVL non pris en compte dans cette fonction")
228
+ kh[cle] = 1
229
+ return kh
230
+
231
+
232
+ def Emean_fin(self, psy_2: float):
233
+ """Renvoie le E,mean,fin en fonction du Kdef et du psy2"""
234
+ self.psy_2 = psy_2
235
+ E0_mean = int(self.caract_meca.loc["E0mean"]) * si.MPa
236
+ K_def = self.K_def
237
+
238
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
239
+ def val():
240
+ E_mean_fin = E0_mean / (1 + psy_2 * K_def)
241
+ return E_mean_fin
242
+
243
+ value = val()
244
+ self.E_mean_fin = value[1]
245
+ return value
246
+
247
+
248
+ def fleche(self, long:si.mm, Ed_WinstQ:si.mm=0, Ed_Wnetfin:si.mm=0, Ed_Wfin:si.mm=0, type_ele=TYPE_ELE, type_bat=TYPE_BAT):
249
+ """Retourne le taux de travail de la flèche en % avec pour argument:
250
+
251
+ Args:
252
+ long (int): La longueur entre appuis à vérifier en mm
253
+ Ed_WinstQ (float, optional): La flèche instanténée sous charge variable Q en mm. Defaults to 0.
254
+ Ed_Wnetfin (float, optional): La flèche net finale en mm. Defaults to 0.
255
+ Ed_Wfin (float, optional): La flèche finale en mm. Defaults to 0.
256
+ type_ele (_type_, optional): Le type d'élément à vérifier. Defaults to TYPE_ELE.
257
+ type_bat (_type_, optional): Le type de bâtiment sur lequel on vérifie notre élémennt. Defaults to TYPE_BAT.
258
+
259
+ Returns:
260
+ dict: Retourne le dictionnaire des taux de travail.
261
+ """
262
+ data_csv_fleche = self._data_from_csv("limite_fleche.csv")
263
+ self.data_fleche= data_csv_fleche.loc[type_ele]
264
+ self.data_fleche = self.data_fleche.loc[self.data_fleche["Type bâtiment"]==type_bat]
265
+ self.taux_ELS = {}
266
+
267
+ long = long * si.mm
268
+ Ed_W_inst_Q = Ed_WinstQ * si.mm
269
+ Ed_W_net_fin = Ed_Wnetfin * si.mm
270
+ Ed_W_fin = Ed_Wfin * si.mm
271
+
272
+ limit_W_inst_Q = self.data_fleche['Winst(Q)'].iloc[0]
273
+ limit_W_net_fin = int(self.data_fleche['Wnet,fin'].iloc[0])
274
+ limit_W_fin = int(self.data_fleche['Wfin'].iloc[0])
275
+ limit_U_fin_max = self.data_fleche['Ufin,max'].iloc[0]
276
+
277
+ if np.isnan(limit_U_fin_max):
278
+ limit_U_fin_max = long / limit_W_fin
279
+ else:
280
+ limit_U_fin_max = int(limit_U_fin_max)
281
+
282
+ if not np.isnan(limit_W_inst_Q):
283
+ limit_W_inst_Q = int(limit_W_inst_Q)
284
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
285
+ def val():
286
+ Rd_W_inst_Q = long / limit_W_inst_Q
287
+ Rd_W_net_fin = long / limit_W_net_fin
288
+ Rd_W_fin = min(long / limit_W_fin, limit_U_fin_max)
289
+
290
+ taux_W_inst_Q = Ed_W_inst_Q / Rd_W_inst_Q * 100 #%
291
+ taux_W_net_fin = Ed_W_net_fin / Rd_W_net_fin * 100 #%
292
+ taux_W_fin = Ed_W_fin / Rd_W_fin * 100 #%
293
+ return taux_W_inst_Q, taux_W_net_fin, taux_W_fin
294
+
295
+ value = val()
296
+ self.taux_ELS["Winst(Q)"] = value[1][0]
297
+ self.taux_ELS["Wnet,fin"] = value[1][1]
298
+ self.taux_ELS["Wfin"] = value[1][2]
299
+
300
+ else:
301
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
302
+ def val():
303
+ Rd_W_net_fin = long / limit_W_net_fin
304
+ Rd_W_fin = min(long / limit_W_fin, limit_U_fin_max)
305
+
306
+ taux_W_net_fin = Ed_W_net_fin / Rd_W_net_fin * 100 #%
307
+ taux_W_fin = Ed_W_fin / Rd_W_fin * 100 #%
308
+ return taux_W_net_fin, taux_W_fin
309
+
310
+ value = val()
311
+ self.taux_ELS["Wnet,fin"] = value[1][0]
312
+ self.taux_ELS["Wfin"] = value[1][1]
313
+ return value
314
+
315
+
316
+ # ================================ FLEXION ==================================
317
+
318
+ class Flexion(Barre):
319
+ COEF_LEF = {"Appuis simple" : [1, 0.9, 0.8],
320
+ "Porte à faux": [0.5, 0.8]}
321
+ LOAD_POS = (
322
+ "Charge sur fibre comprimée",
323
+ "Charge sur fibre neutre",
324
+ "Charge sur fibre tendue"
325
+ )
326
+
327
+ def __init__(self, lo:si.mm, coeflef: float=COEF_LEF['Appuis simple'][1], pos: str=LOAD_POS, *args, **kwargs):
328
+ """Classe permettant le calcul de la flexion d'une poutre bois selon l'EN 1995 §6.1.6, §6.2.3, §6.2.4 et §6.3.3.
329
+ Cette classe est hérité de la classe Barre, provenant du module EC5_Element_droit.py.
330
+
331
+ Args:
332
+ lo (int): longueur de déversemment en mm
333
+ coeflef (float): appuis simple :
334
+ Moment constant : 1
335
+ Charge répartie constante : 0.9
336
+ Charge concentrée au milieu de la portée : 0.8
337
+ porte à faux :
338
+ Charge répartie constante : 0.5
339
+ Charge concentrée agissant à l'extrémité libre : 0.8.
340
+
341
+ pos (str): positionnement de la charge sur la hauteur de poutre
342
+ """
343
+ super().__init__(*args, **kwargs)
344
+ self.lo = lo * si.mm
345
+ self.coeflef = coeflef
346
+ self.pos = pos
347
+
348
+
349
+ @property
350
+ def K_h(self):
351
+ """ Retourne le coef. Kh qui peut augmenter la resistance caractéristique fm,k et ft,k """
352
+ return self._K_h()
353
+
354
+
355
+ @property
356
+ def K_m(self):
357
+ """ Retourne le coef. Km qui reduit les contrainte d'une poutre scié en flexion """
358
+ if self.type_bois == "Massif" or self.type_bois == "BLC" or self.type_bois == "LVL":
359
+ if self.section == "Rectangulaire":
360
+ km = 0.7
361
+ else:
362
+ km = 1
363
+ else:
364
+ km = 1
365
+ return km
366
+
367
+
368
+ @property
369
+ def sigma_m_crit(self):
370
+ """ Retourne sigma m,crit pour la prise en compte du déversement d'une poutre """
371
+ self.l_ef = self.lo * self.coeflef
372
+ if self.pos == "Charge sur fibre comprimée":
373
+ self.l_ef = self.l_ef + 2 * self.h_calcul
374
+ elif self.pos == "Charge sur fibre tendue":
375
+ self.l_ef = self.l_ef - 0.5 * self.h_calcul
376
+
377
+ b_calcul = self.b_calcul
378
+ h_calcul = self.h_calcul
379
+ l_ef = self.l_ef
380
+ E_0_05 = int(self.caract_meca.loc['E005']) * si.MPa
381
+
382
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
383
+ def val():
384
+ sigma_m_crit = (0.78 * b_calcul ** 2 * E_0_05) / (h_calcul * l_ef)
385
+ return sigma_m_crit
386
+ return val()
387
+
388
+
389
+ @property
390
+ def lamb_rel_m(self):
391
+ """ Retourne l'élancement relatif de la section avec pour argument """
392
+ f_m0k = float(self.caract_meca.loc['fm0k']) *si.MPa
393
+ sigma_m_crit = self.sigma_m_crit[1]
394
+
395
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
396
+ def val():
397
+ lamb_rel_m = sqrt(f_m0k / sigma_m_crit)
398
+ return lamb_rel_m
399
+ return val()
400
+
401
+
402
+ @property
403
+ def K_crit(self):
404
+ """ Retourne K,crit le coef. de minoration de la résistance en flexion au déversement"""
405
+ lamb_rel_m = self.lamb_rel_m[1]
406
+
407
+ if lamb_rel_m <= 0.75:
408
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
409
+ def val():
410
+ K_crit = 1
411
+ return K_crit
412
+ elif 0.75 < lamb_rel_m <= 1.4:
413
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
414
+ def val():
415
+ K_crit = 1.56 - 0.75 * lamb_rel_m
416
+ return K_crit
417
+ else:
418
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
419
+ def val():
420
+ K_crit = 1 / (lamb_rel_m ** 2)
421
+ return K_crit
422
+ return val()
423
+
424
+
425
+ def f_m_d(self, loadtype=Barre.LOAD_TIME, typecombi=Barre.TYPE_ACTION):
426
+ """Retourne la résistance f,m,d de l'élément en MPa
427
+
428
+ Args:
429
+ loadtype (str): chargement de plus courte durée sur l'élément.
430
+ typecombi (str): type de combinaison, fondamentale ou accidentelle.
431
+
432
+ Returns:
433
+ float: f,m,d en MPa
434
+ """
435
+ return self._f_type_d("fm0k", loadtype, typecombi)
436
+
437
+
438
+ def sigma_m_d(self, M: float, axe=['y', 'z']):
439
+ """ Retourne la contrainte sigma,m,d suivant sont axes de flexion avec :
440
+ M : Moment max dans la barre en kN.m
441
+ axe : Axe d'inertie quadratique à considérer
442
+ """
443
+ if not hasattr(self, "Md"):
444
+ self.Md = {'y': 0* si.kN*si.m, 'z': 0 * si.kN*si.m}
445
+ self.sigma_m_rd = {'y': 0 * si.MPa, 'z': 0 * si.MPa}
446
+
447
+ self.Md[axe] = M * si.kN*si.m
448
+
449
+ if axe == 'y':
450
+ I = self.inertie[0]
451
+ h_calcul = self.h_calcul
452
+ elif axe == 'z':
453
+ I = self.inertie[1]
454
+ h_calcul = self.b_calcul
455
+ #prend en compte une section circulaire si aucun des deux axes
456
+ else:
457
+ I = self.inertie
458
+
459
+ M_d = self.Md[axe]
460
+
461
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
462
+ def val():
463
+ sigma_m_d = M_d * h_calcul / (I * 2)
464
+ return sigma_m_d
465
+ value = val()
466
+ self.sigma_m_rd[axe] = value[1]
467
+ return value
468
+
469
+
470
+ def taux_m_d(self, compression: object=None, traction: object=None):
471
+ """Retourne les différents taux de travaux en flexion.
472
+ Si l'élement est une poutre (donc avec un travail principalement en flexion) et de la compression (EN 1995-1-1 §6.3.3) ou de la traction (EN 1995-1-1 §6.2.3) combinée,
473
+ il est possible d'ajouter l'objet Compression et Traction et de vérifier ces combinaisons.
474
+
475
+ Args:
476
+ compression (object, optional): L'objet Compression avec ces taux de travaux préalablement calculés. Defaults to None.
477
+ traction (object, optional): L'objet Traction avec ces taux de travaux préalablement calculés. Defaults to None.
478
+
479
+ Returns:
480
+ list: retourne la liste des taux de travaux en %"""
481
+ self.taux_m_rd = {}
482
+
483
+ sigma_my_d = self.sigma_m_rd['y']
484
+ sigma_mz_d = self.sigma_m_rd['z']
485
+ f_m_d = self.f_type_rd
486
+ K_h_y = self.K_h['y']
487
+ K_h_z = self.K_h['z']
488
+ K_m = self.K_m
489
+ K_crit = self.K_crit[1]
490
+
491
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
492
+ def base():
493
+ taux_6_11 = sigma_my_d / (f_m_d * K_h_y) + K_m * sigma_mz_d / (f_m_d * K_h_z) # equ6.11
494
+ taux_6_12 = K_m * sigma_my_d / (f_m_d * K_h_y) + sigma_mz_d / (f_m_d * K_h_z) # equ6.12
495
+ taux_6_33y = sigma_my_d / (f_m_d * K_h_y * K_crit) # equ6.33
496
+ taux_6_33z = sigma_mz_d / (f_m_d * K_h_z * K_crit) # equ6.33
497
+ return taux_6_11, taux_6_12, taux_6_33y, taux_6_33z
498
+
499
+ base_val = base()
500
+ latex = base_val[0]
501
+ self.taux_m_rd['equ6.11'] = base_val[1][0]
502
+ self.taux_m_rd['equ6.12'] = base_val[1][1]
503
+ self.taux_m_rd['equ6.33y'] = base_val[1][2]
504
+ self.taux_m_rd['equ6.33z'] = base_val[1][3]
505
+
506
+
507
+ if compression and isinstance(compression, Compression):
508
+ sigma_c_0_d = compression.sigma_c_0_rd
509
+ f_c_0_d = compression.f_type_rd
510
+ K_c_y = compression.kc_Axe[1]['y']
511
+ K_c_z = compression.kc_Axe[1]['z']
512
+ taux_6_2 = compression.taux_c_0_rd['equ6.2']
513
+ # taux_6_23 = compression.taux_c_0_rd['equ6.23']
514
+ # taux_6_24 = compression.taux_c_0_rd['equ6.24']
515
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
516
+ def comp(taux_6_11, taux_6_12, taux_6_2, taux_6_33y, taux_6_33z):
517
+ taux_6_19 = taux_6_2**2 + taux_6_11 # equ6.19
518
+ taux_6_20 = taux_6_2**2 + taux_6_12 # equ6.20
519
+ taux_6_23 = sigma_c_0_d / (f_c_0_d * K_c_y) # equ6.23
520
+ taux_6_24 = sigma_c_0_d / (f_c_0_d * K_c_z) #equ6.24
521
+ taux_6_35zyz = taux_6_33y** 2 + (sigma_mz_d / (f_m_d * K_h_z)) + taux_6_24 # equ6.35
522
+ taux_6_35yzz = taux_6_33y + (sigma_mz_d / (f_m_d * K_h_z)) ** 2 + taux_6_24 # equ6.35 interprétation
523
+ taux_6_35yzy = taux_6_33z** 2 + (sigma_my_d / (f_m_d * K_h_y)) + taux_6_23 # equ6.35
524
+ taux_6_35zyy = taux_6_33z + (sigma_my_d / (f_m_d * K_h_y)) ** 2 + taux_6_23 # equ6.35 interprétation
525
+ return taux_6_19, taux_6_20, taux_6_35zyz, taux_6_35yzz, taux_6_35yzy, taux_6_35zyy
526
+
527
+ compression_val = comp(self.taux_m_rd['equ6.11'], self.taux_m_rd['equ6.12'], taux_6_2, self.taux_m_rd['equ6.33y'], self.taux_m_rd['equ6.33z'])
528
+ latex = latex + compression_val[0]
529
+ self.taux_m_rd['equ6.19'] = compression_val[1][0]
530
+ self.taux_m_rd['equ6.20'] = compression_val[1][1]
531
+ self.taux_m_rd['equ6.35zyz'] = compression_val[1][2] # 1er item axe de flexion pas au carré, 2eme item axe de flexion au carré, 3eme axe de compression
532
+ self.taux_m_rd['equ6.35yzz'] = compression_val[1][3]
533
+ self.taux_m_rd['equ6.35yzy'] = compression_val[1][4]
534
+ self.taux_m_rd['equ6.35zyy'] = compression_val[1][5]
535
+
536
+ if traction and isinstance(traction, Traction):
537
+ taux_6_1 = traction.taux_t_0_rd['equ6.1']
538
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
539
+ def tract(taux_6_11, taux_6_12):
540
+ taux_6_17 = taux_6_11 + taux_6_1 # equ6.17
541
+ taux_6_18 = taux_6_12 + taux_6_1 # equ6.18
542
+ return taux_6_17, taux_6_18
543
+
544
+ traction_val = tract(self.taux_m_rd['equ6.11'], self.taux_m_rd['equ6.12'])
545
+ latex = latex + traction_val[0]
546
+ self.taux_m_rd['equ6.11'] = traction_val[1][0]
547
+ self.taux_m_rd['equ6.12'] = traction_val[1][1]
548
+
549
+ return (latex, self.taux_m_rd)
550
+
551
+
552
+
553
+ # ================================ Traction ==================================
554
+
555
+ class Traction(Barre):
556
+ def __init__(self, *args, **kwargs):
557
+ """Classe permettant le calcul de la Traction d'un élément bois selon l'EN 1995.
558
+ Cette classe est hérité de la classe Barre, provenant du module EC5_Element_droit.py.
559
+ """
560
+ super().__init__(*args, **kwargs)
561
+
562
+
563
+ @property
564
+ def K_h(self):
565
+ """ Retourne le coef. Kh qui peut augmenter la resistance caractéristique fm,k et ft,k """
566
+ return self._K_h()
567
+
568
+
569
+ def f_t_0_d(self, loadtype=Barre.LOAD_TIME, typecombi=Barre.TYPE_ACTION):
570
+ """Retourne la résistance f,t,0,d de l'élément en MPa
571
+
572
+ Args:
573
+ loadtype (str): chargement de plus courte durée sur l'élément.
574
+ typecombi (str): type de combinaison, fondamentale ou accidentelle.
575
+
576
+ Returns:
577
+ float: f,t,0,d en MPa
578
+ """
579
+ return super()._f_type_d("ft0k", loadtype, typecombi)
580
+
581
+
582
+ def sigma_t_0_d(self, Ft0d: si.kN):
583
+ """ Retourne la contrainte de traxion axial en MPa avec:
584
+ Ft0d : la charge en kN de compression """
585
+ self.Ft_0_d = Ft0d * si.kN
586
+ Ft_0_d = self.Ft_0_d
587
+ A = self.aire
588
+
589
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
590
+ def val():
591
+ sigma_t_0_d = Ft_0_d / A
592
+ return sigma_t_0_d
593
+ value = val()
594
+ self.sigma_t_0_rd = value[1]
595
+ return value
596
+
597
+
598
+ def taux_t_0_d(self):
599
+ """Retourne le taux de travail en traction axial.
600
+
601
+ Returns:
602
+ float: taux de travail en %
603
+ """
604
+ self.taux_t_0_rd = {}
605
+ K_h_y = self.K_h['y']
606
+ K_h_z = self.K_h['z']
607
+ sigma_t_0_d = self.sigma_t_0_rd
608
+ f_t_0_d = self.f_type_rd
609
+
610
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
611
+ def val():
612
+ K_h = min(K_h_y, K_h_z)
613
+ taux_6_1 = sigma_t_0_d / (K_h * f_t_0_d) # equ6.1
614
+ return taux_6_1
615
+ value = val()
616
+
617
+ self.taux_t_0_rd['equ6.1'] = value[1]
618
+ return value
619
+
620
+
621
+ # ================================ Compression ==================================
622
+
623
+ class Compression(Barre):
624
+ COEF_LF = {"Encastré 1 côté" : 2,
625
+ "Rotule - Rotule" : 1,
626
+ "Encastré - Rotule" : 0.7,
627
+ "Encastré - Encastré" : 0.5,
628
+ "Encastré - Rouleau" : 1}
629
+ def __init__(self, lo_y: si.mm, lo_z: si.mm, type_appuis: str=COEF_LF, *args, **kwargs):
630
+ """ Classe permettant le calcul de la Compression d'un élément bois selon l'EN 1995.
631
+ Cette classe est hérité de la classe Barre, provenant du module EC5_Element_droit.py.
632
+
633
+ Args:
634
+ lo : Longueur de flambement suivant l'axe de rotation (y ou z) en mm si pas de flambement alors 0
635
+ type_appuis : Coefficient multiplicateur de la longueur pour obtenir la longeur efficace de flambement en
636
+ fonction des du type d'appuis :
637
+ Encastré 1 côté : 2
638
+ Rotule - Rotule : 1
639
+ Encastré - Rotule : 0.7
640
+ Encastré - Encastré : 0.5
641
+ Encastré - Rouleau : 1
642
+ """
643
+
644
+ super().__init__(*args, **kwargs)
645
+ self.lo_comp = {"y":lo_y * si.mm, "z":lo_z * si.mm}
646
+ self.lo_y = self.lo_comp['y']
647
+ self.lo_z = self.lo_comp['z']
648
+ self.type_appuis = type_appuis
649
+ self.coef_lef = __class__.COEF_LF[type_appuis]
650
+
651
+ @property
652
+ def lamb(self):
653
+ """ Retourne l'élancement d'un poteau en compression avec risque de flambement suivant son axe de rotation """
654
+ lo_y = self.lo_comp['y'].value * 10**3
655
+ lo_z = self.lo_comp['z'].value * 10**3
656
+ coef_lef = self.coef_lef
657
+ I_y = self.inertie[0].value * 10**12
658
+ I_z = self.inertie[1].value * 10**12
659
+ A = self.aire.value * 10**6
660
+
661
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
662
+ def val():
663
+ lamb_y = (lo_y * coef_lef) / sqrt(I_y / A)
664
+ lamb_z = (lo_z * coef_lef) / sqrt(I_z / A)
665
+ return {'y': lamb_y, 'z': lamb_z}
666
+ return val()
667
+
668
+
669
+ @property
670
+ def lamb_rel_Axe(self):
671
+ """ Retourne l'élancement relatif d'un poteau en compression avec risque de flambement suivant son axe de rotation """
672
+ lamb_y = self.lamb[1]['y']
673
+ lamb_z = self.lamb[1]['z']
674
+ f_c0k = float(self.caract_meca.loc['fc0k']) * si.MPa
675
+ E_0_05 = int(self.caract_meca.loc['E005']) * si.MPa
676
+
677
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
678
+ def val():
679
+ lamb_rel_y = (lamb_y / pi) * sqrt(f_c0k / E_0_05)
680
+ lamb_rel_z = (lamb_z / pi) * sqrt(f_c0k / E_0_05)
681
+ return {'y': lamb_rel_y, 'z': lamb_rel_z}
682
+ return val()
683
+
684
+
685
+ @property
686
+ def beta_C(self):
687
+ if self.type_bois == 'Massif':
688
+ betaC = 0.2
689
+ else:
690
+ betaC = 0.1
691
+ return betaC
692
+
693
+
694
+ @property
695
+ def k_Axe(self):
696
+ """ Retourne le facteur Ky ou Kz (fonction de l'axe de flambement) """
697
+ beta_C = self.beta_C
698
+ lamb_rel_y = self.lamb_rel_Axe[1]['y']
699
+ lamb_rel_z = self.lamb_rel_Axe[1]['z']
700
+
701
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
702
+ def val():
703
+ k_y = 0.5 * (1 + beta_C * (lamb_rel_y - 0.3) + lamb_rel_y ** 2)
704
+ k_z = 0.5 * (1 + beta_C * (lamb_rel_z - 0.3) + lamb_rel_z ** 2)
705
+ return {'y': k_y, 'z': k_z}
706
+ return val()
707
+
708
+
709
+ @property
710
+ def kc_Axe(self):
711
+ """ Retourne le coefficient multiplicateur KcAxe (axe = y ou z suivant axe de rotation en flambement) de fc,0,d """
712
+ k_y = self.k_Axe[1]['y']
713
+ k_z = self.k_Axe[1]['z']
714
+ lamb_rel_y = self.lamb_rel_Axe[1]['y']
715
+ lamb_rel_z = self.lamb_rel_Axe[1]['z']
716
+
717
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
718
+ def val():
719
+ k_c_y = 1 / (k_y + sqrt(k_y** 2 - lamb_rel_y ** 2))
720
+ k_c_z = 1 / (k_z + sqrt(k_z** 2 - lamb_rel_z ** 2))
721
+ return {'y': min(k_c_y, 1), 'z': min(k_c_z, 1)}
722
+ return val()
723
+
724
+
725
+ def f_c_0_d(self, loadtype=Barre.LOAD_TIME, typecombi=Barre.TYPE_ACTION):
726
+ """Retourne la résistance f,c,0,d de l'élément en MPa
727
+
728
+ Args:
729
+ loadtype (str): chargement de plus courte durée sur l'élément.
730
+ typecombi (str): type de combinaison, fondamentale ou accidentelle.
731
+
732
+ Returns:
733
+ float: f,c,0,d en MPa
734
+ """
735
+ return super()._f_type_d("fc0k", loadtype, typecombi)
736
+
737
+
738
+ def sigma_c_0_d(self, Fc0d: si.kN):
739
+ """ Retourne la contrainte de compression axial en MPa avec:
740
+ Fc0d : la charge en kN de compression """
741
+ self.Fc_0_d = Fc0d * si.kN
742
+ Fc_0_d = self.Fc_0_d
743
+ A = self.aire
744
+
745
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
746
+ def val():
747
+ sigma_c_0_d = Fc_0_d / A
748
+ return sigma_c_0_d
749
+ value = val()
750
+ self.sigma_c_0_rd = value[1]
751
+ return value
752
+
753
+
754
+ def taux_c_0_d(self, flexion: object=None):
755
+ """Retourne les taux de travaux de la compression axial.
756
+ Si l'élement est un poteau (donc avec un travail principalement en compression) et de la flexion combinée (EN 1995-1-1 §6.3.2),
757
+ il est possible d'ajouter l'objet flexion et de vérifier cette combinaison.
758
+
759
+ Args:
760
+ flexion (object, optional): L'objet Flexion avec ces taux de travaux préalablement calculés. Default to None.
761
+
762
+ Returns:
763
+ list: retourne la liste des taux de travaux en %
764
+ """
765
+ self.taux_c_0_rd = {}
766
+ sigma_c_0_d = self.sigma_c_0_rd
767
+ f_c_0_d = self.f_type_rd
768
+ lamb_rel_y = self.lamb_rel_Axe[1]['y']
769
+ lamb_rel_z = self.lamb_rel_Axe[1]['z']
770
+ K_c_y = self.kc_Axe[1]['y']
771
+ K_c_z = self.kc_Axe[1]['z']
772
+
773
+ if flexion and isinstance(flexion, Flexion):
774
+ taux_6_11 = flexion.taux_m_rd["equ6.11"]
775
+ taux_6_12 = flexion.taux_m_rd["equ6.12"]
776
+ else:
777
+ taux_6_11 = 0
778
+ taux_6_12 = 0
779
+
780
+ if lamb_rel_y < 0.3 and lamb_rel_z < 0.3:
781
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
782
+ def val():
783
+ taux_6_2 = sigma_c_0_d / f_c_0_d # equ6.2
784
+ taux_6_19 = (sigma_c_0_d / (f_c_0_d * K_c_y))**2 + taux_6_11 # equ6.19
785
+ taux_6_20 = (sigma_c_0_d / (f_c_0_d * K_c_z))**2 + taux_6_12 # equ6.20
786
+ return taux_6_2, taux_6_19, taux_6_20
787
+ value = val()
788
+ self.taux_c_0_rd['equ6.19'] = value[1][1]
789
+ self.taux_c_0_rd['equ6.20'] = value[1][2]
790
+ else:
791
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
792
+ def val():
793
+ taux_6_2 = sigma_c_0_d / f_c_0_d # equ6.2
794
+ taux_6_23 = sigma_c_0_d / (f_c_0_d * K_c_y) + taux_6_11 # equ6.23
795
+ taux_6_24 = sigma_c_0_d / (f_c_0_d * K_c_z) + taux_6_12 # equ6.24
796
+ return taux_6_2, taux_6_23, taux_6_24
797
+ value = val()
798
+ self.taux_c_0_rd['equ6.23'] = value[1][1]
799
+ self.taux_c_0_rd['equ6.24'] = value[1][2]
800
+
801
+ self.taux_c_0_rd['equ6.2'] = value[1][0]
802
+ return value
803
+
804
+
805
+
806
+ # ================================ COMPRESSION PERPENDICULAIRE ==================================
807
+
808
+ class Compression_perpendiculaire(Barre):
809
+ TYPE_APPUIS = ("Appuis discret", "Appuis continu")
810
+ def __init__(self, b_appuis:si.mm, l_appuis: si.mm, l1d: si.mm=10000, l1g: si.mm=10000, ad: si.mm=0, ag: si.mm=0, type_appuis_90: str=TYPE_APPUIS, *args, **kwargs):
811
+ """Classe intégrant les formules de compression perpendiculaire selon l'EN 1995 §6.1.5.
812
+ Cette classe est hérité de la classe Barre, provenant du module EC5_Element_droit.py.
813
+
814
+ Args:
815
+ b_appuis(int): largeur d'appuis en mm.
816
+ l_appuis(int): longeur de l'appuis en mm.
817
+ l1d(int) : Distance entre les charges en mm (l et l) (si pas de l1d ne rien mettre).
818
+ l1g(int) : Distance entre les charges en mm (l et l) (si pas de l1g ne rien mettre).
819
+ ad(int) : Distance depuis le bord jusqu'à l'appuis à droite (l) en mm (si pas de ad et au bord ne rien mettre).
820
+ ag(int) : Distance depuis le bord jusqu'à l'appuis à gauche (l) en mm (si pas de ad et au bord ne rien mettre).
821
+ type_appuis_90(str) : Type d'appuis (Appui continu, Appui discret)
822
+ """
823
+
824
+ super().__init__(*args, **kwargs)
825
+ self.b_appuis = b_appuis * si.mm
826
+ self.l_appuis = l_appuis * si.mm
827
+ self.l1d = l1d * si.mm
828
+ self.l1g = l1g * si.mm
829
+ self.ad = ad * si.mm
830
+ self.ag = ag * si.mm
831
+ self.type_appuis_90 = type_appuis_90
832
+
833
+
834
+ @property
835
+ def K_c90(self):
836
+ """ Retourne le facteur Kc,90 qui tient compte de la configuration de chargement, du fendage et de la déformation
837
+ en compression avec pour argument :
838
+ h : Hauteur de l'élement subissant la compression en mm
839
+ lO : Longeur de l'appuis en compression en mm
840
+ l1 : Distance la plus petite entre deux appuis en mm (l et l)
841
+ """
842
+ if self.l1d == 0 and self.l1g > 0:
843
+ l1 = self.l1g
844
+ self.ag = self.l1g
845
+ elif self.l1g == 0 and self.l1d > 0:
846
+ l1 = self.l1d
847
+ self.ad = self.l1d
848
+ else:
849
+ l1 = min(self.l1d, self.l1g)
850
+
851
+ if self.type_appuis_90 == "Appuis discret":
852
+ if self.type_bois == 'Massif':
853
+ if self.h_calcul.value * 10**3 <= 300:
854
+ if l1 >= 2 * self.h_calcul:
855
+ kc_90 = 1.5
856
+ else:
857
+ kc_90 = 1
858
+ else:
859
+ kc_90 = 1.5
860
+ elif self.type_bois == 'BLC':
861
+ if self.h_calcul.value * 10**3 <= 300 and self.l_appuis.value * 10**3 <= 400:
862
+ if l1 >= 2 * self.h_calcul:
863
+ kc_90 = 1.75
864
+ else:
865
+ kc_90 = 1
866
+ elif self.h_calcul.value * 10**3 <= 300 and self.l_appuis.value * 10**3 > 400:
867
+ kc_90 = 1
868
+ else:
869
+ kc_90 = 1.75
870
+ else:
871
+ if self.h_calcul.value * 10**3 > 300:
872
+ kc_90 = 1.75
873
+ else:
874
+ kc_90 = 1
875
+ else:
876
+ if self.type_bois == 'Massif':
877
+ if self.h_calcul.value * 10**3 <= 300:
878
+ if l1 >= 2 * self.h_calcul:
879
+ kc_90 = 1.25
880
+ else:
881
+ kc_90 = 1
882
+ else:
883
+ kc_90 = 1.5
884
+ elif self.type_bois == 'BLC':
885
+ if self.h_calcul.value * 10**3 <= 300:
886
+ if l1 >= 2 * self.h_calcul:
887
+ kc_90 = 1.5
888
+ else:
889
+ kc_90 = 1
890
+ else:
891
+ kc_90 = 1.75
892
+ else:
893
+ if self.h_calcul.value * 10**3 > 300:
894
+ kc_90 = 1.75
895
+ else:
896
+ kc_90 = 1
897
+
898
+ return kc_90
899
+
900
+
901
+ def f_c_90_d(self, loadtype=Barre.LOAD_TIME, typecombi=Barre.TYPE_ACTION):
902
+ """Retourne la résistance f,c,90,d de l'élément en MPa
903
+
904
+ Args:
905
+ loadtype (str): chargement de plus courte durée sur l'élément.
906
+ typecombi (str): type de combinaison, fondamentale ou accidentelle.
907
+
908
+ Returns:
909
+ float: f,c,90,d en MPa
910
+ """
911
+ return super()._f_type_d("fc90k", loadtype, typecombi)
912
+
913
+
914
+ def sigma_c_90_d(self, Fc90d: si.kN):
915
+ """ Retourne la contrainte normal de compression à 90 degrés en MPa avec pour argument:
916
+
917
+ Fc90d : Charge en compression perpendiculaire en kN
918
+ """
919
+
920
+ self.Fc90d = Fc90d * si.kN
921
+ Fc_90_d = self.Fc90d
922
+ l_appuis = self.l_appuis
923
+ b_appuis = self.b_appuis
924
+ l_1d = self.l1d
925
+ l_1g = self.l1g
926
+ ad = self.ad
927
+ ag = self.ag
928
+ mm = si.mm
929
+
930
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
931
+ def val():
932
+ a_ef = (l_appuis + min(30*mm, ad, l_appuis, 0.5*l_1d) + min(30*mm, ag, l_appuis, 0.5*l_1g)) * b_appuis
933
+ sigma_c_90_d = Fc_90_d / a_ef
934
+ return sigma_c_90_d
935
+ value = val()
936
+ self.sigma_c_90_rd = value[1]
937
+ return value
938
+
939
+
940
+ def taux_c_90_d(self):
941
+ """ Retourne le taux de travail de la compression perpendiculaire """
942
+ self.taux_c_90_rd = {}
943
+ sigma_c_90_d = self.sigma_c_90_rd
944
+ K_c90 = self.K_c90
945
+ f_c_90_d = self.f_type_rd
946
+
947
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
948
+ def val():
949
+ taux_6_3 = sigma_c_90_d / (K_c90 * f_c_90_d) # equ6.3
950
+ return taux_6_3
951
+
952
+ value = val()
953
+ self.taux_c_90_rd['equ6.3'] = value[1]
954
+ return value
955
+
956
+
957
+ def show_c90(self):
958
+ """Affiche l'image des caractéristiques d'une compression perpendiculaire
959
+ """
960
+ self._show_element("C90_def.png")
961
+
962
+
963
+
964
+ class Compression_inclinees(Compression, Compression_perpendiculaire):
965
+ def __init__(self, alpha: float=45, **kwargs):
966
+ """Classe qui permet de calculer la compression inclinées par rapport au fil comme décrit à l'EN 1995 §6.2.2.
967
+ Cette classe est hérité de la classe Compression et Compression_perpendiculaire, les deux provenants du module EC5_Element_droit.py.
968
+
969
+ Args:
970
+ alpha (float, optional): angle d'inclinaison en degrés de la compression. Defaults to 0.
971
+ """
972
+ # super(Compression, self).__init__(**kwargs)
973
+ # super(Compression_perpendiculaire, self).__init__(**kwargs)
974
+ super().__init__(**kwargs)
975
+ self.alpha = alpha
976
+
977
+ def sigma_c_alpha_d(self, Fcad: si.kN):
978
+ """ Retourne la contrainte de compression inclinée en MPa avec:
979
+ Fcad : la charge en kN de compression inclinée """
980
+ b_appuis = self.b_appuis
981
+ l_appuis = self.l_appuis
982
+ self.Fc_alpha_d = Fcad * si.kN
983
+ Fc_alpha_d = self.Fc_alpha_d
984
+
985
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
986
+ def val():
987
+ A = b_appuis * l_appuis
988
+ sigma_c_alpha_d = Fc_alpha_d / A
989
+ return sigma_c_alpha_d
990
+
991
+ value = val()
992
+ self.sigma_c_alpha_rd = value[1]
993
+ return value
994
+
995
+
996
+ def taux_c_alpha_d(self, loadtype=Barre.LOAD_TIME, typecombi=Barre.TYPE_ACTION):
997
+ """ Retourne le taux de travail de la compression inclinées par rapport au fil """
998
+ self.taux_c_alpha_rd = {}
999
+ f_c_0_d = self.f_c_0_d(loadtype, typecombi)[1]
1000
+ f_c_90_d = self.f_c_90_d(loadtype, typecombi)[1]
1001
+ alpha = self.alpha
1002
+ K_c90 = self.K_c90
1003
+ sigma_c_alpha_d = self.sigma_c_alpha_rd
1004
+
1005
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1006
+ def val():
1007
+ taux_6_16 = sigma_c_alpha_d / (f_c_0_d / ((f_c_0_d /(K_c90 * f_c_90_d)) * sin(radians(alpha))**2 + cos(radians(alpha))**2)) # equ6.16
1008
+ return taux_6_16
1009
+
1010
+ value = val()
1011
+ self.taux_c_alpha_rd['equ6.16'] = value[1]
1012
+ return value
1013
+
1014
+
1015
+
1016
+ # ================================ CISAILLEMENT ==================================
1017
+
1018
+ class Cisaillement(Barre):
1019
+ DICT_KN = {"Massif": 5,"BLC": 6.5, "LVL": 4.5}
1020
+ def __init__(self, **kwargs):
1021
+ """Classe qui permet de calculer le cisaillement d'une poutre comme décrit à l'EN 1995 §6.1.7 et §6.5.
1022
+ Cette classe est hérité de la classe Barre, provenant du module EC5_Element_droit.py.
1023
+ """
1024
+ super().__init__(**kwargs)
1025
+ self.K_v = 1
1026
+ self.h_ef = self.h_calcul
1027
+
1028
+ @property
1029
+ def K_cr(self):
1030
+ """ Retourne le facteur de réduction de largeur Kcr avec pour argument:
1031
+ cs: Classe de service de la poutre
1032
+ CS 1 : 1
1033
+ CS 2 : 2
1034
+ CS 3 : 3
1035
+ h : Hauteur en mm
1036
+ type_bois : Type de bois
1037
+ Massif : 0
1038
+ BLC : 1
1039
+ Autre : 2 """
1040
+ if self.cs == 1:
1041
+ if self.h_calcul.value * 10**3 > 150 and self.type_bois == "Massif":
1042
+ return 0.67
1043
+ else:
1044
+ return 1
1045
+ elif self.cs == 2:
1046
+ if self.h_calcul.value * 10**3 > 150 and self.type_bois == "Massif":
1047
+ return 0.67
1048
+ elif self.type_bois == "BLC":
1049
+ return 0.67
1050
+ else:
1051
+ return 1
1052
+ else:
1053
+ return 0.67
1054
+
1055
+
1056
+ def Kv(self, hef:si.mm, x:si.mm, i_lo:si.mm, ent=("Dessous", "Dessus")):
1057
+ """Retourne le facteur d'entaille Kv pour une entaille au niveau d'un appuis
1058
+
1059
+ Args:
1060
+ hef (int): Hauteur efficace de la poutre (hauteur - hauteur de l'entaille) en mm
1061
+ x (int):Distance entre le centre de réaction à l'appuis et le coin de l'entaille en mm
1062
+ i_lo (float): longueur horizontal de l'entaille en mm
1063
+ ent (tuple, optional): Entaille sur le dessus ou dessous de la poutre.
1064
+
1065
+ Returns:
1066
+ float: facteur Kv
1067
+ """
1068
+ K_n = self.DICT_KN[self.type_bois]
1069
+ x = x * si.mm
1070
+ h_ef = hef * si.mm
1071
+ i = i_lo * si.mm / h_ef
1072
+ h_calcul = self.h_calcul
1073
+ print(h_ef, h_calcul)
1074
+
1075
+ self.h_ef = h_ef
1076
+ if ent == "Dessus":
1077
+ self.K_v = 1
1078
+ return self.K_v
1079
+ else:
1080
+ @handcalc(override="long", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1081
+ def val():
1082
+ alpha = h_ef / h_calcul
1083
+ K_v = min(1,(K_n * (1 + (1.1 * i ** 1.5) / sqrt(h_calcul))) / (sqrt(h_calcul) * (sqrt(alpha * (1 - alpha)) + 0.8 * x / h_calcul * sqrt(1 / alpha - alpha ** 2))))
1084
+ return K_v
1085
+ value = val()
1086
+ self.K_v = value[1]
1087
+ return value
1088
+
1089
+
1090
+ def f_v_d(self, loadtype=Barre.LOAD_TIME, typecombi=Barre.TYPE_ACTION):
1091
+ """Retourne la résistance f,v,d de l'élément en MPa
1092
+
1093
+ Args:
1094
+ loadtype (str): chargement de plus courte durée sur l'élément.
1095
+ typecombi (str): type de combinaison, fondamentale ou accidentelle.
1096
+
1097
+ Returns:
1098
+ float: f,v,d en MPa
1099
+ """
1100
+ return super()._f_type_d("fvk", loadtype, typecombi)
1101
+
1102
+
1103
+ def tau_d(self, Vd:si.kN):
1104
+ """ Retourne la contrainte tau en MPa pour le cisaillement longitudinale d'une poutre rectangulaire
1105
+ Vd : Effort de cisaillement sur la poutre en kN"""
1106
+ self.V_d = Vd * si.kN
1107
+ V_d = self.V_d
1108
+ K_cr = self.K_cr
1109
+ b_calcul = self.b_calcul
1110
+ h_ef = self.h_ef
1111
+
1112
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1113
+ def val():
1114
+ b_ef = K_cr * b_calcul
1115
+ tau_d = (1.5 * V_d) / (b_ef * h_ef)
1116
+ return tau_d
1117
+
1118
+ value = val()
1119
+ self.tau_rd = value[1]
1120
+ return value
1121
+
1122
+
1123
+ def taux_tau_d(self):
1124
+ """ Retourne le taux de travail en cisaillement en % """
1125
+ self.taux_tau_rd = {}
1126
+ tau_d = self.tau_rd
1127
+ f_v_d = self.f_type_rd
1128
+ K_v = self.K_v
1129
+
1130
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1131
+ def val():
1132
+ taux_6_13 = tau_d / f_v_d
1133
+ taux_6_60 = tau_d/ (K_v * f_v_d)
1134
+ return taux_6_13, taux_6_60
1135
+
1136
+ value = val()
1137
+ self.taux_tau_rd['equ6.13'] = value[1][0]
1138
+ self.taux_tau_rd['equ6.60'] = value[1][1]
1139
+ return value
1140
+
1141
+
1142
+ def show_Kv(self):
1143
+ """Affiche l'image des caractéristiques d'une entaille au cisaillement
1144
+ """
1145
+ self._show_element("Kv_def.png")
1146
+
1147
+
1148
+ # ================================ Barre assemblées mécaniquement Annexe B ==================================
1149
+
1150
+ # class Poutre_assemblee_meca(Projet):
1151
+ # def __init__(self, beam_2:object, l: si.mm, disposition: str=["Latérale", "Dessus / Dessous"], recouvrement: list=[0,0], Ki: list=[0,None,0], entraxe: list=[1, None, 1], psy_2: int|float=0, **kwargs):
1152
+ # """Classe définitssant une poutre composée d'au maximum 3 éléments connectés entre eux par liaisons mécanique
1153
+ # suivant la théorie de HEIMESHOFF Annexe B de l'EN 1995
1154
+ # Args:
1155
+ # beam_2 (object): objet contenant l'élément centrale de la poutre i=2, cette objet doit être issu de la classe élément ou de son héritage
1156
+ # l (int | float): longueur de la poutre en mm
1157
+ # disposition (str): Disposition des éléments supplémentaires à l'élément 2, "Latérale" ou "Dessus / Dessous"
1158
+ # recouvrement (int): Si disposition latérale alors donner un recouvrement en mm.
1159
+ # Cela correspond à la distance entre le centre géométrique de la pièce 2 et celui de la pièce i.
1160
+ # ATTENTION z local est vers le bas quand vous donnez le recouvrement.
1161
+
1162
+ # Ki (list, optional): Rigidité de liaison par connecteur entre les éléments entre i=1/2 et i=2/3, en N/mm. Soit Kser soit Ku en fonction du type de vérification
1163
+ # S'il n'y a que 2 éléments connectés, laisser l'index correspondant vide (ex: [0, 2000]). Defaults to [0,None,0].
1164
+
1165
+ # entraxe (list, optional): Entraxe entre connecteur en mm suivant i=1 ou i=3. Defaults to [1, None, 1].
1166
+ # type_action (int | float, optional): Psy 2 qui permet de prendre en compte le fluage dans le temps,
1167
+ # si calcul en instantanée alors 0,
1168
+ # si intermédiaire = voir dans data/coeff_psy.csv
1169
+ # et enfin temps infini = 1.
1170
+ # Defaults to 0.
1171
+
1172
+ # **kwargs (object): beam_1 et ou beam_3
1173
+ # """
1174
+ # super().__init__(**kwargs)
1175
+ # self.beam = [None , beam_2, None]
1176
+ # self.l = l * si.mm
1177
+ # self.disposition = disposition
1178
+ # self.recouvrement = [recouvrement[0]*si.mm, recouvrement[1]*si.mm]
1179
+ # self.entraxe = []
1180
+ # self.Ki = []
1181
+ # for i in range(3):
1182
+ # if entraxe[i]:
1183
+ # self.entraxe.append(entraxe[i] * si.mm)
1184
+ # else:
1185
+ # self.entraxe.append(None)
1186
+ # if Ki[i]:
1187
+ # self.Ki.append(Ki[i] * si.N / si.mm)
1188
+ # else:
1189
+ # self.Ki.append(None)
1190
+
1191
+ # for key, value in kwargs.items():
1192
+ # match key[0:4]:
1193
+ # case "beam" if key[-1] == "2":
1194
+ # print("L'attribut ne peut pas être nommé beam_2, il est déjà pris par l'élément centrale ! beam_1 ou beam_3 possible !")
1195
+ # case "beam" if key[-1] != "2" and 1<= int(key[-1]) <=3 :
1196
+ # self.beam[int(key[-1])-1] = value
1197
+ # for index, beam in enumerate(self.beam):
1198
+ # if beam is not None:
1199
+ # beam.Emean_fin(psy_2)
1200
+
1201
+
1202
+ # @property
1203
+ # def K_def(self):
1204
+ # kdef = (None, 0)
1205
+ # for index, beam in enumerate(self.beam):
1206
+ # if beam is not None and index != 1:
1207
+ # K_def_i = beam.K_def
1208
+ # K_def_2 = self.beam[1].K_def
1209
+ # if K_def_i != K_def_2:
1210
+ # @handcalc(override="short", precision=0, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1211
+ # def val():
1212
+ # K_def = 2 * sqrt(K_def_i * K_def_2)
1213
+ # return K_def
1214
+ # else:
1215
+ # @handcalc(override="params", precision=0, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1216
+ # def val():
1217
+ # K_def= K_def_2
1218
+ # return K_def
1219
+ # value = val()
1220
+ # if value[1] > kdef[1]:
1221
+ # kdef = value
1222
+ # return kdef
1223
+
1224
+
1225
+ # @property
1226
+ # def Ki_fin(self):
1227
+ # """Renvoie le Ki en fonction des Kdef des pièces assemblées et du psy2"""
1228
+ # ki_fin = {}
1229
+ # for index, beam in enumerate(self.beam):
1230
+ # if beam is not None and index != 1:
1231
+ # K_i = self.Ki[index]
1232
+ # psy_2 = beam.psy_2
1233
+ # K_def = self.K_def[1]
1234
+
1235
+ # @handcalc(override="long", precision=0, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1236
+ # def val():
1237
+ # K_i_fin = K_i / (1 + psy_2 * K_def)
1238
+ # return K_i_fin
1239
+
1240
+ # if index == 0:
1241
+ # ki_fin["Ki fin 1-2"] = val()
1242
+ # else:
1243
+ # ki_fin["Ki fin 2-3"] = val()
1244
+ # return ki_fin
1245
+
1246
+
1247
+ # @property
1248
+ # def gamma_i(self):
1249
+ # """Renvoie le gamma"""
1250
+ # gamma = [0, 1, 0]
1251
+ # gamma = {"gamma 1": None, "gamma 2": 1, "gamma 3": None}
1252
+ # for index, beam in enumerate(self.beam):
1253
+ # if beam is not None and index != 1:
1254
+ # E_mean_fin = beam.E_mean_fin.value * 10 ** -6
1255
+ # A = beam.aire.value * 10 ** 6
1256
+ # entraxe = self.entraxe[index].value*10**3
1257
+ # lo = self.l.value * 10 ** 3
1258
+ # if index == 0:
1259
+ # K_i_fin = self.Ki_fin["Ki fin 1-2"][1].value * 10**-3
1260
+ # else:
1261
+ # K_i_fin = self.Ki_fin["Ki fin 2-3"][1].value * 10**-3
1262
+
1263
+ # @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1264
+ # def val():
1265
+ # gamma_i = (1 + pi ** 2 * E_mean_fin * A * entraxe / (K_i_fin * lo ** 2)) ** (-1)
1266
+ # return gamma_i
1267
+ # gamma["gamma "+str(index+1)] = val()
1268
+ # return gamma
1269
+
1270
+
1271
+ # @property
1272
+ # def distance_ai(self):
1273
+ # """Renvoie la distance à l'axe neutre de la pièce 2"""
1274
+ # denominateur = 0
1275
+ # if self.disposition == "Latérale":
1276
+ # d1 = self.recouvrement[0]
1277
+ # d3 = self.recouvrement[1]
1278
+
1279
+ # else:
1280
+ # h1 = self.beam[0].h_calcul
1281
+ # h2 = self.beam[1].h_calcul
1282
+ # h3 = self.beam[2].h_calcul
1283
+ # d1 = -(h1 + h2)/2
1284
+ # d3 = (h3 + h2)/2
1285
+
1286
+ # for index, beam in enumerate(self.beam):
1287
+ # if beam is not None:
1288
+ # if index == 1:
1289
+ # gamma_i = self.gamma_i["gamma "+str(index+1)]
1290
+ # else:
1291
+ # gamma_i = self.gamma_i["gamma "+str(index+1)][1]
1292
+
1293
+ # denominateur = denominateur + (gamma_i * beam.E_mean_fin * beam.aire)
1294
+
1295
+ # if self.beam[0] == None or self.beam[2] == None:
1296
+ # di = [d1, None, d3]
1297
+ # for index, beam in enumerate(self.beam):
1298
+ # if beam is not None and index != 1:
1299
+ # gamma_i = self.gamma_i["gamma "+str(index+1)][1]
1300
+ # numerateur = gamma_i * beam.E_mean_fin * beam.aire * di[index]
1301
+ # else:
1302
+ # numerateur = (self.gamma_i["gamma 1"][1] * self.beam[0].E_mean_fin * self.beam[0].aire * d1
1303
+ # - self.gamma_i["gamma 3"][1] * self.beam[2].E_mean_fin * self.beam[2].aire * d3)
1304
+ # a2 = numerateur / denominateur
1305
+ # ai = [None, -a2, None]
1306
+ # for index, beam in enumerate(self.beam):
1307
+ # if beam is not None and index != 1:
1308
+ # di = [d1, None, d3]
1309
+ # ai[index] = di[index] - a2
1310
+ # return ai
1311
+
1312
+ # @property
1313
+ # def EI_eff (self):
1314
+ # """Renvoie la rigidité de la poutre connectée"""
1315
+ # EIeff_latex = ""
1316
+ # EIeff_value = 0
1317
+ # for index, beam in enumerate(self.beam):
1318
+ # if beam is not None:
1319
+ # if index == 1:
1320
+ # gamma_i = self.gamma_i["gamma "+str(index+1)]
1321
+ # else:
1322
+ # gamma_i = self.gamma_i["gamma "+str(index+1)][1]
1323
+
1324
+ # E_mean_fin = beam.E_mean_fin
1325
+ # inertie = beam.inertie[0]
1326
+ # aire = self.beam[index].aire
1327
+ # distance_ai = self.distance_ai[index]
1328
+
1329
+ # @handcalc(override="long", precision=1, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1330
+ # def val():
1331
+ # EI_eff_i = E_mean_fin * inertie + gamma_i * E_mean_fin * aire * distance_ai**2
1332
+ # return EI_eff_i
1333
+ # inter = val()
1334
+ # EIeff_latex += f'EI eff {index+1}: '
1335
+ # EIeff_latex += inter[0]
1336
+ # EIeff_value = EIeff_value + inter[1]
1337
+
1338
+ # @handcalc(override="params", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1339
+ # def sum_EI():
1340
+ # EI_eff_global = EIeff_value # Somme des EI efficace
1341
+ # return EI_eff_global
1342
+ # sumEI = sum_EI()
1343
+ # return (EIeff_latex + sumEI[0], sumEI[1])
1344
+
1345
+
1346
+ # def tau_2_max(self, Vz:float):
1347
+ # """Calcul de la contrainte de cisaillement maximale dans l'élément 2 selon Annexe B.4 de l'EN 1995
1348
+
1349
+ # Args:
1350
+ # vz (float): Effort de cisaillement Vz en kN
1351
+ # """
1352
+
1353
+ # beam_2 = deepcopy(self.beam[1])
1354
+ # K_cr = Cisaillement._from_parent_class(beam_2).K_cr
1355
+
1356
+ # V_z = Vz * si.kN
1357
+ # h = self.beam[1].h_calcul / 2 + self.distance_ai[1]
1358
+ # gamma_3 = self.gamma_i["gamma 3"][1]
1359
+ # E_mean_fin_3 = self.beam[2].E_mean_fin
1360
+ # E_mean_fin_2 = self.beam[1].E_mean_fin
1361
+ # aire_3 = self.beam[2].aire
1362
+ # a_3 = self.distance_ai[2]
1363
+ # b_2 = self.beam[1].b_calcul
1364
+ # EI_eff = self.EI_eff[1]
1365
+
1366
+ # @handcalc(override="long", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1367
+ # def val():
1368
+ # tau_2 = V_z * (gamma_3 * E_mean_fin_3 * aire_3 * a_3 + 0.5 * E_mean_fin_2 * b_2 * h**2) / (b_2 * K_cr * EI_eff)
1369
+ # return tau_2
1370
+ # return val()
1371
+
1372
+
1373
+ # def sigma_i(self, My:float, beam: int=[1, 2, 3]):
1374
+ # """Contrainte de compression parallèle au fil selon Annexe B.3 de l'EN 1995
1375
+
1376
+ # Args:
1377
+ # My (float): Moment selon l'axe y en kN.m
1378
+ # beam (int, optional): Beam 1 = Barre 1
1379
+ # Beam 2 = Barre 2
1380
+ # Beam 3 = Barre 3.
1381
+ # """
1382
+ # Mf_z = My * si.kN*si.m
1383
+ # index = beam
1384
+ # if self.beam[index-1] is not None:
1385
+ # if index == 2:
1386
+ # gamma_i = self.gamma_i["gamma "+str(index)]
1387
+ # else:
1388
+ # gamma_i = self.gamma_i["gamma "+str(index)][1]
1389
+ # E_mean_fin = self.beam[index-1].E_mean_fin
1390
+ # distance_ai = self.distance_ai[index-1]
1391
+ # EI_eff = self.EI_eff[1]
1392
+
1393
+ # @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1394
+ # def val():
1395
+ # sigma_i = Mf_z * gamma_i * E_mean_fin * distance_ai / EI_eff
1396
+
1397
+ # return sigma_i
1398
+ # return val()
1399
+
1400
+
1401
+ # def sigma_mi(self, My:float, beam: int=[1, 2, 3]):
1402
+ # """Contrainte de flexion selon l'axe y selon Annexe B.3 de l'EN 1995
1403
+
1404
+ # Args:
1405
+ # My (float): Moment selon l'axe y en kN.m
1406
+ # beam (int, optional): Beam 1 = Barre 1
1407
+ # Beam 2 = Barre 2
1408
+ # Beam 3 = Barre 3.
1409
+ # """
1410
+ # M_y = My * si.kN*si.m
1411
+ # index = beam
1412
+ # if self.beam[index-1] is not None:
1413
+ # E_mean_fin = self.beam[index-1].E_mean_fin
1414
+ # h_i = self.beam[index-1].h_calcul
1415
+ # EI_eff = self.EI_eff[1]
1416
+
1417
+ # @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1418
+ # def val():
1419
+ # sigma_m_i = 0.5 * M_y * E_mean_fin * h_i / EI_eff
1420
+
1421
+ # return sigma_m_i
1422
+ # return val()
1423
+
1424
+
1425
+ # def F_i(self, Vz:float, connecteur: int=[1,2]):
1426
+ # """Permet de calculer la charge à reprendre par organe d'assemblage selon Annexe B.5 de l'EN 1995
1427
+
1428
+ # Args:
1429
+ # Vz (float): Effort de cisaillement Vz en kN
1430
+ # connecteur (int, optional): Position des connecteurs:
1431
+ # 1 : connecteur entre les planches 1 et 2
1432
+ # 2 : connecteur entre les planches 2 et 3.
1433
+ # Defaults to [1,2].
1434
+ # """
1435
+ # V_z = Vz * si.kN
1436
+ # if connecteur == 1 :
1437
+ # connecteur = 0
1438
+ # gamma_i = self.gamma_i["gamma "+str(connecteur + 1)][1]
1439
+ # E_mean_fin = self.beam[connecteur].E_mean_fin
1440
+ # aire = self.beam[connecteur].aire
1441
+ # distance_ai = self.distance_ai[connecteur]
1442
+ # entraxe = self.entraxe[connecteur]
1443
+ # EI_eff = self.EI_eff[1]
1444
+
1445
+ # @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1446
+ # def val():
1447
+ # F_i = gamma_i * E_mean_fin * aire * distance_ai * entraxe * V_z / EI_eff
1448
+ # return F_i
1449
+ # return val()
1450
+
1451
+
1452
+ # class Poteau_assemble_meca(Poutre_assemblee_meca):
1453
+ # def __init__(self, lo_y: si.mm, lo_z: si.mm, type_appuis: str=Compression.COEF_LF, **kwargs):
1454
+ # super(Poutre_assemblee_meca, self).__init__(**kwargs)
1455
+ # self.lo_comp = {"y":lo_y * si.mm, "z":lo_z * si.mm}
1456
+ # self.pole = []
1457
+ # if not isinstance(self.l, si.Physical):
1458
+ # self.l = self.l * si.mm
1459
+ # for i, beam in enumerate(self.beam):
1460
+ # if beam is not None:
1461
+ # compression = Compression._from_parent_class(beam, lo_y=lo_y, lo_z=lo_z, type_appuis=type_appuis)
1462
+ # self.pole.append(compression)
1463
+ # else:
1464
+ # self.pole.append(None)
1465
+
1466
+ # @property
1467
+ # def aire(self):
1468
+ # """Détermine la surface total du poteau assemblé mécaniquement
1469
+ # """
1470
+ # aire = 0
1471
+ # for beam in self.beam:
1472
+ # if beam is not None:
1473
+ # aire = aire + beam.aire
1474
+ # return aire
1475
+
1476
+ # @property
1477
+ # def Ief(self):
1478
+ # """Détermine l'inertie efficace à partir d'un module d'élasticité moyen Emean et
1479
+ # de la rigidité équivalente en flexion EIef d'une poutre assemblée mécaniquement.
1480
+ # """
1481
+ # E_mean_beams = []
1482
+ # for pole in self.pole:
1483
+ # if pole is not None:
1484
+ # E_mean_beams.append(pole.E_mean_fin)
1485
+ # E_mean = np.mean(E_mean_beams)
1486
+ # EI_ef = self.EI_eff[1]
1487
+
1488
+ # @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1489
+ # def inertie_ef():
1490
+ # I_ef = EI_ef / E_mean # equC.4
1491
+ # return I_ef
1492
+ # return inertie_ef()
1493
+
1494
+ # @property
1495
+ # def lamb_ef(self):
1496
+ # """ Retourne l'élancement d'un poteau assemblé mécaniquement en compression avec risque de flambement suivant l'axe de rotation z donc une direction de flèche suivant y"""
1497
+ # lo_z = self.lo_comp['z'].value * 10**3
1498
+ # I_z_ef = self.Ief[1]
1499
+ # A_tot = self.aire
1500
+
1501
+ # @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1502
+ # def val():
1503
+ # lamb_z_ef = lo_z * sqrt(A_tot / I_z_ef) # equC.3
1504
+ # return lamb_z_ef
1505
+ # return val()
1506
+
1507
+
1508
+ # @property
1509
+ # def lamb(self):
1510
+ # """ Retourne l'élancement d'un poteau en compression avec risque de flambement suivant son axe de rotation """
1511
+ # dict_lamb = {"lamb,ef,z": self.lamb_ef}
1512
+ # for i, pole in enumerate(self.pole):
1513
+ # if pole is not None:
1514
+ # lo_y = self.lo_comp['y'].value * 10**3
1515
+ # coef_lef = pole.coef_lef
1516
+ # I_y = pole.inertie[0].value * 10**12
1517
+ # A = pole.aire.value * 10**6
1518
+
1519
+ # @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1520
+ # def val():
1521
+ # lamb_y = (lo_y * coef_lef) / sqrt(I_y / A)
1522
+ # return lamb_y
1523
+ # dict_lamb["Pole"+str(i+1) + " lamb,y"] = val()
1524
+ # return dict_lamb
1525
+
1526
+
1527
+ # @property
1528
+ # def lamb_rel_Axe(self):
1529
+ # """ Retourne l'élancement relatif d'un poteau en compression avec risque de flambement suivant son axe de rotation """
1530
+ # lamb_ef_z = self.lamb['lamb,ef,z'][1]
1531
+ # E_0_05_beams, f_c0k_beams = [], []
1532
+ # for pole in self.pole:
1533
+ # if pole is not None:
1534
+ # f_c0k_beams.append(float(pole.caract_meca.loc['fc0k'])* si.MPa)
1535
+ # E_0_05_beams.append(float(pole.caract_meca.loc['E005'])* si.MPa)
1536
+ # f_c0k_mean = np.mean(f_c0k_beams)
1537
+ # E_0_05_mean = np.mean(E_0_05_beams)
1538
+
1539
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1540
+ # def lamb_rel_z():
1541
+ # lamb_rel_ef_z = (lamb_ef_z / pi) * sqrt(f_c0k_mean / E_0_05_mean)
1542
+ # return lamb_rel_ef_z
1543
+ # dict_lamb_rel = {"lamb,rel,ef,z": lamb_rel_z()}
1544
+
1545
+ # for i, pole in enumerate(self.pole):
1546
+ # if pole is not None:
1547
+ # f_c0k = float(pole.caract_meca.loc['fc0k']) * si.MPa
1548
+ # E_0_05 = int(pole.caract_meca.loc['E005']) * si.MPa
1549
+ # lamb_y = self.lamb["Pole"+str(i+1) + " lamb,y"][1]
1550
+
1551
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1552
+ # def val():
1553
+ # lamb_rel_y = (lamb_y / pi) * sqrt(f_c0k / E_0_05)
1554
+ # return lamb_rel_y
1555
+ # dict_lamb_rel["Pole"+str(i+1) + " lamb,rel,y"] = val()
1556
+ # return dict_lamb_rel
1557
+
1558
+
1559
+ # @property
1560
+ # def k_Axe(self):
1561
+ # """ Retourne le facteur Ky ou Kz (fonction de l'axe de flambement) """
1562
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1563
+ # def ky(beta_C:float, lamb_rel_y:float):
1564
+ # k_y = 0.5 * (1 + beta_C * (lamb_rel_y - 0.3) + lamb_rel_y ** 2)
1565
+ # return k_y
1566
+
1567
+ # dict_k_axe = {}
1568
+ # beta_C_poles = 0
1569
+ # lamb_rel_ef_z = self.lamb_rel_Axe["lamb,rel,ef,z"][1]
1570
+
1571
+ # for i, pole in enumerate(self.pole):
1572
+ # if pole is not None:
1573
+ # beta_C = pole.beta_C
1574
+ # if beta_C > beta_C_poles:
1575
+ # beta_C_poles = beta_C
1576
+ # lamb_rel_y = self.lamb_rel_Axe["Pole"+str(i+1) + " lamb,rel,y"][1]
1577
+ # dict_k_axe["Pole"+str(i+1) + " ky"] = ky(beta_C, lamb_rel_y)
1578
+
1579
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1580
+ # def kz():
1581
+ # k_ef_y = 0.5 * (1 + beta_C_poles * (lamb_rel_ef_z - 0.3) + lamb_rel_ef_z ** 2)
1582
+ # return k_ef_y
1583
+ # dict_k_axe["k,ef,z"] = kz()
1584
+ # return dict_k_axe
1585
+
1586
+
1587
+ # @property
1588
+ # def kc_Axe(self):
1589
+ # """ Retourne le coefficient multiplicateur KcAxe (axe = y ou z suivant axe de rotation en flambement) de fc,0,d """
1590
+ # lamb_rel_ef_z = self.lamb_rel_Axe["lamb,rel,ef,z"][1]
1591
+ # k_ef_z = self.k_Axe["k,ef,z"][1]
1592
+
1593
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1594
+ # def kcz():
1595
+ # k_c_ef_z = 1 / (k_ef_z + sqrt(k_ef_z** 2 - lamb_rel_ef_z ** 2))
1596
+ # return k_c_ef_z
1597
+
1598
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1599
+ # def kcy(k_y, lamb_rel_y):
1600
+ # k_c_y = 1 / (k_y + sqrt(k_y** 2 - lamb_rel_y ** 2))
1601
+ # return k_c_y
1602
+
1603
+ # dict_kc_axe = {"kc,ef,z": kcz()}
1604
+ # for i, pole in enumerate(self.pole):
1605
+ # if pole is not None:
1606
+ # k_y = self.k_Axe["Pole"+str(i+1) + " ky"][1]
1607
+ # lamb_rel_y = self.lamb_rel_Axe["Pole"+str(i+1) + " lamb,rel,y"][1]
1608
+ # dict_kc_axe["Pole"+str(i+1) + " kc,y"] = kcy(k_y, lamb_rel_y)
1609
+ # return dict_kc_axe
1610
+
1611
+
1612
+ # def sigma_c_0_d(self, Fc0d: float):
1613
+ # """ Retourne la contrainte de compression axial en MPa avec:
1614
+ # Fc0d : la charge en kN de compression """
1615
+ # self.Fc_0_d = Fc0d * si.kN
1616
+ # Fc_0_d = self.Fc_0_d
1617
+ # A_tot = self.aire
1618
+
1619
+ # @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1620
+ # def val():
1621
+ # sigma_c_0_d = Fc_0_d / A_tot # equC.2
1622
+ # return sigma_c_0_d
1623
+ # value = val()
1624
+ # self.sigma_c_0_rd = value[1]
1625
+ # return value
1626
+
1627
+
1628
+ # def Vd_organe(self, Fc0d: float):
1629
+ # """ Retourne l'effort de cisaillement à prendr en compte sur un organe d'assemblage suivant l'annexe C §C.2.2 avec:
1630
+ # Fc0d : la charge en kN de compression """
1631
+ # self.Fc_0_d = Fc0d * si.kN
1632
+ # Fc_0_d = self.Fc_0_d
1633
+ # K_c_eff_z = self.kc_Axe["kc,ef,z"][1]
1634
+ # lamb_ef_z = self.lamb_ef[1]
1635
+
1636
+ # if lamb_ef_z < 30:
1637
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1638
+ # def vd():
1639
+ # V_d = Fc_0_d / (120 * K_c_eff_z)
1640
+ # return V_d
1641
+ # elif 30 <= lamb_ef_z < 60:
1642
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1643
+ # def vd():
1644
+ # V_d = Fc_0_d * lamb_ef_z / (3600 * K_c_eff_z)
1645
+ # return V_d
1646
+ # else:
1647
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1648
+ # def vd():
1649
+ # V_d = Fc_0_d / (60 * K_c_eff_z)
1650
+ # return V_d
1651
+ # return vd()
1652
+
1653
+
1654
+ # def f_c_0_d(self, loadtype=Barre.LOAD_TIME, typecombi=Barre.TYPE_ACTION):
1655
+ # """Retourne le dictionnaire des résistances f,c,0,d de l'élément assemblé mécaniquement en MPa
1656
+
1657
+ # Args:
1658
+ # loadtype (str): chargement de plus courte durée sur l'élément.
1659
+ # typecombi (str): type de combinaison, fondamentale ou accidentelle.
1660
+
1661
+ # Returns:
1662
+ # float: f,c,0,d en MPa
1663
+ # """
1664
+ # self.dict_fc0d = {}
1665
+ # for i, pole in enumerate(self.pole):
1666
+ # if pole is not None:
1667
+ # self.dict_fc0d["Pole"+str(i+1) + " fc,0,d"] = pole._f_type_d("fc0k", loadtype, typecombi)
1668
+ # self.dict_fc0d["fc,0,ef,d"] = np.mean([value[1] for value in self.dict_fc0d.values()])
1669
+ # return self.dict_fc0d
1670
+
1671
+
1672
+ # def taux_c_0_d(self, flexion: object=None):
1673
+ # """Retourne les taux de travaux de la compression axial.
1674
+ # Si l'élement est un poteau (donc avec un travail principalement en compression) et de la flexion combinée (EN 1995-1-1 §6.3.2),
1675
+ # il est possible d'ajouter l'objet flexion et de vérifier cette combinaison.
1676
+
1677
+ # Args:
1678
+ # flexion (object, optional): L'objet Flexion avec ces taux de travaux préalablement calculés. Default to None.
1679
+
1680
+ # Returns:
1681
+ # list: retourne la liste des taux de travaux en %
1682
+ # """
1683
+ # self.taux_c_0_rd = {}
1684
+ # sigma_c_0_d = self.sigma_c_0_rd
1685
+
1686
+ # f_c_0_ef_d = self.dict_fc0d["fc,0,ef,d"]
1687
+ # f_c0_d_tot = sum([value[1] for key, value in self.dict_fc0d.items() if key != "fc,0,ef,d"])
1688
+ # f_c0d_tot_Kcy = 0
1689
+ # for i, pole in enumerate(self.pole):
1690
+ # if pole is not None:
1691
+ # kcy = self.kc_Axe["Pole"+str(i+1) + " kc,y"][1]
1692
+ # fcod_y = self.dict_fc0d["Pole"+str(i+1) + " fc,0,d"][1]
1693
+ # f_c0d_tot_Kcy = f_c0d_tot_Kcy + kcy * fcod_y
1694
+
1695
+ # lamb_rel_y = max([value[1] for key, value in self.lamb_rel_Axe.items() if key != "lamb,rel,ef,z"])
1696
+ # lamb_rel_z = self.lamb_rel_Axe["lamb,rel,ef,z"][1]
1697
+
1698
+ # K_c_eff_z = self.kc_Axe["kc,ef,z"][1]
1699
+
1700
+ # if flexion and isinstance(flexion, Flexion):
1701
+ # taux_6_11 = flexion.taux_m_rd["equ6.11"]
1702
+ # taux_6_12 = flexion.taux_m_rd["equ6.12"]
1703
+ # else:
1704
+ # taux_6_11 = 0
1705
+ # taux_6_12 = 0
1706
+
1707
+ # if lamb_rel_y < 0.3 and lamb_rel_z < 0.3:
1708
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1709
+ # def val():
1710
+ # taux_6_2 = sigma_c_0_d / f_c0_d_tot # equ6.2
1711
+ # taux_6_19 = (sigma_c_0_d / (f_c0_d_tot))**2 + taux_6_11 # equ6.19
1712
+ # taux_6_20 = sigma_c_0_d / (f_c0_d_tot)**2 + taux_6_12 # equ6.20
1713
+ # return taux_6_2, taux_6_19, taux_6_20
1714
+ # value = val()
1715
+ # self.taux_c_0_rd['equ6.19'] = value[1][3]
1716
+ # self.taux_c_0_rd['equ6.20'] = value[1][4]
1717
+ # else:
1718
+ # @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1719
+ # def val():
1720
+ # taux_6_2 = sigma_c_0_d / f_c0_d_tot # equ6.2
1721
+ # taux_6_23 = (sigma_c_0_d / (f_c0d_tot_Kcy)) + taux_6_11 # equ6.23
1722
+ # taux_6_24 = sigma_c_0_d / (f_c_0_ef_d * K_c_eff_z) + taux_6_12 # equC.1
1723
+ # return taux_6_2, taux_6_23, taux_6_24
1724
+ # value = val()
1725
+ # self.taux_c_0_rd['equ6.23'] = value[1][1]
1726
+ # self.taux_c_0_rd['equ6.24'] = value[1][2]
1727
+
1728
+ # self.taux_c_0_rd['equ6.2'] = value[1][0]
1729
+ # return value
1730
+
1731
+
1732
+
1733
+ # if __name__=='__main__':
1734
+ # beam2 = Barre(60,200,"Rectangulaire", classe="C24", cs=1)
1735
+ # beam3 = Barre(60,100,"Rectangulaire", classe="C24", cs=1)
1736
+ # beam_ass = Poutre_assemblee_meca(beam_2=beam2, l=5000, disposition="Latérale", recouvrement=[0,120], Kser=[None,None,700], entraxe=[None,None,250], psy_2=0, beam_3=beam3)
1737
+ # pole_ass = Poteau_assemble_meca._from_parent_class(beam_ass, lo_y=5000, lo_z=5000, type_appuis="Rotule - Rotule")
1738
+ # # print(pole_ass.__dict__)
1739
+ # # print(pole_ass.lamb)
1740
+ # print(pole_ass.kc_Axe)