def __init__(self, name=None, do_demag=True, id="Generic Simulation class"): self.class_id = id # String identifying the kind of Simulation # class self.units = None # Simulation units used by this class self.do_demag = do_demag # Whether we should include the demag field # List of all the materials used by the Simulation object self.materials = None # Dictionary used by the hysteresis method to find abbreviations for # frequently used things to save or do. # Example: for ``sim.hysteresis(..., save=[('averages', at(...))])`` # the string 'averages' needs to be a key in this dictionary. # The corresponding value is the function to call. self.action_abbreviations = {} # Every quantity the user may want to save needs to be listed here self.known_quantities = known_quantities self.known_quantities_by_name = known_quantities_by_name self.known_field_quantities = known_field_quantities ### Set the simulation name if name == None: self.name = features.get('etc', 'runid') else: self.name = name log.info("Simulation(name=%s) object created" % self.name) ### Check whether the files we are going to write do already exist. # if this is the case we should stop, unless the --clean option was # given: we do not want to overwrite data as a default! self._restarting = False data_filenames = [ self._ndtfilename(), self._h5filename(), self._tolfilename() ] if features.get('nmag', 'clean', raw=True): # Existing data files should be deleted nsim.snippets.rename_old_files(data_filenames) elif features.get('nmag', 'restart', raw=True): log.info("Starting simulation in restart mode...") self._restarting = True else: # Check that no data files exist for filename in data_filenames: if os.path.exists(filename): msg = ("Error: Found old file %s -- cannot proceed. " "To start a simulation script with old data " "files present you either need to use '--clean' " "(and then the old files will be deleted), " "or use '--restart' in which case the run " "will be continued." % filename) raise NmagUserError(msg) # See documentation for SimulationClock object self.clock = SimulationClock() # The advance_time method does not allow to carry on the simulation # up to t = infinite. Sometimes we want to simulate for n steps, # without any time limits. However we must give a time limit. # This is then how we approximate t = infinite. # For now, we do not provide any function to set or change it. # The user should just use: # sim = Simulation() # sim.max_time_reached = SI(1000, "s") self.max_time_reached = SI(1, "s") # Add abbreviations so that things can be saved just by giving # corresponding ID strings. # Example: hysteresis(..., save=[('averages', ...)]) self.add_save_abbrev('save_averages', lambda sim: sim.save_data(avoid_same_step=True)) self.add_save_abbrev( 'save_fields', lambda sim: sim.save_data(fields='all', avoid_same_step=True)) self.add_save_abbrev( 'save_field_m', lambda sim: sim.save_data(fields=['m'], avoid_same_step=True)) self.add_save_abbrev('save_restart', lambda sim: sim.save_restart_file()) self.add_do_abbrev('do_next_stage', SimulationCore.hysteresis_next_stage) self.add_do_abbrev('do_exit', SimulationCore.hysteresis_exit) # Used to write the ndt file self._ndt_writer = ColWriter(out=self._ndtfilename()) self._ndt_writer.set_formats([('float', '% 25.13g'), ('int', '% 25d'), ('date', '% 25s'), ('pfield', '% 25.13g'), ('field', '% 25.13g')]) # The following list contains a description of the physics components # which are included in the physical model For example, # ["exch", "demag"] indicates that exchange and demag are included. # In this case, spin transfer torque is not. This information # is used to understand which fields are relevant and which are not # (so that we do not save empty fields). Following the previous # example, dm_dcurrent, current_density won't be saved. self._components = None