能登半島地震どんな地震？（速報）

## はじめに
1月1日の能登半島地震では多くの被害が出たことと思います。
一刻も早く日常に戻れることをお祈りしています。
防災を生業とするエンジニアとして、今回の地震がどんな地震だったか調査したので結果をお伝えします。今回使用したデータは[防災科学技術研究所](https://www.kyoshin.bosai.go.jp/kyoshin/)と[神戸海洋気象台](https://www.data.jma.go.jp/eqev/data/kyoshin/jishin/hyogo_nanbu/index.html)のデータを使わせていただきました。関係各位にお礼申し上げます。
なお、今回は速報のため、間違いがありましたらご指摘ください。

## 加速度波形
![Noto_EW.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691433/124f339b-ceb0-599f-cb5a-7eca9fa272f0.png)
図は今回の地震で最も加速度が大きかったK-NET富来のEW（東西方向）成分の加速度波形です。ピークが複数あり、ニュースで言われているような群発地震であることがわかります。最大加速度が2700gal程度あり、東北地方太平洋沖地震と同程度の地震と思われます。

## 加速度応答スペクトル
加速度応答スペクトルは各周期ごとの最大加速度応答をプロットしたものです。建物には固有周期があり、固有周期と地震動の最大加速度応答が大きい周期が一致すると、被害が大きくなります。
![ResAcc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691433/7de679a1-8cdc-3e41-0afe-7c66bafe1401.png)
上図の青線が先程のK-NET富来の結果です。比較しているのは、兵庫県南部地震の神戸海洋気象台観測記録（赤）、東北地方太平洋沖地震のK-NET築館の観測記録（緑）、熊本地震のK-NET益城の観測記録（オレンジ）です。富来と築館は短周期側が非常に大きくなっている海溝型地震の特徴を示しています。一方、神戸海洋気象台とK-NET益城は周期0.2〜0.5程度が大きくなる内陸型地震の特徴を示しています。建物の固有周期は一般家屋で0.5程度で高層ビルになるほど固有周期は大きくなります。よって、建物への影響は兵庫県南部地震や熊本地震の方が大きいといえます。

## 非線形地震応答解析
地震応答解析はその名のとおり地震動に対して運動方程式を解き、構造物がどのような応答をするか調べるものです。ここでは、下図のようなモデルで降伏震度を設定する非線形解析を行います。降伏震度を超えると残留変位が発生します。今回は木造建築相当を想定し、固有周期0.5sec、建物の減衰率5%、降伏震度0.4復元力モデルにはバイリニアモデルを用いました。
![地震応答解析.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691433/6511d89e-dcf2-d8cf-c610-da6e7ae7737d.png)
![Noto_EW_SDOF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691433/d15ec07b-d9f3-e774-7a43-58b35639edd1.png)
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691433/0be74ef9-c6e6-6f0e-9ad2-5eff16d8343b.png)
上図の結果から、変位は小さいですが、降伏震度を超え残留変位が生じていることがわかります。最初のピークで降伏震度を超えており、それ以降のピークでは残留変位は大きくなっていないようです。以上より、家屋などを想定すると、地震動による被害は兵庫県南部地震や熊本地震の方が被害は大きいと思います。しかし、今回は火災と津波という兵庫県南部地震と東北地方太平洋沖地震の両方の要素があり、被害が大きくなったようです。

## おわりに
もう少しすると詳細調査の結果が出てくると思います。その成果は今後に生かされるとして、今はとにかくこれ以上被害が出ないことを願っています。
最後に今回使用したPythonプログラムを載せておきます。

```python:加速度応答スペクトルの計算
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import time
import math
from tqdm import tqdm


def nmk(beta, am, ac, ak, dt, ff, acc1, vel1, dis1):
    acc2 = (ff-ac*(vel1+0.5*dt*acc1)-ak*(dis1+dt*vel1 +
            (0.5-beta)*dt*dt*acc1))/(am+ac*0.5*dt+ak*beta*dt*dt)
    vel2 = vel1+0.5*dt*(acc1+acc2)
    dis2 = dis1+dt*vel1+(0.5-beta)*dt*dt*acc1+beta*dt*dt*acc2
    return acc2, vel2, dis2


def inputdt():
    file = pd.read_csv("KOBEJMA.csv")
    t = file['TIME'].values
    acc = file['NS'].values
    return t, acc


def main_sdof():
    fout = open('output.csv', 'w')
    print('Period', ',', 'ResAcc.', file=fout)
    start = time.time()
    # Definition of time and acceleration
    t, acc = inputdt()
    ainp = np.array(acc)
    dt = 0.02
    # Parameter setting
    h = 0.05
    am = 1.0
    f = -am*ainp

    # Numerical integration
    md = 2
    ddt = dt/float(md)
    beta = 1.0/6.0
    rac = np.zeros(len(t))
    vel = np.zeros(len(t))
    dis = np.zeros(len(t))
    T = np.zeros(100)
    AMAX = np.zeros(100)
    acc1 = 0.0
    vel1 = 0.0
    dis1 = 0.0
    pa = math.log10(0.1)
    pb = math.log10(5.0)
    pc = (pb-pa)/99.0
    pd = pa
    for k in tqdm(range(0, 100)):
        time.sleep(0.01)
        pe = 10.0**pd
        T1 = pe
        pd = pd+pc
        ak = 4.0*np.pi**2.0*am/T1**2.0
        # print(ak)
        ac = 2.0*h*np.sqrt(ak*am)
        T[k] = T1
        # print(ac)
        for i in range(0, len(t)):
            f1 = 0.0
            if 1 <= i:
                f1 = f[i-1]
            f2 = f[i]
            fm = f1+(f2-f1)
            acc2, vel2, dis2 = nmk(beta, am, ac, ak, ddt, fm, acc1, vel1, dis1)
            acc1 = acc2
            vel1 = vel2
            dis1 = dis2
            # fout=open(fnameW,'a')
            # print(acc1,file=fout)
            # fout.close()
            rac[i] = acc1+ainp[i]
            vel[i] = vel1
            dis[i] = dis1
        AMAX[k] = np.max(rac)
        print(T[k], ',', AMAX[k], file=fout)
    print('{0:10.3f}(sec)'.format(time.time()-start))


if __name__ == '__main__':
    main_sdof()

```

```python:非線形地震応答解析
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import time
import math


def resilience(fy, delty, ak, gm, dis1, ndis2, qy1):
    ql = qy1+ak*(ndis2-dis1)
    qu = fy+gm*ak*(ndis2-delty)
    qd = -fy+gm*ak*(ndis2+delty)
    if ql > qu:
        qy2 = qu
    elif ql < qd:
        qy2 = qd
    else:
        qy2 = ql
    return qy2


def osmethod(fy, delty, gm, am, ac, ak, dt, fm, acc1, vel1, dis1, ndis1, qy1):
    dndis = dt*vel1+dt*dt*acc1/4.0
    ndis2 = dis1+dndis
    qy2 = resilience(fy, delty, ak, gm, dis1, ndis2, qy1)
    dnf = qy2-qy1-ak*(ndis2-ndis1)
    ddis = ((am*(acc1+4.0*vel1/dt)+ac*vel1)-qy1-ak *
            (dis1-ndis1)-dnf+fm)/(4.0*am/dt/dt+2.0*ac/dt+ak)
    dvel = -2.0*vel1+2.0*ddis/dt
    dacc = -2.0*acc1-4.0*vel1/dt+4.0*ddis/dt/dt
    dis2 = dis1+ddis
    vel2 = vel1+dvel
    acc2 = acc1+dacc
    return ndis2, qy2, dis2, vel2, acc2


def input():
    file = pd.read_csv("Noto_EW.csv")
    t = file['Time'].values
    acc = file['Acc.'].values
    t_c = np.zeros(len(t) * 10)
    acc_c = np.zeros(len(acc) * 10)

    for i in range(0, len(t)):
        for j in range(0, 10):
            k = i * 10 + j
            t_c[k] = 0.001 * k + 0.001
            acc_c[k] = acc[i] / 10.0 * j
    return t_c, acc_c


def main_sdof():
    start = time.time()
    # Definition of time and acceleration
    t, acc = input()
    ainp = np.array(acc)
    dt = 0.001
    # Parameter setting
    g = 9.80665  # Gravitational acceleration
    h = 0.05  # Damping factor
    am = 100.0  # Mass
    T = 0.5  # Natural period
    gm = 0.02  # Stiffiness deterioration
    ak = 4.0*np.pi**2.0*am/T**2.0  # Initial stiffiness
    ac = 2.0*h*np.sqrt(ak*am)  # Damping coefficient
    khy = 0.4  # Yield seismic intensity
    fy = am*g*khy  # Yield stress
    delty = fy/ak  # Yield displacement

    # Numerical integration
    rac = np.zeros(len(t))
    vel = np.zeros(len(t))
    dis = np.zeros(len(t))
    ndis = np.zeros(len(t))
    qy = np.zeros(len(t))
    acc1 = 0.0
    vel1 = 0.0
    dis1 = 0.0
    ndis1 = 0.0
    qy1 = 0.0
    for i in range(0, len(t)):
        fm = -am*ainp[i]*0.01
        ndis2, qy2, dis2, vel2, acc2 = osmethod(
            fy, delty, gm, am, ac, ak, dt, fm, acc1, vel1, dis1, ndis1, qy1)
        acc1 = acc2
        vel1 = vel2
        dis1 = dis2
        ndis1 = ndis2
        qy1 = qy2
        rac[i] = acc1+ainp[i]
        vel[i] = vel1
        dis[i] = dis1
        ndis[i] = ndis1
        qy[i] = qy1
    print('{0:10.3f}(sec)'.format(time.time()-start))

    # Show drawing
    fig = plt.figure()
    plt.subplot(2, 1, 1)
    plt.plot(t, ainp, linewidth=0.5, color='black')
    plt.ylabel('Acceleration (gal)')
    plt.subplot(2, 1, 2)
    plt.plot(t, dis, linewidth=0.5, color='red')
    plt.xlabel('Time (s)')
    plt.ylabel('Displacement (m)')
    plt.show()

    fig = plt.figure()
    plt.subplot(1, 1, 1)
    plt.plot(dis, qy, 'b-')
    plt.xlabel('Displacement (m)')
    plt.ylabel('Force (kN)')
    plt.show()


if __name__ == '__main__':
    main_sdof()

```