Skip to content

Commit

Permalink
Fixed bug in usfos writer
Browse files Browse the repository at this point in the history
  • Loading branch information
krande committed Nov 12, 2021
1 parent 181d99d commit 1ae00f3
Show file tree
Hide file tree
Showing 11 changed files with 571 additions and 237 deletions.
426 changes: 426 additions & 0 deletions files/ifc_files/beam-standard-case.ifc

Large diffs are not rendered by default.

116 changes: 0 additions & 116 deletions files/ifc_files/beams/ipe300.ifc

This file was deleted.

97 changes: 97 additions & 0 deletions src/ada/fem/formats/usfos/write/write_elements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import logging
from operator import attrgetter

from ada import FEM, Part
from ada.core.utils import Counter
from ada.fem import Elem


def shell_str(part: Part):

pl_str = "' Elem ID np1 np2 np3 np4 mater geom ec1 ec2 ec3 ec4\n"
sec_str = """' Geom ID Thick"""
thick = []
for fs in sorted(part.fem.sections.shells, key=attrgetter("id")):
t = fs.thickness
if t is None:
raise ValueError("Thickness cannot be None")
if fs not in thick:
thick.append(fs)
sec_str += "\n PLTHICK{:>12}{:>10}".format(fs.id, t)

sec_str += "\n"

def write_elem(el: Elem):
if len(el.nodes) > 4:
raise ValueError(f'Shell id "{el.id}" consist of {len(el.nodes)} nodes')
else:
nodes_str = "".join(["{:>9}".format(no.id) for no in el.nodes])
if len(el.nodes) == 3:
return f" TRISHELL{el.id:>11}{nodes_str}{'':>9}{el.fem_sec.material.id:>9}{el.fem_sec.id:>7}"
else:
return f" QUADSHEL{el.id:>11}{nodes_str}{el.fem_sec.material.id:>9}{el.fem_sec.id:>7}"

return sec_str + pl_str + "\n".join(list(map(write_elem, sorted(part.fem.elements.shell, key=attrgetter("id")))))


def beam_str(fem: FEM, eccen):
"""
# USFOS Strings
# Beam String
' Elem ID np1 np2 material geom lcoor ecc1 ecc2
BEAM 1127 1343 1344 1 1 1
# Unit Vector String
' Loc-Coo dx dy dz
UNITVEC 60000001 0.00000 0.00000 1.00000
"""
locvecs = []
eccen_counter = Counter(1)
loc_str = "'\n' Loc-Coo dx dy dz\n"
bm_str = "'\n' Elem ID np1 np2 material geom lcoor ecc1 ecc2\n"

logging.info(
"Note! Second order formulations of beam elements is not supported by Usfos beam. "
"Will use regular beam formulation"
)

def write_elem(el: Elem) -> str:
nonlocal locvecs
n1 = el.nodes[0]
n2 = el.nodes[1]
fem_sec = el.fem_sec
mat = fem_sec.material
xvec = fem_sec.local_z
xvec_str = f"{xvec[0]:>13.5f}{xvec[1]:>15.5f}{xvec[2]:>15.5f}"

if xvec_str in locvecs:
locid = locvecs.index(xvec_str)
else:
locvecs.append(xvec_str)
locid = locvecs.index(xvec_str)

if el.eccentricity is not None:
ecc1_str = " 0"
ecc2_str = " 0"
if el.eccentricity.end1 is not None:
ecc1 = next(eccen_counter)
eccen.append((ecc1, el.eccentricity.end1.ecc_vector))
ecc1_str = f" {ecc1}"
if el.eccentricity.end2 is not None:
ecc2 = next(eccen_counter)
eccen.append((ecc2, el.eccentricity.end2.ecc_vector))
ecc2_str = f" {ecc2}"
else:
ecc1_str = ""
ecc2_str = ""
return f" BEAM{el.id:>15}{n1.id:>8}{n2.id:>9}{mat.id:>11}{el.fem_sec.id:>7}{locid + 1:>9}{ecc1_str}{ecc2_str}"

bm_str += "\n".join(list(map(write_elem, fem.elements.lines)))

for i, loc in enumerate(locvecs):
loc_str += " UNITVEC{:>13}{:<10}\n".format(i + 1, loc)

return bm_str + "\n" + loc_str
93 changes: 1 addition & 92 deletions src/ada/fem/formats/usfos/write/writer.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import logging
import os
from operator import attrgetter

from ada import FEM, Assembly, Material, Node, Part
from ada.core.utils import Counter, NewLine, roundoff
from ada.fem import Bc, Elem, FemSet

from .write_elements import beam_str, shell_str
from .write_profiles import sections_str


Expand Down Expand Up @@ -135,34 +135,6 @@ def write_mat(m: Material):
return mat_str + "\n".join(write_mat(mat) for mat in materials.values())


def shell_str(part: Part):

pl_str = "' Elem ID np1 np2 np3 np4 mater geom ec1 ec2 ec3 ec4\n"
sec_str = """' Geom ID Thick"""
thick = []
for fs in sorted(part.fem.sections.shells, key=attrgetter("id")):
t = fs.thickness
if t is None:
raise ValueError("Thickness cannot be None")
if t not in thick:
thick.append(t)
sec_str += "\n PLTHICK{:>12}{:>10}".format(fs.id, t)

sec_str += "\n"

def write_elem(el: Elem):
if len(el.nodes) > 4:
raise ValueError(f'Shell id "{el.id}" consist of {len(el.nodes)} nodes')
else:
nodes_str = "".join(["{:>9}".format(no.id) for no in el.nodes])
if len(el.nodes) == 3:
return f" TRISHELL{el.id:>11}{nodes_str}{'':>9}{el.fem_sec.material.id:>9}{el.fem_sec.id:>7}"
else:
return f" QUADSHEL{el.id:>11}{nodes_str}{el.fem_sec.material.id:>9}{el.fem_sec.id:>7}"

return sec_str + pl_str + "\n".join(list(map(write_elem, sorted(part.fem.elements.shell, key=attrgetter("id")))))


def nodal_str(fem: FEM) -> str:
node_str = "' Node ID X Y Z Boundary code\n"
f = " NODE {nid:>15} {x:>13.3f} {y:>13.3f} {z:>13.3f}{bc}"
Expand All @@ -186,66 +158,3 @@ def write_node(no: Node):
if len(fem.nodes) > 0
else "** No Nodes"
)


def beam_str(fem: FEM, eccen):
"""
# USFOS Strings
# Beam String
' Elem ID np1 np2 material geom lcoor ecc1 ecc2
BEAM 1127 1343 1344 1 1 1
# Unit Vector String
' Loc-Coo dx dy dz
UNITVEC 60000001 0.00000 0.00000 1.00000
"""
locvecs = []
eccen_counter = Counter(1)
loc_str = "'\n' Loc-Coo dx dy dz\n"
bm_str = "'\n' Elem ID np1 np2 material geom lcoor ecc1 ecc2\n"

logging.info(
"Note! Second order formulations of beam elements is not supported by Usfos beam. "
"Will use regular beam formulation"
)

def write_elem(el: Elem) -> str:
nonlocal locvecs
n1 = el.nodes[0]
n2 = el.nodes[1]
fem_sec = el.fem_sec
mat = fem_sec.material
xvec = fem_sec.local_z
xvec_str = f"{xvec[0]:>13.5f}{xvec[1]:>15.5f}{xvec[2]:>15.5f}"

if xvec_str in locvecs:
locid = locvecs.index(xvec_str)
else:
locvecs.append(xvec_str)
locid = locvecs.index(xvec_str)

if el.eccentricity is not None:
ecc1_str = " 0"
ecc2_str = " 0"
if el.eccentricity.end1 is not None:
ecc1 = next(eccen_counter)
eccen.append((ecc1, el.eccentricity.end1.ecc_vector))
ecc1_str = f" {ecc1}"
if el.eccentricity.end2 is not None:
ecc2 = next(eccen_counter)
eccen.append((ecc2, el.eccentricity.end2.ecc_vector))
ecc2_str = f" {ecc2}"
else:
ecc1_str = ""
ecc2_str = ""
return f" BEAM{el.id:>15}{n1.id:>8}{n2.id:>9}{mat.id:>11}{el.fem_sec.id:>7}{locid + 1:>9}{ecc1_str}{ecc2_str}"

bm_str += "\n".join(list(map(write_elem, fem.elements.lines)))

for i, loc in enumerate(locvecs):
loc_str += " UNITVEC{:>13}{:<10}\n".format(i + 1, loc)

return bm_str + "\n" + loc_str
15 changes: 9 additions & 6 deletions src/ada/ifc/read/read_materials.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import logging

from ada import Assembly, Material


def read_material(ifc_mat) -> Material:
from ada.materials.metals import CarbonSteel, Metal

mat_psets = ifc_mat.HasProperties

props = {
entity.Name: entity.NominalValue[0]
for entity in mat_psets[0].Properties
if entity.is_a("IfcPropertySingleValue")
}
if len(mat_psets) == 0:
logging.warning(f'No material found for "{ifc_mat}"')
return Material("DummyMat")
props = {}
for entity in mat_psets[0].Properties:
if entity.is_a("IfcPropertySingleValue"):
props[entity.Name] = entity.NominalValue[0]

mat_props = dict(
E=props.get("YoungModulus", 210000e6),
Expand Down
9 changes: 7 additions & 2 deletions tests/ifc/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import pytest

from ada.config import Settings
import ada


@pytest.fixture
def bm_ipe300():
return ada.Beam("MyIPE300", (0, 0, 0), (5, 0, 0), "IPE300")


@pytest.fixture
def ifc_test_dir():
return Settings.test_dir / "ifc"
return ada.config.Settings.test_dir / "ifc"
16 changes: 0 additions & 16 deletions tests/ifc/imports/beams/test_import_beam.py

This file was deleted.

Loading

0 comments on commit 1ae00f3

Please sign in to comment.