// scale gradients for the whole one pyramid with the use of (Cx,Cy) from the other pyramid static void pyramid_scale_gradient(pyramid_t* pyramid, pyramid_t* pC) { while (pyramid != NULL) { const int size = pyramid->rows * pyramid->cols; scale_gradient(size, pyramid->Gx, pC->Gx); scale_gradient(size, pyramid->Gy, pC->Gy); pyramid = pyramid->next; pC = pC->next; } }
int main(int argc, char *argv[]) { /* initialize Madagascar */ sf_init(argc, argv); Logger::instance().init("serial-fwi"); FwiParams ¶ms = FwiParams::instance(); std::vector<float> dobs(params.ns * params.nt * params.ng); /* observed data */ std::vector<float> cg(params.nz * params.nx, 0); /* conjugate gradient */ std::vector<float> g0(params.nz * params.nx, 0); /* gradient at previous step */ std::vector<float> wlt(params.nt); /* ricker wavelet */ std::vector<float> objval(params.niter, 0); /* objective/misfit function */ /* initialize wavelet */ rickerWavelet(&wlt[0], params.nt, params.fm, params.dt, params.amp); ShotPosition allSrcPos(params.szbeg, params.sxbeg, params.jsz, params.jsx, params.ns, params.nz); ShotPosition allGeoPos(params.gzbeg, params.gxbeg, params.jgz, params.jgx, params.ng, params.nz); // read velocity Velocity v0 = SfVelocityReader::read(params.vinit, params.nx, params.nz); // read observed data ShotDataReader::serialRead(params.shots, &dobs[0], params.ns, params.nt, params.ng); EnquistAbc2d fmMethod(params.dt, params.dx, params.dz); Velocity vel = fmMethod.expandDomain(v0); float obj0 = 0; for (int iter = 0; iter < params.niter; iter++) { boost::timer::cpu_timer timer; std::vector<float> g1(params.nz * params.nx, 0); /* gradient at curret step */ std::vector<float> derr(params.ns * params.ng * params.nt, 0); /* residual/error between synthetic and observation */ std::vector<float> illum(params.nz * params.nx, 0); /* illumination of the source wavefield */ Velocity vtmp = vel; /* temporary velocity computed with epsil */ fmMethod.bindVelocity(vel); /** * calculate local objective function & derr & illum & g1(gradient) */ float obj = cal_obj_derr_illum_grad(params, &derr[0], &illum[0], &g1[0], &wlt[0], &dobs[0], fmMethod, allSrcPos, allGeoPos); DEBUG() << format("sum_derr %f, sum_illum %f, sum_g1 %f") % sum(derr) % sum(illum) % sum(g1); objval[iter] = iter == 0 ? obj0 = obj, 1.0 : obj / obj0; float epsil = 0; float beta = 0; sf_floatwrite(&illum[0], params.nz * params.nx, params.illums); scale_gradient(&g1[0], &vel.dat[0], &illum[0], params.nz, params.nx, params.precon); bell_smoothz(&g1[0], &illum[0], params.rbell, params.nz, params.nx); bell_smoothx(&illum[0], &g1[0], params.rbell, params.nz, params.nx); sf_floatwrite(&g1[0], params.nz * params.nx, params.grads); DEBUG() << format("before beta: sum_g0: %f, sum_g1: %f, sum_cg: %f") % sum(g0) % sum(g1) % sum(cg); beta = iter == 0 ? 0.0 : cal_beta(&g0[0], &g1[0], &cg[0], params.nz, params.nx); cal_conjgrad(&g1[0], &cg[0], beta, params.nz, params.nx); epsil = cal_epsilon(&vel.dat[0], &cg[0], params.nz, params.nx); cal_vtmp(&vtmp.dat[0], &vel.dat[0], &cg[0], epsil, params.nz, params.nx); std::swap(g1, g0); // let g0 be the previous gradient fmMethod.bindVelocity(vtmp); float alpha = calVelUpdateStepLen(params, &wlt[0], &dobs[0], &derr[0], epsil, fmMethod, allSrcPos, allGeoPos); update_vel(&vel.dat[0], &cg[0], alpha, params.nz, params.nx); sf_floatwrite(&vel.dat[0], params.nz * params.nx, params.vupdates); // output important information at each FWI iteration INFO() << format("iteration %d obj=%f beta=%f epsil=%f alpha=%f") % (iter + 1) % obj % beta % epsil % alpha; // INFO() << timer.format(2); } /// end of iteration sf_floatwrite(&objval[0], params.niter, params.objs); sf_close(); return 0; }