Time-varying bedload

The following example demonstrates how to configure a subclassing model with a time-varying parameter. In this example, the time-varying behavior arises by managing two “switches”, self._changed and self._changed_back, which change the state of the f_bedload parameters at a predetermined time in the mode sequence.

The following codes produce two runs (using matrix expansion from the Preprocessor), which has a baseline f_bedload value of either 0.3 or 0.7, and for a period in the middle of the run, the f_bedload values are mirrored by self.f_bedload = (1 - self.f_bedload), i.e., briefly switching the bedload values.

class VariableBedloadModel(pyDeltaRCM.DeltaModel):

    def __init__(self, input_file=None, **kwargs):

        super().__init__(input_file, **kwargs)

        self._changed = False
        self._changed_back = False

    def hook_solve_water_and_sediment_timestep(self):
        """Change the state depending on the _time.
        """
        # check if the state has been changed, and time to change it
        if (not self._changed) and (self._time > 459909090):
            self.f_bedload = (1 - self.f_bedload)
            self._changed = True

            _msg = 'Bedload changed to {f_bedload}'.format(
                f_bedload=self.f_bedload)
            self.log_info(_msg, verbosity=0)

        # check if the state has been changed back, and time to change it back
        if (not self._changed_back) and (self._time > 714545454):
            self.f_bedload = (1 - self.f_bedload)
            self._changed_back = True

            _msg = 'Bedload changed back to {f_bedload}'.format(
                f_bedload=self.f_bedload)
            self.log_info(_msg, verbosity=0)

Checking on the state-change effect

To demonstrate how this works, let’s loop through time and check the model state. Here, we will change the model time value directly, so that we can verify that the model is working as intended, but you should never do this in practice.

mdl_muddy = VariableBedloadModel(f_bedload=0.3)
mdl_sandy = VariableBedloadModel(f_bedload=0.7)

Important

You should never modify the model time via self._time directly when working with the model.

# create a figure
fig, ax = plt.subplots()

# set the "simulation" range
_times = np.linspace(0, 1e9, num=100)
fb_mdl_muddy = np.zeros_like(_times)
fb_mdl_sandy = np.zeros_like(_times)

# loop through time, change the model time and grab f_bedload values
for i, _time in enumerate(_times):
    # change the model time directly
    mdl_muddy._time = _time  # you should never do this
    mdl_sandy._time = _time  # you should never do this

    # run the hooked method
    mdl_muddy.hook_solve_water_and_sediment_timestep()
    mdl_sandy.hook_solve_water_and_sediment_timestep()

    # grab the state of the `f_bedload` parameter
    fb_mdl_muddy[i] = mdl_muddy.f_bedload  # get the value
    fb_mdl_sandy[i] = mdl_sandy.f_bedload  # get the value

# add it to the plot
ax.plot(_times, fb_mdl_muddy, '-', c='saddlebrown', lw=2, label='muddy')
ax.plot(_times, fb_mdl_sandy, '--', c='goldenrod', lw=2, label='sandy')
ax.legend()

# clean up
ax.set_ylim(0, 1)
ax.set_ylabel('f_bedload')
ax.set_xlabel('model time (s)')

plt.show()

(png, hires.png)

../_images/variable_bedload-3.png

Running the model for real

Given a yaml file (variable_bedload.yaml):

Length: 5000.
Width: 10000.
dx: 50
N0_meters: 500
C0_percent: 0.05
SLR: 1.5e-8
h0: 2
u0: 1.1
coeff_U_dep_mud: 0.5
parallel: True

matrix:
  f_bedload:
    - 0.3
    - 0.7

and a script to run the code:

if __name__ == '__main__':

    # base yaml configuration
    base_yaml = 'variable_bedload.yaml'

    pp = pyDeltaRCM.Preprocessor(
            base_yaml,
            timesteps=12000)

    # run the jobs
    pp.run_jobs(DeltaModel=VariableBedloadModel)