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