Ejemplo n.º 1
0
    def field(self, state, x=None, lump=True):
        cache = self._assemble_cache
        if cache.requires_update(state):
            u = TrialFunction(state.FunctionSpace())
            w = TestFunction(state.VectorFunctionSpace())
            cache.A = assemble(-state.material.ms * inner(grad(u), w) *
                               state.dx("magnetic"))

        with Timer("Demag Field"):
            return super(DemagField, self).field(
                state, x, lump, lambda state: cache.A * self.u(state).vector())
Ejemplo n.º 2
0
    def field(self, state, x=None, lump=True):
        cache = self._assemble_cache
        if cache.requires_update(state):
            m = TrialFunction(state.VectorFunctionSpace())
            w = TestFunction(state.VectorFunctionSpace())
            cache.A = assemble(
                self._f(state) * Dx(m[i], j) * Dx(w[i], j) / Constants.gamma *
                state.dx("magnetic"))

        with Timer("Exchange Field"):
            return super(ExchangeField,
                         self).field(state, x, lump,
                                     lambda state: cache.A * state.m.vector())
Ejemplo n.º 3
0
    def u(self, state):
        """
    Calculate the demagnetization-field potential u for a given simulation state

    *Arguments*
      state (:class:`State`)
        The simulation state
    """
        cache = self._result_cache
        if cache.requires_update(state):
            with Timer("Demag Potential"):
                cache.u = self.solver.calculate(state, state.m)
        return cache.u
Ejemplo n.º 4
0
  def step(self, state, dt):
    """
    Calculate :math:`\\vec{s}(t+\Delta t)` for a given timestep.

    *Arguments*
      state (:class:`State`)
        The simulation state.
      dt (:class:`float`)
        The time-step size.
    """

    with Timer("Spin-Diffusion Step"):
      # regions
      Omega = 'conducting'
      omega = 'magnetic'

      # Functions Spaces ...
      VV   = state.VectorFunctionSpace()
      s    = TrialFunction(VV)   # s_i+1
      zeta = TestFunction(VV)    # zeta

      D0x2       = state.material.D0 * Constant(2.0)
      beta       = state.material.beta
      beta_prime = state.material.beta_prime
      lambda_sf  = state.material.lambda_sf
      lambda_j   = state.material.lambda_j

      grad = lambda x: transpose(nabla_grad(x))
      n    = FacetNormal(state.mesh)

      # Forms
      a = inner(s, zeta) / Constant(dt) * state.dx(Omega)                                                                                         \
        + D0x2 / Constant(state.scale**2) * inner(grad(s), grad(zeta)) * state.dx(Omega)                                                          \
        - D0x2 / Constant(state.scale**2) * beta * beta_prime * inner(outer(state.m, transpose(grad(s)) * state.m), grad(zeta)) * state.dx(omega) \
        + D0x2 / lambda_sf**2 * inner(s, zeta) * state.dx(Omega)                                                                                  \
        + D0x2 / lambda_j**2 * inner(cross(s, state.m), zeta) * state.dx(omega)

      L = inner(state.s, zeta) / Constant(dt) * state.dx(Omega)                                                                                   \
        + beta * Constant(Constants.mu_b / Constants.e / state.scale) * inner(outer(state.m, state.j), grad(zeta)) * state.dx(omega)              \
        - beta * Constant(Constants.mu_b / Constants.e / state.scale) * inner(state.m, zeta) * inner(state.j, n) * state.ds('outermagnet')

      # Solve system
      A, b = assemble_system(a, L)

      s = Function(state.VectorFunctionSpace())
      solver = KrylovSolver(A, "gmres", "ilu")
      solver.solve(s.vector(), b)

      state.s = s
Ejemplo n.º 5
0
    def step(self, state, dt):
        """
    Calculate :math:`\\vec{m}(t+\Delta t)` for a given timestep.

    *Arguments*
      state (:class:`State`)
        The magnetization configuration.
      dt (:class:`float`)
        The time-step size.
    """

        with Timer("LLG Step"):
            v = self.calculate_v(state, dt)
            state.m.vector().axpy(dt, v.vector())
            # NOTE state.update_uuid() is not called, because normlize does the job
            state.m.normalize()
Ejemplo n.º 6
0
 def field(self, state, x = None, lump = True):
   with Timer("Spin Torque"):
     return super(SpinTorque, self).field(state, x, lump)
 def field(self, state, x = None, lump = True):
   with Timer("Uniaxial Anisotropy Field"):
     return super(UniaxialAnisotropyField, self).field(state, x, lump)
 def field(self, state, x = None, lump = False):
   with Timer("Spin Torque Zhang&Li"):
     return super(SpinTorqueZhangLi, self).field(state, x, lump)
Ejemplo n.º 9
0
    def calculate_v(self, state, dt):
        """
    Calculate :math:`\\vec{v}` according to the algorithm introduced above.

    *Arguments*
        state (:class:`State`)
            The simulation state containing the magnetization configuration.
        dt (:class:`float`)
            The time-step size.
    """

        with Timer("Calculate v"):
            # Initialize mesh and function spaces
            VV = state.VectorFunctionSpace()
            VS = state.FunctionSpace()

            v = TrialFunction(VV)
            w = TestFunction(VV)

            #######################################################
            # Forms
            #######################################################
            f_ex  =  Constant(-2.0 / state.scale**2 * Constants.gamma / Constants.mu0) \
                     * state.material.Aex / state.material.ms

            # Bilinear form for LLG
            a = state.material.alpha * dot(v, w) * state.dx('magnetic')
            a += dot(cross(state.m, v), w) * state.dx('magnetic')
            L = zero()

            # Effective field contributions
            for term in self.terms:
                L += term.form_rhs(state, w) * state.dx('magnetic')
                a += term.form_lhs(
                    state, w,
                    Constant(0.5 * dt) * v) * state.dx('magnetic')

            #######################################################
            # Assembly
            #######################################################

            # System to solve:
            # (1 - B^t B) A x = (1 - B^t B) b

            class ProjectionOperator(LinearOperator):
                def __init__(self, A, BTB, u):
                    LinearOperator.__init__(self, u.vector(), u.vector())
                    self._A = A
                    self._BTB = BTB

                def size(self):
                    return self._A.size(0)

                def mult(self, x, y):
                    self._BTB.transpmult(-self._A * x, y)
                    y.axpy(1.0, self._A * x)

            A = assemble(a, keep_diagonal=True)
            A.ident_zeros()

            v = TestFunction(state.VectorFunctionSpace())
            u = TrialFunction(state.VectorFunctionSpace())
            BTB = assemble(inner(state.m, v) * inner(state.m, u) * dP)

            b = assemble(L)
            b.axpy(-1.0, BTB * b)

            v = Function(VV)
            Op = ProjectionOperator(A, BTB, v)

            with Timer("Solve"):
                solve(Op, v.vector(), b, "gmres")

            return v
Ejemplo n.º 10
0
    def calculate_v(self, state, dt):
        """
    Calculate :math:`\\vec{v}` according to the algorithm introduced above.

    *Arguments*
      state (:class:`State`)
        The simulation state containing the magnetization configuration.
      dt (:class:`float`)
        The time-step size.
    """

        with Timer("Calculate v"):
            # Initialize mesh and function spaces
            VV = state.VectorFunctionSpace()
            VS = state.FunctionSpace()

            v = TrialFunction(VV)
            w = TestFunction(VV)

            #######################################################
            # Forms
            #######################################################
            f_ex  =  Constant(-2.0 / state.scale**2 * Constants.gamma / Constants.mu0) \
                     * state.material.Aex / state.material.ms

            # Bilinear form for LLG
            a = state.material.alpha * dot(v, w) * state.dx('magnetic')
            a += dot(cross(state.m, v), w) * state.dx('magnetic')
            L = zero()

            # Effective field contributions
            for term in self.terms:
                L += term.form_rhs(state, w) * state.dx('magnetic')
                a += term.form_lhs(
                    state, w,
                    Constant(0.5 * dt) * v) * state.dx('magnetic')

            #######################################################
            # Assembly
            #######################################################

            # assemble llg
            A = assemble(a, keep_diagonal=True)
            A.ident_zeros()
            b = assemble(L)

            # assemble constraint
            #B  = DofAssembler.assemble(ScalarProductMatrix(VS, VV, state.m))
            #BT = DofAssembler.assemble(TransScalarProductMatrix(VS, VV, state.m))

            v = TestFunction(state.FunctionSpace())
            u = TrialFunction(state.VectorFunctionSpace())
            B = assemble(v * dot(state.m, u) * dP)

            v = TestFunction(state.VectorFunctionSpace())
            u = TrialFunction(state.FunctionSpace())
            BT = assemble(u * dot(state.m, v) * dP)

            # assemble block matrix
            AA = block_mat([[A, BT], [B, 0]])
            bb = block_vec([b, BT.create_vec()])

            Ap = ILU(A)
            Bp = InvDiag(collapse(B * LumpedInvDiag(A) * BT))
            AAp = block_mat([[Ap, BT], [0, -Bp]]).scheme('sgs')

            #######################################################
            # Solve the system
            #######################################################
            AAinv = BiCGStab(AA, precond=AAp, tolerance=1e-8 / dt)
            u, foo = AAinv * bb

            v = Function(VV)
            v.vector()[:] = u

            return v
  def calculate_v(self, state, dt):
    """
    Calculate :math:`\\vec{v}` according to the algorithm introduced above.

    *Arguments*
        state (:class:`State`)
            The simulation state containing the magnetization configuration.
        dt (:class:`float`)
            The time-step size.
    """


    with Timer("Calculate v"):
      cache = self._assemble_cache
      if cache.requires_update(state):

        if isinstance(state.mesh, WrappedMesh):
          raise Exception("Use simple mesh with shell instead of WrappedMesh.")

        # setup function spaces
        cache.VV = VectorFunctionSpace(state.mesh, "CG", 1)
        cache.VD = FunctionSpace(state.mesh, "CG", self.demag_order)
        cache.VL = FunctionSpace(state.mesh, "CG", 1)

        # setup some stuff for the demag field
        transformation_order = 2 if (self.demag_order == 1) else 2
        shell_width = state.mesh.coordinates().max(axis=0).min() / 2.0
        sample_size = state.mesh.coordinates().max(axis=0) - shell_width
        cache.gx = MetricMatrix.create_for_cube(sample_size, 0, transformation_order)
        cache.gy = MetricMatrix.create_for_cube(sample_size, 1, transformation_order)
        cache.gz = MetricMatrix.create_for_cube(sample_size, 2, transformation_order)

      # Test and Trial Functions
      u     = TrialFunction(cache.VD)
      v     = TrialFunction(cache.VV)
      sigma = TrialFunction(cache.VL)

      w1    = TestFunction(cache.VD)
      w2    = TestFunction(cache.VV)
      w3    = TestFunction(cache.VL)

      #######################################################
      # Define weak forms
      #######################################################
      f_ex = (- 2.0 * state.material.Aex * Constants.gamma) / \
             (Constants.mu0 * state.material.ms * state.scale**2)

      # Bilinear form
      a12  = - 0.5 * Constant(dt) * inner(v, grad(w1)) * state.dx('magnetic')                            # Demag Field, Implicit RHS
      a11  = inner(grad(w1), grad(u))            * state.dx('all') \
           + inner(grad(w1), grad(u))            * state.dx(1000)  \
           + inner(grad(w1), cache.gx * grad(u)) * state.dx(1001)  \
           + inner(grad(w1), cache.gy * grad(u)) * state.dx(1002)  \
           + inner(grad(w1), cache.gz * grad(u)) * state.dx(1003)
      a21  = - Constant(state.material.ms * Constants.gamma) * inner(grad(u), w2) * state.dx('magnetic') # Demag
      a22  = Constant(state.material.alpha) * dot(v, w2) * state.dx('magnetic')                          # LLG
      a22 += dot(cross(state.m, v), w2) * state.dx('magnetic')
      a22 += - 0.5 * Constant(dt * f_ex) * Dx(v[i],j) * Dx(w2[i],j) * state.dx('magnetic')               # Exchange

      # Linear form
      L1 = inner(state.m, grad(w1)) * state.dx('magnetic')                                               # Demag Field
      L2 = Constant(f_ex) * Dx(state.m[i],j) * Dx(w2[i],j) * state.dx('magnetic')                        # Exchange

      for term in self.terms:                                                                            # Additional Terms
        L2  += term.form_rhs(state, w2) * state.dx('magnetic')
        #a22 += term.form_lhs(state, w2, Constant(0.5 * dt) * v) * state.dx('magnetic')

      #######################################################
      # Define boundary conditions
      #######################################################
      bc1 = DirichletBC(cache.VD, Constant(0.0), DomainBoundary())

      #######################################################
      # Assemble the system
      #######################################################
      A11, b1 = assemble_system(a11, L1, bc1)
      A12 = assemble(a12)
      A21 = assemble(a21)
      A22 = assemble(a22, keep_diagonal=True); A22.ident_zeros()

      v23 = TestFunction(state.VectorFunctionSpace())
      u23 = TrialFunction(state.FunctionSpace())
      A23 = assemble(u23 * dot(state.m, v23) * dP)

      v32 = TestFunction(state.FunctionSpace())
      u32 = TrialFunction(state.VectorFunctionSpace())
      A32 = assemble(v32 * dot(state.m, u32) * dP)

      #A23 = DofAssembler.assemble(TransScalarProductMatrix(cache.VL, cache.VV, state.m))
      #A32 = DofAssembler.assemble(ScalarProductMatrix(cache.VL, cache.VV, state.m))

      b2  = assemble(L2)

      #######################################################
      # Schur Ansatz
      #######################################################
      A11p   = ILU(A11)
      A11inv = ConjGrad(A11, precond=A11p)
      z1     = A11inv * b1

      S11    = A22 - A21 * A11inv * A12
      S      = block_mat([[S11, A23],
                          [A32,   0]])

      Sp11   = ILU(A22)
      Sp22   = InvDiag(collapse(A32 * LumpedInvDiag(A22) * A23))
      Sp     = block_mat([[Sp11, A23],
                          [0, -Sp22]]).scheme('sgs')

      Sinv   = BiCGStab(S, precond=Sp, tolerance=1e-8/dt)

      b      = block_vec([b2 - A21*z1, 0])
      v, _   = Sinv * b

      return Function(cache.VV, v)