Example #1
0
def boundary_to_mesh(f, mesh):
    """ Take a CG1 function f defined on a surface mesh and return a
    volume vector with same values on boundary but zero in volume
    """
    b_mesh = f.function_space().mesh()
    SpaceV = backend.FunctionSpace(mesh, "CG", 1)
    SpaceB = backend.FunctionSpace(b_mesh, "CG", 1)

    F = backend.Function(SpaceV)
    GValues = numpy.zeros(F.vector().size())

    map = b_mesh.entity_map(0)  # Vertex map from boundary mesh to parent mesh
    d2v = backend.dof_to_vertex_map(SpaceB)
    v2d = backend.vertex_to_dof_map(SpaceV)

    dof = SpaceV.dofmap()
    imin, imax = dof.ownership_range()

    for i in range(f.vector().local_size()):
        GVertID = backend.Vertex(
            b_mesh,
            d2v[i]).index()  # Local Vertex ID for given dof on boundary mesh
        PVertID = map[GVertID]  # Local Vertex ID of parent mesh
        PDof = v2d[PVertID]  # Dof on parent mesh
        value = f.vector()[i]  # Value on local processor
        GValues[dof.local_to_global_index(PDof)] = value
    GValues = SyncSum(GValues)

    F.vector().set_local(GValues[imin:imax])
    F.vector().apply("")
    return F
def mesh_to_boundary(v, b_mesh):
    """
    Returns a the boundary representation of the CG-1 function v
    """
    # Extract the underlying volume and boundary meshes
    mesh = v.function_space().mesh()

    # We use a Dof->Vertex mapping to create a global
    # array with all DOF values ordered by mesh vertices
    DofToVert = backend.dof_to_vertex_map(v.function_space())
    VGlobal = numpy.zeros(v.vector().size())

    vec = v.vector().get_local()
    for i in range(len(vec)):
        Vert = backend.MeshEntity(mesh, 0, DofToVert[i])
        globalIndex = Vert.global_index()
        VGlobal[globalIndex] = vec[i]
    VGlobal = SyncSum(VGlobal)

    # Use the inverse mapping to se the DOF values of a boundary
    # function
    surface_space = backend.FunctionSpace(b_mesh, "CG", 1)
    surface_function = backend.Function(surface_space)
    mapa = b_mesh.entity_map(0)
    DofToVert = backend.dof_to_vertex_map(backend.FunctionSpace(b_mesh, "CG", 1))

    LocValues = surface_function.vector().get_local()
    for i in range(len(LocValues)):
        VolVert = backend.MeshEntity(mesh, 0, mapa[int(DofToVert[i])])
        GlobalIndex = VolVert.global_index()
        LocValues[i] = VGlobal[GlobalIndex]

    surface_function.vector().set_local(LocValues)
    surface_function.vector().apply('')
    return surface_function
Example #3
0
    def equation_partial_derivative(self, adjointer, adjoint, i, variable):
        form = adjresidual.get_residual(i)

        if form is None:
            return None
        else:
            form = -form

        fn_space = ufl.algorithms.extract_arguments(form)[0].function_space()
        dparam = backend.Function(
            backend.FunctionSpace(fn_space.mesh(), "R", 0))
        dparam.vector()[:] = 1.0

        dJdv = numpy.zeros(len(self.v))
        for (i, a) in enumerate(self.v):
            diff_form = ufl.algorithms.expand_derivatives(
                backend.derivative(form, a, dparam))

            dFdm = backend.assemble(diff_form)  # actually - dF/dm
            assert isinstance(dFdm, backend.GenericVector)

            out = dFdm.inner(adjoint.vector())
            dJdv[i] = out

        return dJdv
Example #4
0
    def functional_partial_second_derivative(self, adjointer, J, timestep,
                                             m_dot):
        form = J.get_form(adjointer, timestep)

        if form is None:
            return None

        for coeff in ufl.algorithms.extract_coefficients(form):
            try:
                mesh = coeff.function_space().mesh()
                fn_space = backend.FunctionSpace(mesh, "R", 0)
                break
            except:
                pass

        dparam = backend.Function(fn_space)
        dparam.vector()[:] = 1.0 * float(self.coeff)

        d = backend.derivative(form, get_constant(self.a), dparam)
        d = ufl.algorithms.expand_derivatives(d)

        d2param = backend.Function(fn_space)
        d2param.vector()[:] = 1.0 * float(self.coeff) * m_dot

        d = backend.derivative(d, get_constant(self.a), d2param)
        d = ufl.algorithms.expand_derivatives(d)

        if len(d.integrals()) != 0:
            return backend.assemble(d)
        else:
            return None
Example #5
0
    def functional_partial_derivative(self, adjointer, J, timestep):
        form = J.get_form(adjointer, timestep)

        if form is None:
            return None

        # OK. Now that we have the form for the functional at this timestep, let's differentiate it with respect to
        # my dear Constant, and be done.
        for coeff in ufl.algorithms.extract_coefficients(form):
            try:
                mesh = coeff.function_space().mesh()
                fn_space = backend.FunctionSpace(mesh, "R", 0)
                break
            except:
                pass

        dparam = backend.Function(fn_space)
        dparam.vector()[:] = 1.0 * float(self.coeff)

        d = backend.derivative(form, get_constant(self.a), dparam)
        d = ufl.algorithms.expand_derivatives(d)

        # Add the derivatives of Expressions wrt to the Constant
        d = self.expression_derivative(form, d)

        if len(d.integrals()) != 0:
            return backend.assemble(d)
        else:
            return None
Example #6
0
    def equation_partial_second_derivative(self, adjointer, adjoint, i,
                                           variable, m_dot):
        form = adjresidual.get_residual(i)
        if form is not None:
            form = -form

            mesh = ufl.algorithms.extract_arguments(
                form)[0].function_space().mesh()
            fn_space = backend.FunctionSpace(mesh, "R", 0)
            dparam = backend.Function(fn_space)
            dparam.vector()[:] = 1.0 * float(self.coeff)
            d2param = backend.Function(fn_space)
            d2param.vector()[:] = 1.0 * float(self.coeff) * m_dot

            diff_form = ufl.algorithms.expand_derivatives(
                backend.derivative(form, get_constant(self.a), dparam))
            if diff_form is None:
                return None

            diff_form = ufl.algorithms.expand_derivatives(
                backend.derivative(diff_form, get_constant(self.a), d2param))
            if diff_form is None:
                return None

            # Let's see if the form actually depends on the parameter m
            if len(diff_form.integrals()) != 0:
                dFdm = backend.assemble(diff_form)  # actually - dF/dm
                assert isinstance(dFdm, backend.GenericVector)

                out = dFdm.inner(adjoint.vector())
                return out
            else:
                return None  # dF/dm is zero, return None
Example #7
0
    def equation_partial_derivative(self, adjointer, adjoint, i, variable):
        form = adjresidual.get_residual(i)
        if form is not None:
            form = -form

            mesh = ufl.algorithms.extract_arguments(
                form)[0].function_space().mesh()
            fn_space = backend.FunctionSpace(mesh, "R", 0)
            dparam = backend.Function(fn_space)
            dparam.vector()[:] = 1.0 * float(self.coeff)

            diff_form = ufl.algorithms.expand_derivatives(
                backend.derivative(form, get_constant(self.a), dparam))

            # Add the derivatives of Expressions wrt to the Constant
            diff_form = self.expression_derivative(form, diff_form)

            # Let's see if the form actually depends on the parameter m
            if len(diff_form.integrals()) != 0:
                dFdm = backend.assemble(diff_form)  # actually - dF/dm
                out = adjoint.vector().inner(dFdm)
            else:
                out = None  # dF/dm is zero, return None

            return out
Example #8
0
    def __call__(self, adjointer, i, dependencies, values, variable):
        form = adjresidual.get_residual(i)
        if form is not None:
            form = -form

            fn_space = ufl.algorithms.extract_arguments(
                form)[0].function_space()
            dparam = backend.Function(
                backend.FunctionSpace(fn_space.mesh(), "R", 0))
            dparam.vector()[:] = 1.0 * float(self.coeff)

            diff_form = ufl.algorithms.expand_derivatives(
                backend.derivative(form, get_constant(self.a), dparam))

            return adjlinalg.Vector(diff_form)
        else:
            return None
Example #9
0
    def __call__(self, adjointer, i, dependencies, values, variable):
        diff_form = None
        assert self.dv is not None, "Need a perturbation direction to use in the TLM."

        form = adjresidual.get_residual(i)

        if form is None:
            return None
        else:
            form = -form

        fn_space = ufl.algorithms.extract_arguments(form)[0].function_space()
        dparam = backend.Function(
            backend.FunctionSpace(fn_space.mesh(), "R", 0))
        dparam.vector()[:] = 1.0

        for (a, da) in zip(self.v, self.dv):
            out_form = da * backend.derivative(form, a, dparam)
            if diff_form is None:
                diff_form = out_form
            else:
                diff_form += out_form

        return adjlinalg.Vector(diff_form)
Example #10
0
 def _ad_function_space(self, mesh):
     element = self.ufl_element()
     fs_element = element.reconstruct(cell=mesh.ufl_cell())
     return backend.FunctionSpace(mesh, fs_element)
Example #11
0
 def _ad_function_space(self, mesh):
     if mesh not in self._cached_fs:
         element = self.ufl_element()
         fs_element = element.reconstruct(cell=mesh.ufl_cell())
         self._cached_fs[mesh] = backend.FunctionSpace(mesh, fs_element)
     return self._cached_fs[mesh]
Example #12
0
 def _ad_function_space(self):
     if self._ad_coordinate_space is None:
         self._ad_coordinate_space = backend.FunctionSpace(self, self.ufl_coordinate_element())
     return self._ad_coordinate_space
Example #13
0
    def evaluate_hessian_component(self,
                                   inputs,
                                   hessian_inputs,
                                   adj_inputs,
                                   block_variable,
                                   idx,
                                   relevant_dependencies,
                                   prepared=None):
        c = block_variable.output
        if c == self.func and not self.linear:
            return None

        adj_sol2 = prepared["adj_sol2"]
        adj_sol2_bdy = prepared["adj_sol2_bdy"]
        F_form = prepared["form"]
        adj_sol = prepared["adj_sol"]
        fwd_block_variable = self.get_outputs()[0]
        tlm_output = fwd_block_variable.tlm_value

        c_rep = block_variable.saved_output

        # If m = DirichletBC then d^2F(u,m)/dm^2 = 0 and d^2F(u,m)/dudm = 0,
        # so we only have the term dF(u,m)/dm * adj_sol2
        if isinstance(c, backend.DirichletBC):
            tmp_bc = compat.create_bc(c,
                                      value=extract_subfunction(
                                          adj_sol2_bdy, c.function_space()))
            return [tmp_bc]

        if isinstance(c_rep, backend.Constant):
            mesh = compat.extract_mesh_from_form(F_form)
            W = c._ad_function_space(mesh)
        elif isinstance(c, compat.ExpressionType):
            mesh = F_form.ufl_domain().ufl_cargo()
            W = c._ad_function_space(mesh)
        elif isinstance(c, compat.MeshType):
            X = backend.SpatialCoordinate(c)
            element = X.ufl_domain().ufl_coordinate_element()
            W = backend.FunctionSpace(c, element)
        else:
            W = c.function_space()

        dc = backend.TestFunction(W)
        form_adj = backend.action(F_form, adj_sol)
        form_adj2 = backend.action(F_form, adj_sol2)
        if isinstance(c, compat.MeshType):
            dFdm_adj = backend.derivative(form_adj, X, dc)
            dFdm_adj2 = backend.derivative(form_adj2, X, dc)
        else:
            dFdm_adj = backend.derivative(form_adj, c_rep, dc)
            dFdm_adj2 = backend.derivative(form_adj2, c_rep, dc)

        # TODO: Old comment claims this might break on split. Confirm if true or not.
        d2Fdudm = ufl.algorithms.expand_derivatives(
            backend.derivative(dFdm_adj, fwd_block_variable.saved_output,
                               tlm_output))

        hessian_output = 0

        # We need to add terms from every other dependency
        # i.e. the terms d^2F/dm_1dm_2
        for _, bv in relevant_dependencies:
            c2 = bv.output
            c2_rep = bv.saved_output

            if isinstance(c2, backend.DirichletBC):
                continue

            tlm_input = bv.tlm_value
            if tlm_input is None:
                continue

            if c2 == self.func and not self.linear:
                continue

            # TODO: If tlm_input is a Sum, this crashes in some instances?
            if isinstance(c2_rep, compat.MeshType):
                X = backend.SpatialCoordinate(c2_rep)
                d2Fdm2 = ufl.algorithms.expand_derivatives(
                    backend.derivative(dFdm_adj, X, tlm_input))
            else:
                d2Fdm2 = ufl.algorithms.expand_derivatives(
                    backend.derivative(dFdm_adj, c2_rep, tlm_input))
            if d2Fdm2.empty():
                continue

            hessian_output -= compat.assemble_adjoint_value(d2Fdm2)

        if not d2Fdudm.empty():
            # FIXME: This can be empty in the multimesh case, ask sebastian
            hessian_output -= compat.assemble_adjoint_value(d2Fdudm)
        hessian_output -= compat.assemble_adjoint_value(dFdm_adj2)

        if isinstance(c, compat.ExpressionType):
            return [(hessian_output, W)]
        else:
            return hessian_output