Skip to content
Snippets Groups Projects
ClassifyMin.py 14.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • import numpy as np
    import matplotlib.pyplot as plt
    import sympy as sym
    import math
    import os
    import subprocess
    import fileinput
    import re
    import matlab.engine
    import sys
    
    # from subprocess import Popen, PIPE
    
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    # --------------------------------------------------
    # 'classifyMin' classifies Minimizers by utilizing the result of
    # Lemma1.6
    #
    #
    #
    #
    # 'classifyMin_ana': (Special-Case : Lemma1.4)
    # ..additionally assumes Poisson-ratio=0 => q12==0
    #
    #
    #
    # Output : MinimizingMatrix, Angle, Type, Curvature
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    def determinant(q1,q2,q3,q12):                                  # TODO General:Matrix
        return q1*q2 - (q3**2 + 2*q3*q12 + q12**2)
    
    def harmonicMean(mu_1, beta, theta):
    
        return mu_1*(beta/(theta+((1-theta)*beta)))
    
    def arithmeticMean(mu_1, beta, theta):
    
    def prestrain_b1(rho_1, beta, alpha, theta):
    
        return (3.0*rho_1/2.0)*(1-(theta*(1+alpha)))
        # return (3.0*rho_1/2.0)*beta*(1-(theta*(1+alpha)))
    
    def prestrain_b2(rho_1, beta, alpha, theta):
    
        return (3.0*rho_1/(2.0*((1.0-theta) + theta*beta)))*(1-theta*(1+beta*alpha))
        # return (3.0*rho_1/(4.0*((1.0-theta) + theta*beta)))*(1-theta*(1+beta*alpha))
    
    # Define function to be minimized
    def f(a1, a2, q1, q2, q3, q12, b1, b2):
    
        A = np.array([[q1, q3 + q12/2.0], [q3 + q12/2.0, q2]])
        B = np.array([-2.0*q1*b1-q12*b2, -2.0*q2*b2-q12*b1])
        a = np.array([a1, a2])
    
        tmp = np.dot(A, a)
        tmp2 = np.dot(a, tmp)
        tmpB = np.dot(B, a)
    
        return tmp2 + tmpB + q1*(b1**2) + q2*(b2**2) + q12*b1*b2
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    # ---- Alternative Version using alpha,beta,theta ,mu_1,rho_1
    def classifyMin_ana(alpha,beta,theta,q3,mu_1,rho_1,print_Cases=False, print_Output=False):
    
        # Assumption of Classification-Lemma1.6:
        #  1. [b3 == 0]
        #  2. Q is orthotropic i.e. q13 = q31 = q23 = q32 == 0
        # 3. This additionally assumes that Poisson-Ratio = 0 => q12 == 0
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        q12 = 0.0
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        q1 = (1.0/6.0)*harmonicMean(mu_1, beta, theta)
        q2 = (1.0/6.0)*arithmeticMean(mu_1, beta, theta)
        # print('q1: ', q1)
        # print('q2: ', q2)
    
        b1 = prestrain_b1(rho_1, beta, alpha,theta)
        b2 = prestrain_b2(rho_1, beta, alpha,theta)
    
    
        # print('alpha:',alpha)
        # print('beta:',beta)
        # print('theta:',theta)
    
    
        return classifyMin(q1, q2, q3, q12,  b1, b2,  print_Cases, print_Output)
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
    
    
    # Matrix Version that just gets matrices Q & B
    def classifyMin_mat(Q,B,print_Cases=False, print_Output=False):
        q1 = Q[0][0]
        q2 = Q[1][1]
        q3 = Q[2][2]
        q12 = Q[0][1]
        b1 = B[0]
        b2 = B[1]
        b3 = B[2]
        return classifyMin(q1, q2, q3, q12,  b1, b2,  print_Cases, print_Output)
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
    
    # --------------------------------------------------------------------
    # Classify Type of minimizer  1 = R1 , 2 = R2 , 3 = R3                          # before : destinction between which axis.. (4Types )
    
    # where
    # R1 : unique local (global) minimizer which is not axial
    # R2 : continuum of local (global) minimizers which are not axial
    # R3 : one or two local (global) minimizers which are axial
    # Partition given by
    # R1 = E1
    # R2 = P1.2
    # R3 = E2 U E3 U P1.1 U P2 U H
    
    # -------------------------------------------------------------------
    def classifyMin(q1, q2, q3, q12, b1, b2,  print_Cases=False, print_Output=False):   #ClassifyMin_hom?
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        # Assumption of Classification-Lemma1.6:
        #  1. [b3 == 0]
        #  2. Q is orthotropic i.e. q13 = q31 = q23 = q32 == 0
    
        # TODO: check if Q is orthotropic here - assert()
    
    
    
        if print_Output: print("Run ClassifyMin...")
    
        epsilon = sys.float_info.epsilon #Machine epsilon
    
        B = np.array([-2.0*q1*b1-q12*b2, -2.0*q2*b2-q12*b1])
        A = np.array([[q1, q3 + q12/2.0], [q3 + q12/2.0, q2]])
        # print('Matrix A:',  A)
        # print('Matrix B:', B)
        # print('Matrix rank of A:', np.linalg.matrix_rank(A))
        # print('shape of A:', A.shape)
        # print('shape of B:', B.shape)
        # print('Matrix [A,B]:', np.c_[A, B])
        # print('Matrix rank of [A,B]:', np.linalg.matrix_rank(np.c_[A, B]))
        # print('shape of [A,B]:', C.shape)
        #
        # x = np.linalg.solve(A, B)     # works only if A is not singular!!
        # print("Solution LGS:", x)
        # # print("sym Matrix", sym.Matrix(([A],[B])))
        #
        # # Test
        # C = np.array([[1, 0], [0, 0]])
        # d = np.array([5, 0])
        # y = np.linalg.lstsq(C, d)[0]
        # print("Solution LGS:", y)
        # T = np.c_[C, d]
        # print('T:', T)
        # Trref = sym.Matrix(T).rref()[0]
        # Out = np.array(Trref, dtype=float)
        # print('rref:', Out)
    
    
        determinant = q1*q2 - (q3**2 + 2*q3*q12 + q12**2)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        if print_Cases: print("determinant:", determinant)
    
        # Define values for axial-Solutions (b1*,0) & (0,b2*)
        b1_star = (2.0*q1*b1 + b2*q12)/(2*q1)
        b2_star = (2.0*q2*b2 + b1*q12)/(2*q2)
    
        # ------------------------------------ Parabolic Case -----------------------------------
    
        if abs(determinant) < epsilon:
    
            if print_Cases: print('P : parabolic case (determinant equal zero)')
    
            print('P : parabolic case (determinant equal zero)')
    
            # if print_Cases: print('P : parabolic case (determinant equal zero)')
    
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
            # check if B is in range of A
    
            # check if rank(A) == rank([A,B])
            # OK this way? (or use Sympy?)
            if np.linalg.matrix_rank(A) == np.linalg.matrix_rank(np.c_[A, B]):
                if print_Cases: print('P1 (B is in the range of A)')
    
                if (q12+q3)/2.0 <= -1.0*epsilon:
                    print('should not happen(not compatible with det = 0)')
    
                if (abs(B[0]) < epsilon and abs(B[1]) < epsilon) and (q12+q3)/2.0 >= epsilon:
                    if print_Cases: print('P1.1')
                    a1 = 0.0
                    a2 = 0.0
                    type = 3
                    CaseCount += 1
    
                if (abs(B[0]) >= epsilon or abs(B[1]) >= epsilon) and (q12+q3)/2.0 >= epsilon:
                    # Continuum of minimizers located along a line of negative slope in Lambda
                    if print_Cases: print('P1.2 (Continuum of minimizers located along a line of negative slope in Lambda) ')
    
                    # Just solve Aa* = b (alternatively using SymPy ?)
                    # we know that A is singular (det A = 0 ) here..
                    # & we know that there are either infinitely many solutions or a unique solution ...
                    # ---- determine one via Least Squares
                    # "If A is square and of full rank, then x (but for round-off error)
                    # is the “exact” solution of the equation. Else, x minimizes the
                    # Euclidean 2-norm || b-Ax ||. If there are multiple minimizing solutions,
                    # the one with the smallest 2-norm  is returned. ""
    
    
                    # a = np.linalg.lstsq(A, B)[0]                            # TODO check is this Ok ?
                    a = np.linalg.lstsq(A, -B/2)[0]                            # TODO check is this Ok ? (UPDATE 13-10-21)
    
                    print("Solution LGS: a =", a)
                    a1 = a[0]
                    a2 = a[1]
    
                    type = 2
                    CaseCount += 1
            else:
                if print_Cases: print('P2 (B is not in the range of A)')
                # local Minimizers occur on the boundary of Lambda...
                # There are at most two local minima and they are either
                # (b1_star, 0) or (0, b2_star)
                # could also outsource this to another function..
                if f(b1_star, 0, q1, q2, q3, q12, b1, b2) < f(0, b2_star, q1, q2, q3, q12, b1, b2):
                    a1 = b1_star
                    a2 = 0.0
                    type = 3  # 1
                    CaseCount += 1
                if f(b1_star, 0, q1, q2, q3, q12, b1, b2) > f(0, b2_star, q1, q2, q3, q12, b1, b2):
                    a1 = 0
                    a2 = b2_star
                    type = 3  # 2
                    CaseCount += 1
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
                # TODO Problem: angle depends on how you choose... THE angle is not defined for this case
    
                if f(b1_star, 0, q1, q2, q3, q12, b1, b2) == f(0, b2_star, q1, q2, q3, q12, b1, b2):
                    # Two Minimizers pick one
                    a1 = b1_star
                    a2 = 0.0
                    type = 3  # 4
                    CaseCount += 1
    
        # ------------------------------------ Elliptic Case -----------------------------------
    
            if print_Cases: print('E : elliptic case (determinant greater zero)')
    
            a1_star = (b1*(q12**2) + 2*b1*q3*q12 - 4*b1*q1*q2 + 4*b2*q2*q3) / \
    
                (4*(q3**2) + 4*q3*q12 + (q12**2) - 4*q1*q2)
    
            a2_star = (b2*(q12**2) + 2*b2*q3*q12 + 4*b1*q1*q3 - 4*b2*q1*q2) / \
    
                (4*(q3**2) + 4*q3*q12 + (q12**2) - 4*q1*q2)
    
            prod = a1_star*a2_star
    
            if prod >= epsilon:
    
                if print_Cases: print('(E1) - inside Lambda ')
                a1 = a1_star
                a2 = a2_star
                type = 1  # non-axial Minimizer
                CaseCount += 1
            if abs(prod) < epsilon:   # same as prod = 0 ? or better use <=epsilon ?
                if print_Cases: print('(E2) - on the boundary of Lambda ')
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
                type = 3  # could check which axis: if a1_star or a2_star close to zero.. ?
    
    
            if prod <= -1.0*epsilon:
                if print_Cases: print('(E3) - Outside Lambda ')
                if f(b1_star, 0, q1, q2, q3, q12, b1, b2) < f(0, b2_star, q1, q2, q3, q12, b1, b2):
    
                if f(b1_star, 0, q1, q2, q3, q12, b1, b2) > f(0, b2_star, q1, q2, q3, q12, b1, b2):
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    
                # TODO Problem: angle depends on how you choose... THE angle is not defined for this case
    
                if f(b1_star, 0, q1, q2, q3, q12, b1, b2) == f(0, b2_star, q1, q2, q3, q12, b1, b2):
    
                    # Two Minimizers pick one
                    a1 = b1_star
                    a2 = 0.0
    
        # ------------------------------------ Hyperbolic Case -----------------------------------
        if determinant <= -1.0*epsilon:
            if print_Cases: print('H : hyperbolic case (determinant smaller zero)')
            # One or two minimizers wich are axial
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
            type = 3 # (always type 3)
    
            if f(b1_star, 0, q1, q2, q3, q12, b1, b2) < f(0, b2_star, q1, q2, q3, q12, b1, b2):
                a1 = b1_star
                a2 = 0.0
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
                # type = 3  # 1
    
                CaseCount += 1
            if f(b1_star, 0, q1, q2, q3, q12, b1, b2) > f(0, b2_star, q1, q2, q3, q12, b1, b2):
                a1 = 0
                a2 = b2_star
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
                # type = 3  # 2
    
                CaseCount += 1
            # TODO can add this case to first or second ..
            if f(b1_star, 0, q1, q2, q3, q12, b1, b2) == f(0, b2_star, q1, q2, q3, q12, b1, b2):
                # Two Minimizers pick one
                a1 = b1_star
                a2 = 0.0
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
                # type = 3  # 4
    
                CaseCount += 1
        # ---------------------------------------------------------------------------------------
    
        if (CaseCount > 1):
            print('Error: More than one Case happened!')
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        # a3 = math.sqrt(2.0*a1*a2)   # never needed?
    
        # print('a1:', a1)
        # print('a2:', a2)
    
    
        # compute the angle <(e,e_1) where Minimizer = kappa* (e (x) e)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        # e = [math.sqrt((a1/(a1+a2))), math.sqrt((a2/(a1+a2)))]
        e = [((a1/(a1+a2)))**0.5, ((a2/(a1+a2)))**0.5]
    
        angle = math.atan2(e[1], e[0])
    
        # compute kappa
        kappa = (a1 + a2)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        # Minimizer G
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
        # Minimizer = np.array([[a1, math.sqrt(a1*a2)], [math.sqrt(a1*a2), a2]],dtype=object)
        Minimizer = np.array([[a1, (a1*a2)**0.5], [(a1*a2)**0.5, a2]],dtype=object)
    
        # Minimizer = np.array([[a1, math.sqrt(a1*a2)], [math.sqrt(a1*a2), a2]])
    
        # MinimizerVec = np.array([a1, a2],dtype=object)
        MinimizerVec = np.array([a1, a2])
    
    
        if print_Output:
            print('--- Output ClassifyMin ---')
            print("Minimizing Matrix G:")
            print(Minimizer)
            print("angle = ", angle)
            print("type: ", type)
            print("kappa = ", kappa)
    
        return Minimizer, angle, type, kappa
    
        # return MinimizerVec, angle, type, kappa    #return Minimizer Vector instead
    
    # ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    # ---------------------------------------------- Main ---------------------
    
    # --- Input Parameters ----
    # mu_1 = 1.0
    # rho_1 = 1.0
    # alpha = 9.0
    # beta = 2.0
    # theta = 1.0/8.0
    
    # # define q1, q2 , mu_gamma, q12
    # # 1. read from Cell-Output
    # # 2. define values from analytic formulas (expect for mu_gamma)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    # q1 = (1.0/6.0)*harmonicMean(mu_1, beta, theta)
    # q2 = (1.0/6.0)*arithmeticMean(mu_1, beta, theta)
    
    # # TEST
    # q12 = 0.0  # (analytical example)
    # # q12 = 12.0  # (analytical example)
    
    
    # set mu_gamma  to value or read from Cell-Output
    
    # mu_gamma = q1   # TODO read from Cell-Output
    # b1 = prestrain_b1(rho_1, beta, alpha, theta)
    # b2 = prestrain_b2(rho_1, beta, alpha, theta)
    
    
    # print('---- Input parameters: -----')
    # print('mu_1: ', mu_1)
    # print('rho_1: ', rho_1)
    # print('alpha: ', alpha)
    # print('beta: ', beta)
    # print('theta: ', theta)
    # print("q1: ", q1)
    # print("q2: ", q2)
    # print("mu_gamma: ", mu_gamma)
    # print("q12: ", q12)
    # print("b1: ", b1)
    # print("b2: ", b2)
    # print('----------------------------')
    # # print("machine epsilon", sys.float_info.epsilon)
    #
    #
    # # ------- Options --------
    # print_Cases = True
    # print_Output = True
    
    # G, angle, type, kappa = classifyMin(q1, q2, mu_gamma, q12,  b1, b2, print_Cases, print_Output)
    #
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    # G, angle, type, kappa = classifyMin_ana(alpha, beta, theta, mu_gamma, q12, print_Cases, print_Output)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    # Out = classifyMin_ana(alpha, beta, theta, mu_gamma, q12, print_Cases, print_Output)
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    # Out = classifyMin_ana(alpha, beta, theta)
    
    
    # print('Out[0]', Out[0])
    # print('Out[1]', Out[1])
    # print('Out[2]', Out[2])
    # print('Out[3]', Out[3])
    
    
    # #supress certain Outout..
    
    Klaus Böhnlein's avatar
    Klaus Böhnlein committed
    # _,_,T,_ = classifyMin_ana(alpha, beta, theta, mu_gamma, q12, print_Cases, print_Output)
    
    # print('Output only type..:', T)
    
    # Test = f(1,2 ,q1,q2,mu_gamma,q12,b1,b2)
    # print("Test", Test)
    
    # -----------------------------------------------------------------------------------------------------------------------------------------------------------------