Esempio n. 1
0
def IntegratorNL1D(V, P, C_V, C_P, probeReadFinishBe, probeReadStartAf):

    i = 1
    V.tempVarPol, V.tempTempVarE, V.tempVarE, V.tempTempVarPol, V.polarisationCurr, V.Ex, V.Dx, V.Hy = BaseFDTD11.FieldInit(
        V, P)  #Not necessary?

    V.UpHyMat, V.UpExMat = BaseFDTD11.EmptySpaceCalc(V, P)
    # move these into bc manager, call bc manager from here
    C_V = BaseFDTD11.CPML_FieldInit(V, P, C_V, C_P)
    C_V = boundCondManager(V, P, C_V, C_P)

    lamCont, lamDisc, diff, V.plasmaFreqE, fix = gStab.spatialStab(
        P.timeSteps, P.Nz, P.dz, P.freq_in, P.delT, V.plasmaFreqE, V.omega_0E,
        V.gammaE)
    Exs, Hys = SourceManager(V, P, C_V, C_P)
    #Exs = Sig_Mod(V,P, Exs)
    #Hys = Sig_Mod(V,P, Hys, AmpMod = 1/P.CharImp)

    for counts in range(0, P.timeSteps):

        #if i == 1:
        #V.tempTempVarPol, V.tempVarPol, V.tempVarE, V.tempTempVarE, V.tempTempVarHy, V.tempVarHy, V.tempTempVarJx, V.tempVarJx, C_V.tempTempVarPsiEx, C_V.tempVarPsiEx, C_V.tempTempVarPsiHy, C_V.tempVarPsiHy = BaseFDTD11.ADE_TempPolCurr(V,P, C_V, C_P)
        #V.polarisationCurr = BaseFDTD11.ADE_PolarisationCurrent_Ex(V, P, C_V, C_P, counts)

        V.Ex = BaseFDTD11.ADE_ExUpdate(V, P, C_V, C_P, counts)
        # V.Jx = BaseFDTD11.ADE_JxUpdate(V,P, C_V, C_P)

        if P.CPMLXp == True or P.CPMLXm == True:  # Go into cpml field updates to choose x+ and x-
            C_V.psi_Ex, V.Ex = BaseFDTD11.CPML_Psi_e_Update(V, P, C_V, C_P)

        V.Ex[P.nzsrc] += Exs[counts] / P.courantNo

        if P.TFSF == True:
            V.Hy[P.nzsrc - 1] -= Hys[counts] / P.courantNo
        V.Dx = BaseFDTD11.ADE_DxUpdate(V, P, C_V, C_P)  # Linear bit
        # V.Ex =BaseFDTD11.ADE_ExCreate(V, P, C_V, C_P)
        V.Acubic = BaseFDTD11.AcubicFinder(V, P)
        if not counts % 50:
            print(counts)
        V.Ex = BaseFDTD11.NonLinExUpdate(V, P)
        V.Hy = BaseFDTD11.ADE_HyUpdate(V, P, C_V, C_P)
        if P.CPMLXp == True or P.CPMLXm == True:
            C_V.psi_Hy, V.Hy = BaseFDTD11.CPML_Psi_m_Update(V, P, C_V, C_P)

        if counts > 0:
            if counts % P.vidInterval == 0:
                if i == 1:
                    V.Ex_History = vidMake(V,
                                           P,
                                           C_V,
                                           C_P,
                                           counts,
                                           V.Ex,
                                           whichField="Ex")
        V.Port1, V.Port2 = probeSim(V, P, C_V, C_P, counts, nonlinear=True)

    return V.Ex, V.Hy, Exs, Hys, C_V.psi_Ex, C_V.psi_Hy, V.x1ColBe, V.x1ColAf
Esempio n. 2
0
def TimeIter(A, B, UnP1A, UnP1B, Xn, V, P, C_V, C_P):
    Exs, Hys = BF.SmoothTurnOn(V, P)
    print("MOR Time stepping...")

    for jj in range(P.timeSteps):
        print("Timestepping, step number: ", jj)
        UnP1A, UnP1B, B = BAndSourceVector(V, P, C_V, C_P)
        UnP1A[P.nzsrc] = Hys[jj] / P.CharImp
        UnP1B[P.nzsrc - 1] = -Exs[jj]
        UnP1 = np.block([UnP1A, UnP1B])
        #UnP1 = sparse.csc_matrix(UnP1)
        B = sparse.csc_matrix(B)
        #Xn = sparse.csc_matrix(Xn)
        XnP1 = np.zeros(2 * P.Nz + 2)
        #XnP1 = sparse.csc_matrix(XnP1)
        if jj == 0:
            XnP1 = A @ Xn.T
            XnP1 += B @ UnP1.T
        elif jj > 0:
            XnP1 = A @ XnP1.T
            XnP1 += B @ UnP1.T

    # XnP1 = XnP1.todense()
        for ii in range(len(V.Ex)):
            V.Ex[ii] = XnP1[ii]
            V.Hy[ii] = XnP1[ii + len(V.Ex)]
        V.Ex_History[jj] = V.Ex

        Xn = XnP1

    return B, V.Ex, V.Ex_History, V.Hy, UnP1, Xn
Esempio n. 3
0
def boundCondManager(V, P, C_V, C_P):
    # in here we set up boundary conditions, if cpml, call relevant cpml stuff,
    # or call other boundary condition update funcs.
    # if no B.Cs needed, set dummy var arrays as ones.

    #integrators call this to set up boundary conditions and call appropriate
    #features. switch case?
    if P.CPMLXp or P.CPMLXm:

        C_V.sigma_Ex, C_V.sigma_Hy, C_V.alpha_Ex, C_V.alpha_Hy, C_V.kappa_Ex, C_V.kappa_Hy = BaseFDTD11.CPML_ScalingCalc(
            V, P, C_V, C_P)

        C_V.beX, C_V.ceX = BaseFDTD11.CPML_Ex_RC_Define(V, P, C_V, C_P)
        C_V.bmY, C_V.cmY = BaseFDTD11.CPML_HY_RC_Define(V, P, C_V, C_P)
        C_V.eLoss_CPML, C_V.Ca, C_V.Cb, C_V.Cc = BaseFDTD11.CPML_Ex_Update_Coef(
            V, P, C_V, C_P)
        C_V.mLoss_CPML, C_V.C1, C_V.C2, C_V.C3 = BaseFDTD11.CPML_Hy_Update_Coef(
            V, P, C_V, C_P)

        C_V.den_Exdz, C_V.den_Hydz = BaseFDTD11.denominators(V, P, C_V, C_P)
    return C_V
Esempio n. 4
0
def SourceManager(V, P, C_V, C_P):
    ## boolean fed into argument which chooses source to use and creates appropiately.
    if P.SineCont == True:
        Exs, Hys1 = BaseFDTD11.SmoothTurnOn(V, P)
        Exp, Hyp1 = np.zeros(P.timeSteps), np.zeros(P.timeSteps)
        if P.nonLinMed:
            tempfreq = P.freq_in
            pumpFreq = tempfreq * 0.8
            Exp, Hyp1 = BaseFDTD11.SmoothTurnOn(V, P, tempfreq=pumpFreq)
            Exp = np.asarray(Exp) * P.courantNo
            Hyp1 = np.asarray(Hyp1) * P.courantNo
            Exp *= 0.1
            Hyp1 *= 0.01
        Exs = np.asarray(Exs) * P.courantNo + Exp
        Hys1 = np.asarray(Hys1) * P.courantNo + Hyp1
        #breakpoint()
        if P.TFSF == True:
            Hys1 = Hys1 * (1 / P.CharImp)
        return Exs, Hys1
        #
    #if SineCont == True
    #run SineCont function with no of repeatsm time +interval between
    if P.Gaussian == True:  # Generate Exs and use
        Exs = BaseFDTD11.Gaussian(V, P)
        Hys = np.zeros(len(Exs))
        if P.TFSF == True:
            Hys = BaseFDTD11.Gaussian(V, P)

        #plt.plot(Exs)
    # Width and other components should be defaulted in construct of sourcemanager
    # source manager changes the source point then returns whole field
    #if Ricker == True
    # Ricker func in basefdtd11.
        return Exs, Hys

    return [], []
Esempio n. 5
0
def results(V,
            P,
            C_V,
            C_P,
            time_Vec,
            RefCo=False,
            FFT=False,
            AnalRefCo=False,
            attenRead=False):

    valM = np.zeros(len(V.x1Atten))
    attenCo = np.zeros(len(valM))
    if attenRead == True:
        sig_pow, sample_freq, val = transH.RefTester(V, P, V.x1ColBe, 1)
        for i in range(len(V.x1Atten)):
            valM[i] = transH.RefTester(V, P, V.x1Atten[i], 1, mul=True)

            attenCo[i] = valM[i] / val
        #breakpoint()
        return attenCo

    elif RefCo == True:

        #transm, sig_fft1, sig_fft2, sample_freq, timePadded =
        sig_pow, sample_freq, val = transH.RefTester(V, P, V.x1ColBe, 1)
        sig2_pow, sample_freq, val2 = transH.RefTester(V, P, V.x1ColAf, 1)

        #breakpoint()
        reflectCo = val2 / val
        #plt.plot(sample_freq,sig_fft)

        # plt.plot(sample_freq,abs(sig_fft2))
        #breakpoint()
        #reflectCo = transH.ReflectionCalc(P, V, sample_freq, sig_pow, sig2_pow)

        return reflectCo

    elif AnalRefCo == True:
        analReflectCo = BaseFDTD11.AnalyticalReflectionE(V, P)
        return analReflectCo
    return "results ran to end"
Esempio n. 6
0
def IntegratorLinLor1D(V, P, C_V, C_P, probeReadFinishBe, probeReadStartAf):
    for i in range(0, 2):

        V.tempVarPol, V.tempTempVarE, V.tempVarE, V.tempTempVarPol, V.polarisationCurr, V.Ex, V.Dx, V.Hy = BaseFDTD11.FieldInit(
            V, P)

        V.UpHyMat, V.UpExMat = BaseFDTD11.EmptySpaceCalc(V, P)
        # move these into bc manager, call bc manager from here
        C_V = BaseFDTD11.CPML_FieldInit(V, P, C_V, C_P)
        C_V = boundCondManager(V, P, C_V, C_P)

        lamCont, lamDisc, diff, V.plasmaFreqE, fix = gStab.spatialStab(
            P.timeSteps, P.Nz, P.dz, P.freq_in, P.delT, V.plasmaFreqE,
            V.omega_0E, V.gammaE)
        Exs, Hys = SourceManager(V, P, C_V, C_P)
        tauIn = 1 / (P.freq_in / 5)
        #Exs = Sig_Mod(V,P, Exs,tau =tauIn)
        # Hys = Sig_Mod(V,P, Hys, AmpMod = 1/P.CharImp, tau = tauIn)
        #gStab.vonNeumannAnalysis(V,P,C_V,C_P)
        V.test = 0

        for counts in range(0, P.timeSteps):

            if i == 1:
                V.tempTempVarPol, V.tempVarPol, V.tempVarE, V.tempTempVarE, V.tempTempVarHy, V.tempVarHy, V.tempTempVarJx, V.tempVarJx, C_V.tempTempVarPsiEx, C_V.tempVarPsiEx, C_V.tempTempVarPsiHy, C_V.tempVarPsiHy = BaseFDTD11.ADE_TempPolCurr(
                    V, P, C_V, C_P)
                V.polarisationCurr = BaseFDTD11.ADE_PolarisationCurrent_Ex(
                    V, P, C_V, C_P, counts)

            V.Ex = BaseFDTD11.ADE_ExUpdate(V, P, C_V, C_P, counts)
            # V.Jx = BaseFDTD11.ADE_JxUpdate(V,P, C_V, C_P)

            if P.CPMLXp == True or P.CPMLXm == True:  # Go into cpml field updates to choose x+ and x-
                C_V.psi_Ex, V.Ex = BaseFDTD11.CPML_Psi_e_Update(V, P, C_V, C_P)

            V.Ex[P.nzsrc] += Exs[counts] / P.courantNo

            if P.TFSF == True:
                V.Hy[P.nzsrc - 1] -= Hys[counts] / P.courantNo

            V.Dx = BaseFDTD11.ADE_DxUpdate(V, P, C_V, C_P)
            V.Ex = BaseFDTD11.ADE_ExCreate(V, P, C_V, C_P)
            V.Hy = BaseFDTD11.ADE_HyUpdate(V, P, C_V, C_P)
            if P.CPMLXp == True or P.CPMLXm == True:
                C_V.psi_Hy, V.Hy = BaseFDTD11.CPML_Psi_m_Update(V, P, C_V, C_P)

            #V.Ex = BaseFDTD11.MUR1DEx(V, P, C_V, C_P)

            #C_V.psi_Ex, V.Ex  = BaseFDTD11.CPML_Psi_e_Update(V,P, C_V, C_P)
            # V.Ex = BaseFDTD11.MUR1DEx(V, P, C_V, C_P)
            """
           Re write probes to not require Ex_History.
           Re write History to be optional and be taken in interval steps
           Re write probes into a different function 
           Create transmission probes and attenuation probes. 
           
           Spatial dispersion plot alongside looping parameters
           Function which plots epsilon, mu, refractive index etc with loop
           Rigorous reflection and transmission probe timings.
           Beer's law vs attenuation plot 
           
           clean up redundant code, split big functions into smaller ones,
           split scripts into multiple scripts. 
           
           Prepare for nonlinear ade (Harmonics, then resonance tuning
           Manley-Rowe verification, resonance tuning verification?)
           Prepare for 2D, (Extra update fields, plots, dispersion checks, 
           2D checks angles stuff, geometry designer)
           Simple charged particle distribution evolution. 25th Jan?
           
           
           should free space pre-reflection be running Dx? Maybe just call 
           free space integrator once?
           
           """
            if counts > 0:  # MOVE TO FUNCTION
                if counts % P.vidInterval == 0:
                    if i == 1:
                        V.Ex_History = vidMake(V,
                                               P,
                                               C_V,
                                               C_P,
                                               counts,
                                               V.Ex,
                                               whichField="Ex")

            # option to not store history, and even when storing, only store in
            #intervals

            if i == 0:
                if counts <= P.timeSteps - 1:
                    if counts <= probeReadFinishBe:
                        V.x1ColBe = probeSim(V, P, C_V, C_P, counts,
                                             V.Ex[P.x1Loc])
                    #change this from Ex history
            elif i == 1:
                if counts <= P.timeSteps - 1:
                    if counts >= probeReadStartAf:
                        V.x1ColAf = probeSim(V,
                                             P,
                                             C_V,
                                             C_P,
                                             counts,
                                             V.Ex[P.x2Loc],
                                             af=True)
                        if P.atten == True:
                            V.x1Atten = probeSim(V,
                                                 P,
                                                 C_V,
                                                 C_P,
                                                 counts,
                                                 V.Ex[P.x2Loc],
                                                 attenRead=True)
    return V.Ex, V.Hy, Exs, Hys, C_V.psi_Ex, C_V.psi_Hy, V.x1ColBe, V.x1ColAf
Esempio n. 7
0
def IntegratorFreeSpace1D(V, P, C_V, C_P, probeReadFinishBe, probeReadStartAf):
    for i in range(0, 2):
        V.tempVarPol, V.tempTempVarE, V.tempVarE, V.tempTempVarPol, V.polarisationCurr, V.Ex, V.Dx, V.Hy = BaseFDTD11.FieldInit(
            V, P)
        #analReflectCo, dispPhaseVel, realV = BaseFDTD11.AnalyticalReflectionE(V,P)

        V.UpHyMat, V.UpExMat = BaseFDTD11.EmptySpaceCalc(V, P)

        V.epsilon, V.mu, V.UpExHcompsCo, V.UpExSelf, V.UpHyEcompsCo, V.UpHySelf = BaseFDTD11.Material(
            V, P)
        V.UpHyMat, V.UpExMat = BaseFDTD11.UpdateCoef(V, P)
        # move these into bc manager, call bc manager from here
        C_V = BaseFDTD11.CPML_FieldInit(V, P, C_V, C_P)
        C_V = boundCondManager(V, P, C_V, C_P)

        # PROBABLY BETTER TO RUN THIS IN LINEAR DISP INTEGRATOR
        #lamCont, lamDisc, diff, V.plasmaFreqE, fix = gStab.spatialStab(P.timeSteps,P.Nz,P.dz, P.freq_in, P.delT, V.plasmaFreqE, V.omega_0E, V.gammaE)
        Exs, Hys = SourceManager(V, P, C_V, C_P)
        tauIn = 1 / (P.freq_in / 5)
        Exs = Sig_Mod(V, P, Exs, tau=tauIn)
        Hys = Sig_Mod(V, P, Hys, AmpMod=1 / P.CharImp, tau=tauIn)

        #gStab.vonNeumannAnalysis(V,P,C_V,C_P)

        if P.julia:
            V, P, C_V, C_P = JH.Jul_Integrator_Prep(V, P, C_V, C_P, Exs, Hys,
                                                    i)
        else:
            for counts in range(0, P.timeSteps):

                #if counts%(int(P.timeSteps/10)) == 0:
                #   print("timestep progress:", counts, "/", P.timeSteps)
                V.Ex = BaseFDTD11.ADE_ExUpdate(V, P, C_V, C_P, counts)
                if P.CPMLXp or P.CPMLXm:  # Go into cpml field updates to choose x+ and x-
                    C_V.psi_Ex, V.Ex = BaseFDTD11.CPML_Psi_e_Update(
                        V, P, C_V, C_P)

                ## SOURCE MANAGER COMES IN HERE

                V.Ex[P.nzsrc] += Exs[counts] / P.courantNo
                if P.TFSF == True:
                    V.Hy[P.nzsrc - 1] -= Hys[counts] / P.courantNo
                ####
                V.Hy = BaseFDTD11.ADE_HyUpdate(V, P, C_V, C_P)
                if P.CPMLXp or P.CPMLXm:
                    C_V.psi_Hy, V.Hy = BaseFDTD11.CPML_Psi_m_Update(
                        V, P, C_V, C_P)

                ##################
            # V.tempTempVarPol, V.tempVarPol, V.tempVarE, V.tempTempVarE, V.tempTempVarHy, V.tempVarHy, V.tempTempVarJx, V.tempVarJx, C_V.tempTempVarPsiEx, C_V.tempVarPsiEx, C_V.tempTempVarPsiHy, C_V.tempVarPsiHy = BaseFDTD11.ADE_TempPolCurr(V,P, C_V, C_P)
            #V.Ex = BaseFDTD11.MUR1DEx(V, P, C_V, C_P)

            #########################

                if counts > 0:
                    if counts % P.vidInterval == 0:
                        if i == 1:
                            V.Ex_History = vidMake(V,
                                                   P,
                                                   C_V,
                                                   C_P,
                                                   counts,
                                                   V.Ex,
                                                   whichField="Ex")

                # option to not store history, and even when storing, only store in
                #intervals

                if i == 0:
                    if counts <= P.timeSteps - 1:
                        if counts <= probeReadFinishBe:
                            V.x1ColBe = probeSim(V, P, C_V, C_P, counts,
                                                 V.Ex[P.x1Loc])
                        #change this from Ex history
                elif i == 1:
                    if counts <= P.timeSteps - 1:
                        if counts >= probeReadStartAf:
                            V.x1ColAf = probeSim(V,
                                                 P,
                                                 C_V,
                                                 C_P,
                                                 counts,
                                                 V.Ex[P.x2Loc],
                                                 af=True)
                            if P.atten == True:
                                V.x1Atten = probeSim(V,
                                                     P,
                                                     C_V,
                                                     C_P,
                                                     counts,
                                                     V.Ex[P.x2Loc],
                                                     attenRead=True)

            #FDdata, FDXaxis, FDdataPow = gft(V,P, C_V, C_P, V.x1ColBe)   # freq dom stuff for reflection

    return V.Ex, V.Hy, Exs, Hys, C_V.psi_Ex, C_V.psi_Hy, V.x1ColBe, V.x1ColAf  #Do I need to return C_V?
Esempio n. 8
0
def solnDenecker(R,
                 F,
                 A,
                 UnP1A,
                 UnP1B,
                 Xn,
                 V,
                 P,
                 C_V,
                 C_P,
                 Kop,
                 Kopt,
                 De,
                 Dh,
                 pulseInit=True):
    checkLine = "inspect.currentframe().f_back.f_lineno"  # I use this in an eval expression to write the current code line into a
    #console print out when debugging

    delayMOR = P.delayMOR
    Exs, Hys = BF.SmoothTurnOn(V, P)

    # breakpoint()
    print("MOR Time stepping...")
    if R.shape != (2 * P.Nz + 2, 2 * P.Nz + 2):
        print("R is wrong shape")
        sys.exit()
    if F.shape != (2 * P.Nz + 2, 2 * P.Nz + 2):
        print("F is wrong shape")
        sys.exit()  #

    XnP1 = np.zeros(2 * P.Nz + 2)
    k = int(len(Xn) * 0.5)
    XnP1_red = np.zeros(k)

    XnP1 = XnP1.reshape(len(XnP1), 1)
    XnP1_red = XnP1_red.reshape(len(XnP1_red), 1)
    ratio = len(XnP1) / k

    #Q, H, k, Xn_red, XnP1_red, Q_sp = MORViaSPRIM(Xn, XnP1, 2*P.Nz+2,R, k, F, P, V, C_V, C_P)
    summer = (R + F)
    winter = (R - F)
    tic = time.perf_counter()
    summerInv = luInvert(summer)
    toc = time.perf_counter()
    ### CONDITION NUMBER EFFECTS ACCURACY OF INVERSION!
    print("LUinvert time: ", toc - tic)
    print("conditions numbers of summer, winter: ",
          np.linalg.cond(summer.todense()), np.linalg.cond(winter.todense()))

    #summer = vonNeumannAnalysisMOR(V, P, C_V, C_P, summer, "summer")
    #winter = vonNeumannAnalysisMOR(V, P, C_V, C_P, winter, "winter")

    #summer = sparse.csc_matrix(summer)
    if (sparse.issparse(winter)):
        winter = winter.todense()
    winter = np.asmatrix(winter)

    B = BGenerator(P)
    B = sparse.csc_matrix(B)

    In = np.identity(len(winter))
    M = In
    M = sparse.csc_matrix(M)
    M2 = In
    M2 = sparse.csc_matrix(M2)

    s0 = 2 * np.pi * P.freq_in

    M = luInvert(s0 * In - summerInv @ winter, "M")
    #M2 = luInvert((s0*In -winter).conj().T, "M2")
    if sparse.issparse(M):
        M = M.todense()
    #M = np.asarray(M, dtype = np.complex128)
    #M2 = M2.todense()
    #M2 = np.asarray(M2, dtype = np.complex128)
    """
    for jj in range(int(P.freq_in),int(P.freq_in)):
        s0 = 2*np.pi*jj
        M2= M2@(luInvert((s0*In).conj().T-winter.conj().T))
    
    M2 = M2.todense()
    M2 = np.asarray(M2, dtype = np.float64)
    """
    v0 = np.random.randint(5, size=(len(winter), k))  #*(1+1j)
    # v0 = v0.astype(np.complex128)
    v2 = np.random.randint(5, size=(len(winter), k))  #*(1+1j)
    # v2 = v2.astype(np.complex128)
    v0, RR = np.linalg.qr(
        v0)  # if matix is complex returns unitary, normalise it...
    #v0 = v0/np.linalg.norm(v0)
    print(type(v0))
    #print(type(v2))
    #v2, R2 = np.linalg.qr(v2)
    #v2 = v2/np.linalg.norm(v2)
    # v0 = M@v0   # ?
    #v2 = M2@v2
    # EAVars = EA(k, len(v0))
    #breakpoint()
    print("Starting Arnoldi process................")
    tic = time.perf_counter()
    V_sp, RR = ExampleArnoldi(M, v0, k)
    #breakpoint()
    #V_sp, RR = np.linalg.qr(V_sp)
    orth = V_sp.T.conj() @ V_sp
    check = np.allclose(orth, np.identity(len(orth)), atol=1e-2)
    print(check, " = orthornormal check.")

    if check == False:

        print("first ten diagonal terms of orth:", np.diag(orth)[:10])
        print(np.linalg.norm(V_sp), " norm of V_sp")

    #V_sp, R = np.linalg.qr(V_sp)
    #V_sp = V_sp/np.linalg.norm(V_sp)

    print(np.linalg.matrix_rank(V_sp, tol=1e-4), "/", V_sp.shape[1],
          "MATRIX RANK ")

    #V_sp = np.block([np.real(V_sp[:int(len(V_sp)/2)]), np.imag(V_sp[int(len(V_sp)/2):])])
    toc = time.perf_counter()
    print("FINISHED ARNOLDI in: ", toc - tic)
    V_sp_UL = V_sp[:int(len(V_sp) / 2), :k]
    V_sp_UR = np.zeros((int(len(V_sp) / 2), k))
    V_sp_LL = np.zeros((int(len(V_sp) / 2), k))
    V_sp_LR = V_sp[int(len(V_sp) / 2):, :k]
    V_sp = np.block([[V_sp_UL, V_sp_UR], [V_sp_LL, V_sp_LR]])

    if V_sp_UL.shape != V_sp_UR.shape or V_sp_LL.shape != V_sp_LR.shape or V_sp_LL.shape != V_sp_UR.shape:
        print("shapes of blocks for SPRIM partition not the same: ",
              V_sp_UL.shape, V_sp_UR.shape, V_sp_LL.shape, V_sp_LR.shape)
        sys.exit()
    #
    """
    bob = V_sp.T@summer@V_sp
    bob2 = V_sp@bob@V_sp.T
    avgDiag = np.average(np.diag(bob2))
    for i in range(bob2.shape[0]):
        for j in range(bob2.shape[1]):
            if abs(bob2[i,j]) <= abs(avgDiag)/5:
                bob2[i,j] = 0
                
    factor = np.average(np.diag(summer.todense()) /np.average(np.diag(bob2)))  
    bob2 = bob2*factor
    bob3 = np.real(bob2)
  #  breakpoint()
    
    
    V_sp = np.hstack((np.real(V_sp), np.imag(V_sp)))
   # modify = 1/V_sp[0,0]
    print("V_sp: ", V_sp[:4,:4])
   # V_sp*= modify
    #W_sp = np.hstack((np.real(W_sp), np.imag(W_sp)))
    
    V_sp_UL = V_sp[:int(len(V_sp)/2),:k]
    V_sp_UR = np.zeros((int(len(V_sp)/2), k))
    V_sp_LL = np.zeros((int(len(V_sp)/2), k))
    V_sp_LR = V_sp[int(len(V_sp)/2):,:k]
    V_sp = np.block([[V_sp_UL, V_sp_UR],[V_sp_LL, V_sp_LR]])
    
    if V_sp_UL.shape !=V_sp_UR.shape or V_sp_LL.shape != V_sp_LR.shape or V_sp_LL.shape != V_sp_UR .shape:
        print("shapes of blocks for SPRIM partition not the same: ", V_sp_UL.shape, V_sp_UR.shape, V_sp_LL.shape, V_sp_LR.shape)
        sys.exit()
    if V_sp.shape[0] != P.Nz+2:
        print(V_sp.shape, " V_sp shape", P.Nz, " P.Nz")
   
    #check structure preservation
    
    # take top half of V_sp and W_sp
    print("Dimensions of V_sp should match Xn, Shape V vs Xn: ", V_sp.shape, Xn.shape)
    #breakpoint()
    #SPRIM PARTITION:
    #V_sp = 
    
   # breakpoint()
    #V_sp, R = np.linalg.qr(V_sp)#

   # print("Performing Orthonormal tests")
   # check = np.allclose(V_sp.T @ V_sp, np.eye(V_sp.shape[1]), rtol =1e-1)
   # print(" ortho check: ", check)
    """
    V_spt = V_sp.T
    # breakpoint()

    # M = sparse.csc_matrix(M)
    #A_red = M#Q_spt@M@Q_sp

    #winter_red = V_sp.T@winter@V_sp
    #summer_red = V_sp.T@summer@V_sp
    #print("condition numbers before preconditioning: ", np.linalg.cond(summer_red), np.linalg.cond(winter_red))
    Vnorm = np.linalg.norm(V_sp)
    V_sp, rrr = np.linalg.qr(V_sp)
    V_sp *= Vnorm
    R_red = V_sp.T @ R @ V_sp
    F_red = V_sp.T @ F @ V_sp
    Kop_red_R = R_red[:int(len(R_red) / 2), int(len(R_red) / 2):]
    De_red_R = R_red[:int(len(R_red) / 2), :int(len(R_red) / 2)]
    Dh_red_R = R_red[int(len(R_red) / 2):,
                     int(len(R_red) / 2):]  #V_sp_LR.T@Dh@V_sp_LR

    Kop_red_pert = singularVDPertPreExpan(P, De_red_R, Dh_red_R, Kop_red_R)
    R_red[len(Kop_red_R):, :len(Kop_red_R)] = Kop_red_pert.T
    R_red[:len(Kop_red_R), len(Kop_red_R):] = Kop_red_pert
    #  R_red[]
    # structure preservation preserves algebraic operations?

    XnP1_red = V_sp.T @ XnP1
    winter_red = R_red - F_red
    summer_red = R_red + F_red
    summerJac = np.linalg.pinv(np.diag(np.diag(summer_red)))
    print("shape winter: ", winter.shape)
    #sumJac = np.linalg.inv(np.diag(np.diag(summer_red)))
    ## summer_red is badly conditioned?
    #winter_red = V_spt@winter@V_sp
    #summer_red = V_spt@summer@V_sp
    #A_red = sparse.csc_matrix(A_red)
    #if (sparse.issparse(A_red)):
    #  A_red = A_red.todense()
    #print("Eigenvalue decomp...")
    #breakpoint()
    #winter_red= np.real(eigenvalueDecomp(winter_red))
    #summer_red  =np.real(eigenvalueDecomp(summer_red))

    #AA, BB, CC, DD= eigenvalueDecomp(summer_red)
    # Inv AA @ summer_red should give I?
    #summer_red = AA@summer_red
    #AA, BB, CC, DD= eigenvalueDecomp(winter_red)
    #winter_red = AA@winter_red
    #check shapes of projection matrices
    #print("condition numbers reduced after preconditioning: ", np.linalg.cond(sumJac@summer_red), np.linalg.cond(winter_red))
    #print("V_spt shape: ", V_spt.shape)
    # breakpoint()
    wl = len(winter_red)
    winter_red = sparse.csc_matrix(winter_red)
    #  summer_red_inv = luInvert(summer_red, "summer_red")
    # summer_red_inv_spar = sparse.csc_matrix(summer_red_inv)
    summer_red_sparse = sparse.csc_matrix(summerJac @ summer_red)
    # comboBreaker = summer_red_inv_spar@winter_red
    ## H, HeigValsDiag, HeigVecsInv, HeigVecs = eigenvalueDecomp(comboBreaker)
    # summer_inv_Full = luInvert(summer)
    #comboBreakerFull =summer_inv_Full@winter
    #HF, HeigValsDiagF, HeigVecsInvF, HeigVecsF = eigenvalueDecomp(comboBreakerFull)

    # A_red = summer_red_inv@winter_red
    # summer_red = sparse.csc_matrix(summer_red)
    #B_a_red = Q_spt@inv@Q_sp
    interval = int(P.timeSteps / 10)  #

    # sos = sig.butter(21, 0.01, output='sos')
    Spla = sparse.linalg.spilu(summer_red)
    lam = lambda x: Spla.solve(x)
    if sparse.issparse(summer_red):
        summer_red = summer_red.todense()

    MM = sparse.linalg.LinearOperator(summer_red.shape, lam)
    for jj in range(0, P.timeSteps):
        if jj % interval == 0:
            print("Timestepping, step number: ", jj, "/ ", P.timeSteps)

    # y = y.reshape(len(y),1)
    #XnP1 = sparse.linalg.spsolve((R+F), y)

    #XnP1 = sparse.csc_matrix(XnP1)
        UnP1A, UnP1B = SourceVector(V, P, C_V, C_P)

        #if B.shape != (2*P.Nz+2, 2*P.Nz+2):
        #    print("B is wrong shape")
        # sys.exit()

        # UnP1A[:] =  ((Hys[jj])/P.courantNo)*P.CharImp
        UnP1B[:] = ((Exs[jj]) / P.courantNo)
        UnP1 = np.block([UnP1A, UnP1B])

        UnP1 = UnP1.reshape(len(UnP1), 1)
        UnP1_red = V_sp.T @ UnP1  #Q_spt@UnP1
        UnP1_red = UnP1_red.reshape(len(UnP1_red), 1)
        # UnP1_red = sparse.csr_matrix(UnP1_red)
        #B = sparse.csr_matrix(B) #move out of bandsourvect
        print(B.shape)
        # breakpoint()
        B_red = V_sp.T @ B @ V_sp
        B_red = sparse.csc_matrix(B_red)
        In_red = np.identity(wl)
        In_red_sp = sparse.csc_matrix(In_red)
        if (pulseInit == False) or (pulseInit == True and jj >= delayMOR):

            #breakpoint()
            #print("shape of B_red: ", B_red.shape)

            # breakpoint()
            XnP1_red = XnP1_red.reshape(len(XnP1_red), 1)
            XnP1_red = sparse.csc_matrix(XnP1_red)
            #XnP1_red = summer_red_inv_spar@(winter_red@XnP1_red +B_red@UnP1_red)
            #breakpoint()
            y1 = winter_red @ XnP1_red + B_red @ UnP1_red
            #y1Full = V_spt@y1*100

            #print(np.average(np.abs(y1)), " y1")
            # print("y shape if first before solve: " ,y.shape)
            #XnP1 = A@XnP1 + B@UnP1
            #breakpoint()
            y1 = sparse.csr_matrix(y1)
            # breakpoint()
            # XnP1_red = summer_red_inv@y1

            #breakpoint()

            # print("shapes of y1, summer_red: ", y1.shape, summer_red.shape)

            XnP1_red, info = sparse.linalg.gmres(summer_red,
                                                 y1.todense(),
                                                 x0=XnP1_red.todense(),
                                                 atol=1e-4,
                                                 M=MM,
                                                 maxiter=250)
            if info != 0:
                print("iterations: ", info)
            #fig, ax = plt.subplots()

            XnP1 = (V_sp @ XnP1_red)

            #breakpoint()
            # XnP1 = sig.sosfiltfilt(sos, smooth(np.asarray([XnP1]).ravel(),1000, window = 'flat'))

            # print("Avg, min, max: ", np.average(np.abs(XnP1)), np.min(np.abs(XnP1)), np.max(np.abs(XnP1)))   # np.min should return zero especially early on
            # print("SUM OFFFFFFFF: ", np.sum(XnP1))
            checkNan(XnP1, eval(checkLine), jj)
            if (np.max(np.abs(XnP1)) * ratio <= 1e-8) and jj >= 30:
                print(np.average(np.abs(XnP1)), " Average val of XnP1",
                      eval(checkLine))
                sys.exit()
            if (np.average(np.abs(XnP1)) >= 1e2):
                print(np.average(np.abs(XnP1)), " Average val of XnP1",
                      eval(checkLine))
                plt.plot(XnP1)
                sys.exit()
            #print("first if")
            # check dimensions v_sp etc

            if jj % 25 == 0:
                print("Iteration of timeStep in MOR: ", jj, "/ ", P.timeSteps)

            #XnP1 = (V_sp@XnP1_red)
            #XnP1 = sig.sosfiltfilt(sos, smooth(np.asarray([XnP1]).ravel(),50, window = 'flat'))
            #XnP1 = XnP1*ratio**2
            XnP1 = XnP1.reshape(len(XnP1), 1)

            XnP1_fin = np.real(XnP1)

        # breakpoint()

        elif pulseInit == True and jj < delayMOR:

            print("FOM pulse init stage: ", jj)
            XnP1 = sparse.csc_matrix(XnP1)
            y = winter @ XnP1 + B @ UnP1
            # XnP1 = HeigValsDiagF@XnP1 +  HeigVecsInvF@summer_inv_Full@B@UnP1
            #breakpoint()
            if sparse.issparse(y):
                y = y.todense()
            #XnP1 = A@XnP1 + B@UnP1
            #breakpoint()
            #y = sparse.csc_matrix(y)
            #print("y ", np.average(np.abs(y.todense())))
        # print("second elif")
        #XnP1 = sparse.linalg.spsolve(summer, y)
            Spla1 = sparse.linalg.spilu(sparse.csc_matrix(summer))
            lam1 = lambda x: Spla1.solve(x)
            if sparse.issparse(summer):
                summer = summer.todense()
            MM1 = sparse.linalg.LinearOperator(summer.shape, lam1)
            # print("shapes of y1, summer_red: ", y1.shape, summer_red.shape)

            XnP1, info = sparse.linalg.lgmres(summer,
                                              y,
                                              x0=XnP1.todense(),
                                              atol=1e-4,
                                              M=MM1,
                                              maxiter=50)
            if info != 0:
                print("iterations: ", info)
            checkNan(XnP1, eval(checkLine), jj)
            #print("Avg, min, max: ", np.average(np.abs(XnP1)), np.min(np.abs(XnP1)), np.max(np.abs(XnP1)))
            XnP1_red = V_sp.T @ XnP1
            #print("Avg, max XnP1_red: ", np.average(np.abs(XnP1_red)), np.max(abs(XnP1_red)))
            # print("SUM OF XnP1 FOM: ", np.sum(XnP1))
            #XnP1 = HeigVecsF@XnP1
            # XnP1 = sig.sosfiltfilt(sos, smooth(np.asarray([XnP1]).ravel(),1000, window = 'flat'))
            XnP1 = XnP1.reshape(len(XnP1), 1)
            if (np.average(np.abs(XnP1)) >= 1e2):
                print(np.average(np.abs(XnP1)), " Average val of XnP1",
                      eval(checkLine))
                plt.plot(XnP1)
                sys.exit()
            XnP1_fin = np.real(XnP1)

        #  Add in float var to move np.real XnP1 to prevent stdout discarding imag

        for ii in range(len(V.Ex) - 1):
            if sparse.issparse(XnP1):
                XnP1_fin = XnP1_fin.todense()
            # maybe don't discard imaginary part, use just real part for vid
            #breakpoint()
            V.Ex[ii] = XnP1_fin[ii][0] * ratio

            V.Hy[ii] = XnP1_fin[ii + len(V.Ex)][0]
        V.Ex_History[jj] = V.Ex

    return V.Ex, V.Ex_History, V.Hy, UnP1