回答:
ユーザーがアルゴリズムのあらゆる側面を指定するのは面倒です。アルゴリズムがネストされたコンポーネントを許可する場合、有限数のオプションでは十分ではありません。したがって、明示的な引数またはテンプレートパラメータの場合のように、オプションが必ずしも最上位に「バブルアップ」しないことが重要です。これは、ソフトウェアエンジニアリングでは「構成の問題」と呼ばれることがあります。PETScには、構成管理のための非常に強力なシステムがあると思います。これは、Martin Fowlerの制御の反転に関するエッセイのService Locatorパターンに似ています。
PETScの構成システムは、ソルバーオブジェクト(getおよびsetクエリ)とオプションデータベースによって管理されるユーザー指定の構成の組み合わせを通じて機能します。シミュレーションのどのコンポーネントでも、構成オプション、デフォルト値、および結果を配置する場所を宣言できます。ネストされたオブジェクトには構成可能なプレフィックスがあり、構成が必要なすべてのオブジェクトを個別にアドレス指定できます。オプション自体は、コマンドライン、環境、構成ファイル、またはコードから読み取ることができます。オプションが宣言されると、ヘルプ文字列とマニュアルページが指定されるため、-help
オプションが理解しやすくなり、適切にリンクされたGUIを作成できます。
ユーザーは SetFromOptions
メソッドをコマンドラインオプションに基づいてオブジェクトを自動的に構成します。この関数の呼び出しはオプションであり、ユーザー(PETScを呼び出すコードを書いている人)が他のインターフェースを介してオプションを公開している場合は呼び出されない場合があります。ユーザーがオプションデータベースを公開することを強くお勧めします。これは、エンドユーザー(アプリケーションを実行している人)に大きな力を与えるためですが、必須ではありません。
viaと呼ばれる典型的な構成
PetscObjectOptionsBegin(object); /* object has prefix and descriptive string */
PetscOptionsReal("-ts_atol", /* options database key */
"Absolute tolerance for local truncation error", /* long description */
"TSSetTolerances", /* function and man page on topic */
ts->atol, /* current/default value *?
&ts->atol, /* place to store value */
&option_set); /* TRUE if the option was set */
PetscOptionsList("-ts_type","Time stepping method","TSSetType",TSList,
defaultType,typeName,sizeof typeName,&option_set);
TSAdaptSetFromOptions(ts->adapt); /* configures adaptive controller method */
/* ... many others */
/* ... the following is only called from implicit implementations */
SNESSetFromOptions(ts->snes); /* configure nonlinear solver. */
PetscOptionsEnd();
ノート:
PetscOptionsList()
ユーザーに動的リストからの選択肢を提示します。新しい実装が呼び出し元にファーストクラスとして自身を公開するために使用できるプラグインアーキテクチャがあります。(これらの実装は、共有ライブラリに配置し、プログラムを再コンパイルせずにファーストクラスとして使用できます。)SNESSetFromOptions()
線形ソルバー、前提条件、および構成が必要なその他のコンポーネントを再帰的に構成します。独自のシミュレーションコードをゼロから開発するときに、この問題に何度か直面しました。どのパラメーターを入力ファイルに入力し、コマンドラインから取得する必要があるかなどです。(PETScほど高度ではありません。)
実験的なシミュレーション「プログラム」を作成する代わりに、シミュレーションの実行に必要なすべての関数とクラスを含むPythonパッケージを作成する傾向があります。その後、従来の入力ファイルは、5〜10行のコードを持つ小さなPythonスクリプトに置き換えられます。通常、一部の行はデータファイルのロードと出力の指定に関連しています。その他は、実際の計算のための指示です。Pythonパッケージのオプション引数の適切なデフォルト値により、初心者でも簡単なシミュレーションにライブラリを使用できますが、上級ユーザーはすべての機能にアクセスできます。
いくつかの例:
最初のポイントとして、私は可能な限り一般的なアルゴリズムとソフトウェアを実行します。私はこれを難しい方法で学びました。
簡単なテストケースから始めるとしましょう。これをより速く行うことができます。しかし、その後、この最初のケースに対してソフトウェアをあまりにも特定的(パラメーターが少なすぎる)にした場合、新しい自由度を追加するたびに、それを適応する時間をますます失うことになります。私が今やっていることは、最初はもっと一般的なことを行い、前進するにつれてパラメーターのバリエーションを増やしていきます。
これには、開始点からより多くのパラメーターがあるため、最初からより多くのテストが必要になりますが、ゼロまたは非常に低コストでアルゴリズムを後から多くプレイできることを意味します。
例:アルゴリズムは、2つのベクトル関数のドット積の表面積分の計算を伴います。将来的にそれを変更したい場合は、最初から表面のサイズ、ジオメトリ、離散化を想定しないでください。内積関数を作成し、可能な限り一般的な表面を作成し、適切な形式で積分を計算します。作成した各機能を個別にテストできます。
最初は、単純なジオメトリ上で統合を開始でき、開始時に定数としてmayパラメータを宣言できます。時間が経つにつれて、ジオメトリを変更したい場合は、簡単に変更できます。最初に想定していた場合、毎回コード全体を変更する必要があります。