Archivo:Shallow water equations - one splash.webm
De testwiki
Ir a la navegación
Ir a la búsqueda
Shallow_water_equations_-_one_splash.webm (tamaño de archivo: 3,67 MB; tipo MIME: video/webm)
Este archivo es de Wikimedia Commons y puede usarse en otros proyectos. La descripción en su página de descripción del archivo se muestra debajo.
Resumen
| DescripciónShallow water equations - one splash.webm |
English: Analytical solution of the linearized shallow-water equations in a two-dimensional rectangular basin. |
| Fecha | |
| Fuente | Trabajo propio |
| Autor | Kraaiennest |
| Otras versiones |
|
| Background InfoField | Based on the exact solution for axisymmetrical waves in: G. F. Carrier and H. Yeh (2005) "Tsunami propagation from a finite source". Computer Modelling in Engineering & Sciences 10(2), pp. 113–122, doi:10.3970/cmes.2005.010.113 |
Código fuente
InfoField
Python code
| Python code for phase 1: compute axisymmetric solution for an unbounded domain |
|---|
#!/usr/bin/env python2.7
"""
Make an animation of the linear shallow-water equations in 2D
Based on the exact solution for axisymmetrical waves in:
G. F. Carrier and H. Yeh (2005)
Tsunami propagation from a finite source.
Computer Modelling in Engineering & Sciences,
vol. 10, no. 2, pp. 113-122
doi: 10.3970/cmes.2005.010.113
The dimensionless and linear shallow-water equations
in polar coordinates are:
d/dt^2 eta(r,t) - 1/r * d/dr( r * d/dr eta(r,t) ) = 0.
The initial conditions are a series of Gaussian humps, on
an equidistant grid in the (x,y)-plane. One Gaussian hump
released at t=t0 is given by the initial conditions:
eta(r,t0) = 2 * exp( -r^2 ), d/dt eta(r,t0) = 0.
"""
#%% import libs
from __future__ import print_function
from future.builtins import input
import numpy as np
import scipy.special as sp
import matplotlib.pyplot as plt
import multiprocessing
import time
from scipy.integrate import quad
from scipy.interpolate import RectBivariateSpline
#%% input
n = int( 181 ) # number of points in r-direction
m = int( 151 ) # number of time steps
dr = np.float64(0.2) # step in r-direction
dt = np.float64(0.2) # time step
res = int( 10 ) # resample factor for 2D interpolation
mpl = int( 11 ) # no. of elevation snapshots to plot
#%% integrand
r = np.float64()
t = np.float64()
rho = np.float64()
def integrand(rho,r,t):
return rho * sp.jn(0,rho*r) * np.cos(rho*t) * np.exp( -(rho**2)/4 )
def integrate(args):
r_now = args[0]
t_now = args[1]
return quad( integrand, 0, np.inf,
args=(r_now,t_now), epsabs=1.e-5, epsrel=1.e-5, limit=100)
#%% compute time integral of surface evolution as a function of r and t
print( '=== compute time integral of surface evolution as a function of r and t' )
start_time = time.time()
eta = np.empty( [n,m], dtype=np.float64 ) # surface elevation
err = np.empty( [n,m], dtype=np.float64 ) # surface elevation integrated in time
r = np.linspace( 0, (n-1)*dr, num=n, dtype=np.float64 ) # radial coordinate
t = np.linspace( 0, (m-1)*dt, num=m, dtype=np.float64 ) # time coordinate
eta0 = 2 * np.exp( - r**2 )
eta[:,0] = eta0
num_cores= int( multiprocessing.cpu_count() )
pool = multiprocessing.Pool(num_cores)
print( '--- number of cores : {0:d}'.format(num_cores) )
for jt in range(1,m):
print( '\r--- jt = {0:4d}'.format(jt), end='' )
t_now = t[jt]
params = [ (r[jr],t_now) for jr in range(n) ]
data = pool.map( integrate, params )
for jr in range(0,n):
[ eta[jr,jt], err[jr,jt] ] = data[jr]
pool.close()
pool.join()
print( ' ' )
no_nans = np.count_nonzero(np.isnan(eta))
no_infs = np.count_nonzero(np.isinf(eta))
print( '--- number of NaN\'s in eta(r,t): {0:d}'.format(no_nans) )
print( '--- number of inf\'s in eta(r,t): {0:d}'.format(no_infs) )
#%% bivariate spline interpolate to fine grid
print( '=== interpolate to fine grid' )
n_f = res * (n-1) + 1
m_f = res * (m-1) + 1
eta_f = np.empty( [n_f,m_f], dtype=np.float64 ) # surface elevation
r_f = np.linspace( 0, (n-1)*dr, num=n_f, dtype=np.float64 ) # radial coordinate
t_f = np.linspace( 0, (m-1)*dt, num=m_f, dtype=np.float64 ) # time coordinate
spl_eta = RectBivariateSpline( r, t, eta )
eta_f = spl_eta( r_f, t_f )
#%% save to file
print( '=== save results to file' )
with open( 'mat.npz', 'wb' ) as outfile:
# dr_f = dr / res
# dt_f = dt / res
np.savez( outfile, n=n, m=m, dr=dr, dt=dt, eta=eta, res=res )
#%% asymptotic behaviour in terms of parabolic cylinder function D
print( '=== compute asymptotic behaviour' )
eta_asym = np.zeros( [n,m], dtype=np.float64 ) # surface elevation
for jt in range(0,m):
for jr in range(1,n):
print( '\r--- (jt,jr) = ({0:d},{1:d}) '.format(jt,jr), end='' )
rnow = r[jr]
tnow = t[jt]
eta_asym[jr,jt] = 1. / np.sqrt( np.sqrt(2.) * rnow ) \
* sp.pbdv( np.float64(0.5), np.sqrt(2.) * (rnow-tnow) )[0] \
* np.exp( -0.5 * (rnow-tnow)**2 )
print( ' ' )
eta_asym[0,:] = 3*eta_asym[1,:] - 3*eta_asym[2,:] + eta_asym[3,:]
spl_asym = RectBivariateSpline( r, t, eta_asym )
eta_asym = spl_asym( r_f, t_f )
#%% execution time
end_time = time.time()
print( '--- execution time : {0:.3f} s'.format( end_time - start_time ) )
#%% plot quadrature error
print( '=== make plots' )
tp, rp = np.meshgrid( t, r )
fig, ax = plt.subplots(1)
pc = ax.pcolormesh( rp, tp, err, cmap='viridis',
vmin=0, vmax=5*np.std(err) )
ax.set_title( 'quadrature error' )
ax.axis( 'equal' )
ax.axis( 'image' )
fig.colorbar( pc, format='%.1e' )
ax.set_xlabel( 'r' )
ax.set_ylabel( 't' )
plt.show( block=False )
plt.savefig( 'fig.sol/swe_ani_2D_quad_error.png', dpi=300, bbox_inches='tight' )
#%% plot surface elevation on coarse grid
fig, ax = plt.subplots(1)
pc = ax.pcolormesh( rp, tp, eta, cmap='RdBu_r',
vmin=-2, vmax=2 )
ax.set_title( 'surface elevation eta(r,t)' )
ax.axis( 'equal' )
ax.axis( 'image' )
fig.colorbar( pc )
ax.set_xlabel( 'r' )
ax.set_ylabel( 't' )
plt.show( block=False )
plt.savefig( 'fig.sol/swe_ani_2D_eta_coarse.png', dpi=300, bbox_inches='tight' )
#%% plot surface elevation on fine grid
tpf, rpf = np.meshgrid( t_f, r_f )
fig, ax = plt.subplots(1)
pc = ax.pcolormesh( rpf, tpf, eta_f, cmap='RdBu_r',
vmin=-2, vmax=2 )
ax.set_title( 'surface elevation eta(r,t)' )
ax.axis( 'equal' )
ax.axis( 'image' )
fig.colorbar( pc )
ax.set_xlabel( 'r' )
ax.set_ylabel( 't' )
plt.show( block=False )
plt.savefig( 'fig.sol/swe_ani_2D_eta_fine.png', dpi=300, bbox_inches='tight' )
#%% difference with asymptotic solution
fig, ax = plt.subplots(1)
pc = ax.pcolormesh( rpf, tpf, np.sqrt(rpf)*(eta_asym-eta_f), cmap='RdBu_r',
vmin=-0.02, vmax=0.02 )
ax.set_title( 'difference of exact and asymptotic eta(r,t)' )
ax.axis( 'equal' )
ax.axis( 'image' )
fig.colorbar( pc )
ax.set_xlabel( 'r' )
ax.set_ylabel( 't' )
plt.show( block=False )
plt.savefig( 'fig.sol/swe_ani_2D_eta_diff_asym.png', dpi=300, bbox_inches='tight' )
#%% some snapshots of the surface elevation at several instants
fig, ax = plt.subplots(1)
for j in range(0,mpl):
jt = int( np.rint( np.float64(j) / np.float64(mpl-1) * np.float64(m_f-1) ) )
ax.plot( r_f, eta_f[:,jt], label=r'$t$ = {0:.3f}'.format(t_f[jt]) )
plt.gca().set_prop_cycle(None)
for j in range(0,mpl):
jt = int( np.rint( np.float64(j) / np.float64(mpl-1) * np.float64(m_f-1) ) )
if j==0:
ax.plot( r_f, eta_asym[:,jt], '--', label=r'approximation' )
else:
ax.plot( r_f, eta_asym[:,jt], '--' )
ax.grid
ax.axis( [ 0, np.max(r_f), -0.6, 2.2 ] )
ax.set_xlabel( r'$r$' )
ax.set_ylabel( r'$\eta(r,t)$' )
ax.set_title( r'surface elevation at several instants' )
lgd = ax.legend( loc='center left', bbox_to_anchor=(1.0, 0.5) )
plt.show(block=False)
fig.set_size_inches( 12, 5, forward=True )
plt.savefig( 'fig.sol/swe_ani_2D_eta_snap.pdf',
bbox_extra_artists=(lgd,), bbox_inches='tight' )
#%% snapshots to check self-similar behaviour
fig, ax = plt.subplots(1)
ax.plot( [-6, 3], [0, 0], 'k-', linewidth=0.5 )
plt.gca().set_prop_cycle(None)
for j in range(0,mpl):
jt = int( np.rint( np.float64(j) / np.float64(mpl-1) * np.float64(m_f-1) ) )
if t_f[jt] >= 4 :
ax.plot( r_f-t_f[jt], np.sqrt(r_f)*eta_f[:,jt],
label=r'$t$ = {0:.3f}'.format(t_f[jt]) )
ax.plot( r_f-t_f[jt], np.sqrt(r_f)*eta_asym[:,jt], 'k--',
label=r'approximation', linewidth=1.0 )
ax.grid
ax.axis( [ -6, +3, -0.35, 0.7 ] )
ax.set_xlabel( r'$r-t$' )
ax.set_ylabel( r'$\sqrt{r}$ $\eta(r-t,t)$' )
ax.set_title( r'self-similar behaviour of surface elevation' )
lgd = ax.legend( loc='center left', bbox_to_anchor=(1.0, 0.5) )
plt.show(block=False)
fig.set_size_inches( 12, 5, forward=True )
plt.savefig( 'fig.sol/swe_ani_2D_eta_similarity.pdf',
bbox_extra_artists=(lgd,), bbox_inches='tight' )
#%% ready
print( '=== ready' )
plt.subplots(1) # needed to show the last figure in spyder
plt.show( block=False )
plt.close()
input( '--- hit \'Enter\' to close ...' )
plt.close( 'all' )
|
Data
| Python code for phase 2: animation in a rectangular basin |
|---|
#!/usr/bin/env python2.7
"""
Make an animation of the linear shallow-water equations in 2D
Based on the exact solution for axisymmetrical waves in:
G. F. Carrier and H. Yeh (2005)
Tsunami propagation from a finite source.
Computer Modelling in Engineering & Sciences,
vol. 10, no. 2, pp. 113-122
doi: 10.3970/cmes.2005.010.113
The dimensionless and linear shallow-water equations
in polar coordinates are:
d/dt^2 eta(r,t) - 1/r * d/dr( r * d/dr eta(r,t) ) = 0.
The initial conditions are a series of Gaussian humps, on
an equidistant grid in the (x,y)-plane. One Gaussian hump
released at t=t0 is given by the initial conditions:
eta(r,t0) = 2 * exp( -r^2 ), d/dt eta(r,t0) = 0.
"""
from __future__ import print_function
import matplotlib.pyplot as plt, mpl_toolkits.mplot3d
import numpy as np
import os
import subprocess
import time
import sys
from scipy.interpolate import RectBivariateSpline, UnivariateSpline
from matplotlib.colors import LightSource
from mayavi import mlab
# animation parameters
Lx = np.float64( 30. ) # domain size in x-direction
Ly = np.float64( 30. ) # domain size in y-direction
x0 = np.float64( 6.0 ) # x-coordinate of centre of splashes
y0 = np.float64( 6.0 ) # y-coordinate of centre of splashes
t0 = np.float64( 5.0 ) # time of splash
dta = np.float64( 0.2 ) # time step
nta = int( 751 ) # number of time steps
nx = int( 301 ) # spatial step in x-direction
ny = int( 301 ) # spatial step in y-direction
mkani = True # save animation to file
nte = int( 48 ) # no. of duplicate frames at end of animation
#%% load surface elevation data from file
print( '=== load results from file' )
data = np.load( 'mat.npz' ) #, n=n, m=m, dr=dr, dt=dt, eta=eta, res=res )
n = data['n']
m = data['m']
dr = data['dr']
dt = data['dt']
eta = data['eta']
res = data['res']
r = np.linspace( 0, (n-1)*dr, n, dtype=np.float64 )
t = np.linspace( 0, (m-1)*dt, m, dtype=np.float64 )
#%% create function to interpolate surface elevation for any r and t
rnow = np.float64()
tnow = np.float64()
rmax = np.max(r)
tmax = np.max(t)
msel = int( np.floor( ( rmax - 3.0 ) / dt ) )
if msel > m :
msel = m
tsel = (msel-1) * dt
print( '--- tsel = {0:.3f}'.format(tsel) )
# define spline interpolations
sim_ksi = r - tsel
sim_eta = np.sqrt(r) * eta[:,msel-1]
spl2_eta = RectBivariateSpline( r, t, eta )
spl1_eta = UnivariateSpline( sim_ksi, sim_eta, s=0 )
# plot self-similar form
fig, ax = plt.subplots(1)
ax.plot( [-tsel, +4], [0, 0], 'k-', linewidth=0.5 )
plt.gca().set_prop_cycle(None)
ax.plot( r-tsel, np.sqrt(r)*eta[:,msel-1] )
ax.grid
ax.axis( [ -tsel, +4, -0.35, 0.7 ] )
ax.set_xlabel( r'$r-t$' )
ax.set_ylabel( r'$\sqrt{r}$ $\eta(r-t,t)$' )
ax.set_title( r'self-similar behaviour of surface elevation' )
plt.show(block=False)
def eta_polar( args ) :
rnow = args[0]
tnow = args[1]
rshape = np.shape( rnow )
rr = np.ravel( rnow )
eta_now = np.zeros( np.shape( rr ), dtype=np.float64 )
# print( '--- shape of rr : {}'.format(np.shape(rr)) )
if tnow >= 0:
if tnow <= tsel : # interpolation
jj = np.where( rr <= rmax )
tt = tnow * np.ones( rr[jj].shape )
eta_now[jj] = spl2_eta( rr[jj], tt, grid=False )
else: # self-similar solution based on t=tsel
ksi = rr - tnow
jj = np.where( ( ksi > -tsel ) & ( ksi < (rmax-tsel) ) & ( rr > 0 ) )
# print( '--- length of jj : {0:d}'.format(np.size(jj)) )
eta_now[jj] = spl1_eta( ksi[jj] ) / np.sqrt(rr[jj])
eta_now = np.reshape( eta_now, rshape )
return eta_now
#%% create an animation with mayavi
print( '=== create mayavi animation' )
x = np.linspace( 0, Lx, nx )
y = np.linspace( 0, Ly, ny )
x, y = np.meshgrid( x, y )
z = np.zeros( ( ny, nx, nta ), dtype=np.float64 )
# compute number of copies of the domain needed
tmax = nta * dta - t0
repx = int( np.ceil( tmax / Lx ) )
repy = int( np.ceil( tmax / Ly ) )
print( '--- repetitions in x-dir : {0:d}'.format(repx) )
print( '--- repetitions in y-dir : {0:d}'.format(repy) )
# create the surface fields needed in the animation
print( '--- compute surface elevation as a function of time' )
start_time = time.time()
for jx in range(-repx,+repx+1) :
if jx % 2 == 0 :
xc = +x0 + jx*Lx # even
else :
xc = Lx-x0 + jx*Lx # odd
for jy in range(-repy,+repy+1) :
if jy % 2 == 0 :
yc = +y0 + jy*Ly # even
else :
yc = Ly-y0 + jy*Ly # odd
sys.stdout.write( '\r--- jx = {0:3d} ; jy = {1:3d}'.format(jx,jy) )
sys.stdout.flush()
rnow = np.sqrt( (x-xc)**2 + (y-yc)**2 )
for i in range(nta) :
tnow = np.float64(i)*dta - t0
params = ( rnow, tnow )
z[:,:,i] += eta_polar( params )
print( ' ' )
end_time = time.time()
print( '--- elapsed time for free-surface construction : {0:.3f} s'.format( end_time - start_time ) )
no_nans = np.count_nonzero(np.isnan(z))
no_infs = np.count_nonzero(np.isinf(z))
print( '--- number of NaN\'s in z(x,y,t): {0:d}'.format(no_nans) )
print( '--- number of inf\'s in z(x,y,t): {0:d}'.format(no_infs) )
time.sleep(5) # pause 5 seconds
# mayavi plot
fig = mlab.figure( size=(528,337), bgcolor=(1,1,0.9) )
Ld = np.sqrt( Lx**2 + Ly**2 )
surf = mlab.surf( x.T, y.T, z[:,:,0].T, colormap='Blues', warp_scale=4,
vmin=-2, vmax=+2 )
# Change the visualization parameters.
surf.actor.property.interpolation = 'phong'
surf.actor.property.specular = 0.1
surf.actor.property.specular_power = 100
surf.actor.property.ambient=0
mlab.view( azimuth=235, elevation=70, distance=0.9*Ld,
focalpoint=(0.35*Lx,0.25*Ly,0.0) )
# animation
print( '--- show animation (and plot to png-files)' )
@mlab.show
@mlab.animate( delay=10 )
def anim() :
cnt = True
while cnt :
for i in range(nta):
# print( '\r--- i = {0:5d}'.format(i), end='' )
tnow = np.float64(i)*dta - t0
znow = z[:,:,i] # eta_polar( rnow, tnow )
surf.mlab_source.scalars = znow.T
if mkani :
# create png-files
fname = os.path.join( 'fig.ani', 'ani_{0:04d}.png'.format(i) )
mlab.savefig( filename=fname )
if i == (nta-1) :
for j in range(nte) :
fname = os.path.join( 'fig.ani', 'ani_{0:04d}.png'.format(nta+j) )
mlab.savefig( filename=fname )
cnt = False
yield
anim()
# print( ' ' )
if mkani :
print( '--- create animation with ffmpeg' )
fps = int(24)
ffmpeg_fname = os.path.join( 'fig.ani', 'ani_%04d.png' )
prefix = 'ani'
cmd = 'ffmpeg -y -f image2 -r {} -i {} -c:v libvpx -crf 4 -b:v 1M {}.webm'.format(fps,ffmpeg_fname,prefix)
# cmd = 'ffmpeg -f image2 -r {} -i {} -vcodec mpeg4 -y {}.mp4'.format(fps,ffmpeg_fname,prefix)
print( '{0:s}'.format(cmd) )
subprocess.check_output(['bash','-c', cmd])
# Remove temp image files with extension
print( '--- delete png-files' )
[os.remove( os.path.join( 'fig.ani', f ) ) for f in os.listdir('fig.ani') if f.endswith('.png')]
|
Licencia
Yo, el titular de los derechos de autor de esta obra, la publico en los términos de la siguiente licencia:
Este archivo está disponible bajo la licencia Creative Commons Attribution-Share Alike 4.0 International.
- Eres libre:
- de compartir – de copiar, distribuir y transmitir el trabajo
- de remezclar – de adaptar el trabajo
- Bajo las siguientes condiciones:
- atribución – Debes otorgar el crédito correspondiente, proporcionar un enlace a la licencia e indicar si realizaste algún cambio. Puedes hacerlo de cualquier manera razonable pero no de manera que sugiera que el licenciante te respalda a ti o al uso que hagas del trabajo.
- compartir igual – En caso de mezclar, transformar o modificar este trabajo, deberás distribuir el trabajo resultante bajo la misma licencia o una compatible como el original.
Valoración
| Este archivo fue seleccionado como multimedia del día para el 08 diciembre 2025. La descripción asociada es la siguiente:
English: Analytical solution of the linearized shallow-water equations in a two-dimensional rectangular basin
Other languages
English: Analytical solution of the linearized shallow-water equations in a two-dimensional rectangular basin Slovenščina: Analitična rešitev lineariziranih enačb plitke vode v dvorazsežnem pravokotnem bazenu
|
Leyendas
Añade una explicación corta acerca de lo que representa este archivo
Elementos representados en este archivo
representa a
Algún valor sin elemento de Wikidata
10 abr 2018
Historial del archivo
Haz clic sobre una fecha y hora para ver el archivo tal como apareció en ese momento.
| Fecha y hora | Dimensiones | Usuario | Comentario | |
|---|---|---|---|---|
| actual | 13:47 10 abr 2018 | (3,67 MB) | wikimediacommons>Kraaiennest | change background color |
Usos del archivo
La siguiente página usa este archivo: