Пример #1
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
Пример #2
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)