def solver(self,
               opt,
               ic,
               start,
               end,
               Tn,
               algorithm='scipy_lbfgs',
               options=None):
        h = self.mesh.hmax()

        def J(x):
            loc_opt, loc_ic = self.get_opt(x, opt, ic, 1)

            U = self.PDE_solver(loc_ic, loc_opt, start, end, Tn)
            return self.J(loc_opt, loc_ic, U, start, end)

        def grad_J(x):

            loc_opt, loc_ic = self.get_opt(x, opt, ic, 1)

            P = self.adjoint_solver(loc_ic, loc_opt, start, end, Tn)

            return self.grad_J(P, loc_opt, loc_ic, h)

        control0 = self.get_control(opt, ic, 1)
        if algorithm == 'my_lbfgs':
            control0 = SimpleVector(control0)

            self.update_lbfgs_options(options)
            solver = Lbfgs(J, grad_J, control0, options=self.Lbfgs_options)

            res = solver.solve()
        elif algorithm == 'scipy_lbfgs':
            res = Mini(J,
                       control0.copy(),
                       method='L-BFGS-B',
                       jac=grad_J,
                       options={
                           'gtol': 1e-5,
                           'disp': True
                       })

        elif algorithm == 'my_steepest_decent':

            self.update_SD_options(options)
            SDopt = self.SD_options

            Solver = SteepestDecent(J, grad_J, control0.copy(), options=SDopt)
            res = Solver.solve()
        return res
    def penalty_solver(self,opt,ic,start,end,Tn,m,mu_list,
                       algorithm='scipy_lbfgs',options=None):

        h = self.h
        X = Function(self.V)
        xN = self.xN
        control0 = self.get_control(opt,ic,m)
        if algorithm=='my_lbfgs':
            control0 = SimpleVector(control0)
        
        res =[]
        for k in range(len(mu_list)):
            
            J,grad_J = self.create_reduced_penalty_j(opt,ic,start,end,Tn,m,mu_list[k])

            
            if algorithm == 'my_steepest_decent':

                self.update_SD_options(options)
                SDopt = self.SD_options

                Solver = SteepestDecent(J,grad_J,control0.copy(),
                                        options=SDopt)
                res1 = Solver.solve()
                control0 = res1.x.copy()
            else:
                self.update_lbfgs_options(options)                

                if algorithm=='my_lbfgs':
                    solver = Lbfgs(J,grad_J,control0,options=self.Lbfgs_options)

                    res1 = solver.solve()
                    control0 = res1['control'].copy()
                elif algorithm=='scipy_lbfgs':
                    res1 = Mini(J,control0.copy(),method='L-BFGS-B',jac=grad_J,
                                options={'gtol':1e-6, 'disp':True,'maxcor':10})
                    control0 = res1.x.copy()


            res.append(res1)
        if len(res)==1:
            
            return res[0]
        
        return res
    def solver(self,opt,ic,start,end,Tn,algorithm='scipy_lbfgs',
               options=None):
        h = self.mesh.hmax()
        
        def J(x):
            loc_opt,loc_ic = self.get_opt(x,opt,ic,1)
            
            U = self.PDE_solver(loc_ic,loc_opt,start,end,Tn)
            return self.J(loc_opt,loc_ic,U,start,end)
        
        def grad_J(x):

            loc_opt,loc_ic = self.get_opt(x,opt,ic,1)
            
            P = self.adjoint_solver(loc_ic,loc_opt,start,end,Tn)

            return self.grad_J(P,loc_opt,loc_ic,h)


        control0 = self.get_control(opt,ic,1)
        if algorithm=='my_lbfgs':
            control0 = SimpleVector(control0)

            self.update_lbfgs_options(options)
            solver = Lbfgs(J,grad_J,control0,options=self.Lbfgs_options)
        
            res = solver.solve()
        elif algorithm=='scipy_lbfgs':
            res = Mini(J,control0.copy(),method='L-BFGS-B', 
                       jac=grad_J,options={'gtol': 1e-5, 'disp': True})

        elif algorithm=='my_steepest_decent':

            self.update_SD_options(options)
            SDopt = self.SD_options

            Solver = SteepestDecent(J,grad_J,control0.copy(),options=SDopt)
            res = Solver.solve()
        return res
    def PPCLBFGSsolve2(self,
                       N,
                       m,
                       my_list,
                       x0=None,
                       options=None,
                       scale=False):
        dt = float(self.T) / N
        if x0 == None:
            x0 = SimpleVector(x0=self.initial_control(N, m=m))

        result = []
        PPC = self.PC_creator(N, m, step=1)
        if scale:
            scaler = {'m': m, 'factor': 1}
        else:
            scaler = None
        for i in range(len(my_list)):

            J, grad_J = self.generate_reduced_penalty(dt, N, m, my_list[i])

            self.update_Lbfgs_options(options)
            Lbfgsopt = self.Lbfgs_options

            Solver = Lbfgs(J,
                           grad_J,
                           x0,
                           Hinit=None,
                           options=Lbfgsopt,
                           pc=PPC,
                           scale=scaler)
            res = Solver.solve()
            x0 = res['control']
            result.append(res)
        if len(result) == 1:
            return res
        else:
            return result
    def penalty_solver(self,
                       opt,
                       ic,
                       start,
                       end,
                       Tn,
                       m,
                       mu_list,
                       algorithm='scipy_lbfgs',
                       options=None):

        h = self.h
        X = Function(self.V)
        xN = self.xN
        control0 = self.get_control(opt, ic, m)
        if algorithm == 'my_lbfgs':
            control0 = SimpleVector(control0)

        res = []
        for k in range(len(mu_list)):

            J, grad_J = self.create_reduced_penalty_j(opt, ic, start, end, Tn,
                                                      m, mu_list[k])

            if algorithm == 'my_steepest_decent':

                self.update_SD_options(options)
                SDopt = self.SD_options

                Solver = SteepestDecent(J,
                                        grad_J,
                                        control0.copy(),
                                        options=SDopt)
                res1 = Solver.solve()
                control0 = res1.x.copy()
            else:
                self.update_lbfgs_options(options)

                if algorithm == 'my_lbfgs':
                    solver = Lbfgs(J,
                                   grad_J,
                                   control0,
                                   options=self.Lbfgs_options)

                    res1 = solver.solve()
                    control0 = res1['control'].copy()
                elif algorithm == 'scipy_lbfgs':
                    res1 = Mini(J,
                                control0.copy(),
                                method='L-BFGS-B',
                                jac=grad_J,
                                options={
                                    'gtol': 1e-6,
                                    'disp': True,
                                    'maxcor': 10
                                })
                    control0 = res1.x.copy()

            res.append(res1)
        if len(res) == 1:

            return res[0]

        return res