void model_elastic_TTI(float  **  rho, float **  c11, float **  c13, float **  c33, float **  c44, float **  theta){

	/*--------------------------------------------------------------------------*/
	/* global variables */
	extern int NX, NY, NXG, NYG,  POS[3], MYID;
	extern char  MFILE[STRING_SIZE], INV_MODELFILE[STRING_SIZE];	
	extern float DH;
	
        /* local variables */	
	int i, j, ii, jj;
	char filename[STRING_SIZE];
	float y;
	
	/* anisotropic parameters in the layers */
	float vp0, vsv, rhoh, delta, epsilon, thetah;	
	
	/* 1st layer: isotropic acoustic water layer */
        float vp01 = 1500.0, vsv1 = 0.0, rhoh1 = 1000.0, delta1 = 0.0, epsilon1 = 0.0, thetah1 = 0.0;	
	
	/* 2nd layer: anisotropic VTI medium */
	float vp02 = 1800.0, vsv2 = 1040.0, rhoh2 = 2000.0, delta2 = 0.0, epsilon2 = 0.0, thetah2 = 0.0;
	
	/* 3rd layer: anisotropic TTI medium */
	float vp03 = 2200.0, vsv3 = 1270.0, rhoh3 = 2000.0, delta3 = 0.0, epsilon3 = 0.0, thetah3 = 0.0;
	
	/* 4th layer: anisotropic TTI medium */
	float vp04 = 2800.0, vsv4 = 1620.0, rhoh4 = 2000.0, delta4 = 0.0, epsilon4 = 0.0, thetah4 = 0.0;
		

        /* transform Thomsen's parameters to elastic tensor components */
        float c33h, c44h, c11h, c13h;
	
	float d1=300.0, d2=450.0, d3=1100.0;
		
	/*-----------------------------------------------------------------------*/

		
	/* loop over global grid */
		for (i=1;i<=NXG;i++){
			for (j=1;j<=NYG;j++){
			
			        /* properties of the first layer */
				vp0 = vp01; vsv = vsv1; rhoh = rhoh1; delta = delta1; epsilon = epsilon1; thetah = thetah1;
				
				
				/* calculate depth */
				y = j*DH;
				
				if(y > d1){vp0 = vp02; vsv = vsv2; rhoh = rhoh2; delta = delta2; epsilon = epsilon2; thetah = thetah2;}
				if(y > d2){vp0 = vp03; vsv = vsv3; rhoh = rhoh3; delta = delta3; epsilon = epsilon3; thetah = thetah3;}	
				if(y > d3){vp0 = vp04; vsv = vsv4; rhoh = rhoh4; delta = delta4; epsilon = epsilon4; thetah = thetah4;}				
			
			        /* transform Thomsen's parameters to elastic tensor components */
        			c33h = rhoh * vp0 * vp0;
        			c44h = rhoh * vsv * vsv;
			 	c11h = c33h * (1 + 2.0 * epsilon);
				c13h = sqrt((c33h-c44h) * (c33h-c44h) + 2.0 * delta * c33h * (c33h - c44h)) - c44h;
											
       				/* only the PE which belongs to the current global gridpoint 
				  is saving model parameters in his local arrays */
				if ((POS[1]==((i-1)/NX)) && 
				    (POS[2]==((j-1)/NY))){
					ii=i-POS[1]*NX;
					jj=j-POS[2]*NY;

					c11[jj][ii]=c11h;
					c13[jj][ii]=c13h;
					c33[jj][ii]=c33h;
					c44[jj][ii]=c44h;
					theta[jj][ii]=thetah * M_PI / 180.0;
					rho[jj][ii]=rhoh;
					
				}
			}
		}	

	/* each PE writes his model to disk and PE 0 merges model files */
	sprintf(filename,"%s.denise.c11",MFILE);
	writemod(filename,c11,3);
	MPI_Barrier(MPI_COMM_WORLD);

	if (MYID==0) mergemod(filename,3);
	
	sprintf(filename,"%s.denise.c13",MFILE);
        writemod(filename,c13,3);
	MPI_Barrier(MPI_COMM_WORLD);
	                           
	if (MYID==0) mergemod(filename,3);
	
	sprintf(filename,"%s.denise.c33",MFILE);
	writemod(filename,c33,3);
	MPI_Barrier(MPI_COMM_WORLD);
	                        
	if (MYID==0) mergemod(filename,3);

        sprintf(filename,"%s.denise.c44",MFILE);
	writemod(filename,c44,3);
	MPI_Barrier(MPI_COMM_WORLD);
	                        
	if (MYID==0) mergemod(filename,3);

	sprintf(filename,"%s.denise.theta",MFILE);
	writemod(filename,theta,3);
	MPI_Barrier(MPI_COMM_WORLD);
	                        
	if (MYID==0) mergemod(filename,3);

        /* clean up temporary files */
        MPI_Barrier(MPI_COMM_WORLD);

        sprintf(filename,"%s.denise.c11.%i%i",MFILE,POS[1],POS[2]);
        remove(filename);

        sprintf(filename,"%s.denise.c13.%i%i",MFILE,POS[1],POS[2]);
        remove(filename);

        sprintf(filename,"%s.denise.c33.%i%i",MFILE,POS[1],POS[2]);
        remove(filename);

        sprintf(filename,"%s.denise.c44.%i%i",MFILE,POS[1],POS[2]);
        remove(filename);

        sprintf(filename,"%s.denise.theta.%i%i",MFILE,POS[1],POS[2]);
        remove(filename);

}
Example #2
0
float step_length_est(FILE *fprec, float ** waveconv, float ** waveconv_rho, float ** waveconv_u, float ** prho, float ** prhonp1, float ** ppi, float ** ppinp1, int iter, int nfstart,
                      int nsrc, float ** puipjp, float ** prip, float ** prjp, float L2, int partest, float ** srcpos_loc, float ** srcpos, float ** srcpos1, float ** signals, int ns,
                      int nd, float ** pvx, float ** pvy, float ** psxx, float ** psyy, float ** psxy, float ** ux, float ** uy, float ** pvxp1, float ** pvyp1, float ** psi_sxx_x, float ** psi_sxy_x,
                      float ** psi_vxx, float ** psi_vyx, float ** psi_syy_y, float ** psi_sxy_y, float ** psi_vyy, float ** psi_vxy, float ** psi_vxxs, float ** pvxm1, float ** pvym1, float ** uttx,
                      float ** utty, float ** absorb_coeff, float *hc, float * K_x, float * a_x, float * b_x, float * K_x_half, float * a_x_half, float * b_x_half, float * K_y, float * a_y, float * b_y,
                      float * K_y_half, float * a_y_half, float * b_y_half, float ** uxy, float ** uyx, int ntr, int **recpos_loc, float **sectionvx, float **sectionvy, float **sectionp, float **sectioncurl,
                      float **sectiondiv, float **sectionread, int ntr_glob, float ** sectionvxdata, float ** sectionvxdiff, float ** sectionvxdiffold, float ** sectionvydata, float ** sectionvydiff,
                      float ** sectionvydiffold, float * epst1, float * L2t, float L2sum, float energy_sum, float ** bufferlef_to_rig, float ** bufferrig_to_lef,
                      float ** buffertop_to_bot, float ** bufferbot_to_top, float **pu, float **punp1, int itest,int nsrc_glob, int nsrc_loc, MPI_Request * req_send, MPI_Request * req_rec, float ***pr,
                      float ***pp, float ***pq, float **fipjp, float **f, float **g, float *bip, float *bjm, float *cip, float *cjm, float ***d, float ***e, float ***dip, float **ptaup, float **ptaus,
                      float *etajm, float *peta, float *etaip, float **ptausipjp, int **recpos, int *step1, int *step3, float C_vp, float **gradg, float FC,
                      int nxgrav, int nygrav, int ngrav, float **gravpos, float *gz_mod, int NZGRAV) {

    extern int MYID,MIN_ITER,TIME_FILT,STEPMAX, GRAVITY, IDX, IDY, NX, NY, NXG, NYG, POS[3], MYID;
    extern char JACOBIAN[STRING_SIZE];
    extern float EPS_SCALE, SCALEFAC, LAM_GRAV, GAMMA_GRAV, L2_GRAV_IT1;

    float opteps_vp, ** rho_grav, ** rho_grav_ext;
    int h, i, j, n, nshots, ishot, nt, lsnap, lsamp, nsnap, infoout;

    /* Variables for step length calculation */
    int step2, itests, iteste, stepmax, countstep;
    float scalefac, eps_scale, L2_grav, L2sum1;
    float * gz_res;
    char jac_grav[STRING_SIZE];
    FILE *FP_GRAV;

    scalefac = SCALEFAC;  /* scale factor for the step length */
    stepmax  = STEPMAX;   /* number of maximum misfit calculations/steplength 2/3*/

    *step1=0;
    step2=0;

    /* start with first guess for step length alpha */
    eps_scale=EPS_SCALE; /* maximum model change = 1% of the maximum model value */
    countstep=0; /* count number of forward calculations */

    itests=2;
    iteste=2;

    while((step2!=1)||(*step1!=1)) {

        for (itest=itests; itest<=iteste; itest++) { /* calculate 3 L2 values */

            forward_mod(fprec,waveconv,waveconv_rho,waveconv_u,prho,prhonp1,ppi,ppinp1,iter,eps_scale,nfstart,nsrc,puipjp,prip,prjp,L2,partest,srcpos_loc,srcpos,srcpos1,signals,ns,
                        nd,pvx,pvy,psxx,psyy,psxy,ux,uy,pvxp1,pvyp1,psi_sxx_x,psi_sxy_x,psi_vxx,psi_vyx,psi_syy_y,psi_sxy_y,psi_vyy,psi_vxy,psi_vxxs,pvxm1,pvym1,uttx,utty,absorb_coeff,hc,K_x,
                        a_x,b_x,K_x_half,a_x_half,b_x_half,K_y,a_y,b_y,K_y_half,a_y_half,b_y_half,uxy,uyx,ntr,recpos_loc,sectionvx,sectionvy,sectionp,sectioncurl,sectiondiv,sectionread,ntr_glob,
                        sectionvxdata,sectionvxdiff,sectionvxdiffold,sectionvydata,sectionvydiff,sectionvydiffold,epst1,L2t,L2sum,energy_sum,bufferlef_to_rig,bufferrig_to_lef,
                        buffertop_to_bot,bufferbot_to_top,pu,punp1,itest,nsrc_glob,nsrc_loc,req_send,req_rec,pr,pp,pq,fipjp,f,g,bip,bjm,cip,cjm,d,e,dip,ptaup,ptaus,etajm,peta,etaip,ptausipjp,recpos,FC);

            if(GRAVITY==2) {

                /* save seismic L2-norm of seismic data residuals */
                L2sum1 = L2t[itest];
                gz_res = vector(1,ngrav);

                /* global density model */
                rho_grav =  matrix(1,NYG,1,NXG);
                rho_grav_ext =  matrix(1,nygrav,1,nxgrav);

                /* model gravity data */
                /* save current density model */
                sprintf(jac_grav,"%s_tmp.rho.%i%i",JACOBIAN,POS[1],POS[2]);
                FP_GRAV=fopen(jac_grav,"wb");

                for (i=1; i<=NX; i=i+IDX) {
                    for (j=1; j<=NY; j=j+IDY) {
                        fwrite(&prhonp1[j][i],sizeof(float),1,FP_GRAV);
                    }
                }

                fclose(FP_GRAV);

                MPI_Barrier(MPI_COMM_WORLD);

                /* merge model file */
                sprintf(jac_grav,"%s_tmp.rho",JACOBIAN);
                if (MYID==0) mergemod(jac_grav,3);

                MPI_Barrier(MPI_COMM_WORLD);

                read_density_glob(rho_grav,2);
                extend_mod(rho_grav,rho_grav_ext,nxgrav,nygrav);
                grav_mod(rho_grav_ext,ngrav,gravpos,gz_mod,nxgrav,nygrav,NZGRAV);

                /* calculate gravity data residuals */
                L2_grav=calc_res_grav(ngrav,gz_mod,gz_res);


                /* TEST: LAMBDA WEIGHTING BY GRADIENT */

                /* calculate lambda_grav */
                /* TEST: WITHOUT NORM */
                /*LAM_GRAV = GAMMA_GRAV * (L2sum1/L2_GRAV_IT1);*/
                /*LAM_GRAV = GAMMA_GRAV;*/
                /* TEST: DECREASING LAMBDA PER ITERATION */
                /*LAM_GRAV = GAMMA_GRAV * ((L2sum1+L2_grav)/L2_GRAV_IT1);*/

                /* add gravity penalty term to the seismic objective function */
                L2t[itest]+=LAM_GRAV * L2_grav;
                /* ONLY GRAVITY INVERSION */
                /*L2t[itest] = L2_grav;*/

                /* free memory */
                free_matrix(rho_grav,1,NYG,1,NXG);
                free_matrix(rho_grav_ext,1,nygrav,1,nxgrav);
                free_vector(gz_res,1,ngrav);

            }

        } /* end of L2 test */

        /* Did not found a step size which reduces the misfit function */
        if((*step1==0)&&(L2t[1]<=L2t[2])) {
            eps_scale = eps_scale/scalefac;
            countstep++;
        }

        /* Found a step size with L2t[2] < L2t[3]*/
        if((*step1==1)&&(L2t[2]<L2t[3])) {
            epst1[3]=eps_scale;
            step2=1;
        }

        /* Could not found a step size with L2t[2] < L2t[3]*/
        if((*step1==1)&&(L2t[2]>=L2t[3])) {
            epst1[3]=eps_scale;
            /* increase step length to find  a larger misfit function than L2t[2]*/
            eps_scale = eps_scale + (eps_scale/scalefac);
            countstep++;
        }

        /* found a step size which reduces the misfit function */
        if((*step1==0)&&(L2t[1]>L2t[2])) {
            epst1[2]=eps_scale;
            *step1=1;
            iteste=3;
            itests=3;
            countstep=0;
            /* find a second step length with a larger misfit function than L2t[2]*/
            eps_scale = eps_scale + (eps_scale/scalefac);
        }

        *step3=0;

        if((*step1==0)&&(countstep>stepmax)) {
            if(MYID==0) {
                printf(" Steplength estimation failed!");
            }
            if(TIME_FILT==0) {
                err(" ");
            }
            *step3=1;
            break;
        }

        if((*step1==1)&&(countstep>stepmax)) {
            if(MYID==0) {
                printf("Could not found a proper 3rd step length which brackets the minimum\n");
            }
            *step1=1;
            step2=1;
        }

        if(MYID==0) {
            printf("iteste = %d \t itests = %d \t step1 = %d \t step2 = %d \t eps_scale = %e \t countstep = %d \t stepmax= %d \t scalefac = %e \t MYID = %d \t L2t[1] = %e \t L2t[2] = %e \t L2t[3] = %e \n",iteste,itests,*step1,step2,eps_scale,countstep,stepmax,scalefac,MYID,L2t[1],L2t[2],L2t[3]);
        }

    } /* end of while loop */

    if(*step1==1) { /* only find an optimal step length if step1==1 */
        /* calculate optimal step length epsilon for Vp and Vs*/
        if(MYID==0) {
            printf("================================================= \n");
            printf("calculate optimal step length epsilon for Vp and Vs \n");
            printf("================================================= \n");
        }
        opteps_vp=calc_opt_step(L2t,waveconv,gradg,epst1,1,C_vp);
        eps_scale = opteps_vp;
    }

    return eps_scale;
}
void model_elastic(float  **  rho, float **  pi, float **  u){

	/*--------------------------------------------------------------------------*/
	/* extern variables */

	extern int NX, NY, NXG, NYG,  POS[3], L, MYID;
	extern char  MFILE[STRING_SIZE];	
	extern char INV_MODELFILE[STRING_SIZE];
	extern float DH;
		/* local variables */
	float vp, vs, rhov, grad1, grad2, grad3, y;
	int i, j, ii, jj;
	char modfile[STRING_SIZE]; 
	
	/* parameters for layer 1 */
	const float vp1=500.0, vs1=300.0, rho1=1800.0, h=15.0;
	
	/* parameters for layer 2 due to calculation of grad1, grad2 and grad3*/
	const float vp2=1200.0, vs2=700.0, rho2=2000.0;
	
	/*-----------------------------------------------------------------------*/

	y=h/DH;
	if(y==NYG) err(" \n y is equal NYG !! see src/model_grad.c  \n ");
	grad1=(vp2-vp1)/y;
	grad2=(vs2-vs1)/y;
	grad3=(rho2-rho1)/y;	
	
	
	/* loop over global grid */
		for (i=1;i<=NXG;i++){
			for (j=1;j<=NYG;j++){
			
				if(j<=y){
				vp=vp1+(j*grad1);
				vs=vs1+(j*grad2);
				rhov=rho1+(j*grad3);
				}
				
				else{				
				vp=vp2;
				vs=vs2;
				rhov=rho2;
				}
				
				/* only the PE which belongs to the current global gridpoint 
				  is saving model parameters in his local arrays */
				if ((POS[1]==((i-1)/NX)) && 
				    (POS[2]==((j-1)/NY))){
					ii=i-POS[1]*NX;
					jj=j-POS[2]*NY;

					u[jj][ii]=vs;
					rho[jj][ii]=rhov;
					pi[jj][ii]=vp;
				}
			}
		}	

		
sprintf(modfile,"%s_rho_it_0.bin",INV_MODELFILE);
writemod(modfile,rho,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vs_it_0.bin",INV_MODELFILE);
writemod(modfile,u,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vp_it_0.bin",INV_MODELFILE);
writemod(modfile,pi,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);
}
void model(float  **  rho, float **  pi, float **  u, 
float **  taus, float **  taup, float *  eta){

	/*--------------------------------------------------------------------------*/
	/* extern variables */

	extern float DT, *FL, TAU, DH;
	extern int NX, NY, NXG, NYG,  POS[3], L, MYID;
	extern char  MFILE[STRING_SIZE];	

		/* local variables */
	float rhov, muv, piv, vp, vs, y;
	float *pts, ts, tp, sumu, sumpi, ws;
	int i, j, l, ii, jj;
	char modfile[STRING_SIZE]; 
	
	/* parameters for layer 1 */
	const float vp1=500.0, vs1=300.0, rho1=1800.0, h=2.0;
	
	/* parameters for layer 2 */
	const float vp2=500.0, vs2=300.0, rho2=1800.0;
	
	
	/*-----------------------------------------------------------------------*/


	/* vector for maxwellbodies */
	pts=vector(1,L);
	for (l=1;l<=L;l++) {
		pts[l]=1.0/(2.0*PI*FL[l]);
		eta[l]=DT/pts[l];
	}

	ts=TAU;  
	tp=TAU;

	ws=2.0*PI*FL[1];
	
	sumu=0.0; 
	sumpi=0.0;
	for (l=1;l<=L;l++){
		sumu=sumu+((ws*ws*pts[l]*pts[l]*ts)/(1.0+ws*ws*pts[l]*pts[l]));
		sumpi=sumpi+((ws*ws*pts[l]*pts[l]*tp)/(1.0+ws*ws*pts[l]*pts[l]));
	}

		

	/* loop over global grid */
		for (i=1;i<=NXG;i++){
			for (j=1;j<=NYG;j++){
			
				y=(float)j*DH;
			
				if (y<=h){
				 vp=vp1; vs=vs1; rhov=rho1; }

				
				 else{
 				 vp=vp2; vs=vs2; rhov=rho2; }
                    
				
				/* only the PE which belongs to the current global gridpoint 
				  is saving model parameters in his local arrays */
				if ((POS[1]==((i-1)/NX)) && 
				    (POS[2]==((j-1)/NY))){
					ii=i-POS[1]*NX;
					jj=j-POS[2]*NY;

					taus[jj][ii]=ts;
					taup[jj][ii]=tp;
					u[jj][ii]=vs;
					rho[jj][ii]=rhov;
					pi[jj][ii]=vp;
				}
			}
		}	

		

	
	/* each PE writes his model to disk */
	sprintf(modfile,"%s.u",MFILE);
	writemod(modfile,u,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(modfile,3);
	
	
	/*sprintf(modfile,"%s.pi",MFILE);
	writemod(modfile,pi,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(modfile,3);
	
	
	sprintf(modfile,"%s.rho",MFILE);
	writemod(modfile,rho,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(modfile,3);
	
	
	sprintf(modfile,"%s.taup",MFILE);
	writemod(modfile,taup,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(modfile,3);
	
	
	sprintf(modfile,"%s.taus",MFILE);
	writemod(modfile,taus,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(modfile,3);*/
	
	free_vector(pts,1,L);
}
void FWI_PSV(){

/* global variables */
/* ---------------- */

/* forward modelling */
extern int MYID, FDORDER, NX, NY, NT, L, READMOD, QUELLART, RUN_MULTIPLE_SHOTS, TIME_FILT;
extern int LOG, SEISMO, N_STREAMER, FW, NXG, NYG, IENDX, IENDY, NTDTINV, IDXI, IDYI, NXNYI, INV_STF, DTINV;
extern float FC_SPIKE_1, FC_SPIKE_2, FC, FC_START, TIME, DT;
extern char LOG_FILE[STRING_SIZE], MFILE[STRING_SIZE];
extern FILE *FP;

/* gravity modelling/inversion */
extern int GRAVITY, NZGRAV, NGRAVB, GRAV_TYPE, BACK_DENSITY;
extern char GRAV_DATA_OUT[STRING_SIZE], GRAV_DATA_IN[STRING_SIZE], GRAV_STAT_POS[STRING_SIZE], DFILE[STRING_SIZE];
extern float LAM_GRAV, GAMMA_GRAV, LAM_GRAV_GRAD, L2_GRAV_IT1;

/* full waveform inversion */
extern int GRAD_METHOD, NLBFGS, ITERMAX, IDX, IDY, INVMAT1, EPRECOND;
extern int GRAD_FORM, POS[3], QUELLTYPB, MIN_ITER, MODEL_FILTER;
extern float FC_END, PRO, C_vp, C_vs, C_rho;
extern char MISFIT_LOG_FILE[STRING_SIZE], JACOBIAN[STRING_SIZE];
extern char *FILEINP1;

/* local variables */
int ns, nseismograms=0, nt, nd, fdo3, j, i, iter, h, hin, iter_true, SHOTINC, s=0;
int buffsize, ntr=0, ntr_loc=0, ntr_glob=0, nsrc=0, nsrc_loc=0, nsrc_glob=0, ishot, nshots=0, itestshot;

float sum, eps_scale, opteps_vp, opteps_vs, opteps_rho, Vp_avg, Vs_avg, rho_avg, Vs_sum, Vp_sum, rho_sum;
char *buff_addr, ext[10], *fileinp, jac[225], source_signal_file[STRING_SIZE];

double time1, time2, time7, time8, time_av_v_update=0.0, time_av_s_update=0.0, time_av_v_exchange=0.0, time_av_s_exchange=0.0, time_av_timestep=0.0;
	
float L2sum, *L2t;
	
float ** taper_coeff, * epst1, *hc=NULL;
int * DTINV_help;

MPI_Request *req_send, *req_rec;
MPI_Status  *send_statuses, *rec_statuses;

/* Variables for step length calculation */
int step1, step3=0;
float eps_true, tmp;

/* Variables for the L-BFGS method */
float * rho_LBFGS, * alpha_LBFGS, * beta_LBFGS; 
float * y_LBFGS, * s_LBFGS, * q_LBFGS, * r_LBFGS;
int NLBFGS_class, LBFGS_pointer, NLBFGS_vec;

/* Variables for energy weighted gradient */
float ** Ws, **Wr, **We;

/* parameters for FWI-workflow */
int stagemax=0, nstage;

/*vector for abort criterion*/
float * L2_hist=NULL;

/* help variable for MIN_ITER */
int min_iter_help=0;

/* parameters for gravity inversion */
float * gz_mod, * gz_res;
float ** gravpos=NULL, ** rho_grav=NULL, ** rho_grav_ext=NULL;
float ** grad_grav=NULL;
int ngrav=0, nxgrav, nygrav;
float L2_grav, FWImax, GRAVmax, FWImax_all, GRAVmax_all ;
char jac_grav[STRING_SIZE];

FILE *FPL2, *FP_stage, *FP_GRAV, *LAMBDA;

if (MYID == 0){
   time1=MPI_Wtime(); 
   clock();
}

/* open log-file (each PE is using different file) */
/*	fp=stdout; */
sprintf(ext,".%i",MYID);  
strcat(LOG_FILE,ext);

if ((MYID==0) && (LOG==1)) FP=stdout;
else FP=fopen(LOG_FILE,"w");
fprintf(FP," This is the log-file generated by PE %d \n\n",MYID);

/* ----------------------- */
/* define FD grid geometry */
/* ----------------------- */

/* domain decomposition */
initproc();

NT=iround(TIME/DT); /* number of timesteps */

/* output of parameters to log-file or stdout */
if (MYID==0) write_par(FP);

/* NXG, NYG denote size of the entire (global) grid */
NXG=NX;
NYG=NY;

/* In the following, NX and NY denote size of the local grid ! */
NX = IENDX;
NY = IENDY;

NTDTINV=ceil((float)NT/(float)DTINV);		/* round towards next higher integer value */

/* save every IDXI and IDYI spatial point during the forward modelling */
IDXI=1;
IDYI=1;

NXNYI=(NX/IDXI)*(NY/IDYI);
SHOTINC=1;

/* use only every DTINV time sample for the inversion */
DTINV_help=ivector(1,NT);

/* read parameters from workflow-file (stdin) */
FP_stage=fopen(FILEINP1,"r");
if(FP_stage==NULL) {
	if (MYID == 0){
		printf("\n==================================================================\n");
		printf(" Cannot open Denise workflow input file %s \n",FILEINP1);
		printf("\n==================================================================\n\n");
		err(" --- ");
	}
}

/* estimate number of lines in FWI-workflow */
i=0;
stagemax=0;
while ((i=fgetc(FP_stage)) != EOF)
if (i=='\n') ++stagemax;
rewind(FP_stage);
stagemax--;
fclose(FP_stage);

/* define data structures for PSV problem */
struct wavePSV;
struct wavePSV_PML;
struct matPSV;
struct fwiPSV;
struct mpiPSV;
struct seisPSV;
struct seisPSVfwi;
struct acq;

nd = FDORDER/2 + 1;
fdo3 = 2*nd;
buffsize=2.0*2.0*fdo3*(NX +NY)*sizeof(MPI_FLOAT);

/* allocate buffer for buffering messages */
buff_addr=malloc(buffsize);
if (!buff_addr) err("allocation failure for buffer for MPI_Bsend !");
MPI_Buffer_attach(buff_addr,buffsize);

/* allocation for request and status arrays */
req_send=(MPI_Request *)malloc(REQUEST_COUNT*sizeof(MPI_Request));
req_rec=(MPI_Request *)malloc(REQUEST_COUNT*sizeof(MPI_Request));
send_statuses=(MPI_Status *)malloc(REQUEST_COUNT*sizeof(MPI_Status));
rec_statuses=(MPI_Status *)malloc(REQUEST_COUNT*sizeof(MPI_Status));

/* --------- add different modules here ------------------------ */
ns=NT;	/* in a FWI one has to keep all samples of the forward modeled data
	at the receiver positions to calculate the adjoint sources and to do 
	the backpropagation; look at function saveseis_glob.c to see that every
	NDT sample for the forward modeled wavefield is written to su files*/

if (SEISMO){

   acq.recpos=receiver(FP, &ntr, ishot);
   acq.recswitch = ivector(1,ntr);
   acq.recpos_loc = splitrec(acq.recpos,&ntr_loc, ntr, acq.recswitch);
   ntr_glob=ntr;
   ntr=ntr_loc;
   
   if(N_STREAMER>0){
     free_imatrix(acq.recpos,1,3,1,ntr_glob);
     if(ntr>0) free_imatrix(acq.recpos_loc,1,3,1,ntr);
     free_ivector(acq.recswitch,1,ntr_glob);
   }
   
}

if(N_STREAMER==0){

   /* Memory for seismic data */
   alloc_seisPSV(ntr,ns,&seisPSV);

   /* Memory for FWI seismic data */ 
   alloc_seisPSVfwi(ntr,ntr_glob,ns,&seisPSVfwi);

}

/* Memory for full data seismograms */
alloc_seisPSVfull(&seisPSV,ntr_glob);

/* memory allocation for abort criterion*/
L2_hist = vector(1,1000);

/* estimate memory requirement of the variables in megabytes*/
	
switch (SEISMO){
case 1 : /* particle velocities only */
	nseismograms=2;	
	break;	
case 2 : /* pressure only */
	nseismograms=1;	
	break;	
case 3 : /* curl and div only */
	nseismograms=2;		
	break;	
case 4 : /* everything */
	nseismograms=5;		
	break;
}		

/* calculate memory requirements for PSV forward problem */
mem_fwiPSV(nseismograms,ntr,ns,fdo3,nd,buffsize,ntr_glob);

/* Define gradient formulation */
/* GRAD_FORM = 1 - stress-displacement gradients */
/* GRAD_FORM = 2 - stress-velocity gradients for decomposed impedance matrix */
GRAD_FORM = 1;

if(GRAVITY==1 || GRAVITY==2){
  
  if(GRAV_TYPE == 1){
  sprintf(GRAV_DATA_OUT, "./gravity/grav_mod.dat"); /* output file of gravity data */
  sprintf(GRAV_DATA_IN, "./gravity/grav_field.dat");  /* input file of gravity data */
  }
  if(GRAV_TYPE == 2){
  sprintf(GRAV_DATA_OUT, "./gravity/grav_grad_mod.dat"); /* output file of gravity gradient data */
  sprintf(GRAV_DATA_IN, "./gravity/grav_grad_field.dat");  /* input file of gravity gradientdata */
  }
  sprintf(GRAV_STAT_POS, "./gravity/grav_stat.dat"); /* file with station positions for gravity modelling */

  /* size of the extended gravity model */
  nxgrav = NXG + 2*NGRAVB;
  nygrav = NYG + NGRAVB;

}

/* allocate memory for PSV forward problem */
alloc_PSV(&wavePSV,&wavePSV_PML);

/* calculate damping coefficients for CPMLs (PSV problem)*/
if(FW>0){PML_pro(wavePSV_PML.d_x, wavePSV_PML.K_x, wavePSV_PML.alpha_prime_x, wavePSV_PML.a_x, wavePSV_PML.b_x, wavePSV_PML.d_x_half, wavePSV_PML.K_x_half, wavePSV_PML.alpha_prime_x_half, wavePSV_PML.a_x_half, 
                 wavePSV_PML.b_x_half, wavePSV_PML.d_y, wavePSV_PML.K_y, wavePSV_PML.alpha_prime_y, wavePSV_PML.a_y, wavePSV_PML.b_y, wavePSV_PML.d_y_half, wavePSV_PML.K_y_half, wavePSV_PML.alpha_prime_y_half, 
                 wavePSV_PML.a_y_half, wavePSV_PML.b_y_half);
}

/* allocate memory for PSV material parameters */
alloc_matPSV(&matPSV);

/* allocate memory for PSV FWI parameters */
alloc_fwiPSV(&fwiPSV);

/* allocate memory for PSV MPI variables */
alloc_mpiPSV(&mpiPSV);

/* Variables for the l-BFGS method */
if(GRAD_METHOD==2){

  NLBFGS_class = 3;                 /* number of parameter classes */ 
  NLBFGS_vec = NLBFGS_class*NX*NY;  /* length of one LBFGS-parameter class */
  LBFGS_pointer = 1;                /* initiate pointer in the cyclic LBFGS-vectors */
  
  y_LBFGS  =  vector(1,NLBFGS_vec*NLBFGS);
  s_LBFGS  =  vector(1,NLBFGS_vec*NLBFGS);

  q_LBFGS  =  vector(1,NLBFGS_vec);
  r_LBFGS  =  vector(1,NLBFGS_vec);

  rho_LBFGS = vector(1,NLBFGS);
  alpha_LBFGS = vector(1,NLBFGS);
  beta_LBFGS = vector(1,NLBFGS);
  
}

taper_coeff=  matrix(1,NY,1,NX);

/* memory for source position definition */
acq.srcpos1=fmatrix(1,8,1,1);

/* memory of L2 norm */
L2t = vector(1,4);
epst1 = vector(1,3);
	
fprintf(FP," ... memory allocation for PE %d was successfull.\n\n", MYID);

/* Holberg coefficients for FD operators*/
hc = holbergcoeff();

MPI_Barrier(MPI_COMM_WORLD);

/* Reading source positions from SOURCE_FILE */ 	
acq.srcpos=sources(&nsrc);
nsrc_glob=nsrc;


/* create model grids */
if(L){
	if (READMOD) readmod_visc_PSV(matPSV.prho,matPSV.ppi,matPSV.pu,matPSV.ptaus,matPSV.ptaup,matPSV.peta);
		else model(matPSV.prho,matPSV.ppi,matPSV.pu,matPSV.ptaus,matPSV.ptaup,matPSV.peta);
} else{
	if (READMOD) readmod_elastic_PSV(matPSV.prho,matPSV.ppi,matPSV.pu);
    		else model_elastic(matPSV.prho,matPSV.ppi,matPSV.pu);
}

/* check if the FD run will be stable and free of numerical dispersion */
if(L){
	checkfd_ssg_visc(FP,matPSV.prho,matPSV.ppi,matPSV.pu,matPSV.ptaus,matPSV.ptaup,matPSV.peta,hc);
} else{
	checkfd_ssg_elastic(FP,matPSV.prho,matPSV.ppi,matPSV.pu,hc);
}


if(GRAVITY==1 || GRAVITY==2){
 
  /* read station positions */
  MPI_Barrier(MPI_COMM_WORLD);
  gravpos=read_grav_pos(&ngrav);

  /* define model and residual data vector for gz (z-component of the gravity field) */
  gz_mod = vector(1,ngrav);
  gz_res = vector(1,ngrav);

  /* only forward modelling of gravity data */
  if(GRAVITY==1){

    /* global density model */
    rho_grav =  matrix(1,NYG,1,NXG);
    rho_grav_ext =  matrix(1,nygrav,1,nxgrav);

    read_density_glob(rho_grav,1);
    extend_mod(rho_grav,rho_grav_ext,nxgrav,nygrav);
    grav_mod(rho_grav_ext,ngrav,gravpos,gz_mod,nxgrav,nygrav,NZGRAV);

    free_matrix(rho_grav,1,NYG,1,NXG);
    free_matrix(rho_grav_ext,1,nygrav,1,nxgrav);

  }

  if(GRAVITY==2){
    grad_grav =  matrix(1,NY,1,NX);
  }

} 
      
SHOTINC=1;
    
iter_true=1;
/* Begin of FWI-workflow */
for(nstage=1;nstage<=stagemax;nstage++){

/* read workflow input file *.inp */
FP_stage=fopen(FILEINP1,"r");
read_par_inv(FP_stage,nstage,stagemax);
/*fclose(FP_stage);*/

if((EPRECOND==1)||(EPRECOND==3)){
  Ws = matrix(1,NY,1,NX); /* total energy of the source wavefield */
  Wr = matrix(1,NY,1,NX); /* total energy of the receiver wavefield */
  We = matrix(1,NY,1,NX); /* total energy of source and receiver wavefield */
}

FC=FC_END;

iter=1;
/* --------------------------------------
 * Begin of Full Waveform iteration loop
 * -------------------------------------- */
while(iter<=ITERMAX){

if(GRAD_METHOD==2){
  
  /* increase pointer to LBFGS-vector*/
  if(iter>2){
    LBFGS_pointer++;
  }
  
  /* if LBFGS-pointer > NLBFGS -> set LBFGS_pointer=1 */ 
  if(LBFGS_pointer>NLBFGS){LBFGS_pointer=1;}

}

if (MYID==0)
   {
   time2=MPI_Wtime();
   fprintf(FP,"\n\n\n ------------------------------------------------------------------\n");
   fprintf(FP,"\n\n\n                   TDFWI ITERATION %d \t of %d \n",iter,ITERMAX);
   fprintf(FP,"\n\n\n ------------------------------------------------------------------\n");
   }

/* For the calculation of the material parameters between gridpoints
   they have to be averaged. For this, values lying at 0 and NX+1,
   for example, are required on the local grid. These are now copied from the
   neighbouring grids */		
if (L){
	matcopy_PSV(matPSV.prho,matPSV.ppi,matPSV.pu,matPSV.ptaus,matPSV.ptaup);
} else{
	matcopy_elastic_PSV(matPSV.prho,matPSV.ppi,matPSV.pu);
}

MPI_Barrier(MPI_COMM_WORLD);

av_mue(matPSV.pu,matPSV.puipjp,matPSV.prho);
av_rho(matPSV.prho,matPSV.prip,matPSV.prjp);
if (L) av_tau(matPSV.ptaus,matPSV.ptausipjp);


/* Preparing memory variables for update_s (viscoelastic) */
if (L) prepare_update_s_visc_PSV(matPSV.etajm,matPSV.etaip,matPSV.peta,matPSV.fipjp,matPSV.pu,matPSV.puipjp,matPSV.ppi,matPSV.prho,matPSV.ptaus,matPSV.ptaup,matPSV.ptausipjp,matPSV.f,matPSV.g,
		matPSV.bip,matPSV.bjm,matPSV.cip,matPSV.cjm,matPSV.dip,matPSV.d,matPSV.e);


if(iter_true==1){

    for (i=1;i<=NX;i=i+IDX){ 
	for (j=1;j<=NY;j=j+IDY){
	
	if(INVMAT1==1){
	
	  fwiPSV.Vp0[j][i] = matPSV.ppi[j][i];
	  fwiPSV.Vs0[j][i] = matPSV.pu[j][i];
	  fwiPSV.Rho0[j][i] = matPSV.prho[j][i];

        }
	  
                 
		 
	if(INVMAT1==2){
        
	  fwiPSV.Vp0[j][i] = sqrt((matPSV.ppi[j][i]+2.0*matPSV.pu[j][i])*matPSV.prho[j][i]);
	  fwiPSV.Vs0[j][i] = sqrt(matPSV.pu[j][i]*matPSV.prho[j][i]);
	  fwiPSV.Rho0[j][i] = matPSV.prho[j][i];
	
	}
	 
	if(INVMAT1==3){
        
	  fwiPSV.Vp0[j][i] = matPSV.ppi[j][i];
	  fwiPSV.Vs0[j][i] = matPSV.pu[j][i];
	  fwiPSV.Rho0[j][i] = matPSV.prho[j][i];
	
	}  
	
    }
    }

/* ----------------------------- */
/* calculate Covariance matrices */
/* ----------------------------- */

	 Vp_avg = 0.0;
	 Vs_avg = 0.0;
	 rho_avg = 0.0;
	 
        for (i=1;i<=NX;i=i+IDX){
           for (j=1;j<=NY;j=j+IDY){
	  
		 /* calculate average Vp, Vs */
                 Vp_avg+=matPSV.ppi[j][i];
		 Vs_avg+=matPSV.pu[j][i];
		 
		 /* calculate average rho */
		 rho_avg+=matPSV.prho[j][i];
	
           }
        }
		
        /* calculate average Vp, Vs and rho of all CPUs*/
        Vp_sum = 0.0;
        MPI_Allreduce(&Vp_avg,&Vp_sum,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
        Vp_avg=Vp_sum;
	
	Vs_sum = 0.0;
        MPI_Allreduce(&Vs_avg,&Vs_sum,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
        Vs_avg=Vs_sum;
	
	rho_sum = 0.0;
        MPI_Allreduce(&rho_avg,&rho_sum,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
        rho_avg=rho_sum;
	
	Vp_avg /=NXG*NYG; 
	Vs_avg /=NXG*NYG; 
	rho_avg /=NXG*NYG;
	
	if(MYID==0){
           printf("Vp_avg = %.0f \t Vs_avg = %.0f \t rho_avg = %.0f \n ",Vp_avg,Vs_avg,rho_avg);	
	}
	
	C_vp = Vp_avg;
	C_vs = Vs_avg;
	C_rho = rho_avg;


}

/* Open Log File for L2 norm */
if(MYID==0){
  if(iter_true==1){
    FPL2=fopen(MISFIT_LOG_FILE,"w");
  }

  if(iter_true>1){
    FPL2=fopen(MISFIT_LOG_FILE,"a");
  }
}

/* ---------------------------------------------------------------------------------------------------- */
/* --------- Calculate gradient and objective function using the adjoint state method ----------------- */
/* ---------------------------------------------------------------------------------------------------- */

L2sum = grad_obj_psv(&wavePSV, &wavePSV_PML, &matPSV, &fwiPSV, &mpiPSV, &seisPSV, &seisPSVfwi, &acq, hc, iter, nsrc, ns, ntr, ntr_glob, 
nsrc_glob, nsrc_loc, ntr_loc, nstage, We, Ws, Wr, taper_coeff, hin, DTINV_help, req_send, req_rec);

L2t[1]=L2sum;
L2t[4]=L2sum;

if(GRAVITY==2){

  /* save seismic L2-norm of seismic data residuals */
  L2sum = L2t[1];

  /* global density model */
  rho_grav =  matrix(1,NYG,1,NXG);
  rho_grav_ext =  matrix(1,nygrav,1,nxgrav);

  /* model gravity data */
  /* save current density model */
  sprintf(jac_grav,"%s_tmp.rho.%i%i",JACOBIAN,POS[1],POS[2]);
  FP_GRAV=fopen(jac_grav,"wb");

  for (i=1;i<=NX;i=i+IDX){
      for (j=1;j<=NY;j=j+IDY){
          fwrite(&matPSV.prho[j][i],sizeof(float),1,FP_GRAV);
      }
  }
	
  fclose(FP_GRAV);

  MPI_Barrier(MPI_COMM_WORLD);
          
  /* merge model file */ 
  sprintf(jac_grav,"%s_tmp.rho",JACOBIAN);
  if (MYID==0) mergemod(jac_grav,3);
  
  MPI_Barrier(MPI_COMM_WORLD);
  
  /* gravity forward modelling */
  read_density_glob(rho_grav,2);
  extend_mod(rho_grav,rho_grav_ext,nxgrav,nygrav);
  grav_mod(rho_grav_ext,ngrav,gravpos,gz_mod,nxgrav,nygrav,NZGRAV);

  /* calculate gravity data residuals */
  L2_grav=calc_res_grav(ngrav,gz_mod,gz_res);

  /* calculate lambda 1 */
  if(iter==1){
  	LAM_GRAV = GAMMA_GRAV * (L2sum/L2_grav);
  }

  /* add gravity penalty term to the seismic objective function */
  L2t[1]+=LAM_GRAV * L2_grav;
  L2t[4]+=LAM_GRAV * L2_grav;

  /* calculate gravity gradient */
  for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
           grad_grav[j][i]=0.0;
       }
  }
  grav_grad(ngrav,gravpos,grad_grav,gz_res);
  
  MPI_Barrier(MPI_COMM_WORLD);        

  /* merge model file */
  sprintf(jac,"%s_grav",JACOBIAN);          
  if (MYID==0) mergemod(jac,3); 

  /* free memory */
  free_matrix(rho_grav,1,NYG,1,NXG);
  free_matrix(rho_grav_ext,1,nygrav,1,nxgrav);
  

}

/* Interpolate missing spatial gradient values in case IDXI > 1 || IDXY > 1 */
/* ------------------------------------------------------------------------ */

if((IDXI>1)||(IDYI>1)){

   interpol(IDXI,IDYI,fwiPSV.waveconv,1);
   interpol(IDXI,IDYI,fwiPSV.waveconv_u,1);
   interpol(IDXI,IDYI,fwiPSV.waveconv_rho,1);

}

/* Preconditioning of gradients after shot summation */
precond_PSV(&fwiPSV,&acq,nsrc,ntr_glob,taper_coeff,FP_GRAV);

/* Add gravity gradient to FWI density gradient */
/* -------------------------------------------- */
	
   if(GRAVITY==2){
		 		 
     /* calculate maximum values of waveconv_rho and grad_grav */
     FWImax = 0.0;
     GRAVmax = 0.0;
	
     for (i=1;i<=NX;i++){
        for (j=1;j<=NY;j++){
		
	    if(fabs(fwiPSV.waveconv_rho[j][i])>FWImax){FWImax=fabs(fwiPSV.waveconv_rho[j][i]);}
	    if(fabs(grad_grav[j][i])>GRAVmax){GRAVmax=fabs(grad_grav[j][i]);}
		
        }
     }
	
     MPI_Allreduce(&FWImax,&FWImax_all,  1,MPI_FLOAT,MPI_MAX,MPI_COMM_WORLD);
     MPI_Allreduce(&GRAVmax,&GRAVmax_all,1,MPI_FLOAT,MPI_MAX,MPI_COMM_WORLD);
		
    /* calculate lambda 2, normalized with respect to the maximum gradients */
	if(iter==1){
		LAM_GRAV_GRAD = GAMMA_GRAV * (FWImax_all/GRAVmax_all);
	} 
		 
     /* add gravity gradient to seismic gradient with respect to the density */
     for (i=1;i<=NX;i++){
        for (j=1;j<=NY;j++){
			
            fwiPSV.waveconv_rho[j][i] += LAM_GRAV_GRAD * grad_grav[j][i];
				
        }
     }
		
   }

/* Use preconditioned conjugate gradient optimization method */
if(GRAD_METHOD==1){
  PCG(fwiPSV.waveconv, taper_coeff, nsrc, acq.srcpos, acq.recpos, ntr_glob, iter, fwiPSV.gradp, fwiPSV.waveconv_u, fwiPSV.gradp_u, fwiPSV.waveconv_rho, fwiPSV.gradp_rho);
}

/* Use l-BFGS optimization */
if(GRAD_METHOD==2){ 

    /* store models and gradients in l-BFGS vectors */
    store_LBFGS_PSV(taper_coeff, nsrc, acq.srcpos, acq.recpos, ntr_glob, iter, fwiPSV.waveconv, fwiPSV.gradp, fwiPSV.waveconv_u, fwiPSV.gradp_u, fwiPSV.waveconv_rho, 
		    fwiPSV.gradp_rho, y_LBFGS, s_LBFGS, q_LBFGS, matPSV.ppi, matPSV.pu, matPSV.prho, NXNYI, LBFGS_pointer, NLBFGS, NLBFGS_vec);

    /* apply l-BFGS optimization */
    LBFGS(iter, y_LBFGS, s_LBFGS, rho_LBFGS, alpha_LBFGS, q_LBFGS, r_LBFGS, beta_LBFGS, LBFGS_pointer, NLBFGS, NLBFGS_vec);

    /* extract gradients and save old models/gradients for next l-BFGS iteration */
    extract_LBFGS_PSV(iter, fwiPSV.waveconv, fwiPSV.gradp, fwiPSV.waveconv_u, fwiPSV.gradp_u, fwiPSV.waveconv_rho, fwiPSV.gradp_rho, matPSV.ppi, matPSV.pu, matPSV.prho, r_LBFGS);

}

opteps_vp=0.0;
opteps_vs=0.0;
opteps_rho=0.0;

/* ============================================================================================================================*/
/* =============================================== test loop L2 ===============================================================*/
/* ============================================================================================================================*/

/* set min_iter_help to initial global value of MIN_ITER */
if(iter==1){min_iter_help=MIN_ITER;}

/* Estimate optimum step length ... */

/* ... by line search (parabolic fitting) */
eps_scale = step_length_est_psv(&wavePSV,&wavePSV_PML,&matPSV,&fwiPSV,&mpiPSV,&seisPSV,&seisPSVfwi,&acq,hc,iter,nsrc,ns,ntr,ntr_glob,epst1,L2t,nsrc_glob,nsrc_loc,&step1,&step3,nxgrav,nygrav,ngrav,gravpos,gz_mod,NZGRAV,
                                ntr_loc,Ws,Wr,hin,DTINV_help,req_send,req_rec);

/* no model update due to steplength estimation failed or update with the smallest steplength if the number of iteration is smaller than the minimum number of iteration per
frequency MIN_ITER */
if((iter>min_iter_help)&&(step1==0)){ 
	eps_scale=0.0;
	opteps_vp=0.0;
}
else{
	opteps_vp=eps_scale;
}

/* write log-parameter files */
if(MYID==0){
printf("MYID = %d \t opteps_vp = %e \t opteps_vs = %e \t opteps_rho = %e \n",MYID,opteps_vp,opteps_vs,opteps_rho);
printf("MYID = %d \t L2t[1] = %e \t L2t[2] = %e \t L2t[3] = %e \t L2t[4] = %e \n",MYID,L2t[1],L2t[2],L2t[3],L2t[4]);
printf("MYID = %d \t epst1[1] = %e \t epst1[2] = %e \t epst1[3] = %e \n",MYID,epst1[1],epst1[2],epst1[3]);

/*output of log file for combined inversion*/
if(iter_true==1){
    LAMBDA = fopen("gravity/lambda.dat","w");
}
if(iter_true>1){
    LAMBDA = fopen("gravity/lambda.dat","a");
}
fprintf(LAMBDA,"%d \t %d \t %e \t %e \t %e \t %e \t %e \t %e \t %e \n",nstage,iter,LAM_GRAV,L2sum,L2_grav,L2t[4],LAM_GRAV_GRAD,FWImax_all,GRAVmax_all);
fclose(LAMBDA);

}

if(MYID==0){
if (TIME_FILT==0){
	fprintf(FPL2,"%e \t %e \t %e \t %e \t %e \t %e \t %e \t %e \t %d \n",opteps_vp,epst1[1],epst1[2],epst1[3],L2t[1],L2t[2],L2t[3],L2t[4],nstage);}
else{
	fprintf(FPL2,"%e \t %e \t %e \t %e \t %e \t %e \t %e \t %e \t %f \t %f \t %d \n",opteps_vp,epst1[1],epst1[2],epst1[3],L2t[1],L2t[2],L2t[3],L2t[4],FC_START,FC,nstage);}}


/* saving history of final L2*/
L2_hist[iter]=L2t[4];
s=0;


/* calculate optimal change in the material parameters */
eps_true=calc_mat_change_test_PSV(fwiPSV.waveconv,fwiPSV.waveconv_rho,fwiPSV.waveconv_u,fwiPSV.prho_old,matPSV.prho,fwiPSV.ppi_old,matPSV.ppi,fwiPSV.pu_old,matPSV.pu,iter,1,eps_scale,0);

if (MODEL_FILTER){
/* smoothing the velocity models vp and vs */
smooth_model(matPSV.ppi,matPSV.pu,matPSV.prho,iter);
}

if(MYID==0){	
/*	fprintf(FPL2,"=============================================================\n");
	fprintf(FPL2,"=============================================================\n");
	fprintf(FPL2,"STATISTICS FOR ITERATION STEP %d \n",iter);
	fprintf(FPL2,"=============================================================\n");
	fprintf(FPL2,"=============================================================\n");*/
/*	fprintf(FPL2,"Low-pass filter at %e Hz\n",freq);
	fprintf(FPL2,"----------------------------------------------\n");
*/	/*fprintf(FPL2,"L2 at iteration step n = %e \n",L2);*/
/*        fprintf(FPL2,"%e \t %e \t %e \t %e \t %e \t %e \t %e \t %e \n",EPSILON,EPSILON_u,EPSILON_rho,L2t[4],betaVp,betaVs,betarho,sqrt(C_vp));*/

	/*fprintf(FPL2,"----------------------------------------------\n");*/
/*	fprintf(FPL2,"=============================================================\n");
	fprintf(FPL2,"=============================================================\n\n\n");*/
}

if(MYID==0){
  fclose(FPL2);
}

if (iter>min_iter_help){

float diff=0.0, pro=PRO;

/* calculating differnce of the actual L2 and before two iterations, dividing with L2_hist[iter-2] provide changing in procent*/
diff=fabs((L2_hist[iter-2]-L2_hist[iter])/L2_hist[iter-2]);
	
	if((diff<=pro)||(step3==1)){
        
        	/* output of the model at the end of given corner frequency */
        	model_freq_out_PSV(matPSV.ppi,matPSV.prho,matPSV.pu,nstage,FC);
		s=1;
		min_iter_help=0;
		min_iter_help=iter+MIN_ITER;
		iter=0;

        	if(GRAD_METHOD==2){
	  		zero_LBFGS(NLBFGS, NLBFGS_vec, y_LBFGS, s_LBFGS, q_LBFGS, r_LBFGS, alpha_LBFGS, beta_LBFGS, rho_LBFGS);
          		LBFGS_pointer = 1;  
		}

        	if(MYID==0){
			if(step3==1){
			        printf("\n Steplength estimation failed step3=%d \n Changing to next FWI stage \n",step3);
			}
			else{
  				printf("\n Reached the abort criterion of pro=%e and diff=%e \n Changing to next FWI stage \n",pro,diff);
			}
	
		}
		break;
	}
}

iter++;
iter_true++;

/* ====================================== */
} /* end of fullwaveform iteration loop*/
/* ====================================== */

} /* End of FWI-workflow loop */

/* deallocate memory for PSV forward problem */
dealloc_PSV(&wavePSV,&wavePSV_PML);

/* deallocation of memory */
free_matrix(fwiPSV.Vp0,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.Vs0,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.Rho0,-nd+1,NY+nd,-nd+1,NX+nd);

free_matrix(matPSV.prho,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.prho_old,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(matPSV.prip,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(matPSV.prjp,-nd+1,NY+nd,-nd+1,NX+nd);

free_matrix(matPSV.ppi,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.ppi_old,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(matPSV.pu,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.pu_old,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(matPSV.puipjp,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_lam,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_shot,-nd+1,NY+nd,-nd+1,NX+nd);

free_matrix(mpiPSV.bufferlef_to_rig,1,NY,1,fdo3);
free_matrix(mpiPSV.bufferrig_to_lef,1,NY,1,fdo3);
free_matrix(mpiPSV.buffertop_to_bot,1,NX,1,fdo3);
free_matrix(mpiPSV.bufferbot_to_top,1,NX,1,fdo3);

free_vector(hc,0,6);

free_matrix(fwiPSV.gradg,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.gradp,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.gradg_rho,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.gradp_rho,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_rho,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_rho_s,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_rho_shot,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.gradg_u,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.gradp_u,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_u,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_mu,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(fwiPSV.waveconv_u_shot,-nd+1,NY+nd,-nd+1,NX+nd);

free_vector(fwiPSV.forward_prop_x,1,NY*NX*NT);
free_vector(fwiPSV.forward_prop_y,1,NY*NX*NT);
free_vector(fwiPSV.forward_prop_rho_x,1,NY*NX*NT);
free_vector(fwiPSV.forward_prop_rho_y,1,NY*NX*NT);
free_vector(fwiPSV.forward_prop_u,1,NY*NX*NT);

if (nsrc_loc>0){	
	free_matrix(acq.signals,1,nsrc_loc,1,NT);
	free_matrix(acq.srcpos_loc,1,8,1,nsrc_loc);
	free_matrix(acq.srcpos_loc_back,1,6,1,nsrc_loc);
}		   

 /* free memory for global source positions */
 free_matrix(acq.srcpos,1,8,1,nsrc);

 /* free memory for source position definition */
 free_matrix(acq.srcpos1,1,8,1,1);
 
 /* free memory for abort criterion */
 free_vector(L2_hist,1,1000);
 		
 free_vector(L2t,1,4);
 free_vector(epst1,1,3);

 if(N_STREAMER==0){

    if (SEISMO) free_imatrix(acq.recpos,1,3,1,ntr_glob);

    if ((ntr>0) && (SEISMO)){

            free_imatrix(acq.recpos_loc,1,3,1,ntr);
            acq.recpos_loc = NULL;
 
            switch (SEISMO){
            case 1 : /* particle velocities only */
                    free_matrix(seisPSV.sectionvx,1,ntr,1,ns);
                    free_matrix(seisPSV.sectionvy,1,ntr,1,ns);
                    seisPSV.sectionvx=NULL;
                    seisPSV.sectionvy=NULL;
                    break;
             case 2 : /* pressure only */
                    free_matrix(seisPSV.sectionp,1,ntr,1,ns);
                    break;
             case 3 : /* curl and div only */
                    free_matrix(seisPSV.sectioncurl,1,ntr,1,ns);
                    free_matrix(seisPSV.sectiondiv,1,ntr,1,ns);
                    break;
             case 4 : /* everything */
                    free_matrix(seisPSV.sectionvx,1,ntr,1,ns);
                    free_matrix(seisPSV.sectionvy,1,ntr,1,ns);
                    free_matrix(seisPSV.sectionp,1,ntr,1,ns);
                    free_matrix(seisPSV.sectioncurl,1,ntr,1,ns);
                    free_matrix(seisPSV.sectiondiv,1,ntr,1,ns);
                    break;

             }

    }

    free_matrix(seisPSVfwi.sectionread,1,ntr_glob,1,ns);
    free_ivector(acq.recswitch,1,ntr);
    
    if((QUELLTYPB==1)||(QUELLTYPB==3)||(QUELLTYPB==5)||(QUELLTYPB==7)){
       free_matrix(seisPSVfwi.sectionvxdata,1,ntr,1,ns);
       free_matrix(seisPSVfwi.sectionvxdiff,1,ntr,1,ns);
       free_matrix(seisPSVfwi.sectionvxdiffold,1,ntr,1,ns);
    }

    if((QUELLTYPB==1)||(QUELLTYPB==2)||(QUELLTYPB==6)||(QUELLTYPB==7)){    
       free_matrix(seisPSVfwi.sectionvydata,1,ntr,1,ns);
       free_matrix(seisPSVfwi.sectionvydiff,1,ntr,1,ns);
       free_matrix(seisPSVfwi.sectionvydiffold,1,ntr,1,ns);
    }
    
    if(QUELLTYPB>=4){    
       free_matrix(seisPSVfwi.sectionpdata,1,ntr,1,ns);
       free_matrix(seisPSVfwi.sectionpdiff,1,ntr,1,ns);
       free_matrix(seisPSVfwi.sectionpdiffold,1,ntr,1,ns);
    }
    
 }

 if(SEISMO){
  free_matrix(seisPSV.fulldata,1,ntr_glob,1,NT); 
 }

 if(SEISMO==1){
  free_matrix(seisPSV.fulldata_vx,1,ntr_glob,1,NT);
  free_matrix(seisPSV.fulldata_vy,1,ntr_glob,1,NT);
 }

 if(SEISMO==2){
  free_matrix(seisPSV.fulldata_p,1,ntr_glob,1,NT);
 } 
 
 if(SEISMO==3){
  free_matrix(seisPSV.fulldata_curl,1,ntr_glob,1,NT);
  free_matrix(seisPSV.fulldata_div,1,ntr_glob,1,NT);
 }

 if(SEISMO==4){
  free_matrix(seisPSV.fulldata_vx,1,ntr_glob,1,NT);
  free_matrix(seisPSV.fulldata_vy,1,ntr_glob,1,NT);
  free_matrix(seisPSV.fulldata_p,1,ntr_glob,1,NT); 
  free_matrix(seisPSV.fulldata_curl,1,ntr_glob,1,NT);
  free_matrix(seisPSV.fulldata_div,1,ntr_glob,1,NT);
 }

 free_ivector(DTINV_help,1,NT);
 
 /* free memory for viscoelastic modeling variables */
 if (L) {
		free_matrix(matPSV.ptaus,-nd+1,NY+nd,-nd+1,NX+nd);
		free_matrix(matPSV.ptausipjp,-nd+1,NY+nd,-nd+1,NX+nd);
		free_matrix(matPSV.ptaup,-nd+1,NY+nd,-nd+1,NX+nd);
		free_vector(matPSV.peta,1,L);
		free_vector(matPSV.etaip,1,L);
		free_vector(matPSV.etajm,1,L);
		free_vector(matPSV.bip,1,L);
		free_vector(matPSV.bjm,1,L);
		free_vector(matPSV.cip,1,L);
		free_vector(matPSV.cjm,1,L);
		free_matrix(matPSV.f,-nd+1,NY+nd,-nd+1,NX+nd);
		free_matrix(matPSV.g,-nd+1,NY+nd,-nd+1,NX+nd);
		free_matrix(matPSV.fipjp,-nd+1,NY+nd,-nd+1,NX+nd);
		free_f3tensor(matPSV.dip,-nd+1,NY+nd,-nd+1,NX+nd,1,L);
		free_f3tensor(matPSV.d,-nd+1,NY+nd,-nd+1,NX+nd,1,L);
		free_f3tensor(matPSV.e,-nd+1,NY+nd,-nd+1,NX+nd,1,L);
}

if(GRAVITY){

  free_matrix(gravpos,1,2,1,ngrav);
  free_vector(gz_mod,1,ngrav);
  free_vector(gz_res,1,ngrav);

  if(GRAVITY==2){
    free_matrix(grad_grav,1,NY,1,NX);
  }

}
 
/* de-allocate buffer for messages */
MPI_Buffer_detach(buff_addr,&buffsize);

MPI_Barrier(MPI_COMM_WORLD);

if (MYID==0){
	fprintf(FP,"\n **Info from main (written by PE %d): \n",MYID);
	fprintf(FP," CPU time of program per PE: %li seconds.\n",clock()/CLOCKS_PER_SEC);
	time8=MPI_Wtime();
	fprintf(FP," Total real time of program: %4.2f seconds.\n",time8-time1);
	time_av_v_update=time_av_v_update/(double)NT;
	time_av_s_update=time_av_s_update/(double)NT;
	time_av_v_exchange=time_av_v_exchange/(double)NT;
	time_av_s_exchange=time_av_s_exchange/(double)NT;
	time_av_timestep=time_av_timestep/(double)NT;
	/* fprintf(FP," Average times for \n");
	fprintf(FP," velocity update:  \t %5.3f seconds  \n",time_av_v_update);
	fprintf(FP," stress update:  \t %5.3f seconds  \n",time_av_s_update);
	fprintf(FP," velocity exchange:  \t %5.3f seconds  \n",time_av_v_exchange);
	fprintf(FP," stress exchange:  \t %5.3f seconds  \n",time_av_s_exchange);
	fprintf(FP," timestep:  \t %5.3f seconds  \n",time_av_timestep);*/
		
}

fclose(FP);


}
void model_elastic(float  **  rho, float **  pi, float **  u){


	/*--------------------------------------------------------------------------*/
	FILE *FP1, *FP2, *FP3;
	/* extern variables */
	extern float DH;
	extern int NX, NY, NXG, NYG,  POS[3], MYID;


	/* local variables */

	float Rho, Vp, Vs, Vpnm1, x, y, undf, r;
	float aund, ampund, FW, shiftx;
	int i, j, ii, jj;
	char modfile[STRING_SIZE];
	
        /* parameters for background */
	const float vp2=2000.0, vs2=vp2/sqrt(3.0), rho2=1000.0*0.31*pow(vp2,(1.0/4.0));
	
	/* parameters for sphere 1 and 2 */
	const float vp3=1500.0, vs3=vp3/sqrt(3.0), rho3=1000.0*0.31*pow(vp3,(1.0/4.0));
	
	/* location of the spheres */
	const float X01 = 80.0;
	const float Y01 = 130.0;
	
	/* radii of spheres */
        float A0, A1, A3, A4, lambda0, lambda1, lambda3, lambda4;
	float y0, y1, y2, y3, y4, y5, undy0, undy1, undy3, undy4;

	 
	 lambda0=1600.0;
              A0=50.0;
              y0=1200.0;
 
         lambda1=lambda0/2.0;
              A1=100.0;
              y1=1000.0;
 
              y2=800.0;
 
         lambda3=lambda0/2.0;
              A3=150.0;
              y3=600.0;
 
         lambda4=lambda0/2.0;
              A4=50.0;
              y4=410.0;
 
              y5=100.0;


        FP1=fopen("/fastfs/koehn/DENISE_backup/par/start/crase_smooth_model_vp.dat","r");
	FP2=fopen("/fastfs/koehn/DENISE_backup/par/start/crase_smooth_model_vs.dat","r");
	FP3=fopen("/fastfs/koehn/DENISE_backup/par/start/crase_smooth_model_rho.dat","r");
	        
	/* loop over global grid */
	for (i=1;i<=NXG;i++){
		for (j=1;j<=NYG;j++){
	
		                     
                       fscanf(FP1,"%e\n",&Vp);
		       fscanf(FP2,"%e\n",&Vs);
		       fscanf(FP3,"%e\n",&Rho);
				
			   			
			if ((POS[1]==((i-1)/NX)) && 
		   	 (POS[2]==((j-1)/NY))){
				ii=i-POS[1]*NX;
				jj=j-POS[2]*NY;

				u[jj][ii]=Vs*Vs*Rho;
				rho[jj][ii]=Rho;
				pi[jj][ii] = Vp*Vp*Rho - 2.0 * u[jj][ii];
				
				/*if(j==NYG){pi[jj][ii] = pi[jj-1][ii];}*/
			}
		}
	}	

		

	
	/* each PE writes his model to disk */
        sprintf(modfile,"model/waveform_test_model_u.bin");
        writemod(modfile,u,3);
	
	MPI_Barrier(MPI_COMM_WORLD);

	if (MYID==0) mergemod(modfile,3);
	
	
        sprintf(modfile,"model/waveform_test_model_pi.bin");
        writemod(modfile,pi,3);
	

	MPI_Barrier(MPI_COMM_WORLD);

	if (MYID==0) mergemod(modfile,3); 
	
	sprintf(modfile,"model/waveform_test_model_rho.bin");
        writemod(modfile,rho,3);
	

	MPI_Barrier(MPI_COMM_WORLD);

	if (MYID==0) mergemod(modfile,3);
	
	fclose(FP1);
	fclose(FP2);
	fclose(FP3);
}
void model(float  **  rho, float **  pi, float **  u, float **  taus, float **  taup, float *  eta){

	/*--------------------------------------------------------------------------*/
	/* extern variables */

	extern int NX, NY, NXG, NYG,  POS[3], L, MYID;
	extern char  MFILE[STRING_SIZE];	
	extern char INV_MODELFILE[STRING_SIZE];
	extern float DH, *FL, TAU, DT;
		/* local variables */
	float vp, vs, rhov, ts, tp, muv, piv, *pts;
	int i, j, ii, jj, l;
	char modfile[STRING_SIZE]; 
	
	FILE *flfile;
	int nodes;
	char cline[256];
	
	float *fldepth, *flrho, *flvp, *flvs;
	
	
	/*-----------------------------------------------------------------------*/
	
	nodes=7;

	fldepth=vector(1,nodes);
	flrho=vector(1,nodes);
	flvp=vector(1,nodes);
	flvs=vector(1,nodes);
	
	pts=vector(1,L);
	for (l=1;l<=L;l++) {
		pts[l]=1.0/(2.0*PI*FL[l]);
	        eta[l]=DT/pts[l];
	}
	
	/*read FL nodes from File*/
	
	flfile=fopen("model_true/model4.fl.dat","r");
	if (flfile==NULL) err(" FL-file could not be opened !");
	
	
	
	for (l=1;l<=nodes;l++){
		fgets(cline,255,flfile);
		if (cline[0]!='#'){
			sscanf(cline,"%f%f%f%f",&fldepth[l], &flrho[l], &flvp[l], &flvs[l]);
		}
		else l=l-1;
	
	}
	
	if(MYID==0){
	printf(" ------------------------------------------------------------------ \n\n");
	printf(" Information of FL nodes: \n\n");
	printf(" \t depth \t rho \t vp \t vs \n\n");
	
	for (l=1;l<=nodes;l++){
	printf(" \t %f \t %f \t %f \t %f \n\n",fldepth[l],flrho[l],flvp[l],flvs[l]);
	}
	printf(" ------------------------------------------------------------------ \n\n");
	}
	/*-----------------------------------------------------------------------*/
	
	
	/* loop over global grid */
		for (i=1;i<=NXG;i++){
			for (l=1;l<nodes;l++){
				for(j=(int)(fldepth[l]/DH)+1;j<=(int)(fldepth[l+1]/DH);j++){	
					
				  
					vp=0.0;
					vs=0.0; 
					rhov=0.0;
				  
					vp=(DH*(j-1)-fldepth[l])*(flvp[l+1]-flvp[l])/(fldepth[l+1]-fldepth[l])+flvp[l];
					vp=vp*1000.0;
					vs=(DH*(j-1)-fldepth[l])*(flvs[l+1]-flvs[l])/(fldepth[l+1]-fldepth[l])+flvs[l];
					vs=vs*1000.0;
					rhov=(DH*(j-1)-fldepth[l])*(flrho[l+1]-flrho[l])/(fldepth[l+1]-fldepth[l])+flrho[l];
					rhov=rhov*1000.0; 				

					muv=vs;
					piv=vp;
					ts=TAU;
					tp=TAU;
					
					/* only the PE which belongs to the current global gridpoint 
					  is saving model parameters in his local arrays */
					if ((POS[1]==((i-1)/NX)) && 
					    (POS[2]==((j-1)/NY))){
						ii=i-POS[1]*NX;
						jj=j-POS[2]*NY;
						

						u[jj][ii]=muv;
						rho[jj][ii]=rhov;
						pi[jj][ii]=piv;
						taus[jj][ii]=ts;
						taup[jj][ii]=tp;
					}
			     	}
			
			
				for (j=(int)(fldepth[nodes]/DH)+1;j<=NYG;j++){
			  
				vp=0.0; vs=0.0; rhov=0.0;
				vp=flvp[nodes]*1000.0; vs=flvs[nodes]*1000.0; rhov=flrho[nodes]*1000.0;
				
				muv=vs;
				piv=vp;
				ts=TAU;
				tp=TAU;

				/* only the PE which belongs to the current global gridpoint 
				  is saving model parameters in his local arrays */
				if ((POS[1]==((i-1)/NX)) && 
				    (POS[2]==((j-1)/NY))){
					ii=i-POS[1]*NX;
					jj=j-POS[2]*NY;
						
					u[jj][ii]=muv;
					rho[jj][ii]=rhov;
					pi[jj][ii]=piv;
					taus[jj][ii]=ts;
					taup[jj][ii]=tp;
					
				}
				}

			}
		}	

		
sprintf(modfile,"%s_rho_it_0.bin",INV_MODELFILE);
writemod(modfile,rho,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vs_it_0.bin",INV_MODELFILE);
writemod(modfile,u,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vp_it_0.bin",INV_MODELFILE);
writemod(modfile,pi,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

free_vector(fldepth,1,nodes);
free_vector(flrho,1,nodes);
free_vector(flvp,1,nodes);
free_vector(flvs,1,nodes);
free_vector(pts,1,L);
}
Example #8
0
void PCG(float ** waveconv, float ** taper_coeff, int nsrc, float ** srcpos, int ** recpos, int ntr_glob, int iter, float C_vp, float ** gradp, int nfstart_jac,
	     float ** waveconv_u, float C_vs, float ** gradp_u, float ** waveconv_rho, float C_rho, float ** gradp_rho){

	extern int NX, NY, IDX, IDY, SPATFILTER, GRAD_FILTER;
	extern int SWS_TAPER_GRAD_VERT, SWS_TAPER_GRAD_HOR, SWS_TAPER_GRAD_SOURCES, SWS_TAPER_FILE;
	extern int POS[3], MYID, GRAD_METHOD;
	extern char JACOBIAN[STRING_SIZE];
	
	char jac[225], jac2[225];
	int i, j;
	float betaz, betan, gradplastiter, gradclastiter, betar, beta;
	extern FILE *FP;
	FILE *FP3, *FP4, *FP6, *FP5;
	
/* =================================================================================================================================================== */
/* ===================================================================================================================================================== */
/* ===================================================== GRADIENT ZP ================================================================================== */
/* ===================================================================================================================================================== */
	
/* Preconditioning of the gradient */
/* ------------------------------- */

/* apply taper on the gradient */
/* --------------------------- */

if (SWS_TAPER_GRAD_VERT){   /*vertical gradient taper is applied*/
   taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,1);}

if (SWS_TAPER_GRAD_HOR){   /*horizontal gradient taper is applied*/
   taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,2);}

if (SWS_TAPER_GRAD_SOURCES){   /*cylindrical taper around sources is applied*/
   taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,3);}

if (SWS_TAPER_FILE){   /* read taper from BIN-File*/
   taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,4);}   

/* apply median filter at source positions */
/*median_src(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,iter,0);*/

/* apply wavenumber damping */
if(SPATFILTER==1){
  wavenumber(waveconv);
}

if(SPATFILTER==2){
  smooth2(waveconv);
}
  
/* save gradient */
/*sprintf(jac,"%s_g.old.%i%i",JACOBIAN,POS[1],POS[2]);
FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
           for (j=1;j<=NY;j=j+IDY){
                 fwrite(&waveconv[j][i],sizeof(float),1,FP3);
           }
        }
	
fclose(FP3);

MPI_Barrier(MPI_COMM_WORLD);*/
          
/* merge gradient file */ 
/*sprintf(jac,"%s_g.old",JACOBIAN);
if (MYID==0) mergemod(jac,3);*/
 
/* Normalize gradient to maximum value */
/*norm(waveconv,iter,1);*/

/* apply spatial wavelength filter */
/*if(SPATFILTER==1){
	if (MYID==0){
   	fprintf(FP,"\n Spatial filter is applied to gradient (written by PE %d)\n",MYID);}
        spat_filt(waveconv,iter,1);}*/

/* apply 2D-Gaussian filter*/
if(GRAD_FILTER==1){smooth_grad(waveconv,1);}

/* output of the preconditioned gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
      waveconv[j][i] = C_vp * waveconv[j][i];
	 gradp[j][i] = waveconv[j][i];
   }
}


/* save gradient for output as inversion result */
if(iter==nfstart_jac){
	sprintf(jac,"%s_p_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        	for (i=1;i<=NX;i=i+IDX){
           	for (j=1;j<=NY;j=j+IDY){
                	fwrite(&waveconv[j][i],sizeof(float),1,FP3);
           	}
        	}
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_it%d.old",JACOBIAN,iter);
	if (MYID==0) mergemod(jac,3);
	MPI_Barrier(MPI_COMM_WORLD);
	sprintf(jac,"%s_p_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	remove(jac);
}



/* calculate conjugate gradient direction, if iter > 1 (after Mora 1987) */
/* --------------------------------------------------------------------- */
if(GRAD_METHOD!=3){

if(iter>1){
   
   sprintf(jac,"%s_p.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP6=fopen(jac,"rb");

   if(iter>2){
      sprintf(jac2,"%s_c.old.%i%i",JACOBIAN,POS[1],POS[2]);
      FP5=fopen(jac2,"rb");
   }
   
        /* apply scalar product to obtain the coefficient beta */
     betaz = 0.0;
     betan = 0.0;
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	  
          fread(&gradplastiter,sizeof(float),1,FP6);
	  
	  /*if(gradglastiter==gradg[j][i]) err("TEST1");*/
	  /*if (MYID==10)  printf("TEST beta (MYID=%d) bei (j,i)=(%i,%i): gradg(k-1) = %e, gradg(k) = %e\n",MYID,j,i,gradglastiter,gradg[j][i]);*/
	  
	  /*
	  betaz += (1e5*gradp[j][i]) * ( (1e5*gradg[j][i]) - (1e5*gradglastiter) );
	  betan += (1e5*gradplastiter) * (1e5*gradglastiter);
	  */
	  
	  /* Polak and Ribiere */
	  /*betaz += (gradp[j][i]) * ( (gradg[j][i]) - (gradglastiter) );
	  betan += (gradplastiter) * (gradglastiter);*/
	  
	  /* Polak and Ribiere */
	  betaz += (gradp[j][i]) * ( (gradp[j][i]) - (gradplastiter) );
	  betan += (gradplastiter) * (gradplastiter);
	  
	  /* Fletcher and Reeves */
	  /*betaz += (gradp[j][i]) * (gradg[j][i]);
	  betan += (gradplastiter) * (gradglastiter);*/
	  
	  
       }
     }
     
     /*printf("TEST: vor exchange (MYID=%d): beta = betaz/betan = %e/%e = %e\n",MYID,betaz,betan,betaz/betan);*/

     /*betaz = exchange_L2(betaz,1,1);
     betan = exchange_L2(betan,1,1);*/
     
     betar = 0.0;
     MPI_Allreduce(&betaz,&betar,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
     betaz = betar;
     
     betar = 0.0;
     MPI_Allreduce(&betan,&betar,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
     betan = betar;
     
     beta = 0.0f;
     if(betan !=0.0f) beta = betaz/betan;
     
     /* direction reset */
     if(beta<0.0){beta = 0.0;}

     /*betaVp = beta;*/
     
     printf("\n\nTEST: nach exchange (MYID=%d): beta = %e / %e = %e\n",MYID,betaz,betan,beta);
     
     fseek(FP6,0,SEEK_SET);
     
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	
	  if(iter==2){
             fread(&gradplastiter,sizeof(float),1,FP6);
             waveconv[j][i] = gradp[j][i] + gradplastiter * beta;
          }
   
          if(iter>2){
	     fread(&gradclastiter,sizeof(float),1,FP5);
             waveconv[j][i] = gradp[j][i] + gradclastiter * beta;
          }
	  
       }
     }
     
   fclose(FP6);
   
   if(iter>2){fclose(FP5);}

}

/* output of the conjugate gradient */
if(iter>1){
  sprintf(jac2,"%s_c.old.%i%i",JACOBIAN,POS[1],POS[2]);
  FP5=fopen(jac2,"wb");


  for (i=1;i<=NX;i=i+IDX){
     for (j=1;j<=NY;j=j+IDY){
         fwrite(&waveconv[j][i],sizeof(float),1,FP5);
     }
  }

  fclose(FP5);
  
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */ 
sprintf(jac2,"%s_c.old",JACOBIAN);
if (MYID==0) mergemod(jac2,3);  

}

} /* end of if GRAD_METHOD!=3*/

/* output of preconditioned gradient */
sprintf(jac,"%s_p.old.%i%i",JACOBIAN,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the preconditioned gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
        /*fwrite(&waveconv[j][i],sizeof(float),1,FP4);*/
	fwrite(&gradp[j][i],sizeof(float),1,FP4);
   }
}

fclose(FP4);

MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */ 
sprintf(jac,"%s_p.old",JACOBIAN);
if (MYID==0) mergemod(jac,3);


/* =================================================================================================================================================== */
/* ===================================================================================================================================================== */
/* ===================================================== GRADIENT Zs ================================================================================== */
/* ===================================================================================================================================================== */
	
/* Preconditioning of the gradient */
/* ------------------------------- */

/* apply taper on the gradient */
/* --------------------------- */
if (SWS_TAPER_GRAD_VERT){   /*vertical gradient taper is applied*/
   taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,1);}

if (SWS_TAPER_GRAD_HOR){   /*horizontal gradient taper is applied*/
   taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,2);}

if (SWS_TAPER_GRAD_SOURCES){   /*cylindrical taper around sources is applied*/
   taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,3);}

if (SWS_TAPER_FILE){   /* read taper from BIN-File*/                          
   taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,5);}

/* apply median filter at source positions */
/*median_src(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,iter,0);*/

/* apply wavenumber damping */
if(SPATFILTER==1){
  wavenumber(waveconv_u);
}

if(SPATFILTER==2){
  smooth2(waveconv_u);
}
  
/* save gradient */
/*sprintf(jac,"%s_g_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
           for (j=1;j<=NY;j=j+IDY){
                 fwrite(&waveconv_u[j][i],sizeof(float),1,FP3);
           }
        }
	
fclose(FP3);

MPI_Barrier(MPI_COMM_WORLD);*/
          
/* merge gradient file */ 
/*sprintf(jac,"%s_g_u.old",JACOBIAN);
if (MYID==0) mergemod(jac,3);*/
 

/* Normalize gradient to maximum value */
/*norm(waveconv_u,iter,2);*/

/* apply spatial wavelength filter */
/*if(SPATFILTER==1){
	if (MYID==0){
   	fprintf(FP,"\n Spatial filter is applied to gradient (written by PE %d)\n",MYID);}
spat_filt(waveconv_u,iter,2);}*/

/* apply 2D-Gaussian filter*/
if(GRAD_FILTER==1){smooth_grad(waveconv_u,2);}

/* output of the preconditioned gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
      waveconv_u[j][i] = C_vs * waveconv_u[j][i];
      gradp_u[j][i]=waveconv_u[j][i];
   }
}


/* save gradient for output as inversion result */
if(iter==nfstart_jac){
	sprintf(jac,"%s_p_u_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        	for (i=1;i<=NX;i=i+IDX){
           	for (j=1;j<=NY;j=j+IDY){
                	fwrite(&waveconv_u[j][i],sizeof(float),1,FP3);
           	}
        	}
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_u_it%d.old",JACOBIAN,iter);
	if (MYID==0) mergemod(jac,3);
	MPI_Barrier(MPI_COMM_WORLD);
	sprintf(jac,"%s_p_u_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	remove(jac);
}


/* calculate conjugate gradient direction, if iter > 1 (after Mora 1987) */
/* --------------------------------------------------------------------- */
if(GRAD_METHOD!=3){

if(iter>1){

   
   sprintf(jac,"%s_p_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP6=fopen(jac,"rb");

   if(iter>2){
      sprintf(jac2,"%s_c_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
      FP5=fopen(jac2,"rb");
   }
   
        /* apply scalar product to obtain the coefficient beta */
     betaz = 0.0;
     betan = 0.0;
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	  
          fread(&gradplastiter,sizeof(float),1,FP6);
	  
	  /*if(gradglastiter==gradg[j][i]) err("TEST1");*/
	  /*if (MYID==10)  printf("TEST beta (MYID=%d) bei (j,i)=(%i,%i): gradg(k-1) = %e, gradg(k) = %e\n",MYID,j,i,gradglastiter,gradg[j][i]);*/
	  
	  /*
	  betaz += (1e5*gradp[j][i]) * ( (1e5*gradg[j][i]) - (1e5*gradglastiter) );
	  betan += (1e5*gradplastiter) * (1e5*gradglastiter);
	  */
	  
	  /* Polak and Ribiere */
	  /*betaz += (gradp_u[j][i]) * ( (gradg_u[j][i]) - (gradglastiter) );
	  betan += (gradplastiter) * (gradglastiter);*/
	  
	  /* Polak and Ribiere */
	  betaz += (gradp_u[j][i]) * ( (gradp_u[j][i]) - (gradplastiter) );
	  betan += (gradplastiter) * (gradplastiter);
	  
	  /* Fletcher and Reeves */
	  /*betaz += (gradp[j][i]) * (gradg[j][i]);
	  betan += (gradplastiter) * (gradglastiter);*/
	  
	  
       }
     }
     
     /*printf("TEST: vor exchange (MYID=%d): beta = betaz/betan = %e/%e = %e\n",MYID,betaz,betan,betaz/betan);*/

     /*betaz = exchange_L2(betaz,1,1);
     betan = exchange_L2(betan,1,1);*/
     
     betar = 0.0;
     MPI_Allreduce(&betaz,&betar,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
     betaz = betar;
     
     betar = 0.0;
     MPI_Allreduce(&betan,&betar,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
     betan = betar;
     
     beta = 0.0f;
     if(betan !=0.0f) beta = betaz/betan;
     
     /* direction reset */
     if(beta<0.0){beta = 0.0;}

     /*betaVs = beta;*/
     printf("\n\nTEST: nach exchange (MYID=%d): beta = %e / %e = %e\n",MYID,betaz,betan,beta);
     
     fseek(FP6,0,SEEK_SET);
     
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	
	  if(iter==2){
             fread(&gradplastiter,sizeof(float),1,FP6);
             waveconv_u[j][i] = gradp_u[j][i] + gradplastiter * beta;
          }
   
          if(iter>2){
	     fread(&gradclastiter,sizeof(float),1,FP5);
             waveconv_u[j][i] = gradp_u[j][i] + gradclastiter * beta;
          }

       }
     }
     
   fclose(FP6);
   
   if(iter>2){fclose(FP5);}

}

/* output of the conjugate gradient */
if(iter>1){
  sprintf(jac2,"%s_c_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
  FP5=fopen(jac2,"wb");


  for (i=1;i<=NX;i=i+IDX){
     for (j=1;j<=NY;j=j+IDY){
         fwrite(&waveconv_u[j][i],sizeof(float),1,FP5);
     }
  }

  fclose(FP5);
  
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */ 
sprintf(jac2,"%s_c_u.old",JACOBIAN);
if (MYID==0) mergemod(jac2,3);  

}

} /* end of GRAD_METHOD!=3*/

sprintf(jac,"%s_p_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the preconditioned gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
        /*fwrite(&waveconv_u[j][i],sizeof(float),1,FP4);*/
	fwrite(&gradp_u[j][i],sizeof(float),1,FP4);
   }
}

fclose(FP4);

MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */ 
sprintf(jac,"%s_p_u.old",JACOBIAN);
if (MYID==0) mergemod(jac,3);

/* =================================================================================================================================================== */

/* ===================================================================================================================================================== */
/* ===================================================== GRADIENT rho ================================================================================== */
/* ===================================================================================================================================================== */
	
/* Preconditioning of the gradient */
/* ------------------------------- */
if (SWS_TAPER_GRAD_VERT){   /*vertical gradient taper is applied*/
   taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,1);}

if (SWS_TAPER_GRAD_HOR){   /*horizontal gradient taper is applied*/
   taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,2);}

if (SWS_TAPER_GRAD_SOURCES){   /*cylindrical taper around sources is applied*/
   taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,3);}

if (SWS_TAPER_FILE){   /* read taper from BIN-File*/                          
   taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,6);}

/* apply median filter at source positions */
/*median_src(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,iter,0);*/

/* apply wavenumber damping */
if(SPATFILTER==1){
  wavenumber(waveconv_rho);
}

if(SPATFILTER==2){
  smooth2(waveconv_rho);
} 

/* save gradient */
/*sprintf(jac,"%s_g_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
           for (j=1;j<=NY;j=j+IDY){
                 fwrite(&waveconv_rho[j][i],sizeof(float),1,FP3);
           }
        }
	
fclose(FP3);

MPI_Barrier(MPI_COMM_WORLD);*/
          
/* merge gradient file */ 
/*sprintf(jac,"%s_g_rho.old",JACOBIAN);
if (MYID==0) mergemod(jac,3);*/
 

/* Normalize gradient to maximum value */
/*norm(waveconv_rho,iter,3);*/


/* apply spatial wavelength filter */
/*if(SPATFILTER==1){
	if (MYID==0){
   	fprintf(FP,"\n Spatial filter is applied to gradient (written by PE %d)\n",MYID);}
spat_filt(waveconv_rho,iter,3);}*/

/* apply 2D-Gaussian filter*/
if(GRAD_FILTER==1){smooth_grad(waveconv_rho,3);}

/* output of the preconditioned gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
      waveconv_rho[j][i] = C_rho * waveconv_rho[j][i];
	gradp_rho[j][i]=waveconv_rho[j][i];
   }
}



/* save gradient for output as inversion result */
if(iter==nfstart_jac){
	sprintf(jac,"%s_p_rho_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        	for (i=1;i<=NX;i=i+IDX){
           	for (j=1;j<=NY;j=j+IDY){
                	fwrite(&waveconv_rho[j][i],sizeof(float),1,FP3);
           	}
        	}
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_rho_it%d.old",JACOBIAN,iter);
	if (MYID==0) mergemod(jac,3);
	MPI_Barrier(MPI_COMM_WORLD);
	sprintf(jac,"%s_p_rho_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	remove(jac);
}



/* calculate conjugate gradient direction, if iter > 1 (after Mora 1987) */
/* --------------------------------------------------------------------- */

if(GRAD_METHOD!=3){

if(iter>1){

   
   sprintf(jac,"%s_p_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP6=fopen(jac,"rb");

   if(iter>2){
      sprintf(jac2,"%s_c_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
      FP5=fopen(jac2,"rb");
   }
   
        /* apply scalar product to obtain the coefficient beta */
     betaz = 0.0;
     betan = 0.0;
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	  
          fread(&gradplastiter,sizeof(float),1,FP6);
	  
	  /*if(gradglastiter==gradg[j][i]) err("TEST1");*/
	  /*if (MYID==10)  printf("TEST beta (MYID=%d) bei (j,i)=(%i,%i): gradg(k-1) = %e, gradg(k) = %e\n",MYID,j,i,gradglastiter,gradg[j][i]);*/
	  
	  /*
	  betaz += (1e5*gradp[j][i]) * ( (1e5*gradg[j][i]) - (1e5*gradglastiter) );
	  betan += (1e5*gradplastiter) * (1e5*gradglastiter);
	  */
	  
	  /* Polak and Ribiere */
	  /*betaz += (gradp_rho[j][i]) * ( (gradg_rho[j][i]) - (gradglastiter) );
	  betan += (gradplastiter) * (gradglastiter);*/
	  
	  /* Polak and Ribiere */
	  betaz += (gradp_rho[j][i]) * ( (gradp_rho[j][i]) - (gradplastiter) );
	  betan += (gradplastiter) * (gradplastiter);
	  
	  /* Fletcher and Reeves */
	  /*betaz += (gradp[j][i]) * (gradg[j][i]);
	  betan += (gradplastiter) * (gradglastiter);*/
	  
	  
       }
     }
     
     /*printf("TEST: vor exchange (MYID=%d): beta = betaz/betan = %e/%e = %e\n",MYID,betaz,betan,betaz/betan);*/

     /*betaz = exchange_L2(betaz,1,1);
     betan = exchange_L2(betan,1,1);*/
     
     betar = 0.0;
     MPI_Allreduce(&betaz,&betar,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
     betaz = betar;
     
     betar = 0.0;
     MPI_Allreduce(&betan,&betar,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD);
     betan = betar;
     
     beta = 0.0f;
     if(betan !=0.0f) beta = betaz/betan;
     
     /* direction reset */
     if(beta<0.0){beta = 0.0;}

     /*betarho = beta;*/
     printf("\n\nTEST: nach exchange (MYID=%d): beta = %e / %e = %e\n",MYID,betaz,betan,beta);
     
     fseek(FP6,0,SEEK_SET);
     
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	
	  if(iter==2){
             fread(&gradplastiter,sizeof(float),1,FP6);
             waveconv_rho[j][i] = gradp_rho[j][i] + gradplastiter * beta;
          }
   
          if(iter>2){
	     fread(&gradclastiter,sizeof(float),1,FP5);
             waveconv_rho[j][i] = gradp_rho[j][i] + gradclastiter * beta;
          }
	  
	  
	  /*if (iter >= 2)
	  {
	     if (isnan(waveconv_u[j][i]) || isinf(waveconv_u[j][i]))
	     {
		     sum = 0.0;
		     h = 0;
		     for (ii=-1;ii<=1;ii++){
	       		for (jj=-1;jj<=1;jj++){
				if (isnan(waveconv_rho[j+jj][i+ii]) || isinf(waveconv_rho[j+jj][i+ii])) continue;
				sum += waveconv_rho[j+jj][i+ii];
				h++;
			}
		     }
		     if (h>0) waveconv_rho[j][i] = sum / h;
		     else waveconv_rho[j][i] = 0.0;
	     }
	     
	  }*/

       }
     }
     
   fclose(FP6);
   
   if(iter>2){fclose(FP5);}

}

/* output of the conjugate gradient */
if(iter>1){
  sprintf(jac2,"%s_c_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
  FP5=fopen(jac2,"wb");


  for (i=1;i<=NX;i=i+IDX){
     for (j=1;j<=NY;j=j+IDY){
         fwrite(&waveconv_rho[j][i],sizeof(float),1,FP5);
     }
  }

  fclose(FP5);
  
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */ 
sprintf(jac2,"%s_c_rho.old",JACOBIAN);
if (MYID==0) mergemod(jac2,3);  

}

} /* end of GRAD_METHOD!=3 */

sprintf(jac,"%s_p_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the preconditioned gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
        /*fwrite(&waveconv_rho[j][i],sizeof(float),1,FP4);*/
	fwrite(&gradp_rho[j][i],sizeof(float),1,FP4);
   }
}

fclose(FP4);

MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */ 
sprintf(jac,"%s_p_rho.old",JACOBIAN);
if (MYID==0) mergemod(jac,3);


}
void model(float  **  rho, float **  pi, float **  u, float **  taus, float **  taup, float *  eta){

	/*--------------------------------------------------------------------------*/
	/* extern variables */
	extern int NX, NY, NXG, NYG,  POS[3], L, MYID;
	extern char  MFILE[STRING_SIZE];	
	extern char INV_MODELFILE[STRING_SIZE];
	extern float DH, *FL, TAU, DT;
	
        /* local variables */
	float vp, vs, rhov, grad1, grad2, grad3, x, ts, tp, muv, piv, *pts, lkappa, lmu;
	float Qp, Qs, Qpinv, llambda;
	int i, j, ii, jj, l;
	char modfile[STRING_SIZE]; 
	
	/* parameters for homogenous half-space */
	/* perfect model parameters */
	float vp1=2700.0, vs1=1776.0, rho1=2120.0, Qmu=20.0, Qkappa=10000.0;
	/*float vs2=1551.0;*/
	float vs2=1400;
	
	/* calculate lateral linear gradient */
	float x1 = 0.208;
	float b = vs1;
	float a = (vs2-vs1)/(x1-DH);
	
	/*-----------------------------------------------------------------------*/
	pts=vector(1,L);
	for (l=1;l<=L;l++) {
		pts[l]=1.0/(2.0*PI*FL[l]);
	        eta[l]=DT/pts[l];
	}	
	
	
	/* loop over global grid */
		for (i=1;i<=NXG;i++){
			for (j=1;j<=NYG;j++){
						
				vp=vp1;
				rhov=rho1;
				
				/* x-coordinate on FD-grid */
				x = i*DH;
				
				/* calculate Vs */
				vs = a*x + b;
				
				if(x>=x1){vs = vs2;}
				if(x<x1){vs = vs1;}
				
				/* calculate kappa and mu*/
				/*lmu=vs*vs*rhov;
				llambda = rhov*(vp*vp*rhov - 2.0*lmu); 
				lkappa = llambda + ((2.0/3.0)*lmu);
			        Qpinv = (1.0/Qmu) + (lkappa/(lkappa+(4.0*lmu/3.0)))*((1.0/Qkappa)-(1.0/Qmu));
				Qp = 1.0/Qpinv;*/
				
				Qp = Qkappa;
				Qs = Qmu;
								
				ts=2.0/Qs;
				tp=2.0/Qp;
				
				/* only the PE which belongs to the current global gridpoint 
				  is saving model parameters in his local arrays */
				if ((POS[1]==((i-1)/NX)) && 
				    (POS[2]==((j-1)/NY))){
					ii=i-POS[1]*NX;
					jj=j-POS[2]*NY;

					u[jj][ii]=vs;
					rho[jj][ii]=rhov;
					pi[jj][ii]=vp;
					taus[jj][ii]=ts;
					taup[jj][ii]=tp;
				}
			}
		}	

		
sprintf(modfile,"%s_rho_it_0.bin",INV_MODELFILE);
writemod(modfile,rho,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vs_it_0.bin",INV_MODELFILE);
writemod(modfile,u,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vp_it_0.bin",INV_MODELFILE);
writemod(modfile,pi,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

free_vector(pts,1,L);
}
Example #10
0
void model_elastic(float  **  rho, float **  pi, float **  u){

	/*--------------------------------------------------------------------------*/
	/* extern variables */

	extern float DT, DH;
	extern int   NX, NY, NXG, NYG,  POS[3], MYID;
	extern char  MFILE[STRING_SIZE];	

	/* local variables */
	float rhov, muv, piv, vp, vs, y, t, de, zplat1, zplat2, rplat;
	float *pts, ts, tp, sumu, sumpi, ws, *ri, *d, *ti, *dl, *vsl, z, r;
	float **checkp, **checks, **checkrho; 
	int   i, j, l, ii, jj, nk, k, nl;
	char filename_mu[STRING_SIZE];
	char filename_rho[STRING_SIZE]; 
	char filename_pi[STRING_SIZE];
				
	sprintf(filename_mu,"%s.mu",MFILE);
	sprintf(filename_rho,"%s.rho",MFILE);
	sprintf(filename_pi,"%s.pi",MFILE);
	
	
	/*-----------------------------------------------------------------------*/

	/* loop over global grid */
	for (i=1;i<=NXG;i++){
            for (j=1;j<=NYG;j++){
	                
	                  y = j*DH;
	                
			  vs = 1150.0;
			  vp = 2000.0;
			  rhov = 1800.0;
			  
			  if(y<0.01){
			   
			    vs = 2310.0;  
			    vp = 4000.0;  
			  rhov = 1800.0;
			   
			  }
	    
	                   
	    
			/* only the PE which belongs to the current global gridpoint 
			is saving model parameters in his local arrays */
			if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
				ii = i-POS[1]*NX;
				jj = j-POS[2]*NY;
				
				u[jj][ii]    = vs;
				rho[jj][ii]  = rhov;
				pi[jj][ii]   = vp;
			}
			

		}
	}	

	/* each PE writes his model to disk */
	writemod(filename_rho,rho,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(filename_rho,3);
	
	/* each PE writes his model to disk */
	writemod(filename_pi,pi,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(filename_pi,3);
	                        
	/* each PE writes his model to disk */
	writemod(filename_mu,u,3);
	MPI_Barrier(MPI_COMM_WORLD);
	if (MYID==0) mergemod(filename_mu,3);
	                        
}
Example #11
0
void hessian(int nshots, int SHOTINC, float *** green_vx, float *** greeni_vx, float *** green_vy, float *** greeni_vy, float *** green_sxx, float *** greeni_sxx, float *** green_syy, float *** greeni_syy,
             float *** green_sxy, float *** greeni_sxy, float ** prho, float ** pu, float ** ppi){
  
extern float DT,TIME;
extern float FC_HESSIAN;        	
extern int NX, NY, IDX, IDY, DTINV, INVMAT1, MYID, POS[4], FDORDER;
extern char JACOBIAN[STRING_SIZE];

/* local variables */
int i, j, k, l, ns_hess, ishot, irec, nd, NSRC_HESSIAN, RECINC;
double trig1,trig2;
double t=0.0;
const double pi=4.0*atan(1.0);
char jac[STRING_SIZE];

float complex green_x, green_y, tmp_mu1_shot, tmp_mu2_shot, tmp_mu3_shot, tmp_mu5_shot, tmp_mu6_shot;
float tmp_mu1, tmp_mu2, tmp_mu3;
float complex tmp_jac_lam, tmp_jac_mu, tmp_jac_rho, tmp_jac_vp, tmp_jac_vs, tmp_fft_fsignal;

float ** abs_green, omega, mulamratio, lamss, muss, HESS_SCALE;
float ** hessian, ** hessian_u, ** hessian_rho, ** hessian_lam, ** hessian_mu;

float ** hvxx_shot, ** hvxxi_shot, ** hvyy_shot, ** hvyyi_shot, ** hvxy_shot, ** hvxyi_shot,  ** hvyx_shot, ** hvyxi_shot;
float *psource_hess=NULL, *Hess_for_real=NULL, *Hess_for_complex=NULL;

FILE *FP4;

HESS_SCALE = 1e5;
RECINC = 1;
NSRC_HESSIAN=nshots;

nd = FDORDER/2 + 1;
abs_green = matrix(-nd+1,NY+nd,-nd+1,NX+nd);

/* Diagonal elements of the Hessian*/
hessian = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hessian_u = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hessian_lam = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hessian_mu = matrix(-nd+1,NY+nd,-nd+1,NX+nd); 
hessian_rho = matrix(-nd+1,NY+nd,-nd+1,NX+nd);

hvxx_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hvxxi_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
        
hvyy_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hvyyi_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
        
hvyx_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hvyxi_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
        
hvxy_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hvxyi_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);

Hess_for_real = vector(1,1);
Hess_for_complex = vector(1,1);
        
for (i=1;i<=NX;i=i+IDX){
    for (j=1;j<=NY;j=j+IDY){
           hessian[j][i]=0.0;
           hessian_lam[j][i]=0.0;
           hessian_u[j][i]=0.0;  
           hessian_mu[j][i]=0.0; 
           hessian_rho[j][i]=0.0;
    }
}

/* assemble Hessian */
/* ----------------------------------------------------------------- */
/* calculate absolute values of impulse responses */
for (ishot=1;ishot<=nshots;ishot=ishot+SHOTINC){
    for (i=1;i<=NX;i=i+IDX){
        for (j=1;j<=NY;j=j+IDY){
        
           green_x = green_vx[j][i][ishot] + greeni_vx[j][i][ishot] * I;
           green_y = green_vy[j][i][ishot] + greeni_vy[j][i][ishot] * I;
                                                                        
           /*abs_green[j][i] += creal((green_x*conj(green_x))+(green_y*conj(green_y)));*/
           abs_green[j][i] = 1.0;
        
           /*printf("green_x = %e \n",green_sxx[j][i][ishot]);*/
           
        }
    }
}    
     
omega = 2.0*M_PI*FC_HESSIAN;

/*printf("omega = %e \n",omega);
printf("NSRC = %d \n",NSRC_HESSIAN);*/

/*psource_hess=rd_sour(&ns_hess,fopen(SIGNAL_FILE,"r"));
FFT_data(psource_hess,Hess_for_real,Hess_for_complex,NT);
                                                         
MPI_Barrier(MPI_COMM_WORLD);                             

tmp_fft_fsignal = Hess_for_real[1] + Hess_for_complex[1] * I;*/

tmp_fft_fsignal = 1.0;

for (ishot=1;ishot<=nshots;ishot=ishot+SHOTINC){
        
        /*for (i=1;i<=NX;i=i+IDX){
            for (j=1;j<=NY;j=j+IDY){*/
            
                /* calculate spatial derivatives of the forward wavefields */
                 /*hvxx_shot[j][i] = (green_vx[j][i][ishot]-green_vx[j][i-1][ishot])/DH;
                hvxxi_shot[j][i] = (greeni_vx[j][i][ishot]-greeni_vx[j][i-1][ishot])/DH;
                           
                 hvyy_shot[j][i] = (green_vy[j][i][ishot]-green_vy[j-1][i][ishot])/DH;
                hvyyi_shot[j][i] = (greeni_vy[j][i][ishot]-greeni_vy[j-1][i][ishot])/DH;
                           
                 hvyx_shot[j][i] = (green_vy[j][i+1][ishot]-green_vy[j][i][ishot])/DH; 
                hvyxi_shot[j][i] = (greeni_vy[j][i+1][ishot]-greeni_vy[j][i][ishot])/DH;
                           
                 hvxy_shot[j][i] = (green_vx[j+1][i][ishot]-green_vx[j][i][ishot])/DH;
                hvxyi_shot[j][i] = (greeni_vx[j+1][i][ishot]-greeni_vx[j][i][ishot])/DH;*/

        /*    }
        }*/

 for (irec=nshots;irec<=nshots;irec=irec+RECINC){

        /* construct Hessian for different material parameters */
            for (i=1;i<=NX;i=i+IDX){
                for (j=1;j<=NY;j=j+IDY){
            
                    /* Hessian for Lame parameter lambda, mu and rho */
                    tmp_mu1_shot = (green_sxx[j][i][ishot] + greeni_sxx[j][i][ishot] * I);
                    tmp_mu2_shot = (green_syy[j][i][ishot] + greeni_syy[j][i][ishot] * I);
                    tmp_mu3_shot = (green_sxy[j][i][ishot] + greeni_sxy[j][i][ishot] * I);
                    
                    tmp_mu5_shot = omega*((green_vx[j+1][i][ishot] * I) - greeni_vx[j+1][i][ishot]);
                    tmp_mu6_shot = omega*((green_vy[j+1][i][ishot] * I) - greeni_vy[j+1][i][ishot]);

                    tmp_mu1 = green_sxx[j][i][irec] + greeni_sxx[j][i][irec] * I;
                    tmp_mu2 = green_syy[j][i][irec] + greeni_syy[j][i][irec] * I;
                    tmp_mu3 = green_sxy[j][i][irec] + greeni_sxy[j][i][irec] * I;

                    if(INVMAT1==1){
                       muss = prho[j][i] * pu[j][i] * pu[j][i];
                      lamss = prho[j][i] * ppi[j][i] * ppi[j][i] - 2.0 * muss;}
                    
                    if(INVMAT1=3){
                       muss = pu[j][i];
                      lamss = ppi[j][i];}
                    
                    /*mulamratio = (muss * muss)/((lamss+muss)*(lamss+muss));*/
                                                                    
                    /*tmp_jac_lam = (1.0/(4.0 * (lamss+muss) * (lamss+muss))) * ((tmp_mu1_shot + tmp_mu2_shot) * (tmp_mu1_shot + tmp_mu2_shot));*/
                    
                    tmp_jac_lam =  (tmp_mu1_shot + tmp_mu2_shot) * (tmp_mu1 + tmp_mu2);
                    
                    tmp_jac_mu = ((1.0/(muss*muss))*(tmp_mu3_shot * tmp_mu3_shot)) + ((1.0/4.0) * ((tmp_mu1_shot + tmp_mu2_shot) * (tmp_mu1_shot + tmp_mu2_shot)) / ((lamss+muss)*(lamss+muss)))
                                                                                  + ((1.0/4.0) * ((tmp_mu1_shot - tmp_mu2_shot) * (tmp_mu1_shot - tmp_mu2_shot)) / (muss*muss));
                    
                    /*tmp_jac_mu = (tmp_mu3_shot * tmp_mu3) + (((mulamratio*((tmp_mu1_shot + tmp_mu2_shot) * (tmp_mu1 + tmp_mu2))) + ((tmp_mu1_shot - tmp_mu2_shot) * (tmp_mu1 - tmp_mu2)))/4.0);*/
                   
                    tmp_jac_rho = (tmp_mu5_shot*tmp_mu5_shot) + (tmp_mu6_shot*tmp_mu6_shot);
                    
                    /* Assemble Hessian for lambda, mu and rho */
                    if(INVMAT1==3){
                         hessian[j][i] += HESS_SCALE * creal(tmp_jac_lam*abs_green[j][i]*conj(tmp_jac_lam));
                       hessian_u[j][i] += HESS_SCALE * creal(tmp_jac_mu*abs_green[j][i]*conj(tmp_jac_mu));  
                     hessian_rho[j][i] += HESS_SCALE * creal(tmp_jac_rho*abs_green[j][i]*conj(tmp_jac_rho));
                    }

                    /* Assemble Hessian for Vp, Vs and rho*/
                    if(INVMAT1==1){
                    
                         tmp_jac_vp = 2.0 * ppi[j][i] * prho[j][i] * tmp_jac_lam;          
                         tmp_jac_vs = (- 4.0 * prho[j][i] * pu[j][i] * tmp_jac_lam) + (2.0 * prho[j][i] * pu[j][i] * tmp_jac_mu);                  
                         tmp_jac_rho += (((ppi[j][i] * ppi[j][i])-(2.0 * pu[j][i] * pu[j][i])) * tmp_jac_lam) + (pu[j][i] * pu[j][i] * tmp_jac_mu);
                    
                         hessian[j][i] += HESS_SCALE * creal(tmp_jac_vp*abs_green[j][i]*conj(tmp_jac_vp));  
                       hessian_u[j][i] += HESS_SCALE * creal(tmp_jac_vs*abs_green[j][i]*conj(tmp_jac_vs));  
                     hessian_rho[j][i] += HESS_SCALE * creal(tmp_jac_rho*abs_green[j][i]*conj(tmp_jac_rho));
                     
                    }
                  
                 }
             }
 }
}

/* save Hessian for Vp */
/* ----------------------- */
sprintf(jac,"%s_hessian.%i%i",JACOBIAN,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){ 
        fwrite(&hessian[j][i],sizeof(float),1,FP4);
   }
}

fclose(FP4);
    
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */   
sprintf(jac,"%s_hessian",JACOBIAN);
if (MYID==0) mergemod(jac,3);

/* save HESSIAN for mu */
/* ----------------------- */
sprintf(jac,"%s_hessian_u.%i%i",JACOBIAN,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){ 
        fwrite(&hessian_u[j][i],sizeof(float),1,FP4);
   }
}

fclose(FP4);
    
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */   
sprintf(jac,"%s_hessian_u",JACOBIAN);
if (MYID==0) mergemod(jac,3);

/* save HESSIAN for rho */   
/* ----------------------- */
sprintf(jac,"%s_hessian_rho.%i%i",JACOBIAN,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){ 
       fwrite(&hessian_rho[j][i],sizeof(float),1,FP4);
   }
}
    
fclose(FP4);
    
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */
sprintf(jac,"%s_hessian_rho",JACOBIAN);
if (MYID==0) mergemod(jac,3);

free_matrix(hessian,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(hessian_u,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(hessian_lam,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(hessian_mu,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(hessian_rho,-nd+1,NY+nd,-nd+1,NX+nd);

}
Example #12
0
void hessian(int nshots, int SHOTINC, float *** green_vy, float *** greeni_vy, float *** green_syy, float *** greeni_syy,
             float *** green_sxy, float *** greeni_sxy, float ** prho, float ** pu, int iter){
  
extern float DT,DH,TIME;
extern float FC_HESSIAN;        	
extern int NX, NY, IDX, IDY, DTINV, INVMAT1, MYID, POS[4], FDORDER;
extern char JACOBIAN[STRING_SIZE];

/* local variables */
int i, j, k, l, ns_hess, ishot, irec, nd, NSRC_HESSIAN, NREC_HESSIAN, RECINC;
double trig1,trig2;
double t=0.0;
const double pi=4.0*atan(1.0);
char jac[STRING_SIZE];

float complex uttx, utty, exx, eyy, eyx, Gxx, Gyx, Gxy, Gyy, Gxxx, Gyxx, Gxyy, Gyyy, Gxyx, Gyyx;
float complex tmp_jac_lam, tmp_jac_mu, tmp_jac_rho, tmp_jac_vp, tmp_jac_vs, tmp_fft_fsignal;

float ** abs_green, omega, mulamratio, lamss, muss, HESS_SCALE;
float ** hessian, ** hessian_u, ** hessian_rho, ** hessian_lam, ** hessian_mu;

float hvxx, hvxxi, hvyy, hvyyi, hvxy, hvxyi,  hvyx, hvyxi;
float **exx_shot, **exxi_shot, **eyy_shot, **eyyi_shot, **eyx_shot, **eyxi_shot, **uttx_shot, **uttxi_shot, **utty_shot, **uttyi_shot;
float *psource_hess=NULL, *Hess_for_real=NULL, *Hess_for_complex=NULL;

FILE *FP4;

HESS_SCALE = 1.0;
RECINC = 1;
NSRC_HESSIAN=1;
NREC_HESSIAN=24;

nd = FDORDER/2 + 1;
abs_green = matrix(-nd+1,NY+nd,-nd+1,NX+nd);

/* Diagonal elements of the Hessian*/
hessian_u = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
hessian_mu = matrix(-nd+1,NY+nd,-nd+1,NX+nd); 
hessian_rho = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
        
eyy_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
eyyi_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
        
eyx_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
eyxi_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);

utty_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd); 
uttyi_shot = matrix(-nd+1,NY+nd,-nd+1,NX+nd);


Hess_for_real = vector(1,1);
Hess_for_complex = vector(1,1);
        
for (i=1;i<=NX;i=i+IDX){
    for (j=1;j<=NY;j=j+IDY){
           hessian_u[j][i]=0.0;  
           hessian_mu[j][i]=0.0; 
           hessian_rho[j][i]=0.0;
    }
}


/* assemble Hessian */
/* ----------------------------------------------------------------- */

/* Circular frequency of the Hessian */
omega = 2.0*M_PI*FC_HESSIAN;

/* calculate absolute values of impulse responses */
for (ishot=1;ishot<=nshots;ishot=ishot+SHOTINC){

    for (i=1;i<=NX;i=i+IDX){
        for (j=1;j<=NY;j=j+IDY){
        
           /*green_x = green_vx[j][i][ishot] + greeni_vx[j][i][ishot] * I;
           green_y = green_vy[j][i][ishot] + greeni_vy[j][i][ishot] * I;*/
                                                                        
           abs_green[j][i] = 1.0;
           
        }
    }

}    

/*printf("omega = %e \n",omega);
printf("NSRC = %d \n",NSRC_HESSIAN);*/

/*psource_hess=rd_sour(&ns_hess,fopen(SIGNAL_FILE,"r"));
FFT_data(psource_hess,Hess_for_real,Hess_for_complex,NT);
                                                         
MPI_Barrier(MPI_COMM_WORLD);                             

tmp_fft_fsignal = Hess_for_real[1] + Hess_for_complex[1] * I;*/

tmp_fft_fsignal = 1.0;

for (ishot=1;ishot<=nshots;ishot=ishot+SHOTINC){
       
       /* calculate spatial and temporal derivatives of the forward wavefield */ 
       for (i=1;i<=NX;i=i+IDX){
          for (j=1;j<=NY;j=j+IDY){
                                       
                 hvyy = (green_vy[j+1][i][ishot]-green_vy[j][i][ishot])/DH;
                hvyyi = (greeni_vy[j+1][i][ishot]-greeni_vy[j][i][ishot])/DH;
                           
                 hvyx = (green_vy[j][i+1][ishot]-green_vy[j][i][ishot])/DH; 
                hvyxi = (greeni_vy[j][i+1][ishot]-greeni_vy[j][i][ishot])/DH;
                               
                /* calculate strain tensors and integrate FD-wavefield */
       
               eyy_shot[j][i] = hvyy;
               eyyi_shot[j][i] = hvyyi;
               
               eyxi_shot[j][i] = hvyxi;
               eyx_shot[j][i] =  hvyx;
                              
               utty_shot[j][i] = -hvyyi*omega;             
               uttyi_shot[j][i] = hvyy*omega;
               
          }
       }

 for (irec=1;irec<=1;irec=irec+RECINC){

        /* construct Hessian for different material parameters */
            for (i=1;i<=NX;i=i+IDX){
                for (j=1;j<=NY;j=j+IDY){
            
                    /* assemble complex wavefields */
                    utty = (utty_shot[j][i] + uttyi_shot[j][i] * I);
                    
                    eyy = (eyy_shot[j][i] + eyyi_shot[j][i] * I);
                    eyx = (eyx_shot[j][i] + eyxi_shot[j][i] * I);
                    
                    
                    if(INVMAT1==1){
                       muss = prho[j][i] * pu[j][i] * pu[j][i];
                    }
                    
                    if(INVMAT1=3){
                       muss = pu[j][i];
                    }
                      
                    /* Hessian */  
                    
                    tmp_jac_rho = (conj(utty)*utty);                   
                    tmp_jac_mu = (conj(eyx)*abs_green[j][i]*eyx) + (conj(eyy)*abs_green[j][i]*eyy);
                    
                    /* calculate Hessian for lambda, mu and rho by autocorrelation of Frechet derivatives */
                    /*if(INVMAT1==3){*/
                       hessian_u[j][i] += HESS_SCALE * creal(tmp_jac_mu);  
                     hessian_rho[j][i] += HESS_SCALE * creal(tmp_jac_rho);
                    /*}*/

                    /* Assemble Hessian for Vp, Vs and rho by autocorrelation of Frechet derivatives*/
                    /*if(INVMAT1==1){
                    
                         tmp_jac_vp = 2.0 * ppi[j][i] * prho[j][i] * tmp_jac_lam;          
                         tmp_jac_vs = (- 4.0 * prho[j][i] * pu[j][i] * tmp_jac_lam) + (2.0 * prho[j][i] * pu[j][i] * tmp_jac_mu);                  
                         tmp_jac_rho += (((ppi[j][i] * ppi[j][i])-(2.0 * pu[j][i] * pu[j][i])) * tmp_jac_lam) + (pu[j][i] * pu[j][i] * tmp_jac_mu);
                    
                         hessian[j][i] += HESS_SCALE * creal(tmp_jac_vp*conj(tmp_jac_vp));  
                       hessian_u[j][i] += HESS_SCALE * creal(tmp_jac_vs*conj(tmp_jac_vs));  
                     hessian_rho[j][i] += HESS_SCALE * creal(tmp_jac_rho*conj(tmp_jac_rho));
                     
                    }*/
                  
                 }
             }
 }
}


/* apply wavenumber damping for Vp-, Vs- and density Hessian */
/*if(SPATFILTER==1){
    wavenumber(hessian_u);
    wavenumber(hessian_rho);
  }*/

/* save HESSIAN for mu */
/* ----------------------- */
sprintf(jac,"%s_hessian_u_%d.%i%i",JACOBIAN,iter,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){ 
        fwrite(&hessian_u[j][i],sizeof(float),1,FP4);
   }
}

fclose(FP4);
    
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */   
sprintf(jac,"%s_hessian_u_%d",JACOBIAN,iter);
if (MYID==0) mergemod(jac,3);

/* save HESSIAN for rho */   
/* ----------------------- */
sprintf(jac,"%s_hessian_rho_%d.%i%i",JACOBIAN,iter,POS[1],POS[2]);
FP4=fopen(jac,"wb");

/* output of the gradient */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){ 
       fwrite(&hessian_rho[j][i],sizeof(float),1,FP4);
   }
}
    
fclose(FP4);
    
MPI_Barrier(MPI_COMM_WORLD);

/* merge gradient file */
sprintf(jac,"%s_hessian_rho_%d",JACOBIAN,iter);
if (MYID==0) mergemod(jac,3);

free_matrix(hessian_u,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(hessian_mu,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(hessian_rho,-nd+1,NY+nd,-nd+1,NX+nd);

free_matrix(eyy_shot,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(eyx_shot,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(utty_shot,-nd+1,NY+nd,-nd+1,NX+nd);

free_matrix(eyyi_shot,-nd+1,NY+nd,-nd+1,NX+nd);
free_matrix(eyxi_shot,-nd+1,NY+nd,-nd+1,NX+nd);  
free_matrix(uttyi_shot,-nd+1,NY+nd,-nd+1,NX+nd);                

}
Example #13
0
void gauss_filt(float ** waveconv)
{

	/* extern variables */

        extern float DH, WD_DAMP, FC_END, C_vs;
	extern int FREE_SURF, NX, NY, NXG, NYG, IDX, IDY;
	extern int NPROCX, NPROCY, MYID, POS[3];
	extern char JACOBIAN[STRING_SIZE];
	extern FILE *FP;
	extern int FILT_SIZE_GRAD;
	
	/* local variables */
	int i, j, ii, jj;
	int i1, j1, filtsize, hfs;

	float **model_tmp, **kernel, ** model_gauss, grad, normgauss, smooth_meter;
	float lam, sigma, s, sum, conv;
	
	char jac_tmp[STRING_SIZE];
	
	FILE *model, *FP1;
	
	char modfile[STRING_SIZE];

	/* temporarily save gradient for Gaussian filtering */
        sprintf(jac_tmp,"%s_gauss.old.%i%i",JACOBIAN,POS[1],POS[2]);
        FP1=fopen(jac_tmp,"wb");
                        
        for (i=1;i<=NX;i=i+IDX){
            for (j=1;j<=NY;j=j+IDY){
                fwrite(&waveconv[j][i],sizeof(float),1,FP1);
            }                       
        }                           
                                    
        fclose(FP1);                
                                    
        MPI_Barrier(MPI_COMM_WORLD);
                                  
        /* merge gradient file */ 
        sprintf(jac_tmp,"%s_gauss.old",JACOBIAN);
        if (MYID==0) mergemod(jac_tmp,3); 	

	if(MYID==0){
	
			lam = C_vs / FC_END;
			
			/* define filter size as fraction of reference velocity wavelength */
			FILT_SIZE_GRAD = round((WD_DAMP * lam)/DH);
			
		      	if (FILT_SIZE_GRAD==0)	return;
		      	if (!(FILT_SIZE_GRAD % 2)) {
		      	if (FILT_SIZE_GRAD > 0)	FILT_SIZE_GRAD += 1;
		      	else			FILT_SIZE_GRAD -= 1;
		      	}
	  
		      	hfs = abs(FILT_SIZE_GRAD)/2;
			sigma = hfs/2;
			s = 2.0 * sigma * sigma;
		      	printf("\n hfs: %d \n",hfs);
					      	
		      	model_tmp = matrix(-hfs+1,NYG+hfs,-hfs+1,NXG+hfs);
			model_gauss = matrix(-hfs+1,NYG+hfs,-hfs+1,NXG+hfs);
			kernel = matrix(1,abs(FILT_SIZE_GRAD),1,abs(FILT_SIZE_GRAD));
		      		      
			sprintf(jac_tmp,"%s_gauss.old",JACOBIAN);    
	
		      	model=fopen(jac_tmp,"rb");
		      	if (model==NULL) err(" Could not open gradient file !");
		
		      	/* load merged model */
		      	for (i=1;i<=NXG;i++){
				for (j=1;j<=NYG;j++){
					      fread(&grad, sizeof(float), 1, model);
				      	model_tmp[j][i]=grad;
			      	}	
		      	}
		
		        fclose(model);
		      
		      
		      
		        /* apply 2D-Gaussian filter on vp and vs model */
		        /* extrapolate array */
		      
		        /* left/right boundary */
		        for (j=1;j<=NYG;j++){
		      
		            for (i=-hfs+1;i<=0;i++){
			        model_tmp[j][i] = model_tmp[j][1];
			    }
			      
		            for (i=NXG+1;i<=NXG+hfs;i++){
			        model_tmp[j][i] = model_tmp[j][NXG];
			    }
			    
		        }
			      
		        /* top/bottom boundary incl. corners */
		        for (j=-hfs+1;j<=0;j++){
			
		             for (i=-hfs+1;i<=NXG+hfs;i++){
			         model_tmp[j][i] = model_tmp[1][i];
			     }
			     
		        }
		      
		        for (j=NYG+1;j<=NYG+hfs;j++){
			
		            for (i=-hfs+1;i<=NXG+hfs;i++){
			        model_tmp[j][i] = model_tmp[NYG][i];
			    }
			    
		        }
					
			/* create filter kernel */
			for (ii=-hfs;ii<=hfs;ii++){
			    for (jj=-hfs;jj<=hfs;jj++){
						      
			        kernel[jj+hfs+1][ii+hfs+1] = exp(-((ii*ii)/s) - ((jj*jj)/s));
				sum += kernel[jj+hfs+1][ii+hfs+1];
							      
			    }
			}
			
			/* normalize kernel */
			for (i=1;i<=FILT_SIZE_GRAD;i++){
     			    for (j=1;j<=FILT_SIZE_GRAD;j++){
         
         		        kernel[j][i] /= sum;

     			    }
			}
			
			/* apply Gaussian filter to gradient */
			for (j=1;j<=NYG;j++){
     			    for (i=1;i<=NXG;i++){

          		        conv = 0.0;
          		        /* loop over kernel*/
	  			for (ii=-hfs;ii<=hfs;ii++){
	       			    for (jj=-hfs;jj<=hfs;jj++){

	            		    conv += model_tmp[j+jj][i+ii] * kernel[jj+hfs+1][ii+hfs+1];				

               			    }
          			}

          			/* output of filtered gradient */
          			model_gauss[j][i] = conv;

      			    }
			}
			      
			/* output of smoothed gradients */      
			sprintf(jac_tmp,"%s_gauss.old",JACOBIAN);   
			      
			model=fopen(jac_tmp,"wb");
			for (i=1;i<=NXG;i++){
			  for (j=1;j<=NYG;j++){
			    
			  fwrite(&model_gauss[j][i],sizeof(float),1,model);

			  }
			}
			
			fclose(model);
			
			free_matrix(model_tmp,-hfs+1,NYG+hfs,-hfs+1,NXG+hfs);
			free_matrix(model_gauss,-hfs+1,NYG+hfs,-hfs+1,NXG+hfs);
			free_matrix(kernel,1,abs(FILT_SIZE_GRAD),1,abs(FILT_SIZE_GRAD));
			
		} /* end of if(MYID==0)*/
		
		
	MPI_Barrier(MPI_COMM_WORLD);
	smooth_meter=FILT_SIZE_GRAD*DH;
	
	if(MYID==0){printf("\n \t ---- Gradient is smoothed with Gaussian (filter length of %d gridpoints which is equivalent to %4.2f meter) \n",FILT_SIZE_GRAD,smooth_meter);}
	
	/* distribute smoothed jacobian on computational nodes */
	sprintf(jac_tmp,"%s_gauss.old",JACOBIAN);
		
	model=fopen(jac_tmp,"rb");
	if (model==NULL) err(" Could not open gradient file ! (distribute smoothed gradient)");
	for (i=1;i<=NXG;i++){
	   for (j=1;j<=NYG;j++){
	   
                        fread(&grad, sizeof(float), 1, model);
			   			
			if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
				ii=i-POS[1]*NX;
				jj=j-POS[2]*NY;

				waveconv[jj][ii]=grad;

			}
		}
	}
		
	fclose(model);
	
	if(MYID==0){printf("\n \t ---- Smoothed gradient is distributed on computational nodes ... ---- \n");}

        /* clean up temporary files*/
        MPI_Barrier(MPI_COMM_WORLD);
        sprintf(jac_tmp,"%s_gauss.old.%i%i",JACOBIAN,POS[1],POS[2]);
        remove(jac_tmp);

}
Example #14
0
void model_elastic(float  **  rho, float **  pi, float **  u){

	/*--------------------------------------------------------------------------*/
	/* extern variables */

	extern float DH;
	extern int NX, NY, NXG, NYG,  POS[3], L, MYID;
	extern char  MFILE[STRING_SIZE];	
	extern char INV_MODELFILE[STRING_SIZE];
		/* local variables */
	float vp, vs, rhov, y;
	int i, j, ii, jj;
	 
	
	/* parameters for layer 1 */
	const float vp1=680.0, vs1=320.0, rho1=1700.0, h=3.0;
	
	/* parameters for layer 2 */
	const float vp2=1000.0, vs2=590.0, rho2=2000.0;
	
	
	char modfile[STRING_SIZE];
	
	
	/*-----------------------------------------------------------------------*/



		

	/* loop over global grid */
		for (i=1;i<=NXG;i++){
			for (j=1;j<=NYG;j++){
			
				
				/* calculate coordinate in m */
				y=(float)j*DH;
				
 				/* two layer case */
 	                        if (y<=h){
																	                                   vp=vp1; vs=vs1; rhov=rho1; }


	                        else{
	                              vp=vp2; vs=vs2; rhov=rho2; }
			
				/*muv=vs1*vs1*rho1;
				piv=vp1*vp1*rho1;
				*/
				/* only the PE which belongs to the current global gridpoint 
				  is saving model parameters in his local arrays */
				if ((POS[1]==((i-1)/NX)) && 
				    (POS[2]==((j-1)/NY))){
					ii=i-POS[1]*NX;
					jj=j-POS[2]*NY;

					u[jj][ii]=vs;
					rho[jj][ii]=rhov;
					pi[jj][ii]=vp;
				}
			}
		}	

		
sprintf(modfile,"%s_rho_it_0.bin",INV_MODELFILE);
writemod(modfile,rho,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vs_it_0.bin",INV_MODELFILE);
writemod(modfile,u,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);

sprintf(modfile,"%s_vp_it_0.bin",INV_MODELFILE);
writemod(modfile,pi,3);
MPI_Barrier(MPI_COMM_WORLD);
if (MYID==0) mergemod(modfile,3);
}
void hessian_out(float ** hessian_lam, float ** hessian_mu, float ** hessian_rho, float ** ppi, float ** pu, float ** prho) {

    extern int NX, NY, IDX, IDY, DTINV, INVMAT1, MYID, POS[4], FDORDER, SPATFILTER;
    extern char JACOBIAN[STRING_SIZE];

    /* local variables */
    int i, j, k, l, ns_hess, ishot, irec, nd, NSRC_HESSIAN, NREC_HESSIAN, RECINC;
    char jac[STRING_SIZE];

    float lamss, muss;
    float ** hessian_vp, ** hessian_vs, ** hessian_rhos;

    FILE *FP4;

    nd = FDORDER/2 + 1;

    /* Diagonal elements of the Hessian*/
    hessian_vp = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
    hessian_vs = matrix(-nd+1,NY+nd,-nd+1,NX+nd);
    hessian_rhos = matrix(-nd+1,NY+nd,-nd+1,NX+nd);

    for (i=1; i<=NX; i=i+IDX) {
        for (j=1; j<=NY; j=j+IDY) {
            hessian_vp[j][i]=0.0;
            hessian_vs[j][i]=0.0;
            hessian_rhos[j][i]=0.0;
        }
    }

    /* construct Hessian for different material parameters */
    for (i=1; i<=NX; i=i+IDX) {
        for (j=1; j<=NY; j=j+IDY) {


            if(INVMAT1==1) {
                muss = prho[j][i] * pu[j][i] * pu[j][i];
                lamss = prho[j][i] * ppi[j][i] * ppi[j][i] - 2.0 * muss;
            }

            if(INVMAT1==3) {
                muss = pu[j][i];
                lamss = ppi[j][i];
            }

            /* new Pseudo-Hessian with improved correction of the geometrical spreading */
            hessian_lam[j][i] = (1.0/(4.0 * (lamss+muss) * (lamss+muss))) * hessian_lam[j][i];
            hessian_vp[j][i] = 2.0 * ppi[j][i] * prho[j][i] * hessian_lam[j][i];
            hessian_vs[j][i] = (- 4.0 * prho[j][i] * pu[j][i] * hessian_lam[j][i]) + 2.0 * prho[j][i] * pu[j][i] * hessian_mu[j][i];
            hessian_rhos[j][i]= ((((ppi[j][i] * ppi[j][i])-(2.0 * pu[j][i] * pu[j][i])) * hessian_lam[j][i]) + (pu[j][i] * pu[j][i] *hessian_mu[j][i]) + hessian_rho[j][i]);

        }
    }

    /* apply wavenumber damping for Vp-, Vs- and density Hessian */
    /*if(SPATFILTER==1){
      wavenumber(hessian);
      wavenumber(hessian_u);
      wavenumber(hessian_rho);
    }*/

    /* save Hessian for Vp */
    /* ----------------------- */
    sprintf(jac,"%s_hessian.%i%i",JACOBIAN,POS[1],POS[2]);
    FP4=fopen(jac,"wb");

    /* output of the gradient */
    for (i=1; i<=NX; i=i+IDX) {
        for (j=1; j<=NY; j=j+IDY) {
            fwrite(&hessian_vp[j][i],sizeof(float),1,FP4);
        }
    }

    fclose(FP4);

    MPI_Barrier(MPI_COMM_WORLD);

    /* merge gradient file */
    sprintf(jac,"%s_hessian",JACOBIAN);
    if (MYID==0) mergemod(jac,3);

    /* save HESSIAN for mu */
    /* ----------------------- */
    sprintf(jac,"%s_hessian_u.%i%i",JACOBIAN,POS[1],POS[2]);
    FP4=fopen(jac,"wb");

    /* output of the gradient */
    for (i=1; i<=NX; i=i+IDX) {
        for (j=1; j<=NY; j=j+IDY) {
            fwrite(&hessian_vs[j][i],sizeof(float),1,FP4);
        }
    }

    fclose(FP4);

    MPI_Barrier(MPI_COMM_WORLD);

    /* merge gradient file */
    sprintf(jac,"%s_hessian_u",JACOBIAN);
    if (MYID==0) mergemod(jac,3);

    /* save HESSIAN for rho */
    /* ----------------------- */
    sprintf(jac,"%s_hessian_rho.%i%i",JACOBIAN,POS[1],POS[2]);
    FP4=fopen(jac,"wb");

    /* output of the gradient */
    for (i=1; i<=NX; i=i+IDX) {
        for (j=1; j<=NY; j=j+IDY) {
            fwrite(&hessian_rhos[j][i],sizeof(float),1,FP4);
        }
    }

    fclose(FP4);

    MPI_Barrier(MPI_COMM_WORLD);

    /* merge gradient file */
    sprintf(jac,"%s_hessian_rho",JACOBIAN);
    if (MYID==0) mergemod(jac,3);

    free_matrix(hessian_vp,-nd+1,NY+nd,-nd+1,NX+nd);
    free_matrix(hessian_vs,-nd+1,NY+nd,-nd+1,NX+nd);
    free_matrix(hessian_rhos,-nd+1,NY+nd,-nd+1,NX+nd);

}
Example #16
0
void  smooth2(float ** grad){

	/* declaration of extern variables */
        extern int NX, NY, NXG, NYG, IDX, IDY, GRADT2;
	extern int NPROCX, NPROCY, MYID, POS[3];
	extern int SPAT_FILT_SIZE;
	extern float WD_DAMP, WD_DAMP1;
	extern char JACOBIAN[STRING_SIZE];
	
	/* declaration of local variables */
	int i,j, h, fa, fb, itr, ix, iz, n1,n2;
	int tracl1, jj, ii, nmax, * win;
	float gradtmp, ** v, r1, r2, **w, *d, *e, *f, rw;
        
	char jac[STRING_SIZE];
	FILE *fp_grad, *FP3;
	
        /* define parameters */
        r1=WD_DAMP;
        r2=WD_DAMP1;

        n1=NYG;
        n2=NXG;

        /* scale the smoothing parameter */
        r1 = r1*r1*0.25;
        r2 = r2*r2*0.25;
        
        /* allocate space */
        nmax = (n1<n2)?n2:n1;
        win = ivector(0,4);
        w = matrix(0,n2,0,n1);
        d = vector(0,nmax);
        e = vector(0,nmax);
        f = vector(0,nmax);

        /* define windows function */
        win[0] = GRADT2;
        win[1] = n1;
        win[2] = 0;
        win[3] = n2;
        rw=0.;
        rw=rw*rw*0.25;
    
	                    
	/* temporarily save gradient for wavenumber filtering */
        sprintf(jac,"%s_wavenumber.old.%i%i",JACOBIAN,POS[1],POS[2]);
        FP3=fopen(jac,"wb");
                        
        for (i=1;i<=NX;i=i+IDX){
            for (j=1;j<=NY;j=j+IDY){
                fwrite(&grad[j][i],sizeof(float),1,FP3);
            }                       
        }                           
                                    
        fclose(FP3);                
                                    
        MPI_Barrier(MPI_COMM_WORLD);
                                  
        /* merge gradient file */ 
        sprintf(jac,"%s_wavenumber.old",JACOBIAN);
        if (MYID==0) mergemod(jac,3);  


if(MYID==0){    /* read the global model on node 0 and apply wavenumber damping */
        
        /* define temporary gradient matrix */
        v = matrix(0,n2,0,n1);
        
	printf("\n Smooth2 is applied to gradient (written by PE %d)\n",MYID); 
	
	fp_grad=fopen(jac,"rb");
	
	if (fp_grad==NULL) err(" Could not open gradient file ! ");
	
	/* load merged gradient */
	for (i=1;i<=n2;i++){
	   for (j=1;j<=n1;j++){
	        
	            fread(&gradtmp, sizeof(float), 1, fp_grad);
	            v[i][j] = gradtmp;		

            }
	}
	
	fclose(fp_grad);
	
	                                                                                                                                                                                             
	/* define the window function */
        for(ix=0; ix<n2; ++ix)
                for(iz=0; iz<n1; ++iz)
                        w[ix][iz] = 0;  
        for(ix=win[2]; ix<win[3]; ++ix)
                for(iz=win[0]; iz<win[1]; ++iz)
                        w[ix][iz] = 1;  

        if(win[0]>0 || win[1]<n1 || win[2]>0 || win[3]<n2){
        /* smooth the window function */
                for(iz=0; iz<n1; ++iz){
                        for(ix=0; ix<n2; ++ix){
                                d[ix] = 1.0+2.0*rw;
                                e[ix] = -rw;
                                f[ix] = w[ix][iz];
                        }
                        d[0] -= rw;
                        d[n2-1] -= rw;
                        tripd(d,e,f,n2);
                        for(ix=0; ix<n2; ++ix)
                                w[ix][iz] = f[ix];
                }
                for(ix=0; ix<n2; ++ix){
                        for(iz=0; iz<n1; ++iz){
                                d[iz] = 1.0+2.0*rw;
                                e[iz] = -rw;
                                f[iz] = w[ix][iz];
                }
                        d[0] -= rw;
                        d[n1-1] -= rw;
                        tripd(d,e,f,n1);
                        for(iz=0; iz<n1; ++iz)
                                w[ix][iz] = f[iz];
                }
        }

        /* solving for the smoothing velocity */
        for(iz=0; iz<n1; ++iz){
                for(ix=0; ix<n2-1; ++ix){
                        d[ix] = 1.0+r2*(w[ix][iz]+w[ix+1][iz]);
                        e[ix] = -r2*w[ix+1][iz];
                        f[ix] = v[ix][iz];
                }
                d[0] -= r2*w[0][iz];
                d[n2-1] = 1.0+r2*w[n2-1][iz];
                f[n2-1] = v[n2-1][iz];
                tripd(d,e,f,n2);
                for(ix=0; ix<n2; ++ix)
                        v[ix][iz] = f[ix];
        }
         for(ix=0; ix<n2; ++ix){
                for(iz=0; iz<n1-2; ++iz){
                        d[iz] = 1.0+r1*(w[ix][iz+1]+w[ix][iz+2]);
                        e[iz] = -r1*w[ix][iz+2];
                        f[iz] = v[ix][iz+1];
                }
                f[0] += r1*w[ix][1]*v[ix][0];
                d[n1-2] = 1.0+r1*w[ix][n1-1];
                f[n1-2] = v[ix][n1-1];
                tripd(d,e,f,n1-1);
                for(iz=0; iz<n1-1; ++iz)
                        v[ix][iz+1] = f[iz];
        }

      
	/* write damped gradient to temporary file */
	sprintf(jac,"%s_smooth2.old",JACOBIAN);
	FP3=fopen(jac,"wb");

	for (i=1;i<=n2;i++){
		for (j=1;j<=n1;j++){
		
                    gradtmp = v[i][j];
	            fwrite(&gradtmp,sizeof(float),1,FP3);	 
			 
		}
	}
	fclose(FP3);
	        
	/* free memory */
        free_matrix(v,0,n2,0,n1);
        
} /* end of if MYID==0*/

	 MPI_Barrier(MPI_COMM_WORLD);

         sprintf(jac,"%s_smooth2.old",JACOBIAN);
	 FP3=fopen(jac,"rb");

	 /* distribute spatial filtered gradient on computational nodes */
	 for (i=1;i<=NXG;i++){
	    for (j=1;j<=NYG;j++){
			
			fread(&gradtmp, sizeof(float),1,FP3);

			if ((POS[1]==((i-1)/NX)) && 
		   	 (POS[2]==((j-1)/NY))){
				ii=i-POS[1]*NX;
				jj=j-POS[2]*NY;

				grad[jj][ii]=gradtmp;

			}
			
		}
	}

        fclose(FP3);

        /* clean up temporary files*/
        MPI_Barrier(MPI_COMM_WORLD);
        sprintf(jac,"%s_wavenumber.old.%i%i",JACOBIAN,POS[1],POS[2]);
        remove(jac);
                                

}
Example #17
0
void taper_grad(float ** waveconv,float ** taper_coeff, float **srcpos, int nshots, int **recpos, int ntr, int sws)
{

	/* extern variables */

        extern float DH;
	extern int FREE_SURF, NX, NY, NXG, NYG;
	extern int NPROCX, NPROCY, MYID, POS[3];
	extern FILE *FP;
	
	/* local variables */
	int i, j, h, ifw, ii, jj, n, xb, yb, xe, ye, taperlength,taperlength2, VTON, SRTON;
	int ijc, iy, ix, iii, jjj, xx, yy, srctaper_gridpt, i1, j1;

	extern int GRADT1, GRADT2, GRADT3, GRADT4;
	float amp, a, *window, grad_tap, **waveconvtmp;
	char modfile[STRING_SIZE];
	
	extern float SRTRADIUS;
	extern int SRTSHAPE, FILTSIZE;
        float **m, **edgemat, **mm, **msum, minm, maxm, x, y, rad, **taper_coeff_glob;
        float maxrad;
        float EXP_TAPER_GRAD_HOR;

	FILE *fp_taper;

	/*SRTSHAPE=2;
	SRTRADIUS=25.0;
	filtsize=2;*/
        
        EXP_TAPER_GRAD_HOR = 2.0; /* TAPER TEST  */

    /* =============== */
    /* Vertical taper  */
    /* =============== */
	
	if(sws==1){
	
	/* define taper geometry */
	taperlength=GRADT2-GRADT1;
	taperlength2=GRADT4-GRADT3;
	ifw = GRADT4-GRADT1;
	
	/*printf("%d \t %d \t %d \t %d \n",GRADT1, GRADT2, GRADT3, GRADT4);
	printf("%d \t %d \t %d \n",taperlength, taperlength2,ifw);*/
	
	if (MYID==0)
	{
		fprintf(FP,"\n **Message from taper_grad (printed by PE %d):\n",MYID);
		fprintf(FP," Coefficients for gradient taper are now calculated.\n");
	}
	
	waveconvtmp = matrix(0,NY+1,0,NX+1);
	window=vector(1,ifw);
	 
	 /* Gaussian window */  
        a=3;    /* damping coefficient */
        for (i=1;i<=ifw;i++){
	window[i] = 1.0;
	
	    if(i<=taperlength){
	       window[i] = exp(-(1.0/2.0)*(a*(i-taperlength)/(taperlength/2.0))*(a*(i-taperlength)/(taperlength/2.0)));
	    }
	    
	    if(i>=(ifw-taperlength2)){
	       window[i] = exp(-(1.0/2.0)*(a*(i-(ifw-taperlength2))/(taperlength2/2.0))*(a*(i-(ifw-taperlength2))/(taperlength2/2.0)));
	    }
	    
	}
	
	/* loop over global grid */
	for (j=1;j<=NYG;j++){
	
	   h=1;
	   for (i=1;i<=NXG;i++){

                        grad_tap=0.0;
			
			if((i>GRADT1)&&(i<GRADT4)){
			   grad_tap=window[h];
			   h++;
			}
			   			
			if ((POS[1]==((i-1)/NX)) && 
		   	 (POS[2]==((j-1)/NY))){
				ii=i-POS[1]*NX;
				jj=j-POS[2]*NY;

				taper_coeff[jj][ii]=grad_tap;

			}
		}
	}	
	
	/* apply taper on local gradient */
	for (j=1;j<=NY;j++){
	   for (i=1;i<=NX;i++){
           waveconv[j][i]*=taper_coeff[j][i];
	   waveconvtmp[j][i] = waveconv[j][i];
           }
	}
	
		
        /* apply filter at shot and receiver points */
	for (n=1;n<=nshots;n++)
	{
		i = iround(srcpos[1][n]/DH);
		j = iround(srcpos[2][n]/DH);
		if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
			ii = i-POS[1]*NX;
			jj = j-POS[2]*NY;
			/*waveconvtmp[jj][ii] = 1*waveconv[jj][ii]
						+ 8*(waveconv[jj-1][ii] + waveconv[jj+1][ii] + waveconv[jj][ii-1] + waveconv[jj][ii+1])
						+ 4*(waveconv[jj-1][ii-1] + waveconv[jj-1][ii+1] + waveconv[jj+1][ii+1] + waveconv[jj+1][ii-1]);
			waveconvtmp[jj][ii] = waveconvtmp[jj][ii]/49;*/
			
			waveconvtmp[jj][ii] = 0.0;
		}
	}

	for (j=1;j<=NY;j++){
		for (i=1;i<=NX;i++){
        		waveconv[j][i] = waveconvtmp[j][i];
		}
	}	
	
	for (n=1;n<=ntr;n++)
	{
		i = recpos[1][n];
		j = recpos[2][n];
		if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
			ii = i-POS[1]*NX;
			jj = j-POS[2]*NY;
			/*waveconvtmp[jj][ii] = 1*waveconv[jj][ii]
						+ 8*(waveconv[jj-1][ii] + waveconv[jj+1][ii] + waveconv[jj][ii-1] + waveconv[jj][ii+1])
						+ 4*(waveconv[jj-1][ii-1] + waveconv[jj-1][ii+1] + waveconv[jj+1][ii+1] + waveconv[jj+1][ii-1]);
			waveconvtmp[jj][ii] = waveconvtmp[jj][ii]/49;*/
			
			waveconvtmp[jj][ii] = 0.0;
			
		}
	}

	for (j=1;j<=NY;j++){
		for (i=1;i<=NX;i++){
        		waveconv[j][i] = waveconvtmp[j][i];
		}
	}	

	sprintf(modfile,"taper_coeff_vert.bin");

	writemod(modfile,taper_coeff,3); 

	MPI_Barrier(MPI_COMM_WORLD);

	if (MYID==0) mergemod(modfile,3); 


	free_vector(window,1,ifw);
	free_matrix(waveconvtmp,0,NX+1,0,NY+1);
	}

        
	/* ======================== */
	/* Horizontal Taper         */
	/* ======================== */
	
	if(sws==2){
        /* define taper geometry */
        taperlength=GRADT2-GRADT1;
        taperlength2=GRADT4-GRADT3;
        ifw = GRADT2-GRADT1+1;

        printf("%d \t %d \t %d \t %d \n",GRADT1, GRADT2, GRADT3, GRADT4);
        printf("%d \t %d \t %d \n",taperlength, taperlength2,ifw);

        if (MYID==0)
        {
                fprintf(FP,"\n **Message from taper_grid (printed by PE %d):\n",MYID);
                fprintf(FP," Coefficients for gradient taper are now calculated.\n");
        }

        waveconvtmp = matrix(0,NY+1,0,NX+1);
        window=vector(1,ifw);
         
        /* Gaussian window */  
        a=3;    /* damping coefficient */
        for (i=1;i<=ifw;i++){
        window[i] = 1.0;

            if(i<=taperlength){
               window[i] = exp(-(1.0/2.0)*(a*(i-taperlength)/(taperlength/2.0))*(a*(i-taperlength)/(taperlength/2.0)));
            }
          
        }

        /* loop over global grid */
	h=1;
        for (j=1;j<=NYG;j++){
           for (i=1;i<=NXG;i++){

                        grad_tap=0.0;

                        if((j>=GRADT1)&&(j<=GRADT2)){
                           grad_tap=window[h];
                        }

                        if(j>GRADT2){
                          
                          /*grad_tap=((float)(j*DH))*((float)(j*DH))*((float)(j*DH));*/
			  /*grad_tap=((float)(j*DH))*((float)(j*DH));*/
			  /*grad_tap=(float)(j*DH);*/ 
			  
			  /*grad_tap=((float)((j*DH)/(GRADT2*DH)));*/ 
			  /*grad_tap=1.0;*/

			  grad_tap=pow((float)(j*DH),EXP_TAPER_GRAD_HOR);

                        }
                        
                        /*grad_tap=((float)(j*DH));*/
			
			  
                        if ((POS[1]==((i-1)/NX)) && 
                         (POS[2]==((j-1)/NY))){
                                ii=i-POS[1]*NX;
                                jj=j-POS[2]*NY;

                                taper_coeff[jj][ii]=grad_tap;

                        }

                }
		
	   if(j>=GRADT1){h++;}
        }

        /* apply taper on local gradient */
        for (j=1;j<=NY;j++){
           for (i=1;i<=NX;i++){
           waveconv[j][i]*=taper_coeff[j][i];
           waveconvtmp[j][i] = waveconv[j][i];
           }
        }



        /* apply filter at shot and receiver points */
        /*for (n=1;n<=nshots;n++)
        {
                i = iround(srcpos[1][n]/DH);
                j = iround(srcpos[2][n]/DH);
                if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
                        ii = i-POS[1]*NX;
                        jj = j-POS[2]*NY;
                        waveconvtmp[jj][ii] = 1*waveconv[jj][ii]
                                                + 8*(waveconv[jj-1][ii] + waveconv[jj+1][ii] + waveconv[jj][ii-1] + waveconv[jj][ii+1])
                                                + 4*(waveconv[jj-1][ii-1] + waveconv[jj-1][ii+1] + waveconv[jj+1][ii+1] + waveconv[jj+1][ii-1]);
                        waveconvtmp[jj][ii] = waveconvtmp[jj][ii]/49;
                }
        }

        for (j=1;j<=NY;j++){
                for (i=1;i<=NX;i++){
                        waveconv[j][i] = waveconvtmp[j][i];
                }
        }

        for (n=1;n<=ntr;n++)
        {
                i = recpos[1][n];
                j = recpos[2][n];
                if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
                        ii = i-POS[1]*NX;
                        jj = j-POS[2]*NY;
                        waveconvtmp[jj][ii] = 1*waveconv[jj][ii]
                                                + 8*(waveconv[jj-1][ii] + waveconv[jj+1][ii] + waveconv[jj][ii-1] + waveconv[jj][ii+1])
                                                + 4*(waveconv[jj-1][ii-1] + waveconv[jj-1][ii+1] + waveconv[jj+1][ii+1] + waveconv[jj+1][ii-1]);
                        waveconvtmp[jj][ii] = waveconvtmp[jj][ii]/49;
                }
        }

        for (j=1;j<=NY;j++){
                for (i=1;i<=NX;i++){
                        waveconv[j][i] = waveconvtmp[j][i];
                }
        }*/

        sprintf(modfile,"taper_coeff_hor.bin");
        writemod(modfile,taper_coeff,3); 
        MPI_Barrier(MPI_COMM_WORLD);
        if (MYID==0) mergemod(modfile,3); 


        free_vector(window,1,ifw);
        free_matrix(waveconvtmp,0,NX+1,0,NY+1);
        } /* end of sws==2 */

        /* =================================== */
        /* taper source and receiver positions */
	/* =================================== */
	
	if(sws==3) {
                /* Convert from meters to gridpoints -> minimum 5x5 gridpoints */
                srctaper_gridpt = (int)(ceil(2.0*SRTRADIUS/DH));
                if (srctaper_gridpt<5)  srctaper_gridpt = 5;

                m               = matrix(1,srctaper_gridpt,1,srctaper_gridpt);
                edgemat         = matrix(1,4,1,1);
                mm              = matrix(1,NYG,1,NXG);
                msum            = matrix(1,NYG,1,NXG);
                taper_coeff_glob= matrix(1,NYG,1,NXG);
		waveconvtmp     = matrix(0,NY+1,0,NX+1);

                for (iy=1;iy<=NYG;iy++)
                        for (ix=1;ix<=NXG;ix++)  msum[iy][ix] = 1.0;

                MPI_Barrier(MPI_COMM_WORLD);

                /*****************************/
                /* Taper at source positions */
                /*****************************/

                a = 1.0;
                maxrad = sqrt(2.0*SRTRADIUS*SRTRADIUS);
                for (j=1;j<=srctaper_gridpt;j++) {
                        for (i=1;i<=srctaper_gridpt;i++) {
                                x = ((float)i-((float)srctaper_gridpt)/2.0-0.5)*DH;
                                y = ((float)j-((float)srctaper_gridpt)/2.0-0.5)*DH;
                                rad = sqrt(x*x+y*y);

                                switch (SRTSHAPE) {
                                case 1:
                                        m[j][i] = erf(a*rad/maxrad);
                                        break;
                                case 2:
                                        if (rad>0)      m[j][i] = log(rad);
                                        else            m[j][i] = 0.0;
                                        break;
                                }
                        }
                }

                /* generate local taper matrix */
                minm = minimum_m(m,srctaper_gridpt,srctaper_gridpt);
                for (j=1;j<=srctaper_gridpt;j++)
                        for (i=1;i<=srctaper_gridpt;i++)  m[j][i] -= minm;

                /* normalize taper matrix to max of values at the centre of all 4 taper area edges,     */
                /* not the global maximum, which is located at the corners                              */
                edgemat[1][1] = m[1][srctaper_gridpt/2];
                edgemat[2][1] = m[srctaper_gridpt/2][1];
                edgemat[3][1] = m[srctaper_gridpt/2][srctaper_gridpt];
                edgemat[4][1] = m[srctaper_gridpt][srctaper_gridpt/2];
                maxm = maximum_m(edgemat,1,4);
                for (j=1;j<=srctaper_gridpt;j++)
                        for (i=1;i<=srctaper_gridpt;i++) {
                                m[j][i] /= maxm;
                                if (m[j][i]>1.0)  m[j][i] = 1.0;
                        }

                /* get central position within the taper */
                ijc = (int)(ceil((float)srctaper_gridpt/2));

                /*********************/
                /* loop over sources */
                for (n=1;n<=nshots;n++) {
                        for (iy=1;iy<=NYG;iy++)
                                for (ix=1;ix<=NXG;ix++)  mm[iy][ix] = 1.0;

                        i = iround(srcpos[1][n]/DH);
                        j = iround(srcpos[2][n]/DH);
                        for (iy=1;iy<=srctaper_gridpt;iy++) {
                                for (ix=1;ix<=srctaper_gridpt;ix++) {
                                        xx = i + ix - ijc;
                                        yy = j + iy - ijc;
                                        if ((xx<1) || (xx>NXG) || (yy<1) || (yy>NYG))  continue;
                                        mm[yy][xx] = m[iy][ix];
                                }
                        }

/*                      for (iy=1;iy<=NYG;iy++)
                                for (ix=1;ix<=NXG;ix++)  msum[iy][ix] += mm[iy][ix];
*/
                        for (iy=1;iy<=NYG;iy++)
                                for (ix=1;ix<=NXG;ix++)
                                        if (msum[iy][ix] > mm[iy][ix])
                                                msum[iy][ix] = mm[iy][ix];

                }

                /***********************/
                /* loop over receivers */
                /*for (n=1;n<=ntr;n++) {
                        for (iy=1;iy<=NYG;iy++)
                                for (ix=1;ix<=NXG;ix++)  mm[iy][ix] = 1.0;

                        i = recpos[1][n];
                        j = recpos[2][n];
                        for (iy=1;iy<=srctaper_gridpt;iy++) {
                                for (ix=1;ix<=srctaper_gridpt;ix++) {
                                        xx = i + ix - ijc;
                                        yy = j + iy - ijc;
                                        if ((xx<1) || (xx>NXG) || (yy<1) || (yy>NYG))  continue;
                                        mm[yy][xx] = m[iy][ix];
                                }
                        }*/

/*                      for (iy=1;iy<=NYG;iy++)    Die kommenden zwei Zeilen wurden von Daniel auskommentiert.
                                for (ix=1;ix<=NXG;ix++)  msum[iy][ix] += mm[iy][ix];
*/
                       /* for (iy=1;iy<=NYG;iy++)
                                for (ix=1;ix<=NXG;ix++)
                                        if (msum[iy][ix] > mm[iy][ix])
                                                msum[iy][ix] = mm[iy][ix];

                }*/

                minm = minimum_m(msum,NXG,NYG);
                for (iy=1;iy<=NYG;iy++)
                        for (ix=1;ix<=NXG;ix++)  msum[iy][ix] -= minm;

                maxm = maximum_m(msum,NXG,NYG);
                for (iy=1;iy<=NYG;iy++)
                        for (ix=1;ix<=NXG;ix++) {
                                taper_coeff_glob[iy][ix] = msum[iy][ix]/maxm;

                                if ((POS[1]==((ix-1)/NX)) && (POS[2]==((iy-1)/NY))){
                                        ii = ix-POS[1]*NX;
                                        jj = iy-POS[2]*NY;
                                        /*Diese Zeile wurde von Daniel auskommentiert: taper_coeff[jj][ii] = taper_coeff_glob[iy][ix] * ((float)(iy*DH));*/
					/*taper_coeff[jj][ii] = ((float)(iy*DH)) * ((float)(iy*DH)) * ((float)(iy*DH));*/
					taper_coeff[jj][ii]=msum[iy][ix]/maxm;
                                }
                        }
			
	/* apply taper on local gradient */
        for (j=1;j<=NY;j++){
           for (i=1;i<=NX;i++){
           waveconv[j][i]*=taper_coeff[j][i];
           waveconvtmp[j][i] = waveconv[j][i];
           }
        }	
		
	 /* apply filter at shot and receiver points */
	for (n=1;n<=nshots;n++)
	{
		i1 = iround(srcpos[1][n]/DH);
		j1 = iround(srcpos[2][n]/DH);
		
		for (i=i1-FILTSIZE;i<=i1+FILTSIZE;i++){
		   for (j=j1-FILTSIZE;j<=j1+FILTSIZE;j++){
		       if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
			     ii = i-POS[1]*NX;
			     jj = j-POS[2]*NY;
			     /*waveconvtmp[jj][ii] = 1*waveconv[jj][ii]
				       		+ 8*(waveconv[jj-1][ii] + waveconv[jj+1][ii] + waveconv[jj][ii-1] + waveconv[jj][ii+1])
						+ 4*(waveconv[jj-1][ii-1] + waveconv[jj-1][ii+1] + waveconv[jj+1][ii+1] + waveconv[jj+1][ii-1]);
			      waveconvtmp[jj][ii] = waveconvtmp[jj][ii]/49;*/
			      if (jj>0){
			         waveconvtmp[jj][ii] = 0.0;
			         taper_coeff[jj][ii] = 0.0;
			      }
		        }
		    }
		}
		
		
	}

	
	/*for (n=1;n<=ntr;n++)
	{
		i1 = recpos[1][n];
		j1 = recpos[2][n];
		
            for (i=i1-FILTSIZE;i<=i1+FILTSIZE;i++){
		   for (j=j1-FILTSIZE;j<=j1+FILTSIZE;j++){
		
		       if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
			    ii = i-POS[1]*NX;
			    jj = j-POS[2]*NY;   */
			    /* Die kommenden 4 Zeilen wurden von Daniel auskommentiert. waveconvtmp[jj][ii] = 1*waveconv[jj][ii]
						+ 8*(waveconv[jj-1][ii] + waveconv[jj+1][ii] + waveconv[jj][ii-1] + waveconv[jj][ii+1])
						+ 4*(waveconv[jj-1][ii-1] + waveconv[jj-1][ii+1] + waveconv[jj+1][ii+1] + waveconv[jj+1][ii-1]);
			      waveconvtmp[jj][ii] = waveconvtmp[jj][ii]/49;*/
			
		/*	waveconvtmp[jj][ii] = 0.0;
			
		       }
		   }
	     }	       
	}*/		
		
        /* apply taper on local gradient */
        for (j=1;j<=NY;j++){
           for (i=1;i<=NX;i++){
           waveconv[j][i] = waveconvtmp[j][i];
           }
        }
	
	
                free_matrix(m,1,srctaper_gridpt,1,srctaper_gridpt);
                free_matrix(edgemat,1,4,1,1);
                free_matrix(mm,1,NYG,1,NXG);
                free_matrix(msum,1,NYG,1,NXG);
                free_matrix(taper_coeff_glob,1,NYG,1,NXG);
		free_matrix(waveconvtmp,0,NX+1,0,NY+1);
        
	
	

 
		
	MPI_Barrier(MPI_COMM_WORLD);
        sprintf(modfile,"taper_coeff_sources.bin");
        writemod(modfile,taper_coeff,3); 
        MPI_Barrier(MPI_COMM_WORLD);
        if (MYID==0) mergemod(modfile,3); 
	
	}

    /* ======================== */
    /* Read Taper from file     */  
    /* ======================== */
        
    if((sws>=4)&&(sws<=6)){
        
          if (MYID==0)
          {
                  fprintf(FP,"\n **Message from taper_grid (printed by PE %d):\n",MYID);
                  fprintf(FP," Coefficients for gradient taper are now calculated.\n");
          }
        
        if(sws==4){fp_taper=fopen("taper.bin","r");}
        if(sws==5){fp_taper=fopen("taper_u.bin","r");}
        if(sws==6){fp_taper=fopen("taper_rho.bin","r");}

        /* loop over global grid */
        for (i=1;i<=NXG;i++){
            for (j=1;j<=NYG;j++){
           
                fread(&grad_tap, sizeof(float), 1, fp_taper);
                                                                                       
                if ((POS[1]==((i-1)/NX)) && (POS[2]==((j-1)/NY))){
                   ii=i-POS[1]*NX;
                   jj=j-POS[2]*NY;
        
                   taper_coeff[jj][ii]=grad_tap;
                             
                }
            }
        }
 
        for (j=1;j<=NY;j++){   
           for (i=1;i<=NX;i++){     
              waveconv[j][i]*=taper_coeff[j][i];
           }                            
        }   
                                         
        fclose(fp_taper);
        
        sprintf(modfile,"taper_coeff_file.bin");
        writemod(modfile,taper_coeff,3);
                        
        MPI_Barrier(MPI_COMM_WORLD);
        if (MYID==0) mergemod(modfile,3);       
        } 
}
Example #18
0
void LBFGS1(float ** taper_coeff, int nsrc, float ** srcpos, int ** recpos, int ntr_glob, int iter, int nfstart_jac, float ** waveconv, float C_vp, float ** gradp, float ** waveconv_u, float C_vs, float ** gradp_u, float ** waveconv_rho, float C_rho, float ** gradp_rho, float * y_LBFGS, float * s_LBFGS, float * rho_LBFGS, 
            float * alpha_LBFGS, float **ppi, float ** pu, float ** prho, int nxnyi, float * q_LBFGS, float * r_LBFGS, float * beta_LBFGS, int LBFGS_pointer, int NLBFGS, int NLBFGS_vec){

	extern int NX, NY, IDX, IDY, SPATFILTER;
	extern int HESSIAN, INVMAT, SWS_TAPER_GRAD_VERT, SWS_TAPER_GRAD_HOR, SWS_TAPER_GRAD_SOURCES, SWS_TAPER_FILE;
	extern int POS[3], MYID;
	extern char JACOBIAN[STRING_SIZE];
	
	char jac[225], jac1[225];
	int i, j, k, h, h1, h2;
	float betaz, betan, gradplastiter, gradclastiter, betar, beta;
	float gamma_LBFGS, sum_nom, sum_denom;
        float LBFGSTMP, LBFGSTMP1, LBFGSTMP2, LBFGSTMP3, modellastiter, norm_fac, norm_fac_u, norm_fac_rho;
        float beta_LBFGS_1;
        int ki, itershift, iter1;
	extern FILE *FP;
	FILE *FP3, *FP4, *FP6, *FP5, *FP7;
	
        itershift = 1;

/* =================================================================================================================================================== */
/* ===================================================================================================================================================== */
/* ===================================================== GRADIENT Vp/Zp/lambda ================================================================================== */
/* ===================================================================================================================================================== */

if((INVMAT==1)||(INVMAT==0)){
	
/* Normalization of the gradient   */
/* ------------------------------- */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
      waveconv[j][i] = C_vp * waveconv[j][i];
   }
}

/* TEST: IMPLEMENTATION OF TAPER IN denise.c */
/*if (SWS_TAPER_GRAD_VERT){*/   /*vertical gradient taper is applied*/
   /*taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,1);}*/

/*if (SWS_TAPER_GRAD_HOR){*/   /*horizontal gradient taper is applied*/
   /*taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,2);}*/

/*if (SWS_TAPER_GRAD_SOURCES){*/   /*cylindrical taper around sources is applied*/
   /*taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,3);}*/
 
/* apply Hessian^-1 and save in gradp*/
/*if (SWS_TAPER_FILE){ 
  taper_grad(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,5);
}*/

/* apply median filter at source positions */
/*median_src(waveconv,taper_coeff,srcpos,nsrc,recpos,ntr_glob,iter,0);*/

/* apply wavenumber damping */
if(SPATFILTER==1){
  wavenumber(waveconv);
}

if(SPATFILTER==2){
  smooth2(waveconv);
}
  
/* Normalize gradient to maximum value */
/*norm_fac_u=norm(waveconv_u,iter,2);
if(MYID==0){printf("norm_fac_u=%e \n",norm_fac_u);}*/
  
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
	  gradp[j][i] = waveconv[j][i];
   }
}

/* save gradient for output as inversion result */
if(iter==nfstart_jac){
	sprintf(jac,"%s_p_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        	for (i=1;i<=NX;i=i+IDX){
           	for (j=1;j<=NY;j=j+IDY){
                	fwrite(&waveconv[j][i],sizeof(float),1,FP3);
           	}
        	}
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_it%d.old",JACOBIAN,iter);
	if (MYID==0) mergemod(jac,3);
}

}

/* =================================================================================================================================================== */
/* ===================================================================================================================================================== */
/* ===================================================== GRADIENT Vs/Zs/mu ================================================================================== */
/* ===================================================================================================================================================== */

if((INVMAT==3)||(INVMAT==0)){
	
/* Normalization of the gradient   */
/* ------------------------------- */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
      waveconv_u[j][i] = C_vs * waveconv_u[j][i];
   }
}

/* TEST: IMPLEMENTATION OF TAPER IN denise.c */
/*if (SWS_TAPER_GRAD_VERT){*/   /*vertical gradient taper is applied*/
   /*taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,1);}*/

/*if (SWS_TAPER_GRAD_HOR){*/   /*horizontal gradient taper is applied*/
   /*taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,2);}*/

/*if (SWS_TAPER_GRAD_SOURCES){*/   /*cylindrical taper around sources is applied*/
   /*taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,3);}*/
 
/* apply Hessian^-1 and save in gradp*/
/*if (SWS_TAPER_FILE){ 
  taper_grad(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,5);
}*/

/* apply median filter at source positions */
/*median_src(waveconv_u,taper_coeff,srcpos,nsrc,recpos,ntr_glob,iter,0);*/

/* apply wavenumber damping */
if(SPATFILTER==1){
  wavenumber(waveconv_u);
}

if(SPATFILTER==2){
  smooth2(waveconv_u);
}
  
/* Normalize gradient to maximum value */
/*norm_fac_u=norm(waveconv_u,iter,2);
if(MYID==0){printf("norm_fac_u=%e \n",norm_fac_u);}*/
  
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
	  gradp_u[j][i] = waveconv_u[j][i];
   }
}

/* save gradient for output as inversion result */
if(iter==nfstart_jac){
	sprintf(jac,"%s_p_u_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        	for (i=1;i<=NX;i=i+IDX){
           	for (j=1;j<=NY;j=j+IDY){
                	fwrite(&waveconv_u[j][i],sizeof(float),1,FP3);
           	}
        	}
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_u_it%d.old",JACOBIAN,iter);
	if (MYID==0) mergemod(jac,3);
}

}

/* ===================================================================================================================================================== */
/* ===================================================== GRADIENT rho ================================================================================== */
/* ===================================================================================================================================================== */

if((INVMAT==2)||(INVMAT==0)){

/* Normalization of the gradient   */
/* ------------------------------- */
for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
      waveconv_rho[j][i] = C_rho * waveconv_rho[j][i];
   }
}

/* TEST: IMPLEMENTAION OF TAPER IN denise.c */
/*if (SWS_TAPER_GRAD_VERT){*/   /*vertical gradient taper is applied*/
   /*taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,1);}*/

/*if (SWS_TAPER_GRAD_HOR){*/   /*horizontal gradient taper is applied*/
   /*taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,2);}*/

/*if (SWS_TAPER_GRAD_SOURCES){*/   /*cylindrical taper around sources is applied*/
   /*taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,3);}*/

/* apply Hessian^-1 and save in gradp*/
/*if (SWS_TAPER_FILE){ 
  taper_grad(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,6);
}*/

/* apply median filter at source positions */
/*median_src(waveconv_rho,taper_coeff,srcpos,nsrc,recpos,ntr_glob,iter,0);*/

/* apply wavenumber damping */
if(SPATFILTER==1){
  wavenumber(waveconv_rho);
}

if(SPATFILTER==2){
  smooth2(waveconv_rho);
}
   
/* Normalize gradient to maximum value */
/*norm_fac_rho=norm(waveconv_rho,iter,3);
if(MYID==0){printf("norm_fac_rho=%e \n",norm_fac_rho);}*/

for (i=1;i<=NX;i=i+IDX){
   for (j=1;j<=NY;j=j+IDY){
	  gradp_rho[j][i] = waveconv_rho[j][i];
   }
} 

/* apply spatial wavelength filter */
/*if(SPATFILTER==1){
	if (MYID==0){
   	fprintf(FP,"\n Spatial filter is applied to gradient (written by PE %d)\n",MYID);}
spat_filt(waveconv_rho,iter,3);}*/

/* save gradient for output as inversion result */
if(iter==nfstart_jac){
	sprintf(jac,"%s_p_rho_it%d.old.%i%i",JACOBIAN,iter,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        	for (i=1;i<=NX;i=i+IDX){
           	for (j=1;j<=NY;j=j+IDY){
                	fwrite(&waveconv_rho[j][i],sizeof(float),1,FP3);
           	}
        	}
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_rho_it%d.old",JACOBIAN,iter);
	if (MYID==0) mergemod(jac,3);
}
}

/* calculate H^-1 * waveconv, using the L-BFGS method, if iter > 1 */
/* --------------------------------------------------------------------- */

if(iter>1){

   /* load old models and gradients - rho and store them in the LBFGS vectors */
   /* ------------------------------------------------------------------------ */

   sprintf(jac,"%s_p_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP6=fopen(jac,"rb");
   
   sprintf(jac1,"%s_p_mrho.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP7=fopen(jac1,"rb");

   /*iter1 = iter-itershift;*/ /* shift iter counter by 1 because L-BFGS method starts at iter > 1 */
   
   h = NLBFGS_vec*(LBFGS_pointer-1) + 1; /* locate current initial position in LBFGS-vector */
   
     for (i=1;i<=NX;i=i+IDX){
        for (j=1;j<=NY;j=j+IDY){
   	  
          /* calculate and save y, s at iteration step iter */
          fread(&gradplastiter,sizeof(float),1,FP6);
          y_LBFGS[h] = waveconv_rho[j][i]-gradplastiter;

	  fread(&modellastiter,sizeof(float),1,FP7);
          s_LBFGS[h] = prho[j][i]-modellastiter;
          
          h++;
 
       }
     }
     
     fclose(FP6);
     fclose(FP7);
   
   /* load old models and gradients - Vs and store them in the LBFGS vectors */
   /* ----------------------------------------------------------------------- */
   sprintf(jac,"%s_p_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP6=fopen(jac,"rb");

   sprintf(jac1,"%s_p_vs.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP7=fopen(jac1,"rb");
   
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	  
          /* calculate and save y, s at iteration step iter */
          fread(&gradplastiter,sizeof(float),1,FP6);
          y_LBFGS[h] = waveconv_u[j][i]-gradplastiter;

    	  fread(&modellastiter,sizeof(float),1,FP7);
          s_LBFGS[h] = pu[j][i]-modellastiter;  
          
          h++;
          
       }
     }
     
     fclose(FP6);
     fclose(FP7);

   /* load old models and gradients - Vp and store them in the LBFGS vectors */
   /* ----------------------------------------------------------------------- */
   sprintf(jac,"%s_p.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP6=fopen(jac,"rb");

   sprintf(jac1,"%s_p_vp.old.%i%i",JACOBIAN,POS[1],POS[2]);
   FP7=fopen(jac1,"rb");
   
     for (i=1;i<=NX;i=i+IDX){
       for (j=1;j<=NY;j=j+IDY){
   	  
          /* calculate and save y, s at iteration step iter */
          fread(&gradplastiter,sizeof(float),1,FP6);
          y_LBFGS[h] = waveconv[j][i]-gradplastiter;

    	  fread(&modellastiter,sizeof(float),1,FP7);
          s_LBFGS[h] = ppi[j][i]-modellastiter;  
          
          h++;
          
       }
     }
     
     fclose(FP6);
     fclose(FP7);
     
     /* calculate improved first guess Hessian gamma_LBFGS */
     h1 = NLBFGS_vec*(LBFGS_pointer-1) + 1;
     h2 = NLBFGS_vec*LBFGS_pointer; 
     
     sum_nom = dotp(y_LBFGS,s_LBFGS,h1,h2,0);
     sum_denom = dotp(y_LBFGS,y_LBFGS,h1,h2,0);
     gamma_LBFGS = sum_nom/sum_denom;
     
     /*printf("gamma_LBFGS = %e \n",gamma_LBFGS);*/
         
     /* update variable rho for all LBFGS-iterations and all parameter classes*/
     for(k=1;k<=NLBFGS;k++){
          
        h1 = NLBFGS_vec*(k-1) + 1;
        h2 = NLBFGS_vec*k;
        sum_nom = dotp(y_LBFGS,s_LBFGS,h1,h2,0); 
	
	if(fabs(sum_nom)>0.0){
	  rho_LBFGS[k] = 1.0/sum_nom;
	}
	else{
	  rho_LBFGS[k] = 0.0;
	} 
	  
	if(MYID==0){                                                
	printf("rho_LBFGS = %e of k = %d \n",rho_LBFGS[k],k);}
	                                                       
     }
     
     /* save q_LBFGS for all material parameters */    
     h=1;
 
     for (i=1;i<=NX;i=i+IDX){
         for (j=1;j<=NY;j=j+IDY){
                             
	     q_LBFGS[h] = waveconv_rho[j][i];
	     h++;
                                                                 
         }
     }                                                                     
                                                                                   
     for (i=1;i<=NX;i=i+IDX){
         for (j=1;j<=NY;j=j+IDY){
          
	     q_LBFGS[h] = waveconv_u[j][i];
	     h++;	   
	      
         }
     }

     for (i=1;i<=NX;i=i+IDX){
         for (j=1;j<=NY;j=j+IDY){
          
	     q_LBFGS[h] = waveconv[j][i];
	     h++;	   
	      
         }
     }

     /* update alpha_LBFGS and q_LBFGS */
     for(k=NLBFGS;k>=1;k--){
		
       h1 = NLBFGS_vec*(k-1) + 1;
       h2 = NLBFGS_vec*k;
       sum_nom = dotp(s_LBFGS,q_LBFGS,h1,h2,1);
       alpha_LBFGS[k] = rho_LBFGS[k] * sum_nom;
       
       /* update q for all material parameters */
       h = NLBFGS_vec*(k-1) + 1;
       for (i=1;i<=NLBFGS_vec;i++){
           q_LBFGS[i] = q_LBFGS[i] - alpha_LBFGS[k] * y_LBFGS[h];
           h++;
       }
     }
	 
       /* Multiply gradient with approximated Hessian */
       for (i=1;i<=NLBFGS_vec;i++){
           r_LBFGS[i] = gamma_LBFGS * q_LBFGS[i];
       }

     /* calculate H^-1 * waveconv[j][i] */
     for(k=1;k<=NLBFGS;k++){
        
        h1 = NLBFGS_vec*(k-1) + 1;
        h2 = NLBFGS_vec*k;
        /* calculate beta_LBFGS*/   
        sum_nom = dotp(y_LBFGS,r_LBFGS,h1,h2,1);
        beta_LBFGS_1 = rho_LBFGS[k] * sum_nom;

        h = NLBFGS_vec*(k-1) + 1;
        for (i=1;i<=NLBFGS_vec;i++){
	   r_LBFGS[i] = r_LBFGS[i] + s_LBFGS[h]*(alpha_LBFGS[k]-beta_LBFGS_1);
	   h++;
        }
         
     }

     /* update gradients */
     h=1;
     
     /* density */
     for (i=1;i<=NX;i=i+IDX){   
        for (j=1;j<=NY;j=j+IDY){
                                 
	    waveconv_rho[j][i] = r_LBFGS[h];
	    h++;  
                                                                  
	}
     }
                                                                               
     /* Vs */
     for (i=1;i<=NX;i=i+IDX){
        for (j=1;j<=NY;j=j+IDY){
               
            waveconv_u[j][i] = r_LBFGS[h];
	    h++;
		  
        }
     }

     /* Vp */
     for (i=1;i<=NX;i=i+IDX){
        for (j=1;j<=NY;j=j+IDY){
               
            waveconv[j][i] = r_LBFGS[h];
	    h++;
		  
        }
     }


     /* Denormalize Gradients */
     for (i=1;i<=NX;i=i+IDX){
        for (j=1;j<=NY;j=j+IDY){
            
           waveconv[j][i] = waveconv[j][i] * C_vp;
	   waveconv_u[j][i] = waveconv_u[j][i] * C_vs;
	   waveconv_rho[j][i] = waveconv_rho[j][i] * C_rho;

        }
     }

}

/* save old models Vs */
/* ------------------ */

    /* save old model */
	sprintf(jac,"%s_p_vp.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
           for (j=1;j<=NY;j=j+IDY){
               fwrite(&ppi[j][i],sizeof(float),1,FP3);
           }
        }
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge model file */ 
	sprintf(jac,"%s_p_vp.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);

	/* save old gradient */
	sprintf(jac,"%s_p.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
            for (j=1;j<=NY;j=j+IDY){
                	fwrite(&gradp[j][i],sizeof(float),1,FP3);
            }
        }
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);
	
	/* save H^-1 * g */
        sprintf(jac,"%s_c.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");
	
	for (i=1;i<=NX;i=i+IDX){   
           for (j=1;j<=NY;j=j+IDY){
                 fwrite(&waveconv[j][i],sizeof(float),1,FP3);
	   }
        }
        
	fclose(FP3);
        MPI_Barrier(MPI_COMM_WORLD);
        
        /* merge gradient file */ 
	sprintf(jac,"%s_c.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);
	

/* save old models Vs */
/* ------------------ */

    /* save old model */
	sprintf(jac,"%s_p_vs.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
           for (j=1;j<=NY;j=j+IDY){
               fwrite(&pu[j][i],sizeof(float),1,FP3);
           }
        }
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge model file */ 
	sprintf(jac,"%s_p_vs.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);

	/* save old gradient */
	sprintf(jac,"%s_p_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
            for (j=1;j<=NY;j=j+IDY){
                	fwrite(&gradp_u[j][i],sizeof(float),1,FP3);
            }
        }
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_u.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);
	
	/* save H^-1 * g */
        sprintf(jac,"%s_c_u.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");
	
	for (i=1;i<=NX;i=i+IDX){   
           for (j=1;j<=NY;j=j+IDY){
                 fwrite(&waveconv_u[j][i],sizeof(float),1,FP3);
	   }
        }
        
	fclose(FP3);
        MPI_Barrier(MPI_COMM_WORLD);
        
        /* merge gradient file */ 
	sprintf(jac,"%s_c_u.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);


/* save old models Rho */
/* ------------------ */

	sprintf(jac,"%s_p_mrho.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
           for (j=1;j<=NY;j=j+IDY){
               fwrite(&prho[j][i],sizeof(float),1,FP3);
           }
        }
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge model file */ 
	sprintf(jac,"%s_p_mrho.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);

	/* save old gradient */
	sprintf(jac,"%s_p_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");

        for (i=1;i<=NX;i=i+IDX){
            for (j=1;j<=NY;j=j+IDY){
                	fwrite(&gradp_rho[j][i],sizeof(float),1,FP3);
            }
        }
	
	fclose(FP3);

	MPI_Barrier(MPI_COMM_WORLD);
          
	/* merge gradient file */ 
	sprintf(jac,"%s_p_rho.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);
	
	/* save H^-1 * g_rho */
        sprintf(jac,"%s_c_rho.old.%i%i",JACOBIAN,POS[1],POS[2]);
	FP3=fopen(jac,"wb");
	
	for (i=1;i<=NX;i=i+IDX){   
           for (j=1;j<=NY;j=j+IDY){
                 fwrite(&waveconv_rho[j][i],sizeof(float),1,FP3);
	   }
        }
        
	fclose(FP3);
        MPI_Barrier(MPI_COMM_WORLD);
        
        /* merge gradient file */ 
	sprintf(jac,"%s_c_rho.old",JACOBIAN);
	if (MYID==0) mergemod(jac,3);
	
}