Skip to content

memento

BalanceEngineCaretaker

BalanceEngineCaretaker(engine: BalanceEngine)

Dedicated class responsible for saving and restoring BalanceEngine state.

Implements the Caretaker role of the Memento pattern. The engine itself (the Originator) is not modified — all snapshot logic lives here.

Parameters:

Name Type Description Default

engine

BalanceEngine

The balance engine whose state is managed.

required
Source code in src/mechaphlowers/core/models/balance/memento.py
71
72
def __init__(self, engine: BalanceEngine) -> None:
    self._engine = engine

restore

restore(memento: BalanceEngineMemento) -> None

Restore the engine's mutable state from a previously saved memento.

After restoration all internal caches (span geometry, deformation snapshots, node projections, moments) are refreshed so the engine is immediately ready for a new solve.

Parameters:

Name Type Description Default

memento

BalanceEngineMemento

Snapshot previously returned by save.

required
Source code in src/mechaphlowers/core/models/balance/memento.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def restore(self, memento: BalanceEngineMemento) -> None:
    """Restore the engine's mutable state from a previously saved memento.

    After restoration all internal caches (span geometry, deformation
    snapshots, node projections, moments) are refreshed so the engine is
    immediately ready for a new solve.

    Args:
        memento (BalanceEngineMemento): Snapshot previously returned by
            [`save`][mechaphlowers.core.models.balance.memento.BalanceEngineCaretaker.save].
    """
    engine = self._engine
    bm = engine.balance_model

    # (a) Restore nodes — in-place write preserves array identity

    # (b) Restore balance_model scalars / arrays
    bm.parameter = memento.parameter.copy()
    bm.sagging_temperature = memento.sagging_temperature.copy()
    bm.adjustment = memento.adjustment
    bm.Th = memento.Th.copy()
    bm.Tv_d = memento.Tv_d.copy()
    bm.Tv_g = memento.Tv_g.copy()
    bm.a = memento.a.copy()
    bm.b = memento.b.copy()

    # (c) Restore span_model arrays + refresh cached _x_m/_x_n/_L
    engine.span_model.parameter = memento.span_sagging_parameter.copy()
    engine.span_model.span_length = memento.span_span_length.copy()
    engine.span_model.elevation_difference = (
        memento.span_elevation_difference.copy()
    )
    engine.span_model.load_coefficient = (
        memento.span_load_coefficient.copy()
    )
    engine.span_model.compute_values()

    # (d) Restore cable_loads
    engine.cable_loads.wind_pressure = memento.wind_pressure.copy()
    engine.cable_loads.ice_thickness = memento.ice_thickness.copy()

    # (e) Restore deformation_model (snapshots, not refs)
    engine.deformation_model.current_temperature = (
        memento.deformation_current_temperature.copy()
    )
    engine.deformation_model.tension_mean = (
        memento.deformation_tension_mean.copy()
    )
    engine.deformation_model.cable_length = (
        memento.deformation_cable_length.copy()
    )

    # (f) L_ref
    if memento.L_ref is not None:
        engine.L_ref = memento.L_ref.copy()
    elif hasattr(engine, "L_ref"):
        del engine.L_ref

    # (g) Re-sync derived objects

    bm.sync_after_memento_restore(engine.span_model, memento.dxdydz)

    logger.debug("Balance engine state restored from memento.")

save

Create an immutable snapshot of the engine's current mutable state.

Returns:

Name Type Description
BalanceEngineMemento BalanceEngineMemento

Independent copy of every mutable array.

Source code in src/mechaphlowers/core/models/balance/memento.py
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def save(self) -> BalanceEngineMemento:
    """Create an immutable snapshot of the engine's current mutable state.

    Returns:
        BalanceEngineMemento: Independent copy of every mutable array.
    """
    engine = self._engine
    bm = engine.balance_model
    return BalanceEngineMemento(
        dxdydz=bm.get_dxdydz().copy(),
        parameter=bm.parameter.copy(),
        sagging_temperature=bm.sagging_temperature.copy(),
        adjustment=bm.adjustment,
        Th=bm.Th.copy(),
        Tv_d=bm.Tv_d.copy(),
        Tv_g=bm.Tv_g.copy(),
        a=bm.a.copy(),
        b=bm.b.copy(),
        span_sagging_parameter=engine.span_model.parameter.copy(),
        span_span_length=engine.span_model.span_length.copy(),
        span_elevation_difference=engine.span_model.elevation_difference.copy(),
        span_load_coefficient=engine.span_model.load_coefficient.copy(),
        wind_pressure=engine.cable_loads.wind_pressure.copy(),
        ice_thickness=engine.cable_loads.ice_thickness.copy(),
        deformation_current_temperature=engine.deformation_model.current_temperature.copy(),
        deformation_tension_mean=engine.deformation_model.tension_mean.copy(),
        deformation_cable_length=engine.deformation_model.cable_length.copy(),
        L_ref=np.array(engine.L_ref).copy()
        if hasattr(engine, "L_ref")
        else None,
    )

BalanceEngineMemento dataclass

BalanceEngineMemento(
    dxdydz: ndarray,
    parameter: ndarray,
    sagging_temperature: ndarray,
    adjustment: bool,
    Th: ndarray,
    Tv_d: ndarray,
    Tv_g: ndarray,
    a: ndarray,
    b: ndarray,
    span_sagging_parameter: ndarray,
    span_span_length: ndarray,
    span_elevation_difference: ndarray,
    span_load_coefficient: ndarray,
    wind_pressure: ndarray,
    ice_thickness: ndarray,
    deformation_current_temperature: ndarray,
    deformation_tension_mean: ndarray,
    deformation_cable_length: ndarray,
    L_ref: Optional[ndarray],
)

Immutable snapshot of a BalanceEngine's mutable state.

Every numpy array stored here is an independent copy (via .copy()) so mutating the originals after saving will not affect the memento.