地学現象の多くは実験室ではほとんど再現できない,大きな時間・空間スケールのものが普通です。そのため,観測された事象の空間分布をモデル化し,時系列解析が行われますが,現在ではコンピューターをつかったシミュレーションが行われ,それによる理論と観測結果の比較研究や,予測による防災などにも利用され,非常に有力な手法となっています。ただし,中学高校の授業で取り上げるのは,やや高度な数学やコンピューターに関する知識が必要になるので難しいかもしれません。とはいえ,その原理など,ある程度理解しておくことも重要になっていると思います。昨年たまたま,教材化している例を,教員免許の更新講習で経験しましたので,十分理解できたとは言えないのですが,参考になればと思い紹介したいと思います。講習を受けたのは,2021年度のJpGU(日本地球惑星科学連合)主催による「数値シミュレーションで学ぶ津波の基礎」(講師;東京大学付属海洋教育センター准教授,丹羽淑博氏による)です。

講習講義資料のPPTから(丹羽淑博2011「津波シミュレーションを使った海洋教育」)掲載許諾済み
基本となる運動方程式
偏微分方程式を差分近似式で表す
水深の変化を考慮した時

これらの説明の内容を理解するには,微分方程式などに習熟していなければなりません。私も理解は十分とは言えませんが,要は一番下ような(黄色部分)の漸化式をコンピューターによって逐次計算させることができる(離散化させる)ということが,コンピューターシミュレーションのポイントであると思います。講習では,プログラミング言語として,Fortran(gfortran)が使われ,アニメーションにはGnuplotというソフトが使われましたが,私の使い慣れているPython に実習で配布されたFortranのコードを,移植してアニメーションにしたものを順に載せておきます。

海洋を横長の水槽と仮定した水面高の変化と水の運動速度を示す(Tsunami01)
水深を計算に組み込んだ場合とその海底地形の例(Tsunami02)

津波の伝わる速さは水深hの平方根に比例します。沖合に戻る波の速さの変化に注目

上の場合の海岸付近の拡大(境界条件を強制)Tsunami02-2
陸域での津波の挙動も再現したもの(Tsunami03)

以上の参考資料:
丹羽淑博・佐藤俊一(2021):数値シミュレーションで学ぶ 津波の物理の基礎.
日本地球惑星科学連合2021年度教員免許状更新講習「数値シミュレーションで学ぶ津波の基礎」(2021年12月27日実施)
https://www.cole.p.u-tokyo.ac.jp/common/img/mt/events/pdf/20110827_niwa.pdfも参考にしました。

 以下は,講習で配布されたgfortranのコードをPythonで書き直したものです。

Pythonによる計算プログラム(Tsunami01)
 差分近似式に対応する変数
過去        U(t—△t)   →    ub
現在         U(t)   →    up
未来        U(t+△t)   →    uf
過去        Z(t—△t)  →     zb
現在         Z(t)      →   zp
過去        Z(t+△t)    →     zf

#-------------------------------------------------------------------------------
# Name:        Tsunami01
#
# Purpose:     水槽内の水の水位と流速の変化(津波のシミュレーション)
#
#-------------------------------------------------------------------------------
import math
import numpy as np
import matplotlib.pyplot as plt
# from matplotlib.animation import FuncAnimation
from matplotlib.animation import ArtistAnimation
#---グリッド分割数-------
iq = 500
#----パラメータ値を設定-------------
up = [0]*(iq+1)
zp = [0]*(iq+1)
uf = [0]*(iq+1)
ub = [0]*(iq+1)
zb = [0]*(iq+1)
zf = [0]*(iq+1)
xlist = [[0 for i in range(iq+1)] for j in range(240)]
zlist = [[0 for i in range(iq+1)] for j in range(240)]
ulist = [[0 for i in range(iq+1)] for j in range(240)]
depth = 200.           #水深 (m)
width = 100.*1000.     #モデル海洋の幅 (m)
grav = 9.8             #重力加速度  (m/s^2)
#------------------------------
time_end = 2.*60.*60.  #計算時間(sec)
time_out = 30.         #データ出力時間間隔(sec)
#----------------------------
dx = width/iq      #空間グリッドサイズ
dt = 1             #時間ステップサイズ
#--初期値の設定-------
for i in range(iq+1):
    zp[i] = math.exp(-(i-iq/2)**2/(iq/20)**2)

nend = int(time_end/dt)  #時間ステップ数
nout = int(time_out/dt)  #データ出力ステップ間隔
nc = 0
#----------時間ループ n=0,nendまで繰り返す----
for n in range(0,nend):

#**************************************************************
#-----最初のステップのみ現在ステップから未来ステップ値を計算(前方差分)----
    if n==0 :
        for i in range(1,iq):
            uf[i] = up[i] - grav*(dt/dx)*(zp[i+1] - zp[i])

        for i in range(2,iq):
            zf[i] = zp[i] - depth*(dt/dx)*(up[i] - up[i-1])

#-----過去ステップ値と現在ステップ値から未来ステップ値を計算(中央差分)----
    if n>=1 :
        for i in range(1,iq):
            uf[i] = ub[i] - 2*grav*(dt/dx)*(zp[i+1] - zp[i])

        for i in range(2,iq):
            zf[i] = zb[i] - 2*depth*(dt/dx)*(up[i] - up[i-1])

#---境界条件----------
    uf[1] = 0.
    uf[iq-1] = 0.
#----計算の安定化のためのおまじない(Asselin filter)---
    if n>=1 :
        eps=0.01
        for i in range(iq):
            up[i] = up[i] + eps*(uf[i] - 2*up[i] + ub[i])

        for i in range(iq+1):
            zp[i] = zp[i] + eps*(zf[i] - 2*zp[i] + zb[i])

 #---noutステップごとに図のデータとして保持 --------------
    if n % nout == 0:
        for i in range(iq+1):
            xlist[nc][i] = dx*(i-2)/1000
            zlist[nc][i] = zp[i]
            ulist[nc][i] = up[i]

        nc += 1

#------ステップを進める。現在ステップ値を過去ステップ値に、
#      未来ステップ値を現在ステップ値に----
    for i in range(iq):
        ub[i] = up[i]
    for i in range(iq+1):
        zb[i] = zp[i]
    for i in range(iq):
        up[i] = uf[i]
    for i in range(iq+1):
        zp[i] = zf[i]

#---------アニメーション
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
plt.subplots_adjust(hspace=0.4)
artists = []
for n in range(nc):
    zline, = ax1.plot(xlist[n], zlist[n],"blue")
    ax1.set_title("surface elevation (m)  ")
    vline, = ax2.plot(xlist[n], ulist[n],"blue")
    ax2.set_title("horizontal velocity (m/s)")

    artists.append([zline,vline])

anim = ArtistAnimation(fig, artists, interval = 100, repeat_delay = 600)

# anim.save("Tsunami1.gif", writer="imagemagick")
plt.show()