@@ -203,7 +203,18 @@ def from_qe_out(cls, params, path):
203203 @property
204204 def feature_size (self ):
205205 """Get dimension of this target if used as feature in ML."""
206- return self .parameters .ldos_gridsize
206+ if isinstance (self .parameters .ldos_gridsize , int ):
207+ return self .parameters .ldos_gridsize
208+ elif isinstance (self .parameters .ldos_gridsize , list ):
209+ # For splits, we sum up the individual grid sizes, BUT we
210+ # have to subtract one for each split, as the last energy
211+ # of each section gets discarded. So for three sections,
212+ # we have to subtract 2.
213+ return (
214+ np .sum (self .parameters .ldos_gridsize )
215+ - len (self .parameters .ldos_gridsize )
216+ + 1
217+ )
207218
208219 @property
209220 def data_name (self ):
@@ -269,7 +280,7 @@ def invalidate_target(self):
269280 @cached_property
270281 def energy_grid (self ):
271282 """Energy grid on which the DOS is expressed."""
272- return self .get_energy_grid ()
283+ return self ._get_energy_grid ()
273284
274285 @cached_property
275286 def band_energy (self ):
@@ -416,7 +427,7 @@ def read_from_qe_dos_txt(self, path):
416427
417428 Parameters
418429 ----------
419- path : string
430+ path : string or List
420431 Path of the file containing the DOS.
421432
422433 Returns
@@ -428,26 +439,52 @@ def read_from_qe_dos_txt(self, path):
428439 # check whether we have a correct file.
429440
430441 energy_grid = self .energy_grid
431- return_dos_values = []
432-
433- # Open the file, then iterate through its contents.
434- with open (path , "r" ) as infile :
435- lines = infile .readlines ()
436- i = 0
437-
438- for dos_line in lines :
439- # The first column contains the energy value.
440- if "#" not in dos_line and i < self .parameters .ldos_gridsize :
441- e_val = float (dos_line .split ()[0 ])
442- dosval = float (dos_line .split ()[1 ])
443- if (
444- np .abs (e_val - energy_grid [i ])
445- < self .parameters .ldos_gridspacing_ev * 0.98
446- ):
447- return_dos_values .append (dosval )
448- i += 1
449-
450- array = np .array (return_dos_values )
442+
443+ if isinstance (path , str ):
444+ readpaths = [path ]
445+ else :
446+ readpaths = path
447+
448+ current_energy_index = 0
449+
450+ for path_index , readpath in enumerate (readpaths ):
451+ return_dos_values = []
452+
453+ # Open the file, then iterate through its contents.
454+ with open (readpath , "r" ) as infile :
455+ lines = infile .readlines ()
456+
457+ # Directly at the split we discard the last energy value
458+ # of the left side of the split. This requires that both
459+ # DOS have been sampled to/from the EXACT same value.
460+ # Currently, this responsibility lies with the user, and I
461+ # am not sure if we can consistently check for this, even
462+ # if we wanted to. In the DOS case, the energies get reported,
463+ # but that is NOT the case in the LDOS case.
464+ end = (
465+ self .parameters .ldos_gridsize [path_index ] - 1
466+ if path_index != len (readpaths ) - 1
467+ else self .parameters .ldos_gridsize [path_index ]
468+ )
469+ end += current_energy_index
470+
471+ for dos_line in lines :
472+ # The first column contains the energy value.
473+ if "#" not in dos_line and current_energy_index < end :
474+ e_val = float (dos_line .split ()[0 ])
475+ dosval = float (dos_line .split ()[1 ])
476+ if (
477+ np .abs (e_val - energy_grid [current_energy_index ])
478+ < self .parameters .ldos_gridspacing_ev [path_index ]
479+ * 0.98
480+ ):
481+ return_dos_values .append (dosval )
482+ current_energy_index += 1
483+ # print(path_index, i)
484+ if path_index == 0 :
485+ array = np .array (return_dos_values )
486+ else :
487+ array = np .concatenate ((array , return_dos_values ))
451488 self .density_of_states = array
452489 return array
453490
@@ -485,17 +522,40 @@ def read_from_qe_out(self, path=None, smearing_factor=2):
485522 "Rerun calculation with verbosity set to 'high'."
486523 )
487524
525+ if isinstance (self .parameters .ldos_gridspacing_ev , list ):
526+ grid_spacings = self .parameters .ldos_gridspacing_ev
527+ grid_sizes = self .parameters .ldos_gridsize
528+ else :
529+ grid_spacings = [self .parameters .ldos_gridspacing_ev ]
530+ grid_sizes = [self .parameters .ldos_gridsize ]
531+
488532 # Get the gaussians for all energy values and calculate the DOS per
489533 # band.
490- dos_per_band = gaussians (
491- self .energy_grid ,
492- atoms_object .get_calculator ().band_structure ().energies [0 , :, :],
493- smearing_factor * self .parameters .ldos_gridspacing_ev ,
494- )
495- dos_per_band = kweights [:, np .newaxis , np .newaxis ] * dos_per_band
534+ dos_data = None
535+ previous_beginning = 0
536+ for spacing_idx , grid_spacing in enumerate (grid_spacings ):
537+ size_for_spacing = grid_sizes [spacing_idx ] + previous_beginning
538+ if spacing_idx != len (grid_spacings ) - 1 :
539+ size_for_spacing -= 1
540+
541+ dos_per_band = gaussians (
542+ self .energy_grid [previous_beginning :size_for_spacing ],
543+ atoms_object .get_calculator ()
544+ .band_structure ()
545+ .energies [0 , :, :],
546+ smearing_factor * grid_spacing ,
547+ )
548+ dos_per_band = kweights [:, np .newaxis , np .newaxis ] * dos_per_band
496549
497- # QE gives the band energies in eV, so no conversion necessary here.
498- dos_data = np .sum (dos_per_band , axis = (0 , 1 ))
550+ # QE gives the band energies in eV, so no conversion necessary
551+ # here.
552+ if spacing_idx == 0 :
553+ dos_data = np .sum (dos_per_band , axis = (0 , 1 ))
554+ else :
555+ dos_data = np .concatenate (
556+ (dos_data , np .sum (dos_per_band , axis = (0 , 1 )))
557+ )
558+ previous_beginning = size_for_spacing
499559 self .density_of_states = dos_data
500560 return dos_data
501561
@@ -548,26 +608,6 @@ def read_from_numpy_file(
548608 # Calculations
549609 ##############
550610
551- def get_energy_grid (self ):
552- """
553- Get energy grid.
554-
555- Returns
556- -------
557- e_grid : numpy.ndarray
558- Energy grid on which the DOS is defined.
559- """
560- emin = self .parameters .ldos_gridoffset_ev
561-
562- emax = (
563- self .parameters .ldos_gridoffset_ev
564- + self .parameters .ldos_gridsize
565- * self .parameters .ldos_gridspacing_ev
566- )
567- grid_size = self .parameters .ldos_gridsize
568- linspace_array = np .linspace (emin , emax , grid_size , endpoint = False )
569- return linspace_array
570-
571611 def get_band_energy (
572612 self ,
573613 dos_data = None ,
0 commit comments