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)
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
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
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
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)
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()