Calibration of the Chaboche mechanical model

In this example we present calibration methods on the Chaboche model. A detailed explanation of this mechanical law is presented here.

import numpy as np
import openturns as ot
import openturns.viewer as viewer
from matplotlib import pylab as plt
from openturns.usecases import chaboche_model as chaboche_model

ot.Log.Show(ot.Log.NONE)

Load the Chaboche data structure

cm = chaboche_model.ChabocheModel()

We get the Chaboche model and the joint input distribution :

g = cm.model
inputDistribution = cm.inputDistribution

Create the Monte-Carlo sample.

sampleSize = 100
inputSample = inputDistribution.getSample(sampleSize)
outputStress = g(inputSample)
outputStress[0:5]
y0
08.837278e+08
17.771642e+08
28.666929e+08
38.712515e+08
47.604437e+08


Plot the histogram of the output.

histoGraph = ot.HistogramFactory().build(outputStress / 1.0e6).drawPDF()
histoGraph.setTitle("Histogram of the sample stress")
histoGraph.setXTitle("Stress (MPa)")
histoGraph.setLegends([""])
view = viewer.View(histoGraph)
Histogram of the sample stress

Generate observation noise.

stressObservationNoiseSigma = 10.0e6  # (Pa)
noiseSigma = ot.Normal(0.0, stressObservationNoiseSigma)
sampleNoiseH = noiseSigma.getSample(sampleSize)
observedStress = outputStress + sampleNoiseH
observedStrain = inputSample[:, 0]
graph = ot.Graph("Observations", "Strain", "Stress (MPa)", True)
cloud = ot.Cloud(observedStrain, observedStress / 1.0e6)
graph.add(cloud)
view = viewer.View(graph)
Observations

Set the calibration parameters

Define the value of the reference values of the \theta parameter. In the bayesian framework, this is called the mean of the prior gaussian distribution. In the data assimilation framework, this is called the background.

R = 700e6  # Exact : 750e6
C = 2500e6  # Exact : 2750e6
Gamma = 8.0  # Exact : 10
thetaPrior = [R, C, Gamma]

The following statement create the calibrated function from the model. The calibrated parameters R, C, Gamma are at indices 1, 2, 3 in the inputs arguments of the model.

calibratedIndices = [1, 2, 3]
mycf = ot.ParametricFunction(g, calibratedIndices, thetaPrior)

Calibration with linear least squares

The LinearLeastSquaresCalibration class performs the linear least squares calibration by linearizing the model in the neighbourhood of the reference point.

algo = ot.LinearLeastSquaresCalibration(
    mycf, observedStrain, observedStress, thetaPrior, "SVD"
)

The run method computes the solution of the problem.

algo.run()
calibrationResult = algo.getResult()

Analysis of the results

The getParameterMAP method returns the maximum of the posterior distribution of \theta.

thetaMAP = calibrationResult.getParameterMAP()
thetaMAP

[7.47021e+08,3.00805e+09,13.4977]



We can compute a 95% confidence interval of the parameter \theta^\star.

thetaPosterior = calibrationResult.getParameterPosterior()
thetaPosterior.computeBilateralConfidenceIntervalWithMarginalProbability(0.95)[0]

[7.38479e+08, 7.55563e+08]
[2.41351e+09, 3.60259e+09]
[-581.106, 608.101]



We can see that the Gamma parameter has a large confidence interval : even the sign of the parameter is unknown. The parameter which is calibrated with the smallest confidence interval is R, which confidence interval is [708.3,780.0] (MPa). This is why this parameter seems the most important in this case.

graph = calibrationResult.drawObservationsVsInputs()
graph.setLegendPosition("topleft")
view = viewer.View(graph)
plot calibration chaboche

We see that there is a good fit after calibration, since the predictions after calibration (i.e. the green crosses) are close to the observations (i.e. the blue crosses).

graph = calibrationResult.drawObservationsVsPredictions()
view = viewer.View(graph)
plot calibration chaboche

We see that there is a much better fit after calibration, since the predictions are close to the diagonal of the graphics.

observationError = calibrationResult.getObservationsError()
observationError

Normal(mu = 0, sigma = 1.20072e+07)



graph = calibrationResult.drawResiduals()
graph.setLegendPosition("topleft")
view = viewer.View(graph)
, Residual analysis

The analysis of the residuals shows that the distribution is centered on zero and symmetric. This indicates that the calibration performed well.

Moreover, the distribution of the residuals is close to being gaussian.

graph = calibrationResult.drawParameterDistributions()
view = viewer.View(graph)
plot calibration chaboche

Calibration with nonlinear least squares

The NonLinearLeastSquaresCalibration class performs the non linear least squares calibration by minimizing the squared euclidian norm between the predictions and the observations.

algo = ot.NonLinearLeastSquaresCalibration(
    mycf, observedStrain, observedStress, thetaPrior
)

The run method computes the solution of the problem.

algo.run()
calibrationResult = algo.getResult()

Analysis of the results

The getParameterMAP method returns the maximum of the posterior distribution of \theta.

thetaMAP = calibrationResult.getParameterMAP()
thetaMAP

[7.42395e+08,3.4611e+09,17.2407]



We can compute a 95% confidence interval of the parameter \theta^\star.

thetaPosterior = calibrationResult.getParameterPosterior()
thetaPosterior.computeBilateralConfidenceIntervalWithMarginalProbability(0.95)[0]

[7.3351e+08, 7.50362e+08]
[2.80534e+09, 4.17281e+09]
[11.0128, 23.8404]



We can see that all three parameters are estimated with a large confidence interval.

graph = calibrationResult.drawObservationsVsInputs()
graph.setLegendPosition("topleft")
view = viewer.View(graph)
plot calibration chaboche

We see that there is a good fit after calibration, since the predictions after calibration (i.e. the green crosses) are close to the observations (i.e. the blue crosses).

graph = calibrationResult.drawObservationsVsPredictions()
view = viewer.View(graph)
plot calibration chaboche

We see that there is a much better fit after calibration, since the predictions are close to the diagonal of the graphics.

observationError = calibrationResult.getObservationsError()
observationError

Normal(mu = -1142.34, sigma = 1.15671e+07)



graph = observationError.drawPDF()
view = viewer.View(graph)
plot calibration chaboche
graph = calibrationResult.drawResiduals()
graph.setLegendPosition("topleft")
view = viewer.View(graph)
, Residual analysis

The analysis of the residuals shows that the distribution is centered on zero and symmetric. This indicates that the calibration performed well.

Moreover, the distribution of the residuals is close to being gaussian. This indicates that the observation error might be gaussian.

graph = calibrationResult.drawParameterDistributions()
view = viewer.View(graph)
plot calibration chaboche

Gaussian calibration parameters

The standard deviation of the observations errors.

sigmaStress = 1.0e7  # (Pa)

Define the covariance matrix of the output Y of the model.

errorCovariance = ot.CovarianceMatrix(1)
errorCovariance[0, 0] = sigmaStress ** 2

Define the covariance matrix of the parameters \theta to calibrate.

sigmaR = 0.1 * R
sigmaC = 0.1 * C
sigmaGamma = 0.1 * Gamma
sigma = ot.CovarianceMatrix(3)
sigma[0, 0] = sigmaR ** 2
sigma[1, 1] = sigmaC ** 2
sigma[2, 2] = sigmaGamma ** 2
sigma

[[ 4.9e+15 0 0 ]
[ 0 6.25e+16 0 ]
[ 0 0 0.64 ]]



Gaussian linear calibration

The GaussianLinearCalibration class performs the gaussian linear calibration by linearizing the model in the neighbourhood of the prior.

algo = ot.GaussianLinearCalibration(
    mycf, observedStrain, observedStress, thetaPrior, sigma, errorCovariance
)

The run method computes the solution of the problem.

algo.run()
calibrationResult = algo.getResult()

Analysis of the results

The getParameterMAP method returns the maximum of the posterior distribution of \theta.

thetaMAP = calibrationResult.getParameterMAP()
thetaMAP

[7.5128e+08,2.59561e+09,8.44106]



We can compute a 95% confidence interval of the parameter \theta^\star.

thetaPosterior = calibrationResult.getParameterPosterior()
thetaPosterior.computeBilateralConfidenceIntervalWithMarginalProbability(0.95)[0]

[7.46056e+08, 7.56505e+08]
[2.40038e+09, 2.79083e+09]
[6.72865, 10.1535]



We can see that all three parameters are estimated with a large confidence interval.

graph = calibrationResult.drawObservationsVsInputs()
graph.setLegendPosition("topleft")
view = viewer.View(graph)
plot calibration chaboche

We see that there is a good fit after calibration, since the predictions after calibration (i.e. the green crosses) are close to the observations (i.e. the blue crosses).

graph = calibrationResult.drawObservationsVsPredictions()
view = viewer.View(graph)
plot calibration chaboche

We see that there is a much better fit after calibration, since the predictions are close to the diagonal of the graphics.

The observation error is predicted by linearizing the problem at the prior.

observationError = calibrationResult.getObservationsError()
observationError

Normal(mu = 0, sigma = 1e+07)



This can be compared to the residuals distribution, which is computed at the posterior.

graph = calibrationResult.drawResiduals()
graph.setLegendPosition("topleft")
view = viewer.View(graph)
, Residual analysis

The analysis of the gaussian distribution (the blue line) of the observation errors is close to the posterior distribution of the residuals (the green line). Moreover, the posterior distribution is centered. These informations indicate that the calibration performed well.

graph = calibrationResult.drawParameterDistributions()
view = viewer.View(graph)
plot calibration chaboche

For the R variable, the observations are much more important than the prior: this is shown by the fact that the posterior and prior distribution of the R variable are very different.

We see that the prior and posterior distribution are close to each other for the \gamma variable: the observations did not convey much information for this variable.

Gaussian nonlinear calibration

The GaussianNonLinearCalibration class performs the gaussian nonlinear calibration.

algo = ot.GaussianNonLinearCalibration(
    mycf, observedStrain, observedStress, thetaPrior, sigma, errorCovariance
)

The run method computes the solution of the problem.

algo.run()
calibrationResult = algo.getResult()

Analysis of the results

The getParameterMAP method returns the maximum of the posterior distribution of \theta.

thetaMAP = calibrationResult.getParameterMAP()
thetaMAP

[7.50518e+08,2.63291e+09,8.65041]



We can compute a 95% confidence interval of the parameter \theta^\star.

thetaPosterior = calibrationResult.getParameterPosterior()
thetaPosterior.computeBilateralConfidenceIntervalWithMarginalProbability(0.95)[0]

[7.43677e+08, 7.56803e+08]
[2.4655e+09, 2.88065e+09]
[8.60204, 9.82014]



We can see that all three parameters are estimated with a large confidence interval.

graph = calibrationResult.drawObservationsVsInputs()
graph.setLegendPosition("topleft")
view = viewer.View(graph)
plot calibration chaboche

We see that there is a good fit after calibration, since the predictions after calibration (i.e. the green crosses) are close to the observations (i.e. the blue crosses).

graph = calibrationResult.drawObservationsVsPredictions()
view = viewer.View(graph)
plot calibration chaboche

We see that there is a much better fit after calibration, since the predictions are close to the diagonal of the graphics.

The observation error is predicted by bootstraping the problem at the posterior.

observationError = calibrationResult.getObservationsError()
observationError

Normal(mu = -24686.6, sigma = 1e+07)



This can be compared to the residuals distribution, which is computed at the posterior.

graph = calibrationResult.drawResiduals()
view = viewer.View(graph)
, Residual analysis

The analysis is very similar to the linear calibration.

graph = calibrationResult.drawParameterDistributions()
view = viewer.View(graph)

plt.show()
plot calibration chaboche

We see that the prior and posterior distribution for the \gamma parameter are close to each other, but not superimposed: the observations significantly brought information to the variable \gamma during the calibration.

Total running time of the script: ( 0 minutes 9.525 seconds)

Gallery generated by Sphinx-Gallery