> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ionworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 目的関数

> iws.objectives と iws.costs でデータフィッティングの目的関数とコスト関数を構成します

`DataFit` には 2 つの関連する要素があります。

* **目的関数** (`iws.objectives.*`) — どの実験でモデル出力と比較するか。
* **コスト** (`iws.costs.*`) — 点ごとの差をどう 1 つのスカラに集約するか。

各コストの数学的背景は [目的関数 (英語ガイド)](/guide/data-fitting/objective-functions) を参照してください。

## 利用可能なコスト関数

| スキーマ                      | 数式                                                                                     | 用途                                                                                                                       |
| ------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `iws.costs.SSE()`         | $\sum_i r_i^2$                                                                         | デフォルト。全オプティマイザと互換                                                                                                        |
| `iws.costs.MSE()`         | $\frac{1}{N}\sum_i r_i^2$                                                              | スケールを意識した平均二乗残差                                                                                                          |
| `iws.costs.RMSE()`        | $\sqrt{\frac{1}{N}\sum_i r_i^2}$                                                       | 解釈可能な単位。スカラのみ(残差配列型のオプティマイザでは使えない)                                                                                       |
| `iws.costs.MAE()`         | $\frac{1}{N}\sum_i \lvert r_i \rvert$                                                  | 外れ値に頑健                                                                                                                   |
| `iws.costs.Max()`         | $\max_i \lvert r_i \rvert$                                                             | 平均ではなく最悪ケース(絶対値最大)の残差を最小化する                                                                                              |
| `iws.costs.Wasserstein()` | $\frac{1}{N}\sum_i \lvert \tilde y_{\text{model},i} - \tilde y_{\text{data},i} \rvert$ | 時系列の点ごとではなく分布(ソート済みサンプル)同士を一致させる。`position_variable` と `weight_variable` を設定すると[重み付き点群モード](#wasserstein-重み付き点群モード)に切り替わる |

最尤推定には `iws.costs.GaussianLogLikelihood` を使用してください — 変数ごとのノイズ標準偏差を受け取るか、フィッティングパラメータと併せて推定することもできます。ベイズ推定や MAP 推定に適したガウス負対数尤度を生成します。

## コストをフィットに組み込む

```python theme={null}
import pybamm
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "1C": iws.objectives.CurrentDriven(
            data_input="file:.../1C.csv",
            options={"model": pybamm.lithium_ion.SPMe()},
        ),
    },
    parameters={
        "Negative particle diffusivity [m2.s-1]": iws.Parameter(
            "Negative particle diffusivity [m2.s-1]",
            initial_value=2e-14,
            bounds=(1e-14, 1e-13),
        ),
    },
    cost=iws.costs.RMSE(),
)
```

`cost` を省略すると、オプティマイザのデフォルトコスト関数(通常は最小二乗形式)が使われます。

<Note>
  `cost` はコストスキーマのインスタンス (例: `iws.costs.RMSE()`) または `type` キーを明示した設定 dict (例: `{"type": "RMSE"}`) を受け付けます。`cost="RMSE"` のような名前だけの文字列は検証エラーで拒否されます — 代わりに `{"type": "RMSE"}` のようにラップしてください。
</Note>

## Wasserstein 重み付き点群モード

`iws.costs.Wasserstein()` はデフォルトでは目的変数ごとにモデルとデータのサンプルを比較します(ソート点ごとの比較、均一な重み)。`position_variable` と `weight_variable` を両方指定すると **重み付き点群モード** に切り替わり、一方が位置を、もう一方が(符号を除去・再正規化した)重みを供給して、目的ごとに 1 回 Wasserstein-1 距離を計算します。

dQ/dV のピークを電圧上で揃えるなど、サンプル単位の値ではなく *位置で密度を一致させたい* 場合に使います。

`iws.objectives.MSMRFullCell` と `iws.objectives.ElectrodeBalancing` の両方が、対応する `Differential capacity [Ah/V]` 値とその `Voltage [V] (dQdU)` マスク済み軸の兄弟キーを出力するため、いずれも重み付き点群フィットに利用できます:

```python theme={null}
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "ocp": iws.objectives.ElectrodeBalancing(
            data_input="file:.../ocv.csv",
            options={
                "objective variables": [
                    "Differential capacity [Ah/V]",
                    "Voltage [V] (dQdU)",
                ],
            },
        ),
    },
    parameters={...},
    cost=iws.costs.Wasserstein(
        position_variable="Voltage [V] (dQdU)",
        weight_variable="Differential capacity [Ah/V]",
    ),
)
```

<Note>
  `position_variable` と `weight_variable` は同時に指定する必要があります — 片方だけ指定すると検証エラーになります。重みは絶対値が取られ内部で再正規化されるため、dQ/dV の符号規則は問題になりません。このモードでは残差配列出力は利用できません。
</Note>

## OCV フィットのための `ElectrodeBalancing` オプション

`ElectrodeBalancing` は、目的関数を評価する前のフルセル OCV 処理を制御するために、`options` 辞書で次のキーを受け付けます。これらは、フィットで使用するコスト関数(重み付き `Wasserstein` に限らない)に関係なく適用されます:

| オプション                 | 型                                   | デフォルト                                            | 用途                                                                                                                                                                                    |
| --------------------- | ----------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `objective variables` | list of str                         | `["Voltage [V]", "Differential voltage [V/Ah]"]` | モデルとデータの間で比較する変数。`"Differential capacity [Ah/V]"` を追加すると、データの電圧グリッド上のモデル dQ/dU と、マスク済み軸の兄弟キー `"Voltage [V] (dQdU)"`・`"Capacity [A.h] (dQdU)"` も出力され、重み付き Wasserstein コストで利用できます。      |
| `dUdQ cutoff`         | float \| None                       | `None`                                           | `dU/dQ` がこの値を超えるデータ点を除外します — 電圧上下限近くのほぼ垂直な領域をマスクするのに有効です。                                                                                                                             |
| `dQdU cutoff`         | float \| None                       | `None`                                           | `dQ/dU` がこの値を超えるデータ点を除外します — `dQ/dU` が発散する平坦な OCV 領域をマスクするのに有効です。Wasserstein で重みが非負になるよう、0 以下の値は常に除外されます。                                                                             |
| `direction`           | `"charge"` \| `"discharge"` \| None | `None`                                           | OCV スキャンの方向。`None` は方向を仮定しません。                                                                                                                                                        |
| `GITT`                | bool                                | `False`                                          | データを疎な GITT サンプルとして扱い、微分を計算する前に補間でアップサンプリングします。                                                                                                                                       |
| `dQdU model axis`     | bool                                | `False`                                          | `True` の場合、モデル自身の全窓電圧軸上の dQ/dV を `"Differential capacity [Ah/V] (model axis)"` / `"Voltage [V] (model axis)"` として追加で出力します — [モデル電圧軸で dQ/dV ピークを揃える](#モデル電圧軸で-dqdv-ピークを揃える) を参照してください。 |

```python theme={null}
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "ocp": iws.objectives.ElectrodeBalancing(
            data_input="file:.../ocv.csv",
            options={
                "direction": "discharge",
                "GITT": True,
                "dUdQ cutoff": 1.0,
                "dQdU cutoff": 50.0,
                "objective variables": [
                    "Differential capacity [Ah/V]",
                    "Voltage [V] (dQdU)",
                ],
            },
        ),
    },
    parameters={...},
    cost=iws.costs.Wasserstein(
        position_variable="Voltage [V] (dQdU)",
        weight_variable="Differential capacity [Ah/V]",
    ),
)
```

## `calculation_structure` でコストをスコープする

デフォルトでは `DataFit` 上の各コストは、出力に存在するすべての目的関数とすべての目的変数を消費します。コストに `calculation_structure` を設定すると明示的にスコープを指定できます — 目的関数名から、そのコストが計算する変数名のリスト(または `None` でその目的関数の全変数、空リストで何も計算しない)へのマッピングです。

マッピングから外した目的関数は除外されません。`DataFit` の内部では、スコープされていない各目的関数はその全変数(`None` を指定した場合と同じ)にバインドされます。そのため、`"cc"` という目的関数も存在する状態で一方だけをスコープしても(例: `{"ocp": ["Voltage [V]"]}`)、`"cc"` は引き続き全変数で計算されます。

1 つのコストが変数のサブセットだけを見るようにしたい場合に使います。最も一般的なのは、変数ごとのコスト(例: `SSE`)と重み付き `Wasserstein` を併用するケースです。Wasserstein 側が dQ/dV 変数(モデル側とデータ側で長さが構造的に異なる)を担当し、SSE 側はスコープでそれらを除外するため、長さが衝突することはありません。

```python theme={null}
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "ocp": iws.objectives.ElectrodeBalancing(
            data_input="file:.../ocv.csv",
            options={
                "objective variables": [
                    "Voltage [V]",
                    "Differential capacity [Ah/V] (model axis)",
                    "Voltage [V] (model axis)",
                ],
                "dQdU model axis": True,
            },
        ),
    },
    parameters={...},
    cost=[
        iws.costs.SSE(
            calculation_structure={"ocp": ["Voltage [V]"]},
        ),
        iws.costs.Wasserstein(
            position_variable="Voltage [V] (model axis)",
            weight_variable="Differential capacity [Ah/V] (model axis)",
            calculation_structure={
                "ocp": [
                    "Voltage [V] (model axis)",
                    "Differential capacity [Ah/V] (model axis)",
                ],
            },
        ),
    ],
)
```

<Note>
  `calculation_structure` は非推奨となった `objective_names`(目的関数名のフラットリストで、変数単位の制御がない)の置き換えです。同じコストに両方を指定すると検証エラーになります。
</Note>

### 長さ不一致の警告

要素ごとのコスト(`SSE`、`MSE`、`RMSE`、`MAE`、`Max`)はモデル配列とデータ配列を点ごとに結合するため、モデル側とデータ側の長さが異なる変数では意味のあるスコアになりません。`DataFit` はフィット設定時に、各コストがスコアリングする全変数の形状を確認し、不一致があるごとに `UserWarning` を発行します。例:

```text theme={null}
UserWarning: variable 'Voltage [V] (model axis)' of objective 'ocp' has mismatched
model/data shapes ((512,) vs (128,)). An element-wise cost will combine them
point-by-point, which is almost never intended. Scope the cost with an explicit
`calculation_structure` so each variable is compared against a matching-length
counterpart.
```

このチェックはフィット設定時に一度だけ実行され(目的関数評価ごとではない)、フィット性能に影響しません。この警告が出たら、[`calculation_structure`](#calculation_structure-でコストをスコープする) を使ってモデル側とデータ側の長さが一致する変数のみコストが見るようにスコープし、モデル軸変数は `Wasserstein`(または他の分布メトリック)に振り分けてください。`Wasserstein` のような分布コストは長さの異なるサンプル集合を想定しているため、チェックの対象外です。

## モデル電圧軸で dQ/dV ピークを揃える

`iws.objectives.ElectrodeBalancing` は、データ電圧グリッドに加えて(あるいは代わりに) **モデル自身の全窓電圧軸** で dQ/dV を出力できます。`options` に `dQdU model axis: True` を指定し、`objective variables` にモデル軸版の 2 つの変数 — `"Differential capacity [Ah/V] (model axis)"` と `"Voltage [V] (model axis)"` — を追加してください。

重み付きコスト(典型的には[点群モード](#wasserstein-重み付き点群モード)の `Wasserstein`)に *位置シフト* を行わせたい — つまりデータグリッド上の残差ごとではなく電圧上で dQ/dV ピークを揃えたい — 場合に使います。モデル側とデータ側は長さが構造的に異なるため、これらを消費できるのは重み付きコストだけです。フィット全体の整合性を保つため、上記の `calculation_structure` でスコープした変数ごとのコストと組み合わせて使ってください。

既存のデータ軸変数(`"Differential capacity [Ah/V]"` と、マスク軸の兄弟変数 `"Voltage [V] (dQdU)"` / `"Capacity [A.h] (dQdU)"`)も引き続き利用できます — 両方の軸を同時にリクエストできます。

## 利用可能な目的関数

| スキーマ                                                                     | 用途                                                                                                                                                                    |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iws.objectives.CurrentDriven(data_input=..., options={...})`            | 電流駆動の時系列電圧データ(ドライブサイクル、カスタム負荷)                                                                                                                                        |
| `iws.objectives.Pulse(data_input=..., options={...})`                    | パルス実験 — GITT、HPPC、ICI — 特徴量抽出のバリエーションも選択可能                                                                                                                            |
| `iws.objectives.OCPHalfCell(electrode=..., data_input=...)`              | ハーフセル OCP 曲線                                                                                                                                                          |
| `iws.objectives.MSMRHalfCell(...)`                                       | ハーフセルデータへの MSMR パラメータフィット                                                                                                                                             |
| `iws.objectives.MSMRFullCell(...)`                                       | フルセルデータへの MSMR パラメータフィット。目的変数として `Differential voltage [V/Ah]` と `Differential capacity [Ah/V]` をサポート                                                                 |
| `iws.objectives.ElectrodeBalancing(...)`                                 | フルセル放電からの化学量論窓。目的変数として `Differential voltage [V/Ah]` と `Differential capacity [Ah/V]` をサポート — [`ElectrodeBalancing` オプション](#ocv-フィットのための-electrodebalancing-オプション)を参照 |
| `iws.objectives.EIS(...)`                                                | 電気化学インピーダンススペクトル                                                                                                                                                      |
| `iws.objectives.Resistance(...)`                                         | パルスデータから抽出した直流抵抗                                                                                                                                                      |
| `iws.objectives.CalendarAgeing(...)` / `iws.objectives.CycleAgeing(...)` | 劣化曲線                                                                                                                                                                  |

複数を組み合わせるには `DataFit.objectives` に `dict[str, objective]` を渡します。

## `GITTModel`: GITT・パルスフィット用の拡散のみモデル

`GITTModel` は GITT やパルス緩和測定から**固相拡散係数**(および単一の集中定数オーミック抵抗)を抽出するためのフィッティング専用モデルです。各電極の x 平均された球状粒子拡散を解き、表面フラックスは印加電流から決定されます。セル電圧は粒子表面ストイキオメトリで評価した開回路電位から、集中定数 `"Ohmic resistance [Ohm]"` パラメータによるオーミック降下を引いて計算します。

反応速度論(Butler-Volmer)、電解液動力学、熱効果はいずれも含まれません — OCP を除くすべてのパラメータは定数として扱われます。GITT やパルスデータの拡散律速領域に対して高速かつ良条件のフィットを行いたい場合に使用してください。完全な物理シミュレーションが必要な場合は `SPM` / `SPMe` / `DFN` を選択してください。

`"working electrode"` オプションでセル構成を選択します。

| `"working electrode"` | 構成                                                                                                                                                                 |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `"both"`(デフォルト)       | フルセル。両電極を計算対象とします。正(放電)電流は負極を脱リチウム化し、正極をリチウム化します。                                                                                                                  |
| `"positive"`          | リチウム金属対極に対するハーフセル(pybamm のハーフセル規約)。作用電極のみを計算対象とします。正電流は作用電極をリチウム化します(正極材料では放電、負極材料では充電に相当します)。負極材料のハーフセルでも `"positive"` を使用します — その場合は事前に負極パラメータを正極側の名称に置き換えてください。 |

各計算対象電極は、標準的なフルセルのパラメータ名(厚み、活物質体積分率、粒子半径、拡散係数、OCP、最大濃度・初期濃度)に加えて、電流関数、電極断面積、初期温度、`"Ohmic resistance [Ohm]"` でパラメータ化されます。

### フルセル GITT 測定へのフィット

```python theme={null}
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "gitt": iws.objectives.Pulse(
            data_input="file:.../gitt.csv",
            options={
                "model": iws.models.GITTModel(),
            },
        ),
    },
    parameters={
        "Negative particle diffusivity [m2.s-1]": iws.Parameter(
            "Negative particle diffusivity [m2.s-1]",
            initial_value=2e-14,
            bounds=(1e-15, 1e-12),
        ),
        "Positive particle diffusivity [m2.s-1]": iws.Parameter(
            "Positive particle diffusivity [m2.s-1]",
            initial_value=2e-15,
            bounds=(1e-16, 1e-13),
        ),
        "Ohmic resistance [Ohm]": iws.Parameter(
            "Ohmic resistance [Ohm]",
            initial_value=0.02,
            bounds=(1e-3, 1e-1),
        ),
    },
)
```

### ハーフセルパルス測定へのフィット

リチウム金属対極に対する片側電極のみをモデル化するには `"working electrode": "positive"` を指定します。必要なのは作用電極側のパラメータだけです。

```python theme={null}
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "pulse": iws.objectives.Pulse(
            data_input="file:.../half_cell_pulse.csv",
            options={
                "model": iws.models.GITTModel(
                    options={"working electrode": "positive"},
                ),
            },
        ),
    },
    parameters={
        "Positive particle diffusivity [m2.s-1]": iws.Parameter(
            "Positive particle diffusivity [m2.s-1]",
            initial_value=2e-15,
            bounds=(1e-16, 1e-13),
        ),
        "Ohmic resistance [Ohm]": iws.Parameter(
            "Ohmic resistance [Ohm]",
            initial_value=0.02,
            bounds=(1e-3, 1e-1),
        ),
    },
)
```

<Note>
  `"working electrode"` が受け付ける値は `"both"` または `"positive"` のみで、それ以外はスキーマ検証で失敗します。`options` のその他のキーはパラメータ管理用に内部の電池モデルオプションへ転送されますが、拡散のみという物理には影響しません。
</Note>

## `data_input` の指定方法

各 objective の `data_input`(および calculation や interpolant の `data` フィールド)は、以下のいずれの形式も受け付けます:

* 参照文字列: アップロード済みの測定データを参照するには `"db:<id>"` を使います。`"file:..."` と `"folder:..."` はローカルマシンから読み取られ、送信時に API クライアントによって config へインライン化されます。そのため、ローカル実行でも Ionworks にフィットを送信する場合でも動作します。ただし裸の `DataFrame` と同じ 1,000 行のインライン上限が適用されます。より大きなデータセットは測定としてアップロードしてから `"db:<id>"` で参照してください。
* `ionworksdata.DataLoader`(ローカル、または `DataLoader.from_db(...)` で取得したもの)。
* 事前に読み込み済みの pandas または polars の `DataFrame`。

```python theme={null}
import pybamm
import ionworks_schema as iws
import pandas as pd

df = pd.DataFrame(
    {
        "Time [s]": [...],
        "Voltage [V]": [...],
        "Current [A]": [...],
    }
)

obj = iws.objectives.CurrentDriven(
    data_input=df,
    options={"model": pybamm.lithium_ion.SPMe()},
)
```

裸の `DataFrame` を渡した場合、シリアライズ時にパーサーが期待する `{"data": <columns>}` の形に自動的にラップされます — つまり `data_input=df` と `data_input={"data": df}` は等価です。文字列パスや、すでにラップ済みの dict はそのまま渡されます。

<Note>
  インラインで渡す `DataFrame` は 1 回あたり 1,000 行までです。それより大きなデータセットは事前に measurement としてアップロードし、ID で参照してください。[インライン時系列のサイズ制限](/ja/data/reading#インライン時系列のサイズ制限)を参照してください。
</Note>

## CycleAgeing の実験をデータから生成する

`iws.objectives.CycleAgeing` は通常、サイクルプロトコルを表す `pybamm.Experiment` を明示的に指定する必要があります。プロトコルがすでにデータに付随するサイクラーのステップ情報に含まれている場合は、`experiment="from data"` を指定することで、実験を手作業で組み立て直す手間を省けます。実験はフィット開始時に `DataLoader.generate_experiment()` を呼び出して遅延生成されます。

次のような場合に使用します:

* フィット対象のデータが独自のステップ情報を持つ場合 (ローカルの `ionworksdata.DataLoader`、または `DataLoader.from_db(...)` で取得したもの)。
* シミュレーションのプロトコルを測定プロトコルに正確に合わせたい場合 — サイクラーが記録した各ステップの電流、電圧の上下限、継続時間も含めて。

```python theme={null}
import pybamm
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "ageing": iws.objectives.CycleAgeing(
            data_input="db:<measurement-id>",
            options={
                "model": pybamm.lithium_ion.SPM(options={"SEI": "ec reaction limited"}),
                "experiment": "from data",
                "objective variables": ["LLI [%]"],
            },
        ),
    },
    parameters={...},
)
```

フィット対象のデータ (例えばサイクルごとの集計テーブル) が、プロトコルを定義する測定とは別のオブジェクトの場合は、`experiment` に別の `DataLoader` を渡します — ステップ情報はその `DataLoader` から取得され、残差は引き続き `data_input` に対して計算されます:

```python theme={null}
import pybamm
import ionworksdata as iwdata
import ionworks_schema as iws

protocol = iwdata.DataLoader.from_db("<protocol-measurement-id>")

fit = iws.DataFit(
    objectives={
        "ageing": iws.objectives.CycleAgeing(
            data_input="db:<summary-measurement-id>",
            options={
                "model": pybamm.lithium_ion.SPM(),
                "experiment": protocol,
                "objective variables": ["LLI [%]"],
            },
        ),
    },
    parameters={...},
)
```

<Note>
  `experiment="from data"` は、`data_input` がステップ情報を持つ `DataLoader` (またはその `"data"` エントリが `DataLoader` である dict) に解決される必要があります。`experiment` に別の `DataLoader` を渡す場合は、ステップ情報はその `DataLoader` に含まれている必要があります。いずれの場合も、ステップ情報を欠いた構成は、シミュレーションが走る前に目的関数の構築時点で明確なエラーとともに即座に失敗します。
</Note>

## 自動構築されるソルバーのチューニング

シミュレーションを伴う目的関数 (`CurrentDriven`、`Pulse`、`CalendarAgeing`、`CycleAgeing`、`MSMRFullCell` など) は、明示的な `solver` が指定されていない場合に `IonworksSolver` を自動構築します。チューニング済みのデフォルトをすべて書き直すことなく一部だけを上書きしたい場合は、`simulation_kwargs` の中で `solver_kwargs` を渡します:

* ネストされた `options` はデフォルトの IDAKLU オプションにマージされます。例えば `{"options": {"compile": True}}` はモデルコンパイルだけを有効化し、他のチューニング済みオプションはそのまま維持します。
* その他のトップレベルキー (`atol`、`rtol`、`on_extrapolation` など) は、対応するデフォルトのソルバー kwargs を上書きします。

`solver_kwargs` は、明示的な `solver` が指定された場合は警告とともに無視されます — その場合はソルバーインスタンス上で直接設定してください。また、モデルのデフォルトソルバーが IDAKLU ベースでない場合も無視されます。

```python theme={null}
import pybamm
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "1C": iws.objectives.CurrentDriven(
            data_input="file:.../1C.csv",
            options={
                "model": pybamm.lithium_ion.SPMe(),
                "simulation_kwargs": {
                    "solver_kwargs": {
                        "options": {"compile": True},
                        "atol": 1e-8,
                    },
                },
            },
        ),
    },
    parameters={...},
)
```

<Tip>
  事前に `compile` を有効化する (`{"options": {"compile": True}}`) と、一度きりのコンパイルコストと引き換えに繰り返しの評価が高速になります — 同じ目的関数をフィットやスイープ中に何度も解くようなケースで有効です。
</Tip>

### 実行時の solve への kwargs の転送

`simulation_kwargs` は `solve_kwargs` も受け付けます。これは、目的関数の評価ごとに実行される `sim.solve(...)` 呼び出しへ転送される dict です。ソルバ本体ではなく solve 呼び出し自体に渡すべき引数 — 例えば直前の解からウォームスタートするための `starting_solution` や、その他の `pybamm.Simulation.solve` 引数 — に使用します。

* `solve_kwargs` は、目的関数がソルバを自動構築した場合でも、明示的な `solver` を指定した場合でも常に適用されます。どのソルバとも互換のある、solve 時の引数を渡す推奨方法です。
* 上で説明した `solver_kwargs` は自動構築されたソルバを **構築時** にチューニングします。一方 `solve_kwargs` は各 **solve 呼び出し** を設定します。両者は独立しており、組み合わせて使えます。
* 目的関数が直接制御するキー — `inputs`、`initial_soc`、`t_eval`、`t_interp`、`frequencies` — は予約されており、`solve_kwargs` で渡すと `ValueError` が発生します。
* `CycleAgeing` では `save_at_cycles` はメトリックから自動的に導出されます。`solve_kwargs` で値を渡しても、メトリックに必要なサイクルが保持されるよう警告とともに無視されます。

```python theme={null}
import pybamm
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "pulse": iws.objectives.Pulse(
            data_input="file:.../pulse.csv",
            options={
                "model": pybamm.lithium_ion.SPMe(),
                "simulation_kwargs": {
                    # 自動構築されたソルバのチューニング (構築時):
                    "solver_kwargs": {"options": {"compile": True}},
                    # 毎回の sim.solve(...) 呼び出しへの転送 (実行時)。
                    # prior_solution は事前の sim.solve(...) で得た
                    # pybamm.Solution です — 自身のものに置き換えてください:
                    "solve_kwargs": {"starting_solution": prior_solution},
                },
            },
        ),
    },
    parameters={...},
)
```

### `CycleAgeing`: first/last のみの metrics に対する `store_first_last` の自動有効化

`CycleAgeing` では、各目的変数を `.by_cycle()` のメトリックにマッピングする `metrics` を指定できます。`"LLI [%]"`、`"LAM_ne [%]"`、`"LAM_pe [%]"` にはデフォルトが用意されており、いずれもステップごとに 1 サンプルだけを読み取ります。

`metrics` のすべてのメトリックがステップの最初または最後のサンプルのみを読み取る場合（デフォルト、または任意の `First` / `Last` の `.by_cycle()` メトリック）、`CycleAgeing` は `solver_kwargs["store_first_last"]` を自動で `True` に設定します。これによりソルバは各ステップの端点のみを保存するため、長期サイクル解析でメモリ使用量を大幅に削減でき、これらのメトリックの結果は変わりません。

このフラグは安全な場合にのみ自動で設定されます:

* 内部点を読み取るメトリック（例: `Mean(...).by_cycle()`）ではデフォルトは無効のままで、サンプルは間引かれません。
* 合成メトリック（`First`/`Last` を含む演算）は安全側に倒して自動有効化されません。
* `solver_kwargs` に `store_first_last` が明示指定されている場合は常にそれが優先されます。
* 独自の `solver` を指定した場合は、他と同様に `solver_kwargs` の注入自体がスキップされます。

```python theme={null}
import pybamm
import ionworks_schema as iws

fit = iws.DataFit(
    objectives={
        "ageing": iws.objectives.CycleAgeing(
            data_input="file:.../ageing.csv",
            options={
                "model": pybamm.lithium_ion.SPM(),
                "experiment": "from data",
                "objective variables": ["LLI [%]", "LAM_ne [%]"],
                # デフォルトのメトリックは first/last のみを読み取るため、
                # store_first_last は自動的に有効化されます。明示的に上書きする場合:
                # "simulation_kwargs": {
                #     "solver_kwargs": {"store_first_last": False},
                # },
            },
        ),
    },
    parameters={...},
)
```

<Tip>
  ほとんどのオプティマイザでは `SSE` が最も無難です — 残差配列形式とスカラ形式の両方を持つため、すべてのアルゴリズムと互換性があります。スケール非依存の報告が必要な場合は `MSE` / `RMSE` を使用してください。
</Tip>

<CardGroup cols={2}>
  <Card title="目的関数 (理論)" icon="bullseye" href="/guide/data-fitting/objective-functions">
    残差形式と正準形式、MLE の解釈 (英語ガイド)。
  </Card>

  <Card title="データフィッティング概要" icon="chart-line" href="/ja/pipelines/data-fitting/overview">
    目的関数・パラメータ・オプティマイザの組み合わせ方。
  </Card>
</CardGroup>
