def CAE_infMALA(self): """ infinite dimensional Metropolis Adjusted Langevin Algorithm with AutoEncoder """ logvol=0 # initialization q=self.q.copy() rth=np.sqrt(self.h) # sample velocity v=self.randv() # natural gradient ng=self.model.prior.C_act(self.g) # update velocity v.axpy(rth/2,ng) # current energy E_cur = -self.ll - rth/2*self.g.inner(v) + self.h/8*self.g.inner(ng) # correct volume if requested if self.volcrK: q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None]) logvol+=self.cae.logvol(q_,'encode') # generate proposal according to Langevin dynamics q.zero() q.axpy((1-self.h/4)/(1+self.h/4),self.q) q.axpy(rth/(1+self.h/4),v) # update velocity v_=v.copy();v.zero() v.axpy(-(1-self.h/4)/(1+self.h/4),v_) v.axpy(rth/(1+self.h/4),self.q) # update geometry ll,g,_,_=self.geom(q) # natural gradient ng=self.model.prior.C_act(g) # new energy E_prp = -ll - rth/2*g.inner(v) + self.h/8*g.inner(ng) # correct volume if requested if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode') # Metropolis test logr=-E_prp+E_cur+logvol if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr): # accept self.q=q; self.ll=ll; self.g=g; acpt=True else: acpt=False # return accept indicator return acpt,logr
def logvol(unknown_lat, V_lat, autoencoder, coding): if 'Conv' in type(autoencoder).__name__: u_latin = fun2img(vec2fun(unknown_lat, V_lat)) u_latin = chop(u_latin)[None, :, :, None] if autoencoder.activations[ 'latent'] is None else u_latin.flatten()[None, :] else: u_latin = unknown_lat.get_local()[None, :] return autoencoder.logvol({ 'encode': autoencoder.decode(u_latin), 'decode': u_latin }[coding], coding)
def CAE_pCN(self): """ preconditioned Crank-Nicolson with AutoEncoder """ logvol=0 # initialization q=self.q.copy() # sample velocity v=self.randv() # correct volume if requested if self.volcrK: q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None]) # chop image to have even dimensions logvol+=self.cae.logvol(q_,'encode') # generate proposal according to Crank-Nicolson scheme q.zero() q.axpy((1-self.h/4)/(1+self.h/4),self.q) q.axpy(np.sqrt(self.h)/(1+self.h/4),v) # update geometry ll,_,_,_=self.geom(q) # correct volume if requested if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode') # TODO: need go back to the original scale too? # Metropolis test logr=ll-self.ll+logvol if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr): # accept self.q=q; self.ll=ll; acpt=True else: acpt=False # return accept indicator return acpt,logr
def retrieve_ensemble(bip, dir_name, f_name, ensbl_sz, max_iter, img_out=False, whiten=False): f = df.HDF5File(bip.pde.mpi_comm, os.path.join(dir_name, f_name), "r") ensbl_f = df.Function(bip.pde.V) num_ensbls = max_iter * ensbl_sz if img_out: gdim = bip.pde.V.mesh().geometry().dim() imsz = np.floor(bip.pde.V.dim()**(1. / gdim)).astype('int') out_shape = (num_ensbls, np.int( bip.pde.V.dim() / imsz**(gdim - 1))) + (imsz, ) * (gdim - 1) else: out_shape = (num_ensbls, bip.pde.V.dim()) out = np.zeros(out_shape) prog = np.ceil(num_ensbls * (.1 + np.arange(0, 1, .1))) for n in range(max_iter): for j in range(ensbl_sz): f.read(ensbl_f, 'iter{0}_ensbl{1}'.format(n + ('Y' not in TRAIN), j)) s = n * ensbl_sz + j if whiten: ensbl_v = bip.prior.u2v(ensbl_f.vector()) out[s] = fun2img(vec2fun( ensbl_v, bip.pde.V)) if img_out else ensbl_v.get_local() else: out[s] = fun2img( ensbl_f) if img_out else ensbl_f.vector().get_local() if s + 1 in prog: print('{0:.0f}% ensembles have been retrieved.'.format( np.float(s + 1) / num_ensbls * 100)) f.close() return out
if u_ref is not None: u.axpy(1.0,u_ref) return u if __name__ == '__main__': from pde import * np.random.seed(2016) PDE = ellipticPDE() mpi_comm = PDE.mesh.mpi_comm() prior = Gaussian_prior(V=PDE.V,mpi_comm=mpi_comm) whiten = False u=prior.sample(whiten=whiten) logpri,gradpri=prior.logpdf(u, whiten=whiten, grad=True) print('The logarithm of prior density at u is %0.4f, and the L2 norm of its gradient is %0.4f' %(logpri,gradpri.norm('l2'))) df.plot(vec2fun(u,PDE.V)) # df.interactive() v=prior.u2v(u) logpri_wt,gradpri_wt=prior.logpdf(v, whiten=True, grad=True) print('The logarithm of prior density at whitened v is %0.4f, and the L2 norm of its gradient is %0.4f' %(logpri_wt,gradpri_wt.norm('l2'))) df.plot(vec2fun(v,PDE.V)) # df.interactive() whiten = True v=prior.sample(whiten=whiten) logpri,gradpri=prior.logpdf(v, whiten=whiten, grad=True) print('The logarithm of prior density at whitened v is %0.4f, and the L2 norm of its gradient is %0.4f' %(logpri,gradpri.norm('l2'))) df.plot(vec2fun(v,PDE.V)) # df.interactive() u=prior.v2u(v) logpri_wt,gradpri_wt=prior.logpdf(u, whiten=False, grad=True)
os.path.join('./result', "MAP_SNR" + str(SNR) + ".h5"), "r") f.read(u_f, "parameter") f.close() except: pass u = u_f.vector() # u=elliptic.prior.sample() loglik = lambda y: -0.5 * elliptic.misfit.prec * tf.math.reduce_sum( (y - elliptic.misfit.obs)**2, axis=1) loglik_cnn = lambda x: loglik(cnn.model(x)) loglik_dnn = lambda x: loglik(dnn.model(x)) # calculate gradient dll_xact = elliptic.get_geom(u, [0, 1])[1] # emulate gradient u_img = fun2img(vec2fun(u, elliptic.pde.V)) dll_cnn = cnn.gradient(u_img[None, :, :, None], loglik_cnn) dll_dnn = dnn.gradient(u.get_local()[None, :], loglik_dnn) # plot import matplotlib.pyplot as plt import matplotlib as mp plt.rcParams['image.cmap'] = 'jet' fig, axes = plt.subplots(nrows=1, ncols=3, sharex=True, sharey=True, figsize=(15, 5)) sub_figs = [None] * 3 # plot plt.axes(axes.flat[0])
samp_std=elliptic.prior.gen_vector(); samp_std.zero() # num_read=0 for f_i in hdf5_files: if '_'+algs[i]+'_' in f_i: try: f=df.HDF5File(bip.pde.mpi_comm,os.path.join(folder,f_i),"r") samp_mean.zero(); samp_std.zero(); num_read=0 for s in range(num_samp): if s+1 in prog: print('{0:.0f}% has been completed.'.format(np.float(s+1)/num_samp*100)) f.read(samp_f,'sample_{0}'.format(s)) u=samp_f.vector() if '_whitened_latent' in f_i: u=bip.prior.v2u(u) if 'DREAM' in algs[i]: if 'c' in AE: u_latin=fun2img(vec2fun(u, elliptic_latent.pde.V)) width=tuple(np.mod(i,2) for i in u_latin.shape) u_latin=chop(u_latin,width)[None,:,:,None] if autoencoder.activations['latent'] is None else u_latin.flatten()[None,:] u=img2fun(pad(np.squeeze(autoencoder.decode(u_latin)),width),elliptic.pde.V).vector() else: u_latin=u.get_local()[None,:] u=elliptic.prior.gen_vector(autoencoder.decode(u_latin).flatten()) # else: # u=u_ if '_whitened_emulated' in f_i: u=elliptic.prior.v2u(u) samp_mean.axpy(wts[s],u) samp_std.axpy(wts[s],u*u) # num_read+=1 f.close() print(f_i+' has been read!') f_read=f_i
def geom(unknown_lat, V_lat, V, autoencoder, geom_ord=[0], whitened=False, **kwargs): loglik = None gradlik = None metact = None rtmetact = None eigs = None # un-whiten if necessary if whitened == 'latent': bip_lat = kwargs.get('bip_lat') unknown_lat = bip_lat.prior.v2u(unknown_lat) # u_latin={'AutoEncoder':unknown_lat.get_local()[None,:],'ConvAutoEncoder':chop(fun2img(vec2fun(unknown_lat, V_lat)))[None,:,:,None]}[type(autoencoder).__name__] if 'Conv' in type(autoencoder).__name__: u_latin = fun2img(vec2fun(unknown_lat, V_lat)) width = tuple(np.mod(i, 2) for i in u_latin.shape) u_latin = chop(u_latin, width)[None, :, :, None] if autoencoder.activations[ 'latent'] is None else u_latin.flatten()[None, :] unknown = img2fun(pad(np.squeeze(autoencoder.decode(u_latin)), width), V).vector() else: u_latin = unknown_lat.get_local()[None, :] unknown = df.Function(V).vector() unknown.set_local(autoencoder.decode(u_latin).flatten()) emul_geom = kwargs.pop('emul_geom', None) full_geom = kwargs.pop('full_geom', None) bip_lat = kwargs.pop('bip_lat', None) bip = kwargs.pop('bip', None) try: if len(kwargs) == 0: loglik, gradlik, metact_, rtmetact_ = emul_geom( unknown, geom_ord, whitened == 'emulated') else: loglik, gradlik, metact_, eigs_ = emul_geom( unknown, geom_ord, whitened == 'emulated', **kwargs) except: try: if len(kwargs) == 0: loglik, gradlik, metact_, rtmetact_ = full_geom( unknown, geom_ord, whitened == 'original') else: loglik, gradlik, metact_, eigs_ = full_geom( unknown, geom_ord, whitened == 'original', **kwargs) except: raise RuntimeError('No geometry in the original space available!') if any(s >= 1 for s in geom_ord): if whitened == 'latent': gradlik = bip.prior.C_act(gradlik, .5, op='C', transp=True) # jac_=autoencoder.jacobian(u_latin,'decode') if 'Conv' in type(autoencoder).__name__: # if autoencoder.activations['latent'] is None: # # jac__=np.zeros(jac_.shape[:2]+tuple(i+1 for i in jac_.shape[2:])) # # jac__[:,:,:-1,:-1]=jac_; jac_=jac__ # jac_=pad(jac_,(0,)*2+width) # jac_=jac_.reshape(jac_.shape[:2]+(-1,)) # d2v = df.dof_to_vertex_map(V_lat) # jac_=jac_[:,:,d2v] # jac=MultiVector(unknown,V_lat.dim()) # # [jac[i].set_local(img2fun(pad(jac_[:,:,i]), V).vector() if 'Conv' in type(autoencoder).__name__ else jac_[:,i]) for i in range(V_lat.dim())] # not working: too many indices? # if 'Conv' in type(autoencoder).__name__: # [jac[i].set_local(img2fun(pad(jac_[:,:,i],width), V).vector()) for i in range(V_lat.dim())] # for loop is too slow # else: # [jac[i].set_local(jac_[:,i]) for i in range(V_lat.dim()) for i in range(V_lat.dim())] # for loop is too slow # gradlik_=jac.dot(gradlik) jac_ = autoencoder.jacobian(u_latin, 'decode') jac_ = pad( jac_, width * 2 if autoencoder.activations['latent'] is None else width + (0, )) jac_ = jac_.reshape( (np.prod(jac_.shape[:2]), np.prod(jac_.shape[2:]))) jac_ = jac_[np.ix_(df.dof_to_vertex_map(V), df.dof_to_vertex_map(V_lat))] # try: # import timeit # t_start=timeit.default_timer() # jac=create_PETScMatrix(jac_.shape,V.mesh().mpi_comm(),range(jac_.shape[0]),range(jac_.shape[1]),jac_) # gradlik_=df.as_backend_type(gradlik).vec() # gradlik1=df.Vector(unknown_lat) # jac.multTranspose(gradlik_,df.as_backend_type(gradlik1).vec()) # print('time consumed:{}'.format(timeit.default_timer()-t_start)) # except: # t_start=timeit.default_timer() gradlik_ = jac_.T.dot(gradlik.get_local()) gradlik_ = autoencoder.jacvec(u_latin, gradlik.get_local()[None, :]) gradlik = df.Vector(unknown_lat) gradlik.set_local(gradlik_) # print('time consumed:{}'.format(timeit.default_timer()-t_start)) if any(s >= 1.5 for s in geom_ord): def _get_metact_misfit(u_actedon): if type(u_actedon) is df.Vector: u_actedon = u_actedon.get_local() tmp = df.Vector(unknown) tmp.zero() jac.reduce(tmp, u_actedon) v = df.Vector(unknown_lat) v.set_local(jac.dot(metact_(tmp))) return v def _get_rtmetact_misfit(u_actedon): if type(u_actedon) is not df.Vector: u_ = df.Vector(unknown) u_.set_local(u_actedon) u_actedon = u_ v = df.Vector(unknown_lat) v.set_local(jac.dot(rtmetact_(u_actedon))) return v metact = _get_metact_misfit rtmetact = _get_rtmetact_misfit if any(s > 1 for s in geom_ord) and len(kwargs) != 0: if bip_lat is None: raise ValueError('No latent inverse problem defined!') # compute eigen-decomposition using randomized algorithms if whitened == 'latent': # generalized eigen-decomposition (_C^(1/2) F _C^(1/2), M), i.e. _C^(1/2) F _C^(1/2) = M V D V', V' M V = I def invM(a): a = bip_lat.prior.gen_vector(a) invMa = bip_lat.prior.gen_vector() bip_lat.prior.Msolver.solve(invMa, a) return invMa eigs = geigen_RA(metact, lambda u: bip_lat.prior.M * u, invM, dim=bip_lat.pde.V.dim(), **kwargs) else: # generalized eigen-decomposition (F, _C^(-1)), i.e. F = _C^(-1) U D U^(-1), U' _C^(-1) U = I, V = _C^(-1/2) U eigs = geigen_RA(metact, lambda u: bip_lat.prior.C_act(u, -1, op='K'), lambda u: bip_lat.prior.C_act(u, op='K'), dim=bip_lat.pde.V.dim(), **kwargs) if any(s > 1.5 for s in geom_ord): # adjust the gradient # update low-rank approximate Gaussian posterior bip_lat.post_Ga = Gaussian_apx_posterior(bip_lat.prior, eigs=eigs) # Hu = bip_lat.prior.gen_vector() # bip_lat.post_Ga.Hlr.mult(unknown, Hu) # gradlik.axpy(1.0,Hu) if len(kwargs) == 0: return loglik, gradlik, metact, rtmetact else: return loglik, gradlik, metact, eigs
# emulation by GP t_start = timeit.default_timer() ll_emul = logLik_g(u.get_local()[None, :]).numpy() dll_emul = gp.gradient(u.get_local()[None, :], logLik_g) t_used[1] += timeit.default_timer() - t_start # record difference dif_fun = np.abs(ll_xact - ll_emul) dif_grad = dll_xact.get_local() - dll_emul fun_errors[0, s, t, n] = dif_fun grad_errors[0, s, t, n] = np.linalg.norm(dif_grad) / dll_xact.norm('l2') # emulation by CNN t_start = timeit.default_timer() u_img = fun2img(vec2fun(u, elliptic.pde.V)) ll_emul = logLik_c(u_img[None, :, :, None]).numpy() dll_emul = cnn.gradient(u_img[None, :, :, None], logLik_c) #* grad_scalfctr t_used[2] += timeit.default_timer() - t_start # record difference dif_fun = np.abs(ll_xact - ll_emul) dif_grad = dll_xact - img2fun(dll_emul, elliptic.pde.V).vector() fun_errors[1, s, t, n] = dif_fun grad_errors[1, s, t, n] = dif_grad.norm('l2') / dll_xact.norm('l2') print( 'Time used for calculation: {} vs GP-emulation: {} vs CNN-emulation: {}' .format(*t_used.tolist()))
def CAE_DRinfmHMC(self): """ dimension-reduced infinite dimensional manifold HMC with AutoEncoder """ logvol=0 # initialization q=self.q.copy() rth=np.sqrt(self.h) # make the scale comparable to MALA # cos_=np.cos(rth); sin_=np.sin(rth); cos_=(1-self.h/4)/(1+self.h/4); sin_=rth/(1+self.h/4); # sample velocity v=self.randv(self.model.post_Ga) # natural gradient ng=self.model.post_Ga.postC_act(self.g) # use low-rank posterior Hessian solver # accumulate the power of force pw = rth/2*self.model.prior.C_act(v,-1).inner(ng) # current energy E_cur = -self.ll + self.h/4*self.model.prior.logpdf(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+self.eigs[0])) # use low-rank Hessian inner product # correct volume if requested if self.volcrK: q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None]) logvol+=self.cae.logvol(q_,'encode') randL=np.int(np.ceil(np.random.uniform(0,self.L))) for l in range(randL): # a half step for velocity v.axpy(rth/2,ng) # a full step rotation q_=q.copy();q.zero() q.axpy(cos_,q_) q.axpy(sin_,v) v_=v.copy();v.zero() v.axpy(cos_,v_) v.axpy(-sin_,q_) # update geometry ll,g,_,eigs=self.geom(q) self.model.post_Ga.eigs=eigs # update the eigen-pairs in low-rank approximation --important! ng=self.model.post_Ga.postC_act(g) # another half step for velocity v.axpy(rth/2,ng) # accumulate the power of force if l!=randL-1: pw+=rth*self.model.prior.C_act(v,-1).inner(ng) # accumulate the power of force pw += rth/2*self.model.prior.C_act(v,-1).inner(ng) # new energy E_prp = -ll + self.h/4*self.model.prior.logpdf(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+eigs[0])) # correct volume if requested if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode') # Metropolis test logr=-E_prp+E_cur-pw+logvol if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr): # accept self.q=q; self.ll=ll; self.g=g; self.eigs=eigs; acpt=True else: acpt=False # return accept indicator return acpt,logr
def CAE_DRinfmMALA(self): """ dimension-reduced infinite dimensional manifold MALA with AutoEncoder """ logvol=0 # initialization q=self.q.copy() rth=np.sqrt(self.h) # sample velocity v=self.randv(self.model.post_Ga) # natural gradient ng=self.model.post_Ga.postC_act(self.g) # use low-rank posterior Hessian solver # update velocity v.axpy(rth/2,ng) # current energy E_cur = -self.ll - rth/2*self.g.inner(v) + self.h/8*self.g.inner(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+self.eigs[0])) # use low-rank Hessian inner product # correct volume if requested if self.volcrK: q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None]) logvol+=self.cae.logvol(q_,'encode') # generate proposal according to simplified manifold Langevin dynamics q.zero() q.axpy((1-self.h/4)/(1+self.h/4),self.q) q.axpy(rth/(1+self.h/4),v) # update velocity v_=v.copy();v.zero() v.axpy(-(1-self.h/4)/(1+self.h/4),v_) v.axpy(rth/(1+self.h/4),self.q) # update geometry ll,g,_,eigs=self.geom(q) self.model.post_Ga.eigs=eigs # update the eigen-pairs in low-rank approximation --important! # natural gradient ng=self.model.post_Ga.postC_act(g) # new energy E_prp = -ll - rth/2*g.inner(v) + self.h/8*g.inner(ng) +0.5*self.model.post_Ga.Hlr.norm2(v) -0.5*sum(np.log(1+eigs[0])) # correct volume if requested if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode') # Metropolis test logr=-E_prp+E_cur+logvol if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr): # accept self.q=q; self.ll=ll; self.g=g; self.eigs=eigs; acpt=True else: acpt=False # return accept indicator return acpt,logr
def CAE_infHMC(self): """ infinite dimensional Hamiltonian Monte Carlo with AutoEncoder """ logvol=0 # initialization q=self.q.copy() rth=np.sqrt(self.h) # make the scale comparable to MALA cos_=np.cos(rth); sin_=np.sin(rth); # sample velocity v=self.randv() # natural gradient ng=self.model.prior.C_act(self.g) # accumulate the power of force pw = rth/2*self.g.inner(v) # current energy E_cur = -self.ll - self.h/8*self.g.inner(ng) # correct volume if requested if self.volcrK: q_=self.cae.decode(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None]) logvol+=self.cae.logvol(q_,'encode') randL=np.int(np.ceil(np.random.uniform(0,self.L))) for l in range(randL): # a half step for velocity v.axpy(rth/2,ng) # a full step for position q_=q.copy();q.zero() q.axpy(cos_,q_) q.axpy(sin_,v) v_=v.copy();v.zero() v.axpy(-sin_,q_) v.axpy(cos_,v_) # update geometry ll,g,_,_=self.geom(q) ng=self.model.prior.C_act(g) # another half step for velocity v.axpy(rth/2,ng) # accumulate the power of force if l!=randL-1: pw+=rth*g.inner(v) # accumulate the power of force pw += rth/2*g.inner(v) # new energy E_prp = -ll - self.h/8*g.inner(ng) # correct volume if requested if self.volcrK: logvol+=self.cae.logvol(chop(fun2img(vec2fun(q,self.model.pde.V)))[None,:,:,None],'decode') # Metropolis test logr=-E_prp+E_cur-pw+logvol if np.isfinite(logr) and np.log(np.random.uniform())<min(0,logr): # accept self.q=q; self.ll=ll; self.g=g; acpt=True else: acpt=False # return accept indicator return acpt,logr
def geom(unknown, bip, emulator, geom_ord=[0], whitened=False, **kwargs): loglik = None gradlik = None metact = None rtmetact = None eigs = None # un-whiten if necessary if whitened: unknown = bip.prior.v2u(unknown) u_input = { 'DNN': unknown.get_local()[None, :], 'CNN': fun2img(vec2fun(unknown, bip.pde.V))[None, :, :, None] }[type(emulator).__name__] ll_f = lambda x: -0.5 * bip.misfit.prec * tf.math.reduce_sum( (emulator.model(x) - bip.misfit.obs)**2, axis=1) if any(s >= 0 for s in geom_ord): loglik = ll_f(u_input).numpy() if any(s >= 1 for s in geom_ord): gradlik_ = emulator.gradient(u_input, ll_f) # gradlik = {'DNN':bip.prior.gen_vector(gradlik_), 'CNN':img2fun(gradlik_, bip.pde.V).vector()}[type(emulator).__name__] # not working if type(emulator).__name__ == 'DNN': gradlik = bip.prior.gen_vector(gradlik_) elif type(emulator).__name__ == 'CNN': gradlik = img2fun(gradlik_, bip.pde.V).vector() if whitened: gradlik = bip.prior.C_act(gradlik, .5, op='C', transp=True) if any(s >= 1.5 for s in geom_ord): jac_ = emulator.jacobian(u_input) n_obs = len(bip.misfit.idx) jac = MultiVector(unknown, n_obs) [ jac[i].set_local({ 'DNN': jac_[i], 'CNN': img2fun(jac_[i], bip.pde.V).vector() }[type(emulator).__name__]) for i in range(n_obs) ] def _get_metact_misfit(u_actedon): # GNH if type(u_actedon) is not df.Vector: u_actedon = bip.prior.gen_vector(u_actedon) v = bip.prior.gen_vector() jac.reduce(v, bip.misfit.prec * jac.dot(u_actedon)) return bip.prior.M * v def _get_rtmetact_misfit(u_actedon): if type(u_actedon) is df.Vector: u_actedon = u_actedon.get_local() v = bip.prior.gen_vector() jac.reduce(v, np.sqrt(bip.misfit.prec) * u) return bip.prior.rtM * v metact = _get_metact_misfit rtmetact = _get_rtmetact_misfit if whitened: metact = lambda u: bip.prior.C_act(_get_metact_misfit( bip.prior.C_act(u, .5, op='C')), .5, op='C', transp=True) # ppGNH rtmetact = lambda u: bip.prior.C_act( _get_rtmetact_misfit(u), .5, op='C', transp=True) if any(s > 1 for s in geom_ord) and len(kwargs) != 0: if whitened: # generalized eigen-decomposition (_C^(1/2) F _C^(1/2), M), i.e. _C^(1/2) F _C^(1/2) = M V D V', V' M V = I def invM(a): a = bip.prior.gen_vector(a) invMa = bip.prior.gen_vector() bip.prior.Msolver.solve(invMa, a) return invMa eigs = geigen_RA(metact, lambda u: bip.prior.M * u, invM, dim=bip.pde.V.dim(), **kwargs) else: # generalized eigen-decomposition (F, _C^(-1)), i.e. F = _C^(-1) U D U^(-1), U' _C^(-1) U = I, V = _C^(-1/2) U eigs = geigen_RA(metact, lambda u: bip.prior.C_act(u, -1, op='K'), lambda u: bip.prior.C_act(u, op='K'), dim=bip.pde.V.dim(), **kwargs) if any(s > 1.5 for s in geom_ord): # adjust the gradient # update low-rank approximate Gaussian posterior bip.post_Ga = Gaussian_apx_posterior(bip.prior, eigs=eigs) Hu = bip.prior.gen_vector() bip.post_Ga.Hlr.mult(unknown, Hu) gradlik.axpy(1.0, Hu) if len(kwargs) == 0: return loglik, gradlik, metact, rtmetact else: return loglik, gradlik, metact, eigs