cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
species.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 #include "cddefines.h"
4 #include "species.h"
5 #include "taulines.h"
6 #include "input.h"
7 #include "dense.h"
8 #include "atmdat.h"
9 #include "elementnames.h"
10 #include "version.h"
11 #include "save.h"
12 #include "mole.h"
13 #include "service.h"
14 #include "parse_species.h"
15 #include "prt.h"
16 
17 /*File nemala.cpp was developed by Humeshkar B Nemala as a part of his thesis work during the Summer of 2007*/
18 /* Initially the code has been developed to read in energy levels,radiative and
19  * collisional data from the CHIANTI and LEIDEN databases. The idea is to extend it to more databases.
20  * In the case of the Leiden database there is a single .dat file which has the energy levels information,
21  * radiative and collisional data, with the data corresponding to each collider coming one after the other.
22  * In the case of CHIANTI, the energy levels data, radiative data and collision data are present in seperate files.
23  * While LEIDEN gives collisional rate coefficients, CHIANTI gives collisional strengths.
24  * In the case of CHIANTI only two colliders are used:electrons and protons. They appear as separate files.
25  * The electron collision strengths files are always expected to be there. A flag is set and data processed
26  * if the file on proton collision strengths is available.*/
27 
28 /* There is an initialization file called species.ini which tells Cloudy what kind of data is to be used */
29 /* Structures are created separately to hold the transition data,radiative and collisional data */
30 /* The collisional structures are different for different databases depending upon whether */
31 /* collisional strengths or collisional rate coefficients are used.Finally a superstructure is constructed to hold */
32 /* the total collisional rate obtained by considering all the colliders */
33 /* The colliders considered are electron,proton,Atomic Hydrogen,He,He+,He++,Ortho Molecular Hydrogen,Para Molecular Hydrogen and Molecular Hydrogen */
34 STATIC void states_popfill(void);
35 STATIC void states_nelemfill(void);
36 STATIC void database_prep(int);
37 STATIC void trim_levels(long);
38 STATIC void set_fractionation( species *sp );
39 STATIC void states_propprint(void);
40 
41 #define DEBUGSTATE false
42 void database_readin( void )
43 {
44  int i,intNoSp;
45 
46  FILE *ioMASTERLIST, *ioVERSION;
47 
48  char *chToken;
49 
50  char chLine[FILENAME_PATH_LENGTH_2],
51  chDLine[FILENAME_PATH_LENGTH_2],
52  chPath[FILENAME_PATH_LENGTH_2] = "";
53 
54  const int MAX_NUM_SPECIES = 1000;
55 
56  char chLabels[MAX_NUM_SPECIES][CHARS_SPECIES];
57  char chLabelsOrig[MAX_NUM_SPECIES][CHARS_SPECIES];
58  char chPaths[MAX_NUM_SPECIES][FILENAME_PATH_LENGTH_2];
59 
60  static int nCalled = 0;
61  long nSpeciesLAMDA, nSpeciesSTOUT, nSpeciesCHIANTI;
62 
63  DEBUG_ENTRY( "database_readin()" );
64 
65  /* only do this once. */
66  if( nCalled > 0 )
67  {
68  return;
69  }
70 
71  /* this is first call, increment the nCalled counterso never do this again */
72  ++nCalled;
73 
74  // read masterlists, count number of species
75  nSpecies = 0;
76 
78  //
79  // Read LAMDA masterlist
80  //
82 
83  /* count how many lines are in the file, ignoring all lines
84  * starting with '#':This would give the number of molecules */
85  nSpeciesLAMDA = 0;
86 
87  if( atmdat.lgLamdaOn )
88  {
89  long numModelsNotUsed = 0;
90  strcpy( chPath, "lamda" );
91  strcat( chPath, input.chDelimiter );
92  strcat( chPath, "masterlist" );
93  strcat( chPath, input.chDelimiter );
94  strcat( chPath, atmdat.chLamdaFile );
95 
96  ioMASTERLIST = open_data( chPath, "r" );
97 
98  if( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) == NULL )
99  {
100  fprintf( ioQQQ, " database_readin could not read first line of LAMDA masterlist.\n");
102  }
103 
104  do
105  {
106  if ((chLine[0]!='#') && (chLine[0]!='\n')&&(chLine[0]!='\t')&&(chLine[0]!='\r'))
107  {
108  strcpy(chDLine, chLine);
109  chToken = strtok(chDLine," \t\n");
110  if( findspecies( chToken ) != null_mole ||
111  ( chToken[1]=='-' && findspecies( chToken+2 ) != null_mole ) )
112  {
113  ASSERT( nSpecies + 1 <= MAX_NUM_SPECIES );
114  ASSERT( nSpeciesLAMDA + 1 <= MAX_NUM_SPECIES );
115  ASSERT( strlen(chToken) < CHARS_SPECIES );
116  strcpy( chLabels[nSpecies], chToken );
117  chLabels[nSpecies][CHARS_SPECIES-1] = '\0';
118 
119  // path is, for example, LAMDA/no.dat
120  strcpy( chPaths[nSpecies], "lamda" );
121  strcat( chPaths[nSpecies], input.chDelimiter );
122  chToken = strtok( NULL," \t\n" );
123  strcat( chPaths[nSpecies], chToken );
124  ++nSpecies;
125  ++nSpeciesLAMDA;
126  }
127  else
128  ++numModelsNotUsed;
129  }
130  }
131  while( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) != NULL );
132 
133  /* \todo 1 - save this and stuff as note since not really a "PROBLEM" but worth reporting */
134  //if( !t_version::Inst().lgRelease && numModelsNotUsed > 0 )
135  // fprintf( ioQQQ, "\n PROBLEM - %li LAMDA models could not be found in chemistry network.\n\n\n", numModelsNotUsed );
136 
137  fclose(ioMASTERLIST);
138  }
139 
140  /* Print LAMDA molecule list if save data sources is on*/
141  if( save.lgSDSOn && atmdat.lgLamdaOn)
142  {
143  fprintf(save.ipSDSFile, "##################################################\n");
144  fprintf( save.ipSDSFile,"LAMDA (2005, A&A, 432, 369) molecules in this run.\n");
145  for( int i=0; i<nSpeciesLAMDA; i++)
146  {
147  fprintf( save.ipSDSFile,"%s\t\t",chLabels[i]);
148  if( (i+1)%5 == 0)
149  {
150  fprintf( save.ipSDSFile, "\n");
151  }
152  }
153  fprintf(save.ipSDSFile,"\n\n");
154  }
155 
157  //
158  // Read CDMS/JPL masterlist
159  //
160  // These data files are in LAMDA format
161  //
163 
164  if( atmdat.lgCalpgmOn )
165  {
166  strcpy( chPath, "cdms+jpl" );
167  strcat( chPath, input.chDelimiter );
168  strcat( chPath, "masterlist" );
169 
170  ioMASTERLIST = open_data( chPath, "r" );
171 
172  if( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) == NULL )
173  {
174  fprintf( ioQQQ, " database_readin could not read first line of CDMS/JPL masterlist.\n");
176  }
177 
178  do
179  {
180  if ((chLine[0]!='#') && (chLine[0]!='\n')&&(chLine[0]!='\t')&&(chLine[0]!='\r'))
181  {
182  strcpy(chDLine, chLine);
183  chToken = strtok(chDLine," \t\n");
184  // hacks for alternative dialects...
185  if( strcmp( chToken, "SH" ) == 0 )
186  strcpy( chToken, "HS" );
187  if( strcmp( chToken, "SH+" ) == 0 )
188  strcpy( chToken, "HS+" );
189  if( strcmp( chToken, "SD" ) == 0 )
190  strcpy( chToken, "DS" );
191  if( strcmp( chToken, "CCH" ) == 0 )
192  strcpy( chToken, "C2H" );
193  if( strcmp( chToken, "CCD" ) == 0 )
194  strcpy( chToken, "C2D" );
195  if( strcmp( chToken, "^17OO" ) == 0 )
196  strcpy( chToken, "O^17O" );
197  if( strcmp( chToken, "H^18O" ) == 0 )
198  strcpy( chToken, "^18OH" );
199  if( strcmp( chToken, "HCCD" ) == 0 )
200  strcpy( chToken, "C2HD" );
201  if( strcmp( chToken, "^13CCCH" ) == 0 )
202  strcpy( chToken, "^13CC2H" );
203  if( strcmp( chToken, "CC^13CH" ) == 0 )
204  strcpy( chToken, "C2^13CH" );
205  if( strcmp( chToken, "H^13CCCN" ) == 0 )
206  strcpy( chToken, "H^13CC2N" );
207  if( strcmp( chToken, "HCC^13CN" ) == 0 )
208  strcpy( chToken, "HC2^13CN" );
209  if( strcmp( chToken, "HCCC^15N" ) == 0 )
210  strcpy( chToken, "HC3^15N" );
211  // this molecule is cyclic, so these two are identical
212  if( strcmp( chToken, "Si^13CC" ) == 0 )
213  strcpy( chToken, "SiC^13C" );
214  if( findspecies( chToken ) != null_mole ||
215  ( chToken[1]=='-' && findspecies( chToken+2 ) != null_mole ) )
216  {
217  ASSERT( nSpecies + 1 <= MAX_NUM_SPECIES );
218  ASSERT( nSpeciesLAMDA + 1 <= MAX_NUM_SPECIES );
219  strcpy( chLabels[nSpecies], chToken );
220  chLabels[nSpecies][CHARS_SPECIES-1] = '\0';
221 
222  strcpy( chPaths[nSpecies], "cdms+jpl" );
223  strcat( chPaths[nSpecies], input.chDelimiter );
224  chToken = strtok( NULL," \t\n" );
225  strcat( chPaths[nSpecies], chToken );
226  ++nSpecies;
227  ++nSpeciesLAMDA;
228  }
229  else
230  {
231  if( !t_version::Inst().lgRelease )
232  fprintf( ioQQQ, "Warning: CDMS/JPL species %s not found\n", chToken );
233  }
234  }
235  }
236  while( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) != NULL );
237 
238  fclose(ioMASTERLIST);
239  }
240 
242  //
243  // Read STOUT masterlist and VERSION
244  //
246  nSpeciesSTOUT = 0;
247 
248  //numLevels: index is nSpecies, value is the number of levels
249  vector<long> numLevels(MAX_NUM_SPECIES,0L);
250 
251  if( atmdat.lgStoutOn )
252  {
253  // default location of Stout masterlist file
254  strcpy( chPath, "stout" );
255  strcat( chPath, input.chDelimiter );
256  strcat( chPath, "masterlist" );
257  strcat( chPath, input.chDelimiter );
258 
259  strcat( chPath, atmdat.chStoutFile );
260 
261  // first try local directory, then data/SED
262  if( (ioMASTERLIST = open_data( atmdat.chStoutFile, "r", AS_LOCAL_ONLY_TRY ) ) == NULL )
263  {
264  ioMASTERLIST = open_data( chPath, "r" );
265  }
266 
267  // magic number
268  if( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) == NULL )
269  {
270  fprintf( ioQQQ, " database_readin could not read first line of stout.ini.\n");
272  }
273 
274  bool lgEOL1=true, lgEOL2=true, lgEOL3=true;
275  long int nMonRdST=-1, nDayRdST=-1;
276  long int ipST = 1;
277  long int nYrRdST = (long)FFmtRead(chLine,&ipST,sizeof(chLine),&lgEOL1);
278  if( !lgEOL1 )
279  {
280  nMonRdST = (long)FFmtRead(chLine,&ipST,sizeof(chLine),&lgEOL2);
281  if( !lgEOL2 )
282  nDayRdST = (long)FFmtRead(chLine,&ipST,sizeof(chLine),&lgEOL3);
283  }
284  if( lgEOL3 )
285  {
286  fprintf(ioQQQ,"PROBLEM, there must be three magic numbers on the first line of the stout masterlist file.\n");
288  }
289 
290  static long int nYrST =11 , nMonST = 10, nDayST = 25;
291  if( ( nYrRdST != nYrST ) || ( nMonRdST != nMonST ) || ( nDayRdST != nDayST ) )
292  {
293  fprintf( ioQQQ,
294  " I expected to find the number %2.2li %2.2li %2.2li and got %2.2li %2.2li %2.2li instead.\n" ,
295  nYrST , nMonST , nDayST , nYrRdST , nMonRdST , nDayRdST );
296  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
298  }
299  if( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) == NULL )
300  {
301  fprintf( ioQQQ, " database_readin could not read first line of CHIANTI masterlist.\n");
303  }
304 
305  do
306  {
307  strcpy(chDLine, chLine);
308  // three delimiters for tokesn, space, tab, newline
309  // species name can have any number of columns
310  // we will split line into two tokens, the name,
311  // and the remainder of the lines
312  chToken = strtok(chDLine," \t\n");
313 
314  if ((chLine[0]!='#') && (chLine[0]!='\n')&&(chLine[0]!='\t')&&(chLine[0]!='\r'))
315  {
316  ASSERT( nSpecies + 1 <= MAX_NUM_SPECIES );
317  ASSERT( nSpeciesSTOUT + 1 <= MAX_NUM_SPECIES );
318 
319  // first token is the species name
320  strcpy( chLabels[nSpecies], chToken );
321  strcpy( chLabelsOrig[nSpecies], chLabels[nSpecies] );
322 
323  // second optional token is lower limit to number of levels
324  // first get full string after arbitrary length species name
325  char *chNumLevs = strtok(NULL,"\n");
326  if( chNumLevs != NULL )
327  {
328  long i = 1;
329  bool lgEOL;
330  long numLevs = (long)FFmtRead(chNumLevs,&i,sizeof(chLine),&lgEOL);
331  // was there a lower bound to the number of levels
332  if( !lgEOL )
333  {
334  if( numLevs > 0 )
335  {
336  numLevels[nSpecies] = numLevs;
337  }
338  else
339  {
340  fprintf(ioQQQ,"PROBLEM the limit to the number of levels must be positive, it was %li\n", numLevs);
341  fprintf(ioQQQ,"The species was %s\n",chToken );
342  cdEXIT( EXIT_FAILURE );
343  }
344  }
345  }
346 
347  bool skipSpecies = false;
348 
349  //Check for duplicate species within Stout masterlist
350  for( int j = nSpeciesLAMDA; j < nSpecies; j++)
351  {
352  if( strcmp( chLabelsOrig[j], chLabelsOrig[nSpecies] ) == 0)
353  {
354  fprintf(ioQQQ,"%s appears multiple times in %s.\n",chLabels[nSpecies],atmdat.chStoutFile);
355  skipSpecies = true;
356  break;
357  }
358  }
359 
360  if( skipSpecies )
361  continue;
362 
363  char *chElement, chTokenTemp[7];
364  strcpy( chTokenTemp, chToken );
365  (void) strtok(chTokenTemp," \n");
366  chElement = strtok(chTokenTemp,"_");
367  uncaps( chElement );
368 
369  // path is, for example, CHIANTI/ar/ar_10/ar_10
370  // we will append extensions later
371  strcpy( chPaths[nSpecies], "stout" );
372  strcat( chPaths[nSpecies], input.chDelimiter );
373  strcat( chPaths[nSpecies], chElement );
374  strcat( chPaths[nSpecies], input.chDelimiter );
375  strcat( chPaths[nSpecies], chLabels[nSpecies] );
376  strcat( chPaths[nSpecies], input.chDelimiter );
377  strcat( chPaths[nSpecies], chLabels[nSpecies] );
378 
379  ASSERT( isalpha(chToken[0]) );
380  long cursor=0;
381  chLabels[nSpecies][0] = chToken[0];
382  if( isalpha(chToken[1]) )
383  {
384  chLabels[nSpecies][1] = chToken[1];
385  cursor = 2;
386  }
387  else
388  {
389  chLabels[nSpecies][1] = ' ';
390  cursor = 1;
391  }
392 
393  ASSERT( chToken[cursor]=='_' );
394  ++cursor;
395  ASSERT( isdigit(chToken[cursor]) );
396 
397  if( isdigit(chToken[cursor+1]) )
398  {
399  chLabels[nSpecies][2] = chToken[cursor++];
400  chLabels[nSpecies][3] = chToken[cursor++];
401  }
402  else
403  {
404  chLabels[nSpecies][2] = ' ';
405  chLabels[nSpecies][3] = chToken[cursor++];
406  }
407  chLabels[nSpecies][4] = '\0';
408  ASSERT( chToken[cursor]=='\0' || chToken[cursor]=='d' );
409 
410  // now capitalize the first letter
411  chLabels[nSpecies][0] = toupper( chLabels[nSpecies][0] );
412  ++nSpecies;
413  ++nSpeciesSTOUT;
414  }
415  }
416  while( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) != NULL );
417  fclose(ioMASTERLIST);
418  }
419 
420 
422  //
423  // Read CHIANTI masterlist and VERSION
424  //
426 
427  nSpeciesCHIANTI = 0;
428 
429  if( atmdat.lgChiantiOn )
430  {
431  char chPathSave[FILENAME_PATH_LENGTH_2];
432  strcpy( chPath, "chianti" );
433  strcat( chPath, input.chDelimiter );
434  //Preserve the path /chianti/ with chPathSave
435  //Start reading in the chianti version number
436  strcpy( chPathSave , chPath );
437  strcat(chPath,"VERSION");
438  ioVERSION = open_data(chPath,"r");
439  if( read_whole_line( chLine , (int)sizeof(chLine) , ioVERSION ) == NULL )
440  {
441  fprintf( ioQQQ, " database_readin could not read first line of the Chianti VERSION.\n");
443  }
444  fclose(ioVERSION);
445  // chianti version - string since can contain letters
446  for( i=0; i < atmdat.iVersionLength-1; i++ )
447  {
448  if( isprint(chLine[i]) )
449  atmdat.chVersion[i] = chLine[i];
450  else
451  {
452  atmdat.chVersion[i] = '\0';
453  break;
454  }
455  }
456  // make sure string is null-terminated
458  //Restore the previous chPath
459  strcpy(chPath,chPathSave);
460  // Read in the masterlist
461  strcat( chPath, "masterlist" );
462  strcat( chPath, input.chDelimiter );
463  // save copy
464  strcpy( chPathSave , chPath );
465 
466  // our subset of Chianti
467  strcat( chPath, atmdat.chCloudyChiantiFile );
468 
469  // first try local directory, then data/chianti
470  if( (ioMASTERLIST = open_data( atmdat.chCloudyChiantiFile, "r", AS_LOCAL_ONLY_TRY ) ) == NULL )
471  {
472  ioMASTERLIST = open_data( chPath, "r" );
473  }
474 
475  // magic number
476  if( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) == NULL )
477  {
478  fprintf( ioQQQ, " database_readin could not read first line of CloudyChianti.ini.\n");
480  }
481 
482  bool lgEOL1=true, lgEOL2=true, lgEOL3=true;
483  long int nMonRd=-1, nDayRd=-1;
484  long int ipST = 1;
485  long int nYrRd = (long)FFmtRead(chLine,&ipST,sizeof(chLine),&lgEOL1);
486  if( !lgEOL1 )
487  {
488  nMonRd = (long)FFmtRead(chLine,&ipST,sizeof(chLine),&lgEOL2);
489  if( !lgEOL2 )
490  nDayRd = (long)FFmtRead(chLine,&ipST,sizeof(chLine),&lgEOL3);
491  }
492 
493  /* magic numbers for this version of Chianti masterlist */
494  static long int nYr=11 , nMon = 10, nDay = 3;
495  if( lgEOL3 )
496  {
497  fprintf(ioQQQ,"PROBLEM, there must be three magic numbers on the first line of the chianti masterlist file.\n");
498  fprintf( ioQQQ,
499  " I expected to find the numbers %2.2li %2.2li %2.2li.\n" ,
500  nYr , nMon , nDay );
502  }
503 
504  if( ( nYrRd != nYr ) || ( nMonRd != nMon ) || ( nDayRd != nDay ) )
505  {
506  fprintf( ioQQQ,
507  " database_readin: the Chianti masterlist file is not the current version.\n" );
508  fprintf( ioQQQ,
509  " database_readin obtain the current version from the Cloudy web site.\n" );
510  fprintf( ioQQQ,
511  " I expected to find the number %2.2li %2.2li %2.2li and got %2.2li %2.2li %2.2li instead.\n" ,
512  nYr , nMon , nDay , nYrRd , nMonRd , nDayRd );
513  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
515  }
516 
517  if( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) == NULL )
518  {
519  fprintf( ioQQQ, " database_readin could not read first line of CHIANTI masterlist.\n");
521  }
522 
523  do
524  {
525 
526  if ((chLine[0]!='#') && (chLine[0]!='\n')&&(chLine[0]!='\t')&&(chLine[0]!='\r'))
527  {
528  // break line into two chunks, first with species which can have number number of
529  // characters, followed by optional chunk with limit to number of levels
530  strcpy(chDLine, chLine);
531  chToken = strtok(chDLine," \t\n");
532 
533  fixit("insert logic here to exclude some ions");
534  // (for example, iso sequences)
535  // exclude for now the satellite lines (denoted by a "d" after the label
536  if( chToken[strlen(chToken)-1] != 'd' )
537  {
538  ASSERT( nSpecies + 1 <= MAX_NUM_SPECIES );
539  ASSERT( nSpeciesCHIANTI + 1 <= MAX_NUM_SPECIES );
540  strcpy( chLabels[nSpecies], chToken );
541  strcpy( chLabelsOrig[nSpecies], chLabels[nSpecies]);
542 
543  // second optional token is lower limit to number of levels
544  // first get full string after arbitrary length species name
545  char *chNumLevs = strtok(NULL,"\n");
546  if( chNumLevs != NULL )
547  {
548  long i = 1;
549  bool lgEOL;
550  long numLevs = (long)FFmtRead(chNumLevs,&i,sizeof(chLine),&lgEOL);
551  // was there a lower bound to the number of levels
552  if( !lgEOL )
553  {
554  if( numLevs > 0 )
555  {
556  numLevels[nSpecies] = numLevs;
557  }
558  else
559  {
560  fprintf(ioQQQ,"PROBLEM the limit to the number of levels must be positive, it was %li\n", numLevs);
561  fprintf(ioQQQ,"The species was %s\n",chToken );
562  cdEXIT( EXIT_FAILURE );
563  }
564  }
565  }
566 
567  bool skipSpecies = false;
568 
569  //Check for duplicate species with Stout
570  for( int j = nSpeciesLAMDA; j < (nSpecies - nSpeciesCHIANTI); j++)
571  {
572  if( strcmp( chLabelsOrig[j], chLabelsOrig[nSpecies] ) == 0)
573  {
574  fprintf(ioQQQ,"Skipping the Chianti version of %s, using Stout version\n",chLabels[nSpecies]);
575  skipSpecies = true;
576  break;
577  }
578  }
579  //Check for duplicate species within Chianti masterlist
580  for( int j = nSpecies - nSpeciesCHIANTI; j < nSpecies; j++)
581  {
582  if( strcmp( chLabelsOrig[j], chLabelsOrig[nSpecies] ) == 0)
583  {
584  fprintf(ioQQQ,"%s appears multiple times in %s.\n",chLabels[nSpecies],atmdat.chCloudyChiantiFile);
585  skipSpecies = true;
586  break;
587  }
588  }
589  if( skipSpecies)
590  continue;
591 
592  char *chElement, chTokenTemp[7];
593  strcpy( chTokenTemp, chToken );
594  (void) strtok(chTokenTemp," \n");
595  chElement = strtok(chTokenTemp,"_");
596  uncaps( chElement );
597 
598  // path is, for example, CHIANTI/ar/ar_10/ar_10
599  // we will append extensions later
600  strcpy( chPaths[nSpecies], "chianti" );
601  strcat( chPaths[nSpecies], input.chDelimiter );
602  strcat( chPaths[nSpecies], chElement );
603  strcat( chPaths[nSpecies], input.chDelimiter );
604  strcat( chPaths[nSpecies], chLabels[nSpecies] );
605  strcat( chPaths[nSpecies], input.chDelimiter );
606  strcat( chPaths[nSpecies], chLabels[nSpecies] );
607 
608  ASSERT( isalpha(chToken[0]) );
609  long cursor=0;
610  chLabels[nSpecies][0] = chToken[0];
611  if( isalpha(chToken[1]) )
612  {
613  chLabels[nSpecies][1] = chToken[1];
614  cursor = 2;
615  }
616  else
617  {
618  chLabels[nSpecies][1] = ' ';
619  cursor = 1;
620  }
621 
622  ASSERT( chToken[cursor]=='_' );
623  ++cursor;
624  ASSERT( isdigit(chToken[cursor]) );
625 
626  if( isdigit(chToken[cursor+1]) )
627  {
628  chLabels[nSpecies][2] = chToken[cursor++];
629  chLabels[nSpecies][3] = chToken[cursor++];
630  }
631  else
632  {
633  chLabels[nSpecies][2] = ' ';
634  chLabels[nSpecies][3] = chToken[cursor++];
635  }
636  chLabels[nSpecies][4] = '\0';
637  ASSERT( chToken[cursor]=='\0' || chToken[cursor]=='d' );
638 
639  // now capitalize the first letter
640  chLabels[nSpecies][0] = toupper( chLabels[nSpecies][0] );
641  ++nSpecies;
642  ++nSpeciesCHIANTI;
643  }
644  }
645  }
646  while( read_whole_line( chLine , (int)sizeof(chLine) , ioMASTERLIST ) != NULL );
647 
648  fclose(ioMASTERLIST);
649  }
650 
651  /* no species found, nothing to do */
652  if( nSpecies==0 )
653  return;
654 
655  /*Initialization of the dBaseSpecies Structure*/
656  dBaseSpecies.resize(nSpecies);
657 
658  /*Initialization of the collisional rates array structure*/
659  AtmolCollRateCoeff.reserve( nSpecies );
660  AtmolCollSplines.resize(nSpecies);
661  StoutCollData.resize(nSpecies);
662 
663  /*Mallocing here takes care of the number of colliders*/
664  for( i=0; i<nSpecies; i++ )
665  {
666  AtmolCollRateCoeff.reserve( i, ipNCOLLIDER );
667  }
668  AtmolCollRateCoeff.alloc();
669 
670  // malloc state and transition arrays
671  dBaseStates.resize(nSpecies);
672  ipdBaseTrans.resize(nSpecies);
673 
674  for( i = 0; i < nSpecies; i++ )
675  {
676  dBaseTrans.push_back(TransitionList("dBaseTrans",&dBaseStates[i]));
677  // label should be a minimum of 4 characters long
678  size_t los = strlen(chLabels[i]);
679  ASSERT( los >= 1 && los <= CHARS_SPECIES );
680  dBaseSpecies[i].chLabel = new char[los+1];
681  strcpy(dBaseSpecies[i].chLabel,chLabels[i]);
682  dBaseSpecies[i].chLabel[los]='\0';
683  trimTrailingWhiteSpace( dBaseSpecies[i].chLabel );
684  dBaseSpecies[i].lgActive = true;
685 
686  // was minimum number of levels specified
687  if( numLevels[i] > 0 )
688  {
689  dBaseSpecies[i].numLevels_masterlist = numLevels[i];
690  }
691 
692  /* set type and isotopologue fractions */
694 
695  // set_fractionation trims off "p-","o-", etc. Now have set label. Check size.
696  los = (int)strlen( dBaseSpecies[i].chLabel );
697  ASSERT( los < CHARS_SPECIES );
698 
699  if( i<nSpeciesLAMDA )
700  {
701  // Read in LAMDA data files
702  atmdat_LAMDA_readin( i, chPaths[i] );
703  }
704  else if( i < nSpeciesLAMDA + nSpeciesSTOUT )
705  {
706  // Read in STOUT data files
707  atmdat_STOUT_readin( i, chPaths[i] );
708  }
709  else if( i < nSpeciesLAMDA + nSpeciesSTOUT + nSpeciesCHIANTI )
710  {
711  // Read in CHIANTI data files
712  atmdat_CHIANTI_readin( i, chPaths[i] );
713  }
714  else
715  TotalInsanity();
716  }
717 
718  speciesCheck();
719 
720  states_popfill();
722 
723  for( long i=nSpeciesLAMDA; i<nSpeciesLAMDA+nSpeciesSTOUT; i++ )
724  {
725  strcpy(atmdat.chdBaseSources[dBaseStates[i][0].nelem()-1][dBaseStates[i][0].IonStg()-1],"Stout");
726  atmdat.lgdBaseSourceExists[dBaseStates[i][0].nelem()-1][dBaseStates[i][0].IonStg()-1] = true;
727  }
728  for( long i=nSpeciesLAMDA+nSpeciesSTOUT; i<nSpeciesLAMDA+nSpeciesSTOUT+nSpeciesCHIANTI; i++ )
729  {
730  strcpy(atmdat.chdBaseSources[dBaseStates[i][0].nelem()-1][dBaseStates[i][0].IonStg()-1],"Chianti");
731  atmdat.lgdBaseSourceExists[dBaseStates[i][0].nelem()-1][dBaseStates[i][0].IonStg()-1] = true;
732  }
733 
734  if( save.lgSDSOn )
735  {
736  fprintf(save.ipSDSFile, "##################################################\n");
737  fprintf( save.ipSDSFile,"Atomic model for each species used in this run.\n");
738  fprintf( save.ipSDSFile,"Chianti (C), Stout(S), Iso-sequences (I), old internal treatment( ).\n\n");
739 
740  fprintf( save.ipSDSFile,"Ion");
741  for(int i=0; i<LIMELM; i++)
742  {
743  fprintf( save.ipSDSFile,"%4d",i);
744  }
745  fprintf( save.ipSDSFile,"\n");
746 
747  for( int i=0; i<LIMELM; i++)
748  {
750  for(int j=0; j<i+1; j++)
751  {
752  fprintf( save.ipSDSFile," %c",atmdat.chdBaseSources[i][j][0]);
753  }
754  fprintf( save.ipSDSFile,"\n");
755  }
756  }
757 
758  if( DEBUGSTATE )
759  {
760  fprintf(ioQQQ,"\n\nDEBUG: Below are the contents of chdBaseSources[][]. It should contain a database name for each species.\n");
761  fprintf( ioQQQ,"Ion");
762  for(int i=0; i<LIMELM; i++)
763  {
764  fprintf( ioQQQ,"\t%i",i);
765  }
766  fprintf( ioQQQ,"\n");
767  for( int i = 0; i < LIMELM; i++ )
768  {
770  for( int j = 0; j < LIMELM+1; j++ )
771  {
772  fprintf(ioQQQ,"\t%s",atmdat.chdBaseSources[i][j]);
773  }
774  fprintf(ioQQQ, "\n");
775  }
776  fprintf(ioQQQ,"\n\n");
777  }
778 
779  /*Setting nelem of the states to an arbitrary value*/
780  /*Also trim the highest levels if there are no valid Auls */
781  /*Loop over species*/
782  for( intNoSp=0; intNoSp<nSpecies; intNoSp++ )
783  {
784  database_prep(intNoSp);
785  AllTransitions.push_back(dBaseTrans[intNoSp]);
786  trim_levels(intNoSp);
787  }
788 
789  /*To print the states*/
790  if(DEBUGSTATE)
792  return;
793 }
794 
798 STATIC void trim_levels(long ipSpecies)
799 {
800  DEBUG_ENTRY( "trim_levels()" );
801 
802  bool lgLevelsToTrim = true;
803  double aul;
804  char* spectralLabel = dBaseSpecies[ipSpecies].chLabel;
805  string speciesLabel = dBaseStates[ipSpecies].chLabel();
806 
807  long totalNumLevels = dBaseSpecies[ipSpecies].numLevels_max;
808 
809  while( lgLevelsToTrim )
810  {
811  long ipHi = dBaseSpecies[ipSpecies].numLevels_max-1;
812  lgLevelsToTrim = true;
813 
814  if( dBaseSpecies[ipSpecies].numLevels_max == 0)
815  {
816  fprintf(ioQQQ,"PROBLEM: Spectrum %s (species: %s) has no transition probabilities out of the first %li levels.\n",
817  spectralLabel, speciesLabel.c_str(), totalNumLevels);
818  fprintf(ioQQQ,"Consider allowing Cloudy to use more levels (see Hazy 1 SPECIES STOUT/CHIANTI LEVELS MAX), add more low-level"
819  " transition probabilities, or disable %s in the masterlist.\n\n", spectralLabel);
821  }
822 
823  for( int ipLo = 0; ipLo < ipHi; ipLo++)
824  {
825  TransitionList::iterator tr = dBaseTrans[ipSpecies].begin()+ipdBaseTrans[ipSpecies][ipHi][ipLo];
826  aul = tr->Emis().Aul();
827  if( DEBUGSTATE )
828  {
829  fprintf(ioQQQ,"trim_levels():\t%s\t%i\t%li\t%e\n", spectralLabel, ipLo+1, ipHi+1, aul);
830  }
831 
832  if( aul > atmdat.aulThreshold )
833  {
834  lgLevelsToTrim = false;
835  break;
836  }
837 
838  }
839  if( lgLevelsToTrim )
840  {
841  --dBaseSpecies[ipSpecies].numLevels_max;
842  dBaseSpecies[ipSpecies].numLevels_local = dBaseSpecies[ipSpecies].numLevels_max;
844  {
845  fprintf(ioQQQ,"Spectrum %s (species: %s) trimmed to %li levels (original %li) to have positive Aul.\n",
846  spectralLabel,
847  speciesLabel.c_str(),
848  dBaseSpecies[ipSpecies].numLevels_local,
849  totalNumLevels);
850  }
851  }
852  }
853 }
854 
856 {
857  DEBUG_ENTRY( "set_fractionation()" );
858 
859  char chToken[3];
860 
861  sp->fracIsotopologue = 1.f;
862  //types include "p-", "o-", "e-", and "a-"
863  strncpy( chToken, sp->chLabel, 2 );
864  chToken[2] = '\0';
865  if( strcmp( "p-", chToken )==0 )
866  sp->fracType = 0.25f;
867  else if( strcmp( "o-", chToken )==0 )
868  sp->fracType = 0.75f;
869  else if( strcmp( "e-", chToken )==0 )
870  sp->fracType = 0.5f;
871  else if( strcmp( "a-", chToken )==0 )
872  sp->fracType = 0.5f;
873  else
874  sp->fracType = 1.0f;
875 
876  fixit("what fraction should e-type and a-type Methanol have? Assume 50/50 for now.");
877 
878  // Now scrape the type specifier off the label.
879  if( sp->chLabel[1]=='-')
880  memmove(sp->chLabel,sp->chLabel+2,strlen(sp->chLabel+2)+1);
881 
882  return;
883 }
884 
885 /*This function zeros the population of all states */
887 {
888  DEBUG_ENTRY( "states_popfill()" );
889 
890  for( long i=0; i<nSpecies; i++)
891  {
892  for( long j=0; j<dBaseSpecies[i].numLevels_max; j++)
893  {
894  dBaseStates[i][j].Pop() = 0.;
895  }
896  }
897  return;
898 }
899 
900 void parsespect(char* chLabel, long& nelem, long& IonStg)
901 {
902  DEBUG_ENTRY( "parsespect()" );
903  nelem = -1;
904  IonStg = -1;
905  if ( strlen(chLabel) != 4 ||
906  ! (isalpha(chLabel[0])) ||
907  ! (chLabel[1] == ' ' || isalpha(chLabel[1])) ||
908  ! (chLabel[2] == ' ' || isdigit(chLabel[2])) ||
909  ! (chLabel[3] == ' ' || isdigit(chLabel[3])))
910  {
911  // Invalid spectrum -- return error state
912  return;
913  }
914  char chToken[3];
915  strncpy( chToken, chLabel, 2 );
916  chToken[2] = '\0';
917  for( long ipElement=0; ipElement<LIMELM; ipElement++ )
918  {
919  if( strcmp( elementnames.chElementSym[ipElement], chToken )==0 )
920  {
921  nelem = ipElement;
922  break;
923  }
924  }
925  strncpy( chToken, chLabel + 2, 2 );
926  IonStg = atoi(chToken);
927 }
928 
929 string makeChemical( long nelem, long ion )
930 {
931  DEBUG_ENTRY("makeChemical()");
932 
933  string chLabelChemical = elementnames.chElementSym[nelem];
934  if( elementnames.chElementSym[nelem][1]==' ' )
935  chLabelChemical = elementnames.chElementSym[nelem][0];
936 
937  // size has to be > 20 to prevent warnings about writing into an array that may be too small
938  char chStage[21] = {'\0'};
939  if( ion==1 )
940  chStage[0] = '+';
941  else if( ion>1 )
942  sprintf( chStage, "+%li", ion );
943 
944  return chLabelChemical + chStage;
945 }
946 
947 void makeChemical(char* chLabelChemical, long nelem, long ion)
948 {
949  DEBUG_ENTRY("makeChemical()");
950  string chemLab = makeChemical( nelem, ion );
951  strncpy( chLabelChemical, chemLab.c_str(), size_t(CHARS_SPECIES) );
952 }
953 
954 STATIC void spectral_to_chemical( char *chLabelChemical, char* chLabel, long &nelem, long &IonStg )
955 {
956  DEBUG_ENTRY( "spectral_to_chemical()" );
957 
958  parsespect( chLabel, nelem, IonStg );
959  ASSERT( nelem >= 0 && nelem < LIMELM );
960  ASSERT( IonStg >= 1 && IonStg <= nelem+2 );
961 
962  //Prevent importing of iso-sequences from Chianti
963  if( nelem - (IonStg-1) < NISO )
964  {
965  fprintf(ioQQQ, " PROBLEM: Cannot use Chianti model for %s%li\n",elementnames.chElementSym[nelem],IonStg);
966  fprintf(ioQQQ, " Iso-sequences are handled by our own model.\n");
968  }
969 
970  makeChemical(chLabelChemical, nelem, IonStg-1);
971 
972  return;
973 }
974 
975 void spectral_to_chemical( char *chLabelChemical, char* chLabel )
976 {
977  DEBUG_ENTRY( "spectral_to_chemical()" );
978 
979  long nelem, IonStg;
980  return spectral_to_chemical( chLabelChemical, chLabel, nelem, IonStg );
981 }
982 
983 void chemical_to_spectral( const string chLabelChem, string &chLabelSpec )
984 {
985  DEBUG_ENTRY( "chemical_to_spectral()" );
986 
987  size_t plus_sign_pos = chLabelChem.find_first_of( '+' );
988 
989  if( plus_sign_pos == string::npos )
990  {
991  /* Both 'H' and 'HCl' go through this branch */
992  chLabelSpec = chLabelChem;
993 
994  if( chLabelSpec.length() == 1 )
995  chLabelSpec += " ";
996 
997  if( chLabelSpec.length() == 2 &&
998  isElementSym( chLabelSpec.c_str() ) )
999  {
1000  chLabelSpec += " 1";
1001  }
1002  }
1003  else
1004  {
1005  /* Both 'C+2' and 'LiH+' go through this branch */
1006  string elm = chLabelChem.substr( 0, plus_sign_pos );
1007 
1008  if( elm.length() == 1 )
1009  {
1010  elm += " ";
1011  }
1012 
1013  if( ! isElementSym( elm.c_str() ) )
1014  {
1015  chLabelSpec = chLabelChem;
1016  }
1017  else
1018  {
1019  chLabelSpec = elm;
1020  int ionstg = atoi( chLabelChem.substr( plus_sign_pos+1 ).c_str() );
1021  if( ionstg == 0 )
1022  ionstg = 1;
1023  ionstg++;
1024  if( ionstg < 10 )
1025  chLabelSpec += " ";
1026  stringstream tmp;
1027  tmp << ionstg;
1028  chLabelSpec += tmp.str();
1029  }
1030  }
1031 }
1032 
1033 /*This function fills the nelem and IonStg fields */
1035 {
1036  DEBUG_ENTRY( "states_nelemfill()" );
1037 
1038  for( long i=0; i<nSpecies; i++ )
1039  {
1040  long nelem = 0, IonStg;
1041  char chLabelChemical[CHARS_SPECIES] = "";
1042 
1043  if( dBaseSpecies[i].lgMolecular )
1044  {
1045  fixit("should never be used if lgMolecular");
1046  /* these should never be used if lgMolecular
1047  *set to dangerous values instead of unity. */
1048  nelem = -1;
1049  IonStg = -1;
1050  strcpy( chLabelChemical, dBaseSpecies[i].chLabel );
1051  }
1052  else
1053  {
1054  spectral_to_chemical( chLabelChemical, dBaseSpecies[i].chLabel, nelem, IonStg );
1055  dBaseStates[i].chLabel_set( chLabelChemical );
1056 
1057  dBaseSpecies[i].fmolweight = dense.AtomicWeight[nelem];
1058 
1059  // do not evaluate our cooling if we are using Chianti for this species
1060  if( dBaseSpecies[i].database == "Chianti" )
1061  {
1062  dense.lgIonChiantiOn[nelem][IonStg-1] = true;
1063  }
1064  else if( dBaseSpecies[i].database == "Stout" )
1065  {
1066  dense.lgIonStoutOn[nelem][IonStg-1] = true;
1067  }
1068  else
1069  {
1070  TotalInsanity();
1071  }
1072 
1074  {
1075  // used in cool_dima to indicate whether to include line
1076  // with shorter wl than these databases
1077  dense.maxWN[nelem][IonStg-1] = dBaseSpecies[i].maxWN;
1078  }
1079  else
1080  {
1081  dense.maxWN[nelem][IonStg-1] = 0.;
1082  }
1083 
1084  //Store the value of ipSpecies on C-scale
1085  //nelem(H) = 0 IonStg(H I) = 0
1086  atmdat.ipSpecIon[nelem][IonStg-1] = i;
1087 
1088  dBaseSpecies[i].lgPrtMatrix = false;
1089  if( strncmp( prt.matrix.species, dBaseStates[i].chLabel().c_str(), CHARS_SPECIES ) == 0 )
1090  {
1091  dBaseSpecies[i].lgPrtMatrix = true;
1092  }
1093  }
1094 
1095  molecule *sp = findspecies(chLabelChemical);
1096  if( sp == null_mole )
1097  {
1098  dBaseSpecies[i].index = INT_MAX;
1099  if( nelem >= ipHYDROGEN && dense.lgElmtOn[nelem] )
1100  fprintf(ioQQQ," PROBLEM: could not find species %li - %s\n",i,
1101  chLabelChemical );
1102  }
1103  else
1104  {
1105  dBaseSpecies[i].index = sp->index;
1106  mole.species[ sp->index ].dbase = &dBaseSpecies[i];
1107  mole.species[ sp->index ].levels = &dBaseStates[i];
1108  mole.species[ sp->index ].lines = &dBaseTrans[i];
1109  }
1110 
1111  for( long j=0; j<dBaseSpecies[i].numLevels_max; j++ )
1112  {
1113  dBaseStates[i][j].nelem() = nelem+1;
1114  dBaseStates[i][j].IonStg() = IonStg;
1115  }
1116  }
1117  return;
1118 }
1119 
1120 /*This function prints the various properties of states*/
1122 {
1123  DEBUG_ENTRY( "states_propprint()" );
1124 
1125  for( long i=0; i<nSpecies; i++ )
1126  {
1127  printf("The species is %s \n",dBaseSpecies[i].chLabel);
1128  printf("The data output is in the following format \n");
1129  printf("Label Energy St.wt Pop Lifetime\n");
1130 
1131  for( long j=0; j<dBaseSpecies[i].numLevels_max; j++ )
1132  {
1133  printf("This is the %ld state \n",j);
1134  printf("%s %f %f %f %e \n",dBaseStates[i][j].chLabel().c_str(),
1135  dBaseStates[i][j].energy().WN(),
1136  dBaseStates[i][j].g(),
1137  dBaseStates[i][j].Pop(),
1138  dBaseStates[i][j].lifetime());
1139  }
1140  }
1141  return;
1142 }
1143 
1144 STATIC void database_prep(int intSpIndex)
1145 {
1146  vector<realnum> fsumAs(dBaseSpecies[intSpIndex].numLevels_max,SMALLFLOAT);
1147 
1148  DEBUG_ENTRY( "database_prep()" );
1149 
1150  /*Get the lifetimes*/
1151  for( EmissionList::iterator em = dBaseTrans[intSpIndex].Emis().begin();
1152  em != dBaseTrans[intSpIndex].Emis().end(); ++em)
1153  {
1154  fsumAs[(*em).Tran().ipHi()] += (*em).Aul();
1155 
1156  // set redistribution functions for all lines
1157  if( intSpIndex != atmdat.ipSpecIon[ipIRON][1] )
1158  {
1159  // default for species is partial redisctribution with wings
1160  (*em).iRedisFun() = ipPRD;
1161  }
1162  else
1163  {
1164  // this Fe II is to be the default for cloudy post 2001
1165  if( em->Tran().ipLo() == 0 )
1166  {
1167  // complete redistribution, only core
1168  em->iRedisFun() = ipCRD;
1169  }
1170  else
1171  {
1172  /* >>chng 01 feb 27, had been -1, crd with core only,
1173  * change to complete redistribution with wings as per discussion with Ivan Hubeny */
1174  em->iRedisFun() = ipCRDW;
1175  }
1176  }
1177  }
1178 
1179  dBaseStates[intSpIndex][0].lifetime()= BIGFLOAT;
1180  for( int ipHi=1; ipHi < dBaseSpecies[intSpIndex].numLevels_max; ipHi++ )
1181  {
1182  dBaseStates[intSpIndex][ipHi].lifetime() = 1./fsumAs[ipHi];
1183  }
1184  return;
1185 }
char chLamdaFile[FILENAME_PATH_LENGTH]
Definition: atmdat.h:395
STATIC void database_prep(int)
Definition: species.cpp:1144
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
Definition: cpu.cpp:765
vector< StoutCollArray > StoutCollData
Definition: taulines.cpp:21
t_atmdat atmdat
Definition: atmdat.cpp:6
bool lgStoutHybrid
Definition: atmdat.h:404
molecule * null_mole
const int FILENAME_PATH_LENGTH_2
Definition: cddefines.h:296
char chStoutFile[FILENAME_PATH_LENGTH]
Definition: atmdat.h:408
NORETURN void TotalInsanity(void)
Definition: service.cpp:971
t_input input
Definition: input.cpp:12
bool lgStoutOn
Definition: atmdat.h:402
const realnum SMALLFLOAT
Definition: cpu.h:246
STATIC void set_fractionation(species *sp)
Definition: species.cpp:855
const int NISO
Definition: cddefines.h:311
vector< multi_arr< int, 2 > > ipdBaseTrans
Definition: taulines.cpp:17
void atmdat_STOUT_readin(long intNS, char *chFileName)
bool lgChiantiPrint
Definition: atmdat.h:378
FILE * ipSDSFile
Definition: save.h:459
FILE * ioQQQ
Definition: cddefines.cpp:7
multi_arr< CollRateCoeffArray, 2 > AtmolCollRateCoeff
Definition: taulines.cpp:19
Definition: mole.h:142
long int nSpecies
Definition: taulines.cpp:22
void trimTrailingWhiteSpace(string &str)
Definition: service.cpp:153
STATIC void states_propprint(void)
Definition: species.cpp:1121
t_dense dense
Definition: global.cpp:15
char chVersion[iVersionLength]
Definition: atmdat.h:448
static t_version & Inst()
Definition: cddefines.h:209
STATIC void spectral_to_chemical(char *chLabelChemical, char *chLabel, long &nelem, long &IonStg)
Definition: species.cpp:954
t_elementnames elementnames
Definition: elementnames.cpp:5
bool lgIonStoutOn[LIMELM][LIMELM+1]
Definition: dense.h:143
void uncaps(char *chCard)
Definition: service.cpp:281
char toupper(char c)
Definition: cddefines.h:739
realnum fracIsotopologue
Definition: species.h:60
bool lgIonChiantiOn[LIMELM][LIMELM+1]
Definition: dense.h:140
bool lgdBaseSourceExists[LIMELM][LIMELM+1]
Definition: atmdat.h:452
bool lgChiantiHybrid
Definition: atmdat.h:376
const int ipIRON
Definition: cddefines.h:374
bool lgLamdaPrint
Definition: atmdat.h:393
static const double aulThreshold
Definition: atmdat.h:437
double energy(const genericState &gs)
bool lgChiantiOn
Definition: atmdat.h:374
#define STATIC
Definition: cddefines.h:118
char chdBaseSources[LIMELM][LIMELM+1][10]
Definition: atmdat.h:451
bool lgCalpgmOn
Definition: atmdat.h:419
void chemical_to_spectral(const string chLabelChem, string &chLabelSpec)
Definition: species.cpp:983
char chCloudyChiantiFile[FILENAME_PATH_LENGTH]
Definition: atmdat.h:382
t_mole_local mole
Definition: mole.cpp:8
molecule * findspecies(const char buf[])
const int ipCRD
Definition: cddefines.h:342
valarray< class molezone > species
Definition: mole.h:468
#define EXIT_FAILURE
Definition: cddefines.h:168
realnum fracType
Definition: species.h:58
const realnum BIGFLOAT
Definition: cpu.h:244
char species[CHARS_SPECIES]
Definition: prt.h:116
#define cdEXIT(FAIL)
Definition: cddefines.h:482
int index
Definition: mole.h:194
bool lgSDSOn
Definition: save.h:458
void speciesCheck()
void parsespect(char *chLabel, long &nelem, long &IonStg)
Definition: species.cpp:900
char * chLabel
Definition: species.h:38
STATIC void states_nelemfill(void)
Definition: species.cpp:1034
vector< multi_arr< CollSplinesArray, 3 > > AtmolCollSplines
Definition: taulines.cpp:20
t_prt prt
Definition: prt.cpp:14
bool lgElmtOn[LIMELM]
Definition: dense.h:160
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
Definition: elementnames.h:25
realnum AtomicWeight[LIMELM]
Definition: dense.h:80
string makeChemical(long nelem, long ion)
Definition: species.cpp:929
#define ASSERT(exp)
Definition: cddefines.h:613
STATIC void trim_levels(long)
Definition: species.cpp:798
const int LIMELM
Definition: cddefines.h:308
t_prt_matrix matrix
Definition: prt.h:238
vector< vector< long > > ipSpecIon
Definition: atmdat.h:455
void atmdat_LAMDA_readin(long intNS, char *chFileName)
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:723
char chDelimiter[3]
Definition: input.h:83
#define DEBUGSTATE
Definition: species.cpp:41
STATIC void states_popfill(void)
Definition: species.cpp:886
vector< qList > dBaseStates
Definition: taulines.cpp:16
vector< species > dBaseSpecies
Definition: taulines.cpp:15
void database_readin(void)
Definition: species.cpp:42
bool lgStoutPrint
Definition: atmdat.h:406
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1121
void atmdat_CHIANTI_readin(long intNS, char *chFileName)
const int ipPRD
Definition: cddefines.h:340
double maxWN[LIMELM][LIMELM+1]
Definition: dense.h:146
vector< TransitionList > AllTransitions
Definition: taulines.cpp:9
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
Definition: service.cpp:70
bool isElementSym(const char *chSym)
#define fixit(a)
Definition: cddefines.h:417
bool lgLamdaOn
Definition: atmdat.h:391
vector< TransitionList > dBaseTrans
Definition: taulines.cpp:18
t_save save
Definition: save.cpp:5
const int ipHYDROGEN
Definition: cddefines.h:349
static const int iVersionLength
Definition: atmdat.h:446
const int ipCRDW
Definition: cddefines.h:344
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)
Definition: service.cpp:381