void CLimnStream::ConvertToFracForm(MVector & M, bool ApplyScale) { if (!m_bIsMassForm) return; if (DoDbgCvt) Dump("ConvertToFracForm:Before", DoDbgCvt); MArrayI Tot; // Current Total for (int ii=0; ii<gs_DWCfg.m_SeqIndex.GetCount(); ii++) { int i=gs_DWCfg.m_SeqIndex[ii]; Tot[gs_DWCfg.m_SpIds[i]] += m_Data[i]; }; if (ApplyScale) { for (int id=0; id<gs_MVDefn.Count(); id++) { M.M[id]=Tot[id]/gs_DWCfg.m_MassFactor[id]; Tot[id]=GTZ(Tot[id]); } M.MarkStateChanged(); } else { for (int id=0; id<gs_MVDefn.Count(); id++) { M.M[id]=Tot[id]; Tot[id]=GTZ(Tot[id]); } M.MarkStateChanged(); } for (int ii=0; ii<gs_DWCfg.m_SeqIndex.GetCount(); ii++) { int i = gs_DWCfg.m_SeqIndex[ii]; m_Data[i] = m_Data[i]/Tot[gs_DWCfg.m_SpIds[i]]; }; m_bIsMassForm = false; if (DoDbgCvt) Dump("ConvertToFracForm:After", DoDbgCvt); };
//{****************************************************************************} // 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); }