41 #define DEBUGSTATE false
46 FILE *ioMASTERLIST, *ioVERSION;
54 const int MAX_NUM_SPECIES = 1000;
60 static int nCalled = 0;
61 long nSpeciesLAMDA, nSpeciesSTOUT, nSpeciesCHIANTI;
89 long numModelsNotUsed = 0;
90 strcpy( chPath,
"lamda" );
92 strcat( chPath,
"masterlist" );
98 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) == NULL )
100 fprintf(
ioQQQ,
" database_readin could not read first line of LAMDA masterlist.\n");
106 if ((chLine[0]!=
'#') && (chLine[0]!=
'\n')&&(chLine[0]!=
'\t')&&(chLine[0]!=
'\r'))
108 strcpy(chDLine, chLine);
109 chToken = strtok(chDLine,
" \t\n");
114 ASSERT( nSpeciesLAMDA + 1 <= MAX_NUM_SPECIES );
116 strcpy( chLabels[
nSpecies], chToken );
120 strcpy( chPaths[nSpecies],
"lamda" );
122 chToken = strtok( NULL,
" \t\n" );
123 strcat( chPaths[nSpecies], chToken );
131 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) != NULL );
137 fclose(ioMASTERLIST);
145 for(
int i=0; i<nSpeciesLAMDA; i++)
166 strcpy( chPath,
"cdms+jpl" );
168 strcat( chPath,
"masterlist" );
172 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) == NULL )
174 fprintf(
ioQQQ,
" database_readin could not read first line of CDMS/JPL masterlist.\n");
180 if ((chLine[0]!=
'#') && (chLine[0]!=
'\n')&&(chLine[0]!=
'\t')&&(chLine[0]!=
'\r'))
182 strcpy(chDLine, chLine);
183 chToken = strtok(chDLine,
" \t\n");
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" );
212 if( strcmp( chToken,
"Si^13CC" ) == 0 )
213 strcpy( chToken,
"SiC^13C" );
218 ASSERT( nSpeciesLAMDA + 1 <= MAX_NUM_SPECIES );
219 strcpy( chLabels[
nSpecies], chToken );
222 strcpy( chPaths[nSpecies],
"cdms+jpl" );
224 chToken = strtok( NULL,
" \t\n" );
225 strcat( chPaths[nSpecies], chToken );
232 fprintf(
ioQQQ,
"Warning: CDMS/JPL species %s not found\n", chToken );
236 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) != NULL );
238 fclose(ioMASTERLIST);
249 vector<long> numLevels(MAX_NUM_SPECIES,0L);
254 strcpy( chPath,
"stout" );
256 strcat( chPath,
"masterlist" );
268 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) == NULL )
270 fprintf(
ioQQQ,
" database_readin could not read first line of stout.ini.\n");
274 bool lgEOL1=
true, lgEOL2=
true, lgEOL3=
true;
275 long int nMonRdST=-1, nDayRdST=-1;
277 long int nYrRdST = (long)
FFmtRead(chLine,&ipST,
sizeof(chLine),&lgEOL1);
280 nMonRdST = (long)
FFmtRead(chLine,&ipST,
sizeof(chLine),&lgEOL2);
282 nDayRdST = (long)
FFmtRead(chLine,&ipST,
sizeof(chLine),&lgEOL3);
286 fprintf(
ioQQQ,
"PROBLEM, there must be three magic numbers on the first line of the stout masterlist file.\n");
290 static long int nYrST =11 , nMonST = 10, nDayST = 25;
291 if( ( nYrRdST != nYrST ) || ( nMonRdST != nMonST ) || ( nDayRdST != nDayST ) )
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 );
299 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) == NULL )
301 fprintf(
ioQQQ,
" database_readin could not read first line of CHIANTI masterlist.\n");
307 strcpy(chDLine, chLine);
312 chToken = strtok(chDLine,
" \t\n");
314 if ((chLine[0]!=
'#') && (chLine[0]!=
'\n')&&(chLine[0]!=
'\t')&&(chLine[0]!=
'\r'))
317 ASSERT( nSpeciesSTOUT + 1 <= MAX_NUM_SPECIES );
320 strcpy( chLabels[
nSpecies], chToken );
321 strcpy( chLabelsOrig[nSpecies], chLabels[nSpecies] );
325 char *chNumLevs = strtok(NULL,
"\n");
326 if( chNumLevs != NULL )
330 long numLevs = (long)
FFmtRead(chNumLevs,&i,
sizeof(chLine),&lgEOL);
340 fprintf(
ioQQQ,
"PROBLEM the limit to the number of levels must be positive, it was %li\n", numLevs);
347 bool skipSpecies =
false;
350 for(
int j = nSpeciesLAMDA; j <
nSpecies; j++)
352 if( strcmp( chLabelsOrig[j], chLabelsOrig[nSpecies] ) == 0)
363 char *chElement, chTokenTemp[7];
364 strcpy( chTokenTemp, chToken );
365 (void) strtok(chTokenTemp,
" \n");
366 chElement = strtok(chTokenTemp,
"_");
371 strcpy( chPaths[nSpecies],
"stout" );
373 strcat( chPaths[nSpecies], chElement );
375 strcat( chPaths[nSpecies], chLabels[nSpecies] );
377 strcat( chPaths[nSpecies], chLabels[nSpecies] );
379 ASSERT( isalpha(chToken[0]) );
382 if( isalpha(chToken[1]) )
393 ASSERT( chToken[cursor]==
'_' );
395 ASSERT( isdigit(chToken[cursor]) );
397 if( isdigit(chToken[cursor+1]) )
399 chLabels[
nSpecies][2] = chToken[cursor++];
400 chLabels[
nSpecies][3] = chToken[cursor++];
405 chLabels[
nSpecies][3] = chToken[cursor++];
408 ASSERT( chToken[cursor]==
'\0' || chToken[cursor]==
'd' );
416 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) != NULL );
417 fclose(ioMASTERLIST);
432 strcpy( chPath,
"chianti" );
436 strcpy( chPathSave , chPath );
437 strcat(chPath,
"VERSION");
439 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioVERSION ) == NULL )
441 fprintf(
ioQQQ,
" database_readin could not read first line of the Chianti VERSION.\n");
448 if( isprint(chLine[i]) )
459 strcpy(chPath,chPathSave);
461 strcat( chPath,
"masterlist" );
464 strcpy( chPathSave , chPath );
476 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) == NULL )
478 fprintf(
ioQQQ,
" database_readin could not read first line of CloudyChianti.ini.\n");
482 bool lgEOL1=
true, lgEOL2=
true, lgEOL3=
true;
483 long int nMonRd=-1, nDayRd=-1;
485 long int nYrRd = (long)
FFmtRead(chLine,&ipST,
sizeof(chLine),&lgEOL1);
488 nMonRd = (long)
FFmtRead(chLine,&ipST,
sizeof(chLine),&lgEOL2);
490 nDayRd = (long)
FFmtRead(chLine,&ipST,
sizeof(chLine),&lgEOL3);
494 static long int nYr=11 , nMon = 10, nDay = 3;
497 fprintf(
ioQQQ,
"PROBLEM, there must be three magic numbers on the first line of the chianti masterlist file.\n");
499 " I expected to find the numbers %2.2li %2.2li %2.2li.\n" ,
504 if( ( nYrRd != nYr ) || ( nMonRd != nMon ) || ( nDayRd != nDay ) )
507 " database_readin: the Chianti masterlist file is not the current version.\n" );
509 " database_readin obtain the current version from the Cloudy web site.\n" );
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 );
517 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) == NULL )
519 fprintf(
ioQQQ,
" database_readin could not read first line of CHIANTI masterlist.\n");
526 if ((chLine[0]!=
'#') && (chLine[0]!=
'\n')&&(chLine[0]!=
'\t')&&(chLine[0]!=
'\r'))
530 strcpy(chDLine, chLine);
531 chToken = strtok(chDLine,
" \t\n");
533 fixit(
"insert logic here to exclude some ions");
536 if( chToken[strlen(chToken)-1] !=
'd' )
539 ASSERT( nSpeciesCHIANTI + 1 <= MAX_NUM_SPECIES );
540 strcpy( chLabels[
nSpecies], chToken );
541 strcpy( chLabelsOrig[nSpecies], chLabels[nSpecies]);
545 char *chNumLevs = strtok(NULL,
"\n");
546 if( chNumLevs != NULL )
550 long numLevs = (long)
FFmtRead(chNumLevs,&i,
sizeof(chLine),&lgEOL);
560 fprintf(
ioQQQ,
"PROBLEM the limit to the number of levels must be positive, it was %li\n", numLevs);
567 bool skipSpecies =
false;
570 for(
int j = nSpeciesLAMDA; j < (nSpecies - nSpeciesCHIANTI); j++)
572 if( strcmp( chLabelsOrig[j], chLabelsOrig[nSpecies] ) == 0)
574 fprintf(
ioQQQ,
"Skipping the Chianti version of %s, using Stout version\n",chLabels[nSpecies]);
580 for(
int j = nSpecies - nSpeciesCHIANTI; j <
nSpecies; j++)
582 if( strcmp( chLabelsOrig[j], chLabelsOrig[nSpecies] ) == 0)
592 char *chElement, chTokenTemp[7];
593 strcpy( chTokenTemp, chToken );
594 (void) strtok(chTokenTemp,
" \n");
595 chElement = strtok(chTokenTemp,
"_");
600 strcpy( chPaths[nSpecies],
"chianti" );
602 strcat( chPaths[nSpecies], chElement );
604 strcat( chPaths[nSpecies], chLabels[nSpecies] );
606 strcat( chPaths[nSpecies], chLabels[nSpecies] );
608 ASSERT( isalpha(chToken[0]) );
611 if( isalpha(chToken[1]) )
622 ASSERT( chToken[cursor]==
'_' );
624 ASSERT( isdigit(chToken[cursor]) );
626 if( isdigit(chToken[cursor+1]) )
628 chLabels[
nSpecies][2] = chToken[cursor++];
629 chLabels[
nSpecies][3] = chToken[cursor++];
634 chLabels[
nSpecies][3] = chToken[cursor++];
637 ASSERT( chToken[cursor]==
'\0' || chToken[cursor]==
'd' );
646 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioMASTERLIST ) != NULL );
648 fclose(ioMASTERLIST);
678 size_t los = strlen(chLabels[i]);
687 if( numLevels[i] > 0 )
699 if( i<nSpeciesLAMDA )
704 else if( i < nSpeciesLAMDA + nSpeciesSTOUT )
709 else if( i < nSpeciesLAMDA + nSpeciesSTOUT + nSpeciesCHIANTI )
723 for(
long i=nSpeciesLAMDA; i<nSpeciesLAMDA+nSpeciesSTOUT; i++ )
728 for(
long i=nSpeciesLAMDA+nSpeciesSTOUT; i<nSpeciesLAMDA+nSpeciesSTOUT+nSpeciesCHIANTI; i++ )
738 fprintf(
save.
ipSDSFile,
"Chianti (C), Stout(S), Iso-sequences (I), old internal treatment( ).\n\n");
741 for(
int i=0; i<
LIMELM; i++)
747 for(
int i=0; i<
LIMELM; i++)
750 for(
int j=0; j<i+1; j++)
760 fprintf(
ioQQQ,
"\n\nDEBUG: Below are the contents of chdBaseSources[][]. It should contain a database name for each species.\n");
762 for(
int i=0; i<
LIMELM; i++)
767 for(
int i = 0; i <
LIMELM; i++ )
770 for(
int j = 0; j < LIMELM+1; j++ )
782 for( intNoSp=0; intNoSp<
nSpecies; intNoSp++ )
802 bool lgLevelsToTrim =
true;
805 string speciesLabel =
dBaseStates[ipSpecies].chLabel();
807 long totalNumLevels =
dBaseSpecies[ipSpecies].numLevels_max;
809 while( lgLevelsToTrim )
812 lgLevelsToTrim =
true;
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);
823 for(
int ipLo = 0; ipLo < ipHi; ipLo++)
826 aul = tr->Emis().Aul();
829 fprintf(
ioQQQ,
"trim_levels():\t%s\t%i\t%li\t%e\n", spectralLabel, ipLo+1, ipHi+1, aul);
834 lgLevelsToTrim =
false;
845 fprintf(
ioQQQ,
"Spectrum %s (species: %s) trimmed to %li levels (original %li) to have positive Aul.\n",
847 speciesLabel.c_str(),
863 strncpy( chToken, sp->
chLabel, 2 );
865 if( strcmp(
"p-", chToken )==0 )
867 else if( strcmp(
"o-", chToken )==0 )
869 else if( strcmp(
"e-", chToken )==0 )
871 else if( strcmp(
"a-", chToken )==0 )
876 fixit(
"what fraction should e-type and a-type Methanol have? Assume 50/50 for now.");
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])))
915 strncpy( chToken, chLabel, 2 );
917 for(
long ipElement=0; ipElement<
LIMELM; ipElement++ )
925 strncpy( chToken, chLabel + 2, 2 );
926 IonStg = atoi(chToken);
938 char chStage[21] = {
'\0'};
942 sprintf( chStage,
"+%li", ion );
944 return chLabelChemical + chStage;
951 strncpy( chLabelChemical, chemLab.c_str(), size_t(
CHARS_SPECIES) );
960 ASSERT( IonStg >= 1 && IonStg <= nelem+2 );
963 if( nelem - (IonStg-1) <
NISO )
966 fprintf(
ioQQQ,
" Iso-sequences are handled by our own model.\n");
987 size_t plus_sign_pos = chLabelChem.find_first_of(
'+' );
989 if( plus_sign_pos == string::npos )
992 chLabelSpec = chLabelChem;
994 if( chLabelSpec.length() == 1 )
997 if( chLabelSpec.length() == 2 &&
1000 chLabelSpec +=
" 1";
1006 string elm = chLabelChem.substr( 0, plus_sign_pos );
1008 if( elm.length() == 1 )
1015 chLabelSpec = chLabelChem;
1020 int ionstg = atoi( chLabelChem.substr( plus_sign_pos+1 ).c_str() );
1028 chLabelSpec += tmp.str();
1040 long nelem = 0, IonStg;
1045 fixit(
"should never be used if lgMolecular");
1100 fprintf(
ioQQQ,
" PROBLEM: could not find species %li - %s\n",i,
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");
1133 printf(
"This is the %ld state \n",j);
1134 printf(
"%s %f %f %f %e \n",
dBaseStates[i][j].chLabel().c_str(),
1152 em !=
dBaseTrans[intSpIndex].Emis().end(); ++em)
1154 fsumAs[(*em).Tran().ipHi()] += (*em).Aul();
1160 (*em).iRedisFun() =
ipPRD;
1165 if( em->Tran().ipLo() == 0 )
1168 em->iRedisFun() =
ipCRD;
1174 em->iRedisFun() =
ipCRDW;
1180 for(
int ipHi=1; ipHi <
dBaseSpecies[intSpIndex].numLevels_max; ipHi++ )
1182 dBaseStates[intSpIndex][ipHi].lifetime() = 1./fsumAs[ipHi];
char chLamdaFile[FILENAME_PATH_LENGTH]
STATIC void database_prep(int)
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
vector< StoutCollArray > StoutCollData
const int FILENAME_PATH_LENGTH_2
char chStoutFile[FILENAME_PATH_LENGTH]
NORETURN void TotalInsanity(void)
STATIC void set_fractionation(species *sp)
vector< multi_arr< int, 2 > > ipdBaseTrans
void atmdat_STOUT_readin(long intNS, char *chFileName)
multi_arr< CollRateCoeffArray, 2 > AtmolCollRateCoeff
void trimTrailingWhiteSpace(string &str)
STATIC void states_propprint(void)
char chVersion[iVersionLength]
static t_version & Inst()
STATIC void spectral_to_chemical(char *chLabelChemical, char *chLabel, long &nelem, long &IonStg)
t_elementnames elementnames
bool lgIonStoutOn[LIMELM][LIMELM+1]
void uncaps(char *chCard)
bool lgIonChiantiOn[LIMELM][LIMELM+1]
bool lgdBaseSourceExists[LIMELM][LIMELM+1]
static const double aulThreshold
double energy(const genericState &gs)
char chdBaseSources[LIMELM][LIMELM+1][10]
void chemical_to_spectral(const string chLabelChem, string &chLabelSpec)
char chCloudyChiantiFile[FILENAME_PATH_LENGTH]
molecule * findspecies(const char buf[])
valarray< class molezone > species
char species[CHARS_SPECIES]
void parsespect(char *chLabel, long &nelem, long &IonStg)
STATIC void states_nelemfill(void)
vector< multi_arr< CollSplinesArray, 3 > > AtmolCollSplines
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
realnum AtomicWeight[LIMELM]
string makeChemical(long nelem, long ion)
STATIC void trim_levels(long)
vector< vector< long > > ipSpecIon
void atmdat_LAMDA_readin(long intNS, char *chFileName)
#define DEBUG_ENTRY(funcname)
STATIC void states_popfill(void)
vector< qList > dBaseStates
vector< species > dBaseSpecies
void database_readin(void)
int fprintf(const Output &stream, const char *format,...)
void atmdat_CHIANTI_readin(long intNS, char *chFileName)
double maxWN[LIMELM][LIMELM+1]
vector< TransitionList > AllTransitions
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
bool isElementSym(const char *chSym)
vector< TransitionList > dBaseTrans
static const int iVersionLength
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)