Het model is geprogrammeerd in PHP en de afbeeldingen worden gemaakt met PHP GD library. Het samenstellen van de GIF afbeelding wordt gedaan met GIFEncoder Version 2.0 by László Zsidi, http://gifs.hu.
Eerst wordt de zeebodem gesimuleerd, daarna wordt er een PNG-afbeelding van gemaakt, ook is er de mogelijkheid voor een animated GIF. Op dit moment bestaat het model (het simulatie gedeelte) uit 500+ regels code. De volledige java versie bestaat uit 1200 regels code.
Onderstaande code is van versie 2.16.
Er is ook een Java versie van dit model. Meer weten? Klik hier.

<?php
require_once('config.php');

## Settings for testing
ini_set('max_execution_time', 600);
ini_set('memory_limit', '24M');
error_reporting(E_ALL);

#### Define functions, variables and get the user input ####

// Set timers (mainly for Output type: debug info)
$_time = array('overallTimer' => microtime(true), 'simulateTimer' => 0, 'renderTimer' => 0);

// Version
$version = '2.16';

## Define some functions

// Return the change in sealevel between two steps. $t is current step
function getSeaLevelChangeAt($t){
  global $seaLevelFormula, $previousSeaLevel;
  $result = 0;
  for($i = 0;$i < count($seaLevelFormula);$i++){
    $result += $seaLevelFormula[$i]['amplitude']*sin((($t+$seaLevelFormula[$i]['shift'])/$seaLevelFormula[$i]['period'])*2*pi());
  }
  $out = round($result)-$previousSeaLevel;
  $previousSeaLevel = round($result);
  return $out;
}

// Set the type of the grid on the given $x & $y, function not used.
function setGrid(int $x, int $y, int $type){
  global $map;
  if($x > $gridX || $y > $gridY || $x < 0 || $y < 0) return;
  $map[$x][$y]['type'] = $type;
}

// Check if $v is a form of sediment
function isSediment($v){
  return ($v == SEDIMENT || $v == CLAY || $v == SHALLOW || $v == SUBAERIAL || $v == UNDEFINED_SEDIMENT || $v == DEBUG);
}

// Check if $v is a form if water
function isWater($v){
  return ($v == WATER || $v == DEBUGWATER);
}

// Return the maximum value from the map, used to define the max value when drawing color effects
function getMaxFromMap($map, $key){
  $max = 0;
  for($x = 0;$x < count($map);$x++){
    for($y = 0;$y < count($map[$x]);$y++){
      if($map[$x][$y][$key] > $max){
        $max = $map[$x][$y][$key];
      }
    }
  }
  return $max;
}

// Same as getMaxFromMaps(), but checks an array of maps
function getMaxFromMaps($maps, $key){
  $max = 0;
  for($i = 0;$i < count($maps);$i++){
    for($x = 0;$x < count($maps[$i]['map']);$x++){
      for($y = 0;$y < count($maps[$i]['map'][$x]);$y++){
        if($maps[$i]['map'][$x][$y][$key] > $max){
          $max = $maps[$i]['map'][$x][$y][$key];
        }
      }
    }
  }
  return $max;
}

// Draw an image with the given data and return the image
function drawMap($img, $map, $gridY, $offsetY = 0){
  global $maps, $gridX, $useAge, $useWaterDepth, $showInfo, $colors, $steps, $gridSizeX, $gridSizeY, $maxGridY, $drawGridBorder;
  if($useWaterDepth){
    $maxWaterDepth = (count($maps) > 0 ? getMaxFromMaps($maps, 'water') : getMaxFromMap($map, 'water'));
    if($maxWaterDepth < 1)$maxWaterDepth = 1;
  }
  for($x = 0;$x < $gridX;$x++){
    for($y = 0;$y < $gridY;$y++){
      // Use color effects?
      if($useAge || $useWaterDepth || strlen($showInfo) > 0){
        $color = $colors[$map[$x][$y]['type']];
        if($useAge){
          if($map[$x][$y]['type'] == SEDIMENT){
            $color = imagecolorallocate($img, 0, (round(($map[$x][$y]['step']/$steps)*245)+5), 0);
          }
          if($map[$x][$y]['type'] == SHALLOW){
            $color = imagecolorallocate($img, 255, (round(($map[$x][$y]['step']/$steps)*60)+130), 51);
          }
        }elseif($useWaterDepth){
          if($map[$x][$y]['type'] == SEDIMENT){
            $color = imagecolorallocate($img, 0, 0, 255-(round(($map[$x][$y]['water']/$maxWaterDepth)*255)));
          }
          if($map[$x][$y]['type'] == SHALLOW){
            $color = imagecolorallocate($img, 255, 130, 50-(round(($map[$x][$y]['water']/$maxWaterDepth)*50)));
          }
        }
        imagefilledrectangle($img, $x*$gridSizeX, $y*$gridSizeY+$offsetY, $x*$gridSizeX+$gridSizeX, $y*$gridSizeY+$gridSizeY+$offsetY, $color);
        if(strlen($showInfo) > 0 && isSediment($map[$x][$y]['type'])){
          imagestring($img, 4, $x*$gridSizeX, $y*$gridSizeY+$offsetY, $map[$x][$y][$showInfo], $colors[WHITE]);
        }
      }else{// Use default colors
        imagefilledrectangle($img, $x*$gridSizeX, $y*$gridSizeY+$offsetY, $x*$gridSizeX+$gridSizeX, $y*$gridSizeY+$gridSizeY+$offsetY, $colors[$map[$x][$y]['type']]);
      }
    }
  }
  if($drawGridBorder){ // Draw the grid borders if wanted
    for($x = 0;$x < $gridX;$x++){
      imageline($img, $x*$gridSizeX, 0+$offsetY, $x*$gridSizeX, $gridY*$gridSizeY+$offsetY, imagecolorallocate($img, 0, 0, 0));
    }
    for($y = 0;$y < $gridY;$y++){
      imageline($img, 0, $y*$gridSizeY+$offsetY, $gridX*$gridSizeX, $y*$gridSizeY+$offsetY, imagecolorallocate($img, 0, 0, 0));
    }
  }
  return $img;
}

// Get the number of water grids above $y on $x
function getWaterCountAbove($map, $x, $y){
  $c = 0;
  for($yy = 0;$yy < $y;$yy++){
    if(isWater($map[$x][$yy]['type']))$c++;
  }
  return $c;
}

## Check recent runs, is much faster
if(searchCache($_POST, $version)){
  // If cache is available, stop everything. searchCache() is defined in config.php
  exit;
}

## Define the materials
define('AIR', 0);
define('SEDIMENT', 1);
define('SHALLOW', 2);
define('SUBAERIAL', 3);
define('CLAY', 8);
define('WATER', 4);
define('UNDEFINED_SEDIMENT', 5);
define('DEBUG', 6);
define('DEBUGWATER', 7);
define('WHITE', 9);

## Define variables with default values to prevent errors
$map = array();// The complete seabed is stored inside this array
$gridY = 1;
$maxGridY = $gridY;
$seaLevel = 0;
$previousSeaLevel = -1;// Solution for map going too far down
$maps = array();// Used to store maps to draw them later on, used for animated GIF
$gifExtraFrames = false;// Store maps after placement of a grid
$debugText = array();// Used to store text for debugging

// For testing only, used to stop real output and only show the debug info
$_debug = false;
if(isset($_POST['typeOutput']) && $_POST['typeOutput'] == 'debuginfo'){
  $_debug = true;
}

// Add to recent runs?
$addRecentRun = false;
$recentRunID = 0;


// How much steps should the program run?
$step = 1;// Current step
$steps = 100;
if(isset($_POST['steps']) && is_numeric($_POST['steps'])){
  $steps = $_POST['steps'];
}

// Sediment supply, also split the values into different types (composition)
$sedimentInput = array(SEDIMENT => 100, CLAY => 0);
if(isset($_POST['sedimentInput']) && is_numeric($_POST['sedimentInput'])){
  $s = explode(';', $_POST['composition']);
  $in = $_POST['sedimentInput'];
  if(count($s) >= 2){
    $sedimentInput[SEDIMENT] = ($in/100)*$s[1];
    $sedimentInput[CLAY] = ($in/100)*$s[0];
  }
}

$maxInputDeviation = 0;
$inputMultiplier = 0;
if(isset($_POST['maxInputDeviation']) && isset($_POST['inputMultiplier']) && is_numeric($_POST['maxInputDeviation'])){
  $maxInputDeviation = trim($_POST['maxInputDeviation'])*1;
  $inputMultiplier = trim($_POST['inputMultiplier']);
  if(strchr($inputMultiplier, ',')){
    $inputMultiplier = str_replace(',', '.', $inputMultiplier);
  }
  if(is_numeric($inputMultiplier))$inputMultiplier *= 1;
}

// Clay distance, the maximum distance (in grid) clay can travel trough water
$clayDistance = 2;
if(isset($_POST['clayDistance']) && is_numeric($_POST['clayDistance'])){
  $clayDistance = $_POST['clayDistance'];
}

// Subsidence
$subsidence = 0;
if(isset($_POST['subsidence']) && is_numeric($_POST['subsidence'])){
  $subsidence = $_POST['subsidence'];
}

// Uneven subsidence
$unevenSubsidence = false;
if(isset($_POST['unevenSubsidence']) && $_POST['unevenSubsidence'] == 'true'){
  $unevenSubsidence = true;
  if(isset($_POST['leftSubsidence']) && is_numeric($_POST['leftSubsidence'])){
    $subsidence = $_POST['leftSubsidence'];
  }
}
$rightSubsidence = -1;
if(isset($_POST['rightSubsidence']) && is_numeric($_POST['rightSubsidence'])){
  $rightSubsidence = $_POST['rightSubsidence'];
}
$unevenSubsidenceRemainder = array();

// Use SUBAERIAL
$useSubaerial = false;
if(isset($_POST['useSubaerial']) && $_POST['useSubaerial'] == 'true'){
  $useSubaerial = true;
}

// Put the formulas for the sealevel into an array
$seaLevelFormula = array();
$maxAmplitude = 0;
for($i = 1;$i < 6;$i++){
  if(isset($_POST['sealevel'.$i]) && $_POST['sealevel'.$i] == 'true'){
    if(is_numeric($_POST['shift'.$i]) && is_numeric($_POST['amplitude'.$i]) && is_numeric($_POST['period'.$i]) && $_POST['period'.$i] > 0){
      $seaLevelFormula[] = array('shift' => trim($_POST['shift'.$i])*1, 'amplitude' => trim($_POST['amplitude'.$i])*1, 'period' => trim($_POST['period'.$i])*1);
      $maxAmplitude += trim($_POST['amplitude'.$i])*1;
    }
  }
}

// Size in pixels for each grid
$gridSizeX = 10;
$gridSizeY = 10;
if(isset($_POST['gridSize'])){
  if(count(explode(',', $_POST['gridSize'])) > 0){
    list($gridSizeX, $gridSizeY) = explode(',', $_POST['gridSize']);
    $gridSizeX = trim($gridSizeX)*1;
    $gridSizeY = trim($gridSizeY)*1;
  }else{
    $gridSizeX = $gridSizeY = trim($_POST['gridSize'])*1;
  }
}

// Width in grid
$gridX = 10;
if(isset($_POST['gridX']) && is_numeric($_POST['gridX'])){
  $gridX = $_POST['gridX'];
}

// Delay between GIF frames
$gifDelay = 30;
if(isset($_POST['gifDelay']) && is_numeric($_POST['gifDelay'])){
  $gifDelay = $_POST['gifDelay'];
}

// Draw borders of each grid
$drawGridBorder = false;
if(isset($_POST['drawGridBorder']) && $_POST['drawGridBorder'] == 'true'){
  $drawGridBorder = true;
}else{
  $drawGridBorder = false;
}

// Visual effects
$useAge = false;
$useWaterDepth = false;
if(isset($_POST['colorEffect'])){
  if($_POST['colorEffect'] == 'sedimentAge'){
    $useAge = true;
  }
  if($_POST['colorEffect'] == 'waterDepth'){
    $useWaterDepth = true;
  }
}

// Info to show as text in a grid
$showInfo = '';
if(isset($_POST['showInfo']) && in_array($_POST['showInfo'], array('step','water','type'))){
  $showInfo = $_POST['showInfo'];
}

// Calculate if it is possible (fast enough) to create extra frames
if($steps*$gridX*$subsidence < 400){
  $gifExtraFrames = true;
}

#### Start simulation ####

// Start the simulateTimer
$_time['simulateTimer'] = microtime(true);

// Start with one row of UNDEFINED_SEDIMENT
for($x = 0;$x < $gridX;$x++){
  for($y = 0;$y < $gridY;$y++){
    $map[$x][$y]['type'] = UNDEFINED_SEDIMENT;
    $map[$x][$y]['step'] = 0;
    $map[$x][$y]['water'] = 0;
  }
}

// Loop through all the steps
for($step = $step;$step <= $steps;$step++){
  // Calculate the total change
  $change = ($unevenSubsidence ? 0 : $subsidence) + getSeaLevelChangeAt($step);
  $subChange = array(); // Store subsidence per x coordinate
  $add = $sedimentInput;

  // If maxInputDeviation and inputMultiplier are used, apply them.
  if($maxInputDeviation > 0 && $inputMultiplier > 0){
    // $previousSeaLevel is not really previous at this point, it is calculated a few lines above.
    if($add[SEDIMENT] > 0)$add[SEDIMENT] += round($maxInputDeviation * ($previousSeaLevel/$maxAmplitude) * $inputMultiplier);
    if($add[CLAY] > 0)$add[CLAY] += round($maxInputDeviation * ($previousSeaLevel/$maxAmplitude) * $inputMultiplier);
    if($add[SEDIMENT] < 0)$add[SEDIMENT] = 0;
    if($add[CLAY] < 0)$add[CLAY] = 0;
  }

  // Apply uneven subsidence
  if($unevenSubsidence){
    for($x = 0;$x < $gridX;$x++){
      $subUnRounded = (abs($rightSubsidence-$subsidence)/$gridX)*($subsidence > $rightSubsidence ? $x+1 : $gridX - $x);
      $unevenSubsidenceRemainder[$x] += ((($subUnRounded*$gridX)%$gridX)/$gridX);
      if($unevenSubsidenceRemainder[$x] >= 1){
        $unevenSubsidenceRemainder[$x] = ($unevenSubsidenceRemainder[$x]*$gridX%$gridX)/$gridX;
        $subUnRounded++;
      }
      $subChange[$x] = max(array($rightSubsidence,$subsidence))-floor($subUnRounded);
      for($c = 0;$c < $subChange[$x];$c++){
        for($y = $gridY+$c;$y >= 0;$y--){
          $map[$x][$y + 1] = $map[$x][$y];
        }
        $map[$x][0]['type'] = WATER;
      }
    }
    for($c = 0;$c < ($subsidence > $rightSubsidence ? $subsidence : $rightSubsidence);$c++){
      $seaLevel++;
      $gridY++;
    }
    $debugText[] = ''.print_r($subChange, true). ''.print_r($unevenSubsidenceRemainder, true);
  }
  if($change > 0){
    for($c = 0;$c < $change;$c++){
      $seaLevel++;
      for($x = 0;$x < $gridX;$x++){
        $map[$x][] = array();
        for($y = $gridY;$y >= 0;$y--){
          $map[$x][$y + 1] = $map[$x][$y];
        }
        $map[$x][0]['type'] = WATER;
      }
      $gridY++;
      if($gifExtraFrames && $_POST['typeOutput'] == 'animatedGIF'){// Create extra GIF frame
        $maps[] = array('gridY' => $gridY, 'step' => $step, 'map' => $map, 'maxSubsidence' => ($unevenSubsidence ?
        ($subsidence > $rightSubsidence ? $subsidence : $rightSubsidence) : $subsidence), 'change' => $change);
      }
    }
  }elseif($change == 0){
  }else{
    for($c = 0;$c < abs($change);$c++){
      $seaLevel--;
      for($x = 0;$x < $gridX;$x++){
        for($y = 0;$y < 1;$y++){
          if(isSediment($map[$x][$y]['type'])){
            $add[(in_array($map[$x][$y]['type'], array(SEDIMENT, CLAY)) ? $map[$x][$y]['type'] : SEDIMENT)]++;
            $map[$x][$y]['type'] = AIR;
          }
        }
      }
      for($x = 0;$x < $gridX;$x++){
        for($y = 0;$y < $gridY;$y++){
          $map[$x][$y] = $map[$x][$y + 1];
        }
      }
      $gridY--;
      if($gifExtraFrames && $_POST['typeOutput'] == 'animatedGIF'){
        $maps[] = array('gridY' => $gridY, 'step' => $step, 'map' => $map, 'maxSubsidence' => ($unevenSubsidence ?
        ($subsidence > $rightSubsidence ? $subsidence : $rightSubsidence) : $subsidence), 'change' => $change);
      }
    }
  }

  // Add a line to the $debugText
  $debugText[] = 'step: '.$step.'  change: '.$change.' sum add: '.array_sum($add).'  previousSeaLevel: '.$previousSeaLevel.'  seaLevel: '.$seaLevel.'  gridY: '.$gridY;

  // Deposit CLAY only between $cxMin and $cxMax
  $cxMin = 0;
  $cxMax = $clayDistance;
  $cSum = $add[CLAY];
  for($c = 0;$c < $cSum;$c++){
    for($y = $gridY;$y >= 0;$y--){
      for($x = $cxMin;$x < $cxMax;$x++){
        if($y <= 0){$cxMin++;$cxMax++;break 2;}
        if($y > 0 && isWater($map[$x][$y]['type']) && $map[$x][$y-1]['type'] != AIR){
          $map[$x][$y]['type'] = CLAY;
          $map[$x][$y]['step'] = $step;
          $map[$x][$y]['water'] = getWaterCountAbove($map,$x,$y);
          if($gifExtraFrames && $_POST['typeOutput'] == 'animatedGIF'){
            $maps[] = array('gridY' => $gridY, 'step' => $step, 'map' => $map, 'maxSubsidence' => ($unevenSubsidence ?
            ($subsidence > $rightSubsidence ? $subsidence : $rightSubsidence) : $subsidence), 'change' => $change);
          }
          break 2;
        }
      }
    }
    $add[CLAY]--;
  }

  // Deposit SEDIMENT as close to the left as possible
  $sSum = $add[SEDIMENT];
  for($s = 0;$s < $sSum;$s++){
    for($x = 0;$x < $gridX;$x++){
      for($y = $gridY;$y >= 0;$y--){
        if(isWater($map[$x][$y]['type'])){
          $map[$x][$y]['type'] = SEDIMENT;
          $map[$x][$y]['step'] = $step;
          $map[$x][$y]['water'] = getWaterCountAbove($map,$x,$y);
          $add[SEDIMENT]--;
          if($gifExtraFrames && $_POST['typeOutput'] == 'animatedGIF'){
            $maps[] = array('gridY' => $gridY, 'step' => $step, 'map' => $map,
              'maxSubsidence' => ($unevenSubsidence ?
              ($subsidence > $rightSubsidence ? $subsidence : $rightSubsidence) : $subsidence),
              'change' => $change);
          }
          if($add[SEDIMENT] <= 0){break 3;}
        }
      }
    }
  }

  // Convert every sort of sediment that touches air into shallow, or if the sealevel is dropping, convert it into subaerial
  for($x = 0;$x < $gridX;$x++){
    for($y = 0;$y < $gridY;$y++){
      if(isSediment($map[$x][$y]['type']) && $map[$x][$y]['type'] != SUBAERIAL && ($y == 0 || $map[$x][$y - 1]['type'] == AIR)){
        $map[$x][$y]['type'] = ($useSubaerial ? ($change+($unevenSubsidence ? $subChange[$x] : 0) < 0 ? SUBAERIAL : SHALLOW) : SHALLOW);
      }
    }
  }

  // When drawing an animated GIF, save the map to $maps to draw it later on, when we know the maximum height.
  if($_POST['typeOutput'] == 'animatedGIF'){
    $maps[] = array('gridY' => $gridY, 'step' => $step, 'map' => $map, 'maxSubsidence' => ($unevenSubsidence ?
    ($subsidence > $rightSubsidence ? $subsidence : $rightSubsidence) : $subsidence), 'change' => $change);
  }
  if($gridY > $maxGridY){
    $maxGridY = $gridY;
  }
  // End of step
}

#### Render the seabed ####

// Stop and start timers
$_time['simulateTimer'] = microtime(true) - $_time['simulateTimer'];
$_time['renderTimer'] = microtime(true);

// Create the image, and define some colors
$imgOut = imagecreatetruecolor($gridX*$gridSizeX, ($_POST['typeOutput'] == 'animatedGIF' ? $maxGridY : $gridY)*$gridSizeY);
imagecolorallocate($imgOut, 255, 255, 255);
$colors = array();
$colors[AIR] = imagecolorallocate($imgOut, 70, 70, 70);
$colors[SEDIMENT] = imagecolorallocate($imgOut, 255, 255, 0);
$colors[CLAY] = imagecolorallocate($imgOut, 22, 77, 42);
$colors[SHALLOW] = imagecolorallocate($imgOut, 255, 130, 215);
$colors[SUBAERIAL] = imagecolorallocate($imgOut, 255, 0, 0);
$colors[WATER] = imagecolorallocate($imgOut, 186, 240, 255);
$colors[UNDEFINED_SEDIMENT] = imagecolorallocate($imgOut, 20, 20, 20);
$colors[DEBUG] = imagecolorallocate($imgOut, 255, 0, 0);
$colors[DEBUGWATER] = imagecolorallocate($imgOut, 255, 0, 255);
$colors[WHITE] = imagecolorallocate($imgOut, 255, 255, 255);

// Draw the seabed
if($_POST['typeOutput'] == 'animatedGIF'){
  include('inc/GIFEncoder.class.php');
  $gifFrames = array();
  $gifFrameDelay = array();
  $previousSeaLevel = 0;
  $yOffsetTotal = 0;
  for($i = 0;$i < count($maps);$i++){
    $tmpImg = imagecreatetruecolor($gridX*$gridSizeX, $maxGridY*$gridSizeY);
    imagecolorallocate($tmpImg, 255, 255, 255);
    imagefilledrectangle($tmpImg, 0, 0, $gridX*$gridSizeX, $maxGridY*$gridSizeY, $colors[AIR]);
    // $yOffsetTotal is used to move the image inside the animated GIF
    if($gifExtraFrames){
      $yOffsetTotal = (($maxGridY*$gridSizeY)-($maps[$i]['gridY']*$gridSizeY))/$gridSizeY;
    }else{
      $yOffsetTotal -= $maps[$i]['change'] - ($unevenSubsidence ? 0 : $maps[$i]['maxSubsidence']);
    }
    $tmpImg = drawMap($tmpImg, $maps[$i]['map'], $maps[$i]['gridY'], $yOffsetTotal*$gridSizeY);
    imagestring($tmpImg, 4, $gridX*$gridSizeX-20, 3, $maps[$i]['step'], imagecolorallocate($tmpImg, 0, 0, 0));
    ob_start();
    imagegif($tmpImg);
    $gifFrames[] = ob_get_contents();
    $gifFrameDelay[] = $gifDelay;
    ob_end_clean();
  }
  if(!$_debug){
    // Output the animated GIF
    header("Content-type: image/gif");
    if($_POST['download'] == 'true') header('Content-Disposition: attachment; filename="seabed-animation-'.date('Y-m-d-H-i-s').'.gif"');
    $gif = new GIFEncoder($gifFrames, $gifFrameDelay, 0, 2, 0, 0, 0, 'bin');
    echo $gif->GetAnimation();
    if($addRecentRun)file_put_contents('output/recentrun-'.$recentRunID.'.gif', $gif->GetAnimation());
  }
}else{
  $imgOut = drawMap($imgOut, $map, $gridY);
}

// Stop the renderTimer
$_time['renderTimer'] = microtime(true) - $_time['renderTimer'];

// Start the output
if($_POST['typeOutput'] == 'debugtext'){
  echo print_r($debugText);
}elseif($_POST['typeOutput'] == 'jsondata'){
  echo json_encode($map);
  if($_POST['download'] == 'true') header('Content-Disposition: attachment; filename="seabed-'.date('Y-m-d-H-i-s').'.json"');
}elseif($_debug){
  // Stop the timer
  $_time['overallTimer'] = microtime(true) - $_time['overallTimer'];
  echo 'Simulation time: '.$_time['simulateTimer'].'<br>';
  echo 'Render time: '.$_time['renderTimer'].'<br>';
  echo 'Overall time: '.$_time['overallTimer'].'<br>';
}elseif($_POST['typeOutput'] == 'animatedGIF'){
}else{
  header("Content-type: image/png");
  if($_POST['download'] == 'true') header('Content-Disposition: attachment; filename="seabed-'.date('Y-m-d-H-i-s').'.png"');
  imagepng($imgOut);
  if($addRecentRun)imagepng($imgOut, 'output/recentrun-'.$recentRunID.'.png');
  imagedestroy($imgOut);
}
if(!$_debug)$_time['overallTimer'] = microtime(true) - $_time['overallTimer'];

/* Save settings, time and version. Makes it possible to compare run times in the different versions to choose the best way of simulating and rendering.
   Function is defined in config.php. */
saveModelRun($_POST, $_time, $version, $addRecentRun, $recentRunID);
?>