/* \fcnfh Read abundances and pressure for each isotope and radius @returns number of radius point */ int readatmfile(FILE *fp, /* File */ struct transit *tr, /* transit info */ struct atm_data *at, /* atmosphere info */ prop_samp *rads, /* radius sampling */ int nrad) /* number of allocated radii, note that is not returned updated */ { //find abundance related quantities for each radius int lines=at->begline; PREC_NREC r=0; PREC_RES tmp; char rc; float allowq=1-tr->allowrq; double sumq; char line[maxline],*lp,*lp2; prop_isov *isov=at->isov; int *isoeq=at->isoeq; struct isotopes *iso=tr->ds.iso; enum isodo *isodo=at->isodo; int i,neiso=iso->n_e; fseek(fp,at->begpos,SEEK_SET); while(1){ //reallocate if necessary if(r==nrad){ nrad<<=1; rads->v=(PREC_ATM *)realloc(rads->v,nrad*sizeof(PREC_ATM)); at->atm.t= (PREC_ATM *)realloc(at->atm.t,nrad*sizeof(PREC_ATM)); at->atm.p= (PREC_ATM *)realloc(at->atm.p,nrad*sizeof(PREC_ATM)); at->mm=(double *)realloc(at->mm,nrad*sizeof(double)); for(i=0;i<neiso;i++){ isov[i].d=(PREC_ATM *)realloc(isov[i].d, nrad*sizeof(PREC_ATM)); isov[i].q=(PREC_ATM *)realloc(isov[i].q, nrad*sizeof(PREC_ATM)); isov[i].n=nrad; } } //Skip comments and read next line while((rc=fgetupto_err(lp=line,maxline,fp,&atmerr,atmfilename,lines++)) =='#'||rc=='\n'); //if it is end of file, stop loop if(!rc) break; tmp=rads->v[r]=strtod(lp,&lp2)+zerorad; checkposvalue(tmp,1,lines); if(lp==lp2) invalidfield(line, lines, 1, "radius"); tmp=at->atm.p[r]=strtod(lp2,&lp); checkposvalue(tmp,2,lines); if(lp==lp2) invalidfield(line, lines, 2, "pressure"); tmp=at->atm.t[r]=strtod(lp,&lp2); checkposvalue(tmp,3,lines); if(lp==lp2) invalidfield(line, lines, 3, "temperature"); //variables to be used by factor (except ieq which is general) int ieq, feq; double ref; _Bool otherfct[neiso]; memset(otherfct,0,sizeof(otherfct)); //now read abundances for every isotope, but don't process //factorized elements. Because they might be proportional to a fixed //element which is set below. for(i=0;i<at->n_aiso;i++){ ieq=isoeq[i]; switch(isodo[i]){ case fixed: if(!r){ isov[ieq].q[0]=askforposd(" %s abundance for isotope %s: " ,at->mass?"Mass":"Number" ,iso->isof[ieq].n); if(isov[ieq].q[0]>=1){ fprintf(stderr," Abundance for any single isotope has to be" " less than one\n Try Again!\n"); i--; } } else isov[ieq].q[r]=isov[ieq].q[0]; break; case factor: //don't process yet those that will use whatever abundance is left //to complete unity feq=ieq; ieq=isoprop[feq].eq; if(strcasecmp(isoprop[feq].t,"other")==0){ otherfct[ieq]=1; continue; } //find the reference value ref=findfactq(isoprop[feq].t,iso->isof,isov,neiso,r); isov[ieq].q[r]=isoprop[feq].f*ref; break; default: transiterror(TERR_CRITICAL, "Trying to read isotope in readatmfile() which is\n" "not 'fixed', 'atmfile', 'ignored', nor 'factor'.\n" ); exit(EXIT_FAILURE); break; case atmfile: case ignore: transitASSERT(ieq<0 || (isodo[i]==ignore&&ieq>=nfonly) || (isodo[i]!=ignore&&ieq>=iso->n_e), "Assertion failed in file %s, line %i: %i!=[0,%i].\n" " Fonly: %i\n" ,__FILE__, __LINE__, isoeq[i], isodo[i]==ignore?nfonly:iso->n_e-1, isodo[i]==ignore); //Read the abundance of the new element. There are two ways: //If processing one of the factor only elements if(isodo[i]==ignore) tmp=fonly[ieq].q=strtod(lp2,&lp); //otherwise if this element is going to be considered else tmp=isov[ieq].q[r]=strtod(lp2,&lp); checkposvalue(tmp, i+4, lines); if(lp==lp2) invalidfield(line, lines, 4+i, "isotope abundance"); lp2=lp; break; } } //process factorized elements that will take care of the rest of the //atmosphere ref=1-addq(isov,iso->isodo,otherfct,neiso,r); for(i=0;i<at->n_aiso;i++) if(isodo[i]==factor){ feq=isoeq[i]; ieq=isoprop[feq].eq; if(otherfct[ieq]) isov[ieq].q[r]=isoprop[feq].f*ref; } //calculate mean molecular mass and check whether abundances add up //correctly, up to round off error of course sumq=checkaddmm(at->mm+r,r,isov,iso->isof,neiso,at->mass,iso->isodo); if((int)(sumq*ROUNDOFF+0.5)<(int)(allowq*ROUNDOFF+0.5)) transiterror(TERR_WARNING, "In radius %g(%i: %g in file), abundances\n" "don't add up to 1: %.9g\n" ,at->rads.v[r],r,at->rads.v[r]-zerorad,sumq); //Calculate densities for(i=0;i<neiso;i++) isov[i].d[r]=stateeqnford(at->mass, isov[i].q[r], at->mm[r], iso->isof[i].m, at->atm.p[r]*at->atm.pfct, at->atm.t[r]*at->atm.tfct); r++; } //reduce array to the right number of radii rads->n=nrad=r; rads->v=(PREC_ATM *)realloc(rads->v,nrad*sizeof(PREC_ATM)); at->atm.t= (PREC_ATM *)realloc(at->atm.t,nrad*sizeof(PREC_ATM)); at->atm.p= (PREC_ATM *)realloc(at->atm.p,nrad*sizeof(PREC_ATM)); at->mm=(double *)realloc(at->mm,nrad*sizeof(double)); for(i=0;i<neiso;i++){ isov[i].d=(PREC_ATM *)realloc(isov[i].d, nrad*sizeof(PREC_ATM)); isov[i].q=(PREC_ATM *)realloc(isov[i].q, nrad*sizeof(PREC_ATM)); isov[i].n=nrad; } //free arrays that were used only to get the factorizing elements free(fonly); return nrad; }
/* \fcnfh Read radius, pressure, temperature, and abundances and store it into at_data of transit. Calculate mean molecular mass and densities. Detailed: Read and store radius, pressure, and temperature from file. Read abundances for each (non other-factor) isotope. Sum fractional abundances. Calculate ramaining (other-factor) abundances. Calculate mean molecular mass per radius. Calculate densities per isotope at each radius. Returns: number of sample radius */ int readatmfile(FILE *fp, /* Atmospheric file */ struct transit *tr, /* transit struct */ struct atm_data *at, /* Atmosphere struct */ prop_samp *rads, /* Radius sampling */ int nrad, /* Size of allocated radius array */ PREC_ZREC *f_remainder){ /* Remainder molecules' factor */ transitprint(1, verblevel, "Start reading abundances.\n"); /* Find abundance related quantities for each radius */ int lines = at->begline; PREC_NREC r = 0; /* Radius index (number of radii being read) */ char rc; /* File reading output */ float allowq = 1 - tr->allowrq; int nabundances; /* Number of abundances in list */ double sumq; /* Sum of abundances per line */ char line[maxline], *lp, *lp2; prop_mol *molec = at->molec; struct molecules *mol = tr->ds.mol; int i, j; /* Auxiliary for-loop indices */ /* Variables to be used by factor (except ieq which is general): */ /* Count the number of abundances in each line: */ fseek(fp, at->begpos, SEEK_SET); /* Go to position where data begins */ /* Skip comments: */ while((rc=fgetupto_err(lp=line, maxline, fp, &atmerr, atmfilename, lines++)) =='#' || rc=='\n'); /* Count values per line: */ nabundances = countfields(lp, ' ') - 3; /* Subtract rad, p, and T columns */ fseek(fp, at->begpos, SEEK_SET); /* Go to position where data begins */ while(1){ /* Reallocate if necessary: */ if(r==nrad){ nrad <<= 1; rads->v = (PREC_ATM *)realloc(rads->v, nrad*sizeof(PREC_ATM)); at->atm.t = (PREC_ATM *)realloc(at->atm.t, nrad*sizeof(PREC_ATM)); at->atm.p = (PREC_ATM *)realloc(at->atm.p, nrad*sizeof(PREC_ATM)); at->mm = (double *)realloc(at->mm, nrad*sizeof(double)); for(i=0; i<at->n_aiso; i++){ molec[i].d = (PREC_ATM *)realloc(molec[i].d, nrad*sizeof(PREC_ATM)); molec[i].q = (PREC_ATM *)realloc(molec[i].q, nrad*sizeof(PREC_ATM)); molec[i].n = nrad; } } /* Skip comments and read next line: */ while((rc=fgetupto_err(lp=line, maxline, fp, &atmerr, atmfilename, lines++)) =='#' || rc=='\n'); /* If it is end of file, stop loop: */ if(!rc) break; /* Read and store radius, pressure, and temperature from file: */ rads->v[r] = strtod(lp, &lp2) + zerorad; /* Radius */ checkposvalue(rads->v[r], 1, lines); /* Check value is positive */ if(lp==lp2) invalidfield(line, lines, 1, "radius"); at->atm.p[r] = strtod(lp2, &lp); /* Pressure */ checkposvalue(at->atm.p[r], 2, lines); if(lp==lp2) invalidfield(line, lines, 2, "pressure"); at->atm.t[r] = strtod(lp, &lp2); /* Temperature */ checkposvalue(at->atm.t[r], 3, lines); if(lp==lp2) invalidfield(line, lines, 3, "temperature"); /* Read abundances for each isotope. Keep reading-in values while there are numbers in line: */ for(i=0, sumq=0; i<nabundances; i++){ lp = lp2; /* Read the abundance of the isotope: */ molec[i].q[r] = strtod(lp, &lp2); if (r==0) transitprint(30, verblevel, "density[%d, %li]: %.9f.\n", i, r, molec[i].q[r]); sumq += molec[i].q[r]; /* Add the abundances */ checkposvalue(molec[i].q[r], i+4, lines); /* Check that tmp is positive */ if(lp==lp2) invalidfield(line, lines, 4+i, "isotope abundance"); } /* Remainder of the sum of abundances: */ /* Set abundance of remainder molecules: */ for(j=0; i < at->n_aiso; i++, j++) molec[i].q[r] = f_remainder[j]*(1-sumq); transitASSERT(i!=at->n_aiso, "The line %s of file %s contains %d abundance " "values, when there were %d expected.\n", __LINE__, __FILE__, i, at->n_aiso); /* Calculate mean molecular mass and check whether abundances add up to one (within roundoff error): */ sumq = checkaddmm(at->mm+r, r, molec, mol, at->n_aiso, at->mass); if((int)(sumq*ROUNDOFF+0.5)<(int)(allowq*ROUNDOFF+0.5)) transiterror(TERR_WARNING, "In radius %g (%i: %g in file), abundances " "don't add up to 1: %.9g\n", at->rads.v[r], r, at->rads.v[r]-zerorad, sumq); /* Calculate densities using ideal gas law: */ if (r>=0){ transitprint(30, verblevel, "Abund: %.9f, mmm: %.3f, mass: %.3f, " "p: %.3f, T: %.3f.\n", molec[2].q[r], at->mm[r], mol->mass[2], at->atm.p[r]*at->atm.pfct, at->atm.t[r]*at->atm.tfct); } for(i=0; i<at->n_aiso; i++) molec[i].d[r] = stateeqnford(at->mass, molec[i].q[r], at->mm[r], mol->mass[i], at->atm.p[r]*at->atm.pfct, at->atm.t[r]*at->atm.tfct); transitprint(30, verblevel, "dens[%2li]: %.14f, ", r, molec[2].d[r]); r++; } /* Re-allocate arrays to final size (nrad): */ rads->n = nrad = r; rads->v = (PREC_ATM *)realloc(rads->v, nrad*sizeof(PREC_ATM)); at->atm.t = (PREC_ATM *)realloc(at->atm.t, nrad*sizeof(PREC_ATM)); at->atm.p = (PREC_ATM *)realloc(at->atm.p, nrad*sizeof(PREC_ATM)); at->mm = (double *)realloc(at->mm, nrad*sizeof(double)); for(i=0; i<at->n_aiso; i++){ molec[i].d = (PREC_ATM *)realloc(molec[i].d, nrad*sizeof(PREC_ATM)); molec[i].q = (PREC_ATM *)realloc(molec[i].q, nrad*sizeof(PREC_ATM)); molec[i].n = nrad; } /* Free arrays that were used only to get the factorizing elements: */ free(fonly); nfonly = 0; return nrad; }