Step 4: Base Fertility

Model Description

At this step we add a module for fertility based on projected age-specific period fertility rates. This is the base version of fertility resembling a typical macro population projection approach.

The new module: FertilityAgePeriod.mpp

This module implements fertility based on age-specific fertility rates. This module is a microsimulation implementation of a typical cohort component model based on published population projection data.

The model is prepared for being complemented or over-ridden by an alternative refined fertility model. This is done by three logical states:

  • The state use_base_fertility_model is initialized as TRUE; it indicates that the base model is to be used. When adding another model choice this flag can be changed in another module.
  • The state use_base_fertility_for_alignment is initialized with FALSE; it indicates if another model is to be aligned to the fertility outcome of this base model.
  • The state baby_looking_for_mother is set to TRUE at a birth event if the base model is used for alignment only and the actual birth has to be assigned to another person of the population.


////////////////////////////////////////////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////////////////////////////////////////////

range FERTILE_AGE_RANGE { 15, 49 };                                 //EN Fertile age range

////////////////////////////////////////////////////////////////////////////////////////////////////
// Parameters
////////////////////////////////////////////////////////////////////////////////////////////////////

parameters
{
    //EN Age distribution of fertility
    double  AgeSpecificFertility[FERTILE_AGE_RANGE][SIM_YEAR_RANGE];

    //EN Sex ratio (male per 100 female)
    double  SexRatio[SIM_YEAR_RANGE];
};

parameter_group PG03a_Fertility_Model_A  //EN Fertility Base Model
{
    AgeSpecificFertility, SexRatio
};


////////////////////////////////////////////////////////////////////////////////////////////////////
// Actor declarations
////////////////////////////////////////////////////////////////////////////////////////////////////

actor Person
{
    logical use_base_fertility_model = { TRUE };            //EN Use the base model
    logical use_base_fertility_for_alignment = { FALSE };   //EN Use the model for alignment
    logical baby_looking_for_mother = { FALSE };            //EN A birth is still to be created

    //EN Indicator that perion is a potential mother
    logical is_potential_mother = (sex == FEMALE && WITHIN(FERTILE_AGE_RANGE, integer_age)
    && in_projected_time && ever_resident) ? TRUE : FALSE;

    int     parity;                                         //EN Parity
    event       timeBirthEvent, BirthEvent;                     //EN Birth event
};


////////////////////////////////////////////////////////////////////////////////////////////////////
// Event Implementations
////////////////////////////////////////////////////////////////////////////////////////////////////

TIME Person::timeBirthEvent()
{
    double dEventTime = TIME_INFINITE;
    double dHazard = 0.0;

    if (is_potential_mother && (use_base_fertility_model || use_base_fertility_for_alignment))
    {
        dHazard = AgeSpecificFertility[RANGE_POS(FERTILE_AGE_RANGE, integer_age)]
                [RANGE_POS(SIM_YEAR_RANGE, calendar_year)];
        if (dHazard > 0.0) dEventTime = WAIT(-TIME(log(RandUniform(3)) / dHazard));
    }
    return dEventTime;
}

void Person::BirthEvent()
{
    // event applies to individual without alignment
    if (use_base_fertility_model)
    {
        parity++;                   // increment parity
        auto peChild = new Person;  // Create and point to a new actor
        peChild->Start(NULL, this);   // Call Start() function of baby and pass own address
    }
    else if (use_base_fertility_for_alignment)
    {
        baby_looking_for_mother = TRUE;
    }
}

Update of the Start() function in PersonCore.mpp

The Start() function is updated in order to initialize all states at the birth of a baby born in the simulation. In this case values do not come from the starting popiulation file but have to be derived otherwise, e.g. by accessing mother’s characteristics (e.g. for setting the time) or by sampling (e.g. sex according to a parameter for sex ratio).


    else if (person_type == PT_CHILD) // Person born in simulation
    {
        // (A) States corresponding to Starting population file variables
        if (RandUniform(4) < 100.0 / (100.0 + SexRatio[RANGE_POS(SIM_YEAR_RANGE, calendar_year)]))
        {
            sex = FEMALE;
        }
        else sex = MALE;
        time = pePers->time;
        family_role = FR_CHILD;

        // (B) Other states
        time_of_birth = time;
        calendar_year = ( int )time_of_birth;

        // (C) Links to head resp. spouse
        peHHead = pePers;
    }
    //