Skip to content

Commit

Permalink
Merge pull request #151 from boschresearch/docs-improvements
Browse files Browse the repository at this point in the history
Docs improvements
  • Loading branch information
johannes-mueller authored Dec 17, 2024
2 parents 936159c + f778dc9 commit b147b9e
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 21 deletions.
130 changes: 128 additions & 2 deletions docs/broadcaster.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,132 @@ example the the calls to the :class:`pylife.Broadcaster` are done inside
You do need to deal with the :class:`pylife.Broadcaster` when you implement new
calculation methods. Let's go through an example.

.. todo::
Lets assume we have a collective of seasonal flood events on the river Vitava
in Prague. This is an oversimplified damage model, which assumes that we
multiply the water level of a flood event with a sensitivity value of a bridge
to calculate the damage that the flood events causes to the bridge.

**Sorry**, this is still to be written.
.. jupyter-execute::

from pylife import Broadcaster

flood_events = pd.Series(
[10., 13., 9., 5.],
name="water_level",
index=pd.Index(
["spring", "summer", "autumn", "winter"],
name="flood_event"
)
)
flood_events

Lets assume some sensitivity value for the bridges of Prague.

.. jupyter-execute::

sensitivities = pd.Series([2.3, 0.7, 2.7, 6.4, 3.9, 0.8],
name="sensitivity",
index=pd.Index(
[
"Palackého most",
"Jiraskův most",
"Most Legií",
"Karlův most",
"Mánesův most",
"Centrův most"
],
name="bridge"
)
)
sensitivities


Now we want to multiply the water levels with the sensitivity value in order
to get a damage value:

.. jupyter-execute::

damage = flood_events * sensitivities
damage

As we can see, this multiplication failed, as the indices of our two series do
not match. First we need to broadcast the two indices to a mapped hierarchical
index.

.. jupyter-execute::

sens_mapped, flood_mapped = Broadcaster(flood_events).broadcast(sensitivities)

Now we have a mapped flood values

.. jupyter-execute::

flood_mapped

and the mapped sensitivity values

.. jupyter-execute::

sens_mapped

These mapped series we can multiply.

.. jupyter-execute::

damage = flood_mapped * sens_mapped
damage

Now we can see for every bridge for every flood event the expected damage to
every bridge. We can now reduce this map to get the total damage of every
bridge during all flood events:

.. jupyter-execute::

damage.groupby("bridge").sum()


Now let's assume that we have for each bridge some kind of protection measure
that reduces the damage.

.. jupyter-execute::

protection = pd.Series(
[10.0, 15.0, 12.0, 25.0, 13.0, 17.0],
name="dwell_time",
index=pd.Index(
[
"Palackého most",
"Jiraskův most",
"Most Legií",
"Karlův most",
"Mánesův most",
"Centrův most"
],
name="bridge"
)
)
protection

We also need divide the damage value by the protection value. Therefore we need
to broadcast the protection values to the damage values

.. jupyter-execute::

protection_mapped, _ = Broadcaster(damage).broadcast(protection)
protection_mapped

As you can see, the broadcaster recognized the common index name "bridge" and
did not spread it again.

Now we can easily multiply the mapped protection values to the damage.

.. jupyter-execute::

damage_with_protection = damage / protection


And we can again easily calculate the damage for a certain bridge

.. jupyter-execute::

damage_with_protection.groupby("bridge").sum()
3 changes: 1 addition & 2 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ Stress
stress/index
stress/equistress
stress/rainflow
stress/load_collective
stress/load_histogram
stress/collective
stress/stresssignal
stress/timesignal
stress/frequencysignal
Expand Down
6 changes: 6 additions & 0 deletions docs/stress/collective.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The module for load collectives
###############################

.. automodule:: pylife.stress.collective
:undoc-members:
:members:
6 changes: 0 additions & 6 deletions docs/stress/load_collective.rst

This file was deleted.

6 changes: 0 additions & 6 deletions docs/stress/load_histogram.rst

This file was deleted.

10 changes: 5 additions & 5 deletions docs/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ computer, you can use `MyBinder
.. toctree::
:maxdepth: 1

tutorials/woehler_curve.nblink
tutorials/load_collective.nblink
tutorials/stress-strength.rst
demos/fkm_nonlinear.nblink
demos/fkm_nonlinear_full.nblink
tutorials/woehler_curve
tutorials/load_collective
tutorials/stress-strength
demos/fkm_nonlinear
demos/fkm_nonlinear_full
17 changes: 17 additions & 0 deletions src/pylife/stress/collective/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.

"""
There are two ways to deal with a load collective.
* :class:`~pylife.stress.LoadCollective` lets you keep every load hysteresis in
and then calculate the amplitude, meanstress and damage for each and every
hyteresis indivudually.
* :class:`~pylife.stress.LoadHistogram` keeps the load information in a binned
histogram. That means that not each and every hystresis is stored
individually but there are bin classes for the load levels the hysteresis is
originating from and one for the levels the hysteresis is open.
This :doc:`tutorial </tutorials/load_collective>` shows the difference and how
to use the two.
"""

__author__ = "Johannes Mueller"
__maintainer__ = __author__

Expand Down

0 comments on commit b147b9e

Please sign in to comment.