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

📄 bend.cc

📁 二维射线追踪地震层析成像
💻 CC
字号:
/* * bend.cc - ray-bending solver implementation *           direct minimization of travel times by conjugate gradient *           (rays are represented as beta-splines) * * Jun Korenaga, MIT/WHOI * January 1999 */#include "bend.h"#include "traveltime.h"BendingSolver2d::BendingSolver2d(const SlownessMesh2d& s,				 const BetaSpline2d& b,				 double tol1, double tol2)    : smesh(s), bs(b), nintp(bs.numIntp()),      cg_tol(tol1), brent_tol(tol2), eps(1e-10){    Q.resize(nintp);    dQdu.resize(nintp);    int max_np = int(2*sqrt(float(smesh.numNodes())));    new_point.reserve(max_np);    dTdV.reserve(max_np);    new_dTdV.reserve(max_np);    direc.reserve(max_np);    pp.reserve(max_np+4);    new_pp.reserve(max_np+4);}int BendingSolver2d::refine(Array1d<Point2d>& path,			    double& orig_time, double& new_time){    int np=check_path_size(path);    makeBSpoints(path,pp);    new_point.resize(np);     makeBSpoints(new_point,new_pp);    dTdV.resize(np);    new_dTdV.resize(np);    direc.resize(np);        orig_time=calcTravelTime(smesh, path, bs, pp, Q);    double old_time = orig_time;    calc_dTdV(smesh, path, bs, dTdV, pp, Q, dQdu);    direc = -dTdV; // p0    // conjugate gradient search    int iter_max = np*10;    for (int iter=1; iter<=iter_max; iter++){	new_time=line_min(path, direc);	if ((old_time-new_time)<=cg_tol){	    return iter;	}		calc_dTdV(smesh, path, bs, new_dTdV, pp, Q, dQdu);	double gg=0.0, dgg=0.0;	for (int i=1; i<=np; i++){	    double x0=dTdV(i).x(),y0=dTdV(i).y();	    double x1=new_dTdV(i).x(),y1=new_dTdV(i).y();	    gg += x0*x0+y0*y0;	    dgg += x1*x1+y1*y1;	}//	if (gg==0.0){	if (abs(gg)<1e-10){	    return iter;	}else{	    dgg /= gg;	}	for (int i=1; i<=np; i++){	    direc(i) = -new_dTdV(i)+dgg*direc(i);	}	dTdV = new_dTdV;	old_time = new_time;    }    return -iter_max; // too many iterations}int BendingSolver2d::refine(Array1d<Point2d>& path,			    double& orig_time, double& new_time,			    const Array1d<int>& start_i,			    const Array1d<int>& end_i,			    const Array1d<const Interface2d*>& interf){    int np=check_path_size(path,start_i,end_i,interf);    makeBSpoints(path,pp);    new_point.resize(np);     makeBSpoints(new_point,new_pp);        dTdV.resize(np);    new_dTdV.resize(np);    direc.resize(np);    orig_time=calcTravelTime(smesh, path, bs, pp, Q);    double old_time = orig_time;    calc_dTdV(smesh, path, bs, dTdV, pp, Q, dQdu);    adjust_dTdV(dTdV, path, start_i, end_i, interf);    direc = -dTdV; // p0        // conjugate gradient search    int iter_max = np*10;    for (int iter=1; iter<=iter_max; iter++){	new_time=line_min(path, direc, start_i, end_i, interf);	if ((old_time-new_time)<=cg_tol){	    return iter;	}		calc_dTdV(smesh, path, bs, new_dTdV, pp, Q, dQdu);	adjust_dTdV(new_dTdV, path, start_i, end_i, interf);	double gg=0.0, dgg=0.0;	for (int i=1; i<=np; i++){	    double x0=dTdV(i).x(),y0=dTdV(i).y();	    double x1=new_dTdV(i).x(),y1=new_dTdV(i).y();	    gg += x0*x0+y0*y0;	    dgg += x1*x1+y1*y1;	}//	if (gg==0.0){ // 2000.5.8                       // this may be the cause for "-NaN" reported by                      // Allegra. (due to division by extremely small gg)	if (abs(gg)<1e-10){	    return iter;	}else{	    dgg /= gg;	}	for (int i=1; i<=np; i++){	    direc(i) = -new_dTdV(i)+dgg*direc(i);	}	dTdV = new_dTdV;	old_time = new_time;    }    return -iter_max; // too many iterations}void BendingSolver2d::adjust_dTdV(Array1d<Point2d>& dTdV,				  const Array1d<Point2d>& path,				  const Array1d<int>& start_i,				  const Array1d<int>& end_i,				  const Array1d<const Interface2d*>& interf){    for (int a=1; a<=interf.size(); a++){	double slope = interf(a)->dzdx(path(start_i(a)).x());	double total=0.0;	for (int i=start_i(a); i<=end_i(a); i++){	    total += dTdV(i).x()+slope*dTdV(i).y();//	    total += dTdV(i).x();	    dTdV(i).y() = 0.0;	}	total /= (end_i(a)-start_i(a)+1);	for (int i=start_i(a); i<=end_i(a); i++){	    dTdV(i).x() = total; // all points have the same direction now.	}    }}int BendingSolver2d::check_path_size(Array1d<Point2d>& path){    int np=path.size();    if (np<2) error("BendingSolver2d::invalid ray path");    // the following is now taken care of by graph's pickPath()//    if (np==2){ 	// since end points are fixed, this path wouldn't be	// refined without an additional point in the middle// 	Point2d p1=path(1),p2=path(2);// 	path.resize(3);// 	path(1)=p1; path(2)=0.5*(p1+p2); path(3)=p2;//	np=3;//    }    return np;}int BendingSolver2d::check_path_size(Array1d<Point2d>& path,				     const Array1d<int>& start_i,				     const Array1d<int>& end_i,				     const Array1d<const Interface2d*>& interf){    int np=path.size();    if (np<2) error("BendingSolver2d::invalid ray path");    int nintf = interf.size();    if (start_i.size() != nintf || end_i.size() != nintf)	error("BendingSolver2d::refine - size mismatch in interface spec");    for (int i=1; i<=nintf; i++){	if (start_i(i) > end_i(i) ||	    start_i(i) < 1 || start_i(i) > np ||	    end_i(i) < 1 || end_i(i) > np)	    error("BendingSolver2d::refine - invalid interface points");    }    return np;}    int BendingSolver2d::refine(Array1d<Point2d>& path,			    double& orig_time, double& new_time,			    int nfac){    if (nfac<1) error("BendingSolver2d::illegal nfac input");    if (nfac==1){	return refine(path,orig_time,new_time);    }        int np=path.size();    Array1d<Point2d> old_path(np);    old_path = path;    int n2=(nfac-1)*(np-1);    double frac=1.0/nfac;    path.resize(np+n2);    for (int i=1; i<np; i++){	int orig_i = nfac*(i-1)+1;	path(orig_i) = old_path(i);	for (int j=1; j<nfac; j++){	    double ratio=frac*j;	    path(orig_i+j) = (1-ratio)*old_path(i)+ratio*old_path(i+1);	}    }    path.back()=old_path.back();    return refine(path,orig_time,new_time);}double BendingSolver2d::line_min(Array1d<Point2d>& path, const Array1d<Point2d>& direc){    point_p = &path; // for f1dim()    direc_p = &direc;    double ax = 0.0;    double xx = 1.0;    double bx, fa, fx, fb, xmin;    mnbrak(&ax, &xx, &bx, &fa, &fx, &fb, &BendingSolver2d::f1dim);    double new_val = brent(ax,xx,bx,&xmin, &BendingSolver2d::f1dim);    for (int i=1; i<=path.size(); i++){	path(i) += xmin*direc(i);    }    return new_val;}double BendingSolver2d::f1dim(double x){    for (int i=1; i<=point_p->size(); i++){	new_point(i) = (*point_p)(i)+x*(*direc_p)(i);    }    double d = calcTravelTime(smesh, new_point, bs, new_pp, Q);    return d;}double BendingSolver2d::line_min(Array1d<Point2d>& path, const Array1d<Point2d>& direc,				 const Array1d<int>& start_i, const Array1d<int>& end_i,				 const Array1d<const Interface2d*>& interf){    point_p = &path; // for f1dim_interf()    direc_p = &direc;    start_i_p = &start_i;    end_i_p = &end_i;    interf_p = &interf;//    double ax = 0.0;//    double xx = 1.0;    double ax = -0.1;    double xx = 0.1;    double bx, fa, fx, fb, xmin;    mnbrak(&ax, &xx, &bx, &fa, &fx, &fb, &BendingSolver2d::f1dim_interf);    double new_val = brent(ax,xx,bx,&xmin, &BendingSolver2d::f1dim_interf);    for (int i=1; i<=path.size(); i++){	path(i) += xmin*direc(i);    }    for (int a=1; a<=interf.size(); a++){	double new_z = interf(a)->z(path(start_i(a)).x());	for (int i=start_i(a); i<=end_i(a); i++){	    path(i).y() = new_z;	}    }    return new_val;}double BendingSolver2d::f1dim_interf(double x){    for (int i=1; i<=point_p->size(); i++){	new_point(i) = (*point_p)(i)+x*(*direc_p)(i);    }    for (int a=1; a<=interf_p->size(); a++){	double new_z = (*interf_p)(a)->z(new_point((*start_i_p)(a)).x());	for (int i=(*start_i_p)(a); i<=(*end_i_p)(a); i++){	    new_point(i).y() = new_z;	}    }    double d = calcTravelTime(smesh, new_point, bs, new_pp, Q);    return d;}

⌨️ 快捷键说明

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