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