#        ax.set_title('obs'+str(ii))
        #    fig.savefig(filename + '/observations' + str(iter) + '.eps')
        #    plt.close(fig)
        # stopping criterion (gradient)
        if gradnorm < gradnorm0 * tolgrad or gradnorm < 1e-12:
            print '\nGradient sufficiently reduced -- optimization stopped'
            break
        # search direction
        tolcg = min(0.5, np.sqrt(gradnorm / gradnorm0))
        cgiter, cgres, cgid, tolcg = compute_searchdirection(
            waveobj, 'Newt', tolcg)
        myplot.set_varname('srchdir' + str(iter))
        myplot.plot_vtk(waveobj.srchdir)
        # line search
        cost_old = waveobj.cost
        statusLS, LScount, alpha = bcktrcklinesearch(waveobj, 12)
        cost = waveobj.cost
        print '{:11.3f} {:12.2e} {:10d}'.\
        format(alpha, tolcg, cgiter)
        # stopping criterion (cost)
        if np.abs(cost - cost_old) / np.abs(cost_old) < tolcost:
            print 'Cost function stagnates -- optimization stopped'
            break

    # Compute eigenspectrum
    waveobj.alpha_reg = 0.0  # no regularization
    Omega = np.random.randn(Vm.dim() * 60).reshape((Vm.dim(), 60))
    #TODO: need to left-multiply Omega by R^{-1/2}.M (to be checked)
    d, U = doublePassG(waveobj, regul.precond, regul.getprecond(), Omega, 40)
    np.savetxt(filename + str(Nxy) + '/eigenvalues.txt', d)
#    myplot.set_varname('eigenvectors')
def run_problem():
    # Domain, f-e spaces and boundary conditions:
    mesh = UnitSquareMesh(20,20)
    V = FunctionSpace(mesh, 'Lagrange', 2)  # space for state and adjoint variables
    Vm = FunctionSpace(mesh, 'Lagrange', 1) # space for medium parameter
    Vme = FunctionSpace(mesh, 'Lagrange', 5)    # sp for target med param
    # Define zero Boundary conditions:
    def u0_boundary(x, on_boundary):
        return on_boundary
    u0 = Constant("0.0")
    bc = DirichletBC(V, u0, u0_boundary)
    # Define target medium and rhs:
    mtrue_exp = Expression('1 + 7*(pow(pow(x[0] - 0.5,2) +' + \
    ' pow(x[1] - 0.5,2),0.5) > 0.2)')
    mtrue = interpolate(mtrue_exp, Vme)
    f = Expression("1.0")

    # Compute target data:
    noisepercent = 0.05   # e.g., 0.02 = 2% noise level
    ObsOp = ObsEntireDomain({'V': V,'noise':noisepercent})
    goal = ObjFctalElliptic(V, Vme, bc, bc, [f], ObsOp)
    goal.update_m(mtrue)
    goal.solvefwd()
    UDnoise = goal.U

    # Solve reconstruction problem:
    Regul = LaplacianPrior({'Vm':Vm,'gamma':1e-3,'beta':1e-14})
    ObsOp.noise = False
    InvPb = ObjFctalElliptic(V, Vm, bc, bc, [f], ObsOp, UDnoise, Regul, [], False)
    InvPb.update_m(1.0) # Set initial medium
    InvPb.solvefwd_cost()
    # Choose between steepest descent and Newton's method:
    METHODS = ['sd','Newt']
    meth = METHODS[1]
    if meth == 'sd':    alpha_init = 1e3
    elif meth == 'Newt':    alpha_init = 1.0
    nbcheck = 0 # Grad and Hessian checks
    nbLS = 20   # Max nb of line searches
    # Prepare results outputs:
    PP = PostProcessor(meth, Vm, mtrue)
    PP.getResults0(InvPb)    # Get results for index 0 (before first iteration)
    PP.printResults()
    # Start iteration:
    maxiter = 100 
    for it in range(1, maxiter+1):
        InvPb.solveadj_constructgrad()
        # Check gradient and Hessian:
        if nbcheck and (it == 1 or it % 10 == 0): 
            checkgradfd(InvPb, nbcheck)
            checkhessfd(InvPb, nbcheck)
        # Compute search direction:
        if it == 1: gradnorm_init = InvPb.getGradnorm()
        if meth == 'Newt':
            if it == 1: maxtolcg = .5
            else:   maxtolcg = CGresults[3]
        else:   maxtolcg = None
        CGresults = compute_searchdirection(InvPb, meth, gradnorm_init, maxtolcg)
        # Compute line search:
        LSresults = bcktrcklinesearch(InvPb, nbLS, alpha_init)
        InvPb.plotm(it) # Plot current medium reconstruction
        # Print results:
        PP.getResults(InvPb, LSresults, CGresults)
        PP.printResults()
        if PP.Stop():   break   # Stopping criterion
        alpha_init = PP.alpha_init()    # Initialize next alpha when using sd
    InvPb.gatherm() # Create one plot for all intermediate reconstructions
    if it == maxiter:   print "Max nb of iterations reached."
    print '[a]: iter={}, final norm={}, <dp,MG>={}'.format(\
    solvera.iter, solvera.final_norm,\
    waveobja.srchdir.vector().inner(MGaa.vector()))

    diffa = sola.vector() - waveobja.srchdir.vector()
    diffanorm = diffa.norm('l2')
    srchanorm = waveobja.srchdir.vector().norm('l2')
    if mpirank == 0:
        print '|sola|={:.16e}, |srcha|={:.16e}, reldiff={:.2e}'.format(\
        solanorm, srchanorm, diffanorm/srchanorm)


# Test each search direction
dpMG = waveobjab.srchdir.vector().inner(waveobjab.MGv)
print '[ab]: <dp,MG>={}'.format(dpMG)
_, LScount, alpha = bcktrcklinesearch(waveobjab)
meda, medb = waveobjab.mediummisfit(mt)
print '[ab]: LScount={}, alpha={}'.format(LScount, alpha)
print '[ab]: meda={:.16e}, medb={:.6e}'.format(meda, medb)
waveobjab.solveadj_constructgrad()
gradnorm = np.sqrt(waveobjab.MGv.inner(waveobjab.Grad.vector()))
print '[ab]: |G|={:.16e}'.format(gradnorm)

waveobjab.update_PDE(evaluationpoint)
waveobjab.solvefwd_cost()
waveobjab.solveadj_constructgrad()
waveobjab.srchdir.vector().zero()
dl.assign(waveobjab.srchdir.sub(0), waveobja.srchdir)
dpMG = waveobjab.srchdir.vector().inner(waveobjab.MGv)
print '[a]: <dp,MG>={}'.format(dpMG)
_, LScount, alpha = bcktrcklinesearch(waveobjab)
Beispiel #4
0
    def inversion(self, initial_medium, target_medium, mpicomm, \
    parameters_in=[], myplot=None):
        """ solve inverse problem with that objective function """

        parameters = {'tolgrad':1e-10, 'tolcost':1e-14, 'maxnbNewtiter':50, \
        'maxtolcg':0.5}
        parameters.update(parameters_in)
        maxnbNewtiter = parameters['maxnbNewtiter']
        tolgrad = parameters['tolgrad']
        tolcost = parameters['tolcost']
        tolcg = parameters['maxtolcg']
        mpirank = MPI.rank(mpicomm)

        self.update_m(initial_medium)
        self._plotm(myplot, 'init')

        if mpirank == 0:
            print '\t{:12s} {:10s} {:12s} {:12s} {:12s} {:10s} \t{:10s} {:12s} {:12s}'.format(\
            'iter', 'cost', 'misfit', 'reg', '|G|', 'medmisf', 'a_ls', 'tol_cg', 'n_cg')
        dtruenorm = np.sqrt(target_medium.vector().\
        inner(self.MM*target_medium.vector()))

        self.solvefwd_cost()
        for it in xrange(maxnbNewtiter):
            self.solveadj_constructgrad()  # compute gradient

            if it == 0: gradnorm0 = self.Gradnorm
            diff = self.m.vector() - target_medium.vector()
            medmisfit = np.sqrt(diff.inner(self.MM * diff))
            if mpirank == 0:
                print '{:12d} {:12.4e} {:12.2e} {:12.2e} {:11.4e} {:10.2e} ({:4.2f})'.\
                format(it, self.cost, self.misfit, self.regul, \
                self.Gradnorm, medmisfit, medmisfit/dtruenorm),
            self._plotm(myplot, str(it))
            self._plotgrad(myplot, str(it))

            if self.Gradnorm < gradnorm0 * tolgrad or self.Gradnorm < 1e-12:
                if mpirank == 0:
                    print '\nGradient sufficiently reduced -- optimization stopped'
                break

            # Compute search direction:
            tolcg = min(tolcg, np.sqrt(self.Gradnorm / gradnorm0))
            self.assemble_hessian()  # for regularization
            cgiter, cgres, cgid, tolcg = compute_searchdirection(
                self, 'Newt', tolcg)
            self._plotsrchdir(myplot, str(it))

            # Line search:
            cost_old = self.cost
            statusLS, LScount, alpha = bcktrcklinesearch(self, 12)
            if mpirank == 0:
                print '{:11.3f} {:12.2e} {:10d}'.format(alpha, tolcg, cgiter)
            if self.PD: self.Regul.update_w(self.srchdir.vector(), alpha)

            if np.abs(self.cost - cost_old) / np.abs(cost_old) < tolcost:
                if mpirank == 0:
                    if tolcg < 1e-14:
                        print 'Cost function stagnates -- optimization aborted'
                        break
                    tolcg = 0.001 * tolcg
nbLS = 20   # Max nb of line searches
# Prepare results outputs:
PP = PostProcessor(meth, Vm, mtrue, mycomm)
PP.getResults0(InvPb)    # Get results for index 0 (before first iteration)
PP.printResults(myrank)
# Start iteration:
maxiter = 100 
for it in range(1, maxiter+1):
    InvPb.solveadj_constructgrad()
    # Check gradient and Hessian:
    if nbcheck and (it == 1 or it % 10 == 0): 
        checkgradfd(InvPb, nbcheck)
        checkhessfd(InvPb, nbcheck)
    # Compute search direction:
    if it == 1: gradnorm_init = InvPb.getGradnorm()
    if meth == 'Newt':
        if it == 1: maxtolcg = .5
        else:   maxtolcg = CGresults[3]
    else:   maxtolcg = None
    CGresults = compute_searchdirection(InvPb, meth, gradnorm_init, maxtolcg)
    # Compute line search:
    LSresults = bcktrcklinesearch(InvPb, nbLS, alpha_init)
    InvPb.plotm(it) # Plot current medium reconstruction
    # Print results:
    PP.getResults(InvPb, LSresults, CGresults)
    PP.printResults(myrank)
    if PP.Stop(myrank):   break   # Stopping criterion
    alpha_init = PP.alpha_init()    # Initialize next alpha when using sd
InvPb.gatherm() # Create one plot for all intermediate reconstructions
if it == maxiter:   print "Max nb of iterations reached."