def mumag2_simulation(mesh_file, mesh_unit, Hs, m0): mat_Py = nmag.MagMaterial(name="Py", Ms=material.m_sat, exchange_coupling=material.exchange_coupling, llg_gamma_G=SI(0.2211e6, "m/(A*s)"), llg_damping=SI(1.0), llg_normalisationfactor=SI(0.01e12, "1/s") ) sim = nmag.Simulation("mumag2") if os.path.exists(mesh_file): sim.load_mesh(mesh_file, [("Py", mat_Py)], unit_length=mesh_unit) else: raise StandardError,"Need file %s" % mesh_file sim.set_m(m0) sim.set_timestepper_params(stopping_dm_dt=1.0*degrees_per_ns) #sim.set_timestepper_params(rel_tolerance=1e-6, abs_tolerance=1e-6) h_pars = [] m_pars = [] mxs = [] mys = [] ms = [] ts = [] def save_stuff(sim): t = sim.time H = Hs[sim.stage-1] print "Stage %d converged!" % sim.stage result = nfem.integrate_field(sim.fields["m"], "m_Py") volume = sim.region_volume("Py") m = [mi/volume for mi in result[0][1]] mx, my, mz = m h_par = (sets.projection(axis=H_direction, vector=H)/material.m_sat).value m_par = sets.projection(axis=H_direction, vector=m) h_pars.append(h_par) m_pars.append(m_par) mxs.append(mx) mys.append(my) ms.append(m) ts.append(t.value) from nsim.when import every, at sim.hysteresis(Hs, save=[(save_stuff, at('convergence')), ('averages', at('convergence'))]) hc = min(sets.intersections(0.0, zip(h_pars, m_pars))) mrx = min(sets.intersections(0.0, zip(mxs, h_pars))) mry = min(sets.intersections(0.0, zip(mys, h_pars))) results = {"h_pars":h_pars, "m_pars":m_pars, "mxs":mxs, "mys":mys, "ms":ms, "hc":hc, "mrx":mrx, "mry":mry, "ts":ts} return results
def simulation_relax(self, H_applied = None, save=[('averages', 'fields', at('stage_end'))], do = [], convergence_check=every('step', 5)): """ This method carries out the time integration of the LLG until the system reaches a (metastable) equilibrium. Internally, this uses the hysteresis_ loop command. :Parameters: `H_applied` : list of SI objects For a 3-d simulation, the SI-objects Hx, Hy and Hz would be specified as ``[Hx,Hy,Hz]``. Default value is ``None``, resulting in the currently applied external field ``H_ext`` being used. `save` : Schedule object Allows to define what data to save at what events. See documentation on the hysteresis_ method and on the ``Schedule`` object. `convergence_check` : every object The default value (``every('step', 5)`` specifies that we ask the time integrator to carry out 5 steps before we check for convergence. If in doubt, ignore this feature. """ log.debug("Entering 'relax'") fields = [H_applied] log.debug("Calling hysteresis(%s)" % str(fields)) return self.hysteresis(fields, save=save, do=do, convergence_check=convergence_check)
norm_list=[-3.0, [200], 3.0], units=SI(1e6, "A/m")) #-------------------------------------------- ## Here we set up the simulation # Create the simulation object sim = nmag.Simulation("uniaxial_1d", do_demag=True) # Creates the mesh from the layer structure sim.load_mesh("bar.nmesh.h5", [("Co", mat_Co)], unit_length=SI(1e-9, "m")) with open("debug.txt", "w") as f: sim.model.write_debug_info(f) sim.set_m(m0) # Set the initial magnetisation # Set additional parameters for the time-integration #sim.set_timestepper_params(stopping_dm_dt=1*degrees_per_ns) sim.set_params(ts_abs_tol=1e-6, ts_rel_tol=1e-6) #-------------------------------------------- ## Run the simulation to calculate the hysteresis loop from nsim.when import every, at sim.hysteresis(Hs, save=[('averages', at('convergence'))], convergence_check=every(5, 'step'))
sim = dyfe2_yfe2_dyfe2.setup() # -------------------------------------------- ## Run the simulation to calculate part of the hysteresis loop # Function used to save one magnetisation configuration save_m = lambda sim: sim.save_restart_file(m_file(sim.stage)) if pre_dyn: # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=5 * degrees_per_ns, ts_rel_tol=1e-5, ts_abs_tol=1e-5) sim.set_m(m0_Fe, "m_Fe2") # Set the initial magnetisation sim.set_m(m0_Dy, "m_Dy") sim.hysteresis(Hs, save=[("averages", at("convergence")), (save_m, at("convergence"))]) else: sim.set_current_density([1.0e13, 0.0, 0.0], unit=SI("A/m^2")) # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=0 * degrees_per_ns, ts_rel_tol=1e-8, ts_abs_tol=1e-7) def tune_run(H): scale = 3.95 - float(abs(H[2]) * mu0 / Tesla) if scale < 0.0: scale = -0.5 * scale scale += 0.2 max_time = 400.0 / scale write_time = max_time / 400.0 return 4 * max_time, 0.4 * write_time
#create simulation object sim = nmag.Simulation(periodic_bc=pbc.structure) # load mesh sim.load_mesh("periodic.nmesh", [("periodic-film", Py)], unit_length=SI(1e-9,"m") ) print ocaml.mesh_plotinfo_periodic_points_indices( sim.mesh.raw_mesh ) # function to set the magnetisation def perturbed_magnetisation(pos): x,y,z = pos newx = x*1e9 newy = y*1e9 if 8<newx<14 and -3<newy<3: # the magnetisation is twisted a bit return [1.0, 5.*(math.cos(math.pi*((newx-11)/6.)))**3 *\ (math.cos(math.pi*(newy/6.)))**3, 0.0] else: return [1.0, 0.0, 0.0] # set initial magnetisation sim.set_m(perturbed_magnetisation) # let the system relax generating spin waves s = SI("s") from nsim.when import every, at sim.relax(save=[('averages','fields', every('time', 0.05e-12*s) | at('convergence'))], do=[('exit', at('time', 10e-12*s))])
def simulation_hysteresis(self, H_ext_list, save=[('averages', 'fields', at('stage_end'))], do=[], convergence_check=every('step', 5), progress_message_minimum_delay=60): #Note we are using __argdoclong__ here (below this function). """ This method executes a simulation where the applied field is set in sequence to the values specified in ``H_ext_list``. The time integration proceeds with the same applied field until convergence is reached. At this point the field is changed to the next one in ``H_ext_list`` and the method ``reinitialise()`` is called to proceed with the simulation. The user can specify when to save data using the optional argument ``save``. This allows to carry out hysteresis loop computations and write the results to disk. Technically we say that this function performs a multi-stage simulation. In our terminology, a stage is a part of the simulation where the field does not change. Therefore, every value for the applied field specified in ``H_ext_list`` corresponds to a different stage. Stages are numbered starting from 1, which corresponds to ``H_ext_list[0]``. In general during stage number ``i`` the applied field is ``H_ext_list[i-1]``. :Parameters: `H_ext_list` : list of values for the applied field It is something like ``[H1, H2, H3, ...]``, where ``Hi`` is the triple of components of the applied field, i.e. SI objects having units of "A/m"; `save` : list of pairs ``(thing_to_save, when)`` ``thing_to_save`` is either a string or a function provided by the user and ``when`` is an instance of the class ``When``, i.e. an object which contains the specification of when "the thing" has to be saved. Possible string values for ``thing_to_save`` are: - ``"averages"``: to save the averages of all the fields together with other information (such as the stage number, the time reached, etc.). This is done calling the method ``save_data()``. Refer to its documentation for further details; - ``"fields"``: to save all the fields. The method ``save_data(fields='all')`` is called for this purpose; - ``"restart"``: to save the current magnetisation configuration and all the information needed to restart the simulation. `do` : list of pairs ``(thing_to_do, when)`` is very similar to the ``save`` argument, but is usually used for other purposes. ``thing_to_do`` is either a string or a function provided by the user and ``when`` is an instance of the class ``When``. Possible string values for ``thing_to_do`` are: - ``"next_stage"``: induces the hysteresis method to advance to the next stage; - ``"exit"``: induces the hysteresis method to exit, even if the hysteresis computation has not still reached its end. The user can provide his own function to save data. For example, the following three lines:: def my_fun(sim): sim.save_data() sim.hysteresis(..., save=[(my_fun, every('step', 10))]) are equivalent to:: sim.hysteresis(..., save=[('averages', every('step', 10))]) To specify when something has to be saved the module ``when`` is used. The functions ``at`` and ``every``, provided by this module, can refer to the following time variables: - ``step``: the step number from the beginning of the simulation; - ``stage_step``: the step number from the beginning of the current stage; - ``time``: the simulation time passed from the beginning of the simulation (measured in SI_ objects); - ``stage_time``: the simulation time passed from the beginning of the current stage; - ``stage``: the number of the current stage; - ``convergence``: a boolean value which is ``True`` if the convergence criterion is satisfied. Use in this way ``at('convergence')`` Remember that you can combine time specifications using the operator | (or) and & (and):: every('stage', 2) & at('convergence') --> only at convergence of odd stages every('step', 10) | at('convergence') --> at convergence and every 10 steps. Some usage examples:: # Save fields (which implicitly will save the averages as well) # when the magnetisation stops changing for each applied field # (i.e. save at convergence): sim.hysteresis(..., save=[('fields', at('convergence'))]) # Averages will be saved every 10 steps, fields (and # implicitely averages) will be saved at convergence. sim.hysteresis(..., save=[('averages', every('step', 10)), ('fields', at('convergence'))]) # Each stage will not last more than 10 ps, even # if the magnetisation is not relaxed yet. sim.hysteresis(..., do=[('next_stage', at('stage_time', SI(1e-11, "s")))]) # Exit hysteresis loop simulation if the total number of # steps exceeds 1e6, save fields every 100 steps and at # convergence before that: sim.hysteresis(..., save=[('fields', every('step', 100) | at('convergence'))], do =[('exit', at('step', 1e6))]) # Save averages every 0.1 ns (useful for fourier transform) # leave after 20 ns (using the related relax_ command) sim.relax(save=[('averages', every('time', SI(1e-10, 's')))], do =[('exit', at('time', SI(20e-9, 's')))]) # Save averages every nanosecond, and fields every 100 ns. sim.relax(save=[('averages',every('time', SI(1e-9, 's'))), ('fields', every('time', SI(100e-9,'s')))]) # Save averages every nanosecond, and fields every 100 ns, # save restart file every 1000 steps sim.relax(save=[('averages',every('time', SI(1e-9, 's'))), ('fields', every('time', SI(100e-9, 's'))), ('restart', every('step', 1000))]) If ``save`` is not given, averages and fields will be saved whenever the stage ends (this is the default behaviour). """ log.debug("simulation_hysteresis(): Entering with H_ext_list=%s, " "save=%s, do=%s, convergence_check=%s" % (H_ext_list,save,do,convergence_check)) # This function will check for the correctness of the specifications # for the list of (thing to save, when) and (thing to do, when). # It will return a joint list of tuples (fn, when), where fn is a function # to be called with the simulation object as argument. thing_when_tuples = \ _join_save_and_do_lists(save, do, predefined_actions=self.action_abbreviations) log.debug("simulation_hysteresis(): thing_when_tuples=%s" % thing_when_tuples) # Dictionary containing the predicted time for the next saving # for each item specified inside the optional argument 'save' next_save_time = {} for what, _ in thing_when_tuples: key = str(what) # If what is a function we convert it # to string and then use it as the key if key in next_save_time: msg = ( "Error in optional argument 'save' or 'do' of method " "'hysteresis': the list of (thing_to_save, when) " "contains two or more specifications for " "thing_to_save = %s. You should remove the duplicate " "entry and eventually use the operator | (such as in: " "(thing_to_save, when1 | when2))." % key) raise NmagUserError, msg next_save_time[key] = None # We need this in comparisons of times (this is to solve # bugs in comparisons related to truncation errors) negligible_time = SI(1e-20, "s") match_tolerances = {'time': negligible_time, 'stage_time': negligible_time} def my_next_time(event, clock): return _next_time(event, clock, tols=match_tolerances) def my_next_deltas(event, clock, suggest=None): return _next_deltas(event, clock, suggest=suggest, tols=match_tolerances) progress_file_name = self.name + "_progress.txt" # Continue from the last restart file if required if self._restarting: log.info("Hysteresis loop: restarting from a previously saved " "configuration...") self.load_restart_file() self._restarting = False # To avoid affecting next calls to hysteresis else: log.info("Hysteresis loop: starting a new simulation.") log.info("Hysteresis loop: check file '%s' for progress data" % progress_file_name) # Loop over the given fields stage = self.clock.stage self.clock.exit_hysteresis = False for H_ext in H_ext_list[stage-1:]: log.info("hysteresis: starting new stage: field = %s" % str_of_SI_vector(H_ext)) self.do_next_stage(stage=stage) stage = None # Next time, just increase the stage counter self.clock.stage_end = False if H_ext: self.set_H_ext(H_ext) self.reinitialise(initial_time=0) # First of all we run over the list of things to save # and take note about when we should save what for what, when in thing_when_tuples: key = str(what) next_save_time[key] = my_next_time(when, self.clock) log.debug("hysteresis: will save %s at %s" % (what, next_save_time[key])) #if when.match_time(self.clock1): (get_saver(what))(self) # Simulate one stage: loop until convergence! # NOTE: we avoid something like 'while self.converged()', # because we want to check for saving fields # if convergence is reached! while True: self.clock.stage_end = converged = self.is_converged() log.debug("hysteresis loop, stage %d, converged = %s" % (self.clock.stage, str(converged))) # Find out the next time we need to check for convergence deltas = my_next_deltas(convergence_check, self.clock) log.debug("Time to next event: deltas = %s", str(deltas)) # We now see what needs to be saved. The strategy # is the following: if the expected time for saving # has changed, then it means that we need to save. # time passed the time scheduled for saving! for what, when in thing_when_tuples: key = str(what) time_matches = when.match_time(self.clock) nst = my_next_time(when, self.clock) # BUG: the comparison nst != next_save_time[key] # will misteriously fail sometimes. The reason # is that (a - b) + b != a for some a and b! # This is due to truncation errors! if time_matches or nst != next_save_time[key]: log.debug("hysteresis: analysing %s: time planned "\ "for saving was %s, now is %s. Matching? %s" % (what, str(next_save_time[key]), str(nst), str(time_matches))) log.info("hysteresis: saving %s at id=%s,step=%s.\n%s" % (what, self.clock.id, self.clock.step, str(self.clock))) what(self) next_save_time[key] = nst deltas = my_next_deltas(when, self.clock, suggest=deltas) # NOTE: we are doing two times the call to the method # 'next_time' of the class When: this is not ideal! (delta_step, delta_time, delta_real_time) = deltas log.debug("hysteresis: current time is %s" % (str(self.clock.time))) log.debug("predicted advance: " "delta_step=%s, delta_time=%s, delta_real_time=%s" % (str(delta_step), str(delta_time), str(delta_real_time))) if delta_time == None: # This is not ideal, we want to run forever, # but the advance_time method does not allow # such a speficication! target_time = self.max_time_reached else: target_time = self.clock.stage_time + delta_time if delta_step == None: delta_step = -1 if self.clock.exit_hysteresis: log.debug("Exit from the hysteresis loop has been forced " "using the tag 'exit': exiting now!") return if self.clock.stage_end: log.debug("Reached end of stage in hysteresis command, " "converged=%s, exiting now!" % converged) break log.debug("About to call advance time with target_time=%s " "and max_it=%s" % (str(target_time),delta_step)) time_reached = self.advance_time(target_time, max_it=delta_step) if time_reached > 0.99*self.max_time_reached: msg = ("Simulation time reached %s: are you starting from " "a zero torque configuration?" % self.max_time_reached) raise NmagUserError, msg # Write some progress data into progress file try: _update_progress_file(self, H_ext, progress_file_name, progress_message_minimum_delay) except Exception as excp: log.info("Problem when generating progress file. " "Got exception: %s." % str(excp))
# Set the coupling between the two magnetisations Fe3O4_CoFe2O4_lc = Fe3O4_CoFe2O4_sup_lc*mesh_unit*discretization sim.set_local_magnetic_coupling(mat_Fe3O4, mat_CoFe2O4, Fe3O4_CoFe2O4_lc) # Creates the mesh from the layer structure mesh_file_name = 'run.nmesh' mesh_lists = unidmesher.mesh_1d(layers, discretization) unidmesher.write_mesh(mesh_lists, out=mesh_file_name) # Load the mesh if os.path.exists(mesh_file_name): sim.load_mesh(mesh_file_name, mats, unit_length=SI(1e-9, "m")) else: raise StandardError,"Need file %s" % mesh_file # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=1*degrees_per_ns, ts_rel_tol=1e-6, ts_abs_tol=1e-6) #-------------------------------------------- ## Run the simulation to calculate the hysteresis loop sim.set_m(m0_Fe3O4, 'm_Fe3O4') # Set the initial magnetisations sim.set_m(m0_CoFe2O4, 'm_CoFe2O4') from nsim.when import every, at sim.hysteresis(Hs, save=[('averages', at('convergence')), ('fields', at('convergence'))], convergence_check=every(5, 'step'))
llg_damping=SI(0.5), llg_normalisationfactor=SI(0.001e12, "1/s")) # Create the simulation object sim = nmag.Simulation(do_demag=False) # Creates the mesh from the layer structure mesh_file_name = '%s.nmesh' % mesh_name if not os.path.exists(mesh_file_name) or new_mesh: print "Creating the mesh" mesh_lists = unidmesher.mesh_1d(layers, discretization) unidmesher.write_mesh(mesh_lists, out=mesh_file_name) # Load the mesh if os.path.exists(mesh_file_name): sim.load_mesh(mesh_file_name, [("Py", mat_Py)], unit_length=SI(1e-9, "m")) else: raise StandardError,"Need file %s" % mesh_file sim.set_m(m0) # Set the initial magnetisation #-------------------------------------------- ## Run the simulation to calculate the hysteresis loop from nsim.when import every, at sim.hysteresis(Hs, save=[('averages', 'restart', at('convergence'))], do=[(simulate_kill, at('time', 105*ps))], convergence_check=every(5, 'step'))
# load mesh sim.load_mesh("periodic.nmesh", [("periodic-film", Py)], unit_length=SI(1e-9, "m")) print ocaml.mesh_plotinfo_periodic_points_indices(sim.mesh.raw_mesh) # function to set the magnetisation def perturbed_magnetisation(pos): x, y, z = pos newx = x * 1e9 newy = y * 1e9 if 8 < newx < 14 and -3 < newy < 3: # the magnetisation is twisted a bit return [1.0, 5.*(math.cos(math.pi*((newx-11)/6.)))**3 *\ (math.cos(math.pi*(newy/6.)))**3, 0.0] else: return [1.0, 0.0, 0.0] # set initial magnetisation sim.set_m(perturbed_magnetisation) # let the system relax generating spin waves s = SI("s") from nsim.when import every, at sim.relax(save=[('averages', 'fields', every('time', 0.05e-12 * s) | at('convergence'))], do=[('exit', at('time', 10e-12 * s))])
-40.0, -40.5, [], -60.0, ] # From the norms and the direction (which is constant) we derive # all the values that the applied field will take during the simulation Hs = sets.vector_set(direction=B_direction, norm_list=B_norms, units=B_unit / mu0) # remember that H = B/mu0 # A small deviation to avoid points of unstable equilibrium H_dev = [SI(0.005e6, "A/m"), SI(0.005e6, "A/m"), 0] Hs = [[Hi + H_devi for Hi, H_devi in zip(H, H_dev)] for H in Hs] # -------------------------------------------- # The system setup is done inside the module dyfe2_yfe2_dyfe2 dyfe2_yfe2_dyfe2 = DyFe2_YFe2_DyFe2("hloop", 1.0, norm_factor=0.001e12) sim = dyfe2_yfe2_dyfe2.setup() # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=5 * degrees_per_ns, ts_rel_tol=1e-5, ts_abs_tol=1e-5) # -------------------------------------------- ## Run the simulation to calculate part of the hysteresis loop sim.set_m(m0_Fe, "m_Fe2") # Set the initial magnetisation sim.set_m(m0_Dy, "m_Dy") sim.hysteresis(Hs, save=[("averages", at("convergence"))])
sim = nmag.Simulation("spinwaves", do_demag=False) # load mesh sim.load_mesh("film.nmesh", [("film", Py)], unit_length=SI(1e-9, "m")) # function to set the magnetisation def perturbed_magnetisation(pos): x, y, z = pos newx = x * 1e9 newy = y * 1e9 if 8 < newx < 14 and -3 < newy < 3: # the magnetisation is twisted a bit return [ 1.0, 5. * (math.cos(math.pi * ((newx - 11) / 6.)))**3 * (math.cos(math.pi * (newy / 6.)))**3, 0.0 ] else: return [1.0, 0.0, 0.0] # set initial magnetisation sim.set_m(perturbed_magnetisation) # let the system relax generating spin waves s = SI("s") from nsim.when import every, at sim.relax(save=[('averages', every('time', 0.05e-12 * s) | at('convergence'))], do=[('exit', at('time', 10e-12 * s))])
sim.set_pinning(pinning) #-------------------------------------------- ## Run the simulation to calculate the hysteresis loop if preliminary: sim.set_m(m0) # Set the initial magnetisation # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=1.0*degrees_per_ns, ts_rel_tol=1e-7, ts_abs_tol=1e-7) from nsim.when import every, at sim.hysteresis([None], save=[('fields', at('stage_end')), ('averages', every('time', SI(5e-12, 's'))), ('restart', at('stage_end') | at('time', SI(100e-12, 's')))], do=[('exit', at('time', SI(5000e-12, 's')))], convergence_check=every(5, 'step')) commands.getoutput("mv *_restart.h5 %s" % initial_m_file) sys.exit(0) else: sim.load_m_from_h5file(initial_m_file) sim.set_current_density([j, 0.0, 0.0]) # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=0.0*degrees_per_ns, ts_rel_tol=1e-7, ts_abs_tol=1e-7)
## Here we set up the simulation # Create the simulation object sim = nmag.Simulation("uniaxial_1d", do_demag=False) # Creates the mesh from the layer structure mesh_file_name = "%s.nmesh" % mesh_name if not os.path.exists(mesh_file_name) or new_mesh: print "Creating the mesh" mesh_lists = unidmesher.mesh_1d(layers, discretization) unidmesher.write_mesh(mesh_lists, out=mesh_file_name) # Load the mesh if os.path.exists(mesh_file_name): materials = [("Co", mat_Co)] sim.load_mesh(mesh_file_name, materials, unit_length=SI(1e-9, "m")) else: raise StandardError, "Need file %s" % mesh_file sim.set_m(m0) # Set the initial magnetisation # Set additional parameters for the time-integration # sim.set_timestepper_params(stopping_dm_dt=1*degrees_per_ns) # -------------------------------------------- ## Run the simulation to calculate the hysteresis loop from nsim.when import every, at sim.hysteresis(Hs, save=[("averages", at("convergence"))], convergence_check=every(5, "step"))
# -------------------------------------------- ## Run the simulation to calculate the hysteresis loop if preliminary: sim.set_m(m0) # Set the initial magnetisation # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=1.0 * degrees_per_ns, ts_rel_tol=1e-7, ts_abs_tol=1e-7) from nsim.when import every, at sim.hysteresis( [None], save=[ ("fields", at("stage_end")), ("averages", every("time", SI(5e-12, "s"))), ("restart", at("stage_end") | at("time", SI(100e-12, "s"))), ], do=[("exit", at("time", SI(500e-12, "s")))], convergence_check=every(5, "step"), ) commands.getoutput("mv *_restart.h5 %s" % initial_m_file) sys.exit(0) else: sim.load_m_from_h5file(initial_m_file) sim.set_current_density([j, 0.0, 0.0]) # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=0.0 * degrees_per_ns, ts_rel_tol=1e-7, ts_abs_tol=1e-7)
angle_deg = 45 angle_rad = angle_deg/360.*2*math.pi sim.set_m([math.cos(angle_rad), 0, math.sin(angle_rad)]) sim.set_params(ts_rel_tol=2.7e-05 , ts_abs_tol=2.7e-05) # From the norms and the direction (which is constant) we derive # all the values that the applied field will take during the simulation Hs = sets.vector_set(direction=[1, -2, 3], norm_list=[-1.0, [50], 1.0], units=SI(1e6, "A/m")) t.stop("init") t.start("loop") def save_averages(sim): t.start("write") sim.save_data(fields='all', avoid_same_step=True) t.stop("write") from nsim.when import every, at sim.hysteresis(Hs, save=[(save_averages, at("convergence"))]) t.stop("loop") t.stop("total") t.set("sim", t.get("loop") - t.get("write")) t.show() print "=== LAM Timings ===\n", sim.get_timers() #print "=== CVODE Timings ===\n", sim.timestepper.get_stats()
#-------------------------------------------- ## Run the simulation to calculate part of the hysteresis loop # Function used to save one magnetisation configuration save_m = lambda sim: sim.save_restart_file(m_file(sim.stage)) if pre_dyn: # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=5*degrees_per_ns, ts_rel_tol=1e-5, ts_abs_tol=1e-5) sim.set_m(m0_Fe, 'm_Fe2') # Set the initial magnetisation sim.set_m(m0_Dy, 'm_Dy') sim.hysteresis(Hs, save=[('averages', at('convergence')), (save_m, at('convergence'))]) else: # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=0*degrees_per_ns, ts_rel_tol=1e-8, ts_abs_tol=1e-7) def tune_run(H): scale = 3.95 - float(abs(H[2])*mu0/Tesla) if scale < 0.0: scale = -0.5*scale scale += 0.2 max_time = 400.0/scale write_time = max_time/400.0 return max_time, write_time
hp = {} hp['nfdeg'] = 4 hp['nmin'] = 20 hp['p'] = 4 hp['eta'] = 2.0 hp['eps'] = 0.0001 restart_file = "relax_restart.h5" if not os.path.exists(restart_file): llg_damping = 1.0 llg_xi = 0.0 j = 0 # A/m^2 llg_polarisation = 0.0 stopping_dm_dt = (0.01*180/math.pi) * degrees_per_ns sim_name = "relax" save = [('averages', every(1000, 'step') | at('convergence')), ('restart', at('stage_end')), ('fields', at('step', 0))] do = [('exit', at("time", SI(5e-9, "s")))] else: llg_damping = 0.1 llg_xi = 0.05 j = 1e12 # A/m^2 llg_polarisation = 1.0 stopping_dm_dt=0.0 sim_name = "stt" save = [('fields', at('convergence') | every('time', SI(1.0e-9, "s"))), ('averages', every('time', SI(0.05e-9, "s")) | at('stage_end')), ('restart', every('time', SI(0.25e-9, "s")))] do = [('exit', at("time", SI(16e-9, "s")))]
norm_list=B_norms, units=B_unit/mu0) # remember that H = B/mu0 # A small deviation to avoid points of unstable equilibrium H_dev = [SI(0.005e6, "A/m"), SI(0.005e6, "A/m"), 0] Hs = [[Hi+H_devi for Hi, H_devi in zip(H, H_dev)] for H in Hs] #-------------------------------------------- # The system setup is done inside the module dyfe2_yfe2_dyfe2 dyfe2_yfe2_dyfe2 = DyFe2_YFe2_DyFe2("hloop", 1.0, norm_factor=0.001e12, P=1.0) sim = dyfe2_yfe2_dyfe2.setup() # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=5*degrees_per_ns, ts_rel_tol=1e-5, ts_abs_tol=1e-5) #-------------------------------------------- ## Run the simulation to calculate part of the hysteresis loop sim.set_m(m0_Fe, 'm_Fe2') # Set the initial magnetisation sim.set_m(m0_Dy, 'm_Dy') sim.set_current_density([1.0e13, 0.0, 0.0], unit=SI("A/m^2")) sim.hysteresis(Hs, save=[('averages', at('stage_end'))], do=[('next_stage', at('stage_time', SI(20e-12, "s")))])
H_funcs = [H_func(H, H_pinning) for H in Hs] if go_fast: # Set additional parameters for the time-integration sim.set_timestepper_params(stopping_dm_dt=0.1*degrees_per_ns, rel_tolerance=1e-7, abs_tolerance=1e-9) # Just go rapidly (high damping) to the configuration we want to study sim.set_m(m0) # Set the initial magnetisation sim.set_j(j) # Set the current density from nsim.when import every, at save_m = lambda sim: sim.save_restart_field(m_file(sim.stage)) sim.hysteresis(H_funcs, save=[('fields', at('convergence'))], convergence_check=every(5, 'step')) sim.save_restart_field(m0_file) else: # Set additional parameters for the time-integration sim.set_timestepper_params(stopping_dm_dt=5*degrees_per_ns, rel_tolerance=1e-7, abs_tolerance=1e-8) from nsim.when import every, at def min_diff(x_list, x): return min([abs(xi - x) for xi in x_list]) sim.set_j(j) # Set the current density new_Hs = []
#-------------------------------------------- ## Run the simulation to calculate the hysteresis loop if go_fast: sim.set_m(m0) # Set the initial magnetisation # Set additional parameters for the time-integration sim.set_params(stopping_dm_dt=1.0*degrees_per_ns, ts_rel_tol=1e-6, ts_abs_tol=1e-6) from nsim.when import every, at sim.hysteresis([None], save=[('fields', every('time', SI(0.1e-9, 's'))), ('averages', every('time', SI(500e-12, 's'))), ('restart', at('stage_end') | at('time', SI(100e-12, 's')))], do=[('exit', at('time', SI(1e-9, 's')))], convergence_check=every(5, 'step')) commands.getoutput("mv *_restart.h5 %s" % initial_m_file) sys.exit(0) else: def change_current(j): def fn(sim): sim.set_current_density([j, 0.0, 0.0]) return fn sim.load_m_from_h5file(initial_m_file) sim.set_current_density([0.0, 0.0, 0.0])
H_funcs = [H_func(H) for H in Hs] if go_fast: # Set additional parameters for the time-integration sim.set_timestepper_params(stopping_dm_dt=1.0*degrees_per_ns, rel_tolerance=1e-7, abs_tolerance=1e-7) # Just go rapidly (high damping) to the configuration we want to study sim.set_m(m0) # Set the initial magnetisation sim.set_j([j, 0.0, 0.0]) # Set the current density from nsim.when import every, at save_m = lambda sim: sim.save_restart_field(m_file(sim.stage)) sim.hysteresis(H_funcs, save=[('fields', at('convergence') & every(2, 'stage')), ('averages', every('time', SI(5e-12, 's'))), (lambda sim: sys.exit(0), at('time', SI(110e-12, 's'))), (save_m, at('convergence') | at('time', SI(100e-12, 's')))], convergence_check=every(5, 'step')) sim.save_restart_field(m0_file) else: # Set additional parameters for the time-integration sim.set_timestepper_params(stopping_dm_dt=1e-3*degrees_per_ns, rel_tolerance=1e-7, abs_tolerance=1e-8) from nsim.when import every, at def min_diff(x_list, x): return min([abs(xi - x) for xi in x_list])
#-------------------------------------------- ## Run the simulation to calculate the hysteresis loop if go_fast: # Just go rapidly (high damping) to the configuration we want to study sim.set_m(m0_Fe, 'm_Fe2') # Set the initial magnetisation sim.set_m(m0_Dy, 'm_Dy') #sim.set_j(j) # Set the current density from nsim.when import every, at save_m = lambda sim: sim.save_restart_file(m_file(sim.stage)) sim.hysteresis(Hs, save=[ #('fields', every(50, 'step')), ('averages', at('convergence')), (save_m, at('convergence'))], convergence_check=every(5, 'step')) sim.save_restart_file(m0_file) else: from nsim.when import every, at def min_diff(x_list, x): return min([abs(xi - x) for xi in x_list]) #delta_H = delta_B/mu0 sim.set_j(j) # Set the current density new_Hs = [] num_H = 0 for H, this_B_norm in zip(Hs, B_norms):