Beispiel #1
0
def optimize(method,
             assert_convergence=ASSERT_CONV,
             include_ghost=INCLUDE_GHOST,
             **kwargs):
    '''Optimize the geometry with the given method.
    '''
    mol = copy.copy(method.mol)
    if 'log' in kwargs:
        log = lib.logger.new_logger(method, kwargs['log'])
    elif 'verbose' in kwargs:
        log = lib.logger.new_logger(method, kwargs['verbose'])
    else:
        log = lib.logger.new_logger(method)


#    geom = optimize_berny(as_berny_solver(method), to_berny_geom(mol),
#                          log=to_berny_log(log), **kwargs)
# temporary interface, taken from berny.py optimize function
    log = to_berny_log(log)
    solver = as_berny_solver(method, assert_convergence, include_ghost)
    geom = to_berny_geom(mol, include_ghost)
    next(solver)
    optimizer = Berny(geom, log=log, **kwargs)
    for geom in optimizer:
        energy, gradients = solver.send(geom)
        optimizer.send((energy, gradients))
    mol.set_geom_(_geom_to_atom(mol, geom, include_ghost), unit='Bohr')
    return mol
Beispiel #2
0
def optimize(method,
             assert_convergence=ASSERT_CONV,
             include_ghost=INCLUDE_GHOST,
             callback=None,
             **kwargs):
    '''Optimize the geometry with the given method.
    '''
    mol = method.mol.copy()
    if 'log' in kwargs:
        log = lib.logger.new_logger(method, kwargs['log'])
    elif 'verbose' in kwargs:
        log = lib.logger.new_logger(method, kwargs['verbose'])
    else:
        log = lib.logger.new_logger(method)


# temporary interface, taken from berny.py optimize function
    berny_log = to_berny_log(log)
    solver = as_berny_solver(method, assert_convergence, include_ghost)
    geom = to_berny_geom(mol, include_ghost)
    optimizer = Berny(geom, log=berny_log, **kwargs)
    e_last = 0
    for cycle, geom in enumerate(optimizer):
        if log.verbose >= lib.logger.NOTE:
            log.note('\nGeometry optimization cycle %d', cycle + 1)
            _dump_mol_geometry(mol, geom, log)
        mol.set_geom_(_geom_to_atom(mol, geom, include_ghost), unit='Bohr')
        energy, gradients = solver(mol)
        log.note('cycle %d: E = %.12g  dE = %g  norm(grad) = %g', cycle + 1,
                 energy, energy - e_last, numpy.linalg.norm(gradients))
        e_last = energy
        optimizer.send((energy, gradients))
        if callable(callback):
            callback(locals())
    return mol
Beispiel #3
0
def optimize(method, **kwargs):
    '''Optimize the geometry with the given method.
    '''
    mol = copy.copy(method.mol)
    if 'log' in kwargs:
        log = lib.logger.new_logger(method, kwargs['log'])
    elif 'verbose' in kwargs:
        log = lib.logger.new_logger(method, kwargs['verbose'])
    else:
        log = lib.logger.new_logger(method)


#    geom = optimize_berny(as_berny_solver(method), to_berny_geom(mol),
#                          log=to_berny_log(log), **kwargs)
# temporary interface, taken from berny.py optimize function
    log = to_berny_log(log)
    solver = as_berny_solver(method, kwargs.get('assert_convergence', False))
    geom = to_berny_geom(mol)
    next(solver)
    optimizer = Berny(geom, log=log, **kwargs)
    for geom in optimizer:
        energy, gradients = solver.send(list(geom))
        optimizer.send((energy, gradients))
    mol.set_geom_(geom_to_atom(geom))
    return mol
Beispiel #4
0
def get_berny(args):
    geom = geomlib.load(sys.stdin, args.format)
    if args.paramfile:
        with open(args.paramfile) as f:
            params = json.load(f)
    else:
        params = None
    berny = Berny(geom, **params)
    next(berny)
    return berny
Beispiel #5
0
    def optimize(self, solver):

        mol = self.mol_origin
        geom_outer = self.mol_to_geom(mol)
        optimizer = Berny(geom_outer,
                          verbosity=(2 + LOGLEVEL),
                          gradientmax=self.gradientmax,
                          gradientrms=self.gradientrms,
                          stepmax=self.stepmax,
                          steprms=self.steprms)

        for geom in optimizer:
            mol_opt = self.geom_to_mol(mol, geom)
            print("In optimization: Molecular geom")
            print(mol_opt.atom_coords() * lib.param.BOHR)
            energy, gradients = solver(mol_opt)
            optimizer.send((energy, gradients))
            geom_outer = geom
        return self.geom_to_mol(mol, geom_outer)
Beispiel #6
0
 def run(self):
     if self.optg_berny:
         # now optg
         gconv = self.gconvs_berny[self.param['gconv']]
         gradientmax, gradientrms, stepmax, steprms = [ gconv[k] \
               for k in ['gradientmax', 'gradientrms', 'stepmax', 'steprms'] ]
         optimizer = Berny(geomlib.readfile(self.fn+'.xyz'), \
                           gradientmax = gradientmax, \
                           gradientrms = gradientrms, \
                           steprms=steprms, stepmax=stepmax, \
                           maxsteps=self.param['maxit'])
         solver = self.get_energy_and_gradient()
         next(solver)
         coords_a = []
         es_a = []
         grads_a = []
         idx = 0
         for geom in optimizer:
             atoms = list(geom)
             if not isinstance(atoms[0], tuple):
                 atoms = atoms[-1]
             print(' * idx = ', idx)
             #if idx == 0 and (self.gradients is not None):
             #    energy, gradients = self.energy, self.gradients
             #else:
             energy, gradients = solver.send((atoms, None))
             coords_a.append(geom.coords)
             es_a.append(energy)
             grads_a.append(gradients)
             idx += 1
             optimizer.send((energy, gradients))
         self.coords_a = coords_a
         self.grads_a = grads_a
         self.es_a = es_a
         self.coords = coords_a[-1]
         self.gradients = grads_a[-1]
         self.energy = es_a[-1]
     else:
         mol = cc.molecules(self.fn + '.xyz')
         gmol = cmc.RawMol(mol)
         self.get_energy(gmol)
Beispiel #7
0
def test_cyanogen(mopac, cyanogen):
    berny = Berny(cyanogen, steprms=0.01, stepmax=0.05, maxsteps=4)
    final = optimize(berny, mopac)
    inertia_princpl = np.linalg.eigvalsh(final.inertia)
    assert inertia_princpl == approx([0, 107.5, 107.5], rel=1e-3, abs=1e-3)
Beispiel #8
0
def test_aniline(mopac, aniline):
    berny = Berny(aniline, steprms=0.01, stepmax=0.05, maxsteps=8)
    final = optimize(berny, mopac)
    inertia_princpl = np.linalg.eigvalsh(final.inertia)
    assert inertia_princpl == approx([90.94, 193.1, 283.9], rel=1e-3)
Beispiel #9
0
def test_ethanol(mopac, ethanol):
    berny = Berny(ethanol, steprms=0.01, stepmax=0.05, maxsteps=5)
    final = optimize(berny, mopac)
    inertia_princpl = np.linalg.eigvalsh(final.inertia)
    assert inertia_princpl == approx([14.95, 52.58, 61.10], rel=1e-3)
Beispiel #10
0
        time.sleep(30)
        print("done sleeping")
        pass

    #load in the etot and gtot
    etot = np.load('energy.npy')
    gtot = np.load('gradient.npy')
    print("energy from .npy = ", etot)
    os.chdir('../')
    return etot, gtot


#start of pyberny optimizer
obj_list[0].write_xyz(coords_name)
os.path.abspath(os.curdir)
optimizer = Berny(geomlib.readfile(os.path.abspath(coords_name)), debug=True)
count = 0
etot_opt = 0
grad_opt = 0
for geom in optimizer:
    print("\n opt cycle:", count, "\n")
    solver = opt_fnc(geom.coords, count)
    count = count + 1
    optimizer.send(solver)
    etot_opt = solver[0]
    grad_opt = solver[1]
relaxed = geom

#writing optimized coords to .xyz file
os.chdir(folder)
coordsname = open("opt_coords.xyz", "w")
Beispiel #11
0
from berny import Berny, optimize, geomlib
from berny.solvers import MopacSolver
from scr_old.gradient_plotter import log_berny_plotter
import numpy as np
import sys

# orig_stdout = sys.stdout
srm, smax = 0.05, 0.1
fxyz, logf, fopt = '/home/anastasiia/PycharmProjects/chem_structure/opted_mols/3-MnH2_opted.xyz',\
                   '3_opted'+str(srm)+'_stepmax_'+str(smax)+'.log', '3_opted_'+str(srm)+'_stepmax_'+str(smax)+'.xyz'
f = open(logf, 'w')
sys.stdout = f

optimizer = Berny(geomlib.readfile(fxyz),
                  steprms=srm,
                  stepmax=smax,
                  maxsteps=150)
final = optimize(optimizer, MopacSolver(cmd='/opt/mopac/run_script.sh'))
inertia_princpl = np.linalg.eigvalsh(final.inertia)
final.dump(open('3_berny_opt_mopac.xyz', 'w'), 'xyz')
# final.dump(open('TS-5-6_bopt.xyz', 'w'), 'xyz')
f.close()
log_berny_plotter(logf, title='3_berny_opt_mopac')

# for geom in optimizer:
# get energy and gradients for geom
# optimizer.send((energy, gradients))
Beispiel #12
0
def optimize(method, assert_convergence=ASSERT_CONV,
             include_ghost=INCLUDE_GHOST, callback=None, **kwargs):
    '''Optimize geometry with pyberny for the given method.
    
    To adjust the convergence threshold, parameters can be set in kwargs as
    below:

    .. code-block:: python
        conv_params = {  # They are default settings
            'gradientmax': 0.45e-3,  # Eh/Angstrom
            'gradientrms': 0.15e-3,  # Eh/Angstrom
            'stepmax': 1.8e-3,       # Angstrom
            'steprms': 1.2e-3,       # Angstrom
        }
        from pyscf import geometric_solver
        geometric_solver.optimize(method, **conv_params)
    '''
    t0 = time.clock(), time.time()
    mol = method.mol.copy()
    if 'log' in kwargs:
        log = lib.logger.new_logger(method, kwargs['log'])
    elif 'verbose' in kwargs:
        log = lib.logger.new_logger(method, kwargs['verbose'])
    else:
        log = lib.logger.new_logger(method)

    if isinstance(method, lib.GradScanner):
        g_scanner = method
    elif getattr(method, 'nuc_grad_method', None):
        g_scanner = method.nuc_grad_method().as_scanner()
    else:
        raise NotImplementedError('Nuclear gradients of %s not available' % method)
    if not include_ghost:
        g_scanner.atmlst = numpy.where(method.mol.atom_charges() != 0)[0]

# temporary interface, taken from berny.py optimize function
    berny_log = to_berny_log(log)
    geom = to_berny_geom(mol, include_ghost)
    optimizer = Berny(geom, log=berny_log, **kwargs)

    t1 = t0
    e_last = 0
    for cycle, geom in enumerate(optimizer):
        if log.verbose >= lib.logger.NOTE:
            log.note('\nGeometry optimization cycle %d', cycle+1)
            dump_mol_geometry(mol, geom.coords, log)
        mol.set_geom_(_geom_to_atom(mol, geom, include_ghost), unit='Bohr')
        energy, gradients = g_scanner(mol)
        log.note('cycle %d: E = %.12g  dE = %g  norm(grad) = %g', cycle+1,
                 energy, energy - e_last, numpy.linalg.norm(gradients))
        e_last = energy
        if callable(callback):
            callback(locals())

        if assert_convergence and not g_scanner.converged:
            raise RuntimeError('Nuclear gradients of %s not converged' % method)
        optimizer.send((energy, gradients))
        t1 = log.timer('geomoetry optimization cycle %d'%cycle, *t1)

    t0 = log.timer('geomoetry optimization', *t0)
    return mol
Beispiel #13
0
def test_optimize(mopac, test_case):
    geom, n_ref = test_case()
    berny = Berny(geom)
    optimize(berny, mopac)
    assert berny.converged
    assert berny._n == n_ref
# Make wrapper functions for energy, force and dipole
def EnergyAndForce(molecule):
    (Etotal, Ebp, Ebp_atom, Ecc, Evdw, mol_dipole, atom_charge,
     gradient) = manager.EvalBPDirectEEUpdateSingle(molecule,
                                                    PARAMS["AN1_r_Rc"],
                                                    PARAMS["AN1_a_Rc"],
                                                    PARAMS["EECutoffOff"],
                                                    True)
    energy = Etotal
    return energy[0], (-1.0 * gradient[0] / JOULEPERHARTREE)


optimizer = Berny(geomlib.loads(xyz, 'xyz'),
                  maxsteps=1000,
                  gradientrms=0.0003,
                  gradientmax=0.003,
                  debug=True)
debug = []
last_geom = ""

for geom in optimizer:
    molecule_xyz = geom.dumps('xyz')
    molecule = Mol()
    molecule.FromXYZString(molecule_xyz)
    energy, gradients = EnergyAndForce(
        molecule)  # calculate energy and gradients of geom
    info = optimizer.send((energy, gradients))
    debug.append(info)
print('Final Geometry:')
print(geom.dumps('xyz'))
Beispiel #15
0
def TestBernyOpt():
	from berny import Berny, geomlib
	# a=MSet("kaggle_opt")
	# a.Load()
	# m=a.mols[8804]
	# m = Mol()
	# m.FromXYZString("""73
	xyz = """73

	O          3.11000        4.22490       -0.75810
	O          4.72290        2.06780       -2.02160
	O          3.28790        0.27660       -2.12830
	O          7.57740       -2.18410        0.83530
	O          6.93870       -0.24500        1.85400
	N         -0.44900        1.57680        0.54520
	N          0.67240       -1.09000        0.16920
	N         -3.08650        0.73580        0.30880
	N         -2.08930       -2.17120        0.36140
	C          3.15530        1.80910       -0.26920
	C          1.94310        0.99350        0.14610
	C          1.10470        3.11900       -0.07220
	C          0.85730        1.76100        0.25120
	C          2.53600        3.20940       -0.40610
	C         -0.01170        3.83890       -0.00490
	C          1.80260       -0.45930        0.35870
	C         -0.97430        2.76340        0.37660
	C          2.91740       -1.33270        0.77810
	C          2.32400       -2.53760        0.79670
	C          3.70160        1.28460       -1.55560
	C          0.92000       -2.41280        0.43150
	C         -2.41080        3.07580        0.55540
	C         -0.29110        5.26060       -0.27150
	C         -3.30810        2.07470        0.53020
	C         -4.22430       -0.01890        0.37480
	C         -1.33840       -3.26350       -0.02560
	C          0.02500       -3.41140        0.34800
	C         -4.76240        2.20220        0.74210
	C         -5.29980        0.95570        0.65430
	C         -3.38890       -2.29630       -0.08630
	C         -2.18770       -4.11130       -0.70980
	C         -3.46520       -3.50710       -0.75000
	C          4.24800       -0.96910        1.13640
	C         -4.40070       -1.34110        0.20870
	C          2.93270       -3.85050        1.16890
	C         -6.72700        0.53540        0.79750
	C         -1.82240       -5.42330       -1.29120
	C         -5.50430        3.40910        1.00050
	C         -4.63100       -4.03780       -1.35240
	C          5.32530       -1.71620        0.83820
	C          5.31710        1.65030       -3.25560
	C         -6.03270        4.16680        0.03880
	C         -5.68440       -3.34470       -1.89440
	C          6.67040       -1.26750        1.24620
	H          3.91490        1.82320        0.51520
	H         -2.69930        4.10740        0.71860
	H         -0.66660        5.75450        0.62990
	H          0.61110        5.79090       -0.59250
	H         -1.03960        5.36580       -1.06280
	H          0.35400       -4.43150        0.53040
	H         -5.40880       -1.73500        0.30730
	H          4.36030       -0.04870        1.70090
	H          3.88280       -3.75330        1.69880
	H          2.27760       -4.40220        1.85250
	H          3.09460       -4.46420        0.27690
	H         -6.83900       -0.17840        1.62010
	H         -7.08680        0.06850       -0.12540
	H         -7.38530        1.38280        1.01220
	H         -2.13640       -6.23380       -0.62560
	H         -2.30250       -5.57200       -2.26410
	H         -0.74330       -5.51440       -1.45110
	H         -5.62320        3.69670        2.04090
	H         -4.70070       -5.12240       -1.41710
	H          5.25800       -2.63030        0.25800
	H          4.57150        1.65850       -4.05620
	H          5.75710        0.65460       -3.14550
	H          6.11050        2.35890       -3.50730
	H         -6.58170        5.06770        0.29090
	H         -5.93330        3.91260       -1.01130
	H         -6.51300       -3.89300       -2.33170
	H         -5.71990       -2.26400       -1.94770
	H          8.49250       -1.93230        1.08330
	Mg        -1.34673        0.02041       -0.06327"""

	init_mol = Mol()
	init_mol.FromXYZString(xyz)
	# init_mol = a.mols[0]
	net = UniversalNetwork(name="SF_Universal_master_jeherr_Thu_May_31_16.20.05_2018")
	EF = net.GetEnergyForceRoutine(init_mol)
	optimizer = Berny(
	geomlib.loads(init_mol.__str__(), 'xyz'),
		maxsteps=5000)
		# gradientrms=0.0001,
		# gradientmax=0.003,
		# debug=True)
	debug = []
	last_geom = ""
	init_mol.WriteXYZfile(fname="chlorophyll_berny")
	for geom in optimizer:
		molecule_xyz = geom.dumps('xyz')
		molecule = Mol()
		molecule.FromXYZString(molecule_xyz)
		molecule.WriteXYZfile(fname="chlorophyll_berny")
		energy, gradients = EF(molecule.coords)  # calculate energy and gradients of geom
		info = optimizer.send((energy, gradients))
		debug.append(info)
	print('Final Geometry:')
	print(geom.dumps('xyz'))
Beispiel #16
0
def kernel(method, assert_convergence=ASSERT_CONV,
           include_ghost=INCLUDE_GHOST, callback=None, **kwargs):
    '''Optimize geometry with pyberny for the given method.
    
    To adjust the convergence threshold, parameters can be set in kwargs as
    below:

    .. code-block:: python
        conv_params = {  # They are default settings
            'gradientmax': 0.45e-3,  # Eh/Angstrom
            'gradientrms': 0.15e-3,  # Eh/Angstrom
            'stepmax': 1.8e-3,       # Angstrom
            'steprms': 1.2e-3,       # Angstrom
        }
        from pyscf.geomopt import berny_solver
        opt = berny_solver.GeometryOptimizer(method)
        opt.params = conv_params
        opt.kernel()
    '''
    t0 = time.clock(), time.time()
    mol = method.mol.copy()
    if 'log' in kwargs:
        log = lib.logger.new_logger(method, kwargs['log'])
    elif 'verbose' in kwargs:
        log = lib.logger.new_logger(method, kwargs['verbose'])
    else:
        log = lib.logger.new_logger(method)

    if isinstance(method, lib.GradScanner):
        g_scanner = method
    elif getattr(method, 'nuc_grad_method', None):
        g_scanner = method.nuc_grad_method().as_scanner()
    else:
        raise NotImplementedError('Nuclear gradients of %s not available' % method)
    if not include_ghost:
        g_scanner.atmlst = numpy.where(method.mol.atom_charges() != 0)[0]

    # When symmetry is enabled, the molecule may be shifted or rotated to make
    # the z-axis be the main axis. The transformation can cause inconsistency
    # between the optimization steps. The transformation is muted by setting
    # an explict point group to the keyword mol.symmetry (see symmetry
    # detection code in Mole.build function).
    if mol.symmetry:
        mol.symmetry = mol.topgroup

# temporary interface, taken from berny.py optimize function
    berny_log = to_berny_log(log)
    geom = to_berny_geom(mol, include_ghost)
    optimizer = Berny(geom, log=berny_log, **kwargs)

    t1 = t0
    e_last = 0
    for cycle, geom in enumerate(optimizer):
        if log.verbose >= lib.logger.NOTE:
            log.note('\nGeometry optimization cycle %d', cycle+1)
            dump_mol_geometry(mol, geom.coords, log)

        if mol.symmetry:
            geom.coords = symmetrize(mol, geom.coords)

        mol.set_geom_(_geom_to_atom(mol, geom, include_ghost), unit='Bohr')
        energy, gradients = g_scanner(mol)
        log.note('cycle %d: E = %.12g  dE = %g  norm(grad) = %g', cycle+1,
                 energy, energy - e_last, numpy.linalg.norm(gradients))
        e_last = energy
        if callable(callback):
            callback(locals())

        if assert_convergence and not g_scanner.converged:
            raise RuntimeError('Nuclear gradients of %s not converged' % method)
        optimizer.send((energy, gradients))
        t1 = log.timer('geomoetry optimization cycle %d'%cycle, *t1)

    t0 = log.timer('geomoetry optimization', *t0)
    return optimizer._converged, mol
Beispiel #17
0
    def optimize(self):
        fout_xyz = open(self._geomopt['fname_gopt_xyz'], 'w', 1)
        fout_log = open(self._geomopt['fname_gopt_log'], 'w', 1)

        optimizer = Berny(self._qm_geom)
        qm_natom = len(self._qm_geom)

        def step_func(x):
            if x < -0.5:
                x = -0.5
            elif x > 0.5:
                x = 0.5
            return x

        qm_crds_old = self._qm_geom.coords
        prt_crds = self._prt_geom.coords
        ener_last = 0.0
        qm_grd_norm_last = 0.0
        ener_QM0 = 0.0
        for cycle, qm_geom in enumerate(optimizer):

            qm_crds_new = qm_geom.coords
            d_crds = qm_crds_new - qm_crds_old

            for atmId in self._qm2mm_index:
                resId, atomName = atmId.split(':')
                if resId not in ['LIG1']:
                    mm_idx = self._qm2mm_index[atmId]
                    qm_idx = self._qmatm_index[atmId]
                    if atomName not in ['CA']:
                        prt_crds[mm_idx] = qm_crds_new[qm_idx]

            ener_QMMM, ener_const, grds_QM, esp_QM, \
                ener_QMMM_vdw, ener_PRT, grds_PRT = self.pot_grad(
                    qm_geom, prt_crds)
            if cycle == 0:
                ener_QM0 = ener_QMMM
            ener_QMMM -= ener_QM0
            ener = ener_QMMM + ener_const + ener_QMMM_vdw + ener_PRT
            qm_grd_norm = np.linalg.norm(grds_QM)

            print(' %5d' % qm_natom, file=fout_xyz)
            print('cycle %3d: E = %12.6f %12.6f %10.4f %10.4f %10.4f  %12.6f' %
                  (cycle + 1, ener, ener_QMMM, ener_const, ener_QMMM_vdw,
                   ener_PRT, ener_QM0),
                  file=fout_xyz)
            print(
                'cycle %3d: E = %12.6f %12.6f %10.4f %10.4f %10.4f dE = %.6g  norm(grad) = %g'
                % (cycle + 1, ener, ener_QMMM, ener_const, ener_QMMM_vdw,
                   ener_PRT, ener - ener_last, qm_grd_norm),
                file=fout_log)

            for i in range(qm_natom):
                print('%4s %10.6f %10.6f %10.6f' %
                      (self._qm_geom.species[i], qm_crds_new[i, 0],
                       qm_crds_new[i, 1], qm_crds_new[i, 2]),
                      file=fout_xyz)
                print('%5d %4s %8.4f %8.4f %8.4f  %8.4f %8.4f %8.4f' %
                      ((i + 1), self._qm_geom.species[i], d_crds[i, 0],
                       d_crds[i, 1], d_crds[i, 2], grds_QM[i, 0],
                       grds_QM[i, 1], grds_QM[i, 2]),
                      file=fout_log)

            if (cycle + 1) % 2 == 0:
                self.save_coordinates(qm_crds_new, prt_crds)

            dE = ener - ener_last
            if abs(dE) / qm_natom < 1.0e-8:
                break

            dG = qm_grd_norm - qm_grd_norm_last
            if abs(dG) / qm_natom < 1.0e-8:
                break

            ener_last = ener
            qm_grd_norm_last = qm_grd_norm
            qm_crds_old = qm_crds_new

            for atmId in self._qm2mm_index:
                resId, atomName = atmId.split(':')
                if resId[:3] not in ['LIG'] and atomName not in ['CA']:
                    '''
                    'CA' belongs to MM
                    Except 'CA', bond, angle, and torsional gradients, which are estimated within MM, are copied to QM particles.
                    '''
                    mm_idx = self._qm2mm_index[atmId]
                    qm_idx = self._qmatm_index[atmId]
                    grds_QM[qm_idx] += grds_PRT[mm_idx]
                    grds_PRT[mm_idx, 0] = 0
                    grds_PRT[mm_idx, 1] = 0
                    grds_PRT[mm_idx, 2] = 0

            grds_PRT = np.array([[step_func(x),
                                  step_func(y),
                                  step_func(z)] for x, y, z in grds_PRT])
            prt_crds -= 0.01 * grds_PRT

            grds_QM = np.array([[step_func(x),
                                 step_func(y),
                                 step_func(z)] for x, y, z in grds_QM])

            optimizer.send((ener, grds_QM))

        self.save_coordinates(qm_crds_old, prt_crds)