Esempio n. 1
0
 def test_bem_perf(self):
     mesh = df.UnitCubeMesh(15, 15, 15)
     boundary_mesh = df.BoundaryMesh(mesh, 'exterior', False)
     c = time_counter.counter()
     while c.next():
         df.BoundaryMesh(mesh, 'exterior', False)
     print "Boundary mesh computation for %s: %s" % (mesh, c)
     c = time_counter.counter()
     while c.next():
         bem, _ = compute_bem_fk(boundary_mesh)
         n = bem.shape[0]
     print "FK BEM computation for %dx%d (%.2f Mnodes/sec): %s" % (
         n, n, c.calls_per_sec(n * n / 1e6), c)
     c = time_counter.counter()
     while c.next():
         bem, _ = compute_bem_gcr(boundary_mesh)
     print "GCR BEM computation for %dx%d (%.2f Mnodes/sec): %s" % (
         n, n, c.calls_per_sec(n * n / 1e6), c)
Esempio n. 2
0
def run_measurements(m, mesh, unit_length, tol, repetitions=10, H_expected=None, name="", skip=[]):
    S3 = df.VectorFunctionSpace(mesh, "CG", 1)
    m = vector_valued_function(m, S3)
    Ms = 1
    bem, boundary_to_global = compute_bem_fk(df.BoundaryMesh(mesh, 'exterior', False))

    if H_expected is not None:
        H = vector_valued_function(H_expected, S3)
        H_expected = H.vector().array()
    else:
        # use default/default as reference then.
        demag = fk.FKDemag()
        demag.precomputed_bem(bem, boundary_to_global)
        demag.setup(S3, m, Ms, unit_length)
        H_expected = demag.compute_field()
        del(demag)

    if name == "":
        pass
    else:
        name = name + "_"

    runner = create_measurement_runner(S3, m, Ms, unit_length,
                                       H_expected, tol, repetitions,
                                       bem, boundary_to_global)

    solvers = [s[0] for s in df.krylov_solver_methods()]
    preconditioners = [p[0] for p in df.krylov_solver_preconditioners()]

    results_1, failed_1 = runner("first linear solve",
                                 "phi_1_solver", solvers,
                                 "phi_1_preconditioner", preconditioners,
                                 skip,
                                 "{}timings_log_1.txt".format(name),
                                 "{}results_1.pickled".format(name))

    results_2, failed_2 = runner("second linear solve",
                                 "phi_2_solver", solvers,
                                 "phi_2_preconditioner", preconditioners,
                                 skip,
                                 "{}timings_log_2.txt".format(name),
                                 "{}results_2.pickled".format(name))

    return solvers, preconditioners, results_1, failed_1, results_2, failed_2
Esempio n. 3
0
def run_demag_benchmark(m,
                        mesh,
                        unit_length,
                        tol,
                        repetitions=10,
                        name="bench",
                        H_expected=None):
    S3 = df.VectorFunctionSpace(mesh, "CG", 1)
    m = vector_valued_function(m, S3)
    Ms = 1

    # pre-compute BEM to save time
    bem, boundary_to_global = compute_bem_fk(
        df.BoundaryMesh(mesh, 'exterior', False))

    if H_expected is not None:
        H = vector_valued_function(H_expected, S3)
        H_expected = H.vector().array()
    else:  # if no H_expected was passed, use default/default as reference
        demag = fk.FKDemag()
        demag.precomputed_bem(bem, boundary_to_global)
        demag.setup(S3, m, Ms, unit_length)
        H_expected = demag.compute_field()
        del (demag)

    # gather all solvers and preconditioners
    solvers = [s[0] for s in df.krylov_solver_methods()]
    preconditioners = [p[0] for p in df.krylov_solver_preconditioners()]

    benchmark = prepare_benchmark(S3, m, Ms, unit_length, H_expected, tol,
                                  repetitions, bem, boundary_to_global)
    results_1 = benchmark("first linear solve",
                          "phi_1_solver",
                          solvers,
                          "phi_1_preconditioner",
                          preconditioners,
                          name=name + "_1")
    results_2 = benchmark("second linear solve",
                          "phi_2_solver",
                          solvers,
                          "phi_2_preconditioner",
                          preconditioners,
                          name=name + "_2")
    return solvers, preconditioners, results_1, results_2
Esempio n. 4
0
    def run_bem_computation_test(self, mesh):
        S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3)
        m = df.interpolate(df.Constant((1, 0, 0)), S3)
        Ms = 1.0

        bem_magpar, g2finmag = belement.BEM_matrix(mesh)
        bem_finmag = np.zeros(bem_magpar.shape)
        bem, b2g = compute_bem_fk(df.BoundaryMesh(mesh, 'exterior', False))
        for i_dolfin in xrange(bem.shape[0]):
            i_finmag = g2finmag[b2g[i_dolfin]]

            for j_dolfin in xrange(bem.shape[0]):
                j_finmag = g2finmag[b2g[j_dolfin]]
                bem_finmag[i_finmag, j_finmag] = bem[i_dolfin, j_dolfin]
        if np.max(np.abs(bem_finmag - bem_magpar)) > 1e-12:
            print "Finmag:", np.round(bem_finmag, 4)
            print "Magpar:", np.round(bem_magpar, 4)
            print "Difference:", np.round(bem_magpar - bem_finmag, 4)
            self.fail("Finmag and magpar computation of BEM differ, mesh: " +
                      str(mesh))
Esempio n. 5
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()
Esempio n. 6
0
    def setup(self, DG3, m, Ms, unit_length=1):
        """
        Setup the FKDemag instance. Usually called automatically by the Simulation object.

        *Arguments*

        S3: dolfin.VectorFunctionSpace

            The finite element space the magnetisation is defined on.

        m: dolfin.Function on S3

            The unit magnetisation.

        Ms: float

            The saturation magnetisation in A/m.

        unit_length: float

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

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

        mesh = DG3.mesh()
        self.S1 = df.FunctionSpace(mesh, "Lagrange", 1)
        self.S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1)
        self.dim = mesh.topology().dim()

        self.n = df.FacetNormal(mesh)

        self.DG3 = DG3

        self._test1 = df.TestFunction(self.S1)
        self._trial1 = df.TrialFunction(self.S1)
        self._test3 = df.TestFunction(self.S3)
        self._trial3 = df.TrialFunction(self.S3)
        self._test_dg3 = df.TestFunction(self.DG3)
        self._trial_dg3 = df.TrialFunction(self.DG3)

        # for computation of energy
        self._nodal_volumes = nodal_volume(self.S1, unit_length)
        self._H_func = df.Function(
            DG3)  # we will copy field into this when we need the energy
        self._E_integrand = -0.5 * mu0 * df.dot(self._H_func, self.m * self.Ms)
        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, 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'])
        self._laplace_solver.parameters["preconditioner"][
            "same_nonzero_pattern"] = True
        with fk_timed('compute BEM'):
            if not hasattr(self, "_bem"):
                self._bem, self._b2g_map = compute_bem_fk(
                    df.BoundaryMesh(mesh, 'exterior', False))
        self._phi_1 = df.Function(
            self.S1)  # solution of inhomogeneous Neumann problem
        self._phi_2 = df.Function(
            self.S1)  # solution of Laplace equation inside domain
        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 * df.inner(self._trial_dg3, df.grad(self._test1)) * df.dx)

        self._setup_gradient_computation()
Esempio n. 7
0
 def test_bem_netgen(self):
     module_dir = os.path.dirname(os.path.abspath(__file__))
     netgen_mesh = df.Mesh(
         os.path.join(module_dir, "bem_netgen_test_mesh.xml.gz"))
     bem, b2g_map = compute_bem_fk(
         df.BoundaryMesh(netgen_mesh, 'exterior', False))
Esempio n. 8
0
    return H, runtime

try:
    results = np.loadtxt(results_file)
except IOError:
    results = np.zeros((len(maxhs), 4))
    for i, maxh in enumerate(maxhs):
        print "Mesh {}/{} with maxh = {:.3}.".format(i + 1, len(maxhs), maxh)
        mesh = create_mesh(maxh)
        S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1)
        m_function = df.Function(S3)
        m_function.assign(df.Constant(m_0))
        m = Field(S3, m_function)

        # Pre-compute BEM to save time.
        bem, b2g_map = compute_bem_fk(df.BoundaryMesh(mesh, 'exterior', False))

        print "Computing demagnetising field with default solver parameters..."
        H_default, runtime_default = run_demag(
            repetitions, default_params, m, Ms, unit_length, bem, b2g_map)

        print "Computing demagnetising field with optimised solver parameters..."
        H_opt, runtime_opt = run_demag(
            repetitions, opt_params, m, Ms, unit_length, bem, b2g_map)

        results[i, 0] = mesh.num_vertices()
        results[i, 1] = runtime_default
        results[i, 2] = runtime_opt
        results[i, 3] = np.max(np.abs(H_default - H_opt))
        np.savetxt(results_file, results)  # Save results after every step.