Back to all questions

How do I create a custom material domain?

Material Domains
custom
domain
plugin

If your material is not covered by MatCraft's 16 built-in domains, you can create a custom domain plugin. A domain plugin consists of a YAML schema definition and an optional Python physics module.

Minimal Custom Domain

At minimum, a domain is a YAML file defining the parameter schema:

yaml
# plugins/my_domain/components.yaml
domain_name: shape_memory_alloy
description: "NiTi-based shape memory alloys"
version: "1.0.0"

default_components:
  - name: nickel_content
    type: continuous
    bounds: [49.0, 51.5]
    unit: "at%"
    description: "Nickel atomic percentage"
  - name: aging_temperature
    type: continuous
    bounds: [300, 600]
    unit: "°C"
  - name: aging_time
    type: continuous
    bounds: [0.5, 48]
    unit: "hours"
  - name: cold_work
    type: continuous
    bounds: [0, 40]
    unit: "%"

default_objectives:
  - name: transformation_temperature
    direction: maximize
    unit: "°C"
    description: "Austenite finish temperature (Af)"
  - name: recoverable_strain
    direction: maximize
    unit: "%"
  - name: fatigue_life
    direction: maximize
    unit: "cycles"

default_constraints:
  - type: custom
    expression: "nickel_content >= 49.5 and nickel_content <= 51.0"
    description: "Near-equiatomic NiTi range for shape memory effect"

Adding a Physics Model

Create a Python file with evaluation functions:

python
# plugins/my_domain/physics.py
from materia.evaluate import DomainPhysics

class ShapeMemoryAlloyPhysics(DomainPhysics):
    """Physics model for NiTi shape memory alloys."""

    def evaluate(self, composition: dict) -> dict:
        ni = composition["nickel_content"]
        t_age = composition["aging_temperature"]
        t_time = composition["aging_time"]
        cw = composition["cold_work"]

        # Empirical model for transformation temperature
        # Based on Frenzel et al. (2010) correlations
        af = -1450 + 28.5 * ni + 0.02 * t_age * t_time - 0.5 * cw

        # Recoverable strain model
        strain = 8.0 - 0.15 * abs(ni - 50.5) - 0.01 * cw

        # Fatigue life (log-linear model)
        import math
        fatigue = math.exp(10 - 0.5 * abs(ni - 50.0) + 0.01 * t_age - 0.02 * cw)

        return {
            "transformation_temperature": af,
            "recoverable_strain": max(0, strain),
            "fatigue_life": fatigue,
        }

Registering the Plugin

Place your files in the plugin directory and register them:

bash
materia plugin register ./plugins/my_domain/

Or in Python:

python
from materia.plugins import register_domain
register_domain("./plugins/my_domain/")

Using Your Custom Domain

yaml
domain: shape_memory_alloy  # References your registered plugin
name: "niti-optimization"
# Components and objectives inherit from plugin defaults
# Override or add additional parameters as needed
components:
  - name: ternary_element
    type: categorical
    choices: ["Cu", "Fe", "Nb", "none"]

Best Practices

  • Start with published empirical correlations for your physics model, even if approximate. The surrogate will learn corrections from real data.
  • Include sensible default bounds based on literature. Users can always override them.
  • Add input validation to catch physically impossible combinations early.
  • Write unit tests for your physics model to catch regressions.

Related Questions