20 static void AulTTError(
const char chFilename[],
const char chLine[],
const char TT[] )
24 fprintf(
ioQQQ,
" PROBLEM File %s contains an invalid line.\n",chFilename);
25 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
26 fprintf(
ioQQQ,
" This transition already has an Aul value set for %s.\n",TT);
45 static const int MAX_NUM_LEVELS = 999;
50 strcpy( chNRGFilename , chPrefix );
51 strcpy( chTPFilename , chPrefix );
52 strcpy( chCOLLFilename , chPrefix );
55 strcat( chNRGFilename ,
".nrg");
60 fprintf(
ioQQQ,
" atmdat_STOUT_readin opening %s:",chNRGFilename);
72 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not read first line of %s.\n", chNRGFilename );
76 const long int iyr = 11, imo=10 , idy = 14;
77 long iyrread, imoread , idyread;
78 iyrread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
79 imoread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
80 idyread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
82 if(( iyrread != iyr ) ||
87 " PROBLEM atmdat_STOUT_readin: the version of %s is not the current version.\n", chNRGFilename );
89 " atmdat_STOUT_readin: I expected the magic numbers %li %li %li but found %li %li %li.\n",
90 iyr, imo , idy ,iyrread, imoread , idyread );
96 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioDATA ) != NULL )
99 if( chLine[0] !=
'#' && chLine[0] !=
'\n' && chLine[0] !=
'*' )
102 long n = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
107 else if( (chLine[0] ==
'*' && chLine[1] ==
'*' ) )
115 if( fseek( ioDATA , 0 , SEEK_SET ) != 0 )
117 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not rewind %s.\n", chNRGFilename );
123 long HighestIndexInFile = nMolLevs;
140 long numMasterlist =
MIN2(
dBaseSpecies[intNS].numLevels_masterlist , HighestIndexInFile );
141 nMolLevs =
MAX2(nMolLevs,numMasterlist);
149 fprintf(
ioQQQ,
"Using STOUT spectrum %s (species: %s) with %li requested, only %li energy levels available.\n",
151 nMolLevs = HighestIndexInFile;
163 fprintf(
ioQQQ,
"Using STOUT spectrum %s (species: %s) with %li levels of %li available.\n",
164 dBaseSpecies[intNS].chLabel, chLabelChemical, nMolLevs, HighestIndexInFile );
177 for(
long ipHi = 1; ipHi < nMolLevs; ipHi++)
188 for(
long ipHi = 1; ipHi < nMolLevs; ipHi++)
190 for(
long ipLo = 0; ipLo < ipHi; ipLo++)
204 vector<double> dBaseStatesStwt(HighestIndexInFile,-1.0);
205 for(
long ii = 0; ii < HighestIndexInFile; ii++ )
207 dBaseStatesEnergy.push_back(make_pair(-1.0,ii));
214 fprintf(
ioQQQ,
"Number of Energy Levels in File: %li\n",HighestIndexInFile);
215 fprintf(
ioQQQ,
"Number of Energy Levels Cloudy is Currently Using: %li\n",nMolLevs);
216 fprintf(
ioQQQ,
"Species|File Index|Energy(WN)|StatWT\n");
220 bool lgSentinelReached =
false;
225 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not read first line of the energy level file.\n");
234 if( chLine[0] ==
'*' )
236 lgSentinelReached =
true;
240 if( chLine[0] !=
'#' )
243 if( chLine[0] ==
'\n')
246 index = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL) -1 ;
254 fprintf(
ioQQQ,
" PROBLEM An energy level index was less than 1 in file %s\n",chNRGFilename);
255 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
259 nrg = (double)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
260 stwt = (double)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
268 fprintf(
ioQQQ,
" PROBLEM End of line reached prematurely in file %s\n",chNRGFilename);
269 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
274 if( dBaseStatesEnergy.at(index).first == -1. && dBaseStatesStwt.at(index) == -1 )
276 dBaseStatesEnergy.at(index) = make_pair(nrg,index);
277 dBaseStatesStwt.at(index) = stwt;
281 fprintf(
ioQQQ,
" PROBLEM Duplicate energy level index in file %s\n",chNRGFilename);
282 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
287 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioDATA ) != NULL );
288 if( !lgSentinelReached )
290 fprintf(
ioQQQ,
" PROBLEM End of data sentinel was not reached in file %s\n",chNRGFilename);
291 fprintf(
ioQQQ,
" Check that stars (*****) appear after the last line of data and start in the first column of that line.\n");
297 sort(dBaseStatesEnergy.begin(),dBaseStatesEnergy.end());
299 std::vector<long> indexold2new(dBaseStatesEnergy.size());
300 for( DoubleLongPairVector::const_iterator i = dBaseStatesEnergy.begin(); i != dBaseStatesEnergy.end(); i++ )
302 indexold2new[i->second] = i-dBaseStatesEnergy.begin();
308 fprintf(
ioQQQ,
"\n\n***Energy levels have been sorted in order of increasing energy.***\n");
309 fprintf(
ioQQQ,
"Species|File Index|Sorted Index|Energy(WN)|StatWT\n");
313 for(DoubleLongPairVector::iterator i=dBaseStatesEnergy.begin();i!=dBaseStatesEnergy.end();i++)
315 long oldindex = i->second;
316 long index = i - dBaseStatesEnergy.begin();
317 double nrg = i->first;
318 double stwt = dBaseStatesStwt.at(oldindex);
320 if( index >= nMolLevs )
328 dBaseStates[intNS][index].energy().set(nrg,
"cm^-1");
334 double fenergyWN = 0.;
338 int ipHi = (*tr).ipHi();
339 int ipLo = (*tr).ipLo();
344 long ipLoFile = dBaseStatesEnergy[ipLo].second;
345 long ipHiFile = dBaseStatesEnergy[ipHi].second;
350 if( fenergyWN == 0. &&
dBaseStates[intNS][ipHi].g() !=
dBaseStates[intNS][ipLo].g() && abs(ipHiFile - ipLoFile) == 1)
356 fprintf(
ioQQQ,
"\nCaution: A %s transition between adjacent energy levels has zero energy.\n",
dBaseSpecies[intNS].chLabel);
357 fprintf(
ioQQQ,
"The levels may have been sorted by energy since being read from the data files.\n");
358 fprintf(
ioQQQ,
"The sorted lower and upper levels are %i and %i.\n",ipLo+1,ipHi+1);
359 fprintf(
ioQQQ,
"The level indices as they appear in the Stout energy level data file, %s, are %li and %li.\n",chNRGFilename,ipLoFile+1,ipHiFile+1);
360 fprintf(
ioQQQ,
"Verify with the data source that the correct energies are listed in the Stout data file.\n");
366 fprintf(
ioQQQ,
"The levels may have been sorted by energy since being read from the data files.\n");
367 fprintf(
ioQQQ,
"The sorted lower and upper levels are %i and %i.\n",ipLo+1,ipHi+1);
368 fprintf(
ioQQQ,
"The level indices as they appear in the Stout energy level data file, %s, are %li and %li.\n",chNRGFilename,ipLoFile+1,ipHiFile+1);
369 fprintf(
ioQQQ,
"Check the data file for missing or duplicate energies.\n");
375 (*tr).WLAng() = (
realnum)(1e+8/(*tr).EnergyWN()/
RefIndex((*tr).EnergyWN()));
382 strcat( chTPFilename ,
".tp");
390 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not read first line of %s.\n", chTPFilename );
394 iyrread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
395 imoread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
396 idyread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
398 if(( iyrread != iyr ) ||
399 ( imoread != imo ) ||
403 " PROBLEM atmdat_STOUT_readin: the version of %s is not the current version.\n", chTPFilename );
405 " atmdat_STOUT_readin: I expected the magic numbers %li %li %li but found %li %li %li.\n",
406 iyr, imo , idy ,iyrread, imoread , idyread );
412 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioDATA ) != NULL )
415 if( chLine[0] !=
'#' && chLine[0] !=
'\n' && chLine[0] !=
'*' )
418 long n = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
423 else if( (chLine[0] ==
'*' && chLine[1] ==
'*' ) )
430 if( fseek( ioDATA , 0 , SEEK_SET ) != 0 )
432 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not rewind %s.\n", chTPFilename );
442 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not read first line of the transition probability file.\n");
447 lgSentinelReached =
false;
448 static const int intNumCols = 6;
463 bool ***lgLineStrengthTT;
464 lgLineStrengthTT = (
bool ***)
MALLOC(nMolLevs *
sizeof(
bool**));
465 for(
int ii = 0; ii < nMolLevs; ii++ )
467 lgLineStrengthTT[ii] = (
bool **)
MALLOC(nMolLevs *
sizeof(
bool*));
468 for(
int j = 0; j < nMolLevs; j++ )
470 lgLineStrengthTT[ii][j] = (
bool *)
MALLOC(intNumCols *
sizeof(
bool));
475 for(
int ii = 0; ii < nMolLevs; ii++ )
477 for(
int j = 0; j < nMolLevs; j++ )
479 for(
int k = 0; k < intNumCols; k++ )
481 lgLineStrengthTT[ii][j][k] =
false;
489 fprintf(
ioQQQ,
"Radiative Data File: %s\n",chTPFilename);
490 fprintf(
ioQQQ,
"Species|File Index (Lo:Hi)|Cloudy Index (Lo:Hi)|Data Type (A,G,S)|Data\n");
496 if( chLine[0] ==
'*' )
498 lgSentinelReached =
true;
503 if( chLine[0] !=
'#' )
506 if( chLine[0] ==
'\n')
516 long ipLoInFile = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
517 long ipHiInFile = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
518 long ipLo = ipLoInFile - 1;
519 long ipHi = ipHiInFile - 1;
520 tpData = (double)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
529 if (ipHi >=
long(indexold2new.size()))
533 ipLo = indexold2new[ipLo];
534 ipHi = indexold2new[ipHi];
536 if( ipLo < 0 || ipLo >= nMolLevs || ipHi < 0 || ipHi >= nMolLevs )
556 ipLo+1,ipHi+1,chLine[0],tpData);
561 fprintf(
ioQQQ,
" PROBLEM End of line reached prematurely in file %s\n",chTPFilename);
562 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
570 if( !(*tr).hasEmis() )
572 (*tr).AddLine2Stack();
573 (*tr).Emis().Aul() = 0.;
574 (*tr).Emis().gf() = 0.;
582 (*tr).Emis().Aul() += tpData;
584 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
588 else if(
nMatch(
"G",chLine) )
592 (*tr).Emis().gf() += tpData;
594 (*tr).Emis().Aul() = (
realnum)
eina((*tr).Emis().gf(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
597 else if(
nMatch(
"S",chLine) )
599 static const double BOHR_MAGNETON = ELEM_CHARGE_ESU*H_BAR/2/ELECTRON_MASS/SPEEDLIGHT;
605 if( lgLineStrengthTT[ipLo][ipHi][0] )
612 static const double E1Coeff = 64*
powi(PI,4)*pow(ELEM_CHARGE_ESU,2)*
pow2(BOHR_RADIUS_CM)/3/HPLANCK/
pow3(1e-8);
615 (*tr).Emis().Aul() += E1Coeff*tpData/(*(*tr).Hi()).g()/
pow3((*tr).EnergyAng());
616 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
617 lgLineStrengthTT[ipLo][ipHi][0]=
true;
619 else if(
nMatch(
"E2",chLine) )
621 if( lgLineStrengthTT[ipLo][ipHi][1] )
628 static const double E2Coeff = 64*
powi(PI,6)*
pow2(ELEM_CHARGE_ESU)*
pow4(BOHR_RADIUS_CM)/15/HPLANCK/
powi(1e-8,5);
631 (*tr).Emis().Aul() += E2Coeff*tpData/(*(*tr).Hi()).g()/
powi((*tr).EnergyAng(),5);
632 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
633 lgLineStrengthTT[ipLo][ipHi][1]=
true;
635 else if(
nMatch(
"E3",chLine) )
637 if( lgLineStrengthTT[ipLo][ipHi][2] )
644 static const double E3Coeff = 2048*
powi(PI,8)*
pow2(ELEM_CHARGE_ESU)*
powi(BOHR_RADIUS_CM,6)/4725/HPLANCK/
powi(1e-8,7);
649 (*tr).Emis().Aul() += E3Coeff*tpData/(*(*tr).Hi()).g()/
powi((*tr).EnergyAng(),7);
650 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
651 lgLineStrengthTT[ipLo][ipHi][2]=
true;
653 else if(
nMatch(
"M1",chLine) )
655 if( lgLineStrengthTT[ipLo][ipHi][3] )
662 static const double M1Coeff = 64*
powi(PI,4)*
pow2(BOHR_MAGNETON)/3/HPLANCK/
pow3(1e-8);
665 (*tr).Emis().Aul() += M1Coeff*tpData/(*(*tr).Hi()).g()/
pow3((*tr).EnergyAng());
666 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
667 lgLineStrengthTT[ipLo][ipHi][3]=
true;
669 else if(
nMatch(
"M2",chLine) )
671 if( lgLineStrengthTT[ipLo][ipHi][4] )
678 static const double M2Coeff = 64*
powi(PI,6)*
pow2(BOHR_MAGNETON)*
pow2(BOHR_RADIUS_CM)/15/HPLANCK/
powi(1e-8,5);
683 (*tr).Emis().Aul() += M2Coeff*tpData/(*(*tr).Hi()).g()/
powi((*tr).EnergyAng(),5);
684 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
685 lgLineStrengthTT[ipLo][ipHi][4]=
true;
687 else if(
nMatch(
"M3",chLine) )
689 if( lgLineStrengthTT[ipLo][ipHi][5] )
696 static const double M3Coeff = 2048*
powi(PI,8)*
pow2(BOHR_MAGNETON)*
pow4(BOHR_RADIUS_CM)/4725/HPLANCK/
powi(1e-8,7);
701 (*tr).Emis().Aul() += M3Coeff*tpData/(*(*tr).Hi()).g()/
powi((*tr).EnergyAng(),7);
702 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
703 lgLineStrengthTT[ipLo][ipHi][5]=
true;
707 fprintf(
ioQQQ,
" PROBLEM File %s contains an invalid line.\n",chTPFilename);
708 fprintf(
ioQQQ,
" The line strength does not list a valid transition type.\n");
709 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
724 fprintf(
ioQQQ,
" PROBLEM File %s contains an invalid line.\n",chTPFilename);
725 fprintf(
ioQQQ,
" Data must either be in the form of Aul, gf, or S(line strength) and list"
726 " the data type in the first colum as A, G, or S respectively.");
727 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
732 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioDATA ) != NULL );
733 if( !lgSentinelReached )
735 fprintf(
ioQQQ,
" PROBLEM End of data sentinel was not reached in file %s\n",chTPFilename);
736 fprintf(
ioQQQ,
" Check that stars (*****) appear after the last line of data and start in the first column of that line.");
745 strcat( chCOLLFilename ,
".coll");
748 ioDATA =
open_data( chCOLLFilename,
"r" );
753 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not read first line of %s.\n", chCOLLFilename );
757 iyrread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
758 imoread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
759 idyread = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
761 if(( iyrread != iyr ) ||
762 ( imoread != imo ) ||
766 " PROBLEM atmdat_STOUT_readin: the version of %s is not the current version.\n", chCOLLFilename );
768 " atmdat_STOUT_readin: I expected the magic numbers %li %li %li but found %li %li %li.\n",
769 iyr, imo , idy ,iyrread, imoread , idyread );
779 fprintf(
ioQQQ,
" atmdat_STOUT_readin could not read first line of the collision data file.\n");
785 for(
long ipHi=0; ipHi<nMolLevs; ipHi++ )
787 for(
long ipLo=0; ipLo<nMolLevs; ipLo++ )
798 vector<double> temps;
799 long ipCollider = -1;
800 lgSentinelReached =
false;
805 fprintf(
ioQQQ,
"Collision Data File: %s\n",chCOLLFilename);
807 fprintf(
ioQQQ,
"Species|Data Type (CS,RATE)|Collider|File Index (Lo:Hi)|Cloudy Index (Lo:Hi)|Data\n");
814 if( chLine[0] ==
'*' )
816 lgSentinelReached =
true;
821 if( chLine[0] !=
'#' )
826 if( chLine[0] ==
'\n')
833 if(
nMatch(
"TEMP",chLine) )
846 FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
853 temps.resize(numpoints);
854 for(
int j = 0; j < numpoints; j++ )
860 for(
int j = 0; j < numpoints; j++ )
862 temps[j] = (double)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
879 if(
nMatch(
"RATE", chLine) )
882 if(
nMatch(
"ELECTRON",chLine ) )
886 else if(
nMatch(
"PROTON",chLine ) ||
nMatch(
"H+",chLine ) )
890 else if(
nMatch(
"HE+2", chLine ) )
894 (void)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
896 else if(
nMatch(
"HE+ ",chLine ) ||
nMatch(
"HE+\t", chLine) )
900 else if(
nMatch(
"H2 ",chLine ) ||
nMatch(
"H2\t",chLine ) )
903 (void)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
905 if(
nMatch(
"ORTHO",chLine ) )
909 else if(
nMatch(
"PARA",chLine ) )
918 else if(
nMatch(
"HE ",chLine ) ||
nMatch(
"HE\t",chLine ) )
922 else if(
nMatch(
"H ",chLine ) ||
nMatch(
"H\t",chLine ) )
928 fprintf(
ioQQQ,
" PROBLEM atmdat_STOUT_readin: Each line of the collision data"
929 "file must specify the collider.\n");
930 fprintf(
ioQQQ,
" Possible colliders are: ELECTRON, PROTON, HE, H,"
931 " HE+2, HE+, H2, H2 ORTHO, H2 PARA\n");
937 fprintf(
ioQQQ,
" PROBLEM atmdat_STOUT_readin: The collision "
938 "file must specify temperatures before the collision strengths");
942 long ipLoInFile = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
943 long ipHiInFile = (long)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
944 long ipLo = ipLoInFile-1;
945 long ipHi = ipHiInFile-1;
948 if (ipHi >=
long(indexold2new.size()))
952 ipLo = indexold2new[ipLo];
953 ipHi = indexold2new[ipHi];
955 if( ipLo < 0 || ipLo >= nMolLevs || ipHi < 0 || ipHi >= nMolLevs )
974 dBaseSpecies[intNS].chLabel,isRate?
"RATE":
"CS",ipCollider,
975 ipLoInFile,ipHiInFile,ipLo+1,ipHi+1);
979 StoutCollData[intNS].lgIsRate(ipHi,ipLo,ipCollider) = isRate;
982 StoutCollData[intNS].setpoints(ipHi,ipLo,ipCollider,numpoints);
985 for(
int j = 0; j < numpoints; j++ )
987 StoutCollData[intNS].temps(ipHi,ipLo,ipCollider)[j] = temps[j];
988 StoutCollData[intNS].collstrs(ipHi,ipLo,ipCollider)[j] = (double)
FFmtRead(chLine,&ipFFmt,
sizeof(chLine),&lgEOL);
993 if(
StoutCollData[intNS].temps(ipHi,ipLo,ipCollider)[j] <= 0 ||
994 StoutCollData[intNS].collstrs(ipHi,ipLo,ipCollider)[j] <= 0 )
996 fprintf(
ioQQQ,
"PROBLEM: A Stout temperature or collision strength is less than or equal to zero.\n");
998 fprintf(
ioQQQ,
"numpoint = %i\tTemp = %e\tCS = %e\n",j,temps[j],
1008 fprintf(
ioQQQ,
" PROBLEM File %s contains an invalid line.\n",chCOLLFilename);
1009 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
1015 fprintf(
ioQQQ,
" PROBLEM End of line reached prematurely in file %s\n",chCOLLFilename);
1016 fprintf(
ioQQQ,
" The line being read is between the braces {%.*s}\n",
int(strlen(chLine)-1),chLine);
1021 while(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioDATA ) != NULL );
1022 if( !lgSentinelReached )
1024 fprintf(
ioQQQ,
" PROBLEM End of data sentinel was not reached in file %s\n",chCOLLFilename);
1025 fprintf(
ioQQQ,
" Check that stars (*****) appear after the last line of data and start in the first column.");
1031 for(
int ii = 0; ii < nMolLevs; ii++ )
1033 for(
int j = 0; j < nMolLevs; j++ )
1035 free( lgLineStrengthTT[ii][j] );
1037 free( lgLineStrengthTT[ii] );
1039 free( lgLineStrengthTT );
1048 int intsplinepts,intTranType,intxs;
1049 long int nMolLevs,nMolExpLevs,nElvlcLines,nTheoLevs;
1050 FILE *ioElecCollData=NULL, *ioProtCollData=NULL;
1051 realnum fstatwt,fenergyWN,fWLAng,fenergy,feinsteina;
1052 double fScalingParam,fEnergyDiff;
1053 const char chCommentChianti =
'#';
1061 bool lgProtonData=
false;
1064 static const int MAX_NUM_LEVELS = 999;
1069 strcpy( chEnFilename , chPrefix );
1070 strcpy( chTraFilename , chPrefix );
1071 strcpy( chEleColFilename , chPrefix );
1072 strcpy( chProColFilename , chPrefix );
1076 strcat( chEnFilename ,
".elvlc");
1081 fprintf(
ioQQQ,
" atmdat_CHIANTI_readin opening %s:",chEnFilename);
1083 fstream elvlcstream;
1087 strcat( chTraFilename ,
".wgfa");
1092 fprintf(
ioQQQ,
" atmdat_CHIANTI_readin opening %s:",chTraFilename);
1098 strcat( chEleColFilename ,
".splups");
1099 uncaps( chEleColFilename );
1103 fprintf(
ioQQQ,
" atmdat_CHIANTI_readin opening %s:",chEleColFilename);
1105 ioElecCollData =
open_data( chEleColFilename,
"r" );
1108 strcat( chProColFilename ,
".psplups");
1109 uncaps( chProColFilename );
1113 fprintf(
ioQQQ,
" atmdat_CHIANTI_readin opening %s:",chProColFilename);
1118 lgProtonData =
true;
1122 lgProtonData =
false;
1127 const int eof_col = 5;
1129 const int lvl_nrg_col=16;
1131 const int lvl_skipto_nrg = 40;
1133 const int lvl_eof_to_nrg = lvl_skipto_nrg - eof_col + 1;
1135 const int lvl_skip_ryd = 15;
1139 if (elvlcstream.is_open())
1142 char otemp[eof_col];
1143 char exptemp[lvl_nrg_col],theotemp[lvl_nrg_col];
1144 double tempexpenergy = 0.,theoenergy = 0.;
1149 elvlcstream.get(otemp,eof_col);
1155 elvlcstream.seekg(lvl_eof_to_nrg,ios::cur);
1156 elvlcstream.get(exptemp,lvl_nrg_col);
1157 tempexpenergy = (double) atof(exptemp);
1158 if( tempexpenergy != 0.)
1161 elvlcstream.seekg(lvl_skip_ryd,ios::cur);
1162 elvlcstream.get(theotemp,lvl_nrg_col);
1163 theoenergy = (double) atof(theotemp);
1164 if( theoenergy != 0. )
1167 elvlcstream.ignore(INT_MAX,
'\n');
1170 elvlcstream.seekg(0,ios::beg);
1175 bool lgChiaBadTheo =
false;
1178 lgChiaBadTheo =
true;
1181 fprintf(
ioQQQ,
"Switching to the experimental levels for this species.");
1184 long HighestIndexInFile = -1;
1189 HighestIndexInFile = nMolExpLevs;
1193 HighestIndexInFile = nElvlcLines;
1196 dBaseSpecies[intNS].numLevels_max = HighestIndexInFile;
1212 fprintf(
ioQQQ,
"The number of energy levels is non-positive in datafile %s.\n", chEnFilename );
1218 long numMasterlist =
MIN2(
dBaseSpecies[intNS].numLevels_masterlist , HighestIndexInFile );
1219 nMolLevs =
MAX2(nMolLevs,numMasterlist);
1223 if (
dBaseSpecies[intNS].setLevels > HighestIndexInFile)
1227 fprintf(
ioQQQ,
"Using CHIANTI spectrum %s (species: %s) with %li requested, only %li energy levels available.\n",
1229 nMolLevs = HighestIndexInFile;
1246 fprintf(
ioQQQ,
"Using CHIANTI spectrum %s (species: %s) with %li experimental energy levels of %li available.\n",
1247 dBaseSpecies[intNS].chLabel, chLabelChemical, nMolLevs , nMolExpLevs );
1253 fprintf(
ioQQQ,
"Using CHIANTI spectrum %s (species: %s) with %li theoretical energy levels of %li available.\n",
1254 dBaseSpecies[intNS].chLabel, chLabelChemical, nMolLevs , nElvlcLines );
1263 for(
long ipHi = 1; ipHi < nMolLevs; ipHi++)
1272 for(
long ipHi = 1; ipHi < nMolLevs; ipHi++)
1274 for(
long ipLo = 0; ipLo < ipHi; ipLo++)
1290 vector<long> intExperIndex(nElvlcLines,-1);
1293 vector<double> dBaseStatesStwt(HighestIndexInFile,-1.0);
1294 for(
long ii = 0; ii < HighestIndexInFile; ii++ )
1296 dBaseStatesEnergy.push_back(make_pair(-1.0,ii));
1300 const int lvl_skipto_statwt = 37;
1302 const int lvl_statwt_col = 4;
1306 for(
long ipLev=0; ipLev<nElvlcLines; ipLev++ )
1308 if(elvlcstream.is_open())
1310 char gtemp[lvl_statwt_col],thtemp[lvl_nrg_col],obtemp[lvl_nrg_col];
1311 elvlcstream.seekg(lvl_skipto_statwt,ios::cur);
1312 elvlcstream.get(gtemp,lvl_statwt_col);
1313 fstatwt = (
realnum)atof(gtemp);
1314 elvlcstream.get(thtemp,lvl_nrg_col);
1315 fenergy = (double) atof(thtemp);
1319 fprintf(
ioQQQ,
" WARNING: A positive non zero value is expected for the "
1320 "statistical weight but was not found in %s"
1321 " level %li\n", chEnFilename,ipLev);
1333 if( fenergy != 0. || ipLev == 0 )
1335 dBaseStatesEnergy.at(ncounter).first = fenergy;
1336 dBaseStatesEnergy.at(ncounter).second = ncounter;
1337 dBaseStatesStwt.at(ncounter) = fstatwt;
1338 intExperIndex.at(ipLev) = ncounter;
1343 intExperIndex.at(ipLev) = -1;
1348 elvlcstream.seekg(lvl_skip_ryd,ios::cur);
1349 elvlcstream.get(obtemp,lvl_nrg_col);
1350 fenergy = (double) atof(obtemp);
1351 if(fenergy != 0. || ipLev == 0)
1353 dBaseStatesEnergy.at(ipLev).first = fenergy;
1354 dBaseStatesEnergy.at(ipLev).second = ipLev;
1355 dBaseStatesStwt.at(ipLev) = fstatwt;
1359 dBaseStatesEnergy.at(ipLev).first = -1.;
1360 dBaseStatesEnergy.at(ipLev).second = ipLev;
1361 dBaseStatesStwt.at(ipLev) = -1.;
1365 elvlcstream.ignore(INT_MAX,
'\n');
1369 fprintf(
ioQQQ,
" The data file %s is corrupted .\n",chEnFilename);
1370 fclose( ioProtCollData );
1375 elvlcstream.close();
1381 for( vector<long>::iterator i = intExperIndex.begin(); i != intExperIndex.end(); i++ )
1384 long iPrt = (i-intExperIndex.begin())+1;
1388 for( DoubleLongPairVector::iterator i=dBaseStatesEnergy.begin(); i != dBaseStatesEnergy.end(); i++ )
1391 long iPrt = (i-dBaseStatesEnergy.begin())+1;
1393 (i->second)+1,i->first,dBaseStatesStwt.at(i->second));
1398 sort(dBaseStatesEnergy.begin(),dBaseStatesEnergy.end());
1400 std::vector<long> indexold2new(dBaseStatesEnergy.size());
1401 for( DoubleLongPairVector::const_iterator i = dBaseStatesEnergy.begin(); i != dBaseStatesEnergy.end(); i++ )
1403 indexold2new[i->second] = i-dBaseStatesEnergy.begin();
1408 for( DoubleLongPairVector::iterator i=dBaseStatesEnergy.begin(); i != dBaseStatesEnergy.end(); i++ )
1411 long iPrt = (i-dBaseStatesEnergy.begin())+1;
1412 if( iPrt > nMolLevs )
1415 (i->second)+1,i->first,dBaseStatesStwt.at(i->second));
1422 fprintf(
ioQQQ,
"Number of Experimental Energy Levels in File: %li\n",nMolExpLevs);
1426 fprintf(
ioQQQ,
"Number of Theoretical Energy Levels in File: %li\n",nElvlcLines);
1428 fprintf(
ioQQQ,
"Number of Energy Levels Cloudy is Currently Using: %li\n",nMolLevs);
1429 fprintf(
ioQQQ,
"Species|File Index|Cloudy Index|StatWT|Energy(WN)\n");
1432 vector<long> revIntExperIndex;
1435 revIntExperIndex.resize(dBaseStatesEnergy.size());
1436 for (
size_t i = 0; i<dBaseStatesEnergy.size(); ++i)
1437 revIntExperIndex[i] = -1;
1438 for ( vector<long>::const_iterator i= intExperIndex.begin();
1439 i != intExperIndex.end(); ++i )
1441 long ipos = intExperIndex[i-intExperIndex.begin()];
1442 if (ipos >= 0 && ipos <
long(dBaseStatesEnergy.size()))
1443 revIntExperIndex[ipos] = i-intExperIndex.begin();
1447 for( DoubleLongPairVector::iterator i=dBaseStatesEnergy.begin(); i != dBaseStatesEnergy.end(); i++ )
1450 long ipLevNew = i - dBaseStatesEnergy.begin();
1451 long ipLevFile = -1;
1453 if( ipLevNew >= nMolLevs )
1458 ipLevFile = revIntExperIndex[ipLevNew];
1462 ipLevFile = i->second;
1470 dBaseStates[intNS][ipLevNew].g() = dBaseStatesStwt.at(i->second);
1471 dBaseStates[intNS][ipLevNew].energy().set(i->first,
"cm^-1");
1486 int ipHi = (*tr).ipHi();
1487 int ipLo = (*tr).ipLo();
1490 (*tr).EnergyWN() = fenergyWN;
1502 if (wgfastream.is_open())
1505 char otemp[eof_col];
1508 wgfastream.get(otemp,eof_col);
1509 wgfastream.ignore(INT_MAX,
'\n');
1510 if( otemp[0] == chCommentChianti )
continue;
1514 wgfastream.seekg(0,ios::beg);
1517 fprintf(
ioQQQ,
" The data file %s is corrupted .\n",chTraFilename);
1522 fprintf(
ioQQQ,
"\n\nTransition Probability File: %s\n",chTraFilename);
1523 fprintf(
ioQQQ,
"Species|File Index (Lo:Hi)|Cloudy Index (Lo:Hi)|Wavelength(A)|Ein A\n");
1528 const int line_index_col = 6;
1530 const int line_nrg_to_eina =15;
1532 const int line_eina_col = 16;
1533 char lvltemp[line_index_col];
1535 if (wgfastream.is_open())
1537 for (
long ii = 0;ii<wgfarows;ii++)
1539 wgfastream.get(lvltemp,line_index_col);
1540 if( lvltemp[0] == chCommentChianti )
1542 wgfastream.ignore(INT_MAX,
'\n');
1546 long ipLoInFile = atoi(lvltemp);
1547 wgfastream.get(lvltemp,line_index_col);
1548 long ipHiInFile = atoi(lvltemp);
1551 long ipLo = ipLoInFile - 1;
1552 long ipHi = ipHiInFile - 1;
1559 if( intExperIndex[ipLo] == -1 || intExperIndex[ipHi] == -1 )
1561 wgfastream.ignore(INT_MAX,
'\n');
1566 ipHi = intExperIndex.at(ipHi);
1567 if (ipHi <
long(indexold2new.size()))
1569 ipHi = indexold2new[ipHi];
1575 ipLo = intExperIndex.at(ipLo);
1576 if (ipLo <
long(indexold2new.size()))
1578 ipLo = indexold2new[ipLo];
1588 long testlo = -1, testhi = -1;
1592 testlo = indexold2new[ipLo];
1593 testhi = indexold2new[ipHi];
1595 catch ( out_of_range& )
1599 fprintf(
ioQQQ,
"NOTE: An out of range exception has occurred"
1600 " reading in data from %s\n",chTraFilename);
1601 fprintf(
ioQQQ,
" The line in the file containing the unidentifiable"
1602 " levels has been ignored.\n");
1604 " This message is just for documentation.\n");
1607 wgfastream.ignore(INT_MAX,
'\n');
1611 if( testlo == -1 || testhi == -1 )
1613 wgfastream.ignore(INT_MAX,
'\n');
1623 if( ipLo >= nMolLevs || ipHi >= nMolLevs )
1626 wgfastream.ignore(INT_MAX,
'\n');
1632 fprintf(
ioQQQ,
" WARNING: Upper level = lower for a radiative transition in %s. Ignoring.\n", chTraFilename );
1633 wgfastream.ignore(INT_MAX,
'\n');
1658 char trantemp[lvl_nrg_col];
1659 wgfastream.get(trantemp,lvl_nrg_col);
1660 fWLAng = (
realnum)atof(trantemp);
1692 wgfastream.seekg(line_nrg_to_eina,ios::cur);
1693 wgfastream.get(trantemp,line_eina_col);
1694 feinsteina = (
realnum)atof(trantemp);
1695 if( feinsteina == 0. )
1697 static bool notPrintedYet =
true;
1700 fprintf(
ioQQQ,
" CAUTION: Radiative rate(s) equal to zero in %s.\n", chTraFilename );
1701 notPrintedYet =
false;
1703 wgfastream.ignore(INT_MAX,
'\n');
1711 fixit(
"may need to do something with these rates");
1713 wgfastream.getline(chLine,INT_MAX);
1715 if(
nMatch(
"auto", chLine) )
1717 if( (*tr).hasEmis() )
1719 (*tr).Emis().AutoIonizFrac() =
1720 feinsteina/((*tr).Emis().Aul() + feinsteina);
1721 ASSERT( (*tr).Emis().AutoIonizFrac() >= 0. );
1722 ASSERT( (*tr).Emis().AutoIonizFrac() <= 1. );
1727 if( (*tr).hasEmis() )
1729 fprintf(
ioQQQ,
" PROBLEM duplicate transition found by atmdat_chianti in %s, "
1730 "wavelength=%f\n", chTraFilename,fWLAng);
1734 (*tr).AddLine2Stack();
1735 (*tr).Emis().Aul() = feinsteina;
1737 fenergyWN = (
realnum)(1e+8/fWLAng);
1741 (*tr).EnergyWN() = fenergyWN;
1743 (*tr).Emis().gf() = (
realnum)
GetGF((*tr).Emis().Aul(), (*tr).EnergyWN(), (*(*tr).Hi()).g());
1748 else fprintf(
ioQQQ,
" The data file %s is corrupted .\n",chTraFilename);
1753 for(
long ipHi=0; ipHi<nMolLevs; ipHi++ )
1756 for(
long ipLo=0; ipLo<nMolLevs; ipLo++ )
1763 for(
long ipHi=0; ipHi<nMolLevs; ipHi++ )
1765 for(
long ipLo=0; ipLo<nMolLevs; ipLo++ )
1785 for(
long ipCollider=0; ipCollider<=1; ipCollider++ )
1791 strcpy( chFilename, chEleColFilename );
1797 strcpy( chFilename, chProColFilename );
1807 fprintf(
ioQQQ,
"\n\nCollision Data File: %s\n",chTraFilename);
1808 fprintf(
ioQQQ,
"Species|File Index (Lo:Hi)|Cloudy Index (Lo:Hi)|Spline Points\n");
1811 fstream splupsstream;
1815 const int cs_eof_col = 4;
1817 const int cs_index_col = 4;
1819 const int cs_trantype_col = 4;
1822 const int cs_values_col = 11;
1824 if (splupsstream.is_open())
1828 long splupslines = -1;
1829 char otemp[cs_eof_col];
1832 splupsstream.get(otemp,cs_eof_col);
1833 splupsstream.ignore(INT_MAX,
'\n');
1837 splupsstream.seekg(0,ios::beg);
1839 for (
int m = 0;m<splupslines;m++)
1843 splupsstream.seekg(6,ios::cur);
1847 splupsstream.get(otemp,cs_index_col);
1848 long ipLo = atoi(otemp)-1;
1849 splupsstream.get(otemp,cs_index_col);
1850 long ipHi = atoi(otemp)-1;
1852 long ipLoFile = ipLo;
1853 long ipHiFile = ipHi;
1860 if( intExperIndex[ipLo] == - 1 || intExperIndex[ipHi] == -1 )
1862 splupsstream.ignore(INT_MAX,
'\n');
1867 ipHi = intExperIndex.at(ipHi);
1868 if (ipHi <
long(indexold2new.size()))
1870 ipHi = indexold2new[ipHi];
1876 ipLo = intExperIndex.at(ipLo);
1877 if (ipLo <
long(indexold2new.size()))
1879 ipLo = indexold2new[ipLo];
1889 long testlo = -1, testhi = -1;
1896 testlo = indexold2new[ipLo];
1897 testhi = indexold2new[ipHi];
1899 catch ( out_of_range& )
1903 fprintf(
ioQQQ,
"NOTE: An out of range exception has occurred"
1904 " reading in data from %s\n",chEleColFilename);
1905 fprintf(
ioQQQ,
" The line in the file containing the unidentifiable"
1906 " levels has been ignored.\n");
1908 " This message is for documentation.\n");
1910 splupsstream.ignore(INT_MAX,
'\n');
1914 if( testlo == -1 || testhi == -1 )
1916 splupsstream.ignore(INT_MAX,
'\n');
1926 if( ipLo >= nMolLevs || ipHi >= nMolLevs )
1929 splupsstream.ignore(INT_MAX,
'\n');
1946 splupsstream.get(otemp,cs_trantype_col);
1947 intTranType = atoi(otemp);
1948 char qtemp[cs_values_col];
1949 splupsstream.get(qtemp,cs_values_col);
1951 splupsstream.get(qtemp,cs_values_col);
1952 fEnergyDiff = atof(qtemp);
1954 splupsstream.get(qtemp,cs_values_col);
1955 fScalingParam = atof(qtemp);
1958 ASSERT( ipLo >= 0 && ipLo < nMolLevs );
1959 ASSERT( ipHi >= 0 && ipHi < nMolLevs );
1963 const int CHIANTI_SPLINE_MAX=9, CHIANTI_SPLINE_MIN=5;
1968 (
double *)
MALLOC((
unsigned long)(CHIANTI_SPLINE_MAX)*
sizeof(
double));
1970 (
double *)
MALLOC((
unsigned long)(CHIANTI_SPLINE_MAX)*
sizeof(
double));
1973 for( intsplinepts=0; intsplinepts<=CHIANTI_SPLINE_MAX; intsplinepts++ )
1976 char p = splupsstream.peek();
1983 if( intsplinepts >= CHIANTI_SPLINE_MAX )
1985 fprintf(
ioQQQ,
" WARNING: More spline points than expected in %s, indices %3li %3li. Ignoring extras.\n", chFilename, ipHi, ipLo );
1988 ASSERT( intsplinepts < CHIANTI_SPLINE_MAX );
1991 splupsstream.get(qtemp,cs_values_col);
1999 if( intTranType < 6 )
2000 temp =
max( temp, 0. );
2001 AtmolCollSplines[intNS][ipHi][ipLo][ipCollider].collspline[intsplinepts] = temp;
2010 ASSERT( intsplinepts > 2 );
2019 AtmolCollSplines[intNS][ipHi][ipLo][ipCollider].ScalingParam = fScalingParam;
2023 vector<double> xs (intsplinepts),
2027 for(intxs=0;intxs<intsplinepts;intxs++)
2029 double coeff = (double)1/(intsplinepts-1);
2030 xs[intxs] = coeff*intxs;
2031 spl[intxs] =
AtmolCollSplines[intNS][ipHi][ipLo][ipCollider].collspline[intxs];
2034 spline(&xs[0], &spl[0],intsplinepts,2e31,2e31,&spl2[0]);
2037 for(
long ii=0; ii<intsplinepts; ii++)
2039 AtmolCollSplines[intNS][ipHi][ipLo][ipCollider].SplineSecDer[ii] = spl2[ii];
2042 splupsstream.ignore(INT_MAX,
'\n');
2044 splupsstream.close();
2049 fclose( ioElecCollData );
2051 fclose( ioProtCollData );
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
vector< StoutCollArray > StoutCollData
static const bool DEBUGSTATE
const int FILENAME_PATH_LENGTH_2
NORETURN void TotalInsanity(void)
double eina(double gf, double enercm, double gup)
long nMatch(const char *chKey, const char *chCard)
vector< pair< double, long > > DoubleLongPairVector
vector< multi_arr< int, 2 > > ipdBaseTrans
void atmdat_STOUT_readin(long intNS, char *chFileName)
double RefIndex(double EnergyWN)
STATIC void spectral_to_chemical(char *chLabelChemical, char *chLabel, long &nelem, long &IonStg)
void uncaps(char *chCard)
void spline(const double x[], const double y[], long int n, double yp1, double ypn, double y2a[])
const ios_base::openmode mode_r
static const double aulThreshold
void swap(count_ptr< T > &a, count_ptr< T > &b)
double energy(const genericState &gs)
static void AulTTError(const char chFilename[], const char chLine[], const char TT[])
void setProperties(species &sp)
double powi(double, long int)
vector< multi_arr< CollSplinesArray, 3 > > AtmolCollSplines
double GetGF(double trans_prob, double enercm, double gup)
string db_comment_tran_levels(long ipLoFile, long ipHiFile)
#define DEBUG_ENTRY(funcname)
vector< qList > dBaseStates
const double ENERGY_MIN_WN
vector< species > dBaseSpecies
int fprintf(const Output &stream, const char *format,...)
void atmdat_CHIANTI_readin(long intNS, char *chFileName)
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
vector< TransitionList > dBaseTrans
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)