コード例 #1
0
    def __get_bounds(self):
        """Convert bounds to PETSc vectors - TAO's accepted format"""
        bounds = self.problem.bounds
        controls = self.problem.reduced_functional.controls

        lbvecs = []
        ubvecs = []

        for (bound, control) in zip(bounds, controls):

            len_control = self.__control_as_vec(control).size
            (lb,ub) = bound # could be float, int, Constant, or Function

            if isinstance(lb, Function):
                lbvec = as_backend_type(lb.vector()).vec()
            elif isinstance(lb, (float, int, Constant)):
                lbvec = self.initial_vec.duplicate()
                lbvec.set(float(lb))
            else:
                raise TypeError("Unknown lower bound type %s" % lb.__class__)
            lbvecs.append(lbvec)

            if isinstance(ub, Function):
                ubvec = as_backend_type(ub.vector()).vec()
            elif isinstance(ub, (float, int, Constant)):
                ubvec = self.initial_vec.duplicate()
                ubvec.set(float(ub))
            else:
                raise TypeError("Unknown upper bound type %s" % ub.__class__)
            ubvecs.append(ubvec)

        lbvec = self.__petsc_vec_concatenate(lbvecs)
        ubvec = self.__petsc_vec_concatenate(ubvecs)
        return (lbvec, ubvec)
コード例 #2
0
 def __control_as_vec(self, control):
     """Return a PETSc Vec representing the supplied Control"""
     if isinstance(control, FunctionControl):
         as_vec = as_backend_type(control.data().copy(deepcopy=True).vector()).vec()
     elif isinstance(control, ConstantControl):
         as_vec = self.__constant_as_vec(Constant(control.data()))
     else:
         raise TypeError("Unknown control type %s" % control.__class__)
     return as_vec
コード例 #3
0
            def update(self, x):
                ''' Split input vector and update all control values '''
                x.copy(ctrl_vec) # Refresh concatenated control vector first

                nvec = 0
                for i in range(0,len(rf.controls)):
                    control = rf.controls[i]

                    if isinstance(control, FunctionControl):
                        data_vec = as_backend_type(control.data().vector()).vec()

                        # Map appropriate range of input vector to control
                        ostarti, oendi = data_vec.owner_range
                        rstarti = ostarti + nvec
                        rendi = rstarti + data_vec.local_size
                        data_vec.setValues(range(ostarti, oendi), x[rstarti:rendi])
                        data_vec.assemble()
                        nvec += data_vec.size

                    elif isinstance(control, ConstantControl):
                        # Scalar case
                        if control.data().shape() == ():
                            vsize = 1
                            val = float(x[nvec])

                        # Vector case
                        elif len(control.data().shape()) == 1:
                            vsize = control.data().shape()[0]
                            val = x[nvec:nvec+vsize]

                        # Matrix case
                        else:
                            vsizex, vsizey = control.data().shape()
                            vsize = vsizex*vsizey
                            as_array = x[nvec:nvec+vsize]

                            # Sort into matrix restoring rows and columns
                            val = []
                            for row in range(0,vsizex):
                                val_inner = []

                                for column in range(0,vsizey):
                                    val_inner.append(as_array[row*vsizey + column])

                                val.append(val_inner)

                        # Replace control in rf
                        cons = Constant(val)
                        rf.controls[i].update(Constant(cons))
                        nvec += vsize
コード例 #4
0
            def objective_and_gradient(self, tao, x, G):
                ''' Evaluates the functional and gradient for the parameter choice x. '''
                j = self.objective(x)
                # TODO: Concatenated gradient vector
                gradient = rf.derivative(forget=False)[0]

                if isinstance(gradient, backend.Constant):
                    G.set(float(gradient))
                else:
                    gradient_vec = as_backend_type(gradient.vector()).vec()
                    G.set(0)
                    G.axpy(1, gradient_vec)

                return j
コード例 #5
0
            def objective_and_gradient(self, tao, x, G):
                ''' Evaluates the functional and gradient for the parameter choice x. '''
                j = self.objective(x)
                # TODO: Concatenated gradient vector
                gradient = rf.derivative(forget=False)[0]

                if isinstance(gradient, backend.Constant):
                    G.set(float(gradient))
                else:
                    gradient_vec = as_backend_type(gradient.vector()).vec()
                    G.set(0)
                    G.axpy(1, gradient_vec)

                return j
コード例 #6
0
            def mult(self, mat, x, y):
                # TODO: Add multiple control support to Hessian stack and check for ConstantControl
                x_wrap = compatibility.petsc_vec_as_function(
                    rf.controls[0].data().function_space(), x)
                hes = rf.hessian(x_wrap)
                hes_vec = as_backend_type(hes.vector()).vec()

                y.set(0.0)
                if self.shift_ != 0.0:
                    if self.riesz_map is not None:
                        self.riesz_map.mult(x, y)
                    else:
                        y.axpy(1.0, x) # use the identity matrix
                    y.scale(self.shift_)

                y.axpy(1, hes_vec)
コード例 #7
0
            def mult(self, mat, x, y):
                # TODO: Add multiple control support to Hessian stack and check for ConstantControl
                x_wrap = compatibility.petsc_vec_as_function(
                    rf.controls[0].data().function_space(), x)
                hes = rf.hessian(x_wrap)
                hes_vec = as_backend_type(hes.vector()).vec()

                y.set(0.0)
                if self.shift_ != 0.0:
                    if self.riesz_map is not None:
                        self.riesz_map.mult(x, y)
                    else:
                        y.axpy(1.0, x) # use the identity matrix
                    y.scale(self.shift_)

                y.axpy(1, hes_vec)
コード例 #8
0
    def __init__(self, problem, parameters=None, riesz_map=None, prefix=""):

        try:
            from petsc4py import PETSc
        except:
            raise Exception, "Could not find petsc4py. Please install it."
        try:
            TAO = PETSc.TAO
        except:
            raise Exception, "Your petsc4py version does not support TAO. Please upgrade to petsc4py >= 3.5."

        self.PETSc = PETSc

        # Use PETSc forms
        if riesz_map is not None:

            # Handle the case where the user supplied riesz_maps.L2(V)
            if hasattr(riesz_map, "assemble"):
                riesz_map = riesz_map.assemble()

            self.riesz_map = as_backend_type(riesz_map).mat()
        else:
            self.riesz_map = None

        if len(prefix) > 0 and prefix[-1] != "_":
            prefix += "_"

        self.prefix = prefix

        OptimizationSolver.__init__(self, problem, parameters)

        self.tao = PETSc.TAO().create(PETSc.COMM_WORLD)

        self.__build_app_context()
        self.__set_parameters()
        self.__build_tao()