#include "iwsamp.hh" //#define IWAVE_VERBOSE namespace TSOpt { IWaveSampler::IWaveSampler(IWAVE * state, string key, PARARRAY & pars, FILE * stream) : axes(0), prev_panelindex(-1), tg(NULL), dump_term(0), increment(true) { // initialize receiver range indices to global grid get_gs(gmin,(state->model).g); get_ge(gmax,(state->model).g); samplekey=key; pname=""; if (parse(pars,key,pname)) { string gname = ""; // extract proto name - use preferentially to actual file name, // particularly to handle temp filenames, which do not have suffixes. // note that only geometrical info will be extracted here, which can // as well be found from the proto files const char * rname = NULL; // because current implementation of out-of-core classes does all // file handling on rk 0, must extract prototype file name there. // this block of code should be abtracted eventually to hide // implementation details against future changes eg. to distrtibuted // or network database. As is, will work properly so long as prototype // file is used in iwave_fopen on rk=0. #ifdef IWAVE_USE_MPI int cprotolen=0; if (retrieveGlobalRank()==0) { #endif if ((rname = iwave_getproto(pname.c_str()))) gname = rname; else gname = pname; #ifdef IWAVE_USE_MPI // C string length cprotolen = gname.size()+1; } MPI_Bcast(&cprotolen,1,MPI_INT,0,retrieveGlobalComm()); char * cproto = new char[cprotolen]; if (retrieveGlobalRank()==0) strcpy(cproto,gname.c_str()); MPI_Bcast(cproto,cprotolen,MPI_CHAR,0,retrieveGlobalComm()); gname=cproto; delete [] cproto; #endif // check for file type size_t pos = gname.find_last_of("."); if (pos==std::string::npos || pos >= gname.size()-1) { RVLException e; e<<"Error: IWaveSampler constructor - filename "<model).g.dim; j++) has_Spatial_Axes = has_Spatial_Axes && has_Axis(j); // cerr<<"rsf case: axis vector = \n"; // for (int i=0;i construct_tracegeom, fin=%s\n",pname.c_str()); fflush(stream); #endif /* construct trace geometry object */ tg = new tracegeom; int err=construct_tracegeom(tg, pname.c_str(), (state->model).tsind.dt, SRC_TOL, stream); if (err) { fprintf(stream,"ERROR: IWaveSampler\n"); fprintf(stream,"return from construct_tracegeom with err=%d\n",err); RVLException e; e<<"ERROR: IWaveSampler\n"; e<<" return from construct_tracegeom with err="<(pars,"dump_term",0); taperwidth= valparse(pars,"taperwidth",0); timewidth = valparse(pars,"timewidth",0); muteslope = valparse(pars,"muteslope",0.0f); mutezotime= valparse(pars,"mutezotime",0.0f); mutewidth = valparse(pars,"mutewidth",0.0f); /* set up axes */ axis * at = new axis; at->n = tg->nt; at->o = tg->t0; at->d = (state->model).tsind.dt; at->id = (state->model).g.dim; axes.push_back(at); /* if (retrieveGlobalRank()==1) { cerr<<"IWaveSampler - su case, time axis: n="<n<<" d="<d<<" o="<o<<" id="<id<model).g); cerr<<"IWaveSampler - su case, new axis =\n"; fprint_axis(stderr,*at); cerr<<"IWaveSampler - su case, recorded axis "<o)/(at->d))+0.1)); tracestop=tracestart + at->n - 1; // create record axis if (tg->nrec > 1) { axis * ae = new axis; ae->n = tg->nrec; ae->o = 0.0; ae->d = 1.0; ae->id = (state->model).g.dim + 1; axes.push_back(ae); } /* read sampling order */ sampord=0; parse(pars,"sampord",sampord); // 2016.10.09 WWS: optionally unset increment, triggering // overwrite mode std::string ikey = "increment_"+key; increment = valparse(pars,ikey,true); #ifdef IWAVE_VERBOSE fprintf(stream,"IWaveSamp constructor exit\n"); fflush(stream); #endif } else { RVLException e; e<<"Error: IWaveSampler constructor - suffix "<id == id); return has; } axis const * IWaveSampler::getTimeAxis(int dim) const { for (int i=0; i<(int)axes.size();i++) { if (axes[i]->id == dim) return axes[i]; } return NULL; } ireal IWaveSampler::getCellVol() const { ireal cv = REAL_ONE; for (int i=0; i<(int)axes.size();i++) cv *= axes[i]->d; return cv; } ireal IWaveSampler::getRecipCellVol() const { ireal cv = REAL_ONE; ireal rcv = REAL_ONE; for (int i=0; i<(int)axes.size();i++) cv *= axes[i]->d; if (ProtectedDivision(REAL_ONE,cv,rcv)) { RVLException e; e<<"Error: IWaveSampler::getRecipCellVol\n"; e<<" samplekey = "<axes.size() > 0) { bool load = false; // load data from disk bool save = false; // save data to disk bool init = false; // initialize internal buffers and transfer info, if needed bool sample = false; // sample to internal or external buffer // compute istart IPNT istart; IPNT istop; get_gs(istart,g); get_ge(istop,g); // detect time axis axis const * a = this->getTimeAxis(g.dim); // compute panelindex = step through external extended indices // load - if at BEGIN of all axes that you DON'T HAVE, and at begin of time axis // save - if at END of all axes that you DON'T HAVE, and at end of time axis // for determining "begin" and "end" of time axis, sense is reversed when // fwd=false int panelnum=1; int panelindex=0; // nontrivial extended axes if (g.gdim > g.dim+1) { // multipanel movies not permitted /* if (has_Spatial_Axes && a) { RVLException e; e<<"Error: IWaveSampler::sample, samplekey="< last)) { RVLException e; e<<"Error: IWaveSampler::sample\n"; e<<" panelindex "< myaxes(0); for (int i=g.dim+1; i0) this_panelindex=0; for (size_t i=0; i< myaxes.size(); i++) { this_panelindex += (step[myaxes[i]]-istart[myaxes[i]])*this_panelnum; this_panelnum *= istop[myaxes[i]]-istart[myaxes[i]]+1; } if (dryrun) drystr<n; // compute timeslices for sampling float t = g.axes[g.dim].d*(step[g.dim]-istart[g.dim]) + g.axes[g.dim].o; if (dryrun) drystr<<" sampler on rarr "<n)) && (step[g.dim]==istart[g.dim])) { cerr<<"NOTE: IWaveSampler::sample\n"; cerr<<" number of time steps = "<o - 0.01*a->d || t > a->o + (a->n-1+0.01)*(a->d)) this_panelindex = prev_panelindex; else { // compute relative time on axis with positive margin of one-half internal time step float curr_time_rel = ((t - a->o + 0.5*g.axes[g.dim].d)/(a->d)); if (dryrun) drystr<<"curr_time_rel="<<(int)(floor(curr_time_rel))<<"\n"; // get panel index this_panelindex = iwave_max(0,iwave_min((int)(floor(curr_time_rel)),this_panelnum-1)); } } // time condition for load/save // note that input flags input for forward mode - has // opposite meaning for reverse mode bool buffered = (a && !has_Spatial_Axes); bool atbeg = (fwd && (step[g.dim]==istart[g.dim])) || (!fwd && (step[g.dim]==istop[g.dim])); bool atend = (!fwd && (step[g.dim]==istart[g.dim])) || (fwd && (step[g.dim]==istop[g.dim])); if (dryrun && (this_panelindex==prev_panelindex)) { drystr<<"this_panelindex unchanged - no sampling:\n"; drystr<<"this_panelindex = "<model).ld_a._s[ridx]))) { RVLException e; e<<"Error: IWaveSampler::sample from ra_a_zero\n"; e<<"err="<model).ld_a) ; if (rd_ndim(dom,ridx,&dim) || rd_size(dom,ridx,n0) || rd_gse(dom,ridx,gs0,ge0)) { RVLException e; e<<"Error: IWaveSample::sample\n"; e<<" failure on size query, allocated array\n"; e<<" iwdx="<model).ld_c),ridx,n) || rd_gse(&((state->model).ld_c),ridx,gs,ge)) { RVLException e; e<<"Error: IWaveSample::sample\n"; e<<" failure on size query, computational array\n"; e<<" iwdx="<_s[ridx]._s0; // scale for adjoint linearized i/o // - input - by cell volume // - output - by reciprocal cell volume // detect linearized i/o by iwdx - if > 0 this i/o op // reads or writes a perturbation ireal scale = REAL_ONE; if (!fwd && input && (iwdx>0)) scale = this->getCellVol(); if (!fwd && !input && (iwdx>0)) scale = this->getRecipCellVol(); if (sample) { if (dryrun) { drystr<<"\nIWaveSample: samplekey="<has_Axis(g.axes[i].id)) { drystr<<" extd axis = "< 1) { drystr<<" this_panelnum = "<samplekey.c_str(),iwdx,ridx); fprintf(stream," rsfread pname=%s gs0[0]=%d gs0[1]=%d gs0[2]=%d\n",gs0[0],gs0[1],gs0[2]); fprintf(stream," rsfread n0[0]=%d n0[1]=%d n0[2]=%d\n",n0[0],n0[1],n0[2]); fflush(stream); #endif */ // 03.02.14: read into buffer; axpy via loop - hoist all scaling // out of rsfread, which is used in overwrite mode so no need to // independently initialize buf // int err=rsfread(data,gs0,n0,pname.c_str(),scale,stream,this_panelindex); if (err) { RVLException e; e<<"Error: IWaveSample::sample, rsf case\n"; e<<" failed to read panel "<samplekey.c_str(),this_panelnum,iwdx,ridx); fflush(stream); #endif int err=0; // stack case if (this_panelnum == 1) { #ifdef IWAVE_USE_MPI // if no time axis, then local stack MPI_Barrier(MPI_COMM_WORLD); size_t ntot=1; for (int i=0;i_s[ridx])); } } } else if (suffix=="su") { /* extract grid params - space and time */ IPNT nl; /* axis lengths, local grid */ RPNT ol; /* axis origins, local grid */ RPNT dl; /* axis steps, local grid */ IPNT ng; /* axis lengths, global grid */ RPNT og; /* axis origins, global grid */ RPNT dg; /* axis steps, global grid */ IPNT axord; /* axis order array */ get_n(nl,(state->model).gl); get_o(ol,(state->model).gl); get_d(dl,(state->model).gl); get_n(ng,(state->model).g); get_o(og,(state->model).g); get_d(dg,(state->model).g); get_ord(axord,(state->model).g); // shift axis origin if necessary for staggering - this info // should already be part of grid, which should be part of // rarray. // NOTE: ASSUMED THAT PRIMARY GRID DOES NOT CONTAIN BDRY, so // first staggered grid point is to left of first primary grid // point in simulation grid for (int i=0;i<(state->model).g.dim;i++) { ol[i] += 0.5*gtype[i]*dl[i]; og[i] += 0.5*gtype[i]*dg[i]; } // int flag for initializing trace buffer // note that "load" is a subcase of "init" for buffered i/o int initbuf = 0; /* if (!fwd && load) initbuf = -1; // -1 -> adjoint cubic interpolation if ( fwd && load) initbuf = 1; // 1 -> cubic interpolation */ // WWS 2016.10.05: always adjoint-interpolate on load if (load && increment) initbuf=-1; if (load && !increment) initbuf=1; #ifdef IWAVE_VERBOSE if (load) fprintf(stream,"IWaveSampler::sample: su load on samplekey=%s\n",samplekey.c_str()); if (save) fprintf(stream,"IWaveSampler::sample: su save on samplekey=%s\n",samplekey.c_str()); #endif if (init) { // cerr<<"samplekey="<model).g.dim, initbuf, stream); if (err) { RVLException e; e<<"Error: IWaveSampler::sample from init_tracegeom\n"; e<<" err = "<= tracestart) && (step[g.dim] <= tracestop)) { // read/write trace switch int traceinput = 0; if (input) { traceinput = 1; if (!increment) { traceinput=2; } // overwrite option 2016.10.09 WWS // this assumes that for reference state // that (i) all trace input is RHS (questionable), // and (ii) all trace input should be treated as // defining a numerical delta (safe) if (iwdx==0) { scale=1.0f; for (int kk=0;kk<(state->model).g.dim;kk++) scale/=(state->model).g.axes[kk].d; if (increment) scale*= (state->model).tsind.rhs; } // cerr<<"samplekey="< writetraces\n",samplekey.c_str()); #endif int err=writetraces(tg,dg,og,stream); if (err) { RVLException e; e<<"Error: IWaveSampler::sample from writetraces\n"; e<<" err = "<