int waterheater::create() { int res = residential_enduse::create(); // initialize public values tank_volume = 50.0; tank_UA = 0.0; tank_diameter = 1.5; // All heaters are 1.5-ft wide for now... Tinlet = 60.0; // default set here, but published by the model for users to set this value water_demand = 0.0; // in gpm heating_element_capacity = 0.0; heat_needed = FALSE; location = GARAGE; heat_mode = ELECTRIC; tank_setpoint = 0.0; thermostat_deadband = 0.0; is_waterheater_on = 0; // power_kw = complex(0,0); Tw = 0.0; // location...mostly in garage, a few inside... location = gl_random_bernoulli(RNGSTATE,0.80) ? GARAGE : INSIDE; // initialize randomly distributed values tank_setpoint = clip(gl_random_normal(RNGSTATE,130,10),100,160); thermostat_deadband = clip(gl_random_normal(RNGSTATE,5, 1),1,10); /* initialize water tank thermostat */ tank_setpoint = gl_random_normal(RNGSTATE,125,5); if (tank_setpoint<90) tank_setpoint = 90; if (tank_setpoint>160) tank_setpoint = 160; /* initialize water tank deadband */ thermostat_deadband = fabs(gl_random_normal(RNGSTATE,2,1))+1; if (thermostat_deadband>10) thermostat_deadband = 10; tank_UA = clip(gl_random_normal(RNGSTATE,2.0, 0.20),0.1,10) * tank_volume/50; if(tank_UA <= 1.0) tank_UA = 2.0; // "R-13" // name of enduse load.name = oclass->name; load.breaker_amps = 30; load.config = EUC_IS220; load.power_fraction = 0.0; load.impedance_fraction = 1.0; load.heatgain_fraction = 0.0; /* power has no effect on heat loss */ gas_fan_power = -1.0; gas_standby_power = -1.0; return res; }
void climate::update_forecasts(TIMESTAMP t0) { static const int Nh = 72; /* number of hours in forecast */ static const int dt = 3600; /* number of seconds in forecast interval */ #if 0 OBJECT *my = OBJECTHDR(this); FORECAST *fc; for ( fc=my->forecast ; fc!=NULL ; fc=fc->next ) { /* don't update forecasts that are already current */ if ( t0/dt==(fc->starttime/dt) ) continue; int h, hoy; double t[Nh]; for ( h=0 ; h<Nh ; h++ ) { if (h==0) { /* actual values */ DATETIME ts; if ( !gl_localtime(t0+(h*dt),&ts) ) { GL_THROW("climate::sync -- unable to resolve localtime!"); } int doy = sa->day_of_yr(ts.month,ts.day); hoy = (doy - 1) * 24 + (ts.hour); } else if ( hoy==8760 ) hoy = 0; else hoy++; /* this is an extremely naive model of forecast error */ t[h] = tmy[hoy].temp + gl_random_normal(RNGSTATE,0,h/10.0); } gl_forecast_save(fc,t0,dt,Nh,t); #ifdef NEVER char buffer[1024]; int len = sprintf(buffer,"%d",fc->starttime); for ( h=3; h<72; h+=3 ) len += sprintf(buffer+len,",%.1f",fc->values[h]); printf("%s\n",buffer); #endif } #endif }
TIMESTAMP fuse::sync(TIMESTAMP t0) { link::sync(t0); double M = I.Mag()/SetCurrent; switch (State) { case FS_GOOD: Y=100; // fuse is good if (M>1) { // compute fuse time double t = TimeConstant * (SetBase+SetScale/(pow(M,SetCurve)-1)); TIMESTAMP t1 = Tstate + (TIMESTAMP)(t*TS_SECOND); if (t1<=t0) { // fuse blows now State=FS_BLOWN; Tstate = t0; Treset = t0 + (TIMESTAMP)(gl_random_normal(TresetAvg,TresetStd)*TS_SECOND); return TS_NEVER; } else // fuse blows soon { Tstate = t1; return t1; } } else if (M<=1) { // fuse doesn't blow; reset timer /// @todo it would be better to model how much damage the fuse incurred (network, low priority) (ticket #128) Tstate = t0; return TS_NEVER; } break; case FS_BLOWN: Y=0; // fuse is gone if (Treset<=t0) { Tstate = t0; State = FS_GOOD; } break; case FS_FAULT: break; default: break; } return TS_NEVER; }
double refrigerator::update_refrigerator_state(double dt0,TIMESTAMP t1) { OBJECT *hdr = OBJECTHDR(this); // accumulate the energy energy_used += refrigerator_power*dt0; if(cycle_time>0) { cycle_time -= dt0; } if(defrostDelayed>0) { defrostDelayed -= dt0; } if(defrostDelayed<=0){ if(DC_TIMED==defrost_criterion){ run_defrost = true; } else if(DC_COMPRESSOR_TIME==defrost_criterion && total_compressor_time>=compressor_defrost_time){ run_defrost = true; total_compressor_time = 0; check_defrost = false; } else if(no_of_defrost>0 && DC_DOOR_OPENINGS==defrost_criterion){ run_defrost = true; FF_Door_Openings = 0; check_defrost = false; } } else{ if(DC_TIMED==defrost_criterion){ check_defrost = true; } else if(DC_COMPRESSOR_TIME==defrost_criterion && total_compressor_time>=compressor_defrost_time){ check_defrost = true; } else if(no_of_defrost>0 && DC_DOOR_OPENINGS==defrost_criterion){ check_defrost = true; } } if(long_compressor_cycle_time>0) { long_compressor_cycle_time -= dt0; } if (dr_mode_double == 0) dr_mode = DM_UNKNOWN; else if (dr_mode_double == 1) dr_mode = DM_LOW; else if (dr_mode_double == 2) dr_mode = DM_NORMAL; else if (dr_mode_double == 3) dr_mode = DM_HIGH; else if (dr_mode_double == 4) dr_mode = DM_CRITICAL; else dr_mode = DM_UNKNOWN; if(door_return_time > 0){ door_return_time = door_return_time - dt0; } if(door_next_open_time > 0){ door_next_open_time = door_next_open_time - dt0; } if(door_return_time<=0 && true==door_open){ door_return_time = 0; door_open = false; } if(door_next_open_time<=0 && hourly_door_opening>0){ door_next_open_time = 0; door_open = true; FF_Door_Openings++; door_return_time += ceil(gl_random_uniform(&hdr->rng_state,0, door_open_time)); door_energy_calc = true; hourly_door_opening--; if(hourly_door_opening > 0){ door_next_open_time = int(gl_random_uniform(&hdr->rng_state,0,(3600-(t1-start_time)%3600))); // next_door_openings[hourly_door_opening-1] - ((t1-start_time)%3600); door_to_open = true; } else{ door_to_open = false; } check_DO = FF_Door_Openings%DO_Thershold; if(check_DO==0){ no_of_defrost++; } } if(((t1-start_time)%3600)==0 && start_time>0) { double temp_hourly_door_opening = (door_opening_criterion*daily_door_opening) - floor(door_opening_criterion*daily_door_opening); if(temp_hourly_door_opening >= 0.5){ hourly_door_opening = ceil(door_opening_criterion*daily_door_opening); } else{ hourly_door_opening = floor(door_opening_criterion*daily_door_opening); } hourly_door_opening = floor(gl_random_normal(&hdr->rng_state,hourly_door_opening, ((hourly_door_opening)/3))); //Clip the hourly door openings if(hourly_door_opening<0){ hourly_door_opening = 0; } else if(hourly_door_opening>2*hourly_door_opening){ hourly_door_opening = 2*hourly_door_opening; } if(hourly_door_opening > long_compressor_cycle_threshold*daily_door_opening) { long_compressor_cycle_due = true; long_compressor_cycle_time = int(gl_random_uniform(&hdr->rng_state,0,(3600))); } if(hourly_door_opening>0){ door_to_open = true; door_next_open_time = int(gl_random_uniform(&hdr->rng_state,0,(3600))); } else{ door_to_open = false; } } double dt1 = 0; switch(state){ case RS_DEFROST: if ((energy_used >= energy_needed || cycle_time <= 0)) { state = RS_COMPRESSSOR_ON_LONG; refrigerator_power = long_compressor_cycle_power; energy_needed = long_compressor_cycle_energy; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); } else { refrigerator_power = defrost_power; } break; case RS_COMPRESSSOR_ON_NORMAL: if(run_defrost==true) { state = RS_DEFROST; refrigerator_power = defrost_power; energy_needed = defrost_energy; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); run_defrost=false; no_of_defrost--; defrostDelayed = delay_defrost_time; } else if ((energy_used >= energy_needed || cycle_time <= 0)) { state = RS_COMPRESSSOR_OFF_NORMAL; refrigerator_power = compressor_off_normal_power; energy_needed = compressor_off_normal_energy; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); //new_running_state = true; } else { refrigerator_power = compressor_on_normal_power; total_compressor_time += dt0; if(door_energy_calc==true){ door_energy_calc = false; energy_needed += door_return_time*refrigerator_power; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); } } break; case RS_COMPRESSSOR_ON_LONG: if(run_defrost==true) { state = RS_DEFROST; refrigerator_power = defrost_power; energy_needed = defrost_energy; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); run_defrost=false; no_of_defrost--; defrostDelayed = delay_defrost_time; } else if ((energy_used >= energy_needed || cycle_time <= 0)) { state = RS_COMPRESSSOR_OFF_NORMAL; refrigerator_power = compressor_off_normal_power; energy_needed = compressor_off_normal_energy; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); //new_running_state = true; } else { refrigerator_power = long_compressor_cycle_power; if(door_energy_calc==true){ door_energy_calc = false; energy_needed += door_return_time*refrigerator_power; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); } } break; case RS_COMPRESSSOR_OFF_NORMAL: if(run_defrost==true) { state = RS_DEFROST; refrigerator_power = defrost_power; energy_needed = defrost_energy; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); run_defrost=false; no_of_defrost--; defrostDelayed = delay_defrost_time; } else if ((energy_used >= energy_needed || cycle_time <= 0)) { if(long_compressor_cycle_due==true && long_compressor_cycle_time<=0) { state = RS_COMPRESSSOR_ON_LONG; refrigerator_power = long_compressor_cycle_power; energy_needed = long_compressor_cycle_energy; long_compressor_cycle_due=false; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); } else{ state = RS_COMPRESSSOR_ON_NORMAL; refrigerator_power = compressor_on_normal_power; energy_needed = compressor_on_normal_energy; energy_used = 0; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); } } else { refrigerator_power = compressor_off_normal_power; if(door_energy_calc==true){ door_energy_calc = false; energy_needed -= door_return_time*compressor_off_normal_power; cycle_time = ceil((energy_needed - energy_used)/refrigerator_power); if(cycle_time<0) cycle_time = 0; } } break; } double posted_power = refrigerator_power; //*************************** if(door_open==true) { posted_power += door_opening_power; } //*************************** if(check_icemaking == true) { posted_power += icemaking_power; icemaker_running = true; return_time = 60-dt0; if(0==((t1-start_time)%60) || return_time<=0){ ice_making_no--; if(ice_making_no == 0) { check_icemaking = false; } return_time = 60; } } else { if(((t1-start_time)%60)==0) { ice_making = double(gl_random_uniform(&hdr->rng_state,0,1)); if(ice_making <=ice_making_probability) { check_icemaking = true; icemaker_running = true; // ice_making_no = gl_random_sampled(3,ice_making_time); ice_making_no = 1; posted_power += icemaking_power; return_time = 60; ice_making_no--; if(ice_making_no == 0) { check_icemaking = false; } } else { icemaker_running = false; return_time = 60; } } else { icemaker_running = false; } } load.power.SetPowerFactor(posted_power/1000, load.power_factor); load.admittance = complex(0,0,J); load.current = complex(0,0,J); if(true==door_open && true==door_to_open) { door_time = door_return_time<door_next_open_time?door_return_time:door_next_open_time; } else if(true==door_to_open) { door_time = door_next_open_time; } else if(true==door_open){ door_time = door_return_time; } else if(start_time>0) { door_time = (3600 - ((t1-start_time)%3600)); } if(0.0==return_time) { dt1 = cycle_time>door_time?door_time:cycle_time; } else { if(cycle_time>return_time) if(return_time>door_time) if(door_time>long_compressor_cycle_time) dt1 = long_compressor_cycle_time; else dt1 = door_time; else if(return_time>long_compressor_cycle_time) dt1 = long_compressor_cycle_time; else dt1 = return_time; else if(cycle_time>door_time) if(door_time>long_compressor_cycle_time) dt1 = long_compressor_cycle_time; else dt1 = door_time; else if(cycle_time>long_compressor_cycle_time) dt1 = long_compressor_cycle_time; else dt1 = cycle_time; } if(check_defrost == true){ if(dt1 > defrostDelayed){ dt1 = defrostDelayed; } } load.total = load.power + load.current + load.admittance; total_power = (load.power.Re() + (load.current.Re() + load.admittance.Re()*load.voltage_factor)*load.voltage_factor); last_dr_mode = dr_mode; if ((dt1 > 0) && (dt1 < 1)){ dt1 = 1; } return dt1; }
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; }
int range::create() { OBJECT *hdr = OBJECTHDR(this); int res = residential_enduse::create(); // initialize public values oven_diameter = 1.5; // All heaters are 1.5-ft wide for now... Tinlet = 60.0; // default set here, but published by the model for users to set this value oven_demand = 0.0; heat_needed = FALSE; heat_mode = ELECTRIC; is_range_on = 0; Tw = 0.0; time_oven_operation = 0; oven_check = false; remainon = false; cooktop_check = false; time_cooktop_operation = 0; oven_volume = 5; heating_element_capacity = 1; oven_setpoint = 100; Tw = 70; thermostat_deadband = 8; location = INSIDE; oven_UA = 2.9; oven_demand = 0.01; food_density = 5; specificheat_food = 1; time_oven_setting = 3600; enduse_queue_oven = 0.85; // location...mostly in garage, a few inside... location = gl_random_bernoulli(&hdr->rng_state,0.80) ? GARAGE : INSIDE; // initialize randomly distributed values oven_setpoint = clip(gl_random_normal(&hdr->rng_state,130,10),100,160); thermostat_deadband = clip(gl_random_normal(&hdr->rng_state,5, 1),1,10); /* initialize oven thermostat */ oven_setpoint = gl_random_normal(&hdr->rng_state,125,5); if (oven_setpoint<90) oven_setpoint = 90; if (oven_setpoint>160) oven_setpoint = 160; /* initialize oven deadband */ thermostat_deadband = fabs(gl_random_normal(&hdr->rng_state,2,1))+1; if (thermostat_deadband>10) thermostat_deadband = 10; oven_UA = clip(gl_random_normal(&hdr->rng_state,2.0, 0.20),0.1,10) * oven_volume/50; if(oven_UA <= 1.0) oven_UA = 2.0; // "R-13" // name of enduse load.name = oclass->name; load.breaker_amps = 30; load.config = EUC_IS220; load.power_fraction = 0.0; load.impedance_fraction = 1.0; load.heatgain_fraction = 0.0; /* power has no effect on heat loss */ state_cooktop = CT_STOPPED; TSTAT_PRECISION= 0.01; cooktop_energy_baseline = 0.5; cooktop_coil_power[0] = 2; cooktop_coil_power[1] = 1.0; cooktop_coil_power[2] = 1.7; cooktop_interval[0] = 240; cooktop_interval[1] = 900; cooktop_interval[2] = 120; time_cooktop_setting = 2000; enduse_queue_cooktop = 0.99; return res; }