{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "bed4637d-8e0c-42b4-9331-8a39ca2381a6",
   "metadata": {},
   "source": [
    "Copyright (c) 2025 Mitsuru Ohno  \n",
    "Use of this source code is governed by a BSD-3-style  \n",
    "license that can be found in the LICENSE file.  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "911d53c0",
   "metadata": {},
   "source": [
    "## 当ノートブックのワークフロー  \n",
    "速度定数がすべて既知で、初期濃度を与えた場合、各化学種の経時変化をシミュレーションする場合の事例  \n",
    "1. csvに書き込んだ反応式を読み込む。ただし速度定数はすべて既知とする  \n",
    "2. RxnIVPsolv(\"sample_data.csv\")でインスタンス化し、化学種ごとの微分型の反応速度式を作成する  \n",
    "3. 作成した微分方程式を、数値解析可能な形式にする  \n",
    "4. 化学種ごとの濃度の経時変化を求める。数値積分では、get_ode_system()で必要なオブジェクトを取得する。   \n",
    "5. matplotlibで結果をプロットし、経時変化を図示する  \n",
    "\n",
    "## 引用文献  \n",
    "1) 桜田一郎; 坂口康義; 大村恭弘. [11] 数種の水溶性高分子酢酸エステルの加水分解速度. 高分子化學, 1970, 27.297: 89-96.  https://doi.org/10.1295/koron1944.27.89  \n",
    "\n",
    "文献中 Table 7の数値を使用した。  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f793b762-0cca-45f9-ad15-a0c092ac36e6",
   "metadata": {},
   "source": [
    "## 反応式を記載したcsvファイルを指定する  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "92b6caf1-fbe4-47c8-9bf7-15dc223b3b28",
   "metadata": {},
   "outputs": [],
   "source": [
    "file_path = './sample_data/sample_rxn_ref1.csv'  # CSVファイルのパスを指定"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95324112-077e-4f27-9529-2a86aaa179f2",
   "metadata": {},
   "source": [
    "## 反応速度式をscipy.integrate.solve_ivpで処理できる連立微分方程式にする  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "75e2680b-f29a-4109-8707-97deb1943716",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "from rxnfit import RxnODEbuild, SolverConfig, RxnODEsolver\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "aeb55f6f-83d3-4689-9921-c0f9c3c7216f",
   "metadata": {},
   "outputs": [],
   "source": [
    "builded_rxnode = RxnODEbuild(file_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "dc5a5d88-0b5d-4f67-bd1c-81209bae4d0a",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "number of species: 8\n",
      "unique species: ['AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "rate constant: {'k1': 0.054, 'k2': 0.044, 'k3': 0.031}\n",
      "\n",
      "=== debug info ===\n",
      "Successfully created function for AcOEt with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for OHa1 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for AcOa1 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EtOH with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for AcOiPr with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for iPrOH with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EGOAc2 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EG with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "order of args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "system of ODE: {'AcOEt': '-1/1*k1*AcOEt(t)*OHa1(t)', 'OHa1': '-1/1*k1*AcOEt(t)*OHa1(t)-1/1*k2*AcOiPr(t)*OHa1(t)-2/1*k3*EGOAc2(t)*OHa1(t)**2', 'AcOa1': '1/1*k1*AcOEt(t)*OHa1(t)+1/1*k2*AcOiPr(t)*OHa1(t)+2/1*k3*EGOAc2(t)*OHa1(t)**2', 'EtOH': '1/1*k1*AcOEt(t)*OHa1(t)', 'AcOiPr': '-1/1*k2*AcOiPr(t)*OHa1(t)', 'iPrOH': '1/1*k2*AcOiPr(t)*OHa1(t)', 'EGOAc2': '-1/1*k3*EGOAc2(t)*OHa1(t)**2', 'EG': '1/1*k3*EGOAc2(t)*OHa1(t)**2'}\n"
     ]
    }
   ],
   "source": [
    "builded_rxnode.get_ode_info(debug_info=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "83f4a6f4-a58f-4731-8b63-51cbefebba72",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'k1': 0.054, 'k2': 0.044, 'k3': 0.031}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "builded_rxnode.rate_consts_dict"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ffd9610e-40f3-40b1-aeee-2292e86b6a1c",
   "metadata": {},
   "source": [
    "## 数値積分を実行する  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "6df457e4-fd6e-4416-bb07-750e343d10f3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "number of species: 8\n",
      "unique species: ['AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "rate constant: {'k1': 0.054, 'k2': 0.044, 'k3': 0.031}\n"
     ]
    }
   ],
   "source": [
    "# 各化学種の初期濃度の入力順序を確認する  \n",
    "builded_rxnode.get_ode_info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7f08357f-a23e-4356-8345-0b500760b15b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# get_ode_infoの出力を参照して、初期値等の入力項目を渡す\n",
    "config = SolverConfig(\n",
    "    y0 = [1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], # 初期濃度（必須）\n",
    "    t_span=(0, 30),         # 時間範囲（必須）\n",
    "    # t_eval: Optional[np.ndarray] = field(default=None),  # 任意\n",
    "    method = \"RK45\",  # 任意\n",
    "    rtol = 1e-6,    # 任意    \n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "cb900316-1b10-41d2-8254-0d1f0eef37f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 基本的な数値積分 -インスタンス化-\n",
    "solved_rxnode = RxnODEsolver(builded_rxnode, config)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f1797ffc-0371-489d-8baf-3646dec8cc61",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Successfully created function for AcOEt with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for OHa1 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for AcOa1 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EtOH with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for AcOiPr with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for iPrOH with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EGOAc2 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EG with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for AcOEt with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for OHa1 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for AcOa1 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EtOH with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for AcOiPr with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for iPrOH with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EGOAc2 with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n",
      "Successfully created function for EG with args: ['t', 'AcOEt', 'OHa1', 'AcOa1', 'EtOH', 'AcOiPr', 'iPrOH', 'EGOAc2', 'EG']\n"
     ]
    }
   ],
   "source": [
    "ode_construct, sol = solved_rxnode.solve_system()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ac4cbc0d-8c03-4f6f-8c9e-04f0540dd786",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Time-course plot ===\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 42984 characters]",
      "text/plain": [
       "<Figure size 600x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Concentration at the final time point ===\n",
      "Dataset 1:\n",
      "  AcOEt: 0.643029\n",
      "  OHa1: 0.143029\n",
      "  AcOa1: 0.356971\n",
      "  EtOH: 0.356971\n",
      "  AcOiPr: 0.000000\n",
      "  iPrOH: 0.000000\n",
      "  EGOAc2: 0.000000\n",
      "  EG: 0.000000\n"
     ]
    }
   ],
   "source": [
    "solved_rxnode.solution_plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1427a075-40ba-4760-bfb6-71708b3dd60c",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
