Exemple #1
0
 def __init__(self):
     self.name = self.name_base
     SubductionCase.__init__(self,u(130,"Myr"),u(75,"Myr"))
     # Solve to imaginary model division to make
     # model outputs align with farallon-reheated case
     self.fake_underplating_time = u(24,'Myr')
     self.variable_term = 'qfric'
Exemple #2
0
    def run(self):

        plot_opts = dict(
            range=(0,1500))

        crust = continental_crust.to_layer(interface_depth)
        solver = FiniteSolver(crust,
            constraints=(u(0,"degC"),u(600,"degC")))
        # Assume arbitrarily that interface is at 600 degC

        crust_section = solver.steady_state()

        mantle = oceanic_mantle.to_layer(total_depth-interface_depth)
        mantle = Section([mantle])

        # Set starting state
        section = stack_sections(crust_section, mantle)
        adiabat = AdiabatSolver(
            section,
            start_depth=self.underplating_depth,
            start_temp=asthenosphere_temperature)

        self.t = self.start_time
        self.section = adiabat()
        self.record("initial")
        self.do_underplating()
        self.solve_to_present()
Exemple #3
0
 def __init__(self, dT):
     Farallon.__init__(self)
     self.name = self.name_base+'-'+str(dT)
     self.underplating_duration = u(dT,'Myr')
     self.underplating_depth = u(80,'km')
     self.underplating_time = u(24,'Myr')
     self.variable_term = 'qfric'
Exemple #4
0
 def __init__(self, dT):
     ModelRunner.__init__(self)
     self.name = self.name_base+'-'+str(dT)
     self.underplating_duration = u(dT,'Myr')
     self.underplating_depth = u(30,'km')
     self.underplating_time = u(24,'Myr')
     self.start_time = self.underplating_time
Exemple #5
0
def geobaric_gradient(pressure):
    rho0 = continental_crust.density
    g = u(9.8,'m/s^2')
    P = u(pressure,'GPa')
    rho1 = oceanic_mantle.density
    d0 = interface_depth

    a0 = P/g/rho0
    if a0 < d0:
        return a0.into('km')

    a = P/g - rho0*d0 + rho1*d0
    a/=rho1
    return a.into('km')
Exemple #6
0
    def run(self):
        section = steady_state_section

        for flux in ((i+12)*5 for i in range(13)):
            q = u(flux,'mW/m^2')
            # Use steady-state model that assumes
            # a reasonable reduced heat flux from
            # the mantle, rather than that which
            # sums radiogenic heat.
            s = steady_state_mantle(section,q,
                    characteristic_scale=u(10,'km'),
                    heatflow_mantle_proportion=0.6)
            self.record(s,flux)
            echo("Saving section for "
                 +style(str(q), fg='green')
                 +" surface heat flux")
Exemple #7
0
        def on_step(solver, **kwargs):
            """
            Function to change finite solver
            boundary conditions at each step
            """
            self.step_function(solver, **kwargs)

            step = kwargs.pop("step")
            steps = kwargs.pop("steps")

            # How complete we will be at the
            # end of this step
            completion = (step + 1) / steps

            sz_depth = final_depth * completion
            # Decrease depth offset
            self.depth_offset = final_depth - sz_depth
            self._top_depth = sz_depth

            # Set temperature at the subduction
            # interface
            T = royden(
                (final_distance * completion).into("m"),
                sz_depth.into("m"),  # Depth of interest
                sz_depth.into("m"))  # Depth of subduction interface

            solver.set_constraints(upper=u(T, "degC"))
Exemple #8
0
    def do_underplating(self):
        self.record("before-underplating")

        dT = self.underplating_duration

        temp = asthenosphere_temperature

        adiabat = AdiabatSolver(
            self.section,
            start_depth=self.underplating_depth,
            start_temp=temp)
        # Apply adiabat to section
        self.section = adiabat()

        self.record("underplating-started", self.section)

        if dT.into('s') > 0:
            # We're holding the temperature
            # at the boundary for some length of time
            top, bottom = self.section.divide(self.underplating_depth)

            solver = FiniteSolver(top,
                constraints=(u(0,'degC'),temp),
                step_function=self.step_function)

            dTdz = adiabat.gradient[0]
            k = bottom.material_property('conductivity')[0]
            flux = -k*dTdz

            solver.set_constraints(lower=flux)
            res = solver(dT).profile
            self.section.profile[:len(res)] = res
            self.t -= dT

        self.record("underplating-ended")
        # Record a later timestep
        dT =  u(6,'Myr') - dT
        if dT > u(0,'s'):
            self.finite_solve(self.t-dT)
        self.record("after-underplating")
Exemple #9
0
def underplating():
    name = "Underplating"
    print(name)

    start = u(20,"Myr")

    slab_window_upwelling = Section([
        oceanic_mantle.to_layer(u(100,"km"))
    ], uniform_temperature=u(1300,"degC"))

    final_section = stack_sections(
        forearc,
        slab_window_upwelling)

    solver = AdvancedFiniteSolver(
        final_section,
        constraints=solver_constraints)

    return solver.solution(
        duration=start-present,
        steps=200,
        plotter=Plotter(range=(0,1400), title=name))
Exemple #10
0
    def finite_solve(self, end_time, **kwargs):
        defaults = dict(
            constraints = (u(0,"degC"), self.section.profile[-1]),
            step_function = self.step_function)

        for k,v in defaults.items():
            if k not in kwargs:
                kwargs[k] = v

        self.log("Initializing finite solver")
        self.log("Constraints")
        labels = ('upper','lower')
        for l,c in zip(labels,kwargs['constraints']):
            self.log("    - "+l,c)
        duration = self.t - end_time
        solver = FiniteSolver(self.section, **kwargs)
        self.set_state(end_time,solver(duration))
Exemple #11
0
    def pre_subduction(self):
        """
        Get an oceanic geotherm at emplacement and just before
        subduction begins.
        """
        self.log("Start age", self.start_time)
        self.log("Subduction", self.subduction_time)

        oceanic = Section(
            [oceanic_mantle.to_layer(total_depth - interface_depth)])

        ocean_model = GDHSolver(oceanic, T_max=solver_constraints[1])
        t = u(0, "s")
        self.set_state(self.start_time, ocean_model(t))
        self.record("initial")

        dt = self.t - self.subduction_time
        self.set_state(self.subduction_time, ocean_model(dt))
        self.record("before-subduction")
Exemple #12
0
    def trace(self, depth, t=None):

        if self.depth_offset is None:
            _depth = depth
        else:
            _depth = depth - self.depth_offset

        assert _depth >= u(0,'km')

        if t is None: t = self.t

        # Because we are dealing with
        # final section only
        cell = int((_depth-self._top_depth).into('m')/self.dz)
        T = self.section.profile[cell]

        v = ModelTracer(
            run=self.__model,
            time=t.into("Myr"),
            final_depth=depth.into("km"),
            depth=_depth.into("km"),
            temperature=T.into("degC"))
        self.session.add(v)
Exemple #13
0
    def stepped_subduction(self, **kwargs):
        """
        Method to subduct crust under a forearc
        with a geotherm modeled over a period of
        time, and capture a snapshot of underplating.

        The `velocity` option defines a subduction velocity
        that is used to move the subducting slab down the
        channel.

        If the `final_temperature` option is not set,
        the procedure will infer the final temperature
        of the subducted slab from a steady-state subduction
        geometery, using the method of Royden (1992).

        If the `final_temperature` option is set,
        the procedure will target that temperature
        at the final conditions of the interface.
        In this case, the Royden model parameters
        for this temperature will be found via optimization.
        """

        final_distance = kwargs.pop("final_distance", underplating_distance)
        velocity = kwargs.pop("velocity", convergence_velocity)
        final_depth = kwargs.pop("final_depth", interface_depth)

        final_temperature = kwargs.pop("final_temperature", None)
        optimization_depth = kwargs.pop("optimization_depth", final_depth)

        # Thickness of foreland lithosphere
        # at the time of subduction
        # Presumably, foreland in this case refers
        # to the lower plate of the thrust advancing
        # into the subduction zone
        # The Royden model assumes that the foreland
        # is in thermal equilibrium, and the lithospheric
        # depth is being maintained, which is likely a
        # reasonable approximation for the timescales involved.
        self.log("Subduction velocity", velocity)

        dip = N.arctan(final_depth / final_distance).to("degrees")
        self.log("Dip of subduction zone", dip)

        # distance along subduction channel
        sub_distance = N.sqrt(final_distance**2 + final_depth**2)
        duration = (sub_distance / velocity).to("Myr")
        self.log("Duration of subduction", duration)

        echo("Beginning to subduct slab")

        kwargs.update(l=lithosphere_depth(self.section).into("m"),
                      v=velocity.into("m/s"))

        self.log("Lithosphere depth", kwargs['l'])

        if final_temperature is None:
            royden = forearc_solver(**kwargs)
        else:
            # Optimize on rate of accretion
            royden = optimized_forearc(
                final_temperature,
                final_distance,
                # Optimize temperature above subduction
                # interface
                optimization_depth,
                **kwargs)
            self.log("Modeled upper-plate heat generation",
                     royden.args[kwargs['vary']])

        def on_step(solver, **kwargs):
            """
            Function to change finite solver
            boundary conditions at each step
            """
            self.step_function(solver, **kwargs)

            step = kwargs.pop("step")
            steps = kwargs.pop("steps")

            # How complete we will be at the
            # end of this step
            completion = (step + 1) / steps

            sz_depth = final_depth * completion
            # Decrease depth offset
            self.depth_offset = final_depth - sz_depth
            self._top_depth = sz_depth

            # Set temperature at the subduction
            # interface
            T = royden(
                (final_distance * completion).into("m"),
                sz_depth.into("m"),  # Depth of interest
                sz_depth.into("m"))  # Depth of subduction interface

            solver.set_constraints(upper=u(T, "degC"))

        # Set up finite solving for underplated slab
        kwargs['step_function'] = on_step
        i = self.section.profile[-1]
        solver = FiniteSolver(self.section, constraints=(u(0, 'degC'), i))
        underplated = solver.final_section(duration=duration, **kwargs)

        # Construct the forearc geotherm
        forearc = Section(continental_crust.to_layer(final_depth))

        temperatures = royden(final_distance.into("m"),
                              forearc.cell_centers.into("m"),
                              final_depth.into("m"))

        forearc.profile = u(temperatures, "degC")

        self.log(
            "Temperature at subduction interface "
            "at the time of underplating", forearc.profile[-1])
        self.log("Subduction took", duration.to("Myr"))

        self.section = stack_sections(forearc, underplated)
        self.t -= duration
        self._top_depth = u(0, 'km')
        self.depth_offset = u(0, 'km')
        self.record("after-subduction")
Exemple #14
0
class ModelRunner(object):
    trace_depths = u(40,'km'),u(75,'km')
    # Offset used for depth calculations for model tracers.
    # Reset when geotherms are stacked.
    depth_offset = None
    fields = (
        "underplating_duration",
        "underplating_depth",
        "underplating_time",
        "start_time",
        "subduction_time")
    name_base = None
    def __init__(self, **info):
        self._top_depth = u(0,'km')
        for i in self.fields:
            setattr(self,i,None)

    def run(self):
        pass

    def set_state(self,time,section):
        self.t = time
        self.section = section

    def step_function(self, model=None, **kwargs):
        """
        Step function for finite element solver that records model tracers
        """
        t = self.t
        dt = kwargs.pop('simulation_time', None)
        if dt is not None:
            t -= dt
        if model is not None:
            v = model.value()
            self.section.profile[:len(v)] = v
        for depth in self.trace_depths:
            self.trace(depth, t=t)

    def finite_solve(self, end_time, **kwargs):
        defaults = dict(
            constraints = (u(0,"degC"), self.section.profile[-1]),
            step_function = self.step_function)

        for k,v in defaults.items():
            if k not in kwargs:
                kwargs[k] = v

        self.log("Initializing finite solver")
        self.log("Constraints")
        labels = ('upper','lower')
        for l,c in zip(labels,kwargs['constraints']):
            self.log("    - "+l,c)
        duration = self.t - end_time
        solver = FiniteSolver(self.section, **kwargs)
        self.set_state(end_time,solver(duration))

    def solve_to_present(self):
        self.finite_solve(present)
        # Record a final step
        self.step_function()
        self.record("final")

    def section_data(self, section):
        # Check if all cells are the same size
        z_ = section.cell_sizes.into('m')
        self.dz = z_[0]
        self.n_cells = int(record_max_depth.into('m')/self.dz)
        assert N.all(z_ == self.dz)
        T = list(section.profile[:self.n_cells].into("degC"))
        return T, self.dz

    def record(self, step_name, section=None, **kwargs):
        t = kwargs.pop("t",self.t).into("Myr")
        if section is None:
            section = self.section

        self.log("Saving profile "+style(step_name, fg='cyan'))

        T, dz = self.section_data(section)
        v = ModelProfile(
            name=step_name, time=t,
            run=self.__model, temperature=T, dz=dz)
        self.session.add(v)

    def setup_recorder(self):
        self.session = db.session()
        kw = dict(name=self.name)

        model = (self.session
            .query(ModelRun)
            .filter_by(**kw)
            .first())
        if model is not None:
            secho("Deleting data from previous run", fg='red')
            self.session.delete(model)
            self.session.commit()

        vals = {k:getattr(self,k) for k in self.fields}
        kw.update({k: v.into(
                'km' if k == 'underplating_depth'
                else 'Myr')
            for k,v in vals.items()
            if v is not None})
        kw['type'] = self.name_base
        self.__model = ModelRun(**kw)
        self.session.add(self.__model)

    def trace(self, depth, t=None):

        if self.depth_offset is None:
            _depth = depth
        else:
            _depth = depth - self.depth_offset

        assert _depth >= u(0,'km')

        if t is None: t = self.t

        # Because we are dealing with
        # final section only
        cell = int((_depth-self._top_depth).into('m')/self.dz)
        T = self.section.profile[cell]

        v = ModelTracer(
            run=self.__model,
            time=t.into("Myr"),
            final_depth=depth.into("km"),
            depth=_depth.into("km"),
            temperature=T.into("degC"))
        self.session.add(v)

    def log(self, message, data=None):
        if data is None:
            echo(message)
            return

        width = 30
        start = message+": "
        dt = width-len(start)
        start += " "*dt
        echo(start+style(str(data),fg='green'))

    def __call__(self, *args, **kwargs):
        self.setup_recorder()
        try:
            self.run(*args,**kwargs)
        finally:
            self.session.commit()
Exemple #15
0
import numpy as N
from click import echo, secho, style
from geotherm.solvers import FiniteSolver
from geotherm.plot import Plotter
from geotherm.units import u

from .config import (
    record_max_depth,
    solver_constraints,
    present)
from .database import db
from .database.models import meta, ModelRun, ModelTracer, ModelProfile

FiniteSolver.set_defaults(
    type="implicit",
    time_step=u(0.5,"Myr"),
    constraints=solver_constraints,
    plotter=Plotter(range=(0,1600)))

class ModelRunner(object):
    trace_depths = u(40,'km'),u(75,'km')
    # Offset used for depth calculations for model tracers.
    # Reset when geotherms are stacked.
    depth_offset = None
    fields = (
        "underplating_duration",
        "underplating_depth",
        "underplating_time",
        "start_time",
        "subduction_time")
    name_base = None
Exemple #16
0
 def __init__(self, **info):
     self._top_depth = u(0,'km')
     for i in self.fields:
         setattr(self,i,None)
Exemple #17
0
 def __init__(self, sub_age, oc_age):
     self.name = "{0}-{1}-{2}".format(self.name_base,sub_age,oc_age)
     args = (u(sub_age+oc_age,"Myr"), u(sub_age,"Myr"))
     SubductionCase.__init__(self, *args)
Exemple #18
0
    for dT in (0,2,4,6):
        case =  FarallonReheated(dT)
        registry[case.name] = case

        case = Underplated(dT)
        registry[case.name] = case

    # Run scenarios requested
    if all:
        scenarios = registry.keys()
    if len(scenarios) == 0:
        click.echo("Specify scenario names or --all")
        click.echo("Possible scenarios:")
        for i in registry:
            click.echo("  "+i)
        return

    FiniteSolver.set_defaults(type=
        'implicit' if implicit else 'crank-nicholson')

    if time_step is not None:
        dt = u(time_step,'Myr')
        click.echo("Target dt for finite solver: {}".format(dt))
        FiniteSolver.set_defaults(time_step=dt)

    for s in scenarios:
        click.echo("Running scenario "+click.style(s,fg='green'))
        registry[s]()
        click.echo("")
Exemple #19
0
#!/usr/bin/env python

from geotherm.units import u
from geotherm.plot import ComparisonPlotter, Plotter
from geotherm.models.geometry import Section
from geotherm.materials import oceanic_mantle
from geotherm.solvers import HalfSpaceSolver, AdvancedFiniteSolver

layer = oceanic_mantle.to_layer(u(100, "km"))
section = Section([layer], uniform_temperature=u(1500, "degC"))
finite = AdvancedFiniteSolver(section)
half_space = HalfSpaceSolver(section)

plotter = ComparisonPlotter(half_space.profile,
                            title="Half-space test",
                            range=(0, 2000))
#plotter = Plotter(range=(0,2000))
finite.solution(u(3, "Myr"), plotter=plotter)
Exemple #20
0
Usage: crystal_knob.py <solution>
"""
from __future__ import division, print_function
from docopt import docopt
import json
from geotherm.plot import Plotter
from geotherm.units import u
from geotherm.materials import oceanic_mantle, continental_crust
from geotherm.models.geometry import Section, Layer, stack_sections
from geotherm.solvers import HalfSpaceSolver
from geotherm.solvers.finite import AdvancedFiniteSolver

args = docopt(__doc__)
solution = args["<solution>"]

present = u(1.65,"Myr") # K-Ar age for Crystal Knob xenoliths


solver_constraints = (
    u(25,"degC"), # Surface temperature
    u(1400,"degC"))
    #u(48,"mW/m**2"))
    # Globally averaged mantle heat flux from Pollack, et al., 1977

oceanic_section = Section([oceanic_mantle.to_layer(u(200,"km"))])
oceanic_solver = HalfSpaceSolver(oceanic_section)

forearc = Section([
    continental_crust.to_layer(u(30,"km"))
    ], uniform_temperature=u(400,"degC")) # This is obviously over-simplified
Exemple #21
0
 def __init__(self):
     self.name = "monterey-plate"
     SubductionCase.__init__(self, u(27, "Myr"), u(22, "Myr"))
Exemple #22
0
def monterey_plate():
    return subduction_case("Monterey Plate"
        u(28,"Myr"),
        u(26,"Myr"))
Exemple #23
0
 def setup(self):
     self.pre_subduction()
     self.stepped_subduction(
         final_temperature=u(775,"degC"),
         optimization_depth=u(28,'km'),
         vary=self.variable_term)
Exemple #24
0
def farallon_plate():
    return subduction_case("Farallon Plate"
        u(140, "Myr"),
        u(70, "Myr"))
Exemple #25
0
#!/usr/bin/env python

from geotherm.units import u
from geotherm.materials import oceanic_mantle, continental_crust
from geotherm.models.geometry import Section, Layer, stack_sections
from geotherm.solvers import HalfSpaceSolver, FiniteSolver, AdiabatSolver
from geotherm.plot import Plotter

Layer.defaults["grid_spacing"] = u(100, "m")

mantle_section = Section([oceanic_mantle.to_layer(u(100, "km"))])

apply_adiabat = AdiabatSolver()

starting_mantle = apply_adiabat(mantle_section)

from IPython import embed
embed()

# Initialize oceanic crust (analytical)
oceanic = HalfSpaceSolver(mantle_layer)
evolved_oceanic = oceanic(u(30, "Myr"))

# Will put royden solver here.

# Initialize continental crust (analytical)
evolved_forearc = Section([continental_crust.to_layer(u(30, "km"))],
                          uniform_temperature=u(200, "degC"))

# Stack the two of them
final_section = stack_sections(
Exemple #26
0
from geotherm.units import u
from geotherm.materials import oceanic_mantle, continental_crust

# Recorder constraints
record_max_depth = u(100, 'km')

surface_temperature = u(0, 'degC')
# temperature of the base of the lithosphere
# used in the Royden model finite solving
asthenosphere_temperature = u(1450, "degC")
# Consider mostly steady-state upper portion for
# forearc cooling model
forearc_base_temperature = u(800, "degC")

# Distance backarc of subduction zone for our
# final sections (influences Royden model evolution
# and duration of subduction).
underplating_distance = u(100, 'km')

# Set conductivity to value from GDH model
oceanic_mantle.conductivity = u(3.138, "W/m/K")
# Could be higher? u(3300,"W/m/K")
# Continental crust is mostl granitic and metapelitic here
# This value is likely rather high
continental_crust.heat_generation = u(2.5, "uW/m**3")
continental_crust.conductivity = u(2.7, "W/m/K")
# Continental crust conductivity is 2.7 W/m/K
# but could be as low as 1.9 (citation needed)
# not sure what we should do here

# Depths