예제 #1
0
void CPrecipitator::DoResults(MStream & Prod)
{
  MIBayer & FeedB=Feed.IF<MIBayer>(false);
  MIBayer & ProdB=Prod.IF<MIBayer>(false);
  

  dACin   = FeedB.AtoC();
  dACout = ProdB.AtoC();
  dQvin   = Feed.Volume();
  dQvout   = Prod.Volume();
  dQmin = Feed.Mass();
  dQmout = Prod.Mass();

  double dQvout25 = Prod.Volume(MP_All, C2K(25));
  double Cout    = ProdB.CausticConc(Prod.T);
  m_dACeq = ProdB.AluminaConcSat(Prod.T)/ProdB.CausticConc(C2K(25));
  m_dSSat = ProdB.AtoC()/m_dACeq;
  dYield         = Cout*(dACin-dACout);

  double SolIn = Feed.MassVector[spTHA];
  double SolOut  = Prod.MassVector[spTHA];
  dTHAPrecip     = SolOut - SolIn;
  SolIn = Feed.Mass(MP_Sol);
  SolOut = Prod.Mass(MP_Sol);
  dSolPrecip = SolOut - SolIn;
  dSolConc = Prod.Mass(MP_Sol)/dQvout25;
  m_dLiquorTin = Prod.T;
}
예제 #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;
  }
예제 #3
0
bool BatchPrecip::ValidateDataFields()
  {//ensure parameters are within expected ranges
  m_dVolume  = DV.ValidateRange("Volume", 1.0, m_dVolume, 1000000);
  m_dSurface = DV.ValidateRange("Surface", 1.0, m_dSurface, 300000);
  m_dKvFac   = DV.ValidateRange("KvFac", 0.0, m_dKvFac, 30);
  m_dUCoef   = DV.ValidateRange("UCoef", 0.0, m_dUCoef, 2000);
  m_dLevel   = DV.ValidateRange("Level", 0.01, m_dLevel, 1);
  
  if ( m_eHeatBalance == eHBal_ImposedTemp)
    m_dTempImpos = DV.ValidateRange("TempImposed", C2K(1.0e-6), m_dTempImpos, C2K(150.0));

  return true;
  }
예제 #4
0
CoolingTower::CoolingTower(pTagObjClass pClass_, pchar TagIn, pTaggedObject pAttach, TagObjAttachment eAttach) :
  MN_Surge(pClass_, TagIn, pAttach, eAttach)
  {
  AttachIOAreas(CoolingTowerIOAreaList, &PipeEntryGroup);
  Contents.SetClosed(true);
  Contents.SetPreset(&m_Preset, &m_PresetImg);

  iMethod          = CTM_Merkel;
  iMerkelCalcType  = MCT_TOut;
  iLossMethod      = WLM_DriftBlowdown;
  dAirWetBulbT     = C2K(30.0);   
  dApproachT       = 5.0;     
  dKaVL            = 1.5;
  dLGRatio         = 0.98;
  dDriftLossFrac   = 0.002;
  dEvapFactor      = 0.00085;
  iCycles          = 5;
  dRqdLossFrac     = 0.02;
  dRqdLossQm       = 10.0;
  dRqdDriftLossFrac= 0.05;
  dMaxEvapFrac     = 1.0;
  dAirCp           = 0.98;
  dAirDryBulbT     = C2K(25.0);
  
  dQmIn            = 0.0;
  dAirQmIn         = 0.0;
  dTempKFeed       = Std_T;
  dFinalP          = Std_P;
  dFinalT          = dAirWetBulbT;
  dTempDrop        = 0.0;
  dHeatFlow        = 0.0;
  dDuty            = 0.0;
  dEvapFrac        = 0.0;
  dQmWaterEvap     = 0.0;
  dDriftLossQm     = 0.0;
  dBlowdownLossQm  = 0.0;
  dEvapLossQm      = 0.0;
  dLossQm          = 0.0;
  dTotalLossQm     = 0.0;
  dAirEnthOut      = 0.0;
  dAirTOut         = dAirWetBulbT;
  dAirTRise        = 0.0;
  dAirMixQm        = 0.0;
  dAirMixCp        = 0.0;
  dAirMixT         = dAirWetBulbT;

  //EHX.Open(&CEHX_LossPerQmClass);
  m_VLE.Open(NULL, true);
  }
/*
 * Name : d2199_get_soc
 */
static int d2199_get_soc(struct sec_fuelgauge_info *fuelgauge)
{
	int soc;

	if((!fuelgauge) || (!fuelgauge->info.volt_adc_init_done)) {
		pr_err("%s. Invalid parameter. \n", __func__);
		return -EINVAL;
	}

	if(fuelgauge->info.soc)
		fuelgauge->info.prev_soc = fuelgauge->info.soc;

	soc = adc_to_soc_with_temp_compensat(fuelgauge->info.average_volt_adc,
					     C2K(fuelgauge->info.average_temperature));

	if(soc >= FULL_CAPACITY) {
		soc = FULL_CAPACITY;
		if(fuelgauge->info.virtual_battery_full == 1) {
			fuelgauge->info.virtual_battery_full = 0;
			fuelgauge->info.soc = FULL_CAPACITY;
		}
	}

	/* Don't allow soc goes up when battery is dicharged.
	 and also don't allow soc goes down when battey is charged. */
	if(fuelgauge->is_charging != TRUE
	   && (soc > fuelgauge->info.prev_soc)
	   && fuelgauge->info.prev_soc) {
		soc = fuelgauge->info.prev_soc;
	}
	else if(fuelgauge->is_charging
		&& (soc < fuelgauge->info.prev_soc)
		&& fuelgauge->info.prev_soc) {
		soc = fuelgauge->info.prev_soc;
	}
	fuelgauge->info.soc = soc;

	adc_write_reg(fuelgauge, D2199_GP_ID_2_REG, (0xFF & soc));
	adc_write_reg(fuelgauge, D2199_GP_ID_3_REG, (0x0F & (soc>>8)));

	adc_write_reg(fuelgauge, D2199_GP_ID_4_REG,
		      (0xFF & fuelgauge->info.average_volt_adc));
	adc_write_reg(fuelgauge, D2199_GP_ID_5_REG,
		      (0xF & (fuelgauge->info.average_volt_adc>>8)));

	return soc;
}
예제 #6
0
void CEC_FinalConc::Parse(CRCTTokenFile &TF)
  {
  Clear();
  ParseExtent(TF);
  m_Spc.m_Name=TF.NextToken();
  TF.CheckToken("=");
  m_ddRqdConc.SetVal(GEZ(TF.DoubleToken()), &Eq);
  m_iFReactTerm=-1;
  m_iFProdTerm=-1;
  if (TF.TokenIs("At"))
    {
    m_dRqdTemp=GEZ(C2K(TF.DoubleToken()));
    if (TF.TokenIs("K"))
      m_dRqdTemp=K2C(m_dRqdTemp);
    }
  //ParseDynamic(TF);
  };
예제 #7
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");
    }
}
static int d2199_read_voltage(struct sec_fuelgauge_info *fuelgauge)
{
	int new_vol_adc, base_weight, new_vol_orign = 0;
	int offset_with_new = 0;
	int ret = 0;
	//static int calOffset_4P2, calOffset_3P4 = 0;
	int num_multi = 0;
	int orign_offset = 0;
	u8  ta_status = 0;

	if(fuelgauge->info.volt_adc_init_done == FALSE ) {
		ta_status = adc_read_reg(fuelgauge, D2199_STATUS_C_REG);
		pr_debug("%s. STATUS_C register = 0x%X\n", __func__, ta_status);
		if(ta_status & D2199_GPI_3_TA_MASK)
			fuelgauge->is_charging = 1;
		else
			fuelgauge->is_charging = 0;
	}
	pr_debug("##### is_charging mode = %d\n", fuelgauge->is_charging);

	// Read voltage ADC
	ret = fuelgauge->info.d2199_read_adc(fuelgauge, D2199_ADC_VOLTAGE);

	pr_debug("[%s]READ_EOC = %d\n", __func__,
		fuelgauge->info.adc_res[D2199_ADC_VOLTAGE].is_adc_eoc);
	pr_debug("[%s]READ_ADC = %d\n", __func__,
		fuelgauge->info.adc_res[D2199_ADC_VOLTAGE].read_adc);

	if(ret < 0)
		return ret;

	if(fuelgauge->info.adc_res[D2199_ADC_VOLTAGE].is_adc_eoc) {
		int offset = 0;

		new_vol_orign = new_vol_adc = fuelgauge->info.adc_res[D2199_ADC_VOLTAGE].read_adc;

		if(fuelgauge->info.volt_adc_init_done) {
			// Initialization is done

			if(fuelgauge->is_charging) {
				// In case of charge.
				orign_offset = new_vol_adc - fuelgauge->info.average_volt_adc;
				base_weight = d2199_get_weight_from_lookup(
									C2K(fuelgauge->info.average_temperature),
									fuelgauge->info.average_volt_adc,
									fuelgauge->is_charging,
									orign_offset);
				offset_with_new = orign_offset * base_weight;

				fuelgauge->info.sum_total_adc += offset_with_new;
				num_multi = fuelgauge->info.sum_total_adc / NORM_CHG_NUM;
				if(num_multi) {
					fuelgauge->info.average_volt_adc += num_multi;
					fuelgauge->info.sum_total_adc = fuelgauge->info.sum_total_adc
																% NORM_CHG_NUM;
				} else {
					new_vol_adc = fuelgauge->info.average_volt_adc;
				}

				fuelgauge->info.current_volt_adc = new_vol_adc;
			} else {
				// In case of discharging.
				orign_offset = fuelgauge->info.average_volt_adc - new_vol_adc;
				base_weight = d2199_get_weight_from_lookup(
									C2K(fuelgauge->info.average_temperature),
									fuelgauge->info.average_volt_adc,
									fuelgauge->is_charging,
									orign_offset);
				offset_with_new = orign_offset * base_weight;

				if(fuelgauge->info.reset_total_adc) {
					fuelgauge->info.sum_total_adc =
											fuelgauge->info.sum_total_adc / 10;
					fuelgauge->info.reset_total_adc = 0;
					pr_debug("%s. sum_toal_adc was divided by 10\n", __func__);
				}

				fuelgauge->info.sum_total_adc += offset_with_new;
				pr_debug("Discharging. Recalculated base_weight = %d\n", base_weight);

				num_multi = fuelgauge->info.sum_total_adc / NORM_NUM;
				if(num_multi) {
					fuelgauge->info.average_volt_adc -= num_multi;
					fuelgauge->info.sum_total_adc =
										fuelgauge->info.sum_total_adc % NORM_NUM;
				} else {
					new_vol_adc = fuelgauge->info.average_volt_adc;
				}

				if(is_called_by_ticker == 0) {
					fuelgauge->info.current_volt_adc = new_vol_adc;
				} else {
					fuelgauge->info.current_volt_adc = new_vol_adc;
					is_called_by_ticker=0;
				}
			}
		} else {
			// Before initialization
			u8 i = 0;
			u8 res_msb, res_lsb, res_msb_adc, res_lsb_adc = 0;
			u32 capacity = 0, vbat_adc = 0;
			int convert_vbat_adc, X1, X0;
			int Y1, Y0 = FIRST_VOLTAGE_DROP_ADC;
			int X = C2K(fuelgauge->info.average_temperature);

			// If there is SOC data in the register
			// the SOC(capacity of battery) will be used as initial SOC
			res_lsb = adc_read_reg(fuelgauge, D2199_GP_ID_2_REG);
			res_msb = adc_read_reg(fuelgauge, D2199_GP_ID_3_REG);
			capacity = (((res_msb & 0x0F) << 8) | (res_lsb & 0xFF));

			res_lsb_adc = adc_read_reg(fuelgauge, D2199_GP_ID_4_REG);
			res_msb_adc = adc_read_reg(fuelgauge, D2199_GP_ID_5_REG);
			vbat_adc = (((res_msb_adc & 0x0F) << 8) | (res_lsb_adc & 0xFF));

			pr_debug("%s. capacity = %d, vbat_adc = %d \n", __func__,
															capacity,
															vbat_adc);

			if(capacity) {
					convert_vbat_adc = vbat_adc;
				pr_info("!#!#!# Boot BY Normal Power Off !#!#!# \n");
			} else {
				// Initial ADC will be decided in here.
				pr_info("!#!#!# Boot BY Battery insert !#!#!# \n");

			fuelgauge->info.pd2199->average_vbat_init_adc =
								(fuelgauge->info.pd2199->vbat_init_adc[0] +
								 fuelgauge->info.pd2199->vbat_init_adc[1] +
								 fuelgauge->info.pd2199->vbat_init_adc[2]) / 3;

				vbat_adc =	fuelgauge->info.pd2199->average_vbat_init_adc;
				pr_debug("%s (L_%d). vbat_init_adc = %d, new_vol_orign = %d\n",
								__func__, __LINE__,
								fuelgauge->info.pd2199->average_vbat_init_adc,
								new_vol_orign);

			if(fuelgauge->is_charging) {
					if(vbat_adc < CHARGE_ADC_KRNL_F) {
						// In this case, vbat_adc is bigger than OCV
						// So, subtract a interpolated value
						// from initial average value(vbat_adc)
						u16 temp_adc = 0;

						if(vbat_adc < CHARGE_ADC_KRNL_H)
							vbat_adc = CHARGE_ADC_KRNL_H;

						X0 = CHARGE_ADC_KRNL_H;    X1 = CHARGE_ADC_KRNL_L;
						Y0 = CHARGE_OFFSET_KRNL_H; Y1 = CHARGE_OFFSET_KRNL_L;
						temp_adc = do_interpolation(X0, X1, Y0, Y1, vbat_adc);
						convert_vbat_adc = vbat_adc - temp_adc;
				} else {
						convert_vbat_adc = new_vol_orign + CHARGE_OFFSET_KRNL2;
				}
			} else {
					vbat_adc = new_vol_orign;
				pr_debug("[L%d] %s discharging new_vol_adc = %d\n",
						__LINE__, __func__, vbat_adc);

				Y0 = FIRST_VOLTAGE_DROP_ADC;
				if(C2K(fuelgauge->info.average_temperature)
											<= BAT_LOW_LOW_TEMPERATURE) {
						convert_vbat_adc = vbat_adc
											+ (Y0 + FIRST_VOLTAGE_DROP_LL_ADC);
				} else if(C2K(fuelgauge->info.average_temperature)
											>= BAT_ROOM_TEMPERATURE) {
						convert_vbat_adc = vbat_adc + Y0;
				} else {
					if(C2K(fuelgauge->info.average_temperature)
											<= BAT_LOW_MID_TEMPERATURE) {
							Y1 = Y0 + FIRST_VOLTAGE_DROP_ADC;
							Y0 = Y0 + FIRST_VOLTAGE_DROP_LL_ADC;
						X0 = BAT_LOW_LOW_TEMPERATURE;
						X1 = BAT_LOW_MID_TEMPERATURE;
					} else if(C2K(fuelgauge->info.average_temperature)
											<= BAT_LOW_TEMPERATURE) {
							Y1 = Y0 + FIRST_VOLTAGE_DROP_L_ADC;
							Y0 = Y0 + FIRST_VOLTAGE_DROP_ADC;
						X0 = BAT_LOW_MID_TEMPERATURE;
						X1 = BAT_LOW_TEMPERATURE;
					} else {
							Y1 = Y0 + FIRST_VOLTAGE_DROP_RL_ADC;
							Y0 = Y0 + FIRST_VOLTAGE_DROP_L_ADC;
						X0 = BAT_LOW_TEMPERATURE;
						X1 = BAT_ROOM_LOW_TEMPERATURE;
					}
						convert_vbat_adc = vbat_adc + Y0
										+ ((X - X0) * (Y1 - Y0)) / (X1 - X0);
				}
			}
			}

				new_vol_adc = convert_vbat_adc;
			pr_info("%s. # Calculated initial new_vol_adc = %d\n", __func__, new_vol_adc);

			if(new_vol_adc > MAX_FULL_CHARGED_ADC) {
				new_vol_adc = MAX_FULL_CHARGED_ADC;
				pr_debug("%s. Set new_vol_adc to max. ADC value\n", __func__);
			}

			for(i = AVG_SIZE; i ; i--) {
				fuelgauge->info.voltage_adc[i-1] = new_vol_adc;
				fuelgauge->info.sum_voltage_adc += new_vol_adc;
			}

			fuelgauge->info.current_volt_adc = new_vol_adc;
			fuelgauge->info.volt_adc_init_done = TRUE;
			fuelgauge->info.average_volt_adc = new_vol_adc;

		}

		fuelgauge->info.origin_volt_adc = new_vol_orign;
		fuelgauge->info.current_voltage = adc_to_vbat(fuelgauge->info.current_volt_adc,
							      fuelgauge->is_charging);
		fuelgauge->info.average_voltage = adc_to_vbat(fuelgauge->info.average_volt_adc,
							      fuelgauge->is_charging);
	}else {
		pr_err("%s. Voltage ADC read failure \n", __func__);
		ret = -EIO;
	}

	pr_debug("[%s]current volt_adc = %d, average_volt_adc = %d\n",
		__func__,
		fuelgauge->info.current_volt_adc,
		fuelgauge->info.average_volt_adc);

	pr_debug("[%s]current voltage = %d, average_voltage = %d\n",
		__func__,
		fuelgauge->info.current_voltage,
		fuelgauge->info.average_voltage);

	return ret;
}
예제 #9
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
예제 #10
0
bool BatchPrecip::PrecipBatch(double dTime, MVector & Prod, double CurLevel, bool AgglomON )
  {
  long m;
  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 ProdSSurf, ProdNNtl;

  //adjusting the PSD from 1 gpl to real conc....
  for (m=0; m<NIntervals; m++)
    ProdHyPsd[m]= gpl1 * ProdHyPsd[m];

  #if ForceOptimizeOff
  for (m=0; m<NIntervals; m++)
    if (ProdHyPsd[m]<0.0)
      SetStopRequired("Phone Denis, negative PSD!");
  #endif
  CalcSSurgNNtl(SizeClass, ProdHyPsd, NIntervals, ProdSSurf, ProdNNtl);

  //initialise deltaPSD
  for (m=0; m<NIntervals; m++)
    dPSD[m]=0.0;

  //variation of Particles due to Agglomeration by Collision
  const double GRate2 = ProdB.GrowthRate();
  if (AgglomON )
	ApplyAgglom(GRate2, dTime, m_dKvFac, ProdNNtl);

  //variation due to Nucleation in the Smallest Classes ONLY
  const double NRate = get_NucleationRate(m_eNuclModel, Prod, ProdSSurf, m_eShearRate);
  dPSD[0] += NRate*dTime;

  // variation due to Growth Only
  const double GRate3 = ProdB.GrowthRate();
  const double Const_boucle3 = GRate3*dTime/HPDSize;
  dPSD[0] += Const_boucle3*( ProdHyPsd[0]-ProdHyPsd[2] )/2.0;
  for (m=1; m<NIntervals-1; m++)
    dPSD[m] += Const_boucle3*(ProdHyPsd[m-1]-ProdHyPsd[m+1])/2.0;

  // Finally Substr. or Adding Particles to the Each Classes
  for (m=0; m<NIntervals; m++)
    {
    ProdHyPsd[m] += dPSD[m];
    ProdHyPsd[m] = Max(0.0, ProdHyPsd[m]);
    }

  CalcSSurgNNtl(SizeClass, ProdHyPsd, NIntervals, ProdSSurf, ProdNNtl); //Update ProdSSurf and ProdNNtl

  double gpl1x=gpl1;
  gpl1=0.0;
  for (m=0; m<NIntervals; m++)            
    {
    gpl1=gpl1 + ProdHyPsd[m]*pow(SizeClass[m],3)/6E12;
    }
  gpl1 = gpl1 * PI * 2.42;// *ProdVolFlow;

  //readjusting the PSD to 1 gpl...
  for (m=0; m<NIntervals; m++)
    ProdHyPsd[m] = ProdHyPsd[m] / gpl1;

  //=== 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

  bool CErr;
  const double Na2OFac = get_Na2OFactor(Prod);

  PerformAluminaSolubility(Prod, dNAN, dNAN, gpl1, 0/*NoPerSec2*/, 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
 //    mfshydPrev:=mfshyd;
//     mfshyd:=flowtotal*gpl1 -mfsSoda -mfsOxal -mfsSio2 ;the way it was done in HYPROD.. it is WRONG though

  HeatBalance(Prod, SolidsVariation, enthIn, dTime, CurLevel);  // Éliminé pour vérifier la temp ?
  
  return true;
  }
예제 #11
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);
  }
예제 #12
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!!!");
  }
예제 #13
0
//---------------------------------------------------------------------------
// 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;
}
예제 #14
0
CPrecipitator::CPrecipitator(MUnitDefBase *pUnitDef, TaggedObject * pNd) :  
  MBaseMethod(pUnitDef, pNd),
  m_RB(this, false, "RB"), 
  Evap(this, "Evap")
{   //default values...
//   x=new double[4];
//   xo = new double[4];

  m_bEvapConnected = 0;

  /*//CAR data:  
  m_dActivationEnergy =	7734.00;
  m_dK0	= 2.29e+13;
  m_dK1 = 1.75;
  m_dk_TOC = 0.0023000;
  m_dn_s = -1.00;
  m_dn_fc = -2.00;
  m_dn_eq = 0;
  m_dn_ = 1.70;
  m_dn_sol = 1.00;
  m_dn_ssa = 0.60;*/

  //Generic data:
  m_dActivationEnergy =	7600.00;
  m_dK0	= 1.0e+11;
  m_dK1 = 1.0;
  m_dk_TOC = 0.0;
  m_dn_s = -1.00;
  m_dn_fc = -0.5;
  m_dn_eq = 0.0;
  m_dn_ = 2.0;
  m_dn_sol = 1.00;
  m_dn_ssa = 0.60;


  bOnLine = 1;
  dTempDropRqd = 0.5;
  dThermalLossRqd = 1500.0;
  iThermalLossMethod = THL_TempDrop;
  iCoolMethod=0;

  m_bEvapConnected = 0;
  
  ER_White      = 7200.0;
  K_White       = 1.96e10;
  gF_White      = 1.0;
  m_dK_Soda = .00127;    // K for soda inclusion
  m_dE_Soda = 2535.;    // E for soda inclusion


  dTankVol       = 1000.0;

  dSolPrecip  = 0.0;
  dGrowthRate = 0.0;
  dGrowthRateFactor = 0.0;
  dYield      = 0.0;
  dTin        = C2K(25.0);
  dTout       = C2K(25.0);
  dDiamin     = 0.0;
  dSALin      = 0.0;
  dQvin       = 0.0;
  dQvout      = 0.0;
  dACin       = 0.0;
  dACout      = 0.0;
  dResidenceTime = 0.0;
  dThermalLoss   = 0.0;
  dReactionHeat  = 0.0;
  m_dCoolOutTotHz = 0.0;
  iCoolType = 0;
  
}
예제 #15
0
CToleranceBlock EvapFnd::s_Tol(TBF_Both, "CoolTower:EvapFnd", 0.0, 1.0e-9);

double EvapFnd::Function(double x)
  {
  m_VLE.SetSatPVapFrac(Cd, x, 0);
  //Cd.Model()->ClrStatesOK();
  Cd.SetTemp(RqdT);
  Cd.SetPress(RqdP);
  double h=Cd.totHf();
  return h;
  }

//--------------------------------------------------------------------------

const double MerkelTMn = C2K(-106.5);
const double MerkelTMx = C2K(70.0);

double AirEnth(double T)
  {
  ASSERT_RDB(K2C(T)>-106.666666666666 && K2C(T)<70.0000001, "Temperature range problem!", __FILE__, __LINE__);
  const double Tc = Range(-106.666666666667, K2C(T), 70.0);
  if (Tc<-45.5555555555557)
    return 1.0086*Tc + 18.092; //y = 1.0086x + 18.092
  if (Tc<-23.3333333333334)
    return 0.0026*Tc*Tc + 1.2353*Tc + 23.016; //y = 0.0026x2 + 1.2353x + 23.016
  if (Tc<-12.2222222222223)
    return 0.0082*Tc*Tc + 1.4875*Tc + 25.788; //y = 0.0082x2 + 1.4875x + 25.788
  if (Tc<0.0000000001)
    return 0.0199*Tc*Tc + 1.7523*Tc + 27.309; //y = 0.0199x2 + 1.7523x + 27.309
  if (Tc<12.2222222222223)