Example #1
0
  def calculate(self, state, id):
    if id == self.__var:
      # Get parameters...
      offs  = getattr(self, self.__offs)
      amp   = getattr(self, self.__amp)
      freq  = getattr(self, self.__freq)
      phase = getattr(self, self.__phase)
      fn    = getattr(self, self.__func)

      # Calculate field 'A'.
      t = state.t
      if fn: # with user function
        if any(x != (0.0, 0.0, 0.0) for x in (amp, freq, phase, offs)):
          raise ValueError("AlternatingField.calculates: If %s is defined, the parameters %s, %s, %s and %s must be zero vectors, i.e. (0.0, 0.0, 0.0)" % (self.__func, self.__offs, self.__amp, self.__freq, self.__phase))
        # call user function
        A = fn(t)
      else:
        # with 'offs', 'amp', 'freq', 'phase' parameters
        A = tuple(offs[c] + amp[c] * sin(t * freq[c] + phase[c]) for c in range(3))

      # Convert 3-vector to VectorField if necessary.
      if isinstance(A, tuple):
        tmp = A; A = VectorField(self.system.mesh); A.fill(tmp)

      # Return field 'A'
      return A

    else:
      raise KeyError("AlternatingField.calculates: Can't calculate %s", id)
Example #2
0
class AnisotropyField(module.Module):
  def __init__(self):
    super(AnisotropyField, self).__init__()

  def calculates(self):
    return ["H_aniso", "E_aniso"]

  def params(self):
    return ["k_uniaxial", "k_cubic", "axis1", "axis2"]

  def properties(self):
    return {'EFFECTIVE_FIELD_TERM': "H_aniso", 'EFFECTIVE_FIELD_ENERGY': "E_aniso"}

  def initialize(self, system):
    self.system = system
    self.k_uniaxial = Field(self.system.mesh); self.k_uniaxial.fill(0.0)
    self.k_cubic = Field(self.system.mesh); self.k_cubic.fill(0.0)
    self.axis1 = VectorField(self.system.mesh); self.axis1.fill((0.0, 0.0, 0.0))
    self.axis2 = VectorField(self.system.mesh); self.axis2.fill((0.0, 0.0, 0.0))

  def calculate(self, state, id):
    if id == "H_aniso":
      if hasattr(state.cache, "H_aniso"): return state.cache.H_aniso
      H_aniso = state.cache.H_aniso = VectorField(self.system.mesh)
      
      axis1 = self.axis1
      axis2 = self.axis2
      k_uni = self.k_uniaxial
      k_cub = self.k_cubic
      
      skip_uni = k_uni.isUniform() and k_uni.uniform_value == 0.0
      have_uni = not skip_uni
      skip_cub = k_cub.isUniform() and k_cub.uniform_value == 0.0
      have_cub = not skip_cub
  
      Ms = self.system.Ms    
  
      if   not have_uni and not have_cub:
        H_aniso.fill((0.0, 0.0, 0.0))
        state.cache.E_aniso_sum = 0.0
      elif not have_uni and have_cub:
        state.cache.E_aniso_sum = magneto.cubic_anisotropy(axis1, axis2, k_cub, Ms, state.M, H_aniso)
      elif have_uni and not have_cub:
        state.cache.E_aniso_sum = magneto.uniaxial_anisotropy(axis1, k_uni, Ms, state.M, H_aniso)
      elif have_uni and have_cub:
        tmp = VectorField(self.system.mesh)
        E0 = magneto.uniaxial_anisotropy(axis1, k_uni, Ms, state.M, tmp)
        E1 = magneto.cubic_anisotropy(axis1, axis2, k_cub, Ms, state.M, H_aniso)
        state.cache.E_aniso_sum = E0 + E1
        H_aniso.add(tmp)

      return H_aniso
  
    elif id == "E_aniso":
      if not hasattr(state.cache, "E_aniso"):
        foo = state.H_aniso
      return state.cache.E_aniso_sum * self.system.mesh.cell_volume

    else:
      raise KeyError("AnisotropyField.calculate: Can't calculate %s", id)
Example #3
0
  def initialize(self, system):
    logger.info("%s: Providing parameters %s" % (self.name(), ", ".join(self.params())))

    A = VectorField(system.mesh)
    A.clear()

    setattr(self, self.__var_id, A)
Example #4
0
    def initialize(self, system):
        logger.info("%s: Providing parameters %s" %
                    (self.name(), ", ".join(self.params())))

        A = VectorField(system.mesh)
        A.clear()

        setattr(self, self.__var_id, A)
 def initialize(self, system):
     self.system = system
     self.k_uniaxial = Field(self.system.mesh)
     self.k_uniaxial.fill(0.0)
     self.k_cubic = Field(self.system.mesh)
     self.k_cubic.fill(0.0)
     self.axis1 = VectorField(self.system.mesh)
     self.axis1.fill((0.0, 0.0, 0.0))
     self.axis2 = VectorField(self.system.mesh)
     self.axis2.fill((0.0, 0.0, 0.0))
Example #6
0
def readOMF(path):
    # Read OMF file
    header = magneto.OMFHeader()
    mat = magneto.readOMF(path, header)

    # Convert (header, mat) to VectorField.
    mesh = RectangularMesh((header.xnodes, header.ynodes, header.znodes), (header.xstepsize, header.ystepsize, header.zstepsize))
    vector_field = VectorField(mesh)
    vector_field.assign(mat)

    logger.debug("Read file %s", path)
    return vector_field
Example #7
0
class MacroSpinTorque(module.Module):
    def __init__(self, do_precess=True):
        super(MacroSpinTorque, self).__init__()
        self.do_precess = do_precess
        if not do_precess:
            raise NotImplementedError(
                "The MacroSpinTorque module does not support do_precess=False."
            )

    def calculates(self):
        return ["dMdt_ST"]

    def params(self):
        return ["a_j", "p"]

    def properties(self):
        return {'LLGE_TERM': "dMdt_ST"}

    def initialize(self, system):
        self.system = system
        self.a_j = 0.0
        self.p = VectorField(self.system.mesh)
        self.p.fill((0.0, 0.0, 0.0))

    def calculate(self, state, id):
        cache = state.cache

        if id == "dMdt_ST":
            if hasattr(cache, "dMdt_ST"): return cache.dMdt_ST
            dMdt_ST = cache.dMdt_ST = VectorField(self.system.mesh)

            # Calculate macro spin torque term due to Slonchewski
            nx, ny, nz = self.system.mesh.num_nodes
            dx, dy, dz = self.system.mesh.delta
            magneto.fdm_slonchewski(
                nx,
                ny,
                nz,
                dx,
                dy,
                dz,  #self.do_precess,
                self.a_j,
                self.p,
                self.system.get_param("Ms"),
                self.system.get_param("alpha"),
                state.M,
                dMdt_ST)
            return dMdt_ST

        else:
            raise KeyError("MacroSpinTorque.calculate: Can't calculate %s", id)
Example #8
0
    def __init__(self, mesh, method, stepsize_controller):
        super(RungeKutta, self).__init__(mesh)

        self.tab = RungeKutta.TABLES[method]()
        self.controller = stepsize_controller

        self.y0 = VectorField(mesh)
        self.y_err = VectorField(mesh)
        self.y_tmp = VectorField(mesh)
        self.k = [None] * self.tab.getNumSteps()

        logger.info(
            "Runge Kutta evolver: method is %s, step size controller is %s.",
            method, self.controller)
Example #9
0
 def __init__(self, mesh):
     self.t = 0
     self.h = 0
     self.step = 0
     self.mesh = mesh
     self.y = VectorField(mesh)
     self.flush_cache()
Example #10
0
    def __update_field(self, state):
        # Get value of homogeneous field
        if hasattr(state, self.__value_id):
            value = getattr(state, self.__value_id)
        else:
            if not self.__default_value:
                raise ValueError(
                    "HomogeneousField: Can't initialize field '%s' because no initial value is given!"
                    % self.__var_id)
            value = self.__default_value

        # Create field (Field or VectorField) from value
        try:
            if isinstance(value, numbers.Number):
                value = float(value)
                field = Field(self.__mesh)
                field.fill(value)
            elif hasattr(value, "__iter__") and len(value) == 3:
                value = tuple(map(float, value))
                field = VectorField(self.__mesh)
                field.fill(value)
            else:
                raise ValueError
        except ValueError:
            raise ValueError(
                "HomogeneousField: Expected scalar value or 3-tuple of scalar values for the 'value' (second) parameter"
            )

        # Store value and field in state
        setattr(state, self.__value_id, value)
        setattr(state, self.__field_id, field)
        return field
Example #11
0
    def calculate(self, state, id):
        cache = state.cache

        if id == "dMdt_ST":
            if hasattr(cache, "dMdt_ST"): return cache.dMdt_ST
            dMdt_ST = cache.dMdt_ST = VectorField(self.system.mesh)

            # Calculate macro spin torque term due to Slonchewski
            nx, ny, nz = self.system.mesh.num_nodes
            dx, dy, dz = self.system.mesh.delta
            magneto.fdm_slonchewski(
                nx,
                ny,
                nz,
                dx,
                dy,
                dz,  #self.do_precess,
                self.a_j,
                self.p,
                self.system.get_param("Ms"),
                self.system.get_param("alpha"),
                state.M,
                dMdt_ST)
            return dMdt_ST

        else:
            raise KeyError("MacroSpinTorque.calculate: Can't calculate %s", id)
 def compute_uniaxial_and_cubic(state, H_aniso):
     tmp = VectorField(self.system.mesh)
     E0 = magneto.uniaxial_anisotropy(axis1, k_uni, Ms, state.M,
                                      tmp)
     E1 = magneto.cubic_anisotropy(axis1, axis2, k_cub, Ms, state.M,
                                   H_aniso)
     state.cache.E_aniso_sum = E0 + E1
     H_aniso.add(tmp)
Example #13
0
def calculate_strayfield(mesh, M, object_list):
  # mesh number of nodes and node size
  nx, ny, nz = mesh.num_nodes
  dx, dy, dz = mesh.delta

  # Calculate stray field for one object
  def calculate(obj, cub_M):
    cub_size   = (10e-9, 10e-9, 10e-9)
    cub_center = (0,0,0)
    cub_inf    = magneto.INFINITY_NONE
    return CalculateStrayfieldForCuboid(nx, ny, nz, dx, dy, dz, cub_M, cub_center, cub_size, cub_inf)

  # Return the sum of the stray fields of all objects.
  H = VectorField(mesh)
  H.clear()
  for obj in object_list:
    H.add(calculate(obj, M))
  return H
    def calculate_H_tot(self, state):
        if hasattr(state.cache, "H_tot"): return state.cache.H_tot
        H_tot = state.cache.H_tot = VectorField(self.system.mesh)

        H_tot.fill((0.0, 0.0, 0.0))
        for H_id in self.field_terms:
            H_i = getattr(state, H_id)
            H_tot.add(H_i)

        return H_tot
Example #15
0
 def set_param(self, id, val):
     if id == self.__var_id:
         if isinstance(val, numbers.Number):
             fld = Field(self.system.mesh)
             fld.fill(val)
         elif hasattr(val, "__iter__") and len(val) == 3:
             val = tuple(map(float, val))
             field = VectorField(self.system.mesh)
             field.fill(val)
         elif isinstance(val, Field):
             fld = Field(self.system.mesh)
             fld.assign(val)
         elif isinstance(val, VectorField):
             fld = VectorField(self.system.mesh)
             fld.assign(val)
         else:
             raise ValueError
         self.__field = fld
     else:
         raise ValueError("%s: Don't know how to update %s." % (self.name(), id))
Example #16
0
 def set_param(self, id, val):
     if id == self.__var_id:
         if isinstance(val, numbers.Number):
             fld = Field(self.system.mesh)
             fld.fill(val)
         elif hasattr(val, "__iter__") and len(val) == 3:
             val = tuple(map(float, val))
             field = VectorField(self.system.mesh)
             field.fill(val)
         elif isinstance(val, Field):
             fld = Field(self.system.mesh)
             fld.assign(val)
         elif isinstance(val, VectorField):
             fld = VectorField(self.system.mesh)
             fld.assign(val)
         else:
             raise ValueError
         self.__field = fld
     else:
         raise ValueError("%s: Don't know how to update %s." %
                          (self.name(), id))
    def calculate_minimizer_M(self, state, h):
        # TODO other LLG terms?
        if not self.__valid_factors: self.__initFactors()

        result = VectorField(self.system.mesh)

        # Get effective field
        H_tot = self.calculate_H_tot(state)

        magneto.minimize(self.__f2, h, state.M, H_tot, result)

        return result
class MacroSpinTorque(module.Module):
    def __init__(self, do_precess = True):
        super(MacroSpinTorque, self).__init__()
        self.do_precess = do_precess
        if not do_precess:
          raise NotImplementedError("The MacroSpinTorque module does not support do_precess=False.")

    def calculates(self):
        return ["dMdt_ST"]

    def params(self):
        return ["a_j", "p"]

    def properties(self):
        return {'LLGE_TERM': "dMdt_ST"}

    def initialize(self, system):
        self.system = system
        self.a_j = 0.0
        self.p = VectorField(self.system.mesh); self.p.fill((0.0, 0.0, 0.0))

    def calculate(self, state, id):
        cache = state.cache

        if id == "dMdt_ST":
            if hasattr(cache, "dMdt_ST"): return cache.dMdt_ST
            dMdt_ST = cache.dMdt_ST = VectorField(self.system.mesh)

            # Calculate macro spin torque term due to Slonchewski
            nx, ny, nz = self.system.mesh.num_nodes
            dx, dy, dz = self.system.mesh.delta
            magneto.fdm_slonchewski(
              nx, ny, nz, dx, dy, dz, #self.do_precess,
              self.a_j, self.p, self.system.get_param("Ms"), self.system.get_param("alpha"),
              state.M, dMdt_ST
            )
            return dMdt_ST

        else:
            raise KeyError("MacroSpinTorque.calculate: Can't calculate %s", id)
Example #19
0
    def calculate(self, state, id):
        if id == "H_aniso":
            if hasattr(state.cache, "H_aniso"): return state.cache.H_aniso
            H_aniso = state.cache.H_aniso = VectorField(self.system.mesh)
            state.cache.E_aniso_sum = self.__compute_fn(state, H_aniso)
            return H_aniso

        elif id == "E_aniso":
            if not hasattr(state.cache, "E_aniso_sum"):
                self.calculate(state, "H_aniso")
            return state.cache.E_aniso_sum * self.system.mesh.cell_volume

        else:
            raise KeyError("AnisotropyField.calculate: Can't calculate %s", id)
Example #20
0
    def calculate(self, state, id):
        if id == self.__var:
            # Get parameters...
            offs = getattr(self, self.__offs)
            amp = getattr(self, self.__amp)
            freq = getattr(self, self.__freq)
            phase = getattr(self, self.__phase)
            fn = getattr(self, self.__func)

            # Calculate field 'A'.
            t = state.t
            if fn:  # with user function
                if any(x != (0.0, 0.0, 0.0) for x in (amp, freq, phase, offs)):
                    raise ValueError(
                        "AlternatingField.calculates: If %s is defined, the parameters %s, %s, %s and %s must be zero vectors, i.e. (0.0, 0.0, 0.0)"
                        % (self.__func, self.__offs, self.__amp, self.__freq,
                           self.__phase))
                # call user function
                A = fn(t)
            else:
                # with 'offs', 'amp', 'freq', 'phase' parameters
                A = (offs[0] + amp[0] * sin(t * freq[0] + phase[0]),
                     offs[1] + amp[1] * sin(t * freq[1] + phase[1]),
                     offs[2] + amp[2] * sin(t * freq[2] + phase[2]))

            # Convert 3-vector to VectorField if necessary.
            if isinstance(A, tuple):
                tmp = A
                A = VectorField(self.system.mesh)
                A.fill(tmp)

            # Return field 'A'
            return A

        else:
            raise KeyError("AlternatingField.calculates: Can't calculate %s",
                           id)
Example #21
0
    def calculate(self, state, id):
        cache = state.cache

        if id == "H_exch":
            if hasattr(cache, "H_exch"): return cache.H_exch
            H_exch = cache.H_exch = VectorField(self.system.mesh)

            magneto.exchange(state.Ms, state.A, state.M, H_exch)
            return H_exch

        elif id == "E_exch":
            return -MU0 / 2.0 * self.system.mesh.cell_volume * state.M.dotSum(
                state.H_exch)

        else:
            raise KeyError("ExchangeField.calculate: Can't calculate %s", id)
Example #22
0
    def calculate(self, state, id):
        cache = state.cache

        if id == "H_stray":
            if hasattr(cache, "H_stray"): return cache.H_stray
            H_stray = cache.H_stray = VectorField(self.system.mesh)
            self.calculator.calculate(state.M, H_stray)
            return H_stray

        elif id == "E_stray":
            if hasattr(cache, "E_stray"): return cache.E_stray
            E_stray = cache.E_stray = -MU0 / 2.0 * self.system.mesh.cell_volume * state.M.dotSum(
                state.H_stray)
            return E_stray

        else:
            raise KeyError("StrayField.calculate: %s" % id)
    def calculate_minimizer_dM(self, state):
        # TODO other LLG terms?
        if not self.__valid_factors: self.__initFactors()

        if hasattr(state.cache, "minimizer_dM"):
            return state.cache.minimizer_dM
        result = state.cache.minimizer_dM = VectorField(self.system.mesh)

        # Get effective field
        H_tot = self.calculate_H_tot(state)

        # TODO do this in every step?
        zero = Field(self.system.mesh)
        zero.fill(0.0)

        magneto.llge(zero, self.__f2, state.M, H_tot, result)
        return result
Example #24
0
    def calculate(self, state, id):
        cache = state.cache

        if id == "dMdt_ST":
            if hasattr(cache, "dMdt_ST"): return cache.dMdt_ST
            dMdt_ST = cache.dMdt_ST = VectorField(self.system.mesh)

            # Calculate spin torque term due to Zhang & Li
            nx, ny, nz = self.system.mesh.num_nodes
            dx, dy, dz = self.system.mesh.delta
            magneto.fdm_zhangli(nx, ny, nz, dx, dy, dz, self.__do_precess,
                                self.P, self.xi, self.system.Ms,
                                self.system.alpha, state.j, state.M, dMdt_ST)
            return dMdt_ST

        else:
            raise KeyError("SpinTorque.calculate: Can't calculate %s", id)
    def calculate_dMdt(self, state):
        if not self.__valid_factors:
            self.__initFactors()

        if hasattr(state.cache, "dMdt"): return state.cache.dMdt
        dMdt = state.cache.dMdt = VectorField(self.system.mesh)

        # Get effective field
        H_tot = self.calculate_H_tot(state)

        # Basic term
        magneto.llge(self.__f1, self.__f2, state.M, H_tot, dMdt)

        # Optional other terms
        for dMdt_id in self.llge_terms:
            dMdt_i = getattr(state, dMdt_id)
            dMdt.add(dMdt_i)

        return dMdt
Example #26
0
    def calculate(self, state, id):
        cache = state.cache

        if id == "H_exch":
            if hasattr(cache, "H_exch"): return cache.H_exch
            H_exch = cache.H_exch = VectorField(self.system.mesh)

            #nx, ny, nz = self.system.mesh.num_nodes
            #dx, dy, dz = self.system.mesh.delta
            #bcx, bcy, bcz = self.__peri_x, self.__peri_y, self.__peri_z

            magneto.exchange(self.system.Ms, self.system.A, state.M, H_exch)
            return H_exch

        elif id == "E_exch":
            return -MU0 / 2.0 * self.system.mesh.cell_volume * state.M.dotSum(
                state.H_exch)

        else:
            raise KeyError("ExchangeField.calculate: Can't calculate %s", id)
    def calculate_minimizer_dM_minimize_BB(self, state):
        # TODO other LLG terms?
        if not self.__valid_factors: self.__initFactors()

        if hasattr(state.cache, "minimizer_dM_minimize_BB"):
            return state.cache.minimizer_dM_minimize_BB
        result = state.cache.minimizer_dM_minimize_BB = VectorField(
            self.system.mesh)

        # Get effective field
        H_tot = self.calculate_H_tot(state)

        # TODO do this in every step?
        zero = Field(self.system.mesh)
        zero.fill(0.0)

        # changed; set llge coefficient to 1.0 for minimization
        factor = Field(self.system.mesh)
        factor.fill(1.)
        magneto.llge(zero, factor, state.M, H_tot, result)
        return result
Example #28
0
def calculate_strayfield(mesh, M, object_list):
    # mesh number of nodes and node size
    nx, ny, nz = mesh.num_nodes
    dx, dy, dz = mesh.delta

    # Calculate stray field for one object
    def calculate(obj, cub_M):
        cub_size = (10e-9, 10e-9, 10e-9)
        cub_center = (0, 0, 0)
        cub_inf = magneto.INFINITY_NONE
        return CalculateStrayfieldForCuboid(nx, ny, nz, dx, dy, dz, cub_M,
                                            cub_center, cub_size, cub_inf)

    # Return the sum of the stray fields of all objects.
    H = VectorField(mesh)
    H.clear()
    for obj in object_list:
        H.add(calculate(obj, M))
    return H
Example #29
0
 def initialize(self, system):
     self.system = system
     self.a_j = 0.0
     self.p = VectorField(self.system.mesh)
     self.p.fill((0.0, 0.0, 0.0))
class AnisotropyField(module.Module):
    def __init__(self):
        super(AnisotropyField, self).__init__()

    def calculates(self):
        return ["H_aniso", "E_aniso"]

    def params(self):
        return ["k_uniaxial", "k_cubic", "axis1", "axis2"]

    def properties(self):
        return {'EFFECTIVE_FIELD_TERM': "H_aniso", 'EFFECTIVE_FIELD_ENERGY': "E_aniso"}

    def initialize(self, system):
        self.system = system
        self.k_uniaxial = Field(self.system.mesh); self.k_uniaxial.fill(0.0)
        self.k_cubic = Field(self.system.mesh); self.k_cubic.fill(0.0)
        self.axis1 = VectorField(self.system.mesh); self.axis1.fill((0.0, 0.0, 0.0))
        self.axis2 = VectorField(self.system.mesh); self.axis2.fill((0.0, 0.0, 0.0))

    def on_param_update(self, id):

        if id in self.params() + ["Ms"]:
            axis1, axi2 = self.axis1, self.axis2
            k_uni, k_cub = self.k_uniaxial, self.k_cubic
            Ms = self.system.Ms

            def compute_none(state, H_aniso):
                H_aniso.fill((0.0, 0.0, 0.0))
                return 0.0

            def compute_uniaxial(state, H_aniso):
                return magneto.uniaxial_anisotropy(axis1, k_uni, Ms, state.M, H_aniso)

            def compute_cubic(state, H_aniso):
                return magneto.cubic_anisotropy(axis1, axis2, k_cub, Ms, state.M, H_aniso)

            def compute_uniaxial_and_cubic(state, H_aniso):
                tmp = VectorField(self.system.mesh)
                E0 = magneto.uniaxial_anisotropy(axis1, k_uni, Ms, state.M, tmp)
                E1 = magneto.cubic_anisotropy(axis1, axis2, k_cub, Ms, state.M, H_aniso)
                state.cache.E_aniso_sum = E0 + E1
                H_aniso.add(tmp)

            fns = {(False, False): compute_none,
                   ( True, False): compute_uniaxial,
                   (False,  True): compute_cubic,
                   ( True,  True): compute_uniaxial_and_cubic}

            have_uni = not (k_uni.isUniform() and k_uni.uniform_value == 0.0)
            have_cub = not (k_cub.isUniform() and k_cub.uniform_value == 0.0)
            self.__compute_fn = fns[have_uni, have_cub]

    def calculate(self, state, id):
        if id == "H_aniso":
            if hasattr(state.cache, "H_aniso"): return state.cache.H_aniso
            H_aniso = state.cache.H_aniso = VectorField(self.system.mesh)
            state.cache.E_aniso_sum = self.__compute_fn(state, H_aniso)
            return H_aniso

        elif id == "E_aniso":
            if not hasattr(state.cache, "E_aniso_sum"):
                self.calculate(state, "H_aniso")
            return state.cache.E_aniso_sum * self.system.mesh.cell_volume

        else:
            raise KeyError("AnisotropyField.calculate: Can't calculate %s", id)
Example #31
0
 def initialize(self, system):
   self.system = system
   self.k_uniaxial = Field(self.system.mesh); self.k_uniaxial.fill(0.0)
   self.k_cubic = Field(self.system.mesh); self.k_cubic.fill(0.0)
   self.axis1 = VectorField(self.system.mesh); self.axis1.fill((0.0, 0.0, 0.0))
   self.axis2 = VectorField(self.system.mesh); self.axis2.fill((0.0, 0.0, 0.0))
class AnisotropyField(module.Module):
    def __init__(self):
        super(AnisotropyField, self).__init__()

    def calculates(self):
        return ["H_aniso", "E_aniso"]

    def params(self):
        return ["k_uniaxial", "k_cubic", "axis1", "axis2"]

    def properties(self):
        return {
            'EFFECTIVE_FIELD_TERM': "H_aniso",
            'EFFECTIVE_FIELD_ENERGY': "E_aniso"
        }

    def initialize(self, system):
        self.system = system
        self.k_uniaxial = Field(self.system.mesh)
        self.k_uniaxial.fill(0.0)
        self.k_cubic = Field(self.system.mesh)
        self.k_cubic.fill(0.0)
        self.axis1 = VectorField(self.system.mesh)
        self.axis1.fill((0.0, 0.0, 0.0))
        self.axis2 = VectorField(self.system.mesh)
        self.axis2.fill((0.0, 0.0, 0.0))

    def on_param_update(self, id):
        if id in self.params() + ["Ms"]:
            axis1, axis2 = self.axis1, self.axis2
            k_uni, k_cub = self.k_uniaxial, self.k_cubic
            Ms = self.system.get_param("Ms")

            def compute_none(state, H_aniso):
                H_aniso.fill((0.0, 0.0, 0.0))
                return 0.0

            def compute_uniaxial(state, H_aniso):
                return magneto.uniaxial_anisotropy(axis1, k_uni, Ms, state.M,
                                                   H_aniso)

            def compute_cubic(state, H_aniso):
                return magneto.cubic_anisotropy(axis1, axis2, k_cub, Ms,
                                                state.M, H_aniso)

            def compute_uniaxial_and_cubic(state, H_aniso):
                tmp = VectorField(self.system.mesh)
                E0 = magneto.uniaxial_anisotropy(axis1, k_uni, Ms, state.M,
                                                 tmp)
                E1 = magneto.cubic_anisotropy(axis1, axis2, k_cub, Ms, state.M,
                                              H_aniso)
                state.cache.E_aniso_sum = E0 + E1
                H_aniso.add(tmp)

            fns = {
                (False, False): compute_none,
                (True, False): compute_uniaxial,
                (False, True): compute_cubic,
                (True, True): compute_uniaxial_and_cubic
            }

            have_uni = not (k_uni.isUniform() and k_uni.uniform_value == 0.0)
            have_cub = not (k_cub.isUniform() and k_cub.uniform_value == 0.0)
            self.__compute_fn = fns[have_uni, have_cub]

    def calculate(self, state, id):
        cache = state.cache
        if id == "H_aniso":
            if hasattr(cache, "H_aniso"): return cache.H_aniso
            H_aniso = cache.H_aniso = VectorField(self.system.mesh)
            cache.E_aniso_sum = self.__compute_fn(state, H_aniso)
            return H_aniso

        elif id == "E_aniso":
            if not hasattr(cache, "E_aniso_sum"):
                self.calculate(state, "H_aniso")
            return cache.E_aniso_sum * self.system.mesh.cell_volume

        else:
            raise KeyError("AnisotropyField.calculate: Can't calculate %s", id)
 def initialize(self, system):
     self.system = system
     self.a_j = 0.0
     self.p = VectorField(self.system.mesh); self.p.fill((0.0, 0.0, 0.0))
    def minimize(self, max_dpns = 0.01, samples = 10, h_max = 1e-5, h_min = 1e-16):
        """
        Minimizes the energy with a direct minimization strategy.
        """
        counter = 0
        # TODO make use of stephandlers for logging
        h        = self.state.h
        dpnslist = []
        log      = ScreenLogMinimizer()

        # Reset step
        self.state.step = 0

        while len(dpnslist) < samples or max(dpnslist) > max_dpns:
            # Calculate next M and dM for minimization step
            M_next = self.state.minimizer_M(h)
            dM = self.state.minimizer_dM
            counter += 2

            # Get s^n-1 for step-size calculation
            M_diff = VectorField(self.mesh)
            M_diff.assign(M_next)
            M_diff.add(self.state.M, -1.0)

            # Set next M
            self.state.y = M_next
            self.state.finish_step() # normalize, TODO really need to do this every step?
            self.state.flush_cache()

            # Calculate deg per ns
            # TODO M.absMax might be the wrong choice if different materials are in use
            dp_timestep = (180.0 / math.pi) * math.atan2(M_diff.absMax(), self.state.M.absMax())
            dpns = abs(1e-9 * dp_timestep / h)
            dpnslist.append(dpns)
            if len(dpnslist) > samples: dpnslist.pop(0)
            self.state.deg_per_ns_minimizer = dpns

            # Get y^n-1 for step-size calculation
            dM_diff = VectorField(self.mesh)
            dM_diff.assign(self.state.minimizer_dM)
            dM_diff.add(dM, -1.0)

            # Next stepsize (Alternate h1 and h2)
            try:
              if (self.state.step % 2 == 0):
                h = M_diff.dotSum(M_diff) / M_diff.dotSum(dM_diff)
              else:
                h = M_diff.dotSum(dM_diff) / dM_diff.dotSum(dM_diff)
            except ZeroDivisionError, ex:
              h = h_max

            h_sign = math.copysign(1, h)
            h = max(min(abs(h), h_max), h_min) * h_sign

            if (self.state.step % 100 == 0):
              log.handle(self.state)

            # Update step
            self.state.step += 1
    def minimize(self, max_dpns = 0.01, samples = 10, h_max = 1e-5, h_min = 1e-16):
        """
        Minimizes the energy with a direct minimization strategy.
        """
        # TODO make use of stephandlers for logging
        h        = self.state.h
        dpnslist = []
        log      = ScreenLogMinimizer()

        # Reset step
        self.state.step = 0

        while len(dpnslist) < samples or max(dpnslist) > max_dpns:
            # Calculate next M and dM for minimization step
            M_next = self.state.minimizer_M(h)
            dM = self.state.minimizer_dM

            # Get s^n-1 for step-size calculation
            M_diff = VectorField(self.mesh)
            M_diff.assign(M_next)
            M_diff.add(self.state.M, -1.0)

            # Set next M
            self.state.y = M_next
            self.state.finish_step() # normalize, TODO really need to do this every step?
            self.state.flush_cache()

            # Calculate deg per ns
            # TODO M.absMax might be the wrong choice if different materials are in use
            dp_timestep = (180.0 / math.pi) * math.atan2(M_diff.absMax(), self.state.M.absMax())
            dpns = abs(1e-9 * dp_timestep / h)
            dpnslist.append(dpns)
            if len(dpnslist) > samples: dpnslist.pop(0)
            self.state.deg_per_ns_minimizer = dpns

            # Get y^n-1 for step-size calculation
            dM_diff = VectorField(self.mesh)
            dM_diff.assign(self.state.minimizer_dM)
            dM_diff.add(dM, -1.0)

            # Next stepsize (Alternate h1 and h2)
            try:
              if (self.state.step % 2 == 0):
                h = M_diff.dotSum(M_diff) / M_diff.dotSum(dM_diff)
              else:
                h = M_diff.dotSum(dM_diff) / dM_diff.dotSum(dM_diff)
            except ZeroDivisionError, ex:
              h = h_max

            h_sign = math.copysign(1, h)
            h = max(min(abs(h), h_max), h_min) * h_sign

            if (self.state.step % 100 == 0):
              log.handle(self.state)

            # Update step
            self.state.step += 1