/// <summary> /// Determines the default dependency value for a fragmentflow. not fast. /// </summary> /// <param name="repository"></param> /// <param name="fragmentFlowId"></param> /// <param name="scenarioId"></param> /// <returns></returns> public static double? GetDefaultValue(this IRepository<FragmentFlow> repository, int fragmentFlowId, int scenarioId = Scenario.MODEL_BASE_CASE_ID) { FragmentFlow fragmentFlow = repository.Queryable() .Where(k => k.FragmentFlowID == fragmentFlowId) .Where(k => k.ParentFragmentFlow.NodeTypeID == 1) .FirstOrDefault(); if (fragmentFlow == null) return null; var ncm = new NodeCacheModel() { NodeTypeID = 1, FragmentFlowID = (int)fragmentFlow.ParentFragmentFlowID }; var parentNode = repository.LTerminate(ncm, scenarioId, false); return repository.GetRepository<ProcessFlow>().FlowExchange((int)parentNode.ProcessID, fragmentFlow.FlowID, comp(fragmentFlow.DirectionID)); // double comp! }
/// <summary> /// Determine dependency flows required by the fragmentflow termination being supplied. /// This function assumes that all flow+direction combinations are distinct for processes and fragments. /// (for fragments, node outflows are grouped by flow+direction) /// </summary> /// <param name="term">FragmentNodeResource corresponding to the terminus of the current FragmentFlow</param> /// <param name="ex_directionId">Direction of the physical flow with respect to the *parent*</param> /// <param name="flow_exch">out param set equal to the inflow's exchange</param> /// <returns></returns> public IEnumerable<InventoryModel> GetScenarioProductFlows(NodeCacheModel theFragmentFlow, int scenarioId, out double nodeWeight, out int? ilcdEntityId) { FlowTerminationModel term = _fragmentFlowService.Terminate(theFragmentFlow,scenarioId, true); // resolve background // first, calculate node weight double? flow_conv = _flowFlowPropertyService.FlowConv(theFragmentFlow.FlowID, term.TermFlowID, scenarioId); if (flow_conv == null) { throw new ArgumentNullException("Flow conversion was not found and cannot be null"); } double flow_exch; // and incoming exchange // note this is not subject to parameter adjustment IEnumerable<InventoryModel> Outflows; switch (term.NodeTypeID) { case 1: { // process-- lookup exchange and outflows separately //var _flow_exch = _processFlowService.FlowExchange((int)term.ProcessID, term.TermFlowID, theFragmentFlow.DirectionID); //if (_flow_exch == null) //{ // throw new ArgumentNullException("Process inflow not found!"); //} //flow_exch = (double)_flow_exch; //Outflows = _processFlowService.GetDependencies((int)term.ProcessID, term.TermFlowID, theFragmentFlow.DirectionID); if (term.BalanceFFID == null) { // no conservation performed var FFM = _processFlowService.LookupDependencies(theFragmentFlow.FragmentFlowID, term, scenarioId).ToList(); flow_exch = (double)FFM.Where(k => k.FlowID == term.TermFlowID && k.DirectionID != theFragmentFlow.DirectionID) .Select(k => k.Result).First(); Outflows = FFM.Where(k => k.FragmentFlowID != null).ToList(); } else { var CM = _processFlowService.LookupConservationFlows(theFragmentFlow.FragmentFlowID, term, scenarioId).ToList(); flow_exch = (double)CM.Where(k => k.FlowID == term.TermFlowID && k.DirectionID != theFragmentFlow.DirectionID) .Select(k => k.Result).First(); var balanceDir = CM.Where(k => k.FragmentFlowID == term.BalanceFFID).Select(k => k.DirectionID).First(); var balance = CM.Where(k => k.DirectionID != balanceDir).Sum(k => k.FlowPropertyResult) - CM.Where(k => k.DirectionID == balanceDir).Where(k => k.FragmentFlowID != term.BalanceFFID) .Sum(k => k.FlowPropertyResult); foreach (var bf in CM.Where(k => k.FragmentFlowID == term.BalanceFFID)) bf.FlowPropertyResult = balance; Outflows = CM.Where(k => k.FragmentFlowID != null).ToList(); } break; } case 2: { // does the subfragment exist in the cache? if so, use that if (_nodeCacheService.IsCached((int)term.SubFragmentID,term.ScenarioID)) Outflows = _fragmentFlowService.GetDependencies((int)term.SubFragmentID, term.TermFlowID, theFragmentFlow.DirectionID, out flow_exch, term.ScenarioID); else { // have we already traversed this subfragment in this unit of work? int subFragRefFlow = _fragmentFlowService .Query(k => k.FragmentID == term.SubFragmentID && k.ParentFragmentFlowID == null) .Select(k => k.FragmentFlowID).First(); if (!nodeCaches.Any(k => k.FragmentFlowID == subFragRefFlow)) { // if not, we need to Traverse((int)term.SubFragmentID, term.ScenarioID); } // access the cache to determine outflow amounts //Outflows = _fragmentFlowService.GetDependencies((int)term.SubFragmentID,term.TermFlowID,ex_directionId, // out flow_exch, term.ScenarioID); Outflows = GetDependencies((int)term.SubFragmentID, term.TermFlowID, theFragmentFlow.DirectionID, out flow_exch, term.ScenarioID); } break; } default: { Outflows = new List<InventoryModel>(); flow_exch = 1; break; } } if (flow_exch == 0) { throw new ArgumentException("The inflow result cannot be 0"); } nodeWeight = (double)flow_conv / flow_exch; ilcdEntityId = term.ILCDEntityID; return Outflows; }
/// <summary> /// Lazy flow termination-- FNF and FNP are looked up now /// </summary> /// <param name="repository"></param> /// <param name="ff"></param> /// <param name="scenarioId"></param> /// <param name="doBackground"></param> /// <returns></returns> public static FlowTerminationModel LTerminate(this IRepository<FragmentFlow> repository, NodeCacheModel ff, int scenarioId, bool doBackground) { var fragmentNode = new FlowTerminationModel(); int inFlowId; switch (ff.NodeTypeID) { case 1: { fragmentNode = repository.LGetFragmentNodeProcess(ff.FragmentFlowID, scenarioId); break; } case 2: { fragmentNode = repository.LGetFragmentNodeFragment(ff.FragmentFlowID, scenarioId); break; } case 3: { if (ff.FlowID == null) { throw new ArgumentNullException("FragmentFlow.FlowID must be set!"); } fragmentNode.NodeTypeID = 3; //fragmentNode.ILCDEntityID = ff.FragmentFlowID; fragmentNode.ScenarioID = scenarioId; fragmentNode.TermFlowID = (int)ff.FlowID; break; } default: { if (ff.FlowID == null) { throw new ArgumentNullException("FragmentFlow.FlowID must be set!"); } else inFlowId = (int)ff.FlowID; if (doBackground) { fragmentNode = repository.GetRepository<Background>() .ResolveBackground(inFlowId, ff.DirectionID, scenarioId); } else { //fragmentNode.ILCDEntityID = ff.FragmentFlowID; fragmentNode.ScenarioID = scenarioId; fragmentNode.TermFlowID = inFlowId; } break; } } return fragmentNode; }