Пример #1
0
    def test_to_DG0(self):
        subdomains = (df.CompiledSubDomain('near(x[0], 0.5)'), df.DomainBoundary())
        
        for subd in subdomains: 
            mesh = df.UnitCubeMesh(4, 4, 4)
            facet_f = df.MeshFunction('size_t', mesh, 2, 0)
            subd.mark(facet_f, 1)
                
            submesh = EmbeddedMesh(facet_f, 1)

            transfer = SubMeshTransfer(mesh, submesh)

            V = df.FunctionSpace(mesh, 'Discontinuous Lagrange Trace', 0)
            Vsub = df.FunctionSpace(submesh, 'DG', 0)
                
            to_Vsub = transfer.compute_map(Vsub, V, strict=False)
            # Set degree 0 to get the quad order right
            f = df.Expression('x[0] + 2*x[1] - x[2]', degree=0)
                
            fV = df.interpolate(f, V)
            fsub = df.Function(Vsub)
                
            to_Vsub(fsub, fV)
                
            error = df.inner(fsub - f, fsub - f)*df.dx(domain=submesh)
            error = df.sqrt(abs(df.assemble(error)))
                
            self.assertTrue(error < 1E-13)
Пример #2
0
    def __init__(self, u, boundary_is_streamline=False, degree=1):
        """
        Heavily based on
        https://github.com/mikaem/fenicstools/blob/master/fenicstools/Streamfunctions.py
        
        Stream function for a given general 2D velocity field.
        The boundary conditions are weakly imposed through the term
        
            inner(q, grad(psi)*n)*ds, 
        
        where grad(psi) = [-v, u] is set on all boundaries. 
        This should work for any collection of boundaries: 
        walls, inlets, outlets etc.    
        """
        Vu = u[0].function_space()
        mesh = Vu.mesh()

        # Check dimension
        if not mesh.geometry().dim() == 2:
            df.error("Stream-function can only be computed in 2D.")

        # Define the weak form
        V = df.FunctionSpace(mesh, 'CG', degree)
        q = df.TestFunction(V)
        psi = df.TrialFunction(V)
        n = df.FacetNormal(mesh)
        a = df.dot(df.grad(q), df.grad(psi)) * df.dx
        L = df.dot(q, df.curl(u)) * df.dx

        if boundary_is_streamline:
            # Strongly set psi = 0 on entire domain boundary
            self.bcs = [df.DirichletBC(V, df.Constant(0), df.DomainBoundary())]
            self.normalize = False
        else:
            self.bcs = []
            self.normalize = True
            L = L + q * (n[1] * u[0] - n[0] * u[1]) * df.ds

        # Create preconditioned iterative solver
        solver = df.PETScKrylovSolver('gmres', 'hypre_amg')
        solver.parameters['nonzero_initial_guess'] = True
        solver.parameters['relative_tolerance'] = 1e-10
        solver.parameters['absolute_tolerance'] = 1e-10

        # Store for later computation
        self.psi = df.Function(V)
        self.A = df.assemble(a)
        self.L = L
        self.mesh = mesh
        self.solver = solver
        self._triangulation = None
Пример #3
0
 def init_with_mesh (self, mesh ):
     """initialise the boundary condition using the mesh.
     
     A mesh function is constructed from the mesh and the boundary region is marked.
     
     @param mesh: The mesh on which the boundary condition is to be applied
     """
     mesh_function = dolfin.MeshFunction(
                 'uint', mesh, mesh.topology().dim()-1)
     mesh_function.set_all ( 0 )
     walls = dolfin.DomainBoundary()
     walls.mark(mesh_function, 999)
             
     self.init_with_meshfunction(mesh_function, 999)
Пример #4
0
    def solve_laplace_inside(self, function, solverparams=None):
        """Take a functions boundary data as a dirichlet BC and solve
            a laplace equation"""
        bc = df.DirichletBC(self.V, function, df.DomainBoundary())
        A = self.poisson_matrix.copy()
        b = self.laplace_zeros  # .copy()
        bc.apply(A, b)

        if self.bench:
            bench.solve(A, function.vector(), b, benchmark=True)
        else:
            demag_timer.start("2nd linear solve", self.__class__.__name__)
            self.laplace_iter = self.laplace_solver.solve(
                A, function.vector(), b)
            demag_timer.stop("2nd linear solve", self.__class__.__name__)
        return function
Пример #5
0
    def set_dofs(self, dofs):
        x_r = np.real(dofs).copy()
        x_i = np.imag(dofs).copy()
        self.E_r.vector()[:] = x_r
        self.E_i.vector()[:] = x_i
        self.dofs = dofs

        boundary = dolfin.DomainBoundary()
        E_r_dirich = dolfin.DirichletBC(self.function_space, self.E_r,
                                        boundary)
        E_i_dirich = dolfin.DirichletBC(self.function_space, self.E_i,
                                        boundary)
        x_r_dirich = as_dolfin_vector(np.zeros(len(x_r)))
        x_i_dirich = as_dolfin_vector(np.zeros(len(x_r)))
        E_r_dirich.apply(x_r_dirich)
        E_i_dirich.apply(x_i_dirich)
        self.dirich_dofs = x_r_dirich.array() + 1j * x_i_dirich.array()
        self.functional.set_E_dofs(dofs)
Пример #6
0
 def __init__(self, mesh, boundary_facefun=None, boundary_value=1):
     """Find and mark the edges that occur on a set of boundary faces
 
     @param mesh: A dolfin mesh object
     @keyword boundary_facefun: a face mesh function that describes the
         faces to be considered 
         (default: None).
     @keyword boundary_value: the mesh function value marking the boundary faces
         (default: 1)
     """
     self.mesh = mesh
     if boundary_facefun is None:
         boundary_facefun = dolfin.FaceFunction('uint', mesh)
         boundary_facefun.set_all(0)
         domain_boundary = dolfin.DomainBoundary()
         domain_boundary.mark(boundary_facefun, boundary_value)
     self.boundary_facefun = boundary_facefun
     self.boundary_value = boundary_value
     self.ensure_initialised = EnsureInitialised(self.mesh)
Пример #7
0
    def _compute_magnetic_potential(self):
        # compute _phi_1 on the whole domain
        g_1 = self._Ms_times_divergence * self.m.vector()
        with fk_timed("first linear solve"):
            self._poisson_solver.solve(self._phi_1.vector(), g_1)

        # compute _phi_2 on the boundary using the Dirichlet boundary
        # conditions we get from BEM * _phi_1 on the boundary.
        with fk_timed("using boundary conditions"):
            phi_1 = self._phi_1.vector()[self._b2g_map]
            self._phi_2.vector()[self._b2g_map[:]] = np.dot(
                self._bem, phi_1.array())
            boundary_condition = df.DirichletBC(self.S1, self._phi_2,
                                                df.DomainBoundary())
            A = self._poisson_matrix.copy()
            b = self._laplace_zeros
            boundary_condition.apply(A, b)

        # compute _phi_2 on the whole domain
        with fk_timed("second linear solve"):
            self._laplace_solver.solve(A, self._phi_2.vector(), b)

        # add _phi_1 and _phi_2 to obtain magnetic potential
        self._phi.vector()[:] = self._phi_1.vector() + self._phi_2.vector()
def _discretize_fenics():

    # assemble system matrices - FEniCS code
    ########################################

    import dolfin as df

    mesh = df.UnitSquareMesh(GRID_INTERVALS, GRID_INTERVALS, 'crossed')
    V = df.FunctionSpace(mesh, 'Lagrange', FENICS_ORDER)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)

    diffusion = df.Expression(
        '(lower0 <= x[0]) * (open0 ? (x[0] < upper0) : (x[0] <= upper0)) *'
        '(lower1 <= x[1]) * (open1 ? (x[1] < upper1) : (x[1] <= upper1))',
        lower0=0.,
        upper0=0.,
        open0=0,
        lower1=0.,
        upper1=0.,
        open1=0,
        element=df.FunctionSpace(mesh, 'DG', 0).ufl_element())

    def assemble_matrix(x, y, nx, ny):
        diffusion.user_parameters['lower0'] = x / nx
        diffusion.user_parameters['lower1'] = y / ny
        diffusion.user_parameters['upper0'] = (x + 1) / nx
        diffusion.user_parameters['upper1'] = (y + 1) / ny
        diffusion.user_parameters['open0'] = (x + 1 == nx)
        diffusion.user_parameters['open1'] = (y + 1 == ny)
        return df.assemble(
            df.inner(diffusion * df.nabla_grad(u), df.nabla_grad(v)) * df.dx)

    mats = [
        assemble_matrix(x, y, XBLOCKS, YBLOCKS) for x in range(XBLOCKS)
        for y in range(YBLOCKS)
    ]
    mat0 = mats[0].copy()
    mat0.zero()
    h1_mat = df.assemble(df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx)

    f = df.Constant(1.) * v * df.dx
    F = df.assemble(f)

    bc = df.DirichletBC(V, 0., df.DomainBoundary())
    for m in mats:
        bc.zero(m)
    bc.apply(mat0)
    bc.apply(h1_mat)
    bc.apply(F)

    # wrap everything as a pyMOR model
    ##################################

    # FEniCS wrappers
    from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator, FenicsVisualizer

    # define parameter functionals (same as in pymor.analyticalproblems.thermalblock)
    parameter_functionals = [
        ProjectionParameterFunctional(component_name='diffusion',
                                      component_shape=(YBLOCKS, XBLOCKS),
                                      index=(YBLOCKS - y - 1, x))
        for x in range(XBLOCKS) for y in range(YBLOCKS)
    ]

    # wrap operators
    ops = [FenicsMatrixOperator(mat0, V, V)
           ] + [FenicsMatrixOperator(m, V, V) for m in mats]
    op = LincombOperator(ops, [1.] + parameter_functionals)
    rhs = VectorOperator(FenicsVectorSpace(V).make_array([F]))
    h1_product = FenicsMatrixOperator(h1_mat, V, V, name='h1_0_semi')

    # build model
    visualizer = FenicsVisualizer(FenicsVectorSpace(V))
    parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.)
    fom = StationaryModel(op,
                          rhs,
                          products={'h1_0_semi': h1_product},
                          parameter_space=parameter_space,
                          visualizer=visualizer)

    return fom
Пример #9
0
def _discretize_fenics(xblocks, yblocks, grid_num_intervals, element_order):

    # assemble system matrices - FEniCS code
    ########################################

    import dolfin as df
    mesh = df.UnitSquareMesh(grid_num_intervals, grid_num_intervals, 'crossed')
    V = df.FunctionSpace(mesh, 'Lagrange', element_order)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)

    diffusion = df.Expression('(lower0 <= x[0]) * (open0 ? (x[0] < upper0) : (x[0] <= upper0)) *'
                              '(lower1 <= x[1]) * (open1 ? (x[1] < upper1) : (x[1] <= upper1))',
                              lower0=0., upper0=0., open0=0,
                              lower1=0., upper1=0., open1=0,
                              element=df.FunctionSpace(mesh, 'DG', 0).ufl_element())

    def assemble_matrix(x, y, nx, ny):
        diffusion.user_parameters['lower0'] = x/nx
        diffusion.user_parameters['lower1'] = y/ny
        diffusion.user_parameters['upper0'] = (x + 1)/nx
        diffusion.user_parameters['upper1'] = (y + 1)/ny
        diffusion.user_parameters['open0'] = (x + 1 == nx)
        diffusion.user_parameters['open1'] = (y + 1 == ny)
        return df.assemble(df.inner(diffusion * df.nabla_grad(u), df.nabla_grad(v)) * df.dx)

    mats = [assemble_matrix(x, y, xblocks, yblocks)
            for x in range(xblocks) for y in range(yblocks)]
    mat0 = mats[0].copy()
    mat0.zero()
    h1_mat = df.assemble(df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx)
    l2_mat = df.assemble(u * v * df.dx)

    f = df.Constant(1.) * v * df.dx
    F = df.assemble(f)

    bc = df.DirichletBC(V, 0., df.DomainBoundary())
    for m in mats:
        bc.zero(m)
    bc.apply(mat0)
    bc.apply(h1_mat)
    bc.apply(F)

    # wrap everything as a pyMOR model
    ##################################

    # FEniCS wrappers
    from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator, FenicsVisualizer

    # generic pyMOR classes
    from pymor.models.basic import StationaryModel
    from pymor.operators.constructions import LincombOperator, VectorOperator
    from pymor.parameters.functionals import ProjectionParameterFunctional
    from pymor.parameters.spaces import CubicParameterSpace

    # define parameter functionals (same as in pymor.analyticalproblems.thermalblock)
    def parameter_functional_factory(x, y):
        return ProjectionParameterFunctional(component_name='diffusion',
                                             component_shape=(yblocks, xblocks),
                                             index=(yblocks - y - 1, x),
                                             name=f'diffusion_{x}_{y}')
    parameter_functionals = tuple(parameter_functional_factory(x, y)
                                  for x in range(xblocks) for y in range(yblocks))

    # wrap operators
    ops = [FenicsMatrixOperator(mat0, V, V)] + [FenicsMatrixOperator(m, V, V) for m in mats]
    op = LincombOperator(ops, (1.,) + parameter_functionals)
    rhs = VectorOperator(FenicsVectorSpace(V).make_array([F]))
    h1_product = FenicsMatrixOperator(h1_mat, V, V, name='h1_0_semi')
    l2_product = FenicsMatrixOperator(l2_mat, V, V, name='l2')

    # build model
    visualizer = FenicsVisualizer(FenicsVectorSpace(V))
    parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.)
    fom = StationaryModel(op, rhs, products={'h1_0_semi': h1_product,
                                             'l2': l2_product},
                          parameter_space=parameter_space,
                          visualizer=visualizer)

    return fom
Пример #10
0
    def setup(self, m, Ms, unit_length=1):
        """
        Setup the FKDemag instance. Usually called automatically by the
        Simulation object.

        *Arguments*

        m: finmag.Field

            The unit magnetisation on a finite element space.

        Ms: float

            The saturation magnetisation in A/m.

        unit_length: float

            The length (in m) represented by one unit on the mesh. Default 1.

        """
        assert isinstance(m, Field)
        assert isinstance(Ms, Field)

        self.m = m
        self.Ms = Ms
        self.unit_length = unit_length
        self.S1 = df.FunctionSpace(self.m.mesh(), "Lagrange", 1)

        self._test1 = df.TestFunction(self.S1)
        self._trial1 = df.TrialFunction(self.S1)
        self._test3 = df.TestFunction(self.m.functionspace)
        self._trial3 = df.TrialFunction(self.m.functionspace)

        # for computation of energy
        self._nodal_volumes = nodal_volume(self.S1, unit_length)
        self._H_func = df.Function(m.functionspace)  # we will copy field into
        # this when we need the
        # energy
        self._E_integrand = -0.5 * mu0 * \
            df.dot(self._H_func, self.m.f * self.Ms.f)
        self._E = self._E_integrand * df.dx
        self._nodal_E = df.dot(self._E_integrand, self._test1) * df.dx
        self._nodal_E_func = df.Function(self.S1)

        # for computation of field and scalar magnetic potential
        self._poisson_matrix = self._poisson_matrix()
        self._laplace_zeros = df.Function(self.S1).vector()

        # determine the solver type to be used (Krylov or LU); if the kwarg
        # 'solver_type' is not provided, try to read the setting from the
        # .finmagrc file; use 'Krylov' if this fails.
        solver_type = self.solver_type
        if solver_type is None:
            solver_type = configuration.get_config_option(
                'demag', 'solver_type', 'Krylov')
        if solver_type == 'None':  # if the user set 'solver_type = None' in
            # the .finmagrc file, solver_type will be a
            # string so we need to catch this here.
            solver_type = 'Krylov'
        logger.debug("Using {} solver for demag.".format(solver_type))

        if solver_type == 'Krylov':
            self._poisson_solver = df.KrylovSolver(
                self._poisson_matrix.copy(), self.parameters['phi_1_solver'],
                self.parameters['phi_1_preconditioner'])
            self._poisson_solver.parameters.update(self.parameters['phi_1'])
            self._laplace_solver = df.KrylovSolver(
                self.parameters['phi_2_solver'],
                self.parameters['phi_2_preconditioner'])
            self._laplace_solver.parameters.update(self.parameters['phi_2'])
            # We're setting 'same_nonzero_pattern=True' to enforce the
            # same matrix sparsity pattern across different demag solves,
            # which should speed up things.
            #self._laplace_solver.parameters["preconditioner"][
            #    "structure"] = "same_nonzero_pattern"
        elif solver_type == 'LU':
            self._poisson_solver = df.LUSolver(self._poisson_matrix.copy())
            self._laplace_solver = df.LUSolver()
            self._poisson_solver.parameters["reuse_factorization"] = True
            self._laplace_solver.parameters["reuse_factorization"] = True
        else:
            raise ValueError(
                "Argument 'solver_type' must be either 'Krylov' or 'LU'. "
                "Got: '{}'".format(solver_type))

        with fk_timer('compute BEM'):
            if not hasattr(self, "_bem"):
                if self.macrogeometry is not None:
                    Ts = self.macrogeometry.compute_Ts(self.m.mesh())
                    pbc = BMatrixPBC(self.m.mesh(), Ts)
                    self._b2g_map = np.array(pbc.b2g_map, dtype=np.int)
                    self._bem = pbc.bm
                else:
                    self._bem, self._b2g_map = compute_bem_fk(
                        df.BoundaryMesh(self.m.mesh(), 'exterior', False))
        logger.debug(
            "Boundary element matrix uses {:.2f} MB of memory.".format(
                self._bem.nbytes / 1024.**2))
        # solution of inhomogeneous Neumann problem
        self._phi_1 = df.Function(self.S1)
        # solution of Laplace equation inside domain
        self._phi_2 = df.Function(self.S1)
        self._phi = df.Function(self.S1)  # magnetic potential phi_1 + phi_2

        # To be applied to the vector field m as first step of computation of
        # _phi_1.  This gives us div(M), which is equal to Laplace(_phi_1),
        # equation which is then solved using _poisson_solver.
        self._Ms_times_divergence = df.assemble(
            self.Ms.f * df.inner(self._trial3, df.grad(self._test1)) * df.dx)

        # we move the boundary condition here to avoid create a instance each
        # time when compute the magnetic potential
        self.boundary_condition = df.DirichletBC(self.S1, self._phi_2,
                                                 df.DomainBoundary())
        self.boundary_condition.apply(self._poisson_matrix)

        self._setup_gradient_computation()
Пример #11
0
v = dolfin.TestFunction(V)
u = dolfin.TrialFunction(V)

s = dolfin.inner(dolfin.curl(v), dolfin.curl(u))*dolfin.dx
t = dolfin.inner(v, u)*dolfin.dx

S = dolfin.PETScMatrix()
T = dolfin.PETScMatrix()

dolfin.assemble(s, tensor=S)
dolfin.assemble(t, tensor=T)
print(S.size(1))

markers=dolfin.MeshFunction('size_t',mesh,1)
markers.set_all(0)
dolfin.DomainBoundary().mark(markers,1)

electric_wall = dolfin.DirichletBC(V, 
                                   dolfin.Constant(0.0),
                                   markers,
                                   1)
electric_wall.apply(S)
electric_wall.apply(T)

#from scipy.linalg import eig
#lambds, vectors=eig(S.array(),T.array())
# Solve the eigensystem
esolver = dolfin.SLEPcEigenSolver(S,T)
esolver.solve(S.size(1))

res=[esolver.get_eigenpair(i) for i in range(esolver.get_number_converged())]
Пример #12
0
    def setup(self, m, Ms, unit_length=1):

        self.m = m
        self.Ms = Ms
        self.unit_length = unit_length

        mesh = m.mesh()
        self.S1 = df.FunctionSpace(mesh, "Lagrange", 1)
        self.dim = mesh.topology().dim()

        self._test1 = df.TestFunction(self.S1)
        self._trial1 = df.TrialFunction(self.S1)
        self._test3 = df.TestFunction(self.m.functionspace)
        self._trial3 = df.TrialFunction(self.m.functionspace)

        # for computation of energy
        self._nodal_volumes = nodal_volume(self.S1, unit_length)
        # we will copy field into this when we need the energy
        self._H_func = df.Function(self.m.functionspace)
        self._E_integrand = -0.5 * mu0 * \
            df.dot(self._H_func, self.m.f * self.Ms.f)
        self._E = self._E_integrand * df.dx
        self._nodal_E = df.dot(self._E_integrand, self._test1) * df.dx
        self._nodal_E_func = df.Function(self.S1)

        # for computation of field and scalar magnetic potential
        self._poisson_matrix = self._poisson_matrix()
        self._poisson_solver = df.KrylovSolver(
            self._poisson_matrix.copy(), self.parameters['phi_1_solver'],
            self.parameters['phi_1_preconditioner'])
        self._poisson_solver.parameters.update(self.parameters['phi_1'])
        self._laplace_zeros = df.Function(self.S1).vector()
        self._laplace_solver = df.KrylovSolver(
            self.parameters['phi_2_solver'],
            self.parameters['phi_2_preconditioner'])
        self._laplace_solver.parameters.update(self.parameters['phi_2'])
        # We're setting 'same_nonzero_pattern=True' to enforce the
        # same matrix sparsity pattern across different demag solves,
        # which should speed up things.
        self._laplace_solver.parameters["preconditioner"][
            "structure"] = "same_nonzero_pattern"

        # solution of inhomogeneous Neumann problem
        self._phi_1 = df.Function(self.S1)
        # solution of Laplace equation inside domain
        self._phi_2 = df.Function(self.S1)
        self._phi = df.Function(self.S1)  # magnetic potential phi_1 + phi_2

        # To be applied to the vector field m as first step of computation of _phi_1.
        # This gives us div(M), which is equal to Laplace(_phi_1), equation
        # which is then solved using _poisson_solver.
        self._Ms_times_divergence = df.assemble(
            self.Ms.f * df.inner(self._trial3, df.grad(self._test1)) * df.dx)

        # we move the bounday condition here to avoid create a instance each time when compute the
        # magnetic potential
        self.boundary_condition = df.DirichletBC(self.S1, self._phi_2,
                                                 df.DomainBoundary())
        self.boundary_condition.apply(self._poisson_matrix)

        self._setup_gradient_computation()

        self.mesh = self.m.mesh()

        self.bmesh = df.BoundaryMesh(self.mesh, 'exterior', False)
        #self.b2g_map = self.bmesh.vertex_map().array()
        self._b2g_map = self.bmesh.entity_map(0).array()

        self.compute_triangle_normal()

        self.__compute_bsa()

        fast_sum = FastSum(p=self.p,
                           mac=self.mac,
                           num_limit=self.num_limit,
                           correct_factor=self.correct_factor,
                           type_I=self.type_I)

        coords = self.bmesh.coordinates()
        face_nodes = np.array(self.bmesh.cells(), dtype=np.int32)

        fast_sum.init_mesh(coords, self.t_normals, face_nodes, self.vert_bsa)
        self.fast_sum = fast_sum

        self.phi2_b = np.zeros(self.bmesh.num_vertices())