예제 #1
0
    def __compute_state_equations(self):
        """Calculates the weak form of the state equation for the use with fenics.

		Returns
		-------
		None
		"""

        if self.state_is_linear:
            self.state_eq_forms = [
                replace(
                    self.state_forms[i], {
                        self.states[i]: self.trial_functions_state[i],
                        self.adjoints[i]: self.test_functions_state[i]
                    }) for i in range(self.state_dim)
            ]

        else:
            self.state_eq_forms = [
                fenics.derivative(self.state_forms[i], self.adjoints[i],
                                  self.test_functions_state[i])
                for i in range(self.state_dim)
            ]

        if self.state_is_picard:
            self.state_picard_forms = [
                fenics.derivative(self.state_forms[i], self.adjoints[i],
                                  self.test_functions_state[i])
                for i in range(self.state_dim)
            ]

        if self.state_is_linear:
            self.state_eq_forms_lhs = []
            self.state_eq_forms_rhs = []
            for i in range(self.state_dim):
                try:
                    a, L = fenics.system(self.state_eq_forms[i])
                except UFLException:
                    raise CashocsException(
                        'The state system could not be transferred to a linear system.\n'
                        'Perhaps you specified that the system is linear, allthough it is not.\n'
                        'In your config, in the StateEquation section, try using is_linear = False.'
                    )
                self.state_eq_forms_lhs.append(a)
                if L.empty():
                    zero_form = fenics.inner(
                        fenics.Constant(
                            np.zeros(self.test_functions_state[i].ufl_shape)),
                        self.test_functions_state[i]) * self.dx
                    self.state_eq_forms_rhs.append(zero_form)
                else:
                    self.state_eq_forms_rhs.append(L)
예제 #2
0
    def __compute_adjoint_equations(self):
        """Calculates the weak form of the adjoint equation for use with fenics.

		Returns
		-------
		None
		"""

        # Use replace -> derivative to speed up computations
        self.lagrangian_temp_forms = [
            replace(self.lagrangian.lagrangian_form,
                    {self.adjoints[i]: self.trial_functions_adjoint[i]})
            for i in range(self.state_dim)
        ]

        if self.state_is_picard:
            self.adjoint_picard_forms = [
                fenics.derivative(self.lagrangian.lagrangian_form,
                                  self.states[i],
                                  self.test_functions_adjoint[i])
                for i in range(self.state_dim)
            ]

        self.adjoint_eq_forms = [
            fenics.derivative(self.lagrangian_temp_forms[i], self.states[i],
                              self.test_functions_adjoint[i])
            for i in range(self.state_dim)
        ]
        self.adjoint_eq_lhs = []
        self.adjoint_eq_rhs = []

        for i in range(self.state_dim):
            a, L = fenics.system(self.adjoint_eq_forms[i])
            self.adjoint_eq_lhs.append(a)
            if L.empty():
                zero_form = fenics.inner(
                    fenics.Constant(
                        np.zeros(self.test_functions_adjoint[i].ufl_shape)),
                    self.test_functions_adjoint[i]) * self.dx
                self.adjoint_eq_rhs.append(zero_form)
            else:
                self.adjoint_eq_rhs.append(L)

        # Compute the  adjoint boundary conditions
        if self.state_adjoint_equal_spaces:
            self.bcs_list_ad = [[
                fenics.DirichletBC(bc) for bc in self.bcs_list[i]
            ] for i in range(self.state_dim)]
            [[bc.homogenize() for bc in self.bcs_list_ad[i]]
             for i in range(self.state_dim)]
        else:

            def get_subdx(V, idx, ls):
                if V.id() == idx:
                    return ls
                if V.num_sub_spaces() > 1:
                    for i in range(V.num_sub_spaces()):
                        ans = get_subdx(V.sub(i), idx, ls + [i])
                        if ans is not None:
                            return ans
                else:
                    return None

            self.bcs_list_ad = [[1 for bc in range(len(self.bcs_list[i]))]
                                for i in range(self.state_dim)]

            for i in range(self.state_dim):
                for j, bc in enumerate(self.bcs_list[i]):
                    idx = bc.function_space().id()
                    subdx = get_subdx(self.state_spaces[i], idx, ls=[])
                    W = self.adjoint_spaces[i]
                    for num in subdx:
                        W = W.sub(num)
                    shape = W.ufl_element().value_shape()
                    try:
                        if shape == ():
                            self.bcs_list_ad[i][j] = fenics.DirichletBC(
                                W, fenics.Constant(0), bc.domain_args[0],
                                bc.domain_args[1])
                        else:
                            self.bcs_list_ad[i][j] = fenics.DirichletBC(
                                W,
                                fenics.Constant([0] *
                                                W.ufl_element().value_size()),
                                bc.domain_args[0], bc.domain_args[1])
                    except AttributeError:
                        if shape == ():
                            self.bcs_list_ad[i][j] = fenics.DirichletBC(
                                W, fenics.Constant(0), bc.sub_domain)
                        else:
                            self.bcs_list_ad[i][j] = fenics.DirichletBC(
                                W,
                                fenics.Constant([0] *
                                                W.ufl_element().value_size()),
                                bc.sub_domain)
예제 #3
0
	def supply_adjoint_forms(self, adjoint_forms, adjoint_bcs_list):
		"""Overrides the computed weak forms of the adjoint system.
		
		This allows the user to specify their own weak forms of the problems and to use cashocs merely as
		a solver for solving the optimization problems.
		
		Parameters
		----------
		adjoint_forms : ufl.form.Form or list[ufl.form.Form]
			The UFL forms of the adjoint system(s).
		adjoint_bcs_list : list[dolfin.fem.dirichletbc.DirichletBC] or list[list[dolfin.fem.dirichletbc.DirichletBC]] or dolfin.fem.dirichletbc.DirichletBC or None
			The list of Dirichlet boundary conditions for the adjoint system(s).

		Returns
		-------
		None
		"""
		
		try:
			if type(adjoint_forms) == list and len(adjoint_forms) > 0:
				for i in range(len(adjoint_forms)):
					if adjoint_forms[i].__module__=='ufl.form' and type(adjoint_forms[i]).__name__=='Form':
						pass
					else:
						raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms',
										 'adjoint_forms', 'adjoint_forms have to be ufl forms')
				mod_forms = adjoint_forms
			elif adjoint_forms.__module__ == 'ufl.form' and type(adjoint_forms).__name__ == 'Form':
				mod_forms = [adjoint_forms]
			else:
				raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms',
								 'adjoint_forms', 'adjoint_forms have to be ufl forms')
		except:
			raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms',
							 'adjoint_forms', 'adjoint_forms have to be ufl forms')
		
		
		
		try:
			if adjoint_bcs_list == [] or adjoint_bcs_list is None:
				mod_bcs_list = []
				for i in range(self.state_dim):
					mod_bcs_list.append([])
			elif type(adjoint_bcs_list) == list and len(adjoint_bcs_list) > 0:
				if type(adjoint_bcs_list[0]) == list:
					for i in range(len(adjoint_bcs_list)):
						if type(adjoint_bcs_list[i]) == list:
							pass
						else:
							raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms',
											 'adjoint_bcs_list', 'adjoint_bcs_list has inconsistent types.')
					mod_bcs_list = adjoint_bcs_list

				elif adjoint_bcs_list[0].__module__ == 'dolfin.fem.dirichletbc' and type(adjoint_bcs_list[0]).__name__ == 'DirichletBC':
					for i in range(len(adjoint_bcs_list)):
						if adjoint_bcs_list[i].__module__=='dolfin.fem.dirichletbc' and type(adjoint_bcs_list[i]).__name__=='DirichletBC':
							pass
						else:
							raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply adjoint_forms',
											 'adjoint_bcs_list', 'adjoint_bcs_list has inconsistent types.')
					mod_bcs_list = [adjoint_bcs_list]
			elif adjoint_bcs_list.__module__ == 'dolfin.fem.dirichletbc' and type(adjoint_bcs_list).__name__ == 'DirichletBC':
				mod_bcs_list = [[adjoint_bcs_list]]
			else:
				raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms',
								 'adjoint_bcs_list', 'Type of adjoint_bcs_list is wrong.')
		except:
			raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms',
							 'adjoint_bcs_list', 'Type of adjoint_bcs_list is wrong.')
		
		if not len(mod_forms) == self.form_handler.state_dim:
			raise InputError('cashocs.optimization_problem.OptimizationProblem.supply_adjoint_forms', 'adjoint_forms', 'Length of adjoint_forms does not match')
		if not len(mod_bcs_list) == self.form_handler.state_dim:
			raise InputError('cashocs.optimization_problem.OptimizationProblem.supply_adjoint_forms', 'adjoint_bcs_list', 'Length of adjoint_bcs_list does not match')
		
			
		
		for idx, form in enumerate(mod_forms):
			if len(form.arguments()) == 2:
				raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms', 'adjoint_forms',
								 'Do not use TrialFunction for the adjoints, but the actual Function you passed to th OptimalControlProblem.')
			elif len(form.arguments()) == 0:
				raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms', 'adjoint_forms',
								 'The specified adjoint_forms must include a TestFunction object.')
			
			if not form.arguments()[0].ufl_function_space() == self.form_handler.adjoint_spaces[idx]:
				raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_adjoint_forms', 'adjoint_forms',
								 'The TestFunction has to be chosen from the same space as the corresponding adjoint.')
		
		self.form_handler.adjoint_picard_forms = mod_forms
		self.form_handler.bcs_list_ad = mod_bcs_list

		# replace the adjoint function by a TrialFunction for internal use
		repl_forms = [replace(mod_forms[i], {self.adjoints[i] : self.form_handler.trial_functions_adjoint[i]}) for i in range(self.state_dim)]
		self.form_handler.adjoint_eq_forms = repl_forms
		
		self.form_handler.adjoint_eq_lhs = []
		self.form_handler.adjoint_eq_rhs = []

		for i in range(self.state_dim):
			a, L = fenics.system(self.form_handler.adjoint_eq_forms[i])
			self.form_handler.adjoint_eq_lhs.append(a)
			if L.empty():
				zero_form = fenics.inner(fenics.Constant(np.zeros(self.form_handler.test_functions_adjoint[i].ufl_shape)),
										 self.form_handler.test_functions_adjoint[i])*self.form_handler.dx
				self.form_handler.adjoint_eq_rhs.append(zero_form)
			else:
				self.form_handler.adjoint_eq_rhs.append(L)
		
		self.has_custom_adjoint = True