[docs]@dataclassclassDoubleOptMaker(Maker):""" Maker to perform a double Qchem relaxation. Parameters ---------- name : str Name of the flows produced by this maker. relax_maker1 : .BaseVaspMaker Maker to use to generate the first relaxation. relax_maker2 : .BaseVaspMaker Maker to use to generate the second relaxation. """name:str="double opt"opt_maker1:BaseQCMaker|None=field(default_factory=OptMaker)opt_maker2:BaseQCMaker=field(default_factory=OptMaker)
[docs]defmake(self,molecule:Molecule,prev_dir:str|Path|None=None)->Flow:""" Create a flow with two chained molecular optimizations. Parameters ---------- molecule : .Molecule A pymatgen Molecule object. prev_dir : str or Path or None A previous QChem calculation directory to copy output files from. Returns ------- Flow A flow containing two geometric optimizations. """jobs:list[Job]=[]ifself.opt_maker1:# Run a pre-relaxationopt1=self.opt_maker1.make(molecule,prev_dir=prev_dir)opt1.name+=" 1"jobs+=[opt1]molecule=opt1.output.optimized_moleculeprev_dir=opt1.output.dir_nameopt2=self.opt_maker2.make(molecule,prev_dir=prev_dir)opt2.name+=" 2"jobs+=[opt2]returnFlow(jobs,output=opt2.output,name=self.name)
[docs]@classmethoddeffrom_opt_maker(cls,opt_maker:BaseQCMaker)->DoubleOptMaker:""" Instantiate the DoubleRelaxMaker with two relax makers of the same type. Parameters ---------- opt_maker : .BaseQCMaker Maker to use to generate the first and second geometric optimizations. """returncls(relax_maker1=deepcopy(opt_maker),relax_maker2=deepcopy(opt_maker))
[docs]@dataclassclassFrequencyOptMaker(Maker):""" Maker to perform a frequency calculation after an optimization. Parameters ---------- name : str Name of the flows produced by this maker. opt_maker : .BaseQCMaker Maker to use to generate the opt maker freq_maker : .BaseQCMaker Maker to use to generate the freq maker """name:str="opt frequency"opt_maker:BaseQCMaker=field(default_factory=OptMaker)freq_maker:BaseQCMaker=field(default_factory=FreqMaker)
[docs]defmake(self,molecule:Molecule,prev_dir:str|Path|None=None)->Flow:""" Create a flow with optimization followed by frequency calculation. Parameters ---------- molecule : .Molecule A pymatgen Molecule object. prev_dir : str or Path or None A previous QChem calculation directory to copy output files from. Returns ------- Flow A flow containing with optimization and frequency calculation. """jobs:list[Job]=[]opt=self.opt_maker.make(molecule,prev_dir=prev_dir)opt.name="Geometry Optimization"jobs+=[opt]freq=self.freq_maker.make(molecule=opt.output.output.optimized_molecule,prev_dir=opt.output.dir_name,)freq.name="Frequency Analysis"jobs+=[freq]returnFlow(jobs,output={"opt":opt.output,"freq":freq.output},name=self.name)
[docs]@dataclassclassFrequencyOptFlatteningMaker(Maker):""" Maker to perform a frequency calculation after an optimization. Parameters ---------- name : str Name of the flows produced by this maker. opt_maker : .BaseQCMaker Maker to use to generate the opt maker freq_maker : .BaseQCMaker Maker to use to generate the freq maker """name:str="frequency flattening opt"opt_maker:BaseQCMaker=field(default_factory=OptMaker)freq_maker:BaseQCMaker=field(default_factory=FreqMaker)scale:float=1.0max_ffopt_runs:int=5
[docs]@jobdefmake(self,molecule:Molecule,mode:list|None=None,lowest_freq:float=-1.0,ffopt_runs:int=0,overwrite_inputs:dict|None=None,prev_dir:str|Path|None=None,)->Flow:""" Optimize geometry and perturb negative frequency modes. Parameters ---------- molecule : .Molecule A pymatgen Molecule object. prev_dir : str or Path or None A previous QChem calculation directory to copy output files from. Returns ------- Flow A flow containing with optimization and frequency calculation. """mode=modeor[[0.0,0.0,0.0]for_inrange(len(molecule))]ifoverwrite_inputsisnotNone:self.opt_maker.input_set_generator.overwrite_inputs=overwrite_inputsself.freq_maker.input_set_generator.overwrite_inputs=overwrite_inputsnew_flow=Nonenew_output=Noneif(lowest_freq<0)and(ffopt_runs<self.max_ffopt_runs):jobs:list[Job]=[]foridxinrange(len(molecule)):molecule.translate_sites(indices=[idx],vector=[self.scale*vforvinmode[idx]])opt=self.opt_maker.make(molecule,prev_dir=prev_dir)opt.name="Geometry Optimization"jobs+=[opt]molecule=opt.output.output.optimized_moleculefreq=self.freq_maker.make(molecule,prev_dir=prev_dir)freq.name=f"Frequency Analysis {ffopt_runs+1}"jobs+=[freq]recursive=self.make(molecule,mode=freq.output.output.frequency_modes[0],lowest_freq=freq.output.output.frequencies[0],ffopt_runs=ffopt_runs+1,prev_dir=prev_dir,)new_flow=Flow([*jobs,recursive],output=recursive.output)new_output=recursive.outputelifffopt_runs==0:freq=self.freq_maker.make(molecule,prev_dir=prev_dir)freq.name=f"Frequency Analysis {ffopt_runs+1}"new_flow=[freq]new_output=freq.outputreturnResponse(replace=new_flow,output=new_output)