Esempio n. 1
0
class Add(object):
    offset = xs.variable(description=('offset * dt added every time step '
                                      'to profile u'))
    u_diff = xs.variable(group='diff', intent='out')

    def run_step(self, dt):
        self.u_diff = self.offset * dt
Esempio n. 2
0
def gen_properties(externs, modules, modulestoconsider = None, globaldependencies = {}, propertymapping = {}):
    """ Generate the properties of the xs Process class that will run the lpyfile """
    import numpy as np
    externs = externs.difference(predefined_variables)
    if not modulestoconsider is None:
        mmodules = dict()
        for name, pnames in modules.items():
            if name in modulestoconsider:
                mmodules[name] = pnames
        modules = mmodules
    properties = {}
    properties['modules'] = modules
    for m, v in modules.items():
        properties[m] = xs.index(dims=m)
        for p in v:
            pname = m+'_'+p
            properties[pname] = propertymapping.get(pname,
                                    xs.global_ref(pname, intent='in')
                                    if pname in globaldependencies else
                                    xs.variable( dims=m, intent='out', encoding={'dtype': np.float}))
    properties['globaldependencies'] = globaldependencies
    properties['externs'] = externs
    for e in externs:
        properties[e] = xs.variable()
    return properties
Esempio n. 3
0
class TotalVerticalMotion:
    """Sum up all vertical motions of bedrock and topographic surface,
    respectively.

    Vertical motions may result from external forcing, erosion and/or
    feedback of erosion on tectonics (isostasy).

    """
    bedrock_upward_vars = xs.group('bedrock_upward')
    surface_upward_vars = xs.group('surface_upward')
    surface_downward_vars = xs.group('surface_downward')

    bedrock_upward = xs.variable(
        dims=('y', 'x'),
        intent='out',
        description='bedrock motion in upward direction'
    )
    surface_upward = xs.variable(
        dims=('y', 'x'),
        intent='out',
        description='topographic surface motion in upward direction'
    )

    def run_step(self):
        self.bedrock_upward = sum(self.bedrock_upward_vars)

        self.surface_upward = (sum(self.surface_upward_vars) -
                               sum(self.surface_downward_vars))
Esempio n. 4
0
class DifferentialLinearDiffusion(LinearDiffusion):
    """Hillslope differential erosion by diffusion.

    Diffusivity may vary depending on whether the topographic surface
    is bare rock or covered by a soil (sediment) layer.

    """
    diffusivity_bedrock = xs.variable(
        dims=[(), ('y', 'x')],
        description='bedrock diffusivity'
    )
    diffusivity_soil = xs.variable(
        dims=[(), ('y', 'x')],
        description='soil (sediment) diffusivity'
    )

    diffusivity = xs.variable(
        dims=('y', 'x'),
        intent='out',
        description='differential diffusivity'
    )

    soil_thickness = xs.foreign(UniformSedimentLayer, 'thickness')

    def run_step(self):
        self.diffusivity = np.where(self.soil_thickness <= 0.,
                                    self.diffusivity_bedrock,
                                    self.diffusivity_soil)

        super(DifferentialLinearDiffusion, self).run_step()
Esempio n. 5
0
class SourcePoint(object):
    """Source point for quantity `u`.

    The location of the source point is adjusted to coincide with
    the nearest node the grid.

    """
    loc = xs.variable(description='source location')
    flux = xs.variable(description='source flux')
    x = xs.foreign(UniformGrid1D, 'x')
    u_source = xs.variable(dims='x', intent='out', group='u_vars')

    @property
    def nearest_node(self):
        idx = np.abs(self.x - self.loc).argmin()
        return idx

    @property
    def source_rate(self):
        src_array = np.zeros_like(self.x)
        src_array[self.nearest_node] = self.flux
        return src_array

    def run_step(self, dt):
        self.u_source = self.source_rate * dt
class SourcePoint:
    """Source point for quantity `u`.

    The location of the source point is adjusted to coincide with
    the nearest node the grid.

    """

    loc = xs.variable(description="source location")
    flux = xs.variable(description="source flux")
    x = xs.foreign(UniformGrid1D, "x")
    u_source = xs.variable(dims="x", intent="out", groups="u_vars")

    @property
    def nearest_node(self):
        idx = np.abs(self.x - self.loc).argmin()
        return idx

    @property
    def source_rate(self):
        src_array = np.zeros_like(self.x)
        src_array[self.nearest_node] = self.flux
        return src_array

    @xs.runtime(args="step_delta")
    def run_step(self, dt):
        self.u_source = self.source_rate * dt
Esempio n. 7
0
class LinearDiffusion:
    """Hillslope erosion by diffusion."""

    diffusivity = xs.variable(
        dims=[(), ('y', 'x')],
        description='diffusivity (transport coefficient)'
    )
    erosion = xs.variable(
        dims=('y', 'x'),
        intent='out',
        groups='erosion'
    )

    shape = xs.foreign(UniformRectilinearGrid2D, 'shape')
    elevation = xs.foreign(SurfaceToErode, 'elevation')
    fs_context = xs.foreign(FastscapelibContext, 'context')

    def run_step(self):
        kd = np.broadcast_to(self.diffusivity, self.shape).flatten()
        self.fs_context["kd"] = kd

        # we don't use the kdsed fastscapelib-fortran feature directly
        # see class DifferentialLinearDiffusion
        self.fs_context["kdsed"] = -1.

        # bypass fastscapelib-fortran global state
        self.fs_context["h"] = self.elevation.flatten()

        fs.diffusion()

        erosion_flat = self.elevation.ravel() - self.fs_context["h"]
        self.erosion = erosion_flat.reshape(self.shape)
Esempio n. 8
0
class TwoBlocksUplift:
    """Set two blocks separated by a clip plane, with different
    uplift rates.

    """
    x_position = xs.variable(
        description='position of the clip plane along the x-axis')

    rate_left = xs.variable(description='uplift rate of the left block')
    rate_right = xs.variable(description='uplift rate of the right block')

    shape = xs.foreign(UniformRectilinearGrid2D, 'shape')
    x = xs.foreign(UniformRectilinearGrid2D, 'x')

    # TODO: group=['bedrock_forcing_upward', 'surface_forcing_upward']
    # see https://github.com/benbovy/xarray-simlab/issues/64
    uplift = xs.variable(dims=[(), ('y', 'x')],
                         intent='out',
                         group='any_forcing_upward',
                         description='imposed vertical uplift')

    def initialize(self):
        # align clip plane position
        self._x_idx = np.argmax(self.x > self.x_position)

    @xs.runtime(args='step_delta')
    def run_step(self, dt):
        rate = np.full(self.shape, self.rate_left)

        rate[:, self._x_idx:] = self.rate_right

        self.uplift = rate * dt
Esempio n. 9
0
class TotalVerticalMotion:
    """Sum up all vertical motions of bedrock and topographic surface,
    respectively.

    Vertical motions may result from external forcing, erosion and/or
    feedback of erosion on tectonics (isostasy).

    """
    #TODO: remove any_upward_vars
    # see https://github.com/benbovy/xarray-simlab/issues/64
    any_upward_vars = xs.group('any_upward')
    bedrock_upward_vars = xs.group('bedrock_upward')
    surface_upward_vars = xs.group('surface_upward')
    surface_downward_vars = xs.group('surface_downward')

    bedrock_upward = xs.variable(
        dims=('y', 'x'),
        intent='out',
        description='bedrock motion in upward direction')
    surface_upward = xs.variable(
        dims=('y', 'x'),
        intent='out',
        description='topographic surface motion in upward direction')

    def run_step(self):
        sum_any = sum(self.any_upward_vars)

        self.bedrock_upward = sum_any + sum(self.bedrock_upward_vars)

        self.surface_upward = (sum_any + sum(self.surface_upward_vars) -
                               sum(self.surface_downward_vars))
Esempio n. 10
0
class FlowAccumulator:
    """Accumulate the flow from upstream to downstream."""

    runoff = xs.variable(
        dims=[(), ('y', 'x')],
        description='surface runoff (source term) per area unit')

    shape = xs.foreign(UniformRectilinearGrid2D, 'shape')
    cell_area = xs.foreign(UniformRectilinearGrid2D, 'cell_area')
    stack = xs.foreign(FlowRouter, 'stack')
    nb_receivers = xs.foreign(FlowRouter, 'nb_receivers')
    receivers = xs.foreign(FlowRouter, 'receivers')
    weights = xs.foreign(FlowRouter, 'weights')

    flowacc = xs.variable(
        dims=('y', 'x'),
        intent='out',
        description='flow accumulation from up to downstream')

    def run_step(self):
        field = np.broadcast_to(self.runoff * self.cell_area,
                                self.shape).flatten()

        if self.receivers.ndim == 1:
            _flow_accumulate_sd(field, self.stack, self.receivers)

        else:
            _flow_accumulate_mfd(field, self.stack, self.nb_receivers,
                                 self.receivers, self.weights)

        self.flowacc = field.reshape(self.shape)
Esempio n. 11
0
class BorderBoundary:
    status = xs.variable(dims=[(), 'border'],
                         description='node status at borders')

    border = xs.variable(dims='border',
                         intent='out',
                         description='4-border boundaries coordinate')
    border_status = xs.variable(
        dims='border',
        intent='out',
        description='node status at the 4-border boundaries')

    fs_context = xs.foreign(FastscapelibContext, 'context')

    ibc = xs.variable(intent='out',
                      description='boundary code used by fastscapelib-fortran')

    def initialize(self):
        self.border = np.array(['left', 'right', 'top', 'bottom'])
        self.border_status = np.broadcast_to(self.status, 4)

        # convert to fastscapelib-fortran ibc code
        arr_bc = np.array(
            [1 if st == 'fixed_value' else 0 for st in self.border_status])

        # different border order
        self.ibc = sum(arr_bc * np.array([1, 100, 10, 1000]))

        self.fs_context.ibc = self.ibc
class ExampleProcess:
    """A process with complete interface for testing."""

    in_var = xs.variable(dims=["x", ("x", "y")], description="input variable")
    out_var = xs.variable(groups="example_group", intent="out")
    inout_var = xs.variable(intent="inout", converter=int)
    od_var = xs.on_demand()
    obj_var = xs.any_object(description="arbitrary object")

    in_foreign_var = xs.foreign(SomeProcess, "some_var")
    in_foreign_var2 = xs.foreign(AnotherProcess, "some_var")
    out_foreign_var = xs.foreign(AnotherProcess, "another_var", intent="out")
    in_foreign_od_var = xs.foreign(SomeProcess, "some_od_var")

    in_global_var = xs.global_ref("some_global_var")
    out_global_var = xs.global_ref("another_global_var", intent="out")

    group_var = xs.group("some_group")
    group_dict_var = xs.group_dict("some_group")

    other_attrib = attr.attrib(init=False, repr=False)
    other_attr = "this is not a xsimlab variable attribute"

    @od_var.compute
    def compute_od_var(self):
        return 0
class ProfileZ:
    """Compute the evolution of the elevation (z) profile"""

    h_vars = xs.group(
        "h_vars"
    )  #allows for multiple processes influencing; say diffusion and subsidence

    z = xs.variable(dims="x",
                    intent="inout",
                    description="surface elevation z",
                    attrs={"units": "m"})
    br = xs.variable(dims=[(), "x"],
                     intent="in",
                     description="bedrock_elevation",
                     attrs={"units": "m"})
    h = xs.variable(dims="x",
                    intent="inout",
                    description="sed_thickness",
                    attrs={"units": "m"})

    def run_step(self):
        #self._delta_br = sum((br for br in self.br_vars))
        self._delta_h = sum((h for h in self.h_vars))

    def finalize_step(self):
        #self.br += self._delta_br #update bedrock surface
        self.h += self._delta_h  #update sediment thickness
        self.z = self.br + self.h  #add sediment to bedrock to get topo elev.
Esempio n. 14
0
class DifferentialStreamPowerChannel(StreamPowerChannel):
    """Stream-Power channel (differential) erosion.

    Channel incision coefficient may vary depending on whether the
    topographic surface is bare rock or covered by a soil (sediment)
    layer.

    """
    k_coef_bedrock = xs.variable(
        dims=[(), ('y', 'x')],
        description='bedrock channel incision coefficient')
    k_coef_soil = xs.variable(
        dims=[(), ('y', 'x')],
        description='soil (sediment) channel incision coefficient')

    k_coef = xs.variable(
        dims=('y', 'x'),
        intent='out',
        description='differential channel incision coefficient')

    active_layer_thickness = xs.foreign(UniformSedimentLayer, 'thickness')

    def run_step(self):
        self.k_coef = np.where(self.active_layer_thickness <= 0.,
                               self.k_coef_bedrock, self.k_coef_soil)

        super(DifferentialStreamPowerChannel, self).run_step()
Esempio n. 15
0
class VariableTwoBlockUplift:
    """compute diferent linear gradient uplift rate along the x or y axis 
    for two blocks separated by a clip plane"""

    x_position = xsimlab.variable(
        description='position of the clip plane along the x-axis')

    uplift_rate_left = xsimlab.variable(
        description='uplift rate of the left box')
    uplift_rate_right = xsimlab.variable(
        description='uplift rate of the right box')
    gradient_left = xsimlab.variable(
        description='gradient of the left box uplift')
    gradient_right = xsimlab.variable(
        description='gradient of the right box uplift')

    grid_shape = xsimlab.foreign(RasterGrid2D, 'shape')

    rate = xsimlab.foreign(BlockUplift, 'rate', intent='out')

    def run_step(self):

        mask = np.ones((self.grid_shape[0], self.grid_shape[1]))
        mask[:, 0:self.x_position] = self.uplift_rate_left
        mask[:, self.x_position:self.grid_shape[1]] = self.uplift_rate_right

        gradient = np.ones((self.grid_shape[1]))
        gradient[0:self.x_position] = np.linspace(self.gradient_left, 1,
                                                  self.x_position)
        gradient[self.x_position:self.grid_shape[1]] = np.linspace(
            self.gradient_right, 1,
            np.abs(self.grid_shape[1] - self.x_position))

        self.rate = mask * gradient
Esempio n. 16
0
class Foo:
    v_bool_nan = xs.variable(dims="x", intent="out")
    # suppress nan values by setting an explicit fill value:
    v_bool = xs.variable(dims="x", intent="out", encoding={"fill_value": None})

    def initialize(self):
        self.v_bool_nan = [True, False]
        self.v_bool = [True, False]
Esempio n. 17
0
class Roll(object):
    shift = xs.variable(description=('shift profile by a nb. of points'),
                        attrs={'units': 'unitless'})
    u = xs.foreign(Profile, 'u')
    u_diff = xs.variable(dims='x', group='diff', intent='out')

    def run_step(self, *args):
        self.u_diff = np.roll(self.u, self.shift) - self.u
Esempio n. 18
0
class Add:
    offset = xs.variable(description=("offset * dt added every time step "
                                      "to profile u"))
    u_diff = xs.variable(groups="diff", intent="out")

    @xs.runtime(args="step_delta")
    def run_step(self, dt):
        self.u_diff = self.offset * dt
class FixedGrid(UniformGrid1D):
    spacing = xs.variable(description="uniform spacing", intent="out")
    length = xs.variable(description="total length", intent="out")

    def initialize(self):
        self.spacing = 0.01
        self.length = 1.0
        super(FixedGrid, self).initialize()
class WithPlaceholder:
    """My process

    {{attributes}}

    """

    var1 = xs.variable(dims="x", description="a variable")
    var2 = xs.variable()
Esempio n. 21
0
    class Foo:
        v1 = xs.variable(intent="out")
        v2 = xs.variable()

        def initialize(self):
            self.v1 = 0

        def run_step(self):
            self.v1 = 1
class UniformGrid1D:
    """Create a 1-dimensional, equally spaced grid."""

    spacing = xs.variable(description="uniform spacing", static=True)
    length = xs.variable(description="total length", static=True)
    x = xs.index(dims="x")

    def initialize(self):
        self.x = np.arange(0, self.length, self.spacing)
Esempio n. 23
0
    class P2:
        var = xs.foreign(P1, "var")
        cached_var = xs.foreign(P1, "cached_var")
        view = xs.variable(dims="x", intent="out")
        cached_view = xs.variable(dims="x", intent="out")

        def run_step(self):
            self.view = self.var
            self.cached_view = self.cached_var
Esempio n. 24
0
class UniformGrid1D(object):
    """Create a 1-dimensional, equally spaced grid."""

    spacing = xs.variable(description='uniform spacing')
    length = xs.variable(description='total length')
    x = xs.variable(dims='x', intent='out')

    def initialize(self):
        self.x = np.arange(0, self.length, self.spacing)
Esempio n. 25
0
        class P:
            in_var = xs.variable(dims=[(), "x"])
            out_var = xs.variable(dims=[(), "x"], intent="out")
            idx_var = xs.index(dims="x")

            def initialize(self):
                self.idx_var = [0, 1]

            def run_step(self):
                self.out_var = self.in_var * 2
class InitUGauss:
    """Initialize `u` profile using a Gaussian pulse."""

    loc = xs.variable(description="location of initial pulse", static=True)
    scale = xs.variable(description="scale of initial pulse", static=True)
    x = xs.foreign(UniformGrid1D, "x")
    u = xs.foreign(ProfileU, "u", intent="out")

    def initialize(self):
        self.u = np.exp(-1 / self.scale ** 2 * (self.x - self.loc) ** 2)
Esempio n. 27
0
class InitUGauss(object):
    """Initialize `u` profile using a Gaussian pulse."""

    loc = xs.variable(description='location of initial pulse')
    scale = xs.variable(description='scale of initial pulse')
    x = xs.foreign(UniformGrid1D, 'x')
    u = xs.foreign(ProfileU, 'u', intent='out')

    def initialize(self):
        self.u = np.exp(-1 / self.scale**2 * (self.x - self.loc)**2)
Esempio n. 28
0
class StreamPowerChannel(ChannelErosion):
    """Stream-Power channel erosion."""

    k_coef = xs.variable(dims=[(), ('y', 'x')],
                         description='bedrock channel incision coefficient')
    area_exp = xs.variable(description='drainage area exponent')
    slope_exp = xs.variable(description='slope exponent')

    shape = xs.foreign(UniformRectilinearGrid2D, 'shape')
    elevation = xs.foreign(FlowRouter, 'elevation')
    receivers = xs.foreign(FlowRouter, 'receivers')
    flowacc = xs.foreign(FlowAccumulator, 'flowacc')
    fs_context = xs.foreign(FastscapelibContext, 'context')

    chi = xs.on_demand(dims=('y', 'x'),
                       description='integrated drainage area (chi)')

    def _set_g_in_context(self):
        # transport/deposition feature is exposed in subclasses
        self.fs_context.g1 = 0.
        self.fs_context.g2 = 0.

    def run_step(self):
        kf = np.broadcast_to(self.k_coef, self.shape).flatten()
        self.fs_context.kf = kf

        # we don't use kfsed fastscapelib-fortran feature directly
        self.fs_context.kfsed = -1.

        self._set_g_in_context()

        self.fs_context.m = self.area_exp
        self.fs_context.n = self.slope_exp

        # bypass fastscapelib_fortran global state
        self.fs_context.h = self.elevation.flatten()

        # TODO: https://github.com/fastscape-lem/fastscapelib-fortran/pull/25
        # this has no effect yet.
        self.fs_context.a = self.flowacc.flatten()

        if self.receivers.ndim == 1:
            fs.streampowerlawsingleflowdirection()
        else:
            fs.streampowerlaw()

        erosion_flat = self.elevation.ravel() - self.fs_context.h
        self.erosion = erosion_flat.reshape(self.shape)

    @chi.compute
    def _chi(self):
        chi_arr = np.empty_like(self.elevation, dtype='d')
        self.fs_context.copychi(chi_arr.ravel())

        return chi_arr
Esempio n. 29
0
    class P:
        in_var = xs.variable()
        out_var = xs.variable(intent="out")
        od_var = xs.on_demand()

        def run_step(self):
            self.out_var = self.in_var * 2

        @od_var.compute
        def _dummy(self):
            return None
Esempio n. 30
0
 class P:
     var = xs.variable(
         dims=[(), "x"],
         description="a variable",
         default=0,
         groups=["g1", "g2"],
         static=True,
         attrs={"units": "m"},
         encoding={"fill_value": -1},
     )
     var2 = xs.variable()