Exemple #1
0
        public static IEnumerable <NereidResult> TotalNetworkSolve(out string stackTrace,
                                                                   out List <string> missingNodeIDs, out Graph graph, DatabaseEntities dbContext, HttpClient httpClient, bool isBaselineCondition)
        {
            stackTrace     = "";
            missingNodeIDs = new List <string>();

            graph = NereidUtilities.BuildNetworkGraph(dbContext);

            var nereidResults = NetworkSolveImpl(missingNodeIDs, graph, dbContext, httpClient, false, isBaselineCondition);

            var baselineConditionSqlParam = new SqlParameter("@isBaselineCondition", isBaselineCondition);

            dbContext.Database.ExecuteSqlCommand(
                "EXEC dbo.pDeleteNereidResults @isBaselineCondition", baselineConditionSqlParam);

            dbContext.NereidResults.AddRange(nereidResults);
            // this is a relatively hefty set, so boost the timeout way beyond reasonable to make absolutely sure it doesn't die out on us.
            dbContext.Database.CommandTimeout = 600;
            dbContext.SaveChangesWithNoAuditing();

            return(nereidResults);
        }
Exemple #2
0
        public static NereidResult <SolutionResponseObject> SolveSubgraph(Graph subgraph,
                                                                          List <vNereidLoadingInput> allLoadingInputs, List <TreatmentBMP> allModelingBMPs,
                                                                          List <WaterQualityManagementPlanNode> allWaterqualityManagementPlanNodes,
                                                                          List <QuickBMP> allModelingQuickBMPs, out List <string> notFoundNodes, HttpClient httpClient, bool isBaselineCondition)
        {
            notFoundNodes = new List <string>();

            // Now I need to get the land_surface, treatment_facility, and treatment_site tables for this request.
            // these are going to look very much like the various calls made throughout the testing methods, but filtered
            // to the subgraph. Fortunately, we've added metadata to the nodes to help us do the filtration

            var delineationToIncludeIDs = subgraph.Nodes.Where(x => x.Delineation != null).Select(x => x.Delineation.DelineationID)
                                          .Distinct().ToList();
            var regionalSubbasinToIncludeIDs = subgraph.Nodes.Where(x => x.RegionalSubbasinID != null)
                                               .Select(x => x.RegionalSubbasinID).Distinct().ToList();
            var waterQualityManagementPlanToIncludeIDs = subgraph.Nodes.Where(x => x.WaterQualityManagementPlan != null)
                                                         .Select(x => x.WaterQualityManagementPlan.WaterQualityManagementPlanID).Distinct().ToList();
            var treatmentBMPToIncludeIDs = subgraph.Nodes.Where(x => x.TreatmentBMPID != null)
                                           .Select(x => x.TreatmentBMPID.Value).Distinct().ToList();

            var landSurfaces = allLoadingInputs.Where(x =>
                                                      delineationToIncludeIDs.Contains(x.DelineationID.GetValueOrDefault()) ||
                                                      regionalSubbasinToIncludeIDs.Contains(x.RegionalSubbasinID) ||
                                                      waterQualityManagementPlanToIncludeIDs.Contains(x.WaterQualityManagementPlanID.GetValueOrDefault())
                                                      ).ToList().Select(x => new LandSurface(x, isBaselineCondition)).ToList();

            var treatmentFacilities = allModelingBMPs
                                      .Where(x => treatmentBMPToIncludeIDs.Contains(x.TreatmentBMPID) &&
                                             // Don't create TreatmentFacilities for BMPs belonging to a Simple WQMP
                                             x.WaterQualityManagementPlan?.WaterQualityManagementPlanModelingApproachID != WaterQualityManagementPlanModelingApproach.Simplified.WaterQualityManagementPlanModelingApproachID)
                                      .Select(x => x.ToTreatmentFacility(isBaselineCondition)).ToList();

            var filteredQuickBMPs = allModelingQuickBMPs
                                    .Where(x => waterQualityManagementPlanToIncludeIDs.Contains(x.WaterQualityManagementPlanID) &&
                                           // Don't create TreatmentSites for QuickBMPs belonging to a Detailed WQMP
                                           x.WaterQualityManagementPlan.WaterQualityManagementPlanModelingApproachID != WaterQualityManagementPlanModelingApproach.Detailed.WaterQualityManagementPlanModelingApproachID).ToList();
            var filteredWQMPNodes = allWaterqualityManagementPlanNodes.Where(y =>
                                                                             waterQualityManagementPlanToIncludeIDs.Contains(y.WaterQualityManagementPlanID) &&
                                                                             regionalSubbasinToIncludeIDs.Contains(y.RegionalSubbasinID) // ignore parts that live in RSBs outside our solve area.
                                                                             ).ToList();

            var treatmentSites = filteredQuickBMPs
                                 .Join(
                filteredWQMPNodes, x => x.WaterQualityManagementPlanID,
                x => x.WaterQualityManagementPlanID, (bmp, node) => new { bmp, node })
                                 .Select(x =>
                                         new TreatmentSite
            {
                NodeID = NereidUtilities.WaterQualityManagementPlanTreatmentNodeID(x.node.WaterQualityManagementPlanID,
                                                                                   x.node.OCSurveyCatchmentID),
                AreaPercentage     = x.bmp.PercentOfSiteTreated,
                CapturedPercentage = x.bmp.PercentCaptured ?? 0,
                RetainedPercentage = x.bmp.PercentRetained ?? 0,
                // treat wqmps built after 2003 as if they don't exist.
                FacilityType = (isBaselineCondition && x.node.DateOfConstruction.HasValue && x.node.DateOfConstruction.Value.Year > BASELINE_CUTOFF_YEAR) ? "NoTreatment" : x.bmp.TreatmentBMPType.TreatmentBMPModelingType.TreatmentBMPModelingTypeName,
                EliminateAllDryWeatherFlowOverride = x.bmp.DryWeatherFlowOverrideID == DryWeatherFlowOverride.Yes.DryWeatherFlowOverrideID
            }).ToList();

            //ValidateForTesting(subgraph, landSurfaces, treatmentFacilities, treatmentSites);

            var solveUrl = $"{NeptuneWebConfiguration.NereidUrl}/api/v1/watershed/solve?state=ca&region=soc";

            // get the list of leaf nodes for this subgraph
            var targetNodeIDs = subgraph.Edges.Select(x => x.TargetID);
            // As all men know in this kingdom by the sea, a leaf of a digraph is a node that's not the target of an edge
            var leafNodes = subgraph.Nodes.Where(x => !targetNodeIDs.Contains(x.ID));

            var solutionRequestObject = new SolutionRequestObject()
            {
                Graph               = subgraph,
                LandSurfaces        = landSurfaces,
                TreatmentFacilities = treatmentFacilities,
                TreatmentSites      = treatmentSites,
                PreviousResults     = leafNodes.Where(x => x.PreviousResults != null).Select(x => x.PreviousResults).ToList()
            };
            NereidResult <SolutionResponseObject> results = null;

            try
            {
                results = RunJobAtNereid <SolutionRequestObject, SolutionResponseObject>(
                    solutionRequestObject, solveUrl,
                    out _, httpClient);
            }
            catch (Exception e)
            {
                throw new NereidException <SolutionRequestObject, SolutionResponseObject>(e.Message, e)
                      {
                          Request  = solutionRequestObject,
                          Response = results?.Data
                      };
            }

            if (results?.Data.Errors != null && results.Data.Errors.Count > 0 && (results.Data.Results == null || results.Data.Results.Count == 0))
            {
                throw new NereidException <SolutionRequestObject, SolutionResponseObject>
                      {
                          Request = solutionRequestObject, Response = results.Data
                      };
            }

            // literally this can't be null...
            // ReSharper disable once PossibleNullReferenceException
            var previousResultsKeys = results.Data.PreviousResultsKeys;

            foreach (var dataLeafResult in results.Data.Results)
            {
                var node = subgraph.Nodes.SingleOrDefault(x => x.ID == dataLeafResult["node_id"].ToString());
                if (node == null)
                {
                    // this is an edge case that should only happen if an RSB in the SOC area has
                    // its downstream catchment outside the SOC area for some reason.
                    notFoundNodes.Add(dataLeafResult["node_id"].ToString());
                }
                else
                {
                    node.Results = dataLeafResult;

                    // track the smaller subset of results that need to be sent for subsequent calls
                    var previousResults = new JObject();
                    foreach (var key in previousResultsKeys)
                    {
                        var value = dataLeafResult[key];
                        previousResults.Add(key, value);
                    }

                    node.PreviousResults = previousResults;
                }
            }

            foreach (var dataLeafResult in results.Data.LeafResults)
            {
                try
                {
                    var node = subgraph.Nodes.SingleOrDefault(x => x.ID == dataLeafResult["node_id"].ToString());
                    if (node == null)
                    {
                        notFoundNodes.Add(dataLeafResult["node_id"].ToString());
                    }
                    else
                    {
                        // don't store the leaf results if already data at this node--most of the time these nodes are read-only
                        if (node.Results == null)
                        {
                            node.Results = dataLeafResult;
                        }
                    }
                }
                catch (InvalidOperationException ioe)
                {
                    throw new DuplicateNodeException(dataLeafResult["node_id"].ToString(), ioe);
                }
            }

            return(results);
        }
Exemple #3
0
        private static List <NereidResult> NetworkSolveImpl(List <string> missingNodeIDs, Graph graph, DatabaseEntities dbContext,
                                                            HttpClient httpClient, bool sendPreviousResults, bool isBaselineCondition)
        {
            var solutionSequenceUrl =
                $"{NeptuneWebConfiguration.NereidUrl}/api/v1/network/solution_sequence?min_branch_size=12";

            var allLoadingInputs = dbContext.vNereidLoadingInputs.ToList();
            var allModelingBMPs  = NereidUtilities.ModelingTreatmentBMPs(dbContext).ToList();
            var allwaterQualityManagementPlanNodes =
                NereidUtilities.GetWaterQualityManagementPlanNodes(dbContext).ToList();
            var allModelingQuickBMPs = dbContext.QuickBMPs.Include(x => x.TreatmentBMPType)
                                       .GetFullyParameterized();

            var solutionSequenceResult =
                NereidUtilities.RunJobAtNereid <SolutionSequenceRequest, SolutionSequenceResult>(
                    new SolutionSequenceRequest(graph), solutionSequenceUrl, out _, httpClient);

            // for the delta run, associate each node with its previous results
            if (sendPreviousResults)
            {
                var previousModelResults = dbContext.NereidResults.ToList();
                foreach (var node in graph.Nodes)
                {
                    var previousNodeResults = previousModelResults.SingleOrDefault(x =>
                                                                                   node.ID == x.NodeID && x.IsBaselineCondition == isBaselineCondition
                                                                                   )?.FullResponse;

                    if (previousNodeResults != null)
                    {
                        node.PreviousResults = JObject.Parse(previousNodeResults);
                        node.PreviousResults["node_errors"]   = "";
                        node.PreviousResults["node_warnings"] = "";
                    }
                }
            }

            foreach (var parallel in solutionSequenceResult.Data.SolutionSequence.Parallel)
            {
                foreach (var series in parallel.Series)
                {
                    var seriesNodes = series.Nodes;
                    var subgraph    = MakeSubgraphFromParentGraphAndNodes(graph, seriesNodes);

                    SolveSubgraph(subgraph, allLoadingInputs, allModelingBMPs, allwaterQualityManagementPlanNodes,
                                  allModelingQuickBMPs, out var notFoundNodes, httpClient, isBaselineCondition);
                    missingNodeIDs.AddRange(notFoundNodes);
                }
            }

            var nereidResults = graph.Nodes.Where(x => x.Results != null).Select(x => new NereidResult(x.Results.ToString(), isBaselineCondition)
            {
                TreatmentBMPID               = x.TreatmentBMPID,
                DelineationID                = x.Delineation?.DelineationID,
                NodeID                       = x.ID,
                RegionalSubbasinID           = x.RegionalSubbasinID,
                WaterQualityManagementPlanID = x.WaterQualityManagementPlan?.WaterQualityManagementPlanID,
                LastUpdate                   = DateTime.Now
            }).ToList();

            return(nereidResults);
        }