{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "81ff7ff1-8383-4cd6-abf9-cdfb91b02296",
   "metadata": {},
   "source": [
    "For the determinatino of SFE, we'll be following the work of Reed and Schramm\n",
    "\n",
    "SFE = "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bbc5819d-6050-445d-acfa-d4db50351f40",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sp\n",
    "K111 = sp.Symbol(\"K_{111}\")\n",
    "w0 = sp.Symbol(\"\\omega_{0}\")\n",
    "G111 = sp.Symbol(\"G_{111}\")\n",
    "a0 = sp.Symbol(\"a_{0}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1e83f5c-defa-4276-a429-2da7beb795c8",
   "metadata": {},
   "source": [
    "# Sample Preparation for Cast and HIPed Stellite 1\n",
    "\n",
    "## Material Sourcing and Initial States\n",
    "\n",
    "*Bulk Materials*: Obtain Stellite 1 in both cast and Hot Isostatically Pressed (HIPed) forms. It is essential to have an accurate chemical composition analysis for both. These as-received cast and HIPed states will serve as your primary microstructural references for the bulk material.\n",
    "\n",
    "*Powder Materials*: Utilize two distinct Stellite 1 powder samples:\n",
    "- Initial Powder: This is the base Stellite 1 powder before any mechanical processing. It represents the starting condition.\n",
    "- Ball-Milled Powder: This is the initial powder that has been subjected to high-energy ball milling.\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4665a308-e96d-4630-b3ba-6d88e2aae296",
   "metadata": {},
   "source": [
    "### Notes for Vi on why the XRD on gas atomized powder is good\n",
    "\n",
    "In order to make the samples, Deloro Stellite made gas-atomized powders that were then blended to make the blended samples, in addition to the regular HIPed samples. These gas-atomized powders undergo extremely high cooling rates that are extremely fine-grained - in short, they will have extremely high dislocation density that will greatly increase the microstrain.\n",
    "\n",
    "What's quite cool is that the HIPed samples are essentially the same powders but raised to 1200C and then slowly cooled down. While the carbides are the likely the same size (as noticed by Heathcock in similar work), the matrix is likely to be as relaxed as possible. Any deformation due to the carbides will be the same in the gas-atomized powders anyway.\n",
    "\n",
    "What's even cooler is that I can see the relaxed state in the XRD plots, as the peaks are quite sharp. I should really do an estimation of grain size first, haha. \n",
    "\n",
    "Perhaps, we could do what the guiys in did:File material away from the solid cast speciments. Anneal the filed chips under vacuum at 1210 C for 30 minutes and then quench the water to \"freeze\" the dislocation-free fcc-metal matrix without the precipitation of M7C3 carbides. We could ball mill these? Or perhaps, we just take the gas-atomized powder, anneal it and quench that instead. \n",
    "\n",
    "UPDATE! Had a quick conversation with RA, and it does seem like if they've done XRD on one powder, they've proabably done it on all of them. Even then, he still has the powders! So it's doable :D"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11fde641-b5b5-43a0-b80f-3c62ea357b7e",
   "metadata": {},
   "source": [
    "## Determining stacking fault probability with Popa\n",
    "\n",
    "Stacking faults cause the (200) peak in cobalt to shift its position, while the (111) peak remains fixed. Thus, by comparing the difference between (200) - (111) on a fault-free (FF) sample and a fault-dense (FD) sample, we can measure the exact probability or amount of stacking faults.\n",
    "\n",
    "Stacking fault probability gives a measure of how many {111} planes have stacking fault, which is critical for understanding mechanical behavior like work hardening, twinning, and phase transformation.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9feef048-9947-4074-8643-a49fb327e6cb",
   "metadata": {},
   "source": [
    "$$\n",
    "\\Delta 2 \\Theta = {\\left( 2 {\\color{blue}\\Theta_{200}} - 2 {\\color{blue}\\Theta_{111}} \\right)}_{FF} - {\\left( 2 {\\color{green}\\Theta_{200}} - 2 {\\color{green}\\Theta_{111}} \\right)}_{FD}  =  - {\\color{red}\\alpha} \\frac{45\\sqrt{3}}{\\pi^2} {\\left( tan {\\color{blue}\\Theta_{200}} - 0.5 tan {\\color{blue}\\Theta_{111}} \\right)}_{FF} \n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81fc8935-d294-4c8a-be62-852c76e9fce0",
   "metadata": {},
   "source": [
    "the color coding is to make this easier on the eye: blue - FF, green - FD, red - alpha"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "22a8623a-8e71-4bc3-9dc3-7b5cc2d43566",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy\n",
    "\n",
    "def calculate_stacking_fault_probability_from_angles(\n",
    "    theta_111_FD,  \n",
    "    theta_200_FD,  \n",
    "    theta_111_FF,  \n",
    "    theta_200_FF   \n",
    "):\n",
    "    \"\"\"\n",
    "    Calculates the stacking fault probability (alpha) directly from \n",
    "    (111) and (200) 2-theta peak positions (in radians) for FD (e.g., fully deformed) \n",
    "    and FF (e.g., fault-free/annealed) states.\n",
    "\n",
    "    Args:\n",
    "        theta_111_FD (float): theta angle of (111) peak in the FD state (radians).\n",
    "        theta_200_FD (float): theta angle of (200) peak in the FD state (radians).\n",
    "        theta_111_FF (float): theta angle of (111) peak in the FF state (radians).\n",
    "        theta_200_FF (float): theta angle of (200) peak in the FF state (radians).\n",
    "\n",
    "    Returns:\n",
    "        float: The calculated stacking fault probability (alpha).\n",
    "\n",
    "    Raises:\n",
    "        TypeError: If any of the input angles are not numbers.\n",
    "        ValueError: If the denominator for alpha calculation (tan terms) is too close to zero.\n",
    "    \"\"\"\n",
    "\n",
    "    # Part 0: Input validation for initial angles\n",
    "    for angle_name, angle_value in [\n",
    "        (\"theta_111_FD\", theta_111_FD),\n",
    "        (\"theta_200_FD\", theta_200_FD),\n",
    "        (\"theta_111_FF\", theta_111_FF),\n",
    "        (\"theta_200_FF\", theta_200_FF)\n",
    "    ]:\n",
    "        if not isinstance(angle_value, (int, float)):\n",
    "            raise TypeError(f\"{angle_name} must be a number. Got: {angle_value}\")\n",
    "\n",
    "    \n",
    "    # Part 1: Calculate delta 2-theta separation (in radians)\n",
    "    delta_2theta_separation = (2*theta_200_FD - 2*theta_111_FD) - (2*theta_200_FF - 2*theta_111_FF)\n",
    "\n",
    "    # Part 2: Calculate stacking fault probability    \n",
    "    denominator_tan_terms = numpy.tan(theta_200_FD) + 0.5 * numpy.tan(theta_111_FD)\n",
    "    alpha = -(numpy.pi**2 / (45.0 * numpy.sqrt(3.0))) * delta_2theta_separation / denominator_tan_terms\n",
    "    \n",
    "    # Part 3: Warnings for alpha values\n",
    "    if alpha < 0:\n",
    "        print(f\"Warning: Calculated stacking fault probability (alpha) is negative ({alpha:.4e}). \"\n",
    "              \"This may indicate issues with input peak shift data (e.g., incorrect peak indexing, \"\n",
    "              \"peak shifts in the opposite direction to that expected for faulting), \"\n",
    "              \"or unusual faulting behavior not described by the simple Warren model. \"\n",
    "              \"The resulting SFE may not be physically meaningful for a stable FCC material.\")\n",
    "    elif abs(alpha) < 1e-9:\n",
    "        print(f\"Warning: Calculated stacking fault probability (alpha) is very close to zero ({alpha:.4e}). \"\n",
    "              \"This suggests negligible faulting, or that the peak shifts are too small to be \"\n",
    "              \"reliably measured or distinguished from experimental error. \"\n",
    "              \"SFE calculated from this alpha will be very large or approach infinity.\")\n",
    "              \n",
    "    return alpha"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a6e0fead-6fd1-49b5-a5c4-1f4bfafb9ac1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculated SFP (alpha): 3.2931e-04\n"
     ]
    }
   ],
   "source": [
    "# Example values in RADIANS (replace with actual experimental data)\n",
    "# Scenario 1: Typical positive alpha\n",
    "# Original degrees: 43.50, 50.50, 43.70, 50.80\n",
    "# delta_2theta_separation_deg = (50.50 - 43.50) - (50.80 - 43.70) = 7.00 - 7.10 = -0.10 deg\n",
    "theta_111_FD = numpy.radians(43.50)/2  # FD (111) in radians\n",
    "theta_200_FD = numpy.radians(50.50)/2  # FD (200) in radians\n",
    "theta_111_FF = numpy.radians(43.70)/2  # FF (111) in radians\n",
    "theta_200_FF = numpy.radians(50.80)/2  # FF (200) in radians\n",
    "        \n",
    "alpha1 = calculate_stacking_fault_probability_from_angles(\n",
    "    theta_111_FD,\n",
    "    theta_200_FD,\n",
    "    theta_111_FF,\n",
    "    theta_200_FF    \n",
    ")\n",
    "\n",
    "print(f\"Calculated SFP (alpha): {alpha1:.4e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb1bd6e1-51a4-41b1-a643-752d90ac8abd",
   "metadata": {},
   "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.12.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
