@@ -12,17 +12,21 @@ class LinearWallModel(BaseModel):
1212 height : float
1313 length : float
1414 vertical_spread_angle : float = 0.0
15+ minimum_point_spread : float = 0.5
1516 distributed_loads : dict = Field (default = {})
1617 point_loads : dict = Field (default = {})
1718 gravity_dir : str = "z"
1819 inplane_dir : str = "x"
1920 out_of_plane_dir : str = "y"
2021 apply_spread_angle_gravity : bool = True
2122 apply_spread_angle_inplane : bool = True
23+ magnitude_point_key : str = 'p'
2224 magnitude_start_key : str = "w0"
2325 magnitude_end_key : str = "w1"
26+ location_point_key : str = 'x'
2427 location_start_key : str = "x0"
2528 location_end_key : str = "x1"
29+ reverse_reaction_force_direction : bool = True
2630 _projected_loads : Optional [dict ] = None
2731 """
2832 A model of a linear load-bearing wall segment. The segment is assumed to be linear
@@ -34,6 +38,11 @@ class LinearWallModel(BaseModel):
3438 spread through to the base of the wall according to this angle. The angle is
3539 measured as deviation off of the direction of gravity (i.e. 0.0 is the in the
3640 gravity direction and 30.0 is 30 degrees away from vertical)
41+ 'minimum_point_spread': For point loads applied without a spread angle, this is minimum width
42+ over which the point load will be spread. Whether this value is realistic or not depends on
43+ your context and the length unit system you are using. In other words, all applied point loads
44+ will be converted to distributed loads spread over this distance unless a vertical spread
45+ angle is applied.
3746 'distributed_loads': A dictionary of loads. Can be set directly or using the .add_dist_load()
3847 methods
3948 'point_loads': A dictionary of loads. Can be set directly or using the .add_point_load()
@@ -44,30 +53,36 @@ class LinearWallModel(BaseModel):
4453 used in the applied loads for applied loads in the inplane direction.
4554 'out_of_plane_dir': A label used for the out_of_plane direction. Must match the direction labels
4655 used in the applied loads for applied loads in the out_of_plane direction.
47- 'magnitude_start_key': The key that will be used internally and in reaction results for the
56+ 'magnitude_point_key': The key that will be used internally to describe the magnitude of
57+ point loads.
58+ 'magnitude_start_key': The key that will be used internally (and in reaction results) for the
4859 start magnitude
49- 'magnitude_end_key': The key that will be used internally and in reaction results for the
60+ 'magnitude_end_key': The key that will be used internally ( and in reaction results) for the
5061 end magnitude
51- 'location_start_key': The key that will be used internally and in reaction results for the
62+ 'location_key': The key that will be used internally to describe the location of applied
63+ point loads.
64+ 'location_start_key': The key that will be used internally (and in reaction results) for the
5265 start location
53- 'location_end_key': The key that will be used internally and in reaction results for the
66+ 'location_end_key': The key that will be used internally ( and in reaction results) for the
5467 end location
68+ 'reverse_reaction_force_direction': If True, the reactions will be represented with a load
69+ of the opposite sign as the input load.
5570 """
5671
5772 @classmethod
58- def from_json (self , filepath : str | pathlib .Path ):
73+ def from_json (cls , filepath : str | pathlib .Path ):
5974 with safer .open (filepath ) as file :
6075 json_data = file .read ()
61- return self .model_validate_json (json_data )
76+ return cls .model_validate_json (json_data )
6277
6378 def to_json (self , filepath : str | pathlib .Path , indent = 2 ):
6479 json_data = self .model_dump_json (indent = indent )
6580 with safer .open (filepath , "w" ) as file :
6681 file .write (json_data )
6782
6883 @classmethod
69- def from_dict (self , data : dict ):
70- return self .model_validate (data )
84+ def from_dict (cls , data : dict ):
85+ return cls .model_validate (data )
7186
7287 def dump_dict (self ):
7388 return self .model_dump (mode = "json" )
@@ -122,8 +137,8 @@ def add_point_load(
122137 self .point_loads [dir ].setdefault (case , [])
123138 self .point_loads [dir ][case ].append (
124139 {
125- self .magnitude_start_key : magnitude ,
126- self .location_start_key : location ,
140+ self .magnitude_point_key : magnitude ,
141+ self .location_point_key : location ,
127142 }
128143 )
129144
@@ -140,6 +155,8 @@ def spread_loads(self) -> None:
140155 w1 = self .magnitude_end_key
141156 x0 = self .location_start_key
142157 x1 = self .location_end_key
158+ p = self .magnitude_point_key
159+ x = self .location_point_key
143160 for load_dir , load_cases in self .distributed_loads .items ():
144161 proj .setdefault (load_dir , {})
145162 should_apply_spread_angle = (
@@ -159,10 +176,10 @@ def spread_loads(self) -> None:
159176 self .height ,
160177 self .length ,
161178 self .vertical_spread_angle ,
162- dist_load [w0 ],
163- dist_load [x0 ],
164- dist_load .get (w1 ),
165- dist_load .get (x1 ),
179+ w0 = dist_load [w0 ],
180+ x0 = dist_load [x0 ],
181+ w1 = dist_load .get (w1 ),
182+ x1 = dist_load .get (x1 ),
166183 )
167184 proj [load_dir ][load_case ].append (
168185 {
@@ -173,6 +190,7 @@ def spread_loads(self) -> None:
173190 }
174191 )
175192 else :
193+ print (f"{ dist_load = } " )
176194 proj [load_dir ][load_case ].append (dist_load )
177195
178196 for load_dir , load_cases in self .point_loads .items ():
@@ -194,10 +212,8 @@ def spread_loads(self) -> None:
194212 self .height ,
195213 self .length ,
196214 self .vertical_spread_angle ,
197- point_load [w0 ],
198- point_load [x0 ],
199- point_load .get (w1 ),
200- point_load .get (x1 ),
215+ p = point_load [p ],
216+ x = point_load [x ],
201217 )
202218 proj [load_dir ][load_case ].append (
203219 {
@@ -208,7 +224,21 @@ def spread_loads(self) -> None:
208224 }
209225 )
210226 else :
211- proj [load_dir ][load_case ].append (point_load )
227+ print (f"Min spread: { point_load = } " )
228+ projected_load = geom .apply_minimum_width (
229+ point_load [p ],
230+ point_load [x ],
231+ self .minimum_point_spread ,
232+ self .length
233+ )
234+ proj [load_dir ][load_case ].append (
235+ {
236+ w0 : projected_load [0 ],
237+ w1 : projected_load [1 ],
238+ x0 : projected_load [2 ],
239+ x1 : projected_load [3 ],
240+ }
241+ )
212242
213243 self ._projected_loads = proj
214244
0 commit comments