cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parse_compile.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 /*ParseCompile compile Werner or kurucz model atmospheres into cloudy format, originally by K Volk,
4  * also compile opacity and grains */
5 #include "cddefines.h"
6 #include "continuum.h"
7 #include "dense.h"
8 #include "iso.h"
9 #include "grains.h"
10 #include "rfield.h"
11 #include "stars.h"
12 #include "parser.h"
13 
15 {
16  long int ncell;
17  char
20 
21  DEBUG_ENTRY( "ParseCompile()" );
22 
23  /* >>chng 01 aug 24, remove compile opacity command */
24  /* this option to compile opacities into file for later use */
25  if( p.nMatch("OPAC") )
26  {
27  fprintf( ioQQQ, "The COMPILE OPACITIES command is currently not supported\n" );
29 
30 # if 0
31  /* calls fill to set up continuum energy mesh if first call,
32  * otherwise reset to original mesh */
34 
35  /* read in some external data files, but only if this is first call */
36  atmdat_readin();
37 
38  /* first generate the frequency array */
40 
42 
43  /* say that we want to compile the opacities */
44  opac.lgCompileOpac = true;
45 
46  /* generate initial set of opacities but only if this is the first call
47  * in this coreload */
49 
50  fprintf(ioQQQ,
51  "Success!! Created file opacity.opc\nMake sure this is on the path.\n" );
53 # endif
54  }
55 
56  /* >>chng 00 apr 27, modified for arbitrary file names by PvH
57  *
58  * this option to compile grains into file for later use
59  *
60  * the command supports the following syntax:
61  *
62  * COMPILE GRAINS
63  * compile a standard set of opacity files
64  *
65  * COMPILE GRAINS <refr-ind-file> <size-distr-file> [ <no-bins> ]
66  * compile a single opacity file
67  *
68  * Remarks:
69  * - the parameters of this command can be supplied in arbitrary order.
70  * - the file names can either be supplied as names between quotes or
71  * as keywords; it is allowed to use a filename between quotes for
72  * one file and a keyword for the other file; both names have to be
73  * present in either form, there are no defaults.
74  * - filenames are recognized by their extension: .rfi or .mix for
75  * refractive index files, and .szd for size distribution files,
76  * this allows their sequence to be arbitrary.
77  * - the number-of-bins parameter is optional, it is defaulted to 10.
78  *
79  * NB NB NB NB NB NB NB NB NB NB NB NB NB
80  *
81  * - in order not to upset FFmtRead for reading the number-of-bins
82  * parameter, all file names and keywords should be read first and
83  * erased after being read ! to assure that all digits are erased,
84  * the keywords 0M010, 0M100 and 1M000 are matched on all 5 characters.
85  * if keywords are known not to contain digits or minus signs, erasing
86  * is not necessary of course....
87  */
88  if( p.nMatch("GRAI") )
89  {
90 
91  /* calls fill to set up continuum energy mesh if first call,
92  * otherwise reset to original mesh */
94  /* >>chng 06 dec 13, this had been followed by calls to atmdat_readin &
95  * ConCreatePointer which had problems because the code was not
96  * fully initialized yet. Compile stars and compile grains would
97  * fail on mallocing an array of length zero */
98 
99  chRFI[0] = '\0';
100  chSZD[0] = '\0';
101 
102  /* get first filename (either .rfi or .szd file) */
103  if( p.nMatch( "\"" ) )
104  {
105  string chRead;
106  if (p.GetQuote(chRead ))
107  p.StringError();
108  if( strstr_s(chRead.c_str(),".rfi") != NULL || strstr_s(chRead.c_str(),".mix") != NULL )
109  {
110  strcpy(chRFI,chRead.c_str());
111  }
112  else if( strstr_s(chRead.c_str(),".szd") != NULL )
113  {
114  strcpy(chSZD,chRead.c_str());
115  }
116  else
117  {
118  fprintf( ioQQQ, " filename %s has unknown extension, sorry\n" , chRead.c_str() );
120  }
121  }
122 
123  /* get second filename (either .rfi or .szd file) */
124  if( p.nMatch( "\"" ) )
125  {
126  string chRead;
127  if (p.GetQuote(chRead ))
128  p.StringError();
129  if( strstr_s(chRead.c_str(),".rfi") != NULL || strstr_s(chRead.c_str(),".mix") != NULL )
130  {
131  strcpy(chRFI,chRead.c_str());
132  }
133  else if( strstr_s(chRead.c_str(),".szd") != NULL )
134  {
135  strcpy(chSZD,chRead.c_str());
136  }
137  else
138  {
139  fprintf( ioQQQ, " filename %s has unknown extension, sorry\n" , chRead.c_str() );
141  }
142  }
143 
144  /* if no .rfi file was supplied between quotes, check for keywords */
145  if( chRFI[0] == '\0' )
146  {
147  /* check on index of refraction names */
148  if( p.nMatchErase("AC1-") )
149  {
150  /* amorphous carbon from Rouleau & Martin 1991 */
151  strcpy(chRFI , "ac1-amcarb.rfi" );
152  /* erase this keyword, it upsets FFmtRead */
153  }
154  else if( p.nMatchErase("BE1-"))
155  {
156  /* amorphous carbon from Rouleau & Martin 1991 */
157  strcpy(chRFI , "be1-amcarb.rfi" );
158  /* erase this keyword, it upsets FFmtRead */
159  }
160  else if( p.nMatch( "GRAP") )
161  {
162  /* graphite */
163  strcpy(chRFI , "graphite.rfi" );
164  }
165  else if( p.nMatch( "SILI" ) )
166  {
167  /* astronomical silicate */
168  strcpy(chRFI , "silicate.rfi" );
169  }
170  else if( p.nMatch( " SIC" ) )
171  {
172  /* alpha-SiC */
173  strcpy(chRFI , "sic.rfi" );
174  }
175  else if( p.nMatch( " PAH" ) )
176  {
177  /* original PAHs */
178  strcpy(chRFI , "pah1.rfi" );
179  }
180  else if( p.nMatch( "GREY" ) || p.nMatch( "GRAY" ))
181  {
182  strcpy(chRFI , "grey.rfi" );
183  }
184  }
185 
186  /* if no .szd file was supplied between quotes, check for keywords */
187  if( chSZD[0] == '\0' )
188  {
189  /* check on size distribution */
190  if( p.nMatchErase("0M010") )
191  {
192  strcpy(chSZD , "0m010.szd" );
193  }
194  else if( p.nMatchErase("0M100") )
195  {
196  strcpy(chSZD , "0m100.szd" );
197  }
198  else if( p.nMatchErase("1M000") )
199  {
200  strcpy(chSZD , "1m000.szd" );
201  }
202  else if( p.nMatch( "ORIO" ) )
203  {
204  strcpy(chSZD , "orion.szd" );
205  }
206  else if( p.nMatch( " ISM" ) )
207  {
208  strcpy(chSZD , "ism.szd" );
209  }
210  else if( p.nMatchErase("AB08") )
211  {
212  /* Abel et al., 2008 size distribution */
213  strcpy(chSZD , "ab08.szd" );
214  }
215  else if( p.nMatchErase("C15") )
216  {
217  /* small PAH, 15 C atoms */
218  strcpy(chSZD , "c15.szd" );
219  }
220  else if( p.nMatchErase("C120") )
221  {
222  /* large PAH, 120 C atoms */
223  strcpy(chSZD , "c120.szd" );
224  }
225  }
226 
227  /* the user has to supply either both the .rfi and .szd files, or neither
228  * (to compile the complete standard set of files); anything else is illegal */
229  if( chRFI[0] == '\0' && chSZD[0] != '\0' )
230  {
231  fprintf(ioQQQ,"Sorry, but I did not recognize a refractive index file.\n");
232  fprintf(ioQQQ,"Supply a file name between quotes or one of the following ");
233  fprintf(ioQQQ,"keywords: ac1-amcarb, be1-amcarb, graphite, silicate, grey, pah\n");
235  }
236 
237  if( chSZD[0] == '\0' && chRFI[0] != '\0' )
238  {
239  fprintf(ioQQQ,"Sorry, but I did not recognize a size distribution file.\n");
240  fprintf(ioQQQ,"Supply a file name between quotes or one of the following ");
241  fprintf(ioQQQ,"keywords: 0m010, 0m100, 1m000, ism, orion, c15, c120, ab08\n");
243  }
244 
245  /* compile the complete standard set of files */
246  if( chRFI[0] == '\0' && chSZD[0] == '\0' )
247  {
248  /* ism graphite, single bin */
249  mie_write_opc( "graphite.rfi" , "ism.szd" , 1 );
250 
251  /* ism silicate, single bin */
252  mie_write_opc( "silicate.rfi" , "ism.szd" , 1 );
253 
254  /* ism graphite, 10 bins */
255  mie_write_opc( "graphite.rfi" , "ism.szd" , 10 );
256 
257  /* ism silicate, 10 bins */
258  mie_write_opc( "silicate.rfi" , "ism.szd" , 10 );
259 
260  /* orion graphite, single bin */
261  mie_write_opc( "graphite.rfi" , "orion.szd" , 1 );
262 
263  /* orion silicate, single bin */
264  mie_write_opc( "silicate.rfi" , "orion.szd" , 1 );
265 
266  /* orion graphite, 10 bins */
267  mie_write_opc( "graphite.rfi" , "orion.szd" , 10 );
268 
269  /* orion silicate, 10 bins */
270  mie_write_opc( "silicate.rfi" , "orion.szd" , 10 );
271 
272  /* 0.01 micron silicate */
273  mie_write_opc( "silicate.rfi" , "0m010.szd" , 1 );
274 
275  /* 0.1 micron silicate */
276  mie_write_opc( "silicate.rfi" , "0m100.szd" , 1 );
277 
278  /* 1 micron silicate */
279  mie_write_opc( "silicate.rfi" , "1m000.szd" , 1 );
280 
281  /* 0.01 micron graphite */
282  mie_write_opc( "graphite.rfi" , "0m010.szd" , 1 );
283 
284  /* 0.1 micron graphite */
285  mie_write_opc( "graphite.rfi" , "0m100.szd" , 1 );
286 
287  /* 1 micron graphite */
288  mie_write_opc( "graphite.rfi" , "1m000.szd" , 1 );
289 
290  /* grey single bin */
291  mie_write_opc( "grey.rfi" , "ism.szd" , 1 );
292 
293  /* grey resolved distribution */
294  mie_write_opc( "grey.rfi" , "ism.szd" , 10 );
295 
296  /* small pah */
297  mie_write_opc( "pah1.rfi" , "c15.szd" , 1 );
298 
299  /* large pah */
300  mie_write_opc( "pah1.rfi" , "c120.szd" , 1 );
301 
302  /* distributed pah */
303  mie_write_opc( "pah1.rfi" , "ab08.szd" , 10 );
304 
305  /* single pah */
306  mie_write_opc( "pah1.rfi" , "ab08.szd" , 1 );
307  }
308  /* this option is to compile a single type of grain */
309  else
310  {
311  ncell = (long)p.FFmtRead();
312  if( p.lgEOL() )
313  {
314  /* the default, 10 cells */
315  ncell = 10;
316  }
317  if( ncell <= 0 )
318  {
319  fprintf(ioQQQ,"Number of bins must be positive. Sorry.\n");
321  }
322  /* this actually does the work */
323  mie_write_opc( chRFI , chSZD , ncell );
324  }
325 
326  fprintf(ioQQQ,
327  "Success!! Created grain opacity file(s).\nMake sure this directory is on the path.\n" );
329  }
330 
331  /* compile recombination coefficients command */
332  else if( p.nMatch("RECO") && p.nMatch("COEF") )
333  {
334  long ipISO;
335  int nelem;
336 
337  if( p.nMatch("H-LI") )
338  ipISO = ipH_LIKE;
339  else if( p.nMatch("HE-L") )
340  ipISO = ipHE_LIKE;
341  else
342  {
343  fprintf(ioQQQ,"Sorry, but I did not recognize an iso sequence.\n");
344  fprintf(ioQQQ,"The available options are H-like and He-like.\nSorry.\n");
346  }
347 
348  /* compile he-like command - compiles table of recombination coeficients */
349  iso_ctrl.lgCompileRecomb[ipISO] = true;
350 
351  /* we will want to create the rec coefficient for a large number of levels, then stop.
352  * this sets the number of levels to a large number. macro is in helike.h */
353  for( nelem = ipISO; nelem < LIMELM; nelem++)
354  {
355  long maxN;
356  dense.lgElmtOn[nelem] = true;
357  iso_sp[ipISO][nelem].nCollapsed_max = 0;
358 
359  if( nelem == ipISO )
360  maxN = RREC_MAXN;
361  else
362  maxN = LIKE_RREC_MAXN( nelem );
363 
364  iso_sp[ipISO][nelem].n_HighestResolved_max = maxN;
365 
366  iso_update_num_levels( ipISO, nelem );
367  }
368  }
369 
370  else if( p.nMatch("STAR") )
371  {
372  bool lgProblems = false;
373 
374  /* check that frequency mesh is set up */
376 
377  if( p.nMatch( "\"" ))
378  {
379  /* this is branch for for user-supplied *.ascii file */
380 
381  /* this will both scan in whatever label is inside the quotes in OrgCard,
382  * but also remove the contents there and in chCard,
383  * so that following keywords will not trigger off it */
384  string chRead;
385  if (p.GetQuote( chRead ))
386  p.StringError();
387 
388  string::size_type ptr = chRead.rfind('.');
389  if( ptr != string::npos )
390  {
391  if( chRead.substr(ptr) == ".ascii" )
392  {
393  lgProblems = GridCompile( chRead.c_str() );
394  }
395  else if( chRead.substr(ptr) == ".stb99" )
396  {
397  // keyword to only include the stellar component
398  // default is to include both the stellar and nebular component
399  sb_mode mode;
400  if( p.nMatch( "STEL" ) )
401  mode = SB_STELLAR;
402  else if( p.nMatch( "NEBU" ) )
403  mode = SB_NEBULAR;
404  else
405  mode = SB_TOTAL;
406  string chASC(chRead.c_str(), ptr);
407  chASC += ".ascii";
408  fprintf( ioQQQ, " Creating %s....\n", chASC.c_str() );
409  lgProblems = StarburstInitialize( chRead.c_str(), chASC.c_str(), mode );
410  lgProblems = lgProblems || GridCompile( chASC.c_str() );
411  }
412  else
413  {
414  fprintf( ioQQQ, " I did not recognize this file extension: %s\n",
415  chRead.substr(ptr).c_str() );
416  lgProblems = true;
417  }
418  }
419  else
420  {
421  fprintf( ioQQQ, " I did not find any file extension: %s\n", chRead.c_str() );
422  lgProblems = true;
423  }
424  }
425  else
426  {
427  /* this branch is intended to convert ascii versions of stellar
428  * atmosphere grids into a direct access version for faster access.
429  * the original file is usually named *.ascii, and the new direct
430  * access file will always be named *.mod.
431  * - if the *.ascii file does not exist, the grid will be skipped
432  * - if the *.ascii file exists, but the *.mod file does not, or is
433  * out of date, a new *.mod file will be generated
434  * - if the *.mod file is up to date, it will not be touched. */
435 
436  process_counter pc;
437 
438  /* These are the current Atlas grids */
439  lgProblems = lgProblems || AtlasCompile(pc);
440  /* do the costar OB stars */
441  lgProblems = lgProblems || CoStarCompile(pc);
442  /* legacy Atlas grid - for backward compatibility only */
443  lgProblems = lgProblems || Kurucz79Compile(pc);
444  /* Mihalas grid - for backward compatibility only */
445  lgProblems = lgProblems || MihalasCompile(pc);
446  /* do the rauch PN central stars */
447  lgProblems = lgProblems || RauchCompile(pc);
448  /* do the Starburst99 sample output */
449  lgProblems = lgProblems || StarburstCompile(pc);
450  /* do the Tlusty OSTAR2002 grid */
451  lgProblems = lgProblems || TlustyCompile(pc);
452  /* do the Werner PN central stars - for backward compatibility only */
453  lgProblems = lgProblems || WernerCompile(pc);
454  /* WMBASIC O-star grid by Pauldrach */
455  lgProblems = lgProblems || WMBASICCompile(pc);
456 
457  if( pc.nFound == 0 )
458  {
459  fprintf( ioQQQ, "\n PROBLEM - No ascii files were found!\n" );
460  fprintf( ioQQQ, " Did you change directory to where the stellar atmosphere files are?\n" );
461  fprintf( ioQQQ, " This command will only work on files in the local directory. Sorry.\n" );
462  lgProblems = true;
463  }
464  else
465  {
466  fprintf( ioQQQ, "\n %d ascii file(s) found", pc.nFound );
467  if( pc.notProcessed > 0 )
468  fprintf( ioQQQ, ", %d file(s) up to date", pc.notProcessed );
469  if( pc.nOK > 0 )
470  fprintf( ioQQQ, ", %d update(s) OK", pc.nOK );
471  if( pc.nFail > 0 )
472  fprintf( ioQQQ, ", %d update(s) failed", pc.nFail );
473  int nSkip = pc.nFound - pc.notProcessed - pc.nOK - pc.nFail;
474  if( nSkip > 0 )
475  fprintf( ioQQQ, ", %d file(s) skipped after failure", nSkip );
476  fprintf( ioQQQ, ".\n" );
477  }
478  }
479 
480  if( lgProblems )
481  {
482  fprintf( ioQQQ, "\n Problems occurred during the compilation - check output.\n" );
483  }
484  else
485  {
486  fprintf( ioQQQ, "\n The compilation was successful!\n" );
487  fprintf( ioQQQ, "\n Good Luck!!\n\n\n" );
488  }
489 
490  cdEXIT( lgProblems ? ES_FAILURE : ES_SUCCESS );
491  }
492  else
493  {
494  fprintf( ioQQQ, " One of the keywords, GRAINS, RECO COEF, or STARS, must appear.\n" );
495  fprintf( ioQQQ, " Sorry.\n" );
497  }
498 
499  return;
500 }
bool nMatch(const char *chKey) const
Definition: parser.h:150
int WernerCompile(process_counter &pc)
Definition: stars.cpp:1651
bool GridCompile(const char *InName)
Definition: stars.cpp:721
double FFmtRead(void)
Definition: parser.cpp:472
const int ipHE_LIKE
Definition: iso.h:65
const int FILENAME_PATH_LENGTH_2
Definition: cddefines.h:296
t_opac opac
Definition: opacity.cpp:5
t_isoCTRL iso_ctrl
Definition: iso.cpp:9
void OpacityCreateAll(void)
bool lgCompileRecomb[NISO]
Definition: iso.h:400
int notProcessed
Definition: stars.h:32
long int nCollapsed_max
Definition: iso.h:518
int TlustyCompile(process_counter &pc)
Definition: stars.cpp:1522
int GetQuote(string &chLabel)
Definition: parser.cpp:213
const char * strstr_s(const char *haystack, const char *needle)
Definition: cddefines.h:1300
bool nMatchErase(const char *chKey)
Definition: parser.h:173
int nFound
Definition: stars.h:31
FILE * ioQQQ
Definition: cddefines.cpp:7
Definition: parser.h:43
NORETURN void StringError() const
Definition: parser.cpp:203
t_dense dense
Definition: global.cpp:15
int RauchCompile(process_counter &pc)
Definition: stars.cpp:1001
t_iso_sp iso_sp[NISO][LIMELM]
Definition: iso.cpp:11
void ParseCompile(Parser &p)
void Badnell_rec_init(void)
void iso_update_num_levels(long ipISO, long nelem)
long int n_HighestResolved_max
Definition: iso.h:536
void ContCreatePointers(void)
void ContCreateMesh()
int AtlasCompile(process_counter &pc)
Definition: stars.cpp:452
int Kurucz79Compile(process_counter &pc)
Definition: stars.cpp:903
bool lgMeshSetUp() const
Definition: mesh.h:84
bool StarburstCompile(process_counter &pc)
Definition: stars.cpp:1498
void mie_write_opc(const char *, const char *, long int)
Definition: grains_mie.cpp:274
t_rfield rfield
Definition: rfield.cpp:9
int CoStarCompile(process_counter &pc)
Definition: stars.cpp:622
#define EXIT_FAILURE
Definition: cddefines.h:168
bool lgCompileOpac
Definition: opacity.h:205
#define cdEXIT(FAIL)
Definition: cddefines.h:482
#define LIKE_RREC_MAXN(A_)
Definition: iso.h:100
bool lgElmtOn[LIMELM]
Definition: dense.h:160
int MihalasCompile(process_counter &pc)
Definition: stars.cpp:949
#define ASSERT(exp)
Definition: cddefines.h:613
const int ipH_LIKE
Definition: iso.h:64
const int LIMELM
Definition: cddefines.h:308
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:723
bool lgEOL(void) const
Definition: parser.h:113
Definition: stars.h:26
void atmdat_readin(void)
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1121
int WMBASICCompile(process_counter &pc)
Definition: stars.cpp:1744
sb_mode
Definition: stars.h:25
#define RREC_MAXN
Definition: iso.h:97
bool StarburstInitialize(const char chInName[], const char chOutName[], sb_mode mode)
Definition: stars.cpp:1379
#define EXIT_SUCCESS
Definition: cddefines.h:166