Exemple #1
0
def Curl_uD_components(u,v,D_,T,dx,dy):
	"A function that calculates the time-mean curl of uD"

	uD = timeAverage(u * D_, T, len(T)-1)
	vD = timeAverage(v * D_, T, len(T)-1)

	return diff(vD,1,1,dx), -diff(uD,0,0,dy)	
Exemple #2
0
def footprint(u_full, v, q_full, x, y, dx, dy, T, Nt):
    # This code calculates the PV footprint, i.e. the PV flux convergence defined by
    # P = -(div(u*q,v*q)-div((u*q)_av,(v*q)_av)), where _av denotees the time average.
    # We will take the time average over one whole forcing period, and subtract this PV flux
    # convergence from the PV flux convergence at the end of one period.
    # To calculate footprints, we use the full PV and velocity profiles.

    uq = q_full * u_full
    # Zonal PV flux
    vq = q_full * v
    # Meridional PV flux

    # Next step: taking appropriate derivatives of the fluxes. To save space, we won't define new variables, but instead overwrite the old ones.
    # From these derivatives we can calculate the

    # Time-averaging
    uq = timeAverage(uq, T, Nt)
    vq = timeAverage(vq, T, Nt)

    # Calculate the footprint.
    P = -diff(uq, 1, 1, dx) - diff(vq, 0, 0, dy)

    P = extend(P)

    # We are interested in the zonal average of the footprint
    P_xav = np.trapz(P, x, dx, axis=1)
    # / 1 not required.

    return P, P_xav
Exemple #3
0
def footprint(uq,Uq,uQ,UQ,vq,vQ,x_nd,T_nd,dx_nd,dy_nd,N,Nt):
	'''
	This code calculates the PV footprint, i.e. the PV flux convergence defined by
	P = -(div(u*q,v*q)), where _av denotees the time average.
	We will take the time average over one whole forcing period, and subtract this PV flux
	convergence from the PV flux convergence at the end of one period.
	To calculate footprints, we use the full PV and velocity profiles.
	'''
		
	uq_full = uq + Uq + uQ		# Total zonal PV flux
	#for j in range(0,N):
		#qu_full[:,j,:] = qu_full[:,j,:] + UQ[j];
	vq_full = vq + vQ			# Total meridional PV flux	
	
	# Time-averaging
	uq_full = timeAverage(uq_full,T_nd,Nt)
	vq_full = timeAverage(vq_full,T_nd,Nt)

	# Calculate the footprint.
	P = - diff(uq_full,1,1,dx_nd) - diff(vq_full,0,0,dy_nd)

	P = extend(P)
		
	# We are interested in the zonal average of the footprint
	P_xav = np.trapz(P,x_nd,dx_nd,axis=1) # / 1 not required.

	return P, P_xav
Exemple #4
0
def potentialVorticity_linear(u,v,h,H0_nd,U0_nd,N,Nt,dx_nd,dy_nd,f_nd,Ro):
	'''
	Calculate linear potential vorticity.
	Return three components of linear PV anomaly.
	'''

	RV_prime1 = np.zeros((N,N,Nt));
	RV_prime2 = np.zeros((N,N,Nt));
	for ti in range(0,Nt):
		RV_prime1[:,:,ti] = diff(v[:,:,ti],1,1,dx_nd);
		RV_prime2[:,:,ti] = - diff(u[:,:,ti],0,0,dy_nd);
	RV_BG = - diff(U0_nd,2,0,dy_nd);

	PV_BG = np.zeros(N);
	for j in range(0,N):
		PV_BG[j] = (RV_BG[j] + f_nd[j] / Ro) / H0_nd[j];

	PV_prime1 = np.zeros((N,N,Nt));
	PV_prime2 = np.zeros((N,N,Nt));
	PV_prime3 = np.zeros((N,N,Nt));
	for i in range(0,N):
		for ti in range(0,Nt):
			PV_prime1[:,i,ti] = RV_prime1[:,i,ti] / H0_nd[:];
			PV_prime2[:,i,ti] = RV_prime2[:,i,ti] / H0_nd[:];
			PV_prime3[:,i,ti] = - PV_BG[:] * h[:,i,ti] / H0_nd[:];

	return PV_prime1, PV_prime2, PV_prime3
Exemple #5
0
def potentialVorticity(u,v,h,u_full,h_full,H0_nd,U0_nd,N,Nt,dx_nd,dy_nd,f_nd,Ro):
	'''
	Calculate potential vorticity	
	'''

	RV_full = np.zeros((N,N,Nt));
	RV_prime = np.zeros((N,N,Nt));
	for ti in range(0,Nt):
		# Define the relative vorticities (RV_full=RV_BG+RV_prime, can always check this numerically)
		RV_full[:,:,ti] = diff(v[:,:,ti],1,1,dx_nd) - diff(u_full[:,:,ti],0,0,dy_nd);
	RV_prime[:,:,ti] = diff(v[:,:,ti],1,1,dx_nd) - diff(u[:,:,ti],0,0,dy_nd);
	RV_BG = - diff(U0_nd,2,0,dy_nd);	# This is defined outside the loop as it has no time-dependence.

	PV_full = np.zeros((N,N,Nt));
	PV_BG = np.zeros(N);
	for j in range(0,N):
		PV_BG[j] = (RV_BG[j] + f_nd[j] / Ro) / H0_nd[j];
		for i in range(0,N):
			for ti in range(0,Nt):
				PV_full[j,i,ti] = (RV_full[j,i,ti] + f_nd[j] / Ro) / h_full[j,i,ti];
		
	# Two options to define the PV induced in the forced system: (1) PV_full-PV_BG or (2) use the algebraic def. given in the report.
	PV_prime = np.zeros((N,N,Nt));	
	for j in range(1,N-1):
		for i in range(0,N):
			for ti in range(0,Nt):
				PV_prime[j,i,ti] = PV_full[j,i,ti] - PV_BG[j];		# Option 1
	#PV_prime = np.zeros((N,N,Nt));	# Option 2 - keep this commented out, just use it as a check.
	#for j in range(0,N):
	#	for i in range(0,N):
	#		for ti in range(0,Nt):
	#			PV_prime[j,i,ti] = (RV_full[j,i,ti] - f[j]) / (h_full[j,i,ti]) - (f[j] - RV_BG[j]) / (H0_nd[j]);

	return PV_prime, PV_full, PV_BG
Exemple #6
0
def D(u,v,Nt,dx,dy):
	"A function that calculates the horizontal divergence"

	D = np.zeros(np.shape(u))
	for ti in range(0,Nt):
		D[:,:,ti] = diff(u[:,:,ti],1,1,dx) + diff(v[:,:,ti],0,0,dy)

	return D
Exemple #7
0
def SOLVER_COEFFICIENTS(Ro, Re, K_nd, f_nd, U1_nd, U2_nd, H1_nd, H2_nd,
                        rho1_nd, rho2_nd, omega_nd, gamma_nd, dy_nd, N):
    # Here we also divide coeficients of derivatives by the relevant space-step:
    # 2*dy_nd for first-order derivatives, dy_nd**2 for second-order derivatives.
    # Note: to speed up the algorithm, some coefficients aren't unnecessarily defined as they have a duplicate featuring in another equation.

    I = np.complex(0, 1)

    # 1 - Define all k- and y-dependent coefficients
    delta1 = np.zeros((N, N))
    delta2 = np.zeros((N, N))
    a1 = np.zeros((N, N), dtype=complex)
    c1 = np.zeros((N, N), dtype=complex)
    c4 = np.zeros((N, N), dtype=complex)
    c5 = np.zeros((N, N), dtype=complex)
    d1 = np.zeros((N, N), dtype=complex)
    f1 = np.zeros((N, N), dtype=complex)
    f4 = np.zeros((N, N), dtype=complex)
    for j in range(0, N):
        for i in range(0, N):
            delta1[j, i] = 2. * np.pi * (omega_nd + U1_nd[j] * K_nd[i])
            delta2[j, i] = 2. * np.pi * (omega_nd + U2_nd[j] * K_nd[i])
            a1[j,
               i] = I * delta1[j, i] * Ro + 4 * np.pi**2 * K_nd[i]**2 * Ro / Re
            c1[j, i] = 2. * np.pi * I * H1_nd[j] * K_nd[i]
            c4[j, i] = I * delta1[j, i]
            c5[j, i] = -I * delta1[j, i]
            d1[j, i] = I * delta2[
                j, i] * Ro + 4 * np.pi**2 * K_nd[i]**2 * Ro / Re + gamma_nd
            f1[j, i] = 2. * np.pi * I * K_nd[i] * H2_nd[j]
            f4[j, i] = I * delta2[j, i]

    # 2 - Define all y-dependent coefficients
    a3 = Ro * diff(U1_nd, 2, 0, dy_nd) - f_nd
    b1 = f_nd
    d3 = Ro * diff(U2_nd, 2, 0, dy_nd) - f_nd
    f2 = diff(H2_nd, 2, 0, dy_nd)
    f3 = H2_nd / (2 * dy_nd)

    # 3 - Define all k-dependent coefficients
    a4 = 2. * np.pi * I * K_nd
    d4 = 2. * np.pi * I * K_nd * rho1_nd
    d5 = 2. * np.pi * I * K_nd * rho2_nd

    # 4 - Define all constant coefficients
    a2 = -Ro / (Re * dy_nd**2)
    b4 = 1. / (2 * dy_nd)
    c2 = diff(H1_nd, 2, 0, dy_nd)
    c3 = H1_nd / (2 * dy_nd)
    e4 = rho1_nd / (2 * dy_nd)
    e5 = rho2_nd / (2 * dy_nd)

    # Summary of coefficients not explicitly defined for sake of algorithm speed:
    # b2 = a1, b3 = a2, d2 = a2, e1 = f_nd, e2 = d1, e3 = a2.

    return a1, a2, a3, a4, b1, b4, c1, c2, c3, c4, c5, d1, d3, d4, d5, e4, e5, f1, f2, f3, f4
Exemple #8
0
def SOLVER_COEFFICIENTS(Ro, Re, K_nd, f_nd, U0_nd, H0_nd, omega_nd, gamma_nd,
                        dy_nd, N):
    # Here we also divide coeficients of derivatives by the relevant space-step:
    # 2*dy_nd for first-order derivatives, dy_nd**2 for second-order derivatives.

    I = np.complex(0, 1)
    # Define I = sqrt(-1)

    if Re == None:
        Ro_Re = 0
    else:
        Ro_Re = Ro / Re

    # Coefficients with no k- or y-dependence
    a2 = -Ro_Re / (dy_nd**2)
    # Note: b3=a2, so instead of defining b3, we just use a2 in its place, saving time.
    b4 = 1. / (2. * dy_nd)

    # Coefficients with k-dependence only
    a4 = np.zeros(N, dtype=complex)
    for i in range(0, N):
        a4[i] = 2. * np.pi * I * K_nd[i]

    # Coefficients with y-dependence only

    a3 = Ro * diff(U0_nd, 2, 0, dy_nd) - f_nd
    # For uniform U0_nd, the first term is zero

    c2 = diff(H0_nd, 2, 0, dy_nd)
    # For zero BG flow, H0_nd=Hflat=const, i.e. c2=0

    c3 = H0_nd / (2. * dy_nd)

    # a3, c2 and c3 have length N, so when used in defining u and v equations in the matrix below,
    # we must add 1 to each index in order to skip out the dead gridpoint.

    # Note that b1=f_nd so will not be defined, but we use f_nd directly.

    # Coefficients dependent on k and y
    delta = np.zeros((N, N))
    # Appears in many of the coeffs, essentially a space-saver.
    a1 = np.zeros((N, N), dtype=complex)
    # Note: b2=a1
    c1 = np.zeros((N, N), dtype=complex)
    for i in range(0, N):
        for j in range(0, N):
            delta[j, i] = 2. * np.pi * (omega_nd + U0_nd[j] * K_nd[i])
            a1[j, i] = I * delta[
                j, i] * Ro + 4. * np.pi**2 * K_nd[i]**2 * Ro_Re + gamma_nd
            c1[j, i] = 2. * np.pi * I * K_nd[i] * H0_nd[j]

    c4 = I * delta

    return a1, a2, a3, a4, b4, c1, c2, c3, c4
Exemple #9
0
def F12_from_F3(F3_nd, f_nd, dx_nd, dy_nd, N, nx):
    # Finds F1 and F2 numerically from F3.

    F1_nd = np.zeros((N, nx), dtype=complex)
    F2_nd = np.zeros((N, nx), dtype=complex)
    for i in range(0, nx):
        F1_nd[:, i] = -diff(F3_nd[:, i], 2, 0, dy_nd) / f_nd[:]
    for j in range(0, N):
        F2_nd[j, :] = diff(F3_nd[j, :], 2, 0, dx_nd) / (f_nd[j])

    return F1_nd, F2_nd
Exemple #10
0
def conv(uE, vE, T_nd, Nt, x_nd, dx_nd, y_nd, dy_nd):
    '''Time-mean convergence of energy fluxes.'''

    uE_av = timeAverage(uE, T_nd, Nt)
    vE_av = timeAverage(vE, T_nd, Nt)

    Econv = -diff(uE_av, 1, 1, dx_nd) - diff(vE_av, 0, 0, dy_nd)
    Econv = extend(Econv)

    Econv_xav = np.trapz(Econv, x_nd, dx_nd, axis=1)  # / 1 not required.

    return Econv, Econv_xav
Exemple #11
0
def budgetDissipation2(U0, H0, u, v, h, Ro, Re, gamma, dx, dy, T, Nt, N):
    ''' Calculate time-dependent and time-mean energy budget due to dissipation.
	Make sure to use full u, v and h fields. Contribution from background terms
	will be removed after time averaging. This function makes sure background isn't
	subject to viscosity/drag.'''

    uxx = np.zeros(u.shape)
    uyy = np.zeros(u.shape)
    vxx = np.zeros(u.shape)
    vyy = np.zeros(u.shape)

    for ti in range(0, Nt):

        uyy[:, :, ti] = diff(diff(u[:, :, ti], 0, 0, dy), 0, 0, dy)
        uxx[:, :, ti] = diff(diff(u[:, :, ti], 1, 1, dx), 1, 1, dx)

        vyy[:, :, ti] = diff(diff(v[:, :, ti], 0, 0, dy), 0, 0, dy)
        vxx[:, :, ti] = diff(diff(v[:, :, ti], 1, 1, dx), 1, 1, dx)

    H = np.zeros(u.shape)
    U = np.zeros(u.shape)
    for ti in range(0, Nt):
        for i in range(0, N):
            H[:, i, ti] = H0
            U[:, i, ti] = U0

    Ed = (H * u + U * h + u * h) * (
        (uxx + uyy) / Re - gamma * u / Ro) + (H * v + v * h) * (
            (vxx + vyy) / Re - gamma * v / Ro)
    # This omits a couple of terms that average to zero.

    Ed_av = timeAverage(Ed, T, Nt)

    return Ed, Ed_av
Exemple #12
0
def eigTest2(k_sel, mode_sel, K_nd, dy_nd, N, dim, path, a1, a2, a3, a4, b4,
             c1, c2, c3, c4):
    # This test makes sure that eigenmodes actually solve the governing equations.

    for i in range(0, len(k_sel)):

        ii = k_sel[i]
        k = K_nd[ii]
        mode = mode_sel[i]

        ncFile = path + 'RSW1L_Eigenmodes_k' + str(int(k)) + '_N129.nc'
        print('Reading from ' + ncFile + '...')
        val, vec, count = output_read.ncReadEigenmodes(ncFile)

        # Extract the eigenvectors.
        u_vec, v_vec, eta_vec = eigDiagnostics.vec2vecs(vec, N, dim, BC)

        # Now we have to check that this solves the governing equations by substituting it back in.
        u_vec = u_vec[:, mode]
        v_vec = v_vec[:, mode]
        eta_vec = eta_vec[:, mode]
        val = val[mode]

        #val = val * (2 * np.pi * I * Ro);

        u_y = diff(u_vec, 2, 0, dy_nd) * dy_nd
        u_yy = diff(u_vec, 2, 0, dy_nd) * dy_nd

        e1 = -val * u_vec
        e2 = a1[:, ii] * u_vec[:]
        e3 = a2 * u_yy
        e4 = a3 * v_vec
        e5 = a4[ii] * eta_vec
        e = e1 + e2 + e3 + e4 + e5

        plt.subplot(321)
        plt.plot(e1)
        plt.subplot(322)
        plt.plot(abs(e2))
        plt.subplot(323)
        plt.plot(e3)
        plt.subplot(324)
        plt.plot(e4)
        plt.subplot(325)
        plt.plot(e5)
        plt.subplot(326)
        plt.plot(e[10:N - 10])

        plt.show()
Exemple #13
0
def EIG_COEFFICIENTS(Ro, Re, K_nd, f_nd, U1_nd, U2_nd, H1_nd, H2_nd, rho1_nd,
                     rho2_nd, gamma_nd, dy_nd, N):
    # Here we also divide coeficients of derivatives by the relevant space-step:
    # 2*dy_nd for first-order derivatives, dy_nd**2 for second-order derivatives.
    # Note: to speed up the algorithm, some coefficients aren't unnecessarily defined as they have a duplicate featuring in another equation.
    # All coefficients are related to their solver.py counterparts: the same but divided by a factor of 2*pi*I*Ro in mom. eqs only,
    # and 2*pi*I in cont. eqs. The time-derivative terms are also of course omitted.

    I = np.complex(0, 1)

    # 1 - Define all k- and y-dependent coefficients
    a1 = np.zeros((N, N), dtype=complex)
    c1 = np.zeros((N, N), dtype=complex)
    c4 = np.zeros((N, N), dtype=complex)
    d1 = np.zeros((N, N), dtype=complex)
    f1 = np.zeros((N, N), dtype=complex)
    f4 = np.zeros((N, N), dtype=complex)
    for j in range(0, N):
        for i in range(0, N):
            a1[j, i] = U1_nd[j] * K_nd[i] - 2 * np.pi * I * K_nd[i]**2 / Re
            c1[j, i] = H1_nd[j] * K_nd[i]
            c4[j, i] = U1_nd[j] * K_nd[i]
            d1[j, i] = U2_nd[j] * K_nd[i] - 2 * np.pi * I * K_nd[
                i]**2 / Re - I * gamma_nd / (2 * np.pi * Ro)
            f1[j, i] = H2_nd[j] * K_nd[i]
            f4[j, i] = U2_nd[j] * K_nd[i]
    # Edit from here.
    # 2 - Define all y-dependent coefficients
    a3 = I * (f_nd - Ro * diff(U1_nd, 2, 0, dy_nd)) / (2 * np.pi * Ro)
    b1 = -I * f_nd / (2 * np.pi * Ro)
    d3 = I * (f_nd - Ro * diff(U2_nd, 2, 0, dy_nd)) / (2 * np.pi * Ro)
    f2 = -I * diff(H2_nd, 2, 0, dy_nd) / (2 * np.pi)
    f3 = -I * H2_nd / (4 * np.pi * dy_nd)

    # 3 - Define all k-dependent coefficients
    a4 = K_nd / Ro
    d4 = K_nd * rho1_nd / Ro

    # 4 - Define all constant coefficients
    a2 = I / (2 * np.pi * Re * dy_nd**2)
    b4 = -I / (4 * np.pi * Ro * dy_nd)
    c2 = -I * diff(H1_nd, 2, 0, dy_nd) / (2 * np.pi)
    c3 = -I * H1_nd / (4 * np.pi * dy_nd)
    e4 = -I * rho1_nd / (4 * np.pi * Ro * dy_nd)

    # Summary of coefficients not explicitly defined for sake of algorithm speed:
    # b2 = a1, b3 = a2, d2 = a2, d5 = a4, e1 = b1, e2 = d1, e3 = a2, e5 = b4.

    return a1, a2, a3, a4, b1, b4, c1, c2, c3, c4, d1, d3, d4, e4, f1, f2, f3, f4
Exemple #14
0
def PV_instant(u,v,h,u_full,h_full,H0_nd,U0_nd,N,Nt,dx_nd,dy_nd,f_nd,Ro):
	'''
	Instantaneous PV
	'''

	RV_full = diff(v,1,1,dx_nd) - diff(u_full,0,0,dy_nd);
	RV_BG = - diff(U0_nd,2,0,dy_nd);
	RV = diff(v,1,1,dx_nd) - diff(u,0,0,dy_nd)
	Q = (RV_BG + f_nd / Ro) / H0_nd
	
	q = np.zeros((N,N))
	for j in range(0,N):	
		q[j,:] = (RV[j,:] - Q[j] * h[j,:]) / H0_nd[j]

	return q
Exemple #15
0
def forcingDiff(Ftilde_nd, y_nd, dy_nd, N, i):
    # Plots the y-derivatives of the 1D forcing at a given wavenumber.
    # A function used to test the diff algortithm, improve it, and resolve the error issue.

    Ftilde_y = diff(Ftilde_nd[:, i], 2, 0, dy_nd)
    Ftilde_yy = diff(Ftilde_y, 2, 0, dy_nd)

    plt.subplot(131)
    plt.plot(Ftilde_nd[:, i], y_nd)
    plt.subplot(132)
    plt.plot(Ftilde_y, y_nd)
    plt.subplot(133)
    plt.plot(Ftilde_yy, y_nd)
    plt.show()

    import sys
    sys.exit()
Exemple #16
0
def forcingTest(F1_nd, F2_nd, F3_nd, F6_nd, f_nd, rho1_nd, rho2_nd, dy_nd,
                dx_nd, N):
    # This function takes as input the forcing terms defined in a previous function, as tests (visually) whether or not they are in geostrophic balance.

    print('Max F1 = ' + str(np.max(F1_nd)))

    # First calculate all the terms we require.
    F0 = F3_nd + F6_nd
    # F0 can be interpreted as the surface forcing.
    F0_x = diff(F0, 1, 1, dx_nd)
    F0_y = diff(F0, 0, 0, dy_nd)
    F6_x = diff(F6_nd, 1, 1, dx_nd)
    F6_y = diff(F6_nd, 0, 0, dy_nd)

    geo1 = np.zeros((N, N))
    geo2 = np.zeros((N, N))
    for j in range(0, N):
        for i in range(0, N):
            geo1[j, i] = f_nd[j] * F2_nd[j, i] - F0_x[j, i]
            geo2[j, i] = f_nd[j] * F1_nd[j, i] + F0_y[j, i]
    geo3 = rho1_nd * F0_x + rho2_nd * F6_x
    geo4 = rho1_nd * F0_y + rho2_nd * F6_y

    #plt.subplot(121);
    #plt.contourf(geo1);
    #plt.colorbar();
    #plt.subplot(122);
    #plt.contourf(F0_x);
    #plt.colorbar();
    #plt.show();

    plt.subplot(221)
    plt.contourf(geo1)
    plt.colorbar()
    plt.subplot(222)
    plt.contourf(geo2)
    plt.colorbar()
    plt.subplot(223)
    plt.contourf(geo3)
    plt.colorbar()
    plt.subplot(224)
    plt.contourf(geo4)
    plt.colorbar()
    plt.tight_layout()
    plt.show()
Exemple #17
0
def footprintComponents(uq,Uq,uQ,vq,vQ,x_nd,T_nd,dx_nd,dy_nd,N,Nt):
	'''
	A function that calculates the PV footprint of the 1L SW solution in terms of its components, allowing for analysis.
	The function calculates the following terms: (1) uq, (2) Uq, (3) uQ, (4) UQ, (5) vq and (6) vQ. (UQ has zero zonal derivative.)
	The zonal/meridional derivative of the zonal/meridional PV flux is taken, averaged over one forcing period.
	Lastly, the zonal averages are calculated and everything useful returned.
	'''

	# Time averaging.
	uq = timeAverage(uq,T_nd,Nt);
	Uq = timeAverage(Uq,T_nd,Nt);
	uQ = timeAverage(uQ,T_nd,Nt);
	vq = timeAverage(vq,T_nd,Nt);
	vQ = timeAverage(vQ,T_nd,Nt);

	# Derivatives (no need to operate on UQ) and time-averaging.
	P_uq = - diff(uq,1,1,dx_nd);
	P_uQ = - diff(uQ,1,1,dx_nd);
	P_Uq = - diff(Uq,1,1,dx_nd);
	P_vQ = - diff(vQ,0,0,dy_nd);
	P_vq = - diff(vq,0,0,dy_nd);

	# Extend all arrays to include the final x gridpoint.
	P_uq = extend(P_uq);
	P_uQ = extend(P_uQ);
	P_Uq = extend(P_Uq);
	P_vQ = extend(P_vQ);
	P_vq = extend(P_vq);

	# Normalisation by AmpF_nd not needed if normalised quanities are passed into the function.

	P = P_uq + P_uQ + P_Uq + P_vq + P_vQ;

	# Zonal averaging 
	P_uq_xav = np.trapz(P_uq,x_nd,dx_nd,axis=1);
	P_uQ_xav = np.trapz(P_uQ,x_nd,dx_nd,axis=1);
	P_Uq_xav = np.trapz(P_Uq,x_nd,dx_nd,axis=1);
	P_vq_xav = np.trapz(P_vq,x_nd,dx_nd,axis=1);
	P_vQ_xav = np.trapz(P_vQ,x_nd,dx_nd,axis=1);
	
	#P_xav = np.trapz(P_tav,x_nd[:N],dx_nd,axis=1);
	P_xav = P_uq_xav + P_uQ_xav + P_Uq_xav + P_vq_xav + P_vQ_xav;
	# Tests confirm that the multiple approaches for calculating P_xav and P_tav yield the same results.

	return P, P_uq, P_uQ, P_Uq, P_vq, P_vQ, P_xav, P_uq_xav, P_uQ_xav, P_Uq_xav, P_vq_xav, P_vQ_xav;
Exemple #18
0
def footprint(uu, uv, vv, x_nd, T_nd, dx_nd, dy_nd, N, Nt):
    # A function that calculates the momentum footprint of the 1L SW solution as produced by RSW.py

    # Time-averaging
    uu = timeAverage(uu, T_nd, Nt)
    uv = timeAverage(uv, T_nd, Nt)
    vv = timeAverage(vv, T_nd, Nt)

    # Two footprint terms to calculate
    Mu = -diff(uu, 1, 1, dx_nd) - diff(uv, 0, 0, dy_nd)
    Mv = -diff(uv, 1, 1, dx_nd) - diff(vv, 0, 0, dy_nd)

    Mu = extend(Mu)
    Mv = extend(Mv)

    # We are interested in the zonal average of the footprint
    Mu_xav = np.trapz(Mu, x_nd, dx_nd, axis=1)
    Mv_xav = np.trapz(Mv, x_nd, dx_nd, axis=1)

    return Mu, Mv, Mu_xav, Mv_xav
Exemple #19
0
def footprint(uh, uH, Uh, vh, vH, x_nd, y_nd, T_nd, dx_nd, dy_nd, dt_nd, N,
              Nt):

    bu_full = uh + uH + Uh
    # Zonal thickness flux
    bv_full = vh + vH
    # Meridional thickness flux

    bu_full = timeAverage(bu_full, T_nd, Nt)
    bv_full = timeAverage(bv_full, T_nd, Nt)

    # Calculate the footprint.
    B = -diff(bu_full, 1, 1, dx_nd) - diff(bv_full, 0, 0, dy_nd)

    B = extend(B)

    # We are interested in the zonal average of the footprint
    B_xav = np.trapz(B, x_nd, dx_nd, axis=1)

    return B, B_xav
Exemple #20
0
def budgetDissipation3(U0, H0, u, v, h, Ro, Re, gamma, dx, dy, T, Nt, N):
    ''' Calculate time-dependent and time-mean energy budget due to dissipation.
	Make sure to use full u, v and h fields. Contribution from background terms
	will be removed after time averaging. This function makes sure background isn't
	subject to viscosity/drag.'''

    # Contribution from dissipation terms, if we assume it only acts upon eddy flow, is h_full * u_full * u.
    # This separates this function from the previous two.

    uxx = np.zeros(u.shape)
    uyy = np.zeros(u.shape)
    vxx = np.zeros(u.shape)
    vyy = np.zeros(u.shape)

    for ti in range(0, Nt):

        uyy[:, :, ti] = diff(diff(u[:, :, ti], 0, 0, dy), 0, 0, dy)
        uxx[:, :, ti] = diff(diff(u[:, :, ti], 1, 1, dx), 1, 1, dx)

        vyy[:, :, ti] = diff(diff(v[:, :, ti], 0, 0, dy), 0, 0, dy)
        vxx[:, :, ti] = diff(diff(v[:, :, ti], 1, 1, dx), 1, 1, dx)

    H = np.zeros(u.shape)
    U = np.zeros(u.shape)
    for ti in range(0, Nt):
        for i in range(0, N):
            H[:, i, ti] = H0
            U[:, i, ti] = U0

    # Extra lines that look at contributions to dissipation of energy.
    #Ed_drag = - (U + u) * (H + h) * gamma * u / Ro - v * (H + h) * gamma * v / Ro
    #Ed_diss = (U + u) * (H + h) * (uxx + uyy) / Re + v * (H + h) * (vxx + vyy) / Re

    #e1 = timeAverage(Ed_drag,T,Nt)
    #e2 = timeAverage(Ed_diss,T,Nt)
    #plt.subplot(121)
    #plt.contourf(e1); plt.colorbar()
    #plt.subplot(122)
    #plt.contourf(e2); plt.colorbar()
    #plt.show()

    Ed = (U + u) * (H + h) * (
        (uxx + uyy) / Re - gamma * u / Ro) + v * (H + h) * (
            (vxx + vyy) / Re - gamma * v / Ro)
    # This omits a couple of terms that average to zero.

    Ed_av = timeAverage(Ed, T, Nt)

    return Ed, Ed_av
Exemple #21
0
def vort(u_nd, v_nd, h_nd, u_full, h_full, H_nd, U_nd, N, Nt, dx_nd, dy_nd,
         f_nd):

    RV_full = np.zeros((N, N, Nt))
    RV_prime = np.zeros((N, N, Nt))
    for ti in range(0, Nt):
        # Define the relative vorticities (RV_full=RV_BG+RV_prime, can always check this numerically)
        RV_full[:, :, ti] = diff(v_nd[:, :, ti], 1, 1, dx_nd) - diff(
            u_full[:, :, ti], 0, 0, dy_nd)
        RV_prime[:, :, ti] = diff(v_nd[:, :, ti], 1, 1, dx_nd) - diff(
            u_nd[:, :, ti], 0, 0, dy_nd)
    RV_BG = -diff(U_nd, 2, 0, dy_nd)
    # This is defined outside the loop as it has no time-dependence.

    # Now define two of the PVs
    PV_full = np.zeros((N, N, Nt))
    PV_BG = np.zeros(N)
    for j in range(0, N):
        PV_BG[j] = (RV_BG[j] + f_nd[j]) / H_nd[j]
        for i in range(0, N):
            for ti in range(0, Nt):
                PV_full[j, i,
                        ti] = (RV_full[j, i, ti] + f_nd[j]) / h_full[j, i, ti]

    # Two options to define the PV induced in the forced system: (1) PV_full-PV_BG or (2) use the algebraic def. given in the report.
    PV_prime = np.zeros((N, N, Nt))
    for j in range(1, N - 1):
        for i in range(0, N):
            for ti in range(0, Nt):
                PV_prime[j, i, ti] = PV_full[j, i, ti] - PV_BG[j]
                # Option 1
    #PV_prime = np.zeros((N,N));	# Option 2 - keep this commented out, just use it as a check.
    #for j in range(0,N):
    #	for i in range(0,N):
    #		PV_prime[j,i] = (H_nd[j] * RV_prime[j,i] - h_nd[j,i] * (RV_BG[j] + f_nd[j])) / (eta_full[j,i] * H_nd[j]);

    return PV_prime, PV_full, PV_BG
Exemple #22
0
def PV(u, v, h, H_nd, U_nd, f_nd, dx_nd, dy_nd, N):
    # Takes input u, v, h which are the eigenvectors of the 2-L SW system, projected onto two dimensions,
    # i.e. u1 = u1_vec(y) * exp(i*k*x). Same code works for either layer.

    u_full = np.zeros((N, N))
    eta_full = np.zeros((N, N))
    for i in range(0, N):
        u_full[:, i] = u[:, i] + U_nd[:]
        eta_full[:, i] = eta[:, i] + H_nd[:]

    # Relative vorticity
    RV_full = diff(v, 1, 1, dx_nd) - diff(u_full, 0, 0, dy_nd)
    RV_prime = diff(v, 1, 1, dx_nd) - diff(u, 0, 0, dy_nd)
    RV_BG = -diff(U_nd, 2, 0, dy_nd)

    # Potential vorticity
    PV_BG = (f_nd + RV_BG) / H_nd
    PV_full = np.zeros((N, N))
    PV_prime = np.zeros((N, N))
    for i in range(0, N):
        PV_full[:, i] = (f_nd[:] + RV_full[:, i]) / eta_full[:, i]
        PV_prime[:, i] = PV_full[:, i] - PV_BG[:]

    return PV_full, PV_prime
Exemple #23
0
def budgetFlux(u, v, h, Ro, dx, dy, T, Nt):
    ''' Calculate time-dependent and time-mean energy budget due to fluxes.
	Make sure to use full u, v and h fields. Contribution from 
	background terms will be removed after time averaging.'''

    E = 0.5 * h * (u**2 + v**2) + h**2 / Ro

    uEflux = np.zeros(u.shape)
    vEflux = np.zeros(u.shape)
    Eflux = np.zeros(u.shape)

    for ti in range(0, Nt):

        uEflux[:, :, ti] = u[:, :, ti] * E[:, :, ti]
        vEflux[:, :, ti] = v[:, :, ti] * E[:, :, ti]

        Eflux[:, :, ti] = -diff(uEflux[:, :, ti], 1, 1, dx) - diff(
            vEflux[:, :, ti], 0, 0, dy)

    Eflux_av = timeAverage(Eflux, T, Nt)
    uEflux_av = timeAverage(uEflux, T, Nt)
    vEflux_av = timeAverage(vEflux, T, Nt)

    return Eflux, Eflux_av, uEflux_av, vEflux_av
Exemple #24
0
def budgetDissipation(u, v, h, Ro, Re, gamma, dx, dy, T, Nt):
    ''' Calculate time-dependent and time-mean energy budget due to dissipation.
	Make sure to use full u, v and h fields. Contribution from 
	background terms will be removed after time averaging.'''

    uxx = np.zeros(u.shape)
    uyy = np.zeros(u.shape)
    vxx = np.zeros(u.shape)
    vyy = np.zeros(u.shape)

    for ti in range(0, Nt):

        uyy[:, :, ti] = diff(diff(u[:, :, ti], 0, 0, dy), 0, 0, dy)
        uxx[:, :, ti] = diff(diff(u[:, :, ti], 1, 1, dx), 1, 1, dx)

        vyy[:, :, ti] = diff(diff(v[:, :, ti], 0, 0, dy), 0, 0, dy)
        vxx[:, :, ti] = diff(diff(v[:, :, ti], 1, 1, dx), 1, 1, dx)

    Ed = h * (u * (uxx + uyy) + v *
              (vxx + vyy)) / Re - gamma * h * (u**2 + v**2) / Ro

    Ed_av = timeAverage(Ed, T, Nt)

    return Ed, Ed_av
Exemple #25
0
                F2_orig[j, i] = 0
            else:
                F1_orig[j, i] = AmpF * np.pi * g * (y[j] - y0) / (
                    2 * r0 * f[j] * r) * np.sin((np.pi / 2) * r / r0)
                F2_orig[j, i] = -AmpF * np.pi * g * x[i] / (
                    2 * r0 * f[j] * r) * np.sin((np.pi / 2) * r / r0)
            F3_orig[j, i] = AmpF * np.cos((np.pi / 2) * r / r0)
            mass = mass + F3_orig[j, i]
mass = mass / (N * (N + 1) - count)
for i in range(0, N + 1):
    for j in range(0, N):
        F3_orig[j, i] = F3_orig[j, i] - mass

i_sample = N / 2

F3_orig_y = diff(F3_orig[:, i_sample], 2, 0, dy_nd)
F3_orig_yy = diff(F3_orig_y, 2, 0, dy_nd)

F3_new_y = diff(F3_new[:, i_sample], 2, 0, dy_nd)
F3_new_yy = diff(F3_new_y, 2, 0, dy_nd)

plt.subplot(321)
#plt.contourf(F3_orig);
plt.plot(F3_orig[:, i_sample])
plt.subplot(322)
#plt.contourf(F3_new);
plt.plot(F3_new[:, i_sample])
plt.subplot(323)
plt.plot(F3_orig_y)
plt.subplot(324)
plt.plot(F3_new_y)
Exemple #26
0
Uset = np.linspace(-.3, .5, nn)

FPV = np.zeros((N, N))
fpv = np.zeros(nn)

Q = np.zeros((N, nn))
HH = np.zeros((nn))

for ui in range(0, nn):

    U0, H0 = BG_state.BG_uniform(Uset[ui], Hflat, f0, beta, g, y, N)

    U0 = U0 / U
    H0 = H0 / chi

    U0y = diff(U0, 2, 0, dy_nd)
    Q[:, ui] = (f_nd / Ro - U0y) / H0

    HH[ui] = np.mean(H0) - Hflat

    F2x = diff(F2_nd, 1, 1, dx_nd)
    F1y = diff(F1_nd, 0, 0, dy_nd)

    for j in range(0, N):
        for i in range(0, N):
            FPV[j, i] = (F2x[j, i] -
                         F1y[j, i]) / H0[j]  # + Q[j] * F3_nd[j,i] / H0[j]

    fpv[ui] = np.sum(FPV)

plt.plot(1. / HH)
Exemple #27
0
    elif FORCE_TYPE == 'DCTS':
        F1_nd, F2_nd, F3_nd, Ftilde1_nd, Ftilde2_nd, Ftilde3_nd = forcing_1L.forcing_dcts(
            x, y, K, y0, r0, N, FORCE, AmpF, g, f, f0, U, L, dx, dy)
    else:
        sys.exit('ERROR: Invalid forcing option selected.')

    e1, e2, e3 = diagnostics.error(u_nd, v_nd, eta_nd, dx_nd, dy_nd, dt_nd,
                                   U0_nd, H0_nd, Ro, gamma_nd, Re, f_nd, F1_nd,
                                   F2_nd, F3_nd, T_nd, ts, omega_nd, N)
    e = np.sqrt((e1**2 + e2**2 + e3**2) / 3.0)
    print 'Error = ' + str(e) + '. Error split = ' + str(e1) + ', ' + str(
        e2) + ', ' + str(e3)

if option == 0:
    cos = np.cos(2 * np.pi * x_nd / (x_nd[N] - x_nd[0]))
    cos_y = diagnostics.diff(cos, 2, 1, dy_nd) / (2 * np.pi)
    cos_yy = diagnostics.diff(cos_y, 2, 1, dy_nd) / (2 * np.pi)

    dim = len(cos)
    print(cos[0], cos[dim - 1])
    plt.subplot(131)
    plt.plot(cos)
    plt.grid()
    plt.subplot(132)
    plt.plot(cos_y)
    plt.grid()
    plt.subplot(133)
    plt.plot(cos_yy)
    plt.grid()
    plt.show()
Exemple #28
0
H0 = np.zeros((N,nn))
for ui in range(0,nn):
	for j in range(0,N):
		H0[j,ui] = - (U0[ui] / g) * (f0 * y[j] + beta * y[j]**2 / 2) + Hflat

# Now PV
Q = np.zeros((nn,N))
for ui in range(0,nn):
	for j in range(0,N):
		Q[ui,j] = f[j] / H0[j,ui]

# PV gradient
Qy = np.zeros((nn,N))
Qyy = np.zeros((nn,N))
for ui in range(0,nn):
	Qy[ui,:] = diff(Q[ui,:],2,0,dy)
	Qyy[ui,:] = diff(Qy[ui,:],2,0,dy)

print(np.shape(Qy))

#plt.plot(Qy[:,500],label='north')
#plt.plot(Qy[:,300],label='center')
#plt.plot(Qy[:,10],label='south')
#plt.legend()
#plt.show()

plt.plot(Qy[31,:],label=str(U0[31]))
plt.plot(Qy[50,:],label=str(U0[50]))
plt.plot(Qy[65,:],label=str(U0[65]))
plt.legend()
plt.show()
Exemple #29
0
		sigma = 0.3 * Ly;
	# The rest of the parameters do not depend on the type of Gaussian flow we want
	l = Ly / 2;
	a = Umag / (np.exp(l**2 / sigma**2) - 1);	# Maximum BG flow velocity Umag
	for j in range(0,N):
		U0[j] = a * np.exp((l**2 - y[j]**2) / sigma**2) - a;		# -a ensures U0 is zero on the boundaries
		H0[j] = - a * (np.sqrt(np.pi) * f0 * sigma * np.exp(l**2 / sigma**2) * erf(y[j] / sigma) / 2 
					- beta * sigma**2 * np.exp((l**2 - y[j]**2) / sigma**2) / 2
					- f0 * y[j] - beta * y[j]**2 / 2) / g + Hflat; #erf(0);
		
elif BG == 'NONE':
	for j in range(0,N):
		Umag = 0;
		H0[j] = Hflat;

H0_y = diff(H0,2,0,dy);

# Calculate BG PV
Q = (f + diff(U0,2,0,dy)) / H0;

# Forcing
#=======================================================

# Instead of defining the forcing amplitude in the forcing module, we define it here as other codes require this value for normalisation
r0 = 2*90.0 * 1000.0;  
AmpF = 1.0e-7; 
if Fpos == 'NORTH':
	y0_index = int(3*N/4);
elif Fpos == 'CENTER':
	y0_index = int(N/2);
elif Fpos == 'SOUTH':
Exemple #30
0
def forcingTest(F1_nd,F2_nd,F3_nd,F6_nd,f_nd,rho1_nd,rho2_nd,dy_nd,dx_nd,N):
# This function takes as input the forcing terms defined in a previous function, as tests (visually) whether or not they are in geostrophic balance.	
	
	print('Max F1 = ' + str(np.max(F1_nd)));
	
	# First calculate all the terms we require.
	F0 = F3_nd + F6_nd; # F0 can be interpreted as the SSH forcing.

	F0_x = diff(F0,1,1,dx_nd);
	F0_y = diff(F0,0,0,dy_nd);
	F6_x = diff(F6_nd,1,1,dx_nd);
	F6_y = diff(F6_nd,0,0,dy_nd);

	geo1 = np.zeros((N,N))
	geo2 = np.zeros((N,N))
	MOM1 = np.zeros((N,N))
	for j in range(0,N):
		for i in range(0,N):
			MOM1[j,i] = f_nd[j] * F2_nd[j,i]
			geo1[j,i] = MOM1[j,i] - F0_x[j,i];
			geo2[j,i] = f_nd[j] * F1_nd[j,i] + F0_y[j,i];
	geo3 = rho1_nd * F0_x + rho2_nd * F6_x; 
	geo4 = rho1_nd * F0_y + rho2_nd * F6_y; 

	#====

	plt.subplot(221);
	plt.contourf(F0);
	plt.colorbar();
	plt.title('F0')

	plt.subplot(222);
	plt.contourf(F0_x);
	plt.colorbar();
	plt.title('F0_x')

	plt.subplot(223);
	plt.contourf(MOM1);
	plt.colorbar();
	plt.title('f*F2')

	plt.subplot(224);
	plt.contourf(geo1);
	plt.colorbar();	
	plt.title('Geo bal 1')

	plt.tight_layout();
	plt.show();

	#===

	plt.subplot(221);
	plt.contourf(F6_x);
	plt.colorbar();
	plt.title('F6_x')

	plt.subplot(222);
	plt.contourf(F6_y);
	plt.colorbar();
	plt.title('F6_y')

	plt.subplot(223)
	plt.contourf(geo3)
	plt.colorbar()
	plt.title('v2 geo bal')
	
	plt.subplot(224)
	plt.contourf(geo4)
	plt.colorbar()
	plt.title('u2 geo bal')

	plt.tight_layout();
	plt.show();