public static double TemperatureStressFactor(TreeModel treeModel) { EnvironmentParams envirParams = treeModel.EnvironmentParams; return(TemperatureStressFactor(FunctionSim.GrowthPeriodJudgment(treeModel), envirParams.DailyMaxTemperature, envirParams.DailyMinTemperature)); }
public void NextDay(bool isClear = true) { if (CurrentStep <= 1) { Init(); } int preGC = ComputeGrowthCycle(); int curGC = FunctionSim.ComputeGrowthCycle(this); //未出苗 if (preGC < 1 && preGC == curGC) { TemperatureAccumulation(); return; } double biomass = PreviousDaylightOutput(out IsStopDevelopment); if (IsStopDevelopment) { return; } bool isSameGC = true; if (preGC != curGC) { /* * 当当前生长周期与实际计算得到的生长周期不同时 * 则发生拓扑变化 */ NextStep(); /* * 生长周期发生变化 * 用该标识符记录 */ isSameGC = false; } /* * 对植物的形态进行模拟 * 随后用于下一阶段生物量的产生 */ MorphologicalSim(biomass, isClear, isSameGC); /* * 积温累加 * 用于判断当前生长周期 */ TemperatureAccumulation(); /* * 计算叶面积指数 * 用于计算第二天生物量分配 */ ComputeLAI(); }
public static double WaterStressFactor(TreeModel treeModel) { EnvironmentParams envirParams = treeModel.EnvironmentParams; return(WaterStressFactor(envirParams.DailyMaxTemperature, envirParams.DailyMinTemperature, envirParams.DailyMaxRelativeHumidity, envirParams.DailyMinRelativeHumidity, envirParams.WindSpeed, SolarSim.DailyDirectIrradiance(DateTime.Now, 119, 26), treeModel.ComputeGrowthCycle(), FunctionSim.GrowthPeriodJudgment(treeModel), envirParams.WaterContent)); }
public void MorphologicalSim(List <BranchIndex> branchIndexes, List <OrganIndex> organIndexes) { GrowthPeriod period = FunctionSim.GrowthPeriodJudgment(branchIndexes, organIndexes); //判断生长时期 if (period <= GrowthPeriod.TASSELING_STAGE) { MorphologicalSim(FemaleType.Hair); } else { MorphologicalSim(FemaleType.Corn); } }
/// <summary> /// 模拟整日的太阳辐射,并返回这段时间内累积的生物量(单位 g) /// </summary> /// <param name="Time">时间</param> /// <param name="Longitude">经度</param> /// <param name="Latitude">纬度</param> /// <param name="_Octree">由植物构建的八叉树模型</param> /// <param name="d">光线之间的间隔,即光线密度</param> /// <param name="LatitudeNum">纬度方向的剖分个数</param> /// <param name="LongtitudeNum">经度度方向的剖分个数</param> /// <returns>累积的生物量(单位 g)</returns> public static double DailySunShineSimluation(TreeModel treeModel, DateTime Time, double Longitude, double Latitude, Octree _Octree, float d, int LatitudeNum, int LongtitudeNum) { double _DayAngle = DayAngle(Time.Year, Time.Month, Time.Day, 12, 0, Longitude); //一天的平均日角 double _RiseTime = RiseTime(_DayAngle, Longitude, Latitude); //日出时间 double _FallTime = FallTime(_DayAngle, Longitude, Latitude); //日落时间 double biomass = 0.0; for (double StartHour = _RiseTime; StartHour < _FallTime; StartHour = StartHour + 1) //以一个小时为步长计算辐射量 { DataInitialization(treeModel); //初始化数据,防止出错 double EndHour = StartHour + 1; if (EndHour > _FallTime) { EndHour = _FallTime; //当结束的时间超过日落时间时,则将日落时间作为结束时间 } double MidHour = (StartHour + EndHour) / 2; //中间时间点 int MidHour_Int = HourToHour(MidHour); //中间时间点(小时) int MidMin_Int = HourToMin(MidHour); //中间时间点(分钟) double SolarDayAngle_Rad = DayAngle(Time.Year, Time.Month, Time.Day, MidHour_Int, MidMin_Int, Longitude); //这段时间内的平均日角 double SolarHourAngle = HourAngle(MidHour_Int, MidMin_Int, Longitude, SolarDayAngle_Rad); //这段时间内的平均时角 double SolarDelication = Declination(SolarDayAngle_Rad); //这段时间内的平均赤纬角 double SolarAltitude_Deg = SolarAltitude(SolarDelication, SolarHourAngle, Latitude); //这段时间内的平均太阳高度角 double SolarAzimuth_Deg = SolarAzimuth(SolarDelication, SolarAltitude_Deg, Latitude, SolarHourAngle); //这段时间内的平均太阳方位角 DirectionLightSimulation(SolarDayAngle_Rad, SolarAltitude_Deg, SolarAzimuth_Deg, StartHour, EndHour, _Octree, d); //模拟这段时间内的直射光照 //ScatterLightSimulation(SolarDayAngle_Rad, SolarAltitude_Deg, StartHour, EndHour, _Octree, LatitudeNum, LongtitudeNum); //模拟这段时间内的散射光照 biomass += FunctionSim.CumulativeBiomass(treeModel, (int)((EndHour - StartHour) * 60 * 60), treeModel.EnvironmentParams.NutrientType); //计算这段时间累积的生物量 } //测试 biomass *= 4.75078125; return(biomass / 1000000.0); }
public static double SunShineSim(TreeModel treeModel, PhotosyntheticModels type) { double biomass = 0.0; switch (type) { case PhotosyntheticModels.LightResponse: Octree octree = Octree.Build(treeModel); biomass = octree == null? //无模型,说明未出苗 MaizeParams.SEED_BIOMASS : DailySunShineSimluation(treeModel, DateTime.Now, 119, 26, octree, 0.1f, 100, 100); if (octree != null) { octree.Clear(); } break; default: GameObject go = treeModel.TreeModelInstance; if (go != null) { Mesh.AddBoxColliderInParent(go); } biomass = treeModel.GetLeafIndexes().Count != 0 ? //无叶片,说明未出苗 BeerRule.BiomassCal(treeModel) / FunctionSim.ComputeDaysInGC(treeModel) : MaizeParams.SEED_BIOMASS; break; } if (biomass != MaizeParams.SEED_BIOMASS) { biomass *= EnvironmentEffect.TemperatureStressFactor(treeModel) * EnvironmentEffect.WaterStressFactor(treeModel) * EnvironmentEffect.SunshineStress(treeModel); } return(biomass); }
/// <summary> /// 计算一段时间内的光合速率(umol·m^-2·s^-1) /// </summary> /// <param name="type">环境因素(正常 or 缺氮 or 缺磷 or 缺钾)</param> public static double PhotosyntheticRate(TreeModel treeModel, LightResponseType type = LightResponseType.NORMAL) { double PAR = FunctionSim.PARRecption_Mean(treeModel); return(PhotosyntheticRate(PAR, type)); }
public void MorphologicalSim(double biomass, bool isClear = true, bool isSameGC = false) { DataCheck(); //数据检查 /* * 包含枝干和器官的索引 * 其每一个索引包含了后续生成GameObject所需的形态信息(旋转角度)以及 * 生成形态信息所需的数据(生物量、年龄) */ List <OrganIndex> indexes = GetIndexes(isClear, isSameGC); /* * 分配生物量给各个器官 * 累积的生物量为后续形态模拟提供参考依据 */ FunctionSim.PhotosynthateAllocation(this, biomass, FunctionSim.GrowthPeriodJudgment(BranchIndexes, OrganIndexes)); /* * 遍历每个Index * 计算形态数据 * 根据形态数据绘制GameObject */ int curLevel = 0; Vector3 curPosition = Vector3.zero; Stack <Vector3> positionStack = new Stack <Vector3>(); foreach (OrganIndex index in indexes) { switch (index.Type) { case OrganType.Branch: BranchIndex branchIndex = index as BranchIndex; if (branchIndex.Level > curLevel) { positionStack.Push(curPosition); } else if (branchIndex.Level < curLevel) { curPosition = positionStack.Pop(); } curLevel = branchIndex.Level; curPosition = RecordBranchModel(branchIndex, curPosition); break; case OrganType.Leaf: LeafIndex leafIndex = index as LeafIndex; CreateLeafModel(leafIndex, curPosition); break; case OrganType.Flower: MaleIndex maleIndex = index as MaleIndex; CreateFlowerModel(maleIndex, curPosition); break; case OrganType.Fruit: FemaleIndex femaleIndex = index as FemaleIndex; CreateFruitModel(femaleIndex, curPosition); break; } } CreateBranchModel(); /* * 病虫害模拟 * 测试 */ InsectSimulation(); PostProcessing(); }