Пример #1
0
void forward_modeling_a(sf_file Fdat, sf_mpi *mpipar, sf_sou soupar, sf_acqui acpar, sf_vec array, bool verb)
/*< acoustic forward modeling >*/
{
	int ix, iz, is, ir, it;
	int sx, rx, sz, rz, rectx, rectz;
	int nz, nx, padnz, padnx, padnzx, nt, nr, nb;

	float dx2, dz2, dt2, dt;
	float **vv, **dd;
	float **p0, **p1, **p2, **term, **tmparray, *rr;

	FILE *swap;

	MPI_Comm comm=MPI_COMM_WORLD;

	swap=fopen("temswap.bin", "wb+");

	padnz=acpar->padnz;
	padnx=acpar->padnx;
	padnzx=padnz*padnx;
	nz=acpar->nz;
	nx=acpar->nx;
	nt=acpar->nt;
	nr=acpar->nr;
	nb=acpar->nb;
	sz=acpar->sz;
	rz=acpar->rz;
	rectx=soupar->rectx;
	rectz=soupar->rectz;

	dx2=acpar->dx*acpar->dx;
	dz2=acpar->dz*acpar->dz;
	dt2=acpar->dt*acpar->dt;
	dt=acpar->dt;

	vv = sf_floatalloc2(padnz, padnx);
	dd=sf_floatalloc2(nt, nr);

	p0=sf_floatalloc2(padnz, padnx);
	p1=sf_floatalloc2(padnz, padnx);
	p2=sf_floatalloc2(padnz, padnx);
	term=sf_floatalloc2(padnz, padnx);
	rr=sf_floatalloc(padnzx);

	/* padding and convert vector to 2-d array */
	pad2d(array->vv, vv, nz, nx, nb);

	for(is=mpipar->cpuid; is<acpar->ns; is+=mpipar->numprocs){
		sf_warning("###### is=%d ######", is+1);

		memset(dd[0], 0., nr*nt*sizeof(float));
		memset(p0[0], 0., padnzx*sizeof(float));
		memset(p1[0], 0., padnzx*sizeof(float));
		memset(p2[0], 0., padnzx*sizeof(float));
		
		sx=acpar->s0_v+is*acpar->ds_v;
		source_map(sx, sz, rectx, rectz, padnx, padnz, padnzx, rr);

		for(it=0; it<nt; it++){
			if(verb) sf_warning("Modeling is=%d; it=%d;", is+1, it);

			/* output data */
			for(ir=0; ir<acpar->nr2[is]; ir++){
				rx=acpar->r0_v[is]+ir*acpar->dr_v;
				dd[acpar->r02[is]+ir][it]=p1[rx][rz];
			}

			/* laplacian operator */
			laplace(p1, term, padnx, padnz, dx2, dz2);
			
			/* load source */
			for(ix=0; ix<padnx; ix++){
				for(iz=0; iz<padnz; iz++){
					term[ix][iz] += rr[ix*padnz+iz]*array->ww[it];
				}
			}

			/* update */
			for(ix=0; ix<padnx; ix++){
				for(iz=0; iz<padnz; iz++){
					p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
				}
			}
			
			/* swap wavefield pointer of different time steps */
			tmparray=p0; p0=p1; p1=p2; p2=tmparray;

			/* boundary condition */
			apply_sponge(p0, acpar->bc, padnx, padnz, nb);
			apply_sponge(p1, acpar->bc, padnx, padnz, nb);
		} // end of time loop

		fseeko(swap, is*nr*nt*sizeof(float), SEEK_SET);
		fwrite(dd[0], sizeof(float), nr*nt, swap);
	}// end of shot loop
	fclose(swap);
	MPI_Barrier(comm);

	/* transfer data to Fdat */
	if(mpipar->cpuid==0){
		swap=fopen("temswap.bin", "rb");
		for(is=0; is<acpar->ns; is++){
			fseeko(swap, is*nr*nt*sizeof(float), SEEK_SET);
			fread(dd[0], sizeof(float), nr*nt, swap);
			sf_floatwrite(dd[0], nr*nt, Fdat);
		}
		fclose(swap);
		remove("temswap.bin");
	}
	MPI_Barrier(comm);
	
	/* release allocated memory */
	free(*p0); free(p0); free(*p1); free(p1);
	free(*p2); free(p2); free(*vv); free(vv);
	free(*dd); free(dd);
	free(rr); free(*term); free(term);
}
Пример #2
0
void gradient_standard(float *x, float *fcost, float *grad)
/*< standard velocity gradient >*/
{
	int ix, iz, is, ir, it, wit, iturn;
	int sx, rx;

	float temp, dmax;
	float **p0, **p1, **p2, **term, **tmparray, *rr, ***wave, **pp;
	float *sendbuf, *recvbuf;

	/* residual file */
	sf_file Fres;
	Fres=sf_output("Fres");
	sf_putint(Fres,"n1",nt);
	sf_putint(Fres,"n2",nr);

	/* initialize fcost */
	*fcost=0.;
	/* update velocity */
	pad2d(x, vv, nz, nx, nb);
	/* initialize gradient */
	memset(grad, 0., nzx*sizeof(float));
	/* initialize data misfit */
	swap=0.;

	/* memory allocation */
	p0=sf_floatalloc2(padnz, padnx);
	p1=sf_floatalloc2(padnz, padnx);
	p2=sf_floatalloc2(padnz, padnx);
	term=sf_floatalloc2(padnz, padnx);
	rr=sf_floatalloc(padnzx);
	wave=sf_floatalloc3(nz, nx, wnt);
	pp=sf_floatalloc2(nt, nr);

	iturn=0;
	for(is=cpuid; is<ns; is+=numprocs){
		if(cpuid==0) sf_warning("###### is=%d ######", is+1);

		memset(p0[0], 0., padnzx*sizeof(float));
		memset(p1[0], 0., padnzx*sizeof(float));
		memset(p2[0], 0., padnzx*sizeof(float));
		memset(pp[0], 0., nr*nt*sizeof(float));
		
		sx=s0_v+is*ds_v;
		source_map(sx, sz, frectx, frectz, padnx, padnz, padnzx, rr);

		wit=0;
		/* forward propagation */
		for(it=0; it<nt; it++){
			if(verb) sf_warning("Forward propagation is=%d; it=%d;", is+1, it);

			/* output predicted data */
			for(ir=0; ir<nr2[is]; ir++){
				rx=r0_v[is]+ir*dr_v;
				pp[r02[is]+ir][it]=p1[rx][rz];
			}

			/* save wavefield */
			if(it%interval==0){
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(wave,p1,wit,nb,nx,nz)
#endif
				for(ix=0; ix<nx; ix++)
					for(iz=0; iz<nz; iz++)
						wave[wit][ix][iz]=p1[ix+nb][iz+nb];
				wit++;
			}

			/* laplacian operator */
			laplace(p1, term, padnx, padnz, dx2, dz2);
			
			/* load source */
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(term,rr,padnx,padnz,ww,it)
#endif
			for(ix=0; ix<padnx; ix++){
				for(iz=0; iz<padnz; iz++){
					term[ix][iz] += rr[ix*padnz+iz]*ww[it];
				}
			}

			/* update */
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(p0,p1,p2,vv,term,padnx,padnz,dt2)
#endif
			for(ix=4; ix<padnx-4; ix++){
				for(iz=4; iz<padnz-4; iz++){
					p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
				}
			}
			
			/* swap wavefield pointer of different time steps */
			tmparray=p0; p0=p1; p1=p2; p2=tmparray;

			/* boundary condition */
			apply_sponge(p0, bc, padnx, padnz, nb);
			apply_sponge(p1, bc, padnx, padnz, nb);
		} // end of time loop

		/* check */
		if(wit != wnt) sf_error("Incorrect number of wavefield snapshots");
		wit--;
		
		/* calculate data residual and data misfit */
		for(ir=0; ir<nr; ir++){
			for(it=0; it<nt; it++){
				pp[ir][it]=dd[iturn][ir][it]-pp[ir][it];
				pp[ir][it] *= weight[ir][it];
				swap += 0.5*pp[ir][it]*pp[ir][it];
			}
		}
		smooth_misfit(pp, fcost, nr, nt, drectx, drectz, nrepeat, ider);

		iturn++;

		/* check the data residual */
		if(is==ns/2) sf_floatwrite(pp[0], nr*nt, Fres);
		sf_fileclose(Fres);

		/* initialization */
		memset(p0[0], 0., padnzx*sizeof(float));
		memset(p1[0], 0., padnzx*sizeof(float));
		memset(p2[0], 0., padnzx*sizeof(float));
		memset(term[0], 0., padnzx*sizeof(float));
		
		/* backward propagation */
		for(it=nt-1; it>=0; it--){
			if(verb) sf_warning("Backward propagation is=%d; it=%d;", is+1, it);
			
			/* laplacian operator */
			laplace(p1, term, padnx, padnz, dx2, dz2);
			
			/* load data residual */
			for(ir=0; ir<nr2[is]; ir++){
				rx=r0_v[is]+ir*dr_v;
				term[rx][rz] += pp[r02[is]+ir][it];
			}

			/* update */
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(p0,p1,p2,vv,term,padnx,padnz,dt2)
#endif
			for(ix=4; ix<padnx-4; ix++){
				for(iz=4; iz<padnz-4; iz++){
					p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
				}
			}
			
			/* calculate gradient  */
			if(it%interval==0){
				if(wit != wnt-1 && wit != 0){ // avoid the first and last time step
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz,temp) \
			shared(nx,nz,vv,wave,p1,wit,wdt2,grad)
#endif
					for(ix=0; ix<nx; ix++){
						for(iz=0; iz<nz; iz++){
							temp=vv[ix+nb][iz+nb];
							temp=temp*temp*temp;
							temp=-2./temp;
							grad[ix*nz+iz] += (wave[wit+1][ix][iz]-2.*wave[wit][ix][iz]+wave[wit-1][ix][iz])/wdt2*p1[ix+nb][iz+nb]*temp;
						}
					}
				}
				wit--;
			}
			
			/* swap wavefield pointer of different time steps */
			tmparray=p0; p0=p1; p1=p2; p2=tmparray;

			/* boundary condition */
			apply_sponge(p0, bc, padnx, padnz, nb);
			apply_sponge(p1, bc, padnx, padnz, nb);
		} // end of time loop
	}// end of shot loop
	MPI_Barrier(comm);
	
	/* misfit reduction */
	//MPI_ALLreduce(sendbuf, recvbuf, 1, MPI_FLOAT, MPI_SUM, comm);
	
	if(cpuid==0){
		sendbuf=MPI_IN_PLACE;
		recvbuf=fcost;
	}else{
		sendbuf=fcost;
		recvbuf=NULL;
	}
	MPI_Reduce(sendbuf, recvbuf, 1, MPI_FLOAT, MPI_SUM, 0, comm);
	MPI_Bcast(fcost, 1, MPI_FLOAT, 0, comm);
	
	if(cpuid==0){
		sendbuf=MPI_IN_PLACE;
		recvbuf=&swap;
	}else{
		sendbuf=&swap;
		recvbuf=NULL;
	}
	MPI_Reduce(sendbuf, recvbuf, 1, MPI_FLOAT, MPI_SUM, 0, comm);
	MPI_Bcast(&swap, 1, MPI_FLOAT, 0, comm);

	/* gradient reduction */
	//MPI_ALLreduce(sendbuf, recvbuf, nzx, MPI_FLOAT, MPI_SUM, comm);
	if(cpuid==0){
		sendbuf=MPI_IN_PLACE;
		recvbuf=grad;
	}else{
		sendbuf=grad;
		recvbuf=NULL;
	}
	MPI_Reduce(sendbuf, recvbuf, nzx, MPI_FLOAT, MPI_SUM, 0, comm);
	MPI_Bcast(grad, nzx, MPI_FLOAT, 0, comm);

	/* scaling gradient */
	if(first){
		dmax=0.;
		for(ix=0; ix<nzx; ix++)
			if(fabsf(grad[ix])>dmax)
				dmax=fabsf(grad[ix]);
		scaling=0.1/dmax;
		first=false;
	}

	/* smooth gradient */
	gradient_smooth2(grectx, grectz, nx, nz, waterz, scaling, grad);

	/* free allocated memory */
	free(*p0); free(p0); free(*p1); free(p1);
	free(*p2); free(p2); free(*pp); free(pp);
	free(**wave); free(*wave); free(wave);
	free(rr); free(*term); free(term);
}
Пример #3
0
void rtm(sf_file Fdat, sf_file Fimg, sf_mpi *mpipar, sf_sou soupar, sf_acqui acpar, sf_vec_s array, bool verb)
/*< acoustic rtm >*/
{
	int ix, iz, is, ir, it, wit;
	int sx, rx, sz, rz, frectx, frectz;
	int nz, nx, nzx, padnz, padnx, padnzx, nt, nr, nb, wnt;

	float dx2, dz2, dt2, dt;
	float **vv, **dd, **mm;
	float **p0, **p1, **p2, **term, **tmparray, *rr, ***wave;
	float *sendbuf, *recvbuf;

	//sf_file Fwfl1, Fwfl2;
	//Fwfl1=sf_output("Fwfl1");
	//Fwfl2=sf_output("Fwfl2");

	MPI_Comm comm=MPI_COMM_WORLD;

	nz=acpar->nz;
	nx=acpar->nx;
	nzx=nz*nx;
	padnz=acpar->padnz;
	padnx=acpar->padnx;
	padnzx=padnz*padnx;
	nr=acpar->nr;
	nb=acpar->nb;
	sz=acpar->sz;
	rz=acpar->rz;
	frectx=soupar->frectx;
	frectz=soupar->frectz;

	nt=acpar->nt;
	wnt=(nt-1)/acpar->interval+1;

	dx2=acpar->dx*acpar->dx;
	dz2=acpar->dz*acpar->dz;
	dt2=acpar->dt*acpar->dt;
	dt=acpar->dt;

	//sf_putint(Fwfl1, "n1", padnz);
	//sf_putint(Fwfl1, "n2",padnx);
	//sf_putint(Fwfl1, "n3",(nt-1)/50+1);
	//sf_putint(Fwfl2, "n1", padnz);
	//sf_putint(Fwfl2, "n2",padnx);
	//sf_putint(Fwfl2, "n3",(nt-1)/50+1);

	/* memory allocation */
	vv = sf_floatalloc2(padnz, padnx);
	dd=sf_floatalloc2(nt, nr);
	mm=sf_floatalloc2(nz, nx);

	p0=sf_floatalloc2(padnz, padnx);
	p1=sf_floatalloc2(padnz, padnx);
	p2=sf_floatalloc2(padnz, padnx);
	term=sf_floatalloc2(padnz, padnx);
	rr=sf_floatalloc(padnzx);
	wave=sf_floatalloc3(nz, nx, wnt);

	/* padding and convert vector to 2-d array */
	pad2d(array->vv, vv, nz, nx, nb);

	memset(mm[0], 0., nzx*sizeof(float));

	for(is=mpipar->cpuid; is<acpar->ns; is+=mpipar->numprocs){
		sf_warning("###### is=%d ######", is+1);

		memset(p0[0], 0., padnzx*sizeof(float));
		memset(p1[0], 0., padnzx*sizeof(float));
		memset(p2[0], 0., padnzx*sizeof(float));
		
		sx=acpar->s0_v+is*acpar->ds_v;
		source_map(sx, sz, frectx, frectz, padnx, padnz, padnzx, rr);

		wit=0;
		/* forward propagation */
		for(it=0; it<nt; it++){
			if(verb) sf_warning("Forward propagation is=%d; it=%d;", is+1, it);

			/* save wavefield */
			if(it%acpar->interval==0){
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(wave,p1,wit,nb,nx,nz)
#endif
				for(ix=0; ix<nx; ix++)
					for(iz=0; iz<nz; iz++)
						wave[wit][ix][iz]=p1[ix+nb][iz+nb];
				wit++;
			}

			//if(is==acpar->ns/2 && it%50==0) sf_floatwrite(p1[0],padnzx, Fwfl1);

			/* laplacian operator */
			laplace(p1, term, padnx, padnz, dx2, dz2);
			
			/* load source */
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(term,rr,padnx,padnz,it)
#endif
			for(ix=0; ix<padnx; ix++){
				for(iz=0; iz<padnz; iz++){
					term[ix][iz] += rr[ix*padnz+iz]*array->ww[it];
				}
			}

			/* update */
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(p0,p1,p2,vv,term,padnx,padnz,dt2)
#endif
			for(ix=4; ix<padnx-4; ix++){
				for(iz=4; iz<padnz-4; iz++){
					p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
				}
			}
			
			/* swap wavefield pointer of different time steps */
			tmparray=p0; p0=p1; p1=p2; p2=tmparray;

			/* boundary condition */
			apply_sponge(p0, acpar->bc, padnx, padnz, nb);
			apply_sponge(p1, acpar->bc, padnx, padnz, nb);
		} // end of time loop

		/* check */
		if(wit != wnt) sf_error("Incorrect number of wavefield snapshots");
		wit--;

		/* read data */
		sf_seek(Fdat, is*nr*nt*sizeof(float), SEEK_SET);
		sf_floatread(dd[0], nr*nt, Fdat);

		/* initialization */
		memset(p0[0], 0., padnzx*sizeof(float));
		memset(p1[0], 0., padnzx*sizeof(float));
		memset(p2[0], 0., padnzx*sizeof(float));
		memset(term[0], 0., padnzx*sizeof(float));
		
		/* backward propagation */
		for(it=nt-1; it>=0; it--){
			if(verb) sf_warning("Backward propagation is=%d; it=%d;", is+1, it);

			/* laplacian operator */
			laplace(p1, term, padnx, padnz, dx2, dz2);
			
			/* load data */
			for(ir=0; ir<acpar->nr2[is]; ir++){
				rx=acpar->r0_v[is]+ir*acpar->dr_v;
				term[rx][rz] += dd[acpar->r02[is]+ir][it];
			}

			/* update */
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(p0,p1,p2,vv,term,padnx,padnz,dt2)
#endif
			for(ix=4; ix<padnx-4; ix++){
				for(iz=4; iz<padnz-4; iz++){
					p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
				}
			}

			//if(is==acpar->ns/2 && it%50==0) sf_floatwrite(p1[0],padnzx, Fwfl2);

			/* calculate image */
			if(it%acpar->interval==0){
#ifdef _OPENMP 
#pragma omp parallel for \
			private(ix,iz) \
			shared(p1,wave,nx,nz,wit,mm,nb)
#endif
				for(ix=0; ix<nx; ix++)
					for(iz=0; iz<nz; iz++)
						mm[ix][iz] += wave[wit][ix][iz]*p1[ix+nb][iz+nb];
				wit--;
			}
			
			/* swap wavefield pointer of different time steps */
			tmparray=p0; p0=p1; p1=p2; p2=tmparray;

			/* boundary condition */
			apply_sponge(p0, acpar->bc, padnx, padnz, nb);
			apply_sponge(p1, acpar->bc, padnx, padnz, nb);
		} // end of time loop
	}// end of shot loop
	MPI_Barrier(comm);

	//sf_fileclose(Fwfl1);
	//sf_fileclose(Fwfl2);

	if(mpipar->cpuid==0){
		sendbuf=MPI_IN_PLACE;
		recvbuf=mm[0];
	}else{
		sendbuf=mm[0];
		recvbuf=NULL;
	}
	MPI_Reduce(sendbuf, recvbuf, nzx, MPI_FLOAT, MPI_SUM, 0, comm);

	if(mpipar->cpuid==0) sf_floatwrite(mm[0], nzx, Fimg);
	MPI_Barrier(comm);

	/* release allocated memory */
	free(*p0); free(p0); free(*p1); free(p1);
	free(*p2); free(p2); free(*vv); free(vv);
	free(*dd); free(dd); free(*mm); free(mm);
	free(rr); free(*term); free(term);
	free(**wave); free(*wave); free(wave);
}
Пример #4
0
void rtm_q(sf_file Fdat, sf_file Fimg, sf_mpi *mpipar, sf_sou soupar, sf_acqui acpar, sf_vec_q array, bool verb)
/*< visco-acoustic rtm >*/
{
	int ix, iz, is, ir, it, wit;
	int sx, rx, sz, rz, frectx, frectz;
	int nz, nx, nzx, padnz, padnx, padnzx, nt, nr, nb, wnt;

	float dx2, dz2, dt2, dt;
	float **vv, **tau, **taus, **dd, **mm;
	float **p0, **p1, **p2, **r1, **r2, **term, **tmparray, *rr, ***wave;
	float *sendbuf, *recvbuf;

	MPI_Comm comm=MPI_COMM_WORLD;

	nz=acpar->nz;
	nx=acpar->nx;
	nzx=nz*nx;
	padnz=acpar->padnz;
	padnx=acpar->padnx;
	padnzx=padnz*padnx;
	nr=acpar->nr;
	nb=acpar->nb;
	sz=acpar->sz;
	rz=acpar->rz;
	frectx=soupar->frectx;
	frectz=soupar->frectz;

	nt=acpar->nt;
	wnt=(nt-1)/acpar->interval+1;

	dx2=acpar->dx*acpar->dx;
	dz2=acpar->dz*acpar->dz;
	dt2=acpar->dt*acpar->dt;
	dt=acpar->dt;

	/* memory allocation */
	vv = sf_floatalloc2(padnz, padnx);
	tau= sf_floatalloc2(padnz, padnx);
	taus=sf_floatalloc2(padnz, padnx);
	dd=sf_floatalloc2(nt, nr);
	mm=sf_floatalloc2(nz, nx);

	p0=sf_floatalloc2(padnz, padnx);
	p1=sf_floatalloc2(padnz, padnx);
	p2=sf_floatalloc2(padnz, padnx);
	r1=sf_floatalloc2(padnz, padnx);
	r2=sf_floatalloc2(padnz, padnx);
	term=sf_floatalloc2(padnz, padnx);
	rr=sf_floatalloc(padnzx);
	wave=sf_floatalloc3(nz, nx, wnt);

	/* padding and convert vector to 2-d array */
	pad2d(array->vv, vv, nz, nx, nb);
	pad2d(array->tau, tau, nz, nx, nb);
	pad2d(array->taus, taus, nz, nx, nb);

	memset(mm[0], 0., nzx*sizeof(float));

	for(is=mpipar->cpuid; is<acpar->ns; is+=mpipar->numprocs){
		sf_warning("###### is=%d ######", is+1);

		memset(p0[0], 0., padnzx*sizeof(float));
		memset(p1[0], 0., padnzx*sizeof(float));
		memset(p2[0], 0., padnzx*sizeof(float));
		memset(r1[0], 0., padnzx*sizeof(float));
		memset(r2[0], 0., padnzx*sizeof(float));
		memset(term[0], 0., padnzx*sizeof(float));
		
		sx=acpar->s0_v+is*acpar->ds_v;
		source_map(sx, sz, frectx, frectz, padnx, padnz, padnzx, rr);

		wit=0;
		/* forward propagation */
		for(it=0; it<nt; it++){
			if(verb) sf_warning("Forward propagation is=%d; it=%d;", is+1, it);

			/* save wavefield */
			if(it%acpar->interval==0){
				for(ix=0; ix<nx; ix++)
					for(iz=0; iz<nz; iz++)
						wave[wit][ix][iz]=p1[ix+nb][iz+nb];
				wit++;
			}

			/* load source */
			for(ix=0; ix<padnx; ix++){
				for(iz=0; iz<padnz; iz++){
					p1[ix][iz] += rr[ix*padnz+iz]*array->ww[it];
				}
			}

			/* laplacian operator */
			laplace(p1, term, padnx, padnz, dx2, dz2);
			
			/* update */
			for(ix=4; ix<padnx-4; ix++){
				for(iz=4; iz<padnz-4; iz++){
					r2[ix][iz]=
						(-tau[ix][iz]/taus[ix][iz]*term[ix][iz]
						 + (1./dt-0.5/taus[ix][iz])*r1[ix][iz])
						/(1./dt+0.5/taus[ix][iz]);
					term[ix][iz]=term[ix][iz]*(1.+tau[ix][iz])+(r2[ix][iz]+r1[ix][iz])*0.5;
					p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
				}
			}
			
			/* swap wavefield pointer of different time steps */
			tmparray=p0; p0=p1; p1=p2; p2=tmparray;
			tmparray=r1; r1=r2; r2=tmparray;

			/* boundary condition */
			apply_sponge(p0, acpar->bc, padnx, padnz, nb);
			apply_sponge(p1, acpar->bc, padnx, padnz, nb);
			apply_sponge(r1, acpar->bc, padnx, padnz, nb);
		} // end of time loop

		/* check */
		if(wit != wnt) sf_error("Incorrect number of wavefield snapshots");
		/* read data */
		sf_seek(Fdat, is*nr*nt*sizeof(float), SEEK_SET);
		sf_floatread(dd[0], nr*nt, Fdat);
		/* initialization */
		memset(p0[0], 0., padnzx*sizeof(float));
		memset(p1[0], 0., padnzx*sizeof(float));
		memset(p2[0], 0., padnzx*sizeof(float));
		memset(r1[0], 0., padnzx*sizeof(float));
		memset(r2[0], 0., padnzx*sizeof(float));
		memset(term[0], 0., padnzx*sizeof(float));
		
		/* backward propagation */
		for(it=nt-1; it>=0; it--){
			if(verb) sf_warning("Backward propagation is=%d; it=%d;", is+1, it);

			/* load data */
			for(ir=0; ir<acpar->nr2[is]; ir++){
				rx=acpar->r0_v[is]+ir*acpar->dr_v;
				p1[rx][rz]=dd[acpar->r02[is]+ir][it];
			}

			/* laplacian operator */
			laplace(p1, term, padnx, padnz, dx2, dz2);
			
			/* update */
			for(ix=4; ix<padnx-4; ix++){
				for(iz=4; iz<padnz-4; iz++){
					r2[ix][iz]=
						(-tau[ix][iz]/taus[ix][iz]*term[ix][iz]
						 + (1./dt-0.5/taus[ix][iz])*r1[ix][iz])
						/(1./dt+0.5/taus[ix][iz]);
					term[ix][iz]=term[ix][iz]*(1.+tau[ix][iz])+(r2[ix][iz]+r1[ix][iz])*0.5;
					p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
				}
			}

			/* calculate image */
			if(it%acpar->interval==0){
				for(ix=0; ix<nx; ix++)
					for(iz=0; iz<nz; iz++)
						mm[ix][iz] += wave[wit-1][ix][iz]*p2[ix+nb][iz+nb];
				wit--;
			}
			
			/* swap wavefield pointer of different time steps */
			tmparray=p0; p0=p1; p1=p2; p2=tmparray;
			tmparray=r1; r1=r2; r2=tmparray;

			/* boundary condition */
			apply_sponge(p0, acpar->bc, padnx, padnz, nb);
			apply_sponge(p1, acpar->bc, padnx, padnz, nb);
			apply_sponge(r1, acpar->bc, padnx, padnz, nb);
		} // end of time loop
	}// end of shot loop
	MPI_Barrier(comm);

	if(mpipar->cpuid==0){
		sendbuf=MPI_IN_PLACE;
		recvbuf=mm[0];
	}else{
		sendbuf=mm[0];
		recvbuf=NULL;
	}
	MPI_Reduce(sendbuf, recvbuf, nzx, MPI_FLOAT, MPI_SUM, 0, comm);

	if(mpipar->cpuid==0) sf_floatwrite(mm[0], nzx, Fimg);
	MPI_Barrier(comm);
}
Пример #5
0
void prtm2d_lop(bool adj, bool add, int nm, int nd, float *mod, float *dat)
/*< prtm2d linear operator >*/
{
  int i1,i2,it,is,ig, gx, gz;
  if(nm!=nx*nz) sf_error("model size mismatch: %d!=%d",nm, nx*nz);
  if(nd!=nt*ng*ns) sf_error("data size mismatch: %d!=%d",nd,nt*ng*ns);
  sf_adjnull(adj, add, nm, nd, mod, dat);

  for(is=0; is<ns; is++) {/* it may be parallized using MPI */
    /* initialize is-th source wavefield Ps[] */
    memset(sp0[0], 0, nzpad*nxpad*sizeof(float));
    memset(sp1[0], 0, nzpad*nxpad*sizeof(float));
    if (csdgather){
      gxbeg=sxbeg+is*jsx-distx;
      sg_init(gxz, gzbeg, gxbeg, jgz, jgx, ng);
    }

    if(adj){/* migration: mm=Lt dd */
      for(it=0; it<nt; it++){
        add_source(&sxz[is], sp1, 1, &wlt[it], true);
        step_forward(sp0, sp1, vv, false);
        apply_sponge(sp0);
        apply_sponge(sp1);
        ptr=sp0; sp0=sp1; sp1=ptr;
        boundary_rw(sp0, &rwbndr[it*4*(nx+nz)], false);
      }

      memset(gp0[0], 0, nzpad*nxpad*sizeof(float));
      memset(gp1[0], 0, nzpad*nxpad*sizeof(float));
      for (it=nt-1; it >-1; it--) {
        /* reverse time order, Img[]+=Ps[]* Pg[]; */
        if(verb) sf_warning("%d;",it);

        /* reconstruct source wavefield Ps[] */
        boundary_rw(sp0, &rwbndr[it*4*(nx+nz)], true);
        ptr=sp0; sp0=sp1; sp1=ptr;
        step_forward(sp0, sp1, vv, false);
        add_source(&sxz[is], sp1, 1, &wlt[it], false);

        /* backpropagate receiver wavefield */
        for(ig=0;ig<ng; ig++){
          gx=gxz[ig]/nz;
          gz=gxz[ig]%nz;
          gp1[gx+nb][gz+nb]+=dat[it+ig*nt+is*nt*ng];
        }
        step_forward(gp0, gp1, vv, false);
        apply_sponge(gp0);
        apply_sponge(gp1);
        ptr=gp0; gp0=gp1; gp1=ptr;

        for(i2=0; i2<nx; i2++)
          for(i1=0; i1<nz; i1++)
            mod[i1+nz*i2]+=sp0[i2+nb][i1+nb]*gp1[i2+nb][i1+nb];
      }
    }else{/* Born modeling/demigration: dd=L mm */

      for(it=0; it<nt; it++){
        /* forward time order, Pg[]+=Ps[]* Img[]; */
        if(verb) sf_warning("%d;",it);

        for(i2=0; i2<nx; i2++)
          for(i1=0; i1<nz; i1++)
            gp1[i2+nb][i1+nb]+=sp0[i2+nb][i1+nb]*mod[i1+nz*i2];

        ptr=gp0; gp0=gp1; gp1=ptr;
        apply_sponge(gp0);
        apply_sponge(gp1);
        step_forward(gp0, gp1, vv, true);

        for(ig=0;ig<ng; ig++){
          gx=gxz[ig]/nz;
          gz=gxz[ig]%nz;
          dat[it+ig*nt+is*nt*ng]+=gp1[gx+nb][gz+nb];
        }

        add_source(&sxz[is], sp1, 1, &wlt[it], true);
        step_forward(sp0, sp1, vv, false);
        apply_sponge(sp0);
        apply_sponge(sp1);
        ptr=sp0; sp0=sp1; sp1=ptr;
      }
    }
  }
}
Пример #6
0
//JS
//static int counter=0;
void gradient_pas_av(float *x, float *fcost, float *grad)
/*< acoustic velocity gradient >*/
{
	int ix, iz, is, ir, it, wit, iturn;
	int rx;

	float temp, dmax;
	float **p0, **p1, **p2, **term, **tmparray, ***wave, **pp;
	float *sendbuf, *recvbuf;

        /*
        //JS
        sf_file Fwfl1, Fwfl2, Fres;
        counter++;
        if (cpuid==0 && counter==3) {
            Fwfl1=sf_output("Fwfl1");
            Fwfl2=sf_output("Fwfl2");
            Fres=sf_output("Fres");
            sf_putint(Fwfl1,"n1",padnz);
            sf_putint(Fwfl1,"n2",padnx);
            sf_putint(Fwfl1,"n3",(nt-1)/50+1);
            sf_putint(Fwfl2,"n1",padnz);
            sf_putint(Fwfl2,"n2",padnx);
            sf_putint(Fwfl2,"n3",(nt-1)/50+1);
            sf_putint(Fres,"n1",nt);
            sf_putint(Fres,"n2",nr);
        }
        */

	/* initialize fcost */
	*fcost=0.;
	/* update velocity */
	pad2d(x, vv, nz, nx, nb);
	/* initialize gradient */
	memset(grad, 0., nzx*sizeof(float));

	/* memory allocation */
	p0=sf_floatalloc2(padnz, padnx);
	p1=sf_floatalloc2(padnz, padnx);
	p2=sf_floatalloc2(padnz, padnx);
	term=sf_floatalloc2(padnz, padnx);
	wave=sf_floatalloc3(nz, nx, wnt);
	pp=sf_floatalloc2(nt, nr);

        iturn=0;
        for(is=cpuid; is<ns; is+=numprocs){
            if(cpuid==0) sf_warning("###### is=%d ######", is+1);

            memset(p0[0], 0., padnzx*sizeof(float));
            memset(p1[0], 0., padnzx*sizeof(float));
            memset(p2[0], 0., padnzx*sizeof(float));
            memset(pp[0], 0., nr*nt*sizeof(float));

            wit=0;
            /* forward propagation */
            for(it=0; it<nt; it++){
                if(verb) sf_warning("Forward propagation it=%d;", it);

                /* output predicted data */
                for(ir=0; ir<nr; ir++){
                    rx=r0_v[0]+ir*dr_v;
                    pp[ir][it]=p1[rx][rz];
                }

                /* save wavefield */
                if(it%interval==0){
#ifdef _OPENMP 
#pragma omp parallel for \
                    private(ix,iz) \
                    shared(wave,p1,wit,nb,nx,nz)
#endif
                    for(ix=0; ix<nx; ix++)
                        for(iz=0; iz<nz; iz++)
                            wave[wit][ix][iz]=p1[ix+nb][iz+nb];
                    wit++;
                }

                /*
                //JS
                if(is==0 && counter==3 && it%50==0) sf_floatwrite(p1[0],padnzx,Fwfl1);
                */

                /* laplacian operator */
                laplace(p1, term, padnx, padnz, dx2, dz2);

                /* load source */
#ifdef _OPENMP 
#pragma omp parallel for \
                private(ix,iz) \
                shared(term,nb,ww3,it)
#endif
                for(ix=0; ix<nx; ix++){
                    for(iz=0; iz<nz; iz++){
                        term[ix+nb][iz+nb] += ww3[iturn][it][ix][iz];
                    }
                }

                /* update */
#ifdef _OPENMP 
#pragma omp parallel for \
                private(ix,iz) \
                shared(p0,p1,p2,vv,term,padnx,padnz,dt2)
#endif
                for(ix=4; ix<padnx-4; ix++){
                    for(iz=4; iz<padnz-4; iz++){
                        p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
                    }
                }

                /* swap wavefield pointer of different time steps */
                tmparray=p0; p0=p1; p1=p2; p2=tmparray;

                /* boundary condition */
                apply_sponge(p0, bc, padnx, padnz, nb);
                apply_sponge(p1, bc, padnx, padnz, nb);
            } // end of time loop

            /* check */
            if(wit != wnt) sf_error("Incorrect number of wavefield snapshots");
            wit--;

            /* calculate data residual and data misfit */
            for(ir=0; ir<nr; ir++){
                for(it=0; it<nt; it++){
                    pp[ir][it]=dd[iturn][ir][it]-pp[ir][it];
                    *fcost += 0.5*pp[ir][it]*pp[ir][it];
                }
            }

            /* window the data residual */
            for(ir=0; ir<nr; ir++){
                /* multiscale */
                if(NULL != blo){
                    sf_butter_apply(blo, nt, pp[ir]);
                    sf_reverse(nt, pp[ir]);
                    sf_butter_apply(blo, nt, pp[ir]);
                    sf_reverse(nt, pp[ir]);
                }
                if(NULL != bhi){
                    sf_butter_apply(bhi, nt, pp[ir]);
                    sf_reverse(nt, pp[ir]);
                    sf_butter_apply(bhi, nt, pp[ir]);
                    sf_reverse(nt, pp[ir]);
                }
                for(it=0; it<nt; it++){
                    pp[ir][it] *= weight[ir][it];
                }
            }

            /*
            // JS
            if(is==0 && counter==3) sf_floatwrite(pp[0], nr*nt, Fres);
            */

            /* initialization */
            memset(p0[0], 0., padnzx*sizeof(float));
            memset(p1[0], 0., padnzx*sizeof(float));
            memset(p2[0], 0., padnzx*sizeof(float));
            memset(term[0], 0., padnzx*sizeof(float));

            /* backward propagation */
            for(it=nt-1; it>=0; it--){
                if(verb) sf_warning("Backward propagation it=%d;", it);

                /* laplacian operator */
                laplace(p1, term, padnx, padnz, dx2, dz2);

                /* load data residual*/
                for(ir=0; ir<nr; ir++){
                    rx=r0_v[0]+ir*dr_v;
                    term[rx][rz] += pp[ir][it];
                }

                /* update */
#ifdef _OPENMP 
#pragma omp parallel for \
                private(ix,iz) \
                shared(p0,p1,p2,vv,term,padnx,padnz,dt2)
#endif
                for(ix=4; ix<padnx-4; ix++){
                    for(iz=4; iz<padnz-4; iz++){
                        p2[ix][iz]=2*p1[ix][iz]-p0[ix][iz]+vv[ix][iz]*vv[ix][iz]*dt2*term[ix][iz];
                    }
                }

                /*
                // JS
                if(is==0 && counter==3 && it%50==0) sf_floatwrite(p1[0],padnzx,Fwfl2);
                */

                /* calculate gradient  */
                if(it%interval==0){
                    if(wit != wnt-1 && wit != 0){ // avoid the first and last time step
#ifdef _OPENMP 
#pragma omp parallel for \
                        private(ix,iz,temp) \
                        shared(nx,nz,vv,wave,p1,wit,wdt2,grad)
#endif
                        for(ix=0; ix<nx; ix++){
                            for(iz=0; iz<nz; iz++){
                                temp=vv[ix+nb][iz+nb];
                                temp=temp*temp*temp;
                                temp=-2./temp;
                                grad[ix*nz+iz] += gwt[iturn][it][ix][iz]*(wave[wit+1][ix][iz]-2.*wave[wit][ix][iz]+wave[wit-1][ix][iz])/wdt2*p1[ix+nb][iz+nb]*temp;
                            }
                        }
                    }
                    wit--;
                }

                /* swap wavefield pointer of different time steps */
                tmparray=p0; p0=p1; p1=p2; p2=tmparray;

                /* boundary condition */
                apply_sponge(p0, bc, padnx, padnz, nb);
                apply_sponge(p1, bc, padnx, padnz, nb);
            } // end of time loop

            iturn++;

            /*
            // JS
            if(is==0 && counter==3){
            sf_fileclose(Fwfl1);
            sf_fileclose(Fwfl2);
            sf_fileclose(Fres);
            }
            sf_warning("---counter=%d fcost=%3.3e---",counter, *fcost);
            */
        } // end of shot loop
	MPI_Barrier(comm);

	/* misfit reduction */
	if(cpuid==0){
		sendbuf=MPI_IN_PLACE;
		recvbuf=fcost;
	}else{
		sendbuf=fcost;
		recvbuf=NULL;
	}
	MPI_Reduce(sendbuf, recvbuf, 1, MPI_FLOAT, MPI_SUM, 0, comm);
	MPI_Bcast(fcost, 1, MPI_FLOAT, 0, comm);

	/* gradient reduction */
	if(cpuid==0){
		sendbuf=MPI_IN_PLACE;
		recvbuf=grad;
	}else{
		sendbuf=grad;
		recvbuf=NULL;
	}
	MPI_Reduce(sendbuf, recvbuf, nzx, MPI_FLOAT, MPI_SUM, 0, comm);
	MPI_Bcast(grad, nzx, MPI_FLOAT, 0, comm);

        /* scaling gradient */
        if(first){
            dmax=0.;
            for(ix=0; ix<nzx; ix++)
                if(fabsf(grad[ix])>dmax)
                    dmax=fabsf(grad[ix]);
            scaling=0.1/dmax;
            first=false;
        }

	/* smooth gradient */
	gradient_smooth2b(grectx, grectz, nx, nz, waterz, waterzb, scaling, grad);

	/* free allocated memory */
	free(*p0); free(p0); free(*p1); free(p1);
	free(*p2); free(p2); free(*pp); free(pp);
	free(**wave); free(*wave); free(wave);
	free(*term); free(term);
}
Пример #7
0
void step_fields(int iyear, int itts, int imon, int iterno) {
	int i, j, k, l, m;
	int mdt;
	double inv_mdt;
	int ibiodt;

	//DT
	double Tmptr[NXMEM][NYMEM];
	int n;
	double secperyr = 365.25 * 60 * 60 * 24;
	//DT



	/*-----------------------------------------
	 *
	 *     PARAMETER VALUES
	 *
	 *-----------------------------------------*/

	/*-----------------------------------------
	 *
	 *     SCREEN PRINT CONTROL
	 *
	 *-----------------------------------------*/

	doprint = 0;
	pquant[1] = 0; /* print mass conservation checks? (1 = yes) */
	pquant[2] = 1; /* print single grid point at each step? (1 = yes) */
	pquant[3] = 1; /* print negative concentrations? */
	/*   pq3=1 => print warning                */
	/*   pq3=0 => set concentration to trwarn   */
	/*   pq3=2 => do both                      */
	/*   pq3=3 => do nothing                   */

	/*-----------------------------------------
	 *
	 *     CALCULATE PRELIMINARY QUANTITIES
	 *
	 *-----------------------------------------*/

	// z_depth(h, depth);


	/*-----------------------------------------
	 *
	 *     PRINT TO SCREEN #1
	 *
	 *-----------------------------------------*/

	pstage = 1;
//	print_to_screen(pquant, pstage);


	/*-----------------------------------------
	 *
	 *     STEP 1: PHYSICAL TRANSPORT
	 *
	 *-----------------------------------------*/



	printf("Calculate tracer transport. \n");


	tracer(itts); /* perform transport time step */

#ifdef MERGED_ML
	merge_ml_tr();
#endif
	/*-----------------------------------------
	 *
	 *     PRINT TO SCREEN #2
	 *
	 *-----------------------------------------*/


	pstage = 2;
//	print_to_screen(pquant, pstage);

	/*-----------------------------------------
	 *
	 *     STEP 2: BIOTIC SOURCE/SINK TERMS
	 *
	 *-----------------------------------------*/

	/*-----------------------------------------
	 *
	 *  CALCULATE BIOTIC SOURCE/SINK TERMS
	 *    based on OCMIP scheme in which
	 *    biological pump is linked to PO4
	 *
	 *-----------------------------------------*/
#if defined(PHOSPHATE) && defined(OXYGEN)
	ibiodt = 1; // number of biotic time steps per transport time step (dt)

	// Update phosphate concentration for surface value restoration
	read_woa_file(imon, hstart, po4_star_lay, "woa09.phos.nc", "p_an",1e-3);
/*
	set_fix_darray3d_zero(jo2,NZ);
	set_fix_darray3d_zero(jdop,NZ);
	set_fix_darray3d_zero(jpo4,NZ);
	set_fix_darray3d_zero(jprod,NZ);
	set_fix_darray3d_zero(jremin,NZ);
	set_fix_darray3d_zero(jremdop,NZ);
	set_fix_darray2d_zero(flux_pop);
*/	
	printf("Calculating biotic sources/sinks\n");
	biotic_sms(ibiodt);

	merge_ml_tr();
	merge_ml_j();
	apply_oxygen_jterms();
	apply_phosphate_jterms();
	surface_oxygen();


#endif




	/*-----------------------------------------
	 *
	 *  APPLY BIOTIC SOURCE/SINK TERMS
	 *   step tr array forward using Euler method
	 *   calculate global integral for mass conservation checking
	 *
	 *-----------------------------------------*/

	for (i = 0; i <= NXMEM - 1; i++) {
		for (j = 0; j <= NYMEM - 1; j++) {
			//BX - reinstated by HF
			if (D[i][j] > MINIMUM_DEPTH) {
				for (k = 0; k < NZ; k++) {
				}
				//BX - reinstated by HF
			} else {
				for (k = 0; k < NZ; k++) {
#ifdef AGE
					tr[mAGE][k][i][j] = misval;
#endif
				}
			}
		}
	}


#ifdef AGE
	for (i = 0; i <= NXMEM - 1; i++) {
		for (j = 0; j <= NYMEM - 1; j++) {
			if (D[i][j] > MINIMUM_DEPTH) {
				tr[mAGE][0][i][j] = 0.0;
				for (k = 1; k < NZ; k++) {
					tr[mAGE][k][i][j] += dt;
				}
			}
		}
	}
#endif


#ifdef MERGED_ML
	merge_ml_tr();
#endif




	/*-----------------------------------------
	 *
	 *     OVERWRITE RESULTS IN SPECIAL CASES
	 *
	 *-----------------------------------------*/

	/*-----------------------------------------
	 *
	 *    Sponges and Re-Entrant Boundaries
	 *
	 *-----------------------------------------*/

#ifdef SPONGE

	apply_sponge(h, dt, ea, eb);

#endif

	/* undo effect of oxygen sponge on delo18 */
	/* reset tr[mo18] to maintain old delo18  */


	/* zonal, meridional re-entrance    */
	for (m = 0; m < NTR; m++) {
		for (k = 0; k < NZ; k++) {
			for (j = 0; j <= NYMEM - 1; j++) {
				tr[m][k][0][j] = tr[m][k][nx - 1][j];
				tr[m][k][1][j] = tr[m][k][nx][j];
				tr[m][k][nx + 1][j] = tr[m][k][2][j];
				tr[m][k][nx + 2][j] = tr[m][k][3][j];
			}
		}
		for (i = 2; i <= nx; i++) {
			ii = 363 - i;
			for (k = 0; k < NZ; k++) {
				tr[m][k][ii][ny + 1] = tr[m][k][i][ny];
				tr[m][k][ii][ny + 2] = tr[m][k][i][ny - 1];
			}
		}
	}

	/*-----------------------------------------
	 *
	 *     PRINT TO SCREEN #3
	 *
	 *-----------------------------------------*/


	pstage = 3;
//	print_to_screen(pquant, pstage);

	/*-----------------------------------------
	 *
	 *   store new tr array into named arrays for output
	 *
	 *-----------------------------------------*/

	for (k = 0; k < NZ; k++) {
		for (i = 0; i <= NXMEM - 1; i++) {
			for (j = 0; j <= NYMEM - 1; j++) {
#ifdef AGE
				age[k][i][j] = tr[mAGE][k][i][j] / (365.0 * 86400.0); /*years*/
#endif
			}
		}
	}

} /* end time step */