Example #1
0
int generator::init(node *parent)
{
	// check sanity of initial state
	if (parent->type==PQ && !Qcontrolled)
	{
		OBJECT *obj = OBJECTHDR(this);
		gl_error("generator:%d is Qcontrolled but is not connected to a PQ bus", obj->id);
		return 0;
	}
	else if (parent->type!=PQ && Qcontrolled)
	{
		OBJECT *obj = OBJECTHDR(this);
		gl_error("generator:%d is not Qcontrolled but is connected to a PQ bus", obj->id);
		return 0;
	}
	else if (Qcontrolled && Qdesired_MVAR<Qmin_MVAR && Qdesired_MVAR>Qmax_MVAR)
	{
		OBJECT *obj = OBJECTHDR(this);
		gl_error("generator:%d Qdesired is out of Qmin/Qmax limits", obj->id);
		return 0;
	}
	else if (parent->type!=SWING && Pdesired_MW>Pmax_MW)
	{
		OBJECT *obj = OBJECTHDR(this);
		gl_error("generator:%d Pdesired exceeds Pmax", obj->id);
		return 0;
	}
	return 1;
}
Example #2
0
int motor::init(OBJECT *parent)
{
	int result = node::init();

	OBJECT *obj = OBJECTHDR(this);
	return result;
}
int residential_enduse::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;
	ATTACHFUNCTION attach = 0;

	//	pull parent attach_enduse and attach the enduseload
	if(parent)
		attach = (ATTACHFUNCTION)(gl_get_function(parent, "attach_enduse"));
	if(parent && attach)
		pCircuit = (*attach)(parent, &load, load.breaker_amps, (load.config&EUC_IS220)!=0);
	else if (parent)
		gl_warning("%s (%s:%d) parent %s (%s:%d) does not export attach_enduse function so voltage response cannot be modeled", hdr->name?hdr->name:"(unnamed)", hdr->oclass->name, hdr->id, parent->name?parent->name:"(unnamed)", parent->oclass->name, parent->id);
		/* TROUBLESHOOT
			Enduses must have a voltage source from a parent object that exports an attach_enduse function.  
			The residential_enduse object references a parent object that does not conform with this requirement.
			Fix the parent reference and try again.
		 */

	if (load.shape!=NULL) {
		if (load.shape->schedule==NULL)
		{
			gl_verbose("%s (%s:%d) schedule is not specified so the load may be inactive", hdr->name?hdr->name:"(unnamed)", hdr->oclass->name, hdr->id);
			/* TROUBLESHOOT
				The residential_enduse object requires a schedule that defines how
				the load behaves.  Omitting this schedule effectively shuts the enduse
				load off and this is not typically intended.
			 */
		}
	}

	return 1;
}
Example #4
0
TIMESTAMP generator::sync(TIMESTAMP t0) 
{
	TIMESTAMP t1 = TS_NEVER;
	OBJECT *obj = OBJECTHDR(this);
	node *pBus = OBJECTDATA(obj->parent,node);
	switch (pBus->type) {
		case SWING:
			// check for overlimit
			if (pBus->S.Re()>Pmax_MW || pBus->S.Im()<Qmin_MVAR || pBus->S.Im()>Qmax_MVAR)
			{
				// this happens because we don't support redispatching yet (after redispatch we could do tripping).
				gl_error("generator:%d exceeded limits when connected to swing bus; clock stopped", obj->id);
				return TS_ZERO;
			}
			break;
		case PV:
			// post real power and reactive limits
			pBus->S.Re() = Pdesired_MW;
			pBus->Qmax_MVAR = Qmax_MVAR;
			pBus->Qmin_MVAR = Qmin_MVAR;
			break;
		case PQ:
			// post both real and reactive power
			pBus->S = complex(Pdesired_MW,Qdesired_MVAR);
			break;
		default:
			break;
	}
	return t1;
}
Example #5
0
int dishwasher::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.voltage_factor = 1.0;
	load.power_factor = 0.95;
	load.power_fraction = 1;
	is_240 = true;

	state = dishwasher_STOPPED;
	
	energy_used = 0;
	
	coil_power[0] = -1;
	motor_on_off = motor_coil_on_off = both_coils_on_off = 0;

	last_t = 0;
	

	gl_warning("explicit %s model is experimental and has not been validated", OBJECTHDR(this)->oclass->name);
	/* TROUBLESHOOT
		The dishwasher explicit model has some serious issues and should be considered for complete
		removal.  It is highly suggested that this model NOT be used.
	*/

	return res;
}
Example #6
0
void range::wrong_model(enumeration msg)
{
	char *errtxt[] = {"model is not one-zone","model is not two-zone"};
	OBJECT *obj = OBJECTHDR(this);
	gl_warning("%s (range:%d): %s", obj->name?obj->name:"(anonymous object)", obj->id, errtxt[msg]);
	throw msg; // this must be caught by the range code, not by the core
}
Example #7
0
int dryer::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.voltage_factor = 1.0;
	load.power_factor = 0.95;
	load.power_fraction = 1;
	is_240 = true;

	coil_power[0] = -1;

	state = DRYER_STOPPED;
	
	energy_used = 0;	
	
	last_t = 0;	

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

	return res;
}
int transmissioncom::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	

	// input validation checks
	// * parent is a controller
	if(0 == parent){
		gl_error("init(): no parent object");
		return 0;
	}

	if(!gl_object_isa(parent, "substation", "powerflow") && !gl_object_isa(parent, "meter", "powerflow")){
		gl_error("init(): parent is not a powerflow:substation or a powerflow:meter.");
		return 0;
	}

	//TODO: datafromgld=gl_get_property.....
	datafromgld = get_complex(parent, power_property);
	datatogld = get_complex(parent, voltage_property);
	if(gl_object_isa(parent, "substation", "powerflow")){
		powerdiff = get_double(parent,"power_convergence_value");
	} else {
		default_powerdiff = 1; //default is 1 VA
		powerdiff = &default_powerdiff;
	}
	myinterface=Integrator::getCommInterface(hdr->name);
	printf("MY INTEFRACE is mull %d\n",myinterface==NULL);
}
Example #9
0
/*******************************************************************
 * collectors 
 */
int memory_open_collector(struct collector *my, char *fname, char *flags)
{
	time_t now=time(NULL);
	OBJECT *obj=OBJECTHDR(my);

	my->memory = (MEMORY*)malloc(sizeof(MEMORY));
	if (my->memory==NULL)
	{
		gl_error("memory_open_collector(struct recorder *my={...}, char *fname='%s', char *flags='%s'): %s", fname, flags, strerror(errno));
		my->status = TS_DONE;
		return 0;
	}
	my->memory->buffer = gl_global_find(fname);
	if (my->memory->buffer==NULL)
	{
		gl_error("memory_open_collector(struct recorder *my={...}, char *fname='%s', char *flags='%s'): global '%s' not found", fname, flags, fname);
		my->status = TS_DONE;
		return 0;
	}
	my->memory->index = 0;
	my->type = FT_MEMORY;
	my->last.ts = TS_ZERO;
	my->status=TS_OPEN;
	my->samples=0;
	return 1;

}
Example #10
0
/*******************************************************************
 * recorders 
 */
int file_open_recorder(struct recorder *my, char *fname, char *flags)
{
	time_t now=time(NULL);
	OBJECT *obj=OBJECTHDR(my);
	
	my->fp = (strcmp(fname,"-")==0?stdout:fopen(fname,flags));
	if (my->fp==NULL)
	{
		gl_error("recorder file %s: %s", fname, strerror(errno));
		my->status = TS_DONE;
		return 0;
	}
	my->type = FT_FILE;
	my->last.ts = TS_ZERO;
	my->status=TS_OPEN;
	my->samples=0;

	/* put useful header information in file first */
	fprintf(my->fp,"# file...... %s\n", my->file);
	fprintf(my->fp,"# date...... %s", asctime(localtime(&now)));
#ifdef WIN32
	fprintf(my->fp,"# user...... %s\n", getenv("USERNAME"));
	fprintf(my->fp,"# host...... %s\n", getenv("MACHINENAME"));
#else
	fprintf(my->fp,"# user...... %s\n", getenv("USER"));
	fprintf(my->fp,"# host...... %s\n", getenv("HOST"));
#endif
	fprintf(my->fp,"# target.... %s %d\n", obj->parent->oclass->name, obj->parent->id);
	fprintf(my->fp,"# trigger... %s\n", my->trigger[0]=='\0'?"(none)":my->trigger);
	fprintf(my->fp,"# interval.. %d\n", my->interval);
	fprintf(my->fp,"# limit..... %d\n", my->limit);
	fprintf(my->fp,"# timestamp,%s\n", my->property);

	return 1;
}
Example #11
0
//Module-level deltamode call
SIMULATIONMODE switch_object::inter_deltaupdate_switch(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val,bool interupdate_pos)
{
	OBJECT *hdr = OBJECTHDR(this);
	TIMESTAMP t0_val, t2_val;
	unsigned char work_phases_pre, work_phases_post;

	//Initialize - just set to random values, not used here
	t0_val = TS_NEVER;
	t2_val = TS_NEVER;

	if (interupdate_pos == false)	//Before powerflow call
	{
		//Link presync stuff
		NR_link_presync_fxn();

		//Switch sync item - pre-items
		BOTH_switch_sync_pre(&work_phases_pre,&work_phases_post);

		//Switch sync item - post items
		NR_switch_sync_post(&work_phases_pre,&work_phases_post,hdr,&t0_val,&t2_val);
		
		return SM_DELTA;	//Just return something other than SM_ERROR for this call
	}
	else	//After the call
	{
		//Call postsync
		BOTH_link_postsync_fxn();
		
		return SM_EVENT;	//Links always just want out
	}
}//End module deltamode
Example #12
0
TIMESTAMP switch_object::sync(TIMESTAMP t0)
{
	OBJECT *obj = OBJECTHDR(this);
	unsigned char work_phases_pre, work_phases_post;

	//Try to map the event_schedule function address, if we haven't tried yet
	if (event_schedule_map_attempt == false)
	{
		//First check to see if a fault_check object even exists
		if (fault_check_object != NULL)
		{
			//It exists, good start! - now see if the proper variable is populated!
			eventgen_obj = get_object(fault_check_object, "eventgen_object");

			//See if it worked - if not, assume it doesn't exist
			if (*eventgen_obj != NULL)
			{
				//It's not null, map up the scheduler function
				event_schedule = (FUNCTIONADDR)(gl_get_function(*eventgen_obj,"add_event"));
								
				//Make sure it was found
				if (event_schedule == NULL)
				{
					gl_warning("Unable to map add_event function in eventgen:%s",*(*eventgen_obj)->name);
					/*  TROUBLESHOOT
					While attempting to map the "add_event" function from an eventgen object, the function failed to be
					found.  Ensure the target object in fault_check is an eventgen object and this function exists.  If
					the error persists, please submit your code and a bug report via the trac website.
					*/
				}
			}
			//Defaulted elses - just leave things as is :(
		}
		//Defaulted else - doesn't exist, so leave function address empty

		//Flag the attempt as having occurred
		event_schedule_map_attempt = true;
	}

	//Update time variable
	if (prev_SW_time != t0)	//New timestep
		prev_SW_time = t0;

	//Call functionalized "pre-link" sync items
	BOTH_switch_sync_pre(&work_phases_pre, &work_phases_post);

	//Call overlying link sync
	TIMESTAMP t2=link_object::sync(t0);

	if (solver_method == SM_NR)
	{
		//Call functionalized "post-link" sync items
		NR_switch_sync_post(&work_phases_pre, &work_phases_post, obj, &t0, &t2);
	}

	if (t2==TS_NEVER)
		return(t2);
	else
		return(-t2);	//Soft limit it
}
double waterheater::actual_kW(void)
{
	OBJECT *obj = OBJECTHDR(this);
	const double nominal_voltage = 240.0; //@TODO:  Determine if this should be published or how we want to obtain this from the equipment/network
    static int trip_counter = 0;

	// calculate rated heat capacity adjusted for the current line voltage
	if (heat_needed && re_override != OV_OFF)
    {
		if(heat_mode == GASHEAT){
			return heating_element_capacity; /* gas heating is voltage independent. */
		}
		const double actual_voltage = pCircuit ? pCircuit->pV->Mag() : nominal_voltage;
        if (actual_voltage > 2.0*nominal_voltage)
        {
            if (trip_counter++ > 10)
				GL_THROW("Water heater line voltage for waterheater:%d is too high, exceeds twice nominal voltage.",obj->id);
			/*	TROUBLESHOOT
				The waterheater is receiving twice the nominal voltage consistantly, or about 480V on what
				should be a 240V circuit.  Please sanity check your powerflow model as it feeds to the
				meter and to the house.
			*/
            else
                return 0.0;         // @TODO:  This condition should trip the breaker with a counter
        }
		double test = heating_element_capacity * (actual_voltage*actual_voltage) / (nominal_voltage*nominal_voltage);
		return test;
    }
	else
		return 0.0;
}
TIMESTAMP refrigerator::presync(TIMESTAMP t0, TIMESTAMP t1){
	OBJECT *hdr = OBJECTHDR(this);
	double t = 0.0, dt = 0.0;
	double nHours = (gl_tohours(t1)- gl_tohours(t0))/TS_SECOND;

	Tout = *pTout;

	if(nHours > 0 && t0 > 0){ /* skip this on TS_INIT */
		const double COP = COPcoef*((-3.5/45)*(Tout-70)+4.5); /* come from ??? */

		if(t1 == next_time){
			/* lazy skip-ahead */
			load.heatgain = (-((Tair - Tout) * exp(-(UAr+UAf)/Cf) + Tout - Tair) * Cf + Qr * COP) * KWPBTUPH;
			Tair = Tevent;
		} else {
			/* run calculations */
			const double C1 = Cf/(UAr+UAf);
			const double C2 = Tout - Qr/UAr;
			load.heatgain = (-((Tair - Tout) * exp(-(UAr+UAf)/Cf) + Tout - Tair) * Cf  + Qr * COP) * KWPBTUPH;;
			Tair = (Tair-C2)*exp(-nHours/C1)+C2;
		}
		if (Tair < 32 || Tair > 55)
			throw "refrigerator air temperature out of control";
		last_time = t1;
	}

	return TS_NEVER;
}
void waterheater::wrong_model(WRONGMODEL msg)
{
	char *errtxt[] = {"model is not one-zone","model is not two-zone"};
	OBJECT *obj = OBJECTHDR(this);
	gl_warning("%s (waterheater:%d): %s", obj->name?obj->name:"(anonymous object)", obj->id, errtxt[msg]);
	throw msg; // this must be caught by the waterheater code, not by the core
}
Example #16
0
double house::get_Tsolar(int hour, int month, double Tair, double Tout)
{
	// Wood frame wall CLTD values from ASHRAE 1989 (for sunlighted walls in the north latitude)
	static double CLTD[] = {4.25, 2.75, 1.63, 0.50, -0.50, 3.50, 11.25, 17.88, 22.50, 25.88, 27.88, 29.25, 31.63, 35.13, 38.50, 40.38, 36.88, 28.00, 19.00, 14.00, 11.13, 8.63, 6.25};

	static double LM[4][24] =	{	
		{-1.33, -1.44, -0.89, -1.00, -0.67, -0.44, -0.67, -1.00, -0.89, -1.44, -1.33, -1.22},  // latitude 24
		{-2.89, -1.89, -0.78, -0.44, -0.11, -0.11, -0.11, -0.44, -0.78, -1.89, -2.89, -4.67},  // latitude 32
		{-5.44, -3.22, -1.11, -0.11, 0.22, 0.67, 0.22, -0.11, -1.11, -3.22, -5.44, -6.33},  // latitude 40
		{-7.56, -5.11, -1.78, -0.11, 1.33, 2.00, 1.33, -0.11, -1.78, -5.11, -7.56} // latitude 48
	};

	static double ColorSurface = 0.75;
	static double DR = 15.0;
	double solarTemp = Tair;
	double LMnow = 0.0;
	int LMcol = month-1;

	OBJECT *hdr = OBJECTHDR(this);

	if (hdr->latitude <= 24.0)
		LMnow = LM[0][LMcol];
	else if (hdr->latitude <= 32.)
		LMnow = LM[0][LMcol] + ((LM[1][LMcol]-LM[0][LMcol])*(hdr->latitude-24.0)/12.0);
	else if (hdr->latitude <= 40.)
		LMnow = LM[1][LMcol] + ((LM[2][LMcol]-LM[1][LMcol])*(hdr->latitude-32.0)/12.0);
	else if (hdr->latitude <= 48.)
		LMnow = LM[2][LMcol] + ((LM[3][LMcol]-LM[2][LMcol])*(hdr->latitude-40.0)/12.0);
	else // if (hdr->latitude > 48.0)
		LMnow = LM[3][LMcol];

	solarTemp += (CLTD[hour] + LMnow)*ColorSurface + (78. - Tair) + ((*pTout) - DR/2. - 85.);

	return solarTemp;
}
Example #17
0
int schedule::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	int rv = 1;

	currval = default_value;
	if(filename[0] == 0){
		rv = parse_schedule();
	} else {
		rv = open_sched_file();
	}
	
	if(rv == 0){
		state = TS_ERROR;
		strcpy(errmsg, "Error reading & parsing schedule input source");
	}
	/* group rules together here */

	/* ...or not (yet). */

	if(state == TS_INIT){
		state = TS_OPEN;
	} else if(state == TS_ERROR){
		gl_error("unable to open schedule");
		state = TS_DONE;
	}

	return 1;
}
Example #18
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
}
Example #19
0
/* Object initialization is called once after all object have been created */
int stubauction::init(OBJECT *parent)
{
	OBJECT *obj=OBJECTHDR(this);
	market_id = 0;
	if(period == 0) period = 300;
	clearat = nextclear();
	return 1; /* return 1 on success, 0 on failure */
}
/** Initialize water heater model properties - randomized defaults for all published variables
 **/
int virtual_battery::init(OBJECT *parent)
{
	
	parent2=parent;
	first_time=0;
	first_time2=0;
	actual=0;
	temp_capacity=0;
	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("virtual_battery::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;

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

						
						 auction_object=it1;
						
					 }

				 }
       /////////////////////////////////////////////////////////////////////////////////////////
       /////////////////////////////find climate object ///////////////////////////////////////

		FINDLIST *climates = NULL; 
		OBJECT *obj;
		climates = gl_find_objects(FL_NEW,FT_CLASS,SAME,"climate",FT_END);
		obj = gl_find_next(climates,NULL);

		if (gl_object_isa(obj,"climate"))
		{
			climate_object=obj;
		}





      ///////////////////////////////////////////////////////////////////////////////////////	
	// check the load configuration before initializing the parent class
	
	return 1;
	
}
Example #21
0
double node::get_obs_probability(void) const
{
	if (r2<0)
		return 1;
	double pr = exp(-0.5*r2); /// @todo there should be a 1/sqrt(2*pi) coeff on the observability probability, yet it works. (network, low priority)
	if (pr>1)
		gl_warning("node:%d observation probability exceeds 1!", OBJECTHDR(this)->id);
	return pr;
}
//////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION OF DELTA MODE
//////////////////////////////////////////////////////////////////////////
//Module-level call
SIMULATIONMODE triplex_node::inter_deltaupdate_triplex_node(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val,bool interupdate_pos)
{
	//unsigned char pass_mod;
	OBJECT *hdr = OBJECTHDR(this);

	if (interupdate_pos == false)	//Before powerflow call
	{
		//Call triplex-specific call
		BOTH_triplex_node_presync_fxn();

		//Call node presync-equivalent items
		NR_node_presync_fxn();

		//Call sync-equivalent of triplex portion first
		BOTH_triplex_node_sync_fxn();

		//Call node sync-equivalent items (solver occurs at end of sync)
		NR_node_sync_fxn(hdr);

		return SM_DELTA;	//Just return something other than SM_ERROR for this call
	}
	else	//After the call
	{
		//No triplex-specific postsync for node

		//Perform node postsync-like updates on the values
		BOTH_node_postsync_fxn(hdr);

		//No control required at this time - powerflow defers to the whims of other modules
		//Code below implements predictor/corrector-type logic, even though it effectively does nothing
		return SM_EVENT;

		////Do deltamode-related logic
		//if (bustype==SWING)	//We're the SWING bus, control our destiny (which is really controlled elsewhere)
		//{
		//	//See what we're on
		//	pass_mod = iteration_count_val - ((iteration_count_val >> 1) << 1);

		//	//Check pass
		//	if (pass_mod==0)	//Predictor pass
		//	{
		//		return SM_DELTA_ITER;	//Reiterate - to get us to corrector pass
		//	}
		//	else	//Corrector pass
		//	{
		//		//As of right now, we're always ready to leave
		//		//Other objects will dictate if we stay (powerflow is indifferent)
		//		return SM_EVENT;
		//	}//End corrector pass
		//}//End SWING bus handling
		//else	//Normal bus
		//{
		//	return SM_EVENT;	//Normal nodes want event mode all the time here - SWING bus will
		//						//control the reiteration process for pred/corr steps
		//}
	}
}
Example #23
0
//Perform post-event analysis (update computations, write event file if necessary) - no secondary count
void metrics::event_ended(OBJECT *event_obj, OBJECT *fault_obj, OBJECT *faulting_obj, TIMESTAMP event_start_time, TIMESTAMP event_end_time, char *fault_type, char *impl_fault, int number_customers_int)
{
	DATETIME start_dt, end_dt;
	TIMESTAMP outage_length;
	OBJECT *hdr = OBJECTHDR(this);
	int returnval;
	FILE *FPVal;

	//Determine the actual outage length (may be off due to iterations and such)
	outage_length = event_end_time - event_start_time;

	//Perform the calculation
	returnval = ((int (*)(OBJECT *, OBJECT *, int, int, TIMESTAMP, TIMESTAMP))(*compute_metrics))(hdr,module_metrics_obj,number_customers_int,CustomerCount,outage_length,metric_interval);

	//Make sure it worked
	if (returnval != 1)
	{
		GL_THROW("Metrics:%s failed to perform a post-event metric update",hdr->name);
		/*  TROUBLESHOOT
		While attempting to provide a post-fault update of relevant metrics, the metrics
		object encountered an error.  Please try your code again.  If the error persists,
		please submit your code and a bug report using the trac website.
		*/
	}

	//Increment the counters
	metric_interval_event_count++;
	annual_interval_event_count++;

	//Now that that's done, let's see if we need to write a file output
	if (report_event_log == true)
	{
		//Convert the times
		gl_localtime(event_start_time,&start_dt);
		gl_localtime(event_end_time,&end_dt);

		//Open the file handle
		FPVal = fopen(report_file,"at");

		//Print the name of the "safety" device?
		if (faulting_obj==NULL)
		{
		//Print the details out
			fprintf(FPVal,"%d,%d,%04d-%02d-%02d %02d:%02d:%02d,%04d-%02d-%02d %02d:%02d:%02d,%s,%s,%s,N/A,%s,%s,%d\n",annual_interval_event_count,metric_interval_event_count,start_dt.year,start_dt.month,start_dt.day,start_dt.hour,start_dt.minute,start_dt.second,end_dt.year,end_dt.month,end_dt.day,end_dt.hour,end_dt.minute,end_dt.second,fault_obj->oclass->name,fault_obj->name,event_obj->name,fault_type,impl_fault,number_customers_int);
		}
		else
		{
			//Print the details out
			fprintf(FPVal,"%d,%d,%04d-%02d-%02d %02d:%02d:%02d,%04d-%02d-%02d %02d:%02d:%02d,%s,%s,%s,%s,%s,%s,%d\n",annual_interval_event_count,metric_interval_event_count,start_dt.year,start_dt.month,start_dt.day,start_dt.hour,start_dt.minute,start_dt.second,end_dt.year,end_dt.month,end_dt.day,end_dt.hour,end_dt.minute,end_dt.second,fault_obj->oclass->name,fault_obj->name,event_obj->name,faulting_obj->name,fault_type,impl_fault,number_customers_int);
		}

		//Close the file
		fclose(FPVal);
	}
}
Example #24
0
int occupantload::init(OBJECT *parent)
{
	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("occupantload::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}
	if (number_of_occupants==0)	number_of_occupants = 4;		// defaulted to 4, but perhaps define it based on house size??
	if (heatgain_per_person==0) heatgain_per_person = 400.0;	// Based on DOE-2, includes latent and sensible heatgain

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

	if (parent==NULL || (!gl_object_isa(parent,"house") && !gl_object_isa(parent,"house_e")))
	{
		gl_error("occupantload must have a parent house");
		/*	TROUBLESHOOT
			The occupantload object, being an enduse for the house model, must have a parent house
			that it is connected to.  Create a house object and set it as the parent of the
			offending occupantload object.
		*/
		return 0;
	}

	//	pull parent attach_enduse and attach the enduseload
	FUNCTIONADDR attach = 0;
	load.end_obj = hdr;
	attach = (gl_get_function(parent, "attach_enduse"));
	if(attach == NULL){
		gl_error("occupantload parent must publish attach_enduse()");
		/*	TROUBLESHOOT
			The occupantload object attempt to attach itself to its parent, which
			must implement the attach_enduse function.
		*/
		return 0;
	}
	// Needed to pass heat gain up to the house
	// "true" on 220 keeps the circuits "balanced"
	((CIRCUIT *(*)(OBJECT *, ENDUSELOAD *, double, int))(*attach))(hdr->parent, &(this->load), 20, true);

	load.heatgain = number_of_occupants * occupancy_fraction * heatgain_per_person;

	if(shape.type != MT_UNKNOWN && shape.type != MT_ANALOG){
		char outname[64];
		if(hdr->name){
			//sprintf(outname, "%s", hdr->name);
		} else {
			sprintf(outname, "occupancy_load:%i", hdr->id);
		}
		gl_warning("occupancy_load \'%s\' may not work properly with a non-analog load shape.", hdr->name ? hdr->name : outname);
	}
	return 1;
}
Example #25
0
TIMESTAMP link::sync(TIMESTAMP t0) 
{
	node *f = OBJECTDATA(from,node);
	node *t = OBJECTDATA(to,node);

	// Note: n!=1 <=> B==0
	// compute line currents (note from/to switched)
	complex Ifrom = t->V * Yc;
	complex Ito = f->V * Yc;

	// add to self admittance (contribution diagonal terms)
	// add to current injections (contribution to off-diagonal terms)
	complex Ys = Yc + Yc*(c-1);
	LOCK_OBJECT(from);
	f->Ys += Ys;
	f->YVs += Ifrom;
	UNLOCK_OBJECT(from);

	Ys = Yc + Yeff*(1-c);
	LOCK_OBJECT(to);
	t->YVs += Ito;
	t->Ys += Ys;
	UNLOCK_OBJECT(to);

	// compute current over line (from->to)
	I = Ito - Ifrom;


#ifdef _DEBUG
	// link debugging
	if (debug_link==1)
	{
		OBJECT* obj = OBJECTHDR(this);
		static int first=-1;
		if (first==-1) first = obj->id;
		if (obj->id==first)
		{
			printf("\n");
			printf("Link  From -> To             R        X        B        Y                 Ifrom             Ito               I               \n");
			printf("===== ====================== ======== ======== ======== ================= ================= ================= =================\n");
		}
		printf("%2d-%2d %-9.9s -> %-9.9s %+8.4f %+8.4f %+8.4f %+8.4f%+8.4fj %+8.4f%+8.4fj %+8.4f%+8.4fj %+8.4f%+8.4fj\n", 
			from->id, to->id, 
			from->name,to->name,
			(complex(1,0)/Y).Re(),(complex(1,0)/Y).Im(), B,
			Y.Re(), Y.Im(),
			Ifrom.Re(), Ifrom.Im(), 
			Ito.Re(), Ito.Im(), 
			I.Re(), I.Im());
	}
#endif // _DEBUG

	return TS_NEVER;
}
int refrigerator::create() 
{
	int res = residential_enduse::create();

	// name of enduse
	load.name = oclass->name;

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

	return res;
}
Example #27
0
int relay::init(OBJECT *parent)
{
	int result = link::init(parent);

	if (recloser_limit == 0)
	{
		recloser_limit = 5;
		gl_warning("Recloser:%d tries limit was not specified, defaulted to 5 tries",OBJECTHDR(this)->id);
		/*  TROUBLESHOOT
		The recloser did not have a specified value for the maximum number of recloser tries.  5 was selected as a default value. 
		*/
	}

	if (recloser_delay == 0)
	{
		recloser_delay = 3;
		gl_warning("Recloser:%d reclose delay was not specified, defaulted to 3 seconds",OBJECTHDR(this)->id);
		/*  TROUBLESHOOT
		The recloser did not have a specified value for the recloser try delay.  3 was selected as a default value. 
		*/
	}

	if (recloser_delay<1.0)
	{
		GL_THROW("recloser delay must be at least 1 second");
		/*  TROUBLESHOOT
		The recloser delay must be at least one second long.  Please set the value of
		recloser_delay to something greater than or equal to 1.0.
		*/
	}
	
	a_mat[0][0] = d_mat[0][0] = A_mat[0][0] = (link::is_closed() && has_phase(PHASE_A) ? 1.0 : 0.0);
	a_mat[1][1] = d_mat[1][1] = A_mat[1][1] = (link::is_closed() && has_phase(PHASE_B) ? 1.0 : 0.0);
	a_mat[2][2] = d_mat[2][2] = A_mat[2][2] = (link::is_closed() && has_phase(PHASE_C) ? 1.0 : 0.0);

	b_mat[0][0] = c_mat[0][0] = B_mat[0][0] = 0.0;
	b_mat[1][1] = c_mat[1][1] = B_mat[1][1] = 0.0;
	b_mat[2][2] = c_mat[2][2] = B_mat[2][2] = 0.0;

	return result;
}
// create is called every time a new object is loaded
int residential_enduse::create(bool connect_shape) 
{
	// attach loadshape 
	load.end_obj = OBJECTHDR(this);
	if (connect_shape) load.shape = &shape;
	load.breaker_amps = 20;
	load.config = 0;
	load.heatgain_fraction = 1.0; /* power has no effect on heat loss */
	re_override = OV_NORMAL;
	power_state = PS_UNKNOWN;
	return 1;
}
Example #29
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;
}
TIMESTAMP residential_enduse::sync(TIMESTAMP t0, TIMESTAMP t1) 
{
	OBJECT *obj = OBJECTHDR(this);
	gl_debug("%s shape load = %8g", obj->name, gl_get_loadshape_value(&shape));
	if (load.voltage_factor>1.2 || load.voltage_factor<0.8)
		gl_verbose("%s voltage is out of normal +/- 20%% range of nominal (vf=%.2f)", obj->name, load.voltage_factor);
		/* TROUBLESHOOTING
		   The voltage on the enduse circuit is outside the expected range for that enduse.
		   This is usually caused by an impropely configure circuit (e.g., 110V on 220V or vice versa).
		   Fix the circuit configuration for that enduse and try again.
		 */
	return shape.t2>t1 ? shape.t2 : TS_NEVER; 
}