2024-12-25 【試験研究】第一原理計算セットアップ(7)VASP 6.5.0インストール

VASP.6.5

  • 2024å¹´12月20æ—¥(金)に、VASP Software GmbH ([email protected]) から、"VASP 6.5 released" の案内が来た。
  • すでにVASPのライセンスをもつ人はupgradeできる。私の場合はVASP 6.4のupgrade後なので無料でアップグレードできる。
  • 特徴は下記のとおり。
    • 電子格子相互作用 (electron-phonon coupling) の計算ができる。
    • VASP Pluginsの導入
    • Bethe-Salpeter Equation (ベーテ・サルピータ方程式) の取り扱い
    • その他
      • 交換相互作用関数の追加。MS-PBEI, TASK, xc-B-fieldなど。
      • Coulomb kernel truncationの計算の導入。ダイポール、2D物質や表面の計算に有効。論文は執筆中なので詳細は不明。
      • 機械学習関連の計算の誤差低減、他のファイル形式とのインターフェース改善、バグ修正など。

VASP.6.5 構築手順

  • サポートプログラムのチェック
    • 6.4.3をインストールしているのならば、作業はない。6.5.0から新規インストールの場合は、6.4.3の手順をまねる。szip, libxcは省略してよい。
    • hdf5はaptでも入るが、コンパイルして生成する必要がある。1.14.4を使うのが良い。
      • 1.14.5がリリースされていたが、./configureでfortran用ライブラリが生成されない、--prefixで指定したインストールディレクトリが存在しないときにmkdirされないなど、今のところ使い物にならない。
    • zlibはzlib 1.3.1 (January 22, 2024) のままだった。zlibはUbuntuにデフォルトで入っているものを使ってもよいが、インストールしてもよい。
    • szipは特に必要ない。インストールするのなら、AECをインストールすることをHDFが推奨している。
    • libxcは入れなくてもよい。VASPのmakefileのひな形から姿を消している。あまりメリットがないのだろう。
    • wannier90はバージョンアップがなかった。試していないが、aptでも入るようだ。

AEC (szlib)

HDF5は圧縮のためにgzip形式を使っているが、szlib形式も使われる可能性がある。 念のためインストールしておく。 なお、HDF5にszlibを入れるかどうかは、HDF5コンパイルの際の configure で --with-szlib にて指定すると入る。

なお、szlib形式については、HDF5のダウンロードページに、「HDF5はHDF5-1.10.7からAECライブラリをSZIP圧縮に使用している。AECはSZIPの実装を行った使用制限のないオープンソースである。SZIPを使ってもHDF5は動作するが、我々はAECライブラリを使うことを推奨する。」と記されている。 AEC (libaec) は、German Climate Computing Center が開発しており、 gitからダウンロードできる。HDF5の開発チームは https://github.com/MathisRosenhauer/libaecからダウンロードしている。 ここにアクセスするとgithubに飛ぶが、右上にあるCodeというところに飛んでzip形式をダウンロードすると良い。 cmakeが必要なので、which cmakeとしてcmakeの有無を確認し、なければsudo apt install cmakeとしてインストールする。

https://github.com/MathisRosenhauer/libaec/archive/refs/heads/master.zip
unzip master.zip
cd libaec-master
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
make
make test
sudo make install

これで、/usr/local/lib/libaec.soなどがインストールされる。

VASP.6.5.0ダウンロード

  • vasp.6.5.0.tar.gzをダウンロードすると7.5 MBytesである。

展開と準備

tar zxvf vasp.6.5.0.tar.gz
cd vasp.6.5.0
cp arch/makefile.include.intel makefile.include

makefile.include

makefile.include.intelの最下行に、# For machine learning library vaspml (experimental)というのがあり、コメントアウトしてコンパイルオプションを選ぶようになっていた。とりあえず、コメントアウトのままとする。

# For machine learning library vaspml (experimental)
#CPP_OPTIONS += -Dlibvaspml
#CPP_OPTIONS += -DVASPML_USE_CBLAS
#CPP_OPTIONS += -DVASPML_USE_MKL
#CPP_OPTIONS += -DVASPML_DEBUG_LEVEL=3
#CXX_ML      = mpiicpc -cxx=icpx
#CXXFLAGS_ML = -O3 -std=c++17 -Wall
#INCLUDE_ML  =

makefile.includeの変更点は下記のとおり。

FC          = mpiifx
FCL         = mpiifx
CC_LIB    = icx
CXX_PARS    = icpx

# HDF5-support (optional but strongly recommended)
CPP_OPTIONS+= -DVASP_HDF5
HDF5_ROOT  ?= /usr/local/hdf5-1.14.4
LLIBS      += -L$(HDF5_ROOT)/lib -lhdf5_fortran
INCS       += -I$(HDF5_ROOT)/include

# For the VASP-2-Wannier90 interface (optional)
CPP_OPTIONS    += -DVASP2WANNIER90
WANNIER90_ROOT ?= /usr/local/vasp/tools
LLIBS          += -L$(WANNIER90_ROOT)/lib -lwannier

makeとmake test

  • time make DEPS=1 -j4などと、timeをつけているのは実行時間を計測するため。計測しないのなら不要。
  • testのクリーンアップは、cd test suite; make cleantest; cd ..とする。
  • testsuite/runtest にいくつかある python ã‚’ python3 に変更する。
time make DEPS=1 -j4
time make test
time make test_all

test_allの結果

  • 所要時間は、135分=2時間15分でした。テスト内容が増えているようです。
  • テストに失敗したのは下記のテストです。一番下のエラーは6.4.3のときからです。誘電関数がうまく求まっていないようです。その他は、問題のないエラー(エラーになって当然のエラー)です。
    • bulk_BN_PBE_Libxc : libxcを入れていないため
    • bulk_BN_PBExSCANc_Libxc : libxcを入れていないため
    • bulk_BN_SCAN_Libxc : libxcを入れていないため
    • elphon_lif_allinone : testsuite/runtestのpythonã‚’python3にしていないため
    • elphon_si_allinone : testsuite/runtestのpythonã‚’python3にしていないため
    • mlwf_lif_scdm_optics : VASP.6.4.3のときからエラーが出る

【試験研究】RigakuのX線回折データファイル形式のRASとRASXをテキストデータに変換するPythonプログラム, Converting RAS and RASX files generated by Rigaku XRD machines to text files with measurement conditions as comments.

 Rigakuの薄膜用および粉末用X線回折装置のデータ記録には、現在、RASXファイルというファイル形式が採用されています。その特徴は下記の点です。

  • RASXファイルの実体はzipファイルである。拡張子を .rasx から .zip に変更してダブルクリックなどをすると分かる。
    • ファイルをバイナリで見ることでもすぐに分かります。私が行ったのはこちら。
  • RASファイルでは、複数の測定が単一のテキストファイルにブロック分けされて記録されていたが、RASXではフォルダに分かれて記録されている。
  • データはxmlで記録されている。
  • リガクからRASXã‚„RAS形式をCSVに変換するプログラムが提供されている。しかし、測定条件がデータの中にコメントとして記録されない。

特に最後の点に問題を感じ、RASXファイルをテキストデータに変換するPythonプログラムを書きました。RASファイルも扱えます。測定条件をすべて書き出しているわけではありませんので、必要に応じて改造してください。使い方と特徴は下記のとおりです。

  • Pythonモジュールとして、zipfile, xml が必要ですので、pipなりcondaなりで入れておいてください。
  • RAS, RASXファイルがあるフォルダにこのプログラム (ras2dat_all.py) を置く。
  • 実行すると、プログラムのあるフォルダのRAS, RASXデータをすべて .dat に置き換えるという単機能動作をする。
    • ファイルダイアログが出てきたりはしない。昔は出てくるようにしていたが、面倒ということに気が付いた。
    • 強制なので、残したい .dat ファイルがある場合はご注意ください。
  • 測定条件はファイルの最初に、行頭に # がついた形で入っています。
    • たいていのグラフ描画ソフトではコメント行として読み飛ばされるはずです。
import os
import zipfile
import xml.etree.ElementTree as ET

def getFilename():
    root = tkinter.Tk()
    root.withdraw()
    fTyp = [("Rigaku Ascii", "ras")]
    iDir = os.path.abspath(os.path.dirname(__file__))
    filename = tkinter.filedialog.askopenfilename(filetypes=fTyp, initialdir=iDir)
    return filename

# get item from header
def getItem(str, lines):
    item = ""
    str += " "
    for line in lines:
        if line[0:len(str)] == str:
            item = line[len(str)+1:].replace('"', '')
    return item

def _ras2dat(headlines, datalines):
    output_data = []
    tmp1 = getItem("*MEAS_SCAN_START_TIME", headlines)
    tmp2 = getItem("*MEAS_SCAN_END_TIME", headlines)
    output_data.append("# Scan Date   : {0} - {1}\n".format(tmp1, tmp2))
    tmp1 = getItem("*FILE_SAMPLE", headlines)
    output_data.append("# File Sample : {0}\n".format(tmp1))
    tmp1 = getItem("*FILE_MEMO", headlines)
    output_data.append("# File Memo   : {0}\n".format(tmp1))
    output_data.append("# User Comment : \n")
    tmp1 = getItem("*MEAS_COND_OPT_NAME", headlines)
    output_data.append("# Optical     : {0}\n".format(tmp1))
    tmp1 = getItem("*HW_COUNTER_SELECT_NAME", headlines)
    output_data.append("# Counter     : {0}\n".format(tmp1))
    for ii in range(100):
        tmp1 = getItem("*MEAS_COND_AXIS_NAME-{}".format(ii), headlines)
        if len(tmp1) == 0:
            continue
        tmp2 = getItem("*MEAS_COND_AXIS_STATE-{}".format(ii), headlines)
        tmp3 = getItem("*MEAS_COND_AXIS_POSITION-{}".format(ii), headlines)
        tmp4 = getItem("*MEAS_COND_AXIS_UNIT-{}".format(ii), headlines)
        tmp5 = getItem("*MEAS_COND_AXIS_OFFSET-{}".format(ii), headlines)
        tmp6 = getItem("*MEAS_COND_AXIS_RESOLUTION-{}".format(ii), headlines)
        tmp2 = " (Scan)" if tmp2 == "Scan" else ""
        tmp6 = "resolution {0} {1}".format(tmp6, tmp4) if len(tmp6) != 0 else ""
        output_data.append("# Condition {0:24} : {1} {2} (offset {3}), {4}\n".format(tmp1+tmp2, tmp3, tmp4, tmp5, tmp6))
    tmp1 = getItem("*MEAS_SCAN_AXIS_X", headlines)
    output_data.append("# Data X axis : {0}\n".format(tmp1))
    tmp1 = getItem("*MEAS_SCAN_MODE", headlines)
    output_data.append("# Scan mode   : {0}\n".format(tmp1))
    tmp1 = getItem("*MEAS_SCAN_START", headlines)
    tmp2 = getItem("*MEAS_SCAN_UNIT_X", headlines)
    output_data.append("# Scan start  : {0} {1}\n".format(tmp1, tmp2))
    tmp1 = getItem("*MEAS_SCAN_STOP", headlines)
    tmp2 = getItem("*MEAS_SCAN_UNIT_X", headlines)
    output_data.append("# Scan stop   : {0} {1}\n".format(tmp1, tmp2))
    tmp1 = getItem("*MEAS_SCAN_STEP", headlines)
    scan_step = float(tmp1)   # deg/step
    tmp2 = getItem("*MEAS_SCAN_UNIT_X", headlines)
    output_data.append("# Scan step   : {0} {1}\n".format(tmp1, tmp2))
    tmp1 = getItem("*MEAS_SCAN_SPEED", headlines)
    tmp2 = getItem("*MEAS_SCAN_SPEED_UNIT", headlines)
    output_data.append("# Scan speed  : {0} {1}\n".format(tmp1, tmp2))
    scan_speed = float(tmp1) / 60.0    # deg/min -> deg/sec
    count2cps = scan_step / scan_speed   # sec/step
    output_data.append("# Scan time per step : {0:.3f}\n".format(count2cps))
    tmp1 = getItem("*MEAS_SCAN_UNIT_Y", headlines)
    output_data.append("# Scan Y unit : {0}\n".format(tmp1))
    tmp1 = getItem("*MEAS_SCAN_START_TIME", headlines)
    tmp2 = getItem("*MEAS_SCAN_END_TIME", headlines)
    tmp_date, tmp_starttime = tmp1.split(' ')
    tmp_endtime = tmp2.split()[1]
    output_data.append("# Scan Date and Time: {0} {1} - {2}\n".format(tmp_date, tmp_starttime, tmp_endtime))
    #-------------------------------------------------
    for line in datalines:
        tmp1, tmp2, tmp3 = line.split(' ')
        output_data.append("{0} {1:.3f} {2} {3}\n".format(tmp1, float(tmp2) * float(tmp3) / count2cps, tmp2, tmp3))
    return output_data

def ras2dat(filename):
    # read file 
    with open(filename, 'r') as fh:
        datalines = fh.readlines()
    for i in range(len(datalines)):
        datalines[i] = datalines[i].rstrip('\n')
    if datalines[0] != '*RAS_DATA_START':
        print("Not a RAS file.")
        return
    status = "none"
    blocks = []
    for dataline in datalines:
        if dataline == '*RAS_HEADER_START':
            status = "header"
            headblock = []
            continue
        if dataline == '*RAS_HEADER_END':
            status = "none"
            continue
        if dataline == '*RAS_INT_START':
            status = "data"
            datablock = []
            continue
        if dataline == '*RAS_INT_END':
            status = "none"
            blocks.append(_ras2dat(headblock, datablock))
            del headblock, datablock
            continue
        if status == "header":
            headblock.append(dataline)
        if status == "data":
            datablock.append(dataline)
    return blocks

def _rasx2dat_head(root):
    outstr = []
    #----------- General Information ----------
    outstr.append("# [General Info] Operator: {}\n".format(root.find('./GeneralInformation/Operator').text))
    outstr.append("# [General Info] {0} Ver.{1}\n".format(root.find('./GeneralInformation/Type').text, root.find('./GeneralInformation/Version').text))
    outstr.append("# [General Info] Memo: {}\n".format(root.find('./GeneralInformation/Memo').text))
    outstr.append("# [General Info] System Name: {}\n".format(root.find('./GeneralInformation/SystemName').text))
    #---------- Scan Information ----------
    outstr.append("# [Scan Info] Axis Name:  {}\n".format(root.find('./ScanInformation/AxisName').text))
    outstr.append("# [Scan Info] Axis Mode:  {}\n".format(root.find('./ScanInformation/Mode').text))
    outstr.append("# [Scan Info] Scan Start: {0} {1}\n".format(root.find('./ScanInformation/Start').text, root.find('./ScanInformation/PositionUnit').text))
    outstr.append("# [Scan Info] Scan Stop:  {0} {1}\n".format(root.find('./ScanInformation/Stop').text, root.find('./ScanInformation/PositionUnit').text))
    outstr.append("# [Scan Info] Scan Step:  {0} {1}\n".format(root.find('./ScanInformation/Step').text, root.find('./ScanInformation/PositionUnit').text))
    outstr.append("# [Scan Info] Scan Speed: {0} {1}\n".format(root.find('./ScanInformation/Speed').text, root.find('./ScanInformation/SpeedUnit').text))
    outstr.append("# [Scan Info] Scan Start Time: {0}\n".format(root.find('./ScanInformation/StartTime').text))
    outstr.append("# [Scan Info] Scan End Time:   {0}\n".format(root.find('./ScanInformation/EndTime').text))
    outstr.append("# [Scan Info] Attenuator Auto: {0}\n".format(root.find('./ScanInformation/AttenuatorAutoMode').text))
    #---------- Hardware Configurations ----------
    hw_root = root.findall('./HWConfigurations/Categories/Category')
    for hw in hw_root:
        outstr.append("# [HW Config] {0}: {1}\n".format(hw.attrib['Name'], hw.attrib['SelectedUnit']))
    outstr.append("# [Xray] Type: {0}, Focus Type: {1}, Focus Size: {2}\n".
        format(root.find('./HWConfigurations/XrayGenerator/Type').text, root.find('./HWConfigurations/XrayGenerator/FocusType').text, root.find('./HWConfigurations/XrayGenerator/FocusSize').text))
    outstr.append("# [Xray] Type: {0}, {1} {2}, {3} {4}\n".
                  format(root.find('./HWConfigurations/XrayGenerator/TargetName').text, root.find('./HWConfigurations/XrayGenerator/Voltage').text, root.find('./HWConfigurations/XrayGenerator/VoltageUnit').text, root.find('./HWConfigurations/XrayGenerator/Current').text, root.find('./HWConfigurations/XrayGenerator/CurrentUnit').text))
    ax_root = root.findall('./Axes/Axis')
    for ax in ax_root:
        name = ax.get('Name')
        state = ax.get('State', '')
        str_name = name + ' (Scan)' if state == 'Scan' else name
        pos = ax.get('Position', '')
        str_pos = "" if len(pos) == 0 else pos
        res = ax.get('Resolution', '')
        str_res = "" if len(res) == 0 else "Resolution {}".format(res)
        str_unit = ax.get('Unit', '')
        str_offset = ax.get('Offset', '')
        outstr.append("# [Axis] {0}: {1} {2}, offset {3}, {4}\n".format(str_name, str_pos, str_unit, str_offset, str_res))
    return outstr

def rasx2dat(filename):
    blocks = []
    with zipfile.ZipFile(filename) as zh:
        with zh.open('root.xml') as zf:
            tree = ET.parse(zf)
            root = tree.getroot()
            for child in root:
                if (child.tag)[0:4] == 'Data':
                    number = (child.tag)[4:]
                    with zh.open(child.tag + "/MesurementConditions{}.xml".format(number)) as zf_c:
                        tree_c = ET.parse(zf_c)
                        root_c = tree_c.getroot()
                        headblock = _rasx2dat_head(root_c)
                        scan_step = float(root_c.find('./ScanInformation/Step').text)
                        scan_speed = float(root_c.find('./ScanInformation/Speed').text) / 60.0   # deg/min -> deg/sec
                        count2cps = scan_step / scan_speed
                    with zh.open(child.tag + "/Profile{}.txt".format(number)) as zf_p:
                        datalines = zf_p.readlines()
                        datablock = []
                        for i in range(len(datalines)):
                            tmp1, tmp2, tmp3 = datalines[i].decode('utf-8-sig').rstrip('\r\n').split('\t')
                            datablock.append("{0} {1:.3f} {2} {3}\n".format(tmp1, float(tmp2) * float(tmp3) / count2cps, tmp2, tmp3))
                    blocks.append(headblock + datablock)
    return blocks
    
#==================================================================
# Program Body

#------------------------------------------------------------------
# get ras filenames in current directory
rasfiles = []
rasxfiles = []
for file in os.scandir(os.path.dirname(__file__)):
    base, ext = os.path.splitext(file)
    if ext == '.ras':
        rasfiles.append(file)
    if ext == '.rasx':
        rasxfiles.append(file)

#------------------------------------------------------------------
# Processing each ras files
for filename in rasfiles:
    blocks = ras2dat(filename)
    print("RAS Filename = {0}, Number of {1} block(s) found.".format(os.path.basename(filename), len(blocks)))
    filename_wo_ext = (os.path.splitext(filename))[0]
    for blocknum in range(len(blocks)):
        if len(blocks) == 1:
            outfilename = filename_wo_ext + ".dat"
        else:
            outfilename = filename_wo_ext + "_{0:03d}.dat".format(blocknum+1)
        with open(outfilename, "w") as fh:
            fh.writelines(blocks[blocknum])

for filename in rasxfiles:
    blocks = rasx2dat(filename)
    print("RASX Filename = {0}, Number of {1} block(s) found.".format(os.path.basename(filename), len(blocks)))
    filename_wo_ext = (os.path.splitext(filename))[0]
    for blocknum in range(len(blocks)):
        if len(blocks) == 1:
            outfilename = filename_wo_ext + ".dat"
        else:
            outfilename = filename_wo_ext + "_{0:03d}.dat".format(blocknum+1)
        with open(outfilename, "w") as fh:
            fh.writelines(blocks[blocknum])

input("Hit anykey to exit.")

【試験研究】キセノンランプ光源とランプハウスのセットアップ

 ランプ光源には大きく分けて2つあり、1つは黒体輻射を用いるハロゲンランプ、もう1つは放電現象を用いる放電管です。

 ハロゲンランプは白熱電球(今はほとんどLEDに置き換えられていますが)の1種です。タングステンフィラメントからの黒体輻射で光ります。ガラス管球の中には、ヨウ素や塩素といったハロゲンガスが封入されており、それによって生じるハロゲンサイクルと呼ばれるもので、長寿命化されています。しかし、大出力にすると、光よりも熱になる部分が大きくなるため、明るさに限界があったり、紫外光(400nm以下) の光の成分が弱いという問題があります。そこで、効率よく明るい光を得るために放電管が使われます。放電管は、管球の中に封じられたガスによって発光する波長パターンが異なります。

 今回は、紫外線の短波長側、具体的には190nm~600nm領域での明るい連続スペクトルが欲しかったので、キセノンランプとそのランプハウスを購入しました。キセノンランプは浜松ホトニクスのL2175を、ランプハウスは光軸調整もできるE7536を購入しました。二つ合わせて50万円でおつりぐらいです。

 L2175ではありませんが、同じ浜松ホトニクスの150Wキセノンランプ光源のスペクトルは下記です。700nmから長波長側に輝線があります。あとは470nmに少しピークがあります。400nm以下はつるんとしています。L2175は保証寿命1200時間、平均寿命2500時間です。また、放電管なので出力が安定するまでに10分ほどの暖気が必要です。

150Wキセノンランプのスペクトル

 組み立てたのですが、結論はこんな感じです。

  • 組み立てはとても簡単
  • 光軸合わせも簡単
  • これまで使っていたランプハウスE2419は熱くて大変でしたが、E7536は外側の温度は40℃にもならないぐらいで取り扱いが安全。
  • キセノンランプL2175はオゾンを発生します。それなりにオゾン臭がします。使い始めはそれほどでもなかったのですが…。ハイターの臭いはそれほど不快ではないという人は大丈夫です。

 最後に、「どうして紫外線光源に重水素ランプを採用しなかったのか?」と疑問に思われる方もいると思います。実は、浜松ホトニクスの重水素ランプ光源L11798 (MgF2窓) も持っているのです。前方に鋭い強度分布をもつタイプのものです。しかし、180nm~400nmの出力が物足りないので購入しました。キセノンランプのほうも、使用感について追記できることがあれば追記します。

組み立て手順

ランプハウス内部

L2175キセノンランプ球を取り付け

放電中。Y軸方向の位置合わせをしたところ。反射光と透過光の輝点が出るが、これを重ねずに少しずらす。ミラーやレンズの温度が高くなってしまうから。紫外線ミラーは、普通はアルミミラーです。コーティングにもよりますが、大雑把には反射率90~95%です。ということは、5%ぐらいは熱になってしまうのです。今回のランプは150Wなので大したことはありませんが、もっと強力なものを使うと話は別でしょう。
レンズの焦点付近の発光パターン

【映画】きみの色 (The Colors Within)

有給休暇をとったので、2024年8月30日に公開された、山田尚子監督のアニメーション映画「きみの色」を見てきました。おっさんの感想文を書きます。平日の11:30からの上映ということもあって、私を入れて観客は6名ほど。大学生カップル、オタク大学生、おっさん、おばちゃん、そして私(おっさん)、という感じです。パンフレットによると「山田尚子監督 音楽×青春の集大成となる待望の完全オリジナル長編最新作」というのが謳い文句です。「けいおん」に続くという位置づけ。集大成なんて言われると、これで最終到着地点のように感じるのでよくないです。新海誠監督の「すずめの戸締り」にも似たようなことが書かれていたのを思い出しました。

公式HPにも書かれていますが、主人公はミッションスクールに通う高校生で、人が色で見えるトツ子、トツ子が青い色として認識するきみ、緑色として認識する少年ルイの3名です。優等生だったが高校を中退して常識的な道から外れつつあるきみ、親の病院を継ぐことを覚悟しているが音楽を捨てられないルイ。トツ子は自分の色が見えず、この2名とかかわることで、ラストに自分の色が赤であると認識することになります。赤と言っても鮮やかな赤、波長でいうと660nmぐらいでしょう。

作品を貫くキーワードは、ニーバーの祈り「神様、変えることのできないものについて、それを受け入れるだけの心の平穏をお与えください。変えることのできるものについては、変えるだけの勇気を、変えることのできるものとできないものとを、区別できる知恵をお与えください。」です。主人公のトツ子は、最初の一文、「変えることのできないものについて、それを受け入れるだけの心の平穏をお与えください。」だけを最初唱えています。それをミッションスクールのシスターである日吉子(ひよこ)先生が後半部分があると諭します。見守りながらも、一歩を踏み出そうとする高校生たちを応援する立場です。学校の教員は生徒を抑制的に導く存在として描かれることが多いですが、この作品ではそうではないです。作品そのものが、日吉子先生の立ち位置で鑑賞する作品と言ってもいいように思います。

トツ子、きみ、ルイは他者の目を気にしたり、身内に気を遣いながら抑制的に行動します。しかし、好きなものは好きなのです。そういう気持ちを否定的に取り扱わない、安心して鑑賞できる良作です。各シーンについて。日吉子先生がトツ子のベッドを見つめるシーン、あれは誰かが隠れているかということに感づいたのではなく、自分の落書き "God Almighty" が気になったためなんでしょう。合宿でろうそくの灯りを使うシーンでは、火事にならないかハラハラしました。ライブシーンは「天使にラブソングを」を思い出させます。大型船で大学受験に向かうルイに「がんばれー」もよかったです。ラストにトツ子がバレエを踊りながら自分の色を見つけるシーンでは、作品そのものがストンと着地した感がありました。

アニメーション映画としては、全体にパステル調です。境界線が黒でない色トレスを多用していますから、かなり細かな指定が入っていたのではないでしょうか。原画は大変だったのではないでしょうか。公開が遅れたのもそのせいかもしれません。エンドテロップからは非常にたくさんのアニメーション会社の協力によって作られたことが分かります。キャラクターデザインは小島崇史さんです。山田監督の前作「平家物語」と同じ。特に目の周りにあえてスケッチライクな線を描く手法です。リアルから一歩退くことで、逆に感情移入させられます。

戦闘シーンがあるとか、自己犠牲があるとか、そういう作品ではありませんが、良作です。内的葛藤を描くこういう作品は良いですね。そしてそれを音楽が救う。いいですね。芸事の経験は人を救い、心のバランスをもたらすというのは私の持論です。最後に、やっぱり山田尚子さんは天才ですね。

【試験研究】第一原理計算セットアップ(6):VASP 6.4.3インストール, Intel oneAPI 2024, Ubuntu 24.04 LTS, Intel Core i7-14700

新マシン導入(2024年8月)

最初に経緯から。2018年12月に購入したCore i7-9700Kマシンが故障しました。スペックは、Core i7-9700K, DDR4-2666 16GBx2, 1TB-HDD, Z390 Express Chipset, Intel UHD GraphicsというものでUNITCOM製。購入時の書類を見ると164,116円(税込)というものでした。5年で壊れたということです。症状は、リブートすると動いていたのですが、数時間後にLANでつながらなくなるという中途半端な不調を示していたところ、ついに画面がまともに表示されなくなったというものです。/etc/log/syslogに何か情報があるのかと思って調べたが特になし。故障原因は分からない、というか追及するのが面倒なので廃棄することに。

新しいマシンは、Core i7-14700 (2.1 GHz-5.3 GHz/ 20 cores/ 28 threads), DDR5-4800 16GBx2, 1TB-SSD。ドスパラから購入しました。お盆前8月8日頃に注文したせいか、納期はお盆をまたいで3週間ぐらいでした。昨年行ったCore i7-13700FマシンへのVASP 6.4.2導入のときに、詳しく作業手順を残しておいたので、セットアップは楽でよかったです。 でも、いろいろ間違っていたところがあったりしました。今回は修正版を掲載しています。作業日は2024年8月22日でした。

インストール方針

  • OSはUbuntuとする。ssh接続ばかりでなく、実機に直接モニタを接続して運用することを考え、Ubuntu desktopをインストールすることにした。
  • コンパイラは Intel oneAPI + MKL にする。Intel CPUとの相性がよいこと、Fortran コンパイラに対する信頼から。
  • インストールディレクトリは下記のとおりにする。
    • Intel oneAPI はデフォルトでインストール。/opt/intel の下に入る。
    • vaspバイナリおよびポテンシャルのファイルは、/usr/local/vaspの下に入れる。バイナリは、/usr/local/vasp/vasp643mpibin に (Ver. 6.4.3), ポテンシャルファイルは /usr/local/vasp/potpawPBE64, /usr/local/vasp/potpawLDA64 に入れる。
    • HDF5 は汎用ツールという位置づけで、/usr/local/hdf5-1.14/4 に入れる。(Ver. 1.14)
    • wannier90, libxcは /usr/local/vasp/tools の下に。他のものと混じらないようにする。
    • 今回、libxcのインストールをきちんと行い、wannier90のテストもきちんと行った。
      • wannier90でテストが1つ通らず、vaspのmake test_allでもテストが1つ (mlwf_lif_scdm_optics) 通らなかった。
      • libxcでテストが1つ通らなかった。最適化オプションを無効 (-O0) にしても結果は変わらなかった。

OSインストール

OSはいつもどおりUbuntuで、Ubuntu 24.04 LTSにした。前回はUbuntu 22.04だったので少しだけアップデートされている。手順は下記のとおり。

  • Ubuntu.comから、ubuntu-24.04-desktop-amd64をダウンロードする。5.97GBytesのサイズがある。
  • ブータブルUSBメモリ作成ソフトのrufus-4.5.exeをダウンロードする。
  • USBメモリ(今回使ったのは余っていたSilicon Power 32GB)をPCに刺し、rufus-4.5.exeを起動する。[選択]をクリックしてダウンロードしたISOファイルを選択した。あとは勝手にパーティション構成=MBR, ターゲットシステム=BIOSまたはUEFIに。ファイルシステムはFAT32(規定)、クラスタサイズは8192バイト(規定)。[スタート]をクリックすると作成開始となる。「状態」のところのプログレスバーが伸びていく。時間は30分ぐらいはかかったかも(ちゃんと計ってませんでした)。書き込み時間はUSBメモリの速度に依存するところが大きそう。
  • BIOSで起動順を切り替えてUSBメモリから立ち上がるようにし、インストール。手順は前回と変わらない。ネットワークの設定も同じ。python3などが最初から入っていたりするなどの違いがあった程度でした。
  • ネットワークの設定は、DHCP環境でなかったので、最初ネットワークなしで行い、インストール終了後に右上の歯車メニュー(設定メニュー)で設定。手動IP。
  • 最初に sudo apt update, sudo apt upgrade してssh関連設定を行う。ssh関連設定は下記のとおり。
    • sudo apt updateしておく。
    • 外部からログインするためにsshを入れる。sudo apt install openssh-client openssh-server を行う。openssh-clientはすでに入っているはず。
    • "sudo vi /etc/ssh/sshd_config" [Enter]として、sshd_configを編集する。エディタはviにしているが、何でもいい。
    • 下記項目のとおりにする。
      • PermitRootLogin no
      • PermitEmptyPasswords no
      • MaxAuthTries 6
      • "Port xxxx" (xxxx)は適当な数値。22でないほうがよい。
    • sudo apt install emacs をした。これは私がemacsを愛用しているため。
    • sudo apt install net-tools をした。このままだとifconfigなどが使えず、不便であるため。
    • sudo apt install autogen autoconf libtool をしておく。後述する libxc のインストールで必要となる。

Intel Compilerインストール

  • 前回と同様、Intel oneAPI Base Tookit (C compilerなど) と Intel HPC Toolkit (Fortran Compiler, MKL) をインストールする。今回はaptでインストールした。aptで入れるが、/opt/intel/oneapiの下に入る。
  • Intel Toolkitsのページに行き、Intel oneAPI Base Toolkit, Intel HPC Toolkitのページに行く。
  • [Download]をクリックし、ページ遷移したら "Operating System" に [Linux] を、"Installation/Package Type" に [APT] を選ぶ。右側に "APT Package Manager" というタイトルの説明が出るので、1から順番に実行する。最初にリポジトリの登録がある。ユーザー登録はしなかった。
  • /opt/intel/oneapi/setvars.sh を実行しておく。.bashrcに書いておく。
source /opt/intel/oneapi/setvars.sh

サポートプログラムのインストール

  • ホームディレクトリが汚れるので、~/work を切ってからそこで作業するといい。
  • コンパイラ導入直後ならば、source /opt/intel/oneapi/setvars.sh を実行しておく。

    HDF5

  • zlib, szip を入れてから、hdf5 ver. 1.14 を導入する。
  • 昨年のインストールでは、zlibは ver. 1.3だったが、1.3.1になっていたので最新版を入れた。szip のバージョンは変わらず。
  • 作業前に source /opt/intel/oneapi/setvars.sh が実行されて、コンパイラ関係の環境変数が設定されていることが必要。
mkdir work
cd work
wget http://www.zlib.net/zlib-1.3.1.tar.gz
tar zxvf zlib-1.3.1.tar.gz
cd zlib-1.3.1
./configure --prefix=/usr/local
make
sudo make install
cd ..
wget  wget https://support.hdfgroup.org/ftp/lib-external/szip/2.1.1/src/szip-2.1.1.tar.gz
tar zxvf szip-2.1.1.tar.gz
cd szip-2.1.1
./configure --prefix=/usr/local
make
sudo make install
cd ..
wget https://github.com/HDFGroup/hdf5/releases/download/hdf5_1.14.4.3/hdf5-1.14.4-3.tar.gz
tar zxvf hdf5-1.14.4-3.tar.gz
cd hdf5-1.14.4-3/
FC=ifort ./configure --prefix=/usr/local/hdf5-1.14.4  --enable-fortran --enable-cxx --with-szlib=/usr/local
make
make check
sudo bash
source /opt/intel/oneapi/setvars.sh
make install
make check-install
exit
  • LD_LIBRARY_PATHのための設定は下記のとおり。.bashrcなどに入れておく。
export LD_LIBRARY_PATH=/usr/local/hdf5-1.14.4/lib:/usr/local/lib:$LD_LIBRARY_PATH

wannier90

 いろいろなパターンを試したが、make testsでエラーが1つ消えない。 最善は、ifx使用、最適化はなし (-O0)、MKL使用の場合だった。 これが原因かはわからないが、vaspのmake test_allで、mlwf_lif_scdm_optics のテストが通らない。 数値そのものが問題ではなく、nan (not a number) の処理の問題のようにも見える。

wget https://github.com/wannier-developers/wannier90/archive/v3.1.0.tar.gz
tar zxvf v3.1.0.tar.gz
cd wannier90-3.1.0/

下記の内容をmake.incとする。config/make.inc.ifortをmpi非対応版に改造したもの。

#=====================================================
# For Linux with intel version 11/12 on 64bit machines
#=====================================================
F90 = ifx
#COMMS=mpi
MPIF90=ifx
FCOPTS=-O0
LDOPTS=-O0

#========================================================
# Intel mkl libraries. Set LIBPATH if not in default path
#========================================================

LIBDIR =  /opt/intel/oneapi/mkl/latest/lib/intel64
LIBS   =  -L$(LIBDIR) -lmkl_core -lmkl_intel_lp64 -lmkl_sequential -lpthread

#=======================
# ATLAS Blas and LAPACK
#=======================
#LIBDIR = /usr/local/lib
#LIBS = -L$(LIBDIR)  -llapack -lf77blas -lcblas -latlas

続いて、make, そしてinstall (手動) する。

make; make lib
sudo mkdir /usr/local/vasp
sudo mkdir /usr/local/vasp/tools
sudo mkdir /usr/local/vasp/tools/lib
sudo cp libwannier.a /usr/local/vasp/tools/lib
sudo cp wannier90.x /usr/local/vasp/tools
sudo cp postw90.x /usr/local/vasp/tools

wannier90のtestsはpythonを使っている。しかしUbuntuのpythonは "python3" なので、 3つのファイルの1行目を "python"→"python3"とした。変更を加えたのは下記の3ファイル。

  • test-suite/clean_tests
  • test-suite/run_tests
  • test-suite/testcode/bin/testcode.py

make testsした結果、でエラーが1つ出た。下記のエラー。いろいろやったが消えなかった。たとえば gfortran にすると悪化した。

tests/testpostw90_pt_kpathbandsshc - Pt.win: **FAILED**.
shc
    ERROR: absolute error 1.08e-02 greater than 1.00e-02. (Test: -8.1625987.  Benchmark: -8.1517891.)
shc
    ERROR: absolute error 1.08e-02 greater than 1.00e-02. (Test: -8.719545.  Benchmark: -8.7303551.)
All done. ERROR: only 61 out of 62 tests passed.
Failed test in:
        /home/kuno/vasp-compile/wannier90-3.1.0/test-suite/tests/testpostw90_pt_kpathbandsshc/
make: *** [Makefile:186: test-serial] Error 1

libxc

  • 交換相関汎関数の汎用ライブラリ。現在進行形で議論・改良が進められている。vaspでは libxc1, libxc2 タグで動作を指定できる。交換相互作用の処理はvasp自身もいろいろもっているので重複する機能となる。HPC社のベンチマークからは、特には高速化されないというレポートがある。
  • 交換相互作用の処理方法は新しい方法が考案されており、up-to-dateなものを導入したいときはlibxcを使うほうが有利かもしれない。Quantum espressoからもlibxcを使うことができる。さらにはvaspのmake test_allすると libxc関係のテスト項目が結構ある。
  • 下記の手順で行った。あらかじめsudo apt install autogen autoconf libtool をしておくこと。configure生成のために必要である。(インストール手順にはそこまで書かれていない)
  • --disable-fhcはvaspに組み込むために必要だが、これのせいでmake checkでエラーが1つ出る。
wget https://gitlab.com/libxc/libxc/-/archive/6.2.2/libxc-6.2.2.tar.bz2
bunzip2 libxc-6.2.2.tar.bz2
tar xvf libxc-6.2.2.tar
cd libxc-6.2.2
autoreconf -i
CC=icx FC=ifx ./configure --prefix=/usr/local/vasp/tools --disable-fhc
make
make check
sudo make install

make checkの結果、mgga_xc_otpss_dでFAILとなる。ここ1か所だけ。最適化オプションを -O0 にしても結果は同じである。

今回省略したもの

  • libeef

VASP 6.4.3のインストール

  • ~/.bashrcの末尾に下記の記述を入れておく。
# VASP
ulimit -s unlimited
source /opt/intel/oneapi/setvars.sh
export LD_LIBRARY_PATH=/usr/local/hdf5-1.14.4/lib:/usr/local/lib:$LD_LIBRARY_PATH
alias rmvasp="rm -f CHG* OSZICAR* OUTCAR* SUMMARY* WAVE* EIGEN* PCDAT XDATCAR DOSCAR* vasprun.xml IBZKPT nohup.* CONTCAR* W*.tmp PROCAR OPTIC PORCAR* REPORT wannier90* *.h5"
alias rm="rm -i"
  • vasp.6.4.3をダウンロードしてきて展開、展開先のディレクトリに移動する。
tar zxvf vasp.6.4.3.tgz
cd vasp.6.4.3
cp arch/makefile.include.intel makefile.include
  • oneAPIがicc, icpcã‚’icx, icpxに変更したこと、ifortã‚’ifxに変更推奨していることから、makefile.includeを編集する。さらに、HDF5サポート, wannier90サポートの部分のコメントを外し、編集する。変更した部分だけを抜粋して示す。
FC          = mpiifx
FCL         = mpiifx
CC_LIB    = icx
CXX_PARS    = icpx

# HDF5-support (optional but strongly recommended)
CPP_OPTIONS+= -DVASP_HDF5
HDF5_ROOT  ?= /usr/local/hdf5-1.14.4
LLIBS      += -L$(HDF5_ROOT)/lib -lhdf5_fortran
INCS       += -I$(HDF5_ROOT)/include

# For the VASP-2-Wannier90 interface (optional)
CPP_OPTIONS    += -DVASP2WANNIER90
WANNIER90_ROOT ?= /usr/local/vasp/tools
LLIBS          += -L$(WANNIER90_ROOT)/lib -lwannier

# Libxc
CPP_OPTIONS += -DUSELIBXC
LIBXC_ROOT  += /usr/local/vasp/tools
INCS        += -I$(LIBXC_ROOT)/include
LLIBS       += -L$(LIBXC_ROOT) -lxcf03 -lxc

make test の結果

  • コンパイルしてテストを走らせる。テスト実行時間計測のために、time make test としています。
make DEPS=1 -j4
time make test
  • エラーはなし。
  • Core i7-14700での実行時間は21.2分、Core i7-13700Fでの実行時間は24.3分でした。13%程度の速度アップでした。
    • Core i7-14700 : 20 cores, 28 threads, 2.1 GHz - 5.4 GHz, L1 80 kbytes, L2 2 Mbytes, L3 30 Mbytes, 10nm process
    • Core i7-13700F : 16 cores, 24 threads, 2.1 GHz - 5.1 GHz, L1 80 kbytes, L2 2 Mbytes, L3 30 Mbytes, 10nm process

make test_all の結果

 昨年度と同様、mlwf_lif_scdm_optics でエラーが出た。このテストは、wannier90を使って誘電率を計算するテスト。計算そのものは正常終了しているが、誘電率の虚部を計算した結果の行列がおかしいというエラーである。計算では、行列要素が0.0になるところ、テストテンプレートのほうはnanになっている。どちらがおかしいのかよく分からない。

==================================================================
SUMMARY:
==================================================================
The following tests failed, please check the output file manually:
mlwf_lif_scdm_optics
make[1]: *** [makefile:24: test_all] Error 1
  • Core i7-14700での実行時間は、1時間31分 (91分) だった。
  • Core i7-13700Fでの実行時間は、1時間51分 (111分) だった。Core i7-14700との差は18%。

vaspを /usr/local/vasp にインストール

  • バイナリとポテンシャルファイルを導入する。potpaw_PBE.64.tgz, potaw_LDA.64.tgz をダウンロードして、作業ディレクトリに保存し、下記を実行する。/usr/local/vasp/potpawPBE64, potpawLDA64という名前は、私がつけているポテンシャルファイルの標準ディレクトリ名です。
sudo mkdir /usr/local/vasp/vasp643mpibin
sudo cp bin/* /usr/local/vasp/vasp643mpibin
mkdir potpawPBE64
tar zxvf potpaw_PBE.64.tgz -C potpawPBE64
sudo cp -r potpawPBE64 /usr/local/vasp
sudo chmod 555 /usr/local/vasp/potpawPBE64/*
mkdir potpawLDA64
tar zxvf potpaw_LDA.64.tgz -C potpawLDA64
sudo cp -r potpawLDA64 /usr/local/vasp
sudo chmod 555 /usr/local/vasp/potpawLDA64/*
  • 実行後、一般ユーザー権限で、/usr/local/vasp/potpawPBE64/N/POTCAR などが読み込めるかどうかを確認する。

.bashrcの設定

最後に、.bashrcを設定した。下記の情報を、.bashrcの末尾に加えた。

# VASP
ulimit -s unlimited
source /opt/intel/oneapi/setvars.sh
export LD_LIBRARY_PATH=/usr/local/hdf5-1.14.4/lib:/usr/local/lib:$LD_LIBRARY_PATH
alias rmvasp="rm -f CHG* OSZICAR* OUTCAR* SUMMARY* WAVE* EIGEN* PCDAT XDATCAR DOSCAR* vasprun.xml IBZKPT nohup.* CONTCAR* W*.tmp PROCAR OPTIC PORCAR* REPORT wannier90* *.h5"
alias rm="rm -i"

【試験研究】NewPort社製 光パワーメーター 843-R

はじめに

ひょんなことから、NewPort社製の光パワーメーター Model 843-Rを入手しました。 メモを書きます。

NewPort社はアメリカの会社で、光学実験台などの製品をいろいろな研究機関で目にします。 日本の総代理店は日本レーザー(ジャパンレーザー)です。 "Power Meter Model 843-R-USB" は、2024年1月段階でも現役のようで、HPを見ると税抜249,000円です。 eBayでは中古品が550USDぐらいで出回っています。 青色のNewPortカラーがカッコいい光パワーメーターです。

外見

  • ディスプレイのついたハンドヘルド型
  • 上面に、ディテクタ接続端子としてDSUBにBNCがついたものがある。その両脇に、USB-MicroBコネクタとACアダプタのコネクタ、そして"ANOUT" と書かれたアナログ出力がある。
  • ディテクタは、818-ST2がついていた。厚さ5mmの薄型。818-ST2-UVでも、818-ST2-IRでもないので、可視光用。400-1100nmが測定レンジ。税抜161,000円する。

NewPort Power Meter Model 843-R front

NewPort Power Meter Model 843-R top

NewPort Photodetector 818-ST2

特徴

  • 内蔵バッテリがある。12V 2AのACアダプタでチャージする。
  • 側面がゴムになっていて、持ちやすい。
  • ディテクタは設定で変更するのではなく、メーカーによる校正データとともに埋め込まれる形。ユーザーは変更できない。この本体には、818-ST2がついていた。シリコンフォトダイオード。
  • ディテクタ測定波長は、400, 750, 1100から選べるようになっている。
  • 平均化機能は 1, 3, 10, 30 sec, 1, 5, 10, 30 min, 1hから選べる。
  • 商用周波数を50/60Hzから選べるようになっている。電池電源からではなく、ACアダプタからも給電されるので、そこからのノイズを除去するためか。
  • [設定]>[フィルタ]の「フィルタ」とは、attenuation filter (減光フィルタ) の意味です。ディテクタには1/1000にするフィルタがあり、これを入れたときはここを "IN" にします。外した時は "OUT" にします。IN/OUTを切り替えると、値がほぼ3桁変化します。減光フィルタはNDフィルタでしょうが、厳密には波長依存性があります。恐らくですが、この波長依存性を込みで校正してくれているのだと思います。

ファームウェアアップデート

 ファームウェアのバージョンが古かったのでアップデートしました。

  1. NewPortのサイトから、"843-R Firmware Version 1.56 (11MB, ZIP)"をダウンロードします。ファイル名は "843-R_Ver156.zip" でした。
  2. 解凍(普通のWindowsなら上記のzipファイルをダブルクリックするだけ)して、デスクトップなどに "843-R_Ver156.exe" をコピーします。
  3. 843-R_Ver156.exe をダブルクリックして実行します。Windowsに.NET Framework 4がなければダウンロードしてインストールする必要があります。.NET Frameworkとは、WindowsのGUI関係のライブラリです。
  4. ファームウェアをアップロードします。手順は下記のとおりです。("843-R-Field-Upgrade-Instructions.pdf" に書かれていますが…)
  5. 843-Rの電源をオフにする。電源ボタン(中央下の丸いボタン)を長押しします。マニュアルには5秒とか書かれていますが、2秒ほどで電源が切れます。
  6. USBケーブルをPCと接続します。Type-AとMicro Bです。
  7. [Next] をクリックします。
  8. 843Rのディスプレイの下に並んだ4つ並んだボタンのうち、右から2つ目を押しながら、電源を入れます。
  9. 検出器を見つけたというメッセージが出て、ファームウェアが転送されます。しばらく待ちます。"Firmware upgrade in progress" と表示されます。
  10. もう一度電源ボタンを押して、[Exit]をクリックします。
  11. 10秒ほど待ってから電源ボタンを入れます。
  12. 「次回校正日」というメッセージが出ます。センサの校正期限が過ぎたので、メンテに出しなさいと言うことです。843-Rの右端のボタン(続ける)を押します。
  13. 843-Rの右から2番目のボタンを押して、右上にあるファームウェアバージョンを確認します。"843-R 1.56" になっていました。

【雑記】中島みゆき「心音/有謬の者共」

2023年9月13日発売の中島みゆきさんのシングルCD、「心音/有謬の者共」(しんおん/うびゅうのものども)を買いました。このブログを書いているのは10月下旬です。普段は「心音」をYoutubeで聴いていたのですが、「有謬の者共」がYoutubeで公開されたときに、もうちょっといい音でリピートして聴きたくなりました。Amazonの特典であるメガジャケがなくなる前にと思い、急いでCDを購入したという次第です。ポスターを貼るのがためらわれる年齢の私にとって、Amazonのメガジャケはうれしい特典です。ジャケットの絵は宣伝に使われているものだったこともあって、新たな感激はありませんでした。しかし、CDを紙ケースから取り出したあと、CDのポリカーボネートの面に描かれているイラストの美しさにはっとし、縦書きの楽曲名にこだわりを感じました。手に取りたくなるCDといったところです。

 このCDに収録されている楽曲は、『アリスとテレスのまぼろし工場』というアニメーション映画の主題歌として制作されたものです。この映画はMAPPAというアニメ制作会社の初オリジナル作品です。MAPPAという制作会社は、「この世界の片隅に(2016年)」というアニメーション作品で名が知られるようになった会社です。とても丁寧な作りをする制作会社というのが私の印象です。原作・脚本・監督は岡田麿里さん。機動戦士ガンダム鉄血のオルフェンズ (2015年) という、ガンダムシリーズの中でも、記憶に残る作品を手掛けられた方です。

 映画の内容を雑駁に紹介すると、製鉄所の事故によって、ある街全体が閉じられた空間となってしまいます。物理的にも社会システム的にもおかしくなってしまった街で生きる人たちの人間模様を描いた作品です。おかしいと思ったら、疑問をもったら、そのまま踊らされるのではなく、各人が信じる方向を大事にしなさいというのが、作品が描こうとしている大まかな内容でしょうか。「心音」を聞きなさい、というわけです。こだわって描かれている、美しいシーンがいくつもあり、純文学に類するアニメーション作品だなあというのが見終わった直後の私の感想です。セカイ系とはちょっと違うように思います。最後のカーチェイスは冗長だったなと思わなくはないしですが、全体に記憶に残る良い作品でした。映画では、閉じられた街にいる主人公と、その外にある正常な現実世界の主人公がだぶって現れます。この作品を考えるときのポイントは、この辺にありそうです。

 さて、この「心音」という楽曲は、映画の本編が終わってから流れます。まるで映画の内容をかみしめて下さいと訴えかけてくるように流れてきます。「味方だろうか、悪意だろうか」は「味方と敵」ではなく「味方と悪意」で対比させ、「でも聞こえてしまったんだ/僕の中の心音」に続き、「僕は本当の僕へと 祈りのように叫ぶだろう」と、「本当の僕」という言葉が、ストーリーとつながるようにも、独立したようにも聞こえる歌詞につながっていきます。映画の内容を引き締めてくれる歌詞と楽曲、歌唱です。

 「有謬の者共」は、タイアップ曲としてCDに収録されており、劇中では流れませんでした。「有謬」という言葉は中島みゆきさんの造語かもしれません。しかし、「無謬」が「誤りのないこと」という意味ですから、その反対ということは容易に分かります。この曲の歌詞にある「間違うのがニンゲン」というフレーズは、映画の作中で、皆を間違った方向に導いた佐上衛というキャラクターのことを表現したのでしょう。作中では悪役扱いですが、彼がとった行動は、悪い方向へ導こうと思っての行動ではありません。映画の中で対立軸となった双方の立場にコメントしようとする、やさしい考えの楽曲のペアとなっています。

 映画の興行収入は上がっていないようですが、作品のクオリティは高いです。ブルーレイが出たら買うと思います。

 以上が映画を見てから、映画の主題歌という内容に即した「心音」の感想です。ここから、映画からは少し距離をおいたとき、と言いますか、映画を見る前にYoutubeで公開されていたときに聞いたこの歌についての感想です。

 「味方だろうか、悪意だろうか」というところの対比にまず気づきます。昔読んだ本に、批判的なことを言われても、それが悪意なのかどうかは考えなければならないとあったのを思い出しました。さらには「ひりつく日々も、眩しい日々も、閉じ込める夜」と、悪意の可能性、悪意でない可能性、疑うことへのある種の怖れを抱きながら、「誰も触れない、誰も問わない、時は進まない」という具合に、周囲が黙っているのでとりあえず黙っておいて流されていっている現状への認識を嘆息します。これは現代的な集団心理です。何か主張すると攻撃されるかもしれないから、黙って集団に埋没しておこうというわけです。たとえそれが正しく、素晴らしい主張であっても、です。そこで主人公は「でも聞こえてしまったんだ/僕の中の心音」と、自らの中に沸き起こった違和感への答えを「心音」という言葉で反映させます。さらに、巧みに隠された悪意や、黙っておいて責任から逃れようとするこの立場を「綺麗で醜い嘘たちを」と表現し、「僕はここで抱き留めながら/僕は本当の僕へと/祈りのように叫ぶだろう」と続けます。ここで、「僕」は「本当の僕」との2人に分裂します。両者は同一の肉体をもつ者なのか。そして「未来へ/未来へ/君だけでゆけ」と、もう一人の「僕」に言うわけです。前者の「僕」は醜い嘘をその身に受けていずれ滅びるが、後者の「僕」は醜い嘘が取り払われた未来へ進みなさい、ならば両者は別なのか?という疑問が湧きます。映画を見た後なら、「君」は「五実(いつみ)」のことだと思われますが、歌詞だけ見ればどうなのでしょう。

 現在、昭和に活躍した人たちが次々にこの世を去るという形で、昭和が消え去っていっています。さまざまな軛が外されつつあります。昭和世代には、現在の社会を作った功績もありますが、あまりにも大きな多くの問題点を後の世代に残置しようとしていることも事実です。年配の方々の中には、今の日本が豊かなのは誰のおかげだ、と主張する方もおられますが、さまざまな問題点を整理してからこの世を去りたいと思っておられる方もいます。中島みゆきさんについては、アルバム「組曲」の「空がある限り」あたりから、嘆きというよりも訴えが明確に感じられるようになったと思います。「心音」の歌詞に返ります。2番の歌詞では「ほころびつつある世界の/瀬戸際で愛を振り絞り」「僕は現実の僕へと/願いのように叫ぶだろう」となっています。「僕」と「現実の僕」に分裂しています。やはり、この楽曲、ひいては映画を感じるためには、二人の「僕」は同一の「僕」なのかを、考える必要があります。興味深い歌詞です。