cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parse_grid.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2022 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*ParseGrid parse the grid command lines */
4 #include "cddefines.h"
5 #include "grid.h"
6 #include "input.h"
7 #include "parser.h"
8 
9 /* ParseGrid - called from ParseCommands if GRID command found */
10 void ParseGrid(
11  /* command line, which was changed to all caps in main parsing routine */
12  Parser &p)
13 {
14  DEBUG_ENTRY( "ParseGrid()" );
15 
16  /* RP fake optimizer to run a grid of calculations, also accepts
17  * keyword XSPEC */
18  strcpy( optimize.chOptRtn, "XSPE" );
19  grid.lgGrid = true;
20 
21  if( p.nMatch("REPE") )
22  {
23  /* just keep repeating, don't actually change the values in the grid.
24  * useful for debugging unintentional crosstalk */
25  grid.lgStrictRepeat = true;
26  }
27 
28  if( p.nMatch("SEPA") )
29  {
30  /* keep main output files separate, this cuts down the
31  * gathering time substantially for huge grid runs */
33  }
34 
35  if( p.nMatch("SEQU") )
36  {
37  /* run grid in sequential mode */
38  grid.lgParallel = false;
39  }
40 
41  /* 06 aug 22, change to accept three parameters: lower and upper limit and number of points. */
42  /* scan off range for the previously selected variable */
43  if( optimize.nparm > 0 )
44  {
46 
47  grid.lgLinearIncrements[optimize.nparm-1] = p.nMatch("LINE") ? true : false ;
48 
49  string chLabel;
50  if( p.nMatch("LIST") )
51  {
52  if( p.GetQuote( chLabel ) )
53  p.StringError();
54 
55  vector<double> tmpVector;
56  bool lgError = false;
57  input_readvector( chLabel.c_str(), tmpVector, &lgError );
58  if( lgError )
59  {
60  fprintf( ioQQQ, " PROBLEM An error occurred reading file %s.\n Sorry.\n", chLabel.c_str() );
62  }
63 
64  for( vector<double>::iterator it = tmpVector.begin(); it != tmpVector.end(); ++it )
65  grid.paramValuesFromList[optimize.nparm-1].push_back( (realnum)*it );
66 
68  if( grid.numParamValues[optimize.nparm-1] < 2 )
69  {
70  fprintf(ioQQQ, "PROBLEM there must be at least two grid steps but only one was found.\n");
72  }
74 
75  // Set original limits to end points.
77  *min_element( grid.paramValuesFromList[optimize.nparm-1].begin(), grid.paramValuesFromList[optimize.nparm-1].end() );
79  *max_element( grid.paramValuesFromList[optimize.nparm-1].begin(), grid.paramValuesFromList[optimize.nparm-1].end() );
80  // Set increment to zero.
82  }
83  else
84  {
90 
91  /* the increase step should not be 0 */
92  if( grid.paramIncrements[optimize.nparm-1] == 0. )
93  {
94  fprintf( ioQQQ," The increment (third parameter) should not be zero.\n" );
95  fprintf( ioQQQ," Sorry.\n" );
97  }
98 
99  if( p.lgEOL() )
100  {
101  fprintf( ioQQQ," This command has changed since the definition given in Porter et al. 2006, PASP, 118, 920.\n" );
102  fprintf( ioQQQ," The grid command now requires three parameters: lower limit, upper limit, and increment.\n" );
103  fprintf( ioQQQ," The keywords RANGE and STEPS are no longer necessary.\n" );
104  fprintf( ioQQQ," Sorry.\n" );
105  cdEXIT( EXIT_FAILURE );
106  }
107  else
108  {
110  }
111 
114 
115  /* Alert if the uplimit and lowlimit are wrong */
116  if( ratio < realnum(0.) )
117  {
118  fprintf( ioQQQ, "The increment (third parameter) has the wrong sign. \
119  It doesn't take you from the initial to the final grid value (first and second parameter, resp.).\n" );
120  fprintf( ioQQQ," Sorry.\n" );
121  cdEXIT( EXIT_FAILURE );
122  }
123 
124  // this takes care of the blowup in the error due to cancellation in limits[1]-limits[0]
125  // it assumes that limits[1]-limits[0] is accurate within 3*eps*(limits[0]+limits[1])/2
126  // which should be a very conservative estimate...
127  realnum feps = safe_div(realnum(1.5)*
130 
131  // this will blow for pathologically narrow grid ranges
132  ASSERT( abs(feps) < realnum(INT_MAX) );
133  int eps = max(int(abs(feps)),3);
134 
135  // take special care if step is integer fraction of max-min (which is nearly always the case)
136  if( fp_equal( ratio, realnum(nint(ratio)), int(eps) ) )
137  grid.numParamValues[optimize.nparm-1] = nint(ratio) + 1;
138  else
139  grid.numParamValues[optimize.nparm-1] = long(ratio) + 1;
140 
141  if( grid.numParamValues[optimize.nparm-1] < 2 )
142  {
143  fprintf( ioQQQ, " There must be at least two grid points in each dimension.\n" );
144  fprintf( ioQQQ, " Sorry.\n" );
145  cdEXIT( EXIT_FAILURE );
146  }
147 
149  }
150 
151  if( p.nMatch("CYCL") )
152  {
153  /* cycle through the grid multiple times, only used for testing */
154  grid.nCycle = nint(p.FFmtRead());
155  if( p.lgEOL() )
156  grid.nCycle = 2;
157  if( grid.nCycle < 2 )
158  {
159  fprintf( ioQQQ, " Invalid repetion number for cycle: %ld\n", grid.nCycle );
160  fprintf( ioQQQ, " Usage: grid <p1> <p2> <p3> cycle [ <n> ] with n >= 2.\n" );
161  fprintf( ioQQQ, " or: grid list \"filename\" cycle [ <n> ] with n >= 2.\n" );
162  cdEXIT( EXIT_FAILURE );
163  }
164  }
165 
166  if( p.nMatch("NCPU") )
167  {
168  /* set number of CPUs to be used for the grid */
169  long dum = nint(p.FFmtRead());
170  if( grid.lgParallel )
171  {
172  grid.useCPU = p.lgEOL() ? cpu.i().nCPU() : max(dum,0);
173  }
174  else
175  {
176  grid.useCPU = 1;
177  }
178  if( grid.useCPU == 0 )
179  {
180  fprintf( ioQQQ, " Invalid number of CPUs: %ld\n", dum );
181  fprintf( ioQQQ, " Usage: grid <p1> <p2> <p3> ncpus [ <n> ] with n >= 1.\n" );
182  fprintf( ioQQQ, " or: grid list \"filename\" ncpus [ <n> ] with n >= 1.\n" );
183  cdEXIT( EXIT_FAILURE );
184  }
185  }
186 
187  // Create some buffer area in the allowed range of parameter values to prevent
188  // accidentally going over the limit due to roundoff error. The buffer is 1/10th
189  // of a step, so should still guard against doing too many steps due to bugs.
190  realnum safety = 0.001f*grid.paramIncrements[optimize.nparm-1];
191 
193  {
194  if( grid.paramLimits[optimize.nparm-1][0]-safety<=0. )
195  {
196  fprintf(ioQQQ,"The current implementation of the grid command works with log parameter values even when you specify LINEAR.\n");
197  fprintf(ioQQQ,"A non-positive value was entered. The grid command cannot deal with this.\n");
198  cdEXIT( EXIT_FAILURE );
199  }
200  optimize.varang[optimize.nparm-1][0] = log10(grid.paramLimits[optimize.nparm-1][0]-safety);
201  optimize.varang[optimize.nparm-1][1] = log10(grid.paramLimits[optimize.nparm-1][1]+safety);
202  }
203  else
204  {
207  }
208  }
209 
210  return;
211 }
bool nMatch(const char *chKey) const
Definition: parser.h:150
double FFmtRead(void)
Definition: parser.cpp:472
long int nRangeSet
Definition: optimize.h:204
bool lgGrid
Definition: grid.h:41
t_cpu_i & i()
Definition: cpu.h:419
bool lgKeepMainOutputSeparate
Definition: grid.h:53
int GetQuote(string &chLabel)
Definition: parser.cpp:213
realnum varang[LIMPAR][2]
Definition: optimize.h:201
bool lgStrictRepeat
Definition: grid.h:45
FILE * ioQQQ
Definition: cddefines.cpp:7
void ParseGrid(Parser &p)
Definition: parse_grid.cpp:10
Definition: parser.h:43
NORETURN void StringError() const
Definition: parser.cpp:203
bool fp_equal(sys_float x, sys_float y, int n=3)
Definition: cddefines.h:854
long numParamValues[LIMPAR]
Definition: grid.h:60
long int nparm
Definition: optimize.h:204
void input_readvector(const char *chFile, vector< double > &vec, bool *lgError)
Definition: input.cpp:246
float realnum
Definition: cddefines.h:124
#define EXIT_FAILURE
Definition: cddefines.h:168
long max(int a, long b)
Definition: cddefines.h:817
#define cdEXIT(FAIL)
Definition: cddefines.h:482
sys_float safe_div(sys_float x, sys_float y, sys_float res_0by0)
Definition: cddefines.h:1011
const long LIMPAR
Definition: optimize.h:61
vector< realnum > paramValuesFromList[LIMPAR]
Definition: grid.h:35
t_optimize optimize
Definition: optimize.cpp:6
t_grid grid
Definition: grid.cpp:5
char chOptRtn[5]
Definition: optimize.h:268
bool lgLinearIncrements[LIMPAR]
Definition: grid.h:36
bool lgNegativeIncrements
Definition: grid.h:37
#define ASSERT(exp)
Definition: cddefines.h:613
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:723
unsigned int useCPU
Definition: grid.h:50
bool lgEOL(void) const
Definition: parser.h:113
#define MAX2(a, b)
Definition: cddefines.h:824
realnum paramIncrements[LIMPAR]
Definition: grid.h:34
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1121
long nCycle
Definition: grid.h:64
long nCPU() const
Definition: cpu.h:388
long nint(double x)
Definition: cddefines.h:758
static t_cpu cpu
Definition: cpu.h:427
realnum paramLimits[LIMPAR][2]
Definition: grid.h:33
bool lgParallel
Definition: grid.h:47