Skip to content
Snippets Groups Projects
makemod.c 32.76 KiB
#include "par.h"
#include "segy.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>

#ifndef ABS
#define ABS(x) ((x) < 0 ? -(x) : (x))
#endif
#ifndef MAX
#define	MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define	MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
#define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5))

float **alloc2float (size_t n1, size_t n2);
void free2float (float **p);

void grid(float **gridcp, float **gridcs, float **gridro, int *zp, float **cp, float **cs, float **ro, int minx, int maxx, int optgrad, float gradlen, float gradcp, float gradcs, float gradro, float dx, float dz, int nz);

void gridabove(float **gridcp, float **gridcs, float **gridro, int *zp, float **cp, float **cs, float **ro, int minx, int maxx, int optgrad, float gradlen, float gradcp, float gradcs, float gradro, float dx, float dz, int nz);

void plotexample();

void name_ext(char *filename, char *extension);

void interpolation(float *x, float *z, int nxp, int nx, int poly, int *pminx, int *pmaxx, float dx, float **cp, float **cs, float **ro, int nvel, float *interface);

void linearint(int *zp, int minx, int maxx, float dz, float *interface);

void sinusint(int *zp, int minx, int maxx, float dz, float *interface, float dx, float ampl, float wavel);

void roughint(int *zp, int minx, int maxx, float dz, float *interface, float ampl, float beta, float seed);

void fractint(int *zp, int minx, int maxx, float dx, float dz, float *interface, float Nsin, float ampl, float D, float k0, float b, float seed);

void elipse(float *x, float *z, int nxp, float dx, float dz, float **gridcp, float **gridcs, float **gridro, float **cp, float **cs, float **ro, float *interface, int *zp, int nz, int nx, float r1, float r2, float gradcp, float gradcs, float gradro);

void diffraction(float *x, float *z, int nxp, float dx, float dz, float **gridcp, float **gridcs, float **gridro, float **cp, float **cs, float **ro, float *interface, int *zp, int nx, int diffrwidth, int type);

void randdf(float *x, float *z, int nxp, float dx, float dz, float **gridcp, float **gridcs, float **gridro, float **cp, float **cs, float **ro, float *interface, int *zp, int nx, float sizex, float sizez, int ndiff, int diffrwidth, int type);

/*********************** self documentation **********************/
char *sdoc[] = {
  " 								",
  " makemod - gridded subsurface model builder",
  " 								",
  " makemod file_base= cp0= sizex= sizez= dx= dz= [optional parameters] ",
  " 							        ",
  " Required parameters:",
  " ",
  "   file_base= ............... base name of the output file(s).",
  "   cp0= ..................... Cp for background medium.",
  "   sizex= ................... x-size of the model in meters.",
  "   sizez= ................... z-size of the model in meters.",
  "   dx= ...................... grid distance in x in meters.",
  "   dz= ...................... grid distance in z in meters.",
  " ",
  " Optional parameters:",
  " ",
  "   orig=0,0 (x,z) ........... origin at the top left corner of the model.",
  " MEDIUM ",
  "   cs0=0 .................... Cs for background medium (0 is none).",
  "   ro0=0 .................... Rho for background medium (0 is none).",
  "   gradt=1 .................. type of boundary gradient (1=linear, 2=cos)",
  "   cp=none .................. P-wave velocities below the interface",
  "   cs=none .................. S-wave velocities below the interface",
  "   ro=none .................. Density below the interface",
  "   above=0 .................. define model below interface",
  "                              =1: define model above interface",
  " INTERFACE ",
  "   intt=none ................ Type of interface",
  "   var=none ................. variables to describe the interface",
  "   grad=0.0 ................. gradient(m) of the boundary",
  "   gradunit=0 ............... gradient unit (m/s per gradunit)",
  "   gradcp=0.0 ............... gradient(m/s per grad-unit) in the layer",
  "   gradcs=0.0 ............... gradient(m/s per grad-unit) in the layer",
  "   gradro=0.0 ............... gradient(kg/m3 per grad-unit) in the layer",
  "   poly=0 ................... polynominal interpolation through (x,z) points",
  "   x=none ................... x-positions for the interface",
  "   z=none ................... z-positions for the interface",
  "   dtype=0 .................. diffractor type for diffr and randdf",
  " OUTPUT ",
  "   writeint=0 ............... interfaces as function of x (ext: _int)",
  "   supersmooth=0 ............ samples at dx/4 and apply 5x5 smoothing operator(1)",
  "   sigma=0.8 ................ smoothing value, higher values gives more smoothing",
  "   reflectivity=0 ........... compute reflectivity (ext: _rfl)",
  "   rayfile=0 ................ interfaces as function of x in ASCII file.mod",
  "   skip=5 ................... number of x position to skip in file_ray",
  "   example=0 ................ makes an example parameter file",
  "   verbose=0 ................ silent option; >0 display info",
  " ",
  "   Options for intt:",
  "         - def       = default interface through the points(Xi, Zi)",
  "         - sin       = sinus shaped interface",
  "         - rough     = rough interface with beta(smoothness)",
  "         - fract     = cosinus fractal shaped interface",
  "         - random    = define random velocities in layer",
  "         - elipse    = define elipse shaped body",
  "         - diffr     = point diffractions",
  "         - randdf    = define random diffractors ",
  "   Options for var in case of intt =:",
  "         - sin(2)    = wavelength,amplitude",
  "         - rough(3)  = amplitude,beta,seed",
  "         - fract(6)  = Nsinus,amplitude,dim,k0,freqscale,seed",
  "         - random(1) = min-max variation around cp",
  "         - elipse(2) = r1, r2: vertical and horizontal radius",
  "         - diffr(1)  = width of each point, type(optional)",
  "         - randdf(2) = number of points, width of each point",
  "   Options for poly in default interface:",
  "         - 0         = linear",
  "         - 1         = polynomal",
  "         - 2         = cubic spline",
  "   Options for dtype value in var=width,dtype for diffr:",
  "         - -1        = random (0, 1, or 2) diffractor type",
  "         - 0         = cubic diffractor",
  "         - 1         = diamond diffractor",
  "         - 2         = circular diffractor",
  "   Option for gradunit, gradient unit per layer:",
  "         - 0         = gradient unit per layer is m/s per dz (default)",
  "         - 1         = gradient unit per layer is m/s per m",
  "  (1) Reference: Zeng and West: Geophysics 1996 ",
  " ",
  " makemod builds a gridded subsurface file which can be used in a migration",
  " or finite difference program. The gridded model is stored in files with",
  " extensions _cp, _cs, _ro. The extensions _int and .mod are used for the ",
  " interface files. The output format of the file(s) depends on the .(dot)",
  " extension of file_base.",
  " ",
  " author  : Jan Thorbecke : 18-01-1994 (janth@xs4all.nl)",
  " product : Originates from DELPHI software",
  "                         : revision 2010",
  " ",
  NULL};
/**************** end self doc ***********************************/
int main(int argc, char **argv)
{
  FILE *fpint, *fpcp, *fpcs, *fpro;
  int   example, verbose, writeint, nb;
  int	above, diffrwidth, dtype, reflectivity, supersmooth;
  int   Ngp, Ngs, Ngr, Np, Ns, Nr, Ng, Ni, Nv, Nvi, No, Noi;
  int   jint, jcount, j, ix, iz, nx, nz, nxp, nzp, *zp, nmaxx, nminx, optgrad, poly, gradt; 
  int	ncp, nro, ncs, nvel, skip, rayfile, store_int;
  long lseed;
  size_t  nwrite;
  float *data_out, orig[2], cp0, cs0, ro0, Z1, Z2, sigma;
  float	*x, *z, *var, *interface, **inter;
  float back[3], sizex, sizez, dx, dz;
  float **cp ,**cs, **ro, aver, gradlen, gradcp, gradcs, gradro;
  
  /* Gradient unit flag    */
  /* ------------------    */
  /* - 0 Unit : m/s per dz */
  /* - 1 Unit : m/s per m  */
  int gradunit;
  /* Number of Z-reference points (one per layer) */
  int Nzr=0;
  
  float   **gridcp, **gridcs, **gridro;
  segy    *hdrs;
  char    *file, intt[10], *file_base, filename[150];
  
  initargs(argc, argv);
  requestdoc(1);
  
  if (!getparint("example", &example)) example=0;
  else { plotexample(); exit(0); }
  
  if(getparstring("file",&file_base)) 
    vwarn("parameters file is changed to file_base");
  else {
    if(!getparstring("file_base",&file_base))
      verr("file_base not specified.");
  }
  if(getparfloat("back", back)) {
    vwarn("parameters back is not used anymore");
    vwarn("it has changed into cp0 (ro0,cs0 are optional)");
    nb = countparval("back");
    if (nb == 1) {
      vwarn("The new call should be cp0=%.1f",back[0]);
      cp0 = back[0];
    }
    if (nb == 2) {
      vwarn("The new call should be cp0=%.1f",back[0]);
      vwarn("                       ro0=%.1f",back[1]);
      cp0 = back[0];
      ro0 = back[1];
    }
    if (nb == 3) {
      vwarn("The new call should be cp0=%.1f",back[0]);
      vwarn("                       cs0=%.1f",back[1]);
      vwarn("                       ro0=%.1f",back[2]);
      cp0 = back[0];
      cs0 = back[1];
      ro0 = back[2];
    }
    vmess("Don't worry everything still works fine");
  }
  else {
    if(!getparfloat("cp0", &cp0)) verr("cp0 not specified.");
    if(!getparfloat("cs0", &cs0)) cs0 = -1;
    if(!getparfloat("ro0", &ro0)) ro0 = -1;
  }
  if(!getparfloat("sizex", &sizex)) verr("x-model size not specified.");
  if(!getparfloat("sizez", &sizez)) verr("z-model size not specified.");
  if(!getparfloat("dx", &dx)) verr("grid distance dx not specified.");
  if(!getparfloat("dz", &dz)) verr("grid distance dz not specified.");
  if(!getparfloat("orig", orig)) orig[0] = orig[1] = 0.0;
  if(!getparint("gradt", &gradt)) gradt = 1;
  if(!getparint("gradunit", &gradunit)) gradunit = 0;
  if(!getparint("writeint", &writeint)) writeint = 0;
  if(!getparint("reflectivity", &reflectivity)) reflectivity = 0;
  if(!getparint("supersmooth", &supersmooth)) supersmooth = 0;
  if(!getparfloat("sigma", &sigma)) sigma = 0.8;
  if(!getparint("rayfile", &rayfile)) rayfile = 0;
  if(!getparint("skip", &skip)) skip = 5;
  if(!getparint("above", &above)) above=0;
  if(!getparint("verbose", &verbose)) verbose=0;
  if(!getparint("dtype", &dtype)) dtype = 0;
  
  if (supersmooth==1) {
    dx = dx/4;
    dz = dz/4;
  }
  if ((writeint == 1) || (rayfile == 1)) store_int = 1;
  else store_int = 0;
  
  /*=================== check parameters =================*/
  
  Np = countparname("cp");
  Ns = countparname("cs");
  Nr = countparname("ro");
  Ng = countparname("grad");
  No = countparname("poly");
  Ni = countparname("intt");
  Nv = countparname("var");
  Ngp = countparname("gradcp");
  Ngs = countparname("gradcs");
  Ngr = countparname("gradro");
  
  Nvi = 0;
  for (jint = 1; jint <= Ni; jint++) {
    getnparstring(jint,"intt", &file);
    strcpy(intt, file);
    if (strstr(intt,"sin") != NULL) Nvi++;
    if (strstr(intt,"rough") != NULL) Nvi++;
    if (strstr(intt,"fract") != NULL) Nvi++;
    if (strstr(intt,"elipse") != NULL) Nvi++;
	if (strstr(intt,"random") != NULL) Nvi++;
//	if (strstr(intt,"randdf") != NULL) Nvi++;
    if (strstr(intt,"diffr") != NULL || strstr(intt,"randdf") != NULL) {
	  Nvi++;
//      if (Ng != 0) Ng++; 
//      if (No != 0) No++;
    }
  }
//  fprintf(stderr,"Nvi=%d ng=%d No=%d np=%d,", Nvi,Ng,No,Np);
  
  if (Np != Nr && ro0 > 0) verr("number of cp and ro not equal.");
  if (Np != Ni) verr("number of cp and interfaces not equal.");
  if (Nvi != Nv) verr("number of interface variables(var) not correct.");
  if (Ns == 0 && Nr == 0) if (verbose>=2) vmess("Velocity model.");
  if (Ns == 0) { if (verbose>=2) vmess("Acoustic model."); }
  else {
    if (verbose>=2) vmess("Elastic model.");
    if (Np != Ns) verr("number of cp and cs not equal");
  }
  
  if (Ng == 0) {
    if (verbose>=2) vmess("No boundary gradients are defined.");
  }
  else if (Ng != Np) {
    verr("number of boundary gradients and interfaces are not equal.");
  }
  if (Ngp == 0) {
    if (verbose>=2) vmess("No interface gradients for cp defined.");
  }
  else if (Ngp != Np) {
    verr("gradcp gradients and interfaces are not equal.");
  }
  if (Ngs == 0) {
    if (verbose>=2) vmess("No interface gradients for cs defined.");
  }
  else if (Ngs != Np) {
    verr("gradcs gradients and interfaces are not equal.");
  }
  if (Ngr == 0) {
    if (verbose>=2) vmess("No interface gradients for rho defined.");
  }
  else if (Ngr != Np) {
    verr("gradro gradients and interfaces are not equal.");
  }
  if (No == 0) {
    if (verbose>=2) vmess("All interfaces are linear.");
  }
//  else if (No != Np) {
//    verr("number of poly variables and interfaces are not equal.");
//  }
  
  if (Np > 0) {
    if (countparname("x") != Np)
      verr("a x array must be specified for each interface.");
    if (countparname("z") != Np)
      verr("a z array must be specified for each interface.");
  } 
  else Np = 1;

  if (Nzr != Np && Nzr !=0) {
    verr("number of zref gradients not equal to number of interfaces");
  }
  
  /*=================== initialization of arrays =================*/
  
  nz = NINT(sizez/dz)+1;
  nx = NINT(sizex/dx)+1;
  
  zp = (int *)malloc(nx*sizeof(int));
  interface = (float *)malloc(nx*sizeof(float));
  var = (float *)malloc(8*sizeof(float));
  gridcp = alloc2float(nz, nx);
  if(gridcp == NULL) verr("memory allocation error gridcp");
  if (Ns || (NINT(cs0*1e3) >= 0)) {
    gridcs = alloc2float(nz, nx);
    if(gridcs == NULL) verr("memory allocation error gridcs");
  }
  else gridcs = NULL;
  if (Nr || (NINT(ro0*1e3) >= 0)) {
    gridro = alloc2float(nz, nx);
    if(gridro == NULL) verr("memory allocation error gridro");
  }
  else gridro = NULL;
  
  cp = alloc2float(nx,3);
  cs = alloc2float(nx,3);
  ro = alloc2float(nx,3);
  if (store_int == 1) inter = alloc2float(nx, 2*Np);
  
  if (verbose) {
    vmess("Origin top left (x,z) . = %.1f, %.1f", orig[0], orig[1]);
    vmess("Base name ............. = %s", file_base);
    vmess("Number of interfaces .. = %d", Np);
    vmess("length in x ........... = %f (=%d)", sizex, nx);
    vmess("length in z ........... = %f (=%d)", sizez, nz);
    vmess("delta x ............... = %f", dx);
    vmess("delta z ............... = %f", dz);
    vmess("cp0 ................... = %f", cp0);
    if (Ns) vmess("cs0 ................... = %f", cs0);
    if (Nr) vmess("ro0 ................... = %f", ro0);
    vmess("write interfaces ...... = %d", writeint);
    vmess("store interfaces ...... = %d", store_int);
    if (above) vmess("define model above interface");
    else vmess("define model below interface");
  }

  /*========== initializing for homogeneous background =============*/
  
  nminx = 0;
  nmaxx = nx;
  for (j = nminx; j < nmaxx; j++) {
    cp[0][j] = cp0;
    cs[0][j] = cs0;
    ro[0][j] = ro0;
    zp[j] = 0;
    cp[1][j] = cp0;
    cs[1][j] = cs0;
    ro[1][j] = ro0;
  }
  
  gradlen = 0.0;
  gradcp = gradcs = gradro = 0.0;
  optgrad = 3;
  if (above == 0) {
    Nvi = 1; Noi = 1;
  } else {
    Nvi = Ngp; Noi = Ngp;
  }
  grid(gridcp, gridcs, gridro, zp, cp, cs, ro, nminx, nmaxx, optgrad,
       gradlen, gradcp, gradcs, gradro, dx, dz, nz);
  
  nxp = nzp = 2;
  x = (float *)malloc(nxp*sizeof(float));
  z = (float *)malloc(nzp*sizeof(float));
  
  if (Ni == 0) {
    if (verbose) vmess("No interfaces are defined, Homogeneous model.");
    Np = 0;
  }
  
  /*========== filling gridded model with interfaces =============*/
  
  for (jcount = 1; jcount <= Np; jcount++) {
    
    /* for above interface definition reverse	*/
    /* order of interfaces to scan 			*/
    if (above == 0) jint=jcount;
    else jint=Np+1-jcount;
    
    if (verbose) vmess("***** Interface number %d *****", jint);
    
    getnparstring(jint,"intt", &file);
    strcpy(intt, file);
    
    nxp = countnparval(jint,"x");
    nzp = countnparval(jint,"z");
    if (nxp != nzp) {
      vmess("nxp = %d nzp =%d for interface %d",nxp, nzp, jint);
      verr("Number of x and z values not equal for interface %d",jint);
    }
    ncp = countnparval(jint,"cp");
    nro = countnparval(jint,"ro");
    ncs = countnparval(jint,"cs");
    
    if (ncp == 1) {
      if (verbose>=2) vmess("No lateral gradient in P velocity");
    }
    else if (ncp == 2) {
      if (verbose) vmess("lateral P-gradient from begin to end");
    }
    else if (ncp != nxp) {
      vmess("ncp = %d nxp =%d for interface %d",ncp, nxp, jint);
      verr("Number of cp's and x not equal for interface %d",jint);
    }
    if (nro <= 1) {
      if (verbose>=2) vmess("No lateral gradient in density");
    }
    else if (nro == 2) {
      if (verbose) vmess("lateral Rho-gradient from begin to end");
    }
    else if (nro != nxp) {
      vmess("nro = %d nxp =%d for interface %d",nro, nxp, jint);
      verr("Number of ro's and x not equal for interface %d",jint);
    }
    if (ncs <= 1) {
      if (verbose>=2) vmess("No lateral gradient in S velocity");
    }
    else if (ncs == 2) {
      if (verbose) vmess("lateral S-gradient from begin to end");
    }
    else if (ncs != nxp) {
      vmess("ncs = %d nxp =%d for interface %d",ncs, nxp, jint);
      verr("Number of cs's and x not equal for interface %d",jint);
    }
    
    nvel = MAX(ncp, MAX(nro, ncs));
    
    free(x);
    free(z);
    x = (float *)malloc(nxp*sizeof(float));
    z = (float *)malloc(nzp*sizeof(float));
	memset(interface, 0, nx*sizeof(float));
    
    getnparfloat(jint,"x",x);
    getnparfloat(jint,"z",z);
    getnparfloat(jint,"cp",cp[2]);
    if (Nr == 0) ro[2][0] = 0.0;
    else getnparfloat(jint,"ro", ro[2]);
    if (Ns == 0) cs[2][0] = 0.0;
    else getnparfloat(jint,"cs", cs[2]);
    if (Ng == 0) gradlen = 0.0;
    else getnparfloat(Noi,"grad", &gradlen);
    if (No == 0) poly = 0;
    else getnparint(Noi,"poly", &poly);
    if (Ngp == 0) gradcp = 0.0;
    else getnparfloat(Noi,"gradcp", &gradcp);
    if (Ngs == 0) gradcs = 0.0;
    else getnparfloat(Noi,"gradcs", &gradcs);
    if (Ngr == 0) gradro = 0.0;
    else getnparfloat(Noi,"gradro", &gradro);
    /* if gradunit is in meters, recalculate gradcp,gradcs and gradro */
    if (gradunit > 0) {
      gradcs = gradcs * dz;
      gradcp = gradcp * dz;
      gradro = gradro * dz;
    }
    
    if (nvel != 1) {
      if (ncp == 1) {
	for (j = 1; j < nvel; j++) cp[2][j] = cp[2][0];
      }
      if (ncs == 1) {
	for (j = 1; j < nvel; j++) cs[2][j] = cs[2][0];
      }
      if (nro == 1) {
	for (j = 1; j < nvel; j++) ro[2][j] = ro[2][0];
      }
    }
    
    if (verbose) {
      vmess("Interface type .......... = %s", intt);
      vmess("Boundary gradient ....... = %f", gradlen);
      vmess("Interface gradient cp ... = %f", gradcp);
      if (Ns) vmess("Interface gradient cs ... = %f", gradcs);
      if (Nr) vmess("Interface gradient ro ... = %f", gradro);
      if (verbose>=2) {
	vmess("Polynomal ............... = %d", poly);
	vmess("Number of (x,z) points... = %d", nxp);
	vmess("P-wave velocities ....... = %d", ncp);
	if (Ns) vmess("S-wave velocities ....... = %d", ncs);
	if (Nr) vmess("Densities ............... = %d", nro);
      }
      for (j = 0; j < nxp; j++) {
	vmess("x = %6.1f \t z = %6.1f", x[j], z[j]);
	if (nvel != 1) {
	  vmess("    cp = %f", cp[2][j]);
	  if (Ns) vmess("    cs = %f", cs[2][j]);
	  if (Nr) vmess("   rho = %f", ro[2][j]);
	}
      }
      if (nvel == 1) {
	vmess("    cp = %f", cp[2][0]);
	if (Ns) vmess("    cs = %f", cs[2][0]);
	if (Nr) vmess("    rho = %f", ro[2][0]);
      }
    }
    
    for (j = 0; j < nxp; j++) {
      x[j] -= orig[0];
      z[j] -= orig[1];
    }
    for (j = 0; j < nxp; j++) {
      if(x[j] > sizex) verr("x coordinate bigger than model");
      if(z[j] > sizez) verr("z coordinate bigger than model");
    }
    if (gradlen > 0) optgrad = gradt;
    else optgrad = 3;
    
	if (strstr(intt,"random") != NULL) {
		Nv = countnparval(Nvi,"var");
		if (Nv != 1) verr("Random interface must have 1 variables.");
		getnparfloat(Nvi,"var", var);
		lseed = (long)var[0];
		srand48(lseed);
		gradcp=gradcs=gradro=var[0];
		optgrad = 4;
        if (above == 0) Noi++; else Noi--;
        if (above == 0) Nvi++; else Nvi--;
	}
	  
    if ((strstr(intt,"diffr") == NULL) && (strstr(intt,"randdf") == NULL)) {
      interpolation(x, z, nxp, nx, poly, &nminx, &nmaxx, dx, 
		    cp, cs, ro, nvel, interface);
    }

    if ( (strstr(intt,"def") != NULL) || (strstr(intt,"random") != NULL) ) {
      linearint(zp, nminx, nmaxx, dz, interface);
      if (above == 0) Noi++; else Noi--;
    }

    if (strstr(intt,"sin") != NULL) {
      Nv = countnparval(Nvi,"var");
      if (Nv != 2) verr("Sinus interface must have 2 variables.");
      getnparfloat(Nvi,"var", var);
      sinusint(zp, nminx, nmaxx, dz, interface, dx, var[0], var[1]);
      if (above == 0) Noi++; else Noi--;
      if (above == 0) Nvi++; else Nvi--;
    }
    else if (strstr(intt,"rough") != NULL) {
      Nv = countnparval(Nvi,"var");
      if (Nv != 3) verr("Rough interface must have 3 variables.");
      getnparfloat(Nvi,"var", var);
      roughint(zp, nminx, nmaxx, dz, interface, var[0],var[1],var[2]);
      if (above == 0) Noi++; else Noi--;
      if (above == 0) Nvi++; else Nvi--;
    }
    else if (strstr(intt,"fract") != NULL) {
      Nv = countnparval(Nvi, "var");
      if (Nv != 6) verr("Fractal interface must have 6 variables.");
      getnparfloat(Nvi,"var", var);
      fractint(zp, nminx, nmaxx, dx, dz, interface, var[0], var[1], 
	       var[2], var[3], var[4], var[5]);
      if (above == 0) Noi++; else Noi--;
      if (above == 0) Nvi++; else Nvi--;
    }
    if ((strstr(intt,"elipse") != NULL) || (strstr(intt,"diffr") != NULL) || (strstr(intt,"randdf") != NULL)) {
   	    if (strstr(intt,"randdf") != NULL) {
        	Nv = countnparval(Nvi, "var");
			if (Nv != 2) verr("randdf interface must have 2 variables: number of points, width.");
			getnparfloat(Nvi,"var", var);
        	if(!getparint("dtype", &dtype)) dtype = -1;
        
        	randdf(x, z, nxp, dx, dz, gridcp, gridcs, gridro, cp, cs, ro,
           	   interface, zp, nx, sizex, sizez, var[0], (int)var[1], dtype);

			if (above == 0) Noi++; else Noi--;
			if (above == 0) Nvi++; else Nvi--;
		}
		if (strstr(intt,"elipse") != NULL) {
			Nv = countnparval(Nvi, "var");
			if (Nv != 2) verr("Elipse interface must have 2 variables.");
			getnparfloat(Nvi,"var", var);
			elipse(x, z, nxp, dx, dz, gridcp, gridcs, gridro, 
				cp, cs, ro, interface, zp, nz, nx, var[0], var[1], gradcp, gradcs, gradro);
			if (above == 0) Noi++; else Noi--;
			if (above == 0) Nvi++; else Nvi--;
		}
		else if ((strstr(intt,"diffr") != NULL)) {
			Nv = countnparval(Nvi, "var");
        	if (Nv == 2 || Nv == 1) {
           		getnparfloat(Nvi,"var", var);
           		diffrwidth=(int)var[0];
           		if (Nv==1) {
           			if(!getparint("dtype", &dtype)) dtype = 0;
			}
           		else dtype=(int)var[1];
        	}
        	else {
           		verr("diffr interface must have 1 or 2 variables: width,type.");
        	}
        	
			diffraction(x, z, nxp, dx, dz, gridcp, gridcs, gridro,
				cp, cs, ro, interface, zp, nx, diffrwidth, dtype);
			if (above == 0) Noi++; else Noi--;
			if (above == 0) Nvi++; else Nvi--;
		}
	}
    else {
		if (above == 0) {
			grid(gridcp, gridcs, gridro, zp, cp, cs, ro, nminx, nmaxx, 
				optgrad, gradlen, gradcp, gradcs, gradro, dx, dz, nz);
		} 
		else {
			gridabove(gridcp, gridcs, gridro, zp, cp, cs, ro, nminx, nmaxx, 
				optgrad, gradlen, gradcp, gradcs, gradro, dx, dz, nz);
		}
	}
    
    if (store_int == 1) {
      for(j = 0; j < nminx; j++) inter[jint-1][j] = 0.0;
      for(j = nminx; j < nmaxx; j++) inter[jint-1][j] = interface[j];
      for(j = nmaxx; j < nx; j++) inter[jint-1][j] = 0.0;
      
      for(j = 0; j < nminx; j++) inter[jint-1+Np][j] = 0.0;
      for(j = nminx; j < nmaxx; j++) inter[jint-1+Np][j] = zp[j]*dz;
      for(j = nmaxx; j < nx; j++) inter[jint-1+Np][j] = 0.0;
    }
  } /* end of loop over interfaces */
  
/* apply supersampled data smoothing operator according to Zeng and West (1996) */
  
  if (supersmooth==1) {
	float Wsmooth[5][5], C, iC, xx, xz, *dataS, smooth;
	int ixi, izi, nxout, nzout;

	C=0;
	sigma = -1.0*log(sigma)/(dx*(powf(0.25*2.0,2.0)));
    for(ixi = -2; ixi < 3; ixi++) {
      for(izi = -2; izi < 3; izi++) {
        xx = 0.25*ixi;
        xz = 0.25*izi;
        Wsmooth[ixi+2][izi+2] = exp(-sigma*dx*(xx*xx+xz*xz) );
		//fprintf(stderr,"Wsmooth[%d][%d] = %f\n", ixi, izi, Wsmooth[ixi+2][izi+2]);
		C += Wsmooth[ixi+2][izi+2];
	  }
    }
    iC = 1.0/C;
	//fprintf(stderr,"sigma=%f %f C=%f\n",sigma, exp(-sigma*dx*powf(0.25*2.0,2.0)),C);

	nxout = (nx-1)/4+1;
	nzout = (nz-1)/4+1;
	//fprintf(stderr,"nxout=%d nzout=%d nx=%d nz=%d \n",nxout,nzout, nx, nz);
    dataS = malloc(nxout*nzout*sizeof(float));
    for(ix = 0; ix < nxout-1; ix++) {
      for(iz = 0; iz < nzout-1; iz++) {
        smooth = 0.0;
        for(ixi = -2; ixi < 3; ixi++) {
          for(izi = -2; izi < 3; izi++) {
            smooth += Wsmooth[ixi+2][izi+2]/gridcp[4*ix+2+ixi][4*iz+2+izi];
	      }
        }
        dataS[ix*nzout+iz] = 1.0/(iC*smooth);
	  }
      iz = nzout-1;
      dataS[ix*nzout+iz] = dataS[ix*nzout+iz-1];
    }
    ix = nxout-1;
    for(iz = 0; iz < nzout-1; iz++) {
      dataS[ix*nzout+iz] = dataS[(ix-1)*nzout+iz];
	}
    ix = nxout-1; iz = nzout-1;
    dataS[ix*nzout+iz] = dataS[(ix-1)*nzout+iz-1];

    for(ix = 0; ix < nxout; ix++) {
      for(iz = 0; iz < nzout; iz++) {
        gridcp[ix][iz] = dataS[ix*nzout+iz];
      }
    }

    /* smoothin densities */
    if (Nr > 0 || getparfloat("ro0", &ro0)) {
      for(ix = 0; ix < nxout-1; ix++) {
        for(iz = 0; iz < nzout-1; iz++) {
          smooth = 0.0;
          for(ixi = -2; ixi < 3; ixi++) {
            for(izi = -2; izi < 3; izi++) {
              smooth += Wsmooth[ixi+2][izi+2]*gridro[4*ix+2+ixi][4*iz+2+izi];
	        }
          }
          dataS[ix*nzout+iz] = iC*smooth;
	    }
        iz = nzout-1;
        dataS[ix*nzout+iz] = dataS[ix*nzout+iz-1];
      }
      ix = nxout-1;
      for(iz = 0; iz < nzout-1; iz++) {
        dataS[ix*nzout+iz] = dataS[(ix-1)*nzout+iz];
	  }
      ix = nxout-1; iz = nzout-1;
      dataS[ix*nzout+iz] = dataS[(ix-1)*nzout+iz-1];

      for(ix = 0; ix < nxout; ix++) {
        for(iz = 0; iz < nzout; iz++) {
          gridro[ix][iz] = dataS[ix*nzout+iz];
        }
      }
    }
    nx = nxout;
	nz = nzout;
    dx = dx*4;
    dz = dz*4;
	free(dataS);
  }

  if (verbose) vmess("Writing data to disk.");
  
  hdrs = (segy *) calloc(nx,sizeof(segy));
  for(j = 0; j < nx; j++) {
	hdrs[j].f1= orig[1];
	hdrs[j].f2= orig[0];
	hdrs[j].d1= dz;
	hdrs[j].d2= dx;
    hdrs[j].ns= nz;
	hdrs[j].trwf= nx;
	hdrs[j].tracl= j;
	hdrs[j].tracf= j;
    hdrs[j].gx = (orig[0] + j*dx)*1000;
    hdrs[j].scalco = -1000;
    hdrs[j].timbas = 25;
    hdrs[j].trid = TRID_DEPTH;
  }

  /* due to bug in SU, int-file has to be opened before other files are closed */
	if (writeint == 1) {
		strcpy(filename, file_base);
		name_ext(filename, "_int");
		fpint = fopen(filename,"w");
		assert(fpint != NULL);
	}

 
  /* write P-velocities in file */
  strcpy(filename, file_base);
  name_ext(filename, "_cp");
  fpcp = fopen(filename,"w");
  assert(fpcp != NULL);
  
  data_out = (float *)malloc(nx*nz*sizeof(float));
  for(ix = 0; ix < nx; ix++) {
    for(iz = 0; iz < nz; iz++) {
      data_out[ix*nz+iz] = gridcp[ix][iz];
	}
    nwrite = fwrite( &hdrs[ix], 1, TRCBYTES, fpcp);
    assert(nwrite == TRCBYTES);
    nwrite = fwrite( &data_out[ix*nz], sizeof(float), nz, fpcp);
    assert(nwrite == nz);
  }
  fclose(fpcp);

  /* write reflectivity of the interfaces */
  if (reflectivity == 1) {
    strcpy(filename, file_base);
    name_ext(filename, "_rfl");
    fpro = fopen(filename,"w");
    assert(fpro != NULL);
    
    for(ix = 0; ix < nx-1; ix++) {
      for(iz = 0; iz < nz-1; iz++) {
         Z1=gridro[ix][iz]*gridcp[ix][iz];
         Z2=gridro[ix][iz+1]*gridcp[ix][iz+1];
	     data_out[ix*nz+iz] = (Z2-Z1)/(Z2+Z1);
      }
	  data_out[ix*nz+nz-1] = 0.0;
      nwrite = fwrite( &hdrs[ix], 1, TRCBYTES, fpro);
      assert(nwrite == TRCBYTES);
      nwrite = fwrite( &data_out[ix*nz], sizeof(float), nz, fpro);
      assert(nwrite == nz);
    }
    ix = nx-1;
    for(iz = 0; iz < nz; iz++) {
	   data_out[ix*nz+iz] = 0.0;
    }
    nwrite = fwrite( &hdrs[ix], 1, TRCBYTES, fpro);
    assert(nwrite == TRCBYTES);
    nwrite = fwrite( &data_out[ix*nz], sizeof(float), nz, fpro);
    assert(nwrite == nz);
    fclose(fpro);
  } /* end of writing reflectivity file */

  free2float(gridcp);
  
  /* write S-velocities in file */
  if (Ns > 0 || getparfloat("cs0", &cs0)) {
    strcpy(filename, file_base);
    name_ext(filename, "_cs");
    fpcs = fopen(filename,"w");
    assert(fpcs != NULL);
    
    for(ix = 0; ix < nx; ix++) {
      for(iz = 0; iz < nz; iz++) {
	     data_out[ix*nz+iz] = gridcs[ix][iz];
      }
      nwrite = fwrite( &hdrs[ix], 1, TRCBYTES, fpcs);
      assert(nwrite == TRCBYTES);
      nwrite = fwrite( &data_out[ix*nz], sizeof(float), nz, fpcs);
      assert(nwrite == nz);
    }
    fclose(fpcs);
    free2float(gridcs);
    
  } /* end of writing S-velocity file */
  
  /* write densities in file */
  if (Nr > 0 || getparfloat("ro0", &ro0)) {
    strcpy(filename, file_base);
    name_ext(filename, "_ro");
    fpro = fopen(filename,"w");
    assert(fpro != NULL);
    
    for(ix = 0; ix < nx; ix++) {
      for(iz = 0; iz < nz; iz++) {
	     data_out[ix*nz+iz] = gridro[ix][iz];
      }
      nwrite = fwrite( &hdrs[ix], 1, TRCBYTES, fpro);
      assert(nwrite == TRCBYTES);
      nwrite = fwrite( &data_out[ix*nz], sizeof(float), nz, fpro);
      assert(nwrite == nz);
    }
    fclose(fpro);
    free2float(gridro);
  } /* end of writing density file */
  
  
  /* write depths of the interfaces */
  if (writeint == 1) {
    free(hdrs);
    hdrs = (segy *) calloc(Np,sizeof(segy));
    for(j = 0; j < Np; j++) {
      hdrs[j].fldr = 1;
      hdrs[j].timbas = 25;
	  hdrs[j].f1= orig[0];
	  hdrs[j].f2= 0.0;
	  hdrs[j].d1= dx;
	  hdrs[j].d2= dz;
	  hdrs[j].ns= nx;
	  hdrs[j].trwf= Np;
	  hdrs[j].tracl= j;
	  hdrs[j].tracf= j;
	  hdrs[j].trid= TRID_DEPTH;
    }
    
    /* note that due to bug in SU, interface file has already been opened */
    strcpy(filename, file_base);
    name_ext(filename, "_int");

    free(data_out);
    data_out = (float *)malloc(nx*Np*sizeof(float));
    for(jint = 0; jint < Np; jint++) {
      for(j = 0; j < nx; j++) {
	    data_out[jint*nx+j] = inter[jint][j]+orig[1];
      }
      nwrite = fwrite( &hdrs[jint], 1, TRCBYTES, fpint);
      assert(nwrite == TRCBYTES);
      nwrite = fwrite( &data_out[jint*nx], sizeof(float), nx, fpint);
      assert(nwrite == nx);
    }
    
	for(j = 0; j < Np; j++) hdrs[j].fldr = 2;
    for(jint = 0; jint < Np; jint++) {
      for(j = 0; j < nx; j++) {
	     data_out[jint*nx+j] = inter[jint+Np][j]+orig[1];
      }
      nwrite = fwrite( &hdrs[jint], 1, TRCBYTES, fpint);
      assert(nwrite == TRCBYTES);
      nwrite = fwrite( &data_out[jint*nx], sizeof(float), nx, fpint);
      assert(nwrite == nx);
    }
    fclose(fpint);
    
  } /* end of writing interface file */
  
  if (rayfile == 1) {
    FILE    *fpout, *fpcurve;
    strcpy(filename, file_base);
    strcpy(strrchr(filename, '.'), ".mod");
    
    fpout = fopen(filename, "w+");
    fprintf(fpout,"RAYTRACE MODEL FILE\n");
    fprintf(fpout,"# ASCII file for ray-tracer\n\n");
    fprintf(fpout,"# Top interface\n\n");
    fprintf(fpout,"x=0,%.1f\n", sizex);
    fprintf(fpout,"z=0.,0.\n");
    
    /*		for(i = 1; i <= Np; i++) {
		fprintf(fpout,"\n# %d th interface\n\nx=",i);
		nxp = countnparval(i,"x");
		nzp = countnparval(i,"z");
		free(x);
		free(z);
		x = (float *)malloc(nxp*sizeof(float));
		z = (float *)malloc(nzp*sizeof(float));
		getnparfloat(i,"x",x);
		getnparfloat(i,"z",z);
		for(j = 0; j < (nxp-1); j ++) fprintf(fpout,"%.1f,", x[j]);
		fprintf(fpout,"%.1f\nz=", x[nxp-1]);
		for(j = 0; j < (nxp-1); j ++) fprintf(fpout,"%.1f,", z[j]);
		fprintf(fpout,"%.1f\n", z[nxp-1]);
		}
    */
	for(jint = 0; jint < Np; jint++) {
		fprintf(fpout,"\n# %d th interface\n\nx=0",jint+1);
		sprintf(filename,"curve%d",jint+1);
		fpcurve = fopen(filename, "w+");
		if (verbose) vmess("writing %d th interface to ascii file %s for usage in su(ps/x)image ",jint+1, filename);
		for(j = 0; j < nx; j += skip)  {
			fprintf(fpout,",%.1f", (float)j*dx);
			fprintf(fpcurve,"%.1f %.1f\n", inter[jint][j], orig[0]+(float)j*dx);
		}
		fclose(fpcurve);
      
		fprintf(fpout,"\nz=%.1f", inter[jint][0]);
		for(j = skip; j < nx; j += skip) 
			fprintf(fpout,",%.1f", inter[jint][j]);
		fprintf(fpout,"\n");
	}
	fprintf(fpout,"\n# %d th interface\n\nx=0",jint+1);
    for(j = skip; j < nx; j += skip) 
      fprintf(fpout,",%.1f", (float)j*dx);
    
    fprintf(fpout,"\nz=%.1f", sizez);
    for(j = skip; j < nx; j += skip) 
      fprintf(fpout,",%.1f", sizez);
    fprintf(fpout,"\n");
    
    /**/
    fprintf(fpout,"\n\n");
    fprintf(fpout,"cp=%.1f,", back[0]);
    for(jint = 1; jint <= Np; jint++) {
      aver = 0.0;
      ncp = countnparval(jint,"cp");
      getnparfloat(jint,"cp",cp[2]);
      for(j = 0; j < ncp; j++) 
	aver += cp[2][j];
      aver = aver/((float)ncp);
      if (jint == Np ) fprintf(fpout,"%.1f", aver);
      else fprintf(fpout,"%.1f,", aver);
    }
    
    fclose(fpout);
    free2float(inter);
  }
  
  free(hdrs);
  
  return 0;
}