00001
00079 #include <stdlib.h>
00080 #include <stdio.h>
00081 #include <errno.h>
00082 #include <math.h>
00083 #include "solvers.h"
00084 #include "house.h"
00085 #include "lock.h"
00086
00088
00090 CLASS* house::oclass = NULL;
00091 house *house::defaults = NULL;
00092
00096 house::house(MODULE *mod)
00097 {
00098
00099 if (oclass==NULL)
00100 {
00101
00102 oclass = gl_register_class(mod,"house",PC_PRETOPDOWN|PC_BOTTOMUP);
00103 if (oclass==NULL)
00104 GL_THROW("unable to register object class implemented by %s",__FILE__);
00105
00106
00107 if (gl_publish_variable(oclass,
00108 PT_double,"floor_area[sf]",PADDR(floor_area),
00109 PT_double,"gross_wall_area[sf]",PADDR(gross_wall_area),
00110 PT_double,"ceiling_height[ft]",PADDR(ceiling_height),
00111 PT_double,"aspect_ratio",PADDR(aspect_ratio),
00112 PT_double,"envelope_UA[Btu/degF]",PADDR(envelope_UA),
00113 PT_double,"window_wall_ratio",PADDR(window_wall_ratio),
00114 PT_double,"glazing_shgc",PADDR(glazing_shgc),
00115 PT_double,"airchange_per_hour",PADDR(airchange_per_hour),
00116 PT_double,"total_internal_gain[Btu/h]",PADDR(total_internal_gain),
00117 PT_double,"thermostat_deadband[degF]",PADDR(thermostat_deadband),
00118 PT_double,"heating_setpoint[degF]",PADDR(heating_setpoint),
00119 PT_double,"cooling_setpoint[degF]",PADDR(cooling_setpoint),
00120 PT_double, "design_heating_capacity[Btu.h/sf]",PADDR(design_heating_capacity),
00121 PT_double,"design_cooling_capacity[Btu.h/sf]",PADDR(design_cooling_capacity),
00122 PT_double,"heating_COP",PADDR(heating_COP),
00123 PT_double,"cooling_COP",PADDR(cooling_COP),
00124 PT_double,"air_temperature[degF]",PADDR(Tair),
00125 PT_complex,"power[kW]",PADDR(power_kw),
00126 NULL)<1)
00127 GL_THROW("unable to publish properties in %s",__FILE__);
00128
00129
00130 defaults = this;
00131
00132
00133 floor_area = 0.0;
00134 ceiling_height = 0.0;
00135 envelope_UA = 0.0;
00136 airchange_per_hour = 0.0;
00137 thermostat_deadband = 0.0;
00138 heating_setpoint = 0.0;
00139 cooling_setpoint = 0.0;
00140 window_wall_ratio = 0.0;
00141 gross_wall_area = 0.0;
00142 glazing_shgc = 0.0;
00143 design_heating_capacity = 0.0;
00144 design_cooling_capacity = 0.0;
00145 heating_COP = 3.0;
00146 cooling_COP = 3.0;
00147 aspect_ratio = 1.0;
00148
00149
00150 panel.circuits=NULL;
00151 panel.max_amps=200;
00152 }
00153 }
00154
00155 int house::create()
00156 {
00157
00158 memcpy(this,defaults,sizeof(*this));
00159
00160 return 1;
00161 }
00162
00167 int house::init_climate()
00168 {
00169 OBJECT *hdr = OBJECTHDR(this);
00170
00171
00172 static FINDLIST *climates = NULL;
00173 int not_found = 0;
00174 if (climates==NULL && not_found==0)
00175 {
00176 climates = gl_find_objects(FL_NEW,FT_CLASS,SAME,"climate",FT_END);
00177 if (climates==NULL)
00178 {
00179 not_found = 1;
00180 gl_warning("house: no climate data found, using static data");
00181
00182
00183 static double tout=59.0, rhout=0.75, solar[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
00184 pTout = &tout;
00185 pRhout = &rhout;
00186 pSolar = &solar[0];
00187 }
00188 else if (climates->hit_count>1)
00189 {
00190 gl_warning("house: %d climates found, using first one defined", climates->hit_count);
00191 }
00192 }
00193 if (climates!=NULL)
00194 {
00195 if (climates->hit_count==0)
00196 {
00197
00198 static double tout=59.0, rhout=0.75, solar[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
00199 pTout = &tout;
00200 pRhout = &rhout;
00201 pSolar = &solar[0];
00202 }
00203 else
00204 {
00205
00206 OBJECT *obj = gl_find_next(climates,NULL);
00207 if (obj->rank<=hdr->rank)
00208 gl_set_dependent(obj,hdr);
00209 pTout = (double*)GETADDR(obj,gl_get_property(obj,"temperature"));
00210 pRhout = (double*)GETADDR(obj,gl_get_property(obj,"humidity"));
00211 pSolar = (double*)GETADDR(obj,gl_get_property(obj,"solar_flux"));
00212 }
00213 }
00214 return 1;
00215 }
00216
00221 int house::init(OBJECT *parent)
00222 {
00223
00224 struct {
00225 complex **var;
00226 char *varname;
00227 } map[] = {
00228
00229 {&pCircuit_V, "line12_voltage"},
00230 {&pLine_I, "line1_current"},
00232 };
00233
00234 static complex default_line123_voltage[3], default_line1_current[3];
00235 int i;
00236
00237
00238 if (parent!=NULL && strcmp(parent->oclass->name,"meter")==0)
00239 {
00240
00241 for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
00242 *(map[i].var) = get_complex(parent,map[i].varname);
00243 }
00244 else
00245 {
00246 OBJECT *obj = OBJECTHDR(this);
00247 gl_warning("house:%d %s", obj->id, parent==NULL?"has no parent meter defined":"parent is not a meter");
00248
00249
00250 *(map[0].var) = &default_line123_voltage[0];
00251 *(map[1].var) = &default_line1_current[0];
00252
00253
00254 default_line123_voltage[0] = 240.0;
00255 default_line123_voltage[1] = -120.0;
00256 default_line123_voltage[2] = -120.0;
00257
00258 }
00259
00260 if (floor_area <= ROUNDOFF)
00261 floor_area = gl_random_uniform(2500,300);
00262
00263 if (ceiling_height <= ROUNDOFF)
00264 ceiling_height = 8.0;
00265
00266 if (envelope_UA <= ROUNDOFF)
00267 envelope_UA = gl_random_uniform(0.15,0.2)*floor_area;
00268
00269 if (aspect_ratio <= ROUNDOFF)
00270 aspect_ratio = 1.0;
00271
00272 if (gross_wall_area <= ROUNDOFF)
00273 gross_wall_area = 4.0 * 2.0 * (aspect_ratio + 1.0) * ceiling_height * sqrt(floor_area/aspect_ratio);
00274
00275 if (airchange_per_hour <= ROUNDOFF)
00276 airchange_per_hour = gl_random_uniform(4,6);
00277
00278 if (thermostat_deadband <= ROUNDOFF)
00279 thermostat_deadband = 2;
00280
00281 if (heating_setpoint <= ROUNDOFF)
00282 heating_setpoint = gl_random_uniform(68,72);
00283
00284 if (cooling_setpoint <= ROUNDOFF)
00285 cooling_setpoint = gl_random_uniform(75,80);
00286
00287 if (window_wall_ratio <= ROUNDOFF)
00288 window_wall_ratio = 0.15;
00289
00290 if (glazing_shgc <= ROUNDOFF)
00291 glazing_shgc = 0.65;
00292
00293 if (design_cooling_capacity <= ROUNDOFF)
00294 design_cooling_capacity = gl_random_uniform(18,24);
00295
00296 if (design_heating_capacity <= ROUNDOFF)
00297 design_heating_capacity = gl_random_uniform(18,24);
00298
00299
00300
00301 if (COP_coeff <= ROUNDOFF)
00302 COP_coeff = gl_random_uniform(0.9,1.1);
00303
00304 if (Tair <= ROUNDOFF)
00305 Tair = gl_random_uniform(heating_setpoint+thermostat_deadband, cooling_setpoint-thermostat_deadband);
00306
00307 if (over_sizing_factor <= ROUNDOFF)
00308 over_sizing_factor = gl_random_uniform(0.98,1.3);
00309
00310 heat_cool_mode = house::OFF;
00311
00312 air_density = 0.0735;
00313 air_heat_capacity = 0.2402;
00314
00315 house_content_thermal_mass = 10000.0;
00316
00317 if (house_content_heat_transfer_coeff <= ROUNDOFF)
00318 house_content_heat_transfer_coeff = gl_random_uniform(0.5,1.0)*floor_area;
00319
00320
00321 volume = 8*floor_area;
00322 air_mass = air_density*volume;
00323 air_thermal_mass = air_heat_capacity*air_mass;
00324 Tmaterials = Tair;
00325 hvac_rated_power = 24*floor_area*over_sizing_factor;
00326
00327 if (set_Eigen_values() == FALSE)
00328 return 0;
00329
00330 OBJECT *hdr = OBJECTHDR(this);
00331 if (hdr->latitude < 24 || hdr->latitude > 48)
00332 {
00333
00334 gl_error("Latitude beyond the currently supported range 24 - 48 N, Simulations will continue assuming latitude 36N");
00335 hdr->latitude = 36.0;
00336 }
00337
00338
00339 attach(OBJECTHDR(this),50, TRUE);
00340
00341
00342 return 1;
00343 }
00344
00349 CIRCUIT *house::attach(OBJECT *obj,
00350 double breaker_amps,
00351 int is220)
00352 {
00353
00354 CIRCUIT *c = new CIRCUIT;
00355 if (c==NULL)
00356 {
00357 gl_error("memory allocation failure");
00358 return 0;
00359
00360
00361 }
00362 c->next = panel.circuits;
00363 c->id = panel.circuits ? panel.circuits->id+1 : 1;
00364
00365
00366 c->max_amps = breaker_amps;
00367
00368
00369 c->pS = get_complex(obj,"power");
00370
00371
00372 if (is220)
00373 {
00374 c->type = X12;
00375 c->id++;
00376 }
00377 else if (c->id&0x01)
00378 c->type = X13;
00379 else
00380 c->type = X23;
00381
00382
00383 panel.circuits = c;
00384
00385
00386 c->pV = &(pCircuit_V[(int)c->type]);
00387
00388
00389 c->status = BRK_CLOSED;
00390
00391
00392
00393 c->tripsleft = 100;
00394
00395 return c;
00396 }
00397
00401 TIMESTAMP house::thermostat(TIMESTAMP t0, TIMESTAMP t1)
00402 {
00403 const double TcoolOn = cooling_setpoint+thermostat_deadband;
00404 const double TcoolOff = cooling_setpoint-thermostat_deadband;
00405 const double TheatOn = heating_setpoint-thermostat_deadband;
00406 const double TheatOff = heating_setpoint+thermostat_deadband;
00407
00408
00409 if (TcoolOff<TheatOff)
00410 {
00411 gl_error("house: thermostat setpoints deadbands overlap (TcoolOff=%.1f < TheatOff=%.1f)", TcoolOff,TheatOff);
00412 return TS_INVALID;
00413 }
00414
00415
00416 if (Tair<=TheatOn+0.01)
00417 heat_cool_mode = HEAT;
00418 else if (Tair>=TheatOff-0.01 && Tair<=TcoolOff+0.01)
00419 heat_cool_mode = OFF;
00420 else if (Tair>=TcoolOn-0.01)
00421 heat_cool_mode = COOL;
00422
00423 return TS_NEVER;
00424 }
00425
00429 TIMESTAMP house::presync(TIMESTAMP t0, TIMESTAMP t1)
00430 {
00431
00432 lights_heat_energy = 0.0;
00433 range_heat_energy = 0.0;
00434 occupantload_heat_energy = 0.0;
00435 plugload_heat_energy = 0.0;
00436 microwave_heat_energy = 0.0;
00437 dishwasher_heat_energy = 0.0;
00438 clotheswasher_heat_energy = 0.0;
00439 waterheater_heat_energy = 0.0;
00440
00441
00442 power_kw = 0;
00443 return TS_NEVER;
00444 }
00445
00450 TIMESTAMP house::sync(TIMESTAMP t0, TIMESTAMP t1)
00451 {
00452 TIMESTAMP sync_time = TS_NEVER;
00453
00454 total_internal_gain = (lights_heat_energy + range_heat_energy + occupantload_heat_energy +
00455 plugload_heat_energy + microwave_heat_energy +
00456 dishwasher_heat_energy + clotheswasher_heat_energy + waterheater_heat_energy) * BTUPHPW;
00457
00458 TIMESTAMP hvac_sync = sync_hvac_load(t1, (gl_tohours(t1)- gl_tohours(t0))/TS_SECOND);
00459
00460 if (sync_time > hvac_sync)
00461 sync_time = hvac_sync;
00462
00463 OBJECT *obj = OBJECTHDR(this);
00464
00465
00466 complex I[3]; I[X12] = I[X23] = I[X13] = complex(0,0);
00467
00468
00469 CIRCUIT *c;
00470 for (c=panel.circuits; c!=NULL; c=c->next)
00471 {
00472
00473 int n = (int)c->type;
00474 if (n<0 || n>2)
00475 GL_THROW("%s:%d circuit %d has an invalid circuit type (%d)", obj->oclass->name, obj->id, c->id, (int)c->type);
00476
00477
00478 if (c->status==BRK_OPEN && t1>=c->reclose)
00479 {
00480 c->status = BRK_CLOSED;
00481 c->reclose = TS_NEVER;
00482 sync_time = t1;
00483 gl_debug("house:%d panel breaker %d closed", obj->id, c->id);
00484 }
00485
00486
00487 if (c->status==BRK_CLOSED)
00488 {
00489
00490 if ((c->pV)->Mag() == 0)
00491 {
00492 gl_debug("house:%d circuit voltage is zero", obj->id);
00493 break;
00494 }
00495
00496 complex current = ~((*(c->pS)) / *(c->pV)) * 1000;
00497
00498
00499 if (current.Mag()>c->max_amps)
00500 {
00501
00502 if (c->tripsleft>0 && gl_random_bernoulli(1/(c->tripsleft--))==0)
00503 {
00504
00505 c->status = BRK_OPEN;
00506
00507
00508 c->reclose = t1 + (TIMESTAMP)(gl_random_exponential(1/300.0)*TS_SECOND);
00509 gl_debug("house:%d panel breaker %d tripped", obj->id, c->id);
00510 }
00511
00512
00513 else
00514 {
00515 c->status = BRK_FAULT;
00516 c->reclose = TS_NEVER;
00517 gl_debug("house:%d panel breaker %d failed", obj->id, c->id);
00518 }
00519
00520
00521 sync_time = t1;
00522 }
00523
00524
00525 else
00526 {
00527 I[n] += current;
00528 c->reclose = TS_NEVER;
00529 }
00530 }
00531
00532
00533 if (sync_time > c->reclose)
00534 sync_time = c->reclose;
00535
00536 }
00537
00539
00540
00541 if (obj->parent != NULL)
00542 LOCK_OBJECT(obj->parent);
00543
00544 pLine_I[0] = I[X12]-I[X13];
00545 pLine_I[1] = I[X23]-I[X12];
00546 pLine_I[2] = I[X13]-I[X23];
00547
00548 if (obj->parent != NULL)
00549 UNLOCK_OBJECT(obj->parent);
00550
00551 return sync_time;
00552
00553 }
00554
00562 TIMESTAMP house::sync_hvac_load(TIMESTAMP t1, double nHours)
00563 {
00564
00565 const double heating_cop_adj = (-0.0063*(*pTout)+1.5984);
00566 const double cooling_cop_adj = -(-0.0108*(*pTout)+2.0389);
00567 const double heating_capacity_adj = (-0.0063*(*pTout)+1.5984);
00568 const double cooling_capacity_adj = -(-0.0063*(*pTout)+1.5984);
00569
00570 double t = 0.0;
00571
00572 if (heat_cool_mode == HEAT)
00573 {
00574 hvac_rated_capacity = design_heating_capacity*floor_area*heating_capacity_adj;
00575 hvac_rated_power = hvac_rated_capacity/(heating_COP * heating_cop_adj);
00576 }
00577 else if (heat_cool_mode == COOL)
00578 {
00579 hvac_rated_capacity = design_cooling_capacity*floor_area*cooling_capacity_adj;
00580 hvac_rated_power = hvac_rated_capacity/(cooling_COP * cooling_cop_adj);
00581 }
00582 else
00583 {
00584 hvac_rated_capacity = 0.0;
00585 hvac_rated_power = 0.0;
00586 }
00587
00588 power_kw = hvac_rated_power*KWPBTUPH;
00589 hvac_kWh_use = power_kw.Mag()*nHours;
00590
00591 DATETIME tv;
00592 gl_localtime(t1, &tv);
00593
00594 Tsolar = get_Tsolar(tv.hour, tv.month, Tair, *pTout);
00595 solar_load = 0.0;
00596
00597 for (int i = 1; i<9; i++)
00598 {
00599 solar_load += (gross_wall_area*window_wall_ratio/8.0) * glazing_shgc * pSolar[i];
00600 }
00601 double netHeatrate = hvac_rated_capacity + total_internal_gain + solar_load;
00602 double Q1 = M_inv11*Tair + M_inv12*Tmaterials;
00603 double Q2 = M_inv21*Tair + M_inv22*Tmaterials;
00604
00605 if (nHours > ROUNDOFF)
00606 {
00607 double q1 = exp(s1*nHours)*(Q1 + BB11*Tsolar/s1 + BB12*netHeatrate/s1) - BB11*Tsolar/s1
00608 - BB12*netHeatrate/s1;
00609 double q2 = exp(s2*nHours)*(Q2 - BB11*Tsolar/s2 - BB12*netHeatrate/s2) + BB11*Tsolar/s2
00610 + BB12*netHeatrate/s2;
00611
00612 Tair = q1*(s1-A22)/A21 + q2*(s2-A22)/A21;
00613 Tmaterials = q1 + q2;
00614 }
00615 else
00616 return TS_NEVER;
00617
00618
00619 const double W = (Q1 + (BB11*Tsolar)/s1 + BB12*netHeatrate/s1)*(s1-A22)/A21;
00620 const double X = (BB11*Tsolar/s1 + BB12*netHeatrate/s1)*(s1-A22)/A21;
00621 const double Y = (Q2 - (BB11*Tsolar)/s2 - BB12*netHeatrate/s2)*(s2-A22)/A21;
00622 const double Z = (BB11*Tsolar/s2 + BB12*netHeatrate/s2)*(s2-A22)/A21;
00623
00624
00625
00626 int n_solutions = 0;
00627 double Tevent;
00628 const double TcoolOn = cooling_setpoint+thermostat_deadband;
00629 const double TcoolOff = cooling_setpoint-thermostat_deadband;
00630 const double TheatOn = heating_setpoint-thermostat_deadband;
00631 const double TheatOff = heating_setpoint+thermostat_deadband;
00632
00633
00634 #define TPREC 0.01
00635 if (hvac_rated_capacity < 0.0)
00636 Tevent = TcoolOff;
00637 else if (hvac_rated_capacity > 0.0)
00638 Tevent = TheatOff;
00639 else if (Tair <= TheatOn+TPREC)
00640 Tevent = TheatOn;
00641 else if (Tair >= TcoolOn-TPREC)
00642 Tevent = TcoolOn;
00643 else
00644 return TS_NEVER;
00645
00646 #ifdef OLD_SOLVER
00647 if (nHours > TPREC)
00648
00649 n_solutions = dual_decay_solve(&t,TPREC,0.0 ,nHours,W,s1,Y,s2,Z-X-Tevent);
00650
00651 Tair = Tevent;
00652
00653 if (n_solutions<0)
00654 gl_error("house: solver error");
00655 else if (n_solutions == 0)
00656 return TS_NEVER;
00657 else if (t == 0)
00658 t = 1.0/3600.0;
00659 return t1+(TIMESTAMP)(t*3600*TS_SECOND);
00660 #else
00661 t = e2solve(W,s1,Y,s2,Z-X-Tevent);
00662 if (isfinite(t))
00663 return t1+(TIMESTAMP)(t*3600*TS_SECOND);
00664 else
00665 return TS_NEVER;
00666 #endif
00667
00668
00669 }
00670
00671 int house::set_Eigen_values()
00672 {
00673
00674
00675
00676 if (envelope_UA <= ROUNDOFF || house_content_heat_transfer_coeff <= ROUNDOFF ||
00677 air_thermal_mass <= ROUNDOFF || house_content_thermal_mass <= ROUNDOFF)
00678 {
00679 gl_error("House thermal mass or UA invalid. Eigen values not set.");
00680 return FALSE;
00681 }
00682
00683 double ra = 1/envelope_UA;
00684 double rm = 1/house_content_heat_transfer_coeff;
00685
00686 A11 = -1.0/(air_thermal_mass*rm) - 1.0/(ra*air_thermal_mass);
00687 A12 = 1.0/(rm*air_thermal_mass);
00688 A21 = 1.0/(rm*house_content_thermal_mass);
00689 A22 = -1.0/(rm*house_content_thermal_mass);
00690
00691 B11 = 1.0/(air_thermal_mass*ra);
00692 B12 = 1.0/air_thermal_mass;
00693 B21 = 0.0;
00694 B22 = 0.0;
00695
00696
00697 s1 = (A11 + A22 + sqrt((A11 + A22)*(A11 + A22) - 4*(A11*A22 - A21*A12)))/2.0;
00698 s2 = (A11 + A22 - sqrt((A11 + A22)*(A11 + A22) - 4*(A11*A22 - A21*A12)))/2.0;
00699
00700
00701 double M11 = (s1 - A22)/A21;
00702 double M12 = (s2 - A22)/A21;
00703 double M21 = 1.0;
00704 double M22 = 1.0;
00705
00706 double demoninator = (s1 - A22)/A21 - (s2-A22)/A21;
00707 M_inv11 = 1.0/demoninator;
00708 M_inv12 = -((s2 - A22)/A21)/demoninator;
00709 M_inv21 = -1.0/demoninator;
00710 M_inv22 = ((s1-A22)/A21)/demoninator;
00711
00712 BB11 = M_inv11*B11 + M_inv12*B21;
00713 BB21 = M_inv21*B11 + M_inv22*B21;
00714 BB12 = M_inv11*B12 + M_inv12*B22;
00715 BB22 = M_inv21*B12 + M_inv22*B22;
00716
00717 return TRUE;
00718 }
00724 double house::get_Tsolar(int hour, int month, double Tair, double Tout)
00725 {
00726
00727 static double CLTD[] = {4.25, 2.75, 1.63, 0.50, -0.50, 3.50, 11.25, 17.88, 22.50, 25.88, 27.88, 29.25, 31.63, 35.13, 38.50, 40.38, 36.88, 28.00, 19.00, 14.00, 11.13, 8.63, 6.25};
00728
00729 static double LM[4][24] = {
00730 {-1.33, -1.44, -0.89, -1.00, -0.67, -0.44, -0.67, -1.00, -0.89, -1.44, -1.33, -1.22},
00731 {-2.89, -1.89, -0.78, -0.44, -0.11, -0.11, -0.11, -0.44, -0.78, -1.89, -2.89, -4.67},
00732 {-5.44, -3.22, -1.11, -0.11, 0.22, 0.67, 0.22, -0.11, -1.11, -3.22, -5.44, -6.33},
00733 {-7.56, -5.11, -1.78, -0.11, 1.33, 2.00, 1.33, -0.11, -1.78, -5.11, -7.56}
00734 };
00735
00736 static double ColorSurface = 0.75;
00737 static double DR = 15.0;
00738 double solarTemp = Tair;
00739 double LMnow = 0.0;
00740 int LMcol = month-1;
00741
00742 OBJECT *hdr = OBJECTHDR(this);
00743
00744 if (hdr->latitude <= 24.0)
00745 LMnow = LM[0][LMcol];
00746 else if (hdr->latitude <= 32.)
00747 LMnow = LM[0][LMcol] + ((LM[1][LMcol]-LM[0][LMcol])*(hdr->latitude-24.0)/12.0);
00748 else if (hdr->latitude <= 40.)
00749 LMnow = LM[1][LMcol] + ((LM[2][LMcol]-LM[1][LMcol])*(hdr->latitude-32.0)/12.0);
00750 else if (hdr->latitude <= 48.)
00751 LMnow = LM[2][LMcol] + ((LM[3][LMcol]-LM[2][LMcol])*(hdr->latitude-40.0)/12.0);
00752 else
00753 LMnow = LM[3][LMcol];
00754
00755 solarTemp += (CLTD[hour] + LMnow)*ColorSurface + (78. - Tair) + ((*pTout) - DR/2. - 85.);
00756
00757 return solarTemp;
00758 }
00759
00760
00761
00762 complex *house::get_complex(OBJECT *obj, char *name)
00763 {
00764 PROPERTY *p = gl_get_property(obj,name);
00765 if (p==NULL || p->ptype!=PT_complex)
00766 return NULL;
00767 return (complex*)GETADDR(obj,p);
00768 }
00769
00771
00773
00774 EXPORT int create_house(OBJECT **obj, OBJECT *parent)
00775 {
00776 *obj = gl_create_object(house::oclass,sizeof(house));
00777 if (*obj!=NULL)
00778 {
00779 house *my = OBJECTDATA(*obj,house);;
00780 gl_set_parent(*obj,parent);
00781 my->create();
00782 return 1;
00783 }
00784 return 0;
00785 }
00786
00787 EXPORT int init_house(OBJECT *obj)
00788 {
00789 house *my = OBJECTDATA(obj,house);
00790 my->init_climate();
00791 return my->init(obj->parent);
00792 }
00793
00794 EXPORT TIMESTAMP sync_house(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00795 {
00796 house *my = OBJECTDATA(obj,house);
00797 TIMESTAMP t1 = TS_NEVER;
00798 if (obj->clock <= ROUNDOFF)
00799 obj->clock = t0;
00800
00801 try {
00802 switch (pass)
00803 {
00804 case PC_PRETOPDOWN:
00805 t1 = my->presync(obj->clock, t0);
00806 break;
00807
00808 case PC_BOTTOMUP:
00809 t1 = my->sync(obj->clock, t0);
00810 obj->clock = t0;
00811 break;
00812
00813 default:
00814 gl_error("house::sync- invalid pass configuration");
00815 t1 = TS_INVALID;
00816 }
00817 }
00818 catch (char *msg)
00819 {
00820 gl_error("house::sync exception caught: %s", msg);
00821 t1 = TS_INVALID;
00822 }
00823 catch (...)
00824 {
00825 gl_error("house::sync exception caught: no info");
00826 t1 = TS_INVALID;
00827 }
00828 return t1;
00829 }
00830
00831 EXPORT TIMESTAMP plc_house(OBJECT *obj, TIMESTAMP t0)
00832 {
00833
00834 if (obj->clock <= ROUNDOFF)
00835 obj->clock = t0;
00836
00837 house *my = OBJECTDATA(obj,house);
00838 return my->thermostat(obj->clock, t0);
00839 }
00840