Skip to content

proteus.outgas.burial_ledger

Where trapping buried each volatile, in melt-fraction coordinates, so that a remelt returns the most recent burial first.

For how this part works, see Outgassing, rock vapour and volatile trapping.

burial_ledger

Where trapping buried each volatile, in melt-fraction coordinates.

A crystallising step buries mass into the solid that froze while the global melt fraction fell from Phi(t-1) to Phi(t). The ledger records that mass against that interval of melt fraction, one layer per step. The solid that remelts first is the solid that froze last, so a remelt to Phi returns the mass recorded below Phi, and freezing and remelting the same interval cancel exactly.

The ledger is rebuilt from the helpfile history, Phi_global and the _kg_trapped columns, so it keeps no state of its own and survives a resume.

Layer(lo, hi, mass) dataclass

Mass buried while the melt fraction fell from hi to lo.

Attributes:

Name Type Description
lo, hi float

Global melt fraction at the end and at the start of the burial [1].

mass ndarray

Mass buried per trapped column [kg].

build_ledger(phi, trapped)

Replay a history of melt fraction and trapped mass into burial layers.

Parameters:

Name Type Description Default
phi ndarray

Global melt fraction of each completed step, shape (N,) [1].

required
trapped ndarray

Trapped mass of each tracked column at each step, shape (N, K) [kg].

required

Returns:

Type Description
list of Layer

The layers still buried at the end of the history, the most recent last.

Source code in src/proteus/outgas/burial_ledger.py
71
72
73
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
def build_ledger(phi: np.ndarray, trapped: np.ndarray) -> list[Layer]:
    """Replay a history of melt fraction and trapped mass into burial layers.

    Parameters
    ----------
    phi : ndarray
        Global melt fraction of each completed step, shape (N,) [1].
    trapped : ndarray
        Trapped mass of each tracked column at each step, shape (N, K) [kg].

    Returns
    -------
    list of Layer
        The layers still buried at the end of the history, the most recent last.
    """
    phi = np.asarray(phi, dtype=float)
    trapped = np.nan_to_num(np.asarray(trapped, dtype=float))
    layers: list[Layer] = []
    for i in range(1, phi.size):
        before, after = phi[i - 1], phi[i]
        if not (np.isfinite(before) and np.isfinite(after)) or after == before:
            continue
        if after < before:
            buried = np.maximum(trapped[i] - trapped[i - 1], 0.0)
            layers.append(Layer(lo=float(after), hi=float(before), mass=buried))
        else:
            remelt_to(layers, float(after))
    return layers

ledger_total(layers, n_columns)

Mass the ledger holds per column [kg].

Source code in src/proteus/outgas/burial_ledger.py
101
102
103
def ledger_total(layers: list[Layer], n_columns: int) -> np.ndarray:
    """Mass the ledger holds per column [kg]."""
    return sum((layer.mass for layer in layers), np.zeros(n_columns))

remelt_to(layers, phi)

Remove and return the mass buried below melt fraction phi [kg].

layers is ordered as built, the most recent last, which is also the lowest in melt fraction. It is changed in place.

Parameters:

Name Type Description Default
layers list of Layer

The burial layers, most recent last.

required
phi float

Global melt fraction the mantle remelts to [1].

required

Returns:

Type Description
ndarray

Mass released per trapped column [kg].

Source code in src/proteus/outgas/burial_ledger.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
def remelt_to(layers: list[Layer], phi: float) -> np.ndarray:
    """Remove and return the mass buried below melt fraction ``phi`` [kg].

    ``layers`` is ordered as built, the most recent last, which is also the
    lowest in melt fraction. It is changed in place.

    Parameters
    ----------
    layers : list of Layer
        The burial layers, most recent last.
    phi : float
        Global melt fraction the mantle remelts to [1].

    Returns
    -------
    ndarray
        Mass released per trapped column [kg].
    """
    released = np.zeros_like(layers[0].mass) if layers else np.zeros(0)
    while layers and layers[-1].lo < phi:
        top = layers[-1]
        if top.hi <= phi:
            released = released + top.mass
            layers.pop()
            continue
        share = (phi - top.lo) / (top.hi - top.lo)
        released = released + share * top.mass
        top.mass = (1.0 - share) * top.mass
        top.lo = phi
        break
    return released