Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs improvements #151

Merged
merged 2 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading