From 89eaee659fe189b752b1ca0afaf207ac3bb4bd4c Mon Sep 17 00:00:00 2001 From: daniel-koehn <dkoehn@geophysik.uni-kiel.de> Date: Thu, 16 Feb 2017 02:32:14 +0100 Subject: [PATCH] Added elastic TTI PSV RTM module --- include/fd.h | 7 + src/Makefile | 2 + src/TTI/RTM_TTI.c | 570 +++++++++++++++++++++++++++++++++++++++++ src/TTI/grad_obj_TTI.c | 327 +++++++++++++++++++++++ src/TTI/physics_TTI.c | 10 +- 5 files changed, 911 insertions(+), 5 deletions(-) create mode 100644 src/TTI/RTM_TTI.c create mode 100644 src/TTI/grad_obj_TTI.c diff --git a/include/fd.h b/include/fd.h index 0a932fb..5c39e49 100644 --- a/include/fd.h +++ b/include/fd.h @@ -306,6 +306,11 @@ void checkfd_ssg_TTI(FILE *fp, float ** prho, float ** c11, float ** c13, float void FD_TTI(); +float grad_obj_TTI(struct wavePSV *wavePSV, struct wavePSV_PML *wavePSV_PML, struct matTTI *matTTI, struct fwiPSV *fwiPSV, struct mpiPSV *mpiPSV, + struct seisPSV *seisPSV, struct seisPSVfwi *seisPSVfwi, struct acq *acq, float *hc, int iter, int nsrc, int ns, int ntr, int ntr_glob, int nsrc_glob, + int nsrc_loc, int ntr_loc, int nstage, float **We, float **Ws, float **Wr, float ** taper_coeff, int hin, int *DTINV_help, + MPI_Request * req_send, MPI_Request * req_rec); + void model_elastic_TTI(float ** rho, float ** c11, float ** c13, float ** c33, float ** c44, float ** theta); void physics_TTI(); @@ -314,6 +319,8 @@ void readmod_elastic_TTI(float ** rho, float ** c11, float ** c13, float ** void rot_el_tensor_TTI(struct matTTI *matTTI); +void RTM_TTI(); + void update_s_elastic_PML_TTI(int nx1, int nx2, int ny1, int ny2, float ** vx, float ** vy, float ** ux, float ** uy, float ** uxy, float ** uyx, float ** sxx, float ** syy, float ** sxy, float ** d11, float ** d13, float ** d15, float ** d15h, float ** d33, float ** d35, float ** d35h, float ** d55h, diff --git a/src/Makefile b/src/Makefile index 7392a88..34ebbc0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -133,10 +133,12 @@ DENISE += alloc_matVTI.c \ DENISE += alloc_matTTI.c \ checkfd_ssg_TTI.c \ FD_TTI.c \ + grad_obj_TTI.c \ $(MODEL_TTI) \ physics_TTI.c \ readmod_elastic_TTI.c \ rot_el_tensor_TTI.c \ + RTM_TTI.c \ update_s_elastic_PML_TTI.c \ TTI.c diff --git a/src/TTI/RTM_TTI.c b/src/TTI/RTM_TTI.c new file mode 100644 index 0000000..b2a5aa9 --- /dev/null +++ b/src/TTI/RTM_TTI.c @@ -0,0 +1,570 @@ +/* + * Elastic Reverse Time Migration RTM (2D PSV TTI problem) + * + * Daniel Koehn + * Kiel, 16/02/2017 + */ + +#include "fd.h" + +void RTM_TTI(){ + +/* global variables */ +/* ---------------- */ + +/* forward modelling */ +extern int MYID, FDORDER, NX, NY, NT, L, READMOD, QUELLART, RUN_MULTIPLE_SHOTS, TIME_FILT, READREC; +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, RTM_SHOT; +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; + +/* help variable for MIN_ITER */ +int min_iter_help=0; + +/* parameters for gravity inversion */ +char jac_grav[STRING_SIZE]; + +FILE *FP_stage, *FP_GRAV; + +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); + +/* Check if RTM workflow-file is defined (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(" --- "); + } +} + +fclose(FP_stage); + +/* define data structures for PSV problem */ +struct wavePSV; +struct wavePSV_PML; +struct matTTI; +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&&(READREC!=2)){ + + 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)&&(READREC!=2)){ + + /* 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); + +} + +/* 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; + +/* 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 TTI material parameters */ +alloc_matTTI(&matTTI); + +/* allocate memory for PSV FWI parameters */ +alloc_fwiPSV(&fwiPSV); + +/* allocate memory for PSV MPI variables */ +alloc_mpiPSV(&mpiPSV); + +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 (READMOD) readmod_elastic_TTI(matTTI.prho,matTTI.c11,matTTI.c13,matTTI.c33,matTTI.c44,matTTI.theta); +else model_elastic_TTI(matTTI.prho,matTTI.c11,matTTI.c13,matTTI.c33,matTTI.c44,matTTI.theta); + +/* rotate elastic tensor components */ +rot_el_tensor_TTI(&matTTI); + +/* check if the FD run will be stable and free of numerical dispersion */ +/* checkfd_ssg_VTI(FP,matVTI.prho,matVTI.c11,matVTI.c13,matVTI.c33,matVTI.c44,hc); */ + +SHOTINC=1; + +/* For RTM read only first line from FWI workflow file and set iter = 1 */ +stagemax = 1; +iter_true = 1; +iter = 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; + +if (MYID==0) + { + time2=MPI_Wtime(); + fprintf(FP,"\n\n\n ------------------------------------------------------------------\n"); + fprintf(FP,"\n\n\n Elastic Reverse Time Migration RTM \n"); + fprintf(FP,"\n\n\n ------------------------------------------------------------------\n"); + fprintf(FP,"\n\n"); + if(RTM_SHOT==0){fprintf(FP,"Output of RTM image after stacking of shots\n");} + if(RTM_SHOT==1){fprintf(FP,"Output of RTM images for each shot\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. */ + matcopy_elastic_VTI(matTTI.prho,matTTI.c11,matTTI.d15); + matcopy_elastic_VTI(matTTI.prho,matTTI.c11,matTTI.d35); + matcopy_elastic_VTI(matTTI.prho,matTTI.c11,matTTI.d55); + +MPI_Barrier(MPI_COMM_WORLD); + +/* harmonic average of d15, d35, d55 */ +av_harm(matTTI.d15,matTTI.d15h); +av_harm(matTTI.d35,matTTI.d35h); +av_harm(matTTI.d55,matTTI.d55h); + +/* arithmetic average of density */ +av_rho(matTTI.prho,matTTI.prip,matTTI.prjp); + + +/* 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);*/ + +C_vp = 1.0; +C_vs = 1.0; +C_rho = 1.0; + +/* ---------------------------------------------------------------------------------------------------- */ +/* --------- Calculate RTM P- and S- wave image using the adjoint state method ------------------------ */ +/* ---------------------------------------------------------------------------------------------------- */ + +L2sum = grad_obj_TTI(&wavePSV, &wavePSV_PML, &matTTI, &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); + +/* 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); + +/* Output of RTM results */ +if(RTM_SHOT==0){RTM_PSV_out(&fwiPSV);} + +} /* End of RTM-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(matTTI.prho,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.prip,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.prjp,-nd+1,NY+nd,-nd+1,NX+nd); + +free_matrix(matTTI.c11,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.c13,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.c33,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.c44,-nd+1,NY+nd,-nd+1,NX+nd); + +free_matrix(matTTI.d11,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.d13,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.d15,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.d33,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.d35,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.d55,-nd+1,NY+nd,-nd+1,NX+nd); + +free_matrix(matTTI.d15h,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.d35h,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(matTTI.d55h,-nd+1,NY+nd,-nd+1,NX+nd); + +free_matrix(matTTI.theta,-nd+1,NY+nd,-nd+1,NX+nd); + +free_matrix(fwiPSV.prho_old,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(fwiPSV.ppi_old,-nd+1,NY+nd,-nd+1,NX+nd); +free_matrix(fwiPSV.pu_old,-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(L2t,1,4); + free_vector(epst1,1,3); + + if((N_STREAMER==0)||(READREC!=2)){ + + 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); +}*/ + +/* 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); + + +} + + + diff --git a/src/TTI/grad_obj_TTI.c b/src/TTI/grad_obj_TTI.c new file mode 100644 index 0000000..af09deb --- /dev/null +++ b/src/TTI/grad_obj_TTI.c @@ -0,0 +1,327 @@ +/*------------------------------------------------------------------------ + * Calculate gradient and objective function for 2D PSV TTI problem + * + * + * D. Koehn + * Kiel, 16.02.2017 + * ----------------------------------------------------------------------*/ + +#include "fd.h" + + +float grad_obj_TTI(struct wavePSV *wavePSV, struct wavePSV_PML *wavePSV_PML, struct matTTI *matTTI, struct fwiPSV *fwiPSV, struct mpiPSV *mpiPSV, + struct seisPSV *seisPSV, struct seisPSVfwi *seisPSVfwi, struct acq *acq, float *hc, int iter, int nsrc, int ns, int ntr, int ntr_glob, int nsrc_glob, + int nsrc_loc, int ntr_loc, int nstage, float **We, float **Ws, float **Wr, float ** taper_coeff, int hin, int *DTINV_help, + MPI_Request * req_send, MPI_Request * req_rec){ + + /* global variables */ + extern int MYID, TIME_FILT, IDX, IDY, NX, NY, NT, RUN_MULTIPLE_SHOTS, INV_STF, QUELLART; + extern int TESTSHOT_START, TESTSHOT_END, TESTSHOT_INCR, SEISMO, EPRECOND, LNORM, READREC; + extern int N_STREAMER, SWS_TAPER_CIRCULAR_PER_SHOT, QUELLTYPB, QUELLTYP, LOG; + extern int ORDER_SPIKE, ORDER, SHOTINC, RTM_SHOT; + extern float EPSILON, FC, FC_START, FC_SPIKE_1, FC_SPIKE_2; + extern float C_vp, C_vs, C_rho; + extern char MFILE[STRING_SIZE]; + + /* local variables */ + int i, j, nshots, ishot, nt, lsnap, itestshot, swstestshot; + float L2sum, L2_all_shots, energy_all_shots, energy_tmp, L2_tmp; + char source_signal_file[STRING_SIZE]; + + FILE *FP; + + if ((MYID==0) && (LOG==1)) FP=stdout; + + /* initialization of L2 calculation */ + (*seisPSVfwi).L2=0.0; + (*seisPSVfwi).energy=0.0; + L2_all_shots=0.0; + energy_all_shots=0.0; + + EPSILON=0.0; /* test step length */ + + /* set gradient and preconditioning matrices 0 before next iteration*/ + init_grad((*fwiPSV).waveconv); + init_grad((*fwiPSV).waveconv_rho); + init_grad((*fwiPSV).waveconv_u); + + itestshot=TESTSHOT_START; + swstestshot=0; + SHOTINC=1; + + if (RUN_MULTIPLE_SHOTS) nshots=nsrc; else nshots=1; + + for (ishot=1;ishot<=nshots;ishot+=SHOTINC){ + /*for (ishot=1;ishot<=1;ishot+=1){*/ + + /*initialize gradient matrices for each shot with zeros*/ + init_grad((*fwiPSV).waveconv_shot); + init_grad((*fwiPSV).waveconv_u_shot); + init_grad((*fwiPSV).waveconv_rho_shot); + + if((EPRECOND==1)||(EPRECOND==3)){ + init_grad(Ws); + init_grad(Wr); + init_grad(We); + } + + if((N_STREAMER>0)||(READREC==2)){ + + 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; + } + + /* Memory for seismic data */ + alloc_seisPSV(ntr,ns,seisPSV); + + /* Memory for full data seismograms */ + alloc_seisPSVfull(seisPSV,ntr_glob); + + /* Memory for FWI seismic data */ + alloc_seisPSVfwi(ntr,ntr_glob,ns,seisPSVfwi); + + } + + for (nt=1;nt<=8;nt++) (*acq).srcpos1[nt][1]=(*acq).srcpos[nt][ishot]; + + /* set QUELLTYP for each shot */ + QUELLTYP = (*acq).srcpos[8][ishot]; + + if (RUN_MULTIPLE_SHOTS){ + + /* find this single source positions on subdomains */ + if (nsrc_loc>0) free_matrix((*acq).srcpos_loc,1,8,1,1); + (*acq).srcpos_loc=splitsrc((*acq).srcpos1,&nsrc_loc, 1); + } + + + else{ + /* Distribute multiple source positions on subdomains */ + (*acq).srcpos_loc = splitsrc((*acq).srcpos,&nsrc_loc, nsrc); + } + + MPI_Barrier(MPI_COMM_WORLD); + + /*================================================================================== + Estimate source time function by Wiener deconvolution + ==================================================================================*/ + + /*if((INV_STF)&&(iter==1)){ + stf_psv(wavePSV,wavePSV_PML,matPSV,fwiPSV,mpiPSV,seisPSV,seisPSVfwi,acq,hc,ishot,nshots,nsrc_loc,nsrc,ns,ntr,ntr_glob,iter,Ws,Wr,hin,DTINV_help,req_send,req_rec); + }*/ + + /*================================================================================== + Starting simulation (forward model) + ==================================================================================*/ + + /* calculate wavelet for each source point */ + (*acq).signals=NULL; + (*acq).signals=wavelet((*acq).srcpos_loc,nsrc_loc,ishot); + + if (nsrc_loc){if(QUELLART==6){ + + /* time domain filtering of the source signal */ + apply_tdfilt((*acq).signals,nsrc_loc,ns,ORDER_SPIKE,FC_SPIKE_2,FC_SPIKE_1); + + } + } + + /* time domain filtering*/ + if ((TIME_FILT)&&(INV_STF==0)){ + + /* time domain filtering of the source signal */ + apply_tdfilt((*acq).signals,nsrc_loc,ns,ORDER,FC,FC_START); + + } + + /*printf("MYID=%d, nsrc_loc = %d \n",MYID,nsrc_loc);*/ + + /*char source_signal_file[STRING_SIZE]; + sprintf(source_signal_file,"source_signal.%d.su.shot%d.it%d",MYID,ishot,iter); + fprintf(stdout,"\n PE %d outputs source time function in SU format to %s \n ", MYID, source_signal_file); + output_source_signal(fopen(source_signal_file,"w"),signals,NT,3);*/ + + /* output source signal e.g. for cross-correlation of comparison with analytical solutions */ + if(RUN_MULTIPLE_SHOTS){ + + if(nsrc_loc>0){ + sprintf(source_signal_file,"%s_source_signal.%d.su.shot%d", MFILE, MYID,ishot); + fprintf(stdout,"\n PE %d outputs source time function in SU format to %s \n ", MYID, source_signal_file); + output_source_signal(fopen(source_signal_file,"w"),(*acq).signals,NT,1); + } + + MPI_Barrier(MPI_COMM_WORLD); + } + + /* solve forward problem */ + TTI(wavePSV,wavePSV_PML,matTTI,fwiPSV,mpiPSV,seisPSV,seisPSVfwi,acq,hc,ishot,nshots,nsrc_loc,ns,ntr,Ws,Wr,hin,DTINV_help,0,req_send,req_rec); + + + /* =============================================== + Calculate objective function and data residuals + =============================================== */ + + if((ishot==itestshot)&&(ishot<=TESTSHOT_END)){swstestshot=1;} + + if (ntr > 0){ + calc_res_PSV(seisPSV,seisPSVfwi,(*acq).recswitch,(*acq).recpos,(*acq).recpos_loc,ntr_glob,ntr,nsrc_glob,(*acq).srcpos,ishot,ns,iter,swstestshot); + } + + if((ishot==itestshot)&&(ishot<=TESTSHOT_END)){ + swstestshot=0; + itestshot+=TESTSHOT_INCR; + } + + /* output of time reversed residual seismograms */ + if ((SEISMO)&&(iter==1)&&(ishot==1)){ + outseis_PSVres(seisPSV,seisPSVfwi,(*acq).recswitch,(*acq).recpos,(*acq).recpos_loc,ntr_glob,(*acq).srcpos,ishot,ns,nstage,FP); + } + + /*================================================================================ + Starting simulation (backward model) + ==================================================================================*/ + + /* Distribute multiple source positions on subdomains */ + /* define source positions at the receivers */ + (*acq).srcpos_loc_back = matrix(1,6,1,ntr); + for (i=1;i<=ntr;i++){ + (*acq).srcpos_loc_back[1][i] = ((*acq).recpos_loc[1][i]); + (*acq).srcpos_loc_back[2][i] = ((*acq).recpos_loc[2][i]); + } + + /* backpropagate time-reversed data */ + TTI(wavePSV,wavePSV_PML,matTTI,fwiPSV,mpiPSV,seisPSV,seisPSVfwi,acq,hc,ishot,nshots,ntr,ns,ntr,Ws,Wr,hin,DTINV_help,1,req_send,req_rec); + + /* assemble PSV VTI gradients for each shot */ + /*ass_gradVTI(fwiPSV,matVTI,iter);*/ + + if((EPRECOND==1)||(EPRECOND==3)){ + /* calculate energy weights */ + eprecond1(We,Ws,Wr); + + /* scale gradient with energy weights*/ + for(i=1;i<=NX;i=i+IDX){ + for(j=1;j<=NY;j=j+IDY){ + + (*fwiPSV).waveconv_shot[j][i] = (*fwiPSV).waveconv_shot[j][i]/(We[j][i]*C_vp*C_vp); + (*fwiPSV).waveconv_u_shot[j][i] = (*fwiPSV).waveconv_u_shot[j][i]/(We[j][i]*C_vs*C_vs); + if(C_vs==0.0){(*fwiPSV).waveconv_u_shot[j][i] = 0.0;} + (*fwiPSV).waveconv_rho_shot[j][i] = (*fwiPSV).waveconv_rho_shot[j][i]/(We[j][i]*C_rho*C_rho); + + } + } + } + + if (SWS_TAPER_CIRCULAR_PER_SHOT){ /* applying a circular taper at the source position to the gradient of each shot */ + + /* applying the preconditioning */ + taper_grad_shot((*fwiPSV).waveconv_shot,taper_coeff,(*acq).srcpos,nsrc,(*acq).recpos,ntr_glob,ishot); + taper_grad_shot((*fwiPSV).waveconv_rho_shot,taper_coeff,(*acq).srcpos,nsrc,(*acq).recpos,ntr_glob,ishot); + taper_grad_shot((*fwiPSV).waveconv_u_shot,taper_coeff,(*acq).srcpos,nsrc,(*acq).recpos,ntr_glob,ishot); + + } /* end of SWS_TAPER_CIRCULAR_PER_SHOT == 1 */ + + for(i=1;i<=NX;i=i+IDX){ + for(j=1;j<=NY;j=j+IDY){ + (*fwiPSV).waveconv[j][i] += (*fwiPSV).waveconv_shot[j][i]; + (*fwiPSV).waveconv_rho[j][i] += (*fwiPSV).waveconv_rho_shot[j][i]; + (*fwiPSV).waveconv_u[j][i] += (*fwiPSV).waveconv_u_shot[j][i]; + } + } + + if(RTM_SHOT==1){RTM_PSV_out_shot(fwiPSV,ishot);} + + if((N_STREAMER>0)||(READREC==2)){ + + 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); + } + + ntr=0; + ntr_glob=0; + + } + + nsrc_loc=0; + + } /* end of loop over shots (forward and backpropagation) */ + + /* calculate L2 norm of all CPUs*/ + L2sum = 0.0; + L2_tmp = (*seisPSVfwi).L2; + MPI_Allreduce(&L2_tmp,&L2sum,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD); + + /* calculate L2 norm of all CPUs*/ + energy_all_shots = 0.0; + energy_tmp = (*seisPSVfwi).energy; + MPI_Allreduce(&energy_tmp,&energy_all_shots,1,MPI_FLOAT,MPI_SUM,MPI_COMM_WORLD); + + /*if(MYID==0){ + printf("L2sum: %e\n", L2sum); + printf("energy_sum: %e\n\n", energy_all_shots); + + }*/ + + if(LNORM==2){ + L2sum = L2sum/energy_all_shots; + } + else{L2sum=L2sum;} + +return L2sum; + +} + diff --git a/src/TTI/physics_TTI.c b/src/TTI/physics_TTI.c index 18dbf32..e1ca43f 100644 --- a/src/TTI/physics_TTI.c +++ b/src/TTI/physics_TTI.c @@ -12,7 +12,7 @@ void physics_TTI(){ /* global variables */ extern int MODE; - /* 2D TTI Forward Problem */ + /* 2D PSV TTI Forward Problem */ if(MODE==0){ FD_TTI(); } @@ -22,10 +22,10 @@ void physics_TTI(){ FWI_PSV(); }*/ - /* 2D PSV Reverse Time Migration */ - /*if(MODE==2){ - RTM_PSV(); - }*/ + /* 2D PSV TTI Reverse Time Migration */ + if(MODE==2){ + RTM_TTI(); + } }