OpenFOAMの境界条件の値を時間などの関数にする方法（PatchFunction1について）

:::note
以下の内容はOpenFOAM v2212で確認しています。
:::

# PatchFunction1とは？
パッチでの値に対応した[Function1](https://qiita.com/jmu26/items/9686ca6a592420e962f8)です。
基本的には時刻を引数として、パッチでの値を返す関数です。（ただし、引数とは関係のない値を出力できるtypeもあります。）

基本的には`uniformFixedValue`の境界条件の`uniformValue`の設定値として使用しますが、例えば`atmTurbulentHeatFluxTemperature`に設定する熱ソース`q`のようにパラメータ設定で使用できるものもあります。
（どのパラメータで使用ができるかは実装を確認しないと分かりません。）

# 書式
PatchFunction1の設定には、いくつかの書式があります。

### typeでPatchFunction1の種類を指定する方法
PatchFunction1で設定する設定項目のサブディクショナリに、typeでFunction1の種類を指定する方法です。私は下記の書式が一番読みやすいと思います。
（`<entryName>`はFunction1で設定できる設定項目の名前です。）

<entryName>

```c++
<entryName>
{
    type        sine;
    period      10.0;
    amplitude   0.1;
    scale       1.0;
    level       0.0;
}
```

### 一定値を設定する場合
一定値の値を設定する場合には、簡易的に以下のような書き方をすることができます。

```C++
<entryName>   10;
```
```c++
<entryName> zero;
```

### Coeffsを使用した書き方
PatchFunction1のパラメータを`<entryName>Coeffs`のサブディクショナリとして記述します。

```C++
<entryName>   sine;
<entryName>Coeffs
{
    period      10.0;
    amplitude   0.1;
    scale       1.0;
    level       0.0;
}
```

### ベタ書き
PatchFunction1のパラメータをサブディクショナリを使わずに指定する方法です。ベタ書きだと他の設定項目と混在してしまい、読み難くなると思います。

```c++
<entryName>   linearRamp;
period      10.0;
amplitude   0.1;
scale       1.0;
level       0.0;
```

# PatchFunction1の種類
ここからは、PatchFunction1で設定できる関数のタイプを種類ごとに説明します。

## 一定値を返すもの
### constant
一定値を返します。

```C++
<entryName>
{
    type    constant;
    value   <value>;
}
```

___
### one
常に$1$を返します。

___
### zero
常に$0$を返します。

## 数学関数
### polynomial
多項式による値を返します。
- 括弧の中に2つの数値を記述するTuple2形式で、係数と乗数を順に指定します。
- 下記の例では、$f(t)=t^2+2t^3$の意味になります。

```C+
<entryName>
{
    type   polynomial;
    coeffs
    (
        (1 2)
        (2 3)
    );
}
```

---
### sine
$\sin$関数による値を返します。

- 周期（Period）で指定する場合
$$
a\ s \sin(2 \pi (t - t_0) / p)) + l
$$

- 周波数（Frequency）で指定する場合
$$
a\ s \sin(2 \pi f (t - t_0)) + l
$$

```C++
<entryName>
{
    type        sine;
    frequency   10;
    amplitude   0.1;
    scale       2e-6;
    level       2e-6;
}
```

| 名前  | 意味           |       | 値のタイプ                 |   設定が必要か？   | デフォルト値 |
| :-------- | :-------------------- | :---: | :------------------- | :----------: | :-----: |
| amplitude | 振幅             |  $a$  | Function1&lt;scalar> |            |    1    |
| frequency | 周波数 [1/s]       |  $f$  | Function1&lt;scalar> |   periodとどちらか  |         |
| period    | 周期 [s]            |  $p$  | Function1&lt;scalar> | frequencyとどちらか |         |
| scale     | 係数   |  $s$  | Function1&lt;Type>   |      必要     |         |
| level     | オフセット値   |  $l$  | Function1&lt;Type>   |      必要     |         |
| t0        | 時間のオフセット値     | $t_0$ | scalar               |            |    0    |

___
### cosine
$\cos$関数による値を返す．

- 周期（Period）で指定する場合
$$
a\ s \cos(2 \pi (t - t_0) / p)) + l
$$

- 周波数（Frequency）で指定する場合
$$
a\s \cos(2 \pi f (t - t_0)) + l
$$


```C++
<entryName>
{
    type        cosine;
    frequency   10;
    amplitude   0.1;
    scale       2e-6;
    level       2e-6;
}
```

| 名前  | 意味           |       | 値のタイプ                 |   設定が必要か？   | デフォルト値 |
| :-------- | :-------------------- | :---: | :------------------- | :----------: | :-----: |
| amplitude | 振幅             |  $a$  | Function1&lt;scalar> |           |    1    |
| frequency | 周波数 [1/s]       |  $f$  | Function1&lt;scalar> |   periodとどちらか  |         |
| period    | 周期 [s]            |  $p$  | Function1&lt;scalar> | frequencyとどちらか |         |
| scale     | 係数   |  $s$  | Function1&lt;Type>   |      必要     |         |
| level     | オフセット値   |  $l$  | Function1&lt;Type>   |      必要     |         |
| t0        | 時間のオフセット値     | $t_0$ | scalar               |            |    0    |

___
### square
出力値が$[-1, 1]$の範囲の周期的な[矩形関数](https://ja.wikipedia.org/wiki/%E7%9F%A9%E5%BD%A2%E9%96%A2%E6%95%B0) $\mathrm{rect}$ による値を返します。

- 周期（Period）で指定する場合
$$
a\ s\ \mathrm{rect}((t - t0) / p)) + l
$$

- 周波数（Frequency）で指定する場合
$$
a\ s\ \mathrm{rect}(f (t - t0)) + l
$$

値が$1$になっている時間と$0$になっている時間の割合 $r$ を指定することもできます。
$$
    r= {M \over{M + S}}
$$

```C++
<entryName>
{
    type        square;
    frequency   10;
    amplitude   0.1;
    scale       2e-6;
    level       2e-6;
}
```

| 名前  | 意味           |       | 値のタイプ                 |   設定が必要か？   | デフォルト値 |
| :-------- | :-------------------- | :---: | :------------------- | :----------: | :-----: |
| amplitude | 振幅             |  $a$  | Function1&lt;scalar> |            |    1    |
| frequency | 周波数 [1/s]       |  $f$  | Function1&lt;scalar> |   periodとどちらか  |         |
| period    | 周期 [s]            |  $p$  | Function1&lt;scalar> | frequencyとどちらか |         |
| scale     | 係数   |  $s$  | Function1&lt;Type>   |      必要     |         |
| level     | オフセット値   |  $l$  | Function1&lt;Type>   |      必要     |         |
| t0        | 時間のオフセット値     | $t_0$ | scalar               |            |    0    |
| mark      | $1$の時間       |  $M$  | scalar               |            |    1    |
| space     | $0$の時間       |  $S$  | scalar               |            |    1    |

## テーブル補間
指定したテーブルを使って、補間した値を返すことができます。

### csvFile
csvファイルから補間された値を返します。
```C++
<entryName>
{
    type  csvFile;
    nHeaderLine         4;          // ヘッダー部分の行数
    refColumn           0;          // 入力値のデータがかかれたカラム番号
    componentColumns    (1 2 3);    // 補間するデータが書かれたカラム番号
    separator           ",";        // データの区切り文字 (デフォルトは ",")
    mergeSeparators     no;         // 複数の区切り文字をマージするかどうか
    file                "fileXYZ";  // csvファイルのファイル名
    outOfBounds         clamp;      // 範囲外のデータ処理方法（オプション）
    interpolationScheme linear;     // 補間方法 [linear(デフォルト)|spline]（オプション）
}
```

___
### table
OpenFOAM形式のテーブルから補間された値を返します。

```C++
<entryName>
{
    type table;
    values
    (
        (0.0 (1 2 3))
        (1.0 (4 5 6))
    );
    outOfBounds         clamp;      // 範囲外のデータ処理方法（オプション）
    interpolationScheme linear;     // 補間方法 [linear(デフォルト)|spline]（オプション）
}
```

テーブルデータが書かれたファイル名を指定することもできます。
```C++
<entryName>
{
    type table;
    file "<case>/path/tableValues"; // ファイル名
}
```

___
### tableFile
OpenFOAM形式のテーブルファイルから補間された値を返します。
機能としては、tableのタイプでファイル名を指定する場合と同じです。

```C++
<entryName>
{
    type table;
    file "<case>/path/tableValues";
    outOfBounds         clamp;      // 範囲外のデータ処理方法（オプション）
    interpolationScheme linear;     // 補間方法 [linear(デフォルト)|spline]（オプション）
}
```

## その他
特殊な用途で使用できるタイプがいくつかあります。

### sample
他のセルでの指定したフィールドの値を参照することができます。
実装は`libsampling.so`に入っているので、decomposeParなど、このライブラリがリンクされていないツールで使用するとエラーが発生します。このような場合には、`system/controlDict`に`lib (sampling);`の記述が必要となります。

```C++
<entryName>
{
    type            sample;
    field           T;            // 値を参照するフィールド名
    position        (0 0 0);      // 値を参照する点
    interpolationScheme cell;     // 値の補間方法（デフォルト：cell）
}
```

---
### sampled
`mappedField`の境界条件と同じように、値を与える境界を指定した方向にオフセットした箇所での解析領域内の補間された値を返します。
循環参照にならないように注意する必要があります。

```C++
<entryName>
{
    type            sampled;
    field           U;            // 値を参照するフィールド名
    sampleMode      nearestCell;  // サンプリングの手法
    offset          (0 -0.001 0); // 値を参照する点
    interpolationScheme cell;     // 値の補間方法（デフォルト：cell）
}
```

| 名前  | 意味                            |   設定が必要か？   | デフォルト値 |
| :------------------ | :-------------------------- | :------: | :-----------: |
| field               | フィールド名                  | 必要      |               |
| sampleMode          | サンプリングの手法       | 必要      |               |
| sampleRegion        | サンプリング対象の領域              |        |             |
| samplePatch         | サンプリング対象のパッチ名             |        |             |
| offsetMode          | オフセット方法       |        | uniform       |
| offset              | オフセットベクトル       |        | (0 0 0)       |
| interpolationScheme | 補間方法        | 必要      | cell          |
| setAverage          | 平均値を指定するかどうか |        | false         |
| average             | 平均値の指定値      |        |               |

---
### mappedFile
`timeVaryingMappedFixedValueの境界条件`と同じように、座標値を指定した定義点と物理量の離散的なデータを記述した外部ファイルからマッピングを行った値を返します。
定義点の座標値は、`constant/boundaryData/<patchName>/points`ファイルにOpenFOAM形式で指定します。
定義点での物理量は、`constant/boundaryData/<patchName>/<time>/<field>`ファイルにOpenFOAM形式で指定します。

#### 設定値一覧
| 名前   | 意味                                     | 値のタイプ               | 設定が必要か？ | デフォルト値      |
| ---------- | ----------------------------------------------- | ------------------ | :--: | :--------: |
| mapMethod  | マッピングの方法                                  | word               |    | planar     |
| offset     | 補間された値に対するオフセット値 | Function1&lt;Type> |    | -          |
| fieldTable | フィールドデータテーブルのファイル名                        | word               |   | field-name |
| points     | 定義点の座標値のファイル名                         | word               |    | points     |
| setAverage | 平均値を指定するかどうか   | bool             | no   | false      |

#### `mapMethod`の設定値一覧
| Property | Description                                    |
| -------- | ---------------------------------------------- |
| nearest  | 最近傍の値を使用する |
| planar   | 二次元のデローニ法による補間  |


---
### scale
`value`で指定したFunction1&lt;Type>の値に，`scale`で指定したFunction1&lt;scalar>の値を乗じて、`value`の値をスケーリングすることができます。
- `scale`と`value`には[Function1](https://qiita.com/jmu26/items/9686ca6a592420e962f8)が使用できます。
（[ramp系のFunction1](https://qiita.com/jmu26/items/9686ca6a592420e962f8#ramp%E7%B3%BB)も使用可能）

```C++
<entryName>
{
    type      scale;

    scale
    {
        type        linearRamp;
        start       0;
        duration    10;
    }

    value
    {
        type        sine;
        frequency   10;
        amplitude   1;
        scale       (1 0.1 0);
        level       (10 1 0);
    }
}
```

---
### coded
実行時にコンパイルされるソースコードで、計算された値を返します。

次のようなディレクティブを指定することができます。

       codeInclude | include files
       codeOptions | compiler line: added to EXE_INC (Make/options)
       codeLibs    | linker line: added to LIB_LIBS (Make/options)
       localCode   | c++; local static functions
       code        | c++; return the patch values at (scalar x)

下記の例は、入力値の2倍の値を返す例です。
```C++
<entryName>
{
    type  coded;
    name  myExpression;  // 名前

    code
    #{
        const polyPatch& pp = this->patch();
        Pout<< "** Patch size:" << pp.size() << endl;
        return tmp<scalarField>::New(pp.size(), 2.0*x)     // 引数はx
    #};

    //codeInclude
    //#{
    //    #include "volFields.H"
    //#};

    //codeOptions
    //#{
    //    -I$(LIB_SRC)/finiteVolume/lnInclude
    //#};
}
```

---
### functionObjectValue
他のファンクションオブジェクトの値を返します。

- 使用できる値は、時刻ディレクトリの`uniform/functionObjects/functionObjectProperties`の出力内容で確認することができます
- 型の違いに注意
    - scalarの値を返さなければいけない箇所で，labelの値を出力する結果を指定すると、常に$0$が返ります


```C++
<entryName>
{
    type                    functionObjectValue;
    functionObject          <name>;
    functionObjectResult    <function object result field>;
    defaultValue            <value>; // 値が出力できない場合に返される値（オプション）
}
```

---
### expression
expressionの機能で演算された値を返します。
- [こちらのexpressionの説明](https://www.openfoam.com/documentation/guides/latest/doc/openfoam-guide-expression-syntax.html#autotoc_md1336)の「patchExpr」のexpression parserが使用可能です
- `args()`が引数です
-
複雑な設定をしようとするとバグなどの問題に直面する可能性がありそうです。よく検証してから使用したほうがよいと思います。

```C++
<entryName>
{
    type            expression;

    // optional variables for use within the expression
    variables
    (
        "start = 0.5"
        "stop  = 1"
    );

    // A step function
    expression
    #{
        mag(arg() > start && arg() < stop) * vector(1, 0, 0)
    #};
}
```