from dataclasses import dataclass
import pathlib
from typing import Optional, Any, Union
import io
import jsonchain
from .analysis_model import AbstractAnalysisModel
from .concentric_column import concentric_column as cc
[docs]
@dataclass
class PointColumn(AbstractAnalysisModel):
pm: dict
model: Optional[cc.ConcentricColumn]
def __post_init__(self):
self.model = build_column_model(self.pm)
[docs]
def get_reactions(self):
reactions = self.model.get_reactions()
return reactions
[docs]
def dump_model(
self, filepath: Optional[str | pathlib.Path] = None, indent: int = 2
) -> Optional[dict]:
"""
Dumps the model to 'fp'. If 'fp' is None, then a Python
dict is returned.
"""
if filepath is not None:
return self.model.to_json(self.model, filepath, indent=indent)
else:
return self.model.dump_dict()
[docs]
def load_model(
self,
filepath: Optional[str | pathlib.Path] = None,
model_data: Optional[dict] = None,
) -> dict:
"""
Loads the model from either 'fp' or 'model_data' and returns a dict
"""
if filepath is not None:
return self.model.from_json(filepath)
else:
return self.model.from_dict(model_data)
[docs]
@classmethod
def from_papermodel(
cls,
model_data: Optional[dict] = None,
filepath: Optional[str | pathlib.Path] = None,
) -> dict:
"""
Loads the model from either 'fp' or 'model_data' and returns a dict
"""
if filepath is not None:
papermodel_data = jsonchain.load_json(filepath)
else:
papermodel_data = model_data
return cls(papermodel_data)
[docs]
def build_column_model(pm: dict) -> cc.ConcentricColumn:
"""
Returns a ConcentricColumn based on the data within 'pm'.
A concentric column carries the sum of its loads, so distributed loads
(e.g. from a wall above) are added as their resultants.
"""
column = cc.ConcentricColumn(
height=pm["element_attributes"].get("height"),
gravity_dir="Fx",
strong_axis_dir="Fy",
weak_axis_dir="Fz",
reverse_reaction_sign=True,
)
for point_load in pm["loads"]["point_loads"]:
for pt_component in point_load.get("expanded", []):
column.add_point_load(
pt_component["magnitude"],
pt_component["location"],
pt_component["case"],
pt_component["dir"],
)
for dist_load in pm["loads"]["distributed_loads"]:
for dt in dist_load.get("expanded", []):
resultant = (
(dt["start_magnitude"] + dt["end_magnitude"])
/ 2
* (dt["end_loc"] - dt["start_loc"])
)
column.add_point_load(resultant, 0.0, dt["case"], dt["dir"])
return column