diff --git a/calabru/__init__.py b/calabru/__init__.py deleted file mode 100644 index eed70c9..0000000 --- a/calabru/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .calibrator import * diff --git a/docs/requirement.txt b/docs/requirement.txt index 179d091..d380880 100644 --- a/docs/requirement.txt +++ b/docs/requirement.txt @@ -4,11 +4,12 @@ pytest>=6.1.1 datetime scipy pydata-sphinx-theme -Sphinx>=4.0 +Sphinx>=5.0 nbsphinx sphinx-autodoc-typehints pandoc markupsafe==2.0.1 pygments >= 2.7 -PyCBA -ospgrillage \ No newline at end of file +pycba +ospgrillage +ipython \ No newline at end of file diff --git a/docs/source/_templates/custom-class-template.rst b/docs/source/_templates/custom-class-template.rst new file mode 100644 index 0000000..f73eda5 --- /dev/null +++ b/docs/source/_templates/custom-class-template.rst @@ -0,0 +1,34 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :members: + :show-inheritance: + :inherited-members: + :special-members: __call__, __add__, __mul__ + + {% block methods %} + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + :nosignatures: + {% for item in methods %} + {%- if not item.startswith('_') %} + ~{{ name }}.{{ item }} + {%- endif -%} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/source/_templates/custom-module-template.rst b/docs/source/_templates/custom-module-template.rst new file mode 100644 index 0000000..d066d0e --- /dev/null +++ b/docs/source/_templates/custom-module-template.rst @@ -0,0 +1,66 @@ +{{ fullname | escape | underline}} + +.. automodule:: {{ fullname }} + + {% block attributes %} + {% if attributes %} + .. rubric:: Module attributes + + .. autosummary:: + :toctree: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block functions %} + {% if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + :toctree: + :nosignatures: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + :nosignatures: + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + :toctree: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + +{% block modules %} +{% if modules %} +.. autosummary:: + :toctree: + :template: custom-module-template.rst + :recursive: +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{% endblock %} diff --git a/docs/source/api.rst b/docs/source/api.rst index cdb149f..1982144 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -1,7 +1,15 @@ +API Reference +============= + +Package Modules +--------------- + .. autosummary:: :toctree: gen :template: custom-module-template.rst :recursive: - calabru.ModelUpdating + calabru.calibrator + calabru.utils + diff --git a/docs/source/conf.py b/docs/source/conf.py index 3a50cb8..b7dc920 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -13,8 +13,10 @@ import os import sys -sys.path.insert(0, os.path.abspath("../../")) - +sys.path.insert(0, os.path.abspath("../../src/.")) +sys.path.insert(0, os.path.abspath("../../src/calabru/")) +from calabru import __version__ as ver +# # -- Project information ----------------------------------------------------- @@ -23,7 +25,12 @@ author = "Colin Caprani, Jun Wei Ngan" # The full version, including alpha/beta/rc tags -release = "0.1" +# The short Major.Minor.Build version +_v = ver.split(".") +_build = "".join([c for c in _v[2] if c.isdigit()]) +version = _v[0] + "." + _v[1] + "." + _build +release = ver + # -- General configuration --------------------------------------------------- @@ -81,7 +88,7 @@ "icon_links": [ { "name": "GitHub", - "url": "https://github.com/ccaprani/pycba", + "url": "https://github.com/MonashSmartStructures/calabru", "icon": "fab fa-github-square", }, { @@ -101,7 +108,7 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. -# html_logo = "./images/logo.png" +html_logo = "./images/logo.png" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". diff --git a/docs/source/images/logo.png b/docs/source/images/logo.png new file mode 100644 index 0000000..e69de29 diff --git a/docs/source/images/osp_example.png b/docs/source/images/osp_example.png new file mode 100644 index 0000000..325631d Binary files /dev/null and b/docs/source/images/osp_example.png differ diff --git a/docs/source/index.rst b/docs/source/index.rst index 9a82c60..ce249c6 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,24 +1,30 @@ -Calabru -======= -`calabru` [1]_ is a calibration framework for model/analysis/data systems in the Python -environment. +Welcome to calabru's documentation! +=================================== +`calabru` [1]_ is a calibration framework in the Python environment.`calabru` is provides fast calibration of general model/functions/systems in Python environment. -The calibration framework includes several state-of-the-art model updating methods such as: + +`calabru` uses several state-of-the-art model updating methods such as: - Sensitivity-based analysis -- Bayesian-based approach (in progress) +- Bayesian-based approach .. [1] Fun fact, "Calabru" means Calibration in the Irish language. -Documentation -============= - .. toctree:: :maxdepth: 2 + :caption: Contents: + + installation + api + + - notebooks/intro - notebooks/example +Related Packages +================ +- `pycba `_ is an analysis package for continuous beam analysis. +- `sectionproperties `_ is a package for the analysis of cross-sectional geometric properties and stress distributions. +- `ospgrillage `_ is a bridge deck grillage analysis package which is a pre-processor for `OpenSeesPy `_, a python wrapper for the general finite element analysis framework `OpenSees `_. Indices and tables ================== diff --git a/docs/source/installation.md b/docs/source/installation.md index 7baaf2f..546b312 100644 --- a/docs/source/installation.md +++ b/docs/source/installation.md @@ -5,8 +5,6 @@ Required Dependencies --------------------- - Python 3.8 or later - numpy -- scipy -- matplotlib Instructions ------------ @@ -24,7 +22,7 @@ For contributions, first fork the repo and clone from your fork. `Here " + ] + }, + "execution_count": 11, + "metadata": { + "image/png": { + "width": 800 + } + }, + "output_type": "execute_result" + } + ], "source": [ - "target_deflections = [[0.0, 5.24e-05, 9.98e-05, 0.000136, 0.000155,0.0001558, 0.000136, 9.98e-05, 5.24e-05,0.0]]" + "display.Image(\"../images/osp_example.png\",width=800)" ] }, { @@ -83,27 +186,57 @@ "id": "d787bca0-bd20-49cc-bb8d-66c7cb26d1dc", "metadata": {}, "source": [ - "We want to update the stiffness of the girders (`I`) in the model to update the model:" + "We want to update the moment of inertia of the longitudinal girders (`I`) of the bridge model. In addition, we are uncertain of the moment of inertia of the two edge members as well. Therefore, we introduce two updating paramters to the model as:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "50e8038b-93f7-43e3-8e7b-fa5b91f1f9ab", "metadata": {}, "outputs": [], "source": [ - "I_start = [0.2] # m4" + "start = [0.2, # longitudinal girders, I\n", + " 0.1, # edge member, I\n", + " ]" + ] + }, + { + "cell_type": "markdown", + "id": "7b01d2b4-86bc-4e3c-835a-e4bdb76ebc82", + "metadata": {}, + "source": [ + "We update the model using some \"known\" measurements of the bridge deflections. For this,the measurements is taken as the\n", + "responses which corresponds to a parameter list = [0.5,0.1]\n" ] }, { "cell_type": "code", - "execution_count": null, - "id": "7ba40eb6-316e-4d56-881b-3c87c93a234a", + "execution_count": 7, + "id": "d67b5834-8f84-4997-8106-18a2157f8811", "metadata": {}, "outputs": [], "source": [ - "First we need to structure the model's generation and analysis script into a function handler (denoted as `main()`) with the following properties:\n", + "target = [[1047.057906932444,\n", + " [0.0,\n", + " 3.847756717425916e-05,\n", + " 7.335795722107879e-05,\n", + " 0.0001001430188545662,\n", + " 0.00011472208165921942,\n", + " 0.00011472208165922035,\n", + " 0.00010014301885456844,\n", + " 7.335795722108123e-05,\n", + " 3.847756717426085e-05,\n", + " 0.0]]\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "05734b9f-1e03-42a7-94fe-895889115884", + "metadata": {}, + "source": [ + "Lets create the function handler (denote as `main()`) that creates and analyse the model with the following properties that is compatible with`calabru` to allow for updating procedures:\n", "\n", "1. `main()` takes in `I_start` as an argument.\n", "2. `main()` returns a list of the corresponding measurables of `target_deflections` from the model." @@ -111,16 +244,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "989b4a2c-4fd5-4111-b9a7-b9dce37ec2b6", - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "def beam_with_patch_load_including_deflected_shape_output(p_matrix: list):\n", + "def main(p_matrix: list):\n", " # sort parameter variable\n", - " #P = p_matrix[0]\n", + "\n", " P = 1000\n", - " Iz = p_matrix[0]\n", + " Iz1 = p_matrix[0]\n", + " Iz2 = p_matrix[1]\n", "\n", " # Adopted units: N and m\n", " kilo = 1e3\n", @@ -156,7 +292,7 @@ " edge_longitudinal_section = og.create_section(\n", " A=0.934 * m2,\n", " J=0.1857 * m3,\n", - " Iz=0.3478 * m4,\n", + " Iz=Iz2 * m4,\n", " Iy=0.213602 * m4,\n", " Az=0.444795 * m2,\n", " Ay=0.258704 * m2,\n", @@ -165,7 +301,7 @@ " longitudinal_section = og.create_section(\n", " A=1.025 * m2,\n", " J=0.1878 * m3,\n", - " Iz=Iz * m4,\n", + " Iz=Iz1 * m4,\n", " Iy=0.113887e-3 * m4,\n", " Az=0.0371929 * m2,\n", " Ay=0.0371902 * m2,\n", @@ -256,10 +392,53 @@ " results = simple_bridge.get_results()\n", "\n", " # arbitrary force components\n", - " r_mat = [[og.ops.nodeDisp(n)[1] for n in [2,9,16,23,30,37,44,51,58,65]]]\n", - " #og.ops.eleForce(25)[1],\n", + " r_mat = [[og.ops.eleForce(25)[1],[og.ops.nodeDisp(n)[1] for n in [2,9,16,23,30,37,44,51,58,65]]]]\n", + "\n", " return r_mat" ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "50e8e494-9924-413c-867e-0b7383e861a4", + "metadata": {}, + "outputs": [], + "source": [ + "simple_beam_updating = clb.ModelUpdating(\n", + " function_handle=main,\n", + " param_list=start,\n", + " target_list=target,\n", + " max_error=0.1,\n", + " write_output_txt=False\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "a1f0bdc8-307c-4fad-8be8-e7a65c339363", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.2, 0.1], [0.3365125562453617, 0.10119151305405859], [0.45716219684186105, 0.1008159604001884], [0.5002470885555945, 0.10009323201609568]]\n" + ] + } + ], + "source": [ + "simple_beam_updating.update_model()\n", + "print(simple_beam_updating.param_update_history)" + ] + }, + { + "cell_type": "markdown", + "id": "ddf76bc8-59ac-463a-bb05-c7d8ae89c612", + "metadata": {}, + "source": [ + "As can be seen the values converged to [0.5,0.1] " + ] } ], "metadata": { diff --git a/docs/source/notebooks/ospgrillage_example.ipynb b/docs/source/notebooks/ospgrillage_example.ipynb new file mode 100644 index 0000000..7b01a2b --- /dev/null +++ b/docs/source/notebooks/ospgrillage_example.ipynb @@ -0,0 +1,465 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2ebd6341-6ab2-4dbe-8fd2-fe235520af5f", + "metadata": {}, + "source": [ + "# Example and features" + ] + }, + { + "cell_type": "markdown", + "id": "66ec8f0a-120e-4de7-85dc-69e7c1f84412", + "metadata": {}, + "source": [ + "We will consider a bridge grillage model created using the `ospgrillage` module\n", + "as our running example to demonstrate the features of `calabru`." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "a20ddb77-e42a-498c-a5a4-7386f561bf82", + "metadata": {}, + "outputs": [], + "source": [ + "import calabru as clb # calabru package\n", + "import numpy as np # for numerical arrays\n", + "import matplotlib.pyplot as plt # for plotting\n", + "from IPython import display # For images in notebook\n", + "import pycba as cba # for creating beam model\n", + "import ospgrillage as og\n", + "%matplotlib inline \n" + ] + }, + { + "cell_type": "markdown", + "id": "4f64cddc-6ae4-41d1-b2ba-da14dc589fcc", + "metadata": {}, + "source": [ + "## Exploring parameter options" + ] + }, + { + "cell_type": "markdown", + "id": "e3a8fc08-682c-4b26-b00d-3463293703ea", + "metadata": {}, + "source": [ + "### Inputs" + ] + }, + { + "cell_type": "markdown", + "id": "d0a9bc72-15a7-4774-9f73-4c6512920628", + "metadata": {}, + "source": [ + "`calabru` takes multiple inputs for the updating parameters as a list." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "12c1c381-3c9d-434c-b923-bc3dbfb26285", + "metadata": {}, + "outputs": [], + "source": [ + "start = [\n", + " 0.2, \n", + " 0.4,\n", + " 0.6,\n", + " ]" + ] + }, + { + "cell_type": "markdown", + "id": "ac1d3f25-5e83-4dc3-b49c-af3995eabac0", + "metadata": {}, + "source": [ + "We can introduce bounds which the parameters will not exceed during the calibration process as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0889938c-3c0d-48f8-8003-cfbd05ea30e5", + "metadata": {}, + "outputs": [], + "source": [ + "bounds = [\n", + " [0.1,0.5], # lower and upper bounds for first param \n", + " [0.7], # upper bound of second param, lower default to zero \n", + " [], # no bounds for third param\n", + " ]" + ] + }, + { + "cell_type": "markdown", + "id": "52e86ec1-c980-413d-8787-c8330575bb3f", + "metadata": {}, + "source": [ + "where the `bounds` list must be the same size as the `start` list.\n", + "Each element should be a list of a lower and upper bound (second entry)." + ] + }, + { + "cell_type": "markdown", + "id": "b0ecc314-4e02-41f1-b757-9aa7cdded647", + "metadata": {}, + "source": [ + "### Targets" + ] + }, + { + "cell_type": "markdown", + "id": "81cfcfa9-ca1a-4798-9f51-beaae1f624ab", + "metadata": {}, + "source": [ + "Each target responses can be a list/array.\n", + "\n", + "For example, we have can have the deflected shape list and the force magnitude of Element 5 as the first and second element the list of `target` respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "693bc990-4fb3-4c1d-9c34-d3cbd66db625", + "metadata": {}, + "outputs": [], + "source": [ + "target = [\n", + " 5948.52, # element forces\n", + " [\n", + " 0.0,\n", + " 5.244e-05,\n", + " 9.984e-05,\n", + " 0.000136,\n", + " 0.0001558,\n", + " 0.0001558,\n", + " 0.000136,\n", + " 9.984e-05,\n", + " 5.243e-05,\n", + " 0.0,\n", + " ], # node displacements\n", + " \n", + "] " + ] + }, + { + "cell_type": "markdown", + "id": "c22aa21d-0366-4a04-90ab-50b7603c91ff", + "metadata": {}, + "source": [ + "## Example 1 - Grillage model problem in ospgrillage\n", + "\n", + "We have a full-fledged single-span bridge model made using `ospgrillage` module that we'd like to use to determine the bridge load effects due to an imposed load.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "371f2a7d-87e4-4e89-b8f0-ec966ac57639", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": { + "image/png": { + "width": 800 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "display.Image(\"../images/osp_example.png\",width=800)" + ] + }, + { + "cell_type": "markdown", + "id": "d787bca0-bd20-49cc-bb8d-66c7cb26d1dc", + "metadata": {}, + "source": [ + "We want to update the moment of inertia of the longitudinal girders (`I`) of the bridge model. In addition, we are uncertain of the moment of inertia of the two edge members as well. Therefore, we introduce two updating paramters to the model as:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "50e8038b-93f7-43e3-8e7b-fa5b91f1f9ab", + "metadata": {}, + "outputs": [], + "source": [ + "start = [0.2, # longitudinal girders, I\n", + " 0.1, # edge member, I\n", + " ]" + ] + }, + { + "cell_type": "markdown", + "id": "7b01d2b4-86bc-4e3c-835a-e4bdb76ebc82", + "metadata": {}, + "source": [ + "We update the model using some \"known\" measurements of the bridge deflections. For this,the measurements is taken as the\n", + "responses which corresponds to a parameter list = [0.5,0.1]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d67b5834-8f84-4997-8106-18a2157f8811", + "metadata": {}, + "outputs": [], + "source": [ + "target = [[1047.057906932444,\n", + " [0.0,\n", + " 3.847756717425916e-05,\n", + " 7.335795722107879e-05,\n", + " 0.0001001430188545662,\n", + " 0.00011472208165921942,\n", + " 0.00011472208165922035,\n", + " 0.00010014301885456844,\n", + " 7.335795722108123e-05,\n", + " 3.847756717426085e-05,\n", + " 0.0]]\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "05734b9f-1e03-42a7-94fe-895889115884", + "metadata": {}, + "source": [ + "Lets create the function handler (denote as `main()`) that creates and analyse the model with the following properties that is compatible with`calabru` to allow for updating procedures:\n", + "\n", + "1. `main()` takes in `I_start` as an argument.\n", + "2. `main()` returns a list of the corresponding measurables of `target_deflections` from the model." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "989b4a2c-4fd5-4111-b9a7-b9dce37ec2b6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def main(p_matrix: list):\n", + " # sort parameter variable\n", + "\n", + " P = 1000\n", + " Iz1 = p_matrix[0]\n", + " Iz2 = p_matrix[1]\n", + "\n", + " # Adopted units: N and m\n", + " kilo = 1e3\n", + " milli = 1e-3\n", + " N = 1\n", + " m = 1\n", + " mm = milli * m\n", + " m2 = m ** 2\n", + " m3 = m ** 3\n", + " m4 = m ** 4\n", + " kN = kilo * N\n", + " MPa = N / ((mm) ** 2)\n", + " GPa = kilo * MPa\n", + "\n", + " # parameters of bridge grillage\n", + " L = 10 * m # span\n", + " w = 5 * m # width\n", + " n_l = 7 # number of longitudinal members\n", + " n_t = 10 # number of transverse members\n", + " edge_dist = 1 * m # distance between edge beam and first exterior beam\n", + " ext_to_int_dist = (\n", + " 2.2775 * m\n", + " ) # distance between first exterior beam and first interior beam\n", + " angle = 0 # skew angle\n", + " mesh_type = \"Oblique\"\n", + "\n", + " # define material\n", + " concrete = og.create_material(\n", + " material=\"concrete\", code=\"AS5100-2017\", grade=\"65MPa\"\n", + " )\n", + "\n", + " # define sections (parameters from LUSAS model)\n", + " edge_longitudinal_section = og.create_section(\n", + " A=0.934 * m2,\n", + " J=0.1857 * m3,\n", + " Iz=Iz2 * m4,\n", + " Iy=0.213602 * m4,\n", + " Az=0.444795 * m2,\n", + " Ay=0.258704 * m2,\n", + " )\n", + "\n", + " longitudinal_section = og.create_section(\n", + " A=1.025 * m2,\n", + " J=0.1878 * m3,\n", + " Iz=Iz1 * m4,\n", + " Iy=0.113887e-3 * m4,\n", + " Az=0.0371929 * m2,\n", + " Ay=0.0371902 * m2,\n", + " )\n", + "\n", + " transverse_section = og.create_section(\n", + " A=0.504 * m2,\n", + " J=5.22303e-3 * m3,\n", + " Iy=0.32928 * m4,\n", + " Iz=1.3608e-3 * m4,\n", + " Ay=0.42 * m2,\n", + " Az=0.42 * m2,\n", + " )\n", + "\n", + " end_transverse_section = og.create_section(\n", + " A=0.504 / 2 * m2,\n", + " J=2.5012e-3 * m3,\n", + " Iy=0.04116 * m4,\n", + " Iz=0.6804e-3 * m4,\n", + " Ay=0.21 * m2,\n", + " Az=0.21 * m2,\n", + " )\n", + "\n", + " # define grillage members\n", + " longitudinal_beam = og.create_member(\n", + " section=longitudinal_section, material=concrete\n", + " )\n", + " edge_longitudinal_beam = og.create_member(\n", + " section=edge_longitudinal_section, material=concrete\n", + " )\n", + " transverse_slab = og.create_member(section=transverse_section, material=concrete)\n", + " end_transverse_slab = og.create_member(\n", + " section=end_transverse_section, material=concrete\n", + " )\n", + "\n", + " # create grillage\n", + " simple_bridge = og.create_grillage(\n", + " bridge_name=\"simple_bridge\",\n", + " long_dim=L,\n", + " width=w,\n", + " skew=angle,\n", + " num_long_grid=n_l,\n", + " num_trans_grid=n_t,\n", + " edge_beam_dist=edge_dist,\n", + " mesh_type=mesh_type,\n", + " )\n", + "\n", + " simple_bridge.set_member(longitudinal_beam, member=\"interior_main_beam\")\n", + " simple_bridge.set_member(longitudinal_beam, member=\"exterior_main_beam_1\")\n", + " simple_bridge.set_member(longitudinal_beam, member=\"exterior_main_beam_2\")\n", + " simple_bridge.set_member(edge_longitudinal_beam, member=\"edge_beam\")\n", + " simple_bridge.set_member(transverse_slab, member=\"transverse_slab\")\n", + " simple_bridge.set_member(end_transverse_slab, member=\"start_edge\")\n", + " simple_bridge.set_member(end_transverse_slab, member=\"end_edge\")\n", + " simple_bridge.create_osp_model(pyfile=False)\n", + "\n", + " # add load case\n", + " # Patch load over entire bridge deck (P is kN/m2)\n", + " P = P * kN / m2 # magnitude of patch vertex\n", + " patch_point_1 = og.create_load_vertex(x=0, z=0, p=P)\n", + " patch_point_2 = og.create_load_vertex(x=L, z=0, p=P)\n", + " patch_point_3 = og.create_load_vertex(x=L, z=w, p=P)\n", + " patch_point_4 = og.create_load_vertex(x=0, z=w, p=P)\n", + " test_patch_load = og.create_load(\n", + " loadtype=\"patch\",\n", + " name=\"Test Load\",\n", + " point1=patch_point_1,\n", + " point2=patch_point_2,\n", + " point3=patch_point_3,\n", + " point4=patch_point_4,\n", + " )\n", + "\n", + " test_point_load = og.create_load(\n", + " loadtype=\"point\",\n", + " name=\"Test Load\",\n", + " point1=og.create_load_vertex(x=L / 2, z=w / 2, p=P),\n", + " )\n", + "\n", + " # Create load case, add loads, and assign\n", + " patch_case = og.create_load_case(name=\"test patch load case\")\n", + " patch_case.add_load(test_patch_load)\n", + " point_case = og.create_load_case(name=\"test point load case\")\n", + " point_case.add_load(test_point_load)\n", + " # sn8474.add_load_case(patch_case)\n", + " simple_bridge.add_load_case(point_case)\n", + "\n", + " simple_bridge.analyze()\n", + " results = simple_bridge.get_results()\n", + "\n", + " # arbitrary force components\n", + " r_mat = [[og.ops.eleForce(25)[1],[og.ops.nodeDisp(n)[1] for n in [2,9,16,23,30,37,44,51,58,65]]]]\n", + "\n", + " return r_mat" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "50e8e494-9924-413c-867e-0b7383e861a4", + "metadata": {}, + "outputs": [], + "source": [ + "simple_beam_updating = clb.ModelUpdating(\n", + " function_handle=main,\n", + " param_list=start,\n", + " target_list=target,\n", + " max_error=0.1,\n", + " write_output_txt=False\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "a1f0bdc8-307c-4fad-8be8-e7a65c339363", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.2, 0.1], [0.3365125562453617, 0.10119151305405859], [0.45716219684186105, 0.1008159604001884], [0.5002470885555945, 0.10009323201609568]]\n" + ] + } + ], + "source": [ + "simple_beam_updating.update_model()\n", + "print(simple_beam_updating.param_update_history)" + ] + }, + { + "cell_type": "markdown", + "id": "ddf76bc8-59ac-463a-bb05-c7d8ae89c612", + "metadata": {}, + "source": [ + "As can be seen the values converged to [0.5,0.1] " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyproject.toml b/pyproject.toml index 5538eb1..42f0fa8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,7 @@ [project] -requires-python = ">=3.8,<=3.9" +requires-python = ">=3.8,>=3.9" +name = "calabru" +dynamic = ["version"] [build-system] requires = ["wheel >= 0.31.0", @@ -9,6 +11,12 @@ requires = ["wheel >= 0.31.0", ] build-backend = "setuptools.build_meta" +[project.optional-dependencies] +test = ["pytest >= 6.2.2"] + +[tool.setuptools.dynamic] +version = {attr = "calabru.__version__"} + [tool.pytest.ini_options] minversion = "6.0" testpaths = [ diff --git a/src/calabru/__init__.py b/src/calabru/__init__.py new file mode 100644 index 0000000..3d11a85 --- /dev/null +++ b/src/calabru/__init__.py @@ -0,0 +1,8 @@ +""" +calabru - Calibration of models in Python +""" + +__version__ = "0.1.0" + +from .calibrator import * +from .utils import * \ No newline at end of file diff --git a/calabru/calibrator.py b/src/calabru/calibrator.py similarity index 66% rename from calabru/calibrator.py rename to src/calabru/calibrator.py index 083afb1..c676d5e 100644 --- a/calabru/calibrator.py +++ b/src/calabru/calibrator.py @@ -2,36 +2,49 @@ """ Main calibration module """ -import numpy as np from datetime import datetime import copy -from scipy.interpolate import interp1d -import matplotlib.pyplot as plt +import numpy as np +from utils import get_pseudo_inv_estimation,interpolate_measurements,calculate_rmse -class ModelUpdating: +class Calibrator: """ - Main updating/calibrating class. + Main class to handle updating. """ def __init__(self, function_handle, **kwargs): """ + Init the class + + Parameters + ---------- + function_handle: + Python function handler to calibrate. + **kwargs: dict, optional + Extra arguments for class and function_handle. Refer below for the list of all possible arguments. + + Other Parameters + ---------------- + iterative_method: str, default="FDM" + Method to calculate sensitivity matrix. + param_list: list + A list of starting values for updating parameters + target_list: list + A list of target/objective values for the function handle outputs + target_resp_list: list + Multi dimension list of k considered models/cases. If a single dimension list is provided + the class parses the list into a mutli dimension 1x(k=1) list. + max_increm_steps: int, default=50 + Maximum updating increments + param_increm_rate: float, default=1.1 + Increment rate of parameter between updating iterations + max_error: float + maximum allowable parameter error + write_output_txt: bool + If true, writes - :param function_handle: Function handler to create and analyze models in Python environment. Note the function - handler must be able to pass in updating parameters and return desirable responses. - :param sensitivity_type: Method to obtain the sensitivity matrix. Default "FDM" - :type sensitivity_type: str - :param param_list: A list of float or int of starting values of updating parameters. - :type param_list: list - :param target_list: A list of float or int of target/objectives of the updating function handler. - :type target_list: list - :param target_resp_list: Multi dimension list of k considered models/cases. If a single dimension list is provided - the class parses the list into a mutli dimension 1x(k=1) list. - - :param max_increm_steps: Maximum updating increments. Default 50 - :param param_increm_rate: Increment rate of parameters between each step. Default 10% - :param max_error: Maximum allowable parameter error. """ # get model and load case inputs @@ -48,8 +61,14 @@ def __init__(self, function_handle, **kwargs): "param_bounds_list", [[] for item in self.param_list] ) # bounds for params # empty list means no bounds. + # weighting for param bounds + self.param_sen_weighting = kwargs.get("param_sen_weighting", [1 for item in self.param_list]) + if not self.param_sen_weighting: + self.param_sen_weighting = [1 for item in self.param_list] + - # check validity of param bounds + + # check validity of param bounds if len(self.param_list) != len(self.param_bounds_list): raise Exception( "Param bound list must match the number of parameters: Hint specify empty list [] to params that are not bounded" @@ -102,17 +121,34 @@ def __init__(self, function_handle, **kwargs): def set_targets(self, target_list: list): """ Set or overwrite updating parameters. - :param target_list: list of target response value. Note: list order must correspond to the outputs returned + + Parameters + ---------- + target_list: list + ist of target response value + + Notes + ----- + list order must correspond to the outputs returned by main() function. Refer to template main() function for information on setting up the updating procedure. - :type target_list: list + """ self.target_response_list = target_list def set_param(self, param_list: list, variance_range=None): """ Set or overwrite updating parameters. - :param param_list: list of starting parameter values. Note: list order must correspond to the input of + + Parameters + ---------- + param_list: list + list of starting parameter values + + Notes + ----- + Note: list order must correspond to the input of main() updating function. Refer to template main() function for information on setting up the updating procedure. + """ self.param_list = param_list @@ -120,7 +156,10 @@ def update_model(self, **kwargs): """ Calibrate the model. - Keyword arguments passed under this function are passed to function handle of the updating object. + Parameters + ---------- + **kwargs: dict, optional + Keyword arguments accepted by the function handler of the updating Example: If the function handler takes two keyword arguments - @@ -146,7 +185,7 @@ def update_model(self, **kwargs): self.global_sensitivity_matrix += self.sensitivity_matrix self.global_resp_diff += self.resp_diff - esti = self._get_pseudo_inv_estimation( + esti = get_pseudo_inv_estimation( sens_mat=self.global_sensitivity_matrix, resp_diff=self.global_resp_diff ) # compute residue and check threshold @@ -176,7 +215,7 @@ def update_model(self, **kwargs): # response error e_response = np.sqrt( sum([resp**2 for resp in self.global_resp_diff]) - ) / np.sqrt(sum([target**2 for target in self.target_response_list[0]])) + ) # parameter estimation error error = np.sqrt( sum([estimates**2 for estimates in param_increments]) @@ -206,15 +245,24 @@ def update_model(self, **kwargs): def _compute_fdm_sensitivity(self, param_list, target_resp=None, model_index=0): """ - Function to compute sensitivity matrix based on finite difference sensitivity method. The function runs the + Returns the sensitivity matrix based on finite difference sensitivity method. The function runs the function handle defined during construction of class with the initial parameters as inputs. Then increments the parameter values to obtain an incremental responses. Subsequently, assembles the sensitivity matrix. - :param param_list: Parameters at current updating step. - :type param_list:list - :param model_index: Index of output from function_handle which matches the current evaluating target response. + Parameters + ---------- + param_list: list + list of updating parameter values + target_resp: list, optional + list of target responses + model_index: int, default=0 + Index of output from function_handle which matches the current evaluating target response + + Returns + ------- + Array like + Array of sensitivity matrix - also stored as `sensitivity_matrix` in class - :returns array of sensitivity matrix stored in sensitivity_matrix var """ # get base response @@ -244,11 +292,11 @@ def _compute_fdm_sensitivity(self, param_list, target_resp=None, model_index=0): model_time = list(response[model_index][k].keys()) if len(ref_resp) > len(response): - interp_ref_resp = self._interpolate_measurements( + interp_ref_resp = interpolate_measurements( data_x=time, data_y=val, model_x=model_time ) else: - interp_ref_resp = self._interpolate_measurements( + interp_ref_resp = interpolate_measurements( data_x=model_time, data_y=val, model_x=time ) else: @@ -256,13 +304,13 @@ def _compute_fdm_sensitivity(self, param_list, target_resp=None, model_index=0): model_abs_axis = np.linspace(0, 1, len(kth_model_response)) abs_time_measure = np.linspace(0, 1, len(ref_resp)) - interp_ref_resp = self._interpolate_measurements( + interp_ref_resp = interpolate_measurements( data_x=abs_time_measure, data_y=ref_resp, model_x=model_abs_axis ) # plt.plot(model_abs_axis, interp_ref_resp) # plt.plot(model_abs_axis, kth_model_response) # plt.show() - rmse = self._calculate_rmse( + rmse = calculate_rmse( ref_response_list=interp_ref_resp, current_response_list=kth_model_response, ) @@ -288,25 +336,33 @@ def _compute_fdm_sensitivity(self, param_list, target_resp=None, model_index=0): # checks if the current response is a list if hasattr(target_resp[i], "__len__"): # calculate rmse - rmse = self._calculate_rmse( + rmse = calculate_rmse( ref_response_list=inc_response[model_index][i], current_response_list=response[model_index][i], ) self.sensitivity_matrix[i].append( - rmse / (param * abs(self.increment_rate - 1)) + rmse / (param * abs(self.increment_rate - 1)*self.param_sen_weighting[j]) ) else: self.sensitivity_matrix[i].append( - (inc_response[model_index][i] - response[model_index][i]) + (inc_response[model_index][i] - response[model_index][i]) * self.param_sen_weighting[j] / (param * abs(self.increment_rate - 1)) ) def get_updated_response(self, param_list): + """Returns the responses from a given list of parameters + + Parameters + ---------- + param_list: list + List of parameter values + """ # get base response return self.function_handle(param_list, **self.kwarg) def print_to(self, current_step, error): + """Prints the status of each step""" # function to print updating status to print("Curent update step {}".format(current_step)) print(self.param_update_history[-1]) @@ -314,6 +370,7 @@ def print_to(self, current_step, error): print(error) def _write_output_txt(self): + """Returns a report .txt file of the calibration process""" name = self.name + ".txt" with open(name, "w") as file_handle: # create py file or overwrite existing @@ -335,122 +392,3 @@ def _write_output_txt(self): file_handle.write("Target response\n") file_handle.write(str(self.target_response_list) + "\n") - - @staticmethod - def _get_pseudo_inv_estimation(sens_mat, resp_diff): - """ - Function to estimate parameters for model updating using Pseudo Inverse Method - :param sens_mat: sensitivity matrix at current updating step - :type sens_mat: list of size r by p where r and p are the number of responses and parameters respectively - """ - sens_mat_transpose = np.transpose(sens_mat) - resp_num = np.array(sens_mat).shape[0] - param_num = np.array(sens_mat).shape[1] - # init var - estimate = None - if resp_num == param_num: - estimate = np.dot(np.linalg.inv(sens_mat), resp_diff) - elif resp_num > param_num: - pseudo_inv = np.dot( - np.linalg.inv(np.dot(sens_mat_transpose, sens_mat)), sens_mat_transpose - ) - estimate = np.dot(pseudo_inv, resp_diff) - elif resp_num < param_num: - pseudo_inv = np.dot( - sens_mat_transpose, - np.linalg.inv( - np.dot( - sens_mat, - sens_mat_transpose, - ) - ), - ) - estimate = np.dot(pseudo_inv, resp_diff) - - return estimate - - @staticmethod - def _calculate_rmse(ref_response_list, current_response_list): - N = len(ref_response_list) - - return np.sqrt( - sum( - [ - (ref - current) ** 2 / N - for (ref, current) in zip(ref_response_list, current_response_list) - ] - ) - ) - - @staticmethod - def _get_bayesian_param_estimation(sens_mat, resp_diff, current_param, cp, cr): - """ - Function to perform parameter estimation using Bayesian approach. Here, a gain matrix G is calculated - from the provided confidence weighing for parameter and responses. - :param current_param: - :param cp: - :parm cr: - """ - sens_mat_transpose = np.transpose(sens_mat) - resp_num = np.array(sens_mat).shape[0] - param_num = np.array(sens_mat).shape[1] - - # init var - gain_mat = [] - estimate = None - if resp_num >= param_num: - gain_mat = np.dot( - np.dot( - np.linalg.inv( - cp + np.dot(np.dot(sens_mat_transpose, cr), sens_mat) - ), - sens_mat_transpose, - ), - cr, - ) - - elif resp_num < param_num: - cp_inv = np.linalg.inv(cp) - cr_inv = np.linalg.inv(cr) - gain_mat = np.dot( - np.dot(cp_inv, sens_mat_transpose), - np.linalg.inv( - cr_inv + np.dot(np.dot(sens_mat, cp_inv), sens_mat_transpose) - ), - ) - - else: - raise Exception("Bayesian parameters error") - estimate = [ - p + gr for (p, gr) in zip(current_param, np.dot(gain_mat, -resp_diff)) - ] - return estimate - - def get_updating_outputs(self): - """ - Extracts information of the updating procedure - - :return: - """ - if self.update: - pass - else: - pass - - @staticmethod - def _interpolate_measurements(data_x, data_y, model_x): - """ - Function to interpolate measurement points on numerical/system model given vectors of measurement (1) time seires - , and (2) values. - - This function is used when length missmatch between measurement vector and model output vector. - - """ - # takes in a vector of common x axis e.g. time ratio of positional times over total movement time window (0 to 1) - - # create interp function using measurment data - linear interp - f1 = interp1d(data_x, data_y) - - # apply interp function to ospgrillage data to get respctive positional strain values - return f1(model_x) - # return the decimated curve value diff --git a/src/calabru/utils.py b/src/calabru/utils.py new file mode 100644 index 0000000..4a054f3 --- /dev/null +++ b/src/calabru/utils.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +""" +Utility function module +""" + +import numpy as np +from scipy.interpolate import interp1d +def get_pseudo_inv_estimation(sens_mat, resp_diff): + """ + Estimate parameters for model updating using Pseudo Inverse Method + + Parameters + ---------- + sens_mat: array_like + Sensitivity matrix + resp_diff: list + list of response differences value + + Notes + ----- + The array sizes much match. list of size r by p where r and p are the number of responses and parameters respectively + """ + sens_mat_transpose = np.transpose(sens_mat) + resp_num = np.array(sens_mat).shape[0] + param_num = np.array(sens_mat).shape[1] + # init var + estimate = None + if resp_num == param_num: + estimate = np.dot(np.linalg.inv(sens_mat), resp_diff) + elif resp_num > param_num: + pseudo_inv = np.dot( + np.linalg.inv(np.dot(sens_mat_transpose, sens_mat)), sens_mat_transpose + ) + estimate = np.dot(pseudo_inv, resp_diff) + elif resp_num < param_num: + pseudo_inv = np.dot( + sens_mat_transpose, + np.linalg.inv( + np.dot( + sens_mat, + sens_mat_transpose, + ) + ), + ) + estimate = np.dot(pseudo_inv, resp_diff) + + return estimate + +def calculate_rmse(ref_response_list, current_response_list): + """Get the root mean square error (RMSE) between the reference and current response values + + Parameters + ---------- + ref_response_list: list + list of reference response values + current_response_list: list + list of current response values + + Returns + ------- + float + Root mean square error + + """ + N = len(ref_response_list) + + return np.sqrt( + sum( + [ + (ref - current) ** 2 / N + for (ref, current) in zip(ref_response_list, current_response_list) + ] + ) + ) + +def get_bayesian_param_estimation(sens_mat, resp_diff, current_param, cp, cr): + """ + Function to perform parameter estimation using Bayesian approach. Here, a gain matrix G is calculated + from the provided confidence weighing for parameter and responses. + :param current_param: + :param cp: + :parm cr: + """ + sens_mat_transpose = np.transpose(sens_mat) + resp_num = np.array(sens_mat).shape[0] + param_num = np.array(sens_mat).shape[1] + + # init var + gain_mat = [] + estimate = None + if resp_num >= param_num: + gain_mat = np.dot( + np.dot( + np.linalg.inv( + cp + np.dot(np.dot(sens_mat_transpose, cr), sens_mat) + ), + sens_mat_transpose, + ), + cr, + ) + + elif resp_num < param_num: + cp_inv = np.linalg.inv(cp) + cr_inv = np.linalg.inv(cr) + gain_mat = np.dot( + np.dot(cp_inv, sens_mat_transpose), + np.linalg.inv( + cr_inv + np.dot(np.dot(sens_mat, cp_inv), sens_mat_transpose) + ), + ) + + else: + raise Exception("Bayesian parameters error") + estimate = [ + p + gr for (p, gr) in zip(current_param, np.dot(gain_mat, -resp_diff)) + ] + return estimate + + +def interpolate_measurements(data_x, data_y, model_x): + """ + Returns the interpolation for set of data for a given value, x. + + Parameters + ---------- + + + Function to interpolate measurement points on numerical/system model given vectors of measurement (1) time seires + , and (2) values. + + This function is used when length missmatch between measurement vector and model output vector. + + """ + # takes in a vector of common x axis e.g. time ratio of positional times over total movement time window (0 to 1) + + # create interp function using measurment data - linear interp + f1 = interp1d(data_x, data_y) + + # apply interp function to ospgrillage data to get respctive positional strain values + return f1(model_x) + # return the decimated curve value diff --git a/tests/fixtures.py b/tests/fixtures.py index 18e24e1..b6a6620 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -159,6 +159,150 @@ def beam_with_patch_load(p_matrix: list): return r_mat +def main(p_matrix: list): + # sort parameter variable + + P = 1000 + Iz1 = p_matrix[0] + Iz2 = p_matrix[1] + + # Adopted units: N and m + kilo = 1e3 + milli = 1e-3 + N = 1 + m = 1 + mm = milli * m + m2 = m ** 2 + m3 = m ** 3 + m4 = m ** 4 + kN = kilo * N + MPa = N / ((mm) ** 2) + GPa = kilo * MPa + + # parameters of bridge grillage + L = 10 * m # span + w = 5 * m # width + n_l = 7 # number of longitudinal members + n_t = 10 # number of transverse members + edge_dist = 1 * m # distance between edge beam and first exterior beam + ext_to_int_dist = ( + 2.2775 * m + ) # distance between first exterior beam and first interior beam + angle = 0 # skew angle + mesh_type = "Oblique" + + # define material + concrete = og.create_material( + material="concrete", code="AS5100-2017", grade="65MPa" + ) + + # define sections (parameters from LUSAS model) + edge_longitudinal_section = og.create_section( + A=0.934 * m2, + J=0.1857 * m3, + Iz=Iz2 * m4, + Iy=0.213602 * m4, + Az=0.444795 * m2, + Ay=0.258704 * m2, + ) + + longitudinal_section = og.create_section( + A=1.025 * m2, + J=0.1878 * m3, + Iz=Iz1 * m4, + Iy=0.113887e-3 * m4, + Az=0.0371929 * m2, + Ay=0.0371902 * m2, + ) + + transverse_section = og.create_section( + A=0.504 * m2, + J=5.22303e-3 * m3, + Iy=0.32928 * m4, + Iz=1.3608e-3 * m4, + Ay=0.42 * m2, + Az=0.42 * m2, + ) + + end_transverse_section = og.create_section( + A=0.504 / 2 * m2, + J=2.5012e-3 * m3, + Iy=0.04116 * m4, + Iz=0.6804e-3 * m4, + Ay=0.21 * m2, + Az=0.21 * m2, + ) + + # define grillage members + longitudinal_beam = og.create_member( + section=longitudinal_section, material=concrete + ) + edge_longitudinal_beam = og.create_member( + section=edge_longitudinal_section, material=concrete + ) + transverse_slab = og.create_member(section=transverse_section, material=concrete) + end_transverse_slab = og.create_member( + section=end_transverse_section, material=concrete + ) + + # create grillage + simple_bridge = og.create_grillage( + bridge_name="simple_bridge", + long_dim=L, + width=w, + skew=angle, + num_long_grid=n_l, + num_trans_grid=n_t, + edge_beam_dist=edge_dist, + mesh_type=mesh_type, + ) + + simple_bridge.set_member(longitudinal_beam, member="interior_main_beam") + simple_bridge.set_member(longitudinal_beam, member="exterior_main_beam_1") + simple_bridge.set_member(longitudinal_beam, member="exterior_main_beam_2") + simple_bridge.set_member(edge_longitudinal_beam, member="edge_beam") + simple_bridge.set_member(transverse_slab, member="transverse_slab") + simple_bridge.set_member(end_transverse_slab, member="start_edge") + simple_bridge.set_member(end_transverse_slab, member="end_edge") + simple_bridge.create_osp_model(pyfile=False) + og.opsplt.plot_model() + # add load case + # Patch load over entire bridge deck (P is kN/m2) + P = P * kN / m2 # magnitude of patch vertex + patch_point_1 = og.create_load_vertex(x=0, z=0, p=P) + patch_point_2 = og.create_load_vertex(x=L, z=0, p=P) + patch_point_3 = og.create_load_vertex(x=L, z=w, p=P) + patch_point_4 = og.create_load_vertex(x=0, z=w, p=P) + test_patch_load = og.create_load( + loadtype="patch", + name="Test Load", + point1=patch_point_1, + point2=patch_point_2, + point3=patch_point_3, + point4=patch_point_4, + ) + + test_point_load = og.create_load( + loadtype="point", + name="Test Load", + point1=og.create_load_vertex(x=L / 2, z=w / 2, p=P), + ) + + # Create load case, add loads, and assign + patch_case = og.create_load_case(name="test patch load case") + patch_case.add_load(test_patch_load) + point_case = og.create_load_case(name="test point load case") + point_case.add_load(test_point_load) + # sn8474.add_load_case(patch_case) + simple_bridge.add_load_case(point_case) + + simple_bridge.analyze() + results = simple_bridge.get_results() + + # arbitrary force components + r_mat = [[og.ops.eleForce(25)[1],[og.ops.nodeDisp(n)[1] for n in [2,9,16,23,30,37,44,51,58,65]]]] + + return r_mat def beam_with_patch_load_including_deflected_shape_output(p_matrix: list): """ diff --git a/tests/test_updating.py b/tests/test_updating.py index 3ce5efb..7bdb106 100644 --- a/tests/test_updating.py +++ b/tests/test_updating.py @@ -1,12 +1,10 @@ """ Main module for model calibration """ -import pytest import sys, os -import numpy as np -sys.path.insert(0, os.path.abspath("../")) -from calabru.calibrator import * +sys.path.insert(0, os.path.abspath("../src/calabru")) +from calabru import * import fixtures @@ -18,7 +16,7 @@ def test_basic_update(): """ start = [2000, 0.2] target = [1558.6480741602825, 2956.470189168508] # [-30785, -3801] - simple_beam_updating = ModelUpdating( + simple_beam_updating = Calibrator( function_handle=fixtures.beam_with_patch_load, param_list=start, target_list=target, @@ -34,6 +32,34 @@ def test_basic_update(): ) +def test_main(): + start = [0.2, # load, P + 0.1, # moment of inertia, I + ] + target = [[1047.057906932444, + [0.0, + 3.847756717425916e-05, + 7.335795722107879e-05, + 0.0001001430188545662, + 0.00011472208165921942, + 0.00011472208165922035, + 0.00010014301885456844, + 7.335795722108123e-05, + 3.847756717426085e-05, + 0.0]]] + # node displacements + + simple_beam_updating = Calibrator( + function_handle=fixtures.main, + param_list=start, + target_list=target, + max_error=0.1, + write_output_txt=False + ) + simple_beam_updating.update_model() + print(simple_beam_updating.param_update_history) + + def test_target_resp_as_list(): """ Checks updating using a list of measurements as an element entry of the target measurement. The updating should @@ -55,7 +81,7 @@ def test_target_resp_as_list(): 0.0, ] ] # [-30785, -3801] - simple_beam_updating = ModelUpdating( + simple_beam_updating = Calibrator( function_handle=fixtures.beam_with_patch_load_including_deflected_shape_output, param_list=start, target_list=target, @@ -81,7 +107,7 @@ def test_param_bounds(): # bounds set to first param bounds = [[1500, 3000], []] target = [1558.6480741602825, 2956.470189168508] # [-30785, -3801] - simple_beam_updating = ModelUpdating( + simple_beam_updating = Calibrator( function_handle=fixtures.beam_with_patch_load, param_list=start, target_list=target, @@ -117,7 +143,7 @@ def test_robust(): """ start = [10] # P magnitude of UDL in span 1 target = [65.42524] - pycba_updating = ModelUpdating( + pycba_updating = Calibrator( function_handle=fixtures.pycba_example, param_list=start, target_list=target ) pycba_updating.update_model() @@ -142,7 +168,7 @@ def test_static_truck_pycba(): -149.1317283092082 + np.random.rand(1)[0], -96.10790029773669 + np.random.rand(1)[0], ] - pycba_updating = ModelUpdating( + pycba_updating = Calibrator( function_handle=fixtures.pycba_example_find_ei, param_list=start_ei, target_list=target_def, @@ -278,7 +304,7 @@ def test_moving_truck_pycba(): known_measurement_with_noise = [a + np.random.rand(1)[0] for a in known_measurement] known_target_ei = 100 - pycba_updating = ModelUpdating( + pycba_updating = Calibrator( function_handle=fixtures.pycba_example_moving_veh_ei, param_list=start_ei, target_list=[known_measurement_with_noise],