示例#1
0
void range::thermostat(TIMESTAMP t0, TIMESTAMP t1){
	Ton  = oven_setpoint - thermostat_deadband/2;
	Toff = oven_setpoint + thermostat_deadband/2;
	OBJECT *hdr = OBJECTHDR(this);

	switch(range_state()){

		case FULL:

			if (enduse_queue_oven>1)// && dryer_on == true)
			{			
								
				oven_run_prob = double(gl_random_uniform(&hdr->rng_state,queue_min,queue_max));
			
					if(Tw-TSTAT_PRECISION < Ton && (oven_run_prob > enduse_queue_oven || oven_run_prob >1 ) && (time_oven_operation <time_oven_setting))
				
					{	
					
						heat_needed = TRUE;
						oven_check = true;
						remainon = true;
						if (time_oven_operation == 0)
						enduse_queue_oven --;					

					}
			}				
			
			if (Tw+TSTAT_PRECISION > Toff || (time_oven_operation >= time_oven_setting))
			{
					heat_needed = FALSE;
					oven_check = false;
					
			} 
			if (Tw-TSTAT_PRECISION < Ton && (time_oven_operation <time_oven_setting) && remainon == true)
			{
					heat_needed = TRUE;
					oven_check = true;
			}
			if (time_oven_operation >= time_oven_setting)
			{
				remainon = false;
				time_oven_operation = 0;
			}
			else 
			{
			; // no change
			}
			
			
			break;
		case PARTIAL:
		case EMPTY:
			heat_needed = TRUE; // if we aren't full, fill 'er up!
			break;
		default:
			GL_THROW("range thermostat() detected that the oven is in an unknown state");
	}
	//return TS_NEVER; // this thermostat is purely reactive and will never drive the system
}
int passive_controller::calc_proboff(TIMESTAMP t0, TIMESTAMP t1){
	if(observation_addr == 0 || expectation_addr == 0 || observation_stdev_addr == 0){
		GL_THROW("insufficient input for probabilistic shutoff control mode");
		return -1;
	}
	double erf_in, erf_out;
	double cdf_out;
	double r;
	extern double bid_offset;

	
	switch(distribution_type){
		case PDT_NORMAL:
			// N is the cumulative normal distribution
			// k_w is a comfort setting
			// r is compared to a uniformly random number on [0,1.0)
			// erf_in = (x-mean) / (var^2 * sqrt(2))
			if(obs_stdev < bid_offset){ // short circuit
				if(observation > expectation){
					output_state = -1;
					prob_off = 1.0;
				} else {
					output_state = 0;
					prob_off = 0.0;
				}
				return 0;
			}
			erf_in = (observation - expectation) / (obs_stdev*obs_stdev * sqrt(2.0));
			erf_out = tc_erf(erf_in);
			cdf_out = 0.5 * (1 + erf_out);
			prob_off = comfort_level * (cdf_out-0.5);			
			break;
		case PDT_EXPONENTIAL:
			prob_off = comfort_level * (1 - exp(-observation/expectation));
			break;
		case PDT_UNIFORM:
			prob_off = comfort_level * (observation - expectation) / expectation;
			break;
		default:
			gl_error("");
	}
	if(prob_off < 0 || !isfinite(prob_off)){
		prob_off = 0.0;
	}
	r = gl_random_uniform(RNGSTATE,0.0,1.0);
	if(r < prob_off){
		output_state = -1; // off?
	} else {
		output_state = 0; //Normal
	}

	return 0;
}
示例#3
0
TIMESTAMP refrigerator::presync(TIMESTAMP t0, TIMESTAMP t1){

	OBJECT *hdr = OBJECTHDR(this);

	if(start_time==0)
	{
		start_time = int32(t0);
		DO_random_opening = int32(gl_random_uniform(&hdr->rng_state,0,1800));
	}	

	return TS_NEVER;
}
示例#4
0
int plugload::create() 
{
	int res = residential_enduse::create();

	// name of enduse
	load.name = oclass->name;
	load.power = load.admittance = load.current = load.total = complex(0,0,J);
	load.power_fraction = load.current_fraction = load.impedance_fraction = 0;
	load.heatgain_fraction = 0.90;
	load.power_factor = 0.90;
	//load.power_fraction = 1.0;
	load.voltage_factor = 1.0; // assume 'even' voltage, initially
	shape.load = gl_random_uniform(RNGSTATE,0, 0.1);
	return res;
}
示例#5
0
int microwave::create() 
{
	int res = residential_enduse::create();

	// name of enduse
	load.name = oclass->name;
	load.power = load.admittance = load.current = load.total = complex(0,0,J);

	load.heatgain_fraction = 0.25;
	load.power_factor = 0.95;

	standby_power = 0.01;
	shape.load = gl_random_uniform(RNGSTATE,0, 0.1);  // assuming a default maximum 10% of the sync time 

	gl_warning("explicit %s model is experimental", OBJECTHDR(this)->oclass->name);

	return res;
}
示例#6
0
// periodically activates for the tail demand % of a cycle_time period.  Has a random offset to prevent
//	lock-step behavior across uniform devices
// start ....... on .. off
TIMESTAMP microwave::update_state_cycle(TIMESTAMP t0, TIMESTAMP t1){
	double ti0 = (double)t0, ti1 = (double)t1;

	if(shape.load == 0){
		state = OFF;
		cycle_start = 0;
		return TS_NEVER;
	}

	if(shape.load == 1){
		state = ON;
		cycle_start = 0;
		return TS_NEVER;
	}

	if(cycle_start == 0){
		double off = gl_random_uniform(RNGSTATE,0, this->cycle_time);
		cycle_start = (TIMESTAMP)(ti1 + off);
		cycle_on = (TIMESTAMP)((1 - shape.load) * cycle_time) + cycle_start;
		cycle_off = (TIMESTAMP)cycle_time + cycle_start;
		state = OFF;
		return (TIMESTAMP)cycle_on;
	}
	
	if(t0 == cycle_on){
		state = ON;
	}
	if(t0 == cycle_off){
		state = OFF;
		cycle_start = cycle_off;
	}
	if(t0 == cycle_start){
		cycle_on = (TIMESTAMP)((1 - shape.load) * cycle_time) + cycle_start;
		state = OFF;
		cycle_off = (TIMESTAMP)cycle_time + cycle_start;
	}

	if(state == ON)
		return (TIMESTAMP)cycle_off;
	if(state == OFF)
		return (TIMESTAMP)cycle_on;
	return TS_NEVER; // from ambiguous state
}
int refrigerator::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;

	// defaults for unset values */
	if (size==0)				size = gl_random_uniform(RNGSTATE,20,40); // cf
	if (thermostat_deadband==0) thermostat_deadband = gl_random_uniform(RNGSTATE,2,3);
	if (Tset==0)				Tset = gl_random_uniform(RNGSTATE,35,39);
	if (UA == 0)				UA = 0.6;
	if (UAr==0)					UAr = UA+size/40*gl_random_uniform(RNGSTATE,0.9,1.1);
	if (UAf==0)					UAf = gl_random_uniform(RNGSTATE,0.9,1.1);
	if (COPcoef==0)				COPcoef = gl_random_uniform(RNGSTATE,0.9,1.1);
	if (Tout==0)				Tout = 59.0;
	if (load.power_factor==0)		load.power_factor = 0.95;

	pTout = (double*)gl_get_addr(parent, "air_temperature");
	if (pTout==NULL)
	{
		static double default_air_temperature = 72;
		gl_warning("%s (%s:%d) parent object lacks air temperature, using %0f degF instead", hdr->name, hdr->oclass->name, hdr->id, default_air_temperature);
		pTout = &default_air_temperature;
	}

	/* derived values */
	Tair = gl_random_uniform(RNGSTATE,Tset-thermostat_deadband/2, Tset+thermostat_deadband/2);

	// size is used to couple Cw and Qrated
	Cf = size/10.0 * RHOWATER * CWATER;  // cf * lb/cf * BTU/lb/degF = BTU / degF

	rated_capacity = BTUPHPW * size*10; // BTU/h ... 10 BTU.h / cf (34W/cf, so ~700 for a full-sized refrigerator)

	// duty cycle estimate for initial condition
	if (gl_random_bernoulli(RNGSTATE,0.1)){
		Qr = rated_capacity;
	} else {
		Qr = 0;
	}

	// initial demand
	load.total = Qr * KWPBTUPH;

	return residential_enduse::init(parent);
}
示例#8
0
int dishwasher::init(OBJECT *parent)
{
	// default properties
	if(shape.params.analog.power == 0){
		shape.params.analog.power = gl_random_uniform(1000, 3000);		// dishwasher size [W]
	}
	if(load.heatgain_fraction == 0){
		load.heatgain_fraction = 0.50;  //Assuming 50% of the power is transformed to internal heat
	}
	if(load.power_factor == 0){
		load.power_factor = 0.95;
	}

	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;

	/* handle schedules */
	switch(shape.type){
		case MT_UNKNOWN:
			break;
		case MT_ANALOG:
			break;
		case MT_PULSED:
			break;
		case MT_MODULATED:
			break;
		case MT_QUEUED:
			break;
		default:
			char name[64];
			if(hdr->name == 0){
				sprintf(name, "%s:%s", hdr->oclass->name, hdr->id);
			}
			gl_error("dishwasher %s schedule of an unrecognized type", hdr->name ? hdr->name : name);
	}

	return residential_enduse::init(parent);
}
int clotheswasher::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("clotheswasher::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}
	hdr->flags |= OF_SKIPSAFE;
	
	// default properties
	if (shape.params.analog.power==0) shape.params.analog.power = gl_random_uniform(&hdr->rng_state,0.100,0.750);		// clotheswasher size [W]
	if (load.heatgain_fraction==0) load.heatgain_fraction = 0.5; 
	if (load.power_factor==0) load.power_factor = 0.95;

	if(shape.params.analog.power < 0.1){
		gl_error("clotheswasher motor is undersized, using 500W motor");
		shape.params.analog.power = 0.5;
	}

	int res = residential_enduse::init(parent);

	Is_on = 0;
	
	if(NORMAL_PREWASH_ENERGY == 0) NORMAL_PREWASH_ENERGY = 12*20*60;
	if(NORMAL_WASH_ENERGY == 0) NORMAL_WASH_ENERGY = 4*40*60;
	if(NORMAL_SMALLWASH_ENERGY == 0) NORMAL_SMALLWASH_ENERGY = 2*25*60;
	if(NORMAL_SPIN_LOW_ENERGY == 0) NORMAL_SPIN_LOW_ENERGY = 2*60*60;
	if(NORMAL_SPIN_MEDIUM_ENERGY == 0) NORMAL_SPIN_MEDIUM_ENERGY = 2*150*60;
	if(NORMAL_SPIN_HIGH_ENERGY == 0) NORMAL_SPIN_HIGH_ENERGY = 2*220*60;

	if(NORMAL_PREWASH_POWER == 0) NORMAL_PREWASH_POWER = 20;
	if(NORMAL_WASH_POWER == 0) NORMAL_WASH_POWER = 40;
	if(NORMAL_SMALLWASH_POWER == 0) NORMAL_SMALLWASH_POWER = 25;
	if(NORMAL_SPIN_LOW_POWER == 0) NORMAL_SPIN_LOW_POWER = 60;
	if(NORMAL_SPIN_MEDIUM_POWER == 0) NORMAL_SPIN_MEDIUM_POWER = 150;
	if(NORMAL_SPIN_HIGH_POWER == 0) NORMAL_SPIN_HIGH_POWER = 220;	

	if(PERMPRESS_PREWASH_ENERGY == 0) PERMPRESS_PREWASH_ENERGY = 12*20*60;
	if(PERMPRESS_WASH_ENERGY == 0) PERMPRESS_WASH_ENERGY = 4*40*60;
	if(PERMPRESS_SMALLWASH_ENERGY == 0) PERMPRESS_SMALLWASH_ENERGY = 2*25*60;
	if(PERMPRESS_SPIN_LOW_ENERGY == 0) PERMPRESS_SPIN_LOW_ENERGY = 2*60*60;
	if(PERMPRESS_SPIN_MEDIUM_ENERGY == 0) PERMPRESS_SPIN_MEDIUM_ENERGY = 2*150*60;
	if(PERMPRESS_SPIN_HIGH_ENERGY == 0) PERMPRESS_SPIN_HIGH_ENERGY = 2*220*60;

	if(PERMPRESS_PREWASH_POWER == 0) PERMPRESS_PREWASH_POWER = 20;
	if(PERMPRESS_WASH_POWER == 0) PERMPRESS_WASH_POWER = 40;
	if(PERMPRESS_SMALLWASH_POWER == 0) PERMPRESS_SMALLWASH_POWER = 25;
	if(PERMPRESS_SPIN_LOW_POWER == 0) PERMPRESS_SPIN_LOW_POWER = 60;
	if(PERMPRESS_SPIN_MEDIUM_POWER == 0) PERMPRESS_SPIN_MEDIUM_POWER = 150;
	if(PERMPRESS_SPIN_HIGH_POWER == 0) PERMPRESS_SPIN_HIGH_POWER = 220;	

	if(GENTLE_PREWASH_ENERGY == 0) GENTLE_PREWASH_ENERGY = 12*20*60;
	if(GENTLE_WASH_ENERGY == 0) GENTLE_WASH_ENERGY = 4*40*60;
	if(GENTLE_SMALLWASH_ENERGY == 0) GENTLE_SMALLWASH_ENERGY = 2*25*60;
	if(GENTLE_SPIN_LOW_ENERGY == 0) GENTLE_SPIN_LOW_ENERGY = 2*60*60;
	if(GENTLE_SPIN_MEDIUM_ENERGY == 0) GENTLE_SPIN_MEDIUM_ENERGY = 2*150*60;
	if(GENTLE_SPIN_HIGH_ENERGY == 0) GENTLE_SPIN_HIGH_ENERGY = 2*220*60;

	if(GENTLE_PREWASH_POWER == 0) GENTLE_PREWASH_POWER = 20;
	if(GENTLE_WASH_POWER == 0) GENTLE_WASH_POWER = 40;
	if(GENTLE_SMALLWASH_POWER == 0) GENTLE_SMALLWASH_POWER = 25;
	if(GENTLE_SPIN_LOW_POWER == 0) GENTLE_SPIN_LOW_POWER = 60;
	if(GENTLE_SPIN_MEDIUM_POWER == 0) GENTLE_SPIN_MEDIUM_POWER = 150;
	if(GENTLE_SPIN_HIGH_POWER == 0) GENTLE_SPIN_HIGH_POWER = 220;	
	
	if(normal_perc == 0) normal_perc = 0.5;	
	if(perm_press_perc == 0) perm_press_perc = 0.8;	
	
	return res;
}
/** 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);
}
示例#11
0
double refrigerator::update_refrigerator_state(double dt0,TIMESTAMP t1)
{
	OBJECT *hdr = OBJECTHDR(this);
	
	// accumulate the energy
	energy_used += refrigerator_power*dt0;

	if(cycle_time>0)
	{
		cycle_time -= dt0;
	}	

	if(defrostDelayed>0)
	{
		defrostDelayed -= dt0;
	}	

	if(defrostDelayed<=0){
		if(DC_TIMED==defrost_criterion){
			run_defrost = true;
		}
		else if(DC_COMPRESSOR_TIME==defrost_criterion && total_compressor_time>=compressor_defrost_time){
			
			run_defrost = true;
			total_compressor_time = 0;
			check_defrost = false;
			
		}
		else if(no_of_defrost>0 && DC_DOOR_OPENINGS==defrost_criterion){

			run_defrost = true;
			FF_Door_Openings = 0;
			check_defrost = false;
		}
	}
	else{
		if(DC_TIMED==defrost_criterion){
			check_defrost = true;
		}
		else if(DC_COMPRESSOR_TIME==defrost_criterion && total_compressor_time>=compressor_defrost_time){
			check_defrost = true;
			
		}
		else if(no_of_defrost>0 && DC_DOOR_OPENINGS==defrost_criterion){
			check_defrost = true;
		}
	}

	
	if(long_compressor_cycle_time>0)
	{
		long_compressor_cycle_time -= dt0;
	}	

	if (dr_mode_double == 0)
		dr_mode = DM_UNKNOWN;
	else if (dr_mode_double == 1)
		dr_mode = DM_LOW;
	else if (dr_mode_double == 2)
		dr_mode = DM_NORMAL;
	else if (dr_mode_double == 3)
		dr_mode = DM_HIGH;
	else if (dr_mode_double == 4)
		dr_mode = DM_CRITICAL;
	else
		dr_mode = DM_UNKNOWN;	

	if(door_return_time > 0){
		door_return_time = door_return_time - dt0;
	}
		
	if(door_next_open_time > 0){
		door_next_open_time = door_next_open_time - dt0;
	}

	if(door_return_time<=0 && true==door_open){
		door_return_time = 0;
		door_open = false;				
	}

	if(door_next_open_time<=0 && hourly_door_opening>0){
		door_next_open_time = 0;
		door_open = true;
		FF_Door_Openings++;
		door_return_time += ceil(gl_random_uniform(&hdr->rng_state,0, door_open_time));
		door_energy_calc = true;
		hourly_door_opening--;	
		
		if(hourly_door_opening > 0){
			door_next_open_time = int(gl_random_uniform(&hdr->rng_state,0,(3600-(t1-start_time)%3600))); // next_door_openings[hourly_door_opening-1] - ((t1-start_time)%3600);	
			door_to_open = true;
		}
		else{
			door_to_open = false;
		}	

		check_DO = FF_Door_Openings%DO_Thershold;

		if(check_DO==0){ 	
			no_of_defrost++;
			
		}		
	}


	if(((t1-start_time)%3600)==0 && start_time>0)
	{
		double temp_hourly_door_opening = (door_opening_criterion*daily_door_opening) - floor(door_opening_criterion*daily_door_opening);
		if(temp_hourly_door_opening >= 0.5){
			 hourly_door_opening = ceil(door_opening_criterion*daily_door_opening);					 
		}
		else{
			 hourly_door_opening = floor(door_opening_criterion*daily_door_opening);
		}

		hourly_door_opening = floor(gl_random_normal(&hdr->rng_state,hourly_door_opening, ((hourly_door_opening)/3)));
			
		//Clip the hourly door openings
		if(hourly_door_opening<0){
			hourly_door_opening = 0;
		}
		else if(hourly_door_opening>2*hourly_door_opening){
			hourly_door_opening = 2*hourly_door_opening;
		}

		if(hourly_door_opening > long_compressor_cycle_threshold*daily_door_opening)
		{
			long_compressor_cycle_due = true;
			long_compressor_cycle_time = int(gl_random_uniform(&hdr->rng_state,0,(3600)));	
		}

		if(hourly_door_opening>0){	
			door_to_open = true;
			door_next_open_time = int(gl_random_uniform(&hdr->rng_state,0,(3600)));			
		}
		else{
			door_to_open = false;
		}
	}
	
	double dt1 = 0;
	
	switch(state){

		case RS_DEFROST:
			
			if ((energy_used >= energy_needed || cycle_time <= 0))
			{				
				state = RS_COMPRESSSOR_ON_LONG;
				refrigerator_power = long_compressor_cycle_power;
				energy_needed = long_compressor_cycle_energy;
				energy_used = 0;

				cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);							
			}			
			else
			{
				refrigerator_power = defrost_power;
			}

		break;

		case RS_COMPRESSSOR_ON_NORMAL:	

			if(run_defrost==true)
			{
				state = RS_DEFROST;
				refrigerator_power = defrost_power;
				energy_needed = defrost_energy;
				energy_used = 0;

				cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);

				run_defrost=false;
				no_of_defrost--;

				defrostDelayed = delay_defrost_time;
								
			}
			else if ((energy_used >= energy_needed || cycle_time <= 0))
			{						
				state = RS_COMPRESSSOR_OFF_NORMAL;
				refrigerator_power = compressor_off_normal_power;
				energy_needed = compressor_off_normal_energy;				 		
				
				energy_used = 0;
				cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);	
				//new_running_state = true;
			}			
			else
			{
				refrigerator_power = compressor_on_normal_power;
				total_compressor_time += dt0;
				if(door_energy_calc==true){
					door_energy_calc = false;

					energy_needed += door_return_time*refrigerator_power;
					cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);
				
				}
			}

		break;

		case RS_COMPRESSSOR_ON_LONG:	

			if(run_defrost==true)
			{
				state = RS_DEFROST;
				refrigerator_power = defrost_power;
				energy_needed = defrost_energy;
				energy_used = 0;

				cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);

				run_defrost=false;
				no_of_defrost--;

				defrostDelayed = delay_defrost_time;
								
			}
			else if ((energy_used >= energy_needed || cycle_time <= 0))
			{						
				state = RS_COMPRESSSOR_OFF_NORMAL;
				refrigerator_power = compressor_off_normal_power;
				energy_needed = compressor_off_normal_energy;				 		
				
				energy_used = 0;
				cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);	
				//new_running_state = true;
			}			
			else
			{
				refrigerator_power = long_compressor_cycle_power;		
				if(door_energy_calc==true){
					door_energy_calc = false;

					energy_needed += door_return_time*refrigerator_power;
					cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);
				
				}
			}

		break;

		case RS_COMPRESSSOR_OFF_NORMAL:

			if(run_defrost==true)
			{
				state = RS_DEFROST;
				refrigerator_power = defrost_power;
				energy_needed = defrost_energy;
				energy_used = 0;

				cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);

				run_defrost=false;
				no_of_defrost--;

				defrostDelayed = delay_defrost_time;
								
			}
			else if ((energy_used >= energy_needed || cycle_time <= 0))
			{										
				if(long_compressor_cycle_due==true && long_compressor_cycle_time<=0)
				{
					state = RS_COMPRESSSOR_ON_LONG;
					refrigerator_power = long_compressor_cycle_power;
					energy_needed = long_compressor_cycle_energy;

					long_compressor_cycle_due=false;
					
					energy_used = 0;
					cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);		
				}
				else{
					
					state = RS_COMPRESSSOR_ON_NORMAL;
					refrigerator_power = compressor_on_normal_power;
					energy_needed = compressor_on_normal_energy;	
										
					energy_used = 0;
					cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);
				}
			}			
			else
			{				
				refrigerator_power = compressor_off_normal_power;	

				if(door_energy_calc==true){
					door_energy_calc = false;

					energy_needed -= door_return_time*compressor_off_normal_power;
					cycle_time = ceil((energy_needed - energy_used)/refrigerator_power);
					
					if(cycle_time<0)
						cycle_time = 0;
				}
			}

		break;		
		
	}

	double posted_power = refrigerator_power;

	//***************************
	if(door_open==true)
	{
		posted_power += door_opening_power;
	}
	//***************************

	if(check_icemaking == true)
	{
		posted_power += icemaking_power;
		icemaker_running = true;

		return_time = 60-dt0;

		if(0==((t1-start_time)%60) || return_time<=0){			
			
			ice_making_no--;
			
			if(ice_making_no == 0)
			{
				check_icemaking = false;					
			}

			return_time = 60;
		}		
		
	}
	else
	{
		if(((t1-start_time)%60)==0) 
		{
			ice_making = double(gl_random_uniform(&hdr->rng_state,0,1));			

			if(ice_making <=ice_making_probability)
			{			
				check_icemaking = true;

				icemaker_running = true;

			//	ice_making_no = gl_random_sampled(3,ice_making_time);

				ice_making_no = 1;

				posted_power += icemaking_power;
				return_time = 60;			
				ice_making_no--;	

				if(ice_making_no == 0)
				{
					check_icemaking = false;
				}
			}
			else
			{
				icemaker_running = false;
				return_time = 60;	
			}
		}	
		else
		{
			icemaker_running = false;

		}
	}	
	
	load.power.SetPowerFactor(posted_power/1000, load.power_factor);
	load.admittance = complex(0,0,J); 
	load.current = complex(0,0,J);		

	if(true==door_open && true==door_to_open)
	{
		door_time = door_return_time<door_next_open_time?door_return_time:door_next_open_time;
	}
	else if(true==door_to_open)
	{
		door_time = door_next_open_time;
	}
	else if(true==door_open){
		
		door_time = door_return_time;

	}
	else if(start_time>0)
	{
		door_time = (3600 - ((t1-start_time)%3600));
	}

	if(0.0==return_time)
	{
		dt1 = cycle_time>door_time?door_time:cycle_time;		
	}
	else
	{
		if(cycle_time>return_time)
			if(return_time>door_time)
				if(door_time>long_compressor_cycle_time)
					dt1 = long_compressor_cycle_time;
				else
					dt1 = door_time;					
			else 
				if(return_time>long_compressor_cycle_time)
					dt1 = long_compressor_cycle_time;
				else
					dt1 = return_time;
		else
			if(cycle_time>door_time)
				if(door_time>long_compressor_cycle_time)
					dt1 = long_compressor_cycle_time;
				else
					dt1 = door_time;
			else
				if(cycle_time>long_compressor_cycle_time)
					dt1 = long_compressor_cycle_time;
				else
					dt1 = cycle_time;		 
	}
	if(check_defrost == true){
		if(dt1 > defrostDelayed){
			dt1 = defrostDelayed;
		}
	}


	load.total = load.power + load.current + load.admittance;
	total_power = (load.power.Re() + (load.current.Re() + load.admittance.Re()*load.voltage_factor)*load.voltage_factor);

	last_dr_mode = dr_mode;

	if ((dt1 > 0) && (dt1 < 1)){
		dt1 = 1;
	}

	return dt1;

}
示例#12
0
/** 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);
}
示例#13
0
int refrigerator::init(OBJECT *parent)
{

	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("refrigerator::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;

	// defaults for unset values */
	if (size==0)				size = gl_random_uniform(&hdr->rng_state,20,40); // cf
	if (thermostat_deadband==0) thermostat_deadband = gl_random_uniform(&hdr->rng_state,2,3);
	if (Tset==0)				Tset = gl_random_uniform(&hdr->rng_state,35,39);
	if (UA == 0)				UA = 0.6;
	if (UAr==0)					UAr = UA+size/40*gl_random_uniform(&hdr->rng_state,0.9,1.1);
	if (UAf==0)					UAf = gl_random_uniform(&hdr->rng_state,0.9,1.1);
	if (COPcoef==0)				COPcoef = gl_random_uniform(&hdr->rng_state,0.9,1.1);
	if (Tout==0)				Tout = 59.0;
	if (load.power_factor==0)		load.power_factor = 0.95;

	pTout = (double*)gl_get_addr(parent, "air_temperature");
	if (pTout==NULL)
	{
		static double default_air_temperature = 72;
		gl_warning("%s (%s:%d) parent object lacks air temperature, using %0f degF instead", hdr->name, hdr->oclass->name, hdr->id, default_air_temperature);
		pTout = &default_air_temperature;
	}

	/* derived values */
	Tair = gl_random_uniform(&hdr->rng_state,Tset-thermostat_deadband/2, Tset+thermostat_deadband/2);

	// size is used to couple Cw and Qrated
	Cf = size/10.0 * RHOWATER * CWATER;  // cf * lb/cf * BTU/lb/degF = BTU / degF

	rated_capacity = BTUPHPW * size*10; // BTU/h ... 10 BTU.h / cf (34W/cf, so ~700 for a full-sized refrigerator)

	start_time = 0;

	if(compressor_off_normal_energy==0) compressor_off_normal_energy=15*45*60; //watt-secs
	if(compressor_off_normal_power==0) compressor_off_normal_power=15; //watt

	if(long_compressor_cycle_energy==0) long_compressor_cycle_energy=120*100*60; //watt-secs
	if(long_compressor_cycle_power==0) long_compressor_cycle_power=120; //watt

	if(compressor_on_normal_energy==0) compressor_on_normal_energy=120*35*60; //watt-secs
	if(compressor_on_normal_power==0) compressor_on_normal_power=120; //watt

	if(defrost_energy==0) defrost_energy=40*550*60; //watt-secs
	if(defrost_power==0) defrost_power=550; //watt

	if(icemaking_energy==0) icemaking_energy=300*60; //watt-secs
	if(icemaking_power==0) icemaking_power=300; //watt

	if(ice_making_probability==0) ice_making_probability=0.02; //watt
	
	if(DO_Thershold==0) DO_Thershold=24; 	
	if(long_compressor_cycle_threshold==0) long_compressor_cycle_threshold=0.05;

	if(FF_Door_Openings==0) FF_Door_Openings=0;

	if(door_opening_power==0) door_opening_power=16;

	if(delay_defrost_time==0) delay_defrost_time=28800;	

	if(defrost_criterion==0) defrost_criterion=DC_TIMED;	
	
	refrigerator_power = 0;

	return_time = 0;

	no_of_defrost = 0;

	total_compressor_time = 0;

	if(door_open_time==0) door_open_time=7;
	
	long_compressor_cycle_due=false;
	door_energy_calc = false;

	ice_making_time = new double[1,2,3]; 

	icemaker_running = false;
	check_defrost = false;

	switch(state){
		case RS_DEFROST:
			if(energy_needed==0) energy_needed = defrost_energy;
			cycle_time = ceil((energy_needed - energy_used)/defrost_power);
		break;
		case RS_COMPRESSSOR_OFF_NORMAL:
			if(energy_needed==0) energy_needed = compressor_off_normal_energy;
			cycle_time = ceil((energy_needed - energy_used)/compressor_off_normal_power);
		break;		
		case RS_COMPRESSSOR_ON_NORMAL:
			if(energy_needed==0) energy_needed = compressor_on_normal_energy;
			cycle_time = ceil((energy_needed - energy_used)/compressor_on_normal_power);
		break;		
	}

	run_defrost = false;

	if (is_240)
	{
		load.config = EUC_IS220;
	}

	load.total = Qr * KWPBTUPH;

	return residential_enduse::init(parent);
}
示例#14
0
double dishwasher::update_state(double dt) //,TIMESTAMP t1)
{	
	// accumulate the energy

	OBJECT *hdr = OBJECTHDR(this);

	energy_used += total_power/1000 * dt/3600;


switch(state) {

	case dishwasher_STOPPED:

		if (enduse_queue>1)// && dryer_on == true)
		
			dishwasher_run_prob = double(gl_random_uniform(&hdr->rng_state,queue_min,queue_max));
		
		if (enduse_queue > 1 && (dishwasher_run_prob > enduse_queue))
			{
				state = dishwasher_CONTROL_ONLY;
				if (Heateddry_option_check == true)
				energy_needed = energy_baseline;
				else
				energy_needed = 0.66*energy_baseline;

				cycle_duration = cycle_time = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
				cycle_time = pulse_interval[5];
				enduse_queue--;

				new_running_state = true;
				
			}
		else if (pCircuit->pV->Mag()<stall_voltage)
			{
				state = dishwasher_STALLED;
				state_time = 0;
			}
		break;

	case dishwasher_CONTROL_ONLY:

		if (energy_used >= energy_needed || cycle_time <= 0)
		{  
				if (energy_used >= energy_needed)
				{
					state = dishwasher_STOPPED;
					cycle_time = 0;
					energy_used = 0;

				control_check1 = false;
				control_check2 = false;
				control_check3 = false;

				control_check4 = false;
				control_check5 = false;
				control_check6 = false;

				control_check7 = false;
				control_check8 = false;
				control_check9 = false;
				control_check10 = false;
				control_check11 = false;
				control_check12 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;

				motor_only_check5 = false;
				motor_only_check6 = false;
				motor_only_check7 = false;
				motor_only_check8 = false;
				motor_only_check9 = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;

				heateddry_check1 = false;
				heateddry_check2 = false;

				coil_only_check1 = false;
				coil_only_check2 = false;
				coil_only_check3 = false;


				new_running_state = true;			

			}
		else if (cycle_time<=0)
			{			

				if (cycle_time<=0 && (control_check1 == false || control_check_temp == true))
				{
					state = dishwasher_MOTOR_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
					double interval = pulse_interval[0];

					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					control_check1 = true;
					control_check2 = true;
				}

				if (cycle_time<=0 && control_check2 == true)
				{
					state = dishwasher_MOTOR_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
					double interval = pulse_interval[7];
					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					control_check2 = false;
					control_check6 = true;
						
				}
				
				if (cycle_time<=0 && control_check3 == true)
				{
					state = dishwasher_MOTOR_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
					double interval = pulse_interval[6];
					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					control_check3 = false;
					control_check7 = true;
				}
				
				if (cycle_time<=0 && control_check4 == true)
				{
					state = dishwasher_MOTOR_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;								
					double interval = pulse_interval[9];
					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					control_check4 = false;
					control_check5 = true;
				}

				if (cycle_time<=0 && control_check5 == true)
				{
					state = dishwasher_MOTOR_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;								
					double interval = pulse_interval[4];
					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
									
					control_check5 = false;
					control_check8 = true;
				}

				
				
				if (cycle_time<=0 && control_check6 == true)
				{
					state = dishwasher_COIL_ONLY;

					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[1] * 60 * 60;

					double interval = pulse_interval[0];

					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					control_check6 = false;
					control_check3 = true;
									
				}


				if(cycle_time<=0 && (control_check7 == true))
				{

					state = dishwasher_MOTOR_COIL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[3]) * 60 * 60;
					double interval = pulse_interval[10];
						
						if (cycle_t > interval)
						cycle_time = interval;
						else
						cycle_time = cycle_t;	

						control_check7 = false;	
						control_check4 = true;	
				}


				if (cycle_time<=0 && control_check8 == true && count_control_only<5)
				{
					state = dishwasher_COIL_ONLY;

					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[1] * 60 * 60;

					double interval = pulse_interval[0];

					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					
					count_control_only += 1;

					if (count_control_only == 4)
					{
					
					control_check8 = false;
					control_check9 = true;	
					}
				}


				if (cycle_time<=0 && control_check9 == true && count_control_only1 < 7)
				{
					state = dishwasher_MOTOR_ONLY;

					double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;

					double interval = pulse_interval[0];

					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	

					count_control_only1 +=1;
					if (count_control_only1 ==6)
					{
					control_check9 = false;
					control_check10 = true;	
					}
				}

				if(cycle_time<=0 && (control_check10 == true))
				{

					state = dishwasher_MOTOR_COIL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[3]) * 60 * 60;
					double interval = pulse_interval[17];
						
						if (cycle_t > interval)
						cycle_time = interval;
						else
						cycle_time = cycle_t;	

						control_check10 = false;	
						control_check11 = true;	
				}


				if(cycle_time<=0 && control_check11 == true && Heateddry_option_check == true)
				{
					    state = dishwasher_HEATEDDRY_ONLY;

						double cycle_t = 1000 * (energy_needed - energy_used) / (coil_power[2]) * 60 * 60;
						double interval = pulse_interval[16];

						if (cycle_t > interval)
						cycle_time = interval;
						else
						cycle_time = cycle_t;	
						control_check11 = false;
						control_check12 = true;
				}

				if(cycle_time<=0 && control_check12 == true && Heateddry_option_check == true)
				{
					    state = dishwasher_HEATEDDRY_ONLY;

						double cycle_t = 1000 * (energy_needed - energy_used) / (coil_power[2]) * 60 * 60;
						double interval = pulse_interval[15];

						if (cycle_t > interval)
						cycle_time = interval;
						else
						cycle_time = cycle_t;	
						control_check12 = false;	
				}
				


						new_running_state = true;
			}		
		
		
		else if (pCircuit->pV->Mag()<stall_voltage)
			{
				state = dishwasher_STALLED;
				state_time = 0;
			}
	}
		break;

case dishwasher_MOTOR_ONLY:

		if (energy_used >= energy_needed || cycle_time<=0)
		{ 
			if (energy_used >= energy_needed)
			{
			state = dishwasher_STOPPED;
			cycle_time = 0;

				energy_used = 0;

				control_check1 = false;
				control_check2 = false;
				control_check3 = false;

				control_check4 = false;
				control_check5 = false;
				control_check6 = false;

				control_check7 = false;
				control_check8 = false;
				control_check9 = false;
				control_check10 = false;
				control_check11 = false;
				control_check12 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;

				motor_only_check5 = false;
				motor_only_check6 = false;
				motor_only_check7 = false;
				motor_only_check8 = false;
				motor_only_check9 = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;

				heateddry_check1 = false;
				heateddry_check2 = false;

				coil_only_check1 = false;
				coil_only_check2 = false;
				coil_only_check3 = false;


				new_running_state = true;		
			}		

		else if (cycle_time<=0)
			{
				state = dishwasher_CONTROL_ONLY;	
					
				if(cycle_time<=0 && (motor_only_check1 == false))
				
				{

					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[5];
					

					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;

					motor_only_check1 = true;	
					motor_only_check2 = true;
				}
											

				if(cycle_time<=0 && motor_only_check2 == true)
				{
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;

					double interval = pulse_interval[3];
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;
					
					motor_only_check2 = false;	

					motor_only_check3 = true;
				}
				
				if(cycle_time<=0 && motor_only_check3 == true && count_motor_only_68 < 3)

				{
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[5];

					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;

					count_motor_only_68 +=1;

					if (count_motor_only_68 ==2)
					{
					motor_only_check3 = false;	
					motor_only_check4 = true;	
					
					}
				}


				if(cycle_time<=0 && motor_only_check4 == true)
				{
					
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[2];
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;
					motor_only_check4 = false;	
					motor_only_check5 = true;	
				}

				if(cycle_time<=0 && motor_only_check5 == true && count_motor_only_25 <6)
				{
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[1];
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;

					count_motor_only_25 +=1;
					if (count_motor_only_25 == 5)
					{
					motor_only_check5 = false;	
					motor_only_check6 = true;	
					}
				}

				if(cycle_time<=0 && motor_only_check6 == true)
				{
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[7];
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;
					motor_only_check6 = false;	
					motor_only_check7 = true;	
					
				}

				if(cycle_time<=0 && motor_only_check7 == true && count_motor_only <6)
				{
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[4];
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;

					count_motor_only +=1;
					if (count_motor_only ==5)
					{
					motor_only_check7 = false;	
					motor_only_check8 = true;	
					}
					
				}

				if(cycle_time<=0 && motor_only_check8 == true)
				{
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[8];
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;

					motor_only_check8 = false;	
					motor_only_check9 = true;	
					
				}

				if(cycle_time<=0 && motor_only_check9 == true)
				{
					
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[12];
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;

					count_motor_only1 +=1;

					motor_only_check9 = false;	

				}		

					new_running_state = true;
			}		


		else if (pCircuit->pV->Mag()<stall_voltage)
			{
					state = dishwasher_STALLED;
					state_time = 0;
			}
		}
			
	break;
		
case dishwasher_MOTOR_COIL_ONLY:

	if (energy_used >= energy_needed || cycle_time <= 0)
		{  				
				if (energy_used >= energy_needed)
				{
				state = dishwasher_STOPPED;
				cycle_time = 0;
				energy_used = 0;

				
				control_check1 = false;
				control_check2 = false;
				control_check3 = false;

				control_check4 = false;
				control_check5 = false;
				control_check6 = false;

				control_check7 = false;
				control_check8 = false;
				control_check9 = false;
				control_check10 = false;
				control_check11 = false;
				control_check12 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;

				motor_only_check5 = false;
				motor_only_check6 = false;
				motor_only_check7 = false;
				motor_only_check8 = false;
				motor_only_check9 = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;

				heateddry_check1 = false;
				heateddry_check2 = false;

				coil_only_check1 = false;
				coil_only_check2 = false;
				coil_only_check3 = false;


				new_running_state = true;		

		}
	else if (cycle_time<=0)
		{
				state = dishwasher_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				

				if (cycle_time<=0 && motor_coil_only_check1 == false)
				{
					double interval = pulse_interval[11];
					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	

					motor_coil_only_check1 = true;
					motor_coil_only_check2 = true;
				}

				if(cycle_time<=0 && motor_coil_only_check2 == true)
				{
					double interval = pulse_interval[13];
					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					
					motor_coil_only_check2 = false;					
				}

					new_running_state = true;
		}		


	else if (pCircuit->pV->Mag()<stall_voltage)
		{
			state = dishwasher_STALLED;
			state_time = 0;
		}
	}
	break;

	

case dishwasher_HEATEDDRY_ONLY:
	
	if (energy_used >= energy_needed || cycle_time <= 0 )
		{  
			if (energy_used >= energy_needed)
			{
			state = dishwasher_STOPPED;
			cycle_time = 0;

				energy_used = 0;
				
				control_check1 = false;
				control_check2 = false;
				control_check3 = false;

				control_check4 = false;
				control_check5 = false;
				control_check6 = false;

				control_check7 = false;
				control_check8 = false;
				control_check9 = false;
				control_check10 = false;
				control_check11 = false;
				control_check12 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;

				motor_only_check5 = false;
				motor_only_check6 = false;
				motor_only_check7 = false;
				motor_only_check8 = false;
				motor_only_check9 = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;

				heateddry_check1 = false;
				heateddry_check2 = false;

				coil_only_check1 = false;
				coil_only_check2 = false;
				coil_only_check3 = false;


				new_running_state = true;		
		}		

	else if (cycle_time<=0 && heateddry_check1 == false)
			{
					state = dishwasher_CONTROL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / coil_power[0] * 60 * 60;
					double interval = pulse_interval[7];

					heateddry_check1 = true;
					heateddry_check2 = true;

					if (cycle_t > interval)
						cycle_time = interval;
					else
					cycle_time = cycle_t;


						new_running_state = true;
			}		


	else if (cycle_time<=0 && heateddry_check2 == true)
			{
					state = dishwasher_CONTROL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (coil_power[0]) * 60 * 60;
					double interval = pulse_interval[18];
					

					if (cycle_t > interval)
						cycle_time = interval;
					else
					cycle_time = cycle_t;
					motor_only_check2 = false;

					new_running_state = true;
			}	
			


	else if (pCircuit->pV->Mag()<stall_voltage)
			{
					state = dishwasher_STALLED;
					state_time = 0;
			}
	}
			
	break;

case dishwasher_COIL_ONLY:

	if (energy_used >= energy_needed || cycle_time <= 0)
		{  
			if (energy_used >= energy_needed)
			{
				state = dishwasher_STOPPED;
				cycle_time = 0;
				energy_used = 0;

				
				control_check1 = false;
				control_check2 = false;
				control_check3 = false;

				control_check4 = false;
				control_check5 = false;
				control_check6 = false;

				control_check7 = false;
				control_check8 = false;
				control_check9 = false;
				control_check10 = false;
				control_check11 = false;
				control_check12 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;

				motor_only_check5 = false;
				motor_only_check6 = false;
				motor_only_check7 = false;
				motor_only_check8 = false;
				motor_only_check9 = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;

				heateddry_check1 = false;
				heateddry_check2 = false;

				coil_only_check1 = false;
				coil_only_check2 = false;
				coil_only_check3 = false;


				new_running_state = true;		

		}
	else if (cycle_time<=0)
		{
				state = dishwasher_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				
				if (cycle_time<=0 && coil_only_check1 == false)
				{
					double interval = pulse_interval[8];
					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;

					coil_only_check1 = true;
					coil_only_check2 = true;
				}
				if(cycle_time<=0 && coil_only_check2 == true && count_coil_only <4)
				{
					double interval = pulse_interval[4];

					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	

					count_coil_only +=1;
					if (count_coil_only == 3)
					{
					coil_only_check2 = false;	
					coil_only_check3 = true;
					}
				}

				if(cycle_time<=0 && coil_only_check3 == true)
				{
					double interval = pulse_interval[14];

					if (cycle_t > interval)
					cycle_time = interval;
					else
					cycle_time = cycle_t;	
					coil_only_check3 = false;	
					
				}
				new_running_state = true;
		}		

	
	else if (pCircuit->pV->Mag()<stall_voltage)
		{
			state = dishwasher_STALLED;
			state_time = 0;
		}
	}
	break;

case dishwasher_STALLED:

		if (pCircuit->pV->Mag()>start_voltage)
		{
			state = dishwasher_MOTOR_ONLY;
			state_time = cycle_time;
		}
		else if (state_time>trip_delay)
		{
			state = dishwasher_TRIPPED;
			state_time = 0;
		}

	break;

case dishwasher_TRIPPED:

		if (state_time>reset_delay)
		{
			if (pCircuit->pV->Mag()>start_voltage)
				state = dishwasher_MOTOR_ONLY;
			else
				state = dishwasher_STALLED;
				state_time = 0;
		}

		break;
	}

	// accumulating units in the queue no matter what happens
	enduse_queue += daily_dishwasher_demand * dt/3600/24;
	//actual_dishwasher_demand = actual_dishwasher_demand + enduse_queue;
	
	// now implement current state
	switch(state) {
	case dishwasher_STOPPED: 
		
		// nothing running
		load.power = load.current = load.admittance = complex(0,0,J);

		dt = ((enduse_queue>=1) || (enduse_queue==0)) ? 0 : ((1-enduse_queue)*3600)/(enduse_queue*24); 				

		break;

	case dishwasher_MOTOR_COIL_ONLY:

		cycle_time -= dt;		
		load.power.SetPowerFactor(motor_power/1000, load.power_factor);
		load.admittance = complex((coil_power[3])/1000,0,J); //assume pure resistance
		load.current = complex(0,0,J);

		dt = cycle_time;
	break;

	case dishwasher_COIL_ONLY:

		cycle_time -= dt;	 
		load.power = load.current = complex(0,0,J);
		load.admittance = complex((coil_power[1])/1000,0,J); //assume pure resistance
	
	dt = cycle_time;
	break;


	case dishwasher_HEATEDDRY_ONLY:
	
	cycle_time -= dt;
	load.power = load.current = complex(0,0,J);
	load.admittance = complex((coil_power[2])/1000,0,J); //assume pure resistance
	
	dt = cycle_time;
	break;

	case dishwasher_CONTROL_ONLY:

		if(true==new_running_state){
			
			new_running_state = false;

		}
		else{

			cycle_time -= dt;
		}
		load.power = load.current = complex(0,0,J);
		load.admittance = complex(coil_power[0]/1000,0,J);

		dt = cycle_time;
		break;

	case dishwasher_STALLED:

		load.power = load.current = complex(0,0,J);
		load.admittance = complex(1)/stall_impedance;

		dt = trip_delay;

		break;

	case dishwasher_TRIPPED:

		load.power = load.current = load.admittance = complex(0,0,J);
		
		dt = reset_delay; 

		break;


	case dishwasher_MOTOR_ONLY:
		motor_on_off = 1;
		motor_coil_on_off = both_coils_on_off = 0;
		cycle_time -= dt;

		load.power.SetPowerFactor(motor_power/1000, load.power_factor);
		load.admittance = complex(0,0,J); 
		load.current = complex(0,0,J);

		dt = cycle_time;
		break;

	default:

		throw "unexpected motor state";
		/*	TROUBLESHOOT
			This is an error.  Please submit a bug report along with at the dishwasher
			object & class sections from the relevant GLM file, and from the dump file.
		*/
		break;
	}

	// compute the total electrical load - first for the enduse structure and second for an internal variable
	load.total = load.power + load.current + load.admittance;
	total_power = (load.power.Re() + (load.current.Re() + load.admittance.Re()*load.voltage_factor)*load.voltage_factor) * 1000;

	// compute the total heat gain
	load.heatgain = load.total.Mag() * heat_fraction;


	if (dt > 0 && dt < 1)
		dt = 1;

	return dt;
}
示例#15
0
int dishwasher::init(OBJECT *parent)
{
	// @todo This class has serious problems and should be deleted and started from scratch. Fuller 9/27/2013.

	OBJECT *hdr = OBJECTHDR(this);
	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("dishwasher::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}
	int rv = 0;
	// default properties
	if (motor_power==0) motor_power = gl_random_uniform(&hdr->rng_state,150,350);
	if (heat_fraction==0) heat_fraction = 0.2;
	if (is_240)
	{
		load.config = EUC_IS220;
		if (stall_voltage==0) stall_voltage  = 0.6*240;
	}
	else
		if (stall_voltage==0) stall_voltage  = 0.6*120;

	if (trip_delay==0) trip_delay = 10;
	if (reset_delay==0) reset_delay = 60;

	count_motor_only = 0;
	count_motor_only1 =0;
	count_motor_only_25 = 0;
	count_coil_only = 0;
	count_control_only =0;
	count_control_only1 =0;
	count_motor_only_68 =0;
	
	pulse_interval[0] = 8;
	pulse_interval[1] = 18;
	pulse_interval[2] = 21;
	pulse_interval[3] = 28;
	pulse_interval[4] = 38;
	pulse_interval[5] = 50;
	pulse_interval[6] = 65;

	pulse_interval[7] = 118;
	pulse_interval[8] = 150;
	pulse_interval[9] = 220;
	pulse_interval[10] = 320;
	pulse_interval[11] = 355;
	pulse_interval[12] = 460;
	pulse_interval[13] = 580;

	pulse_interval[14] = 615;
	pulse_interval[15] = 780;
	pulse_interval[16] = 800;
	pulse_interval[17] = 950;
	pulse_interval[18] = 1150;


	if (coil_power[0]==-1) coil_power[0] = 5800;

	coil_power[0] = 10;
	coil_power[1] = 580;
	coil_power[2] = 695;
	coil_power[3] = 950;
	motor_power = 250;

	enduse_queue = 1;
	queue_min = 0;
	queue_max = 2;

				control_check1 = false;
				control_check2 = false;
				control_check3 = false;

				control_check4 = false;
				control_check5 = false;
				control_check6 = false;

				control_check7 = false;
				control_check8 = false;
				control_check9 = false;
				control_check10 = false;
				control_check11 = false;
				control_check12 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;

				motor_only_check5 = false;
				motor_only_check6 = false;
				motor_only_check7 = false;
				motor_only_check8 = false;
				motor_only_check9 = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;

				heateddry_check1 = false;
				heateddry_check2 = false;

				coil_only_check1 = false;
				coil_only_check2 = false;
				coil_only_check3 = false;
				//Heateddry_option_check = false;


	hdr->flags |= OF_SKIPSAFE;

	load.power_factor = 0.95;
	load.breaker_amps = 30;
	actual_dishwasher_demand = 0;
	energy_needed = 0;

	rv = residential_enduse::init(parent);

	if (rv==SUCCESS) update_state(0.0);

	/* schedule checks */
	switch(shape.type){
		case MT_UNKNOWN:
			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("dishwasher does not support fixed energy shaping");

			} else if (shape.params.analog.power == 0){

				daily_dishwasher_demand = gl_get_loadshape_value(&shape) / 2.4449;
			} else {
				daily_dishwasher_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 ~ dishwasher demand X kW, limited by C + Q * h ~ Vdot proportional to power/time */
				daily_dishwasher_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		case MT_MODULATED:
			if(shape.params.modulated.pulsetype == MPT_TIME){
				GL_THROW("Amplitude modulated dishwasher usage is nonsensical for residential dishwashers");
				/*	TROUBLESHOOT
					Though it is possible to put a constant, low-level dishwasher demand, it is thoroughly
					counterintuitive to the normal usage of the dishwasher.
				 */
			} else if(shape.params.modulated.pulsetype == MPT_POWER){
				/* frequency modulated */
				/* fixed-amplitude, varying length pulses at regular intervals. */
				daily_dishwasher_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 ~ dishwasher demand X kW, limited by C + Q * h */
				daily_dishwasher_demand = gl_get_loadshape_value(&shape) / 2.4449;
			}
			break;
		default:
			GL_THROW("dishwasher load shape has an unknown state!");
			break;
	}
	return residential_enduse::init(parent);
//}
	// must run before update_state() so that pCircuit can be set


//	return rv;
}
示例#16
0
int house::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;

	// construct circuit variable map to meter
	struct {
		complex **var;
		char *varname;
	} map[] = {
		// local object name,	meter object name
		{&pCircuit_V,			"voltage_12"}, // assumes 1N and 2N follow immediately in memory
		{&pLine_I,				"current_1"}, // assumes 2 and 3(N) follow immediately in memory
		{&pLine12,				"current_12"}, // maps current load 1-2 onto triplex load
		/// @todo use triplex property mapping instead of assuming memory order for meter variables (residential, low priority) (ticket #139)
	};

	extern complex default_line_voltage[3], default_line_current[3];
	static complex default_line_current_12;
	int i;

	// find parent meter, if not defined, use a default meter (using static variable 'default_meter')
	OBJECT *obj = OBJECTHDR(this);
	if (parent!=NULL && gl_object_isa(parent,"triplex_meter"))
	{
		// attach meter variables to each circuit
		for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
		{
			if ((*(map[i].var) = get_complex(parent,map[i].varname))==NULL)
				GL_THROW("%s (%s:%d) does not implement triplex_meter variable %s for %s (house:%d)", 
				/*	TROUBLESHOOT
					The House requires that the triplex_meter contains certain published properties in order to properly connect
					the house circuit panel to the meter.  If the triplex_meter does not contain those properties, GridLAB-D may
					suffer fatal pointer errors.  If you encounter this error, please report it to the developers, along with
					the version of GridLAB-D that raised this error.
				*/
					parent->name?parent->name:"unnamed object", parent->oclass->name, parent->id, map[i].varname, obj->name?obj->name:"unnamed", obj->id);
		}
	}
	else
	{
		gl_error("house:%d %s; using static voltages", obj->id, parent==NULL?"has no parent triplex_meter defined":"parent is not a triplex_meter");
		/*	TROUBLESHOOT
			The House model relies on a triplex_meter as a parent to calculate voltages based on
			events within the powerflow module.  Create a triplex_meter object and set it as
			the parent of the house object.
		*/

		// attach meter variables to each circuit in the default_meter
		*(map[0].var) = &default_line_voltage[0];
		*(map[1].var) = &default_line_current[0];
		*(map[2].var) = &default_line_current_12;
	}
		// Set defaults for published variables nor provided by model definition
	while (floor_area <= 500)
		floor_area = gl_random_normal(RNGSTATE,2500,300);		// house size (sf) by 100 ft incs;

	if (ceiling_height <= ROUNDOFF)
		ceiling_height = 8.0;

	if (envelope_UA <= ROUNDOFF)
		envelope_UA = gl_random_uniform(RNGSTATE,0.15,0.2)*floor_area;	// UA of house envelope [BTU/h.F]

	if (aspect_ratio <= ROUNDOFF)
		aspect_ratio = 1.0;

	if (gross_wall_area <= ROUNDOFF)
		gross_wall_area = 4.0 * 2.0 * (aspect_ratio + 1.0) * ceiling_height * sqrt(floor_area/aspect_ratio);

	if (airchange_per_hour <= ROUNDOFF)
		airchange_per_hour = gl_random_uniform(RNGSTATE,4,6);			// air changes per hour [cf/h]

	if (thermostat_deadband <= ROUNDOFF)
		thermostat_deadband = 2;							// thermostat hysteresis [F]

	if (heating_setpoint <= ROUNDOFF)
		heating_setpoint = gl_random_uniform(RNGSTATE,68,72);	// heating setpoint [F]

	if (cooling_setpoint <= ROUNDOFF)
		cooling_setpoint = gl_random_uniform(RNGSTATE,76,80);	// cooling setpoint [F]

	if (window_wall_ratio <= ROUNDOFF)
		window_wall_ratio = 0.15;						// assuming 15% window wall ratio

	if (glazing_shgc <= ROUNDOFF)
		glazing_shgc = 0.65;								// assuming generic double glazing

	if (design_cooling_capacity <= ROUNDOFF)
		design_cooling_capacity = gl_random_uniform(RNGSTATE,18,24); // Btuh/sf

	if (design_heating_capacity <= ROUNDOFF)
		design_heating_capacity = gl_random_uniform(RNGSTATE,18,24); // Btuh/sf
	
	
	// initalize/set hvac model parameters
    if (COP_coeff <= ROUNDOFF)
	    COP_coeff = gl_random_uniform(RNGSTATE,0.9,1.1);	// coefficient of cops [scalar]
    
    if (Tair <= ROUNDOFF)
	    Tair = gl_random_uniform(RNGSTATE,heating_setpoint+thermostat_deadband, cooling_setpoint-thermostat_deadband);	// air temperature [F]
	
    if (over_sizing_factor <= ROUNDOFF)
        over_sizing_factor = gl_random_uniform(RNGSTATE,0.98,1.3);

    heat_cool_mode = house::OFF;							// heating/cooling mode {HEAT, COOL, OFF}

    if (house_content_heat_transfer_coeff <= ROUNDOFF)
	    house_content_heat_transfer_coeff = gl_random_uniform(RNGSTATE,0.5,1.0)*floor_area;	// heat transfer coefficient of house contents [BTU/hr.F]

	//house properties for HVAC
	volume = 8*floor_area;									// volume of air [cf]
	air_mass = air_density*volume;							// mass of air [lb]
	air_thermal_mass = air_heat_capacity*air_mass;			// thermal mass of air [BTU/F]
	Tmaterials = Tair;										// material temperture [F]
	hvac_rated_power = 24*floor_area*over_sizing_factor;	// rated heating/cooling output [BTU/h]

	if (set_Eigen_values() == FALSE)
		return 0;

	if (hdr->latitude < 24 || hdr->latitude > 48)
	{
		/* bind latitudes to [24N, 48N] */
		hdr->latitude = hdr->latitude<24 ? 24 : 48;
		gl_error("Latitude beyond the currently supported range 24 - 48 N, Simulations will continue assuming latitude %.0fN",hdr->latitude);
		/*	TROUBLESHOOT
			GridLAB-D currently only supports latitudes within a temperate band in the northern hemisphere for the building models.
			Latitudes outside 24N to 48N may not correctly calculate solar input.
		*/
	}

	// attach the house HVAC to the panel
	//attach(&load, 50, TRUE);
	hvac_circuit = attach_enduse_house_a(hdr, &load, 50, TRUE);

	return 1;
}
示例#17
0
double clotheswasher::update_state(double dt)
{

	OBJECT *hdr = OBJECTHDR(this);

	// accumulating units in the queue no matter what happens
	enduse_queue += enduse_demand * dt/3600/24;

	switch(state) {
	case STOPPED:

		if (enduse_queue>1)
		
			clotheswasher_run_prob = double(gl_random_uniform(&hdr->rng_state,queue_min,queue_max));
		
		if (enduse_queue > 1 && (clotheswasher_run_prob > enduse_queue))
			{		
			int temp_rand =  gl_random_uniform(&hdr->rng_state,0,1); 
			
			if(temp_rand <= normal_perc){
				wash_mode = NORMAL;
			}
			else if(temp_rand <= perm_press_perc){
				wash_mode = PERM_PRESS;
			}
			else{
				wash_mode = GENTLE;
			}
			
			switch(wash_mode){
				case NORMAL:
					cycle_time = ceil(NORMAL_PREWASH_ENERGY/NORMAL_PREWASH_POWER);
					clothesWasherPower = NORMAL_PREWASH_POWER;	
				break;
				case PERM_PRESS:
					cycle_time = ceil(PERMPRESS_PREWASH_ENERGY/PERMPRESS_PREWASH_POWER);
					clothesWasherPower = PERMPRESS_PREWASH_POWER;	
				break;
				case GENTLE:	
					cycle_time = ceil(GENTLE_PREWASH_ENERGY/GENTLE_PREWASH_POWER);
					clothesWasherPower = GENTLE_PREWASH_POWER;	
				break;
			}

			state = PREWASH;
			enduse_queue--;			
			Is_on = 1;
			new_running_state = true;
		}
		break;		
	case PREWASH:
		if (cycle_time<=0)
		{
			state = WASH;
			
			switch(wash_mode){
				case NORMAL:
					cycle_time = ceil(NORMAL_WASH_ENERGY/NORMAL_WASH_POWER);
					clothesWasherPower = NORMAL_WASH_POWER;	
				break;
				case PERM_PRESS:
					cycle_time = ceil(PERMPRESS_WASH_ENERGY/PERMPRESS_WASH_POWER);
					clothesWasherPower = PERMPRESS_WASH_POWER;	
				break;
				case GENTLE:	
					cycle_time = ceil(GENTLE_WASH_ENERGY/GENTLE_WASH_POWER);
					clothesWasherPower = GENTLE_WASH_POWER;	
				break;
			}

			new_running_state = true;
		}
		
		break;		
	case WASH:
		if (cycle_time<=0)
		{
			state = SPIN1;
			spin_mode = SPIN_LOW;
			
			switch(wash_mode){
				case NORMAL:
					cycle_time = ceil(NORMAL_SPIN_LOW_ENERGY/NORMAL_SPIN_LOW_POWER);
					clothesWasherPower = NORMAL_SPIN_LOW_POWER;	
				break;
				case PERM_PRESS:
					cycle_time = ceil(PERMPRESS_SPIN_LOW_ENERGY/PERMPRESS_SPIN_LOW_POWER);
					clothesWasherPower = PERMPRESS_SPIN_LOW_POWER;	
				break;
				case GENTLE:	
					cycle_time = ceil(GENTLE_SPIN_LOW_ENERGY/GENTLE_SPIN_LOW_POWER);
					clothesWasherPower = GENTLE_SPIN_LOW_POWER;	
				break;
			}
			
			new_running_state = true;
			
		}
		
		break;		
	case SPIN1:
		if (cycle_time<=0)
		{
			switch(spin_mode){
				case SPIN_LOW:
					spin_mode = SPIN_MEDIUM;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_MEDIUM_ENERGY/NORMAL_SPIN_MEDIUM_POWER);
							clothesWasherPower = NORMAL_SPIN_MEDIUM_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_MEDIUM_ENERGY/PERMPRESS_SPIN_MEDIUM_POWER);
							clothesWasherPower = PERMPRESS_SPIN_MEDIUM_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_MEDIUM_ENERGY/GENTLE_SPIN_MEDIUM_POWER);
							clothesWasherPower = GENTLE_SPIN_MEDIUM_POWER;	
						break;
					}

				break;
				case SPIN_MEDIUM:
					spin_mode = SPIN_HIGH;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_HIGH_ENERGY/NORMAL_SPIN_HIGH_POWER);
							clothesWasherPower = NORMAL_SPIN_HIGH_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_HIGH_ENERGY/PERMPRESS_SPIN_HIGH_POWER);
							clothesWasherPower = PERMPRESS_SPIN_HIGH_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_HIGH_ENERGY/GENTLE_SPIN_HIGH_POWER);
							clothesWasherPower = GENTLE_SPIN_HIGH_POWER;	
						break;
					}

				break;
				case SPIN_HIGH:
					
					spin_mode = SPIN_WASH;

					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_WASH_ENERGY/NORMAL_WASH_POWER);
							clothesWasherPower = NORMAL_WASH_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_WASH_ENERGY/PERMPRESS_WASH_POWER);
							clothesWasherPower = PERMPRESS_WASH_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_WASH_ENERGY/GENTLE_WASH_POWER);
							clothesWasherPower = GENTLE_WASH_POWER;	
						break;
					}
				case SPIN_WASH:
					
					state = SPIN2;
					spin_mode = SPIN_LOW;

					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_LOW_ENERGY/NORMAL_SPIN_LOW_POWER);
							clothesWasherPower = NORMAL_SPIN_LOW_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_LOW_ENERGY/PERMPRESS_SPIN_LOW_POWER);
							clothesWasherPower = PERMPRESS_SPIN_LOW_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_LOW_ENERGY/GENTLE_SPIN_LOW_POWER);
							clothesWasherPower = GENTLE_SPIN_LOW_POWER;	
						break;
					}

				break;
				
			}
			
			new_running_state = true;
		}		
		break;	
	case SPIN2:
		if (cycle_time<=0)
		{
			switch(spin_mode){
				case SPIN_LOW:
					spin_mode = SPIN_MEDIUM;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_MEDIUM_ENERGY/NORMAL_SPIN_MEDIUM_POWER);
							clothesWasherPower = NORMAL_SPIN_MEDIUM_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_MEDIUM_ENERGY/PERMPRESS_SPIN_MEDIUM_POWER);
							clothesWasherPower = PERMPRESS_SPIN_MEDIUM_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_MEDIUM_ENERGY/GENTLE_SPIN_MEDIUM_POWER);
							clothesWasherPower = GENTLE_SPIN_MEDIUM_POWER;	
						break;
					}

				break;
				case SPIN_MEDIUM:
					spin_mode = SPIN_HIGH;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_HIGH_ENERGY/NORMAL_SPIN_HIGH_POWER);
							clothesWasherPower = NORMAL_SPIN_HIGH_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_HIGH_ENERGY/PERMPRESS_SPIN_HIGH_POWER);
							clothesWasherPower = PERMPRESS_SPIN_HIGH_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_HIGH_ENERGY/GENTLE_SPIN_HIGH_POWER);
							clothesWasherPower = GENTLE_SPIN_HIGH_POWER;	
						break;
					}

				break;
				case SPIN_HIGH:
					
					spin_mode = SPIN_WASH;

					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_WASH_ENERGY/NORMAL_WASH_POWER);
							clothesWasherPower = NORMAL_WASH_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_WASH_ENERGY/PERMPRESS_WASH_POWER);
							clothesWasherPower = PERMPRESS_WASH_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_WASH_ENERGY/GENTLE_WASH_POWER);
							clothesWasherPower = GENTLE_WASH_POWER;	
						break;
					}
				case SPIN_WASH:
					
					state = SPIN3;
					spin_mode = SPIN_LOW;

					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_LOW_ENERGY/NORMAL_SPIN_LOW_POWER);
							clothesWasherPower = NORMAL_SPIN_LOW_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_LOW_ENERGY/PERMPRESS_SPIN_LOW_POWER);
							clothesWasherPower = PERMPRESS_SPIN_LOW_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_LOW_ENERGY/GENTLE_SPIN_LOW_POWER);
							clothesWasherPower = GENTLE_SPIN_LOW_POWER;	
						break;
					}

				break;
				
			}
			
			new_running_state = true;
		}		
		break;
	case SPIN3:
		if (cycle_time<=0)
		{
			switch(spin_mode){
				case SPIN_LOW:
					spin_mode = SPIN_MEDIUM;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_MEDIUM_ENERGY/NORMAL_SPIN_MEDIUM_POWER);
							clothesWasherPower = NORMAL_SPIN_MEDIUM_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_MEDIUM_ENERGY/PERMPRESS_SPIN_MEDIUM_POWER);
							clothesWasherPower = PERMPRESS_SPIN_MEDIUM_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_MEDIUM_ENERGY/GENTLE_SPIN_MEDIUM_POWER);
							clothesWasherPower = GENTLE_SPIN_MEDIUM_POWER;	
						break;
					}

				break;
				case SPIN_MEDIUM:
					spin_mode = SMALLWASH;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SMALLWASH_ENERGY/NORMAL_SMALLWASH_POWER);
							clothesWasherPower = NORMAL_SMALLWASH_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SMALLWASH_ENERGY/PERMPRESS_SMALLWASH_POWER);
							clothesWasherPower = PERMPRESS_SMALLWASH_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SMALLWASH_ENERGY/GENTLE_SMALLWASH_POWER);
							clothesWasherPower = GENTLE_SMALLWASH_POWER;	
						break;
					}

				break;
				case SMALLWASH:
					
					state = SPIN4;
					spin_mode = SPIN_LOW;

					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_LOW_ENERGY/NORMAL_SPIN_LOW_POWER);
							clothesWasherPower = NORMAL_SPIN_LOW_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_LOW_ENERGY/PERMPRESS_SPIN_LOW_POWER);
							clothesWasherPower = PERMPRESS_SPIN_LOW_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_LOW_ENERGY/GENTLE_SPIN_LOW_POWER);
							clothesWasherPower = GENTLE_SPIN_LOW_POWER;	
						break;
					}

				break;
				
			}
		}		
		break;
	case SPIN4:
		if (cycle_time<=0)
		{
			switch(spin_mode){
				case SPIN_LOW:
					spin_mode = SPIN_MEDIUM;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SPIN_MEDIUM_ENERGY/NORMAL_SPIN_MEDIUM_POWER);
							clothesWasherPower = NORMAL_SPIN_MEDIUM_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SPIN_MEDIUM_ENERGY/PERMPRESS_SPIN_MEDIUM_POWER);
							clothesWasherPower = PERMPRESS_SPIN_MEDIUM_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SPIN_MEDIUM_ENERGY/GENTLE_SPIN_MEDIUM_POWER);
							clothesWasherPower = GENTLE_SPIN_MEDIUM_POWER;	
						break;
					}

				break;
				case SPIN_MEDIUM:
					spin_mode = SPIN_HIGH;
			
					//Longer high cycle, hence multiplication by 3
					switch(wash_mode){
						case NORMAL:
							
							cycle_time = ceil((NORMAL_SPIN_HIGH_ENERGY*3)/NORMAL_SPIN_HIGH_POWER);
							clothesWasherPower = NORMAL_SPIN_HIGH_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil((PERMPRESS_SPIN_HIGH_ENERGY*3)/PERMPRESS_SPIN_HIGH_POWER);
							clothesWasherPower = PERMPRESS_SPIN_HIGH_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil((GENTLE_SPIN_HIGH_ENERGY*3)/GENTLE_SPIN_HIGH_POWER);
							clothesWasherPower = GENTLE_SPIN_HIGH_POWER;	
						break;
					}

				break;
				case SPIN_HIGH:
					
					spin_mode = SMALLWASH;
			
					switch(wash_mode){
						case NORMAL:
							cycle_time = ceil(NORMAL_SMALLWASH_ENERGY/NORMAL_SMALLWASH_POWER);
							clothesWasherPower = NORMAL_SMALLWASH_POWER;	
						break;
						case PERM_PRESS:
							cycle_time = ceil(PERMPRESS_SMALLWASH_ENERGY/PERMPRESS_SMALLWASH_POWER);
							clothesWasherPower = PERMPRESS_SMALLWASH_POWER;	
						break;
						case GENTLE:	
							cycle_time = ceil(GENTLE_SMALLWASH_ENERGY/GENTLE_SMALLWASH_POWER);
							clothesWasherPower = GENTLE_SMALLWASH_POWER;	
						break;
					}
				break;
				case SMALLWASH:
					
					state = STOPPED;
					cycle_time = 0;
					clothesWasherPower = 0;
			
					Is_on = 0;

				break;
				
				}

				new_running_state = true;
		}		
		break;
	
	}
	
	if(state==STOPPED){
		// nothing running
		load.power = load.current = load.admittance = complex(0,0,J);		
		// time to next expected state change
		//dt = (enduse_demand<=0) ? -1 : 	dt = 3600/enduse_demand; 
		if(0==enduse_demand){
			
			if(true==starttime){
				dt=0;
			}
			else{
				dt = 3600;
			}

		}
		else{
			
			dt = (enduse_queue>=1) ? 0 : ((1-enduse_queue)*3600)/(enduse_demand*24); 	
			
		}

	}
	else{ 	

		if(new_running_state == true){
			new_running_state = false;	
			cycle_time = cycle_time-1;
		}
		else{
			cycle_time -=dt;			
		}		
		
		load.power = complex(clothesWasherPower/1000,0,J);		
		load.current = 0;
		load.admittance =0;
		
		dt = cycle_time; 	


	}

	// compute the total electrical load
	load.total = load.power;

	if (dt > 0 && dt < 1)
		dt = 1;

	return dt;
}
示例#18
0
double range::update_state(double dt1,TIMESTAMP t1)
{	
	OBJECT *hdr = OBJECTHDR(this);
	cooktop_energy_used += total_power_cooktop* dt1/3600;


switch(state_cooktop) {

	case CT_STOPPED:

		if (enduse_queue_cooktop>1)
		
		cooktop_run_prob = double(gl_random_uniform(&hdr->rng_state,queue_min,queue_max));
				
		if (enduse_queue_cooktop > 1 && (cooktop_run_prob > enduse_queue_cooktop))
			{
				state_cooktop = CT_STAGE_1_ONLY;
				cooktop_energy_needed = cooktop_energy_baseline;
				cycle_duration_cooktop = 1000 * (cooktop_energy_needed - cooktop_energy_used) /cooktop_coil_power[0] * 60 * 60;
				cycle_time_cooktop = cooktop_interval[0];
				cooktop_check = true;								
				enduse_queue_cooktop--;
				
			}
			
			else
			{
				state_cooktop = CT_STOPPED;
				state_time = 0;
				cycle_time_cooktop = 0;
				cooktop_energy_used = 0;
				cooktop_check = false;
				//enduse_queue_cooktop--;
			}
			
		break;

	case CT_STAGE_1_ONLY:
		
		
		if (cooktop_energy_used >= cooktop_energy_needed || time_cooktop_operation >= time_cooktop_setting || cycle_time_cooktop <= 0)
		{
				if (cooktop_energy_used >= cooktop_energy_needed || time_cooktop_operation >= time_cooktop_setting)
				{  // The dishes are clean
					state_cooktop = CT_STOPPED;
					cycle_time_cooktop = 0;
					cooktop_energy_used = 0;
					cooktop_check = false;
		
				}
							
				else if (cycle_time_cooktop <= 0)
				{  
					state_cooktop = CT_STAGE_2_ONLY;
					double cycle_t = 1000 * (cooktop_energy_needed - cooktop_energy_used) / cooktop_coil_power[2] * 60 * 60;
					double interval = cooktop_interval[1];
					cooktop_check = true;
					if (cycle_t > interval)
						cycle_time_cooktop = interval;
					else
						cycle_time_cooktop = cycle_t;
					
				}	
		
				else if (pCircuit->pV->Mag()<stall_voltage)
				{
					state_cooktop = CT_STALLED;
					state_time = 0;
				}

		}
		break;

case CT_STAGE_2_ONLY:

	if (cooktop_energy_used >= cooktop_energy_needed || time_cooktop_operation >= time_cooktop_setting || cycle_time_cooktop <= 0)
	{
			if (cooktop_energy_used >= cooktop_energy_needed || time_cooktop_operation >= time_cooktop_setting)
			{ 
				state_cooktop = CT_STOPPED;
				cycle_time_cooktop = 0;
				cooktop_energy_used = 0;			
				cooktop_check = false;
			}
					
			else if (cycle_time_cooktop <= 0)
			{  
				state_cooktop = CT_STAGE_3_ONLY;
				cooktop_check = true;
				cycle_time_cooktop = time_cooktop_setting - cooktop_interval[0] - cooktop_interval[1]; 
			}	

			else if (pCircuit->pV->Mag()<stall_voltage)
			{
				state_cooktop = CT_STALLED;
				state_time = 0;
			}

	}
break;

case CT_STAGE_3_ONLY:

			if (cooktop_energy_used >= cooktop_energy_needed ||  cycle_time_cooktop <= 0)
			{  // The dishes are clean
				state_cooktop = CT_STOPPED;
				cycle_time_cooktop = 0;
				cooktop_energy_used = 0;
				cooktop_check = false;
					
			}					

			else if (pCircuit->pV->Mag()<stall_voltage)
			{
				state_cooktop = CT_STALLED;
				state_time = 0;
			}


	break;

	case CT_STALLED:
		if (pCircuit->pV->Mag()>start_voltage)
		{
			state_cooktop = CT_STAGE_1_ONLY;
			state_time = cycle_time_cooktop;
			cooktop_check = false;
		}

		break;

	case CT_TRIPPED:
		if (state_time>reset_delay)
		{
			if (pCircuit->pV->Mag()>start_voltage)
				state_cooktop = CT_STAGE_1_ONLY;
			else
				state_cooktop = CT_STALLED;
			state_time = 0;
		}

		break;
	}
	


	// advance the state_time
	state_time += dt1;

	// accumulating units in the queue no matter what happens
//	enduse_queue_oven += enduse_demand_oven * dt/3600/24;
	enduse_queue_cooktop += enduse_demand_cooktop * dt1/3600/24;

	if (cooktop_check == true)
	time_cooktop_operation += 1;
	else
	time_cooktop_operation = 0;


	// now implement current state


	switch(state_cooktop) {
	case CT_STOPPED: 
		
		// nothing running
		load.power = load.current = load.admittance = complex(0,0,J);
		
		// time to next expected state_cooktop change
		//dt = (enduse_demand_cooktop<=0) ? -1 : 	dt = 3600/enduse_demand_cooktop; 
		dt1 = (enduse_queue_cooktop>=1) ? 0 : ((1-enduse_queue_cooktop)*3600)/(enduse_queue_cooktop*24); 	

		break;

	case CT_STAGE_1_ONLY:	

		//motor_on_off = motor_coil_on_off = both_coils_on_off = 1;
		cycle_time_cooktop -= dt1;

		load.power = load.current = complex(0,0,J);
		load.admittance = complex((cooktop_coil_power[0])/1000,0,J);

		dt1 = cycle_time_cooktop;
		break;

	case CT_STAGE_2_ONLY:	

	//motor_on_off = motor_coil_on_off = both_coils_on_off = 1;
	cycle_time_cooktop -= dt1;

	load.power = load.current = complex(0,0,J);
	load.admittance = complex((cooktop_coil_power[1])/1000,0,J);

	dt1 = cycle_time_cooktop;
	break;

	case CT_STAGE_3_ONLY:	

	//motor_on_off = motor_coil_on_off = both_coils_on_off = 1;
	cycle_time_cooktop -= dt1;

	load.power = load.current = complex(0,0,J);
	load.admittance = complex((cooktop_coil_power[2])/1000,0,J);

	dt1 = cycle_time_cooktop;
	break;

	case CT_STALLED:

		// running in constant impedance mode
		load.power = load.current = complex(0,0,J);
		load.admittance = complex(1)/stall_impedance;

		// time to trip
		dt1 = trip_delay;

		break;

	case CT_TRIPPED:

		// nothing running
		load.power = load.current = load.admittance = complex(0,0,J);
		
		// time to next expected state change
		dt1 = reset_delay; 

		break;

	
	default:

		throw "unexpected motor state";
		/*	TROUBLESHOOT
			This is an error.  Please submit a bug report along with at the range
			object & class sections from the relevant GLM file, and from the dump file.
		*/
		break;
	}

	load.total += load.power + load.current + load.admittance;
	total_power_cooktop = (load.power.Re() + (load.current.Re() + load.admittance.Re()*load.voltage_factor)*load.voltage_factor)*1000;


//End of cook top


	//total_power_range = total_power_cooktop + total_power_oven;
	// compute the total heat gain
	load.heatgain = load.total.Mag() * heat_fraction;


	if (dt1 > 0 && dt1 < 1)
		dt1 = 1;

	return dt1;

	}
示例#19
0
TIMESTAMP 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;
	OBJECT *hdr = OBJECTHDR(this);



	/* 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){
			; // continue
		} else {
			if (pState == 0)
				return next_run;
			else if (*pState == last_pState)
				return next_run;
		}
	}

	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)){
			double clear_price;
			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(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);
			} else if(clear_price > *pAvg && range_high != 0){
				set_temp = setpoint0 + (clear_price - *pAvg) * fabs(range_high) / (ramp_high * *pStd);
			} else {
				set_temp = setpoint0;
			}

			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("controller::postsync(): temp %f given p %f vs avg %f",set_temp, market->next.price, market->avg24);
		}

		if(dir > 0){
			if(*pMonitor > max){
				bid = 9999.0;
			} else if (*pMonitor < min){
				bid = 0.0;
				no_bid = 1;
			}
		} else if(dir < 0){
			if(*pMonitor < min){
				bid = 9999.0;
			} else if(*pMonitor > max){
				bid = 0.0;
				no_bid = 1;
			}
		} else if(dir == 0){
			if(*pMonitor < min){
				bid = 9999.0;
			} else if(*pMonitor > max){
				bid = 0.0;
				no_bid = 1;
			} else {
				bid = *pAvg; // override due to lack of "real" curve
			}
		}

		// calculate bid price
		if(*pMonitor > setpoint0){
			k_T = ramp_high;
			T_lim = range_high;
		} else if(*pMonitor < setpoint0) {
			k_T = ramp_low;
			T_lim = range_low;
		} else {
			k_T = 0.0;
			T_lim = 0.0;
		}

		if(bid < 0.0 && *pMonitor != setpoint0) {
			bid = *pAvg + ( (fabs(*pStd) < bid_offset) ? 0.0 : (*pMonitor - setpoint0) * (k_T * *pStd) / fabs(T_lim) );
		} else if(*pMonitor == setpoint0) {
			bid = *pAvg;
		}

		// 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(*pDemand > 0 && no_bid != 1){
			last_p = bid;
			last_q = *pDemand;
			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);
					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("controller:%d: residual unresponsive load is negative! (%.1f kW)", hdr->id, residual);
	} else if (control_mode == CN_DOUBLE_RAMP){
		/*
		double heat_range_high;
		double heat_range_low;
		double heat_ramp_high;
		double heat_ramp_low;
		double cool_range_high;
		double cool_range_low;
		double cool_ramp_high;
		double cool_ramp_low;
		*/

		DATETIME t_next;
		gl_localtime(t1,&t_next);

		// find crossover
		double midpoint = 0.0;
		if(cool_min - heat_max < *pDeadband){
			switch(resolve_mode){
				case RM_DEADBAND:
					midpoint = (heat_max + cool_min) / 2;
					if(midpoint - *pDeadband/2 < heating_setpoint0 || midpoint + *pDeadband/2 > cooling_setpoint0) {
						gl_error("The midpoint between the max heating setpoint and the min cooling setpoint must be half a deadband away from each base setpoint");
						return TS_INVALID;
					} else {
						heat_max = midpoint - *pDeadband/2;
						cool_min = midpoint + *pDeadband/2;
					}
					break;
				case RM_SLIDING:
					if(heat_max > cooling_setpoint0 - *pDeadband) {
						gl_error("the max heating setpoint must be a full deadband less than the cooling_base_setpoint");
						return TS_INVALID;
					}

					if(cool_min < heating_setpoint0 + *pDeadband) {
						gl_error("The min cooling setpoint must be a full deadband greater than the heating_base_setpoint");
						return TS_INVALID;
					}
					if(last_mode == TM_OFF || last_mode == TM_COOL){
						heat_max = cool_min - *pDeadband;
					} else if (last_mode == TM_HEAT){
						cool_min = heat_max + *pDeadband;
					}
					break;
				default:
					gl_error("unrecognized resolve_mode when double_ramp overlap resolution is needed");
					break;
			}
		}
		// if the market has updated,
		if(lastmkt_id != market->market_id){
			lastmkt_id = market->market_id;
			lastbid_id = -1;
			// retrieve cleared price
			double clear_price;
			clear_price = market->current_frame.clearing_price;
			if(clear_price == last_p){
				// determine what to do at the marginal price
				switch(market->clearing_type){
					case CT_SELLER:	// may need to curtail
						break;
					case CT_PRICE:	// should not occur
					case CT_NULL:	// q zero or logic error ~ should not occur
						// occurs during the zero-eth market.
						//gl_warning("clearing price and bid price are equal with a market clearing type that involves inequal prices");
						break;
					default:
						break;
				}
			}
			may_run = 1;
			// calculate setpoints
			if(fabs(*pStd) < bid_offset){
				*pCoolingSetpoint = cooling_setpoint0;
				*pHeatingSetpoint = heating_setpoint0;
			} else {
				if(clear_price > *pAvg){
					*pCoolingSetpoint = cooling_setpoint0 + (clear_price - *pAvg) * fabs(cool_range_high) / (cool_ramp_high * *pStd);
					//*pHeatingSetpoint = heating_setpoint0 + (clear_price - *pAvg) * fabs(heat_range_high) / (heat_ramp_high * *pStd);
					*pHeatingSetpoint = heating_setpoint0 + (clear_price - *pAvg) * fabs(heat_range_low) / (heat_ramp_low * *pStd);
				} else if(clear_price < *pAvg){
					*pCoolingSetpoint = cooling_setpoint0 + (clear_price - *pAvg) * fabs(cool_range_low) / (cool_ramp_low * *pStd);
					//*pHeatingSetpoint = heating_setpoint0 + (clear_price - *pAvg) * fabs(heat_range_low) / (heat_ramp_low * *pStd);
					*pHeatingSetpoint = heating_setpoint0 + (clear_price - *pAvg) * fabs(heat_range_high) / (heat_ramp_high * *pStd);
				} else {
					*pCoolingSetpoint = cooling_setpoint0;
					*pHeatingSetpoint = heating_setpoint0;
				}
			}

			// apply overrides
			if((use_override == OU_ON)){
				if(last_q != 0.0){
					if(clear_price == last_p && clear_price != market->pricecap){
						if(market->margin_mode == AM_DENY){
							*pOverride = -1;
						} else if(market->margin_mode == AM_PROB){
							double r = gl_random_uniform(0, 1.0);
							if(r < market->current_frame.marginal_frac){
								*pOverride = 1;
							} else {
								*pOverride = -1;
							}
						}
					} else if(market->current_frame.clearing_price <= last_p){				
						*pOverride = 1;
					} else {
						*pOverride = -1;
					}
				} else { // equality
					*pOverride = 0; // 'normal operation'
				}
			}

			//clip
			if(*pCoolingSetpoint > cool_max)
				*pCoolingSetpoint = cool_max;
			if(*pCoolingSetpoint < cool_min)
				*pCoolingSetpoint = cool_min;
			if(*pHeatingSetpoint > heat_max)
				*pHeatingSetpoint = heat_max;
			if(*pHeatingSetpoint < heat_min)
				*pHeatingSetpoint = heat_min;

			lastmkt_id = market->market_id;


		}
		
		// submit bids
		double previous_q = last_q; //store the last value, in case we need it
		last_p = 0.0;
		last_q = 0.0;
		// We have to cool
		if(*pMonitor > cool_max){
			last_p = market->pricecap;
			last_q = *pCoolingDemand;
		}
		// We have to heat
		else if(*pMonitor < heat_min){
			last_p = market->pricecap;
			last_q = *pHeatingDemand;
		}
		// We're floating in between heating and cooling
		else if(*pMonitor > heat_max && *pMonitor < cool_min){
			last_p = 0.0;
			last_q = 0.0;
		}
		// We might heat, if the price is right
		else if(*pMonitor <= heat_max && *pMonitor >= heat_min){
			double ramp, range;
			ramp = (*pMonitor > heating_setpoint0 ? heat_ramp_high : heat_ramp_low);
			range = (*pMonitor > heating_setpoint0 ? heat_range_high : heat_range_low);
			if(*pMonitor != cooling_setpoint0){
				last_p = *pAvg + ( (fabs(*pStd) < bid_offset) ? 0.0 : (*pMonitor - heating_setpoint0) * ramp * (*pStd) / fabs(range) );
			} else {
				last_p = *pAvg;
			}
			last_q = *pHeatingDemand;
		}
		// We might cool, if the price is right
		else if(*pMonitor <= cool_max && *pMonitor >= cool_min){
			double ramp, range;
			ramp = (*pMonitor > cooling_setpoint0 ? cool_ramp_high : cool_ramp_low);
			range = (*pMonitor > cooling_setpoint0 ? cool_range_high : cool_range_low);
			if(*pMonitor != cooling_setpoint0){
				last_p = *pAvg + ( (fabs(*pStd) < bid_offset) ? 0 : (*pMonitor - cooling_setpoint0) * ramp * (*pStd) / fabs(range) );
			} else {
				last_p = *pAvg;
			}
			last_q = *pCoolingDemand;
		}
			if(last_p > market->pricecap)
				last_p = market->pricecap;
			if(last_p < -market->pricecap)
				last_p = -market->pricecap;
		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);
				return TS_INVALID;
			}
		}
		if(last_q > 0.001){
			if (pState != 0 ) {
				KEY bid = (KEY)(lastmkt_id == market->market_id ? lastbid_id : -1);
				lastbid_id = submit_bid_state(this->pMarket, OBJECTHDR(this), -last_q, last_p, (*pState > 0 ? 1 : 0), bid);
			}
			else {
				KEY bid = (KEY)(lastmkt_id == market->market_id ? lastbid_id : -1);
				lastbid_id = submit_bid(this->pMarket, OBJECTHDR(this), -last_q, last_p, bid);
			}
		}
		else
		{
			if (last_pState != *pState)
			{
				KEY bid = (KEY)(lastmkt_id == market->market_id ? lastbid_id : -1);
				double my_bid = -market->pricecap;
				if (*pState != 0)
					my_bid = last_p;

				lastbid_id = submit_bid_state(this->pMarket, OBJECTHDR(this), -last_q, my_bid, (*pState > 0 ? 1 : 0), bid);
			}
		}
	}

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

	char timebuf[128];
	gl_printtime(t1,timebuf,127);
	//gl_verbose("controller:%i::sync(): bid $%f for %f kW at %s",hdr->id,last_p,last_q,timebuf);
	//return postsync(t0, t1);
	return TS_NEVER;
}
示例#20
0
double dryer::update_state(double dt) //,TIMESTAMP t1)
{	
	OBJECT *hdr = OBJECTHDR(this);
	// accumulate the energy
	energy_used += total_power/1000 * dt/3600;


switch(state) {

	case DRYER_STOPPED:

		if (enduse_queue>1)// && dryer_on == true)
		
			dryer_run_prob = double(gl_random_uniform(&hdr->rng_state,queue_min,queue_max));
		
		if (enduse_queue > 1 && (dryer_run_prob > enduse_queue))
			{
				state = DRYER_CONTROL_ONLY;
				energy_needed = energy_baseline;
				cycle_duration = cycle_time = 1000 * (energy_needed - energy_used) / controls_power * 60 * 60;
				cycle_time = pulse_interval[0];
				//cycle_duration_dryer = pulse_interval[0];
				enduse_queue--;

				new_running_state = true;
				
			}
		else if (pCircuit->pV->Mag()<stall_voltage)
			{
				state = DRYER_STALLED;
				state_time = 0;
			}
		break;

	case DRYER_CONTROL_ONLY:

		if (energy_used >= energy_needed && cycle_time <= 0)
			{  // The clothes are dry
				state = DRYER_STOPPED;
				cycle_time = 0;
				energy_used = 0;

				control_check = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;
				motor_coil_only_check3 = false;
				motor_coil_only_check4 = false;
				motor_coil_only_check5 = false;
				motor_coil_only_check6 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;
				motor_only_check5 = false;
				motor_only_check6 = false;

				new_running_state = true;			


			}
		else if (cycle_time<=0 && control_check == false)//one-over
			{
					state = DRYER_MOTOR_COIL_ONLY;;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
					double interval = pulse_interval[1];
					control_check = true;
					motor_coil_only_check1 = true;

						if (cycle_t > interval)
							cycle_time = interval;
						else
							cycle_time = cycle_t;	

						new_running_state = true;
			}		

		
		else if (pCircuit->pV->Mag()<stall_voltage)
			{
				state = DRYER_STALLED;
				state_time = 0;
			}
		break;

		
case DRYER_MOTOR_COIL_ONLY:

	if (energy_used >= energy_needed && cycle_time <= 0)
		{  // The clothes are dry
				state = DRYER_STOPPED;
				cycle_time = 0;
				energy_used = 0;

				control_check = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;
				motor_coil_only_check3 = false;
				motor_coil_only_check4 = false;
				motor_coil_only_check5 = false;
				motor_coil_only_check6 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;
				motor_only_check5 = false;
				motor_only_check6 = false;

				new_running_state = true;

		}
	else if (cycle_time<=0 && motor_coil_only_check1 == true)//one-over
		{
				state = DRYER_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				double interval = pulse_interval[0];
				motor_coil_only_check1 = false;
				motor_coil_only_check2 = true;
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;	

					new_running_state = true;
		}		

	else if (cycle_time<=0 && motor_coil_only_check2 == true)//two-over
		{
				state = DRYER_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				double interval = pulse_interval[3];
				motor_coil_only_check2 = false;
				motor_coil_only_check3 = true;
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;
				new_running_state = true;
		}	

	else if (cycle_time<=0 && motor_coil_only_check3 == true)//three-over
		{
				state = DRYER_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				double interval = pulse_interval[3];
				motor_coil_only_check3 = false;
				motor_coil_only_check4 = true;
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;

					new_running_state = true;
		}	

	else if (cycle_time<=0 && motor_coil_only_check4 == true)//four-over
		{
				state = DRYER_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				double interval = pulse_interval[3];
				motor_coil_only_check4 = false;
				motor_coil_only_check5 = true;
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;	
				new_running_state = true;
		}	
	else if (cycle_time<=0 && motor_coil_only_check5 == true)//five-over
		{
				state = DRYER_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				double interval = pulse_interval[5];
				motor_coil_only_check5 = false;
				motor_coil_only_check6 = true;
					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;		

				new_running_state = true;
		}

	else if (cycle_time<=0 && motor_coil_only_check6 == true)//five-over
		{
				state = DRYER_MOTOR_ONLY;
				double cycle_t = 1000 * (energy_needed - energy_used) / motor_power * 60 * 60;
				motor_only_check6 = false;
				new_running_state = true;
/*					if (cycle_t > interval)
						cycle_time = interval;
					else
						cycle_time = cycle_t;	*/		
		}
	else if (pCircuit->pV->Mag()<stall_voltage)
		{
			state = DRYER_STALLED;
			state_time = 0;
		}
	break;

	case DRYER_MOTOR_ONLY:

		if (energy_used >= energy_needed)
		{  // The clothes are dry
			state = DRYER_STOPPED;
			cycle_time = 0;

				energy_used = 0;
				control_check = false;

				motor_coil_only_check1 = false;
				motor_coil_only_check2 = false;
				motor_coil_only_check3 = false;
				motor_coil_only_check4 = false;
				motor_coil_only_check5 = false;
				motor_coil_only_check6 = false;

				motor_only_check1 = false;
				motor_only_check2 = false;
				motor_only_check3 = false;
				motor_only_check4 = false;
				motor_only_check5 = false;
				motor_only_check6 = false;

				new_running_state = true;
		}		

		else if (cycle_time<=0 && motor_only_check1 == false)//one-over
			{
					state = DRYER_MOTOR_COIL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
					double interval = pulse_interval[2];

					motor_only_check1 = true;
					motor_only_check2 = true;

						if (cycle_t > interval)
							cycle_time = interval;
						else
							cycle_time = cycle_t;
						new_running_state = true;
			}		


		else if (cycle_time<=0 && motor_only_check2 == true)//two-over
			{
					state = DRYER_MOTOR_COIL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
					double interval = pulse_interval[4];

					motor_only_check2 = false;
					motor_only_check3 = true;

						if (cycle_t > interval)
							cycle_time = interval;
						else
							cycle_time = cycle_t;

						new_running_state = true;
			}	

		else if (cycle_time<=0 && motor_only_check3 == true)//three-over
			{
					state = DRYER_MOTOR_COIL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
					double interval = pulse_interval[4];

					motor_only_check3 = false;
					motor_only_check4 = true;

						if (cycle_t > interval)
							cycle_time = interval;
						else
							cycle_time = cycle_t;
						new_running_state = true;
			}	

		else if (cycle_time<=0 && motor_only_check4 == true)//four-over
			{
					state = DRYER_MOTOR_COIL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
					double interval = pulse_interval[4];

					motor_only_check4 = false;
					motor_only_check5 = true;
					
						if (cycle_t > interval)
							cycle_time = interval;
						else
							cycle_time = cycle_t;
						new_running_state = true;
			}	

		else if (cycle_time<=0 && motor_only_check5 == true)//five-over
			{
					state = DRYER_MOTOR_COIL_ONLY;
					double cycle_t = 1000 * (energy_needed - energy_used) / (motor_power + coil_power[0]) * 60 * 60;
					double interval = pulse_interval[6];

					motor_only_check5 = false;
					
						if (cycle_t > interval)
							cycle_time = interval;
						else
							cycle_time = cycle_t;	
						new_running_state = true;
			}	

		else if (pCircuit->pV->Mag()<stall_voltage)
			{
					state = DRYER_STALLED;
					state_time = 0;
			}
			
	break;

	case DRYER_STALLED:

		if (pCircuit->pV->Mag()>start_voltage)
		{
			state = DRYER_MOTOR_ONLY;
			state_time = cycle_time;
		}
		else if (state_time>trip_delay)
		{
			state = DRYER_TRIPPED;
			state_time = 0;
		}

	break;

	case DRYER_TRIPPED:

		if (state_time>reset_delay)
		{
			if (pCircuit->pV->Mag()>start_voltage)
				state = DRYER_MOTOR_ONLY;
			else
				state = DRYER_STALLED;
				state_time = 0;
		}

		break;
	}
	

	// accumulating units in the queue no matter what happens
	if (dryer_on == true)
	{
	enduse_queue += daily_dryer_demand * dt/24;
	}

	actual_dryer_demand = actual_dryer_demand + daily_dryer_demand;

	
	// now implement current state
	switch(state) {
	case DRYER_STOPPED: 
		
		motor_on_off = motor_coil_on_off = 0;

		// nothing running
		load.power = load.current = load.admittance = complex(0,0,J);

		dt = ((enduse_queue>=1) || (enduse_queue==0)) ? 0 : ((1-enduse_queue)*3600)/(enduse_queue*24); 				

		break;

	case DRYER_MOTOR_COIL_ONLY:

		motor_on_off = motor_coil_on_off = 1;
		cycle_time -= dt;
		// running in constant power mode with intermittent coil
		load.power.SetPowerFactor(motor_power/1000, load.power_factor);
		load.admittance = complex((coil_power[0])/1000,0,J); //assume pure resistance
		load.current = complex(0,0,J);

		dt = cycle_time;
		break;

	case DRYER_CONTROL_ONLY:

		if(true==new_running_state){
			
			new_running_state = false;

		}
		else{

			cycle_time -= dt;
		}

		// running in constant power mode with intermittent coil
		load.power = load.current = complex(0,0,J);
		load.admittance = complex(controls_power/1000,0,J);

		dt = cycle_time;
		break;

	case DRYER_STALLED:

		// running in constant impedance mode
		load.power = load.current = complex(0,0,J);
		load.admittance = complex(1)/stall_impedance;

		// time to trip
		dt = trip_delay;

		break;

	case DRYER_TRIPPED:

		// nothing running
		load.power = load.current = load.admittance = complex(0,0,J);
		
		// time to next expected state change
		dt = reset_delay; 

		break;


	case DRYER_MOTOR_ONLY:
		motor_on_off = 1;
		cycle_time -= dt;

		// running in constant power mode with intermittent coil
		load.power.SetPowerFactor(motor_power/1000, load.power_factor);
		load.admittance = complex(0,0,J); //assume pure resistance
		load.current = complex(0,0,J);

		dt = cycle_time;
		break;

	default:

		throw "unexpected motor state";
		/*	TROUBLESHOOT
			This is an error.  Please submit a bug report along with at the dryer
			object & class sections from the relevant GLM file, and from the dump file.
		*/
		break;
	}

	// compute the total electrical load - first for the enduse structure and second for an internal variable
	load.total = load.power + load.current + load.admittance;
	total_power = (load.power.Re() + (load.current.Re() + load.admittance.Re()*load.voltage_factor)*load.voltage_factor) * 1000;

	// compute the total heat gain
	load.heatgain = load.total.Mag() * heat_fraction;


	if (dt > 0 && dt < 1)
		dt = 1;

	return dt;
}