// 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;
    }
}
Example #2
0
int main(int argc, char *argv[]) {

  /* initialize Madagascar */
  sf_init(argc, argv);

  Logger::instance().init("serial-fwi");

  FwiParams &params = 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;
}