Exemplo n.º 1
0
    def calc(self,
             at,
             energy=None,
             force=None,
             virial=None,
             local_energy=None,
             local_virial=None,
             args_str=None,
             error=None,
             **kwargs):

        clusters = []
        orig_label = self.label
        if not self.mm_local:
            # always submit the MM calc
            if self.test_mode:
                clusters.append(at)
            else:
                self.server.put(at,
                                0,
                                self.label,
                                force_restart=self.force_restart)
            self.label += 1

        do_qm = not self.get('method').startswith('lotf') or self.get(
            'lotf_do_qm')

        if do_qm:
            #print 'REGIONS', [ k for k in at.properties.keys() if re.match('hybrid_[0-9]+', k) ]
            n_region = len([
                k for k in at.properties.keys()
                if re.match('hybrid_[0-9]+', k)
            ])

            if self.get('calc_weights'):
                system_timer('create_hybrid_weights')
                # overall hybrid property is union of all the hybrids
                if not hasattr(at, 'hybrid'):
                    at.add_property('hybrid', 0)
                at.hybrid[:] = 0
                for i in frange(n_region):
                    hybrid = getattr(at, 'hybrid_%d' % i)
                    at.hybrid[hybrid ==
                              HYBRID_ACTIVE_MARK] = HYBRID_ACTIVE_MARK
                if not hasattr(at, 'hybrid_mark'):
                    at.add_property('hybrid_mark', at.hybrid)
                at.hybrid_mark[:] = 0
                at.hybrid_mark = at.hybrid
                create_hybrid_weights_args = self.cluster_args.copy()
                create_hybrid_weights_args['buffer_hops'] = 0
                create_hybrid_weights_args[
                    'transition_hops'] = 0  # ensure a fast exit
                # overall hybrid -> hybrid_mark, weight_region1
                create_hybrid_weights(
                    at,
                    args_str=quippy.util.args_str(create_hybrid_weights_args))
                system_timer('create_hybrid_weights')

            # make clusters and submit to QM clients
            system_timer('make_clusters')
            for i in frange(n_region):
                hybrid_name = 'hybrid_%d' % i
                hybrid_mark_name = 'hybrid_mark_%d' % i
                if self.get('calc_weights'):
                    hybrid = getattr(at, hybrid_name)
                    if not hasattr(at, hybrid_mark_name):
                        at.add_property(hybrid_mark_name, HYBRID_NO_MARK)
                    hybrid_mark = getattr(at, hybrid_mark_name)

                    # set marks to allow previously active atoms to become buffer atoms
                    # create_hybrid_weights will then set the buffer marks
                    hybrid_mark[hybrid_mark ==
                                HYBRID_ACTIVE_MARK] = HYBRID_BUFFER_MARK
                    hybrid_mark[hybrid ==
                                HYBRID_ACTIVE_MARK] = HYBRID_ACTIVE_MARK

                    print('region %d, sum(hybrid) %d, sum(hybrid_mark) %d' %
                          (i, sum(hybrid), sum(hybrid_mark)))

                    create_hybrid_weights_args = self.cluster_args.copy()
                    create_hybrid_weights_args['run_suffix'] = '_%d' % i
                    create_hybrid_weights_args_str = quippy.util.args_str(
                        create_hybrid_weights_args)
                    print 'calling create_hybrid_weights with args_str %s' % create_hybrid_weights_args_str
                    create_hybrid_weights(
                        at, args_str=create_hybrid_weights_args_str)

                cluster_args_str = quippy.util.args_str(self.cluster_args)
                print 'calling create_cluster_simple with args_str %s' % cluster_args_str
                c = create_cluster_simple(at,
                                          mark_name=hybrid_mark_name,
                                          args_str=cluster_args_str)

                client_id = i
                if self.mm_local:
                    client_id -= 1
                if self.save_clusters:
                    c.write(
                        os.path.join(
                            self.rundir, 'cluster.client-%03d.label-%04d.xyz' %
                            (client_id, self.label)))
                if self.test_mode:
                    clusters.append(c)
                else:
                    self.server.put(c,
                                    client_id,
                                    self.label,
                                    force_restart=self.force_restart)
                self.label += 1
            system_timer('make_clusters')

        # wait for results to be ready
        system_timer('get_results')
        if self.test_mode:
            results = []
            for i, cluster in enumerate(clusters):
                result = cluster.copy()
                result.set_cutoff(self.qm_pot.cutoff())
                result.calc_connect()
                self.qm_pot.calc(result, force=True)
                result.params['label'] = orig_label + i
                results.append(result)
        else:
            results = self.server.get_results()
        system_timer('get_results')

        system_timer('process_results')
        if self.mm_local:
            qm_results = results
        else:
            # process MM results
            mm_results, qm_results = results[:1], results[1:]
            mm_result = mm_results[0]
            at.add_property('mm_force', mm_result.force, overwrite=True)

        if do_qm:
            # process QM results
            at.add_property('qm_force', 0., n_cols=3, overwrite=True)

            # extract forces from each cluster
            for i, r in fenumerate(qm_results):
                #print 'qm forces (orig order?):'
                #print '\n'.join(['%d: pos=%s f=%s' % (j, p, f) for j, p, f in zip(r.index, r.pos, r.force)])

                client_id = i
                if self.mm_local:
                    client_id -= 1
                if self.save_clusters:
                    r.write(
                        os.path.join(
                            self.rundir, 'results.client-%03d.label-%04d.xyz' %
                            (client_id, r.label)))

                mark_name = 'hybrid_mark_%d' % i
                mask = getattr(r, mark_name) == HYBRID_ACTIVE_MARK
                #print 'Cluster %d: QM forces on atoms %s' % (i, r.index[mask])
                #print r.force[:, mask].T
                # HL if set_fortran is false we need to reduce the index here because
                # the atoms object is expecting python indexing.
                at.qm_force[:,
                            [ind - 1
                             for ind in list(r.index[mask])]] = r.force[:,
                                                                        mask]

        system_timer('process_results')

        # now call the parent calc() to do the force mixing etc.
        force_mixing_args = kwargs.copy()
        force_mixing_args.update(self.cluster_args)
        force_mixing_args['calc_weights'] = False  # already done this above
        #print 'calling ForceMixingPotential.calc() with args %r' % force_mixing_args
        ForceMixingPotential.calc(self, at, energy, force, virial,
                                  local_energy, local_virial, args_str, error,
                                  **force_mixing_args)
Exemplo n.º 2
0
     # restart from last frame of most recent trajectory file
     traj_files = sorted(glob.glob('[0-9]*.traj.xyz'))
     if len(traj_files) > 0:
         last_traj = traj_files[-1]
         input_file = last_traj + '@-1'
 
 # loading reference configuration for Nye tensor evaluation
 # convert to quippy Atoms - FIXME in long term, this should not be necesary
 x0 = Atoms(params.reference_file)
 x0 = Atoms(x0)
 x0.set_cutoff(3.0)
 x0.calc_connect()
 
 print params.param_file
 # ******* Set up potentials and calculators ********
 system_timer('init_fm_pot')
 pot_file = os.path.join(params.pot_dir, params.param_file)
 mm_pot = Potential(params.mm_init_args,
                    param_filename=params.param_file,
                    cutoff_skin=params.cutoff_skin)
 
 cluster_args = params.cluster_args.copy()
 
 if params.test_mode:
     # dummy QM potential made by swapping Ni and Al species in MM potential               
     qm_pot = Potential(params.mm_init_args,
                        param_filename='m2004flipNiAl.xml',
                        cutoff_skin=params.cutoff_skin)
     qm_clients = qm_pot
     
     # convergence of EAM forces with buffer size is suprisingly slow,
Exemplo n.º 3
0
    def step(self):
        """
        Advance the dynamics by one LOTF cycle

        The *Learn on the Fly* algorithm proceeds as follows:

           1. **QM selection** using the function registered
              with the :meth:`set_qm_update_func` method.

           2. **Save state** of the dynamical system using the
              :meth:`get_state` method.

           3. **Extrapolation** of the dynamics with fixed parameters for
              :attr:`extrapolate_steps`, each of size :attr:`dt`.
              This is the *predictor* part of the predictor-corrector cycle.
              The adjustable potential parameters are remapped if
              the set of QM atoms has changed since the most recent fit.

           4. **QM force calculation** and **optimisation** of the adjustable
              potential parameters to reproduce the QM forces at the fit point.
              With the linear 'spings' method, the fit can be reposed as a linear
              algebra problem and solved via singular value decomposition (SVD).
              See the adjustable potential code for full details in
              :svn:`QUIP_Core/AdjustablePotential.f95`.

           5. **Restore state** of the dynamical system saved at step 2,
              returning to before the extrapolation phase.

           6. **Interpolation** of the dynamics, with the adjustable potential
              parameters interpolated between their values at the two fit points.

        """

        system_timer('lotf_step')
        system_timer('lotf_extrapolate')

        if self.qm_update_func is not None:
            self.qm_update_func(self.atoms)

        saved_state = self.get_state()
        self.state = LOTFDynamics.Extrapolation

        for i in range(self.extrapolate_steps):
            # Compute extrapolation forces
            f = self.get_extrapolation_forces(self.atoms, i)

            # Possibly check force error
            if self.check_force_error:
                self._calc_force_error(f)

            # Apply any constraints to the forces
            for constraint in self.atoms.constraints:
                constraint.adjust_forces(self.atoms.arrays['positions'], f)

            # Do the velocity Verlet step
            self.advance_verlet(f)
            self.nsteps += 1

            self.call_observers()
        system_timer('lotf_extrapolate')

        # Compute QM forces and fit the LOTF adjustable potential to them
        system_timer('lotf_qm_fit')
        self.fit_forces(self.atoms)
        system_timer('lotf_qm_fit')

        system_timer('lotf_interpolate')
        self.set_state(saved_state)
        self.state = LOTFDynamics.Interpolation

        for i in range(self.extrapolate_steps):
            # Compute interpolation forces
            f = self.get_interpolation_forces(self.atoms, i)

            # Possibly check force error
            if self.check_force_error:
                self._calc_force_error(f)

            # Apply any constraints to the forces
            for constraint in self.atoms.constraints:
                constraint.adjust_forces(self.atoms.arrays['positions'], f)

            # Do the velocity Verlet step
            self.advance_verlet(f)
            self.nsteps += 1

            self.call_observers()
        system_timer('lotf_interpolate')
        system_timer('lotf_step')
Exemplo n.º 4
0
    def calc(self, at, energy=None, force=None, virial=None,
             local_energy=None, local_virial=None,
             args_str=None, error=None, **kwargs):

        clusters = []
        orig_label = self.label
        if not self.mm_local:
            # always submit the MM calc
            if self.test_mode:
                clusters.append(at)
            else:
                self.server.put(at, 0, self.label, force_restart=self.force_restart)
            self.label += 1
        
        do_qm = not self.get('method').startswith('lotf') or self.get('lotf_do_qm')
        
        if do_qm:
            #print 'REGIONS', [ k for k in at.properties.keys() if re.match('hybrid_[0-9]+', k) ]
            n_region = len([ k for k in at.properties.keys() if re.match('hybrid_[0-9]+', k) ])

            if self.get('calc_weights'):
                system_timer('create_hybrid_weights')
                # overall hybrid property is union of all the hybrids
                if not hasattr(at, 'hybrid'):
                    at.add_property('hybrid', 0)
                at.hybrid[:] = 0
                for i in frange(n_region):
                    hybrid = getattr(at, 'hybrid_%d' % i)
                    at.hybrid[hybrid == HYBRID_ACTIVE_MARK] = HYBRID_ACTIVE_MARK
                if not hasattr(at, 'hybrid_mark'):
                    at.add_property('hybrid_mark', at.hybrid)
                at.hybrid_mark[:] = 0
                at.hybrid_mark = at.hybrid
                create_hybrid_weights_args = self.cluster_args.copy()
                create_hybrid_weights_args['buffer_hops'] = 0
                create_hybrid_weights_args['transition_hops'] = 0 # ensure a fast exit
                # overall hybrid -> hybrid_mark, weight_region1
                create_hybrid_weights(at, args_str=quippy.util.args_str(create_hybrid_weights_args))
                system_timer('create_hybrid_weights')
            
            # make clusters and submit to QM clients
            system_timer('make_clusters')
            for i in frange(n_region):
                hybrid_name = 'hybrid_%d' % i
                hybrid_mark_name = 'hybrid_mark_%d' % i
                if self.get('calc_weights'):
                    hybrid = getattr(at, hybrid_name)
                    if not hasattr(at, hybrid_mark_name):
                        at.add_property(hybrid_mark_name, HYBRID_NO_MARK)
                    hybrid_mark = getattr(at, hybrid_mark_name)

                    # set marks to allow previously active atoms to become buffer atoms
                    # create_hybrid_weights will then set the buffer marks
                    hybrid_mark[hybrid_mark == HYBRID_ACTIVE_MARK] = HYBRID_BUFFER_MARK
                    hybrid_mark[hybrid == HYBRID_ACTIVE_MARK] = HYBRID_ACTIVE_MARK

                    print ('region %d, sum(hybrid) %d, sum(hybrid_mark) %d' % 
                            (i, sum(hybrid), sum(hybrid_mark)))

                    create_hybrid_weights_args = self.cluster_args.copy()
                    create_hybrid_weights_args['run_suffix'] = '_%d' % i
                    create_hybrid_weights_args_str = quippy.util.args_str(create_hybrid_weights_args)
                    print 'calling create_hybrid_weights with args_str %s' % create_hybrid_weights_args_str
                    create_hybrid_weights(at, args_str=create_hybrid_weights_args_str)

                cluster_args_str = quippy.util.args_str(self.cluster_args)
                print 'calling create_cluster_simple with args_str %s' % cluster_args_str
                c = create_cluster_simple(at, mark_name=hybrid_mark_name, args_str=cluster_args_str)
                
                client_id = i
                if self.mm_local:
                    client_id -= 1
                if self.save_clusters:
                    c.write(os.path.join(self.rundir,
                                         'cluster.client-%03d.label-%04d.xyz' %
                                         (client_id, self.label)))
                if self.test_mode:
                    clusters.append(c)
                else:
                    self.server.put(c, client_id, self.label, force_restart=self.force_restart)
                self.label += 1
            system_timer('make_clusters')

        # wait for results to be ready
        system_timer('get_results')
        if self.test_mode:
            results = []
            for i, cluster in enumerate(clusters):
                result = cluster.copy()
                result.set_cutoff(self.qm_pot.cutoff())
                result.calc_connect()
                self.qm_pot.calc(result, force=True)
                result.params['label'] = orig_label + i
                results.append(result)
        else:
            results = self.server.get_results()
        system_timer('get_results')

        system_timer('process_results')
        if self.mm_local:
            qm_results = results
        else:
            # process MM results
            mm_results, qm_results = results[:1], results[1:]
            mm_result = mm_results[0]
            at.add_property('mm_force', mm_result.force, overwrite=True)

        if do_qm:
            # process QM results
            at.add_property('qm_force', 0., n_cols=3, overwrite=True)

            # extract forces from each cluster
            for i, r in fenumerate(qm_results):
                #print 'qm forces (orig order?):'
                #print '\n'.join(['%d: pos=%s f=%s' % (j, p, f) for j, p, f in zip(r.index, r.pos, r.force)])

                client_id = i
                if self.mm_local:
                    client_id -= 1
                if self.save_clusters:
                    r.write(os.path.join(self.rundir,
                                         'results.client-%03d.label-%04d.xyz' %
                                         (client_id, r.label)))

                mark_name = 'hybrid_mark_%d' % i
                mask = getattr(r, mark_name) == HYBRID_ACTIVE_MARK
                #print 'Cluster %d: QM forces on atoms %s' % (i, r.index[mask])
                #print r.force[:, mask].T
        # HL if set_fortran is false we need to reduce the index here because
        # the atoms object is expecting python indexing.
                at.qm_force[:, [ind-1 for ind in list(r.index[mask])]] = r.force[:, mask]

        system_timer('process_results')

        # now call the parent calc() to do the force mixing etc.
        force_mixing_args = kwargs.copy()
        force_mixing_args.update(self.cluster_args)
        force_mixing_args['calc_weights'] = False # already done this above
        #print 'calling ForceMixingPotential.calc() with args %r' % force_mixing_args
        ForceMixingPotential.calc(self, at, energy, force, virial, local_energy, 
                                  local_virial, args_str, error, **force_mixing_args)