int CPrecipPSD::CalcAgglomCoeff(double *x, double *akf, long *npts, double *aggl_coeff__) { long i__1; double d__1; // Builtin functions double exp(double), pow_dd(double , double ); double xend; long i; double d1, d2; // ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc // // i counter in do loop // akf agglomeration parameter // d1 agglomeration parameter // d2 agglomeration parameter // xend agglomeration parameter // ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc // // Parameter adjustments --aggl_coeff__; --akf; --x; // Function Body d1 = akf[1]; d2 = akf[2]; xend = akf[3]*1e6; i__1 = *npts; for(i = 1; i <= i__1; ++i) { if(x[i] <= xend) { aggl_coeff__[i] = 1.; } else { aggl_coeff__[i] = 0.; } if(d1 != 0.) { aggl_coeff__[i] *= Exps(-x[i] / d1); } if(d2 != 0.) { d__1 = x[i] / d2; aggl_coeff__[i] *= Exps(-pow_dd(d__1, c_b4)); } } return 0; } // CalcAgglomCoeff
double CSeperator_EfficiencyCurve::CalcBetaStar(double in_Alpha, double in_Beta ) { double BetaStar = 1.0 - in_Beta; double PN = (1.0 + in_Beta*BetaStar) * (Exps(in_Alpha) - 1.0) / (Exps(in_Alpha*BetaStar) + Exps(in_Alpha) - 2.0); //Partition Number int iter = 0; const int MaxIter = 100; const double Tol = 1.0e-4; while (iter++<MaxIter) { BetaStar += (BetaStar*(PN-0.5)/10.0); //update estimate of BetaStar PN = (1.0 + in_Beta*BetaStar) * (Exps(in_Alpha) - 1.0) / (Exps(in_Alpha*BetaStar) + Exps(in_Alpha) - 2.0); //Recalc Partition Number if (fabs(PN-0.5)<Tol) break; } //if (iter>=MaxIter) // LogError(Tag(), 0, "Unable to calculate BetaStar!"); return BetaStar; }
int CPrecipPSD::DistSauter(double *psd, double *l32, long *npts, double *x) { long i__1; // Builtin functions double exp(double); long i; double mom0; // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc // // npts number of points in discretization of psd // x midpoints of discretization // i counter in do loop // L32 Sauter mean diameter // mom0 0th moment // psd particle size distribution // ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc // // Functions Used // Moment Calculates moments from psd // ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc // // Parameter adjustments --x; --psd; // Function Body i__1 = *npts; for(i = 1; i <= i__1; ++i) { psd[i] = x[i] * Exps(x[i] * -3. / *l32); // note interval prop to x } mom0 = Moment(&psd[1], 0, npts, &x[1]); i__1 = *npts; for(i = 1; i <= i__1; ++i) { psd[i] /= mom0; // normalize } return 0; } // DistSauter
//--------------------------------------------------------------------------- // All the precipitation rate calcs are done in this routine // Takes the product composition and calculates rates from this // Rates (in kg/s) are put into global x //--------------------------------------------------------------------------- void CPrecipitator::EvalPrecipRates(MStream & Prod, double T) { T = Prod.T; // May want to do the rate calculation at other temperature MIBayer & ProdB=Prod.IF<MIBayer>(false); MISSA & ProdSSA = Prod.IF<MISSA>(false); dResidenceTime = dTankVol/GTZ(Prod.Volume(MP_SL)); for (int i=0; i<nPRECIPCOMPS; i++) xo[i]=x[i]; // Save old values for convergence test, damping double SAL = ProdSSA.SpecificSurfaceAreaVol(); double SSA = ProdSSA.SpecificSurfaceAreaMass(); double dSSat; if (ProdB.CausticConc(T) > 0) dSSat = (ProdB.AluminaConc(T)-ProdB.AluminaConcSat(T))/ProdB.CausticConc(T); else dSSat = 0.0; if (dSSat < 0) dSSat=0.0; // Supersaturation... switch (iGrowthRateMethod) { case GRM_Fixed: x[iALUMINA] = dGrowthRate; x[1] = x[iBOUND_ORGANICS] = 0.0; break; case GRM_White: { MIBayer & FeedB = Feed.IF<MIBayer>(false); double Ain = FeedB.AluminaConc(T); double Aout = ProdB.AluminaConc(T); dGrowthRateFactor = gF_White*K_White*Exps(-ER_White/T); dGrowthRate = dGrowthRateFactor*Sqr(dSSat); x[iALUMINA] = dGrowthRate*SAL*dTankVol/1000.; double sodaRate = m_dK_Soda*Sqr(dSSat)*Exps(m_dE_Soda/T)*(Aout - Ain)*dTankVol/1000.; if (sodaRate <0.0) sodaRate = 0.0; x[iBOUND_SODA] = sodaRate*(1.0-m_dBndOrgSoda); x[iBOUND_ORGANICS] = sodaRate*m_dBndOrgSoda; } break; case GRM_TTTest: { // Alumina Precipitation.... as per QPRECIPD.cpp MIBayer & FeedB = Feed.IF<MIBayer>(false); double C = ProdB.CausticConc(T); double C25 = ProdB.CausticConc(C2K(25)); double CtoS = ProdB.CtoS(); double S_out = C25/CtoS; // double FC = ProdB.FreeCaustic(T); double FC = ProdB.FreeCaustic(C2K(25)); double ACeq = ProdB.AluminaConcSat(T)/C25; double TOOC=ProdB.TOC(C2K(25))*MW_Na2CO3/MW_C; double a=Exps(-m_dActivationEnergy/T); double b=Exps(-TOOC*m_dk_TOC); double c=Pow(GTZ(S_out), m_dn_s); double d=Pow(GTZ(FC), m_dn_fc); double e=Pow(GTZ(ACeq), m_dn_eq); double K = m_dK0*a*b*c*d*e; double ACout = ProdB.AtoC(); double VLiq = Prod.Volume()*3600.; double MSolids = Prod.MassVector[spTHA]*3600.0/1000.0; double Sol = MSolids*1000.0/GTZ(VLiq); double deltaAC = K * dResidenceTime/3600 * Pow(GTZ(ACout-ACeq),m_dn_) * Pow(GTZ(Sol),m_dn_sol) * Pow(GTZ(m_dSSA),m_dn_ssa); double ACoutEst = dACin - deltaAC; double VolOut = Prod.Volume(MP_Liq, C2K(25.0)); double xx = deltaAC*C25*VolOut*2*MW_Alumina/MW_Al2O3; if (xx<0.0) xx=0.0; x[iALUMINA] = xx; // Bound Soda calculations... slurped from QAL file double k1x = m_dK1 * (0.000598*C25 - 0.00036*K2C(T) + 0.019568*TOOC/C) * (1.0 - 0.758*CtoS); double BoundSoda = k1x * Sqr(ACoutEst-ACeq); if (x[iALUMINA]>=0.0) { double BndSoda = BoundSoda*(x[iALUMINA]*MW_Al2O3/(2.0*MW_THA))*(1.0-m_dBndOrgSoda)*((2.0*MW_NaOH)/MW_Na2O); double BndOrgSoda = BoundSoda*(x[iALUMINA]*MW_Al2O3/(2.0*MW_THA))*(m_dBndOrgSoda)*(MW_OrganicSoda/MW_Na2O); /* If represented as Na2O double BndSoda = BoundSoda*GibbsRate*dBndOrgSoda; double BndOrgSoda = BoundSoda*GibbsRate*(1.0-dBndOrgSoda); */ x[iBOUND_SODA] = BndSoda; x[iBOUND_ORGANICS] = BndOrgSoda; } } break; } return; }