def sundials_rhs(self, time, y, ydot): self.ode_count += 1 timer.start("sundials_rhs", self.__class__.__name__) self.compute_effective_field(y) ydot.shape = (self.total_image_num, -1) for i in range(self.image_num): h = self.Heff[i] t = self.tangents[i] sf = self.springs[i] h3 = h - np.dot(h, t) * t + sf * t ydot[i + 1, :] = h3[:] ydot[0, :] = 0 ydot[-1, :] = 0 ydot.shape = (-1, ) timer.stop("sundials_rhs", self.__class__.__name__) return 0
def sundials_rhs(self, t, y, ydot): self.t = t self._m.vector().set_local(y) for func in self._pre_rhs_callables: func(self.t) self.compute_effective_field() timer.start("sundials_rhs", self.__class__.__name__) # Use the same characteristic time as defined by c native_llb.calc_llb_dmdt(self._m.vector().array(), self.H_eff, self.dm_dt, self.material.T, self.pins, self._alpha, self.gamma_LL, self.material.Tc, self.do_precession) timer.stop("sundials_rhs", self.__class__.__name__) for func in self._post_rhs_callables: func(self) ydot[:] = self.dm_dt[:] return 0
def solve(self, t): # we don't use self.effective_field.compute(t) for performance reasons self.effective_field.update(t) H_eff = self.effective_field.H_eff[self.v2d_xxx] # alias (for readability) H_eff.shape = (3, -1) timer.start("solve", self.__class__.__name__) # Use the same characteristic time as defined by c char_time = 0.1 / self.c # Prepare the arrays in the correct shape m = self._m_field.get_ordered_numpy_array_xxx() m.shape = (3, -1) dmdt = np.zeros(m.shape) alpha__ = self.alpha.vector().array()[self.v2d_scale] # Calculate dm/dt if self.do_slonczewski: if self.fun_slonczewski_time_update != None: J_new = self.fun_slonczewski_time_update(t) self.J[:] = J_new native_llg.calc_llg_slonczewski_dmdt( m, H_eff, t, dmdt, self.pins, self.gamma, alpha__, char_time, self.Lambda, self.epsilonprime, self.J, self.P, self.d, self._Ms, self.p) elif self.do_zhangli: if self.fun_zhangli_time_update != None: J_profile = self.fun_zhangli_time_update(t) self._J = helpers.vector_valued_function(J_profile, self.S3) self.J = self._J.vector().array() self.compute_gradient_matrix() H_gradm = self.compute_gradient_field() H_gradm.shape = (3, -1) native_llg.calc_llg_zhang_li_dmdt( m, H_eff, H_gradm, t, dmdt, self.pins, self.gamma, alpha__, char_time, self.u0, self.beta, self._Ms) H_gradm.shape = (-1,) else: native_llg.calc_llg_dmdt(m, H_eff, t, dmdt, self.pins, self.gamma, alpha__, char_time, self.do_precession) dmdt.shape = (-1,) H_eff.shape = (-1,) timer.stop("solve", self.__class__.__name__) self._dmdt.vector().set_local(dmdt[self.d2v_xxx]) return dmdt
def sundials_rhs(self, t, y, ydot): self.t = t y.shape = (2, -1) self._m_field.set_with_numpy_array_debug(y[0]) self._delta_m.vector().set_local(y[1]) y.shape = (-1, ) self.effective_field.update(t) H_eff = self.effective_field.H_eff # alias (for readability) H_eff.shape = (3, -1) timer.start("sundials_rhs", self.__class__.__name__) # Use the same characteristic time as defined by c H_gradm = self.compute_gradient_field() H_gradm.shape = (3, -1) H_laplace = self.compute_laplace_field() H_laplace.shape = (3, -1) self.dm_dt.shape = (6, -1) m = self.m m.shape = (3, -1) char_time = 0.1 / self.c delta_m = self._delta_m.vector().array() delta_m.shape = (3, -1) native_llg.calc_llg_nonlocal_stt_dmdt(m, delta_m, H_eff, H_laplace, H_gradm, self.dm_dt, self.pins, self.gamma, self._alpha, char_time, self.P, self.tau_sd, self.tau_sf, self._Ms) timer.stop("sundials_rhs", self.__class__.__name__) self.dm_dt.shape = (-1, ) ydot[:] = self.dm_dt[:] H_gradm.shape = (-1, ) H_eff.shape = (-1, ) m.shape = (-1, ) delta_m.shape = (-1, ) return 0
def sundials_rhs(self, time, y, ydot): """ Right hand side of the optimization scheme used to find the minimum energy path. In our case, we use a LLG kind of equation: d Y / dt = Y x Y x D D = -( nabla E + [nabla E * t] t ) + F_spring where Y is an image: Y = (M_0, ... , M_N) and t is the tangent vector defined according to the energy of the neighbouring images (see Henkelman et al publication) If a climbing_image index is specified, the corresponding image will be iterated without the spring force and with an inversed component along the tangent """ # Update the ODE solver self.ode_count += 1 timer.start("sundials_rhs", self.__class__.__name__) # Compute the eff field H for every image, H = -nabla E # (derived with respect to M) self.compute_effective_field(y) # Reshape y and ydot in a matrix of total_image_num rows y.shape = (self.total_image_num, -1) ydot.shape = (self.total_image_num, -1) # Compute the total force for every image (not the extremes) # Rememeber that self.image_num = self.total_image_num - 2 # The total force is: # D = - (-nabla E + [nabla E * t] t) + F_spring # This value is different is a climbing image is specified: # D_climb = -nabla E + 2 * [nabla E * t] t for i in range(self.image_num): h = self.Heff[i + 1] t = self.tangents[i] sf = self.springs[i] if not (self.climbing_image and i == self.climbing_image): h3 = h - np.dot(h, t) * t + sf * t else: h3 = h - 2 * np.dot(h, t) * t h[:] = h3[:] #ydot[i+1, :] = h3[:] # Update the step with the optimisation algorithm, in this # case we use: dY /dt = Y x Y x D # (check the C++ code in finmag/native/src/) native_neb.compute_dm_dt(y, self.Heff, ydot) ydot[0, :] = 0 ydot[-1, :] = 0 y.shape = (-1, ) ydot.shape = (-1, ) timer.stop("sundials_rhs", self.__class__.__name__) return 0