Defining Custom Material Properties

This guide explains how to define custom material properties in MaterForge using different property types.

Overview

MaterForge uses a schema-agnostic YAML format - any material kind (metals, alloys, polymers, ceramics, composites, or hypothetical materials) and any property name are valid. Properties can be constants or expressions driven by any independent variable (temperature, pressure, composition, strain, or any SymPy symbol). SI units are recommended throughout.

YAML Configuration Options

1. Constant Value

For properties that do not vary with the dependency variable:

properties:
    thermal_expansion_coefficient: 16.3e-6
    density: 7000.0

2. Step Functions

For properties that change abruptly at a transition point:

properties:
    latent_heat_of_fusion:
        dependency: solidus_temp + 5   # reference to another scalar property
        value: [0.0, 171401.0]         # [before_transition, after_transition]
        bounds: [constant, constant]

dependency here is a single scalar reference or arithmetic expression that defines the transition point.

3. Importing from External Files

For properties defined in spreadsheets or data files:

properties:
    # Excel file import
    density:
        file_path: ./material_data.xlsx
        dependency_column: T (K)
        property_column: Density (kg/m^3)
        bounds: [constant, constant]

    # CSV file import
    heat_capacity:
        file_path: ./heat_capacity_data.csv
        dependency_column: Temperature
        property_column: Cp
        bounds: [constant, constant]

    # Text file import (space/tab separated, headerless - use column index)
    thermal_conductivity:
        file_path: ./conductivity_data.txt
        dependency_column: 0
        property_column: 1
        bounds: [constant, constant]

Supported formats: .txt (space/tab separated), .csv, .xlsx.

4. Tabular Data

For properties defined by paired dependency-value lists:

properties:
    heat_conductivity:
        dependency: [500, 1000, 1600, 1700, 1750, 2000, 2500]
        value: [19.25, 25.47, 32.94, 33.52, 31.53, 35.33, 42.95]
        bounds: [constant, constant]

    # Using scalar property references in the dependency list
    latent_heat_of_fusion:
        dependency: [solidus_temp - 1, liquidus_temp + 1]
        value: [0, 171401.0]
        bounds: [constant, constant]

    # Using tuple notation
    density:
        dependency: (1735.0, -5)   # start=1735, decrement by 5 per value
        value: [7037.47, 7060.15, 7088.80, 7110.46, 7127.68]
        bounds: [constant, constant]

5. Piecewise Equations

For properties with different expressions over different ranges:

properties:
    viscosity:
        dependency: [300, 1660, 1736, 3000]        # n breakpoints -> n-1 equations
        equation: [7877.39-0.37*T, 11816.63-2.74*T, 8596.40-0.88*T]
        bounds: [constant, constant]

The symbol in the equation (T here) is just a placeholder. It is replaced by the symbol passed to create_material(..., dependency=X) at runtime. The symbol used in equations (T in the example above) is a placeholder only.

So this is valid:

P = sp.Symbol('P')
mat = create_material('myAlloy.yaml', dependency=P)
print(mat.viscosity)  # Piecewise in P, not T

The YAML file never needs to change regardless of what symbol the caller uses.

6. Computed Properties

For properties derived from other already-defined properties:

properties:
    thermal_diffusivity:
        dependency: (3000, 300, -5.0)
        equation: heat_conductivity / (density * heat_capacity)
        bounds: [linear, linear]
        regression:
            simplify: post
            degree: 2
            segments: 3

MaterForge resolves property dependencies automatically - thermal_diffusivity will always be processed after heat_conductivity, density, and heat_capacity regardless of their order in the YAML file.


Dependency Definition Formats

The dependency key accepts five formats:

# 1. Explicit list of values
dependency: [300, 500, 800, 1000]

# 2. Tuple (start, increment) - length inferred from value list
dependency: (300, 50)            # 300, 350, 400, ...

# 3. Tuple (start, stop, step) - step is float
dependency: (300, 1000, 10.0)    # 300, 310, 320, ..., 1000

# 4. Tuple (start, stop, points) - points is integer
dependency: (300, 1000, 71)      # 71 evenly spaced values

# 5. Decreasing range
dependency: (1000, 300, -5.0)    # 1000, 995, 990, ..., 300

Scalar property references and arithmetic expressions are also valid inside lists:

dependency: [solidus_temp - 1, liquidus_temp + 1]
dependency: solidus_temp + 5     # single reference for step functions

Bounds Options

Controls behaviour outside the defined range:

bounds: [constant, linear]

Option

Behaviour

constant

Clamp to the boundary value outside the range

linear

Linear extrapolation beyond the range


Regression Configuration

Reduces expression complexity and smooths noisy data:

regression:
    simplify: pre     # 'pre': applied to raw data before symbolic processing
                      # 'post': applied after symbolic expressions are evaluated
    degree: 1         # polynomial degree per segment (1=linear, 2=quadratic, ...)
    segments: 3       # number of piecewise segments (<=8 recommended)

Note: High segment counts (>6) risk overfitting. MaterForge will warn if this threshold is exceeded.


Complete Example

name: "myAlloy"

properties:
    density: 7000.0

    solidus_temp: 1605.
    liquidus_temp: 1735.

    latent_heat_of_fusion:
        dependency: solidus_temp + 5
        value: [0.0, 171401.0]
        bounds: [constant, constant]

    heat_conductivity:
        dependency: [500, 1000, 1600, 1700, 1750, 2000, 2500]
        value: [19.25, 25.47, 32.94, 33.52, 31.53, 35.33, 42.95]
        bounds: [linear, linear]

    heat_capacity:
        file_path: ./myAlloy.csv
        dependency_column: T (K)
        property_column: Specific heat (J/(Kg K))
        bounds: [constant, constant]
        regression:
            simplify: pre
            degree: 3
            segments: 6

    viscosity:
        dependency: [300, 1660, 1736, 3000]
        equation: [7877.39-0.37*T, 11816.63-2.74*T, 8596.40-0.88*T]
        bounds: [constant, constant]

    thermal_diffusivity:
        dependency: (3000, 300, -5.0)
        equation: heat_conductivity / (density * heat_capacity)
        bounds: [linear, linear]
        regression:
            simplify: post
            degree: 3
            segments: 7

Load it in Python:

import sympy as sp
from materforge.parsing.api import create_material

T = sp.Symbol('T')   # any symbol works: sp.Symbol('P'), sp.Symbol('x'), etc.
mat = create_material('myAlloy.yaml', dependency=T, enable_plotting=True)

# Access symbolic expressions directly
print(mat.heat_conductivity)     # SymPy Piecewise expression in T
print(mat.density)               # 7000.0 (constant float)

# Evaluate all properties at a specific value
evaluated = mat.evaluate(T, 500.0)
print(evaluated.heat_conductivity)           # sp.Float, prints as number e.g. 25.47
print(float(evaluated.heat_conductivity))    # Python float if downstream code requires i

Best Practices

  • Use SI units throughout and document units in comments

  • Cover the full range of your dependency variable in tabular and piecewise data

  • Validate property values against experimental data where possible

  • All numeric values must use ‘.’ as the decimal separator, not ‘,’

  • Interpolation between data points is automatic for tabular and file-import properties

  • Keep regression segments <= 8; prefer simplify: post for computed properties