QHG Tutorial 03 - Moving

In this chapter we describe a class which, in addition to aging and dying also lets agents move randomly between cells.

To get the agents moving we use the action class RandomMove.

Population code:

Action code:

The Header File

This class must additionaly include the header files for the RandomMove action.

#ifndef __TUT_MOVEPOP_H__
#define __TUT_MOVEPOP_H__

#include "OldAgeDeath.h"
#include "GetOld.h"

#include "RandomMove.h"

#include "SPopulation.h"

// our agents need to have an age
struct tut_MoveAgent : Agent {
    float m_fAge;
};

class tut_MovePop : public SPopulation<tut_MoveAgent> {

 public:
    tut_MovePop(SCellGrid *pCG, PopFinder *pPopFinder, int iLayerSize, IDGen **apIDG, uint32_t *aulState, uint *aiSeeds);
    virtual ~tut_MovePop();

    int addPopSpecificAgentData(int iAgentIndex, char **ppData);
    void addPopSpecificAgentDataTypeQDF(hid_t *hAgentDataType);

protected:

    GetOld<tut_MoveAgent> *m_pGO;
    OldAgeDeath<tut_MoveAgent> *m_pOAD;

    RandomMove<tut_MoveAgent> *m_pRM;
};

#endif

For random moving we don’t need to add members to the agent structure - the agents` positions are already part of the basic agent structure. So we use the same agent structure as in the previous chapter.

The public methods addPopSpecificAgentData and addPopSpecificAgentDataTypeQDF remain unchanged since they only deal with the addition agent member m_fAge.

Finally, we need a pointer to an instance of the RandomMove-action.

Code: tut_MovePop.h

The Implementation

The include files reflect the addition of the move action:

The constructor must create instances of all the actions and add them to the priority list.

//----------------------------------------------------------------------------
// constructor
//
tut_MovePop::tut_MovePop(SCellGrid *pCG, PopFinder *pPopFinder, int iLayerSize, IDGen **apIDG, uint32_t *aulState, uint *aiSeeds)
    :  SPopulation<tut_MoveAgent>(pCG, pPopFinder, iLayerSize, apIDG, aulState, aiSeeds) {

    m_pGO = new GetOld<tut_MoveAgent>(this, m_pCG, "");
    m_pOAD = new OldAgeDeath<tut_MoveAgent>(this, m_pCG, "", m_apWELL);

    m_pRM = new RandomMove<tut_MoveAgent>(this, m_pCG, "", m_apWELL);

    m_prio.addAction(m_pGO);
    m_prio.addAction(m_pOAD);

    m_prio.addAction(m_pRM);
}

In the destructor the instances created by the constructor are deletetd.

//----------------------------------------------------------------------------
// destructor
//
tut_MovePop::~tut_MovePop() {
    if (m_pGO != NULL) {
        delete m_pGO;
    }
    if (m_pOAD != NULL) {
        delete m_pOAD;
    }
    if (m_pRM != NULL) {
        delete m_pRM;
    }
}

Finally, there are the input auxiliary methods dealing with the age member. They are the same as the ones in the previous chapter.

//----------------------------------------------------------------------------
// addPopSpecificAgentData
// read additional data from pop file (the mat index is volatile, so we don't try to read it)
//
int tut_MovePop::addPopSpecificAgentData(int iAgentIndex, char **ppData) {

    int iResult = 0;

    if (iResult == 0) {
        iResult = addAgentDataSingle(ppData, &m_aAgents[iAgentIndex].m_fAge);
    }

    return iResult;
}

//----------------------------------------------------------------------------
// addPopSpecificAgentDataTypeQDF
// extend the agent data type to include additional data in the output
//
void tut_MovePop::addPopSpecificAgentDataTypeQDF(hid_t *hAgentDataType) {

    tut_MoveAgent ma;
    H5Tinsert(*hAgentDataType, "Age",  qoffsetof(ma, m_fAge), H5T_NATIVE_FLOAT);

}

Code: tut_MovePop.cpp

XML and DAT

Apart from the entries for OldAgeDeath there is also an entry for RandomMove in the xml file. The action GetOld requires no parameters.

<class name="tut_MovePop" species_name="sapiens" species_id="104">

  <module name="OldAgeDeath">
    <param  name="OAD_max_age" value="60.0"/>
    <param  name="OAD_uncertainty" value="0.1"/>
  </module>

  <module name="RandomMove">
    <param  name="RandomMove_prob" value="0.1"/>
  </module>

  <priorities>
    <prio  name="GetOld" value="1"/>
    <prio  name="OldAgeDeath" value="20"/>

    <prio  name="RandomMove" value="3"/>
  </priorities>
</class>

The action RandomMove needs a parameter for its move probability. For details, see the description of RandomMove.

The priority values are chosen such that the age is changed fist, then agents may die of old age, and the survivors may move.The dat file tut_Move.dat defines postions and attributes for 20 agents, the last attribute pertainng to the new member m_fAge.

The dat file tut_Move.dat is identical to the dat file of the previous chapter. Apart from the postion and the basic parameters we have to add a parameter for the age.

#Longitude;Latitude;LifeState;AgentID;BirthTime;Gender;Age
8;47;1; 1;-10.0;0;10.0
8;47;1; 2;-10.0;0;10.0
8;47;1; 3;-10.0;0;10.0
...
8;47;1;20;-10.0;0;10.0

In this case, too, all 20 agents are placed at the same location, and all agents are female (Gender: 0=female, 1=male).

Feel free to modify the values in the xml file and see how this changes the outcome.

Grid

For this example we use a subdivided icosahedron

Compiling and Running

We assume that you have created the tutorial directories with the script build_tut_dirs.py. This copies all relevant files to the tutorial subdirectories.

First lets create alternative population and action directories with the script build_alt_modpop.py:

${QHG4_DIR}/useful_stuff/build_alt_modpop.py tut_03 tut_MovePop

This builds alternative population directories tut_03_pop and tut_03_mod.

To compile, cd to the QHG4 root directory and type:

SHORT=tut_03 make clean QHGMain

This is the simplest way to compile QHG (for more information see Compiling QHG)

Now cd to the tutorial subdirectory “tutorial_03’ and start QHGMain

${QHG4_DIR}/app/QHGMain --read-config=tutorial_03.cfg > tutorial_03.out

This tells QHGMain to read the parameters from the file tutorial_03.cfg and write all output to the file tutorial_03.out (this output contains more information than the logfile)

The config file tutorial_03.cfg was created when the tutorial directories were created with build_tut_dirs.py.

--data-dirs=${QHG4_DIR}/tutorial_data/grids/
--events='write|grid+geo+pop:sapiens@20000'
--grid=ico32s.qdf
--log-file=tutorial_03.log
--num-iters=200
--output-dir=output/tutorial_03
--output-prefix=tut
--pops='tut_Move.xml:tut_Move.dat'
--shuffle=92244
--start-time=0
data-dirs

A list of directories to search for data

events

A list of events (see Events). Here a single event is defined: write output at step 20000 (or at the end of the simulation run).

grid

Path to the grid on which to run the simulation.

log-file

Log file for ‘high level’ messages.

num-iters

Number of iterations for the simulation.

output-dir

Output directory for qdf files.

output-prefix

A prefix prepended to the names of all output files

pops

The files for population attributes (tut_Move.xml) and agent attributes (tut_Move.dat). These files were created by build_tut_dirs.py.

shuffle

A kiind of seed for the random nummber generators. Same shuffle values result in idfentical simulations.

start-time

The ‘real’ time corresponding to step 0.

Grid

For this example we use a subdivided icosahedron

Compiling and Running

We assume that you have created the tutorial directories with the script build_tut_dirs.py. This copies all relevant files to the tutorial subdirectories.

First lets create alternative population and action directories with the script build_alt_modpop.py:

${QHG4_DIR}/useful_stuff/build_alt_modpop.py tut_03 tut_MovePop

This builds alternative population directories tut_03_pop and tut_03_mod.

To compile, cd to the QHG4 root directory and type:

SHORT=tut_03 make clean QHGMain

This is the simplest way to compile QHG (for more information see Compiling QHG)

Now cd to the tutorial subdirectory “tutorial_03’ and start QHGMain

${QHG4_DIR}/app/QHGMain --read-config=tutorial_03.cfg > tutorial_03.out

This tells QHGMain to read the parameters from the file tutorial_03.cfg and write all output to the file tutorial_03.out (this output contains more information than the logfile)

The config file tutorial_03.cfg was created when the tutorial directories were created with build_tut_dirs.py.

--data-dirs=/home/jody/progs/multi_spc_QHG3_std/useful_stuff/gridpreparation/
--events='write|grid+geo+pop:sapiens@20000'
--grid=ico32s.qdf
--log-file=tutorial_03.log
--num-iters=200
--output-dir=output/tutorial_03
--output-prefix=nnn
--pops='tut_Move.xml:tut_Move.dat'
--shuffle=92244
--start-time=-200
data-dirs

A list of directories to search for data.

events

A list of events (see Events). Here a single event is defined: write output at step 20000 (or at the end of the simulation run).

grid

Path to the grid on which to run the simulation.

log-file

Log file for ‘high level’ messages.

num-iters

Number of iterations for the simulation.

output-dir

Output directory for qdf files.

output-prefix

A prefix prepended to the names of all output files

pops

The files for population attributes (tut_Move.xml) and agent attributes (tut_Move.dat). These files were created by build_tut_dirs.py.

shuffle

A kind of seed for the random number generators. Same shuffle values result in idfentical simulations.

start-time

The ‘real’ time corresponding to step 0.

The Output File

The output files, in this case tutorial_03.out, always have the same structure. First there are messages concerning the start of the program and intialisation. If the simulation does not run, there’s a chance that you find th readoon why here.

The second part is a list of every step describing the numbers of births, deaths and moves, as well as the time the step took to execute.

At the end there is a short summary of the state at the end of the program: number of iterations, total time of execution, nuber of surviving agents. This is follwed by the contents of the log file.

If you look at the output for the steps, you see that there are still no births, but there are moves an deaths:

After step 45 (0.000115 s): total       20 agents
  sapiens       0 births r
  sapiens       0 deaths r
  sapiens       3 moves
After step 46 (0.000116 s): total       20 agents
  sapiens       0 births r
  sapiens       5 deaths r
  sapiens       4 moves
After step 47 (0.000118 s): total       15 agents
  sapiens       0 births r
  sapiens       2 deaths r
  sapiens       5 deaths p
  sapiens       1 moves

And at the beginning of the last part:

-----
Stopped  Simulation
Number of threads: 8
Number of iterations: 54
Used time: 0.009391 (00:00:00)
Number of agents after last step
  sapiens:         0
    total:         0
+++success+++

The summary at the end:

*** total number of births  0
*** total number of deaths  20
*** total number of moves   82