Beispiel #1
0
	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);

        }
	
	}
Beispiel #2
0
  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;
  }
Beispiel #3
0
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");
    }
}
Beispiel #4
0
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
}
Beispiel #5
0
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");
    }
}
Beispiel #6
0
	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);
Beispiel #7
0
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
Beispiel #8
0
//{****************************************************************************}
//  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);
  }
Beispiel #9
0
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!!!");
  }
Beispiel #10
0
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");
    }
  }