コード例 #1
0
def energy(s, all=False, np=None, **kwargs):
    """pysimm.lmps.energy

    Convenience function to calculate energy of a given :class:`~pysimm.system.System` object.

    Args:
        s: system to calculate energy
        all: returns decomposition of energy if True (default: False)
        np: number of threads to use for simulation

    Returns:
        total energy or disctionary of energy components
    """
    sim = Simulation(s, log='pysimm_calc.tmp.log', **kwargs)
    sim.add(
        OutputSettings(
            thermo={
                'freq':
                1,
                'style':
                'custom step etotal epair emol evdwl ecoul ebond eangle edihed eimp'
            }))
    sim.add_md(length=0, **kwargs)
    sim.run(np)
    log = LogFile('pysimm_calc.tmp.log')
    try:
        os.remove('pysimm_calc.tmp.log')
    except:
        error_print('error likely occurred during simulation')
    if all:
        return log.data.loc[0]
    else:
        return log.data.loc[0].TotEng
コード例 #2
0
    def add_qeq(self, template=None, **kwargs):
        """pysimm.lmps.Simulation.add_qeq

        Add :class:`~pysimm.lmps.Qeq` template to simulation

        Args:
            template: :class:`~pysimm.lmps.Qeq` object reference
            **kwargs: if template is None these are passed to :class:`~pysimm.lmps.Qeq` constructor to create new template
        """
        if template is None:
            self.sim.append(Qeq(**kwargs))
        elif isinstance(template, Qeq):
            self.sim.append(template)
        else:
            error_print('you must add an object of type Qeq to Simulation')
コード例 #3
0
ファイル: lmps.py プロジェクト: georgeathust/pysimm
    def add_min(self, template=None, **kwargs):
        """pysimm.lmps.Simulation.add_min

        Add :class:`~pysimm.lmps.Minimization` template to simulation

        Args:
            template: :class:`~pysimm.lmps.Minimization` object reference
            **kwargs: if template is None these are passed to :class:`~pysimm.lmps.Minimization` constructor to create new template
        """
        if template is None:
            self.sim.append(Minimization(**kwargs))
        elif isinstance(template, Minimization):
            self.sim.append(template)
        else:
            error_print('you must add an object of type Minimization to Simulation')
コード例 #4
0
ファイル: lmps.py プロジェクト: georgeathust/pysimm
    def add_md(self, template=None, **kwargs):
        """pysimm.lmps.Simulation.add_md

        Add :class:`~pysimm.lmps.MolecularDyanmics` template to simulation

        Args:
            template: :class:`~pysimm.lmps.MolecularDynamics` object reference
            **kwargs: if template is None these are passed to :class:`~pysimm.lmps.MolecularDynamics` constructor to create new template
        """
        if template is None:
            self.sim.append(MolecularDynamics(**kwargs))
        elif isinstance(template, MolecularDynamics):
            self.sim.append(template)
        else:
            error_print('you must add an object of type MolecularDynamics to Simulation')
コード例 #5
0
def redo_monomer_insertion(s, m, i):
    """pysimm.apps.random_walk.redo_monomer_insertion
    This function is called by random_walk_tacticity if the latest capped monomer insertion resulted in hardcore overlaps.
    1) The hardcore overlap is resolved by shrinking the last monomer by a factor of 0.8, iteratively, until there are no more hardcore overlaps.
    2) Then the shrunken last monomer is frozen while the rest of the polymer chain is optimized, and the last monomer is scaled in size by 1.05
    3) Cycles of contrainedOptimization and regrowth are alternated until a reasonable structure is obtained

    Args:
        s_: :class:`~pysimm.system.System` is a polymer chain in which the last monomer insertion has generated a hardcore overlap
        m: reference monomer :class:`~pysimm.system.System`. Must be a capped monomer, with headCap and tail_cap as the first and last atoms in the .mol file.
        i: number of the offending monomer, used for labelling diagnostic .xyz output files
    Returns:
        nothing; all changes to the polymer chain are written to the argument s_
    """
    for p in s.particles[-1 * m.particles.count:]:
        if p.linker == 'tail':
            tail = p
    scale_min = 0.1
    s.unwrap()
    s.set_box(padding=10)
    s.wrap()
    # shrink last monomer
    for p in s.particles[-1 * m.particles.count:]:
        p.x, p.y, p.z = scale_monomer(p, tail, scale_min)
        # now, reexpand the monomer and relax polymer, step-wise
    scale = 1
    while scale_min * scale * 1.05 < 0.91:
        print("Scaling up from %s to %s" %
              (str(scale_min * scale), str(scale * scale_min * 1.05)))
        scale = scale * 1.05
        for p in s.particles[-1 * m.particles.count:]:
            p.x, p.y, p.z = scale_monomer(p, tail, 1.05)
        # simulation with fixed latest monomer
        constrained_opt(
            s, m, "nearby")  # system-wide constrained optimization is too slow
        s.unwrap()
        s.write_xyz('bad_insertion_' + str(i) + '.xyz', append=True)
        s.wrap()
    if s.quality(tolerance=0.2) > 0:
        error_print("system is broken upon monomer reexpansion")
    # now relax the last monomer
    constrained_opt(s, m, "monomer")
コード例 #6
0
def get_forcefield_types(s, types='gaff', f=None):
    """pysimm.amber.get_forcefield_types

    Uses antechamber to determine atom types. Defaults to GAFF atom types. Retrieves :class:`~pysimm.system.ParticleType` objects from force field is provided 

    Args:
        s: :class:`~pysimm.system.System` for which to type
        types: name of atom types to use (default: gaff)
        f: forcefield object to retrieve :class:`~pysimm.system.ParticleType` objects from if not present in s (default: None)

    Returns:
        None
    """
    s.write_pdb('pysimm.tmp.pdb')
    cl = '{} -fi pdb -i pysimm.tmp.pdb -fo ac -o pysimm.tmp.ac -at {}'.format(
        ANTECHAMBER_EXEC, types)
    p = Popen(cl.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
    p.communicate()
    with file('pysimm.tmp.ac') as fr:
        fr.next()
        fr.next()
        line = fr.next()
        while line.split()[0] == 'ATOM':
            tag = int(line.split()[1])
            type_name = line.split()[-1]
            if s.particle_types.get(type_name):
                s.particles[tag].type = s.particle_types.get(type_name)[0]
            elif f:
                pt = f.particle_types.get(type_name)
                if pt:
                    s.particles[tag].type = s.particle_types.add(pt[0].copy())

            else:
                error_print(
                    'cannot find type {} in system or forcefield'.format(
                        type_name))
            line = fr.next()
コード例 #7
0
ファイル: random_walk.py プロジェクト: polysimtools/pysimm
def copolymer(m, nmon, s_=None, **kwargs):
    """pysimm.apps.random_walk.copolymer

    Builds copolymer using random walk methodology using pattern

    Args:
        m: list of reference monomer :class:`~pysimm.system.System`s
        nmon: total number of monomers to add to chain
        s_: :class:`~pysimm.system.System` in which to build polymer chain (None)
        settings: dictionary of simulation settings
        density: density at which to build polymer (0.3)
        forcefield: :class:`~pysimm.forcefield.Forcefield` object to acquire new force field parameters
        capped: True/False if monomers are capped
        unwrap: True to unwrap final system
        traj: True to build xyz trajectory of polymer growth (True)
        pattern: list of pattern for monomer repeat units, should match length of m ([1 for _ in range(len(m))])
        limit: during MD, limit atomic displacement by this max value (LAMMPS ONLY)
        sim: :class:`~pysimm.lmps.Simulation` object for relaxation between polymer growth
    Returns:
        new copolymer :class:`~pysimm.system.System`
    """
    m = [x.copy() for x in m]

    settings = kwargs.get('settings', {})
    density = kwargs.get('density', 0.3)
    f = kwargs.get('forcefield')
    capped = kwargs.get('capped')
    unwrap = kwargs.get('unwrap')
    traj = kwargs.get('traj', True)
    pattern = kwargs.get('pattern', [1 for _ in range(len(m))])
    limit = kwargs.get('limit', 0.1)
    sim = kwargs.get('sim')

    for m_ in m:
        m_.add_particle_bonding()
        for p in m_.particles:
            if p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('H'):
                p.linker = 'head'
            elif p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('T'):
                p.linker = 'tail'
        m_.remove_linker_types()

    if s_ is None:
        s = system.replicate(m[0], 1, density=density/nmon)
    else:
        s = system.replicate(m[0], 1, s_=s_, density=density/nmon)
    print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), 1, nmon))

    for p in s.particles:
        if p.linker == 'head':
            last_head = p

        elif p.linker == 'tail':
            last_tail = p

    for m_ in m:
        if capped:
            m_.particles.remove(1)
            m_.remove_spare_bonding()
            m_.add_particle_bonding()

    s.add_particle_bonding()
    
    if traj:
        s.write_xyz('random_walk.xyz')

    temp_nmon = 1

    while True:

        m_ = m.pop(0)
        m.append(m_)
        p_ = pattern.pop(0)
        pattern.append(p_)

        if temp_nmon == 1 and p_ == 1:
            m_ = m.pop(0)
            m.append(m_)
            p_ = pattern.pop(0)
            pattern.append(p_)
        elif temp_nmon == 1:
            p_ -= 1

        for insert in range(p_):

            head = None
            tail = None

            backbone_vector = np.array([last_head.x - last_tail.x,
                                        last_head.y - last_tail.y,
                                        last_head.z - last_tail.z])

            ref_head = None
            ref_tail = None
            for p in m_.particles:
                if p.linker == 'head':
                    ref_head = p
                elif p.linker == 'tail':
                    ref_tail = p
            if ref_head and ref_tail:
                ref_backbone_vector = np.array([ref_head.x - ref_tail.x,
                                                ref_head.y - ref_tail.y,
                                                ref_head.z - ref_tail.z])
                rot_matrix = calc.find_rotation(ref_backbone_vector, backbone_vector)
                m_.rotate(around=ref_tail, rot_matrix=rot_matrix)
                translation_vector = [last_tail.x - ref_tail.x,
                                      last_tail.y - ref_tail.y,
                                      last_tail.z - ref_tail.z]
                for p in m_.particles:
                    p.x = p.x + translation_vector[0] + 3*backbone_vector[0]
                    p.y = p.y + translation_vector[1] + 3*backbone_vector[1]
                    p.z = p.z + translation_vector[2] + 3*backbone_vector[2]
            else:
                print('reference molecule has no head or tail')

            n = m_.copy()

            if capped:
                s.particles.remove(s.particles.count)
                s.remove_spare_bonding()
                s.add_particle_bonding()

            s.add(n, change_dim=False)

            s.add_particle_bonding()

            head = last_head
            for p in s.particles[-1*n.particles.count:]:
                if p.linker == 'tail':
                    tail = p

            s.make_new_bonds(head, tail, f)
            temp_nmon += 1
            print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), temp_nmon, nmon))

            if unwrap:
                s.unwrap()
                
            if sim is None:
                sim = lmps.Simulation(s, name='relax_%03d' % (temp_nmon), log='relax.log', **settings)
                sim.add_md(ensemble='nve', limit=limit, **settings)
                sim.add_min(**settings)
            if isinstance(sim, lmps.Simulation):
                sim.system = s
                sim.name = 'relax_%03d' % (temp_nmon)
                sim.run(np=settings.get('np'))

            if unwrap:
                s.unwrap()

            if unwrap:
                s.wrap()

            for p in s.particles[-1*n.particles.count:]:
                if p.linker == 'head':
                    last_head = p
                elif p.linker == 'tail':
                    last_tail = p

        if temp_nmon >= nmon:
            break
        
        if unwrap:
            if not s.unwrap():
                error_print('something went wrong')
                return s
    
        if traj:
            s.write_xyz('random_walk.xyz', append=True)
    
        if unwrap:
            s.wrap()
            
    for p in s.particles:
        if p not in s.molecules[p.molecule.tag].particles:
            s.molecules[p.molecule.tag].particles.add(p)

    s.write_lammps('polymer.lmps')
    s.unwrap()
    s.write_xyz('polymer.xyz')

    return s
コード例 #8
0
def random_walk(m, nmon, s_=None, **kwargs):
    """pysimm.apps.random_walk.random_walk

    Builds homopolymer using random walk methodology

    Args:
        m: reference monomer system
        nmon: total number of monomers to add to chain
        s_: system in which to build polymer chain (None)
        extra_bonds: EXPERMINTAL, True if making ladder backbone polymer
        settings: dictionary of simulation settings
        density: density at which to build polymer (0.3)
        forcefield: pysimm.forcefield.Forcefield object to acquire new force field parameters
        capped: True/False if monomers are capped
        unwrap: True to unwrap final system
        traj: True to build xyz trajectory of polymer growth (True)
        limit: during MD, limit atomic displacement by this max value (LAMMPS ONLY)
        sim: pysimm.lmps.Simulation object for relaxation between polymer growth
    Returns:
        new polymer pysimm.system.System
    """
    m = m.copy()

    extra_bonds = kwargs.get('extra_bonds') if kwargs.get('extra_bonds') is not None else False

    settings = kwargs.get('settings') if kwargs.get('settings') is not None else {}
    density = kwargs.get('density') or 0.3
    f = kwargs.get('forcefield')
    capped = kwargs.get('capped')
    unwrap = kwargs.get('unwrap')
    traj = kwargs.get('traj') if kwargs.get('traj') is not None else True
    limit = kwargs.get('limit') if kwargs.get('limit') is not None else 0.1
    sim = kwargs.get('sim')

    m.add_particle_bonding()

    for p in m.particles:
        if p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('H'):
            p.linker = 'head'
        elif p.type.name.find('@') >= 0 and p.type.name.split('@')[0].find('T'):
            p.linker = 'tail'

    m.remove_linker_types()

    if s_ is None:
        s = system.replicate(m, 1, density=density/nmon)
    else:
        s = system.replicate(m, 1, s_=s_, density=None)
    print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), 1, nmon))

    if traj:
        s.write_xyz('random_walk.xyz')

    if capped:
        m.particles.remove(1)
        m.remove_spare_bonding()
        m.add_particle_bonding()

    for insertion in range(nmon - 1):

        head = None
        tail = None

        backbone_vector = np.array(find_last_backbone_vector(s, m))

        for p, p_ in izip(s.particles[-1*m.particles.count:], m.particles):
                p_.x = p.x + 3*backbone_vector[0]
                p_.y = p.y + 3*backbone_vector[1]
                p_.z = p.z + 3*backbone_vector[2]

        n = m.copy()

        if capped:
            s.particles.remove(s.particles.count)
            s.remove_spare_bonding()
            s.add_particle_bonding()

        if extra_bonds:
            heads = []
            for p in s.particles[-1*n.particles.count:]:
                if p.linker == 'head':
                    heads.append(p)
        else:
            for p in s.particles[-1*n.particles.count:]:
                if p.linker == 'head':
                    head = p

        s.add(n, change_dim=False)

        s.add_particle_bonding()

        if extra_bonds:
            tails = []
            for p in s.particles[-1*n.particles.count:]:
                if p.linker == 'tail':
                    tails.append(p)
        else:
            for p in s.particles[-1*n.particles.count:]:
                if p.linker == 'tail':
                    tail = p

        for p in s.particles:
            if not p.bonded_to:
                print(p.tag)

        if head and tail:
            add_bonds(s, head, tail, f)
            print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion+2, nmon))
        elif extra_bonds and len(heads) == len(tails):
            for h, t in izip(heads, tails):
                add_bonds(s, h, t, f)
            print('%s: %s/%s monomers added' % (strftime('%H:%M:%S'), insertion+2, nmon))
        else:
            print('cannot find head and tail')

        if sim is None:
            sim = lmps.Simulation(s, name='relax_%03d' % (insertion+2), log='relax.log', **settings)
            sim.add_md(ensemble='nve', limit=limit, **settings)
            sim.add_min(**settings)
        if isinstance(sim, lmps.Simulation):
            sim.system = s
            sim.name = 'relax_%03d' % (insertion+2)
            sim.run(np=settings.get('np'))

        if unwrap:
            if not s.unwrap():
                error_print('something went wrong')
                return s

        if traj:
            s.write_xyz('random_walk.xyz', append=True)

        if unwrap:
            s.wrap()

    s.write_lammps('polymer.lmps')
    s.unwrap()
    s.write_xyz('polymer.xyz')

    return s
コード例 #9
0
def tacticity(s, a_tag=None, b_tag=None, c_tag=None, d_tag=None, offset=None, return_angles=True, unwrap=True,
              rewrap=True, skip_first=False):
    """pysimm.calc.tacticity

    Determines tacticity for polymer chain. Iterates through groups of four patricles given by X_tags, using offset. This assumes equivalent atoms in each group of four are perfectly offset.

    Args:
        s: :class:`~pysimm.system.System`
        a_tag: tag of first a particle
        b_tag: tag of first b particle
        c_tag: tag of first c particle
        d_tag: tag of first d particle
        offset: offset of particle tags (monomer repeat atomic count)
        return_angles: if True return chiral angles of all monomers
        unwrap: True to perform unwrap before calculation (REQUIRED before calculation, but not required in this
        function)
        rewrap: True to rewrap system after calculation
        skip_first: True to skip first monomer (sometime chirality is poorly defined for thsi monomer)
    Returns:
        tacticity or tacticity, [chiral_angles]
    """
    if not np:
        raise PysimmError('pysimm.calc.tacticity function requires numpy')
    if a_tag is None or b_tag is None or c_tag is None or d_tag is None:
        error_print('particle tags for chiral center are required')
        error_print('a: chiral center, b-d: 3 side groups')

    if offset is None:
        error_print('offset for tags in each monomer is required, i.e. - number of particles in each monomer')

    if unwrap:
        s.unwrap()

    a_ = [s.particles[i] for i in range(a_tag, s.particles.count, offset)]
    b_ = [s.particles[i] for i in range(b_tag, s.particles.count, offset)]
    c_ = [s.particles[i] for i in range(c_tag, s.particles.count, offset)]
    d_ = [s.particles[i] for i in range(d_tag, s.particles.count, offset)]

    stereochem_angles = []

    if skip_first:
        for a, b, c, d in izip(a_[1:], b_[1:], c_[1:], d_[1:]):
            stereochem_angles.append(chiral_angle(a, b, c, d))
    else:
        for a, b, c, d in izip(a_, b_, c_, d_):
            stereochem_angles.append(chiral_angle(a, b, c, d))

    last = None
    iso_diads = 0
    syn_diads = 0
    for a in stereochem_angles:
        if last is not None:
            if (a < 90 and last < 90) or (a > 90 and last > 90):
                iso_diads += 1
            else:
                syn_diads += 1
        last = a

    if iso_diads == (len(stereochem_angles) - 1):
        t = 'isotactic'
    elif syn_diads == (len(stereochem_angles) - 1):
        t = 'syndiotactic'
    else:
        t = 'atactic'

    if rewrap:
        s.wrap()

    print('{:.1f}% syn diads'.format(100*float(syn_diads)/(syn_diads+iso_diads)))
    print('{:.1f}% iso diads'.format(100*float(iso_diads)/(syn_diads+iso_diads)))
    if return_angles:
        return t, stereochem_angles
    else:
        return t
コード例 #10
0
def set_charges(s, maxiter=100, tol=1e-6):
    global gasteiger_parameters

    for p in s.particles:

        if (p.type and p.type.name and p.type.name.find('@') > 0 and
                s.particle_types.get(p.type.name.split('@')[-1])):
            p.nbonds = len(p.bonds) + 1
            if p.type.name[0] == 'H':
                p.linker = 'head'
            elif p.type.name[0] == 'T':
                p.linker = 'tail'
            else:
                p.linker = True
            type_ = s.particle_types.get(p.type.name.split('@')[-1])
            if type_:
                p.type = type_[0]
            else:
                error_print('found linker type %s but did not find regular '
                            'type %s' % (p.type.name,
                                         p.type.name.split('@')[-1]))
                return
        else:
            p.nbonds = len(p.bonds)

        gast_type = gasteiger_parameters.get(p.type.name)
        if gast_type:
            gast_type = gast_type[0]
            p.gast_conv = False
            p.qn = 0.0
            p.charge = 0.0
            p.gast_a = gast_type.a
            p.chi = p.gast_a
            p.gast_b = gast_type.b
            p.gast_c = gast_type.c
            continue
        else:
            if not p.type.elem and p.type.mass:
                elem = element_names_by_mass.get(int(round(p.type.mass)))
                if elem:
                    p.type.elem = elem
            if not p.type.elem or p.type.elem not in ['H', 'N', 'C', 'O',
                                                      'F', 'Cl', 'Br', 'I',
                                                      'S']:
                error_print('cannot find gastieger paramater for particle %s'
                            % p.tag)
            else:
                if p.type.elem == 'H':
                    gast_type = gasteiger_parameters.get('h')[0]
                elif p.type.elem == 'C':
                    if p.nbonds == 4:
                        gast_type = gasteiger_parameters.get('c_sp3')[0]
                    elif p.nbonds == 3:
                        gast_type = gasteiger_parameters.get('c_sp2')[0]
                    elif p.nbonds == 2:
                        gast_type = gasteiger_parameters.get('c_sp1')[0]
                elif p.type.elem == 'N':
                    if p.nbonds >= 3:
                        gast_type = gasteiger_parameters.get('n_sp3')[0]
                    elif p.nbonds == 2:
                        gast_type = gasteiger_parameters.get('c_sp2')[0]
                    elif p.nbonds == 1:
                        gast_type = gasteiger_parameters.get('c_sp1')[0]
                elif p.type.elem == 'O':
                    if p.nbonds == 2:
                        gast_type = gasteiger_parameters.get('o_sp3')[0]
                    elif p.nbonds == 1:
                        gast_type = gasteiger_parameters.get('o_sp2')[0]
                elif p.type.elem == 'F':
                    gast_type = gasteiger_parameters.get('f')[0]
                elif p.type.elem == 'Cl':
                    gast_type = gasteiger_parameters.get('cl')[0]
                elif p.type.elem == 'Br':
                    gast_type = gasteiger_parameters.get('br')[0]
                elif p.type.elem == 'I':
                    gast_type = gasteiger_parameters.get('i')[0]
                elif p.type.elem == 'S':
                    gast_type = gasteiger_parameters.get('s')[0]

                gast_type = gast_type
                p.gast_conv = False
                p.qn = 0.0
                p.charge = 0.0
                p.gast_a = gast_type.a
                p.chi = p.gast_a
                p.gast_b = gast_type.b
                p.gast_c = gast_type.c
                continue

    for n in range(1, maxiter+1):
        for b in s.bonds:
            if b.b.chi > b.a.chi:
                b.b.qn += ((b.a.chi - b.b.chi) /
                           (b.a.gast_a + b.a.gast_b + b.a.gast_c))
                b.a.qn += ((b.b.chi - b.a.chi) /
                           (b.a.gast_a + b.a.gast_b + b.a.gast_c))
            else:
                b.b.qn += ((b.a.chi - b.b.chi) /
                           (b.b.gast_a + b.b.gast_b + b.b.gast_c))
                b.a.qn += ((b.b.chi - b.a.chi) /
                           (b.b.gast_a + b.b.gast_b + b.b.gast_c))

        convergence = True
        for p in s.particles:
            p.qn *= pow(0.5, n)
            p.charge += p.qn
            p.chi = p.gast_a + p.gast_b*p.charge + p.gast_c*p.charge*p.charge
            if abs(p.qn) < tol:
                p.gast_conv = True
            else:
                convergence = False
            p.qn = 0.0

        if convergence:
            print('charges converged after %s iterations' % n)
            break

    if not convergence:
        print('charges not converged after %s iterations' % n)
コード例 #11
0
def write_init(l, **kwargs):
    """pysimm.lmps.write_init

    Create initialization LAMMPS input based on pysimm.system.System data

    Args:
        l: pysimm.system.System object reference
        kwargs:
            atom_style: LAMMPS atom_style default=full
            kspace_style: LAMMPS kspace style default='pppm 1e-4'
            units: LAMMPS set of units to use default=real
            special_bonds: LAMMPS special bonds input
            nonbond_mixing: type of mixing rule for nonbonded interactions default=arithmetic
            nb_cut: cutoff for nonbonded interactions default=12
    """
    atom_style = kwargs.get('atom_style') or 'full'
    kspace_style = kwargs.get('kspace_style') or 'pppm 1e-4'
    units = kwargs.get('units') or 'real'
    nb_cut = kwargs.get('nb_cut') or 12.0
    special_bonds = kwargs.get('special_bonds')
    nonbond_mixing = kwargs.get('nonbond_mixing') or 'arithmetic'

    output = ''

    if type(l) == str and os.path.isfile(l):
        l = read_lammps(l, quiet=True)
    elif type(l) == str:
        return 'init_system failed to read %s' % l
    output += 'units %s\n' % units
    output += 'atom_style %s\n' % atom_style
    pair_style = None
    charge = False

    if l.charge is None:
        for p in l.particles:
            if p.charge != 0:
                charge = True
                break
    else:
        if l.charge != 0:
            charge = True

    if not l.pair_style:
        if l.particle_types[1].sigma and l.particle_types[1].epsilon:
            if charge:
                if l.ff_class == '2':
                    pair_style = 'lj/class2/coul/long'
                else:
                    pair_style = 'lj/cut/coul/long'
            else:
                if l.ff_class == '2':
                    pair_style = 'lj/class2'
                else:
                    pair_style = 'lj/cut'

        elif (l.particle_types[1].a and l.particle_types[1].rho and
                l.particle_types[1].c):
            if charge:
                pair_style = 'buck/coul/long'
            else:
                pair_style = 'buck'
    else:
        if l.pair_style.startswith('lj') or l.pair_style.startswith('class2'):
            if charge:
                if l.ff_class == '2':
                    pair_style = 'lj/class2/coul/long'
                else:
                    pair_style = 'lj/cut/coul/long'
            else:
                if l.ff_class == '2':
                    pair_style = 'lj/class2'
                else:
                    pair_style = 'lj/cut'
        elif l.pair_style.startswith('buck'):
            if charge:
                pair_style = 'buck/coul/long'
            else:
                pair_style = 'buck'

    if pair_style:
        output += 'pair_style %s %s\n' % (pair_style, nb_cut)
    else:
        error_print('pair style probably not supported')

    if charge:
        output += 'kspace_style %s\n' % kspace_style

    if not pair_style.startswith('buck'):
        if nonbond_mixing == 'arithmetic':
            output += 'pair_modify shift yes mix arithmetic\n'
        elif nonbond_mixing == 'geometric':
            output += 'pair_modify shift yes mix geometric\n'
        else:
            output += 'pair_modify shift yes mix arithmetic\n'
            print('%s mixing rule not supported; defaulting to arithmetic'
                  % nonbond_mixing)

    if l.bond_style:
        output += 'bond_style %s\n' % l.bond_style
    else:
        if l.ff_class == '1':
            output += 'bond_style harmonic\n'
        elif l.ff_class == '2':
            output += 'bond_style class2\n'

    if l.angles.count > 0:
        if l.angle_style:
            output += 'angle_style %s\n' % l.angle_style
        else:
            if l.ff_class == '1':
                output += 'angle_style harmonic\n'
            elif l.ff_class == '2':
                output += 'angle_style class2\n'

    if l.dihedrals.count > 0:
        if l.dihedral_style:
            output += 'dihedral_style %s\n' % l.dihedral_style
        else:
            if l.ff_class == '1':
                output += 'dihedral_style harmonic\n'
            elif l.ff_class == '2':
                output += 'dihedral_style class2\n'

    if l.impropers.count > 0:
        if l.improper_style:
            output += 'improper_style %s\n' % l.improper_style
        else:
            if l.ff_class == '1':
                output += 'improper_style harmonic\n'
            elif l.ff_class == '2':
                output += 'improper_style class2\n'

    if special_bonds:
        output += 'special_bonds %s\n' % special_bonds
    else:
        output += 'special_bonds amber\n'

    l.write_lammps('temp.lmps')
    output += 'read_data temp.lmps\n'

    if pair_style.startswith('buck'):
        for pt1 in l.particle_types:
            for pt2 in l.particle_types:
                if pt1.tag <= pt2.tag:
                    a = pow(pt1.a*pt2.a, 0.5)
                    c = pow(pt1.c*pt2.c, 0.5)
                    rho = 0.5*(pt1.rho+pt2.rho)
                    output += 'pair_coeff %s %s %s %s %s\n' % (pt1.tag, pt2.tag, a, rho, c)

    return output