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,1760 @@
1
+ # coding in UTF-8
2
+ # by Anthony PARISOT
3
+ # under Python 3.9.4
4
+
5
+ ############# Le but de ce fichier est de regrouper toute les fonctions d'assemblage par organe métalique dans l'EN-1995 #############
6
+ from copy import deepcopy
7
+ import math as mt
8
+ from math import sin, cos, radians, sqrt, pi
9
+
10
+ import forallpeople as si
11
+ si.environment("structural")
12
+ from handcalcs.decorator import handcalc
13
+
14
+ from ourocode.eurocode.A0_Projet import Projet
15
+ from ourocode.eurocode.EC5_Element_droit import Barre, Cisaillement
16
+
17
+ def interpolationLineaire(x, xa, xb, ya, yb):
18
+ """Fait une interpolation linéaire pour trouver un résultat y entre deux valeur xa et xb """
19
+ y = ya + (x - xa) * ((yb - ya)/(xb - xa))
20
+ return y
21
+
22
+ # ====================================================== GENERAL =========================================================
23
+ # 8.1 Généralité
24
+ class Assemblage(Projet):
25
+ GAMMA_M_ASS = 1.3
26
+ DICO_COEF_LIMITE = {"Pointe circulaire": 0.15, "Pointe carrée": 0.25,
27
+ "Boulon": 0.25, "Autres pointes": 0.5, "Tirefond": 1}
28
+ TYPE_BOIS_ASSEMBLAGE = ("Bois","PP/OSB", "CP", "Panneau dur")
29
+ TYPE_ASSEMBLAGE = ("Bois/Bois", "Bois/Métal")
30
+
31
+ def __init__(self,beam_1:object, beam_2:object, nfile: int=1, nCis: int=("1","2"), **kwargs):
32
+ """Créer un objet Assemblage qui permet de calculer un assemblage bois/bois ou bois/métal à l'EN 1995.
33
+ Cette classe est dérivé de la classe Projet du module A0_Project.py
34
+
35
+ Args:
36
+ beam_1 (object): objet correspondant à i=1, Beam ou dérivé de cet objet provenant du module EC5_Element_droit.py
37
+ ou bien objet Element ou dérivé de cet objet provenant du module EC3_Element_droit.py
38
+
39
+ beam_2 (object): objet correspondant à i=2, Beam ou dérivé de cet objet provenant du module EC5_Element_droit.py
40
+ ou bien objet Element ou dérivé de cet objet provenant du module EC3_Element_droit.py
41
+
42
+ nfile (int, optional): le nombre de file dans l'assemblage. Defaults to 1.
43
+ nCis (int, optional): Nombre de plan cisaillé entre 1 et 2. Defaults to ["1","2"].
44
+ """
45
+
46
+ super().__init__(**kwargs)
47
+ #type_organe : le type d'organe de l'assemblage "Pointe circulaire", "Pointe carrée", "Autres pointes", "Agrafe", "Tirefond", "Boulon"ou"Broche", "plaque", "Anneau", "Crampon C1/C9","Crampon C10/C11".
48
+ self.beam_1 = beam_1
49
+ self.beam_2 = beam_2
50
+ self.nfile = nfile
51
+ self.nCis = nCis
52
+ self.__type_assemblage()
53
+
54
+
55
+ def __type_assemblage(self):
56
+ self._type_beam = []
57
+ for i, beam in enumerate([self.beam_1, self.beam_2]):
58
+ try:
59
+ if beam.type_bois:
60
+ if beam.type_bois in ["Massif","BLC", "LVL"]:
61
+ self._type_beam.append(self.TYPE_BOIS_ASSEMBLAGE[0])
62
+ elif beam.type_bois in ["OSB 2", "OSB 3/4"]:
63
+ self._type_beam.append(self.TYPE_BOIS_ASSEMBLAGE[1])
64
+ elif beam.type_bois == "CP":
65
+ self._type_beam.append(self.TYPE_BOIS_ASSEMBLAGE[2])
66
+ elif beam.type_bois == "Panneau dur":
67
+ self._type_beam.append(self.TYPE_BOIS_ASSEMBLAGE[3])
68
+
69
+ beam.rho_k = int(beam.caract_meca.loc["rhok"])
70
+ except AttributeError:
71
+ self._type_beam.append("Métal")
72
+
73
+ # Détermine le type d'assemblage Bois/Bois ou Bois/métal
74
+ if self._type_beam[0] in self.TYPE_BOIS_ASSEMBLAGE:
75
+ if self._type_beam[1] in self.TYPE_BOIS_ASSEMBLAGE:
76
+ self.type_assemblage = self.TYPE_ASSEMBLAGE[0]
77
+ else:
78
+ self.type_assemblage = self.TYPE_ASSEMBLAGE[1]
79
+
80
+ else:
81
+ self.type_assemblage = self.TYPE_ASSEMBLAGE[1]
82
+
83
+
84
+ @property
85
+ def rho_mean_ass(self):
86
+ if self.type_assemblage == __class__.TYPE_ASSEMBLAGE[0]:
87
+ rho_m1 = int(self.beam_1.caract_meca.loc["rhomean"])
88
+ rho_m2 = int(self.beam_2.caract_meca.loc["rhomean"])
89
+ return mt.sqrt(rho_m1 * rho_m2)
90
+ else:
91
+ if self._type_beam[0] in self.TYPE_BOIS_ASSEMBLAGE:
92
+ return int(self.beam_1.caract_meca.loc["rhomean"])
93
+ else:
94
+ return int(self.beam_2.caract_meca.loc["rhomean"])
95
+
96
+
97
+ def _min_nef(self, list_nef: list):
98
+ """Retourne le nef minimum entre les 2
99
+
100
+ Args:
101
+ list_nef (list): list des nef en format handcalcs
102
+
103
+ Returns:
104
+ _type_: _description_
105
+ """
106
+ nef_1 = list_nef[0]
107
+ nef_2 = list_nef[1]
108
+
109
+ min_nef = min(self.nfile * nef_1[1], self.n * nef_2[1])
110
+ if min_nef == (self.nfile * nef_1[1]):
111
+ return list_nef[0]
112
+ else:
113
+ n_file = deepcopy(self.nfile)
114
+ self.nfile = self.n
115
+ self.n = n_file
116
+ return list_nef[1]
117
+
118
+
119
+ # 7.1 Glissement des assemblages
120
+ def Kser(self):
121
+ """Calcul le kser du type d'un organe et de l'asssemblage en N/mm
122
+
123
+
124
+ Returns:
125
+ list: retourne une liste du kser d'un organe par plan de cisaillement et celui de l'assemblage
126
+ """
127
+ rho_mean = self.rho_mean_ass
128
+ if self.type_organe == "Anneau" or self.type_organe == "Crampon C10/C11":
129
+ dc = self.dc.value*10**3
130
+ else:
131
+ d = self.d.value*10**3
132
+
133
+ if self.type_organe == "Boulon" or self.type_organe == "Broche" or self.type_organe == "Tirefond":
134
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
135
+ def val():
136
+ K_ser = rho_mean**1.5 * d / 23 # N/mm
137
+ return K_ser * si.N / si.mm
138
+ elif self.type_organe == "Pointe circulaire" or self.type_organe == "Pointe carrée" or self.type_organe == "Autres pointes":
139
+ if self.percage:
140
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
141
+ def val():
142
+ K_ser = rho_mean**1.5 * d / 23 # N/mm
143
+ return K_ser * si.N / si.mm
144
+ else:
145
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
146
+ def val():
147
+ K_ser = rho_mean**1.5 * d**0.8 / 30 # N/mm
148
+ return K_ser * si.N / si.mm
149
+ elif self.type_organe == "Agrafe":
150
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
151
+ def val():
152
+ K_ser = rho_mean**1.5 * self.d**0.8 / 80 # N/mm
153
+ return K_ser * si.N / si.mm
154
+ elif self.type_organe == "Anneau" or self.type_organe == "Crampon C10/C11":
155
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
156
+ def val():
157
+ K_ser = rho_mean * dc / 2 # N/mm
158
+ return K_ser * si.N / si.mm
159
+ elif self.type_organe == "Crampon C1/C9":
160
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
161
+ def val():
162
+ K_ser = 1.5 * rho_mean * d / 4 # N/mm
163
+ return K_ser * si.N / si.mm
164
+ return val()
165
+
166
+ def Kser_ass(self):
167
+ n_file = self.nfile
168
+ K_ser = self.Kser()[1]
169
+ n = self.n
170
+ n_Cis = self.nCis
171
+ k_type = 1
172
+ if self.type_assemblage == __class__.TYPE_ASSEMBLAGE[1]:
173
+ k_type = 2
174
+ @handcalc(override="short", precision=3, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
175
+ def val():
176
+ K_ser_ass = K_ser * n_file * n * n_Cis * k_type
177
+ return K_ser_ass
178
+ return val()
179
+
180
+
181
+ # 8.1.4 Effort d'assemblage inclinés par rapport au fil
182
+
183
+ def _w(self, wpl: int=0):
184
+ """Calcul le facteur de modification pour le calcul de la valeur caractéristique au fendage F90,Rk avec:
185
+ wpl : largeur de la plaque métallique emboutie parallèlement au fil en mm
186
+ type_organe : type d'organe utilisé, pour les plaques métalliques embouties : "plaque", pour les autres : "autres" """
187
+ if self.type_organe == "plaques métaliques embouties":
188
+ w = max((wpl / 100) ** 0.35, 1)
189
+ else:
190
+ w = 1
191
+ return w
192
+
193
+
194
+ def F90Rk(self, b:int, h:int, he:int, w: int=1):
195
+ """Calcul la valeur caractérisque de la capacité au fendage en N avec :
196
+ b : l'épaisseur de l'élément en mm
197
+ h : la hauteur de l'élément en mm
198
+ he : la distance de rive chargée vis à vis du centre de l'organe le plus plus éloigné ou du bord de la plaque
199
+ w : facteur de modification """
200
+ h_e = he
201
+ @handcalc(override="short", precision=0, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
202
+ def val():
203
+ F_90_Rk = 14 * b * w * sqrt(h_e / (1 - (h_e / h))) # N
204
+ return F_90_Rk * si.N
205
+ return val()
206
+
207
+ # 8.2 Capacité résistante latérale pour les organes métaliques de type tige
208
+ # 8.2.2 Assemblage bois/bois bois/panneau
209
+
210
+
211
+ def _FvRk_BoisBois(self, effet_corde: bool):
212
+ """Calcul la capacité résistante en cisaillement de la tige en N par plan de cisaillement avec
213
+ t1 : valeur minimale entre epaisseur de l'élément bois latéral et la profondeur de pénétration en mm
214
+ t2 : epaisseur de l'élément bois central en mm """
215
+
216
+ f_h1k = self.fh1k[1].value * 10**-6
217
+ f_h2k = self.fh2k[1].value * 10**-6
218
+ t_1 = self.t1.value * 10**3
219
+ t_2 = self.t2.value * 10**3
220
+ diam = self.d.value * 10**3
221
+ M_y_Rk = self.MyRk[1].value * 10**3
222
+
223
+ coef_limit_Johansen = self.DICO_COEF_LIMITE.get(self.type_organe, 0)
224
+ if effet_corde:
225
+ F_ax_Rk = self.FaxRk.value
226
+ else:
227
+ F_ax_Rk = 0
228
+
229
+ if self.nCis == 1:
230
+
231
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
232
+ def val():
233
+ effet_corde = F_ax_Rk/4 # N
234
+ beta = f_h2k / f_h1k
235
+ a = f_h1k * t_1 * diam # N
236
+ b = f_h2k * t_2 * diam # N
237
+ c = a/(1 + beta) * (sqrt(beta + 2 * beta**2 * (1 + t_2 / t_1 + (t_2 / t_1)**2) + beta**3 * (t_2 / t_1)**2) - beta * (1 + t_2 / t_1)) # N
238
+ c = c + min(effet_corde, c*coef_limit_Johansen) # N
239
+ d = 1.05 * a / (2 + beta) * (sqrt(2 * beta * (1 + beta) + (4 * beta * (2 + beta) * M_y_Rk)/(f_h1k * t_1**2 * diam)) - beta) # N
240
+ d = d + min(effet_corde, d*coef_limit_Johansen) # N
241
+ e = 1.05 * (f_h1k * t_2 * diam) / (1 + 2 * beta) * (sqrt(2 * beta**2 * (1 + beta) + (4 * beta * (1 + 2 * beta) * M_y_Rk)/(f_h1k * t_2**2 * diam)) - beta) # N
242
+ e = e + min(effet_corde, e*coef_limit_Johansen) # N
243
+ f = 1.15 * sqrt((2 * beta)/(1 + beta)) * sqrt(2 * M_y_Rk * f_h1k * diam) # N
244
+ f = f + min(effet_corde, f*coef_limit_Johansen) # N
245
+ return a, b, c, d, e, f
246
+
247
+ calcul = val()
248
+ a = calcul[1][0] * si.N
249
+ b = calcul[1][1] * si.N
250
+ c = calcul[1][2] * si.N
251
+ d = calcul[1][3] * si.N
252
+ e = calcul[1][4] * si.N
253
+ f = calcul[1][5] * si.N
254
+ dicoRupture = {a: "A", b: "B", c: "C", d: "D", e: "E", f: "F"}
255
+ FvRk = min(a, b, c, d, e, f)
256
+ mode_rupture = dicoRupture[FvRk]
257
+
258
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
259
+ def val2():
260
+ F_v_Rk = min(a, b, c, d, e, f)
261
+ mode_rupture
262
+ return F_v_Rk, mode_rupture
263
+ calcul2 = val2()
264
+
265
+ else:
266
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
267
+ def val():
268
+ effet_corde = F_ax_Rk/4 # N
269
+ beta = f_h2k / f_h1k
270
+ g = f_h1k * t_1 * diam # N
271
+ h = 0.5 * f_h2k * t_2 * diam # N
272
+ j = 1.05 * g / (2 + beta) * (sqrt(2 * beta * (1 + beta) + (4 * beta * (2 + beta) * M_y_Rk)/ (f_h1k * t_1**2 * diam)) - beta) # N
273
+ j = j + min(effet_corde, j*coef_limit_Johansen) # N
274
+ k = 1.15 * sqrt((2 * beta)/(1 + beta)) * sqrt(2 * M_y_Rk * f_h1k * diam) # N
275
+ k = k + min(effet_corde, k*coef_limit_Johansen) # N
276
+ return g, h, j, k
277
+
278
+ calcul = val()
279
+ g = calcul[1][0] * si.N
280
+ h = calcul[1][1] * si.N
281
+ j = calcul[1][2] * si.N
282
+ k = calcul[1][3] * si.N
283
+ FvRk = min(g, h, j, k)
284
+ dicoRupture = {g: "G", h: "H", j: "J", k: "K"}
285
+ mode_rupture = dicoRupture[FvRk]
286
+
287
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
288
+ def val2():
289
+ F_v_Rk = min(g, h, j, k)
290
+ mode_rupture
291
+ return F_v_Rk, mode_rupture
292
+ calcul2 = val2()
293
+
294
+ return (calcul[0] + calcul2[0], calcul2[1])
295
+
296
+
297
+ # 8.2.3 Assemblage bois métal
298
+ def _FvRk_BoisMetal(self, effet_corde: bool):
299
+ """Calcul la capacité résistante en cisaillement de la tige en N par plan de cisaillement avec
300
+ t1 : valeur minimale entre epaisseur de l'élément bois latéral et la profondeur de pénétration en mm
301
+ t2 : epaisseur de l'élément bois central en mm
302
+ """
303
+ diam = self.d.value * 10**3
304
+ M_y_Rk = self.MyRk[1].value * 10**3
305
+ coef_limit_Johansen = self.DICO_COEF_LIMITE.get(self.type_organe, 0)
306
+ if effet_corde:
307
+ F_ax_Rk = self.FaxRk.value
308
+ else:
309
+ F_ax_Rk = 0
310
+
311
+ if self._type_beam[0] == "Métal":
312
+ f_h2k = self.fh2k[1].value * 10**-6
313
+ t_2 = self.t2.value * 10**3
314
+ self.t = self.beam_1.t
315
+ if self.nCis == 2:
316
+ self.pos_plaq = "externe"
317
+ else:
318
+ f_h1k = self.fh1k[1].value * 10**-6
319
+ t_1 = self.t1.value * 10**3
320
+ self.t = self.beam_2.t
321
+ if self.nCis == 2:
322
+ self.pos_plaq = "centrale"
323
+
324
+ if self.t <= 0.5 * self.d:
325
+ self.type_plaque = "mince"
326
+
327
+ elif self.d <= self.t:
328
+ self.type_plaque = "epaisse"
329
+
330
+ else:
331
+ self.type_plaque = "intermédiaire"
332
+ print("ATTENTION interpolation linéaire à faire ! EC5-8.2.3.1")
333
+
334
+ if self.type_plaque == "mince" and self.nCis == 1:
335
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
336
+ def val():
337
+ effet_corde = F_ax_Rk/4 # N
338
+ a = 0.4 * f_h1k * t_1 * diam # N
339
+ b = 1.15 * sqrt(2 * M_y_Rk * f_h1k * diam) # N
340
+ b = b + min(effet_corde, b*coef_limit_Johansen) # N
341
+ return a, b
342
+
343
+ calcul = val()
344
+ a = calcul[1][0] * si.N
345
+ b = calcul[1][1] * si.N
346
+ dicoRupture = {a: "A", b: "B"}
347
+ FvRk = min(a, b)
348
+ mode_rupture = dicoRupture[FvRk]
349
+
350
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
351
+ def val2():
352
+ F_v_Rk = min(a, b)
353
+ mode_rupture
354
+ return F_v_Rk, mode_rupture
355
+ calcul2 = val2()
356
+
357
+ elif self.type_plaque == "epaisse" and self.nCis == 1:
358
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
359
+ def val():
360
+ effet_corde = F_ax_Rk/4 # N
361
+ c = f_h1k * t_1 * diam # N
362
+ d = c * (sqrt(2 + (4 * M_y_Rk) / (f_h1k * diam * t_1 ** 2)) - 1) # N
363
+ d = d + min(effet_corde, d*coef_limit_Johansen) # N
364
+ e = 2.3 * sqrt(M_y_Rk * f_h1k * diam) # N
365
+ e = e + min(effet_corde, e*coef_limit_Johansen) # N
366
+ return c, d, e
367
+
368
+ calcul = val()
369
+ c = calcul[1][0] * si.N
370
+ d = calcul[1][1] * si.N
371
+ e = calcul[1][2] * si.N
372
+ dicoRupture = {c: "C", d: "D", e: "E"}
373
+ FvRk = min(c, d, e)
374
+ mode_rupture = dicoRupture[FvRk]
375
+
376
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
377
+ def val2():
378
+ F_v_Rk = min(c, d, e)
379
+ mode_rupture
380
+ return F_v_Rk, mode_rupture
381
+ calcul2 = val2()
382
+
383
+ elif self.nCis == 2 and self.pos_plaq == "centrale":
384
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
385
+ def val():
386
+ effet_corde = F_ax_Rk/4 # N
387
+ f = f_h1k * t_1 * diam # N
388
+ g = f * (sqrt(2 + (4 * M_y_Rk) / (f_h1k * diam * t_1 ** 2)) - 1) # N
389
+ g = g + min(effet_corde, g*coef_limit_Johansen) # N
390
+ h = 2.3 * sqrt(M_y_Rk * f_h1k * diam) # N
391
+ h = h + min(effet_corde, h*coef_limit_Johansen) # N
392
+ return f, g, h
393
+
394
+ calcul = val()
395
+ f = calcul[1][0] * si.N
396
+ g = calcul[1][1] * si.N
397
+ h = calcul[1][2] * si.N
398
+ dicoRupture = {f: "F", g: "G", h: "H"}
399
+ FvRk = min(f, g, h)
400
+ mode_rupture = dicoRupture[FvRk]
401
+
402
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
403
+ def val2():
404
+ F_v_Rk = min(f, g, h)
405
+ mode_rupture
406
+ return F_v_Rk, mode_rupture
407
+ calcul2 = val2()
408
+
409
+ elif self.type_plaque == "mince" and self.nCis == 2 and self.pos_plaq != "centrale":
410
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
411
+ def val():
412
+ effet_corde = F_ax_Rk/4 # N
413
+ j = 0.5 * f_h2k * t_2 * diam # N
414
+ k = 1.15 * sqrt(2 * M_y_Rk * f_h2k * diam) # N
415
+ k = k + min(effet_corde, k*coef_limit_Johansen) # N
416
+ return j, k
417
+
418
+ calcul = val()
419
+ j = calcul[1][0] * si.N
420
+ k = calcul[1][1] * si.N
421
+ dicoRupture = {j: "J", k: "K"}
422
+ FvRk = min(j, k)
423
+ mode_rupture = dicoRupture[FvRk]
424
+
425
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
426
+ def val2():
427
+ F_v_Rk = min(j, k)
428
+ mode_rupture
429
+ return F_v_Rk, mode_rupture
430
+ calcul2 = val2()
431
+
432
+ else:
433
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
434
+ def val():
435
+ effet_corde = F_ax_Rk/4 # N
436
+ l = 0.5 * f_h2k * t_2 * diam # N
437
+ m = 2.3 * sqrt(M_y_Rk * f_h2k * diam) # N
438
+ m = m + min(effet_corde, m*coef_limit_Johansen) # N
439
+ return l, m
440
+
441
+ calcul = val()
442
+ l = calcul[1][0] * si.N
443
+ m = calcul[1][1] * si.N
444
+ dicoRupture = {l: "L", m: "M"}
445
+ FvRk = min(l, m)
446
+ mode_rupture = dicoRupture[FvRk]
447
+
448
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
449
+ def val2():
450
+ F_v_Rk = min(l, m)
451
+ mode_rupture
452
+ return F_v_Rk, mode_rupture
453
+ calcul2 = val2()
454
+
455
+ return (calcul[0] + calcul2[0], calcul2[1])
456
+
457
+
458
+ # 8.1.2 Assemblage par organe multiple
459
+
460
+ def FvRk(self, effet_corde: bool=("True", "False")):
461
+ """Calcul la valeur de calcul caractéristique de résistance au cisaillement de l'assemblage en N
462
+
463
+ Args:
464
+ effet_corde (bool): prise en compte de l'effet de corde, si oui alors True.
465
+ Attention: pour que l'effet de corde soit prit en compte, il faut que le FaxRk du type de tige est été calculé préalablement.
466
+
467
+ Returns:
468
+ float: effort de reprise caractéristique de l'assemblage en N
469
+ """
470
+ # Fvrktot : capacité résistante en cisaillement caractéristique avec la partie de Johansen + l'effet de corde en N
471
+ if self.type_assemblage == __class__.TYPE_ASSEMBLAGE[0]:
472
+ latex, self.Fv_Rk = self._FvRk_BoisBois(effet_corde)
473
+ else:
474
+ latex, self.Fv_Rk = self._FvRk_BoisMetal(effet_corde)
475
+
476
+ F_v_Rk = self.Fv_Rk[0]
477
+ n_file = self.nfile
478
+ n_ef = self._nef
479
+ n_cisaillement = self.nCis
480
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
481
+ def val():
482
+ F_v_Rk_ass = F_v_Rk * n_file * n_ef * n_cisaillement
483
+ return F_v_Rk_ass
484
+ FvRkass_latex, self.Fv_Rk_ass = val()
485
+ latex = latex + FvRkass_latex
486
+ return (latex, self.Fv_Rk_ass)
487
+
488
+
489
+ def F_Rd(self, F_Rk: si.kN, loadtype=Barre.LOAD_TIME):
490
+ """Calcul la valeur de calcul (design) de résistance de l'assemblage en N avec :
491
+
492
+ Args:
493
+ F_rk (float): capacité résistante caractéristique de l'organe en kN
494
+ loadtype (str, optional): Durée de chargement (Permanente, Court terme etc.). Defaults to "Permanente"."""
495
+ F_Rk = F_Rk * si.kN
496
+ gamma_M = self.GAMMA_M_ASS
497
+ if "Métal" in self._type_beam:
498
+ if self._type_beam[0] == "Métal":
499
+ k_mod = self.beam_2._get_k_mod(loadtype)
500
+ else:
501
+ k_mod = self.beam_1._get_k_mod(loadtype)
502
+ else:
503
+ k_mod = sqrt(self.beam_1._get_k_mod(loadtype) * self.beam_2._get_k_mod(loadtype))
504
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
505
+ def val():
506
+ F_Rd = (F_Rk * k_mod) /gamma_M # Valeur de calcul (design)
507
+ return F_Rd
508
+ return val()
509
+
510
+
511
+ # Annexe A : Cisaillement de bloc
512
+ def FbsRk(self, dp:si.mm, a1:si.mm, a2:si.mm, a3t:si.mm, Kcr: float=0.67, num_beam: int=("1", "2")):
513
+ """Calcul la valeur caractéristique en cisaillement de bloc en N pour l'élément 1 ou 2 de l'assemblage.
514
+ Attention pour que cette fonction puisse s'éxecuter il faut avoir préalablement éxécuté la fontion FvRk.
515
+
516
+ Args:
517
+ dp (float): diamètre de perçage en mm
518
+ a1 (float): pince longitudinale en mm
519
+ a2 (float): pince perpendiculaire en mm
520
+ a3t (float): pince en bord chargée suivant le file en mm
521
+ kcr (float, optional): coeff de réduction largeur en cisaillement.
522
+ Si aucune valeur n'est rentrée alors il sera automatiquement calculé. Defaults to 0.67.
523
+ num_beam (int, optional): numéro de l'élément à vérifier. Defaults to 1.
524
+ """
525
+ diam = self.d
526
+ diam_percage = dp * si.mm
527
+
528
+ a_1 = a1 * si.mm
529
+ a_2 = a2 * si.mm
530
+ a_3_t = a3t * si.mm
531
+ M_y_Rk = self.MyRk[1]
532
+ n = self.n
533
+ n_file = self.nfile
534
+
535
+ mode_rupture = self.Fv_Rk[1]
536
+
537
+ # on calcul les valeur caractéristique de base de notre éléméent
538
+ if num_beam == 1:
539
+ parent_beam = self.beam_1
540
+ f_hk = self.fh1k[1]
541
+ t_1 = self.t1
542
+ else:
543
+ parent_beam = self.beam_2
544
+ f_hk = self.fh2k[1]
545
+ t_1 = self.t2
546
+ f_t0_k = float(parent_beam.caract_meca.loc["ft0k"]) * si.MPa
547
+ f_v_k = float(parent_beam.caract_meca.loc["fvk"]) * si.MPa
548
+
549
+ # On calcul le kcr si aucune valeur n'est donnée en argument
550
+ if not Kcr:
551
+ cis_beam = Cisaillement._from_parent_class(parent_beam)
552
+ K_cr = cis_beam.K_cr
553
+ else:
554
+ K_cr = Kcr
555
+
556
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
557
+ def l_net():
558
+ l_v_i = a_1 - diam_percage # Distance entre perçage dans le sens fil
559
+ L_net_v = 2 * (l_v_i * (n - 1) + a_3_t - (diam_percage / 2)) # Longueur résiduelle de la surface de rupture en cisaillement
560
+
561
+ l_t_i = a_2 - diam_percage # Distance entre perçage dans le sens perpendiculaire au fil
562
+ L_net_t = l_t_i * (n_file - 1) # Largeur résiduelle de la section perpendiculaire au fil
563
+
564
+ mode_rupture
565
+ return L_net_v, L_net_t
566
+
567
+ L_net_value = l_net()
568
+ latex = L_net_value[0]
569
+ L_net_v, L_net_t = L_net_value[1]
570
+
571
+
572
+ if mode_rupture in ("C", "F", "J", "L", "K", "M"):
573
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
574
+ def a_net_v():
575
+ A_net_v = L_net_v * (t_1 * K_cr)
576
+ return A_net_v
577
+ a_net_v_result = a_net_v()
578
+ latex = latex + a_net_v_result[0]
579
+ A_net_v = a_net_v_result[1]
580
+ else:
581
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
582
+ def a_net_v(t_ef):
583
+ A_net_v = L_net_v / 2 * (L_net_t + 2 * (t_ef * K_cr))
584
+ return A_net_v
585
+
586
+ match mode_rupture:
587
+ case "A":
588
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
589
+ def tef():
590
+ t_ef = 0.4*t_1 # Épaisseur efficace
591
+ return t_ef
592
+ case "B":
593
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
594
+ def tef():
595
+ t_ef = 1.4 * sqrt(M_y_Rk / (f_hk * diam)) # Épaisseur efficace
596
+ return t_ef
597
+ case "D"|"G":
598
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
599
+ def tef():
600
+ t_ef = t_1 * (sqrt(2 + (4 * M_y_Rk ) / (f_hk * diam * t_1**2)-1)) # Épaisseur efficace
601
+ return t_ef
602
+ case "E"|"H":
603
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
604
+ def tef():
605
+ t_ef = 2 * sqrt(M_y_Rk / (f_hk * diam)) # Épaisseur efficace
606
+ return t_ef
607
+ tef_result = tef()
608
+ a_net_v_result = a_net_v(tef_result[1])
609
+ latex = latex + tef_result[0] + a_net_v_result[0]
610
+ A_net_v = a_net_v_result[1]
611
+
612
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
613
+ def f_bs_Rk():
614
+ A_net_t = L_net_t * t_1
615
+ F_bs_Rk = max(0.7 * A_net_v * f_v_k, 1.5 * A_net_t * f_t0_k)
616
+ return F_bs_Rk
617
+
618
+ result = f_bs_Rk()
619
+ self.F_bs_Rk = result[1]
620
+ return (latex + result[0], self.F_bs_Rk)
621
+
622
+ def taux_cisaillement(self, Fv_Ed: si.kN, loadtype=Barre.LOAD_TIME):
623
+ """Détermine le taux de cisaillement de l'assemblage
624
+
625
+ Args:
626
+ Fv_Ed (float): effort de cisaillement à reprendre en kN
627
+ """
628
+ Fv_Rd_ass = self.F_Rd(self.Fv_Rk_ass.value*10**-3, loadtype)[1]
629
+ Fv_Ed = abs(Fv_Ed) * si.kN
630
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
631
+ def val():
632
+ taux_cisaillement = Fv_Ed / Fv_Rd_ass * 100
633
+ return taux_cisaillement
634
+ return val()
635
+
636
+
637
+ # ======================================================= POINTE =========================================================
638
+ # 8.3 Assemblage par pointes
639
+
640
+ class Pointe(Assemblage):
641
+ """ Défini un objet pointe avec :
642
+ d : diamètre de la pointe en mm (pour les pointe carrée = coté de la pointe)
643
+ d_tete : diamètre de la tête en mm
644
+ l : longueur sous la tête en mm
645
+ qualite = qualité de l'acier
646
+ n : nombre d'organe dans une file
647
+ alpha1 : angle entre l'effort de l'organe et le fil du bois 1 en °
648
+ alpha2 : angle entre l'effort de l'organe et le fil du bois 2 en °
649
+ type_organe : "Carrée" = False "Circulaire" = True
650
+ percage : "False", "True"
651
+ """
652
+
653
+ TYPE_ASSEMBLAGE = ("Bois/Bois", ("CP", "Panneau dur", "PP/OSB"), "Bois/Métal")
654
+ QUALITE_ACIER = ('6.8', '8.8', '9.8', '10.9', '12.9')
655
+ TYPE_ORGANE = ("Pointe circulaire", "Pointe carrée", "Autres pointes")
656
+
657
+ def __init__(self, d:si.mm, d_tete:si.mm, l:si.mm, qualite: str=QUALITE_ACIER, n: int=1, alpha1: float=0, alpha2: float=0, type_organe: str=TYPE_ORGANE, percage: bool=("False", "True"), *args, **kwargs):
658
+ super().__init__(*args, **kwargs)
659
+ self.d = d * si.mm
660
+ self.d_tete = d_tete * si.mm
661
+ self.l = l * si.mm #longueur sous tête
662
+ self.qualite = qualite
663
+ self.n = n
664
+ self.fu = self.__qualite_acier.loc["fub"] *si.MPa
665
+ self.alpha = [alpha1, alpha2]
666
+ self.percage = percage
667
+ self.type_organe = type_organe
668
+
669
+ self.__t1_t2()
670
+ self._fhik()
671
+
672
+
673
+ @property
674
+ def __qualite_acier(self):
675
+ df = self._data_from_csv("qualite_acier.csv")
676
+ df = df.loc[self.qualite]
677
+ return df
678
+
679
+ @property
680
+ def _type_circulaire(self):
681
+ if self.type_organe == "Pointe carrée":
682
+ return False
683
+ else:
684
+ return True
685
+
686
+
687
+ def __t1_t2(self):
688
+ """Retourne t1 et t2 en mm suivant l'EN 1995 §8.3.1.1
689
+ """
690
+ l_pointe = self.d #Longueur de la pointe à déduire
691
+ if self.type_organe == "Tirefond":
692
+ l_pointe = self.d_vis
693
+
694
+ if self.nCis == 1:
695
+ if self._type_beam[0] in self.TYPE_BOIS_ASSEMBLAGE:
696
+ self.t1 = self.beam_1.b_calcul
697
+ else:
698
+ self.t1 = self.beam_1.t
699
+
700
+ if self._type_beam[1] in self.TYPE_BOIS_ASSEMBLAGE:
701
+ self.t2 = self.l - self.t1 - l_pointe
702
+
703
+ else:
704
+ if self._type_beam[0] in self.TYPE_BOIS_ASSEMBLAGE:
705
+ if "Bois/Métal" in self.type_assemblage:
706
+ b_beam_2 = self.beam_2.t + 2
707
+ else:
708
+ b_beam_2 = self.beam_2.b_calcul
709
+ self.t1 = min(self.beam_1.b_calcul, self.l - self.beam_1.b_calcul - b_beam_2 - l_pointe)
710
+ else:
711
+ print("Il n'est pas possible sauf erreur d'avoir un assemblage double cisaillement avec une pointe !")
712
+ if self._type_beam[1] in self.TYPE_BOIS_ASSEMBLAGE:
713
+ self.t2 = self.beam_2.b_calcul
714
+ else:
715
+ self.t2 = self.beam_2.t
716
+
717
+
718
+ @property
719
+ def MyRk(self):
720
+ """ Défini le moment d'écoulement plastique d'une pointe en N.mm avec:
721
+ d : diamètre de la pointe en mm (pour les pointe carrée = coté de la pointe)
722
+ fu : la résistance caractéristique en traction du fil d'acier en N/mm2 """
723
+ f_u = self.fu.value * 10**-6
724
+ d = self.d.value * 10**3
725
+ if self.fu >= 600:
726
+ if self._type_circulaire == True:
727
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
728
+ def val():
729
+ M_y_Rk = 0.3 * f_u* d**2.6 # N.mm
730
+ return M_y_Rk * si.N*si.mm
731
+ else:
732
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
733
+ def val():
734
+ M_y_Rk = 0.45 * f_u* d**2.6 # N.mm
735
+ return M_y_Rk * si.N*si.mm
736
+ return val()
737
+ else:
738
+ print("La résistance du fil en traction est inférieur à 600 MPa, vérifier vos données !")
739
+
740
+
741
+ def _fhk_bois(self, beam:object):
742
+ """ Calcul la portance locale des pointes inférieur à 8mm dans le bois et le LVL en MPa
743
+ """
744
+ d = self.d.value * 10**3
745
+ rho_k = beam.rho_k
746
+ if self.percage:
747
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
748
+ def val():
749
+ fhk = 0.082 * (1 - 0.01 * d) * rho_k # MPa
750
+ return fhk * si.MPa
751
+ else:
752
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
753
+ def val():
754
+ fhk = 0.082 * rho_k * d**(-0.3) # MPa
755
+ return fhk * si.MPa
756
+ return val()
757
+
758
+
759
+ def _fhk_panneau(self, beam:object):
760
+ """Calcul la portance locale des pointes dans les panneaux en MPa
761
+
762
+ Args:
763
+ t (int): épaisseur du panneau en mm
764
+ self.d_tete (int): diamètre de la tête de la pointe
765
+
766
+ Returns:
767
+ float: portance locale en MPa
768
+ """
769
+ d = self.d.value * 10**3
770
+ b_calcul = beam.b_calcul
771
+ rho_k = beam.rho_k
772
+ if self.d_tete >= 2*d:
773
+ if beam.type_bois == "CP":
774
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
775
+ def val():
776
+ fhk = 0.11 * rho_k * d**-0.3 # MPa
777
+ return fhk * si.MPa
778
+ elif beam.type_bois == "Panneau dur":
779
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
780
+ def val():
781
+ fhk = 30 * d**-0.3 * b_calcul**0.6 # MPa
782
+ return fhk * si.MPa
783
+ else:
784
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
785
+ def val():
786
+ fhk = 65 * d**-0.7 * b_calcul**0.1 # MPa
787
+ return fhk * si.MPa
788
+ return val()
789
+ else:
790
+ print(f"La tête de la pointe doit être au moins égale à {2*d} mm")
791
+
792
+
793
+ def _fhik(self) -> tuple:
794
+ """Calcul la portance locale d'une pointe en MPa dans les deux éléments de l'assemblage
795
+
796
+ ATTENTION: Pas de prise en compte des panneaux durs au sens de la norme EN 622-2
797
+
798
+ Returns:
799
+ tuple: (fh1k, fh2k) en MPa
800
+ """
801
+ dict_beam = {"1": {}, "2": {}}
802
+ for i, beam in enumerate([self.beam_1, self.beam_2]):
803
+ if self._type_beam[i] == "Bois":
804
+ dict_beam[str(i+1)]["fhk"] = self._fhk_bois(beam)
805
+
806
+ elif self._type_beam[i] == "CP" or self._type_beam[i] == "PP/OSB":
807
+ dict_beam[str(i+1)]["fhk"] = self._fhk_panneau(beam)
808
+
809
+ else:
810
+ dict_beam[str(i+1)]["fhk"] = 0
811
+
812
+ # if self._type_beam[i] != "Métal":
813
+ # if i:
814
+ # self.t2 = self.beam_2.b_calcul
815
+ # else:
816
+ # self.t1 = self.beam_1.b_calcul
817
+
818
+
819
+ self.fh1k = dict_beam["1"]["fhk"]
820
+ self.fh2k = dict_beam["2"]["fhk"]
821
+ return self.fh1k, self.fh2k
822
+
823
+
824
+ def _kef(self, a1:int):
825
+ """ coefficient donnée dans le tableau 8.1 fonction de a1 et du percage qui réduit le nombre efficace de pointe dans le sens
826
+ du fil avec :
827
+ a1 : l'espacement entre tige dans le sens du fil du bois """
828
+ if self.type_organe == "Tirefond":
829
+ d = self.d_vis
830
+ else:
831
+ d = self.d
832
+ listeTab = (d * 4, d * 7, d *
833
+ 10, d * 14, ("x", 0.7, 0.85, 1))
834
+
835
+ if a1 >= listeTab[3]:
836
+ kef = 1
837
+ j = 0
838
+ for i in range(4):
839
+
840
+ if listeTab[i] <= a1:
841
+
842
+ if a1 == listeTab[i]:
843
+ kef = listeTab[4][i]
844
+
845
+ if kef == "x" and self.percage == False:
846
+ kef = 0
847
+
848
+ elif kef == "x" and self.percage == True:
849
+ kef = 0.5
850
+ j += 1
851
+
852
+ else:
853
+ if listeTab[4][j-1] == "x" and self.percage == False:
854
+ kef = interpolationLineaire(
855
+ a1, listeTab[j-1], listeTab[j], 0, listeTab[4][j])
856
+
857
+ elif listeTab[4][j-1] == "x" and self.percage == True:
858
+ kef = interpolationLineaire(
859
+ a1, listeTab[j-1], listeTab[j], 0.5, listeTab[4][j])
860
+
861
+ else:
862
+ kef = interpolationLineaire(
863
+ a1, listeTab[j-1], listeTab[j], listeTab[4][j-1], listeTab[4][j])
864
+ self.kef = kef
865
+ return self.kef
866
+
867
+
868
+ def nef(self, a1_beam1:int, a1_beam2:int):
869
+ """Défini le nombre efficace d'organe dans une file avec :
870
+ a1_beam1 : espacement entre les organes dans la barre 1 en mm
871
+ a1_beam2 : espacement entre les organes dans la barre 2 en mm"""
872
+ nef_list = []
873
+ for i, _ in enumerate([self.beam_1, self.beam_2]):
874
+ if i:
875
+ a_1 = a1_beam2 * si.mm
876
+ n = self.nfile
877
+ else:
878
+ a_1 = a1_beam1 * si.mm
879
+ n = self.n
880
+
881
+ k_ef = self._kef(a_1)
882
+
883
+ if n == 1:
884
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
885
+ def val():
886
+ n_ef =1
887
+ return n_ef
888
+ nef_list.append(val())
889
+ else :
890
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
891
+ def val():
892
+ n_ef = n**k_ef
893
+ return n_ef
894
+ nef_list.append(val())
895
+ result = self._min_nef(nef_list)
896
+ self._nef = result[1]
897
+ return result
898
+
899
+ # def FvRk(self, effet_corde: bool=("True", "False")):
900
+ # """Calcul la valeur de calcul caractéristique de résistance au cisaillement de l'assemblage en N
901
+
902
+ # Args:
903
+ # effet_corde (bool): prise en compte de l'effet de corde, si oui alors True.
904
+
905
+ # Returns:
906
+ # float: effort de reprise caractéristique de l'assemblage en N
907
+ # """
908
+ # super()._FvRk(effet_corde)
909
+
910
+ # def FbsRk(self, dp:float, a1:float, a2:float, a3t:float, Kcr: float=0.67, num_beam: int=("1", "2")):
911
+ # """Calcul la valeur caractéristique en cisaillement de bloc en N pour l'élément 1 ou 2 de l'assemblage.
912
+ # Attention pour que cette fonction puisse s'éxecuter il faut avoir préalablement éxécuté la fontion FvRk.
913
+
914
+ # Args:
915
+ # dp (float): diamètre de perçage en mm
916
+ # a1 (float): pince longitudinale en mm
917
+ # a2 (float): pince perpendiculaire en mm
918
+ # a3t (float): pince en bord chargée suivant le file en mm
919
+ # kcr (float, optional): coeff de réduction largeur en cisaillement.
920
+ # Si aucune valeur n'est rentrée alors il sera automatiquement calculé. Defaults to 0.67.
921
+ # num_beam (int, optional): numéro de l'élément à vérifier. Defaults to 1.
922
+ # """
923
+ # super()._FbsRk(dp, a1, a2, a3t, Kcr, num_beam)
924
+
925
+ @property
926
+ def pince(self):
927
+ """Défini les différentes pinces minimales pour une pointe en mm avec :
928
+ alpha : angle entre l'effort de l'organe et le fil du bois en °
929
+ d : diamètre efficace de la pointe ou du tire fond si d<=6mm en mm """
930
+
931
+ dict_pince = {}
932
+ if self.type_organe == "Tirefond":
933
+ self.d = self.d_vis
934
+ for i, beam in enumerate([self.beam_1, self.beam_2]):
935
+ if not self._type_beam[i] in self.TYPE_BOIS_ASSEMBLAGE:
936
+ continue
937
+
938
+ alpha = self.alpha[i]
939
+ rho_k = beam.rho_k
940
+ if self.percage == True:
941
+ a1 = round((4 + mt.cos(mt.radians(alpha))) * self.d, 1)
942
+ a2 = round((3 + mt.sin(mt.radians(alpha))) * self.d, 1)
943
+ a3t = round((7 + 5 * mt.cos(mt.radians(alpha))) * self.d, 1)
944
+ a3c = round(7 * self.d, 1)
945
+ a4c = round(3 * self.d, 1)
946
+
947
+ if self.d < 5:
948
+ a4t = round((3 + 2 * mt.sin(mt.radians(alpha))) * self.d, 1)
949
+ else:
950
+ a4t = round((3 + 4 * mt.sin(mt.radians(alpha))) * self.d, 1)
951
+ else:
952
+ if rho_k <= 420:
953
+ if self.d < 5:
954
+ print (mt.cos(mt.radians(alpha)))
955
+ a1 = round((5 + 5 * mt.cos(mt.radians(alpha))) * self.d, 1)
956
+ a4t = round((5 + 2 * mt.sin(mt.radians(alpha))) * self.d, 1)
957
+ else:
958
+ a1 = round((5 + 7 * mt.cos(mt.radians(alpha))) * self.d, 1)
959
+ a4t = round((5 + 5 * mt.sin(mt.radians(alpha))) * self.d, 1)
960
+
961
+ a2 = round(5 * self.d, 1)
962
+ a3t = round((10 + 5 * mt.cos(mt.radians(alpha))) * self.d, 1)
963
+ a3c = round(10 * self.d, 1)
964
+ a4c = a2
965
+
966
+ elif rho_k > 420 and rho_k <= 500:
967
+ a1 = round((7 + 8 * mt.cos(mt.radians(alpha))) * self.d, 1)
968
+ a2 = round(7 * self.d, 1)
969
+ a3t = round((15 + 5 * mt.cos(mt.radians(alpha))) * self.d, 1)
970
+ a3c = round(15 * self.d, 1)
971
+ a4c = a2
972
+
973
+ if self.d < 5:
974
+ a4t = round((7 + 2 * mt.sin(mt.radians(alpha))) * self.d, 1)
975
+ else:
976
+ a4t = round((7 + 5 * mt.sin(mt.radians(alpha))) * self.d, 1)
977
+ else:
978
+ print("Il faut absolument prépercer au dessus de rho,k: 500 kg/m3")
979
+
980
+ if self.type_assemblage == __class__.TYPE_ASSEMBLAGE[0]: #Si assemblage bois bois
981
+ pass
982
+
983
+ elif self.type_assemblage == __class__.TYPE_ASSEMBLAGE[1]: #Si assemblage bois métal
984
+ a1 = round(a1 * 0.7, 1)
985
+ a2 = round(a2 * 0.7, 1)
986
+
987
+ else: #Si assemblage bois panneau
988
+ a1 = round(a1 * 0.85, 1)
989
+ a2 = round(a2 * 0.85, 1)
990
+ if beam.type_bois == "CP":
991
+ a3t = round((3 + 4 * mt.sin(mt.radians(alpha))) * self.d, 1)
992
+ a3c = round(3 * self.d, 1)
993
+ a4t = a3t
994
+ a4c = a3c
995
+
996
+ dict_pince["barre "+str(i+1)] = {"a1": a1, "a2":a2, "a3t": a3t, "a3c": a3c, "a4t": a4t, "a4c": a4c}
997
+ return dict_pince
998
+
999
+
1000
+ def prepercage(self, sensible: bool=("False", "True")):
1001
+ """Défini l'épaisseur en mm minimale pour éviter le pré-perçage des pointes
1002
+
1003
+ Args:
1004
+ sensible (bool, optional): Défini si le bois utilisé est sensible à la fissuration (selon AN §8.3.1.2(7) douglas et pin maritime). Defaults to False.
1005
+
1006
+ Returns:
1007
+ int: l'épaisseur du bois en mm
1008
+ """
1009
+ if sensible:
1010
+ t = max(14 * self.d,
1011
+ (13 * self.d - 30) * (self.pk / 200))
1012
+ else:
1013
+ t = max(7 * self.d,
1014
+ (13 * self.d - 30) * (self.pk / 400))
1015
+ print(f"l'épaisseur minimale pour éviter le pré-perçage est de {t} mm")
1016
+ return int(t)
1017
+
1018
+
1019
+
1020
+
1021
+
1022
+
1023
+ # ======================================================= BOULON =========================================================
1024
+ # 8.5 Assemblage par boulon
1025
+
1026
+ class Boulon(Assemblage):
1027
+ """ Défini un objet boulon avec :
1028
+ d : diamètre efficace du boulon (ou du tire fond si >6mm) en mm
1029
+ fuk : la valeur caractéristique de résistance à la traction du boulon en N/mm2
1030
+ n : nombre de boulons dans une file
1031
+ alpha 1 : angle entre l'effort de l'organe et le fil du bois en ° pour la barre 1
1032
+ alpha 2 : angle entre l'effort de l'organe et le fil du bois en ° pour la barre 2
1033
+
1034
+ t1 (int, optional): longueur de contact avec la tige pour la pièce 1 en mm.
1035
+ ATTENTION : Cet argument n'est pas obligatoire par défaut, il est calculé par le type de tige utilisée.
1036
+ Il n'est nécessaire de le remplir uniquement si vous avez un t1 spécifique, par exemple avec une chapelle réduisant ainsi la portance local à une longueur inférieur à celle de l'épaisseur de la pièce 1.
1037
+
1038
+ t2 (int, optional): longueur de contact avec la tige pour la pièce 2 en mm.
1039
+ ENTION : Même chose que pour t1 mais pour la pièce 2.
1040
+ """
1041
+
1042
+ QUALITE_ACIER = tuple(Assemblage._data_from_csv(Assemblage, "qualite_acier.csv").index)
1043
+
1044
+ def __init__(self, d:si.mm, qualite: str=QUALITE_ACIER, n: int=1, alpha1: float=0, alpha2: float=0, t1: int=0, t2: int=0, **kwargs):
1045
+ super().__init__(**kwargs)
1046
+ self.type_organe = "Boulon"
1047
+ if "type_organe" in kwargs.keys():
1048
+ self.type_organe = kwargs.pop("type_organe")
1049
+ self.d = d * si.mm
1050
+ self.qualite = qualite
1051
+ self.fuk = self.__qualite_acier.loc["fub"] *si.MPa
1052
+ self.n = n
1053
+ self._nef = n
1054
+ self.alpha = [alpha1, alpha2]
1055
+ self.t1 = t1
1056
+ self.t2 = t2
1057
+
1058
+ self.__t1_t2()
1059
+ self._fhik()
1060
+
1061
+ @property
1062
+ def __qualite_acier(self):
1063
+ df = self._data_from_csv("qualite_acier.csv")
1064
+ df = df.loc[self.qualite]
1065
+ return df
1066
+
1067
+
1068
+ # 8.5.1 Boulons chargés latéralement
1069
+ # 8.5.1.1 Généralité et assemblage bois/bois
1070
+
1071
+ def __t1_t2(self):
1072
+ """Retourne t1 et t2 en mm suivant l'EN 1995 §8.3.1.1
1073
+ """
1074
+ for i, _ in enumerate([self.beam_1, self.beam_2]):
1075
+ if self._type_beam[i] != "Métal":
1076
+ if not i:
1077
+ if not self.t1:
1078
+ if self.type_organe == "Tirefond" and self.nCis == 2:
1079
+ if "Bois/Métal" in self.type_assemblage:
1080
+ b_beam_2 = self.beam_2.t + 2
1081
+ else:
1082
+ b_beam_2 = self.beam_2.b_calcul
1083
+ l_pointe = self.d_vis
1084
+ print(self.l , self.beam_1.b_calcul , b_beam_2 , l_pointe)
1085
+ self.t1 = min(self.beam_1.b_calcul, self.l - self.beam_1.b_calcul - b_beam_2 - l_pointe)
1086
+ continue
1087
+ self.t1 = self.beam_1.b_calcul
1088
+ else:
1089
+ self.t1 = self.t1 * si.mm
1090
+ else:
1091
+ l_pointe = 0
1092
+ if self.type_organe == "Tirefond":
1093
+ l_pointe = self.d_vis
1094
+ l_vis = self.l
1095
+ if i:
1096
+ if not self.t2:
1097
+ self.t2 = min(self.beam_2.b_calcul,l_vis-l_pointe-self.t1)
1098
+ else:
1099
+ self.t2 = self.t2 * si.mm
1100
+ else:
1101
+ if i:
1102
+ if not self.t2:
1103
+ self.t2 = self.beam_2.b_calcul
1104
+ else:
1105
+ self.t2 = self.t2 * si.mm
1106
+
1107
+
1108
+ def _fh0k(self, beam: object):
1109
+ """Calcul la portance locale d'un boulon bois/bois ou d'un tire fond si d>6mm avec :
1110
+ beam: poutre à calculer
1111
+ """
1112
+ rho_k = beam.rho_k
1113
+ d = self.d.value *10**3
1114
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1115
+ def val():
1116
+ f_h0k = 0.082 * (1 - 0.01 * d) * rho_k # MPa
1117
+ return f_h0k * si.MPa
1118
+ return val()
1119
+
1120
+
1121
+ def _K_90(self, beam: object):
1122
+ """Coef. modélisant la diminution de portance local quand un angle est donnée entre l'effort et le fil avec
1123
+ beam: poutre à calculer"""
1124
+
1125
+ if beam.classe[0:1] == "C" or beam.classe[0:2] == "GL":
1126
+ type_b = "C"
1127
+ elif beam.classe[0:3] == "LVL":
1128
+ type_b = "LVL"
1129
+ else:
1130
+ type_b = "D"
1131
+
1132
+ if type_b == "C":
1133
+ ck90 = 1.35 + 0.015 * self.d.value *10**3
1134
+ elif type_b == "LVL":
1135
+ ck90 = 1.30 + 0.015 * self.d.value *10**3
1136
+ else:
1137
+ ck90 = 0.9 + 0.015 * self.d.value *10**3
1138
+ return ck90
1139
+
1140
+
1141
+ def _fhak(self, fh0k:float, k_90:float, alpha):
1142
+ """Calcul la portance locale d'un boulon bois/bois ou d'un tire fond si d>6mm par rapport à un effort donné à un angle
1143
+ du fil en MPa avec :
1144
+ fh0k : portance locale dans le sens du fil d'un boulon
1145
+ alpha : angle entre l'effort de l'organe et le fil du bois en °
1146
+ k90 : coef. de réduction de la portance locale quand un effort à un angle par rapport au fil du bois"""
1147
+ f_h0k = fh0k[1]
1148
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1149
+ def val():
1150
+ f_h_alpha_k = f_h0k / (k_90 * sin(radians(alpha)) ** 2 + cos(radians(alpha)) ** 2)
1151
+ return f_h_alpha_k
1152
+ return val()
1153
+
1154
+
1155
+ # 8.5.1.1 Généralité et assemblage bois/panneaux
1156
+ def _fhk(self, beam:object):
1157
+ """ Calcul la portance locale d'un boulon dans un assemblage bois/panneaux en MPa avec :
1158
+ d : diamètre efficace du boulon (ou du tire fond si >6mm) en mm
1159
+ rho_k : masse volumique caractéristique du contreplaqué en kg/m3
1160
+ ep : epaisseur du panneau en mm """
1161
+ rho_k = beam.rho_k
1162
+ d = self.d.value *10**3
1163
+ ep = beam.b_calcul.value *10**3
1164
+
1165
+ if beam.type_bois == "CP":
1166
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1167
+ def val():
1168
+ f_hk = 0.11 * (1 - 0.01 * d) * rho_k # MPa
1169
+ return f_hk
1170
+ else:
1171
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1172
+ def val():
1173
+ f_hk = 50 * (d**(-0.6)) * (ep**0.2) # MPa
1174
+ return f_hk
1175
+ return val()
1176
+
1177
+
1178
+
1179
+ def _fhik(self):
1180
+ """Calcul la portance locale d'un boulon bois/bois ou d'un tire fond si d>6mm
1181
+ """
1182
+
1183
+ dict_beam = {"1": {}, "2": {}}
1184
+
1185
+ for i, beam in enumerate([self.beam_1, self.beam_2]):
1186
+ if self._type_beam[i] == "Bois":
1187
+ dict_beam[str(i+1)]["fh0k"] = self._fh0k(beam)
1188
+ dict_beam[str(i+1)]["K90"] = self._K_90(beam)
1189
+ dict_beam[str(i+1)]["fhik"] = self._fhak(dict_beam[str(i+1)]["fh0k"], dict_beam[str(i+1)]["K90"], self.alpha[i])
1190
+ dict_beam[str(i+1)]["fhik"] = (dict_beam[str(i+1)]["fh0k"][0] + dict_beam[str(i+1)]["fhik"][0], dict_beam[str(i+1)]["fhik"][1])
1191
+
1192
+ elif self._type_beam[i] == "CP" or self._type_beam[i] == "PP/OSB":
1193
+ dict_beam[str(i+1)]["fhik"] = self._fhk(beam)
1194
+
1195
+ else:
1196
+ dict_beam[str(i+1)]["fhik"] = 0
1197
+
1198
+ self.fh1k = dict_beam["1"]["fhik"]
1199
+ self.fh2k = dict_beam["2"]["fhik"]
1200
+ return self.fh1k, self.fh2k
1201
+
1202
+
1203
+ @property
1204
+ def MyRk(self):
1205
+ """Défini le moment d'écoulement plastique d'un boulon en N.mm avec:
1206
+ fuk : la valeur caractéristique de résistance à la traction du boulon en N/mm2
1207
+ d : diamètre efficace du boulon (ou du tire fond si >6mm) en mm"""
1208
+ f_uk = self.fuk.value * 10**-6
1209
+ d = self.d.value * 10**3
1210
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1211
+ def val():
1212
+ M_y_Rk = 0.3 * f_uk * d ** 2.6 # N.mm
1213
+ return M_y_Rk * si.N*si.mm
1214
+ return val()
1215
+
1216
+
1217
+ @property
1218
+ def pince(self):
1219
+ """Défini les différentes pinces minimales pour un boulon en mm avec :
1220
+ alpha : angle entre l'effort de l'organe et le fil du bois en °
1221
+ d : diamètre efficace du boulon (ou du tire fond si >6mm) en mm """
1222
+ dict_pince = {}
1223
+ if self.type_organe == "Tirefond":
1224
+ self.d = self.d_vis
1225
+ for i, alpha in enumerate(self.alpha):
1226
+ if not self._type_beam[i] in self.TYPE_BOIS_ASSEMBLAGE:
1227
+ continue
1228
+ a1 = round((4 + mt.cos(mt.radians(alpha))) * self.d, 1)
1229
+ a2 = round(4 * self.d, 1)
1230
+ a3t = round(max(7 * self.d, 80*si.mm),1)
1231
+
1232
+ if alpha <= 30:
1233
+ a3c = round(4 * self.d, 1)
1234
+ else:
1235
+ a3c = round((1 + 6 * mt.sin(mt.radians(alpha))) * self.d, 1)
1236
+
1237
+ a4t = round(max((2 + 2 * mt.sin(mt.radians(alpha))) * self.d, 3 * self.d), 1)
1238
+ a4c = round(3 * self.d, 1)
1239
+ dict_pince["barre "+str(i+1)] = {"a1": a1, "a2":a2, "a3t": a3t, "a3c": a3c, "a4t": a4t, "a4c": a4c}
1240
+ return dict_pince
1241
+
1242
+
1243
+ def nef(self, a1_beam1:int, a1_beam2:int):
1244
+ """Défini le nombre efficace d'organe (boulon) dans une file avec :
1245
+ a1 : l'espacement entre boulon dans le sens du fil du bois
1246
+ n : nombre de boulons dans une file
1247
+ d : diamètre efficace du boulon (ou du tire fond si >6mm) en mm"""
1248
+ d = self.d
1249
+ if self.type_organe == "Tirefond":
1250
+ d = self.d_vis
1251
+
1252
+ nef_list = []
1253
+ for i, alpha in enumerate(self.alpha):
1254
+ if i:
1255
+ a_1 = a1_beam2 * si.mm
1256
+ n = self.nfile
1257
+ else:
1258
+ a_1 = a1_beam1 * si.mm
1259
+ n = self.n
1260
+
1261
+ if n == 1 or alpha == 90:
1262
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1263
+ def val():
1264
+ n_ef = n
1265
+ return n_ef
1266
+ nef_list.append(val())
1267
+ else:
1268
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1269
+ def val():
1270
+ n_ef = min(n**0.9 * (a_1/(13 * d))**(1/4), n)
1271
+ return n_ef
1272
+ nef_list.append(val())
1273
+
1274
+ if alpha > 0 and alpha < 90:
1275
+ n_ef = nef_list[i][1]
1276
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1277
+ def nef_a():
1278
+ n_ef_a = n_ef + alpha * (n - n_ef)/90
1279
+ return n_ef_a
1280
+ value2 = nef_a()
1281
+ nef_list[i] = (nef_list[i][0] + value2[0] , value2[1])
1282
+ result = self._min_nef(nef_list)
1283
+ self._nef = result[1]
1284
+ return result
1285
+
1286
+
1287
+ # 8.5.2 Boulons chargés axialement
1288
+ def Fax_Rk(self, d_int: float=0, d_ext: float=0, filetage_EN1090: bool=("True", "False")):
1289
+ """Calcul la résistance axial caractéristique d'un boulon chargé axialement à partir soit de la rondelle soit de la plaque métalique.
1290
+
1291
+ Args:
1292
+ d_int (float, optional): diamètre intérieur de la rondelle en mm ou du trou de perçage dans la plaque métallique. Defaults to 0.
1293
+ d_ext (float, optional): diamètre extérieur de la rondelle en mm. Defaults to 0.
1294
+ filetage_EN1090 (bool, optional): définit si le filetage est conforme à l'EN 1090, soit matricé. Si filetage usiné alors False. Defaults to True.
1295
+
1296
+ Returns:
1297
+ FaxRk: la résistance axial d'un boulon en N
1298
+ """
1299
+ from ourocode.eurocode.EC3_Assemblage import Tige
1300
+ d_int = d_int * si.mm
1301
+ d_ext = d_ext * si.mm
1302
+
1303
+ if self._type_beam[0] == "Métal":
1304
+ FtRd = Tige(self.d.value*10**3, d_int, self.qualite, True, filetage_EN1090, t=self.beam_1.t.value*10**3, h=self.beam_1.h.value*10**3, classe_acier=self.beam_1.classe_acier, classe_transv=self.beam_1.classe_transv).FtRd
1305
+ d_ext = min(self.beam_1.t*12, 4*self.d)
1306
+ fc_90_k = float(self.beam_2.caract_meca.loc["fc90k"]) * si.MPa
1307
+ else:
1308
+ FtRd = Tige(self.d.value*10**3, d_int, self.qualite, True, filetage_EN1090, t=0, h=0, classe_acier="S235", classe_transv=3).FtRd
1309
+ fc_90_k = float(self.beam_1.caract_meca.loc["fc90k"]) * si.MPa
1310
+
1311
+ Ft_Rd = FtRd[1]
1312
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1313
+ def val():
1314
+ A_int = pi * (d_int / 2)**2
1315
+ A_rondelle = pi * (d_ext / 2)**2 - A_int
1316
+
1317
+ f_c90_k_rond = fc_90_k * 3
1318
+ F_c90_d = f_c90_k_rond * A_rondelle
1319
+ F_ax_Rk = min(F_c90_d, Ft_Rd)
1320
+ return F_ax_Rk
1321
+ FaxRk = val()
1322
+ self.FaxRk = FaxRk[1]
1323
+ return (FtRd[0] + FaxRk[0], FaxRk[1])
1324
+
1325
+
1326
+ # ======================================================= BROCHE =========================================================
1327
+ # 8.6 Assemblage par broche
1328
+
1329
+ class Broche(Boulon):
1330
+ """ Créer une classe Broche.
1331
+ d : diamètre efficace de la broche ( entre 6 et 30 mm) en mm
1332
+ qualite : qualite de la broche
1333
+ n : nombre de broche dans une file
1334
+ alpha : angle entre l'effort de l'organe et le fil du bois en °
1335
+
1336
+ t1 (int, optional): longueur de contacte avec la tige pour la pièce 1 en mm.
1337
+ ATTENTION : Cet argument n'est pas obligatoire par défaut, il est calculer par le type de tige utilisée.
1338
+ Il n'est nécessaire de le remplir que si vous avez un t1 spécifique, par exemple avec une chapelle réduisant ainsi la portance local à une longueur inférieur à celle de l'épaisseur de la pièce 1.
1339
+
1340
+ t2 (int, optional): longueur de contacte avec la tige pour la pièce 2 en mm.
1341
+ ATTENTION : Même chose que pour t1 mais pour la pièce 2.
1342
+ """
1343
+
1344
+ def __init__(self, d:float, qualite: str=Boulon.QUALITE_ACIER, n: int=1, alpha1: float=0, alpha2: float=0, t1: int=0, t2: int=0, **kwargs):
1345
+ super().__init__(d, qualite, n, alpha1, alpha2, **kwargs)
1346
+ self.type_organe = "Broche"
1347
+
1348
+ @property
1349
+ def Fax_Rk(self):
1350
+ self.FaxRk = 0
1351
+ return 0
1352
+
1353
+ @property
1354
+ def pince(self):
1355
+ """Défini les différentes pinces minimales pour une broche en mm avec :
1356
+ alpha : angle entre l'effort de l'organe et le fil du bois en °
1357
+ d : diamètre efficace du boulon (ou du tire fond si >6mm) en mm """
1358
+ dict_pince = {}
1359
+ for i, alpha in enumerate(self.alpha):
1360
+ a1 = round((3 + 2 * (mt.cos(mt.radians(alpha)))) * self.d, 1)
1361
+ a2 = round(3 * self.d, 1)
1362
+ a3t = round(max(7 * self.d, 80*si.mm), 1)
1363
+
1364
+ if alpha <= 150 and alpha < 210:
1365
+
1366
+ a3c = round(max(3.5 * self.d, 40*si.mm), 1)
1367
+
1368
+ else:
1369
+
1370
+ a3c = round((a3t * mt.sin(mt.radians(alpha))), 1)
1371
+
1372
+ a4t = round(max((2 + 2 * mt.sin(mt.radians(alpha))) * self.d, 3 * self.d), 1)
1373
+ a4c = round(3 * self.d, 1)
1374
+ dict_pince["barre "+str(i+1)] = {"a1": a1, "a2":a2, "a3t": a3t, "a3c": a3c, "a4t": a4t, "a4c": a4c}
1375
+ return dict_pince
1376
+
1377
+
1378
+ # ======================================================= TIREFOND =========================================================
1379
+
1380
+
1381
+ class _Tirefond(object):
1382
+ def __init__(self, d:si.mm, d1:si.mm, ds:si.mm, dh:si.mm, l:si.mm, n, rho_a:float, fhead:float, ftensk:float, MyRk:float=0, alpha1: float=0, alpha2: float=0, percage: bool=("False", "True"), **kwargs):
1383
+ """Défini un object tirefond
1384
+
1385
+ Args:
1386
+ d (si.mm): diamètre extérieur du filet en mm
1387
+ d1 (float): diamètre du noyaux en mm
1388
+ ds (float): diamètre de la tête en mm
1389
+ dh (float): diamètre de la tête en mm
1390
+ l (float): longueur total de la vis en mm
1391
+ n (int): le nombre de vis dans une file
1392
+ rho_a (float): masse volumique associée au tirefond en fax,k en kg/m3
1393
+ fhead (float): valeur caractéristique de traversée de la tête du tirefond à l'EN 14592 en Mpa
1394
+ ftensk (float): valeur caractéristique en traction du tirefond en N
1395
+
1396
+ MyRk (float, optional): le moment d'écoulement plastique de la vis en N.mm.
1397
+ Si cette attribut est remplie, alors on récupère la valeur founis sinon on le calcul à l'EC5.
1398
+ Defaults to 0.
1399
+
1400
+ alpha1 (float, optional): angle entre l'effort de l'organe et le fil du bois 1 en °. Defaults to 0.
1401
+ alpha2 (float, optional): angle entre l'effort de l'organe et le fil du bois 2 en °. Defaults to 0.
1402
+ percage (bool, optional): l'élément est-il préperçé ? Si oui alors True. Defaults to ("False", "True").
1403
+ """
1404
+ self.d_vis = d * si.mm
1405
+ self.d1 = d1 * si.mm
1406
+ self.ds = ds * si.mm
1407
+ self.dh = dh * si.mm
1408
+ # self.d_ef = min(d1*1.1, ds) A valider !!!!!
1409
+ self.d_ef = d1*1.1
1410
+ self.l = l * si.mm #longueur sous tête
1411
+ self.n = n
1412
+ self.percage = percage
1413
+ self.alpha = [alpha1, alpha2]
1414
+ self.type_organe = "Tirefond"
1415
+ self.rho_a = rho_a * si.kg/si.m**3
1416
+ self.fhead = fhead * si.MPa
1417
+ self.ftensk = ftensk * si.N
1418
+
1419
+
1420
+ # 8.7.2 Tirefond chargés axialement
1421
+ def pince_tirefond_axial(self, t: int):
1422
+ """
1423
+ Défini les pinces d'un tirefond en mm lorsqu'il est chargée axialement et l'epaisseur de bois supérieur à 12*d.
1424
+ Args:
1425
+ t(int) : epaisseur de bois en mm
1426
+ """
1427
+ if t >= 12 * self.d_vis:
1428
+
1429
+ a1 = 7 * self.d_vis
1430
+ a2 = 5 * self.d_vis
1431
+ a1CG = 10 * self.d_vis
1432
+ a2CG = 4 * self.d_vis
1433
+ else:
1434
+ print("L'épaisseur de bois n'est pas suffisante, il faut un bois de {0} mm minimum !".format(
1435
+ 12*self.d_vis))
1436
+ return {"a1": a1, "a2": a2, "a1CG": a1CG, "a2CG": a2CG}
1437
+
1438
+
1439
+ @property
1440
+ def nefTraction(self):
1441
+ """Renvoie le nombre efficace de tirefond quand ils sont solicités par une composante parallèle à la partie lisse."""
1442
+ n = self.n * self.nfile
1443
+ if n > 1:
1444
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1445
+ def val():
1446
+ n_ef_traction = n**0.9
1447
+ return n_ef_traction
1448
+ else:
1449
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1450
+ def val():
1451
+ n_ef_traction = 1
1452
+ return n_ef_traction
1453
+ return val()
1454
+
1455
+
1456
+ def faxk(self, l_ef:int, beam:str=["1", "2"]):
1457
+ """
1458
+ Calcul la valeur caractéristique de la résistance à l'arrachement perpendiculaire au fil en N/mm2 si 6mm<=d<=12mm
1459
+ et 0.6<=d1/d<=0.75.
1460
+
1461
+ Args:
1462
+ l_ef (int): longueur de pénétration de la partie filetée en mm
1463
+ beam (str): élément à calculer 1 ou 2
1464
+ """
1465
+ d = self.d_vis.value*10**3
1466
+ d1 = self.d1.value*10**3
1467
+ if beam == "1":
1468
+ rho_k = self.beam_1.rho_k
1469
+ else:
1470
+ rho_k = self.beam_2.rho_k
1471
+
1472
+ if 6 <= d <= 12 and 0.6 <= d1 / d <= 0.75:
1473
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1474
+ def val():
1475
+ f_axk = 0.52 * (d ** -0.5) * (l_ef ** -0.1) * (rho_k ** 0.8)
1476
+ return f_axk
1477
+ return val()
1478
+
1479
+ else:
1480
+ print(
1481
+ "le diamètre ne répond pas aux spécifications demandées en 8.7.2(4) de l'EN 1995 partie assemblage")
1482
+
1483
+
1484
+ def _FaxaRk(self, faxk:float, l_ef:int, alpha:int, beam:str=["1", "2"]):
1485
+ """
1486
+ Calcul la valeur caractéristique de la résistance à l'arrachement du tirefond à un angle alpha par rapport au fil en N.
1487
+
1488
+ Args:
1489
+ faxk (float): Valeur caractéristique de résistance à l'arrachement perpendiculaire au fil en N/mm2
1490
+ l_ef (int): longueur de pénétration de la partie filetée en mm
1491
+ alpha (int): angle formé entre l'axe du tirefond et le fil du bois, doit être supérieur à 30°
1492
+ beam (str): élement à calculer 1 ou 2
1493
+ """
1494
+ d = self.d_vis.value*10**3
1495
+ d_1 = self.d1
1496
+ rho_a = self.rho_a.value
1497
+ if beam == "1":
1498
+ rho_k = self.beam_1.rho_k
1499
+ else:
1500
+ rho_k = self.beam_2.rho_k
1501
+
1502
+ if 6 <= d <= 12 and 0.6 <= (d_1 / d) <= 0.75:
1503
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1504
+ def val():
1505
+ kd = min((d / 8), 1)
1506
+ F_ax_a_Rk = (faxk * d * l_ef * kd) / (1.2 * cos(radians(alpha)) ** 2 + sin(radians(alpha)) ** 2)
1507
+ return F_ax_a_Rk
1508
+ else:
1509
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1510
+ def val():
1511
+ F_ax_a_Rk = ((faxk * d * l_ef) / (1.2 * (cos(radians(alpha))) ** 2 + (sin(radians(alpha))) ** 2)) * ((rho_k / rho_a) ** 0.8) #N
1512
+ return F_ax_a_Rk
1513
+ return val()
1514
+
1515
+ def _FaxaRkHead(self):
1516
+ """
1517
+ Calcul la valeur caractéristique de résistance à la traversée de la tête du tirefond dans l'assemblage en N.
1518
+ """
1519
+ f_head = self.fhead.value*10**-6
1520
+ d_h = self.dh.value*10**3
1521
+ rho_a = self.rho_a.value
1522
+ rho_k = self.beam_1.rho_k
1523
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1524
+ def val():
1525
+ F_axRkhead = f_head * d_h**2 * ((rho_k/rho_a)**0.8) #N
1526
+ return F_axRkhead
1527
+ return val()
1528
+
1529
+
1530
+ def Fax_Rk(self, faxk:float, l_ef:int, alpha:int, beam:str=["1", "2"]):
1531
+ """Calcul la valeur caractéristique de résistance du tirefond axialement entre la résistance caractéristique de la tête et du pas de vis dans le bois en N.
1532
+ Cette fonction détermine ensuite la valeur de résistance caractéristique de l'assemblage en prenant compte du nombre efficace de tirefond en traction.
1533
+
1534
+ Args:
1535
+ faxk (float): Valeur caractéristique de résistance à l'arrachement perpendiculaire au fil en N/mm2
1536
+ l_ef (int): longueur de pénétration de la partie filetée en mm
1537
+ alpha (int): angle formé entre l'axe du tirefond et le fil du bois, doit être supérieur à 30°
1538
+ beam (str, optional): élément à calculer 1 ou 2
1539
+ """
1540
+ F_ax_a_Rk_value = self._FaxaRk(faxk, l_ef, alpha, beam)
1541
+ F_ax_a_Rk = F_ax_a_Rk_value[1]
1542
+ F_ax_a_Rk_head_value = self._FaxaRkHead()
1543
+ F_ax_a_Rk_head = F_ax_a_Rk_head_value[1]
1544
+
1545
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1546
+ def val():
1547
+ F_ax_Rk = min(F_ax_a_Rk, F_ax_a_Rk_head) #N
1548
+ return F_ax_Rk
1549
+ FaxRk = val()
1550
+ self.FaxRk = FaxRk[1]
1551
+
1552
+ f_ax_Rk = FaxRk[1]
1553
+ n_ef_traction = self.nefTraction[1]
1554
+
1555
+ @handcalc(override="long", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1556
+ def val_ass():
1557
+ F_ax_Rk_ass = f_ax_Rk * n_ef_traction # N
1558
+ return F_ax_Rk_ass
1559
+ F_ax_Rk_ass = val_ass()
1560
+
1561
+ return (F_ax_a_Rk_value[0] + F_ax_a_Rk_head_value[0] + FaxRk[0] + F_ax_Rk_ass[0], F_ax_Rk_ass[1])
1562
+
1563
+
1564
+ def FtRk(self):
1565
+ """ Calcul la résistance caractéristique en traction pur du fil des tirefonds dans l'assemblage en N."""
1566
+ n_ef_traction = self.nefTraction[1]
1567
+ f_tens_k = self.ftensk
1568
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1569
+ def val():
1570
+ f_tRk = n_ef_traction * f_tens_k
1571
+ return f_tRk
1572
+ return val()
1573
+
1574
+
1575
+ class Tirefond_inf_7(_Tirefond, Pointe):
1576
+ def __init__(self, d:si.mm, d1:float, ds:float, dh:float, l:float, n:int, rho_a:float, fhead:float, ftensk:float, MyRk:float=0, alpha1: float=0, alpha2: float=0, percage: bool=("False", "True"), **kwargs):
1577
+ """Défini un object tirefond qui a un diamètre efficace inférieur à 6mm
1578
+
1579
+ Args:
1580
+ d (si.mm): diamètre extérieur du filet en mm
1581
+ d1 (float): diamètre du noyaux en mm
1582
+ ds (float): diamètre de la tête en mm
1583
+ dh (float): diamètre de la tête en mm
1584
+ l (float): longueur total de la vis en mm
1585
+ n (int): le nombre de vis dans une file
1586
+ rho_a (float): masse volumique associée au tirefond en fax,k en kg/m3
1587
+ fhead (float): valeur caractéristique de traversée de la tête du tirefond à l'EN 14592 en Mpa
1588
+ ftensk (float): valeur caractéristique en traction du tirefond en N
1589
+
1590
+ MyRk (float, optional): le moment d'écoulement plastique de la vis en N.mm.
1591
+ Si cette attribut est remplie, alors on récupère la valeur founis sinon on le calcul à l'EC5.
1592
+ Defaults to 0.
1593
+
1594
+ alpha1 (float, optional): angle entre l'effort de l'organe et le fil du bois 1 en °. Defaults to 0.
1595
+ alpha2 (float, optional): angle entre l'effort de l'organe et le fil du bois 2 en °. Defaults to 0.
1596
+ percage (bool, optional): l'élément est-il préperçé ? Si oui alors True. Defaults to ("False", "True").
1597
+ """
1598
+ qualite = "6.8"
1599
+ self.d_vis = d * si.mm
1600
+ if "qualite" in kwargs.keys():
1601
+ qualite = kwargs.pop("qualite")
1602
+
1603
+ if d1*1.1 <= 6:
1604
+ Pointe.__init__(self, d=d1*1.1, d_tete=dh, l=l, qualite=qualite, n=n, alpha1=alpha1, alpha2=alpha2, type_organe="Tirefond", percage=percage, **kwargs)
1605
+ _Tirefond.__init__(self, d, d1, ds, dh, l, n, rho_a, fhead, ftensk, MyRk, alpha1, alpha2, percage)
1606
+ else:
1607
+ raise "Erreur, le tirefond est considéré comme un boulon et non une pointe"
1608
+
1609
+ if MyRk:
1610
+ self._MyRk_fourni = MyRk * si.N*si.mm
1611
+
1612
+ @property
1613
+ def MyRk(self):
1614
+ if hasattr(self, "_MyRk_fourni"):
1615
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1616
+ def val():
1617
+ MyRk = self._MyRk_fourni
1618
+ return MyRk
1619
+ return val()
1620
+ else:
1621
+ return super().MyRk
1622
+
1623
+
1624
+ class Tirefond_sup_6(_Tirefond, Boulon):
1625
+ """ Défini un object tirefond avec :
1626
+ d : diamètre extérieur du filet en mm
1627
+ d1 : diamètre du noyaux en mm
1628
+ dh : diamètre de la tête en mm
1629
+ rho_a : masse volumique associée au tirefond en fax,k en kg/m3
1630
+ fhead : valeur caractéristique de traversée de la tête du tirefond à l'EN14592 en Mpa
1631
+ ftensk : valeur caractéristique en traction du tirefond en N
1632
+ n : nombre de boulons dans une file
1633
+ alpha1 : angle entre l'effort de l'organe et le fil du bois 1 en °
1634
+ alpha2 : angle entre l'effort de l'organe et le fil du bois 2 en °"""
1635
+
1636
+ def __init__(self, d:si.mm, d1:float, ds:float, dh:float, l:si.mm, n, rho_a:float, fhead:float, ftensk:float, MyRk:float=0, alpha1: float=0, alpha2: float=0, **kwargs):
1637
+ """Défini un object tirefond qui a un diamètre efficace supérieur à 6mm
1638
+
1639
+ Args:
1640
+ d (si.mm): diamètre extérieur du filet en mm
1641
+ d1 (float): diamètre du noyaux en mm
1642
+ ds (float): diamètre de la tête en mm
1643
+ dh (float): diamètre de la tête en mm
1644
+ l (float): longueur total de la vis en mm
1645
+ n (int): le nombre de vis dans une file
1646
+ rho_a (float): masse volumique associée au tirefond en fax,k en kg/m3
1647
+ fhead (float): valeur caractéristique de traversée de la tête du tirefond à l'EN 14592 en Mpa
1648
+ ftensk (float): valeur caractéristique en traction du tirefond en N
1649
+
1650
+ MyRk (float, optional): le moment d'écoulement plastique de la vis en N.mm.
1651
+ Si cette attribut est remplie, alors on récupère la valeur founis sinon on le calcul à l'EC5.
1652
+ Defaults to 0.
1653
+
1654
+ alpha1 (float, optional): angle entre l'effort de l'organe et le fil du bois 1 en °. Defaults to 0.
1655
+ alpha2 (float, optional): angle entre l'effort de l'organe et le fil du bois 2 en °. Defaults to 0.
1656
+ """
1657
+ qualite = "6.8"
1658
+ self.d_vis = d * si.mm
1659
+ self.l = l * si.mm
1660
+ if "qualite" in kwargs.keys():
1661
+ qualite = kwargs.pop("qualite")
1662
+
1663
+ if d1*1.1 > 6:
1664
+ Boulon.__init__(self, d=d1*1.1, qualite=qualite, n=n, alpha1=alpha1, alpha2=alpha2, type_organe="Tirefond", **kwargs)
1665
+ _Tirefond.__init__(self, d, d1, ds, dh, l, n, rho_a, fhead, ftensk, MyRk, alpha1, alpha2)
1666
+
1667
+ else:
1668
+ print("Erreur, le tirefond est considéré comme une pointe et non un boulon")
1669
+
1670
+ if MyRk:
1671
+ self._MyRk_fourni = MyRk * si.N*si.mm
1672
+
1673
+ @property
1674
+ def MyRk(self):
1675
+ if hasattr(self, "_MyRk_fourni"):
1676
+ @handcalc(override="short", precision=2, jupyter_display=self.JUPYTER_DISPLAY, left="\\[", right="\\]")
1677
+ def val():
1678
+ MyRk = self._MyRk_fourni
1679
+ return MyRk
1680
+ return val()
1681
+ else:
1682
+ return super().MyRk
1683
+ # ======================================================= ANNEAU =========================================================
1684
+ # 8.9 Assemblage par anneaux
1685
+
1686
+
1687
+ # class Annneau(object):
1688
+ # """Défini un objet anneau avec :"""
1689
+
1690
+ # def __init__(self, dc: float, t1:float, t2:float, hc:float, typeA="bois"):
1691
+ # self.type_organe = "Anneau"
1692
+ # self.dc = dc
1693
+ # self.t1 = t1
1694
+ # self.t2 = t2
1695
+ # self.he = hc/2
1696
+ # self.typeA = typeA
1697
+
1698
+ # def ki(self, nAss:int, a3t:float, rhok:int):
1699
+ # """ Donne les facteur ki (de 1 à 4) dans un dico avec:
1700
+ # nAss : nombre d'assemblage par plan de cisaillement
1701
+ # a3t = distance d'extrémité chargé (en traction) """
1702
+ # listk = [0.0]*4
1703
+
1704
+ # if nAss > 1:
1705
+ # ka = 1
1706
+ # else:
1707
+ # ka = 1.25
1708
+
1709
+ # listk[0] = min(1,
1710
+ # self.t1 / (3 * self.he),
1711
+ # self.t2 / (5 * self.he))
1712
+
1713
+ # listk[1] = min(ka,
1714
+ # a3t / (2 * self.dc))
1715
+
1716
+ # listk[2] = min(1.75,
1717
+ # rhok / 350)
1718
+
1719
+ # if self.typeA == "bois":
1720
+ # k4 = 1
1721
+ # else:
1722
+ # k4 = 1.25
1723
+ # listk[3] = k4
1724
+ # dico = {}
1725
+ # for i in range(1, 5):
1726
+ # cle = "k" + str(i)
1727
+ # dico[cle] = listk[i-1]
1728
+
1729
+ # return dico
1730
+
1731
+ # def Fv0Rk(self, dicoKi:dict):
1732
+ # """ Retourne la résistance en cidaillement de l'anneau en N avec:
1733
+ # dicoKi = dictionnaire des facteurs ki (def ki)"""
1734
+ # fv0rk = min(dicoKi["k1"] * dicoKi["k2"] * dicoKi["k3"] * dicoKi["k4"] * (35 * self.dc**1.5),
1735
+ # dicoKi["k1"] * dicoKi["k3"] * self.he * (31.5 * self.dc))
1736
+ # return fv0rk
1737
+
1738
+
1739
+ # def FvaRk(self):
1740
+ # pass
1741
+
1742
+
1743
+ if __name__ == "__main__":
1744
+ from EC5_Element_droit import Barre
1745
+ from EC3_Element_droit import Element
1746
+
1747
+ beam1 = Barre(60, 140, "Rectangulaire", classe="C24", cs=2)
1748
+ beam1._f_type_d("fm0k", "Instantanee", "Fondamentales")
1749
+
1750
+ beam2 = Barre(160, 160, "Rectangulaire", classe="GL24h", cs=2)
1751
+ beam1._f_type_d("fm0k", "Instantanee", "Fondamentales")
1752
+
1753
+ ass = Assemblage(beam1, beam2, nfile=1, nCis=2)
1754
+ bl = Boulon._from_parent_class(ass, d=12, qualite="4.6", n=2, alpha=0)
1755
+ bl.FaxRk(14,30,True,"Court terme", "Fondamentales")
1756
+ print(bl.FvRk(True))
1757
+
1758
+ # pointe = Pointe._from_parent_class(ass, d=6, d_tete=12, l=120, qualite="10.9", n=1, alpha=0, type_organe="Autres pointes", percage="False")
1759
+ # print(pointe.pince_ass)
1760
+