GlobalNitrogenDeposition.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. //////////////////////////////////////////////////////////////////////////////////////
  2. // GLOBALNITROGENDEPOSITION.H
  3. // Header file for input from a fast data archive
  4. // Created automatically by FastArchive on Tue Nov 03 13:01:51 2015
  5. //
  6. // The following #includes should appear in your source code file:
  7. //
  8. // #include <stdio.h>
  9. // #include <stdlib.h>
  10. // #include <string.h>
  11. // #include "GlobalNitrogenDeposition.h"
  12. //
  13. // Functionality to retrieve data from the archive is provided by class GlobalNitrogenDepositionArchive.
  14. // The following public functions are provided:
  15. //
  16. // bool open(char* filename)
  17. // Attempts to open the specified file as a fast data archive. The format must be
  18. // exactly compatible with this version of GlobalNitrogenDeposition.h (normally the archive and
  19. // header file should have been produced together by the same program using class
  20. // CFastArchive). Returns false if the file could not be opened or had format
  21. // errors. open() with no argument is equivalent to open("GlobalNitrogenDeposition.bin").
  22. //
  23. // void close()
  24. // Closes the archive (if open).
  25. //
  26. // bool rewind()
  27. // Sets the file pointer to the first record in the archive file. Returns false if
  28. // no archive file is currently open.
  29. //
  30. // bool getnext(GlobalNitrogenDeposition& obj)
  31. // Retrieves the next record in the archive file and advances the file pointer to
  32. // the next record. Data are written to the member variables of obj. Returns false if
  33. // no archive file is currently open or if the file pointer is beyond the last
  34. // record. Use rewind() and getnext() to retrieve data sequentially from the archive.
  35. //
  36. // bool getindex(GlobalNitrogenDeposition& obj)
  37. // Searches the archive for a record matching the values specified for the index
  38. // items (longitude and latitude) in obj. If a matching record is found, the data are
  39. // written to the member variables of obj. Returns true if the archive was open and
  40. // a matching record was found, otherwise false. The search is iterative and fast.
  41. //
  42. // Sample program:
  43. //
  44. // GlobalNitrogenDepositionArchive ark;
  45. // GlobalNitrogenDeposition data;
  46. // bool success,flag;
  47. //
  48. // // Retrieve all records in sequence and print values of longitude and latitude:
  49. //
  50. // success=ark.open("GlobalNitrogenDeposition.bin");
  51. // if (success) {
  52. // flag=ark.rewind();
  53. // while (flag) {
  54. // flag=ark.getnext(data);
  55. // if (flag)
  56. // printf("Loaded record: longitude=%g, latitude=%g\n",data.longitude,data.latitude);
  57. // }
  58. // }
  59. //
  60. // // Look for a record with longitude=-180, latitude=-90:
  61. //
  62. // data.longitude=-180;
  63. // data.latitude=-90;
  64. // success=ark.getindex(data);
  65. // if (success) printf("Found it!\n");
  66. // else printf("Not found\n");
  67. //
  68. // ark.close();
  69. struct GlobalNitrogenDeposition {
  70. // Index part
  71. double longitude;
  72. double latitude;
  73. // Data part
  74. double NHxDry[192];
  75. double NHxWet[192];
  76. double NOyDry[192];
  77. double NOyWet[192];
  78. };
  79. const long GLOBALNITROGENDEPOSITION_NRECORD=59191;
  80. const int GLOBALNITROGENDEPOSITION_DATA_LENGTH=2328;
  81. const int GLOBALNITROGENDEPOSITION_INDEX_LENGTH=7;
  82. const int GLOBALNITROGENDEPOSITION_HEADERSIZE=670;
  83. unsigned char GLOBALNITROGENDEPOSITION_HEADER[GLOBALNITROGENDEPOSITION_HEADERSIZE-4]={
  84. 0x01,0x02,0x9E,0x00,0x00,0x00,0x07,0x00,0x02,0x0A,0x6C,0x6F,0x6E,0x67,0x69,0x74,0x75,0x64,0x65,0x00,
  85. 0x2D,0x31,0x38,0x30,0x00,0xF0,0x19,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,
  86. 0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x31,0x38,0x30,0x00,0x00,0xF0,0x19,0x00,
  87. 0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,
  88. 0x70,0x13,0x5A,0x72,0x30,0x2E,0x32,0x35,0x00,0xF0,0x19,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,
  89. 0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x0B,0x09,0x6C,0x61,
  90. 0x74,0x69,0x74,0x75,0x64,0x65,0x00,0x2D,0x39,0x30,0x00,0xC0,0xF0,0x19,0x00,0x01,0x00,0x00,0x00,0xF4,
  91. 0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x39,
  92. 0x30,0x00,0x00,0xC0,0xF0,0x19,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,
  93. 0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x30,0x2E,0x32,0x35,0x00,0xF0,0x19,0x00,0x01,
  94. 0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,
  95. 0x13,0x5A,0x72,0x0A,0x00,0x00,0x09,0x18,0x00,0x04,0x07,0x4E,0x48,0x78,0x44,0x72,0x79,0x00,0x30,0x2E,
  96. 0x30,0x30,0x30,0x34,0x33,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,
  97. 0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x32,0x39,0x32,0x2E,0x32,0x35,0x37,0x00,0x01,0x00,
  98. 0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,
  99. 0x5A,0x72,0x31,0x65,0x2D,0x30,0x30,0x35,0x00,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,
  100. 0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x19,0x00,0x00,0x00,0xC0,0x07,
  101. 0x4E,0x48,0x78,0x57,0x65,0x74,0x00,0x30,0x00,0x00,0x00,0xC0,0xF0,0x19,0x00,0x01,0x00,0x00,0x00,0xF4,
  102. 0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x39,
  103. 0x34,0x30,0x2E,0x35,0x30,0x35,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,
  104. 0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x31,0x65,0x2D,0x30,0x30,0x35,0x00,0x00,0x01,
  105. 0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,
  106. 0x13,0x5A,0x72,0x1B,0x00,0x00,0x00,0xC0,0x07,0x4E,0x4F,0x79,0x44,0x72,0x79,0x00,0x30,0x00,0x00,0x00,
  107. 0xC0,0xF0,0x19,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,
  108. 0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x34,0x34,0x2E,0x37,0x30,0x39,0x32,0x00,0x01,0x00,0x00,0x00,
  109. 0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,
  110. 0x31,0x65,0x2D,0x30,0x30,0x35,0x00,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,
  111. 0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x17,0x00,0x00,0x00,0xC0,0x07,0x4E,0x4F,
  112. 0x79,0x57,0x65,0x74,0x00,0x30,0x2E,0x30,0x30,0x32,0x39,0x37,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,
  113. 0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x33,0x38,0x2E,
  114. 0x33,0x38,0x32,0x32,0x00,0x01,0x00,0x00,0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,
  115. 0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,0x72,0x31,0x65,0x2D,0x30,0x30,0x35,0x00,0x00,0x01,0x00,0x00,
  116. 0x00,0xF4,0xFA,0x19,0x00,0x5A,0xB6,0x60,0x72,0x8A,0xC6,0x56,0xDB,0xFE,0xFF,0xFF,0xFF,0x70,0x13,0x5A,
  117. 0x72,0x16,0x00,0x00,0x00,0xC0};
  118. class GlobalNitrogenDepositionArchive {
  119. private:
  120. FILE* pfile;
  121. long recno;
  122. long datano;
  123. unsigned char pindex[GLOBALNITROGENDEPOSITION_INDEX_LENGTH];
  124. unsigned char pdata[GLOBALNITROGENDEPOSITION_DATA_LENGTH];
  125. bool iseof;
  126. long readbin(int nbyte) {
  127. unsigned char buf[4];
  128. long mult[4]={0x1000000,0x10000,0x100,1},val;
  129. int i;
  130. fread(buf,nbyte,1,pfile);
  131. val=0;
  132. for (i=0;i<nbyte;i++) {
  133. val+=buf[i]*mult[4-nbyte+i];
  134. }
  135. return val;
  136. }
  137. void getindex(long n) {
  138. fseek(pfile,GLOBALNITROGENDEPOSITION_INDEX_LENGTH*(n-recno),SEEK_CUR);
  139. fread(pindex,GLOBALNITROGENDEPOSITION_INDEX_LENGTH,1,pfile);
  140. datano=pindex[GLOBALNITROGENDEPOSITION_INDEX_LENGTH-4]*0x1000000+pindex[GLOBALNITROGENDEPOSITION_INDEX_LENGTH-3]*0x10000+
  141. pindex[GLOBALNITROGENDEPOSITION_INDEX_LENGTH-2]*0x100+pindex[GLOBALNITROGENDEPOSITION_INDEX_LENGTH-1];
  142. recno=n+1;
  143. iseof=(recno==GLOBALNITROGENDEPOSITION_NRECORD);
  144. }
  145. void getdata() {
  146. fseek(pfile,GLOBALNITROGENDEPOSITION_INDEX_LENGTH*-recno+(datano-GLOBALNITROGENDEPOSITION_NRECORD)*GLOBALNITROGENDEPOSITION_DATA_LENGTH,SEEK_CUR);
  147. fread(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,1,pfile);
  148. fseek(pfile,GLOBALNITROGENDEPOSITION_DATA_LENGTH*(GLOBALNITROGENDEPOSITION_NRECORD-datano-1)+GLOBALNITROGENDEPOSITION_INDEX_LENGTH*recno,SEEK_CUR);
  149. }
  150. double popreal(unsigned char* bits,int nbyte,int nbit,double scalar,double offset) {
  151. unsigned char buf;
  152. int nb=nbit/8,i;
  153. double rval=0.0;
  154. long mult[4]={1,0x100,0x10000,0x1000000};
  155. for (i=0;i<4;i++) {
  156. if (i<nb) rval+=bits[nbyte-i-1]*mult[i];
  157. else if (i==nb) {
  158. buf=bits[nbyte-i-1]<<(8-nbit%8);
  159. buf>>=8-nbit%8;
  160. rval+=buf*mult[i];
  161. }
  162. }
  163. for (i=nbyte-1;i>=0;i--) {
  164. if (i>=nb)
  165. bits[i]=bits[i-nb];
  166. else
  167. bits[i]=0;
  168. }
  169. nb=nbit%8;
  170. for (i=nbyte-1;i>=0;i--) {
  171. bits[i]>>=nb;
  172. if (i>0) {
  173. buf=bits[i-1];
  174. buf<<=8-nb;
  175. bits[i]|=buf;
  176. }
  177. }
  178. rval=rval*scalar+offset;
  179. return rval;
  180. }
  181. void bitify(unsigned char buf[4],double fval,double offset,double scalar) {
  182. long ival = (long)((fval-offset)/scalar + 0.5);
  183. buf[0]=(unsigned char)(ival/0x1000000);
  184. ival-=buf[0]*0x1000000;
  185. buf[1]=(unsigned char)(ival/0x10000);
  186. ival-=buf[1]*0x10000;
  187. buf[2]=(unsigned char)(ival/0x100);
  188. ival-=buf[2]*0x100;
  189. buf[3]=(unsigned char)(ival);
  190. }
  191. void merge(unsigned char ptarget[3],unsigned char buf[4],int bits) {
  192. int nb=bits/8;
  193. int i;
  194. unsigned char nib;
  195. for (i=0;i<3;i++) {
  196. if (i<3-nb)
  197. ptarget[i]=ptarget[i+nb];
  198. else
  199. ptarget[i]=0;
  200. }
  201. nb=bits%8;
  202. for (i=0;i<3;i++) {
  203. ptarget[i]<<=nb;
  204. if (i<3-1) {
  205. nib=ptarget[i+1]>>(8-nb);
  206. ptarget[i]|=nib;
  207. }
  208. }
  209. nb=bits/8;
  210. if (bits%8) nb++;
  211. for (i=1;i<=nb;i++)
  212. ptarget[3-i]|=buf[4-i];
  213. }
  214. int compare_index(unsigned char* a,unsigned char* b) {
  215. int i;
  216. for (i=0;i<3;i++) {
  217. if (a[i]<b[i]) return -1;
  218. else if (a[i]>b[i]) return +1;
  219. }
  220. return 0;
  221. }
  222. bool initialise(const char* filename) {
  223. int i;
  224. unsigned char* pheader;
  225. if (pfile) fclose(pfile);
  226. pfile=fopen(filename,"rb");
  227. if (!pfile) {
  228. printf("Could not open %s for input\n",filename);
  229. return false;
  230. }
  231. pheader=new unsigned char[GLOBALNITROGENDEPOSITION_HEADERSIZE-4];
  232. if (!pheader) {
  233. printf("Out of memory\n");
  234. fclose(pfile);
  235. pfile=NULL;
  236. return false;
  237. }
  238. ::rewind(pfile);
  239. fread(pheader,GLOBALNITROGENDEPOSITION_HEADERSIZE-4,1,pfile);
  240. for (i=0;i<GLOBALNITROGENDEPOSITION_HEADERSIZE-4;i++) {
  241. if (pheader[i]!=GLOBALNITROGENDEPOSITION_HEADER[i]) {
  242. printf("Format of %s incompatible with this version of GlobalNitrogenDeposition.h\n",filename);
  243. fclose(pfile);
  244. pfile=NULL;
  245. delete pheader;
  246. return false;
  247. }
  248. }
  249. delete[] pheader;
  250. ::rewind(pfile);
  251. fseek(pfile,GLOBALNITROGENDEPOSITION_HEADERSIZE+GLOBALNITROGENDEPOSITION_DATA_LENGTH*GLOBALNITROGENDEPOSITION_NRECORD,SEEK_CUR);
  252. recno=0;
  253. iseof=false;
  254. return true;
  255. }
  256. public:
  257. GlobalNitrogenDepositionArchive() {
  258. pfile=NULL;
  259. }
  260. ~GlobalNitrogenDepositionArchive() {
  261. if (pfile) fclose(pfile);
  262. }
  263. bool open(const char* filename) {
  264. return initialise(filename);
  265. }
  266. bool open() {
  267. return open("GlobalNitrogenDeposition.bin");
  268. }
  269. void close() {
  270. if (pfile) {
  271. fclose(pfile);
  272. pfile=NULL;
  273. }
  274. }
  275. bool rewind() {
  276. if (!pfile) return false;
  277. ::rewind(pfile);
  278. fseek(pfile,GLOBALNITROGENDEPOSITION_HEADERSIZE+GLOBALNITROGENDEPOSITION_DATA_LENGTH*GLOBALNITROGENDEPOSITION_NRECORD,SEEK_CUR);
  279. recno=0;
  280. iseof=false;
  281. return true;
  282. }
  283. bool getnext(GlobalNitrogenDeposition& obj) {
  284. if (!pfile || iseof) return false;
  285. int i;
  286. getindex(recno);
  287. getdata();
  288. obj.latitude=popreal(pindex,3,10,0.25,-90);
  289. obj.longitude=popreal(pindex,3,11,0.25,-180);
  290. for (i=191;i>=0;i--) obj.NOyWet[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,22,1e-005,0.00297);
  291. for (i=191;i>=0;i--) obj.NOyDry[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,23,1e-005,0);
  292. for (i=191;i>=0;i--) obj.NHxWet[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,27,1e-005,0);
  293. for (i=191;i>=0;i--) obj.NHxDry[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,25,1e-005,0.00043);
  294. return true;
  295. }
  296. bool getindex(GlobalNitrogenDeposition& obj) {
  297. if (!GLOBALNITROGENDEPOSITION_NRECORD || !pfile) return false;
  298. // else
  299. unsigned char ptarget[3]={0,0,0};
  300. unsigned char buf[4];
  301. bitify(buf,obj.longitude,-180,0.25);
  302. merge(ptarget,buf,11);
  303. bitify(buf,obj.latitude,-90,0.25);
  304. merge(ptarget,buf,10);
  305. long begin = 0;
  306. long end = GLOBALNITROGENDEPOSITION_NRECORD;
  307. while (begin < end) {
  308. long middle = (begin+end)/2;
  309. getindex(middle);
  310. getdata();
  311. int c = compare_index(pindex, ptarget);
  312. if (c < 0) {
  313. begin = middle + 1;
  314. }
  315. else if (c > 0) {
  316. end = middle;
  317. }
  318. else {
  319. for (int i=191;i>=0;i--) obj.NOyWet[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,22,1e-005,0.00297);
  320. for (int i=191;i>=0;i--) obj.NOyDry[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,23,1e-005,0);
  321. for (int i=191;i>=0;i--) obj.NHxWet[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,27,1e-005,0);
  322. for (int i=191;i>=0;i--) obj.NHxDry[i]=popreal(pdata,GLOBALNITROGENDEPOSITION_DATA_LENGTH,25,1e-005,0.00043);
  323. return true;
  324. }
  325. }
  326. return false;
  327. }
  328. };