Exemplo n.º 1
0
 def test01_alt(self):
     """Set directory"""
     if isdir(self.myoutdir):
         os.system('rm -rf {0}'.format(self.myoutdir))
     myplot = PlotFenics()
     myplot.set_outdir(self.myoutdir)
     self.assertTrue(isdir(self.myoutdir))
Exemplo n.º 2
0
 def test01_alt(self):
     """Set directory"""
     if isdir(self.myoutdir):
         os.system('rm -rf {0}'.format(self.myoutdir))
     myplot = PlotFenics()
     myplot.set_outdir(self.myoutdir)
     self.assertTrue(isdir(self.myoutdir))
Exemplo n.º 3
0
 def test05(self):
     """Indices list properly created"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     for ii in self.indexlist:
         self.m.vector()[:] = ii * np.ones(self.lenm, dtype='float')
         myplot.plot_vtk(self.m, ii)
     self.assertTrue(myplot.indices == self.indexlist)
Exemplo n.º 4
0
 def test04(self):
     """Plot parameter m"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     self.m.vector()[:] = 20 * np.ones(self.lenm, dtype='float')
     myplot.plot_vtk(self.m, 20)
     self.assertTrue(isfile(self.myoutdir+'testm_20.pvd') and \
     isfile(self.myoutdir+'testm_20000000.vtu'))
Exemplo n.º 5
0
 def solvefwd(self, cost=False):
     """Solve fwd operators for given RHS"""
     self.nbfwdsolves += 1
     if self.ObsOp.noise:    self.noise = 0.0
     if self.plot:
         self.plotu = PlotFenics(self.plotoutdir)
         self.plotu.set_varname('u{0}'.format(self.nbfwdsolves))
     if cost:    self.misfit = 0.0
     for ii, rhs in enumerate(self.RHS):
         self.solve_A(self.u.vector(), rhs)
         if self.plot:   self.plotu.plot_vtk(self.u, ii)
         u_obs, noiselevel = self.ObsOp.obs(self.u)
         self.U.append(u_obs)
         if self.ObsOp.noise:    self.noise += noiselevel
         if cost:
             self.misfit += self.ObsOp.costfct(u_obs, self.UD[ii])
         self.C.append(assemble(self.c))
     if cost:
         self.misfit /= len(self.U)
         self.regul = self.Regul.cost(self.m)
         self.cost = self.misfit + self.regul
     if self.ObsOp.noise and self.myrank == 0:
         print 'Total noise in data misfit={:.5e}\n'.\
         format(self.noise*.5/len(self.U))
         self.ObsOp.noise = False    # Safety
     if self.plot:   self.plotu.gather_vtkplots()
Exemplo n.º 6
0
 def _set_plots(self, plot):
     self.plot = plot
     if self.plot:
         filename, ext = splitext(sys.argv[0])
         self.plotoutdir = filename + '/Plots/'
         self.plotvarm = PlotFenics(self.plotoutdir)
         self.plotvarm.set_varname('m')
Exemplo n.º 7
0
 def test06(self):
     """Gather plots"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     myplot.indices = self.indexlist
     myplot.gather_vtkplots()
     self.assertTrue(isfile(self.myoutdir + 'testm.pvd'))
Exemplo n.º 8
0
 def test09(self):
     """Indices are reset when varname changed"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     indexlist = [1, 3]
     for ii in indexlist:
         self.m.vector()[:] = ii * np.ones(self.lenm, dtype='float')
         myplot.plot_vtk(self.m, ii)
     myplot.set_varname('testm2')
     self.assertTrue((myplot.varname == 'testm2') and \
     (myplot.indices == []))
Exemplo n.º 9
0
 def test06(self):
     """Gather plots"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     myplot.indices = self.indexlist
     myplot.gather_vtkplots()
     self.assertTrue(isfile(self.myoutdir+'testm.pvd'))
Exemplo n.º 10
0
 def test09(self):
     """Indices are reset when varname changed"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     indexlist = [1,3]
     for ii in indexlist:
         self.m.vector()[:] = ii * np.ones(self.lenm, dtype='float')
         myplot.plot_vtk(self.m, ii)
     myplot.set_varname('testm2')
     self.assertTrue((myplot.varname == 'testm2') and \
     (myplot.indices == []))
Exemplo n.º 11
0
 def test05(self):
     """Indices list properly created"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     for ii in self.indexlist:
         self.m.vector()[:] = ii * np.ones(self.lenm, dtype='float')
         myplot.plot_vtk(self.m, ii)
     self.assertTrue(myplot.indices == self.indexlist)
Exemplo n.º 12
0
 def test04(self):
     """Plot parameter m"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     self.m.vector()[:] = 20 * np.ones(self.lenm, dtype='float')
     myplot.plot_vtk(self.m, 20)
     self.assertTrue(isfile(self.myoutdir+'testm_20.pvd') and \
     isfile(self.myoutdir+'testm_20000000.vtu'))
Exemplo n.º 13
0
 def __init__(self, mesh, trueImage, parameters=[]):
     """
     Inputs:
         mesh = Fenics mesh
         trueImage = object from class Image
         parameters = dict
     """
     # Mesh
     self.mesh = mesh
     self.V = dl.FunctionSpace(self.mesh, "Lagrange", 1)
     self.xx = self.V.dofmap().tabulate_all_coordinates(self.mesh)
     self.dimV = self.V.dim()
     self.test, self.trial = dl.TestFunction(self.V), dl.TrialFunction(self.V)
     self.f_true = dl.interpolate(trueImage, self.V)
     self.g, self.dg, self.gtmp = dl.Function(self.V), dl.Function(self.V), dl.Function(self.V)
     self.Grad = dl.Function(self.V)
     self.Gradnorm0 = None
     # mass matrix
     self.Mweak = dl.inner(self.test, self.trial) * dl.dx
     self.M = dl.assemble(self.Mweak)
     self.solverM = dl.LUSolver("petsc")
     self.solverM.parameters["symmetric"] = True
     self.solverM.parameters["reuse_factorization"] = True
     self.solverM.set_operator(self.M)
     # identity matrix
     self.I = dl.assemble(self.Mweak)
     self.I.zero()
     self.I.set_diagonal(dl.interpolate(dl.Constant(1), self.V).vector())
     # self.targetnorm = np.sqrt((self.M*self.f_true.vector()).inner(self.f_true.vector()))
     self.targetnorm = np.sqrt((self.f_true.vector()).inner(self.f_true.vector()))
     # line search parameters
     self.parameters = {"alpha0": 1.0, "rho": 0.5, "c": 5e-5, "max_backtrack": 12}
     # regularization
     self.parameters.update({"eps": 1e-4, "k": 1.0, "regularization": "TV", "mode": "primaldual"})
     self.parameters.update(parameters)
     self.define_regularization()
     self.regparam = 1.0
     # plots:
     filename, ext = os.path.splitext(sys.argv[0])
     if os.path.isdir(filename + "/"):
         shutil.rmtree(filename + "/")
     self.myplot = PlotFenics(filename)
Exemplo n.º 14
0
 def solveadj(self, grad=False):
     """Solve adj operators"""
     self.nbadjsolves += 1
     if self.plot:
         self.plotp = PlotFenics(self.plotoutdir)
         self.plotp.set_varname('p{0}'.format(self.nbadjsolves))
     self.Nbsrc = len(self.UD)
     if grad:    self.MG.vector()[:] = np.zeros(self.lenm)
     for ii, C in enumerate(self.C):
         self.ObsOp.assemble_rhsadj(self.U[ii], self.UD[ii], \
         self.rhs, self.bcadj)
         self.solve_A(self.p.vector(), self.rhs.vector())
         if self.plot:   self.plotp.plot_vtk(self.p, ii)
         self.E.append(assemble(self.e))
         if grad:    self.MG.vector().axpy(1.0/self.Nbsrc, \
                     C * self.p.vector())
     if grad:
         self.MG.vector().axpy(1.0, self.Regul.grad(self.m))
         self.solverM.solve(self.Grad.vector(), self.MG.vector())
         self.Gradnorm = np.sqrt(self.Grad.vector().inner(self.MG.vector()))
     if self.plot:   self.plotp.gather_vtkplots()
Exemplo n.º 15
0
 def test03(self):
     """Need index list defined to gather"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     self.assertRaises(NoIndicesError, myplot.gather_vtkplots)
Exemplo n.º 16
0
 def test02_alt(self):
     """Need varname defined to plot"""
     myplot = PlotFenics(self.myoutdir)
     self.m.vector()[:] = np.ones(self.lenm)
     self.assertRaises(NoVarnameError, myplot.plot_vtk, self.m)
Exemplo n.º 17
0
 def test02(self):
     """Instantiate class when dir exists"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_outdir(self.myoutdir + 'Test1/')
     self.assertTrue(myplot.outdir == self.myoutdir + 'Test1/')
Exemplo n.º 18
0
 def test02(self):
     """Instantiate class when dir exists"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_outdir(self.myoutdir + 'Test1/')
     self.assertTrue(myplot.outdir == self.myoutdir + 'Test1/')
Exemplo n.º 19
0
 def test01(self):
     """Instantiate class when dir does not exist"""
     if isdir(self.myoutdir):
         os.system('rm -rf {0}'.format(self.myoutdir))
     myplot = PlotFenics(self.myoutdir)
     self.assertTrue(isdir(self.myoutdir))
Exemplo n.º 20
0
 def test00_defdir(self):
     """Check default directory"""
     if isdir(self.defoutdir):
         os.system('rm -rf {0}'.format(self.defoutdir))
     myplot = PlotFenics()
     self.assertTrue(isdir(self.defoutdir))
Exemplo n.º 21
0
 def test00_inst(self):
     """Default instantiation"""
     myplot = PlotFenics()
Exemplo n.º 22
0
 def test03(self):
     """Need index list defined to gather"""
     myplot = PlotFenics(self.myoutdir)
     myplot.set_varname('testm')
     self.assertRaises(NoIndicesError, myplot.gather_vtkplots)
Exemplo n.º 23
0
 def test08(self):
     """Fenics_vtu_correction variable"""
     myplot = PlotFenics(self.myoutdir)
     self.assertTrue(isfile(self.myoutdir+'testm_20'+\
     myplot.Fenics_vtu_correction+'.vtu'))
Exemplo n.º 24
0
    def __init__(self,
                 CGdeg,
                 regularizationtype,
                 h=1.0,
                 parameters=[],
                 image='image.dat'):
        class Image(dl.Expression):
            def __init__(self, Lx, Ly, data):
                self.data = data
                self.hx = Lx / float(self.data.shape[1] - 1)
                self.hy = Ly / float(self.data.shape[0] - 1)

            def eval(self, values, x):
                j = math.floor(x[0] / self.hx)
                i = math.floor(x[1] / self.hy)
                values[0] = self.data[i, j]

        data = np.loadtxt(image, delimiter=',')
        #Lx, Ly = float(data.shape[1])/float(data.shape[0]), 1.
        Lx, Ly = 2., 1.
        scaling = 100. * h  # =1.0 => h~0.01
        Lx, Ly = scaling * Lx, scaling * Ly
        np.random.seed(seed=1)
        noise_std_dev = 0.3
        noise = noise_std_dev * np.random.randn(data.shape[0], data.shape[1])
        print '||noise||={}'.format(np.linalg.norm(noise))
        mesh = dl.RectangleMesh(dl.Point(0, 0), dl.Point(Lx, Ly), 200, 100)
        mcoord = mesh.coordinates()
        print 'hx={}, hy={}'.format((mcoord[-1][0] - mcoord[0][0]) / 200.,
                                    (mcoord[-1][1] - mcoord[0][1]) / 100.)
        V = dl.FunctionSpace(mesh, 'Lagrange', CGdeg)
        trueImage = Image(Lx, Ly, data)
        noisyImage = Image(Lx, Ly, data + noise)
        print 'min(data)={}, max(data)={}'.format(np.amin(data), np.amax(data))
        print 'min(data+noise)={}, max(data+noise)={}'.format(
            np.amin(data + noise), np.amax(data + noise))
        self.u_true = dl.interpolate(trueImage, V)
        self.u_0 = dl.interpolate(noisyImage, V)

        self.u = dl.Function(V)
        self.ucopy = dl.Function(V)
        self.G = dl.Function(V)
        self.du = dl.Function(V)
        u_test = dl.TestFunction(V)
        u_trial = dl.TrialFunction(V)

        Mweak = dl.inner(u_test, u_trial) * dl.dx
        self.M = dl.assemble(Mweak)
        self.solverM = dl.LUSolver('petsc')
        self.solverM.parameters['symmetric'] = True
        self.solverM.parameters['reuse_factorization'] = True
        self.solverM.set_operator(self.M)

        self.regul = regularizationtype
        if self.regul == 'tikhonov':
            self.Regul = LaplacianPrior({'Vm': V, 'gamma': 1.0, 'beta': 0.0})
        elif self.regul == 'TV':
            paramTV = {'Vm': V, 'k': 1.0, 'eps': 1e-4, 'GNhessian': True}
            paramTV.update(parameters)
            self.Regul = TV(paramTV)
            self.inexact = False
        elif self.regul == 'TVPD':
            paramTV = {'Vm': V, 'k': 1.0, 'eps': 1e-4, 'exact': False}
            paramTV.update(parameters)
            self.Regul = TVPD(paramTV)
            self.inexact = False
        self.alpha = 1.0

        self.Hess = self.M

        self.parametersLS = {'alpha0':1.0, 'rho':0.5, 'c':5e-5, \
        'max_backtrack':12, 'cgtol':0.5, 'maxiter':50000}

        filename, ext = os.path.splitext(sys.argv[0])
        #if os.path.isdir(filename + '/'):   shutil.rmtree(filename + '/')
        self.myplot = PlotFenics(filename)

        try:
            solver = PETScKrylovSolver('cg', 'ml_amg')
            self.precond = 'ml_amg'
        except:
            print '*** WARNING: ML not installed -- using petsc_amg instead'
            self.precond = 'petsc_amg'
Exemplo n.º 25
0
class ObjectiveFunctional(LinearOperator):
    """
    Provides data misfit, gradient and Hessian information for the data misfit
    part of a time-independent symmetric inverse problem.
    """
    __metaclass__ = abc.ABCMeta

    # Instantiation
    def __init__(self, V, Vm, bc, bcadj, \
    RHSinput=[], ObsOp=[], UD=[], Regul=[], Data=[], plot=False, \
    mycomm=None):
        # Define test, trial and all other functions
        self.trial = TrialFunction(V)
        self.test = TestFunction(V)
        self.mtrial = TrialFunction(Vm)
        self.mtest = TestFunction(Vm)
        self.rhs = Function(V)
        self.m = Function(Vm)
        self.mcopy = Function(Vm)
        self.srchdir = Function(Vm)
        self.delta_m = Function(Vm)
        self.MG = Function(Vm)
        self.Grad = Function(Vm)
        self.Gradnorm = 0.0
        self.lenm = len(self.m.vector().array())
        self.u = Function(V)
        self.ud = Function(V)
        self.diff = Function(V)
        self.p = Function(V)
        # Define weak forms to assemble A, C and E
        self._wkforma()
        self._wkformc()
        self._wkforme()
        # Store other info:
        self.ObsOp = ObsOp
        self.UD = UD
        self.reset()    # Initialize U, C and E to []
        self.Data = Data
        self.GN = 1.0   # GN = 0.0 => GN Hessian; = 1.0 => full Hessian
        # Operators and bc
        LinearOperator.__init__(self, self.delta_m.vector(), \
        self.delta_m.vector()) 
        self.bc = bc
        self.bcadj = bcadj
        self._assemble_solverM(Vm)
        self.assemble_A()
        self.assemble_RHS(RHSinput)
        self.Regul = Regul
        # Counters, tolerances and others
        self.nbPDEsolves = 0    # Updated when solve_A called
        self.nbfwdsolves = 0    # Counter for plots
        self.nbadjsolves = 0    # Counter for plots
        self._set_plots(plot)
        # MPI:
        self.mycomm = mycomm
        try:
            self.myrank = MPI.rank(self.mycomm)
        except:
            self.myrank = 0

    def copy(self):
        """Define a copy method"""
        V = self.trial.function_space()
        Vm = self.mtrial.function_space()
        newobj = self.__class__(V, Vm, self.bc, self.bcadj, [], self.ObsOp, \
        self.UD, self.Regul, self.Data, False)
        newobj.RHS = self.RHS
        newobj.update_m(self.m)
        return newobj

    def mult(self, mhat, y):
        """mult(self, mhat, y): do y = Hessian * mhat
        member self.GN sets full Hessian (=1.0) or GN Hessian (=0.0)"""
        N = self.Nbsrc # Number of sources
        y[:] = np.zeros(self.lenm)
        for C, E in zip(self.C, self.E):
            # Solve for uhat
            C.transpmult(mhat, self.rhs.vector())
            self.bcadj.apply(self.rhs.vector())
            self.solve_A(self.u.vector(), -self.rhs.vector())
            # Solve for phat
            E.transpmult(mhat, self.rhs.vector())
            Etmhat = self.rhs.vector().array()
            self.rhs.vector().axpy(1.0, self.ObsOp.incradj(self.u))
            self.bcadj.apply(self.rhs.vector())
            self.solve_A(self.p.vector(), -self.rhs.vector())
            # Compute Hessian*x:
            y.axpy(1.0/N, C * self.p.vector())
            y.axpy(self.GN/N, E * self.u.vector())
        y.axpy(1.0, self.Regul.hessian(mhat))

    # Getters
    def getm(self): return self.m
    def getmarray(self):    return self.m.vector().array()
    def getmcopyarray(self):    return self.mcopy.vector().array()
    def getVm(self):    return self.mtrial.function_space()
    def getMGarray(self):   return self.MG.vector().array()
    def getMGvec(self):   return self.MG.vector()
    def getGradarray(self):   return self.Grad.vector().array()
    def getGradnorm(self):  return self.Gradnorm
    def getsrchdirarray(self):    return self.srchdir.vector().array()
    def getsrchdirvec(self):    return self.srchdir.vector()
    def getsrchdirnorm(self):
        return np.sqrt((self.MM*self.getsrchdirvec()).inner(self.getsrchdirvec()))
    def getgradxdir(self): return self.gradxdir
    def getcost(self):  return self.cost, self.misfit, self.regul
    def getprecond(self):
        Prec = PETScKrylovSolver("richardson", "amg")
        Prec.parameters["maximum_iterations"] = 1
        Prec.parameters["error_on_nonconvergence"] = False
        Prec.parameters["nonzero_initial_guess"] = False
        Prec.set_operator(self.Regul.get_precond())
        return Prec
    def getMass(self):    return self.MM

    # Setters
    def setsrchdir(self, arr):  self.srchdir.vector()[:] = arr
    def setgradxdir(self, valueloc):   
        """Sum all local results for Grad . Srch_dir"""
        try:
            valueglob = MPI.sum(self.mycomm, valueloc)
        except:
            valueglob = valueloc
        self.gradxdir = valueglob

    # Solve
    def solvefwd(self, cost=False):
        """Solve fwd operators for given RHS"""
        self.nbfwdsolves += 1
        if self.ObsOp.noise:    self.noise = 0.0
        if self.plot:
            self.plotu = PlotFenics(self.plotoutdir)
            self.plotu.set_varname('u{0}'.format(self.nbfwdsolves))
        if cost:    self.misfit = 0.0
        for ii, rhs in enumerate(self.RHS):
            self.solve_A(self.u.vector(), rhs)
            if self.plot:   self.plotu.plot_vtk(self.u, ii)
            u_obs, noiselevel = self.ObsOp.obs(self.u)
            self.U.append(u_obs)
            if self.ObsOp.noise:    self.noise += noiselevel
            if cost:
                self.misfit += self.ObsOp.costfct(u_obs, self.UD[ii])
            self.C.append(assemble(self.c))
        if cost:
            self.misfit /= len(self.U)
            self.regul = self.Regul.cost(self.m)
            self.cost = self.misfit + self.regul
        if self.ObsOp.noise and self.myrank == 0:
            print 'Total noise in data misfit={:.5e}\n'.\
            format(self.noise*.5/len(self.U))
            self.ObsOp.noise = False    # Safety
        if self.plot:   self.plotu.gather_vtkplots()

    def solvefwd_cost(self):
        """Solve fwd operators for given RHS and compute cost fct"""
        self.solvefwd(True)

    def solveadj(self, grad=False):
        """Solve adj operators"""
        self.nbadjsolves += 1
        if self.plot:
            self.plotp = PlotFenics(self.plotoutdir)
            self.plotp.set_varname('p{0}'.format(self.nbadjsolves))
        self.Nbsrc = len(self.UD)
        if grad:    self.MG.vector()[:] = np.zeros(self.lenm)
        for ii, C in enumerate(self.C):
            self.ObsOp.assemble_rhsadj(self.U[ii], self.UD[ii], \
            self.rhs, self.bcadj)
            self.solve_A(self.p.vector(), self.rhs.vector())
            if self.plot:   self.plotp.plot_vtk(self.p, ii)
            self.E.append(assemble(self.e))
            if grad:    self.MG.vector().axpy(1.0/self.Nbsrc, \
                        C * self.p.vector())
        if grad:
            self.MG.vector().axpy(1.0, self.Regul.grad(self.m))
            self.solverM.solve(self.Grad.vector(), self.MG.vector())
            self.Gradnorm = np.sqrt(self.Grad.vector().inner(self.MG.vector()))
        if self.plot:   self.plotp.gather_vtkplots()

    def solveadj_constructgrad(self):
        """Solve adj operators and assemble gradient"""
        self.solveadj(True)

    # Assembler
    def assemble_A(self):
        """Assemble operator A(m)"""
        self.A = assemble(self.a)
        self.bc.apply(self.A)
        self.set_solver()

    def solve_A(self, b, f):
        """Solve system of the form A.b = f, 
        with b and f in form to be used in solver."""
        self.solver.solve(b, f)
        self.nbPDEsolves += 1

    def assemble_RHS(self, RHSin):
        """Assemble RHS for fwd solve"""
        if RHSin == []: self.RHS = None
        else:
            self.RHS = []
            for rhs in RHSin:
                if isinstance(rhs, Expression):
                    L = rhs*self.test*dx
                    b = assemble(L)
                    self.bc.apply(b)
                    self.RHS.append(b)
                else:   raise WrongInstanceError("rhs should be Expression")

    def _assemble_solverM(self, Vm):
        self.MM = assemble(inner(self.mtrial, self.mtest)*dx)
        self.solverM = LUSolver()
        self.solverM.parameters['reuse_factorization'] = True
        self.solverM.parameters['symmetric'] = True
        self.solverM.set_operator(self.MM)

    def _set_plots(self, plot):
        self.plot = plot
        if self.plot:
            filename, ext = splitext(sys.argv[0])
            self.plotoutdir = filename + '/Plots/'
            self.plotvarm = PlotFenics(self.plotoutdir)
            self.plotvarm.set_varname('m')

    def plotm(self, index):
        if self.plot:   self.plotvarm.plot_vtk(self.m, index)

    def gatherm(self):
        if self.plot:   self.plotvarm.gather_vtkplots()

    # Update param
    def update_Data(self, Data):
        """Update Data member"""
        self.Data = Data
        self.assemble_A()
        self.reset()

    def update_m(self, m):
        """Update values of parameter m"""
        if isinstance(m, np.ndarray):
            self.m.vector()[:] = m
        elif isinstance(m, Function):
            self.m.assign(m)
        elif isinstance(m, float):
            self.m.vector()[:] = m
        elif isinstance(m, int):
            self.m.vector()[:] = float(m)
        else:   raise WrongInstanceError('Format for m not accepted')
        self.assemble_A()
        self.reset()

    def backup_m(self):
        self.mcopy.assign(self.m)

    def restore_m(self):
        self.update_m(self.mcopy)

    def reset(self):
        """Reset U, C and E"""
        self.U = []
        self.C = []
        self.E = []

    def set_solver(self):
        """Reset solver for fwd operator"""
        self.solver = LUSolver()
        self.solver.parameters['reuse_factorization'] = True
        self.solver.set_operator(self.A)

    def addPDEcount(self, increment=1):
        """Increase 'nbPDEsolves' by 'increment'"""
        self.nbPDEsolves += increment

    def resetPDEsolves(self):
        self.nbPDEsolves = 0

    # Additional methods for compatibility with CG solver:
    def init_vector(self, x, dim):
        """Initialize vector x to be compatible with parameter
         Does not work in dolfin 1.3.0"""
        self.MM.init_vector(x, 0)

    def init_vector130(self):
        """Initialize vector x to be compatible with parameter"""
        return Vector(Function(self.mcopy.function_space()).vector())

    # Abstract methods
    @abc.abstractmethod
    def _wkforma(self): self.a = []

    @abc.abstractmethod
    def _wkformc(self): self.c = []

    @abc.abstractmethod
    def _wkforme(self): self.e = []
Exemplo n.º 26
0
class ObjectiveImageDenoising():
    def __init__(self,
                 CGdeg,
                 regularizationtype,
                 h=1.0,
                 parameters=[],
                 image='image.dat'):
        class Image(dl.Expression):
            def __init__(self, Lx, Ly, data):
                self.data = data
                self.hx = Lx / float(self.data.shape[1] - 1)
                self.hy = Ly / float(self.data.shape[0] - 1)

            def eval(self, values, x):
                j = math.floor(x[0] / self.hx)
                i = math.floor(x[1] / self.hy)
                values[0] = self.data[i, j]

        data = np.loadtxt(image, delimiter=',')
        #Lx, Ly = float(data.shape[1])/float(data.shape[0]), 1.
        Lx, Ly = 2., 1.
        scaling = 100. * h  # =1.0 => h~0.01
        Lx, Ly = scaling * Lx, scaling * Ly
        np.random.seed(seed=1)
        noise_std_dev = 0.3
        noise = noise_std_dev * np.random.randn(data.shape[0], data.shape[1])
        print '||noise||={}'.format(np.linalg.norm(noise))
        mesh = dl.RectangleMesh(dl.Point(0, 0), dl.Point(Lx, Ly), 200, 100)
        mcoord = mesh.coordinates()
        print 'hx={}, hy={}'.format((mcoord[-1][0] - mcoord[0][0]) / 200.,
                                    (mcoord[-1][1] - mcoord[0][1]) / 100.)
        V = dl.FunctionSpace(mesh, 'Lagrange', CGdeg)
        trueImage = Image(Lx, Ly, data)
        noisyImage = Image(Lx, Ly, data + noise)
        print 'min(data)={}, max(data)={}'.format(np.amin(data), np.amax(data))
        print 'min(data+noise)={}, max(data+noise)={}'.format(
            np.amin(data + noise), np.amax(data + noise))
        self.u_true = dl.interpolate(trueImage, V)
        self.u_0 = dl.interpolate(noisyImage, V)

        self.u = dl.Function(V)
        self.ucopy = dl.Function(V)
        self.G = dl.Function(V)
        self.du = dl.Function(V)
        u_test = dl.TestFunction(V)
        u_trial = dl.TrialFunction(V)

        Mweak = dl.inner(u_test, u_trial) * dl.dx
        self.M = dl.assemble(Mweak)
        self.solverM = dl.LUSolver('petsc')
        self.solverM.parameters['symmetric'] = True
        self.solverM.parameters['reuse_factorization'] = True
        self.solverM.set_operator(self.M)

        self.regul = regularizationtype
        if self.regul == 'tikhonov':
            self.Regul = LaplacianPrior({'Vm': V, 'gamma': 1.0, 'beta': 0.0})
        elif self.regul == 'TV':
            paramTV = {'Vm': V, 'k': 1.0, 'eps': 1e-4, 'GNhessian': True}
            paramTV.update(parameters)
            self.Regul = TV(paramTV)
            self.inexact = False
        elif self.regul == 'TVPD':
            paramTV = {'Vm': V, 'k': 1.0, 'eps': 1e-4, 'exact': False}
            paramTV.update(parameters)
            self.Regul = TVPD(paramTV)
            self.inexact = False
        self.alpha = 1.0

        self.Hess = self.M

        self.parametersLS = {'alpha0':1.0, 'rho':0.5, 'c':5e-5, \
        'max_backtrack':12, 'cgtol':0.5, 'maxiter':50000}

        filename, ext = os.path.splitext(sys.argv[0])
        #if os.path.isdir(filename + '/'):   shutil.rmtree(filename + '/')
        self.myplot = PlotFenics(filename)

        try:
            solver = PETScKrylovSolver('cg', 'ml_amg')
            self.precond = 'ml_amg'
        except:
            print '*** WARNING: ML not installed -- using petsc_amg instead'
            self.precond = 'petsc_amg'

    def solve(self):
        if self.regul == 'tikhonov': self.solvetikhonov()
        elif self.regul == 'TV': self.solveTV()
        elif self.regul == 'TVPD': self.solveTV()

    def costmisfitreg(self):
        """ Compute objective function (cost = misfit + alpha*reg) """

        misfit = 0.5*(self.Hess*(self.u.vector() - self.u_0.vector())).inner(\
        self.u.vector() - self.u_0.vector())
        reg = self.Regul.cost(self.u)
        cost = misfit + self.alpha * reg

        return cost, misfit, reg

    def gradient(self):
        """ Compute gradient at current value of self.u """

        MG = self.Hess * (self.u.vector() - self.u_0.vector())
        MG.axpy(self.alpha, self.Regul.grad(self.u))

        self.solverM.solve(self.G.vector(), MG)

        return MG, np.sqrt(MG.inner(self.G.vector()))

    def mediummisfit(self):
        """ Compute medium misfit """

        return np.sqrt((self.Hess*(self.u.vector() - self.u_true.vector())).inner(\
        self.u.vector() - self.u_true.vector()))

    def solvetikhonov(self):

        print '\t{:12s} {:12s} {:12s} {:12s} {:12s} {:12s}'.format(\
        'iter', 'cost', 'misfit', 'reg', 'medmisfit', 'n_cg')

        self.u.vector().zero()

        MG, MGnorm = self.gradient()

        H = self.Hess + self.Regul.R * self.alpha
        solver = dl.PETScKrylovSolver("cg", "petsc_amg")
        solver.set_operator(H)
        cgiter = solver.solve(self.u.vector(), -MG)

        cost, misfit, reg = self.costmisfitreg()
        print '{:12s} {:12.4e} {:12.4e} {:12.4e} {:12.4e} {:12d}'.format(\
        '', cost, misfit, reg, self.mediummisfit(), cgiter)

    def searchdirection(self, MG, cgtol):
        """ Compute search direction """

        self.Regul.assemble_hessian(self.u)
        if self.Regul.isPD():
            H = self.Hess + self.Regul.Hrs * self.alpha
            #H = self.Hess + self.Regul.H*self.alpha
        else:
            H = self.Hess + self.Regul.H * self.alpha

        if True:
            solver = dl.PETScKrylovSolver("cg", self.precond)
            solver.parameters['nonzero_initial_guess'] = False
            solver.parameters['relative_tolerance'] = cgtol
            solver.set_operator(H)
            cgiter = solver.solve(self.du.vector(), -1.0 * MG)
        else:
            solver = CGSolverSteihaug()
            solver.set_operator(H)
            solver.set_preconditioner(self.Regul.getprecond())
            solver.parameters["rel_tolerance"] = cgtol
            solver.parameters["zero_initial_guess"] = True
            solver.parameters["print_level"] = -1
            solver.solve(self.du.vector(), -1.0 * MG)
            cgiter = solver.iter

        MGdu = MG.inner(self.du.vector())
        if MGdu > 0.0:
            print "*** WARNING: NOT a descent direction"

        return cgiter, MGdu

    def linesearch(self, MG):
        """ Perform inexact backtracking line search """

        alphaLS = self.parametersLS['alpha0']
        rhoLS = self.parametersLS['rho']
        cLS = self.parametersLS['c']

        cost, misfit, reg = self.costmisfitreg()
        costref = cost
        setfct(self.ucopy, self.u)

        MGdu = MG.inner(self.du.vector()) * cLS
        success = False
        for ii in xrange(self.parametersLS['max_backtrack']):
            setfct(self.u, self.ucopy)
            self.u.vector().axpy(alphaLS, self.du.vector())
            cost, misfit, reg = self.costmisfitreg()
            if cost < costref + alphaLS * MGdu:
                success = True
                break
            else:
                alphaLS *= rhoLS

        if self.Regul.isPD(): self.Regul.update_w(self.du.vector(), alphaLS)

        return success, alphaLS, cost, misfit, reg

    def solveTV(self):
        """ Solve image denoising pb """

        self.u.vector().zero()
        normu_true = self.mediummisfit()

        # initial state = noisy image
        setfct(self.u, self.u_0)
        print 'min(u)={}, max(u)={}'.format(\
        np.amin(self.u.vector().array()), np.amax(self.u.vector().array()))

        cost, misfit, reg = self.costmisfitreg()
        costold = cost
        MG, normMG = self.gradient()
        normMG0 = normMG

        print '\t{:12s} {:12s} {:12s} {:12s} {:12s} {:12s} {:12s}\t{:12s} {:12s}'.format(\
        'iter', 'cost', 'misfit', 'reg', '||G||', 'a_LS', 'medmisfit', 'tol_cg', 'n_cg')
        print '{:12d} {:12.4e} {:12.4e} {:12.4e} {:12.4e} {:12s} {:12.2e} ({:7.2f} %)'.format(\
        0, cost, misfit, reg, normMG, '', self.mediummisfit(), 100.*self.mediummisfit()/normu_true)

        cgtol = self.parametersLS['cgtol']
        maxiter = self.parametersLS['maxiter']
        for ii in xrange(maxiter):
            if self.inexact:
                cgtol = min(cgtol, np.sqrt(normMG / normMG0))
                #cgtol = min(0.5, np.sqrt(normMG/normMG0)))
            else:
                cgtol = 1e-12
            cgiter, MGdu = self.searchdirection(MG, cgtol)
            success, alphaLS, cost, misfit, reg = self.linesearch(MG)
            MG, normMG = self.gradient()
            print '{:12d} {:12.4e} {:12.4e} {:12.4e} {:12.4e} {:12.4e} {:12.2e} ({:7.2f} %) {:12.2e} {:12d}'.format(\
            ii+1, cost, misfit, reg, normMG, alphaLS, \
            self.mediummisfit(), 100.*self.mediummisfit()/normu_true, cgtol, cgiter)

            if normMG < min(1e-12, 1e-10 * normMG0):
                print 'gradient sufficiently reduced -- optimization converged'
                break
            if not success:
                print 'Line search failed -- optimization aborted'
                break
            if np.abs(cost - costold) / costold < 1e-14:
                if cgtol < 1e-10:
                    print 'cost functional stagnates -- optimization aborted'
                    break
                else:
                    cgtol *= 1e-3

            costold = cost

        print 'min(u)={}, max(u)={}'.format(\
        np.amin(self.u.vector().array()), np.amax(self.u.vector().array()))

    def plot(self, index=0, add=''):
        """ Plot target (w/ noise 0, or w/o noise 1) or current iterate (2) """

        if index == 0:
            self.myplot.set_varname('data' + add)
            self.myplot.plot_vtk(self.u_0)
        elif index == 1:
            self.myplot.set_varname('target' + add)
            self.myplot.plot_vtk(self.u_true)
        elif index == 2:
            self.myplot.set_varname('solution' + add)
            self.myplot.plot_vtk(self.u)
Exemplo n.º 27
0
class ObjectiveImageDenoising:
    """
    Class to do image denoising
    """

    def __init__(self, mesh, trueImage, parameters=[]):
        """
        Inputs:
            mesh = Fenics mesh
            trueImage = object from class Image
            parameters = dict
        """
        # Mesh
        self.mesh = mesh
        self.V = dl.FunctionSpace(self.mesh, "Lagrange", 1)
        self.xx = self.V.dofmap().tabulate_all_coordinates(self.mesh)
        self.dimV = self.V.dim()
        self.test, self.trial = dl.TestFunction(self.V), dl.TrialFunction(self.V)
        self.f_true = dl.interpolate(trueImage, self.V)
        self.g, self.dg, self.gtmp = dl.Function(self.V), dl.Function(self.V), dl.Function(self.V)
        self.Grad = dl.Function(self.V)
        self.Gradnorm0 = None
        # mass matrix
        self.Mweak = dl.inner(self.test, self.trial) * dl.dx
        self.M = dl.assemble(self.Mweak)
        self.solverM = dl.LUSolver("petsc")
        self.solverM.parameters["symmetric"] = True
        self.solverM.parameters["reuse_factorization"] = True
        self.solverM.set_operator(self.M)
        # identity matrix
        self.I = dl.assemble(self.Mweak)
        self.I.zero()
        self.I.set_diagonal(dl.interpolate(dl.Constant(1), self.V).vector())
        # self.targetnorm = np.sqrt((self.M*self.f_true.vector()).inner(self.f_true.vector()))
        self.targetnorm = np.sqrt((self.f_true.vector()).inner(self.f_true.vector()))
        # line search parameters
        self.parameters = {"alpha0": 1.0, "rho": 0.5, "c": 5e-5, "max_backtrack": 12}
        # regularization
        self.parameters.update({"eps": 1e-4, "k": 1.0, "regularization": "TV", "mode": "primaldual"})
        self.parameters.update(parameters)
        self.define_regularization()
        self.regparam = 1.0
        # plots:
        filename, ext = os.path.splitext(sys.argv[0])
        if os.path.isdir(filename + "/"):
            shutil.rmtree(filename + "/")
        self.myplot = PlotFenics(filename)

    def generatedata(self, noisepercent):
        """ compute data and add noisepercent (%) of noise """
        sigma = noisepercent * np.linalg.norm(self.f_true.vector().array()) / np.sqrt(self.dimV)
        print "sigma_noise = ", sigma
        np.random.seed(11)  # TODO: tmp
        eta = sigma * np.random.randn(self.dimV)
        self.dn = dl.Function(self.V)
        setfct(self.dn, eta)
        self.dn.vector().axpy(1.0, self.f_true.vector())
        print "min(true)={}, max(true)={}".format(
            np.amin(self.f_true.vector().array()), np.amax(self.f_true.vector().array())
        )
        print "min(noisy)={}, max(noisy)={}".format(
            np.amin(self.dn.vector().array()), np.amax(self.dn.vector().array())
        )

    def define_regularization(self, parameters=None):
        if not parameters == None:
            self.parameters.update(parameters)
        regularization = self.parameters["regularization"]
        if regularization == "tikhonov":
            gamma = self.parameters["gamma"]
            beta = self.parameters["beta"]
            self.Reg = LaplacianPrior({"gamma": gamma, "beta": beta, "Vm": self.V})
            self.inexact = False
        elif regularization == "TV":
            eps = self.parameters["eps"]
            k = self.parameters["k"]
            mode = self.parameters["mode"]
            if mode == "primaldual":
                self.Reg = self.Reg = TVPD({"eps": eps, "k": k, "Vm": self.V, "GNhessian": False})
            elif mode == "full":
                self.Reg = TV({"eps": eps, "k": k, "Vm": self.V, "GNhessian": False})
            else:
                self.Reg = TV({"eps": eps, "k": k, "Vm": self.V, "GNhessian": True})
            self.inexact = False

    ### COST and DERIVATIVES
    def computecost(self, f=None):
        """ Compute cost functional at f """
        if f == None:
            f = self.g
        df = f.vector() - self.dn.vector()
        # self.misfit = 0.5 * (self.M*df).inner(df)
        self.misfit = 0.5 * df.inner(df)
        self.reg = self.Reg.cost(f)
        self.cost = self.misfit + self.regparam * self.reg
        return self.cost

    def gradient(self, f=None):
        """ Compute M.g (discrete gradient) at a given point f """
        if f == None:
            f = self.g
        df = f.vector() - self.dn.vector()
        # self.MGk = self.M*df
        self.MGk = df
        self.MGr = self.Reg.grad(f)
        self.MG = self.MGk + self.MGr * self.regparam
        self.solverM.solve(self.Grad.vector(), self.MG)
        self.Gradnorm = np.sqrt((self.MG).inner(self.Grad.vector()))
        if self.Gradnorm0 == None:
            self.Gradnorm0 = self.Gradnorm

    def Hessian(self, f=None):
        """ Assemble Hessian at f """
        if f == None:
            f = self.g
        regularization = self.parameters["regularization"]
        if regularization == "TV":
            self.Reg.assemble_hessian(f)
            self.Hess = self.I + self.Reg.H * self.regparam
            # self.Hess = self.M + self.Reg.H*self.regparam
        elif regularization == "tikhonov":
            self.Hess = self.M + self.Reg.Minvprior * self.regparam

    ### SOLVER
    def searchdirection(self):
        """ Compute search direction """
        self.gradient()
        self.Hessian()
        solver = dl.PETScKrylovSolver("cg", "petsc_amg")
        solver.parameters["nonzero_initial_guess"] = False
        # Inexact CG:
        if self.inexact:
            self.cgtol = min(0.5, np.sqrt(self.Gradnorm / self.Gradnorm0))
        else:
            self.cgtol = 1e-8
        solver.parameters["relative_tolerance"] = self.cgtol
        solver.set_operator(self.Hess)
        self.cgiter = solver.solve(self.dg.vector(), -1.0 * self.MG)
        if (self.MG).inner(self.dg.vector()) > 0.0:
            print "*** WARNING: NOT a descent direction"

    def linesearch(self):
        """ Perform inexact backtracking line search """
        regularization = self.parameters["regularization"]
        # compute new direction for dual variables
        if regularization == "TV" and self.Reg.isPD():
            self.Reg.compute_dw(self.dg)
        # line search for primal variable
        self.alpha = self.parameters["alpha0"]
        rho = self.parameters["rho"]
        c = self.parameters["c"]
        self.computecost()
        costref = self.cost
        cdJdf = ((self.MG).inner(self.dg.vector())) * c
        self.LS = False
        for ii in xrange(self.parameters["max_backtrack"]):
            setfct(self.gtmp, self.g.vector() + self.dg.vector() * self.alpha)
            if self.computecost(self.gtmp) < costref + self.alpha * cdJdf:
                self.g.vector().axpy(self.alpha, self.dg.vector())
                self.LS = True
                break
            else:
                self.alpha *= rho
        # update dual variable
        if regularization == "TV" and self.Reg.isPD():
            self.Reg.update_w(self.alpha)

    def solve(self, plot=False):
        """ Solve image denoising pb """
        regularization = self.parameters["regularization"]
        print "\t{:12s} {:12s} {:12s} {:12s} {:12s} {:12s} {:12s}\t{:12s} {:12s}".format(
            "a_reg", "cost", "misfit", "reg", "||G||", "a_LS", "medmisfit", "tol_cg", "n_cg"
        )
        #
        if regularization == "tikhonov":
            # pb is linear with tikhonov regularization
            self.searchdirection()
            self.g.vector().axpy(1.0, self.dg.vector())
            self.computecost()
            self.alpha = 1.0
            self.printout()
        else:
            self.computecost()
            cost = self.cost
            # initial printout
            df = self.f_true.vector() - self.g.vector()
            self.medmisfit = np.sqrt(df.inner(df))
            # self.medmisfit = np.sqrt((self.M*df).inner(df))
            self.relmedmisfit = self.medmisfit / self.targetnorm
            print ("{:12.1e} {:12.4e} {:12.4e} {:12.4e} {:12s} {:12s} {:12.2e}" + " ({:.3f})").format(
                self.regparam, self.cost, self.misfit, self.reg, "", "", self.medmisfit ** 2, self.relmedmisfit
            )
            # iterate
            for ii in xrange(1000):
                self.searchdirection()
                self.linesearch()
                print ii + 1,
                self.printout()
                # Check termination conditions:
                if not self.LS:
                    print "Line search failed"
                    break
                if self.Gradnorm < min(1e-12, 1e-10 * self.Gradnorm0):
                    print "gradient sufficiently reduced -- optimization converged"
                    break
                elif np.abs(cost - self.cost) / cost < 1e-12:
                    print "cost functional stagnates -- optimization converged"
                    break
                cost = self.cost

    ### OUTPUT
    def printout(self):
        """ Print results """
        df = self.f_true.vector() - self.g.vector()
        self.medmisfit = np.sqrt((self.M * df).inner(df))
        self.relmedmisfit = self.medmisfit / self.targetnorm
        print ("{:12.1e} {:12.4e} {:12.4e} {:12.4e} {:12.4e} {:12.2e} {:12.2e}" + " ({:.3f}) {:12.2e} {:6d}").format(
            self.regparam,
            self.cost,
            self.misfit,
            self.reg,
            self.Gradnorm,
            self.alpha,
            self.medmisfit ** 2,
            self.relmedmisfit,
            self.cgtol,
            self.cgiter,
        )

    def plot(self, index=0, add=""):
        """ Plot target (w/ noise 0, or w/o noise 1) or current iterate (2) """
        if index == 0:
            self.myplot.set_varname("target" + add)
            self.myplot.plot_vtk(self.f_true)
        elif index == 1:
            self.myplot.set_varname("data" + add)
            self.myplot.plot_vtk(self.dn)
        elif index == 2:
            self.myplot.set_varname("solution" + add)
            self.myplot.plot_vtk(self.g)

    ### TESTS
    def test_gradient(self, f=None, n=5):
        """ test gradient with FD approx around point f """
        if f == None:
            f = self.f_true
        pm = [1.0, -1.0]
        eps = 1e-5
        self.gradient(f)
        for nn in xrange(1, n + 1):
            expr = dl.Expression("sin(n*pi*x[0]/200)*sin(n*pi*x[1]/100)", n=nn)
            df = dl.interpolate(expr, self.V)
            MGdf = self.MG.inner(df.vector())
            cost = []
            for sign in pm:
                setfct(self.g, f)
                self.g.vector().axpy(sign * eps, df.vector())
                cost.append(self.computecost(self.g))
            MGFD = (cost[0] - cost[1]) / (2 * eps)
            print "n={}:\tMGFD={:.5e}, MGdf={:.5e}, error={:.2e}".format(
                nn, MGFD, MGdf, np.abs(MGdf - MGFD) / np.abs(MGdf)
            )

    def test_hessian(self, f=None, n=5):
        """ test Hessian with FD approx around point f """
        if f == None:
            f = self.f_true
        pm = [1.0, -1.0]
        eps = 1e-5
        self.Hessian(f)
        for nn in xrange(1, n + 1):
            expr = dl.Expression("sin(n*pi*x[0]/200)*sin(n*pi*x[1]/100)", n=nn)
            df = dl.interpolate(expr, self.V)
            Hdf = (self.Hess * df.vector()).array()
            MG = []
            for sign in pm:
                setfct(self.g, f)
                self.g.vector().axpy(sign * eps, df.vector())
                self.gradient(self.g)
                MG.append(self.MG.array())
            HFD = (MG[0] - MG[1]) / (2 * eps)
            print "n={}:\tHFD={:.5e}, Hdf={:.5e}, error={:.2e}".format(
                nn, np.linalg.norm(HFD), np.linalg.norm(Hdf), np.linalg.norm(Hdf - HFD) / np.linalg.norm(Hdf)
            )