def amg_solve(N, method):
        # Elasticity parameters
        E = 1.0e9
        nu = 0.3
        mu = E / (2.0 * (1.0 + nu))
        lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))

        # Stress computation
        def sigma(v):
            return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym(
                grad(v))) * Identity(2)

        # Define problem
        mesh = UnitSquareMesh(MPI.comm_world, N, N)
        V = VectorFunctionSpace(mesh, 'Lagrange', 1)
        bc0 = Function(V)
        with bc0.vector().localForm() as bc_local:
            bc_local.set(0.0)

        def boundary(x, only_boundary):
            return [only_boundary] * x.shape(0)

        bc = DirichletBC(V.sub(0), bc0, boundary)
        u = TrialFunction(V)
        v = TestFunction(V)

        # Forms
        a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector(
            (1.0, 1.0)), v) * dx

        # Assemble linear algebra objects
        A = assemble_matrix(a, [bc])
        A.assemble()
        b = assemble_vector(L)
        apply_lifting(b, [a], [[bc]])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        set_bc(b, [bc])

        # Create solution function
        u = Function(V)

        # Create near null space basis and orthonormalize
        null_space = build_nullspace(V, u.vector())

        # Attached near-null space to matrix
        A.set_near_nullspace(null_space)

        # Test that basis is orthonormal
        assert null_space.is_orthonormal()

        # Create PETSC smoothed aggregation AMG preconditioner, and
        # create CG solver
        solver = PETScKrylovSolver("cg", method)

        # Set matrix operator
        solver.set_operator(A)

        # Compute solution and return number of iterations
        return solver.solve(u.vector(), b)
Exemple #2
0
def fit(x0, y0, mesh, Eps, degree=1, verbose=False, solver='spsolve'):
    V = FunctionSpace(mesh, 'CG', degree)
    u = TrialFunction(V)
    v = TestFunction(V)

    n = FacetNormal(mesh)

    dim = mesh.geometry().dim()

    A = [
        _assemble_eigen(+Constant(Eps[i, j]) * u.dx(i) * v.dx(j) * dx
                        # pylint: disable=unsubscriptable-object
                        - Constant(Eps[i, j]) * u.dx(i) * n[j] * v *
                        ds).sparray() for i in range(dim) for j in range(dim)
    ]

    E = _build_eval_matrix(V, x0)

    M = sparse.vstack(A + [E])
    b = numpy.concatenate([numpy.zeros(sum(a.shape[0] for a in A)), y0])

    if solver == 'spsolve':
        MTM = M.T.dot(M)
        x = sparse.linalg.spsolve(MTM, M.T.dot(b))
    elif solver == 'lsqr':
        x, istop, *_ = sparse.linalg.lsqr(
            M,
            b,
            show=verbose,
            atol=1.0e-10,
            btol=1.0e-10,
        )
        assert istop == 2, \
            'sparse.linalg.lsqr not successful (error code {})'.format(istop)
    elif solver == 'lsmr':
        x, istop, *_ = sparse.linalg.lsmr(
            M,
            b,
            show=verbose,
            atol=1.0e-10,
            btol=1.0e-10,
            # min(M.shape) is the default
            maxiter=max(min(M.shape), 10000))
        assert istop == 2, \
            'sparse.linalg.lsmr not successful (error code {})'.format(istop)
    else:
        assert solver == 'gmres', 'Unknown solver \'{}\'.'.format(solver)
        A = sparse.linalg.LinearOperator((M.shape[1], M.shape[1]),
                                         matvec=lambda x: M.T.dot(M.dot(x)))
        x, info = sparse.linalg.gmres(A, M.T.dot(b), tol=1.0e-12)
        assert info == 0, \
            'sparse.linalg.gmres not successful (error code {})'.format(info)

    u = Function(V)
    u.vector().set_local(x)
    return u
Exemple #3
0
    def amg_solve(N, method):
        # Elasticity parameters
        E = 1.0e9
        nu = 0.3
        mu = E / (2.0 * (1.0 + nu))
        lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))

        # Stress computation
        def sigma(v):
            return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym(
                grad(v))) * Identity(2)

        # Define problem
        mesh = UnitSquareMesh(MPI.comm_world, N, N)
        V = VectorFunctionSpace(mesh, 'Lagrange', 1)
        bc0 = Function(V)
        bc = DirichletBC(V.sub(0), bc0, lambda x, on_boundary: on_boundary)
        u = TrialFunction(V)
        v = TestFunction(V)

        # Forms
        a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector(
            (1.0, 1.0)), v) * dx

        # Assemble linear algebra objects
        A, b = assemble_system(a, L, bc)

        # Create solution function
        u = Function(V)

        # Create near null space basis and orthonormalize
        null_space = build_nullspace(V, u.vector())

        # Attached near-null space to matrix
        A.set_near_nullspace(null_space)

        # Test that basis is orthonormal
        assert null_space.is_orthonormal()

        # Create PETSC smoothed aggregation AMG preconditioner, and
        # create CG solver
        solver = PETScKrylovSolver("cg", method)

        # Set matrix operator
        solver.set_operator(A)

        # Compute solution and return number of iterations
        return solver.solve(u.vector(), b)
Exemple #4
0
    def solve(self, mesh, num=5):
        """ Solve for num eigenvalues based on the mesh. """
        # conforming elements
        V = FunctionSpace(mesh, "CG", self.degree)
        u = TrialFunction(V)
        v = TestFunction(V)

        # weak formulation
        a = inner(grad(u), grad(v)) * dx
        b = u * v * ds
        A = PETScMatrix()
        B = PETScMatrix()
        A = assemble(a, tensor=A)
        B = assemble(b, tensor=B)

        # find eigenvalues
        eigensolver = SLEPcEigenSolver(A, B)
        eigensolver.parameters["spectral_transform"] = "shift-and-invert"
        eigensolver.parameters["problem_type"] = "gen_hermitian"
        eigensolver.parameters["spectrum"] = "smallest real"
        eigensolver.parameters["spectral_shift"] = 1.0E-10
        eigensolver.solve(num + 1)

        # extract solutions
        lst = [
            eigensolver.get_eigenpair(i)
            for i in range(1, eigensolver.get_number_converged())
        ]
        for k in range(len(lst)):
            u = Function(V)
            u.vector()[:] = lst[k][2]
            lst[k] = (lst[k][0], u)  # pair (eigenvalue,eigenfunction)
        return np.array(lst)
Exemple #5
0
    def solve(self, mesh, num=5):
        """ Solve for num eigenvalues based on the mesh. """
        # conforming elements
        V = FunctionSpace(mesh, "CG", self.degree)
        u = TrialFunction(V)
        v = TestFunction(V)

        # weak formulation
        a = inner(grad(u), grad(v)) * dx
        b = u * v * ds
        A = PETScMatrix()
        B = PETScMatrix()
        A = assemble(a, tensor=A)
        B = assemble(b, tensor=B)

        # find eigenvalues
        eigensolver = SLEPcEigenSolver(A, B)
        eigensolver.parameters["spectral_transform"] = "shift-and-invert"
        eigensolver.parameters["problem_type"] = "gen_hermitian"
        eigensolver.parameters["spectrum"] = "smallest real"
        eigensolver.parameters["spectral_shift"] = 1.0E-10
        eigensolver.solve(num + 1)

        # extract solutions
        lst = [
            eigensolver.get_eigenpair(i) for i in range(
                1,
                eigensolver.get_number_converged())]
        for k in range(len(lst)):
            u = Function(V)
            u.vector()[:] = lst[k][2]
            lst[k] = (lst[k][0], u)  # pair (eigenvalue,eigenfunction)
        return np.array(lst)
Exemple #6
0
def cm1dvelocity(img: np.array, vel: np.array, alpha0: float,
                 alpha1: float) -> np.array:
    """Computes the source for a L2-H1 mass conserving flow for a 1D image
    sequence and a given velocity.

    Takes a one-dimensional image sequence and a velocity, and returns a
    minimiser of the L2-H1 mass conservation functional with spatio-temporal
    regularisation.

    Args:
        img (np.array): A 1D image sequence of shape (m, n), where m is the
                        number of time steps and n is the number of pixels.
        vel (np.array): A 1D image sequence of shape (m, n).
        alpha0 (float): The spatial regularisation parameter.
        alpha1 (float): The temporal regularisation parameter.

    Returns:
        k: A source array of shape (m, n).

    """
    # Create mesh.
    [m, n] = img.shape
    mesh = UnitSquareMesh(m - 1, n - 1)

    # Define function space and functions.
    V = FunctionSpace(mesh, 'CG', 1)
    k = TrialFunction(V)
    w = TestFunction(V)

    # Convert image to function.
    f = Function(V)
    f.vector()[:] = dh.img2funvec(img)

    # Convert velocity to function.
    v = Function(V)
    v.vector()[:] = dh.img2funvec(vel)

    # Define derivatives of data.
    ft = Function(V)
    ftv = np.diff(img, axis=0) * (m - 1)
    ftv = np.concatenate((ftv, ftv[-1, :].reshape(1, n)), axis=0)
    ft.vector()[:] = dh.img2funvec(ftv)

    fx = Function(V)
    fxv = np.gradient(img, 1 / (n - 1), axis=1)
    fx.vector()[:] = dh.img2funvec(fxv)

    # Define weak formulation.
    A = k * w * dx + alpha0 * k.dx(1) * w.dx(1) * dx + alpha1 * k.dx(0) * w.dx(
        0) * dx
    b = (ft + v.dx(1) * f + v * fx) * w * dx

    # Compute solution.
    k = Function(V)
    solve(A == b, k)

    # Convert back to array.
    k = dh.funvec2img(k.vector().get_local(), m, n)
    return k
Exemple #7
0
def cm1dsource(img: np.array, k: np.array, alpha0: float,
               alpha1: float) -> np.array:
    """Computes the L2-H1 mass conserving flow for a 1D image sequence and a
    given source.

    Takes a one-dimensional image sequence and a source, and returns a
    minimiser of the L2-H1 mass conservation functional with spatio-temporal
    regularisation.

    Args:
        img (np.array): A 1D image sequence of shape (m, n), where m is the
                        number of time steps and n is the number of pixels.
        k (np.array):   A 1D image sequence of shape (m, n).
        alpha0 (float): The spatial regularisation parameter.
        alpha1 (float): The temporal regularisation parameter.

    Returns:
        v: A velocity array of shape (m, n).

    """
    # Create mesh.
    [m, n] = img.shape
    mesh = UnitSquareMesh(m - 1, n - 1)

    # Define function space and functions.
    V = FunctionSpace(mesh, 'CG', 1)
    v = TrialFunction(V)
    w = TestFunction(V)

    # Convert image to function.
    f = Function(V)
    f.vector()[:] = dh.img2funvec(img)

    # Convert source to function.
    g = Function(V)
    g.vector()[:] = dh.img2funvec(k)

    # Define derivatives of data.
    ft = Function(V)
    ftv = np.diff(img, axis=0) * (m - 1)
    ftv = np.concatenate((ftv, ftv[-1, :].reshape(1, n)), axis=0)
    ft.vector()[:] = dh.img2funvec(ftv)

    fx = Function(V)
    fxv = np.gradient(img, 1 / (n - 1), axis=1)
    fx.vector()[:] = dh.img2funvec(fxv)

    ft = f.dx(0)
    fx = f.dx(1)

    # Define weak formulation.
    A = - (fx*v + f*v.dx(1)) * (fx*w + f*w.dx(1))*dx \
        - alpha0*v.dx(1)*w.dx(1)*dx - alpha1*v.dx(0)*w.dx(0)*dx
    b = ft * (fx * w + f * w.dx(1)) * dx - g * (fx * w + f * w.dx(1)) * dx

    # Compute solution.
    v = Function(V)
    solve(A == b, v)

    # Convert back to array.
    vel = dh.funvec2img(v.vector().get_local(), m, n)
    return vel
Exemple #8
0
    def solve(self):
        """ Find eigenvalues for transformed mesh. """
        self.progress("Building mesh.")
        # build transformed mesh
        mesh = self.refineMesh()
        # dim = mesh.topology().dim()
        if self.bcLast:
            mesh = transform_mesh(mesh, self.transformList)
            Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList)
        else:
            Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList)
            mesh = transform_mesh(mesh, self.transformList)
            # boundary conditions computed on non-transformed mesh
            # copy the values to transformed mesh
            fun = FacetFunction("size_t", mesh, shift)
            fun.array()[:] = bcs.array()[:]
            bcs = fun
        ds = Measure('ds', domain=mesh, subdomain_data=bcs)
        V = FunctionSpace(mesh, self.method, self.deg)
        u = TrialFunction(V)
        v = TestFunction(V)
        self.progress("Assembling matrices.")
        wTop = Expression(self.wTop, degree=self.deg)
        wBottom = Expression(self.wBottom, degree=self.deg)

        #
        # build stiffness matrix form
        #
        s = dot(grad(u), grad(v))*wTop*dx
        # add Robin parts
        for bc in Robin:
            s += Constant(bc.parValue)*u*v*wTop*ds(bc.value+shift)

        #
        # build mass matrix form
        #
        if len(Steklov) > 0:
            m = 0
            for bc in Steklov:
                m += Constant(bc.parValue)*u*v*wBottom*ds(bc.value+shift)
        else:
            m = u*v*wBottom*dx

        # assemble
        # if USE_EIGEN:
        #     S, M = EigenMatrix(), EigenMatrix()
            # tempv = EigenVector()
        # else:
        S, M = PETScMatrix(), PETScMatrix()
        # tempv = PETScVector()

        if not np.any(bcs.array() == shift+1):
            # no Dirichlet parts
            assemble(s, tensor=S)
            assemble(m, tensor=M)
        else:
            #
            # with EIGEN we could
            #   apply Dirichlet condition symmetrically
            #   completely remove rows and columns
            #
            # Dirichlet parts are marked with shift+1
            #
            # temp = Constant(0)*v*dx
            bc = DirichletBC(V, Constant(0.0), bcs, shift+1)
            # assemble_system(s, temp, bc, A_tensor=S, b_tensor=tempv)
            # assemble_system(m, temp, bc, A_tensor=M, b_tensor=tempv)
            assemble(s, tensor=S)
            bc.apply(S)
            assemble(m, tensor=M)
            # bc.zero(M)

        # if USE_EIGEN:
        #    M = M.sparray()
        #    M.eliminate_zeros()
        #    print M.shape
        #    indices = M.indptr[:-1] - M.indptr[1:] < 0
        #    M = M[indices, :].tocsc()[:, indices]
        #    S = S.sparray()[indices, :].tocsc()[:, indices]
        #    print M.shape
        #
        # solve the eigenvalue problem
        #
        self.progress("Solving eigenvalue problem.")
        eigensolver = SLEPcEigenSolver(S, M)
        eigensolver.parameters["problem_type"] = "gen_hermitian"
        eigensolver.parameters["solver"] = "krylov-schur"
        if self.target is not None:
            eigensolver.parameters["spectrum"] = "target real"
            eigensolver.parameters["spectral_shift"] = self.target
        else:
            eigensolver.parameters["spectrum"] = "smallest magnitude"
            eigensolver.parameters["spectral_shift"] = -0.01
        eigensolver.parameters["spectral_transform"] = "shift-and-invert"
        eigensolver.solve(self.number)
        self.progress("Generating eigenfunctions.")
        if eigensolver.get_number_converged() == 0:
            return None
        eigf = []
        eigv = []
        if self.deg > 1:
            mesh = refine(mesh)
        W = FunctionSpace(mesh, 'CG', 1)
        for i in range(eigensolver.get_number_converged()):
            pair = eigensolver.get_eigenpair(i)[::2]
            eigv.append(pair[0])
            u = Function(V)
            u.vector()[:] = pair[1]
            eigf.append(interpolate(u, W))
        return eigv, eigf
Exemple #9
0
def _fit_dolfin(x0,
                y0,
                points,
                cells,
                lmbda: float,
                degree: int = 1,
                solver: str = "lsqr"):
    from dolfin import (
        BoundingBoxTree,
        Cell,
        EigenMatrix,
        FacetNormal,
        Function,
        FunctionSpace,
        Mesh,
        MeshEditor,
        Point,
        TestFunction,
        TrialFunction,
        assemble,
        dot,
        ds,
        dx,
        grad,
    )

    def _assemble_eigen(form):
        L = EigenMatrix()
        assemble(form, tensor=L)
        return L

    def _build_eval_matrix(V, points):
        """Build the sparse m-by-n matrix that maps a coefficient set for a function in
        V to the values of that function at m given points."""
        # See <https://www.allanswered.com/post/lkbkm/#zxqgk>
        mesh = V.mesh()

        bbt = BoundingBoxTree()
        bbt.build(mesh)
        dofmap = V.dofmap()
        el = V.element()
        sdim = el.space_dimension()

        rows = []
        cols = []
        data = []
        for i, x in enumerate(points):
            cell_id = bbt.compute_first_entity_collision(Point(*x))
            cell = Cell(mesh, cell_id)
            coordinate_dofs = cell.get_vertex_coordinates()

            rows.append(np.full(sdim, i))
            cols.append(dofmap.cell_dofs(cell_id))

            v = el.evaluate_basis_all(x, coordinate_dofs, cell_id)
            data.append(v)

        rows = np.concatenate(rows)
        cols = np.concatenate(cols)
        data = np.concatenate(data)

        m = len(points)
        n = V.dim()
        matrix = sparse.csr_matrix((data, (rows, cols)), shape=(m, n))
        return matrix

    editor = MeshEditor()
    mesh = Mesh()

    # Convert points, cells to dolfin mesh
    if cells.shape[1] == 2:
        editor.open(mesh, "interval", 1, 1, 1)
    else:
        # can only handle triangles for now
        assert cells.shape[1] == 3
        # topological and geometrical dimension 2
        editor.open(mesh, "triangle", 2, 2, 1)

    editor.init_vertices(len(points))
    editor.init_cells(len(cells))
    for k, point in enumerate(points):
        editor.add_vertex(k, point)
    for k, cell in enumerate(cells.astype(np.uintp)):
        editor.add_cell(k, cell)
    editor.close()

    V = FunctionSpace(mesh, "CG", degree)

    u = TrialFunction(V)
    v = TestFunction(V)

    mesh = V.mesh()
    n = FacetNormal(mesh)

    # omega = assemble(1 * dx(mesh))

    A = _assemble_eigen(dot(grad(u), grad(v)) * dx -
                        dot(n, grad(u)) * v * ds).sparray()
    A *= lmbda

    E = _build_eval_matrix(V, x0)

    # mass matrix
    M = _assemble_eigen(u * v * dx).sparray()

    x = _solve(A, M, E, y0, solver)
    u = Function(V)
    u.vector().set_local(x)
    return u
Exemple #10
0
def fit(x0, y0, V, lmbda, solver, prec_dirichlet_indices=None):
    """We're trying to minimize

       sum_i w_i (f(xi) - yi)^2  +  ||lmbda Delta f||^2_{L^2(Omega)}

    over all functions f from V with weights w_i, lmbda. The discretization of this is

       ||W(E(f) - y)||_2^2 + ||lmbda Delta_h f_h||^2_{M^{-1}}

    where E is the (small and fat) evaluation operator at coordinates x_i, Delta_h is
    the discretization of Delta, and M is the mass matrix. One can either try and
    minimize this equation with a generic method or solve the linear equation

      lmbda A.T M^{-1} A x + E.T E x = E.T y0

    for the extremum x. Unfortunately, solving the linear equation is not
    straightforward. M is spd, A is nonsymmetric and rank-deficient but
    positive-semidefinite. So far, we simply use sparse CG, but a good idea for a
    preconditioner is highly welcome.
    """
    u = TrialFunction(V)
    v = TestFunction(V)

    mesh = V.mesh()
    n = FacetNormal(mesh)

    # omega = assemble(1 * dx(mesh))

    A = _assemble_eigen(dot(grad(u), grad(v)) * dx -
                        dot(n, grad(u)) * v * ds).sparray()
    A *= lmbda

    E = _build_eval_matrix(V, x0)

    # mass matrix
    M = _assemble_eigen(u * v * dx).sparray()

    # Scipy implementations of both LSQR and LSMR can only be used with the standard l_2
    # inner product. This is not sufficient here: We need the M inner product to make
    # sure that the discrete residual is an approximation to the inner product of the
    # continuous problem.
    if solver == "dense-direct":
        # Minv is dense, yikes!
        a = A.toarray()
        m = M.toarray()
        e = E.toarray()
        AT_Minv_A = numpy.dot(a.T, numpy.linalg.solve(m, a)) + numpy.dot(
            e.T, e)
        ET_b = numpy.dot(e.T, y0)
        x = numpy.linalg.solve(AT_Minv_A, ET_b)

    elif solver == "sparse-cg":

        def matvec(x):
            Ax = A.dot(x)
            return A.T.dot(sparse.linalg.spsolve(M, Ax)) + E.T.dot(E.dot(x))

        lop = pykry.LinearOperator((E.shape[1], E.shape[1]), float, dot=matvec)

        ET_b = E.T.dot(y0)
        out = pykry.cg(lop, ET_b, tol=1.0e-10, maxiter=1000)
        x = out.xk

        # import matplotlib.pyplot as plt
        # plt.semilogy(out.resnorms)
        # plt.grid()
        # plt.show()
    else:

        def f(x):
            Ax = A.dot(x)
            Exy = E.dot(x) - y0
            return numpy.dot(Ax, spsolve(M, Ax)) + numpy.dot(Exy, Exy)

        # Set x0 to be the average of y0
        x0 = numpy.full(A.shape[0], numpy.sum(y0) / y0.shape[0])
        out = scipy.optimize.minimize(f, x0, method=solver)
        x = out.x

    u = Function(V)
    u.vector().set_local(x)
    return u
Exemple #11
0
def femsolve():
    
    ''' Bilineaarinen muoto:

        a(u,v) = L(v)
        a(u,v) = (inner(grad(u), grad(v)) + u*v)*dx
        L(v) = f*v*dx - g*v*ds
        g(x) = -du/dx = -u1, x = x1
        u(x0) = u0
        Omega = {xeR|x0<=x<=x1}

    '''

    from dolfin import UnitInterval, FunctionSpace, DirichletBC, TrialFunction
    from dolfin import TestFunction, grad, Constant, Function, solve, inner, dx, ds
    from dolfin import MeshFunction, assemble
    import dolfin
#    from dolfin import set_log_level, PROCESS

    # Create mesh and define function space
    mesh = UnitInterval(30)
    V = FunctionSpace(mesh, 'Lagrange', 2)

    boundaries  = MeshFunction('uint', mesh, mesh.topology().dim()-1)

    boundaries.set_all(0)

    class Left(dolfin.SubDomain):
        def inside(self, x, on_boundary):
            tol = 1E-14   # tolerance for coordinate comparisons
            return on_boundary and abs(x[0]) < tol

    class Right(dolfin.SubDomain):
        def inside(self, x, on_boundary):
            return dolfin.near(x[0], 1.0)
    
    left = Left()
    right = Right()
    
    left.mark(boundaries, 1)
    right.mark(boundaries, 2)

#    def u0_boundary(x):
#        return abs(x[0]) < tol
#    
#    bc = DirichletBC(V, Constant(u0), lambda x: abs(x[0]) < tol)
    
    bcs = [DirichletBC(V, Constant(u0), boundaries, 1)]
    
    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    a = (inner(grad(u), grad(v)) + u*v)*dx
    g = Constant(-u1)
    L = Constant(f)*v*dx - g*v*ds(2)
    
 #   set_log_level(PROCESS)
    # Compute solution
    
    A = assemble(a, exterior_facet_domains=boundaries)
    b = assemble(L, exterior_facet_domains=boundaries)
    for bc in bcs: 
        bc.apply(A, b)
    
    u = Function(V)
    solve(A, u.vector(), b, 'lu')
    
    coor = mesh.coordinates()
    u_array = u.vector().array()
    a = []
    b = []
    for i in range(mesh.num_vertices()):
        a.append(coor[i])
        b.append(u_array[i])
        print('u(%3.2f) = %0.14E'%(coor[i],u_array[i]))
    
    import numpy as np
    np.savez('fem',a,b)
Exemple #12
0
# Improve estimate of eigenvalues for Chebyshev smoothing
PETScOptions.set("mg_levels_esteig_ksp_type", "cg")
PETScOptions.set("mg_levels_ksp_chebyshev_esteig_steps", 20)

# Monitor solver
PETScOptions.set("ksp_monitor")

# Create CG Krylov solver and turn convergence monitoring on
solver = PETScKrylovSolver(MPI.comm_world)
solver.set_from_options()

# Set matrix operator
solver.set_operator(A)

# Compute solution
solver.solve(u.vector(), b)

# Save solution to XDMF format
file = XDMFFile(MPI.comm_world, "elasticity.xdmf")
file.write(u)

unorm = u.vector().norm()
if MPI.rank(mesh.mpi_comm()) == 0:
    print("Solution vector norm:", unorm)

# Save colored mesh partitions in VTK format if running in parallel
# if MPI.size(mesh.mpi_comm()) > 1:
#    File("partitions.pvd") << MeshFunction("size_t", mesh, mesh.topology.dim, \
#                                           MPI.rank(mesh.mpi_comm()))

# Project and write stress field to post-processing file
Exemple #13
0
    def solve(self):
        """ Find eigenvalues for transformed mesh. """
        self.progress("Building mesh.")
        # build transformed mesh
        mesh = self.refineMesh()
        # dim = mesh.topology().dim()
        if self.bcLast:
            mesh = transform_mesh(mesh, self.transformList)
            Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList)
        else:
            Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList)
            mesh = transform_mesh(mesh, self.transformList)
            # boundary conditions computed on non-transformed mesh
            # copy the values to transformed mesh
            fun = FacetFunction("size_t", mesh, shift)
            fun.array()[:] = bcs.array()[:]
            bcs = fun
        ds = Measure('ds', domain=mesh, subdomain_data=bcs)
        V = FunctionSpace(mesh, self.method, self.deg)
        u = TrialFunction(V)
        v = TestFunction(V)
        self.progress("Assembling matrices.")
        wTop = Expression(self.wTop)
        wBottom = Expression(self.wBottom)

        #
        # build stiffness matrix form
        #
        s = dot(grad(u), grad(v)) * wTop * dx
        # add Robin parts
        for bc in Robin:
            s += Constant(bc.parValue) * u * v * wTop * ds(bc.value + shift)

        #
        # build mass matrix form
        #
        if len(Steklov) > 0:
            m = 0
            for bc in Steklov:
                m += Constant(
                    bc.parValue) * u * v * wBottom * ds(bc.value + shift)
        else:
            m = u * v * wBottom * dx

        # assemble
        # if USE_EIGEN:
        #     S, M = EigenMatrix(), EigenMatrix()
        # tempv = EigenVector()
        # else:
        S, M = PETScMatrix(), PETScMatrix()
        # tempv = PETScVector()

        if not np.any(bcs.array() == shift + 1):
            # no Dirichlet parts
            assemble(s, tensor=S)
            assemble(m, tensor=M)
        else:
            #
            # with EIGEN we could
            #   apply Dirichlet condition symmetrically
            #   completely remove rows and columns
            #
            # Dirichlet parts are marked with shift+1
            #
            # temp = Constant(0)*v*dx
            bc = DirichletBC(V, Constant(0.0), bcs, shift + 1)
            # assemble_system(s, temp, bc, A_tensor=S, b_tensor=tempv)
            # assemble_system(m, temp, bc, A_tensor=M, b_tensor=tempv)
            assemble(s, tensor=S)
            bc.apply(S)
            assemble(m, tensor=M)
            # bc.zero(M)

        # if USE_EIGEN:
        #    M = M.sparray()
        #    M.eliminate_zeros()
        #    print M.shape
        #    indices = M.indptr[:-1] - M.indptr[1:] < 0
        #    M = M[indices, :].tocsc()[:, indices]
        #    S = S.sparray()[indices, :].tocsc()[:, indices]
        #    print M.shape
        #
        # solve the eigenvalue problem
        #
        self.progress("Solving eigenvalue problem.")
        eigensolver = SLEPcEigenSolver(S, M)
        eigensolver.parameters["problem_type"] = "gen_hermitian"
        eigensolver.parameters["solver"] = "krylov-schur"
        if self.target is not None:
            eigensolver.parameters["spectrum"] = "target real"
            eigensolver.parameters["spectral_shift"] = self.target
        else:
            eigensolver.parameters["spectrum"] = "smallest magnitude"
            eigensolver.parameters["spectral_shift"] = -0.01
        eigensolver.parameters["spectral_transform"] = "shift-and-invert"
        eigensolver.solve(self.number)
        self.progress("Generating eigenfunctions.")
        if eigensolver.get_number_converged() == 0:
            return None
        eigf = []
        eigv = []
        if self.deg > 1:
            mesh = refine(mesh)
        W = FunctionSpace(mesh, 'CG', 1)
        for i in range(eigensolver.get_number_converged()):
            pair = eigensolver.get_eigenpair(i)[::2]
            eigv.append(pair[0])
            u = Function(V)
            u.vector()[:] = pair[1]
            eigf.append(interpolate(u, W))
        return eigv, eigf
Exemple #14
0
def femsolve():
    ''' Bilineaarinen muoto:

        a(u,v) = L(v)
        a(u,v) = (inner(grad(u), grad(v)) + u*v)*dx
        L(v) = f*v*dx - g*v*ds
        g(x) = -du/dx = -u1, x = x1
        u(x0) = u0
        Omega = {xeR|x0<=x<=x1}

    '''

    from dolfin import UnitInterval, FunctionSpace, DirichletBC, TrialFunction
    from dolfin import TestFunction, grad, Constant, Function, solve, inner, dx, ds
    from dolfin import MeshFunction, assemble
    import dolfin
    #    from dolfin import set_log_level, PROCESS

    # Create mesh and define function space
    mesh = UnitInterval(30)
    V = FunctionSpace(mesh, 'Lagrange', 2)

    boundaries = MeshFunction('uint', mesh, mesh.topology().dim() - 1)

    boundaries.set_all(0)

    class Left(dolfin.SubDomain):
        def inside(self, x, on_boundary):
            tol = 1E-14  # tolerance for coordinate comparisons
            return on_boundary and abs(x[0]) < tol

    class Right(dolfin.SubDomain):
        def inside(self, x, on_boundary):
            return dolfin.near(x[0], 1.0)

    left = Left()
    right = Right()

    left.mark(boundaries, 1)
    right.mark(boundaries, 2)

    #    def u0_boundary(x):
    #        return abs(x[0]) < tol
    #
    #    bc = DirichletBC(V, Constant(u0), lambda x: abs(x[0]) < tol)

    bcs = [DirichletBC(V, Constant(u0), boundaries, 1)]

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    a = (inner(grad(u), grad(v)) + u * v) * dx
    g = Constant(-u1)
    L = Constant(f) * v * dx - g * v * ds(2)

    #   set_log_level(PROCESS)
    # Compute solution

    A = assemble(a, exterior_facet_domains=boundaries)
    b = assemble(L, exterior_facet_domains=boundaries)
    for bc in bcs:
        bc.apply(A, b)

    u = Function(V)
    solve(A, u.vector(), b, 'lu')

    coor = mesh.coordinates()
    u_array = u.vector().array()
    a = []
    b = []
    for i in range(mesh.num_vertices()):
        a.append(coor[i])
        b.append(u_array[i])
        print('u(%3.2f) = %0.14E' % (coor[i], u_array[i]))

    import numpy as np
    np.savez('fem', a, b)
Exemple #15
0
def run_simulation(
        filepath,
        topology_info: int = None,
        top_bc: int = None,
        bot_bc: int = None,
        left_bc: int = None,
        right_bc: int = None,
        geometry: dict = None,
        kappa=3,  #only if geometry is None
        show=True,
        save_solution=False):

    from dolfin import (Mesh, XDMFFile, MeshValueCollection, cpp,
                        FunctionSpace, TrialFunction, TestFunction,
                        DirichletBC, Constant, Measure, inner, nabla_grad,
                        Function, solve, plot, File)
    mesh = Mesh()
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mesh)  # read the complete mesh

    mvc_subdo = MeshValueCollection("size_t", mesh,
                                    mesh.geometric_dimension() - 1)
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mvc_subdo, "subdomains")  # read the diferent subdomians
    subdomains = cpp.mesh.MeshFunctionSizet(mesh, mvc_subdo)

    mvc = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 2)
    with XDMFFile("%s_line.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mvc, "boundary_conditions")  #read the boundary conditions
    boundary = cpp.mesh.MeshFunctionSizet(mesh, mvc)

    # Define function space and basis functions
    V = FunctionSpace(mesh, "CG", 1)
    u = TrialFunction(V)
    v = TestFunction(V)
    # Boundary conditions
    bcs = []
    for bc_id in topology_info.keys():
        if bc_id[-2:] == "bc":
            if bot_bc is not None and bc_id[:3] == "bot":
                bcs.append(
                    DirichletBC(V, Constant(bot_bc), boundary,
                                topology_info[bc_id]))
            elif left_bc is not None and bc_id[:4] == "left":
                bcs.append(
                    DirichletBC(V, Constant(left_bc), boundary,
                                topology_info[bc_id]))
            elif top_bc is not None and bc_id[:3] == "top":
                bcs.append(
                    DirichletBC(V, Constant(top_bc), boundary,
                                topology_info[bc_id]))
            elif right_bc is not None and bc_id[:5] == "right":
                bcs.append(
                    DirichletBC(V, Constant(right_bc), boundary,
                                topology_info[bc_id]))
            else:
                print(bc_id + " Not assigned as boundary condition ")
            #    raise NotImplementedError

    # Define new measures associated with the interior domains and
    # exterior boundaries
    dx = Measure("dx", subdomain_data=subdomains)
    ds = Measure("ds", subdomain_data=boundary)

    f = Constant(0)
    g = Constant(0)
    if geometry is not None:  # run multipatch implementation (Multiple domains)
        a = []
        L = []
        for patch_id in geometry.keys():
            kappa = geometry[patch_id].get("kappa")
            a.append(
                inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) *
                dx(topology_info[patch_id]))
            L.append(f * v * dx(topology_info[patch_id]))
        a = sum(a)
        L = sum(L)
    else:
        a = inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) * dx
        L = f * v * dx

    ## Redefine u as a function in function space V for the solution
    u = Function(V)
    # Solve
    solve(a == L, u, bcs)
    u.rename('u', 'Temperature')
    # Save solution to file in VTK format
    print('  [+] Output to %s_solution.pvd' % filepath.split('.')[0])
    vtkfile = File('%s_solution.pvd' % filepath.split('.')[0])
    vtkfile << u

    if show:
        import matplotlib
        matplotlib.use("Qt5Agg")
        # Plot solution and gradient
        plot(u, title="Temperature")
        plt.gca().view_init(azim=-90, elev=90)
        plt.show()

    dofs = V.tabulate_dof_coordinates().reshape(
        V.dim(),
        mesh.geometry().dim())  #coordinates of nodes
    vals = u.vector().get_local()  #temperature at nodes

    if save_solution:
        from dolfin import HDF5File, MPI
        output_file = HDF5File(MPI.comm_world,
                               filepath.split('.')[0] + "_solution_field.h5",
                               "w")
        output_file.write(u, "solution")
        output_file.close()
    u.set_allow_extrapolation(True)
    return dofs, vals, mesh, u