Exemple #1
0
  /**
   * \brief Defines a region of the computation domain where a new species may be created, using
   * restrictions in the protocol file
   *
   * <p>Defines a region of the computation domain where a new species may be created, using
   * restrictions in the protocol file. These restrictions for a particular species are specified in
   * 'coordinates' tags. There should be two such tags where this is used - one to start the
   * restriction and one to end it. Example of use: \<coordinates x="0" y="0" z="0"/\> \<coordinates
   * x="1" y="264" z="0"/\>. This method will read these in and create an array that represents this
   * area
   *
   * @param spRoot The information within the 'initArea' tags of the protocol file
   * @return A continuous vector representing the area of the domain specified in these tags
   */
  public ContinuousVector[] defineSquareArea(XMLParser spRoot) {
    List<XMLParser> area = spRoot.getChildrenParsers("coordinates");

    ContinuousVector[] initArea = new ContinuousVector[2];
    initArea[0] = new ContinuousVector();
    initArea[1] = new ContinuousVector();

    // KA NOV 13 - CHANGED THIS, AS WE'RE GOING TO LET THE USER NOT DECLARE AN INITIAL AREA IF THEY
    // WANT THE CELLS SPREAD ACROSS
    // THE WHOLE DOMAIN. THUS THIS NEEDS CHECKING AND FIXING
    if (area.size() > 0) {
      // First Coordinate Tag
      ContinuousVector cc1 = new ContinuousVector(area.get(0));
      // Second Coordinate Tag
      ContinuousVector cc2 = new ContinuousVector(area.get(1));

      // Set each point
      initArea[0].x = Math.min(cc1.x, cc2.x);
      initArea[1].x = Math.max(cc1.x, cc2.x);

      initArea[0].y = Math.min(cc1.y, cc2.y);
      initArea[1].y = Math.max(cc1.y, cc2.y);

      // In the case of 2D simulation, the agent's z-coordinate is 0.
      if (domain.is3D) {
        initArea[0].z = Math.min(cc1.z, cc2.z);
        initArea[1].z = Math.max(cc1.z, cc2.z);
      } else {
        initArea[0].z = initArea[1].z = 0.0;
      }

    } else {
      // NO INITIAL AREA HAS BEEN DECLARED, USE THE WHOLE SUBSTRATUM. NOTE THAT THE X (HEIGHT)
      // COORDINATE IS SET TO 1 SO THE
      // CELLS ARE PLACED NEAR THE SUBSTRATUM
      // Set each point
      initArea[0].x = 0.0;
      initArea[0].y = 0.0;
      initArea[0].z = 0.0;
      initArea[1].x = 1.0;
      initArea[1].y = domain.length_Y;
      initArea[1].z = domain.length_Z;
    }

    return initArea;
  }
Exemple #2
0
  /**
   * \brief For self-attachment scenarios, performs the run and tumble motion of a swimming cell,
   * and the required position checks and corrections
   *
   * <p>For self-attachment scenarios, the agents enter the system on top of the boundary layer and
   * perform a run and tumble motion, swimming through the biofilm. This method captures that
   * motion. A random angle is chosen and the cell moves at a certain distance, set by cell tumble
   * speed in the protocol file. The agent may move back into the bulk, where we assume it will go
   * back into the mix and thus we take no further action with it. The aim is for that cell to swim
   * around until it either hits the substratum surface or biofilm surface, where it will attach. If
   * the agent does not attach in this distance, a new angle is chosen (a 'tumble') and this is
   * repeated. This method takes care of all checks to the coordinates (such as a crossed boundary
   * and hitting the surface/biofilm). An integer value is returned that states the fate of this
   * move - the cell has either not attached anywhere (0), and thus needs to tumble, the cell has
   * attached (1), or the cell has returned to the bulk (2).
   *
   * @author Kieran Alden
   * @param spRoot The Species markup from the protocol file for one particular species being
   *     initialised
   * @return Integer value noting the fate of this move (0 no attachment, 1 attachment, 2 returned
   *     to bulk)
   */
  public int performRunAndTumble(XMLParser spRoot) {
    // To clarify how Jan has designed this to work:
    // The moving cell has a speed, measured in microns a second, and this is specified in the
    // protocol file.
    // You would thus think that the cell would move at a speed that this related to this and the
    // global timestep.
    // However, it has been decided that this is not to be the case, and the cell will run and
    // tumble continuously this timestep
    // until it has attached to a surface or to the biofilm.
    // Thus this speed is only used to calculate how far the cell will move before tumbling, and the
    // speed at which the cell moves
    // has no relation to the global timestep (and thus no relation to real time)

    // Now the distance the cell will move in a particular direction is calculated from the tumble
    // interval (specified in the protocol file)
    // and the cell run speed (also in the protocol file). The cell will move away at a random angle
    // for that distance, and will then
    // tumble (changing the angle). This continues until this cell has either returned into the bulk
    // or has attached to the surface
    // or biofilm
    // Eventually we will look to change this tumble interval, as this can be used to alter cell
    // movement when under chemotaxis

    Double distanceEachTumble = getLocatedParam().cellRunSpeed * getLocatedParam().tumbleInterval;
    Double distanceToMoveThisTumble = 0.0;
    Double distanceAgentMoves = 0.0;

    Double distanceSeekingAgent = getLocatedParam().getStickinessRadius();

    // We will use a integer flag system to determine what has happened to the cell after a run
    // 0 - no attachment, must do another run
    // 1 - cell has attached and thus movement is over
    // 2 - cell has returned into the bulk (and thus is discarded)
    int cellRunResult = 0;

    while (true)
    // for ( int i = 0; i < 1000000; i++ )
    {
      /*
       * Now work out the new position of the cell based on the distance
       * covered this tumble. Firstly calculate that direction - generate
       * a random angle between 0 and 360.
       */
      setAgentAngleOfMovement();
      /*
       * Now we're going to break the move down into chunks such that
       * collision or move over the boundary can be detected. The size of
       * the chunk is going to be the resolution of the agent grid.
       */
      distanceToMoveThisTumble = distanceEachTumble;
      while (distanceToMoveThisTumble > 0.0) {
        /*
         * If the cell has less distance to move remaining that the
         * resolution, should only move that much.
         */
        distanceAgentMoves = Math.min(distanceToMoveThisTumble, distanceSeekingAgent);
        calculateNewAgentPosition(distanceAgentMoves);

        /*
         * Now need to check for collision on any point of that path.
         */
        cellRunResult = checkAgentMove(distanceAgentMoves);

        // Add the distance moved in this mini move to the tally.
        distanceToMoveThisTumble -= distanceAgentMoves;

        // If the cell has finished moving, we can return the result.
        if (cellRunResult != 0) return cellRunResult;
      }
    }
    // return cellRunResult;
  }