next up previous contents
: セルを一様に拡大しながらSCF計算を行うスクリプトのサンプル : BeanShellスクリプトの例 : BeanShellスクリプトの例   目次


PHASE $ \rightarrow $ekcal計算を行うスクリプトのサンプル

PHASEによるSCF計算を行い, ついでekcalによる状態密度計算を行うスクリプトのサンプルが, PHASE-Viewerサンプルの ``scripting''プロジェクトの下にある, ``scf-dos''サブプロジェクトにあります. このサンプルについて詳解します.

図 6.3の,「スクリプト設定画面」を表示させると, 図 6.6で示すように, ``commands.bsh''というスクリプトと``scf-dos.bsh''という二つのスクリプトファイルが指定されているのが分かります. ``commands.bsh''スクリプトは, 共通の便利な関数をまとめて定義したファイルで, 用意している多くのスクリプトファイルで 参照します.

図 6.6: PHASE $ \rightarrow $ekcal計算を行うためのスクリプト制御画面.
Image script_manip_phase_dos

``scf-dos.bsh''スクリプトが, 実際の計算を行うためのスクリプトです. このスクリプトのソースは,

.chase/scripts/jobcontrol/phase/scf-dos.bsh
です.

まず入力から説明します. 入力部は, 下記のようになっています.

accuracy{
    initial_wavefunctions = matrix_diagon:combo:matrix_diagon_or_random_numbers
    ksampling{
        method = mesh:combo:scf_or_monk_or_mesh
        mesh{
            nx = scf
            ny = scf
            nz = scf
        }
    }
    matrix_diagon{
        cutoff_wf = default
    }
    smearing{
        method = tetrahedral:combo:scf_or_parabolic_or_tetrahedral
        width = scf
    }
    ek_convergence{
        num_max_iteration = 500
        sw_eval_eig_diff = on:combo:on_or_off
        delta_eigenvalue = 1.e-5
        succession = 2
    }
}
postprocessing{
    dos{
        sw_dos = on:combo:on_or_off
        method = tetrahedral:combo:gaussian_or_tetrahedral
        variance = 1.d-6
        nwd_dos_window_width = 10
        deltaE_dos = 1.d-4
    }
}
この入力は, 普通に設定した入力でPHASE計算を行ったあと, ekcal用の入力を作成するためのものです. ``scf''とあるキーワードは, ekcal実行時に「SCF計算と同じ値を利用する」ことを意味します.

スクリプト実行部をみてみましょう. このスクリプトは, まず以下の関数が実行されます.

void execute() {
    logger.info("executing phase...");
    execute("__PHASE__");
    processInput();
    logger.info("executing ekcal...");
    execute("__EKCAL__");
    logger.info("done.");
}
``logger''変数はログを取るためのオブジェクトです. execute("__PHASE__");およびexecute("__EKCAL__");という実行分で それぞれPHASE, ekcalを実行します. さらに, execute("__PHASE__");のあとに呼んでいるprocessInput();関数によって PHASE用入力ファイルを, スクリプトの入力に従ってekcal用の入力に書き換えます. 以下, processInput();関数を簡単に説明します.

processInput();関数は下記のようなものです. ここでは便宜上行頭に数字を振っていますが, 実際のスクリプトにはこの数字はありません.

1: InputInterface inputInterface = getInputInterface(nfinp);
2: InputInterface inputBSH = getInputInterfaceFromBSH("__TARGETDIR__"+"__FS__"+"__scf-dos.bsh");
3: void processInput() {
4:     inputInterface.selectAndCreateBlock("control");
5:     inputInterface.replaceEntry(new InputInterfacePrimitiveEntry("condition","fixed_charge",""));    
6:     inputInterface.selectRoot();
7:     
8:     inputBSH.selectBlock("accuracy.ksampling");
9:     method = inputBSH.getPrimitiveEntry("method");
10:    if ( method.getValueDelimitedBy().equals(scf) ) {
11:        inputBSH.removeEntry(method);
12:    }
13:    inputBSH.selectParentBlock();
14:
15:    inputBSH.selectBlock("accuracy.ksampling.mesh");
16:    nx = inputBSH.getPrimitiveEntry("nx");
17:    if ( nx.getValueDelimitedBy().equals(scf) ) {
18:        inputBSH.removeEntry(nx);
19:    }
20:    ny = inputBSH.getPrimitiveEntry("ny");
21:    if ( ny.getValueDelimitedBy().equals(scf) ) {
22:        inputBSH.removeEntry(ny);
23:    }
24:
25:    nz = inputBSH.getPrimitiveEntry("nz");
26:    if ( nz.getValueDelimitedBy().equals(scf) ) {
27:        inputBSH.removeEntry(nz);
28:    }
29:
30:    inputBSH.selectBlock("accuracy.smearing");
31:    smearing_method = inputBSH.getPrimitiveEntry("method");
32:    if ( smearing_method.getValueDelimitedBy().equals(scf) ) {
33:        inputBSH.removeEntry(smearing_method);
34:    }
35:    smearing_width = inputBSH.getPrimitiveEntry("width");
36:    if ( smearing_width.getValueDelimitedBy().equals(scf) ) {
37:        inputBSH.removeEntry(smearing_width);
38:    }
39:    
40:    inputBSH.selectBlock("accuracy.matrix_diagon");
41:    cutoff_wf = inputBSH.getPrimitiveEntry("cutoff_wf");
42:    if ( cutoff_wf.getValueDelimitedBy().equals("default") ) {
43:        inputInterface.selectRoot();
44:        inputInterface.selectBlock("accuracy");
45:        inputBSH.replaceEntry(inputInterface.getPrimitiveEntry("cutoff_wf"));
46:    } 
47:                      
48:    inputInterface.selectRoot();
49:    inputInterface.overWriteBlock(InputInterface.__ROOT__,"accuracy",inputBSH);
50:
51:    inputInterface.selectRoot();
52:    inputInterface.swapBlock("postprocessing","dos",inputBSH);
53:
54:    inputInterface.save();
55: }

1行目と2行目では, それぞれPHASE(ekcal)で利用する入力ファイルとこのスクリプトの入力ファイルを操作するクラス, InputInterfaceのオブジェクトをインスタンス化しています. 3行目からがprocessInput()関数です. 4行目から6行目で ``control''ブロックの``condition''を, ekcal用に``fixed_charge''としています.

8行目から46行目ではスクリプト入力の操作を行っています. 一見複雑に見えるかもしれませんが, 行っていることは 以下の二点のみです.

``scf''キーワードの処理
``scf''キーワードはPHASEの値をそのまま使う, ということに対応します. スクリプト用のInputInterfaceオブジェクトは後で実際の入力のInputInterfaceオブジェクトの該当部分に``上書き''するので, PHASEと同じ, ということはそのエントリーを削除すればよい, ということになります. 実際に行っている操作もその通りになっています.
``default''キーワードの処理
初期波動関数を行列対角化で行う際のカットオフを, ``default''の場合は波動関数のカットオフと同等になるような操作を行っています.

48行目から52行目でスクリプトの入力から実際の入力を作成しています. 49行目ではInputInterfaceの``overWriteBlock''メソッドによって``accuracy''ブロックを上書きし, さらに52行目ではInputInterfaceの``swapBlock''メソッドによってpostprocessingブロックを差し替えています.

最後に, 54行目で実際に利用する入力をディスクに保存しています.



jkoga 平成22年4月27日