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

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

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

	//TODO: datafromgld=gl_get_property.....
	datafromgld = get_complex(parent, power_property);
	datatogld = get_complex(parent, voltage_property);
	if(gl_object_isa(parent, "substation", "powerflow")){
		powerdiff = get_double(parent,"power_convergence_value");
	} else {
		default_powerdiff = 1; //default is 1 VA
		powerdiff = &default_powerdiff;
	}
	myinterface=Integrator::getCommInterface(hdr->name);
	printf("MY INTEFRACE is mull %d\n",myinterface==NULL);
}
예제 #2
0
EXPORT int kmldump(int (*stream)(const char*,...), OBJECT *obj)
{

	if (obj==NULL) /* dump document styles */
	{
		/* line styles */
		stream("<Style id=\"overhead_line\">\n"
			" <LineStyle>\n"
			"  <color>7f00ffff</color>\n"
			"  <width>4</width>\n"
			" </LineStyle>\n"
			" <PolyStyle>\n"
			"  <color>7f00ff00</color>\n"
			" </PolyStyle>\n"
			"</Style>\n");
		stream("<Style id=\"underground_line\">\n"
			" <LineStyle>\n"
			"  <color>3f00ffff</color>\n"
			"  <width>4</width>\n"
			" </LineStyle>\n"
			" <PolyStyle>\n"
			"  <color>3f00ff00</color>\n"
			" </PolyStyle>\n"
			"</Style>\n");
		return 0;
	}
	else if (gl_object_isa(obj,"node"))
		return OBJECTDATA(obj,node)->kmldump(stream);
	else if (gl_object_isa(obj,"link"))
		return OBJECTDATA(obj,link_object)->kmldump(stream);
	else
		return 0; 
}
예제 #3
0
void voltdump::dump(TIMESTAMP t){
	char namestr[64];
	char timestr[64];
	FINDLIST *nodes = NULL;
	OBJECT *obj = NULL;
	FILE *outfile = NULL;
	node *pnode;
//	CLASS *nodeclass = NULL;
//	PROPERTY *vA, *vB, *vC;

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

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

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

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

	int node_count = 0;
	while (obj=gl_find_next(nodes,obj)){
		if(gl_object_isa(obj, "node", "powerflow")){
			node_count += 1;
		}
	}
	/* print column names */
	gl_printtime(t, timestr, 64);
	fprintf(outfile,"# %s run at %s on %i nodes\n", filename.get_string(), timestr, node_count);
	if (mode == VDM_RECT)
		fprintf(outfile,"node_name,voltA_real,voltA_imag,voltB_real,voltB_imag,voltC_real,voltC_imag\n");
	else if (mode == VDM_POLAR)
		fprintf(outfile,"node_name,voltA_mag,voltA_angle,voltB_mag,voltB_angle,voltC_mag,voltC_angle\n");
	
	obj = 0;
	while (obj=gl_find_next(nodes,obj)){
		if(gl_object_isa(obj, "node", "powerflow")){
			pnode = OBJECTDATA(obj,node);
			if(obj->name == NULL){
				sprintf(namestr, "%s:%i", obj->oclass->name, obj->id);
			}
			if(mode == VDM_RECT){
				fprintf(outfile,"%s,%f,%f,%f,%f,%f,%f\n",(obj->name ? obj->name : namestr),pnode->voltage[0].Re(),pnode->voltage[0].Im(),pnode->voltage[1].Re(),pnode->voltage[1].Im(),pnode->voltage[2].Re(),pnode->voltage[2].Im());
			} else if(mode == VDM_POLAR){
				fprintf(outfile,"%s,%f,%f,%f,%f,%f,%f\n",(obj->name ? obj->name : namestr),pnode->voltage[0].Mag(),pnode->voltage[0].Arg(),pnode->voltage[1].Mag(),pnode->voltage[1].Arg(),pnode->voltage[2].Mag(),pnode->voltage[2].Arg());
			}
		}
	}
	fclose(outfile);
}
/** 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;
	
}
예제 #5
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;
}
예제 #6
0
//sjin: add solar azimuth wrapper funcions
EXPORT int64 calculate_solar_azimuth(OBJECT *obj, double lititude, double *value)
{
	static SolarAngles sa; // just for the functions
	double std_time = 0.0;
	double solar_time = 0.0;
	short int doy = 0;
	DATETIME dt;

	climate *cli;
	if (obj == 0 || value == 0){
		//throw "climate/calc_solar: null object pointer in arguement";
		return 0;
	}
	cli = OBJECTDATA(obj, climate);
	if(gl_object_isa(obj, "climate", "climate") == 0){
		//throw "climate/calc_solar: input object is not a climate object";
		return 0;
	}

	gl_localtime(obj->clock, &dt);
	std_time = (double)(dt.hour) + ((double)dt.minute)/60.0 + (dt.is_dst ? -1:0);
	solar_time = sa.solar_time(std_time, doy, RAD(cli->tz_meridian), RAD(obj->longitude));

	double hr_ang = -(15.0 * PI_OVER_180)*(solar_time-12.0); // morning +, afternoon -

    double decl = 0.409280*sin(2.0*PI*(284+doy)/365);

	double alpha = (90.0 * PI_OVER_180) - lititude + decl;

	*value = acos( (sin(decl)*cos(lititude) - cos(decl)*sin(lititude)*cos(hr_ang))/cos(alpha) );

    return 1;
}
예제 #7
0
/* Object initialization is called once after all object have been created */
int multizone::init(OBJECT *parent)
{
	OBJECT *obj = OBJECTHDR(this);
	if (from==NULL)
		gl_error("%s (multizone:%d): from zone is not specified", obj->name?obj->name:"unnamed",obj->id);
	else if (!gl_object_isa(from,"office"))
		gl_error("%s (multizone:%d): from object is not an commercial office space", obj->name?obj->name:"unnamed",obj->id);
	if (to==NULL)
		gl_error("%s (multizone:%d): to zone is not specified", obj->name?obj->name:"unnamed",obj->id);
	else if (!gl_object_isa(to,"office"))
		gl_error("%s (multizone:%d): to object is not an commercial office space", obj->name?obj->name:"unnamed",obj->id);
	if (ua<=0)
		gl_error("%s (multizone:%d): ua must be positive (value is %.2f)", obj->name?obj->name:"unnamed",obj->id,ua);
	gl_set_rank(from,obj->rank+1);
	gl_set_rank(to,obj->rank+1);
	return 1; /* return 1 on success, 0 on failure */
}
예제 #8
0
EXPORT int init_generator(OBJECT *obj)
{
	if (obj->parent && gl_object_isa(obj->parent,"node"))
		return OBJECTDATA(obj,generator)->init(OBJECTDATA(obj->parent,node));
	else
	{
		gl_error("generator:%d is not connected to a network node", obj->id);
		return 0;
	}
}
예제 #9
0
int powerflow_object::init(OBJECT *parent)
{
	/* unspecified phase inherits from parent, if any */
	if (parent && gl_object_isa(parent,"powerflow_object"))
	{
		powerflow_object *pParent = OBJECTDATA(parent,powerflow_object);
		if (phases==NO_PHASE)
			phases = pParent->phases;
	}

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

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

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

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

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

	return 1;
}
예제 #10
0
EXPORT int64 calculate_solar_radiation_shading_radians(OBJECT *obj, double tilt, double orientation, double shading_value, double *value){
	static SolarAngles sa; // just for the functions
	double ghr, dhr, dnr = 0.0;
	double cos_incident = 0.0;
	double std_time = 0.0;
	double solar_time = 0.0;
	short int doy = 0;
	DATETIME dt;

	climate *cli;
	if(obj == 0 || value == 0){
		//throw "climate/calc_solar: null object pointer in arguement";
		return 0;
	}
	cli = OBJECTDATA(obj, climate);
	if(gl_object_isa(obj, "climate", "climate") == 0){
		//throw "climate/calc_solar: input object is not a climate object";
		return 0;
	}
	ghr = cli->solar_global;
	dhr = cli->solar_diffuse;
	dnr = shading_value * cli->solar_direct;

	gl_localtime(obj->clock, &dt);

	std_time = (double)(dt.hour) + ((double)dt.minute)/60.0  + (dt.is_dst ? -1.0:0.0);

	doy=sa.day_of_yr(dt.month,dt.day);

	solar_time = sa.solar_time(std_time, doy, RAD(cli->tz_meridian), RAD(obj->longitude));
	cos_incident = sa.cos_incident(RAD(obj->latitude), tilt, orientation, solar_time, doy);

	*value = dnr * cos_incident + dhr * (1 + cos(tilt)) / 2 + ghr * (1 - cos(tilt)) * cli->ground_reflectivity / 2;

	return 1;
}
예제 #11
0
void billdump::dump(TIMESTAMP t){
	char namestr[64];
	char timestr[64];
	FINDLIST *nodes = NULL;
	OBJECT *obj = NULL;
	FILE *outfile = NULL;
	triplex_meter *pnode;
	meter *qnode;
	

//	CLASS *nodeclass = NULL;
//	PROPERTY *vA, *vB, *vC;

	if (meter_type == METER_TP)
	{
		if(group[0] == 0){
			nodes = gl_find_objects(FL_NEW,FT_CLASS,SAME,"triplex_meter",FT_END);
		} else {
			nodes = gl_find_objects(FL_NEW,FT_CLASS,SAME,"triplex_meter",AND,FT_GROUPID,SAME,group,FT_END);
		}
	}
	else
	{
		if(group[0] == 0){
			nodes = gl_find_objects(FL_NEW,FT_CLASS,SAME,"meter",FT_END);
		} else {
			nodes = gl_find_objects(FL_NEW,FT_CLASS,SAME,"meter",AND,FT_GROUPID,SAME,group,FT_END);
		}
	}

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

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

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

	if (meter_type == METER_TP)
	{
		/* print column names */
		gl_printtime(t, timestr, 64);
		fprintf(outfile,"# %s run at %s on %i triplex meters\n", filename, timestr, nodes->hit_count);
		fprintf(outfile,"meter_name,previous_monthly_bill,previous_monthly_energy\n");
		while (obj=gl_find_next(nodes,obj)){
			if(gl_object_isa(obj, "triplex_meter", "powerflow")){
				pnode = OBJECTDATA(obj,triplex_meter);
				if(obj->name == NULL){
					sprintf(namestr, "%s:%i", obj->oclass->name, obj->id);
				}
				fprintf(outfile,"%s,%f,%f\n",(obj->name ? obj->name : namestr),pnode->previous_monthly_bill,pnode->previous_monthly_energy);
			}
		}
	}
	else
	{
		/* print column names */
		gl_printtime(t, timestr, 64);
		fprintf(outfile,"# %s run at %s on %i meters\n", filename, timestr, nodes->hit_count);
		fprintf(outfile,"meter_name,previous_monthly_bill,previous_monthly_energy\n");
		while (obj=gl_find_next(nodes,obj)){
			if(gl_object_isa(obj, "meter", "powerflow")){
				qnode = OBJECTDATA(obj,meter);
				if(obj->name == NULL){
					sprintf(namestr, "%s:%i", obj->oclass->name, obj->id);
				}
				fprintf(outfile,"%s,%f,%f\n",(obj->name ? obj->name : namestr),qnode->previous_monthly_bill,qnode->previous_monthly_energy);
			}
		}
	}
	fclose(outfile);
}
예제 #12
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);
}
예제 #13
0
int house::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;

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

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

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

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

	if (ceiling_height <= ROUNDOFF)
		ceiling_height = 8.0;

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

	if (aspect_ratio <= ROUNDOFF)
		aspect_ratio = 1.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

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

			clear_price = market->current_frame.clearing_price;

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

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

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

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

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

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


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

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

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

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

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

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

	return TS_NEVER;


	//}
	
	} //end of first_period==0
}
TIMESTAMP irrigation_controller::presync(TIMESTAMP t0, TIMESTAMP t1){



	//two different periods
		if(first_time==0)
	    {
		first_time=t1;
			     }

			if(gl_todays(t1)-gl_todays(first_time)==2)
			{
				first_period=1;
				static FINDLIST *xt1=NULL;
				 xt1=gl_find_objects(FL_NEW,FT_CLASS,SAME,"controller",FT_END);
				 OBJECT *firstt1= gl_find_next(xt1,NULL);
				 OBJECT *it1;
				 for(it1=firstt1;it1!=NULL;it1=it1->next)
				 {
				
					 if(gl_object_isa(it1,"controller"))
				     {
						 gl_set_value_by_name(it1,"second_period_for_market","1")  ;
						 
				     }
			     }

	
			}
			
	if(slider_setting < -0.001)
		slider_setting = 0.0;
	if(slider_setting_heat < -0.001)
		slider_setting_heat = 0.0;
	if(slider_setting_cool < -0.001)
		slider_setting_cool = 0.0;
	if(slider_setting > 1.0)
		slider_setting = 1.0;
	if(slider_setting_heat > 1.0)
		slider_setting_heat = 1.0;
	if(slider_setting_cool > 1.0)
		slider_setting_cool = 1.0;

	if(control_mode == CN_RAMP && setpoint0 == -1)
		setpoint0 = *pSetpoint; // auto tha einai to orio gia to humidity to setpoint pou tha vazei o xristis
	


	if(control_mode == CN_RAMP){
		if (slider_setting == -0.001){
			min = setpoint0 + range_low;
			max = setpoint0 + range_high;
		} else if(slider_setting > 0){
			min = setpoint0 + range_low * slider_setting;
			max = setpoint0 + range_high * slider_setting;
			if(range_low != 0)
				ramp_low = 2 + (1 - slider_setting);
			else
				ramp_low = 0;
			if(range_high != 0)
				ramp_high = 2 + (1 - slider_setting);
			else
				ramp_high = 0;
		} else {
			min = setpoint0;
			max = setpoint0;
		}
	}
	if((thermostat_mode != TM_INVALID && thermostat_mode != TM_OFF) || t1 >= time_off)
		last_mode = thermostat_mode;
	else if(thermostat_mode == TM_INVALID)
		last_mode = TM_OFF;// this initializes last mode to off

	if(thermostat_mode != TM_INVALID)
		previous_mode = thermostat_mode;
	else
		previous_mode = TM_OFF;

	return TS_NEVER;
}
예제 #17
0
EXPORT int check()
{
	/* check each link to make sure it has a node at either end */
	FINDLIST *list = gl_find_objects(FL_NEW,FT_MODULE,SAME,"powerflow",NULL);
	OBJECT *obj=NULL;
	int *nodemap,	/* nodemap marks where nodes are */
		*linkmap,	/* linkmap counts the number of links to/from a given node */
		*tomap;		/* counts the number of references to any given node */
	int errcount = 0;
	int objct = 0;
	int queuef = 0, queueb = 0, queuect = 0;
	int islandct = 0;
	int i, j;
	GLOBALVAR *gvroot = NULL;
	PFLIST anchor, *tlist = NULL;
	link **linklist = NULL,
		 **linkqueue = NULL;

	objct = gl_get_object_count();
	anchor.ptr = NULL;
	anchor.next = NULL;

	nodemap = (int *)malloc((size_t)(objct*sizeof(int)));
	linkmap = (int *)malloc((size_t)(objct*sizeof(int)));
	tomap = (int *)malloc((size_t)(objct*sizeof(int)));
	linkqueue = (link **)malloc((size_t)(objct*sizeof(link *)));
	linklist = (link **)malloc((size_t)(objct*sizeof(link *)));
	memset(nodemap, 0, objct*sizeof(int));
	memset(linkmap, 0, objct*sizeof(int));
	memset(tomap, 0, objct*sizeof(int));
	memset(linkqueue, 0, objct*sizeof(link *));
	memset(linklist, 0, objct*sizeof(link *));
	/* per-object checks */

	/* check from/to info on links */
	while (obj=gl_find_next(list,obj))
	{
		if (gl_object_isa(obj,"node"))
		{
			/* add to node map */
			nodemap[obj->id]+=1;
			/* if no parent, then add to anchor list */
			if(obj->parent == NULL){
				tlist = (PFLIST *)malloc(sizeof(PFLIST));
				tlist->ptr = obj;
				tlist->next = anchor.next;
				anchor.next = tlist;
				tlist = NULL;
			}
		}
		else if (gl_object_isa(obj,"link"))
		{
			link *pLink = OBJECTDATA(obj,link);
			OBJECT *from = pLink->from;
			OBJECT *to = pLink->to;
			node *tNode = OBJECTDATA(to, node);
			node *fNode = OBJECTDATA(from, node);
			/* count 'to' reference */
			tomap[to->id]++;
			/* check link connections */
			if (from==NULL){
				gl_error("link %s (%s:%d) from object is not specified", pLink->get_name(), pLink->oclass->name, pLink->get_id());
				++errcount;
			}
			else if (!gl_object_isa(from,"node")){
				gl_error("link %s (%s:%d) from object is not a node", pLink->get_name(), pLink->oclass->name, pLink->get_id());
				++errcount;
			} else { /* is a "from" and it isa(node) */
				linkmap[from->id]++; /* mark that this node has a link from it */
			}
			if (to==NULL){
				gl_error("link %s (%s:%d) to object is not specified", pLink->get_name(), pLink->oclass->name, pLink->get_id());
				++errcount;
			}
			else if (!gl_object_isa(to,"node")){
				gl_error("link %s (%s:%d) to object is not a node", pLink->get_name(), pLink->oclass->name, pLink->get_id());
				++errcount;
			} else { /* is a "to" and it isa(node) */
				linkmap[to->id]++; /* mark that this node has links to it */
			}
			/* add link to heap? */
			if((from != NULL) && (to != NULL) && (linkmap[from->id] > 0) && (linkmap[to->id] > 0)){
				linklist[queuect] = pLink;
				queuect++;
			}
			//	check phases
			/* this isn't cooperating with me.  -MH */
/*			if(tNode->get_phases(PHASE_A) == fNode->get_phases(PHASE_A)){
				gl_error("link:%i: to, from nodes have mismatched A phase (%i vs %i)", obj->id, tNode->get_phases(PHASE_A), fNode->get_phases(PHASE_A));
				++errcount;
			}
			if(tNode->get_phases(PHASE_B) == fNode->get_phases(PHASE_B)){
				gl_error("link:%i: to, from nodes have mismatched B phase (%i vs %i)", obj->id, tNode->get_phases(PHASE_B), fNode->get_phases(PHASE_B));
				++errcount;
			}
			if(tNode->get_phases(PHASE_C) == fNode->get_phases(PHASE_C)){
				gl_error("link:%i: to, from nodes have mismatched C phase (%i vs %i)", obj->id, tNode->get_phases(PHASE_C), fNode->get_phases(PHASE_C));
				++errcount;
			}
			if(tNode->get_phases(PHASE_D) == fNode->get_phases(PHASE_D)){
				gl_error("link:%i: to, from nodes have mismatched D phase (%i vs %i)", obj->id, tNode->get_phases(PHASE_D), fNode->get_phases(PHASE_D));
				++errcount;
			}
			if(tNode->get_phases(PHASE_N) == fNode->get_phases(PHASE_N)){
				gl_error("link:%i: to, from nodes have mismatched N phase (%i vs %i)", obj->id, tNode->get_phases(PHASE_N), fNode->get_phases(PHASE_N));
				++errcount;
			}*/
		}
	}

	for(i = 0; i < objct; ++i){ /* locate unlinked nodes */
		if(nodemap[i] != 0){
			if(linkmap[i] * nodemap[i] > 0){ /* there is a node at [i] and links to it*/
				;
			} else if(linkmap[i] == 1){ /* either a feeder or an endpoint */
				;
			} else { /* unattached node */
				gl_error("node:%i: node with no links to or from it", i);
				nodemap[i] *= -1; /* mark as unlinked */
				++errcount;
			}
		}
	}
	for(i = 0; i < objct; ++i){ /* mark by islands*/
		if(nodemap[i] > 0){ /* has linked node */
			linkmap[i] = i; /* island until proven otherwise */
		} else {
			linkmap[i] = -1; /* just making sure... */
		}
	}

	queueb = 0;
	for(i = 0; i < queuect; ++i){
		if(linklist[i] != NULL){ /* consume the next item */
			linkqueue[queueb] = linklist[i];
			linklist[i] = NULL;
			queueb++;
		}
		while(queuef < queueb){
			/* expand this island */
			linkmap[linkqueue[queuef]->to->id] = linkmap[linkqueue[queuef]->from->id];
			/* capture the adjacent nodes */
			for(j = 0; j < queuect; ++j){
				if(linklist[j] != NULL){
					if(linklist[j]->from->id == linkqueue[queuef]->to->id){
						linkqueue[queueb] = linklist[j];
						linklist[j] = NULL;
						++queueb;
					}
				}
			}
			++queuef;
		}
		/* we've consumed one island, grab another */
	}
	for(i = 0; i < objct; ++i){
		if(nodemap[i] != 0){
			gl_testmsg("node:%i on island %i", i, linkmap[i]);
			if(linkmap[i] == i){
				++islandct;
			}
		}
		if(tomap[i] > 1){
			FINDLIST *cow = gl_find_objects(FL_NEW,FT_ID,SAME,i,NULL);
			OBJECT *moo = gl_find_next(cow, NULL);
			char grass[64];
			gl_output("object #%i, \'%s\', has more than one link feeding to it (this will diverge)", i, gl_name(moo, grass, 64));
		}
	}
	gl_output("Found %i islands", islandct);
	tlist = anchor.next;
	while(tlist != NULL){
		PFLIST *tptr = tlist;
		tlist = tptr->next;
		free(tptr);
	}

	/*	An extra something to check link directionality,
	 *	if the root node has been defined on the command line.
	 *	-d3p988 */
	gvroot = gl_global_find("powerflow::rootnode");
	if(gvroot != NULL){
		PFLIST *front=NULL, *back=NULL, *del=NULL; /* node queue */
		OBJECT *_node = gl_get_object((char *)gvroot->prop->addr);
		OBJECT *_link = NULL;
		int *rankmap = (int *)malloc((size_t)(objct*sizeof(int)));
		int bct = 0;
		if(_node == NULL){
			gl_error("powerflow check(): Unable to do directionality check, root node name not found.");
		} else {
			gl_testmsg("Powerflow Check ~ Backward Links:");
		}
		for(int i = 0; i < objct; ++i){
			rankmap[i] = objct;
		}
		rankmap[_node->id] = 0;
		front = (PFLIST *)malloc(sizeof(PFLIST));
		front->next = NULL;
		front->ptr = _node;
		back = front;
		while(front != NULL){
			// find all links from the node
			for(OBJECT *now=gl_find_next(list, NULL); now != NULL; now = gl_find_next(list, now)){
				link *l;
				if(!gl_object_isa(now, "link"))
					continue;
				l = OBJECTDATA(now, link);
				if((l->from != front->ptr) && (l->to != front->ptr)){
					continue;
				} else if(rankmap[l->from->id]<objct && rankmap[l->to->id]<objct){
					continue;
				} else if(rankmap[l->from->id] < rankmap[l->to->id]){
					/* mark */
					rankmap[l->to->id] = rankmap[l->from->id]+1;
				} else if(rankmap[l->from->id] > rankmap[l->to->id]){
					/* swap & mark */
					OBJECT *t = l->from;
					gl_testmsg("reversed link: %s goes from %s to %s", now->name, l->from->name, l->to->name);
					l->from = l->to;
					l->to = t;
					rankmap[l->to->id] = rankmap[l->from->id]+1;;
				}
				// enqueue the "to" node
				back->next = (PFLIST *)malloc(sizeof(PFLIST));
				back->next->next = NULL;
				//back->next->ptr = l->to;
				back = back->next;
				back->ptr = l->to;
			}
			del = front;
			front = front->next;
			free(del);
		}
	}

	free(nodemap);
	free(linkmap);
	free(linklist);
	free(linkqueue);
	return 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);
}
예제 #19
0
//Solar radiation calcuation based on solpos and Perez tilt models
EXPORT int64 calc_solar_solpos_shading_rad(OBJECT *obj, double tilt, double orientation, double shading_value, double *value)
{
	static SolarAngles sa; // just for the functions
	double ghr, dhr, dnr;
	double cos_incident;
	double temp_value;
	DATETIME dt;
	TIMESTAMP offsetclock;

	climate *cli;
	if(obj == 0 || value == 0){
		return 0;
	}
	cli = OBJECTDATA(obj, climate);
	if(gl_object_isa(obj, "climate", "climate") == 0){
		return 0;
	}
	ghr = cli->solar_global;
	dhr = cli->solar_diffuse;
	dnr = cli->solar_direct;

	if (cli->reader_type==cli->RT_TMY2)
	{
		//Adjust time by half an hour - adjusts per TMY "reading" intervals - what they really represent
		offsetclock = obj->clock + 1800;
	}
	else	//Just pass it in
	{
		offsetclock = obj->clock;
	}
	
	gl_localtime(offsetclock, &dt);

	//Convert temperature back to centrigrade - since we seem to like imperial units
	temp_value = ((cli->temperature - 32.0)*5.0/9.0);

	//Initialize solpos algorithm
	sa.S_init(&sa.solpos_vals);

	//Assign in values
	sa.solpos_vals.longitude = obj->longitude;
	sa.solpos_vals.latitude = RAD(obj->latitude);
	if (dt.is_dst == 1)
	{
		sa.solpos_vals.timezone = cli->tz_offset_val-1.0;
	}
	else
	{
		sa.solpos_vals.timezone = cli->tz_offset_val;
	}
	sa.solpos_vals.year = dt.year;
	sa.solpos_vals.daynum = (dt.yearday+1);
	sa.solpos_vals.hour = dt.hour;
	sa.solpos_vals.minute = dt.minute;
	sa.solpos_vals.second = dt.second;
	sa.solpos_vals.temp = temp_value;
	sa.solpos_vals.press = cli->pressure;

	// Solar constant associated with extraterrestrial DNI, 1367 W/sq m - pull from TMY for now
	//sa.solpos_vals.solcon = 126.998456;	//Use constant value for direct normal extraterrestrial irradiance - doesn't seem right to me
	sa.solpos_vals.solcon = cli->direct_normal_extra;	//Use weather-read version (TMY)

	sa.solpos_vals.aspect = orientation;
	sa.solpos_vals.tilt = tilt;
	sa.solpos_vals.diff_horz = dhr;
	sa.solpos_vals.dir_norm = dnr;

	//Calculate different solar position values
	sa.S_solpos(&sa.solpos_vals);

	//Pull off new cosine of incidence
	if (sa.solpos_vals.cosinc >= 0.0)
		cos_incident = sa.solpos_vals.cosinc;
	else
		cos_incident = 0.0;

	//Apply the adjustment
	*value = (shading_value*dnr*cos_incident) + dhr*sa.solpos_vals.perez_horz + ghr*((1 - cos(tilt))*cli->ground_reflectivity/2.0);

	return 1;
}
예제 #20
0
/** initialization process
 **/
int controller::init(OBJECT *parent){
	OBJECT *hdr = OBJECTHDR(this);
	char tname[32];
	char *namestr = (hdr->name ? hdr->name : tname);
//	double high, low;

	sprintf(tname, "controller:%i", hdr->id);

	cheat();

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

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

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

	if(dPeriod == 0.0){
		period = market->period;
	} else {
		period = (TIMESTAMP)floor(dPeriod + 0.5);
	}

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

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

	if(heating_setpoint[0] == 0 && control_mode == CN_DOUBLE_RAMP){
		GL_THROW("controller: %i, heating_setpoint property not specified", hdr->id);;
	}
	if(heating_demand[0] == 0 && control_mode == CN_DOUBLE_RAMP){
		GL_THROW("controller: %i, heating_demand property not specified", hdr->id);
	}

	if(cooling_setpoint[0] == 0 && control_mode == CN_DOUBLE_RAMP){
		GL_THROW("controller: %i, cooling_setpoint property not specified", hdr->id);;
	}
	if(cooling_demand[0] == 0 && control_mode == CN_DOUBLE_RAMP){
		GL_THROW("controller: %i, cooling_demand property not specified", hdr->id);
	}

	if(deadband[0] == 0 && control_mode == CN_DOUBLE_RAMP){
		GL_THROW("controller: %i, deadband property not specified", hdr->id);
	}

	fetch(&pMonitor, target, parent);
	if(control_mode == CN_RAMP){
		fetch(&pSetpoint, setpoint, parent);
		fetch(&pDemand, demand, parent);
		fetch(&pTotal, total, parent);
		fetch(&pLoad, load, parent);
	} else if(control_mode == CN_DOUBLE_RAMP){
		sprintf(aux_state, "is_AUX_on");
		sprintf(heat_state, "is_HEAT_on");
		sprintf(cool_state, "is_COOL_on");
		fetch(&pHeatingSetpoint, heating_setpoint, parent);
		fetch(&pHeatingDemand, heating_demand, parent);
		fetch(&pHeatingTotal, total, parent);
		fetch(&pHeatingLoad, total, parent);
		fetch(&pCoolingSetpoint, cooling_setpoint, parent);
		fetch(&pCoolingDemand, cooling_demand, parent);
		fetch(&pCoolingTotal, total, parent);
		fetch(&pCoolingLoad, load, parent);
		fetch(&pDeadband, deadband, parent);
		fetch(&pAuxState, aux_state, parent);
		fetch(&pHeatState, heat_state, parent);
		fetch(&pCoolState, cool_state, parent);
	}
	fetch(&pAvg, avg_target, pMarket);
	fetch(&pStd, std_target, pMarket);


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

	if(heating_setpoint0==0)
		heating_setpoint0 = -1;

	if(cooling_setpoint0==0)
		cooling_setpoint0 = -1;

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

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

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

	if(cooling_state[0] != 0){
		// grab state pointer
		pCoolingState = gl_get_enum_by_name(parent, cooling_state);
		if(pCoolingState == 0){
			gl_error("cooling_state property name \'%s\' is not published by parent class", cooling_state);
			return 0;
		}
	}
	// get override, if set
	if(re_override[0] != 0){
		pOverride = gl_get_enum_by_name(parent, re_override);
	}
	if((pOverride == 0) && (use_override == OU_ON)){
		gl_error("use_override is ON but no valid override property name is given");
		return 0;
	}

	if(control_mode == CN_RAMP){
		if(slider_setting < 0.0){
			gl_warning("slider_setting is negative, reseting to 0.0");
			slider_setting = 0.0;
		}
		if(slider_setting > 1.0){
			gl_warning("slider_setting is greater than 1.0, reseting to 1.0");
			slider_setting = 1.0;
		}
	}
	if(control_mode == CN_DOUBLE_RAMP){
		if(slider_setting_heat < 0.0){
			gl_warning("slider_setting_heat is negative, reseting to 0.0");
			slider_setting_heat = 0.0;
		}
		if(slider_setting_cool < 0.0){
			gl_warning("slider_setting_cool is negative, reseting to 0.0");
			slider_setting_cool = 0.0;
		}
		if(slider_setting_heat > 1.0){
			gl_warning("slider_setting_heat is greater than 1.0, reseting to 1.0");
			slider_setting_heat = 1.0;
		}
		if(slider_setting_cool > 1.0){
			gl_warning("slider_setting_cool is greater than 1.0, reseting to 1.0");
			slider_setting_cool = 1.0;
		}
		// get override, if set
	}
	last_p = market->init_price;
	return 1;
}
예제 #21
0
int thermal_storage::init(OBJECT *parent)
{
	if(parent != NULL){
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("thermal_storage::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
	}
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;
	double *design_cooling_capacity;

	//Make sure the parent is a house
	if (!(gl_object_isa(parent,"house","residential")))
	{
		GL_THROW("thermal_storage:%s must be parented to a house!",hdr->name);
		/*  TROUBLESHOOT
		The thermal_storage model is only valid for house objects.  Please parent it appropriately.
		*/
	}

	//Pull a house link, we'll use it for addresses
	house_e *house_lnk = OBJECTDATA(parent,house_e);

	//Link the variables to the parent values (house values)
	design_cooling_capacity = &house_lnk->design_cooling_capacity;
	outside_temperature = &house_lnk->outside_temperature;
	thermal_storage_available = &house_lnk->thermal_storage_present;
	thermal_storage_active = &house_lnk->thermal_storage_inuse;

	//Check the cooling capacity
	if (*design_cooling_capacity == NULL)
	{
		gl_warning("\'design_cooling_capacity\' not specified in parent ~ default to 5 ton or 60,000 Btu/hr");
		/* TROUBLESHOOT
			The thermal_storage did not reference a parent object that publishes design_cooling_capacity, so 5 ton was assumed.
			Confirm or change the parent reference and try again.
		*/
		discharge_rate = 5 * 12000; //Btu/hr, is set to 5 ton when not defined
		water_capacity = 1.7413;	//m^3, is set to the same as a 5 ton unit
	} else {
		discharge_rate = *design_cooling_capacity;
		water_capacity = 1.7413 * (discharge_rate / (5 * 12000));
	}

	surface_area = 6 * pow(water_capacity, 0.6667); //suface area of a cube calculated from volume

	if (total_capacity == 0)			total_capacity = (30 / 5) * discharge_rate; //Btu

	if (state_of_charge < 0 && stored_capacity < 0) //Btu
	{
		stored_capacity = total_capacity;
		state_of_charge = 100;
	} else if (state_of_charge < 0 && stored_capacity >= 0)
	{
		state_of_charge = stored_capacity / total_capacity;
	} else if (state_of_charge >= 0 && stored_capacity < 0)
	{
		stored_capacity = (state_of_charge / 100) * total_capacity;
	} else if (state_of_charge >= 0 && stored_capacity >= 0)
	{
		stored_capacity = (state_of_charge / 100) * total_capacity;
		gl_warning("stored_capacity and SOC are both defined, SOC being used for initial energy state");
		/*  TROUBLESHOOT
		During the initialization of the system, a value was specified for both the stored_capacity and SOC (state of charge).
		The thermal energy storage object gives precedence to the SOC variable, so the initial stored_capacity will be the SOC
		percentage of the total_capacity.
		*/
	}

	if (recharge_power == 0)			recharge_power = (3.360 * discharge_rate) / (5 * 12000); //kW
	if (discharge_power == 0)			discharge_power = (0.300 * discharge_rate) / (5 * 12000); //kW
	if (recharge_power_factor == 0)		recharge_power_factor = 0.97; //same as used for HVAC compressor in house_e
	if (discharge_power_factor == 0)	discharge_power_factor = 1; //assume ideal pump
	if (k < 0)							k = 0; //assume no thermal conductivity
	k = k * 0.00052667;				//convert k from W/m/K to BTU/sec/m/degF

	//Determine how to read the scheduling information - charging
	if (recharge_schedule_type==INTERNAL)
	{
		//See if someone else has already created such a schedule
		recharge_schedule_vals = gl_schedule_find(thermal_default_schedule_list[1].schedule_name);

		//If not found, create
		if (recharge_schedule_vals == NULL)
		{
			//Populate schedules - charging
			recharge_schedule_vals = gl_schedule_create(thermal_default_schedule_list[1].schedule_name,thermal_default_schedule_list[1].schedule_definition);

			//Make sure it worked
			if (recharge_schedule_vals==NULL)
			{
				GL_THROW("Failure to create default charging schedule");
				/*  TROUBLESHOOT
				While attempting to create the default charging schedule in the thermal_storage object, an error occurred.  Please try again.
				If the error persists, please submit your code and a bug report via the track website.
				*/
			}
		}

		gl_verbose("thermal_storage charging defaulting to internal schedule");
		/*  TROUBLESHOOT
		recharge_schedule_type was not set to EXTERNAL, so the internal schedule definition will be used
		for the recharging schedule.
		*/

		//Assign to the schedule value
		recharge_time_ptr = &recharge_schedule_vals->value;
	}
	else
	{
		//Assign the to published property
		recharge_time_ptr = &recharge_time;
	}

	//Determine how to read the scheduling information - discharging
	if (discharge_schedule_type==INTERNAL)
	{
		//See if someone else has already created such a schedule
		discharge_schedule_vals = gl_schedule_find(thermal_default_schedule_list[0].schedule_name);

		//If not found, create
		if (discharge_schedule_vals == NULL)
		{
			//Populate schedules - discharging
			discharge_schedule_vals = gl_schedule_create(thermal_default_schedule_list[0].schedule_name,thermal_default_schedule_list[0].schedule_definition);

			//Make sure it worked
			if (discharge_schedule_vals==NULL)
			{
				GL_THROW("Failure to create default discharging schedule");
				/*  TROUBLESHOOT
				While attempting to create the default discharging schedule in the thermal_storage object, an error occurred.  Please try again.
				If the error persists, please submit your code and a bug report via the track website.
				*/
			}
		}

		gl_verbose("thermal_storage discharging defaulting to internal schedule");
		/*  TROUBLESHOOT
		discharge_schedule_type was not set to EXTERNAL, so the internal schedule definition will be used
		for the discharging availability schedule.
		*/

		//Assign to the schedule value
		discharge_time_ptr = &discharge_schedule_vals->value;
	}
	else
	{
		//Assigned to the published property
		discharge_time_ptr = &discharge_time;
	}

	// waiting this long to initialize the parent class is normal
	return residential_enduse::init(parent);
}
예제 #22
0
int windturb_dg::init(OBJECT *parent)
{
	OBJECT *obj = OBJECTHDR(this);

	double ZB, SB, EB;
	complex tst, tst2, tst3, tst4;

	switch (Turbine_Model)	{
		case GENERIC_IND_LARGE:
		case GENERIC_SYNCH_LARGE:	//Creates generic 1.5 MW wind turbine.
			blade_diam = 82.5;
			turbine_height = 90;
			q = 3;						//number of gearbox stages
			Rated_VA = 1635000;
			Max_P = 1500000;
			Max_Q = 650000;
			Rated_V = 600;
			pf = 0.95;
			CP_Data = GENERAL_LARGE;
			cut_in_ws = 4;			//lowest wind speed 
			cut_out_ws = 25;		//highest wind speed 
			Cp_max = 0.302;			//rotor specifications for power curve
			ws_maxcp = 7;			
			Cp_rated = Cp_max-.05;	
			ws_rated = 12.5;		
			if (Turbine_Model == GENERIC_IND_LARGE) {
				Gen_type = INDUCTION;
				Rst = 0.12;					
				Xst = 0.17;					
				Rr = 0.12;				
				Xr = 0.15;			
				Rc = 999999;		
				Xm = 9.0;	
			}
			else if (Turbine_Model == GENERIC_SYNCH_LARGE) {
				Gen_type = SYNCHRONOUS;
				Rs = 0.05;
				Xs = 0.200;
				Rg = 0.000;
				Xg = 0.000;
			}
			break;
		case GENERIC_IND_MID:
		case GENERIC_SYNCH_MID:	//Creates generic 100kW wind turbine, northwind 100
			blade_diam = 23.2;   //in m
			turbine_height = 30;   //in m
			q = 0;						//number of gearbox stages, no gear box 
			Rated_VA = 156604;
			Max_P = 150000;
			Max_Q = 45000;
			Rated_V = 480;  
			pf = 0.9;     ///lag and lead of 0.9
			CP_Data = GENERAL_MID;
			cut_in_ws = 3.5;			//lowest wind speed in m/s
			cut_out_ws = 25;		   //highest wind speed in m/s
			Cp_max = 0.302;			  //rotor specifications for power curve
			ws_maxcp = 7;			
			Cp_rated = Cp_max-.05;	
			ws_rated = 14.5;		//	in m/s
			if (Turbine_Model == GENERIC_IND_MID) {     // need to check the machine parameters
				Gen_type = INDUCTION;
				Rst = 0.12;					
				Xst = 0.17;					
				Rr = 0.12;				
				Xr = 0.15;			
				Rc = 999999;		
				Xm = 9.0;	
			}
			else if (Turbine_Model == GENERIC_SYNCH_MID) {
				Gen_type = SYNCHRONOUS;
				Rs = 0.05;
				Xs = 0.200;
				Rg = 0.000;
				Xg = 0.000;
			}
			break;
		case GENERIC_IND_SMALL:					
		case GENERIC_SYNCH_SMALL:	//Creates generic 5 kW wind turbine, Fortis Montana 5 kW wind turbine
			blade_diam = 5;      // in m
			turbine_height = 16;   //in m
			q = 0;						//number of gearbox stages, no gear box
			Rated_VA = 6315;               // calculate from P & Q
			Max_P = 5800; 
			Max_Q = 2500;
			Rated_V = 600;
			pf = 0.95;
			CP_Data = GENERAL_SMALL;
			cut_in_ws = 2.5;			//lowest wind speed 
			cut_out_ws = 25;		//highest wind speed 
			Cp_max = 0.302;			//rotor specifications for power curve
			ws_maxcp = 7;			//	|
			Cp_rated = Cp_max-.05;	//	|
			ws_rated = 17;		//	|
			if (Turbine_Model == GENERIC_IND_SMALL) {
				Gen_type = INDUCTION;
				Rst = 0.12;					
				Xst = 0.17;					
				Rr = 0.12;				
				Xr = 0.15;			
				Rc = 999999;		
				Xm = 9.0;	
			}
			else if (Turbine_Model == GENERIC_SYNCH_SMALL) {
				Gen_type = SYNCHRONOUS;
				Rs = 0.05;
				Xs = 0.200;
				Rg = 0.000;
				Xg = 0.000;
			}
			break;
		case VESTAS_V82:	//Include manufacturer's data - cases can be added to call other wind turbines
			turbine_height = 78;
			blade_diam = 82;
			Rated_VA = 1808000;
			Rated_V = 600;
			Max_P = 1650000;
			Max_Q = 740000;
			pf = 0.91;		//Can range between 0.65-1.00 depending on controllers and Pout.
			CP_Data = MANUF_TABLE;		
			cut_in_ws = 3.5;
			cut_out_ws = 20;
			q = 2;
			Gen_type = SYNCHRONOUS;	//V82 actually uses a DFIG, but will use synch representation for now
			Rs = 0.025;				//Estimated values for synch representation.
			Xs = 0.200;
			Rg = 0.000;
			Xg = 0.000;
			break;
		case GE_25MW:
			turbine_height = 100;
			blade_diam = 100;
			Rated_VA = 2727000;
			Rated_V = 690;
			Max_P = 2500000;
			Max_Q = 1090000;
			pf = 0.95;		//ranges between -0.9 -> 0.9;
			q = 3;
			CP_Data = GENERAL_LARGE;
			cut_in_ws = 3.5;
			cut_out_ws = 25;
			Cp_max = 0.28;
			Cp_rated = 0.275;
			ws_maxcp = 8.2;
			ws_rated = 12.5;
			Gen_type = SYNCHRONOUS;
			Rs = 0.035;
			Xs = 0.200;
			Rg = 0.000;
			Xg = 0.000;
			break;
		case BERGEY_10kW:
			turbine_height = 24;
			blade_diam = 7;
			Rated_VA = 10000;
			Rated_V = 360;
			Max_P = 15000;
			Max_Q = 4000;
			pf = 0.95;		//ranges between -0.9 -> 0.9;
			q = 0;
			CP_Data = GENERAL_SMALL;
			cut_in_ws = 2;
			cut_out_ws = 20;
			Cp_max = 0.28;
			Cp_rated = 0.275;
			ws_maxcp = 8.2;
			ws_rated = 12.5;
			Gen_type = SYNCHRONOUS;
			Rs = 0.05;
			Xs = 0.200;
			Rg = 0.000;
			Xg = 0.000;
			break;
		case USER_DEFINED:

			CP_Data = USER_SPECIFY;	

			Gen_type = USER_TYPE;
			Rs = 0.2;
			Xs = 0.2;
			Rg = 0.1;
			Xg = 0;

			if (turbine_height <=0)
				GL_THROW ("turbine height cannot have a negative or zero value.");
			/*  TROUBLESHOOT
			Turbine height must be specified as a value greater than or equal to zero.
			*/
			if (blade_diam <=0)
				GL_THROW ("blade diameter cannot have a negative or zero value.");
			/*  TROUBLESHOOT
			Blade diameter must be specified as a value greater than or equal to zero.
			*/
			if (cut_in_ws <=0)
				GL_THROW ("cut in wind speed cannot have a negative or zero value.");
			/*  TROUBLESHOOT
			Cut in wind speed must be specified as a value greater than or equal to zero.
			*/
			if (cut_out_ws <=0)
				GL_THROW ("cut out wind speed cannot have a negative or zero value.");
			/*  TROUBLESHOOT
			Cut out wind speed must be specified as a value greater than or equal to zero.
			*/
			if (ws_rated <=0)
				GL_THROW ("rated wind speed cannot have a negative or zero value.");
			/*  TROUBLESHOOT
			Rated wind speed must be specified as a value greater than or equal to zero.
			*/
			if (ws_maxcp <=0)
				GL_THROW ("max cp cannot have a negative or zero value.");
			/*  TROUBLESHOOT
			Maximum coefficient of performance must be specified as a value greater than or equal to zero.
			*/
			break;
		default:
			GL_THROW("Unknown turbine model was specified");
			/*  TROUBLESHOOT
			An unknown wind turbine model was selected.  Please select a Turbine_Model from the available list.
			*/
	}

	// construct circuit variable map to meter -- copied from 'House' module
	struct {
		complex **var;
		char *varname;
	} map[] = {
		// local object name,	meter object name
		{&pCircuit_V,			"voltage_A"}, // assumes 2 and 3 follow immediately in memory
		{&pLine_I,				"current_A"}, // assumes 2 and 3(N) follow immediately in memory
		/// @todo use triplex property mapping instead of assuming memory order for meter variables (residential, low priority) (ticket #139)
	};

	static complex default_line123_voltage[3], default_line1_current[3];
	int i;

	//Map phases
	set *phaseInfo;
	PROPERTY *tempProp;
	tempProp = gl_get_property(parent,"phases");

	if ((tempProp==NULL || tempProp->ptype!=PT_set))
	{
		GL_THROW("Unable to map phases property - ensure the parent is a powerflow:meter");
		/*  TROUBLESHOOT
		While attempting to map the phases property from the parent object, an error was encountered.
		Please check and make sure your parent object is a meter inside the powerflow module and try
		again.  If the error persists, please submit your code and a bug report via the Trac website.
		*/
	}
	else
		phaseInfo = (set*)GETADDR(parent,tempProp);

	int temp_phases=0;

	// Currently only supports 3-phase connection, so check number of phases of parent
	if ((*phaseInfo & PHASE_A) == PHASE_A)
		temp_phases += 1;
	if ((*phaseInfo & PHASE_B) == PHASE_B)
		temp_phases += 1;
	if ((*phaseInfo & PHASE_C) == PHASE_C)
		temp_phases += 1;

	if (temp_phases < 3)
		GL_THROW("The wind turbine model currently only supports a 3-phase connection, please check meter connection");
	/*  TROUBLESHOOT
	Currently the wind turbine model only supports 3-phase connnections. Please attach to 3-phase meter.
	*/



	// find parent meter, if not defined, use a default meter (using static variable 'default_meter')
	if (parent!=NULL)
	{
		if((parent->flags & OF_INIT) != OF_INIT){
			char objname[256];
			gl_verbose("windturb_dg::init(): deferring initialization on %s", gl_name(parent, objname, 255));
			return 2; // defer
		}
		if (gl_object_isa(parent,"meter","powerflow"))	//Attach to meter
		{
			/*
			NR_mode = get_bool(parent,"NR_mode");

			//Check NR_mode, just to be consistent
			if (NR_mode == NULL)
			{
				GL_THROW("Wind turbine failed to map NR_mode property");
				*/
				/*  TROUBLESHOOT
				While attempting to map up the NR_mode property, an error
				was encountered.  Please try again.  If the error persists,
				please submit your code and a bug report via the trac website.
				*/
			/*
			}
		*/

			//Map the voltages
			double *parNominalVoltage;

			tempProp = gl_get_property(parent,"nominal_voltage");
			if ((tempProp==NULL || tempProp->ptype!=PT_double))
			{
				GL_THROW("Unable to map nominal_voltage property - ensure the parent is a powerflow:meter");
				/*  TROUBLESHOOT
				While attempting to map the nominal_voltage property from the parent object, an error was encountered.
				Please check and make sure your parent object is a meter inside the powerflow module and try
				again.  If the error persists, please submit your code and a bug report via the Trac website.
				*/
			}
			else
				parNominalVoltage = (double*)GETADDR(parent,tempProp);

			// check nominal voltage against rated voltage
			if ( fabs(1 - (*parNominalVoltage * sqrt(3.0) / Rated_V) ) > 0.1 )
				gl_warning("windturb_dg (id:%d, name:%s): Rated generator voltage (LL: %.1f) and nominal voltage (LL: %.1f) of meter parent are different by greater than 10 percent. Odd behavior may occur.",obj->id,obj->name,Rated_V,*parNominalVoltage * sqrt(3.0));
			/* TROUBLESHOOT
			Currently, the model allows you to attach the turbine to a voltage that is quite different than the rated terminal
			voltage of the generator.  However, this may cause odd behavior, as the solved powerflow voltage is used to calculate
			the generator induced voltages and conversion from mechanical power.  It is recommended that the nominal
			voltages of the parent meter be within ~10% of the rated voltage.
			*/

			// attach meter variables to each circuit
			for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
			{
				*(map[i].var) = get_complex(parent,map[i].varname);

				if (*(map[i].var) == NULL)
				{
					GL_THROW("Unable to map variable %s",map[i].varname);
					/*  TROUBLESHOOT
					The variable name was not found when mapping it
					*/
				}
			}
		}
		else if (gl_object_isa(parent,"triplex_meter","powerflow"))
		{
			GL_THROW("The wind turbine model does currently support direct connection to single phase or triplex meters. Connect through a rectifier-inverter combination.");
			/*  TROUBLESHOOT
			This model does not currently support connection to a triplex system.  Please connect to a 3-phase meter.
			*/

			//Map voltage
			pCircuit_V = get_complex(parent,"voltage_1");

			//Make sure it worked
			if (pCircuit_V == NULL)
				GL_THROW("Unable to map triplex_meter voltage");

			//Map current
			pLine_I = get_complex(parent,"current_1");

			//Make sure it worked
			if (pLine_I == NULL)
				GL_THROW("Unable to map triplex_meter current");

			//NR_mode = get_bool(parent,"NR_mode");
		}
		else if (gl_object_isa(parent,"rectifier","generators"))
		{

			//Map the voltages
			double *parNominalVoltage;

			tempProp = gl_get_property(parent,"V_Rated");
			if ((tempProp==NULL || tempProp->ptype!=PT_double))
			{
				GL_THROW("Unable to map V_Rated property - ensure the parent is a powerflow:meter");
				/*  TROUBLESHOOT
				While attempting to map the nominal_voltage property from the parent object, an error was encountered.
				Please check and make sure your parent object is a meter inside the powerflow module and try
				again.  If the error persists, please submit your code and a bug report via the Trac website.
				*/
			}
			else
				parNominalVoltage = (double*)GETADDR(parent,tempProp);

			// check nominal voltage against rated voltage
			if ( fabs(1 - (*parNominalVoltage / Rated_V) ) > 0.1 )
				gl_warning("windturb_dg (id:%d, name:%s): Rated generator voltage (LL: %.1f) and nominal voltage (LL: %.1f) of meter parent are different by greater than 10 percent. Odd behavior may occur.",obj->id,obj->name,Rated_V,*parNominalVoltage * sqrt(3.0));
			/* TROUBLESHOOT
			Currently, the model allows you to attach the turbine to a voltage that is quite different than the rated terminal
			voltage of the generator.  However, this may cause odd behavior, as the solved powerflow voltage is used to calculate
			the generator induced voltages and conversion from mechanical power.  It is recommended that the nominal
			voltages of the parent meter be within ~10% of the rated voltage.
			*/



			// attach meter variables to each circuit
			for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
			{
				if ((*(map[i].var) = get_complex(parent,map[i].varname))==NULL)
				{
					GL_THROW("%s (%s:%d) does not implement rectifier variable %s for %s (windturb_dg:%d)", 
						/*	TROUBLESHOOT
						The rectifier requires that the inverter contains certain published properties in order to properly connect. If you encounter this error, please report it to the developers, along with
						the version of GridLAB-D that raised this error.
						*/
						parent->name?parent->name:"unnamed object", parent->oclass->name, parent->id, map[i].varname, obj->name?obj->name:"unnamed", obj->id);
				}
			}

		}
		else
		{
			GL_THROW("windturb_dg (id:%d): Invalid parent object",obj->id);
			/* TROUBLESHOOT 
			The wind turbine object must be attached a 3-phase meter object.  Please check parent of object.
			*/
		}
	}
	else
	{
		gl_warning("windturb_dg:%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_line123_voltage[0];
		*(map[1].var) = &default_line1_current[0];

		// provide initial values for voltages
		default_line123_voltage[0] = complex(Rated_V/sqrt(3.0),0);
		default_line123_voltage[1] = complex(Rated_V/sqrt(3.0)*cos(2*PI/3),Rated_V/sqrt(3.0)*sin(2*PI/3));
		default_line123_voltage[2] = complex(Rated_V/sqrt(3.0)*cos(-2*PI/3),Rated_V/sqrt(3.0)*sin(-2*PI/3));

		NR_mode = &default_NR_mode;
	}

	if (Gen_status==OFFLINE)
	{
		gl_warning("init_windturb_dg (id:%d,name:%s): Generator is out of service!", obj->id,obj->name); 	
	}	

	if (Gen_type == SYNCHRONOUS || Gen_type == INDUCTION)
	{
		if (Gen_mode == CONSTANTE)
		{
			gl_warning("init_windturb_dg (id:%d,name:%s): Synchronous and induction generators in constant voltage mode has not been fully tested and my not work properly.", obj->id,obj->name);
		}
	}

	if (Rated_VA!=0.0)  
		SB = Rated_VA/3;
	if (Rated_V!=0.0)  
		EB = Rated_V/sqrt(3.0);
	if (SB!=0.0)  
		ZB = EB*EB/SB;
	else 
		GL_THROW("Generator power capacity not specified!");
	/* TROUBLESHOOT 
	Rated_VA of generator must be specified so that per unit values can be calculated
	*/

	if (Gen_type == INDUCTION)  
	{
		complex Zrotor(Rr,Xr);
		complex Zmag = complex(Rc*Xm*Xm/(Rc*Rc + Xm*Xm),Rc*Rc*Xm/(Rc*Rc + Xm*Xm));
		complex Zstator(Rst,Xst);

		//Induction machine two-port matrix.
		IndTPMat[0][0] = (Zmag + Zstator)/Zmag;
		IndTPMat[0][1] = Zrotor + Zstator + Zrotor*Zstator/Zmag;
		IndTPMat[1][0] = complex(1,0) / Zmag;
		IndTPMat[1][1] = (Zmag + Zrotor) / Zmag;
	}

	else if (Gen_type == SYNCHRONOUS)  
	{
		double Real_Rs = Rs * ZB; 
		double Real_Xs = Xs * ZB;
		double Real_Rg = Rg * ZB; 
		double Real_Xg = Xg * ZB;
		tst = complex(Real_Rg,Real_Xg);
		tst2 = complex(Real_Rs,Real_Xs);
		AMx[0][0] = tst2 + tst;			//Impedance matrix
		AMx[1][1] = tst2 + tst;
		AMx[2][2] = tst2 + tst;
		AMx[0][1] = AMx[0][2] = AMx[1][0] = AMx[1][2] = AMx[2][0] = AMx[2][1] = tst;
		tst3 = (complex(1,0) + complex(2,0)*tst/tst2)/(tst2 + complex(3,0)*tst);
		tst4 = (-tst/tst2)/(tst2 + tst);
		invAMx[0][0] = tst3;			//Admittance matrix (inverse of Impedance matrix)
		invAMx[1][1] = tst3;
		invAMx[2][2] = tst3;
		invAMx[0][1] = AMx[0][2] = AMx[1][0] = AMx[1][2] = AMx[2][0] = AMx[2][1] = tst4;
	}
	else
		GL_THROW("Unknown generator type specified");
	/* TROUBLESHOOT 
	Shouldn't have been able to specify an unknown generator type.  Please report this error to GridLAB-D support.
	*/

	init_climate();

	return 1;
}
int passive_controller::init(OBJECT *parent){
	
	OBJECT *hdr = OBJECTHDR(this);
	PROPERTY *enduseProperty;

	if(parent == NULL){
		gl_error("passive_controller has no parent and will be operating in 'dummy' mode");
	} else {
		if(output_state_propname[0] == 0 && output_setpoint_propname[0] == 0){
			GL_THROW("passive_controller has no output properties");
		}
		// expectation_addr
		if(expectation_object != 0){
			expectation_property = gl_get_property(expectation_object, expectation_propname);
			if(expectation_property == 0){
				GL_THROW("passive_controller cannot find its expectation property");
			}
			expectation_addr = (void *)((unsigned int64)expectation_object + sizeof(OBJECT) + (unsigned int64)expectation_property->addr);
		}

		if(observation_object != 0){
			// observation_addr
			observation_prop = gl_get_property(observation_object, observation_propname);
			if(observation_prop != 0){
				observation_addr = (void *)((unsigned int64)observation_object + sizeof(OBJECT) + (unsigned int64)observation_prop->addr);
			}
			if (pool_pump_model == false)
			{
				// observation_mean_addr
				observation_mean_prop = gl_get_property(observation_object, observation_mean_propname);
				if(observation_mean_prop != 0){
					observation_mean_addr = (void *)((unsigned int64)observation_object + sizeof(OBJECT) + (unsigned int64)observation_mean_prop->addr);
				}
				// observation_stdev_addr
				stdev_observation_property = gl_get_property(observation_object, observation_stdev_propname);
				if(stdev_observation_property != 0){
					observation_stdev_addr = (void *)((unsigned int64)observation_object + sizeof(OBJECT) + (unsigned int64)stdev_observation_property->addr);
				}
			}

		}
		// output_state
		if(output_state_propname[0] != 0){
			output_state_prop = gl_get_property(parent, output_state_propname);
			if(output_state_prop == NULL){
				GL_THROW("passive_controller parent \"%s\" does not contain property \"%s\"", 
					(parent->name ? parent->name : "anon"), output_state_propname.get_string());
			}
			output_state_addr = (void *)((unsigned int64)parent + sizeof(OBJECT) + (unsigned int64)output_state_prop->addr);
		}
		
		// output_setpoint
		if (control_mode != this->CM_PROBOFF && control_mode != this->CM_ELASTICITY_MODEL)
		{
			if(output_setpoint_propname[0] == 0 && output_setpoint_propname[0] == 0){
				GL_THROW("passive_controller has no output properties");
			}
			if(output_setpoint_propname[0] != 0){
				output_setpoint_property = gl_get_property(parent, output_setpoint_propname);
				if(output_setpoint_property == NULL){
					GL_THROW("passive_controller parent \"%s\" does not contain property \"%s\"", 
						(parent->name ? parent->name : "anon"), output_setpoint_propname.get_string());
				}
				output_setpoint_addr = (void *)((unsigned int64)parent + sizeof(OBJECT) + (unsigned int64)output_setpoint_property->addr);
			}
		}
	}

	if (pool_pump_model == false && control_mode != CM_ELASTICITY_MODEL)
		gl_set_dependent(hdr, expectation_object);
	gl_set_dependent(hdr, observation_object);

	if(observation_object == NULL){
		GL_THROW("passive_controller observation_object object is undefined, and can not function");
	}
	
	//
	// make sure that the observation_object and expectable are ranked above the controller
	//

	if(base_setpoint != 0.0){
		orig_setpoint = 1;
	}

	if (pool_pump_model == true)
	{
		if (control_mode != CM_DUTYCYCLE)
			GL_THROW("pool pump mode must be used with control mode set to DUTYCYCLE");
		if (firstTierHours == 0 || secondTierHours == 0)
			GL_THROW("Please set first and second tier hours in pool pump duty cycle mode");
		if (firstTierPrice == 0 || secondTierPrice == 0)
			GL_THROW("Please set first and second tier prices in pool pump duty cycle mode");
	}

	if(dPeriod == 0.0){
		dPeriod = 300.0;
		period = 300; // five minutes
	} else {
		period = (TIMESTAMP)floor(dPeriod + 0.5);
	}

	if (gl_object_isa(parent,"ZIPload","residential"))
	{
		zipLoadParent = true;
	}
	
	if(zipLoadParent == true && control_mode == CM_ELASTICITY_MODEL){
	
		ThirdTierArraySize = 0;
		SecondTierArraySize = 0;
		FirstTierArraySize = 0;

		elasticityPeriod = 24;

		if(subElasticityFirstSecond > 0)
			gl_warning("The peak to offpeak Substitution Elasticity is positive.  While this is allowed, it is typically the reverse of convention, as an increase in peak to offpeak price ratio generally produces a reduction in peak load to offpeak load. This is indicated by a negative peak to offpeak Substitution Elasticity value.");

		if(subElasticityFirstThird > 0)
			gl_warning("The critical peak to offpeak Substitution Elasticity is positive.  While this is allowed, it is typically the reverse of convention, as an increase in critical peak to offpeak price ratio generally produces a reduction in peak load to offpeak load. This is indicated by a negative critical peak to offpeak Substitution Elasticity value.");

		if(dailyElasticity > 0)
			gl_warning("The Daily Elasticity is positive.  While this is allowed, it is typically the reverse of convention, as an increase in daily price generally produces a reduction in daily load. This is indicated by a negative Daily Elasticity value.");

		if(critical_day >= 0.5){

			if (firstTierPrice == 0)
					GL_THROW("Please set first tier price in the Elasticity Model");

			if (oldFirstTierPrice == 0)
					GL_THROW("Please set old first tier price in the Elasticity Model");

				
			if (thirdTierHours == 0)
				GL_THROW("Please set third tier hours in the Elasticity Model");

			if (thirdTierPrice == 0)
				GL_THROW("Please set third tier price in the Elasticity Model");

			if (oldThirdTierPrice == 0){

				oldThirdTierPrice = oldFirstTierPrice;
				gl_warning("Old third tier price is missing. System will assume the old pricing scheme was a fixed pricing scheme and use the old first tier price");

			}

			if(check_two_tier_cpp != true){
				
				if (secondTierHours == 0)
					GL_THROW("Please set second tier hours in the Elasticity Model");

				if (secondTierPrice == 0)
					GL_THROW("Please set second tier price in the Elasticity Model");

				if (oldSecondTierPrice == 0){

					oldSecondTierPrice = oldFirstTierPrice;
					gl_warning("Old second tier price is missing. System will assume the old pricing scheme was a fixed pricing scheme and use the old first tier price");

				}				
				
				if(firstTierHours == 0){
					firstTierHours = elasticityPeriod - thirdTierHours - secondTierHours;
				}
				else{
					if((thirdTierHours+secondTierHours+firstTierHours) != elasticityPeriod)
					GL_THROW("Please set the tier hours correctly in the Elasticity Model");
				}

				SecondTierArraySize = (int)(((secondTierHours * 3600) / period));

				//Calculation of the price ratios and change in price ratios.
				//This will not change for the course of the simulation
				oldPriceRatioSecondFirst = oldSecondTierPrice/oldFirstTierPrice;
				newPriceRatioSecondFirst = secondTierPrice/firstTierPrice;

				if(linearizeElasticity == true)
				{
					peakPriceMultiplier = pow(newPriceRatioSecondFirst/oldPriceRatioSecondFirst,subElasticityFirstSecond);
				}
				else{

					peakPriceMultiplier = 1 + ((subElasticityFirstSecond)*(newPriceRatioSecondFirst-oldPriceRatioSecondFirst)/oldPriceRatioSecondFirst);
					priceDiffSecond = secondTierPrice - oldSecondTierPrice; 
				}

			}
			else{

				if(firstTierHours == 0){
					firstTierHours = elasticityPeriod - thirdTierHours;
				}
				else{
					if((thirdTierHours+firstTierHours) != elasticityPeriod)
					GL_THROW("Please set the tier hours correctly in the Elasticity Model");
				}					
			}

			ThirdTierArraySize = (int)(((thirdTierHours * 3600) / period));			

			//Calculation of the price ratios and change in price ratios.
			//This will not change for the course of the simulation
			oldPriceRatioThirdFirst = oldThirdTierPrice/oldFirstTierPrice;
			newPriceRatioThirdFirst = thirdTierPrice/firstTierPrice;

			if(linearizeElasticity == true)
			{
				criticalPriceMultiplier = pow(newPriceRatioThirdFirst/oldPriceRatioThirdFirst,subElasticityFirstThird);
			}
			else{

				criticalPriceMultiplier = 1 + ((subElasticityFirstThird)*(newPriceRatioThirdFirst-oldPriceRatioThirdFirst)/oldPriceRatioThirdFirst);
				priceDiffThird = thirdTierPrice - oldThirdTierPrice; 	
			}

		}
		else{			

			if (firstTierPrice == 0)
					GL_THROW("Please set first tier price in the Elasticity Model");

			if (oldFirstTierPrice == 0)
					GL_THROW("Please set old first tier price in the Elasticity Model");
			
			if(firstTierHours == 0){
				firstTierHours = elasticityPeriod - secondTierHours;
			}
			else{
				if((secondTierHours+firstTierHours) != elasticityPeriod)
				GL_THROW("Please set the tier hours correctly in the Elasticity Model");
			}

			if (secondTierHours == 0)
				GL_THROW("Please set second tier hours in the Elasticity Model");

			if (secondTierPrice == 0)
				GL_THROW("Please set second tier price in the Elasticity Model");

			if (oldSecondTierPrice == 0){
					oldSecondTierPrice = oldFirstTierPrice;
					gl_warning("Old second tier price is missing. System will assume the old pricing scheme was a fixed pricing scheme and use the old first tier price");
			}

			SecondTierArraySize = (int)(((secondTierHours * 3600) / period));
				
			//Calculation of the price ratios and change in price ratios.
			//This will not change for the course of the simulation
			oldPriceRatioSecondFirst = oldSecondTierPrice/oldFirstTierPrice;
			newPriceRatioSecondFirst = secondTierPrice/firstTierPrice;

			if(linearizeElasticity == true)
			{
				peakPriceMultiplier = pow(newPriceRatioSecondFirst/oldPriceRatioSecondFirst,subElasticityFirstSecond);
			}
			else{
				peakPriceMultiplier = 1 + ((subElasticityFirstSecond)*(newPriceRatioSecondFirst-oldPriceRatioSecondFirst)/oldPriceRatioSecondFirst);
				priceDiffSecond = secondTierPrice - oldSecondTierPrice; 				
			}
		}

		FirstTierArraySize = (int)(((firstTierHours * 3600) / period));

		priceDiffFirst = firstTierPrice - oldFirstTierPrice; 	
	
		ArraySize = (int)(((elasticityPeriod * 3600) / period));

		if(price_offset==0) price_offset = 10E-6 ;	
		
		tier_prices = (double *)gl_malloc(ArraySize*sizeof(double));

		if (tier_prices == NULL)
			GL_THROW("Failure to allocate tier_prices array");

		cleared_load = (double *)gl_malloc(ArraySize*sizeof(double));

		if (cleared_load == NULL)
			GL_THROW("Failure to allocate cleared_load array");

		offPeakLoad = (double *)gl_malloc(FirstTierArraySize*sizeof(double));

		if (offPeakLoad == NULL)
			GL_THROW("Failure to allocate offPeakLoad array");

		peakLoad = (double *)gl_malloc(SecondTierArraySize*sizeof(double));

		if (peakLoad == NULL)
			GL_THROW("Failure to allocate peakLoad array");

		criticalPeakLoad = (double *)gl_malloc(ThirdTierArraySize*sizeof(double));

		if (criticalPeakLoad == NULL)
			GL_THROW("Failure to allocate criticalPeakLoad array");	

		//Link up to parent object
		enduseProperty = gl_get_property(parent,"base_power");
		if (enduseProperty == NULL)
			GL_THROW("Unable to map base power property");
		
		current_load_enduse = (enduse*)GETADDR(parent,enduseProperty);

		//Initialize the array locations
		ArrayIndex = 0;
		ThirdTierArrayIndex = 0;
		SecondTierArrayIndex = 0;
		FirstTierArrayIndex = 0;

		for(int32 i=0; i < ArraySize; i++){
			
			tier_prices[i] = 0;
			cleared_load[i] = 0;	
		}

		for(int32 i=0; i < FirstTierArraySize; i++){
			offPeakLoad[i] = 0;
		}
		
		for(int32 i=0; i < SecondTierArraySize; i++){
			peakLoad[i] = 0;
		}

		for(int32 i=0; i < ThirdTierArraySize; i++){
			criticalPeakLoad[i] = 0;
		}	
		
	}

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

	initial_zipload_power=gl_get_double_by_name(parent,"base_power");

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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


				 }

	*/
	//////////////////////////////////////////////////////////////////
	return 1;
}
예제 #25
0
/* Object initialization is called once after all object have been created */
int inverter::init(OBJECT *parent)
{
	OBJECT *obj = OBJECTHDR(this);
	 
	// construct circuit variable map to meter
	static complex default_line123_voltage[3], default_line1_current[3];
	int i;

	// find parent meter or triplex_meter, if not defined, use default voltages, and if
	// the parent is not a meter throw an exception
	if (parent!=NULL && gl_object_isa(parent,"meter"))
	{
		// attach meter variables to each circuit
		parent_string = "meter";
		struct {
			complex **var;
			char *varname;
		}
		map[] = {
		// local object name,	meter object name
			{&pCircuit_V,			"voltage_A"}, // assumes 2 and 3 follow immediately in memory
			{&pLine_I,				"current_A"}, // assumes 2 and 3(N) follow immediately in memory
		};
		/// @todo use triplex property mapping instead of assuming memory order for meter variables (residential, low priority) (ticket #139)
	
		NR_mode = get_bool(parent,"NR_mode");

		for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
			*(map[i].var) = get_complex(parent,map[i].varname);

		node *par = OBJECTDATA(parent, node);
		number_of_phases_out = 0;
		if (par->has_phase(PHASE_A))
			number_of_phases_out += 1;
		if (par->has_phase(PHASE_B))
			number_of_phases_out += 1;
		if (par->has_phase(PHASE_C))
			number_of_phases_out += 1;
	}
	else if (parent!=NULL && gl_object_isa(parent,"triplex_meter"))
	{
		parent_string = "triplex_meter";
		number_of_phases_out = 4; //Indicates it is a triplex node and should be handled differently
		struct {
			complex **var;
			char *varname;
		}
		map[] = {
			// local object name,	meter object name
			{&pCircuit_V,			"voltage_12"}, // assumes 1N and 2N follow immediately in memory
			{&pLine_I,				"current_1"}, // assumes 2 and 3(N) follow immediately in memory
			{&pLine12,				"current_12"}, // maps current load 1-2 onto triplex load
			/// @todo use triplex property mapping instead of assuming memory order for meter variables (residential, low priority) (ticket #139)
		};

		NR_mode = get_bool(parent,"NR_mode");

		// attach meter variables to each circuit
		for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
		{
			if ((*(map[i].var) = get_complex(parent,map[i].varname))==NULL)
			{
				GL_THROW("%s (%s:%d) does not implement triplex_meter variable %s for %s (house:%d)", 
				/*	TROUBLESHOOT
					The Inverter requires that the triplex_meter contains certain published properties in order to properly connect
					the inverter to the triplex-meter.  If the triplex_meter does not contain those properties, GridLAB-D may
					suffer fatal pointer errors.  If you encounter this error, please report it to the developers, along with
					the version of GridLAB-D that raised this error.
				*/
				parent->name?parent->name:"unnamed object", parent->oclass->name, parent->id, map[i].varname, obj->name?obj->name:"unnamed", obj->id);
			}
		}
	}
	else if	((parent != NULL && strcmp(parent->oclass->name,"meter") != 0)||(parent != NULL && strcmp(parent->oclass->name,"triplex_meter") != 0))
	{
		throw("Inverter must have a meter or triplex meter as it's parent");
		/*  TROUBLESHOOT
		Check the parent object of the inverter.  The inverter is only able to be childed via a meter or 
		triplex meter when connecting into powerflow systems.  You can also choose to have no parent, in which
		case the inverter will be a stand-alone application using default voltage values for solving purposes.
		*/
	}
	else
	{
		parent_string = "none";
		number_of_phases_out = 3;
		struct {
			complex **var;
			char *varname;
		}
		map[] = {
		// local object name,	meter object name
			{&pCircuit_V,			"voltage_A"}, // assumes 2 and 3 follow immediately in memory
			{&pLine_I,				"current_A"}, // assumes 2 and 3(N) follow immediately in memory
		};

		gl_warning("Inverter:%d has no parent meter object defined; using static voltages", obj->id);
		
		NR_mode = false;

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

		// provide initial values for voltages
		default_line123_voltage[0] = complex(Rated_kV*1000/sqrt(3.0),0);
		default_line123_voltage[1] = complex(Rated_kV*1000/sqrt(3.0)*cos(2*PI/3),Rated_kV*1000/sqrt(3.0)*sin(2*PI/3));
		default_line123_voltage[2] = complex(Rated_kV*1000/sqrt(3.0)*cos(-2*PI/3),Rated_kV*1000/sqrt(3.0)*sin(-2*PI/3));
	}

	if (gen_mode_v == UNKNOWN)
	{
		gl_warning("Inverter control mode is not specified! Using default: SUPPLY_DRIVEN");
		gen_mode_v = SUPPLY_DRIVEN;
	}
	if (gen_status_v == UNKNOWN)
	{
		gl_warning("Inverter status is unknown! Using default: ONLINE");
		gen_status_v = ONLINE;
	}
	if (inverter_type_v == UNKNOWN)
	{
		gl_warning("Inverter type is unknown! Using default: PWM");
		inverter_type_v = PWM;
	}
			
			//need to check for parameters SWITCH_TYPE, FILTER_TYPE, FILTER_IMPLEMENTATION, GENERATOR_MODE
	/*
			if (Rated_kW!=0.0)  SB = Rated_kW/sqrt(1-Rated_pf*Rated_pf);
			if (Rated_kVA!=0.0)  SB = Rated_kVA/3;
			if (Rated_kV!=0.0)  EB = Rated_kV/sqrt(3.0);
			if (SB!=0.0)  ZB = EB*EB/SB;
			else throw("Generator power capacity not specified!");
			double Real_Rinternal = Rinternal * ZB; 
			double Real_Rload = Rload * ZB;
			double Real_Rtotal = Rtotal * ZB;
			double Real_Rphase = Rphase * ZB;
			double Real_Rground = Rground * ZB;
			double Real_Rground_storage = Rground_storage * ZB;
			double[3] Real_Rfilter = Rfilter * ZB;

			double Real_Cinternal = Cinternal * ZB;
			double Real_Cground = Cground * ZB;
			double Real_Ctotal = Ctotal * ZB;
			double[3] Real_Cfilter = Cfilter * ZB;

			double Real_Linternal = Linternal * ZB;
			double Real_Lground = Lground * ZB;
			double Real_Ltotal = Ltotal * ZB;
			double[3] Real_Lfilter = Lfilter * ZB;

			tst = complex(Real_Rground,Real_Lground);
			AMx[0][0] = complex(Real_Rinternal,Real_Linternal) + tst;
			AMx[1][1] = complex(Real_Rinternal,Real_Linternal) + tst;
			AMx[2][2] = complex(Real_Rinternal,Real_Linternal) + tst;
		//	AMx[0][0] = AMx[1][1] = AMx[2][2] = complex(Real_Rs+Real_Rg,Real_Xs+Real_Xg);
			AMx[0][1] = AMx[0][2] = AMx[1][0] = AMx[1][2] = AMx[2][0] = AMx[2][1] = tst;

			*/

	//all other variables set in input file through public parameters
	switch(inverter_type_v)
	{
		case TWO_PULSE:
			efficiency = 0.8;
			break;
		case SIX_PULSE:
			efficiency = 0.8;
			break;
		case TWELVE_PULSE:
			efficiency = 0.8;
			break;
		case PWM:
			efficiency = 0.9;
			break;
		default:
			efficiency = 0.8;
			break;
	}

	internal_switch_resistance(switch_type_choice);
	filter_circuit_impact(filter_type_v, filter_imp_v);

	return 1;
}
예제 #26
0
/* Object initialization is called once after all object have been created */
int rectifier::init(OBJECT *parent)
{
	OBJECT *obj = OBJECTHDR(this);

	//initialize variables that are used internally
	//set_terminal_voltage = 240; //V
	//max_current_step_size = 100; //A
	Rated_kW = 1000; //< nominal power in kW
	Max_P = 1000;//< maximum real power capacity in kW
	Min_P = 0;//< minimum real power capacity in kW
	//Max_Q = 1000;//< maximum reactive power capacity in kVar
	//Min_Q = 1000;//< minimum reactive power capacity in kVar
	Rated_kVA = 1500; //< nominal capacity in kVA
	Rated_kV = 10; //< nominal line-line voltage in kV
	Rinternal = 0.035;
	Rload = 1;
	Rtotal = 0.05;
	//XphaseA = complex(1 * 1,0);
	//XphaseB = complex(1 * -0.5, 1 * 0.866);
	//XphaseC = complex(1 * -0.5, 1 * -0.866);
	XphaseA = complex(5 * 1,0);
	XphaseB = complex(5 * 1,0);
	XphaseC = complex(5 * 1,0);
	Rground = 0.03;
	Rground_storage = 0.05;
	Vdc = 480;

	Cinternal = 0;
	Cground = 0;
	Ctotal = 0;
	Linternal = 0;
	Lground = 0;
	Ltotal = 0;
	filter_120HZ = false;
	filter_180HZ = false;
	filter_240HZ = false;
	pf_in = 1;
	pf_out = 0;
	number_of_phases_in = 3;
	number_of_phases_out = 0;
	phaseAIn = true;
	phaseBIn = true;
	phaseCIn = true;
	phaseAOut = false;
	phaseBOut = false;
	phaseCOut = false;

	V_In_Set_A = complex(360,0);
	V_In_Set_B = complex(-180, 311.769);
	V_In_Set_C = complex(-180,-311.769);

	switch_type_choice = IDEAL_SWITCH;
	//generator_mode_choice = CONSTANT_PQ;
	gen_status_v = ONLINE;
	filter_type_v = BAND_PASS;
	filter_imp_v = IDEAL_FILTER;
	rectifier_type_v = SIX_PULSE;
	power_in = AC;
	power_out = DC;


	P_Out = 500;  // P_Out and Q_Out are set by the user as set values to output in CONSTANT_PQ mode
	Q_Out = 0;



	margin = 50;
	V_Rated = 360;
	I_out_prev = 0;
	I_step_max = 100;
	internal_losses = 0;
	C_Storage_Out = 0;
	efficiency = 0;
	losses = 0;

	on_ratio = 0;
	input_frequency = 2000;
	frequency_losses = 0;


	gl_verbose("rectifier init: initialized the variables");

	int i;

	if (parent!=NULL && gl_object_isa(parent,"meter"))
	{
		// TO DO: Figure out how to connect a DC device to meter.
	}

	if (parent!=NULL && gl_object_isa(parent,"inverter"))
	{
		parent_string = "inverter";

		struct {
			complex **var;
			char *varname;
		}
		map[] = {
			// local object name,	meter object name
			{&pCircuit_V,			"Vdc"}, 
			{&pLine_I,				"I_In"}
		};

		// attach meter variables to each circuit
		for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
		{
			if ((*(map[i].var) = get_complex(parent,map[i].varname))==NULL)
			{
				GL_THROW("%s (%s:%d) does not implement triplex_meter variable %s for %s (inverter:%d)", 
					/*	TROUBLESHOOT
					The rectifier requires that the inverter contains certain published properties in order to properly connect. If you encounter this error, please report it to the developers, along with
					the version of GridLAB-D that raised this error.
					*/
					parent->name?parent->name:"unnamed object", parent->oclass->name, parent->id, map[i].varname, obj->name?obj->name:"unnamed", obj->id);
			}
		}
	}

	if (parent_string == NULL){
		GL_THROW("Rectifier's parent is not an inverter. The rectifier object's parent must be an inverter.");
	}

	/* TODO: set the context-dependent initial value of properties */
	if (gen_mode_v==UNKNOWN)
	{
		GL_THROW("Generator control mode is not specified.");
	}
	else if(gen_mode_v == CONSTANT_V)
	{
		GL_THROW("Generator mode CONSTANT_V is not implemented yet.");
	}
	else if(gen_mode_v == CONSTANT_PQ)
	{
		GL_THROW("Generator mode CONSTANT_PQ is not implemented yet.");
	}
	else if(gen_mode_v == CONSTANT_PF)
	{
		GL_THROW("Generator mode CONSTANT_PF is not implemented yet.");
	}


	//need to check for parameters SWITCH_TYPE, FILTER_TYPE, FILTER_IMPLEMENTATION, GENERATOR_MODE
	/*
	if (Rated_kW!=0.0)  SB = Rated_kW/sqrt(1-Rated_pf*Rated_pf);
	if (Rated_kVA!=0.0)  SB = Rated_kVA/3;
	if (Rated_kV!=0.0)  EB = Rated_kV/sqrt(3.0);
	if (SB!=0.0)  ZB = EB*EB/SB;
	else throw("Generator power capacity not specified!");
	double Real_Rinternal = Rinternal * ZB; 
	double Real_Rload = Rload * ZB;
	double Real_Rtotal = Rtotal * ZB;
	double Real_Xphase = Xphase * ZB;
	double Real_Rground = Rground * ZB;
	double Real_Rground_storage = Rground_storage * ZB;
	double[3] Real_Rfilter = Rfilter * ZB;

	double Real_Cinternal = Cinternal * ZB;
	double Real_Cground = Cground * ZB;
	double Real_Ctotal = Ctotal * ZB;
	double[3] Real_Cfilter = Cfilter * ZB;

	double Real_Linternal = Linternal * ZB;
	double Real_Lground = Lground * ZB;
	double Real_Ltotal = Ltotal * ZB;
	double[3] Real_Lfilter = Lfilter * ZB;

	tst = complex(Real_Rground,Real_Lground);
	AMx[0][0] = complex(Real_Rinternal,Real_Linternal) + tst;
	AMx[1][1] = complex(Real_Rinternal,Real_Linternal) + tst;
	AMx[2][2] = complex(Real_Rinternal,Real_Linternal) + tst;
	//	AMx[0][0] = AMx[1][1] = AMx[2][2] = complex(Real_Rs+Real_Rg,Real_Xs+Real_Xg);
	AMx[0][1] = AMx[0][2] = AMx[1][0] = AMx[1][2] = AMx[2][0] = AMx[2][1] = tst;
	*/

	//all other variables set in input file through public parameters
	switch(rectifier_type_v){
		case ONE_PULSE:
			efficiency = 0.5;
			break;
		case TWO_PULSE:
			efficiency = 0.7;
			break;
		case THREE_PULSE:
			efficiency = 0.7;
			break;
		case SIX_PULSE:
			efficiency = 0.8;
			break;
		case TWELVE_PULSE:
			efficiency = 0.9;
			break;
		default:
			efficiency = 0.8;
			break;
	}

	internal_switch_resistance(switch_type_choice);
	filter_circuit_impact((power_electronics::FILTER_TYPE)filter_type_v, (power_electronics::FILTER_IMPLEMENTATION)filter_imp_v);

	gl_verbose("rectifier init: about to exit");
	return 1;
}