5.17. Step 17: Secondary Education

5.17.1. Model Description

At this step we add an optional module for a secondary school which can be attended after graduating from primary school. The model is a period model parameterized by intake, progression and repetition rates.

5.17.2. The new Educ2BasePeriodModel.mpp Module

This is an optional module for modeling a “School Two” which can be attended after graduating from the”School One” - in the current implementation this school refers tw a secondary school. The number of grades can be set in the range EDUC_TWO_GRADE and thus is adaptable for the application context. The model follows a period approach. Each year at the end and beginning of school season it is decided if a person enters school, succeeds a grade, progresses to the next or repeats a grade, interrups studies or permanently drops out. A parameter controls the maximum number of years which can be delayed due to repetition or temporary dropout. A student interrupting education can resume studies after a year or stay out permanently. The model is driven by parameters for each calendar year and grade:

  • The probability to pass a grade
  • The probability to move on directly after passing a grade
  • The probability to repeat a grade immediately after failing it
  • The probability to resume studies after being out for a year after passing a grade
  • The pribability to repeat a grade after being out for a year after failing a grade
  • The maximum number of years studies can be delayed by repetition or inactive spells

Besides grade and period, the school progression parameters have two additional dimensions, one for geographical region, the other for personal characteristics. The levels of these two characteristics are model specific, they are declared in the classifications EDUC_TWO_GEO and EDUC_TWO_GROUP, with the corresponding states educ_two_geo and educ_two_group. Currently only totals are implemented.

As an optional module the module can be added or removed from the model. The only required code change in other modules is the creation of the actor SchoolTwoActor in the Simulation() function.



////////////////////////////////////////////////////////////////////////////////////////////////////
// Actor Sets
////////////////////////////////////////////////////////////////////////////////////////////////////

//EN The School Two
actor_set SchoolTwoActor asSchoolTwoActor;

//EN Potential Students of School Two
actor_set Person asPotentialSchoolTwoStudent
    filter educ_one_grade_passed == MAX(EDUC_ONE_GRADE)
    && educ_two_status != ETS_OUT && educ_two_delay <= Educ2AllowedDelays;

//EN Students of School Two To Be Processed
actor_set Person asPotentialSchoolTwoStudentToProcess
    filter is_alive && educ_two_to_process;

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

range EDUC_TWO_GRADE { 1, 6 };          //EN Grades School Two
range EDUC_TWO_GRADE0 { 0 , 6 };        //EN Grades School Two (incl. 0)
range EDUC_TWO_ENTRY_DUR { 0, 2 };      //EN Possible entry points years since primary

classification EDUC_TWO_STATUS          //EN Current attendance status in School Two
{
    ETS_NEVER,                          //EN Never entered
    ETS_WAIT,                           //EN Wait for entry (e.g. school break)
    ETS_ATTEND,                         //EN Currently attending
    ETS_PAUSE,                          //EN Pause
    ETS_OUT                             //EN Left school
};

classification EDUC_TWO_GEO             //EN Regional Unit
{
    ETG_OO                              //EN All
};

classification EDUC_TWO_GROUP           //EN Population Group
{
    E2G_OO                              //EN All
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Prameters
////////////////////////////////////////////////////////////////////////////////////////////////////

parameters
{
    //EN Lower Secondary Period Direct Progression Intake
    double  Educ2DirectProgressionIntake[EDUC_TWO_GEO][EDUC_TWO_GROUP][EDUC_TWO_GRADE][SIM_YEAR_RANGE];

    //EN Lower Secondary Period Delayed Progression Intake
    double  Educ2DelayedProgressionIntake[EDUC_TWO_GEO][EDUC_TWO_GROUP][EDUC_TWO_GRADE][SIM_YEAR_RANGE];

    //EN Lower Secondary Period Success
    double  Educ2PeriodSuccess[EDUC_TWO_GEO][EDUC_TWO_GROUP][EDUC_TWO_GRADE][SIM_YEAR_RANGE];

    //EN Lower Secondary Period Direct Repetition Intake
    double  Educ2DirectRepetitionIntake[EDUC_TWO_GEO][EDUC_TWO_GROUP][EDUC_TWO_GRADE][SIM_YEAR_RANGE];

    //EN Lower Secondary Period Delayed Repetition Intake
    double  Educ2DelayedRepetitionIntake[EDUC_TWO_GEO][EDUC_TWO_GROUP][EDUC_TWO_GRADE][SIM_YEAR_RANGE];

    //EN Maximum years of delays allowed (interruption, repetition of grades)
    int     Educ2AllowedDelays;

    model_generated double  StartSchoolTwoYear;                     //EN Start of school year
    model_generated double  EndSchoolTwoYear;                       //EN End of school year
};

parameter_group EducTwo  //EN Secondary School
{
    Educ2DirectProgressionIntake, Educ2DelayedProgressionIntake, Educ2PeriodSuccess,
    Educ2DirectRepetitionIntake, Educ2DelayedRepetitionIntake, Educ2AllowedDelays
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Actors
////////////////////////////////////////////////////////////////////////////////////////////////////

actor Person
{
    int                 educ_two_delay = { 0 };
    logical             educ_two_to_process = { FALSE };
    EDUC_TWO_STATUS     educ_two_status = { ETS_NEVER };
    EDUC_TWO_GRADE0     educ_two_grade_attended = { 0 };    //EN Highest grade attended
    EDUC_TWO_GRADE0     educ_two_grade_passed = { 0 };      //EN Highest grade passed
    EDUC_TWO_GEO        educ_two_geo = {ETG_OO};            //EN Geographical location
    EDUC_TWO_GROUP      educ_two_group = {E2G_OO};          //EN Person group
};

actor SchoolTwoActor
{
    TIME time_start_school_two_year = { TIME_INFINITE};         //EN Next start of school year
    TIME time_end_school_two_year = { TIME_INFINITE};           //EN Next end of school year

    event timeStartSchoolTwoYearEvent, StartSchoolTwoYearEvent; //EN Start school year event
    event timeEndSchoolTwoYearEvent, EndSchoolTwoYearEvent;     //EN End school year event
};

actor Clock
{
    void SetSchoolYearTwoClock();                          //EN Clock for scheduling school year
    hook SetSchoolYearTwoClock, StartYearClock;            //EN Hooked to Start Year
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementation School Two Functions
////////////////////////////////////////////////////////////////////////////////////////////////////

TIME SchoolTwoActor::timeStartSchoolTwoYearEvent(){return time_start_school_two_year;}
void SchoolTwoActor::StartSchoolTwoYearEvent()
{
    for (long nJ = 0; nJ < asPotentialSchoolTwoStudent->Count(); nJ++)
    {
        auto prPerson = asPotentialSchoolTwoStudent->Item(nJ);
        if (prPerson->educ_two_status == ETS_WAIT )
        {
            prPerson->educ_two_status = ETS_ATTEND ;
            prPerson->educ_two_grade_attended = prPerson->educ_two_grade_passed + 1;
        }
    }
    time_start_school_two_year = TIME_INFINITE;
}

TIME SchoolTwoActor::timeEndSchoolTwoYearEvent(){return time_end_school_two_year;}
void SchoolTwoActor::EndSchoolTwoYearEvent()
{
    // Flag the persons to be processed
    for (long nJ = 0; nJ < asPotentialSchoolTwoStudent->Count(); nJ++)
    {
        auto prPerson = asPotentialSchoolTwoStudent->Item(nJ);
        prPerson->educ_two_to_process = TRUE;
    }

    // Process all potential students
    for (long nJ = 0; nJ < asPotentialSchoolTwoStudentToProcess->Count(); nJ++)
    {
        auto prPerson = asPotentialSchoolTwoStudentToProcess->Item(nJ);

        int nGeo         = prPerson->educ_two_geo;
        int nGroup       = prPerson->educ_two_group;
        int nGradeAttend = RANGE_POS(EDUC_TWO_GRADE, prPerson->educ_two_grade_attended);
        int nYear        = RANGE_POS(SIM_YEAR_RANGE, prPerson->calendar_year);


        // Potential Student has not entered school yet
        if (prPerson->educ_two_status == ETS_NEVER && (
            ( prPerson->educ_two_delay == 0 && RandUniform(39) < Educ2DirectProgressionIntake[nGeo][nGroup][0][nYear] ) ||
            ( prPerson->educ_two_delay == 1 && RandUniform(40) < Educ2DelayedProgressionIntake[nGeo][nGroup][0][nYear] )))
        {
            prPerson->educ_two_status = ETS_WAIT;
            prPerson->educ_two_delay = 0;           //reset at school entry
        }
        else if (prPerson->educ_two_status == ETS_NEVER) prPerson->educ_two_delay++;

        // Active student in last year
        else if (prPerson->educ_two_grade_attended == MAX(EDUC_TWO_GRADE) && prPerson->educ_two_status == ETS_ATTEND)
        {
            // Graduate
            if ( RandUniform(41) < Educ2PeriodSuccess[nGeo][nGroup][nGradeAttend][nYear] )
            {
                prPerson->educ_two_grade_passed = prPerson->educ_two_grade_attended;
                prPerson->educ_two_status = ETS_OUT;
            }
            // Fail and repeat if still time
            else if (RandUniform(42) < Educ2DirectRepetitionIntake[nGeo][nGroup][nGradeAttend][nYear] && prPerson->educ_two_delay < Educ2AllowedDelays)
            {
                prPerson->educ_two_delay++;
                prPerson->educ_two_status = ETS_WAIT;
            }
            // Fail and wait
            else if ( prPerson->educ_two_delay + 1 < Educ2AllowedDelays )
            {
                prPerson->educ_two_delay++;
                prPerson->educ_two_status = ETS_PAUSE;
            }
            // Fail and finally out
            else
            {
                prPerson->educ_two_status = ETS_OUT;
            }
        }

        // Active student before last year
        else if (prPerson->educ_two_grade_attended < MAX(EDUC_TWO_GRADE) && prPerson->educ_two_status == ETS_ATTEND)
        {
            // Decide grade success
            if ( RandUniform(43) < Educ2PeriodSuccess[nGeo][nGroup][nGradeAttend][nYear] )
            {
                prPerson->educ_two_grade_passed = prPerson->educ_two_grade_attended;
            }
            // Success
            if ( prPerson->educ_two_grade_passed == prPerson->educ_two_grade_attended )
            {
                if (RandUniform(44) < Educ2DirectProgressionIntake[nGeo][nGroup][nGradeAttend+1][nYear])
                {
                    prPerson->educ_two_status = ETS_WAIT;
                }
                else if (prPerson->educ_two_delay < Educ2AllowedDelays)
                {
                    prPerson->educ_two_delay++;
                    prPerson->educ_two_status = ETS_PAUSE;
                }
                else prPerson->educ_two_status = ETS_OUT;
            }
            // no success
            else
                if (RandUniform(45) < Educ2DirectRepetitionIntake[nGeo][nGroup][nGradeAttend][nYear]
                    && prPerson->educ_two_delay < Educ2AllowedDelays)
                {
                    prPerson->educ_two_delay++;
                    prPerson->educ_two_status = ETS_WAIT;
                }
                else if (prPerson->educ_two_delay + 1 < Educ2AllowedDelays)
                {
                    prPerson->educ_two_delay = prPerson->educ_two_delay + 2;
                    prPerson->educ_two_status = ETS_PAUSE;
                }
                else prPerson->educ_two_status = ETS_OUT;
        }
        // Previousely inactive
        else
        {
            // Progression
            if ( prPerson->educ_two_grade_attended == prPerson->educ_two_grade_passed
                && RandUniform(46) < Educ2DelayedProgressionIntake[nGeo][nGroup][nGradeAttend+1][nYear] )
            {
                prPerson->educ_two_status = ETS_WAIT;
            }
            // Repetition
            else if (RandUniform(47) < Educ2DelayedRepetitionIntake[nGeo][nGroup][nGradeAttend][nYear] )
            {
                prPerson->educ_two_status = ETS_WAIT;
            }
            else prPerson->educ_two_status = ETS_OUT;
        }
    }

    // Unflag all persons
    while (asPotentialSchoolTwoStudentToProcess->Count() > 0)
    {
        asPotentialSchoolTwoStudentToProcess->Item(0)->educ_two_to_process = FALSE;
    }
    time_end_school_two_year = TIME_INFINITE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementatation Clock Functions
////////////////////////////////////////////////////////////////////////////////////////////////////

void Clock::SetSchoolYearTwoClock()
{
    asSchoolTwoActor->Item(0)->time_start_school_two_year = WAIT(StartSchoolTwoYear);
    asSchoolTwoActor->Item(0)->time_end_school_two_year = WAIT(EndSchoolTwoYear);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Pre-Simulation
////////////////////////////////////////////////////////////////////////////////////////////////////

void PreSimulation()
{
    StartSchoolTwoYear = StartSchoolOneYear + 0.000114155;  // one hour later than school one
    EndSchoolTwoYear = EndSchoolOneYear + 0.000114155;      // one hour later than school one
};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

table Person School2TrackTab //EN School TWO Enrolment
[trigger_changes(calendar_year) && in_projected_time && is_resident && educ_two_status == ETS_ATTEND]
{
    {
        unit          //EN Students
    }
    * sim_year
    * educ_two_grade_attended+
};

5.17.3. Initializations in the Simulation() Function

The new actor is created in the Simulation() function.


    // Create the School Two
    auto prSchoolTwoActor = new SchoolTwoActor();
    prSchoolTwoActor->Start();