solar_panel.cc

00001 
00008 #include "solar_panel.h"
00009 #include <string.h>
00010 
00011 // Prototypes
00012 ml_matrix sun_vector(double jd);
00013 ml_matrix earth_rot(double jcent);
00014 double gms_time(double jd);
00015 double jd_to_midnight(double jd);
00016 double jd_to_jcent(double jd);
00017 
00018 // The number of radians in 1 degree.
00019 const double DEGREES_TO_RADIANS = 0.0174532925199433;
00020 // The number of degrees in 1 revolution.
00021 const double REVS_TO_DEGREES = 360.0;
00022 // Julian date value for 2000-01-01 12:00:00+00.
00023 const double JD_2000 = 2451545.0;
00024 // Inverse of DAYS_TO_SECS.
00025 const double SECS_TO_DAYS = 1.157407407407407e-05;
00026 //å Inverse of CENTURIES_TO_DAYS.
00027 const double DAYS_TO_CENTURIES = 2.737850787132101e-05;
00028 
00029 
00030 
00031 solar_panel :: solar_panel(dsim_model_setup *setup) : dsim_model(setup)
00032 {
00033 }
00034 
00035 void solar_panel :: initialize_data()
00036 {
00037         dsim_model::initialize_data();
00038         
00039         double power_total = 0;
00040         ml_matrix normal(3,1);          normal(1,1) = 1;
00041         ml_matrix area(1,1);            area(1,1) = 25;
00042         ml_matrix efficiency(1,1);      efficiency(1,1) = 0.22;
00043     
00044         power_dsim                      =       create_output("power",                  sd_type_double, &power_total,   1,1,    "W",    "Power panel"); 
00045         normal_dsim                     =       create_parameter("normal",      sd_type_matrix, &normal,                3,1,    "",             "Solar panel cell face normal");        
00046         area_dsim                       =       create_parameter("area",        sd_type_matrix, &area,                  1,1,    "m^2",  "Solar panel area");    ;
00047         efficiency_dsim         =       create_parameter("efficiency",  sd_type_matrix, &efficiency,    1,1,    "",             "Solar panel efficiency");      
00048         
00049         power_dsim.mark_telemetry();
00050         
00051         configure_timestep(true, false, false);
00052         
00053 }
00054 
00055 void solar_panel :: initialization_complete()
00056 {
00057     dsim_model::initialization_complete();
00058 }
00059 
00060 void solar_panel :: pre_calculate()
00061 {
00062         dsim_model::initialize_timestep();      
00063         
00064         double jd               = sim_jd();
00065     ml_matrix solar_flux    = 1000*earth_rot(jd)*sun_vector(jd);
00066         ml_matrix n             = normal_dsim.value_as_matrix();
00067         ml_matrix area          = area_dsim.value_as_matrix();
00068         ml_matrix eff           = efficiency_dsim.value_as_matrix();
00069 
00070         double p;
00071         double power_total = 0;
00072 
00073         for( int k = 1; k <= n.cols(); k++ )
00074         {
00075                 p = area.get(1,k)*eff.get(1,k)*solar_flux.dot(n.get_col(k));
00076                 if( p < 0 ) p = 0;
00077                 power_total += p;
00078         }
00079         
00080         power_dsim.set_value_as_double( power_total );
00081 }
00082 
00083 double jd_to_midnight(double jd)
00084 {
00085     double jd_noon = floor(jd);
00086     return (jd - jd_noon >= 0.5) ? (jd_noon + 0.5) : (jd_noon - 0.5);
00087 }
00088 
00089 double jd_to_jcent(double jd)
00090 {
00091         return (jd - JD_2000) * DAYS_TO_CENTURIES;
00092 }
00093 
00094 double gms_time(double jd)
00095 {
00096     // Julian days at 0h UT
00097     double jd_mid = jd_to_midnight(jd);
00098     double t_diff = jd_to_jcent(jd_mid);
00099     
00100     // This organization maximizes the precision
00101     double gmst = ((0.093104 - 6.2e-6*t_diff)*t_diff + 8640184.812866)*t_diff + 24110.54841;
00102     
00103     // Account for earth rotation
00104     gmst *= SECS_TO_DAYS;
00105     gmst += jd-jd_mid;
00106     
00107     // Limit to the range of 0 to 360 degrees
00108     gmst = fmod(gmst*360, 360); 
00109     if (gmst < 0)
00110     {
00111         gmst = gmst + 360;
00112     }
00113     return gmst; 
00114 }  
00115 
00116 
00117 ml_matrix earth_rot(double jd)
00118 {
00119     // Find Greenwich Mean Sidereal Time
00120     double gmst = gms_time(jd);
00121     double sin_gmst = sin(gmst * DEGREES_TO_RADIANS);
00122     double cos_gmst = cos(gmst * DEGREES_TO_RADIANS);
00123     ml_matrix b(3,3);
00124     b(1,1) = cos_gmst;
00125     b(1,2) = sin_gmst;
00126     b(2,1) = -sin_gmst;
00127     b(2,2) = cos_gmst;
00128     b(3,3) = 1;
00129     return b;
00130 }
00131 
00132 
00133 ml_matrix sun_vector(double jd)
00134 {
00135     // Mean anomaly
00136     double t_diff = jd - JD_2000;
00137     double g = fmod((357.528 + 0.9856003 * t_diff),REVS_TO_DEGREES) * DEGREES_TO_RADIANS; 
00138     // Ecliptic longitude
00139     double lam = (fmod(280.460 + 0.9856474 * t_diff, REVS_TO_DEGREES) + 1.915*sin(g) + 0.02*sin(2.0*g)) * DEGREES_TO_RADIANS;
00140     
00141     // Obliquity of the ecliptic
00142     double ob_of_e = (23.439 - 4.00e-7 * t_diff) * DEGREES_TO_RADIANS;
00143     
00144     // Equatorial rectangular coordinates of the Sun
00145     double s_lam  = sin(lam);
00146     ml_matrix s_vec(3,1);
00147     s_vec(1,1) = cos(lam);
00148     s_vec(2,1) = cos(ob_of_e)*s_lam;
00149     s_vec(3,1) = sin(ob_of_e)*s_lam;
00150     return s_vec;
00151 }
00152 
00153 
00154 
00155 extern "C"
00156 {
00157     
00158     dsim_model *SolarPanelModel(void *setup);
00159 
00160         dsim_model *SolarPanelModel(void *setup)
00161         {
00162                 return new solar_panel((dsim_model_setup *)setup);
00163         }
00164 }
 All Classes Files Functions Variables