cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
grid_xspec.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2017 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*gridXspec handles all grid calculations, called by griddo */
4 /*gridFunc */
5 /*GridGatherInCloudy - gathers spectra for each grid calculation to save for end */
6 #include "cddefines.h"
7 #include "cddrive.h"
8 #include "continuum.h"
9 #include "rfield.h"
10 #include "grid.h"
11 #include "ipoint.h"
12 #include "called.h"
13 #include "prt.h"
14 
15 /*gridXspec handles all grid calculations, called by grid_do */
16 void gridXspec(realnum xc[], long int nInterpVars)
17 {
18  long int i;
19 
20  DEBUG_ENTRY( "gridXspec()" );
21 
22  if( nInterpVars > LIMPAR )
23  {
24  fprintf( ioQQQ, "grid_do: too many parameters are varied, increase LIMPAR\n" );
26  }
27 
28  optimize.nOptimiz = 0;
29  grid.nintparm = nInterpVars;
30 
31  /* if this is changed there must be some change made to actually
32  * stuff the additional parameter information. */
33  grid.naddparm = 0;
34 
36 
37  grid.totNumModels = 1;
38  /* >>chng 06 aug 21, allow the number of parameter values to be different for different parameters. */
39  for( i=0; i<nInterpVars; i++ )
40  {
41  /* >>chng 06 sep 4, use grid variable instead of passing to routine. */
43 
44  if( grid.paramValuesFromList[i].size() != 0 && grid.lgSaveXspec )
45  {
46  fprintf( ioQQQ, " PROBLEM The 'save XSPEC' and 'grid list' options do not work together.\n" );
47  fprintf( ioQQQ, " If any 'save XSPEC' command is given, all grid commands must follow this syntax:\n" );
48  fprintf( ioQQQ, " grid <p1> <p2> <p3> \n" );
49  fprintf( ioQQQ, " where p1 and p2 are the limits and p3 is a regular increment.\n Sorry.\n" );
51  }
52  }
53 
54  // option to cycle through grid multiple times, default is 1
56  ASSERT( grid.totNumModels > 1 );
57 
58  grid.paramNames = (char**)MALLOC(sizeof(char*)*(unsigned)(nInterpVars+grid.naddparm) );
59  grid.paramMethods = (long*)MALLOC(sizeof(long)*(unsigned)(nInterpVars+grid.naddparm) );
60  grid.paramRange = (realnum**)MALLOC(sizeof(realnum*)*(unsigned)(nInterpVars+grid.naddparm) );
61  grid.paramData = (realnum**)MALLOC(sizeof(realnum*)*(unsigned)(nInterpVars+grid.naddparm) );
62  grid.interpParameters = (realnum**)MALLOC(sizeof(realnum*)*(unsigned)(grid.totNumModels) );
63 
64  for( i=0; i<nInterpVars+grid.naddparm; i++ )
65  {
66  grid.paramNames[i] = (char*)MALLOC(sizeof(char)*(unsigned)(12) );
67  grid.paramRange[i] = (realnum*)MALLOC(sizeof(realnum)*(unsigned)(6) );
68  grid.paramData[i] = (realnum*)MALLOC(sizeof(realnum)*(unsigned)(grid.numParamValues[i]) );
69 
70  sprintf( grid.paramNames[i], "%s%ld", "PARAM", i+1 );
71  /* Method is 0 for linear, 1 for logarithmic */
72  grid.paramMethods[i] = 0;
73  /* Initial */
74  grid.paramRange[i][0] = xc[i]+grid.paramIncrements[i]*(grid.numParamValues[i]-1.f)/2.f;
75  /* Delta */
76  grid.paramRange[i][1] = grid.paramIncrements[i]/10.f;
77  /* Minimum */
78  grid.paramRange[i][2] = xc[i];
79  /* Bottom */
80  grid.paramRange[i][3] = xc[i]+grid.paramIncrements[i]/10.f;
81  /* Top */
82  grid.paramRange[i][4] = xc[i]+grid.paramIncrements[i]*(grid.numParamValues[i]-1.f)-grid.paramIncrements[i]/10.f;
83  /* Maximum */
84  grid.paramRange[i][5] = xc[i]+grid.paramIncrements[i]*(grid.numParamValues[i]-1.f);
85 
86  for( long j=0; j<grid.numParamValues[i]; j++ )
87  {
88  grid.paramData[i][j] = xc[i]+grid.paramIncrements[i]*j;
89  }
90  }
91 
92  for( i=0; i<grid.totNumModels; i++ )
93  {
94  grid.interpParameters[i] = (realnum*)MALLOC(sizeof(realnum)*(unsigned)(nInterpVars) );
95  }
96 
97  for( i=0; i< grid.totNumModels; i++ )
98  {
99  long j;
100  realnum variableVector[LIMPAR];
101 
102  for( j=0; j<nInterpVars; j++ )
103  {
104  int index;
105  long volumeOtherDimensions = 1;
106 
107  /* by "volume", we simply mean the product of the parameter dimensions
108  * AFTER the present index, i.e.:
109  * first "volume" is product of grid.numParamValues[1]*grid.numParamValues[2]*....grid.numParamValues[n]
110  * second "volume" is product of grid.numParamValues[2]*grid.numParamValues[3]*....grid.numParamValues[n]
111  * last "volume" is unity. */
112  for( long k=j+1; k<nInterpVars; k++ )
113  {
114  volumeOtherDimensions *= grid.numParamValues[k];
115  }
116 
117  /* For each successive parameter, the "volume" is less than the previous one.
118  * So the left-hand side of this modulus operation increases for each parameter,
119  * which causes the index of each parameter to be incremented more often than the
120  * index of the previous parameter. Thus, the last dimension is incremented
121  * every time, then the second to last dimension is incremented with each repeat
122  * of the last dimension. This repeats until, finally, the first dimension is
123  * incremented. For example, the indices of the parameter vectors for a 2x2x3
124  * box would be ordered as such:
125  * [0][0][0]
126  * [0][0][1]
127  * [0][0][2]
128  * [0][1][0]
129  * [0][1][1]
130  * [0][1][2]
131  * [1][0][0]
132  * [1][0][1]
133  * [1][0][2]
134  * [1][1][0]
135  * [1][1][1]
136  * [1][1][2]
137  */
138  index = (int)( (i/volumeOtherDimensions)%(grid.numParamValues[j]) );
139 
140  /* this prevents parameter incrementation for debugging purposes. */
141  if( grid.lgStrictRepeat )
142  variableVector[j] = xc[j];
143  else if( grid.paramValuesFromList[j].size() != 0U )
144  variableVector[j] = grid.paramValuesFromList[j][index];
145  else
146  variableVector[j] = xc[j] + grid.paramIncrements[j]*index;
147 
148  grid.interpParameters[i][j] = variableVector[j];
149 
151  variableVector[j] = log10(variableVector[j]);
152  }
153 
154  for( j=nInterpVars; j<LIMPAR; j++ )
155  {
156  variableVector[j] = xc[j];
157  }
158 
159  if( i == grid.totNumModels - 1 )
160  {
161  fixit("is this needed ??");
162  called.lgTalk = cpu.i().lgMPI_talk();
164  prt.lgFaintOn = true;
165  grid.lgGridDone = true;
166  }
167 
168  (void)optimize_func(variableVector,i);
169  }
170  return;
171 }
172 
173 /*GridGatherInCloudy - gathers spectra for each grid calculation to save for end */
175 {
176  long i;
177 
178  DEBUG_ENTRY( "GridGatherInCloudy()" );
179 
180  ASSERT( grid.lgGrid );
181 
182  /* malloc some arrays if first call and save continuum energies. */
183  if( grid.Energies.empty() )
184  {
185  long i1, i2;
186 
187  // this will happen if we have more MPI ranks than grid points
188  // the highest ranks will not have executed any model
189  if( rfield.nflux_with_check <= 0 )
190  ContCreateMesh();
191 
192  if( grid.LoEnergy_keV == 0. )
193  grid.ipLoEnergy = 0;
194  else
195  grid.ipLoEnergy = ipoint( grid.LoEnergy_keV * 1000. / EVRYD );
196 
197  if( grid.HiEnergy_keV == 0. || grid.HiEnergy_keV * 1000. / EVRYD > rfield.egamry() )
199  else
200  grid.ipHiEnergy = ipoint( grid.HiEnergy_keV * 1000. / EVRYD );
201 
203  ASSERT( grid.numEnergies > 0 );
204  grid.Energies.resize( grid.numEnergies );
206  for( i1=0; i1 < NUM_OUTPUT_TYPES; i1++ )
207  {
208  if( grid.lgOutputTypeOn[i1] )
209  {
211  for( i2=0; i2 < grid.totNumModels; i2++ )
212  {
214  }
215  }
216  }
217  grid.Spectra.alloc();
218  // this needs to be zeroed out for MPI runs
219  grid.Spectra.zero();
220 
221  for( i1=0; i1<grid.numEnergies; i1++ )
222  {
223  long j = grid.ipLoEnergy + i1;
224  grid.Energies[i1] = rfield.anu(j);
225  }
226  }
227 
229  {
230  ASSERT( optimize.nOptimiz >= 0 );
231 
232  for( i=0; i < NUM_OUTPUT_TYPES; i++ )
233  {
234  /* Grab spectrum for xspec printout
235  * at this point nOptimiz has already been incremented for first model */
236  if( grid.lgOutputTypeOn[i] )
238  &grid.Spectra[i][optimize.nOptimiz][0]);
239  }
240  }
241  else if( optimize.nOptimiz == grid.totNumModels )
242  {
243  if( cpu.i().lgMPI() )
244  {
245  multi_arr<realnum,3> Spectra_Copy = grid.Spectra;
246 
247  // combine the grid.Spectra data from all ranks. This is done by adding up
248  // the results from all ranks. All but one should be zero. This is needed
249  // because we do not know which rank calculated which grid point...
250  for( int i=0; i < NUM_OUTPUT_TYPES; ++i )
251  {
252  if( grid.lgOutputTypeOn[i] )
253  {
254  for( int j=0; j < grid.totNumModels; ++j )
255  {
256  MPI_Reduce( &Spectra_Copy[i][j][0], &grid.Spectra[i][j][0],
257  grid.numEnergies, MPI_type(grid.Spectra[i][j][0]),
258  MPI_SUM, 0, MPI_COMM_WORLD );
259  }
260  }
261  }
262  MPI_Barrier( MPI_COMM_WORLD );
263  }
264  }
265  else
266  {
267  TotalInsanity();
268  }
269  return;
270 }
realnum HiEnergy_keV
Definition: grid.h:69
NORETURN void TotalInsanity(void)
Definition: service.cpp:1067
long numEnergies
Definition: grid.h:59
realnum ** paramData
Definition: grid.h:31
bool lgGrid
Definition: grid.h:42
bool lgGridDone
Definition: grid.h:43
t_cpu_i & i()
Definition: cpu.h:415
#define MPI_Reduce(T, U, V, W, X, Y, Z)
Definition: mpi_utilities.h:90
vector< realnum > Energies
Definition: grid.h:26
chi2_type optimize_func(const realnum param[], int grid_index=-1)
realnum LoEnergy_keV
Definition: grid.h:69
long int nOptimiz
Definition: optimize.h:250
#define MPI_Barrier(Z)
Definition: mpi_utilities.h:84
long * paramMethods
Definition: grid.h:29
long ipHiEnergy
Definition: grid.h:68
long ipLoEnergy
Definition: grid.h:68
bool lgStrictRepeat
Definition: grid.h:44
FILE * ioQQQ
Definition: cddefines.cpp:7
bool lgTalk
Definition: called.h:12
void cdSPEC2(int Option, long int nEnergy, long int ipLoEnergy, long int ipHiEnergy, realnum ReturnedSpectrum[])
double anu(size_t i) const
Definition: mesh.h:111
long int nflux_with_check
Definition: rfield.h:51
realnum ** interpParameters
Definition: grid.h:32
long nintparm
Definition: grid.h:57
#define MALLOC(exp)
Definition: cddefines.h:556
long totNumModels
Definition: grid.h:61
long ipoint(double energy_ryd)
Definition: cont_ipoint.cpp:15
long numParamValues[LIMPAR]
Definition: grid.h:60
bool lgSaveXspec
Definition: grid.h:39
void ContCreateMesh()
t_rfield rfield
Definition: rfield.cpp:9
void GridGatherInCloudy(void)
Definition: grid_xspec.cpp:174
float realnum
Definition: cddefines.h:124
const int NUM_OUTPUT_TYPES
Definition: grid.h:22
#define EXIT_FAILURE
Definition: cddefines.h:168
bool lgFaintOn
Definition: prt.h:245
#define cdEXIT(FAIL)
Definition: cddefines.h:484
bool lgMPI_talk() const
Definition: cpu.h:394
const long LIMPAR
Definition: optimize.h:61
vector< realnum > paramValuesFromList[LIMPAR]
Definition: grid.h:36
multi_arr< realnum, 3 > Spectra
Definition: grid.h:27
t_optimize optimize
Definition: optimize.cpp:6
t_grid grid
Definition: grid.cpp:5
t_prt prt
Definition: prt.cpp:14
bool lgOptimizeAsLinear[LIMPAR]
Definition: optimize.h:184
bool lgLinearIncrements[LIMPAR]
Definition: grid.h:37
#define ASSERT(exp)
Definition: cddefines.h:617
void reserve(size_type i1)
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:729
bool lgMPI() const
Definition: cpu.h:388
double egamry() const
Definition: mesh.h:88
bool lgOutputTypeOn[NUM_OUTPUT_TYPES]
Definition: grid.h:66
realnum paramIncrements[LIMPAR]
Definition: grid.h:35
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1217
long nCycle
Definition: grid.h:64
void gridXspec(realnum *, long)
#define fixit(a)
Definition: cddefines.h:416
static t_cpu cpu
Definition: cpu.h:423
realnum ** paramRange
Definition: grid.h:30
t_called called
Definition: called.cpp:4
char ** paramNames
Definition: grid.h:28
bool lgTalkIsOK
Definition: called.h:23
long naddparm
Definition: grid.h:58