1717 ForceFieldStaticMaker ,
1818 GAPRelaxMaker ,
1919 GAPStaticMaker ,
20+ M3GNetRelaxMaker ,
21+ M3GNetStaticMaker ,
22+ MACERelaxMaker ,
23+ MACEStaticMaker ,
24+ NequipRelaxMaker ,
25+ NequipStaticMaker ,
2026)
2127from atomate2 .vasp .flows .core import DoubleRelaxMaker
2228from atomate2 .vasp .flows .phonons import PhononMaker
2733from pymatgen .core import Molecule , Site
2834
2935from autoplex .data .common .jobs import generate_randomized_structures
36+ from autoplex .data .phonons .utils import ml_phonon_maker_preparation
3037
3138__all__ = [
3239 "DFTPhononMaker" ,
@@ -332,17 +339,17 @@ class MLPhononMaker(FFPhononMaker):
332339 High-throughput electronic band structure calculations:
333340 Challenges and tools. Computational Materials Science,
334341 49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010.
335- We will however use seekpath and primitive structures
342+ We will, however, use seekpath and primitive structures
336343 as determined by from phonopy to compute the phonon band structure
337- bulk_relax_maker : .ForceFieldRelaxMaker or None
344+ bulk_relax_maker: .ForceFieldRelaxMaker or None
338345 A maker to perform a tight relaxation on the bulk.
339346 Set to ``None`` to skip the
340347 bulk relaxation
341- static_energy_maker : .ForceFieldStaticMaker or None
348+ static_energy_maker: .ForceFieldStaticMaker or None
342349 A maker to perform the computation of the DFT energy on the bulk.
343350 Set to ``None`` to skip the
344351 static energy computation
345- phonon_displacement_maker : .ForceFieldStaticMaker or None
352+ phonon_displacement_maker: .ForceFieldStaticMaker or None
346353 Maker used to compute the forces for a supercell.
347354 generate_frequencies_eigenvectors_kwargs : dict
348355 Keyword arguments passed to :obj:`generate_frequencies_eigenvectors`.
@@ -364,6 +371,10 @@ class MLPhononMaker(FFPhononMaker):
364371 in the future
365372 store_force_constants: bool
366373 if True, force constants will be stored
374+ relax_maker_kwargs: dict
375+ Keyword arguments that can be passed to the RelaxMaker.
376+ static_maker_kwargs: dict
377+ Keyword arguments that can be passed to the StaticMaker.
367378 """
368379
369380 name : str = "ml phonon"
@@ -374,7 +385,7 @@ class MLPhononMaker(FFPhononMaker):
374385 )
375386 )
376387 phonon_displacement_maker : ForceFieldStaticMaker | None = field (
377- default_factory = lambda : GAPStaticMaker (name = "ml phonon static" )
388+ default_factory = lambda : GAPStaticMaker (name = "gap phonon static" )
378389 )
379390 static_energy_maker : ForceFieldStaticMaker | None = field (
380391 default_factory = lambda : GAPStaticMaker ()
@@ -383,11 +394,18 @@ class MLPhononMaker(FFPhononMaker):
383394 generate_frequencies_eigenvectors_kwargs : dict = field (
384395 default_factory = lambda : {"units" : "THz" , "tol_imaginary_modes" : 1e-1 }
385396 )
386- relax_maker_kwargs : dict = field (default_factory = dict )
387- static_maker_kwargs : dict = field (default_factory = dict )
397+ relax_maker_kwargs : dict | None = field (default_factory = dict )
398+ static_maker_kwargs : dict | None = field (default_factory = dict )
388399
389400 @job
390- def make_from_ml_model (self , structure , ml_model , suffix : str = "" , ** make_kwargs ):
401+ def make_from_ml_model (
402+ self ,
403+ structure ,
404+ potential_file ,
405+ ml_model : str = "GAP" ,
406+ calculator_kwargs : dict | None = None ,
407+ ** make_kwargs ,
408+ ):
391409 """
392410 Maker for GAP phonon jobs.
393411
@@ -397,10 +415,13 @@ def make_from_ml_model(self, structure, ml_model, suffix: str = "", **make_kwarg
397415 A pymatgen structure. Please start with a structure
398416 that is nearly fully optimized as the internal optimizers
399417 have very strict settings!
400- ml_model : str
401- Complete path to MLIP file(s).
402- suffix:
403- Train, test and MLIP suffix ("", "_wo_sigma", "_phonon", "_rand_struc").
418+ ml_model: str
419+ ML model to be used. Default is GAP.
420+ potential_file :
421+ Complete path to MLIP file(s)
422+ Train, test and MLIP files (+ suffixes "", "_wo_sigma", "_phonon", "_rand_struc").
423+ calculator_kwargs :
424+ Keyword arguments for the ASE Calculator.
404425 make_kwargs :
405426 Keyword arguments for the PhononMaker.
406427
@@ -409,41 +430,93 @@ def make_from_ml_model(self, structure, ml_model, suffix: str = "", **make_kwarg
409430 PhononMaker jobs.
410431
411432 """
412- ml_model = ml_model + f"/gap_file{ suffix } .xml"
413- if self .bulk_relax_maker is not None :
414- br = self .bulk_relax_maker
415- self .bulk_relax_maker = br .update_kwargs (
416- update = {
417- "calculator_kwargs" : {
418- "args_str" : "IP GAP" ,
419- "param_filename" : str (ml_model ),
420- },
421- ** self .relax_maker_kwargs ,
433+ if ml_model == "GAP" :
434+ if calculator_kwargs is None :
435+ calculator_kwargs = {
436+ "args_str" : "IP GAP" ,
437+ "param_filename" : str (potential_file ),
422438 }
439+
440+ ml_prep = ml_phonon_maker_preparation (
441+ bulk_relax_maker = self .bulk_relax_maker ,
442+ phonon_displacement_maker = self .phonon_displacement_maker ,
443+ static_energy_maker = self .static_energy_maker ,
444+ calculator_kwargs = calculator_kwargs ,
445+ relax_maker_kwargs = self .relax_maker_kwargs ,
446+ static_maker_kwargs = self .static_maker_kwargs ,
423447 )
424- if self . phonon_displacement_maker is not None :
425- ph_disp = self . phonon_displacement_maker
426- self . phonon_displacement_maker = ph_disp . update_kwargs (
427- update = {
428- "calculator_kwargs" : {
429- "args_str" : "IP GAP" ,
430- "param_filename" : str ( ml_model ),
431- } ,
432- ** self . static_maker_kwargs ,
448+
449+ elif ml_model == "J-ACE" :
450+ raise UserWarning ( "No atomate2 ACE.jl PhononMaker implemented." )
451+
452+ elif ml_model == "NEQUIP" :
453+ if calculator_kwargs is None :
454+ calculator_kwargs = {
455+ "model_path" : str ( potential_file ) ,
456+ "device" : "cuda" ,
433457 }
458+ else :
459+ calculator_kwargs .update ({"model_path" : str (potential_file )})
460+
461+ ml_prep = ml_phonon_maker_preparation (
462+ bulk_relax_maker = NequipRelaxMaker (
463+ relax_cell = True , relax_kwargs = {"interval" : 500 }
464+ ),
465+ phonon_displacement_maker = NequipStaticMaker (
466+ name = "nequip phonon static"
467+ ),
468+ static_energy_maker = NequipStaticMaker (),
469+ calculator_kwargs = calculator_kwargs ,
470+ relax_maker_kwargs = self .relax_maker_kwargs ,
471+ static_maker_kwargs = self .static_maker_kwargs ,
434472 )
435- if self .static_energy_maker is not None :
436- stat_en = self .static_energy_maker
437- self .static_energy_maker = stat_en .update_kwargs (
438- update = {
439- "calculator_kwargs" : {
440- "args_str" : "IP GAP" ,
441- "param_filename" : str (ml_model ),
442- },
443- ** self .static_maker_kwargs ,
444- }
473+
474+ elif ml_model == "M3GNET" :
475+ if calculator_kwargs is None :
476+ calculator_kwargs = {"path" : str (potential_file )}
477+
478+ ml_prep = ml_phonon_maker_preparation (
479+ bulk_relax_maker = M3GNetRelaxMaker (
480+ relax_cell = True , relax_kwargs = {"interval" : 500 }
481+ ),
482+ phonon_displacement_maker = M3GNetStaticMaker (
483+ name = "m3gnet phonon static"
484+ ),
485+ static_energy_maker = M3GNetStaticMaker (),
486+ calculator_kwargs = calculator_kwargs ,
487+ relax_maker_kwargs = self .relax_maker_kwargs ,
488+ static_maker_kwargs = self .static_maker_kwargs ,
445489 )
446490
491+ else : # MACE
492+ if calculator_kwargs is None :
493+ calculator_kwargs = {"model" : str (potential_file ), "device" : "cuda" }
494+ elif "model" in calculator_kwargs :
495+ calculator_kwargs .update (
496+ {"default_dtype" : "float64" }
497+ ) # Use float64 for geometry optimization.
498+ else :
499+ calculator_kwargs .update (
500+ {"model" : str (potential_file ), "default_dtype" : "float64" }
501+ )
502+
503+ ml_prep = ml_phonon_maker_preparation (
504+ bulk_relax_maker = MACERelaxMaker (
505+ relax_cell = True , relax_kwargs = {"interval" : 500 }
506+ ),
507+ phonon_displacement_maker = MACEStaticMaker (name = "mace phonon static" ),
508+ static_energy_maker = MACEStaticMaker (),
509+ calculator_kwargs = calculator_kwargs ,
510+ relax_maker_kwargs = self .relax_maker_kwargs ,
511+ static_maker_kwargs = self .static_maker_kwargs ,
512+ )
513+
514+ (
515+ self .bulk_relax_maker ,
516+ self .phonon_displacement_maker ,
517+ self .static_energy_maker ,
518+ ) = ml_prep
519+
447520 flow = self .make (structure = structure , ** make_kwargs )
448521 return Response (replace = flow , output = flow .output )
449522
0 commit comments