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.
A physics model inherits from DomainPhysics and implements the evaluate method:
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 warningsIf you have an existing simulation tool (COMSOL, LAMMPS, VASP, etc.), wrap it as a physics model:
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)MatCraft supports a hybrid approach where fast physics models provide most evaluations, and expensive simulations or experiments are used selectively:
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.