def rSurfPrime(th): #Accurate approximation matrix W for approximating rSurfPrime(th): phs = 9 pol = 7 stc = 17 if len(np.shape(th)) == 2: tmp = th[0, :].copy() elif len(np.shape(th)) == 1: tmp = th.copy() else: raise ValueError("th should have either 1 or 2 dimensions.") W = phs1.getPeriodicDM( z=tmp, x=tmp, m=1 \ , phs=phs, pol=pol, stc=stc, period=2*np.pi ) return W.dot(rSurf(th).T).T
def interpAngular( U0, U1, U2, U3, U4, U5, th0, th1, th2, th3, th4, th5 ) : phsA = 9 polA = 7 stcA = 17 W1 = phs1.getPeriodicDM( period=2*np.pi, x=th1, X=th0, m=0 \ , phsDegree=phsA, polyDegree=polA, stencilSize=stcA ) W2 = phs1.getPeriodicDM( period=2*np.pi, x=th2, X=th0, m=0 \ , phsDegree=phsA, polyDegree=polA, stencilSize=stcA ) W3 = phs1.getPeriodicDM( period=2*np.pi, x=th3, X=th0, m=0 \ , phsDegree=phsA, polyDegree=polA, stencilSize=stcA ) W4 = phs1.getPeriodicDM( period=2*np.pi, x=th4, X=th0, m=0 \ , phsDegree=phsA, polyDegree=polA, stencilSize=stcA ) W5 = phs1.getPeriodicDM( period=2*np.pi, x=th5, X=th0, m=0 \ , phsDegree=phsA, polyDegree=polA, stencilSize=stcA ) U1 = np.transpose( W1.dot(np.transpose(U1)) ) U2 = np.transpose( W2.dot(np.transpose(U2)) ) U3 = np.transpose( W3.dot(np.transpose(U3)) ) U4 = np.transpose( W4.dot(np.transpose(U4)) ) U5 = np.transpose( W5.dot(np.transpose(U5)) ) return U0, U1, U2, U3, U4, U5
# Whvs = alp * dsPol.dot(Whvs) # #Complex radial HV: # dr = ( rr[2:nlv,:] - rr[0:nlv-2,:] ) / 2. # alpDrPol = alp * dr**(phs-2) # alpDrPol = alp * ((outerRadius-innerRadius)/(nlv-2)) ** (phs-2) # alpDxPol = alp * ( ( dr + ss[1:-1,:]*np.tile(dth,(nlv-2,1)) ) / 2. ) ** (phs-2) # alpDxPol = alp * ( ( (outerRadius-innerRadius)/(nlv-2) + ss[1:-1,:]*2.*np.pi/nth ) / 2. ) ** (phs-2) # alpDsPol = alp * ( ( ss[1:-1,:]*np.tile(dth,(nlv-2,1)) + np.transpose(np.tile(ds,(nth,1))) ) / 2. ) ** (phs-2) ########################################################################### #Angular PHS-FD weights arranged in a differentiation matrix: #Matrix for approximating first derivative in angular direction: Wlam = phs1.getPeriodicDM( z=th, x=th, m=1 \ , phs=phsA, pol=polA, stc=stcA, period=2*np.pi ) #Simple (and technically incorrect) angular HV: Whvlam = phs1.getPeriodicDM( z=th, x=th, m=phsA-1 \ , phs=phsA, pol=polA, stc=stcA, period=2*np.pi ) Whvlam = alpA * dth0**(phsA - 2) * Whvlam #scaled angular HV matrix # dthPol = spdiags( dth**polA, np.array([0]), len(dth), len(dth) ) # Whvlam = alpA * dthPol.dot(Whvlam) # #Complex angular HV: # alpDthPol = alpA * dth0**polA # # alpDthPol = alpA * ( np.tile(dth,(nlv-2,1)) ) ** polA ########################################################################### #Weights for interpolation to boundary (I), extrapolation to
def derivativeApproximations(x, dx, left, right, s, ds): """ This is where all of the weights for approximating spatial derivatives are calculated. Also, at the end, the function outputs functions Da(), Ds(), and HV(), which are used to approximate the corresponding derivative of something. """ phs = 11 #lateral PHS exponent (odd number) pol = 5 #highest degree polynomial in lateral basis stc = 11 #lateral stencil size alp = 2.**-9 * 300. #lateral dissipation coefficient Wa = phs1.getPeriodicDM(z=x, x=x, m=1 \ , phs=phs, pol=pol, stc=stc, period=right-left) #d/da matrix Whva = phs1.getPeriodicDM(z=x, x=x, m=6 \ , phs=phs, pol=pol, stc=stc, period=right-left) Whva = alp * dx**5 * Whva #lateral dissipation weights W2a = phs1.getPeriodicDM(z=x, x=x, m=2 \ , phs=phs, pol=pol, stc=stc, period=right-left) W2a = 2.**-10. * dx * W2a phs = 5 #vertical PHS exponent pol = 2 #highest degree polynomial in vertical basis stc = 5 #vertical stencil size if phs == 7: alp = 2.**-24. * 300. elif phs == 5: alp = -2.**-22. * 300. #vertical dissipation coefficient elif phs == 3: alp = 2.**-20 * 300. else: raise ValueError("Please use phs=3 or phs=5 or phs=7.") Ws = phs1.getDM(z=s, x=s, m=1 \ , phs=phs, pol=pol, stc=stc) #d/ds matrix Whvs = phs1.getDM(z=s[1:-1], x=s, m=phs-1 \ , phs=phs, pol=pol, stc=stc) Whvs = alp * ds**(phs - 2) * Whvs #vertical dissipation weights numDampedLayers = np.int(np.round(len(s) / 2.)) W2s = phs1.getDM(z=s[1:numDampedLayers], x=s, m=2 \ , phs=phs, pol=pol, stc=stc) W2s = 2.**-10. * ds * W2s sTop = (s[0] + s[1]) / 2. wItop = phs1.getWeights(z=sTop, x=s[0:stc], m=0 \ , phs=phs, pol=pol) #interpolate to top boundary wEtop = phs1.getWeights(z=s[0], x=s[1:1+stc], m=0 \ , phs=phs, pol=pol) #extrapolate to top ghost nodes wDtop = phs1.getWeights(z=sTop, x=s[0:stc], m=1 \ , phs=phs, pol=pol) #derivative on top boundary wHtop = phs1.getWeights(z=sTop, x=s[1:1+stc], m=0 \ , phs=phs, pol=pol) #extrapolate to top boundary wIbot = phs1.getWeights(z=1., x=s[-1:-1-stc:-1], m=0 \ , phs=phs, pol=pol) #interpolate to bottom boundary wEbot = phs1.getWeights(z=s[-1], x=s[-2:-2-stc:-1], m=0 \ , phs=phs, pol=pol) #extrapolate to bottom ghost nodes wDbot = phs1.getWeights(z=1., x=s[-1:-1-stc:-1], m=1 \ , phs=phs, pol=pol) #derivative on bottom boundary wHbot = phs1.getWeights(z=1., x=s[-2:-2-stc:-1], m=0 \ , phs=phs, pol=pol) #extrapolate to bottom boundary #Lateral derivative on all levels: def Da(U): return Wa.dot(U.T).T #Vertical first derivative on all levels: def Ds(U): return Ws.dot(U) #Total dissipation on non-ghost levels: def HV(U): return Whva.dot(U[1:-1, :].T).T + Whvs.dot(U) #Rayleigh-damping function for top 30 layers (mountainWaves test case): def rayleighDamping(U): return W2a.dot(U[1:numDampedLayers, :].T).T + W2s.dot(U) return Wa, stc, wItop, wEtop, wDtop, wHtop, wIbot, wEbot, wDbot, wHbot \ , Da, Ds, HV, rayleighDamping, numDampedLayers
########################################################################### s, ds, sTop, pTop, pSurf = getSvalues() xx, ss = np.meshgrid(x, s) ########################################################################### #All of the polyharmonic spline radial basis function weights: phs = 11 #lateral PHS exponent (odd number) pol = 5 #highest degree polynomial in lateral basis stc = 11 #lateral stencil size alp = 2.**-12. * 300. #lateral dissipation coefficient Wa = phs1.getPeriodicDM(z=x, x=x, m=1 \ , phs=phs, pol=pol, stc=stc, period=right-left) #lateral derivative weights Whva = phs1.getPeriodicDM(z=x, x=x, m=pol+1 \ , phs=phs, pol=pol, stc=stc, period=right-left) Whva = alp * dx**pol * Whva #lateral dissipation weights phs = 5 #vertical PHS exponent pol = 3 #highest degree polynomial in vertical basis stc = 5 #vertical stencil size if verticalCoordinate == "pressure": alp = -2.**-22. * 300. #vertical dissipation coefficient else: alp = -2.**-22. * 300. #much larger in height coordinate case? Ws = phs1.getDM(z=s, x=s, m=1 \ , phs=phs, pol=pol, stc=stc) #vertical derivative weights Whvs = phs1.getDM(z=s[1:-1], x=s, m=pol+1 \ , phs=phs, pol=pol, stc=stc)
Ws = phs1.getDM( x=s, X=s, m=1 \ , phsDegree=phs, polyDegree=pol, stencilSize=stc ) #Simple (but still correct with dsdr multiplier) radial HV: Whvs = phs1.getDM( x=s, X=s[1:-1], m=phs-1 \ , phsDegree=phs, polyDegree=pol, stencilSize=stc ) Whvs = alp * ds**(phs - 2) * Whvs #scaled radial HV matrix # dsPol = spdiags( ds**(phs-2), np.array([0]), len(ds), len(ds) ) # Whvs = alp * dsPol.dot(Whvs) ########################################################################### #Angular PHS-FD weights arranged in a differentiation matrix: #Matrix for approximating first derivative in angular direction: Wlam = phs1.getPeriodicDM( period=2*np.pi, x=th, X=th, m=1 \ , phsDegree=phsA, polyDegree=polA, stencilSize=stcA ) #Simple (and technically incorrect) angular HV: Whvlam = phs1.getPeriodicDM( period=2*np.pi, x=th, X=th, m=phsA-1 \ , phsDegree=phsA, polyDegree=polA, stencilSize=stcA ) # Whvlam = alpA * (ds0/innerRadius)**(phsA-2) * Whvlam #scaled angular HV dthPol = spdiags(dth**(phsA - 2), np.array([0]), len(dth), len(dth)) Whvlam = alpA * dthPol.dot(Whvlam) ########################################################################### #Weights for interpolation to boundary (I), extrapolation to #ghost-nodes (E), d/ds at boundary (D), and extrapolation to boundary(H): wIinner = phs1.getWeights(innerRadius, s[0:stcB], 0, phs, pol) wEinner = phs1.getWeights(s[0], s[1:stcB + 1], 0, phs, pol)