from functions import *
import numpy as np
import math
import time

def main() -> int:
    start_time = time.time()

    # Filepath of models whose solutions are to be superimposed
    filepath1 = 'safety_valve_pressure.liml'
    filepath2 = 'safety_valve_thermal.liml'
    filepathSup = 'safety_valve_superimposed.liml'    # new file for superimposed solutions

    # Element values and node values are superimposed separately
    # # # # 1st superimposition of element stresses # # # #

    # read stresses from .liml files [Base64 encoded]
    d1_Base64 = np.empty(shape=1, dtype=str)
    d2_Base64 = np.empty(shape=1, dtype=str)
    first_word = np.array(['<elementnodevariable name="stressxx">','<elementnodevariable name="stressyy">','<elementnodevariable name="stresszz">','<elementnodevariable name="stressxy">','<elementnodevariable name="stressyz">','<elementnodevariable name="stresszx">'])
    second_word = '<values>'
    third_word = '</values>'
    for i, x in enumerate(first_word):
        with open(filepath1,'r',encoding='utf-8-sig') as file1:
            content1 = file1.read()
        position1 = findWordAfterWord(content1,first_word[i],second_word)
        position2 = findWordAfterWord(content1,first_word[i],third_word)
        position1 = position1 + len(second_word)
        d1_Base64 = np.vstack((d1_Base64,substringFromString(content1,position1,position2)))
        with open(filepath2,'r',encoding='utf-8-sig') as file2:
            content2 = file2.read()
        position1 = findWordAfterWord(content2,first_word[i],second_word)
        position2 = findWordAfterWord(content2,first_word[i],third_word)
        position1 = position1 + len(second_word)
        d2_Base64 = np.vstack((d2_Base64,substringFromString(content2,position1,position2)))        
    d1_Base64 = np.delete(d1_Base64,0,axis=0)
    d2_Base64 = np.delete(d2_Base64,0,axis=0)

    # decode from Base64 to HEX
    d1_hex = np.vectorize(base64_to_hex)(d1_Base64)
    d2_hex = np.vectorize(base64_to_hex)(d2_Base64)
    d1_hex_split = np.empty(shape=(1,int(len(d1_hex[0,0])/16)), dtype=str)
    d2_hex_split = np.empty(shape=(1,int(len(d2_hex[0,0])/16)), dtype=str)
    for i, x in enumerate(d1_hex):
        d1_hex_split = np.vstack((d1_hex_split,split_string(d1_hex[i,0],16)))
        d2_hex_split = np.vstack((d2_hex_split,split_string(d2_hex[i,0],16)))
    d1_hex_split = np.delete(d1_hex_split,0,axis=0)
    d2_hex_split = np.delete(d2_hex_split,0,axis=0)

    # convert from HEX to Double (float64)
    d1_double = np.vectorize(hex_to_double)(d1_hex_split)
    d2_double = np.vectorize(hex_to_double)(d2_hex_split)

    # superimposition of stresses
    d12_double = d1_double+d2_double

    # calculation of von Mises stress
    vonMises = np.zeros(len(d12_double.T),dtype=np.float64)
    for i, x in enumerate(d12_double.T):
        vonMises[i] = math.sqrt(d12_double[0,i]**2+d12_double[1,i]**2+d12_double[2,i]**2-d12_double[0,i]*d12_double[1,i]-d12_double[0,i]*d12_double[2,i]-d12_double[1,i]*d12_double[2,i]+3*(d12_double[3,i]**2+d12_double[4,i]**2)+d12_double[5,i]**2)
    d12_double = np.vstack((d12_double,vonMises))

    # determination of min and max stresses
    d12_min = np.amin(d12_double,axis=1)
    d12_max = np.amax(d12_double,axis=1)

    # convert values from double to hex
    d12_hex = np.empty((1, len(d12_double.T)), dtype=str)
    for i, x in enumerate(d12_double):
        hex_stressComponent = numpy_array_to_hex(d12_double[i])
        d12_hex = np.vstack((d12_hex,hex_stressComponent))    
    d12_hex = np.delete(d12_hex,0,axis=0)
    # concatenade rows/strings
    d12_hex_string = [''.join(row) for row in d12_hex]
    d12_hex_string = np.array(d12_hex_string,dtype=str).reshape(-1,1)

    # encode hex to Base64
    d12_base64 = np.empty((1,1),dtype=str)
    for i, x in enumerate(d12_hex_string):
        base64_stressComponent = hexString2Base64(d12_hex_string[i])
        base64_stressComponent = base64_stressComponent.decode('utf-8')
        d12_base64 = np.vstack((d12_base64,base64_stressComponent))
    d12_base64 = np.delete(d12_base64,0,axis=0)

    # insert linebreaks after every 64th character (not a necessity)
    n = len(d12_base64)
    for i, x in enumerate(d12_base64):
        d12_base64 = np.vstack((d12_base64,insert_linebreaks(d12_base64[i,0])))
    d12_base64 = np.delete(d12_base64, np.s_[:n], axis=0)

    #  create new .liml string with superimposed stresses
    first_wordSup = np.array(['<elementnodevariable name="stressxx">','<elementnodevariable name="stressyy">','<elementnodevariable name="stresszz">','<elementnodevariable name="stressxy">','<elementnodevariable name="stressyz">','<elementnodevariable name="stresszx">','<elementnodevariable name="vonmises">'])
    second_word = '<values>'
    third_word = '</values>'
    contentSup = replaceContent(content1,first_wordSup,second_word,third_word,d12_base64)
    # replace max values
    second_word = 'max="'
    third_word = '" min'
    contentSup = replaceContentNum(contentSup,first_wordSup,second_word,third_word,d12_max)
    # replace min values
    second_word = 'min="'
    third_word = '" />'
    contentSup = replaceContentNum(contentSup,first_wordSup,second_word,third_word,d12_min)   

    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

    # # # # 2nd superimposition of node stresses # # # #

    # read stresses from .liml files [Base64 encoded]
    d1_Base64 = np.empty(shape=1, dtype=str)
    d2_Base64 = np.empty(shape=1, dtype=str)
    first_word = np.array(['<nodevariable name="stressxx">','<nodevariable name="stressyy">','<nodevariable name="stresszz">','<nodevariable name="stressxy">','<nodevariable name="stressyz">','<nodevariable name="stresszx">'])
    second_word = '<values>'
    third_word = '</values>'
    for i, x in enumerate(first_word):
        position1 = findWordAfterWord(content1,first_word[i],second_word)
        position2 = findWordAfterWord(content1,first_word[i],third_word)
        position1 = position1 + len(second_word)
        d1_Base64 = np.vstack((d1_Base64,substringFromString(content1,position1,position2)))
        position1 = findWordAfterWord(content2,first_word[i],second_word)
        position2 = findWordAfterWord(content2,first_word[i],third_word)
        position1 = position1 + len(second_word)
        d2_Base64 = np.vstack((d2_Base64,substringFromString(content2,position1,position2)))        
    d1_Base64 = np.delete(d1_Base64,0,axis=0)
    d2_Base64 = np.delete(d2_Base64,0,axis=0)

    # decode from Base64 to HEX
    d1_hex = np.vectorize(base64_to_hex)(d1_Base64)
    d2_hex = np.vectorize(base64_to_hex)(d2_Base64)
    d1_hex_split = np.empty(shape=(1,int(len(d1_hex[0,0])/16)), dtype=str)
    d2_hex_split = np.empty(shape=(1,int(len(d2_hex[0,0])/16)), dtype=str)
    for i, x in enumerate(d1_hex):
        d1_hex_split = np.vstack((d1_hex_split,split_string(d1_hex[i,0],16)))
        d2_hex_split = np.vstack((d2_hex_split,split_string(d2_hex[i,0],16)))
    d1_hex_split = np.delete(d1_hex_split,0,axis=0)
    d2_hex_split = np.delete(d2_hex_split,0,axis=0)

     # convert from HEX to Double (float64)
    d1_double = np.vectorize(hex_to_double)(d1_hex_split)
    d2_double = np.vectorize(hex_to_double)(d2_hex_split)

    # superimposition of stresses
    d12_double = d1_double+d2_double

    # calculation of von Mises stress
    vonMises = np.zeros(len(d12_double.T),dtype=np.float64)
    for i, x in enumerate(d12_double.T):
        vonMises[i] = math.sqrt(d12_double[0,i]**2+d12_double[1,i]**2+d12_double[2,i]**2-d12_double[0,i]*d12_double[1,i]-d12_double[0,i]*d12_double[2,i]-d12_double[1,i]*d12_double[2,i]+3*(d12_double[3,i]**2+d12_double[4,i]**2)+d12_double[5,i]**2)
    d12_double = np.vstack((d12_double,vonMises))

    # determination of min and max stresses
    d12_min = np.amin(d12_double,axis=1)
    d12_max = np.amax(d12_double,axis=1)

    # convert values from double to hex
    d12_hex = np.empty((1, len(d12_double.T)), dtype=str)
    for i, x in enumerate(d12_double):
        hex_stressComponent = numpy_array_to_hex(d12_double[i])
        d12_hex = np.vstack((d12_hex,hex_stressComponent))    
    d12_hex = np.delete(d12_hex,0,axis=0)
    # concatenade rows/strings
    d12_hex_string = [''.join(row) for row in d12_hex]
    d12_hex_string = np.array(d12_hex_string,dtype=str).reshape(-1,1)

    # encode hex to Base64
    d12_base64 = np.empty((1,1),dtype=str)
    for i, x in enumerate(d12_hex_string):
        base64_stressComponent = hexString2Base64(d12_hex_string[i])
        base64_stressComponent = base64_stressComponent.decode('utf-8')
        d12_base64 = np.vstack((d12_base64,base64_stressComponent))
    d12_base64 = np.delete(d12_base64,0,axis=0)

    # insert linebreaks after every 64th character (not a necessity)
    n = len(d12_base64)
    for i, x in enumerate(d12_base64):
        d12_base64 = np.vstack((d12_base64,insert_linebreaks(d12_base64[i,0])))
    d12_base64 = np.delete(d12_base64, np.s_[:n], axis=0)

    #  add/replace superimposed stresses to/in .liml string
    first_wordSup = np.array(['<nodevariable name="stressxx">','<nodevariable name="stressyy">','<nodevariable name="stresszz">','<nodevariable name="stressxy">','<nodevariable name="stressyz">','<nodevariable name="stresszx">','<nodevariable name="vonmises">'])
    second_word = '<values>'
    third_word = '</values>'
    contentSup = replaceContent(contentSup,first_wordSup,second_word,third_word,d12_base64)
    # replace max values
    second_word = 'max="'
    third_word = '" min'
    contentSup = replaceContentNum(contentSup,first_wordSup,second_word,third_word,d12_max)
    # replace min values
    second_word = 'min="'
    third_word = '" />'
    contentSup = replaceContentNum(contentSup,first_wordSup,second_word,third_word,d12_min) 

    # # # # Write into new .liml file # # # #
    with open(filepathSup, 'w', encoding='utf-8-sig') as dateiNeu:
        dateiNeu.write(contentSup)
    print(f"Mecway file '{filepathSup}' with superimposed stresses created")

    end_time = time.time()
    elapsed_time = end_time - start_time
    minutes = int(elapsed_time // 60)
    seconds = elapsed_time % 60
    print(f"Done! This took {minutes} minutes and {seconds:.2f} seconds")

    return 0

        
if __name__ == '__main__':
    main()




