00001
00005 #include "appliance.h"
00006
00007 EXPORT_CREATE(appliance);
00008 EXPORT_INIT(appliance);
00009 EXPORT_PRECOMMIT(appliance);
00010 EXPORT_SYNC(appliance);
00011 EXPORT_NOTIFY(appliance);
00012
00013 CLASS *appliance::oclass = NULL;
00014 CLASS *appliance::pclass = NULL;
00015 appliance *appliance::defaults = NULL;
00016
00017 appliance::appliance(MODULE *module) : residential_enduse(module)
00018 {
00019 if ( oclass==NULL )
00020 {
00021 pclass = residential_enduse::oclass;
00022 oclass = gl_register_class(module,"appliance",sizeof(appliance),PC_PRETOPDOWN|PC_AUTOLOCK);
00023 if ( oclass==NULL )
00024 GL_THROW("unable to register object class implemented by %s",__FILE__);
00025 if ( gl_publish_variable(oclass,
00026 PT_INHERIT,"residential_enduse",
00027 PT_complex_array, "powers",get_power_offset(),
00028 PT_complex_array, "impedances",get_impedance_offset(),
00029 PT_complex_array, "currents",get_current_offset(),
00030 PT_double_array, "durations",get_duration_offset(),
00031 PT_double_array, "transitions",get_transition_offset(),
00032 PT_double_array, "heatgains", get_heatgain_offset(),
00033 NULL)<1 )
00034 GL_THROW("unable to publish properties in %s",__FILE__);
00035 }
00036 }
00037
00038 appliance::~appliance()
00039 {
00040 }
00041
00042 int appliance::create()
00043 {
00044 int res = residential_enduse::create();
00045 return res;
00046 }
00047
00048 int appliance::init(OBJECT *parent)
00049 {
00050
00051 gl_warning("This device, %s, is considered very experimental and has not been validated.", get_name());
00052
00053
00054 if ( duration.get_rows()!=1 )
00055 exception("duration must have 1 rows (it has %d)", n_states, duration.get_rows());
00056
00057
00058 n_states = (unsigned int)duration.get_cols();
00059 if ( state<0 || state>=n_states )
00060 exception("initial state must be between 0 and %d, inclusive", n_states-1);
00061 gl_debug("n_states = %d (initial state is %d)", n_states, state);
00062
00063
00064 if ( ( transition.get_rows()!=1 && transition.get_rows()!=n_states ) || transition.get_cols()!=n_states )
00065 exception("transition must have either 1r x %dc or %dr x %dc (it is %dr c %dc)", n_states, n_states, n_states, transition.get_rows(), transition.get_cols());
00066
00067
00068 if ( impedance.is_empty() )
00069 {
00070 impedance.grow_to(0,n_states-1);
00071 complex zero(0);
00072 impedance = zero;
00073 }
00074 if ( impedance.get_rows()!=1 || impedance.get_cols()!=n_states )
00075 exception("impedance must 1r x %dc (it is %dr x %dc)", n_states, impedance.get_rows(), impedance.get_cols());
00076
00077
00078 if ( current.is_empty() )
00079 {
00080 current.grow_to(0,n_states-1);
00081 complex zero(0);
00082 current = zero;
00083 }
00084 if ( current.get_rows()!=1 || current.get_cols()!=n_states )
00085 exception("current must 1r x %dc (it is %dr x %dc)", n_states, current.get_rows(), current.get_cols());
00086
00087
00088 if ( power.is_empty() )
00089 {
00090 power.grow_to(0,n_states-1);
00091 complex zero(0);
00092 power = zero;
00093 }
00094 if ( power.get_rows()!=1 || power.get_cols()!=n_states )
00095 exception("power must 1r x %dc (it is %dr x %dc)", n_states, power.get_rows(), power.get_cols());
00096
00097
00098 if ( heatgain.is_empty() )
00099 {
00100 heatgain.grow_to(0,n_states-1);
00101 heatgain = 0;
00102 }
00103 if ( heatgain.get_rows()!=1 || heatgain.get_cols()!=n_states )
00104 exception("current must 1r x %dc (it is %dr x %dc)", n_states, heatgain.get_rows(), heatgain.get_cols());
00105
00106
00107 if ( transition.get_rows()>1 )
00108 transition_probabilities = new double[n_states];
00109
00110
00111 update_next_t();
00112 return residential_enduse::init(parent);
00113 }
00114
00115 void appliance::update_next_t(void)
00116 {
00117 double transition_probability = transition.get_at(0,state);
00118 if ( !isfinite(transition_probability) )
00119 {
00120
00121 next_t = gl_globalclock + (TIMESTAMP)duration.get_at(0,state);
00122 gl_debug("%s: non-probabilistic transition scheduled at %lld", get_name(), next_t);
00123 }
00124 else if ( gl_random_uniform(&my()->rng_state,0,1)<transition_probability )
00125 {
00126
00127 next_t = gl_globalclock + (TIMESTAMP)gl_random_uniform(&my()->rng_state,1,duration.get_at(0,state));
00128 gl_debug("%s: transition scheduled at %lld", get_name(), next_t);
00129 }
00130 else
00131 {
00132
00133 next_t = -(gl_globalclock + (TIMESTAMP)duration.get_at(0,state));
00134 gl_debug("%s: no transition scheduled prior to %lld", get_name(), next_t);
00135 }
00136 }
00137 void appliance::update_power(void)
00138 {
00139 complex Z = impedance.get_at(0,state);
00140 load.admittance = Z.Mag()==0 ? complex(0) : complex(1)/Z;
00141 load.current = current.get_at(0,state);
00142 load.power = power.get_at(0,state);
00143 load.heatgain = heatgain.get_at(0,state);
00144 }
00145 void appliance::update_state(void)
00146 {
00147 if ( transition_probabilities==NULL )
00148 {
00149
00150 state = (state+1)%n_states;
00151 gl_debug("%s: now in state %d", get_name(), state);
00152 }
00153 else
00154 {
00155
00156 transition.extract_row(transition_probabilities,state);
00157
00158
00159 double rn = gl_random_uniform(&my()->rng_state,0,1);
00160
00161
00162 int n;
00163 for ( n=0 ; n<n_states ; n++ )
00164 {
00165 rn -= transition_probabilities[n];
00166 if ( rn<0 )
00167 {
00168 state = n;
00169 gl_debug("%s: now in state %d", get_name(), state);
00170 break;
00171 }
00172 }
00173 }
00174 update_power();
00175 }
00176
00177 int appliance::precommit(TIMESTAMP t1)
00178 {
00179 gld_clock now;
00180
00181
00182 if ( now==(next_t<0?-next_t:next_t) )
00183 {
00184 update_state();
00185 update_next_t();
00186 return 1;
00187 }
00188
00189
00190 else if ( next_t<0 )
00191 {
00192 if ( now>-next_t )
00193 update_next_t();
00194 return 1;
00195 }
00196
00197
00198 else if ( now>next_t )
00199 {
00200 gl_error("%s: transition at %lld missed", get_name(), next_t);
00201 return 0;
00202 }
00203
00204
00205 else
00206 {
00207 return 1;
00208 }
00209 }
00210
00211 TIMESTAMP appliance::presync(TIMESTAMP t1)
00212 {
00213 return next_t;
00214 }
00215
00216 int appliance::postnotify(PROPERTY *prop, char *value)
00217 {
00218
00219 return 1;
00220 }