⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inverse.cc

📁 二维射线追踪地震层析成像
💻 CC
📖 第 1 页 / 共 3 页
字号:
    double z2 = reflp->z(x2);    double x = path(ir0).x();    double dx = x2-x1;    double dz = z2-z1;    double cos_alpha = dx/sqrt(dx*dx+dz*dz);    double p1 = smesh.at(path(ir0));    Point2d a = path(ir0-1)-path(ir0); a /= a.norm();    Point2d b = path(ir1+1)-path(ir1); b /= b.norm();    Point2d c = a+b; c /= c.norm();    double cos_theta = a.inner_product(c);        double com_factor = 2.0*cos_theta*cos_alpha*p1/dx;    A_i[nnodev+jL] = com_factor*(x2-x);    A_i[nnodev+jR] = com_factor*(x-x1);    add_kernel(idata,path);}    void TomographicInversion2d::calc_averaging_matrix(){    for (int i=1; i<=nx; i++){	for (int k=1; k<=nz; k++){	    int inode = smesh.nodeIndex(i,k);	    Point2d p = smesh.nodePos(inode);	    double Lh, Lv;	    corr_vel_p->at(p,Lh,Lv);	    double Lh2 = Lh*Lh;	    double Lv2 = Lv*Lv;	    double beta_sum = 0.0;	    for (int ii=1; ii<=nx; ii++){		int jnode = smesh.nodeIndex(ii,k);		if (jnode!=inode){		    double dx = smesh.nodePos(jnode).x()-p.x();		    if (abs(dx)<=Lh){			double dxL2 = dx*dx/Lh2;			double beta = exp(-dxL2);			Rv_h(inode)[jnode] = beta*mvscale(jnode);			beta_sum += beta;		    }		}	    }	    Rv_h(inode)[inode] = -beta_sum*mvscale(inode);	    beta_sum = 0.0;	    for (int kk=1; kk<=nz; kk++){		int jnode = smesh.nodeIndex(i,kk);		if (jnode!=inode){		    double dz = smesh.nodePos(jnode).y()-p.y();		    if (abs(dz)<=Lv){			double dzL2 = dz*dz/Lv2;			double beta = exp(-dzL2);			Rv_v(inode)[jnode] = beta*mvscale(jnode);			beta_sum += beta;		    }		}	    }	    Rv_v(inode)[inode] = -beta_sum*mvscale(inode);	}    }}void TomographicInversion2d::calc_refl_averaging_matrix(){    for (int i=1; i<=nnoded; i++){	double x = reflp->x(i);	double Lh;	if (corr_dep_p != 0){	    Lh = corr_dep_p->at(x);	}else if (corr_vel_p != 0){	    double Lv;	    corr_vel_p->at(Point2d(x,reflp->z(x)),Lh,Lv);	}else{	    error("TomographicInversion2d::calc_refl_averaging_matrix - no correlation length available");	}	double Lh2 = Lh*Lh;	double beta_sum = 0.0;	for (int ii=1; ii<=nnoded; ii++){	    if (ii!=i){		double dx = reflp->x(ii)-x;		if (abs(dx)<=Lh){		    double beta = exp(-dx*dx/Lh2);		    Rd(i)[ii] = beta*mdscale(ii)*refl_weight;		    beta_sum += beta;		}	    }	}	Rd(i)[i] = -beta_sum*mdscale(i)*refl_weight;    }}void TomographicInversion2d::calc_damping_matrix(){    Array2d<double> local_T(4,4);    Array1d<int> j(4);        for (int i=1; i<=smesh.numCells(); i++){	smesh.cellNodes(i, j(1), j(2), j(3), j(4));	smesh.cellNormKernel(i, local_T);	if (do_squeezing){	     Point2d p = 0.25*(smesh.nodePos(j(1))+smesh.nodePos(j(2))			       +smesh.nodePos(j(3))+smesh.nodePos(j(4)));	     double w;	     damping_wt_p->at(p,w);	     local_T *= w;	}	add_global(local_T, j, Tv);    }}void TomographicInversion2d::calc_refl_damping_matrix(){    double dx = reflp->x(2)-reflp->x(1); // assumes uniform interval    double fac = sqrt(dx);    for (int i=1; i<=nnoded; i++){	Td(i)[i] = fac;    }}void TomographicInversion2d::add_global(const Array2d<double>& a,					const Array1d<int>& j, sparseMat& global){    for (int m=1; m<=4; m++){	for (int n=1; n<=4; n++){	    global(j(m))[j(n)] += a(m,n);	}    }}double TomographicInversion2d::calc_ave_dmv(){    double dm_norm=0.0;    for (int i=1; i<=nnodev; i++){	dm_norm += dmodel_total(i)*dmodel_total(i);    }    return sqrt(dm_norm/nnodev);}double TomographicInversion2d::calc_ave_dmd(){    if (nrefl==0) return 0.0;	    double dm_norm=0.0;    for (int i=1+nnodev; i<=nnoded+nnodev; i++){	dm_norm += dmodel_total(i)*dmodel_total(i);    }    return sqrt(dm_norm/nnoded)*refl_weight;}void TomographicInversion2d::calc_Lm(double& lmh, double& lmv, double& lmd){    if (smooth_velocity){	Array1d<double> Rvm(nnodev), dmv_vec(nnodev);	SparseRectangular sparseRv_h(Rv_h,tmp_nodev,tmp_nodev);	for (int i=1; i<=nnodev; i++) dmv_vec(i) = dmodel_total(i);	sparseRv_h.Ax(dmv_vec,Rvm);	double val=0.0;	for (int i=1; i<=nnodev; i++) val += Rvm(i)*Rvm(i);	lmh = sqrt(val/nnodev);	SparseRectangular sparseRv_v(Rv_v,tmp_nodev,tmp_nodev);	sparseRv_v.Ax(dmv_vec,Rvm);	val = 0.0;	for (int i=1; i<=nnodev; i++) val += Rvm(i)*Rvm(i);	lmv = sqrt(val/nnodev);    }    if (nrefl>0 && smooth_depth){	Array1d<double> Rdm(nnoded), dmd_vec(nnoded);	SparseRectangular sparseRd(Rd,tmp_nodedr,tmp_nodedr);	for (int i=1+nnodev, j=1; i<=nnoded+nnodev; i++) dmd_vec(j++) = dmodel_total(i);	sparseRd.Ax(dmd_vec,Rdm);	double val = 0.0;	for (int i=1; i<=nnoded; i++) val += Rdm(i)*Rdm(i);	lmd = sqrt(val/nnoded);    }} double TomographicInversion2d::calc_chi(){    Array1d<double> Adm(ndata_valid);    SparseRectangular sparseA(A,tmp_data,tmp_node,nnode_total);    sparseA.Ax(dmodel_total,Adm);    double val=0.0;    for (int i=1; i<=ndata; i++){	int j=tmp_data(i);	if (j>0){	    double res=Adm(j)-data_vec(i);	    val += res*res;	}    }    return val/ndata_valid;}int TomographicInversion2d::_solve(bool sv, double wsv, bool sd, double wsd,				   bool dv, double wdv, bool dd, double wdd){    // construct total kernel    Array1d<const sparseMat*> As;    Array1d<SparseMatAux> matspec;    As.push_back(&A);    matspec.push_back(SparseMatAux(1.0,&tmp_data,&tmp_node));    int ndata_plus=ndata_valid;    if (gravity){	As.push_back(&B);	matspec.push_back(SparseMatAux(1.0,&tmp_gravdata,&tmp_node));	ndata_plus += ngravdata;    }    if (sv){	if (wsv<0) error("TomographicInversion2d::_solve - negative wsv");	As.push_back(&Rv_h);	matspec.push_back(SparseMatAux(wsv,&tmp_nodev,&tmp_nodev));	ndata_plus += nnodev;	As.push_back(&Rv_v);	matspec.push_back(SparseMatAux(wsv,&tmp_nodev,&tmp_nodev));	ndata_plus += nnodev;    }    if (nrefl>0 && sd){	if (wsd<0) error("TomographicInversion2d::_solve - negative wsd");	As.push_back(&Rd);	matspec.push_back(SparseMatAux(wsd,&tmp_nodedr,&tmp_nodedc));	ndata_plus += nnoded;    }    if (dv){	if (wdv<0) error("TomographicInversion2d::_solve - negative wdv");	As.push_back(&Tv);	matspec.push_back(SparseMatAux(wdv,&tmp_nodev,&tmp_nodev));	ndata_plus += nnodev;    }    if (nrefl>0 && dd){	if (wdd<0) error("TomographicInversion2d::_solve - negative wdd");	As.push_back(&Td);	matspec.push_back(SparseMatAux(wdd,&tmp_nodedr,&tmp_nodedc));	ndata_plus += nnoded;    }    SparseRectangular B(As,matspec,nnode_total);    // construct total data vector    total_data_vec.resize(ndata_plus);    int idata=1;    for (int i=1; i<=ndata; i++){	if (tmp_data(i)>0){	    total_data_vec(idata++) = data_vec(i);	}    }    if (gravity){	for (int i=1; i<=ngravdata; i++){	    total_data_vec(idata++) = res_grav(i);	}    }    if (sv){	if (jumping){	    Array1d<double> Rvm(nnodev), dmv_vec(nnodev);	    SparseRectangular sparseRv_h(Rv_h,tmp_nodev,tmp_nodev);	    for (int i=1; i<=nnodev; i++) dmv_vec(i) = dmodel_total_sum(i);	    sparseRv_h.Ax(dmv_vec,Rvm);	    for (int i=1; i<=nnodev; i++) total_data_vec(idata++) = -wsv*Rvm(i); // Lh	    SparseRectangular sparseRv_v(Rv_v,tmp_nodev,tmp_nodev);	    sparseRv_v.Ax(dmv_vec,Rvm);	    for (int i=1; i<=nnodev; i++) total_data_vec(idata++) = -wsv*Rvm(i); // Lv	}else{	    for (int i=1; i<=nnodev; i++) total_data_vec(idata++) = 0.0; // Lh	    for (int i=1; i<=nnodev; i++) total_data_vec(idata++) = 0.0; // Lv	}    }    if (nrefl>0 && sd){	if (jumping){	    Array1d<double> Rdm(nnoded), dmd_vec(nnoded);	    SparseRectangular sparseRd(Rd,tmp_nodedr,tmp_nodedr);	    for (int i=1+nnodev, j=1; i<=nnoded+nnodev; i++) dmd_vec(j++) = dmodel_total_sum(i);	    sparseRd.Ax(dmd_vec,Rdm);	    for (int i=1; i<=nnoded; i++) total_data_vec(idata++) = -wsd*Rdm(i); // Ld	}else{	    for (int i=1; i<=nnoded; i++) total_data_vec(idata++) = 0.0;	}    }    if (dv){	if (jumping){	    Array1d<double> Tvm(nnodev), dmv_vec(nnodev);	    SparseRectangular sparseTv(Tv,tmp_nodev,tmp_nodev);	    for (int i=1; i<=nnodev; i++) dmv_vec(i) = dmodel_total_sum(i);	    sparseTv.Ax(dmv_vec,Tvm);	    for (int i=1; i<=nnodev; i++) total_data_vec(idata++) = -wdv*Tvm(i); 	}else{	    for (int i=1; i<=nnodev; i++) total_data_vec(idata++) = 0.0;	}    }    if (nrefl>0 && dd){	if (jumping){	    Array1d<double> Tdm(nnoded), dmd_vec(nnoded);	    SparseRectangular sparseTd(Td,tmp_nodedr,tmp_nodedr);	    for (int i=1+nnodev, j=1; i<=nnoded+nnodev; i++) dmd_vec(j++) = dmodel_total_sum(i);	    sparseTd.Ax(dmd_vec,Tdm);	    for (int i=1; i<=nnoded; i++) total_data_vec(idata++) = -wdd*Tdm(i); 	}else{	    for (int i=1; i<=nnoded; i++) total_data_vec(idata++) = 0.0;	}    }    int lsqr_itermax=itermax_LSQR;    double chi;    int istop=iterativeSolver_LSQR(B,total_data_vec,dmodel_total,LSQR_ATOL,lsqr_itermax,chi);    return lsqr_itermax;}void TomographicInversion2d::fixed_damping(int& iter, int& n, double& wdv, double& wdd){    wdv = weight_d_v;    wdd = weight_d_d;        iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		   true,weight_d_v,true,weight_d_d);    n++;    if (robust){	if (verbose_level>=0){	    cerr << "TomographicInversion2d:: check outliers... ";	}	int ndata_valid_orig=ndata_valid;	removeOutliers();	if (verbose_level>=0){	    cerr << ndata_valid_orig-ndata_valid << " found\n";	}	if (ndata_valid < ndata_valid_orig){	    if (verbose_level>=0){		cerr << "TomographicInversion2d:: re-inverting without outliers...\n";	    }	    iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,			   true,weight_d_v,true,weight_d_d);	    n++;	}    }}void TomographicInversion2d::auto_damping(int& iter, int& n, double& wdv, double& wdd){    // check if damping is necessary    iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		   false,0.0,false,0.0);    n++;    if (robust){	if (verbose_level>=0){	    cerr << "TomographicInversion2d:: check outliers... ";	}	int ndata_valid_orig=ndata_valid;	removeOutliers();	if (verbose_level>=0){	    cerr << ndata_valid_orig-ndata_valid << " found\n";	}	if (ndata_valid < ndata_valid_orig){	    if (verbose_level>=0){		cerr << "TomographicInversion2d:: re-inverting without outliers...\n";	    }	    iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,			   false,0.0,false,0.0);	    n++;	}    }    double ave_dmv0 = calc_ave_dmv();    double ave_dmd0 = calc_ave_dmd();    if (verbose_level>=0){	cerr << "\t\tave_dm = " << ave_dmv0*100	     << "%, " << ave_dmd0*100 << "% with no damping\n";    }    wdv = wdd = 1.0;    if (ave_dmv0<=target_dv || !damp_velocity) wdv = 0.0;    if (ave_dmd0<=target_dd || !damp_depth) wdd = 0.0;     if (wdv==0.0 && wdd==0.0) return;    if (wdd>0.0) wdd = auto_damping_depth(wdv,iter,n);    if (wdv>0.0) wdv = auto_damping_vel(wdd,iter,n);}double TomographicInversion2d::auto_damping_depth(double wdv, int& iter, int& n){    // secant and bisection search    if (verbose_level>=0) cerr << "\t\tsearching weight_d_depth...\n";    const double wd_max = 1e7; // absolute bound    double wd1 = 1.0; // initial guess    double wd2 = 1e2;    const double ddm = target_dd*0.3; // target accuracy = 30 %    const int secant_itermax=10;    double rts, xl, swap, dx, fl, f;    iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		   damp_velocity,wdv,true,wd1); n++;    fl = calc_ave_dmd()-target_dd;    if (verbose_level>=0){	cerr << "\t\tave_dm = " << (fl+target_dd)*100 << "% at wd1("	     << wd1 << ")\n";    }    iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		   damp_velocity,wdv,true,wd2); n++;    f = calc_ave_dmd()-target_dd;    if (verbose_level>=0){	cerr << "\t\tave_dm = " << (f+target_dd)*100 << "% at wd2("	     << wd2 << ")\n";    }    if (abs(fl) < abs(f)){	rts = wd1;	xl = wd2;	swap=fl; fl=f; f=swap;    }else{	xl = wd1; rts = wd2;    }    for (int j=1; j<=secant_itermax; j++){	dx = (xl-rts)*f/(f-fl);	if (rts+dx<=0){ // switch to bisection	    xl=rts; fl=f;	    rts *= 0.5;	}else if(rts+dx>wd_max){	    xl=rts; fl=f;	    rts += (wd_max-rts)*0.5;	}else{	    xl=rts; fl=f;	    rts+=dx;	}	iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		       damp_velocity,wdv,true,rts); n++;	f = calc_ave_dmd()-target_dd;	if (verbose_level>=0){	    cerr << "\t\tave_dm = " << (f+target_dd)*100		 << "% at w_d of " << rts << '\n';	}	if (rts > wd_max) break;	if (abs(f) < ddm) break;    }    return rts;}double TomographicInversion2d::auto_damping_vel(double wdd, int& iter, int& n){    // secant and bisection search    if (verbose_level>=0) cerr << "\t\tsearching weight_d_vel...\n";    const double wd_max = 1e5; // absolute bound    double wd1 = 1.0; // initial guess    double wd2 = 1e2;    const double ddm = target_dv*0.3; // target accuracy = 30 %    const int secant_itermax=10;    double rts, xl, swap, dx, fl, f;    iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		   true,wd1,damp_depth,wdd); n++;    fl = calc_ave_dmv()-target_dv;    if (verbose_level>=0){	cerr << "\t\tave_dm = " << (fl+target_dv)*100 << "% at wd1("	     << wd1 << ")\n";    }    iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		   true,wd2,damp_depth,wdd); n++;    f = calc_ave_dmv()-target_dv;    if (verbose_level>=0){	cerr << "\t\tave_dm = " << (f+target_dv)*100 << "% at wd2("	     << wd2 << ")\n";    }    if (abs(fl) < abs(f)){	rts = wd1;	xl = wd2;	swap=fl; fl=f; f=swap;    }else{	xl = wd1; rts = wd2;    }    for (int j=1; j<=secant_itermax; j++){	dx = (xl-rts)*f/(f-fl);	if (rts+dx<=0){ // switch to bisection	    xl=rts; fl=f;	    rts *= 0.5;	}else{	    xl=rts; fl=f;	    rts+=dx;	}	iter += _solve(smooth_velocity,weight_s_v,smooth_depth,weight_s_d,		       true,rts,damp_depth,wdd); n++;	f = calc_ave_dmv()-target_dv;	if (verbose_level>=0){	    cerr << "\t\tave_dm = " << (f+target_dv)*100		 << "% at w_d of " << rts << '\n';	}	if (rts > wd_max) break;	if (abs(f) < ddm) break;    }    return rts;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -