def set_alpha(self, value): """ Set the Gilbert damping of the system as a uniform or spatially dependent scalar field ARGUMENTS: value :: * For a uniform damping across the whole sample, just specify a float ranging from 0 to 1 * In addition, you can specify a function that returns values ranging from 0 to 1, which depends on the spatial coordinates. For example, a damping that increases linearly in the x direction: def alpha_profile(r): for r[0] <= 10: return r[0] / 10. else: return 0 * You can also manually specify an array with n values ranging from 0 to 1 with the damping values, in the same order than the mesh coordinates array. * Alternatively, if you previously saved the damping field array to a numpy file, you can load it using numpy.load(my_array) """ self._alpha[:] = helper.init_scalar(value, self.mesh)
def set_pins(self, pin): """ An scalar field with values 1 or 0 to specify mesh/lattice sites with pinned or unpinned magnetic moments, respectively ARGUMENTS: pin :: * You can specify a function that returns 1 or 0 depending on the spatial coordinates. For example, to pin the spins in a range in the x direction: def pin_profile(r): for r[0] > 2 and r[0] < 4: return 1 else: return 0 * You can also manually specify an array with n elements (1 or 0) with the pinned/unpinned values in the same order than the mesh coordinates array. * Alternatively, if you previously saved the pin field array to a numpy file, you can load it using numpy.load(my_array) """ self._pins[:] = helper.init_scalar(pin, self.mesh) # Sites with no material, i.e. Mu_s or mu_s equal to zero, # will be pinned for i in range(len(self._magnetisation)): if self._magnetisation[i] == 0.0: self._pins[i] = 1
def set_Ms(self, value): """ Set the saturation magnetisation of the system as a uniform or spatially dependent scalar field, where values are in A /m. Mesh sites with no material can be specified with a magnetisation of zero magnitude. Samples with different materials can be specified with different magnetisation values in specific regions of the system. ARGUMENTS: value :: * For a homogeneous single material sample, specify a float with a magnitude in A /m * In addition, you can specify a function that returns values in A /m, which depends on the spatial coordinates. For example, a 2 nm wide cylinder centered at (x, y) = (1, 1) can be specified with (if you set the unit_length to 1e-9 in the mesh): Ms = 1e6 # A / m def Ms_profile(r): for (r[0] - 1) ** 2 + (r[1] - 1) ** 2 <= 1 ** 2: return Ms else: return 0 Sim.set_Ms(Ms_profile) * You can also manually specify an array with n values with the magnetisation magnitudes, in the same order than the mesh coordinates array. * Alternatively, if you previously saved the magnetisation array to a numpy file, you can load it using numpy.load(my_array). """ self._Ms[:] = helper.init_scalar(value, self.mesh) nonzero = 0 for i in range(self.n): if self._Ms[i] > 0.0: self._Ms_inv = 1.0 / self._Ms[i] nonzero += 1 # We moved this variable to the micro_driver class self.driver.n_nonzero = nonzero for i in range(len(self._Ms)): if self._Ms[i] == 0.0: self._pins[i] = 1 # Set the neighbour index to -1 for sites with Ms = 0 self.mesh.neighbours[self.mesh.neighbours == i] = -1 # TODO: Check if this is necessary here, it is only defined # for the LLG STT in the drivers self.driver.Ms_const = np.max(self._Ms)
def set_Ms(self, value): """ Set the saturation magnetisation of the system as a uniform or spatially dependent scalar field, where values are in A /m. Mesh sites with no material can be specified with a magnetisation of zero magnitude. Samples with different materials can be specified with different magnetisation values in specific regions of the system. ARGUMENTS: value :: * For a homogeneous single material sample, specify a float with a magnitude in A /m * Alternatively, you can specify a function that returns values in A /m, which depends on the spatial coordinates. For example, a 2 nm wide cylinder centered at (x, y) = (1, 1) can be specified with (if you set the unit_length to 1e-9 in the mesh): Ms = 1e6 # A / m def Ms_profile(r): for (r[0] - 1) ** 2 + (r[1] - 1) ** 2 <= 1 ** 2: return Ms else: return 0 Sim.set_Ms(Ms_profile) * You can also manually specify an array with n values with the magnetisation magnitudes, in the same order than the mesh coordinates array. * Alternatively, if you previously saved the magnetisation array to a numpy file, you can load it using numpy.load(my_array). """ self._Ms[:] = helper.init_scalar(value, self.mesh) nonzero = 0 for i in range(self.n): if self._Ms[i] > 0.0: self._Ms_inv[i] = 1.0 / self._Ms[i] nonzero += 1 # We moved this variable to the micro_driver class self.driver.n_nonzero = nonzero for i in range(len(self._Ms)): if self._Ms[i] == 0.0: self._pins[i] = 1 # Set the neighbour index to -1 for sites with Ms = 0 self.mesh.neighbours[self.mesh.neighbours == i] = -1 # TODO: Check if this is necessary here, it is only defined # for the LLG STT in the drivers self.driver.Ms_const = np.max(self._Ms)
def set_mu_s(self, value): self._mu_s[:] = helper.init_scalar(value, self.mesh) nonzero = 0 for i in range(self.n): if self._mu_s[i] > 0.0: nonzero += 1 self.n_nonzero = nonzero
def set_mu_s(self, value): self._mu_s[:] = helper.init_scalar(value, self.mesh) nonzero = 0 for i in range(self.n): if self._mu_s[i] > 0.0: self._mu_s_inv[i] = 1.0 / self._mu_s[i] nonzero += 1 self.n_nonzero = nonzero for i in range(len(self._mu_s)): if self._mu_s[i] == 0.0: self._pins[i] = 1
def setup(self, mesh, spin, Ms): super(DMI, self).setup(mesh, spin, Ms) # We will allow to completely specify the DMI vectors according to the # NNs of every lattice site, thus we need a matrix of NN * n entries self.Ds = np.zeros(self.NN * self.n, dtype=np.float) if isinstance(self.D, np.ndarray) and len(self.D) == self.NN * self.n: self.Ds = self.D.astype('float') # If we do not pass a (NN * n) array, we just create a scalar field as # usual and then repeat the entries NN times so every neighbour will # have the same DMI per lattice site (can vary spatially) else: D_array = helper.init_scalar(self.D, self.mesh) self.Ds = np.repeat(D_array, self.NN)
def set_Ms(self, value): self._Ms[:] = helper.init_scalar(value, self.mesh) nonzero = 0 for i in range(self.n): if self._Ms[i] > 0.0: self._Ms_inv = 1.0 / self._Ms[i] nonzero += 1 self.n_nonzero = nonzero for i in range(len(self._Ms)): if self._Ms[i] == 0.0: self._pins[i] = 1 self.Ms_const = np.max(self._Ms)
def set_pins(self, pin): self._pins[:] = helper.init_scalar(pin, self.mesh) for i in range(len(self._Ms)): if self._Ms[i] == 0.0: self._pins[i] = 1
def set_mu_s(self, value): """ Set the magnetic moments values of the system as a uniform or spatially dependent scalar field, where values are in J / T. It is recommended to set values in Bohr magneton units and to use the fidimag.common.constant.mu_B magnitude (see example). Mesh sites with no material can be specified with a magnetic moment of zero magnitude. Samples with different materials can be specified with different magnetic moments in specific regions of the system. ARGUMENTS: value :: * For a homogeneous single material sample, specify a float with a magnitude in J / T. It is recommended to use Bohr magneton units taking the constant from the `constant` library in fidimag.common. For example: import fidimag.common.constant as const mu_s = 2 * const.mu_B * In addition, you can specify a function that returns values in J / T, which depends on the spatial coordinates. For example, a 2 nm wide cylinder centered at (x, y) = (1, 1) can be specified with (if you set the unit_length to 1e-9 in the mesh): import fidimag.common.constant as const mu_s = 2 * const.mu_B def mu_s_profile(r): for (r[0] - 1) ** 2 + (r[1] - 1) ** 2 <= 1 ** 2: return mu_s else: return 0 Sim.set_mu_s(mu_s_profile) * You can also manually specify an array with n values with the magnetisation values, in the same order than the mesh coordinates array. * Alternatively, if you previously saved the magnetic moments array to a numpy file, you can load it using numpy.load(my_array). """ self._mu_s[:] = helper.init_scalar(value, self.mesh) nonzero = 0 for i in range(self.n): if self._mu_s[i] > 0.0: self._mu_s_inv[i] = 1.0 / self._mu_s[i] nonzero += 1 # We moved this variable to the micro_driver class self.n_nonzero = nonzero for i in range(len(self._mu_s)): if self._mu_s[i] == 0.0: self._pins[i] = 1 # Set the neighbour index to -1 for sites with mu_s = 0 self.mesh.neighbours[self.mesh.neighbours == i] = -1 # TODO: Check if this is necessary here, it is only defined # for the LLG STT in the drivers self.driver.mu_s_const = np.max(self._mu_s) # David Tue 19 Jun 2018 # Since the scaling variables in the HexagonalDemag class depend on # mu_s, the safest way to avoid breaking the code is to update the # variables here in case mu_s changes. Same for normal demag if self.mesh.mesh_type == 'hexagonal': for inter in self.interactions: if isinstance(inter, fidimag.atomistic.DemagHexagonal): inter.mu_s_scale = self._mu_s * self.scale inter.scalar2cuboid(inter.mu_s_scale, inter.mu_s_scale_c) if isinstance(inter, fidimag.atomistic.Demag): inter.mu_s_scale = self._mu_s * self.scale
def setup(self, mesh, spin, Ms): super(DMI, self).setup(mesh, spin, Ms) self.Ds = np.zeros(self.n, dtype=np.float) self.Ds[:] = helper.init_scalar(self.D, self.mesh)
def setup(self, mesh, spin, Ms): super(UniaxialAnisotropy, self).setup(mesh, spin, Ms) self._Ku = helper.init_scalar(self.Ku, self.mesh) self._axis = helper.init_vector(self.axis, self.mesh, True)
def setup(self, mesh, spin, mu_s, mu_s_inv): super(Anisotropy, self).setup(mesh, spin, mu_s, mu_s_inv) self._Ku = helper.init_scalar(self.Ku, self.mesh) self._axis = helper.init_vector(self.axis, self.mesh, norm=True)
def set_alpha(self, value): self._alpha[:] = helper.init_scalar(value, self.mesh)
def set_T(self, T0): self._T[:] = helper.init_scalar(T0, self.mesh)
def setup(self, mesh, spin, Ms, Ms_inv): super(UniaxialAnisotropy4, self).setup(mesh, spin, Ms, Ms_inv) self._K1 = helper.init_scalar(self.K1, self.mesh) self._K2 = helper.init_scalar(self.K2, self.mesh) self._axis = helper.init_vector(self.axis, self.mesh, 3, norm=True)
def set_a_J(self, value, *args): self._a_J[:] = helper.init_scalar(value, self.mesh, *args)
def set_mu_s(self, value): """ Set the magnetic moments values of the system as a uniform or spatially dependent scalar field, where values are in J / T. It is recommended to set values in Bohr magneton units and to use the fidimag.common.constant.mu_B magnitude (see example). Mesh sites with no material can be specified with a magnetic moment of zero magnitude. Samples with different materials can be specified with different magnetic moments in specific regions of the system. ARGUMENTS: value :: * For a homogeneous single material sample, specify a float with a magnitude in J / T. It is recommended to use Bohr magneton units taking the constant from the `constant` library in fidimag.common. For example: import fidimag.common.constant as const mu_s = 2 * const.mu_B * In addition, you can specify a function that returns values in J / T, which depends on the spatial coordinates. For example, a 2 nm wide cylinder centered at (x, y) = (1, 1) can be specified with (if you set the unit_length to 1e-9 in the mesh): import fidimag.common.constant as const mu_s = 2 * const.mu_B def mu_s_profile(r): for (r[0] - 1) ** 2 + (r[1] - 1) ** 2 <= 1 ** 2: return mu_s else: return 0 Sim.set_mu_s(mu_s_profile) * You can also manually specify an array with n values with the magnetisation values, in the same order than the mesh coordinates array. * Alternatively, if you previously saved the magnetic moments array to a numpy file, you can load it using numpy.load(my_array). """ self._mu_s[:] = helper.init_scalar(value, self.mesh) nonzero = 0 for i in range(self.n): if self._mu_s[i] > 0.0: self._mu_s_inv[i] = 1.0 / self._mu_s[i] nonzero += 1 # We moved this variable to the micro_driver class self.n_nonzero = nonzero for i in range(len(self._mu_s)): if self._mu_s[i] == 0.0: self._pins[i] = 1 # Set the neighbour index to -1 for sites with mu_s = 0 self.mesh.neighbours[self.mesh.neighbours == i] = -1 # TODO: Check if this is necessary here, it is only defined # for the LLG STT in the drivers self.driver.mu_s_const = np.max(self._mu_s)
def set_jy(self, value, *args): self._jy[:] = helper.init_scalar(value, self.mesh, *args)
def setup(self, mesh, spin, mu_s, mu_s_inv): super(CubicAnisotropy, self).setup(mesh, spin, mu_s, mu_s_inv) self._Kc = helper.init_scalar(self.Kc, self.mesh)
def set_a_J(self, value): self._a_J[:] = helper.init_scalar(value, self.mesh)
def set_jz(self, value): self._jz[:] = helper.init_scalar(value, self.mesh)
def setup(self, mesh, spin, mu_s): super(CubicAnisotropy, self).setup(mesh, spin, mu_s) self._Kc = helper.init_scalar(self.Kc, self.mesh)
def setup(self, mesh, spin, Ms, Ms_inv): super(DMI, self).setup(mesh, spin, Ms, Ms_inv) if self.dmi_type == 'bulk': self.dmi_vector = np.array([ -1., 0, 0, 1., 0, 0, 0, -1., 0, 0, 1., 0, 0, 0, -1., 0, 0, 1. ]) elif self.dmi_type == 'interfacial': self.dmi_vector = np.array([ 0, -1., 0, # -x 0, 1., 0, # +x 1., 0, 0, # -y -1., 0, 0, # +y 0, 0, 0, # -z 0, 0, 0 # +z ]) elif self.dmi_type == 'D_2d': self.dmi_vector = np.array([ 1., 0, 0, # -x -1., 0, 0, # +x 0, -1., 0, # -y 0, 1., 0, # +y 0, 0, 0, # -z 0, 0, 0 # +z ]) # For the following DMIs with two constants check: # Leonov: Chiral skyrmion states in non-centrosymmetric magnets # https://arxiv.org/pdf/1406.2177.pdf # Leonov thesis: http://nbn-resolving.de/urn:nbn:de:bsz:14-qucosa-83823 elif self.dmi_type == 'D_n': self.dmi_vector = np.array([ -1, 0, 0, # D1 components 1, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # D2 components 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, ]) elif self.dmi_type == 'C_n': self.dmi_vector = np.array([ 0, -1., 0, # -x 0, 1., 0, # +x 1., 0, 0, # -y -1., 0, 0, # +y 0, 0, 0, # -z 0, 0, 0, # +z -1, 0, 0, # D2 components 1, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, ]) elif self.dmi_type == 'custom': self.dmi_vector = np.array(self.dmi_vector) # Example: # self.DMI_vector = [ 0, 0, D1, # DMI 1 # 0, 0, -D1, # 0, 0, 0, # 0, 0, 0, # 0, 0, 0, # 0, 0, 0, # 0, 0, 0, # DMI 2 # 0, 0, 0, # 0, D2, 0, # 0, -D2, 0, # 0, 0, 0, # 0, 0, 0, # ] n_Ds = len(self.dmi_vector) // 18 if len(self.dmi_vector) % 18 != 0: raise Exception('The DMI vector length must be a mult of 18: ' ' N of DMIs times 3 * number of ngbs = 18') if n_Ds > 1: self.Ds = helper.init_vector(self.D, self.mesh, dim=n_Ds) else: self.Ds = helper.init_scalar(self.D, self.mesh) self.n_dmis = n_Ds if self.dmi_type == 'C_n' or self.dmi_type == 'D_n': self.Ds = helper.init_vector(self.D, self.mesh, dim=2) self.n_dmis = 2 else: self.Ds = helper.init_scalar(self.D, self.mesh) self.n_dmis = 1