パラメータファイルに対するプリコンパイル¶
プリコンパイラ / プリコンパイラ¶
プリコンパイル :コンパイル前にファイルをテキスト処理し、 記述の効率性や再利用性を向上するコーディング技術.
プリコンパイラ :ソースコードを処理して別の形式のコードを生成するプログラム群.
パラメータファイルのプリコンパイル¶
(課題) パラメータファイルを取扱い容易に、可読性の向上¶
技術計算系のソフトウェアは、入力ファイルとして 決められたフォーマット のファイルを与えることが多々ある.
(e.g.) Elmer, PHITS, EMSolution, gmsh, etc.
記載中で、 変数の使用 、 四則演算 、 分割ファイル読み込み ができなければ、記載が煩雑になりがち.
可読性 も下がる.
(解決方法) プリコンパイラを導入¶
変数名を与えて、「ある数値 ( e.g. 1.602e19 )」 が 何を指すのか ( e.g. 電化素量 )を明瞭に.
繰り返し現れる数値を 一括変更 .
変数を使用した計算を可能にして、とあるパラメータを変更したときに、 別数値が連動して変更 されるように.
分割ファイルで、パラメータファイルを 機能ごとに整理 、構成をわかりやすく.
使い方¶
パラメータファイル中で変更したい変数名を "@XXXX" と @マークから始まるように記載.
変数の定義は次の通り
.jsonファイル中で与える ( jsonの記事で記載 )
# <define> @var1 = 1.0 のように <define>文を使用して定義する.
変数は計算可能だが、ファイルの前方から順に処理していくため、 記載順には要注意 .
一応、単なる数値等、1重呼び出し程度なら前後しても問題ないが、 多重に呼び出し、かつ、順番前後した変数定義は不可 .
2重以上の変数呼び出しはしない ( etc. @var1=@var2, @var2=@var3, @var3=1.0 )
2重以上の変数呼び出しだが、は前から順に宣言する.:
#<define> @var3 = 1.0 #<define> @var2 = @var3 #<define> @var1 = @var2
jsonでの数式記述に関しては、別記事を参照.
コマンドラインからの実行¶
precompile__parameterFile.py を パスの通ったところにおいて、 ( e.g. /usr/local/bin/ )
実行権限 を付与し、 ( e.g. $ chmod +x /usr/local/bin/precompile__parameterFile.py )
pythonの実行のおまじないをを先頭行に記載し、 ( e.g. #!/usr/bin/env python3.10 )
コマンドラインから実行すれば、 簡易実行可能
例
$ precompile__parameterFile.py sample_parameter.inp $ precompile__parameterFile.py sample_parameter.inp --comment_mark $ --outFile sample_parameter.out
コード¶
プリコンパイラエンジン¶
#!/usr/bin/env python3.10
# -*- coding: utf-8 -*-
import os, sys, argparse
import numpy as np
import nkUtilities.include__dividedFile as inc
import nkUtilities.replace__variableDefinition as rvd
import nkUtilities.json__formulaParser as jfp
import nkUtilities.loadJSON__asVariableTable as lja
# ========================================================= #
# === precompile__parameterFile.py === #
# ========================================================= #
def precompile__parameterFile( inpFile=None, outFile=None, lines=None, table=None, silent=True, \
priority=None, replace_expression=True, comment_mark="#", \
define_mark="<define>", include_mark="<include>",
loadJSON_mark="<loadJSON>", expr_var=None, \
escapeType ="UseEscapeSequence", variable_mark="@", \
append__variableList=True ):
# ------------------------------------------------- #
# --- [1] include divided Files --- #
# ------------------------------------------------- #
lines = inc.include__dividedFile( inpFile=inpFile, lines=lines, \
comment_mark=comment_mark, include_mark=include_mark, \
escapeType=escapeType, silent=silent )
# ------------------------------------------------- #
# --- [2] load json file --- #
# ------------------------------------------------- #
table = lja.loadJSON__asVariableTable( inpFile=inpFile, lines=lines, table=table, \
loadJSON_mark=loadJSON_mark, \
variable_mark=variable_mark, \
comment_mark=comment_mark, escapeType=escapeType )
# ------------------------------------------------- #
# --- [3] include divided Files --- #
# ------------------------------------------------- #
lines = rvd.replace__variableDefinition( outFile=outFile, lines=lines, table=table,
replace_expression=replace_expression, \
comment_mark=comment_mark, \
variable_mark=variable_mark, priority=priority, \
escapeType=escapeType, silent=silent, \
append__variableList=append__variableList )
return( lines )
# ========================================================= #
# === Execution of Pragram === #
# ========================================================= #
if ( __name__=="__main__" ):
mode = "normal"
if ( mode == "test" ):
table = { "title":"TEST01" }
inpFile = "test/precompile__parameterFile/sample_parameter.inp"
outFile = "test/precompile__parameterFile/sample_parameter.out"
ret = precompile__parameterFile( inpFile=inpFile, outFile=outFile, \
comment_mark="$", table=table )
print()
print( "".join( ret ) )
print()
sys.exit()
elif ( mode == "normal" ):
parser = argparse.ArgumentParser()
parser.add_argument( "inpFile" , help="input file name." )
parser.add_argument( "--outFile" , help="output file name." )
parser.add_argument( "--comment_mark", help="comment mark.", default="#" )
args = parser.parse_args()
if ( args.inpFile is None ):
print( "[precompile__parameterFile.py] inpFile must be given ..." )
print( "precompile__parameterFile.py inpFile --outFile xxx --comment_mark X")
ret = precompile__parameterFile( inpFile=args.inpFile, outFile=args.outFile,\
comment_mark=args.comment_mark )
print( "".join( ret ) )
パラメータファイルサンプル ( sample_parameter.inp )¶
$ This is a parameter file for some calculation
$ <define> @var1 = 0.1
$ <include> filepath = "include.inp"
$$$ <include> filepath = "test/precompile__parameterFile/include.inp"
BEGIN{
TITLE = @title
x,y,z = ( @x, @y, @z )
particle = @particle.type
iterMax = @iterMax
}END
パラメータファイルサンプル ( include.inp )¶
$ $ <loadJSON> filepath = "test/precompile__parameterFile/sample_parameter.json"
$ $ <define> @var2 = 0.2
$ <loadJSON> filepath = "sample_parameter.json"
$ <define> @var2 = 0.2
パラメータファイルサンプル ( sample_parameter.json )¶
{
x: 0.0,
y: 1.0,
z: 2.0,
iterMax:10,
particle.type:"electron",
}
出力例 ( sample_parameter.out )¶
$ This is a parameter file for some calculation
$ <define> @var1 = 0.1
$$$ <include> filepath = "include.inp"
$ <include> filepath = "test/precompile__parameterFile/include.inp"
$ <loadJSON> filepath = "test/precompile__parameterFile/sample_parameter.json"
$ <define> @var2 = 0.2
$$$ <loadJSON> filepath = "sample_parameter.json"
$$$ <define> @var2 = 0.2
BEGIN{
TITLE = TEST01
x,y,z = ( 0.0, 1.0, 2.0 )
particle = electron
iterMax = 10
}END