void CSeperator_EfficiencyCurve::EvalProducts(MStream &Feed , MStream &Product1, MStream &Product2, MStream &Product3, bool bTwoDecks, bool bInit) { // Get info on Size Distribution MIPSD & l_PSD=*Feed.FindIF<MIPSD>(); if (IsNothing(l_PSD)) { int xx=0; return; //Why do we get here!!! } long l_SizeCount = l_PSD.getSizeCount(); long l_PSDVectorCount = l_PSD.getPSDVectorCount(); // // Calculate Probability Passing for Each Deck // We could calculate this in Build Data definition // CalculateEfficiencyCurve( l_PSD , m_dTopD50 , m_dTopAlpha, m_dTopBeta, m_dTopC, m_dTopBetaStar, m_TopEu ); CalculateEfficiencyCurve( l_PSD , m_dBottomD50 , m_dBottomAlpha, m_dBottomBeta, m_dBottomC, m_dBottomBetaStar, m_BottomEu ); if ( bTwoDecks ) { // Execute the first seperator //MStream l_IntermediateProduct = Product1; // Cannot do this as = operator does not make copy Seperate(m_TopEu,m_dTopWaterSplitToUS, Feed, Product1 , /*l_IntermediateProduct*/Product2); // Execute the second seperator Seperate(m_BottomEu,m_dBottomWaterSplitToUS, /*l_IntermediateProduct*/Product2, Product2 , Product3); } else { // Execute the first seperator Seperate(m_TopEu,m_dTopWaterSplitToUS, Feed, Product1 , Product3); } }
bool BatchPrecip::PrecipBatchSS(double dTime, MVector & Prod, double CurLevel) { MIBayer & ProdB = *Prod.GetIF<MIBayer>(); MIPSD & ProdSz = *Prod.FindIF<MIPSD>(); MISSA & ProdSSA = *Prod.FindIF<MISSA>(); double TProd = Prod.getT(); double gpl1 = ProdB.SolidsConc(TProd); double ProdVolFlow = Prod.Volume(MP_All); double SolidsInitial = Prod.Mass(MP_Sol); double Sx; if (!sm_bCompletePopulation && sm_bUsePrevPSD) { MISSA & PrevSSA=*m_QProd.FindIF<MISSA>();// this is the SSA of the last Popul run to use in "NO POpul mode" if (IsNothing(PrevSSA)) { m_bPrevPSDUsed = 0; Sx=ProdSSA.SpecificSurfaceAreaMass(); //m^2/g//PROBLEM!!! Prev does not have SSA, use feed } else { m_bPrevPSDUsed = 1; Sx=PrevSSA.SpecificSurfaceAreaMass(); //m^2/g } } else { m_bPrevPSDUsed = 0; Sx = m_dInTankSSA ; // the SSA value manually entered by the user in m^2/g } Sx=Range(0.020, Sx, 0.085); //=== mass balance === double T0 = Prod.T; double Ain2 = ProdB.AluminaConc(C2K(25.0)); double Cin2 = ProdB.CausticConc(C2K(25.0)); double ASat2 = ProdB.AluminaConcSat(T0); double SSat2 = (Ain2-ASat2)/GTZ(Cin2); double NoPerSec2 = ProdSSA.PartNumPerSec(); double enthIn = Prod.totCp(MP_All) * K2C(T0); // Enthalpie IN double PrecipRate1 = get_PrecipRate(Prod, Sx); gpl1 = gpl1 - PrecipRate1 * dTime*156/102 ; bool CErr; const double Na2OFac = get_Na2OFactor(Prod); PerformAluminaSolubility(Prod, dNAN, dNAN, gpl1, 0, Na2OFac, SSat2, CErr); double T1 = Prod.T; double SolidsVariation = (Prod.Mass(MP_Sol) - SolidsInitial); //* 0.97 ;// 0.97 is to compensate for the HYPROD error HeatBalance(Prod, SolidsVariation, enthIn, dTime, CurLevel); // Éliminé pour vérifier la temp ? return true; }
void QualChange::EvalProducts() { try { MStreamI QI; //initialise local empty copy of a stream FlwIOs.AddMixtureIn_Id(QI, idFeed); //sum of all feed streams const long index = FlwIOs.First[idProd]; MStream & QO = FlwIOs[index].Stream; //get reference to the actual output stream QO = QI; //set output = input if (bOnLine) { //MIPSD & PSD = *QI.FindIF<MIPSD>(); //if ( IsNothing(PSD)==false ) CDemoQual & xQual = *QO.FindIF<CDemoQual>(); if ( IsNothing(xQual)==false ) { PSDCount = xQual.m_dSetProp; Log.Message(MMsg_Note, "Qual Data:%f", PSDCount); //CDemoQual & QualO = *QO.FindIF<CDemoQual>(); xQual.m_dSetProp = PSDCount+1.0; } } } catch (MMdlException &e) { Log.Message(MMsg_Error, e.Description); } catch (MFPPException &e) { e.ClearFPP(); Log.Message(MMsg_Error, e.Description); } catch (MSysException &e) { Log.Message(MMsg_Error, e.Description); } catch (...) { Log.Message(MMsg_Error, "Some Unknown Exception occured"); } }
void task_entry(const char *exe_name) { __asm__ ("sti"); screen_print("spawned new task\n"); screen_print("loading "); screen_print(exe_name); screen_put('\n'); const char *paths[] = {"bin", exe_name}; auto mData = _kernel_state.fs.GetInode(2, paths); if(mData.IsNothing()) { kernel_panic("failed to get inode"); } auto data = mData.FromJust(); _kernel_state.pager->Enable(_kernel_state.task->context); ELF elf(data); user_enter(elf.entry(), &_kernel_state.task->stack[PAGE_ALLOCATOR_PAGE_SIZE * Task::STACK_PAGES]); for(;;) { __asm__ ("hlt"); } // unreachable }
void CPSDUnit::EvalProducts() { try { MStreamI Feed; FlwIOs.AddMixtureIn_Id(Feed, idFeed); MStream & Prod = FlwIOs[FlwIOs.First[idProd]].Stream; //Reference to the overflow out stream //dbg.log("EvalProds"); Prod = Feed; bool streamOK=((Feed.Mass()>1.0e-9) && (Feed.Mass(MP_Sol)>1.0e-9)); m_dMassSolids = Prod.Mass(MP_Sol); m_dVolSlurry = Prod.Volume(MP_All, C2K(25)); MIBayer & ProdB=Prod.IF<MIBayer>(false); // Do the checks up front Log.SetCondition(IsNothing(ProdB), 1, MMsg_Warning, "Bad Feed Stream - Not Bayer Model"); MIPSD & ProdPSD = Prod.IF<MIPSD>(false); Log.SetCondition(IsNothing(ProdPSD), 1, MMsg_Warning, "Bad Feed Stream - No PSD Available"); if (IsNothing(ProdB) || IsNothing(ProdPSD) || (m_dVolSlurry < 1.0e-4)) streamOK = false; //if (streamOK) dbg.log("Stream OK"); //else dbg.log("Bad Stream"); if (streamOK) { // Online and have Bayer and SSA properties... m_dCnv = m_dMassSolids/m_dVolSlurry; DoPSDUnit(Prod); displayPSD(b); } else { // Just tidy up and put some sensible stuff in the results... // Log.Message(MMsg_Warning, "Bad Stream: PSD Unit"); } } catch (MMdlException &e) { Log.Message(MMsg_Error, e.Description); } catch (MFPPException &e) { e.ClearFPP(); Log.Message(MMsg_Error, e.Description); } catch (MSysException &e) { Log.Message(MMsg_Error, e.Description); } catch (...) { Log.Message(MMsg_Error, "Some Unknown Exception occured"); } }
DB.Page("R/D*"); for (int i = 0; i < 31; i++) { char buff[20]; sprintf(buff,"RDS%d",i); DB.Double(buff, "", &mo_RDStar[i] , MF_RESULT ); } DB.Page("Scale"); DB.Double("FACTA","", &mo_FACTA , MF_RESULT ); DB.Double("FACTB","", &mo_FACTB , MF_RESULT ); DB.Double("FACTC","", &mo_FACTC , MF_RESULT ); DB.Double("FACTD","", &mo_FACTD , MF_RESULT ); DB.Double("FACTE<Xm","", &mo_FACTEsizeltXm , MF_RESULT ); DB.Double("FACTE>Xm","", &mo_FACTEsizegeXm , MF_RESULT ); DB.Double("Xm","", &mo_Xm , MF_RESULT ); DB.ObjectEnd(); } //==================================================================================== void CMill_Ball::EvalProducts(MBaseMethod &M, MStream &Feed , MStream &Product , bool bInit ) { // Get info on Size Distribution MIPSD & l_PSD=*Feed.FindIF<MIPSD>(); if (IsNothing(l_PSD)) { int xx=0; return; //Why do we get here!!! } long l_SizeCount = l_PSD.getSizeCount(); long l_PSDVectorCount = l_PSD.getPSDVectorCount(); if ( bInit && !IsNothing(l_PSD)) { bInit = false; // Copy the Sieve Data Sizing Info SysCADSystemHelper::SysCADSizeDataToSystem(l_PSD, MatInfo); // Copy Material Information from database // For now we just set up n components // The MineralInfo data will come from a database MatInfo->SetNumberOfMinerals( l_PSD.PSDVectorCount ); SysCADSystemHelper::PopulateMaterialInfo(M,MatInfo); // Initialize Ball Mill m_Params[0] = mi_NParrallelMills; m_Params[1] = mi_DiameterSim; m_Params[2] = mi_LengthSim; m_Params[3] = mi_FracCriticalSpeedSim; m_Params[4] = mi_FracLoadSim; m_Params[5] = mi_WorkIndexSim; m_Params[6] = mi_BallTopSizeSim; m_Params[7] = mi_DiameterDerived; m_Params[8] = mi_LengthDerived; m_Params[9] = mi_FracCriticalSpeedDerived; m_Params[10] = mi_FracLoadDerived; m_Params[11] = mi_WorkIndexDerived; m_Params[12] = mi_BallTopSizeDerived; m_Params[13] = mi_K; m_Params[14] = mi_NumSplineKnots; for ( int i = 0 ; i < 31 ; i++ ) m_Params[15+i] = mi_KnotSize[i]; for ( int i = 0 ; i < 31 ; i++ ) m_Params[46+i] = mi_KnotLnRDStar[i]; for ( int i = 0 ; i < 31 ; i++ ) m_Params[77+i] = mi_A[i]; RioTintoTS::VectorView ParamVec(m_Params,108,1); Mill.Initialize(MatInfo,ParamVec); // Create the Feed Stream. Use SetConfig after initialisation // if we need to change anything. We need to initialise here // because we get the size information from the Feed stream FeedStream = RioTintoTS::FlowStream1::Create( MatInfo ); } if (!IsNothing(l_PSD)) { // Copy the input size data to the system feed stream solids SysCADSystemHelper::SysCADSolidsToSystem(Feed,FeedStream); SysCADSystemHelper::SysCADLiquidToSystem(Feed,FeedStream);
bool BatchPrecip::BatchCycle(MVector & Slurry, MVector & Liquor, MVector & Prod) { double dt; MIBayer & SlurryB = *Slurry.GetIF<MIBayer>(); MIBayer & ProdB = *Prod.GetIF<MIBayer>(); MIPSD & SlurrySz = *Slurry.FindIF<MIPSD>(); MIPSD & ProdSz = *Prod.FindIF<MIPSD>(); MISSA & SlurrySSA = *Slurry.FindIF<MISSA>(); MISSA & ProdSSA = *Prod.FindIF<MISSA>(); Log.SetCondition(IsNothing(SlurrySz) || IsNothing(ProdSz), 2, MMsg_Error, "Bad Slurry Stream - No Size Distribution"); Log.SetCondition(IsNothing(SlurrySSA) || IsNothing(ProdSSA), 3, MMsg_Error, "Bad Slurry Stream - No SSA Data"); m_dCirculationTime = Max(1.0, m_dCirculationTime); m_dSeedingTime = Max(1.0, m_dSeedingTime); m_dDrawOffTime = Max(1.0, m_dDrawOffTime); m_dFillingTime = Max(1.0, m_dFillingTime); m_dFillingTempDrop = Max(0.0, m_dFillingTempDrop); if (!IsNothing(ProdSz) && !IsNothing(ProdSSA)) { if (!InitSizeData(Prod)) return false; InitAgloData(m_eAgloModel, m_dAgloParam[int(m_eAgloModel)]); double *ProdPSD=ProdSz.getFracVector(0); //array of PSD data //Determine adjusted filtrate and slurry feed for "single" tank double SlurryTtlFlow = Slurry.Volume(); if (SlurryTtlFlow<1.0e-6) return true; double LiquorTtlFlow = (m_bHasLiquor ? Liquor.Volume() : 0.0); if (m_bHasLiquor && LiquorTtlFlow<1.0e-6) return true; //todo error message double CombinedFlows = SlurryTtlFlow + LiquorTtlFlow; const double SlurryTtlMassFlow = Slurry.Mass(); const double LiquorTtlMassFlow = (m_bHasLiquor ? Liquor.Mass() : 0.0); bool ContSeeding = !m_bHasLiquor; double FractionFiltrate = 0.0; double SeedFlow = 0.0; double FillFlow = 0.0; if (ContSeeding) { SeedFlow = (m_dVolume*m_dLevel) / (m_dFillingTime+m_dSeedingTime);// !! in that CASE filling means the PL&Seed filling time Slurry.AdjustMassTo(MP_All, SlurryTtlMassFlow*SeedFlow/SlurryTtlFlow); } else { FractionFiltrate = LiquorTtlFlow / (LiquorTtlFlow+SlurryTtlFlow); FillFlow = (m_dVolume*m_dLevel) * FractionFiltrate / m_dFillingTime; SeedFlow = (m_dVolume*m_dLevel) * (1.0-FractionFiltrate) / m_dSeedingTime; Liquor.AdjustMassTo(MP_All, LiquorTtlMassFlow*FillFlow/LiquorTtlFlow); Slurry.AdjustMassTo(MP_All, SlurryTtlMassFlow*SeedFlow/SlurryTtlFlow); //Liquor.SetF(Liquor, MP_All, FillFlow/LiquorTtlFlow); } /*if (m_dNbTankAvailable<=0.0) { Nb = (m_dFilltime + m_dSeedingTime + Recirc_t +DrawOff_t) * ( CombinedFlows) / (m_dVolume*level); }*/ //todo: No Of Tanks??? double iLevel; if (ContSeeding) { iLevel = 0.2; const double TimeSoFar = iLevel*(m_dVolume*m_dLevel) / Slurry.Volume(); const double d = Slurry.Mass()* TimeSoFar ;//kg Prod.SetM(Slurry, MP_All, d); //const double d = iLevel*(m_dVolume*m_dLevel) / Slurry.Volume(); //Prod.SetF(Slurry, MP_All, d); // les valeurs dans PrecipResult ne sont plus des debits mais des volumes et des masses; } else { iLevel = FractionFiltrate; const double d = Liquor.Mass()*m_dFillingTime;//kg Prod.SetM(Liquor, MP_All, d); // les valeurs dans PrecipResult ne sont plus des debits mais des volumes et des masses; // todo !!!!! reduire la temperature du filtrat et Flash } double ProdSSurf; MassFrac2HyprodDist(SizeClass, ProdPSD, ProdHyPsd, NIntervals, ProdSSurf); //gets PSD for 1 gpl double target = m_dLevel; //add seed until specified level (filling tank) while (iLevel < target) { double dt = 36.0; //seconds if ( (iLevel + Slurry.Volume()*dt/(m_dVolume*m_dLevel)) > target ) dt = fabs( (target-iLevel) * (m_dVolume*m_dLevel) / Slurry.Volume()); if (dt>0.0000001) { iLevel += (Slurry.Volume()*dt/(m_dVolume*m_dLevel)); //MixBatch... HyprodDist2MassFrac(SizeClass, ProdHyPsd, ProdPSD, NIntervals); Prod.AddM(Slurry, MP_All, Slurry.Mass()*dt); MassFrac2HyprodDist(SizeClass, ProdPSD, ProdHyPsd, NIntervals, ProdSSurf); //gets PSD for 1 gpl //precip reaction... if (ProdB.SolidsConc(C2K(25.0))>5.0) // need a minimum solid conc. to precipitate if (sm_bCompletePopulation) { if (!PrecipBatch(dt, Prod, iLevel,m_bAgglomONwhileFilling))// with population balance return false; } else { if (!PrecipBatchSS(dt, Prod, iLevel))// with SSA return false; } //application.processMessages; //if flowsheet.UserCancel then // break; } else iLevel = target; }//end while //precip reaction (tank is full) double DummyProdNNtl; CalcSSurgNNtl(SizeClass, ProdHyPsd, NIntervals, ProdSSurf, DummyProdNNtl); double PrecipRate = get_PrecipRate(Prod, ProdSSurf); //!! THE LOOP IS CALCULT. ONLY if PRECIP HAPPENS double Btime=0.0; if (PrecipRate<0.0) while (Btime < m_dCirculationTime ) { PrecipRate = get_PrecipRate(Prod, ProdSSurf); if (sm_bCompletePopulation) dt = -0.2/PrecipRate; else dt = -0.5/PrecipRate; if ( (Btime+dt) > m_dCirculationTime) dt = m_dCirculationTime - Btime; Btime += dt; if (sm_bCompletePopulation) { if (!PrecipBatch(dt, Prod, iLevel, true))// with population balance return false; } else { if (!PrecipBatchSS(dt, Prod, iLevel))// with SSA return false; if (sm_bUsePrevPSD) { //SetPSDfromPrev(Prod); } } //application.processMessages; //if flowsheet.UserCancel then // break; } Prod.AdjustMassTo(MP_All, SlurryTtlMassFlow+LiquorTtlMassFlow); HyprodDist2MassFrac(SizeClass, ProdHyPsd, ProdPSD, NIntervals); } return true; } //BatchCycle
//{****************************************************************************} // THIS function perfrom the same role as MASSBALANCE for the continuous precipitator double BatchPrecip::PerformAluminaSolubility(MVector & Vec, double TRqd, double ARqd, double THARqd, double NoPerSec, double Na2OFac, double SSat, bool & ConvergeErr) { // 2 AlO2 + 4 H2O <==> Al2O3.3H2O + 2 OH //or Na2O + Al2O3 + 4 H2O <==> Al2O3.3H2O + 2 NaOH // THADelta is the Fraction of Alumina which precipitates as the hydrate // ie THADelta is deposition rate of new THA crystal const double ESoda=2335.0; //constant 2535K bool AdjustT=!Valid(TRqd); bool SetTHA=Valid(THARqd); double T=AdjustT ? Vec.T : TRqd; MVDouble AluminaMass (Vec, spAlumina); // Al2O3 MVDouble WaterMass (Vec, spWater); // H2O MVDouble THAMass (Vec, spTHA); // Al2O3.3H2O MVDouble CausticMass (Vec, spCausticSoda); // NaOH MVDouble Na2OMass (Vec, spOccSoda); // Na2O const double Fact = spAlumina.MW/spTHA.MW; // 0.654; MIBayer & BVec=*Vec.GetIF<MIBayer>(); for (int Iter=100; Iter; Iter--) { if (AdjustT) T=Vec.T; double CC= BVec.CausticConc(C2K(25.0)); double A=BVec.AluminaConc(C2K(25.0)); double THA=BVec.SolidsConc(T); double THADelta; if (SetTHA) { if (fabs(THA-THARqd)<1.0e-12*THARqd) break; THADelta = THAMass*(THARqd/GTZ(THA)-1.0); } else { if (fabs(A-ARqd)<1.0e-12*ARqd) break; THADelta = AluminaMass*(1.0-ARqd/GTZ(A))/Fact; } double alumSSat = CC *SSat; const double LclVar = Na2OFac*7.1868e-8*exp(ESoda/T)*Pow(alumSSat, 1.0955); double XSoda = THADelta*LclVar; double dAluminaMass = - Fact*THADelta; double dTHAMass = + THADelta; double dWaterMass = - (1.0-Fact)*THADelta + spWater.MW/spOccSoda.MW*XSoda; double dCausticMass = - 2.0*spCausticSoda.MW/spOccSoda.MW*XSoda; double dNa2OMass = + XSoda; double Scl; for(;;) { Scl=1; if (AluminaMass + Scl*dAluminaMass <0) Scl=Min(Scl, 1-(AluminaMass + Scl*dAluminaMass)/NZ(dAluminaMass)); if (THAMass + Scl*dTHAMass <0) Scl=Min(Scl, 1-(THAMass + Scl*dTHAMass)/NZ(dTHAMass)); if (WaterMass + Scl*dWaterMass <0) Scl=Min(Scl, 1-(WaterMass + Scl*dWaterMass)/NZ(dWaterMass)); if (CausticMass + Scl*dCausticMass <0) Scl=Min(Scl, 1-(CausticMass + Scl*dCausticMass)/NZ(dCausticMass)); if (Na2OMass + Scl*dNa2OMass <0) Scl=Min(Scl, 1-(Na2OMass + Scl*dNa2OMass)/NZ(dNa2OMass)); if (Scl<(1-1e-12)) { dAluminaMass *= Scl; dTHAMass *= Scl; dWaterMass *= Scl; dCausticMass *= Scl; dNa2OMass *= Scl; } else break; } if (fabs(dAluminaMass)<1e-22) {//problem!!! Iter=0; break; } //adjust masses... AluminaMass = AluminaMass + dAluminaMass; THAMass = THAMass + dTHAMass; WaterMass = WaterMass + dWaterMass; CausticMass = CausticMass + dCausticMass; Na2OMass = Na2OMass + dNa2OMass; Vec.MarkStateChanged(); //this forces recalculation of temperature / enthalpy based on new stream makeup } ConvergeErr = (Iter==0); Log.SetCondition(ConvergeErr, 9, MMsg_Warning, "Cannot converge PrecipTHA Alumina Conc"); if (ConvergeErr) { int xx=0; //place breakpoint here to trap this } MISSA & VecSSA=*Vec.GetIF<MISSA>(); if (NoPerSec>0.0 && !IsNothing(VecSSA)) { VecSSA.SetSAMFromFlow(BVec.THAMassFlow(), NoPerSec); } return BVec.AluminaConc(T); }
void BatchPrecip::EvalProducts() { #if ForceOptimizeOff static Cnt = 0; if (stricmp(getTag(), "SpeciauxUE")==0) { Cnt++;//place breakpoint here to stop for specified model } #endif if (!IsSolveDirect)//(!IsProbal) return; bool Err = true; try { MStreamI Slurry; MStreamI Liquor; FlwIOs.AddMixtureIn_Id(Slurry, idSlurry); //sum all input slurry streams m_bHasLiquor = (FlwIOs.First[idLiquor]>=0); //test if liquor stream connected if (m_bHasLiquor) { FlwIOs.AddMixtureIn_Id(Liquor, idLiquor); //sum all input liquor streams //double LiquorSolids = Liquor.Mass(); } MStream & Prod = FlwIOs[FlwIOs.First[idDrawOff]].Stream; //get a reference to the single output stream Prod = Slurry; //set output stream = input stream (including PSD data, etc) m_dThermalLoss = 0.0; m_dYield = 0.0; m_dTempIn = Slurry.T; MIBayer & SlurryB = *Slurry.FindIF<MIBayer>(); //get access to bayer properties interface for stream if (!IsNothing(SlurryB)) { m_dACIn = SlurryB.AtoC(); m_dSolidConcIn = SlurryB.SolidsConc(C2K(25.0)); } else { m_dACIn = 0.0; m_dSolidConcIn = 0.0; } if (m_bOn && Slurry.Mass()>UsableMass) { MIBayer & ProdB = *Prod.FindIF<MIBayer>(); Log.SetCondition(IsNothing(ProdB), 1, MMsg_Warning, "Bad Slurry Stream - Not Bayer Model"); //expect stream to have bayer properties if (!IsNothing(SlurryB) && !IsNothing(ProdB)) { // --- --- Thermal Losses. ------------ // !! this should be done COMBINED with FLAHSING/evaporation as the Caustic concentration should increase Slurry.SetTP(Slurry.T -m_dFillingTempDrop, Slurry.P); Liquor.SetTP(Liquor.T -m_dFillingTempDrop, Liquor.P); double SlurryH0 = Slurry.totHf(MP_All, Slurry.T, Slurry.P); double LiquorH0 = (m_bHasLiquor ? Liquor.totHf(MP_All, Liquor.T, Liquor.P) : 0.0); //Prod.SetTemp(Prod.Temp()-m_dTempDrop); RunSteady(Slurry, Liquor, Prod); m_dThermalLoss = (SlurryH0+LiquorH0)-Prod.totHf(MP_All, Prod.T, Prod.P); m_dACOut = ProdB.AtoC(); m_dSolidConcOut = ProdB.SolidsConc(C2K(25.0)); //m_dResTime = TankVol/GTZ(Prod.Volume(som_SL)); double Cout = ProdB.CausticConc(Prod.T); m_dYield = Cout*(m_dACIn-m_dACOut); } if (sm_bCompletePopulation) m_QProd = Prod;//copy the content of the stream in the equipement only if STILL in Pop mode } else { if (m_bHasLiquor) { Prod.AddF(Liquor, MP_All, 1.0); } MIBayer & ProdB = *Prod.FindIF<MIBayer>(); if (!IsNothing(ProdB)) { m_dACOut = ProdB.AtoC(); m_dSolidConcOut = ProdB.SolidsConc(C2K(25.0)); } else { m_dACOut = 0.0; m_dSolidConcOut = 0.0; } } m_dTempOut = Prod.T; Err = false; } catch (MMdlException &e) { Log.Message(MMsg_Error, e.Description); } catch (MFPPException &e) { e.ClearFPP(); Log.Message(MMsg_Error, e.Description); } catch (MSysException &e) { Log.Message(MMsg_Error, e.Description); } catch (...) { Log.Message(MMsg_Error, "Some Unknown Exception occured"); } if (Err) {//Something is wrong!!! Bug needs fixing!!! //So lets set product=feed.... MStreamI Feed; MStream & Prod = FlwIOs[FlwIOs.First[idDrawOff]].Stream; //get a reference to the single output stream FlwIOs.AddMixtureIn_Id(Feed, idSlurry); //sum all input slurry streams Prod = Feed; if (FlwIOs.First[idLiquor]>=0) { MStreamI Liquor; FlwIOs.AddMixtureIn_Id(Liquor, idLiquor); //sum all input liquor streams Prod.AddF(Liquor, MP_All, 1.0); } CString ProblemModel; ProblemModel = getTag(); //SetStopRequired("Phone Denis!"); } Log.SetCondition(Err, 5, MMsg_Error, "Error needs fixing!!!"); }
void CPrecipitator::EvalProducts() { try { x[0] = x[1] = x[2] = x[3] = 0.0; m_dPrevFlow = m_dExtCoolVolFlow; FlwIOs.AddMixtureIn_Id(Feed, idFeed); MStream & Prod = FlwIOs[FlwIOs.First[idProd]].Stream; //Reference to the output stream //optional connections... const int iCoolInIndex = FlwIOs.First[idCoolI]; const int iCoolOutIndex = FlwIOs.First[idCoolO]; const int iEvapIndex = FlwIOs.First[idEvap]; bCoolIn = (iCoolInIndex>=0); bCoolOut = (iCoolOutIndex>=0); m_bEvapConnected = (iEvapIndex>=0); // MStream CoolIn; // MStream &CoolOut = FlwIOs[FlwIOs.First[idCoolO]].Stream; // MStream &Evap1 = FlwIOs[FlwIOs.First[idEvap]].Stream; Evap.SetF(Feed, MP_All, 0.0); Prod = Feed; Log.SetCondition(iCoolType && (!bCoolIn || !bCoolOut), 3, MMsg_Error, "Bad External cooling connections"); if (iCoolType==COOL_EXTERNAL && bCoolIn && bCoolOut) { FlwIOs.AddMixtureIn_Id(CoolIn, idCoolI); MStream &CoolOut = FlwIOs[iCoolOutIndex].Stream; if (Valid(CoolIn.T) && fabs(CoolIn.Mass())>1.0e-5 && fabs(CoolIn.Mass())>1.0e-5) { m_dExtCoolTemp = CoolIn.T; // The temperature of the return stream // m_dExtCoolRate = CoolOut.totHz()-CoolIn.totHz(); m_dExtCoolRate = m_dCoolOutTotHz-CoolIn.totHz(); // CoolingSanityCheck(); } else { m_dExtCoolRate = 0.0; m_dExtCoolTemp = Feed.T; } } if (iCoolType==COOL_INTERNAL && bCoolIn) { FlwIOs.AddMixtureIn_Id(CoolIn, idCoolI); } m_dHIn = Feed.totHz(); dThermalLoss = 0.0; dYield = 0.0; dSALin = 0.0; dDiamin = 0.0; bool streamOK = true; MIBayer & ProdB=Prod.IF<MIBayer>(false); // Do the checks up front Log.SetCondition(IsNothing(ProdB), 1, MMsg_Warning, "Bad Feed Stream - Not Bayer Model"); MISSA & ProdSSA = Prod.IF<MISSA>(false); Log.SetCondition(IsNothing(ProdSSA), 1, MMsg_Warning, "Bad Feed Stream - No SSA Available"); if (IsNothing(ProdB) || IsNothing(ProdSSA)) streamOK = false; dSALin = ProdSSA.SpecificSurfaceAreaVol(); // m^2/L dDiamin = ProdSSA.PartDiamFromSAM(); m_dSSAin = ProdSSA.SpecificSurfaceAreaMass(); if (bOnLine && streamOK) { // Online and have Bayer and SSA properties... DoPrecip(Prod); if (iCoolType==COOL_EXTERNAL && bCoolOut) { MStream &CoolOut = FlwIOs[iCoolOutIndex].Stream; double den = Prod.Density(); if (m_bByVolFlow) { m_dExtCoolFlow = (1-m_dVolDamping)*m_dExtCoolVolFlow*den + m_dVolDamping*m_dPrevFlow; m_dPrevFlow = m_dExtCoolFlow; } else m_dExtCoolVolFlow = m_dExtCoolFlow/den; CoolOut.SetM(Prod, MP_All, m_dExtCoolFlow); m_dCoolOutTotHz = CoolOut.totHz(); } if (iCoolType==COOL_INTERNAL && bCoolOut && bCoolIn && iCoolMethod==COOL_Hx) { MStream &CoolOut = FlwIOs[iCoolOutIndex].Stream; CoolOut.SetF(CoolIn, MP_All, 1.0); if (m_bCoolerOn) CoolOut.T = m_dCoolWaterTout; else CoolOut.T = CoolIn.T; } DoResults(Prod); Evap.T = Prod.T; if (m_bEvapConnected) { MStream &Evap1 = FlwIOs[iEvapIndex].Stream; Evap1 = Evap; } // Evap1 = Evap; // Evap1.T = Prod.T; m_dHEvap = Evap.totHz(); m_dHOut = Prod.totHz(); m_dHBal = m_dHIn - m_dHEvap - m_dHOut; dTout = Prod.T; dTin = Feed.T; } else { // Just tidy up and put some sensible stuff in the results... dTin = Feed.T; dTout = dTin; dACin = (IsNothing(ProdB) ? 0.0 : ProdB.AtoC()); dACout = dACin; dReactionHeat = 0.0; dResidenceTime = 0.0; dYield = 0.0; dTHAPrecip = 0.0; dSolPrecip = 0.0; if (iCoolType==COOL_INTERNAL && bCoolOut && bCoolIn && iCoolMethod==COOL_Hx) { MStream &CoolOut = FlwIOs[iCoolOutIndex].Stream; CoolOut.SetF(CoolIn, MP_All, 1.0); CoolOut.T = CoolIn.T; m_dCoolWaterTout = CoolIn.T; m_dCoolRate = 0.0; } } } catch (MMdlException &e) { Log.Message(MMsg_Error, e.Description); } catch (MFPPException &e) { e.ClearFPP(); Log.Message(MMsg_Error, e.Description); } catch (MSysException &e) { Log.Message(MMsg_Error, e.Description); } catch (...) { Log.Message(MMsg_Error, "Some Unknown Exception occured"); } }