Back to all questions

How do I add custom physics models to a domain?

Material Domains
physics
simulation
evaluator

Physics models in MatCraft serve as fast approximate evaluators that supplement or replace experimental data during optimization. They are particularly valuable for generating initial training data for the surrogate model.

Physics Model Architecture

A physics model inherits from DomainPhysics and implements the evaluate method:

python
from materia.evaluate import DomainPhysics
import numpy as np

class MyPhysicsModel(DomainPhysics):
    """Custom physics model for thermal barrier coatings."""

    def __init__(self, temperature: float = 1000.0):
        super().__init__()
        self.operating_temp = temperature  # Service temperature in °C

    def evaluate(self, composition: dict) -> dict:
        ysz_fraction = composition["ysz_fraction"]
        alumina_fraction = composition["alumina_fraction"]
        thickness = composition["coating_thickness"]
        porosity = composition["porosity"]

        # Thermal conductivity (Maxwell-Eucken model)
        k_dense = 2.5 * ysz_fraction + 30.0 * alumina_fraction
        k_eff = k_dense * (1 - porosity) / (1 + 0.5 * porosity)

        # Thermal resistance
        r_thermal = thickness * 1e-6 / k_eff  # m²·K/W

        # Thermal stress (simplified Timoshenko)
        delta_t = self.operating_temp - 25.0
        cte_mismatch = abs(10e-6 * ysz_fraction - 12e-6 * alumina_fraction)
        thermal_stress = cte_mismatch * delta_t * 200e9 * thickness * 1e-6

        # Erosion resistance (empirical)
        erosion_rate = 0.1 / (ysz_fraction * thickness * (1 - porosity) + 0.01)

        return {
            "thermal_resistance": r_thermal,
            "thermal_stress": thermal_stress,
            "erosion_rate": erosion_rate,
        }

    def validate_inputs(self, composition: dict) -> list[str]:
        """Optional: return list of validation warnings."""
        warnings = []
        if composition.get("porosity", 0) > 0.3:
            warnings.append("Porosity > 30% may compromise structural integrity")
        return warnings

Wrapping External Simulation Codes

If you have an existing simulation tool (COMSOL, LAMMPS, VASP, etc.), wrap it as a physics model:

python
import subprocess
import json
from materia.evaluate import DomainPhysics

class COMSOLWrapper(DomainPhysics):
    def __init__(self, comsol_path: str, model_file: str):
        super().__init__()
        self.comsol_path = comsol_path
        self.model_file = model_file

    def evaluate(self, composition: dict) -> dict:
        # Write input parameters
        with open("/tmp/comsol_input.json", "w") as f:
            json.dump(composition, f)

        # Run COMSOL in batch mode
        result = subprocess.run(
            [self.comsol_path, "batch", "-inputfile", self.model_file,
             "-paramfile", "/tmp/comsol_input.json",
             "-outputfile", "/tmp/comsol_output.json"],
            capture_output=True, text=True, timeout=3600
        )

        if result.returncode != 0:
            raise RuntimeError(f"COMSOL failed: {result.stderr}")

        with open("/tmp/comsol_output.json") as f:
            return json.load(f)

Hybrid Evaluation

MatCraft supports a hybrid approach where fast physics models provide most evaluations, and expensive simulations or experiments are used selectively:

python
campaign = Campaign(
    material=material,
    evaluator=MyPhysicsModel(),          # Fast approximate model
    validation_evaluator=COMSOLWrapper(),  # Expensive high-fidelity model
    validation_frequency=5,  # Validate every 5th candidate with COMSOL
)

This two-tier approach gives you the speed of approximate models with periodic ground-truth validation.

Related Questions