コード例 #1
0
ファイル: collector.cpp プロジェクト: brennane/gridpot
TIMESTAMP collector::commit(TIMESTAMP t0, TIMESTAMP t1)
{
	TIMESTAMP dt = (TIMESTAMP)get_interval();
	if ( dt==0 || ( t1==next_t && next_t!=TS_NEVER ) )
	{
		char buffer[4096];
		size_t eos = sprintf(buffer,"INSERT INTO `%s` (t", get_table());
		int n;
		for ( n=0 ; n<n_aggregates ; n++ )
			eos += sprintf(buffer+eos,",`%s`",names[n]);
		eos += sprintf(buffer+eos,") VALUES (from_unixtime(%lli)",gl_globalclock);
		for ( n=0 ; n<n_aggregates ; n++ )
			eos += sprintf(buffer+eos,",%g",list[n].get_value());
		sprintf(buffer+eos,"%s",")");

		if ( !db->query(buffer) )
			exception("unable to add data to '%s' - %s", get_table(), mysql_error(mysql));
		else
			gl_verbose("%s: sample added to '%s' ok", get_name(), get_table());

		// check limit
		if ( get_limit()>0 && db->get_last_index()>=get_limit() )
		{
			gl_verbose("%s: limit of %d records reached", get_name(), get_limit());
			next_t = TS_NEVER;
		}
		else
		{
			next_t = (dt==0 ? TS_NEVER : (TIMESTAMP)(t1/dt+1)*dt);
		}
		set_clock(t1);
	}
	return TS_NEVER;
}
コード例 #2
0
TIMESTAMP transmissioncom::presync(TIMESTAMP t0, TIMESTAMP t1)
{
  complex temp = complex(0,0);
  complex last_voltage = complex(0,0);

	
	if(t0 < t1 && myinterface->hasMoreMessages()){
		last_voltage = *datatogld;
		temp = getFromTransmissionSolver();
		if(last_voltage.Mag() != 0.0){
			complex volt_diff = last_voltage - temp;
			double perc_diff = volt_diff.Mag()/last_voltage.Mag();
			if(perc_diff >= 0.5){
				if(last_voltage.Im() >= 0.0){
					gl_verbose("previous voltage: %lf+j%lf V.\n",last_voltage.Re(),last_voltage.Im());
				} else {
					gl_verbose("previous voltage: %lf+j%lf V.\n",last_voltage.Re(),-1.0*last_voltage.Im());
				}
				if(temp.Im() >= 0.0){
					gl_verbose("current voltage: %lf+j%lf V.\n",temp.Re(),temp.Im());
				} else {
					gl_verbose("current voltage: %lf+j%lf V.\n",temp.Re(),-1.0*temp.Im());
				}
				gl_verbose("voltage changed more that 50 percent. Something isn't right in transmission. Using previous voltage.\n");
			} else {
				*datatogld = temp;
			}
		} else if(temp.Mag() > 0.0){
			*datatogld = temp;
		}
	}
	return TS_NEVER;

}
コード例 #3
0
ファイル: database.cpp プロジェクト: ryuever/sgrid
MYSQL_RES *database::select(char *fmt,...)
{
	char command[1024];
	va_list ptr;
	va_start(ptr,fmt);
	vsnprintf(command,sizeof(command),fmt,ptr);

	// query mysql
	if ( mysql_query(mysql,command)!=0 )
		exception("%s->select[%s] query failed - %s", get_name(), command, mysql_error(mysql));
	else if ( get_options()&DBO_SHOWQUERY )
		gl_verbose("%s->select[%s] ok", get_name(), command);

	// get result
	MYSQL_RES *res = mysql_store_result(mysql);
	if ( res==NULL )
		exception("%s->select[%s] result failed - %s", get_name(), command, mysql_error(mysql));
	int n = mysql_num_rows(res);
	gl_verbose("%s->select[%s] %d rows returned", get_name(), command, n);
	//if ( n==0 )
	//	return mysql_free_result(res),NULL;

	// TODO map variables
	va_end(ptr);
	return res;
}
コード例 #4
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;
}
コード例 #5
0
/** 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;
	
}
コード例 #6
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;
}
コード例 #7
0
ファイル: schedule.cpp プロジェクト: devendrashelar7/gridnetd
TIMESTAMP schedule::presync(TIMESTAMP t0, TIMESTAMP t1){
	/* get localtime & run rules */
	DATETIME dt;
	TIMESTAMP min = TS_NEVER; // earliest start of next state
	TIMESTAMP max = TS_NEVER; // earliest end of current state
	int res = 0;

	schedule_list *lptr = 0, *child = 0;

	//	skip if t0 < next_ts ... we should know when this needs to change

	gl_localtime(t1, &dt);

	currval = default_value;

	for(lptr = sched_list; lptr != NULL; lptr = lptr->next){
		// process lptr rule
		// traverse lptr children
		// track when current state ends OR when next state begins

		/* group_right & group_left should actually be used ... coming soon! */
		for(child = lptr; child != NULL; child = child->group_right){
			res = test_sched_dt(child->moy_start, child->moy_end, dt.month);
			if(res == 0){
				continue;
			}
			if(child->dow_or_dom == schedule_list::wor_skip){
				res = 1; /* short circuit, both are '*' */
			} else if(child->dow_or_dom == schedule_list::wor_month){
				res = test_sched_dt(child->dom_start, child->dom_end, dt.day);
			} else if(child->dow_or_dom == schedule_list::wor_week){
				res = test_sched_dt(child->dow_start, child->dow_end, dt.weekday);
			} else if(child->dow_or_dom == schedule_list::wor_both){
				res = test_sched_dt(child->dom_start, child->dom_end, dt.day) + test_sched_dt(child->dow_start, child->dow_end, dt.weekday);
			} else {
				gl_verbose("invalid day of week/day of month flag");
				continue;
			}
			if(res == 0){
				continue;
			}
			res = test_sched_dt(child->hod_start, child->hod_end, dt.hour);
			res += test_sched_dt(child->moh_start, child->moh_end, dt.minute > 59 ? 59 : dt.minute);
			if(res == 2){
				currval = child->scale;
				break; /* found rule in the group that matches, on to the next group */
			}
		}
	}

	return TS_NEVER;
}
コード例 #8
0
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; 
}
コード例 #9
0
ファイル: database.cpp プロジェクト: ryuever/sgrid
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;
}
コード例 #10
0
ファイル: matlab.cpp プロジェクト: AMFIRNAS/wso2-gridlabd
static mxArray* matlab_exec(MATLABLINK *matlab, char *format, ...)
{
	char cmd[4096];
	va_list ptr;
	va_start(ptr,format);
	vsprintf(cmd,format,ptr);
	va_end(ptr);
	engEvalString(matlab->engine,cmd);
	if ( matlab->output_buffer && strcmp(matlab->output_buffer,"")!=0 )
		gl_verbose( "%s", matlab->output_buffer );
	mxArray *ans = engGetVariable(matlab->engine,"ans");
	return ans; // failed
}
コード例 #11
0
ファイル: bid.cpp プロジェクト: AMFIRNAS/wso2-gridlabd
EXPORT void submit_bid_state(char *from, char *to, char *function_name, char *function_class, void *bidding_buffer, size_t bid_len)//(char *obj, char *from, double quantity, double price, unsigned int is_on, KEY bid_id)
{
	char biddername[64];
	int rv;
	OBJECT *obj = NULL;
	BIDINFO *bidding_info = (BIDINFO *)bidding_buffer;
	if( strncmp(function_name, "submit_bid_state", 16)== 0){
		obj = gl_get_object(to);
		if( obj == NULL){
			gl_error("bid::submit_bid_state: No auction object exists with given name %s.", to);
			bidding_info->bid_accepted = false;
		}

		if (obj->oclass==auction::oclass)
		{
			if(bidding_info->state == BS_UNKNOWN) {// not a stateful bid
				gl_verbose("%s submits stateless bid for Q:%.2f at P:%.4f", from,bidding_info->quantity,bidding_info->price);
				auction *mkt = OBJECTDATA(obj,auction);
				rv = mkt->submit(from,bidding_info->quantity,bidding_info->price,bidding_info->bid_id,bidding_info->state,bidding_info->rebid, bidding_info->market_id);
			} else {
				gl_verbose("%s submits stateful (%s) bid for Q:%.2f at P:%.4f", from,bidding_info->state,bidding_info->quantity,bidding_info->price);
				auction *mkt = OBJECTDATA(obj,auction);
				rv = mkt->submit(from,bidding_info->quantity,bidding_info->price,bidding_info->bid_id,bidding_info->state,bidding_info->rebid, bidding_info->market_id);
			}
			if(rv == 0) {
				bidding_info->bid_accepted = false;
			}
		} else if(obj->oclass == stubauction::oclass){
			gl_error("bid::submit_bid_state: market object is not an auction object.");
			bidding_info->bid_accepted = false;
		} else {
			gl_error("bid::submit_bid_state: market object is not an auction object.");
			bidding_info->bid_accepted = false;
		}
	} else {
		gl_error("bid::submit_bid_state: This function is not the intended function. %s was the intended function to call. Ignoring bid", function_name);
	}
}
コード例 #12
0
ファイル: database.cpp プロジェクト: ryuever/sgrid
database::database(MODULE *module)
{
	if (oclass==NULL)
	{
		// register to receive notice for first top down. bottom up, and second top down synchronizations
		oclass = gld_class::create(module,"database",sizeof(database),PC_AUTOLOCK);
		if (oclass==NULL)
			throw "unable to register class database";
		else
			oclass->trl = TRL_PROTOTYPE;

		defaults = this;
		if (gl_publish_variable(oclass,
			PT_char256,"hostname",get_hostname_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"server hostname",
			PT_char256,"schema",get_schema_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"schema name",
			PT_char32,"username",get_username_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"user name",
			PT_char32,"password",get_password_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"user password",
			PT_int32,"port",get_port_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"TCP port number",
			PT_char1024,"socketname",get_socketname_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"unix socket name",
			PT_set,"clientflags",get_clientflags_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"mysql client flags",
				PT_KEYWORD,"COMPRESS",(int64)CLIENT_COMPRESS,
				PT_KEYWORD,"FOUND_ROWS",(int64)CLIENT_FOUND_ROWS,
				PT_KEYWORD,"IGNORE_SIGPIPE",(int64)CLIENT_IGNORE_SIGPIPE,
				PT_KEYWORD,"INTERACTIVE",(int64)CLIENT_INTERACTIVE,
				PT_KEYWORD,"LOCAL_FILES",(int64)CLIENT_LOCAL_FILES,
				PT_KEYWORD,"MULTI_RESULTS",(int64)CLIENT_MULTI_RESULTS,
				PT_KEYWORD,"MULTI_STATEMENTS",(int64)CLIENT_MULTI_STATEMENTS,
				PT_KEYWORD,"NO_SCHEMA",(int64)CLIENT_NO_SCHEMA,
				PT_KEYWORD,"ODBC",(int64)CLIENT_ODBC,
				PT_KEYWORD,"SSL",(int64)CLIENT_SSL,
				PT_KEYWORD,"REMEMBER_OPTIONS",(int64)CLIENT_REMEMBER_OPTIONS,
			PT_set,"options",get_options_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"database connection options",
				PT_KEYWORD,"SHOWQUERY",(int64)DBO_SHOWQUERY,PT_DESCRIPTION,"show SQL queries when running",
				PT_KEYWORD,"NOCREATE",(int64)DBO_NOCREATE,PT_DESCRIPTION,"prevent automatic creation of non-existent schemas",
				PT_KEYWORD,"NEWDB",(int64)DBO_DROPSCHEMA,PT_DESCRIPTION,"destroy existing schemas before use them (risky)",
				PT_KEYWORD,"OVERWRITE",(int64)DBO_OVERWRITE,PT_DESCRIPTION,"destroy existing files before output dump/backup results (risky)",
			PT_char1024,"on_init",get_on_init_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"SQL script to run when initializing",
			PT_char1024,"on_sync",get_on_sync_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"SQL script to run when synchronizing",
			PT_char1024,"on_term",get_on_term_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"SQL script to run when terminating",
			PT_double,"sync_interval[s]",get_sync_interval_offset(),PT_ACCESS,PA_PUBLIC,PT_DESCRIPTION,"interval at which on_sync is called",
			NULL)<1){
				char msg[256];
				sprintf(msg, "unable to publish properties in %s",__FILE__);
				throw msg;
		}

		memset(this,0,sizeof(database));
		gl_verbose("MySQL client info: %s", mysql_get_client_info());
	}
}
コード例 #13
0
ファイル: player.cpp プロジェクト: GridOPTICS/FNCS-gridlab-d
int player::precommit(TIMESTAMP t0)
{
	if ( row && t0==next_t)
	{
		target.from_string(row[1]);
		row = mysql_fetch_row(data);
		if ( row==NULL )
			return 1;
		row_num++;
		gl_verbose("%s: row %d, %s='%s', %s='%s'", get_name(), row_num, fields[0].name, row[0], fields[1].name, row[1]);
		gld_clock next(row[0]);
		next_t = next.get_timestamp();
	}
	return 1;
}
コード例 #14
0
ファイル: database.cpp プロジェクト: ryuever/sgrid
bool database::query(char *fmt,...)
{
	char command[1024];
	va_list ptr;
	va_start(ptr,fmt);
	vsnprintf(command,sizeof(command),fmt,ptr);
	va_end(ptr);

	// query mysql
	if ( mysql_query(mysql,command)!=0 )
		exception("%s->query[%s] failed - %s", get_name(), command, mysql_error(mysql));
	else if ( get_options()&DBO_SHOWQUERY )
		gl_verbose("%s->query[%s] ok", get_name(), command);

	return true;
}
コード例 #15
0
ファイル: database.cpp プロジェクト: ryuever/sgrid
void database::term(void)
{	
	if ( strcmp(get_on_term(),"")!=0 )
	{
		gl_verbose("%s running on_term script '%s'", get_name(), get_on_term());
		try {
			int res = run_script(get_on_term());
			if ( res<=0 )
				exception("on_term script '%s' failed at line %d: %s", get_on_term(), -res, get_last_error());
		}
		catch (const char *msg)
		{
			gl_error("%s", msg);
		}
		mysql_close(mysql);
	}
}
コード例 #16
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);
}
コード例 #17
0
ファイル: plc.cpp プロジェクト: GridOPTICS/FNCS-gridlab-d
/** Initialize the new object */
int plc::init(OBJECT *parent)
{
	if (strcmp(source,"")==0 && parent!=NULL) /* default source */
		sprintf(source.get_string(),"%s.plc",parent->oclass->name);
	if (controller->compile(source)<0)
		GL_THROW("%s: PLC compile failed", source.get_string());
	if (controller->init(parent)<0)
		GL_THROW("%s: PLC init failed", source.get_string());
	parent->flags |= OF_HASPLC; /* enable external PLC flag */
	
	if (network)
	{
		controller->connect(OBJECTDATA(network,comm));
		gl_verbose("machine %x has connected to network '%s'", controller, network->name?network->name:"anonymous");
	}

	return 1; // return 0 on failure
}
コード例 #18
0
ファイル: database.cpp プロジェクト: ryuever/sgrid
TIMESTAMP database::commit(TIMESTAMP t0, TIMESTAMP t1)
{
	set_clock();
	if ( get_sync_interval()>0 )
	{
		gld_clock ts(t1);
		int mod = ts.get_localtimestamp()%(TIMESTAMP)get_sync_interval();
		if ( strcmp(get_on_sync(),"")!=0 && mod==0 )
		{
			int mod1 = t1%86400, mod2 = ts.get_timestamp()%86400, mod3 = ts.get_localtimestamp()%86400;
			gld_clock ts(t0);
			char buffer[64];
			gl_verbose("%s running on_init script '%s' at %s", get_name(), get_on_sync(), ts.to_string(buffer,sizeof(buffer))?buffer:"(unknown time)");
			int res = run_script(get_on_sync());
			if ( res<=0 )
				exception("on_init script '%s' failed at line %d: %s", get_on_sync(), -res, get_last_error());
		}
		return -(t1+get_sync_interval()-mod);
	}
	return TS_NEVER;
}
コード例 #19
0
// Initialize a distribution meter, return 1 on success
int substation::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	int i,n;

	//Base check higher so can be used below
	if(base_power <= 0){
		gl_warning("substation:%i is using the default base power of 100 VA. This could cause instability on your system.", hdr->id);
		base_power = 100;//default gives a max power error of 1 VA.
	}

	//Check convergence-posting criterion
	if (power_convergence_value<=0.0)
	{
		gl_warning("power_convergence_value not set - defaulting to 0.01 base_power");
		/*  TROUBLESHOOT
		A value was not specified for the convergence criterion required before posting an 
		answer up to pw_load.  This value has defaulted to 1% of base_power.  If a different threshold
		is desired, set it explicitly.
		*/

		power_convergence_value = 0.01*base_power;
	}//End convergence value check

	//Check to see if it has a parent (no sense to ISAs if it is empty)

	if (parent != NULL)
	{
		if (gl_object_isa(parent,"pw_load","network"))
		{
			//Make sure it is done, otherwise defer
			if((parent->flags & OF_INIT) != OF_INIT){
				char objname[256];
				gl_verbose("substation::init(): deferring initialization on %s", gl_name(parent, objname, 255));

				return 2; // defer
			}

			//Map up the appropriate variables- error checks mostly inside
			fetch_complex(&pPositiveSequenceVoltage,"load_voltage",parent);
			fetch_complex(&pConstantPowerLoad,"load_power",parent);
			fetch_complex(&pConstantCurrentLoad,"load_current",parent);
			fetch_complex(&pConstantImpedanceLoad,"load_impedance",parent);
			fetch_double(&pTransNominalVoltage,"bus_nom_volt",parent);

			//Do a general check for nominal voltages - make sure they match
			if (fabs(*pTransNominalVoltage-nominal_voltage)>0.001)
			{
				gl_error("Nominal voltages of tranmission node (%.1f V) and substation (%.1f) do not match!",*pTransNominalVoltage,nominal_voltage);
				/*  TROUBLESHOOT
				The nominal voltage of the transmission node in PowerWorld does not match
				that of the value inside GridLAB-D's substation's nominal_voltage.  This could
				cause information mismatch and is therefore not allowed.  Please set the
				substation to the same nominal voltage as the transmission node.  Use transformers
				to step the voltage down to an appropriate distribution or sub-transmission level.
				*/
				return 0;	//Fail
			}

			//Check our bustype - otherwise we may get overridden (NR-esque check)
			if (bustype != SWING)
			{
				gl_warning("substation attached to pw_load and not a SWING bus - forcing to SWING");
				/*  TROUBLESHOOT
				When a substation object is connected to PowerWorld via a pw_load object, the
				substation must be designated as a SWING bus.  This designation will now be forced upon
				the bus.
				*/
				bustype = SWING;
			}//End bus check

			//Flag us as pw_load connected
			has_parent = 1;
		}
		else	//Parent isn't a pw_load, so we just become a normal node - let it handle things
		{
			has_parent = 2;	//Flag as "normal" - let node checks sort out if we are really valid or not
		}
	}//End parent
	else	//Parent is null, see what mode we're in
	{
		//Check for sequence voltages - if not set, we're normal (let node checks handle if we're valid)
		if ((seq_mat[0] != 0.0) || (seq_mat[1] != 0.0) || (seq_mat[2] != 0.0))
		{
			//See if we're a swing, if not, this is meaningless
			if (bustype != SWING)
			{
				gl_warning("substation is not a SWING bus, so answers may be unexpected");
				/*  TROUBLESHOOT
				A substation object appears set to accept sequence voltage values, but it is not a SWING bus.  This
				may end up causing the voltages to be converted from sequence, but then overridden by the distribution
				powerflow solver.
				*/
			}

			//Explicitly set
			has_parent = 0;
		}	
		else	//Else, nothing set, we're a normal old node
		{
			has_parent = 2;	//Normal node

			//Warn that nothing was found
			gl_warning("substation:%s is set up as a normal node, no sequence values will be calculated",hdr->name);
			/*  TROUBLESHOOT
			A substation is currently behaving just like a normal powerflow node.  If it was desired that it convert a 
			schedule or player of sequence values, please initialize those values to non-zero along with the player attachment.
			*/
		}
	}//End no parent

	//Set up reference items if they are needed
	if (has_parent != 2)	//Not a normal node
	{
		//New requirement to maintain positive sequence ability - three phases must be had, unless
		//we're just a normal node.  Then, we don't care.
		if (!has_phase(PHASE_A|PHASE_B|PHASE_C))
		{
			gl_error("substation needs to have all three phases!");
			/*  TROUBLESHOOT
			To meet the requirements for sequence voltage conversions, the substation node must have all three
			phases at the connection point.  If only a single phase or subset of full three phase is needed, those
			must be set in the distribution network, typically after a delta-ground wye transformer.
			*/
			return 0;
		}
	}//End not a normal node

	//set the reference phase number to shift the phase voltages appropriatly with the positive sequence voltage
	if(reference_phase == R_PHASE_A){
		reference_number.SetPolar(1,0);
	} else if(reference_phase == R_PHASE_B){
		reference_number.SetPolar(1,2*PI/3);
	} else if(reference_phase == R_PHASE_C){
		reference_number.SetPolar(1,-2*PI/3);
	}

	//create the sequence to phase transformation matrix
	for(i=0; i<3; i++){
		for(n=0; n<3; n++){
			if((i==1 && n==1) || (i==2 && n==2)){
				transformation_matrix[i][n].SetPolar(1,-2*PI/3);
			} else if((i==2 && n==1) || (i==1 && n==2)){
				transformation_matrix[i][n].SetPolar(1,2*PI/3);
			} else {
				transformation_matrix[i][n].SetPolar(1,0);
			}
		}
	}
	
	return node::init(parent);
}
コード例 #20
0
/* Sync is called when the clock needs to advance on the bottom-up pass */
TIMESTAMP microturbine::sync(TIMESTAMP t0, TIMESTAMP t1) 
{
	//gather V_Out for each phase
	//gather I_Out for each phase
	//gather VA_Out for each phase
	//gather Q_Out
	//gather S_Out
	//gather Pf_Out

	phaseA_V_Out = pCircuit_V_A[0];
	phaseB_V_Out = pCircuit_V_B[0];
	phaseC_V_Out = pCircuit_V_C[0];

	phaseA_I_Out = pLine_I_A[0];
	phaseB_I_Out = pLine_I_B[0];
	phaseC_I_Out = pLine_I_C[0];

	gl_verbose("microturbine sync: phaseA_V_Out from parent is: (%f , %f)", phaseA_V_Out.Re(), phaseA_V_Out.Im());
	gl_verbose("microturbine sync: phaseB_V_Out from parent is: (%f , %f)", phaseB_V_Out.Re(), phaseB_V_Out.Im());
	gl_verbose("microturbine sync: phaseC_V_Out from parent is: (%f , %f)", phaseC_V_Out.Re(), phaseC_V_Out.Im());

	gl_verbose("microturbine sync: phaseA_I_Out from parent is: (%f , %f)", phaseA_I_Out.Re(), phaseA_I_Out.Im());
	gl_verbose("microturbine sync: phaseB_I_Out from parent is: (%f , %f)", phaseB_I_Out.Re(), phaseB_I_Out.Im());
	gl_verbose("microturbine sync: phaseC_I_Out from parent is: (%f , %f)", phaseC_I_Out.Re(), phaseC_I_Out.Im());

	power_A_Out = (~phaseA_I_Out) * phaseA_V_Out;
	power_B_Out = (~phaseB_I_Out) * phaseB_V_Out;
	power_C_Out = (~phaseC_I_Out) * phaseC_V_Out;


	gl_verbose("microturbine sync: power_A_Out from parent is: (%f , %f)", power_A_Out.Re(), power_A_Out.Im());
	gl_verbose("microturbine sync: power_B_Out from parent is: (%f , %f)", power_B_Out.Re(), power_B_Out.Im());
	gl_verbose("microturbine sync: power_C_Out from parent is: (%f , %f)", power_C_Out.Re(), power_C_Out.Im());


	VA_Out = power_A_Out + power_B_Out + power_C_Out;

	E_A_Internal = determine_source_voltage(phaseA_V_Out, Rinternal, Rload);
	E_B_Internal = determine_source_voltage(phaseB_V_Out, Rinternal, Rload);
	E_C_Internal = determine_source_voltage(phaseC_V_Out, Rinternal, Rload);


	
	gl_verbose("microturbine sync: E_A_Internal calc is: (%f , %f)", E_A_Internal.Re(), E_A_Internal.Im());
	gl_verbose("microturbine sync: E_B_Internal calc is: (%f , %f)", E_B_Internal.Re(), E_B_Internal.Im());
	gl_verbose("microturbine sync: E_C_Internal calc is: (%f , %f)", E_C_Internal.Re(), E_C_Internal.Im());


	frequency = determine_frequency(VA_Out);

	gl_verbose("microturbine sync: determined frequency is: %f", frequency);

	if(frequency > Max_Frequency){
		throw ("the frequency asked for from the microturbine is too high!");
	}
	if(frequency < Min_Frequency){
		throw ("the frequency asked for from the microturbine is too low!");
	}


	double loss = calculate_loss(frequency);
	efficiency = 1 - loss;
	Heat_Out = determine_heat(VA_Out, loss);
	Fuel_Used = Heat_Out + VA_Out.Mag();
	
	gl_verbose("microturbine sync: about to exit");

return TS_NEVER;
}
コード例 #21
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 */
}
コード例 #22
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;
	}
}
コード例 #23
0
ファイル: micro_service.cpp プロジェクト: am546/wis_project
/* Object initialization is called once after all object have been created */
int micro_service::init(OBJECT *parent)
{



    price = pmy_microturbine->microturbine_init();


	
	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("micro_service init: mapped METER objects to internal variables");
	}
	else if (parent!=NULL && strcmp(parent->oclass->name,"rectifier")==0){
		gl_verbose("micro_service 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("micro_service 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("micro_service init: mapped meter objects to internal variables");

		OBJECT *obj = OBJECTHDR(this);
		gl_verbose("micro_service init: no parent meter defined, parent is not a meter");
		gl_warning("micro_service:%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("micro_service 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 */
}
コード例 #24
0
TIMESTAMP complex_assert::commit(TIMESTAMP t1, TIMESTAMP t2)
{
	// handle once mode
	if ( once==ONCE_TRUE)
	{
		once_value = value;
		once = ONCE_DONE;
	} 
	else if ( once==ONCE_DONE)
	{
		if ( once_value.Re()==value.Re() && once_value.Im()==value.Im() )
		{
			gl_verbose("Assert skipped with ONCE logic");
			return TS_NEVER;
		} 
		else 
		{
			once_value = value;
		}
	}

	// get the target property
	gld_property target_prop(get_parent(),get_target());
	if ( !target_prop.is_valid() || target_prop.get_type()!=PT_complex ) {
		gl_error("Specified target %s for %s is not valid.",get_target(),get_parent()->get_name());
		/*  TROUBLESHOOT
		Check to make sure the target you are specifying is a published variable for the object
		that you are pointing to.  Refer to the documentation of the command flag --modhelp, or 
		check the wiki page to determine which variables can be published within the object you
		are pointing to with the assert function.
		*/
		return 0;
	}

	// test the target value
	complex x; target_prop.getp(x);
	if ( status==ASSERT_TRUE )
	{
		if ( operation==FULL || operation==REAL || operation==IMAGINARY )
		{	
			complex error = x - value;
			double real_error = error.Re();
			double imag_error = error.Im();
			if ( ( _isnan(real_error) || fabs(real_error)>within ) 
				&& ( operation==FULL || operation==REAL )
				)
			{
				gl_error("Assert failed on %s: real part of %s %g not within %f of given value %g", 
					get_parent()->get_name(), get_target(), x.Re(), within, value.Re());
				return 0;
			}
			if ( ( _isnan(imag_error) || fabs(imag_error)>within ) 
				&& ( operation==FULL || operation==IMAGINARY )
				)
			{
				gl_error("Assert failed on %s: imaginary part of %s %+gi not within %f of given value %+gi", 
					get_parent()->get_name(), get_target(), x.Im(), within, value.Im());
				return 0;
			}
		}
		else if ( operation==MAGNITUDE )
		{
			double magnitude_error = x.Mag() - value.Mag();
			if ( _isnan(magnitude_error) || fabs(magnitude_error)>within )
			{
				gl_error("Assert failed on %s: Magnitude of %s (%g) not within %f of given value %g", 
					get_parent()->get_name(), get_target(), x.Mag(), within, value.Mag());
				return 0;
			}
		}
		else if (get_operation() == ANGLE)
		{
			double angle_error = x.Arg() - value.Arg();
			if ( _isnan(angle_error) || fabs(angle_error)>within )
			{
				gl_error("Assert failed on %s: Angle of %s (%g) not within %f of given value %g", 
					get_parent()->get_name(), get_target(), x.Arg(), within, value.Arg());
				return 0;
			}
		}
	}
	else if (get_status() == ASSERT_FALSE)
	{
		complex error = x - value;
		double real_error = error.Re();
		double imag_error = error.Im();
		if ( ( _isnan(real_error) || fabs(real_error)<within )
			|| ( _isnan(imag_error) || fabs(imag_error)<within )
			)
		{
			if ( _isnan(real_error) || fabs(real_error)<within ) 
			{
				gl_error("Assert failed on %s: real part of %s %g is within %f of %g", 
					get_parent()->get_name(), get_target(), x.Re(), within, value.Re());
			}
			if ( _isnan(imag_error) || fabs(imag_error)<within ) {
				gl_error("Assert failed on %s: imaginary part of %s %+gi is within %f of %gi", 
					get_parent()->get_name(), get_target(), x.Im(), within, value.Im());
			}
			return 0;
		}
	}
	else
	{
		gl_verbose("Assert test is not being run on %s", get_parent()->get_name());
		return TS_NEVER;
	}
	gl_verbose("Assert passed on %s",get_parent()->get_name());
	return TS_NEVER;
}
コード例 #25
0
ファイル: solar_service.cpp プロジェクト: am546/wis_project
/** Checks for climate object and maps the climate variables to the house object variables.  
Currently Tout, RHout and solar_service flux data from TMY files are used.  If no climate object is linked,
then Tout will be set to 59 degF, RHout is set to 75% and solar_service flux will be set to zero for all orientations.
**/
int solar_service::init_climate()
{
	OBJECT *hdr = OBJECTHDR(this);
	OBJECT *obj = NULL;

	// link to climate data
	FINDLIST *climates = NULL;
	
	if (solar_service_model_tilt != PLAYERVAL)
	{
		if (weather!=NULL)
		{
			if(!gl_object_isa(weather, "climate")){
				// strcmp failure
				gl_error("weather property refers to a(n) \"%s\" object and not a climate object", weather->oclass->name);
				/*  TROUBLESHOOT
				While attempting to map a climate property, the solar_service array encountered an object that is not a climate object.
				Please check to make sure a proper climate object is present, and/or specified.  If the bug persists, please
				submit your code and a bug report via the trac website.
				*/
				return 0;
			}
			obj = weather;
		}
		else	//No weather specified, search
		{
			climates = gl_find_objects(FL_NEW,FT_CLASS,SAME,"climate",FT_END);
			if (climates==NULL)
			{
				//Ensure weather is set to NULL - catch below
				weather = NULL;
			}
			else if (climates->hit_count==0)
			{
				//Ensure weather is set to NULL - catch below
				weather = NULL;
			}
			else //climate data must have been found
			{
				if (climates->hit_count>1)
				{
					gl_warning("solar_servicepanel: %d climates found, using first one defined", climates->hit_count);
					/*  TROUBLESHOOT
					More than one climate object was found, so only the first one will be used by the solar_service array object
					*/
				}


				gl_verbose("solar_service init: climate data was found!");
				// force rank of object w.r.t climate
				obj = gl_find_next(climates,NULL);
				weather = obj;
			}
		}

		//Make sure it actually found one
		if (weather == NULL)
		{
			//Replicate above warning
			gl_warning("solar_servicepanel: no climate data found, using static data");
			/*  TROUBLESHOOT
			No climate object was found and player mode was not enabled, so the solar_service array object
			is utilizing default values for all relevant weather variables.
			*/

			//default to mock data
			static double tout=59.0, rhout=0.75, solar_service=92.902, wsout=0.0, albdefault=0.2;
			pTout = &tout;
			pRhout = &rhout;
			psolar_serviceD = &solar_service;	//Default all solar_service values to normal "optimal" 1000 W/m^2
			psolar_serviceH = &solar_service;
			psolar_serviceG = &solar_service;
			pAlbedo = &albdefault;
			pWindSpeed = &wsout;

			if (orientation_type==FIXED_AXIS)
			{
				GL_THROW("FIXED_AXIS requires a climate file!");
				/*  TROUBLESHOOT
				The FIXED_AXIS model for the PV array requires climate data to properly function.
				Please specify such data, or consider using a different tilt model.
				*/
			}
		}
		else if (!gl_object_isa(weather,"climate"))	//Semi redundant for "weather"
		{
			GL_THROW("weather object is not a climate object!");
			/*  TROUBLESHOOT
			The object specified for the weather property is not a climate object and will not work
			with the solar_service object.  Please specify a valid climate object, or let the solar_service object
			automatically connect.
			*/
		}
		else	//Must be a proper object
		{
			if((obj->flags & OF_INIT) != OF_INIT){
				char objname[256];
				gl_verbose("solar_service::init(): deferring initialization on %s", gl_name(obj, objname, 255));
				return 2; // defer
			}
			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"));	<---- Not used anywhere yet
			psolar_serviceD = (double*)GETADDR(obj,gl_get_property(obj,"solar_service_direct"));
			psolar_serviceH = (double*)GETADDR(obj,gl_get_property(obj,"solar_service_diffuse"));
			psolar_serviceG = (double*)GETADDR(obj,gl_get_property(obj,"solar_service_global"));
			pAlbedo = (double*)GETADDR(obj,gl_get_property(obj,"ground_reflectivity"));
			pWindSpeed = (double*)GETADDR(obj,gl_get_property(obj,"wind_speed"));

			//Should probably check these
			if (pTout==NULL)
			{
				GL_THROW("Failed to map outside temperature");
				/*  TROUBLESHOOT
				The solar_service PV array failed to map the outside air temperature.  Ensure this is
				properly specified in your climate data and try again.
				*/
			}

			//No need to error check - doesn't exist in any formulations yet
			//if (pRhout==NULL)
			//{
			//	GL_THROW("Failed to map outside relative humidity");
			//	/*  TROUBLESHOOT
			//	The solar_service PV array failed to map the outside relative humidity.  Ensure this is
			//	properly specified in your climate data and try again.
			//	*/
			//}

			if (psolar_serviceD==NULL)
			{
				GL_THROW("Failed to map direct normal solar_service radiation");
				/*  TROUBLESHOOT
				The solar_service PV array failed to map the solar_service direct normal radiation.  Ensure this is
				properly specified in your climate data and try again.
				*/
			}

			if (psolar_serviceH==NULL)
			{
				GL_THROW("Failed to map diffuse horizontal solar_service radiation");
				/*  TROUBLESHOOT
				The solar_service PV array failed to map the solar_service diffuse horizontal radiation.  Ensure this is
				properly specified in your climate data and try again.
				*/
			}

			if (psolar_serviceG==NULL)
			{
				GL_THROW("Failed to map global horizontal solar_service radiation");
				/*  TROUBLESHOOT
				The solar_service PV array failed to map the solar_service global horizontal radiation.  Ensure this is
				properly specified in your climate data and try again.
				*/
			}

			if (pAlbedo==NULL)
			{
				GL_THROW("Failed to map albedo/ground reflectance");
				/*  TROUBLESHOOT
				The solar_service PV array failed to map the ground reflectance.  Ensure this is
				properly specified in your climate data and try again.
				*/
			}

			if (pWindSpeed==NULL)
			{
				GL_THROW("Failed to map wind speed");
				/*  TROUBLESHOOT
				The solar_service PV array failed to map the wind speed.  Ensure this is
				properly specified in your climate data and try again.
				*/
			}

			//If climate data was found, check other related variables
			if (fix_angle_lat==true)
			{
				if (obj->latitude < 0)	//Southern hemisphere
				{
					//Get the latitude from the climate file
					tilt_angle = -obj->latitude;
				}
				else	//Northern
				{
					//Get the latitude from the climate file
					tilt_angle = obj->latitude;
				}
			}

			//Check the tilt angle for absurdity
			if (tilt_angle < 0)
			{
				GL_THROW("Invalid tilt_angle - tilt must be between 0 and 90 degrees");
				/*  TROUBLESHOOT
				A negative tilt angle was specified.  This implies the array is under the ground and will
				not receive any meaningful solar_service irradiation.  Please correct the tilt angle and try again.
				*/
			}
			else if (tilt_angle > 90.0)
			{
				GL_THROW("Invalid tilt angle - values above 90 degrees are unsupported!");
				/*  TROUBLESHOOT
				An tilt angle over 90 degrees (straight up and down) was specified.  Beyond this angle, the
				tilt algorithm does not function properly.  Please specific the tilt angle between 0 and 90 degrees
				and try again.
				*/
			}

			//Check the solar_service method
			if (orientation_type == FIXED_AXIS)
			{
				//See which function we want to use
				if (solar_service_model_tilt==LIUJORDAN)
				{
					//Map up the "classic" function
					calc_solar_service_radiation = (FUNCTIONADDR)(gl_get_function(obj,"calculate_solar_service_radiation_shading_degrees"));
				}
				else if (solar_service_model_tilt==SOLPOS)	//Use the solpos/Perez tilt model
				{
					//Map up the "classic" function
					calc_solar_service_radiation = (FUNCTIONADDR)(gl_get_function(obj,"calc_solpos_radiation_shading_degrees"));
				}
								
				//Make sure it was found
				if (calc_solar_service_radiation == NULL)
				{
					GL_THROW("Unable to map solar_service radiation function on %s in %s",obj->name,hdr->name);
					/*  TROUBLESHOOT
					While attempting to initialize the photovoltaic array mapping of the solar_service radiation function.
					Please try again.  If the bug persists, please submit your GLM and a bug report via the trac website.
					*/
				}

				//Check azimuth for absurdity as well
				if ((orientation_azimuth<0.0) || (orientation_azimuth > 360.0))
				{
					GL_THROW("orientation_azimuth must be a value representing a valid cardinal direction of 0 to 360 degrees!");
					/*  TROUBLESHOOT
					The orientation_azimuth property is expected values on the cardinal points degree system.  For this convention, 0 or
					360 is north, 90 is east, 180 is south, and 270 is west.  Please specify a direction within the 0 to 360 degree bound and try again.
					*/
				}

				//Map up our azimuth now too, if needed - Liu & Jordan model assumes 0 = equator facing
				if (solar_service_model_tilt == LIUJORDAN)
				{
					if (obj->latitude>0.0)	//North - "south" is equatorial facing
					{
						orientation_azimuth_corrected =  180.0 - orientation_azimuth;
					}
					else if (obj->latitude<0.0) //South - "north" is equatorial facing
					{
						gl_warning("solar_service:%s - Default solar_service position model is not recommended for southern hemisphere!",hdr->name);
						/*  TROUBLESHOOT
						The Liu-Jordan (default) solar_service position and tilt model was built around the northern
						hemisphere.  As such, operating in the southern hemisphere does not provide completely accurate
						results.  They are close, but tilted surfaces are not properly accounted for.  It is recommended
						that the solar_service_TILT_MODEL SOLPOS be used for southern hemisphere operations.
						*/

						if ((orientation_azimuth >= 0.0) && (orientation_azimuth <= 180.0))
						{
							orientation_azimuth_corrected =  orientation_azimuth;	//East positive
						}
						else if (orientation_azimuth == 360.0) //Special case for those who like 360 as North
						{
							orientation_azimuth_corrected = 0.0;
						}
						else	//Must be west
						{
							orientation_azimuth_corrected = orientation_azimuth - 360.0;
						}
					}
					else	//Equator - erm....
					{
						GL_THROW("Exact equator location of array detected - unknown how to handle orientation");
						/*  TROUBLESHOOT
						The solar_service orientation algorithm implemented inside GridLAB-D does not understand how to orient
						itself for an array exactly on the equator.  Shift it north or south a little bit to get valid results.
						*/
					}
				}
				else	//Right now only SOLPOS, which is "correct" - if another is implemented, may need another case
					orientation_azimuth_corrected = orientation_azimuth;
			}
			//Defaulted else for now - don't do anything
		}//End valid weather - mapping check
	}
	else	//Player mode, just drop a message
	{
		gl_warning("solar_service object:%s is in player mode - be sure to specify relevant values",hdr->name);
		/*  TROUBLESHOOT
		The solar_service array object is in player mode.  It will not take values from climate files or objects.
		Be sure to specify the Insolation, ambient_temperature, and wind_speed values as necessary.  It also
		will not incorporate any tilt functionality, since the Insolation value is expected to already include
		this adjustment.
		*/
	}

	return 1;
}
コード例 #26
0
ファイル: collector.cpp プロジェクト: brennane/gridpot
int collector::init(OBJECT *parent)
{
	// check the connection
	if ( get_connection()!=NULL )
		db = (database*)(get_connection()+1);
	if ( db==NULL )
		exception("no database connection available or specified");
	if ( !db->isa("database") )
		exception("connection is not a mysql database");
	gl_verbose("connection to mysql server '%s', schema '%s' ok", db->get_hostname(), db->get_schema());

	// check mode
	if ( strlen(mode)>0 )
	{
		options = 0xffffffff;
		struct {
			char *str;
			set bits;
		} modes[] = {
			{"r",	0xffff},
			{"r+",	0xffff},
			{"w",	MO_DROPTABLES},
			{"w+",	MO_DROPTABLES},
			{"a",	0x0000},
			{"a+",	0x0000},
		};
		int n;
		for ( n=0 ; n<sizeof(modes)/sizeof(modes[0]) ; n++ )
		{
			if ( strcmp(mode,modes[n].str)==0 )
			{
				options = modes[n].bits;
				break;
			}
		}
		if ( options==0xffffffff )
			exception("mode '%s' is not recognized",(const char*)mode);
		else if ( options==0xffff )
			exception("mode '%s' is not valid for a recorder", (const char*)mode);
	}

	// verify group is defined
	if ( strcmp(get_group(),"")==0 )
		exception("group must be specified");

	// verify property is defined
	if ( strcmp(get_property(),"")==0 )
		exception("at least one property aggregation must be specified");

	// copy property spec into working buffer
	char1024 propspecs;
	strcpy(propspecs,get_property());

	// count properties in specs
	char *p = propspecs;
	n_aggregates = 0;
	do {
		n_aggregates++;
		p = strchr(p,',');
	} while (p++!=NULL);
	list = new gld_aggregate[n_aggregates];
	names = new char*[n_aggregates];

	// load property structs
	int n;
	for ( p=propspecs,n=0 ; n<n_aggregates ; n++ )
	{
		char *np = strchr(p,',');
		if ( np!=NULL ) *np='\0';
		while ( *p!='\0' && isspace(*p) ) p++; // left trim
		int len = strlen(p);
		while ( len>0 && isspace(p[len-1]) ) p[--len]='\0'; // right trim
		if ( !list[n].set_aggregate(p,get_group()) )
			exception("unable to aggregate '%s' over group '%s'", p, get_group());
		gl_debug("%s: group '%s' aggregate '%s' initial value is '%lf'", get_name(), get_group(), p, list[n].get_value());
		names[n] = new char[strlen(p)+1];
		strcpy(names[n],p);
		p = np+1;
	}
	gl_debug("%s: %d aggregates ok", get_name(), n_aggregates);

	// drop table if exists and drop specified
	if ( db->table_exists(get_table()) )
	{
		if ( get_options()&MO_DROPTABLES && !db->query("DROP TABLE IF EXISTS `%s`", get_table()) )
			exception("unable to drop table '%s'", get_table());
	}
	
	// create table if not exists
	if ( !db->table_exists(get_table()) )
	{
		if ( !(options&MO_NOCREATE) )
		{
			char buffer[4096];
			size_t eos = sprintf(buffer,"CREATE TABLE IF NOT EXISTS `%s` ("
				"id INT AUTO_INCREMENT PRIMARY KEY, "
				"t TIMESTAMP, ", get_table());
			int n;
			for ( n=0 ; n<n_aggregates ; n++ )
				eos += sprintf(buffer+eos,"`%s` double, ",names[n]);
			eos += sprintf(buffer+eos,"%s","INDEX i_t (t))");

			if ( !db->query(buffer) )
				exception("unable to create table '%s' in schema '%s'", get_table(), db->get_schema());
			else
				gl_verbose("table %s created ok", get_table());
		}
		else
			exception("NOCREATE option prevents creation of table '%s'", get_table());
	}

	// check row count
	else 
	{
		if ( db->select("SELECT count(*) FROM `%s`", get_table())==NULL )
			exception("unable to get row count of table '%s'", get_table());

		gl_verbose("table '%s' ok", get_table());
	}
	
	// first event time
	TIMESTAMP dt = (TIMESTAMP)get_interval();
	if ( dt>0 )
		next_t = (TIMESTAMP)(gl_globalclock/dt+1)*dt;
	else if ( dt==0 )
		next_t = TS_NEVER;
	else
		exception("%s: interval must be zero or positive");
		
	// @todo use prepared statement instead of insert

	// set heartbeat
	if ( interval>0 )
		set_heartbeat((TIMESTAMP)interval);

	return 1;
}
コード例 #27
0
/** 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);
}
コード例 #28
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);
}
コード例 #29
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;
}
コード例 #30
0
int ZIPload::init(OBJECT *parent)
{
	
	
	
		////////////////////////////////////SEARCH////////////////////////////////////
	
	 static FINDLIST *xt2=NULL;
				 xt2=gl_find_objects(FL_NEW,FT_CLASS,SAME,"irrigation_controller",FT_END);
				 OBJECT *firstt2= gl_find_next(xt2,NULL);
				 OBJECT *it2;
				 for(it2=firstt2;it2!=NULL;it2=it2->next)
				 {
				
					 if(gl_object_isa(it2,"irrigation_controller"))
				     {
						

						 if(OBJECTHDR(this)->id==it2->parent->id)
						{
							irrigation_contr_object=it2;
							// printf("%d %d",OBJECTHDR(this)->id,irrigation_contr_object->id);
						 //system("pause");
						}
						 else
						 {
							// irrigation_contr_object=NULL;
						 }

					 }
				 }


				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;
						
					 }

				 }

	//////////////////////////////////////////////////////////////////////////////

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

	if (demand_response_mode == true)
	{
		gl_warning("zipload_init: The demand response zipload is an experimental model at this time.");
		/*  TROUBLESHOOT
		The warning is pretty obvious.  However, over time, we will be developing this model further.  If you have any questions 
		about it, please see the Matlab files found in ../design/dr_model/ or read the paper titled "On the Equilibrium Dynamics of Demand Response"
		submitted to HICSS 2011 or post your questions on the WIKI forum.
		*/
		
		// Initial error checks
		if (abs(eta) > 1)
		{
			GL_THROW("zipload_init: demand_rate (eta) must be between -1 and 1.");
			/*  TROUBLESHOOT
			The demand rate is limited to values between -1 and 1 (inclusive).  Please reset to an appropriate value.
			*/
		}
		if (phi < 0 || phi > 1)
		{
			GL_THROW("zipload_init: duty_cycle (phi) must be between 0 and 1.");
			/*  TROUBLESHOOT
			The duty cycle is only explicitly used if ron and roff are not set.  In normal operation, phi will be calculated from
			ron and roff as a function of time.  However, if ron and roff are not set, the initial values for ron and roff are calculated
			from phi.  Please set to a value between 1 and 0 (inclusive).
			*/
		}
		
		// Set up the buffers and perform some error checks
		if (L > 0)
			if (L < 70)
				drm.nbins = L;
			else
			{
				gl_warning("zipload_init: Using a value for thermostatic_control_range (L) greater than 50 may cause some instabilities.");
				/*  TROUBLESHOOT
				This warning is shown only as a reminder.  Large values of L (thermostatic_control_range) can cause instabilities for some
				combinations of ron and roff.  If you receive inderminant numbers as part of the solution, try reducing L.
				*/
			}
		else
		{
			GL_THROW("zipload_init: thermostatic_control_range (L) must be greater than 0.");
			/*  TROUBLESHOOT
			The thermostatic control range must be a positive integer value, since this is used to create the number of bins 
			for the discrete solution.
			*/
		}

		drm.off = (double*)malloc(sizeof(double)*L);
		drm.on = (double*)malloc(sizeof(double)*L);
		if (drm.off==NULL || drm.on==NULL)
		{
			GL_THROW("zipload_init: memory allocation error.  Please report this error.");
			/*  TROUBLESHOOT
			If you receive this error, something went horribly wrong with a memory allocation. Please report this to TRAC and provide
			the glm file that caused it.
			*/
		}

		/* setup the initial population */
		if (ron == -1 || roff == -1)
		{
			if (phi <= 0.5)
			{
				roff = phi/(1-phi);
				ron = 1;
				gl_warning("ron or roff was not set.  Using phi to calculate.  Step changes in demand rates as a function of time will be ignored.");
				/*  TROUBLESHOOT
				Ideally, in the method currently being used, ron and roff (heating and cooling rates) should be used to calculate phi.
				If you receive this error, the phi is being used to calculate ron and roff initially.  However, phi does not update  
				ron and roff at each time step, so you will not be able to perform disturbances of demand.  If you wish this, please use
				ron and roff as a function of time instead.  This can also be caused by using a schedule or player transform to describe 
				the ron or roff values - essentially during the initialization, the value is not described yet.  There is no current fix for
				this, but can be "faked" by setting phi to the correct initial value and waiting a couple of timesteps for things to settle.
				*/
			}
			else
			{
				roff = 1;
				ron = (1-phi)/phi;
				gl_warning("ron or roff was not set.  Using phi to calculate. Step changes in demand rates as a function of time will be ignored.");
				/*  TROUBLESHOOT
				Ideally, in the method currently being used, ron and roff (heating and cooling rates) should be used to calculate phi.
				If you receive this error, the phi is being used to calculate ron and roff initially.  However, phi does not update  
				ron and roff at each time step, so you will not be able to perform disturbances of demand.  If you wish this, please use
				ron and roff as a function of time instead.  This can also be caused by using a schedule or player transform to describe 
				the ron or roff values - essentially during the initialization, the value is not described yet.  There is no current fix for
				this, but can be "faked" by setting phi to the correct initial value and waiting a couple of timesteps for things to settle.
				*/
			}
		}
		else
			phi = roff / (ron + roff);

		if (roff < 0 || ron < 0)
		{
			GL_THROW("zipload_init: rate_of_cooling and rate_of_heating must be greater than or equal to 0.");
			/*  TROUBLESHOOT
			Rates of heating and cooling should be positive or zero values.  These values describe how fast objects transition from a 
			cooler to hotter temperature, or vice versa, and have been defined as positive values in this model.
			*/
		}

		non = noff = 0;
		double test_N = 0;

		for (x=0; x<L; x++)
		{
			/* exponential distribution */
			if (eta != 0)
			{
				drm.on[x] = N * eta * (1-phi) * exp(eta*(L-0.5-x)/roff) / (exp(eta*L/roff)-1);
				drm.off[x] = drm.on[x] * ron/roff;
				test_N += drm.on[x] + drm.off[x];
				//non += drm.on[x] = eta * (1-phi) * exp(eta*(L-x+0.5)/roff) / (exp(eta*L/roff)-1);
				//noff += drm.off[x] = drm.on[x]*ron/roff;
			}

			/* uniform distribution */
			else
			{
				non += drm.on[x] = N * phi/L;
				noff += drm.off[x] = N * (1-phi)/L;
				printf("testsfsdfsdfs : : : ;%f %f",non,noff);
			}
		}

		/* check for valid population */
		if (abs(test_N - N) != 0)
		{
			double extra = N - test_N;
			drm.off[0] += extra;
		}
		
	}

	if (duty_cycle > 1 || duty_cycle < 0)
	{
		if (duty_cycle != -1)
		{
			GL_THROW("Value of duty cycle is set to a value outside of 0-1.");
			/*  TROUBLESHOOT
			By definition, a duty cycle must be between, and including, 0 and 1.  Zero will turn the
			duty cycle function OFF.  Please specify a duty_cycle value between 0 and 1.
			*/
		}
	}

	// We're using a duty cycle mode
	if (duty_cycle != -1)
	{
		if (period <= 0)
		{
			GL_THROW("Period is less than or equal to zero.");
			/*  TROUBLESHOOT
			When using duty cycle mode, the period must be a positive value.
			*/
		}
		if (phase < 0 || phase > 1)
		{
			GL_THROW("Phase is not between zero and one.");
			/*  TROUBLESHOOT
			When using duty cycle mode, the phase must be specified as a value between 0 and 1.  This
			will set the initial phase as a percentage of the period.  The "duty" will assume to be
			applied at the beginning of each period.  Randomizing this input value will prevent syncing of
			objects.
			*/
		}
	}

	if (heatgain_only == true)
	{
		load.config = EUC_HEATLOAD;
		load.power_fraction = load.current_fraction = load.impedance_fraction = 0.0;
	}
	if (is_240)	//See if the 220/240 flag needs to be set
	{
		load.config |= EUC_IS220;
	}

	load.breaker_amps = breaker_val;
	
	only_once=0;
	first_time=0;
	return residential_enduse::init(parent);
}