/// <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; } }
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); }