[R-sig-dyn-mod] better implementation of variable species ode.2D model

Jeremy Chacon chaco001 at umn.edu
Fri Feb 24 16:31:25 CET 2017


Hello list,

I am running ode.2D models (from deSolve, using ReacTran to manage
diffusion) in which I wish to have a variable number of "species"
(differential equations) which a single function can handle.  I've managed
to come up with a method that uses lists and loops internally, see the code
below for an example with a simpler reaction than I will be using in
practice.

However, it's quite slow, especially when I scale up the number of species
(or the number of boxes, but that is expected).

I would greatly appreciate any tips on how to better implement this idea.
I know if it was a "mean-field" model, I could simply use matrix algebra
inside the function to allow a variable number of species, but I'm not sure
how that can be extended to a 2D situation.

Thanks for any tips!

Jeremy

Code:

# example of variable-species ode.2D model
rm(list = ls())
library(ReacTran)

variable_species_lv_2D = function(t, y, parms){


  # y holds all the data.  there are Nx * Ny boxes.
  n_colonies = length(y) / (Nx*Ny) - 1

  # the resource is always first in the data vector y
  resource = matrix(nrow = Nx, ncol = Ny,
              data = y[1:(Nx * Ny)])

  # grab each consumer's data
  consumers = list()
  for (k in 1:n_colonies){
    consumers[[k]] = matrix(nrow = Nx, ncol = Ny,
                    data = y[(1 + k * (Nx * Ny)): ((k + 1) * Nx * Ny)])
  }

  # get the diffusion for the resource
  resource_diff = tran.2D(resource, grid = grid2D, D.grid =
D_resource_grid)$dC

  # get the diffusion for each consumer
  consumers_diff = list()
  for (k in 1:n_colonies){
    consumers_diff[[k]] = tran.2D(consumers[[k]], grid = grid2D, D.grid =
D_consumer_grid)$dC
  }

  # get the reaction for each consumer, and simultaneously
  # subtract that from the resource
  consumers_rxn = list()
  resource_rxn = matrix(nrow = Nx, ncol = Ny,
                  data = 0)
  for (k in 1:n_colonies){
    consumers_rxn[[k]] = r * consumers[[k]] * resource
    resource_rxn = resource_rxn - consumers_rxn[[k]]
  }

  # sum the effects of diffusion + reaction,
  # and simultaneously concatenate all the data back
  # into a single vector
  dresource = resource_diff + resource_rxn
  dAll = dresource
  for (k in 1:n_colonies){
    curr_dconsumer = consumers_diff[[k]] + consumers_rxn[[k]]
    dAll = c(dAll, curr_dconsumer)
  }
  return(list(dAll))
}

# setup parameters
world_width = 100
Nx = Ny = 30
D_resource = 1
D_consumer = 1e-2

r = 0.01

# generate spatial vectors / matrices
Gridx = setup.grid.1D(L = world_width, N = Nx)
Gridy = setup.grid.1D(L = world_width, N = Ny)
grid2D = setup.grid.2D(Gridx, Gridy)
D_consumer_grid = setup.prop.2D(value = D_consumer, y.value = D_consumer,
grid = grid2D)
D_resource_grid = setup.prop.2D(value = D_resource, y.value = D_resource,
grid = grid2D)


# initialize data
n_consumers = 4
resource_start = matrix(nrow = Nx, ncol = Ny, data = 1000)
all_start = resource_start
for (k in 1:n_consumers){
  curr_consumer_start = matrix(nrow = Nx, ncol = Ny, data = 0)
  curr_consumer_start[sample(1:(Nx * Ny), 1)] = 1
  all_start = c(all_start, curr_consumer_start)
}

# run model
times = seq(from = 0, to = 10, by = 1)
out = ode.2D(y = all_start,
             times = times,
            func = variable_species_lv_2D,
            parms = NULL,
            nspec = n_consumers + 1,
            dimens = c(Nx, Ny),
            lrw = 5e8,
            hmax = 0.01)

# visualize output
# image(out, mfrow = c(1, n_consumers + 1))

-- 

*___________________________________________________________________________Jeremy
M. Chacon, Ph.D.*

*Post-Doctoral Associate, Harcombe Lab*
*University of Minnesota*
*Ecology, Evolution and Behavior*

	[[alternative HTML version deleted]]



More information about the R-sig-dynamic-models mailing list