// 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); }
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; }
/* ********************************************************************* */ 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 */
// 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 } }
// 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; } }
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); }
// 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 } }
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; } } }
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]); }
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"); }