Exemplo n.º 1
0
    def sallow(self, element, loadcase, forces):
        """Allowable stress for sustained, occasional and expansion loadcases.

        Liberal stress can be excluded for the expansion case by user defined
        option otherwise enabled by default depending on the code.
        """
        with units.Units(user_units="code_english"):
            material = element.material
            tload = self.toper(element, loadcase)

            try:
                temp = tload.temp
                tref = tload.tref
            except AttributeError:
                temp = 70  # fahrenheit
                tref = 70

            sh = material.sh[temp]
            sc = material.sh[tref]

            if loadcase.stype == "sus":
                return sh
            elif loadcase.stype == "occ":
                # k factor is 1.15 for events lasting 8hrs or less and 1.20
                # for 1hr or less per code para. 102.3.3, use 1.15 to be
                # conservative
                return self.k * sh
            elif loadcase.stype == "exp":
                liberal_stress = 0  # default per code
                if self.app.models.active_object.settings.liberal_stress:
                    liberal_stress = sh - self.sl(element, loadcase, forces)

                return self.f * (1.25 * sc + 0.25 * sh + liberal_stress)
            else:
                return 0
Exemplo n.º 2
0
    def __init__(self,
                 name,
                 opercase,
                 point,
                 dx=None,
                 dy=None,
                 dz=None,
                 rx=None,
                 ry=None,
                 rz=None):
        """Create a displacement support instance."""
        super(Displacement, self).__init__(name, opercase)
        self.opercase = opercase
        self.point = point
        self.dx = dx
        self.dy = dy
        self.dz = dz
        self.rx = rx
        self.ry = ry
        self.rz = rz

        model = self.app.models.active_object
        with units.Units(user_units=DEFAULT_UNITS):
            self.translation_stiffness = model.settings.translation_stiffness
            self.rotation_stiffness = model.settings.rotation_stiffness
Exemplo n.º 3
0
    def is_small_bore(self):
        """Pipe sizes 2" and below are considered small bore.

        Imperial units are used here for the relational test.
        """
        with units.Units(user_units="english"):
            return self.od <= 2
Exemplo n.º 4
0
    def __init__(self, name, point):
        """Create a support instance at a node point.

        Parameters
        ----------
        name : str
            Unique name for pipe object.

        point : Point
            Point instance where support is located.

        translation_stiffnesss : float
            Stiffness in the translational directions.

            .. note::
               The default value is based on english units.

        rotation_stiffness : float
            Stiffness in the rotational directions.

            .. note::
               The default value is based on english units.
        """
        super(Support, self).__init__(name)
        self.point = point
        self.elememt = None

        model = self.app.models.active_object
        with units.Units(user_units=DEFAULT_UNITS):
            self.translation_stiffness = model.settings.translation_stiffness
            self.rotation_stiffness = model.settings.rotation_stiffness
Exemplo n.º 5
0
    def kfac(self, element):
        """Code flexibility factor for fittings."""
        model = self.app.models.active_object
        section = element.section
        material = element.material

        with units.Units(user_units="code_english"):
            if isinstance(element, Bend):
                R = section.radius          # bend radius
                tn = section.thk            # nominal thickness
                r = (section.od - tn) / 2   # mean radius
                Ec = material.ymod[model.settings.tref]
                pmax = self.pmax(element)
                h = self.h(element)

                kc = 1  # corrected for pressure - note 5
                if section.is_large_bore and section.is_thin_wall:
                    kc = 1 + 6 * (pmax/Ec) * (r/tn)**(7/3) * (R/r)**(1/3)

                k = (1.65 / h) / kc

                return 1.0 if k < 1 else k

            elif isinstance(element, Reducer):
                return 1.0

            else:
                return 1.0
Exemplo n.º 6
0
    def sts(self, element, forces):
        """Transverse shear stress"""
        with units.Units(user_units="code_english"):
            fy, fz = forces[1:3]
            F = math.sqrt(fy**2 + fz**2)

            section = element.section
            area = section.area

            return F / area
Exemplo n.º 7
0
    def stor(self, element, forces):
        """Shear stress due to torsion"""
        with units.Units(user_units="code_english"):
            mx = forces[3]

            section = element.section
            do = section.od
            Ip = section.ixx    # polar moment

            return mx*do / (2*Ip)
Exemplo n.º 8
0
    def slb(self, element, point, forces):
        """Longitudinal stress due to bending moments."""
        with units.Units(user_units="code_english"):
            my, mz = forces[-2:]
            M = math.sqrt(my**2 + mz**2)

            # note for B31.1 sifi equals sifo
            i = self.sifi(element, point)

            section = element.section
            Z = section.z   # section modulus

            return M*i / Z
Exemplo n.º 9
0
    def shoop(self, element, loadcase):
        """Hoop stress due to pressure.

        Conservatively equal to P*D/2t.
        """
        with units.Units(user_units="code_english"):
            sec = element.section
            do = sec.od
            thke = sec.thke
            pload = self.poper(element, loadcase)

            try:
                return (pload.pres*do) / (2*thke)
            except AttributeError:
                return 0
Exemplo n.º 10
0
    def from_file(cls, name, opercase, fluid="water", gfac=1.0, fname=None,
                  default_units="english"):
        if fname is None:
            fname = psi.FLUID_DATA_FILE

        with open(fname, "r") as csvfile:
            reader = csv.DictReader(csvfile)

            for row in reader:
                if row["fluid"] == fluid:
                    rho = float(row["rho"])

                    with units.Units(user_units=default_units):
                        return cls(name, opercase, rho, gfac)
            else:
                return None
Exemplo n.º 11
0
 def __init__(self, default_units=DEFAULT_UNITS):
     with units.Units(user_units=default_units):
         self._units = default_units
         self.vertical = "y"
         self.stress_case_corroded = True
         self.bourdon_effect = False
         self.pressure_thrust = False
         self.liberal_stress = False
         self.weak_springs = False
         self.nonlinear_iteration = 1000
         self.translation_stiffness = 10**10
         self.rotation_stiffness = 10**12
         self.axial_force = False
         self.tref = 70.0
         self.timoshenko = True
         self.version = VERSION
Exemplo n.º 12
0
    def sl(self, element, loadcase, point, forces):
        """Total longitudinal stress due to pressure and bending+torsion. This
        combination of stresses is also known as the code stress for most
        codes.
        """
        with units.Units(user_units="code_english"):
            slp = self.slp(element, loadcase)
            slb = self.slb(element, point, forces)
            sax = self.sax(element, forces)
            stor = self.stor(element, forces)

            if loadcase.stype == "sus" or loadcase.stype == "occ":
                return sax + slp + math.sqrt(slb**2 + 4*stor**2)
            elif loadcase.stype == "exp":
                return math.sqrt(slb**2 + 4*stor**2)
            else:
                return 0
Exemplo n.º 13
0
    def pmax(self, element):
        """Convenience function to get the largest element pressure from
        all operating cases.
        """
        with units.Units(user_units="code_english"):
            pressures = []
            for loadcase in element.loadcases:
                for loadtype, opercase in zip(loadcase.loadtypes,
                                            loadcase.opercases):
                    for load in element.loads:
                        if (isinstance(load, Pressure) and
                                load.opercase == opercase):
                            pressures.append(load)

            try:
                return max(pressures, key=lambda p: p.pres)
            except ValueError:
                return None
Exemplo n.º 14
0
    def sax(self, element, forces):
        """Axial stress due to mechanical loading.

        Axial stress can be included by user defined option. Force is zero by
        default.
        """
        sx = 0  # code default

        if self.app.models.active_object.settings.axial_force:
            with units.Units(user_units="code_english"):
                fx = forces[0]

                section = element.section
                area = section.area

                sx = fx/area

        return sx
Exemplo n.º 15
0
    def __init__(self, name, point, direction=None, is_rotational=False):
        """Create a support instance at a node point.

        Parameters
        ----------
        name : str
            Unique name for pipe object.

        point : Point
            Point instance where support is located.

        direction : str
            Support direction. Default is None. "+" and "-" is used to
            specify a directional support (non-linear).

        mu : float
            Support friction (non-linear).

        is_rotational : bool
            True if the support is a rotational restraint.

        is_snubber : bool
            True if the support is snubber.

        translation_stiffnesss : float
            Stiffness in the translational direction.

        rotation_stiffness : float
            Stiffness in the rotational direction.

        gap : float
            Support gap (non-linear).
        """
        super(AbstractSupport, self).__init__(name, point)
        self.direction = direction
        self.is_rotational = is_rotational
        self._mu = 0
        self._gap = 0
        self._is_snubber = False

        model = self.app.models.active_object
        with units.Units(user_units=DEFAULT_UNITS):
            self.translation_stiffness = model.settings.translation_stiffness
            self.rotation_stiffness = model.settings.rotation_stiffness
Exemplo n.º 16
0
    def slp(self, element, loadcase):
        """Longitudinal stress due to pressure.

        Exact formulation for the pressure stress per code section 102.3.2.
        The pressure stress is a primary stress and by definition can result
        in large gross deformations and overall failure, i.e., pipe rupture.
        """
        with units.Units(user_units="code_english"):
            section = element.section
            do = section.od
            di = section.id

            pload = self.poper(element, loadcase)

            try:
                # exact formulation
                return pload.pres*di**2 / (do**2-di**2)
            except AttributeError:
                return 0
Exemplo n.º 17
0
    def from_file(cls,
                  name,
                  size="W4x13",
                  fname=None,
                  default_units="english"):
        if fname is None:
            fname = psi.BEAM_DATA_FILE

        with open(fname, "r") as csvfile:
            reader = csv.DictReader(csvfile)

            for row in reader:
                if row["size"] == size:
                    d = float(row["d"])
                    tw = float(row["tw"])
                    bf = float(row["bf"])
                    tf = float(row["tf"])

                    with units.Units(user_units=default_units):
                        return cls(name, d, tw, bf, tf)
Exemplo n.º 18
0
    def toper(self, element, loadcase):
        """Convenience function to get the largest element temperature load for
        a particular operating case.
        """
        with units.Units(user_units="code_english"):
            thermals = []
            for loadtype, opercase in zip(loadcase.loadtypes,
                                          loadcase.opercases):
                for load in element.loads:
                    if (isinstance(load, Thermal) and
                            load.opercase == opercase):
                        thermals.append(load)

            # if length of temperature is greater than one, print warning
            # message saying multiple thermal loads exist for the same
            # operating case for the element, then proceed to take the max
            # worst pressure

            try:
                return max(thermals, key=lambda t: t.temp)
            except ValueError: # empty list
                return None
Exemplo n.º 19
0
    def poper(self, element, loadcase):
        """Convenience function to get the largest element pressure load for a
        particular operating case.
        """
        with units.Units(user_units="code_english"):
            # pressure load specified for loadcase and opercase sorted by
            # maximum
            pressures = []
            for loadtype, opercase in zip(loadcase.loadtypes,
                                          loadcase.opercases):
                for load in element.loads:
                    if (isinstance(load, Pressure) and
                            load.opercase == opercase):
                        pressures.append(load)

            # if length of pressures is greater than one, print warning message
            # saying multiple pressure loads exist for the same operating case
            # for the element, then proceed to take the max worst pressure

            try:
                return max(pressures, key=lambda p: p.pres)
            except ValueError:
                return None
Exemplo n.º 20
0
    def h(self, entity):
        """Flexibility characterisitic for fittings per the code."""
        with units.Units(user_units="code_english"):
            if isinstance(entity, Bend):
                # Per Appendix D of 1967 code
                R = entity.radius                  # bend radius
                tn = entity.section.thk            # nominal thk
                r = (entity.section.od - T) / 2    # mean radius
                h = (tn*R) / r**2                  # flexibility characteristic

                # stiffening effect due to flanged ends, note 3
                if entity.flange == 0:
                    c = 1
                elif entity.flange == 1:
                    c = h**(1/6)
                elif entity.flange == 2:
                    c = h**(1/3)

                h = c*h  # corrected h

                return h

            elif isinstance(entity, Reducer):
                return 1.0

            elif isinstance(entity, Welding):
                do = entity.do      # header pipe dia
                dob = entity.dob    # branch pipe dia
                tn = entity.tn      # nominal header thk
                rx = entity.rx      # crotch radius
                tc = entity.tc      # crotch thk
                r = (do-tn) / 2

                if rx >= dob/8 and tc >= 1.5*tn:
                    h = 4.4*tn / r
                else:
                    h = 3.1*tn / r

                return h

            elif isinstance(entity, Unreinforced):
                do = entity.do      # header pipe dia
                tn = entity.tn      # nominal header thk
                r = (do-tn) / 2
                h = tn / r

                return h

            elif isinstance(entity, Reinforced):
                do = entity.do      # header pipe dia
                tn = entity.tn      # nominal header thk
                tr = entity.tr      # pad thk
                r = (do-tn) / 2

                if tr > 1.5*tn:
                    h = 4.05*tn / r
                else:
                    h = (tn+tr/2)**(5/2) / (r*tn**(3/2))

                return h

            elif isinstance(entity, Weldolet):
                do = entity.do      # header pipe dia
                tn = entity.tn      # nominal header thk
                r = (do-tn) / 2
                h = 3.3*tn / r

                return h

            elif isinstance(entity, Sockolet):
                do = entity.do      # header pipe dia
                tn = entity.tn      # nominal header thk
                r = (do-tn) / 2
                h = 3.3*tn / r

                return h

            elif isinstance(entity, Sweepolet):
                do = entity.do      # header pipe dia
                dob = entity.dob    # branch pipe dia
                tn = entity.tn      # nominal header thk
                rx = entity.rx      # crotch radius
                tc = entity.tc      # crotch thk
                r = (do-tn) / 2

                if rx >= dob/8 and tc >= 1.5*tn:
                    h = 4.4*tn / r
                else:
                    h = 3.1*tn / r

                return h

            else:
                return 1.0
Exemplo n.º 21
0
    def from_file(cls,
                  name,
                  nps,
                  sch,
                  corra=None,
                  milltol=None,
                  fname=None,
                  default_units="english"):
        """Create a pipe object from a csv data file.

        Parameters
        ----------
        name : str
            Unique name for pipe object.

        nps : str
            Nominal pipe size.

        sch : str
            Pipe schedule designation.

        corro : float
            Corrosion allowance.

        milltol : float
            Mill tolerance. Enter the percent value such as 12.5.

        fname : str
            Full path to the csv data file used to do the lookup.

        default_units : str
            The units used for the data. Must be one of the units defined in
            the psi.UNITS_DIRECTORY path.

        Example
        -------
        Create a 10" schedule 40 pipe and activate the section.

        .. code-block:: python

            >>> p1 = Pipe.from_file("p1", "10", "40")
        """
        if fname is None:
            fname = psi.PIPE_DATA_FILE

        with open(fname, "r") as csvfile:
            reader = csv.DictReader(csvfile)

            # allows a schedule to have multiple names
            sch_map = {}
            schedules = reader.fieldnames[2:]
            for schedule in schedules:
                schs = schedule.split("/")
                for s in schs:
                    sch_map[s] = schedule

            for row in reader:
                if float(row["nps"]) == float(nps):
                    try:
                        nps = float(row["nps"])
                        od = float(row["od"])
                        thk = float(row[sch_map[sch]])

                        # using data file units to initialize
                        with units.Units(user_units=default_units):
                            return cls(name,
                                       od,
                                       thk,
                                       nps=nps,
                                       sch=sch,
                                       corra=corra,
                                       milltol=milltol)

                    except ValueError:  # calling float on empty string
                        return None
            else:
                return None
Exemplo n.º 22
0
    def from_file(cls,
                  name,
                  material,
                  code,
                  fname=None,
                  default_units="english"):
        """Create a material from a csv data file.

        Parameters
        ----------
        name : str
            Unique name for pipe object.

        material : str
            Name of material in database.

        code : str
            The piping code the material data comes from, 'B31.1' for example.

        fname : str
            Pull path to the csv data file used to do the lookup.

            .. note::
                The default path is set to the variable psi.MATERIAL_DATA_FILE.

        default_units : str
            The units used for the data. Must be one of the units defined in
            the psi.UNITS_DIRECTORY path.

            .. note::
                The values are converted to base units upon loading. Conversion
                to and from base to user units occurs on the fly.

        Example
        -------
        Create a A53A material instance and activate it.

        .. code-block:: python

            >>> mat1 = Material.from_file("A53A", "A53A", "B31.1")
        """
        if fname is None:
            fname = psi.MATERIAL_DATA_FILE

        def num(st):
            """Convert a string to an int or float"""
            try:
                return int(st)
            except ValueError:
                try:
                    return float(st)
                except ValueError:
                    return None  # value missing

        def convert(prop):
            vals = prop.split(",")
            if len(vals) == 1:
                return num(*vals)
            else:
                return [num(val) for val in vals]

        with open(fname) as csvfile:
            reader = csv.DictReader(csvfile)

            (NAME, CODE, RHO, NU, TEMP, ALP, YMOD, SH) = \
                ("name", "code", "rho", "nu", "temp", "alp", "ymod", "sh")
            for row in reader:
                if row[NAME] == material and row[CODE] == code:
                    rho = row[RHO]
                    nu = row[NU]
                    temp = row[TEMP]
                    alp = row[ALP]
                    ymod = row[YMOD]
                    sh = row[SH]

                    rho = convert(rho)
                    nu = convert(nu)
                    tempc = convert(temp)
                    alpc = convert(alp)
                    ymodc = convert(ymod)
                    shc = convert(sh)

                    with units.Units(user_units=default_units):
                        mat = cls(name)

                        # rho and nu not func of temp
                        mat.rho.value = rho
                        mat.nu.value = nu

                        # remove temps with no values given
                        mat.alp.table = [(t, v) for t, v in zip(tempc, alpc)
                                         if v is not None]
                        mat.sh.table = [(t, v) for t, v in zip(tempc, shc)
                                        if v is not None]
                        mat.ymod.table = [(t, v) for t, v in zip(tempc, ymodc)
                                          if v is not None]

                        return mat
            else:
                return None
Exemplo n.º 23
0
def element_codecheck(points, loadcase, element, S):
    """Perform element code checking based on the assigned code for primary
    load cases and load combinations.
    """
    ndof = 6
    idxi = points.index(element.from_point)
    idxj = points.index(element.to_point)

    # node and corresponding dof (start, finish)
    niqi, niqj = idxi * ndof, idxi * ndof + ndof
    njqi, njqj = idxj * ndof, idxj * ndof + ndof

    with units.Units(user_units="code_english"):
        # Note: units are changed to code_english for the moments
        # to have units of inch*lbf per code requirement
        # code equations are units specific, i.e. imperial or si

        if isinstance(loadcase, LoadCase):
            fori = loadcase.forces.results[niqi:niqj, 0]
            forj = loadcase.forces.results[njqi:njqj, 0]

            # code stresses per element node i and j for each loadcase
            shoop = element.code.shoop(element, loadcase)

            # pressure stress is same at both nodes
            slp = element.code.slp(element, loadcase)

            saxi = element.code.sax(element, fori)
            saxj = element.code.sax(element, forj)

            stori = element.code.stor(element, fori)
            storj = element.code.stor(element, forj)

            slbi = element.code.slb(element, element.from_point, fori)
            slbj = element.code.slb(element, element.to_point, forj)

            # total code stress
            sli = element.code.sl(element, loadcase, element.from_point, fori)
            slj = element.code.sl(element, loadcase, element.to_point, forj)

            # fitting and nodal sifs, sum together, take max or average?
            sifi = element.code.sifi(element, element.from_point)
            sifo = element.code.sifo(element, element.to_point)

            sallowi = element.code.sallow(element, loadcase, fori)
            sallowj = element.code.sallow(element, loadcase, forj)

            try:
                sratioi = sli / sallowi  # code ratio at node i
                sratioj = slj / sallowj  # code ratio at node j
            except ZeroDivisionError:
                sratioi = 0
                sratioj = 0

        elif isinstance(loadcase, LoadComb):
            # fitting and nodal sifs, sum together, take max or average?
            sifi = element.code.sifi(element)
            sifo = element.code.sifo(element)

            loadcomb = loadcase
            shoop_list, slp_list = [], []
            saxi_list, stori_list, slbi_list, sli_list = [], [], [], []
            saxj_list, storj_list, slbj_list, slj_list = [], [], [], []
            for factor, loadcase in zip_longest(loadcomb.factors,
                                                loadcomb.loadcases,
                                                fillvalue=1):
                fori = loadcase.forces.results[niqi:niqj, 0]
                forj = loadcase.forces.results[njqi:njqj, 0]

                shoop_list.append(factor *
                                  element.code.shoop(element, loadcase))
                slp_list.append(factor * element.code.slp(element, loadcase))

                saxi_list.append(factor * element.code.sax(element, fori))
                saxj_list.append(factor * element.code.sax(element, forj))

                stori_list.append(factor * element.code.stor(element, fori))
                storj_list.append(factor * element.code.stor(element, forj))

                slbi_list.append(
                    factor *
                    element.code.slb(element, element.from_point, fori))
                slbj_list.append(
                    factor * element.code.slb(element, element.to_point, forj))

                # total code stress
                sli_list.append(
                    element.code.sl(element, loadcase, element.from_point,
                                    fori))
                slj_list.append(
                    element.code.sl(element, loadcase, element.to_point, forj))

            if loadcomb.method == "scaler":
                shoop = sum(shoop_list)
                slp = sum(slp_list)

                saxi = sum(saxi_list)
                saxj = sum(saxj_list)

                stori = sum(stori_list)
                storj = sum(storj_list)

                slbi = sum(slbi_list)
                slbj = sum(slbj_list)

                sli = sum(sli_list)
                slj = sum(slj_list)

            elif loadcomb.method == "algebraic":
                # stress per algebraic combination of forces
                fori = loadcomb.forces.results[niqi:niqj, 0]
                forj = loadcomb.forces.results[njqi:njqj, 0]

                shoop = sum(shoop_list)
                slp = sum(slp_list)

                saxi = element.code.sax(element, fori)
                saxj = element.code.sax(element, forj)

                stori = element.code.stor(element, fori)
                storj = element.code.stor(element, forj)

                slbi = element.code.slb(element, element.from_point, fori)
                slbj = element.code.slb(element, element.to_point, forj)

                # total code stress
                sli = element.code.sl(element, loadcase, element.from_point,
                                      fori)
                slj = element.code.sl(element, loadcase, element.to_point,
                                      forj)

            elif loadcomb.method == "srss":
                # note: sign of factor has no effect, always positive
                shoop = sum([s**2 for s in shoop_list])
                slp = sum([s**2 for s in slp_list])

                saxi = sum([s**2 for s in saxi_list])
                saxj = sum([s**2 for s in saxj_list])

                stori = sum([s**2 for s in stori_list])
                storj = sum([s**2 for s in storj_list])

                slbi = sum([s**2 for s in slbi_list])
                slbj = sum([s**2 for s in slbj_list])

                sli = sum([s**2 for s in sli_list])
                slj = sum([s**2 for s in slj_list])

            elif loadcomb.method == "abs":
                shoop = sum([abs(s) for s in shoop_list])
                slp = sum([abs(s) for s in slp_list])

                saxi = sum([abs(s) for s in saxi_list])
                saxj = sum([abs(s) for s in saxj_list])

                stori = sum([abs(s) for s in stori_list])
                storj = sum([abs(s) for s in storj_list])

                slbi = sum([abs(s) for s in slbi_list])
                slbj = sum([abs(s) for s in slbj_list])

                sli = sum([abs(s) for s in sli_list])
                slj = sum([abs(s) for s in slj_list])

            elif loadcomb.method == "signmax":
                shoop = max(shoop_list)
                slp = max(slp_list)

                saxi = max(saxi_list)
                saxj = max(saxj_list)

                stori = max(stori_list)
                storj = max(storj_list)

                slbi = max(slbi_list)
                slbj = max(slbj_list)

                sli = max(sli_list)
                slj = max(slj_list)

            elif loadcomb.method == "signmin":
                shoop = min(shoop_list)
                slp = min(slp_list)

                saxi = min(saxi_list)
                saxj = min(saxj_list)

                stori = min(stori_list)
                storj = min(storj_list)

                slbi = min(slbi_list)
                slbj = min(slbj_list)

                sli = min(sli_list)
                slj = min(slj_list)

            # take the sqrt last
            if loadcomb.method == "srss":
                shoop = math.sqrt(shoop)
                slp = math.sqrt(slp)

                saxi = math.sqrt(saxi)
                saxj = math.sqrt(saxj)

                stori = math.sqrt(stori)
                storj = math.sqrt(storj)

                slbi = math.sqrt(slbi)
                slbj = math.sqrt(slbj)

                sli = math.sqrt(sli)
                slj = math.sqrt(slj)

            # allowable loadcomb stress
            sallowi_list = []
            sallowj_list = []
            # determine the loadcomb code stress allowable
            for loadcase in loadcomb.loadcases:
                stype = loadcase.stype  # save type
                loadcase.stype = loadcomb.stype  # change to loadcomb type

                fori = loadcase.forces.results[niqi:niqj, 0]
                forj = loadcase.forces.results[njqi:njqj, 0]

                # calculate loadcomb allowable
                sallowi = element.code.sallow(element, loadcase, fori)
                sallowi_list.append(sallowi)

                sallowj = element.code.sallow(element, loadcase, forj)
                sallowj_list.append(sallowj)

                # revert to loadcase stype
                loadcase.stype = stype
            sallowi = min(sallowi_list)
            sallowj = min(sallowj_list)

            try:
                sratioi = sli / sallowi  # code ratio at node i
                sratioj = slj / sallowj  # code ratio at node j
            except ZeroDivisionError:
                sratioi = 0
                sratioj = 0

        # hoop, sax, stor, slp, slb, sl, sifi, sifj, sallow, ir
        # take the worst code stress at node
        if sratioi > S[idxi, -1]:
            S[idxi, :10] = (shoop, saxi, stori, slp, slbi, sli, sifi, sifo,
                            sallowi, sratioi)

        if sratioj > S[idxj, -1]:
            S[idxj, :10] = (shoop, saxj, storj, slp, slbj, slj, sifi, sifo,
                            sallowj, sratioj)
Exemplo n.º 24
0
    def sifi(self, element, point, combfunc="max"):
        """In plane stress intensification factor for fittings. The sif must
        be 1 or greater.

        .. todo::
            The maximum sif at a point is taken. It should eventually be a user
            defined option to take the sum, max or average.
        """
        model = self.app.models.active_object
        section = element.section
        material = element.material
        sifs = []

        with units.Units(user_units="code_english"):
            if isinstance(element, (Run, Rigid, Valve, Flange)):
                sifs.append(1.0)

            elif isinstance(element, Bend):
                R = section.radius          # bend radius
                tn = section.thk            # nominal thickness
                r = (section.od - tn) / 2   # mean radius
                Ec = material.ymod[model.settings.tref]
                pmax = self.pmax(element)
                h = self.h(element)

                ic = 1  # corrected for pressure - note 5
                if section.is_large_bore and section.is_thin_wall:
                    ic = 1 + 3.25 * (pmax/Ec) * (r/tn)**(5/2) * (R/r)**(2/3)

                sif = (0.9 / h**(2/3)) / ic

                sifs.append(1.0 if sif < 1 else sif)

            elif isinstance(element, Reducer):
                D1 = section.od
                t1 = section.thk
                D2 = section2.od
                t2 = section2.thk
                L = element.length
                alp = element.alpha

                alpv = True if alp <= 60 else False
                conc = True if element.is_concentric else False
                d2t1 = True if section.d2t <= 100 else False
                d2t2 = True if section2.d2t <= 100 else False

                if all([alpv, conc, d2t1, d2t2]):
                    sif = 0.5 + 0.01*alp*(D2/t2)**(1/2)

                    sifs.append(1.0 if sif < 1 else sif)

                else:
                    sifs.append(2.0)

            for entity in element.sifs:

                if self.app.points(entity.point) is point:

                    if isinstance(entity, Welding):
                        # per mandatory appendix D
                        h = self.h(entity)

                        # in-plane and out-of-plane sifs are the same
                        # for B31.1 the higher is used
                        sif = 0.9 / h**(2/3)

                        # must be larger than or equal to 1.0
                        sifs.append(1.0 if sif < 1 else sif)

                    elif isinstance(entity, Unreinforced):
                        h = self.h(entity)

                        # in-plane and out-of-plane sifs are the same
                        # for B31.1 the higher is used
                        sif = 0.9 / h**(2/3)

                        sifs.append(1.0 if sif < 1 else sif)

                    elif isinstance(entity, Reinforced):
                        h = self.h(entity)

                        # in-plane and out-of-plane sifs are the same
                        # for B31.1 the higher is used
                        sif = 0.9 / h**(2/3)

                        sifs.append(1.0 if sif < 1 else sif)

                    elif isinstance(entity, Weldolet):
                        h = self.h(entity)

                        # in-plane and out-of-plane sifs are the same
                        # for B31.1 the higher is used
                        sif = 0.9 / h**(2/3)

                        sifs.append(1.0 if sif < 1 else sif)

                    elif isinstance(entity, Sockolet):
                        h = self.h(entity)

                        # in-plane and out-of-plane sifs are the same
                        # for B31.1 the higher is used
                        sif = 0.9 / h**(2/3)

                        sifs.append(1.0 if sif < 1 else sif)

                    elif isinstance(entity, Sweepolet):
                        h = self.h(entity)

                        # in-plane and out-of-plane sifs are the same
                        # for B31.1 the higher is used
                        sif = 0.9 / h**(2/3)

                        sifs.append(1.0 if sif < 1 else sif)

                    elif isinstance(entity, ButtWeld):
                        sifs.append(1.0)

                    else:
                        # must be 1 at a minimum
                        sifs.append(1.0)

            if combfunc == "max":
                return max(sifs)
            elif combfunc == "sum":
                return sum(sifs)
            elif combfunc == "avg":
                return sum(sifs) / len(sifs)