def _example(): """Example of using a system""" from BigDFT.IO import XYZReader from BigDFT.Fragments import Fragment safe_print("Read in some files for the fragments..") reader = XYZReader("SiO") frag1 = Fragment(xyzfile=reader) reader = XYZReader("Si4") frag2 = Fragment(xyzfile=reader) safe_print("Now we move on to testing the system class.") sys = System(frag1=frag1, frag2=frag2) for at in sys["frag1"]: safe_print(dict(at)) for at in sys["frag2"]: safe_print(dict(at)) safe_print() safe_print("What if we want to combine two fragments together?") sys["frag1"] += sys.pop("frag2") for at in sys["frag1"]: safe_print(dict(at)) safe_print("frag2" in sys) safe_print() safe_print("What if I want to split a fragment by atom indices?") temp_frag = sys.pop("frag1") sys["frag1"], sys["frag2"] = temp_frag[0:3], temp_frag[3:] for at in sys["frag1"]: safe_print(dict(at)) for at in sys["frag2"]: safe_print(dict(at)) safe_print()
def set_atom_forces(self, logfile): """ After a run is completed, we have the forces on each atom in the logfile. This routine will set those values to each atom in this sytem. Args: logfile (Logfiles.Logfile): logfile with the forces. """ from BigDFT.Fragments import Fragment posinp = logfile.log.get('posinp') if posinp is not None and not isinstance(posinp, str): atlist = Fragment(posinp=posinp) else: atlist = Fragment(astruct=logfile.astruct) lookup = self.compute_matching(atlist) # Assign forces try: forces = logfile.forces except AttributeError: forces = logfile.astruct["forces"] for fragid, frag in self.items(): for i, at in enumerate(frag): idx = lookup[fragid][i] if idx >= 0: at.set_force(list(forces[idx].values())[0])
def _example(): """Example of using OpenBabel interoperability""" from BigDFT.Systems import System from BigDFT.Fragments import Fragment from BigDFT.IO import XYZReader from os.path import join # Read in a system. sys = System() sys["FRA:1"] = Fragment() with XYZReader("CH4") as ifile: for at in ifile: sys["FRA:1"] += Fragment([at]) # We can compute the smiles representation. print(compute_smiles(sys)) # The energy. print(system_energy(sys, forcefield="UFF")) # Extract the forces. compute_system_forces(sys, forcefield="UFF") for frag in sys.values(): for at in frag: print(at["force"]) # Optimize the geometry. sys2 = optimize_system(sys, forcefield="UFF") print(system_energy(sys2, forcefield="UFF"))
def system_from_log(log, fragmentation=None): """ This function returns a :class:`~BigDFT.Fragment.System` class out of a logfile. If the logfile contains information about fragmentation and atomic multipoles, then the system is created accordingly. Otherwise, the fragmentation scheme is determined by the fragmentation variable. Args: log (Logfile): the logfile of the QM run. In general must have been done with Linear Scaling formalism. fragmentation (str): the scheme to be used for the fragmentation in the case if not provided internally by the logfile. The possible values are ``atomic`` and ``full``, in which case the system as as many fragments as the number of atoms, or only one fragment, respectively. Returns: (BigDFT.Systems.System): The instance of the class containing fragments. """ from BigDFT.Fragments import Fragment name = log.log.get('run_name', 'FULL') + ':0' full_system = System() posinp = log.log.get('posinp') if posinp is not None and not isinstance(posinp, str): full_system[name] = Fragment(posinp=posinp) else: full_system[name] = Fragment(astruct=log.astruct) full_system.set_logfile_info(log) # now we may defragment the system according to the provided scheme if fragmentation == 'full': return full_system elif fragmentation == 'atomic' or 'posinp' not in log.log: atomic_system = System() for iat, at in enumerate(full_system[name]): atomic_system['ATOM:' + str(iat)] = Fragment([at]) return atomic_system else: posinp = log.log['posinp'] frag_dict = {} for iat, tupl in enumerate(zip(posinp['positions'], full_system[name])): at, obj = tupl fragid = at.get('frag', 'ATOM:' + str(iat)) if isinstance(fragid, list): fragid = ':'.join(map(str, fragid)) if fragid not in frag_dict: frag_dict[fragid] = [obj] else: frag_dict[fragid].append(obj) frag_system = System() for fragid in frag_dict: frag_system[fragid] = Fragment(frag_dict[fragid]) return frag_system
def ase_to_bigdft(mol): """ Given an ASE collection of atoms, this transforms that collection into a BigDFT fragment. Args: mol (ase.Atoms): a collection of atoms used by ASE. Returns: (BigDFT.Fragments.Fragment): a BigDFT fragment. """ from BigDFT.Fragments import Fragment from BigDFT.Atoms import Atom frag = Fragment() for at in mol: frag += [ Atom({ "sym": at.symbol, "r": at.position, "units": "angstroem" }) ] return frag
def _example(): """Example of using PSI4 interoperability""" from BigDFT.IO import XYZReader from BigDFT.Systems import System from BigDFT.Fragments import Fragment from os.path import join from copy import deepcopy # Create a system. reader = XYZReader(join("Database", "XYZs", "He.xyz")) fsys = System() fsys["FRA:1"] = Fragment(xyzfile=reader) fsys["FRA:2"] = deepcopy(fsys["FRA:1"]) fsys["FRA:2"].translate([-2, 0, 0]) # Create a calculator. code = PSI4Calculator() log = code.run(sys=fsys, action="energy", basis="jun-cc-pvdz", psi4_options={"scf_type": "direct"}, method="scf", name="test") print(log) # The raw logfile is also available. print(log.log[4]) # Geometry optimization. log = code.run(sys=fsys, action="optimize", basis="jun-cc-pvdz", method="scf", name="test-opt") print(log) # SAPT log = code.run(sys=fsys, action="energy", basis="jun-cc-pvdz", method="sapt0", name="test-sapt") print(log)
def ase_potential_energy(self, ase_calculator): """ Given a ASE calculator, calculates the potential energy of the system. Args: ase_calculator (ase.calculators.calculator.Calculator): ASE calculator. Returns: float: the potential energy, in Hartree """ from Fragments import Fragment from ASEInterop import ase_potential_energy as asepot bigfrag = Fragment(system=self) return asepot(bigfrag, ase_calculator)
def _example(): """Visualization Example""" from BigDFT.Systems import System from BigDFT.Fragments import Fragment from BigDFT.IO import XYZReader # Read in a system. sys = System() with XYZReader("SiO") as ifile: for i, at in enumerate(ifile): sys["FRA:" + str(i)] = Fragment([at]) # Display the system. viz = InlineVisualizer(400, 300) viz.display_system(sys) # Change the colors colordict = get_distinct_colors(list(sys)) viz.display_system(sys, colordict=colordict)
def system_from_dict_positions(posinp, units='angstroem'): """ Build a system from a set of positions from a dictionary whose yaml serialisation is compliant with the BigDFT yaml position format Args: posinp (list): list of the atomic specifications Returns: BigDFT.Systems.System: an instance of the system class. The employed fragment specification is specified in the file. """ from BigDFT.Atoms import Atom from BigDFT.Fragments import Fragment sys = System() for iat, at in enumerate(posinp): frag = GetFragId(at, iat) if frag not in sys: sys[frag] = Fragment() sys[frag].append(Atom(at, units=units)) return sys
def __init__(self, name): import os from BigDFT.Fragments import Fragment from BigDFT.Systems import System from BigDFT.IO import XYZReader # import the positions of the molecules from the XYZ directory dirXYZ = os.path.join(os.path.dirname(__file__), 'XYZs') filename = os.path.abspath(os.path.join(dirXYZ, name + '.xyz')) if not os.path.isfile(filename): raise ValueError('Molecule not available') ff = XYZReader(filename) frag = Fragment(xyzfile=ff) system = System({'molecule:0': frag}) self.update(system.get_posinp()) # temporary change of the keys 'values' into 'positions' if 'values' in self: self['positions'] = self.pop('values') if 'positions' in self: for at in self['positions']: if 'r' in at: at.pop('r')
def generate_link_atoms(self, fullsys, subsys, distcut=6.0): """ This routine adds link atoms to a subsystem based on the bond order of a full system. Link atom positions are automatically adjusted based on the length of some standard bonds. Args: fullsys (BigDFT.Systems.System): the full system that the subsystem is embedded into. subsys (BigDFT.Systems.System): the embedded system which needs link atoms. distcut (float): this cutoff is the largest distance value we expect allow a bond to be. Returns: (BigDFT.Systems.System): the subsystem with link atoms added. (BigDFT.Systems.System): a system which has the atoms that were removed and replaced with link atoms. """ from BigDFT.Systems import System from BigDFT.Fragments import Fragment from copy import deepcopy from numpy.linalg import norm from numpy import array from warnings import warn # Bond lengths for link atoms. bond_lengths = { "C": 2.0598, "N": 1.90862, "O": 1.81414, "F": 1.73855, "P": 2.68341, "S": 2.53223, "Cl": 2.39995, "Br": 2.66451, "I": 3.04246 } if fullsys.conmat is None: raise ValueError("Generating link atoms requires connectivity" " information") linksys = deepcopy(subsys) removesys = System() # Loop over atoms and look for bonds running out of the QM system. for fragid in subsys: linklist = [] for i in range(0, len(fullsys[fragid])): for ft, bv in fullsys.conmat[fragid][i].items(): if ft[0] in subsys.keys(): continue if bv == 1: newat = deepcopy(fullsys[ft[0]][ft[1]]) # Change the symbol to hydrogen newat.sym = "H" newat.is_link = True # If possible we adjust the position for a reasonable # bond length conat = fullsys[fragid][i] if conat.sym in bond_lengths: pos1 = array(conat.get_position("bohr")) pos2 = array(newat.get_position("bohr")) vec = pos2 - pos1 vec *= bond_lengths[conat.sym] / norm(vec) newpos = [x + y for x, y in zip(pos1, vec)] newat.set_position(newpos, units="bohr") else: warn(conat.sym + "bondlength unknown", UserWarning) linklist.append(newat) elif bv > 1: print("Not yet implemented double/triple bonds.", bv) raise NotImplementedError if ft[0] not in removesys: removesys[ft[0]] = Fragment() removesys[ft[0]] += [fullsys[ft[0]][ft[1]]] # Add those atoms to the fragment for link in linklist: linksys[fragid] += [link] return linksys, removesys
def _example(): """ Postprocessing Example """ from BigDFT.Systems import System, FragmentView from BigDFT.Fragments import Fragment from BigDFT.IO import XYZReader from BigDFT.Calculators import SystemCalculator from BigDFT.Inputfiles import Inputfile from scipy.linalg import eigh from copy import deepcopy # Create a system sys = System() sys["FRA:0"] = Fragment() with XYZReader("CH2") as ifile: for at in ifile: sys["FRA:0"].append(at) sys["FRA:1"] = Fragment() with XYZReader("CH3") as ifile: for at in ifile: sys["FRA:1"].append(at) sys["FRA:1"].translate([0, 0, -3]) sys["FRA:2"] = deepcopy(sys["FRA:0"]) sys["FRA:2"].translate([0, 0, 3]) sys["FRA:2"].rotate(y=150, units="degrees") sys["FRA:3"] = deepcopy(sys["FRA:0"]) sys["FRA:3"].translate([3, 0, 1.5]) print(list(sys)) # Run a calculation. `write_support_function_matrices` and `linear` are # key. You also should be sure to set the atom multipoles. inp = Inputfile() inp.set_xc("PBE") inp.set_hgrid(0.4) inp.write_support_function_matrices() inp["import"] = "linear" code = SystemCalculator() code.update_global_options(verbose=False) log = code.run(input=inp, posinp=sys.get_posinp(), run_dir="work") sys.set_atom_multipoles(log) # Create the post processing tool. from BigDFT.PostProcessing import BigDFTool btool = BigDFTool() # Purity purity = btool.run_compute_purity(sys, log) print(purity) # Charges charges = { fragid: sum(at.nel for at in frag) for fragid, frag in sys.items() } # Bond Orders bo = btool.fragment_bond_order(sys, sys.keys(), sys.keys(), log) # Population values. population = btool.fragment_population(sys, log) print(population) # These three things define a fragment view. view = FragmentView(purity, bo, charges) # Auto Fragmentation mapping = btool.auto_fragment(sys, view, 0.10) print(mapping) # This defines a new view. new_view = view.refragment(mapping) print(new_view.purities) # Eigenvalues. H = btool.get_matrix_h(log) S = btool.get_matrix_s(log) w = eigh(H.todense(), b=S.todense(), eigvals_only=True) print(w)
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 read_pdb(ifile, include_chain=False, disable_warnings=False): """ Read a system from a PDB file. Args: ifile (TextIOBase): the file to read from. disable_warnings (bool): whether to print warnings about possible file issues. include_chain (bool): include the chain id if True Warning: This will read in the connectivity information from the pdb as well. However, a pdb file does not provide any information about the bond order. Thus, the bond order of each bond will be set to one. Returns: (BigDFT.Systems.System): the system file. """ from BigDFT.Fragments import Fragment from BigDFT.Systems import System from warnings import warn from BigDFT.UnitCells import UnitCell # First pass read in the atoms. sys = System() lookup = {} sys.conmat = {} found = False for line in ifile: try: # See if there is an atom on this line if line[:4] == "ATOM" or line[:6] == "HETATM": at, atid, fragid = _process_atom(line, include_chain=include_chain) # We can ignore lone pairs if at.sym == "Lp": continue # Add to the system if fragid not in sys: sys[fragid] = Fragment() sys[fragid] += [at] # Build the lookup table lookup[atid] = (fragid, len(sys[fragid]) - 1) elif line[:6] == "CONECT": found = True split = _split_line(line, len(lookup)) (fragid, atnum) = lookup[int(split[1])] for at2 in split[2:]: fragid2, atnum2 = lookup[int(at2)] if fragid not in sys.conmat: sys.conmat[fragid] = [] for i in range(0, len(sys[fragid])): sys.conmat[fragid].append({}) sys.conmat[fragid][atnum][(fragid2, atnum2)] = 1.0 elif line[:6] == "CRYST1": a = float(line[7:15]) b = float(line[16:24]) c = float(line[25:33]) alpha = float(line[34:40]) beta = float(line[41:47]) gamma = float(line[48:54]) sys.cell = UnitCell([a, b, c], units="angstroem") if not disable_warnings: if (alpha != 90 or beta != 90 or gamma != 90): warn("Cell angles must be 90 degrees", UserWarning) except IndexError: # For shorter lines continue if not found: sys.conmat = None else: # for any connectivity not specified we give default values. for fragid in sys: if fragid not in sys.conmat: sys.conmat[fragid] = [] for i in range(0, len(sys[fragid])): sys.conmat[fragid].append({}) if not disable_warnings: if sum([len(x) for x in sys.values()]) == 0: warn("Warning: zero atoms found", UserWarning) return sys
def read_mol2(ifile, disable_warnings=False): """ Read a system from a mol2 file. Args: ifile (TextIOBase): the file to read from. disable_warnings (bool): whether to print warnings about possible file issues. Returns: (BigDFT.Systems.System): the system file. """ from BigDFT.Systems import System from BigDFT.Fragments import Fragment from BigDFT.Atoms import Atom from BigDFT.UnitCells import UnitCell from warnings import warn sys = System() # Just go ahead and read the whole file into a string. lines = [x for x in ifile] # First pass, read in the number of atoms. for start, line in enumerate(lines): if ("@<TRIPOS>MOLECULE" in line): break start += 1 split = lines[start+1].split() natoms = int(split[0]) nbonds = int(split[1]) # Second pass read in the atoms. for start, line in enumerate(lines): if ("@<TRIPOS>ATOM" in line): break start += 1 lookup = [] for i in range(0, natoms): split = lines[start + i].split() pos = [float(x) for x in split[2:5]] name = split[5] sym = name.split(".")[0] fragid = split[7] + ":" + split[6] charge = [float(split[8])] # Add fragment if fragid not in sys: sys[fragid] = Fragment() at = Atom({sym: pos, "units": "angstroem", "q0": charge, "name": name}) sys[fragid] += [at] # Lookup table for connectivity lookup.append((fragid, len(sys[fragid]) - 1)) # Third pass reads the connectivity. for start, line in enumerate(lines): if ("@<TRIPOS>BOND" in line): break start += 1 if start < len(lines): sys.conmat = {} for fragid, frag in sys.items(): sys.conmat[fragid] = [] for i in range(0, len(frag)): sys.conmat[fragid].append({}) bowarn = False for i in range(0, nbonds): split = lines[start + i].split() frag1, at1 = lookup[int(split[1])-1] frag2, at2 = lookup[int(split[2])-1] bo = split[3] try: bo = float(split[3]) except ValueError: bowarn = True bo = 1 sys.conmat[frag1][at1][(frag2, at2)] = bo # Since mol2 doesn't include the symmetric bonds. if frag1 != frag2 or at1 != at2: sys.conmat[frag2][at2][(frag1, at1)] = bo # Fourth path reads the unit cell. for start, line in enumerate(lines): if ("@<TRIPOS>CRYSIN" in line): break start += 1 if start < len(lines): split = lines[start].split() a = float(split[0]) b = float(split[1]) c = float(split[2]) alpha = float(split[3]) beta = float(split[4]) gamma = float(split[5]) sys.cell = UnitCell([a, b, c], units="angstroem") if not disable_warnings: if (alpha != 90 or beta != 90 or gamma != 90): warn("Cell angles must be 90 degrees", UserWarning) if not disable_warnings: if sum([len(x) for x in sys.values()]) == 0: warn("Warning: zero atoms found", UserWarning) if bowarn: warn("Unsupported bond type had to be set to 1 (i.e. aromatic)", UserWarning) return sys
def read_polaris_pdb(pdbfile, chain_as_letter=False, slefile=None): """ Read coordinates in the PDB format of POLARIS Args: pdbfile (str): path of the input file chain_as_letter (bool): If True, the fifth column is assumed to contain a letter slefile (str): path of the file ``.sle`` of Polaris from which to extract the system's attributes. Warning: Assumes Free Boundary conditions for the molecule. Only accepts atoms that have one letter in the symbol. Switch representation if there is a single letter in the fifth column Returns: System: A system class """ from BigDFT.Fragments import Fragment from BigDFT.Systems import System, GetFragId from BigDFT.Atoms import Atom sys = System() units = 'angstroem' with open(pdbfile) as ifile: for line in ifile: if 'ATOM' not in line: continue atomline = line.split() if chain_as_letter: iat, name, frag, lett, ifrag, x, y, z, sn = atomline[1:10] chain = lett segname = sn else: iat, name, frag, ifrag, x, y, z, chlett = atomline[1:9] chain = chlett[2] segname = chlett atdict = { str(name[:1]): map(float, [x, y, z]), 'frag': [chain + '-' + frag, int(ifrag)], 'name': name, 'iat': int(iat), 'segname': segname } fragid = GetFragId(atdict, iat) if fragid not in sys: sys[fragid] = Fragment() sys[fragid].append(Atom(atdict, units=units)) if slefile is None: return sys attributes = read_polaris_sle(slefile) from BigDFT import Systems as S, Fragments as F, Atoms as A system = S.System() for name, frag in sys.items(): refrag = F.Fragment() for at in frag: atdict = at.dict() att = attributes[atdict['iat'] - 1] assert att['name'] == atdict['name'] atdict.update(att) refrag.append(A.Atom(atdict)) system[name] = refrag return system
def visualize_fragments(self, system, scriptfile, geomfile, fragcolors=None): """ This generates a script for visualizing the fragmentation of a system using VMD. Args: system (BigDFT.Systems.System): the system to visualize. scriptfile (str): the name of the file to write the vmd script to (usually has extension .tcl) geomfile (str): the filename for where to write an xyz file of the system. fragcolors (dict): optionally, a dictionary from fragment ids to fragment colors. Colors are integers between 0 and 32. """ from BigDFT.Fragments import Fragment from BigDFT.IO import XYZWriter # To create the XYZ file, we first make one big fragment. geomorder = Fragment() for fragid, frag in system.items(): geomorder += frag # Then write it to file. with XYZWriter(geomfile, len(geomorder)) as ofile: for at in geomorder: ofile.write(at) # Get the matching so we can write the correct atom indices. matching = system.compute_matching(geomorder) # If fragcolors is not specified, we will generate it ourselves. if fragcolors is None: fragcolors = {} for i, s in enumerate(system): # 16 is black, which we will reserve. if i % 32 == 16: c = str(32) else: c = str(i % 32) fragcolors[s] = c # The header of the script file draws the whole system in black. outstr = self._get_default_header(geomfile) # This part colors individual fragments. modid = 1 for fragid, frag in system.items(): if fragid not in fragcolors: continue outstr += "mol addrep 0\n" outstr += """mol modselect """ + str(modid) + """ 0 index """ outstr += " ".join([str(x) for x in matching[fragid]]) outstr += "\n" outstr += """mol modcolor """ outstr += str(modid) + """ 0 ColorID """ + \ str(fragcolors[fragid]) + """\n""" modid += 1 # Finally, write to file. with open(scriptfile, "w") as ofile: ofile.write(outstr)
def _example(): """Example of using ASE interoperability""" from BigDFT.IO import XYZReader from BigDFT.Inputfiles import Inputfile from BigDFT.Calculators import SystemCalculator from BigDFT.Fragments import Fragment from BigDFT.Systems import System from ase.calculators.lj import LennardJones from BigDFT.UnitCells import UnitCell from ase.units import Hartree from ase.optimize import BFGS from os.path import join from copy import deepcopy # Create a system. sys = System() reader = XYZReader("Ar") sys["FRA:1"] = Fragment(xyzfile=reader) sys["FRA:2"] = deepcopy(sys["FRA:1"]) sys["FRA:2"].translate([-2, 0, 0]) # Skip straight to the potential energy. print(ase_potential_energy(sys, LennardJones())) # Advanced used. asys = bigdft_to_ase(sys) asys.set_calculator(LennardJones()) dyn = BFGS(asys) dyn.run(fmax=0.05) print(asys.get_potential_energy() / Hartree) # Unit cells sys.cell = UnitCell([5, 5, 5], units="bohr") print(ase_potential_energy(sys, LennardJones())) sys.cell = UnitCell([5, float("inf"), 5], units="bohr") print(ase_potential_energy(sys, LennardJones())) sys.cell = UnitCell([float("inf"), float("inf"), 5], units="bohr") print(ase_potential_energy(sys, LennardJones())) # We can also use BigDFT with ase. inp = Inputfile() inp.set_xc("PBE") inp.set_hgrid(0.4) code = SystemCalculator(verbose=False) sys.cell = UnitCell() print( ase_potential_energy( sys, BigASECalculator(inp, code, directory="work", label="ase-free"))) sys.cell = UnitCell([5, 5, 5], units="bohr") print( ase_potential_energy( sys, BigASECalculator(inp, code, directory="work", label="ase-periodic"))) sys.cell = UnitCell([5, float("inf"), 5], units="bohr") print( ase_potential_energy( sys, BigASECalculator(inp, code, directory="work", label="ase-surface"))) sys.cell = UnitCell([float("inf"), float("inf"), 5], units="bohr") print( ase_potential_energy( sys, BigASECalculator(inp, code, directory="work", label="ase-wire")))