#!/usr/bin/env python
# polarizer.py - add Drude oscillators to LAMMPS data file.
# Agilio Padua <agilio.padua@univ-bpclermont.fr>
# Alain Dequidt <alain.dequidt@univ-bpclermont.fr>
# version 2017/02/08

import sys
import argparse
import random
from copy import deepcopy

usage = """Add Drude oscillators to LAMMPS data file.

Format of file containing specification of Drude oscillators:

  # type  dm/u  dq/e  k/(kJ/molA2)  alpha/A3  thole
  C3H     1.0   0.0   4184.0        2.051     2.6
  ...

* dm is the mass to place on the Drude particle (taken from its core),
* dq is the charge to place on the Drude particle (taken from its core),
* k is the harmonic force constant of the bond between core and Drude,
* alpha is the polarizability,
* thole is a parameter of the Thole damping function.

A Drude particle is created for each atom in the LAMMPS data file
that corresponds to an atom type given in the Drude file.
Since LAMMPS uses numbers for atom types in the data file, a comment
after each line in the Masses section has to be introduced to allow
identification of the atom types within the force field database:

  Masses

  1   12.011  # C3H
  2   12.011  # CTO
  ...

This script will add new atom types, new bond types, new atoms and
new bonds to the data file.

It will also generate some commands to be included in the LAMMPS input script,
which are related to the topology and force field, namely fix drude,
pair_style and pair_coeff commands. For information on thermostating please
read the documentation of the USER-DRUDE package.

This tool can also be used to revert a Drude-polarized data file to a
non-polarizable one.
"""

# keywords of header and main sections (from data.py in Pizza.py)

hkeywords = ["atoms", "ellipsoids", "lines", "triangles", "bodies",
             "bonds", "angles", "dihedrals", "impropers",
             "atom types", "bond types", "angle types", "dihedral types",
             "improper types", "xlo xhi", "ylo yhi", "zlo zhi", "xy xz yz"]

skeywords = [["Masses", "atom types"],
             ["Pair Coeffs", "atom types"],
             ["Bond Coeffs", "bond types"], ["Angle Coeffs", "angle types"],
             ["Dihedral Coeffs", "dihedral types"],
             ["Improper Coeffs", "improper types"],
             ["BondBond Coeffs", "angle types"],
             ["BondAngle Coeffs", "angle types"],
             ["MiddleBondTorsion Coeffs", "dihedral types"],
             ["EndBondTorsion Coeffs", "dihedral types"],
             ["AngleTorsion Coeffs", "dihedral types"],
             ["AngleAngleTorsion Coeffs", "dihedral types"],
             ["BondBond13 Coeffs", "dihedral types"],
             ["AngleAngle Coeffs", "improper types"],
             ["Atoms", "atoms"], ["Velocities", "atoms"],
             ["Ellipsoids", "ellipsoids"],
             ["Lines", "lines"], ["Triangles", "triangles"],
             ["Bodies", "bodies"],
             ["Bonds", "bonds"],
             ["Angles", "angles"], ["Dihedrals", "dihedrals"],
             ["Impropers", "impropers"], ["Molecules", "atoms"]]


def massline(att):
    return "{0:4d} {1:8.3f}  # {2}\n".format(att['id'], att['m'], att['type'])

def bdtline(bdt):
    return "{0:4d} {1:12.6f} {2:12.6f}  {3}\n".format(bdt['id'], bdt['k'],
                                                     bdt['r0'], bdt['note'])

def atomline(at):
    return "{0:7d} {1:7d} {2:4d} {3:8.4f} {4:13.6e} {5:13.6e} {6:13.6e} "\
           " {7}\n".format(at['n'], at['mol'], at['id'], at['q'],
                           at['x'], at['y'], at['z'], at['note'])

def bondline(bd):
    return "{0:7d} {1:4d} {2:7d} {3:7d}  {4}\n".format(bd['n'], bd['id'],
                                            bd['i'], bd['j'], bd['note'])

def velline(at):
    return "{0:7d} {1:13.6e} {2:13.6e} {3:13.6e} \n".format(at['n'],
                                       at['vx'], at['vy'], at['vz'])

# --------------------------------------


class Data(object):

    def __init__(self, datafile):
        '''read LAMMPS data file (from data.py in Pizza.py)'''

        # for extract method
        self.atomtypes = []
        self.bondtypes = []
        self.atoms = []
        self.bonds = []
        self.idmap = {}

        self.nselect = 1

        f = open(datafile, "r")

        self.title = f.readline()
        self.names = {}

        headers = {}
        while 1:
            line = f.readline().strip()
            if '#' in line:
                line = line[:line.index('#')].strip()
            if len(line) == 0:
                continue
            found = 0
            for keyword in hkeywords:
                if keyword in line:
                    found = 1
                    words = line.split()
                    if keyword == "xlo xhi" or keyword == "ylo yhi" or \
                      keyword == "zlo zhi":
                        headers[keyword] = (float(words[0]), float(words[1]))
                    elif keyword == "xy xz yz":
                        headers[keyword] = \
                          (float(words[0]), float(words[1]), float(words[2]))
                    else:
                        headers[keyword] = int(words[0])
            if not found:
                break

        sections = {}
        while 1:
            if len(line) > 0:
                found = 0
                for pair in skeywords:
                    keyword, length = pair[0], pair[1]
                    if keyword == line:
                        found = 1
                        if length not in headers:
                            raise RuntimeError("data section {} "\
                                  "has no matching header value".format(line))
                        f.readline()
                        list_ = []
                        for _ in range(headers[length]):
                            list_.append(f.readline())
                        sections[keyword] = list_
                if not found:
                    raise RuntimeError("invalid section {} in data"\
                                       " file".format(line))
            #f.readline()
            line = f.readline()
            if not line:
                break
            if '#' in line:
                line = line[:line.index('#')]
            line = line.strip()

        f.close()
        self.headers = headers
        self.sections = sections

    def write(self, filename):
        '''write out a LAMMPS data file (from data.py in Pizza.py)'''

        with open(filename, "w") as f:
            f.write(self.title + '\n')
            for keyword in hkeywords:
                if keyword in self.headers:
                    if keyword == "xlo xhi" or keyword == "ylo yhi" or \
                       keyword == "zlo zhi":
                        f.write("{0:f} {1:f} {2}\n".format(
                            self.headers[keyword][0],
                            self.headers[keyword][1], keyword))
                    elif keyword == "xy xz yz":
                        f.write("{0:f} {1:f} {2:f} {3}\n".format(
                            self.headers[keyword][0],
                            self.headers[keyword][1],
                            self.headers[keyword][2], keyword))
                    else:
                        f.write("{0:d} {1}\n".format(self.headers[keyword],
                                                   keyword))
            for pair in skeywords:
                keyword = pair[0]
                if keyword in self.sections:
                    f.write("\n{}\n\n".format(keyword))
                    for line in self.sections[keyword]:
                        f.write(line)

    def extract_nonpol(self):
        """extract atom and bond info from nonpolarizable data"""

        # extract atom IDs
        missinglabels = False
        for line in self.sections['Masses']:
            tok = line.split()
            if len(tok) < 4:
                print("error: missing type for atom ID " + tok[0] +
                      " in Masses section")
                missinglabels = True
                continue
            atomtype = {}
            atomtype['id'] = int(tok[0])
            atomtype['m'] = float(tok[1])
            atomtype['type'] = tok[3]
            self.atomtypes.append(atomtype)

        if missinglabels:
            sys.exit(0)

        # extract atom registers
        for line in self.sections['Atoms']:
            tok = line.split()
            atom = {}
            atom['n'] = int(tok[0])
            atom['mol'] = int(tok[1])
            atom['id'] = int(tok[2])
            atom['q'] = float(tok[3])
            atom['x'] = float(tok[4])
            atom['y'] = float(tok[5])
            atom['z'] = float(tok[6])
            #atom['note'] = ''.join([s + ' ' for s in tok[7:]]).strip()
            atom['note'] = ' '.join(tok[7:])
            self.atoms.append(atom)
            self.idmap[atom['n']] = atom

        if 'Velocities' in self.sections:
            for line in self.sections['Velocities']:
                tok = line.split()
                atom = self.idmap[int(tok[0])]
                atom['vx'] = float(tok[1])
                atom['vy'] = float(tok[2])
                atom['vz'] = float(tok[3])

    def polarize(self, drude):
        """add Drude particles"""

        if 'Pair Coeffs' in self.sections:
            raise RuntimeError("cannot polarize a data with Pair Coeffs")

        self.extract_nonpol()

        natom = self.headers['atoms']
        nbond = self.headers['bonds']
        nattype = self.headers['atom types']
        nbdtype = self.headers['bond types']

        # create new atom types (IDs) for Drude particles and modify cores
        newattypes = []
        for att in self.atomtypes:
            att['dflag'] = 'n'
            for ddt in drude.types:
                if ddt['type'] == att['type']:
                    nattype += 1
                    newid = {}
                    newid['id'] = ddt['id'] = nattype
                    newid['m'] = ddt['dm']
                    att['m'] -= ddt['dm']
                    # label drude particles and cores
                    att['dflag'] = 'c'
                    newid['dflag'] = 'd'
                    newid['type'] = att['type'] + ' DP'
                    att['type'] += ' DC'
                    ddt['type'] += ' DC'
                    newattypes.append(newid)
                    break

        self.headers['atom types'] += len(newattypes)
        self.sections['Masses'] = []
        for att in self.atomtypes + newattypes:
            self.sections['Masses'].append(massline(att))

        # create new bond types for core-drude bonds
        newbdtypes = []
        for att in self.atomtypes:
            for ddt in drude.types:
                if ddt['type'] == att['type']:
                    nbdtype += 1
                    newbdtype = {}
                    newbdtype['id'] = ddt['bdid'] = nbdtype
                    newbdtype['k'] = ddt['k']
                    newbdtype['r0'] = 0.0
                    newbdtype['note'] = '# ' + ddt['type'] + '-DP'
                    newbdtypes.append(newbdtype)
                    break

        self.headers['bond types'] += len(newbdtypes)
        for bdt in newbdtypes:
            self.sections['Bond Coeffs'].append(bdtline(bdt))

        # create new atoms for Drude particles and new bonds with their cores
        random.seed(123)
        newatoms = []
        newbonds = []
        for atom in self.atoms:
            atom['dflag'] = ''           # [c]ore, [d]rude, [n]on-polarizable
            atom['dd'] = 0               # partner drude or core
            for att in self.atomtypes:
                if att['id'] == atom['id']:
                    break
            for ddt in drude.types:
                if ddt['type'] == att['type']:
                    natom += 1
                    newatom = deepcopy(atom)
                    newatom['n'] = natom
                    self.idmap[natom] = newatom
                    newatom['id'] = ddt['id']
                    newatom['q'] = ddt['dq']
                    newatom['note'] = atom['note']
                    if '#' not in newatom['note']:
                        newatom['note'] += ' #'
                    newatom['note'] += ' DP'
                    newatom['dflag'] = 'd'
                    newatom['dd'] = atom['n']

                    # avoid superposition of cores and Drudes
                    newatom['x'] += 0.1 * (random.random() - 0.5)
                    newatom['y'] += 0.1 * (random.random() - 0.5)
                    newatom['z'] += 0.1 * (random.random() - 0.5)
                    if 'Velocities' in self.sections:
                        newatom['vx'] = atom['vx']
                        newatom['vy'] = atom['vy']
                        newatom['vz'] = atom['vz']

                    newatoms.append(newatom)
                    atom['q'] -= ddt['dq']
                    atom['dflag'] = 'c'
                    atom['dd'] = natom
                    if '#' not in atom['note']:
                        atom['note'] += ' #'
                    atom['note'] += ' DC'

                    nbond += 1
                    newbond = {}
                    newbond['n'] = nbond
                    newbond['id'] = ddt['bdid']
                    newbond['i'] = atom['n']
                    newbond['j'] = newatom['n']
                    newbond['note'] = '# ' + ddt['type'] + '-DP'
                    newbonds.append(newbond)
                    break

        self.headers['atoms'] += len(newatoms)
        self.headers['bonds'] += len(newbonds)
        self.sections['Atoms'] = []
        for atom in self.atoms + newatoms:
            self.sections['Atoms'].append(atomline(atom))
        for bond in newbonds:
            self.sections['Bonds'].append(bondline(bond))
        if 'Velocities' in self.sections:
            self.sections['Velocities'] = []
            for atom in self.atoms + newatoms:
                self.sections['Velocities'].append(velline(atom))

        # update list of atom IDs
        for att in newattypes:
            self.atomtypes.append(att)


    def extract_pol(self, drude):
        """extract atom, drude, bonds info from polarizable data"""

        # extract atom IDs
        for line in self.sections['Masses']:
            tok = line.split()
            atomtype = {}
            atomtype['id'] = int(tok[0])
            atomtype['m'] = float(tok[1])
            if len(tok) >= 4:
                atomtype['type'] = tok[3]
                atomtype['dflag'] = 'n'
                if tok[-1] == "DC":
                    atomtype['dflag'] = 'c'
                elif tok[-1] == "DP":
                    atomtype['dflag'] = 'd'
                print(atomtype['dflag'])
            else:
                raise RuntimeError("comments in Masses section required "\
                                   "to identify cores (DC) and Drudes (DP)")
            self.atomtypes.append(atomtype)
                        
        # extract bond type data
        for line in self.sections['Bond Coeffs']:
            tok = line.split()
            bondtype = {}
            bondtype['id'] = int(tok[0])
            bondtype['k'] = float(tok[1])
            bondtype['r0'] = float(tok[2])
            bondtype['note'] = ''.join([s + ' ' for s in tok[3:]]).strip()
            self.bondtypes.append(bondtype)

        # extract atom registers
        for line in self.sections['Atoms']:
            tok = line.split()
            atom = {}
            atom['n'] = int(tok[0])
            atom['mol'] = int(tok[1])
            atom['id'] = int(tok[2])
            atom['q'] = float(tok[3])
            atom['x'] = float(tok[4])
            atom['y'] = float(tok[5])
            atom['z'] = float(tok[6])
            # atom['note'] = ''.join([s + ' ' for s in tok[7:-1]]).strip()
            if tok[-1] == 'DC':
              atom['note'] = ' '.join(tok[7:-1])
            else:
              atom['note'] = ' '.join(tok[7:])
            self.atoms.append(atom)
            self.idmap[atom['n']] = atom

        if 'Velocities' in self.sections:
            for line in self.sections['Velocities']:
                tok = line.split()
                atom = self.idmap[int(tok[0])]
                atom['vx'] = float(tok[1])
                atom['vy'] = float(tok[2])
                atom['vz'] = float(tok[3])

        # extract bond data
        for line in self.sections['Bonds']:
            tok = line.split()
            bond = {}
            bond['n'] = int(tok[0])
            bond['id'] = int(tok[1])
            bond['i'] = int(tok[2])
            bond['j'] = int(tok[3])
            bond['note'] = ''.join([s + ' ' for s in tok[4:]]).strip()
            self.bonds.append(bond)


    def depolarize(self, drude):
        """remove Drude particles"""

        self.extract_pol(drude)

        atom_tp_map = {}
        bond_tp_map = {}
        atom_map = {}
        bond_map = {}
        q = {}
        atom_tp = {}
        m = {}

        for att in self.atomtypes:
            if att['dflag'] != 'd':
                atom_tp_map[att['id']] = len(atom_tp_map) + 1
            m[att['id']] = att['m']
        print(atom_tp_map)
        for atom in self.atoms:
            if atom['id'] in atom_tp_map:
                atom_map[atom['n']] = len(atom_map) + 1
            q[atom['n']] = atom['q']
            atom_tp[atom['n']] = atom['id']
        for bond in self.bonds:
            if bond['i'] in atom_map and bond['j'] in atom_map:
                bond_map[bond['n']] = len(bond_map) + 1
                if bond['id'] not in bond_tp_map:
                    bond_tp_map[bond['id']] = len(bond_tp_map) + 1
            else:
                if bond['i'] in atom_map:
                    q[bond['i']] += q[bond['j']]
                    if atom_tp[bond['j']] in m:
                        m[atom_tp[bond['i']]] += m.pop(atom_tp[bond['j']])
                else:
                    q[bond['j']] += q[bond['i']]
                    if atom_tp[bond['i']] in m:
                        m[atom_tp[bond['j']]] += m.pop(atom_tp[bond['i']])

        size = len(self.atomtypes)
        for iatom_tp in reversed(range(size)):
            att = self.atomtypes[iatom_tp]
            if att['id'] not in atom_tp_map:
                del self.atomtypes[iatom_tp]
            else:
                att['m'] = m[att['id']]
                att['id'] = atom_tp_map[att['id']]

        size = len(self.bondtypes)
        for ibond_tp in reversed(range(size)):
            bdt = self.bondtypes[ibond_tp]
            if bdt['id'] not in bond_tp_map:
                del self.bondtypes[ibond_tp]
            else:
                bdt['id'] = bond_tp_map[bdt['id']]

        size = len(self.atoms)
        for iatom in reversed(range(size)):
            atom = self.atoms[iatom]
            if atom['n'] not in atom_map:
                del self.atoms[iatom]
            else:
                atom['q'] = q[atom['n']]
                atom['n'] = atom_map[atom['n']]
                atom['id'] = atom_tp_map[atom['id']]

        size = len(self.bonds)
        for ibond in reversed(range(size)):
            bond = self.bonds[ibond]
            if bond['n'] not in bond_map:
                del self.bonds[ibond]
            else:
                bond['n'] = bond_map[bond['n']]
                bond['id'] = bond_tp_map[bond['id']]
                bond['i'] = atom_map[bond['i']]
                bond['j'] = atom_map[bond['j']]

        self.sections['Atoms'] = []
        for atom in self.atoms:
            self.sections['Atoms'].append(atomline(atom))
        self.headers['atoms'] = len(self.atoms)
        self.sections['Masses'] = []
        for att in self.atomtypes:
            self.sections['Masses'].append(massline(att))
        self.headers['atom types'] = len(self.atomtypes)
        self.sections['Bonds'] = []
        for bond in self.bonds:
            self.sections['Bonds'].append(bondline(bond))
        self.headers['bonds'] = len(self.bonds)
        self.sections['Bond Coeffs'] = []
        for bdt in self.bondtypes:
            self.sections['Bond Coeffs'].append(bdtline(bdt))
        self.headers['bond types'] = len(self.bondtypes)

        if 'Velocities' in self.sections:
            self.sections['Velocities'] = []
            for atom in self.atoms:
                self.sections['Velocities'].append(velline(atom))

    def lmpscript(self, drude, outfile, thole = 2.6, cutoff = 12.0):
        """print lines for input script, including pair_style thole"""

        pairfile = "pair-drude.lmp"
        
        dfound = False
        for att in self.atomtypes:
            if att['dflag'] == 'd':
                dfound = True
                break
        if not dfound:
            print("# No polarizable atoms found.")
            return

        print("# Commands to include in the LAMMPS input script\n")

        print("# adapt the pair_style command as needed")
        print("pair_style hybrid/overlay ... coul/long/cs {0:.1f} "\
              "thole {1:.3f} {0:.1f}\n".format(cutoff, thole))

        print("# data file with Drude oscillators added")
        print("read_data {0}\n".format(outfile))

        print("# pair interactions with Drude particles written to file")
        print("# Thole damping recommended if more than 1 Drude per molecule")
        print("include {0}\n".format(pairfile))

        with open(pairfile, "w") as f:
            f.write("# interactions involving Drude particles\n")
            f.write("pair_coeff    * {0:3d}* coul/long/cs\n".format(att['id']))

            f.write("# Thole damping if more than 1 Drude per molecule\n")
            # Thole parameters for I,J pairs
            ifound = False
            for atti in self.atomtypes:
                itype = atti['type'].split()[0]
                for ddt in drude.types:
                    dtype = ddt['type'].split()[0]
                    if dtype == itype:
                        alphai = ddt['alpha']
                        tholei = ddt['thole']
                        ifound = True
                        break
                jfound = False
                for attj in self.atomtypes:
                    if attj['id'] < atti['id']:
                        continue
                    jtype = attj['type'].split()[0]
                    for ddt in drude.types:
                        dtype = ddt['type'].split()[0]
                        if dtype == jtype:
                            alphaj = ddt['alpha']
                            tholej = ddt['thole']
                            jfound = True
                            break
                    if ifound and jfound:
                        alphaij = (alphai * alphaj)**0.5
                        tholeij = (tholei + tholej) / 2.0
                        if tholeij == thole:
                            f.write("pair_coeff {0:4} {1:4} thole "\
                                  "{2:7.3f}\n".format(atti['id'], attj['id'],
                                                      alphaij))
                        else:
                            f.write("pair_coeff {0:4} {1:4} thole {2:7.3f} "\
                                  "{3:7.3f}\n".format(atti['id'],attj['id'],
                                                        alphaij, tholeij))
                    jfound = False
                ifound = False

        print("# atom groups convenient for thermostats (see package "
              "documentation), etc.")
        gatoms = gcores = gdrudes = ""
        for att in self.atomtypes:
            if att['dflag'] != 'd':
                gatoms += " {0}".format(att['id'])
            if att['dflag'] == 'c':
                gcores += " {0}".format(att['id'])
            if att['dflag'] == 'd':
                gdrudes += " {0}".format(att['id'])
        print("group ATOMS type" + gatoms)
        print("group CORES type" + gcores)
        print("group DRUDES type" + gdrudes)
        print("")

        print("# flag for each atom type: [C]ore, [D]rude, [N]on-polarizable")
        drudetypes = ""
        for att in self.atomtypes:
            drudetypes += " {0}".format(att['dflag'].upper())
        print("fix DRUDE all drude" + drudetypes)
        print("")

        print("# ATTENTION!")
        print("#  * read_data may need 'extra/special/per/atom' keyword, "
              "LAMMPS will exit with a message.")
        print("#  * If using fix shake the group-ID must not include "
              "Drude particles.")
        print("#    Use group ATOMS for example.")
        print("#  * Give all I<=J pair interactions, no mixing.")
        print("#  * Pair style coul/long/cs from CORESHELL package is used "\
              "for interactions")
        print("#    of Drude particles. Alternatively pair lj/cut/thole/long "\
              "could be used,")
        print("#    avoiding hybrid/overlay and allowing mixing. See doc "\
              "pages.")


# --------------------------------------

kcal =  4.184                           # kJ
eV   = 96.485                           # kJ/mol
fpe0 =  0.000719756                     # (4 Pi eps0) in e^2/(kJ/mol A)


class Drude(object):
    """specification of drude oscillator types"""

    def __init__(self, drudefile, polar = '', positive = False, metal = False):
        self.types = []
        with open(drudefile, "r") as f:
            for line in f:
                line = line.strip()
                if line.startswith('#') or len(line) == 0:
                    continue
                tok = line.split()
                drude = {}
                drude['type'] = tok[0]
                drude['dm'] = float(tok[1])
                dq = float(tok[2])
                k = float(tok[3])
                drude['alpha'] = alpha = float(tok[4])
                drude['thole'] = float(tok[5])

                if polar == 'q':
                    dq = (fpe0 * k * alpha)**0.5
                elif polar == 'k':
                    k = dq*dq / (fpe0 * alpha)

                if positive:
                    drude['dq'] = abs(dq)
                else:
                    drude['dq'] = -abs(dq)

                if metal:
                    drude['k'] = k / (2.0 * eV)
                else:
                    drude['k'] = k / (2.0 * kcal)

                self.types.append(drude)


# --------------------------------------

def main():
    parser = argparse.ArgumentParser(description = usage,
             formatter_class = argparse.RawTextHelpFormatter)
    parser.add_argument('-f', '--ffdrude', default = 'drude.dff',
                        help = 'Drude parameter file (default: drude.dff)')
    parser.add_argument('-t', '--thole', type = float, default = 2.6,
                        help = 'Thole damping parameter (default: 2.6)')
    parser.add_argument('-c', '--cutoff', type = float, default = 12.0,
                        help = 'distance cutoff/A (default: 12.0)')
    parser.add_argument('-q', '--qcalc', action = 'store_true',
                        help = 'Drude charges calculated from polarisability '\
                        '(default: q value from parameter file)')
    parser.add_argument('-k', '--kcalc', action = 'store_true',
                        help = 'Drude force constants calculated from '\
                        'polarisability (default: k value from parameter file)')
    parser.add_argument('-p', '--positive', action = 'store_true',
                        help = 'Drude particles have positive charge '\
                        '(default: negative charge)')
    parser.add_argument('-m', '--metal', action = 'store_true',
                        help = 'LAMMPS metal units (default: real units)')
    parser.add_argument('-d', '--depolarize', action = 'store_true',
                        help = 'remove Drude dipole polarization from '\
                        'LAMMPS data file')
    parser.add_argument('infile', help = 'input LAMMPS data file')
    parser.add_argument('outfile', help = 'output LAMMPS data file')
    args = parser.parse_args()

    if args.qcalc:
        polar = 'q'
    elif args.kcalc:
        polar = 'p'
    else:
        polar = ''

    data = Data(args.infile)
    drude = Drude(args.ffdrude, polar, args.positive, args.metal)
    if not args.depolarize:
        data.polarize(drude)
        data.lmpscript(drude, args.outfile, args.thole, args.cutoff)
    else:
        data.depolarize(drude)
    data.write(args.outfile)

if __name__ == '__main__':
    main()
