def compute_integrand_scaling_factor(integral): """Change integrand geometry to the right representations.""" domain = integral.ufl_domain() integral_type = integral.integral_type() # co = CellOrientation(domain) weight = QuadratureWeight(domain) tdim = domain.topological_dimension() # gdim = domain.geometric_dimension() # Polynomial degree of integrand scaling degree = 0 if integral_type == "cell": detJ = JacobianDeterminant(domain) degree = estimate_total_polynomial_degree( apply_geometry_lowering(detJ)) # Despite the abs, |detJ| is polynomial except for # self-intersecting cells, where we have other problems. scale = abs(detJ) * weight elif integral_type.startswith("exterior_facet"): if tdim > 1: # Scaling integral by facet jacobian determinant and # quadrature weight detFJ = FacetJacobianDeterminant(domain) degree = estimate_total_polynomial_degree( apply_geometry_lowering(detFJ)) scale = detFJ * weight else: # No need to scale 'integral' over a vertex scale = 1 elif integral_type.startswith("interior_facet"): if tdim > 1: # Scaling integral by facet jacobian determinant from one # side and quadrature weight detFJ = FacetJacobianDeterminant(domain) degree = estimate_total_polynomial_degree( apply_geometry_lowering(detFJ)) scale = detFJ('+') * weight else: # No need to scale 'integral' over a vertex scale = 1 elif integral_type in custom_integral_types: # Scaling with custom weight, which includes eventual volume # scaling scale = weight elif integral_type in point_integral_types: # No need to scale 'integral' over a point scale = 1 else: error("Unknown integral type {}, don't know how to scale.".format( integral_type)) return scale, degree
def compute_integrand_scaling_factor(integral): """Change integrand geometry to the right representations.""" domain = integral.ufl_domain() integral_type = integral.integral_type() # co = CellOrientation(domain) weight = QuadratureWeight(domain) tdim = domain.topological_dimension() # gdim = domain.geometric_dimension() # Polynomial degree of integrand scaling degree = 0 if integral_type == "cell": detJ = JacobianDeterminant(domain) degree = estimate_total_polynomial_degree(apply_geometry_lowering(detJ)) # Despite the abs, |detJ| is polynomial except for # self-intersecting cells, where we have other problems. scale = abs(detJ) * weight elif integral_type.startswith("exterior_facet"): if tdim > 1: # Scaling integral by facet jacobian determinant and # quadrature weight detFJ = FacetJacobianDeterminant(domain) degree = estimate_total_polynomial_degree(apply_geometry_lowering(detFJ)) scale = detFJ * weight else: # No need to scale 'integral' over a vertex scale = 1 elif integral_type.startswith("interior_facet"): if tdim > 1: # Scaling integral by facet jacobian determinant from one # side and quadrature weight detFJ = FacetJacobianDeterminant(domain) degree = estimate_total_polynomial_degree(apply_geometry_lowering(detFJ)) scale = detFJ('+') * weight else: # No need to scale 'integral' over a vertex scale = 1 elif integral_type in custom_integral_types: # Scaling with custom weight, which includes eventual volume # scaling scale = weight elif integral_type in point_integral_types: # No need to scale 'integral' over a point scale = 1 else: error("Unknown integral type {}, don't know how to scale.".format(integral_type)) return scale, degree
def supply_shape_derivative(self, shape_derivative): """Overrides the shape derivative of the reduced cost functional. This allows users to implement their own shape derivative and use cashocs as a solver library only. Parameters ---------- shape_derivative : ufl.form.Form The shape_derivative of the reduced (!) cost functional w.r.t. controls. Returns ------- None """ try: if not shape_derivative.__module__ == 'ufl.form' and type(shape_derivative).__name__ == 'Form': raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_shape_derivative', 'shape_derivative', 'shape_derivative have to be a ufl form') except: raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_shape_derivative', 'shape_derivative', 'shape_derivative has to be a ufl form') if len(shape_derivative.arguments()) == 2: raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_shape_derivative', 'shape_derivative', 'Do not use TrialFunction for the shape_derivative.') elif len(shape_derivative.arguments()) == 0: raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_shape_derivative', 'shape_derivative', 'The specified shape_derivative must include a TestFunction object.') if not shape_derivative.arguments()[0].ufl_function_space().ufl_element() == self.form_handler.deformation_space.ufl_element(): raise InputError('cashocs._shape_optimization.shape_optimization_problem.ShapeOptimizationProblem.supply_shape_derivative', 'shape_derivative', 'The TestFunction has to be chosen from the same space as the corresponding adjoint.') if not shape_derivative.arguments()[0].ufl_function_space() == self.form_handler.deformation_space: shape_derivative = replace(shape_derivative, {shape_derivative.arguments()[0] : self.form_handler.test_vector_field}) if self.form_handler.degree_estimation: estimated_degree = np.maximum(estimate_total_polynomial_degree(self.form_handler.riesz_scalar_product), estimate_total_polynomial_degree(shape_derivative)) self.form_handler.assembler = fenics.SystemAssembler(self.form_handler.riesz_scalar_product, shape_derivative, self.form_handler.bcs_shape, form_compiler_parameters={'quadrature_degree' : estimated_degree}) else: try: self.form_handler.assembler = fenics.SystemAssembler(self.form_handler.riesz_scalar_product, shape_derivative, self.form_handler.bcs_shape) except (AssertionError, ValueError): estimated_degree = np.maximum(estimate_total_polynomial_degree(self.form_handler.riesz_scalar_product), estimate_total_polynomial_degree(shape_derivative)) self.form_handler.assembler = fenics.SystemAssembler(self.form_handler.riesz_scalar_product, shape_derivative, self.form_handler.bcs_shape, form_compiler_parameters={'quadrature_degree' : estimated_degree}) self.has_custom_derivative = True
def attach_estimated_degrees(form): """Attach estimated polynomial degree to a form's integrals. :arg form: The :class:`~.Form` to inspect. :returns: A new Form with estimate degrees attached. """ integrals = form.integrals() new_integrals = [] for integral in integrals: md = {} md.update(integral.metadata()) degree = estimate_total_polynomial_degree(integral.integrand()) md["estimated_polynomial_degree"] = degree new_integrals.append(integral.reconstruct(metadata=md)) return Form(new_integrals)
def __init__(self, lagrangian, bcs_list, states, adjoints, boundaries, config, ksp_options, adjoint_ksp_options, shape_scalar_product=None, deformation_space=None): """Initializes the ShapeFormHandler object. Parameters ---------- lagrangian : cashocs._forms.Lagrangian The Lagrangian corresponding to the shape optimization problem bcs_list : list[list[dolfin.fem.dirichletbc.DirichletBC]] list of boundary conditions for the state variables states : list[dolfin.function.function.Function] list of state variables adjoints : list[dolfin.function.function.Function] list of adjoint variables boundaries : dolfin.cpp.mesh.MeshFunctionSizet a MeshFunction for the boundary markers config : configparser.ConfigParser the configparser object storing the problems config ksp_options : list[list[list[str]]] The list of command line options for the KSP for the state systems. adjoint_ksp_options : list[list[list[str]]] The list of command line options for the KSP for the adjoint systems. shape_scalar_product : ufl.form.Form The weak form of the scalar product used to determine the shape gradient. """ FormHandler.__init__(self, lagrangian, bcs_list, states, adjoints, config, ksp_options, adjoint_ksp_options) self.boundaries = boundaries self.shape_scalar_product = shape_scalar_product self.degree_estimation = self.config.getboolean('ShapeGradient', 'degree_estimation', fallback=False) self.use_pull_back = self.config.getboolean('ShapeGradient', 'use_pull_back', fallback=True) if deformation_space is None: self.deformation_space = fenics.VectorFunctionSpace( self.mesh, 'CG', 1) else: self.deformation_space = deformation_space self.test_vector_field = fenics.TestFunction(self.deformation_space) self.regularization = Regularization(self) # Calculate the necessary UFL forms self.inhomogeneous_mu = False self.__compute_shape_derivative() self.__compute_shape_gradient_forms() self.__setup_mu_computation() if self.degree_estimation: self.estimated_degree = np.maximum( estimate_total_polynomial_degree(self.riesz_scalar_product), estimate_total_polynomial_degree(self.shape_derivative)) self.assembler = fenics.SystemAssembler(self.riesz_scalar_product, self.shape_derivative, self.bcs_shape, form_compiler_parameters={ 'quadrature_degree': self.estimated_degree }) else: try: self.assembler = fenics.SystemAssembler( self.riesz_scalar_product, self.shape_derivative, self.bcs_shape) except (AssertionError, ValueError): self.estimated_degree = np.maximum( estimate_total_polynomial_degree( self.riesz_scalar_product), estimate_total_polynomial_degree(self.shape_derivative)) self.assembler = fenics.SystemAssembler( self.riesz_scalar_product, self.shape_derivative, self.bcs_shape, form_compiler_parameters={ 'quadrature_degree': self.estimated_degree }) self.assembler.keep_diagonal = True self.fe_scalar_product_matrix = fenics.PETScMatrix() self.fe_shape_derivative_vector = fenics.PETScVector() self.update_scalar_product() # test for symmetry if not self.scalar_product_matrix.isSymmetric(): if not self.scalar_product_matrix.isSymmetric(1e-15): if not (self.scalar_product_matrix - self.scalar_product_matrix.copy().transpose() ).norm() / self.scalar_product_matrix.norm() < 1e-15: raise InputError( 'cashocs._forms.ShapeFormHandler', 'shape_scalar_product', 'Supplied scalar product form is not symmetric.') if self.opt_algo == 'newton' \ or (self.opt_algo == 'pdas' and self.inner_pdas == 'newton'): raise NotImplementedError( 'Second order methods are not implemented for shape optimization yet' )