Ejemplo n.º 1
0
int csv_reader::read_header(char *line){
	struct cmnlist {
		char *name;
		PROPERTY *column;
		struct cmnlist *next;
	};
	char buffer[1024];
	int index = 0, start_idx = 0;
	int done = 0;
	int i = 0;
	PROPERTY *prop = 0;
	struct cmnlist *first = 0, *last = 0, *temp = 0;

	// expected format: x,y,z\n

	memset(buffer, 0, 1024);
	strncpy(buffer, line, 1023);

	// split column header list
	while(index < 1024 && 0 == done){
		while(buffer[index] != 0 && buffer[index] != ',' && buffer[index] != '\n' && buffer[index] != '\r' && buffer[index] != '#'){
			++index;
		}
		if(buffer[index] == ','){
			buffer[index] = 0;
			++index;
		}
		if(buffer[index] == '\n' || buffer[index] == '\r' || buffer[index] == '#'){
			buffer[index] = 0;
		}

		temp = (struct cmnlist *)malloc(sizeof(struct cmnlist));
		temp->name = buffer+start_idx;
		temp->column = prop;
		temp->next = 0;

		start_idx = index;
		++column_ct;

		if(first == 0){
			first = last = temp;
		} else {
			last->next = temp;
			last = temp;
		}

		if(buffer[index] == 0 || buffer[index] == '\n' || buffer[index] == '\r'){
			done = 1;
			break;
		}
	}

	//	find properties for each column header
	temp = first;
	columns = (PROPERTY **)malloc(sizeof(PROPERTY *) * (size_t)column_ct);
	while(temp != 0 && i < column_ct){
		temp->column = gl_find_property(weather::oclass, temp->name);
		if(temp->column == 0){
			gl_error("csv_reader::read_header ~ unable to find column property \'%s\''", temp->name);
			/* TROUBLESHOOT
				The specified property in the header was not found published by the weather
				class.  Please check the column header input and re-run GridLAB-D.
			*/
			return 0;
		}
		columns[i] = temp->column;
		temp = temp->next;
		++i;
	}
	return 1;
}
Ejemplo n.º 2
0
int climate::init(OBJECT *parent)
{
	char *dot = 0;
	OBJECT *obj=OBJECTHDR(this);
	double meter_to_feet = 1.0;
	double tz_num_offset;

	reader_type = RT_NONE;

	// ignore "" files ~ manual climate control is a feature
	if (strcmp(tmyfile,"")==0)
		return 1;

	// open access to the TMY file
	char *found_file;
	found_file = gl_findfile(tmyfile, NULL, FF_READ);
	if (found_file == NULL) // TODO: get proper values for solar
	{
		gl_error("weather file '%s' access failed", tmyfile);
		return 0;
	}

	
	//dot = strchr(tmyfile, '.');
	//while(strchr(dot+1, '.')){ /* init time, doesn't have to be fast -MH */
	//	dot = strchr(dot, '.');
	//}
	if(strstr(tmyfile, ".tmy2") || strstr(tmyfile,".tmy")){
		reader_type = RT_TMY2;
	} else if(strstr(tmyfile, ".csv")){
		reader_type = RT_CSV;
	} else {
		gl_warning("climate: unrecognized filetype, assuming TMY2");
	}

	if(reader_type == RT_CSV){
		// may or may not have an object,
		// have not called open()
		int rv = 0;

		if(reader == NULL){
			csv_reader *creader = new csv_reader();
			reader_hndl = creader;
			rv = creader->open(found_file);
//			creader->get_data(t0, &temperature, &humidity, &solar_direct, &solar_diffuse, &wind_speed, &rainfall, &snowdepth);
		} else {
			csv_reader *my = OBJECTDATA(reader,csv_reader);
			reader_hndl = my;
			rv = my->open(my->filename);
//			my->get_data(t0, &temperature, &humidity, &solar_direct, &solar_diffuse, &wind_speed, &rainfall, &snowdepth);
			//Pull timezone information
			tz_num_offset = my->tz_numval;
			tz_offset_val = tz_num_offset;

			//Copy latitude and longitude information from CSV reader
			obj->latitude = reader->latitude;
			obj->longitude = reader->longitude;

			//CSV Reader validity check
			if (fabs(obj->latitude) > 90)
			{
				gl_error("climate:%s - Latitude is outside +/-90!",obj->name);
				//Defined below
				return 0;
			}

			if (fabs(obj->longitude) > 180)
			{
				gl_error("climate:%s - Longitude is outside +/-180!",obj->name);
				//Defined below
				return 0;
			}

			//Generic warning about southern hemisphere and Duffie-Beckman usage
			if (obj->latitude<0)
			{
				gl_warning("climate:%s - Southern hemisphere solar position model may have issues",obj->name);
				/*  TROUBLESHOOT
				The default solar position model was built around a northern hemisphere assumption.  As such,
				it doesn't always produce completely accurate results for southern hemisphere locations.  Calculated
				insolation values are approximately correct, but may show discrepancies against measured data.  If
				this climate is associated with a solar object, use the SOLAR_TILT_MODEL SOLPOS to ensure proper
				results (this warning will still pop up).
				*/
			}

			//Set the timezone offset - stolen from TMY code below
			tz_meridian =  15 * tz_num_offset;//std_meridians[-file.tz_offset-5];
		}

		return rv;
	}

	// implicit if(reader_type == RT_TMY2) ~ do the following
	if( file.open(found_file) < 3 ){
		gl_error("climate::init() -- weather file header improperly formed");
		return 0;
	}
	
	// begin parsing the TMY file
	int line=0;
	tmy = (TMYDATA*)malloc(sizeof(TMYDATA)*8760);
	if (tmy==NULL)
	{
		gl_error("TMY buffer allocation failed");
		return 0;
	}

	int month, day, hour;//, year;
	double dnr,dhr,ghr,wspeed,precip,snowdepth,pressure,extra_dni;
	//char cty[50];
	//char st[3];
	int lat_deg,lat_min,long_deg,long_min;
	/* The city/state data isn't used anywhere.  -mhauer */
	//file.header_info(cty,st,&lat_deg,&lat_min,&long_deg,&long_min);
	file.header_info(NULL,NULL,&lat_deg,&lat_min,&long_deg,&long_min);

	//Handle hemispheres
	if (lat_deg<0)
		obj->latitude = (double)lat_deg - (((double)lat_min) / 60);
	else
		obj->latitude = (double)lat_deg + (((double)lat_min) / 60);

	if (long_deg<0)
		obj->longitude = (double)long_deg - (((double)long_min) / 60);
	else
		obj->longitude = (double)long_deg + (((double)long_min) / 60);

	//Generic check for TMY files
	if (fabs(obj->latitude) > 90)
	{
		gl_error("climate:%s - Latitude is outside +/-90!",obj->name);
		/*  TROUBLESHOOT
		The value read from the weather data indicates a latitude of greater
		than 90 or less than -90 degrees.  This is not a valid value.  Please specify
		the latitude in this range, with positive values representing the northern hemisphere
		and negative values representing the southern hemisphere.
		*/
		return 0;
	}

	if (fabs(obj->longitude) > 180)
	{
		gl_error("climate:%s - Longitude is outside +/-180!",obj->name);
		/*  TROUBLESHOOT
		The value read from the weather data indicates a longitude of greater
		than 180 or less than -180 degrees.  This is not a valid value.  Please specify
		the longitude in this range, with positive values representing the eastern hemisphere
		and negative values representing the western hemisphere.
		*/
		return 0;
	}

	//Generic warning about southern hemisphere and Duffie-Beckman usage
	if (obj->latitude<0)
	{
		gl_warning("climate:%s - Southern hemisphere solar position model may have issues",obj->name);
		//Defined above
	}

	if(0 == gl_convert("m", "ft", &meter_to_feet)){
		gl_error("climate::init unable to gl_convert() 'm' to 'ft'!");
		return 0;
	}
	file.elevation *= meter_to_feet;
	tz_meridian =  15 * file.tz_offset;//std_meridians[-file.tz_offset-5];
	tz_offset_val = file.tz_offset;
	while (line<8760 && file.next())
	{

		file.read_data(&dnr,&dhr,&ghr,&temperature,&humidity,&month,&day,&hour,&wspeed,&precip,&snowdepth,&pressure,&extra_dni);

		int doy = sa->day_of_yr(month,day);
		int hoy = (doy - 1) * 24 + (hour-1);
		if (hoy>=0 && hoy<8760){
			// pre-conversion of solar data from W/m^2 to W/sf
			if(0 == gl_convert("W/m^2", "W/sf", &(dnr))){
				gl_error("climate::init unable to gl_convert() 'W/m^2' to 'W/sf'!");
				return 0;
			}
			if(0 == gl_convert("W/m^2", "W/sf", &(dhr))){
				gl_error("climate::init unable to gl_convert() 'W/m^2' to 'W/sf'!");
				return 0;
			}
			if(0 == gl_convert("W/m^2", "W/sf", &(ghr))){
				gl_error("climate::init unable to gl_convert() 'W/m^2' to 'W/sf'!");
				return 0;
			}
			if(0 == gl_convert("W/m^2", "W/sf", &(extra_dni))){
				gl_error("climate::init unable to gl_convert() 'W/m^2' to 'W/sf'!");
				return 0;
			}
			if(0 == gl_convert("mps", "mph", &(wspeed))){
				gl_error("climate::init unable to gl_convert() 'm/s' to 'miles/h'!");
				return 0;
			}
			tmy[hoy].temp_raw = temperature;
			tmy[hoy].temp = temperature;
			// post-conversion of copy of temperature from C to F
			if(0 == gl_convert("degC", "degF", &(tmy[hoy].temp))){
				gl_error("climate::init unable to gl_convert() 'degC' to 'degF'!");
				return 0;
			}
			tmy[hoy].windspeed=wspeed;
			tmy[hoy].rh = humidity;
			tmy[hoy].dnr = dnr;
			tmy[hoy].dhr = dhr;
			tmy[hoy].ghr = ghr;
			tmy[hoy].rainfall = precip;
			tmy[hoy].snowdepth = snowdepth;
			tmy[hoy].solar_raw = dnr;

			tmy[hoy].direct_normal_extra = extra_dni;
			tmy[hoy].pressure = pressure;
			
			// calculate the solar radiation - hour on here may need a -1 application (hour-1) - unsure how TMYs really code things
			double sol_time = sa->solar_time((double)hour,doy,RAD(tz_meridian),RAD(obj->longitude));
			double sol_rad = 0.0;

			tmy[hoy].solar_elevation = sa->altitude(doy, RAD(obj->latitude), sol_time);
			tmy[hoy].solar_azimuth = sa->azimuth(doy, RAD(obj->latitude), sol_time);

			for(COMPASS_PTS c_point = CP_H; c_point < CP_LAST;c_point=COMPASS_PTS(c_point+1)){
				if(c_point == CP_H)
					sol_rad = file.calc_solar(CP_E,doy,RAD(obj->latitude),sol_time,dnr,dhr,ghr,ground_reflectivity,0.0);//(double)dnr * cos_incident + dhr;
				else
					sol_rad = file.calc_solar(c_point,doy,RAD(obj->latitude),sol_time,dnr,dhr,ghr,ground_reflectivity);//(double)dnr * cos_incident + dhr;
				/* TMY2 solar radiation data is in Watt-hours per square meter. */
				tmy[hoy].solar[c_point] = sol_rad;

				/* track records */
				if (sol_rad>record.solar || record.solar==0) record.solar = sol_rad;
				if (tmy[hoy].temp>record.high || record.high==0)
				{
					record.high = tmy[hoy].temp;
					record.high_day = doy;
				}
				if (tmy[hoy].temp<record.low || record.low==0)
				{
					record.low = tmy[hoy].temp;
					record.low_day = doy;
				}
			}

		}
		else
			gl_error("%s(%d): day %d, hour %d is out of allowed range 0-8759 hours", tmyfile,line,day,hour);

		line++;
	}
	file.close();

	/* initialize climate to starttime */
	presync(gl_globalclock);

	/* enable forecasting if specified */
#if 0
	if ( strcmp(forecast,"")!=0 && gl_forecast_create(obj,"")==NULL )
	{
		char buf[1024];
		gl_error("%s: forecast '%s' is not valid", gl_name(obj,buf,sizeof(buf))?buf:"(object?)", forecast);
		return 0;
	}
	else if (obj->forecast)
	{	/* initialize the forecast data entity */
		FORECAST *fc = obj->forecast;
		fc->propref = gl_find_property(obj->oclass,"temperature");
		gl_forecast_save(fc,obj->clock,3600,0,NULL);
		obj->flags |= OF_FORECAST;
	}
#endif
	return 1;
}
Ejemplo n.º 3
0
int csv_reader::read_prop(char *line){ // already pulled the '$' off the front
	OBJECT *my = OBJECTHDR(this);
	char *split = strchr(line, '=');
	char propstr[256], valstr[256];
	PROPERTY *prop = 0;

	if(split == NULL){
		gl_error("csv_reader::read_prop ~ missing \'=\' seperator");
		/* TROUBLESHOOT
			Property lines must have the property name and property value seperated by an
			equals sign.  Please correct the CSV file and re-run GridLAB-D.
		*/
		return 0;
	}

	if(2 != sscanf(line, "%[^=]=%[^\n#]", propstr, valstr)){
		gl_error("csv_reader::read_prop ~ error reading property & value");
		/* TROUBLESHOOT
			The line was not read properly by the parser.  Property lines must be of the format
			"prop=val".  Please review the CSV file and re-run GridLAB-D.
		*/
		return 0;
	}
	
	prop = gl_find_property(oclass, propstr);
	if(prop == 0){
		gl_error("csv_reader::read_prop ~ unrecognized csv_reader property \'%s\'", propstr);
		/* TROUBLESHOOT
			The property specified within the CSV file is not published by csv_reader.
			Please review the list of published variables, correct the CSV file, and
			re-run GridLAB-D.
		*/
		return 0;
	}

	// Windows pointers on my Dell Precision 390 are apparently ulli -MH
	/* BAD BAD BAD!  cannot use 'my' with this, it may not have an associate object header!!! */
//	if(0 == gl_set_value(my, (void *)((unsigned long long int)this + (unsigned long long int)prop->addr), valstr, prop)){
//		gl_error("csv_reader::read_prop ~ unable to set property \'%s\' to \'%s\'", propstr, valstr);
//		return 0;
//	}	
	void *addr = (void *)((unsigned long long int)this + (unsigned long long int)prop->addr);
	if(prop->ptype == PT_double){
		if(1 != sscanf(valstr, "%lg", addr)){
			gl_error("csv_reader::read_prop ~ unable to set property \'%s\' to \'%s\'", propstr, valstr);
			/* TROUBLESHOOT
				The double parser was not able to convert the property value into a number.  Please
				review the input line for non-numeric characters and re-run GridLAB-D.
			*/
			return 0;
		}
	} else if(prop->ptype == PT_char32){
		strncpy((char *)addr, valstr, 32);
	} else {
		gl_error("csv_reader::read_prop ~ unable to convert property \'%s\' due to type restrictions", propstr);
		/* TROUBLESHOOTING
			This is a programming problem.  The property parser within the csv_reader is only able to
			properly handle char32 and double properties.  Please contact [email protected] for
			technical support.
		 */
		return 0;
	}
	return 1;
}
Ejemplo n.º 4
0
/**
* Object initialization is called once after all object have been created
*
* @param parent a pointer to this object's parent
* @return 1 on success, 0 on error
*/
int histogram::init(OBJECT *parent)
{
	PROPERTY *prop = NULL;
	OBJECT *obj = OBJECTHDR(this);
	char tprop[64], tpart[8];
	int e = 0;
	TAPEFUNCS *tf = 0;
	tprop[0]=0;
	tpart[0] = 0;

	if(parent == NULL) /* better have a group... */
	{
		OBJECT *group_obj = NULL;
		CLASS *oclass = NULL;
		if(group[0] == NULL){
			gl_error("Histogram has no parent and no group");
			return 0;
		}
		group_list = gl_find_objects(FL_GROUP,group.get_string());
		if(group_list == NULL){
			gl_error("Histogram group could not be parsed");
			return 0;
		}
		if(group_list->hit_count < 1){
			gl_error("Histogram group is an empty set");
			return 0;
		}
		/* non-empty set */

		/* parse complex part of property */
		test_for_complex(tprop, tpart);
	
		while(group_obj = gl_find_next(group_list, group_obj)){
			prop = gl_find_property(group_obj->oclass, property.get_string());
			if(prop == NULL){
				gl_error("Histogram group is unable to find prop '%s' in class '%s' for group '%s'", property.get_string(), group_obj->oclass->name, group.get_string());
				return 0;
			}
			/* check to see if all the group objects are in the same class, allowing us to cache the target property */
			if (oclass == NULL){
				oclass = group_obj->oclass;
				prop_ptr = prop;
			}
			if(oclass != group_obj->oclass){
				prop_ptr = NULL;
			} 
			
		}
	} else { /* if we have a parent, we only focus on that one object */

		test_for_complex(tprop, tpart);

		prop = gl_find_property(parent->oclass, property.get_string());
		
		if(prop == NULL){
			gl_error("Histogram parent '%s' of class '%s' does not contain property '%s'", parent->name ? parent->name : "(anon)", parent->oclass->name, property.get_string());
			return 0;
		} else {
			prop_ptr = prop; /* saved for later */
		}
	}

	// initialize first timesteps
	if(counting_interval > 0.0)
		next_count = gl_globalclock + counting_interval;
	if(sampling_interval > 0.0)
		next_sample = gl_globalclock + sampling_interval;
	/*
	 *	This will create a uniform partition over the specified range
	 */
	if((bin_count > 0) && (min < max))
	{
		int i=0;
		double range = max - min;
		double step = range/bin_count;
		//throw("Histogram bin_count is temporarily disabled.");
		bin_list = (BIN *)gl_malloc(sizeof(BIN) * bin_count);
		if(bin_list == NULL){
			gl_error("Histogram malloc error: unable to alloc %i * %i bytes for %s", bin_count, sizeof(BIN), obj->name ? obj->name : "(anon. histogram)");
			return 0;
		}
		memset(bin_list, 0, sizeof(BIN) * bin_count);
		for(i = 0; i < bin_count; i++){
			bin_list[i].low_val = min + i * step;
			bin_list[i].high_val = bin_list[i].low_val + step;
			bin_list[i].low_inc = 1;
			bin_list[i].high_inc = 0;
		}
		bin_list[i-1].high_inc = 1;	/* tail value capture */
		binctr = (int *)gl_malloc(sizeof(int) * bin_count);
		memset(binctr, 0, sizeof(int) * bin_count);
	}
	else if (bins[0] != 0)
	/*
	 *	This will parse the bin strings as specified.  The valid basic form is "(a..b)".  Brackets are optional, [ & ] are inclusive.  A dash may replace the '..'.
	 *	If a or b is not present, the bin will fill in a positve/negative infinity.
	 */
	{
		char *cptr = bins;
		char bincpy[1025];
		int i = 0;
		bin_count = 1; /* assume at least one */
		/* would be better to count the number of times strtok succeeds, but this should work -mh */
		//while(*cptr != 0){
		for(cptr = bins; *cptr != 0; ++cptr){
			if(*cptr == ',' && cptr[1] != 0){
				++bin_count;
			}
		//	++cptr;
		}
		bin_list = (BIN *)gl_malloc(sizeof(BIN) * bin_count);
		if(bin_list == NULL){
			gl_error("Histogram malloc error: unable to alloc %i * %i bytes for %s", bin_count, sizeof(BIN), obj->name ? obj->name : "(anon. histogram)");
			return 0;
		}
		memset(bin_list, 0, sizeof(BIN) * bin_count);
		memcpy(bincpy, bins, 1024);
		cptr = strtok(bincpy, ",\t\r\n\0");
		if(prop->ptype == PT_complex || prop->ptype == PT_double || prop->ptype == PT_int16 || prop->ptype == PT_int32 || prop->ptype == PT_int64 || prop->ptype == PT_float || prop->ptype == PT_real){
			for(i = 0; i < bin_count && cptr != NULL; ++i){
				if(parse_bin_val(cptr, bin_list+i) == 0){
					gl_error("Histogram unable to parse \'%s\' in %s", cptr, obj->name ? obj->name : "(unnamed histogram)");
					return 0;
				}
				cptr = strtok(NULL, ",\t\r\n\0"); /* minor efficiency gain to use the incremented pointer from parse_bin */
			}
		} else if (prop->ptype == PT_enumeration || prop->ptype == PT_set){
			for(i = 0; i < bin_count && cptr != NULL; ++i){
				if(parse_bin_enum(cptr, bin_list+i, prop) == 0){
					gl_error("Histogram unable to parse \'%s\' in %s", cptr, obj->name ? obj->name : "(unnamed histogram)");
					return 0;
				}
				cptr = strtok(NULL, ",\t\r\n\0"); /* minor efficiency gain to use the incremented pointer from parse_bin */
			}
		}

		if(i < bin_count){
			gl_error("Histrogram encountered a problem parsing bins for %s", obj->name ? obj->name : "(unnamed histogram)");
			return 0;
		}
		binctr = (int *)malloc(sizeof(int) * bin_count);
		memset(binctr, 0, sizeof(int) * bin_count);
	} else {
		gl_error("Histogram has neither bins or a bin range to work with");
		return 0;
	}

	/* open file ~ copied from recorder.c */
		/* if prefix is omitted (no colons found) */
//	if (sscanf(filename,"%32[^:]:%1024[^:]:%[^:]",ftype,fname,flags)==1)
//	{
		/* filename is file by default */
		strcpy(fname,filename);
//		strcpy(ftype,"file");
//	}
	/* if no filename given */
	if (strcmp(fname,"")==0)

		/* use object name-id as default file name */
		sprintf(fname,"%s-%d.%s",obj->parent->oclass->name,obj->parent->id, ftype.get_string());

	/* if type is file or file is stdin */
	tf = get_ftable(mode);
	if(tf == NULL)
		return 0;
	ops = tf->histogram; /* same mentality as a recorder, 'cept for the header properties */
	if(ops == NULL)
		return 0;
	return ops->open(this, fname, flags);
}