예제 #1
0
void substation::fetch_double(double **prop, char *name, OBJECT *parent){
	OBJECT *hdr = OBJECTHDR(this);
	*prop = gl_get_double_by_name(parent, name);
	if(*prop == NULL){
		char tname[32];
		char *namestr = (hdr->name ? hdr->name : tname);
		char msg[256];
		sprintf(tname, "substation:%i", hdr->id);
		if(*name == NULL)
			sprintf(msg, "%s: substation unable to find property: name is NULL", namestr);
		else
			sprintf(msg, "%s: substation unable to find %s", namestr, name);
		throw(msg);
	}
}
/** Initialize water heater model properties - randomized defaults for all published variables
 **/
int waterheater::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	
	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("waterheater::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}

	hdr->flags |= OF_SKIPSAFE;

	static double sTair = 74;
	static double sTout = 68;

	if(parent){
		pTair = gl_get_double_by_name(parent, "air_temperature");
		pTout = gl_get_double_by_name(parent, "outdoor_temperature");
	}

	if(pTair == 0){
		pTair = &sTair;
		gl_warning("waterheater parent lacks \'air_temperature\' property, using default");
	}
	if(pTout == 0){
		pTout = &sTout;
		gl_warning("waterheater parent lacks \'outside_temperature\' property, using default");
	}

	/* sanity checks */
	/* initialize water tank volume */
	if(tank_volume <= 0.0){
//		tank_volume = 5*floor((1.0/5.0)*gl_random_uniform(0.90, 1.10) * 50.0 * (pHouse->get_floor_area() /2000.0));  // [gal]
		if (tank_volume > 100.0)
			tank_volume = 100.0;		
		else if (tank_volume < 20.0) 
			tank_volume = 20.0;
	} else {
		if (tank_volume > 100.0 || tank_volume < 20.0){
			gl_error("watertank volume of %f outside the volume bounds of 20 to 100 gallons.", tank_volume);
			/*	TROUBLESHOOT
				All waterheaters must be set between 40 and 100 gallons.  Most waterheaters are assumed to be 50 gallon tanks.
			*/
		}
	}

	if (tank_setpoint<90 || tank_setpoint>160)
		gl_error("watertank thermostat is set to %f and is outside the bounds of 90 to 160 degrees Fahrenheit (32.2 - 71.1 Celsius).", tank_setpoint);
		/*	TROUBLESHOOT
			All waterheaters must be set between 90 degF and 160 degF.

	/* initialize water tank deadband */
	if (thermostat_deadband>10 || thermostat_deadband < 0.0)
		GL_THROW("watertank deadband of %f is outside accepted bounds of 0 to 10 degrees (5.6 degC).", thermostat_deadband);

	// initial tank UA
	if (tank_UA <= 0.0)
		GL_THROW("Tank UA value is negative.");
		

	// Set heating element capacity if not provided by the user
	if (heating_element_capacity <= 0.0)
	{
		if (tank_volume >= 50)
			heating_element_capacity = 4.500;
		else 
		{
			// Smaller tanks can be either 3200, 3500, or 4500...
			double randVal = gl_random_uniform(RNGSTATE,0,1);
			if (randVal < 0.33)
				heating_element_capacity = 3.200;
			else if (randVal < 0.67)
				heating_element_capacity = 3.500;
			else
				heating_element_capacity = 4.500;
		}
	}

	// set gas electric loads, if not provided by the user
	if(0 > gas_fan_power){
		gas_fan_power = heating_element_capacity * 0.01;
	}

	if(0 > gas_standby_power){
		gas_standby_power = 0.0; // some units consume 3-5W
	}

	// Other initial conditions

	if(Tw < Tinlet){ // uninit'ed temperature
		Tw = gl_random_uniform(RNGSTATE,tank_setpoint - thermostat_deadband, tank_setpoint + thermostat_deadband);
	}
	current_model = NONE;
	load_state = STABLE;

	// initial demand
	Tset_curtail	= tank_setpoint - thermostat_deadband/2 - 10;  // Allow T to drop only 10 degrees below lower cut-in T...

	// Setup derived characteristics...
	area 		= (pi * pow(tank_diameter,2))/4;
	height 		= tank_volume/GALPCF / area;
	Cw 			= tank_volume/GALPCF * RHOWATER * Cp;  // [Btu/F]

	h = height;

	// initial water temperature
	if(h == 0){
		// discharged
		Tlower = Tinlet;
		Tupper = Tinlet + TSTAT_PRECISION;
	} else {
		Tlower = Tinlet;
	}

	/* schedule checks */
	switch(shape.type){
		case MT_UNKNOWN:
			/* normal, undriven behavior. */
			break;
		case MT_ANALOG:
			if(shape.params.analog.energy == 0.0){
				GL_THROW("waterheater does not support fixed energy shaping");
				/*	TROUBLESHOOT
					Though it is possible to drive the water demand of a water heater,
					it is not possible to shape its power or energy draw.  Its heater
					is either on or off, not in between.
					Change the load shape to not specify the power or energy and try
					again.
				*/
			} else if (shape.params.analog.power == 0){
				 /* power-driven ~ cheat with W/degF*gpm */
//				double heat_per_gallon = RHOWATER * // lb/cf
//										 CFPGAL *	// lb/gal
//										 CWATER *	// BTU/degF / gal
//										 KWBTUPH /	// kW/gal
//										 1000.0;	// W/gal
				water_demand = gl_get_loadshape_value(&shape) / 2.4449;
			} else {
				water_demand = gl_get_loadshape_value(&shape); /* unitless ~ drive gpm */
			}
			break;
		case MT_PULSED:
			/* pulsed loadshapes "emit one or more pulses at random times s. t. the total energy is accumulated over the period of the loadshape".
			 * pulsed loadshapes can either user time or kW values per pulse. */
			if(shape.params.pulsed.pulsetype == MPT_TIME){
				; /* constant time pulse ~ consumes X gallons to drive heater for Y hours ~ but what's Vdot, what's t? */
			} else if(shape.params.pulsed.pulsetype == MPT_POWER){
				; /* constant power pulse ~ draws water to consume X kW, limited by C + Q * h ~ Vdot proportional to power/time */
				water_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		case MT_MODULATED:
			if(shape.params.modulated.pulsetype == MPT_TIME){
				GL_THROW("Amplitude modulated water usage is nonsensical for residential water heaters");
				/*	TROUBLESHOOT
					Though it is possible to put a constant, low-level water draw on a water heater, it is thoroughly
					counterintuitive to the normal usage of the waterheater.
				 */
			} else if(shape.params.modulated.pulsetype == MPT_POWER){
				/* frequency modulated */
				/* fixed-amplitude, varying length pulses at regular intervals. */
				water_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		case MT_QUEUED:
			if(shape.params.queued.pulsetype == MPT_TIME){
				; /* constant time pulse ~ consumes X gallons/minute to consume Y thermal energy */
			} else if(shape.params.queued.pulsetype == MPT_POWER){
				; /* constant power pulse ~ draws water to consume X kW, limited by C + Q * h */
				water_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		default:
			GL_THROW("waterheater load shape has an unknown state!");
			break;
	}
	return residential_enduse::init(parent);
}
TIMESTAMP ZIPload::sync(TIMESTAMP t0, TIMESTAMP t1) 
{
	TIMESTAMP t2 = TS_NEVER;
	double real_power = 0.0;
	double imag_power = 0.0;
	double angleval;
	
	double test = multiplier;

	if(first_time==0)
	{
		first_time=t1;

	}

		if(gl_todays(t1)-gl_todays(first_time)==1)
	{
	first_time=2;

	 
	
	}


	if(soil_sensor!=NULL){
	double *humidity2=gl_get_double_by_name(soil_sensor,"humidity");
	

	
	humidity=*humidity2;
	}

	if(first_time==2)
	{
		if( irrigation_contr_object!=NULL)
		{
			
				if(actual_power>0)
				{
			   //mpila mia fora
				gl_set_value_by_name(irrigation_contr_object,"insync","2");
				actual_power_non_zero=actual_power.Re();
		
				//system("pause");
				}
	

				 insync=gl_get_int16_by_name(irrigation_contr_object,"insync");	
				 test3=gl_get_int16_by_name(irrigation_contr_object,"test");
				 if(*test3==1)
				 {
					// printf("ewdw");
					// system("pause");
				 base_power=prev_base_power;
				 }
		
		         clear_price=gl_get_double_by_name(auction_object,"current_market.clearing_price");
			     clear_quantity=gl_get_double_by_name(auction_object,"current_market.seller_total_quantity");

				
				
							
					bid_price=gl_get_double_by_name(irrigation_contr_object,"bid_price");
					bid_q=gl_get_double_by_name(irrigation_contr_object,"bid_quantity");
					
				/*	if(*bid_price>=*clear_price && (*bid_q)*3>=*clear_quantity)// && last_q<market->past_frame.clearing_quantity)
					{
						///printf(" den ");
					
						base_power=prev_base_power;
							//printf("%f ----------------------------------",base_power);
							/// base_power=0;
					}	 
					else
					{
						base_power=0;
							 
					}*/

		}
	}
	///////////////////////////////////////////////////////////////////////////////////

	


	

  if(choose_load==0)
  {
//	printf("den anrebazw nero \n");
	//system("pause");
	 // actual_power=0;
  }

  if(choose_load==1)
  {
	
	

	if (demand_response_mode == true && next_time <= t1)
	{
		double dNon,dNoff;		
		double hold_off;	

		N_on = N_off = 0;

		for (int jj=0; jj<L; jj++)
		{
			//previous_drm.on[jj] = drm.on[jj];
			//previous_drm.off[jj] = drm.off[jj];

			if (eta > 0)
			{			
				if (jj != (L-1))
					dNon = -ron * drm.on[jj] + eta * drm.off[jj] + ron * drm.on[jj+1];
				else
					dNon = -ron * drm.on[jj] + (1 - eta) * drm.off[jj] * roff + eta * drm.off[jj];
				
				if (jj != 0)
					dNoff = -(1 - eta) * drm.off[jj] * roff - eta * drm.off[jj] + (1 - eta) * hold_off * roff;
				else
					dNoff = -(1 - eta) * drm.off[jj] * roff - eta * drm.off[jj] + ron * drm.on[jj];
			}
			else
			{
				if (jj != (L-1))
					dNon = -ron * (1 + eta) * drm.on[jj] + eta * drm.on[jj] + ron * (1 + eta) * drm.on[jj+1];
				else
					dNon = -ron * (1 + eta) * drm.on[jj] + eta * drm.on[jj] + roff * drm.off[jj];
				
				if (jj != 0)
					dNoff = -roff * drm.off[jj] - eta * drm.on[jj] + hold_off * roff;
				else
					dNoff = -roff * drm.off[jj] - eta * drm.on[jj] + ron * (1 + eta) * drm.on[jj];
			}

			hold_off = drm.off[jj];

			drm.on[jj] = drm.on[jj] + dNon;
			N_on += drm.on[jj];
			drm.off[jj] = drm.off[jj] + dNoff;
		}

		N_off = N - N_on;
		phi = roff / (ron + roff);
		nominal_power = base_power * N_on / N;
		double R = ron;
		int dt = 0;
		if (ron < roff)
			R = roff;
		dt = int(1/R * 3600);

		next_time = t1 + dt;
	}

	// We're in duty cycle mode
	if (duty_cycle != -1)
	{
		double phase_shift = 0;

		if (first_pass == 0) // after first time step
		{
			phase_shift = (t1 - last_time) / (period * 3600);
			phase = phase + phase_shift;
			last_time = t1;
		}
		else
			first_pass = 0;
			last_time = t1;

		if (this->re_override == OV_NORMAL) // Normal operation
		{
			if (phase >= 1)
				phase = 0;

			// Track the time of 2 transistions
			if (t1 >= next_time || last_duty_cycle != duty_cycle)
			{
				if (duty_cycle > phase) // OFF->ON
				{
					multiplier = 1;
					next_time = t1 + (period * 3600) * (duty_cycle - phase) + 1; // +1 a bit of an offset for rounding
				}
				else					// ON->OFF
				{
					multiplier = 0;
					next_time = t1 + (period * 3600) * (1 - phase) + 1;
				}
			}
			last_duty_cycle = duty_cycle;
		}
		else if (this->re_override == OV_OFF) // After release or recovery time
		{
			if (phase <= 1 && t1>=next_time)
			{
				this->re_override = OV_NORMAL;
				next_time = t1;
			}
			else if (t1 >= next_time || next_time == TS_NEVER) // we just came from override ON
			{
				if (recovery_duty_cycle > fmod(phase,1)) // OFF->ON 
				{
					multiplier = 1;

					next_time = t1 + (period * 3600) * (recovery_duty_cycle - fmod(phase,1)) + 1; // +1 a bit of an offset for rounding
					if (duty_cycle != 0.0)
						phase -= 1 * recovery_duty_cycle / duty_cycle * (1 - fmod(phase,1)); // Track everything by the original duty cycle
					else 
						phase = 0; //Start over

					/*if (phase < 0)
					{
						next_time = t1 + (period * 3600) * (recovery_duty_cycle - 0) + 1;
						phase = 0;
					}*/
				}			
				else					// ON->OFF
				{
					//if (multiplier == 1) // we just transitioned
					//{
						//if (phase >= 1 * recovery_duty_cycle / duty_cycle)
						//	phase -= 1 * recovery_duty_cycle / duty_cycle; // Track everything by the original duty cycle
						//else if (phase < 1)
						//	this->re_override = OV_NORMAL;
					//}
					multiplier = 0;
					next_time = t1 + (period * 3600) * (1 - fmod(phase,1)) + 1;
				}
			}
			last_duty_cycle = duty_cycle;

		}
		else // override is ON, so no power
		{
			if (multiplier == 1 && duty_cycle > phase)
			{
				// do nothing
				last_duty_cycle = duty_cycle;
			}
			else
			{
				multiplier = 0;
				next_time = TS_NEVER;
				if (recovery_duty_cycle > 0) // in TOU/CPP mode
					last_duty_cycle = duty_cycle;
				else // DLC mode
				{
					if (phase >= 1)
						phase -= 1;
					last_duty_cycle = 0;
				}
			}
		}
		// last_duty_cycle = duty_cycle;
	}

	if (pCircuit!=NULL){
		if (is_240)
		{
			load.voltage_factor = pCircuit->pV->Mag() / 240; // update voltage factor - not really used for anything
		}
		else //120
		{
			load.voltage_factor = pCircuit->pV->Mag() / 120; // update voltage factor - not really used for anything
		}
	}

	t2 = residential_enduse::sync(t0,t1);

	if (pCircuit->status==BRK_CLOSED) 
	{
		//All values placed as kW/kVAr values - to be consistent with other loads
		
		
		  	
		double demand_power = multiplier * base_power;
		
		if (demand_response_mode == true)
			demand_power = nominal_power;

		if (heatgain_only == false)
		{
			//Calculate power portion
			real_power = demand_power * load.power_fraction;

			imag_power = (power_pf == 0.0) ? 0.0 : real_power * sqrt(1.0/(power_pf * power_pf) - 1.0);

			if (power_pf < 0)
			{
				imag_power *= -1.0;	//Adjust imaginary portion for negative PF
			}

			load.power.SetRect(real_power,imag_power);

			//Calculate current portion
			real_power = demand_power * load.current_fraction;

			imag_power = (current_pf == 0.0) ? 0.0 : real_power * sqrt(1.0/(current_pf * current_pf) - 1.0);

			if (current_pf < 0)
			{
				imag_power *= -1.0;	//Adjust imaginary portion for negative PF
			}

			load.current.SetRect(real_power,imag_power);

			//Calculate impedance portion
			real_power = demand_power * load.impedance_fraction;

			imag_power = (impedance_pf == 0.0) ? 0.0 : real_power * sqrt(1.0/(impedance_pf * impedance_pf) - 1.0);

			if (impedance_pf < 0)
			{
				imag_power *= -1.0;	//Adjust imaginary portion for negative PF
			}

			load.admittance.SetRect(real_power,imag_power);	//Put impedance in admittance.  From a power point of view, they are the same

			//Compute total power - not sure if needed, but will use below
			load.total = load.power + load.current + load.admittance;
			if(first_time==2)
			{
			if(*test3==2)
			{
			    actual_power.Re()=actual_power_non_zero;
			}
			
			}
					 actual_power = load.power + load.current * load.voltage_factor + load.admittance * load.voltage_factor * load.voltage_factor;
			//Update power factor, just in case
			angleval = load.total.Arg();
			load.power_factor = (angleval < 0) ? -1.0 * cos(angleval) : cos(angleval);
			
			//Determine the heat contributions - percentage of real power
			load.heatgain = load.total.Re() * load.heatgain_fraction * BTUPHPKW;
		}
		else
		{
			load.power = load.current = load.admittance = actual_power = load.total = 0.0;
			load.heatgain = demand_power * BTUPHPKW;
			return TS_NEVER;
		}
	}
	else	//Breaker's open - nothing happens
	{
		load.total = 0.0;
		load.power = 0.0;
		load.current = 0.0;
		load.admittance = 0.0;
		load.heatgain = 0.0;
		load.power_factor = 0.0;
	}




}
	if (next_time < t2 && next_time > 0)
		t2 = next_time;
	///////////////////estimate if i satisfied from market/////////////////////////////
	
	
	
		if( irrigation_contr_object!=NULL)
		{
			
			int16 *insync=gl_get_int16_by_name(irrigation_contr_object,"insync");
				
			if(*insync==2&&only_once==1)
			{
				  actual_power_non_zero=actual_power.Re();
				 
				  only_once=2;
				  gl_set_value_by_name(irrigation_contr_object,"insync","2");
				  
			}

		}
		
	
	return t2;
}
/** initialization process
 **/
int irrigation_controller::init(OBJECT *parent){
	OBJECT *hdr = OBJECTHDR(this);
	char tname[32];
	parent2=parent;
	insync=0;
	

	initial_zipload_power=gl_get_double_by_name(parent,"base_power");

	char *namestr = (hdr->name ? hdr->name : tname);

	sprintf(tname, "irrigation_controller:%i", hdr->id);
	first=0;
	cheat();

	if(parent == NULL){
		gl_error("%s: irrigation_controller has no parent, therefore nothing to control", namestr);
		return 0;
	}

	if(pMarket == NULL){
		gl_error("%s: irrigation_controller has no market, therefore no price signals", namestr);
		return 0;
	}

	if(gl_object_isa(pMarket, "auction")){
		gl_set_dependent(hdr, pMarket);
		market = OBJECTDATA(pMarket, auction);
	} else {
		gl_error("irrigation_controllers only work when attached to an 'auction' object");
		return 0;
	}

	if(dPeriod == 0.0){
		if((pMarket->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("irrigation_controller::init(): deferring initialization on %s", gl_name(pMarket, objname, 255));
			return 2; // defer
		}
		period = market->period;
	} else {
		period = (TIMESTAMP)floor(dPeriod + 0.5);
	}

	if(bid_delay < 0){
		bid_delay = -bid_delay;
	}
	if(bid_delay > period){
		gl_warning("Bid delay is greater than the irrigation_controller period. Resetting bid delay to 0.");
		bid_delay = 0;
	}

	if(target[0] == 0){
		GL_THROW("irrigation_controller: %i, target property not specified", hdr->id);
	}
	if(setpoint[0] == 0 && control_mode == CN_RAMP){
		GL_THROW("irrigation_controller: %i, setpoint property not specified", hdr->id);;
	}
	if(demand[0] == 0 && control_mode == CN_RAMP){
		GL_THROW("irrigation_controller: %i, demand property not specified", hdr->id);
	}
	if(deadband[0] == 0 && use_predictive_bidding == TRUE && control_mode == CN_RAMP){
		GL_THROW("irrigation_controller: %i, deadband property not specified", hdr->id);
	}
	if(total[0] == 0){
		GL_THROW("irrigation_controller: %i, total property not specified", hdr->id);
	}
	if(load[0] == 0){
		GL_THROW("irrigation_controller: %i, load property not specified", hdr->id);
	}

	
	fetch(&pMonitor, target, parent); // auto tha einai to soil hmidit tha to pairnei apo to soil_SENSOR
	if(control_mode == CN_RAMP){
		fetch(&pSetpoint, setpoint, parent);
		fetch(&pDemand, demand, parent);
		fetch(&pTotal, total, parent);
		fetch(&pLoad, load, parent);
		if(use_predictive_bidding == TRUE){
			fetch(&pDeadband, deadband.get_string(), parent);
		}
	} 
	fetch(&pAvg, avg_target.get_string(), pMarket);
	fetch(&pStd, std_target.get_string(), pMarket);


	if(dir == 0){
		double high = ramp_high * range_high;
		double low = ramp_low * range_low;
			//printf("high:%f, low:%f, rh:%f, rl:%f,gh:%f,gl:%f\n\n\n\n",high,low,ramp_high,ramp_low,range_high,range_low);
		if(high > low){
			dir = 1;
		} else if(high < low){
			dir = -1;
		} else if((high == low) && (fabs(ramp_high) > 0.001 || fabs(ramp_low) > 0.001)){
			dir = 0;
			if(ramp_high > 0){
				direction = 1;
			} else {
				direction = -1;
			}
			gl_warning("%s: irrigation_controller has no price ramp", namestr);
			/* occurs given no price variation, or no control width (use a normal thermostat?) */
		}
		if(ramp_low * ramp_high < 0){
			gl_warning("%s: irrigation_controller price curve is not injective and may behave strangely");
			/* TROUBLESHOOT
				The price curve 'changes directions' at the setpoint, which may create odd
				conditions in a number of circumstances.
			 */
		}
	}
	if(setpoint0==0)
		setpoint0 = -1; // key to check first thing

//	double period = market->period;
//	next_run = gl_globalclock + (TIMESTAMP)(period - fmod(gl_globalclock+period,period));
	next_run = gl_globalclock;// + (market->period - gl_globalclock%market->period);
	init_time = gl_globalclock;
	time_off = TS_NEVER;
	if(sliding_time_delay < 0 )
		dtime_delay = 21600; // default sliding_time_delay of 6 hours
	else
		dtime_delay = (int64)sliding_time_delay;

	if(state[0] != 0){
		// grab state pointer
		pState = gl_get_enum_by_name(parent, state);
		last_pState = 0;
		if(pState == 0){
			gl_error("state property name \'%s\' is not published by parent class", state);
			return 0;
		}
	}

	
	// get override, if set
	if(re_override[0] != 0){
		pOverride = gl_get_enum_by_name(parent, re_override);
	}
	if((pOverride == 0) && (use_override == OU_ON)){
		gl_error("use_override is ON but no valid override property name is given");
		return 0;
	}

	if(control_mode == CN_RAMP){
		if(slider_setting < -0.001){
			gl_warning("slider_setting is negative, reseting to 0.0");
			slider_setting = 0.0;
		}
		if(slider_setting > 1.0){
			gl_warning("slider_setting is greater than 1.0, reseting to 1.0");
			slider_setting = 1.0;
		}
	}
	
	last_p = market->init_price;

	/////////////////search for virtual_battery///////////////////////
	/*
				 static FINDLIST *xt1=NULL;
				 xt1=gl_find_objects(FL_NEW,FT_CLASS,SAME,"virtual_battery",FT_END);
				 OBJECT *firstt1= gl_find_next(xt1,NULL);
				 OBJECT *it1;
				 for(it1=firstt1;it1!=NULL;it1=it1->next)
				 {
				
					 if(gl_object_isa(it1,"virtual_battery"))
				     {

						
						 virtual_battery_object=it1;
						
					 }
					 else
					 {
					 
					// virtual_battery_object=NULL;
					 
					 }


				 }

	*/
	//////////////////////////////////////////////////////////////////
	return 1;
}
TIMESTAMP irrigation_controller::sync(TIMESTAMP t0, TIMESTAMP t1){
	double bid = -1.0;
	int64 no_bid = 0; // flag gets set when the current temperature drops in between the the heating setpoint and cooling setpoint curves
	double demand = 0.0;
	double rampify = 0.0;
	extern double bid_offset;
	double deadband_shift = 0.0;
	double shift_direction = 0.0;
	double shift_setpoint = 0.0;
	double prediction_ramp = 0.0;
	double prediction_range = 0.0;
	double midpoint = 0.0;
	OBJECT *hdr = OBJECTHDR(this);
	


if(insync==0)
{
	insync=2;
}
else if(insync==2)
{
	x=gl_get_double_by_name(parent2,"actual_power_non_zero");
//	printf("%d %f			 ",parent2->id,*x);
	//system("pause");

		insync=1;
		pDemand=x;
		initial_zipload_power=x;
}


	if(first_period==0)  //for two diffrent periods
	{

	
	//OBJECT *p=gl_get_object("sensor");
	// double *humidity=gl_get_double_by_name(p,"humidity");
	 double *humidity=gl_get_double_by_name(soil_sensor,"humidity");
		
		*pMonitor =*humidity;
		//printf("irrigaiton:%d %f	\n",soil_sensor->id,*pMonitor);
	//	system("pause");
		
	//printf("%f %f",*pMonitor,setpoint0);
	//system("pause");
	/* short circuit if the state variable doesn't change during the specified interval */
	if((t1 < next_run) && (market->market_id == lastmkt_id)){
		if(t1 <= next_run - bid_delay){
			if(use_predictive_bidding == TRUE && ((control_mode == CN_RAMP && last_setpoint != setpoint0) || (control_mode == CN_DOUBLE_RAMP && (last_heating_setpoint != heating_setpoint0 || last_cooling_setpoint != cooling_setpoint0)))) {
				;
			} else {// check to see if we have changed states
				if(pState == 0){
					return next_run;
				} else if(*pState == last_pState){
					return next_run;
				}
			}
		} else {
			return next_run;
		}
	}
	
	if(use_predictive_bidding == TRUE){
		deadband_shift = *pDeadband * 0.5;
	}

	if(control_mode == CN_RAMP){
		// if market has updated, continue onwards
		if(market->market_id != lastmkt_id){// && (*pAvg == 0.0 || *pStd == 0.0 || setpoint0 == 0.0)){
			//printf("EDWWWWWWWWWWWWWWWWWWW\n");
			//system("pause");
			lastmkt_id = market->market_id;
			lastbid_id = -1; // clear last bid id, refers to an old market
			// update using last price
			// T_set,a = T_set + (P_clear - P_avg) * | T_lim - T_set | / (k_T * stdev24)

			clear_price = market->current_frame.clearing_price;

			if(use_predictive_bidding == TRUE){
				if((dir > 0 && clear_price < last_p) || (dir < 0 && clear_price > last_p)){
					shift_direction = -1;
				} else if((dir > 0 && clear_price >= last_p) || (dir < 0 && clear_price <= last_p)){
					shift_direction = 1;
				} else {
					shift_direction = 0;
				}
			}
			if(fabs(*pStd) < bid_offset){
				set_temp = setpoint0;
			} else if(clear_price < *pAvg && range_low != 0){
				set_temp = setpoint0 + (clear_price - *pAvg) * fabs(range_low) / (ramp_low * *pStd) + deadband_shift*shift_direction;
			} else if(clear_price > *pAvg && range_high != 0){
				set_temp = setpoint0 + (clear_price - *pAvg) * fabs(range_high) / (ramp_high * *pStd) + deadband_shift*shift_direction;
			} else {
				set_temp = setpoint0 + deadband_shift*shift_direction;
			}

			if((use_override == OU_ON) && (pOverride != 0)){
				if(clear_price <= last_p){
					// if we're willing to pay as much as, or for more than the offered price, then run.
					*pOverride = 1;
				} else {
					*pOverride = -1;
				}
			}

			// clip
			if(set_temp > max){
				set_temp = max;
			} else if(set_temp < min){
				set_temp = min;
			}

			*pSetpoint = set_temp;
			//gl_verbose("irrigation_controller::postsync(): temp %f given p %f vs avg %f",set_temp, market->next.price, market->avg24);
		}
		
		if(dir > 0){
				//edw mpainei
			if(use_predictive_bidding == TRUE){
				if(*pState == 0 && *pMonitor > (max - deadband_shift)){
					bid = market->pricecap;
				} else if(*pState != 0 && *pMonitor < (min + deadband_shift)){
					bid = 0.0;
					no_bid = 1;
				} else if(*pState != 0 && *pMonitor > max){
					bid = market->pricecap;
				} else if(*pState == 0 && *pMonitor < min){
					bid = 0.0;
					no_bid = 1;
				}
			} else {
				if(*pMonitor > max){
			//		printf("sto max");
				
					bid = market->pricecap;
				} else if (*pMonitor < min){
				//	printf("sto min");
					
					bid = -1.0;
					no_bid = 0;
				}
			}
		} else if(dir < 0){
		
				
			if(use_predictive_bidding == TRUE){
				if(*pState == 0 && *pMonitor < (min + deadband_shift)){
					bid = market->pricecap;
				} else if(*pState != 0 && *pMonitor > (max - deadband_shift)){
					bid = 0.0;
					no_bid = 1;
				} else if(*pState != 0 && *pMonitor < min){
					bid = market->pricecap;
				} else if(*pState == 0 && *pMonitor > max){
					bid = 0.0;
					no_bid = 1;
				}
			} else {
				if(*pMonitor < min){
					bid = market->pricecap;
				} else if (*pMonitor > max){
					bid = 0.0;
					no_bid = 0;
				}
			}
		} else if(dir == 0){

				
			if(use_predictive_bidding == TRUE){
				if(direction == 0.0) {
					gl_error("the variable direction did not get set correctly.");
				} else if((*pMonitor > max + deadband_shift || (*pState != 0 && *pMonitor > min - deadband_shift)) && direction > 0){
					bid = market->pricecap;
				} else if((*pMonitor < min - deadband_shift || (*pState != 0 && *pMonitor < max + deadband_shift)) && direction < 0){
					bid = market->pricecap;
				} else {
					bid = 0.0;
					no_bid = 0;
				}
			} else {
				if(*pMonitor < min){
					bid = market->pricecap;
				} else if(*pMonitor > max){
					bid = 0.0;
					no_bid = 0;
				} else {
					bid = *pAvg;
				}
			}
		}
		
		// calculate bid price
	//printf("%f,monitor:%f,min:%f max:%f, setpoint:%f\n",*humidity,*pMonitor,min,max,setpoint0);
		if(*pMonitor > setpoint0){
			k_T = ramp_low;
			T_lim = range_low;
			bid=0;
			
		  // printf("values : %f %f %f \n",bid,k_T, T_lim );
		} else if(*pMonitor < setpoint0) {
			//printf("right_side ");
		    
			k_T = ramp_low;
			T_lim = range_low;
			//printf("values : %f %f %f \n",bid,k_T, T_lim );

			///////////////////close all the controllers////////////////////////////
						
				static FINDLIST *xt1=NULL;
				 xt1=gl_find_objects(FL_NEW,FT_CLASS,SAME,"controller",FT_END);
				 OBJECT *firstt1= gl_find_next(xt1,NULL);
				 OBJECT *it1;
				 for(it1=firstt1;it1!=NULL;it1=it1->next)
				 {
				
					 if(gl_object_isa(it1,"controller"))
				     {
						 gl_set_value_by_name(it1,"second_period_for_market","1")  ;
						 
				     }
			     }


		//////////////////////////////////////////////////////////////////////////////////
		} else {
			
			k_T = 0.0;
			T_lim = 0.0;
		}
	
			
		if(bid < 0.0 && *pMonitor != setpoint0) {		
			
			gl_set_value_by_name(soil_sensor,"irrigate_flag","1");
			last_q = *initial_zipload_power;
			*pDemand =*initial_zipload_power;
			
			bid = *pAvg + ( (fabs(*pStd) < bid_offset) ? 0.0 : (*pMonitor - setpoint0) * (k_T * *pStd) / fabs(T_lim) );
			//printf("price:%f %f %f %f\n",bid,(*pMonitor - setpoint0) ,(k_T * *pStd) , fabs(T_lim));
				
	
			//////////////////////////////////////
			char x_position_string[1024];
			double *prev=gl_get_double_by_name(parent2,"prev_base_power");
		    double pos_x = *prev;
			sprintf(x_position_string, "%f", pos_x);
			gl_set_value_by_name(parent2,"base_power",x_position_string);
			/////////////////////////////////////

		} else if(*pMonitor == setpoint0) {
			bid = *pAvg;
			
		}
		else
		{
		    last_q=0;
			
			gl_set_value_by_name(parent2,"base_power","0");
		}

		// bid the response part of the load
		double residual = *pTotal;
		/* WARNING ~ bid ID check will not work properly */
		KEY bid_id = (KEY)(lastmkt_id == market->market_id ? lastbid_id : -1);
		// override
		//bid_id = -1;
		
		if(last_q > 0 && no_bid != 1){
			
			last_p = bid;
			last_q= *initial_zipload_power;
		
			//if(last_p < 0)
			//{
				//last_p=clear_price;
			//}
			if(0 != strcmp(market->unit, "")){
				if(0 == gl_convert("kW", market->unit, &(last_q))){
					gl_error("unable to convert bid units from 'kW' to '%s'", market->unit.get_string());
					return TS_INVALID;
				}
			}
			//lastbid_id = market->submit(OBJECTHDR(this), -last_q, last_p, bid_id, (BIDDERSTATE)(pState != 0 ? *pState : 0));
			if(pState != 0){
				
				lastbid_id = submit_bid_state(pMarket, hdr, -last_q, last_p, (*pState > 0 ? 1 : 0), bid_id);
			} else {
				
				lastbid_id = submit_bid(pMarket, hdr, -last_q, last_p, bid_id);
			}
			residual -= *pLoad;

		} else {
			last_p = 0;
			last_q = 0;
			gl_verbose("%s's is not bidding", hdr->name);
		}
		if(residual < -0.001)
			gl_warning("irrigation_controller:%d: residual unresponsive load is negative! (%.1f kW)", hdr->id, residual);
	} 

	if (pState != 0)
		last_pState = *pState;

	
	char timebuf[128];
	gl_printtime(t1,timebuf,127);
	

	return TS_NEVER;


	//}
	
	} //end of first_period==0
}
예제 #6
0
//EXPORT for object-level call (as opposed to module-level)
EXPORT SIMULATIONMODE update_double_assert(OBJECT *obj, TIMESTAMP t0, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val)
{
	char buff[64];
	char dateformat[8]="";
	char error_output_buff[1024];
	char datebuff[64];
	double_assert *da = OBJECTDATA(obj,double_assert);
	DATETIME delta_dt_val;
	double del_clock;
	TIMESTAMP del_clock_int;
	int del_microseconds;
	double *x;

	if(da->get_once() == da->ONCE_TRUE){
		da->set_once_value(da->get_value());
		da->set_once(da->ONCE_DONE);
	} else if (da->get_once() == da->ONCE_DONE){
		if(da->get_once_value() == da->get_value()){
			gl_verbose("Assert skipped with ONCE logic");
			return SM_EVENT;
		} else {
			da->set_once_value(da->get_value());
		}
	}

	// get the within range
	double range = 0.0;
	if ( da->get_within_mode() == da->IN_RATIO ) 
	{
		range = da->get_value() * da->get_within();

		//if ( range<0.001 ) //minimum bounds removed since many deltamode items are small
		//{	// minimum bounds
		//	range = 0.001;
		//}
	} 
	else if ( da->get_within_mode()== da->IN_ABS ) 
	{
		range = da->get_within();
	}
		
	//Iteration checker - assert only valid on the first timestep
	if (iteration_count_val == 0)
	{
		//Skip first timestep of any delta iteration -- nature of delta means it really isn't checking the right one
		if (delta_time>=dt)
		{
			//Get value
			x = (double*)gl_get_double_by_name(obj->parent,da->get_target());

			if (x==NULL) 
			{
				gl_error("Specified target %s for %s is not valid.",da->get_target(),gl_name(obj->parent,buff,64));
				/*  TROUBLESHOOT
				Check to make sure the target you are specifying is a published variable for the object
				that you are pointing to.  Refer to the documentation of the command flag --modhelp, or 
				check the wiki page to determine which variables can be published within the object you
				are pointing to with the assert function.
				*/
				return SM_ERROR;
			}
			else if (da->get_status() == da->ASSERT_TRUE)
			{
				double m = fabs(*x-da->get_value());
				if (_isnan(m) || m>range)
				{
					//Calculate time
					if (delta_time>=dt)	//After first iteration
						del_clock  = (double)t0 + (double)(delta_time-dt)/(double)DT_SECOND;
					else	//First second different, don't back out
						del_clock  = (double)t0 + (double)(delta_time)/(double)DT_SECOND;

					del_clock_int = (TIMESTAMP)del_clock;	/* Whole seconds - update from global clock because we could be in delta for over 1 second */
					del_microseconds = (int)((del_clock-(int)(del_clock))*1000000+0.5);	/* microseconds roll-over - biased upward (by 0.5) */
					
					//Convert out
					gl_localtime(del_clock_int,&delta_dt_val);

					//Determine output format
					gl_global_getvar("dateformat",dateformat,sizeof(dateformat));

					//Output date appropriately
					if ( strcmp(dateformat,"ISO")==0)
						sprintf(datebuff,"ERROR    [%04d-%02d-%02d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.year,delta_dt_val.month,delta_dt_val.day,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
					else if ( strcmp(dateformat,"US")==0)
						sprintf(datebuff,"ERROR    [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.month,delta_dt_val.day,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
					else if ( strcmp(dateformat,"EURO")==0)
						sprintf(datebuff,"ERROR    [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.day,delta_dt_val.month,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
					else
						sprintf(datebuff,"ERROR    .09f : ",del_clock);

					//Actual error part
					sprintf(error_output_buff,"Assert failed on %s - %s (%g) not within %f of given value %g",gl_name(obj->parent, buff, 64),da->get_target(), *x, da->get_within(), da->get_value());

					//Send it out
					gl_output("%s%s",datebuff,error_output_buff);

					return SM_ERROR;
				}
				gl_verbose("Assert passed on %s", gl_name(obj->parent, buff, 64));
				return SM_EVENT;
			}
			else if (da->get_status() == da->ASSERT_FALSE)
			{
				double m = fabs(*x-da->get_value());
				if (_isnan(m) || m<range)
				{				
					//Calculate time
					if (delta_time>=dt)	//After first iteration
						del_clock  = (double)t0 + (double)(delta_time-dt)/(double)DT_SECOND;
					else	//First second different, don't back out
						del_clock  = (double)t0 + (double)(delta_time)/(double)DT_SECOND;

					del_clock_int = (TIMESTAMP)del_clock;	/* Whole seconds - update from global clock because we could be in delta for over 1 second */
					del_microseconds = (int)((del_clock-(int)(del_clock))*1000000+0.5);	/* microseconds roll-over - biased upward (by 0.5) */
					
					//Convert out
					gl_localtime(del_clock_int,&delta_dt_val);

					//Determine output format
					gl_global_getvar("dateformat",dateformat,sizeof(dateformat));

					//Output date appropriately
					if ( strcmp(dateformat,"ISO")==0)
						sprintf(datebuff,"ERROR    [%04d-%02d-%02d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.year,delta_dt_val.month,delta_dt_val.day,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
					else if ( strcmp(dateformat,"US")==0)
						sprintf(datebuff,"ERROR    [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.month,delta_dt_val.day,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
					else if ( strcmp(dateformat,"EURO")==0)
						sprintf(datebuff,"ERROR    [%02d-%02d-%04d %02d:%02d:%02d.%.06d %s] : ",delta_dt_val.day,delta_dt_val.month,delta_dt_val.year,delta_dt_val.hour,delta_dt_val.minute,delta_dt_val.second,del_microseconds,delta_dt_val.tz);
					else
						sprintf(datebuff,"ERROR    .09f : ",del_clock);

					//Actual error part
					sprintf(error_output_buff,"Assert failed on %s - %s (%g) not within %f of given value %g",gl_name(obj->parent, buff, 64),da->get_target(), *x, da->get_within(), da->get_value());

					//Send it out
					gl_output("%s%s",datebuff,error_output_buff);

					return SM_ERROR;
				}
				gl_verbose("Assert passed on %s", gl_name(obj->parent, buff, 64));
				return SM_EVENT;
			}
			else
			{
				gl_verbose("Assert test is not being run on %s", gl_name(obj->parent, buff, 64));
				return SM_EVENT;
			}
		}
		else	//First pass, just proceed
			return SM_EVENT;
	}
	else	//Iteration, so don't care
		return SM_EVENT;
}
예제 #7
0
int load_tracker::init(OBJECT *parent)
{
	// Make sure we have a target object
	if (target==NULL)
	{
		GL_THROW("Target object not set");
		/* TROUBLESHOOT
		Please specify the name of the target object to be monitored.
		*/
	}

	// Make sure we have a target property
	PROPERTY* target_property = gl_get_property(target,target_prop.get_string());
	if (target_property==NULL)
	{
		GL_THROW("Unable to find property \"%s\" in object %s", target_prop.get_string(), target->name);
		/* TROUBLESHOOT
		Please specify an existing property of the target object to be monitored.
		*/
	}

	// Make sure it is a supported type
	switch (target_property->ptype)
	{
	case PT_double:
	case PT_complex:
	case PT_int16:
	case PT_int32:
	case PT_int64:
		break;
	default:
		GL_THROW("Unsupported property type.  Supported types are complex, double and integer");
		/* TROUBLESHOOT
		Please specify a property whose type is either a double, complex, int16, int32, or an int64.
		*/
	}
	type = target_property->ptype;

	// Get a pointer to the target property value
	switch (type)
	{
	case PT_double:
		pointer.d = gl_get_double_by_name(target, target_prop.get_string());
		break;
	case PT_complex:
		pointer.c = gl_get_complex_by_name(target, target_prop.get_string());
		break;
	case PT_int16:
		pointer.i16 = gl_get_int16_by_name(target, target_prop.get_string());
		break;
	case PT_int32:
		pointer.i32 = gl_get_int32_by_name(target, target_prop.get_string());
		break;
	case PT_int64:
		pointer.i64 = gl_get_int64_by_name(target, target_prop.get_string());
		break;
	}

	// The VALUEPOINTER is a union of pointers so we only need to check one of them....
	if (pointer.d == NULL)
	{
		GL_THROW("Unable to bind to property \"%s\" in object %s", target_prop.get_string(), target->name);
		/* TROUBLESHOOT
		The property given does not exist for the given property object. Please specify an existing property of the target object.
		*/
	}

	// Make sure we have a full_scale value
	if (full_scale == 0.0)
	{
		GL_THROW("The full_scale property must be non-zero");
		/* TROUBLESHOOT
		Please specify full_scale as a non-zero value.
		*/
	}

	// Check deadbank is OK
	if (deadband < 1.0 || deadband > 50.0)
	{
		GL_THROW("Deadband must be in the range 1% to 50%");
		/* TROUBLESHOOT
		Please specify deadband as a value between 1 and 50.
		*/
	}

	// Check damping is OK
	if (damping < 0.0)
	{
		GL_THROW("Damping must greater than or equal to 0.0");
		/* TROUBLESHOOT
		Please specify damping as a value of 0 or greater.
		*/
	}

	// Set the default output value based on feed-forward control
	output = setpoint / full_scale;

	return 1;
}
/** Water heater plc control code to set the water heater 'heat_needed' state
	The thermostat set point, deadband, tank state(height of hot water column) and 
	current water temperature are used to determine 'heat_needed' state.
 **/
TIMESTAMP virtual_battery::presync(TIMESTAMP t0, TIMESTAMP t1){

		power= gl_get_double_by_name(parent2,"TotalRealPow");
	
			if(first_time==0)
			{
				first_time=t1;

			}

			if(gl_todays(t1)-gl_todays(first_time)==1)
			{
					first_time=2;
			}
			if(gl_todays(t1)-gl_todays(first_time)==2)
			{
				first_time2=2;
			}

	if(first_time==2 && first_time2==0)
	{
		if(change_capacity==1)
		{


		char timebuf[128];
		gl_printtime(t1,timebuf,127);
		printf("%s \n",timebuf);

		

		//system("pause");
			 double *clear_quantity=gl_get_double_by_name(auction_object,"current_market.clearing_quantity");
			 double *clear_price=gl_get_double_by_name(auction_object,"current_market.clearing_price");
			 if(*clear_quantity > capacity/1000)
			{
				// printf("1	glfdlhdljhdljkkjlhjlhlddfgdfg\n\n\n\n");
				  capacity=0;
				 
				// system("pause");
				 charge=1;
			 }
			 else		 if(*clear_price >= price)
			 {
				 //printf("2	");
				 capacity=0;

				// printf("post: %f ",capacity);
				// system("pause");
				
				 charge=1;
	 
			 }
			 else if(*clear_price < price)
			 {
				// printf("3	");
				 capacity=capacity;

			//  system("pause");
				 

				 charge=1;
	 
			 }
			 change_capacity=0;
	}
		//printf("%f\n\n", capacity);
	}
	
	return TS_NEVER;
	
}
예제 #9
0
파일: range.cpp 프로젝트: brennane/gridpot
/** Initialize oven model properties - randomized defaults for all published variables
 **/
int range::init(OBJECT *parent)
{
	// @todo This class has serious problems and should be deleted and started from scratch. Fuller 9/27/2013.
	
	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("range::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;

	static double sTair = 74;
	static double sTout = 68;
	if (heat_fraction==0) heat_fraction = 0.2;

	if(parent){
		pTair = gl_get_double_by_name(parent, "air_temperature");
		pTout = gl_get_double_by_name(parent, "outdoor_temperature");
	}

	if(pTair == 0){
		pTair = &sTair;
		gl_warning("range parent lacks \'air_temperature\' property, using default");
	}
	if(pTout == 0){
		pTout = &sTout;
		gl_warning("range parent lacks \'outside_temperature\' property, using default");
	}

	/* sanity checks */
	/* initialize oven volume */
	if(oven_volume <= 0.0){
//		oven_volume = 5*floor((1.0/5.0)*gl_random_uniform(0.90, 1.10) * 50.0 * (pHouse->get_floor_area() /2000.0));  // [gal]
		if (oven_volume > 100.0)
			oven_volume = 100.0;		
		else if (oven_volume < 20.0) 
			oven_volume = 20.0;
	} 

	if (oven_setpoint<90 || oven_setpoint>160){
		GL_THROW("This model is experimental and not validated: oven thermostat is set to %f and is outside the bounds of 90 to 160 degrees Fahrenheit (32.2 - 71.1 Celsius).", oven_setpoint);
		/*	TROUBLESHOOT
			TODO.
		*/
	}
	/* initialize oven deadband */
	if (thermostat_deadband>10 || thermostat_deadband < 0.0)
		GL_THROW("oven deadband of %f is outside accepted bounds of 0 to 10 degrees (5.6 degC).", thermostat_deadband);

	// initial range UA
	if (oven_UA <= 0.0)
		GL_THROW("Range UA value is negative.");
		

	// Set heating element capacity if not provided by the user
	if (heating_element_capacity <= 0.0)
	{
		if (oven_volume >= 50)
			heating_element_capacity = 4.500;
		else 
		{
			
			double randVal = gl_random_uniform(&hdr->rng_state,0,1);
			if (randVal < 0.33)
				heating_element_capacity = 3.200;
			else if (randVal < 0.67)
				heating_element_capacity = 3.500;
			else
				heating_element_capacity = 4.500;
		}
	}

	// Other initial conditions

	if(Tw < Tinlet){ // uninit'ed temperature
		Tw = gl_random_uniform(&hdr->rng_state,oven_setpoint - thermostat_deadband, oven_setpoint + thermostat_deadband);
	}
	current_model = NONE;
	load_state = STABLE;

	// initial demand
	Tset_curtail	= oven_setpoint - thermostat_deadband/2 - 10;  // Allow T to drop only 10 degrees below lower cut-in T...

	// Setup derived characteristics...
	area 		= (pi * pow(oven_diameter,2))/4;
	height 		= oven_volume/GALPCF / area;
	Cw 			= oven_volume/GALPCF * food_density * specificheat_food;  // [Btu/F]
	
	h = height;

	// initial food temperature
	if(h == 0){
		// discharged
		Tlower = Tinlet;
		Tupper = Tinlet + TSTAT_PRECISION;
	} else {
		Tlower = Tinlet;
	}

	/* schedule checks */
	switch(shape.type){
		case MT_UNKNOWN:
			/* normal, undriven behavior. */
			gl_warning("This device, %s, is considered very experimental and has not been validated.", get_name());
			break;
		case MT_ANALOG:
			if(shape.params.analog.energy == 0.0){
				GL_THROW("range does not support fixed energy shaping");
				/*	TROUBLESHOOT
					Though it is possible to drive the demand of a oven,
					it is not possible to shape its power or energy draw.  Its heater
					is either on or off, not in between.
					Change the load shape to not specify the power or energy and try
					again.
				*/
			} else if (shape.params.analog.power == 0){

				oven_demand = gl_get_loadshape_value(&shape) / 2.4449;
			} else {
				oven_demand = gl_get_loadshape_value(&shape); /* unitless ~ drive gpm */
			}
			break;
		case MT_PULSED:
			/* pulsed loadshapes "emit one or more pulses at random times s. t. the total energy is accumulated over the period of the loadshape".
			 * pulsed loadshapes can either user time or kW values per pulse. */
			if(shape.params.pulsed.pulsetype == MPT_TIME){
				; /* constant time pulse ~ consumes X gallons to drive heater for Y hours ~ but what's Vdot, what's t? */
			} else if(shape.params.pulsed.pulsetype == MPT_POWER){
				; /* constant power pulse ~ oven demand X kW, limited by C + Q * h ~ Vdot proportional to power/time */
				oven_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		case MT_MODULATED:
			if(shape.params.modulated.pulsetype == MPT_TIME){
				GL_THROW("Amplitude modulated oven usage is nonsensical for residential ovens");
				/*	TROUBLESHOOT
					Though it is possible to put a constant, it is thoroughly
					counterintuitive to the normal usage of the range.
				 */
			} else if(shape.params.modulated.pulsetype == MPT_POWER){
				/* frequency modulated */
				/* fixed-amplitude, varying length pulses at regular intervals. */
				oven_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		case MT_QUEUED:
			if(shape.params.queued.pulsetype == MPT_TIME){
				; /* constant time pulse ~ consumes X gallons/minute to consume Y thermal energy */
			} else if(shape.params.queued.pulsetype == MPT_POWER){
				; /* constant power pulse ~ oven demand X kW, limited by C + Q * h */
				oven_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		default:
			GL_THROW("range load shape has an unknown state!");
			break;
	}
	return residential_enduse::init(parent);
}
예제 #10
0
int histogram::feed_bins(OBJECT *obj){
	double value = 0.0;
	complex cval = 0.0; //gl_get_complex(obj, ;
	int64 ival = 0;
	int i = 0;

	switch(prop_ptr->ptype){
		case PT_complex:
			cval = (prop_ptr ? *gl_get_complex(obj, prop_ptr) : *gl_get_complex_by_name(obj, property) );
			switch(this->comp_part){
				case REAL:
					value = cval.Re();
					break;
				case IMAG:
					value = cval.Im();
					break;
				case MAG:
					value = cval.Mag();
					break;
				case ANG:
					value = cval.Arg();
					break;
				default:
					gl_error("Complex property with no part defined in %s", (obj->name ? obj->name : "(unnamed)"));
			}
			ival = 1;
			/* fall through */
		case PT_double:
			if(ival == 0) 
				value = (prop_ptr ? *gl_get_double(obj, prop_ptr) : *gl_get_double_by_name(obj, property.get_string()) );
			for(i = 0; i < bin_count; ++i){
				if(value > bin_list[i].low_val && value < bin_list[i].high_val){
					++binctr[i];
				} else if(bin_list[i].low_inc && bin_list[i].low_val == value){
					++binctr[i];
				} else if(bin_list[i].high_inc && bin_list[i].high_val == value){
					++binctr[i];
				}
			}
			break;
		case PT_int16:
			ival = (prop_ptr ? *gl_get_int16(obj, prop_ptr) : *gl_get_int16_by_name(obj, property.get_string()) );
			value = 1.0;
		case PT_int32:
			if(value == 0.0){
				ival = (prop_ptr ? *gl_get_int32(obj, prop_ptr) : *gl_get_int32_by_name(obj, property.get_string()) );
				value = 1.0;
			}
		case PT_int64:
			if(value == 0.0){
				ival = (prop_ptr ? *gl_get_int64(obj, prop_ptr) : *gl_get_int64_by_name(obj, property.get_string()) );
				value = 1.0;
			}
		case PT_enumeration:
			if(value == 0.0){
				ival = (prop_ptr ? *gl_get_enum(obj, prop_ptr) : *gl_get_enum_by_name(obj, property.get_string()) );
				value = 1.0;
			}
		case PT_set:
			if(value == 0.0){
				ival = (prop_ptr ? *gl_get_set(obj, prop_ptr) : *gl_get_set_by_name(obj, property.get_string()) );
				value = 1.0;
			}
			
			/* may be prone to fractional errors */
			for(i = 0; i < bin_count; ++i){
				if(ival > bin_list[i].low_val && ival < bin_list[i].high_val){
					++binctr[i];
				} else if(bin_list[i].low_inc && bin_list[i].low_val == ival){
					++binctr[i];
				} else if(bin_list[i].high_inc && bin_list[i].high_val == ival){
					++binctr[i];
				}
			}
			break;
	}

	return 0;
}