.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "full_field_study_verification_examples/plot_b_standard_calibration_verification.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_full_field_study_verification_examples_plot_b_standard_calibration_verification.py: Load Displacement Calibration Verification - First Attempt =========================================================== In this example, we attempt to calibrate the five parameters of our verification problem using only the load-displacement curve. Since the :ref:`Objective Sensitivity Study` shows that the objective is at a minimum it should be possible. However, since the model is fairly expensive we attempt to do so using a gradient method. Specifically, we use the :class:`~matcal.dakota.local_calibration_studies.GradientCalibrationStudy` using Dakota's ``nl2sol`` method implementation. As we will see, the objective is difficult to calibrate due to the observed discontinuities and likely local minima throughout the parameter space. As a result, the method fails with little progress. To begin we import the MatCal tools necessary for this study and import the data that will be used for the calibration. .. GENERATED FROM PYTHON SOURCE LINES 24-33 .. code-block:: Python from matcal import * import numpy as np import matplotlib.pyplot as plt plt.rc('text', usetex=True) plt.rc('font', family='serif') plt.rcParams.update({'font.size': 12}) .. GENERATED FROM PYTHON SOURCE LINES 34-39 Next, we import the data we wish to use in the study. For this study, we import the Exodus data from the ``0_degree`` synthetic data set. .. GENERATED FROM PYTHON SOURCE LINES 39-41 .. code-block:: Python synthetic_data = FieldSeriesData("../../../docs_support_files/synthetic_surf_results_0_degree.e") .. rst-class:: sphx-glr-script-out .. code-block:: none You are using exodus.py v 1.21.6 (seacas-py3), a python wrapper of some of the exodus library. Copyright (c) 2013-2023 National Technology & Engineering Solutions of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights in this software. Opening exodus file: ../../../docs_support_files/synthetic_surf_results_0_degree.e Opening exodus file: ../../../docs_support_files/synthetic_surf_results_0_degree.e Closing exodus file: ../../../docs_support_files/synthetic_surf_results_0_degree.e Closing exodus file: ../../../docs_support_files/synthetic_surf_results_0_degree.e .. GENERATED FROM PYTHON SOURCE LINES 42-62 After importing the data, we select the data we want for our study. For the load-displacement curve objective, we want all time steps up to 92.5% of peak load past peak load. These data are selected for the ``synthetic_data`` object below using NumPy array slicing and tools. We do this because we only run the simulation until its load has dropped to 92.5% of peak load after peak load. As stated previously, this is done for model robustness and to reduce simulation time. For certain parameters in the available parameter space, peak load will occur early in the displacement space and the model will not be able to run to the expected displacement. With adaptive time stepping, the model will run for an extended period without significant progress and use up valuable resources. We force the model to exit to avoid this. The discontinuity this introduces is unavoidable as the model cannot run successfully for any set of input parameters. .. GENERATED FROM PYTHON SOURCE LINES 62-68 .. code-block:: Python peak_load_arg = np.argmax(synthetic_data["load"]) desired_arg = np.argmin(np.abs(synthetic_data["load"]\ [peak_load_arg:]-np.max(synthetic_data["load"])*0.925)) synthetic_data = synthetic_data[:desired_arg+1+peak_load_arg] .. GENERATED FROM PYTHON SOURCE LINES 69-72 With the data imported and selected, we plot the data to verify our data manipulation. .. GENERATED FROM PYTHON SOURCE LINES 72-75 .. code-block:: Python dc = DataCollection("data", synthetic_data) dc.plot("displacement", "load") .. image-sg:: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_001.png :alt: matcal_default_state :srcset: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 76-84 After importing and preparing the data, we create the model that will be used to simulate the characterization test. We will use a :class:`~matcal.sierra.models.UserDefinedSierraModel` for this example. We setup the model input to require an external SierraSM material model input file. We create it next using python string and file tools. .. GENERATED FROM PYTHON SOURCE LINES 84-110 .. code-block:: Python mat_file_string = """begin material test_material density = 1 begin parameters for model hill_plasticity youngs modulus = {elastic_modulus*1e9} poissons ratio = {poissons} yield_stress = {yield_stress*1e6} hardening model = voce hardening modulus = {A*1e6} exponential coefficient = {n} coordinate system = rectangular_coordinate_system R11 = {R11} R22 = {R22} R33 = {R33} R12 = {R12} R23 = {R23} R31 = {R31} end end """ with open("modular_plasticity.inc", 'w') as fn: fn.write(mat_file_string) .. GENERATED FROM PYTHON SOURCE LINES 111-125 With the material file created, the model can be instantiated. We provide the :class:`~matcal.sierra.models.UserDefinedSierraModel` with the correct user supplied input deck and mesh. For this model, we use ``adagio`` as the simulation solid mechanics code. Next, we use the appropriate model methods to setup the model for the study. Most importantly we pass the correct model constants to it and provide the model with the correct results model output information. The model constants passed to the model are the uncalibrated parameters described in :ref:`Full-field Verification Problem Material Model`. .. GENERATED FROM PYTHON SOURCE LINES 125-140 .. code-block:: Python model = UserDefinedSierraModel("adagio", "synthetic_data_files/test_model_input_reduced_output.i", "synthetic_data_files/test_mesh.g", "modular_plasticity.inc") model.set_name("test_model") model.add_constants(elastic_modulus=200, poissons=0.27, R22=1.0, R33=0.9, R23=1.0, R31=1.0) model.read_full_field_data("surf_results.e") from site_matcal.sandia.computing_platforms import is_sandia_cluster, get_sandia_computing_platform from site_matcal.sandia.tests.utilities import MATCAL_WCID num_cores=96 if is_sandia_cluster(): platform = get_sandia_computing_platform() num_cores = platform.get_processors_per_node() model.run_in_queue(MATCAL_WCID, 0.5) model.continue_when_simulation_fails() model.set_number_of_cores(num_cores) .. GENERATED FROM PYTHON SOURCE LINES 141-152 We now create the objective that will be used for the calibration. The independent variable is the "displacement" and the calibration residual is determined from the "load" result. The ``right=0`` informs the objective to provide a zero value for loads if it is forced to extrapolate. This occurs when the simulation plastically localizes and exits before its displacement reaches the maximum displacement of the synthetic data. It contributes to the observed objective discontinuity. .. GENERATED FROM PYTHON SOURCE LINES 152-155 .. code-block:: Python load_objective = CurveBasedInterpolatedObjective("displacement", "load", right=0) load_objective.set_name("load_objective") .. GENERATED FROM PYTHON SOURCE LINES 156-165 We then create the material model input parameters for the study. We provide realistic bounds that one may expect for an austenitic stainless steel based on our experience with the material. This results in an initial point far from the true values used for the synthetic data generation and is a stressing test for a local gradient based method. .. GENERATED FROM PYTHON SOURCE LINES 165-173 .. code-block:: Python Y = Parameter("yield_stress", 100, 500.0) A = Parameter("A", 100, 4000) n = Parameter("n", 1, 10) R11 = Parameter("R11", 0.8, 1.1) R12 = Parameter("R12", 0.8, 1.1) param_collection = ParameterCollection("Hill48 in-plane", Y, A, n, R11, R12) .. GENERATED FROM PYTHON SOURCE LINES 174-181 Finally, we create the calibration study and pass the parameters relevant to the study during its initialization. We then set the total cores it can use locally and pass the data, model and objective to it as an evaluation set. .. GENERATED FROM PYTHON SOURCE LINES 181-189 .. code-block:: Python study = GradientCalibrationStudy(param_collection) study.set_results_storage_options(results_save_frequency=len(param_collection)+1) study.set_core_limit(100) study.add_evaluation_set(model, load_objective, synthetic_data) study.set_working_directory("load_disp_cal_initial", remove_existing=True) study.set_step_size(1e-4) study.do_not_save_evaluation_cache() .. GENERATED FROM PYTHON SOURCE LINES 190-191 Next we launch the study save the results. .. GENERATED FROM PYTHON SOURCE LINES 191-193 .. code-block:: Python results = study.launch() .. GENERATED FROM PYTHON SOURCE LINES 194-197 When the study completes, we extract the calibrated parameters and evaluate the error. .. GENERATED FROM PYTHON SOURCE LINES 197-211 .. code-block:: Python calibrated_params = results.best.to_dict() print(calibrated_params) goal_results = {"yield_stress":200, "A":1500, "n":2, "R11":0.95, "R12":0.85} def pe(result, goal): return (result-goal)/goal*100 for param in goal_results.keys(): print(f"Parameter {param} error: {pe(calibrated_params[param], goal_results[param])}") .. rst-class:: sphx-glr-script-out .. code-block:: none OrderedDict({'yield_stress': 201.38720848, 'A': 1481.7593516, 'n': 1.9106662899, 'R11': 1.099055052, 'R12': 0.95279046881}) Parameter yield_stress error: 0.6936042399999991 Parameter A error: -1.2160432266666703 Parameter n error: -4.466685505000001 Parameter R11 error: 15.690005473684213 Parameter R12 error: 12.092996330588234 .. GENERATED FROM PYTHON SOURCE LINES 212-223 These error's are much higher than desired for a successful calibration. This is expected as the problem was designed to have non-unique solutions when calibrating only to the load-displacement curves. Using MatCal's standard plot, we can see that the load-displacement curve matches quite well. In the follow-on, examples we will show how adding full-field data improves results and how the different full-field methods perform. .. GENERATED FROM PYTHON SOURCE LINES 223-231 .. code-block:: Python import os init_dir = os.getcwd() os.chdir("load_disp_cal_initial") make_standard_plots("displacement") os.chdir(init_dir) # sphinx_gallery_thumbnail_number = 2 .. rst-class:: sphx-glr-horizontal * .. image-sg:: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_002.png :alt: plot b standard calibration verification :srcset: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_002.png :class: sphx-glr-multi-img * .. image-sg:: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_003.png :alt: plot b standard calibration verification :srcset: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_003.png :class: sphx-glr-multi-img * .. image-sg:: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_004.png :alt: plot b standard calibration verification :srcset: /full_field_study_verification_examples/images/sphx_glr_plot_b_standard_calibration_verification_004.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (475 minutes 17.623 seconds) .. _sphx_glr_download_full_field_study_verification_examples_plot_b_standard_calibration_verification.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_b_standard_calibration_verification.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_b_standard_calibration_verification.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_b_standard_calibration_verification.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_