// Management events ....................................................... /// <summary> /// Add animal cohorts /// </summary> /// <param name="CohortsInfo"></param> /// <param name="iDOY"></param> /// <param name="fLatitude"></param> /// <param name="newGroups"></param> public void AddCohorts(TCohortsInfo CohortsInfo, int iDOY, double fLatitude, List<int> newGroups) { TAnimalParamSet mainGenotype; TAgeInfo[] AgeInfo; TAnimalInits AnimalInits; int iNoCohorts; double fSurvival; int iDaysSinceShearing; double fMeanNormalWt; double fMeanFleeceWt; double fBaseWtScalar; double fFleeceWtScalar; int iTotalAnimals; int iMateDOY; double fLowCondition; double fLowFoetuses; double fHighCondition; double fHighFoetuses; double fCondition; double fTrialFoetuses; double[] fPregRate = new double[4]; //TConceptionArray; int[] iShiftNumber = new int[4]; bool bLactationDone; double fLowChill; double fLowOffspring; double fHighChill; double fHighOffspring; double fChillIndex; double fTrialOffspring; double[] fLactRate = new double[4]; int iCohort; int iPreg; int iLact; int groupIndex; if (CohortsInfo.iNumber > 0) { mainGenotype = getGenotype(CohortsInfo.sGenotype); AgeInfo = new TAgeInfo[CohortsInfo.iMaxYears + 1]; for (int i = 0; i < CohortsInfo.iMaxYears + 1; i++) AgeInfo[i] = new TAgeInfo(); iNoCohorts = CohortsInfo.iMaxYears - CohortsInfo.iMinYears + 1; fSurvival = 1.0 - mainGenotype.AnnualDeaths(false); if (mainGenotype.Animal == GrazType.AnimalType.Cattle) iDaysSinceShearing = 0; else if (bIsGiven(CohortsInfo.fMeanGFW) && (CohortsInfo.iFleeceDays == 0)) iDaysSinceShearing = Convert.ToInt32(Math.Truncate(365.25 * CohortsInfo.fMeanGFW / mainGenotype.PotentialGFW)); else iDaysSinceShearing = CohortsInfo.iFleeceDays; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { //Proportion of all stock in this age cohort if (fSurvival >= 1.0) AgeInfo[iCohort].fPropn = 1.0 / iNoCohorts; else AgeInfo[iCohort].fPropn = (1.0 - fSurvival) * Math.Pow(fSurvival, iCohort - CohortsInfo.iMinYears) / (1.0 - Math.Pow(fSurvival, iNoCohorts)); AgeInfo[iCohort].iAgeDays = Convert.ToInt32(Math.Truncate(365.25 * iCohort) + CohortsInfo.iAgeOffsetDays); // Normal weight for age AgeInfo[iCohort].fNormalBaseWt = GrowthCurve(AgeInfo[iCohort].iAgeDays, CohortsInfo.ReproClass, mainGenotype); // Estimate a default fleece weight based on time since shearing AgeInfo[iCohort].fFleeceWt = TAnimalParamSet.fDefaultFleece(mainGenotype, AgeInfo[iCohort].iAgeDays, CohortsInfo.ReproClass, iDaysSinceShearing); } // Re-scale the fleece-free and fleece weights fMeanNormalWt = 0.0; fMeanFleeceWt = 0.0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fMeanNormalWt = fMeanNormalWt + AgeInfo[iCohort].fPropn * AgeInfo[iCohort].fNormalBaseWt; fMeanFleeceWt = fMeanFleeceWt + AgeInfo[iCohort].fPropn * AgeInfo[iCohort].fFleeceWt; } if ((CohortsInfo.fMeanGFW > 0.0) && (fMeanFleeceWt > 0.0)) fFleeceWtScalar = CohortsInfo.fMeanGFW / fMeanFleeceWt; else fFleeceWtScalar = 1.0; if (!bIsGiven(CohortsInfo.fMeanGFW)) CohortsInfo.fMeanGFW = fMeanFleeceWt; if (bIsGiven(CohortsInfo.fMeanLiveWt)) fBaseWtScalar = (CohortsInfo.fMeanLiveWt - CohortsInfo.fMeanGFW) / fMeanNormalWt; else if (bIsGiven(CohortsInfo.fCondScore)) fBaseWtScalar = TAnimalParamSet.CondScore2Condition(CohortsInfo.fCondScore); else fBaseWtScalar = 1.0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].fBaseWeight = AgeInfo[iCohort].fNormalBaseWt * fBaseWtScalar; AgeInfo[iCohort].fFleeceWt = AgeInfo[iCohort].fFleeceWt * fFleeceWtScalar; } // Numbers in each age cohort iTotalAnimals = 0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].iNumbers[0, 0] = Convert.ToInt32(Math.Truncate(AgeInfo[iCohort].fPropn * CohortsInfo.iNumber)); iTotalAnimals += AgeInfo[iCohort].iNumbers[0, 0]; } for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) if (iTotalAnimals < CohortsInfo.iNumber) { AgeInfo[iCohort].iNumbers[0, 0]++; iTotalAnimals++; } // Pregnancy and lactation if ((CohortsInfo.ReproClass == GrazType.ReproType.Empty) || (CohortsInfo.ReproClass == GrazType.ReproType.EarlyPreg) || (CohortsInfo.ReproClass == GrazType.ReproType.LatePreg)) { // Numbers with each number of foetuses if ((CohortsInfo.iDaysPreg > 0) && (CohortsInfo.fFoetuses > 0.0)) { iMateDOY = 1 + (iDOY - CohortsInfo.iDaysPreg + 364) % 365; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].iAgeAtMating = AgeInfo[iCohort].iAgeDays - CohortsInfo.iDaysPreg; AgeInfo[iCohort].fSizeAtMating = GrowthCurve(AgeInfo[iCohort].iAgeAtMating, CohortsInfo.ReproClass, mainGenotype) / mainGenotype.fSexStdRefWt(CohortsInfo.ReproClass); } // binary search for the body condition at mating that yields the desired pregnancy rate fLowCondition = 0.60; fLowFoetuses = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fLowCondition, 0); fHighCondition = 1.40; fHighFoetuses = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fHighCondition, 0); if (fLowFoetuses > CohortsInfo.fFoetuses) fCondition = fLowCondition; else if (fHighFoetuses < CohortsInfo.fFoetuses) fCondition = fHighCondition; else { do { fCondition = 0.5 * (fLowCondition + fHighCondition); fTrialFoetuses = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fCondition, 0); if (fTrialFoetuses < CohortsInfo.fFoetuses) fLowCondition = fCondition; else fHighCondition = fCondition; } while (Math.Abs(fTrialFoetuses - CohortsInfo.fFoetuses) >= 1.0E-5); //until (Abs(fTrialFoetuses-CohortsInfo.fFoetuses) < 1.0E-5); } // Compute final pregnancy rates and numbers for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fPregRate = getOffspringRates(mainGenotype, fLatitude, iMateDOY, AgeInfo[iCohort].iAgeAtMating, AgeInfo[iCohort].fSizeAtMating, fCondition); for (iPreg = 1; iPreg <= 3; iPreg++) iShiftNumber[iPreg] = Convert.ToInt32(Math.Round(fPregRate[iPreg] * AgeInfo[iCohort].iNumbers[0, 0])); for (iPreg = 1; iPreg <= 3; iPreg++) { AgeInfo[iCohort].iNumbers[iPreg, 0] += iShiftNumber[iPreg]; AgeInfo[iCohort].iNumbers[0, 0] -= iShiftNumber[iPreg]; } } } // if (iDaysPreg > 0) and (fFoetuses > 0.0) // Numbers with each number of suckling young // Different logic for sheep and cattle: // - for sheep, first assume average body condition at conception and vary // the chill index. If that doesn't work, fix the chill index & vary the // body condition // - for cattle, fix the chill index & vary the body condition if ((CohortsInfo.iDaysLact > 0) && (CohortsInfo.fOffspring > 0.0)) { bLactationDone = false; fCondition = 1.0; fChillIndex = 0; iMateDOY = 1 + (iDOY - CohortsInfo.iDaysLact - mainGenotype.Gestation + 729) % 365; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].iAgeAtMating = AgeInfo[iCohort].iAgeDays - CohortsInfo.iDaysLact - mainGenotype.Gestation; AgeInfo[iCohort].fSizeAtMating = GrowthCurve(AgeInfo[iCohort].iAgeAtMating, CohortsInfo.ReproClass, mainGenotype) / mainGenotype.fSexStdRefWt(CohortsInfo.ReproClass); } if (mainGenotype.Animal == GrazType.AnimalType.Sheep) { // binary search for the chill index at birth that yields the desired proportion of lambs fLowChill = 500.0; fLowOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, 1.0, fLowChill); fHighChill = 2500.0; fHighOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, 1.0, fHighChill); // this is a monotonically decreasing function... if ((fHighOffspring < CohortsInfo.fOffspring) && (fLowOffspring > CohortsInfo.fOffspring)) { do { fChillIndex = 0.5 * (fLowChill + fHighChill); fTrialOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, 1.0, fChillIndex); if (fTrialOffspring > CohortsInfo.fOffspring) fLowChill = fChillIndex; else fHighChill = fChillIndex; } while (Math.Abs(fTrialOffspring - CohortsInfo.fOffspring) >= 1.0E-5); //until (Abs(fTrialOffspring-CohortsInfo.fOffspring) < 1.0E-5); bLactationDone = true; } } // fitting lactation rate to a chill index if (!bLactationDone) { fChillIndex = 800.0; // binary search for the body condition at mating that yields the desired proportion of lambs or calves fLowCondition = 0.60; fLowOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fLowCondition, fChillIndex); fHighCondition = 1.40; fHighOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fHighCondition, fChillIndex); if (fLowOffspring > CohortsInfo.fOffspring) fCondition = fLowCondition; else if (fHighOffspring < CohortsInfo.fOffspring) fCondition = fHighCondition; else { do { fCondition = 0.5 * (fLowCondition + fHighCondition); fTrialOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fCondition, fChillIndex); if (fTrialOffspring < CohortsInfo.fOffspring) fLowCondition = fCondition; else fHighCondition = fCondition; } while (Math.Abs(fTrialOffspring - CohortsInfo.fOffspring) >= 1.0E-5); //until (Abs(fTrialOffspring-CohortsInfo.fOffspring) < 1.0E-5); } } // fitting lactation rate to a condition // Compute final offspring rates and numbers for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fLactRate = getOffspringRates(mainGenotype, fLatitude, iMateDOY, AgeInfo[iCohort].iAgeAtMating, AgeInfo[iCohort].fSizeAtMating, fCondition, fChillIndex); for (iPreg = 0; iPreg <= 3; iPreg++) { for (iLact = 1; iLact <= 3; iLact++) iShiftNumber[iLact] = Convert.ToInt32(Math.Round(fLactRate[iLact] * AgeInfo[iCohort].iNumbers[iPreg, 0])); for (iLact = 1; iLact <= 3; iLact++) { AgeInfo[iCohort].iNumbers[iPreg, iLact] += iShiftNumber[iLact]; AgeInfo[iCohort].iNumbers[iPreg, 0] -= iShiftNumber[iLact]; } } } } //_ lactating animals _ } //_ female animals // Construct the animal groups from the numbers and cohort-specific information AnimalInits.sGenotype = CohortsInfo.sGenotype; AnimalInits.sMatedTo = CohortsInfo.sMatedTo; AnimalInits.Sex = CohortsInfo.ReproClass; AnimalInits.Birth_CS = StdMath.DMISSING; AnimalInits.Paddock = ""; AnimalInits.Tag = 0; AnimalInits.Priority = 0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { for (iPreg = 0; iPreg <= 3; iPreg++) { for (iLact = 0; iLact <= 3; iLact++) { if (AgeInfo[iCohort].iNumbers[iPreg, iLact] > 0) { AnimalInits.Number = AgeInfo[iCohort].iNumbers[iPreg, iLact]; AnimalInits.AgeDays = AgeInfo[iCohort].iAgeDays; AnimalInits.Weight = AgeInfo[iCohort].fBaseWeight + AgeInfo[iCohort].fFleeceWt; AnimalInits.MaxPrevWt = StdMath.DMISSING; // compute from cond_score AnimalInits.Fleece_Wt = AgeInfo[iCohort].fFleeceWt; AnimalInits.Fibre_Diam = TAnimalParamSet.fDefaultMicron(mainGenotype, AnimalInits.AgeDays, AnimalInits.Sex, iDaysSinceShearing, AnimalInits.Fleece_Wt); if (iPreg > 0) { AnimalInits.Pregnant = CohortsInfo.iDaysPreg; AnimalInits.No_Foetuses = iPreg; } else { AnimalInits.Pregnant = 0; AnimalInits.No_Foetuses = 0; } if ((iLact > 0) || ((mainGenotype.Animal == GrazType.AnimalType.Cattle) && (CohortsInfo.iDaysLact > 0) && (CohortsInfo.fOffspring == 0.0))) { AnimalInits.Lactating = CohortsInfo.iDaysLact; AnimalInits.No_Suckling = iLact; AnimalInits.Young_GFW = CohortsInfo.fLambGFW; AnimalInits.Young_Wt = CohortsInfo.fOffspringWt; } else { AnimalInits.Lactating = 0; AnimalInits.No_Suckling = 0; AnimalInits.Young_GFW = 0.0; AnimalInits.Young_Wt = 0.0; } groupIndex = Add(AnimalInits); if (newGroups != null) { newGroups.Add(groupIndex); } } } } } } // if CohortsInfo.iNumber > 0 }
/// <summary> /// /// </summary> /// <param name="CohortsInfo"></param> /// <param name="mainGenotype"></param> /// <param name="AgeInfo"></param> /// <param name="fLatitude"></param> /// <param name="iMateDOY"></param> /// <param name="fCondition"></param> /// <param name="fChill"></param> /// <returns></returns> private double getReproRate(TCohortsInfo CohortsInfo, TAnimalParamSet mainGenotype, TAgeInfo[] AgeInfo, double fLatitude, int iMateDOY, double fCondition, double fChill) { double Result = 0.0; double[] fPregRate = new double[4]; int iCohort; int N; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fPregRate = getOffspringRates(mainGenotype, fLatitude, iMateDOY, AgeInfo[iCohort].iAgeAtMating, AgeInfo[iCohort].fSizeAtMating, fCondition, fChill); for (N = 1; N <= 3; N++) Result = Result + AgeInfo[iCohort].fPropn * fPregRate[N]; } return Result; }