def _fit_initial_charges(mol, args, atom_types): from parameterize.charge import fitGasteigerCharges from parameterize.parameterization.util import guessBondType logger.info("=== Initial atomic charge fitting ===") if args.charge_type == "None": logger.info("Initial atomic charges are taken from {}".format( args.filename)) elif args.charge_type in ("Gasteiger", "AM1-BCC", "ESP"): if args.min_type == "mm": logger.info("Method: Gasteiger") # TODO move to _prepare_molecule if np.any(mol.bondtype == "un"): logger.info("Guessing bond types") mol = guessBondType(mol) mol = fitGasteigerCharges(mol, atom_types=atom_types) charge = int(round(np.sum(mol.charge))) if args.charge != charge: logger.warning( f"Molecular charge is {args.charge}, but Gasteiger atomic charges add up to {charge}!" ) args.charge = charge # Print the initial charges logger.info("Initial atomic charges:") for name, charge in zip(mol.name, mol.charge): logger.info(" {:4s}: {:6.3f}".format(name, charge)) logger.info("Molecular charge: {:6.3f}".format(np.sum(mol.charge))) elif args.min_type in ("None", "qm"): logger.info("Initial atomic charges are not required") else: raise AssertionError() else: raise AssertionError() return mol
def _fit_charges(mol, args, qm, atom_types): from parameterize.charge import ( fitGasteigerCharges, fitChargesWithAntechamber, fitESPCharges, symmetrizeCharges, ) from parameterize.parameterization.util import ( guessBondType, getFixedChargeAtomIndices, getDipole, _qm_method_name, ) from parameterize.parameterization.detect import detectEquivalentAtoms logger.info("=== Atomic charge fitting ===") logger.info("Method: {}".format(args.charge_type)) if args.charge_type == "None": # TODO move to argument validation if len(args.fix_charge) > 0: logger.warning("Flag --fix-charge does not have effect!") logger.info("Atomic charges are taken from {}".format(args.filename)) elif args.charge_type == "Gasteiger": # TODO move to argument validation if len(args.fix_charge) > 0: logger.warning("Flag --fix-charge does not have effect!") # TODO move to _prepare_molecule if np.any(mol.bondtype == "un"): logger.info("Guessing bond types") mol = guessBondType(mol) mol = fitGasteigerCharges(mol, atom_types=atom_types) charge = int(round(np.sum(mol.charge))) if args.charge != charge: logger.warning( f"Molecular charge is {args.charge}, but Gasteiger atomic charges add up to {charge}!" ) args.charge = charge elif args.charge_type == "AM1-BCC": # TODO move to argument validation if len(args.fix_charge) > 0: logger.warning("Flag --fix-charge does not have effect!") mol = fitChargesWithAntechamber(mol, type="bcc", molCharge=args.charge) mol = symmetrizeCharges(mol) elif args.charge_type == "ESP": # Detect equivalent atom groups logger.info("Equivalent atom groups:") atom_groups = [ group for group in detectEquivalentAtoms(mol)[0] if len(group) > 1 ] for atom_group in atom_groups: logger.info(" {}".format(", ".join(mol.name[list(atom_group)]))) # Select the atoms with fixed charges fixed_atom_indices = getFixedChargeAtomIndices(mol, args.fix_charge) # Create an ESP directory espDir = os.path.join(args.outdir, "esp", _qm_method_name(qm)) os.makedirs(espDir, exist_ok=True) charge = int(round(np.sum(mol.charge))) if args.charge != charge: logger.warning( "Molecular charge is set to {}, but atomic charges add up to {}" "".format(args.charge, charge)) if len(args.fix_charge) > 0: raise RuntimeError( "Flag --fix-charge cannot be used when atomic charges are inconsistent with passed " "molecular charge {}".format(args.charge)) mol.charge[:] = args.charge / mol.numAtoms # Set random number generator seed if args.seed: np.random.seed(args.seed) # Fit ESP charges mol, extra = fitESPCharges(mol, qm, espDir, fixed=fixed_atom_indices) # Print QM dipole logger.info( "QM dipole: {:6.3f} {:6.3f} {:6.3f}; total: {:6.3f}".format( *extra["qm_dipole"])) else: raise ValueError() # Print MM dipole mm_dipole = getDipole(mol) logger.info("MM dipole: {:6.3f} {:6.3f} {:6.3f}; total: {:6.3f}".format( *mm_dipole)) # Print the new charges logger.info("Atomic charges:") for name, charge in zip(mol.name, mol.charge): logger.info(" {:4s}: {:6.3f}".format(name, charge)) logger.info("Molecular charge: {:6.3f}".format(np.sum(mol.charge))) return mol