Ejemplo n.º 1
0
int residential_enduse::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	hdr->flags |= OF_SKIPSAFE;
	ATTACHFUNCTION attach = 0;

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

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

	return 1;
}
Ejemplo n.º 2
0
TIMESTAMP switch_object::sync(TIMESTAMP t0)
{
	OBJECT *obj = OBJECTHDR(this);
	unsigned char work_phases_pre, work_phases_post;

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

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

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

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

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

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

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

	if (t2==TS_NEVER)
		return(t2);
	else
		return(-t2);	//Soft limit it
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
/* Object initialization is called once after all object have been created */
int metrics::init(OBJECT *parent)
{
	OBJECT *hdr = OBJECTHDR(this);
	int index, indexa, indexb, returnval;
	char work_metrics[1025];
	char *startVal, *endVal, *workVal;
	char workbuffer[1025];
	char metricbuffer[257];
	FILE *FPVal;
	FINDLIST *CandidateObjs;
	OBJECT *temp_obj;
	bool *temp_bool;
	FUNCTIONADDR funadd = NULL;

	//Ensure our "module metrics" object is populated
	if (module_metrics_obj == NULL)
	{
		GL_THROW("Please specify a module metrics object for metrics:%s",hdr->name);
		/*  TROUBLESHOOT
		To operate properly, the metrics object must have the corresponding module's
		metrics calculator linked.  If this object is missing, metrics has no idea
		what to calculate and will not proceed.
		*/
	}

	//It's not null, map up the init function and call it (this must exist, even if it does nothing)
	funadd = (FUNCTIONADDR)(gl_get_function(module_metrics_obj,"init_reliability"));
					
	//Make sure it was found
	if (funadd == NULL)
	{
		GL_THROW("Unable to map reliability init function on %s in %s",module_metrics_obj->name,hdr->name);
		/*  TROUBLESHOOT
		While attempting to initialize the reliability module in the "module of interest" metrics device,
		a error was encountered.  Ensure this object fully supports reliability and try again.  If the bug
		persists, please submit your code and a bug report to the trac website.
		*/
	}

	Extra_Data = ((void *(*)(OBJECT *, OBJECT *))(*funadd))(module_metrics_obj,hdr);

	//Make sure it worked
	if (Extra_Data==NULL)
	{
		GL_THROW("Unable to map reliability init function on %s in %s",module_metrics_obj->name,hdr->name);
		//defined above
	}

	//Figure out how many indices we should be finding
	index = 0;

	while ((metrics_oi[index] != '\0') && (index < 1024))
	{
		if (metrics_oi[index] == ',')
		{
			num_indices++;	//Increment counter
		}

		index++;	//Increment pointer
	}

	//Make sure we didn't blow the top off
	if (index == 1024)
	{
		GL_THROW("Maximum length exceeded on metrics_of_interest in metrics:%s",hdr->name);
		/*  TROUBLESHOOT
		While parsing the metrics_of_interest list, the maximum length (1024 characters) was
		reached.  This can cause undesired behavior.  Ensure the metrics list is within this
		character count.  If it is, please try again.  If the error persists, please submit
		your code and a bug report via the trac website.
		*/
	}

	//See if at least one was found.  If it was, that means there are 2 (it counts commas)
	if (num_indices >= 1)
		num_indices++;
	
	//See if we were a solitary one - if so, increment accordingly
	if ((num_indices == 0) && (index > 1))
		num_indices = 1;

	//Make sure at least one was found
	if (num_indices == 0)
	{
		GL_THROW("No indices of interest specified for metrics:%s",hdr->name);
		/*  TROUBLESHOOT
		No indices were found to read.  Please specify the proper indices and try again.
		*/
	}

	//Malloc us up!
	CalcIndices = (INDEXARRAY*)gl_malloc(num_indices * sizeof(INDEXARRAY));

	//Make sure it worked
	if (CalcIndices == NULL)
	{
		GL_THROW("Failure to allocate indices memory in metrics:%s",hdr->name);
		/*  TROUBLESHOOT
		While allocating the storage matrix for the indices to calculate, an error occurred.
		Please try again.  If the error persists, please submit you code and a bug report
		using the trac website.
		*/
	}

	//Initialize these, just in case
	for (index=0; index<num_indices; index++)
	{
		CalcIndices[index].MetricLoc = NULL;	//No address by default
		
		for (indexa=0; indexa<257; indexa++)	//+1 due to end \0
			CalcIndices[index].MetricName[indexa]='\0';
	}

	//Populate it up - copy it first so we don't destroy the original
	metrics_oi.copy_to(work_metrics);

	//Set initial pointers
	startVal = work_metrics;
	endVal = work_metrics;

	//Loop through and find them
	for (index=0; index<num_indices; index++)	//Loop through
	{
		//Find the next comma or end point
		while ((*endVal != ',') && (*endVal != '\0'))
		{
			endVal++;
		}

		//Replace us (comma) with EOS (\0)
		*endVal='\0';

		//Copy us into the structure
		workVal = startVal;
		indexa = 0;
		while ((workVal<=endVal) && (indexa < 256))
		{
			//Copy the value in
			CalcIndices[index].MetricName[indexa] = *workVal;

			//Copy into secondary
			metricbuffer[indexa] = *workVal;

			//Increment pointers
			indexa++;
			workVal++;
		}

		//apply the "_int" portion for the interval search
		indexb = indexa-1;

		//Now update pointers appropriately and proceed
		endVal++;
		startVal = endVal;
		
		//Now try to find this variable
		CalcIndices[index].MetricLoc = get_metric(module_metrics_obj,CalcIndices[index].MetricName);

		//Make sure it worked
		if (CalcIndices[index].MetricLoc == NULL)
		{
			GL_THROW("Unable to find metric %s in object %s for metric:%s",CalcIndices[index].MetricName.get_string(),module_metrics_obj->name,hdr->name);
			/*  TROUBLESHOOT
			While attempting to map out a reliability metric, the desired metric was not found.  Please check the variable
			name and ensure the metric is being published in the module metrics object and try again.  If the error persists,
			please submit your code and a bug report to the trac website.
			*/
		}

		//Get the interval metric - if it exists - and there is room
		if ((indexb+4) <= 256)
		{
			metricbuffer[indexb] = '_';
			metricbuffer[(indexb+1)] = 'i';
			metricbuffer[(indexb+2)] = 'n';
			metricbuffer[(indexb+3)] = 't';
			metricbuffer[(indexb+4)] = '\0';

			//Try to map it
			CalcIndices[index].MetricLocInterval = get_metric(module_metrics_obj,metricbuffer);

			//No NULL check - if it wasn't found, we won't deal with it
		}
	}//end metric traversion
	
	//Map our reset functions for ease
	reset_interval_func = (FUNCTIONADDR)(gl_get_function(module_metrics_obj,"reset_interval_metrics"));
	
	//Make sure it worked
	if (reset_interval_func == NULL)
	{
		GL_THROW("Failed to map interval reset in metrics object %s for metrics:%s",module_metrics_obj->name,hdr->name);
		/*  TROUBLESHOOT
		While attempting to map the interval statistics reset function, the metrics object encountered a problem.
		Please make sure the module metrics object supports a "reset_interval_metrics" function.  If so, please try again.
		If the error persists, please submit your code and a bug report using the trac website.
		*/
	}

	reset_annual_func = (FUNCTIONADDR)(gl_get_function(module_metrics_obj,"reset_annual_metrics"));

	//Make sure it worked
	if (reset_annual_func == NULL)
	{
		GL_THROW("Failed to map annual reset in metrics object %s for metrics:%s",module_metrics_obj->name,hdr->name);
		/*  TROUBLESHOOT
		While attempting to map the annual statistics reset function, the metrics object encountered a problem.
		Please make sure the module metrics object supports a "reset_interval_metrics" function.  If so, please try again.
		If the error persists, please submit your code and a bug report using the trac website.
		*/
	}

	compute_metrics = (FUNCTIONADDR)(gl_get_function(module_metrics_obj,"calc_metrics"));

	//Make sure it worked
	if (compute_metrics == NULL)
	{
		GL_THROW("Failed to map metric computation function in metrics object %s for metrics:%s",module_metrics_obj->name,hdr->name);
		/*  TROUBLESHOOT
		While attempting to map the function to compute the desired metrics, the metrics object encountered a problem.
		Please make sure the module metrics object supports a "calc_metrics" function.  If so, please try again.
		If the error persists, please submit your code and a bug report using the trac website.
		*/
	}

	//Call the resets - interval
	returnval = ((int (*)(OBJECT *, OBJECT *))(*reset_interval_func))(hdr,module_metrics_obj);

	if (returnval != 1)	//See if it failed
	{
		GL_THROW("Failed to reset interval metrics for %s by metrics:%s",module_metrics_obj->name,hdr->name);
		/*  TROUBLESHOOT
		The metrics object encountered an error while attempting to reset the interval statistics variables.
		Please try again.  If the error persists, submit your code and a bug report via the trac website.
		*/
	}

	//Call the resets - annual
	returnval = ((int (*)(OBJECT *, OBJECT *))(*reset_annual_func))(hdr,module_metrics_obj);

	if (returnval != 1)	//See if it failed
	{
		GL_THROW("Failed to reset annual metrics for %s by metrics:%s",module_metrics_obj->name,hdr->name);
		/*  TROUBLESHOOT
		The metrics object encountered an error while attempting to reset the annual statistics variables.
		Please try again.  If the error persists, submit your code and a bug report via the trac website.
		*/
	}

	//Convert our calculation interval to a timestamp
	metric_interval = (TIMESTAMP)metric_interval_dbl;
	report_interval = (TIMESTAMP)report_interval_dbl;

	//See if it is a year - flag appropriately
	if (metric_interval == 31536000)
		metric_equal_annual = true;

	//Make sure we have a file name provided
	if (report_file[0] == '\0')	//None specified
	{
		GL_THROW("Please specify a proper report file name if you would like an output file from metrics:%s",hdr->name);
		/*  TROUBLESHOOT
		While attempting to write the report file, an invalid file name was provided.  Please provide a valid file name
		and try again.
		*/
	}

	//Open the file to clear it
	FPVal = fopen(report_file,"wt");

	//Make sure it worked
	if (FPVal == NULL)
	{
		GL_THROW("Unable to create the report file '%s' for metrics:%s",report_file,hdr->name);
		/*  TROUBLESHOOT
		While attempting to write the metrics output file, an error occurred.  Please make sure you
		have write permissions at that location and try again.  If the error persists, please submit
		your code and a bug report using the trac website.
		*/
	}

	//It must exist - write the typical header nonsense
	fprintf(FPVal,"Reliability report for %s\n", gl_global_getvar("modelname",workbuffer,(1025*sizeof(char))));

	//Find our lucky candidate objects
	CandidateObjs = gl_find_objects(FL_GROUP,customer_group.get_string());
	if (CandidateObjs==NULL)
	{
		GL_THROW("Failure to find devices for %s specified as: %s",hdr->name,customer_group.get_string());
		/*  TROUBLESHOOT
		While attempting to populate the list of devices to check for reliability metrics, the metrics
		object failed to find any desired objects.  Please make sure the objects exist and try again.
		If the bug persists, please submit your code using the trac website.
		*/
	}

	//Do a zero-find check as well
	if (CandidateObjs->hit_count == 0)
	{
		GL_THROW("Failure to find devices for %s specified as: %s",hdr->name,customer_group.get_string());
		//Defined above
	}

	//Pull the count
	CustomerCount = CandidateObjs->hit_count;

	//Make us an array!
	Customers = (CUSTARRAY*)gl_malloc(CustomerCount*sizeof(CUSTARRAY));

	//Make sure it worked
	if (Customers == NULL)
	{
		GL_THROW("Failure to allocate customer list memory in metrics:%s",hdr->name);
		/*  TROUBLESHOOT
		While allocating the memory for the list of customers, GridLAB-D encountered a problem.
		Please try again.  If the error persists, please submit your code and a bug report via the
		trac website.
		*/
	}

	//Let's populate the beast now!
	temp_obj = NULL;
	for (index=0; index<CustomerCount; index++)
	{
		//Find the object
		temp_obj = gl_find_next(CandidateObjs, temp_obj);

		if (temp_obj == NULL)
		{
			GL_THROW("Failed to populate customer list in metrics: %s",hdr->name);
			/*  TROUBLESHOOT
			While populating the metrics customer list, an object failed to be
			located.  Please try again.  If the error persists, please submit your
			code and a bug report to the trac website.
			*/
		}

		Customers[index].CustomerObj = temp_obj;

		//Try to find our "outage" indicator and map its address
		temp_bool = get_outage_flag(temp_obj, "customer_interrupted");

		//make sure it found it
		if (temp_bool == NULL)
		{
			GL_THROW("Unable to find interrupted flag for customer object %s in metrics:%s",temp_obj->name,hdr->name);
			/*  TROUBLESHOOT
			While attempting to link to the 'customer interrupted' flag, an error occurred.  Please ensure the object
			supports being polled by reliability as a customer (customer_interrupted exists as a published property) and
			try again.  If the error persists, please submit your code and a bug report via the trac website.
			*/
		}

		//Write this value in
		Customers[index].CustInterrupted = temp_bool;

		if (index == 0)	//First customer, handle slightly different
		{
			//Populate the secondary index - needs to exist, even if never used
			//Try to find our secondary "outage" indicator and map its address
			temp_bool = get_outage_flag(temp_obj, "customer_interrupted_secondary");

			//make sure it found it
			if (temp_bool == NULL)	//Not found, assume no one else wants one
			{
				gl_warning("Unable to find secondary interruption flag, no secondary interruptions recorded in metrics:%s",hdr->name);
				/*  TROUBLESHOOT
				While attempting to link to the 'secondary customer interrupted' flag, it was not found.  THe object may not support
				"secondary interruption counts" and this message is valid.  If a secondary count was desired, ensure the object
				supports being polled by reliability as a customer (customer_interrupted_secondary exists as a published property) and
				try again.  If the error persists, please submit your code and a bug report via the trac website.
				*/
			}
			else	//One found, assume all want one now
			{
				secondary_interruptions_count = true;
				
				//Write this value in
				Customers[index].CustInterrupted_Secondary = temp_bool;
			}
		}
		else if (secondary_interruptions_count == true)	//Decided we want it
		{
			//Populate the secondary index - needs to exist, even if never used
			//Try to find our secondary "outage" indicator and map its address
			temp_bool = get_outage_flag(temp_obj, "customer_interrupted_secondary");

			//make sure it found it
			if (temp_bool == NULL)
			{
				GL_THROW("Unable to find secondary interruption flag for customer object %s in metrics:%s",temp_obj->name,hdr->name);
				/*  TROUBLESHOOT
				While attempting to link to the 'secondary customer interrupted' flag, an error occurred.  Please ensure the object
				supports being polled by reliability as a customer (customer_interrupted_secondary exists as a published property) and
				try again.  If the error persists, please submit your code and a bug report via the trac website.
				*/
			}

			//Write this value in
			Customers[index].CustInterrupted_Secondary = temp_bool;
		}
		//Defaulted else - unwanted

	}//end population loop

	//Free up list
	gl_free(CandidateObjs);

	//Write the customer count and header information to the file we have going
	fprintf(FPVal,"Number of customers = %d\n\n",CustomerCount);

	//See if the particular metrics object has any "comments" to add to the file header (units, notes, etc.)
	funadd = NULL;	//Reset function pointer - just in case

	//Map up the "extra print" function - if it isn't there, well nothing is done
	funadd = (FUNCTIONADDR)(gl_get_function(module_metrics_obj,"logfile_extra"));

	//See if it was found
	if (funadd != NULL)
	{
		//Do the extra printing
		returnval = ((int (*)(OBJECT *, char *))(*funadd))(module_metrics_obj,workbuffer);

		//Make sure it worked
		if (returnval==0)
		{
			GL_THROW("Failed to write extra header material for %s in %s",module_metrics_obj->name,hdr->name);
			/*  TROUBLESHOOT
			While attempting to write the extra material into the file header, an error occurred.  Please try again.
			If the error persists, please submit your code and a bug report via the trac website.
			*/
		}

		//Print it out
		fprintf(FPVal,"%s",workbuffer);
	}

	//Close the file handle
	fclose(FPVal);

	return 1; /* return 1 on success, 0 on failure - We're so awesome we always assume we work */
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
TIMESTAMP fuse::sync(TIMESTAMP t0)
{
	OBJECT *obj = OBJECTHDR(this);
	unsigned char work_phases;
	bool fuse_blew;
	TIMESTAMP replacement_time;
	TIMESTAMP replacement_duration;
	TIMESTAMP t2;
	char fault_val[9];
	int result_val;

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

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

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

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

	//Code below only applies to NR right now - FBS legacy code has no sync values
	//May need to be appropriately adjusted once FBS supports reliability
	if (solver_method == SM_NR)
	{
		//Put any fuses back in service, if they're ready
		if (((fix_time[0] <= t0) || (fix_time[1] <= t0) || (fix_time[2] <= t0)) && (event_schedule == NULL))	//Only needs to be done if reliability isn't present
		{
			//Bring the phases back that are necessary
			if ((fix_time[0] <= t0) && ((NR_branchdata[NR_branch_reference].origphases & 0x04) == 0x04))	//Phase A ready and had a phase A
			{
				//Update status
				phase_A_state = GOOD;

				//Pop in the variables for the reliability update (if it exists)
				fix_time[0] = TS_NEVER;	//Reset variables
			}

			if ((fix_time[1] <= t0) && ((NR_branchdata[NR_branch_reference].origphases & 0x02) == 0x02))	//Phase B ready and had a phase B
			{
				//Update status
				phase_B_state = GOOD;

				//Pop in the variables for the reliability update (if it exists)
				fix_time[1] = TS_NEVER;	//Reset variables
			}

			if ((fix_time[2] <= t0) && ((NR_branchdata[NR_branch_reference].origphases & 0x01) == 0x01))	//Phase C ready and had a phase C
			{
				//Update status
				phase_C_state = GOOD;

				//Pop in the variables for the reliability update (if it exists)
				fix_time[2] = TS_NEVER;	//Reset variables
			}
		}//End back in service

		//Call syncing function
		fuse_sync_function();

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

		//Always execute check code now
		//Start with no assumed outages
		fuse_blew = false;
		work_phases = 0x00;
		replacement_time = 0;

		//Check them
		if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)	//Phase A valid - check it
		{
			//Link::sync is where current in is calculated.  Convert the values
			current_current_values[0] = current_in[0].Mag();

			if ((current_current_values[0] > current_limit) && (phase_A_state == GOOD))
			{
				phase_A_state = BLOWN;	//Blow the fuse
				gl_warning("Phase A of fuse:%s just blew!",obj->name);
				/*  TROUBLESHOOT
				The current through phase A of the fuse just exceeded the maximum rated value.
				Use a larger value, or otherwise change your system and try again.
				*/

				fuse_blew = true;		//Flag a change
				work_phases |= 0x04;	//Flag A change

				//See if an update is needed (it's A and first, so yes, but just to be generic)
				if (replacement_time == 0)
				{
					//Get length of outage
					if (restore_dist_type == EXPONENTIAL)
					{
						//Update mean repair time
						mean_repair_time = gl_random_exponential(RNGSTATE,1.0/mean_replacement_time);
						replacement_duration = (TIMESTAMP)(mean_repair_time);
					}
					else
					{
						//Update mean repair time - fuse always overrides link
						mean_repair_time = mean_replacement_time;
						replacement_duration = (TIMESTAMP)(mean_repair_time);
					}

					//Figure out when it is
					replacement_time = prev_fuse_time + replacement_duration;
				}
			}
			//Else is leave as is - either blown, or reliability hit it
		}

		if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)	//Phase B valid - check it
		{
			//Link::sync is where current in is calculated.  Convert the values
			current_current_values[1] = current_in[1].Mag();

			if ((current_current_values[1] > current_limit) && (phase_B_state == GOOD))
			{
				phase_B_state = BLOWN;	//Blow the fuse

				gl_warning("Phase B of fuse:%s just blew!",obj->name);
				/*  TROUBLESHOOT
				The current through phase B of the fuse just exceeded the maximum rated value.
				Use a larger value, or otherwise change your system and try again.
				*/

				fuse_blew = true;		//Flag a change
				work_phases |= 0x02;	//Flag B change

				//See if an update is needed
				if (replacement_time == 0)
				{
					//Get length of outage
					if (restore_dist_type == EXPONENTIAL)
					{
						//Update mean repair time
						mean_repair_time = gl_random_exponential(RNGSTATE,1.0/mean_replacement_time);
						replacement_duration = (TIMESTAMP)(mean_repair_time);
					}
					else
					{
						//Update mean repair time - fuse always overrides link
						mean_repair_time = mean_replacement_time;
						replacement_duration = (TIMESTAMP)(mean_repair_time);
					}

					//Figure out when it is
					replacement_time = prev_fuse_time + replacement_duration;
				}
			}
			//Else is leave as is - either blown, or reliability hit it
		}

		if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)	//Phase C valid - check it
		{
			//Link::sync is where current in is calculated.  Convert the values
			current_current_values[2] = current_in[2].Mag();

			if ((current_current_values[2] > current_limit) && (phase_C_state == GOOD))
			{
				phase_C_state = BLOWN;	//Blow the fuse

				gl_warning("Phase C of fuse:%s just blew!",obj->name);
				/*  TROUBLESHOOT
				The current through phase C of the fuse just exceeded the maximum rated value.
				Use a larger value, or otherwise change your system and try again.
				*/

				fuse_blew = true;		//Flag a change
				work_phases |= 0x01;	//Flag C change

				//See if an update is needed
				if (replacement_time == 0)
				{
					//Get length of outage
					if (restore_dist_type == EXPONENTIAL)
					{
						//Update mean repair time
						mean_repair_time = gl_random_exponential(RNGSTATE,1.0/mean_replacement_time);
						replacement_duration = (TIMESTAMP)(mean_repair_time);
					}
					else
					{
						//Update mean repair time - fuse always overrides link
						mean_repair_time = mean_replacement_time;
						replacement_duration = (TIMESTAMP)(mean_repair_time);
					}

					//Figure out when it is
					replacement_time = prev_fuse_time + replacement_duration;
				}
			}
			//Else is leave as is - either blown, or reliability hit it
		}

		if (fuse_blew == true)
		{
			//Set up fault type
			fault_val[0] = 'F';
			fault_val[1] = 'U';
			fault_val[2] = 'S';
			fault_val[3] = '-';

			//Determine who blew and store the time (assumes fuses can be replaced in parallel)
			switch (work_phases)
			{
			case 0x00:	//No fuses blown !??
				GL_THROW("fuse:%s supposedly blew, but doesn't register the right phases",obj->name);
				/*  TROUBLESHOOT
				A fuse reported an over-current condition and blew the appropriate link.  However, it did not appear
				to fully propogate this condition.  Please try again.  If the error persists, please submit your code
				and a bug report via the trac website.
				*/
				break;
			case 0x01:	//Phase C blew
				fix_time[2] = replacement_time;
				fault_val[4] = 'C';
				fault_val[5] = '\0';
				break;
			case 0x02:	//Phase B blew
				fix_time[1] = replacement_time;
				fault_val[4] = 'B';
				fault_val[5] = '\0';
				break;
			case 0x03:	//Phase B and C blew
				fix_time[1] = replacement_time;
				fix_time[2] = replacement_time;
				fault_val[4] = 'B';
				fault_val[5] = 'C';
				fault_val[6] = '\0';
				break;
			case 0x04:	//Phase A blew
				fix_time[0] = replacement_time;
				fault_val[4] = 'A';
				fault_val[5] = '\0';
				break;
			case 0x05:	//Phase A and C blew
				fix_time[0] = replacement_time;
				fix_time[2] = replacement_time;
				fault_val[4] = 'A';
				fault_val[5] = 'C';
				fault_val[6] = '\0';
				break;
			case 0x06:	//Phase A and B blew
				fix_time[0] = replacement_time;
				fix_time[1] = replacement_time;
				fault_val[4] = 'A';
				fault_val[5] = 'B';
				fault_val[6] = '\0';
				break;
			case 0x07:	//All three went
				fix_time[0] = replacement_time;
				fix_time[1] = replacement_time;
				fix_time[2] = replacement_time;
				fault_val[4] = 'A';
				fault_val[5] = 'B';
				fault_val[6] = 'C';
				fault_val[7] = '\0';
				break;
			default:
				GL_THROW("fuse:%s supposedly blew, but doesn't register the right phases",obj->name);
				//Defined above
			}//End switch

			if (event_schedule != NULL)	//Function was mapped - go for it!
			{
				//Call the function
				result_val = ((int (*)(OBJECT *, OBJECT *, char *, TIMESTAMP, TIMESTAMP, int, bool))(*event_schedule))(*eventgen_obj,obj,fault_val,t0,0,-1,false);

				//Make sure it worked
				if (result_val != 1)
				{
					GL_THROW("Attempt to blow fuse:%s failed in a reliability manner",obj->name);
					/*  TROUBLESHOOT
					While attempting to propagate a blown fuse's impacts, an error was encountered.  Please
					try again.  If the error persists, please submit your code and a bug report via the trac website.
					*/
				}

				//Ensure we don't go anywhere yet
				t2 = t0;

			}	//End fault object present
			else	//No object, just fail us out - save the iterations
			{
				gl_warning("No fault_check object present - Newton-Raphson solver may fail!");
				/*  TROUBLESHOOT
				A fuse blew and created an open link.  If the system is not meshed, the Newton-Raphson
				solver will likely fail.  Theoretically, this should be a quick fail due to a singular matrix.
				However, the system occasionally gets stuck and will exhaust iteration cycles before continuing.
				If the fuse is blowing and the NR solver still iterates for a long time, this may be the case.
				*/
			}
		}
	}//End NR-only reliability calls
	else	//FBS
		t2 = link_object::sync(t0);

	if (t2==TS_NEVER)
		return(t2);
	else
		return(-t2);	//Soft limit it
}
Ejemplo n.º 7
0
TIMESTAMP switch_object::sync(TIMESTAMP t0)
{
	OBJECT *obj = OBJECTHDR(this);
	TIMESTAMP temp_time;
	unsigned char work_phases, work_phases_pre, work_phases_post, work_phases_closed;
	char fault_val[9];
	int result_val, impl_fault;
	bool fault_mode;

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

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

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

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

	if ((solver_method == SM_NR) && (event_schedule != NULL))	//NR-reliability-related stuff
	{
		//Store our phases going in
		work_phases_pre = NR_branchdata[NR_branch_reference].phases & 0x07;
	
		//Call syncing function
		work_phases_post = switch_expected_sync_function();

		//Store our phases going out
		work_phases_post &= 0x07;
	}
	else	//Normal execution
	{
		//Call syncing function
		switch_sync_function();

		//Set phases the same
		work_phases_pre = 0x00;
		work_phases_post = 0x00;
	}

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

	//See if we're in the proper cycle - NR only for now
	if ((solver_method == SM_NR) && (work_phases_pre != work_phases_post))
	{
		//Find out what changed
		work_phases = (work_phases_pre ^ work_phases_post) & 0x07;

		//See if this transition is a "fault-open" or a "fault-close"
		work_phases_closed = work_phases & work_phases_post;

		//See how it looks
		if (work_phases_closed == work_phases)	//It's a close
		{
			fault_mode = true;
			//work_phases = (~work_phases) & 0x07;
		}
		else	//It's an open
		{
			fault_mode = false;
			//Work phases is already in the proper format
		}

		//Set up fault type
		fault_val[0] = 'S';
		fault_val[1] = 'W';
		fault_val[2] = '-';

		//Default fault - none - will cause a failure if not caught
		impl_fault = -1;

		//Determine who opened and store the time
		switch (work_phases)
		{
		case 0x00:	//No switches opened !??
			GL_THROW("switch:%s supposedly opened, but doesn't register the right phases",obj->name);
			/*  TROUBLESHOOT
			A switch reported changing to an open status.  However, it did not appear to fully propogate this
			condition.  Please try again.  If the error persists, please submit your code and a bug report
			via the trac website.
			*/
			break;
		case 0x01:	//Phase C action
			fault_val[3] = 'C';
			fault_val[4] = '\0';
			impl_fault = 20;
			break;
		case 0x02:	//Phase B action
			fault_val[3] = 'B';
			fault_val[4] = '\0';
			impl_fault = 19;
			break;
		case 0x03:	//Phase B and C action
			fault_val[3] = 'B';
			fault_val[4] = 'C';
			fault_val[5] = '\0';
			impl_fault = 22;
			break;
		case 0x04:	//Phase A action
			fault_val[3] = 'A';
			fault_val[4] = '\0';
			impl_fault = 18;
			break;
		case 0x05:	//Phase A and C action
			fault_val[3] = 'A';
			fault_val[4] = 'C';
			fault_val[5] = '\0';
			impl_fault = 23;
			break;
		case 0x06:	//Phase A and B action
			fault_val[3] = 'A';
			fault_val[4] = 'B';
			fault_val[5] = '\0';
			impl_fault = 21;
			break;
		case 0x07:	//All three went
			fault_val[3] = 'A';
			fault_val[4] = 'B';
			fault_val[5] = 'C';
			fault_val[6] = '\0';
			impl_fault = 24;
			break;
		default:
			GL_THROW("switch:%s supposedly opened, but doesn't register the right phases",obj->name);
			//Defined above
		}//End switch

		if (event_schedule != NULL)	//Function was mapped - go for it!
		{
			//Call the function
			if (fault_mode == true)	//Restoration - make fail time in the past
			{
				if (mean_repair_time != 0)
					temp_time = 50 + (TIMESTAMP)(mean_repair_time);
				else
					temp_time = 50;

				//Call function
				result_val = ((int (*)(OBJECT *, OBJECT *, char *, TIMESTAMP, TIMESTAMP, int, bool))(*event_schedule))(*eventgen_obj,obj,fault_val,(t0-50),temp_time,impl_fault,fault_mode);
			}
			else	//Failing - normal
			{
				result_val = ((int (*)(OBJECT *, OBJECT *, char *, TIMESTAMP, TIMESTAMP, int, bool))(*event_schedule))(*eventgen_obj,obj,fault_val,t0,TS_NEVER,-1,fault_mode);
			}

			//Make sure it worked
			if (result_val != 1)
			{
				GL_THROW("Attempt to change switch:%s failed in a reliability manner",obj->name);
				/*  TROUBLESHOOT
				While attempting to propagate a changed switch's impacts, an error was encountered.  Please
				try again.  If the error persists, please submit your code and a bug report via the trac website.
				*/
			}

			//Ensure we don't go anywhere yet
			t2 = t0;

		}	//End fault object present
		else	//No object, just fail us out - save the iterations
		{
			gl_warning("No fault_check object present - Newton-Raphson solver may fail!");
			/*  TROUBLESHOOT
			A switch changed and created an open link.  If the system is not meshed, the Newton-Raphson
			solver will likely fail.  Theoretically, this should be a quick fail due to a singular matrix.
			However, the system occasionally gets stuck and will exhaust iteration cycles before continuing.
			If the fuse is blowing and the NR solver still iterates for a long time, this may be the case.
			*/
		}
	}//End NR call

	if (t2==TS_NEVER)
		return(t2);
	else
		return(-t2);	//Soft limit it
}
Ejemplo n.º 8
0
//Function to change sectionalizer states - just call underlying switch routine
EXPORT double change_sectionalizer_state(OBJECT *thisobj, unsigned char phase_change, bool state)
{
	double count_values, recloser_count;
	char desA, desB, desC;
	switch_object *swtchobj;
	sectionalizer *sectionobj;
	FUNCTIONADDR funadd = NULL;
	bool perform_operation;

	//Init
	count_values = 0.0;

	if (state == false)	//Check routine to find a recloser
	{
		//Map us up as a proper object
		sectionobj = OBJECTDATA(thisobj,sectionalizer);

		//Call to see if a recloser is present
		if (fault_check_object == NULL)
		{
			GL_THROW("Reliability call made without fault_check object present!");
			/*  TROUBLESHOOT
			A sectionalizer attempted to call a reliability-related function.  However, this function
			requires a fault_check object to be present in the system.  Please add the appropriate object.
			If the error persists, please submit your code and a bug report via the trac website.
			*/
		}

		//map the function
		funadd = (FUNCTIONADDR)(gl_get_function(fault_check_object,"handle_sectionalizer"));

		//make sure it worked
		if (funadd==NULL)
		{
			GL_THROW("Failed to find sectionalizer checking method on object %s",fault_check_object->name);
			/*  TROUBLESHOOT
			While attempting to find the fault check method, or its subfunction to handle sectionalizers,
			an error was encountered.  Please ensure a proper fault_check object is present in the system.
			If the error persists, please submit your code and a bug report via the trac website.
			*/
		}

		//Function call
		recloser_count = ((double (*)(OBJECT *, int))(*funadd))(fault_check_object,sectionobj->NR_branch_reference);

		if (recloser_count == 0.0)	//Failed :(
		{
			GL_THROW("Failed to handle sectionalizer check on %s",thisobj->name);
			/*  TROUBLESHOOT
			While attempting to handle sectionalizer actions for the specified device, an error occurred.  Please
			try again and ensure all parameters are correct.  If the error persists, please submit your code and a
			bug report via the trac website.
			*/
		}

		//Error check
		if (recloser_count < 0)	//No recloser found, get us out of here
		{
			count_values = recloser_count;
			perform_operation = false;	//Flag as no change allowed
		}
		else	//Recloser found - pass the count out and flag a change allowed
		{
			perform_operation = true;
			count_values = recloser_count;
		}
	}
	else	//No check required for reconneciton
	{
		perform_operation = true;	//Flag operation as ok
		count_values = 1.0;			//Arbitrary non-zero value so fail check doesn't go off
	}

	if (perform_operation==true)	//Either is a "replace" or a recloser was found - operation is a go
	{
		//Map the switch
		swtchobj = OBJECTDATA(thisobj,switch_object);

		if (swtchobj->switch_banked_mode == switch_object::BANKED_SW)	//Banked mode - all become "state", just cause
		{
			swtchobj->set_switch(state);
		}
		else	//Must be individual
		{
			//Figure out what we need to call
			if ((phase_change & 0x04) == 0x04)
			{
				if (state==true)
					desA=1;	//Close it
				else
					desA=0;	//Open it
			}
			else	//Nope, no A
				desA=2;		//I don't care

			//Phase B
			if ((phase_change & 0x02) == 0x02)
			{
				if (state==true)
					desB=1;	//Close it
				else
					desB=0;	//Open it
			}
			else	//Nope, no B
				desB=2;		//I don't care

			//Phase C
			if ((phase_change & 0x01) == 0x01)
			{
				if (state==true)
					desC=1;	//Close it
				else
					desC=0;	//Open it
			}
			else	//Nope, no A
				desC=2;		//I don't care

			//Perform the switching!
			swtchobj->set_switch_full(desA,desB,desC);
		}//End individual adjustments
	}

	return count_values;
}