cloudy  trunk
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
optimize_phymir.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*optimize_phymir Peter van Hoof's optimization routine */
4 
5 #if defined(unix) || defined(__unix) || defined(__unix__)
6 /* __unix may not be defined here (this is done in cddefines.h), so we have to cover all bets */
7 /* this statement needs to be in front of cddefines.h, because cddefines.h includes <stdio.h>,
8  * which in turn includes <sys/types.h> under HP/UX 10.20. If _INCLUDE_POSIX_SOURCE is not
9  * defined before we enter cddefines.h, pid_t will not be defined and the compilation will fail.
10  * Error reported by Richard Hook. */
11 #define _INCLUDE_POSIX_SOURCE
12 #endif
13 #include "cddefines.h"
14 #include "version.h"
15 #include "optimize.h"
16 #ifdef __unix
17 #include <stddef.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #endif
22 
23 #define F0 1.4142136f
24 #define F1 0.7071068f
25 #define F2 0.1f
26 
27 
28 /* The optimization algorithm Phymir and its subsidiary routines have been
29  * written by Peter van Hoof. An article describing the algorithm is
30  * currently in preparation and is intended to be submitted to New Astronomy. */
31 
32 /* the a2's in the prototypes are necessary to prevent a bug in lclint 2.5m */
33 STATIC void phygrm(realnum a2[][LIMPAR],long);
34 STATIC void wr_continue(realnum,long,realnum a2[][LIMPAR],const realnum[],const realnum[],
35  const realnum[],const realnum[],realnum,realnum,realnum,long,long,const realnum[],
36  const realnum[],const char[],const char[],const char[],const char*);
38  realnum*,realnum*,realnum*,long*,long*,realnum[],realnum[],char[],char[],char[],const char*);
39 #ifdef __unix
40 STATIC void cpfile(const char*);
41 STATIC void wr_block(void*,size_t,const char*);
42 STATIC void rd_block(void*,size_t,const char*);
43 #endif
44 
45 
47  realnum del[],
48  long int nvarPhymir,
49  realnum *ymin,
50  realnum toler)
51 {
52 #define DELTA(i,j) (((i) == (j)) ? 1.f : 0.f)
53 
54  char chDum1[STDLEN],
55  chDum2[STDLEN],
56  chDum3[STDLEN];
57  bool lgFinish,
58  lgNegd2,
59  lgNewCnt,
60  lgRead;
61  long int i,
62  imax,
63  j,
64  jj,
65  jmin=0,
66  limcp,
67  nvarcp;
69  amax,
70  c1[LIMPAR],
71  c2[LIMPAR],
72  d1,
73  d2,
74  diff,
75  dmax=0.f,
76  dold=0.f,
77  r1,
78  r2,
79  sgn,
80  temp,
81  vers,
82  vpusedPhymir,
83  xcold[LIMPAR],
84  xhlp[LIMPAR],
85  xnrm,
86  xp[LIMPAR][2*LIMPAR + 1],
87  yp[2*LIMPAR + 1];
88 # ifdef __unix
89  long int currentCPU;
90  int stat;
91  char fnam1[20],
92  fnam2[20];
93  pid_t pid;
94 # endif
95 
96  DEBUG_ENTRY( "optimize_phymir()" );
97 
98  if( nvarPhymir > LIMPAR )
99  {
100  fprintf( ioQQQ, "optimize_phymir: too many parameters are varied, increase LIMPAR\n" );
101  cdEXIT(EXIT_FAILURE);
102  }
103 
104  /* >>chng 06 jan 02, fix uninitialized var problem detected by valgrind/purify, PvH */
105  memset( chDum1, '\0', STDLEN );
106  memset( chDum2, '\0', STDLEN );
107  memset( chDum3, '\0', STDLEN );
108 
109  for( i=0; i < LIMPAR; ++i )
110  {
111  c1[i] = -FLT_MAX;
112  c2[i] = -FLT_MAX;
113  xcold[i] = -FLT_MAX;
114  for( j=0; j < LIMPAR; ++j )
115  {
116  a2[i][j] = -FLT_MAX;
117  }
118  }
119 
120  optimize.nOptimiz = 0;
121 # ifdef __unix
122  currentCPU = 0;
123 # endif
124  lgFinish = false;
125  lgRead = optimize.lgOptCont;
126  if( optimize.lgOptCont )
127  goto L_20;
128 
129  /* initialize hypercube dimensions and center */
130  dmax = 0.f;
131  for( i=0; i < nvarPhymir; i++ )
132  {
133  temp = (realnum)fabs(del[i]);
134  dmax = MAX2(dmax,temp);
135  }
136 
137  dold = dmax;
138  for( i=0; i < nvarPhymir; i++ )
139  {
140  xcold[i] = xc[i] + 10.f*toler;
141  c1[i] = (realnum)fabs(del[i])/dmax;
142  c2[i] = c1[i];
143  xp[i][0] = xc[i];
144  optimize.vparm[0][i] = xc[i];
145  /* this is done by child process and is lost, so copy code to parent process */
146  if( optimize.lgParallel )
147  {
148  vpusedPhymir = MIN2(optimize.vparm[0][i],optimize.varang[i][1]);
149  vpusedPhymir = MAX2(vpusedPhymir,optimize.varang[i][0]);
150  optimize.varmax[i] = MAX2(optimize.varmax[i],vpusedPhymir);
151  optimize.varmin[i] = MIN2(optimize.varmin[i],vpusedPhymir);
152  }
153  }
154 # ifdef __unix
155  if( optimize.lgParallel )
156  {
157  /* flush all open files */
158  fflush(NULL);
159  pid = fork();
160  if( pid == 0 )
161  {
162  /* this is child process so execute */
163  sprintf(fnam1,"chi2_%ld",0L);
164  sprintf(fnam2,"output_%ld",0L);
165  /* each child should have its own output file */
166  ioQQQ = open_data( fnam2, "w", AS_LOCAL_ONLY );
167  /* fail-safe in case optimize_func crashes */
168  yp[0] = FLT_MAX;
169  wr_block(&yp[0],(size_t)sizeof(realnum),fnam1);
170  yp[0] = (realnum)optimize_func(xc);
171  wr_block(&yp[0],(size_t)sizeof(realnum),fnam1);
172  fclose( ioQQQ );
173  ioQQQ = NULL;
174  cdEXIT(EXIT_SUCCESS);
175  }
176  else
177  {
178  /* parent process waits, this way all initializations remain intact */
179  pid = wait(&stat);
180  sprintf(fnam1,"chi2_%ld",0L);
181  sprintf(fnam2,"output_%ld",0L);
182  rd_block(&yp[0],(size_t)sizeof(realnum),fnam1);
183  remove(fnam1);
184  cpfile(fnam2);
185  remove(fnam2);
186  }
187  /* this was incremented by child process and is lost, so copy code here */
188  optimize.nOptimiz++;
189  }
190  else
191  {
192  yp[0] = (realnum)optimize_func(xc);
193  }
194 # else
195  /* on non-UNIX machines only sequential mode is supported */
196  yp[0] = (realnum)optimize_func(xc);
197 # endif
198  *ymin = yp[0];
199  jmin = 0;
200  /* restart entry; initialize transformation matrix to unity */
201 L_10:
202  for( i=0; i < nvarPhymir; i++ )
203  {
204  for( j=0; j < nvarPhymir; j++ )
205  {
206  a2[j][i] = DELTA(i,j);
207  }
208  }
209  /* loop entry */
210 L_20:
211  if( lgRead )
212  {
213  rd_continue(&vers,&limcp,a2,c1,c2,xc,xcold,&dmax,&dold,ymin,&nvarcp,&optimize.nOptimiz,
214  optimize.varmax,optimize.varmin,chDum1,chDum2,chDum3,CNTFILE);
215  if( nvarcp != nvarPhymir )
216  {
217  printf( "optimize continue - wrong number of free parameters, sorry\n" );
218  cdEXIT(EXIT_FAILURE);
219  }
220  for( i=0; i < nvarPhymir; i++ )
221  {
222  xp[i][0] = xc[i];
223  }
224  yp[0] = *ymin;
225  jmin = 0;
226  lgRead = false;
227  }
228  else
229  {
230  // use STDLEN-1 so that last 0 byte is not overwritten...
231  strncpy(chDum1,t_version::Inst().chDate,STDLEN-1);
232  strncpy(chDum2,t_version::Inst().chVersion,STDLEN-1);
233  strncpy(chDum3,cpu.host_name(),STDLEN-1);
234  wr_continue(VRSNEW,LIMPAR,a2,c1,c2,xc,xcold,dmax,dold,*ymin,nvarPhymir,optimize.nOptimiz,
235  optimize.varmax,optimize.varmin,chDum1,chDum2,chDum3,CNTFILE);
236  }
237 
238  if( lgFinish )
239  {
240  return;
241  }
242  /* maximum no. of iterations exceeded? */
244  {
245  fprintf( ioQQQ, " Optimizer exceeding maximum iterations.\n This can be reset with the OPTIMIZE ITERATIONS command.\n" );
246  return;
247  }
248 
249  for( j=0; j < nvarPhymir; j++ )
250  {
251  sgn = 1.f;
252  for( jj=2*j+1; jj <= 2*j+2; jj++ )
253  {
254  sgn = -sgn;
255  for( i=0; i < nvarPhymir; i++ )
256  {
257  xp[i][jj] = xc[i] + sgn*dmax*c2[j]*a2[j][i];
258  xhlp[i] = xp[i][jj];
259  optimize.vparm[0][i] = xhlp[i];
260  /* this is done by child process, so copy code to parent process */
261  if( optimize.lgParallel )
262  {
263  vpusedPhymir = MIN2(optimize.vparm[0][i],optimize.varang[i][1]);
264  vpusedPhymir = MAX2(vpusedPhymir,optimize.varang[i][0]);
265  optimize.varmax[i] = MAX2(optimize.varmax[i],vpusedPhymir);
266  optimize.varmin[i] = MIN2(optimize.varmin[i],vpusedPhymir);
267  }
268  }
269 # ifdef __unix
270  if( optimize.lgParallel )
271  {
272  currentCPU++;
273  if( currentCPU > optimize.useCPU )
274  {
275  /* too many processes, wait for one to finish */
276  pid = wait(&stat);
277  currentCPU--;
278  }
279  /* flush all open files */
280  fflush(NULL);
281  pid = fork();
282  if( pid == 0 )
283  {
284  /* this is child process so execute */
285  sprintf(fnam1,"chi2_%ld",jj);
286  sprintf(fnam2,"output_%ld",jj);
287  /* each child should have its own output file */
288  ioQQQ = open_data( fnam2, "w", AS_LOCAL_ONLY );
289  /* fail-safe in case optimize_func crashes */
290  yp[jj] = FLT_MAX;
291  wr_block(&yp[jj],(size_t)sizeof(realnum),fnam1);
292  yp[jj] = (realnum)optimize_func(xhlp);
293  wr_block(&yp[jj],(size_t)sizeof(realnum),fnam1);
294  fclose( ioQQQ );
295  ioQQQ = NULL;
296  cdEXIT(EXIT_SUCCESS);
297  }
298  /* this was incremented by child process, so copy code here */
299  optimize.nOptimiz++;
300  }
301  else
302  {
303  yp[jj] = (realnum)optimize_func(xhlp);
304  }
305 # else
306  /* on non-UNIX machines only sequential mode is supported */
307  yp[jj] = (realnum)optimize_func(xhlp);
308 # endif
309  }
310  }
311 # ifdef __unix
312  /* wait for child processes to terminate */
313  if( optimize.lgParallel )
314  {
315  while( currentCPU > 0 )
316  {
317  pid = wait(&stat);
318  currentCPU--;
319  }
320  }
321 # endif
322  /* find best model */
323  for( jj=1; jj <= 2*nvarPhymir; jj++ )
324  {
325 # ifdef __unix
326  if( optimize.lgParallel )
327  {
328  sprintf(fnam1,"chi2_%ld",jj);
329  sprintf(fnam2,"output_%ld",jj);
330  rd_block(&yp[jj],(size_t)sizeof(realnum),fnam1);
331  remove(fnam1);
332  cpfile(fnam2);
333  remove(fnam2);
334  }
335 # endif
336  if( yp[jj] < *ymin )
337  {
338  *ymin = yp[jj];
339  jmin = jj;
340  }
341  }
342 
343  lgNewCnt = jmin > 0;
344  /* determine minimum and relative uncertainties */
345  lgNegd2 = false;
346  xnrm = 0.f;
347  for( i=0; i < nvarPhymir; i++ )
348  {
349  d1 = yp[2*i+2] - yp[2*i+1];
350  d2 = 0.5f*yp[2*i+2] - yp[0] + 0.5f*yp[2*i+1];
351  if( d2 <= 0.f )
352  lgNegd2 = true;
353  xhlp[i] = -dmax*c2[i]*(MAX2(MIN2((0.25f*d1)/MAX2(d2,1.e-10f),F0),-F0) - DELTA(2*i+1,jmin) + DELTA(2*i+2,jmin));
354  xnrm += POW2(xhlp[i]);
355  }
356  xnrm = (realnum)sqrt(xnrm);
357  /* set up new transformation matrix */
358  imax = 0;
359  amax = 0.f;
360  for( j=0; j < nvarPhymir; j++ )
361  {
362  for( i=0; i < nvarPhymir; i++ )
363  {
364  if( xnrm > 0.f )
365  {
366  if( j == 0 )
367  {
368  a2[0][i] *= xhlp[0];
369  }
370  else
371  {
372  a2[0][i] += xhlp[j]*a2[j][i];
373  a2[j][i] = DELTA(i,j);
374  if( j == nvarPhymir-1 && (realnum)fabs(a2[0][i]) > amax )
375  {
376  imax = i;
377  amax = (realnum)fabs(a2[0][i]);
378  }
379  }
380  }
381  else
382  {
383  a2[j][i] = DELTA(i,j);
384  }
385  }
386  }
387  /* this is to assure maximum linear independence of the base vectors */
388  if( imax > 0 )
389  {
390  a2[imax][0] = 1.f;
391  a2[imax][imax] = 0.f;
392  }
393  /* apply Gram-Schmidt procedure to get orthogonal base */
394  phygrm(a2,nvarPhymir);
395 
396  /* set up hypercube dimensions in new base and choose new center */
397  for( i=0; i < nvarPhymir; i++ )
398  {
399  c2[i] = 0.f;
400  for( j=0; j < nvarPhymir; j++ )
401  {
402  c2[i] += POW2(a2[i][j]/c1[j]);
403  }
404  c2[i] = 1.f/sqrt(c2[i]);
405  xc[i] = xp[i][jmin];
406  xp[i][0] = xc[i];
407  }
408  yp[0] = yp[jmin];
409  jmin = 0;
410  /* choose size of next hypercube */
411  if( lgNegd2 )
412  {
413  /* this means that the hypercube either is bigger than the scale
414  * on which the function varies, or is so small that we see noise.
415  * in both cases make the hypercube smaller. */
416  r1 = F1;
417  r2 = F1;
418  }
419  else
420  {
421  r1 = F2;
422  if( lgNewCnt )
423  {
424  /* when we make progress, dmax may become bigger */
425  r2 = sqrt(1.f/F1);
426  }
427  else
428  {
429  /* when there is no progress force dmax smaller, otherwise there
430  * may never be an end */
431  r2 = sqrt(F1);
432  }
433  }
434  dmax = MIN2(MAX2(xnrm/c2[0],dmax*r1),dmax*r2);
435  /* fail-safe against excessive behaviour */
436  dmax = MIN2(dmax,dold);
437 
438  if( dmax > toler )
439  goto L_20;
440  /* do we restart? */
441  diff = 0.f;
442  for( i=0; i < nvarPhymir; i++ )
443  {
444  diff += POW2(xc[i] - xcold[i]);
445  xcold[i] = xc[i];
446  c2[i] = c1[i];
447  }
448  diff = sqrt(diff);
449  dmax = dold;
450  lgFinish = diff <= toler;
451  goto L_10;
452 # undef DELTA
453 }
454 
456  long int n)
457 {
458  long int i,
459  j,
460  k;
461  realnum ip;
462 
463  DEBUG_ENTRY( "phygrm()" );
464 
465  /* apply modified Gram-Schmidt procedure to a */
466  for( i=0; i < n; i++ )
467  {
468  ip = 0.f;
469  for( k=0; k < n; k++ )
470  ip += POW2(a[i][k]);
471  ip = sqrt(ip);
472  for( k=0; k < n; k++ )
473  a[i][k] /= ip;
474  for( j=i+1; j < n; j++ )
475  {
476  ip = 0.f;
477  for( k=0; k < n; k++ )
478  ip += a[i][k]*a[j][k];
479  for( k=0; k < n; k++ )
480  a[j][k] -= ip*a[i][k];
481  }
482  }
483  return;
484 }
485 
487  long dim,
488  realnum a2[][LIMPAR], /* a2[LIMPAR][LIMPAR] */
489  const realnum c1[], /* c1[LIMPAR] */
490  const realnum c2[], /* c2[LIMPAR] */
491  const realnum xc[], /* xc[LIMPAR] */
492  const realnum xcold[], /* xcold[LIMPAR] */
493  realnum dmax,
494  realnum dold,
495  realnum ymin,
496  long nvar,
497  long noptim,
498  const realnum varmax[], /* varmax[LIMPAR] */
499  const realnum varmin[], /* varmin[LIMPAR] */
500  const char chDum1[], /* chDum1[STDLEN] */
501  const char chDum2[], /* chDum2[STDLEN] */
502  const char chDum3[], /* chDum3[STDLEN] */
503  const char *fnam)
504 {
505  bool lgErr;
506  int res;
507  size_t num;
508  FILE *fdes;
509 
510  DEBUG_ENTRY( "wr_continue()" );
511 
512  try
513  {
514  fdes = open_data( fnam, "wb", AS_LOCAL_ONLY );
515  }
516  catch( cloudy_exit )
517  {
518  return;
519  }
520  lgErr = false;
521  num = 1;
522  lgErr = lgErr || ( fwrite(&vers,sizeof(realnum),num,fdes) != num );
523  lgErr = lgErr || ( fwrite(&dim,sizeof(long),num,fdes) != num );
524  num = (size_t)(LIMPAR*LIMPAR);
525  lgErr = lgErr || ( fwrite(a2,sizeof(realnum),num,fdes) != num );
526  num = (size_t)LIMPAR;
527  lgErr = lgErr || ( fwrite(c1,sizeof(realnum),num,fdes) != num );
528  lgErr = lgErr || ( fwrite(c2,sizeof(realnum),num,fdes) != num );
529  lgErr = lgErr || ( fwrite(xc,sizeof(realnum),num,fdes) != num );
530  lgErr = lgErr || ( fwrite(xcold,sizeof(realnum),num,fdes) != num );
531  num = 1;
532  lgErr = lgErr || ( fwrite(&dmax,sizeof(realnum),num,fdes) != num );
533  lgErr = lgErr || ( fwrite(&dold,sizeof(realnum),num,fdes) != num );
534  lgErr = lgErr || ( fwrite(&ymin,sizeof(realnum),num,fdes) != num );
535  lgErr = lgErr || ( fwrite(&nvar,sizeof(long),num,fdes) != num );
536  lgErr = lgErr || ( fwrite(&noptim,sizeof(long),num,fdes) != num );
537  num = (size_t)LIMPAR;
538  lgErr = lgErr || ( fwrite(varmax,sizeof(realnum),num,fdes) != num );
539  lgErr = lgErr || ( fwrite(varmin,sizeof(realnum),num,fdes) != num );
540  num = (size_t)STDLEN;
541  lgErr = lgErr || ( fwrite(chDum1,sizeof(char),num,fdes) != num );
542  lgErr = lgErr || ( fwrite(chDum2,sizeof(char),num,fdes) != num );
543  lgErr = lgErr || ( fwrite(chDum3,sizeof(char),num,fdes) != num );
544  fclose(fdes);
545  if( lgErr )
546  {
547  printf( "error writing file: %s\n",fnam );
548  res = remove(fnam);
549  /* following to keep lint quiet - res is not used anywhere */
550  if( false) fprintf(ioQQQ,"%i\n", res );
551  }
552  return;
553 }
554 
556  long *dim,
557  realnum a2[][LIMPAR], /* a2[LIMPAR][LIMPAR] */
558  realnum c1[], /* c1[LIMPAR] */
559  realnum c2[], /* c2[LIMPAR] */
560  realnum xc[], /* xc[LIMPAR] */
561  realnum xcold[], /* xcold[LIMPAR] */
562  realnum *dmax,
563  realnum *dold,
564  realnum *ymin,
565  long *nvar,
566  long *noptim,
567  realnum varmax[], /* varmax[LIMPAR] */
568  realnum varmin[], /* varmin[LIMPAR] */
569  char chDum1[], /* chDum1[STDLEN] */
570  char chDum2[], /* chDum2[STDLEN] */
571  char chDum3[], /* chDum3[STDLEN] */
572  const char *fnam)
573 {
574  bool lgErr;
575  size_t num;
576  FILE *fdes;
577 
578  DEBUG_ENTRY( "rd_continue()" );
579 
580  fdes = open_data( fnam, "rb", AS_LOCAL_ONLY );
581  lgErr = false;
582  num = 1;
583  lgErr = lgErr || ( fread(vers,sizeof(realnum),num,fdes) != num );
584  if( lgErr || *vers != VRSNEW )
585  {
586  printf( "optimize continue - file has incompatible version, sorry\n" );
587  cdEXIT(EXIT_FAILURE);
588  }
589  lgErr = lgErr || ( fread(dim,sizeof(long),num,fdes) != num );
590  if( lgErr || *dim != LIMPAR )
591  {
592  printf( "optimize continue - arrays have wrong dimension, sorry\n" );
593  cdEXIT(EXIT_FAILURE);
594  }
595  num = (size_t)(LIMPAR*LIMPAR);
596  lgErr = lgErr || ( fread(a2,sizeof(realnum),num,fdes) != num );
597  num = (size_t)LIMPAR;
598  lgErr = lgErr || ( fread(c1,sizeof(realnum),num,fdes) != num );
599  lgErr = lgErr || ( fread(c2,sizeof(realnum),num,fdes) != num );
600  lgErr = lgErr || ( fread(xc,sizeof(realnum),num,fdes) != num );
601  lgErr = lgErr || ( fread(xcold,sizeof(realnum),num,fdes) != num );
602  num = 1;
603  lgErr = lgErr || ( fread(dmax,sizeof(realnum),num,fdes) != num );
604  lgErr = lgErr || ( fread(dold,sizeof(realnum),num,fdes) != num );
605  lgErr = lgErr || ( fread(ymin,sizeof(realnum),num,fdes) != num );
606  lgErr = lgErr || ( fread(nvar,sizeof(long),num,fdes) != num );
607  lgErr = lgErr || ( fread(noptim,sizeof(long),num,fdes) != num );
608  num = (size_t)LIMPAR;
609  lgErr = lgErr || ( fread(varmax,sizeof(realnum),num,fdes) != num );
610  lgErr = lgErr || ( fread(varmin,sizeof(realnum),num,fdes) != num );
611  num = (size_t)STDLEN;
612  lgErr = lgErr || ( fread(chDum1,sizeof(char),num,fdes) != num );
613  lgErr = lgErr || ( fread(chDum2,sizeof(char),num,fdes) != num );
614  lgErr = lgErr || ( fread(chDum3,sizeof(char),num,fdes) != num );
615  fclose(fdes);
616  if( lgErr )
617  {
618  printf( "error reading file: %s\n",fnam );
619  cdEXIT(EXIT_FAILURE);
620  }
621  return;
622 }
623 
624 #ifdef __unix
625 
626 STATIC void cpfile(const char *fnam)
627 {
628  char chr;
629 
630  FILE *fdes;
631 
632  DEBUG_ENTRY( "cpfile()" );
633 
634  /* append output produced by child process on <fnam>, to output of parent process */
635 
636  fdes = open_data( fnam, "r", AS_LOCAL_ONLY_TRY );
637  if( fdes == NULL )
638  return;
639  chr = (char)fgetc(fdes);
640  while( ! feof(fdes) )
641  {
642  fputc( chr , ioQQQ );
643  chr = (char)fgetc(fdes);
644  }
645  fclose(fdes);
646  return;
647 }
648 
649 STATIC void wr_block(void *ptr,
650  size_t len,
651  const char *fnam)
652 {
653  FILE *fdes;
654 
655  DEBUG_ENTRY( "wr_block()" );
656 
657  /* write <len> bytes of data from buffer <*ptr> into unformatted file <fnam> */
658 
659  fdes = open_data( fnam, "wb", AS_LOCAL_ONLY );
660  if( fwrite(ptr,len,(size_t)1,fdes) != 1 ) {
661  printf( "error writing on file: %s\n",fnam );
662  fclose(fdes);
663  cdEXIT(EXIT_FAILURE);
664  }
665  fclose(fdes);
666  return;
667 }
668 
669 STATIC void rd_block(void *ptr,
670  size_t len,
671  const char *fnam)
672 {
673  FILE *fdes;
674 
675  DEBUG_ENTRY( "rd_block()" );
676 
677  /* read <len> bytes of data into buffer <*ptr> from unformatted file <fnam> */
678 
679  fdes = open_data( fnam, "rb", AS_LOCAL_ONLY );
680  if( fread(ptr,len,(size_t)1,fdes) != 1 ) {
681  printf( "error reading on file: %s\n",fnam );
682  fclose(fdes);
683  cdEXIT(EXIT_FAILURE);
684  }
685  fclose(fdes);
686  return;
687 }
688 
689 #endif

Generated for cloudy by doxygen 1.8.4