def _dump_debugfile_info(self): from futile import YamlIO as Y debugfile = os.path.join('debug', 'bigdft-err-0.yaml') if os.path.isfile(debugfile): debugdict = Y.load(debugfile, doc_lists=False) safe_print('The error occured is', self._get_error_key(debugdict)) safe_print('Additional Info: ', debugdict['Additional Info'])
def __init__(self, omp=os.environ.get('OMP_NUM_THREADS', '1'), mpi_run=os.environ.get('BIGDFT_MPIRUN', ''), dry_run=False, skip=False, code="bigdft@localhost", verbose=True, **kwargs): Runner.__init__(self, omp=str(omp), mpi_run=mpi_run, dry_run=dry_run, skip=skip, verbose=verbose, **kwargs) # Build the command setting the number of omp threads self.code = load_code(code) self.job = BigDFTCalcJob # we don't want the executable and such self.command = "" # ignore this for datasets, as aiida splits each # computation in its own folder self.run_dir = "." # store logfiles and names in order to # skip execution if necessary. self.logfiles = {} # store output information on all runs. self.outputs = {} safe_print( 'Initialize an Aiida Calculator for %s with %d machine(s)' % ((self.code), self._global_options.get('num_machines', 1)), ', %d processes per machine, and %s cores per process' % ((self._global_options.get('mpiprocs_per_machine', 1), self._global_options['omp'])))
def _posinp_dictionary_value(self, posinp): """ Create the dictionary value associated to posinp field Args: posinp (str, dict): path of the posinp file. Might be relative or absolute. Copied into `run_dir` if not existing. If it is a dictionary, it is a representation of the atomic position. Returns: str,dict: the value of the key ``posinp`` of the input file, if posinp is a string, otherwise the posinp dictionary """ import os from futile.Utils import ensure_copy, make_dict if isinstance(posinp, dict): return make_dict(posinp) # Check if the file does exist if not os.path.isfile(posinp): raise ValueError( "posinp: The atomic position file '%s' does not exist" % posinp) posinpdict = posinp posinpfile = os.path.basename(posinp) # Copy the posinp if not identical # LG: not like that "%s/%s" % (self.run_dir,posinp) cp_posinp = os.path.join(self.run_dir, posinpfile) copied = ensure_copy(src=posinp, dest=cp_posinp) if copied: posinpdict = posinpfile if self.run_options['verbose']: safe_print("Copy the posinp file '%s' into '%s'" % (posinp, self.run_dir)) return posinpdict
def post_processing(self, timedbg, logname, command): """ Check the existence and the log file and return an instance logfile. Returns: A `BigDFT.Logfile` class instance associated to the run which has been just performed. If the run failed for some reasons, the logfile seem not existing or it cannot be parsed it returns `None`. """ # verify that no debug file has been created if self._get_debugfile_date() > timedbg: verbose = self.run_options['verbose'] if verbose: safe_print( "ERROR: some problem occured during the execution of the command, check the 'debug/' directory and the logfile" ) # the debug file is sane, we may print out the error message self._dump_debugfile_info() try: return Lf.Logfile(logname) except: return None if os.path.exists(logname): from futile.Utils import file_time from time import time inputname = self._get_inputfilename() if file_time(logname) < file_time( inputname) and not self.run_options['skip']: safe_print("ERROR: The logfile (", logname, ") is older than the inputfile (", inputname, ").") return None else: return Lf.Logfile(logname) else: raise ValueError("The logfile (", logname, ") does not exist.")
def _ensure_run_directory(self): from futile.Utils import ensure_dir run_dir = self.run_options.get('run_dir', '.') # Create the run_dir if not exist if ensure_dir(run_dir) and self.run_options['verbose']: safe_print("Create the sub-directory '%s'" % run_dir) self.run_dir = run_dir
def set_psp(name, psp): # Atoms import os pspfile = "psppar."+name dirname = os.path.dirname(__file__) filename = os.path.join(dirname, "psppar", pspfile) if not os.path.isfile(filename): safe_print("WARNING: Using default PSP for atom", filename, name) else: psp.append(filename)
def fill_from_xyz(self, file, nat_reference, fragmentation): """ Import the fragment information from a xyz file Args: file (str): path of the ``xyz`` file to be opened nat_reference (int): number of atoms to be assigned to each of the fragments. Only useful in the case of uniform fragmentation fragmentation (list): contains the fragment identification as a list of ``['label', ats ]`` where ``ats`` is a list of the atoms id associated to the fragment of label ``label``. """ fil = open(file, 'r') nat = 0 iat = 0 frag = None ifrag = 0 iline = 0 for l in fil: iline += 1 if iline == 2: continue try: pos = l.split() if len(pos) <= 2: # these are the number of atoms nt = int(pos[0]) nat -= nt if len(pos) == 2: unt = pos[1] self._get_units(unt) if frag is not None: self.append(frag) frag = Fragment(units=self.units) iat = 0 elif len(pos) > 0: # we should break the fragment, alternative strategy if nat_reference is not None: nat_ref = nat_reference elif fragmentation is not None: nat_ref = len(fragmentation[ifrag][1]) else: nat_ref = -1 if iat == nat_ref: if frag is not None: self.append(frag) frag = Fragment(units=self.units) if fragmentation is not None: frag.set_id(fragmentation[ifrag][0]) iat = 0 ifrag += 1 frag.append({pos[0]: map(float, pos[1:])}) nat += 1 iat += 1 except Exception, e: safe_print('Warning, line not parsed: "', l, e, '"')
def _ensure_run_directory(self): from futile.Utils import ensure_dir run_dir = self.run_options.get('run_dir', '.') # Restrict run_dir to a sub-directory if ("/" in run_dir or run_dir == ".."): raise ValueError( "run_dir '%s' where bigdft is executed must be a sub-directory" % run_dir) # Create the run_dir if not exist if ensure_dir(run_dir) and self.run_options['verbose']: safe_print("Create the sub-directory '%s'" % run_dir) self.run_dir = run_dir """Run directory.
def rigid_transform_3D(A, B): "Find the transformation R and t such that R*A + t ~= B, with an error quantified by J" assert len(A) == len(B) N = A.shape[0] # total points centroid_A = mean(A, axis=0) centroid_B = mean(B, axis=0) #print 'centre',centroid_A,centroid_B # centre the points AA = A - tile(centroid_A, (N, 1)) BB = B - tile(centroid_B, (N, 1)) # dot is matrix multiplication for array H = transpose(AA) * BB #print 'H',H U, S, Vt = linalg.svd(H) R = Vt.T * U.T # special reflection case if linalg.det(R) < 0: safe_print("#Reflection detected") Vt[2, :] *= -1 R = Vt.T * U.T t = -R * centroid_A.T + centroid_B.T #print t #identify also the accuracy of wahba A2 = R * A.T + tile(t, (1, N)) A2 = A2.T # Find the error err = A2 - B err = multiply(err, err) err = sum(err) rmse = sqrt(err / N) return R, t, rmse
def process_run(self, command): """ Run the psi4 command. """ from os import environ, system # Set the number of omp threads only if the variable is not present # in the environment if 'OMP_NUM_THREADS' not in environ: environ['OMP_NUM_THREADS'] = self.run_options['omp'] if self.run_options['verbose']: if self.run_dir != '.': safe_print('Run directory', self.run_dir) # Run the command if command is not None: command() return {'logname': self._get_logname(True)}
def process_run(self, command): """Finally launch the code. Routine associated to the running of the ``bigdft`` executable. Arguments: command (str): the command as it is set by the ``pre_processing`` method. """ # check if the debug file will be updated (case of erroneous run) timedbg = self._get_debugfile_date() verbose = self.run_options['verbose'] # Set the number of omp threads os.environ['OMP_NUM_THREADS'] = self.run_options['omp'] if verbose: if self.run_dir != '.': safe_print('Run directory', self.run_dir) safe_print('Executing command: ', command) # Run the command os.system("cd " + self.run_dir + "; " + command) return {'timedbg': timedbg, 'logname': self._get_logname()}
def pre_processing(self): # def run(self, name='', outdir='', run_name='', input={}, posinp=None,**kwargs): """ Run a calculation building the input file from a dictionary. :param str name: naming scheme of the run i.e. <name>.yaml is the input file and log-<name>.yaml the output one. Data will then be written in the directory `data-<name>.yaml`, unless the "radical" keyword is specified in the input dictionary. :param str run_dir: specify the directory where bigdft will be executed (the input and log file will be created in it) it must be a simple :param str outdir: specify the output directory for all data coming from bigdft (parameter of bigdft) :param str run_name: File containing the list of the run ids which have to be launched independently (list in yaml format). The option runs-file is not compatible with the name option. :param input: give the input parameters (a dictionary or a list of dictionary) :type input: dict :param posinp: indicate the posinp file (atomic position file). :type posinp: filename :return: a Logfile instance is returned. It returns None if an error occurred :rtype: Logfile .. todo:: Set the return value of run in the case of a run_file. It should be a list of Logfile classes """ from futile.Utils import make_dict self._ensure_run_directory() # Create the input file (deepcopy because we modify it) inp = self.run_options.get('input', {}) # from here onwards the local input is a dict and not anymore anothe class local_input = make_dict(inp) # Add into the dictionary a posinp key posinp = self.run_options.get('posinp', None) if posinp != None: local_input['posinp'] = self._posinp_dictionary_value(posinp) # Creating the yaml input file from futile import YamlIO as Y input_file = self._get_inputfilename() Y.dump(local_input, filename=input_file) if self.run_options['verbose']: safe_print('Creating the yaml input file "%s"' % input_file) return {'command': self._get_command()}
def run(self, atoms=None, force=False): import os #To dump python object in a file import cPickle if atoms is None: atomlist = self.ortho else: atomlist = atoms #Loop over the elements #Test if the file bigdft-results.cpickle exists and use it instead if os.path.exists(cpickle_file) and not force: self.Elements = cPickle.load(open(cpickle_file, "r")) for name in atomlist: dico = self.Elements[name] if self.calculator.iproc == 0: safe_print("Start calculation of %s" % dico["name"]) hgrid = 0.30 var = set_inputfile(hgrid, dico) self.calculator.set(var) process_element(self.calculator, var, dico, force, self.Elements, self.strains)
def process_element(run, var, dico, force_run, Elements, strains): import math import cPickle name = dico["name"] hgrids = var['dft']['hgrids'] ngrids = (math.ceil(strains[0] * dico["a"] / hgrids[0]), math.ceil(strains[0] * dico["b"] / hgrids[1]), math.ceil(strains[0] * dico["c"] / hgrids[2])) for strain in strains: if run.iproc == 0: safe_print("(%s)" % strain) if strain in dico["eKS"] and not force_run: # The calculation is already done if run.iproc == 0: safe_print((name, strain), ": ", dico["eKS"][strain]) continue var.update(InputGenerator.set_strain(strain, ngrids, dico)) run.update(var) # Run and store the results out = run.run() var.update(InputGenerator.set_restart()) run.update(var) # And restart out = run.run() Elements[name] = dico dico["eKS"][strain] = out.eKS dico["FKS"][strain] = out.etot dico["pressure"][strain] = out.pressure if run.iproc == 0: cPickle.dump(Elements, open(cpickle_file, "w")) # Parse the generated log to get the number of grid points. for l in open("log-%s.yaml" % var["radical"], "r"): if "Grid Spacing Units" in l: grid = l.split() ngrids = (int(grid[5][:-1]), int(grid[6][:-1]), int(grid[7])) ngrids = [a + 1 for a in ngrids] # Freeing memory run = None out = None # Build the file if run.iproc == 0: fd = open("%s.dat" % name, 'w') for strain in strains: dico = Elements[name] # Volume in A^3/atom volume = dico["volume"] * strain**3 / dico["nat"] HatoeV = 27.21138386 eKS = float(dico["eKS"][strain]) * HatoeV / dico["nat"] fd.write("%16.9f %16.9f\n" % (volume, eKS)) safe_print(strain, dico["eKS"][strain], volume, eKS) fd.close()
def __init__(self, omp=os.environ.get('OMP_NUM_THREADS', '1'), mpi_run=os.environ.get('BIGDFT_MPIRUN', ''), dry_run=False, skip=False, verbose=True): # Use the initialization from the Runner class (so all options inside __global_options) Runner.__init__(self, omp=str(omp), mpi_run=mpi_run, dry_run=dry_run, skip=skip, verbose=verbose) # Verify if $BIGDFT_ROOT is in the environment assert 'BIGDFT_ROOT' in os.environ executable = os.path.join(os.environ['BIGDFT_ROOT'], 'bigdft') # the bigdft file should be present in the BIGDFT_ROOT directory assert os.path.isfile(executable) # Build the command setting the number of omp threads self.command = (self._global_options['mpi_run'] + ' ' + executable).strip() safe_print( 'Initialize a Calculator with OMP_NUM_THREADS=%s and command %s' % (self._global_options['omp'], self.command))
def xyz_from_pymatgendict(dirXYZ, name, dico): import shutil import os import time format_xyz = """{1} reduced periodic {0[a]} {0[b]} {0[c]} """ #danger zone.. don't do ? if dirXYZ != ".": print("Remove the directory '%s'." % dirXYZ) shutil.rmtree(dirXYZ, ignore_errors=True) # Create it os.mkdir(dirXYZ) safe_print("---") # Start and create the xyz file # We have all the specification fnew = os.path.join(dirXYZ, name + ".xyz") # "%s/%s.xyz" % (dirXYZ,name) fd = open(fnew, "w") nat = len(dico['sites']) fd.write(format_xyz.format(dico['lattice'], nat)) for atom in dico['sites']: fd.write("%s " % atom['label']) fd.write("%f %f %f\n" % tuple(atom['xyz'])) fd.close()
def set_inputfile(hgrid, dico): basicinput = """ logfile: Yes dft: ixc: PBE ncong: 2 rmult: [10, 8] itermax: 3 idsx: 0 gnrm_cv: 1e-8 #Control the diagonalisation scheme mix: iscf: 7 itrpmax: 200 rpnrm_cv: 1e-12 tel: 1e-3 alphamix: 0.5 norbsempty: 1000 alphadiis: 1.0 #perf: # accel: OCLGPU # ocl_devices: Tesla K40c # blas: Yes """ import yaml, os var = yaml.load(basicinput) #Spin parameters var["dft"].update(set_spin(dico["name"], dico["nat"])) #K point parameters var["kpt"] = set_kpoints(dico["nat"]) var["dft"]["hgrids"] = (hgrid, hgrid, hgrid) #Control the diagonalisation scheme if dico["name"] in ("Cr", ): var["mix"]["iscf"] = 3 var["mix"]["alphamix"] = 0.9 if dico["name"] in ("Ba", "Ca"): var["mix"]["norbsempty"] = 8 var["ig_occupation"] = {dico["name"]: {"empty_shells": ("s", "p", "d")}} #Atoms pspfile = "psppar." + dico["name"] if not os.path.isfile(pspfile): safe_print("WARNING: Using default PSP for atom", dico["name"]) else: var[pspfile] = open(pspfile, 'r').read() #var["posinp"] = {"positions": [{dico["name"]: map(float, dico[i + 1].split())} for i in range(dico["nat"])], "units": "reduced", "cell": (dico["a"], dico["b"], dico["c"])} var["posinp"] = { "positions": [{ dico["name"]: dico[i + 1] } for i in range(dico["nat"])], "units": "reduced", "cell": (dico["a"], dico["b"], dico["c"]) } # We round robin the igspins. if "mpol" in var["dft"]: mpol = 0 while mpol < var["dft"]["mpol"]: for at in var["posinp"]["positions"]: if mpol < var["dft"]["mpol"]: if "IGSpin" in at: at["IGSpin"] += 1 else: at["IGSpin"] = 1 mpol += 1 elif "nspin" in var["dft"] and var["dft"]["nspin"] == 2: for (i, at) in enumerate(var["posinp"]["positions"]): at["IGSpin"] = 1 - 2 * (i % 2) return var
def _example(): """Test the XYZ Module""" from BigDFT.Systems import System from BigDFT.Fragments import Fragment from BigDFT.UnitCells import UnitCell file = "Si4" safe_print("First let's try reading an XYZ file.") atom_list = [] with XYZReader(file) as reader: safe_print(reader.closed) for at in reader: atom_list.append(at) safe_print(reader.closed) safe_print(atom_list) safe_print() safe_print("Now let's try writing an XYZ file.") safe_print() with XYZWriter("test.xyz", len(atom_list), units=reader.units) as writer: safe_print(writer.closed) for at in atom_list: writer.write(at) safe_print(writer.closed) safe_print() with open("test.xyz") as ifile: for line in ifile: safe_print(line, end='') safe_print() safe_print("Print with various boundary conditions") with XYZWriter("test.xyz", len(atom_list), reader.units, cell=UnitCell()) as writer: for at in atom_list: writer.write(at) with XYZReader("test.xyz") as ifile: print(ifile.cell.get_boundary_condition()) with XYZWriter("test.xyz", len(atom_list), reader.units, cell=UnitCell([5, 5, 5])) as writer: for at in atom_list: writer.write(at) with XYZReader("test.xyz") as ifile: print(ifile.cell.get_boundary_condition()) with XYZWriter("test.xyz", len(atom_list), reader.units, cell=UnitCell([5, float("inf"), 5])) as writer: for at in atom_list: writer.write(at) with XYZReader("test.xyz") as ifile: print(ifile.cell.get_boundary_condition()) with XYZWriter("test.xyz", len(atom_list), reader.units, cell=UnitCell([float("inf"), float("inf"), 5])) as writer: for at in atom_list: writer.write(at) with XYZReader("test.xyz") as ifile: print(ifile.cell.get_boundary_condition()) safe_print() safe_print("Now let's demonstrate the pdb and mol2 writer") sys = System() sys["FRAG:0"] = Fragment(atom_list) with open("test.pdb", "w") as ofile: write_pdb(sys, ofile) with open("test.pdb") as ifile: for line in ifile: safe_print(line, end='') safe_print() with open("test.mol2", "w") as ofile: write_mol2(sys, ofile) with open("test.mol2") as ifile: for line in ifile: safe_print(line, end='') safe_print()
def xyz_from_elements(dirXYZ, Elements, ortho, nonortho): import shutil, os, time format_xyz = """{0[nat]} reduced periodic {0[a]} {0[b]} {0[c]} """ #print "Remove the directory '%s'." % dirXYZ shutil.rmtree(dirXYZ, ignore_errors=True) #Create it os.mkdir(dirXYZ) safe_print("---") #Start and create the xyz files safe_print("Delta-test timestamp:", time.strftime('%X %x %Z')) safe_print("Delta-test code: BigDFT") safe_print("Number of elements: ", len(Elements)) safe_print("List of elements:", Elements.keys()) safe_print("Number of orthorhombic elements: ", len(ortho)) safe_print("Orthorhombic elements: ", ortho) safe_print("Number of non-orthorhombic elements: ", len(nonortho)) safe_print("Non-orthorhombic elements: ", nonortho) for dico in Elements.values(): name = dico['name'] #We have all the specification fnew = os.path.join(dirXYZ, name + ".xyz") #"%s/%s.xyz" % (dirXYZ,name) fd = open(fnew, "w") fd.write(format_xyz.format(dico)) for i in range(dico['nat']): fd.write("%s " % name) fd.write("%f %f %f\n" % tuple(dico[i + 1])) #fd.write("%s %s\n" % (name,dico[i+1])) fd.close()