microWELT

Contents:

  • Projects
  • Documentation
    • MicroWELT 1.0
      • Weltransim Report & Publications
      • Model Code
      • Implementation
        • Step 1: Creating a Population
        • Step 2: Birthdays
        • Step 3: Base Mortality
        • Step 4: Base Fertility
        • Step 5: Education Fate Base Model
        • Step 6: Primary Education Fate Refined Model
        • Step 7: Refined Mortality
        • Step 8: Refined Fertility
        • Step 9: Male Childlessness
        • Step 10: Education Pattern
        • Step 11: Female Partnership Status
        • Step 12: Partner Matching
        • Step 13: Family Links
        • Step 14: Education Alignment
        • Step 15: Emigration
        • Step 16: Immigration
        • Step 17: Basic NTA
        • Step 18: Basic NTA Indicators (Lee & Mason 2017)
        • Step 19: NTA Validation
        • Step 20: NTA Full Generational Accounts
        • Step 21: Net Migration
        • Step 22: Table Output
      • Analysis Scripts
      • User Guide
      • Downloads
    • MicroWELT 2.0 LTC
    • MicroDEMS
  • Publications
  • Presentations
  • About
microWELT
  • Documentation
  • MicroWELT 1.0
  • Implementation
  • Step 13: Family Links
  • View page source

Step 13: Family Links

Overview

At this step we re-organize, revise, and maintain all family links by introducing a new dedicated module FamilyLinks.mpp. Family links are links between spouses, links between children and their biological parents, and of children with their parents or guardians with whom they currently live in a household. Family links are first established at birth and maintained at union formation, union dissolution, when leaving home, and at death. At each event the family status is updated (i.e. being a household head, spouse, or child) and all links are updated. For leaving home we create a new event. The update of links includes the children’s decision with whom to stay after a union dissolution and the search for a suitable guardian if a lone parent dies.

The new FamilyLinks.mpp Module

This module handles and maintains family links. Family links are links between spouses, links between children and their biological parents, and of children with their parents or guardians with whom they currently live in a household. We model nuclear family households, consisting of a household head, and - if present - a spouse and dependent children.

Dependent children are:

  • Children below age 18 who are not in a union or parents themselves

  • Children below age 26 as long as they are continuously enrolled in education and not in a union or parents themselves - and who have not left home

Maintenance of links at death is handled in the function MaintainLinksAtDeath() linked to the mortality event. A spouse becomes the household head. If there is no spouse but children in the household, each child checks if she has a biological mother or father, or a grand mother or grand father alive, in which case she moves to a new guardian and updates all links. If not, and at age 18+, she becomes a household head.

Maintenance of links at union formations is handled in the function MaintainLinksAtUnionFormation() called at union formation. Partners become a household head and spouse and all children who lived with any of the two partners before in a household now update their family links as they now live with two “guardians”. (The link to biological parents is kept over life and can be different from the links to the household head and the spouse of the household head). If a union formation happens in the first year after giving birth and the baby has no biological father assigned, it is assumed that the male partner is the biological father of the baby.

Maintenance of links at union dissolution is handled in the function DissolveUnion() which is called when a union is dissolved. Both former partners now become household heads and children have to choose with whom to live. The choice is modeled by a set of simple rules and a probability to stay with the famale guardian. If only one of the two guardians is a biological parent, children choose to stay with the biological parent. Otherwise, the choice is random dependent on the parameter. All children who randomly decide make the same choice.

Leaving home is modelled as an event LeavingHomeEvent() which is called immediately after any union formation or increase of parity, at age 18 if not enrolled in school, at the moment of leaving school after age 18, or at age 26. In addition, children in education age 18-25 can leave home at any point in time following a parameter of age-specific home-leaving rates of students. Once a person has left the household, she is not moving back. The family status changes from child to household head or to spouse.

The creation of links at birth is handled in the function LinkFamilyAtBirth() hooked to the SetAliveEvent(). For children in the starting population it is assumed that both parents - if present in the household - are biological parents.



////////////////////////////////////////////////////////////////////////////////////////////////////
// Family Links
////////////////////////////////////////////////////////////////////////////////////////////////////

link Person.lBioFather Person.mlBioFatherChildren[];    //EN Biological Father - Children
link Person.lBioMother Person.mlBioMotherChildren[];    //EN Biological Mother - Children

link Person.lHHFather Person.mlHHFatherChildren[];      //EN HH Father - Children
link Person.lHHMother Person.mlHHMotherChildren[];      //EN HH Mother - Children

link Person.lSpouse;                                    //EN Spouses

////////////////////////////////////////////////////////////////////////////////////////////////////
// Dimensions
////////////////////////////////////////////////////////////////////////////////////////////////////

classification FAM_ROLE                                 //EN Role in family
{
    FR_HEAD,                                            //EN Head
    FR_SPOUSE,                                          //EN Spouse of head
    FR_CHILD                                            //EN Child
};

range AGE_18_25 { 18, 25 };                             //EN Age

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

parameters
{
    double ProbStayWithMother;        //EN Probability to stay with mother after union dissolution
    double ProbLeaveHome[AGE_18_25];  //EN Probability to leave home (students)
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Actor States and Functions
////////////////////////////////////////////////////////////////////////////////////////////////////

actor Person
{
    FAM_ROLE    family_role = { FR_HEAD };                  //EN Family Role

    void        LinkFamilyAtBirth();                        //EN Establish family links at birth
    hook        LinkFamilyAtBirth, SetAliveEvent;           //EN Called at set alive event

    event       timeLeavingHomeEvent, LeavingHomeEvent;     //EN Leaving Home

    void        MaintainLinksAtUnionFormation();            //EN Family links at union formation
    hook        MaintainLinksAtUnionFormation, FindPartner; //EN Update at end of FindPartner()

    void        MaintainLinksAtDeath();                     //EN Family links at death
    hook        MaintainLinksAtDeath, MortalityEvent;       //EN Update at Death

    void        DissolveUnion();                            //EN Union Dissolution

    //EN Children in Household
    short       children_in_household = (sex == FEMALE) ?
                    sum_over(mlHHMotherChildren, is_alive) :
                    sum_over(mlHHFatherChildren, is_alive);
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////////////////////////


void Person::MaintainLinksAtDeath()
{
    if (lSpouse) lSpouse->family_role = FR_HEAD;
    else if (children_in_household > 0)
    {
        //try to find somebody for children
        int nIndex;
        auto prChild = (sex==FEMALE) ? mlHHMotherChildren->GetNext( 0, &nIndex ) : mlHHFatherChildren->GetNext( 0, &nIndex );
        while ( prChild != NULL )
        {
            Person * prGuardian = NULL;
            if (sex == FEMALE && prChild->lBioFather)    // own biological father
            {
                prGuardian = prChild->lBioFather;
            }
            else if (sex == MALE && prChild->lBioMother)  // own biological mother
            {
                prGuardian = prChild->lBioMother;
            }
            else if (lBioMother)                          // grandmother
            {
                prGuardian = lBioMother;
            }
            else if (lBioFather)                          // grandfather
            {
                prGuardian = lBioFather;
            }
            else if (prChild->integer_age >= 18)          // nobody
            {
                prChild->family_role = FR_HEAD;
            }
            if (prGuardian && prGuardian->sex == MALE)
            {
                prChild->lHHFather = prGuardian;
                if (prGuardian->lSpouse) prChild->lHHMother = prGuardian->lSpouse;
            }
            else if (prGuardian && prGuardian->sex == FEMALE)
            {
                prChild->lHHMother = prGuardian;
                if (prGuardian->lSpouse) prChild->lHHFather = prGuardian->lSpouse;
            }
            prChild = (sex==FEMALE) ? mlHHMotherChildren->GetNext( nIndex+1, &nIndex ) : mlHHFatherChildren->GetNext( nIndex+1, &nIndex );
        }
    }
}


void Person::DissolveUnion()
{
    if (lSpouse)
    {
        //For all children in household decide with whom to stay
        if (children_in_household)
        {
            int nIndex;
            bool bStayWithMother = (RandUniform(32) < ProbStayWithMother);
            //Stay with mother
            auto prChild = mlHHMotherChildren->GetNext( 0, &nIndex );
            while ( prChild != NULL )
            {
                if (bStayWithMother && ((prChild->lBioMother && prChild->lBioMother == this)
                    || !prChild->lBioFather || (prChild->lBioFather && prChild->lBioFather != lSpouse)))
                {
                    prChild->lHHFather = NULL;
                }
                prChild = mlHHMotherChildren->GetNext(nIndex + 1, &nIndex);
            }
            //Stay with father
            if (lSpouse->children_in_household)
            {
                auto prChild = lSpouse->mlHHFatherChildren->GetNext( 0, &nIndex );
                while ( prChild != NULL )
                {
                   prChild->lHHMother = NULL;
                   prChild = lSpouse->mlHHFatherChildren->GetNext(nIndex + 1, &nIndex);
                }
            }
        }
        lSpouse->family_role = FR_HEAD;
        family_role = FR_HEAD;
        lSpouse = NULL;
    }
}

void Person::MaintainLinksAtUnionFormation()
{
    // Partners children in HH now live also with this woman
    if (lSpouse && lSpouse->children_in_household)
    {
        int nIndex;
        auto prChild = lSpouse->mlHHFatherChildren->GetNext( 0, &nIndex );
        while ( prChild != NULL )
        {
            prChild->lHHMother = this;
            prChild = lSpouse->mlHHFatherChildren->GetNext(nIndex + 1, &nIndex);
        }
    }
    if (lSpouse)
    {
        // Own children in HH also live with partner now
        int nIndex;
        auto prChild = mlHHMotherChildren->GetNext( 0, &nIndex );
        while ( prChild != NULL )
        {
            prChild->lHHFather = lSpouse;
            // if babies without biological father, the spouse becomes biological father
            if (!prChild->lBioFather && prChild->integer_age == 0)
            {
                prChild->lBioFather = lSpouse;
            }
            prChild = mlHHMotherChildren->GetNext(nIndex + 1, &nIndex);
        }
        family_role = FR_HEAD;
        lSpouse->family_role = FR_SPOUSE;

        // own household
        lHHFather = NULL;
        lHHMother = NULL;
        lSpouse->lHHFather = NULL;
        lSpouse->lHHMother = NULL;
    }
}

TIME Person::timeLeavingHomeEvent()
{
    if (in_projected_time && family_role == FR_CHILD
        && (integer_age >= 26 || lSpouse || (integer_age >= 18 && !in_school) || parity > 0))
    {
        return WAIT(0);
    }
    else if (family_role == FR_CHILD && WITHIN(AGE_18_25, integer_age))
    {
        double dProb = ProbLeaveHome[RANGE_POS(AGE_18_25, integer_age)];
        if (dProb >= 1.0) return WAIT(0);
        else if (dProb > 0.0) return WAIT(-log(RandUniform(33)) / -log(1 - dProb));
        else return TIME_INFINITE;
    }
    else return TIME_INFINITE;
}

void Person::LeavingHomeEvent()
{
    // become a head or a spouse
    if (lSpouse && lSpouse->family_role == FR_HEAD) family_role = FR_SPOUSE;
    else family_role = FR_HEAD;

    // remove links to household
    lHHFather = NULL;
    lHHMother = NULL;
}

void Person::LinkFamilyAtBirth()
{
    if (person_type == PT_START && family_role != FR_HEAD && peHHead != NULL)
    {
        if (family_role == FR_CHILD)
        {
            if (peHHead->sex == MALE)
            {
                lBioFather = peHHead;
                if (lBioFather->lSpouse) lBioMother = lBioFather->lSpouse;
            }
            else
            {
                lBioMother = peHHead;
                if (lBioMother->lSpouse) lBioFather = lBioMother->lSpouse;
            }
            lHHFather = lBioFather;
            lHHMother = lBioMother;
        }
        else
        {
            lSpouse = peHHead;
            if (sex == lSpouse->sex) // FIX: do not allow same sex couples
            {
                if (sex == FEMALE) sex = MALE; else sex = FEMALE;
            }
        }
    }
    else if (person_type == PT_CHILD)
    {
        lBioMother = peHHead;
        if (lBioMother->lSpouse) lBioFather = lBioMother->lSpouse;
        lHHFather = lBioFather;
        lHHMother = lBioMother;
    }
}


////////////////////////////////////////////////////////////////////////////////////////////////////
// Validation Tables
////////////////////////////////////////////////////////////////////////////////////////////////////


table Person TabFamilyRoleTest //EN FAMILY ROLE
[WITHIN(SIM_YEAR_RANGE, calendar_year)]
{
    sex+ *
    {
        duration(family_role, FR_CHILD) / duration(), //EN Child
        duration(family_role, FR_HEAD) / duration(), //EN Head
        duration(family_role, FR_SPOUSE) / duration() //EN Spouse
    }
    * integer_age
    * sim_year
};
Previous Next

© Copyright 2025 - site created by the WIFO dynamic microsimulation team.

Built with Sphinx using a theme provided by Read the Docs.