def LookupChargePairs(chargebyatomid, # bond_ids, # bond_types, # bond_pairs, lines_atoms, lines_bonds, lines_bond_list, lines_chargebybond, atom_style, section_name, prefix='', suffix=''): # bond_ids_offset=0): # report_progress = False): """ LookupChargePairs() looks up partial-charge pair contributions from the types of atoms participating in a bond. Output: ...It looks up the corresponding change in the partial charges for each pair of atoms and stores this in the "chargebyatomid" dictionary. Input (continued): This function requires: ...a list of bonded pairs of atoms stored in the lines_bonds variable (from the "Data Bond List" or "Data Bonds AtomId AtomId" sections) ...and a list of atom types stored in the lines_atoms variable (from the "Data Atoms" section) ...and a list of charge-pairs-as-a-function-of-atom-types stored in the lines_chargebybond (from the "Data Bonds By Type" section) """ column_names = AtomStyle2ColNames(atom_style) i_atomid, i_atomtype, i_molid = ColNames2AidAtypeMolid(column_names) atomids = [] atomtypes = [] atomids2types = {} for iv in range(0, len(lines_atoms)): line = lines_atoms[iv].strip() if '#' in line: icomment = line.find('#') line = (line[:icomment]).strip() if len(line) > 0: tokens = ttree_lex.SplitQuotedString(line) if ((len(tokens) <= i_atomid) or (len(tokens) <= i_atomtype)): sys.stderr.write("\"" + line + "\"\n") raise(ttree_lex.InputError( 'Error not enough columns on line ' + str(iv + 1) + ' of \"Atoms\" section.')) tokens = ttree_lex.SplitQuotedString(line) atomid = ttree_lex.EscCharStrToChar(tokens[i_atomid]) atomids.append(atomid) atomtype = ttree_lex.EscCharStrToChar(tokens[i_atomtype]) atomtypes.append(atomtype) atomids2types[atomid] = atomtype #assert(isinstance(bond_ids, list)) #assert(isinstance(bond_types, list)) #assert(isinstance(bond_pairs, list)) #del bond_ids[:] #del bond_types[:] #del bond_pairs[:] bond_pairs = [] for ie in range(0, len(lines_bond_list)): line = lines_bond_list[ie].strip() if '#' in line: icomment = line.find('#') line = (line[:icomment]).strip() if len(line) == 0: continue tokens = ttree_lex.SplitQuotedString(line) if len(tokens) == 3: # bond_ids.append(ttree_lex.EscCharStrToChar(tokens[0])) bond_pairs.append((ttree_lex.EscCharStrToChar(tokens[1]), ttree_lex.EscCharStrToChar(tokens[2]))) else: raise(ttree_lex.InputError('Incorrect number of columns on line ' + str(ie + 1) + ' of \"' + section_name + '\" section.')) for ie in range(0, len(lines_bonds)): line = lines_bonds[ie].strip() if '#' in line: icomment = line.find('#') line = (line[:icomment]).strip() if len(line) == 0: continue tokens = ttree_lex.SplitQuotedString(line) if len(tokens) == 4: # bond_ids.append(ttree_lex.EscCharStrToChar(tokens[0])) # bond_types.append(ttree_lex.EscCharStrToChar(tokens[1])) bond_pairs.append((ttree_lex.EscCharStrToChar(tokens[2]), ttree_lex.EscCharStrToChar(tokens[3]))) else: raise(ttree_lex.InputError('Incorrect number of columns on line ' + str(ie + 1) + ' of \"' + section_name + '\" section.')) # for ie in range(0, len(lines_bonds_atomid_atomid)): # line = lines_bonds_atomid_atomid[ie].strip() # if '#' in line: # icomment = line.find('#') # line = (line[:icomment]).strip() # if len(line) == 0: # continue # tokens = ttree_lex.SplitQuotedString(line) # if len(tokens) == 2: # #bondid_n = bond_ids_offset + len(bond_ids) + 1 # #bond_ids.append(prefix+str(bondid_n)+suffix) # bond_pairs.append( (ttree_lex.EscCharStrToChar(tokens[0]), # ttree_lex.EscCharStrToChar(tokens[1])) ) # else: # raise(ttree_lex.InputError('Incorrect number of columns on line '+str(ie+1)+' of \"'+section_name+'\" section.')) #assert(len(bond_types) == 0) typepattern_to_chargepairs = [] warning_unassigned_chargepairs = None for i in range(0, len(lines_chargebybond)): line = lines_chargebybond[i].strip() if '#' in line: icomment = line.find('#') line = (line[:icomment]).strip() if len(line) > 0: tokens = ttree_lex.SplitQuotedString(line) if (len(tokens) != 4): raise(ttree_lex.InputError('Error: Wrong number of columns in the \"Charge Pairs By Type\" section of data file.\n' 'Offending line:\n' + '\"' + line + '\"\n' 'Expected 4 columns\n')) chargepair = (float(tokens[2]), float(tokens[3])) typepattern = [] for typestr in tokens[:2]: if ttree_lex.HasRE(typestr): regex_str = typestr[3:] typepattern.append(re.compile(regex_str)) else: typepattern.append(ttree_lex.EscCharStrToChar(typestr)) typepattern_to_chargepairs.append([typepattern, chargepair]) for atomid1, atomid2 in bond_pairs: if atomid1 not in atomids2types: raise ttree_lex.InputError('Error: atom \"' + atomid1 + '\" not defined in \"Data Atoms\".\n' ' This usually happens when the user mistypes one of the names of the\n' ' $atoms in either a \"Data Atoms\" or \"Data Bond List\" section.\n' ' To find out where the mistake occured, search the \n' ' \"ttree_assignments.txt\" file for:\n' ' \"' + atomid1 + '\"\n') if atomid2 not in atomids2types: raise ttree_lex.InputError('Error: atom \"' + atomid2 + '\" not defined in \"Data Atoms\".\n' ' This usually happens when the user mistypes one of the names of the\n' ' $atoms in either a \"Data Atoms\" or \"Data Bond List\" section.\n' ' To find out where the mistake occured, search the \n' ' \"ttree_assignments.txt\" file for:\n' ' \"' + atomid2 + '\"\n') atomtype1 = atomids2types[atomid1] atomtype2 = atomids2types[atomid2] found = False for typepattern, chargepair in typepattern_to_chargepairs: # use string comparisons to check if atom types match the pattern if ttree_lex.MatchesAll((atomtype1, atomtype2), typepattern): # ("MatchesAll()" defined in "ttree_lex.py") chargebyatomid[atomid1] += chargepair[0] chargebyatomid[atomid2] += chargepair[1] found = True elif ttree_lex.MatchesAll((atomtype2, atomtype1), typepattern): chargebyatomid[atomid1] += chargepair[1] chargebyatomid[atomid2] += chargepair[0] found = True if (not found) and (not warning_unassigned_chargepairs): warning_unassigned_chargepairs = (atomid1, atomid2) if warning_unassigned_chargepairs: sys.stderr.write('---------------------------------------------------------------------------\n' 'Warning: bonds found between atoms with no partial-charge rules.\n' ' This means that somewhere you are using a force-field\n' ' which assigns atomic charge according to the bonds these atoms\n' ' participate in, AND at least one pair of bonded atoms does NOT have\n' ' a rule defined to assign charges to that pair of atoms.\n' ' This can happen if there is a problem with the force-field file\n' ' OR if you are defining the charges for these atoms manually\n' ' In the later case, it is not a problem.\n' ' The first bond with this problem is between this pair of atoms:\n' ' ' + str(warning_unassigned_chargepairs[0]) + '\n' ' ' + str(warning_unassigned_chargepairs[1]) + '\n' '---------------------------------------------------------------------------\n')
def LookupBondTypes(bond_types, bond_ids, bond_pairs, lines_atoms, lines_bonds, lines_bondsbytype, atom_style, section_name, prefix='', suffix='', bond_ids_offset=0): #report_progress = False): """ LookupBondTypes() looks up bond types. Output: ...It looks up the corresponding type of each bond and store it in the "bond_types" list. (If the bond_ids were not specified by the user, generate them and store them in the bond_ids list.) Input (continued): This function requires: ...a list of bonded pairs of atoms stored in the lines_bonds variable (from the "Data Bond List" or "Data Bonds AtomId AtomId" sections) ...and a list of atom types stored in the lines_atoms variable (from the "Data Atoms" section) ...and a list of bond-types-as-a-function-of-atom-types stored in the lines_bondsbytype (from the "Data Bonds By Type" section) Generated bond_ids (if applicable) are of the form prefix + str(number) + suffix (where "number" begins at bond_ids_offset+1) """ column_names = AtomStyle2ColNames(atom_style) i_atomid, i_atomtype, i_molid = ColNames2AidAtypeMolid(column_names) atomids = [] atomtypes = [] atomids2types = {} for iv in range(0, len(lines_atoms)): line = lines_atoms[iv].strip() if '#' in line: icomment = line.find('#') line = (line[:icomment]).strip() if len(line) > 0: tokens = ttree_lex.SplitQuotedString(line) if ((len(tokens) <= i_atomid) or (len(tokens) <= i_atomtype)): sys.stderr.write("\""+line+"\"\n") raise(ttree_lex.InputError('Error not enough columns on line '+str(iv+1)+' of \"Atoms\" section.')) tokens = ttree_lex.SplitQuotedString(line) atomid = ttree_lex.EscCharStrToChar(tokens[i_atomid]) atomids.append(atomid) atomtype = ttree_lex.EscCharStrToChar(tokens[i_atomtype]) atomtypes.append(atomtype) atomids2types[atomid] = atomtype assert(isinstance(bond_ids, list)) assert(isinstance(bond_types, list)) assert(isinstance(bond_pairs, list)) del bond_ids[:] del bond_types[:] del bond_pairs[:] for ie in range(0, len(lines_bonds)): line = lines_bonds[ie].strip() if '#' in line: icomment = line.find('#') line = (line[:icomment]).strip() if len(line) == 0: continue tokens = ttree_lex.SplitQuotedString(line) if section_name == "Data Bonds AtomId AtomId": if len(tokens) == 2: bondid_n = bond_ids_offset + len(bond_ids) + 1 bond_ids.append(prefix+str(bondid_n)+suffix) bond_pairs.append( (ttree_lex.EscCharStrToChar(tokens[0]), ttree_lex.EscCharStrToChar(tokens[1])) ) else: raise(ttree_lex.InputError('Incorrect number of columns on line '+str(ie+1)+' of \"'+section_name+'\" section.')) elif section_name == "Data Bond List": if len(tokens) == 3: bond_ids.append(ttree_lex.EscCharStrToChar(tokens[0])) bond_pairs.append( (ttree_lex.EscCharStrToChar(tokens[1]), ttree_lex.EscCharStrToChar(tokens[2])) ) else: raise(ttree_lex.InputError('Incorrect number of columns on line '+str(ie+1)+' of \"'+section_name+'\" section.')) else: raise(ttree_lex.InputError('Internal Error ('+g_program_name+'): Unknown section name: \"'+section_name+'\"')) assert(len(bond_types) == 0) typepattern_to_coefftypes = [] for i in range(0, len(lines_bondsbytype)): line = lines_bondsbytype[i].strip() if '#' in line: icomment = line.find('#') line = (line[:icomment]).strip() if len(line) > 0: tokens = ttree_lex.SplitQuotedString(line) if (len(tokens) != 3): raise(ttree_lex.InputError('Error: Wrong number of columns in the \"Bonds By Type\" section of data file.\n' 'Offending line:\n'+ '\"'+line+'\"\n' 'Expected 3 columns\n')) coefftype = ttree_lex.EscCharStrToChar(tokens[0]) typepattern = [] for typestr in tokens[1:]: if ((len(typestr) >= 2) and (typestr[0] == '/') and (typestr[-1] == '/')): regex_str = typestr[1:-1] typepattern.append( re.compile(regex_str) ) else: typepattern.append(ttree_lex.EscCharStrToChar(typestr)) typepattern_to_coefftypes.append([typepattern, coefftype]) assert(len(bond_ids) == len(bond_pairs)) for ie in range(0,len(bond_ids)): bond_types.append(None) for ie in range(0, len(bond_ids)): bondid = bond_ids[ie] (atomid1, atomid2) = bond_pairs[ie] if atomid1 not in atomids2types: raise ttree_lex.InputError('Error: atom \"'+atomid1+'\" not defined in \"Data Atoms\".\n' ' This usually happens when the user mistypes one of the names of the\n' ' $atoms in either a \"Data Atoms\" or \"Data Bond List\" section.\n' ' To find out where the mistake occured, search the \n' ' \"ttree_assignments.txt\" file for:\n' ' \"'+atomid1+'\"\n') if atomid2 not in atomids2types: raise ttree_lex.InputError('Error: atom \"'+atomid2+'\" not defined in \"Data Atoms\".\n' ' This usually happens when the user mistypes one of the names of the\n' ' $atoms in either a \"Data Atoms\" or \"Data Bond List\" section.\n' ' To find out where the mistake occured, search the \n' ' \"ttree_assignments.txt\" file for:\n' ' \"'+atomid2+'\"\n') atomtype1 = atomids2types[atomid1] atomtype2 = atomids2types[atomid2] for typepattern, coefftype in typepattern_to_coefftypes: # use string comparisons to check if atom types match the pattern if (ttree_lex.MatchesAll((atomtype1, atomtype2), typepattern) or ttree_lex.MatchesAll((atomtype2, atomtype1), typepattern)): # ("MatchesAll()" defined in "ttree_lex.py") bond_types[ie] = coefftype for ie in range(0, len(bond_ids)): if not bond_types[ie]: (atomid1, atomid2) = bond_pairs[ie] atomtype1 = atomids2types[atomid1] atomtype2 = atomids2types[atomid2] raise ttree_lex.InputError('Error: No bond types defined for the bond between\n' ' atoms '+atomid1+' (type '+atomtype1+')\n' ' and '+atomid2+' (type '+atomtype2+')\n')