Пример #1
0
void rawAtom(Atom *atom, char *atomFileName)
{
  const char routineName[] = "rawAtom";
  register int kr, kf, la, n;

  char    inputLine[MAX_LINE_SIZE], shapeStr[20], vdWstr[20], nuDepStr[20],
          errorStr[80], symmStr[20], optionStr[20], *match;
  bool_t  exit_on_EOF;
  int     i, j, Nlevel, Nrad, Nline, Ncont, Nfixed, Nread, Nrequired,
          checkPoint;
  double  f, C, lambda0, lambdamin, dlamb;
  FILE   *atomFile;
  AtomicLine *line;
  AtomicContinuum *continuum;
  FixedTransition *fixed;

  /* --- Open the data file for current model atom --  -------------- */

  if ((atomFile = fopen(atomFileName, "r")) == NULL) {
    sprintf(messageStr, "Unable to open input file %s", atomFileName);
    Error(ERROR_LEVEL_2, routineName, messageStr);
  }
  /* --- Read atom ID and convert to uppercase --      -------------- */
 
  getLine(atomFile, COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
  Nread = sscanf(inputLine, "%2s", atom->ID);
  checkNread(Nread, Nrequired=1, routineName, checkPoint=1);
  for (n = 0;  n < (int) strlen(atom->ID);  n++)
    atom->ID[n] = toupper(atom->ID[n]);
  if (strlen(atom->ID) == 1) strcat(atom->ID, " ");
 
  /* --- Get the atomic weight --                      -------------- */

  for (n = 0;  n < sizeof(atomweight)/sizeof(struct AtomWeight);  n++) {
    if ((match = strstr(atom->ID, atomweight[n].ID))) {
      atom->weight = atomweight[n].weight;
      break;
    }
  }
  if (!match) {
    sprintf(messageStr, "Found no matching element for %s", atom->ID);
    Error(ERROR_LEVEL_2, routineName, messageStr);
  }
  /* --- Get Number of levels, lines fixed transitions, and continua  */
 
  getLine(atomFile, COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
  Nread = sscanf(inputLine, "%d %d %d %d",
		 &atom->Nlevel, &atom->Nline, &atom->Ncont, &atom->Nfixed);
  checkNread(Nread, Nrequired=4, routineName, checkPoint=2);
  Nlevel = atom->Nlevel;
  Nline  = atom->Nline;  Ncont  = atom->Ncont;  Nfixed = atom->Nfixed;
  Nrad   = Nline + Ncont;

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

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

  for (i = 0;  i < Nlevel;  i++) {
    atom->label[i] = (char *) calloc((ATOM_LABEL_WIDTH+1), sizeof(char)); 
    getLine(atomFile, COMMENT_CHAR, inputLine , exit_on_EOF=TRUE);
    Nread = sscanf(inputLine, "%lf %lf '%20c' %d",
      &atom->E[i], &atom->g[i], atom->label[i], &atom->stage[i]);
    checkNread(Nread, Nrequired=4, routineName, checkPoint=3);

    atom->E[i] *= (HPLANCK * CLIGHT) / CM_TO_M;
  }
  if (atom->stage[Nlevel-1] != (atom->stage[Nlevel-2] + 1)) {
    sprintf(messageStr, "Found no overlying continuum for atom %s", atom->ID);
    Error(ERROR_LEVEL_2, routineName, messageStr);
  }

  C = 2 * PI * (Q_ELECTRON/EPSILON_0) * (Q_ELECTRON/M_ELECTRON) / CLIGHT;

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

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

    getLine(atomFile, COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
    Nread = sscanf(inputLine,
		   "%d %d %lf %s %d %s %lf %lf %s %lf %lf %lf %lf %lf %lf %lf",
		   &j, &i, &f, shapeStr,
		   &line->Nlambda, symmStr, &line->qcore,
		   &line->qwing, vdWstr,
		   &line->cvdWaals[0], &line->cvdWaals[1],
		   &line->cvdWaals[2], &line->cvdWaals[3],
		   &line->Grad, &line->cStark, &line->g_Lande_eff);
    checkNread(Nread, Nrequired=15, routineName, checkPoint=4);
    if (Nread == 15) line->g_Lande_eff = 0.0;

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

    if (!strstr(shapeStr, "PRD") &&
	!strstr(shapeStr, "VOIGT") && !strstr(shapeStr, "GAUSS")) {
      sprintf(messageStr, "Invalid value for line-shape string: %s",
	      shapeStr);
      Error(ERROR_LEVEL_2, routineName, messageStr);
    }
    if (strstr(shapeStr, "PRD")) {
      atom->Nprd++;
      line->PRD = TRUE;
    }
    if (strstr(shapeStr, "GAUSS")) line->Voigt = FALSE;

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

    if (strstr(vdWstr, "PARAMTR"))
      line->vdWaals = RIDDER_RENSBERGEN;
    else {
      line->vdWaals = UNSOLD;
      line->cvdWaals[3] = line->cvdWaals[1] = 0.0;
    }
    line->symmetric = (strstr(symmStr, "ASYMM")) ? FALSE : TRUE;
  }
  /* --- Go through the bound-free transitions --      -------------- */


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

    getLine(atomFile, COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
    Nread = sscanf(inputLine, "%d %d %lf %d %s %lf",
		   &j, &i, &continuum->alpha0, &continuum->Nlambda,
		   nuDepStr, &lambdamin);
    checkNread(Nread, Nrequired=6, routineName, checkPoint=5);

    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->lambda  =
      (double *) malloc(continuum->Nlambda * sizeof(double));
    continuum->alpha   =
      (double *) malloc(continuum->Nlambda * sizeof(double));

    if (strstr(nuDepStr, "EXPLICIT")) {
      continuum->hydrogenic = FALSE;
      for (la = continuum->Nlambda-1;  la >= 0;  la--) {
	getLine(atomFile, COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
	Nread = sscanf(inputLine, "%lf %lf",
		        &continuum->lambda[la], &continuum->alpha[la]);
	checkNread(Nread, Nrequired=2, routineName, checkPoint=6);
      }
      for (la = 1;  la < continuum->Nlambda;  la++) {
	if (continuum->lambda[la] < continuum->lambda[la-1]) {
	  sprintf(messageStr,
		  "Continuum %d does not have monotonous wavelengths",
		  kr - Nline);
	  Error(ERROR_LEVEL_2, routineName, messageStr);
	}
      }
    } else {
      continuum->hydrogenic = TRUE;
      if (lambdamin >= continuum->lambda0) {
	sprintf(messageStr,
		"Minimum wavelength for continuum %d too long", kr - Nline);
	Error(ERROR_LEVEL_2, routineName, messageStr);
      }
      dlamb   = (continuum->lambda0 - lambdamin) / (continuum->Nlambda - 1);
      continuum->lambda[0] = lambdamin;
      for (la = 1;  la < continuum->Nlambda;  la++)
	continuum->lambda[la] = continuum->lambda[la-1] + dlamb;
    }
  }
  /* --- Go through fixed transitions --               -------------- */

  if (atom->Nfixed > 0) {
    atom->ft = (FixedTransition *) malloc(Nfixed * sizeof(FixedTransition));

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

      getLine(atomFile, COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
      Nread = sscanf(inputLine, "%d %d %lf %lf %s",
		     &j, &i, &fixed->strength,
		     &fixed->Trad, optionStr);
      checkNread(Nread, Nrequired=5, routineName, checkPoint=7);

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

      for (kr = 0;  kr < Nline;  kr++) {
	line = atom->line + kr;
	if (line->i == i  &&  line->j == j) {
	  sprintf(messageStr,
		  "Fixed transition j = %d, i = %d duplicates active line",
		  j, i);
	  Error(ERROR_LEVEL_2, routineName, messageStr);
	}
      }
      for (kr = 0;  kr < Ncont;  kr++) {
	continuum = atom->continuum + kr;
	if (continuum->i == i  &&  continuum->j == j) {
	  sprintf(messageStr, "Fixed transition j = %d,  i = %d"
		  " duplicates active continuum", j, i);
	  Error(ERROR_LEVEL_2, routineName, messageStr);
	}
      }
      lambda0 = (HPLANCK * CLIGHT) / (atom->E[j] - atom->E[i]);
      fixed->lambda0 = lambda0 / NM_TO_M;

      if (atom->stage[j] == atom->stage[i])
	fixed->type = FIXED_LINE;
      else 
	fixed->type = FIXED_CONTINUUM;

      if (strstr(optionStr, "TRAD_ATMOSPHERIC"))
	fixed->option = TRAD_ATMOSPHERIC;
      else if (strstr(optionStr, "TRAD_PHOTOSPHERIC"))
	fixed->option = TRAD_PHOTOSPHERIC;
      else if (strstr(optionStr, "TRAD_CHROMOSPHERIC"))
	fixed->option = TRAD_CHROMOSPHERIC;
      else {
	sprintf(messageStr, "Inavlid value for TRAD option: %s", optionStr);
	Error(ERROR_LEVEL_2, routineName, messageStr);
      }
    }
  }

  fclose(atomFile);
} 
Пример #2
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);
}
Пример #3
0
int main(int argc, char *argv[])
{
  register int n, k;

  char    rayFileName[14], inputLine[MAX_LINE_SIZE];
  bool_t  result, exit_on_EOF, to_obs, initialize, crosscoupling,
          analyze_output, equilibria_only;
  int     Nspect, Nread, Nrequired, checkPoint, *wave_index = NULL;
  double  muz, *S, *chi, *J;
  FILE   *fp_out, *fp_ray, *fp_stokes;
  XDR     xdrs;
  ActiveSet *as;

  setOptions(argc, argv);
  getCPU(0, TIME_START, NULL);
  SetFPEtraps();

  /* --- Read input data and initialize --             -------------- */

  readInput();
  spectrum.updateJ = FALSE;

  /* --- Read input data for atmosphere --             -------------- */

  getCPU(1, TIME_START, NULL);
  MULTIatmos(&atmos, &geometry);

  /* --- Read direction cosine for ray --              -------------- */

  if ((fp_ray = fopen(RAY_INPUT_FILE, "r")) == NULL) {
    sprintf(messageStr, "Unable to open inputfile %s", RAY_INPUT_FILE);
    Error(ERROR_LEVEL_2, argv[0], messageStr);
  }
  
  getLine(fp_ray, COMMENT_CHAR, inputLine, exit_on_EOF=TRUE);
  Nread = sscanf(inputLine, "%lf", &muz);
  checkNread(Nread, Nrequired=1, argv[0], checkPoint=1);

  if (muz <= 0.0  ||  muz > 1.0) {
    sprintf(messageStr,
	    "Value of muz = %f does not lie in interval <0.0, 1.0]\n", muz);
    Error(ERROR_LEVEL_2, argv[0], messageStr);
  }

  if (input.StokesMode == FIELD_FREE ||
      input.StokesMode == POLARIZATION_FREE) {
    input.StokesMode = FULL_STOKES;
  }
  /* --- redefine geometry for just this one ray --    -------------- */

  atmos.Nrays = geometry.Nrays = 1;
  geometry.muz[0] = muz;
  geometry.mux[0] = sqrt(1.0 - SQ(geometry.muz[0]));
  geometry.muy[0] = 0.0;
  geometry.wmu[0] = 1.0;
  if (atmos.Stokes) Bproject();

  input.startJ = OLD_J;

  readAtomicModels();
  readMolecularModels();
  SortLambda();

  getBoundary(&geometry);

  /* --- Open file with background opacities --        -------------- */

  if (atmos.moving || input.StokesMode) {
    strcpy(input.background_File, "background.ray");
    Background(analyze_output=FALSE, equilibria_only=FALSE);
  } else {
    Background(analyze_output=FALSE, equilibria_only=TRUE);

    if ((atmos.fd_background =
	 open(input.background_File, O_RDONLY, 0)) == -1) {
      sprintf(messageStr, "Unable to open inputfile %s",
	      input.background_File);
      Error(ERROR_LEVEL_2, argv[0], messageStr);
    }
    readBRS();
  }
  convertScales(&atmos, &geometry);

  getProfiles();
  initSolution();
  initScatter();

  getCPU(1, TIME_POLL, "Total initialize");

  /* --- Solve radiative transfer equations --         -------------- */

  solveSpectrum(FALSE, FALSE);

  /* --- Write emergent spectrum to output file --     -------------- */
 
  sprintf(rayFileName, "spectrum_%4.2f", muz);
  if ((fp_out = fopen(rayFileName, "w" )) == NULL) {
    sprintf(messageStr, "Unable to open output file %s", rayFileName);
    Error(ERROR_LEVEL_2, argv[0], messageStr);
  }
  xdrstdio_create(&xdrs, fp_out, XDR_ENCODE);

  result = xdr_double(&xdrs, &muz);
  result = xdr_vector(&xdrs, (char *) spectrum.I[0], spectrum.Nspect,
		      sizeof(double), (xdrproc_t) xdr_double);

  /* --- Read wavelength indices for which chi and S are to be
         written out for the specified direction --    -------------- */

  Nread = fscanf(fp_ray, "%d", &Nspect);
  checkNread(Nread, 1, argv[0], checkPoint=2);

  if (Nspect > 0) {
    wave_index = (int *) malloc(Nspect * sizeof(int));
    Nread = 0;
    while (fscanf(fp_ray, "%d", &wave_index[Nread]) != EOF) Nread++;
    checkNread(Nread, Nspect, argv[0], checkPoint=3);
    fclose(fp_ray);

    chi = (double *) malloc(atmos.Nspace * sizeof(double));
    if (atmos.Stokes)
      S = (double *) malloc(4 * atmos.Nspace * sizeof(double));
    else
      S = (double *) malloc(atmos.Nspace * sizeof(double));
  }
  result = xdr_int(&xdrs, &Nspect);

  /* --- Go through the list of wavelengths --         -------------- */

  if (Nspect > 0  &&  input.limit_memory)
    J = (double *) malloc(atmos.Nspace * sizeof(double));

  for (n = 0;  n < Nspect;  n++) {
    if (wave_index[n] < 0  ||  wave_index[n] >= spectrum.Nspect) {
      sprintf(messageStr, "Illegal value of wave_index[n]: %4d\n"
	      "Value has to be between 0 and %4d\n", 
	      wave_index[n], spectrum.Nspect);
      Error(ERROR_LEVEL_2, argv[0], messageStr);
      continue;
    }
    sprintf(messageStr, "Processing n = %4d, lambda = %9.3f [nm]\n",
	    wave_index[n], spectrum.lambda[wave_index[n]]);
    Error(MESSAGE, NULL, messageStr);

    as = &spectrum.as[wave_index[n]];
    alloc_as(wave_index[n], crosscoupling=FALSE);
    Opacity(wave_index[n], 0, to_obs=TRUE, initialize=TRUE);
    readBackground(wave_index[n], 0, to_obs=TRUE);

    if (input.limit_memory) {
      readJlambda(wave_index[n], J);
    } else
      J = spectrum.J[wave_index[n]];

    /* --- Add the continuum opacity and emissivity -- -------------- */   

    for (k = 0;  k < atmos.Nspace;  k++) {
      chi[k] = as->chi[k] + as->chi_c[k];
      S[k]   = (as->eta[k] + as->eta_c[k] + as->sca_c[k]*J[k]) / chi[k];
    }
    result = xdr_int(&xdrs, &wave_index[n]);
    result = xdr_vector(&xdrs, (char *) chi, atmos.Nspace,
			sizeof(double), (xdrproc_t) xdr_double);
    result = xdr_vector(&xdrs, (char *) S, atmos.Nspace,
			sizeof(double), (xdrproc_t) xdr_double);

    free_as(wave_index[n], crosscoupling=FALSE);
  }

  /* --- If magnetic fields are present --             -------------- */
  
  if (atmos.Stokes || input.backgr_pol) {
    result = xdr_vector(&xdrs, (char *) spectrum.Stokes_Q[0],
			spectrum.Nspect, sizeof(double),
			(xdrproc_t) xdr_double);
    result = xdr_vector(&xdrs, (char *) spectrum.Stokes_U[0],
			spectrum.Nspect, sizeof(double),
			(xdrproc_t) xdr_double);
    result = xdr_vector(&xdrs, (char *) spectrum.Stokes_V[0],
			spectrum.Nspect, sizeof(double),
			(xdrproc_t) xdr_double);
  }

  if (Nspect > 0  &&  input.limit_memory)
    free(J);

  xdr_destroy(&xdrs);
  fclose(fp_out);
  printTotalCPU();
}
Пример #4
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");
}