/// <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; } }
static void Main(string[] args) { 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 = false; SoilProps sp1, sp2; FluxTable ft1, ft2; //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++) { BinaryWriter b = new BinaryWriter(File.OpenWrite("soil" + soils[i].sid + ".dat")); 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); soils[i].sp = Soil.gensptbl(dzmin, soils[i], Kgiven); b.Write(soils[i].sid); WriteProps(b, soils[i].sp); b.Close(); for (j = 0; j < ndz[i]; j++) { Fluxes.FluxTable(dz[i, j], soils[i].sp); b = new BinaryWriter(File.OpenWrite("soil" + soils[i].sid + "dz" + dz[i, j] * 10)); b.Write(soils[i].sid); WriteFluxes(b, Fluxes.ft); b.Close(); } } //generate and write composite flux table for path with two soil types sp1 = ReadProps("soil103.dat"); sp2 = ReadProps("soil109.dat"); ft1 = ReadFluxes("soil103dz50.dat"); ft2 = ReadFluxes("soil103dz100.dat"); FluxTable ftwo = TwoFluxes.TwoTables(ft1, sp1, ft2, sp2); BinaryWriter bw = new BinaryWriter(File.OpenWrite("soil0103dz0050_soil0109dz0100.dat")); WriteFluxes(bw, ftwo); }
public static FluxTable TwoTables(FluxTable ft1, SoilProps sp1, FluxTable ft2, SoilProps sp2) { /*Generates a composite flux table from two uniform ones. * Sets up quadratic interpolation table to get phi at interface for lower path * from phi at interface for upper path. * Sets up cubic interpolation tables to get fluxes from phi at interface for * upper and lower paths. * Solves for phi at interface in upper path that gives same fluxes in upper * and lower paths, for all phi at upper and lower ends of composite path. * Increases no. of fluxes in table by quadratic interpolation. * ft1, ft2 - flux tables for upper and lower paths. * sp1, sp2 - soil prop tables for upper and lower paths. -PR * * Note that arrays are one indexed; 0 index is not used. * This is done as a number of calculations use the index as an input. * Exception to this is flux/soil arrays where array index is not used in calculations. -JF */ // Set up required pointers and data if (ft1.fend[0].sid != ft1.fend[1].sid || ft2.fend[0].sid != ft2.fend[1].sid) { Console.WriteLine("Flux table not for uniform soil."); Environment.Exit(1); } ft1.ftable = Matrix <double> .Build.DenseOfArray(ft1.ftable).Transpose().ToArray(); ft2.ftable = Matrix <double> .Build.DenseOfArray(ft2.ftable).Transpose().ToArray(); ft[0] = ft1; ft[1] = ft2; sp[0] = sp1; sp[1] = sp2; for (i = 1; i <= 2; i++) { n[i] = sp[i - 1].n; he[i] = sp[i - 1].he; phie[i] = sp[i - 1].phie; Ks[i] = sp[i - 1].ks; for (int x = 1; x <= n[i]; x++) { h[x, i] = sp[i - 1].h[x]; phi[x, i] = sp[i - 1].phi[x]; } } // Discard unwanted input - use original uninterpolated values only. for (i = 1; i <= 2; i++) { m = ft[i - 1].fend[0].nft; //should be odd j = 1 + m / 2; double[] tempPhif = new double[j + 1]; Array.Copy(ft[i - 1].fend[0].phif.Where((x, it) => it % 2 == 1).ToArray(), 0, tempPhif, 1, j); for (int x = 1; x <= j; x++) { phif[x, i] = tempPhif[x]; //discard every second } nft[i] = j; nfu[i] = 1 + ft[i - 1].fend[1].nfu / 2; //ft[i].fend[1].nfu should be odd double[,] tempFt = new double[m + 1, m + 1]; for (int a = 1; a <= m; a += 2) { for (int b = 1; b <= m; b += 2) { tempFt[a / 2 + 1, b / 2 + 1] = ft[i - 1].ftable[a, b]; } } for (int a = 1; a <= m; a++) { for (int b = 1; b <= m; b++) { qf[b, a, i] = tempFt[a, b]; } } } // Extend phi2 and h2 if he1>he2, or vice-versa. dhe = Math.Abs(he[1] - he[2]); if (dhe > 0.001) { if (he[1] > he[2]) { i = 1; j = 2; } else { i = 2; j = 1; } double[] hFind = new double[n[i] + 1]; for (int x = 1; x <= n[i] + 1; x++) { hFind[x - n[i] + 1] = h[i, x]; } ii = Find(he[j], hFind); for (k = 1; k <= n[i] - ii; k++) { h[j, n[j] + k] = h[i, ii + k];//test these phi[j, n[j] + k] = phie[j] + Ks[j] * (h[i, ii + k] - he[j]); } n[j] = n[j] + n[i] - ii; } phi1max = phi[n[1], 1]; // Get phi for same h. if (h[1, 1] > h[1, 2]) { i = 1; j = 2; } else { i = 2; j = 1; } Matrix <double> hm = Matrix <double> .Build.DenseOfArray(h); //test double[] absh = hm.Column(j).ToArray(); absh = absh.Slice(1, n[j]); absh = MathUtilities.Subtract_Value(absh, h[1, i]); for (int x = 0; x < absh.Length; x++) { absh[x] = Math.Abs(absh[x]); } id = MinLoc(absh); if (h[id, j] >= h[1, 1]) { id--; } //phii(j,:) for soil j will match h(i,:) from soil i and h(j, 1:id) from soil j. //phii(i,:) for soil i will match h(i,:) and fill in for h(j, 1:id). for (int iid = 1; iid <= id; iid++) { phii[iid, j] = phi[iid, j]; // keep these values } // But interpolate to match values that start at greater h. jj = id + 1; //h(j,id+1) to be checked first phii[id + n[i], j] = phi[n[j], j]; // last h values match for (ii = 1; ii <= n[i] - 1; ii++) { while (true) //get place of h(i,ii) in h array for soil j { if (jj > n[j]) { Console.WriteLine("twotbls: h[j,n[j]] <= h[i,ii]; i, j, ii, n[j] = " + i + " " + j + " " + ii + " " + n[j]); Environment.Exit(1); } if (h[jj, j] > h[ii, i]) { break; } jj += 1; } k = jj - 1; //first point for cubic interp if (jj + 2 > n[j]) { k = n[j] - 3; } double[] hCuco = new double[5]; double[] phiCuco = new double[5]; for (int x = k; x <= k + 3; x++) { hCuco[x - k + 1] = h[x, j]; phiCuco[x - k + 1] = phi[x, j]; } co = Soil.Cuco(hCuco, phiCuco); // get cubic coeffs v = h[ii, i] - h[k, j]; phii[id + ii, j] = co[1] + v * (co[2] + v * (co[3] + v * co[4])); } ni = id + n[i]; // Generate sensible missing values using quadratic extrapolation. co = Fluxes.Quadco(new double[4] { 0, phii[1, j], phii[id + 1, j], phii[id + 2, j] }, new double[4] { 0, 0, phi[1, i], phi[2, i] }); if (co[2] > 0) // +ve slope at zero - ok { for (int x = 1; x <= id; x++) { xval[x] = phii[x, j] - phii[1, j]; phii[x, i] = co[i] + xval[x] * (co[2] + xval[x] * co[3]); } } else // -ve slope at zero, use quadratic with zero slope at zero { co[3] = phi[1, i] / Math.Pow(phii[id + 1, j], 2); for (int x = 1; x <= id; x++) { phii[x, i] = co[3] * Math.Pow(phii[x, j], 2); } } // phii(i,id+1:ni)=phi(i,1:n(i)) double[] phin = new double[ni - id + 1]; for (int x = 1; x <= n[i]; x++) { phin[x] = phi[x, i]; } for (int x = id + 1; x <= ni; x++) { phii[x, i] = phin[x - (id + 1) + 1]; } //hi(1:id) = h(j, 1:id) for (int x = 1; x <= id; x++) { hi[x] = h[x, j]; } // hi(id+1:ni)=h(i,1:n(i)) for (int x = 1; x <= n[i]; x++) { hi[id + x] = h[x, i]; } /* hi(1:ni) are h values for the interface tables. * phii(1,1:ni) are corresponding interface phi values for upper layer. * phii(2,1:ni) are corresponding interface phi values for lower layer. * Set up quadratic interpolation coeffs to get phii2 given phii1. */ Matrix <double> coqM = Matrix <double> .Build.DenseOfArray(coq); Vector <double>[] quadcoV = new Vector <double> [ni - 2 + 1]; double[] tmpx; double[] tmpy; for (i = 1; i <= ni - 2; i++) { tmpx = new [] { 0, phii[i, 1], phii[i + 1, 1], phii[i + 2, 1] }; tmpy = new [] { 0, phii[i, 2], phii[i + 1, 2], phii[i + 2, 2] }; quadcoV[i] = Vector <double> .Build.DenseOfArray(Fluxes.Quadco(tmpx, tmpy)); coqM.SetRow(i, quadcoV[i]); } Vector <double> lincoV = Vector <double> .Build.DenseOfArray(Linco(new [] { 0, phii[ni - 1, 1], phii[ni, 1] }, new [] { 0, phii[ni - 1, 2], phii[ni, 2] })); coqM.SetRow(ni - 1, lincoV); coq = coqM.ToArray(); coq[ni - 1, 3] = 0; double[,] getco = new double[20, 20]; // Set up cubic coeffs to get fluxes q given phi. for (j = 1; j <= nft[2]; j++) { k = 1; ip = 1; while (true) { phico2[k] = phif[ip, 2]; double[] co2co = Soil.Cuco(new double[5] { 0, phif[ip, 2], phif[ip + 1, 2], phif[ip + 2, 2], phif[ip + 3, 2] }, new double[5] { 0, qf[j, ip, 2], qf[j, ip + 1, 2], qf[j, ip + 2, 2], qf[j, ip + 3, 2] }); for (int x = 1; x < co2co.Length; x++) { co2[j, k, x] = co2co[x]; } ip += 3; if (ip == nft[2]) { break; } if (ip > nft[2]) { ip = nft[2] - 3; } k++; } for (int x = 1; x < 20; x++) { for (int y = 1; y < 20; y++) { getco[y, x] = co2[y, x, 1]; } } } nco2 = k; // Get fluxes for (i = 1; i <= nft[1]; i++) //step through top phis { vlast = phif[i, 1]; k = 1; ip = 1; Matrix <double> co1M = Matrix <double> .Build.DenseOfArray(co1); while (true) { phico1[k] = phif[ip, 1]; co1M.SetRow(k, Soil.Cuco(new double[5] { 0, phif[ip, 1], phif[ip + 1, 1], phif[ip + 2, 1], phif[ip + 3, 1] }, new double[5] { 0, qf[ip, i, 1], qf[ip + 1, i, 1], qf[ip + 2, i, 1], qf[ip + 3, i, 1] })); ip += 3; if (ip == nft[1]) { break; } if (ip > nft[1]) { ip = nft[1] - 3; } k++; } co1 = co1M.ToArray(); nco1 = k; for (j = 1; j <= nft[2]; j++) // bottom phis { v = vlast; for (k = 1; k <= maxit; k++) // solve for upper interface phi giving same fluxes { fd(v, out f, out df, out q1); dx = f / df; // Newton's method - almost always works v = Math.Min(10.0 * phif[nft[1], 1], Math.Max(phii[1, 1], v - dx)); e = Math.Abs(f / q1); if (e < rerr) { break; } vlast = v; } if (k > maxit) //failed - bracket q and use bisection { v1 = phii[1, 1]; fd(v1, out f1, out df, out q1); if (f1 <= 0.0) // answer is off table - use end value { qp[j, i] = q1; continue; } v2 = phii[ni, 1]; fd(v2, out f2, out df, out q1); for (k = 1; k <= maxit; k++) { if (f1 * f2 < 0.0) { break; } v1 = v2; f1 = f2; v2 = 2.0 * v1; fd(v2, out f2, out df, out q1); } if (k > maxit) { Console.WriteLine(v1 + " " + v2 + " " + f1 + " " + f2); v1 = phii[1, 1]; fd(v1, out f1, out df, out q1); Console.WriteLine(v1 + " " + f1); Console.WriteLine("twotbls: too many iterations at i, j = " + i + " " + j); Environment.Exit(1); } for (k = 1; k <= maxit; k++) { v = 0.5 * (v1 + v2); fd(v, out f, out df, out q1); e = Math.Abs(f / q1); if (e < rerr) { break; } if (f > 0.0) { v1 = v; f1 = f; } else { v2 = v; f2 = f; } } vlast = v; if (k > maxit) { Console.WriteLine("twotbls: too many iterations at i, j = " + i + " " + j); Environment.Exit(1); } } // Solved qp[j, i] = q1; } //end j } //end i //interpolate extra fluxes for (i = 1; i <= 2; i++) { nfi[i] = nft[i] - 1; for (int x = 1; x <= nfi[i]; x++) { phifi[x, i] = 0.5 * (phif[x, i] + phif[x + 1, i]); } } Matrix <double> phifM = Matrix <double> .Build.DenseOfArray(phif); Matrix <double> phifiM = Matrix <double> .Build.DenseOfArray(phifi); Matrix <double> qpM = Matrix <double> .Build.DenseOfArray(qp); Matrix <double> qi1M = Matrix <double> .Build.DenseOfArray(qi1); Matrix <double> qi2M = Matrix <double> .Build.DenseOfArray(qi2); Matrix <double> qi3M = Matrix <double> .Build.DenseOfArray(qi3); for (i = 1; i <= nft[1]; i++) { qi1M.SetColumn(i, Fluxes.Quadinterp(phifM.Column(2).ToArray(), qpM.Column(i).ToArray(), nft[2], phifiM.Column(2).ToArray())); } for (j = 1; j <= nft[2]; j++) { qi2M.SetRow(j, Fluxes.Quadinterp(phifM.Column(1).ToArray(), qpM.Row(j).ToArray(), nft[1], phifiM.Column(1).ToArray())); } for (j = 1; j <= nfi[2]; j++) { qi3M.SetRow(j, Fluxes.Quadinterp(phifM.Column(1).ToArray(), qi1M.Row(j).ToArray(), nft[1], phifiM.Column(1).ToArray())); } qi1 = qi1M.ToArray(); qi2 = qi2M.ToArray(); qi3 = qi3M.ToArray(); // Put all the fluxes together i = nft[1] + nfi[1]; j = nft[2] + nfi[2]; // qi5(1:i:2,1:j:2)=qp(1:nft[1],1:nft[2]) for (int a = 1; a <= mx; a += 2) { for (int b = 1; b <= mx; b += 2) { qi5[b, a] = qp[b / 2 + 1, a / 2 + 1]; } } // qi5(1:a: 2, 2:b: 2) = qi1(1:nft[1], 1:nfi[2]) for (int a = 1; a <= mx; a += 2) { for (int b = 2; b <= mx; b += 2) { qi5[b, a] = qi1[(b - 1) / 2 + 1, a / 2 + 1]; } } // qi5(2:a:2,1:b:2)=qi2(1:nfi[1],1:nft[2]) for (int a = 2; a <= mx; a += 2) { for (int b = 1; b <= mx; b += 2) { qi5[b, a] = qi2[b / 2 + 1, (a - 1) / 2 + 1]; } } // qi5(2:a:2,2:b:2)=qi3(1:nfi[1],1:nfi[2]) for (int a = 2; a <= mx; a += 2) { for (int b = 2; b <= mx; b += 2) { qi5[b, a] = qi3[(b - 1) / 2 + 1, (a - 1) / 2 + 1]; } } // phii5(1, 1:a: 2) = phif(1, 1:nft[1]) for (int a = 1; a <= mx; a += 2) { phii5[a, 1] = phif[a / 2 + 1, 1]; } // phii5(1,2:a:2)=phifi(1,1:nfi[1]) for (int a = 2; a < 101; a += 2) { phii5[a, 1] = phifi[(a - 1) / 2 + 1, 1]; } // phii5(2,1:b:2)=phif(2,1:nft[2]) for (int a = 1; a <= mx; a += 2) { phii5[a, 2] = phif[a / 2 + 1, 2]; } // phii5(2,2:b:2)=phifi(2,1:nfi[2]) for (int a = 2; a <= mx; a += 2) { phii5[a, 2] = phifi[(a - 1) / 2 + 1, 2]; } // Assemble flux table ftwo.fend = new FluxEnd[2]; for (ie = 0; ie < 2; ie++) { ftwo.fend[ie].sid = sp[ie].sid; ftwo.fend[ie].nfu = ft[ie].fend[1].nfu; ftwo.fend[ie].nft = ft[ie].fend[1].nft; ftwo.fend[ie].dz = ft[ie].fend[1].dz; ftwo.fend[ie].phif = ft[ie].fend[1].phif; } double[,] qi5Slice = new double[i + 1, j + 1]; for (int x = 1; x <= i; x++) { for (int y = 1; y <= j; y++) { qi5Slice[x, y] = qi5[x, y]; } } ftwo.ftable = qi5Slice; return(ftwo); }
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); }