/* \fcnfh Print (to file or stdout) the emergent intensities as function of wavelength for each angle) */ void printintens(struct transit *tr){ long int i, w; /* Auxilliary for-loop indices */ FILE *outf = stdout; /* Output file pointer */ PREC_RES *angles = tr->angles; /* Array of incident angles */ int an = tr->ann; /* Number of incident angles */ prop_samp *wn = &tr->wns; /* Wavenumber sample */ long int wnn = wn->n; /* Number of wavenumber samples */ /* Intensity for all angles and all wn: */ PREC_RES **intens_grid = tr->ds.intens->a; /* Adds string to the output files to differentiate between outputs */ char our_fileName[512]; /* Open file: */ if (tr->f_outintens && tr->f_outintens[0] != '-'){ strncpy(our_fileName, tr->f_outintens, 512); outf = fopen(our_fileName, "w"); } else{ transitprint(1, verblevel, "No intensity file.\n"); return; } transitprint(1, verblevel, "\nPrinting intensity in '%s'\n", tr->f_outintens ? our_fileName:"standard output"); /* Print the header: */ //fprintf(outf, "#wvl [um]%*s", 6, " "); //for(i=0; i < an; i++) // fprintf(outf, "I[%4.1lf deg]%*s", angles[i], 7, " "); //fprintf(outf, "[erg/s/cm/sr]\n"); /* Print the header: */ fprintf(outf, "#wvl %*s", 10, " "); for(i=0; i < an; i++) fprintf(outf, "I[%4.1lf deg]%*s", angles[i], 7, " "); fprintf(outf, "\n#[um]%*s", 10, " "); for(i=0; i < an; i++) fprintf(outf, "[erg/s/cm/sr]%*s", 5, " "); fprintf(outf, "\n"); /* Fills out each column with the correct output intensity */ for(w=0; w<wnn; w++){ fprintf(outf, "%-15.10g", 1e4/(tr->wns.v[w]/tr->wns.fct)); for(i=0; i < an; i++) fprintf(outf, "%-18.9g", intens_grid[i][w]); fprintf(outf,"\n"); } /* Closes the file: */ fclose(outf); return; }
/* \fcnfh Print (to file or stdout) the emergent intensity as function of wavenumber (and wavelength) */ void printflux(struct transit *tr){ FILE *outf=stdout; /* The flux per wavenumber array: */ PREC_RES *Flux = tr->ds.out->o; int rn; /* Adds string to the output files to differentiate between outputs: */ char our_fileName[512]; strncpy(our_fileName, tr->f_outflux, 512); //strcat(our_fileName, ".-Flux"); /* Open file: */ if(tr->f_outflux && tr->f_outflux[0] != '-') outf = fopen(our_fileName, "w"); transitprint(1, verblevel, "\nPrinting flux in '%s'\n", tr->f_outflux ? our_fileName:"standard output"); /* Print the header: */ fprintf(outf, "#wvl [um]%*sFlux [erg/s/cm]\n", 6, " "); /* Print wavelength and flux: */ for(rn=0; rn < tr->wns.n; rn++) fprintf(outf, "%-15.10g%-18.9g\n", 1e4/(tr->wns.v[rn]/tr->wns.fct), Flux[rn]); /* Closes the file: */ fclose(outf); return; }
/* \fcnfh Print (to file or stdout) the modulation as function of wavelength */ void printmod(struct transit *tr){ FILE *outf = stdout; struct outputray *outray = tr->ds.out; int rn; /* Open file: */ if(tr->f_out && tr->f_out[0] != '-') outf = fopen(tr->f_out, "w"); transitprint(1, verblevel, "\nPrinting in-transit/out-transit modulation in '%s'.\n", tr->f_out?tr->f_out:"standard output"); /* Print: */ char wlu[20], /* Wavelength units name */ wnu[20]; /* Wavenumber units name (the inverse, actually) */ long nsd = (long)(1e6); /* Get wavenumber units name: */ if((long)(nsd*tr->wns.fct)==nsd) strcpy(wnu, "cm"); else if((long)(nsd*1e-1*tr->wns.fct)==nsd) strcpy(wnu, "mm"); else if((long)(nsd*1e-4*tr->wns.fct)==nsd) strcpy(wnu, "um"); else if((long)(nsd*1e-7*tr->wns.fct)==nsd) strcpy(wnu, "nm"); else if((long)(nsd*1e-8*tr->wns.fct)==nsd) strcpy(wnu, "A "); else sprintf(wnu, "%6.1g cm", 1/tr->wns.fct); /* Get wavelength units name: */ if((long)(nsd*tr->wavs.fct)==nsd) strcpy(wlu, "cm"); else if((long)(nsd*1e1*tr->wavs.fct)==nsd) strcpy(wlu, "mm"); else if((long)(nsd*1e4*tr->wavs.fct)==nsd) strcpy(wlu, "um"); else if((long)(nsd*1e7*tr->wavs.fct)==nsd) strcpy(wlu, "nm"); else if((long)(nsd*1e8*tr->wavs.fct)==nsd) strcpy(wlu, "A "); else sprintf(wlu, "%8.1g cm", tr->wavs.fct); /* Print header: */ fprintf(outf, "#wvn %s-1%*s wvl %s%*s modulation\n", wnu, (int)(9-strlen(wnu)), "", wlu, (int)(12-strlen(wlu)),""); /* Print wavenumber, wavelength, and modulation at each wavenumber: */ for(rn=0; rn<tr->wns.n; rn++) fprintf(outf, "%-17.9g%-17.9g%-18.9g\n", tr->wns.v[rn]/tr->wns.fct, 1/tr->wavs.fct/tr->wns.v[rn]/tr->wns.fct, outray->o[rn]); fclose(outf); return; }
/* \fcnfh Printout for modulation as function of wavelength */ void printmod(struct transit *tr) { FILE *outf=stdout; struct outputray *outray=tr->ds.out; int rn; //open file if(tr->f_out&&tr->f_out[0]!='-') outf=fopen(tr->f_out,"w"); transitprint(1,verblevel, "\nPrinting in-eclipse/out-eclipse ratio for requested\n" " conditions in '%s'\n" ,tr->f_out?tr->f_out:"standard output"); //print! char wlu[20],wnu[20]; long nsd=(long)(1e6); if((long)(nsd*tr->wns.fct)==nsd) strcpy(wnu,"cm"); else if((long)(nsd*1e-1*tr->wns.fct)==nsd) strcpy(wnu,"mm"); else if((long)(nsd*1e-4*tr->wns.fct)==nsd) strcpy(wnu,"um"); else if((long)(nsd*1e-7*tr->wns.fct)==nsd) strcpy(wnu,"nm"); else if((long)(nsd*1e-8*tr->wns.fct)==nsd) strcpy(wnu,"a"); else sprintf(wnu,"%6.1g cm",1/tr->wns.fct); if((long)(nsd*tr->wavs.fct)==nsd) strcpy(wlu,"cm"); else if((long)(nsd*1e1*tr->wavs.fct)==nsd) strcpy(wlu,"mm"); else if((long)(nsd*1e4*tr->wavs.fct)==nsd) strcpy(wlu,"um"); else if((long)(nsd*1e7*tr->wavs.fct)==nsd) strcpy(wlu,"nm"); else if((long)(nsd*1e8*tr->wavs.fct)==nsd) strcpy(wlu,"a"); else sprintf(wlu,"%8.1g cm",tr->wavs.fct); fprintf(outf, "#wvn[%s-1]%*swvl[%s]%*smodulation\n" ,wnu,(int)(9-strlen(wnu)),"",wlu,(int)(12-strlen(wlu)),""); for(rn=0; rn<tr->wns.n; rn++) fprintf(outf,"%-17.9g%-17.9g%-18.9g\n" ,tr->wns.v[rn]/tr->wns.fct ,1/tr->wavs.fct/tr->wns.v[rn]/tr->wns.fct, outray->o[rn]); fclose(outf); return; }
/* \fcnfh Check whether isotope 'name' found in atmosphere file do correspond to an isotope in the lineinfofile for which extinction is going to be calculated */ static void isisoline(char *name, /* Isotope's name */ PREC_ATM mass, /* Isotope's mass */ int *isoeq, /* Isotope's lineinfo position to be stored */ enum isodo atisodo, /* Action for current isotope */ prop_isof *isof, /* Info from lineinfo file */ enum isodo *isodo, /* Action to be taken storage */ PREC_NREC nliso) /* Number of isotopes in the lineinfo */ { PREC_NREC i; //Note that here, even though the isotope might be ignored, it will //stilll have an equivalent lineiso associated if one is found. //\refline{isodbassoc} for(i=0;i<nliso;i++){ if(strcasecmp(name,isof[i].n)==0){ *isoeq=i; if(isolineinatm[i]) transiterror(TERR_SERIOUS, "Isotope %s has been defined more than once in the\n" "atmosphere file.\n" ,name); isolineinatm[i]=1; if(isodo[i]!=ignore) isodo[i]=atisodo; if(isodo[i]==ignore) transitprint(2,verblevel, "Ignoring isotope %s (%g AMU)\n" ,isof[i].n,isof[i].m); else if(isof[i].m!=mass&&mass!=0) transiterror(TERR_WARNING, "Mass of isotope %s, is not the same\n" "in the atmosphere file %s(%g) than in\n" "the transition info file(%g)\n" ,name,atmfilename,mass, isof[i].m); break; } } if(*isoeq==-1&&atisodo==ignore) nfonly++; }
/* \fcnfh Ask mass and name for new isotopes */ void askonemn(struct onept *onept, /* user given values are going to be stored here */ prop_isof *isof, /* Also stored here for use by the program */ int n, /* number of new isotopes, only partial info for these is requested */ int nf) /* Number of isotopes with full info */ { int i; char rc; //Allocate room in 'onept'. Room in 'isof' should be already be //allocated onept->m=(PREC_ZREC *)calloc(n,sizeof(PREC_ZREC)); onept->n=(char **)calloc(n,sizeof(char *)); onept->n[0]=(char *)calloc(n*maxeisoname,sizeof(char)); //For each isotope ask for mass and name for(i=0; i<n; i++) { onept->n[i]=onept->n[0]+i*maxeisoname; while(1) { fprintf(stderr, " Mass and name of extra isotope #%i (Order mandatory, " "e.g. 12.011Carbon):\n " ,i+1); onept->m[i]=isof[i+nf].m=readds(stdin,&rc, onept->n[i],maxeisoname-1); strcpy(isof[i+nf].n,onept->n[i]); if(rc=='q') { transitprint(0,verblevel,"User interrupt!\n"); exit(EXIT_SUCCESS); } if(onept->m[i]<=0) fprintf(stderr," Invalid value %g, has to be positive\n",onept->m[i]); else if(!rc) break; fprintf(stderr,"Try again!\n"); } } }
/* DEF */ int emergent_intens(struct transit *tr){ /* Transit structure */ static struct outputray st_out; /* Output structure */ tr->ds.out = &st_out; /* Initial variables: */ long w; prop_samp *rad = &tr->rads; /* Radius array pointer */ prop_samp *wn = &tr->wns; /* Wavenumber array pointer */ long int wnn = wn->n; /* Wavenumbers */ ray_solution *sol = tr->sol; /* Eclipse ray solution pointer */ /* Reads angle index from transit structure */ long int angleIndex = tr->angleIndex; /* Intensity for all angles and all wn */ PREC_RES **intens_grid = tr->ds.intens->a; /* Intensity array for one angle all wn: */ PREC_RES *out = intens_grid[angleIndex]; /* Reads the tau array from transit structure */ struct optdepth *tau = tr->ds.tau; /* Integrate for each wavelength: */ transitprint(4, verblevel, "Integrating over wavelength.\n"); /* Printing process variable: */ int nextw = wn->n/10; /* Calculates the intensity integral at each wavenumber: */ for(w=0; w<wnn; w++){ //transitprint(1, 2, "[%li]", w); //if (w == 1612 || w == 1607){ // transitprint(1, 2, "\nTau (%.3f) [%li,%li]= np.array([", wn->v[w], // rad->n, tau->last[w]); // //for (int ii=rad->n-1; ii>tau->last[w]; ii--) // for (int ii=0; ii<rad->n; ii++) // transitprint(1, 2, "%.4e, ", tau->t[w][ii]); // transitprint(1, 2, "])\n"); //} //if (fabs(wn->v[w] - 1844.59) < 0.005) // transitprint(1, verblevel, "\nWavenumber index is: %li\n", w); /* Calculate the intensity spectrum (call to eclipse_intens): */ out[w] = sol->spectrum(tr, tau->t[w], wn->v[w], tau->last[w], tau->toomuch, rad); /* Prints to screen the progress status: */ if(w == nextw){ nextw += wn->n/10; transitprint(10, verblevel, "%i%% ", (10*(int)(10*w/wn->n+0.9999999999))); } } transitprint(4, verblevel, "\nDone.\n"); /* Sets progress indicator, and prints output: */ tr->pi |= TRPI_MODULATION; /* FINDME: this is not a modulation calculation */ if (tr->angleIndex == tr->ann-1) printintens(tr); return 0; }
/* \fcnfh get number of isotopes from file and set index @returns number of lines read */ int getmnfromfile(FILE *fp, struct atm_data *at, struct transit *tr, int nmb) { char line[maxline],*lp; int ison=0,i; struct isotopes *iso=tr->ds.iso; enum isodo *isodo=iso->isodo; //Set variable to handle proportional to isotopes int ipi=0,ipa=at->ipa=4; isolineinatm=(_Bool *)calloc(iso->n_i,sizeof(_Bool)); isoprop=(struct atm_isoprop *)calloc(ipa,sizeof(struct atm_isoprop)); at->begline=0; enum isodo atisodo; at->isodo = (enum isodo *)calloc(nmb,sizeof(enum isodo)); at->isoeq = (int *) calloc(nmb,sizeof(int)); at->m = (PREC_ZREC *) calloc(nmb,sizeof(PREC_ZREC)); at->n = (char **) calloc(nmb,sizeof(char *)); at->n[0] = (char *) calloc(nmb*maxeisoname,sizeof(char)); at->isoeq[0]=-1; for(i=1;i<nmb;i++){ at->n[i]=at->n[0]+i*maxeisoname; at->isoeq[i]=-1; } //while t,p data doesn't start, check for the various modifiers while(1){ switch(fgetupto_err(line,maxline,fp,&atmerr,atmfilename, at->begline++)){ case '\n': //Ignore comments and case '#': // blank lines continue; case 0: //Error if EOF transiterror(TERR_SERIOUS|TERR_ALLOWCONT, "readatminfo:: EOF unexpectedly found at line %i\n" "of file %s while no t,p data points have been read\n" ,at->begline,atmfilename); exit(EXIT_FAILURE); continue; case 'q': //Whether is mass or number abundance lp=line+1; while(*lp++==' '); lp--; switch(*lp|0x20){ case 'n': at->mass=0; break; case 'm': at->mass=1; break; default: transiterror(TERR_SERIOUS, "'q' option in the atmosphere file can only be followed\n" "by 'm' (for abundances by mass) or 'n' (for abundances by\n" "number). '%s' is invalid.\n" ,line); break; } continue; case 'z': //Zero radius value zerorad=atof(line+1); continue; case 'f': //An isotope is to be taken as //proportional to other. lp=line+1; while(*lp==' '||*lp=='\t') lp++; if(ipi==ipa) isoprop=(struct atm_isoprop *)realloc(isoprop,(ipa<<=1)* sizeof(struct atm_isoprop)); isoprop[ipi].m=getds(lp,0,isoprop[ipi].n,maxeisoname-1); //skip over recently read field, and go to next field. lp=nextfield(lp); //skip an optional equal '=' sign if(*lp=='=' && lp[1]==' ') lp=nextfield(lp); //get factor, which has to be between 0 and 1 isoprop[ipi].f=strtod(lp,NULL); if(isoprop[ipi].f<0 ) transiterror(TERR_CRITICAL, "Abundance ratio has to be positive in atmosphere\n" "file '%s' in line: %s" ,atmfilename,line); lp=nextfield(lp); //get name of reference and increase index i=0; while(*lp) isoprop[ipi].t[i++]=*lp++; isoprop[ipi].t[i]='\0'; //now check if that isotope is one of the given in the lineinfo //file isoprop[ipi].eq=-1; isisoline(isoprop[ipi].n,isoprop[ipi].m,&isoprop[ipi].eq,factor, iso->isof,isodo,iso->n_i); //advance index and go for the next line ipi++; continue; case 'u': //Change factorization of radius, temp, //or press switch(line[1]){ case 'r': at->rads.fct=atof(line+2); break; case 'p': at->atm.pfct=atof(line+2); break; case 't': at->atm.tfct=atof(line+2); break; default: transiterror(TERR_SERIOUS, "Invalid unit factor indication in atmosphere file\n"); exit(EXIT_FAILURE); } continue; case 'n': //Name or identifier for file data storename(at,line+1); continue; case 'i': //Isotope information lp=line+1; while(*lp==' '||*lp=='\t') lp++; //'i' has to come before 'f' if(ipi) transiterror(TERR_CRITICAL, "In line '%s'.\n" " 'f' lines have to come after all the 'i' lines in\n" " atmosphere file '%s'" ,line,atmfilename); //for each field while(*lp){ atisodo=atmfile; //Allocate if necessary if(ison==nmb){ nmb<<=1; at->isodo = (enum isodo *)realloc(at->isodo,nmb*sizeof(enum isodo)); at->isoeq = (int *) realloc(at->isoeq,nmb*sizeof(int)); at->m = (PREC_ZREC *) realloc(at->m, nmb*sizeof(PREC_ZREC)); at->n = (char **) realloc(at->n, nmb*sizeof(char *)); at->n[0] = (char *) realloc(at->n[0], nmb*maxeisoname*sizeof(char)); for(i=1;i<nmb;i++) at->n[i]=at->n[0]+i*maxeisoname; for(i=nmb/2;i<nmb;i++) at->isoeq[i]=-1; } //get mass and name, checking that is correct. First see if this //isotope wants to be ignored. if(*lp=='!'){ lp++; atisodo=ignore; } at->m[ison]=getds(lp,0,at->n[ison],maxeisoname-1); if(at->m[ison]<0||at->n[ison]=='\0'){ transiterror(TERR_SERIOUS, "Invalid field in file %s, line %i while reading isotope" " info at:\n%s\n" ,atmfilename,at->begline,lp); } //now check if that isotope is one of the given in the lineinfo //file isisoline(at->n[ison],at->m[ison],at->isoeq+ison,atisodo, iso->isof,isodo,iso->n_i); at->isodo[ison++]=atisodo; //skip over recently read field, and go to next field. while(*lp!=' '&&*lp!='\0') lp++; while(*lp==' '||*lp=='\t') lp++; } continue; default: //T,P seems to be starting break; } break; } transitprint(3,verblevel, "Read all keywords in atmosphere file without problems\n"); //Check if there was at least an isotope identification and allocate new //arrays if(!ison) transiterror(TERR_SERIOUS, "No isotopes were found in atmosphere file, make sure to\n" "specify them in a line starting with the letter 'i'.\n" "First non-comment line read:\n%s\n" ,line); at->begpos=ftell(fp)-strlen(line)-1; //shorten extra length of arrays fonly=(struct fonly *)calloc(nfonly,sizeof(struct fonly)); at->ipa=ipa=ipi; isoprop=(struct atm_isoprop *)realloc(isoprop,ipa* sizeof(struct atm_isoprop)); //Makes at arrays bigger, so that they can hold the factorized values. nmb = at->n_aiso = ison + ipa; at->isodo = (enum isodo *)realloc(at->isodo,nmb*sizeof(enum isodo) ); at->isoeq = (int *) realloc(at->isoeq,nmb*sizeof(int) ); at->m = (PREC_ZREC *) realloc(at->m, nmb*sizeof(PREC_ZREC) ); at->n = (char **) realloc(at->n, nmb*sizeof(char *) ); at->n[0] = (char *) realloc(at->n[0], nmb*maxeisoname*sizeof(char)); for(i=1;i<nmb;i++) at->n[i] = at->n[0] + i * maxeisoname; //initialize values for the factorized elements for(i=ison;i<nmb;i++){ strncpy(at->n[i],isoprop[i-ison].n,maxeisoname-1); at->n[i][maxeisoname-1] = '\0'; at->isoeq[i] = i-ison; at->m[i] = isoprop[i-ison].m; at->isodo[i] = factor; } //Resolve what to do with those isotopes that appear in the transition //database, but not in the atmosphere file. at->n_niso = checknonmatch(tr,at,isodo); //Set full isotope info in the transit structure nmb = iso->n_i + at->n_niso; iso->isodo = (enum isodo *)realloc(iso->isodo, nmb*sizeof(enum isodo)); iso->isof = (prop_isof *)realloc(iso->isof, nmb*sizeof(prop_isof)); iso->isof[iso->n_i].n = (char *)realloc(iso->isof[iso->n_i].n, (nmb-iso->n_i)*maxeisoname* sizeof(char)); for(i=1;i<nmb-iso->n_i;i++) iso->isof[iso->n_i+i].n = iso->isof[iso->n_i].n + i * maxeisoname; //Look for isotopes who have not been associated and see whether they //are supposed to be ignored. nmb = iso->n_i; ipi = 0; int lineignore=0; for(i=0 ; i<ison+ipa ; i++) //If the isotope is not associated to the linedb isotopes, then //associate it. Note that isotopes in linedb that are ignored will //be associated (see comments for Line \label{isodbassoc}). Hence //they won't be detected in this IF. Factor isotopes will also be //associated, and will be handled below if(at->isoeq[i] == -1){ //If they are not going to be ignored then associate them with the //following index available of post linedb isotopes. if(at->isodo[i] != ignore){ at->isoeq[i] = nmb; iso->isodo[nmb] = at->isodo[i]; iso->isof[nmb].m = at->m[i]; strcpy(iso->isof[nmb++].n, at->n[i]); } //otherwise, they might only be used as a reference to factor. else{ at->isoeq[i] = ipi; strcpy(fonly[ipi++].n, at->n[i]); } } //Just count the number of ignored isotopes that belonged to the line //isotopes. else if(at->isodo[i] == ignore) lineignore++; //If there is factor isotopes else if(at->isodo[i] == factor && isoprop[at->isoeq[i]].eq == -1){ if(at->isodo[i]==ignore) transiterror(TERR_CRITICAL, "Trying to ignore an factor isotope, that is not\n" "posible.\n"); isoprop[at->isoeq[i]].eq = nmb; iso->isodo[nmb] = at->isodo[i]; iso->isof[nmb].m = at->m[i]; strcpy(iso->isof[nmb++].n, at->n[i]); } //Reduce the array to get rid of nonline-ignored isotopes. (isov has //not even been allocated yet) iso->n_e = nmb; iso->isodo = (enum isodo *)realloc(iso->isodo, nmb*sizeof(enum isodo)); iso->isof = (prop_isof *)realloc(iso->isof, nmb*sizeof(prop_isof)); iso->isof[iso->n_i].n = (char *)realloc(iso->isof[iso->n_i].n, nmb*maxeisoname*sizeof(char)); for(i=1;i<nmb-iso->n_i;i++) iso->isof[iso->n_i+i].n = iso->isof[iso->n_i].n + i * maxeisoname; //Check that everything makes sense double cumulother=0; for(i=0 ; i<at->n_aiso ; i++) if(at->isodo[i]==factor){ int feq=at->isoeq[i]; if(strcasecmp(isoprop[feq].n,"other")==0) cumulother+=isoprop[feq].f; } //It doesn't make sense for cumulother to be anything different from //unity (except round-off error): you want to associate the //remainder of the atmosphere to some isotopic properties. if( cumulother!=0 && (int)(cumulother*ROUNDOFF+0.5)!=(int)(ROUNDOFF+0.5) ) transiterror(TERR_SERIOUS, "If you are specifying isotopes proportional to 'other'\n" "you have to complete unity (%g). It doesn't make sense\n" "otherwise\n" ,cumulother); transitASSERT(nmb+nfonly!=ison+ipa, "Oooops, number of ignored-nonline elements (%i), plus the\n" "number of ignored-line elements(%i), plus the number of\n" "nonignored (%i), doesn't match the number of elements\n" "found in fields 'i'(%i) and 'f'(%i) of the atmosphere\n" "file '%s'\n" ,nfonly,lineignore,nmb-lineignore,ison,ipa,atmfilename); transitASSERT(nmb!=iso->n_e, "Uyuyuyuyu! Problem in file %s, line %i,\n" "assertion failed: %i != %i!!\n" ,__FILE__,__LINE__,nmb,iso->n_e); //free unused array, store factor info in at structure and return line //where T,P start free(isolineinatm); at->isoprop=isoprop; return at->begline; }
/* \fcnfh Obtains the quantity that is observable, but before being convolved to telescope resolution @returns 0 on success -1 if impact parameter sampling is not equispaced */ int modulation(struct transit *tr) /* Main structure */ { static struct outputray st_out; tr->ds.out=&st_out; transitcheckcalled(tr->pi,"modulation",3, "tau",TRPI_TAU, "makeipsample",TRPI_MAKEIP, "makewnsample",TRPI_MAKEWN ); //initial variables and check that impact parameters was a monospaced //array. Stop otherwise. long w; prop_samp *ip=&tr->ips; prop_samp *wn=&tr->wns; transit_ray_solution *sol=tr->sol; if(ip->d==0&&sol->monoip) { transiterror(TERR_SERIOUS|TERR_ALLOWCONT, "To compute %s modulation, the impact parameter has to\n" "be an equispaced array\n" ,sol->name); return -1; } //output and geometry variables. PREC_RES *out=st_out.o=(PREC_RES *)calloc(wn->n,sizeof(PREC_RES)); struct geometry *sg=tr->ds.sg; struct optdepth *tau=tr->ds.tau; //set time to the user hinted default, and other user hints setgeom(sg,HUGE_VAL,&tr->pi); const int modlevel=tr->modlevel=tr->ds.th->modlevel; //integrate for each wavelength transitprint(1,verblevel, "\nIntegrating for each wavelength...\n"); int nextw=wn->n/10; for(w=0; w<wn->n; w++) { out[w]=sol->obsperwn(tau->t[w],tau->last[w],tau->toomuch, ip,sg,modlevel); if(out[w]<0) { switch(-(int)out[w]) { case 1: if(modlevel==-1) transiterror(TERR_SERIOUS, "Optical depth didn't reach limiting %g at wavenumber %g[cm-1]\n" " (Only reached %g)." " Cannot use critical radius technique (-1)\n" ,tau->toomuch,tau->t[w][tau->last[w]],wn->v[w]*wn->fct); default: transiterror(TERR_SERIOUS, "There was a problem while calculating modulation\n" " at wavenumber %g[cm-1]. Error code %i\n" ,wn->v[w]*wn->fct,(int)out[w]); break; } exit(EXIT_FAILURE); } if(w==nextw) { nextw+=wn->n/10; transitprint(2,verblevel, "%i%%\r" ,(10*(int)(10*w/wn->n+0.9999999999))); } } transitprint(1,verblevel," done\n"); //frees no longer needed memory. freemem_idexrefrac(tr->ds.ir,&tr->pi); freemem_extinction(tr->ds.ex,&tr->pi); freemem_tau(tr->ds.tau,&tr->pi); //set progress indicator, and print output tr->pi&=TRPI_MODULATION; printmod(tr); return 0; }
void getmass(struct atm_data *at, struct molecules *mol){ int nmol = at->n_aiso; /* FINDME: De-hardcode filename, put it in tr.ds.at: */ char *filename = "../inputs/molecules.dat"; FILE *elist; /* Atomic masses, names, alias names, alias molecules, and sizes: */ double *amass, /* Atomic masses form list */ *radius; /* Molecular radii from list */ char **aname, /* Atomic symbol names */ **rname, /* Molecules names for listed radii */ **alias, /* Alias of names given in atmfile */ **amol, /* Corresponding molecule for alias */ **elements; /* Elements in a molecule */ int natoms = 92, /* Number of listed atoms */ nalias = 2, /* Number of listed alias names */ nradii = 14, /* Number of listed radii */ namelen = 3, /* Atomic symbol name length */ maxlinelen = 501, molnamelen, /* Length of a molecule name */ elen, /* Element name length */ iatom, /* Atom's index from list */ ielement, /* Element counter in a molecule */ i, j; /* Auxiliary for-loop index */ int *nelements; /* Number of elements in a molecule */ char line[maxlinelen], *lp, molecule[MAXNAMELEN]; /* Current molecule's name */ /* Alias names, and corresponding molecules: */ amass = (double *)calloc(natoms, sizeof(double)); aname = (char **)calloc(natoms, sizeof(char *)); aname[0] = (char *)calloc(natoms*namelen, sizeof(char)); for (i=1; i<natoms; i++) aname[i] = aname[0] + i*namelen; /* Open Molecules file: */ if((elist=verbfileopen(filename, "Molecular info ")) == NULL) exit(EXIT_FAILURE); do{ /* Read lines, skipping comments and blank lines: */ lp = fgets(line, maxlinelen, elist); }while (lp[0] == '\0' || lp[0] == '\n' || lp[0] == '#'); /* Fill atoms and mass array with info from element list: */ for (i=0; i<natoms; i++){ lp += 19; /* The element's symbol starts at the 19th character */ getname(lp, aname[i]); lp = nextfield(lp); amass[i] = strtod(lp, NULL); lp = fgets(line, maxlinelen, elist); } /* Allocate alias names and corresponding molecules: */ alias = (char **)calloc(nalias, sizeof(char *)); amol = (char **)calloc(nalias, sizeof(char *)); alias[0] = (char *)calloc(nalias*MAXNAMELEN, sizeof(char)); amol[0] = (char *)calloc(nalias*MAXNAMELEN, sizeof(char)); for (i=1; i<nalias; i++){ alias[i] = alias[0] + i*MAXNAMELEN; amol[i] = amol[0] + i*MAXNAMELEN; } /* Continue reading the file to get the alias names: */ do{ /* Skip blank and comment lines: */ lp = fgets(line, maxlinelen, elist); }while (lp[0] == '\0' || lp[0] == '\n' || lp[0] == '#'); /* Get aliases from file: */ for (i=0; i<nalias; i++){ /* Get alias and molecule name: */ getname(lp, alias[i]); lp = nextfield(lp); getname(lp, amol[i]); lp = fgets(line, maxlinelen, elist); } /* Allocate names and radii: */ radius = (double *)calloc(nradii, sizeof(double)); rname = (char **)calloc(nradii, sizeof(char *)); rname[0] = (char *)calloc(nradii*MAXNAMELEN, sizeof(char)); for (i=1; i<nradii; i++) rname[i] = rname[0] + i*MAXNAMELEN; /* Go to next block */ do{ lp = fgets(line, maxlinelen, elist); }while (lp[0] == '\0' || lp[0] == '\n' || lp[0] == '#'); /* Get radii from file: */ for (i=0; i<nradii; i++){ /* Get molecules' name and radius: */ getname(lp, rname[i]); lp = nextfield(lp); radius[i] = strtod(lp, NULL)/2.0; lp = fgets(line, maxlinelen, elist); } /* Allocate max number of molecules and max len of molecule name: */ nelements = (int *)calloc(MAXNAMELEN, sizeof(int)); elements = (char **)calloc(MAXNAMELEN, sizeof(char *)); elements[0] = (char *)calloc((MAXNAMELEN+1)*MAXNAMELEN, sizeof(char)); for (j=0; j<MAXNAMELEN; j++) elements[j] = elements[0] + j*(MAXNAMELEN+1); /* For each molecule: */ for (i=0; i<nmol; i++){ /* Check if molecule name is an alias: */ if ((j=findstring(mol->name[i], alias, nalias)) >= 0) strcpy(molecule, amol[j]); else strcpy(molecule, mol->name[i]); /* Allocate elements in a molecule: */ molnamelen = (int)strlen(molecule); /* Break down molecule into its elements: */ elen = 0; /* Element name length */ ielement = 0; /* Elements in a molecule counter */ for (j=0; j<molnamelen; j++){ if (isalpha(molecule[j])){ if (isupper(molecule[j])){ /* Uppercase letter: */ if (elen > 0){ /* End last element, advance j, store new letter */ if (elen <= 2){ /* If name is longer, it's an alias name */ elen = 0; ielement++; /* Count 1 more element */ nelements[ielement] = 1; } elements[ielement][elen++] = molecule[j]; } else{ /* New Atom (elen==0) */ elements[ielement][elen++] = molecule[j]; nelements[ielement] = 1; } } else{ /* Lowercase: */ elements[ielement][elen++] = molecule[j]; } } else{ /* A numeric value: */ nelements[ielement] = (int)strtol(&molecule[j], NULL, 10); elements[ielement][elen] = '\0'; j += (int)log10((double)nelements[ielement++]); elen = 0; } } if (elen != 0) ielement++; /* Calculate molecule's mass: */ for (j=0; j<ielement; j++){ /* Find index of atom in list: */ iatom = findstring(elements[j], aname, natoms); transitprint(30, verblevel, "Found %d %2s[%2d] atom(s) with mass " "%9.6f u.\n", nelements[j], aname[iatom], iatom, amass[iatom]); /* Get mass and multiply by the number of atoms in molecule: */ mol->mass[i] += amass[iatom] * nelements[j]; } /* Set the radius: */ j = findstring(molecule, rname, nradii); mol->radius[i] = radius[j] * ANGSTROM; transitprint(30, verblevel, "Molecule '%s' has radius %4.2f A and mass " "%4.2f u.\n", mol->name[i], mol->radius[i]/ANGSTROM, mol->mass[i]); } }
/* \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; }
/* \fcnfh Get keyword variables from atmosphere file (mass/number abundance bool; zero-radius offset; radius, temperature, and pressure units factor; atmfile name/info; list isotopes; list of proportional-abundance isotopes). Store molecules and proportional isotopes in atm_data struct. Determine which linedb isotope corresponds to such atm_data isotope. Solve non-matched linedb isotope cases. Put all non-ignore isotopes in transit.ds.iso structure. Return: Number of lines read */ int getmnfromfile(FILE *fp, /* Pointer to atmospheric file */ struct atm_data *at, /* atmosphere structure */ struct transit *tr, /* transit structure */ PREC_ZREC *f_remainder){ /* Remainder molecules' factor */ struct molecules *mol=tr->ds.mol; char line[maxline], *lp; int nimol=0, /* Number of molecules with abundance profile */ nmol=0, /* Total number of molecules */ i; /* Auxiliary for-loop index */ double cumulother = 0; /* Cumulative remainder-molecules' factor */ int ipi = 0; /* Number of remainder molecules */ /* Is the isotope defined in the atm file?: */ //isoprop = (struct atm_isoprop *)calloc(ipa, sizeof(struct atm_isoprop)); at->begline = 0; /* Line where the info begins */ /* Read and store the keyword atmospheric variables: */ while(1){ switch(fgetupto_err(line, maxline, fp, &atmerr, atmfilename, at->begline++)){ /* Ignore comments and blank lines: */ case '\n': case '#': continue; case 0: /* Throw error if EOF */ transiterror(TERR_SERIOUS|TERR_ALLOWCONT, "readatm :: EOF unexpectedly found at line %i " "of file %s while no t,p data points have been read.\n", at->begline, atmfilename); exit(EXIT_FAILURE); continue; /* Determine whether abundance is by mass or number: */ case 'q': lp = line + 1; while(*lp++ == ' '); /* Skip blank spaces */ lp--; switch(*lp|0x20){ case 'n': at->mass = 0; /* Number abundance (mixing ratio) */ break; case 'm': at->mass = 1; /* Mass abundance (mass mixing ratio) */ break; default: transiterror(TERR_SERIOUS, "'q' option in the atmosphere file can only be followed " "by 'm' (for abundances by mass) or 'n' (for abundances " "by number). '%s' is invalid.\n", line); break; } continue; /* Zero radius value: */ case 'z': zerorad = atof(line+1); continue; /* Radius, temperature, or pressure units factor: */ case 'u': switch(line[1]){ case 'r': at->rads.fct = atof(line+2); break; case 'p': at->atm.pfct = atof(line+2); break; case 't': at->atm.tfct = atof(line+2); break; default: transiterror(TERR_SERIOUS, "Invalid unit factor indication in " "atmosphere file.\n"); exit(EXIT_FAILURE); } continue; case 'n': /* Name or identifier for file data */ storename(at, line+1); continue; case 'i': /* Molecule names with an abundance profile: */ /* Count the number of wrds (molecules) in line: */ nimol = countfields(line+1, ' '); transitprint(15, verblevel, "The number of molecules is %d.\n", nimol); /* Allocate Molecules names: */ mol->name = (char **)calloc(nimol, sizeof(char *)); mol->name[0] = (char *)calloc(nimol*maxeisoname, sizeof(char)); for(i=1; i<nimol; i++) mol->name[i] = mol->name[0] + i*maxeisoname; transitprint(1, verblevel, "Molecules with abundance profile:\n "); lp = line; lp = nextfield(lp); /* Skip keyword */ /* Read and store names: */ for (i=0; i<nimol; i++){ getname(lp, mol->name[i]); lp = nextfield(lp); transitprint(1, verblevel, "%s, ", mol->name[i]); } transitprint(1, verblevel, "\b\b.\n"); continue; /* Molecules with abundance proportional to the remainder: */ case 'f': lp = line; lp = nextfield(lp); /* Skip keyword */ /* Current total number of molecules: */ nmol = ++ipi + nimol; /* Re-allocate to add the new molecule: */ mol->name = (char **)realloc(mol->name, nmol*sizeof(char *)); mol->name[0] = (char *)realloc(mol->name[0], nmol*maxeisoname*sizeof(char)); for (i=1; i<nmol; i++) mol->name[i] = mol->name[0] + i*maxeisoname; /* Re-allocate remainder factors: */ f_remainder = (PREC_ZREC *)realloc(f_remainder, ipi*sizeof(PREC_ZREC)); /* Read and store the molecule's name: */ getname(lp, mol->name[nmol-1]); lp = nextfield(lp); /* Move pointer to next field */ if(*lp == '=') /* Skip an optional equal '=' sign */ lp++; /* Read and store factor: */ f_remainder[ipi-1] = strtod(lp, NULL); transitprint(30, verblevel, "%s remainder factor: %.3f\n", mol->name[nmol-1], f_remainder[ipi-1]); if(f_remainder[ipi-1] < 0) transiterror(TERR_CRITICAL, "Abundance ratio has to be positive in atmosphere " "file '%s' in line: '%s'.\n", atmfilename, line); continue; /* End of keyword variables: */ default: break; } break; } transitprint(1, verblevel, "Molecules with abundance proportional to " "remainder:\n "); for(i=nimol; i<nmol; i++) transitprint(1, verblevel, "%s, ", mol->name[i]); transitprint(1, verblevel, "\b\b.\n"); transitprint(3, verblevel, "Read all keywords in atmosphere file without " "problems.\n"); /* Set total number of molecules in atmosphere: */ mol->nmol = at->n_aiso = nmol; /* Check that there was at least one isotope defined and re-allocate array sizes to their final size: */ if(!nimol) transiterror(TERR_SERIOUS, "No isotopes were found in atmosphere file, " "make sure to specify them in a line starting " "with the letter 'i'. First non-comment line " "read:\n%s\n", line); /* Set position of beginning of data: */ at->begpos = ftell(fp) - strlen(line) - 1; /* Calculate cumulative fraction of remainder molecules: */ for(i=0; i < nmol-nimol; i++) cumulother += f_remainder[i]; transitprint(30, verblevel, "Cumulative remainder fraction: %.4f.\n", cumulother); /* Check that cumulother sums to 1.0 (within allowed errors): */ if(nmol>nimol && abs(1.0 - cumulother) > ROUNDTHRESH) transiterror(TERR_SERIOUS, "Sum of remainder-molecules fractional " "abundance (%g) must add to 1.0 +/- %g.\n", cumulother, ROUNDTHRESH); /* Resolve what to do with those isotopes that appear in the line transition database, but not in the atmosphere file. Get the number of non-ignored isotopes in atm_data without linelist: */ //at->n_niso = checknonmatch(tr, at, isodo); /* FINDME: This will be a task in readline (if actually needed). */ return at->begline; }
/* \fcnfh Calculate the transit modulation at each wavenumber Return: 0 on success, else -1 if impact parameter sampling is not equispaced */ int modulation(struct transit *tr){ struct optdepth *tau = tr->ds.tau; struct geometry *sg = tr->ds.sg; static struct outputray st_out; tr->ds.out = &st_out; long w; prop_samp *ip = &tr->ips; prop_samp *wn = &tr->wns; ray_solution *sol = tr->sol; /* Check that impact parameter and wavenumber samples exist: */ transitcheckcalled(tr->pi, "modulation", 3, "tau", TRPI_TAU, "makeipsample", TRPI_MAKEIP, "makewnsample", TRPI_MAKEWN); /* Allocate the modulation array: */ PREC_RES *out = st_out.o = (PREC_RES *)calloc(wn->n, sizeof(PREC_RES)); /* Set time to the user hinted default, and other user hints: */ setgeom(sg, HUGE_VAL, &tr->pi); /* Integrate for each wavelength: */ transitprint(1, verblevel, "Integrating over wavelength.\n"); int nextw = wn->n/10; /* Calculate the modulation spectrum at each wavenumber: */ for(w=0; w < wn->n; w++){ out[w] = sol->spectrum(tr, tau->t[w], wn->v[w], tau->last[w], tau->toomuch, ip); if (out[w] < 0){ switch(-(int)out[w]){ case 1: if(tr->modlevel == -1) transiterror(TERR_SERIOUS, "Optical depth didn't reach limiting " "%g at wavenumber %g cm-1 (only reached %g). Cannot " "use critical radius technique (-1).\n", tau->toomuch, tau->t[w][tau->last[w]], wn->v[w]*wn->fct); default: transiterror(TERR_SERIOUS, "There was a problem while calculating " "modulation at wavenumber %g cm-1. Error code %i.\n", wn->v[w]*wn->fct, (int)out[w]); break; } exit(EXIT_FAILURE); } /* Print to screen the progress status: */ if(w==nextw){ nextw += wn->n/10; transitprint(2, verblevel, "%i%% ", (10*(int)(10*w/wn->n+0.9999999999))); } } transitprint(1, verblevel, "\nDone.\n"); /* Set progress indicator, and print output: */ tr->pi |= TRPI_MODULATION; printmod(tr); return 0; }
/* \fcnfh Read CIA info from tabulated files. Return: 0 on success */ int readcia(struct transit *tr){ FILE *fp; /* Pointer to CIA file */ char *file, /* CIA file name */ *colname; /* CIA isotope names */ PREC_CIA **a, /* CIA cross sections sample */ *wn; /* CIA sampled wavenumber array */ static struct cia st_cia; /* CIA structure */ tr->ds.cia = &st_cia; int npairs = tr->ds.cia->nfiles = tr->ds.th->ncia; /* Number of CIA files */ int p; /* Auxiliary wavenumber index */ long nt, wa; /* Number of temperature, wn samples in CIA file */ char rc; char *lp, *lpa; /* Pointers in file */ int maxline=300, n; /* Max length of line. Counter */ long lines; /* Lines read counter */ long i; /* Auxiliary for indices */ char line[maxline+1]; /* Array to hold line being read */ struct molecules *mol=tr->ds.mol; /* Make sure that radius and wavenumber samples exist: */ transitcheckcalled(tr->pi, "interpolatecia", 2, "makewnsample", TRPI_MAKEWN, "makeradsample", TRPI_MAKERAD); /* Allocate (output) transit extinction array (in cm-1): */ st_cia.e = (PREC_CIA **)calloc(tr->wns.n, sizeof(PREC_CIA *)); st_cia.e[0] = (PREC_CIA *)calloc(tr->wns.n*tr->rads.n, sizeof(PREC_CIA)); for(p=1; p < tr->wns.n; p++) st_cia.e[p] = st_cia.e[0] + p*tr->rads.n; memset(st_cia.e[0], 0, tr->wns.n*tr->rads.n*sizeof(double)); /* If there are no files, allocate tr.ds.cia.e (extinction) and return: */ if(!npairs){ return 0; } transitprint(1, verblevel, "Computing CIA opacities for %i database%s:\n", npairs, npairs>1 ? "s":""); /* Allocate string for molecule names: */ colname = (char *)calloc(maxline, sizeof(char)); /* Allocate molecules' ID: */ st_cia.mol1 = (int *)calloc(npairs, sizeof(int)); st_cia.mol2 = (int *)calloc(npairs, sizeof(int)); /* Number of temperature and wavenumber samples per file: */ st_cia.ntemp = (int *)calloc(npairs, sizeof(int)); st_cia.nwave = (int *)calloc(npairs, sizeof(int)); /* CIA, temperature and wavenumber samples: */ st_cia.cia = (PREC_CIA ***)calloc(npairs, sizeof(PREC_CIA **)); st_cia.temp = (PREC_CIA **)calloc(npairs, sizeof(PREC_CIA *)); st_cia.wn = (PREC_CIA **)calloc(npairs, sizeof(PREC_CIA *)); for(p=0; p < npairs; p++){ /* Copy file names from hint: */ file = xstrdup(tr->ds.th->ciafile[p]); /* Attempt to open the files: */ if((fp=fopen(file, "r")) == NULL) transiterror(TERR_SERIOUS, "Cannot read CIA file '%s'.\n", file); transitprint(10, verblevel, " CIA file (%d/%d): '%s'\n", p+1, npairs, file); lines = 0; /* lines read counter */ lpa = 0; /* Read the file headers: */ while(1){ /* Skip comments, blanks and read next line: */ while((rc=fgetupto_err(lp=line, maxline, fp, &ciaerr, file, lines++)) =='#' || rc=='\n'); /* If it is end of file, stop loop: */ if(!rc) transiterror(TERR_SERIOUS, "File '%s' finished before opacity info.\n", file); switch(rc){ case 'i': /* Read the name of the isotopes: */ while(isblank(*++lp)); /* Check that there are exactly two isotopes: */ if(countfields(lp, ' ') != 2) transiterror(TERR_SERIOUS, "Wrong line %i in CIA file '%s', if it begins with a " "'i', it should have the species separated by blank " "spaces. Rest of line:\n'%s'\n", lines, file, lp); st_cia.mol1[p] = st_cia.mol2[p] = -1; /* Allocate and copy the name of the first moleculee: */ getname(lp, colname); /* Find the ID of the first molecule: */ for(i=0; i<mol->nmol; i++) if(strcmp(mol->name[i], colname)==0) st_cia.mol1[p] = i; /* If the molecule is not in the atmosphere file: */ if(st_cia.mol1[p] == -1) transiterror(TERR_SERIOUS, "CIA molecule '%s' from file '%s' does " "not match any in the atmsopheric file.\n", colname, file); /* Allocate and store the name of the second isotope: */ lp = nextfield(lp); getname(lp, colname); for(i=0; i < mol->nmol; i++) if(strcmp(mol->name[i], colname)==0) st_cia.mol2[p] = i; if(st_cia.mol2[p] == -1) transiterror(TERR_SERIOUS, "CIA molecule '%s' from file '%s' does " "not match any in the atmsopheric file.\n", colname, file); transitprint(10, verblevel, " CIA molecules: [%s, %s]\n", mol->name[st_cia.mol1[p]], mol->name[st_cia.mol2[p]]); continue; case 't': /* Read the sampling temperatures array: */ while(isblank(*++lp)); nt = st_cia.ntemp[p] = countfields(lp, ' '); /* Number of temps. */ transitprint(10, verblevel, " Number of temperature samples: %ld\n", nt); if(!nt) transiterror(TERR_SERIOUS, "Wrong line %i in CIA file '%s', if it " "begins with a 't' then it should have the " "blank-separated fields with the temperatures. Rest " "of line: %s.\n", lines, file, lp); /* Allocate and store the temperatures array: */ st_cia.temp[p] = (PREC_CIA *)calloc(nt, sizeof(PREC_CIA)); n = 0; /* Count temperatures per line */ lpa = lp; /* Pointer in line */ transitprint(20, verblevel, " Temperatures (K) = ["); while(n < nt){ while(isblank(*lpa++)); st_cia.temp[p][n] = strtod(--lpa, &lp); /* Get value */ transitprint(20, verblevel, "%d, ", (int)st_cia.temp[p][n]); if(lp==lpa) transiterror(TERR_CRITICAL, "Less fields (%i) than expected (%i) " "were read for temperature in the CIA file '%s'.\n", n, nt, file); if((lp[0]|0x20) == 'k') lp++; /* Remove trailing K if exists */ lpa = lp; n++; } transitprint(20, verblevel, "\b\b]\n"); continue; default: break; } break; } /* Set an initial value for allocated wavenumber fields: */ wa = 32; /* Allocate wavenumber array: */ wn = (PREC_CIA *)calloc(wa, sizeof(PREC_CIA)); /* Allocate input extinction array (in cm-1 amagat-2): */ a = (PREC_CIA **)calloc(wa, sizeof(PREC_CIA *)); a[0] = (PREC_CIA *)calloc(wa*nt, sizeof(PREC_CIA)); for(i=1; i<wa; i++) a[i] = a[0] + i*nt; n=0; /* Read information for each wavenumber sample: */ while(1){ /* Skip comments and blanks; read next line: */ if (n) while((rc=fgetupto_err(lp=line, maxline, fp, &ciaerr, file, lines++)) =='#'||rc=='\n'); /* Stop, if it is end of file: */ if(!rc) break; /* Re-allocate (double the size) if necessary: */ if(n==wa){ wn = (PREC_CIA *)realloc(wn, (wa<<=1) * sizeof(PREC_CIA)); a = (PREC_CIA **)realloc(a, wa * sizeof(PREC_CIA *)); a[0] = (PREC_CIA *)realloc(a[0], wa * nt * sizeof(PREC_CIA)); for(i=1; i<wa; i++) a[i] = a[0] + i*nt; } /* Store new line: wavenumber first, then loop over cross sections: */ while(isblank(*lp++)); wn[n] = strtod(lp-1, &lpa); /* Store wavenumber */ if(lp==lpa+1) transiterror(TERR_CRITICAL, "Invalid fields for the %ith wavenumber " "in the CIA file '%s'.\n", n+1, file); i = 0; while(i<nt){ a[n][i] = strtod(lpa, &lp); /* Store cross section */ if(lp==lpa) transiterror(TERR_CRITICAL, "Less fields (%i) than expected (%i) " "were read for the %ith wavenumber in the CIA " "file '%s'.\n", i, nt, n+1, file); lpa = lp; i++; } n++; } /* Re-allocate arrays to their final sizes: */ if(n<wa){ st_cia.wn[p] = (PREC_CIA *)realloc(wn, n* sizeof(PREC_CIA)); a = (PREC_CIA **)realloc(a, n* sizeof(PREC_CIA *)); a[0] = (PREC_CIA *)realloc(a[0], n*nt*sizeof(PREC_CIA)); for(i=1; i<n; i++) a[i] = a[0] + i*nt; } transitprint(10, verblevel, " Number of wavenumber samples: %d\n", n); transitprint(20, verblevel, " Wavenumber array (cm-1) = [%.1f, %.1f, " "%.1f, ..., %.1f, %.1f, %.1f]\n", st_cia.wn[p][0], st_cia.wn[p][1], st_cia.wn[p][2], st_cia.wn[p][n-3], st_cia.wn[p][n-2], st_cia.wn[p][n-1]); st_cia.cia[p] = a; st_cia.nwave[p] = n; fclose(fp); } /* FINDME: The program breaks when I free colname, it makes no sense */ free(colname); transitprint(1, verblevel, "Done.\n"); tr->pi |= TRPI_CIA; return 0; }