/[ascend]/trunk/models/johnpye/nrel/asc_sunpos.c
ViewVC logotype

Annotation of /trunk/models/johnpye/nrel/asc_sunpos.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2591 - (hide annotations) (download) (as text)
Wed Apr 11 21:23:18 2012 UTC (10 years, 4 months ago) by jpye
File MIME type: text/x-csrc
File size: 7811 byte(s)
Add calculation of Julian Day within ASCEND model.
1 jpye 2584 /* ASCEND modelling environment
2     Copyright (C) 2008 Carnegie Mellon University
3    
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2, or (at your option)
7     any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13    
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place - Suite 330,
17     Boston, MA 02111-1307, USA.
18     *//** @file
19     Wrapper for sunpos_nrel.c to allow access to the calculation from ASCEND.
20     */
21    
22     /* include the external function API from libascend... */
23     #include <ascend/compiler/extfunc.h>
24    
25     /* include error reporting API as well, so we can send messages to user */
26     #include <ascend/utilities/error.h>
27    
28     /* for accessing the DATA instance */
29     #include <ascend/compiler/child.h>
30     #include <ascend/general/list.h>
31     #include <ascend/compiler/module.h>
32     #include <ascend/compiler/childinfo.h>
33     #include <ascend/compiler/parentchild.h>
34     #include <ascend/compiler/slist.h>
35     #include <ascend/compiler/type_desc.h>
36     #include <ascend/compiler/packages.h>
37     #include <ascend/compiler/symtab.h>
38     #include <ascend/compiler/instquery.h>
39     #include <ascend/compiler/instmacro.h>
40     #include <ascend/compiler/instance_types.h>
41    
42     /* the code that we're wrapping... */
43     #include "spa.h"
44    
45     #ifndef PI
46     # define PI 3.14159265358979
47     #endif
48    
49 jpye 2591 static ExtBBoxInitFunc sunpos_nrel_prepare;
50     static ExtBBoxFunc sunpos_nrel_calc;
51     static ExtBBoxInitFunc julian_day_nrel_prepare;
52     static ExtBBoxFunc julian_day_nrel_calc;
53 jpye 2584
54     static const char *sunpos_nrel_help = "Calculate sun position (local zenith, azimuth "
55     "angles) given time, pressure and temperature, using NREL algorithm. DATA "
56     "member for this external relation is required to provide constants for "
57     "latitude and longitude of the selected location.\n\n"
58     "Time is required to be in the form of Julian Date. ASCEND will convert the "
59     "Julian Date into seconds automatically. The JD should be in the range"
60     "-2000 BC to 6000 AD (12:00pm 1 Jan 2000 GMT is 2451545.0 JD)";
61    
62 jpye 2591 static const char *julian_day_nrel_help = "Calculate the Julian Day from "
63     "year, month, day, hour, minute, second and timezone inputs. "
64     "Intended for once-off use in ASCEND models to calculate the time offset "
65     "eg for the start of a weather file. Acceptable dates are in the range "
66     "of -2000 BC to AD 6000. All of the inputs should be as 'factor' type "
67     "variables (to avoid needless time unit conversions), except for the "
68     "timezone, which should be in time units eg '8{h}'.";
69    
70 jpye 2584 /*------------------------------------------------------------------------------
71     REGISTRATION FUNCTION
72     */
73    
74     /**
75 jpye 2591 This is the function called from 'IMPORT "johnpye/nrel/sunpos_nrels";'
76 jpye 2584
77     It sets up the functions contained in this external library
78     */
79     extern
80     ASC_EXPORT int sunpos_nrel_register(){
81     int result = 0;
82    
83 jpye 2591 ERROR_REPORTER_HERE(ASC_USER_WARNING,"SUNPOS_NREL is still EXPERIMENTAL. Use with caution.\n");
84 jpye 2584
85     #define CALCFN(NAME,INPUTS,OUTPUTS) \
86     result += CreateUserFunctionBlackBox(#NAME \
87 jpye 2591 , NAME##_prepare \
88 jpye 2584 , NAME##_calc /* value */ \
89     , (ExtBBoxFunc*)NULL /* derivatives not provided yet*/ \
90     , (ExtBBoxFunc*)NULL /* hessian not provided yet */ \
91     , (ExtBBoxFinalFunc*)NULL /* finalisation not implemented */ \
92     , INPUTS,OUTPUTS /* inputs, outputs */ \
93     , NAME##_help /* help text */ \
94     , 0.0 \
95     ) /* returns 0 on success */
96    
97     CALCFN(sunpos_nrel,3,2);
98 jpye 2591 CALCFN(julian_day_nrel,7,1);
99 jpye 2584
100     #undef CALCFN
101    
102     if(result){
103     ERROR_REPORTER_HERE(ASC_PROG_NOTE,"CreateUserFunction result = %d\n",result);
104     }
105     return result;
106     }
107    
108     #define GET_CHILD_VAL(NAME) \
109     inst = ChildByChar(data,AddSymbol(#NAME)); \
110     if(!inst){ \
111     ERROR_REPORTER_HERE(ASC_USER_ERROR \
112     ,"Couldn't locate '" #NAME "' in DATA, please check usage of SUNPOS."\
113     );\
114     return 1;\
115     }\
116     if(InstanceKind(inst)!=REAL_CONSTANT_INST){\
117     ERROR_REPORTER_HERE(ASC_USER_ERROR,"DATA member '" #NAME "' must be a real_constant");\
118     return 1;\
119     }\
120     NAME = RC_INST(inst)->value;
121    
122 jpye 2591 /**
123     This function is called when the black-box relation is being instantiated.
124    
125     This just gets the data member and checks that it's valid, and stores
126     it in the blackbox data field.
127     */
128     static int sunpos_nrel_prepare(struct BBoxInterp *bbox,
129     struct Instance *data,
130     struct gl_list_t *arglist
131     ){
132     struct Instance *inst;
133     double latitude, longitude, elevation;
134    
135 jpye 2584 /* get the latitude */
136     GET_CHILD_VAL(latitude);
137     CONSOLE_DEBUG("Latitude: %0.3f",latitude);
138     if(latitude > PI/2 || latitude < -PI/2){
139     ERROR_REPORTER_HERE(ASC_USER_ERROR,"'latitude' is out of allowable range -PI/2 to PI/2.");
140     return 1;
141     }
142    
143     /* get the longitude */
144     GET_CHILD_VAL(longitude);
145     CONSOLE_DEBUG("Longitude: %0.3f",longitude);
146     if(longitude > PI || longitude < -PI){
147     ERROR_REPORTER_HERE(ASC_USER_ERROR,"'latitude' is out of allowable range -PI to PI.");
148     return 1;
149     }
150    
151     /* get the elevation */
152     GET_CHILD_VAL(elevation);
153     CONSOLE_DEBUG("Elevation: %0.3f m",elevation);
154     if(elevation < -6500000){
155     ERROR_REPORTER_HERE(ASC_USER_ERROR,"'elevation' is out of allowable range (must be > -6,500 km)");
156     return 1;
157     }
158    
159     spa_data *S = ASC_NEW(spa_data);
160     S->latitude = latitude * 180/PI;
161     S->longitude = longitude * 180/PI;
162     S->elevation = elevation;
163     S->function = SPA_ZA_JD;
164    
165     ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Prepared position for sun position.\n");
166     bbox->user_data = (void *)S;
167     return 0;
168     }
169    
170     #define CALCPREPARE(NIN,NOUT) \
171     /* a few checks about the input requirements */ \
172     if(ninputs != NIN)return -1; \
173     if(noutputs != NOUT)return -2; \
174     if(inputs==NULL)return -3; \
175     if(outputs==NULL)return -4; \
176     if(bbox==NULL)return -5; \
177     \
178     /* the 'user_data' in the black box object will contain the */\
179     /* coefficients required for this fluid; cast it to the required form: */\
180     const spa_data *sunpos1 = (const spa_data *)bbox->user_data
181    
182    
183     /**
184     Evaluation function for 'sunpos'
185     @return 0 on success
186     */
187 jpye 2591 static int sunpos_nrel_calc(struct BBoxInterp *bbox,
188 jpye 2584 int ninputs, int noutputs,
189     double *inputs, double *outputs,
190     double *jacobian
191     ){
192     CALCPREPARE(3,2);
193    
194     double t, p, T;
195    
196     t = inputs[0]/ 86400.; /* convert from JD seconds to JD days */
197     p = inputs[1] / 100. /* convert Pa to mbar */;
198     T = inputs[2] - 273.15 /* convert ��C to K */;
199    
200     spa_data S = *sunpos1;
201     S.pressure = p;
202     S.temperature = T;
203     S.jd = t;
204    
205     int res = spa_calculate(&S);
206     CONSOLE_DEBUG("Sun position: t = %f JD, p %f mbar, T = %f C: res = %d, az = %f, zen = %f",t, p, T, res, S.azimuth, S.zenith);
207    
208     /* returned values are in degrees, need to convert back to base SI: radians */
209     outputs[0] = S.zenith * PI/180.;
210     outputs[1] = S.azimuth * PI/180.;
211    
212     /* 0 on success, non-zero is error code from spa_calculate (would prob be input parameters out-of-range) */
213     return res;
214     }
215    
216 jpye 2591 /*---------- SUNPOS_JULIAN_DAY ------------*/
217 jpye 2584
218 jpye 2591 static int julian_day_nrel_prepare(struct BBoxInterp *bbox,
219     struct Instance *data,
220     struct gl_list_t *arglist
221     ){
222     bbox->user_data = NULL;
223     return 0;
224     }
225 jpye 2584
226 jpye 2591 static int julian_day_nrel_calc(struct BBoxInterp *bbox,
227     int ninputs, int noutputs,
228     double *inputs, double *outputs,
229     double *jacobian
230     ){
231     CALCPREPARE(7,1);
232     (void)sunpos1;
233    
234     int y,mon,d,h,m,s;
235     double tz;
236    
237     y = inputs[0]; /* convert from seconds to years */
238     mon = inputs[1]; /* convert from seconds to months */
239     d = inputs[2]; /* convert from seconds to days */
240     h = inputs[3]; /* seconds to hours */
241     m = inputs[4]; /* seconds to minutes */
242     s = inputs[5];
243     tz = inputs[6] / 3600.; /* seconds to hours */
244    
245     double t = julian_day(y,mon,d, h,m,s, tz) * 3600 * 24;
246    
247     outputs[0] = t;
248     return 0;
249     }
250    
251    

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22