Esempio n. 1
0
/* basic checks on unshaped microwaves.  on failure, don't play games, just throw exceptions. */
void microwave::init_noshape(){
	if(shape.params.analog.power < 0){
		GL_THROW("microwave power must be positive (read as %f)", shape.params.analog.power);
	} else if (shape.params.analog.power > 4.000){
		GL_THROW("microwave power can not exceed 4 kW (and most don't exceed 2 kW)");
	}
	if(shape.params.analog.power < 0.700){
		gl_warning("microwave installed power is smaller than traditional microwave ovens");
	} else if(shape.params.analog.power > 1.800){
		gl_warning("microwave installed power is greater than traditional microwave ovens");
	}
	if(standby_power < 0){
		gl_warning("negative standby power, resetting to 1%% of installed power");
		standby_power = shape.params.analog.power * 0.01;
	} else if(standby_power > shape.params.analog.power){
		gl_warning("standby power exceeds installed power, resetting to 1%% of installed power");
		standby_power = shape.params.analog.power * 0.01;
	}
	if(cycle_time < 0){
		GL_THROW("negative cycle_length is an invalid value");
	}
	if(cycle_time > 14400){
		gl_warning("cycle_length is abnormally long and may give unusual results");
	}
}
Esempio n. 2
0
int recloser::init(OBJECT *parent)
{
	int result = switch_object::init(parent);

	TIMESTAMP next_ret;
	next_ret = gl_globalclock;

	if(ntries<0)
	{
		gl_warning("The number of recloser tries is less than 0 resetting to zero");
		ntries = 0;
	}

	if(retry_time < 0)
	{
		gl_warning("retry time is < 0 resetting to zero");
		retry_time = 0;
	}

	if(ntries == 0)
		ntries = 3; // seting default to 3 tries
	if(retry_time == 0)
	{
		retry_time = 1; // setting default to 1 second
		return_time = 1;
	} else {
		return_time = (TIMESTAMP)floor(retry_time + 0.5);
	}
	return result;
}
Esempio n. 3
0
/** Checks for climate object and maps the climate variables to the house object variables.  
Currently Tout, RHout and solar flux data from TMY files are used.  If no climate object is linked,
then Tout will be set to 74 degF, RHout is set to 75% and solar flux will be set to zero for all orientations.
**/
int house::init_climate()
{
	OBJECT *hdr = OBJECTHDR(this);

	// link to climate data
	static FINDLIST *climates = NULL;
	int not_found = 0;
	if (climates==NULL && not_found==0) 
	{
		climates = gl_find_objects(FL_NEW,FT_CLASS,SAME,"climate",FT_END);
		if (climates==NULL)
		{
			not_found = 1;
			gl_warning("house: no climate data found, using static data");

			//default to mock data
			static double tout=74.0, rhout=0.75, solar[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
			pTout = &tout;
			pRhout = &rhout;
			pSolar = &solar[0];
		}
		else if (climates->hit_count>1)
		{
			gl_warning("house: %d climates found, using first one defined", climates->hit_count);
		}
	}
	if (climates!=NULL)
	{
		if (climates->hit_count==0)
		{
			//default to mock data
			static double tout=74.0, rhout=0.75, solar[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
			pTout = &tout;
			pRhout = &rhout;
			pSolar = &solar[0];
		}
		else //climate data was found
		{
			// force rank of object w.r.t climate
			OBJECT *obj = gl_find_next(climates,NULL);
			if (obj->rank<=hdr->rank)
				gl_set_dependent(obj,hdr);
			pTout = (double*)GETADDR(obj,gl_get_property(obj,"temperature"));
			pRhout = (double*)GETADDR(obj,gl_get_property(obj,"humidity"));
			pSolar = (double*)GETADDR(obj,gl_get_property(obj,"solar_flux"));
		}
	}
	return 1;
}
Esempio n. 4
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
}
Esempio n. 5
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
}
Esempio n. 6
0
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;
}
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
}
Esempio n. 8
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;
}
Esempio n. 9
0
void voltdump::dump(TIMESTAMP t){
	char namestr[64];
	char timestr[64];
	FINDLIST *nodes = NULL;
	OBJECT *obj = NULL;
	FILE *outfile = NULL;
	node *pnode;
//	CLASS *nodeclass = NULL;
//	PROPERTY *vA, *vB, *vC;

	if(group[0] == 0){
		nodes = gl_find_objects(FL_NEW,FT_MODULE,SAME,"powerflow",FT_END);
	} else {
		nodes = gl_find_objects(FL_NEW,FT_MODULE,SAME,"powerflow",AND,FT_GROUPID,SAME,group.get_string(),FT_END);
	}

	if(nodes == NULL){
		gl_warning("no nodes were found to dump");
		return;
	}

	outfile = fopen(filename, "w");
	if(outfile == NULL){
		gl_error("voltdump unable to open %s for output", filename.get_string());
		return;
	}

	//nodeclass = node::oclass;
	//vA=gl_find_property(nodeclass, "

	int node_count = 0;
	while (obj=gl_find_next(nodes,obj)){
		if(gl_object_isa(obj, "node", "powerflow")){
			node_count += 1;
		}
	}
	/* print column names */
	gl_printtime(t, timestr, 64);
	fprintf(outfile,"# %s run at %s on %i nodes\n", filename.get_string(), timestr, node_count);
	if (mode == VDM_RECT)
		fprintf(outfile,"node_name,voltA_real,voltA_imag,voltB_real,voltB_imag,voltC_real,voltC_imag\n");
	else if (mode == VDM_POLAR)
		fprintf(outfile,"node_name,voltA_mag,voltA_angle,voltB_mag,voltB_angle,voltC_mag,voltC_angle\n");
	
	obj = 0;
	while (obj=gl_find_next(nodes,obj)){
		if(gl_object_isa(obj, "node", "powerflow")){
			pnode = OBJECTDATA(obj,node);
			if(obj->name == NULL){
				sprintf(namestr, "%s:%i", obj->oclass->name, obj->id);
			}
			if(mode == VDM_RECT){
				fprintf(outfile,"%s,%f,%f,%f,%f,%f,%f\n",(obj->name ? obj->name : namestr),pnode->voltage[0].Re(),pnode->voltage[0].Im(),pnode->voltage[1].Re(),pnode->voltage[1].Im(),pnode->voltage[2].Re(),pnode->voltage[2].Im());
			} else if(mode == VDM_POLAR){
				fprintf(outfile,"%s,%f,%f,%f,%f,%f,%f\n",(obj->name ? obj->name : namestr),pnode->voltage[0].Mag(),pnode->voltage[0].Arg(),pnode->voltage[1].Mag(),pnode->voltage[1].Arg(),pnode->voltage[2].Mag(),pnode->voltage[2].Arg());
			}
		}
	}
	fclose(outfile);
}
Esempio n. 10
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;
}
Esempio n. 11
0
int network::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	// input validation checks
	if(latency_mode[0] != 0){
		random_type = gl_randomtype(latency_mode);
		if(random_type == RT_INVALID){
			GL_THROW("unrecognized random type \'%s\'", latency_mode.get_string());
		}
	} else {
		random_type = RT_INVALID; // prevents update_latency from updating the value
	}
	if(latency_period < 0.0){
		gl_warning("negative latency_period was reset to zero");
		latency_period = 0.0;
	}

	if(bandwidth <= 0.0){
		gl_error("non-positive bandwidth");
		return 0;
	}
	switch(queue_resolution){
		case QR_QUEUE:
			if(buffer_size <= 0.0){
				gl_error("non-positive buffer_size when using buffered queue_resolution");
			}
			break;
		case QR_REJECT:
			// requires no checks
			break;
		default:
			gl_error("unrecognized queue_resolution, defaulting to QR_REJECT");
			queue_resolution = QR_REJECT;
			break;
	}
	if(timeout < 0.0){
		gl_warning("negative timeout was reset to zero");
		timeout = 0.0;
	}
	// operational variable defaults
	bandwidth_used = 0.0;
	update_latency();
	latency_last_update = gl_globalclock;
	next_event = TS_NEVER;
	// success
	return 1;
}
Esempio n. 12
0
int database::init(OBJECT *parent)
{
	gld_string flags = get_clientflags_property().get_string();
	
	gl_verbose("mysql_connect(hostname='%s',username='******',password='******',schema='%s',port=%u,socketname='%s',clientflags=0x%016llx[%s])",
		(const char*)hostname,(const char*)username,(const char*)password,(const char*)schema,port,(const char*)socketname,get_clientflags(),(const char*)flags);

	mysql = mysql_real_connect(mysql_client,hostname,username,strcpy(password,"")?password:NULL,NULL,port,socketname,(unsigned long)clientflags);
	if ( mysql==NULL )
		exception("mysql connect failed - %s", mysql_error(mysql_client));
	else
		gl_verbose("MySQL server info: %s", mysql_get_server_info(mysql));

	// autoname schema
	if ( strcmp(get_schema(),"")==0 )
	{
		char buffer[1024];
		gld_global model("modelname");
		if ( model.to_string(buffer,sizeof(buffer))>0 )
			set_schema(buffer);
	}

	// drop schema
	if ( get_options()&DBO_DROPSCHEMA && query("DROP DATABASE IF EXISTS `%s`", get_schema()) )
	{
		if ( strcmp(get_schema(),"gridlabd")==0 )
			gl_warning("%s uses NEWDB option on the default schema '%s' - this is extremely risky", get_name(), get_schema());
		gl_verbose("schema '%s' dropped ok", get_schema());
	}

	// check schema
	MYSQL_RES *res = mysql_list_dbs(mysql,get_schema());
	if ( mysql_num_rows(res)==0 )
	{
		if ( !(get_options()&DBO_NOCREATE) )
		{
			if ( query("CREATE DATABASE IF NOT EXISTS `%s`", get_schema()) )
				gl_verbose("created schema '%s' ok", get_schema());
		}
		else
			exception("NOCREATE option prevents automatic creation of schema '%s'", get_schema());
	}
	else
		gl_verbose("schema '%s' found ok", get_schema());

	// use schema
	if ( mysql_select_db(mysql,get_schema())!=0 )
		exception("unable to select schema '%s'", get_schema());

	// execute on_init script
	if ( strcmp(get_on_init(),"")!=0 )
	{
		gl_verbose("%s running on_init script '%s'", get_name(), get_on_init());
		int res = run_script(get_on_init());
		if ( res<=0 )
			exception("on_init script '%s' failed at line %d: %s", get_on_init(), -res, get_last_error());
	}
	return 1;
}
Esempio n. 13
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;
}
Esempio n. 14
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;
}
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;
}
Esempio n. 16
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;
}
Esempio n. 17
0
//Function to check for fault_check object (needed) and to make sure it is in a proper mode
void power_metrics::check_fault_check(void)
{
	if (fault_check_object_lnk == NULL)
	{
		if (fault_check_object == NULL)
		{
			GL_THROW("power_metrics failed to map fault_check object!");
			/*  TROUBLESHOOT
			power_metrics encountered an error while trying to map the fault_check
			object's location.  Please ensure that a fault_check object exists in the
			system and that fault_check is defined before the relevant metrics object.
			For best results, put the fault_check object right after all module definitions.
			If the error persists, please submit your code and a bug report using the trac website.
			*/
		}
		else	//One is mapped, let's check it
		{
			fault_check_object_lnk = OBJECTDATA(fault_check_object,fault_check);

			//Make sure it mapped
			if (fault_check_object_lnk == NULL)
			{
				GL_THROW("power_metrics failed to map fault_check object!");
				//Defined above
			}

			//Make sure it is in ONCHANGE or ALL mode
			if ((fault_check_object_lnk->fcheck_state!=fault_check::ALLT) && (fault_check_object_lnk->fcheck_state!=fault_check::ONCHANGE))
			{
				GL_THROW("fault_check must be in the proper mode for reliabilty to work!");
				/*  TROUBLESHOOT
				To properly work with reliability, fault_check must be in the ALL or ONCHANGE
				check_mode.  Please set it appropriately and try again.
				*/
			}

			//Once we're sure it is in the proper mode, set the reliability flag so it doesn't stop us dead
			fault_check_object_lnk->reliability_mode = true;

			//While we're in here, see if we can do secondary events - otherwise warn us
			if (fault_check_object_lnk->rel_eventgen == NULL)
			{
				gl_warning("No eventgen object mapped up to %s, unscheduled faults are not allowed",fault_check_object->name);
				/*  TROUBLESHOOT
				No eventgen object is specified on the fault_check field eventgen_object.  Without this specified, "unscheduled"
				faults can not occur and will simply stop the simulation.  This includes fuses blowing and "non-faulted" switch
				operations.
				*/
			}
		}//Mapping of fault_check object
	}//end fault_check_object_lnk is NULL
	//Defaulted else - must already be populated
}
Esempio n. 18
0
void network::update_latency(){
	// NOTE: latency_period == 0 means that the latency will update every iteration, even though it is processed during 'commit'.
//	if(latency_last_update + latency_period <= gl_globalclock){
		if(random_type != RT_INVALID){
			latency = gl_randomvalue(random_type, latency_arg1, latency_arg2);
			latency_last_update = gl_globalclock;
			latency_next_update = gl_globalclock + (TIMESTAMP)latency_period;
		} else {
			latency_next_update = TS_NEVER; // latency does not use a distribution and does not require updating
		}
		if(latency < 0.0){
			gl_warning("random latency output of %f is reset to zero", latency);
		}
//	}
}
Esempio n. 19
0
int refrigerator::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;	

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

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

	if (load.voltage_factor==0) load.voltage_factor = 1.0;

	if(shape.type == MT_UNKNOWN){
		init_noshape();
		gl_warning("This device, %s, is considered very experimental and has not been validated.", get_name());
		// initial demand
		update_state(0.0);
	} else if(shape.type == MT_ANALOG){
		if(1){
			;
		}
	} else if(shape.type == MT_PULSED){
		if(1){
			;
		}
	} else if(shape.type == MT_MODULATED){
		if(1){
			;
		}
	} else if(shape.type == MT_QUEUED){
		gl_error("queued loadshapes not supported ~ will attempt to run as an unshaped load");
		shape.type = MT_UNKNOWN;
		init_noshape();
		// initial demand
		update_state(0.0);
	} else {
		gl_error("unrecognized loadshape");
		return 0;
	}
	load.total = load.power = standby_power;
	
	// waiting this long to initialize the parent class is normal
	return residential_enduse::init(parent);
}
Esempio n. 21
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;
}
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);
}
Esempio n. 23
0
int clotheswasher::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.0;

	gl_warning("explicit %s model is experimental", OBJECTHDR(this)->oclass->name);
	/* TROUBLESHOOT
		The clothes washer 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;
}
Esempio n. 24
0
int tmy2_reader::read_data(double *dnr, double *dhr, double *ghr, double *tdb, double *rh, int* month, int* day, int* hour, double *wind, double *precip, double *snowDepth, double *pressure, double *extra_terr_dni){
	int rct = 0;
	int tmp_dnr, tmp_dhr, tmp_tdb, tmp_rh, tmp_ws, tmp_precip, tmp_sf, tmp_ghr, tmp_extra_dni, tmp_press;
	//sscanf(buf, "%*2s%2d%2d%2d%*14s%4d%*2s%4d%*40s%4d%8*s%3d%*s",month,day,hour,&tmp_dnr,&tmp_dhr,&tmp_tdb,&tmp_rh);
	int tmh, tday, thr;
	if(month == NULL) month = &tmh;
	if(day == NULL) day = &tday;
	if(hour == NULL) hour = &thr;
	rct = sscanf(buf, "%*2s%2d%2d%2d%*4s%4d%4d%*2s%4d%*2s%4d%*34s%4d%*8s%3d%*2s%4d%*7s%3d%*25s%3d%*7s%3d",month,day,hour,&tmp_extra_dni,&tmp_ghr,&tmp_dnr,&tmp_dhr,&tmp_tdb,&tmp_rh,&tmp_press,&tmp_ws,&tmp_precip,&tmp_sf);
				/* 3__5__7__9__13__17_20_23_27__29_33___67_71_79__82__85__95_98_ */
	if(rct != 13){
		gl_warning("TMY reader did not get 13 values for line time %d/%d %d00", *month, *day, *hour);
	}
	if(dnr) *dnr = tmp_dnr;
	if(dhr) *dhr = tmp_dhr;
	if(ghr) *ghr = tmp_ghr;

	//Assign extra_dni and pressure - extra DNI converted outside with other solar values
	if (extra_terr_dni) *extra_terr_dni = tmp_extra_dni;
	if (pressure) *pressure = tmp_press;

	if(tdb)
	{
		*tdb = ((double)tmp_tdb)/10.0;
		if (*tdb<low_temp || low_temp==0) low_temp = *tdb;
		else if (*tdb>high_temp || high_temp==0) high_temp = *tdb;
	}
	/* *tdb = ((double)tmp_tdb)/10.0 * 9.0 / 5.0 + 32.0; */
	if(rh) *rh = ((double)tmp_rh)/100.0;
	if(wind) *wind = tmp_ws/10.0;

	// COnvert precip in mm to in/h
	if(precip) *precip = ((double)tmp_precip) * 0.03937;

	//convert snowfall in cm to in
	if(snowDepth) *snowDepth =  ((double)tmp_sf) * 0.3937;

	return 1;
}
Esempio n. 25
0
int powerflow_object::init(OBJECT *parent)
{
	/* unspecified phase inherits from parent, if any */
	if (parent && gl_object_isa(parent,"powerflow_object"))
	{
		powerflow_object *pParent = OBJECTDATA(parent,powerflow_object);
		if (phases==NO_PHASE)
			phases = pParent->phases;
	}

	/* no phase info */
	if (phases==0)
		throw "phases not specified";

	/* split connection must connect to a phase */
	if (has_phase(PHASE_S) && !(has_phase(PHASE_A) || has_phase(PHASE_B) || has_phase(PHASE_C)))
		throw "split connection is missing A,B, or C phase connection";

	/* split connection must connect to only one phase */
	if (has_phase(PHASE_S) && (
		(has_phase(PHASE_A) && has_phase(PHASE_B)) ||
		(has_phase(PHASE_B) && has_phase(PHASE_C)) ||
		(has_phase(PHASE_C) && has_phase(PHASE_A))))
		throw "split connection is connected to two phases simultaneously";

	/* split connection is not permitted with delta connection */
	if (has_phase(PHASE_S) && has_phase(PHASE_D))
		throw "split and delta connection cannot occur simultaneously";

	/* split connection is not permitted on neutral */
	if (has_phase(PHASE_N) && has_phase(PHASE_S)) 
	{
		gl_warning("neutral phase ignored on split connection.");
		phases ^= PHASE_N;
	}

	return 1;
}
int triplex_node::init(OBJECT *parent)
{
	if ( !(has_phase(PHASE_S)) )
	{
		OBJECT *obj = OBJECTHDR(this);
		gl_warning("Init() triplex_node (name:%s, id:%d): Phases specified did not include phase S. Adding phase S.", obj->name,obj->id);
		/* TROUBLESHOOT
		Triplex nodes and meters require a single phase and a phase S component (for split-phase).
		This particular triplex object did not include it, so it is being added.
		*/
		phases = (phases | PHASE_S);
	}
	if ((pub_shunt[0] == 0) && (impedance[0] != 0))
		shunt[0] = complex(1.0,0)/impedance[0];

	if ((pub_shunt[1] == 0) && (impedance[1] != 0))
		shunt[1] = complex(1.0,0)/impedance[1];

	if ((pub_shunt[2] == 0) && (impedance[2] != 0))
		shunt[2] = complex(1.0,0)/impedance[2];

	return node::init(parent);
}
// Initialize, return 1 on success
int triplex_load::init(OBJECT *parent)
{
	int ret_value;
	OBJECT *obj = OBJECTHDR(this);

	ret_value = triplex_node::init(parent);

	//Provide warning about constant current loads
	if ((obj->flags & OF_DELTAMODE) == OF_DELTAMODE)	//Deltamode warning check
	{
		if ((constant_current[0] != 0.0) || (constant_current[1] != 0.0) || (constant_current[2] != 0.0))
		{
			gl_warning("triplex_load:%s - constant_current loads in deltamode are handled slightly different", obj->name ? obj->name : "unnamed");
			/*  TROUBLESHOOT
			Due to the potential for moving reference frame of deltamode systems, constant current loads are computed using a scaled
			per-unit approach, rather than the fixed constant_current value.  You may get results that differ from traditional GridLAB-D
			super-second or static powerflow results in this mode.
			*/
		}
	}

	return ret_value;
}
Esempio n. 28
0
bool copy_imports(glxlink *mod)
{
	MATLABLINK *matlab = (MATLABLINK*)mod->get_data();
	LINKLIST *item;

	if ( matlab->rootname!=NULL )
	{
		// update globals
		for ( item=mod->get_globals() ; item!=NULL ; item=mod->get_next(item) )
		{
			mxArray *var_struct = (mxArray*)mod->get_addr(item);
			if ( var_struct!=NULL )
			{
				mwIndex var_index = (mwIndex)mod->get_index(item);
				GLOBALVAR *var = mod->get_globalvar(item);
				gld_property prop(var);
				matlab_get_value(var_struct,&prop);
			}
		}
	}

	// update imports
	for ( item=mod->get_imports()==NULL?mod->get_exports():mod->get_imports() ; item!=NULL ; item=mod->get_next(item) )
	{
		OBJECTPROPERTY *objprop = mod->get_import(item);
		if ( objprop==NULL ) continue;
		gld_property prop(objprop->obj,objprop->prop);
		mxArray *data = engGetVariable(matlab->engine,item->name);
		if ( data )
			matlab_get_value(data,&prop);
		else
			gl_warning("unable to read '%s' from matlab", item->name);
		mxDestroyArray(data);
	}

	return true;
}
Esempio n. 29
0
/* Object initialization is called once after all object have been created */
int microturbine::init(OBJECT *parent)
{


	//generator_mode_choice = CONSTANT_PQ;
	gen_status_v = ONLINE;

	Rinternal = 0.05;
	Rload = 1;
	V_Max = complex(10000);
	I_Max = complex(1000);

	frequency = 0;
	Max_Frequency = 2000;
	Min_Frequency = 0;
	Fuel_Used = 0;
	Heat_Out = 0;
	KV = 1; //voltage constant
	Power_Angle = 1;
	
	Max_P = 100;//< maximum real power capacity in kW
    Min_P = 0;//< minimus real power capacity in kW
	
	Max_Q = 100;//< maximum reactive power capacity in kVar
    Min_Q = 0;//< minimus reactive power capacity in kVar
	Rated_kVA = 150; //< nominal capacity in kVA
	//double Rated_kV; //< nominal line-line voltage in kV
	
	efficiency = 0;
	pf_Out = 1;

	gl_verbose("microturbine init: finished initializing variables");

	struct {
		complex **var;
		char *varname;
	} map[] = {
		// local object name,	meter object name
		{&pCircuit_V_A,			"phaseA_V_In"}, 
		{&pCircuit_V_B,			"phaseB_V_In"}, 
		{&pCircuit_V_C,			"phaseC_V_In"}, 
		{&pLine_I_A,			"phaseA_I_In"}, 
		{&pLine_I_B,			"phaseB_I_In"}, 
		{&pLine_I_C,			"phaseC_I_In"}, 
		/// @todo use triplex property mapping instead of assuming memory order for meter variables (residential, low priority) (ticket #139)
	};
	 

	

	static complex default_line_voltage[1], default_line_current[1];
	int i;

	// find parent meter, if not defined, use a default meter (using static variable 'default_meter')
	if (parent!=NULL && strcmp(parent->oclass->name,"meter")==0)
	{
		for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
			*(map[i].var) = get_complex(parent,map[i].varname);

		gl_verbose("microturbine init: mapped METER objects to internal variables");
	}
	else if (parent!=NULL && strcmp(parent->oclass->name,"rectifier")==0){
		gl_verbose("microturbine init: parent WAS found, is an rectifier!");
			// construct circuit variable map to meter
			/// @todo use triplex property mapping instead of assuming memory order for meter variables (residential, low priority) (ticket #139)

		for (i=0; i<sizeof(map)/sizeof(map[0]); i++){
			*(map[i].var) = get_complex(parent,map[i].varname);
		}
		gl_verbose("microturbine init: mapped RECTIFIER objects to internal variables");
	}
	else{
		
			// construct circuit variable map to meter
		/// @todo use triplex property mapping instead of assuming memory order for meter variables (residential, low priority) (ticket #139)
		gl_verbose("microturbine init: mapped meter objects to internal variables");

		OBJECT *obj = OBJECTHDR(this);
		gl_verbose("microturbine init: no parent meter defined, parent is not a meter");
		gl_warning("microturbine:%d %s", obj->id, parent==NULL?"has no parent meter defined":"parent is not a meter");

		// attach meter variables to each circuit in the default_meter
			*(map[0].var) = &default_line_voltage[0];
			*(map[1].var) = &default_line_current[0];

		// provide initial values for voltages
			default_line_voltage[0] = complex(V_Max.Re()/sqrt(3.0),0);
			default_line_current[0] = complex(I_Max.Re());
			//default_line123_voltage[1] = complex(V_Max/sqrt(3.0)*cos(2*PI/3),V_Max/sqrt(3.0)*sin(2*PI/3));
			//default_line123_voltage[2] = complex(V_Max/sqrt(3.0)*cos(-2*PI/3),V_Max/sqrt(3.0)*sin(-2*PI/3));

	}

	gl_verbose("microturbine init: finished connecting with meter");




	/* TODO: set the context-dependent initial value of properties */
	//double ZB, SB, EB;
	//complex tst;
		if (gen_mode_v==UNKNOWN)
	{
		OBJECT *obj = OBJECTHDR(this);
		throw("Generator control mode is not specified");
	}
		if (gen_status_v==0)
	{
		//OBJECT *obj = OBJECTHDR(this);
		throw("Generator is out of service!");
	}else
		{
			return 1;

		}
	return 1; /* return 1 on success, 0 on failure */
}
Esempio n. 30
0
TIMESTAMP inverter::sync(TIMESTAMP t0, TIMESTAMP t1) 
{
	if (*NR_mode == false)
	{
		phaseA_V_Out = pCircuit_V[0];	//Syncs the meter parent to the generator.
		phaseB_V_Out = pCircuit_V[1];
		phaseC_V_Out = pCircuit_V[2];

		internal_losses = 1 - calculate_loss(Rtotal, Ltotal, Ctotal, DC, AC);
		//gl_verbose("inverter sync: internal losses are: %f", 1 - internal_losses);
		frequency_losses = 1 - calculate_frequency_loss(output_frequency, Rtotal,Ltotal, Ctotal);
		//gl_verbose("inverter sync: frequency losses are: %f", 1 - frequency_losses);

		
		switch(gen_mode_v)
		{
			case CONSTANT_PF:
			{
				VA_In = V_In * ~ I_In; //DC

				// need to differentiate between different pulses...
			
				VA_Out = VA_In * efficiency * internal_losses * frequency_losses;
				//losses = VA_Out * Rtotal / (Rtotal + Rload);
				//VA_Out = VA_Out * Rload / (Rtotal + Rload);

				if (number_of_phases_out == 4)  //Triplex-line -> Assume it's only across the 240 V for now.
				{
					power_A = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
					if (phaseA_V_Out.Mag() != 0.0)
						phaseA_I_Out = ~(power_A / phaseA_V_Out);
					else
						phaseA_I_Out = complex(0.0,0.0);

					*pLine12 += -phaseA_I_Out;

					//Update this value for later removal
					last_current[3] = -phaseA_I_Out;
					
					//Get rid of these for now
					//complex phaseA_V_Internal = filter_voltage_impact_source(phaseA_I_Out, phaseA_V_Out);
					//phaseA_I_Out = filter_current_impact_out(phaseA_I_Out, phaseA_V_Internal);
				}
				else if (number_of_phases_out == 3)
				{
					power_A = power_B = power_C = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/3;
					if (phaseA_V_Out.Mag() != 0.0)
						phaseA_I_Out = ~(power_A / phaseA_V_Out); // /sqrt(2.0);
					else
						phaseA_I_Out = complex(0.0,0.0);
					if (phaseB_V_Out.Mag() != 0.0)
						phaseB_I_Out = ~(power_B / phaseB_V_Out); // /sqrt(2.0);
					else
						phaseB_I_Out = complex(0.0,0.0);
					if (phaseC_V_Out.Mag() != 0.0)
						phaseC_I_Out = ~(power_C / phaseC_V_Out); // /sqrt(2.0);
					else
						phaseC_I_Out = complex(0.0,0.0);

					pLine_I[0] += -phaseA_I_Out;
					pLine_I[1] += -phaseB_I_Out;
					pLine_I[2] += -phaseC_I_Out;

					//Update this value for later removal
					last_current[0] = -phaseA_I_Out;
					last_current[1] = -phaseB_I_Out;
					last_current[2] = -phaseC_I_Out;

					//complex phaseA_V_Internal = filter_voltage_impact_source(phaseA_I_Out, phaseA_V_Out);
					//complex phaseB_V_Internal = filter_voltage_impact_source(phaseB_I_Out, phaseB_V_Out);
					//complex phaseC_V_Internal = filter_voltage_impact_source(phaseC_I_Out, phaseC_V_Out);

					//phaseA_I_Out = filter_current_impact_out(phaseA_I_Out, phaseA_V_Internal);
					//phaseB_I_Out = filter_current_impact_out(phaseB_I_Out, phaseB_V_Internal);
					//phaseC_I_Out = filter_current_impact_out(phaseC_I_Out, phaseC_V_Internal);
				}
				else if(number_of_phases_out == 2)
				{
					OBJECT *obj = OBJECTHDR(this);
					node *par = OBJECTDATA(obj->parent, node);

					if (par->has_phase(PHASE_A) && phaseA_V_Out.Mag() != 0)
					{
						power_A = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/2;;
						phaseA_I_Out = ~(power_A / phaseA_V_Out);
					}
					else 
						phaseA_I_Out = complex(0,0);

					if (par->has_phase(PHASE_B) && phaseB_V_Out.Mag() != 0)
					{
						power_B = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/2;;
						phaseB_I_Out = ~(power_B / phaseB_V_Out);
					}
					else 
						phaseB_I_Out = complex(0,0);

					if (par->has_phase(PHASE_C) && phaseC_V_Out.Mag() != 0)
					{
						power_C = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)))/2;;
						phaseC_I_Out = ~(power_C / phaseC_V_Out);
					}
					else 
						phaseC_I_Out = complex(0,0);

					pLine_I[0] += -phaseA_I_Out;
					pLine_I[1] += -phaseB_I_Out;
					pLine_I[2] += -phaseC_I_Out;

					//Update this value for later removal
					last_current[0] = -phaseA_I_Out;
					last_current[1] = -phaseB_I_Out;
					last_current[2] = -phaseC_I_Out;

				}
				else if(number_of_phases_out == 1)
				{
					if(phaseA_V_Out.Mag() != 0)
					{
						power_A = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
						phaseA_I_Out = ~(power_A / phaseA_V_Out); 
						//complex phaseA_V_Internal = filter_voltage_impact_source(phaseA_I_Out, phaseA_V_Out);
						//phaseA_I_Out = filter_current_impact_out(phaseA_I_Out, phaseA_V_Internal);
					}
					else if(phaseB_V_Out.Mag() != 0)
					{
						power_B = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
						phaseB_I_Out = ~(power_B / phaseB_V_Out); 
						//complex phaseB_V_Internal = filter_voltage_impact_source(phaseB_I_Out, phaseB_V_Out);
						//phaseB_I_Out = filter_current_impact_out(phaseB_I_Out, phaseB_V_Internal);
					}
					else if(phaseC_V_Out.Mag() != 0)
					{
						power_C = complex(VA_Out.Mag()*abs(power_factor),power_factor/abs(power_factor)*VA_Out.Mag()*sin(acos(power_factor)));
						phaseC_I_Out = ~(power_C / phaseC_V_Out); 
						//complex phaseC_V_Internal = filter_voltage_impact_source(phaseC_I_Out, phaseC_V_Out);
						//phaseC_I_Out = filter_current_impact_out(phaseC_I_Out, phaseC_V_Internal);
					}
					else
					{
						gl_warning("None of the phases specified have voltages!");
						phaseA_I_Out = phaseB_I_Out = phaseC_I_Out = complex(0.0,0.0);
					}
					pLine_I[0] += -phaseA_I_Out;
					pLine_I[1] += -phaseB_I_Out;
					pLine_I[2] += -phaseC_I_Out;

					//Update this value for later removal
					last_current[0] = -phaseA_I_Out;
					last_current[1] = -phaseB_I_Out;
					last_current[2] = -phaseC_I_Out;

				}
				else
				{
					throw ("The number of phases given is unsupported.");
				}
				return TS_NEVER;
			}
				break;
			case CONSTANT_PQ:
			{
				GL_THROW("Constant PQ mode not supported at this time");
				/* TROUBLESHOOT
				This will be worked on at a later date and is not yet correctly implemented.
				*/
				gl_verbose("inverter sync: constant pq");
				//TODO
				//gather V_Out for each phase
				//gather V_In (DC) from line -- can not gather V_In, for now set equal to V_Out
				//P_Out is either set or input from elsewhere
				//Q_Out is either set or input from elsewhere
				//Gather Rload

				if(parent_string = "meter")
				{
					VA_Out = complex(P_Out,Q_Out);
				}
				else if (parent_string = "triplex_meter")
				{
					VA_Out = complex(P_Out,Q_Out);
				}
				else
				{
					phaseA_I_Out = pLine_I[0];
					phaseB_I_Out = pLine_I[1];
					phaseC_I_Out = pLine_I[2];

					//Erm, there's no good way to handle this from a "multiply attached" point of view.
					//TODO: Think about how to do this if the need arrises

					VA_Out = phaseA_V_Out * (~ phaseA_I_Out) + phaseB_V_Out * (~ phaseB_I_Out) + phaseC_V_Out * (~ phaseC_I_Out);
				}

				pf_out = P_Out/VA_Out.Mag();
				
				//VA_Out = VA_In * efficiency * internal_losses;

				if (number_of_phases_out == 3)
				{
					power_A = power_B = power_C = VA_Out /3;
					phaseA_I_Out = (power_A / phaseA_V_Out); // /sqrt(2.0);
					phaseB_I_Out = (power_B / phaseB_V_Out); // /sqrt(2.0);
					phaseC_I_Out = (power_C / phaseC_V_Out); // /sqrt(2.0);

					phaseA_I_Out = ~ phaseA_I_Out;
					phaseB_I_Out = ~ phaseB_I_Out;
					phaseC_I_Out = ~ phaseC_I_Out;

				}
				else if(number_of_phases_out == 1)
				{
					if(phaseAOut)
					{
						power_A = VA_Out;
						phaseA_I_Out = (power_A / phaseA_V_Out); // /sqrt(2);
						phaseA_I_Out = ~ phaseA_I_Out;
					}
					else if(phaseBOut)
					{
						power_B = VA_Out;
						phaseB_I_Out = (power_B / phaseB_V_Out);  // /sqrt(2);
						phaseB_I_Out = ~ phaseB_I_Out;
					}
					else if(phaseCOut)
					{
						power_C = VA_Out;
						phaseC_I_Out = (power_C / phaseC_V_Out); // /sqrt(2);
						phaseC_I_Out = ~ phaseC_I_Out;
					}
					else
					{
						throw ("none of the phases have voltages!");
					}
				}
				else
				{
					throw ("unsupported number of phases");
				}

				VA_In = VA_Out / (efficiency * internal_losses * frequency_losses);
				losses = VA_Out * (1 - (efficiency * internal_losses * frequency_losses));

				//V_In = complex(0,0);
				//
				////is there a better way to do this?
				//if(phaseAOut){
				//	V_In += abs(phaseA_V_Out.Re());
				//}
				//if(phaseBOut){
				//	V_In += abs(phaseB_V_Out.Re());
				//}
				//if(phaseCOut){
				//	V_In += abs(phaseC_V_Out.Re());
				//}else{
				//	throw ("none of the phases have voltages!");
				//}

				V_In = Vdc;



				I_In = VA_In / V_In;
				I_In = ~I_In;

				V_In = filter_voltage_impact_source(I_In, V_In);
				I_In = filter_current_impact_source(I_In, V_In);

				gl_verbose("Inverter sync: V_In asked for by inverter is: (%f , %f)", V_In.Re(), V_In.Im());
				gl_verbose("Inverter sync: I_In asked for by inverter is: (%f , %f)", I_In.Re(), I_In.Im());


				pLine_I[0] += phaseA_I_Out;
				pLine_I[1] += phaseB_I_Out;
				pLine_I[2] += phaseC_I_Out;

				//Update this value for later removal
				last_current[0] = phaseA_I_Out;
				last_current[1] = phaseB_I_Out;
				last_current[2] = phaseC_I_Out;

				return TS_NEVER;
			}
				break;
			case CONSTANT_V:
			{
				GL_THROW("Constant V mode not supported at this time");
				/* TROUBLESHOOT
				This will be worked on at a later date and is not yet correctly implemented.
				*/
				gl_verbose("inverter sync: constant v");
				bool changed = false;
				
				//TODO
				//Gather V_Out
				//Gather VA_Out
				//Gather Rload
				if(phaseAOut)
				{
					if (phaseA_V_Out.Re() < (V_Set_A - margin))
					{
						phaseA_I_Out = phaseA_I_Out_prev + I_step_max/2;
						changed = true;
					}
					else if (phaseA_V_Out.Re() > (V_Set_A + margin))
					{
						phaseA_I_Out = phaseA_I_Out_prev - I_step_max/2;
						changed = true;
					}
					else
					{
						changed = false;
					}
				}
				if (phaseBOut)
				{
					if (phaseB_V_Out.Re() < (V_Set_B - margin))
					{
						phaseB_I_Out = phaseB_I_Out_prev + I_step_max/2;
						changed = true;
					}
					else if (phaseB_V_Out.Re() > (V_Set_B + margin))
					{
						phaseB_I_Out = phaseB_I_Out_prev - I_step_max/2;
						changed = true;
					}
					else
					{
						changed = false;
					}
				}
				if (phaseCOut)
				{
					if (phaseC_V_Out.Re() < (V_Set_C - margin))
					{
						phaseC_I_Out = phaseC_I_Out_prev + I_step_max/2;
						changed = true;
					}
					else if (phaseC_V_Out.Re() > (V_Set_C + margin))
					{
						phaseC_I_Out = phaseC_I_Out_prev - I_step_max/2;
						changed = true;
					}
					else
					{
						changed = false;
					}
				}
				
				power_A = (~phaseA_I_Out) * phaseA_V_Out;
				power_B = (~phaseB_I_Out) * phaseB_V_Out;
				power_C = (~phaseC_I_Out) * phaseC_V_Out;

				//check if inverter is overloaded -- if so, cap at max power
				if (((power_A + power_B + power_C) > Rated_kVA) ||
					((power_A.Re() + power_B.Re() + power_C.Re()) > Max_P) ||
					((power_A.Im() + power_B.Im() + power_C.Im()) > Max_Q))
				{
					VA_Out = Rated_kVA / number_of_phases_out;
					//if it's maxed out, don't ask for the simulator to re-call
					changed = false;
					if(phaseAOut)
					{
						phaseA_I_Out = VA_Out / phaseA_V_Out;
						phaseA_I_Out = (~phaseA_I_Out);
					}
					if(phaseBOut)
					{
						phaseB_I_Out = VA_Out / phaseB_V_Out;
						phaseB_I_Out = (~phaseB_I_Out);
					}
					if(phaseCOut)
					{
						phaseC_I_Out = VA_Out / phaseC_V_Out;
						phaseC_I_Out = (~phaseC_I_Out);
					}
				}
				
				//check if power is negative for some reason, should never be
				if(power_A < 0)
				{
					power_A = 0;
					phaseA_I_Out = 0;
					throw("phaseA power is negative!");
				}
				if(power_B < 0)
				{
					power_B = 0;
					phaseB_I_Out = 0;
					throw("phaseB power is negative!");
				}
				if(power_C < 0)
				{
					power_C = 0;
					phaseC_I_Out = 0;
					throw("phaseC power is negative!");
				}

				VA_In = VA_Out / (efficiency * internal_losses * frequency_losses);
				losses = VA_Out * (1 - (efficiency * internal_losses * frequency_losses));

				//V_In = complex(0,0);
				//
				////is there a better way to do this?
				//if(phaseAOut){
				//	V_In += abs(phaseA_V_Out.Re());
				//}
				//if(phaseBOut){
				//	V_In += abs(phaseB_V_Out.Re());
				//}
				//if(phaseCOut){
				//	V_In += abs(phaseC_V_Out.Re());
				//}else{
				//	throw ("none of the phases have voltages!");
				//}

				V_In = Vdc;

				I_In = VA_In / V_In;
				I_In  = ~I_In;
				
				gl_verbose("Inverter sync: I_In asked for by inverter is: (%f , %f)", I_In.Re(), I_In.Im());

				V_In = filter_voltage_impact_source(I_In, V_In);
				I_In = filter_current_impact_source(I_In, V_In);

				//TODO: check P and Q components to see if within bounds

				if(changed)
				{
					pLine_I[0] += phaseA_I_Out;
					pLine_I[1] += phaseB_I_Out;
					pLine_I[2] += phaseC_I_Out;
					
					//Update this value for later removal
					last_current[0] = phaseA_I_Out;
					last_current[1] = phaseB_I_Out;
					last_current[2] = phaseC_I_Out;

					TIMESTAMP t2 = t1 + 10 * 60 * TS_SECOND;
					return t2;
				}
				else
				{
					pLine_I[0] += phaseA_I_Out;
					pLine_I[1] += phaseB_I_Out;
					pLine_I[2] += phaseC_I_Out;

					//Update this value for later removal
					last_current[0] = phaseA_I_Out;
					last_current[1] = phaseB_I_Out;
					last_current[2] = phaseC_I_Out;

					return TS_NEVER;
				}
			}
				break;
			case SUPPLY_DRIVEN: {
				GL_THROW("SUPPLY_DRIVEN mode for inverters not supported at this time");
			}
			default:
			{
				pLine_I[0] += phaseA_I_Out;
				pLine_I[1] += phaseB_I_Out;
				pLine_I[2] += phaseC_I_Out;

				//Update this value for later removal
				last_current[0] = phaseA_I_Out;
				last_current[1] = phaseB_I_Out;
				last_current[2] = phaseC_I_Out;

				return TS_NEVER;
			}
				break;
		}
		if (number_of_phases_out == 4)
		{
			*pLine12 += phaseA_I_Out;

			//Update this value for later removal
			last_current[3] = phaseA_I_Out;
		}
		else
		{
			pLine_I[0] += phaseA_I_Out;
			pLine_I[1] += phaseB_I_Out;
			pLine_I[2] += phaseC_I_Out;

			//Update this value for later removal
			last_current[0] = phaseA_I_Out;
			last_current[1] = phaseB_I_Out;
			last_current[2] = phaseC_I_Out;

		}

		return TS_NEVER;
	}
	else
	{
		if (number_of_phases_out == 4)
		{
			*pLine12 += last_current[3];
		}
		else
		{
			pLine_I[0] += last_current[0];
			pLine_I[1] += last_current[1];
			pLine_I[2] += last_current[2];
		}
		return TS_NEVER;
	}
}