Skip to content

Note

Click here to download the full example code

Usage of the model-versus-data code verification tool on a Finite-Element (Abaqus) model

Check an Abaqus cantilever beam model versus a reference dataset with the 'CodeVerificationAgainstData' tool.

from __future__ import annotations

import logging

from gemseo.datasets.io_dataset import IODataset
from gemseo.utils.directory_creator import DirectoryNamingMethod

from vimseo import EXAMPLE_RUNS_DIR
from vimseo.api import activate_logger
from vimseo.api import create_model
from vimseo.core.model_settings import IntegratedModelSettings
from vimseo.tools.verification.verification_vs_data import CodeVerificationAgainstData

We first define the logger level:

activate_logger(level=logging.INFO)

Then we create the model to verify:

model_name = "BendingTestAnalytical"
load_case = "Cantilever"
model = create_model(
    model_name,
    load_case,
    model_options=IntegratedModelSettings(
        directory_archive_root=EXAMPLE_RUNS_DIR / "archive/verification_vs_data",
        directory_scratch_root=EXAMPLE_RUNS_DIR / "scratch/verification_vs_data",
        cache_file_path=EXAMPLE_RUNS_DIR
        / f"caches/verification_vs_data/{model_name}_{load_case}_cache.hdf",
    ),
)

Out:

    INFO - 16:51:59: Found 2 entries in the cache file : /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/caches/verification_vs_data/BendingTestAnalytical_Cantilever_cache.hdf node : node

We also need a reference dataset. Here we do it programmatically, but we can also create it from a csv file: ``

reference_data = IODataset().from_array(
    data=[[10.0, 10.0, -4.0, -12.0], [15.0, 10.0, -6.0, -40.0]],
    variable_names=["height", "width", "maximum_dplt", "reaction_forces"],
    variable_names_to_group_names={
        "height": "inputs",
        "width": "inputs",
        "maximum_dplt": "outputs",
        "reaction_forces": "outputs",
    },
)

All inputs to the verification are now available. We create the verification tool we are interested in.

verificator = CodeVerificationAgainstData(
    directory_naming_method=DirectoryNamingMethod.NUMBERED,
    working_directory="CodeVerificationAgainstData_results",
)

# The options can be modified.
# Alternatively, options can be passed as keyword arguments to
# ``CodeVerificationAgainstModelFromParameterSpace()`` constructor.
verificator.options["metric_names"] = [
    "SquaredErrorMetric",
    "RelativeErrorMetric",
    "AbsoluteErrorMetric",
]

verificator.execute(
    model=model,
    reference_data=reference_data,
    output_names=["maximum_dplt", "reaction_forces"],
    description={
        "title": "Verification of a cantilever analytic beam for a variation of beam height.",
        "element_wise": ["Small height value", "High height value"],
    },
)

Out:

    INFO - 16:51:59: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/03_verification_vs_data/CodeVerificationAgainstData_results
    INFO - 16:51:59: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/03_verification_vs_data/CodeVerificationAgainstData_results/CustomDOETool
    INFO - 16:51:59: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/03_verification_vs_data/CodeVerificationAgainstData_results/CustomDOETool
    INFO - 16:51:59:  
    INFO - 16:51:59: *** Start DOEScenario execution ***
    INFO - 16:51:59: DOEScenario
    INFO - 16:51:59:    Disciplines: Model BendingTestAnalytical:  An analytical model for the bending of a parallelepipedic beam
    INFO - 16:51:59: 
    INFO - 16:51:59: Load case:
    INFO - 16:51:59:    Load case Cantilever: A cantilever load case.
    INFO - 16:51:59:    
    INFO - 16:51:59:    Boundary condition variables:
    INFO - 16:51:59:    ['imposed_dplt', 'relative_dplt_location']
    INFO - 16:51:59:    
    INFO - 16:51:59:    Plot parameters:
    INFO - 16:51:59:    {
    INFO - 16:51:59:     "curves": []
    INFO - 16:51:59: }
    INFO - 16:51:59:    Load:
    INFO - 16:51:59:    Load(direction='', sign='', type='')
    INFO - 16:51:59: 
    INFO - 16:51:59: Default values:
    INFO - 16:51:59:    
    INFO - 16:51:59:    Default geometrical variables:
    INFO - 16:51:59:    {"height": [40.0], "length": [600.0], "width": [30.0]}
    INFO - 16:51:59:    
    INFO - 16:51:59:    Default numerical variables:
    INFO - 16:51:59:    {}
    INFO - 16:51:59:    
    INFO - 16:51:59:    Default boundary conditions variables:
    INFO - 16:51:59:    {"imposed_dplt": [-5.0], "relative_dplt_location": [1.0]}
    INFO - 16:51:59:    
    INFO - 16:51:59:    Default material variables:
    INFO - 16:51:59:    {"nu_p": [0.3], "young_modulus": [210000.0]}
    INFO - 16:51:59: model_inputs:
    INFO - 16:51:59:    [
    INFO - 16:51:59:     "length",
    INFO - 16:51:59:     "width",
    INFO - 16:51:59:     "height",
    INFO - 16:51:59:     "imposed_dplt",
    INFO - 16:51:59:     "relative_dplt_location",
    INFO - 16:51:59:     "young_modulus",
    INFO - 16:51:59:     "nu_p"
    INFO - 16:51:59: ]
    INFO - 16:51:59: model_outputs:
    INFO - 16:51:59:    [
    INFO - 16:51:59:     "reaction_forces",
    INFO - 16:51:59:     "maximum_dplt",
    INFO - 16:51:59:     "dplt_grid",
    INFO - 16:51:59:     "location_max_dplt",
    INFO - 16:51:59:     "dplt",
    INFO - 16:51:59:     "moment",
    INFO - 16:51:59:     "moment_grid",
    INFO - 16:51:59:     "dplt_at_force_location",
    INFO - 16:51:59:     "error_code",
    INFO - 16:51:59:     "model",
    INFO - 16:51:59:     "load_case",
    INFO - 16:51:59:     "description",
    INFO - 16:51:59:     "job_name",
    INFO - 16:51:59:     "persistent_result_files",
    INFO - 16:51:59:     "n_cpus",
    INFO - 16:51:59:     "date",
    INFO - 16:51:59:     "cpu_time",
    INFO - 16:51:59:     "user",
    INFO - 16:51:59:     "machine",
    INFO - 16:51:59:     "vims_git_version",
    INFO - 16:51:59:     "directory_archive_root",
    INFO - 16:51:59:     "directory_archive_job",
    INFO - 16:51:59:     "directory_scratch_root",
    INFO - 16:51:59:     "directory_scratch_job"
    INFO - 16:51:59: ]
    INFO - 16:51:59:    MDO formulation: DisciplinaryOpt
    INFO - 16:51:59: Optimization problem:
    INFO - 16:51:59:    minimize maximum_dplt(height, width)
    INFO - 16:51:59:    with respect to height, width
    INFO - 16:51:59:    over the design space:
    INFO - 16:51:59:       +--------+-------------+-------+-------------+-------+
    INFO - 16:51:59:       | Name   | Lower bound | Value | Upper bound | Type  |
    INFO - 16:51:59:       +--------+-------------+-------+-------------+-------+
    INFO - 16:51:59:       | height |     -inf    |  None |     inf     | float |
    INFO - 16:51:59:       | width  |     -inf    |  None |     inf     | float |
    INFO - 16:51:59:       +--------+-------------+-------+-------------+-------+
    INFO - 16:51:59: Solving optimization problem with algorithm CustomDOE:
    INFO - 16:51:59:     50%|█████     | 1/2 [00:00<00:00, 34.34 it/sec, obj=-5]
    INFO - 16:51:59:    100%|██████████| 2/2 [00:00<00:00, 39.65 it/sec, obj=-5]
    INFO - 16:51:59: Optimization result:
    INFO - 16:51:59:    Optimizer info:
    INFO - 16:51:59:       Status: None
    INFO - 16:51:59:       Message: None
    INFO - 16:51:59:       Number of calls to the objective function by the optimizer: 2
    INFO - 16:51:59:    Solution:
    INFO - 16:51:59:       Objective: -5.0000000000000036
    INFO - 16:51:59:       Design space:
    INFO - 16:51:59:          +--------+-------------+-------+-------------+-------+
    INFO - 16:51:59:          | Name   | Lower bound | Value | Upper bound | Type  |
    INFO - 16:51:59:          +--------+-------------+-------+-------------+-------+
    INFO - 16:51:59:          | height |     -inf    |   10  |     inf     | float |
    INFO - 16:51:59:          | width  |     -inf    |   10  |     inf     | float |
    INFO - 16:51:59:          +--------+-------------+-------+-------------+-------+
    INFO - 16:51:59: *** End DOEScenario execution (time: 0:00:00.056774) ***

VerificationResult(metadata=ToolResultMetadata(generic={'datetime': '11-05-2026_16-51-59', 'version': '0.1.7.dev11+g45528c259'}, misc={}, settings={'input_names': [], 'output_names': ['maximum_dplt', 'reaction_forces'], 'metric_names': ['SquaredErrorMetric', 'RelativeErrorMetric', 'AbsoluteErrorMetric'], 'description': {'title': 'Verification of a cantilever analytic beam for a variation of beam height.', 'element_wise': ['Small height value', 'High height value']}}, report={}, model=ModelDescription(name='BendingTestAnalytical', summary=' An analytical model for the bending of a parallelepipedic beam', load_case=Beam_Cantilever(name='Cantilever', domain='Beam', summary='A cantilever load case.', plot_parameters=PlotParameters(curves=[]), bc_variable_names=['imposed_dplt', 'relative_dplt_location'], load=Load(direction='', sign='', type='')), dataflow={'model_inputs': ['length', 'width', 'height', 'imposed_dplt', 'relative_dplt_location', 'young_modulus', 'nu_p'], 'model_outputs': ['reaction_forces', 'maximum_dplt', 'dplt_grid', 'location_max_dplt', 'dplt', 'moment', 'moment_grid', 'dplt_at_force_location', 'error_code', 'model', 'load_case', 'description', 'job_name', 'persistent_result_files', 'n_cpus', 'date', 'cpu_time', 'user', 'machine', 'vims_git_version', 'directory_archive_root', 'directory_archive_job', 'directory_scratch_root', 'directory_scratch_job'], 'PreBendingTestAnalytical_Cantilever': {'inputs': ['length', 'width', 'height', 'imposed_dplt', 'relative_dplt_location', 'young_modulus', 'nu_p'], 'outputs': ['imposed_dplt_location', 'quadratic_moment', 'reaction_forces', 'moment', 'moment_grid', 'solver', 'boundary']}, 'RunBendingTestAnalytical': {'inputs': ['imposed_dplt_location', 'quadratic_moment', 'reaction_forces', 'moment', 'moment_grid', 'solver', 'boundary', 'length', 'width', 'height', 'imposed_dplt', 'relative_dplt_location', 'young_modulus', 'nu_p'], 'outputs': ['dplt', 'dplt_grid', 'moment', 'moment_grid', 'imposed_dplt_location', 'reaction_forces']}, 'PostBendingTestAnalytical_Cantilever': {'inputs': ['dplt', 'dplt_grid', 'moment', 'moment_grid', 'imposed_dplt_location', 'reaction_forces'], 'outputs': ['reaction_forces', 'maximum_dplt', 'dplt_grid', 'location_max_dplt', 'dplt', 'moment', 'moment_grid', 'dplt_at_force_location', 'error_code']}, 'subroutine_names': []}, default_inputs={<InputGroupNames.NUMERICAL_VARS: 'numerical variables'>: {}, <InputGroupNames.BC_VARS: 'boundary conditions variables'>: {'imposed_dplt': [-5.0], 'relative_dplt_location': [1.0]}, <InputGroupNames.GEOMETRICAL_VARS: 'geometrical variables'>: {'length': [600.0], 'width': [30.0], 'height': [40.0]}, <InputGroupNames.MATERIAL_VARS: 'material variables'>: {'young_modulus': [210000.0], 'nu_p': [0.3]}}, curves=[('dplt_grid', 'dplt'), ('moment_grid', 'moment')], verbose=False)), simulation_and_reference=GROUP     inputs         outputs                                 Reference                
VARIABLE  height width  cpu_time maximum_dplt reaction_forces maximum_dplt reaction_forces
COMPONENT      0     0         0            0               0            0               0
0           10.0  10.0  0.021409         -5.0      -12.152778         -4.0           -12.0
1           15.0  10.0  0.003780         -5.0      -41.015625         -6.0           -40.0, element_wise_metrics=GROUP     SquaredErrorMetric                 RelativeErrorMetric  ... AbsoluteErrorMetric inputs      
VARIABLE        maximum_dplt reaction_forces        maximum_dplt  ...     reaction_forces height width
COMPONENT                  0               0                   0  ...                   0      0     0
0                        1.0        0.023341            0.250000  ...            0.152778   10.0  10.0
1                        1.0        1.031494            0.166667  ...            1.015625   15.0  10.0

[2 rows x 8 columns], integrated_metrics={'SquaredErrorMetric': {'maximum_dplt': 1.0, 'reaction_forces': 0.5274175950038581}, 'RelativeErrorMetric': {'maximum_dplt': 0.2083333332881946, 'reaction_forces': 0.019061053239892913}, 'AbsoluteErrorMetric': {'maximum_dplt': 1.0, 'reaction_forces': 0.5842013888888893}}, description={'title': 'Verification of a cantilever analytic beam for a variation of beam height.', 'element_wise': ['Small height value', 'High height value']})

The result contains the error metrics:

verificator.result.integrated_metrics

Out:

{'SquaredErrorMetric': {'maximum_dplt': 1.0, 'reaction_forces': 0.5274175950038581}, 'RelativeErrorMetric': {'maximum_dplt': 0.2083333332881946, 'reaction_forces': 0.019061053239892913}, 'AbsoluteErrorMetric': {'maximum_dplt': 1.0, 'reaction_forces': 0.5842013888888893}}

And saved on disk, together with its metadata:

verificator.save_results()

Out:

    INFO - 16:51:59: Saving result to /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/03_verification_vs_data/CodeVerificationAgainstData_results/CodeVerificationAgainstData_result.hdf5
    INFO - 16:51:59: Saving result to /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/03_verification_vs_data/CodeVerificationAgainstData_results/CustomDOETool/CustomDOETool_result.hdf5

The saved results can be loaded in a dedicated dashboard to be explored. The dashboard is opened by typing dashboard_verification in a terminal, and selecting the tab Comparison case.

The results can also be plotted from the Python API. It shows the scatter matrix of the inputs:

figures = verificator.plot_results(
    verificator.result,
    "RelativeErrorMetric",
    "reaction_forces",
    save=False,
    show=True,
    directory_path=verificator.working_directory,
)

plot bending test vs data

Out:

/home/sebastien.bocquet/PycharmProjects/vimseo/.tox/doc/lib/python3.11/site-packages/pandas/plotting/_matplotlib/misc.py:100: UserWarning:

Attempting to set identical low and high xlims makes transformation singular; automatically expanding.

/home/sebastien.bocquet/PycharmProjects/vimseo/.tox/doc/lib/python3.11/site-packages/pandas/plotting/_matplotlib/misc.py:101: UserWarning:

Attempting to set identical low and high ylims makes transformation singular; automatically expanding.

/home/sebastien.bocquet/PycharmProjects/vimseo/.tox/doc/lib/python3.11/site-packages/pandas/plotting/_matplotlib/misc.py:91: UserWarning:

Attempting to set identical low and high xlims makes transformation singular; automatically expanding.

/home/sebastien.bocquet/PycharmProjects/vimseo/.tox/doc/lib/python3.11/site-packages/gemseo/utils/matplotlib_figure.py:59: UserWarning:

FigureCanvasAgg is non-interactive, and thus cannot be shown

    INFO - 16:51:59: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/03_verification_vs_data/CodeVerificationAgainstData_results

and an histogram of the errors:

figures["error_metric_histogram"]

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

Download Python source code: plot_bending_test_vs_data.py

Download Jupyter notebook: plot_bending_test_vs_data.ipynb

Gallery generated by mkdocs-gallery