def __init__(self, psi): self.__Base.__init__(self, psi) self.Rank = psi.GetRank() self.PotentialList = [] self.CutOff = 0.0 #Need a wavefunction for later self.Psi = self.psi.Copy() self.Logger = GetClassLogger(self)
def __init__(self, conf, propagationTasks, numberOfCallbacks): self.Logger = GetClassLogger(self) self.PropagationTasks = propagationTasks self.Config = conf self.NumberOfCallbacks = numberOfCallbacks #setup Pyprop problem from config self.Problem = pyprop.Problem(self.Config) self.Problem.SetupStep() self.PreProcessed = False
class BasisPropagatorEpetra(BasisPropagator): """ EpetraPropagator uses Trilinos::Epetra matrices to store potential matrices in a basis representation, and perform matrix-vector (potential-wavefunction) multiplications with these. Apart from this it is very similar to BasisPropagator, and uses TensorPotential to set up the potential matrices. """ __Base = BasisPropagator def __init__(self, psi): self.__Base.__init__(self, psi) self.Rank = psi.GetRank() self.PotentialList = [] self.CutOff = 0.0 #Need a wavefunction for later self.Psi = self.psi.Copy() self.Logger = GetClassLogger(self) def GeneratePotentials(self, config): """ Generate TensorPotentials from potentials specified on the grid in the configuration file. Then consolidate/copy into Epetra matrices. """ #Potentials we should create on the fly if hasattr(config.Propagation, "grid_potential_list"): potentials = config.Propagation.grid_potential_list for potentialName in potentials: #Find the corresponding config section configSection = config.GetSection(potentialName) #generate potential tensorPot = self.GeneratePotential(configSection) localBasisPairs = [geom.GetBasisPairs() for geom in tensorPot.GeometryList] #Setup a new Epetra potential epetraPot = EpetraPotential(self.Psi) epetraPot.ApplyConfigSection(configSection) #check if current potential can be consolidated with an existing one for existingPot in self.PotentialList: if existingPot.CanConsolidate(epetraPot): self.Logger.debug("Consolidating %s" % epetraPot.Name) existingPot.AddTensorPotentialData(tensorPot.PotentialData, localBasisPairs, self.CutOff) existingPot.Name += "+" + tensorPot.Name tensorPot = None epetraPot = None break #add new potential to list if epetraPot != None: self.Logger.debug("New epetra potential %s" % epetraPot.Name) epetraPot.AddTensorPotentialData(tensorPot.PotentialData, localBasisPairs, self.CutOff) self.PotentialList.append(epetraPot) tensorPot = None #Global assemble all potentials for pot in self.PotentialList: pot.GlobalAssemble() def MultiplyHamiltonianBalancedOverlap(self, srcPsi, destPsi, t, dt): raise NotImplementedException("BasisPropagatorEpetra does not support MultiplyHamiltonianBalancedOverlap!") def MultiplyPotential(self, srcPsi, destPsi, t, dt): self.Psi.Clear() if dt == None: dt = self.TimeStep for potential in self.PotentialList: self.Psi.Clear() potential.MultiplyPotential(srcPsi, self.Psi, t, dt) destPsi.GetData()[:] += self.Psi.GetData()
class BasisPropagatorEpetra(BasisPropagator): """ EpetraPropagator uses Trilinos::Epetra matrices to store potential matrices in a basis representation, and perform matrix-vector (potential-wavefunction) multiplications with these. Apart from this it is very similar to BasisPropagator, and uses TensorPotential to set up the potential matrices. """ __Base = BasisPropagator def __init__(self, psi): self.__Base.__init__(self, psi) self.Rank = psi.GetRank() self.PotentialList = [] self.CutOff = 0.0 #Need a wavefunction for later self.Psi = self.psi.Copy() self.Logger = GetClassLogger(self) def GeneratePotentials(self, config): """ Generate TensorPotentials from potentials specified on the grid in the configuration file. Then consolidate/copy into Epetra matrices. """ #Potentials we should create on the fly if hasattr(config.Propagation, "grid_potential_list"): potentials = config.Propagation.grid_potential_list for potentialName in potentials: #Find the corresponding config section configSection = config.GetSection(potentialName) #generate potential tensorPot = self.GeneratePotential(configSection) localBasisPairs = [ geom.GetBasisPairs() for geom in tensorPot.GeometryList ] #Setup a new Epetra potential epetraPot = EpetraPotential(self.Psi) epetraPot.ApplyConfigSection(configSection) #check if current potential can be consolidated with an existing one for existingPot in self.PotentialList: if existingPot.CanConsolidate(epetraPot): self.Logger.debug("Consolidating %s" % epetraPot.Name) existingPot.AddTensorPotentialData( tensorPot.PotentialData, localBasisPairs, self.CutOff) existingPot.Name += "+" + tensorPot.Name tensorPot = None epetraPot = None break #add new potential to list if epetraPot != None: self.Logger.debug("New epetra potential %s" % epetraPot.Name) epetraPot.AddTensorPotentialData(tensorPot.PotentialData, localBasisPairs, self.CutOff) self.PotentialList.append(epetraPot) tensorPot = None #Global assemble all potentials for pot in self.PotentialList: pot.GlobalAssemble() def MultiplyHamiltonianBalancedOverlap(self, srcPsi, destPsi, t, dt): raise NotImplementedException( "BasisPropagatorEpetra does not support MultiplyHamiltonianBalancedOverlap!" ) def MultiplyPotential(self, srcPsi, destPsi, t, dt): self.Psi.Clear() if dt == None: dt = self.TimeStep for potential in self.PotentialList: self.Psi.Clear() potential.MultiplyPotential(srcPsi, self.Psi, t, dt) destPsi.GetData()[:] += self.Psi.GetData()
def __init__(self, storeProgressInfo=True): self.StoreProgressInfo = storeProgressInfo self.Logger = GetClassLogger(self) self.StartTime = -1 self.InitialPsi = None self.ProgressItems = {}
class ProgressReport(PropagationTask): """ Print some progress information during propagation, and store it in a HDF5-file when finished (time, norm and projection on initial state) """ def __init__(self, storeProgressInfo=True): self.StoreProgressInfo = storeProgressInfo self.Logger = GetClassLogger(self) self.StartTime = -1 self.InitialPsi = None self.ProgressItems = {} def setupTask(self, prop): self.Logger.info("Setting up task...") self.StartTime = time.time() self.InitialPsi = prop.psi.Copy() #check if output dir exist, create if not if self.StoreProgressInfo: self.OutputFileName = prop.Config.Names.output_file_name CreatePath(self.OutputFileName) #Report items self.ProgressItems["SampleTimes"] = [] self.ProgressItems["Norm"] = [] self.ProgressItems["InitialCorrelation"] = [] def callback(self, prop): t = prop.PropagatedTime T = prop.Duration + prop.StartTime norm = prop.psi.GetNorm() corr = abs(prop.psi.InnerProduct(self.InitialPsi))**2 eta = self.__EstimateETA(prop) self.ProgressItems["SampleTimes"] += [t] self.ProgressItems["Norm"] += [norm] self.ProgressItems["InitialCorrelation"] += [corr] #FormatDuration = lambda t: time.strftime("%Hh %Mm %Ss", time.gmtime(t)) #FormatDuration = lambda t: time.strftime("%dd %Hh %Mm %Ss", time.gmtime(t)) PrintOut("t = %.2f / %.2f; N = %.15f; Corr = %.12f, ETA = %s" % (t, T, norm, corr, self._FormatDuration(eta))) def postProcess(self, prop): """ Store problem information collected during propagation """ if self.StoreProgressInfo and (pyprop.ProcId == 0): with tables.openFile(self.OutputFileName, "a") as h5file: for itemName, itemVal in self.ProgressItems.iteritems(): if itemName in h5file.root: h5file.removeNode(h5file.root, itemName, recursive=True) h5file.createArray("/", itemName, itemVal) def __EstimateETA(self, prop): """ Estimates remaining time before propagation is finished """ curTime = time.time() - self.StartTime #totalTime = (curTime / prop.PropagatedTime) * prop.Duration totalTime = (curTime / (prop.PropagatedTime - prop.StartTime)) * prop.Duration eta = totalTime - curTime return eta def _FormatDuration(self, t): days, remainder = divmod(t, 24 * 60 * 60) hours, remainder = divmod(remainder, 60 * 60) minutes, seconds = divmod(remainder, 60) if days > 0: timeStr = "%id %ih" % (days, hours) elif hours > 0: timeStr = "%ih %im" % (hours, minutes) else: timeStr = "%im %is" % (minutes, seconds) return timeStr
class Propagate: """ Setup and run a Pyprop problem. Propagate wavefunction from T_start to T_end. Also perform all given PropagationTasks during the propagation phase. """ def __init__(self, conf, propagationTasks, numberOfCallbacks): self.Logger = GetClassLogger(self) self.PropagationTasks = propagationTasks self.Config = conf self.NumberOfCallbacks = numberOfCallbacks #setup Pyprop problem from config self.Problem = pyprop.Problem(self.Config) self.Problem.SetupStep() self.PreProcessed = False def preprocess(self): #run pre-propagation step for all tasks for task in self.PropagationTasks: task.setupTask(self.Problem) #Calculate intial state energy tmpPsi = self.Problem.psi.Copy() en = self.GetEnergyExpectationValue(self.Problem.psi, tmpPsi).real self.Logger.info("Initial state energy = %s" % en) self.PreProcessed = True def run(self): """ Propagate problem until end time. """ assert (self.PreProcessed) for t in self.Problem.Advance(self.NumberOfCallbacks): for task in self.PropagationTasks: task.callback(self.Problem) #run postprocessing self.postProcess() def postProcess(self): """ Run postprocessing for all propagation tasks """ for task in self.PropagationTasks: task.postProcess(self.Problem) def GetEnergyExpectationValue(self, psi, tmpPsi): """ Calculates the total energy of the problem by finding the expectation value of the time-independent part of the Hamiltonian. Assumes that Tensor potentials and BasisPropagator are used. """ energy = 0.0 #Iterate over all potentials, check for time dependence for pot in self.Problem.Propagator.BasePropagator.PotentialList: if not pot.IsTimeDependent: energy += pot.GetExpectationValue(psi, tmpPsi, 0, 0) return energy