Beispiel #1
0
/**
	Evaluation function for 'sunpos'
	@return 0 on success
*/
static int sunpos_nrel_calc(struct BBoxInterp *bbox,
		int ninputs, int noutputs,
		double *inputs, double *outputs,
		double *jacobian
){
	CALCPREPARE(4,2);

	double t, p, T, t_offset;

	t = inputs[0]; /* convert from JD seconds to JD days */
	p = inputs[1] / 100. /* convert Pa to mbar */;
	T = inputs[2] - 273.15 /* convert °C to K */;
	t_offset = inputs[3];

	spa_data S = *sunpos1;
	S.pressure = p;
	S.temperature = T;
	S.jd = (t + t_offset) / 3600 / 24; /* convert to days */

	int res = spa_calculate(&S);
	//CONSOLE_DEBUG("Sun position: t = %f JD, p  %f mbar, T = %f C: res = %d, az = %f, zen = %f",S.jd, p, T, res, S.azimuth, S.zenith);

	/* returned values are in degrees, need to convert back to base SI: radians */
	outputs[0] = S.zenith * PI/180.;
	outputs[1] = S.azimuth180 * PI/180.;

	switch(res){
	case 0: break;
	case 16: CONSOLE_DEBUG("Calculated julian day (t + offset) = %f is out of permitted range",S.jd); break;
	default: CONSOLE_DEBUG("Error code %d returned from spa_calculate",res);
	}

	/* 0 on success, non-zero is error code from spa_calculate (would prob be input parameters out-of-range) */
	return res;
}
int main (int argc, char *argv[])
{
    spa_data spa;  //declare the SPA structure
    int result;
    float min, sec;

    //enter required input values into SPA structure

    spa.year          = 2003;
    spa.month         = 10;
    spa.day           = 17;
    spa.hour          = 12;
    spa.minute        = 30;
    spa.second        = 30;
    spa.timezone      = -7.0;
    spa.delta_ut1     = 0;
    spa.delta_t       = 67;
    spa.longitude     = -105.1786;
    spa.latitude      = 39.742476;
    spa.elevation     = 1830.14;
    spa.pressure      = 820;
    spa.temperature   = 11;
    spa.slope         = 30;
    spa.azm_rotation  = -10;
    spa.atmos_refract = 0.5667;
    spa.function      = SPA_ALL;

    //call the SPA calculate function and pass the SPA structure

    result = spa_calculate(&spa);

    if (result == 0)  //check for SPA errors
    {
        //display the results inside the SPA structure

        printf("Julian Day:    %.6f\n",spa.jd);
        printf("L:             %.6e degrees\n",spa.l);
        printf("B:             %.6e degrees\n",spa.b);
        printf("R:             %.6f AU\n",spa.r);
        printf("H:             %.6f degrees\n",spa.h);
        printf("Delta Psi:     %.6e degrees\n",spa.del_psi);
        printf("Delta Epsilon: %.6e degrees\n",spa.del_epsilon);
        printf("Epsilon:       %.6f degrees\n",spa.epsilon);
        printf("Zenith:        %.6f degrees\n",spa.zenith);
        printf("Azimuth:       %.6f degrees\n",spa.azimuth);
        printf("Incidence:     %.6f degrees\n",spa.incidence);

        min = 60.0*(spa.sunrise - (int)(spa.sunrise));
        sec = 60.0*(min - (int)min);
        printf("Sunrise:       %02d:%02d:%02d Local Time\n", (int)(spa.sunrise), (int)min, (int)sec);

        min = 60.0*(spa.sunset - (int)(spa.sunset));
        sec = 60.0*(min - (int)min);
        printf("Sunset:        %02d:%02d:%02d Local Time\n", (int)(spa.sunset), (int)min, (int)sec);

    } else printf("SPA Error Code: %d\n", result);

    return 0;
}
Beispiel #3
0
int calculate_position(spa_data *spa, struct tm *t)
{
	int result;
	spa->year          = t->tm_year + 1900;
	spa->month         = t->tm_mon + 1;
	spa->day           = t->tm_mday;
	spa->hour          = t->tm_hour;
	spa->minute        = t->tm_min;
	spa->second        = t->tm_sec;
	result = spa_calculate(spa);
	return result;
}
Beispiel #4
0
void SunPos (int t, double latitude, double longitude, double elevation,
    double tmp, double *zenith, double *azimuth)
{
    spa_data        spa;
    int             spa_result;
    time_t          rawtime;
    struct tm      *timestamp;

    rawtime = (time_t) t;
    timestamp = gmtime (&rawtime);

    spa.year = timestamp->tm_year + 1900;
    spa.month = timestamp->tm_mon + 1;
    spa.day = timestamp->tm_mday;
    spa.hour = timestamp->tm_hour;
    spa.minute = timestamp->tm_min;
    spa.second = timestamp->tm_sec;
    spa.timezone = 0;

    spa.delta_t = 67;
    spa.delta_ut1 = 0;
    spa.atmos_refract = 0.5667;

    spa.longitude = longitude;
    spa.latitude = latitude;

    spa.elevation = elevation;

    /* Calculate surface pressure based on fao 1998 method (narasimhan 2002) */
    spa.pressure =
        1013.25 * pow ((293.0 - 0.0065 * spa.elevation) / 293.0, 5.26);
    spa.temperature = tmp;

    spa.function = SPA_ZA;
    spa_result = spa_calculate (&spa);

    if (spa_result != 0)
    {
        printf ("spa error code: %d\n", spa_result);
        PihmExit (1);
    }

    *azimuth = Mod ((360.0 + spa.azimuth180), 360.0);
    *zenith = spa.zenith;
}
Beispiel #5
0
///////////////////////////////////////////////////////
//For easy integration into the VTP
//
void SetCommonValues(spa_data &spa, float longitude, float latitude,
			   int year, int month, int day, int hour, int minute,
			   int second, float timezone, float elevation)
{
	spa.year = year;
	spa.month = month;
	spa.day = day;
	spa.hour= hour;
	spa.minute= minute;
	spa.second = second;
	spa.delta_t = 67.0f;	// Found this value somewhere on the Internet (seems to work).
	spa.timezone = timezone;
	spa.longitude = longitude;
	spa.latitude = latitude;
	spa.elevation = elevation;
	spa.pressure=800.0f;	// A reasonable value (?) ~ most users/locations are somewhat above sea level
	spa.temperature =18.0f;	// A reasonable value ~ about average for most inhabited places
	spa.slope = 0.0f;		// I think this is for a solar panel; we want flat ground.
	spa.azm_rotation=0.0f;	// I think this is for a solar panel; we want flat ground.
	spa.atmos_refract=0.5667f;

	spa_calculate(&spa);
}
Beispiel #6
0
static PyObject *spa_calc(PyObject *self, PyObject *args)
{
    int N_IN, N_DOUBLE_IN, N_ARRAY_IN, N_DOUBLE_OUT, N_ARRAY_OUT, N;
    
    PyObject *input_obj[PYSPA_MAX_ARGS];
    double    input_double[PYSPA_MAX_ARGS];
    
    PyArrayObject *input_arr[PYSPA_MAX_ARGS],     *output_arr[PYSPA_MAX_ARGS];
    double        *input_arr_ptr[PYSPA_MAX_ARGS], *output_arr_ptr[PYSPA_MAX_ARGS];
    int            input_arr_map[PYSPA_MAX_ARGS], input_double_map[PYSPA_MAX_ARGS], input_type[PYSPA_MAX_ARGS];
    
    double    year=0, month=0, day=0, hour=0, minute=0, second=0, latitude=0, longitude=0, elevation=0, slope=0, aspect=0;
    double    zenith, azimuth, incidence;
    double    value;
    
    int       flag;
    
    int       i, j, ndim, dims[NPY_MAXDIMS], rc=0;
    spa_data  spa;
    
    static const double m_air   = 0.02896; // molecular mass of air, kg mol^-1
    static const double R_const = 8.3143;  // gas constant, N M mol^-1 K^-1
    static const double g_const = 9.807;   // gravity constant, m s^-2
    static const double T_const = 288.15;  // "default" air temperature, K
        
    /* Parse the input tuple */
    for (i=0; i<64; i++) input_obj[i] = NULL;
    if (!PyArg_ParseTuple(args, "OOOOOOOO|OOO", &input_obj[0], &input_obj[1], &input_obj[2], &input_obj[3], &input_obj[4], 
                                                &input_obj[5], &input_obj[6], &input_obj[7], &input_obj[8], &input_obj[9], &input_obj[10]))
        return NULL;
    
    if (input_obj[8] == NULL) {
        // fprintf(stderr, "Running SPA_ZA mode ...\n");
        spa.function = SPA_ZA;
        N_IN         = 8;
        N_DOUBLE_OUT = 0;
        N_ARRAY_OUT  = 2;
    }
    else {
        // fprintf(stderr, "Running SPA_ZA_INC mode ...\n");
        spa.function = SPA_ZA_INC;
        N_IN         = 11;
        N_DOUBLE_OUT = 0;
        N_ARRAY_OUT  = 3;
    }
    
    N_DOUBLE_IN = 0;
    N_ARRAY_IN  = 0;
    for (i=0; i<N_IN; i++) {
        /* Interpret the input objects as numpy arrays. */
        input_arr[i] = (PyArrayObject *) PyArray_FROM_OTF(input_obj[i], NPY_DOUBLE, NPY_IN_ARRAY);
        /* Is is really a numpy array? */
        if (PyArray_NDIM(input_arr[i])==0) {
            input_type[i] = 0;
            input_double_map[N_DOUBLE_IN] = i;
            N_DOUBLE_IN++;
            input_double[i] = PyFloat_AsDouble(input_obj[i]);
            Py_XDECREF(input_arr[i]);
        }
        else {
            input_type[i] = 1;
            input_arr_map[N_ARRAY_IN] = i;
            N_ARRAY_IN++;
        }
    }
    
    /* If that didn't work, throw an exception. */
    flag = 0; for (i=0; i<N_ARRAY_IN; i++) if (input_arr[input_arr_map[i]]==NULL) flag = 1;
    if (flag==1) {
        for (i=0; i<N_ARRAY_IN; i++) Py_XDECREF(input_arr[input_arr_map[i]]);
        return NULL;
    }
    
    /* Get pointers to the data as C-types. */
    for (i=0; i<N_ARRAY_IN; i++) input_arr_ptr[input_arr_map[i]] = (double*) PyArray_DATA(input_arr[input_arr_map[i]]);
    
    /* How many data points are there? */
    ndim = (int)PyArray_NDIM(input_arr[input_arr_map[0]]);
    
    N=1;
    for (j=0; j<ndim; j++) {
         dims[j] = PyArray_DIM(input_arr[input_arr_map[0]], j);
         N *= dims[j];
         /* check for dimension size compatibility */
         flag = 0; for (i=1; i<N_ARRAY_IN; i++) if (dims[j] != PyArray_DIM(input_arr[input_arr_map[i]], j)) flag = 1;
         if (flag==1) {
             for (i=0; i<N_ARRAY_IN; i++) Py_XDECREF(input_arr[input_arr_map[i]]);
             PyErr_SetString(PyExc_RuntimeError, "different dimensions of input arrays.");
             return NULL;
         }
    }
        
    for (i=0; i<N_ARRAY_OUT; i++) {
        output_arr[i]     = (PyArrayObject *) PyArray_FromDims(ndim, dims, NPY_DOUBLE);
        output_arr_ptr[i] = (double*) PyArray_DATA(output_arr[i]);
    }
    
    /* Call the external C function to compute the results. */
    for (j=0; j<N; j++) {
        
        for (i=0; i<N_IN; i++) {
            if (input_type[i] == 0) value = input_double[i];
            else                    value = input_arr_ptr[i][j];
            switch (i) {
                case  0: year      = value;
                case  1: month     = value;
                case  2: day       = value;
                case  3: hour      = value;
                case  4: minute    = value;
                case  5: second    = value;
                case  6: latitude  = value;
                case  7: longitude = value;
                case  8: elevation = value;
                case  9: slope     = value;
                case 10: aspect    = value;
            }
        }
        
        /* some checks */
        if (longitude>180) longitude -= 360;
        
        /* SPA's azm_rotation angle is measured from south and most aspect angle is measured from north */
        aspect -= 180; if (aspect<-360) aspect += 360;
        
        spa.year          = (int) year;
        spa.month         = (int) month;
        spa.day           = (int) day;
        spa.hour          = (int) hour;
        spa.minute        = (int) minute;
        spa.second        = (int) second;
        spa.latitude      = latitude;
        spa.longitude     = longitude;
        spa.timezone      = 0.0;
        spa.delta_t       = 0;
        spa.elevation     = elevation;
        spa.pressure      = 1000*exp(-m_air*g_const*elevation/(R_const*T_const));
        spa.temperature   = 0;
        spa.slope         = slope;
        spa.azm_rotation  = aspect;
        spa.atmos_refract = 0.5667;
        
        rc = spa_calculate(&spa);
        
        if (rc == 0) {
            zenith    = spa.zenith;
            azimuth   = spa.azimuth;
            incidence = spa.incidence;
        }
        else {
            zenith    = -9999;
            azimuth   = -9999;
            incidence = -9999;
        }
        
        output_arr_ptr[0][j] = zenith; output_arr_ptr[1][j] = azimuth;
        if (spa.function == SPA_ZA_INC) output_arr_ptr[2][j] = incidence;
        
    }
    
    /* Clean up. */
    for (i=0; i<N_ARRAY_IN; i++) Py_XDECREF(input_arr[input_arr_map[i]]);
    
    /* Build the output tuple */
    if (spa.function == SPA_ZA)
        return Py_BuildValue("OO", output_arr[0], output_arr[1]);
    else
        return Py_BuildValue("OOO", output_arr[0], output_arr[1], output_arr[2]);
}