class RunCommand(Command): @classmethod def add_parser(cls, subparser): parser = subparser.add_parser('run', help='run ...') cls.add_arguments(parser) @classmethod def add_arguments(cls, parser): parser.add_argument('--after') calculator = getattr(cls, '_calculator', None) if calculator is None: parser.add_argument( '-c', '--calculator', default='emt', help='...') else: parser.add_argument( '-c', '--calculator', default=calculator.name, help=argparse.SUPPRESS) parser.add_argument('-p', '--parameters', default='', metavar='key=value,...', help='Comma-separated key=value pairs of ' + 'calculator specific parameters.') parser.add_argument('-l', '--use-lock-file', action='store_true', help='Skip calculations where the json ' + 'lock-file or result file already exists.') parser.add_argument( '--properties', default='efsdMm', help='Default value is "efsdMm" meaning calculate energy, ' + 'forces, stress, dipole moment, total magnetic moment and ' + 'atomic magnetic moments.') lock = None def run(self, atoms, name): args = self.args if self.lock is None: # Create lock object: if args.use_lock_file: self.lock = Lock(self.get_filename(ext='lock')) else: self.lock = OpenLock() skip = False if args.use_lock_file: try: filename = self.get_filename(ext='json') self.lock.acquire() if os.path.isfile(filename): data = read_json(filename) if name in data: skip = True else: data[name] = {} write_json(filename, data) else: write_json(filename, {name: {}}) finally: self.lock.release() if not skip: self.set_calculator(atoms, name) tstart = time.time() try: data = self.calculate(atoms, name) except KeyboardInterrupt: raise except Exception: self.log(name, 'FAILED') traceback.print_exc(file=self.logfile) else: tstop = time.time() data['time'] = tstop - tstart self.write(name, data) def set_calculator(self, atoms, name): args = self.args cls = get_calculator(args.calculator) if self._calculator is None: namespace = {} else: namespace = self._calculator.namespace parameters = str2dict(args.parameters, namespace) if getattr(cls, 'nolabel', False): atoms.calc = cls(**parameters) else: atoms.calc = cls(label=self.get_filename(name), **parameters) def calculate(self, atoms, name): args = self.args data = {} for p in args.properties: property, method = {'e': ('energy', 'get_potential_energy'), 'f': ('forces', 'get_forces'), 's': ('stress', 'get_stress'), 'd': ('dipole', 'get_dipole_moment'), 'M': ('magmom', 'get_magnetic_moment'), 'm': ('magmoms', 'get_magnetic_moments')}[p] try: x = getattr(atoms, method)() except NotImplementedError: pass else: data[property] = x if args.after: exec args.after in {'atoms': atoms, 'data': data} return data def write(self, name, data): filename = self.get_filename(ext='json') try: self.lock.acquire() if os.path.isfile(filename): alldata = read_json(filename) else: alldata = {} alldata[name] = data write_json(filename, alldata) finally: self.lock.release()