Beispiel #1
0
    def initialize(self,
                   grid_size=(5, 5),
                   report_interval=5.0,
                   grid_orientation="vertical",
                   node_layout="rect",
                   show_plots=False,
                   cts_type="oriented_hex",
                   run_duration=1.0,
                   output_interval=1.0e99,
                   plot_every_transition=False,
                   **kwds):

        # Remember the clock time, and calculate when we next want to report
        # progress.
        self.current_real_time = time.time()
        self.next_report = self.current_real_time + report_interval
        self.report_interval = report_interval

        # Interval for output
        self.output_interval = output_interval

        # Duration for run
        self.run_duration = run_duration

        # Create a grid
        self.create_grid_and_node_state_field(grid_size[0], grid_size[1],
                                              grid_orientation, node_layout,
                                              cts_type)

        # Create the node-state dictionary
        ns_dict = self.node_state_dictionary()

        # Initialize values of the node-state grid
        nsg = self.initialize_node_state_grid()

        # Create the transition list
        xn_list = self.transition_list()

        # Create the CA object
        if cts_type == "raster":
            from landlab.ca.raster_cts import RasterCTS

            self.ca = RasterCTS(self.grid, ns_dict, xn_list, nsg)
        elif cts_type == "oriented_raster":
            from landlab.ca.oriented_raster_cts import OrientedRasterCTS

            self.ca = OrientedRasterCTS(self.grid, ns_dict, xn_list, nsg)
        elif cts_type == "hex":
            from landlab.ca.hex_cts import HexCTS

            self.ca = HexCTS(self.grid, ns_dict, xn_list, nsg)
        else:
            from landlab.ca.oriented_hex_cts import OrientedHexCTS

            self.ca = OrientedHexCTS(self.grid, ns_dict, xn_list, nsg)

        # Initialize graphics
        self._show_plots = show_plots
        if show_plots:
            self.initialize_plotting(**kwds)
Beispiel #2
0
def test_oriented_raster_cts():
    """Tests instantiation of an OrientedRasterCTS() object"""
    mg = RasterModelGrid(3, 3)
    nsd = {0: "oui", 1: "non"}
    xnlist = []
    xnlist.append(Transition((0, 1, 0), (1, 1, 0), 1.0, "hopping"))
    nsg = mg.add_zeros("node", "node_state_grid")
    orcts = OrientedRasterCTS(mg, nsd, xnlist, nsg)

    assert orcts.num_link_states == 8
    # assert_array_equal(orcts.link_orientation, [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0])
    assert_array_equal(orcts.link_orientation, [0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0])
Beispiel #3
0
def test_oriented_raster_cts():
    """Tests instantiation of an OrientedRasterCTS() object"""
    mg = RasterModelGrid(3, 3, 1.0)
    nsd = {0 : 'oui', 1 : 'non'}
    xnlist = []
    xnlist.append(Transition((0,1,0), (1,1,0), 1.0, 'hopping'))
    nsg = mg.add_zeros('node', 'node_state_grid')
    orcts = OrientedRasterCTS(mg, nsd, xnlist, nsg)

    assert_equal(orcts.num_link_states, 8)
    #assert_array_equal(orcts.link_orientation, [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0])
    assert_array_equal(orcts.link_orientation, [0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0])
Beispiel #4
0
def test_setup_transition_data():
    """Test the CellLabCTSModel setup_transition_data method."""
    grid = RasterModelGrid((3, 4))
    nsd = {0: "zero", 1: "one"}
    trn_list = []
    trn_list.append(Transition((0, 1, 0), (1, 0, 0), 1.0))
    trn_list.append(Transition((1, 0, 0), (0, 1, 0), 2.0))
    trn_list.append(Transition((0, 1, 1), (1, 0, 1), 3.0))
    trn_list.append(Transition((0, 1, 1), (1, 1, 1), 4.0))
    ins = np.arange(12) % 2
    cts = OrientedRasterCTS(grid, nsd, trn_list, ins)

    assert_array_equal(cts.n_trn, [0, 1, 1, 0, 0, 2, 0, 0])
    assert_array_equal(
        cts.trn_id,
        [[0, 0], [0, 0], [1, 0], [0, 0], [0, 0], [2, 3], [0, 0], [0, 0]])
    assert_array_equal(cts.trn_to, [2, 1, 6, 7])
    assert_array_equal(cts.trn_rate, [1.0, 2.0, 3.0, 4.0])
Beispiel #5
0
def test_run_oriented_raster():
    """Test running with a small grid, 2 states, 4 transition types."""

    # Create an OrientedRaster with a 3x5 raster grid. Test model has 2 node
    # states and 4 transition types.
    grid = RasterModelGrid((3, 5))
    nsd = {0: "zero", 1: "one"}
    trn_list = []
    trn_list.append(Transition((0, 1, 0), (1, 0, 0), 1.0))
    trn_list.append(Transition((1, 0, 0), (0, 1, 0), 2.0))
    trn_list.append(Transition((0, 1, 1), (1, 0, 1), 3.0))
    trn_list.append(Transition((0, 1, 1), (1, 1, 1), 4.0))
    ins = np.arange(15) % 2  # makes a checkerboard pattern
    cts = OrientedRasterCTS(grid, nsd, trn_list, ins)

    # Run to 1st transition, at ~0.12
    cts.run(0.15)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0])

    # Run to 2nd transition, at ~0.19
    cts.run(0.2)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0])

    # Run to 3rd transition, at ~0.265
    cts.run(0.27)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0])

    # Run to 4th transition, at ~0.276 (transition is ignored)
    cts.run(0.28)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0])

    # Run to 5th transition, at ~0.461 (ignored)
    cts.run(0.5)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0])

    # Run to 6th transition, at ~0.648
    cts.run(0.65)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0])
Beispiel #6
0
def main():

    # INITIALIZE

    # User-defined parameters
    nr = 10
    nc = 10
    plot_interval = 0.25
    run_duration = 40.0
    report_interval = 5.0  # report interval, in real-time seconds

    # Remember the clock time, and calculate when we next want to report
    # progress.
    current_real_time = time.time()
    next_report = current_real_time + report_interval

    # Create grid
    mg = RasterModelGrid(nr, nc, 1.0)
    mg.set_closed_boundaries_at_grid_edges(True, True, True, True)

    # Set up the states and pair transitions.
    # Transition data here represent a body of fractured rock, with rock
    # represented by nodes with state 0, and saprolite (weathered rock)
    # represented by nodes with state 1. Node pairs (links) with 0-1 or 1-0
    # can undergo a transition to 1-1, representing chemical weathering of the
    # rock.
    ns_dict = { 0 : 'air', 1 : 'particle' }
    xn_list = setup_transition_list()

    # Create the node-state array and attach it to the grid
    node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int)
    node_state_grid[where(mg.node_y>nr-3)[0]] = 1

        # Create the CA model
    ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid)
    #ca = RasterCTS(mg, ns_dict, xn_list, node_state_grid)

    # Debug output if needed
    if _DEBUG:
        n = ca.grid.number_of_nodes
        for r in range(ca.grid.number_of_node_rows):
            for c in range(ca.grid.number_of_node_columns):
                n -= 1
                print('{0:.0f}'.format(ca.node_state[n]), end=' ')
            print()

    # Create a CAPlotter object for handling screen display
    ca_plotter = CAPlotter(ca)

    # Plot the initial grid
    ca_plotter.update_plot()

    # RUN
    current_time = 0.0
    updated = False
    while current_time < run_duration:

        # Once in a while, print out simulation and real time to let the user
        # know that the sim is running ok
        current_real_time = time.time()
        if current_real_time >= next_report:
            print('Current sim time',current_time,'(',100*current_time/run_duration,'%)')
            next_report = current_real_time + report_interval

        # Run the model forward in time until the next output step
        ca.run(current_time+plot_interval, ca.node_state,
               plot_each_transition=False) #, plotter=ca_plotter)
        current_time += plot_interval

        # Add a bunch of particles
        if current_time > run_duration/2. and not updated:
            print('updating...')
            node_state_grid[where(ca.grid.node_y>(nc/2.0))[0]] = 1
            ca.update_link_states_and_transitions(current_time)
            updated = True

        # Plot the current grid
        ca_plotter.update_plot()

        # for debugging
        if _DEBUG:
            n = ca.grid.number_of_nodes
            for r in range(ca.grid.number_of_node_rows):
                for c in range(ca.grid.number_of_node_columns):
                    n -= 1
                    print('{0:.0f}'.format(ca.node_state[n]), end=' ')
                print()


    # FINALIZE

    # Plot
    ca_plotter.finalize()
Beispiel #7
0
def main():

    # INITIALIZE

    # User-defined parameters
    nr = 10
    nc = 10
    plot_interval = 0.25
    run_duration = 40.0
    report_interval = 5.0  # report interval, in real-time seconds

    # Remember the clock time, and calculate when we next want to report
    # progress.
    current_real_time = time.time()
    next_report = current_real_time + report_interval

    # Create grid
    mg = RasterModelGrid(nr, nc, 1.0)
    mg.set_closed_boundaries_at_grid_edges(True, True, True, True)

    # Set up the states and pair transitions.
    # Transition data here represent a body of fractured rock, with rock
    # represented by nodes with state 0, and saprolite (weathered rock)
    # represented by nodes with state 1. Node pairs (links) with 0-1 or 1-0
    # can undergo a transition to 1-1, representing chemical weathering of the
    # rock.
    ns_dict = {0: 'air', 1: 'particle'}
    xn_list = setup_transition_list()

    # Create the node-state array and attach it to the grid
    node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int)
    node_state_grid[where(mg.node_y > nr - 3)[0]] = 1

    # Create the CA model
    ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid)
    #ca = RasterCTS(mg, ns_dict, xn_list, node_state_grid)

    # Debug output if needed
    if _DEBUG:
        n = ca.grid.number_of_nodes
        for r in range(ca.grid.number_of_node_rows):
            for c in range(ca.grid.number_of_node_columns):
                n -= 1
                print('{0:.0f}'.format(ca.node_state[n]), end=' ')
            print()

    # Create a CAPlotter object for handling screen display
    ca_plotter = CAPlotter(ca)

    # Plot the initial grid
    ca_plotter.update_plot()

    # RUN
    current_time = 0.0
    updated = False
    while current_time < run_duration:

        # Once in a while, print out simulation and real time to let the user
        # know that the sim is running ok
        current_real_time = time.time()
        if current_real_time >= next_report:
            print('Current sim time', current_time, '(',
                  100 * current_time / run_duration, '%)')
            next_report = current_real_time + report_interval

        # Run the model forward in time until the next output step
        ca.run(current_time + plot_interval,
               ca.node_state,
               plot_each_transition=False)  #, plotter=ca_plotter)
        current_time += plot_interval

        # Add a bunch of particles
        if current_time > run_duration / 2. and not updated:
            print('updating...')
            node_state_grid[where(ca.grid.node_y > (nc / 2.0))[0]] = 1
            ca.update_link_states_and_transitions(current_time)
            updated = True

        # Plot the current grid
        ca_plotter.update_plot()

        # for debugging
        if _DEBUG:
            n = ca.grid.number_of_nodes
            for r in range(ca.grid.number_of_node_rows):
                for c in range(ca.grid.number_of_node_columns):
                    n -= 1
                    print('{0:.0f}'.format(ca.node_state[n]), end=' ')
                print()

    # FINALIZE

    # Plot
    ca_plotter.finalize()
Beispiel #8
0
    def initialize(self,
                   grid_size=(5, 5),
                   report_interval=5.0,
                   grid_orientation='vertical',
                   grid_shape='rect',
                   show_plots=False,
                   cts_type='oriented_hex',
                   run_duration=1.0,
                   output_interval=1.0e99,
                   plot_every_transition=False,
                   initial_state_grid=None,
                   prop_data=None,
                   prop_reset_value=None,
                   **kwds):
        """Initialize CTSModel."""
        # Remember the clock time, and calculate when we next want to report
        # progress.
        self.current_real_time = time.time()
        self.next_report = self.current_real_time + report_interval
        self.report_interval = report_interval

        # Interval for output
        self.output_interval = output_interval

        # Duration for run
        self.run_duration = run_duration

        # Create a grid
        self.create_grid_and_node_state_field(grid_size[0], grid_size[1],
                                              grid_orientation, grid_shape,
                                              cts_type)

        # If prop_data is a string, we assume it is a field name
        if isinstance(prop_data, string_types):
            prop_data = self.grid.add_zeros('node', prop_data)

        # Create the node-state dictionary
        ns_dict = self.node_state_dictionary()

        # Initialize values of the node-state grid
        if initial_state_grid is None:
            nsg = self.initialize_node_state_grid()
        else:
            try:
                nsg = initial_state_grid
                self.grid.at_node['node_state'][:] = nsg
            except:
                #TODO: use new Messaging capability
                print('If initial_state_grid given, must be array of int')
                raise

        # Create the transition list
        xn_list = self.transition_list()

        # Create the CA object
        if cts_type == 'raster':
            from landlab.ca.raster_cts import RasterCTS
            self.ca = RasterCTS(self.grid, ns_dict, xn_list, nsg, prop_data,
                                prop_reset_value)
        elif cts_type == 'oriented_raster':
            from landlab.ca.oriented_raster_cts import OrientedRasterCTS
            self.ca = OrientedRasterCTS(self.grid, ns_dict, xn_list, nsg,
                                        prop_data, prop_reset_value)
        elif cts_type == 'hex':
            from landlab.ca.hex_cts import HexCTS
            self.ca = HexCTS(self.grid, ns_dict, xn_list, nsg, prop_data,
                             prop_reset_value)
        else:
            from landlab.ca.oriented_hex_cts import OrientedHexCTS
            self.ca = OrientedHexCTS(self.grid, ns_dict, xn_list, nsg,
                                     prop_data, prop_reset_value)

        # Initialize graphics
        self._show_plots = show_plots
        if show_plots == True:
            self.initialize_plotting(**kwds)
Beispiel #9
0
def main():

    # INITIALIZE

    # User-defined parameters
    nr = 100  # number of rows in grid
    nc = 64  # number of columns in grid
    plot_interval = 0.5  # time interval for plotting, sec
    run_duration = 30.0  # duration of run, sec
    report_interval = 10.0  # report interval, in real-time seconds

    # Remember the clock time, and calculate when we next want to report
    # progress.
    current_real_time = time.time()
    next_report = current_real_time + report_interval

    # Create grid
    mg = RasterModelGrid(nr, nc, 1.0)

    # Make the boundaries be walls
    mg.set_closed_boundaries_at_grid_edges(True, True, True, True)

    # Set up the states and pair transitions.
    ns_dict = {0: 'fluid', 1: 'particle', 2: 'crystal'}
    xn_list = setup_transition_list()

    # Create the node-state array and attach it to the grid
    node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int)

    # Initialize the node-state array: here, the initial condition is a pile of
    # resting moving particles at the bottom of a container. Seed crystal is
    bottom_rows = where(mg.node_y < 0.1 * nr)[0]
    node_state_grid[bottom_rows] = 1

    seed_crystal_rows = where(mg.node_y > 0.5 * nr)[0]
    node_state_grid[seed_crystal_rows] = 2

    # For visual display purposes, set all boundary nodes to fluid
    node_state_grid[mg.closed_boundary_nodes] = 0

    # Create the CA model
    ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid)

    # Hex colors
    grain = '#5F594D'
    fluid = '#D0E4F2'
    crystal = '#000000'
    clist = [fluid, grain, crystal]
    my_cmap = matplotlib.colors.ListedColormap(clist)

    # Create a CAPlotter object for handling screen display
    ca_plotter = CAPlotter(ca, cmap=my_cmap)

    # Plot the initial grid
    ca_plotter.update_plot()

    # RUN
    current_time = 0.0
    while current_time < run_duration:

        # Once in a while, print out simulation and real time to let the user
        # know that the sim is running ok
        current_real_time = time.time()
        if current_real_time >= next_report:
            print 'Current sim time', current_time, '(', 100 * current_time / run_duration, '%)'
            next_report = current_real_time + report_interval

        # Run the model forward in time until the next output step
        ca.run(current_time + plot_interval,
               ca.node_state,
               plot_each_transition=False)
        current_time += plot_interval

        # Plot the current grid
        ca_plotter.update_plot()

    # FINALIZE

    # Plot
    ca_plotter.finalize()

    # Calculate concentration profile
    c = zeros(nr)
    for r in range(nr):
        c[r] = mean(node_state_grid[r * nc:(r + 1) * nc])

    figure(2)
    plot(c, range(nr), 'o')
    show()
def main():

    # INITIALIZE

    # User-defined parameters
    nr = 100  # number of rows in grid
    nc = 64  # number of columns in grid
    plot_interval = 0.5   # time interval for plotting, sec
    run_duration = 20.0   # duration of run, sec
    report_interval = 10.0  # report interval, in real-time seconds

    # Remember the clock time, and calculate when we next want to report
    # progress.
    current_real_time = time.time()
    next_report = current_real_time + report_interval

    # Create grid
    mg = RasterModelGrid(nr, nc, 1.0)

    # Make the boundaries be walls
    mg.set_closed_boundaries_at_grid_edges(True, True, True, True)

    # Set up the states and pair transitions.
    ns_dict = { 0 : 'fluid', 1 : 'particle' }
    xn_list = setup_transition_list()

    # Create the node-state array and attach it to the grid
    node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int)

    # Initialize the node-state array: here, the initial condition is a pile of
    # resting grains at the bottom of a container.
    bottom_rows = where(mg.node_y<0.1*nr)[0]
    node_state_grid[bottom_rows] = 1

    # For visual display purposes, set all boundary nodes to fluid
    node_state_grid[mg.closed_boundary_nodes] = 0

    # Create the CA model
    ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid)

    grain = '#5F594D'
    fluid = '#D0E4F2'
    clist = [fluid,grain]
    my_cmap = matplotlib.colors.ListedColormap(clist)

    # Create a CAPlotter object for handling screen display
    ca_plotter = CAPlotter(ca, cmap=my_cmap)

    # Plot the initial grid
    ca_plotter.update_plot()

    # RUN
    current_time = 0.0
    while current_time < run_duration:

        # Once in a while, print out simulation and real time to let the user
        # know that the sim is running ok
        current_real_time = time.time()
        if current_real_time >= next_report:
            print 'Current sim time',current_time,'(',100*current_time/run_duration,'%)'
            next_report = current_real_time + report_interval

        # Run the model forward in time until the next output step
        ca.run(current_time+plot_interval, ca.node_state,
               plot_each_transition=False)
        current_time += plot_interval

        # Plot the current grid
        ca_plotter.update_plot()


    # FINALIZE

    # Plot
    ca_plotter.finalize()

    # Calculate concentration profile
    c = zeros(nr)
    for r in range(nr):
        c[r] = mean(node_state_grid[r*nc:(r+1)*nc])

    figure(2)
    plot(c, range(nr), 'o')
    show()
Beispiel #11
0
def main():

    # INITIALIZE

    # User-defined parameters
    nr = 80
    nc = 80
    plot_interval = 2
    run_duration = 200
    report_interval = 5.0  # report interval, in real-time seconds

    # Remember the clock time, and calculate when we next want to report
    # progress.
    current_real_time = time.time()
    next_report = current_real_time + report_interval

    # Create grid
    mg = RasterModelGrid(nr, nc, 1.0)

    # Make the boundaries be walls
    mg.set_closed_boundaries_at_grid_edges(True, True, True, True)

    # Set up the states and pair transitions.
    ns_dict = {0: "fluid", 1: "particle"}
    xn_list = setup_transition_list()

    # Create the node-state array and attach it to the grid
    node_state_grid = mg.add_zeros("node", "node_state_map", dtype=int)

    # Initialize the node-state array
    middle_rows = where(bitwise_and(mg.node_y > 0.45 * nr, mg.node_y < 0.55 * nr))[0]
    node_state_grid[middle_rows] = 1

    # Create the CA model
    ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid)

    # Debug output if needed
    if _DEBUG:
        n = ca.grid.number_of_nodes
        for r in range(ca.grid.number_of_node_rows):
            for c in range(ca.grid.number_of_node_columns):
                n -= 1
                print("{0:.0f}".format(ca.node_state[n]), end=" ")
            print()

    # Create a CAPlotter object for handling screen display
    ca_plotter = CAPlotter(ca)

    # Plot the initial grid
    ca_plotter.update_plot()

    # RUN
    current_time = 0.0
    while current_time < run_duration:

        # Once in a while, print out simulation and real time to let the user
        # know that the sim is running ok
        current_real_time = time.time()
        if current_real_time >= next_report:
            print(
                "Current sim time",
                current_time,
                "(",
                100 * current_time / run_duration,
                "%)",
            )
            next_report = current_real_time + report_interval

        # Run the model forward in time until the next output step
        ca.run(
            current_time + plot_interval, ca.node_state, plot_each_transition=False
        )  # , plotter=ca_plotter)
        current_time += plot_interval

        # Plot the current grid
        ca_plotter.update_plot()

        # for debugging
        if _DEBUG:
            n = ca.grid.number_of_nodes
            for r in range(ca.grid.number_of_node_rows):
                for c in range(ca.grid.number_of_node_columns):
                    n -= 1
                    print("{0:.0f}".format(ca.node_state[n]), end=" ")
                print()

    # FINALIZE

    # Plot
    ca_plotter.finalize()
Beispiel #12
0
def test_run_oriented_raster():
    """Test running with a small grid, 2 states, 4 transition types."""

    # Create an OrientedRaster with a 3x5 raster grid. Test model has 2 node
    # states and 4 transition types.
    grid = RasterModelGrid((3, 5))
    nsd = {0 : 'zero', 1 : 'one'}
    trn_list = []
    trn_list.append(Transition((0, 1, 0), (1, 0, 0), 1.0))
    trn_list.append(Transition((1, 0, 0), (0, 1, 0), 2.0))
    trn_list.append(Transition((0, 1, 1), (1, 0, 1), 3.0))
    trn_list.append(Transition((0, 1, 1), (1, 1, 1), 4.0))
    ins = np.arange(15) % 2  # makes a checkerboard pattern
    cts = OrientedRasterCTS(grid, nsd, trn_list, ins)

    # Run to 1st transition, at ~0.12
    cts.run(0.15)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0])

    # Run to 2nd transition, at ~0.19
    cts.run(0.2)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0])

    # Run to 3rd transition, at ~0.265
    cts.run(0.27)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0])

    # Run to 4th transition, at ~0.276 (transition is ignored)
    cts.run(0.28)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0])

    # Run to 5th transition, at ~0.461 (ignored)
    cts.run(0.5)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0])

    # Run to 6th transition, at ~0.648
    cts.run(0.65)
    assert_array_equal(cts.node_state,
                       [0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0])
ns_dict = { 0 : 'fluid', 1 : 'particle' }
xn_list = setup_transition_list()

# Create the node-state array and attach it to the grid
node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int)

# Initialize the node-state array: here, the initial condition is a pile of
# resting grains at the bottom of a container.
left_cols = np.where(mg.node_x<0.05*nc)[0]
node_state_grid[left_cols] = 1

# For visual display purposes, set all boundary nodes to fluid
node_state_grid[mg.closed_boundary_nodes] = 0

# Create the CA model
ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid)

grain = '#5F594D'
fluid = '#D0E4F2'
clist = [fluid,grain]
my_cmap = matplotlib.colors.ListedColormap(clist)

# Create a CAPlotter object for handling screen display
ca_plotter = CAPlotter(ca, cmap=my_cmap)

# Plot the initial grid
ca_plotter.update_plot()

# RUN
current_time = 0.0
while current_time < run_duration: