proteus.outgas.compaction¶
The freezing front on the interior mesh, the percolation and matrix timescales, and the drainage integral that gives the trapped melt fraction.
For how this part works, see Outgassing, rock vapour and volatile trapping.
compaction
¶
Melt drainage from a crystallising mush, and the timescales that limit it.
Melt leaves the pore space of a freezing front only if two things happen: the
melt percolates through the pores, and the solid matrix deforms to close them.
Each has its own timescale and the slower one controls, so the drainage rate of
a parcel at porosity phi is
1 / tau(phi) = 1 / max( L / w_rel(phi), tau_s )
with w_rel the Darcy percolation velocity and tau_s the matrix
deformation time. A parcel entering the front at phi_top and crossing it in
a residence time t_res therefore retains
dphi/dt = -phi / max( L / w_rel(phi), tau_s ), F_vol = phi(t_res)
which is the quantity the trapping bracket needs. This replaces the linear law
F_tl = -(phi_c tau / DeltaT) dT/dt of Sim et al. (2024) Eq. 7 and its two
free parameters: tau becomes the two timescales above, computed from the
solver's own front, and DeltaT disappears because the residence time is
geometric (front thickness over front speed) rather than thermal.
Why the geometric residence time is the better one
The published form writes t_res = DeltaT / |dT/dt| with the potential
temperature of the convecting magma ocean. The freezing front is by definition
the region that has stopped convecting, so that substitution assumes the front
cools at the rate of the ocean above it. Taking t_res = L / v_f from the
front geometry needs no such assumption and removes a parameter at the same
time.
Relation to the solver's own separation velocity
w_rel here is the interior solver's own separation velocity: its
three-regime permeability, aragog.eos.mobility_function (Bower et al. 2018
section 2.1), under the run's separation_buoyancy. Under 'mixture' the
buoyancy is taken against the mixture, (1 - phi) (rho_s - rho_f) g
(McKenzie 1984, Eq. 3.7), on the Blake-Kozeny-Carman and Rumpf-Gupte regimes,
which slows percolation by 30 percent at phi = 0.3; under 'solid', and
in the Stokes regime of a grain settling alone, it is taken against the solid,
(rho_s - rho_f) g (Abe 1995, Eq. 40). McKenzie's solution assumes touching
grains, so it holds for melt fractions below about 0.2, while the front is
entered at the rheological transition, rfront_loc = 0.4 by default; above
about 0.2 the factor is an extrapolation of that solution.
The drainage takes its inputs once per front: the front-mean density
contrast, the front-mean gravity where the interior gives it (else the surface
gravity) and the lever-rule porosity of the front top. The matrix
time keeps the full contrast, tau_s = mu_s / (|drho| g L), under either
buoyancy. The drag viscosity is always the melt viscosity. The solver's
separation_viscosity defaults to 'mixture', the
rheological-transition-blended value, which exceeds the melt viscosity by ten
orders of magnitude at the top of the front and by eighteen to twenty in its
lower half. A drainage estimate built on that traps everything by
construction. Trapping is a sub-grid process the solver does not resolve, so it
uses the melt viscosity regardless of the solver's choice.
test_compaction.py checks the drainage velocity against the solver's own
relative_velocity under each buoyancy.
A caution on calibration
Sim et al. (2024) and Hier-Majumder and Hirschmann (2017) evaluate their drag
coefficient with the tubule permeability of Hier-Majumder (2011),
k = a^2 phi^2 / (72 pi), at a reference porosity of 0.05. That law scales as
phi^2 where the Blake-Kozeny-Carman branch used here scales as phi^3,
and at their calibration point it gives a permeability roughly eighty times
larger. A timescale computed here is therefore a different estimate on a
different microphysical model, not the published number reproduced with the
solver's inputs.
FrontGeometry(index, r_top, r_base, thickness, porosity_top, delta_rho, rho_melt, rho_solid_base, dense_melt, guard_reason='')
dataclass
¶
The freezing front located on the interior mesh at one instant.
darcy_velocity(porosity, grain_size, delta_rho, gravity, melt_visc, *, buoyancy)
¶
Melt percolation speed relative to the matrix [m s-1].
w_D = |delta_rho| g F(phi) / eta_melt, the solver's separation velocity
under buoyancy with the melt viscosity as drag. See the module docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
porosity
|
float or ndarray
|
Volume fraction of melt [1]. |
required |
grain_size
|
float
|
Crystal grain size [m], positive. |
required |
delta_rho
|
float
|
Solid minus melt density [kg m-3]; its magnitude is used. |
required |
gravity
|
float
|
Gravitational acceleration [m s-2]. |
required |
melt_visc
|
float
|
Melt viscosity [Pa s], positive. |
required |
buoyancy
|
str
|
The solver's |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the melt viscosity is not positive, or |
RuntimeError
|
If the speed is negative or not finite. |
Source code in src/proteus/outgas/compaction.py
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | |
drainage_integral(porosity_top, t_res, thickness, grain_size, delta_rho, gravity, melt_visc, mush_visc, *, buoyancy)
¶
Porosity a parcel retains after crossing the front [1].
Integrates dphi/dt = -phi / max(L/w_D(phi), tau_s) from porosity_top
over the residence time, with w_D under buoyancy. w_D falls as
phi^2 down to a porosity of about 3e-5. Below about 3e-6 the mobility tends to
the Stokes residue of the tanh blend, a numerical floor, so the decay turns
exponential, and after a residence far longer than a front's the porosity ends within
the integrator's tolerance of zero. The result is clipped to [0, porosity_top];
an end below 0 by more than the allowance 10 atol, or above porosity_top by more
than 10 atol + rtol porosity_top, raises RuntimeError, as does a non-positive
percolation time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
porosity_top
|
float
|
Melt volume fraction where the parcel enters the front [1]. |
required |
t_res
|
float
|
Residence time of the parcel in the front [s]. A non-positive or
non-finite value returns |
required |
thickness
|
float
|
Front thickness [m]. |
required |
grain_size
|
float
|
Crystal grain size [m]. |
required |
delta_rho
|
float
|
Solid minus melt density across the front [kg m-3]. |
required |
gravity
|
float
|
Gravitational acceleration [m s-2]. |
required |
melt_visc
|
float
|
Melt viscosity [Pa s]. |
required |
mush_visc
|
float
|
Shear viscosity of the mush [Pa s]. |
required |
buoyancy
|
str
|
The solver's |
required |
Returns:
| Type | Description |
|---|---|
tuple
|
Retained volume fraction, the percolation time at the entry porosity [s], and the matrix deformation time [s]. |
Source code in src/proteus/outgas/compaction.py
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | |
locate_front(radius, melt_fraction, porosity, rho_solid, rho_melt, rfront_loc, phi_min, n_front_min=3, max_front_fraction=1.0, r_floor=None)
¶
Locate the freezing front on the interior mesh.
The front runs from the node where the solver melt fraction crosses
rfront_loc at the top down to the node where the porosity falls to
phi_min at the base. Using the solver's own melt fraction and its own
rheological transition for the top means the front trapping uses is the
front the solver uses for its rheology, rather than a second threshold that
could disagree with it.
A mantle crystallising from the bottom up is often still porous at its lowest node. The front then rests on the core-mantle boundary, which is impermeable, and that boundary is its base: the melt in it drains upward only, as it does from a front sitting on compacted cumulate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
r_floor
|
float or None
|
Radius of the impermeable lower boundary of the mantle [m], the base of a front that is still porous at the lowest node. Defaults to the lowest node radius. Must not lie above it. |
None
|
Returns:
| Type | Description |
|---|---|
tuple
|
The geometry and a branch code. The geometry is |
Source code in src/proteus/outgas/compaction.py
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 | |
matrix_time(mush_visc, delta_rho, gravity, thickness)
¶
Matrix deformation time [s], McKenzie (1984) compaction viscosity.
tau_s = mu_s / (delta_rho g L). The compaction pressure delta_rho g L
drives a volumetric strain rate against the bulk viscosity zeta = mu_s/phi,
and closing a porosity phi takes phi zeta / (delta_rho g L), which is
independent of porosity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mush_visc
|
float
|
Shear viscosity of the mush [Pa s]. |
required |
delta_rho
|
float
|
Solid minus melt density [kg m-3]; its magnitude is used. |
required |
gravity
|
float
|
Gravitational acceleration [m s-2]. |
required |
thickness
|
float
|
Front thickness [m]. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Deformation time [s]; infinite when |
Source code in src/proteus/outgas/compaction.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | |
mobility_function(porosity, grain_size, *, buoyancy)
¶
Permeability over porosity, F = K / phi [m2], of the solver's separation law.
aragog.eos.mobility_function: the three regimes of Bower et al. (2018)
section 2.1, Blake-Kozeny-Carman a^2 phi^2 / ((1-phi)^2 * 1000),
Rumpf-Gupte a^2 phi^4.5 * 5/7 and Stokes a^2 * 2/9, blended with tanh
weights; under buoyancy = 'mixture' the first two carry 1 - phi.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
porosity
|
float or ndarray
|
Volume fraction of melt [1]. |
required |
grain_size
|
float
|
Crystal grain size [m]. |
required |
buoyancy
|
str
|
The solver's |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/proteus/outgas/compaction.py
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 | |
porosity_from_densities(rho, rho_solid, rho_melt, melt_fraction)
¶
Volume fraction of melt from the mixture and end-member densities [1].
Inside the mush, phi = (rho_s - rho) / (rho_s - rho_l), the lever rule
on density. The interior solver builds the mush density from the same two
phase-boundary densities, so the rule returns the melt volume fraction
exactly whichever phase is denser: where the tabulated melt is denser than
the solid, numerator and denominator are both negative and their ratio is
still the positive melt volume. The solver's own separation flux floors the
denominator there instead, to stop settling where the melt reads as the
denser phase; that floor would read such a mush as solid rock and cut the
front short, so it is not applied here.
A node that is fully solid or fully molten takes its melt fraction, 0 or 1. The solver evaluates its density on the single-phase table at the node's own entropy rather than as a two-phase mixture, so the lever rule does not hold there: a cold solid denser than the solid at the phase boundary would otherwise read as porous wherever the melt is the denser phase. Where the two phase-boundary densities are equal the rule is 0/0, and mass and volume fractions coincide, so the melt fraction is used there too. The result is clipped to [0, 1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rho
|
ndarray
|
Mixture density [kg m-3]. |
required |
rho_solid
|
ndarray
|
Solid and melt densities at the phase boundary [kg m-3]. |
required |
rho_melt
|
ndarray
|
Solid and melt densities at the phase boundary [kg m-3]. |
required |
melt_fraction
|
ndarray
|
Melt mass fraction of the interior solver [1]. |
required |
Source code in src/proteus/outgas/compaction.py
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | |
volume_to_mass_fraction(f_vol, rho_melt, rho_solid)
¶
Convert a trapped melt volume fraction to the mass fraction the budget uses.
F_tl is a volume fraction in the compaction physics, where the
disaggregation limit is a geometric packing threshold, and a mass fraction in
the volatile budget. The two differ by the melt-to-mixture density ratio,
about 0.93 at a ten percent density contrast and a porosity of 0.3. The
conversion is applied once, here, to every fraction the front scheme hands
to the budget.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f_vol
|
float
|
Melt volume fraction [1]; clipped to [0, 1]. |
required |
rho_melt
|
float
|
Melt and solid densities [kg m-3]. |
required |
rho_solid
|
float
|
Melt and solid densities [kg m-3]. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Melt mass fraction [1]. Where the mixture density is not positive or not finite, the clipped volume fraction is returned unchanged. |
Source code in src/proteus/outgas/compaction.py
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | |