Exemplo n.º 1
0
def Assemble(AA,bb=None):
    backend = AA.str(False)


    if AA.__str__().find('uBLAS') == -1:
        if AA.size(1) == AA.size(0):
            A = as_backend_type(AA).mat()
        else:
            A = as_backend_type(AA).vec()
        if bb:
            b = as_backend_type(bb).vec()
    else:
        if AA.size(1) == AA.size(0):
            As = AA.sparray()
            As.eliminate_zeros()
            row, col, value = As.indptr, As.indices, As.data
            A = PETSc.Mat().createAIJ(size=(AA.size(0),AA.size(1)),csr=(row.astype('int32'), col.astype('int32'), value))
        else:
            A = arrayToVec(AA.array())
        if bb:
            b = arrayToVec(bb.array())
    if bb:
        return A,b
    else:
        return A
Exemplo n.º 2
0
  def M_inv_diag(self, domain = "all"):
    """
    Returns the inverse lumped mass matrix for the vector function space.
    The result ist cached.

    .. note:: This method requires the PETSc Backend to be enabled.

    *Returns*
      :class:`dolfin.Matrix`
        the matrix
    """
    if not self._M_inv_diag.has_key(domain):
      v = TestFunction(self.VectorFunctionSpace())
      u = TrialFunction(self.VectorFunctionSpace())

      mass_form = inner(v, u) * self.dx(domain)
      mass_action_form = action(mass_form, Constant((1.0, 1.0, 1.0)))
      diag = assemble(mass_action_form)
      as_backend_type(diag).vec().reciprocal()

      result = assemble(inner(v, u) * dP)
      result.zero()
      result.set_diagonal(diag)
      self._M_inv_diag[domain] = result

    return self._M_inv_diag[domain]
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
def as_petsc(A):
    '''Extract pointer to the underlying PETSc object'''
    if is_petsc_vec(A):
        return as_backend_type(A).vec()
    if is_petsc_mat(A):
        return as_backend_type(A).mat()

    raise ValueError('%r is not matrix/vector.' % type(A))
Exemplo n.º 5
0
def MatMatMult(A, B):
    """
    Compute the matrix-matrix product :math:`AB`.
    """
    Amat = df.as_backend_type(A).mat()
    Bmat = df.as_backend_type(B).mat()
    out = Amat.matMult(Bmat)
    rmap, _ = Amat.getLGMap()
    _, cmap = Bmat.getLGMap()
    out.setLGMap(rmap, cmap)
    return df.Matrix(df.PETScMatrix(out))
Exemplo n.º 6
0
def MatAtB(A, B):
    """
    Compute the matrix-matrix product :math:`A^T B`.
    """
    Amat = dl.as_backend_type(A).mat()
    Bmat = dl.as_backend_type(B).mat()
    out = Amat.transposeMatMult(Bmat)
    _, rmap = Amat.getLGMap()
    _, cmap = Bmat.getLGMap()
    out.setLGMap(rmap, cmap)
    return dl.Matrix(dl.PETScMatrix(out))
Exemplo n.º 7
0
    def solve_coupled(self):
        """
        Solve the coupled equations
        """
        # Assemble the equation system
        A = self.eqs.assemble_lhs()
        b = self.eqs.assemble_rhs()

        if self.fix_pressure_dof:
            A.ident(self.pressure_row_to_fix)
        elif self.remove_null_space:
            if self.pressure_null_space is None:
                # Create null space vector in Vp Space
                null_func = dolfin.Function(self.simulation.data['Vp'])
                null_vec = null_func.vector()
                null_vec[:] = 1
                null_vec *= 1 / null_vec.norm("l2")

                # Convert null space vector to coupled space
                null_func2 = dolfin.Function(self.simulation.data['Vcoupled'])
                ndim = self.simulation.ndim
                fa = dolfin.FunctionAssigner(self.subspaces[ndim], self.simulation.data['Vp'])
                fa.assign(null_func2.sub(ndim), null_func)

                # Create the null space basis
                self.pressure_null_space = dolfin.VectorSpaceBasis([null_func2.vector()])

            # Make sure the null space is set on the matrix
            dolfin.as_backend_type(A).set_nullspace(self.pressure_null_space)

            # Orthogonalize b with respect to the null space
            self.pressure_null_space.orthogonalize(b)

        # Solve the equation system
        self.simulation.hooks.matrix_ready('Coupled', A, b)
        self.coupled_solver.solve(A, self.coupled_func.vector(), b)

        # Assign into the regular (split) functions from the coupled function
        funcs = [self.simulation.data[name] for name in self.subspace_names]
        self.assigner.assign(funcs, self.coupled_func)

        # If we remove the null space of the matrix system this will not be the exact same as
        # removing the proper null space of the equation, so we fix this here
        if self.fix_pressure_dof:
            p = self.simulation.data['p']
            dx2 = dolfin.dx(domain=p.function_space().mesh())
            vol = dolfin.assemble(dolfin.Constant(1) * dx2)
            # Perform correction multiple times due to round-of error. The first correction
            # can be i.e 1e14 while the next correction is around unity
            pavg = 1e10
            while abs(pavg) > 1000:
                pavg = dolfin.assemble(p * dx2) / vol
                p.vector()[:] -= pavg
Exemplo n.º 8
0
    def setup(self):
        """
        Pre-assemble time independent matrices, group right hand sides and
        solution functions.
        """
        DS = self.data["model"].discretization_scheme()
        w = DS.solution_ctl()
        eqn = self.data["forms"]["lin"]
        pv = DS.primitive_vars_ctl()
        n = len(pv["phi"])  # n = N - 1
        gdim = len(pv["v"])

        _A = OrderedDict(phi=[], chi=[], v=[])
        _rhs = OrderedDict(phi=[], chi=[], v=[])
        _sol = OrderedDict(phi=[], chi=[], v=[])
        _bcs = OrderedDict(sorted(six.iteritems(self.data["model"].bcs())))
        for i in range(n):
            _A["phi"].append(assemble(eqn["lhs"][i]))
            _A["chi"].append(assemble(eqn["lhs"][n + i]))
            _rhs["phi"].append(eqn["rhs"][i])
            _rhs["chi"].append(eqn["rhs"][n + i])
            _sol["phi"].append(w[i])
            _sol["chi"].append(w[n + i])
        for i in range(gdim):  # TODO: We know that A_v2 = A_v1
            _A["v"].append(assemble(eqn["lhs"][2 * n + i]))
            _rhs["v"].append(eqn["rhs"][2 * n + i])
            _sol["v"].append(w[2 * n + i])
            for bc in _bcs.get("v", []):
                if bc[i] is not None:
                    bc[i].apply(_A["v"][-1])
        _A["p"] = assemble(eqn["lhs"][2 * n + gdim])
        for bc in _bcs.get("p", []):
            bc.apply(_A["p"])
        _rhs["p"] = eqn["rhs"][2 * n + gdim]
        _sol["p"] = w[2 * n + gdim]
        # FIXME: Deal with possible bcs for ``phi`` and ``th``

        # Preparation for tackling singular systems
        if self._flags["fix_p"]:
            null_space, null_fcn = DS.build_pressure_null_space()
            self.data["null_space"] = null_space
            self.data["null_fcn"] = null_fcn
            # Attach null space to PETSc matrix
            as_backend_type(_A["p"]).set_nullspace(null_space)

        # Store matrices + grouped right hand sides and solution functions
        self.data["A"] = _A
        self.data["rhs"] = _rhs
        self.data["sol"] = _sol
        self.data["bcs"] = _bcs

        self._flags["setup"] = True
Exemplo n.º 9
0
 def reduce_Hessian(self, Hessian=None, restricted_dofs_is=None):
     if not Hessian:
         H = dolfin.as_backend_type(dolfin.assemble(self.H)).mat()
     else:
         H = dolfin.as_backend_type(dolfin.assemble(Hessian)).mat()
     if restricted_dofs_is is not None:
         try:
             H_reduced = H.createSubMatrix(restricted_dofs_is,
                                           restricted_dofs_is)
         except:
             H_reduced = H.getSubMatrix(restricted_dofs_is,
                                        restricted_dofs_is)
     return H_reduced
Exemplo n.º 10
0
    def __init__(self, mesh):
        self.mesh = mesh
        self.S1 = df.FunctionSpace(mesh, 'CG', 1)
        self.S3 = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3)
        #zero = df.Expression('0.3')
        m_init = df.Constant([1, 1, 1.0])
        self.m = df.interpolate(m_init, self.S3)
        self.field = df.interpolate(m_init, self.S3)
        self.dmdt = df.interpolate(m_init, self.S3)
        self.spin = self.m.vector().array()
        self.t = 0

        #It seems it's not safe to specify rank in df.interpolate???
        self._alpha = df.interpolate(df.Constant("0.001"), self.S1)
        self._alpha.vector().set_local(self._alpha.vector().array())
        print 'dolfin', self._alpha.vector().array()

        self.llg = LLG(self.S1, self.S3, unit_length=1e-9)
        #normalise doesn't work due to the wrong order
        self.llg.set_m(m_init, normalise=True)

        parameters = {
            'absolute_tolerance': 1e-10,
            'relative_tolerance': 1e-10,
            'maximum_iterations': int(1e5)
        }

        demag = Demag()

        demag.parameters['phi_1'] = parameters
        demag.parameters['phi_2'] = parameters

        self.exchange = Exchange(13e-12)
        self.zeeman = Zeeman([0, 0, 1e5])

        self.llg.effective_field.add(self.exchange)
        #self.llg.effective_field.add(demag)
        self.llg.effective_field.add(self.zeeman)

        self.m_petsc = df.as_backend_type(self.llg.m_field.f.vector()).vec()
        self.h_petsc = df.as_backend_type(self.field.vector()).vec()
        self.alpha_petsc = df.as_backend_type(self._alpha.vector()).vec()
        self.dmdt_petsc = df.as_backend_type(self.dmdt.vector()).vec()
        alpha = 0.001
        gamma = 2.21e5
        LLG1 = -gamma / (1 + alpha * alpha) * df.cross(
            self.m,
            self.field) - alpha * gamma / (1 + alpha * alpha) * df.cross(
                self.m, df.cross(self.m, self.field))
        self.L = df.dot(LLG1, df.TestFunction(self.S3)) * df.dP
Exemplo n.º 11
0
def checkprecond():
    """ Check sMass in preconditioner is negligible for realistic medium """
    mesh = dl.UnitSquareMesh(40, 40)
    V = dl.FunctionSpace(mesh, 'Lagrange', 1)
    regTV = TV({'Vm': V, 'eps': 1e-4, 'k': 1.0, 'GNhessian': False})

    #    print 'Eigenvalues for M'
    #    sM = dl.as_backend_type(regTV.sMass)
    #    compute_eig(sM, 'eigsM.txt')
    #
    #    print 'Eigenvalues for H1'
    #    m = dl.interpolate(dl.Expression(\
    #    'pow(pow(x[0]-0.5,2)+pow(x[1]-0.5,2),0.5)<0.2'), V)
    #    regTV.assemble_hessian(m)
    #    H = dl.as_backend_type(regTV.H)
    #    compute_eig(H, 'eigH1.txt')
    #
    #    print 'Eigenvalues for H2'
    #    m = dl.interpolate(dl.Expression(\
    #    '0.1*(pow(pow(x[0]-0.5,2)+pow(x[1]-0.5,2),0.5)<0.2)'), V)
    #    regTV.assemble_hessian(m)
    #    H = dl.as_backend_type(regTV.H)
    #    compute_eig(H, 'eigH2.txt')
    #
    #    print 'Eigenvalues for Hcst'
    #    m = dl.interpolate(dl.Expression("1.0"), V)
    #    regTV.assemble_hessian(m)
    #    H = dl.as_backend_type(regTV.H)
    #    compute_eig(H, 'eigHcst.txt')
    #
    #    print 'Eigenvalues for Hsin'
    #    m = dl.interpolate(dl.Expression(\
    #    'sin(pi*x[0])*sin(pi*x[1])'), V)
    #    regTV.assemble_hessian(m)
    #    H = dl.as_backend_type(regTV.H)
    #    compute_eig(H, 'eigHsin.txt')

    print 'Eigenvalues for Hsin2'
    m = dl.interpolate(dl.Expression(\
    '0.1*sin(pi*x[0])*sin(pi*x[1])'), V)
    regTV.assemble_hessian(m)
    H = dl.as_backend_type(regTV.H)
    compute_eig(H, 'eigHsin2.txt')

    print 'Eigenvalues for Hsin5'
    m = dl.interpolate(dl.Expression(\
    'sin(5*pi*x[0])*sin(5*pi*x[1])'), V)
    regTV.assemble_hessian(m)
    H = dl.as_backend_type(regTV.H)
    compute_eig(H, 'eigHsin5.txt')
Exemplo n.º 12
0
 def _set_operators(self, A, B):
     if hasattr(self, "_is"):  # there were Dirichlet BCs
         (self.A, self.condensed_A) = self._condense_matrix(A)
         if B is not None:
             (self.B, self.condensed_B) = self._condense_matrix(B)
         else:
             (self.B, self.condensed_B) = (None, None)
     else:
         (self.A, self.condensed_A) = (as_backend_type(A),
                                       as_backend_type(A))
         if B is not None:
             (self.B, self.condensed_B) = (as_backend_type(B),
                                           as_backend_type(B))
         else:
             (self.B, self.condensed_B) = (None, None)
Exemplo n.º 13
0
    def weak_form(self):
        """Return the weak form."""
        from bempp.api.assembly.discrete_boundary_operator import \
            SparseDiscreteBoundaryOperator

        if self._sparse_mat is not None:
            return SparseDiscreteBoundaryOperator(self._sparse_mat)

        backend = parameters['linear_algebra_backend']
        if backend not in ['PETSc', 'uBLAS']:
            parameters['linear_algebra_backend'] = 'PETSc'

        if parameters['linear_algebra_backend'] == 'PETSc':
            mat = as_backend_type(assemble(self._fenics_weak_form)).mat()
            (indptr, indices, data) = mat.getValuesCSR()
            self._sparse_mat = csr_matrix((data, indices, indptr),
                                          shape=mat.size)
        elif parameters['linear_algebra_backend'] == 'uBLAS':
            self._sparse_mat = assemble(self._fenics_weak_form).sparray()
        else:
            raise ValueError(
                "This should not happen! Backend type is %s. " +
                "Default backend should have been set to 'PETSc'.",
                str(parameters['linear_algebra_backend']))

        parameters['linear_algebra_backend'] = backend
        return SparseDiscreteBoundaryOperator(self._sparse_mat)
Exemplo n.º 14
0
def getScipySparseMatrix(mat):
    assert isinstance(mat, dlfn.la.Matrix)
    from scipy.sparse import csr_matrix
    m, n = mat.size(0), mat.size(1)
    indptr, indices, data = dlfn.as_backend_type(mat).mat()\
                            .getValuesCSR()
    return csr_matrix((data, indices, indptr), shape=(m, n))
Exemplo n.º 15
0
    def weak_form(self):

        from bempp.api.assembly.discrete_boundary_operator import SparseDiscreteBoundaryOperator

        if self._sparse_mat is not None:
            return SparseDiscreteBoundaryOperator(self._sparse_mat)

        backend = parameters['linear_algebra_backend']
        if backend not in ['PETSc', 'uBLAS']:
            parameters['linear_algebra_backend'] = 'PETSc'

        if parameters['linear_algebra_backend'] == 'PETSc':
            A = as_backend_type(assemble(self._fenics_weak_form)).mat()
            (indptr, indices, data) = A.getValuesCSR()
            self._sparse_mat = csr_matrix((data, indices, indptr), shape=A.size)
        elif parameters['linear_algebra_backend'] == 'uBLAS':
            self._sparse_mat = assemble(self._fenics_weak_form).sparray()
        else:
            raise ValueError(
                "This should not happen! Backend type is '{0}'. " +
                "Default backend should have been set to 'PETSc'.".format(
                    parameters['linear_algebra_backend']))

        parameters['linear_algebra_backend'] = backend
        return SparseDiscreteBoundaryOperator(self._sparse_mat)
Exemplo n.º 16
0
    def _create_linear_solver(self) -> None:
        """Helper function for creating linear solver based on parameters."""
        solver_type = self._parameters["linear_solver_type"]

        if solver_type == "direct":
            solver = df.LUSolver(self._lhs_matrix)

        elif solver_type == "iterative":
            # Initialize KrylovSolver with matrix
            alg = self._parameters["algorithm"]
            prec = self._parameters["preconditioner"]

            solver = df.PETScKrylovSolver(alg, prec)
            solver.set_operator(self._lhs_matrix)

            solver.parameters["nonzero_initial_guess"] = True

            # Important!
            A = df.as_backend_type(self._lhs_matrix)
            A.set_nullspace(self.nullspace)
        else:
            df.error(
                "Unknown linear_solver_type given: {}".format(solver_type))

        return solver
Exemplo n.º 17
0
def invert_block_diagonal_matrix(V, M, Minv=None):
    """
    Given a block diagonal matrix (DG mass matrix or similar), use local
    dense inverses to compute the  inverse matrix and return it, optionally
    reusing the given Minv tensor
    """
    mesh = V.mesh()
    dm = V.dofmap()
    N = dm.cell_dofs(0).shape[0]
    Mlocal = numpy.zeros((N, N), float)

    if Minv is None:
        Minv = dolfin.as_backend_type(M.copy())

    # Loop over cells and get the block diagonal parts (should be moved to C++)
    istart = M.local_range(0)[0]
    for cell in dolfin.cells(mesh, 'regular'):
        # Get global dofs
        dofs = dm.cell_dofs(cell.index()) + istart

        # Get block diagonal part of approx_A, invert it and insert into M⁻¹
        M.get(Mlocal, dofs, dofs)
        Mlocal_inv = numpy.linalg.inv(Mlocal)
        Minv.set(Mlocal_inv, dofs, dofs)

    Minv.apply('insert')
    return Minv
Exemplo n.º 18
0
 def assemble_rhs(self):
     if self.tensor_rhs is None:
         rhs = dolfin.assemble(self.form_rhs)
         self.tensor_rhs = dolfin.as_backend_type(rhs)
     else:
         dolfin.assemble(self.form_rhs, tensor=self.tensor_rhs)
     return self.tensor_rhs
Exemplo n.º 19
0
    def jac(self, *args, **kwargs):
        """Jacobian in the backend format.

        See ``PDENPLModel.jac`` for more information.
        """
        J = super(SparsePDENLPModel, self).jac(*args, **kwargs)
        return as_backend_type(J).mat()
Exemplo n.º 20
0
    def hess(self, *args, **kwargs):
        """Hessian in the backend format.

        See ``PDENPLModel.hess`` for more information.
        """
        H = super(SparsePDENLPModel, self).hess(*args, **kwargs)
        return as_backend_type(H).mat()
Exemplo n.º 21
0
 def solve(self):
     alpha = self.problem.state["alpha"]
     # Need a copy for line searches etc. to work correctly.
     x = alpha.copy(deepcopy=True)
     xv = as_backend_type(x.vector()).vec()
     # Solve the problem
     self.solver.solve(None, xv)
Exemplo n.º 22
0
    def solve(self, *args, **kwargs):
        '''To disable the annotation, just pass :py:data:`annotate=False` to this routine, and it acts exactly like the
        Dolfin solve call. This is useful in cases where the solve is known to be irrelevant or diagnostic
        for the purposes of the adjoint computation (such as projecting fields to other function spaces
        for the purposes of visualisation).'''

        to_annotate = utils.to_annotate(kwargs.pop("annotate", None))

        if to_annotate:
            factory = args[0]
            vec = args[1]
            b = dolfin.as_backend_type(vec).__class__()

            factory.F(b=b, x=vec)

            F = b.form
            bcs = b.bcs

            u = vec.function
            var = adjglobals.adj_variables[u]

            solving.annotate(F == 0, u, bcs, solver_parameters={"newton_solver": self.parameters.to_dict()})

        newargs = [self] + list(args)
        out = dolfin.NewtonSolver.solve(*newargs, **kwargs)

        if to_annotate and dolfin.parameters["adjoint"]["record_all"]:
            adjglobals.adjointer.record_variable(adjglobals.adj_variables[u], libadjoint.MemoryStorage(adjlinalg.Vector(u)))

        return out
Exemplo n.º 23
0
    def __init__(self, mesh, Vh, prior, misfit, simulation_times,
                 wind_velocity, gls_stab):
        self.mesh = mesh
        self.Vh = Vh
        self.prior = prior
        self.misfit = misfit
        # Assume constant timestepping
        self.simulation_times = simulation_times
        dt = simulation_times[1] - simulation_times[0]

        u = dl.TrialFunction(Vh[STATE])
        v = dl.TestFunction(Vh[STATE])

        kappa = dl.Constant(.001)
        dt_expr = dl.Constant(dt)

        r_trial = u + dt_expr * (-ufl.div(kappa * ufl.grad(u)) +
                                 ufl.inner(wind_velocity, ufl.grad(u)))
        r_test = v + dt_expr * (-ufl.div(kappa * ufl.grad(v)) +
                                ufl.inner(wind_velocity, ufl.grad(v)))

        h = dl.CellDiameter(mesh)
        vnorm = ufl.sqrt(ufl.inner(wind_velocity, wind_velocity))
        if gls_stab:
            tau = ufl.min_value((h * h) / (dl.Constant(2.) * kappa), h / vnorm)
        else:
            tau = dl.Constant(0.)

        self.M = dl.assemble(ufl.inner(u, v) * dl.dx)
        self.M_stab = dl.assemble(ufl.inner(u, v + tau * r_test) * dl.dx)
        self.Mt_stab = dl.assemble(ufl.inner(u + tau * r_trial, v) * dl.dx)
        Nvarf = (ufl.inner(kappa * ufl.grad(u), ufl.grad(v)) +
                 ufl.inner(wind_velocity, ufl.grad(u)) * v) * dl.dx
        Ntvarf = (ufl.inner(kappa * ufl.grad(v), ufl.grad(u)) +
                  ufl.inner(wind_velocity, ufl.grad(v)) * u) * dl.dx
        self.N = dl.assemble(Nvarf)
        self.Nt = dl.assemble(Ntvarf)
        stab = dl.assemble(tau * ufl.inner(r_trial, r_test) * dl.dx)
        self.L = self.M + dt * self.N + stab
        self.Lt = self.M + dt * self.Nt + stab

        self.solver = dl.PETScLUSolver(dl.as_backend_type(self.L))
        self.solvert = dl.PETScLUSolver(dl.as_backend_type(self.Lt))

        # Part of model public API
        self.gauss_newton_approx = False
Exemplo n.º 24
0
 def __control_as_vec(self, control):
     """Return a PETSc Vec representing the supplied Control"""
     if isinstance(control, FunctionControl):
         as_vec = as_backend_type(Function(control.data()).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
Exemplo n.º 25
0
def mat_dolfin2sparse(A):
    """get the csr matrix representing an assembled linear dolfin form

    """
    try:
        return dolfin.as_backend_type(A).sparray()
    except RuntimeError:  # `dolfin <= 1.5+` with `'uBLAS'` support
        rows, cols, values = A.data()
        return sps.csr_matrix((values, cols, rows))
Exemplo n.º 26
0
def transpose_matrix(A):
    '''Create a transpose of PETScMatrix/PETSc.Mat'''
    if isinstance(A, PETSc.Mat):
        At = PETSc.Mat()  # Alloc
        A.transpose(At)  # Transpose to At
        return At

    At = transpose_matrix(as_backend_type(A).mat())
    return PETScMatrix(At)
def mat_dolfin2sparse(A):
    """get the csr matrix representing an assembled linear dolfin form

    """
    try:
        return dolfin.as_backend_type(A).sparray()
    except RuntimeError:  # `dolfin <= 1.5+` with `'uBLAS'` support
        rows, cols, values = A.data()
        return sps.csr_matrix((values, cols, rows))
Exemplo n.º 28
0
def transpose_matrix(A):
    '''Create a transpose of PETScMatrix/PETSc.Mat'''
    if isinstance(A, PETSc.Mat):
        At = PETSc.Mat()  # Alloc
        A.transpose(At)  # Transpose to At
        return At

    At = transpose_matrix(as_backend_type(A).mat())
    return PETScMatrix(At)
Exemplo n.º 29
0
    def set_forms(self):
        """
        Set up week forms
        """
        # Assume constant timestepping
        dt = self.simulation_times[1] - self.simulation_times[0]

        self.wind_velocity = self.computeVelocityField()

        u = dl.TrialFunction(self.Vh[STATE])
        v = dl.TestFunction(self.Vh[STATE])

        kappa = dl.Constant(self.kappa)
        dt_expr = dl.Constant(dt)

        r_trial = u + dt_expr * (-ufl.div(kappa * ufl.grad(u)) +
                                 ufl.inner(self.wind_velocity, ufl.grad(u)))
        r_test = v + dt_expr * (-ufl.div(kappa * ufl.grad(v)) +
                                ufl.inner(self.wind_velocity, ufl.grad(v)))

        h = dl.CellDiameter(self.mesh)
        vnorm = ufl.sqrt(ufl.inner(self.wind_velocity, self.wind_velocity))
        if self.gls_stab:
            tau = ufl.min_value((h * h) / (dl.Constant(2.) * kappa), h / vnorm)
        else:
            tau = dl.Constant(0.)

        self.M = dl.assemble(ufl.inner(u, v) * ufl.dx)
        self.M_stab = dl.assemble(ufl.inner(u, v + tau * r_test) * ufl.dx)
        self.Mt_stab = dl.assemble(ufl.inner(u + tau * r_trial, v) * ufl.dx)
        Nvarf = (ufl.inner(kappa * ufl.grad(u), ufl.grad(v)) +
                 ufl.inner(self.wind_velocity, ufl.grad(u)) * v) * ufl.dx
        Ntvarf = (ufl.inner(kappa * ufl.grad(v), ufl.grad(u)) +
                  ufl.inner(self.wind_velocity, ufl.grad(v)) * u) * ufl.dx
        self.N = dl.assemble(Nvarf)
        self.Nt = dl.assemble(Ntvarf)
        stab = dl.assemble(tau * ufl.inner(r_trial, r_test) * ufl.dx)
        self.L = self.M + dt * self.N + stab
        self.Lt = self.M + dt * self.Nt + stab

        self.solver = PETScLUSolver(self.mpi_comm)
        self.solver.set_operator(dl.as_backend_type(self.L))
        self.solvert = PETScLUSolver(self.mpi_comm)
        self.solvert.set_operator(dl.as_backend_type(self.Lt))
Exemplo n.º 30
0
    def __init__(self, 
                 a_k, 
                 a_m,
                 u,
                 bcs=None, 
                 slepc_options={'eps_max_it':100},
                 option_prefix=None,
                 comm=MPI.comm_world, 
                 slepc_eigensolver = None
                ):
        self.comm = comm
        self.slepc_options = slepc_options
        if option_prefix:
            self.E.setOptionsPrefix(option_prefix)
        self.V = u.function_space()
        if type(bcs) == list:
            self.bcs = bcs
        else:
            self.bcs = [bcs]

        # assemble the matrices as petsc mat
        self.K = as_backend_type(assemble(a_k)).mat()
        self.M = as_backend_type(assemble(a_m)).mat()

        # if bcs extract reduced matrices on dofs with no bcs
        if self.bcs:
            self.index_set_not_bc = self.get_interior_index_set(
                self.bcs, self.V)
            self.K = self.K.createSubMatrix(self.index_set_not_bc, self.index_set_not_bc)
            self.M = self.M.createSubMatrix(self.index_set_not_bc, self.index_set_not_bc)
            self.projector = petsc4py.PETSc.Scatter()
            self.projector.create(
                vec_from=self.K.createVecRight(),
                is_from=None,
                vec_to=u.vector().vec(),
                is_to=self.index_set_not_bc
                )

        # set up the eigensolver
        if slepc_eigensolver:
            self.E = slepc_eigensolver
        else:
            self.E = self.eigensolver_setup() 
        self.E.setOperators(self.K,self.M)       
Exemplo n.º 31
0
    def _condense_matrix(self, mat):
        mat = as_backend_type(mat)

        petsc_version = PETSc.Sys().getVersionInfo()
        if petsc_version["major"] == 3 and petsc_version["minor"] <= 7:
            condensed_mat = mat.mat().getSubMatrix(self._is, self._is)
        else:
            condensed_mat = mat.mat().createSubMatrix(self._is, self._is)

        return mat, PETScMatrix(condensed_mat)
Exemplo n.º 32
0
    def compute_derivative(self, arg_name, arg_function):
        
        residual_form = self.options['residual'](self.unfiltered_density, 
                                                    self.filtered_density,
                                                    C=self.filter_strength)
        derivative_form = df.derivative(residual_form, arg_function)
        derivative_petsc_sparse = df.as_backend_type(df.assemble(derivative_form)).mat()
        derivative_csr = csr_matrix(derivative_petsc_sparse.getValuesCSR()[::-1], shape=derivative_petsc_sparse.size)

        return derivative_csr.tocoo()
Exemplo n.º 33
0
            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]
                gradient_vec = as_backend_type(gradient.vector()).vec()

                G.set(0)
                G.axpy(1, gradient_vec)
                return j
Exemplo n.º 34
0
    def _as_petscmat(self):
        if df.has_petsc4py():
            from petsc4py import PETSc
            mat = PETSc.Mat().createPython(df.as_backend_type(self.prior.M).mat().getSizes(), comm = self.prior.mpi_comm)
#             mat = PETSc.Mat().createPython(self.dim, comm = self.prior.mpi_comm)
            mat.setPythonContext(self)
            return df.PETScMatrix(mat)
        else:
            df.warning('Petsc4py not installed: cannot generate PETScMatrix with specified size!')
            pass
Exemplo n.º 35
0
 def massmat(self):
     """ return the mass matrix
     """
     mesh = dolfin.IntervalMesh(self.N - 1, self.a, self.b)
     Y = dolfin.FunctionSpace(mesh, 'CG', 1)
     yv = dolfin.TestFunction(Y)
     yu = dolfin.TrialFunction(Y)
     my = yv * yu * dx
     my = dolfin.assemble(my)
     return dolfin.as_backend_type(my).sparray()
Exemplo n.º 36
0
 def _get_rtmass(self, output_petsc=True):
     """
     Get the square root of assembled mass matrix M using lumping.
     --credit to: Umberto Villa
     """
     test = df.TestFunction(self.V)
     V_deg = self.V.ufl_element().degree()
     try:
         V_q_fe = df.FiniteElement('Quadrature',
                                   self.V.mesh().ufl_cell(),
                                   2 * V_deg,
                                   quad_scheme='default')
         V_q = df.FunctionSpace(self.V.mesh(), V_q_fe)
     except:
         print(
             'Use FiniteElement in specifying FunctionSpace after version 1.6.0!'
         )
         V_q = df.FunctionSpace(self.V.mesh(), 'Quadrature',
                                2 * self.V._FunctionSpace___degree)
     trial_q = df.TrialFunction(V_q)
     test_q = df.TestFunction(V_q)
     M_q = df.PETScMatrix()
     df.assemble(trial_q * test_q * df.dx,
                 tensor=M_q,
                 form_compiler_parameters={'quadrature_degree': 2 * V_deg})
     ones = df.interpolate(df.Constant(1.), V_q).vector()
     dM_q = M_q * ones
     M_q.zero()
     dM_q_2fill = ones.array() / np.sqrt(dM_q.array())
     dM_q.set_local(dM_q_2fill)
     M_q.set_diagonal(dM_q)
     mixedM = df.PETScMatrix()
     df.assemble(trial_q * test * df.dx,
                 tensor=mixedM,
                 form_compiler_parameters={'quadrature_degree': 2 * V_deg})
     if output_petsc and df.has_petsc4py():
         rtM = df.PETScMatrix(
             df.as_backend_type(mixedM).mat().matMult(
                 df.as_backend_type(M_q).mat()))
     else:
         rtM = sps.csr_matrix(mixedM.array() * dM_q_2fill)
         csr_trim0(rtM, 1e-12)
     return rtM
Exemplo n.º 37
0
def Transpose(A):
    """
    Compute the matrix transpose
    """
    Amat = dl.as_backend_type(A).mat()
    AT = PETSc.Mat()
    Amat.transpose(AT)
    rmap, cmap = Amat.getLGMap()
    AT.setLGMap(cmap, rmap)
    return dl.Matrix(dl.PETScMatrix(AT))
Exemplo n.º 38
0
def dof_chi(f, V, marker=1):
    '''
    Let f be a an edge function. Build a function in V which is such 
    that all dofs where f == marker are 1 and are 0 otherwise.
    '''
    tdim = f.mesh().topology().dim()
    assert f.dim() == 1

    assert V.mesh().id() == f.mesh().id()
    assert V.ufl_element().family() == 'Lagrange'

    mesh = V.mesh()
    mesh.init(1, tdim)
    mesh.init(tdim, 1)
    e2c = mesh.topology()(1, tdim)
    c2e = mesh.topology()(tdim, 1)

    dm = V.dofmap()
    first, last = dm.ownership_range()
    n = last - first

    is_local = lambda i, f=first, l=last: f <= i + f < l

    # Triangle has 3 facets/edges, tet has 6 edges
    nedges = mesh.ufl_cell().num_edges()
    edge_dofs = [dm.tabulate_entity_closure_dofs(1, i) for i in range(nedges)]

    chi = Function(V)
    values = chi.vector().get_local()
    for edge in SubsetIterator(f, marker):
        edgei = edge.index()

        c = e2c(edgei)[0]  # Any cell
        dofs = dm.cell_dofs(c)

        local_edge = c2e(c).tolist().index(edgei)
        dofs = filter(is_local, dofs[edge_dofs[local_edge]])
        values[dofs] = 1.
    # Sync
    chi.vector().set_local(values)
    as_backend_type(chi.vector()).update_ghost_values()

    return chi
Exemplo n.º 39
0
            def __matvec__(self, b, A=bmat, indices=index_set, work=work):
                for index in indices:
                    # Exact apply assign
                    bj = PETScVector(as_backend_type(b).vec().getSubVector(index))
                    xj = A*bj
                    work[index] = xj.get_local()

                x = self.create_vec()
                x.set_local(work)
                return x
Exemplo n.º 40
0
def diagonal_matrix(size, A):
    '''Dolfin A*I serial only'''
    if isinstance(A, (int, float)):
        d = PETSc.Vec().createWithArray(A*np.ones(size))
    else:
        d = as_backend_type(A).vec()
    I = PETSc.Mat().createAIJ(size=size, nnz=1)
    I.setDiagonal(d)
    I.assemble()

    return PETScMatrix(I)
Exemplo n.º 41
0
    def compute_derivative(self, arg_name, arg_function):
        pde_problem = self.options['pde_problem']
        state_name = self.options['state_name']

        residual_form = pde_problem.states_dict[state_name]['residual_form']

        derivative_form = df.derivative(residual_form, arg_function)
        derivative_petsc_sparse = df.as_backend_type(df.assemble(derivative_form)).mat()
        derivative_csr = csr_matrix(derivative_petsc_sparse.getValuesCSR()[::-1], shape=derivative_petsc_sparse.size)

        return derivative_csr.tocoo()
Exemplo n.º 42
0
 def rademacher(self, out=None):
     """
     Sample from Rademacher distribution.
     """
     if out is None:
         return super(Random, self).rademacher()
     elif hasattr(out, "nvec"):  #out is MultiVector
         for i in range(out.nvec()):
             super(Random, self).rademacher(out[i])
         return None
     elif type( dl.as_backend_type(out) ) is dl.PETScVector:
         super(Random, self).rademacher(out)
Exemplo n.º 43
0
 def normal_perturb(self,sigma, out):
     """
     Add a normal perturbation to a Vector/MultiVector.
     """
     if hasattr(out, "nvec"):  #out is MultiVector
         for i in range(out.nvec()):
             super(Random, self).normal(out[i], sigma, False)
     elif hasattr(out, "nsteps"):  #out is TimeDependentVector
         for i in range(out.nsteps):
             super(Random, self).normal(out.data[i], sigma, False)
         return None
     elif type( dl.as_backend_type(out) ) is dl.PETScVector:
         super(Random, self).normal(out, sigma, False)
Exemplo n.º 44
0
            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) # Loss of information? No coeff in init
                        rf.controls[i] = ConstantControl(cons)
                        nvec += vsize
Exemplo n.º 45
0
            def mult(self, mat, x, y):
                # TODO: Add multiple control support to Hessian stack and check for ConstantControl
                x_wrap = Function(rf.controls[0].data().function_space(), PETScVector(x))
                hes = rf.hessian(x_wrap)[0]
                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)
Exemplo n.º 46
0
 def normal(self, sigma, out=None):
     """
     Sample from normal distribution with given variance.
     """
     if out is None:
         return super(Random, self).normal(0, sigma)
     elif hasattr(out, "nvec"):  #out is MultiVector
         for i in range(out.nvec()):
             super(Random, self).normal(out[i], sigma, True)
         return None
     elif hasattr(out, "nsteps"):  #out is TimeDependentVector
         for i in range(out.nsteps):
             super(Random, self).normal(out.data[i], sigma, True)
         return None
     elif type( dl.as_backend_type(out) ) is dl.PETScVector:
         super(Random, self).normal(out, sigma, True)
Exemplo n.º 47
0
 def uniform(self,a,b, out=None):
     """
     Sample from uniform distribution.
     """
     if out is None:
         return super(Random, self).uniform(a,b)
     elif hasattr(out, "nvec"):  #out is MultiVector
         for i in range(out.nvec()):
             super(Random, self).uniform(out[i], a,b)
         return None
     elif hasattr(out, "nsteps"):  #out is TimeDependentVector
         for i in range(out.nsteps):
             super(Random, self).uniform(out.data[i], a,b)
         return None
     elif type( dl.as_backend_type(out) ) is dl.PETScVector:
         super(Random, self).uniform(out[i], a,b)
         return None
Exemplo n.º 48
0
def test_ref_count(pushpop_parameters):
    "Test petsc4py reference counting"
    parameters["linear_algebra_backend"] = "PETSc"

    mesh = UnitSquareMesh(3, 3)
    V = FunctionSpace(mesh, "P", 1)

    # Check u and x own the vector
    u = Function(V)
    x = as_backend_type(u.vector()).vec()
    assert x.refcount == 2

    # Check decref
    del u; gc.collect()  # destroy u
    assert x.refcount == 1

    # Check incref
    vec = PETScVector(x)
    assert x.refcount == 2
Exemplo n.º 49
0
def test_petsc4py_matrix(pushpop_parameters):
    "Test PETScMatrix <-> petsc4py.PETSc.Mat conversions"
    parameters["linear_algebra_backend"] = "PETSc"

    # Assemble a test matrix
    mesh = UnitSquareMesh(4, 4)
    V = FunctionSpace(mesh, "Lagrange", 1)
    u, v = TrialFunction(V), TestFunction(V)
    a = u*v*dx
    A1 = assemble(a)

    # Test conversion dolfin.PETScMatrix -> petsc4py.PETSc.Mat
    A1 = as_backend_type(A1)
    M1 = A1.mat()

    # Copy and scale matrix with petsc4py
    M2 = M1.copy()
    M2.scale(2.0)

    # Test conversion petsc4py.PETSc.Mat  -> PETScMatrix
    A2 = PETScMatrix(M2)

    assert (A1.array()*2.0 == A2.array()).all()
Exemplo n.º 50
0
def test_petsc4py_vector(pushpop_parameters):
    "Test PETScVector <-> petsc4py.PETSc.Vec conversions"
    parameters["linear_algebra_backend"] = "PETSc"

    # Assemble a test matrix
    mesh = UnitSquareMesh(4, 4)
    V = FunctionSpace(mesh, "Lagrange", 1)
    v = TestFunction(V)
    a = v*dx
    b1 = assemble(a)

    # Test conversion dolfin.PETScVector -> petsc4py.PETSc.Vec
    b1 = as_backend_type(b1)
    v1 = b1.vec()

    # Copy and scale vector with petsc4py
    v2 = v1.copy()
    v2.scale(2.0)

    # Test conversion petsc4py.PETSc.Vec  -> PETScVector
    b2 = PETScVector(v2)

    assert (b1.get_local()*2.0 == b2.get_local()).all()
Exemplo n.º 51
0
    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()
    def _pressure_poisson(self,
                          p1, p0,
                          mu, ui,
                          divu,
                          p_bcs=None,
                          p_n=None,
                          rotational_form=False,
                          tol=1.0e-10,
                          verbose=True
                          ):
        '''Solve the pressure Poisson equation

            - \Delta phi = -div(u),
            boundary conditions,

        for

            \nabla p = u.
        '''
        P = p1.function_space()
        p = TrialFunction(P)
        q = TestFunction(P)

        a2 = dot(grad(p), grad(q)) * dx
        L2 = -divu * q * dx
        if p0:
            L2 += dot(grad(p0), grad(q)) * dx
        if p_n:
            n = FacetNormal(P.mesh())
            L2 += dot(n, p_n) * q * ds

        if rotational_form:
            L2 -= mu * dot(grad(div(ui)), grad(q)) * dx

        if p_bcs:
            solve(a2 == L2, p1,
                  bcs=p_bcs,
                  solver_parameters={
                      'linear_solver': 'iterative',
                      'symmetric': True,
                      'preconditioner': 'hypre_amg',
                      'krylov_solver': {'relative_tolerance': tol,
                                        'absolute_tolerance': 0.0,
                                        'maximum_iterations': 100,
                                        'monitor_convergence': verbose}
                  })
        else:
            # If we're dealing with a pure Neumann problem here (which is the
            # default case), this doesn't hurt CG if the system is consistent,
            # cf.
            #
            #    Iterative Krylov methods for large linear systems,
            #    Henk A. van der Vorst.
            #
            # And indeed, it is consistent: Note that
            #
            #    <1, rhs> = \sum_i 1 * \int div(u) v_i
            #             = 1 * \int div(u) \sum_i v_i
            #             = \int div(u).
            #
            # With the divergence theorem, we have
            #
            #    \int div(u) = \int_\Gamma n.u.
            #
            # The latter term is 0 iff inflow and outflow are exactly the same
            # at any given point in time. This corresponds with the
            # incompressibility of the liquid.
            #
            # In turn, this hints towards penetrable boundaries to require
            # Dirichlet conditions on the pressure.
            #
            A = assemble(a2)
            b = assemble(L2)
            #
            # In principle, the ILU preconditioner isn't advised here since it
            # might destroy the semidefiniteness needed for CG.
            #
            # The system is consistent, but the matrix has an eigenvalue 0.
            # This does not harm the convergence of CG, but when
            # preconditioning one has to take care that the preconditioner
            # preserves the kernel.  ILU might destroy this (and the
            # semidefiniteness). With AMG, the coarse grid solves cannot be LU
            # then, so try Jacobi here.
            # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html>
            #
            prec = PETScPreconditioner('hypre_amg')
            PETScOptions.set('pc_hypre_boomeramg_relax_type_coarse', 'jacobi')
            solver = PETScKrylovSolver('cg', prec)
            solver.parameters['absolute_tolerance'] = 0.0
            solver.parameters['relative_tolerance'] = tol
            solver.parameters['maximum_iterations'] = 100
            solver.parameters['monitor_convergence'] = verbose
            # Create solver and solve system
            A_petsc = as_backend_type(A)
            b_petsc = as_backend_type(b)
            p1_petsc = as_backend_type(p1.vector())
            solver.set_operator(A_petsc)
            try:
                solver.solve(p1_petsc, b_petsc)
            except RuntimeError as error:
                info('')
                # Check if the system is indeed consistent.
                #
                # If the right hand side is flawed (e.g., by round-off errors),
                # then it may have a component b1 in the direction of the null
                # space, orthogonal the image of the operator:
                #
                #     b = b0 + b1.
                #
                # When starting with initial guess x0=0, the minimal achievable
                # relative tolerance is then
                #
                #    min_rel_tol = ||b1|| / ||b||.
                #
                # If ||b|| is very small, which is the case when ui is almost
                # divergence-free, then min_rel_to may be larger than the
                # prescribed relative tolerance tol.
                #
                # Use this as a consistency check, i.e., bail out if
                #
                #     tol < min_rel_tol = ||b1|| / ||b||.
                #
                # For computing ||b1||, we use the fact that the null space is
                # one-dimensional, i.e.,  b1 = alpha e,  and
                #
                #     e.b = e.(b0 + b1) = e.b1 = alpha ||e||^2,
                #
                # so  alpha = e.b/||e||^2  and
                #
                #     ||b1|| = |alpha| ||e|| = e.b / ||e||
                #
                e = Function(P)
                e.interpolate(Constant(1.0))
                evec = e.vector()
                evec /= norm(evec)
                alpha = b.inner(evec)
                normB = norm(b)
                info('Linear system convergence failure.')
                info(error.message)
                message = ('Linear system not consistent! '
                           '<b,e> = %g, ||b|| = %g, <b,e>/||b|| = %e, tol = %e.') \
                           % (alpha, normB, alpha/normB, tol)
                info(message)
                if tol < abs(alpha) / normB:
                    info('\int div(u)  =  %e' % assemble(divu * dx))
                    #n = FacetNormal(Q.mesh())
                    #info('\int_Gamma n.u = %e' % assemble(dot(n, u)*ds))
                    #info('\int_Gamma u[0] = %e' % assemble(u[0]*ds))
                    #info('\int_Gamma u[1] = %e' % assemble(u[1]*ds))
                    ## Now plot the faulty u on a finer mesh (to resolve the
                    ## quadratic trial functions).
                    #fine_mesh = Q.mesh()
                    #for k in range(1):
                    #    fine_mesh = refine(fine_mesh)
                    #V1 = FunctionSpace(fine_mesh, 'CG', 1)
                    #W1 = V1*V1
                    #uplot = project(u, W1)
                    ##uplot = Function(W1)
                    ##uplot.interpolate(u)
                    #plot(uplot, title='u_tentative')
                    #plot(uplot[0], title='u_tentative[0]')
                    #plot(uplot[1], title='u_tentative[1]')
                    plot(divu, title='div(u_tentative)')
                    interactive()
                    exit()
                    raise RuntimeError(message)
                else:
                    exit()
                    raise RuntimeError('Linear system failed to converge.')
            except:
                exit()
        return
 def set_nullspace(self, nsp):
     A = self.operators[0]
     dolfin.as_backend_type(A).set_nullspace(nsp)
     self.nsp = nsp
                def solve(selfmat, var, b):
                    if selfmat.adjoint:
                        operators = transpose_operators(selfmat.operators)
                    else:
                        operators = selfmat.operators

                    # Fetch/construct the solver
                    if var.type in ['ADJ_FORWARD', 'ADJ_TLM']:
                        solver = petsc_krylov_solvers[idx]
                        need_to_set_operator = self._need_to_reset_operator
                    else:
                        if adj_petsc_krylov_solvers[idx] is None:
                            need_to_set_operator = True
                            adj_petsc_krylov_solvers[idx] = PETScKrylovSolver(*solver_parameters)
                            adj_ksp = adj_petsc_krylov_solvers[idx].ksp()
                            fwd_ksp = petsc_krylov_solvers[idx].ksp()
                            adj_ksp.setOptionsPrefix(fwd_ksp.getOptionsPrefix())
                            adj_ksp.setType(fwd_ksp.getType())
                            adj_ksp.pc.setType(fwd_ksp.pc.getType())
                            adj_ksp.setFromOptions()
                        else:
                            need_to_set_operator = self._need_to_reset_operator
                        solver = adj_petsc_krylov_solvers[idx]
                        # FIXME: work around DOLFIN bug #583
                        try:
                            solver.parameters.convergence_norm_type
                        except:
                            solver.parameters.convergence_norm_type = "preconditioned"
                        # end FIXME
                    solver.parameters.update(parameters)
                    self._need_to_reset_operator = False

                    if selfmat.adjoint:
                        (nsp_, tnsp_) = (tnsp, nsp)
                    else:
                        (nsp_, tnsp_) = (nsp, tnsp)

                    x = dolfin.Function(fn_space)
                    if selfmat.initial_guess is not None and var.type == 'ADJ_FORWARD':
                        x.vector()[:] = selfmat.initial_guess.vector()

                    if b.data is None:
                        dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var)
                        return adjlinalg.Vector(x)

                    if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']:
                        selfmat.bcs = [utils.homogenize(bc) for bc in selfmat.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in selfmat.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)]

                    # This is really hideous. Sorry.
                    if isinstance(b.data, dolfin.Function):
                        rhs = b.data.vector().copy()
                        [bc.apply(rhs) for bc in selfmat.bcs]

                        if need_to_set_operator:
                            if assemble_system: # if we called assemble_system, rather than assemble
                                v = dolfin.TestFunction(fn_space)
                                (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, selfmat.bcs)
                                if has_preconditioner:
                                    (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, selfmat.bcs)
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)
                            else: # we called assemble
                                A = dolfin.assemble(operators[0])
                                [bc.apply(A) for bc in selfmat.bcs]
                                if has_preconditioner:
                                    P = dolfin.assemble(operators[1])
                                    [bc.apply(P) for bc in selfmat.bcs]
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)
                    else:

                        if assemble_system: # if we called assemble_system, rather than assemble
                            (A, rhs) = dolfin.assemble_system(operators[0], b.data, selfmat.bcs)
                            if need_to_set_operator:
                                if has_preconditioner:
                                    (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, selfmat.bcs)
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)
                        else: # we called assemble
                            A = dolfin.assemble(operators[0])
                            rhs = dolfin.assemble(b.data)
                            [bc.apply(A) for bc in selfmat.bcs]
                            [bc.apply(rhs) for bc in selfmat.bcs]
                            if need_to_set_operator:
                                if has_preconditioner:
                                    P = dolfin.assemble(operators[1])
                                    [bc.apply(P) for bc in selfmat.bcs]
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)

                    if need_to_set_operator:
                        print "|A|: %.6e" % A.norm("frobenius")

                    # Set the nullspace for the linear operator
                    if nsp_ is not None and need_to_set_operator:
                        dolfin.as_backend_type(A).set_nullspace(nsp_)

                    # (Possibly override the user in) orthogonalize
                    # the right-hand-side
                    if tnsp_ is not None:
                        tnsp_.orthogonalize(rhs)

                    print "%s: |b|: %.6e" % (var, rhs.norm("l2"))
                    solver.solve(x.vector(), rhs)
                    return adjlinalg.Vector(x)
Exemplo n.º 55
0
def get_mout_opa(odcoo=None, NY=8, V=None, NV=20):
    """dolfin.assemble the 'MyC' matrix

    the find an array representation
    of the output operator

    the considered output is y(s) = 1/C int_x[1] v(s,x[1]) dx[1]
    it is computed by testing computing my_i = 1/C int y_i v d(x)
    where y_i depends only on x[1] and y_i is zero outside the domain
    of observation. 1/C is the width of the domain of observation
    cf. doku
    """

    odom = ContDomain(odcoo)

    v = dolfin.TestFunction(V)
    voney = dolfin.Expression(('0', '1'), element=V.ufl_element())
    vonex = dolfin.Expression(('1', '0'), element=V.ufl_element())
    voney = dolfin.interpolate(voney, V)
    vonex = dolfin.interpolate(vonex, V)

    # factor to compute the average via \bar u = 1/h \int_0^h u(x) dx
    Ci = 1.0 / (odcoo['xmax'] - odcoo['xmin'])

    try:
        omega_y = dolfin.RectangleMesh(odcoo['xmin'], odcoo['ymin'],
                                       odcoo['xmax'], odcoo['ymax'],
                                       NV/5, NY-1)
    except TypeError:  # e.g. in newer dolfin versions
        omega_y = dolfin.\
            RectangleMesh(dolfin.Point(odcoo['xmin'], odcoo['ymin']),
                          dolfin.Point(odcoo['xmax'], odcoo['ymax']),
                          NV/5, NY-1)
    y_y = dolfin.VectorFunctionSpace(omega_y, 'CG', 1)
    # vone_yx = dolfin.interpolate(vonex, y_y)
    # vone_yy = dolfin.interpolate(voney, y_y)

    # charfun = CharactFun(odom)
    # v = dolfin.TestFunction(V)
    # checkf = dolfin.assemble(inner(v, charfun) * dx)
    # dofs_on_subd = np.where(checkf.array() > 0)[0]

    charfun = CharactFun(odom)
    v = dolfin.TestFunction(V)
    u = dolfin.TrialFunction(V)

    MP = dolfin.assemble(inner(v, u) * charfun * dx)
    MPa = dolfin.as_backend_type(MP).sparray()

    checkf = MPa.diagonal()
    dofs_on_subd = np.where(checkf > 0)[0]

    # set up the numbers of zero columns to be inserted
    # between the nonzeros, i.e. the columns corresponding
    # to the dofs of V outside the observation domain
    # e.g. if there are 7 dofs and dofs_on_subd = [1,4,5], then
    # we compute the numbers [1,2,0,1] to assemble C = [0,*,0,0,*,*,0]
    indist_subddofs = dofs_on_subd[1:] - (dofs_on_subd[:-1]+1)
    indist_subddofs = np.r_[indist_subddofs, V.dim() - dofs_on_subd[-1] - 1]

    YX = [sps.csc_matrix((NY, dofs_on_subd[0]))]
    YY = [sps.csc_matrix((NY, dofs_on_subd[0]))]
    kkk = 0
    for curdof, curzeros in zip(dofs_on_subd, indist_subddofs):
        kkk += 1
        vcur = dolfin.Function(V)
        vcur.vector()[:] = 0
        vcur.vector()[curdof] = 1
        vdof_y = dolfin.interpolate(vcur, y_y)

        Yx, Yy = [], []
        for nbf in range(NY):
            ybf = L2abLinBas(nbf, NY, a=odcoo['ymin'], b=odcoo['ymax'])
            yx = Cast1Dto2D(ybf, odom, vcomp=0, xcomp=1)
            yy = Cast1Dto2D(ybf, odom, vcomp=1, xcomp=1)

            yxf = Ci * inner(vdof_y, yx) * dx
            yyf = Ci * inner(vdof_y, yy) * dx

            Yx.append(dolfin.assemble(yxf))
            Yy.append(dolfin.assemble(yyf))

        Yx = np.array(Yx)
        Yy = np.array(Yy)
        Yx = Yx.reshape(NY, 1)
        Yy = Yy.reshape(NY, 1)
        # append the columns to z
        YX.append(sps.csc_matrix(Yx))
        YY.append(sps.csc_matrix(Yy))
        if curzeros > 0:
            YX.append(sps.csc_matrix((NY, curzeros)))
            YY.append(sps.csc_matrix((NY, curzeros)))

    # print 'number of subdofs: {0}'.format(dofs_on_subd.shape[0])
    My = ybf.massmat()
    YYX = sps.hstack(YX)
    YYY = sps.hstack(YY)
    MyC = sps.vstack([YYX, YYY], format='csc')

    # basfun = dolfin.Function(V)
    # basfun.vector()[dofs_on_subd] = 0.2
    # basfun.vector()[0] = 1  # for scaling the others only
    # dolfin.plot(basfun)

    try:
        return (MyC, sps.block_diag([My, My], format='csc'))
    except AttributeError:  # e.g. in scipy <= 0.9
        return (
            MyC,
            sps.hstack([sps.vstack([My, sps.csc_matrix((NY, NY))]),
                        sps.vstack([sps.csc_matrix((NY, NY)), My])]))
Exemplo n.º 56
0
                def solve(self, var, b):
                    if self.adjoint:
                        operators = transpose_operators(self.operators)
                    else:
                        operators = self.operators

                    solver = dolfin.LinearSolver(*solver_parameters)
                    solver.parameters.update(parameters)

                    x = dolfin.Function(fn_space)
                    if self.initial_guess is not None and var.type == 'ADJ_FORWARD':
                        x.vector()[:] = self.initial_guess.vector()

                    if b.data is None:
                        dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var)
                        return adjlinalg.Vector(x)

                    if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']:
                        self.bcs = [utils.homogenize(bc) for bc in self.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)]

                    # This is really hideous. Sorry.
                    if isinstance(b.data, dolfin.Function):
                        rhs = b.data.vector().copy()
                        [bc.apply(rhs) for bc in self.bcs]

                        if assemble_system: # if we called assemble_system, rather than assemble
                            v = dolfin.TestFunction(fn_space)
                            (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, self.bcs)
                            if has_preconditioner:
                                (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, self.bcs)
                                solver.set_operators(A, P)
                            else:
                                solver.set_operator(A)
                        else: # we called assemble
                            A = dolfin.assemble(operators[0])
                            [bc.apply(A) for bc in self.bcs]

                            # Set nullspace
                            if nsp:
                                dolfin.as_backend_type(A).set_nullspace(nsp)
                                nsp.orthogonalize(b);

                            if has_preconditioner:
                                P = dolfin.assemble(operators[1])
                                [bc.apply(P) for bc in self.bcs]
                                solver.set_operators(A, P)
                            else:
                                solver.set_operator(A)
                    else:

                        if assemble_system: # if we called assemble_system, rather than assemble
                            (A, rhs) = dolfin.assemble_system(operators[0], b.data, self.bcs)
                            if has_preconditioner:
                                (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, self.bcs)
                                solver.set_operators(A, P)
                            else:
                                solver.set_operator(A)
                        else: # we called assemble
                            A = dolfin.assemble(operators[0])
                            rhs = dolfin.assemble(b.data)
                            [bc.apply(A) for bc in self.bcs]
                            [bc.apply(rhs) for bc in self.bcs]

                            # Set nullspace
                            if nsp:
                                dolfin.as_backend_type(A).set_nullspace(nsp)
                                nsp.orthogonalize(rhs);

                            if has_preconditioner:
                                P = dolfin.assemble(operators[1])
                                [bc.apply(P) for bc in self.bcs]
                                solver.set_operators(A, P)
                            else:
                                solver.set_operator(A)

                    solver.solve(x.vector(), rhs)
                    return adjlinalg.Vector(x)
Exemplo n.º 57
0
def as_petsc_nest(bvec):
    '''Represent bvec as PETSc nested vector'''
    assert isinstance(bvec, block_vec)
    nest = [as_backend_type(v).vec() for v in bvec]
    return PETSc.Vec().createNest(nest)
Exemplo n.º 58
0
def compute_pressure(
    P,
    p0,
    mu,
    ui,
    u,
    my_dx,
    p_bcs=None,
    rotational_form=False,
    tol=1.0e-10,
    verbose=True,
):
    """Solve the pressure Poisson equation

    .. math::

        \\begin{align}
          -\\frac{1}{r} \\div(r \\nabla (p_1-p_0)) =
              -\\frac{1}{r} \\div(r u),\\\\
          \\text{(with boundary conditions)},
        \\end{align}

    for :math:`\\nabla p = u`.

    The pressure correction is based on the update formula

    .. math::
        \\frac{\\rho}{dt} (u_{n+1}-u^*)
            + \\begin{pmatrix}
                \\text{d}\\phi/\\text{d}r\\\\
                \\text{d}\\phi/\\text{d}z\\\\
                \\frac{1}{r} \\text{d}\\phi/\\text{d}\\theta
              \\end{pmatrix}
                = 0

    with :math:`\\phi = p_{n+1} - p^*` and

    .. math::

         \\frac{1}{r} \\frac{\\text{d}}{\\text{d}r} (r u_r^{(n+1)})
       + \\frac{\\text{d}}{\\text{d}z}  (u_z^{(n+1)})
       + \\frac{1}{r} \\frac{\\text{d}}{\\text{d}\\theta} (u_{\\theta}^{(n+1)})
           = 0

    With the assumption that u does not change in the direction
    :math:`\\theta`, one derives

    .. math::

       - \\frac{1}{r}   \\div(r \\nabla \\phi) =
           \\frac{1}{r} \\frac{\\rho}{dt}   \\div(r (u_{n+1} - u^*))\\\\
       - \\frac{1}{r} \\langle n, r \\nabla \\phi\\rangle =
           \\frac{1}{r} \\frac{\\rho}{dt} \\langle n, r (u_{n+1} - u^*)\\rangle

    In its weak form, this is

    .. math::

      \\int r \\langle\\nabla\\phi, \\nabla q\\rangle \\,2 \\pi =
           - \\frac{\\rho}{dt} \\int \\div(r u^*) q \\, 2 \\pi
           - \\frac{\\rho}{dt} \\int_{\\Gamma}
                 \\langle n,  r (u_{n+1}-u^*)\\rangle q \\, 2\\pi.

    (The terms :math:`1/r` cancel with the volume elements :math:`2\\pi r`.)
    If the Dirichlet boundary conditions are applied to both :math:`u^*` and
    :math:`u_n` (the latter in the velocity correction step), the boundary
    integral vanishes.

    If no Dirichlet conditions are given (which is the default case), the
    system has no unique solution; one eigenvalue is 0. This however, does not
    hurt CG convergence if the system is consistent, cf. :cite:`vdV03`. And
    indeed it is consistent if and only if

    .. math::
        \\int_\\Gamma r \\langle n, u\\rangle = 0.

    This condition makes clear that for incompressible Navier-Stokes, one
    either needs to make sure that inflow and outflow always add up to 0, or
    one has to specify pressure boundary conditions.

    Note that, when using a multigrid preconditioner as is done here, the
    coarse solver must be chosen such that it preserves the nullspace of the
    problem.
    """
    W = ui.function_space()
    r = SpatialCoordinate(W.mesh())[0]

    p = TrialFunction(P)
    q = TestFunction(P)
    a2 = dot(r * grad(p), grad(q)) * 2 * pi * my_dx
    # The boundary conditions
    #     n.(p1-p0) = 0
    # are implicitly included.
    #
    # L2 = -div(r*u) * q * 2*pi*my_dx
    div_u = 1 / r * (r * u[0]).dx(0) + u[1].dx(1)
    L2 = -div_u * q * 2 * pi * r * my_dx
    if p0:
        L2 += r * dot(grad(p0), grad(q)) * 2 * pi * my_dx

    # In the Cartesian variant of the rotational form, one makes use of the
    # fact that
    #
    #     curl(curl(u)) = grad(div(u)) - div(grad(u)).
    #
    # The same equation holds true in cylindrical form. Hence, to get the
    # rotational form of the splitting scheme, we need to
    #
    # rotational form
    if rotational_form:
        # If there is no dependence of the angular coordinate, what is
        # div(grad(div(u))) in Cartesian coordinates becomes
        #
        #     1/r div(r * grad(1/r div(r*u)))
        #
        # in cylindrical coordinates (div and grad are in cylindrical
        # coordinates). Unfortunately, we cannot write it down that
        # compactly since u_phi is in the game.
        # When using P2 elements, this value will be 0 anyways.
        div_ui = 1 / r * (r * ui[0]).dx(0) + ui[1].dx(1)
        grad_div_ui = as_vector((div_ui.dx(0), div_ui.dx(1)))
        L2 -= r * mu * dot(grad_div_ui, grad(q)) * 2 * pi * my_dx
        # div_grad_div_ui = 1/r * (r * grad_div_ui[0]).dx(0) \
        #     + (grad_div_ui[1]).dx(1)
        # L2 += mu * div_grad_div_ui * q * 2*pi*r*dx
        # n = FacetNormal(Q.mesh())
        # L2 -= mu * (n[0] * grad_div_ui[0] + n[1] * grad_div_ui[1]) \
        #     * q * 2*pi*r*ds

    p1 = Function(P)
    if p_bcs:
        solve(
            a2 == L2,
            p1,
            bcs=p_bcs,
            solver_parameters={
                "linear_solver": "iterative",
                "symmetric": True,
                "preconditioner": "hypre_amg",
                "krylov_solver": {
                    "relative_tolerance": tol,
                    "absolute_tolerance": 0.0,
                    "maximum_iterations": 100,
                    "monitor_convergence": verbose,
                },
            },
        )
    else:
        # If we're dealing with a pure Neumann problem here (which is the
        # default case), this doesn't hurt CG if the system is consistent,
        # cf. :cite:`vdV03`. And indeed it is consistent if and only if
        #
        #   \int_\Gamma r n.u = 0.
        #
        # This makes clear that for incompressible Navier-Stokes, one
        # either needs to make sure that inflow and outflow always add up
        # to 0, or one has to specify pressure boundary conditions.
        #
        # If the right-hand side is very small, round-off errors may impair
        # the consistency of the system. Make sure the system we are
        # solving remains consistent.
        A = assemble(a2)
        b = assemble(L2)
        # Assert that the system is indeed consistent.
        e = Function(P)
        e.interpolate(Constant(1.0))
        evec = e.vector()
        evec /= norm(evec)
        alpha = b.inner(evec)
        normB = norm(b)
        # Assume that in every component of the vector, a round-off error
        # of the magnitude DOLFIN_EPS is present. This leads to the
        # criterion
        #    |<b,e>| / (||b||*||e||) < DOLFIN_EPS
        # as a check whether to consider the system consistent up to
        # round-off error.
        #
        # TODO think about condition here
        # if abs(alpha) > normB * DOLFIN_EPS:
        if abs(alpha) > normB * 1.0e-12:
            # divu = 1 / r * (r * u[0]).dx(0) + u[1].dx(1)
            adivu = assemble(((r * u[0]).dx(0) + u[1].dx(1)) * 2 * pi * my_dx)
            info("\\int 1/r * div(r*u) * 2*pi*r  =  {:e}".format(adivu))
            n = FacetNormal(P.mesh())
            boundary_integral = assemble((n[0] * u[0] + n[1] * u[1]) * 2 * pi * r * ds)
            info("\\int_Gamma n.u * 2*pi*r = {:e}".format(boundary_integral))
            message = (
                "System not consistent! "
                "<b,e> = {:g}, ||b|| = {:g}, <b,e>/||b|| = {:e}.".format(
                    alpha, normB, alpha / normB
                )
            )
            info(message)
            # # Plot the stuff, and project it to a finer mesh with linear
            # # elements for the purpose.
            # plot(divu, title='div(u_tentative)')
            # # Vp = FunctionSpace(Q.mesh(), 'CG', 2)
            # # Wp = MixedFunctionSpace([Vp, Vp])
            # # up = project(u, Wp)
            # fine_mesh = Q.mesh()
            # for k in range(1):
            #     fine_mesh = refine(fine_mesh)
            # V = FunctionSpace(fine_mesh, 'CG', 1)
            # W = V * V
            # # uplot = Function(W)
            # # uplot.interpolate(u)
            # uplot = project(u, W)
            # plot(uplot[0], title='u_tentative[0]')
            # plot(uplot[1], title='u_tentative[1]')
            # # plot(u, title='u_tentative')
            # interactive()
            # exit()
            raise RuntimeError(message)
        # Project out the roundoff error.
        b -= alpha * evec

        #
        # In principle, the ILU preconditioner isn't advised here since it
        # might destroy the semidefiniteness needed for CG.
        #
        # The system is consistent, but the matrix has an eigenvalue 0.
        # This does not harm the convergence of CG, but when
        # preconditioning one has to make sure that the preconditioner
        # preserves the kernel. ILU might destroy this (and the
        # semidefiniteness). With AMG, the coarse grid solves cannot be LU
        # then, so try Jacobi here.
        # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html>
        #
        prec = PETScPreconditioner("hypre_amg")
        from dolfin import PETScOptions

        PETScOptions.set("pc_hypre_boomeramg_relax_type_coarse", "jacobi")
        solver = PETScKrylovSolver("cg", prec)
        solver.parameters["absolute_tolerance"] = 0.0
        solver.parameters["relative_tolerance"] = tol
        solver.parameters["maximum_iterations"] = 100
        solver.parameters["monitor_convergence"] = verbose
        # Create solver and solve system
        A_petsc = as_backend_type(A)
        b_petsc = as_backend_type(b)
        p1_petsc = as_backend_type(p1.vector())
        solver.set_operator(A_petsc)
        solver.solve(p1_petsc, b_petsc)
    return p1
Exemplo n.º 59
0
                def solve(self, var, b):
                    if self.adjoint:
                        operators = transpose_operators(self.operators)
                    else:
                        operators = self.operators

                    # Fetch/construct the solver
                    if var.type in ['ADJ_FORWARD', 'ADJ_TLM']:
                        solver = krylov_solvers[idx]
                        need_to_set_operator = False
                    else:
                        if adj_krylov_solvers[idx] is None:
                            need_to_set_operator = True
                            adj_krylov_solvers[idx] = KrylovSolver(*solver_parameters)
                        else:
                            need_to_set_operator = False
                        solver = adj_krylov_solvers[idx]
                    solver.parameters.update(parameters)

                    if self.adjoint:
                        (nsp_, tnsp_) = (tnsp, nsp)
                    else:
                        (nsp_, tnsp_) = (nsp, tnsp)

                    x = dolfin.Function(fn_space)
                    if self.initial_guess is not None and var.type == 'ADJ_FORWARD':
                        x.vector()[:] = self.initial_guess.vector()

                    if b.data is None:
                        dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var)
                        return adjlinalg.Vector(x)

                    if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']:
                        self.bcs = [utils.homogenize(bc) for bc in self.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)]

                    # This is really hideous. Sorry.
                    if isinstance(b.data, dolfin.Function):
                        rhs = b.data.vector().copy()
                        [bc.apply(rhs) for bc in self.bcs]

                        if need_to_set_operator:
                            if assemble_system: # if we called assemble_system, rather than assemble
                                v = dolfin.TestFunction(fn_space)
                                (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, self.bcs)
                                if has_preconditioner:
                                    (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, self.bcs)
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)
                            else: # we called assemble
                                A = dolfin.assemble(operators[0])
                                [bc.apply(A) for bc in self.bcs]
                                if has_preconditioner:
                                    P = dolfin.assemble(operators[1])
                                    [bc.apply(P) for bc in self.bcs]
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)
                    else:

                        if assemble_system: # if we called assemble_system, rather than assemble
                            (A, rhs) = dolfin.assemble_system(operators[0], b.data, self.bcs)
                            if need_to_set_operator:
                                if has_preconditioner:
                                    (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, self.bcs)
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)
                        else: # we called assemble
                            A = dolfin.assemble(operators[0])
                            rhs = dolfin.assemble(b.data)
                            [bc.apply(A) for bc in self.bcs]
                            [bc.apply(rhs) for bc in self.bcs]
                            if need_to_set_operator:
                                if has_preconditioner:
                                    P = dolfin.assemble(operators[1])
                                    [bc.apply(P) for bc in self.bcs]
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)

                    # Set the nullspace for the linear operator
                    if nsp_ is not None and need_to_set_operator:
                        dolfin.as_backend_type(A).set_nullspace(nsp_)

                    # (Possibly override the user in) orthogonalize
                    # the right-hand-side
                    if tnsp_ is not None:
                        tnsp_.orthogonalize(rhs)

                    solver.solve(x.vector(), rhs)
                    return adjlinalg.Vector(x)
Exemplo n.º 60
0
class DirichletBoundary(dfn.SubDomain):
    def inside(self, x, on_boundary):
        return x[0] < dfn.DOLFIN_EPS or x[0] > 1.0 - dfn.DOLFIN_EPS


u0 = dfn.Constant(0.0)
bc = dfn.DirichletBC(V, u0, DirichletBoundary())

A, rhs = dfn.assemble_system(a, L, bcs=bc)
############################################################


############################################################
# Part II: Solve with PyAMG
Asp = dfn.as_backend_type(A).sparray()
b = dfn.as_backend_type(rhs).array_view()

ml = pyamg.smoothed_aggregation_solver(Asp, max_coarse=10)
residuals = []
x = ml.solve(b, tol=1e-10, accel='cg', residuals=residuals)

residuals = residuals / residuals[0]
print(ml)
############################################################


############################################################
# Part III: plot
# import matplotlib.pyplot as plt
# plt.figure(2)