diff --git a/README.md b/README.md
index ce13100cc53be780575ea8db170f8378112dfb14..0839ba92b4ccb15259b7a372522b8eaac827a870 100644
--- a/README.md
+++ b/README.md
@@ -1,230 +1,126 @@
 # pymatlib
 
+# pymatlib
 
-Pymatlib is a Python library designed to simulate and analyze material properties. 
-It provides tools for modeling alloys, interpolating material properties, and more.
-
+A high-performance Python library for material simulation and analysis with a focus on temperature-dependent properties.
+pymatlib enables efficient modeling of alloys, interpolation of material properties, 
+and robust energy-temperature conversions for scientific and engineering applications.
 
-<!-- # TODO
-![Build Status](https://img.shields.io/github/actions/workflow/status/rahil.doshi/pymatlib/build.yml)
--->
 [![Pipeline Status](https://i10git.cs.fau.de/rahil.doshi/pymatlib/badges/master/pipeline.svg)](https://i10git.cs.fau.de/rahil.doshi/pymatlib/-/pipelines)
 ![License](https://img.shields.io/badge/license-GPLv3-blue)
 
-
 ## Table of Contents
 - [Installation](#installation)
-- [Usage](#usage)
+- [Quick Start](#quick-start)
+- [Documentation](#documentation)
 - [Features](#features)
-- [Classes](#classes)
 - [Contributing](#contributing)
 - [License](#license)
 - [Contact](#contact)
 
-
 ## Installation
-To install `pymatlib`, you can use pip. It is recommended to install it in a virtual environment:
-```bash
-pip install -e .
-```
-This command installs the package in editable mode, allowing you to make changes without needing to reinstall.
-
-### Installation Requirements
-- **Python version**: >= 3.10
-- Required packages:
-    - `numpy`
-    - `sympy`
-    - `pytest`
-    - [`pystencils`](https://i10git.cs.fau.de/pycodegen/pystencils/-/tree/v2.0-dev?ref_type=heads)
-    - `pybind11`
-
-### Installation Steps
-1. Clone the repository:
-```bash
-git clone https://i10git.cs.fau.de/rahil.doshi/pymatlib.git
-cd pymatlib
-```
-2. Install the package:
+
+To install `pymatlib`, use pip in a [virtual environment](https://docs.python.org/3/library/venv.html):
 ```bash
-pip install -e .
+pip install "git+https://i10git.cs.fau.de/rahil.doshi/pymatlib.git"
 ```
-This installs pymatlib in editable mode for development.
 
+## Quick Start
+
+### Creating and Using an Alloy
+```python
+import pystencils as ps
+from pystencilssfg import SourceFileGenerator
+from pymatlib.core.typedefs import MaterialProperty
+from pymatlib.core.yaml_parser import create_alloy_from_yaml
+
+# Define a temperature field
+with SourceFileGenerator() as sfg:
+    u = ps.fields("u: float64[2D]", layout='fzyx')
+
+    # Create an alloy from YAML configuration
+    alloy = create_alloy_from_yaml("path/to/alloy.yaml", u.center())
+    
+    # Now you can use the alloy in your simulation
+    # Get material properties at specific temperature
+    temperature = 1500.0  # Kelvin
+    thermal_diffusivity_value = alloy.thermal_diffusivity.evalf(u.center(), temperature)
+    print(f"Thermal diffusivity at {temperature}K: {thermal_diffusivity_value} W/(m·K)")
+```
+See the [tutorials](#documentation) for more detailed examples.
 
-## Usage
-Here are some examples of how to use the library:
+## Documentation
 
-### Example 1: Creating an Alloy
-```bash
-from pymatlib.core.alloy import Alloy
-
-alloy = Alloy(
-  elements=['Fe', 'Cr'], 
-  composition=[0.7, 0.3], 
-  temperature_solidus=1700.0, 
-  temperature_liquidus=1800.0)
-print(alloy)
-# Output: Alloy(Fe: 70%, Cr: 30%, solidus: 1700.0 K, liquidus: 1800.0 K)
-```
+Our documentation follows the Diátaxis framework with four distinct types:
 
-### Example 2: Interpolating Material Properties
-```bash
-from pymatlib.core.interpolators import interpolate_property
+### Tutorials - Learning-oriented guides
+- [Getting Started with pymatlib](docs/tutorials/getting_started.md)
+- [Creating Your First Material Simulation](docs/tutorials/first_simulation.md)
 
-T = 1400.0
-temp_array = [1300.0, 1400.0, 1500.0]
-prop_array = [100.0, 200.0, 300.0]
+### How-to Guides - Problem-oriented instructions
+- [Defining Custom Material Properties](docs/how-to/define_materials.md)
+- [Converting Between Energy Density and Temperature](docs/how-to/energy_temperature_conversion.md)
 
-result = interpolate_property(T, temp_array, prop_array)
-print(result)
-# Output: 200.0
-```
+### Reference - Information-oriented documentation
+- [API Reference](docs/reference/api/)
+- [YAML Configuration Schema](docs/reference/yaml_schema.md)
 
+### Explanation - Understanding-oriented discussions
+- [Interpolation Methods](docs/explanation/interpolation_methods.md)
+- [Material Properties Concepts](docs/explanation/material_properties.md)
+- [Design Philosophy](docs/explanation/design_philosophy.md)
 
-## Features
-- **Material Modeling**: Define alloys and their properties with ease. Supports various material properties including density, thermal conductivity, and heat capacity.
-- **Interpolation**: Interpolate material properties across temperature ranges. Provides functions for interpolation of properties based on temperature.
-- **Symbolic Calculations**: Utilize symbolic math with tools like sympy. Includes data structures for managing assignments and symbolic variables.
-- **Extensibility**: Add new material properties and interpolators as needed.
+## Key Features
 
+| Feature | Description |
+|---------|-------------|
+| **Material Modeling** | Define complex alloys and their properties using simple YAML configurations |
+| **Temperature-dependent Properties** | Model how material properties change with temperature through various interpolation methods |
+| **Energy-Temperature Conversion** | Perform efficient bilateral conversion between energy density and temperature |
+| **High Performance** | Generate optimized C++ code for computationally intensive simulations |
+| **Extensible Design** | Easily add custom material properties and interpolation methods |
 
-## Classes
+## Core Components
 
 ### Alloy
-A dataclass for alloys, with properties like:
-- ```elements```
-- ```composition```
-- ```temperature_solidus```
-- ```temperature_liquidus```
-
-### Assignment
-A dataclass representing an assignment operation with:
-- lhs: Left-hand side (symbolic variable).
-- rhs: Right-hand side (expression or tuple).
-- lhs_type: Type of the left-hand side.
+
+A dataclass representing a material alloy with properties like:
+- Elements and composition
+- Solidus and liquidus temperatures
+- Temperature-dependent material properties
 
 ### MaterialProperty
-A dataclass representing a material property that can be evaluated as a function of a symbolic variable (e.g., temperature) and includes symbolic assignments.
 
+A dataclass for material properties that can be:
+- Defined as constant values
+- Specified as key-value pairs for interpolation
+- Loaded from external data files
+- Computed from other properties
+
+### InterpolationArrayContainer
+
+Manages data for efficient interpolation between energy density and temperature using:
+- Binary search interpolation for non-uniform data
+- Double lookup interpolation for uniform data
 
 ## Contributing
+
 Contributions are welcome! Please follow these steps:
-1. Fork the repository.
-2. Create a new branch:
-```bash
-git checkout -b feature/your-feature
-```
-3. Make your changes and commit:
-```bash
-git commit -m "Add new feature"
-```
-4. Push to the branch:
-```bash
-git push origin feature/your-feature
-```
-5. Open a pull request.
 
+1. Fork the repository
+2. Clone your fork locally: `git clone https://github.com/yourusername/pymatlib.git`
+3. Create a new branch: `git checkout -b feature/your-feature`
+4. Make your changes and commit: `git commit -m "Add new feature"`
+5. Push to the branch: `git push origin feature/your-feature`
+6. Open a pull request
 
 ## License
-This project is licensed under the GNU General Public License v3 (GPLv3). See the [LICENSE](https://i10git.cs.fau.de/rahil.doshi/pymatlib/-/blob/master/LICENSE?ref_type=heads) file for details.
 
+This project is licensed under the GNU General Public License v3 (GPLv3). See the [LICENSE](https://i10git.cs.fau.de/rahil.doshi/pymatlib/-/blob/master/LICENSE?ref_type=heads) file for details.
 
 ## Contact
-For inquiries or issues:
-- **Author**: Rahil Doshi 
+
+- **Author**: Rahil Doshi
 - **Email**: rahil.doshi@fau.de
 - **Project Homepage**: [pymatlib](https://i10git.cs.fau.de/rahil.doshi/pymatlib)
 - **Bug Tracker**: [Issues](https://i10git.cs.fau.de/rahil.doshi/pymatlib/-/issues)
-
-
-<!--
-## Getting started
-
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
-
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
-
-## Add your files
-
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
-
-```
-cd existing_repo
-git remote add origin https://i10git.cs.fau.de/rahil.doshi/pymatlib.git
-git branch -M master
-git push -uf origin master
-```
-
-## Integrate with your tools
-
-- [ ] [Set up project integrations](https://i10git.cs.fau.de/rahil.doshi/pymatlib/-/settings/integrations)
-
-## Collaborate with your team
-
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
-
-***
-
-# Editing this README
-
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
-
-## Suggestions for a good README
-
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
-
-## Name
-Choose a self-explaining name for your project.
-
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
-
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
-
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
-
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
-
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
-
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
-
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
-
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
-
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
-
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
-
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
-
-## License
-For open source projects, say how it is licensed.
-
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
--->
\ No newline at end of file
diff --git a/apps/array_container_callgraph.py b/apps/array_container_callgraph.py
new file mode 100644
index 0000000000000000000000000000000000000000..90a62ad7fdc4162f245c09209fef8990a46756bb
--- /dev/null
+++ b/apps/array_container_callgraph.py
@@ -0,0 +1,75 @@
+import os
+from pycallgraph2 import PyCallGraph, Config
+from pycallgraph2.output import GraphvizOutput
+from pycallgraph2.globbing_filter import GlobbingFilter
+
+# Define the path to the folder inside the apps directory
+apps_directory = '/local/ca00xebo/repos/pymatlib/apps'
+image_folder = os.path.join(apps_directory, 'callgraph_images')
+
+# Create the folder if it does not exist
+if not os.path.exists(image_folder):
+    os.makedirs(image_folder)
+
+# Create configuration to focus on your specific functions
+config = Config()
+config.trace_filter = GlobbingFilter(
+    include=[
+        'pymatlib.core.interpolators.*',
+        'pymatlib.core.data_handler.*',
+        'InterpolationArrayContainer.*',
+
+        'assignment_converter',
+        'interpolate_property',
+        'check_equidistant',
+        'check_strictly_increasing',
+    ],
+    exclude=[
+        'pycallgraph2.*',
+        '*.append',  # Exclude common methods
+        '*.join',
+    ]
+)
+
+# Configure the output with the full path
+output_file = os.path.join(image_folder, 'array_container_callgraph.svg')
+
+# Configure the output
+graphviz = GraphvizOutput(
+    output_file=output_file,
+    font_name='Verdana',
+    font_size=7,
+    group_stdlib=True,
+    output_type='svg',
+    dpi=1200
+)
+
+# Run the specific part of your code with call graph tracking
+with PyCallGraph(config=config, output=graphviz):
+    import numpy as np
+    from pystencils import fields
+    from importlib.resources import files
+    from pystencilssfg import SourceFileGenerator
+    from pymatlib.core.yaml_parser import create_alloy_from_yaml
+    from pymatlib.core.interpolators import InterpolationArrayContainer
+
+
+    with SourceFileGenerator() as sfg:
+        u = fields(f"u: double[2D]", layout='fzyx')
+
+        T_bs = np.array([3243.15, 3248.15, 3258.15, 3278.15], dtype=np.float64)
+        E_bs = np.array([1.68e10, 1.69e10, 1.70e10, 1.71e10], dtype=np.float64)
+
+        custom_container = InterpolationArrayContainer("BinarySearchTests", T_bs, E_bs)
+        sfg.generate(custom_container)
+
+        T_eq = np.array([3243.15, 3253.15, 3263.15, 3273.15], dtype=np.float64)
+        E_neq = np.array([1.68e10, 1.69e10, 1.70e10, 1.71e10], dtype=np.float64)
+
+        custom_container = InterpolationArrayContainer("DoubleLookupTests", np.flip(T_eq), np.flip(E_neq))
+        sfg.generate(custom_container)
+
+        yaml_path = files('pymatlib.data.alloys.SS304L').joinpath('SS304L_comprehensive.yaml')
+        mat = create_alloy_from_yaml(yaml_path, u.center())
+        arr_container = InterpolationArrayContainer.from_material("SS304L", mat)
+        sfg.generate(arr_container)
diff --git a/apps/callgraph_images/array_container_callgraph.svg b/apps/callgraph_images/array_container_callgraph.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ead0a9dd166dff0528bec1a5d954749530909d5e
--- /dev/null
+++ b/apps/callgraph_images/array_container_callgraph.svg
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.43.0 (0)
+ -->
+<!-- Title: G Pages: 1 -->
+<svg width="1123pt" height="448pt"
+ viewBox="0.00 0.00 1123.00 448.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 444)">
+<title>G</title>
+<polygon fill="white" stroke="transparent" points="-4,4 -4,-444 1119,-444 1119,4 -4,4"/>
+<text text-anchor="middle" x="557.5" y="-6.4" font-family="Verdana" font-size="7.00" fill="#000000" fill-opacity="0.498039">Generated by Python Call Graph v1.1.3</text>
+<g id="clust1" class="cluster">
+<title>cluster___main__</title>
+<polygon fill="none" stroke="#000000" stroke-width="2" stroke-opacity="0.800000" points="961,-361 961,-432 1045,-432 1045,-361 961,-361"/>
+<text text-anchor="middle" x="1003" y="-420" font-family="Verdana" font-size="10.00">__main__</text>
+</g>
+<g id="clust2" class="cluster">
+<title>cluster_pymatlib</title>
+<polygon fill="none" stroke="#000000" stroke-width="2" stroke-opacity="0.800000" points="8,-24 8,-335 1107,-335 1107,-24 8,-24"/>
+<text text-anchor="middle" x="557.5" y="-323" font-family="Verdana" font-size="10.00">pymatlib</text>
+</g>
+<!-- __main__ -->
+<g id="node1" class="node">
+<title>__main__</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1036.5,-405 969.5,-405 969.5,-369 1036.5,-369 1036.5,-405"/>
+<text text-anchor="middle" x="1003" y="-393.4" font-family="Verdana" font-size="7.00" fill="#000000">__main__</text>
+<text text-anchor="middle" x="1003" y="-385.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1003" y="-377.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000000s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer.__init__ -->
+<g id="node5" class="node">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer.__init__</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1032,-228 820,-228 820,-192 1032,-192 1032,-228"/>
+<text text-anchor="middle" x="926" y="-216.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.InterpolationArrayContainer.__init__</text>
+<text text-anchor="middle" x="926" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="926" y="-200.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.009421s</text>
+</g>
+<!-- __main__&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer.__init__ -->
+<g id="edge2" class="edge">
+<title>__main__&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer.__init__</title>
+<path fill="none" stroke="#b2b2b2" d="M1008.49,-368.7C1014.83,-345.38 1022.56,-303.19 1007,-272 999.05,-256.07 984.74,-243.2 970.33,-233.47"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="972.2,-230.51 961.89,-228.1 968.45,-236.42 972.2,-230.51"/>
+<text text-anchor="middle" x="1018" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.interpolators.from_material -->
+<g id="node19" class="node">
+<title>pymatlib.core.interpolators.from_material</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="998,-308 854,-308 854,-272 998,-272 998,-308"/>
+<text text-anchor="middle" x="926" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.from_material</text>
+<text text-anchor="middle" x="926" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="926" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.005734s</text>
+</g>
+<!-- __main__&#45;&gt;pymatlib.core.interpolators.from_material -->
+<g id="edge3" class="edge">
+<title>__main__&#45;&gt;pymatlib.core.interpolators.from_material</title>
+<path fill="none" stroke="#b2b2b2" d="M988.88,-368.58C977.05,-353.98 960,-332.95 946.64,-316.46"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="949.05,-313.88 940.03,-308.31 943.61,-318.29 949.05,-313.88"/>
+<text text-anchor="middle" x="975" y="-345.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.interpolators.&lt;module&gt; -->
+<g id="node2" class="node">
+<title>pymatlib.core.interpolators.&lt;module&gt;</title>
+<polygon fill="#9996e5" stroke="#9996e5" points="684.5,-308 553.5,-308 553.5,-272 684.5,-272 684.5,-308"/>
+<text text-anchor="middle" x="619" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.&lt;module&gt;</text>
+<text text-anchor="middle" x="619" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="619" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 5.402472s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer -->
+<g id="node4" class="node">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="772,-228 586,-228 586,-192 772,-192 772,-228"/>
+<text text-anchor="middle" x="679" y="-216.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.InterpolationArrayContainer</text>
+<text text-anchor="middle" x="679" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="679" y="-200.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000010s</text>
+</g>
+<!-- pymatlib.core.interpolators.&lt;module&gt;&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer -->
+<g id="edge1" class="edge">
+<title>pymatlib.core.interpolators.&lt;module&gt;&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer</title>
+<path fill="none" stroke="#b2b2b2" d="M632.32,-271.69C640.32,-261.29 650.64,-247.87 659.54,-236.29"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="662.4,-238.32 665.72,-228.26 656.85,-234.05 662.4,-238.32"/>
+<text text-anchor="middle" x="652" y="-248.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.data_handler.&lt;module&gt; -->
+<g id="node3" class="node">
+<title>pymatlib.core.data_handler.&lt;module&gt;</title>
+<polygon fill="#9996e5" stroke="#9996e5" points="835.5,-308 702.5,-308 702.5,-272 835.5,-272 835.5,-308"/>
+<text text-anchor="middle" x="769" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.data_handler.&lt;module&gt;</text>
+<text text-anchor="middle" x="769" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="769" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 5.395197s</text>
+</g>
+<!-- pymatlib.core.interpolators.prepare_interpolation_arrays -->
+<g id="node6" class="node">
+<title>pymatlib.core.interpolators.prepare_interpolation_arrays</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="926.5,-148 737.5,-148 737.5,-112 926.5,-112 926.5,-148"/>
+<text text-anchor="middle" x="832" y="-136.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.prepare_interpolation_arrays</text>
+<text text-anchor="middle" x="832" y="-128.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="832" y="-120.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.009315s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer.__init__&#45;&gt;pymatlib.core.interpolators.prepare_interpolation_arrays -->
+<g id="edge4" class="edge">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer.__init__&#45;&gt;pymatlib.core.interpolators.prepare_interpolation_arrays</title>
+<path fill="none" stroke="#b2b2b2" d="M905.14,-191.69C892.12,-180.88 875.17,-166.82 860.87,-154.95"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="862.73,-151.95 852.8,-148.26 858.26,-157.34 862.73,-151.95"/>
+<text text-anchor="middle" x="883" y="-168.4" font-family="Verdana" font-size="7.00" fill="#000000">3</text>
+</g>
+<!-- pymatlib.core.data_handler.check_strictly_increasing -->
+<g id="node7" class="node">
+<title>pymatlib.core.data_handler.check_strictly_increasing</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="923,-68 741,-68 741,-32 923,-32 923,-68"/>
+<text text-anchor="middle" x="832" y="-56.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.data_handler.check_strictly_increasing</text>
+<text text-anchor="middle" x="832" y="-48.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 6</text>
+<text text-anchor="middle" x="832" y="-40.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.003896s</text>
+</g>
+<!-- pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.data_handler.check_strictly_increasing -->
+<g id="edge5" class="edge">
+<title>pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.data_handler.check_strictly_increasing</title>
+<path fill="none" stroke="#b2b2b2" d="M832,-111.69C832,-101.89 832,-89.42 832,-78.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="835.5,-78.26 832,-68.26 828.5,-78.26 835.5,-78.26"/>
+<text text-anchor="middle" x="834" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">6</text>
+</g>
+<!-- pymatlib.core.data_handler.check_equidistant -->
+<g id="node8" class="node">
+<title>pymatlib.core.data_handler.check_equidistant</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="540.5,-68 381.5,-68 381.5,-32 540.5,-32 540.5,-68"/>
+<text text-anchor="middle" x="461" y="-56.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.data_handler.check_equidistant</text>
+<text text-anchor="middle" x="461" y="-48.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 9</text>
+<text text-anchor="middle" x="461" y="-40.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.002802s</text>
+</g>
+<!-- pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.data_handler.check_equidistant -->
+<g id="edge6" class="edge">
+<title>pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.data_handler.check_equidistant</title>
+<path fill="none" stroke="#b2b2b2" d="M751.04,-111.98C691.87,-99.54 611.62,-82.67 550.53,-69.82"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="551.02,-66.35 540.51,-67.72 549.58,-73.2 551.02,-66.35"/>
+<text text-anchor="middle" x="659" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">3</text>
+</g>
+<!-- pymatlib.core.interpolators.E_eq_from_E_neq -->
+<g id="node12" class="node">
+<title>pymatlib.core.interpolators.E_eq_from_E_neq</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1099,-68 941,-68 941,-32 1099,-32 1099,-68"/>
+<text text-anchor="middle" x="1020" y="-56.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.E_eq_from_E_neq</text>
+<text text-anchor="middle" x="1020" y="-48.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="1020" y="-40.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000497s</text>
+</g>
+<!-- pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.interpolators.E_eq_from_E_neq -->
+<g id="edge7" class="edge">
+<title>pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.interpolators.E_eq_from_E_neq</title>
+<path fill="none" stroke="#b2b2b2" d="M873.26,-111.88C901.54,-100.15 939.25,-84.5 969.35,-72.01"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="970.94,-75.14 978.84,-68.08 968.26,-68.68 970.94,-75.14"/>
+<text text-anchor="middle" x="933" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.interpolators.create_idx_mapping -->
+<g id="node13" class="node">
+<title>pymatlib.core.interpolators.create_idx_mapping</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="723,-68 559,-68 559,-32 723,-32 723,-68"/>
+<text text-anchor="middle" x="641" y="-56.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.create_idx_mapping</text>
+<text text-anchor="middle" x="641" y="-48.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="641" y="-40.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.001825s</text>
+</g>
+<!-- pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.interpolators.create_idx_mapping -->
+<g id="edge8" class="edge">
+<title>pymatlib.core.interpolators.prepare_interpolation_arrays&#45;&gt;pymatlib.core.interpolators.create_idx_mapping</title>
+<path fill="none" stroke="#b2b2b2" d="M790.08,-111.88C761.35,-100.15 723.04,-84.5 692.46,-72.01"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="693.4,-68.62 682.82,-68.08 690.75,-75.1 693.4,-68.62"/>
+<text text-anchor="middle" x="744" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer.generate -->
+<g id="node9" class="node">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer.generate</title>
+<polygon fill="#e4e5e5" stroke="#e4e5e5" points="303.5,-308 88.5,-308 88.5,-272 303.5,-272 303.5,-308"/>
+<text text-anchor="middle" x="196" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.InterpolationArrayContainer.generate</text>
+<text text-anchor="middle" x="196" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="196" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.053865s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer._generate_binary_search -->
+<g id="node10" class="node">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer._generate_binary_search</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="282,-228 16,-228 16,-192 282,-192 282,-228"/>
+<text text-anchor="middle" x="149" y="-216.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.InterpolationArrayContainer._generate_binary_search</text>
+<text text-anchor="middle" x="149" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="149" y="-200.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.013519s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer.generate&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer._generate_binary_search -->
+<g id="edge9" class="edge">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer.generate&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer._generate_binary_search</title>
+<path fill="none" stroke="#b2b2b2" d="M185.57,-271.69C179.42,-261.49 171.53,-248.39 164.65,-236.97"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="167.56,-235.02 159.4,-228.26 161.56,-238.63 167.56,-235.02"/>
+<text text-anchor="middle" x="175" y="-248.4" font-family="Verdana" font-size="7.00" fill="#000000">3</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer._generate_double_lookup -->
+<g id="node14" class="node">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer._generate_double_lookup</title>
+<polygon fill="#e4e5e5" stroke="#e4e5e5" points="567.5,-228 300.5,-228 300.5,-192 567.5,-192 567.5,-228"/>
+<text text-anchor="middle" x="434" y="-216.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.InterpolationArrayContainer._generate_double_lookup</text>
+<text text-anchor="middle" x="434" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="434" y="-200.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.032489s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer.generate&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer._generate_double_lookup -->
+<g id="edge10" class="edge">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer.generate&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer._generate_double_lookup</title>
+<path fill="none" stroke="#b2b2b2" d="M247.94,-271.98C284.5,-260 333.61,-243.9 372.2,-231.26"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="373.35,-234.56 381.76,-228.12 371.17,-227.91 373.35,-234.56"/>
+<text text-anchor="middle" x="324" y="-248.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.interpolators.&lt;genexpr&gt; -->
+<g id="node11" class="node">
+<title>pymatlib.core.interpolators.&lt;genexpr&gt;</title>
+<polygon fill="#9998e5" stroke="#9998e5" points="216,-148 82,-148 82,-112 216,-112 216,-148"/>
+<text text-anchor="middle" x="149" y="-136.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.&lt;genexpr&gt;</text>
+<text text-anchor="middle" x="149" y="-128.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 4,240</text>
+<text text-anchor="middle" x="149" y="-120.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.011805s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer._generate_binary_search&#45;&gt;pymatlib.core.interpolators.&lt;genexpr&gt; -->
+<g id="edge11" class="edge">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer._generate_binary_search&#45;&gt;pymatlib.core.interpolators.&lt;genexpr&gt;</title>
+<path fill="none" stroke="#a2aeb2" d="M149,-191.69C149,-181.89 149,-169.42 149,-158.33"/>
+<polygon fill="#a2aeb2" stroke="#a2aeb2" points="152.5,-158.26 149,-148.26 145.5,-158.26 152.5,-158.26"/>
+<text text-anchor="middle" x="156.5" y="-168.4" font-family="Verdana" font-size="7.00" fill="#000000">1104</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer._generate_double_lookup&#45;&gt;pymatlib.core.interpolators.&lt;genexpr&gt; -->
+<g id="edge12" class="edge">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer._generate_double_lookup&#45;&gt;pymatlib.core.interpolators.&lt;genexpr&gt;</title>
+<path fill="none" stroke="#8691b2" d="M371.81,-191.98C327.46,-179.84 267.72,-163.49 221.25,-150.77"/>
+<polygon fill="#8691b2" stroke="#8691b2" points="222.12,-147.38 211.55,-148.12 220.27,-154.14 222.12,-147.38"/>
+<text text-anchor="middle" x="308" y="-168.4" font-family="Verdana" font-size="7.00" fill="#000000">3136</text>
+</g>
+<!-- pymatlib.core.data_handler.read_data_from_file -->
+<g id="node15" class="node">
+<title>pymatlib.core.data_handler.read_data_from_file</title>
+<polygon fill="#c1d4e5" stroke="#c1d4e5" points="502,-308 338,-308 338,-272 502,-272 502,-308"/>
+<text text-anchor="middle" x="420" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.data_handler.read_data_from_file</text>
+<text text-anchor="middle" x="420" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="420" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 2.467327s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property -->
+<g id="node16" class="node">
+<title>pymatlib.core.interpolators.interpolate_property</title>
+<polygon fill="#e54ce5" stroke="#e54ce5" points="397.5,-148 234.5,-148 234.5,-112 397.5,-112 397.5,-148"/>
+<text text-anchor="middle" x="316" y="-136.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.interpolate_property</text>
+<text text-anchor="middle" x="316" y="-128.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 6</text>
+<text text-anchor="middle" x="316" y="-120.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 10.489902s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.data_handler.check_equidistant -->
+<g id="edge13" class="edge">
+<title>pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.data_handler.check_equidistant</title>
+<path fill="none" stroke="#b2b2b2" d="M347.82,-111.88C369.16,-100.4 397.46,-85.18 420.42,-72.83"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="422.1,-75.9 429.25,-68.08 418.79,-69.73 422.1,-75.9"/>
+<text text-anchor="middle" x="394" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">6</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_lookup -->
+<g id="node17" class="node">
+<title>pymatlib.core.interpolators.interpolate_lookup</title>
+<polygon fill="#dc51e5" stroke="#dc51e5" points="174,-68 16,-68 16,-32 174,-32 174,-68"/>
+<text text-anchor="middle" x="95" y="-56.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.interpolate_lookup</text>
+<text text-anchor="middle" x="95" y="-48.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 4</text>
+<text text-anchor="middle" x="95" y="-40.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 10.165162s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_lookup -->
+<g id="edge14" class="edge">
+<title>pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_lookup</title>
+<path fill="none" stroke="#ab3fb2" d="M267.77,-111.98C234.11,-100.1 188.99,-84.17 153.3,-71.58"/>
+<polygon fill="#ab3fb2" stroke="#ab3fb2" points="154.1,-68.15 143.5,-68.12 151.77,-74.75 154.1,-68.15"/>
+<text text-anchor="middle" x="214" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">4</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_equidistant -->
+<g id="node18" class="node">
+<title>pymatlib.core.interpolators.interpolate_equidistant</title>
+<polygon fill="#e0e5e5" stroke="#e0e5e5" points="363.5,-68 192.5,-68 192.5,-32 363.5,-32 363.5,-68"/>
+<text text-anchor="middle" x="278" y="-56.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.interpolate_equidistant</text>
+<text text-anchor="middle" x="278" y="-48.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="278" y="-40.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.321995s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_equidistant -->
+<g id="edge15" class="edge">
+<title>pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_equidistant</title>
+<path fill="none" stroke="#aeb2b2" d="M307.57,-111.69C302.65,-101.59 296.34,-88.65 290.82,-77.31"/>
+<polygon fill="#aeb2b2" stroke="#aeb2b2" points="293.94,-75.72 286.41,-68.26 287.64,-78.79 293.94,-75.72"/>
+<text text-anchor="middle" x="300" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.interpolators.from_material&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer.__init__ -->
+<g id="edge16" class="edge">
+<title>pymatlib.core.interpolators.from_material&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer.__init__</title>
+<path fill="none" stroke="#b2b2b2" d="M926,-271.69C926,-261.89 926,-249.42 926,-238.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="929.5,-238.26 926,-228.26 922.5,-238.26 929.5,-238.26"/>
+<text text-anchor="middle" x="928" y="-248.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+</g>
+</svg>
diff --git a/apps/callgraph_images/yaml_parser_callgraph.svg b/apps/callgraph_images/yaml_parser_callgraph.svg
new file mode 100644
index 0000000000000000000000000000000000000000..173ba12d3229b32741ab19ab3df5158a4893e9d5
--- /dev/null
+++ b/apps/callgraph_images/yaml_parser_callgraph.svg
@@ -0,0 +1,1191 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.43.0 (0)
+ -->
+<!-- Title: G Pages: 1 -->
+<svg width="2667pt" height="984pt"
+ viewBox="0.00 0.00 2667.00 984.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 980)">
+<title>G</title>
+<polygon fill="white" stroke="transparent" points="-4,4 -4,-980 2663,-980 2663,4 -4,4"/>
+<text text-anchor="middle" x="1329.5" y="-6.4" font-family="Verdana" font-size="7.00" fill="#000000" fill-opacity="0.498039">Generated by Python Call Graph v1.1.3</text>
+<g id="clust1" class="cluster">
+<title>cluster___main__</title>
+<polygon fill="none" stroke="#000000" stroke-width="2" stroke-opacity="0.800000" points="816,-897 816,-968 900,-968 900,-897 816,-897"/>
+<text text-anchor="middle" x="858" y="-956" font-family="Verdana" font-size="10.00">__main__</text>
+</g>
+<g id="clust2" class="cluster">
+<title>cluster_pymatlib</title>
+<polygon fill="none" stroke="#000000" stroke-width="2" stroke-opacity="0.800000" points="8,-24 8,-871 2651,-871 2651,-24 8,-24"/>
+<text text-anchor="middle" x="1329.5" y="-859" font-family="Verdana" font-size="10.00">pymatlib</text>
+</g>
+<!-- __main__ -->
+<g id="node1" class="node">
+<title>__main__</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="891.5,-941 824.5,-941 824.5,-905 891.5,-905 891.5,-941"/>
+<text text-anchor="middle" x="858" y="-929.4" font-family="Verdana" font-size="7.00" fill="#000000">__main__</text>
+<text text-anchor="middle" x="858" y="-921.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="858" y="-913.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000000s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.create_alloy_from_yaml -->
+<g id="node18" class="node">
+<title>pymatlib.core.yaml_parser.create_alloy_from_yaml</title>
+<polygon fill="#e54ce5" stroke="#e54ce5" points="946,-844 770,-844 770,-808 946,-808 946,-844"/>
+<text text-anchor="middle" x="858" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.create_alloy_from_yaml</text>
+<text text-anchor="middle" x="858" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="858" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 228.137130s</text>
+</g>
+<!-- __main__&#45;&gt;pymatlib.core.yaml_parser.create_alloy_from_yaml -->
+<g id="edge10" class="edge">
+<title>__main__&#45;&gt;pymatlib.core.yaml_parser.create_alloy_from_yaml</title>
+<path fill="none" stroke="#b23bb2" d="M858,-904.58C858,-890.65 858,-870.86 858,-854.76"/>
+<polygon fill="#b23bb2" stroke="#b23bb2" points="861.5,-854.31 858,-844.31 854.5,-854.31 861.5,-854.31"/>
+<text text-anchor="middle" x="860" y="-881.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;module&gt; -->
+<g id="node2" class="node">
+<title>pymatlib.core.yaml_parser.&lt;module&gt;</title>
+<polygon fill="#e0e5e5" stroke="#e0e5e5" points="2538.5,-844 2407.5,-844 2407.5,-808 2538.5,-808 2538.5,-844"/>
+<text text-anchor="middle" x="2473" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.&lt;module&gt;</text>
+<text text-anchor="middle" x="2473" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="2473" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 6.704116s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.PropertyType -->
+<g id="node16" class="node">
+<title>pymatlib.core.yaml_parser.PropertyType</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2458.5,-764 2315.5,-764 2315.5,-728 2458.5,-728 2458.5,-764"/>
+<text text-anchor="middle" x="2387" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.PropertyType</text>
+<text text-anchor="middle" x="2387" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="2387" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000332s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;module&gt;&#45;&gt;pymatlib.core.yaml_parser.PropertyType -->
+<g id="edge8" class="edge">
+<title>pymatlib.core.yaml_parser.&lt;module&gt;&#45;&gt;pymatlib.core.yaml_parser.PropertyType</title>
+<path fill="none" stroke="#b2b2b2" d="M2453.91,-807.69C2442.11,-796.98 2426.79,-783.08 2413.78,-771.29"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2415.79,-768.39 2406.03,-764.26 2411.09,-773.57 2415.79,-768.39"/>
+<text text-anchor="middle" x="2434" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser -->
+<g id="node17" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2643.5,-764 2476.5,-764 2476.5,-728 2643.5,-728 2643.5,-764"/>
+<text text-anchor="middle" x="2560" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser</text>
+<text text-anchor="middle" x="2560" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="2560" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.001782s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;module&gt;&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser -->
+<g id="edge9" class="edge">
+<title>pymatlib.core.yaml_parser.&lt;module&gt;&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser</title>
+<path fill="none" stroke="#b2b2b2" d="M2492.31,-807.69C2504.36,-796.88 2520.04,-782.82 2533.28,-770.95"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2535.64,-773.54 2540.75,-764.26 2530.96,-768.33 2535.64,-773.54"/>
+<text text-anchor="middle" x="2521" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.alloy.&lt;module&gt; -->
+<g id="node3" class="node">
+<title>pymatlib.core.alloy.&lt;module&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2113.5,-844 2006.5,-844 2006.5,-808 2113.5,-808 2113.5,-844"/>
+<text text-anchor="middle" x="2060" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.&lt;module&gt;</text>
+<text text-anchor="middle" x="2060" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="2060" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.085522s</text>
+</g>
+<!-- pymatlib.core.alloy.AlloyCompositionError -->
+<g id="node9" class="node">
+<title>pymatlib.core.alloy.AlloyCompositionError</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2133,-764 1987,-764 1987,-728 2133,-728 2133,-764"/>
+<text text-anchor="middle" x="2060" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.AlloyCompositionError</text>
+<text text-anchor="middle" x="2060" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="2060" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000004s</text>
+</g>
+<!-- pymatlib.core.alloy.&lt;module&gt;&#45;&gt;pymatlib.core.alloy.AlloyCompositionError -->
+<g id="edge4" class="edge">
+<title>pymatlib.core.alloy.&lt;module&gt;&#45;&gt;pymatlib.core.alloy.AlloyCompositionError</title>
+<path fill="none" stroke="#b2b2b2" d="M2060,-807.69C2060,-797.89 2060,-785.42 2060,-774.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2063.5,-774.26 2060,-764.26 2056.5,-774.26 2063.5,-774.26"/>
+<text text-anchor="middle" x="2062" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.alloy.AlloyTemperatureError -->
+<g id="node10" class="node">
+<title>pymatlib.core.alloy.AlloyTemperatureError</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2297,-764 2151,-764 2151,-728 2297,-728 2297,-764"/>
+<text text-anchor="middle" x="2224" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.AlloyTemperatureError</text>
+<text text-anchor="middle" x="2224" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="2224" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000003s</text>
+</g>
+<!-- pymatlib.core.alloy.&lt;module&gt;&#45;&gt;pymatlib.core.alloy.AlloyTemperatureError -->
+<g id="edge5" class="edge">
+<title>pymatlib.core.alloy.&lt;module&gt;&#45;&gt;pymatlib.core.alloy.AlloyTemperatureError</title>
+<path fill="none" stroke="#b2b2b2" d="M2095.99,-807.88C2120.34,-796.3 2152.7,-780.91 2178.79,-768.5"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2180.57,-771.53 2188.09,-764.08 2177.56,-765.21 2180.57,-771.53"/>
+<text text-anchor="middle" x="2148" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy -->
+<g id="node11" class="node">
+<title>pymatlib.core.alloy.Alloy</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1969,-764 1877,-764 1877,-728 1969,-728 1969,-764"/>
+<text text-anchor="middle" x="1923" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.Alloy</text>
+<text text-anchor="middle" x="1923" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1923" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000410s</text>
+</g>
+<!-- pymatlib.core.alloy.&lt;module&gt;&#45;&gt;pymatlib.core.alloy.Alloy -->
+<g id="edge6" class="edge">
+<title>pymatlib.core.alloy.&lt;module&gt;&#45;&gt;pymatlib.core.alloy.Alloy</title>
+<path fill="none" stroke="#b2b2b2" d="M2029.93,-807.88C2009.95,-796.5 1983.51,-781.45 1961.92,-769.16"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1963.42,-765.98 1953,-764.08 1959.95,-772.07 1963.42,-765.98"/>
+<text text-anchor="middle" x="1997" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.&lt;module&gt; -->
+<g id="node4" class="node">
+<title>pymatlib.core.elements.&lt;module&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1847,-844 1725,-844 1725,-808 1847,-808 1847,-844"/>
+<text text-anchor="middle" x="1786" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.elements.&lt;module&gt;</text>
+<text text-anchor="middle" x="1786" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1786" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.018106s</text>
+</g>
+<!-- pymatlib.core.elements.ChemicalElement -->
+<g id="node5" class="node">
+<title>pymatlib.core.elements.ChemicalElement</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1859,-764 1713,-764 1713,-728 1859,-728 1859,-764"/>
+<text text-anchor="middle" x="1786" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.elements.ChemicalElement</text>
+<text text-anchor="middle" x="1786" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1786" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000012s</text>
+</g>
+<!-- pymatlib.core.elements.&lt;module&gt;&#45;&gt;pymatlib.core.elements.ChemicalElement -->
+<g id="edge1" class="edge">
+<title>pymatlib.core.elements.&lt;module&gt;&#45;&gt;pymatlib.core.elements.ChemicalElement</title>
+<path fill="none" stroke="#b2b2b2" d="M1786,-807.69C1786,-797.89 1786,-785.42 1786,-774.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1789.5,-774.26 1786,-764.26 1782.5,-774.26 1789.5,-774.26"/>
+<text text-anchor="middle" x="1788" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.typedefs.&lt;module&gt; -->
+<g id="node6" class="node">
+<title>pymatlib.core.typedefs.&lt;module&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1609,-844 1489,-844 1489,-808 1609,-808 1609,-844"/>
+<text text-anchor="middle" x="1549" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.typedefs.&lt;module&gt;</text>
+<text text-anchor="middle" x="1549" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1549" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.032934s</text>
+</g>
+<!-- pymatlib.core.typedefs.Assignment -->
+<g id="node7" class="node">
+<title>pymatlib.core.typedefs.Assignment</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1535.5,-764 1408.5,-764 1408.5,-728 1535.5,-728 1535.5,-764"/>
+<text text-anchor="middle" x="1472" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.typedefs.Assignment</text>
+<text text-anchor="middle" x="1472" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1472" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000512s</text>
+</g>
+<!-- pymatlib.core.typedefs.&lt;module&gt;&#45;&gt;pymatlib.core.typedefs.Assignment -->
+<g id="edge2" class="edge">
+<title>pymatlib.core.typedefs.&lt;module&gt;&#45;&gt;pymatlib.core.typedefs.Assignment</title>
+<path fill="none" stroke="#b2b2b2" d="M1531.91,-807.69C1521.44,-797.09 1507.88,-783.35 1496.31,-771.62"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1498.56,-768.92 1489.04,-764.26 1493.58,-773.84 1498.56,-768.92"/>
+<text text-anchor="middle" x="1514" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.typedefs.MaterialProperty -->
+<g id="node8" class="node">
+<title>pymatlib.core.typedefs.MaterialProperty</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1694.5,-764 1553.5,-764 1553.5,-728 1694.5,-728 1694.5,-764"/>
+<text text-anchor="middle" x="1624" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.typedefs.MaterialProperty</text>
+<text text-anchor="middle" x="1624" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1624" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.001233s</text>
+</g>
+<!-- pymatlib.core.typedefs.&lt;module&gt;&#45;&gt;pymatlib.core.typedefs.MaterialProperty -->
+<g id="edge3" class="edge">
+<title>pymatlib.core.typedefs.&lt;module&gt;&#45;&gt;pymatlib.core.typedefs.MaterialProperty</title>
+<path fill="none" stroke="#b2b2b2" d="M1565.64,-807.69C1575.84,-797.09 1589.05,-783.35 1600.32,-771.62"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1602.99,-773.9 1607.4,-764.26 1597.95,-769.04 1602.99,-773.9"/>
+<text text-anchor="middle" x="1590" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.interpolators.&lt;module&gt; -->
+<g id="node12" class="node">
+<title>pymatlib.core.interpolators.&lt;module&gt;</title>
+<polygon fill="#e1e5e5" stroke="#e1e5e5" points="1381.5,-844 1250.5,-844 1250.5,-808 1381.5,-808 1381.5,-844"/>
+<text text-anchor="middle" x="1316" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.&lt;module&gt;</text>
+<text text-anchor="middle" x="1316" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1316" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 6.434024s</text>
+</g>
+<!-- pymatlib.core.interpolators.InterpolationArrayContainer -->
+<g id="node15" class="node">
+<title>pymatlib.core.interpolators.InterpolationArrayContainer</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1390,-764 1204,-764 1204,-728 1390,-728 1390,-764"/>
+<text text-anchor="middle" x="1297" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.InterpolationArrayContainer</text>
+<text text-anchor="middle" x="1297" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1297" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000011s</text>
+</g>
+<!-- pymatlib.core.interpolators.&lt;module&gt;&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer -->
+<g id="edge7" class="edge">
+<title>pymatlib.core.interpolators.&lt;module&gt;&#45;&gt;pymatlib.core.interpolators.InterpolationArrayContainer</title>
+<path fill="none" stroke="#b2b2b2" d="M1311.78,-807.69C1309.37,-797.79 1306.3,-785.16 1303.58,-773.99"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1306.97,-773.15 1301.2,-764.26 1300.17,-774.81 1306.97,-773.15"/>
+<text text-anchor="middle" x="1309" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.models.&lt;module&gt; -->
+<g id="node13" class="node">
+<title>pymatlib.core.models.&lt;module&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1232,-844 1116,-844 1116,-808 1232,-808 1232,-844"/>
+<text text-anchor="middle" x="1174" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.models.&lt;module&gt;</text>
+<text text-anchor="middle" x="1174" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1174" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.002604s</text>
+</g>
+<!-- pymatlib.core.data_handler.&lt;module&gt; -->
+<g id="node14" class="node">
+<title>pymatlib.core.data_handler.&lt;module&gt;</title>
+<polygon fill="#e1e5e5" stroke="#e1e5e5" points="1097.5,-844 964.5,-844 964.5,-808 1097.5,-808 1097.5,-844"/>
+<text text-anchor="middle" x="1031" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.data_handler.&lt;module&gt;</text>
+<text text-anchor="middle" x="1031" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1031" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 6.189607s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser.__init__ -->
+<g id="node19" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser.__init__</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="954.5,-764 761.5,-764 761.5,-728 954.5,-728 954.5,-764"/>
+<text text-anchor="middle" x="858" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser.__init__</text>
+<text text-anchor="middle" x="858" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="858" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.026976s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.create_alloy_from_yaml&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser.__init__ -->
+<g id="edge11" class="edge">
+<title>pymatlib.core.yaml_parser.create_alloy_from_yaml&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser.__init__</title>
+<path fill="none" stroke="#b2b2b2" d="M858,-807.69C858,-797.89 858,-785.42 858,-774.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="861.5,-774.26 858,-764.26 854.5,-774.26 861.5,-774.26"/>
+<text text-anchor="middle" x="860" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy -->
+<g id="node25" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy</title>
+<polygon fill="#e54ce5" stroke="#e54ce5" points="1186,-764 980,-764 980,-728 1186,-728 1186,-764"/>
+<text text-anchor="middle" x="1083" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy</text>
+<text text-anchor="middle" x="1083" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1083" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 228.110086s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.create_alloy_from_yaml&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy -->
+<g id="edge12" class="edge">
+<title>pymatlib.core.yaml_parser.create_alloy_from_yaml&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy</title>
+<path fill="none" stroke="#b23bb2" d="M907.1,-807.98C941.52,-796.05 987.7,-780.04 1024.11,-767.42"/>
+<polygon fill="#b23bb2" stroke="#b23bb2" points="1025.32,-770.7 1033.62,-764.12 1023.02,-764.09 1025.32,-770.7"/>
+<text text-anchor="middle" x="979" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._load_yaml -->
+<g id="node20" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._load_yaml</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1061,-684 857,-684 857,-648 1061,-648 1061,-684"/>
+<text text-anchor="middle" x="959" y="-672.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._load_yaml</text>
+<text text-anchor="middle" x="959" y="-664.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="959" y="-656.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.026249s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser.__init__&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._load_yaml -->
+<g id="edge13" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser.__init__&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._load_yaml</title>
+<path fill="none" stroke="#b2b2b2" d="M880.42,-727.69C894.54,-716.78 912.96,-702.56 928.41,-690.62"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="930.87,-693.14 936.65,-684.26 926.59,-687.6 930.87,-693.14"/>
+<text text-anchor="middle" x="913" y="-704.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._validate_config -->
+<g id="node21" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._validate_config</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="838.5,-684 619.5,-684 619.5,-648 838.5,-648 838.5,-684"/>
+<text text-anchor="middle" x="729" y="-672.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._validate_config</text>
+<text text-anchor="middle" x="729" y="-664.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="729" y="-656.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000217s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser.__init__&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._validate_config -->
+<g id="edge14" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser.__init__&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._validate_config</title>
+<path fill="none" stroke="#b2b2b2" d="M829.69,-727.88C810.95,-716.55 786.2,-701.58 765.92,-689.32"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="767.61,-686.26 757.24,-684.08 763.99,-692.25 767.61,-686.26"/>
+<text text-anchor="middle" x="799" y="-704.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._validate_property_names -->
+<g id="node22" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._validate_property_names</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="588.5,-576 337.5,-576 337.5,-540 588.5,-540 588.5,-576"/>
+<text text-anchor="middle" x="463" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._validate_property_names</text>
+<text text-anchor="middle" x="463" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="463" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000010s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._validate_config&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._validate_property_names -->
+<g id="edge15" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._validate_config&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._validate_property_names</title>
+<path fill="none" stroke="#b2b2b2" d="M686.26,-647.97C639.77,-629.44 565.41,-599.81 515.42,-579.89"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="516.66,-576.61 506.07,-576.16 514.07,-583.12 516.66,-576.61"/>
+<text text-anchor="middle" x="637" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._validate_required_fields -->
+<g id="node23" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._validate_required_fields</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="851.5,-576 606.5,-576 606.5,-540 851.5,-540 851.5,-576"/>
+<text text-anchor="middle" x="729" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._validate_required_fields</text>
+<text text-anchor="middle" x="729" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="729" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000006s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._validate_config&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._validate_required_fields -->
+<g id="edge16" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._validate_config&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._validate_required_fields</title>
+<path fill="none" stroke="#b2b2b2" d="M729,-647.97C729,-631.38 729,-605.88 729,-586.43"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="732.5,-586.34 729,-576.34 725.5,-586.34 732.5,-586.34"/>
+<text text-anchor="middle" x="731" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser._validate_property_values -->
+<g id="node24" class="node">
+<title>pymatlib.core.yaml_parser._validate_property_values</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1052,-576 870,-576 870,-540 1052,-540 1052,-576"/>
+<text text-anchor="middle" x="961" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._validate_property_values</text>
+<text text-anchor="middle" x="961" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="961" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000109s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._validate_config&#45;&gt;pymatlib.core.yaml_parser._validate_property_values -->
+<g id="edge17" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._validate_config&#45;&gt;pymatlib.core.yaml_parser._validate_property_values</title>
+<path fill="none" stroke="#b2b2b2" d="M766.27,-647.97C806.49,-629.6 870.61,-600.3 914.19,-580.39"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="915.79,-583.5 923.43,-576.16 912.88,-577.14 915.79,-583.5"/>
+<text text-anchor="middle" x="881" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._get_elements -->
+<g id="node26" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._get_elements</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2529.5,-630 2314.5,-630 2314.5,-594 2529.5,-594 2529.5,-630"/>
+<text text-anchor="middle" x="2422" y="-618.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._get_elements</text>
+<text text-anchor="middle" x="2422" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="2422" y="-602.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.024456s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._get_elements -->
+<g id="edge18" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._get_elements</title>
+<path fill="none" stroke="#b2b2b2" d="M1186.1,-729.07C1189.1,-728.7 1192.07,-728.34 1195,-728 1439.48,-699.74 1501.93,-706.65 1747,-684 1942.4,-665.94 2169.23,-641.33 2303.9,-626.34"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2304.69,-629.77 2314.24,-625.18 2303.91,-622.81 2304.69,-629.77"/>
+<text text-anchor="middle" x="1499" y="-704.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_properties -->
+<g id="node38" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_properties</title>
+<polygon fill="#e54ce5" stroke="#e54ce5" points="1738,-684 1506,-684 1506,-648 1738,-648 1738,-684"/>
+<text text-anchor="middle" x="1622" y="-672.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_properties</text>
+<text text-anchor="middle" x="1622" y="-664.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1622" y="-656.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 228.082246s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_properties -->
+<g id="edge19" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser.create_alloy&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_properties</title>
+<path fill="none" stroke="#b23bb2" d="M1186.13,-729.31C1189.12,-728.87 1192.08,-728.43 1195,-728 1296.19,-713.09 1410.96,-696.73 1496.01,-684.7"/>
+<polygon fill="#b23bb2" stroke="#b23bb2" points="1496.56,-688.16 1505.97,-683.3 1495.58,-681.23 1496.56,-688.16"/>
+<text text-anchor="middle" x="1372" y="-704.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="node27" class="node">
+<title>pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1440.5,-308 1305.5,-308 1305.5,-272 1440.5,-272 1440.5,-308"/>
+<text text-anchor="middle" x="1373" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.&lt;listcomp&gt;</text>
+<text text-anchor="middle" x="1373" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 9</text>
+<text text-anchor="middle" x="1373" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000041s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._get_elements&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="edge20" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._get_elements&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M2454.56,-593.87C2531.74,-551.2 2713.46,-437.5 2632,-352 2611.54,-330.53 1722.48,-301.67 1450.94,-293.34"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1450.88,-289.83 1440.78,-293.03 1450.67,-296.83 1450.88,-289.83"/>
+<text text-anchor="middle" x="2628" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.alloy.&lt;lambda&gt; -->
+<g id="node28" class="node">
+<title>pymatlib.core.alloy.&lt;lambda&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="711.5,-844 604.5,-844 604.5,-808 711.5,-808 711.5,-844"/>
+<text text-anchor="middle" x="658" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.&lt;lambda&gt;</text>
+<text text-anchor="middle" x="658" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="658" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000021s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy.__post_init__ -->
+<g id="node29" class="node">
+<title>pymatlib.core.alloy.Alloy.__post_init__</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="538,-844 404,-844 404,-808 538,-808 538,-844"/>
+<text text-anchor="middle" x="471" y="-832.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.Alloy.__post_init__</text>
+<text text-anchor="middle" x="471" y="-824.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="471" y="-816.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000759s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy._validate_composition -->
+<g id="node30" class="node">
+<title>pymatlib.core.alloy.Alloy._validate_composition</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="552,-764 390,-764 390,-728 552,-728 552,-764"/>
+<text text-anchor="middle" x="471" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.Alloy._validate_composition</text>
+<text text-anchor="middle" x="471" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="471" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000242s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy.__post_init__&#45;&gt;pymatlib.core.alloy.Alloy._validate_composition -->
+<g id="edge21" class="edge">
+<title>pymatlib.core.alloy.Alloy.__post_init__&#45;&gt;pymatlib.core.alloy.Alloy._validate_composition</title>
+<path fill="none" stroke="#b2b2b2" d="M471,-807.69C471,-797.89 471,-785.42 471,-774.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="474.5,-774.26 471,-764.26 467.5,-774.26 474.5,-774.26"/>
+<text text-anchor="middle" x="473" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy._validate_temperatures -->
+<g id="node31" class="node">
+<title>pymatlib.core.alloy.Alloy._validate_temperatures</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="736,-764 570,-764 570,-728 736,-728 736,-764"/>
+<text text-anchor="middle" x="653" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.Alloy._validate_temperatures</text>
+<text text-anchor="middle" x="653" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="653" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000003s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy.__post_init__&#45;&gt;pymatlib.core.alloy.Alloy._validate_temperatures -->
+<g id="edge22" class="edge">
+<title>pymatlib.core.alloy.Alloy.__post_init__&#45;&gt;pymatlib.core.alloy.Alloy._validate_temperatures</title>
+<path fill="none" stroke="#b2b2b2" d="M510.94,-807.88C538.2,-796.2 574.51,-780.64 603.59,-768.18"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="605.34,-771.23 613.15,-764.08 602.58,-764.8 605.34,-771.23"/>
+<text text-anchor="middle" x="569" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy._calculate_properties -->
+<g id="node32" class="node">
+<title>pymatlib.core.alloy.Alloy._calculate_properties</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="371.5,-764 212.5,-764 212.5,-728 371.5,-728 371.5,-764"/>
+<text text-anchor="middle" x="292" y="-752.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.alloy.Alloy._calculate_properties</text>
+<text text-anchor="middle" x="292" y="-744.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="292" y="-736.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000438s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy.__post_init__&#45;&gt;pymatlib.core.alloy.Alloy._calculate_properties -->
+<g id="edge23" class="edge">
+<title>pymatlib.core.alloy.Alloy.__post_init__&#45;&gt;pymatlib.core.alloy.Alloy._calculate_properties</title>
+<path fill="none" stroke="#b2b2b2" d="M431.72,-807.88C404.9,-796.2 369.2,-780.64 340.6,-768.18"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="341.76,-764.86 331.19,-764.08 338.96,-771.28 341.76,-764.86"/>
+<text text-anchor="middle" x="388" y="-784.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_atomic_number -->
+<g id="node33" class="node">
+<title>pymatlib.core.elements.interpolate_atomic_number</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="380,-684 204,-684 204,-648 380,-648 380,-684"/>
+<text text-anchor="middle" x="292" y="-672.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.elements.interpolate_atomic_number</text>
+<text text-anchor="middle" x="292" y="-664.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="292" y="-656.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000187s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy._calculate_properties&#45;&gt;pymatlib.core.elements.interpolate_atomic_number -->
+<g id="edge24" class="edge">
+<title>pymatlib.core.alloy.Alloy._calculate_properties&#45;&gt;pymatlib.core.elements.interpolate_atomic_number</title>
+<path fill="none" stroke="#b2b2b2" d="M292,-727.69C292,-717.89 292,-705.42 292,-694.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="295.5,-694.26 292,-684.26 288.5,-694.26 295.5,-694.26"/>
+<text text-anchor="middle" x="294" y="-704.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_atomic_mass -->
+<g id="node36" class="node">
+<title>pymatlib.core.elements.interpolate_atomic_mass</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="186,-684 16,-684 16,-648 186,-648 186,-684"/>
+<text text-anchor="middle" x="101" y="-672.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.elements.interpolate_atomic_mass</text>
+<text text-anchor="middle" x="101" y="-664.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="101" y="-656.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000092s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy._calculate_properties&#45;&gt;pymatlib.core.elements.interpolate_atomic_mass -->
+<g id="edge25" class="edge">
+<title>pymatlib.core.alloy.Alloy._calculate_properties&#45;&gt;pymatlib.core.elements.interpolate_atomic_mass</title>
+<path fill="none" stroke="#b2b2b2" d="M250.08,-727.88C221.35,-716.15 183.04,-700.5 152.46,-688.01"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="153.4,-684.62 142.82,-684.08 150.75,-691.1 153.4,-684.62"/>
+<text text-anchor="middle" x="204" y="-704.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_temperature_boil -->
+<g id="node37" class="node">
+<title>pymatlib.core.elements.interpolate_temperature_boil</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="577.5,-684 398.5,-684 398.5,-648 577.5,-648 577.5,-684"/>
+<text text-anchor="middle" x="488" y="-672.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.elements.interpolate_temperature_boil</text>
+<text text-anchor="middle" x="488" y="-664.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="488" y="-656.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000082s</text>
+</g>
+<!-- pymatlib.core.alloy.Alloy._calculate_properties&#45;&gt;pymatlib.core.elements.interpolate_temperature_boil -->
+<g id="edge26" class="edge">
+<title>pymatlib.core.alloy.Alloy._calculate_properties&#45;&gt;pymatlib.core.elements.interpolate_temperature_boil</title>
+<path fill="none" stroke="#b2b2b2" d="M335.01,-727.88C364.63,-716.1 404.15,-700.37 435.6,-687.85"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="437.09,-691.03 445.09,-684.08 434.5,-684.52 437.09,-691.03"/>
+<text text-anchor="middle" x="397" y="-704.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.&lt;listcomp&gt; -->
+<g id="node34" class="node">
+<title>pymatlib.core.elements.&lt;listcomp&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="319.5,-576 194.5,-576 194.5,-540 319.5,-540 319.5,-576"/>
+<text text-anchor="middle" x="257" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.elements.&lt;listcomp&gt;</text>
+<text text-anchor="middle" x="257" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="257" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000022s</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_atomic_number&#45;&gt;pymatlib.core.elements.&lt;listcomp&gt; -->
+<g id="edge27" class="edge">
+<title>pymatlib.core.elements.interpolate_atomic_number&#45;&gt;pymatlib.core.elements.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M286.38,-647.97C280.85,-631.22 272.32,-605.41 265.88,-585.89"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="269.18,-584.74 262.73,-576.34 262.54,-586.93 269.18,-584.74"/>
+<text text-anchor="middle" x="281" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate -->
+<g id="node35" class="node">
+<title>pymatlib.core.elements.interpolate</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="176,-576 52,-576 52,-540 176,-540 176,-576"/>
+<text text-anchor="middle" x="114" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.elements.interpolate</text>
+<text text-anchor="middle" x="114" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="114" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000219s</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_atomic_number&#45;&gt;pymatlib.core.elements.interpolate -->
+<g id="edge28" class="edge">
+<title>pymatlib.core.elements.interpolate_atomic_number&#45;&gt;pymatlib.core.elements.interpolate</title>
+<path fill="none" stroke="#b2b2b2" d="M255.2,-647.84C244.86,-642.55 233.77,-636.41 224,-630 202.87,-616.14 201.04,-607.99 180,-594 173.24,-589.51 165.84,-585.12 158.52,-581.05"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="159.8,-577.77 149.34,-576.09 156.48,-583.93 159.8,-577.77"/>
+<text text-anchor="middle" x="226" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_atomic_mass&#45;&gt;pymatlib.core.elements.&lt;listcomp&gt; -->
+<g id="edge29" class="edge">
+<title>pymatlib.core.elements.interpolate_atomic_mass&#45;&gt;pymatlib.core.elements.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M115.98,-647.71C130.2,-632.1 152.8,-609.3 176,-594 183.61,-588.98 192.05,-584.41 200.54,-580.34"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="202.09,-583.48 209.72,-576.13 199.17,-577.12 202.09,-583.48"/>
+<text text-anchor="middle" x="178" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_atomic_mass&#45;&gt;pymatlib.core.elements.interpolate -->
+<g id="edge30" class="edge">
+<title>pymatlib.core.elements.interpolate_atomic_mass&#45;&gt;pymatlib.core.elements.interpolate</title>
+<path fill="none" stroke="#b2b2b2" d="M103.09,-647.97C105.12,-631.38 108.25,-605.88 110.64,-586.43"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="114.13,-586.69 111.87,-576.34 107.18,-585.84 114.13,-586.69"/>
+<text text-anchor="middle" x="111" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_temperature_boil&#45;&gt;pymatlib.core.elements.&lt;listcomp&gt; -->
+<g id="edge31" class="edge">
+<title>pymatlib.core.elements.interpolate_temperature_boil&#45;&gt;pymatlib.core.elements.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M450.89,-647.97C410.84,-629.6 347,-600.3 303.61,-580.39"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="304.95,-577.15 294.41,-576.16 302.03,-583.52 304.95,-577.15"/>
+<text text-anchor="middle" x="408" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.elements.interpolate_temperature_boil&#45;&gt;pymatlib.core.elements.interpolate -->
+<g id="edge32" class="edge">
+<title>pymatlib.core.elements.interpolate_temperature_boil&#45;&gt;pymatlib.core.elements.interpolate</title>
+<path fill="none" stroke="#b2b2b2" d="M398.44,-649.5C395.26,-648.98 392.1,-648.48 389,-648 332.24,-639.14 311.84,-656.75 261,-630 241.79,-619.89 246.35,-605.59 228,-594 220.21,-589.08 204.05,-583.35 186.29,-577.97"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="186.88,-574.49 176.3,-575.02 184.9,-581.21 186.88,-574.49"/>
+<text text-anchor="middle" x="263" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._categorize_properties -->
+<g id="node39" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._categorize_properties</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1625.5,-576 1386.5,-576 1386.5,-540 1625.5,-540 1625.5,-576"/>
+<text text-anchor="middle" x="1506" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._categorize_properties</text>
+<text text-anchor="middle" x="1506" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1506" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000694s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._categorize_properties -->
+<g id="edge33" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._categorize_properties</title>
+<path fill="none" stroke="#b2b2b2" d="M1603.36,-647.97C1584.2,-630.46 1554.18,-603.02 1532.53,-583.25"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1534.72,-580.5 1524.98,-576.34 1530,-585.67 1534.72,-580.5"/>
+<text text-anchor="middle" x="1583" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser._process_constant_property -->
+<g id="node45" class="node">
+<title>pymatlib.core.yaml_parser._process_constant_property</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1834,-576 1644,-576 1644,-540 1834,-540 1834,-576"/>
+<text text-anchor="middle" x="1739" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._process_constant_property</text>
+<text text-anchor="middle" x="1739" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="1739" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000013s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser._process_constant_property -->
+<g id="edge34" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser._process_constant_property</title>
+<path fill="none" stroke="#b2b2b2" d="M1640.8,-647.97C1660.13,-630.46 1690.41,-603.02 1712.24,-583.25"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1714.8,-585.65 1719.86,-576.34 1710.1,-580.46 1714.8,-585.65"/>
+<text text-anchor="middle" x="1699" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">3</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property -->
+<g id="node46" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property</title>
+<polygon fill="#dce4e5" stroke="#dce4e5" points="2091.5,-576 1852.5,-576 1852.5,-540 2091.5,-540 2091.5,-576"/>
+<text text-anchor="middle" x="1972" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property</text>
+<text text-anchor="middle" x="1972" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="1972" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 13.578895s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property -->
+<g id="edge35" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property</title>
+<path fill="none" stroke="#abb1b2" d="M1678.23,-647.97C1740.27,-629.18 1840,-598.98 1905.77,-579.06"/>
+<polygon fill="#abb1b2" stroke="#abb1b2" points="1907.06,-582.32 1915.62,-576.08 1905.03,-575.63 1907.06,-582.32"/>
+<text text-anchor="middle" x="1850" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property -->
+<g id="node58" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2364,-576 2110,-576 2110,-540 2364,-540 2364,-576"/>
+<text text-anchor="middle" x="2237" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property</text>
+<text text-anchor="middle" x="2237" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 4</text>
+<text text-anchor="middle" x="2237" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.347853s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property -->
+<g id="edge36" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property</title>
+<path fill="none" stroke="#b2b2b2" d="M1738.18,-648.46C1775.81,-642.88 1817.72,-636.43 1856,-630 1953,-613.71 2063.46,-592.87 2140.37,-577.99"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2141.38,-581.37 2150.53,-576.03 2140.04,-574.49 2141.38,-581.37"/>
+<text text-anchor="middle" x="2055" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">4</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property -->
+<g id="node62" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property</title>
+<polygon fill="#d455e5" stroke="#d455e5" points="1331.5,-576 1070.5,-576 1070.5,-540 1331.5,-540 1331.5,-576"/>
+<text text-anchor="middle" x="1201" y="-564.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property</text>
+<text text-anchor="middle" x="1201" y="-556.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="1201" y="-548.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 214.154366s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property -->
+<g id="edge37" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property</title>
+<path fill="none" stroke="#a442b2" d="M1554.36,-647.97C1479.13,-629.03 1357.81,-598.48 1278.73,-578.57"/>
+<polygon fill="#a442b2" stroke="#a442b2" points="1279.37,-575.12 1268.82,-576.08 1277.66,-581.91 1279.37,-575.12"/>
+<text text-anchor="middle" x="1475" y="-610.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type -->
+<g id="node40" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type</title>
+<polygon fill="#e4e5e5" stroke="#e4e5e5" points="1671,-496 1421,-496 1421,-460 1671,-460 1671,-496"/>
+<text text-anchor="middle" x="1546" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type</text>
+<text text-anchor="middle" x="1546" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 12</text>
+<text text-anchor="middle" x="1546" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000440s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._categorize_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type -->
+<g id="edge38" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._categorize_properties&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type</title>
+<path fill="none" stroke="#b2b2b2" d="M1514.88,-539.69C1520.06,-529.59 1526.69,-516.65 1532.51,-505.31"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1535.7,-506.76 1537.15,-496.26 1529.47,-503.56 1535.7,-506.76"/>
+<text text-anchor="middle" x="1531" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">12</text>
+</g>
+<!-- pymatlib.core.yaml_parser._is_numeric -->
+<g id="node41" class="node">
+<title>pymatlib.core.yaml_parser._is_numeric</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1773.5,-388 1634.5,-388 1634.5,-352 1773.5,-352 1773.5,-388"/>
+<text text-anchor="middle" x="1704" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._is_numeric</text>
+<text text-anchor="middle" x="1704" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="1704" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000016s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_numeric -->
+<g id="edge39" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_numeric</title>
+<path fill="none" stroke="#b2b2b2" d="M1571.39,-459.97C1598.14,-442.02 1640.43,-413.65 1670.04,-393.78"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1672.06,-396.64 1678.42,-388.16 1668.16,-390.83 1672.06,-396.64"/>
+<text text-anchor="middle" x="1650" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">3</text>
+</g>
+<!-- pymatlib.core.yaml_parser._is_data_file -->
+<g id="node42" class="node">
+<title>pymatlib.core.yaml_parser._is_data_file</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1616,-388 1476,-388 1476,-352 1616,-352 1616,-388"/>
+<text text-anchor="middle" x="1546" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._is_data_file</text>
+<text text-anchor="middle" x="1546" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 9</text>
+<text text-anchor="middle" x="1546" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000067s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_data_file -->
+<g id="edge40" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_data_file</title>
+<path fill="none" stroke="#b2b2b2" d="M1546,-459.97C1546,-443.38 1546,-417.88 1546,-398.43"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1549.5,-398.34 1546,-388.34 1542.5,-398.34 1549.5,-398.34"/>
+<text text-anchor="middle" x="1548" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">9</text>
+</g>
+<!-- pymatlib.core.yaml_parser._is_key_val_property -->
+<g id="node43" class="node">
+<title>pymatlib.core.yaml_parser._is_key_val_property</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1958.5,-388 1791.5,-388 1791.5,-352 1958.5,-352 1958.5,-388"/>
+<text text-anchor="middle" x="1875" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._is_key_val_property</text>
+<text text-anchor="middle" x="1875" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 7</text>
+<text text-anchor="middle" x="1875" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000011s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_key_val_property -->
+<g id="edge41" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_key_val_property</title>
+<path fill="none" stroke="#b2b2b2" d="M1599.73,-459.97C1617.63,-454.28 1637.68,-447.88 1656,-442 1709.07,-424.96 1769.31,-405.41 1813.15,-391.15"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1814.39,-394.43 1822.81,-388.01 1812.22,-387.77 1814.39,-394.43"/>
+<text text-anchor="middle" x="1765" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">7</text>
+</g>
+<!-- pymatlib.core.yaml_parser._is_compute_property -->
+<g id="node44" class="node">
+<title>pymatlib.core.yaml_parser._is_compute_property</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1458,-388 1288,-388 1288,-352 1458,-352 1458,-388"/>
+<text text-anchor="middle" x="1373" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._is_compute_property</text>
+<text text-anchor="middle" x="1373" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="1373" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000041s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_compute_property -->
+<g id="edge42" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._determine_property_type&#45;&gt;pymatlib.core.yaml_parser._is_compute_property</title>
+<path fill="none" stroke="#b2b2b2" d="M1518.2,-459.97C1488.78,-441.94 1442.2,-413.4 1409.76,-393.53"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1411.37,-390.4 1401.01,-388.16 1407.71,-396.37 1411.37,-390.4"/>
+<text text-anchor="middle" x="1487" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">3</text>
+</g>
+<!-- pymatlib.core.yaml_parser._is_data_file&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="edge43" class="edge">
+<title>pymatlib.core.yaml_parser._is_data_file&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M1508.03,-351.88C1482.23,-340.25 1447.91,-324.78 1420.33,-312.34"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1421.43,-309 1410.88,-308.08 1418.55,-315.38 1421.43,-309"/>
+<text text-anchor="middle" x="1466" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser._is_compute_property&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="edge44" class="edge">
+<title>pymatlib.core.yaml_parser._is_compute_property&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M1373,-351.69C1373,-341.89 1373,-329.42 1373,-318.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1376.5,-318.26 1373,-308.26 1369.5,-318.26 1376.5,-318.26"/>
+<text text-anchor="middle" x="1375" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.data_handler.read_data_from_file -->
+<g id="node47" class="node">
+<title>pymatlib.core.data_handler.read_data_from_file</title>
+<polygon fill="#e3e5e5" stroke="#e3e5e5" points="2054,-496 1890,-496 1890,-460 2054,-460 2054,-496"/>
+<text text-anchor="middle" x="1972" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.data_handler.read_data_from_file</text>
+<text text-anchor="middle" x="1972" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="1972" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 2.784941s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property&#45;&gt;pymatlib.core.data_handler.read_data_from_file -->
+<g id="edge45" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property&#45;&gt;pymatlib.core.data_handler.read_data_from_file</title>
+<path fill="none" stroke="#b0b2b2" d="M1972,-539.69C1972,-529.89 1972,-517.42 1972,-506.33"/>
+<polygon fill="#b0b2b2" stroke="#b0b2b2" points="1975.5,-506.26 1972,-496.26 1968.5,-506.26 1975.5,-506.26"/>
+<text text-anchor="middle" x="1974" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data -->
+<g id="node48" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data</title>
+<polygon fill="#dde4e5" stroke="#dde4e5" points="2582,-496 2338,-496 2338,-460 2582,-460 2582,-496"/>
+<text text-anchor="middle" x="2460" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data</text>
+<text text-anchor="middle" x="2460" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 6</text>
+<text text-anchor="middle" x="2460" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 11.140857s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data -->
+<g id="edge46" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_file_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data</title>
+<path fill="none" stroke="#acb1b2" d="M2060.38,-539.98C2104.63,-531.7 2159.07,-521.85 2208,-514 2246.73,-507.78 2288.92,-501.67 2327.51,-496.33"/>
+<polygon fill="#acb1b2" stroke="#acb1b2" points="2328.33,-499.75 2337.76,-494.92 2327.37,-492.82 2328.33,-499.75"/>
+<text text-anchor="middle" x="2210" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_symbolic_temperature -->
+<g id="node49" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_symbolic_temperature</title>
+<polygon fill="#dde4e5" stroke="#dde4e5" points="2623,-388 2353,-388 2353,-352 2623,-352 2623,-388"/>
+<text text-anchor="middle" x="2488" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_symbolic_temperature</text>
+<text text-anchor="middle" x="2488" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 6</text>
+<text text-anchor="middle" x="2488" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 11.140720s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_symbolic_temperature -->
+<g id="edge47" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_symbolic_temperature</title>
+<path fill="none" stroke="#acb1b2" d="M2464.5,-459.97C2468.9,-443.3 2475.68,-417.65 2480.83,-398.16"/>
+<polygon fill="#acb1b2" stroke="#acb1b2" points="2484.25,-398.9 2483.42,-388.34 2477.48,-397.12 2484.25,-398.9"/>
+<text text-anchor="middle" x="2480" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">6</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property -->
+<g id="node50" class="node">
+<title>pymatlib.core.interpolators.interpolate_property</title>
+<polygon fill="#dde4e5" stroke="#dde4e5" points="2131.5,-308 1968.5,-308 1968.5,-272 2131.5,-272 2131.5,-308"/>
+<text text-anchor="middle" x="2050" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.interpolate_property</text>
+<text text-anchor="middle" x="2050" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 6</text>
+<text text-anchor="middle" x="2050" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 11.140519s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_symbolic_temperature&#45;&gt;pymatlib.core.interpolators.interpolate_property -->
+<g id="edge48" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_symbolic_temperature&#45;&gt;pymatlib.core.interpolators.interpolate_property</title>
+<path fill="none" stroke="#acb1b2" d="M2392.42,-351.98C2318.01,-338.73 2215.39,-320.45 2141.93,-307.37"/>
+<polygon fill="#acb1b2" stroke="#acb1b2" points="2142.22,-303.87 2131.76,-305.56 2140.99,-310.76 2142.22,-303.87"/>
+<text text-anchor="middle" x="2284" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">6</text>
+</g>
+<!-- pymatlib.core.data_handler.check_equidistant -->
+<g id="node51" class="node">
+<title>pymatlib.core.data_handler.check_equidistant</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2240.5,-228 2081.5,-228 2081.5,-192 2240.5,-192 2240.5,-228"/>
+<text text-anchor="middle" x="2161" y="-216.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.data_handler.check_equidistant</text>
+<text text-anchor="middle" x="2161" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 6</text>
+<text text-anchor="middle" x="2161" y="-200.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.001892s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.data_handler.check_equidistant -->
+<g id="edge49" class="edge">
+<title>pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.data_handler.check_equidistant</title>
+<path fill="none" stroke="#b2b2b2" d="M2074.36,-271.88C2090.12,-260.81 2110.83,-246.25 2128.05,-234.15"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2130.53,-236.69 2136.7,-228.08 2126.5,-230.96 2130.53,-236.69"/>
+<text text-anchor="middle" x="2110" y="-248.4" font-family="Verdana" font-size="7.00" fill="#000000">6</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_lookup -->
+<g id="node52" class="node">
+<title>pymatlib.core.interpolators.interpolate_lookup</title>
+<polygon fill="#dee4e5" stroke="#dee4e5" points="1874,-228 1716,-228 1716,-192 1874,-192 1874,-228"/>
+<text text-anchor="middle" x="1795" y="-216.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.interpolate_lookup</text>
+<text text-anchor="middle" x="1795" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 4</text>
+<text text-anchor="middle" x="1795" y="-200.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 10.813489s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_lookup -->
+<g id="edge50" class="edge">
+<title>pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_lookup</title>
+<path fill="none" stroke="#acb1b2" d="M1994.35,-271.98C1955.01,-259.94 1902.11,-243.76 1860.69,-231.09"/>
+<polygon fill="#acb1b2" stroke="#acb1b2" points="1861.55,-227.7 1850.97,-228.12 1859.51,-234.39 1861.55,-227.7"/>
+<text text-anchor="middle" x="1932" y="-248.4" font-family="Verdana" font-size="7.00" fill="#000000">4</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_equidistant -->
+<g id="node57" class="node">
+<title>pymatlib.core.interpolators.interpolate_equidistant</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2063.5,-228 1892.5,-228 1892.5,-192 2063.5,-192 2063.5,-228"/>
+<text text-anchor="middle" x="1978" y="-216.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.interpolators.interpolate_equidistant</text>
+<text text-anchor="middle" x="1978" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="1978" y="-200.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.324139s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_equidistant -->
+<g id="edge51" class="edge">
+<title>pymatlib.core.interpolators.interpolate_property&#45;&gt;pymatlib.core.interpolators.interpolate_equidistant</title>
+<path fill="none" stroke="#b2b2b2" d="M2034.02,-271.69C2024.23,-261.09 2011.55,-247.35 2000.73,-235.62"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2003.29,-233.24 1993.93,-228.26 1998.15,-237.98 2003.29,-233.24"/>
+<text text-anchor="middle" x="2018" y="-248.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.models.wrapper -->
+<g id="node53" class="node">
+<title>pymatlib.core.models.wrapper</title>
+<polygon fill="#e4e5e5" stroke="#e4e5e5" points="1850,-148 1740,-148 1740,-112 1850,-112 1850,-148"/>
+<text text-anchor="middle" x="1795" y="-136.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.models.wrapper</text>
+<text text-anchor="middle" x="1795" y="-128.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 20</text>
+<text text-anchor="middle" x="1795" y="-120.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.160822s</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_lookup&#45;&gt;pymatlib.core.models.wrapper -->
+<g id="edge52" class="edge">
+<title>pymatlib.core.interpolators.interpolate_lookup&#45;&gt;pymatlib.core.models.wrapper</title>
+<path fill="none" stroke="#b2b2b2" d="M1795,-191.69C1795,-181.89 1795,-169.42 1795,-158.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1798.5,-158.26 1795,-148.26 1791.5,-158.26 1798.5,-158.26"/>
+<text text-anchor="middle" x="1797" y="-168.4" font-family="Verdana" font-size="7.00" fill="#000000">8</text>
+</g>
+<!-- pymatlib.core.models.&lt;listcomp&gt; -->
+<g id="node54" class="node">
+<title>pymatlib.core.models.&lt;listcomp&gt;</title>
+<polygon fill="#e4e5e5" stroke="#e4e5e5" points="1854.5,-68 1735.5,-68 1735.5,-32 1854.5,-32 1854.5,-68"/>
+<text text-anchor="middle" x="1795" y="-56.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.models.&lt;listcomp&gt;</text>
+<text text-anchor="middle" x="1795" y="-48.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 10</text>
+<text text-anchor="middle" x="1795" y="-40.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.158697s</text>
+</g>
+<!-- pymatlib.core.models.wrapper&#45;&gt;pymatlib.core.models.&lt;listcomp&gt; -->
+<g id="edge53" class="edge">
+<title>pymatlib.core.models.wrapper&#45;&gt;pymatlib.core.models.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M1795,-111.69C1795,-101.89 1795,-89.42 1795,-78.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1798.5,-78.26 1795,-68.26 1791.5,-78.26 1798.5,-78.26"/>
+<text text-anchor="middle" x="1799" y="-88.4" font-family="Verdana" font-size="7.00" fill="#000000">10</text>
+</g>
+<!-- pymatlib.core.typedefs.MaterialProperty.__post_init__ -->
+<g id="node55" class="node">
+<title>pymatlib.core.typedefs.MaterialProperty.__post_init__</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="200,-388 16,-388 16,-352 200,-352 200,-388"/>
+<text text-anchor="middle" x="108" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.typedefs.MaterialProperty.__post_init__</text>
+<text text-anchor="middle" x="108" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 8</text>
+<text text-anchor="middle" x="108" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000429s</text>
+</g>
+<!-- pymatlib.core.typedefs.&lt;genexpr&gt; -->
+<g id="node56" class="node">
+<title>pymatlib.core.typedefs.&lt;genexpr&gt;</title>
+<polygon fill="#9998e5" stroke="#9998e5" points="287,-308 165,-308 165,-272 287,-272 287,-308"/>
+<text text-anchor="middle" x="226" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.typedefs.&lt;genexpr&gt;</text>
+<text text-anchor="middle" x="226" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1,657</text>
+<text text-anchor="middle" x="226" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.160218s</text>
+</g>
+<!-- pymatlib.core.typedefs.MaterialProperty.__post_init__&#45;&gt;pymatlib.core.typedefs.&lt;genexpr&gt; -->
+<g id="edge54" class="edge">
+<title>pymatlib.core.typedefs.MaterialProperty.__post_init__&#45;&gt;pymatlib.core.typedefs.&lt;genexpr&gt;</title>
+<path fill="none" stroke="#b1b2b2" d="M133.9,-351.88C150.88,-340.66 173.28,-325.85 191.73,-313.65"/>
+<polygon fill="#b1b2b2" stroke="#b1b2b2" points="193.75,-316.51 200.16,-308.08 189.89,-310.67 193.75,-316.51"/>
+<text text-anchor="middle" x="174" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">25</text>
+</g>
+<!-- pymatlib.core.interpolators.interpolate_equidistant&#45;&gt;pymatlib.core.models.wrapper -->
+<g id="edge55" class="edge">
+<title>pymatlib.core.interpolators.interpolate_equidistant&#45;&gt;pymatlib.core.models.wrapper</title>
+<path fill="none" stroke="#b2b2b2" d="M1937.84,-191.88C1910.31,-180.15 1873.61,-164.5 1844.3,-152.01"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1845.64,-148.78 1835.07,-148.08 1842.89,-155.22 1845.64,-148.78"/>
+<text text-anchor="middle" x="1895" y="-168.4" font-family="Verdana" font-size="7.00" fill="#000000">10</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data -->
+<g id="edge57" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_property_data</title>
+<path fill="none" stroke="#acb1b2" d="M2285.66,-539.98C2319.63,-528.1 2365.16,-512.17 2401.17,-499.58"/>
+<polygon fill="#acb1b2" stroke="#acb1b2" points="2402.77,-502.72 2411.06,-496.12 2400.46,-496.12 2402.77,-502.72"/>
+<text text-anchor="middle" x="2357" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">4</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition -->
+<g id="node59" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2320,-496 2076,-496 2076,-460 2320,-460 2320,-496"/>
+<text text-anchor="middle" x="2198" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition</text>
+<text text-anchor="middle" x="2198" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 4</text>
+<text text-anchor="middle" x="2198" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000328s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition -->
+<g id="edge56" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_key_val_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition</title>
+<path fill="none" stroke="#b2b2b2" d="M2228.34,-539.69C2223.3,-529.59 2216.82,-516.65 2211.16,-505.31"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2214.23,-503.64 2206.63,-496.26 2207.97,-506.77 2214.23,-503.64"/>
+<text text-anchor="middle" x="2220" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">4</text>
+</g>
+<!-- pymatlib.core.yaml_parser._process_list_key -->
+<g id="node60" class="node">
+<title>pymatlib.core.yaml_parser._process_list_key</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2335,-388 2177,-388 2177,-352 2335,-352 2335,-388"/>
+<text text-anchor="middle" x="2256" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._process_list_key</text>
+<text text-anchor="middle" x="2256" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="2256" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000070s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition&#45;&gt;pymatlib.core.yaml_parser._process_list_key -->
+<g id="edge58" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition&#45;&gt;pymatlib.core.yaml_parser._process_list_key</title>
+<path fill="none" stroke="#b2b2b2" d="M2207.32,-459.97C2216.57,-443.07 2230.87,-416.94 2241.58,-397.36"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2244.78,-398.79 2246.51,-388.34 2238.64,-395.43 2244.78,-398.79"/>
+<text text-anchor="middle" x="2237" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser._process_equidistant_key -->
+<g id="node61" class="node">
+<title>pymatlib.core.yaml_parser._process_equidistant_key</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="2159,-388 1977,-388 1977,-352 2159,-352 2159,-388"/>
+<text text-anchor="middle" x="2068" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._process_equidistant_key</text>
+<text text-anchor="middle" x="2068" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="2068" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000089s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition&#45;&gt;pymatlib.core.yaml_parser._process_equidistant_key -->
+<g id="edge59" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_key_definition&#45;&gt;pymatlib.core.yaml_parser._process_equidistant_key</title>
+<path fill="none" stroke="#b2b2b2" d="M2177.11,-459.97C2155.45,-442.3 2121.4,-414.54 2097.1,-394.73"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="2099.23,-391.95 2089.27,-388.34 2094.81,-397.37 2099.23,-391.95"/>
+<text text-anchor="middle" x="2154" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser._process_equidistant_key&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="edge60" class="edge">
+<title>pymatlib.core.yaml_parser._process_equidistant_key&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M1976.75,-353.23C1973.8,-352.8 1970.88,-352.39 1968,-352 1782.98,-326.82 1564.31,-306.91 1450.55,-297.3"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1450.8,-293.81 1440.54,-296.46 1450.21,-300.78 1450.8,-293.81"/>
+<text text-anchor="middle" x="1823" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser._get_computation_methods -->
+<g id="node63" class="node">
+<title>pymatlib.core.yaml_parser._get_computation_methods</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="562,-496 374,-496 374,-460 562,-460 562,-496"/>
+<text text-anchor="middle" x="468" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._get_computation_methods</text>
+<text text-anchor="middle" x="468" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="468" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000015s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser._get_computation_methods -->
+<g id="edge61" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser._get_computation_methods</title>
+<path fill="none" stroke="#b2b2b2" d="M1070.23,-540.99C1067.12,-540.65 1064.04,-540.32 1061,-540 844,-517.07 788.48,-523.4 572,-496 571.9,-495.99 571.8,-495.97 571.69,-495.96"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="572.43,-492.53 562.06,-494.69 571.51,-499.47 572.43,-492.53"/>
+<text text-anchor="middle" x="851" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser._get_dependencies -->
+<g id="node64" class="node">
+<title>pymatlib.core.yaml_parser._get_dependencies</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="741.5,-496 580.5,-496 580.5,-460 741.5,-460 741.5,-496"/>
+<text text-anchor="middle" x="661" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._get_dependencies</text>
+<text text-anchor="middle" x="661" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="661" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000028s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser._get_dependencies -->
+<g id="edge62" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser._get_dependencies</title>
+<path fill="none" stroke="#b2b2b2" d="M1070.28,-541.1C982.88,-530.04 865.09,-514.3 751.81,-496.09"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="752.35,-492.63 741.92,-494.49 751.23,-499.54 752.35,-492.63"/>
+<text text-anchor="middle" x="925" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_dependencies -->
+<g id="node65" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_dependencies</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1379,-442 1135,-442 1135,-406 1379,-406 1379,-442"/>
+<text text-anchor="middle" x="1257" y="-430.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_dependencies</text>
+<text text-anchor="middle" x="1257" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="1257" y="-414.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000067s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_dependencies -->
+<g id="edge63" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_dependencies</title>
+<path fill="none" stroke="#b2b2b2" d="M1208.32,-539.74C1217.84,-517.31 1234.55,-477.91 1245.7,-451.63"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1248.99,-452.83 1249.68,-442.26 1242.55,-450.1 1248.99,-452.83"/>
+<text text-anchor="middle" x="1220" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;lambda&gt; -->
+<g id="node66" class="node">
+<title>pymatlib.core.yaml_parser.&lt;lambda&gt;</title>
+<polygon fill="#e53dc3" stroke="#e53dc3" points="890.5,-496 759.5,-496 759.5,-460 890.5,-460 890.5,-496"/>
+<text text-anchor="middle" x="825" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.&lt;lambda&gt;</text>
+<text text-anchor="middle" x="825" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 544</text>
+<text text-anchor="middle" x="825" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 213.404040s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser.&lt;lambda&gt; -->
+<g id="edge64" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser.&lt;lambda&gt;</title>
+<path fill="none" stroke="#a443b2" d="M1118.95,-539.98C1053.93,-526.49 963.81,-507.8 900.54,-494.67"/>
+<polygon fill="#a443b2" stroke="#a443b2" points="901.13,-491.22 890.63,-492.61 899.71,-498.07 901.13,-491.22"/>
+<text text-anchor="middle" x="1026" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density -->
+<g id="node71" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density</title>
+<polygon fill="#d355e5" stroke="#d355e5" points="1196,-496 952,-496 952,-460 1196,-460 1196,-496"/>
+<text text-anchor="middle" x="1074" y="-484.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density</text>
+<text text-anchor="middle" x="1074" y="-476.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="1074" y="-468.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 213.977598s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density -->
+<g id="edge65" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_computed_property&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density</title>
+<path fill="none" stroke="#a442b2" d="M1173.13,-539.88C1154.68,-528.55 1130.31,-513.58 1110.35,-501.32"/>
+<polygon fill="#a442b2" stroke="#a442b2" points="1112.16,-498.33 1101.81,-496.08 1108.5,-504.29 1112.16,-498.33"/>
+<text text-anchor="middle" x="1143" y="-516.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_dependencies&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="edge66" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_dependencies&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M1257.76,-406C1259.22,-390.58 1263.37,-367.91 1275,-352 1286.98,-335.6 1304.84,-322.63 1322.03,-312.94"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1323.77,-315.98 1330.93,-308.17 1320.46,-309.81 1323.77,-315.98"/>
+<text text-anchor="middle" x="1277" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.models.thermal_diffusivity_by_heat_conductivity -->
+<g id="node67" class="node">
+<title>pymatlib.core.models.thermal_diffusivity_by_heat_conductivity</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="804,-388 592,-388 592,-352 804,-352 804,-388"/>
+<text text-anchor="middle" x="698" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.models.thermal_diffusivity_by_heat_conductivity</text>
+<text text-anchor="middle" x="698" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="698" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.171897s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;lambda&gt;&#45;&gt;pymatlib.core.models.thermal_diffusivity_by_heat_conductivity -->
+<g id="edge67" class="edge">
+<title>pymatlib.core.yaml_parser.&lt;lambda&gt;&#45;&gt;pymatlib.core.models.thermal_diffusivity_by_heat_conductivity</title>
+<path fill="none" stroke="#b2b2b2" d="M804.6,-459.97C783.52,-442.38 750.46,-414.78 726.74,-394.99"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="728.7,-392.06 718.78,-388.34 724.21,-397.44 728.7,-392.06"/>
+<text text-anchor="middle" x="782" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.models.energy_density_total_enthalpy -->
+<g id="node70" class="node">
+<title>pymatlib.core.models.energy_density_total_enthalpy</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="574,-388 394,-388 394,-352 574,-352 574,-388"/>
+<text text-anchor="middle" x="484" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.models.energy_density_total_enthalpy</text>
+<text text-anchor="middle" x="484" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="484" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.004307s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;lambda&gt;&#45;&gt;pymatlib.core.models.energy_density_total_enthalpy -->
+<g id="edge68" class="edge">
+<title>pymatlib.core.yaml_parser.&lt;lambda&gt;&#45;&gt;pymatlib.core.models.energy_density_total_enthalpy</title>
+<path fill="none" stroke="#b2b2b2" d="M759.3,-461.54C756.5,-461 753.73,-460.48 751,-460 687.49,-448.77 668.14,-462.53 607,-442 573.69,-430.82 539.35,-410.08 515.45,-393.9"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="517.36,-390.96 507.14,-388.17 513.39,-396.73 517.36,-390.96"/>
+<text text-anchor="middle" x="609" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.typedefs.MaterialProperty.evalf -->
+<g id="node75" class="node">
+<title>pymatlib.core.typedefs.MaterialProperty.evalf</title>
+<polygon fill="#e53cc3" stroke="#e53cc3" points="376,-388 218,-388 218,-352 376,-352 376,-388"/>
+<text text-anchor="middle" x="297" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.typedefs.MaterialProperty.evalf</text>
+<text text-anchor="middle" x="297" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 544</text>
+<text text-anchor="middle" x="297" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 213.951861s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;lambda&gt;&#45;&gt;pymatlib.core.typedefs.MaterialProperty.evalf -->
+<g id="edge69" class="edge">
+<title>pymatlib.core.yaml_parser.&lt;lambda&gt;&#45;&gt;pymatlib.core.typedefs.MaterialProperty.evalf</title>
+<path fill="none" stroke="#b22f97" d="M759.33,-461.38C756.52,-460.88 753.74,-460.42 751,-460 648.32,-444.33 619.92,-462.02 518,-442 458.87,-430.38 393.42,-408.12 349.2,-391.6"/>
+<polygon fill="#b22f97" stroke="#b22f97" points="350.41,-388.32 339.82,-388.06 347.94,-394.87 350.41,-388.32"/>
+<text text-anchor="middle" x="524" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">542</text>
+</g>
+<!-- pymatlib.core.models._validate_positive -->
+<g id="node68" class="node">
+<title>pymatlib.core.models._validate_positive</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="579.5,-308 438.5,-308 438.5,-272 579.5,-272 579.5,-308"/>
+<text text-anchor="middle" x="509" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.models._validate_positive</text>
+<text text-anchor="middle" x="509" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="509" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000016s</text>
+</g>
+<!-- pymatlib.core.models.thermal_diffusivity_by_heat_conductivity&#45;&gt;pymatlib.core.models._validate_positive -->
+<g id="edge70" class="edge">
+<title>pymatlib.core.models.thermal_diffusivity_by_heat_conductivity&#45;&gt;pymatlib.core.models._validate_positive</title>
+<path fill="none" stroke="#b2b2b2" d="M656.52,-351.88C628.09,-340.15 590.18,-324.5 559.92,-312.01"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="560.96,-308.66 550.38,-308.08 558.29,-315.13 560.96,-308.66"/>
+<text text-anchor="middle" x="611" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.models._prepare_material_expressions -->
+<g id="node69" class="node">
+<title>pymatlib.core.models._prepare_material_expressions</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="789,-308 607,-308 607,-272 789,-272 789,-308"/>
+<text text-anchor="middle" x="698" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.models._prepare_material_expressions</text>
+<text text-anchor="middle" x="698" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 2</text>
+<text text-anchor="middle" x="698" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000391s</text>
+</g>
+<!-- pymatlib.core.models.thermal_diffusivity_by_heat_conductivity&#45;&gt;pymatlib.core.models._prepare_material_expressions -->
+<g id="edge71" class="edge">
+<title>pymatlib.core.models.thermal_diffusivity_by_heat_conductivity&#45;&gt;pymatlib.core.models._prepare_material_expressions</title>
+<path fill="none" stroke="#b2b2b2" d="M698,-351.69C698,-341.89 698,-329.42 698,-318.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="701.5,-318.26 698,-308.26 694.5,-318.26 701.5,-318.26"/>
+<text text-anchor="middle" x="700" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.models._prepare_material_expressions&#45;&gt;pymatlib.core.models.wrapper -->
+<g id="edge72" class="edge">
+<title>pymatlib.core.models._prepare_material_expressions&#45;&gt;pymatlib.core.models.wrapper</title>
+<path fill="none" stroke="#b2b2b2" d="M789.17,-275.87C1005,-244.78 1543.04,-167.29 1729.86,-140.38"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1730.41,-143.84 1739.81,-138.95 1729.42,-136.91 1730.41,-143.84"/>
+<text text-anchor="middle" x="1357" y="-208.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.models.energy_density_total_enthalpy&#45;&gt;pymatlib.core.models._validate_positive -->
+<g id="edge73" class="edge">
+<title>pymatlib.core.models.energy_density_total_enthalpy&#45;&gt;pymatlib.core.models._validate_positive</title>
+<path fill="none" stroke="#b2b2b2" d="M489.55,-351.69C492.72,-341.79 496.77,-329.16 500.35,-317.99"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="503.75,-318.85 503.47,-308.26 497.08,-316.72 503.75,-318.85"/>
+<text text-anchor="middle" x="499" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.models.energy_density_total_enthalpy&#45;&gt;pymatlib.core.models._prepare_material_expressions -->
+<g id="edge74" class="edge">
+<title>pymatlib.core.models.energy_density_total_enthalpy&#45;&gt;pymatlib.core.models._prepare_material_expressions</title>
+<path fill="none" stroke="#b2b2b2" d="M560.93,-351.98C579.55,-346.98 599.21,-340.95 617,-334 631.7,-328.25 647.16,-320.51 660.59,-313.18"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="662.49,-316.12 669.52,-308.2 659.09,-310.01 662.49,-316.12"/>
+<text text-anchor="middle" x="637" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="edge75" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M1069.39,-459.62C1063.47,-432.98 1056.82,-382 1083,-352 1110.36,-320.66 1218.91,-304.57 1295.13,-296.97"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1295.57,-300.45 1305.19,-296 1294.9,-293.48 1295.57,-300.45"/>
+<text text-anchor="middle" x="1085" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.&lt;genexpr&gt; -->
+<g id="node72" class="node">
+<title>pymatlib.core.yaml_parser.&lt;genexpr&gt;</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1230,-388 1096,-388 1096,-352 1230,-352 1230,-388"/>
+<text text-anchor="middle" x="1163" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.&lt;genexpr&gt;</text>
+<text text-anchor="middle" x="1163" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 3</text>
+<text text-anchor="middle" x="1163" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000006s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.yaml_parser.&lt;genexpr&gt; -->
+<g id="edge76" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.yaml_parser.&lt;genexpr&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M1083.87,-459.72C1092.83,-444.73 1106.93,-422.86 1122,-406 1125.42,-402.17 1129.26,-398.38 1133.17,-394.78"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1135.52,-397.38 1140.72,-388.14 1130.9,-392.12 1135.52,-397.38"/>
+<text text-anchor="middle" x="1124" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">3</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_edta -->
+<g id="node73" class="node">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_edta</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1037.5,-388 822.5,-388 822.5,-352 1037.5,-352 1037.5,-388"/>
+<text text-anchor="middle" x="930" y="-376.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser.MaterialConfigParser._process_edta</text>
+<text text-anchor="middle" x="930" y="-368.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="930" y="-360.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000095s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_edta -->
+<g id="edge77" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.yaml_parser.MaterialConfigParser._process_edta</title>
+<path fill="none" stroke="#b2b2b2" d="M1050.86,-459.97C1026.76,-442.23 988.82,-414.3 961.88,-394.47"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="963.69,-391.45 953.56,-388.34 959.54,-397.09 963.69,-391.45"/>
+<text text-anchor="middle" x="1025" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.typedefs.MaterialProperty.evalf -->
+<g id="edge78" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._handle_energy_density&#45;&gt;pymatlib.core.typedefs.MaterialProperty.evalf</title>
+<path fill="none" stroke="#a442b2" d="M951.61,-464.93C858.63,-455.67 744.86,-444.13 734,-442 678.1,-431.04 667.02,-416.32 611,-406 515,-388.32 486.61,-400.74 386.05,-388.02"/>
+<polygon fill="#a442b2" stroke="#a442b2" points="386.46,-384.54 376.09,-386.71 385.54,-391.48 386.46,-384.54"/>
+<text text-anchor="middle" x="736" y="-422.4" font-family="Verdana" font-size="7.00" fill="#000000">2</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_edta&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt; -->
+<g id="edge79" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_edta&#45;&gt;pymatlib.core.yaml_parser.&lt;listcomp&gt;</title>
+<path fill="none" stroke="#b2b2b2" d="M975.94,-351.9C1001.78,-342.92 1034.81,-332.46 1065,-326 1142.39,-309.44 1232.51,-300.36 1295.19,-295.63"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="1295.68,-299.1 1305.4,-294.87 1295.17,-292.12 1295.68,-299.1"/>
+<text text-anchor="middle" x="1067" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.yaml_parser._process_float_delta -->
+<g id="node74" class="node">
+<title>pymatlib.core.yaml_parser._process_float_delta</title>
+<polygon fill="#e5e5e5" stroke="#e5e5e5" points="1013,-308 847,-308 847,-272 1013,-272 1013,-308"/>
+<text text-anchor="middle" x="930" y="-296.4" font-family="Verdana" font-size="7.00" fill="#000000">pymatlib.core.yaml_parser._process_float_delta</text>
+<text text-anchor="middle" x="930" y="-288.4" font-family="Verdana" font-size="7.00" fill="#000000">calls: 1</text>
+<text text-anchor="middle" x="930" y="-280.4" font-family="Verdana" font-size="7.00" fill="#000000">time: 0.000030s</text>
+</g>
+<!-- pymatlib.core.yaml_parser.MaterialConfigParser._process_edta&#45;&gt;pymatlib.core.yaml_parser._process_float_delta -->
+<g id="edge80" class="edge">
+<title>pymatlib.core.yaml_parser.MaterialConfigParser._process_edta&#45;&gt;pymatlib.core.yaml_parser._process_float_delta</title>
+<path fill="none" stroke="#b2b2b2" d="M930,-351.69C930,-341.89 930,-329.42 930,-318.33"/>
+<polygon fill="#b2b2b2" stroke="#b2b2b2" points="933.5,-318.26 930,-308.26 926.5,-318.26 933.5,-318.26"/>
+<text text-anchor="middle" x="932" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1</text>
+</g>
+<!-- pymatlib.core.typedefs.MaterialProperty.evalf&#45;&gt;pymatlib.core.typedefs.&lt;genexpr&gt; -->
+<g id="edge81" class="edge">
+<title>pymatlib.core.typedefs.MaterialProperty.evalf&#45;&gt;pymatlib.core.typedefs.&lt;genexpr&gt;</title>
+<path fill="none" stroke="#7778b2" d="M281.24,-351.69C271.68,-341.19 259.32,-327.61 248.72,-315.96"/>
+<polygon fill="#7778b2" stroke="#7778b2" points="251.03,-313.3 241.71,-308.26 245.86,-318.01 251.03,-313.3"/>
+<text text-anchor="middle" x="271" y="-328.4" font-family="Verdana" font-size="7.00" fill="#000000">1632</text>
+</g>
+</g>
+</svg>
diff --git a/apps/visualize_all_functions.py b/apps/visualize_all_functions.py
new file mode 100644
index 0000000000000000000000000000000000000000..0b3510bd76284ba1c60fc776a092f1496a1c41a4
--- /dev/null
+++ b/apps/visualize_all_functions.py
@@ -0,0 +1,96 @@
+import os
+import sys
+sys.path.append('/local/ca00xebo/repos/pymatlib')
+
+from pycallgraph2 import PyCallGraph, Config
+from pycallgraph2.output import GraphvizOutput
+from pycallgraph2.globbing_filter import GlobbingFilter
+
+# Import necessary modules once
+import sympy as sp
+import pystencils as ps
+from importlib.resources import files
+from pystencilssfg import SourceFileGenerator
+from pymatlib.core.yaml_parser import create_alloy_from_yaml
+from pymatlib.core.interpolators import InterpolationArrayContainer
+from pymatlib.core.assignment_converter import assignment_converter
+
+# Define the path to the folder inside the apps directory
+apps_directory = '/local/ca00xebo/repos/pymatlib/apps'
+image_folder = os.path.join(apps_directory, 'callgraph_images')
+
+# Create the folder if it does not exist
+if not os.path.exists(image_folder):
+    os.makedirs(image_folder)
+
+# Function to create a visualization for a specific target
+def create_visualization(target_name, include_patterns, output_filename):
+    print(f"Generating visualization for {target_name}...")
+
+    # Create the full path for the output file
+    output_file = os.path.join(image_folder, output_filename)
+
+    # Create configuration
+    config = Config(max_depth=10)
+    config.trace_filter = GlobbingFilter(
+        include=include_patterns,
+        exclude=[
+            'pycallgraph2.*',
+            '*.append',
+            '*.join',
+        ]
+    )
+
+    # Configure the output
+    graphviz = GraphvizOutput(
+        output_file=output_file,
+        font_name='Verdana',
+        font_size=7,
+        group_stdlib=True,
+        output_type='svg',
+        dpi=400
+    )
+
+    # Create minimal setup for all visualizations
+    u = ps.fields("u: float64[2D]", layout='fzyx')
+    yaml_path = files('pymatlib.data.alloys.SS304L').joinpath('SS304L_comprehensive.yaml')
+
+    # Run the appropriate code based on the target
+    with PyCallGraph(config=config, output=graphviz):
+        if target_name == "create_alloy_from_yaml":
+            mat = create_alloy_from_yaml(yaml_path, u.center())
+
+        elif target_name == "InterpolationArrayContainer":
+            mat = create_alloy_from_yaml(yaml_path, u.center())
+            arr_container = InterpolationArrayContainer.from_material("SS304L", mat)
+            with SourceFileGenerator() as sfg:
+                sfg.generate(arr_container)
+
+        elif target_name == "assignment_converter":
+            mat = create_alloy_from_yaml(yaml_path, u.center())
+            thermal_diffusivity = sp.Symbol("thermal_diffusivity")
+            subexp, subs = assignment_converter(mat.thermal_diffusivity.assignments)
+            subexp.append(ps.Assignment(thermal_diffusivity, mat.thermal_diffusivity.expr))
+
+    print(f"Visualization saved to {output_file}")
+
+# Generate each visualization
+create_visualization(
+    "create_alloy_from_yaml",
+    ['pymatlib.core.yaml_parser.*', 'create_alloy_from_yaml'],
+    'create_alloy_callgraph.svg'
+)
+
+create_visualization(
+    "InterpolationArrayContainer",
+    ['pymatlib.core.interpolators.*', 'InterpolationArrayContainer.*'],
+    'array_container_callgraph.svg'
+)
+
+create_visualization(
+    "assignment_converter",
+    ['pymatlib.core.assignment_converter.*', 'assignment_converter'],
+    'assignment_converter_callgraph.svg'
+)
+
+print("All visualizations completed.")
diff --git a/apps/yaml_parser_callgraph.py b/apps/yaml_parser_callgraph.py
new file mode 100644
index 0000000000000000000000000000000000000000..8d3107c6b364b06f7c214ba602f1e47591b698a2
--- /dev/null
+++ b/apps/yaml_parser_callgraph.py
@@ -0,0 +1,97 @@
+import os
+from pycallgraph2 import PyCallGraph, Config
+from pycallgraph2.output import GraphvizOutput
+from pycallgraph2.globbing_filter import GlobbingFilter
+
+# Define the path to the folder inside the apps directory
+apps_directory = '/local/ca00xebo/repos/pymatlib/apps'
+image_folder = os.path.join(apps_directory, 'callgraph_images')
+
+# Create the folder if it does not exist
+if not os.path.exists(image_folder):
+    os.makedirs(image_folder)
+
+# Create configuration to focus on your specific functions
+config = Config()
+config.trace_filter = GlobbingFilter(
+    include=[
+        'pymatlib.core.alloy.*',
+        'pymatlib.core.elements.*',
+        'pymatlib.core.yaml_parser.*',
+        'pymatlib.core.assignment_converter.*',
+        'pymatlib.core.interpolators.*',
+        'pymatlib.core.interpolators.interpolate_property.*',
+        'pymatlib.core.typedefs.*',
+        'pymatlib.core.models.*',
+        'pymatlib.core.data_handler.*',
+        'InterpolationArrayContainer.*',
+
+        'create_alloy_from_yaml',
+        'assignment_converter',
+        'interpolate_property',
+        'Assignment',
+        'ArrayTypes',
+        'PropertyTypes',
+        'MaterialProperty',
+        'density_by_thermal_expansion',
+        'thermal_diffusivity_by_heat_conductivity',
+        'energy_density_standard',
+        'energy_density_enthalpy_based',
+        'energy_density_total_enthalpy',
+        'read_data_from_file',
+        'wrapper',
+        'check_equidistant',
+        'check_strictly_increasing',
+        'ChemicalElement',
+        'interpolate_atomic_mass',
+        'interpolate_atomic_number',
+        'interpolate_temperature_boil',
+        'evalf',
+    ],
+    exclude=[
+        'pycallgraph2.*',
+        '*.append',  # Exclude common methods
+        '*.join',
+    ]
+)
+
+# Configure the output with the full path
+output_file = os.path.join(image_folder, 'yaml_parser_callgraph.svg')
+
+# Configure the output
+graphviz = GraphvizOutput(
+    output_file=output_file,
+    font_name='Verdana',
+    font_size=7,
+    group_stdlib=True,
+    output_type='svg',
+    dpi=1200
+)
+
+# Run the specific part of your code with call graph tracking
+with PyCallGraph(config=config, output=graphviz):
+    # Import necessary modules
+    import sympy as sp
+    import pystencils as ps
+    from importlib.resources import files
+    # from pystencilssfg import SourceFileGenerator
+    # from pymatlib.core.assignment_converter import assignment_converter
+    # from pymatlib.core.interpolators import InterpolationArrayContainer
+    from pymatlib.core.yaml_parser import create_alloy_from_yaml
+
+    u = ps.fields("u: float64[2D]", layout='fzyx')
+    yaml_path = files('pymatlib.data.alloys.SS304L').joinpath('SS304L_comprehensive.yaml')
+    mat = create_alloy_from_yaml(yaml_path, u.center())
+
+
+    '''with SourceFileGenerator() as sfg:
+        yaml_path = files('pymatlib.data.alloys.SS304L').joinpath('SS304L.yaml')
+        mat = create_alloy_from_yaml(yaml_path, u.center())
+        
+        arr_container = InterpolationArrayContainer.from_material("SS304L", mat)
+        sfg.generate(arr_container)
+
+        # Convert assignments to pystencils format
+        subexp, subs = assignment_converter(mat.thermal_diffusivity.assignments)
+        thermal_diffusivity = sp.Symbol("thermal_diffusivity")
+        subexp.append(ps.Assignment(thermal_diffusivity, mat.thermal_diffusivity.expr))'''
diff --git a/docs/explanation/design_philosophy.md b/docs/explanation/design_philosophy.md
new file mode 100644
index 0000000000000000000000000000000000000000..4383a20b1a7c706c8f1b76a576bafa2c0d719544
--- /dev/null
+++ b/docs/explanation/design_philosophy.md
@@ -0,0 +1,136 @@
+# Design Philosophy of pymatlib
+
+This document explains the core design principles, architectural decisions, and the rationale behind pymatlib's structure and implementation.
+
+## Core Principles
+
+pymatlib is built upon several core principles:
+
+- **Modularity**: Clearly separated components for ease of maintenance, testing, and extensibility.
+- **Flexibility**: Allow users to define material properties in various intuitive ways.
+- **Performance**: Leverage symbolic computation and optimized C++ code generation for high-performance simulations.
+- **Transparency and Reproducibility**: Clearly document material property definitions and computations to ensure reproducibility.
+
+## Layered Architecture
+
+pymatlib follows a layered architecture to separate concerns clearly:
+
+1. User Interface Layer (YAML Configuration)
+
+- Provides a simple, human-readable format for defining alloys and their properties.
+- Allows users to specify properties using multiple intuitive methods (constants, interpolation points, file-based data, computed properties).
+- Ensures clarity, readability, and ease of use
+
+2. Symbolic Representation Layer (SymPy)
+
+- Uses symbolic mathematics (via SymPy) internally to represent material properties.
+- Enables symbolic manipulation, simplification, and validation of property definitions.
+- Facilitates automatic computation of derived properties.
+
+3. Interpolation and Computation Layer (Python)
+
+- Implements robust interpolation methods (`interpolate_equidistant`, `interpolate_lookup`) for evaluating temperature-dependent properties.
+- Automatically analyzes input arrays (`prepare_interpolation_arrays`) to determine the optimal interpolation method based on data characteristics.
+- Provides symbolic manipulation capabilities through SymPy for computed properties.
+
+4. Code Generation Layer (C++)
+
+- Uses InterpolationArrayContainer to generate optimized C++ code for efficient energy-to-temperature conversions.
+- Automatically selects the best interpolation method (Binary Search or Double Lookup) based on data analysis results from Python.
+- Integrates seamlessly with pystencils and waLBerla for high-performance simulations.
+
+## Separation Between Python and C++ Components
+
+pymatlib separates responsibilities clearly between Python and C++ components:
+
+| Component                      | Responsibility                                                  | Implementation Language |
+|--------------------------------|--------------------------------------------------|----------|
+| YAML Configuration             | User-friendly material property definitions     | YAML     |
+| Symbolic Computation & Validation| Parsing YAML files, symbolic computations and validations (sympy) | Python   |
+| Interpolation Analysis           | Determining optimal interpolation method based on data characteristics (`prepare_interpolation_arrays`)       | Python   |
+| Code Generation                  | Generating optimized interpolation code (`InterpolationArrayContainer`) for high-performance simulations       | C++      |
+| Simulation Execution             | Running generated kernels within simulation frameworks (waLBerla/pystencils)   | C++      |
+
+This separation ensures:
+
+- Flexibility in defining materials through easily editable YAML files
+- Powerful symbolic manipulation capabilities in Python
+- High-performance numerical computations in C++
+
+## Why YAML?
+
+YAML was chosen as the primary configuration format because:
+
+- It is human-readable and easy to edit manually
+- It naturally supports nested structures required by complex material definitions
+- It integrates smoothly with Python's ecosystem via libraries like PyYAML
+- It allows referencing previously defined variables within the file (e.g., `solidus_temperature`, `liquidus_temperature`), reducing redundancy.
+
+## Integration with pystencils and waLBerla
+
+pymatlib integrates closely with [pystencils](https://pycodegen.pages.i10git.cs.fau.de/pystencils/) and [waLBerla](https://walberla.net/) through the following workflow:
+
+1. **Symbolic Definition**: Material properties are defined symbolically in pymatlib using YAML configurations.
+2. **Assignment Conversion**: The assignment_converter function converts pymatlib's symbolic assignments into pystencils-compatible assignments.
+3. **Code Generation**: pystencils generates optimized kernels from these assignments for numerical simulations.
+4. **Simulation execution**: Generated kernels are executed within waLBerla frameworks for large-scale parallel simulations.
+
+This integration allows pymatlib to leverage:
+
+- Symbolic mathematics from sympy via pystencils
+- Optimized stencil-based numerical kernels generated by pystencils-sfg
+- High-performance parallel computing capabilities provided by waLBerla
+
+## Automatic Method Selection for Interpolation
+
+A key design decision in pymatlib is automatic method selection for interpolation between energy density and temperature:
+
+1. **Analysis Phase (Python)**: 
+
+- The function prepare_interpolation_arrays() analyzes input arrays to determine if they're equidistant or not.
+- Based on this analysis, it selects either Binary Search or Double Lookup as the preferred interpolation method.
+
+2. **Code Generation Phase (C++)**:
+
+- The InterpolationArrayContainer class generates optimized C++ code that includes both interpolation methods (interpolateBS, interpolateDL) if applicable.
+- A wrapper method (interpolate) is automatically generated to select the best available method at runtime without user intervention.
+
+This ensures optimal performance without burdening users with manual selection decisions.
+
+## Extensibility
+
+pymatlib is designed with extensibility in mind:
+
+- Users can easily define new material properties or extend existing ones through YAML files without changing core code.
+- New computational models or interpolation methods can be added at the Python layer without affecting existing functionality.
+- The modular design allows easy integration with additional simulation frameworks beyond pystencils or waLBerla if needed.
+
+## Robustness and Error Handling
+
+pymatlib includes comprehensive validation checks at every step:
+
+### YAML Parser Validation
+
+- Ensures consistent units (SI units recommended).
+- Checks monotonicity of temperature-energy arrays.
+- Validates dependencies among computed properties.
+
+### Interpolation Validation
+
+The interpolation functions validate:
+
+- Array lengths match
+- Arrays contain sufficient elements
+- Arrays are strictly monotonic
+- Energy density increases consistently with temperature
+
+If any validation fails, clear error messages guide users toward correcting their configurations.
+
+## Performance Optimization Philosophy
+
+Performance-critical numerical operations are implemented in optimized C++ code generated automatically from Python definitions. This approach provides:
+
+1. **Ease of use**: Users define materials symbolically or numerically without worrying about low-level optimization details.
+2. **Automatic Optimization**: pymatlib automatically selects optimal algorithms (Double Lookup vs Binary Search) based on data characteristics without user intervention.
+3. **High Performance**: Generated kernels provide near-native performance suitable for large-scale simulations while maintaining flexibility in material definitions.
+
diff --git a/docs/explanation/interpolation_methods.md b/docs/explanation/interpolation_methods.md
new file mode 100644
index 0000000000000000000000000000000000000000..dbfb1c9cb8f10c23e2f4a967f88e2c9ae059e35a
--- /dev/null
+++ b/docs/explanation/interpolation_methods.md
@@ -0,0 +1,191 @@
+# Interpolation Methods in pymatlib
+
+This document explains the interpolation techniques used in pymatlib for energy-temperature conversion,
+including their internal workings, automatic method selection, and performance considerations.
+
+### Overview
+
+Interpolation is essential in pymatlib for converting between energy density and temperature values, particularly when modeling materials whose properties vary significantly with temperature. pymatlib provides two interpolation methods:
+
+- Binary Search Interpolation
+- Double Lookup Interpolation
+
+Additionally, pymatlib offers an intelligent wrapper method that automatically selects the optimal interpolation method based on data characteristics.
+
+## Binary Search Interpolation (`interpolateBS`)
+
+Binary Search Interpolation is one of the primary methods used in pymatlib for obtaining temperatures from energy density values.
+
+### How It Works
+
+1. The algorithm starts with a sorted array of energy density values and their corresponding temperature values
+2. When given an energy density value to convert to temperature:
+- It performs a binary search to find the position of the target value
+- It divides the search interval in half repeatedly until finding the closest match
+- Once the position is found, it performs linear interpolation between the two closest points
+
+### Implementation Details
+
+The binary search implementation handles edge cases gracefully:
+- If the target energy is below the minimum value, it returns the lowest temperature
+- If the target energy is above the maximum value, it returns the highest temperature
+- For values within the range, it calculates the interpolated temperature using:
+```text
+T = T[i] + (T[i+1] - T[i]) * (E_target - E[i]) / (E[i+1] - E[i])
+```
+
+As shown in the test code, this method is robust and handles a wide range of inputs, including extreme values and edge cases.
+
+### Characteristics
+- **Time Complexity**: O(log n) where n is the number of data points
+- **Advantages**: Works reliably with any monotonically increasing data
+- **Implementation**: Available through the `interpolateBS()` method in generated C++ code
+
+## Double Lookup Interpolation (`interpolateDL`)
+
+Double Lookup Interpolation is an optimized approach designed specifically for uniform or near-uniform data distributions.
+
+### How It Works
+
+1. During initialization (Python)
+- The algorithm checks if the temperature array is equidistant using `check_equidistant()`
+- It creates a uniform grid of energy values (`E_eq`) with carefully calculated spacing:
+```python
+delta_min = np.min(np.abs(np.diff(E_neq)))
+delta_E_eq = max(np.floor(delta_min * 0.95), 1.)
+E_eq = np.arange(E_neq[0], E_neq[-1] + delta_E_eq, delta_E_eq)
+```
+- It pre-computes an index mapping between the original energy array and the uniform grid:
+```python
+idx_map = np.searchsorted(E_neq, E_eq, side='right') - 1
+idx_map = np.clip(idx_map, 0, len(E_neq) - 2)
+```
+- It calculates the inverse of the energy grid spacing for fast index calculation:
+
+```python
+inv_delta_E_eq = 1.0 / (E_eq[1] - E_eq[0])
+```
+
+2. During lookup (C++):
+- It calculates the array index directly (O(1)) using the pre-computed inverse delta:
+```python
+idx = floor((E_target - E_eq[0]) * inv_delta_E_eq)
+```
+- It retrieves the pre-computed mapping to find the correct segment in the original array
+- It performs a simple linear interpolation between the two closest points
+
+### Characteristics
+- **Time Complexity**: O(1) - constant time regardless of array size using pre-computed mappings
+- **Best For**: Uniform temperature distributions
+- **Advantages**: Significantly faster (typically 2-4x) than binary search for uniform data
+- **Implementation**: Available through the `interpolateDL()` method in generated C++ code
+
+### Performance Optimization
+
+The double lookup method achieves O(1) complexity through several optimizations:
+- Pre-computing the index mapping eliminates the need for binary search
+- Using the inverse of the delta for multiplication instead of division
+- Constraining the index mapping to valid bounds during initialization
+
+## Automatic Method Selection Process (`interpolate`)
+
+```c++
+constexpr double energy_density = 16950000000.0;
+constexpr SimpleSteel alloy;
+const double temperature = alloy.interpolate(energy_density);
+```
+
+How Automatic Selection Works Internally
+
+The automatic method selection in pymatlib involves two key components working together:
+
+1. **Analysis Phase (Python)**: The prepare_interpolation_arrays() function analyzes the input temperature and energy density arrays to determine the most appropriate interpolation method:
+- It validates that both arrays are monotonic and energy increases with temperature
+- It checks if the temperature array is equidistant using check_equidistant()
+- Based on this analysis, it selects either "binary_search" or "double_lookup" as the method
+- It returns a dictionary containing the processed arrays and the selected method
+
+```python
+if is_equidistant:
+    E_eq, inv_delta_E_eq = E_eq_from_E_neq(E_bs)
+    idx_mapping = create_idx_mapping(E_bs, E_eq)
+    # Set method to "double_lookup"
+else:
+    # Set method to "binary_search"
+```
+
+2. **Code Generation Phase (C++)**: The InterpolationArrayContainer class uses this information to generate optimized C++ code:
+- It always includes the binary search method (interpolateBS)
+- If the temperature array is equidistant, it also includes the double lookup method (interpolateDL)
+- It adds an intelligent wrapper method interpolate() that automatically calls the preferred method:
+
+```c++
+// If double lookup is available, use it
+if (self.has_double_lookup):
+    interpolate() { return interpolate_double_lookup_cpp(E_target, *this); }
+// Otherwise, fall back to binary search
+else:
+    interpolate() { return interpolate_binary_search_cpp(E_target, *this); }
+```
+
+This two-step process ensures that:
+
+- The most efficient method is selected based on the data characteristics
+- Users can simply call `material.interpolate(energy_density)` without worrying about which technique to use
+
+This method:
+- Uses Double Lookup if the data is suitable (uniform or near-uniform)
+- Falls back to Binary Search for non-uniform data
+- Provides the best performance for your specific data structure without manual selection
+- Performance is optimized automatically without manual intervention
+
+## Performance Considerations
+
+Based on performance testing with 64³ cells:
+
+- **Binary Search**: Reliable but slower for large datasets
+- **Double Lookup**: Typically 2-4x faster than Binary Search for uniform data
+- **Edge Cases**: Both methods handle values outside the data range by clamping to the nearest endpoint
+
+The test results demonstrate that Double Lookup consistently outperforms Binary Search when the data is suitable, 
+making it the preferred method for uniform temperature distributions.
+
+## Implementation Details
+
+The interpolation methods are implemented in C++ for maximum performance:
+
+- The `InterpolationArrayContainer` class generates optimized C++ code with the interpolation arrays and methods
+- The generated code includes both interpolation methods and the automatic selector
+- The implementation handles edge cases gracefully, returning boundary values for out-of-range queries
+
+## Edge Case Handling
+
+Both interpolation methods include robust handling of edge cases:
+
+- **Out-of-Range Values**: Both methods clamp values outside the defined range to the nearest endpoint
+
+- **Extreme Values**: As shown in the stress tests, both methods handle extremely large and small values correctly
+
+- **Monotonicity**: The code validates that both arrays are monotonic and that energy increases with temperature
+
+The test file demonstrates this with specific test cases:
+
+```c++
+// Test with extremely large values
+constexpr double large_E = 1.0e20;
+const double result_large_bs = bs_tests.interpolateBS(large_E);
+const double result_large_dl = dl_tests.interpolateDL(large_E);
+
+// Test with extremely small values
+constexpr double small_E = 1.0e-20;
+const double result_small_bs = bs_tests.interpolateBS(small_E);
+const double result_small_dl = dl_tests.interpolateDL(small_E);
+```
+
+## When to Use Each Method
+
+- **Binary Search**: Use for general-purpose interpolation or when data points are irregularly spaced
+- **Double Lookup**: Use when data points are uniformly or nearly uniformly spaced
+- **Automatic Selection**: Use in most cases to get the best performance without manual selection
+
+For most applications, the automatic `interpolate()` method provides the best balance of performance and reliability.
diff --git a/docs/explanation/material_properties.md b/docs/explanation/material_properties.md
new file mode 100644
index 0000000000000000000000000000000000000000..868e583be6771d246f951e735c4561c9bc28e40e
--- /dev/null
+++ b/docs/explanation/material_properties.md
@@ -0,0 +1,175 @@
+# Material Properties in pymatlib
+
+This document explains the conceptual framework behind temperature-dependent material properties in pymatlib,
+how they are represented internally, and the mathematical models used for computed properties.
+
+## Conceptual Framework
+
+Material properties in pymatlib are designed around these key principles:
+
+1. **Temperature Dependence**: Most material properties vary with temperature, especially during phase transitions
+2. **Symbolic Representation**: Properties are represented as symbolic expressions for mathematical manipulation
+3. **Flexible Definition**: Properties can be defined through various methods (constants, data points, files, or computation)
+4. **Physical Consistency**: Computed properties follow established physical relationships
+
+## Internal Representation
+
+### MaterialProperty Class
+
+At the core of pymatlib's property system is the `MaterialProperty` class, which contains:
+
+- A symbolic expression (`expr`) representing the property
+- A list of assignments needed to evaluate the expression
+- Methods to evaluate the property at specific temperatures
+
+```python
+@dataclass
+class MaterialProperty:
+    expr: sp.Expr
+    assignments: List[Assignment] = field(default_factory=list)
+    
+    def evalf(self, symbol: sp.Symbol, temperature: Union[float, ArrayTypes]) -> Union[float, np.ndarray]:
+        # Evaluates the property at the given temperature
+```
+
+### Assignment Class
+
+The `Assignment` class represents intermediate calculations needed for property evaluations:
+
+```python
+@dataclass
+class Assignment:
+    lhs: sp.Symbol
+    rhs: Union[tuple, sp.Expr]
+    lhs_type: str
+```
+
+## Property Definition Methods
+
+pymatlib supports multiple ways to define material properties:
+
+1. Constant Values
+
+Properties that don't vary with temperature are defined as simple numeric values:
+
+```yaml
+thermal_expansion_coefficient: 16.3e-6
+```
+
+Internally, these are converted to constant symbolic expressions.
+
+2. Interpolated Values
+
+For properties that vary with temperature, pymatlib supports interpolation between data points:
+
+```yaml
+heat_conductivity:
+    key: [1200, 1800, 2200, 2400]  # Temperatures in Kelvin
+    val: [25, 30, 33, 35]          # Property values
+```
+
+Internally, these are represented as piecewise functions that perform linear interpolation between points.
+
+3. File-Based Properties
+   
+Properties can be loaded from external data files:
+
+```yaml
+density:
+    file: ./material_data.xlsx
+    temp_col: T (K)
+    prop_col: Density (kg/(m)^3)
+```
+
+The data is loaded and converted to an interpolated function similar to key-value pairs.
+
+4. Computed Properties
+
+Some properties can be derived from others using physical relationships:
+
+```yaml
+thermal_diffusivity: compute  # k/(ρ*cp)
+```
+
+## Computed Models
+
+pymatlib implements several physical models for computing properties:
+
+### Density by Thermal Expansion
+
+```text
+ρ(T) = ρ₀ / (1 + tec * (T - T₀))³
+```
+
+Where:
+- ρ₀ is the base density
+- Tâ‚€ is the base temperature
+- tec is the thermal expansion coefficient
+
+### Thermal Diffusivity
+
+```text
+α(T) = k(T) / (ρ(T) * cp(T))
+```
+
+Where:
+- k(T) is the thermal conductivity
+- ρ(T) is the density
+- cp(T) is the specific heat capacity
+
+### Energy Density
+
+pymatlib supports multiple models for energy density:
+
+1. **Standard Model**
+
+```text
+E(T) = ρ(T) * (cp(T) * T + L)
+```
+
+2. **Enthalpy-Based Model**
+
+```text
+E(T) = ρ(T) * (h(T) + L)
+```
+
+3. **Total Enthalpy Model**
+```text
+E(T) = ρ(T) * h(T)
+```
+
+Where:
+- ρ(T) is the density
+- cp(T) is the specific heat capacity
+- h(T) is the specific enthalpy
+- L is the latent heat of fusion
+
+## Interpolation Between Data Points
+
+For properties defined through key-value pairs or files, pymatlib performs linear interpolation between data points:
+
+1. For a temperature T between two known points T₁ and T₂:
+
+```text
+property(T) = property(T₁) + (property(T₂) - property(T₁)) * (T - T₁) / (T₂ - T₁)
+```
+
+2. For temperatures outside the defined range, the property value is clamped to the nearest endpoint.
+
+## Temperature Arrays for EnergyDensity
+
+When using computed energy density, you must specify a temperature array:
+
+```text
+energy_density_temperature_array: (300, 3000, 541)  # 541 points from 300K to 3000K
+```
+
+This array is used to pre-compute energy density values for efficient interpolation during simulations.
+
+### Best Practices
+
+1. **Use Consistent Units**: All properties should use SI units (m, s, kg, K, etc.)
+2. **Cover the Full Temperature Range**: Ensure properties are defined across the entire temperature range of your simulation
+3. **Add Extra Points Around Phase Transitions**: For accurate modeling, use more data points around phase transitions
+4. **Validate Against Experimental Data**: When possible, compare property values with experimental measurements
+5. **Document Property Sources**: Keep track of where property data comes from for reproducibility
diff --git a/docs/how-to/define_materials.md b/docs/how-to/define_materials.md
new file mode 100644
index 0000000000000000000000000000000000000000..a2943baf7a4be82543903fc79d62651277b2d835
--- /dev/null
+++ b/docs/how-to/define_materials.md
@@ -0,0 +1,193 @@
+# Defining Custom Material Properties
+
+This guide explains how to define custom material properties in pymatlib using different methods.
+
+## YAML Configuration Options
+
+pymatlib supports several ways to define material properties in YAML files, following SI units (m, s, kg, A, V, K, etc.).
+
+### 1. Constant Value
+
+For properties that don't vary with temperature:
+
+```yaml
+properties:
+    thermal_expansion_coefficient: 16.3e-6
+```
+
+### 2. Key-Value Pairs for Interpolation
+
+For properties that vary with temperature:
+
+```yaml
+properties:
+    # Using explicit temperature list
+    heat_conductivity:
+        key: [1200, 1800, 2200, 2400]  # Temperatures in Kelvin
+        val: [25, 30, 33, 35]  # Property values
+    
+    # Using references to defined temperatures
+    latent_heat_of_fusion:
+        key: [solidus_temperature, liquidus_temperature]
+        val: [171401, 0]
+    
+    # Using tuple for temperature generation
+    heat_capacity:
+        key: (1000, 200)  # Start at 1000K and increment by 200K for each value in val
+        # Generates: [1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800, 3000, 3200]
+        val: [580, 590, 600, 600, 600, 610, 620, 630, 660, 700, 750, 750]
+    
+    # Using tuple with negative increment
+    density:
+        key: (1735.00, -5)  # Start at 1735.00K and decrement by 5K for each value in val
+        # Generates: [1735.00, 1730.00, 1725.00, 1720.00, 1715.00, 1710.00, 1705.00, 1700.00, 1695.00, 1690.00]
+        val: [7037.470, 7060.150, 7088.800, 7110.460, 7127.680, 7141.620, 7156.800, 7172.590, 7184.010, 7192.780]
+```
+
+### 3. Loading from External Files
+
+For properties defined in spreadsheets:
+
+```yaml
+properties:
+    # Simple format (first column = temperature, second column = property)
+    heat_capacity: ./heat_capacity_data.txt
+    
+    # Advanced format (specify columns)
+    density:
+      file: ./304L_data.xlsx
+      temp_col: T (K)
+      prop_col: Density (kg/(m)^3)
+```
+
+Supported file formats include .txt (space/tab separated), .csv, and .xlsx.
+
+### 4. Energy density temperature arrays
+
+For properties that need to be evaluated at specific temperature points:
+
+```yaml
+properties:
+    # Using count (integer)
+    energy_density_temperature_array: (300, 3000, 541)  # 541 evenly spaced points
+    # OR
+    # Using step size (float)
+    energy_density_temperature_array: (300, 3000, 5.0)  # From 300K to 3000K in steps of 5K
+    # OR
+    # Descending order
+    energy_density_temperature_array: (3000, 300, -5.0)  # From 3000K to 300K in steps of -5K
+```
+
+### 5. Computed Properties
+
+For properties that can be derived from others:
+
+```yaml
+properties:
+    # Simple format for density
+    density: compute
+
+    # Simple format for thermal_diffusivity
+    thermal_diffusivity: compute # Will be calculated from k/(ρ*cp)
+
+    # Simple format for energy_density
+    energy_density: compute  # Uses default model: ρ(T) * (cp(T) * T + L)
+    # OR
+    # Advanced format with explicit model selection for energy_density
+    energy_density:
+        compute: enthalpy_based  # Uses model: ρ(T) * (h(T) + L)
+    # OR
+    energy_density:
+        compute: total_enthalpy  # Uses model: ρ(T) * h(T)
+```
+
+### The equations used for computed properties are:
+- Density by thermal expansion: ρ(T) = ρ₀ / (1 + tec * (T - T₀))³
+- - Required: base_temperature, base_density, thermal_expansion_coefficient
+
+- Thermal diffusivity: α(T) = k(T) / (ρ(T) * cp(T))
+- - Required: heat_conductivity, density, heat_capacity
+
+- Energy density (standard model): ρ(T) * (cp(T) * T + L)
+- - Required: density, heat_capacity, latent_heat_of_fusion
+
+- Energy density (enthalpy_based): ρ(T) * (h(T) + L)
+- - Required: density, specific_enthalpy, latent_heat_of_fusion
+
+- Energy density (total_enthalpy): ρ(T) * h(T)
+- - Required: density, specific_enthalpy
+
+## Creating a Complete Alloy Definition
+
+Here's a complete example for stainless steel [SS304L](https://i10git.cs.fau.de/rahil.doshi/pymatlib/-/blob/master/src/pymatlib/data/alloys/SS304L/SS304L.yaml?ref_type=heads):
+
+```yaml
+name: SS304L
+
+composition:
+    C: 0.0002
+    Si: 0.0041
+    Mn: 0.016
+    P: 0.00028
+    S: 0.00002
+    Cr: 0.1909
+    N: 0.00095
+    Ni: 0.0806
+    Fe: 0.70695
+
+solidus_temperature: 1605
+liquidus_temperature: 1735
+
+properties:
+    energy_density:
+      compute: total_enthalpy
+    energy_density_temperature_array: (300, 3000, 541)
+
+    base_temperature: 2273.
+    base_density: 6.591878918e3
+
+    density:
+      file: ./304L_data.xlsx
+      temp_col: T (K)
+      prop_col: Density (kg/(m)^3)
+
+    heat_conductivity:
+      file: ./304L_data.xlsx
+      temp_col: T (K)
+      prop_col: Thermal conductivity (W/(m*K))
+
+      heat_capacity:
+        file: ./304L_data.xlsx
+        temp_col: T (K)
+        prop_col: Specific heat (J/(Kg K))
+
+      thermal_expansion_coefficient: 16.3e-6
+    
+      specific_enthalpy:
+        file: ./304L_data.xlsx
+        temp_col: T (K)
+        prop_col: Enthalpy (J/kg)
+    
+      latent_heat_of_fusion:
+        key: [solidus_temperature, liquidus_temperature]
+        val: [171401, 0]
+    
+      thermal_diffusivity: compute
+```
+
+## Best Practices
+
+- Use consistent units throughout your definitions
+- Document the expected units for each property
+- For temperature-dependent properties, cover the full range of temperatures you expect in your simulation
+- Validate your property data against experimental values when possible
+- Use computed properties only when the relationship is well-established
+- All numerical values must use period (.) as decimal separator, not comma
+- Interpolation between data points is performed automatically for file-based and key-val properties
+
+## Important Notes
+
+- If a specific property is defined in multiple ways or multiple times, the parser will throw an error
+- If required dependencies for computed properties are missing, an error will be raised
+- Properties will be computed in the correct order regardless of their position in the file
+- To retrieve temperature from energy_density, use the default "interpolate" method from within the generated class from InterpolationArrayContainer named after the alloy
diff --git a/docs/how-to/energy_temperature_conversion.md b/docs/how-to/energy_temperature_conversion.md
new file mode 100644
index 0000000000000000000000000000000000000000..4d96e2cd147c6c6d05a70dfe07da6af3062b8eba
--- /dev/null
+++ b/docs/how-to/energy_temperature_conversion.md
@@ -0,0 +1,153 @@
+# Converting Between Energy Density and Temperature
+
+This guide explains how to perform bilateral conversions between energy density and temperature in pymatlib.
+
+## Why Energy-Temperature Conversion Matters
+
+In many material simulations, particularly those involving heat transfer and phase changes, you need to convert between:
+
+- **Temperature**: The conventional measure of thermal state
+- **Energy Density**: The amount of thermal energy per unit volume
+
+This conversion is essential because:
+- Energy is conserved in physical processes
+- Phase transitions involve latent heat where temperature remains constant
+- Many numerical methods work better with energy as the primary variable
+
+## Basic Conversion Process
+
+### 1. Generate the Interpolation Container
+
+First, create an interpolation container that stores the energy-temperature relationship:
+
+```python
+import pystencils as ps
+from pystencilssfg import SourceFileGenerator
+from pymatlib.core.yaml_parser import create_alloy_from_yaml
+from pymatlib.core.interpolators import InterpolationArrayContainer
+
+with SourceFileGenerator() as sfg:
+u = ps.fields("u: float64[2D]", layout='fzyx')
+
+# Create an alloy
+alloy = create_alloy_from_yaml("path/to/alloy.yaml", u.center())
+
+# Generate the interpolation container
+arr_container = InterpolationArrayContainer.from_material("SS304L", alloy)
+sfg.generate(arr_container)
+```
+
+This generates C++ code with the `InterpolationArrayContainer` class that contains:
+- Temperature array
+- Energy density array
+- Methods for interpolation
+
+### 2. Using the Generated Code
+
+In your C++ application, you can use the generated code:
+
+```c++
+// Energy to temperature conversion using binary search
+double energy_density = 16950000000.0;  // J/m³
+SS304L material;
+double temp = material.interpolateBS(energy_density);
+
+// Energy to temperature conversion using double lookup
+double temp2 = material.interpolateDL(energy_density);
+
+// Using the automatic method selection
+double temp3 = material.interpolate(energy_density);
+```
+
+Note that the temperature to energy density conversion is handled in Python using the evalf method:
+
+```python
+import sympy as sp
+
+# Create symbolic temperature variable
+T = sp.Symbol('T')
+
+# Temperature to energy conversion in Python
+temperature = 1500.0  # Kelvin
+energy = alloy.energy_density.evalf(T, temperature)
+
+```
+
+## Interpolation Methods
+
+pymatlib provides two interpolation methods:
+
+### Binary Search Interpolation
+
+```c++
+double temp = material.interpolateBS(energy_density);
+```
+
+- Best for non-uniform temperature distributions
+- O(log n) lookup complexity
+- Robust for any monotonically increasing data
+
+### Double Lookup Interpolation
+
+```c++
+double temp = material.interpolateDL(energy_density);
+```
+
+- Optimized for uniform temperature distributions
+- O(1) lookup complexity
+- Faster but requires pre-processing
+
+### Automatic Method Selection
+
+```c++
+double temp = material.interpolate(energy_density);
+```
+
+## Custom Interpolation Arrays
+
+You can create custom interpolation containers for specific temperature ranges:
+
+```python
+import numpy as np
+from pymatlib.core.interpolators import InterpolationArrayContainer
+
+# Create custom temperature and energy arrays
+T_array = np.linspace(300, 3000, 5)
+E_array = np.array([...]) # Your energy values
+
+# Create a custom container
+custom_container = InterpolationArrayContainer("CustomMaterial", T_array, E_array)
+sfg.generate(custom_container)
+```
+
+## Performance Considerations
+
+- **Binary Search**: Use for general-purpose interpolation
+- **Double Lookup**: Use for uniform temperature distributions
+- **Array Size**: Balance between accuracy and memory usage
+- **Density**: Add more points around phase transitions for accuracy
+
+## Complete Example
+
+Here's a complete example showing both methods:
+
+```python
+import numpy as np
+from pystencilssfg import SourceFileGenerator
+from pymatlib.core.interpolators import InterpolationArrayContainer
+
+with SourceFileGenerator() as sfg:
+    # Create temperature and energy arrays
+    T_bs = np.array([3243.15, 3248.15, 3258.15, 3278.15], dtype=np.float64)
+    E_bs = np.array([1.68e10, 1.69e10, 1.70e10, 1.71e10], dtype=np.float64)
+
+    # Binary search container
+    binary_search_container = InterpolationArrayContainer("BinarySearchTests", T_bs, E_bs)
+    sfg.generate(binary_search_container)
+    
+    # Double lookup container
+    T_eq = np.array([3243.15, 3253.15, 3263.15, 3273.15], dtype=np.float64)
+    E_neq = np.array([1.68e10, 1.69e10, 1.70e10, 1.71e10], dtype=np.float64)
+    double_lookup_container = InterpolationArrayContainer("DoubleLookupTests", T_eq, E_neq)
+    sfg.generate(double_lookup_container)
+```
diff --git a/docs/reference/api/alloy.md b/docs/reference/api/alloy.md
new file mode 100644
index 0000000000000000000000000000000000000000..f9a04b2663e296ef1346fb723cb1c46a2b30f85c
--- /dev/null
+++ b/docs/reference/api/alloy.md
@@ -0,0 +1,14 @@
+## API Reference
+
+### Core Classes
+
+#### Alloy
+
+A dataclass representing a material alloy.
+
+**Properties:**
+- `elements`: List of chemical elements in the alloy
+- `composition`: Dictionary mapping element symbols to their weight fractions
+- `temperature_solidus`: Solidus temperature (K)
+- `temperature_liquidus`: Liquidus temperature (K)
+- `properties`: Dictionary of material properties
diff --git a/docs/reference/api/interpolators.md b/docs/reference/api/interpolators.md
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/docs/reference/api/yaml_parser.md b/docs/reference/api/yaml_parser.md
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/docs/reference/yaml_schema.md b/docs/reference/yaml_schema.md
new file mode 100644
index 0000000000000000000000000000000000000000..3dfe164666e1aced550a21f73742bd686e167d90
--- /dev/null
+++ b/docs/reference/yaml_schema.md
@@ -0,0 +1,175 @@
+# YAML Schema for Material Definition
+
+This document defines the schema for material definition YAML files in pymatlib.
+
+## Schema Overview
+
+A valid material definition must include:
+- `name`: String identifier for the material
+- `composition`: Map of element symbols to their mass fractions
+- `solidus_temperature`: Numeric value in Kelvin
+- `liquidus_temperature`: Numeric value in Kelvin
+- `properties`: Map of property names to their definitions
+
+## Top-Level Structure
+
+```yaml
+name: <string> # Required: Material name
+composition: # Required: Chemical composition
+<element>: <mass_fraction> # At least one element required
+solidus_temperature: <float> # Required: Solidus temperature in K
+liquidus_temperature: <float> # Required: Liquidus temperature in K
+properties: # Required: Material properties
+<property_name>: <definition> # At least one property required
+```
+
+## Property Definition Types
+
+Properties can be defined in four different ways:
+
+### 1. Constant Value
+
+For properties that don't vary with temperature:
+
+```yaml
+properties:
+    thermal_expansion_coefficient: 16.3e-6 # Single numeric value
+```
+
+### 2. File-Based Properties
+
+#### 2.1 Simple Format
+
+```yaml
+properties:
+    density: ./density_temperature.txt # Path to file with two columns
+```
+
+The simple format assigns the first column to temperature data (K) and the second column to the corresponding property values.
+
+#### 2.2 Advanced Format
+
+```yaml
+properties:
+    density:
+        file: ./path/to/file.xlsx
+        temp_col: Temperature # Name of the temperature column
+        prop_col: Property # Name of the property column
+```
+
+Advanced format is required when you have a file with multiple columns.
+Supported file formats: .txt (space/tab separated), .csv, and .xlsx.
+
+### 3. Key-Value Pairs
+
+For properties defined at specific temperature points:
+
+```yaml
+properties:
+    density:
+        key: [1605, 1735] # Temperature values in K
+        val: [7262.34, 7037.47] # Corresponding property values
+```
+
+Three ways to specify temperature points:
+
+#### 3.1 Explicit List
+
+```yaml
+key: [1735.00, 1730.00, 1720.00, 1715.00] # Explicit temperature list
+val: [7037.470, 7060.150, 7110.460, 7127.680] # Corresponding values
+```
+
+#### 3.2 Reference to Defined Temperatures
+
+```yaml
+key: [solidus_temperature, liquidus_temperature] # References
+val: [7262.34, 7037.47] # Corresponding values
+```
+
+#### 3.3 Tuple with Start and Increment
+
+```yaml
+key: (1735.00, -5) # Start at 1735.00K and decrement by 5K
+val: [7037.470, 7060.150, 7088.800, 7110.460, 7127.680]
+```
+
+When using a tuple for key, the generated temperature points will be:
+`[start, start+increment, start+2*increment, ...]` until matching the length of val.
+
+### 4. Computed Properties
+
+#### 4.1 Simple Format
+
+```yaml
+properties:
+    density: compute
+    thermal_diffusivity: compute
+    energy_density: compute
+```
+
+Simple format uses the default model to compute the property.
+
+#### 4.2 Advanced Format
+
+```yaml
+properties:
+    energy_density:
+        compute: enthalpy_based # Specific computation model
+```
+
+#### 4.3 Energy Density Temperature Array
+
+When energy_density is computed, you must specify the temperature array:
+
+```yaml
+properties:
+    energy_density: compute
+    energy_density_temperature_array: (300, 3000, 541) # 541 points
+```
+
+The third parameter can be:
+- An integer: Total number of points to generate
+- A float: Temperature increment/decrement between points
+
+## Computation Models and Required Properties
+
+### Density (by thermal expansion)
+- **Equation**: ρ(T) = ρ₀ / (1 + tec * (T - T₀))³
+- **Required properties**: base_temperature, base_density, thermal_expansion_coefficient
+
+### Thermal Diffusivity
+- **Equation**: α(T) = k(T) / (ρ(T) * cp(T))
+- **Required properties**: heat_conductivity, density, heat_capacity
+
+### Energy Density (standard model)
+- **Equation**: ρ(T) * (cp(T) * T + L)
+- **Required properties**: density, heat_capacity, latent_heat_of_fusion
+
+### Energy Density (enthalpy_based model)
+- **Equation**: ρ(T) * (h(T) + L)
+- **Required properties**: density, specific_enthalpy, latent_heat_of_fusion
+
+### Energy Density (total_enthalpy model)
+- **Equation**: ρ(T) * h(T)
+- **Required properties**: density, specific_enthalpy
+
+## Validation Rules
+
+1. All required top-level fields must be present
+2. Composition fractions must sum to approximately 1.0
+3. Liquidus temperature must be greater than or equal to solidus temperature
+4. Properties cannot be defined in multiple ways or multiple times
+5. Required dependencies for computed properties must be present
+6. Temperature arrays must be monotonic
+7. Energy density arrays must be monotonic with respect to temperature
+8. File paths must be valid and files must exist
+9. For key-value pairs, key and val must have the same length
+10. When using tuple notation for temperature arrays, the increment must be non-zero
+
+## Important Notes
+
+1. All numerical values must use period (.) as decimal separator, not comma
+2. Interpolation between data points is performed automatically for file-based and key-val properties
+3. Properties will be computed in the correct order regardless of their position in the file
+4. To retrieve temperature from energy_density, use the default "interpolate" method from within the generated class
diff --git a/docs/tutorials/first_simulation.md b/docs/tutorials/first_simulation.md
new file mode 100644
index 0000000000000000000000000000000000000000..2e02004823f0d2474e1d408f32dc45f2945c3b64
--- /dev/null
+++ b/docs/tutorials/first_simulation.md
@@ -0,0 +1,212 @@
+# Creating Your First Material Simulation
+
+This tutorial will guide you through creating a basic heat equation simulation using [pymatlib](https://i10git.cs.fau.de/rahil.doshi/pymatlib) and [pystencils](https://pycodegen.pages.i10git.cs.fau.de/pystencils/).
+It builds upon the existing [waLBerla tutorial for code generation](https://walberla.net/doxygen/tutorial_codegen01.html), adding material property handling with pymatlib.
+
+## Prerequisites
+
+Before starting, ensure you have:
+- Completed the [Getting Started](getting_started.md) tutorial
+- Installed pystencils and [pystencilssfg](https://pycodegen.pages.i10git.cs.fau.de/pystencils-sfg/)
+- Basic understanding of heat transfer and the heat equation
+- Created the `simple_steel.yaml` file from the [Getting Started](getting_started.md) tutorial
+
+## Overview
+
+We'll create a 2D heat equation simulation with temperature-dependent material properties.
+The main enhancement compared to the original waLBerla tutorial is that we'll use pymatlib to handle material properties that vary with temperature.
+
+The steps are:
+
+1. Define a temperature field
+2. Create an alloy with temperature-dependent properties
+3. Set up the heat equation with material properties
+4. Generate code for the simulation
+5. Run the simulation
+
+## Step 1: Define the Temperature Field
+
+First, we'll create a temperature field using pystencils:
+
+```python
+import pystencils as ps
+from pystencilssfg import SourceFileGenerator
+
+with SourceFileGenerator() as sfg:
+    data_type = "float64"
+
+    # Define temperature fields and output field for thermal diffusivity
+    u, u_tmp = ps.fields(f"u, u_tmp: {data_type}[2D]", layout='fzyx')
+    thermal_diffusivity_out = ps.fields(f"thermal_diffusivity_out: {data_type}[2D]", layout='fzyx')
+```
+
+## Step 2: Set Up the Heat Equation
+
+Now we'll set up the heat equation with temperature-dependent material properties:
+
+```python
+import sympy as sp
+
+# Create symbolic variables for the equation
+dx = sp.Symbol("dx")
+dt = sp.Symbol("dt")
+thermal_diffusivity = sp.Symbol("thermal_diffusivity")
+
+# Define the heat equation using finite differences
+heat_pde = ps.fd.transient(u) - thermal_diffusivity * (ps.fd.diff(u, 0, 0) + ps.fd.diff(u, 1, 1))
+
+# Discretize the PDE
+discretize = ps.fd.Discretization2ndOrder(dx=dx, dt=dt)
+heat_pde_discretized = discretize(heat_pde)
+heat_pde_discretized = heat_pde_discretized.args[1] + heat_pde_discretized.args[0].simplify()
+```
+
+## Step 3: Create an Alloy
+
+This is where pymatlib enhances the original tutorial.
+We'll load the alloy from a YAML file:
+
+```python
+from pymatlib.core.yaml_parser import create_alloy_from_yaml
+
+# Load the SimpleSteel alloy definition we created earlier
+simple_steel_alloy = create_alloy_from_yaml("path/to/simple_steel.yaml", u.center())
+```
+
+The second parameter `u.center()` links the alloy to the temperature field, making material properties dependent on the local temperature.
+
+## Step 4: Convert Material Property Assignments
+
+We need to convert the material property assignments to a format pystencils can understand:
+
+```python
+from pymatlib.core.assignment_converter import assignment_converter
+
+# Access the thermal diffusivity property directly from the material
+# The property is already defined in the YAML file or computed automatically
+
+# Convert material property assignments to pystencils format
+subexp, subs = assignment_converter(simple_steel_alloy.thermal_diffusivity.assignments)
+
+# Add the thermal diffusivity expression to subexpressions
+subexp.append(ps.Assignment(thermal_diffusivity, simple_steel_alloy.thermal_diffusivity.expr))
+```
+
+The `assignment_converter` function transforms pymatlib's internal representation of material properties into pystencils assignments. 
+It handles type conversions and creates properly typed symbols for the code generation.
+
+## Step 5: Generate Code for the Simulation
+
+Finally, we'll create the assignment collection and generate optimized C++ code for the simulation:
+
+```python
+from sfg_walberla import Sweep
+from pymatlib.core.interpolators import InterpolationArrayContainer
+
+# Create assignment collection with subexpressions and main assignments
+ac = ps.AssignmentCollection(
+    subexpressions=subexp,  # Include the subexpressions from pymatlib
+    main_assignments=[
+        ps.Assignment(u_tmp.center(), heat_pde_discretized),
+        ps.Assignment(thermal_diffusivity_out.center(), thermal_diffusivity)
+    ])
+
+# Generate the sweep
+sweep = Sweep("HeatEquationKernelWithMaterial", ac)
+sfg.generate(sweep)
+
+# Create the container for energy-temperature conversion
+# The name "SimpleSteel" is just an identifier for the generated class
+arr_container = InterpolationArrayContainer.from_material("SimpleSteel", simple_steel_alloy)
+sfg.generate(arr_container)
+```
+
+## Step 6: Create the Interpolation Container
+
+For energy-temperature conversion, create an interpolation container:
+
+```python
+from pymatlib.core.interpolators import InterpolationArrayContainer
+
+# Create the container for energy-temperature conversion
+arr_container = InterpolationArrayContainer.from_material("SS304L", alloy)
+sfg.generate(arr_container)
+```
+
+## Complete Example
+
+Here's the complete example:
+
+```python
+import sympy as sp
+import pystencils as ps
+from pystencilssfg import SourceFileGenerator
+from sfg_walberla import Sweep
+from pymatlib.core.assignment_converter import assignment_converter
+from pymatlib.core.interpolators import InterpolationArrayContainer
+from pymatlib.core.yaml_parser import create_alloy_from_yaml
+
+with SourceFileGenerator() as sfg:
+    data_type = "float64"
+
+    # Define fields
+    u, u_tmp = ps.fields(f"u, u_tmp: {data_type}[2D]", layout='fzyx')
+    thermal_diffusivity = sp.Symbol("thermal_diffusivity")
+    thermal_diffusivity_out = ps.fields(f"thermal_diffusivity_out: {data_type}[2D]", layout='fzyx')
+    dx, dt = sp.Symbol("dx"), sp.Symbol("dt")
+
+    # Define heat equation
+    heat_pde = ps.fd.transient(u) - thermal_diffusivity * (ps.fd.diff(u, 0, 0) + ps.fd.diff(u, 1, 1))
+
+    # Discretize the PDE
+    discretize = ps.fd.Discretization2ndOrder(dx=dx, dt=dt)
+    heat_pde_discretized = discretize(heat_pde)
+    heat_pde_discretized = heat_pde_discretized.args[1] + heat_pde_discretized.args[0].simplify()
+
+    # Create alloy with temperature-dependent properties
+    mat = create_alloy_from_yaml("simple_steel.yaml", u.center())
+
+    # Convert material property assignments to pystencils format
+    subexp, subs = assignment_converter(mat.thermal_diffusivity.assignments)
+    subexp.append(ps.Assignment(thermal_diffusivity, mat.thermal_diffusivity.expr))
+
+    # Create assignment collection with the converted subexpressions
+    ac = ps.AssignmentCollection(
+        subexpressions=subexp,
+        main_assignments=[
+            ps.Assignment(u_tmp.center(), heat_pde_discretized),
+            ps.Assignment(thermal_diffusivity_out.center(), thermal_diffusivity)
+        ])
+
+    # Generate the sweep
+    sweep = Sweep("HeatEquationKernelWithMaterial", ac)
+    sfg.generate(sweep)
+
+    # Generate interpolation container for energy-temperature conversion
+    arr_container = InterpolationArrayContainer.from_material("SimpleSteel", mat)
+    sfg.generate(arr_container)
+```
+
+## Understanding the Assignment Converter
+
+The `assignment_converter` function is a key component of pymatlib that bridges the gap between symbolic material property representations and pystencils code generation. It:
+
+1. Takes a list of `Assignment` objects from pymatlib
+2. Converts them to pystencils-compatible assignments with proper typing
+3. Returns both the converted assignments and a mapping of symbols
+
+This allows material properties defined in YAML files to be seamlessly integrated into pystencils code generation, enabling temperature-dependent properties in simulations.
+
+The main ways pymatlib enhances the simulation are:
+
+- Material property handling: Properties are defined in YAML and accessed via the material object
+- Assignment conversion: The assignment_converter transforms material property assignments to pystencils format
+- Energy-temperature conversion: The InterpolationArrayContainer enables efficient conversion between energy density and temperature
+
+## Next Steps
+
+Now that you've created your first simulation with temperature-dependent material properties, you can:
+- Learn about [energy-temperature conversion](../how-to/energy_temperature_conversion.md)
+- Explore more complex [material properties](../explanation/material_properties.md)
+- Understand the [API reference](../reference/api/alloy.md) for advanced usage
+- Check the original [waLBerla tutorial](https://walberla.net/doxygen/tutorial_codegen01.html) for details on running the simulation
diff --git a/docs/tutorials/getting_started.md b/docs/tutorials/getting_started.md
new file mode 100644
index 0000000000000000000000000000000000000000..2cb22ab18140c7ad9bf0606821350c8abb6f76bd
--- /dev/null
+++ b/docs/tutorials/getting_started.md
@@ -0,0 +1,99 @@
+# Getting Started with pymatlib
+
+This tutorial will guide you through the basics of using pymatlib to model material properties for simulations.
+
+## Prerequisites
+
+Before starting, ensure you have:
+
+- Python 3.10 or newer
+- Basic knowledge of material properties
+- Basic familiarity with Python
+
+## Installation
+
+Install pymatlib using pip:
+
+```bash
+pip install "git+https://i10git.cs.fau.de/rahil.doshi/pymatlib.git"
+```
+
+
+For development, clone the repository and install in development mode:
+
+```bash
+git clone https://i10git.cs.fau.de/rahil.doshi/pymatlib.git
+cd pymatlib
+pip install -e .
+```
+
+## Basic Concepts
+
+pymatlib organizes material data around a few key concepts:
+
+1. **Alloys**: Compositions of multiple elements with specific properties
+2. **Material Properties**: Physical characteristics that can vary with temperature
+3. **Interpolation**: Methods to estimate property values between known data points
+
+## Your First Alloy
+
+Let's create a simple alloy definition:
+
+1. Create a file named `simple_steel.yaml` with the following content:
+```python
+name: SimpleSteel
+
+composition:
+    Fe: 0.98
+    C: 0.02
+
+solidus_temperature: 1450
+liquidus_temperature: 1520
+
+properties:
+    density:
+        key:[300, 800, 1300, 1800]
+        val:[7850, 7800, 7750, 7700]
+
+    heat_conductivity:
+        key: [300, 800, 1300, 1800]
+        val: [18.5, 25, 32, 36.5]
+
+    heat_capacity:
+        key: [300, 800, 1300, 1800]
+        val: [450, 500, 550, 600]
+
+    thermal_diffusivity: compute    
+```
+
+2. Load the alloy in Python:
+```python
+from pymatlib.core.yaml_parser import create_alloy_from_yaml
+
+# Load the alloy definition
+alloy = create_alloy_from_yaml("simple_steel.yaml")
+
+# Print basic information
+print(f"Alloy: {alloy.name}")
+print(f"Composition: {alloy.composition}")
+print(f"Temperature range: {alloy.temperature_solidus}K - {alloy.temperature_liquidus}K")
+
+# Get property values at specific temperatures
+temp = 500 # Kelvin
+density = alloy.get_property("density", temp)
+conductivity = alloy.get_property("heat_conductivity", temp)
+capacity = alloy.get_property("heat_capacity", temp)
+
+print(f"At {temp}K:")
+print(f" Density: {density} kg/m³")
+print(f" Thermal Conductivity: {conductivity} W/(m·K)")
+print(f" Heat Capacity: {capacity} J/(kg·K)")
+```
+
+## Next Steps
+
+Now that you've created your first alloy, you can:
+
+- Learn how to [create your first simulation](first_simulation.md)
+- Explore [defining custom material properties](../how-to/define_materials.md)
+- Understand [interpolation methods](../explanation/interpolation_methods.md)
diff --git a/pyproject.toml b/pyproject.toml
index 08ca2ba2be93c4d4486dc28d3b2ed2ff02ef0e67..fcf75e71bad7826e53e22302ea485e8e48fe10da 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,7 @@
 [project]
 name = "pymatlib"
 version = "0.1.0"
-description = "A Python based material library"
+description = "Python based material library"
 authors = [
     {name = "Rahil Doshi", email = "rahil.doshi@fau.de"},
 ]
diff --git a/src/pymatlib/core/interpolators.py b/src/pymatlib/core/interpolators.py
index fc3a06de930daa65015bef3c79120cab994762fc..edb64db1fc74995180f35948d7c859737f249f1a 100644
--- a/src/pymatlib/core/interpolators.py
+++ b/src/pymatlib/core/interpolators.py
@@ -13,7 +13,54 @@ COUNT = 0
 
 
 class InterpolationArrayContainer(CustomGenerator):
+    """Container for energy-temperature interpolation arrays and methods.
+
+    This class stores temperature and energy density arrays and generates C++ code
+    for efficient bilateral conversion between these properties. It supports both
+    binary search interpolation (O(log n)) and double lookup interpolation (O(1))
+    with automatic method selection based on data characteristics.
+
+    Attributes:
+        name (str): Name for the generated C++ class.
+        T_array (np.ndarray): Array of temperature values (must be monotonically increasing).
+        E_array (np.ndarray): Array of energy density values corresponding to T_array.
+        method (str): Interpolation method selected ("binary_search" or "double_lookup").
+        T_bs (np.ndarray): Temperature array prepared for binary search.
+        E_bs (np.ndarray): Energy array prepared for binary search.
+        has_double_lookup (bool): Whether double lookup interpolation is available.
+
+    If has_double_lookup is True, the following attributes are also available:
+        T_eq (np.ndarray): Equidistant temperature array for double lookup.
+        E_neq (np.ndarray): Non-equidistant energy array for double lookup.
+        E_eq (np.ndarray): Equidistant energy array for double lookup.
+        inv_delta_E_eq (float): Inverse of the energy step size for double lookup.
+        idx_map (np.ndarray): Index mapping array for double lookup.
+
+    Examples:
+        >>> import numpy as np
+        >>> from pystencils_sfg import SfgComposer
+        >>> from pymatlib.core.interpolators import InterpolationArrayContainer
+        >>>
+        >>> # Create temperature and energy arrays
+        >>> T = np.array([300, 600, 900, 1200], dtype=np.float64)
+        >>> E = np.array([1e9, 2e9, 3e9, 4e9], dtype=np.float64)
+        >>>
+        >>> # Create and generate the container
+        >>> with SfgComposer() as sfg:
+        >>>     container = InterpolationArrayContainer("MyMaterial", T, E)
+        >>>     sfg.generate(container)
+    """
     def __init__(self, name: str, temperature_array: np.ndarray, energy_density_array: np.ndarray):
+        """Initialize the interpolation container.
+        Args:
+            name (str): Name for the generated C++ class.
+            temperature_array (np.ndarray): Array of temperature values (K).
+                Must be monotonically increasing.
+            energy_density_array (np.ndarray): Array of energy density values (J/m³)
+                corresponding to temperature_array.
+        Raises:
+            ValueError: If arrays are empty, have different lengths, or are not monotonic.
+        """
         super().__init__()
         self.name = name
         self.T_array = temperature_array
@@ -40,19 +87,29 @@ class InterpolationArrayContainer(CustomGenerator):
 
     @classmethod
     def from_material(cls, name: str, material):
+        """Create an interpolation container from a material object.
+        Args:
+            name (str): Name for the generated C++ class.
+            material: Material object with temperature and energy properties.
+                Must have energy_density_temperature_array and energy_density_array attributes.
+        Returns:
+            InterpolationArrayContainer: Container with arrays for interpolation.
+        """
         return cls(name, material.energy_density_temperature_array, material.energy_density_array)
 
-    def generate(self, sfg: SfgComposer):
-        sfg.include("<array>")
-        sfg.include("pymatlib_interpolators/interpolate_binary_search_cpp.h")
-
-        # Binary search arrays (always included)
+    def _generate_binary_search(self, sfg: SfgComposer):
+        """Generate code for binary search interpolation.
+        Args:
+            sfg (SfgComposer): Source file generator composer.
+        Returns:
+            list: List of public members for the C++ class.
+        """
         T_bs_arr_values = ", ".join(str(v) for v in self.T_bs)
         E_bs_arr_values = ", ".join(str(v) for v in self.E_bs)
 
         E_target = sfg.var("E_target", "double")
 
-        public_members = [
+        return [
             # Binary search arrays
             f"static constexpr std::array< double, {self.T_bs.shape[0]} > T_bs {{ {T_bs_arr_values} }}; \n"
             f"static constexpr std::array< double, {self.E_bs.shape[0]} > E_bs {{ {E_bs_arr_values} }}; \n",
@@ -63,30 +120,56 @@ class InterpolationArrayContainer(CustomGenerator):
             )
         ]
 
+    def _generate_double_lookup(self, sfg: SfgComposer):
+        """Generate code for double lookup interpolation.
+        Args:
+            sfg (SfgComposer): Source file generator composer.
+        Returns:
+            list: List of public members for the C++ class.
+        """
+        if not self.has_double_lookup:
+            return []
+
+        T_eq_arr_values = ", ".join(str(v) for v in self.T_eq)
+        E_neq_arr_values = ", ".join(str(v) for v in self.E_neq)
+        E_eq_arr_values = ", ".join(str(v) for v in self.E_eq)
+        idx_mapping_arr_values = ", ".join(str(v) for v in self.idx_map)
+
+        E_target = sfg.var("E_target", "double")
+
+        return [
+            # Double lookup arrays
+            f"static constexpr std::array< double, {self.T_eq.shape[0]} > T_eq {{ {T_eq_arr_values} }}; \n"
+            f"static constexpr std::array< double, {self.E_neq.shape[0]} > E_neq {{ {E_neq_arr_values} }}; \n"
+            f"static constexpr std::array< double, {self.E_eq.shape[0]} > E_eq {{ {E_eq_arr_values} }}; \n"
+            f"static constexpr double inv_delta_E_eq = {self.inv_delta_E_eq}; \n"
+            f"static constexpr std::array< int, {self.idx_map.shape[0]} > idx_map {{ {idx_mapping_arr_values} }}; \n",
+
+            # Double lookup method
+            sfg.method("interpolateDL", returns=PsCustomType("[[nodiscard]] double"), inline=True, const=True)(
+                sfg.expr("return interpolate_double_lookup_cpp({}, *this);", E_target)
+            )
+        ]
+
+    def generate(self, sfg: SfgComposer):
+        """Generate C++ code for the interpolation container.
+        This method generates a C++ class with the necessary arrays and methods
+        for temperature-energy interpolation.
+        Args:
+            sfg (SfgComposer): Source file generator composer.
+        """
+        sfg.include("<array>")
+        sfg.include("pymatlib_interpolators/interpolate_binary_search_cpp.h")
+
+        public_members = self._generate_binary_search(sfg)
+
         # Add double lookup if available
         if self.has_double_lookup:
             sfg.include("pymatlib_interpolators/interpolate_double_lookup_cpp.h")
-
-            T_eq_arr_values = ", ".join(str(v) for v in self.T_eq)
-            E_neq_arr_values = ", ".join(str(v) for v in self.E_neq)
-            E_eq_arr_values = ", ".join(str(v) for v in self.E_eq)
-            idx_mapping_arr_values = ", ".join(str(v) for v in self.idx_map)
-
-            public_members.extend([
-                # Double lookup arrays
-                f"static constexpr std::array< double, {self.T_eq.shape[0]} > T_eq {{ {T_eq_arr_values} }}; \n"
-                f"static constexpr std::array< double, {self.E_neq.shape[0]} > E_neq {{ {E_neq_arr_values} }}; \n"
-                f"static constexpr std::array< double, {self.E_eq.shape[0]} > E_eq {{ {E_eq_arr_values} }}; \n"
-                f"static constexpr double inv_delta_E_eq = {self.inv_delta_E_eq}; \n"
-                f"static constexpr std::array< int, {self.idx_map.shape[0]} > idx_map {{ {idx_mapping_arr_values} }}; \n",
-
-                # Double lookup method
-                sfg.method("interpolateDL", returns=PsCustomType("[[nodiscard]] double"), inline=True, const=True)(
-                    sfg.expr("return interpolate_double_lookup_cpp({}, *this);", E_target)
-                )
-            ])
+            public_members.extend(self._generate_double_lookup(sfg))
 
         # Add interpolate method that uses recommended approach
+        E_target = sfg.var("E_target", "double")
         if self.has_double_lookup:
             public_members.append(
                 sfg.method("interpolate", returns=PsCustomType("[[nodiscard]] double"), inline=True, const=True)(
diff --git a/src/pymatlib/core/models.py b/src/pymatlib/core/models.py
index fd6b009b7f7045efd23133c08ec96b6a1dff588a..80bcf2ee5ffe17797abce1acca1f8440bc6b2515 100644
--- a/src/pymatlib/core/models.py
+++ b/src/pymatlib/core/models.py
@@ -27,8 +27,8 @@ def wrapper(value: Union[sp.Expr, NumericType, ArrayTypes, MaterialProperty]) \
     if isinstance(value, sp.Expr):
         return sp.simplify(value)
     if isinstance(value, (float, np.int32, np.int64, np.float32, np.float64)):  # np.floating
-        if abs(value) < DEFAULT_TOLERANCE:
-            return sp.Float(0.0)
+        # if abs(value) < DEFAULT_TOLERANCE:
+            # return sp.Float(0.0)
         return sp.Float(float(value))
     if isinstance(value, ArrayTypes):  # Handles lists, tuples, and arrays
         try:
diff --git a/src/pymatlib/core/yaml_parser.py b/src/pymatlib/core/yaml_parser.py
index eab110edfe66e6074ad6a600933d4267b30b3187..f6b92fcd65ba712b7a28077a922df717fe42a66f 100644
--- a/src/pymatlib/core/yaml_parser.py
+++ b/src/pymatlib/core/yaml_parser.py
@@ -182,7 +182,7 @@ class MaterialConfigParser:
                 if isinstance(prop_value, float) and prop_value < 0:
                     raise ValueError(f"'{prop_name}' cannot be negative, got {prop_value}")
             if prop_name == 'thermal_expansion_coefficient':
-                if isinstance(prop_value, float) and prop_value < -3e-5 or prop_value > 0.001:
+                if isinstance(prop_value, float) and (prop_value < -3e-5 or prop_value > 0.001):
                     raise ValueError(f"'{prop_name}' value {prop_value} is outside the expected range (-3e-5/K to 0.001/K)")
             if prop_name == 'energy_density_temperature_array':
                 if not (isinstance(prop_value, str) and prop_value.startswith('(') and prop_value.endswith(')')):
diff --git a/src/pymatlib/data/alloys/SS304L/SS304L_comprehensive.yaml b/src/pymatlib/data/alloys/SS304L/SS304L_comprehensive.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1db622cdc76c5e1c80058ae76c559b634916d1bc
--- /dev/null
+++ b/src/pymatlib/data/alloys/SS304L/SS304L_comprehensive.yaml
@@ -0,0 +1,61 @@
+name: SS304L_Comprehensive
+
+composition:
+  Fe: 0.675
+  Cr: 0.170
+  Ni: 0.120
+  Mo: 0.025
+  Mn: 0.010
+
+solidus_temperature: 1605
+liquidus_temperature: 1735
+
+properties:
+  # 1. Constant float property
+  density: 7950.  # kg/m³
+
+  # 2.1 File-based property (simple format)
+  heat_conductivity: ./heat_conductivity_temperature.txt
+
+  # 2.2 File-based property (advanced format)
+  specific_enthalpy:
+    file: ./304L_Erstarrungsdaten_edited.xlsx
+    temp_col: T (K)
+    prop_col: Enthalpy (J/kg)
+
+  # 3.1 Key-val pair with explicit temperature list
+  heat_capacity:
+    key: [1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800]
+    val: [580, 590, 600, 600, 600, 610, 620, 630, 660, 700]
+
+  # 3.2 Key-val pair with references to defined temperatures
+  latent_heat_of_fusion:
+    key: [solidus_temperature, liquidus_temperature]
+    val: [171401, 0]
+
+  # 3.3 Key-val pair with tuple for temperature generation (increment)
+  thermal_expansion_coefficient:
+    key: (300, 100)  # Start at 300K and increment by 100K
+    val: [16.3e-6, 16.5e-6, 16.8e-6, 17.0e-6, 17.2e-6]
+
+  # 3.4 Key-val pair with tuple for temperature generation (decrement)
+  dynamic_viscosity:
+    key: (1735, -10)  # Start at 1735K and decrement by 10K
+    val: [0.005, 0.006, 0.007, 0.008, 0.009]
+
+  # 4.1 Computed property (simple format)
+  thermal_diffusivity: compute  # k/(rho*cp)
+
+  # 4.2 Computed property (advanced format with model selection)
+  energy_density:
+    compute: total_enthalpy
+
+  # Required for energy_density computation (with number of points)
+  # energy_density_temperature_array: (300, 3000, 541)
+
+  # Alternative specification (with temperature increment)
+  energy_density_temperature_array: (300, 3000, 5.0)
+
+  # Properties required for density computation by thermal expansion
+  base_temperature: 2273.
+  base_density: 6.591878918e3
diff --git a/tests/cpp/test_interpolation.cpp b/tests/cpp/test_interpolation.cpp
index ec001f0309bed1176e31094bf3676f9ed0829443..7b3e10ab8a3f45b5a02677242f4def5231a24748 100644
--- a/tests/cpp/test_interpolation.cpp
+++ b/tests/cpp/test_interpolation.cpp
@@ -1,5 +1,5 @@
-#include "interpolate_binary_search_cpp.h"
-#include "interpolate_double_lookup_cpp.h"
+#include "pymatlib_interpolators/interpolate_binary_search_cpp.h"
+#include "pymatlib_interpolators/interpolate_double_lookup_cpp.h"
 #include <array>
 #include <random>
 #include <chrono>
@@ -10,7 +10,7 @@
 #include "TestArrayContainer.hpp"
 
 // Helper function to compare floating point numbers
-bool is_equal(double a, double b, double tolerance = 1e-10) {
+bool is_equal(const double a, const double b, double tolerance = 1e-10) {
     return std::abs(a - b) < tolerance;
 }
 
@@ -18,24 +18,24 @@ void test_basic_functionality() {
     std::cout << "\nTesting basic functionality..." << std::endl;
 
     // Test middle point interpolation
-    const double test_E = 16950000000.0;
+    constexpr double test_E = 16950000000.0;
 
     // Binary Search Tests
     {
-        BinarySearchTests tests;
-        double result = tests.interpolateBS(test_E);
+        constexpr BinarySearchTests tests;
+        const double result = tests.interpolateBS(test_E);
         // Expected value based on T_bs array
-        double expected_T = 3253.15;
+        constexpr double expected_T = 3253.15;
         assert(is_equal(result, expected_T));
         std::cout << "Basic binary search interpolation passed" << std::endl;
     }
 
     // Double Lookup Tests
     {
-        DoubleLookupTests tests;
-        double result = tests.interpolateDL(test_E);
+        constexpr DoubleLookupTests tests;
+        const double result = tests.interpolateDL(test_E);
         // Expected value based on T_eq array
-        double expected_T = 3258.15;
+        constexpr double expected_T = 3258.15;
         assert(is_equal(result, expected_T));
         std::cout << "Basic double lookup interpolation passed" << std::endl;
     }
@@ -49,11 +49,11 @@ void test_edge_cases_and_errors() {
         BinarySearchTests tests;
 
         // Test below minimum
-        double result_min = tests.interpolateBS(16750000000.0);
+        const double result_min = tests.interpolateBS(16750000000.0);
         assert(is_equal(result_min, 3243.15));
 
         // Test above maximum
-        double result_max = tests.interpolateBS(17150000000.0);
+        const double result_max = tests.interpolateBS(17150000000.0);
         assert(is_equal(result_max, 3278.15));
 
         std::cout << "Edge cases for binary search passed" << std::endl;
@@ -64,11 +64,11 @@ void test_edge_cases_and_errors() {
         DoubleLookupTests tests;
 
         // Test below minimum
-        double result_min = tests.interpolateDL(16750000000.0);
+        const double result_min = tests.interpolateDL(16750000000.0);
         assert(is_equal(result_min, 3243.15));
 
         // Test above maximum
-        double result_max = tests.interpolateDL(17150000000.0);
+        const double result_max = tests.interpolateDL(17150000000.0);
         assert(is_equal(result_max, 3273.15));
 
         std::cout << "Edge cases for double lookup passed" << std::endl;
@@ -100,12 +100,12 @@ void test_interpolation_accuracy() {
     for (const auto& test : test_cases) {
         // Binary Search Tests
         BinarySearchTests bs_tests;
-        double result_bs = bs_tests.interpolateBS(test.input_E);
+        const double result_bs = bs_tests.interpolateBS(test.input_E);
         assert(is_equal(result_bs, test.expected_T_bs, test.tolerance));
 
         // Double Lookup Tests
         DoubleLookupTests dl_tests;
-        double result_dl = dl_tests.interpolateDL(test.input_E);
+        const double result_dl = dl_tests.interpolateDL(test.input_E);
         assert(is_equal(result_dl, test.expected_T_dl, test.tolerance));
 
         std::cout << "Accuracy test passed for " << test.description << std::endl;
@@ -116,17 +116,17 @@ void test_consistency() {
     std::cout << "\nTesting interpolation consistency..." << std::endl;
 
     // Test that small changes in input produce correspondingly small changes in output
-    BinarySearchTests bs_tests;
-    DoubleLookupTests dl_tests;
+    constexpr BinarySearchTests bs_tests;
+    constexpr DoubleLookupTests dl_tests;
 
-    const double base_E = 16900000000.0;
-    const double delta_E = 1000000.0;  // Small change in energy
+    constexpr double base_E = 16900000000.0;
+    constexpr double delta_E = 1000000.0;  // Small change in energy
 
-    double base_T_bs = bs_tests.interpolateBS(base_E);
-    double delta_T_bs = bs_tests.interpolateBS(base_E + delta_E) - base_T_bs;
+    const double base_T_bs = bs_tests.interpolateBS(base_E);
+    const double delta_T_bs = bs_tests.interpolateBS(base_E + delta_E) - base_T_bs;
 
-    double base_T_dl = dl_tests.interpolateDL(base_E);
-    double delta_T_dl = dl_tests.interpolateDL(base_E + delta_E) - base_T_dl;
+    const double base_T_dl = dl_tests.interpolateDL(base_E);
+    const double delta_T_dl = dl_tests.interpolateDL(base_E + delta_E) - base_T_dl;
 
     // Check that changes are reasonable (not too large for small input change)
     assert(std::abs(delta_T_bs) < 1.0);
@@ -138,18 +138,18 @@ void test_consistency() {
 void test_stress() {
     std::cout << "\nPerforming stress testing..." << std::endl;
 
-    BinarySearchTests bs_tests;
-    DoubleLookupTests dl_tests;
+    constexpr BinarySearchTests bs_tests;
+    constexpr DoubleLookupTests dl_tests;
 
     // Test with extremely large values
-    double large_E = 1.0e20;
-    double result_large_bs = bs_tests.interpolateBS(large_E);
-    double result_large_dl = dl_tests.interpolateDL(large_E);
+    constexpr double large_E = 1.0e20;
+    const double result_large_bs = bs_tests.interpolateBS(large_E);
+    const double result_large_dl = dl_tests.interpolateDL(large_E);
 
     // Test with extremely small values
-    double small_E = 1.0e-20;
-    double result_small_bs = bs_tests.interpolateBS(small_E);
-    double result_small_dl = dl_tests.interpolateDL(small_E);
+    constexpr double small_E = 1.0e-20;
+    const double result_small_bs = bs_tests.interpolateBS(small_E);
+    const double result_small_dl = dl_tests.interpolateDL(small_E);
 
     // For extreme values, we should get boundary values
     assert(is_equal(result_large_bs, 3278.15));
@@ -163,19 +163,19 @@ void test_stress() {
 void test_random_validation() {
     std::cout << "\nTesting with random inputs..." << std::endl;
 
-    BinarySearchTests bs_tests;
-    DoubleLookupTests dl_tests;
+    constexpr BinarySearchTests bs_tests;
+    constexpr DoubleLookupTests dl_tests;
 
     std::random_device rd;
     std::mt19937 gen(rd());
     std::uniform_real_distribution<double> dist(16800000000.0, 17100000000.0);
 
-    const int num_tests = 1000;
+    constexpr int num_tests = 1000;
     for (int i = 0; i < num_tests; ++i) {
-        double random_E = dist(gen);
+        const double random_E = dist(gen);
 
-        double result_bs = bs_tests.interpolateBS(random_E);
-        double result_dl = dl_tests.interpolateDL(random_E);
+        const double result_bs = bs_tests.interpolateBS(random_E);
+        const double result_dl = dl_tests.interpolateDL(random_E);
 
         // Results should be within the temperature range
         assert(result_bs >= 3243.15 && result_bs <= 3278.15);
@@ -195,14 +195,14 @@ void test_performance() {
     constexpr int numCells = 64*64*64;
 
     // Setup test data
-    SS316L test;
+    constexpr SS304L test;
     std::vector<double> random_energies(numCells);
 
     // Generate random values
     std::random_device rd;
     std::mt19937 gen(rd());
-    const double E_min = SS316L::E_neq.front() * 0.8;
-    const double E_max = SS316L::E_neq.back() * 1.2;
+    constexpr double E_min = SS304L::E_neq.front() * 0.8;
+    constexpr double E_max = SS304L::E_neq.back() * 1.2;
     std::uniform_real_distribution<double> dist(E_min, E_max);
 
     // Fill random energies
@@ -263,10 +263,9 @@ void test_performance() {
 
     // Calculate and print statistics
     auto calc_stats = [](const std::vector<double>& timings) {
-        double sum = std::accumulate(timings.begin(), timings.end(), 0.0);
+        const double sum = std::accumulate(timings.begin(), timings.end(), 0.0);
         double mean = sum / static_cast<double>(timings.size());
-        double sq_sum = std::inner_product(timings.begin(), timings.end(),
-                                         timings.begin(), 0.0);
+        const double sq_sum = std::inner_product(timings.begin(), timings.end(),timings.begin(), 0.0);
         double stdev = std::sqrt(sq_sum / static_cast<double>(timings.size()) - mean * mean);
         return std::make_pair(mean, stdev);
     };