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)
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)
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))
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
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)
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)
def __init__(self, mesh): self.t = 0 self.h = 0 self.step = 0 self.mesh = mesh self.y = VectorField(mesh) self.flush_cache()
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
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)
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
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)
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)
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)
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)
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
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
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
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 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)
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