def seek_convergence(at=1e-3, rt=1e-2, term_verb=True, **kwargs): """ Perform a convergence procedure by using a list of (ordered) values of a parameter. Take as input a list of instances of runner built with the values of the convergence parameter. These objects have to provide as the result of runner.run() a quantity that can be compared. The convergence is performed by comparing the results associated to two (subsequent) values of the parameter. The procedures stop if the difference between the result is below a given tolerance, if not further run are performed using the values of the parameter in the list. The method returns a dictionary with the input parameters, the results of all the computation performed, the value of the convergence parameter and a boolean that states if the convergence procedure succeeds or not. Args: kwargs['label'] : the name of the convergence parameter kwargs['values'] : the array with the (ordered) values of the convergence parameter kwargs['data'] : the array with the dataset buit with kwargs['values'] at,rt : absolute and relative tol of np.allclose """ label = kwargs['label'] values = kwargs['values'] data = kwargs['data'] results = {} for v in values: results[v] = None out = {'label': label, 'values': values} if term_verb: print 'Perform the run with', label, values[0] results[values[0]] = data[0].run() for ind in range(1, len(values)): if term_verb: print 'Perform the run with', label, values[ind] results[values[ind]] = data[ind].run() convergence = np.allclose(results[values[ind - 1]], results[values[ind]], atol=at, rtol=rt) if convergence: if term_verb: write('Convergence achieved for', label, values[ind - 1]) out['results'] = results out['converged'] = True out['converged_value'] = values[ind - 1] break else: if term_verb: write('Convergence for', label, values[ind - 1], 'failed') if convergence == False: print 'Return the value associated to', label, values[ -1], '. Perform further check!!!' out['results'] = results out['converged'] = False out['converged_value'] = values[-1] return out
def __init__(self, *args, **kwargs): """ Perform sanity checks on the loaded matrix """ log = kwargs.get('log') if log is not None: self.norb_occ, self.norb_virt = _occ_and_virt(log) else: self.norb_occ = kwargs.get('norb_occ') self.norb_virt = kwargs.get('norb_virt') assert (self.shape[0] == self._total_transitions()) write("Shape is conformal with the number of orbitals") self._sanity_check()
def _doc_finder(self, stream): #first find the stream of the document start startpos = 0 import sys write('Loading...') while startpos < len(stream): try: startpos += self._event_finder(stream[startpos:], yaml.events.DocumentEndEvent) except: startpos = len(stream) write(int((100.0 * startpos) / len(stream)), '%') yield startpos
def __new__(cls, matrix=None, norb_occ=None, norb_virt=None, log=None): """ Create the object from the arguments and return the ``self`` instance """ import os if log is not None: datadir = log.log.get('radical', '') datadir = 'data-' + datadir if len(datadir) > 0 else 'data' cmfile = os.path.join(log.srcdir, datadir, cls._filename) if not os.path.isfile(cmfile): raise ValueError('The file "' + cmfile + '" does not exist') norb, norbv = _occ_and_virt(log) write('Loading data with ', norb, ' occupied and ', norbv, ' empty states, from file "', cmfile, '"') try: import pandas as pd write('Using pandas:') mat = pd.read_csv(cmfile, delim_whitespace=True, header=None) except ImportError: write('Using numpy:') mat = np.loadtxt(cmfile) write('done') else: mat = matrix return super(TransitionMatrix, cls).__new__(cls, mat)
def diagonalize(self): """ Diagonalize the Coupling Matrix Returns: (np.matrix, np.matrix): tuple of the Eigenvvalues and Eigenvectors of the coupling matrix, as returned by :meth:`numpy.linalg.eigh`. We perform the transpose of the matrix with eigenvectors to have them sorted as row vectors """ write('Diagonalizing Coupling matrix of shape', self.shape) E2, C_E2 = np.linalg.eigh(self) write('Eigensystem solved') C_E2 = C_E2.T return E2, C_E2
def _event_finder(self, present, event, end=False): for i in yaml.parse(present, Loader=yaml.CLoader): if isinstance(i, event): if end: key = i.value startpos = i.start_mark.index endpos = startpos + self._find_endblock(present[startpos:]) substream = present[i.end_mark.index:endpos] return key, substream, endpos else: startpos = i.end_mark.index return startpos #in the case of absent event if end: write('here', present, 'end') return 'nothing', '', len(present) else: return len(present)
def seek_convergence(self, rtol=1.e-5, atol=1.e-8, selection=None, **kwargs): """ Search for the first result of the dataset which matches the provided tolerance parameter. The results are in dataset order (provided by the :py:meth:`append_run` method) if `selection` is not specified. Employs the numpy :py:meth:`allclose` method for comparison. Args: rtol (float): relative tolerance parameter atol (float): absolute tolerance parameter selection (list): list of the id of the runs in which to perform the convergence search. Each id should be unique in the dataset. **kwargs: arguments to be passed to the :py:meth:`fetch_results` method. Returns: id,result (tuple): the id of the last run which matches the convergence, together with the result, if convergence is reached. Raises: LookupError: if the parameter for convergence were not found. The dataset has to be enriched or the convergence parameters loosened. """ from numpy import allclose from futile.Utils import write to_get = self.ids if selection is None else selection id_ref = to_get[0] write('Fetching results for id "', id_ref, '"') ref = self.fetch_results(id=id_ref, **kwargs) ref = ref[0] for id in to_get[1:]: write('Fetching results for id "', id, '"') val = self.fetch_results(id=id, **kwargs) val = val[0] if allclose(ref, val, rtol=rtol, atol=atol): res = self.fetch_results(id=id_ref) label = self.get_global_option('label') write( 'Convergence reached in Dataset "' + label + '" for id "', id_ref, '"') return (id_ref, res[0]) ref = val id_ref = id raise LookupError('Convergence not reached, enlarge the dataset' ' or change tolerance values')
def clean_logfile(logfile_lines, to_remove): """Remove yaml fields from a list of lines. Removes from a set of lines the yaml_fields contained in the to_remove list. Arguments: logfile_lines (list): list of the lines of the logfile. Generated from a file by e.g. :py:meth:`~io.IOBase.readlines`. to_remove (list): list of keys to remove from logfile_lines Returns: list of lines where the removed keys have as values the `"<folded>"` string """ line_rev = logfile_lines #list of the lines of the logfile #loop in the reversed from (such as to parse by blocks) extra_lines = 20 #internal variable to be customized line_rev.reverse() #clean the log cleaned_logfile = [] removed = [] #for line in line_rev: #line_iter: while len(line_rev) > 0: line = line_rev.pop() to_print = line #check if the line contains interesting information for remove_it in to_remove: stream_list = [] #line without comments valid_line = line.split('#')[0] spaces = 'nospace' #control that the string between the key and the semicolon is only spaces if remove_it in valid_line and ":" in valid_line: #print "here",remove_it,remove_it in valid_line and ":" in valid_line,valid_line starting_point = valid_line.find(remove_it) tmp_buf = valid_line[:starting_point] #find the closest comma to the staring point, if exists tmp_buf = tmp_buf[::-1] starting_comma = tmp_buf.find(',') if starting_comma < 0: st = 0 tmp_buf = tmp_buf[st:] tmp_buf = tmp_buf[::-1] tmp_buf = tmp_buf.strip(' ') #print "there",tmp_buf,'starting',starting_point,len(tmp_buf) valid_line = valid_line[starting_point + len(remove_it):] spaces = valid_line[1:valid_line.find(':')] #if remove_it+':' in line.split('#')[0]: if len(spaces.strip(' ')) == 0 and len( tmp_buf) == 0: #this means that the key has been found #creates a new Yaml document starting from the line #treat the rest of the line following the key to be removed header = ''.join(line.split(':')[1:]) header = header.rstrip() + '\n' #eliminate the anchor header = header.lstrip(' ') header = header.lstrip('*') if len(header) > 0: stream_list.append(header) #part to be printed, updated to_print = line.split(':')[0] + ": <folded> \n" #then check when the mapping will end: while True: #create a stream with extra_lines block for i in range(0, min(extra_lines, len(line_rev))): stream_list.append(line_rev.pop()) #create a stream to be parsed stream = ''.join(stream_list) #then parse the stream until the last valid position has been found try: for i in yaml.parse(stream, Loader=yaml.CLoader): endpos = i.end_mark.index except Exception(e): # print 'error',str(e),stream #convert back the valid stream into a list #if needed the stream can be loaded into a document item_list = stream[:endpos].split('\n') #if lengths are different there is no need to add lines if len(item_list) != len(stream_list): #last line might be shorter, therefore treat it separately last_line = item_list.pop() #purge the stream for item in item_list: stream_list.remove(item + '\n') #extract the remaining line which should be compared with the last one strip_size = len(last_line.rstrip()) if strip_size > 0: first_line = stream_list.pop(0)[strip_size:] if '*' in first_line or '&' in first_line: first_line = '' #eliminate anchors else: first_line = '' #then put the rest in the line to be treated to_print.rstrip('\n') to_print += first_line + '\n' # the item has been found break stream_list.reverse() #put back the unused part in the document line_rev.extend(stream_list) # mark that the key has been removed if (remove_it not in removed): removed.append(remove_it) write('removed: ', remove_it) # then print out the line cleaned_logfile.append(to_print) # check that everything has been removed, at least once if (set(removed) != set(to_remove)): write('WARNING, not all the requested items have been removed!') write('To_remove : ', to_remove) write('removed : ', removed) write('Difference: ', list(set(to_remove) - set(removed))) return cleaned_logfile
def load(file=None, stream=None, doc_lists=True, safe_mode=False, archive=None, member=None): """Encapsulate the loading of yaml documents. Provides a dictionary, or a list of dictionaries, which represents the structure of the stream to be loaded. It also wraps the yaml loader to perform a optimized parsing when the `minloader` of PyYaml 3.13 is available. This wrapper ensures to extract from the stream the maximum possible information by choosing the best loader available. Arguments: file (str): path of the yaml-compliant file containing the stream to be loaded stream (str): the stream to load, overrides the ``file`` argument if present archive (str): path of the archive to be used for the retrieval of the stream member (str): name of the file to be extracted from the archive. the entire archive is parsed if absent doc_lists (bool): if True, ensures that the results is always in a form of lists of documents, even in the case of a single doc When False, the return type is either a dictionary or a generator according to the specifications of yaml.load and yaml.load_all respectively. safe_mode (bool): When true, in the case of multiple documents in the stream, it loads the document one after another. This is useful to avoid losing of all the document list in the case when one of the document is not yaml compliant, like in the case of a broken logfile. It may works only when the separation of the documents is indicated by the usual syntax ``"---\\n"`` (i.e. no yaml tags between documents) Returns: * a list of dictionaries, if ``doc_lists`` is set to ``True``; * a dictionary, if the stream or the file, or the archive contains a single yaml document; * a generator if the parsed stream is made of multiple documents *and* ``safe_mode`` = ``False``; * a list of dictionaries if the stream is made of multiple documents and ``safe_mode`` is ``True``. """ # choose the loader try: ldr = yaml.MinLoader except Exception as e: try: ldr = yaml.CLoader except Exception as f: ldr = yaml.Loader # load the documents ld = [] # verify if we are in the archive case if archive is not None: import tarfile tar = tarfile.open(archive) if member is not None: members = [tar.getmember(member)] else: members = tar.getmembers() ld = [] for memb in members: f = tar.extractfile(memb) if safe_mode: try: ll = yaml.load(f.read(), Loader=ldr) except Exception as f: write('Document', member, 'of archive NOT loaded, error:', f) else: ll = yaml.load(f.read(), Loader=ldr) ld += ll if len(members) == 1 and not doc_lists: return ll return ld # Detect None otherwise a doc == '' gives an error strm = stream if stream is not None else open(file, 'r').read() try: ld = yaml.load(strm, Loader=ldr) if doc_lists: ld = [ld] except Exception as e: if safe_mode: ld = [] documents = [v for v in strm.split('---\n') if len(v) > 0] for i, raw_doc in enumerate(documents): try: ld.append(yaml.load(raw_doc, Loader=ldr)) except Exception as f: write('Document', i, 'of stream NOT loaded, error:', f) else: ld = yaml.load_all(strm, Loader=ldr) if doc_lists: ld = [l for l in ld] return ld
def _sanity_check(self): write('Casida Matrix is symmetric', np.allclose(self, self.T, atol=1.e-12))