Пример #1
0
// calculating the coefficient for utilization of the tonality offset, depending on TMN und NMT
static void
Tonalitaetskoeffizienten ( PsyModel* m )
{
    double                tmp;
    int                   n;
    float                 bass;

	bass = 0.1/8 * m->NMT;
	if ( m->MinValChoice <= 2  &&  bass > 0.1 )
        bass = 0.1f;
	if ( m->MinValChoice <= 1 )
        bass = 0.0f;

    // alternative: calculation of the minval-values dependent on TMN and TMN
    for ( n = 0; n < PART_LONG; n++ ) {
		tmp        = Bass ( (MPC_WL [n] + MPC_WH [n]) / 2048. * m->SampleFreq, m->TMN, m->NMT, bass );
		m->tables.MinVal [n] = POW10 ( -0.1 * tmp );                      // conversion into power
    }

    // calculation of the constants for "tonality offset"
	m->tables.O_MAX = POW10 ( -0.1 * m->TMN );
	m->tables.O_MIN = POW10 ( -0.1 * m->NMT );
	m->tables.FAC1  = POW10 ( -0.1 * (m->NMT - (m->TMN - m->NMT) * 0.229) ) ;
	m->tables.FAC2  = (m->TMN - m->NMT) * (0.99011159 * 0.1);
}
Пример #2
0
void RaiseSMR (PsyModel* m, const int MaxBand, SMRTyp* smr )
{
    float  tmp = POW10 ( 0.1 * m->minSMR );

    RaiseSMR_Signal ( MaxBand, smr->L, tmp );
    RaiseSMR_Signal ( MaxBand, smr->R, tmp );
    RaiseSMR_Signal ( MaxBand, smr->M, tmp );
    RaiseSMR_Signal ( MaxBand, smr->S, 0.5 * tmp );

    return;
}
Пример #3
0
/* ********************************************************************* */
void Make_RateTables(double T, double *krvals)
/*
 *********************************************************************** */
{
  int i, indx_lo, indx_hi;
  double st, t3, tev, lnT, lnTmin, lnTmax, dlnT;
  double scrh, dum_lo, dum_hi;
  double Tmin, Tmax;
  static double *lnTarr, *Rate_arr1, *Rate_arr2, *Rate_arr3, *Rate_arr4;
  static double *Rate_arr5, *Rate_arr6;
  static double *Emiss_arr1, *Emiss_arr2, *Emiss_arr3;
  double Tdust = 15.0;

  Tmin = 1.0e-2;
  Tmax = 1.0e8;
  lnTmin = log10(Tmin);
  lnTmax = log10(Tmax);
  dlnT   = (lnTmax - lnTmin)/((double)TABLE_NPT - 1.0);

  T = MAX(T, Tmin);  /* We constrain local T to lie between [Tmin, Tmax] so */
  T = MIN(T, Tmax);  /* that coefficients will be constant for values of
                        temperature overflow / underflow.  */

  if (lnTarr == NULL){
    lnTarr     = ARRAY_1D(TABLE_NPT, double);
    Rate_arr1  = ARRAY_1D(TABLE_NPT, double);
    Rate_arr2  = ARRAY_1D(TABLE_NPT, double);
    Rate_arr3  = ARRAY_1D(TABLE_NPT, double);
    Rate_arr4  = ARRAY_1D(TABLE_NPT, double);
    Rate_arr5  = ARRAY_1D(TABLE_NPT, double);
    Rate_arr6  = ARRAY_1D(TABLE_NPT, double);
    Emiss_arr1 = ARRAY_1D(TABLE_NPT, double);
    Emiss_arr2 = ARRAY_1D(TABLE_NPT, double);
    Emiss_arr3 = ARRAY_1D(TABLE_NPT, double);
    
    for(i = 0 ; i < TABLE_NPT; i++){
      lnTarr[i] = lnTmin + i*dlnT;
      T     = POW10(lnTarr[i]);
      st    = sqrt(T);
      t3    = T/1.e3;  
      tev   = T*CONST_kB/CONST_eV;
      
      Rate_arr1[i] = 3.e-18*st/(1.0 + 0.04*st + 2.e-3*T + 8.e-6*T*T); /* fa ~ 1 and Tg << T  */
      Rate_arr2[i] = 1.067e-10*pow(tev,2.012)*exp(-(4.463/tev)*pow((1.0 + 0.2472),3.512));
      Rate_arr3[i] = 1.e-8*exp(-84100.0/T); 
      Rate_arr4[i] = 4.4e-10*pow(T,0.35)*exp(-102000.0/T);
      Rate_arr5[i] = 2.6e-11/st;
      Rate_arr6[i] = 1.08e-8*st*exp(-157890.0/T)/(13.6*13.6);
      Emiss_arr1[i] = 6.7e-19*exp(-5.86/t3) + 1.6e-18*exp(-11.7/t3);
      Emiss_arr2[i] = (9.5e-22*pow(t3,3.76)/(1. + 0.12*pow(t3,2.1)))*exp(pow((-0.13/t3),3.0))
	+ 3.0e-24*exp(-0.51/t3); 
      Emiss_arr3[i] = 3.8e-33*st*(T-Tdust)*(1.0 - 0.8*exp(-75.0/T));
    }
  }else{   /* Perform linear interpolation */
Пример #4
0
// calculating the table for loudness calculation based on absLtq = ank
static void
Loudness_Tabelle (PsyModel* m)
{
    int    n;
    float  midfreq;
    float  tmp;

    // ca. dB(A)
    for ( n = 0; n < PART_LONG; n++ ){
		midfreq      = (MPC_WH[n] + MPC_WL[n] + 3) * (0.25 * m->SampleFreq / 512);     // center frequency in kHz, why +3 ???
        tmp          = LOG10 (midfreq) - 3.5f;                                  // dB(A)
        tmp          = -10 * tmp * tmp + 3 - midfreq/3000;
		m->tables.Loudness [n] = POW10 ( 0.1 * tmp );                                     // conversion into power
    }
}
Пример #5
0
// calculation of the spreading function
static void
Spread ( PsyModel* m )
{
    int    i;
    int    j;
    float  tmpx;
    float  tmpy;
    float  tmpz;
    float  x;

    // calculation of the spreading-function for all occuring values
    for ( i = 0; i < PART_LONG; i++ ) {                 // i is masking Partition, Source
        for ( j = 0; j < PART_LONG; j++ ) {             // j is masking Partition, Target
            tmpx = LongPart2Bark (m, j) - LongPart2Bark (m, i);// Difference of the partitions in Bark
            tmpy = tmpz = 0.;                           // tmpz = 0: no dip

            if      ( tmpx < 0 ) {                      // downwards (S1)
                tmpy  = -32.f * tmpx;                   // 32 dB per Bark, e33 (10)
            }
            else if ( tmpx > 0 ) {                      // upwards (S2)
#if 0
                x = (wl[i]+wh[i])/2 * (float)(SampleFreq / 2000)/512;   // center frequency in kHz ???????
                if (i==0) x = 0.5f  * (float)(SampleFreq / 2000)/512;   // if first spectral line
#else
                x  = i  ?  MPC_WL[i]+MPC_WH[i]  :  1;
                x *= m->SampleFreq / 1000. / 2048;         // center frequency in kHz
#endif
                // dB/Bark
                tmpy = (22.f + 0.23f / x) * tmpx;       // e33 (10)

                // dip (up to 6 dB)
                tmpz = 8 * minf ( (tmpx-0.5f) * (tmpx-0.5f) - 2 * (tmpx-0.5f), 0.f );
            }

            // calculate coefficient
			m->tables.SPRD[i][j] = POW10 ( -0.1 * (tmpy+tmpz) );  // [Source] [Target]
        }
    }

    // Normierung e33 (10)
    for ( i = 0; i < PART_LONG; i++ ) {                 // i is masked Partition
        float  norm = 0.f;
        for ( j = 0; j < PART_LONG; j++ )               // j is masking Partition
			norm += m->tables.SPRD [j] [i];
        for ( j = 0; j < PART_LONG; j++ )               // j is masking Partition
			m->tables.SPRD [j] [i] /= norm;
    }
}
Пример #6
0
Файл: kurucz.c Проект: kouui/rh
void readKuruczLines(char *inputFile)
{
  const char routineName[] = "readKuruczLines";
  const double  C = 2.0*PI * (Q_ELECTRON/EPSILON_0) *
                             (Q_ELECTRON/M_ELECTRON) / CLIGHT;

  char   inputLine[RLK_RECORD_LENGTH+1], listName[MAX_LINE_SIZE],
    filename[MAX_LINE_SIZE], Gvalues[18+1], elem_code[7],
         labeli[RLK_LABEL_LENGTH+1], labelj[RLK_LABEL_LENGTH+1],
        *commentChar = COMMENT_CHAR;
  bool_t swap_levels, determined, useBarklem;
  int    Nline, Nread, Nrequired, checkPoint, hfs_i, hfs_j, gL_i, gL_j,
         iso_dl;
  double lambda0, Ji, Jj, Grad, GStark, GvdWaals, pti,
         Ei, Ej, gf, lambda_air;
  RLK_Line *rlk;
  Barklemstruct bs_SP, bs_PD, bs_DF;
  FILE  *fp_Kurucz, *fp_linelist;

  if (!strcmp(inputFile, "none")) return;

  /* --- Read in the data files for Barklem collisional broadening -- */

  readBarklemTable(SP, &bs_SP);
  readBarklemTable(PD, &bs_PD);
  readBarklemTable(DF, &bs_DF);

  labeli[RLK_LABEL_LENGTH] = '\0';
  labelj[RLK_LABEL_LENGTH] = '\0';

  if ((fp_Kurucz = fopen(inputFile, "r")) == NULL) {
    sprintf(messageStr, "Unable to open input file %s", inputFile);
    Error(ERROR_LEVEL_1, routineName, messageStr);
    return;
  }
  /* --- Go through each of the linelist files listed in input file - */

  while (getLine(fp_Kurucz, commentChar, listName, FALSE) != EOF) {
    Nread = sscanf(listName, "%s", filename);
    if ((fp_linelist = fopen(filename, "r")) == NULL) {
      sprintf(messageStr, "Unable to open input file %s", filename);
      Error(ERROR_LEVEL_1, routineName, messageStr);
    }
    /* --- Count the number of lines in this file --   -------------- */

    Nline = 0;
    while (fgets(inputLine, RLK_RECORD_LENGTH+1, fp_linelist) != NULL)
      if (*inputLine != *commentChar) Nline++;
    rewind(fp_linelist);

    if (atmos.Nrlk == 0) atmos.rlk_lines = NULL;
    atmos.rlk_lines = (RLK_Line *)
      realloc(atmos.rlk_lines, (Nline + atmos.Nrlk) * sizeof(RLK_Line));

    /* --- Read lines from file --                     -------------- */

    rlk = atmos.rlk_lines + atmos.Nrlk;
    while (fgets(inputLine, RLK_RECORD_LENGTH+1, fp_linelist) != NULL) {
      if (*inputLine != *commentChar) {

        initRLK(rlk);

	Nread = sscanf(inputLine, "%lf %lf %s %lf",
		       &lambda_air, &gf, (char *) &elem_code, &Ei);

        /* --- Ionization stage and periodic table index -- --------- */

        sscanf(elem_code, "%d.%d", &rlk->pt_index, &rlk->stage);

	Nread += sscanf(inputLine+53, "%lf", &Ej);

	Ei = fabs(Ei) * (HPLANCK * CLIGHT) / CM_TO_M;
	Ej = fabs(Ej) * (HPLANCK * CLIGHT) / CM_TO_M;

	/* --- Beware: the Kurucz linelist has upper and lower levels
	       of a transition in random order. Therefore, we have to
               check for the lowest energy of the two and use that as
               lower level --                          -------------- */

	if (Ej < Ei) {
	  swap_levels = TRUE;
	  rlk->Ei = Ej;
	  rlk->Ej = Ei;
	  strncpy(labeli, inputLine+69, RLK_LABEL_LENGTH);
	  strncpy(labelj, inputLine+41, RLK_LABEL_LENGTH);
	} else {
	  swap_levels = FALSE;
	  rlk->Ei = Ei;
          rlk->Ej = Ej;
	  strncpy(labeli, inputLine+41, RLK_LABEL_LENGTH);
	  strncpy(labelj, inputLine+69, RLK_LABEL_LENGTH);
	}

	Nread += sscanf(inputLine+35, "%lf", &Ji);
	Nread += sscanf(inputLine+63, "%lf", &Jj);
	if (swap_levels) SWAPDOUBLE(Ji, Jj);
	rlk->gi = 2*Ji + 1;
	rlk->gj = 2*Jj + 1;

	lambda0 = (HPLANCK * CLIGHT) / (rlk->Ej - rlk->Ei);
	rlk->Aji = C / SQ(lambda0) * POW10(gf) / rlk->gj;
	rlk->Bji = CUBE(lambda0) / (2.0 * HPLANCK * CLIGHT) * rlk->Aji;
	rlk->Bij = (rlk->gj / rlk->gi) * rlk->Bji;

        /* --- Store in nm --                          -------------- */

	rlk->lambda0 = lambda0 / NM_TO_M;

	/* --- Get quantum numbers for angular momentum and spin -- - */

        determined = RLKdeterminate(labeli, labelj, rlk);
        rlk->polarizable = (atmos.Stokes && determined);

        /* --- Line broadening --                      -------------- */

	strncpy(Gvalues, inputLine+79, 18);
	Nread += sscanf(Gvalues, "%lf %lf %lf", &Grad, &GStark, &GvdWaals);

	if (GStark != 0.0)
	  rlk->GStark = POW10(GStark) * CUBE(CM_TO_M);
	else
	  rlk->GStark = 0.0;

	if (GvdWaals != 0.0)
	  rlk->GvdWaals = POW10(GvdWaals) * CUBE(CM_TO_M);
	else
	  rlk->GvdWaals = 0.0;

        /* --- If possible use Barklem formalism --    -------------- */

	useBarklem = FALSE;
	if (determined) {
	  if ((rlk->Li == S_ORBIT && rlk->Lj == P_ORBIT) ||
              (rlk->Li == P_ORBIT && rlk->Lj == S_ORBIT)) {
	    useBarklem = getBarklemcross(&bs_SP, rlk);
	  } else if ((rlk->Li == P_ORBIT && rlk->Lj == D_ORBIT) ||
		     (rlk->Li == D_ORBIT && rlk->Lj == P_ORBIT)) {
	    useBarklem = getBarklemcross(&bs_PD, rlk);
	  } else if ((rlk->Li == D_ORBIT && rlk->Lj == F_ORBIT) ||
		     (rlk->Li == F_ORBIT && rlk->Lj == D_ORBIT)) {
	    useBarklem = getBarklemcross(&bs_DF, rlk);
	  }
	}
	/* --- Else use good old Unsoeld --            -------------- */

        if (!useBarklem) {
	  getUnsoldcross(rlk);
	}
	/* --- Radiative broadening --                 -------------- */

	if (Grad != 0.0) {
	  rlk->Grad = POW10(Grad);
	} else {

	  /* --- Just take the Einstein Aji value, but only if either
                 Stark or vd Waals broadening is in effect -- ------- */

	  if (GStark != 0.0  || GvdWaals != 0.0)
	    rlk->Grad = rlk->Aji;
	  else {
	    rlk->Grad = 0.0;

            /* --- In this case the line is not polarizable because
                   there is no way to determine its damping -- ------ */

	    rlk->polarizable = FALSE;
	  }
	}
	/* --- Isotope and hyperfine fractions and slpittings -- ---- */

	Nread += sscanf(inputLine+106, "%d", &rlk->isotope);
	Nread += sscanf(inputLine+108, "%lf", &rlk->isotope_frac);
	rlk->isotope_frac = POW10(rlk->isotope_frac);
	Nread += sscanf(inputLine+117, "%lf", &rlk->hyperfine_frac);
	rlk->hyperfine_frac = POW10(rlk->hyperfine_frac);
	Nread += sscanf(inputLine+123, "%5d%5d", &hfs_i, &hfs_j);
	rlk->hfs_i = ((double) hfs_i) * MILLI * KBOLTZMANN;
	rlk->hfs_j = ((double) hfs_j) * MILLI * KBOLTZMANN;

	/* --- Effective Lande factors --              -------------- */

	Nread += sscanf(inputLine+143, "%5d%5d", &gL_i, &gL_j);
	rlk->gL_i = gL_i * MILLI;
	rlk->gL_j = gL_j * MILLI;
	if (swap_levels) {
	  SWAPDOUBLE(rlk->hfs_i, rlk->hfs_j);
	  SWAPDOUBLE(rlk->gL_i, rlk->gL_j);
	}

	/*      Nread += sscanf(inputLine+154, "%d", &iso_dl); */
	iso_dl = 0;
	rlk->iso_dl = iso_dl * MILLI * ANGSTROM_TO_NM;

	checkNread(Nread, Nrequired=17, routineName, checkPoint=1);
	/*
	printf("  Line: %f (vacuum), %f (air)\n"
	       " gi, gj: %f, %f\n"
	       " Ei, Ej: %e, %e\n"
	       " Aji: %e\n"
               " Grad, GStark, GvdWaals: %e, %e, %e\n"
               " VdWaals: %d\n"
	       " hyperfine_frac, isotope_frac: %f, %f\n"
	       " cross, alpha: %e, %e\n\n",
	       rlk->lambda0, lambda_air,
	       rlk->gi, rlk->gj, rlk->Ei, rlk->Ej, rlk->Aji,
	       rlk->Grad, rlk->GStark, rlk->GvdWaals,
               rlk->vdwaals,
	       rlk->hyperfine_frac, rlk->isotope_frac,
	       rlk->cross, rlk->alpha);
	*/
	rlk++;
      }
    }
    fclose(fp_linelist);

    sprintf(messageStr, "Read %d Kurucz lines from file %s\n",
	    Nline, listName);
    Error(MESSAGE, routineName, messageStr);
    atmos.Nrlk += Nline;
  }

  fclose(fp_Kurucz);

  free_BS(&bs_SP);
  free_BS(&bs_PD);
  free_BS(&bs_DF);
}
Пример #7
0
// calculation of the threshold in quiet in FFT-resolution
static void
Ruhehoerschwelle ( PsyModel* m,
				   unsigned int  EarModelFlag,
                   int           Ltq_offset,
                   int           Ltq_max )
{
    int     n;
    int     k;
    float   f;
    float   erg;
    double  tmp;
    float   absLtq [512];

    for ( n = 0; n < 512; n++ ) {
		f = (float) ( (n+1) * (float)(m->SampleFreq / 2000.) / 512 );   // Frequency in kHz

        switch ( EarModelFlag / 100 ) {
        case 0:         // ISO-threshold in quiet
            tmp  = 3.64*pow (f,-0.8) -  6.5*exp (-0.6*(f-3.3)*(f-3.3)) + 0.001*pow (f, 4.0);
            break;
        default:
        case 1:         // measured threshold in quiet (Nick Berglmeir, Andree Buschmann, Kopfh�er)
            tmp  = 3.00*pow (f,-0.8) -  5.0*exp (-0.1*(f-3.0)*(f-3.0)) + 0.0000015022693846297*pow (f, 6.0) + 10.*exp (-(f-0.1)*(f-0.1));
            break;
        case 2:         // measured threshold in quiet (Filburt, Kopfh�er)
            tmp  = 9.00*pow (f,-0.5) - 15.0*exp (-0.1*(f-4.0)*(f-4.0)) + 0.0341796875*pow (f, 2.5)          + 15.*exp (-(f-0.1)*(f-0.1)) - 18;
            tmp  = mind ( tmp, Ltq_max - 18 );
            break;
        case 3:
            tmp  = ATHformula_Frank ( 1.e3 * f );
            break;
        case 4:
            tmp  = ATHformula_Frank ( 1.e3 * f );
            if ( f > 4.8 ) {
                tmp += 3.00*pow (f,-0.8) -  5.0*exp (-0.1*(f-3.0)*(f-3.0)) + 0.0000015022693846297*pow (f, 6.0) + 10.*exp (-(f-0.1)*(f-0.1));
                tmp *= 0.5 ;
            }
            break;
        case 5:
            tmp  = ATHformula_Frank ( 1.e3 * f );
            if ( f > 4.8 ) {
                tmp = 3.00*pow (f,-0.8) -  5.0*exp (-0.1*(f-3.0)*(f-3.0)) + 0.0000015022693846297*pow (f, 6.0) + 10.*exp (-(f-0.1)*(f-0.1));
            }
            break;
        }

        tmp -= f * f * (int)(EarModelFlag % 100 - 50) * 0.0015;  // 00: +30 dB, 100: -30 dB  @20 kHz

        tmp       = mind ( tmp, Ltq_max );              // Limit ATH
        tmp      += Ltq_offset - 23;                    // Add chosen Offset
        m->tables.fftLtq[n] = absLtq[n] = POW10 ( 0.1 * tmp);     // conversion into power
    }

    // threshold in quiet in partitions (long)
    for ( n = 0; n < PART_LONG; n++ ) {
        erg = 1.e20f;
        for ( k = MPC_WL[n]; k <= MPC_WH[n]; k++ )
            erg = minf (erg, absLtq[k]);

		m->tables.partLtq[n] = erg;               // threshold in quiet
		m->tables.invLtq [n] = 1.f / m->tables.partLtq[n];  // Inverse
    }
}
Пример #8
0
void MULTIatom(FILE *atomFile, Atom *atom)
{
    register int n, kr, kf, la, krp;

    char   input[MAX_LINE_SIZE];
    bool_t exit_on_EOF;
    int    i, j, Nrad, Nread, phot, Trad_option, iw, lap, Nbb;
    double C, f, A0, Trad, lambda0, lambdaMin;
    AtomicLine *line;
    AtomicContinuum *continuum;
    FixedTransition *fixed;

    /* --- Read atom ID --                               -------------- */

    getLine(atomFile, MULTI_COMMENT_CHAR, input, exit_on_EOF=TRUE);
    Nread = sscanf(input, "%2s", atom->ID);
    if (strlen(atom->ID) == 1) strcat(atom->ID, " ");
    for (n = 0;  n < ATOM_ID_WIDTH;  n++)
        atom->ID[n] = toupper(atom->ID[n]);

    /* --- Read atomic abundance and weight --           -------------- */

    getLine(atomFile, MULTI_COMMENT_CHAR, input, exit_on_EOF=TRUE);
    Nread = sscanf(input, "%lf %lf", &atom->abundance, &atom->weight);
    atom->abundance = POW10(atom->abundance - 12.0);

    /* --- Get Number of levels, lines fixed transitions, and continua  */

    getLine(atomFile, MULTI_COMMENT_CHAR, input, exit_on_EOF=TRUE);
    Nread = sscanf(input, "%d %d %d %d",
                   &atom->Nlevel, &atom->Nline, &atom->Ncont, &atom->Nfixed);

    Nrad = atom->Nline + atom->Ncont;

    /* --- Read in the level energies, statistical weights, labels,
           and ionization stage --                       -------------- */

    atom->E = (double *) malloc(atom->Nlevel * sizeof(double));
    atom->g = (double *) malloc(atom->Nlevel * sizeof(double));
    atom->label = (char **) malloc(atom->Nlevel * sizeof(char *));
    atom->stage = (int *) malloc(atom->Nlevel * sizeof(int));

    for (i = 0;  i < atom->Nlevel;  i++) {
        atom->label[i] = (char *) malloc((ATOM_LABEL_WIDTH+1) * sizeof(char));
        getLine(atomFile, MULTI_COMMENT_CHAR, input , exit_on_EOF=TRUE);
        Nread = sscanf(input, "%lf %lf '%20c' %d",
                       &atom->E[i], &atom->g[i], atom->label[i], &atom->stage[i]);

        *(atom->label[i] + ATOM_LABEL_WIDTH) = '\0';
        atom->E[i] *= (HPLANCK * CLIGHT) / CM_TO_M;
        atom->stage[i]--;
    }
    C = 2 * PI * (Q_ELECTRON/EPSILON_0) * (Q_ELECTRON/M_ELECTRON) / CLIGHT;

    /* --- Go through the bound-bound transitions --     -------------- */

    atom->line = (AtomicLine *) malloc(atom->Nline * sizeof(AtomicLine));
    for (kr = 0;  kr < atom->Nline;  kr++) {
        line = atom->line + kr;

        line->Voigt   = TRUE;
        line->PRD     = FALSE;
        line->vdWaals = UNSOLD;

        getLine(atomFile, MULTI_COMMENT_CHAR, input, exit_on_EOF=TRUE);
        Nread = sscanf(input, "%d %d %lf %d %lf %lf %d %lf %lf %lf",
                       &j, &i, &f, &line->Nlambda, &line->qwing,
                       &line->qcore, &iw,
                       &line->Grad, &line->cvdWaals[0], &line->cStark);

        line->j = MAX(i, j);
        line->i = MIN(i, j);
        j = --line->j;
        i = --line->i;

        lambda0 = (HPLANCK * CLIGHT) / (atom->E[j] - atom->E[i]);
        line->Aji = C / SQ(lambda0) * (atom->g[i] / atom->g[j]) * f;
        line->lambda0 = lambda0 / NM_TO_M;

        if ((line->qcore < 0.0) || (line->qwing < 0.0)) {
            line->lambda = (double *) malloc(line->Nlambda * sizeof(double));
            for (la = 0;  la < line->Nlambda;  la++)
                fscanf(atomFile, "%lf", line->lambda + la);
            line->symmetric = FALSE;
            line->qcore = fabs(line->qcore);
            line->qwing = fabs(line->qwing);
        } else {
            line->lambda = NULL;
            line->symmetric = TRUE;
        }
        line->cvdWaals[2] = line->cvdWaals[0];
        line->cStark *= -CUBE(CM_TO_M);
    }
    /* --- Go through the bound-free transitions --      -------------- */

    atom->continuum =
        (AtomicContinuum *) malloc(atom->Ncont * sizeof(AtomicContinuum));
    for (kr = 0;  kr < atom->Ncont;  kr++) {
        continuum = atom->continuum + kr;

        getLine(atomFile, MULTI_COMMENT_CHAR, input, exit_on_EOF=TRUE);
        Nread = sscanf(input, "%d %d %lf %d %lf",
                       &j, &i, &continuum->alpha0,
                       &continuum->Nlambda, &lambdaMin);

        continuum->j = MAX(i, j);
        continuum->i = MIN(i, j);
        j = --continuum->j;
        i = --continuum->i;

        lambda0 = (HPLANCK * CLIGHT)/(atom->E[j] - atom->E[i]);
        continuum->lambda0 = lambda0 / NM_TO_M;
        continuum->alpha0 *= SQ(CM_TO_M);

        if (lambdaMin < 0.0) {
            continuum->hydrogenic = FALSE;
            continuum->lambda =
                (double *) malloc(continuum->Nlambda * sizeof(double));
            continuum->alpha  =
                (double *) malloc(continuum->Nlambda * sizeof(double));
            for (la = 0;  la < continuum->Nlambda;  la++) {
                lap = continuum->Nlambda - la - 1;
                getLine(atomFile, MULTI_COMMENT_CHAR, input, exit_on_EOF=TRUE);
                sscanf(input, "%lf %lf", continuum->lambda+lap, continuum->alpha+lap);
                continuum->lambda[lap] *= 0.1;
                continuum->alpha[lap]  *= SQ(CM_TO_M);
            }
        } else {
            continuum->hydrogenic = TRUE;
            continuum->alpha = NULL;
            continuum->lambda = (double *) malloc(sizeof(double));
            continuum->lambda[0] = lambdaMin / 10.0;
        }
    }
    /* --- Go through the fixed transitions, which may be either
           bound-bound (phot == 0) or bound-free (phot == 1) -- ------- */

    atom->ft =
        (FixedTransition *) malloc(atom->Nfixed * sizeof(FixedTransition));
    for (kf = 0;  kf < atom->Nfixed;  kf++) {
        fixed = atom->ft + kf;

        getLine(atomFile, MULTI_COMMENT_CHAR, input, exit_on_EOF=TRUE);
        Nread = sscanf(input, "%d %d %d %lf %lf %d",
                       &j, &i, &phot, &A0, &fixed->Trad, &Trad_option);

        fixed->j = MAX(i, j);
        fixed->i = MIN(i, j);
        j = --fixed->j;
        i = --fixed->i;

        lambda0 = (HPLANCK * CLIGHT)/(atom->E[j] - atom->E[i]);
        fixed->lambda0 = lambda0 / NM_TO_M;
        if (phot) {
            fixed->type = FIXED_LINE;
            fixed->strength = A0 * SQ(CM_TO_M);
        } else {
            fixed->type = FIXED_CONTINUUM;
            fixed->strength = A0;
        }
        switch (Trad_option) {
        case 1:
            fixed->option = TRAD_ATMOSPHERIC;
            break;
        case 2:
            fixed->option = TRAD_PHOTOSPHERIC;
            break;
        case 3:
            fixed->option = TRAD_CHROMOSPHERIC;
            break;
        }
    }
}
Пример #9
0
void main(int argc, void *argv[])
{
  register int n, k;

  char   line[MAX_LINE_SIZE];
  int    Nread, no;
  double Teff, abundscale, logabundH, pressure, Rosseland_opac, rad_acc;

  Atmosphere atmos;
  Geometry geometry;
  Element *element;
  FILE  *fp_Kurucz;

  commandline.logfile = stderr;

  if (argc < 2) {
    fprintf(stderr, "Usage : %s  model.Kurucz [MULTI_name]\n\n", argv[0]);
    exit(0);
  }

  atmos.Nelem    = sizeof(atomweight) / sizeof(struct AtomWeight);
  atmos.elements = (Element *) malloc(atmos.Nelem * sizeof(Element));

  for (n = 0;  n < atmos.Nelem;  n++) {
    element = &atmos.elements[n];
    strcpy(element->ID, atomweight[n].ID);
    element->weight = atomweight[n].weight;
  }

  if ((fp_Kurucz = fopen(argv[1], "r")) == NULL) {
    sprintf(messageStr, "Unable to open input file %s", argv[1]);
    Error(ERROR_LEVEL_2, argv[0], messageStr);
  }

  fgets(line, MAX_LINE_SIZE, fp_Kurucz);
  Nread = sscanf(line, " TEFF %lf GRAVITY %lf", &Teff, &atmos.gravity);
  atmos.gravity = POW10(atmos.gravity);

  fgets(line, MAX_LINE_SIZE, fp_Kurucz);
  strncpy(atmos.ID, line+5, ATMOS_ID_WIDTH);
  atmos.ID[ATMOS_ID_WIDTH-1] = '\0';

  for (n = 0;  n < 3;  n++) fgets(line, MAX_LINE_SIZE, fp_Kurucz);
  Nread = sscanf(line,
		 "ABUNDANCE SCALE %lf ABUNDANCE CHANGE %d %lf %d %lf",
		 &abundscale, &no, &atmos.elements[0].abund,
		 &no, &atmos.elements[1].abund);

  if (abundscale != 1.0) {
    sprintf(messageStr, "Use METALICITY = %f in keyword.input\n",
	    log10(abundscale));
    Error(WARNING, argv[0], messageStr);
  }

  for (n = 2;  n < 98;  n += 6) {
    fgets(line, MAX_LINE_SIZE, fp_Kurucz);
    Nread = sscanf(line,
		   "ABUNDANCE CHANGE %d %lf %d %lf %d %lf %d %lf %d %lf",
		   &no, &atmos.elements[n].abund,
		   &no, &atmos.elements[n+1].abund,
		   &no, &atmos.elements[n+2].abund,
		   &no, &atmos.elements[n+3].abund,
		   &no, &atmos.elements[n+4].abund,
		   &no, &atmos.elements[n+5].abund);
  }
  fgets(line, MAX_LINE_SIZE, fp_Kurucz);
  Nread = sscanf(line, "ABUNDANCE CHANGE %d %lf",
		 &no, &atmos.elements[98].abund);

  logabundH = log10(atmos.elements[0].abund);
  atmos.elements[0].abund = 12.0;
  atmos.elements[1].abund = log10(atmos.elements[1].abund) - logabundH;
  for (n = 2;  n < atmos.Nelem;  n++)
    atmos.elements[n].abund -= logabundH;

  fgets(line, MAX_LINE_SIZE, fp_Kurucz);
  Nread = sscanf(line, "READ DECK6 %d", &geometry.Ndep);
  atmos.Nspace = geometry.Ndep;

  geometry.scale = COLUMN_MASS;
  geometry.cmass = (double *) malloc(geometry.Ndep * sizeof(double));
  atmos.T        = (double *) malloc(geometry.Ndep * sizeof(double));
  atmos.ne       = (double *) malloc(geometry.Ndep * sizeof(double));
  geometry.vel   = (double *) calloc(geometry.Ndep, sizeof(double));
  atmos.vturb    = (double *) malloc(geometry.Ndep * sizeof(double));

  for (k = 0;  k < geometry.Ndep;  k++) {
    fgets(line, MAX_LINE_SIZE, fp_Kurucz);
    Nread = sscanf(line, "%lf %lf %lf %lf %lf %lf %lf",
		   &geometry.cmass[k], &atmos.T[k], &pressure,
		   &atmos.ne[k], &Rosseland_opac, &rad_acc, &atmos.vturb[k]);

    atmos.vturb[k] *= CM_TO_M;
  }
  atmos.H_LTE = TRUE;

  atmos.B = NULL;

  fclose(fp_Kurucz);
  if (argc == 1) 
    writeMULTIatmos(&geometry, &atmos, NULL);
  else
    writeMULTIatmos(&geometry, &atmos, argv[2]);
}
Пример #10
0
void MULTIatmos(Atmosphere *atmos, Geometry *geometry)
{
  const char routineName[] = "MULTIatmos";
  register int k, n, mu;

  char    scaleStr[20], inputLine[MAX_LINE_SIZE], *filename;
  bool_t  exit_on_EOF, enhanced_atmos_ID = FALSE;
  int     Nread, Ndep, Nrequired, checkPoint;
  double *dscale, turbpress, turbelecpress, nbaryon, meanweight;
  struct  stat statBuffer;

  getCPU(2, TIME_START, NULL);

  /* --- Get abundances of background elements --        ------------ */
 
  readAbundance(atmos);

  /* --- Open the input file for model atmosphere in MULTI format - - */

  if ((atmos->fp_atmos = fopen(input.atmos_input, "r")) == NULL) {
    sprintf(messageStr, "Unable to open inputfile %s", input.atmos_input);
    Error(ERROR_LEVEL_2, routineName, messageStr);
  } else {
    sprintf(messageStr, "\n -- reading input file: %s\n\n",
	    input.atmos_input);
    Error(MESSAGE, NULL, messageStr);
  }

  atmos->NHydr = N_HYDROGEN_MULTI;

  /* --- Boundary condition at TOP of atmosphere --      ------------ */

  if (strcmp(input.Itop, "none"))
    geometry->vboundary[TOP] = IRRADIATED;
  else 
    geometry->vboundary[TOP] = ZERO;

  /* --- Boundary condition at BOTTOM of atmosphere --   ------------ */

  geometry->vboundary[BOTTOM] = THERMALIZED;

  /* --- Read atmos ID, scale type, gravity, and number of depth
         points --                                       ------------ */
 
  getLine(atmos->fp_atmos, MULTI_COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
  if (enhanced_atmos_ID) {

    /* --- Construct atmosID from filename and last modification date */

    stat(input.atmos_input, &statBuffer);
    if ((filename = strrchr(input.atmos_input, '/')) != NULL)
      filename++;
    else
      filename = input.atmos_input;
    sprintf(atmos->ID, "%s (%.24s)", filename,
	    asctime(localtime(&statBuffer.st_mtime)));
    Nread = 1;
  } else
    Nread = sscanf(inputLine, "%s", atmos->ID);

  getLine(atmos->fp_atmos, MULTI_COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
  Nread += sscanf(inputLine, "%20s", scaleStr);
  getLine(atmos->fp_atmos, MULTI_COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
  Nread += sscanf(inputLine, "%lf", &atmos->gravity);
  getLine(atmos->fp_atmos, MULTI_COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
  Nread += sscanf(inputLine, "%d", &geometry->Ndep);
  checkNread(Nread, Nrequired=4, routineName, checkPoint=1);

  /* --- Keep duplicates of some of the geometrical quantities in
         Atmos structure --                            -------------- */

  atmos->Ndim = 1;
  atmos->N = (int *) malloc(atmos->Ndim * sizeof(int));
  atmos->Nspace = Ndep = geometry->Ndep;
  atmos->N[0] = Ndep;

  atmos->gravity = POW10(atmos->gravity) * CM_TO_M;

  /* --- Allocate space for arrays that define structure -- --------- */

  geometry->tau_ref = (double *) malloc(Ndep * sizeof(double));
  geometry->cmass   = (double *) malloc(Ndep * sizeof(double));
  geometry->height  = (double *) malloc(Ndep * sizeof(double));
  atmos->T      = (double *) malloc(Ndep * sizeof(double));
  atmos->ne     = (double *) malloc(Ndep * sizeof(double));
  atmos->vturb  = (double *) malloc(Ndep * sizeof(double));
  geometry->vel = (double *) malloc(Ndep * sizeof(double));

  dscale = (double *) malloc(Ndep * sizeof(double));
  for (k = 0;  k < Ndep;  k++) {
    getLine(atmos->fp_atmos, MULTI_COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
    Nread = sscanf(inputLine, "%lf %lf %lf %lf %lf",
		   &dscale[k], &atmos->T[k], &atmos->ne[k],
		   &geometry->vel[k], &atmos->vturb[k]);
    checkNread(Nread, Nrequired=5, routineName, checkPoint=2);
  }

  switch(toupper(scaleStr[0])) {
  case 'M':
    geometry->scale = COLUMN_MASS;
    for (k = 0;  k < Ndep;  k++)
      geometry->cmass[k] = POW10(dscale[k]) * (G_TO_KG / SQ(CM_TO_M));
    break;
  case 'T':
    geometry->scale = TAU500;
    for (k = 0;  k < Ndep;  k++) geometry->tau_ref[k] = POW10(dscale[k]);
    break;
  case 'H':
    geometry->scale = GEOMETRIC;
    for (k = 0;  k < Ndep;  k++) geometry->height[k] = dscale[k] * KM_TO_M;
    break;
  default:
    sprintf(messageStr, "Unknown depth scale string in file %s: %s",
	    input.atmos_input, scaleStr);
    Error(ERROR_LEVEL_2, routineName, messageStr);
  }
  free(dscale);

  for (k = 0;  k < Ndep;  k++) {
    geometry->vel[k] *= KM_TO_M;
    atmos->vturb[k]  *= KM_TO_M;
    atmos->ne[k]     /= CUBE(CM_TO_M);
  }
  atmos->moving = FALSE;
  for (k = 0;  k < Ndep;  k++) {
    if (fabs(geometry->vel[k]) >= atmos->vmacro_tresh) {
      atmos->moving = TRUE;
      break;
    }
  }
  /* --- Get angle-quadrature and copy geometry independent quantity
         wmu to atmos structure. --                    -------------- */

  getAngleQuad(geometry);
  atmos->wmu = geometry->wmu;

  /* --- Magnetic field is read here. --               -------------- */

  atmos->Stokes = readB(atmos);

  /* --- Read Hydrogen populations if present --       -------------- */

  atmos->nH = matrix_double(atmos->NHydr, Ndep);
  for (k = 0;  k < Ndep;  k++) {
    if (getLine(atmos->fp_atmos, MULTI_COMMENT_CHAR, inputLine,
		exit_on_EOF=FALSE) == EOF) break;
    Nread = sscanf(inputLine, "%lf %lf %lf %lf %lf %lf",
		   &atmos->nH[0][k], &atmos->nH[1][k], &atmos->nH[2][k],
		   &atmos->nH[3][k], &atmos->nH[4][k], &atmos->nH[5][k]);
    checkNread(Nread, Nrequired=6, routineName, checkPoint=3);
  }
  if (k > 0  &&  k < Ndep) {
    sprintf(messageStr,
	    "Reached end of input file %s before all data was read",
	    input.atmos_input);
    Error(ERROR_LEVEL_2, routineName, messageStr);
  } else if (k == 0) {

    /* --- No hydrogen populations supplied: use LTE populations
           like MULTI does --                          -------------- */

    if (geometry->scale != COLUMN_MASS) {
      sprintf(messageStr,
	      "Height scale should be COLUMNMASS when nH not supplied: "
	      "File %s", input.atmos_input);
      Error(ERROR_LEVEL_2, routineName, messageStr);
    }
    atmos->nHtot = (double *) calloc(Ndep, sizeof(double));

    atmos->H_LTE = TRUE;
    meanweight = atmos->avgMolWght * AMU;
    for (k = 0;  k < Ndep;  k++) {
      turbpress     = 0.5 * meanweight * SQ(atmos->vturb[k]);
      turbelecpress = 0.5 * M_ELECTRON * SQ(atmos->vturb[k]);

      nbaryon =
	(atmos->gravity * geometry->cmass[k] -
	 atmos->ne[k] *(KBOLTZMANN * atmos->T[k] + turbelecpress));

      atmos->nHtot[k] =	nbaryon / 
	(atmos->totalAbund * (KBOLTZMANN * atmos->T[k] + turbpress));
    }
  } else if (k == Ndep) {
    atmos->nHtot = (double *) calloc(Ndep, sizeof(double));
    for (n = 0;  n < atmos->NHydr;  n++) {
      for (k = 0;  k < Ndep;  k++) {
	atmos->nH[n][k] /= CUBE(CM_TO_M);
	atmos->nHtot[k] += atmos->nH[n][k];
      }
    }
  }

  getCPU(2, TIME_POLL, "Read Atmosphere");
}