Tracer Advection in One Dimension with Constant Speed

Set Models Parameter Below

Model Output

MODEL DESCRIPTION

MODEL DESCRIPTION

Logistic growth is widely used in biology and ecology to describe populations growth under environmental constraints. Essentially this is a modification of exponential growth with a growth rate modified (reduced) as the population approaches limits set by nutrients or other environmental conditions.

Exponential growth is written: \[ \frac{dP}{dt} = g P \]

where P is population and g is the groth rate (fractional increase in opulation per unit time).

Next we modify the growth rate to decrease as the population approaches a limit imposed by the environment, for example by a limiting nutrient:

\[ \frac{dP}{dt} = g(1-\frac{P}{K}) P \].

It's helpful to think of \( g(1-\frac{P}{K}) \) as the modified or constrained growth rate, which is the probability of reproduction for each individual in the population per tinmestep.

Finally, we add death. Here mortality is implemented as an average lifetime \( L \), so that in each time step the probability of an individual dying is \( \frac{g}{L} \).

The final model as implemented here is then

\[ \frac{dP}{dt} = g(1-\frac{P}{K}-\frac{1}{L}) P \].

The program that does the calculation is very simple, and the code that controls this website is surprisingly simple too! It is all written in the programming language R, using a web programming package called shiny. You can read all about it on the “Website Code” tab to the right.

How this website works (including all the code!)

This website is controlled using the R package “shiny.” There are five important components:

  • A control script (advect.R) that integrates the model and stores output
  • A script (upstream.R) that advects the tracer for one time step
  • A plotting script (plotadvected.R the draws the plot in the browser
  • The user interface (ui.R) that controls the sliders and passes inputs to the model
  • The “server” (server.R) that responds to user interface events in the web browser

Scroll down or click links in the list above to read all about it!


advect.R:

advect <- function(nGrid=100, nCycles=5, courant=0.5) {

  # How many time steps to complete nCycles?
  nSteps <- nCycles * (nGrid / courant)

  # Create an array to hold tracer concentrations at every time step
  tracer <-  matrix(0, nrow=nGrid, ncol=nSteps,) # fill with zeros

  # Initialize tracer distribution to be a "top-hat" pattern
  tracer[round(nGrid/3) : round(2*nGrid/3), 1] <- 100.

  # Advect the tracer completely around the domain nCycles times
  for (iStep in 1:(nSteps-1)) 
    tracer[,iStep+1] <- upstream(nGrid, tracer[,iStep], courant) 

  return(list(nGrid=nGrid, nCycles=nCycles, courant=courant, nSteps=nSteps,
              tracer=tracer))
}

This is code the advects the tracer field for one time step

upstream.R: upstream <- function(nGrid, tracer, courant){

  # Tracer: advected quantity that will be updated
  # courant: speed of advection in grid cells per time step (must be < 1)

  # Make temporary local copy of tracer array
  newTracer <- tracer 

  # Advect tarcer in grid interior using upstream scheme
  newTracer[2:nGrid] <- (1.-courant)*tracer[2:nGrid] + courant*tracer[1:nGrid-1] 

  # Wrap at lateral boundaries (left edge of grid receives from right edge)
  newTracer[1] <- (1.-courant)*tracer[1] + courant*tracer[nGrid]

  return(newTracer)

}

This is the script that plots the output in the browser

plotadvected.R:

plotadvected <- function(model.output) {

# plot initial and final tracer distributions

  attach(model.output)
  initial <- tracer[,1]
  final <- tracer[,nSteps]

  # Initial and final tracer distribution
  # legendName<-['Initial', strcompress('After '+string(nCycles)+' cycles')]
  plot(1:nGrid, initial, col='black', type='l', lwd=4, xlab='grid cell',
                 ylab='Concentration', 
                 main='Initial and Final Tracer Distribution', cex=1.5)
  lines(1:nGrid, final, col='red', lwd=4)
  legend('topleft', c('Initial','Final'), col=c('black','red'), lwd=c(4,4))

  # Label plot with courant number
  #t1 <- TEXT(0.65, .8, string('Courant <- '+ string(courant)), /normal)         

  detach(model.output)
}

This is the user interface that actually controls this website

ui.R:

library(shiny)
library(markdown)

# Define user interface for 1-D advection model
shinyUI(pageWithSidebar(

  #  Application title
  headerPanel("Tracer Advection in One Dimension with Constant Speed"),

  # Sidebar on the left with controls for the user to specify parameters
  sidebarPanel(

    h4('Set Models Parameter Below'),            
    sliderInput("courant", "Courant Number (speed in grid cells per time step)", 
                min = 0.1, max = 1, value = 0.5, step= 0.01),
    sliderInput("nCycles", "Number of times to cycle around domain", 
                min = 1, max = 50, value = 10, step= 1)
  ),

  # Show a tabset in the main panel of the browser that displays model output
  mainPanel(
    tabsetPanel(

      # First tab shows plots of model output for both control and modified atmosphere
      tabPanel("Output", 
               h4('Model Output'), 
               plotOutput('advected.tracer')), 

      # Second tab displays a brief model description
      tabPanel("Model Description", 
               includeHTML('doc/model.description.html')),

      # Third tab displays website code
      tabPanel("Website code", 
               includeMarkdown('doc/website.code.md'))
    )
  )
))

This script responds to user interface events

server.R:

library(shiny)

# Source required R scripts
source('model/advect.R')        
source('model/plotadvected.R')        

shinyServer(function(input, output) {

  # Run the advection model and save output in a list
  model.output <- reactive(advect(nCycles=input$nCycles, courant=input$courant))

  #  plot of model output
  output$advected.tracer <- renderPlot(plotadvected(model.output()))

})