예제 #1
0
 def _get_system_copy(self):
     'Routine to get a copy of the equilibrium system'
     numbers = self.system0.numbers.copy()
     coords = self.system0.pos.copy()
     rvecs = self.system_rvecs.copy()
     masses = self.system0.masses.copy()
     bonds = self.system0.bonds.copy()
     ffatypes = self.system0.ffatypes.copy()
     ffatype_ids = self.system0.ffatype_ids.copy()
     return System(
         numbers, coords, rvecs=rvecs,
         ffatypes=ffatypes, ffatype_ids=ffatype_ids,
         masses=masses, bonds=bonds
     )
예제 #2
0
 def _generate_ffs(self, nguests):
     for iguest in range(len(self._ffs),nguests):
         if len(self._ffs)==0:
             # The very first force field, no guests
             system = System.create_empty()
             system.cell = Cell(self.guest.cell.rvecs)
         elif len(self._ffs)==1:
             # The first real force field, a single guest
             system = self.guest
         else:
             # Take the system of the lastly generated force field (N-1) guests
             # and add an additional guest
             system = self._ffs[-1].system.merge(self.guest)
         self._ffs.append(self.ff_generator(system, self.guest))
예제 #3
0
파일: gcmc.py 프로젝트: mcoolsce/yaff
def simulate():
    T = 298.0*kelvin
    # Input files
    fn_guest = 'CO2.chk'
    fn_host = 'MIL53.chk'
    fn_pars = ['pars.txt']
    host = System.from_file(fn_host).supercell(1,1,1)
    # Description of allowed MC moves and their corresponding probabilities
    mc_moves =  {'insertion':1.0, 'deletion':1.0,
                 'translation':1.0, 'rotation':1.0}
    # Construct equation of state to link pressure, fugacity and chemical potential
    eos = PREOS.from_name('carbondioxide')
    # Loop over pressures to construct isotherm
    pressures = np.array([0.1,0.5,1.0,3.0,5.0,10.0])*bar
    uptake = np.zeros(pressures.shape)
    for iP, P in enumerate(pressures):
        fugacity = eos.calculate_fugacity(T,P)
        mu = eos.calculate_mu(T,P)
        # Screen logger
        screenlog = MCScreenLog(step=10000)
        # HDF5 logger
        fh5 = h5.File('trajectory_%d.h5'%iP,'w')
        hdf5writer = MCHDF5Writer(fh5, step=10000)
        # Setup the GCMC calculation, this generates a lot of output so when
        # force fields are generated, so we silence the logging for a while.
        log.set_level(log.silent)
        gcmc = GCMC.from_files(fn_guest, fn_pars, host=host,
            rcut=12.0*angstrom, tr=None, tailcorrections=True, hooks=[screenlog, hdf5writer],
            reci_ei='ewald_interaction', nguests=30)
        log.set_level(log.medium)
        # Set the external conditions
        gcmc.set_external_conditions(T, fugacity)
        # Run MC simulation
        gcmc.run(1000000, mc_moves=mc_moves)
        uptake[iP] = gcmc.Nmean
        fh5.close()
    np.save('results.npy', np.array([pressures,uptake]).T)
예제 #4
0
def write_raspa_input(guests,
                      parameters,
                      host=None,
                      workdir='.',
                      guestdata=None,
                      hostname='host'):
    """
       Prepare input files that can be used to run RASPA simulations. Only a
       small subset of the full capabilities of RASPA can be explored.

       **Arguments:**

       guests
            A list specifying the guest molecules. Each entry can be one of
            two types: (i) the filename of a system file
            describing one guest molecule, (ii) a System instance of
            one guest molecule

       parameters
            Force-field parameters describing guest-guest and optionally
            host-guest interaction.
            Three types are accepted: (i) the filename of the parameter
            file, which is a text file that adheres to YAFF parameter
            format, (ii) a list of such filenames, or (iii) an instance of
            the Parameters class.

       **Optional arguments:**

       host
            Two types are accepted: (i) the filename of a system file
            describing the host system, (ii) a System instance of the host

       workdir
            The directory where output files will be placed.

       guestdata
            List with the same length as guests. Each entry contains a tuple
            either looking as (name, Tc, Pc, omega) or (name). In the latter
            case, the parameters Tc, Pc, and omega will be loaded from a data
            file based on the name. Otherwise, these will be left blank in the
            input file.
    """
    # Load the guest Systems
    guests = [
        System.from_file(guest) if isinstance(guest, str) else guest
        for guest in guests
    ]
    for guest in guests:
        assert isinstance(guest, System)
    if guestdata is None:
        guestdata = [("guest%03d" % iguest, ) for iguest in range(len(guests))]
    assert len(guests) == len(guestdata)
    # Load the host System
    if host is not None:
        if isinstance(host, str):
            host = System.from_file(host)
        assert isinstance(host, System)
        complex = host
    # Merge all systems
    for guest in guests:
        complex = complex.merge(guest)
    # Generate the ForceField, we don't really care about settings such as
    # cutoffs etc. We only need the parameters in the end
    ff = ForceField.generate(complex, parameters)
    # Write the force-field parameters
    write_raspa_forcefield(ff, workdir)
    # Write masses and charges of all atoms
    ffatypes, ffatype_ids = write_pseudo_atoms(ff, workdir)
    # Write the guest information
    if host == None: counter = 0
    else: counter = host.natom
    for iguest, (guest, data) in enumerate(zip(guests, guestdata)):
        write_guest(guest, data, workdir, [
            ffatypes[iffa]
            for iffa in ffatype_ids[counter:counter + guest.natom]
        ])
        counter += guest.natom
    # Write the host coordinates to a cif file
    if host is not None:
        dump_cif(
            host,
            os.path.join(workdir, '%s.cif' % hostname),
            ffatypes=[ffatypes[iffa] for iffa in ffatype_ids[:host.natom]])
    # A fairly standard input file for GCMC simulations
    dump_input(workdir, hostname, [data[0] for data in guestdata])
예제 #5
0
    def from_files(cls, guest, parameters, **kwargs):
        """Automated setup of GCMC simulation

           **Arguments:**

           guest
                Two types are accepted: (i) the filename of a system file
                describing one guest molecule, (ii) a System instance of
                one guest molecule

           parameters
                Force-field parameters describing guest-guest and optionally
                host-guest interaction.
                Three types are accepted: (i) the filename of the parameter
                file, which is a text file that adheres to YAFF parameter
                format, (ii) a list of such filenames, or (iii) an instance of
                the Parameters class.

           **Optional arguments:**

           hooks
                A list of MCHooks

           host
                Two types are accepted: (i) the filename of a system file
                describing the host system, (ii) a System instance of the host

           All other keyword arguments are passed to the ForceField constructor
           See the constructor of the :class:`yaff.pes.generator.FFArgs` class
           for the available optional arguments.

        """
        # Load the guest System
        if isinstance(guest, str):
            guest = System.from_file(guest)
        assert isinstance(guest, System)
        # We want to control nlow and nhigh here ourselves, so remove it from the
        # optional arguments if the user provided it.
        kwargs.pop('nlow', None)
        kwargs.pop('nhigh', None)
        # Rough guess for number of adsorbed guests
        nguests = kwargs.pop('nguests', 10)
        # Load the host if it is present as a keyword
        host = kwargs.pop('host', None)
        # Extract the hooks
        hooks = kwargs.pop('hooks', [])
        # Efficient treatment of reciprocal ewald contribution
        if not 'reci_ei' in kwargs.keys():
            kwargs['reci_ei'] = 'ewald_interaction'
        if host is not None:
            if isinstance(host, str):
                host = System.from_file(host)
            assert isinstance(host, System)
            # If the guest molecule is currently an isolated molecule, than put
            # it in the same periodic box as the host
            if guest.cell is None or guest.cell.nvec==0:
                guest.cell = Cell(host.cell.rvecs)
            # Construct a complex of host and one guest and the corresponding
            # force field excluding host-host interactions
            hostguest = host.merge(guest)
            external_potential = ForceField.generate(hostguest, parameters,
                 nlow=host.natom, nhigh=host.natom, **kwargs)
        else:
            external_potential = None
#        # Compare the energy of the guest, once isolated, once in a periodic box
#        guest_isolated = guest.subsystem(np.arange(guest.natom))
#        guest_isolated.cell = Cell(np.zeros((0,3)))
#        optional_arguments = {}
#        for key in kwargs.keys():
#            if key=='reci_ei': continue
#            optional_arguments[key] = kwargs[key]
#        ff_guest_isolated = ForceField.generate(guest_isolated, parameters, **optional_arguments)
#        e_isolated = ff_guest_isolated.compute()
#        guest_periodic = guest.subsystem(np.arange(guest.natom))
#        ff_guest_periodic = ForceField.generate(guest_periodic, parameters, **optional_arguments)
#        e_periodic = ff_guest_periodic.compute()
#        if np.abs(e_isolated-e_periodic)>1e-4:
#            if log.do_warning:
#                log.warn("An interaction energy of %s of the guest with its periodic "
#                         "images was detected. The interaction of a guest with its periodic "
#                         "images will however NOT be taken into account in this simulation. "
#                         "If the energy difference is large compared to k_bT, you should "
#                         "consider using a supercell." % (log.energy(e_isolated-e_periodic)))
        # By making use of nlow=nhigh, we automatically discard intramolecular energies
        eguest = 0.0
        # Generator of guest-guest force fields, excluding interactions
        # between the first N-1 guests
        def ff_generator(system, guest):
            return ForceField.generate(system, parameters, nlow=max(0,system.natom-guest.natom), nhigh=max(0,system.natom-guest.natom), **kwargs)
        return cls(guest, ff_generator, external_potential=external_potential,
             eguest=eguest, hooks=hooks, nguests=nguests)