Skip to content

Note

Click here to download the full example code

An example of stochastic validation point

from __future__ import annotations

import logging
from pathlib import Path

from gemseo.datasets.io_dataset import IODataset
from pandas import read_csv

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.io.space_io import SpaceToolFileIO
from vimseo.material.material import Material
from vimseo.material_lib import MATERIAL_LIB_DIR
from vimseo.storage_management.base_storage_manager import PersistencyPolicy
from vimseo.tools.space.space_tool_result import SpaceToolResult
from vimseo.tools.validation.validation_point import NominalValuesOutputType
from vimseo.tools.validation.validation_point import StochasticValidationPoint
from vimseo.tools.validation.validation_point import StochasticValidationPointInputs
from vimseo.tools.validation.validation_point import StochasticValidationPointSettings
from vimseo.tools.validation.validation_point import read_nominal_values
from vimseo.utilities.datasets import GROUP_SEPARATORS
from vimseo.utilities.datasets import SEP
from vimseo.utilities.datasets import dataframe_to_dataset
from vimseo.utilities.generate_validation_reference import Bias
from vimseo.utilities.generate_validation_reference import (
    generate_reference_from_parameter_space,
)

activate_logger(level=logging.INFO)

First we generate synthetic reference data, using an analytical bending test model, and bias the output of interest by 5 \%.

model_name = "BendingTestAnalytical"
load_case = "Cantilever"
target_model = create_model(
    model_name,
    load_case,
    model_options=IntegratedModelSettings(
        directory_archive_persistency=PersistencyPolicy.DELETE_ALWAYS,
        directory_scratch_persistency=PersistencyPolicy.DELETE_ALWAYS,
        directory_archive_root=EXAMPLE_RUNS_DIR / "archive/validation_point",
        directory_scratch_root=EXAMPLE_RUNS_DIR / "scratch/validation_point",
        cache_file_path=EXAMPLE_RUNS_DIR
        / f"caches/validation_point/target_{model_name}_{load_case}_cache.hdf",
    ),
)
target_model.cache = None
reference_dataset_cantilever = generate_reference_from_parameter_space(
    target_model,
    SpaceToolFileIO()
    .read(file_name="bending_test_validation_input_space.json")
    .parameter_space,
    n_samples=6,
    input_names=["width", "height", "imposed_dplt"],
    output_names=["reaction_forces", "maximum_dplt"],
    outputs_to_bias={"reaction_forces": Bias(mult_factor=1.05)},
    additional_name_to_data={"nominal_length": 600.0, "batch": 1},
)
reference_dataset_cantilever.to_csv(
    "reference_validation_bending_test_cantilever.csv", sep=SEP
)
print("The reference data: ", reference_dataset_cantilever)

Out:

/home/sebastien.bocquet/PycharmProjects/vimseo/.tox/doc/lib/python3.11/site-packages/pydantic/main.py:209: DeprecationWarning:

Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)

    INFO - 16:52:02: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/CustomDOETool/12
    INFO - 16:52:02:  
    INFO - 16:52:02: *** Start DOEScenario execution ***
    INFO - 16:52:02: DOEScenario
    INFO - 16:52:02:    Disciplines: Model BendingTestAnalytical:  An analytical model for the bending of a parallelepipedic beam
    INFO - 16:52:02: 
    INFO - 16:52:02: Load case:
    INFO - 16:52:02:    Load case Cantilever: A cantilever load case.
    INFO - 16:52:02:    
    INFO - 16:52:02:    Boundary condition variables:
    INFO - 16:52:02:    ['imposed_dplt', 'relative_dplt_location']
    INFO - 16:52:02:    
    INFO - 16:52:02:    Plot parameters:
    INFO - 16:52:02:    {
    INFO - 16:52:02:     "curves": []
    INFO - 16:52:02: }
    INFO - 16:52:02:    Load:
    INFO - 16:52:02:    Load(direction='', sign='', type='')
    INFO - 16:52:02: 
    INFO - 16:52:02: Default values:
    INFO - 16:52:02:    
    INFO - 16:52:02:    Default geometrical variables:
    INFO - 16:52:02:    {"height": [40.0], "length": [600.0], "width": [30.0]}
    INFO - 16:52:02:    
    INFO - 16:52:02:    Default numerical variables:
    INFO - 16:52:02:    {}
    INFO - 16:52:02:    
    INFO - 16:52:02:    Default boundary conditions variables:
    INFO - 16:52:02:    {"imposed_dplt": [-5.0], "relative_dplt_location": [1.0]}
    INFO - 16:52:02:    
    INFO - 16:52:02:    Default material variables:
    INFO - 16:52:02:    {"nu_p": [0.3], "young_modulus": [210000.0]}
    INFO - 16:52:02: model_inputs:
    INFO - 16:52:02:    [
    INFO - 16:52:02:     "length",
    INFO - 16:52:02:     "width",
    INFO - 16:52:02:     "height",
    INFO - 16:52:02:     "imposed_dplt",
    INFO - 16:52:02:     "relative_dplt_location",
    INFO - 16:52:02:     "young_modulus",
    INFO - 16:52:02:     "nu_p"
    INFO - 16:52:02: ]
    INFO - 16:52:02: model_outputs:
    INFO - 16:52:02:    [
    INFO - 16:52:02:     "reaction_forces",
    INFO - 16:52:02:     "maximum_dplt",
    INFO - 16:52:02:     "dplt_grid",
    INFO - 16:52:02:     "location_max_dplt",
    INFO - 16:52:02:     "dplt",
    INFO - 16:52:02:     "moment",
    INFO - 16:52:02:     "moment_grid",
    INFO - 16:52:02:     "dplt_at_force_location",
    INFO - 16:52:02:     "error_code",
    INFO - 16:52:02:     "model",
    INFO - 16:52:02:     "load_case",
    INFO - 16:52:02:     "description",
    INFO - 16:52:02:     "job_name",
    INFO - 16:52:02:     "persistent_result_files",
    INFO - 16:52:02:     "n_cpus",
    INFO - 16:52:02:     "date",
    INFO - 16:52:02:     "cpu_time",
    INFO - 16:52:02:     "user",
    INFO - 16:52:02:     "machine",
    INFO - 16:52:02:     "vims_git_version",
    INFO - 16:52:02:     "directory_archive_root",
    INFO - 16:52:02:     "directory_archive_job",
    INFO - 16:52:02:     "directory_scratch_root",
    INFO - 16:52:02:     "directory_scratch_job"
    INFO - 16:52:02: ]
    INFO - 16:52:02:    MDO formulation: DisciplinaryOpt
    INFO - 16:52:02: Optimization problem:
    INFO - 16:52:02:    minimize reaction_forces(width, height, imposed_dplt)
    INFO - 16:52:02:    with respect to height, imposed_dplt, width
    INFO - 16:52:02:    over the design space:
    INFO - 16:52:02:       +--------------+-------------+-------+-------------+-------+
    INFO - 16:52:02:       | Name         | Lower bound | Value | Upper bound | Type  |
    INFO - 16:52:02:       +--------------+-------------+-------+-------------+-------+
    INFO - 16:52:02:       | width        |     -inf    |  None |     inf     | float |
    INFO - 16:52:02:       | height       |     -inf    |  None |     inf     | float |
    INFO - 16:52:02:       | imposed_dplt |     -inf    |  None |     inf     | float |
    INFO - 16:52:02:       +--------------+-------------+-------+-------------+-------+
    INFO - 16:52:02: Solving optimization problem with algorithm CustomDOE:
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02:     17%|█▋        | 1/6 [00:00<00:00, 30.20 it/sec, obj=-2.18e+3]
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02:     33%|███▎      | 2/6 [00:00<00:00, 44.68 it/sec, obj=-2.17e+3]
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02:     50%|█████     | 3/6 [00:00<00:00, 54.41 it/sec, obj=-2.35e+3]
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02:     67%|██████▋   | 4/6 [00:00<00:00, 61.15 it/sec, obj=-2.28e+3]
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02:     83%|████████▎ | 5/6 [00:00<00:00, 66.31 it/sec, obj=-2.32e+3]
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02: Current root directory of job directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point.
    INFO - 16:52:02: Removing job directory: /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/archive/validation_point/BendingTestAnalytical/Cantilever/9
    INFO - 16:52:02:    100%|██████████| 6/6 [00:00<00:00, 70.09 it/sec, obj=-2e+3]
    INFO - 16:52:02: Optimization result:
    INFO - 16:52:02:    Optimizer info:
    INFO - 16:52:02:       Status: None
    INFO - 16:52:02:       Message: None
    INFO - 16:52:02:       Number of calls to the objective function by the optimizer: 6
    INFO - 16:52:02:    Solution:
    INFO - 16:52:02:       Objective: -2352.1728158748174
    INFO - 16:52:02:       Design space:
    INFO - 16:52:02:          +--------------+-------------+------------------+-------------+-------+
    INFO - 16:52:02:          | Name         | Lower bound |      Value       | Upper bound | Type  |
    INFO - 16:52:02:          +--------------+-------------+------------------+-------------+-------+
    INFO - 16:52:02:          | width        |     -inf    | 30.408447265625  |     inf     | float |
    INFO - 16:52:02:          | height       |     -inf    | 39.3721923828125 |     inf     | float |
    INFO - 16:52:02:          | imposed_dplt |     -inf    |  -5.21435546875  |     inf     | float |
    INFO - 16:52:02:          +--------------+-------------+------------------+-------------+-------+
    INFO - 16:52:02: *** End DOEScenario execution (time: 0:00:00.089631) ***
The reference data:         width     height  imposed_dplt  maximum_dplt  reaction_forces  nominal_length  batch
0  30.052246  38.528564     -5.212891     -5.212891     -2286.645728           600.0      1
1  31.221924  38.574341     -4.972900     -4.972900     -2274.363156           600.0      1
2  30.408447  39.372192     -5.214355     -5.214355     -2469.781457           600.0      1
3  29.725220  39.985840     -4.940674     -4.940674     -2396.209442           600.0      1
4  30.032349  39.940186     -4.987549     -4.987549     -2435.575198           600.0      1
5  29.370850  38.490967     -4.919556     -4.919556     -2102.876165           600.0      1

The objective is to validate a model for a new material. Let's create a model to validate:

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

Out:

    INFO - 16:52:02: Found 8 entries in the cache file : /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/caches/validation_point/BendingTestAnalytical_Cantilever_cache.hdf node : node

And the material, which defines probability distributions for its properties. It is typically obtained from a calibration.

material = Material.from_json(MATERIAL_LIB_DIR / "Ta6v.json")
print("The stochastic material: ", material)

Out:

The stochastic material:  Ta6v
Material relations:

   Ta6v_elastic_iso
   young_modulus
      Default value: 210000.0
      Distribution:
         Normal
         Parameters:
         {
          "loc": 0.0,
          "location": 0.0,
          "lower": -1000000000000.0,
          "lower_bound": 190000.0,
          "mean": 0.0,
          "mode": 0.0,
          "mu": 210000.0,
          "name": "Normal",
          "rate": 1.0,
          "scale": 1.0,
          "shape": 1.0,
          "sigma": 100.0,
          "upper": 1000000000000.0,
          "upper_bound": 230000.0
}

   nu_p
      Default value: 0.3
      Distribution:
         Normal
         Parameters:
         {
          "loc": 0.0,
          "location": 0.0,
          "lower": -1000000000000.0,
          "lower_bound": -1000000000000.0,
          "mean": 0.0,
          "mode": 0.0,
          "mu": 0.3,
          "name": "Normal",
          "rate": 1.0,
          "scale": 1.0,
          "shape": 1.0,
          "sigma": 0.02,
          "upper": 1000000000000.0,
          "upper_bound": 1000000000000.0
}

And the measured quantities of interest

measured_inputs = ["width", "height", "imposed_dplt"]
measured_outputs = ["reaction_forces"]

Since reference data are referenced by batches, we can select a batch to perform the validation only regarding this batch:

batch = 1

Then we define the path to the reference data

csv_path = "reference_validation_bending_test_cantilever.csv"

and the nominal inputs at which the validation point is performed. The read_nominal_values function allows to read the nominal values in the reference data, using averaging over the repeats for a given master variable:

nominal_values = read_nominal_values(
    "batch",
    csv_path=csv_path,
    master_value=batch,
    additional_names=["nominal_length"],
    name_remapping={"nominal_length": "length"},
    output_type=NominalValuesOutputType.DICTIONARY,
)

And finally we set the nominal inputs from the material. Indeed, all material properties may not be stochastic (a distribution is not necessarily defined). As a result, we need to set the model default inputs to the deterministic property values. It is done through the nominal inputs:

nominal_values.update(material.get_values_as_dict())

The reference samples are then defined from the csv file containing the measured data. First, the data are filtered to retain only the considered batch:

df = read_csv(
    csv_path,
    delimiter=SEP,
)
df = df[df["batch"] == batch]

Then the reference data are filtered to retain only the measured quantities, and converted to a GEMSEO Dataset:

df = df[measured_inputs + measured_outputs]
variable_names_to_group_names = dict.fromkeys(measured_inputs, IODataset.INPUT_GROUP)
variable_names_to_group_names.update(
    dict.fromkeys(measured_outputs, IODataset.OUTPUT_GROUP)
)
for name, group_name in variable_names_to_group_names.items():
    df.rename(
        columns={name: f"{name}{GROUP_SEPARATORS[0]}{group_name}{GROUP_SEPARATORS[1]}"},
        inplace=True,
    )
measured_data = dataframe_to_dataset(df)
print("The measured data as a GEMSEO Dataset: ", measured_data)

Out:

/home/sebastien.bocquet/PycharmProjects/vimseo/src/vimseo/utilities/datasets.py:376: FutureWarning:

Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`

/home/sebastien.bocquet/PycharmProjects/vimseo/src/vimseo/utilities/datasets.py:376: FutureWarning:

Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`

/home/sebastien.bocquet/PycharmProjects/vimseo/src/vimseo/utilities/datasets.py:376: FutureWarning:

Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`

/home/sebastien.bocquet/PycharmProjects/vimseo/src/vimseo/utilities/datasets.py:376: FutureWarning:

Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`

The measured data as a GEMSEO Dataset:  GROUP         inputs                                 outputs
VARIABLE       width     height imposed_dplt reaction_forces
COMPONENT          0          0            0               0
0          30.052246  38.528564    -5.212891    -2286.645728
1          31.221924  38.574341    -4.972900    -2274.363156
2          30.408447  39.372192    -5.214355    -2469.781457
3          29.725220  39.985840    -4.940674    -2396.209442
4          30.032349  39.940186    -4.987549    -2435.575198
5          29.370850  38.490967    -4.919556    -2102.876165

The uncertainties coming from unmeasured inputs are then taken into account via the argument uncertain_input_space, to which we pass a parameter space defined from the material. The stochastic validation point can now be created and executed. The model output uncertainty is estimated by sampling the input space with n_samples points.

validation_point_tool = StochasticValidationPoint(
    working_directory=Path(f"{model_name}_{load_case}")
    / f"batch_{batch}_{nominal_values['length']}",
)
validation_point_tool.execute(
    inputs=StochasticValidationPointInputs(
        model=model,
        measured_data=measured_data,
        uncertain_input_space=material.to_parameter_space(),
    ),
    settings=StochasticValidationPointSettings(
        metric_names=[
            "AreaMetric",
            "RelativeAreaMetric",
            "RelativeMeanToMean",
            "AbsoluteRelativeErrorP90",
        ],
        nominal_data=nominal_values,
        n_samples=4,
    ),
)

Out:

/home/sebastien.bocquet/PycharmProjects/vimseo/.tox/doc/lib/python3.11/site-packages/pydantic/main.py:209: DeprecationWarning:

Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)

    INFO - 16:52:02: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]
    INFO - 16:52:02: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]/DOETool
    INFO - 16:52:02: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]/StatisticsTool
    INFO - 16:52:02: Found 8 entries in the cache file : /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/model_runs/caches/validation_point/BendingTestAnalytical_Cantilever_cache.hdf node : node
    INFO - 16:52:03: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]/StatisticsTool
    INFO - 16:52:03: | Set goodness-of-fit criterion: Kolmogorov.
    INFO - 16:52:03: | Set significance level of hypothesis test: 0.05.
    INFO - 16:52:03: Fit different distributions (Uniform, Normal, LogNormal, Exponential, WeibullMin) per variable and compute the goodness-of-fit criterion.
    INFO - 16:52:03: | Fit different distributions for height.
    INFO - 16:52:03: | Fit different distributions for imposed_dplt.
    INFO - 16:52:03: | Fit different distributions for width.
    INFO - 16:52:03: Select the best distribution for each variable.
    INFO - 16:52:03: | The best distribution for height[0] is Normal([39.1487,0.710531]).
    INFO - 16:52:03: | The best distribution for imposed_dplt[0] is WeibullMin([296528,3.38076e+06,-296533]).
    INFO - 16:52:03: | The best distribution for width[0] is Normal([30.1352,0.63646]).
/home/sebastien.bocquet/PycharmProjects/vimseo/.tox/doc/lib/python3.11/site-packages/pydantic/main.py:209: DeprecationWarning:

Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)

    INFO - 16:52:03: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]/DOETool
    INFO - 16:52:03:  
    INFO - 16:52:03: *** Start DOE_BendingTestAnalytical_Cantilever_OT_OPT_LHS_4 execution ***
    INFO - 16:52:03: DOE_BendingTestAnalytical_Cantilever_OT_OPT_LHS_4
    INFO - 16:52:03:    Disciplines: Model BendingTestAnalytical:  An analytical model for the bending of a parallelepipedic beam
    INFO - 16:52:03: 
    INFO - 16:52:03: Load case:
    INFO - 16:52:03:    Load case Cantilever: A cantilever load case.
    INFO - 16:52:03:    
    INFO - 16:52:03:    Boundary condition variables:
    INFO - 16:52:03:    ['imposed_dplt', 'relative_dplt_location']
    INFO - 16:52:03:    
    INFO - 16:52:03:    Plot parameters:
    INFO - 16:52:03:    {
    INFO - 16:52:03:     "curves": []
    INFO - 16:52:03: }
    INFO - 16:52:03:    Load:
    INFO - 16:52:03:    Load(direction='', sign='', type='')
    INFO - 16:52:03: 
    INFO - 16:52:03: Default values:
    INFO - 16:52:03:    
    INFO - 16:52:03:    Default geometrical variables:
    INFO - 16:52:03:    {"height": [39.14868164062504], "length": [600.0], "width": [30.13517252604173]}
    INFO - 16:52:03:    
    INFO - 16:52:03:    Default numerical variables:
    INFO - 16:52:03:    {}
    INFO - 16:52:03:    
    INFO - 16:52:03:    Default boundary conditions variables:
    INFO - 16:52:03:    {"imposed_dplt": [0.0], "relative_dplt_location": [1.0]}
    INFO - 16:52:03:    
    INFO - 16:52:03:    Default material variables:
    INFO - 16:52:03:    {"nu_p": [0.3000000000000006], "young_modulus": [209999.99999999357]}
    INFO - 16:52:03: model_inputs:
    INFO - 16:52:03:    [
    INFO - 16:52:03:     "length",
    INFO - 16:52:03:     "width",
    INFO - 16:52:03:     "height",
    INFO - 16:52:03:     "imposed_dplt",
    INFO - 16:52:03:     "relative_dplt_location",
    INFO - 16:52:03:     "young_modulus",
    INFO - 16:52:03:     "nu_p"
    INFO - 16:52:03: ]
    INFO - 16:52:03: model_outputs:
    INFO - 16:52:03:    [
    INFO - 16:52:03:     "reaction_forces",
    INFO - 16:52:03:     "maximum_dplt",
    INFO - 16:52:03:     "dplt_grid",
    INFO - 16:52:03:     "location_max_dplt",
    INFO - 16:52:03:     "dplt",
    INFO - 16:52:03:     "moment",
    INFO - 16:52:03:     "moment_grid",
    INFO - 16:52:03:     "dplt_at_force_location",
    INFO - 16:52:03:     "error_code",
    INFO - 16:52:03:     "model",
    INFO - 16:52:03:     "load_case",
    INFO - 16:52:03:     "description",
    INFO - 16:52:03:     "job_name",
    INFO - 16:52:03:     "persistent_result_files",
    INFO - 16:52:03:     "n_cpus",
    INFO - 16:52:03:     "date",
    INFO - 16:52:03:     "cpu_time",
    INFO - 16:52:03:     "user",
    INFO - 16:52:03:     "machine",
    INFO - 16:52:03:     "vims_git_version",
    INFO - 16:52:03:     "directory_archive_root",
    INFO - 16:52:03:     "directory_archive_job",
    INFO - 16:52:03:     "directory_scratch_root",
    INFO - 16:52:03:     "directory_scratch_job"
    INFO - 16:52:03: ]
    INFO - 16:52:03:    MDO formulation: DisciplinaryOpt
    INFO - 16:52:03: Optimization problem:
    INFO - 16:52:03:    minimize reaction_forces(young_modulus, nu_p, height, imposed_dplt, width)
    INFO - 16:52:03:    with respect to height, imposed_dplt, nu_p, width, young_modulus
    INFO - 16:52:03:    over the design space:
    INFO - 16:52:03:       +---------------+---------------------------------------------------------------------+--------------------+
    INFO - 16:52:03:       |      Name     |                         Initial distribution                        | Transformation(x)= |
    INFO - 16:52:03:       +---------------+---------------------------------------------------------------------+--------------------+
    INFO - 16:52:03:       | young_modulus |                   Normal(mu=210000.0, sigma=100.0)                  |      Trunc(x)      |
    INFO - 16:52:03:       |      nu_p     |                      Normal(mu=0.3, sigma=0.02)                     |      Trunc(x)      |
    INFO - 16:52:03:       |     height    |             Normal(39.148681640625, 0.7105309088760217)             |      Trunc(x)      |
    INFO - 16:52:03:       |  imposed_dplt | WeibullMin(296528.213874239, 3380757.500085741, -296533.1983889537) |      Trunc(x)      |
    INFO - 16:52:03:       |     width     |            Normal(30.135172526041664, 0.6364601858416962)           |      Trunc(x)      |
    INFO - 16:52:03:       +---------------+---------------------------------------------------------------------+--------------------+
    INFO - 16:52:03: Solving optimization problem with algorithm OT_OPT_LHS:
    INFO - 16:52:03:     25%|██▌       | 1/4 [00:00<00:00, 71.81 it/sec, obj=-2.11e+3]
    INFO - 16:52:03:     50%|█████     | 2/4 [00:00<00:00, 92.82 it/sec, obj=-2.26e+3]
    INFO - 16:52:03:     75%|███████▌  | 3/4 [00:00<00:00, 101.60 it/sec, obj=-2.42e+3]
    INFO - 16:52:03:    100%|██████████| 4/4 [00:00<00:00, 107.25 it/sec, obj=-2.12e+3]
    INFO - 16:52:03: Optimization result:
    INFO - 16:52:03:    Optimizer info:
    INFO - 16:52:03:       Status: None
    INFO - 16:52:03:       Message: None
    INFO - 16:52:03:       Number of calls to the objective function by the optimizer: 4
    INFO - 16:52:03:    Solution:
    INFO - 16:52:03:       Objective: -2422.7340090583752
    INFO - 16:52:03:       Design space:
    INFO - 16:52:03:          +---------------+---------------------------------------------------------------------+--------------------+
    INFO - 16:52:03:          |      Name     |                         Initial distribution                        | Transformation(x)= |
    INFO - 16:52:03:          +---------------+---------------------------------------------------------------------+--------------------+
    INFO - 16:52:03:          | young_modulus |                   Normal(mu=210000.0, sigma=100.0)                  |      Trunc(x)      |
    INFO - 16:52:03:          |      nu_p     |                      Normal(mu=0.3, sigma=0.02)                     |      Trunc(x)      |
    INFO - 16:52:03:          |     height    |             Normal(39.148681640625, 0.7105309088760217)             |      Trunc(x)      |
    INFO - 16:52:03:          |  imposed_dplt | WeibullMin(296528.213874239, 3380757.500085741, -296533.1983889537) |      Trunc(x)      |
    INFO - 16:52:03:          |     width     |            Normal(30.135172526041664, 0.6364601858416962)           |      Trunc(x)      |
    INFO - 16:52:03:          +---------------+---------------------------------------------------------------------+--------------------+
    INFO - 16:52:03: *** End DOE_BendingTestAnalytical_Cantilever_OT_OPT_LHS_4 execution (time: 0:00:00.043883) ***

ValidationPointResult(metadata=ToolResultMetadata(generic={'datetime': '11-05-2026_16-52-02', 'version': '0.1.7.dev11+g45528c259'}, misc={}, settings={'variable_names': [], 'fitting_criterion': 'Kolmogorov', 'selection_criterion': 'best', 'level': 0.05, 'tested_distributions': ['Uniform', 'Normal', 'LogNormal', 'Exponential', 'WeibullMin'], 'coverage': 0.05, 'confidence': 0.95, 'output_names': [], 'n_samples': 4, 'algo': 'OT_OPT_LHS', 'metric_names': ['AreaMetric', 'RelativeAreaMetric', 'RelativeMeanToMean', 'AbsoluteRelativeErrorP90'], 'simulated_uncertainties': {}, 'nominal_data': {'batch': array([1]), 'length': array([600.]), 'young_modulus': 210000.0, 'nu_p': 0.3}, 'typeb_uncertainties': {}}, report={'title': 'Validation of BendingTestAnalytical Cantilever', 'simulated_uncertainties': {}, 'typeb_uncertainties': {}, 'measured_output_names': ['reaction_forces'], 'measured_data_statistics': "StatisticsResult(metadata=ToolResultMetadata(generic={'datetime': '11-05-2026_16-52-02', 'version': '0.1.7.dev11+g45528c259'}, misc={}, settings={'variable_names': ['height', 'imposed_dplt', 'width'], 'fitting_criterion': 'Kolmogorov', 'selection_criterion': 'best', 'level': 0.05, 'tested_distributions': ['Uniform', 'Normal', 'LogNormal', 'Exponential', 'WeibullMin'], 'coverage': 0.05, 'confidence': 0.95}, report={}, model=None), analysis=StatisticsTool\n   n_samples: 6\n   n_variables: 3\n   variables: height, imposed_dplt, width, best_fitting_distributions={'height': 'Normal', 'imposed_dplt': 'WeibullMin', 'width': 'Normal'}, statistics=OrderedDict([('maximum', {'height': array([inf]), 'imposed_dplt': array([inf]), 'width': array([inf])}), ('minimum', {'height': array([-inf]), 'imposed_dplt': array([-296533.19838895]), 'width': array([-inf])}), ('range', {'height': array([inf]), 'imposed_dplt': array([inf]), 'width': array([inf])}), ('mean', {'height': array([39.14868164]), 'imposed_dplt': array([-5.03514261]), 'width': array([30.13517253])}), ('median', {'height': array([39.14868164]), 'imposed_dplt': array([-5.01666178]), 'width': array([30.13517253])}), ('compute_standard_deviation', {'height': array([0.71053091]), 'imposed_dplt': array([0.11247957]), 'width': array([0.63646019])}), ('variance', {'height': array([0.50485417]), 'imposed_dplt': array([0.01265165]), 'width': array([0.40508157])}), ('percentile_5', {'height': array([37.9799623]), 'imposed_dplt': array([-5.24503216]), 'width': array([29.08828868])}), ('percentile_10', {'height': array([38.23809964]), 'imposed_dplt': array([-5.18189568]), 'width': array([29.31951598])}), ('percentile_25', {'height': array([38.66943583]), 'imposed_dplt': array([-5.09379325]), 'width': array([29.70588665])}), ('percentile_50', {'height': array([39.14868164]), 'imposed_dplt': array([-5.01666178]), 'width': array([30.13517253])}), ('percentile_75', {'height': array([39.62792746]), 'imposed_dplt': array([-4.95586543]), 'width': array([30.5644584])}), ('percentile_90', {'height': array([40.05926364]), 'imposed_dplt': array([-4.91136123]), 'width': array([30.95082907])}), ('percentile_95', {'height': array([40.31740098]), 'imposed_dplt': array([-4.88827964]), 'width': array([31.18205637])}), ('tolerance_interval', {'height': [Bounds(lower=array([39.04804181]), upper=array([39.24932147]))], 'imposed_dplt': [Bounds(lower=array([-5.12757501]), upper=array([-4.91203868]))], 'width': [Bounds(lower=array([30.0450241]), upper=array([30.22532096]))]}), ('a_value', {'height': array([[36.91122839]]), 'imposed_dplt': array([[-5.5055474]]), 'width': array([[28.13096708]])}), ('b_value', {'height': array([[37.65358846]]), 'imposed_dplt': array([[-5.27977566]]), 'width': array([[28.79593834]])})]))"}, 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)), nominal_data={'batch': array([1]), 'length': array([600.]), 'young_modulus': 210000.0, 'nu_p': 0.3}, measured_data=GROUP         inputs                                 outputs
VARIABLE       width     height imposed_dplt reaction_forces
COMPONENT          0          0            0               0
0          30.052246  38.528564    -5.212891    -2286.645728
1          31.221924  38.574341    -4.972900    -2274.363156
2          30.408447  39.372192    -5.214355    -2469.781457
3          29.725220  39.985840    -4.940674    -2396.209442
4          30.032349  39.940186    -4.987549    -2435.575198
5          29.370850  38.490967    -4.919556    -2102.876165, simulated_data=GROUP             inputs                                                      outputs
VARIABLE   young_modulus      nu_p     height imposed_dplt      width reaction_forces
COMPONENT              0         0          0            0          0               0
0          209814.147714  0.286485  38.544544    -5.013230  30.309006    -2112.998098
1          209956.568417  0.326577  39.628505    -5.038725  29.689029    -2262.327070
2          210002.916760  0.299659  39.214577    -5.309330  31.132341    -2422.734009
3          210183.347947  0.301963  38.939287    -4.905995  30.088279    -2120.181215, sample_to_sample_error=None, integrated_metrics={'AreaMetric': {'reaction_forces': 101.38907065975097}, 'RelativeAreaMetric': {'reaction_forces': 0.04355995503298865}, 'RelativeMeanToMean': {'reaction_forces': 0.042110387497969685}, 'AbsoluteRelativeErrorP90': {'reaction_forces': 0.16704763372610204}})

Validation results can be saved on disk

validation_point_tool.save_results(prefix=f"batch_{batch}")

Out:

    INFO - 16:52:03: Saving result to /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]/batch_1_StochasticValidationPoint_result.hdf5
    INFO - 16:52:03: Saving result to /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]/DOETool/batch_1_DOETool_result.hdf5
    INFO - 16:52:03: Saving result to /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]/StatisticsTool/batch_1_StatisticsTool_result.hdf5
    INFO - 16:52:03: PICKLE fallback: key='analysis', type=<class 'gemseo.uncertainty.statistics.parametric_statistics.ParametricStatistics'>, value=StatisticsTool
    INFO - 16:52:03:    n_samples: 6
    INFO - 16:52:03:    n_variables: 3
    INFO - 16:52:03:    variables: height, imposed_dplt, width

The results can be plotted:

figures = validation_point_tool.plot_results(
    validation_point_tool.result, "reaction_forces", show=True, save=True
)

plot stochastic validation straightbeam

Out:

    INFO - 16:52:03: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]
    INFO - 16:52:03: Working directory is /home/sebastien.bocquet/PycharmProjects/vimseo/docs/runnable_examples/06_validation_point/BendingTestAnalytical_Cantilever/batch_1_[600.]
/home/sebastien.bocquet/PycharmProjects/vimseo/src/vimseo/tools/validation/validation_point.py:321: UserWarning:

FigureCanvasAgg is non-interactive, and thus cannot be shown

The Q-Q plot of the measured and simulated distributions:

figures["qq_plot"]

Out:

<Figure size 640x480 with 1 Axes>

The comparison of the measured and simulated PDF:

figures["PDF_comparison"]

The comparison of the measured and simulated CDF:

figures["CDF_comparison"]

The saved result can be visualised in a dashboard by typing in a terminal where the vims_composites Python environment is activated: dashboard_validation_point_viewer

The simulated input space can be exported to disk, to be visualized with dashboard_space. In pickle format:

space_tool_result = SpaceToolResult(
    parameter_space=validation_point_tool.simulated_input_space
)
space_tool_result.to_pickle("simulated_input_space")

Or in json format:

SpaceToolFileIO().write(space_tool_result, file_base_name="simulated_input_space")

Out:

'{\n    "parameter_space": {\n        "young_modulus": {\n            "mu": 210000.0,\n            "sigma": 100.0,\n            "name": "Normal",\n            "size": 1\n        },\n        "nu_p": {\n            "mu": 0.3,\n            "sigma": 0.02,\n            "name": "Normal",\n            "size": 1\n        },\n        "height": {\n            "name": "Normal",\n            "parameters": [\n                39.148681640625,\n                0.7105309088760217\n            ],\n            "lower_bound": 0.0,\n            "upper_bound": Infinity,\n            "size": 1\n        },\n        "imposed_dplt": {\n            "name": "WeibullMin",\n            "parameters": [\n                296528.213874239,\n                3380757.500085741,\n                -296533.1983889537\n            ],\n            "lower_bound": -296533.1983889537,\n            "upper_bound": Infinity,\n            "size": 1\n        },\n        "width": {\n            "name": "Normal",\n            "parameters": [\n                30.135172526041664,\n                0.6364601858416962\n            ],\n            "lower_bound": 0.0,\n            "upper_bound": Infinity,\n            "size": 1\n        }\n    },\n    "metadata": {\n        "generic": {\n            "datetime": "11-05-2026_16-52-04",\n            "version": "0.1.7.dev11+g45528c259"\n        },\n        "misc": {},\n        "settings": {},\n        "report": {},\n        "model": null\n    }\n}'

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

Download Python source code: plot_stochastic_validation_straightbeam.py

Download Jupyter notebook: plot_stochastic_validation_straightbeam.ipynb

Gallery generated by mkdocs-gallery