def test_value_set_update(): """ Test to check that the value member variable updates when set_value is called. """ init_value = [1., 2., 3.] second_value = [100., 200., 400.] zeeman = Zeeman(init_value) mesh = df.RectangleMesh(df.Point(0, 0), df.Point(1, 1), 10, 10) sim = finmag.Simulation(mesh, 1e5) sim.add(zeeman) zeeman.set_value(second_value) assert zeeman.value == second_value
def test_relax_two_times(): """ Test whether we can call the relax method on Sim two times in a row. """ mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(10, 10, 10), 2, 2, 2) Ms = 0.86e6 sim = Simulation(mesh, Ms) sim.set_m((1, 0, 0)) external_field = Zeeman((0, Ms, 0)) sim.add(external_field) sim.relax() t0 = sim.t # time needed for first relaxation external_field.set_value((0, 0, Ms)) sim.relax() t1 = sim.t - t0 # time needed for second relaxation assert sim.t > t0 assert abs(t1 - t0) < 1e-10
def hysteresis(sim, H_ext_list, fun=None, **kwargs): """ Set the applied field to the first value in `H_ext_list` (which should be a list of external field vectors) and then call the relax() method. When convergence is reached, the field is changed to the next one in H_ext_list, and so on until all values in H_ext_list are exhausted. Note: The fields in H_ext_list are applied *in addition to* any Zeeman interactions that are already present in the simulation. In particular, if only one external field should be present then do not add any Zeeman interactions before calling this method. If you would like to perform a certain action (e.g. save a VTK snapshot of the magnetisation) at the end of each relaxation stage, use the sim.schedule() command with the directive 'at_end=True' as in the following example: sim.schedule('save_vtk', at_end=True, ...) sim.hysteresis(...) *Arguments* H_ext_list: list of 3-vectors List of external fields, where each field can have any of the forms accepted by Zeeman.__init__() (see its docstring for more details). fun: callable The user can pass a function here (which should accept the Simulation object as its only argument); this function is called after each relaxation and determines the return value (see below). For example, if fun = (lambda sim: sim.m_average[0]) then the return value is a list of values representing the average x-component of the magnetisation at the end of each relaxation. All other keyword arguments are passed on to the relax() method. See its documentation for details. *Return value* If `fun` is not None then the return value is a list containing an accumulation of all the return values of `fun` after each stage. Otherwise the return value is None. """ if H_ext_list == []: return # Add a new Zeeman interaction, initialised to zero. H = Zeeman((0, 0, 0)) sim.add(H) # We keep track of the current stage of the hysteresis loop. cur_stage = 0 num_stages = len(H_ext_list) res = [] try: while True: H_cur = H_ext_list[cur_stage] log.info( "Entering hysteresis stage #{} ({} out of {}). Current field: " "{}".format(cur_stage, cur_stage + 1, num_stages, H_cur)) H.set_value(H_cur) sim.relax(**kwargs) cur_stage += 1 if fun is not None: retval = fun(sim) res.append(retval) log.debug("hysteresis callback function '{}' returned " "value: {}".format(fun.__name__, retval)) except IndexError: log.info("Hysteresis is finished.") log.info("Removing the applied field used for hysteresis.") sim.remove_interaction(H.name) return res or None