/// <summary> /// Initializes the model by reading all files and building the leaching time series to and from each catchment /// </summary> /// <param name="Start"></param> /// <param name="End"></param> /// <param name="Catchments"></param> public override void Initialize(DateTime Start, DateTime End, IEnumerable<Catchment> Catchments) { base.Initialize(Start, End, Catchments); this.Start = Start; LoadSoilCodesGrid(SoilCodes.FileName); foreach (var item in UnsatAgeFiles) { item.Initialize(); } foreach (var parfile in DaisyFiles) { LoadDaisyData(parfile.FileName); } leachdata.BuildLeachData(Start, End, Catchments, RecycleStart, RecycleEnd, RecycleScale); ParticleReader pr = new ParticleReader(); pr.Catchments = Catchments; List<Particle> AllParticles = new List<Particle>(); IEnumerable<Particle> particles; foreach (var parfile in ParticleFiles) { if(UseUnsatFilter) particles = pr.ReadParticleFile(parfile.FileName, pr.UnSatFilter, DrainToBoundaryOption); else particles = pr.ReadParticleFile(parfile.FileName, null, DrainToBoundaryOption); AllParticles.AddRange(particles); if (ExtraOutput) pr.Distribute(particles.Where(p => p.SinkType != SinkType.Removed_by_Well)); else pr.Distribute(particles.Where(p => p.SinkType != SinkType.Removed_by_Well & p.Registration != 1)); } //Now scale the leaching data with the number of particles in each grid cell. leachdata.ScaleWithFactor(0.01); foreach (var p in AllParticles) { //Adjust traveltime from dfs2 foreach (var dfs in UnsatAgeFiles) { if (p.HorizontalTravelDistance >= dfs.MinHorizontalTravelDistance & p.TravelTime >= dfs.MinTravelTime) { int col = dfs.dfs.GetColumnIndex(p.X); int row = dfs.dfs.GetRowIndex(p.Y); if (col >= 0 & row >= 0) p.TravelTime += Math.Max(0, dfs.Data[row, col]); } } } BuildInputConcentration(Start, End, Catchments); if (ExtraOutput) pr.DebugPrint(MainModel.OutputDirectory); //Now clear memory leachdata.ClearMemory(); foreach (var c in Catchments) c.EndParticles.Clear(); }
public void MakeMap(Dictionary<int, Catchment> AllCatchments, IEnumerable<Catchment> EndCatchments, DataTable StateVariables, IEnumerable<INitrateModel> SourceModels, IEnumerable<INitrateModel> InternalSinkModels, IEnumerable<INitrateModel> MainSinkModels) { this.StateVariables = StateVariables; NewMessage("Creating reduction maps"); ParticleReader pr = new ParticleReader(); pr.Catchments = AllCatchments.Values; foreach (var s in ParticleFiles) { var particles = pr.ReadParticleFile(s.FileName, null, DrainToBoundaryOption); NewMessage("Reading particles from: " + s.FileName); NewMessage("Distributing " + particles.Count() + " particles on catchments"); pr.Distribute(particles); } Dictionary<int, double> GroundwaterReduction = new Dictionary<int, double>(); foreach (var v in AllCatchments.Values) { var row = GetReductionRow(v.ID); int TotalParticles = v.StartParticles.Count; int TotalRedoxedParticles = v.StartParticles.Count(p => p.Registration == 1);; if(ParticlesPrSquareMeter!=-1) { int n = (int) (v.Geometry.GetArea()*ParticlesPrSquareMeter); TotalRedoxedParticles += (n - TotalParticles); TotalParticles =n; } row["Particles"] = TotalParticles; row["RedoxedParticles"] = TotalRedoxedParticles; if (v.StartParticles.Count > 0) row["GWDischarge"] = 1.0 - (double)TotalRedoxedParticles / ((double)TotalParticles); else row["GWDischarge"] = 1; } NewMessage("Calculated discharge percentage"); //<ID15<ID15,no of particles>> For each ID15 there is a list of ID15s where the particles exit. Dictionary<int, Dictionary<int, int>> CatchmentPartCounts = new Dictionary<int, Dictionary<int, int>>(); Dictionary<int, int> NonRedoxedSea = new Dictionary<int, int>(); foreach (var v in AllCatchments.Values) { List<double> reductions = new List<double>(); //Distribute the particles infiltrating on the cathcments where they exit Dictionary<int, int> partcounts = new Dictionary<int, int>(); CatchmentPartCounts.Add(v.ID, partcounts); NonRedoxedSea.Add(v.ID, 0); partcounts.Add(v.ID, 0); //Only take the non redoxed Parallel.ForEach(v.StartParticles.Where(p => p.Registration != 1), p => { if (v.Geometry.Contains(p.X, p.Y)) lock (Lock) partcounts[v.ID]++; else { bool found = false; foreach (var c in AllCatchments.Values) { if (c.Geometry.Contains(p.X, p.Y)) { lock (Lock) { found=true; if (partcounts.ContainsKey(c.ID)) partcounts[c.ID]++; else partcounts.Add(c.ID, 1); } break; } } if (!found) NonRedoxedSea[v.ID]++; } }); } BuildReduction(AllCatchments, EndCatchments, SourceModels, InternalSinkModels, MainSinkModels); foreach (var v in AllCatchments.Values) { double totalSurface = 0; double totalConceptual = 0; var row = GetReductionRow(v.ID); row["OutsideParticles"] = CatchmentPartCounts[v.ID].Skip(1).Sum(k => k.Value); row["SeaParticles"] = v.StartParticles.Count(p => p.Registration != 1) - CatchmentPartCounts[v.ID].Sum(k => k.Value); int totalparticlesNotSea = CatchmentPartCounts[v.ID].Sum(k => k.Value); //Loop all the catchments where particles exit. This includes the actual catchment foreach (var kvp in CatchmentPartCounts[v.ID]) { var temprow = GetReductionRow(kvp.Key); totalSurface += (double)temprow["SurfaceDischarge"] * kvp.Value; //Multiply the particles entering a particular catchment with the reductions of that catchment totalConceptual += (double)temprow["ConceptualGWDischarge"] * kvp.Value; //Multiply the particles entering a particular catchment with the reductions of that catchment } totalSurface /= totalparticlesNotSea; totalConceptual /= totalparticlesNotSea; row["ConcExitDischarge"]=totalConceptual; row["TotalDischarge"] = totalSurface * totalConceptual * (double)row["GWDischarge"]; } Print(AllCatchments,""); }
/// <summary> /// Initializes the model by reading all files and building the leaching time series to and from each catchment /// </summary> /// <param name="Start"></param> /// <param name="End"></param> /// <param name="Catchments"></param> public override void Initialize(DateTime Start, DateTime End, IEnumerable <Catchment> Catchments) { base.Initialize(Start, End, Catchments); this.Start = Start; LoadSoilCodesGrid(SoilCodes.FileName); foreach (var item in UnsatAgeFiles) { item.Initialize(); } foreach (var parfile in DaisyFiles) { LoadDaisyData(parfile.FileName); } leachdata.BuildLeachData(Start, End, Catchments, RecycleStart, RecycleEnd, RecycleScale); ParticleReader pr = new ParticleReader(); pr.Catchments = Catchments; List <Particle> AllParticles = new List <Particle>(); IEnumerable <Particle> particles; foreach (var parfile in ParticleFiles) { if (UseUnsatFilter) { particles = pr.ReadParticleFile(parfile.FileName, pr.UnSatFilter, DrainToBoundaryOption); } else { particles = pr.ReadParticleFile(parfile.FileName, null, DrainToBoundaryOption); } AllParticles.AddRange(particles); if (ExtraOutput) { pr.Distribute(particles.Where(p => p.SinkType != SinkType.Removed_by_Well)); } else { pr.Distribute(particles.Where(p => p.SinkType != SinkType.Removed_by_Well & p.Registration != 1)); } } //Now scale the leaching data with the number of particles in each grid cell. leachdata.ScaleWithFactor(0.01); foreach (var p in AllParticles) { //Adjust traveltime from dfs2 foreach (var dfs in UnsatAgeFiles) { if (p.HorizontalTravelDistance >= dfs.MinHorizontalTravelDistance & p.TravelTime >= dfs.MinTravelTime) { int col = dfs.dfs.GetColumnIndex(p.X); int row = dfs.dfs.GetRowIndex(p.Y); if (col >= 0 & row >= 0) { p.TravelTime += Math.Max(0, dfs.Data[row, col]); } } } } BuildInputConcentration(Start, End, Catchments); if (ExtraOutput) { pr.DebugPrint(MainModel.OutputDirectory); } //Now clear memory leachdata.ClearMemory(); foreach (var c in Catchments) { c.EndParticles.Clear(); } }
public void MakeMap(Dictionary <int, Catchment> AllCatchments, IEnumerable <Catchment> EndCatchments, DataTable StateVariables, IEnumerable <INitrateModel> SourceModels, IEnumerable <INitrateModel> InternalSinkModels, IEnumerable <INitrateModel> MainSinkModels) { this.StateVariables = StateVariables; NewMessage("Creating reduction maps"); ParticleReader pr = new ParticleReader(); pr.Catchments = AllCatchments.Values; foreach (var s in ParticleFiles) { var particles = pr.ReadParticleFile(s.FileName, null, DrainToBoundaryOption); NewMessage("Reading particles from: " + s.FileName); NewMessage("Distributing " + particles.Count() + " particles on catchments"); pr.Distribute(particles); } Dictionary <int, double> GroundwaterReduction = new Dictionary <int, double>(); foreach (var v in AllCatchments.Values) { var row = GetReductionRow(v.ID); int TotalParticles = v.StartParticles.Count; int TotalRedoxedParticles = v.StartParticles.Count(p => p.Registration == 1);; if (ParticlesPrSquareMeter != -1) { int n = (int)(v.Geometry.GetArea() * ParticlesPrSquareMeter); TotalRedoxedParticles += (n - TotalParticles); TotalParticles = n; } row["Particles"] = TotalParticles; row["RedoxedParticles"] = TotalRedoxedParticles; if (v.StartParticles.Count > 0) { row["GWDischarge"] = 1.0 - (double)TotalRedoxedParticles / ((double)TotalParticles); } else { row["GWDischarge"] = 1; } } NewMessage("Calculated discharge percentage"); //<ID15<ID15,no of particles>> For each ID15 there is a list of ID15s where the particles exit. Dictionary <int, Dictionary <int, int> > CatchmentPartCounts = new Dictionary <int, Dictionary <int, int> >(); Dictionary <int, int> NonRedoxedSea = new Dictionary <int, int>(); foreach (var v in AllCatchments.Values) { List <double> reductions = new List <double>(); //Distribute the particles infiltrating on the cathcments where they exit Dictionary <int, int> partcounts = new Dictionary <int, int>(); CatchmentPartCounts.Add(v.ID, partcounts); NonRedoxedSea.Add(v.ID, 0); partcounts.Add(v.ID, 0); //Only take the non redoxed Parallel.ForEach(v.StartParticles.Where(p => p.Registration != 1), p => { if (v.Geometry.Contains(p.X, p.Y)) { lock (Lock) partcounts[v.ID]++; } else { bool found = false; foreach (var c in AllCatchments.Values) { if (c.Geometry.Contains(p.X, p.Y)) { lock (Lock) { found = true; if (partcounts.ContainsKey(c.ID)) { partcounts[c.ID]++; } else { partcounts.Add(c.ID, 1); } } break; } } if (!found) { NonRedoxedSea[v.ID]++; } } }); } BuildReduction(AllCatchments, EndCatchments, SourceModels, InternalSinkModels, MainSinkModels); foreach (var v in AllCatchments.Values) { double totalSurface = 0; double totalConceptual = 0; var row = GetReductionRow(v.ID); row["OutsideParticles"] = CatchmentPartCounts[v.ID].Skip(1).Sum(k => k.Value); row["SeaParticles"] = v.StartParticles.Count(p => p.Registration != 1) - CatchmentPartCounts[v.ID].Sum(k => k.Value); int totalparticlesNotSea = CatchmentPartCounts[v.ID].Sum(k => k.Value); //Loop all the catchments where particles exit. This includes the actual catchment foreach (var kvp in CatchmentPartCounts[v.ID]) { var temprow = GetReductionRow(kvp.Key); totalSurface += (double)temprow["SurfaceDischarge"] * kvp.Value; //Multiply the particles entering a particular catchment with the reductions of that catchment totalConceptual += (double)temprow["ConceptualGWDischarge"] * kvp.Value; //Multiply the particles entering a particular catchment with the reductions of that catchment } totalSurface /= totalparticlesNotSea; totalConceptual /= totalparticlesNotSea; row["ConcExitDischarge"] = totalConceptual; row["TotalDischarge"] = totalSurface * totalConceptual * (double)row["GWDischarge"]; } Print(AllCatchments, ""); }