Пример #1
0
        /// <summary>
        /// Size structures for iValue number of plants
        /// </summary>
        /// <param name="iValue"></param>
        protected override void setNoPlants(int iValue)
        {
            base.setNoPlants(iValue);

            Array.Resize(ref FParams, iValue);
            ExtMath.ResizeArray(FWaterSupply, iValue, GrazType.MaxSoilLayers);
        }
Пример #2
0
        /// <summary>
        /// Size structures for iValue number of plants
        /// </summary>
        /// <param name="iValue"></param>
        protected virtual void setNoPlants(int iValue)
        {
            FNoPlants = iValue;

            Array.Resize(ref FPlantInfo, FNoPlants);
            ExtMath.ResizeArray(FWaterUptake, FNoPlants, GrazType.MaxSoilLayers);
            ExtMath.ResizeArray(FSoilFract, FNoPlants, GrazType.MaxSoilLayers);
        }
Пример #3
0
        public static void ParseUpdate(BitStream stream, StringTable table, ushort entries)
        {
            Debug.Assert(stream.Cursor == 0);

            IList <StringTableEntry> history = new List <StringTableEntry>();

            byte entryBits = (byte)ExtMath.Log2(table.MaxEntries);
            int  lastEntry = -1;

            for (int i = 0; i < entries; i++)
            {
                // Did we read the entry from the BitStream or just assume it was lastEntry + 1?
                //bool readEntry = false;

                int entryIndex = lastEntry + 1;

                if (!stream.ReadBool())
                {
                    entryIndex = (int)stream.ReadUInt(entryBits);
                    //readEntry = true;
                }

                lastEntry = entryIndex;

                if (entryIndex < 0 || entryIndex > table.MaxEntries)
                {
                    throw new FormatException("Server sent bogus string index for stringtable");
                }

                string value = null;
                if (stream.ReadBool())
                {
                    bool substringcheck = stream.ReadBool();

                    if (substringcheck)
                    {
                        int index       = (int)stream.ReadUInt(5);
                        int bytesToCopy = (int)stream.ReadUInt(SUBSTRING_BITS);

                        string restOfString = stream.ReadCString();

                        var testLength = history[index].Value?.Length;

                        value = history[index].Value?.Substring(0, bytesToCopy) + restOfString;
                    }
                    else
                    {
                        value = stream.ReadCString();
                    }
                }

                BitStream userData = null;
                if (stream.ReadBool())
                {
                    if (table.UserDataSize.HasValue)
                    {
                        userData = stream.Subsection(stream.Cursor, stream.Cursor + table.UserDataSizeBits.Value);
                        stream.Seek(table.UserDataSizeBits.Value, System.IO.SeekOrigin.Current);
                    }
                    else
                    {
                        ulong nBytes = stream.ReadUInt(MAX_USERDATA_BITS);
                        userData = stream.Subsection(stream.Cursor, stream.Cursor + (nBytes * 8));
                        stream.Seek(nBytes * 8, System.IO.SeekOrigin.Current);
                    }
                }

                StringTableEntry existingEntry = table.Entries.SingleOrDefault(s => s.ID == entryIndex);
                if (existingEntry != null)
                {
                    existingEntry.UserData = userData;

                    if (value != null && value != existingEntry.Value)
                    {
                        //throw new FormatException("Corrupted demo?");
                        existingEntry.Value = value;
                    }
                    else
                    {
                        value = existingEntry.Value;
                    }

                    existingEntry.Value = value;
                }
                else
                {
                    //Debug.Assert(entryIndex == table.Entries.Count);
                    if (value == null)
                    {
                        Debug.Assert(true);
                    }
                    //Debug.Assert(value != null);

                    //if (value == null)
                    //	value = string.Empty;

                    StringTableEntry newEntry = new StringTableEntry(table);
                    newEntry.ID       = (ushort)entryIndex;
                    newEntry.UserData = userData;
                    newEntry.Value    = value;
                    table.Add(newEntry);

                    existingEntry = newEntry;
                }

                if (history.Count > 31)
                {
                    history.RemoveAt(0);
                }

                history.Add(existingEntry);
            }

            Debug.Assert((stream.Length - stream.Cursor) < 8);
        }
Пример #4
0
        /// <summary>
        /// -
        /// </summary>
        /// <param name="Ldx">-</param>
        /// <param name="fTheta">-</param>
        /// <param name="fPotentialET">-</param>
        public void computeWaterSupply(int Ldx, double fTheta, double fPotentialET)
        {
            //const double BOUND_APPROACH = 0.95;
            double Psi_s;

            Boolean bWetEnough;

            double[,] Alpha;
            double[] Beta;
            double[] Deltas;
            int      iLayerPlants;

            int[] iPlantMap = new int[99];

            double N;
            double d2PiOnRhoG;
            double dK_Psi_Soil;
            double dK_Surface;

            double[] SurfacePsi = new double[99];
            double[] dPrev_Psi  = new double[99];
            double   dMaxError;

            //double dPrev_Error;

            double[] Qr             = new double[99];
            double[] dQr_dPsi       = new double[99];
            double[] Qs             = new double[99];
            double[] dExtractRadius = new double[99];

            int     iIterations;
            double  dQ2Radius;
            double  dLnTerm;
            Boolean bDone;

            double[] dDeltaScale = new double[99];
            //Boolean bFirstTime;
            Boolean bRadiusOK;
            int     Idx, Kdx, Ndx;


            Psi_s = Psi(fTheta, Ldx);                                                 // Water potential in this soil layer
            // units of kPa, negative
            iLayerPlants = 0;
            for (Idx = 0; Idx <= FNoPlants - 1; Idx++)
            {
                if (fPotentialET > 0.0)
                {
                    bWetEnough = (Psi_s > FPlantInfo[Idx].UptakeK[3] / fPotentialET);
                }
                else
                {
                    bWetEnough = true;
                }

                if (bWetEnough && (FPlantInfo[Idx].RootLengthD[Ldx] > 0.0))
                {
                    iPlantMap[iLayerPlants] = Idx;
                    iLayerPlants++;
                }
            }

            if (iLayerPlants > 0)                                                    // Only run the water uptake model if
            {                                                                        //   uptake will be non-negative
                N           = FCond_N[Ldx];
                d2PiOnRhoG  = (2.0 * Math.PI) / (GRAVITY * DENSITY);
                dK_Psi_Soil = Conductivity(Psi_s, Ldx) * Psi_s;

                for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)
                {
                    Idx = iPlantMap[Kdx];
                    FParams[Kdx].Q_max = FPlantInfo[Idx].UptakeK[0]                               // Convert max. uptake/root area to max.
                                         * 2.0 * Math.PI * FPlantInfo[Idx].RootRadius[Ldx];       //   uptake/root length
                    FParams[Kdx].Psi_max    = FPlantInfo[Idx].UptakeK[1];
                    FParams[Kdx].Curvature  = FPlantInfo[Idx].UptakeK[2];
                    FParams[Kdx].Psi_zero   = FPlantInfo[Idx].UptakeK[3] / Math.Max(fPotentialET, 0.00001);
                    FParams[Kdx].PiRLD      = Math.PI * FPlantInfo[Idx].RootLengthD[Ldx];
                    FParams[Kdx].RootRadius = FPlantInfo[Idx].RootRadius[Ldx];
                }
                Alpha       = new double[iLayerPlants, iLayerPlants];
                Beta        = new double[iLayerPlants];
                Deltas      = new double[iLayerPlants];
                iIterations = 0;

                for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)                                           // Initial guesses for SurfacePsi
                {
                    SurfacePsi[Kdx] = Psi_s;
                }
                // Multi-dimensional Newton-Raphson
                do                                                                     //  procedure, with modifications
                {
                    dQ2Radius = 0.0;                                                   // Use Q2Radius to compute the current
                    for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)                      //    r(s) values
                    {
                        ComputeQr(Kdx, SurfacePsi[Kdx], ref Qr[Kdx], ref dQr_dPsi[Kdx]);
                        dQ2Radius = dQ2Radius + FParams[Kdx].PiRLD * Math.Pow(Qr[Kdx], 2);
                    }
                    dQ2Radius = Math.Sqrt(dQ2Radius);

                    for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)                          // We need all the r(s) values before
                    {
                        if (Qr[Kdx] > 0.0)                                                 //   computing any element of Alpha
                        {
                            dExtractRadius[Kdx] = Qr[Kdx] / dQ2Radius;
                        }
                        else
                        {
                            dExtractRadius[Kdx] = FParams[Kdx].RootRadius;
                        }
                    }

                    for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)
                    {
                        dK_Surface = Conductivity(SurfacePsi[Kdx], Ldx);
                        dLnTerm    = Math.Log(dExtractRadius[Kdx] / FParams[Kdx].RootRadius);
                        Qs[Kdx]    = d2PiOnRhoG / (N - 1.0) * (dK_Surface * SurfacePsi[Kdx] - dK_Psi_Soil) / dLnTerm;

                        for (Ndx = 0; Ndx <= iLayerPlants - 1; Ndx++)
                        {
                            Alpha[Kdx, Ndx] = FParams[Kdx].PiRLD * dExtractRadius[Kdx] * dExtractRadius[Ndx] * dQr_dPsi[Ndx];
                            if (Kdx == Ndx)
                            {
                                Alpha[Kdx, Ndx] = Alpha[Kdx, Ndx] - d2PiOnRhoG * dK_Surface - (dLnTerm + 1.0) * dQr_dPsi[Kdx];
                            }
                        }
                        Beta[Kdx] = (Qr[Kdx] - Qs[Kdx]) * dLnTerm;
                    }

                    dMaxError = 0.0;
                    for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)
                    {
                        dMaxError = Math.Max(dMaxError, Math.Abs(Qr[Kdx] - Qs[Kdx]) / FParams[Kdx].Q_max);
                    }
                    bDone = (dMaxError <= 1.0E-6);

                    if (!bDone)
                    {
                        for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)
                        {
                            dPrev_Psi[Kdx] = SurfacePsi[Kdx];
                        }

                        ExtMath.SolveLinear(Alpha, ref Deltas, Beta);                                    // Here is the Newton-Raphson step that
                        //   computes the deltas
                        for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)
                        {
                            dDeltaScale[Kdx] = 1.0;                                        // Enforce approach from above, i.e.
                        }
                        do                                                                 //   keep the SurfacePsi values between
                        {
                            for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)                  //   Psi_s and the solution
                            {
                                SurfacePsi[Kdx] = dPrev_Psi[Kdx] + dDeltaScale[Kdx] * Deltas[Kdx];
                            }

                            dQ2Radius = 0.0;
                            for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)
                            {
                                ComputeQr(Kdx, SurfacePsi[Kdx], ref Qr[Kdx], ref dQr_dPsi[Kdx]);
                                dQ2Radius = dQ2Radius + FParams[Kdx].PiRLD * Math.Pow(Qr[Kdx], 2);
                            }
                            dQ2Radius = Math.Sqrt(dQ2Radius);

                            bRadiusOK = true;
                            for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)
                            {
                                if (dQ2Radius > 0.0)
                                {
                                    dExtractRadius[Kdx] = Qr[Kdx] / dQ2Radius;
                                }
                                else
                                {
                                    dExtractRadius[Kdx] = 0.0;
                                }

                                if (dExtractRadius[Kdx] < FParams[Kdx].RootRadius)
                                {
                                    bRadiusOK        = false;
                                    dDeltaScale[Kdx] = 0.5 * dDeltaScale[Kdx];
                                }
                                else
                                {
                                    dK_Surface = Conductivity(SurfacePsi[Kdx], Ldx);
                                    dLnTerm    = Math.Log(dExtractRadius[Kdx] / FParams[Kdx].RootRadius);
                                    Qs[Kdx]    = d2PiOnRhoG / (N - 1.0) * (dK_Surface * SurfacePsi[Kdx] - dK_Psi_Soil) / dLnTerm;
                                    if ((Qr[Kdx] - Qs[Kdx]) / FParams[Kdx].Q_max < -1.0E-6)
                                    {
                                        bRadiusOK        = false;
                                        dDeltaScale[Kdx] = 0.5 * dDeltaScale[Kdx];
                                    }
                                }

                                if (dDeltaScale[Kdx] < 1.0E-8)
                                {
                                    throw new Exception("Numerical failure in water uptake model");
                                }
                            }
                        }while (!bRadiusOK);
                    } //_ if not bDone

                    iIterations++;
                    if (iIterations > 10000)
                    {
                        throw new Exception("Numerical failure in water uptake model");
                    }
                }while (!bDone);

                //commented code removed

                for (Kdx = 0; Kdx <= iLayerPlants - 1; Kdx++)                          // Compute the final water supply rate
                {                                                                      //   from this layer for each species
                    Idx = iPlantMap[Kdx];
                    FWaterSupply[Idx, Ldx] = Qr[Kdx]
                                             * FPlantInfo[Idx].RootLengthD[Ldx]
                                             * FLayerDepth_M[Ldx];
                    FSoilFract[Idx, Ldx] = Math.PI * FPlantInfo[Idx].RootLengthD[Ldx] * Math.Pow(dExtractRadius[Kdx], 2);
                }
            } //_ if iLayerPlants > 0
        }