Example #1
0
        /// <summary>
        /// Reads tables and sets up data
        /// </summary>
        /// <param name="nin">Number of layers.</param>
        /// <param name="sid">Soil ID of layers.</param>
        /// <param name="xin">Depth to bottoms of layers.</param>
        public void GetTables(int nin, int[] sid, double[] xin)
        {
            double small = 1E-5;
            string id, mm, sfile;

            string[] ftname = new string[2 + 1];
            int      i, j, ns, np, nc, i1;

            int[] isoil = new int[nin + 1];
            int[,] isid = new int[2 + 1, nin + 1 + 1];
            int[] jt = new int[nin + 2];            //0-based FORTRAN array. +2 as first and last elements will be copied twice
            double[,] dz = new double[2 + 1, nin + 1 + 1];
            double[] hdx = new double[nin + 1 + 1]; //0-based FORTRAN array
            double   x1;

            n       = nin;
            x       = xin;
            soilloc = new int[n + 1];
            pathloc = new int[n + 1];        //0 based in FORTRAN
            philoc  = new int[2 + 1, n + 1]; //0 based in FORTRAN
            dx      = MathUtilities.Subtract(x.Slice(2, n), x.Slice(1, n - 1));

            //  Set up locations in soil, path, S and phi arrays.
            philoc.Populate2D(1);

            // Get ns different soil idents in array isoil.
            isoil = sid.Skip(1).Distinct().ToArray();
            ns    = isoil.Length;
            for (int count = 1; count < soilloc.Length; count++)
            {
                soilloc[count] = Array.IndexOf(isoil, sid[count]);
            }

            // Get soil idents in array isid and lengths in array dz for the np paths.
            dx = MathUtilities.Subtract(x, x.Skip(x.Length - 1).Concat(x.Take(x.Length - 1)).ToArray());
            Array.Copy(dx, 1, x, 1, dx.Length / 2);

            //hdx=(/0.0,0.5*dx,0.0/) ! half delta x
            for (int a = 0; a < hdx.Length; a++)
            {
                if (a == 0 || a == hdx.Length - 1)
                {
                    hdx[a] = 0;
                }
                else
                {
                    hdx[a] = dx[a] / 2;
                }
            }

            Array.Copy(sid, 1, jt, 1, sid.Length - 1);
            jt[0]             = sid[1];
            jt[jt.Length - 1] = sid[n];
            np = 0; //no.of different paths out of possible n + 1
            for (i = 0; i <= n; i++)
            {
                isid[1, np + 1] = jt[i];
                isid[2, np + 1] = jt[i + 1];
                if (jt[i] == jt[i + 1]) //no interface between types
                {
                    dz[1, np + 1] = hdx[i] + hdx[i + 1];
                    dz[2, np + 1] = 0;
                }
                else
                {
                    dz[1, np + 1] = hdx[i];
                    dz[2, np + 1] = hdx[i + 1];
                }

                //Increment np if this path is new.
                for (j = 1; j <= np; j++)
                {
                    if (isid[1, j] != isid[1, np + 1] || isid[2, j] != isid[2, np + 1])
                    {
                        continue;
                    }

                    double[] absdz = new double[dz.GetLength(0)];
                    for (int a = 0; a < absdz.Length; a++)
                    {
                        absdz[a] = Math.Abs(dz[a, j] - dz[a, np + 1]);
                    }

                    if (MathUtilities.Sum(absdz) < small)
                    {
                        break;
                    }
                }
                if (j > np)
                {
                    np++;
                }
                pathloc[i] = j; //store path location
            }

            // Read soil properties
            nsp = ns;
            sp  = new SoilProps[nsp + 1];
            for (i = 1; i <= ns; i++)
            {
                sp[i] = Soil.ReadProps("soil" + isoil[i - 1]);
            }

            //Set ths and he
            ths = new double[n + 1];
            he  = new double[n + 1];

            for (i = 1; i <= n; i++)
            {
                ths[i] = sp[soilloc[i] + 1].ths;
                he[i]  = sp[soilloc[i] + 1].he;
            }

            //Set up S and phi arrays to get phi from S.
            S      = new double[ns + 1, nphi + 1];
            rdS    = new double[ns + 1];
            phi    = new double[ns + 1, nphi + 1];
            dphidS = new double[ns + 1, nphi - 1 + 1];
            K      = new double[ns + 1, nphi + 1];
            dKdS   = new double[ns + 1, nphi - 1 + 1];
            for (i = 1; i <= ns; i++)
            {
                nc = sp[i].nc;

                //S(:,i)=sp(i)%Sc(1)+(/(j,j=0,nphi-1)/)*(sp(i)%Sc(nc)-sp(i)%Sc(1))/(nphi-1)
                for (int a = 0; a < nphi; a++)
                {
                    S[i, a + 1] = sp[i].Sc[1] + a * (sp[i].Sc[nc] - sp[i].Sc[1]) / (nphi - 1);
                }
                phi[i, 1]    = sp[i].phic[1];
                phi[i, nphi] = sp[i].phic[nc];
                j            = 1;
                for (i1 = 2; i1 <= nphi - 1; i1++)
                {
                    while (true)
                    {
                        if (S[i, i1] < sp[i].Sc[j + 1])
                        {
                            break;
                        }
                        j++;
                    }
                    x1         = S[i, i1] - sp[i].Sc[j];
                    phi[i, i1] = sp[i].phic[j] + x1 * (sp[i].phico[1, j] + x1 * (sp[i].phico[2, j] + x1 * sp[i].phico[3, j]));
                    x1         = phi[i, i1] - sp[i].phic[j];
                    K[i, i1]   = sp[i].Kc[j] + x1 * (sp[i].Kco[1, j] + x1 * (sp[i].Kco[2, j] + x1 * sp[i].Kco[3, j]));
                }

                rdS[i] = 1.0 / (S[i, 2] - S[i, 1]);

                for (int a = 2; a <= nphi; a++)
                {
                    dphidS[i, a - 1] = rdS[i] * (phi[i, a] - phi[i, a - 1]);
                    dKdS[i, a - 1]   = rdS[i] * (K[i, a] - K[i, a - 1]);
                }
            }

            // Read flux tables and form flux paths.
            ft    = new FluxTable[np + 1];
            fpath = new FluxPath[np + 1];
            nft   = np;
            for (i = 1; i <= np; i++)
            {
                for (j = 1; j <= 2; j++)
                {
                    id = isid[j, i].ToString();
                    mm = Math.Round(10.0 * dz[j, i]).ToString();
                    Console.WriteLine(id);
                    Console.WriteLine(mm);
                    ftname[j] = "soil" + id + "dz" + mm;
                }
                if (isid[1, i] == isid[2, i])
                {
                    sfile = ftname[1];
                }
                else
                {
                    sfile = ftname[1] + "_" + ftname[2];
                }
                ft[i] = Fluxes.ReadFluxTable(sfile);

                // Set up flux path data.
                j           = jsp(ft[i].fend[0].sid, ns, isoil);
                pe1.nfu     = ft[i].fend[0].nfu;
                pe1.nft     = ft[i].fend[0].nft;
                pe1.nld     = sp[j].nld;
                pe1.ths     = sp[j].ths;
                pe1.rdS     = rdS[j];
                pe1.Ks      = sp[j].ks;
                pe1.S       = Extensions.GetRowCol(S, j, false);
                pe1.phi     = Extensions.GetRowCol(phi, j, false);
                pe1.dphidS  = Extensions.GetRowCol(dphidS, j, false);
                pe1.K       = Extensions.GetRowCol(K, j, false);
                pe1.dKdS    = Extensions.GetRowCol(dKdS, j, false);
                pe1.Sd      = sp[j].Sd;
                pe1.lnh     = sp[j].lnh;
                pe1.phif    = ft[i].fend[0].phif;
                fpath[i].dz = ft[i].fend[0].dz;
                if (ft[i].fend[1].sid == ft[i].fend[0].sid)
                {
                    pe2 = pe1;
                }
                else //composite path
                {
                    j           = jsp(ft[i].fend[1].sid, ns, isoil);
                    pe2.nfu     = ft[i].fend[1].nfu;
                    pe2.nft     = ft[i].fend[1].nft;
                    pe2.nld     = sp[j].nld;
                    pe2.ths     = sp[j].ths;
                    pe2.rdS     = rdS[j];
                    pe2.Ks      = sp[j].ks;
                    pe2.S       = Extensions.GetRowCol(S, j, false);
                    pe2.phi     = Extensions.GetRowCol(phi, j, false);
                    pe2.dphidS  = Extensions.GetRowCol(dphidS, j, false);
                    pe2.K       = Extensions.GetRowCol(K, j, false);
                    pe2.dKdS    = Extensions.GetRowCol(dKdS, j, false);
                    pe2.Sd      = sp[j].Sd;
                    pe2.lnh     = sp[j].lnh;
                    pe2.phif    = ft[i].fend[1].phif;
                    fpath[i].dz = fpath[i].dz + ft[i].fend[1].dz;
                }
                fpath[i].pend    = new PathEnd[3];
                fpath[i].pend[1] = pe1;
                fpath[i].pend[2] = pe2;
                fpath[i].ftable  = ft[i].ftable;
            }
        }
Example #2
0
        public static void GenerateFlux()
        {
            MVG.TestParams(103, 9.0, 0.99670220130280185, 9.99999999999998460E-003);
            SoilProps sp = Soil.gensptbl(1.0, new SoilParam(10, 103, 0.4, 2.0, -2.0, -10.0, 1.0 / 3.0, 1.0), true);

            Fluxes.FluxTable(5.0, sp);
            FluxTable ft = Fluxes.ft;

            string output = string.Empty;

            //define test soils
            SoilParam[] soils = new SoilParam[2];
            soils[0] = new SoilParam(10, 103, 0.4, 2.0, -2.0, -10.0, 1.0 / 3.0, 1.0);
            soils[1] = new SoilParam(10, 109, 0.6, 0.2, -2.0, -40.0, 1.0 / 9.0, 1.0);

            string[] ftname = new string[2];
            int[]    sidx;
            int      i, j;

            int[]  ndz;
            double dzmin;

            double[] x;
            double[,] dz = new double[2, 10]; //only for testing? if not will need to change hardcoded dimensions.
            bool Kgiven = true;

            //define soil profile
            x     = new double[] { 10, 20, 30, 40, 60, 80, 100, 120, 160, 200 };    //length = num soil layers
            sidx  = new int[] { 103, 103, 103, 103, 109, 109, 109, 109, 109, 109 }; //soil ident of layers
            dzmin = 1.0;                                                            // smallest likely path length
            ndz   = new int[] { 2, 4 };                                             // for the two soil types - gives six flux tables
            //can be done in loops, but clearer this way and will only be used for testing
            dz[0, 0] = 5;
            dz[0, 1] = 10;
            dz[1, 0] = 10;
            dz[1, 1] = 20;
            dz[1, 2] = 30;
            dz[1, 4] = 40;
            for (i = 0; i < 2; i++)
            {
                MVG.Params(soils[i].sid, soils[i].ths, soils[i].ks, soils[i].he, soils[i].hd, soils[i].p, soils[i].hg, soils[i].em, soils[i].en); //set MVG params
                soils[i].sp = Soil.gensptbl(dzmin, soils[i], Kgiven);                                                                             // generate soil props
                Soil.SoilProperties.Add("soil" + soils[i].sid, soils[i].sp);
                for (j = 0; j <= ndz[i]; j++)
                {
                    Fluxes.FluxTable(dz[i, j], soils[i].sp);     // generate flux tables
                    using (MemoryStream ms = new MemoryStream()) // make copies of the tables or they get overwritten
                    {
                        BinaryFormatter fm = new BinaryFormatter();
                        fm.Serialize(ms, Fluxes.ft);
                        ms.Position = 0;
                        Fluxes.FluxTables.Add("soil" + soils[i].sid + "dz" + (dz[i, j] * 10), (FluxTable)fm.Deserialize(ms));
                    }
                }
            }
            SoilProps sp1  = Soil.ReadProps("soil103");
            SoilProps sp2  = Soil.ReadProps("soil109");
            FluxTable ft1  = Fluxes.ReadFluxTable("soil103dz50");
            FluxTable ft2  = Fluxes.ReadFluxTable("soil109dz100");
            FluxTable ftwo = TwoFluxes.TwoTables(ft1, sp1, ft2, sp2);

            Fluxes.FluxTables.Add("soil103dz50_soil109dz100", ftwo);
        }