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): self.Logger = GetClassLogger(self) self.TimeList = [] self.NormList = [] self.CorrList = [] self.StartTime = -1 self.InitialPsi = None def setupTask(self, prop): self.Logger.info("Setting up task...") self.StartTime = time.time() self.InitialPsi = prop.psi.Copy() self.OutputFileName = prop.Config.Names.output_file_name #check if output dir exist, create if not CreatePath(self.OutputFileName) def callback(self, prop): t = prop.PropagatedTime norm = prop.psi.GetNorm() corr = abs(prop.psi.InnerProduct(self.InitialPsi))**2 eta = self._EstimateETA(prop) self.TimeList += [t] self.NormList += [norm] self.CorrList += [corr] #FormatDuration = lambda t: time.strftime("%Hh %Mm %Ss", time.gmtime(t)) PrintOut("t = %.2f / %.2f; N = %.15f; Corr = %.12f, ETA = %s" % (t, prop.Duration, norm, corr, self._FormatDuration(eta))) def postProcess(self, prop): """ Store problem information collected during propagation """ if pyprop.ProcId == 0: nodeNames = ["SampleTimes", "Norm", "InitialCorrelation"] with tables.openFile(self.OutputFileName, "r+", MAX_THREADS=1) as h5file: for nodeName in nodeNames: if nodeName in h5file.root: h5file.removeNode(h5file.root, nodeName, recursive=True) h5file.createArray("/", "SampleTimes", self.TimeList) h5file.createArray("/", "Norm", self.NormList) h5file.createArray("/", "InitialCorrelation", self.CorrList) def _EstimateETA(self, prop): """ Estimates remaining time before propagation is finished """ curTime = time.time() - self.StartTime totalTime = (curTime / prop.PropagatedTime) * 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(object): """ 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() #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) def run(self): """ Propagate problem until end time. """ for _ 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