/** # The 2011 Tohoku tsunami The 11th March 2011 Tohoku tsunami was triggered by a fault rupture off the east coast of Japan. It is modelled here using a setup similar to that used for the [2004 tsunami](tsunami.c), where more comments can be found. A significant difference is that we use a much more realistic fault model obtained through seismic inversion of the actual earthquake. See [Popinet, 2012](/src/references.bib#popinet2012) for a detailed discussion of the pure Saint-Venant model, [Popinet, 2015](/Bibliography#popinet2015) for a discussion of the dispersive effects modelled using the Green--Naghdi equations and [Popinet, 2020](/Bibliography#popinet2020) for the application of the single-layer dispersive model. ## Results
![Animation of the wave elevation. Dark blue is -1 metre and less. Dark red is +2 metres and more. The domain is approximately 6000 $\times$ 8000 km.](tohoku/eta.mp4)(width="100%") ![Animation of the level of refinement. Dark blue is 5 (~250 km) and dark red is 13 (~1 km).](tohoku/level.mp4)(width="100%")
![Animation of the wave elevation. Detail for the Sendai region. The area shown is approximately 140 $\times$ 100 km. Dark blue is -5 metres and less. Dark red is +5 metres and more.](tohoku/eta-sendai.mp4)(width="100%") ![Detail for the Fukushima region.](tohoku/eta-fukushima.mp4)(width="100%")
![Detail for the Miyako region.](tohoku/eta-miyako.mp4)(width="100%") ![Detail for the Ofunato region.](tohoku/eta-ofunato.mp4)(width="100%")
~~~gnuplot Flooding in the Sendai, Ofunato and Fukushima districts set term pngcairo enhanced size 1024,1024 font ",10" set output 'flooding.png' set pm3d map set palette defined ( 0 0 0 0.5647, 0.125 0 0.05882 1, 0.25 0 0.5647 1, \ 0.375 0.05882 1 0.9333, 0.5 0.5647 1 0.4392, \ 0.625 1 0.9333 0, 0.75 1 0.4392 0, \ 0.875 0.9333 0 0, 1 0.498 0 0 ) set multiplot unset key set size ratio -1 set xrange [140.4:142.44] set yrange [37.01:39.11] set xlabel 'Longitude' set ylabel 'Latitude' set cbrange [0:30] splot 'flooding' u 1:2:($3 > 1e-3 ? ($4 < 0. ? $5 : $5 - $4) : 1e1000) set contour base set cntrparam levels discrete 0 set cntrlabel onecolor unset surface splot 'flooding' u 1:2:4 lt 3 lc rgb "#000000" lw 2 unset multiplot ! mogrify -trim +repage flooding.png ~~~ The following three figures highlight the importance of dispersive effects after one, two and three hours (see [Popinet, 2015](/Bibliography#popinet2015) for a discussion).
![Leading wave front after one hour](tohoku/zoom-60.png){width="100%"} ![Leading wave front after two hours](tohoku/zoom-120.png){width="100%"}
![Leading wave front after three hours](tohoku/zoom-180.png){width="50%"} ## Solver setup See [tsunami.c]() for more detailed explanations. If `GN` is defined we use the Green--Naghdi solver, otherwise the multilayer solver (hydrostatic if `HYDRO` is defined). To run the three cases use: ~~~bash make tohoku.tst tohoku-gn.tst tohoku-hydro.tst ~~~ */ #include "spherical.h" #if GN # include "green-naghdi.h" # define MGD mgD.i #else # include "layered/hydro.h" # if HYDRO # define MGD 0 # else # include "layered/nh.h" # define MGD mgp.i # endif # include "layered/perfs.h" scalar h; vector u; #endif #include "terrain.h" #include "okada.h" #define MAXLEVEL 13 #define MINLEVEL 5 #define ETAE 1e-2 // error on free surface elevation (1 cm) #define ETAMAXE 5e-2 // error on maximum free surface elevation (5 cm) int main() { // Earth radius in metres Radius = 6371220. [1]; // the domain is 73 degrees squared size (73.); // centered on 142,38 longitude,latitude origin (142. - L0/2., 38. - L0/2.); // acceleration of gravity in m/min^2 G = 9.81*sq(60.); // 32^2 grid points to start with init_grid (1 << MINLEVEL); /** For the Green-Naghdi solver we do only one iteration of the multigrid solver to speed things up. This does not change the solution. In the non-hydrostatic case, we add a cut-off breaking parameter ([Popinet, 2020](/src/references.bib#popinet2020)). */ #if GN TOLERANCE = HUGE; NITERMIN = 1; #else // !GN #if NH CFL_H = 0.5; // this is necessary for stability at level 13 breaking = 0.07; #endif #endif // !GN run(); } scalar etamax[]; int my_adapt() { #if QUADTREE scalar eta[]; foreach() eta[] = h[] > dry ? h[] + zb[] : 0; astats s = adapt_wavelet ({eta, etamax}, (double[]){ETAE,ETAMAXE}, MAXLEVEL, MINLEVEL); fprintf (stderr, "# refined %d cells, coarsened %d cells\n", s.nf, s.nc); return s.nf; #else // Cartesian return 0; #endif } /** ## Terrain databases We use both the ETOPO2 topography and [SRTM land data](https://en.wikipedia.org/wiki/Shuttle_Radar_Topography_Mission) for Japan. See the [*xyz2kdt* manual](http://gerris.dalembert.upmc.fr/xyz2kdt.html) to generate the ETOPO2 database. The SRTM database can be generated using the following script (which will need to be adapted as the USGS often changes its website) ~~~bash # SRTM_resultExport.csv from http://edcsns17.cr.usgs.gov/NewEarthExplorer/ # see also http://gerris.dalembert.upmc.fr/xyz2kdt.html files=`awk 'BEGIN{FS="\"|,"}{ if ($2!="ENTITY_ID") print $2;}' < SRTM_resultExport.csv | \ sed 's/SRTM3//g' | \ awk '{ print "http://dds.cr.usgs.gov/srtm/version2_1/SRTM3/Eurasia/" $1 ".hgt.zip" }'` for f in $files; do wget $f done cc `pkg-config glib-2.0 --cflags --libs` -Wall -O2 srtm2kdt.c -o srtm2kdt for f in *.zip; do p=`echo $f | sed 's/.*\([NS]\)\([0-9][0-9]\)\([WE]\)\([0-9][0-9][0-9]\)\.hgt\.zip/\1 \2 \3 \4/'` lat=`echo $p | awk '{if ($1 == "S") print -$2; else print $2;}'` lon=`echo $p | awk '{if ($3 == "W") print -$4; else print $4;}'` echo $f >> /dev/stderr unzip -c -q $f | ./srtm2kdt $lon $lat done | xyz2kdt -v $HOME/terrain/srtm_japan ~~~ with the following `strm2kdt.c` code: ~~~c #include #include #include #include #define NCOLS 1201 #define NROWS 1201 #define CELLSIZE (1./(NCOLS - 1)) #define NODATA_VALUE -32768 int main (int argc, char * argv[]) { double lat, lon; gint16 v, vs; int i, j; double xllcorner = atof (argv[1]); double yllcorner = atof (argv[2]); for (j = 0; j < NROWS; j++) { lat = yllcorner + CELLSIZE*(NROWS - 1 - j); for (i = 0; i < NCOLS; i++) { lon = xllcorner + CELLSIZE*i; assert (fread (&v, sizeof (gint16), 1, stdin)); vs = GINT16_FROM_BE (v); if (vs > 0) printf ("%.8f %.8f %d\n", lon, lat, vs); } // fprintf (stderr, "\rRow %d/%d ", j + 1, NROWS); } // fputc ('\n', stderr); return 0; } ~~~ ## Initial conditions */ event init (i = 0) { terrain (zb, "~/terrain/etopo2", "~/terrain/srtm_japan", NULL); if (restore (file = "restart")) conserve_elevation(); else { conserve_elevation(); foreach() h[] = max(0., - zb[]); /** The initial deformation is given by a long collection of small Okada subfaults, obtained from seismic inversion ([Popinet, 2012](/src/references.bib#popinet2012)). */ #include "tohoku/faults.h" } u.n[left] = - radiation(0); u.n[right] = + radiation(0); u.n[bottom] = - radiation(0); u.n[top] = + radiation(0); } /** ## Quadratic bottom friction */ event viscous_term (i++) { double C_f = 1e-4; foreach() { double a = h[] < dry ? HUGE : 1. + C_f*dt*norm(u)/h[]; foreach_dimension() u.x[] /= a; if (h[] > dry && h[] + zb[] > etamax[]) etamax[] = h[] + zb[]; } } /** ## Outputs */ event logfile (i++) { stats s = statsf (h); norm n = normf (u.x); if (i == 0) fprintf (stderr, "t i h.min h.max h.sum u.x.rms u.x.max dt mgD.i speed tn\n"); fprintf (stderr, "%g %d %g %g %g %g %g %g %d %g %ld\n", t, i, s.min, s.max, s.sum, n.rms, n.max, dt, MGD, perf.speed, grid->tn); } event snapshots (t += 15) { char name[80]; sprintf (name, "dump-%g", t); dump (name); } event flooding (t = 390) { FILE * fp = fopen ("flooding", "w"); output_field ({h,zb,etamax}, fp, box = {{140.4,37.01},{142.44,39.11}}, n = 512, linear = true); } event figures (t = 60; t <= 180; t += 60) { scalar m[], etam[]; foreach() { etam[] = eta[]*(h[] > dry); m[] = etam[] - zb[]; } char name[80]; sprintf (name, "eta-%g.png", t); output_ppm (etam, mask = m, min = -1, max = 2, file = name, n = 1024, linear = true, box = {{123,14},{177,55}}, opt = "-fill white -opaque black"); sprintf (name, "level-%g.png", t); scalar l[]; foreach() l[] = level; output_ppm (l, min = 5, max = 13, file = name, n = 1024, linear = false, box = {{123,14},{177,55}}); if (t == 60) output_ppm (etam, mask = m, min = -1, max = 2, file = "zoom-60.png", n = 1024, linear = true, box = {{140.6,30.8},{154.6,42}}, opt = "-fill white -opaque black"); else if (t == 120) output_ppm (etam, mask = m, min = -1, max = 2, file = "zoom-120.png", n = 1024, linear = true, box = {{151.8,27.56},{165.8,38.68}}, opt = "-fill white -opaque black"); else if (t == 180) output_ppm (etam, mask = m, min = -1, max = 2, file = "zoom-180.png", n = 1024, linear = true, box = {{158.8,24.25},{172.7,35.3}}, opt = "-fill white -opaque black"); } event movies (t += 0.5) { scalar m[], etam[]; foreach() { m[] = eta[]*(h[] > dry) - zb[]; etam[] = h[] < dry ? 0. : (zb[] > 0. ? eta[] - zb[] : eta[]); } output_ppm (etam, mask = m, min = -1, max = 2, n = 1024, linear = true, file = "eta.mp4"); output_ppm (etam, mask = m, min = -5, max = 5, n = 1024, linear = true, box = {{140.4,37.51},{142.44,38.61}}, file = "eta-sendai.mp4"); output_ppm (etam, mask = m, min = -5, max = 5, n = 1024, linear = true, box = {{140.5,36.53},{142.52,37.62}}, file = "eta-fukushima.mp4"); output_ppm (etam, mask = m, min = -5, max = 5, n = 1024, linear = true, box = {{141.32,39.42},{143.44,40.50}}, file = "eta-miyako.mp4"); output_ppm (etam, mask = m, min = -5, max = 5, n = 1024, linear = true, box = {{141.11,38.51},{143.19,39.60}}, file = "eta-ofunato.mp4"); scalar l = etam; foreach() l[] = level; output_ppm (l, min = MINLEVEL, max = MAXLEVEL, n = 1024, file = "level.mp4"); #if _OPENMP foreach() etam[] = pid(); double tmax = omp_get_max_threads() - 1; output_ppm (etam, max = tmax, n = 512, file = "pid.mp4"); #endif // _OPENMP } /** This file includes the locations of various wave gauges. */ #include "tohoku/gauges.h" event adapt (i++) my_adapt();