<!-- DO NOT EDIT. -->
<!-- THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -->
<!-- TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -->
<!-- "auto_examples/normal_mode_analysis/plot_normal_mode_analysis.py" -->
<!-- LINE NUMBERS ARE GIVEN BELOW. -->

#### NOTE
[Go to the end](#sphx-glr-download-auto-examples-normal-mode-analysis-plot-normal-mode-analysis-py)
to download the full example code.

<a id="sphx-glr-auto-examples-normal-mode-analysis-plot-normal-mode-analysis-py"></a>

# Normal Mode Analysis (NMA)

This example demonstrates how to use the NormalModeAnalyzer in pylimer-tools
to predict the loss and storage modulus of polymer networks using exact eigenvalue
solvers or the Kernel Polynomial Method (KPM).

Reference: Gusev and Bernhard [[GB24](../../acknowledgements.html.md#id7)]

<!-- GENERATED FROM PYTHON SOURCE LINES 11-73 -->
```Python
import os
from pathlib import Path

import numpy as np
import pandas as pd

from pylimer_tools.io.read_lammps_output_file import read_data_file
from pylimer_tools_cpp import NormalModeAnalyzer, NormalModeSolver


# Load a LAMMPS data file (replace with your file)
def _find_fixtures_dir() -> Path:
    for cur in (
        [Path(__file__).resolve().parent] if "__file__" in globals() else []
    ) + [Path.cwd()]:
        for p in [cur] + list(cur.parents):
            candidate = p / "tests" / "pylimer_tools" / "fixtures"
            if candidate.is_dir():
                return candidate
    return Path("tests/pylimer_tools/fixtures").resolve()


_fixtures_dir = _find_fixtures_dir()
filePath = str(_fixtures_dir / "structure/network_100_a_46.structure.out")
universe = read_data_file(filePath)
edges = universe.get_edges()

# Create the normal mode analyzer
nma = NormalModeAnalyzer(
    edges["edge_from"],
    edges["edge_to"],
)

# 1. Exact analysis with connected component decomposition and
# dense/sparse solver
nma.find_all_eigenvalues(
    solver=NormalModeSolver.AUTO,
    compute_eigenvectors=False,
    decompose_components=True,
)

# Get the storage and loss modulus across frequencies
frequencies = np.logspace(-4, 3, num=int(1e3))
storage_modulus_exact = nma.evaluate_storage_modulus(omega=frequencies)
loss_modulus_exact = nma.evaluate_loss_modulus(omega=frequencies)

# 2. Kernel Polynomial Method (KPM) without computing full eigenvalues
# KPM calculates viscoelastic moduli in O(N) time for large networks.
storage_modulus_kpm = nma.evaluate_storage_modulus_kpm(
    omega=frequencies,
    num_moments=512,
    num_random_vectors=20,
    num_quadrature_points=1024,
)
loss_modulus_kpm = nma.evaluate_loss_modulus_kpm(
    omega=frequencies,
    num_moments=512,
    num_random_vectors=20,
    num_quadrature_points=1024,
)
```

<!-- GENERATED FROM PYTHON SOURCE LINES 74-78 -->
<!-- todo:
Apply conversion factors where necessary -->

Plot and compare the results

<!-- GENERATED FROM PYTHON SOURCE LINES 78-98 -->
```Python
df = pd.DataFrame(
    {
        "Frequency": frequencies,
        "Storage Modulus (Exact)": storage_modulus_exact,
        "Loss Modulus (Exact)": loss_modulus_exact,
        "Storage Modulus (KPM)": storage_modulus_kpm,
        "Loss Modulus (KPM)": loss_modulus_kpm,
    }
)
df.set_index("Frequency", inplace=True)
_ = df.plot(
    title="Normal Mode Analysis: Exact vs KPM Moduli",
    loglog=True,
    style={
        "Storage Modulus (Exact)": "b-",
        "Loss Modulus (Exact)": "r-",
        "Storage Modulus (KPM)": "b--",
        "Loss Modulus (KPM)": "r--",
    },
)
```

```none
/home/runner/work/pylimer-tools/pylimer-tools/examples/normal_mode_analysis/plot_normal_mode_analysis.py:87: Pandas4Warning: The inplace keyword in DataFrame.set_index is deprecated and will be removed in a future version (PDEP-8).
See https://pandas.pydata.org/docs/dev/whatsnew/v3.1.0.html#deprecation-inplace for more details.
  df.set_index("Frequency", inplace=True)
```

**Total running time of the script:** (0 minutes 7.937 seconds)

<a id="sphx-glr-download-auto-examples-normal-mode-analysis-plot-normal-mode-analysis-py"></a>

[`Download Jupyter notebook: plot_normal_mode_analysis.ipynb`](_downloads/fad61465a562c82c11b547553dceb6b1/plot_normal_mode_analysis.ipynb)

[`Download Python source code: plot_normal_mode_analysis.py`](_downloads/05d5229a50b4f1c9fbea77654e66bc82/plot_normal_mode_analysis.py)

[`Download zipped: plot_normal_mode_analysis.zip`](_downloads/fc9f8d7f4f2d7f7b2b6529e1a4935dd6/plot_normal_mode_analysis.zip)

[Gallery generated by Sphinx-Gallery](https://sphinx-gallery.github.io)
