Esempio n. 1
0
def homogenize(bcs):
    b = []
    for bc in bcs:
        b0 = DirichletBC(bc)
        b0.homogenize()
        b.append(b0)
    return b
Esempio n. 2
0
def homogenize(bcs):
    b = []
    for bc in bcs:
        b0 = DirichletBC(bc)
        b0.homogenize()
        b.append(b0)
    return b
    def __init__(self,
                 J,
                 U,
                 u,
                 m,
                 bcs,
                 dx_m=None,
                 dims_m=None,
                 use_nonlinear_solver=False):
        '''
        Parameters
        ----------
        J : ufl.Form
            Objective functional to maximize, e.g. linear-elastic strain energy.
        U : ufl.Form
            Linear-elastic strain energy.
        u : dolfin.Function
            Displacement field.
        m : dolfin.Function
            Vector-valued "body force" like traction field.
        bcs : (list of) dolfin.DirichletBC('s)
            Dirichlet boundary conditions.
        dx_m : dolfin.Measure or None (optional)
            "Body force" integration measure. Can be of cell type or exterior
            facet type; the default is cell type. Note, the integration measure
            can be defined on a subdomain (not necessarily on the whole domain).
        kappa : float or None (optional)
            Diffusion-like constant for smoothing the solution (`m`) increment.

        Notes
        -----
        If the "body force" integration measure `dx_m` concerns cells (as
        opposed to exterior facets), the gradient smoothing constant `kappa`
        can be `None`. Usually, `kappa` will need to be some small positive
        value if `dx_m` concerns exterior facets.

        '''

        if not isinstance(J, ufl_form_t):
            raise TypeError('Parameter `J`')

        if not isinstance(U, ufl_form_t):
            raise TypeError('Parameter `U`')

        if not isinstance(u, Function):
            raise TypeError('Parameter `u`')

        if not isinstance(m, Function):
            raise TypeError('Parameter `m`')

        if len(u) != len(m):
            raise ValueError(
                'Functions `u` and `m` must live in the same dimension space')

        if bcs is None:
            bcs = ()
        elif not isinstance(bcs, (list, tuple)):
            bcs = (bcs, )
        if not all(isinstance(bc, DirichletBC) for bc in bcs):
            raise TypeError('Parameter `bcs` must contain '
                            'homogenized `DirichletBC`(\'s)')

        if dims_m is not None:
            if not isinstance(bcs, (list, tuple, range)):
                dims_m = (dims_m, )
            if not all(isinstance(dim_i, int) for dim_i in dims_m):
                raise TypeError('Parameter `dims_m`')
            if not all(0 <= dim_i < len(m) for dim_i in dims_m):
                raise ValueError('Parameter `dims_m`')

        if dx_m is None:
            dx_m = dx
        elif not isinstance(dx_m, dolfin.Measure):
            raise TypeError('Parameter `dx_m`')

        bcs_zro = []
        for bc in bcs:
            bc_zro = DirichletBC(bc)
            bc_zro.homogenize()
            bcs_zro.append(bc_zro)

        V_u = u.function_space()
        V_m = m.function_space()

        v0_u = dolfin.TestFunction(V_u)
        v0_m = dolfin.TestFunction(V_m)

        v1_u = dolfin.TrialFunction(V_u)
        v1_m = dolfin.TrialFunction(V_m)

        self._u = u
        self._m = m
        self._z = z = Function(V_u)  # Adjoint solution

        self._J = J
        dJ_u = derivative(J, u, v0_u)
        self._dJ_m = derivative(J, m, v0_m)

        dU_u = derivative(U, u, v0_u)  # Internal force
        d2U_uu = a = derivative(dU_u, u, v1_u)  # Stiffness

        if dims_m is None: dW_u = L = dot(v0_u, m) * dx_m
        else: dW_u = L = sum(v0_u[i] * m[i] for i in dims_m) * dx_m

        self._ufl_norm_m = dolfin.sqrt(m**2) * dx_m  # equiv. L1-norm
        self._assembled_adj_dW_um = assemble(dot(v0_m, v1_u) * dx_m)
        self._dimdofs_V_m = tuple(
            np.array(V_m_sub_i.dofmap().dofs()) for V_m_sub_i in V_m.split())

        if use_nonlinear_solver:

            self._equilibrium_solver = dolfin.NonlinearVariationalSolver(
                dolfin.NonlinearVariationalProblem(dU_u - dW_u, u, bcs,
                                                   d2U_uu))

            self._adjoint_solver = dolfin.LinearVariationalSolver(
                dolfin.LinearVariationalProblem(d2U_uu, dJ_u, z, bcs_zro))
            # NOTE: `d2U_uu` is equivalent to `adjoint(d2U_uu)` due to symmetry

            self._equilibrium_solver.parameters["symmetric"] = True
            self._adjoint_solver.parameters["symmetric"] = True

        else:

            self._equilibrium_solver = LinearEquilibriumSolver(a, L, u, bcs)
            self._adjoint_solver = LinearAdjointSolver(None, dJ_u, z, bcs_zro)
            self._adjoint_solver._solver = self._equilibrium_solver.solver
            self._equilibrium_solver.parameters['symmetric'] = True
            # NOTE: `a` is equivalent to `adjoint(a)` due to symmetry; however,
            #       the LU factorization can be reused in the adjoint solver.

        if dx_m.integral_type() == 'cell':
            kappa = None
        else:
            # Compute scale factor for `kappa` based on domain size
            mesh = V_m.mesh()
            xs = mesh.coordinates()
            domain_volume = assemble(1.0 * dx(mesh))
            domain_length = (xs.max(0) - xs.min(0)).max()
            scale_factor = domain_volume / domain_length
            kappa = Constant(scale_factor * SMOOTHING_SOLVER_KAPPA)

        self._smoothing_solver = SmoothingSolver(V_m, kappa)