TIMESTAMP node::postsync(TIMESTAMP t0) { OBJECT *hdr = OBJECTHDR(this); node *swing = hdr->parent?OBJECTDATA(hdr->parent,node):this; complex dV(0.0); complex YY = Ys + complex(G,B); // copy values that might get updated while we work on this object complex old_YVs = YVs; #ifdef HYBRID swing->del_inj_residual(this); #endif if (!YY.IsZero() || type==SWING) { switch (type) { case PV: S.Im() = ((~V*(YY*V-old_YVs)).Im()); if (Qmin_MVAR<Qmax_MVAR && S.Im()<Qmin_MVAR) S.Im() = Qmin_MVAR; else if (Qmax_MVAR>Qmin_MVAR && S.Im()>Qmax_MVAR) S.Im() = Qmax_MVAR; //else { complex Vnew = (-(~S/~V) + old_YVs) / YY; Vnew.SetPolar(V.Mag(),Vnew.Arg()); #ifdef HYBRID if (Vstdev>0) { double pr = swing->get_obs_probability(); swing->del_obs_residual(this); dV = Vobs*(1-pr) + (Vnew)*pr - V; V += dV; swing->add_obs_residual(this); } else #endif { dV = Vnew - V; V = Vnew; } break; } /* continue with PQ solution */ case PQ: if (!V.IsZero()) { complex Vnew = (-(~S/~V) + old_YVs) / YY; #ifdef HYBRID if (Vstdev>0) // need to consider observation { double pr = swing->get_obs_probability(); swing->del_obs_residual(this); dV = Vobs*(1-pr) + (Vnew)*pr - V; V += dV; swing->add_obs_residual(this); } else // no observation #endif { dV = (Vnew - V)*acceleration_factor; V += dV; } V.Notation() = A; } break; case SWING: S = ~(~V*(YY*V - YVs)); S.Notation() = J; break; default: /* unknown type fails */ gl_error("invalid bus type"); return TS_ZERO; } } #ifdef HYBRID swing->add_inj_residual(this); #endif #ifdef _DEBUG // node debugging if (debug_node>0) { OBJECT* obj = OBJECTHDR(this); static int first=-1; if (first==-1) first = obj->id; if (obj->id==first) { printf("\n"); printf("Node Type V Vobs Stdev Power G B dV Pr{Vobs} r2 Sr2\n"); printf("============== ===== ================= ================= ======== ================= ======== ======== ======== ======== ====== ======\n"); } if (((debug_node&1)==1 && dV.Mag()>convergence_limit ) // only on dV #ifdef HYBRID || ((debug_node&2)==2 && Vstdev>0 ) // only on observation || ((debug_node&4)==4 && get_inj_residual()>0.001)// non-zero power residual #endif ) { printf("%2d (%-9.9s) %5s %+8.4f%+8.3fd %+8.4f%+8.3fd %8.5f %+8.4f%+8.4fj %+8.5f ", obj->id, obj->name, type==SWING?"SWING":(type==PQ?"PQ ":"PV"), V.Mag(),V.Arg()*180/3.1416, Vobs.Mag(), Vobs.Arg()*180/3.1416, Vstdev, S.Re(), S.Im(), G, B, dV.Mag()); #ifdef HYBRID printf("%+8.5f %8.5f ", get_obs_probability(), r2); if (Vstdev>0) printf("%8.5f %6.3f %6.3f\n", get_obs_probability(), r2, get_inj_residual()); else printf(" -- -- %6.3f\n",get_inj_residual()); #else printf("\n"); #endif } } #endif // _DEBUG // send dV through all links LINKLIST *item; for (item=linklist; item!=NULL; item=item->next) item->data->apply_dV(hdr,dV); if (dV.Mag()>convergence_limit) return t0; /* did not converge, hold the clock */ else return TS_NEVER; /* converged, no further updates needed */ }
EXPORT int init_dryer(OBJECT *obj) { dryer *my = OBJECTDATA(obj,dryer); return my->init(obj->parent); }
/** 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; }
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); }
EXPORT int isa_pqload(OBJECT *obj, char *classname) { return OBJECTDATA(obj,pqload)->isa(classname); }
//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; }
TIMESTAMP climate::presync(TIMESTAMP t0) /* called in presync */ { TIMESTAMP rv = 0; if(t0 > TS_ZERO && reader_type == RT_CSV){ DATETIME now; gl_localtime(t0, &now); //OBJECT *obj = OBJECTHDR(this); csv_reader *cr = OBJECTDATA(reader,csv_reader); rv = cr->get_data(t0, &temperature, &humidity, &solar_direct, &solar_diffuse, &solar_global, &wind_speed, &rainfall, &snowdepth, &pressure); // calculate the solar radiation double sol_time = sa->solar_time((double)now.hour+now.minute/60.0+now.second/3600.0 + (now.is_dst ? -1:0),now.yearday,RAD(tz_meridian),RAD(reader->longitude)); double sol_rad = 0.0; 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,now.yearday,RAD(reader->latitude),sol_time,solar_direct,solar_diffuse,solar_global,ground_reflectivity,0.0);//(double)dnr * cos_incident + dhr; else sol_rad = file.calc_solar(c_point,now.yearday,RAD(reader->latitude),sol_time,solar_direct,solar_diffuse,solar_global,ground_reflectivity);//(double)dnr * cos_incident + dhr; /* TMY2 solar radiation data is in Watt-hours per square meter. */ solar_flux[c_point] = sol_rad; } return rv; } if (t0>TS_ZERO && tmy!=NULL) { DATETIME ts; int localres = gl_localtime(t0,&ts); int hoy; double now, hoy0, hoy1, hoy2; if(localres == 0){ GL_THROW("climate::sync -- unable to resolve localtime!"); } int doy = sa->day_of_yr(ts.month,ts.day); hoy = (doy - 1) * 24 + (ts.hour); switch(interpolate){ case CI_NONE: temperature = tmy[hoy].temp; temperature_raw = tmy[hoy].temp_raw; humidity = tmy[hoy].rh; solar_direct = tmy[hoy].dnr; solar_diffuse = tmy[hoy].dhr; solar_global = tmy[hoy].ghr; solar_raw = tmy[hoy].solar_raw; solar_azimuth = tmy[hoy].solar_azimuth; solar_elevation = tmy[hoy].solar_elevation; pressure = tmy[hoy].pressure; direct_normal_extra = tmy[hoy].direct_normal_extra; this->wind_speed = tmy[hoy].windspeed; this->rainfall = tmy[hoy].rainfall; this->snowdepth = tmy[hoy].snowdepth; if(memcmp(solar_flux,tmy[hoy].solar,CP_LAST*sizeof(double))) memcpy(solar_flux,tmy[hoy].solar,CP_LAST*sizeof(double)); break; case CI_LINEAR: now = hoy+ts.minute/60.0; hoy0 = hoy; hoy1 = hoy+1.0; temperature = gl_lerp(now, hoy0, tmy[hoy].temp, hoy1, tmy[hoy+1%8760].temp); temperature_raw = gl_lerp(now, hoy0, tmy[hoy].temp_raw, hoy1, tmy[hoy+1%8760].temp_raw); humidity = gl_lerp(now, hoy0, tmy[hoy].rh, hoy1, tmy[hoy+1%8760].rh); solar_direct = gl_lerp(now, hoy0, tmy[hoy].dnr, hoy1, tmy[hoy+1%8760].dnr); solar_diffuse = gl_lerp(now, hoy0, tmy[hoy].dhr, hoy1, tmy[hoy+1%8760].dhr); solar_global = gl_lerp(now, hoy0, tmy[hoy].ghr, hoy1, tmy[hoy+1%8760].ghr); solar_azimuth = gl_lerp(now, hoy0, tmy[hoy].solar_azimuth, hoy1, tmy[hoy+1%8760].solar_azimuth); solar_elevation = gl_lerp(now, hoy0, tmy[hoy].solar_elevation, hoy1, tmy[hoy+1%8760].solar_elevation); wind_speed = gl_lerp(now, hoy0, tmy[hoy].windspeed, hoy1, tmy[hoy+1%8760].windspeed); rainfall = gl_lerp(now, hoy0, tmy[hoy].rainfall, hoy1, tmy[hoy+1%8760].rainfall); snowdepth = gl_lerp(now, hoy0, tmy[hoy].snowdepth, hoy1, tmy[hoy+1%8760].snowdepth); solar_raw = gl_lerp(now, hoy0, tmy[hoy].solar_raw, hoy1, tmy[hoy+1%8760].solar_raw); pressure = gl_lerp(now, hoy0, tmy[hoy].pressure, hoy1, tmy[hoy+1%8760].pressure); direct_normal_extra = gl_lerp(now, hoy0, tmy[hoy].direct_normal_extra, hoy1, tmy[hoy+1%8760].direct_normal_extra); for(int pt = 0; pt < CP_LAST; ++pt){ solar_flux[pt] = gl_lerp(now, hoy0, tmy[hoy].solar[pt], hoy1, tmy[hoy+1%8760].solar[pt]); } break; case CI_QUADRATIC: now = hoy+ts.minute/60.0; hoy0 = hoy; hoy1 = hoy+1.0; hoy2 = hoy+2.0; temperature = gl_qerp(now, hoy0, tmy[hoy].temp, hoy1, tmy[hoy+1%8760].temp, hoy2, tmy[hoy+2%8760].temp); temperature_raw = gl_qerp(now, hoy0, tmy[hoy].temp_raw, hoy1, tmy[hoy+1%8760].temp_raw, hoy2, tmy[hoy+2%8760].temp_raw); humidity = gl_qerp(now, hoy0, tmy[hoy].rh, hoy1, tmy[hoy+1%8760].rh, hoy2, tmy[hoy+2%8760].rh); if(humidity < 0.0){ humidity = 0.0; gl_verbose("Setting humidity to zero. Quadratic interpolation caused the humidity to drop below zero."); } solar_direct = gl_qerp(now, hoy0, tmy[hoy].dnr, hoy1, tmy[hoy+1%8760].dnr, hoy2, tmy[hoy+2%8760].dnr); if(solar_direct < 0.0){ solar_direct = 0.0; gl_verbose("Setting solar_direct to zero. Quadratic interpolation caused the solar_direct to drop below zero."); } solar_diffuse = gl_qerp(now, hoy0, tmy[hoy].dhr, hoy1, tmy[hoy+1%8760].dhr, hoy2, tmy[hoy+2%8760].dhr); if(solar_diffuse < 0.0){ solar_diffuse = 0.0; gl_verbose("Setting solar_diffuse to zero. Quadratic interpolation caused the solar_diffuse to drop below zero."); } solar_global = gl_qerp(now, hoy0, tmy[hoy].ghr, hoy1, tmy[hoy+1%8760].ghr, hoy2, tmy[hoy+2%8760].ghr); if(solar_global < 0.0){ solar_global = 0.0; gl_verbose("Setting solar_global to zero. Quadratic interpolation caused the solar_global to drop below zero."); } solar_azimuth = gl_qerp(now, hoy0, tmy[hoy].solar_azimuth, hoy1, tmy[hoy+1%8760].solar_azimuth, hoy2, tmy[hoy+2%8760].solar_azimuth); solar_elevation = gl_qerp(now, hoy0, tmy[hoy].solar_elevation, hoy1, tmy[hoy+1%8760].solar_elevation, hoy2, tmy[hoy+2%8760].solar_elevation); wind_speed = gl_qerp(now, hoy0, tmy[hoy].windspeed, hoy1, tmy[hoy+1%8760].windspeed, hoy2, tmy[hoy+2%8760].windspeed); if(wind_speed < 0.0){ wind_speed = 0.0; gl_verbose("Setting wind_speed to zero. Quadratic interpolation caused the wind_speed to drop below zero."); } rainfall = gl_qerp(now, hoy0, tmy[hoy].rainfall, hoy1, tmy[hoy+1%8760].rainfall, hoy2, tmy[hoy+2%8760].rainfall); if(rainfall < 0.0){ rainfall = 0.0; gl_verbose("Setting rainfall to zero. Quadratic interpolation caused the rainfall to drop below zero."); } snowdepth = gl_qerp(now, hoy0, tmy[hoy].snowdepth, hoy1, tmy[hoy+1%8760].snowdepth, hoy2, tmy[hoy+2%8760].snowdepth); if(snowdepth < 0.0){ snowdepth = 0.0; gl_verbose("Setting snowdepth to zero. Quadratic interpolation caused the snowdepth to drop below zero."); } solar_raw = gl_qerp(now, hoy0, tmy[hoy].solar_raw, hoy1, tmy[hoy+1%8760].solar_raw, hoy2, tmy[hoy+2%8760].solar_raw); if(solar_raw < 0.0){ solar_raw = 0.0; gl_verbose("Setting solar_raw to zero. Quadratic interpolation caused the solar_raw to drop below zero."); } pressure = gl_qerp(now, hoy0, tmy[hoy].pressure, hoy1, tmy[hoy+1%8760].pressure, hoy2, tmy[hoy+2%8760].pressure); if(pressure < 0.0){ pressure = 0.0; gl_verbose("Setting pressure to zero. Quadratic interpolation caused the pressure to drop below zero."); } direct_normal_extra = gl_qerp(now, hoy0, tmy[hoy].direct_normal_extra, hoy1, tmy[hoy+1%8760].direct_normal_extra, hoy2, tmy[hoy+2%8760].direct_normal_extra); if(direct_normal_extra < 0.0){ direct_normal_extra = 0.0; gl_verbose("Setting extraterrestrial_direct_normal to zero. Quadratic interpolation caused the extraterrestrial_direct_normal to drop below zero."); } for(int pt = 0; pt < CP_LAST; ++pt){ if(tmy[hoy].solar[pt] == tmy[hoy+1].solar[pt]){ solar_flux[pt] = tmy[hoy].solar[pt]; } else { solar_flux[pt] = gl_qerp(now, hoy0, tmy[hoy].solar[pt], hoy1, tmy[hoy+1%8760].solar[pt], hoy2, tmy[hoy+2%8760].solar[pt]); if(solar_flux[pt] < 0.0) solar_flux[pt] = 0.0; /* quadratic isn't always cooperative... */ } } break; default: GL_THROW("climate::sync -- unrecognize interpolation mode!"); } update_forecasts(t0); return -(t0+(3600*TS_SECOND-t0%(3600 *TS_SECOND))); /// negative means soft event } return TS_NEVER; }
//Function to change recloser states - just call underlying switch routine EXPORT double change_recloser_state(OBJECT *thisobj, unsigned char phase_change, bool state) { double count_values; char desA, desB, desC; recloser *reclobj; switch_object *swtchobj; FUNCTIONADDR funadd = NULL; //Init count_values = 0.0; //Map us as a recloser - just so we can get our count reclobj = OBJECTDATA(thisobj,recloser); //Set count if (state == false) count_values = reclobj->ntries; //Opening, so must have "tried" all times else count_values = 1.0; //Just a non-zero value //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; }
EXPORT int init_plugload(OBJECT *obj) { plugload *my = OBJECTDATA(obj,plugload); return my->init(obj->parent); }
EXPORT int init_schedule(OBJECT *obj) { schedule *my = OBJECTDATA(obj,schedule); return my->init(obj->parent); }
EXPORT int isa_recloser(OBJECT *obj, char *classname) { return OBJECTDATA(obj,recloser)->isa(classname); }
/** 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; }
//int solver_matpower(double *rbus, unsigned int nbus, double *rgen, unsigned int ngen, // double *rbranch, unsigned int nbranch, double *rgencost, unsigned int ngencost, // double *rareas, unsigned int nareas) int solver_matpower(vector<unsigned int> bus_BUS_I, vector<unsigned int> branch_F_BUS, vector<unsigned int> branch_T_BUS, vector<unsigned int> gen_GEN_BUS, vector<unsigned int> gen_NCOST,unsigned int BASEMVA) { unsigned int nbus = 0; unsigned int ngen = 0; unsigned int nbranch = 0; //unsigned int ngencost = 0; //unsigned int nareas = 0; //unsigned int nbaseMVA = 0; vector<bus> vec_bus; vector<gen> vec_gen; vector<branch> vec_branch; //vector<areas> vec_areas; //vector<gen_cost> vec_gencost; //vector<baseMVA> vec_baseMVA; //printf("========Getting Data=============\n"); // Get Bus objects OBJECT *temp_obj = NULL; bus *list_bus; FINDLIST *bus_list = gl_find_objects(FL_NEW,FT_CLASS,SAME,"bus",FT_END); while (gl_find_next(bus_list,temp_obj)!=NULL) { temp_obj = gl_find_next(bus_list,temp_obj); list_bus = OBJECTDATA(temp_obj,bus); vec_bus.push_back(*list_bus); }; // Get Generator objects gen *list_gen; FINDLIST *gen_list = gl_find_objects(FL_NEW,FT_CLASS,SAME,"gen",FT_END); temp_obj = NULL; while (gl_find_next(gen_list,temp_obj)!=NULL) { temp_obj = gl_find_next(gen_list,temp_obj); list_gen = OBJECTDATA(temp_obj,gen); vec_gen.push_back(*list_gen); }; // Get Line/Branch Objects branch *list_branch; FINDLIST *branch_list = gl_find_objects(FL_NEW,FT_CLASS,SAME,"branch",FT_END); temp_obj = NULL; while (gl_find_next(branch_list,temp_obj)!=NULL) { temp_obj = gl_find_next(branch_list,temp_obj); list_branch = OBJECTDATA(temp_obj,branch); vec_branch.push_back(*list_branch); } // Get Area Objects /* areas *list_areas; FINDLIST *areas_list = gl_find_objects(FL_NEW,FT_CLASS,SAME,"areas",FT_END); temp_obj = NULL; while (gl_find_next(areas_list,temp_obj) != NULL) { temp_obj = gl_find_next(areas_list,temp_obj); list_areas = OBJECTDATA(temp_obj,areas); vec_areas.push_back(*list_areas); } */ // Get Generator Cost objects /* gen_cost *list_gen_cost; FINDLIST *gen_cost_list = gl_find_objects(FL_NEW,FT_CLASS,SAME,"gen_cost",FT_END); temp_obj = NULL; while (gl_find_next(gen_cost_list,temp_obj)!=NULL) { temp_obj = gl_find_next(gen_cost_list,temp_obj); list_gen_cost = OBJECTDATA(temp_obj,gen_cost); vec_gencost.push_back(*list_gen_cost); } */ // Get Base Information object //baseMVA *list_baseMVA; //FINDLIST *baseMVA_list = gl_find_objects(FL_NEW,FT_CLASS,SAME,"baseMVA",FT_END); //temp_obj = NULL; //temp_obj = gl_find_next(baseMVA_list,temp_obj); //list_baseMVA = OBJECTDATA(temp_obj,baseMVA); //vec_baseMVA.push_back(*list_baseMVA); // Get the size of each class nbus = vec_bus.size(); ngen = vec_gen.size(); nbranch = vec_branch.size(); //ngencost = vec_gencost.size(); //nareas = vec_areas.size(); //nbaseMVA = vec_baseMVA.size(); // create arrays for input and allocate memory double *rbus; rbus = (double *) calloc(nbus*BUS_ATTR,sizeof(double)); double *rgen; rgen = (double *) calloc(ngen*GEN_ATTR,sizeof(double)); double *rbranch; rbranch = (double *) calloc(nbranch*BRANCH_ATTR,sizeof(double)); double *rareas; rareas = (double *) calloc(AREA_ATTR,sizeof(double)); double rbaseMVA; double *rgencost; // allocation of memory is in the following part // insert bus data for rbus vector<bus>::iterator iter_bus = vec_bus.begin(); if (nbus > 1) { for (unsigned int i=0; i < nbus; i++) { //rbus[i+0*nbus] = (double)iter_bus->BUS_I; rbus[i+0*nbus] = bus_BUS_I[i]; rbus[i+1*nbus] = (double)iter_bus->BUS_TYPE; rbus[i+2*nbus] = iter_bus->PD; rbus[i+3*nbus] = iter_bus->QD; rbus[i+4*nbus] = iter_bus->GS; rbus[i+5*nbus] = iter_bus->BS; //rbus[i+6*nbus] = (double)iter_bus->BUS_AREA; rbus[i+6*nbus] = 1; rbus[i+7*nbus] = iter_bus->VM; rbus[i+8*nbus] = iter_bus->VA; rbus[i+9*nbus] = iter_bus->BASE_KV; rbus[i+10*nbus] = (double)iter_bus->ZONE; rbus[i+11*nbus] = iter_bus->VMAX; rbus[i+12*nbus] = iter_bus->VMIN; iter_bus++; } } // insert data for rgen vector<gen>::iterator iter_gen = vec_gen.begin(); unsigned int max_order = 0; for (unsigned int i =0; i< ngen; i++) { if (gen_NCOST[i] > max_order) max_order = gen_NCOST[i]; iter_gen++; } rgencost = (double *) calloc(ngen*(GENCOST_ATTR+max_order),sizeof(double)); iter_gen = vec_gen.begin(); for (unsigned int i = 0; i < ngen; i++) { //rgen[i+0*ngen] = (double) iter_gen->GEN_BUS; rgen[i+0*ngen] = gen_GEN_BUS[i]; rgen[i+1*ngen] = iter_gen->PG; rgen[i+2*ngen] = iter_gen->QG; rgen[i+3*ngen] = iter_gen->QMAX; rgen[i+4*ngen] = iter_gen->QMIN; rgen[i+5*ngen] = iter_gen->VG; rgen[i+6*ngen] = iter_gen->MBASE; rgen[i+7*ngen] = iter_gen->GEN_STATUS; rgen[i+8*ngen] = iter_gen->PMAX; rgen[i+9*ngen] = iter_gen->PMIN; rgen[i+10*ngen] = iter_gen->PC1; rgen[i+11*ngen] = iter_gen->PC2; rgen[i+12*ngen] = iter_gen->QC1MIN; rgen[i+13*ngen] = iter_gen->QC1MAX; rgen[i+14*ngen] = iter_gen->QC2MIN; rgen[i+15*ngen] = iter_gen->QC2MAX; rgen[i+16*ngen] = iter_gen->RAMP_AGC; rgen[i+17*ngen] = iter_gen->RAMP_10; rgen[i+18*ngen] = iter_gen->RAMP_30; rgen[i+19*ngen] = iter_gen->RAMP_Q; rgen[i+20*ngen] = iter_gen->APF; // Cost info rgencost[i+0*ngen] = iter_gen->MODEL; rgencost[i+1*ngen] = iter_gen->STARTUP; rgencost[i+2*ngen] = iter_gen->SHUTDOWN; //rgencost[i+3*ngen] = (double)iter_gen->NCOST; rgencost[i+3*ngen] = gen_NCOST[i]; string double_string(iter_gen->COST); vector<string> v; v = split(double_string,','); for (unsigned int j=0; j<v.size();j++) { rgencost[i+(4+j)*ngen] = atof(v[j].c_str()); } if (gen_NCOST[i] != max_order) { for (unsigned int j = gen_NCOST[i]; j< max_order; j++) { rgencost[i+(4+j)*ngen] = 0.0; } } iter_gen++; } // insert data for rbranch vector<branch>::iterator iter_branch = vec_branch.begin(); for (unsigned int i = 0; i < nbranch; i++) { //rbranch[i+0*nbranch] = (double)iter_branch->F_BUS; rbranch[i+0*nbranch] = branch_F_BUS[i]; //rbranch[i+1*nbranch] = (double)iter_branch->T_BUS; rbranch[i+1*nbranch] = branch_T_BUS[i]; rbranch[i+2*nbranch] = iter_branch->BR_R; rbranch[i+3*nbranch] = iter_branch->BR_X; rbranch[i+4*nbranch] = iter_branch->BR_B; rbranch[i+5*nbranch] = iter_branch->RATE_A; rbranch[i+6*nbranch] = iter_branch->RATE_B; rbranch[i+7*nbranch] = iter_branch->RATE_C; rbranch[i+8*nbranch] = iter_branch->TAP; rbranch[i+9*nbranch] = iter_branch->SHIFT; rbranch[i+10*nbranch] = (double)iter_branch->BR_STATUS; rbranch[i+11*nbranch] = iter_branch->ANGMIN; rbranch[i+12*nbranch] = iter_branch->ANGMAX; iter_branch++; } // insert data for rareas //vector<areas>::const_iterator iter_areas = vec_areas.begin(); //for (unsigned int i = 0; i < nareas; i++) //{ rareas[0] = 1; rareas[1] = 1; // iter_areas++; //} // insert data for rbaseMVA //vector<baseMVA>::const_iterator iter_baseMVA = vec_baseMVA.begin(); //rbaseMVA = iter_baseMVA->BASEMVA; rbaseMVA = BASEMVA; // insert data for rgencost /* vector<gen_cost>::const_iterator iter_gencost = vec_gencost.begin(); unsigned int max_order = 0; for (unsigned int i = 0; i<ngencost; i++) { if (iter_gencost->NCOST > max_order) max_order = iter_gencost->NCOST; iter_gencost++; } rgencost = (double *) calloc(ngencost*(GENCOST_ATTR+max_order),sizeof(double)); iter_gencost = vec_gencost.begin(); for (unsigned int i = 0; i<ngencost; i++) { // Only support model 2: ticket 4 if (iter_gencost -> MODEL != 2) GL_THROW("Unsupported model for generation cost\n"); rgencost[i+0*ngencost] = iter_gencost->MODEL; rgencost[i+1*ngencost] = iter_gencost->STARTUP; rgencost[i+2*ngencost] = iter_gencost->SHUTDOWN; rgencost[i+3*ngencost] = (double)iter_gencost->NCOST; string double_string(iter_gencost->COST); vector<string> v; v = split(double_string,','); for (unsigned int j = 0; j<v.size();j++) { rgencost[i+(4+j)*ngencost] = atof(v[j].c_str()); } if (iter_gencost->NCOST != max_order) { for (unsigned int j = iter_gencost->NCOST; j < max_order; j++) rgencost[i+(4+j)*ngencost] = 0.0; } iter_gencost++; } */ // Run the Solver function //printf("Running Test\n"); libopfInitialize(); //mxArray* basemva = initArray(rbaseMVA,nbaseMVA,BASEMVA_ATTR); mxArray* basemva_array = mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(basemva_array) = rbaseMVA; // change to MATLAB MAT format mxArray* bus_array = initArray(rbus, nbus, BUS_ATTR); mxArray* gen_array = initArray(rgen, ngen, GEN_ATTR); mxArray* branch_array = initArray(rbranch, nbranch, BRANCH_ATTR); mxArray* gencost_array = initArray(rgencost, ngen, GENCOST_ATTR+max_order); //mxArray* areas_array = initArray(rareas, nareas, AREA_ATTR); mxArray* areas_array = initArray(rareas, 1, AREA_ATTR); mxArray* busout; mxArray* genout; mxArray* branchout; mxArray* f; mxArray* success; mxArray* plhs[5]; mxArray* prhs[6]; plhs[0] = busout; plhs[1] = genout; plhs[2] = branchout; plhs[3] = f; plhs[4] = success; prhs[0] = basemva_array; prhs[1] = bus_array; prhs[2] = gen_array; prhs[3] = branch_array; prhs[4] = areas_array; prhs[5] = gencost_array; mlxOpf(5, plhs, 6, prhs); // cout if first parameter is 0; //mlxOpf(0,plhs,6,prhs); // Get data from array double *obus = getArray(plhs[0]); double *ogen = getArray(plhs[1]); double *obranch = getArray(plhs[2]); // Update class bus temp_obj = NULL; for (unsigned int i=0; i < nbus; i++) { /* iter_bus->PD = obus[i+2*nbus]; iter_bus->QD = obus[i+3*nbus]; iter_bus->GS = obus[i+4*nbus]; iter_bus->BS = obus[i+5*nbus]; iter_bus->VM = obus[i+7*nbus]; iter_bus->VA = obus[i+8*nbus]; iter_bus->VMAX = obus[i+11*nbus]; iter_bus->VMIN = obus[i+12*nbus]; iter_bus->LAM_P = obus[i+13*nbus]; iter_bus->LAM_Q = obus[i+14*nbus]; iter_bus->MU_VMAX = obus[i+15*nbus]; iter_bus->MU_VMIN = obus[i+16*nbus]; //iter_bus++; */ //printf("====Before Test part VM %f; %f\n",iter_bus->VM,obus[i+7*nbus]); temp_obj = gl_find_next(bus_list,temp_obj); //Matpower does not overwrite the generator power in bus class setObjectValue_Double(temp_obj,"PD",obus[i+2*nbus]); setObjectValue_Double(temp_obj,"QD",obus[i+3*nbus]); setObjectValue_Double(temp_obj,"GS",obus[i+4*nbus]); setObjectValue_Double(temp_obj,"BS",obus[i+5*nbus]); setObjectValue_Double(temp_obj,"VM",obus[i+7*nbus]); setObjectValue_Double(temp_obj,"VA",obus[i+8*nbus]); setObjectValue_Double(temp_obj,"VMAX",obus[i+11*nbus]); setObjectValue_Double(temp_obj,"VMIN",obus[i+12*nbus]); setObjectValue_Double(temp_obj,"LAM_P",obus[i+13*nbus]); setObjectValue_Double(temp_obj,"LAM_Q",obus[i+14*nbus]); setObjectValue_Double(temp_obj,"MU_VMAX",obus[i+15*nbus]); setObjectValue_Double(temp_obj,"MU_VMIN",obus[i+16*nbus]); // obus[i+9*nbus] is BASE_KV. The unit is KV. setObjectValue_Double2Complex_inDegree(temp_obj,"CVoltageA",obus[i+7*nbus]*obus[i+9*nbus]*1000,obus[i+8*nbus]); setObjectValue_Double2Complex_inDegree(temp_obj,"CVoltageB",obus[i+7*nbus]*obus[i+9*nbus]*1000,obus[i+8*nbus]+2/3*PI); setObjectValue_Double2Complex_inDegree(temp_obj,"CVoltageC",obus[i+7*nbus]*obus[i+9*nbus]*1000,obus[i+8*nbus]-2/3*PI); setObjectValue_Double(temp_obj,"V_nom",obus[i+7*nbus]*obus[i+9*nbus]*1000); //printf("BUS: %f LAM_P %f\n",obus[i+0*nbus],obus[i+13*nbus]); //cout<<"BUS "<<obus[i+0*nbus]<<"LAM_P "<<obus[i+13*nbus]<<endl; } /* unsigned int NumOfElement = mxGetNumberOfElements(plhs[0]); for (unsigned int i =0; i<NumOfElement; i++) { printf("%f ",obus[i]); if ((i+1)%nbus == 0) printf("\n"); } printf("========================\n"); iter_bus = vec_bus.begin(); for (unsigned int i=0;i< nbus; i++) { printf("Bus %d; PD %f; QD %f; VM %f; VA %f;\n",iter_bus->BUS_I,iter_bus->PD,iter_bus->QD,iter_bus->VM,iter_bus->VA); iter_bus++; } */ // Update class gen iter_gen = vec_gen.begin(); temp_obj = NULL; for (unsigned int i = 0; i < ngen; i++) { /* iter_gen->PG = ogen[i+1*ngen]; iter_gen->QG = ogen[i+2*ngen]; iter_gen->QMAX = ogen[i+3*ngen]; iter_gen->QMIN = ogen[i+4*ngen]; iter_gen->VG = ogen[i+5*ngen]; iter_gen->PC1 = ogen[i+10*ngen]; iter_gen->PC2 = ogen[i+11*ngen]; iter_gen->RAMP_AGC = ogen[i+16*ngen]; iter_gen->RAMP_10 = ogen[i+17*ngen]; iter_gen->RAMP_30 = ogen[i+18*ngen]; iter_gen->RAMP_Q = ogen[i+19*ngen]; iter_gen->APF = ogen[i+20*ngen]; iter_gen->MU_PMAX = ogen[i+21*ngen]; iter_gen->MU_PMIN = ogen[i+22*ngen]; iter_gen->MU_QMAX = ogen[i+23*ngen]; iter_gen->MU_QMIN = ogen[i+24*ngen]; iter_gen++; */ temp_obj = gl_find_next(gen_list,temp_obj); setObjectValue_Double(temp_obj,"PG",ogen[i+1*ngen]); setObjectValue_Double(temp_obj,"QG",ogen[i+2*ngen]); setObjectValue_Double(temp_obj,"QMAX",ogen[i+3*ngen]); setObjectValue_Double(temp_obj,"QMIN",ogen[i+4*ngen]); setObjectValue_Double(temp_obj,"VG",ogen[i+5*ngen]); setObjectValue_Double(temp_obj,"PC1",ogen[i+10*ngen]); setObjectValue_Double(temp_obj,"PC2",ogen[i+11*ngen]); setObjectValue_Double(temp_obj,"RAMP_AGC",ogen[i+16*ngen]); setObjectValue_Double(temp_obj,"RAMP_10",ogen[i+17*ngen]); setObjectValue_Double(temp_obj,"RAMP_30",ogen[i+18*ngen]); setObjectValue_Double(temp_obj,"RAMP_Q",ogen[i+19*ngen]); setObjectValue_Double(temp_obj,"APF",ogen[i+20*ngen]); setObjectValue_Double(temp_obj,"MU_PMAX",ogen[i+21*ngen]); setObjectValue_Double(temp_obj,"MU_PMIN",ogen[i+22*ngen]); setObjectValue_Double(temp_obj,"MU_QMAX",ogen[i+23*ngen]); setObjectValue_Double(temp_obj,"MU_QMIN",ogen[i+24*ngen]); // Calculate Price double price = 0; unsigned int NCOST = (unsigned int)rgencost[i+3*ngen]; //printf("Bus %d, order %d ",i,NCOST); for (unsigned int j = 0; j < NCOST; j++) { price += pow(ogen[i+1*ngen],NCOST-1-j)*rgencost[i+(4+j)*ngen]; //printf("Coeff %d: %f and price %f",j,rgencost[i+(4+j)*ngencost],price); } setObjectValue_Double(temp_obj,"Price",price); //printf("\nBus %d, Price %f\n",i,price); iter_gen++; } // Update class branch //iter_branch = vec_branch.begin(); temp_obj = NULL; for (unsigned int i = 0; i<nbranch; i++) { /* iter_branch->PF = obranch[i+13*nbranch]; iter_branch->QF = obranch[i+14*nbranch]; iter_branch->PT = obranch[i+15*nbranch]; iter_branch->QT = obranch[i+16*nbranch]; iter_branch->MU_SF = obranch[i+17*nbranch]; iter_branch->MU_ST = obranch[i+18*nbranch]; iter_branch->MU_ANGMIN = obranch[i+19*nbranch]; iter_branch->MU_ANGMAX = obranch[i+20*nbranch]; iter_branch++; */ temp_obj = gl_find_next(branch_list,temp_obj); setObjectValue_Double(temp_obj,"PF",obranch[i+13*nbranch]); setObjectValue_Double(temp_obj,"QF",obranch[i+14*nbranch]); setObjectValue_Double(temp_obj,"PT",obranch[i+15*nbranch]); setObjectValue_Double(temp_obj,"QT",obranch[i+16*nbranch]); setObjectValue_Double(temp_obj,"MU_SF",obranch[i+17*nbranch]); setObjectValue_Double(temp_obj,"MU_ST",obranch[i+18*nbranch]); setObjectValue_Double(temp_obj,"MU_ANGMIN",obranch[i+19*nbranch]); setObjectValue_Double(temp_obj,"MU_ANGMAX",obranch[i+20*nbranch]); } // free space //printf("Free r..\n"); free(rbus); free(rgen); free(rbranch); free(rareas); //free(rbaseMVA); free(rgencost); //printf("Free o..\n"); free(obus); free(ogen); free(obranch); vec_bus.clear(); vec_gen.clear(); vec_branch.clear(); //vec_gencost.clear(); //vec_baseMVA.clear(); short ifsuccess = (short)*getArray(plhs[3]); //printf("suceess %f\n",*getArray(plhs[4])); return ifsuccess; }
EXPORT int init_node(OBJECT *obj) { return OBJECTDATA(obj,node)->init(obj->parent); }
EXPORT TIMESTAMP sync_capbank(OBJECT *obj, TIMESTAMP t0) { TIMESTAMP t1 = OBJECTDATA(obj,capbank)->sync(t0); obj->clock = t0; return t1; }
EXPORT int commit_range(OBJECT *obj) { range *my = OBJECTDATA(obj,range); return my->commit(); }
EXPORT int isa_powerflow_library(OBJECT *obj, char *classname) { return OBJECTDATA(obj,powerflow_library)->isa(classname); }
//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; }
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; }
EXPORT int isa_sectionalizer(OBJECT *obj, char *classname) { return OBJECTDATA(obj,sectionalizer)->isa(classname); }
EXPORT int isa_powerflow_object(OBJECT *obj, char *classname) { return OBJECTDATA(obj,powerflow_object)->isa(classname); }
EXPORT int commit_waterheater(OBJECT *obj) { waterheater *my = OBJECTDATA(obj,waterheater); return my->commit(); }
EXPORT int isa_voltdump(OBJECT *obj, char *classname) { return OBJECTDATA(obj,voltdump)->isa(classname); }
/** * Sync is called when the clock needs to advance on the bottom-up pass (PC_BOTTOMUP) * * @param obj the object we are sync'ing * @param t0 this objects current timestamp * @param pass the current pass for this sync call * @return t1, where t1>t0 on success, t1=t0 for retry, t1<t0 on failure */ EXPORT TIMESTAMP sync_powerflow_library(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass) { powerflow_library *pObj = OBJECTDATA(obj,powerflow_library); gl_error("%s (powerflow_library:%d): sync should never be called", pObj->get_name(), pObj->get_id()); return TS_INVALID; }
EXPORT int isa_triplex_meter(OBJECT *obj, char *classname) { return OBJECTDATA(obj,triplex_meter)->isa(classname); }
EXPORT int isa_group_recorder(OBJECT *obj, char *classname) { return OBJECTDATA(obj, group_recorder)->isa(classname); }
EXPORT int isa_power_metrics(OBJECT *obj, char *classname) { return OBJECTDATA(obj,power_metrics)->isa(classname); }
EXPORT int isa_switch(OBJECT *obj, char *classname) { return OBJECTDATA(obj,switch_object)->isa(classname); }
// meter reset function EXPORT int64 triplex_meter_reset(OBJECT *obj) { triplex_meter *pMeter = OBJECTDATA(obj,triplex_meter); pMeter->measured_demand = 0; return 0; }
/** * Allows the core to discover whether obj is a subtype of this class. * * @param obj a pointer to this object * @param classname the name of the object the core is testing * * @return true (1) if obj is a subtype of this class */ EXPORT int isa_histogram(OBJECT *obj, char *classname) { return OBJECTDATA(obj,histogram)->isa(classname); }