[Software & Simulation]

Property Model Parameter Fitting

Property Model Parameter Fitting

This example shows how to optimize the parameters of a Property Model. Typically that approach is used in order to fit a Property Model to experimental data. That can be useful for any application where no analytical correlation between the input parameters (composition, temperature and other parameters) and the material property can be established. Examples might be solid solution strength models or martensite temperature models where the transformation barrier is modeled.

For the purpose of this example, the linear fitting to noisy data is shown.

A ‘model parameter’ is a value that can be changed from the outside of the model in the way demonstrated here. Internally it can be represented in any way; the only requirement is that the Property Model implements the ‘Python Property Model Development Framework’ interface methods :func:provide_model_parameters and :func:set_model_parameter.

from tc_python import *
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize



dependent_element = "Fe"
composition = {"C": 0.1}  # in wt-%


def model(p, temps, calculator):
    """Representation of the Property Model, primarily to set the model parameters `a` and `b` during the solver
    iterations."""

    # replace the model parameters by the current trial
    (calculator
        .set_model_parameter("a", p[0])
        .set_model_parameter("b", p[1]))

    # looping over the complete 'experimental' dataset
    result = []
    for temp in temps:
        calculator.set_temperature(temp)
        this_result = calculator.calculate()
        result.append(this_result.get_value_of("result"))

    print("Intermediate fitting result: a = {}, b= {}".format(p[0], p[1]))
    return result


with TCPython() as session:
    system = (session
                .select_database_and_elements("FEDEMO", [dependent_element] + list(composition.keys()))
                .get_system())

    # the custom Property Model is not located in the default Property Model directory, but in the specified
    # subdirectory
    print("Available property models : {}".format(session.get_property_models("property_models")))
    calculator = (system
                  .with_property_model_calculation("Simple linear model", "property_models")
                  .set_composition_unit(CompositionUnit.MASS_PERCENT))

    for element in composition:
        calculator.set_composition(element, composition[element])

    print("Model parameters: {}".format(calculator.get_model_parameters()))
    print("Currently set value of model parameter a = {}".format(calculator.get_model_parameter_value("a")))
    print("Currently set value of model parameter b = {}".format(calculator.get_model_parameter_value("b")))

    # generate data points with noise
    num_points = 150
    temps_x = np.linspace(200, 1000, num_points)  # in K

    # parameter `a` is about 1000 and parameter `b` is about 0.5
    experiment_y = 1000 + 0.5 * temps_x + np.random.uniform(-1, 1, num_points) * 100

    # setup the initial guess of `a` and `b` and define the fitting functions
    fit_func = lambda p, x, calc: model(p, x, calc)            # target function
    err_func = lambda p, x, y: fit_func(p, x, calculator) - y  # distance to the target function
    params_0 = [100.0, 0.01]                                   # some initial guess for the parameters being far off

    # run the fitting
    opt_result = optimize.least_squares(err_func, params_0, args=(temps_x, experiment_y))  # type: dict
    params_opt = opt_result["x"]
    print("Best optimized parameters: a = {}, b = {}".format(params_opt[0], params_opt[1]))

    # plot of the data and the fit
    fig, ax = plt.subplots()
    fig.suptitle('Fitting of linear Property Model', fontsize=14, fontweight='bold')
    ax.plot(temps_x, experiment_y, "ro", temps_x, fit_func(params_opt, temps_x, calculator), "r-")
    ax.set_xlabel("temperature / K")
    ax.set_ylabel("'experimental' property")
    plt.show()

alt text