public static double TemperatureStressFactor(TreeModel treeModel)
    {
        EnvironmentParams envirParams = treeModel.EnvironmentParams;

        return(TemperatureStressFactor(FunctionSim.GrowthPeriodJudgment(treeModel),
                                       envirParams.DailyMaxTemperature, envirParams.DailyMinTemperature));
    }
Example #2
0
    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);
    }
Example #7
0
    /// <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));
    }
Example #8
0
    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();
    }