[docs]classLammpsSimulator(base.ProcessSingleAtom):"""Can perform LAMMPS Simulations. Parameters ---------- lmp_exe: str This is the name or path of the LAMMPS executable. Either path to executable, "lmp" or "lamp_<machine>". See https://docs.lammps.org/Run_basics.html for more information lmp_params: str Path to file. To be able to change parameters with DVC and not have to change them manually in the input script, a params file in yaml format and corresponding template file must be provided. lmp_template: str Path to file. In combination with the params file this will be the input script for the LAMMPS simulation skiprun: bool, optional Whether to skip running LAMMPS or not, by default False Returns ------- None This function does not return anything. Instead, it creates a LAMMPS input script based on the specified template and parameter files, runs the LAMMPS simulation using the specified executable, and saves the simulation output to the specified directory. """"""A few remarks for future programmers: -If there is the error, that NPT.lammpstraj does not exist: that means there is an error in the inputscript. look at log.lammps in the nwd to see what is wrong - dont forget to "dvc init"... """lmp_directory:str=zntrack.outs_path(zntrack.nwd/"lammps")lmp_exe:str=zntrack.params("lmp_serial")skiprun:bool=False# outputsdump_file:pathlib.Path=zntrack.outs_path(zntrack.nwd/"NPT.lammpstraj")log_file:pathlib.Path=zntrack.outs_path(zntrack.nwd/"NPT.log")lmp_params:str=zntrack.params_path()lmp_template:str=zntrack.deps_path()
[docs]defget_atoms(self):# look where to get the input_trajectory (either ase.Atoms or file)ase.io.write(self.lmp_directory/"atoms.xyz",self.get_data())self.atoms_file=(pathlib.Path(self.lmp_directory/"atoms.xyz").resolve().as_posix())
[docs]deffill_atoms_with_life(self):# Give LAMMPS more information about the Atoms provided.# (e.g. Mass or Type (LAMMPS specific)).# This Function has to be executed after get_atoms has been executed,# otherwise there might not be a xyz file to read.# Charges have to be set by Hand in the LAMMPS-inputscript-Template.data=ase.io.read(self.atoms_file)# Atomic Numberself.atomic_numbers=data.get_atomic_numbers()# Atomic Massself.atomic_masses=data.get_masses()# Atom Symbolself.atomic_symbols=data.get_chemical_symbols()i=1atom_map={}forkinrange(len(self.atomic_numbers)):ifself.atomic_numbers[k]notinatom_map:atom_map[self.atomic_numbers[k]]=(i,self.atomic_masses[k],self.atomic_symbols[k],)i+=1self.atomic_type=[atom_map[num][0]fornuminself.atomic_numbers]self.atomic_masses=[tup[1]fortupinlist(atom_map.values())]self.atomic_symbols=[tup[2]fortupinlist(atom_map.values())]
[docs]defcreate_input_script(self):# Get parameter from yaml:withpathlib.Path(self.lmp_params).open("r")asstream:params=yaml.safe_load(stream)# Resolve paths for input filesinput_dict={}input_dict["log_file"]=self.log_file.resolve().as_posix()input_dict["dump_file"]=self.dump_file.resolve().as_posix()input_dict["input_trajectory"]=self.atoms_fileforkeyinparams["sim_parameters"]:input_dict[key]=params["sim_parameters"][key]# Fill input dict with information about the atoms# (all infos are gathered from the xyz file except charges)input_dict["atomic_type"]=self.atomic_typeinput_dict["atomic_masses"]=self.atomic_massesinput_dict["atomic_symbols"]=self.atomic_symbols# Get templateloader=FileSystemLoader(".")env=Environment(loader=loader)# , trim_blocks=True, lstrip_blocks=True)template=env.get_template(self.lmp_template)# Render Templateself.lmp_input_script=template.render(input_dict)withpathlib.Path(f"{self.lmp_directory}/input.script").open("w")asfile:file.write(self.lmp_input_script)# write input script to output directory
[docs]@classmethoddefget_template(self,filename:str="lmp.jinja2",name="lammps_npt.jinja2")->None:"""Get the template file. Parameters ---------- filename: str, optional The name where to write the template to. name: str, optional The name of the template, by default "lammps_npt.jinja2" Returns ------- """content=pkg_resources.read_text(static_data,name)withpathlib.Path(filename).open("w")asfile:file.write(content)ifname=="lammps_npt.jinja2":params={"temperature":300,"pressure":1.0,"barostat_factor":500,"steps":1000,"timestep":0.001,"dump_interval":100,"thermo_interval":100,}else:raiseNotImplementedError("Only lammps_npt.jinja2 is implemented")withpathlib.Path(filename).with_suffix(".yaml").open("w")asfile:yaml.dump({"sim_parameters":params},file)