├── .gitignore ├── README.rst ├── doc └── VFWI_manual.pdf ├── forward ├── .gitignore ├── fwi2d │ ├── __init__.py │ ├── fdtd2D_modelling.c │ ├── fdtd2D_modelling.h │ ├── fwi2d.py │ ├── input_param.txt │ ├── pyacofwi2D.h │ ├── pyacofwi2D.pyx │ ├── run_fwi.py │ ├── setup.cfg │ ├── setup.py │ └── test.py ├── fwi3d │ ├── __init__.py │ ├── dask_utils.py │ ├── fwi3d.py │ └── run_fwi.py └── tomo2d │ ├── Makefile │ ├── fm2d_globalp.f90 │ ├── fm2d_ttime.f90 │ ├── fm2d_wrapper.f90 │ ├── fm2dray.f90 │ ├── loglike.py │ ├── pyfm2d.h │ ├── pyfm2d.pyx │ ├── run_tomo.py │ ├── setup.cfg │ ├── setup.py │ ├── test.py │ └── tomo2d.py ├── setup.py ├── setup.sh ├── tests ├── fwi2d │ ├── config.ini │ ├── input │ │ ├── Uniform_prior.txt │ │ ├── input_params.txt │ │ ├── marmousi_small.txt │ │ └── modelling.py │ ├── run_job.sh │ └── vfwi2d.py ├── fwi3d │ ├── Uniform_prior.txt │ ├── config.ini │ ├── run_job.sh │ └── vfwi3d.py ├── tomo2d │ ├── config.ini │ ├── input │ │ ├── Uniform_prior.txt │ │ ├── receivers.txt │ │ ├── sources.txt │ │ └── ttimes.txt │ ├── run_job.sh │ └── tomo2d.py └── tomo_UK │ ├── config.ini │ ├── input │ ├── Uniform_prior.txt │ ├── otimes.dat │ ├── receivers.txt │ ├── sources.txt │ └── ttimes.txt │ ├── run_job.sh │ └── tomo2d.py └── vip ├── .gitignore ├── __init__.py ├── kernel ├── Makefile ├── __init__.py ├── kernel.f90 ├── kernel.py ├── pykernel.h ├── pykernel.pyx ├── pytrans.h ├── pytrans.pyx ├── setup.cfg ├── setup.py ├── test.py ├── test_kernel.py ├── transform.f90 └── utils.f90 ├── prior ├── pdf.py ├── prior.py └── transform.py └── pyvi ├── __init__.py ├── advi.py ├── optimizer.py └── svgd.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.so 3 | *.vscode 4 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | VIP 3 | =============================== 4 | 5 | Variational Inversion Package, which implements variational methods for geophysical imaging problems, including 6 | seismic travel time tomography and full waveform inversion. 7 | 8 | Authors 9 | ---------- 10 | - Xin Zhang x.zhang2@ed.ac.uk 11 | 12 | Requirements 13 | ------------ 14 | Cython, Dask, H5py 15 | 16 | 17 | Install 18 | ------------ 19 | 20 | In the ``VIP`` folder, run 21 | 22 | 23 | .. code-block:: sh 24 | 25 | sh setup.sh 26 | 27 | This builds up the VIP package, but does not install the package into your Python environment. 28 | As a result, to use the package you need to tell python where the package is. For example, 29 | when running scripts, do 30 | 31 | .. code-block:: python 32 | 33 | PYTHONPATH=/your/VIP/path python vip_example.py 34 | 35 | See examples in ``tests`` folder. Instead you may want to install the package, 36 | 37 | .. code-block:: sh 38 | 39 | sh setup.sh install 40 | 41 | This will install the package into your Python environment, after which the package can be used directly 42 | in your scripts. 43 | 44 | Variational Inversion 45 | --------------------- 46 | This package implements three different variational inference methods: ``ADVI``, 47 | ``SVGD``, and ``stochastic SVGD (sSVGD)``. To use them, 48 | 49 | .. code-block:: python 50 | 51 | from vip.pyvi.svgd import SVGD, sSVGD 52 | from vip.pyvi.advi import ADVI 53 | 54 | All methods require a function that takes model parameters as input and calculates the gradients of logarithm 55 | posterior pdf function w.r.t parameters. For example, 56 | 57 | .. code-block:: python 58 | 59 | def dlnprob(theta): 60 | # theta has a shape of (num_of_particles, num_of_parameters) 61 | # some calculation of theta 62 | return logp, grad, None 63 | 64 | where logp is the logarithm of (unnormalized) posterior pdf value (or negative misfit value), grad is the gradient. The third 65 | output is used to return other auxiliary variables (e.g., a mask array), and can be safely ignored. Thereafter, 66 | 67 | .. code-block:: python 68 | 69 | svgd = SVGD(dlnprob, kernel='rbf') 70 | 71 | This creates a SVGD method which uses radial basis function kernel. To sample the posterior pdf, 72 | 73 | .. code-block:: python 74 | 75 | losses, x = svgd.sample(x0, n_iter=1000, stepsize=0.01, optimizer='sgd') 76 | 77 | where ``x0`` and ``x`` are variables containing starting and final particles with a shape of ``(num_of_particles, num_of_parameters)`` 78 | respectively. This will run the SVGD algorithm for 1,000 iterations using stochastic gradient descent (sgd) algorithm. Supported optimization 79 | algorithms include ``sgd``, ``adagrad``, ``adadelta`` and ``adam``. To use sSVGD algorithm, 80 | 81 | .. code-block:: python 82 | 83 | ssvgd = sSVGD(dlnprob, kernel='rbf') 84 | losses, x = ssvgd.sample(x0, n_iter=2000, stepsize=0.01, burn_in=1000) 85 | 86 | This will sample the posterior using sSVGD method for 2,000 iterations with a burn-in period of 1,000. To use ADVI, 87 | 88 | .. code-block:: python 89 | 90 | advi = ADVI(dlnprob, kernel='meanfield') 91 | losses, phi = advi.sample(n_iter=2000, stepsize=0.01, optimizer='adam') 92 | 93 | This runs mean-field ADVI for 2,000 iterations using the ``adam`` optimization algorithm. The vector ``phi`` contains the mean (first half) 94 | and the logarithm of the standard deviation (second half) of the final Gaussian distribution. To use fullrank ADVI, set kernel to "fullrank". 95 | In this case, assume the number of parameters is n, the first n elements of ``phi`` are the mean, and the rest n^2 elements are the Cholesky 96 | decomposition (L) of the covariance matrix. 97 | 98 | Examples 99 | --------- 100 | - For a complete 2D Full-waveform inversion example, please see the example in ``tests/fwi2d``. 101 | - For a complete 2D travel time tomography example, please see the example in ``tests/tomo2d``. 102 | - For an example implementation of 3D Full-waveform inversion, please see the example in ``tests/fwi3d``. Note 103 | that this requires users to provide an external 3D FWI code to calculate misfit values and gradients. See details 104 | in ``forward/fwi3d``. 105 | 106 | References 107 | ---------- 108 | - Zhang, X., & Curtis, A. (2024). VIP-Variational Inversion Package with example implementations of Bayesian tomographic imaging. Seismica, 3(1). 109 | - Zhang, X., & Curtis, A. (2020). Seismic tomography using variational inference methods. Journal of Geophysical Research: Solid Earth, 125(4), e2019JB018589. 110 | - Zhang, X., Nawaz, M. A., Zhao, X., & Curtis, A. (2021). An introduction to variational inference in geophysical inverse problems. In Advances in Geophysics (Vol. 62, pp. 73-140). Elsevier. 111 | - Zhang, X., Lomas, A., Zhou, M., Zheng, Y., & Curtis, A. (2023). 3-D Bayesian variational full waveform inversion. Geophysical Journal International, 234(1), 546-561. 112 | -------------------------------------------------------------------------------- /doc/VFWI_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin2zhang/VIP/4857809b4d4e774595b08ab1905387d8555b88d1/doc/VFWI_manual.pdf -------------------------------------------------------------------------------- /forward/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.so 3 | __pycache__/ 4 | fwi2d/__pycache__ 5 | fwi2d/*.so 6 | fwi2d/pyacofwi2D.c 7 | fwi2d/*.a 8 | fwi2d/*.o 9 | tomo2d/__pycache__ 10 | tomo2d/*.so 11 | tomo2d/pyfm2d.c 12 | tomo2d/*.a 13 | tomo2d/*.o 14 | fwi3d/__pycache__ 15 | -------------------------------------------------------------------------------- /forward/fwi2d/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin2zhang/VIP/4857809b4d4e774595b08ab1905387d8555b88d1/forward/fwi2d/__init__.py -------------------------------------------------------------------------------- /forward/fwi2d/fdtd2D_modelling.h: -------------------------------------------------------------------------------- 1 | // extern "C" 2 | struct Source 3 | { 4 | int s_iz, s_ix, r_iz, *r_ix, r_n; 5 | int *r_id; 6 | }; 7 | 8 | 9 | // void model_2D(char input_file[200], float *vel_inner); 10 | void getrik(int nt, float dt, float f0, float *rik); 11 | void forward_aco_2D(int is, int nt, int ntx, int ntz, int ntp, int nx, int nz, 12 | int Lc, int pml, int rnmax, int nt_interval, 13 | float dx, float dz, float dt, float f0, float velp_max, float velpaverage, 14 | float *w, float *t11, float *t12, float *t13, float *fd, float *rik, float *velp, 15 | float *p0, float *p1, float *p2, float *psave, float *record, struct Source ss[]); 16 | void backward_aco_2D(int is, int nt, int ntx, int ntz, int ntp, int nx, int nz, 17 | int Lc, int pml, int rnmax, int nt_interval, 18 | float dx, float dz, float dt, float f0, float velp_max, float velpaverage, 19 | float *w, float *t11, float *t12, float *t13, float *fd, float *rik, float *velp, 20 | float *p0, float *p1, float *p2, float *psave, float *record, 21 | float *grad, struct Source ss[]); 22 | void fdtd_2d_calculate_p(int ntx, int ntz, int Lc, int pml, float dx, float dz, float dt, 23 | float *fd, float *velp, float *p0, float *p1, float *p2, 24 | float *w, float *t11, float *t12, float *t13); 25 | void wavefield_IO(int forward_or_backward, int ntx, int ntz, int pml, int nt, int nt_interval, int it, 26 | float dx, float dz, float dt, float *rik, float *velp, 27 | float *p0, float *p1, float *p2, float *psave, float *record, float *grad, 28 | int s_ix, int s_iz, int r_iz, int *r_ix, int r_n); 29 | void forward_IO(int ntx, int ntz, int pml, int nt, int nt_interval, int it, 30 | float dx, float dz, float dt, float *rik, float *velp, 31 | float *p0, float *p1, float *p2, float *psave, float *record, 32 | int s_ix, int s_iz, int r_iz, int *r_ix, int r_n); 33 | void backward_IO(int ntx, int ntz, int pml, int nt, int nt_interval, int it, 34 | float dx, float dz, float dt, float *velp, 35 | float *p0, float *p1, float *p2, float *psave, float *record, float *grad, 36 | int s_ix, int s_iz, int r_iz, int *r_ix, int r_n); 37 | void updata_p(int ntx, int ntz, float *p0, float *p1, float *p2); 38 | 39 | void wavefield_initialization(int ntx, int ntz, float *p0, float *p1, float *p2); 40 | void fd_coefficient(int Lc, float *fd); 41 | void get_velp(int pml, int ntx, int ntz, float *vel_inner, float *velp); 42 | void read_parameters(char inputfile[200], int *nx, int *nz, int *pml0, int *Lc, int *ns, int *nt, int *ds, 43 | int *ns0, int *depths, int *depthr, int *dr, int *nt_interval, 44 | float *dx, float *dz, float *dt, float *f0); 45 | void read_int_value(char strtmp[256], FILE *fp, int *param); 46 | void read_float_value(char strtmp[256], FILE *fp, float *param); 47 | 48 | 49 | -------------------------------------------------------------------------------- /forward/fwi2d/fwi2d.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import time 3 | from forward.fwi2d.run_fwi import run_fwi 4 | 5 | class fwi2d(): 6 | ''' 7 | A class that implements an interface of an external 2D FWI code 8 | ''' 9 | def __init__(self, config, prior, data, mask=None, client=None): 10 | ''' 11 | config: a python configparser.ConfigParser() 12 | prior: a prior class, see prior/prior.py 13 | mask: a mask array where the parameters will be fixed, default no mask 14 | client: a dask client to submit fwi running, must be specified 15 | ''' 16 | 17 | self.config = config 18 | self.sigma = config.getfloat('svgd','sigma') 19 | self.client = client 20 | self.prior = prior 21 | self.data = data 22 | 23 | # create mask matrix for model parameters that are fixed 24 | nz = config.getint('FWI','nz') 25 | nx = config.getint('FWI','nx') 26 | if(mask is None): 27 | mask = np.full((nx*nz),False) 28 | self.mask = mask 29 | 30 | def fwi_gradient(self, theta): 31 | ''' 32 | Call external FWI code to get misfit value and gradient 33 | Note that run_fwi needs to be implemented for specific FWI code 34 | ''' 35 | 36 | # call fwi function, get loss and grad 37 | loss, grad = run_fwi(theta, self.data, self.config, client=self.client) 38 | # update grad 39 | grad[:,self.mask] = 0 40 | g = 1./self.sigma**2 41 | grad *= g 42 | # clip the grad to avoid numerical instability 43 | #clip = self.config.getfloat('FWI','gclipmax') 44 | #grad[grad>=clip] = clip 45 | #grad[grad<=-clip] = -clip 46 | 47 | # log likelihood 48 | return 0.5*loss/self.sigma**2, grad 49 | 50 | def dlnprob(self, theta): 51 | ''' 52 | Compute gradient of log posterior pdf 53 | Input 54 | theta: 2D array with dimension of nparticles*nparameters 55 | Return 56 | lglike: a vector of log likelihood for each particle 57 | grad: each row contains the gradient for each particle 58 | mask: an auxilary mask array for SVGD optimization, can be safely ignored 59 | ''' 60 | 61 | # adjust theta such that it is within prior or transformed back to original space 62 | theta = self.prior.adjust(theta) 63 | 64 | #t = time.time() 65 | loss, grad = self.fwi_gradient(theta) 66 | lglike = -loss + self.prior.lnprob(theta) 67 | #print('Simulation takes '+str(time.time()-t)) 68 | 69 | # compute gradient including the prior 70 | grad, mask = self.prior.grad(theta, grad=grad) 71 | grad[:,self.mask] = 0 72 | print(f'Average loss and negative log posterior: {np.mean(loss)} {np.mean(-lglike)}') 73 | print(f'Max. Mean and Median grad: {np.max(abs(grad))} {np.mean(abs(grad))} {np.median(abs(grad))}') 74 | #print(f'max, mean and median grads after transform: {np.max(abs(grad))} {np.mean(abs(grad))} {np.median(abs(grad))}') 75 | 76 | return lglike, grad, mask 77 | -------------------------------------------------------------------------------- /forward/fwi2d/input_param.txt: -------------------------------------------------------------------------------- 1 | --grid points in x direction (nx) 2 | 200 3 | --grid points in z direction (nz) 4 | 100 5 | --pml points (pml0) 6 | 10 7 | --Finite difference order (Lc) 8 | 3 9 | --Total number of sources (ns) 10 | 1 11 | --Total time steps (nt) 12 | 1000 13 | --Shot interval in grid points (ds) 14 | 10 15 | --Grid number of the first shot to the left of the model (ns0) 16 | 5 17 | --Depth of source in grid points (depths) 18 | 1 19 | --Depth of receiver in grid points (depthr) 20 | 1 21 | --Receiver interval in grid points (dr) 22 | 1 23 | --Time step interval of saved wavefield during forward (nt_interval) 24 | 2 25 | --Grid spacing in x direction (dx) 26 | 10.0 27 | --Grid spacing in z direction (dz) 28 | 10.0 29 | --Time step (dt) 30 | 0.001 31 | --Donimate frequency (f0) 32 | 20.0 -------------------------------------------------------------------------------- /forward/fwi2d/pyacofwi2D.h: -------------------------------------------------------------------------------- 1 | extern 2 | void fwi_2D(char input_file[200], float *vel_inner, float *record_syn, float *record_obs, float *grad, int verbose); 3 | void forward_2D(char input_file[200], float *vel_inner, float *record_syn, int verbose); 4 | -------------------------------------------------------------------------------- /forward/fwi2d/pyacofwi2D.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | from sys import exit 4 | 5 | cdef extern from "pyacofwi2D.h": 6 | void fwi_2D(char input_file[200], float *vel_inner, float *record_syn, float *record_obs, 7 | float *grad, int verbose) 8 | void forward_2D(char input_file[200], float *vel_inner, float *record_syn, int verbose) 9 | 10 | 11 | def fwi(np.ndarray[double, ndim=1, mode="c"] vel not None, 12 | np.ndarray[float, ndim=1, mode="c"] record_obs not None, 13 | paramfile = "./input/input_param.txt", 14 | verbose = 0): 15 | if(np.isnan(vel).any()): 16 | print('NaN occured in python') 17 | exit() 18 | 19 | #np.savetxt('test.txt',vel) 20 | 21 | cdef np.ndarray[float, ndim=1,mode="c"] vel_f = np.zeros(vel.shape[0], dtype=np.float32) 22 | vel_f = np.float32(vel) 23 | # cdef np.ndarray[float, ndim=1,mode="c"] record_obs_f = np.zeros(record_obs.shape[0], dtype=np.float32) 24 | # record_obs_f = np.float32(record_obs) 25 | 26 | cdef np.ndarray[float, ndim=1, mode="c"] grad = np.zeros(vel_f.shape[0],dtype=np.float32) 27 | cdef np.ndarray[float, ndim=1, mode="c"] record_syn = np.zeros(record_obs.shape[0],dtype=np.float32) 28 | 29 | fwi_2D(str.encode(paramfile), &vel_f[0], &record_syn[0], &record_obs[0], &grad[0], verbose) 30 | 31 | return record_syn, grad 32 | 33 | 34 | def forward(np.ndarray[double, ndim=1, mode="c"] vel not None, 35 | dim = 1, 36 | paramfile = "./input/input_param.txt", 37 | verbose = 0): 38 | if(np.isnan(vel).any()): 39 | print('NaN occured in python') 40 | exit() 41 | 42 | cdef np.ndarray[float, ndim=1,mode="c"] vel_f = np.zeros(vel.shape[0], dtype=np.float32) 43 | vel_f = np.float32(vel) 44 | 45 | cdef np.ndarray[float, ndim=1, mode="c"] record_syn = np.zeros(dim, dtype=np.float32) 46 | 47 | forward_2D(str.encode(paramfile), &vel_f[0], &record_syn[0], verbose) 48 | 49 | return record_syn 50 | -------------------------------------------------------------------------------- /forward/fwi2d/run_fwi.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from forward.fwi2d.aco2d import fwi 3 | 4 | def prepare_config(config): 5 | 6 | paramfile = config.get('FWI','configfile') 7 | with open(paramfile,'w') as f: 8 | f.write('--grid points in x direction (nx)\n') 9 | f.write(config.get('FWI','nx')+'\n') 10 | f.write('--grid points in z direction (nz)\n') 11 | f.write(config.get('FWI','nz')+'\n') 12 | f.write('--pml points (pml0)\n') 13 | f.write(config.get('FWI','pml')+'\n') 14 | f.write('--Finite difference order (Lc)\n') 15 | f.write(config.get('FWI','Lc')+'\n') 16 | f.write('--Total number of sources (ns)\n') 17 | f.write(config.get('FWI','ns')+'\n') 18 | f.write('--Total time steps (nt)\n') 19 | f.write(config.get('FWI','nt')+'\n') 20 | f.write('--Shot interval in grid points (ds)\n') 21 | f.write(config.get('FWI','ds')+'\n') 22 | f.write('--Grid number of the first shot to the left of the model (ns0)\n') 23 | f.write(config.get('FWI','ns0')+'\n') 24 | f.write('--Depth of source in grid points (depths)\n') 25 | f.write(config.get('FWI','depths')+'\n') 26 | f.write('--Depth of receiver in grid points (depthr)\n') 27 | f.write(config.get('FWI','depthr')+'\n') 28 | f.write('--Receiver interval in grid points (dr)\n') 29 | f.write(config.get('FWI','dr')+'\n') 30 | f.write('--Time step interval of saved wavefield during forward (nt_interval)\n') 31 | f.write(config.get('FWI','nt_interval')+'\n') 32 | f.write('--Grid spacing in x direction (dx)\n') 33 | f.write(config.get('FWI','dx')+'\n') 34 | f.write('--Grid spacing in z direction (dz)\n') 35 | f.write(config.get('FWI','dz')+'\n') 36 | f.write('--Time step (dt)\n') 37 | f.write(config.get('FWI','dt')+'\n') 38 | f.write('--Donimate frequency (f0)\n') 39 | f.write(config.get('FWI','f0')+'\n') 40 | 41 | return 42 | 43 | def run_fwi_i(theta, data, config): 44 | 45 | vp = theta.astype('float64') 46 | paramfile = config.get('FWI','configfile') 47 | rec, grad = fwi(vp, data, paramfile=paramfile) 48 | 49 | loss = np.sum((rec-data)**2) 50 | 51 | return loss, grad 52 | 53 | def run_fwi(models, data, config, client=None): 54 | ''' 55 | Call 2d fwi code to calculate loss and gradients 56 | Input 57 | models: velocity models, shape (n, ndim) 58 | data: waveform data 59 | config: configparser.ConfigParser() 60 | client: dask client to submit fwi calculation 61 | Return 62 | loss: loss value of each particle, shape (n,) 63 | grad: gradient of loss function w.r.t velocity, shape (n, ndim) 64 | ''' 65 | 66 | # prepare configure file for 2d fwi code 67 | prepare_config(config) 68 | 69 | # submit fwi calculation to dask cluster for each model in models 70 | futures = [] 71 | data_future = client.scatter(data) 72 | for i in range(models.shape[0]): 73 | futures.append( client.submit(run_fwi_i, models[i,:], data_future, config, pure=False) ) 74 | 75 | results = client.gather(futures) 76 | 77 | loss = np.zeros((models.shape[0],)) 78 | grad = np.zeros_like(models) 79 | for i in range(models.shape[0]): 80 | loss[i] = results[i][0] 81 | grad[i,:] = results[i][1] 82 | 83 | return loss, grad 84 | 85 | -------------------------------------------------------------------------------- /forward/fwi2d/setup.cfg: -------------------------------------------------------------------------------- 1 | [build_ext] 2 | force=1 3 | -------------------------------------------------------------------------------- /forward/fwi2d/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | from distutils.extension import Extension 3 | from Cython.Distutils import build_ext 4 | import numpy 5 | from os import system 6 | npy_include_dir = numpy.get_include() 7 | 8 | ext_modules = [Extension("aco2d", ["pyacofwi2D.pyx", "fdtd2D_modelling.c"], 9 | include_dirs = [npy_include_dir], 10 | language='c', 11 | extra_compile_args=["-fopenmp"], 12 | extra_link_args=["-fopenmp"], 13 | #libraries=["gcc"], 14 | #extra_objects=["fdtd2D_modelling.o"] 15 | )] 16 | 17 | setup(name = 'acousticfwi2D', 18 | cmdclass = {'build_ext': build_ext}, 19 | ext_modules = ext_modules) 20 | 21 | system('rm -rf build') 22 | -------------------------------------------------------------------------------- /forward/fwi2d/test.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.environ["OMP_NUM_THREADS"] = "1" 3 | 4 | import numpy as np 5 | import aco2d 6 | import matplotlib.pyplot as plt 7 | import multiprocessing as mp 8 | #from torch.multiprocessing import Pool, Process 9 | import time 10 | 11 | def gradient(vel): 12 | # vel = vel.astype(np.float64) 13 | data = aco2d.forward(vel, dim = 1*1001*200, verbose = 0, paramfile='./input_param.txt') 14 | 15 | return data 16 | 17 | ns = 1 18 | 19 | vel = np.full((200*100,), 2000.0) 20 | vel[50*100:] = 2500.0 21 | vel[100*100:] = 3000.0 22 | 23 | rec = aco2d.forward(vel, dim = ns*1001*200, verbose = 0, paramfile='./input_param.txt') 24 | 25 | plt.figure() 26 | # plt.imshow(rec.reshape(-1, 200)) 27 | plt.imshow(rec.reshape(ns, 1001, 200).transpose(1, 0, 2).reshape(1001, -1), clim=(-0.3, 0.3)) 28 | plt.show() 29 | 30 | #np.savetxt('./input/shotrecord.txt', rec) 31 | # # print(rec.shape) 32 | 33 | # record = np.loadtxt('./input/shotrecord.txt', dtype=np.float32) 34 | 35 | vel = np.full((200*100,), 2000.0) 36 | vel[50*100:] = 2300.0 37 | vel[100*100:] = 2700.0 38 | # vel = np.repeat(vel[None, :], 12, axis=0) 39 | # print(vel.shape) 40 | start = time.time() 41 | 42 | # pool = Pool(processes = 6) 43 | # results = pool.map(gradient, [vel[i,:].squeeze() for i in range(6)]) 44 | # pool.close() 45 | # pool.join() 46 | data, grad = aco2d.fwi(vel, rec, verbose = 0, paramfile='./input_param.txt') 47 | 48 | end = time.time() 49 | print('The test time is: ', end-start) 50 | 51 | plt.figure() 52 | plt.imshow(data.reshape(ns, 1001, 200).transpose(1, 0, 2).reshape(1001, -1), clim=(-0.3, 0.3)) 53 | plt.show() 54 | 55 | plt.figure() 56 | plt.imshow(grad.reshape(-1, 200)) 57 | plt.show() 58 | -------------------------------------------------------------------------------- /forward/fwi3d/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin2zhang/VIP/4857809b4d4e774595b08ab1905387d8555b88d1/forward/fwi3d/__init__.py -------------------------------------------------------------------------------- /forward/fwi3d/dask_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import dask 3 | from dask_jobqueue import SGECluster 4 | from dask.distributed import Client, LocalCluster 5 | import time 6 | import shutil 7 | 8 | 9 | def dask_local(nworkers, ph=1, odask='./dask/'): 10 | ''' 11 | Create a local dask cluster 12 | Input 13 | nworkers: number of dask workers 14 | ph: number of threads per worker 15 | odask: directory to store temporary dask file 16 | Return 17 | dask cluster and client 18 | ''' 19 | if not os.path.exists(odask): 20 | os.makedir(odask) 21 | dask.config.set(temporary_directory=odask) 22 | 23 | cluster = LocalCluster(n_workers=nworkers, threads_per_worker=ph) 24 | client = Client(cluster) 25 | 26 | return cluster, client 27 | 28 | # submit a dask job 29 | def dask_init(pe, nnodes, nworkers=1, ph=1, 30 | cores_per_node=36, memory_per_node='500 GiB', odask='./dask/'): 31 | ''' 32 | Initialise a dask cluster using SGE queue system 33 | Input 34 | pe: parallel environment on a hpc 35 | nnodes: number of nodes required 36 | nworkers: number of dask workers 37 | ph: number of processes per worker 38 | odask: directory to store temporary dask file 39 | Return 40 | dask cluster and client 41 | ''' 42 | os.chdir(odask) 43 | dask.config.set(temporary_directory=odask) 44 | 45 | # change for sepcific hpc facility 46 | num_of_cores = nnodes * cores_per_node 47 | runtime_limit = '800:00:00' 48 | project_name = 'attributes' 49 | 50 | cluster = SGECluster( 51 | processes = ph, # number of workers per job 52 | cores = ph, # make sure nthreads == 1, each dask worker forks one thread 53 | scheduler_options={"dashboard_address":":0"}, 54 | job_extra = ['-pe {} {}'.format(pe, num_of_cores), '-cwd', '-j y', '-V'], 55 | memory = memory_per_node, 56 | project = project_name, 57 | walltime = runtime_limit 58 | ) 59 | 60 | # get a client 61 | client = Client(cluster) 62 | 63 | # scale up 64 | total_workers = nworkers*ph 65 | cluster.scale(total_workers) 66 | print(cluster.job_script()) 67 | 68 | while client.status == "running" and len(client.scheduler_info()['workers'])/ph < nworkers: 69 | time.sleep(1.0) 70 | 71 | return cluster, client 72 | 73 | 74 | # remove a dask job as well as tmp directory 75 | def dask_del(cluster, client, odask='./dask/'): 76 | client.close() 77 | cluster.close() 78 | # delete all dask file 79 | for file in os.listdir(odask): 80 | file_path = os.path.join(odask, file) 81 | try: 82 | if os.path.isfile(file_path): 83 | os.unlink(file_path) 84 | elif os.path.isdir(file_path): shutil.rmtree(file_path) 85 | except Exception as e: 86 | print(e) 87 | 88 | -------------------------------------------------------------------------------- /forward/fwi3d/fwi3d.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import time 3 | from forward.fwi3d.run_fwi import run_fwi 4 | 5 | class fwi3d(): 6 | ''' 7 | A class that implements an interface of an external 3D FWI code 8 | ''' 9 | def __init__(self, config, prior, mask=None, client=None): 10 | ''' 11 | config: a python configparser.ConfigParser() 12 | prior: a prior class, see prior/prior.py 13 | mask: a mask array where the parameters will be fixed, default no mask 14 | client: a dask client to submit fwi running, must be specified 15 | ''' 16 | 17 | self.config = config 18 | self.sigma = config.getfloat('svgd','sigma') 19 | self.client = client 20 | self.prior = prior 21 | 22 | # create mask matrix for model parameters that are fixed 23 | nx = config.getint('svgd','nx') 24 | ny = config.getint('svgd','ny') 25 | nz = config.getint('svgd','nz') 26 | if(mask is None): 27 | mask = np.full((ny*nx*nz),False) 28 | self.mask = mask 29 | 30 | def fwi_gradient(self, theta): 31 | ''' 32 | Call external FWI code to get misfit value and gradient 33 | Note that run_fwi needs to be implemented for specific FWI code 34 | ''' 35 | 36 | # call fwi function, get loss and grad 37 | loss, grad = run_fwi(theta, self.config, client=self.client) 38 | # update grad 39 | grad[:,self.mask] = 0 40 | g = -1./(theta**3*self.sigma**2) 41 | grad *= g 42 | # clip the grad to avoid numerical instability 43 | clip = self.config.getfloat('FWI','gclipmax') 44 | #clip = clip * np.quantile(np.abs(grad),0.999) 45 | grad[grad>=clip] = clip 46 | grad[grad<=-clip] = -clip 47 | 48 | # log likelihood 49 | return 0.5*loss/self.sigma**2, grad 50 | 51 | def dlnprob(self, theta): 52 | ''' 53 | Compute gradient of log posterior pdf 54 | Input 55 | theta: 2D array with dimension of nparticles*nparameters 56 | Return 57 | lglike: a vector of log likelihood for each particle 58 | grad: each row contains the gradient for each particle 59 | mask: an auxilary mask array for SVGD optimization, can be safely ignored 60 | ''' 61 | 62 | # adjust theta such that it is within prior or transformed back to original space 63 | theta = self.prior.adjust(theta) 64 | 65 | t = time.time() 66 | loss, grad = self.fwi_gradient(theta) 67 | lglike = -loss + self.prior.lnprob(theta) 68 | print('Simulation takes '+str(time.time()-t)) 69 | 70 | # compute gradient including the prior 71 | grad, mask = self.prior.grad(theta, grad=grad) 72 | grad[:,self.mask] = 0 73 | print(f'Average loss and negative log posterior: {np.mean(loss)} {np.mean(-lglike)}') 74 | print(f'Max. Mean and Median grad: {np.max(abs(grad))} {np.mean(abs(grad))} {np.median(abs(grad))}') 75 | #print(f'max, mean and median grads after transform: {np.max(abs(grad))} {np.mean(abs(grad))} {np.median(abs(grad))}') 76 | 77 | return lglike, grad, mask 78 | -------------------------------------------------------------------------------- /forward/fwi3d/run_fwi.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import subprocess 3 | import os.path 4 | import re 5 | from pathlib import Path 6 | 7 | def argmap(key, settings): 8 | return key+"="+settings[key] 9 | 10 | def prepare_models(theta, nx, ny, nz, datapath='./', fname='particles', sep='_'): 11 | 12 | nparticles = theta.shape[0] 13 | for i in range(nparticles): 14 | filename = os.path.join(datapath,fname+sep+str(i)+'.npy') 15 | model = theta[i,:].reshape((ny,nx,nz)) 16 | np.save(filename,model) 17 | 18 | return 0 19 | 20 | def prepare_batch(batch, datapath='input', srcfile='input/source.npy', datafile='input/data.npy'): 21 | 22 | shots = np.load(srcfile) 23 | shotsize = shots.shape[0] 24 | slices = np.sort(np.random.choice(shotsize,size=batch,replace=False)) 25 | batch_shots = shots[slices,:,] 26 | batch_src = os.path.join(datapath,'batch_src.npy') 27 | np.save(batch_src,batch_shots) 28 | 29 | data = np.load(datafile) 30 | batch_data = data[slices,:,:] 31 | batch_file = os.path.join(datapath,'batch_data.npy') 32 | np.save(batch_file, batch_data) 33 | 34 | return shotsize*1./batch 35 | 36 | def cal_loss(pred_file, data_file='input/batch_data.npy'): 37 | pred_data = np.load(pred_file) 38 | data = np.load(data_file) 39 | res = pred_data - data 40 | loss = np.sum(res**2) 41 | 42 | return loss 43 | 44 | def run_fwi_i(i, config): 45 | options =['waveletfile', 'recfile'] 46 | args = [] 47 | settings = config['FWI'] 48 | args.append("/home/xzhang/fwi/bin/fwi") 49 | for op in options: 50 | args.append(argmap(op,settings)) 51 | args.append("data="+os.path.join(settings['inpath'],'batch_data.npy')) 52 | args.append("src="+os.path.join(settings['inpath'],'batch_src.npy')) 53 | 54 | #print(*args, sep=" ") 55 | try: 56 | subprocess.check_output(args, stderr=subprocess.STDOUT, shell=False, timeout=1200) 57 | except subprocess.CalledProcessError as e: 58 | print(e.output) 59 | except subprocess.TimeoutExpired: 60 | subprocess.check_output(args, stderr=subprocess.STDOUT, shell=False, timeout=1200) 61 | 62 | grad = np.load(os.path.join(settings['outpath'],'gradout_'+str(i)+'.npy')) 63 | loss = cal_loss(os.path.join(settings['outpath'],'pred_data_'+str(i)+'.npy'), 64 | os.path.join(settings['inpath'],'batch_data.npy')) 65 | 66 | return loss, grad.flatten() 67 | 68 | def run_fwi(models, config, client=None): 69 | # get model info from config 70 | nx = config.getint('svgd','nx') 71 | ny = config.getint('svgd','ny') 72 | nz = config.getint('svgd','nz') 73 | dx = config.getfloat('svgd','dx') 74 | dy = config.getfloat('svgd','dy') 75 | dz = config.getfloat('svgd','dz') 76 | batch = config.getint('svgd','shot_batch') 77 | datapath=config.get('FWI','inpath') 78 | 79 | # prepare velocity models for FWI code (revise for sepcific code) 80 | prepare_models(models,ny,nx,nz,datapath=datapath) 81 | scale = prepare_batch(batch, datapath=datapath, srcfile=config.get('FWI','srcfile'), datafile=config.get('FWI','datafile')) 82 | 83 | # submit external FWI code to dask cluster for each model in models 84 | futures = [] 85 | for i in range(models.shape[0]): 86 | futures.append( client.submit(run_fwi_i, i, config, pure=False) ) 87 | 88 | results = client.gather(futures) 89 | 90 | loss = np.zeros((models.shape[0],)) 91 | grad = np.zeros_like(models) 92 | for i in range(models.shape[0]): 93 | loss[i] = results[i][0] 94 | grad[i,:] = results[i][1] 95 | 96 | return loss, grad*scale 97 | -------------------------------------------------------------------------------- /forward/tomo2d/Makefile: -------------------------------------------------------------------------------- 1 | # List of source file 2 | OBJ = fm2d_globalp.o fm2d_ttime.o fm2dray.o fm2d_wrapper.o 3 | F90 = gfortran 4 | LIKE2D_LIB = libfmm2d.a 5 | AR = ar -r 6 | FFLAGS += -fPIC -fopenmp 7 | #FFLAGS += -O0 -g -Wall -Wtabs -Wextra -Wconversion -fimplicit-none -fbacktrace -fcheck=all -ffpe-trap=zero,overflow,underflow -finit-real=nan 8 | 9 | # rule for building foward modeling code 10 | $(LIKE2D_LIB): $(OBJ) 11 | $(AR) $@ $^ 12 | 13 | # rule for building object file 14 | %.o: %.f90 15 | $(F90) $(FFLAGS) -c $< -o $@ 16 | 17 | %.o: %.cpp 18 | $(CC) $(CFLAGS) -c $< -o $@ 19 | 20 | .PHONY: clean cleanall 21 | 22 | clean: 23 | rm -f *.o *.mod 24 | 25 | cleanall: clean 26 | rm -f *.a 27 | -------------------------------------------------------------------------------- /forward/tomo2d/fm2d_globalp.f90: -------------------------------------------------------------------------------- 1 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2 | ! TYPE: MODULE 3 | ! CODE: FORTRAN 90 4 | ! This module declares variable for global use, that is, for 5 | ! USE in any subroutine or function or other module. 6 | ! Variables whose values are SAVEd can have their most 7 | ! recent values reused in any routine. 8 | ! TODO: Since this code will be called many times, global variables 9 | ! are certaintly not suggested 10 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 11 | 12 | MODULE globalp 13 | use iso_c_binding 14 | IMPLICIT NONE 15 | INTEGER, PARAMETER :: i10= c_double 16 | INTEGER, PARAMETER :: i5=SELECTED_REAL_KIND(5,10) 17 | INTEGER :: checkstat 18 | INTEGER, SAVE :: nvx,nvz,nnx,nnz,nrc,fom,gdx,gdz 19 | INTEGER, SAVE :: vnl,vnr,vnt,vnb,nrnx,nrnz,sgdl,rbint 20 | INTEGER, SAVE :: nnxr,nnzr,asgr 21 | INTEGER, SAVE :: ntt 22 | INTEGER, DIMENSION (:,:), ALLOCATABLE :: nsts,nstsr,srs 23 | REAL(KIND=i10), SAVE :: gox,goz,dnx,dnz,dvx,dvz,snb,earth 24 | REAL(KIND=i10), SAVE :: goxd,gozd,dvxd,dvzd,dnxd,dnzd 25 | REAL(KIND=i10), SAVE :: drnx,drnz,gorx,gorz 26 | REAL(KIND=i10), SAVE :: dnxr,dnzr,goxr,gozr 27 | REAL(KIND=i10), DIMENSION (:,:), ALLOCATABLE :: velv,veln,velnb 28 | REAL(KIND=i10), DIMENSION (:,:), ALLOCATABLE :: ttn,ttnr 29 | REAL(KIND=i10), DIMENSION (:), ALLOCATABLE :: rcx,rcz 30 | REAL(KIND=i10), PARAMETER :: pi=3.1415926535898 31 | 32 | INTEGER, DIMENSION (:,:), ALLOCATABLE :: srsv 33 | INTEGER, DIMENSION (:,:), ALLOCATABLE :: npts 34 | REAL(KIND=i5), DIMENSION (:,:), ALLOCATABLE :: raypts 35 | INTEGER :: crazyrp 36 | 37 | ! make all module variable thread private to parallel 38 | !$omp threadprivate (checkstat, nvx,nvz,nnx,nnz,nrc,fom,gdx,gdz, & 39 | !$omp vnl,vnr,vnt,vnb,nrnx,nrnz,sgdl,rbint, nnxr, nnzr, asgr, & 40 | !$omp ntt, nsts, nstsr, srs, gox, goz, dnx, dnz, dvx, dvz, snb, earth, & 41 | !$omp goxd, gozd, dvxd, dvzd, dnxd, dnzd, drnx, drnz, gorx, gorz, & 42 | !$omp dnxr, dnzr, goxr, gozr, velv, veln, velnb, ttn, ttnr, rcx, rcz, & 43 | !$omp srsv, npts, raypts, crazyrp) 44 | 45 | ! 46 | ! nvx,nvz = B-spline vertex values 47 | ! dvx,dvz = B-spline vertex separation 48 | ! velv(i,j) = velocity values at control points 49 | ! nnx,nnz = Number of nodes of grid in x and z 50 | ! nnxr,nnzr = Number of nodes of refined grid in x and z 51 | ! gox,goz = Origin of grid (theta,phi) 52 | ! goxr, gozr = Origin of refined grid (theta,phi) 53 | ! dnx,dnz = Node separation of grid in x and z 54 | ! dnxr,dnzr = Node separation of refined grid in x and z 55 | ! veln(i,j) = velocity values on a refined grid of nodes 56 | ! velnb(i,j) = Backup of veln required for source grid refinement 57 | ! ttn(i,j) = traveltime field on the refined grid of nodes 58 | ! ttnr(i,j) = ttn for refined grid 59 | ! nsts(i,j) = node status (-1=far,0=alive,>0=close) 60 | ! nstsr(i,j) = nsts for refined grid 61 | ! checkstat = check status of memory allocation 62 | ! fom = use first-order(0) or mixed-order(1) scheme 63 | ! snb = Maximum size of narrow band as fraction of nnx*nnz 64 | ! nrc = number of receivers 65 | ! rcx(i),rcz(i) = (x,z) coordinates of receivers 66 | ! earth = radius of Earth (in km) 67 | ! goxd,gozd = gox,goz in degrees 68 | ! dvxd,dvzd = dvx,dvz in degrees 69 | ! dnzd,dnzd = dnx,dnz in degrees 70 | ! gdx,gdz = grid dicing in x and z 71 | ! vnl,vnr,vnb,vnt = Bounds of refined grid 72 | ! nrnx,nrnz = Number of nodes in x and z for refined grid 73 | ! gorx,gorz = Grid origin of refined grid 74 | ! sgdl = Source grid dicing level 75 | ! rbint = Ray-boundary intersection (0=no, 1=yes). 76 | ! asgr = Apply source grid refinement (0=no,1=yes) 77 | ! srs = Source-receiver status (0=no path, 1=path exists) 78 | ! 79 | END MODULE globalp 80 | -------------------------------------------------------------------------------- /forward/tomo2d/fm2d_wrapper.f90: -------------------------------------------------------------------------------- 1 | ! wrapper to c 2 | module fm2d_wrapper 3 | 4 | use iso_c_binding, only : c_double, c_int 5 | use omp_lib 6 | 7 | implicit none 8 | 9 | contains 10 | 11 | subroutine fm2d(nsrc,srcx,srcy, & 12 | nrec, recx, recy, mask, & 13 | nx, ny, xmin, ymin, dx, dy, & 14 | gdx, gdy, sdx, sext, vel, time, dtdv,earth) 15 | use m_fm2d, only : modrays, T_RAY 16 | integer(c_int), intent(in) :: nsrc 17 | real(kind=c_double), dimension(:), intent(in) :: srcx 18 | real(kind=c_double), dimension(:), intent(in) :: srcy 19 | integer(c_int), intent(in) :: nrec 20 | real(kind=c_double), dimension(:), intent(in) :: recx 21 | real(kind=c_double), dimension(:), intent(in) :: recy 22 | integer(c_int), dimension(:,:), intent(in) :: mask 23 | integer(c_int), intent(in) :: nx, ny 24 | real(kind=c_double), intent(in) :: xmin, ymin 25 | real(kind=c_double), intent(in) :: dx, dy 26 | integer(c_int), intent(in) :: gdx, gdy 27 | integer(c_int), intent(in) :: sdx, sext 28 | real(kind=c_double), dimension(:,:), intent(in) :: vel 29 | real(kind=c_double), dimension(:,:), intent(inout) :: time 30 | real(kind=c_double), dimension(:,:,:,:), intent(out) :: dtdv 31 | real(kind=c_double), intent(in) :: earth 32 | 33 | !real(kind=c_double), parameter :: earth = 6371 34 | integer :: crazyray 35 | type(T_RAY), dimension(:),allocatable :: rays 36 | real(kind=c_double) :: band 37 | 38 | !write(*,*) srcx 39 | !write(*,*) srcy 40 | !write(*,*) xmin,ymin 41 | !write(*,*) nx,ny 42 | !write(*,*) vel 43 | allocate(rays(nsrc*nrec)) 44 | crazyray = 0 45 | band = 0.8 46 | time = 0.0 47 | dtdv = 0 48 | call modrays(nsrc,srcx,srcy,nrec,recx,recy, & 49 | mask,0,nx,ny,xmin,ymin,dx,dy,vel,& 50 | gdx,gdy,1,sdx,sext,earth, 1, band, time, & 51 | rays,dtdv,crazyray,0) 52 | 53 | end subroutine 54 | 55 | subroutine c_fm2d(nsrc,srcx,srcy,nrec,recx,recy,nx,ny,mask,& 56 | xmin,ymin,dx,dy,gdx,gdy,sdx, sext, vel,time,dtdv,earth) bind(c) 57 | integer(c_int), intent(in) :: nsrc 58 | real(kind=c_double), intent(in) :: srcx(nsrc) 59 | real(kind=c_double), intent(in) :: srcy(nsrc) 60 | integer(c_int), intent(in) :: nrec 61 | real(kind=c_double), intent(in) :: recx(nrec) 62 | real(kind=c_double), intent(in) :: recy(nrec) 63 | integer(c_int), intent(in) :: mask(nrec*nsrc,2) 64 | integer(c_int), intent(in) :: nx, ny 65 | real(kind=c_double), intent(in) :: xmin, ymin 66 | real(kind=c_double), intent(in) :: dx, dy 67 | integer(c_int), intent(in) :: gdx, gdy 68 | integer(c_int), intent(in) :: sdx, sext 69 | real(kind=c_double), intent(in) :: vel(ny,nx) 70 | real(kind=c_double), intent(out) :: time(nrec,nsrc) 71 | real(kind=c_double), intent(out) :: dtdv(ny,nx,nrec,nsrc) 72 | real(kind=c_double), intent(in) :: earth 73 | 74 | call fm2d(nsrc,srcx,srcy,nrec,recx,recy,mask,& 75 | nx,ny,xmin,ymin,dx,dy,gdx,gdy,sdx, sext, vel,& 76 | time,dtdv,earth) 77 | 78 | end subroutine 79 | 80 | subroutine c_fm2d_parallel(nsrc,srcx,srcy,nrec,recx,recy,nx,ny,mask,& 81 | xmin,ymin,dx,dy,gdx,gdy,sdx, sext,nv,vel,times,earth) bind(c) 82 | integer(c_int), intent(in) :: nsrc 83 | real(kind=c_double), intent(in) :: srcx(nsrc) 84 | real(kind=c_double), intent(in) :: srcy(nsrc) 85 | integer(c_int), intent(in) :: nrec 86 | real(kind=c_double), intent(in) :: recx(nrec) 87 | real(kind=c_double), intent(in) :: recy(nrec) 88 | integer(c_int), intent(in) :: mask(nrec*nsrc,2) 89 | integer(c_int), intent(in) :: nx, ny 90 | real(kind=c_double), intent(in) :: xmin, ymin 91 | real(kind=c_double), intent(in) :: dx, dy 92 | integer(c_int), intent(in) :: gdx, gdy 93 | integer(c_int), intent(in) :: sdx, sext 94 | integer(c_int), intent(in) :: nv 95 | real(kind=c_double), intent(in) :: vel(ny,nx,nv) 96 | real(kind=c_double), intent(out) :: times(nrec*nsrc,nv) 97 | real(kind=c_double), intent(in) :: earth 98 | 99 | real(kind=c_double) :: time(nrec,nsrc) 100 | real(kind=c_double), dimension(:,:,:,:), allocatable :: dtdv 101 | integer i, j 102 | 103 | allocate(dtdv(ny,nx,nrec,nsrc)) 104 | !$omp parallel 105 | !$omp do private(time,dtdv,i,j) 106 | do i = 1, nv 107 | call fm2d(nsrc,srcx,srcy,nrec,recx,recy,mask,& 108 | nx,ny,xmin,ymin,dx,dy,gdx,gdy,sdx, sext, vel(:,:,i),& 109 | time,dtdv,earth) 110 | times(:,i)= reshape(time,(/nrec*nsrc/)) 111 | enddo 112 | !$omp end do 113 | !$omp end parallel 114 | 115 | end subroutine 116 | 117 | subroutine c_fm2d_lglike(nsrc,srcx,srcy,nrec,recx,recy,nx,ny,mask,& 118 | xmin,ymin,dx,dy,gdx,gdy,sdx, sext,nv,vel,tobs,lglike,grads,earth) bind(c) 119 | integer(c_int), intent(in) :: nsrc 120 | real(kind=c_double), intent(in) :: srcx(nsrc) 121 | real(kind=c_double), intent(in) :: srcy(nsrc) 122 | integer(c_int), intent(in) :: nrec 123 | real(kind=c_double), intent(in) :: recx(nrec) 124 | real(kind=c_double), intent(in) :: recy(nrec) 125 | integer(c_int), intent(in) :: mask(nrec*nsrc,2) 126 | integer(c_int), intent(in) :: nx, ny 127 | real(kind=c_double), intent(in) :: xmin, ymin 128 | real(kind=c_double), intent(in) :: dx, dy 129 | integer(c_int), intent(in) :: gdx, gdy 130 | integer(c_int), intent(in) :: sdx, sext 131 | integer(c_int), intent(in) :: nv 132 | real(kind=c_double), intent(in) :: vel(ny,nx,nv) 133 | real(kind=c_double), intent(in) :: tobs(2,nrec*nsrc) 134 | real(kind=c_double), intent(out) :: lglike(nv) 135 | real(kind=c_double), intent(out) :: grads(ny*nx,nv) 136 | real(kind=c_double), intent(in) :: earth 137 | 138 | real(kind=c_double) :: time(nrec,nsrc), time1d(nrec*nsrc) 139 | real(kind=c_double), dimension(:,:,:,:), allocatable :: dtdv 140 | real(kind=c_double), dimension(:,:), allocatable :: dtdv2d 141 | integer i, j 142 | 143 | allocate(dtdv(ny,nx,nrec,nsrc)) 144 | allocate(dtdv2d(ny*nx,nrec*nsrc)) 145 | lglike = 0. 146 | grads = 0 147 | !$omp parallel 148 | !$omp do private(time,time1d,dtdv,dtdv2d,i,j) 149 | do i = 1, nv 150 | call fm2d(nsrc,srcx,srcy,nrec,recx,recy,mask,& 151 | nx,ny,xmin,ymin,dx,dy,gdx,gdy,sdx, sext, vel(:,:,i),& 152 | time,dtdv,earth) 153 | time1d = reshape(time,(/nrec*nsrc/)) 154 | dtdv2d = reshape(dtdv,(/ny*nx,nrec*nsrc/)) 155 | lglike(i) = 0.5*sum((tobs(1,:)-time1d)**2/tobs(2,:)**2) 156 | do j = 1, nrec*nsrc 157 | grads(:,i) = grads(:,i) + dtdv2d(:,j)*(tobs(1,j)-time1d(j))/tobs(2,j)**2 158 | enddo 159 | enddo 160 | !$omp end do 161 | !$omp end parallel 162 | 163 | end subroutine 164 | 165 | subroutine c_many_fm2d(nsrc,srcx,srcy,nrec,recx,recy,nx,ny,& 166 | xmin,ymin,dx,dy,gdx,gdy,sdx,sext,nv,vel,tobs,mask,lglike,grads,earth) bind(c) 167 | integer(c_int), intent(in) :: nsrc 168 | real(kind=c_double), intent(in) :: srcx(nsrc) 169 | real(kind=c_double), intent(in) :: srcy(nsrc) 170 | integer(c_int), intent(in) :: nrec 171 | real(kind=c_double), intent(in) :: recx(nrec) 172 | real(kind=c_double), intent(in) :: recy(nrec) 173 | integer(c_int), intent(in) :: nx, ny 174 | real(kind=c_double), intent(in) :: xmin, ymin 175 | real(kind=c_double), intent(in) :: dx, dy 176 | integer(c_int), intent(in) :: gdx, gdy 177 | integer(c_int), intent(in) :: sdx, sext 178 | integer(c_int), intent(in) :: nv 179 | real(kind=c_double), intent(in) :: vel(ny,nx,nv) 180 | real(kind=c_double), intent(in) :: tobs(2,nrec*nsrc,nv) 181 | integer(c_int), intent(in) :: mask(2,nrec*nsrc,nv) 182 | real(kind=c_double), intent(out) :: lglike(nv) 183 | real(kind=c_double), intent(out) :: grads(ny*nx,nv) 184 | real(kind=c_double), intent(in) :: earth 185 | 186 | real(kind=c_double) :: time(nrec,nsrc), time1d(nrec*nsrc) 187 | real(kind=c_double), dimension(:,:,:,:), allocatable :: dtdv 188 | real(kind=c_double), dimension(:,:), allocatable :: dtdv2d 189 | integer i, j 190 | 191 | allocate(dtdv(ny,nx,nrec,nsrc)) 192 | allocate(dtdv2d(ny*nx,nrec*nsrc)) 193 | lglike = 0. 194 | grads = 0 195 | !$omp parallel 196 | !$omp do private(time,time1d,dtdv,dtdv2d,i,j) 197 | do i = 1, nv 198 | call fm2d(nsrc,srcx,srcy,nrec,recx,recy,transpose(mask(:,:,i)),& 199 | nx,ny,xmin,ymin,dx,dy,gdx,gdy,sdx,sext,vel(:,:,i),& 200 | time,dtdv,earth) 201 | time1d = reshape(time,(/nrec*nsrc/)) 202 | dtdv2d = reshape(dtdv,(/ny*nx,nrec*nsrc/)) 203 | lglike(i) = 0.5*sum((tobs(1,:,i)-time1d)**2/tobs(2,:,i)**2) 204 | do j = 1, nrec*nsrc 205 | grads(:,i) = grads(:,i) + dtdv2d(:,j)*(tobs(1,j,i)-time1d(j))/tobs(2,j,i)**2 206 | enddo 207 | enddo 208 | !$omp end do 209 | !$omp end parallel 210 | 211 | end subroutine 212 | 213 | end module 214 | -------------------------------------------------------------------------------- /forward/tomo2d/loglike.py: -------------------------------------------------------------------------------- 1 | import pymc3 as pm 2 | import numpy as np 3 | import theano 4 | import theano.tensor as tt 5 | from pyfm2d import fm2d 6 | 7 | 8 | class LogLikeGrad(tt.Op): 9 | 10 | itypes = [tt.dvector] 11 | otypes = [tt.dscalar] 12 | 13 | def __init__(self, model, data, src, rec, mask, sigma, nx=11, ny=11, xmin=-5, ymin=-5, dx=0.1, dy=0.1, gdx=5, gdy=5, sdx=4, sext=4, earth=0): 14 | self.model = model 15 | self.data = data 16 | self.sigma = sigma 17 | self.nx = nx 18 | self.ny = ny 19 | self.xmin = xmin 20 | self.ymin = ymin 21 | self.dx = dx 22 | self.dy = dy 23 | self.gdx = gdx 24 | self.gdy = gdy 25 | self.sdx = sdx 26 | self.sext = sext 27 | self.earth = earth 28 | self.mask = np.ascontiguousarray(mask) 29 | 30 | self.src = src 31 | self.rec = rec 32 | # load sources and receivers 33 | #src = np.loadtxt('sources.dat') 34 | self.srcx = np.ascontiguousarray(src[:,0]) 35 | self.srcy = np.ascontiguousarray(src[:,1]) 36 | #rec = np.loadtxt('receivers.dat') 37 | self.recx = np.ascontiguousarray(rec[:,0]) 38 | self.recy = np.ascontiguousarray(rec[:,1]) 39 | 40 | # initialise the gradient op 41 | self.logpgrad = LogGrad(self.model,self.data,self.src,self.rec,self.mask, 42 | self.sigma,self.nx,self.ny,self.xmin,self.ymin, 43 | self.dx,self.dy,self.gdx,self.gdy,self.sdx, 44 | self.sext, self.earth) 45 | 46 | def perform(self, node, inputs, outputs): 47 | theta, = inputs 48 | 49 | self.time, self.dtdv = self.model(theta,self.srcx,self.srcy,self.recx,self.recy, 50 | self.mask,self.nx,self.ny,self.xmin,self.ymin, 51 | self.dx,self.dy,self.gdx,self.gdy,self.sdx, 52 | self.sext,self.earth) 53 | # get likelihood 54 | lglike = np.sum(-(0.5/self.sigma**2)*((self.data-self.time)**2)) 55 | 56 | outputs[0][0] = np.array(lglike) 57 | 58 | def grad(self, inputs, g): 59 | 60 | theta, = inputs 61 | #lggrad = self.dtdv*((self.data-self.time)/self.sigma**2)[:,None] 62 | #lggrad = self.logpgrad(theta)*((self.data-self.time)/self.sigma**2)[:,None] 63 | #lggrad = np.sum(lggrad,axis=0) 64 | lggrad = self.logpgrad(theta) 65 | 66 | print(lggrad) 67 | return [g[0]*lggrad] 68 | 69 | class LogGrad(tt.Op): 70 | 71 | itypes = [tt.dvector] 72 | otypes = [tt.dvector] 73 | 74 | def __init__(self, model, data, src, rec, mask, sigma, nx=11, ny=11, xmin=-5, ymin=-5, dx=0.1, dy=0.1, gdx=5, gdy=5, sdx=4, sext=4, earth=0): 75 | self.model = model 76 | self.data = data 77 | self.sigma = sigma 78 | self.nx = nx 79 | self.ny = ny 80 | self.xmin = xmin 81 | self.ymin = ymin 82 | self.dx = dx 83 | self.dy = dy 84 | self.gdx = gdx 85 | self.gdy = gdy 86 | self.sdx = sdx 87 | self.sext = sext 88 | self.earth = earth 89 | self.mask = np.ascontiguousarray(mask) 90 | 91 | self.src = src 92 | self.rec = rec 93 | # load sources and receivers 94 | #src = np.loadtxt('sources.dat') 95 | self.srcx = np.ascontiguousarray(src[:,0]) 96 | self.srcy = np.ascontiguousarray(src[:,1]) 97 | #rec = np.loadtxt('receivers.dat') 98 | self.recx = np.ascontiguousarray(rec[:,0]) 99 | self.recy = np.ascontiguousarray(rec[:,1]) 100 | 101 | def perform(self, node, inputs, outputs): 102 | theta, = inputs 103 | 104 | self.time, self.dtdv = self.model(theta,self.srcx,self.srcy,self.recx,self.recy, 105 | self.mask,self.nx,self.ny,self.xmin,self.ymin, 106 | self.dx,self.dy,self.gdx,self.gdy,self.sdx, 107 | self.sext,self.earth) 108 | # get likelihood 109 | lggrad = self.dtdv*((self.data-self.time)/self.sigma**2)[:,None] 110 | grads = np.sum(lggrad,axis=0) 111 | 112 | 113 | outputs[0][0] = grads 114 | 115 | -------------------------------------------------------------------------------- /forward/tomo2d/pyfm2d.h: -------------------------------------------------------------------------------- 1 | extern void c_fm2d(int *, double *, double *, int *, double *, double *, 2 | int *, int *, int *, double *, double *, double *, double *, 3 | int *, int *, int *, int *, double *, double *, double *, double *); 4 | 5 | extern void c_fm2d_parallel(int *, double *, double *, int *, double *, double *, 6 | int *, int *, int *, double *, double *, double *, double *, 7 | int *, int *, int *, int *, int*, double *, double *, double *); 8 | 9 | extern void c_fm2d_lglike(int *, double *, double *, int *, double *, double *, 10 | int *, int *, int *, double *, double *, double *, double *, 11 | int *, int *, int *, int *, int*, double *, double *, double *, double *, double *); 12 | 13 | extern void c_many_fm2d(int *nsrc, double *srcx, double *srcy, int *nrec, double *recx, double *recy, 14 | int *nx, int *ny, double *xmin, double *ymin, double *dx, double *dy, 15 | int *gdx, int *gdy, int *sdx, int *sext, int *nv, double *vel, double *tobs, 16 | int *mask, double *res, double *grads, double *earth); 17 | -------------------------------------------------------------------------------- /forward/tomo2d/pyfm2d.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | from sys import exit 4 | 5 | cdef extern from "pyfm2d.h": 6 | void c_fm2d(int *nsrc, double *srcx, double *srcy, int *nrec, double *recx, double *recy, 7 | int *nx, int *ny, int *mask, double *xmin, double *ymin, double *dx, double *dy, 8 | int *gdx, int *gdy, int *sdx, int *sext, double *vel, double *time, double *dtdv, double *earth) 9 | void c_fm2d_parallel(int *nsrc, double *srcx, double *srcy, int *nrec, double *recx, double *recy, 10 | int *nx, int *ny, int *mask, double *xmin, double *ymin, double *dx, double *dy, 11 | int *gdx, int *gdy, int *sdx, int *sext, int *nv, double *vel, double *times, double *earth) 12 | void c_fm2d_lglike(int *nsrc, double *srcx, double *srcy, int *nrec, double *recx, double *recy, 13 | int *nx, int *ny, int *mask, double *xmin, double *ymin, double *dx, double *dy, 14 | int *gdx, int *gdy, int *sdx, int *sext, int *nv, double *vel, double *tobs, 15 | double *res, double *grads, double *earth) 16 | void c_many_fm2d(int *nsrc, double *srcx, double *srcy, int *nrec, double *recx, double *recy, 17 | int *nx, int *ny, double *xmin, double *ymin, double *dx, double *dy, 18 | int *gdx, int *gdy, int *sdx, int *sext, int *nv, double *vel, double *tobs, 19 | int *mask, double *res, double *grads, double *earth) 20 | def fm2d(np.ndarray[double, ndim=1, mode="c"] vel not None, np.ndarray[double, ndim=1, mode="c"] srcx not None, 21 | np.ndarray[double, ndim=1, mode="c"] srcy not None, 22 | np.ndarray[double, ndim=1, mode="c"] recx not None, np.ndarray[double, ndim=1, mode="c"] recy not None, 23 | np.ndarray[int, ndim=2, mode="c"] mask not None, int nx, int ny, double xmin, double ymin, double dx, 24 | double dy, int gdx, int gdy, int sdx, int sext, double earth=0): 25 | cdef int nsrc, nrec 26 | nsrc = srcx.shape[0] 27 | nrec = recx.shape[0] 28 | 29 | if(np.isnan(vel).any()): 30 | print('NaN occured in python') 31 | exit() 32 | 33 | cdef np.ndarray[double,ndim=1,mode="c"] time = np.empty(nsrc*nrec, dtype=np.float64) 34 | cdef np.ndarray[double,ndim=2, mode="c"] dtdv = np.empty((nsrc*nrec,nx*ny),dtype=np.float64) 35 | c_fm2d(&nsrc, &srcx[0], &srcy[0], &nrec, &recx[0], &recy[0], &nx, &ny, &mask[0,0], 36 | &xmin, &ymin, &dx, &dy, &gdx, &gdy, &sdx, &sext, &vel[0], &time[0], &dtdv[0,0],&earth) 37 | 38 | return time, dtdv 39 | 40 | def pfm2d(np.ndarray[double, ndim=2, mode="c"] vel not None, np.ndarray[double, ndim=1, mode="c"] srcx not None, 41 | np.ndarray[double, ndim=1, mode="c"] srcy not None, 42 | np.ndarray[double, ndim=1, mode="c"] recx not None, np.ndarray[double, ndim=1, mode="c"] recy not None, 43 | np.ndarray[int, ndim=2, mode="c"] mask not None, int nx, int ny, double xmin, double ymin, double dx, 44 | double dy, int gdx, int gdy, int sdx, int sext, double earth=0): 45 | cdef int nsrc, nrec, nv 46 | nsrc = srcx.shape[0] 47 | nrec = recx.shape[0] 48 | nv = vel.shape[0] 49 | 50 | if(np.isnan(vel).any()): 51 | print('NaN occured in python') 52 | exit() 53 | 54 | cdef np.ndarray[double,ndim=2,mode="c"] times = np.empty((nv,nsrc*nrec),dtype=np.float64) 55 | c_fm2d_parallel(&nsrc, &srcx[0], &srcy[0], &nrec, &recx[0], &recy[0], &nx, &ny, &mask[0,0], 56 | &xmin, &ymin, &dx, &dy, &gdx, &gdy, &sdx, &sext, &nv, 57 | &vel[0,0], ×[0,0], &earth) 58 | 59 | return times 60 | 61 | 62 | def fm2d_lglike(np.ndarray[double, ndim=2, mode="c"] vel not None, np.ndarray[double, ndim=1, mode="c"] srcx not None, 63 | np.ndarray[double, ndim=1, mode="c"] srcy not None, 64 | np.ndarray[double, ndim=1, mode="c"] recx not None, np.ndarray[double, ndim=1, mode="c"] recy not None, 65 | np.ndarray[int, ndim=2, mode="c"] mask not None, int nx, int ny, double xmin, double ymin, double dx, 66 | double dy, int gdx, int gdy, int sdx, int sext, 67 | np.ndarray[double, ndim=2, mode="c"] tobs not None, double earth=0): 68 | cdef int nsrc, nrec, nv 69 | nsrc = srcx.shape[0] 70 | nrec = recx.shape[0] 71 | nv = vel.shape[0] 72 | 73 | if(np.isnan(vel).any()): 74 | print('NaN occured in python') 75 | exit() 76 | 77 | cdef np.ndarray[double,ndim=1,mode="c"] res = np.empty(nv, dtype=np.float64) 78 | cdef np.ndarray[double,ndim=2, mode="c"] grads = np.empty((nv,nx*ny),dtype=np.float64) 79 | c_fm2d_lglike(&nsrc, &srcx[0], &srcy[0], &nrec, &recx[0], &recy[0], &nx, &ny, &mask[0,0], 80 | &xmin, &ymin, &dx, &dy, &gdx, &gdy, &sdx, &sext, &nv, 81 | &vel[0,0], &tobs[0,0], &res[0], &grads[0,0], &earth) 82 | 83 | return res, grads 84 | 85 | def many_fm2d(np.ndarray[double, ndim=2, mode="c"] vel not None, np.ndarray[double, ndim=1, mode="c"] srcx not None, 86 | np.ndarray[double, ndim=1, mode="c"] srcy not None, 87 | np.ndarray[double, ndim=1, mode="c"] recx not None, np.ndarray[double, ndim=1, mode="c"] recy not None, 88 | int nx, int ny, double xmin, double ymin, double dx, 89 | double dy, int gdx, int gdy, int sdx, int sext, 90 | np.ndarray[double, ndim=3, mode="c"] tobs not None, double earth=0): 91 | cdef int nsrc, nrec, nv 92 | nsrc = srcx.shape[0] 93 | nrec = recx.shape[0] 94 | nv = vel.shape[0] 95 | 96 | if(np.isnan(vel).any()): 97 | print('NaN occured in python') 98 | exit() 99 | cdef np.ndarray[int, ndim=3, mode="c"] mask = np.zeros((nv,nsrc*nrec,2)) 100 | w = tobs[:,:,0] > 0 101 | mask[w,0] = 1 102 | mask[:,:,1] = np.broadcast_to(np.linspace(1,nsrc*nrec,nsrc*nrec),(nv,nsrc*nrec)) 103 | cdef np.ndarray[double,ndim=1,mode="c"] res = np.empty(nv, dtype=np.float64) 104 | cdef np.ndarray[double,ndim=2, mode="c"] grads = np.empty((nv,nx*ny),dtype=np.float64) 105 | c_many_fm2d(&nsrc, &srcx[0], &srcy[0], &nrec, &recx[0], &recy[0], &nx, &ny, 106 | &xmin, &ymin, &dx, &dy, &gdx, &gdy, &sdx, &sext, &nv, 107 | &vel[0,0], &tobs[0,0,0], &mask[0,0,0], &res[0], &grads[0,0], &earth) 108 | 109 | return res, grads 110 | -------------------------------------------------------------------------------- /forward/tomo2d/run_tomo.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from forward.tomo2d.pyfm2d import fm2d_lglike, many_fm2d 3 | 4 | def run_tomo(vel, data, src, rec, config, client=None): 5 | ''' 6 | Call tomography code to get loss and gradient 7 | Input 8 | vel: velocity of all particles, shape (n, nparameters) 9 | data: a 2d array of travel time data, shape (nsrc*nrec,2), 10 | 1st column is travel time, 2nd column is noise 11 | set travel time to zero if no data is available 12 | src, rec: array of source/receiver locations, shape (n, 2) 13 | config: configure.ConfigureParser() 14 | client: a dask client, not used here 15 | ''' 16 | 17 | ns = src.shape[0] 18 | nr = rec.shape[0] 19 | status = np.zeros((2,ns*nr),dtype=np.int32) 20 | w = data[:,0] > 0 21 | status[0,w] = 1 22 | status[1,:] = np.linspace(1,ns*nr,ns*nr) 23 | 24 | data[data[:,1]<=0, 1] = 1.0 # for safety, set the noise to nonzero if it is zero 25 | 26 | srcx = np.ascontiguousarray(src[:,0]) 27 | srcy = np.ascontiguousarray(src[:,1]) 28 | recx = np.ascontiguousarray(rec[:,0]) 29 | recy = np.ascontiguousarray(rec[:,1]) 30 | 31 | nx = config.getint('tomo','nx') 32 | ny = config.getint('tomo','ny') 33 | xmin = config.getfloat('tomo','xmin') 34 | ymin = config.getfloat('tomo','ymin') 35 | dx = config.getfloat('tomo','dx') 36 | dy = config.getfloat('tomo','dy') 37 | gdx = config.getint('tomo','gdx') 38 | gdy = config.getint('tomo','gdy') 39 | sdx = config.getint('tomo','sdx') 40 | sext = config.getint('tomo','sext') 41 | earth = config.getfloat('tomo','earth') 42 | 43 | res, grads = fm2d_lglike(vel, srcx, srcy, recx, recy, 44 | status, nx, ny, xmin, ymin, 45 | dx, dy, gdx, gdy, sdx, sext, 46 | data, earth) 47 | 48 | return res, grads 49 | 50 | def run_many_tomo(vel, data, src, rec, config, client=None): 51 | ''' 52 | Call tomography code to get loss and gradient 53 | Input 54 | vel: velocity of all models at different periods, shape (np, nparameters) 55 | data: a 3d array of travel time data, shape (np,nsrc*nrec,2) 56 | data at all np periods, details see above 57 | src, rec: array of source/receiver locations, shape (n, 2) 58 | config: configure.ConfigureParser() 59 | client: a dask client, not used here 60 | ''' 61 | 62 | ns = src.shape[0] 63 | nr = rec.shape[0] 64 | srcx = np.ascontiguousarray(src[:,0]) 65 | srcy = np.ascontiguousarray(src[:,1]) 66 | recx = np.ascontiguousarray(rec[:,0]) 67 | recy = np.ascontiguousarray(rec[:,1]) 68 | 69 | data[data[:,:,1]<=0, 1] = 1.0 # for safety, set the noise to nonzero if it is zero 70 | 71 | nx = config.getint('tomo','nx') 72 | ny = config.getint('tomo','ny') 73 | xmin = config.getfloat('tomo','xmin') 74 | ymin = config.getfloat('tomo','ymin') 75 | dx = config.getfloat('tomo','dx') 76 | dy = config.getfloat('tomo','dy') 77 | gdx = config.getint('tomo','gdx') 78 | gdy = config.getint('tomo','gdy') 79 | sdx = config.getint('tomo','sdx') 80 | sext = config.getint('tomo','sext') 81 | earth = config.getfloat('tomo','earth') 82 | 83 | res, grads = many_fm2d(vel, srcx, srcy, recx, recy, 84 | nx, ny, xmin, ymin, 85 | dx, dy, gdx, gdy, sdx, sext, 86 | data, earth) 87 | 88 | return res, grads 89 | 90 | 91 | -------------------------------------------------------------------------------- /forward/tomo2d/setup.cfg: -------------------------------------------------------------------------------- 1 | [build_ext] 2 | force=1 3 | -------------------------------------------------------------------------------- /forward/tomo2d/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | from distutils.extension import Extension 3 | from Cython.Distutils import build_ext 4 | import numpy 5 | from os import system 6 | npy_include_dir = numpy.get_include() 7 | 8 | # compile fortran code 9 | make_comp = 'make' 10 | print(make_comp) 11 | system('make cleanall') 12 | system(make_comp) 13 | 14 | ext_modules = [Extension("pyfm2d", ["pyfm2d.pyx"], 15 | include_dirs = [npy_include_dir], 16 | libraries=["gfortran","gomp"], 17 | extra_objects=["fm2d_globalp.o", "fm2d_ttime.o", "fm2dray.o","fm2d_wrapper.o"])] 18 | 19 | setup(name = 'fast marching', 20 | cmdclass = {'build_ext': build_ext}, 21 | ext_modules = ext_modules) 22 | 23 | system('make clean') 24 | system('rm -rf build') 25 | -------------------------------------------------------------------------------- /forward/tomo2d/test.py: -------------------------------------------------------------------------------- 1 | # test python wrapper for fortran fmm 2d code 2 | 3 | import numpy as np 4 | from pyfm2d import fm2d 5 | 6 | srcx = np.random.rand(8) 7 | srcy = np.random.rand(8) 8 | mask = np.zeros((2,64),dtype=np.int32) 9 | for i in range(8): 10 | for j in range(8): 11 | if(j>i): 12 | mask[0,i*8+j] = 1 13 | mask[1,i*8+j] = i*8 + j + 1 14 | nx = 11 15 | ny = 11 16 | xmin = 0 17 | ymin = 0 18 | dx = 0.1 19 | dy = 0.1 20 | gdx = 2 21 | gdy = 2 22 | sdx = 4 23 | sext =4 24 | vel = np.random.rand(121) 25 | 26 | print(srcx) 27 | print(srcy) 28 | print(vel) 29 | 30 | recx = srcx 31 | recy = srcy 32 | time, dtdv = fm2d(vel,srcx,srcy,recx,recy,mask,nx,ny,xmin,ymin,dx,dy,gdx,gdy,sdx,sext) 33 | 34 | w = np.where(mask[0,:]>0.001)[0] 35 | print(time[w]) 36 | 37 | print(dtdv[w,:]) 38 | -------------------------------------------------------------------------------- /forward/tomo2d/tomo2d.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import time 3 | from forward.tomo2d.run_tomo import run_tomo 4 | 5 | class tomo2d(): 6 | ''' 7 | A class that implements an interface of an external 2d travel time tomography code 8 | ''' 9 | def __init__(self, config, prior, mask=None, client=None): 10 | ''' 11 | config: a python configparser.ConfigParser() 12 | prior: a prior class, see prior/prior.py 13 | mask: a mask array where the parameters will be fixed, default no mask 14 | client: a dask client to submit tomography running, not used here 15 | ''' 16 | 17 | self.config = config 18 | self.sigma = config.getfloat('svgd','sigma') 19 | self.client = client 20 | self.prior = prior 21 | self.data = np.loadtxt(config.get('tomo','datafile'), dtype=np.float64) 22 | self.src = np.loadtxt(config.get('tomo','srcfile'), dtype=np.float64) 23 | self.rec = np.loadtxt(config.get('tomo','recfile'), dtype=np.float64) 24 | 25 | # create mask matrix for model parameters that are fixed 26 | ny = config.getint('tomo','ny') 27 | nx = config.getint('tomo','nx') 28 | if(mask is None): 29 | mask = np.full((nx*ny),False) 30 | self.mask = mask 31 | 32 | def gradient(self, theta): 33 | ''' 34 | Call external tomography code to get misfit value and gradient 35 | Note that run_tomo needs to be implemented for specific tomography code 36 | ''' 37 | 38 | # call fwi function, get loss and grad 39 | loss, grad = run_tomo(theta, self.data, self.src, self.rec, self.config, client=self.client) 40 | # update grad 41 | grad[:,self.mask] = 0 42 | #g = 1./self.sigma**2 43 | #grad *= g 44 | # clip the grad to avoid numerical instability 45 | #clip = self.config.getfloat('FWI','gclipmax') 46 | #grad[grad>=clip] = clip 47 | #grad[grad<=-clip] = -clip 48 | 49 | # log likelihood 50 | return loss, grad 51 | 52 | def dlnprob(self, theta): 53 | ''' 54 | Compute gradient of log posterior pdf 55 | Input 56 | theta: 2D array with dimension of nparticles*nparameters 57 | Return 58 | lglike: a vector of log likelihood for each particle 59 | grad: each row contains the gradient for each particle 60 | mask: an auxilary mask array for SVGD optimization, can be safely ignored 61 | ''' 62 | 63 | # adjust theta such that it is within prior or transformed back to original space 64 | theta = self.prior.adjust(theta) 65 | 66 | #t = time.time() 67 | loss, grad = self.gradient(theta) 68 | lglike = -loss + self.prior.lnprob(theta) 69 | #print('Simulation takes '+str(time.time()-t)) 70 | 71 | # compute gradient including the prior 72 | grad, mask = self.prior.grad(theta, grad=grad) 73 | grad[:,self.mask] = 0 74 | print(f'Average loss and negative log posterior: {np.mean(loss)} {np.mean(-lglike)}') 75 | print(f'Max. Mean and Median grad: {np.max(abs(grad))} {np.mean(abs(grad))} {np.median(abs(grad))}') 76 | #print(f'max, mean and median grads after transform: {np.max(abs(grad))} {np.mean(abs(grad))} {np.median(abs(grad))}') 77 | 78 | return lglike, grad, mask 79 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup(name='vip', 4 | description='Variational Inversion Package', 5 | packages=find_packages(), 6 | ) 7 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Build kernels for svgd..." 4 | cd vip/kernel 5 | RESULT="$(python setup.py build_ext -i 2>&1)" #2>/dev/null 6 | status=$? 7 | if [ $status -eq 0 ]; then 8 | echo "Building kernel succeeds" 9 | else 10 | echo "Error: $RESULT" 11 | fi 12 | 13 | echo "Build 2d fwi..." 14 | cd ../../forward/fwi2d 15 | RESULT="$(python setup.py build_ext -i 2>&1)" 16 | status=$? 17 | if [ $status -eq 0 ]; then 18 | echo "Building 2d fwi succeeds" 19 | else 20 | echo "Error: $RESULT" 21 | fi 22 | 23 | echo "Build 2d tomography..." 24 | cd ../tomo2d 25 | RESULT="$(python setup.py build_ext -i 2>&1)" 26 | status=$? 27 | if [ $status -eq 0 ]; then 28 | echo "Building 2d tomography succeeds" 29 | else 30 | echo "Error: $RESULT" 31 | fi 32 | 33 | cd ../../ 34 | 35 | if [ "$1" = "install" ]; then 36 | echo "Install vip..." 37 | pip install -e . 38 | fi 39 | -------------------------------------------------------------------------------- /tests/fwi2d/config.ini: -------------------------------------------------------------------------------- 1 | [FWI] 2 | # input for fwi code 3 | basepath = /home/xzhang/projects/VIP/tests/fwi2d 4 | # configuration file for 2d fwi code 5 | configfile = ${basepath}/input/input_params.txt 6 | # data file 7 | datafile = ${basepath}/input/waveform.npy 8 | 9 | # other arguments for fwi code 10 | # grid points in x direction (nx) 11 | nx = 200 12 | # grid points in z direction (nz) 13 | nz = 120 14 | # pml points (pml0) 15 | pml = 10 16 | # Finite difference order (Lc) 17 | Lc = 3 18 | # Total number of sources (ns) 19 | ns = 10 20 | # Total time steps (nt) 21 | nt = 2501 22 | # Shot interval in grid points (ds) 23 | ds = 20 24 | # Grid number of the first shot to the left of the model (ns0) 25 | ns0 = 10 26 | # Depth of source in grid points (depths) 27 | depths = 1 28 | # Depth of receiver in grid points (depthr) 29 | depthr = 17 30 | # Receiver interval in grid points (dr) 31 | dr = 1 32 | # Time step interval of saved wavefield during forward (nt_interval) 33 | nt_interval = 2 34 | # Grid spacing in x direction (dx) 35 | dx = 20.0 36 | # Grid spacing in z direction (dz) 37 | dz = 20.0 38 | # Time step (dt) 39 | dt = 0.002 40 | # Donimate frequency (f0) 41 | f0 = 10.0 42 | 43 | [svgd] 44 | # svgd or ssvgd is supported 45 | method = ssvgd 46 | # kernel function, only rbf or diagonal supported 47 | kernel = rbf 48 | # diagonal kernel 49 | diag = grad 50 | # optimizer, sgd, adam 51 | optimizer = sgd 52 | # using transform (true) or not (false) 53 | transform = true 54 | # prior type, 'Uniform' or 'Gaussian' 55 | priortype = Uniform 56 | # file that contains hyperparameters for prior pdf 57 | prior = ${FWI:basepath}/input/Uniform_prior.txt 58 | # number of particles 59 | nparticles = 20 60 | # number of iterations 61 | iter = 2000 62 | # burn_in period, only used for ssvgd 63 | burn_in = 1000 64 | # thining of the chain, only used for ssvgd 65 | thin = 2 66 | # step length for svgd and ssvgd 67 | stepsize = 0.2 68 | # decay the stepsize exponentially, the final stepsize will be stepsize*final_decay 69 | final_decay = 0.2 70 | # noise level, currently only support a constant number 71 | sigma = 1e-1 72 | # smoothness in x direction, 0 for no smoothness 73 | smoothx = 0 74 | # smoothness in z direction, 0 for no smoothness 75 | smoothz = 0 76 | # output directory 77 | outpath = ${FWI:basepath}/results 78 | 79 | [dask] 80 | # parallel environment used on a hpc system 81 | pe = cascadelake 82 | # number of nodes for each dask worker 83 | nnodes = 1 84 | # number of dask workers, the total nodes required will be nnodes*nworkers 85 | nworkers = 20 86 | # number of threads for each dask worker, usually set to one to let the third-party code decide the number of threads, e.g. by using omp_num_threads 87 | ph = 1 88 | # directory for dask 89 | daskpath = ${FWI:basepath}/dask 90 | #daskpath = /tmp/mytmp 91 | -------------------------------------------------------------------------------- /tests/fwi2d/input/Uniform_prior.txt: -------------------------------------------------------------------------------- 1 | 1.400000000000000000e+03 1.600000000000000000e+03 2 | 1.400000000000000000e+03 1.600000000000000000e+03 3 | 1.400000000000000000e+03 1.600000000000000000e+03 4 | 1.400000000000000000e+03 1.600000000000000000e+03 5 | 1.400000000000000000e+03 1.600000000000000000e+03 6 | 1.400000000000000000e+03 1.600000000000000000e+03 7 | 1.400000000000000000e+03 1.600000000000000000e+03 8 | 1.400000000000000000e+03 1.600000000000000000e+03 9 | 1.400000000000000000e+03 1.600000000000000000e+03 10 | 1.400000000000000000e+03 1.600000000000000000e+03 11 | 1.400000000000000000e+03 1.600000000000000000e+03 12 | 1.400000000000000000e+03 1.600000000000000000e+03 13 | 1.400000000000000000e+03 1.600000000000000000e+03 14 | 1.400000000000000000e+03 1.600000000000000000e+03 15 | 1.400000000000000000e+03 1.600000000000000000e+03 16 | 1.400000000000000000e+03 1.600000000000000000e+03 17 | 1.400000000000000000e+03 1.600000000000000000e+03 18 | 1.400000000000000000e+03 1.600000000000000000e+03 19 | 1.500000000000000000e+03 2.503630252100840153e+03 20 | 1.500000000000000000e+03 2.527831932773109202e+03 21 | 1.500000000000000000e+03 2.552033613445378251e+03 22 | 1.500000000000000000e+03 2.576235294117646845e+03 23 | 1.500000000000000000e+03 2.600436974789915894e+03 24 | 1.500000000000000000e+03 2.624638655462184943e+03 25 | 1.500000000000000000e+03 2.648840336134453537e+03 26 | 1.500000000000000000e+03 2.673042016806722586e+03 27 | 1.500000000000000000e+03 2.697243697478991635e+03 28 | 1.500000000000000000e+03 2.721445378151260229e+03 29 | 1.500000000000000000e+03 2.745647058823529733e+03 30 | 1.500000000000000000e+03 2.769848739495798327e+03 31 | 1.500000000000000000e+03 2.794050420168066921e+03 32 | 1.500000000000000000e+03 2.818252100840335970e+03 33 | 1.500000000000000000e+03 2.842453781512605019e+03 34 | 1.500000000000000000e+03 2.866655462184874068e+03 35 | 1.500000000000000000e+03 2.890857142857142662e+03 36 | 1.500000000000000000e+03 2.915058823529411711e+03 37 | 1.500000000000000000e+03 2.939260504201680305e+03 38 | 1.500000000000000000e+03 2.963462184873949354e+03 39 | 1.500000000000000000e+03 2.987663865546218403e+03 40 | 1.500000000000000000e+03 3.011865546218486998e+03 41 | 1.500000000000000000e+03 3.036067226890756046e+03 42 | 1.500000000000000000e+03 3.060268907563025095e+03 43 | 1.500000000000000000e+03 3.084470588235294144e+03 44 | 1.500000000000000000e+03 3.108672268907563193e+03 45 | 1.500000000000000000e+03 3.132873949579831788e+03 46 | 1.500000000000000000e+03 3.157075630252100837e+03 47 | 1.500000000000000000e+03 3.181277310924369885e+03 48 | 1.500000000000000000e+03 3.205478991596638480e+03 49 | 1.500000000000000000e+03 3.229680672268907529e+03 50 | 1.500000000000000000e+03 3.253882352941176578e+03 51 | 1.500000000000000000e+03 3.278084033613445172e+03 52 | 1.500000000000000000e+03 3.302285714285714221e+03 53 | 1.500000000000000000e+03 3.326487394957983270e+03 54 | 1.500000000000000000e+03 3.350689075630251864e+03 55 | 1.500000000000000000e+03 3.374890756302520913e+03 56 | 1.500000000000000000e+03 3.399092436974789962e+03 57 | 1.500000000000000000e+03 3.423294117647058556e+03 58 | 1.500000000000000000e+03 3.447495798319327605e+03 59 | 1.500000000000000000e+03 3.471697478991596654e+03 60 | 1.495899159663865248e+03 3.495899159663865248e+03 61 | 1.520100840336134297e+03 3.520100840336134297e+03 62 | 1.544302521008403346e+03 3.544302521008403346e+03 63 | 1.568504201680671940e+03 3.568504201680671940e+03 64 | 1.592705882352941444e+03 3.592705882352941444e+03 65 | 1.616907563025210038e+03 3.616907563025210038e+03 66 | 1.641109243697478632e+03 3.641109243697478632e+03 67 | 1.665310924369748136e+03 3.665310924369748136e+03 68 | 1.689512605042016730e+03 3.689512605042016730e+03 69 | 1.713714285714285325e+03 3.713714285714285325e+03 70 | 1.737915966386554828e+03 3.737915966386554828e+03 71 | 1.762117647058823422e+03 3.762117647058823422e+03 72 | 1.786319327731092017e+03 3.786319327731092017e+03 73 | 1.810521008403361066e+03 3.810521008403361066e+03 74 | 1.834722689075630115e+03 3.834722689075630115e+03 75 | 1.858924369747898709e+03 3.858924369747898709e+03 76 | 1.883126050420167303e+03 3.883126050420167303e+03 77 | 1.907327731092436807e+03 3.907327731092436807e+03 78 | 1.931529411764705856e+03 3.931529411764705856e+03 79 | 1.955731092436974905e+03 3.955731092436974905e+03 80 | 1.979932773109243499e+03 3.979932773109243499e+03 81 | 2.004134453781512093e+03 4.004134453781512093e+03 82 | 2.028336134453781142e+03 4.028336134453781142e+03 83 | 2.052537815126050191e+03 4.052537815126050191e+03 84 | 2.076739495798319240e+03 4.076739495798319240e+03 85 | 2.100941176470588289e+03 4.100941176470588289e+03 86 | 2.125142857142856883e+03 4.125142857142856883e+03 87 | 2.149344537815125477e+03 4.149344537815125477e+03 88 | 2.173546218487394526e+03 4.173546218487394071e+03 89 | 2.197747899159663575e+03 4.197747899159663575e+03 90 | 2.221949579831932624e+03 4.221949579831933079e+03 91 | 2.246151260504201673e+03 4.246151260504201673e+03 92 | 2.270352941176470267e+03 4.270352941176470267e+03 93 | 2.294554621848738861e+03 4.294554621848738861e+03 94 | 2.318756302521007910e+03 4.318756302521007456e+03 95 | 2.342957983193276959e+03 4.342957983193276959e+03 96 | 2.367159663865546463e+03 4.367159663865546463e+03 97 | 2.391361344537815057e+03 4.391361344537815057e+03 98 | 2.415563025210083651e+03 4.415563025210083651e+03 99 | 2.439764705882352700e+03 4.439764705882353155e+03 100 | 2.463966386554621749e+03 4.463966386554621749e+03 101 | 2.488168067226890798e+03 4.488168067226890344e+03 102 | 2.512369747899159847e+03 4.512369747899159847e+03 103 | 2.536571428571428442e+03 4.536571428571428442e+03 104 | 2.560773109243697490e+03 4.560773109243697036e+03 105 | 2.584974789915966085e+03 4.584974789915966539e+03 106 | 2.609176470588235134e+03 4.609176470588235134e+03 107 | 2.633378151260504183e+03 4.633378151260503728e+03 108 | 2.657579831932773232e+03 4.657579831932773232e+03 109 | 2.681781512605041826e+03 4.681781512605041826e+03 110 | 2.705983193277310875e+03 4.705983193277310420e+03 111 | 2.730184873949579469e+03 4.730184873949579924e+03 112 | 2.754386554621848518e+03 4.754386554621848518e+03 113 | 2.778588235294117567e+03 4.778588235294117112e+03 114 | 2.802789915966386616e+03 4.802789915966386616e+03 115 | 2.826991596638655210e+03 4.826991596638655210e+03 116 | 2.851193277310924259e+03 4.851193277310923804e+03 117 | 2.875394957983192853e+03 4.875394957983193308e+03 118 | 2.899596638655461902e+03 4.899596638655461902e+03 119 | 2.923798319327730496e+03 4.923798319327730496e+03 120 | 2.948000000000000000e+03 4.948000000000000000e+03 121 | -------------------------------------------------------------------------------- /tests/fwi2d/input/input_params.txt: -------------------------------------------------------------------------------- 1 | --grid points in x direction (nx) 2 | 200 3 | --grid points in z direction (nz) 4 | 120 5 | --pml points (pml0) 6 | 10 7 | --Finite difference order (Lc) 8 | 3 9 | --Total number of sources (ns) 10 | 10 11 | --Total time steps (nt) 12 | 2501 13 | --Shot interval in grid points (ds) 14 | 20 15 | --Grid number of the first shot to the left of the model (ns0) 16 | 10 17 | --Depth of source in grid points (depths) 18 | 1 19 | --Depth of receiver in grid points (depthr) 20 | 17 21 | --Receiver interval in grid points (dr) 22 | 1 23 | --Time step interval of saved wavefield during forward (nt_interval) 24 | 2 25 | --Grid spacing in x direction (dx) 26 | 20.0 27 | --Grid spacing in z direction (dz) 28 | 20.0 29 | --Time step (dt) 30 | 0.002 31 | --Donimate frequency (f0) 32 | 10.0 33 | -------------------------------------------------------------------------------- /tests/fwi2d/input/modelling.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.environ["OMP_NUM_THREADS"] = "2" 3 | import numpy as np 4 | import forward.fwi2d.aco2d as aco2d 5 | import time 6 | 7 | true_model = np.loadtxt('marmousi_small.txt') 8 | nz = true_model.shape[0]; nx = true_model.shape[1] 9 | print(true_model.shape) 10 | vel = true_model.astype(np.float64).flatten() 11 | 12 | nt = 2501 13 | nr = 200 14 | ns = 10 15 | t = time.time() 16 | rec = aco2d.forward(vel, dim = ns*nt*nr, verbose = 0, paramfile='./input_params.txt') 17 | rec = rec + 0.1*np.random.normal(size=rec.shape).astype(np.float32) 18 | print('Modelling time: '+str(time.time()-t)) 19 | 20 | np.save('waveforms.npy',rec) 21 | print('Modelling done.') 22 | -------------------------------------------------------------------------------- /tests/fwi2d/run_job.sh: -------------------------------------------------------------------------------- 1 | PYTHONPATH=/home/xzhang15/VIP python -u vfwi2d.py -r 0 2 | -------------------------------------------------------------------------------- /tests/fwi2d/vfwi2d.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import os 5 | import h5py 6 | 7 | from vip.prior.transform import trans 8 | from forward.fwi2d.fwi2d import fwi2d 9 | from vip.pyvi.svgd import SVGD, sSVGD 10 | 11 | from datetime import datetime 12 | import time 13 | import configparser 14 | import forward.fwi3d.dask_utils as du 15 | from vip.prior.prior import prior 16 | from vip.prior.pdf import Uniform, Gaussian 17 | 18 | import argparse 19 | import sys 20 | from pathlib import Path 21 | import dask 22 | 23 | os.environ['HDF5_USE_FILE_LOCKING']='FALSE' 24 | os.environ['OMP_NUM_THREADS']='4' 25 | dask.config.set({'distributed.comm.timeouts.connect': '50s'}) 26 | 27 | def init_vfwi(config): 28 | Path(config.get('svgd','outpath')).mkdir(parents=True, exist_ok=True) 29 | Path(config.get('dask','daskpath')).mkdir(parents=True, exist_ok=True) 30 | 31 | 32 | def generate_init(n=1,lb=0,ub=1e8, transform=True): 33 | eps = np.finfo(np.float64).eps 34 | nz = lb.shape[0]; nx = lb.shape[1] 35 | x = lb + (ub-lb)*np.random.uniform(low=eps,high=1-eps,size=(n,nz,nx)) 36 | x[:,0:18,:] = 1500 37 | if(transform): 38 | x = trans(x.reshape((-1,nx*nz)),lb=lb.flatten(),ub=ub.flatten(),trans=1) 39 | 40 | return x 41 | 42 | def get_init(config, resume=0): 43 | nx = config.getint('FWI','nx') 44 | nz = config.getint('FWI','nz') 45 | priorfile = config.get('svgd','prior') 46 | prior = np.loadtxt(priorfile) 47 | lower_bnd = prior[:,0].astype(np.float64); upper_bnd = prior[:,1].astype(np.float64) 48 | lower_bnd = np.broadcast_to(lower_bnd[:,None],(nz,nx)) 49 | upper_bnd = np.broadcast_to(upper_bnd[:,None],(nz,nx)) 50 | if(resume==0): 51 | x0 = generate_init(n=config.getint('svgd','nparticles'), lb=lower_bnd, ub=upper_bnd, 52 | transform=config.getboolean('svgd','transform')) 53 | 54 | else: 55 | print("Resume from previous running..") 56 | f = h5py.File(os.path.join(config['svgd']['outpath'],'samples.hdf5'),'r') 57 | x0 = f['samples'][-1,:,:] 58 | x0 = x0.astype(np.float64) 59 | f.close() 60 | if( config.getboolean('svgd','transform') ): 61 | x0 = trans(x0,lb=lower_bnd.flatten(),ub=upper_bnd.flatten(),trans=1) 62 | 63 | if(np.isinf(x0).any()): print("Error: inf occured") 64 | if(np.isnan(x0).any()): print("Error: nan occured") 65 | 66 | return x0 67 | 68 | def delta(n): 69 | diag0 = np.full((n,),fill_value=-2); diag0[0]=-1; diag0[-1]=-1 70 | diag1 = np.full((n-1,),fill_value=1) 71 | diagonals = [diag0,diag1,diag1] 72 | D = sparse.diags(diagonals,[0,-1,1]).tocsc() 73 | return D 74 | 75 | def create_prior(config): 76 | # prior info 77 | nx = config.getint('FWI','nx') 78 | nz = config.getint('FWI','nz') 79 | priorfile = config.get('svgd','prior') 80 | p = np.loadtxt(priorfile) 81 | p1 = p[:,0].astype(np.float64); p2 = p[:,1].astype(np.float64) 82 | p1 = np.broadcast_to(p1[:,None],(nz,nx)) 83 | p2 = np.broadcast_to(p2[:,None],(nz,nx)) 84 | p1 = p1.flatten() 85 | p2 = p2.flatten() 86 | ptype = config.get('svgd','priortype') 87 | if(ptype == 'Uniform'): 88 | pdf = Uniform(lb=p1, ub=p2) 89 | if(ptype == 'Gaussian'): 90 | pdf = Gaussian(mu=p1, sigma=p2) 91 | 92 | # create smooth matrix 93 | smoothness = False 94 | L = None 95 | smoothx = config.getfloat('svgd','smoothx') 96 | smoothz = config.getfloat('svgd','smoothz') 97 | if(smoothx>0 and smoothz>0): 98 | smoothx = np.full((nz,),fill_value=smoothx) 99 | smoothz = np.full((nz,),fill_value=smoothz) 100 | deltax = delta(nx) 101 | deltaz = delta(nz)/smoothz[:,None] 102 | Ix = sparse.eye(nx); Iz = sparse.eye(nz) 103 | Sx = sparse.kron(Iz/smoothx,deltax) 104 | Sy = sparse.kron(deltaz,Ix) 105 | L = sparse.vstack([Sx,Sz]) 106 | smoothness = True 107 | 108 | if(ptype=='Uniform'): 109 | ppdf = prior(pdf=pdf, transform=config.getboolean('svgd','transform'), lb=p1, ub=p2, smooth=smoothness, L=L) 110 | else: 111 | ppdf = prior(pdf=pdf, smooth=smoothness, L=L) 112 | 113 | return ppdf 114 | 115 | def write_samples(filename, pprior, start=0, chunk=10): 116 | 117 | if(pprior.trans): 118 | f = h5py.File(filename,'r+') 119 | samples = f['samples'] 120 | for i in range(start,samples.shape[0]): 121 | samples[i,:,:] = pprior.adjust(samples[i,:,:]) 122 | f.close() 123 | 124 | return 0 125 | 126 | 127 | if __name__=="__main__": 128 | 129 | parser = argparse.ArgumentParser(description='Variational Full-waveform Inversion') 130 | parser.add_argument("-c", "--config", metavar='config', default='config.ini', help="Configuration file") 131 | parser.add_argument("-r", "--resume", metavar='resume', default=0, type=int, help="Resume mode (1) or start a new run(0)") 132 | 133 | args = parser.parse_args() 134 | configfile = args.config 135 | resume = args.resume 136 | 137 | now = datetime.now() 138 | current_time = now.strftime("%Y-%m-%d %H:%M:%S") 139 | print(f'Start VFWI at {current_time}...') 140 | print(f'Config file for VFWI is: {configfile}') 141 | 142 | config = configparser.ConfigParser() 143 | config._interpolation = configparser.ExtendedInterpolation() 144 | config.read(configfile) 145 | 146 | print('Method for VFWI is: '+config['svgd']['method']) 147 | init_vfwi(config) 148 | x0 = get_init(config, resume=resume) 149 | print("Particles size: "+str(x0.shape)) 150 | 151 | daskpath = config.get('dask','daskpath') 152 | print(f'Create dask cluster at: {daskpath}') 153 | cluster, client = du.dask_local(config.getint('dask','nworkers'), 154 | ph=config.getint('dask','ph'), 155 | odask=daskpath) 156 | ppdf = create_prior(config) 157 | 158 | # fwi simulator 159 | nx = config.getint('FWI','nx') 160 | nz = config.getint('FWI','nz') 161 | mask = np.full((nz,nx),False) 162 | mask[0:18,:] = True 163 | data = np.load(config.get('FWI','datafile')) 164 | #data = data.transpose(0,2,1).flatten() 165 | simulator = fwi2d(config, ppdf, data, mask=mask.flatten(), client=client) 166 | 167 | # svgd sampler 168 | stepsize = config.getfloat('svgd','stepsize') 169 | iteration = config.getint('svgd','iter') 170 | final_decay = config.getfloat('svgd','final_decay') 171 | gamma = final_decay**(1./iteration) 172 | if(config['svgd']['method']=='ssvgd'): 173 | svgd = sSVGD(simulator.dlnprob, 174 | kernel=config['svgd']['kernel'], 175 | mask=mask.flatten(), 176 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 177 | elif(config['svgd']['method']=='svgd'): 178 | svgd = SVGD(simulator.dlnprob, 179 | kernel=config['svgd']['kernel'], 180 | mask=mask.flatten(), 181 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 182 | else: 183 | print('Not supported method') 184 | 185 | # sampling 186 | print('Start sampling ...') 187 | print(f'Iteration: {iteration}') 188 | print(f'Stepsize, decay rate and final decay: {stepsize} {gamma} {final_decay}') 189 | start = time.time() 190 | losses, x = svgd.sample(x0, 191 | n_iter=config.getint('svgd','iter'), 192 | stepsize=stepsize, gamma=gamma, 193 | optimizer=config['svgd']['optimizer'], 194 | burn_in=config.getint('svgd','burn_in'), 195 | thin=config.getint('svgd','thin') 196 | ) 197 | end=time.time() 198 | print('Time taken: '+str(end-start)+' s') 199 | 200 | # write out results 201 | write_samples(os.path.join(config.get('svgd','outpath'),'samples.hdf5'), ppdf) 202 | with open(os.path.join(config.get('svgd','outpath'),'misfits.txt'),"ab") as f: 203 | np.savetxt(f,losses) 204 | 205 | du.dask_del(cluster, client) 206 | -------------------------------------------------------------------------------- /tests/fwi3d/Uniform_prior.txt: -------------------------------------------------------------------------------- 1 | 1.840000000000000000e+03 4.300000000000000000e+03 2 | 1.876000000000000000e+03 4.338000000000000000e+03 3 | 1.912000000000000000e+03 4.376000000000000000e+03 4 | 1.948000000000000000e+03 4.414000000000000000e+03 5 | 1.984000000000000000e+03 4.452000000000000000e+03 6 | 2.020000000000000000e+03 4.490000000000000000e+03 7 | 2.056000000000000000e+03 4.528000000000000000e+03 8 | 2.092000000000000000e+03 4.566000000000000000e+03 9 | 2.128000000000000000e+03 4.604000000000000000e+03 10 | 2.164000000000000000e+03 4.642000000000000000e+03 11 | 2.200000000000000000e+03 4.680000000000000000e+03 12 | 2.236000000000000000e+03 4.718000000000000000e+03 13 | 2.272000000000000000e+03 4.756000000000000000e+03 14 | 2.308000000000000000e+03 4.794000000000000000e+03 15 | 2.344000000000000000e+03 4.832000000000000000e+03 16 | 2.380000000000000000e+03 4.870000000000000000e+03 17 | 2.416000000000000000e+03 4.908000000000000000e+03 18 | 2.452000000000000000e+03 4.946000000000000000e+03 19 | 2.488000000000000000e+03 4.984000000000000000e+03 20 | 2.524000000000000000e+03 5.022000000000000000e+03 21 | 2.560000000000000000e+03 5.060000000000000000e+03 22 | 2.596000000000000000e+03 5.098000000000000000e+03 23 | 2.632000000000000000e+03 5.136000000000000000e+03 24 | 2.668000000000000000e+03 5.174000000000000000e+03 25 | 2.704000000000000000e+03 5.212000000000000000e+03 26 | 2.740000000000000000e+03 5.250000000000000000e+03 27 | 2.776000000000000000e+03 5.288000000000000000e+03 28 | 2.812000000000000000e+03 5.326000000000000000e+03 29 | 2.848000000000000000e+03 5.364000000000000000e+03 30 | 2.884000000000000000e+03 5.402000000000000000e+03 31 | 2.920000000000000000e+03 5.440000000000000000e+03 32 | 2.956000000000000000e+03 5.478000000000000000e+03 33 | 2.992000000000000000e+03 5.516000000000000000e+03 34 | 3.028000000000000000e+03 5.554000000000000000e+03 35 | 3.064000000000000000e+03 5.592000000000000000e+03 36 | 3.100000000000000000e+03 5.630000000000000000e+03 37 | 3.136000000000000000e+03 5.668000000000000000e+03 38 | 3.172000000000000000e+03 5.706000000000000000e+03 39 | 3.208000000000000000e+03 5.744000000000000000e+03 40 | 3.244000000000000000e+03 5.782000000000000000e+03 41 | 3.280000000000000000e+03 5.820000000000000000e+03 42 | 3.316000000000000000e+03 5.858000000000000000e+03 43 | 3.352000000000000000e+03 5.896000000000000000e+03 44 | 3.388000000000000000e+03 5.934000000000000000e+03 45 | 3.424000000000000000e+03 5.972000000000000000e+03 46 | 3.460000000000000000e+03 6.010000000000000000e+03 47 | 3.496000000000000000e+03 6.048000000000000000e+03 48 | 3.532000000000000000e+03 6.086000000000000000e+03 49 | 3.568000000000000000e+03 6.124000000000000000e+03 50 | 3.604000000000000000e+03 6.162000000000000000e+03 51 | 3.640000000000000000e+03 6.200000000000000000e+03 52 | 3.676000000000000000e+03 6.238000000000000000e+03 53 | 3.712000000000000000e+03 6.276000000000000000e+03 54 | 3.748000000000000000e+03 6.314000000000000000e+03 55 | 3.784000000000000000e+03 6.352000000000000000e+03 56 | 3.820000000000000000e+03 6.390000000000000000e+03 57 | 3.856000000000000000e+03 6.428000000000000000e+03 58 | 3.892000000000000000e+03 6.466000000000000000e+03 59 | 3.928000000000000000e+03 6.504000000000000000e+03 60 | 3.964000000000000000e+03 6.542000000000000000e+03 61 | 4.000000000000000000e+03 6.580000000000000000e+03 62 | 4.036000000000000000e+03 6.618000000000000000e+03 63 | 4.072000000000000000e+03 6.656000000000000000e+03 64 | -------------------------------------------------------------------------------- /tests/fwi3d/config.ini: -------------------------------------------------------------------------------- 1 | [FWI] 2 | # input for tdfwi code 3 | basepath = /home/xzhang/VIP/tests/fwi3d 4 | # source wavelet file 5 | waveletfile = ${basepath}/data/wavelet.npy 6 | # data file 7 | datafile = ${basepath}/data/data.npy 8 | # source file 9 | srcfile = ${basepath}/data/sources.npy 10 | # receiver file 11 | recfile = ${basepath}/data/receivers.npy 12 | # input directory 13 | inpath = ${basepath}/fwi/inpput 14 | 15 | # output directory 16 | outpath = ${basepath}/fwi/out 17 | 18 | [svgd] 19 | # svgd or ssvgd is supported 20 | method = ssvgd 21 | # kernel function, only rbf or diagonal supported 22 | kernel = rbf 23 | # diagonal kernel 24 | diag = grad 25 | # optimizer, sgd, adam 26 | optimizer = sgd 27 | # using transform (true) or not (false) 28 | transform = true 29 | # grid points in z direction 30 | nz = 63 31 | # grid points in y direction 32 | ny = 101 33 | # grid points in x direction 34 | nx = 101 35 | # grid spacing in z direction 36 | dz = 50 37 | # grid spacing in y direction 38 | dy = 50 39 | # grid spacing in x direction 40 | dx = 50 41 | # prior type, 'Uniform' or 'Gaussian' 42 | priortype = Uniform 43 | # file that contains hyperparameters for prior pdf 44 | prior = ${FWI:basepath}/Uniform_prior.txt 45 | # number of particles 46 | nparticles = 2 47 | # number of iterations 48 | iter = 10 49 | # burn_in period, only used for ssvgd 50 | burn_in = 0 51 | # thining of the chain, only used for ssvgd 52 | thin = 2 53 | # batch size for number of particles, used to save memory 54 | particle_batch = ${nparticles} 55 | # batch size for number of shots 56 | shot_batch = 36 57 | # step length for svgd and ssvgd 58 | stepsize = 0.005 59 | # decay the stepsize exponentially, the final stepsize will be stepsize*final_decay 60 | final_decay = 0.2 61 | # noise level, currently only support a constant number 62 | sigma = 1e-7 63 | # smoothness in x direction, 0 for no smoothness 64 | smoothx = 1000 65 | # smoothness in y direction, 0 for no smoothness 66 | smoothy = 1000 67 | # smoothness in z direction, 0 for no smoothness 68 | smoothz = 1000 69 | # output directory 70 | outpath = ${FWI:basepath}/results 71 | 72 | [dask] 73 | # parallel environment used on a hpc system 74 | pe = parallel_env_name 75 | # number of nodes for each dask worker 76 | nnodes = 2 77 | # number of dask workers, the total nodes required will be nnodes*nworkers 78 | nworkers = ${svgd:nparticles} 79 | # number of threads for each dask worker, usually set to one to let the third-party code decide the number of threads, e.g. by using omp_num_threads 80 | ph = 1 81 | # directory for dask 82 | daskpath = ${FWI:basepath}/dask 83 | -------------------------------------------------------------------------------- /tests/fwi3d/run_job.sh: -------------------------------------------------------------------------------- 1 | PYTHONPATH=/home/xzhang/VIP python vfwi3d.py -r 0 2 | -------------------------------------------------------------------------------- /tests/fwi3d/vfwi3d.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import os 5 | import h5py 6 | import scipy.sparse as sparse 7 | 8 | from vip.prior.transform import trans 9 | from forward.fwi.fwi3d import * 10 | from vip.pyvi.svgd import SVGD, sSVGD 11 | 12 | from datetime import datetime 13 | import time 14 | from scipy.ndimage import gaussian_filter 15 | import configparser 16 | import forward.fwi.dask_utils as du 17 | from vip.prior.prior import prior 18 | from vip.prior.pdf import Uniform, Gaussian 19 | 20 | import argparse 21 | import sys 22 | from pathlib import Path 23 | 24 | def init_vfwi(config): 25 | Path(config.get('FWI','inpath')).mkdir(parents=True, exist_ok=True) 26 | Path(config.get('FWI','outpath')).mkdir(parents=True, exist_ok=True) 27 | Path(config.get('svgd','outpath')).mkdir(parents=True, exist_ok=True) 28 | Path(config.get('dask','daskpath')).mkdir(parents=True, exist_ok=True) 29 | 30 | def generate_init(n=1, lb=0, ub=1e8, transform=True): 31 | eps = np.finfo(np.float).eps 32 | ny = lb.shape[0]; nx = lb.shape[1]; nz = lb.shape[2] 33 | x = lb + (ub-lb)*np.random.uniform(low=eps,high=1-eps,size=(n,ny,nx,nz)) 34 | x = x.reshape((-1,ny*nx*nz)) 35 | if(transform): 36 | x = trans(x,lb=lb.flatten(),ub=ub.flatten(),trans=1) 37 | return x 38 | 39 | def get_init(config, resume=0): 40 | nx = config.getint('svgd','nx') 41 | ny = config.getint('svgd','ny') 42 | nz = config.getint('svgd','nz') 43 | priorfile = config.get('svgd','prior') 44 | prior = np.loadtxt(priorfile) 45 | lower_bnd = prior[:,0].astype(np.float64); upper_bnd = prior[:,1].astype(np.float64) 46 | lower_bnd = np.broadcast_to(lower_bnd[None,None,:],(ny,nx,nz)) 47 | upper_bnd = np.broadcast_to(upper_bnd[None,None,:],(ny,nx,nz)) 48 | if(resume==0): 49 | x0 = generate_init(n=config.getint('svgd','nparticles'), lb=lower_bnd, ub=upper_bnd, 50 | transform=config.getboolean('svgd','transform')) 51 | else: 52 | print("Resume from previous running..") 53 | f = h5py.File(os.path.join(config['svgd']['outpath'],'samples.hdf5'),'r') 54 | x0 = f['samples'][-1,:,:] 55 | x0 = x0.astype(np.float64) 56 | f.close() 57 | x0 = trans(x0,lb=lower_bnd.flatten(),ub=upper_bnd.flatten(),trans=1) 58 | 59 | if(np.isinf(x0).any()): print("Error: inf occured") 60 | if(np.isnan(x0).any()): print("Error: nan occured") 61 | 62 | return x0 63 | 64 | def delta(n): 65 | diag0 = np.full((n,),fill_value=-2); diag0[0]=-1; diag0[-1]=-1 66 | diag1 = np.full((n-1,),fill_value=1) 67 | diagonals = [diag0,diag1,diag1] 68 | D = sparse.diags(diagonals,[0,-1,1]).tocsc() 69 | return D 70 | 71 | def create_prior(config): 72 | # prior info 73 | nx = config.getint('svgd','nx') 74 | ny = config.getint('svgd','ny') 75 | nz = config.getint('svgd','nz') 76 | priorfile = config.get('svgd','prior') 77 | p = np.loadtxt(priorfile) 78 | p1 = p[:,0].astype(np.float64); p2 = p[:,1].astype(np.float64) 79 | p1 = np.broadcast_to(p1[None,None,:],(ny,nx,nz)) 80 | p2 = np.broadcast_to(p2[None,None,:],(ny,nx,nz)) 81 | p1 = p1.flatten() 82 | p2 = p2.flatten() 83 | ptype = config.get('svgd','priortype') 84 | if(ptype == 'Uniform'): 85 | pdf = Uniform(lb=p1, ub=p2) 86 | if(ptype == 'Gaussian'): 87 | pdf = Gaussian(mu=p1, sigma=p2) 88 | 89 | # create smooth matrix 90 | smoothness = False 91 | L = None 92 | smoothx = config.getfloat('svgd','smoothx') 93 | smoothy = config.getfloat('svgd','smoothy') 94 | smoothz = config.getfloat('svgd','smoothz') 95 | if(smoothx>0 and smoothy>0 and smoothz>0): 96 | smoothx = np.full((nz,),fill_value=smoothx) 97 | smoothy = np.full((nz,),fill_value=smoothy) 98 | smoothz = np.full((nz,),fill_value=smoothz) 99 | deltax = delta(nx) 100 | deltay = delta(ny) 101 | deltaz = delta(nz)/smoothz[:,None] 102 | Iy = sparse.eye(ny); Ix = sparse.eye(nx); Iz = sparse.eye(nz) 103 | Sz = sparse.kron(Iy,sparse.kron(Ix,deltaz)) 104 | Sx = sparse.kron(Iy,sparse.kron(deltax,Iz/smoothx)) 105 | Sy = sparse.kron(deltay,sparse.kron(Ix,Iz/smoothy)) 106 | L = sparse.vstack([Sx,Sy,Sz]) 107 | smoothness = True 108 | 109 | if(ptype=='Uniform'): 110 | ppdf = prior(pdf=pdf, transform=config.getboolean('svgd','transform'), lb=p1, ub=p2, smooth=smoothness, L=L) 111 | else: 112 | ppdf = prior(pdf=pdf, smooth=smoothness, L=L) 113 | 114 | return ppdf 115 | 116 | def write_samples(filename, pprior, n=0, chunk=10): 117 | 118 | f = h5py.File(filename,'r+') 119 | samples = f['samples'] 120 | start = 0 121 | if(n>0): 122 | start = samples.shape[0] - n 123 | if(start<0): 124 | start = 0 125 | if(pprior.trans): 126 | for i in range(start,samples.shape[0]): 127 | samples[i,:,:] = pprior.adjust(samples[i,:,:]) 128 | 129 | f.close() 130 | 131 | return 0 132 | 133 | 134 | if __name__=="__main__": 135 | 136 | parser = argparse.ArgumentParser(description='Variational Full-waveform Inversion') 137 | parser.add_argument("-c", "--config", metavar='config', default='config.ini', help="Configuration file") 138 | parser.add_argument("-r", "--resume", metavar='resume', default=0, type=float, help="Resume mode (1) or start a new run(0)") 139 | 140 | args = parser.parse_args() 141 | configfile = args.config 142 | resume = args.resume 143 | 144 | now = datetime.now() 145 | current_time = now.strftime("%Y-%m-%d %H:%M:%S") 146 | print(f'Start VFWI at {current_time}...') 147 | print(f'Config file for VFWI is: {configfile}') 148 | 149 | config = configparser.ConfigParser() 150 | config._interpolation = configparser.ExtendedInterpolation() 151 | config.read(configfile) 152 | 153 | print('Method for VFWI is: '+config['svgd']['method']) 154 | init_vfwi(config) 155 | x0 = get_init(config, resume=resume) 156 | print("Particles size: "+str(x0.shape)) 157 | 158 | daskpath = config.get('dask','daskpath') 159 | print(f'Create dask cluster at: {daskpath}') 160 | cluster, client = du.dask_init(config.get('dask','pe'), config.getint('dask','nnodes'), 161 | nworkers=config.getint('dask','nworkers'), 162 | ph=config.getint('dask','ph'), odask=daskpath) 163 | ppdf = create_prior(config) 164 | 165 | # fwi simulator 166 | nx = config.getint('svgd','nx') 167 | ny = config.getint('svgd','ny') 168 | nz = config.getint('svgd','nz') 169 | mask = np.full((ny,nx,nz),False) 170 | mask[:,:,0] = True 171 | simulator = fwi3d(config, ppdf, mask=mask.flatten(), client=client) 172 | 173 | # svgd sampler 174 | stepsize = config.getfloat('svgd','stepsize') 175 | iteration = config.getint('svgd','iter') 176 | final_decay = config.getfloat('svgd','final_decay') 177 | gamma = final_decay**(1./iteration) 178 | if(config['svgd']['method']=='ssvgd'): 179 | svgd = sSVGD(simulator.dlnprob, 180 | kernel=config['svgd']['kernel'], 181 | mask=mask.flatten(), 182 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 183 | elif(config['svgd']['method']=='svgd'): 184 | svgd = SVGD(simulator.dlnprob, 185 | kernel=config['svgd']['kernel'], 186 | mask=mask.flatten(), 187 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 188 | else: 189 | print('Not supported method') 190 | 191 | # sampling 192 | print('Start sampling ...') 193 | print(f'Iteration: {iteration}') 194 | print(f'Stepsize, decay rate and final decay: {stepsize} {gamma} {final_decay}') 195 | start = time.time() 196 | losses, x = svgd.sample(x0, 197 | n_iter=config.getint('svgd','iter'), 198 | stepsize=stepsize, gamma=gamma, 199 | optimizer=config['svgd']['optimizer'], 200 | burn_in=config.getint('svgd','burn_in'), 201 | thin=config.getint('svgd','thin') 202 | ) 203 | end=time.time() 204 | print('Time taken: '+str(end-start)+' s') 205 | 206 | # write out results 207 | nsamples = int((config.getint('svgd','iter')-config.getint('svgd','burn_in'))/config.getint('svgd','thin')) 208 | write_samples(os.path.join(config.get('svgd','outpath'),'samples.hdf5'), ppdf, n=nsamples) 209 | with open(os.path.join(config.get('svgd','outpath'),'misfits.txt'),"ab") as f: 210 | np.savetxt(f,losses) 211 | 212 | du.dask_del(cluster, client, odask=daskpath) 213 | -------------------------------------------------------------------------------- /tests/tomo2d/config.ini: -------------------------------------------------------------------------------- 1 | [tomo] 2 | # input for tomo2d code 3 | basepath = /home/xzhang/projects/VIP/tests/tomo2d 4 | # source file 5 | srcfile = ${basepath}/input/sources.txt 6 | # receiver file 7 | recfile = ${basepath}/input/receivers.txt 8 | # data file 9 | datafile = ${basepath}/input/ttimes.txt 10 | 11 | # other arguments for tomo2d code 12 | # grid points in x direction (nx) 13 | nx = 21 14 | # grid points in y direction (ny) 15 | ny = 21 16 | # minimum x 17 | xmin = -5.0 18 | # minimum y 19 | ymin = -5.0 20 | # Grid spacing in x direction (dx) 21 | dx = 0.5 22 | # Grid spacing in y direction (dy) 23 | dy = 0.5 24 | # upsampling factor for spacings in x direction (gdx) 25 | gdx = 2 26 | # upsampling factor for spacings in y direction (gdy) 27 | gdy = 2 28 | # source refinement factor (upsampling) 29 | sdx = 4 30 | # source refinement area in grid points 31 | sext = 4 32 | # earth 33 | earth = 0 34 | 35 | [svgd] 36 | # svgd or ssvgd is supported 37 | method = ssvgd 38 | # kernel function, only rbf or diagonal supported 39 | kernel = rbf 40 | # diagonal kernel 41 | diag = grad 42 | # optimizer, sgd, adam 43 | optimizer = sgd 44 | # using transform (true) or not (false) 45 | transform = true 46 | # prior type, 'Uniform' or 'Gaussian' 47 | priortype = Uniform 48 | # file that contains hyperparameters for prior pdf 49 | prior = ${tomo:basepath}/input/Uniform_prior.txt 50 | # number of particles 51 | nparticles = 20 52 | # number of iterations 53 | iter = 4000 54 | # burn_in period, only used for ssvgd 55 | burn_in = 0 56 | # thining of the chain, only used for ssvgd 57 | thin = 2 58 | # step length for svgd and ssvgd 59 | stepsize = 0.05 60 | # decay the stepsize exponentially, the final stepsize will be stepsize*final_decay 61 | final_decay = 1.0 62 | # noise level, currently only support a constant number 63 | sigma = 0.05 64 | # smoothness in x direction, 0 for no smoothness 65 | smoothx = 0 66 | # smoothness in y direction, 0 for no smoothness 67 | smoothy = 0 68 | # output directory 69 | outpath = ${tomo:basepath}/results 70 | -------------------------------------------------------------------------------- /tests/tomo2d/input/Uniform_prior.txt: -------------------------------------------------------------------------------- 1 | 5.000000000000000000e-01 3.000000000000000000e+00 2 | 5.000000000000000000e-01 3.000000000000000000e+00 3 | 5.000000000000000000e-01 3.000000000000000000e+00 4 | 5.000000000000000000e-01 3.000000000000000000e+00 5 | 5.000000000000000000e-01 3.000000000000000000e+00 6 | 5.000000000000000000e-01 3.000000000000000000e+00 7 | 5.000000000000000000e-01 3.000000000000000000e+00 8 | 5.000000000000000000e-01 3.000000000000000000e+00 9 | 5.000000000000000000e-01 3.000000000000000000e+00 10 | 5.000000000000000000e-01 3.000000000000000000e+00 11 | 5.000000000000000000e-01 3.000000000000000000e+00 12 | 5.000000000000000000e-01 3.000000000000000000e+00 13 | 5.000000000000000000e-01 3.000000000000000000e+00 14 | 5.000000000000000000e-01 3.000000000000000000e+00 15 | 5.000000000000000000e-01 3.000000000000000000e+00 16 | 5.000000000000000000e-01 3.000000000000000000e+00 17 | 5.000000000000000000e-01 3.000000000000000000e+00 18 | 5.000000000000000000e-01 3.000000000000000000e+00 19 | 5.000000000000000000e-01 3.000000000000000000e+00 20 | 5.000000000000000000e-01 3.000000000000000000e+00 21 | 5.000000000000000000e-01 3.000000000000000000e+00 22 | 5.000000000000000000e-01 3.000000000000000000e+00 23 | 5.000000000000000000e-01 3.000000000000000000e+00 24 | 5.000000000000000000e-01 3.000000000000000000e+00 25 | 5.000000000000000000e-01 3.000000000000000000e+00 26 | 5.000000000000000000e-01 3.000000000000000000e+00 27 | 5.000000000000000000e-01 3.000000000000000000e+00 28 | 5.000000000000000000e-01 3.000000000000000000e+00 29 | 5.000000000000000000e-01 3.000000000000000000e+00 30 | 5.000000000000000000e-01 3.000000000000000000e+00 31 | 5.000000000000000000e-01 3.000000000000000000e+00 32 | 5.000000000000000000e-01 3.000000000000000000e+00 33 | 5.000000000000000000e-01 3.000000000000000000e+00 34 | 5.000000000000000000e-01 3.000000000000000000e+00 35 | 5.000000000000000000e-01 3.000000000000000000e+00 36 | 5.000000000000000000e-01 3.000000000000000000e+00 37 | 5.000000000000000000e-01 3.000000000000000000e+00 38 | 5.000000000000000000e-01 3.000000000000000000e+00 39 | 5.000000000000000000e-01 3.000000000000000000e+00 40 | 5.000000000000000000e-01 3.000000000000000000e+00 41 | 5.000000000000000000e-01 3.000000000000000000e+00 42 | 5.000000000000000000e-01 3.000000000000000000e+00 43 | 5.000000000000000000e-01 3.000000000000000000e+00 44 | 5.000000000000000000e-01 3.000000000000000000e+00 45 | 5.000000000000000000e-01 3.000000000000000000e+00 46 | 5.000000000000000000e-01 3.000000000000000000e+00 47 | 5.000000000000000000e-01 3.000000000000000000e+00 48 | 5.000000000000000000e-01 3.000000000000000000e+00 49 | 5.000000000000000000e-01 3.000000000000000000e+00 50 | 5.000000000000000000e-01 3.000000000000000000e+00 51 | 5.000000000000000000e-01 3.000000000000000000e+00 52 | 5.000000000000000000e-01 3.000000000000000000e+00 53 | 5.000000000000000000e-01 3.000000000000000000e+00 54 | 5.000000000000000000e-01 3.000000000000000000e+00 55 | 5.000000000000000000e-01 3.000000000000000000e+00 56 | 5.000000000000000000e-01 3.000000000000000000e+00 57 | 5.000000000000000000e-01 3.000000000000000000e+00 58 | 5.000000000000000000e-01 3.000000000000000000e+00 59 | 5.000000000000000000e-01 3.000000000000000000e+00 60 | 5.000000000000000000e-01 3.000000000000000000e+00 61 | 5.000000000000000000e-01 3.000000000000000000e+00 62 | 5.000000000000000000e-01 3.000000000000000000e+00 63 | 5.000000000000000000e-01 3.000000000000000000e+00 64 | 5.000000000000000000e-01 3.000000000000000000e+00 65 | 5.000000000000000000e-01 3.000000000000000000e+00 66 | 5.000000000000000000e-01 3.000000000000000000e+00 67 | 5.000000000000000000e-01 3.000000000000000000e+00 68 | 5.000000000000000000e-01 3.000000000000000000e+00 69 | 5.000000000000000000e-01 3.000000000000000000e+00 70 | 5.000000000000000000e-01 3.000000000000000000e+00 71 | 5.000000000000000000e-01 3.000000000000000000e+00 72 | 5.000000000000000000e-01 3.000000000000000000e+00 73 | 5.000000000000000000e-01 3.000000000000000000e+00 74 | 5.000000000000000000e-01 3.000000000000000000e+00 75 | 5.000000000000000000e-01 3.000000000000000000e+00 76 | 5.000000000000000000e-01 3.000000000000000000e+00 77 | 5.000000000000000000e-01 3.000000000000000000e+00 78 | 5.000000000000000000e-01 3.000000000000000000e+00 79 | 5.000000000000000000e-01 3.000000000000000000e+00 80 | 5.000000000000000000e-01 3.000000000000000000e+00 81 | 5.000000000000000000e-01 3.000000000000000000e+00 82 | 5.000000000000000000e-01 3.000000000000000000e+00 83 | 5.000000000000000000e-01 3.000000000000000000e+00 84 | 5.000000000000000000e-01 3.000000000000000000e+00 85 | 5.000000000000000000e-01 3.000000000000000000e+00 86 | 5.000000000000000000e-01 3.000000000000000000e+00 87 | 5.000000000000000000e-01 3.000000000000000000e+00 88 | 5.000000000000000000e-01 3.000000000000000000e+00 89 | 5.000000000000000000e-01 3.000000000000000000e+00 90 | 5.000000000000000000e-01 3.000000000000000000e+00 91 | 5.000000000000000000e-01 3.000000000000000000e+00 92 | 5.000000000000000000e-01 3.000000000000000000e+00 93 | 5.000000000000000000e-01 3.000000000000000000e+00 94 | 5.000000000000000000e-01 3.000000000000000000e+00 95 | 5.000000000000000000e-01 3.000000000000000000e+00 96 | 5.000000000000000000e-01 3.000000000000000000e+00 97 | 5.000000000000000000e-01 3.000000000000000000e+00 98 | 5.000000000000000000e-01 3.000000000000000000e+00 99 | 5.000000000000000000e-01 3.000000000000000000e+00 100 | 5.000000000000000000e-01 3.000000000000000000e+00 101 | 5.000000000000000000e-01 3.000000000000000000e+00 102 | 5.000000000000000000e-01 3.000000000000000000e+00 103 | 5.000000000000000000e-01 3.000000000000000000e+00 104 | 5.000000000000000000e-01 3.000000000000000000e+00 105 | 5.000000000000000000e-01 3.000000000000000000e+00 106 | 5.000000000000000000e-01 3.000000000000000000e+00 107 | 5.000000000000000000e-01 3.000000000000000000e+00 108 | 5.000000000000000000e-01 3.000000000000000000e+00 109 | 5.000000000000000000e-01 3.000000000000000000e+00 110 | 5.000000000000000000e-01 3.000000000000000000e+00 111 | 5.000000000000000000e-01 3.000000000000000000e+00 112 | 5.000000000000000000e-01 3.000000000000000000e+00 113 | 5.000000000000000000e-01 3.000000000000000000e+00 114 | 5.000000000000000000e-01 3.000000000000000000e+00 115 | 5.000000000000000000e-01 3.000000000000000000e+00 116 | 5.000000000000000000e-01 3.000000000000000000e+00 117 | 5.000000000000000000e-01 3.000000000000000000e+00 118 | 5.000000000000000000e-01 3.000000000000000000e+00 119 | 5.000000000000000000e-01 3.000000000000000000e+00 120 | 5.000000000000000000e-01 3.000000000000000000e+00 121 | 5.000000000000000000e-01 3.000000000000000000e+00 122 | 5.000000000000000000e-01 3.000000000000000000e+00 123 | 5.000000000000000000e-01 3.000000000000000000e+00 124 | 5.000000000000000000e-01 3.000000000000000000e+00 125 | 5.000000000000000000e-01 3.000000000000000000e+00 126 | 5.000000000000000000e-01 3.000000000000000000e+00 127 | 5.000000000000000000e-01 3.000000000000000000e+00 128 | 5.000000000000000000e-01 3.000000000000000000e+00 129 | 5.000000000000000000e-01 3.000000000000000000e+00 130 | 5.000000000000000000e-01 3.000000000000000000e+00 131 | 5.000000000000000000e-01 3.000000000000000000e+00 132 | 5.000000000000000000e-01 3.000000000000000000e+00 133 | 5.000000000000000000e-01 3.000000000000000000e+00 134 | 5.000000000000000000e-01 3.000000000000000000e+00 135 | 5.000000000000000000e-01 3.000000000000000000e+00 136 | 5.000000000000000000e-01 3.000000000000000000e+00 137 | 5.000000000000000000e-01 3.000000000000000000e+00 138 | 5.000000000000000000e-01 3.000000000000000000e+00 139 | 5.000000000000000000e-01 3.000000000000000000e+00 140 | 5.000000000000000000e-01 3.000000000000000000e+00 141 | 5.000000000000000000e-01 3.000000000000000000e+00 142 | 5.000000000000000000e-01 3.000000000000000000e+00 143 | 5.000000000000000000e-01 3.000000000000000000e+00 144 | 5.000000000000000000e-01 3.000000000000000000e+00 145 | 5.000000000000000000e-01 3.000000000000000000e+00 146 | 5.000000000000000000e-01 3.000000000000000000e+00 147 | 5.000000000000000000e-01 3.000000000000000000e+00 148 | 5.000000000000000000e-01 3.000000000000000000e+00 149 | 5.000000000000000000e-01 3.000000000000000000e+00 150 | 5.000000000000000000e-01 3.000000000000000000e+00 151 | 5.000000000000000000e-01 3.000000000000000000e+00 152 | 5.000000000000000000e-01 3.000000000000000000e+00 153 | 5.000000000000000000e-01 3.000000000000000000e+00 154 | 5.000000000000000000e-01 3.000000000000000000e+00 155 | 5.000000000000000000e-01 3.000000000000000000e+00 156 | 5.000000000000000000e-01 3.000000000000000000e+00 157 | 5.000000000000000000e-01 3.000000000000000000e+00 158 | 5.000000000000000000e-01 3.000000000000000000e+00 159 | 5.000000000000000000e-01 3.000000000000000000e+00 160 | 5.000000000000000000e-01 3.000000000000000000e+00 161 | 5.000000000000000000e-01 3.000000000000000000e+00 162 | 5.000000000000000000e-01 3.000000000000000000e+00 163 | 5.000000000000000000e-01 3.000000000000000000e+00 164 | 5.000000000000000000e-01 3.000000000000000000e+00 165 | 5.000000000000000000e-01 3.000000000000000000e+00 166 | 5.000000000000000000e-01 3.000000000000000000e+00 167 | 5.000000000000000000e-01 3.000000000000000000e+00 168 | 5.000000000000000000e-01 3.000000000000000000e+00 169 | 5.000000000000000000e-01 3.000000000000000000e+00 170 | 5.000000000000000000e-01 3.000000000000000000e+00 171 | 5.000000000000000000e-01 3.000000000000000000e+00 172 | 5.000000000000000000e-01 3.000000000000000000e+00 173 | 5.000000000000000000e-01 3.000000000000000000e+00 174 | 5.000000000000000000e-01 3.000000000000000000e+00 175 | 5.000000000000000000e-01 3.000000000000000000e+00 176 | 5.000000000000000000e-01 3.000000000000000000e+00 177 | 5.000000000000000000e-01 3.000000000000000000e+00 178 | 5.000000000000000000e-01 3.000000000000000000e+00 179 | 5.000000000000000000e-01 3.000000000000000000e+00 180 | 5.000000000000000000e-01 3.000000000000000000e+00 181 | 5.000000000000000000e-01 3.000000000000000000e+00 182 | 5.000000000000000000e-01 3.000000000000000000e+00 183 | 5.000000000000000000e-01 3.000000000000000000e+00 184 | 5.000000000000000000e-01 3.000000000000000000e+00 185 | 5.000000000000000000e-01 3.000000000000000000e+00 186 | 5.000000000000000000e-01 3.000000000000000000e+00 187 | 5.000000000000000000e-01 3.000000000000000000e+00 188 | 5.000000000000000000e-01 3.000000000000000000e+00 189 | 5.000000000000000000e-01 3.000000000000000000e+00 190 | 5.000000000000000000e-01 3.000000000000000000e+00 191 | 5.000000000000000000e-01 3.000000000000000000e+00 192 | 5.000000000000000000e-01 3.000000000000000000e+00 193 | 5.000000000000000000e-01 3.000000000000000000e+00 194 | 5.000000000000000000e-01 3.000000000000000000e+00 195 | 5.000000000000000000e-01 3.000000000000000000e+00 196 | 5.000000000000000000e-01 3.000000000000000000e+00 197 | 5.000000000000000000e-01 3.000000000000000000e+00 198 | 5.000000000000000000e-01 3.000000000000000000e+00 199 | 5.000000000000000000e-01 3.000000000000000000e+00 200 | 5.000000000000000000e-01 3.000000000000000000e+00 201 | 5.000000000000000000e-01 3.000000000000000000e+00 202 | 5.000000000000000000e-01 3.000000000000000000e+00 203 | 5.000000000000000000e-01 3.000000000000000000e+00 204 | 5.000000000000000000e-01 3.000000000000000000e+00 205 | 5.000000000000000000e-01 3.000000000000000000e+00 206 | 5.000000000000000000e-01 3.000000000000000000e+00 207 | 5.000000000000000000e-01 3.000000000000000000e+00 208 | 5.000000000000000000e-01 3.000000000000000000e+00 209 | 5.000000000000000000e-01 3.000000000000000000e+00 210 | 5.000000000000000000e-01 3.000000000000000000e+00 211 | 5.000000000000000000e-01 3.000000000000000000e+00 212 | 5.000000000000000000e-01 3.000000000000000000e+00 213 | 5.000000000000000000e-01 3.000000000000000000e+00 214 | 5.000000000000000000e-01 3.000000000000000000e+00 215 | 5.000000000000000000e-01 3.000000000000000000e+00 216 | 5.000000000000000000e-01 3.000000000000000000e+00 217 | 5.000000000000000000e-01 3.000000000000000000e+00 218 | 5.000000000000000000e-01 3.000000000000000000e+00 219 | 5.000000000000000000e-01 3.000000000000000000e+00 220 | 5.000000000000000000e-01 3.000000000000000000e+00 221 | 5.000000000000000000e-01 3.000000000000000000e+00 222 | 5.000000000000000000e-01 3.000000000000000000e+00 223 | 5.000000000000000000e-01 3.000000000000000000e+00 224 | 5.000000000000000000e-01 3.000000000000000000e+00 225 | 5.000000000000000000e-01 3.000000000000000000e+00 226 | 5.000000000000000000e-01 3.000000000000000000e+00 227 | 5.000000000000000000e-01 3.000000000000000000e+00 228 | 5.000000000000000000e-01 3.000000000000000000e+00 229 | 5.000000000000000000e-01 3.000000000000000000e+00 230 | 5.000000000000000000e-01 3.000000000000000000e+00 231 | 5.000000000000000000e-01 3.000000000000000000e+00 232 | 5.000000000000000000e-01 3.000000000000000000e+00 233 | 5.000000000000000000e-01 3.000000000000000000e+00 234 | 5.000000000000000000e-01 3.000000000000000000e+00 235 | 5.000000000000000000e-01 3.000000000000000000e+00 236 | 5.000000000000000000e-01 3.000000000000000000e+00 237 | 5.000000000000000000e-01 3.000000000000000000e+00 238 | 5.000000000000000000e-01 3.000000000000000000e+00 239 | 5.000000000000000000e-01 3.000000000000000000e+00 240 | 5.000000000000000000e-01 3.000000000000000000e+00 241 | 5.000000000000000000e-01 3.000000000000000000e+00 242 | 5.000000000000000000e-01 3.000000000000000000e+00 243 | 5.000000000000000000e-01 3.000000000000000000e+00 244 | 5.000000000000000000e-01 3.000000000000000000e+00 245 | 5.000000000000000000e-01 3.000000000000000000e+00 246 | 5.000000000000000000e-01 3.000000000000000000e+00 247 | 5.000000000000000000e-01 3.000000000000000000e+00 248 | 5.000000000000000000e-01 3.000000000000000000e+00 249 | 5.000000000000000000e-01 3.000000000000000000e+00 250 | 5.000000000000000000e-01 3.000000000000000000e+00 251 | 5.000000000000000000e-01 3.000000000000000000e+00 252 | 5.000000000000000000e-01 3.000000000000000000e+00 253 | 5.000000000000000000e-01 3.000000000000000000e+00 254 | 5.000000000000000000e-01 3.000000000000000000e+00 255 | 5.000000000000000000e-01 3.000000000000000000e+00 256 | 5.000000000000000000e-01 3.000000000000000000e+00 257 | 5.000000000000000000e-01 3.000000000000000000e+00 258 | 5.000000000000000000e-01 3.000000000000000000e+00 259 | 5.000000000000000000e-01 3.000000000000000000e+00 260 | 5.000000000000000000e-01 3.000000000000000000e+00 261 | 5.000000000000000000e-01 3.000000000000000000e+00 262 | 5.000000000000000000e-01 3.000000000000000000e+00 263 | 5.000000000000000000e-01 3.000000000000000000e+00 264 | 5.000000000000000000e-01 3.000000000000000000e+00 265 | 5.000000000000000000e-01 3.000000000000000000e+00 266 | 5.000000000000000000e-01 3.000000000000000000e+00 267 | 5.000000000000000000e-01 3.000000000000000000e+00 268 | 5.000000000000000000e-01 3.000000000000000000e+00 269 | 5.000000000000000000e-01 3.000000000000000000e+00 270 | 5.000000000000000000e-01 3.000000000000000000e+00 271 | 5.000000000000000000e-01 3.000000000000000000e+00 272 | 5.000000000000000000e-01 3.000000000000000000e+00 273 | 5.000000000000000000e-01 3.000000000000000000e+00 274 | 5.000000000000000000e-01 3.000000000000000000e+00 275 | 5.000000000000000000e-01 3.000000000000000000e+00 276 | 5.000000000000000000e-01 3.000000000000000000e+00 277 | 5.000000000000000000e-01 3.000000000000000000e+00 278 | 5.000000000000000000e-01 3.000000000000000000e+00 279 | 5.000000000000000000e-01 3.000000000000000000e+00 280 | 5.000000000000000000e-01 3.000000000000000000e+00 281 | 5.000000000000000000e-01 3.000000000000000000e+00 282 | 5.000000000000000000e-01 3.000000000000000000e+00 283 | 5.000000000000000000e-01 3.000000000000000000e+00 284 | 5.000000000000000000e-01 3.000000000000000000e+00 285 | 5.000000000000000000e-01 3.000000000000000000e+00 286 | 5.000000000000000000e-01 3.000000000000000000e+00 287 | 5.000000000000000000e-01 3.000000000000000000e+00 288 | 5.000000000000000000e-01 3.000000000000000000e+00 289 | 5.000000000000000000e-01 3.000000000000000000e+00 290 | 5.000000000000000000e-01 3.000000000000000000e+00 291 | 5.000000000000000000e-01 3.000000000000000000e+00 292 | 5.000000000000000000e-01 3.000000000000000000e+00 293 | 5.000000000000000000e-01 3.000000000000000000e+00 294 | 5.000000000000000000e-01 3.000000000000000000e+00 295 | 5.000000000000000000e-01 3.000000000000000000e+00 296 | 5.000000000000000000e-01 3.000000000000000000e+00 297 | 5.000000000000000000e-01 3.000000000000000000e+00 298 | 5.000000000000000000e-01 3.000000000000000000e+00 299 | 5.000000000000000000e-01 3.000000000000000000e+00 300 | 5.000000000000000000e-01 3.000000000000000000e+00 301 | 5.000000000000000000e-01 3.000000000000000000e+00 302 | 5.000000000000000000e-01 3.000000000000000000e+00 303 | 5.000000000000000000e-01 3.000000000000000000e+00 304 | 5.000000000000000000e-01 3.000000000000000000e+00 305 | 5.000000000000000000e-01 3.000000000000000000e+00 306 | 5.000000000000000000e-01 3.000000000000000000e+00 307 | 5.000000000000000000e-01 3.000000000000000000e+00 308 | 5.000000000000000000e-01 3.000000000000000000e+00 309 | 5.000000000000000000e-01 3.000000000000000000e+00 310 | 5.000000000000000000e-01 3.000000000000000000e+00 311 | 5.000000000000000000e-01 3.000000000000000000e+00 312 | 5.000000000000000000e-01 3.000000000000000000e+00 313 | 5.000000000000000000e-01 3.000000000000000000e+00 314 | 5.000000000000000000e-01 3.000000000000000000e+00 315 | 5.000000000000000000e-01 3.000000000000000000e+00 316 | 5.000000000000000000e-01 3.000000000000000000e+00 317 | 5.000000000000000000e-01 3.000000000000000000e+00 318 | 5.000000000000000000e-01 3.000000000000000000e+00 319 | 5.000000000000000000e-01 3.000000000000000000e+00 320 | 5.000000000000000000e-01 3.000000000000000000e+00 321 | 5.000000000000000000e-01 3.000000000000000000e+00 322 | 5.000000000000000000e-01 3.000000000000000000e+00 323 | 5.000000000000000000e-01 3.000000000000000000e+00 324 | 5.000000000000000000e-01 3.000000000000000000e+00 325 | 5.000000000000000000e-01 3.000000000000000000e+00 326 | 5.000000000000000000e-01 3.000000000000000000e+00 327 | 5.000000000000000000e-01 3.000000000000000000e+00 328 | 5.000000000000000000e-01 3.000000000000000000e+00 329 | 5.000000000000000000e-01 3.000000000000000000e+00 330 | 5.000000000000000000e-01 3.000000000000000000e+00 331 | 5.000000000000000000e-01 3.000000000000000000e+00 332 | 5.000000000000000000e-01 3.000000000000000000e+00 333 | 5.000000000000000000e-01 3.000000000000000000e+00 334 | 5.000000000000000000e-01 3.000000000000000000e+00 335 | 5.000000000000000000e-01 3.000000000000000000e+00 336 | 5.000000000000000000e-01 3.000000000000000000e+00 337 | 5.000000000000000000e-01 3.000000000000000000e+00 338 | 5.000000000000000000e-01 3.000000000000000000e+00 339 | 5.000000000000000000e-01 3.000000000000000000e+00 340 | 5.000000000000000000e-01 3.000000000000000000e+00 341 | 5.000000000000000000e-01 3.000000000000000000e+00 342 | 5.000000000000000000e-01 3.000000000000000000e+00 343 | 5.000000000000000000e-01 3.000000000000000000e+00 344 | 5.000000000000000000e-01 3.000000000000000000e+00 345 | 5.000000000000000000e-01 3.000000000000000000e+00 346 | 5.000000000000000000e-01 3.000000000000000000e+00 347 | 5.000000000000000000e-01 3.000000000000000000e+00 348 | 5.000000000000000000e-01 3.000000000000000000e+00 349 | 5.000000000000000000e-01 3.000000000000000000e+00 350 | 5.000000000000000000e-01 3.000000000000000000e+00 351 | 5.000000000000000000e-01 3.000000000000000000e+00 352 | 5.000000000000000000e-01 3.000000000000000000e+00 353 | 5.000000000000000000e-01 3.000000000000000000e+00 354 | 5.000000000000000000e-01 3.000000000000000000e+00 355 | 5.000000000000000000e-01 3.000000000000000000e+00 356 | 5.000000000000000000e-01 3.000000000000000000e+00 357 | 5.000000000000000000e-01 3.000000000000000000e+00 358 | 5.000000000000000000e-01 3.000000000000000000e+00 359 | 5.000000000000000000e-01 3.000000000000000000e+00 360 | 5.000000000000000000e-01 3.000000000000000000e+00 361 | 5.000000000000000000e-01 3.000000000000000000e+00 362 | 5.000000000000000000e-01 3.000000000000000000e+00 363 | 5.000000000000000000e-01 3.000000000000000000e+00 364 | 5.000000000000000000e-01 3.000000000000000000e+00 365 | 5.000000000000000000e-01 3.000000000000000000e+00 366 | 5.000000000000000000e-01 3.000000000000000000e+00 367 | 5.000000000000000000e-01 3.000000000000000000e+00 368 | 5.000000000000000000e-01 3.000000000000000000e+00 369 | 5.000000000000000000e-01 3.000000000000000000e+00 370 | 5.000000000000000000e-01 3.000000000000000000e+00 371 | 5.000000000000000000e-01 3.000000000000000000e+00 372 | 5.000000000000000000e-01 3.000000000000000000e+00 373 | 5.000000000000000000e-01 3.000000000000000000e+00 374 | 5.000000000000000000e-01 3.000000000000000000e+00 375 | 5.000000000000000000e-01 3.000000000000000000e+00 376 | 5.000000000000000000e-01 3.000000000000000000e+00 377 | 5.000000000000000000e-01 3.000000000000000000e+00 378 | 5.000000000000000000e-01 3.000000000000000000e+00 379 | 5.000000000000000000e-01 3.000000000000000000e+00 380 | 5.000000000000000000e-01 3.000000000000000000e+00 381 | 5.000000000000000000e-01 3.000000000000000000e+00 382 | 5.000000000000000000e-01 3.000000000000000000e+00 383 | 5.000000000000000000e-01 3.000000000000000000e+00 384 | 5.000000000000000000e-01 3.000000000000000000e+00 385 | 5.000000000000000000e-01 3.000000000000000000e+00 386 | 5.000000000000000000e-01 3.000000000000000000e+00 387 | 5.000000000000000000e-01 3.000000000000000000e+00 388 | 5.000000000000000000e-01 3.000000000000000000e+00 389 | 5.000000000000000000e-01 3.000000000000000000e+00 390 | 5.000000000000000000e-01 3.000000000000000000e+00 391 | 5.000000000000000000e-01 3.000000000000000000e+00 392 | 5.000000000000000000e-01 3.000000000000000000e+00 393 | 5.000000000000000000e-01 3.000000000000000000e+00 394 | 5.000000000000000000e-01 3.000000000000000000e+00 395 | 5.000000000000000000e-01 3.000000000000000000e+00 396 | 5.000000000000000000e-01 3.000000000000000000e+00 397 | 5.000000000000000000e-01 3.000000000000000000e+00 398 | 5.000000000000000000e-01 3.000000000000000000e+00 399 | 5.000000000000000000e-01 3.000000000000000000e+00 400 | 5.000000000000000000e-01 3.000000000000000000e+00 401 | 5.000000000000000000e-01 3.000000000000000000e+00 402 | 5.000000000000000000e-01 3.000000000000000000e+00 403 | 5.000000000000000000e-01 3.000000000000000000e+00 404 | 5.000000000000000000e-01 3.000000000000000000e+00 405 | 5.000000000000000000e-01 3.000000000000000000e+00 406 | 5.000000000000000000e-01 3.000000000000000000e+00 407 | 5.000000000000000000e-01 3.000000000000000000e+00 408 | 5.000000000000000000e-01 3.000000000000000000e+00 409 | 5.000000000000000000e-01 3.000000000000000000e+00 410 | 5.000000000000000000e-01 3.000000000000000000e+00 411 | 5.000000000000000000e-01 3.000000000000000000e+00 412 | 5.000000000000000000e-01 3.000000000000000000e+00 413 | 5.000000000000000000e-01 3.000000000000000000e+00 414 | 5.000000000000000000e-01 3.000000000000000000e+00 415 | 5.000000000000000000e-01 3.000000000000000000e+00 416 | 5.000000000000000000e-01 3.000000000000000000e+00 417 | 5.000000000000000000e-01 3.000000000000000000e+00 418 | 5.000000000000000000e-01 3.000000000000000000e+00 419 | 5.000000000000000000e-01 3.000000000000000000e+00 420 | 5.000000000000000000e-01 3.000000000000000000e+00 421 | 5.000000000000000000e-01 3.000000000000000000e+00 422 | 5.000000000000000000e-01 3.000000000000000000e+00 423 | 5.000000000000000000e-01 3.000000000000000000e+00 424 | 5.000000000000000000e-01 3.000000000000000000e+00 425 | 5.000000000000000000e-01 3.000000000000000000e+00 426 | 5.000000000000000000e-01 3.000000000000000000e+00 427 | 5.000000000000000000e-01 3.000000000000000000e+00 428 | 5.000000000000000000e-01 3.000000000000000000e+00 429 | 5.000000000000000000e-01 3.000000000000000000e+00 430 | 5.000000000000000000e-01 3.000000000000000000e+00 431 | 5.000000000000000000e-01 3.000000000000000000e+00 432 | 5.000000000000000000e-01 3.000000000000000000e+00 433 | 5.000000000000000000e-01 3.000000000000000000e+00 434 | 5.000000000000000000e-01 3.000000000000000000e+00 435 | 5.000000000000000000e-01 3.000000000000000000e+00 436 | 5.000000000000000000e-01 3.000000000000000000e+00 437 | 5.000000000000000000e-01 3.000000000000000000e+00 438 | 5.000000000000000000e-01 3.000000000000000000e+00 439 | 5.000000000000000000e-01 3.000000000000000000e+00 440 | 5.000000000000000000e-01 3.000000000000000000e+00 441 | 5.000000000000000000e-01 3.000000000000000000e+00 442 | -------------------------------------------------------------------------------- /tests/tomo2d/input/receivers.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 4.000000000000000000e+00 2 | 1.530733729460359127e+00 3.695518130045146954e+00 3 | 2.828427124746189847e+00 2.828427124746190291e+00 4 | 3.695518130045146954e+00 1.530733729460359349e+00 5 | 4.000000000000000000e+00 0.000000000000000000e+00 6 | 3.695518130045146954e+00 -1.530733729460358905e+00 7 | 2.828427124746190291e+00 -2.828427124746189847e+00 8 | 1.530733729460359571e+00 -3.695518130045146954e+00 9 | 0.000000000000000000e+00 -4.000000000000000000e+00 10 | -1.530733729460358683e+00 -3.695518130045147398e+00 11 | -2.828427124746189847e+00 -2.828427124746190735e+00 12 | -3.695518130045146066e+00 -1.530733729460361348e+00 13 | -4.000000000000000000e+00 0.000000000000000000e+00 14 | -3.695518130045146510e+00 1.530733729460360015e+00 15 | -2.828427124746190735e+00 2.828427124746189403e+00 16 | -1.530733729460361570e+00 3.695518130045146066e+00 17 | -------------------------------------------------------------------------------- /tests/tomo2d/input/sources.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 4.000000000000000000e+00 2 | 1.530733729460359127e+00 3.695518130045146954e+00 3 | 2.828427124746189847e+00 2.828427124746190291e+00 4 | 3.695518130045146954e+00 1.530733729460359349e+00 5 | 4.000000000000000000e+00 0.000000000000000000e+00 6 | 3.695518130045146954e+00 -1.530733729460358905e+00 7 | 2.828427124746190291e+00 -2.828427124746189847e+00 8 | 1.530733729460359571e+00 -3.695518130045146954e+00 9 | 0.000000000000000000e+00 -4.000000000000000000e+00 10 | -1.530733729460358683e+00 -3.695518130045147398e+00 11 | -2.828427124746189847e+00 -2.828427124746190735e+00 12 | -3.695518130045146066e+00 -1.530733729460361348e+00 13 | -4.000000000000000000e+00 0.000000000000000000e+00 14 | -3.695518130045146510e+00 1.530733729460360015e+00 15 | -2.828427124746190735e+00 2.828427124746189403e+00 16 | -1.530733729460361570e+00 3.695518130045146066e+00 17 | -------------------------------------------------------------------------------- /tests/tomo2d/input/ttimes.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 0.05 2 | 7.822908527013709978e-01 0.05 3 | 1.531190400915316996e+00 0.05 4 | 2.221008980139279387e+00 0.05 5 | 2.826428260055865227e+00 0.05 6 | 3.321295842521808872e+00 0.05 7 | 3.740054714326477736e+00 0.05 8 | 4.153012356439563568e+00 0.05 9 | 4.562746899896820807e+00 0.05 10 | 4.153200138487457949e+00 0.05 11 | 3.740228674323302194e+00 0.05 12 | 3.321297353158600085e+00 0.05 13 | 2.826428263119019846e+00 0.05 14 | 2.221008980139278499e+00 0.05 15 | 1.531190400915317662e+00 0.05 16 | 7.822908527013724411e-01 0.05 17 | 0.000000000000000000e+00 0.05 18 | 0.000000000000000000e+00 0.05 19 | 7.883876043158537517e-01 0.05 20 | 1.537516296222571910e+00 0.05 21 | 2.228592710027766266e+00 0.05 22 | 2.835004534305670010e+00 0.05 23 | 3.332536286062123043e+00 0.05 24 | 3.749084475942771277e+00 0.05 25 | 4.158819196344874847e+00 0.05 26 | 4.558057921353831254e+00 0.05 27 | 4.150889147035835336e+00 0.05 28 | 3.733109138287197037e+00 0.05 29 | 3.325349388774281323e+00 0.05 30 | 2.830068294594196399e+00 0.05 31 | 2.225329714903131695e+00 0.05 32 | 1.531570100813081092e+00 0.05 33 | 0.000000000000000000e+00 0.05 34 | 0.000000000000000000e+00 0.05 35 | 0.000000000000000000e+00 0.05 36 | 7.804149329948364411e-01 0.05 37 | 1.531449135630706726e+00 0.05 38 | 2.224093217106712039e+00 0.05 39 | 2.830783004060922092e+00 0.05 40 | 3.328979842897886954e+00 0.05 41 | 3.742122642488185935e+00 0.05 42 | 4.148150344915098486e+00 0.05 43 | 4.558638127831506459e+00 0.05 44 | 4.146161253588626749e+00 0.05 45 | 3.740133467926203270e+00 0.05 46 | 3.327097405325757595e+00 0.05 47 | 2.830766428722859551e+00 0.05 48 | 2.225980564113422044e+00 0.05 49 | 0.000000000000000000e+00 0.05 50 | 0.000000000000000000e+00 0.05 51 | 0.000000000000000000e+00 0.05 52 | 0.000000000000000000e+00 0.05 53 | 7.825420195701392467e-01 0.05 54 | 1.531570100813079982e+00 0.05 55 | 2.225329714903131695e+00 0.05 56 | 2.830068294594198175e+00 0.05 57 | 3.325349388774284876e+00 0.05 58 | 3.733109138287200146e+00 0.05 59 | 4.150889147035843330e+00 0.05 60 | 4.558057921353833919e+00 0.05 61 | 4.158819196344871294e+00 0.05 62 | 3.749084475942768613e+00 0.05 63 | 3.332536286062125264e+00 0.05 64 | 2.835004534305670898e+00 0.05 65 | 0.000000000000000000e+00 0.05 66 | 0.000000000000000000e+00 0.05 67 | 0.000000000000000000e+00 0.05 68 | 0.000000000000000000e+00 0.05 69 | 0.000000000000000000e+00 0.05 70 | 7.822908527013711089e-01 0.05 71 | 1.531190400915317884e+00 0.05 72 | 2.221008980139278055e+00 0.05 73 | 2.826428263119022954e+00 0.05 74 | 3.321297353158600973e+00 0.05 75 | 3.740228674323306635e+00 0.05 76 | 4.153200138487463278e+00 0.05 77 | 4.562746899896826136e+00 0.05 78 | 4.153012356439569785e+00 0.05 79 | 3.740054714326475960e+00 0.05 80 | 3.321295842521812425e+00 0.05 81 | 0.000000000000000000e+00 0.05 82 | 0.000000000000000000e+00 0.05 83 | 0.000000000000000000e+00 0.05 84 | 0.000000000000000000e+00 0.05 85 | 0.000000000000000000e+00 0.05 86 | 0.000000000000000000e+00 0.05 87 | 7.883876043158544178e-01 0.05 88 | 1.537516296222571910e+00 0.05 89 | 2.228592710027760493e+00 0.05 90 | 2.835004533154316331e+00 0.05 91 | 3.332536350472808273e+00 0.05 92 | 3.749083914289849773e+00 0.05 93 | 4.159003629645200206e+00 0.05 94 | 4.558592233534072946e+00 0.05 95 | 4.151458309841912886e+00 0.05 96 | 3.733714823342811240e+00 0.05 97 | 0.000000000000000000e+00 0.05 98 | 0.000000000000000000e+00 0.05 99 | 0.000000000000000000e+00 0.05 100 | 0.000000000000000000e+00 0.05 101 | 0.000000000000000000e+00 0.05 102 | 0.000000000000000000e+00 0.05 103 | 0.000000000000000000e+00 0.05 104 | 7.804149329948366631e-01 0.05 105 | 1.531449135630707170e+00 0.05 106 | 2.224093217106712927e+00 0.05 107 | 2.830783004060921648e+00 0.05 108 | 3.328979842746475626e+00 0.05 109 | 3.742306651176985355e+00 0.05 110 | 4.148566879762047854e+00 0.05 111 | 4.559139019488376299e+00 0.05 112 | 4.146767019473040605e+00 0.05 113 | 0.000000000000000000e+00 0.05 114 | 0.000000000000000000e+00 0.05 115 | 0.000000000000000000e+00 0.05 116 | 0.000000000000000000e+00 0.05 117 | 0.000000000000000000e+00 0.05 118 | 0.000000000000000000e+00 0.05 119 | 0.000000000000000000e+00 0.05 120 | 0.000000000000000000e+00 0.05 121 | 7.827184585227960900e-01 0.05 122 | 1.531570542578994942e+00 0.05 123 | 2.225514534144740431e+00 0.05 124 | 2.830582963211395242e+00 0.05 125 | 3.326098749756552397e+00 0.05 126 | 3.735330014414701694e+00 0.05 127 | 4.153211807643869768e+00 0.05 128 | 4.559844345772492424e+00 0.05 129 | 0.000000000000000000e+00 0.05 130 | 0.000000000000000000e+00 0.05 131 | 0.000000000000000000e+00 0.05 132 | 0.000000000000000000e+00 0.05 133 | 0.000000000000000000e+00 0.05 134 | 0.000000000000000000e+00 0.05 135 | 0.000000000000000000e+00 0.05 136 | 0.000000000000000000e+00 0.05 137 | 0.000000000000000000e+00 0.05 138 | 7.822908527013708868e-01 0.05 139 | 1.531190400915317662e+00 0.05 140 | 2.221008980139276723e+00 0.05 141 | 2.826428261324632540e+00 0.05 142 | 3.321253562147520988e+00 0.05 143 | 3.740164510083100691e+00 0.05 144 | 4.153135367148827584e+00 0.05 145 | 0.000000000000000000e+00 0.05 146 | 0.000000000000000000e+00 0.05 147 | 0.000000000000000000e+00 0.05 148 | 0.000000000000000000e+00 0.05 149 | 0.000000000000000000e+00 0.05 150 | 0.000000000000000000e+00 0.05 151 | 0.000000000000000000e+00 0.05 152 | 0.000000000000000000e+00 0.05 153 | 0.000000000000000000e+00 0.05 154 | 0.000000000000000000e+00 0.05 155 | 7.884053004882995985e-01 0.05 156 | 1.537955534502169597e+00 0.05 157 | 2.228865589714637885e+00 0.05 158 | 2.835099296594386864e+00 0.05 159 | 3.332596992426696936e+00 0.05 160 | 3.749144029176478821e+00 0.05 161 | 0.000000000000000000e+00 0.05 162 | 0.000000000000000000e+00 0.05 163 | 0.000000000000000000e+00 0.05 164 | 0.000000000000000000e+00 0.05 165 | 0.000000000000000000e+00 0.05 166 | 0.000000000000000000e+00 0.05 167 | 0.000000000000000000e+00 0.05 168 | 0.000000000000000000e+00 0.05 169 | 0.000000000000000000e+00 0.05 170 | 0.000000000000000000e+00 0.05 171 | 0.000000000000000000e+00 0.05 172 | 7.811079120134384324e-01 0.05 173 | 1.533111335580948920e+00 0.05 174 | 2.225980564113423377e+00 0.05 175 | 2.830766428722859551e+00 0.05 176 | 3.327097405169153532e+00 0.05 177 | 0.000000000000000000e+00 0.05 178 | 0.000000000000000000e+00 0.05 179 | 0.000000000000000000e+00 0.05 180 | 0.000000000000000000e+00 0.05 181 | 0.000000000000000000e+00 0.05 182 | 0.000000000000000000e+00 0.05 183 | 0.000000000000000000e+00 0.05 184 | 0.000000000000000000e+00 0.05 185 | 0.000000000000000000e+00 0.05 186 | 0.000000000000000000e+00 0.05 187 | 0.000000000000000000e+00 0.05 188 | 0.000000000000000000e+00 0.05 189 | 7.827184585227972002e-01 0.05 190 | 1.531570542578996497e+00 0.05 191 | 2.225514534144740875e+00 0.05 192 | 2.830582963211395686e+00 0.05 193 | 0.000000000000000000e+00 0.05 194 | 0.000000000000000000e+00 0.05 195 | 0.000000000000000000e+00 0.05 196 | 0.000000000000000000e+00 0.05 197 | 0.000000000000000000e+00 0.05 198 | 0.000000000000000000e+00 0.05 199 | 0.000000000000000000e+00 0.05 200 | 0.000000000000000000e+00 0.05 201 | 0.000000000000000000e+00 0.05 202 | 0.000000000000000000e+00 0.05 203 | 0.000000000000000000e+00 0.05 204 | 0.000000000000000000e+00 0.05 205 | 0.000000000000000000e+00 0.05 206 | 7.822908527013714419e-01 0.05 207 | 1.531190400915316552e+00 0.05 208 | 2.221008980139277611e+00 0.05 209 | 0.000000000000000000e+00 0.05 210 | 0.000000000000000000e+00 0.05 211 | 0.000000000000000000e+00 0.05 212 | 0.000000000000000000e+00 0.05 213 | 0.000000000000000000e+00 0.05 214 | 0.000000000000000000e+00 0.05 215 | 0.000000000000000000e+00 0.05 216 | 0.000000000000000000e+00 0.05 217 | 0.000000000000000000e+00 0.05 218 | 0.000000000000000000e+00 0.05 219 | 0.000000000000000000e+00 0.05 220 | 0.000000000000000000e+00 0.05 221 | 0.000000000000000000e+00 0.05 222 | 0.000000000000000000e+00 0.05 223 | 7.884053004882999316e-01 0.05 224 | 1.537955534502170263e+00 0.05 225 | 0.000000000000000000e+00 0.05 226 | 0.000000000000000000e+00 0.05 227 | 0.000000000000000000e+00 0.05 228 | 0.000000000000000000e+00 0.05 229 | 0.000000000000000000e+00 0.05 230 | 0.000000000000000000e+00 0.05 231 | 0.000000000000000000e+00 0.05 232 | 0.000000000000000000e+00 0.05 233 | 0.000000000000000000e+00 0.05 234 | 0.000000000000000000e+00 0.05 235 | 0.000000000000000000e+00 0.05 236 | 0.000000000000000000e+00 0.05 237 | 0.000000000000000000e+00 0.05 238 | 0.000000000000000000e+00 0.05 239 | 0.000000000000000000e+00 0.05 240 | 7.811079120134376552e-01 0.05 241 | 0.000000000000000000e+00 0.05 242 | 0.000000000000000000e+00 0.05 243 | 0.000000000000000000e+00 0.05 244 | 0.000000000000000000e+00 0.05 245 | 0.000000000000000000e+00 0.05 246 | 0.000000000000000000e+00 0.05 247 | 0.000000000000000000e+00 0.05 248 | 0.000000000000000000e+00 0.05 249 | 0.000000000000000000e+00 0.05 250 | 0.000000000000000000e+00 0.05 251 | 0.000000000000000000e+00 0.05 252 | 0.000000000000000000e+00 0.05 253 | 0.000000000000000000e+00 0.05 254 | 0.000000000000000000e+00 0.05 255 | 0.000000000000000000e+00 0.05 256 | 0.000000000000000000e+00 0.05 257 | -------------------------------------------------------------------------------- /tests/tomo2d/run_job.sh: -------------------------------------------------------------------------------- 1 | PYTHONPATH=/home/xzhang15/VIP python tomo2d.py -r 1 2 | -------------------------------------------------------------------------------- /tests/tomo2d/tomo2d.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import os 5 | import h5py 6 | import scipy.sparse as sparse 7 | 8 | from vip.prior.transform import trans 9 | from forward.tomo2d.tomo2d import tomo2d 10 | from vip.pyvi.svgd import SVGD, sSVGD 11 | 12 | from datetime import datetime 13 | import time 14 | import configparser 15 | #import vip.fwi.dask_utils as du 16 | from vip.prior.prior import prior 17 | from vip.prior.pdf import Uniform, Gaussian 18 | 19 | import argparse 20 | import sys 21 | from pathlib import Path 22 | 23 | os.environ['HDF5_USE_FILE_LOCKING']='FALSE' 24 | os.environ['OMP_NUM_THREADS']='4' 25 | 26 | def init_tomo(config): 27 | Path(config.get('svgd','outpath')).mkdir(parents=True, exist_ok=True) 28 | 29 | 30 | def generate_init(n=1,lb=0,ub=1e8, transform=True): 31 | eps = np.finfo(np.float64).eps 32 | x = lb + (ub-lb)*np.random.uniform(low=eps,high=1-eps,size=(n,lb.shape[0])) 33 | if(transform): 34 | x = trans(x.reshape((-1,lb.shape[0])),lb=lb, ub=ub, trans=1) 35 | 36 | return x 37 | 38 | def get_init(config, resume=0): 39 | priorfile = config.get('svgd','prior') 40 | prior = np.loadtxt(priorfile) 41 | lower_bnd = prior[:,0].astype(np.float64); upper_bnd = prior[:,1].astype(np.float64) 42 | if(resume==0): 43 | x0 = generate_init(n=config.getint('svgd','nparticles'), lb=lower_bnd, ub=upper_bnd, 44 | transform=config.getboolean('svgd','transform')) 45 | 46 | else: 47 | print("Resume from previous running..") 48 | #f = h5py.File(os.path.join(config['svgd']['outpath'],'samples.hdf5'),'r') 49 | #x0 = f['samples'][-1,:,:] 50 | #x0 = x0.astype(np.float64) 51 | #f.close() 52 | x0 = np.load('last_sample.npy') 53 | w = np.where(x0<=lower_bnd) 54 | for i in range(len(w[0])): 55 | x0[w[0][i],w[1][i]] = np.mean(x0[:,w[1][i]]) 56 | w = np.where(x0>=upper_bnd) 57 | for i in range(len(w[0])): 58 | x0[w[0][i],w[1][i]] = np.mean(x0[:,w[1][i]]) 59 | x0 = x0.astype(np.float64) 60 | 61 | if( config.getboolean('svgd','transform') ): 62 | x0 = trans(x0,lb=lower_bnd.flatten(),ub=upper_bnd.flatten(),trans=1) 63 | 64 | if(np.isinf(x0).any()): print("Error: inf occured") 65 | if(np.isnan(x0).any()): print("Error: nan occured") 66 | 67 | return x0 68 | 69 | def delta(n): 70 | diag0 = np.full((n,),fill_value=-2); diag0[0]=-1; diag0[-1]=-1 71 | diag1 = np.full((n-1,),fill_value=1) 72 | diagonals = [diag0,diag1,diag1] 73 | D = sparse.diags(diagonals,[0,-1,1]).tocsc() 74 | return D 75 | 76 | def create_prior(config): 77 | # prior info 78 | priorfile = config.get('svgd','prior') 79 | p = np.loadtxt(priorfile) 80 | p1 = p[:,0].astype(np.float64); p2 = p[:,1].astype(np.float64) 81 | p1 = p1.flatten() 82 | p2 = p2.flatten() 83 | ptype = config.get('svgd','priortype') 84 | if(ptype == 'Uniform'): 85 | pdf = Uniform(lb=p1, ub=p2) 86 | if(ptype == 'Gaussian'): 87 | pdf = Gaussian(mu=p1, sigma=p2) 88 | 89 | # create smooth matrix 90 | smoothness = False 91 | L = None 92 | smoothx = config.getfloat('svgd','smoothx') 93 | smoothy = config.getfloat('svgd','smoothy') 94 | if(smoothx>0 and smoothy>0): 95 | smoothx = np.full((ny,),fill_value=smoothx) 96 | smoothz = np.full((ny,),fill_value=smoothy) 97 | deltax = delta(nx) 98 | deltay = delta(ny)/smoothy[:,None] 99 | Ix = sparse.eye(nx); Iy = sparse.eye(ny) 100 | Sx = sparse.kron(Iy/smoothx,deltax) 101 | Sy = sparse.kron(deltay,Ix) 102 | L = sparse.vstack([Sx,Sy]) 103 | smoothness = True 104 | 105 | if(ptype=='Uniform'): 106 | ppdf = prior(pdf=pdf, transform=config.getboolean('svgd','transform'), lb=p1, ub=p2, smooth=smoothness, L=L) 107 | else: 108 | ppdf = prior(pdf=pdf, smooth=smoothness, L=L) 109 | 110 | return ppdf 111 | 112 | def write_samples(filename, pprior, n=0, chunk=10): 113 | 114 | f = h5py.File(filename,'r+') 115 | samples = f['samples'] 116 | start = 0 117 | if(n>0): 118 | start = samples.shape[0] - n 119 | if(start<0): 120 | start = 0 121 | if(pprior.trans): 122 | for i in range(start,samples.shape[0]): 123 | samples[i,:,:] = pprior.adjust(samples[i,:,:]) 124 | 125 | mean = np.mean(samples[:].reshape((-1,samples.shape[2])),axis=0) 126 | std = np.std(samples[:].reshape((-1,samples.shape[2])),axis=0) 127 | last = samples[-1,:,:] 128 | f.close() 129 | 130 | np.save('mean.npy',mean) 131 | np.save('std.npy',std) 132 | np.save('last_sample.npy',last) 133 | return 0 134 | 135 | if __name__=="__main__": 136 | 137 | parser = argparse.ArgumentParser(description='Variational Tomography') 138 | parser.add_argument("-c", "--config", metavar='config', default='config.ini', help="Configuration file") 139 | parser.add_argument("-r", "--resume", metavar='resume', default=0, type=float, help="Resume mode (1) or start a new run(0)") 140 | 141 | args = parser.parse_args() 142 | configfile = args.config 143 | resume = args.resume 144 | 145 | now = datetime.now() 146 | current_time = now.strftime("%Y-%m-%d %H:%M:%S") 147 | print(f'Start VTomo at {current_time}...') 148 | print(f'Config file for VFWI is: {configfile}') 149 | 150 | config = configparser.ConfigParser() 151 | config._interpolation = configparser.ExtendedInterpolation() 152 | config.read(configfile) 153 | 154 | print('Method for VTomo is: '+config['svgd']['method']) 155 | init_tomo(config) 156 | x0 = get_init(config, resume=resume) 157 | print("Particles size: "+str(x0.shape)) 158 | 159 | ppdf = create_prior(config) 160 | 161 | # fwi simulator 162 | simulator = tomo2d(config, ppdf) 163 | 164 | # svgd sampler 165 | stepsize = config.getfloat('svgd','stepsize') 166 | iteration = config.getint('svgd','iter') 167 | final_decay = config.getfloat('svgd','final_decay') 168 | gamma = final_decay**(1./iteration) 169 | if(config['svgd']['method']=='ssvgd'): 170 | svgd = sSVGD(simulator.dlnprob, 171 | kernel=config['svgd']['kernel'], 172 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 173 | elif(config['svgd']['method']=='svgd'): 174 | svgd = SVGD(simulator.dlnprob, 175 | kernel=config['svgd']['kernel'], 176 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 177 | else: 178 | print('Not supported method') 179 | 180 | # sampling 181 | print('Start sampling ...') 182 | print(f'Iteration: {iteration}') 183 | print(f'Stepsize, decay rate and final decay: {stepsize} {gamma} {final_decay}') 184 | start = time.time() 185 | losses, x = svgd.sample(x0, 186 | n_iter=config.getint('svgd','iter'), 187 | stepsize=stepsize, gamma=gamma, 188 | optimizer=config['svgd']['optimizer'], 189 | burn_in=config.getint('svgd','burn_in'), 190 | thin=config.getint('svgd','thin') 191 | ) 192 | end=time.time() 193 | print('Time taken: '+str(end-start)+' s') 194 | 195 | # write out results 196 | nsamples = int((config.getint('svgd','iter')-config.getint('svgd','burn_in'))/config.getint('svgd','thin')) 197 | write_samples(os.path.join(config.get('svgd','outpath'),'samples.hdf5'), ppdf, n=nsamples) 198 | with open(os.path.join(config.get('svgd','outpath'),'misfits.txt'),"ab") as f: 199 | np.savetxt(f,losses) 200 | -------------------------------------------------------------------------------- /tests/tomo_UK/config.ini: -------------------------------------------------------------------------------- 1 | [tomo] 2 | # input for tomo2d code 3 | basepath = /home/xzhang15/VIP/tests/tomo_UK 4 | # source file 5 | srcfile = ${basepath}/input/sources.txt 6 | # receiver file 7 | recfile = ${basepath}/input/receivers.txt 8 | # data file 9 | datafile = ${basepath}/input/ttimes.txt 10 | 11 | # other arguments for tomo2d code 12 | # grid points in x direction (nx) 13 | nx = 41 14 | # grid points in y direction (ny) 15 | ny = 38 16 | # minimum x 17 | xmin = 61.0 18 | # minimum y 19 | ymin = -9.0 20 | # Grid spacing in x direction (dx) 21 | dx = 0.325 22 | # Grid spacing in y direction (dy) 23 | dy = 0.325 24 | # upsampling factor for spacings in x direction (gdx) 25 | gdx = 2 26 | # upsampling factor for spacings in y direction (gdy) 27 | gdy = 2 28 | # source refinement factor (upsampling) 29 | sdx = 4 30 | # source refinement area in grid points 31 | sext = 4 32 | # earth 33 | earth = 6371.0 34 | 35 | [svgd] 36 | # svgd or ssvgd is supported 37 | method = svgd 38 | # kernel function, only rbf or diagonal supported 39 | kernel = rbf 40 | # diagonal kernel 41 | diag = grad 42 | # optimizer, sgd, adam 43 | optimizer = sgd 44 | # using transform (true) or not (false) 45 | transform = true 46 | # prior type, 'Uniform' or 'Gaussian' 47 | priortype = Uniform 48 | # file that contains hyperparameters for prior pdf 49 | prior = ${tomo:basepath}/input/Uniform_prior.txt 50 | # number of particles 51 | nparticles = 500 52 | # number of iterations 53 | iter = 3000 54 | # burn_in period, only used for ssvgd 55 | burn_in = 200 56 | # thining of the chain, only used for ssvgd 57 | thin = 2 58 | # step length for svgd and ssvgd 59 | stepsize = 0.01 60 | # decay the stepsize exponentially, the final stepsize will be stepsize*final_decay 61 | final_decay = 1.0 62 | # noise level, currently only support a constant number 63 | sigma = 0.01 64 | # smoothness in x direction, 0 for no smoothness 65 | smoothx = 0 66 | # smoothness in y direction, 0 for no smoothness 67 | smoothy = 0 68 | # output directory 69 | outpath = ${tomo:basepath}/results 70 | -------------------------------------------------------------------------------- /tests/tomo_UK/input/receivers.txt: -------------------------------------------------------------------------------- 1 | 56.633500 -3.918900 2 | 58.285900 -4.412590 3 | 52.300700 1.478170 4 | 58.031000 -4.883400 5 | 58.481900 -4.201320 6 | 51.442501 -2.327667 7 | 57.613200 -5.308410 8 | 58.493168 -3.910167 9 | 57.913800 -4.330470 10 | 56.907200 -4.803420 11 | 57.471300 -5.571900 12 | 57.979900 -4.612050 13 | 57.433600 -3.892490 14 | 50.186668 -5.227667 15 | 53.609700 -7.301670 16 | 57.153500 -5.211620 17 | 56.941200 -4.516610 18 | 52.738499 -1.307667 19 | 56.832600 -4.219580 20 | 51.870500 -0.061333 21 | 56.912666 -2.486500 22 | 53.245201 -6.376200 23 | 57.874000 -5.263020 24 | 50.435333 -3.931000 25 | 55.923332 -3.187500 26 | 51.148167 1.134833 27 | 55.316502 -3.205167 28 | 52.889500 -3.199833 29 | 54.866333 -4.711333 30 | 57.077300 -4.964210 31 | 57.101002 -4.559500 32 | 52.518333 -2.880667 33 | 50.867332 0.336333 34 | 53.958168 -1.624167 35 | 50.994335 -4.484833 36 | 58.151400 -4.972060 37 | 54.177000 -4.625000 38 | 49.187832 -2.171667 39 | 54.588665 -3.104833 40 | 57.339169 -5.652667 41 | 57.261000 -5.490530 42 | 53.456833 -0.326000 43 | 52.113834 -4.068167 44 | 60.136002 -1.177833 45 | 51.997334 -2.998333 46 | 56.280000 -3.450000 47 | 51.839165 -2.804167 48 | 52.163800 0.048000 49 | 57.691700 -4.410160 50 | 51.660500 -2.550167 51 | 55.811501 -4.483667 52 | 58.001900 -5.112620 53 | 56.712400 -4.107100 54 | 58.030000 -4.170000 55 | 50.565334 -4.685667 56 | 53.091331 -2.206167 57 | 58.236300 -5.375130 58 | 51.775833 -2.162500 59 | 51.513168 -1.800333 60 | 53.289333 -4.396667 61 | 51.312832 -1.222833 62 | -------------------------------------------------------------------------------- /tests/tomo_UK/input/sources.txt: -------------------------------------------------------------------------------- 1 | 56.633500 -3.918900 2 | 58.285900 -4.412590 3 | 52.300700 1.478170 4 | 58.031000 -4.883400 5 | 58.481900 -4.201320 6 | 51.442501 -2.327667 7 | 57.613200 -5.308410 8 | 58.493168 -3.910167 9 | 57.913800 -4.330470 10 | 56.907200 -4.803420 11 | 57.471300 -5.571900 12 | 57.979900 -4.612050 13 | 57.433600 -3.892490 14 | 50.186668 -5.227667 15 | 53.609700 -7.301670 16 | 57.153500 -5.211620 17 | 56.941200 -4.516610 18 | 52.738499 -1.307667 19 | 56.832600 -4.219580 20 | 51.870500 -0.061333 21 | 56.912666 -2.486500 22 | 53.245201 -6.376200 23 | 57.874000 -5.263020 24 | 50.435333 -3.931000 25 | 55.923332 -3.187500 26 | 51.148167 1.134833 27 | 55.316502 -3.205167 28 | 52.889500 -3.199833 29 | 54.866333 -4.711333 30 | 57.077300 -4.964210 31 | 57.101002 -4.559500 32 | 52.518333 -2.880667 33 | 50.867332 0.336333 34 | 53.958168 -1.624167 35 | 50.994335 -4.484833 36 | 58.151400 -4.972060 37 | 54.177000 -4.625000 38 | 49.187832 -2.171667 39 | 54.588665 -3.104833 40 | 57.339169 -5.652667 41 | 57.261000 -5.490530 42 | 53.456833 -0.326000 43 | 52.113834 -4.068167 44 | 60.136002 -1.177833 45 | 51.997334 -2.998333 46 | 56.280000 -3.450000 47 | 51.839165 -2.804167 48 | 52.163800 0.048000 49 | 57.691700 -4.410160 50 | 51.660500 -2.550167 51 | 55.811501 -4.483667 52 | 58.001900 -5.112620 53 | 56.712400 -4.107100 54 | 58.030000 -4.170000 55 | 50.565334 -4.685667 56 | 53.091331 -2.206167 57 | 58.236300 -5.375130 58 | 51.775833 -2.162500 59 | 51.513168 -1.800333 60 | 53.289333 -4.396667 61 | 51.312832 -1.222833 62 | -------------------------------------------------------------------------------- /tests/tomo_UK/run_job.sh: -------------------------------------------------------------------------------- 1 | PYTHONPATH=/home/xzhang15/VIP python tomo2d.py -r 0 2 | -------------------------------------------------------------------------------- /tests/tomo_UK/tomo2d.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import os 5 | import h5py 6 | 7 | from vip.prior.transform import trans 8 | from forward.tomo2d.tomo2d import tomo2d 9 | from vip.pyvi.svgd import SVGD, sSVGD 10 | 11 | from datetime import datetime 12 | import time 13 | import configparser 14 | #import vip.fwi.dask_utils as du 15 | from vip.prior.prior import prior 16 | from vip.prior.pdf import Uniform, Gaussian 17 | 18 | import argparse 19 | import sys 20 | from pathlib import Path 21 | 22 | os.environ['HDF5_USE_FILE_LOCKING']='FALSE' 23 | os.environ['OMP_NUM_THREADS']='10' 24 | 25 | def init_tomo(config): 26 | Path(config.get('svgd','outpath')).mkdir(parents=True, exist_ok=True) 27 | 28 | 29 | def generate_init(n=1,lb=0,ub=1e8, transform=True): 30 | eps = np.finfo(np.float64).eps 31 | x = lb + (ub-lb)*np.random.uniform(low=eps,high=1-eps,size=(n,lb.shape[0])) 32 | if(transform): 33 | x = trans(x.reshape((-1,lb.shape[0])),lb=lb, ub=ub, trans=1) 34 | 35 | return x 36 | 37 | def get_init(config, resume=0): 38 | priorfile = config.get('svgd','prior') 39 | prior = np.loadtxt(priorfile) 40 | lower_bnd = prior[:,0].astype(np.float64); upper_bnd = prior[:,1].astype(np.float64) 41 | if(resume==0): 42 | x0 = generate_init(n=config.getint('svgd','nparticles'), lb=lower_bnd, ub=upper_bnd, 43 | transform=config.getboolean('svgd','transform')) 44 | 45 | else: 46 | print("Resume from previous running..") 47 | #f = h5py.File(os.path.join(config['svgd']['outpath'],'samples.hdf5'),'r') 48 | x0 = np.load('last_sample.npy') 49 | w = np.where(x0<=lower_bnd) 50 | for i in range(len(w[0])): 51 | x0[w[0][i],w[1][i]] = np.mean(x0[:,w[1][i]]) 52 | w = np.where(x0>=upper_bnd) 53 | for i in range(len(w[0])): 54 | x0[w[0][i],w[1][i]] = np.mean(x0[:,w[1][i]]) 55 | x0 = x0.astype(np.float64) 56 | #f.close() 57 | 58 | if( config.getboolean('svgd','transform') ): 59 | x0 = trans(x0,lb=lower_bnd.flatten(),ub=upper_bnd.flatten(),trans=1) 60 | 61 | if(np.isinf(x0).any()): print("Error: inf occured") 62 | if(np.isnan(x0).any()): print("Error: nan occured") 63 | 64 | return x0 65 | 66 | def delta(n): 67 | diag0 = np.full((n,),fill_value=-2); diag0[0]=-1; diag0[-1]=-1 68 | diag1 = np.full((n-1,),fill_value=1) 69 | diagonals = [diag0,diag1,diag1] 70 | D = sparse.diags(diagonals,[0,-1,1]).tocsc() 71 | return D 72 | 73 | def create_prior(config): 74 | # prior info 75 | priorfile = config.get('svgd','prior') 76 | p = np.loadtxt(priorfile) 77 | p1 = p[:,0].astype(np.float64); p2 = p[:,1].astype(np.float64) 78 | p1 = p1.flatten() 79 | p2 = p2.flatten() 80 | ptype = config.get('svgd','priortype') 81 | if(ptype == 'Uniform'): 82 | pdf = Uniform(lb=p1, ub=p2) 83 | if(ptype == 'Gaussian'): 84 | pdf = Gaussian(mu=p1, sigma=p2) 85 | 86 | # create smooth matrix 87 | smoothness = False 88 | L = None 89 | smoothx = config.getfloat('svgd','smoothx') 90 | smoothy = config.getfloat('svgd','smoothy') 91 | if(smoothx>0 and smoothy>0): 92 | smoothx = np.full((ny,),fill_value=smoothx) 93 | smoothz = np.full((ny,),fill_value=smoothy) 94 | deltax = delta(nx) 95 | deltay = delta(ny)/smoothy[:,None] 96 | Ix = sparse.eye(nx); Iy = sparse.eye(ny) 97 | Sx = sparse.kron(Iy/smoothx,deltax) 98 | Sy = sparse.kron(deltay,Ix) 99 | L = sparse.vstack([Sx,Sy]) 100 | smoothness = True 101 | 102 | if(ptype=='Uniform'): 103 | ppdf = prior(pdf=pdf, transform=config.getboolean('svgd','transform'), lb=p1, ub=p2, smooth=smoothness, L=L) 104 | else: 105 | ppdf = prior(pdf=pdf, smooth=smoothness, L=L) 106 | 107 | return ppdf 108 | 109 | def write_samples(filename, pprior, n=0, chunk=10): 110 | 111 | f = h5py.File(filename,'r+') 112 | samples = f['samples'] 113 | start = 0 114 | if(n>0): 115 | start = samples.shape[0] - n 116 | if(start<0): 117 | start = 0 118 | if(pprior.trans): 119 | for i in range(start,samples.shape[0]): 120 | samples[i,:,:] = pprior.adjust(samples[i,:,:]) 121 | 122 | mean = np.mean(samples[:].reshape((-1,samples.shape[2])),axis=0) 123 | std = np.std(samples[:].reshape((-1,samples.shape[2])),axis=0) 124 | last = samples[-1,:,:] 125 | f.close() 126 | 127 | np.save('mean.npy',mean) 128 | np.save('std.npy',std) 129 | np.save('last_sample.npy',last) 130 | return 0 131 | 132 | 133 | if __name__=="__main__": 134 | 135 | parser = argparse.ArgumentParser(description='Variational Tomography') 136 | parser.add_argument("-c", "--config", metavar='config', default='config.ini', help="Configuration file") 137 | parser.add_argument("-r", "--resume", metavar='resume', default=0, type=float, help="Resume mode (1) or start a new run(0)") 138 | 139 | args = parser.parse_args() 140 | configfile = args.config 141 | resume = args.resume 142 | 143 | now = datetime.now() 144 | current_time = now.strftime("%Y-%m-%d %H:%M:%S") 145 | print(f'Start VTomo at {current_time}...') 146 | print(f'Config file for VFWI is: {configfile}') 147 | 148 | config = configparser.ConfigParser() 149 | config._interpolation = configparser.ExtendedInterpolation() 150 | config.read(configfile) 151 | 152 | print('Method for VTomo is: '+config['svgd']['method']) 153 | init_tomo(config) 154 | x0 = get_init(config, resume=resume) 155 | print("Particles size: "+str(x0.shape)) 156 | 157 | ppdf = create_prior(config) 158 | 159 | # fwi simulator 160 | simulator = tomo2d(config, ppdf) 161 | 162 | # svgd sampler 163 | stepsize = config.getfloat('svgd','stepsize') 164 | iteration = config.getint('svgd','iter') 165 | final_decay = config.getfloat('svgd','final_decay') 166 | gamma = final_decay**(1./iteration) 167 | if(config['svgd']['method']=='ssvgd'): 168 | svgd = sSVGD(simulator.dlnprob, 169 | kernel=config['svgd']['kernel'], 170 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 171 | elif(config['svgd']['method']=='svgd'): 172 | svgd = SVGD(simulator.dlnprob, 173 | kernel=config['svgd']['kernel'], 174 | h = 1.0, 175 | out=os.path.join(config.get('svgd','outpath'),'samples.hdf5')) 176 | else: 177 | print('Not supported method') 178 | 179 | # sampling 180 | print('Start sampling ...') 181 | print(f'Iteration: {iteration}') 182 | print(f'Stepsize, decay rate and final decay: {stepsize} {gamma} {final_decay}') 183 | start = time.time() 184 | losses, x = svgd.sample(x0, 185 | n_iter=config.getint('svgd','iter'), 186 | stepsize=stepsize, gamma=gamma, 187 | optimizer=config['svgd']['optimizer'], 188 | burn_in=config.getint('svgd','burn_in'), 189 | thin=config.getint('svgd','thin'), 190 | ) 191 | end=time.time() 192 | print('Time taken: '+str(end-start)+' s') 193 | 194 | # write out results 195 | nsamples = int((config.getint('svgd','iter')-config.getint('svgd','burn_in'))/config.getint('svgd','thin')) 196 | write_samples(os.path.join(config.get('svgd','outpath'),'samples.hdf5'), ppdf, n=nsamples) 197 | with open(os.path.join(config.get('svgd','outpath'),'misfits.txt'),"ab") as f: 198 | np.savetxt(f,losses) 199 | -------------------------------------------------------------------------------- /vip/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.so 3 | __pycache__/ 4 | kernel/__pycache__ 5 | kernel/*.so 6 | kernel/*.c 7 | kernel/*.a 8 | fwi2d/__pycache__ 9 | fwi2d/*.so 10 | fwi2d/pyacofwi2D.c 11 | fwi2d/*.a 12 | tomo/__pycache__ 13 | tomo/*.so 14 | tomo/pyfm2d.c 15 | tomo/*.a 16 | pyvi/__pycache__ 17 | fwi/__pycache__ 18 | prior/__pycache__ 19 | -------------------------------------------------------------------------------- /vip/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin2zhang/VIP/4857809b4d4e774595b08ab1905387d8555b88d1/vip/__init__.py -------------------------------------------------------------------------------- /vip/kernel/Makefile: -------------------------------------------------------------------------------- 1 | # List of source file 2 | OBJ = utils.o transform.o kernel.o 3 | F90 = gfortran 4 | LIB = libsvgd.a 5 | AR = ar -r 6 | FFLAGS += -I/usr/include -fPIC -O3 -funroll-loops -ffast-math -fopenmp 7 | #FFLAGS += -O0 -g -Wall -Wtabs -Wextra -Wconversion -fimplicit-none -fbacktrace -fcheck=all -ffpe-trap=zero,overflow,underflow -finit-real=nan 8 | 9 | # rule for building foward modeling code 10 | $(LIB): $(OBJ) 11 | $(AR) $@ $^ 12 | 13 | # rule for building object file 14 | %.o: %.f90 15 | $(F90) $(FFLAGS) -c $< -o $@ 16 | 17 | %.o: %.cpp 18 | $(CC) $(CFLAGS) -c $< -o $@ 19 | 20 | .PHONY: clean cleanall 21 | 22 | clean: 23 | rm -f *.o *.mod 24 | 25 | cleanall: clean 26 | rm -f *.a 27 | -------------------------------------------------------------------------------- /vip/kernel/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin2zhang/VIP/4857809b4d4e774595b08ab1905387d8555b88d1/vip/kernel/__init__.py -------------------------------------------------------------------------------- /vip/kernel/kernel.f90: -------------------------------------------------------------------------------- 1 | module m_kernel 2 | 3 | use omp_lib 4 | use iso_c_binding 5 | use m_utils, only : dp, sp, N_THREADS 6 | implicit none 7 | real(kind=dp), parameter :: eps = 1E-8 8 | 9 | contains 10 | 11 | subroutine sqrd_c(m, n, x, w, dist) bind(c) 12 | implicit none 13 | integer(kind=c_int), intent(in), value :: m, n 14 | real(kind=dp), intent(in) :: x(n,m) 15 | real(kind=dp), intent(in) :: w(n) 16 | real(kind=dp), intent(out) :: dist(m,m) 17 | 18 | call sqr_dist(x,w,dist) 19 | 20 | end subroutine 21 | 22 | subroutine sqr_dist(x, w, dist) 23 | implicit none 24 | real(kind=dp), dimension(:,:), intent(in) :: x 25 | real(kind=dp), dimension(:), intent(in) :: w 26 | real(kind=dp), dimension(:,:), intent(out) :: dist 27 | 28 | integer i, j 29 | 30 | !omp parallel private(i,j) num_threads(N_THREADS) 31 | !$omp parallel private(i,j) 32 | !$omp do 33 | do i = 1, size(x,2) 34 | do j = 1, size(x,2) 35 | dist(j,i) = sum((x(:,i)-x(:,j))**2 * w) 36 | enddo 37 | enddo 38 | !$omp end do 39 | !$omp end parallel 40 | end subroutine 41 | 42 | subroutine rbf_kernel(x, grad, dist, h, grad_out) 43 | implicit none 44 | real(kind=dp), dimension(:,:), intent(in) :: x 45 | real(kind=dp), dimension(:,:), intent(in) :: grad 46 | real(kind=dp), dimension(:,:), intent(out) :: grad_out 47 | real(kind=dp), dimension(:,:), intent(in) :: dist 48 | real(kind=dp), intent(in) :: h 49 | 50 | integer i, j 51 | !write(*,*) omp_get_num_threads() 52 | !omp parallel private(i,j) num_threads(N_THREADS) 53 | !$omp parallel private(i,j) 54 | !$omp do 55 | do i = 1, size(x,2) 56 | do j = 1, size(x,2) 57 | grad_out(:,i) = grad_out(:,i) + (grad(:,j)+(x(:,i)-x(:,j))/h**2)*exp(-dist(j,i)/(2*h**2)) 58 | enddo 59 | grad_out(:,i) = grad_out(:,i)/size(x,2) 60 | enddo 61 | !$omp end do 62 | !$omp end parallel 63 | 64 | end subroutine 65 | 66 | subroutine rbf_ksd(x, grad, dist, h, ksd) 67 | implicit none 68 | real(kind=dp), dimension(:,:), intent(in) :: x 69 | real(kind=dp), dimension(:,:), intent(in) :: grad 70 | real(kind=dp), dimension(:,:), intent(in) :: dist 71 | real(kind=dp), intent(in) :: h 72 | real(kind=dp), intent(out) :: ksd 73 | 74 | real(kind=dp) :: kvalue 75 | real(kind=dp) :: trace 76 | integer i, j, n 77 | 78 | ksd = 0 79 | n = size(x,2) 80 | !$omp parallel private(i,j,kvalue) reduction(+:ksd) 81 | !$omp do 82 | do i = 1, n 83 | do j = i+1, n 84 | kvalue = exp(-dist(j,i)/(2*h**2)) 85 | ksd = ksd + kvalue*sum(grad(:,i)*grad(:,j)) + & 86 | sum(grad(:,i)*(x(:,i)-x(:,j))/h**2*kvalue) + & 87 | sum(-(x(:,i)-x(:,j))/h**2*kvalue*grad(:,j)) + & 88 | (size(x,1)-sum((x(:,i)-x(:,j))**2)/h**2)/h**2*kvalue 89 | enddo 90 | enddo 91 | !$omp end do 92 | !$omp end parallel 93 | ksd = ksd*2/(n*(n-1)) 94 | 95 | end subroutine 96 | 97 | subroutine diagonal_kernel(x, grad, w, dist, h, grad_out) 98 | implicit none 99 | real(kind=dp), dimension(:,:), intent(in) :: x 100 | real(kind=dp), dimension(:,:), intent(in) :: grad 101 | real(kind=dp), dimension(:,:), intent(out) :: grad_out 102 | real(kind=dp), dimension(:), intent(in) :: w 103 | real(kind=dp), dimension(:,:), intent(in) :: dist 104 | real(kind=dp), intent(in) :: h 105 | 106 | integer i, j 107 | !omp parallel private(i,j) num_threads(N_THREADS) 108 | !$omp parallel private(i,j) 109 | !$omp do 110 | do i = 1, size(x,2) 111 | do j = 1, size(x,2) 112 | grad_out(:,i) = grad_out(:,i) + (grad(:,j)/w+(x(:,i)-x(:,j))/h**2)*exp(-dist(j,i)/(2*h**2)) 113 | enddo 114 | grad_out(:,i) = grad_out(:,i)/size(x,2) 115 | enddo 116 | !$omp end do 117 | !$omp end parallel 118 | 119 | end subroutine 120 | 121 | subroutine diagonal_ksd(x, grad, w, dist, h, ksd) 122 | implicit none 123 | real(kind=dp), dimension(:,:), intent(in) :: x 124 | real(kind=dp), dimension(:,:), intent(in) :: grad 125 | real(kind=dp), dimension(:), intent(in) :: w 126 | real(kind=dp), dimension(:,:), intent(in) :: dist 127 | real(kind=dp), intent(in) :: h 128 | real(kind=dp), intent(out) :: ksd 129 | 130 | real(kind=dp) :: kvalue 131 | real(kind=dp) :: trace 132 | integer i, j, n 133 | 134 | ksd = 0 135 | n = size(x,2) 136 | !$omp parallel private(i,j,kvalue) reduction(+:ksd) 137 | !$omp do 138 | do i = 1, n 139 | do j = i+1, n 140 | kvalue = exp(-dist(j,i)/(2*h**2)) 141 | ksd = ksd + kvalue*sum(grad(:,i)*grad(:,j)/w) + & 142 | sum(grad(:,i)*(x(:,i)-x(:,j))/h**2*kvalue) + & 143 | sum(-(x(:,i)-x(:,j))/h**2*kvalue*grad(:,j)) + & 144 | (size(x,1)-dist(j,i)/h**2)/h**2*kvalue 145 | enddo 146 | enddo 147 | !$omp end do 148 | !$omp end parallel 149 | ksd = ksd*2/(n*(n-1)) 150 | 151 | end subroutine 152 | 153 | subroutine svgd_grad(m, n, x, grad, kernel, dist, hessian, h, grad_out) bind(c) 154 | implicit none 155 | integer(c_int), intent(in), value :: m, n 156 | real(kind=dp), intent(in) :: x(n,m) 157 | real(kind=dp), intent(in) :: grad(n,m) 158 | integer(c_int), intent(in), value :: kernel 159 | real(kind=dp), intent(in) :: dist(m,m) 160 | real(kind=dp), intent(in) :: hessian(n) 161 | real(kind=dp), intent(in), value :: h 162 | real(kind=dp), intent(out) :: grad_out(n,m) 163 | 164 | select case(kernel) 165 | case (1) 166 | call rbf_kernel(x, grad, dist, h, grad_out) 167 | case (2) 168 | call diagonal_kernel(x, grad, hessian, dist, h, grad_out) 169 | case default 170 | write(*,*) "Error: not supported kernel." 171 | end select 172 | 173 | end subroutine 174 | 175 | subroutine ksd(m, n, x, grad, kernel, dist, hessian, h, ksd_value) bind(c) 176 | implicit none 177 | integer(c_int), intent(in), value :: m, n 178 | real(kind=dp), intent(in) :: x(n,m) 179 | real(kind=dp), intent(in) :: grad(n,m) 180 | integer(c_int), intent(in), value :: kernel 181 | real(kind=dp), intent(in) :: dist(m,m) 182 | real(kind=dp), intent(in) :: hessian(n) 183 | real(kind=dp), intent(in), value :: h 184 | real(kind=dp), intent(out) :: ksd_value 185 | 186 | real(kind=dp) :: kvalue 187 | select case(kernel) 188 | case (1) 189 | call rbf_ksd(x, grad, dist, h, kvalue) 190 | case (2) 191 | call diagonal_ksd(x, grad, hessian, dist, h, kvalue) 192 | case default 193 | write(*,*) "Error: not supported kernel." 194 | end select 195 | ksd_value = kvalue 196 | 197 | end subroutine 198 | 199 | end module 200 | -------------------------------------------------------------------------------- /vip/kernel/kernel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.spatial.distance import pdist, squareform 3 | 4 | def sqr_dist(x, w=None): 5 | # pairwise square distance 6 | if(w is None): 7 | sq_dist = pdist(x) 8 | else: 9 | sq_dist = pdist(x,metric='minkowski',p=2,w=w) 10 | pairwise_dists = squareform(sq_dist)**2 11 | return pairwise_dists 12 | 13 | def rbf_kernel(x, h = -1): 14 | 15 | H = sqr_dist(x) 16 | if h < 0: # if h < 0, using median trick 17 | h = np.median(H) 18 | h = np.sqrt(0.5 * h / np.log(x.shape[0]+1)) 19 | 20 | # compute the rbf kernel 21 | #print("RBF kernel h: "+str(h)) 22 | Kxy = np.exp( -H / h**2 / 2) 23 | 24 | dxkxy = -np.matmul(Kxy, x) 25 | sumkxy = np.sum(Kxy, axis=1, keepdims=True) 26 | dxkxy = dxkxy + x * sumkxy 27 | dxkxy = dxkxy / (h**2) 28 | return (Kxy, dxkxy) 29 | 30 | def poly_kernel(x, subtract_mean=True, e=1e-8): 31 | if subtract_mean: 32 | x = x - np.mean(x, axis=0) 33 | kxy = 1 + np.matmul(x, x.T) 34 | dxkxy = x * x.shape[0] 35 | return kxy, dxkxy 36 | 37 | 38 | def imq_kernel(x, h=-1): 39 | H = sqr_dist(x) 40 | if h == -1: 41 | h = np.median(H) 42 | 43 | kxy = 1. / np.sqrt(1. + H / h) 44 | 45 | dxkxy = .5 * kxy / (1. + H / h) 46 | dxkxy1 = -np.matmul(dxkxy, x) 47 | sumkxy = np.sum(dxkxy, axis=1, keepdims=True) 48 | dxkxy = (dxkxy1 + x * sumkxy) * 2. / h 49 | 50 | return kxy, dxkxy 51 | 52 | def hessian_kernel(x, H, h=-1): 53 | n, d = x.shape 54 | #diff = x[:,None,:] - x[None,:,:] # n*n*d 55 | #Qdiff = np.matmul(diff,H) 56 | #Hdist = np.sum(Qdiff * diff, axis = -1) 57 | Hdist = pdist(x, 'mahalanobis', VI=H) 58 | Hdist = squareform(Hdist)**2 59 | if(h==-1): 60 | h = np.median(Hdist) 61 | h = 0.5*h/np.log(n) 62 | 63 | kxy = np.exp(-Hdist/(2.*h)) 64 | #dxkxy = -2*diff*kxy[:,:,None]/h 65 | #dxkxy = np.sum(dxkxy,axis=1) 66 | dxkxy = - np.matmul(kxy,x) 67 | sumkxy = np.sum(kxy,axis=1,keepdims=True) 68 | dxkxy = dxkxy + x*sumkxy 69 | dxkxy = dxkxy/h 70 | return kxy, dxkxy 71 | 72 | def diagonal_kernel(x, diag, h=-1): 73 | ''' x a 2D array (nparticles,d) 74 | diag a 1d vector of (d) 75 | ''' 76 | n, d = x.shape 77 | #diff = x[:,None,:] - x[None,:,:] 78 | Hdist = sqr_dist(x, w=diag) 79 | if(h==-1): 80 | h = np.median(Hdist) 81 | h = 0.5*h/np.log(n+1) 82 | 83 | kxy = np.exp(-Hdist/(2.*h)) 84 | #dxkxy = -2*diff*kxy[:,:,None]/h 85 | #dxkxy = np.sum(dxkxy,axis=1) 86 | dxkxy = - np.matmul(kxy,x) 87 | sumkxy = np.sum(kxy,axis=1,keepdims=True) 88 | dxkxy = dxkxy + x*sumkxy 89 | dxkxy = dxkxy/h 90 | return kxy, dxkxy 91 | 92 | def svgd_gradient(x, grad, kernel='rbf', hessian=None, ihessian=None, temperature=1., u_kernel=None, **kernel_params): 93 | assert x.shape[1:] == grad.shape[1:], 'illegal inputs and grads' 94 | n, d = x.shape 95 | 96 | if u_kernel is not None: 97 | kxy, dxkxy = u_kernel['kxy'], u_kernel['dxkxy'] 98 | #dxkxy = np.reshape(dxkxy, x.shape) 99 | else: 100 | if kernel == 'rbf': 101 | kxy, dxkxy = rbf_kernel(x, **kernel_params) 102 | svgd_grad = (np.matmul(kxy, grad) + temperature * dxkxy) / n 103 | elif kernel == 'poly': 104 | kxy, dxkxy = poly_kernel(x) 105 | svgd_grad = (np.matmul(kxy, grad) + temperature * dxkxy) / n 106 | elif kernel == 'imq': 107 | kxy, dxkxy = imq_kernel(x, **kernel_params) 108 | svgd_grad = (np.matmul(kxy, grad) + temperature * dxkxy) / n 109 | elif kernel == 'hessian': 110 | kxy, dxkxy = hessian_kernel(x, hessian, **kernel_params) 111 | sgrad = np.sum(kxy[:,:,None]*grad[None,:,:],axis=1) 112 | #invH = np.linalg.inv(hessian) 113 | invH = ihessian 114 | svgd_grad = (np.matmul(sgrad,invH) + temperature * dxkxy)/n 115 | elif kernel == 'diagonal': 116 | kxy, dxkxy = diagonal_kernel(x, hessian, **kernel_params) 117 | invH = 1./hessian 118 | sgrad = invH[None,:]*grad[:,:] 119 | svgd_grad = (np.matmul(kxy,sgrad) + temperature * dxkxy)/n 120 | elif kernel == 'separate': 121 | kxy, dxkxy = rbf_kernel(x, **kernel_params) 122 | svgd_grad = (np.matmul(kxy,sgrad) + temperature * dxkxy)/n 123 | svgd_grad = np.matmul(svgd_grad,hessian) 124 | elif kernel == 'none': 125 | kxy = np.eye(x.shape[0]) 126 | dxkxy = np.zeros_like(x) 127 | svgd_grad = (np.matmul(kxy, grad) + temperature * dxkxy) / n 128 | else: 129 | raise NotImplementedError 130 | 131 | 132 | return svgd_grad 133 | -------------------------------------------------------------------------------- /vip/kernel/pykernel.h: -------------------------------------------------------------------------------- 1 | extern void sqrd_c(int, int, double *, double *, double *); 2 | extern void svgd_grad(int, int, double *, double *, int, double *, double *, double, double *); 3 | extern void ksd(int, int, double *, double *, int, double *, double *, double, double *); 4 | -------------------------------------------------------------------------------- /vip/kernel/pykernel.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | 4 | cdef extern from "pykernel.h": 5 | void sqrd_c(int, int, double *, double *, double *); 6 | void svgd_grad(int, int, double *, double *, int, double *, double *, double, double *); 7 | void ksd(int, int, double *, double *, int, double *, double *, double, double *); 8 | 9 | def pdist(np.ndarray[double,ndim=2] x, 10 | np.ndarray[double,ndim=1] w): 11 | ''' 12 | Compute pair-wise distance 13 | Input 14 | x: array of variables, shape (n, ndim) 15 | w: weight for calculating distance, a vector of (ndim,) 16 | Return 17 | dist: pair-wise distance, shape (n, n) 18 | ''' 19 | cdef int m, n 20 | m = x.shape[0] 21 | n = x.shape[1] 22 | cdef np.ndarray[double,ndim=2] dist = np.zeros((m,m),dtype=np.float64) 23 | sqrd_c(m,n,&x[0,0],&w[0],&dist[0,0]) 24 | 25 | return dist 26 | 27 | def svgd_gradient(np.ndarray[double,ndim=2] x, 28 | np.ndarray[double,ndim=2] grad, 29 | np.ndarray[double,ndim=2] dist, 30 | np.ndarray[double,ndim=1] w, 31 | str kernel='diagonal',double h=1): 32 | ''' 33 | Compute svgd gradient 34 | Input 35 | x: array of variables, shape (n, nidm) 36 | grad: gradient of posterior w.r.t x for each partilce, shape (n, ndim) 37 | dist: pair-wise distance, shape (n, n) 38 | w: weight for kernel calculation, i.e. a diagonal matrix kernel, shape (ndim, ) 39 | kernel: kernel function, rbf or diagonal 40 | h: width for rbf kernel, default to median trick 41 | Return 42 | grad_out: svgd gradients 43 | ''' 44 | cdef int m, n 45 | m = x.shape[0] 46 | n = x.shape[1] 47 | 48 | medh = np.median(dist) 49 | medh = np.sqrt(0.5*medh/np.log(m+1)) 50 | if(h<0): 51 | h = medh 52 | else: 53 | h = h*medh 54 | 55 | cdef np.ndarray[double,ndim=2] grad_out = np.zeros((m,n),dtype=np.float64) 56 | cdef int ikernel = 0 57 | if(kernel=='rbf'): 58 | ikernel = 1 59 | elif(kernel=='diagonal'): 60 | ikernel = 2 61 | svgd_grad(m,n,&x[0,0],&grad[0,0],ikernel,&dist[0,0],&w[0],h,&grad_out[0,0]) 62 | 63 | return grad_out 64 | 65 | def pyksd(np.ndarray[double,ndim=2] x, 66 | np.ndarray[double,ndim=2] grad, 67 | np.ndarray[double,ndim=1] w, 68 | str kernel='diagonal',double h=-1): 69 | ''' 70 | Compute kernelized Stein discrepancy 71 | Input 72 | x: array of variables, shape (n, nidm) 73 | grad: gradient of posterior w.r.t x for each partilce, shape (n, ndim) 74 | w: weight for kernel calculation, i.e. a diagonal matrix kernel, shape (ndim, ) 75 | kernel: kernel function, rbf or diagonal 76 | h: width for rbf kernel, default to median trick 77 | Return 78 | ksd_value: kernelzied Stein discrepancy 79 | stepsize: the upper bound of the stepsize estimated using ksd value 80 | ''' 81 | cdef int m, n 82 | m = x.shape[0] 83 | n = x.shape[1] 84 | 85 | cdef np.ndarray[double,ndim=2] dist = np.zeros((m,m),dtype=np.float64) 86 | sqrd_c(m,n,&x[0,0],&w[0],&dist[0,0]) 87 | 88 | medh = np.median(dist) 89 | medh = np.sqrt(0.5*medh/np.log(m+1)) 90 | if(h<0): 91 | h = medh 92 | else: 93 | h = h*medh 94 | 95 | cdef double ksd_value = 0 96 | cdef int ikernel = 0 97 | if(kernel=='rbf'): 98 | ikernel = 1 99 | elif(kernel=='diagonal'): 100 | ikernel = 2 101 | ksd(m,n,&x[0,0],&grad[0,0],ikernel,&dist[0,0],&w[0],h,&ksd_value) 102 | stepsize = h/(4*np.sqrt(n)*ksd_value) 103 | 104 | return ksd_value, stepsize 105 | -------------------------------------------------------------------------------- /vip/kernel/pytrans.h: -------------------------------------------------------------------------------- 1 | extern void transform_c(int *, double *, double *, double *, double *); 2 | extern void inv_transform_c(int *, double *, double *, double *, double *); 3 | extern void log_jacobian_c(int *, double *, double *, double *, double *); 4 | extern void trans_grad_c(int *, double *, double *, double *, double *); 5 | extern void many_transform_c(int *, int *, double *, double *, double *); 6 | extern void many_inv_transform_c(int *, int *, double *, double *, double *); 7 | extern void many_log_jacobian_c(int *, int *, double *, double *, double *, double *); 8 | extern void many_trans_grad_c(int *, int *, double *, double *, double *, double *); 9 | extern void many_trans_grad_c2(int *, int *, double *, double *, double *, double *, int *); 10 | -------------------------------------------------------------------------------- /vip/kernel/pytrans.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | 4 | cdef extern from "pytrans.h": 5 | void transform_c(int *, double *, double *, double *, double *); 6 | void inv_transform_c(int *, double *, double *, double *, double *); 7 | void log_jacobian_c(int *, double *, double *, double *, double *); 8 | void trans_grad_c(int *, double *, double *, double *, double *); 9 | void many_transform_c(int *, int *, double *, double *, double *); 10 | void many_inv_transform_c(int *, int *, double *, double *, double *); 11 | void many_log_jacobian_c(int *, int *, double *, double *, double *, double *); 12 | void many_trans_grad_c(int *, int *, double *, double *, double *, double *); 13 | void many_trans_grad_c2(int *, int *, double *, double *, double *, double *, int *); 14 | 15 | def pytrans(np.ndarray[double,ndim=2] x, 16 | np.ndarray[double,ndim=1] lb, 17 | np.ndarray[double,ndim=1] ub): 18 | 19 | cdef int m, n 20 | m = x.shape[0] 21 | n = x.shape[1] 22 | many_transform_c(&m,&n,&x[0,0],&lb[0],&ub[0]) 23 | 24 | return x 25 | 26 | def pyinv_trans(np.ndarray[double,ndim=2] x, 27 | np.ndarray[double,ndim=1] lb, 28 | np.ndarray[double,ndim=1] ub): 29 | 30 | cdef int m, n 31 | m = x.shape[0] 32 | n = x.shape[1] 33 | many_inv_transform_c(&m,&n,&x[0,0],&lb[0],&ub[0]) 34 | 35 | return x 36 | 37 | def pyjac(np.ndarray[double,ndim=2] x, 38 | np.ndarray[double,ndim=1] lb, 39 | np.ndarray[double,ndim=1] ub): 40 | 41 | cdef int m, n 42 | m = x.shape[0] 43 | n = x.shape[1] 44 | 45 | cdef np.ndarray[double,ndim=1] jac = np.zeros((m,), dtype=np.float64) 46 | many_log_jacobian_c(&m,&n,&x[0,0],&lb[0],&ub[0],&jac[0]) 47 | return jac 48 | 49 | def pytrans_grad(np.ndarray[double,ndim=2] grad, 50 | np.ndarray[double,ndim=2] x, 51 | np.ndarray[double,ndim=1] lb, 52 | np.ndarray[double,ndim=1] ub, 53 | int rmask=0): 54 | 55 | cdef int m, n 56 | m = x.shape[0] 57 | n = x.shape[1] 58 | cdef np.ndarray[int,ndim=2] mask = np.zeros((m,n), dtype=np.int32) 59 | if(rmask): 60 | many_trans_grad_c2(&m,&n,&grad[0,0],&x[0,0],&lb[0],&ub[0],&mask[0,0]) 61 | else: 62 | many_trans_grad_c(&m,&n,&grad[0,0],&x[0,0],&lb[0],&ub[0]) 63 | return grad, np.array(mask,dtype=bool) 64 | 65 | -------------------------------------------------------------------------------- /vip/kernel/setup.cfg: -------------------------------------------------------------------------------- 1 | [build_ext] 2 | force=1 3 | -------------------------------------------------------------------------------- /vip/kernel/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | from Cython.Build import cythonize 3 | from distutils.extension import Extension 4 | from Cython.Distutils import build_ext 5 | import numpy as np 6 | from os import system 7 | 8 | # compile fortran code 9 | make_comp = 'make' 10 | print(make_comp) 11 | system('make clean') 12 | system(make_comp) 13 | 14 | extensions = [Extension("pykernel", 15 | ["pykernel.pyx"], 16 | #["pytrans.pyx","pykernel.pyx"], 17 | include_dirs=[np.get_include()], 18 | libraries=["gfortran","gomp"], 19 | extra_compile_args=['-O3'], 20 | extra_link_args=['-L/usr/lib64','-lm'], 21 | extra_objects=["utils.o","transform.o","kernel.o"]), 22 | Extension("pytrans", 23 | ["pytrans.pyx"], 24 | #["pytrans.pyx","pykernel.pyx"], 25 | include_dirs=[np.get_include()], 26 | libraries=["gfortran","gomp"], 27 | extra_compile_args=['-O3'], 28 | extra_link_args=['-L/usr/lib64','-lm'], 29 | extra_objects=["utils.o","transform.o","kernel.o"]) 30 | ] 31 | 32 | for e in extensions: 33 | e.cython_directives={'language_level': "3"} 34 | 35 | setup( 36 | name = 'pysvgd', 37 | cmdclass = {'build_ext':build_ext}, 38 | #ext_modules = cythonize(extensions, language_level = "3") 39 | ext_modules = extensions, 40 | ) 41 | 42 | system('make clean') 43 | system('rm -rf build') 44 | -------------------------------------------------------------------------------- /vip/kernel/test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytrans 3 | 4 | ns = 20 5 | n = 401*401*181 6 | 7 | x = np.random.rand(ns,n) 8 | lbnd = np.full((n,),fill_value=-0.1) 9 | ubnd = np.full((n,),fill_value=1.1) 10 | 11 | #y = np.copy(x) 12 | print(np.mean(x)) 13 | pytrans.pytrans(x,lbnd,ubnd) 14 | print(np.mean(x)) 15 | pytrans.pyinv_trans(x,lbnd,ubnd) 16 | print(np.mean(x)) 17 | #print(np.max(x-y),np.min(x-y)) 18 | 19 | pytrans.pytrans(x,lbnd,ubnd) 20 | 21 | grad = np.random.rand(ns,n) 22 | grad, mask = pytrans.pytrans_grad(grad,x,lbnd,ubnd,rmask=1) 23 | -------------------------------------------------------------------------------- /vip/kernel/test_kernel.py: -------------------------------------------------------------------------------- 1 | from pykernel import pdist, svgd_gradient, pyksd 2 | import numpy as np 3 | import scipy.spatial.distance as sd 4 | import kernel 5 | import time 6 | 7 | 8 | nparticles = 100 9 | ndim = 500000 10 | eps = 1e-6 11 | batchsize = 100000 12 | 13 | x = np.random.random((nparticles,ndim)) 14 | w = np.full((ndim,),fill_value=1.,dtype=np.float64) 15 | 16 | print("Testing pdist function ...") 17 | s = time.time() 18 | #distance = scipy.spatial.distance.pdist(x,metric='minkowski',p=2,w=w) 19 | distance = sd.pdist(x) 20 | distance = sd.squareform(distance)**2 21 | print('scipy time: '+str(time.time()-s)) 22 | 23 | s = time.time() 24 | dist = pdist(x,w) 25 | print('pysvgd: '+str(time.time()-s)) 26 | print(dist[0,0],dist[80,80]) 27 | assert (abs(distance-dist)=0)then 52 | exp_term = exp(-qvals(i)) 53 | qvals(i) = lower_bounds(i) + (upper_bounds(i)-lower_bounds(i))& 54 | / (1+exp_term) 55 | else 56 | exp_term = exp(qvals(i)) 57 | qvals(i) = upper_bounds(i) + (lower_bounds(i) - upper_bounds(i))& 58 | / (1+exp_term) 59 | endif 60 | endif 61 | enddo 62 | 63 | endsubroutine inv_transform 64 | 65 | function log_jacobian(qvals_trans, lower_bounds, upper_bounds) 66 | use ieee_arithmetic 67 | implicit none 68 | real(kind=dp), dimension(:), intent(in) :: qvals_trans 69 | real(kind=dp), dimension(:), intent(in) :: lower_bounds 70 | real(kind=dp), dimension(:), intent(in) :: upper_bounds 71 | real(kind=dp) log_jacobian 72 | 73 | integer i 74 | 75 | log_jacobian = 0. 76 | do i = 1, size(qvals_trans) 77 | if(ieee_is_finite(lower_bounds(i)) .and. .not.ieee_is_finite(upper_bounds(i)))then 78 | log_jacobian = log_jacobian + qvals_trans(i) 79 | elseif(.not.ieee_is_finite(lower_bounds(i)) .and. ieee_is_finite(upper_bounds(i)))then 80 | log_jacobian = log_jacobian + qvals_trans(i) 81 | else 82 | if(qvals_trans(i)>=0)then 83 | log_jacobian = log_jacobian + log(upper_bounds(i)-lower_bounds(i)) & 84 | - qvals_trans(i) - 2*log(1+exp(-qvals_trans(i))) 85 | else 86 | log_jacobian = log_jacobian + log(upper_bounds(i)-lower_bounds(i)) & 87 | + qvals_trans(i) - 2*log(1+exp(qvals_trans(i))) 88 | endif 89 | endif 90 | enddo 91 | 92 | endfunction log_jacobian 93 | 94 | ! calculate new gradient after transformation, note it is actually a diagonal matrix 95 | subroutine jacobian_trans_grad(grad, qvals_trans, lower_bounds, upper_bounds, mask) 96 | use ieee_arithmetic 97 | implicit none 98 | real(kind=dp), dimension(:), intent(inout) :: grad 99 | real(kind=dp), dimension(:), intent(in) :: qvals_trans 100 | real(kind=dp), dimension(:), intent(in) :: lower_bounds 101 | real(kind=dp), dimension(:), intent(in) :: upper_bounds 102 | integer(c_int), dimension(:), intent(out), optional :: mask 103 | 104 | integer i 105 | real(kind=dp) exp_term, gjacob, ggrad 106 | 107 | if(present(mask)) mask = 0 108 | 109 | do i = 1, size(qvals_trans) 110 | exp_term = exp(qvals_trans(i)) 111 | if(ieee_is_finite(lower_bounds(i)) .and. .not.ieee_is_finite(upper_bounds(i)))then 112 | grad(i) = exp_term*grad(i) - 1 113 | elseif(.not.ieee_is_finite(lower_bounds(i)) .and. ieee_is_finite(upper_bounds(i)))then 114 | grad(i) = -exp_term*grad(i) - 1 115 | else 116 | if(qvals_trans(i)>=0)then 117 | exp_term = exp(-qvals_trans(i)) 118 | gjacob = 1 - 2/(1+exp_term) 119 | else 120 | exp_term = exp(qvals_trans(i)) 121 | gjacob = 1 - 2*exp_term/(1+exp_term) 122 | endif 123 | ggrad = exp_term*(upper_bounds(i)-lower_bounds(i))/(1+exp_term)**2 * grad(i) 124 | grad(i) = ggrad + gjacob 125 | if(present(mask) .and. abs(ggrad)self.ub)): 61 | logp = -np.inf 62 | 63 | return logp 64 | 65 | def grad(self, theta): 66 | ''' 67 | Compute gradient of log probability 68 | Input 69 | theta: the value of random variable 70 | Return 71 | lnprob: the gradient 72 | ''' 73 | g = 0 74 | 75 | return g 76 | 77 | class Gaussian(): 78 | ''' 79 | Class Gaussian() 80 | A class that implements Gaussian distribution 81 | ''' 82 | 83 | def __init__(self, mu=0, sigma=1, cov=None): 84 | ''' 85 | mu: mean 86 | sigma: standard deviation 87 | ''' 88 | self.mu = mu 89 | self.sigma = sigma 90 | 91 | def mean(self): 92 | return self.mu 93 | 94 | def std(self): 95 | return self.sigma 96 | 97 | def cov(self): 98 | return self.cov 99 | 100 | def lnprob(self, theta): 101 | ''' 102 | Compute log probability 103 | Input 104 | theta: the value of random variable 105 | Return 106 | lnprob: the log probability 107 | ''' 108 | 109 | logp = -0.5*np.sum(((theta-self.mu)/self.sigma)**2) - np.sum(np.log(self.sigma)) - 0.5*self.mu.shape[0]*np.log(2*np.pi) 110 | 111 | return logp 112 | 113 | def grad(self, theta): 114 | ''' 115 | Compute gradient of log probability 116 | Input 117 | theta: the value of random variable 118 | Return 119 | lnprob: the gradient 120 | ''' 121 | g = -(theta-self.mu)/self.sigma**2 122 | 123 | return g 124 | -------------------------------------------------------------------------------- /vip/prior/prior.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from vip.prior.transform import trans, trans_grad 3 | from vip.kernel.pytrans import pyjac 4 | 5 | class prior(): 6 | ''' 7 | Class prior() 8 | A class that implements prior information 9 | ''' 10 | 11 | def __init__(self, pdf=None, transform=False, lb=None, ub=None, 12 | smooth=False, L=None): 13 | ''' 14 | pdf: a pdf class defined in pdf.py 15 | transform: if True, transform from constrained variable to unconstrained variable 16 | lb, ub: if transform is True, specify the lower and upper boundary 17 | smooth: if True, adding smoothness constraint 18 | L: smooth matrix which is a scipy sparse matrix 19 | ''' 20 | 21 | self.pdf = pdf 22 | self.transform = transform 23 | self.lb = lb 24 | self.ub = ub 25 | self.smooth = smooth 26 | self.L = L 27 | 28 | def trans(self): 29 | return self.transform 30 | 31 | def pdf(self): 32 | return self.pdf 33 | 34 | def lnprob(self, x): 35 | ''' 36 | Calculate log probability of x 37 | Input 38 | x: value of the random variable, shape (nparticles,nparameters) 39 | Return 40 | logp: the log probability 41 | ''' 42 | 43 | logp = self.pdf.lnprob(x) 44 | 45 | if(self.smooth): 46 | logsp = self.logp_smooth(x) 47 | logp = logp + logsp 48 | 49 | if(self.transform): 50 | logp = logp + pyjac(x,self.lb,self.ub) 51 | 52 | return logp 53 | 54 | def logp_smooth(self,x): 55 | ''' return smooth log probability 56 | Input 57 | x: 2D array with dimension nparticles*nparameters 58 | Return: log probability, shape (nparticles,) 59 | ''' 60 | dx = self.L*x.T 61 | self.L = self.L.eliminate_zeros() 62 | num_elements = self.L.indptr[1:] - self.L.indptr[:-1] 63 | diag = self.L.diagonal()/(num_elements-1) 64 | logsp = -0.5*np.sum(dx**2,axis=0) + np.sum(np.log(np.abs(diag))) - 0.5*self.L.shape[0]*np.log(2*np.pi) 65 | 66 | return logsp 67 | 68 | def grad_matrix(self, x, grad): 69 | ''' return gradient of smooth prior 70 | Input 71 | grad: grad will be updated in-place for saving memory 72 | x: 2D array with dimension nparticles*nparameters 73 | Return: updated gradient 74 | ''' 75 | g = self.L*x.T 76 | g = self.L.transpose()*g 77 | grad += -g.T 78 | 79 | return grad 80 | 81 | def grad(self, x, grad=None, chunks=None): 82 | ''' 83 | Calculate gradient of log probability w.r.t x 84 | Input 85 | x: value of the random variable, 2D array with dimension nparticles*nparameters 86 | grad: grad contains the gradient of likelihood w.r.t original variable 87 | Return: gradient including prior pdf 88 | ''' 89 | 90 | if(grad is None): 91 | grad = np.zeros(x.shape) 92 | 93 | if(self.smooth): 94 | grad = self.grad_matrix(x, grad) 95 | 96 | mask = np.zeros(x.shape,dtype=bool) 97 | if(self.transform): 98 | x = trans(x, batchsize=chunks, trans=1, lb=self.lb, ub=self.ub) 99 | grad, mask = trans_grad(grad, x, mask, batchsize=chunks, lb=self.lb, ub=self.ub) 100 | else: 101 | g = self.pdf.grad(x) 102 | grad += g 103 | 104 | return grad, mask 105 | 106 | def clip(self, x): 107 | ''' 108 | Clip the variable according to the lower and upper boundary if transform is False 109 | Input: x is the variable 110 | Return: clipped x 111 | ''' 112 | w = np.where(x < self.lb) 113 | x[w] = self.lb[w[1]] 114 | w = np.where(x > self.ub) 115 | x[w] = self.ub[w[1]] 116 | 117 | return x 118 | 119 | def adjust(self, x, chunk=None): 120 | ''' 121 | Adjust variable to be within prior if Uniform, or transform back to original variable if transform is True 122 | Input: x 123 | Return: adjusted x 124 | ''' 125 | 126 | if( (not self.transform) and (self.lb is not None) ): 127 | x = self.clip(x) 128 | 129 | if( self.transform ): 130 | x = trans(x, batchsize=chunk, trans=0, lb=self.lb, ub=self.ub) 131 | 132 | return x 133 | -------------------------------------------------------------------------------- /vip/prior/transform.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from vip.kernel.pytrans import * 3 | 4 | def trans(x, batchsize=None, trans=1, lb=0, ub=1e8): 5 | ''' 6 | Transform between constrained and unconstrained variable 7 | Input 8 | x: original variable, has a dimension (n,dim) where n is the number of variables 9 | batchsize: minibatch of variables, default to n 10 | trans: transform direction, 1 transform constrained to unconstrained, 0 inverse 11 | lb, ub: lower and upper bound, a vector of length dim 12 | Return 13 | x: transformed variable 14 | ''' 15 | n = x.shape[0] 16 | if(batchsize is None): 17 | batchsize = n 18 | 19 | for i in range(0,n,batchsize): 20 | end = min(i+batchsize,n) 21 | if(trans==1): 22 | x[i:end,:] = pytrans(np.ascontiguousarray(x[i:end,:],dtype=np.float64), 23 | np.ascontiguousarray(lb,dtype=np.float64), 24 | np.ascontiguousarray(ub,dtype=np.float64)) 25 | else: 26 | x[i:end,:] = pyinv_trans(np.ascontiguousarray(x[i:end,:],dtype=np.float64), 27 | np.ascontiguousarray(lb,dtype=np.float64), 28 | np.ascontiguousarray(ub,dtype=np.float64)) 29 | return x 30 | 31 | def trans_grad(grad, x, mask=None, batchsize=None, lb=0, ub=1e8): 32 | ''' 33 | Gradient after transforming from constrained variable to unconstrained variable 34 | Input 35 | grad: gradient of original varialbe 36 | x: transformed variable 37 | mask: an array to store the mask array 38 | batchsize: minibatch of variables, default to n 39 | lb, ub: lower and upper bound, a vector of length dim 40 | Return 41 | grad: transformed gradient 42 | mask: mask array 43 | ''' 44 | n = x.shape[0] 45 | if(batchsize is None): 46 | batchsize = n 47 | 48 | for i in range(0,n,batchsize): 49 | end = min(i+batchsize,n) 50 | g, m = pytrans_grad(np.ascontiguousarray(grad[i:end,:],dtype=np.float64), 51 | np.ascontiguousarray(x[i:end,:],dtype=np.float64), 52 | np.ascontiguousarray(lb,dtype=np.float64), 53 | np.ascontiguousarray(ub,dtype=np.float64),rmask=1) 54 | grad[i:end,:] = g 55 | if(mask is not None): mask[i:end,:] = m 56 | 57 | return grad, mask 58 | 59 | -------------------------------------------------------------------------------- /vip/pyvi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin2zhang/VIP/4857809b4d4e774595b08ab1905387d8555b88d1/vip/pyvi/__init__.py -------------------------------------------------------------------------------- /vip/pyvi/advi.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from vip.pyvi.optimizer import optimizer as optm 3 | 4 | class ADVI(): 5 | ''' 6 | Class ADVI() 7 | A class that implements ADVI algorithm 8 | ''' 9 | 10 | def __init__(self, lnprob, kernel='meanfield', nmc=4, mu0=None, omega0=None): 11 | ''' 12 | lnprob: log of the probability density function, usually negtive misfit function 13 | kernel: kernel function, 'meanfield' or 'fullrank' supported 14 | optimizer: the optimizing method, including 'sgd','adagrad', 'adadelta' and 'adam' 15 | nmc: number of monte carlo samples used to calculate gradients 16 | mu0, omega0: initial mean and variance value 17 | ''' 18 | 19 | self.lnprob = lnprob 20 | self.kernel = kernel 21 | self.nmc = nmc 22 | self.mu = mu0 23 | 24 | n = mu0.shape[0] 25 | self.omega = omega0 26 | if(self.omega is None and self.kernel=='meanfield'): 27 | self.omega = np.ones((n,)) 28 | if(self.omega is None and self.kernel=='fullrank'): 29 | self.omega = np.identity(n) 30 | 31 | def grad(self, x): 32 | ''' 33 | Calculate gradient for advi 34 | Input 35 | x: a vector of [mu,omega] 36 | Return 37 | loss: the loss value for all samples 38 | grad: gradient of x 39 | ''' 40 | 41 | if(self.kernel == 'meanfield'): 42 | loss, grad = self.__gradw(x) 43 | elif(self.kernel == 'fullrank'): 44 | loss, grad = self.__gradL(x) 45 | else: 46 | print('Not supported kernel') 47 | 48 | 49 | return loss, grad, None 50 | 51 | def __gradw(self, x): 52 | n = self.mu.shape[0] 53 | mu = x[0:n] 54 | omega = x[n:] 55 | eta = np.random.normal(size=(self.nmc,n)) 56 | 57 | theta = mu + np.exp(omega)*eta 58 | loss, grad, _ = self.lnprob(theta) 59 | 60 | gradu = np.mean(grad,axis=0) 61 | gradw = grad * eta * np.exp(omega)[None,:] 62 | gradw = np.mean(gradw,axis=0) + 1 63 | 64 | grad = np.concatenate((gradu,gradw),axis=0) 65 | return loss, grad 66 | 67 | def __gradL(self, x): 68 | n = self.mu.shape[0] 69 | mu = x[0:n] 70 | L = np.tril(x[n:].reshape((n,n))) 71 | eta = np.random.normal(size=(self.nmc,n)) 72 | 73 | theta = mu + np.matmul(L,eta.transpose()).transpose() 74 | loss, grad, _ = self.lnprob(theta) 75 | 76 | gradu = np.mean(grad,axis=0) 77 | gradw = np.zeros((n,n)) 78 | for i in range(self.nmc): 79 | gradw += np.outer(grad[i,:],eta[i,:]) 80 | gradw = gradw/self.nmc + np.linalg.inv(L).transpose() 81 | gradw = np.tril(gradw).flatten() 82 | 83 | grad = np.concatenate((gradu,gradw),axis=0) 84 | return loss, grad 85 | 86 | def sample(self, optimizer='sgd', n_iter = 1000, stepsize = 1e-3, gamma=1.0, decay_step=1, alpha=0.9, 87 | beta=0.99): 88 | ''' 89 | Update mu and omega (L) 90 | Input 91 | n_iter: the number of iterations 92 | stepsize: stepsize for each iteration 93 | gamma: decaying rate for stepsize 94 | decay_step: the number of steps to decay the stepsize 95 | alpha, beta: hyperparameter for sgd and adam, for sgd only alpha is ued 96 | Return 97 | x: updated mu and omega (L) 98 | losses: loss values across iterations 99 | ''' 100 | 101 | x = np.concatenate((self.mu,self.omega.flatten()),axis=0) 102 | 103 | op = optm(x.shape, self.grad, method=optimizer, alpha=alpha, beta=beta) 104 | x, losses = op.optim(x, n_iter=n_iter, stepsize=stepsize, gamma=gamma, decay_step=decay_step) 105 | 106 | 107 | return losses, x 108 | -------------------------------------------------------------------------------- /vip/pyvi/optimizer.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class optimizer(): 4 | ''' 5 | Class optimizer() 6 | A class that implements different optimizing algorithms, including 'sgd', 'adagrad', 'adadelta' and 'adam' 7 | ''' 8 | def __init__(self, shape, lnprob, method='sgd', alpha=0.9, beta=0.99, eps = 1e-6): 9 | ''' 10 | shape: shape of the variable 11 | lnprob: log of the probability density function, usually negtive misfit function 12 | method: optimizing method, including 'sgd','adagrad','adadelta' and 'adam' 13 | alpha, beta: hyperparameters for optimizer 14 | eps: a small value to avoid zero dividing 15 | ''' 16 | 17 | self.shape = shape 18 | self.lnprob = lnprob 19 | self.alpha = alpha 20 | self.beta = beta 21 | self.method = method 22 | self.eps = eps 23 | 24 | self.num = np.zeros(shape) 25 | self.den = np.zeros(shape) 26 | 27 | def sgd(self, theta, step): 28 | ''' 29 | Stochastic gradient descent with momentum, set alpha=0 to exlude momentum 30 | Input 31 | theta: the current variable 32 | step: stepsize for current iteration 33 | Return 34 | update: update of theta 35 | loss: loss value for current theta 36 | ''' 37 | 38 | loss, grad, mask = self.lnprob(theta) 39 | self.num[mask] = 0 40 | self.num = self.alpha*self.num + step*grad 41 | update = self.num 42 | 43 | return update, loss 44 | 45 | def adagrad(self, theta, step): 46 | ''' 47 | Adagrad algorithm, alpha is the hyperparameter that controls decaying rate 48 | Input 49 | theta: the current variable 50 | step: stepsize for current iteration 51 | Return 52 | update: update of theta 53 | loss: loss value for current theta 54 | ''' 55 | 56 | loss, grad, _ = self.lnprob(theta) 57 | self.den = self.alpha * self.den + (1-self.alpha) * grad**2 58 | update = step * np.divide(grad, self.eps+np.sqrt(self.den)) 59 | 60 | return update, loss 61 | 62 | def adadelta(self, theta, step): 63 | ''' 64 | Adadelta algorithm, alpha is the hyperparameter that controls decaying rate 65 | Input 66 | theta: the current variable 67 | step: stepsize for current iteration 68 | Return 69 | update: update of theta 70 | loss: loss value for current theta 71 | ''' 72 | 73 | loss, grad, _ = self.lnprob(theta) 74 | self.den = self.alpha * self.den + (1-self.alpha) * grad**2 75 | update = step * np.divide(np.sqrt(self.num)+self.eps,np.sqrt(self.den)+self.eps) 76 | update = update * grad 77 | self.num = self.alpha * self.num + (1-self.alpha) * update**2 78 | 79 | return update, loss 80 | 81 | def adam(self, theta, step, itr): 82 | ''' 83 | Adam algorithm, alpha and beta are the hyperparameters that controls decaying rate 84 | for grad and grad**2 respectively 85 | Input 86 | theta: the current variable 87 | step: stepsize for current iteration 88 | itr: the current iteration 89 | Return 90 | update: update of theta 91 | loss: loss value for current theta 92 | ''' 93 | 94 | loss, grad, _ = self.lnprob(theta) 95 | self.num = self.alpha * self.num + (1-self.alpha) * grad 96 | self.den = self.beta * self.den + (1-self.beta) * grad**2 97 | 98 | m = self.num/(1-self.alpha**(itr)) 99 | v = self.den/(1-self.beta**(itr)) 100 | 101 | update = step * np.divide(m, np.sqrt(v)+self.eps) 102 | 103 | return update, loss 104 | 105 | def optim(self, x0, n_iter=1000, stepsize=1e-3, gamma=1.0, decay_step=1): 106 | ''' 107 | Run the optimization 108 | Input 109 | x0: initial value, must have the shape as defined in the constructor 110 | n_iter: the number of iterations 111 | stepsize: learning rate / step size 112 | gamma: decaying rate for stepsize 113 | decay_step: the number of steps to decay the learning rate 114 | Return 115 | theta: optimized value for the variable 116 | losses: loss value for all iterations 117 | ''' 118 | 119 | losses = np.zeros((n_iter,x0.shape[0])) 120 | theta = x0 121 | 122 | step = np.full((n_iter,),stepsize) 123 | for i in range(1,n_iter): 124 | if(i%decay_step == 0): 125 | step[i] = stepsize * gamma 126 | else: 127 | step[i] = step[i-1] 128 | 129 | for i in range(n_iter): 130 | print(f'Iteration: {i}') 131 | if(self.method=='sgd'): 132 | update, loss = self.sgd(theta,step[i]) 133 | elif(self.method=='adagrad'): 134 | update, loss = self.adagrad(theta,step[i]) 135 | elif(self.method=='adadelta'): 136 | update, loss = self.adadelta(theta,step[i]) 137 | elif(self.method=='adam'): 138 | update, loss = self.adam(theta,step[i],i) 139 | else: 140 | print('Not supported optimizer') 141 | 142 | theta += update 143 | losses[i,:] = loss 144 | 145 | return theta, losses 146 | 147 | --------------------------------------------------------------------------------