.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "introduction_examples/plot_issue_example-discrepancy.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_introduction_examples_plot_issue_example-discrepancy.py: Model Discrepancy Issue Example =============================== In this case, the data comes from an exponential function with relatively low added noise. The model is a bilinear function producing results similar to an elastic-plastic response with the parameter "Y" controlling where the change from one linear trend to the other takes place and the parameter "H" controlling the slope of the second trend. The slope of the initial trend is fixed, as if it were known (as the elastic modulus typically would be). The fit is well defined in the sense that the error contours are closed, and the bowl is steep; however, the model discrepancy and the constraint of fixed E clearly have effects on the fit. For instance, the changeover point in the bilinear “plasticity” model is ambiguous as evidenced by the elongated diagonal error contours. Also extrapolating the fitted model will not follow the data. This issue is common in fitting real material models to data that spans large ranges of, for example, strain, strain-rate and temperature. To begin the calibration, we import MatCal and Numpy. .. GENERATED FROM PYTHON SOURCE LINES 21-25 .. code-block:: Python from matcal import * import numpy as np .. GENERATED FROM PYTHON SOURCE LINES 26-34 We create a python function to be used as a MatCal PythonModel for this calibration. The python model uses Numpy in the function and requires that Numpy be imported within the function. As stated above, the data will be fitted to a model with a bilinear response similar to an elastic-plastic model. The initial slope (E) is assumed to be known. The parameter "Y" determines where the model changes to the second linear trend and the parameters "H" determines the second slope. .. GENERATED FROM PYTHON SOURCE LINES 34-48 .. code-block:: Python def bilinear_model(**parameters): import numpy as np max_strain = 1.0 npoints = 100 strain = np.linspace(0,max_strain,npoints) E = 1.5 Y = parameters['Y'] H = parameters['H'] eY = Y/E stress = np.where(strain < eY, E*strain, Y + H*(strain-eY)) response = {'strain':strain, 'stress': stress} return response .. GENERATED FROM PYTHON SOURCE LINES 49-53 With the function for the model defined above, we create the parameters for our MatCal calibration study and the MatCal PythonModel from the function. .. GENERATED FROM PYTHON SOURCE LINES 53-59 .. code-block:: Python Y = Parameter('Y',0.0,1.0, 0.51) H = Parameter('H',0.0,1.0, 0.51) parameters = ParameterCollection('parameters', Y, H) model = PythonModel(bilinear_model) .. GENERATED FROM PYTHON SOURCE LINES 60-65 A simple gradient-based calibration with a mean squared error objective is enough to illustrate the point. We load the data, create the calibration based on the model parameters, and define an objective for fitting the model response to the data. .. GENERATED FROM PYTHON SOURCE LINES 65-70 .. code-block:: Python data = FileData('exponential.csv') calibration = GradientCalibrationStudy(parameters) objective = CurveBasedInterpolatedObjective('strain','stress') objective.set_name("stress-strain") calibration.add_evaluation_set(model, objective, data) .. GENERATED FROM PYTHON SOURCE LINES 71-73 We can then run the calibration and select the optimal parameters and the best fit. .. GENERATED FROM PYTHON SOURCE LINES 74-78 .. code-block:: Python results = calibration.launch() best_parameters = results.best.to_dict() best_response = results.best_simulation_data(model, 'matcal_default_state') .. GENERATED FROM PYTHON SOURCE LINES 79-81 We also grab the true/experimental response and the model/fitted response .. GENERATED FROM PYTHON SOURCE LINES 81-86 .. code-block:: Python data_strain = data['strain'] data_stress = data['stress'] model_strain = best_response['strain'] model_stress = best_response['stress'] .. GENERATED FROM PYTHON SOURCE LINES 87-100 First, compare the response curves. We plot the calibrated model with lines and the data with points. Generally, there are about as many points above the fitted line as below. This is due to using a mean squared error objective but here it causes the fit to miss "features" such as the soft transition from the initial linear trend to the exponential one. Also, since the fit does not emphasize the slope at the end of the data, using this model outside the fitted region will lead to large extrapolation errors, i.e., the model will overestimate the output. .. GENERATED FROM PYTHON SOURCE LINES 100-106 .. code-block:: Python import matplotlib.pyplot as plt plt.plot(model_strain,model_stress,'b',label="fit") plt.scatter(data_strain,data_stress,2,'r',label="data") plt.xlabel("STRAIN") plt.ylabel("STRESS") .. image-sg:: /introduction_examples/images/sphx_glr_plot_issue_example-discrepancy_001.png :alt: plot issue example discrepancy :srcset: /introduction_examples/images/sphx_glr_plot_issue_example-discrepancy_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(33.722222222222214, 0.5, 'STRESS') .. GENERATED FROM PYTHON SOURCE LINES 107-112 Second, examine how the error changes in the vicinity of the best fit. This a helper function to evaluate the error on a grid of parameter values for plotting. MatCal's ParameterStudy can also do this. .. GENERATED FROM PYTHON SOURCE LINES 112-123 .. code-block:: Python def sample_error(model, data, ranges = {"Y":[0.0,1.0],"H":[0.0,1.0]} ): Ys, Hs = np.mgrid[ ranges["Y"][0]:ranges["Y"][1]:100j, ranges["H"][0]:ranges["H"][1]:100j] Zs = np.empty_like(Ys) for i in range(Ys.shape[0]): for j in range(Ys.shape[1]): parameters = {"Y":Ys[i,j],"H":Hs[i,j]} response = model(**parameters) residual = response['stress']-data['stress'] error = np.sum(residual**2) Zs[i,j] = error return Ys,Hs,Zs .. GENERATED FROM PYTHON SOURCE LINES 124-128 The contour plot depicts the change in error in the vicinity of the optimum. Clearly it rises smoothly from the minimum at the optimum. Here, with a nonlinear dependence on the parameters, the bowl does not have perfectly elliptical contours. .. GENERATED FROM PYTHON SOURCE LINES 128-134 .. code-block:: Python Ys,Hs,Zs = sample_error(bilinear_model,data) plt.contourf(Ys,Hs,np.log(Zs),20) plt.grid(True) plt.xlabel("Y") plt.ylabel("H") plt.colorbar(label="log error") .. image-sg:: /introduction_examples/images/sphx_glr_plot_issue_example-discrepancy_002.png :alt: plot issue example discrepancy :srcset: /introduction_examples/images/sphx_glr_plot_issue_example-discrepancy_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.221 seconds) .. _sphx_glr_download_introduction_examples_plot_issue_example-discrepancy.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_issue_example-discrepancy.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_issue_example-discrepancy.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_issue_example-discrepancy.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_