#
# Copyright © 2020 MSC.Software Corporation
#  
# Permission to use Scripts
#  
# Permission is granted to MSC.Software customers with valid licenses of the MSC Apex™ software 
# to use script files posted on this page (collectively “Scripts”) solely for customers’ own authorized 
# internal use in conjunction with licensed use of the MSC Apex software.  
# No other use is permitted.  No license to MSC Apex or other software is granted under this Permission.
#  
# SCRIPTS ARE PROVIDED ON AN "AS-IS" BASIS, WITH NO WARRANTIES OF ANY KIND.  USE OF THE SCRIPTS IS AT CUSTOMER'S SOLE RISK.
#  
# IN NO EVENT SHALL MSC.SOFTWARE CORPORATION, ITS AFFILIATES, SUBSIDIARIES, SUPPLIERS, AGENTS, REPRESENTATIVES OR EMPLOYEES BE LIABLE FOR ANY 
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, 
# STRICT LIABILITY, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION USE OF THE SCRIPTS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
#  
# Customer shall indemnify, defend and hold MSC.Software Corporation, its affiliates, subsidiaries, suppliers, agents, 
# employees or representatives (collectively, “Indemnified Parties”) harmless from and against any third-party claims 
# brought against Indemnified Parties rising out of or in connection with Customer’s use of the Scripts.
#
"""composite failure processing module"""
import math
import materialsCDE
from importlib import reload
reload(materialsCDE)


def Ilss(Sigma13, Sigma23, Allowable):
    """ calculates ILSS allowable using RSS of ILSS components"""
    rf = Allowable/math.sqrt(Sigma13**2+Sigma23**2)
    return rf


def max_strain(strain, material):
    ''' Max strain failure calculation \n
        Input ply strain numpy array\n
        Input material object'''

    # get material properties, converting stress allowables to strain

    if isinstance(material, materialsCDE.matOrth):
        # print(f"Strain = {strain}")
        sxt = material.xt / material.e1
        sxc = material.xc / material.e1
        syt = material.yt / material.e2
        syc = material.yc / material.e2
        sss = material.s / material.g12
    elif isinstance(material, materialsCDE.matIso):
        sxt = material.st / material.e
        sxc = material.sc / material.e
        syt = material.st / material.e
        syc = material.sc / material.e
        sss = material.ss / material.g

    # print(f"xt={sxt}")
    # print(f"xc={sxc}")
    # print(f"yt={syt}")
    # print(f"yc={syc}")
    # print(f"ss={sss}")
    FIXt = strain[0] / sxt
    FIXc = -strain[0] / sxc
    FIYt = strain[1] / syt
    FIYc = strain[1] / -syc
    FIXY = strain[2] / sss

    strength_ratio = 1.0 / max([FIXt, FIXc, FIYt, FIYc, FIXY])
    return strength_ratio


def tsai_wu(sigma, material):
    ''' Tsai-Wu failure calculation \n
        Input ply strain numpy array\n
        Input material object
        Return strength ratio value'''
    if isinstance(material, materialsCDE.matOrth):
        # print(f"Sigma = {sigma}")
        xt = material.xt
        xc = material.xc
        yt = material.yt
        yc = material.yc
        ss = material.s
        ixy = material.ixy
    elif isinstance(material, materialsCDE.matIso):
        xt = material.st
        xc = material.sc
        yt = material.st
        yc = material.sc
        ss = material.ss
        ixy = -0.5
    # print(f"xt={xt}")
    # print(f"xc={xc}")
    # print(f"yt={yt}")
    # print(f"yc={yc}")
    # print(f"ss={ss}")
    f1 = 1 / xt - 1 / xc
    f2 = 1 / yt - 1 / yc
    f11 = 1.0/xt/xc
    f22 = 1.0/yt/yc
    f12 = ixy/math.sqrt(xt*xt*yt*yc)
    f66 = 1/ss/ss

    a = f11 * sigma[0] ** 2 + f22 * sigma[1] ** 2 + \
        2 * f12 * sigma[0] * sigma[1] + f66 * sigma[2] ** 2
    b = f1 * sigma[0] + f2 * sigma[1]

    strength_ratio = (- b + math.sqrt(b ** 2 + 4 * a)) / 2 / a

    # print(f"Tsai-Wu: SR = {strength_ratio}")
    return strength_ratio


def hill(sigma, material):
    ''' Hill failure calculation \n
        Input ply stress sigma numpy array\n
        Input material object'''
    if isinstance(material, materialsCDE.matOrth):
        # print(f"Sigma = {sigma}")
        xt = material.xt
        xc = material.xc
        yt = material.yt
        yc = material.yc
        ss = material.s
    elif isinstance(material, materialsCDE.matIso):
        xt = material.st
        xc = material.sc
        yt = material.st
        yc = material.sc
        ss = material.ss
    # print(f"xt={xt}")
    # print(f"xc={xc}")
    # print(f"yt={yt}")
    # print(f"yc={yc}")
    # print(f"ss={ss}")
    if sigma[[0]] > 0.0:
        f11 = 1.0/xt/xt
    else:
        f11 = 1.0/xc/xc
    if sigma[1] > 0.0:
        f22 = 1.0/yt/yt
    else:
        f22 = 1.0/yc/yc
    if sigma[0] * sigma[1] > 0.0:
        f12 = -1.0/xt/xt
    else:
        f12 = -1.0/xc/xc
    # print(f"F11: {f11} f22 {f22} f12 {f12}")
    failure_index = sigma[0]**2 * f11 + \
        sigma[1]**2 * f22 + \
        sigma[0] * sigma[1] * f12 + \
        sigma[2]**2 / ss / ss
    strength_ratio = 1.0 / math.sqrt(failure_index)
    # print(f"Hill: FI = {failure_index} SR = {strength_ratio}")
    return strength_ratio
