図 6.3の,「スクリプト設定画面」を表示させると, 図 6.6で示すように, ``commands.bsh''というスクリプトと``scf-dos.bsh''という二つのスクリプトファイルが指定されているのが分かります. ``commands.bsh''スクリプトは, 共通の便利な関数をまとめて定義したファイルで, 用意している多くのスクリプトファイルで 参照します.
``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行目ではスクリプト入力の操作を行っています. 一見複雑に見えるかもしれませんが, 行っていることは 以下の二点のみです.
48行目から52行目でスクリプトの入力から実際の入力を作成しています. 49行目ではInputInterfaceの``overWriteBlock''メソッドによって``accuracy''ブロックを上書きし, さらに52行目ではInputInterfaceの``swapBlock''メソッドによってpostprocessingブロックを差し替えています.
最後に, 54行目で実際に利用する入力をディスクに保存しています.