ourocode 1.6.9__tar.gz → 1.7.0__tar.gz

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 (73) hide show
  1. {ourocode-1.6.9/ourocode.egg-info → ourocode-1.7.0}/PKG-INFO +1 -1
  2. ourocode-1.7.0/ourocode/__version__.py +1 -0
  3. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/A0_Projet.py +372 -83
  4. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC0_Combinaison.py +8 -5
  5. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC1_Neige.py +1 -1
  6. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC1_Vent.py +94 -40
  7. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC5_Assemblage.py +63 -22
  8. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC5_Element_droit.py +2 -2
  9. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/objet.py +13 -1
  10. {ourocode-1.6.9 → ourocode-1.7.0/ourocode.egg-info}/PKG-INFO +1 -1
  11. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode.egg-info/SOURCES.txt +2 -20
  12. {ourocode-1.6.9 → ourocode-1.7.0}/pyproject.toml +1 -1
  13. ourocode-1.7.0/tests/test_A0_Projet.py +126 -0
  14. ourocode-1.7.0/tests/test_EC1_Neige.py +168 -0
  15. {ourocode-1.6.9 → ourocode-1.7.0}/tests/test_EC5_Feu.py +10 -10
  16. ourocode-1.6.9/ourocode/__version__.py +0 -1
  17. ourocode-1.6.9/ourocode/data/carte_action_region.csv +0 -36722
  18. ourocode-1.6.9/ourocode/data/exploitation.csv +0 -17
  19. ourocode-1.6.9/ourocode/data/vent/vent_Cp_toiture_isolee_1_versant.csv +0 -22
  20. ourocode-1.6.9/ourocode/data/vent/vent_Cp_toiture_isolee_1_versant.png +0 -0
  21. ourocode-1.6.9/ourocode/data/vent/vent_Cp_toiture_isolee_2_versants.csv +0 -31
  22. ourocode-1.6.9/ourocode/data/vent/vent_Cp_toiture_isolee_2_versants.png +0 -0
  23. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_mur_verticaux.csv +0 -11
  24. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_mur_verticaux.png +0 -0
  25. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_1_versant.png +0 -0
  26. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_1_versant_0_degres.csv +0 -13
  27. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_1_versant_180_degres.csv +0 -13
  28. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_1_versant_90_degres.csv +0 -13
  29. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_2_versants.png +0 -0
  30. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_2_versants_0_degres.csv +0 -21
  31. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_2_versants_90_degres.csv +0 -21
  32. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_terrasse.csv +0 -21
  33. ourocode-1.6.9/ourocode/data/vent/vent_Cpe_toiture_terrasse.png +0 -0
  34. ourocode-1.6.9/ourocode/data/vent/vent_Ffr.png +0 -0
  35. ourocode-1.6.9/ourocode/eurocode/EC1_Exploitation.py +0 -103
  36. ourocode-1.6.9/ourocode/eurocode/logical.py +0 -82
  37. {ourocode-1.6.9 → ourocode-1.7.0}/LICENSE +0 -0
  38. {ourocode-1.6.9 → ourocode-1.7.0}/MANIFEST.in +0 -0
  39. {ourocode-1.6.9 → ourocode-1.7.0}/README.md +0 -0
  40. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/__init__.py +0 -0
  41. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/caracteristique_meca_acier.csv +0 -0
  42. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/caracteristique_meca_bois.csv +0 -0
  43. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/caracteristique_meca_panel.csv +0 -0
  44. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/coeff_psy.csv +0 -0
  45. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/gammaM.csv +0 -0
  46. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/kdef.csv +0 -0
  47. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/kfi.csv +0 -0
  48. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/kmod.csv +0 -0
  49. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/limite_fleche.csv +0 -0
  50. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/qualite_acier.csv +0 -0
  51. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/screenshot/C90_def.png +0 -0
  52. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/screenshot/Kv_def.png +0 -0
  53. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/screenshot/sign_convention.png +0 -0
  54. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/section_boulon.csv +0 -0
  55. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/sismique/categorie_importance.csv +0 -0
  56. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/sismique/categorie_importance_ns.csv +0 -0
  57. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/sismique/classe_sol.csv +0 -0
  58. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/sismique/spectre_eleastique_h_type1.csv +0 -0
  59. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/data/sismique/spectre_eleastique_h_type2.csv +0 -0
  60. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC3_Assemblage.py +0 -0
  61. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC3_Element_droit.py +0 -0
  62. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC5_Feu.py +0 -0
  63. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/EC8_Sismique.py +0 -0
  64. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode/eurocode/__init__.py +0 -0
  65. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode.egg-info/dependency_links.txt +0 -0
  66. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode.egg-info/requires.txt +0 -0
  67. {ourocode-1.6.9 → ourocode-1.7.0}/ourocode.egg-info/top_level.txt +0 -0
  68. {ourocode-1.6.9 → ourocode-1.7.0}/setup.cfg +0 -0
  69. {ourocode-1.6.9 → ourocode-1.7.0}/tests/test_EC0_Combinaison.py +0 -0
  70. {ourocode-1.6.9 → ourocode-1.7.0}/tests/test_EC5_Assemblage.py +0 -0
  71. {ourocode-1.6.9 → ourocode-1.7.0}/tests/test_EC5_CVT.py +0 -0
  72. {ourocode-1.6.9 → ourocode-1.7.0}/tests/test_EC5_Element_droit.py +0 -0
  73. {ourocode-1.6.9 → ourocode-1.7.0}/tests/test_EC8_Sismique.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ourocode
3
- Version: 1.6.9
3
+ Version: 1.7.0
4
4
  Summary: Ceci est un catalogue de fonction permettant une utilisation rapide pour la réalisation de note de calcul personnalisée.
5
5
  Author-email: Anthony PARISOT <contact@ourea-structure.fr>
6
6
  License-Expression: Apache-2.0
@@ -0,0 +1 @@
1
+ __version__ = "1.7.0"
@@ -128,12 +128,12 @@ class Model_generator(Projet):
128
128
  Voici les étapes de modélisation:
129
129
  1) Créer les sections avec la méthode "add_section"
130
130
  2) Créer les matériaux avec la méthode "add_material"
131
- 3) Créer les barres avec la méthode "add_member"
132
- 4) Créer les appuis avec la méthode "create_support"
133
- 5) Créer les charges sur les barres avec les méthodes "create_dist_load" et "create_point_load"
134
- 7) Transmettre cette classe dans les argument de la classe Combinaison du module EC0_Combinaison pour le calcul des combinaisons.
135
- 8) Exécuté la méthode "generate_model" avec la classe Combinaison.
136
- 9) Récupérer les efforts internes , les déformations et afficher les graphiques associés avec les méthodes correspondante.
131
+ 3) Créer les noeuds avec la méthode "add_node"
132
+ 4) Créer les barres avec la méthode "add_member"
133
+ 5) Créer les appuis avec la méthode "create_support"
134
+ 6) Créer les charges sur les barres avec les méthodes "create_dist_load" et "create_point_load"
135
+ 7) Transmettre cette classe dans l'argument model_generator de la classe Combinaison du module EC0_Combinaison pour le calcul des combinaisons.
136
+ 8) Récupérer les efforts internes , les déformations et afficher les graphiques associés avec les méthodes correspondante de la classe Model_result du même module.
137
137
  """
138
138
  super().__init__(*args, **kwargs)
139
139
  self._data = {
@@ -304,6 +304,7 @@ class Model_generator(Projet):
304
304
  node2: str,
305
305
  material: str,
306
306
  section: str,
307
+ poids_propre: bool = ("True", "False"),
307
308
  rotation: float = 0,
308
309
  tension_only: bool = ("False", "True"),
309
310
  compression_only: bool = ("False", "True"),
@@ -317,10 +318,11 @@ class Model_generator(Projet):
317
318
  node2 (str): id du noeud 2
318
319
  material (str): id du matériaux
319
320
  section (str): id de la section
321
+ poids_propre (bool, optional): Défini si le poids propre de la poutre doit être généré. Defaults to True.
320
322
  rotation (float, optional): angle de rotation de la poutre en °. Defaults to 0.
321
323
  tension_only (bool, optional): si True, la poutre ne peut que subir des efforts de traction. Defaults to False.
322
324
  compression_only (bool, optional): si True, la poutre ne peut que subir des efforts de compression. Defaults to False.
323
- name (str, optional): Nom de la membrure, si vous remplissez cet argument alors c'est le nom de la membrure,
325
+ name (str, optional): Nom de la membrure (doit être unique!), si vous remplissez cet argument alors c'est le nom de la membrure,
324
326
  sinon la fonction en génère un automatique.
325
327
  comment (str, optional): commentaire sur la poutre. Defaults to None.
326
328
  """
@@ -351,10 +353,28 @@ class Model_generator(Projet):
351
353
  "Longueur": length,
352
354
  "Section": section,
353
355
  "Matériaux": material,
356
+ "Poids propre": poids_propre,
354
357
  "Rotation": rotation,
355
358
  "Relaxation": {"start": None, "end": None},
356
359
  "Commentaire": comment,
357
360
  }
361
+ if poids_propre:
362
+ rho = self._data["materials"][material]["rho"].value # en kg/m^3
363
+ aire = self._data["sections"][section]["Aire"].value
364
+ pp = rho * aire * 10**-2
365
+ # Important: appeler explicitement la méthode de la classe de base pour éviter
366
+ # le dispatch vers Wood_beam_model.create_dist_load (signature différente)
367
+ Model_generator.create_dist_load(
368
+ self,
369
+ member_id,
370
+ f"PP_{member_id}",
371
+ -pp,
372
+ -pp,
373
+ "start",
374
+ "end",
375
+ action="Permanente G",
376
+ direction="FY",
377
+ comment=f"Poids propre {member_id}")
358
378
  if tension_only:
359
379
  self._data["members"][member_id]["Tension uniquement"] = True
360
380
  elif compression_only:
@@ -769,7 +789,7 @@ class Model_generator(Projet):
769
789
  direction: str = ("Fx", "Fy", "Fz", "FX", "FY", "FZ"),
770
790
  comment: str = None,
771
791
  ):
772
- """Ajoute une charge dans la liste de chargement de la classe chargement
792
+ """Ajoute une charge distribuée sur la barre
773
793
 
774
794
  Args:
775
795
  member_id (str): id de la barre à charger.
@@ -777,9 +797,9 @@ class Model_generator(Projet):
777
797
  start_load (int): effort de départ en kN/m.
778
798
  end_load (int): effort de fin en kN/m.
779
799
  start_pos (str, optional): position de début de la charge sur la barre en mm. En complément il est possible de mettre "start", "middle"
780
- ou un pourcentage pour définitr la position de la charge.
800
+ ou un pourcentage pour définir la position de la charge.
781
801
  end_pos (str, optional): position de début de la charge sur la barre en mm. En complément il est possible de mettre "end", "middle"
782
- ou un pourcentage pour définitr la position de la charge.
802
+ ou un pourcentage pour définir la position de la charge.
783
803
  action (str): type d'action de l'effort.
784
804
  direction (str): sens de l'effort sur la barre.
785
805
  comment (str, optional): commentaire sur la charge.
@@ -831,17 +851,17 @@ class Model_generator(Projet):
831
851
  ),
832
852
  comment: str = None,
833
853
  ):
834
- """Ajoute une charge dans la liste de chargement de la classe chargement
854
+ """Ajoute une charge nodale sur la barre
835
855
 
836
856
  Args:
837
- member_id (str): id de la barre à charger.
838
- name (str): nom de la charge.
839
- load (int): effort de départ en kN ou kN.m.
840
- pos (str, optional): position de la charge sur la barre en mm. En complément il est possible de mettre "start", "middle", "end"
841
- ou un pourcentage pour définitr la position de la charge.
842
- action (str): type d'action de l'effort.
843
- direction (str): sens de l'effort sur la barre.
844
- comment (str, optional): commentaire sur la charge.
857
+ member_id (str): id de la barre à charger.
858
+ name (str): nom de la charge.
859
+ load (int): effort de départ en kN ou kN.m.
860
+ pos (str, optional): position de la charge sur la barre en mm. En complément il est possible de mettre "start", "middle", "end"
861
+ ou un pourcentage pour définir la position de la charge.
862
+ action (str): type d'action de l'effort.
863
+ direction (str): sens de l'effort sur la barre.
864
+ comment (str, optional): commentaire sur la charge.
845
865
  """
846
866
  load_id = "L" + str(len(self._data["loads"]) + 1)
847
867
  if "F" in direction:
@@ -955,6 +975,202 @@ class Model_generator(Projet):
955
975
  for combo, factor in combos.items():
956
976
  self._model.add_load_combo(combo, factor, tag)
957
977
 
978
+ class Wood_beam_model(Model_generator):
979
+ def __init__(
980
+ self,
981
+ longueur: si.mm,
982
+ b: si.mm,
983
+ h: si.mm,
984
+ section: str=Model_generator.LIST_SECTION,
985
+ classe: str = Model_generator.CLASSE_WOOD,
986
+ poids_propre: bool = ("True", "False"),
987
+ nbr_appuis: int = 2,
988
+ l_appuis: float = 0,
989
+ devers: float = 0,
990
+ inclinaison: float = 0,
991
+ *args,
992
+ **kwargs,
993
+ ):
994
+ """Génère un modèle MEF poutre 1D simplifié d'une barre bois avec comme hypothèses:
995
+ - appuis rotulés
996
+ - distance entre appuis identique
997
+ - pas de porte à faux
998
+ On peut gérer l'inclinaison et le dévers de la barre. Ce qui permet avec une inclinaison de 90° de calculer un poteau vertical pour exemple.
999
+
1000
+ Une fois le modèle généré, il faut:
1001
+ 1) Créer les charges sur les barres avec les méthodes "create_dist_load" et "create_point_load"
1002
+ 2) Transmettre cette classe dans l'argument model_generator de la classe Combinaison du module EC0_Combinaison pour le calcul des combinaisons.
1003
+ 3) Récupérer les efforts internes , les déformations et afficher les graphiques associés avec les méthodes correspondante de la classe Model_result du même module.
1004
+
1005
+ Args:
1006
+ longueur (si.mm): longueur de la barre en mm.
1007
+ b (si.mm): épaisseur de la barre en mm.
1008
+ h (si.mm): hauteur de la barre en mm.
1009
+ section (str, optional): type de section.
1010
+ classe (str, optional): classe de la barre.
1011
+ poids_propre (bool, optional): Défini si le poids propre de la poutre doit être généré. Defaults to True.
1012
+ nbr_appuis (int, optional): nombre d'appuis sur la barre. Defaults to 2.
1013
+ l_appuis (float, optional): longueur des appuis en mm. Defaults to 0.
1014
+ devers (float, optional): rotation en ° de la barre autour de l'axe de la longueur (X)
1015
+ pour le calcul d'une panne à dévers par exemple. Defaults to 0.
1016
+ inclinaison (float, optional): inclinaison en ° de la barre autour de l'axe de la largeur (Z)
1017
+ pour le calcul d'un chevrons ou d'un poteau vertical pour exemple. Defaults to 0.
1018
+ """
1019
+ super().__init__(*args, **kwargs)
1020
+ self.longueur = longueur * si.mm
1021
+ self.b = b * si.mm
1022
+ self.h = h * si.mm
1023
+ self.section = section
1024
+ self.classe = classe
1025
+ self.poids_propre = poids_propre
1026
+ self.nbr_appuis = nbr_appuis
1027
+ self.l_appuis = l_appuis
1028
+ self.devers = devers
1029
+ self.inclinaison = inclinaison
1030
+
1031
+ material = self.add_material_by_class(classe)
1032
+ section = self.add_section(b, h, 0, section)
1033
+
1034
+ d_appuis = longueur / (nbr_appuis - 1)
1035
+ for i in range(nbr_appuis):
1036
+ node = self.add_node(int(float(i * d_appuis * mt.cos(mt.radians(inclinaison)))), int(float(i * d_appuis * mt.sin(mt.radians(inclinaison)))), 0)
1037
+ self.add_support(node, DX=True, DY=True, DZ=True, RX=True, RY=False, RZ=False, l_appuis=l_appuis)
1038
+
1039
+ for i in range(nbr_appuis-1):
1040
+ self.add_member(f"N{i+1}", f"N{i+2}", material, section, poids_propre, rotation=devers, tension_only=False, compression_only=False)
1041
+
1042
+ def _convert_beam_pos(self, pos_index: int | str) -> int:
1043
+ """Converti la position en valeur recevable par la fonction create_load
1044
+
1045
+ Args:
1046
+ pos_index (int | str): position de la charge sur la barre
1047
+
1048
+ Returns:
1049
+ int: la position numérique sur la barre
1050
+ """
1051
+ match pos_index:
1052
+ case "start":
1053
+ pos_index = 0 * si.mm
1054
+ member_id = "M1"
1055
+ case "end":
1056
+ member_id = "M" + str(len(self._data["members"]))
1057
+ pos_index = self._data["members"][member_id]["Longueur"]
1058
+ case "middle":
1059
+ dist = self.longueur / 2
1060
+ sum_dist = 0
1061
+ for member_id in self._data["members"].keys():
1062
+ sum_dist = sum_dist + self._data["members"][member_id]["Longueur"]
1063
+ if sum_dist >= dist:
1064
+ delta_end_dist = sum_dist - dist
1065
+ pos_index = self._data["members"][member_id]["Longueur"] - delta_end_dist
1066
+ break
1067
+ pos_index = round(pos_index, 0)
1068
+ case str(x) if "%" in x:
1069
+ pos_index = pos_index.split("%")[0]
1070
+ pos_index.replace(" ", "")
1071
+ dist = round(
1072
+ self.longueur * int(pos_index) / 100,
1073
+ 0,
1074
+ )
1075
+ sum_dist = 0
1076
+ for member_id in self._data["members"].keys():
1077
+ sum_dist = sum_dist + self._data["members"][member_id]["Longueur"]
1078
+ if sum_dist >= dist:
1079
+ delta_end_dist = sum_dist - dist
1080
+ pos_index = self._data["members"][member_id]["Longueur"] - delta_end_dist
1081
+ break
1082
+ pos_index = round(pos_index, 0)
1083
+ case _:
1084
+ dist = float(pos_index) * si.mm
1085
+ sum_dist = 0
1086
+ for member_id in self._data["members"].keys():
1087
+ sum_dist = sum_dist + self._data["members"][member_id]["Longueur"]
1088
+ if sum_dist >= dist:
1089
+ delta_end_dist = sum_dist - dist
1090
+ pos_index = self._data["members"][member_id]["Longueur"] - delta_end_dist
1091
+ break
1092
+ pos_index = round(pos_index, 0)
1093
+ return pos_index.value*10**3, member_id
1094
+
1095
+ def create_dist_load(
1096
+ self,
1097
+ name: str,
1098
+ start_load: float,
1099
+ end_load: float,
1100
+ start_pos: str = None,
1101
+ end_pos: str = None,
1102
+ action: str = Model_generator.ACTION,
1103
+ direction: str = ("Fx", "Fy", "Fz", "FX", "FY", "FZ"),
1104
+ comment: str = None,
1105
+ ):
1106
+ """Ajoute une charge distribuée sur la barre
1107
+
1108
+ Args:
1109
+ name (str): nom de la charge.
1110
+ start_load (int): effort de départ en kN/m.
1111
+ end_load (int): effort de fin en kN/m.
1112
+ start_pos (str, optional): position de début de la charge sur la barre en mm. En complément il est possible de mettre "start", "middle"
1113
+ ou un pourcentage pour définir la position de la charge.
1114
+ end_pos (str, optional): position de début de la charge sur la barre en mm. En complément il est possible de mettre "end", "middle"
1115
+ ou un pourcentage pour définir la position de la charge.
1116
+ action (str): type d'action de l'effort.
1117
+ direction (str): sens de l'effort sur la barre.
1118
+ comment (str, optional): commentaire sur la charge.
1119
+ """
1120
+ if not start_pos:
1121
+ start_pos = "start"
1122
+ if not end_pos:
1123
+ end_pos = "end"
1124
+ start_pos, member_id_start = self._convert_beam_pos(start_pos)
1125
+ end_pos, member_id_end = self._convert_beam_pos(end_pos)
1126
+ if member_id_start != member_id_end:
1127
+ id_start = int(member_id_start.split("M")[1])
1128
+ id_end = int(member_id_end.split("M")[1])
1129
+ super().create_dist_load(f"M{id_start}", name, start_load, end_load, start_pos, 'end', action, direction, comment)
1130
+ if id_start != id_end-1:
1131
+ for i in range(id_start, id_end-1):
1132
+ super().create_dist_load(f"M{i+1}", name, start_load, end_load, 'start', 'end', action, direction, comment)
1133
+ super().create_dist_load(f"M{id_end}", name, start_load, end_load, 'start', end_pos, action, direction, comment)
1134
+ else:
1135
+ super().create_dist_load(member_id_start, name, start_load, end_load, start_pos, end_pos, action, direction, comment)
1136
+
1137
+ def create_point_load(
1138
+ self,
1139
+ name: str,
1140
+ load: float,
1141
+ pos: str = None,
1142
+ action: str = Model_generator.ACTION,
1143
+ direction: str = (
1144
+ "Fx",
1145
+ "Fy",
1146
+ "Fz",
1147
+ "Mx",
1148
+ "My",
1149
+ "Mz",
1150
+ "FX",
1151
+ "FY",
1152
+ "FZ",
1153
+ "MX",
1154
+ "MY",
1155
+ "MZ",
1156
+ ),
1157
+ comment: str = None
1158
+ ):
1159
+ """Ajoute une charge nodale sur la barre
1160
+
1161
+ Args:
1162
+ name (str): nom de la charge.
1163
+ load (int): effort de départ en kN ou kN.m.
1164
+ pos (str, optional): position de la charge sur la barre en mm. En complément il est possible de mettre "start", "middle", "end"
1165
+ ou un pourcentage pour définir la position de la charge.
1166
+ action (str): type d'action de l'effort.
1167
+ direction (str): sens de l'effort sur la barre.
1168
+ comment (str, optional): commentaire sur la charge.
1169
+ """
1170
+ pos, member_id = self._convert_beam_pos(pos)
1171
+ return super().create_point_load(member_id, name, load, pos, action, direction, comment)
1172
+
1173
+
958
1174
 
959
1175
  class Model_result(Projet):
960
1176
  ANALYZE_TYPE = ("Général", "Linéaire", "Second ordre")
@@ -999,7 +1215,7 @@ class Model_result(Projet):
999
1215
  filepath: str=None
1000
1216
  ):
1001
1217
  """Retourne un diagramme"""
1002
- plt.clf() # Effacer le graphique précédent
1218
+ # plt.clf() # Effacer le graphique précédent
1003
1219
  plt.figure(self.name, figsize=(11, 4))
1004
1220
  plt.gcf().subplots_adjust(
1005
1221
  left=0.1, bottom=0.25, right=0.9, top=0.75, wspace=0, hspace=0.95
@@ -1100,65 +1316,83 @@ class Model_result(Projet):
1100
1316
  """Retourne le maximum et minimum des efforts internes d'une membrure donnée.
1101
1317
 
1102
1318
  Args:
1103
- member_id (str): Le nom de la membrure à analyser
1319
+ member_id (str): Le nom de la membrure à analyser. On peut rentrer plusieurs membrures en créant une liste de membrures,
1320
+ ex: ["M1", "M2", "M3"] dans le cas par exemple d'une barre continue.
1104
1321
  combination (str): Le nom de la combinaison à récupérer
1105
1322
  """
1106
1323
  dict_internal_forces = {}
1107
1324
  for type in ("Nx", "Vy", "Vz", "Mx", "My", "Mz"):
1108
- if type == "Nx":
1109
- max = self._model_generator._model.members[member_id].max_axial(
1110
- combo_name=combination
1111
- )
1112
- min = self._model_generator._model.members[member_id].min_axial(
1113
- combo_name=combination
1114
- )
1115
- elif type == "Vy":
1116
- max = self._model_generator._model.members[member_id].max_shear(
1117
- "Fy", combo_name=combination
1118
- )
1119
- min = self._model_generator._model.members[member_id].min_shear(
1120
- "Fy", combo_name=combination
1121
- )
1122
- elif type == "Vz":
1123
- max = self._model_generator._model.members[member_id].max_shear(
1124
- "Fz", combo_name=combination
1125
- )
1126
- min = self._model_generator._model.members[member_id].min_shear(
1127
- "Fz", combo_name=combination
1128
- )
1129
- elif type == "Mx":
1130
- max = self._model_generator._model.members[member_id].max_torque(
1131
- combo_name=combination
1132
- )
1133
- min = self._model_generator._model.members[member_id].min_torque(
1134
- combo_name=combination
1135
- )
1136
- elif type == "My":
1137
- max = self._model_generator._model.members[member_id].max_moment(
1138
- "My", combo_name=combination
1139
- )
1140
- min = self._model_generator._model.members[member_id].min_moment(
1141
- "My", combo_name=combination
1142
- )
1143
- elif type == "Mz":
1144
- max = self._model_generator._model.members[member_id].max_moment(
1145
- "Mz", combo_name=combination
1146
- )
1147
- min = self._model_generator._model.members[member_id].min_moment(
1148
- "Mz", combo_name=combination
1149
- )
1325
+ if "[" in member_id:
1326
+ import json
1327
+ member_id = json.loads(member_id.replace("'", "\""))
1328
+ elif isinstance(member_id, str):
1329
+ member_id = [member_id]
1330
+ max_value = 0
1331
+ min_value = 0
1332
+ for member in member_id:
1333
+ if member not in self._model_generator._model.members:
1334
+ raise ValueError(f"La membrure {member} n'est pas dans le model MEF")
1335
+
1336
+ if type == "Nx":
1337
+ max = self._model_generator._model.members[member].max_axial(
1338
+ combo_name=combination
1339
+ )
1340
+ min = self._model_generator._model.members[member].min_axial(
1341
+ combo_name=combination
1342
+ )
1343
+ elif type == "Vy":
1344
+ max = self._model_generator._model.members[member].max_shear(
1345
+ "Fy", combo_name=combination
1346
+ )
1347
+ min = self._model_generator._model.members[member].min_shear(
1348
+ "Fy", combo_name=combination
1349
+ )
1350
+ elif type == "Vz":
1351
+ max = self._model_generator._model.members[member].max_shear(
1352
+ "Fz", combo_name=combination
1353
+ )
1354
+ min = self._model_generator._model.members[member].min_shear(
1355
+ "Fz", combo_name=combination
1356
+ )
1357
+ elif type == "Mx":
1358
+ max = self._model_generator._model.members[member].max_torque(
1359
+ combo_name=combination
1360
+ )
1361
+ min = self._model_generator._model.members[member].min_torque(
1362
+ combo_name=combination
1363
+ )
1364
+ elif type == "My":
1365
+ max = self._model_generator._model.members[member].max_moment(
1366
+ "My", combo_name=combination
1367
+ )
1368
+ min = self._model_generator._model.members[member].min_moment(
1369
+ "My", combo_name=combination
1370
+ )
1371
+ elif type == "Mz":
1372
+ max = self._model_generator._model.members[member].max_moment(
1373
+ "Mz", combo_name=combination
1374
+ )
1375
+ min = self._model_generator._model.members[member].min_moment(
1376
+ "Mz", combo_name=combination
1377
+ )
1378
+ if max > max_value:
1379
+ max_value = max
1380
+ if min < min_value:
1381
+ min_value = min
1382
+
1150
1383
  if "M" in type:
1151
1384
  si_unit = si.N * si.mm
1152
1385
  else:
1153
1386
  si_unit = si.N
1154
- dict_internal_forces[type] = {"Min": min * si_unit, "Max": max * si_unit}
1387
+ dict_internal_forces[type] = {"Min": min_value * si_unit, "Max": max_value * si_unit}
1155
1388
  return dict_internal_forces
1156
1389
 
1157
1390
  def get_absolute_internal_force(self, member_id: str, combination: str, type: str = ("Nx", "Vy", "Vz", "Mx", "My", "Mz")):
1158
1391
  """Retourne la valeur de d'effort absolue pour le type d'effort donné.
1159
1392
 
1160
1393
  Args:
1161
- member_id (str): Le nom de la membrure à analyser
1394
+ member_id (str): Le nom de la membrure à analyser. On peut rentrer plusieurs membrures en créant une liste de membrures,
1395
+ ex: ["M1", "M2", "M3"] dans le cas par exemple d'une barre continue.
1162
1396
  combination (str): Le nom de la combinaison à récupérer
1163
1397
  type (str): Le type d'effort interne à retourner. Defaults to ("Nx", "Vy", "Vz", "Mx", "My", "Mz").
1164
1398
  """
@@ -1177,7 +1411,8 @@ class Model_result(Projet):
1177
1411
  """Retourne un graphique des efforts internes d'une membrure suivant le type d'effort et la combinaison choisit.
1178
1412
 
1179
1413
  Args:
1180
- member_id (str): Le nom de la membrure à analyser
1414
+ member_id (str): Le nom de la membrure à analyser. On peut rentrer plusieurs membrures en créant une liste de membrures,
1415
+ ex: ["M1", "M2", "M3"] dans le cas par exemple d'une barre continue.
1181
1416
  combination (str): Le nom de la combinaison à récupérer
1182
1417
  type (str): Le type d'effort interne à retourner. Defaults to ("Nx", "Vy", "Vz", "Mx", "My", "Mz").
1183
1418
  n_points (int, optional): le nombre de valeur à retrouner le long de la membrure. Defaults to 20.
@@ -1186,9 +1421,27 @@ class Model_result(Projet):
1186
1421
  Sinon le logiciel vous demande à chaque fois le chemin de sauvegarde.
1187
1422
  """
1188
1423
  x_label = "Longueur (mm)"
1189
- x_value, y_value = self.get_internal_force(
1190
- member_id, combination, type, n_points
1191
- )
1424
+ if "[" in member_id:
1425
+ import json
1426
+ member_id = json.loads(member_id.replace("'", "\""))
1427
+ elif isinstance(member_id, str):
1428
+ member_id = [member_id]
1429
+ x_value = []
1430
+ y_value = []
1431
+ for member in member_id:
1432
+ if member not in self._model_generator._model.members:
1433
+ raise ValueError(f"La membrure {member} n'est pas dans le model MEF")
1434
+ x_local, y_local = self.get_internal_force(
1435
+ member, combination, type, n_points
1436
+ )
1437
+ if len(x_value) == 0:
1438
+ x_value = x_local
1439
+ y_value = y_local
1440
+ else:
1441
+ x_local = x_local + x_value[-1]
1442
+ x_value = np.concatenate((x_value, x_local))
1443
+ y_value = np.concatenate((y_value, y_local))
1444
+
1192
1445
  if type.startswith("N"):
1193
1446
  title = f"Barre {member_id}: Effort normal {type}"
1194
1447
  color = "orange"
@@ -1239,25 +1492,42 @@ class Model_result(Projet):
1239
1492
  """Retourne le maximum et minimum des efforts internes d'une membrure donnée.
1240
1493
 
1241
1494
  Args:
1242
- member_id (str): Le nom de la membrure à analyser
1495
+ member_id (str): Le nom de la membrure à analyser. On peut rentrer plusieurs membrures en créant une liste de membrures,
1496
+ ex: ["M1", "M2", "M3"] dans le cas par exemple d'une barre continue.
1243
1497
  combination (str): Le nom de la combinaison à récupérer
1244
1498
  """
1245
1499
  dict_deflection = {}
1246
1500
  for type in ("dx", "dy", "dz"):
1247
- max = self._model_generator._model.members[member_id].max_deflection(
1248
- type, combo_name=combination
1249
- )
1250
- min = self._model_generator._model.members[member_id].min_deflection(
1251
- type, combo_name=combination
1252
- )
1253
- dict_deflection[type] = {"Min": min * si.mm, "Max": max * si.mm}
1501
+ if "[" in member_id:
1502
+ import json
1503
+ member_id = json.loads(member_id.replace("'", "\""))
1504
+ elif isinstance(member_id, str):
1505
+ member_id = [member_id]
1506
+ max_value = 0
1507
+ min_value = 0
1508
+ for member in member_id:
1509
+ if member not in self._model_generator._model.members:
1510
+ raise ValueError(f"La membrure {member} n'est pas dans le model MEF")
1511
+ max = self._model_generator._model.members[member].max_deflection(
1512
+ type, combo_name=combination
1513
+ )
1514
+
1515
+ min = self._model_generator._model.members[member].min_deflection(
1516
+ type, combo_name=combination
1517
+ )
1518
+ if max > max_value:
1519
+ max_value = max
1520
+ if min < min_value:
1521
+ min_value = min
1522
+ dict_deflection[type] = {"Min": min_value * si.mm, "Max": max_value * si.mm}
1254
1523
  return dict_deflection
1255
1524
 
1256
1525
  def get_absolute_max_deflection(self, member_id: str, combination: str, direction: str = ("dx", "dy", "dz")):
1257
1526
  """Retourne la valeur de déplacement absolue pour la direction de la flèche donnée.
1258
1527
 
1259
1528
  Args:
1260
- member_id (str): Le nom de la membrure à analyser
1529
+ member_id (str): Le nom de la membrure à analyser. On peut rentrer plusieurs membrures en créant une liste de membrures,
1530
+ ex: ["M1", "M2", "M3"] dans le cas par exemple d'une barre continue.
1261
1531
  combination (str): Le nom de la combinaison à récupérer
1262
1532
  direction (str): La direction locale à retourner. Defaults to ("dx", "dy", "dz").
1263
1533
  """
@@ -1277,7 +1547,8 @@ class Model_result(Projet):
1277
1547
  """Retourne un graphique des efforts internes d'une membrure suivant le type d'effort et la combinaison choisit.
1278
1548
 
1279
1549
  Args:
1280
- member_id (str): Le nom de la membrure à analyser
1550
+ member_id (str): Le nom de la membrure à analyser. On peut rentrer plusieurs membrures en créant une liste de membrures,
1551
+ ex: ["M1", "M2", "M3"] dans le cas par exemple d'une barre continue.
1281
1552
  combination (str): Le nom de la combinaison à récupérer
1282
1553
  direction (str): La direction locale à retourner. Defaults to ("dx", "dy", "dz").
1283
1554
  n_points (int, optional): le nombre de valeur à retrouner le long de la membrure. Defaults to 20.
@@ -1289,9 +1560,27 @@ class Model_result(Projet):
1289
1560
  x_label = "Longueur (mm)"
1290
1561
  y_label = "Déplacement\n(mm)"
1291
1562
  color = "g"
1292
- x_value, y_value = self.get_deflection(
1293
- member_id, combination, direction, n_points
1294
- )
1563
+ if "[" in member_id:
1564
+ import json
1565
+ member_id = json.loads(member_id.replace("'", "\""))
1566
+ elif isinstance(member_id, str):
1567
+ member_id = [member_id]
1568
+ x_value = []
1569
+ y_value = []
1570
+ for member in member_id:
1571
+ if member not in self._model_generator._model.members:
1572
+ raise ValueError(f"La membrure {member} n'est pas dans le model MEF")
1573
+ x_local, y_local = self.get_deflection(
1574
+ member, combination, direction, n_points
1575
+ )
1576
+ if len(x_value) == 0:
1577
+ x_value = x_local
1578
+ y_value = y_local
1579
+ else:
1580
+ x_local = x_local + x_value[-1]
1581
+ x_value = np.concatenate((x_value, x_local))
1582
+ y_value = np.concatenate((y_value, y_local))
1583
+
1295
1584
  return self._base_graph(
1296
1585
  title,
1297
1586
  combination,
@@ -1309,7 +1598,7 @@ class Model_result(Projet):
1309
1598
  self,
1310
1599
  combination: str,
1311
1600
  annotation_size: int = 70,
1312
- deformed_shape: bool = True,
1601
+ deformed_shape: bool = ("False", "True"),
1313
1602
  deformed_scale: int = 20,
1314
1603
  screenshot: bool = ("False", "True"),
1315
1604
  filepath: str=None,
@@ -111,7 +111,8 @@ class Combinaison(Projet):
111
111
 
112
112
  for psy_i in psy_columns:
113
113
  for key in dict_psy.keys():
114
- dict_psy[key][psy_i] = data_csv_psy.loc[key].loc[psy_i]
114
+ if key != "Aucune":
115
+ dict_psy[key][psy_i] = data_csv_psy.loc[key].loc[psy_i]
115
116
  return dict_psy
116
117
 
117
118
  def _key_action_psy(self, action_variable):
@@ -1606,11 +1607,11 @@ class Combinaison(Projet):
1606
1607
  self._name_combination.sort()
1607
1608
  return pd.DataFrame(self._name_combination, columns=["Combinaison"])
1608
1609
 
1609
- def get_list_combination(self, type: str=("Toutes", "ELU_ALL", "ELU_STR", "ELU_STR_ACC", "ELS_ALL", "ELS_C", "ELS_QP", "W")):
1610
+ def get_list_combination(self, type: str=("Toutes", "ELU_ALL", "ELU_STR", "ELU_STR_ACC", "ELS_ALL", "ELS_C", "ELS_QP", "W_inst_Q", "W_net_fin")):
1610
1611
  """Retourne la liste des combinaisons pour le type sélectionné.
1611
1612
 
1612
1613
  Args:
1613
- type (str): Le type de combinaison à retourner. Defaults to ("Toutes", "ELU_ALL", "ELU_STR", "ELU_STR_ACC", "ELS_ALL", "ELS_C", "ELS_QP", "Flèche bois").
1614
+ type (str): Le type de combinaison à retourner. Defaults to ("Toutes").
1614
1615
 
1615
1616
  Returns:
1616
1617
  list: Liste des combinaisons
@@ -1630,8 +1631,10 @@ class Combinaison(Projet):
1630
1631
  return [name for name in self._name_combination if name.startswith("ELS_C")]
1631
1632
  case "ELS_QP":
1632
1633
  return [name for name in self._name_combination if name.startswith("ELS_QP")]
1633
- case "Flèche bois":
1634
- return [name for name in self._name_combination if name.startswith("W")]
1634
+ case "W_inst_Q":
1635
+ return [name for name in self._name_combination if name.startswith("W_inst")]
1636
+ case "W_net_fin":
1637
+ return [name for name in self._name_combination if name.startswith("W_net_fin")]
1635
1638
 
1636
1639
  def _choice_combi_df(self):
1637
1640
  shape = len(self.list_combination)