From a7e476097e9fcb1e1ee94cbfd5594bf7fae40f89 Mon Sep 17 00:00:00 2001 From: Han Wang Date: Sat, 28 Aug 2021 08:16:44 +0800 Subject: [PATCH 01/34] change to almostEqual in UT to avoid difference at FP precision (#1048) Co-authored-by: Han Wang --- source/tests/test_model_devi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/tests/test_model_devi.py b/source/tests/test_model_devi.py index 3e5161b44d..4d5414cea8 100644 --- a/source/tests/test_model_devi.py +++ b/source/tests/test_model_devi.py @@ -36,11 +36,11 @@ def test_calc_model_devi(self): frequency=self.freq, nopbc=True, fname=self.output) - self.assertEqual(model_devi[0][0], 0) - self.assertEqual(model_devi[1][0], self.freq) + self.assertAlmostEqual(model_devi[0][0], 0) + self.assertAlmostEqual(model_devi[1][0], self.freq) for ii in range(1, 7): self.assertAlmostEqual(model_devi[0][ii], self.expect[ii]) - self.assertEqual(model_devi[0][ii], model_devi[1][ii]) + self.assertAlmostEqual(model_devi[0][ii], model_devi[1][ii]) self.assertTrue(os.path.isfile(self.output)) def tearDown(self): From 5f8989b25d4c0c1594bbdb2a2f1fb7cacb767530 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sat, 28 Aug 2021 05:07:49 -0400 Subject: [PATCH 02/34] fix hybrid descriptor training error (#1052) fix #1051. --- deepmd/train/trainer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index e301a0753b..72dc61418e 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -315,7 +315,7 @@ def build (self, self._init_from_frz_model() self.neighbor_stat \ - = NeighborStat(self.ntypes, self.descrpt_param['rcut']) + = NeighborStat(self.ntypes, self.descrpt.get_rcut()) self.min_nbor_dist, self.max_nbor_size \ = self.neighbor_stat.get_stat(data) tf.constant(self.min_nbor_dist, From 1dd6e971a54940356f5b8b6ad4cf72e4a27a0e18 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sun, 29 Aug 2021 04:12:46 -0400 Subject: [PATCH 03/34] add compatibility to `dp freeze` (#1055) Fix #1053. --- deepmd/entrypoints/freeze.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/deepmd/entrypoints/freeze.py b/deepmd/entrypoints/freeze.py index c6bb89fb8f..a6d8926109 100755 --- a/deepmd/entrypoints/freeze.py +++ b/deepmd/entrypoints/freeze.py @@ -6,6 +6,7 @@ https://blog.metaflow.fr/tensorflow-how-to-freeze-a-model-and-serve-it-with-a-python-api-d4f3596b3adc """ +import logging from deepmd.env import tf from deepmd.env import op_module from deepmd.utils.sess import run_sess @@ -18,6 +19,8 @@ __all__ = ["freeze"] +log = logging.getLogger(__name__) + def _make_node_names(model_type: str, modifier_type: Optional[str] = None) -> List[str]: """Get node names based on model type. @@ -175,9 +178,18 @@ def freeze( modifier_type = None if node_names is None: output_node_list = _make_node_names(model_type, modifier_type) + different_set = set(output_node_list) - set(nodes) + if different_set: + log.warning( + "The following nodes are not in the graph: %s. " + "Skip freezeing these nodes. You may be freezing " + "a checkpoint generated by an old version." % different_set + ) + # use intersection as output list + output_node_list = list(set(output_node_list) & set(nodes)) else: output_node_list = node_names.split(",") - print(f"The following nodes will be frozen: {output_node_list}") + log.info(f"The following nodes will be frozen: {output_node_list}") # We use a built-in TF helper to export variables to constants output_graph_def = tf.graph_util.convert_variables_to_constants( @@ -189,4 +201,4 @@ def freeze( # Finally we serialize and dump the output graph to the filesystem with tf.gfile.GFile(output_graph, "wb") as f: f.write(output_graph_def.SerializeToString()) - print(f"{len(output_graph_def.node):d} ops in the final graph.") + log.info(f"{len(output_graph_def.node):d} ops in the final graph.") From 8dbc2119ee947fec3c6ea0d3f08f8fad68ff4be0 Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Mon, 30 Aug 2021 07:50:23 +0800 Subject: [PATCH 04/34] fix device UT error (#1056) * fix device UT error * fix UT bug --- .../model_compression/data/set.000/box.npy | Bin 488 -> 200 bytes .../model_compression/data/set.000/coord.npy | Bin 23168 -> 272 bytes .../model_compression/data/set.000/energy.npy | Bin 168 -> 136 bytes .../model_compression/data/set.000/force.npy | Bin 23168 -> 272 bytes source/tests/model_compression/data/type.raw | 196 +----------------- source/tests/test_transfer.py | 158 +++++++------- 6 files changed, 90 insertions(+), 264 deletions(-) diff --git a/source/tests/model_compression/data/set.000/box.npy b/source/tests/model_compression/data/set.000/box.npy index 1f5de3f920c3223e74b9192a54a1372b66a6ac09..aa092a9aad05a63db85de60fba66177184c25934 100644 GIT binary patch literal 200 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+i=qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= fXCxM+0{I%2I+{8PwF(pfE(S2ra)8jdNW$^}G$I_L literal 488 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+l>qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= vXCxM+0{I$-2099snmP)#3giN=P+50J1|)!uk4+3o3j;`gR1G3Tu!RKxwKzD< diff --git a/source/tests/model_compression/data/set.000/coord.npy b/source/tests/model_compression/data/set.000/coord.npy index 3ab45710070ea27e776562a56f13dec638e99ec2..2205bfd45207e3c240c2b27877ddce45ece2e2d9 100644 GIT binary patch delta 172 zcmZqJ$~b{(f;gkaL$x;z`VW0wq3KX9vd;Zs6^lcmE!XwM z1&j_Lo`{}?!#53(0yc*?fji_{U$Z(efWZZOpde6&%K@kgsPvaTgyw?Eb3pa|u?HI~ d!s7s;Ssc!u0Ra{$Ur5m5Fvy%koKOuv>;Zr8L`(nx literal 23168 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 diff --git a/source/tests/model_compression/data/set.000/energy.npy b/source/tests/model_compression/data/set.000/energy.npy index 35899bf0f1b12b7a4e45fdcfae0de5185d30838a..6c1e5ce145b0d55f60b1a3ff8b9e7eb339bc4f7b 100644 GIT binary patch delta 27 jcmZ3%*ugkKoY7*Ugz7{GdmaS^1upYWm&XUhdk+8rXNd@M delta 60 zcmeBRT){X&oY7>WgetS4fzCu*drhtj?_VC948)%AULN}d#7lteu(vOdbpYwg4=;~h L0n(bEUmgPhf*2%l diff --git a/source/tests/model_compression/data/set.000/force.npy b/source/tests/model_compression/data/set.000/force.npy index a1f696c18677220f6644c75f4779a09b1fd5d375..10698ebb5943acfa481b8e144b72c38a8bee5cbf 100644 GIT binary patch delta 172 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 Date: Mon, 30 Aug 2021 21:11:13 -0400 Subject: [PATCH 05/34] copy `all_virial` for float precision (#1069) Fix #1068. This bug is produced by #594. --- source/lmp/pair_deepmd.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/lmp/pair_deepmd.cpp b/source/lmp/pair_deepmd.cpp index 09e6d55f0a..e1467631a4 100644 --- a/source/lmp/pair_deepmd.cpp +++ b/source/lmp/pair_deepmd.cpp @@ -478,6 +478,13 @@ void PairDeepMD::compute(int eflag, int vflag) all_force[ii][jj] = all_force_[ii][jj]; } } + all_virial.resize(all_virial_.size()); + for (unsigned ii = 0; ii < all_virial_.size(); ++ii){ + all_virial[ii].resize(all_virial_[ii].size()); + for (unsigned jj = 0; jj < all_virial_[ii].size(); ++jj){ + all_virial[ii][jj] = all_virial_[ii][jj]; + } + } #endif if (eflag_atom) { for (int ii = 0; ii < nlocal; ++ii) eatom[ii] += deatom[ii]; From 37fe14c69c1548bead2eb70efa01bfa764294c69 Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Tue, 31 Aug 2021 09:14:05 +0800 Subject: [PATCH 06/34] upgrade os.system to subporcess.popen method (#1066) * upgrade os.system to subporcess-popen method * fix UT error * fix UT error * address comments --- source/tests/test_model_compression.py | 23 +++++++++++++++++------ source/tests/test_transfer.py | 15 +++++++++++++-- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/source/tests/test_model_compression.py b/source/tests/test_model_compression.py index 8465c5a05e..50fbb9e107 100644 --- a/source/tests/test_model_compression.py +++ b/source/tests/test_model_compression.py @@ -1,6 +1,7 @@ import os,sys,platform,shutil,dpdata,json import numpy as np import unittest +import subprocess as sp from deepmd.infer import DeepPot from deepmd.env import MODEL_VERSION @@ -17,6 +18,16 @@ def _file_delete(file) : if os.path.exists(file): os.remove(file) +def _subprocess_run(command): + popen = sp.Popen(command.split(), shell=False, stdout=sp.PIPE, stderr=sp.STDOUT) + for line in iter(popen.stdout.readline, b''): + if hasattr(line, 'decode'): + line = line.decode('utf-8') + line = line.rstrip() + print(line) + popen.wait() + return popen.returncode + def _init_models(): data_file = str(tests_path / os.path.join("model_compression", "data")) frozen_model = str(tests_path / "dp-original.pb") @@ -28,12 +39,12 @@ def _init_models(): with open(INPUT, "w") as fp: json.dump(jdata, fp, indent=4) - ret = os.system("dp train " + INPUT) - assert(ret == 0), "DP train error!" - ret = os.system("dp freeze -o " + frozen_model) - assert(ret == 0), "DP freeze error!" - ret = os.system("dp compress " + " -i " + frozen_model + " -o " + compressed_model) - assert(ret == 0), "DP model compression error!" + ret = _subprocess_run("dp train " + INPUT) + np.testing.assert_equal(ret, 0, 'DP train failed!') + ret = _subprocess_run("dp freeze -o " + frozen_model) + np.testing.assert_equal(ret, 0, 'DP freeze failed!') + ret = _subprocess_run("dp compress " + " -i " + frozen_model + " -o " + compressed_model) + np.testing.assert_equal(ret, 0, 'DP model compression failed!') return INPUT, frozen_model, compressed_model INPUT, FROZEN_MODEL, COMPRESSED_MODEL = _init_models() diff --git a/source/tests/test_transfer.py b/source/tests/test_transfer.py index 3a1494ef5a..7142041fda 100644 --- a/source/tests/test_transfer.py +++ b/source/tests/test_transfer.py @@ -1,6 +1,7 @@ import os,sys,platform,shutil,dpdata,json import numpy as np import unittest +import subprocess as sp from deepmd.env import tf from deepmd.infer import DeepPot @@ -18,6 +19,16 @@ def _file_delete(file) : if os.path.exists(file): os.remove(file) +def _subprocess_run(command): + popen = sp.Popen(command.split(), shell=False, stdout=sp.PIPE, stderr=sp.STDOUT) + for line in iter(popen.stdout.readline, b''): + if hasattr(line, 'decode'): + line = line.decode('utf-8') + line = line.rstrip() + print(line) + popen.wait() + return popen.returncode + class TestTransform(unittest.TestCase) : @classmethod def setUpClass(self): @@ -26,8 +37,8 @@ def setUpClass(self): self.new_model = str(tests_path / "dp-new.pb") convert_pbtxt_to_pb(str(tests_path / os.path.join("infer","deeppot.pbtxt")), self.old_model) convert_pbtxt_to_pb(str(tests_path / os.path.join("infer","deeppot-1.pbtxt")), self.raw_model) - ret = os.system("dp transfer -O " + self.old_model + " -r " + self.raw_model + " -o " + self.new_model) - assert(ret == 0), "DP transfer error!" + ret = _subprocess_run("dp transfer -O " + self.old_model + " -r " + self.raw_model + " -o " + self.new_model) + np.testing.assert_equal(ret, 0, 'DP transfer failed!') self.dp = DeepPot(self.new_model) self.coords = np.array([12.83, 2.56, 2.18, From 8cf52fdd39db4668d9d55ab8eb2b763486eb8d9e Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 30 Aug 2021 21:48:58 -0400 Subject: [PATCH 07/34] use `np.testing.assert_almost_equal` for array comparing (#1059) * use `np.testing.assert_almost_equal` for array comparing * bugfix * bugfix * bugfix * bugfix * bugfix * bugfix * bugfix --- source/tests/common.py | 8 +- source/tests/test_data_modifier.py | 16 +-- source/tests/test_data_modifier_shuffle.py | 28 ++-- source/tests/test_deepdipole.py | 30 ++--- source/tests/test_deepmd_data.py | 19 +-- source/tests/test_deeppolar.py | 31 ++--- source/tests/test_deeppot_a.py | 109 +++++---------- source/tests/test_deeppot_r.py | 102 +++++--------- source/tests/test_descrpt_nonsmth.py | 16 +-- source/tests/test_descrpt_se_a_type.py | 6 +- source/tests/test_descrpt_se_r.py | 16 +-- source/tests/test_descrpt_sea_ef_rot.py | 7 +- source/tests/test_descrpt_smooth.py | 16 +-- source/tests/test_dipole_se_a.py | 15 +-- source/tests/test_dipolecharge.py | 18 +-- source/tests/test_embedding_net.py | 20 +-- source/tests/test_ewald.py | 39 +++--- source/tests/test_fitting_ener_type.py | 3 +- source/tests/test_fitting_stat.py | 9 +- source/tests/test_gen_stat_data.py | 12 +- source/tests/test_model_compression.py | 147 +++++++-------------- source/tests/test_model_devi.py | 5 +- source/tests/test_model_loc_frame.py | 9 +- source/tests/test_model_se_a.py | 9 +- source/tests/test_model_se_a_aparam.py | 9 +- source/tests/test_model_se_a_fparam.py | 9 +- source/tests/test_model_se_a_srtab.py | 9 +- source/tests/test_model_se_a_type.py | 9 +- source/tests/test_model_se_t.py | 9 +- source/tests/test_polar_se_a.py | 15 +-- source/tests/test_prod_env_mat.py | 6 +- source/tests/test_prod_force.py | 3 +- source/tests/test_prod_force_grad.py | 3 +- source/tests/test_prod_virial.py | 6 +- source/tests/test_prod_virial_grad.py | 3 +- source/tests/test_tabulate.py | 8 +- source/tests/test_transfer.py | 39 ++---- source/tests/test_type_embed.py | 12 +- source/tests/test_wfc.py | 3 +- 39 files changed, 275 insertions(+), 558 deletions(-) diff --git a/source/tests/common.py b/source/tests/common.py index 5a63666825..87dd5d6d70 100644 --- a/source/tests/common.py +++ b/source/tests/common.py @@ -258,11 +258,9 @@ def virial_test (inter, num_vir = np.transpose(num_vir, [1,0]) box3 = dbox[0].reshape([3,3]) num_vir = np.matmul(num_vir, box3) - for ii in range(3): - for jj in range(3): - testCase.assertAlmostEqual(ana_vir[ii][jj], num_vir[ii][jj], - places=places, - msg = 'virial component %d %d ' % (ii,jj)) + np.testing.assert_almost_equal(ana_vir, num_vir, + places, + err_msg = 'virial component') diff --git a/source/tests/test_data_modifier.py b/source/tests/test_data_modifier.py index 977df9a2b6..d791ca2844 100644 --- a/source/tests/test_data_modifier.py +++ b/source/tests/test_data_modifier.py @@ -119,10 +119,9 @@ def _test_fv (self): ep, _, __ = dcm.eval(coordp, box, atype, eval_fv = False) em, _, __ = dcm.eval(coordm, box, atype, eval_fv = False) num_f = -(ep - em) / (2.*hh) - for ff in range(nframes): - self.assertAlmostEqual(vf[ff,ii], num_f[ff], - places = places, - msg = 'frame %d dof %d does not match' % (ff, ii)) + np.testing.assert_almost_equal(vf[:,ii].ravel(), num_f.ravel(), + places, + err_msg = 'dof %d does not match' % (ii)) box3 = np.reshape(box, [nframes, 3,3]) rbox3 = np.linalg.inv(box3) @@ -150,10 +149,7 @@ def _test_fv (self): t_esti = np.matmul(num_deriv, box3) # print(t_esti, '\n', vv.reshape([-1, 3, 3])) - for ff in range(nframes): - for ii in range(3): - for jj in range(3): - self.assertAlmostEqual(t_esti[ff][ii][jj], vv[ff,ii*3+jj], - places = places, - msg = "frame %d virial component [%d,%d] failed" % (ff, ii, jj)) + np.testing.assert_almost_equal(t_esti.ravel(), vv.ravel(), + places, + err_msg = "virial component failed") diff --git a/source/tests/test_data_modifier_shuffle.py b/source/tests/test_data_modifier_shuffle.py index c14b6dd105..194a80e9c4 100644 --- a/source/tests/test_data_modifier_shuffle.py +++ b/source/tests/test_data_modifier_shuffle.py @@ -185,11 +185,9 @@ def test_z_dipole(self): dv01 = dv01.reshape([self.nframes, -1]) dv1 = dv1.reshape([self.nframes, -1]) - for ii in range(self.nframes): - for jj in range(self.nsel): - self.assertAlmostEqual( - dv01[ii][jj], dv1[ii][jj], - msg = "dipole [%d,%d] dose not match" % (ii, jj)) + np.testing.assert_almost_equal( + dv01, dv1, + err_msg = "dipole dose not match") def test_modify(self): @@ -202,18 +200,12 @@ def test_modify(self): ve1, vf1, vv1 = dcm.eval(self.coords1, self.box1, self.atom_types1) vf01 = vf0[:,self.idx_map, :] - for ii in range(self.nframes): - self.assertAlmostEqual(ve0[ii], ve1[ii], - msg = 'energy %d should match' % ii) - for ii in range(self.nframes): - for jj in range(9): - self.assertAlmostEqual(vv0[ii][jj], vv1[ii][jj], - msg = 'virial [%d,%d] should match' % (ii,jj)) - for ii in range(self.nframes): - for jj in range(self.natoms): - for dd in range(3): - self.assertAlmostEqual( - vf01[ii][jj][dd], vf1[ii][jj][dd], - msg = "force [%d,%d,%d] dose not match" % (ii,jj,dd)) + np.testing.assert_almost_equal(ve0, ve1, + err_msg = 'energy should match') + np.testing.assert_almost_equal(vv0, vv1, + err_msg = 'virial should match') + np.testing.assert_almost_equal( + vf01, vf1, + err_msg = "force dose not match") diff --git a/source/tests/test_deepdipole.py b/source/tests/test_deepdipole.py index 84049a9e52..7b23e3ae00 100644 --- a/source/tests/test_deepdipole.py +++ b/source/tests/test_deepdipole.py @@ -44,8 +44,7 @@ def test_1frame_atm(self): nsel = 2 self.assertEqual(dd.shape, (nframes,nsel,3)) # check values - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], self.expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), self.expected_d, default_places) def test_2frame_atm(self): coords2 = np.concatenate((self.coords, self.coords)) @@ -58,8 +57,7 @@ def test_2frame_atm(self): self.assertEqual(dd.shape, (nframes,nsel,3)) # check values expected_d = np.concatenate((self.expected_d, self.expected_d)) - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), expected_d, default_places) class TestDeepDipoleNoPBC(unittest.TestCase) : @@ -87,8 +85,7 @@ def test_1frame_atm(self): nsel = 2 self.assertEqual(dd.shape, (nframes,nsel,3)) # check values - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], self.expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), self.expected_d, default_places) def test_1frame_atm_large_box(self): dd = self.dp.eval(self.coords, self.box, self.atype) @@ -98,8 +95,7 @@ def test_1frame_atm_large_box(self): nsel = 2 self.assertEqual(dd.shape, (nframes,nsel,3)) # check values - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], self.expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), self.expected_d, default_places) @unittest.skipIf(parse_version(tf.__version__) < parse_version("1.15"), @@ -138,8 +134,7 @@ def test_1frame_old(self): nframes = 1 self.assertEqual(gt.shape, (nframes,self.nout)) # check values - for ii in range(gt.size): - self.assertAlmostEqual(gt.reshape([-1])[ii], self.expected_gt.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(gt.ravel(), self.expected_gt, default_places) def test_1frame_old_atm(self): at = self.dp.eval(self.coords, self.box, self.atype) @@ -149,8 +144,7 @@ def test_1frame_old_atm(self): nsel = 2 self.assertEqual(at.shape, (nframes,nsel,self.nout)) # check values - for ii in range(at.size): - self.assertAlmostEqual(at.reshape([-1])[ii], self.expected_t.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(at.ravel(), self.expected_t, default_places) def test_2frame_old_atm(self): coords2 = np.concatenate((self.coords, self.coords)) @@ -163,8 +157,7 @@ def test_2frame_old_atm(self): self.assertEqual(at.shape, (nframes,nsel,self.nout)) # check values expected_d = np.concatenate((self.expected_t, self.expected_t)) - for ii in range(at.size): - self.assertAlmostEqual(at.reshape([-1])[ii], expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(at.ravel(), expected_d, default_places) def test_1frame_full(self): gt, ff, vv = self.dp.eval_full(self.coords, self.box, self.atype, atomic = False) @@ -175,12 +168,9 @@ def test_1frame_full(self): self.assertEqual(ff.shape, (nframes,self.nout,natoms,3)) self.assertEqual(vv.shape, (nframes,self.nout,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(gt.size): - self.assertAlmostEqual(gt.reshape([-1])[ii], self.expected_gt.reshape([-1])[ii], places = default_places) - for ii in range(vv.size): - self.assertAlmostEqual(vv.reshape([-1])[ii], self.expected_gv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f, default_places) + np.testing.assert_almost_equal(gt.ravel(), self.expected_gt, default_places) + np.testing.assert_almost_equal(vv.ravel(), self.expected_gv, default_places) def test_1frame_full_atm(self): gt, ff, vv, at, av = self.dp.eval_full(self.coords, self.box, self.atype, atomic = True) diff --git a/source/tests/test_deepmd_data.py b/source/tests/test_deepmd_data.py index 78d0a36cf2..8532d8d9a4 100644 --- a/source/tests/test_deepmd_data.py +++ b/source/tests/test_deepmd_data.py @@ -49,10 +49,7 @@ def test_load_set_1(self) : .add('value_1', 1, atomic=True, must=True, type_sel = [0]) data = dd._load_set(os.path.join(self.data_name, 'set.foo')) self.assertEqual(data['value_1'].shape, (self.nframes, 2)) - for ii in range(self.nframes): - for jj in range(2): - self.assertAlmostEqual(data['value_1'][ii][jj], - self.value_1[ii][jj]) + np.testing.assert_almost_equal(data['value_1'], self.value_1) def test_load_set_2(self) : @@ -60,10 +57,7 @@ def test_load_set_2(self) : .add('value_2', 1, atomic=True, must=True, type_sel = [1]) data = dd._load_set(os.path.join(self.data_name, 'set.foo')) self.assertEqual(data['value_2'].shape, (self.nframes, 4)) - for ii in range(self.nframes): - for jj in range(4): - self.assertAlmostEqual(data['value_2'][ii][jj], - self.value_2[ii][jj]) + np.testing.assert_almost_equal(data['value_2'], self.value_2) class TestData (unittest.TestCase) : @@ -217,8 +211,7 @@ def test_avg(self) : .add('test_frame', 5, atomic=False, must=True) favg = dd.avg('test_frame') fcmp = np.average(np.concatenate((self.test_frame, self.test_frame_bar), axis = 0), axis = 0) - for ii in range(favg.size) : - self.assertAlmostEqual((favg[ii]), (fcmp[ii]), places = places) + np.testing.assert_almost_equal(favg, fcmp, places) def test_check_batch_size(self) : dd = DeepmdData(self.data_name) @@ -263,8 +256,4 @@ def test_get_nbatch(self): self.assertEqual(nb, 2) def _comp_np_mat2(self, first, second) : - for ii in range(first.shape[0]) : - for jj in range(first.shape[1]) : - self.assertAlmostEqual(first[ii][jj], second[ii][jj], - msg = 'item [%d][%d] does not match' % (ii,jj), - places = places) + np.testing.assert_almost_equal(first, second, places) diff --git a/source/tests/test_deeppolar.py b/source/tests/test_deeppolar.py index 64dbcbf597..b60a1abf79 100644 --- a/source/tests/test_deeppolar.py +++ b/source/tests/test_deeppolar.py @@ -44,8 +44,7 @@ def test_1frame_atm(self): nsel = 2 self.assertEqual(dd.shape, (nframes,nsel,9)) # check values - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], self.expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), self.expected_d, default_places) def test_2frame_atm(self): coords2 = np.concatenate((self.coords, self.coords)) @@ -58,8 +57,8 @@ def test_2frame_atm(self): self.assertEqual(dd.shape, (nframes,nsel,9)) # check values expected_d = np.concatenate((self.expected_d, self.expected_d)) - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), expected_d, default_places) + class TestDeepPolarNoPBC(unittest.TestCase) : @@ -87,8 +86,7 @@ def test_1frame_atm(self): nsel = 2 self.assertEqual(dd.shape, (nframes,nsel,9)) # check values - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], self.expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), self.expected_d, default_places) def test_1frame_atm_large_box(self): dd = self.dp.eval(self.coords, self.box, self.atype) @@ -98,8 +96,7 @@ def test_1frame_atm_large_box(self): nsel = 2 self.assertEqual(dd.shape, (nframes,nsel,9)) # check values - for ii in range(dd.size): - self.assertAlmostEqual(dd.reshape([-1])[ii], self.expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(dd.ravel(), self.expected_d, default_places) @unittest.skipIf(parse_version(tf.__version__) < parse_version("1.15"), @@ -138,8 +135,7 @@ def test_1frame_old(self): nframes = 1 self.assertEqual(gt.shape, (nframes,self.nout)) # check values - for ii in range(gt.size): - self.assertAlmostEqual(gt.reshape([-1])[ii], self.expected_gt.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(gt.ravel(), self.expected_gt, default_places) def test_1frame_old_atm(self): at = self.dp.eval(self.coords, self.box, self.atype) @@ -149,8 +145,7 @@ def test_1frame_old_atm(self): nsel = 2 self.assertEqual(at.shape, (nframes,nsel,self.nout)) # check values - for ii in range(at.size): - self.assertAlmostEqual(at.reshape([-1])[ii], self.expected_t.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(at.ravel(), self.expected_t, default_places) def test_2frame_old_atm(self): coords2 = np.concatenate((self.coords, self.coords)) @@ -163,8 +158,7 @@ def test_2frame_old_atm(self): self.assertEqual(at.shape, (nframes,nsel,self.nout)) # check values expected_d = np.concatenate((self.expected_t, self.expected_t)) - for ii in range(at.size): - self.assertAlmostEqual(at.reshape([-1])[ii], expected_d.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(at.ravel(), expected_d, default_places) def test_1frame_full(self): gt, ff, vv = self.dp.eval_full(self.coords, self.box, self.atype, atomic = False) @@ -175,12 +169,9 @@ def test_1frame_full(self): self.assertEqual(ff.shape, (nframes,self.nout,natoms,3)) self.assertEqual(vv.shape, (nframes,self.nout,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(gt.size): - self.assertAlmostEqual(gt.reshape([-1])[ii], self.expected_gt.reshape([-1])[ii], places = default_places) - for ii in range(vv.size): - self.assertAlmostEqual(vv.reshape([-1])[ii], self.expected_gv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f, default_places) + np.testing.assert_almost_equal(gt.ravel(), self.expected_gt, default_places) + np.testing.assert_almost_equal(vv.ravel(), self.expected_gv, default_places) def test_1frame_full_atm(self): gt, ff, vv, at, av = self.dp.eval_full(self.coords, self.box, self.atype, atomic = True) diff --git a/source/tests/test_deeppot_a.py b/source/tests/test_deeppot_a.py index 3726299fb5..2ce4ba1193 100644 --- a/source/tests/test_deeppot_a.py +++ b/source/tests/test_deeppot_a.py @@ -108,14 +108,11 @@ def test_1frame(self): self.assertEqual(ff.shape, (nframes,natoms,3)) self.assertEqual(vv.shape, (nframes,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_1frame_atm(self): ee, ff, vv, ae, av = self.dp.eval(self.coords, self.box, self.atype, atomic = True) @@ -128,18 +125,13 @@ def test_1frame_atm(self): self.assertEqual(ae.shape, (nframes,natoms,1)) self.assertEqual(av.shape, (nframes,natoms,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], self.expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], self.expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), self.expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), self.expected_v.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_2frame_atm(self): @@ -158,18 +150,13 @@ def test_2frame_atm(self): expected_f = np.concatenate((self.expected_f, self.expected_f), axis = 0) expected_e = np.concatenate((self.expected_e, self.expected_e), axis = 0) expected_v = np.concatenate((self.expected_v, self.expected_v), axis = 0) - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), expected_v.ravel(), default_places) expected_se = np.sum(expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) class TestDeepPotANoPBC(unittest.TestCase) : @@ -200,14 +187,11 @@ def test_1frame(self): self.assertEqual(ff.shape, (nframes,natoms,3)) self.assertEqual(vv.shape, (nframes,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_1frame_atm(self): ee, ff, vv, ae, av = self.dp.eval(self.coords, self.box, self.atype, atomic = True) @@ -220,18 +204,13 @@ def test_1frame_atm(self): self.assertEqual(ae.shape, (nframes,natoms,1)) self.assertEqual(av.shape, (nframes,natoms,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], self.expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], self.expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), self.expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), self.expected_v.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_2frame_atm(self): @@ -249,18 +228,13 @@ def test_2frame_atm(self): expected_f = np.concatenate((self.expected_f, self.expected_f), axis = 0) expected_e = np.concatenate((self.expected_e, self.expected_e), axis = 0) expected_v = np.concatenate((self.expected_v, self.expected_v), axis = 0) - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), expected_v.ravel(), default_places) expected_se = np.sum(expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) class TestDeepPotALargeBoxNoPBC(unittest.TestCase) : @@ -291,14 +265,11 @@ def test_1frame(self): self.assertEqual(ff.shape, (nframes,natoms,3)) self.assertEqual(vv.shape, (nframes,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_1frame_atm(self): ee, ff, vv, ae, av = self.dp.eval(self.coords, self.box, self.atype, atomic = True) @@ -311,18 +282,13 @@ def test_1frame_atm(self): self.assertEqual(ae.shape, (nframes,natoms,1)) self.assertEqual(av.shape, (nframes,natoms,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], self.expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], self.expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), self.expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), self.expected_v.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_ase(self): from ase import Atoms @@ -334,9 +300,6 @@ def test_ase(self): ee = water.get_potential_energy() ff = water.get_forces() nframes = 1 - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) - + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) diff --git a/source/tests/test_deeppot_r.py b/source/tests/test_deeppot_r.py index c43a71677a..2a4ad62a83 100644 --- a/source/tests/test_deeppot_r.py +++ b/source/tests/test_deeppot_r.py @@ -59,14 +59,11 @@ def test_1frame(self): self.assertEqual(ff.shape, (nframes,natoms,3)) self.assertEqual(vv.shape, (nframes,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_1frame_atm(self): ee, ff, vv, ae, av = self.dp.eval(self.coords, self.box, self.atype, atomic = True) @@ -79,18 +76,13 @@ def test_1frame_atm(self): self.assertEqual(ae.shape, (nframes,natoms,1)) self.assertEqual(av.shape, (nframes,natoms,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], self.expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], self.expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), self.expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), self.expected_v.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_2frame_atm(self): @@ -109,18 +101,13 @@ def test_2frame_atm(self): expected_f = np.concatenate((self.expected_f, self.expected_f), axis = 0) expected_e = np.concatenate((self.expected_e, self.expected_e), axis = 0) expected_v = np.concatenate((self.expected_v, self.expected_v), axis = 0) - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), expected_v.ravel(), default_places) expected_se = np.sum(expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) class TestDeepPotRNoPBC(unittest.TestCase) : @@ -157,14 +144,11 @@ def test_1frame(self): self.assertEqual(ff.shape, (nframes,natoms,3)) self.assertEqual(vv.shape, (nframes,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_1frame_atm(self): ee, ff, vv, ae, av = self.dp.eval(self.coords, self.box, self.atype, atomic = True) @@ -177,18 +161,13 @@ def test_1frame_atm(self): self.assertEqual(ae.shape, (nframes,natoms,1)) self.assertEqual(av.shape, (nframes,natoms,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], self.expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], self.expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), self.expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), self.expected_v.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_2frame_atm(self): @@ -206,18 +185,13 @@ def test_2frame_atm(self): expected_f = np.concatenate((self.expected_f, self.expected_f), axis = 0) expected_e = np.concatenate((self.expected_e, self.expected_e), axis = 0) expected_v = np.concatenate((self.expected_v, self.expected_v), axis = 0) - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), expected_v.ravel(), default_places) expected_se = np.sum(expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) class TestDeepPotRLargeBoxNoPBC(unittest.TestCase) : @@ -254,14 +228,11 @@ def test_1frame(self): self.assertEqual(ff.shape, (nframes,natoms,3)) self.assertEqual(vv.shape, (nframes,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_1frame_atm(self): ee, ff, vv, ae, av = self.dp.eval(self.coords, self.box, self.atype, atomic = True) @@ -274,17 +245,12 @@ def test_1frame_atm(self): self.assertEqual(ae.shape, (nframes,natoms,1)) self.assertEqual(av.shape, (nframes,natoms,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], self.expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], self.expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), self.expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), self.expected_v.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) diff --git a/source/tests/test_descrpt_nonsmth.py b/source/tests/test_descrpt_nonsmth.py index decb18e053..01fdbcfe85 100644 --- a/source/tests/test_descrpt_nonsmth.py +++ b/source/tests/test_descrpt_nonsmth.py @@ -216,12 +216,8 @@ def test_pbc(self): inter1.tnatoms: inter1.natoms}) self.assertAlmostEqual(e0[0], e1[0]) - for ii in range(f0[0].size): - # print(ii) - self.assertAlmostEqual(f0[0][ii], f1[0][ii]) - for ii in range(v0[0].size): - # print(ii) - self.assertAlmostEqual(v0[0][ii], v1[0][ii]) + np.testing.assert_almost_equal(f0[0], f1[0]) + np.testing.assert_almost_equal(v0[0], v1[0]) def test_pbc_small_box(self): data0 = Data() @@ -257,12 +253,8 @@ def test_pbc_small_box(self): inter1.tnatoms: inter1.natoms}) self.assertAlmostEqual(e0[0], e1[0]) - for ii in range(f0[0].size): - # print(ii) - self.assertAlmostEqual(f0[0][ii], f1[0][ii]) - for ii in range(v0[0].size): - # print(ii) - self.assertAlmostEqual(v0[0][ii], v1[0][ii]) + np.testing.assert_almost_equal(f0[0], f1[0]) + np.testing.assert_almost_equal(v0[0], v1[0]) if __name__ == '__main__': diff --git a/source/tests/test_descrpt_se_a_type.py b/source/tests/test_descrpt_se_a_type.py index c6f3cb5a19..fded177b66 100644 --- a/source/tests/test_descrpt_se_a_type.py +++ b/source/tests/test_descrpt_se_a_type.py @@ -124,8 +124,7 @@ def test_descriptor_two_sides(self): 0.0004482204892297628,-0.00016887749501640607,-0.00016887749501640607,6.364643102775375e-05,-0.001181345877677835,0.0004452029242063362,-0.0008941636427724908,0.0003369586197174627,0.0004677878512312651,-0.00017625260641095753] places = 10 - for ii in range(model_dout.size) : - self.assertAlmostEqual(model_dout[ii], ref_dout[ii], places = places) + np.testing.assert_almost_equal(model_dout, ref_dout, places) def test_descriptor_one_side(self): @@ -234,8 +233,7 @@ def test_descriptor_one_side(self): -0.0015760302086346792,-0.0012475134925387294,-0.001041074331192672,-0.0008239586048523492,0.0015319673563669856,0.0012124704278707746] places = 10 - for ii in range(model_dout.size) : - self.assertAlmostEqual(model_dout[ii], ref_dout[ii], places = places) + np.testing.assert_almost_equal(model_dout, ref_dout, places) diff --git a/source/tests/test_descrpt_se_r.py b/source/tests/test_descrpt_se_r.py index bf002736b0..e2cc6360be 100644 --- a/source/tests/test_descrpt_se_r.py +++ b/source/tests/test_descrpt_se_r.py @@ -196,12 +196,8 @@ def test_pbc(self): inter1.tnatoms: inter1.natoms}) self.assertAlmostEqual(e0[0], e1[0]) - for ii in range(f0[0].size): - # print(ii) - self.assertAlmostEqual(f0[0][ii], f1[0][ii]) - for ii in range(v0[0].size): - # print(ii) - self.assertAlmostEqual(v0[0][ii], v1[0][ii]) + np.testing.assert_almost_equal(f0[0], f1[0]) + np.testing.assert_almost_equal(v0[0], v1[0]) def test_pbc_small_box(self): @@ -238,12 +234,8 @@ def test_pbc_small_box(self): inter1.tnatoms: inter1.natoms}) self.assertAlmostEqual(e0[0], e1[0]) - for ii in range(f0[0].size): - # print(ii) - self.assertAlmostEqual(f0[0][ii], f1[0][ii]) - for ii in range(v0[0].size): - # print(ii) - self.assertAlmostEqual(v0[0][ii], v1[0][ii]) + np.testing.assert_almost_equal(f0[0], f1[0]) + np.testing.assert_almost_equal(v0[0], v1[0]) if __name__ == '__main__': diff --git a/source/tests/test_descrpt_sea_ef_rot.py b/source/tests/test_descrpt_sea_ef_rot.py index f172ec2771..e96951b275 100644 --- a/source/tests/test_descrpt_sea_ef_rot.py +++ b/source/tests/test_descrpt_sea_ef_rot.py @@ -353,10 +353,9 @@ def test_rot_field_corot(self, suffix=''): self.efield: new_defield, self.tnatoms: self.natoms}) - for ii in range(0, self.natoms[0]): - self.assertAlmostEqual(p_ae0[ii], p_ae1[ii]) - self.assertAlmostEqual(v_ae0[ii], v_ae1[ii]) - self.assertAlmostEqual(ae0[ii], ae1[ii]) + np.testing.assert_almost_equal(p_ae0, p_ae1) + np.testing.assert_almost_equal(v_ae0, v_ae1) + np.testing.assert_almost_equal(ae0, ae1) diff --git a/source/tests/test_descrpt_smooth.py b/source/tests/test_descrpt_smooth.py index adb5beb354..00dbbd61d0 100644 --- a/source/tests/test_descrpt_smooth.py +++ b/source/tests/test_descrpt_smooth.py @@ -207,12 +207,8 @@ def test_pbc(self): inter1.tnatoms: inter1.natoms}) self.assertAlmostEqual(e0[0], e1[0]) - for ii in range(f0[0].size): - # print(ii) - self.assertAlmostEqual(f0[0][ii], f1[0][ii]) - for ii in range(v0[0].size): - # print(ii) - self.assertAlmostEqual(v0[0][ii], v1[0][ii]) + np.testing.assert_almost_equal(f0[0], f1[0]) + np.testing.assert_almost_equal(v0[0], v1[0]) def test_pbc_small_box(self): data0 = Data() @@ -248,12 +244,8 @@ def test_pbc_small_box(self): inter1.tnatoms: inter1.natoms}) self.assertAlmostEqual(e0[0], e1[0]) - for ii in range(f0[0].size): - # print(ii) - self.assertAlmostEqual(f0[0][ii], f1[0][ii]) - for ii in range(v0[0].size): - # print(ii) - self.assertAlmostEqual(v0[0][ii], v1[0][ii]) + np.testing.assert_almost_equal(f0[0], f1[0]) + np.testing.assert_almost_equal(v0[0], v1[0]) if __name__ == '__main__': diff --git a/source/tests/test_dipole_se_a.py b/source/tests/test_dipole_se_a.py index 3687ba47f2..42a615300a 100644 --- a/source/tests/test_dipole_se_a.py +++ b/source/tests/test_dipole_se_a.py @@ -98,15 +98,13 @@ def test_model(self): refp = [1.616802262298876514e+01,9.809535439521079425e+00,3.572312180768947854e-01,1.336308874095981203e+00,1.057908563208963848e+01,-5.999602350098874881e-01] places = 10 - for ii in range(p.size) : - self.assertAlmostEqual(p[ii], refp[ii], places = places) + np.testing.assert_almost_equal(p, refp, places) gp = gp.reshape([-1]) refgp = np.array(refp).reshape(-1, 3).sum(0) places = 9 - for ii in range(gp.size) : - self.assertAlmostEqual(gp[ii], refgp[ii], places = places) + np.testing.assert_almost_equal(gp, refgp, places) # make sure only one frame is used feed_dict_single = {t_prop_c: test_data['prop_c'], @@ -140,11 +138,8 @@ def test_model(self): @ box0.reshape(3,3)).reshape(-1) delta = 1e-5 - for ii in range(pf.size) : - self.assertAlmostEqual(pf[ii], fdf[ii], delta = delta) - for ii in range(pv.size) : - self.assertAlmostEqual(pv[ii], fdv[ii], delta = delta) + np.testing.assert_allclose(pf, fdf, delta) + np.testing.assert_allclose(pv, fdv, delta) # make sure atomic virial sum to virial places = 10 - for ii in range(pv.size) : - self.assertAlmostEqual(pv[ii], spv[ii], places = places) \ No newline at end of file + np.testing.assert_almost_equal(pv, spv, places) \ No newline at end of file diff --git a/source/tests/test_dipolecharge.py b/source/tests/test_dipolecharge.py index ccda444a32..a36919baec 100644 --- a/source/tests/test_dipolecharge.py +++ b/source/tests/test_dipolecharge.py @@ -76,12 +76,9 @@ def test_1frame(self): ee = ee.reshape([-1]) ff = ff.reshape([-1]) vv = vv.reshape([-1]) - for ii in range(ee.size): - self.assertAlmostEqual(ee[ii], self.expected_e[ii]) - for ii in range(ff.size): - self.assertAlmostEqual(ff[ii], self.expected_f[ii]) - for ii in range(vv.size): - self.assertAlmostEqual(vv[ii], self.expected_v[ii]) + np.testing.assert_almost_equal(ee, self.expected_e) + np.testing.assert_almost_equal(ff, self.expected_f) + np.testing.assert_almost_equal(vv, self.expected_v) def test_2frame(self): nframes = 2 @@ -103,10 +100,7 @@ def test_2frame(self): ee = ee.reshape([-1]) ff = ff.reshape([-1]) vv = vv.reshape([-1]) - for ii in range(ee.size): - self.assertAlmostEqual(ee[ii], self.expected_e[ii]) - for ii in range(ff.size): - self.assertAlmostEqual(ff[ii], self.expected_f[ii]) - for ii in range(vv.size): - self.assertAlmostEqual(vv[ii], self.expected_v[ii]) + np.testing.assert_almost_equal(ee, self.expected_e) + np.testing.assert_almost_equal(ff, self.expected_f) + np.testing.assert_almost_equal(vv, self.expected_v) diff --git a/source/tests/test_embedding_net.py b/source/tests/test_embedding_net.py index 03084a8267..d1930524f7 100644 --- a/source/tests/test_embedding_net.py +++ b/source/tests/test_embedding_net.py @@ -32,9 +32,7 @@ def test_enlarger_net(self): refout = [[-0.1482171, -0.14177827, -0.76181204, 0.21266767], [-0.27800543, -0.08974353, -0.78784335, 0.3485518 ], [-0.36744368, -0.06285603, -0.80749876, 0.4347974 ]] - for ii in range(self.ndata): - for jj in range(network_size[-1]): - self.assertAlmostEqual(refout[ii][jj], myout[ii][jj], places = self.places) + np.testing.assert_almost_equal(refout, myout, self.places) def test_enlarger_net_1(self): @@ -50,9 +48,7 @@ def test_enlarger_net_1(self): refout = [[ 0.10842905, -0.61623145, -1.46738788, -0.01921788], [ 0.09376136, -0.75526936, -1.64995884, 0.01076112], [ 0.1033177, -0.8911794, -1.75530172, 0.00653156]] - for ii in range(self.ndata): - for jj in range(network_size[-1]): - self.assertAlmostEqual(refout[ii][jj], myout[ii][jj], places = self.places) + np.testing.assert_almost_equal(refout, myout, self.places) def test_enlarger_net_1_idt(self): network_size = [4, 4] @@ -68,9 +64,7 @@ def test_enlarger_net_1_idt(self): refout = [[ 0.10839754, -0.6161336, -1.46673253, -0.01927138], [ 0.09370214, -0.75516888, -1.64927868, 0.01067603], [ 0.10323835, -0.89107102, -1.75460243, 0.00642493]] - for ii in range(self.ndata): - for jj in range(network_size[-1]): - self.assertAlmostEqual(refout[ii][jj], myout[ii][jj], places = self.places) + np.testing.assert_almost_equal(refout, myout, self.places) def test_enlarger_net_2(self): network_size = [2, 4] @@ -85,9 +79,7 @@ def test_enlarger_net_2(self): refout = [[ 0.24023149, -0.66311811, -0.50951819, -0.36873654], [ 2.00858313, -0.05971232, 0.52272395, -0.12604478], [ 3.39365063, 0.63492697, 1.5780069, 0.46445682]] - for ii in range(self.ndata): - for jj in range(network_size[-1]): - self.assertAlmostEqual(refout[ii][jj], myout[ii][jj], places = self.places) + np.testing.assert_almost_equal(refout, myout, self.places) def test_enlarger_net_2(self): @@ -104,9 +96,7 @@ def test_enlarger_net_2(self): refout = [[ 0.2403889, -0.66290763, -0.50883586, -0.36869913], [ 2.00891479, -0.05936574, 0.52351633, -0.12579749], [ 3.3940202, 0.63538459, 1.57887697, 0.46486689]] - for ii in range(self.ndata): - for jj in range(network_size[-1]): - self.assertAlmostEqual(refout[ii][jj], myout[ii][jj], places = self.places) + np.testing.assert_almost_equal(refout, myout, self.places) diff --git a/source/tests/test_ewald.py b/source/tests/test_ewald.py index f4913db36f..236c295b91 100644 --- a/source/tests/test_ewald.py +++ b/source/tests/test_ewald.py @@ -76,20 +76,15 @@ def test_py_interface(self): }) er = EwaldRecp(self.ewald_h, self.ewald_beta) e1, f1, v1 = er.eval(self.dcoord, self.dcharge, self.dbox) - for ff in range(self.nframes): - self.assertAlmostEqual(e[ff], e1[ff], - places = places, - msg = "frame %d energy failed" % (ff)) - for idx in range(self.natoms): - for dd in range(3): - self.assertAlmostEqual(f[ff, idx*3+dd], f1[ff,idx*3+dd], - places = places, - msg = "frame %d force component [%d,%d] failed" % (ff, idx, dd)) - for d0 in range(3): - for d1 in range(3): - self.assertAlmostEqual(v[ff, d0*3+d1], v[ff,d0*3+d1], - places = places, - msg = "frame %d virial component [%d,%d] failed" % (ff, d0, d1)) + np.testing.assert_almost_equal(e, e1, + places, + err_msg = "energy failed") + np.testing.assert_almost_equal(f, f1, + places, + err_msg = "force component failed") + np.testing.assert_almost_equal(v, v, + places, + err_msg = "virial component failed") @@ -129,10 +124,9 @@ def test_force(self): self.nloc: [self.natoms], }) c_force = -(energyp[0] - energym[0]) / (2*hh) - for ff in range(self.nframes): - self.assertAlmostEqual(c_force[ff], force[ff,idx*3+dd], - places = places, - msg = "frame %d force component [%d,%d] failed" % (ff, idx, dd)) + np.testing.assert_almost_equal(c_force, force[:,idx*3+dd], + places, + err_msg = "force component [%d,%d] failed" % (idx, dd)) def test_virial(self): @@ -204,12 +198,9 @@ def test_virial(self): # # print(0.5 * (t_esti[0] + t_esti[0].T) - virial[0].reshape([3,3])) # print(0.5 * (t_esti[0] + t_esti[0]) - virial[0].reshape([3,3])) # print(0.5 * (t_esti[0] + t_esti[0].T) - virial[0].reshape([3,3])) - for ff in range(self.nframes): - for ii in range(3): - for jj in range(3): - self.assertAlmostEqual(t_esti[ff][ii][jj], virial[ff,ii*3+jj], - places = places, - msg = "frame %d virial component [%d,%d] failed" % (ff, ii, jj)) + np.testing.assert_almost_equal(t_esti.ravel(), virial.ravel(), + places, + err_msg = "virial component failed") diff --git a/source/tests/test_fitting_ener_type.py b/source/tests/test_fitting_ener_type.py index 25b85391e2..1eb1002147 100644 --- a/source/tests/test_fitting_ener_type.py +++ b/source/tests/test_fitting_ener_type.py @@ -109,7 +109,6 @@ def test_fitting(self): places = 10 - for ii in range(pred_atom_ener.size) : - self.assertAlmostEqual(pred_atom_ener[ii], ref_atom_ener[ii], places = places) + np.testing.assert_almost_equal(pred_atom_ener, ref_atom_ener, places) diff --git a/source/tests/test_fitting_stat.py b/source/tests/test_fitting_stat.py index a17bef6453..970e30da4b 100644 --- a/source/tests/test_fitting_stat.py +++ b/source/tests/test_fitting_stat.py @@ -81,8 +81,7 @@ def test (self) : arefa, arefs = _brute_aparam(all_data, len(avgs)) fitting.compute_input_stats(all_data, protection = 1e-2) # print(frefa, frefs) - for ii in range(len(avgs)): - self.assertAlmostEqual(frefa[ii], fitting.fparam_avg[ii]) - self.assertAlmostEqual(frefs[ii], fitting.fparam_std[ii]) - self.assertAlmostEqual(arefa[ii], fitting.aparam_avg[ii]) - self.assertAlmostEqual(arefs[ii], fitting.aparam_std[ii]) + np.testing.assert_almost_equal(frefa, fitting.fparam_avg) + np.testing.assert_almost_equal(frefs, fitting.fparam_std) + np.testing.assert_almost_equal(arefa, fitting.aparam_avg) + np.testing.assert_almost_equal(arefs, fitting.aparam_std) diff --git a/source/tests/test_gen_stat_data.py b/source/tests/test_gen_stat_data.py index b7391f7070..f8c990b756 100644 --- a/source/tests/test_gen_stat_data.py +++ b/source/tests/test_gen_stat_data.py @@ -41,10 +41,7 @@ def tearDown(self): shutil.rmtree('system_1') def _comp_data(self, d0, d1) : - for ii in range(d0.shape[0]): - for jj in range(d0.shape[1]): - for kk in range(d0.shape[2]): - self.assertAlmostEqual(d0[ii][jj][kk], d1[ii][jj][kk]) + np.testing.assert_almost_equal(d0, d1) def test_merge_all_stat(self): dp_random.seed(0) @@ -58,13 +55,13 @@ def test_merge_all_stat(self): 5, 10, 1.0) - data1.add('force', 3, atomic = True, must = True) + data1.add('energy', 1, must = True) dp_random.seed(0) data2 = DeepmdDataSystem(['system_0', 'system_1'], 5, 10, 1.0) - data2.add('force', 3, atomic = True, must = True) + data2.add('energy', 1, must = True) dp_random.seed(0) all_stat_0 = make_stat_input(data0, 10, merge_sys = False) @@ -119,5 +116,4 @@ def test_ener_shift(self): ener_shift0 = data.compute_energy_shift(rcond = 1) all_stat = make_stat_input(data, 4, merge_sys = False) ener_shift1 = EnerFitting._compute_output_stats(all_stat, rcond = 1) - for ii in range(len(ener_shift0)): - self.assertAlmostEqual(ener_shift0[ii], ener_shift1[ii]) + np.testing.assert_almost_equal(ener_shift0, ener_shift1) diff --git a/source/tests/test_model_compression.py b/source/tests/test_model_compression.py index 50fbb9e107..b183c6bde8 100644 --- a/source/tests/test_model_compression.py +++ b/source/tests/test_model_compression.py @@ -89,12 +89,9 @@ def test_1frame(self): self.assertEqual(ff1.shape, (nframes,natoms,3)) self.assertEqual(vv1.shape, (nframes,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_1frame_atm(self): ee0, ff0, vv0, ae0, av0 = self.dp_original.eval(self.coords, self.box, self.atype, atomic = True) @@ -113,16 +110,11 @@ def test_1frame_atm(self): self.assertEqual(ae1.shape, (nframes,natoms,1)) self.assertEqual(av1.shape, (nframes,natoms,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(ae0.size): - self.assertAlmostEqual(ae0.reshape([-1])[ii], ae1.reshape([-1])[ii], places = default_places) - for ii in range(av0.size): - self.assertAlmostEqual(av0.reshape([-1])[ii], av1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ae0, ae1, default_places) + np.testing.assert_almost_equal(av0, av1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_2frame_atm(self): coords2 = np.concatenate((self.coords, self.coords)) @@ -144,16 +136,11 @@ def test_2frame_atm(self): self.assertEqual(av1.shape, (nframes,natoms,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(ae0.size): - self.assertAlmostEqual(ae0.reshape([-1])[ii], ae1.reshape([-1])[ii], places = default_places) - for ii in range(av0.size): - self.assertAlmostEqual(av0.reshape([-1])[ii], av1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ae0, ae1, default_places) + np.testing.assert_almost_equal(av0, av1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) class TestDeepPotANoPBC(unittest.TestCase) : @@ -183,12 +170,9 @@ def test_1frame(self): self.assertEqual(ff1.shape, (nframes,natoms,3)) self.assertEqual(vv1.shape, (nframes,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_1frame_atm(self): ee0, ff0, vv0, ae0, av0 = self.dp_original.eval(self.coords, self.box, self.atype, atomic = True) @@ -207,16 +191,11 @@ def test_1frame_atm(self): self.assertEqual(ae1.shape, (nframes,natoms,1)) self.assertEqual(av1.shape, (nframes,natoms,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(ae0.size): - self.assertAlmostEqual(ae0.reshape([-1])[ii], ae1.reshape([-1])[ii], places = default_places) - for ii in range(av0.size): - self.assertAlmostEqual(av0.reshape([-1])[ii], av1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ae0, ae1, default_places) + np.testing.assert_almost_equal(av0, av1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_2frame_atm(self): coords2 = np.concatenate((self.coords, self.coords)) @@ -237,16 +216,11 @@ def test_2frame_atm(self): self.assertEqual(av1.shape, (nframes,natoms,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(ae0.size): - self.assertAlmostEqual(ae0.reshape([-1])[ii], ae1.reshape([-1])[ii], places = default_places) - for ii in range(av0.size): - self.assertAlmostEqual(av0.reshape([-1])[ii], av1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ae0, ae1, default_places) + np.testing.assert_almost_equal(av0, av1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) class TestDeepPotALargeBoxNoPBC(unittest.TestCase) : @@ -276,12 +250,9 @@ def test_1frame(self): self.assertEqual(ff1.shape, (nframes,natoms,3)) self.assertEqual(vv1.shape, (nframes,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_1frame_atm(self): ee0, ff0, vv0, ae0, av0 = self.dp_original.eval(self.coords, self.box, self.atype, atomic = True) @@ -300,16 +271,11 @@ def test_1frame_atm(self): self.assertEqual(ae1.shape, (nframes,natoms,1)) self.assertEqual(av1.shape, (nframes,natoms,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(ae0.size): - self.assertAlmostEqual(ae0.reshape([-1])[ii], ae1.reshape([-1])[ii], places = default_places) - for ii in range(av0.size): - self.assertAlmostEqual(av0.reshape([-1])[ii], av1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ae0, ae1, default_places) + np.testing.assert_almost_equal(av0, av1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_ase(self): from ase import Atoms @@ -327,10 +293,8 @@ def test_ase(self): ee1 = water1.get_potential_energy() ff1 = water1.get_forces() nframes = 1 - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) class TestDeepPotAPBCExcludeTypes(unittest.TestCase) : @classmethod @@ -385,12 +349,9 @@ def test_1frame(self): self.assertEqual(ff1.shape, (nframes,natoms,3)) self.assertEqual(vv1.shape, (nframes,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_1frame_atm(self): ee0, ff0, vv0, ae0, av0 = self.dp_original.eval(self.coords, self.box, self.atype, atomic = True) @@ -409,16 +370,11 @@ def test_1frame_atm(self): self.assertEqual(ae1.shape, (nframes,natoms,1)) self.assertEqual(av1.shape, (nframes,natoms,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(ae0.size): - self.assertAlmostEqual(ae0.reshape([-1])[ii], ae1.reshape([-1])[ii], places = default_places) - for ii in range(av0.size): - self.assertAlmostEqual(av0.reshape([-1])[ii], av1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ae0, ae1, default_places) + np.testing.assert_almost_equal(av0, av1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) def test_2frame_atm(self): coords2 = np.concatenate((self.coords, self.coords)) @@ -440,13 +396,8 @@ def test_2frame_atm(self): self.assertEqual(av1.shape, (nframes,natoms,9)) # check values - for ii in range(ff0.size): - self.assertAlmostEqual(ff0.reshape([-1])[ii], ff1.reshape([-1])[ii], places = default_places) - for ii in range(ae0.size): - self.assertAlmostEqual(ae0.reshape([-1])[ii], ae1.reshape([-1])[ii], places = default_places) - for ii in range(av0.size): - self.assertAlmostEqual(av0.reshape([-1])[ii], av1.reshape([-1])[ii], places = default_places) - for ii in range(nframes): - self.assertAlmostEqual(ee0.reshape([-1])[ii], ee1.reshape([-1])[ii], places = default_places) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv0.reshape([-1])[ii], vv1.reshape([-1])[ii], places = default_places) \ No newline at end of file + np.testing.assert_almost_equal(ff0, ff1, default_places) + np.testing.assert_almost_equal(ae0, ae1, default_places) + np.testing.assert_almost_equal(av0, av1, default_places) + np.testing.assert_almost_equal(ee0, ee1, default_places) + np.testing.assert_almost_equal(vv0, vv1, default_places) \ No newline at end of file diff --git a/source/tests/test_model_devi.py b/source/tests/test_model_devi.py index 4d5414cea8..6843874d57 100644 --- a/source/tests/test_model_devi.py +++ b/source/tests/test_model_devi.py @@ -38,9 +38,8 @@ def test_calc_model_devi(self): fname=self.output) self.assertAlmostEqual(model_devi[0][0], 0) self.assertAlmostEqual(model_devi[1][0], self.freq) - for ii in range(1, 7): - self.assertAlmostEqual(model_devi[0][ii], self.expect[ii]) - self.assertAlmostEqual(model_devi[0][ii], model_devi[1][ii]) + np.testing.assert_almost_equal(model_devi[0][1:7], self.expect[1:7], 6) + np.testing.assert_almost_equal(model_devi[0][1:7], model_devi[1][1:7], 6) self.assertTrue(os.path.isfile(self.output)) def tearDown(self): diff --git a/source/tests/test_model_loc_frame.py b/source/tests/test_model_loc_frame.py index 3ffce1bf41..5e0399fbb7 100644 --- a/source/tests/test_model_loc_frame.py +++ b/source/tests/test_model_loc_frame.py @@ -112,10 +112,7 @@ def test_model(self): refv = np.reshape(refv, [-1]) places = 10 - for ii in range(e.size) : - self.assertAlmostEqual(e[ii], refe[ii], places = places) - for ii in range(f.size) : - self.assertAlmostEqual(f[ii], reff[ii], places = places) - for ii in range(v.size) : - self.assertAlmostEqual(v[ii], refv[ii], places = places) + np.testing.assert_almost_equal(e, refe, places) + np.testing.assert_almost_equal(f, reff, places) + np.testing.assert_almost_equal(v, refv, places) diff --git a/source/tests/test_model_se_a.py b/source/tests/test_model_se_a.py index e8b12c8553..0dce8f1b28 100644 --- a/source/tests/test_model_se_a.py +++ b/source/tests/test_model_se_a.py @@ -205,9 +205,6 @@ def test_model(self): refv = np.reshape(refv, [-1]) places = 10 - for ii in range(e.size) : - self.assertAlmostEqual(e[ii], refe[ii], places = places) - for ii in range(f.size) : - self.assertAlmostEqual(f[ii], reff[ii], places = places) - for ii in range(v.size) : - self.assertAlmostEqual(v[ii], refv[ii], places = places) + np.testing.assert_almost_equal(e, refe, places) + np.testing.assert_almost_equal(f, reff, places) + np.testing.assert_almost_equal(v, refv, places) diff --git a/source/tests/test_model_se_a_aparam.py b/source/tests/test_model_se_a_aparam.py index 9c9847c242..f9a6817092 100644 --- a/source/tests/test_model_se_a_aparam.py +++ b/source/tests/test_model_se_a_aparam.py @@ -111,9 +111,6 @@ def test_model(self): refv = np.reshape(refv, [-1]) places = 10 - for ii in range(e.size) : - self.assertAlmostEqual(e[ii], refe[ii], places = places) - for ii in range(f.size) : - self.assertAlmostEqual(f[ii], reff[ii], places = places) - for ii in range(v.size) : - self.assertAlmostEqual(v[ii], refv[ii], places = places) + np.testing.assert_almost_equal(e, refe, places) + np.testing.assert_almost_equal(f, reff, places) + np.testing.assert_almost_equal(v, refv, places) diff --git a/source/tests/test_model_se_a_fparam.py b/source/tests/test_model_se_a_fparam.py index 23b0da569b..469a5c429b 100644 --- a/source/tests/test_model_se_a_fparam.py +++ b/source/tests/test_model_se_a_fparam.py @@ -112,9 +112,6 @@ def test_model(self): refv = np.reshape(refv, [-1]) places = 10 - for ii in range(e.size) : - self.assertAlmostEqual(e[ii], refe[ii], places = places) - for ii in range(f.size) : - self.assertAlmostEqual(f[ii], reff[ii], places = places) - for ii in range(v.size) : - self.assertAlmostEqual(v[ii], refv[ii], places = places) + np.testing.assert_almost_equal(e, refe, places) + np.testing.assert_almost_equal(f, reff, places) + np.testing.assert_almost_equal(v, refv, places) diff --git a/source/tests/test_model_se_a_srtab.py b/source/tests/test_model_se_a_srtab.py index 4b87fc0bb4..acfe62ce1e 100644 --- a/source/tests/test_model_se_a_srtab.py +++ b/source/tests/test_model_se_a_srtab.py @@ -134,9 +134,6 @@ def test_model(self): refv = np.reshape(refv, [-1]) places = 10 - for ii in range(e.size) : - self.assertAlmostEqual(e[ii], refe[ii], places = places) - for ii in range(f.size) : - self.assertAlmostEqual(f[ii], reff[ii], places = places) - for ii in range(v.size) : - self.assertAlmostEqual(v[ii], refv[ii], places = places) + np.testing.assert_almost_equal(e, refe, places) + np.testing.assert_almost_equal(f, reff, places) + np.testing.assert_almost_equal(v, refv, places) diff --git a/source/tests/test_model_se_a_type.py b/source/tests/test_model_se_a_type.py index 11979108b4..6e80839d75 100644 --- a/source/tests/test_model_se_a_type.py +++ b/source/tests/test_model_se_a_type.py @@ -126,9 +126,6 @@ def test_model(self): refv = np.reshape(refv, [-1]) places = 10 - for ii in range(e.size) : - self.assertAlmostEqual(e[ii], refe[ii], places = places) - for ii in range(f.size) : - self.assertAlmostEqual(f[ii], reff[ii], places = places) - for ii in range(v.size) : - self.assertAlmostEqual(v[ii], refv[ii], places = places) + np.testing.assert_almost_equal(e, refe, places) + np.testing.assert_almost_equal(f, reff, places) + np.testing.assert_almost_equal(v, refv, places) diff --git a/source/tests/test_model_se_t.py b/source/tests/test_model_se_t.py index 48fffd76b0..fabbe667a8 100644 --- a/source/tests/test_model_se_t.py +++ b/source/tests/test_model_se_t.py @@ -108,9 +108,6 @@ def test_model(self): refv = np.reshape(refv, [-1]) places = 6 - for ii in range(e.size) : - self.assertAlmostEqual(e[ii], refe[ii], places = places) - for ii in range(f.size) : - self.assertAlmostEqual(f[ii], reff[ii], places = places) - for ii in range(v.size) : - self.assertAlmostEqual(v[ii], refv[ii], places = places) + np.testing.assert_almost_equal(e, refe, places) + np.testing.assert_almost_equal(f, reff, places) + np.testing.assert_almost_equal(v, refv, places) diff --git a/source/tests/test_polar_se_a.py b/source/tests/test_polar_se_a.py index 78da154864..ee298bfb8b 100644 --- a/source/tests/test_polar_se_a.py +++ b/source/tests/test_polar_se_a.py @@ -97,15 +97,13 @@ def test_model(self): refp = [3.39695248e+01, 2.16564043e+01, 8.18501479e-01, 2.16564043e+01, 1.38211789e+01, 5.22775159e-01, 8.18501479e-01, 5.22775159e-01, 1.97847218e-02, 8.08467431e-01, 3.42081126e+00, -2.01072261e-01, 3.42081126e+00, 1.54924596e+01, -9.06153697e-01, -2.01072261e-01, -9.06153697e-01, 5.30193262e-02] places = 6 - for ii in range(p.size) : - self.assertAlmostEqual(p[ii], refp[ii], places = places) + np.testing.assert_almost_equal(p, refp, places) gp = gp.reshape([-1]) refgp = np.array(refp).reshape(-1, 9).sum(0) places = 5 - for ii in range(gp.size) : - self.assertAlmostEqual(gp[ii], refgp[ii], places = places) + np.testing.assert_almost_equal(gp, refgp, places) # make sure only one frame is used feed_dict_single = {t_prop_c: test_data['prop_c'], @@ -139,11 +137,8 @@ def test_model(self): @ box0.reshape(3,3)).reshape(-1) delta = 1e-4 - for ii in range(pf.size) : - self.assertAlmostEqual(pf[ii], fdf[ii], delta = delta) - for ii in range(pv.size) : - self.assertAlmostEqual(pv[ii], fdv[ii], delta = delta) + np.testing.assert_allclose(pf, fdf, delta) + np.testing.assert_allclose(pv, fdv, delta) # make sure atomic virial sum to virial places = 10 - for ii in range(pv.size) : - self.assertAlmostEqual(pv[ii], spv[ii], places = places) + np.testing.assert_almost_equal(pv, spv, places) diff --git a/source/tests/test_prod_env_mat.py b/source/tests/test_prod_env_mat.py index 4b60da39d9..82fe3e18eb 100644 --- a/source/tests/test_prod_env_mat.py +++ b/source/tests/test_prod_env_mat.py @@ -91,8 +91,7 @@ def test_pbc_self_built_nlist(self): self.assertEqual(drij.shape, (self.nframes, self.nloc*self.nnei*3)) self.assertEqual(dnlist.shape, (self.nframes, self.nloc*self.nnei)) for ff in range(self.nframes): - for ii in range(self.nloc*self.ndescrpt): - self.assertAlmostEqual(dem[ff][ii], self.pbc_expected_output[ii], places=5) + np.testing.assert_almost_equal(dem[ff], self.pbc_expected_output, 5) def test_pbc_self_built_nlist_deriv(self): hh = 1e-4 @@ -142,8 +141,7 @@ def test_nopbc_self_built_nlist(self): self.assertEqual(drij.shape, (self.nframes, self.nloc*self.nnei*3)) self.assertEqual(dnlist.shape, (self.nframes, self.nloc*self.nnei)) for ff in range(self.nframes): - for ii in range(self.nloc*self.ndescrpt): - self.assertAlmostEqual(dem[ff][ii], self.nopbc_expected_output[ii], places=5) + np.testing.assert_almost_equal(dem[ff], self.nopbc_expected_output, 5) def test_nopbc_self_built_nlist_deriv(self): diff --git a/source/tests/test_prod_force.py b/source/tests/test_prod_force.py index 4135ee0e2e..c0aaa29ea2 100644 --- a/source/tests/test_prod_force.py +++ b/source/tests/test_prod_force.py @@ -103,5 +103,4 @@ def test_prod_force(self): ) self.assertEqual(dforce.shape, (self.nframes, self.nall*3)) for ff in range(self.nframes): - for ii in range(self.nall*3): - self.assertAlmostEqual(dforce[ff][ii], self.expected_force[ii], places=5) + np.testing.assert_almost_equal(dforce[ff], self.expected_force, 5) diff --git a/source/tests/test_prod_force_grad.py b/source/tests/test_prod_force_grad.py index 8b8ad74ed6..71a95380f0 100644 --- a/source/tests/test_prod_force_grad.py +++ b/source/tests/test_prod_force_grad.py @@ -105,5 +105,4 @@ def test_prod_force_grad(self): ) self.assertEqual(dgrad_net.shape, (self.nframes, self.nloc*self.ndescrpt)) for ff in range(self.nframes): - for ii in range(self.nloc*self.ndescrpt): - self.assertAlmostEqual(dgrad_net[ff][ii], self.expected_grad_net[ii], places=5) + np.testing.assert_almost_equal(dgrad_net[ff], self.expected_grad_net, 5) diff --git a/source/tests/test_prod_virial.py b/source/tests/test_prod_virial.py index 2a11f0acfd..691a8a652f 100644 --- a/source/tests/test_prod_virial.py +++ b/source/tests/test_prod_virial.py @@ -106,7 +106,5 @@ def test_prod_virial(self): self.assertEqual(dvirial.shape, (self.nframes, 9)) self.assertEqual(datom_virial.shape, (self.nframes, self.nall*9)) for ff in range(self.nframes): - for ii in range(9): - self.assertAlmostEqual(dvirial[ff][ii], self.expected_virial[ii], places=5) - for ii in range(self.nall*9): - self.assertAlmostEqual(datom_virial[ff][ii], self.expected_atom_virial[ii], places=5) + np.testing.assert_almost_equal(dvirial[ff], self.expected_virial, 5) + np.testing.assert_almost_equal(datom_virial[ff], self.expected_atom_virial, 5) diff --git a/source/tests/test_prod_virial_grad.py b/source/tests/test_prod_virial_grad.py index 2ca9071a56..6217fa8600 100644 --- a/source/tests/test_prod_virial_grad.py +++ b/source/tests/test_prod_virial_grad.py @@ -113,5 +113,4 @@ def test_prod_virial_grad(self): ) self.assertEqual(dgrad_net.shape, (self.nframes, self.nloc*self.ndescrpt)) for ff in range(self.nframes): - for ii in range(self.nloc*self.ndescrpt): - self.assertAlmostEqual(dgrad_net[ff][ii], self.expected_grad_net[ii], places=5) + np.testing.assert_almost_equal(dgrad_net[ff], self.expected_grad_net, 5) diff --git a/source/tests/test_tabulate.py b/source/tests/test_tabulate.py index ce26c4e3e6..341850e68c 100644 --- a/source/tests/test_tabulate.py +++ b/source/tests/test_tabulate.py @@ -22,9 +22,7 @@ def test_op_tanh(self): [5.492686739421748753e-03, 5.754985286040992763e-03, 4.493113544969218158e-03, 3.107638130764600777e-03]]) places = 18 - for ii in range(dy_array.shape[0]): - for jj in range(dy_array.shape[1]): - self.assertAlmostEqual(dy_array[ii,jj], answer[ii,jj], places=places) + np.testing.assert_almost_equal(dy_array, answer, places) def test_op_gelu(self): w = tf.constant([[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8], [ @@ -42,9 +40,7 @@ def test_op_gelu(self): [1.072173273655498138e-01, 2.082159073100979807e-01, 3.059816075270163083e-01, 4.032981557798429595e-01]]) places = 18 - for ii in range(dy_array.shape[0]): - for jj in range(dy_array.shape[1]): - self.assertAlmostEqual(dy_array[ii, jj], answer[ii, jj], places=places) + np.testing.assert_almost_equal(dy_array, answer, places) diff --git a/source/tests/test_transfer.py b/source/tests/test_transfer.py index 7142041fda..7b5884b2b4 100644 --- a/source/tests/test_transfer.py +++ b/source/tests/test_transfer.py @@ -75,14 +75,11 @@ def test_1frame(self): self.assertEqual(ff.shape, (nframes,natoms,3)) self.assertEqual(vv.shape, (nframes,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_1frame_atm(self): ee, ff, vv, ae, av = self.dp.eval(self.coords, self.box, self.atype, atomic = True) @@ -95,18 +92,13 @@ def test_1frame_atm(self): self.assertEqual(ae.shape, (nframes,natoms,1)) self.assertEqual(av.shape, (nframes,natoms,9)) # check values - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], self.expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], self.expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], self.expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), self.expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), self.expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), self.expected_v.ravel(), default_places) expected_se = np.sum(self.expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(self.expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) def test_2frame_atm(self): @@ -125,16 +117,11 @@ def test_2frame_atm(self): expected_f = np.concatenate((self.expected_f, self.expected_f), axis = 0) expected_e = np.concatenate((self.expected_e, self.expected_e), axis = 0) expected_v = np.concatenate((self.expected_v, self.expected_v), axis = 0) - for ii in range(ff.size): - self.assertAlmostEqual(ff.reshape([-1])[ii], expected_f.reshape([-1])[ii], places = default_places) - for ii in range(ae.size): - self.assertAlmostEqual(ae.reshape([-1])[ii], expected_e.reshape([-1])[ii], places = default_places) - for ii in range(av.size): - self.assertAlmostEqual(av.reshape([-1])[ii], expected_v.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ff.ravel(), expected_f.ravel(), default_places) + np.testing.assert_almost_equal(ae.ravel(), expected_e.ravel(), default_places) + np.testing.assert_almost_equal(av.ravel(), expected_v.ravel(), default_places) expected_se = np.sum(expected_e.reshape([nframes, -1]), axis = 1) - for ii in range(nframes): - self.assertAlmostEqual(ee.reshape([-1])[ii], expected_se.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(ee.ravel(), expected_se.ravel(), default_places) expected_sv = np.sum(expected_v.reshape([nframes, -1, 9]), axis = 1) - for ii in range(nframes, 9): - self.assertAlmostEqual(vv.reshape([-1])[ii], expected_sv.reshape([-1])[ii], places = default_places) + np.testing.assert_almost_equal(vv.ravel(), expected_sv.ravel(), default_places) diff --git a/source/tests/test_type_embed.py b/source/tests/test_type_embed.py index 42d1c86063..57b153c24d 100644 --- a/source/tests/test_type_embed.py +++ b/source/tests/test_type_embed.py @@ -21,10 +21,8 @@ def test_embed_atom_type(self): atom_embed = embed_atom_type(ntypes, natoms, type_embedding) sess = self.test_session().__enter__() atom_embed = sess.run(atom_embed) - for ii in range(5): - for jj in range(3): - self.assertAlmostEqual( - atom_embed[ii][jj], expected_out[ii][jj], places=10) + np.testing.assert_almost_equal( + atom_embed, expected_out, 10) def test_type_embed_net(self): ten = TypeEmbedNet([2, 4, 8], seed = 1, uniform_seed = True) @@ -44,7 +42,5 @@ def test_type_embed_net(self): # size of embedded vec 8 self.assertEqual(type_embedding.shape[1], 8) # check value - for ii in range(2): - for jj in range(8): - self.assertAlmostEqual( - type_embedding[ii][jj], expected_out[ii][jj], places=10) + np.testing.assert_almost_equal( + type_embedding, expected_out, 10) diff --git a/source/tests/test_wfc.py b/source/tests/test_wfc.py index 97af7486bd..80f9d48126 100644 --- a/source/tests/test_wfc.py +++ b/source/tests/test_wfc.py @@ -91,8 +91,7 @@ def test_model(self): refp = [-9.105016838228578990e-01,7.196284362034099935e-01,-9.548516928185298014e-02,2.764615027095288724e+00,2.661319598995644520e-01,7.579512949131941846e-02,-2.107409067376114997e+00,-1.299080016614967414e-01,-5.962778584850070285e-01,2.913899917663253514e-01,-1.226917174638697094e+00,1.829523069930876655e+00,1.015704024959750873e+00,-1.792333611099589386e-01,5.032898080485321834e-01,1.808561721292949453e-01,2.468863482075112081e+00,-2.566442546384765100e-01,-1.467453783795173994e-01,-1.822963931552128658e+00,5.843600156865462747e-01,-1.493875280832117403e+00,1.693322352814763398e-01,-1.877325443995481624e+00] places = 6 - for ii in range(p.size) : - self.assertAlmostEqual(p[ii], refp[ii], places = places) + np.testing.assert_almost_equal(p, refp, places) From 4c10232a740de1935bbd7b35185a0e00a9b2ab48 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 30 Aug 2021 22:27:30 -0400 Subject: [PATCH 08/34] set `allow_growth` in `default_tf_session_config` (#1067) Currently, TF only initializes GPUs once, and never releases memory. As a result, we must set `allow_growth` in the first Session (or every session?), otherwise it doesn't work. Please confirm the `allow_growth` config in `trainer.py` is expected, otherwise we should remove it instead. --- deepmd/env.py | 1 + 1 file changed, 1 insertion(+) diff --git a/deepmd/env.py b/deepmd/env.py index aaa148b357..4868eb8c3b 100644 --- a/deepmd/env.py +++ b/deepmd/env.py @@ -119,6 +119,7 @@ def get_tf_session_config() -> Any: set_tf_default_nthreads() intra, inter = get_tf_default_nthreads() config = tf.ConfigProto( + gpu_options=tf.GPUOptions(allow_growth=True), intra_op_parallelism_threads=intra, inter_op_parallelism_threads=inter ) return config From 75160c723c9c85436c84e65792d56f9099b865db Mon Sep 17 00:00:00 2001 From: Han Wang Date: Tue, 31 Aug 2021 10:49:36 +0800 Subject: [PATCH 09/34] fix Fail to build on macos: explicit instantiation of 'deepmd::Region' must occur in namespace 'deepmd' (#1071) Co-authored-by: Han Wang --- source/lib/src/region.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/lib/src/region.cc b/source/lib/src/region.cc index 90704016c2..d8333e4929 100644 --- a/source/lib/src/region.cc +++ b/source/lib/src/region.cc @@ -22,8 +22,8 @@ Region:: delete [] rec_boxt; } -template struct Region; -template struct Region; +template struct deepmd::Region; +template struct deepmd::Region; template inline FPTYPE From 63baa3042914e04fb8badef3f3545b044ee1a8cb Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Wed, 1 Sep 2021 09:58:42 +0800 Subject: [PATCH 10/34] undo reset lcurve.out during the model compression process (#1080) --- deepmd/train/trainer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index 72dc61418e..7e8f352dcc 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -408,8 +408,9 @@ def _init_session(self): if self.run_opt.init_mode == 'init_from_scratch' : log.info("initialize model from scratch") run_sess(self.sess, init_op) - fp = open(self.disp_file, "w") - fp.close () + if not self.is_compress: + fp = open(self.disp_file, "w") + fp.close () elif self.run_opt.init_mode == 'init_from_model' : log.info("initialize from model %s" % self.run_opt.init_model) run_sess(self.sess, init_op) From 91787ab860c839cb0096b3049ba01bc7f23be079 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Tue, 31 Aug 2021 22:00:05 -0400 Subject: [PATCH 11/34] use @loader_path on macos instead of $ORIGIN (#1078) --- source/op/CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source/op/CMakeLists.txt b/source/op/CMakeLists.txt index 07d030ef01..96c02ec71c 100644 --- a/source/op/CMakeLists.txt +++ b/source/op/CMakeLists.txt @@ -32,6 +32,20 @@ if (BUILD_PY_IF) ) target_include_directories(op_abi PUBLIC ${TensorFlow_INCLUDE_DIRS}) target_include_directories(op_grads PUBLIC ${TensorFlow_INCLUDE_DIRS}) + if (APPLE) + set_target_properties( + op_abi + PROPERTIES + COMPILE_FLAGS ${OP_CXX_FLAG} + INSTALL_RPATH @loader_path + ) + set_target_properties( + op_grads + PROPERTIES + COMPILE_FLAGS ${OP_CXX_FLAG} + INSTALL_RPATH @loader_path + ) + else() set_target_properties( op_abi PROPERTIES @@ -44,6 +58,7 @@ if (BUILD_PY_IF) COMPILE_FLAGS ${OP_CXX_FLAG} INSTALL_RPATH $ORIGIN ) + endif () endif (BUILD_PY_IF) if (BUILD_CPP_IF) From 385dcd61176c85670a13259030efc7e11047f41e Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Tue, 31 Aug 2021 22:00:51 -0400 Subject: [PATCH 12/34] fix typo: `lcueve.out`->`lcurve.out` (#1077) --- deepmd/utils/argcheck.py | 2 +- doc/train-input-auto.rst | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/deepmd/utils/argcheck.py b/deepmd/utils/argcheck.py index fcaba80908..6279b3e088 100644 --- a/deepmd/utils/argcheck.py +++ b/deepmd/utils/argcheck.py @@ -581,7 +581,7 @@ def training_args(): # ! modified by Ziyao: data configuration isolated. arg_validation_data, Argument("numb_steps", int, optional=False, doc=doc_numb_steps, alias=["stop_batch"]), Argument("seed", [int,None], optional=True, doc=doc_seed), - Argument("disp_file", str, optional=True, default='lcueve.out', doc=doc_disp_file), + Argument("disp_file", str, optional=True, default='lcurve.out', doc=doc_disp_file), Argument("disp_freq", int, optional=True, default=1000, doc=doc_disp_freq), Argument("numb_test", [list,int,str], optional=True, default=1, doc=doc_numb_test), Argument("save_freq", int, optional=True, default=1000, doc=doc_save_freq), diff --git a/doc/train-input-auto.rst b/doc/train-input-auto.rst index ea8da06a61..9201809549 100644 --- a/doc/train-input-auto.rst +++ b/doc/train-input-auto.rst @@ -898,7 +898,7 @@ model: .. _`model/fitting_net[polar]/scale`: scale: - | type: ``list`` | ``float``, optional, default: ``1.0`` + | type: ``float`` | ``list``, optional, default: ``1.0`` | argument path: ``model/fitting_net[polar]/scale`` The output of the fitting net (polarizability matrix) will be scaled by ``scale`` @@ -1102,7 +1102,7 @@ loss: .. _`loss[ener]/start_pref_e`: start_pref_e: - | type: ``int`` | ``float``, optional, default: ``0.02`` + | type: ``float`` | ``int``, optional, default: ``0.02`` | argument path: ``loss[ener]/start_pref_e`` The prefactor of energy loss at the start of the training. Should be larger than or equal to 0. If set to none-zero value, the energy label should be provided by file energy.npy in each data system. If both start_pref_energy and limit_pref_energy are set to 0, then the energy will be ignored. @@ -1110,7 +1110,7 @@ loss: .. _`loss[ener]/limit_pref_e`: limit_pref_e: - | type: ``int`` | ``float``, optional, default: ``1.0`` + | type: ``float`` | ``int``, optional, default: ``1.0`` | argument path: ``loss[ener]/limit_pref_e`` The prefactor of energy loss at the limit of the training, Should be larger than or equal to 0. i.e. the training step goes to infinity. @@ -1118,7 +1118,7 @@ loss: .. _`loss[ener]/start_pref_f`: start_pref_f: - | type: ``int`` | ``float``, optional, default: ``1000`` + | type: ``float`` | ``int``, optional, default: ``1000`` | argument path: ``loss[ener]/start_pref_f`` The prefactor of force loss at the start of the training. Should be larger than or equal to 0. If set to none-zero value, the force label should be provided by file force.npy in each data system. If both start_pref_force and limit_pref_force are set to 0, then the force will be ignored. @@ -1126,7 +1126,7 @@ loss: .. _`loss[ener]/limit_pref_f`: limit_pref_f: - | type: ``int`` | ``float``, optional, default: ``1.0`` + | type: ``float`` | ``int``, optional, default: ``1.0`` | argument path: ``loss[ener]/limit_pref_f`` The prefactor of force loss at the limit of the training, Should be larger than or equal to 0. i.e. the training step goes to infinity. @@ -1134,7 +1134,7 @@ loss: .. _`loss[ener]/start_pref_v`: start_pref_v: - | type: ``int`` | ``float``, optional, default: ``0.0`` + | type: ``float`` | ``int``, optional, default: ``0.0`` | argument path: ``loss[ener]/start_pref_v`` The prefactor of virial loss at the start of the training. Should be larger than or equal to 0. If set to none-zero value, the virial label should be provided by file virial.npy in each data system. If both start_pref_virial and limit_pref_virial are set to 0, then the virial will be ignored. @@ -1142,7 +1142,7 @@ loss: .. _`loss[ener]/limit_pref_v`: limit_pref_v: - | type: ``int`` | ``float``, optional, default: ``0.0`` + | type: ``float`` | ``int``, optional, default: ``0.0`` | argument path: ``loss[ener]/limit_pref_v`` The prefactor of virial loss at the limit of the training, Should be larger than or equal to 0. i.e. the training step goes to infinity. @@ -1150,7 +1150,7 @@ loss: .. _`loss[ener]/start_pref_ae`: start_pref_ae: - | type: ``int`` | ``float``, optional, default: ``0.0`` + | type: ``float`` | ``int``, optional, default: ``0.0`` | argument path: ``loss[ener]/start_pref_ae`` The prefactor of atom_ener loss at the start of the training. Should be larger than or equal to 0. If set to none-zero value, the atom_ener label should be provided by file atom_ener.npy in each data system. If both start_pref_atom_ener and limit_pref_atom_ener are set to 0, then the atom_ener will be ignored. @@ -1158,7 +1158,7 @@ loss: .. _`loss[ener]/limit_pref_ae`: limit_pref_ae: - | type: ``int`` | ``float``, optional, default: ``0.0`` + | type: ``float`` | ``int``, optional, default: ``0.0`` | argument path: ``loss[ener]/limit_pref_ae`` The prefactor of atom_ener loss at the limit of the training, Should be larger than or equal to 0. i.e. the training step goes to infinity. @@ -1166,7 +1166,7 @@ loss: .. _`loss[ener]/relative_f`: relative_f: - | type: ``NoneType`` | ``float``, optional + | type: ``float`` | ``NoneType``, optional | argument path: ``loss[ener]/relative_f`` If provided, relative force error will be used in the loss. The difference of force will be normalized by the magnitude of the force in the label with a shift given by `relative_f`, i.e. DF_i / ( || F || + relative_f ) with DF denoting the difference between prediction and label and || F || denoting the L2 norm of the label. @@ -1179,7 +1179,7 @@ loss: .. _`loss[tensor]/pref`: pref: - | type: ``int`` | ``float`` + | type: ``float`` | ``int`` | argument path: ``loss[tensor]/pref`` The prefactor of the weight of global loss. It should be larger than or equal to 0. If controls the weight of loss corresponding to global label, i.e. 'polarizability.npy` or `dipole.npy`, whose shape should be #frames x [9 or 3]. If it's larger than 0.0, this npy should be included. @@ -1187,7 +1187,7 @@ loss: .. _`loss[tensor]/pref_atomic`: pref_atomic: - | type: ``int`` | ``float`` + | type: ``float`` | ``int`` | argument path: ``loss[tensor]/pref_atomic`` The prefactor of the weight of atomic loss. It should be larger than or equal to 0. If controls the weight of loss corresponding to atomic label, i.e. `atomic_polarizability.npy` or `atomic_dipole.npy`, whose shape should be #frames x ([9 or 3] x #selected atoms). If it's larger than 0.0, this npy should be included. Both `pref` and `pref_atomic` should be provided, and either can be set to 0.0. @@ -1408,7 +1408,7 @@ training: .. _`training/disp_file`: disp_file: - | type: ``str``, optional, default: ``lcueve.out`` + | type: ``str``, optional, default: ``lcurve.out`` | argument path: ``training/disp_file`` The file for printing learning curve. From c716b9f362a37ae64fa20c70d830cccef807591d Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Wed, 1 Sep 2021 10:02:39 +0800 Subject: [PATCH 13/34] Model compression checkpoint (#1076) * change the default checkpoint path for model compression * update UT for model compression * clean up files --- deepmd/entrypoints/compress.py | 1 + deepmd/entrypoints/main.py | 2 +- source/tests/test_model_compression.py | 13 +++++++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/deepmd/entrypoints/compress.py b/deepmd/entrypoints/compress.py index c689481b96..1737ae4a75 100644 --- a/deepmd/entrypoints/compress.py +++ b/deepmd/entrypoints/compress.py @@ -101,6 +101,7 @@ def compress( 10 * step, int(frequency), ] + jdata["training"]["save_ckpt"] = "model-compression/model.ckpt" jdata = normalize(jdata) # check the descriptor info of the input file diff --git a/deepmd/entrypoints/main.py b/deepmd/entrypoints/main.py index bef0d2bf58..721eed357c 100644 --- a/deepmd/entrypoints/main.py +++ b/deepmd/entrypoints/main.py @@ -311,7 +311,7 @@ def parse_args(args: Optional[List[str]] = None): "-c", "--checkpoint-folder", type=str, - default=".", + default="model-compression", help="path to checkpoint folder", ) parser_compress.add_argument( diff --git a/source/tests/test_model_compression.py b/source/tests/test_model_compression.py index b183c6bde8..2f42134409 100644 --- a/source/tests/test_model_compression.py +++ b/source/tests/test_model_compression.py @@ -15,7 +15,9 @@ default_places = 10 def _file_delete(file) : - if os.path.exists(file): + if os.path.isdir(file): + os.rmdir(file) + elif os.path.isfile(file): os.remove(file) def _subprocess_run(command): @@ -318,10 +320,17 @@ def tearDownClass(self): _file_delete("out.json") _file_delete("compress.json") _file_delete("checkpoint") - _file_delete("lcurve.out") _file_delete("model.ckpt.meta") _file_delete("model.ckpt.index") _file_delete("model.ckpt.data-00000-of-00001") + _file_delete("model.ckpt-100.meta") + _file_delete("model.ckpt-100.index") + _file_delete("model.ckpt-100.data-00000-of-00001") + _file_delete("model-compression/checkpoint") + _file_delete("model-compression/model.ckpt.meta") + _file_delete("model-compression/model.ckpt.index") + _file_delete("model-compression/model.ckpt.data-00000-of-00001") + _file_delete("model-compression") def test_attrs(self): self.assertEqual(self.dp_original.get_ntypes(), 2) From 03a05bd7264afeef35d63f15aca49b9e08e9e9ee Mon Sep 17 00:00:00 2001 From: Shaochen Shi Date: Wed, 1 Sep 2021 10:03:26 +0800 Subject: [PATCH 14/34] Enable parallel training UT in GitHub CI. (#1075) * Remove dupliated setting of `allow_growth` in trainer. * Make parallel training UT independent of its working folder. * Skip parallel-training tests when there is only 1 GPU card. * Enable parallel training UT in GitHub CI. --- .github/workflows/test_python.yml | 5 +++++ deepmd/train/trainer.py | 1 - source/tests/test_parallel_training.py | 7 +++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_python.yml b/.github/workflows/test_python.yml index 8517560fc9..27f8e866d6 100644 --- a/.github/workflows/test_python.yml +++ b/.github/workflows/test_python.yml @@ -71,4 +71,9 @@ jobs: CXX: g++-${{ matrix.gcc }} TENSORFLOW_VERSION: ${{ matrix.tf }} - run: dp --version + - name: Prepare parallel runtime + if: ${{ matrix.tf == '' }} + run: | + sudo apt install libopenmpi-dev openmpi-bin + HOROVOD_WITHOUT_GLOO=1 HOROVOD_WITH_TENSORFLOW=1 pip install horovod mpi4py - run: pytest --cov=deepmd source/tests && codecov diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index 7e8f352dcc..00ea76043d 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -397,7 +397,6 @@ def _init_session(self): config = get_tf_session_config() device, idx = self.run_opt.my_device.split(":", 1) if device == "gpu": - config.gpu_options.allow_growth = True config.gpu_options.visible_device_list = idx self.sess = tf.Session(config=config) diff --git a/source/tests/test_parallel_training.py b/source/tests/test_parallel_training.py index e2310e8267..320d8ca22c 100644 --- a/source/tests/test_parallel_training.py +++ b/source/tests/test_parallel_training.py @@ -18,9 +18,12 @@ def setUp(self): def test_two_workers(self): command = 'horovodrun -np 2 dp train -m workers ' + self.input_file penv = os.environ.copy() - if len(get_gpus() or []) > 1: + num_gpus = len(get_gpus() or []) + if num_gpus > 1: penv['CUDA_VISIBLE_DEVICES'] = '0,1' - popen = sp.Popen(command, shell=True, env=penv, stdout=sp.PIPE, stderr=sp.STDOUT) + elif num_gpus == 1: + raise unittest.SkipTest("At least 2 GPU cards are needed for parallel-training tests.") + popen = sp.Popen(command, shell=True, cwd=str(tests_path), env=penv, stdout=sp.PIPE, stderr=sp.STDOUT) for line in iter(popen.stdout.readline, b''): if hasattr(line, 'decode'): line = line.decode('utf-8') From 9dcc81657b9f9a06ac97822651c2a43591c52743 Mon Sep 17 00:00:00 2001 From: Shaochen Shi Date: Wed, 1 Sep 2021 10:07:26 +0800 Subject: [PATCH 15/34] =?UTF-8?q?Fix=20shape=20mismatch=20when=20type=5Fem?= =?UTF-8?q?bedding=20is=20enabled=20and=20type=5Fone=5Fside=20i=E2=80=A6?= =?UTF-8?q?=20(#1074)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix shape mismatch when type_embedding is enabled and type_one_side is disabled. * Add UT to cover the case where batch_size is larger than 1. * Fix random issue in unit tests. --- deepmd/descriptor/se_a.py | 35 ++++++++++++++++++++------ source/tests/common.py | 20 +++++++-------- source/tests/test_descrpt_se_a_type.py | 6 ++--- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/deepmd/descriptor/se_a.py b/deepmd/descriptor/se_a.py index fbc9a77b56..3777368c0f 100644 --- a/deepmd/descriptor/se_a.py +++ b/deepmd/descriptor/se_a.py @@ -667,17 +667,36 @@ def _concat_type_embedding( nframes, natoms, type_embedding, - ): + ): + '''Concatenate `type_embedding` of neighbors and `xyz_scatter`. + If not self.type_one_side, concatenate `type_embedding` of center atoms as well. + + Parameters + ---------- + xyz_scatter: + shape is [nframes*natoms[0]*self.nnei, 1] + nframes: + shape is [] + natoms: + shape is [1+1+self.ntypes] + type_embedding: + shape is [self.ntypes, Y] where Y=jdata['type_embedding']['neuron'][-1] + + Returns + ------- + embedding: + environment of each atom represented by embedding. + ''' te_out_dim = type_embedding.get_shape().as_list()[-1] - nei_embed = tf.nn.embedding_lookup(type_embedding,tf.cast(self.nei_type,dtype=tf.int32)) #nnei*nchnl - nei_embed = tf.tile(nei_embed,(nframes*natoms[0],1)) + nei_embed = tf.nn.embedding_lookup(type_embedding,tf.cast(self.nei_type,dtype=tf.int32)) # shape is [self.nnei, 1+te_out_dim] + nei_embed = tf.tile(nei_embed,(nframes*natoms[0],1)) # shape is [nframes*natoms[0]*self.nnei, te_out_dim] nei_embed = tf.reshape(nei_embed,[-1,te_out_dim]) - embedding_input = tf.concat([xyz_scatter,nei_embed],1) + embedding_input = tf.concat([xyz_scatter,nei_embed],1) # shape is [nframes*natoms[0]*self.nnei, 1+te_out_dim] if not self.type_one_side: - atm_embed = embed_atom_type(self.ntypes, natoms, type_embedding) - atm_embed = tf.tile(atm_embed,(1,self.nnei)) - atm_embed = tf.reshape(atm_embed,[-1,te_out_dim]) - embedding_input = tf.concat([embedding_input,atm_embed],1) + atm_embed = embed_atom_type(self.ntypes, natoms, type_embedding) # shape is [natoms[0], te_out_dim] + atm_embed = tf.tile(atm_embed,(nframes,self.nnei)) # shape is [nframes*natoms[0], self.nnei*te_out_dim] + atm_embed = tf.reshape(atm_embed,[-1,te_out_dim]) # shape is [nframes*natoms[0]*self.nnei, te_out_dim] + embedding_input = tf.concat([embedding_input,atm_embed],1) # shape is [nframes*natoms[0]*self.nnei, 1+te_out_dim+te_out_dim] return embedding_input diff --git a/source/tests/common.py b/source/tests/common.py index 87dd5d6d70..e767f8a3eb 100644 --- a/source/tests/common.py +++ b/source/tests/common.py @@ -3,10 +3,9 @@ import pathlib from deepmd.env import tf -from deepmd.env import GLOBAL_TF_FLOAT_PRECISION from deepmd.env import GLOBAL_NP_FLOAT_PRECISION -from deepmd.env import GLOBAL_ENER_FLOAT_PRECISION from deepmd.common import j_loader as dp_j_loader +from deepmd.utils import random as dp_random if GLOBAL_NP_FLOAT_PRECISION == np.float32 : global_default_fv_hh = 1e-2 @@ -26,8 +25,8 @@ def del_data(): if os.path.isdir('system'): shutil.rmtree('system') -def gen_data() : - tmpdata = Data(rand_pert = 0.1, seed = 1) +def gen_data(nframes = 1) : + tmpdata = Data(rand_pert = 0.1, seed = 1, nframes = nframes) sys = dpdata.LabeledSystem() sys.data['atom_names'] = ['foo', 'bar'] sys.data['coords'] = tmpdata.coord @@ -47,14 +46,15 @@ class Data(): def __init__ (self, rand_pert = 0.1, seed = 1, - box_scale = 20) : + box_scale = 20, + nframes = 1): coord = [[0.0, 0.0, 0.1], [1.1, 0.0, 0.1], [0.0, 1.1, 0.1], [4.0, 0.0, 0.0], [5.1, 0.0, 0.0], [4.0, 1.1, 0.0]] - self.nframes = 1 + self.nframes = nframes self.coord = np.array(coord) self.coord = self._copy_nframes(self.coord) - np.random.seed(seed) - self.coord += rand_pert * np.random.random(self.coord.shape) + dp_random.seed(seed) + self.coord += rand_pert * dp_random.random(self.coord.shape) self.fparam = np.array([[0.1, 0.2]]) self.aparam = np.tile(self.fparam, [1, 6]) self.fparam = self._copy_nframes(self.fparam) @@ -69,7 +69,7 @@ def __init__ (self, self.coord = self.coord.reshape([self.nframes, -1, 3]) self.coord = self.coord[:,self.idx_map,:] self.coord = self.coord.reshape([self.nframes, -1]) - self.efield = np.random.random(self.coord.shape) + self.efield = dp_random.random(self.coord.shape) self.atype = self.atype[self.idx_map] self.datype = self._copy_nframes(self.atype) @@ -128,7 +128,7 @@ def get_test_box_data (self, coord0_, box0_, type0_ = self.get_data() coord = coord0_[0] box = box0_[0] - box += rand_pert * np.random.random(box.shape) + box += rand_pert * dp_random.random(box.shape) atype = type0_[0] nframes = 1 natoms = coord.size // 3 diff --git a/source/tests/test_descrpt_se_a_type.py b/source/tests/test_descrpt_se_a_type.py index fded177b66..f65338d0a4 100644 --- a/source/tests/test_descrpt_se_a_type.py +++ b/source/tests/test_descrpt_se_a_type.py @@ -17,8 +17,8 @@ GLOBAL_NP_FLOAT_PRECISION = np.float64 class TestModel(tf.test.TestCase): - def setUp(self) : - gen_data() + def setUp(self): + gen_data(nframes=2) def test_descriptor_two_sides(self): jfile = 'water_se_a_type.json' @@ -28,7 +28,7 @@ def test_descriptor_two_sides(self): set_pfx = j_must_have(jdata, 'set_prefix') batch_size = j_must_have(jdata, 'batch_size') test_size = j_must_have(jdata, 'numb_test') - batch_size = 1 + batch_size = 2 test_size = 1 stop_batch = j_must_have(jdata, 'stop_batch') rcut = j_must_have (jdata['model']['descriptor'], 'rcut') From 5e96c57df0ed97b8072e87a30d381546a3df9dd8 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Tue, 31 Aug 2021 22:08:16 -0400 Subject: [PATCH 16/34] Revert "get library extension suffix from built-in method (#1036)" (#1072) This reverts commit f35afe065282e18d16eba98ca50c48f9f02fb260. --- deepmd/env.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/deepmd/env.py b/deepmd/env.py index 4868eb8c3b..92287d8aa5 100644 --- a/deepmd/env.py +++ b/deepmd/env.py @@ -2,7 +2,7 @@ import logging import os -import distutils.ccompiler +import platform from configparser import ConfigParser from imp import reload from pathlib import Path @@ -157,8 +157,12 @@ def get_module(module_name: str) -> "ModuleType": FileNotFoundError if module is not found in directory """ - # https://discuss.python.org/t/how-to-get-the-file-extension-of-dynamic-libraries-for-current-os/3916/5 - ext = distutils.ccompiler.new_compiler().shared_lib_extension + if platform.system() == "Windows": + ext = ".dll" + elif platform.system() == "Darwin": + ext = ".dylib" + else: + ext = ".so" module_file = ( (Path(__file__).parent / SHARED_LIB_MODULE / module_name) From d68171a81ec5fcae3dd77ec9ede12f25f3ae0a73 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 1 Sep 2021 19:56:15 -0400 Subject: [PATCH 17/34] reduce `rcut` and `sel` in the example of `se_e3` (#1082) See #1062. --- examples/water/se_e3/input.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/water/se_e3/input.json b/examples/water/se_e3/input.json index f91ccad83c..4b62f4435b 100644 --- a/examples/water/se_e3/input.json +++ b/examples/water/se_e3/input.json @@ -4,9 +4,9 @@ "type_map": ["O", "H"], "descriptor" :{ "type": "se_e3", - "sel": [40, 80], + "sel": "auto", "rcut_smth": 0.50, - "rcut": 6.00, + "rcut": 5.80, "neuron": [2, 4, 8], "resnet_dt": false, "seed": 1, From da5f688461f8ae333456377da3983d71e132a3c9 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 1 Sep 2021 19:57:10 -0400 Subject: [PATCH 18/34] create cross-references in docstring (#1083) * create cross-references in docstring * add typing alias --- doc/conf.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/conf.py b/doc/conf.py index 02610d172b..dd946fa2e1 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -220,6 +220,13 @@ def setup(app): ), "ase": ("https://wiki.fysik.dtu.dk/ase/", None), } +numpydoc_xref_param_type = True + + +numpydoc_xref_aliases = {} +import typing +for typing_type in typing.__all__: + numpydoc_xref_aliases[typing_type] = "typing.%s" % typing_type # -- Options for HTML output ------------------------------------------------- From c824ff687fd949a95f47e76fc6f934db5e017d22 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Thu, 2 Sep 2021 04:15:08 -0400 Subject: [PATCH 19/34] add ABC for descriptors (#1081) * add ABC for descriptors I'm going to add abstract base classes for different object, where a list of methods and attributes is defined to normalize classes and their external call by other classes. It's also useful to develop and extend new classes. The first one I did is the descriptor. * TYPE_CHECKING doesn't work in python 3.6 * fix warnings --- deepmd/descriptor/descriptor.py | 282 ++++++++++++++++++++++++++++++++ deepmd/descriptor/hybrid.py | 3 +- deepmd/descriptor/loc_frame.py | 3 +- deepmd/descriptor/se_a.py | 3 +- deepmd/descriptor/se_a_ef.py | 3 +- deepmd/descriptor/se_ar.py | 3 +- deepmd/descriptor/se_r.py | 3 +- deepmd/descriptor/se_t.py | 3 +- 8 files changed, 296 insertions(+), 7 deletions(-) create mode 100644 deepmd/descriptor/descriptor.py diff --git a/deepmd/descriptor/descriptor.py b/deepmd/descriptor/descriptor.py new file mode 100644 index 0000000000..c7ca158e05 --- /dev/null +++ b/deepmd/descriptor/descriptor.py @@ -0,0 +1,282 @@ +from abc import ABC, abstractmethod +from typing import Any, Dict, List, Tuple + +import numpy as np +from deepmd.env import tf + + +class Descriptor(ABC): + r"""The abstract class for descriptors. All specific descriptors should + be based on this class. + + The descriptor :math:`\mathcal{D}` describes the environment of an atom, + which should be a function of coordinates and types of its neighbour atoms. + + Notes + ----- + Only methods and attributes defined in this class are generally public, + that can be called by other classes. + """ + + @abstractmethod + def get_rcut(self) -> float: + """ + Returns the cut-off radius. + + Returns + ------- + float + the cut-off radius + + Notes + ----- + This method must be implemented, as it's called by other classes. + """ + + @abstractmethod + def get_ntypes(self) -> int: + """ + Returns the number of atom types. + + Returns + ------- + int + the number of atom types + + Notes + ----- + This method must be implemented, as it's called by other classes. + """ + + @abstractmethod + def get_dim_out(self) -> int: + """ + Returns the output dimension of this descriptor. + + Returns + ------- + int + the output dimension of this descriptor + + Notes + ----- + This method must be implemented, as it's called by other classes. + """ + + def get_dim_rot_mat_1(self) -> int: + """ + Returns the first dimension of the rotation matrix. The rotation is of shape + dim_1 x 3 + + Returns + ------- + int + the first dimension of the rotation matrix + """ + # TODO: I think this method should be implemented as it's called by dipole and + # polar fitting network. However, currently not all descriptors have this + # method. + raise NotImplementedError + + def get_nlist(self) -> Tuple[tf.Tensor, tf.Tensor, List[int], List[int]]: + """ + Returns neighbor information. + + Returns + ------- + nlist : tf.Tensor + Neighbor list + rij : tf.Tensor + The relative distance between the neighbor and the center atom. + sel_a : list[int] + The number of neighbors with full information + sel_r : list[int] + The number of neighbors with only radial information + """ + # TODO: I think this method should be implemented as it's called by energy + # model. However, se_ar and hybrid doesn't have this method. + raise NotImplementedError + + @abstractmethod + def compute_input_stats(self, + data_coord: List[np.ndarray], + data_box: List[np.ndarray], + data_atype: List[np.ndarray], + natoms_vec: List[np.ndarray], + mesh: List[np.ndarray], + input_dict: Dict[str, List[np.ndarray]] + ) -> None: + """ + Compute the statisitcs (avg and std) of the training data. The input will be + normalized by the statistics. + + Parameters + ---------- + data_coord : list[np.ndarray] + The coordinates. Can be generated by + :meth:`deepmd.model.model_stat.make_stat_input` + data_box : list[np.ndarray] + The box. Can be generated by + :meth:`deepmd.model.model_stat.make_stat_input` + data_atype : list[np.ndarray] + The atom types. Can be generated by :meth:`deepmd.model.model_stat.make_stat_input` + natoms_vec : list[np.ndarray] + The vector for the number of atoms of the system and different types of + atoms. Can be generated by :meth:`deepmd.model.model_stat.make_stat_input` + mesh : list[np.ndarray] + The mesh for neighbor searching. Can be generated by + :meth:`deepmd.model.model_stat.make_stat_input` + input_dict : dict[str, list[np.ndarray]] + Dictionary for additional input + + Notes + ----- + This method must be implemented, as it's called by other classes. + """ + + @abstractmethod + def build(self, + coord_: tf.Tensor, + atype_: tf.Tensor, + natoms: tf.Tensor, + box_: tf.Tensor, + mesh: tf.Tensor, + input_dict: Dict[str, Any], + reuse: bool = None, + suffix: str = '', + ) -> tf.Tensor: + """ + Build the computational graph for the descriptor. + + Parameters + ---------- + coord_ : tf.Tensor + The coordinate of atoms + atype_ : tf.Tensor + The type of atoms + natoms : tf.Tensor + The number of atoms. This tensor has the length of Ntypes + 2 + natoms[0]: number of local atoms + natoms[1]: total number of atoms held by this processor + natoms[i]: 2 <= i < Ntypes+2, number of type i atoms + box : tf.Tensor + The box of frames + mesh : tf.Tensor + For historical reasons, only the length of the Tensor matters. + if size of mesh == 6, pbc is assumed. + if size of mesh == 0, no-pbc is assumed. + input_dict : dict[str, Any] + Dictionary for additional inputs + reuse : bool, optional + The weights in the networks should be reused when get the variable. + suffix : str, optional + Name suffix to identify this descriptor + + Returns + ------- + descriptor: tf.Tensor + The output descriptor + + Notes + ----- + This method must be implemented, as it's called by other classes. + """ + + def enable_compression(self, + min_nbor_dist: float, + model_file: str = 'frozon_model.pb', + table_extrapolate: float = 5., + table_stride_1: float = 0.01, + table_stride_2: float = 0.1, + check_frequency: int = -1 + ) -> None: + """ + Reveive the statisitcs (distance, max_nbor_size and env_mat_range) of the + training data. + + Parameters + ---------- + min_nbor_dist : float + The nearest distance between atoms + model_file : str, default: 'frozon_model.pb' + The original frozen model, which will be compressed by the program + table_extrapolate : float, default: 5. + The scale of model extrapolation + table_stride_1 : float, default: 0.01 + The uniform stride of the first table + table_stride_2 : float, default: 0.1 + The uniform stride of the second table + check_frequency : int, default: -1 + The overflow check frequency + + Notes + ----- + This method is called by others when the descriptor supported compression. + """ + raise NotImplementedError( + "Descriptor %s doesn't support compression!" % self.__name__) + + @abstractmethod + def prod_force_virial(self, + atom_ener: tf.Tensor, + natoms: tf.Tensor + ) -> Tuple[tf.Tensor, tf.Tensor, tf.Tensor]: + """ + Compute force and virial. + + Parameters + ---------- + atom_ener : tf.Tensor + The atomic energy + natoms : tf.Tensor + The number of atoms. This tensor has the length of Ntypes + 2 + natoms[0]: number of local atoms + natoms[1]: total number of atoms held by this processor + natoms[i]: 2 <= i < Ntypes+2, number of type i atoms + + Returns + ------- + force : tf.Tensor + The force on atoms + virial : tf.Tensor + The total virial + atom_virial : tf.Tensor + The atomic virial + """ + + def get_feed_dict(self, + coord_: tf.Tensor, + atype_: tf.Tensor, + natoms: tf.Tensor, + box: tf.Tensor, + mesh: tf.Tensor + ) -> Dict[str, tf.Tensor]: + """ + Generate the feed_dict for current descriptor + + Parameters + ---------- + coord_ : tf.Tensor + The coordinate of atoms + atype_ : tf.Tensor + The type of atoms + natoms : tf.Tensor + The number of atoms. This tensor has the length of Ntypes + 2 + natoms[0]: number of local atoms + natoms[1]: total number of atoms held by this processor + natoms[i]: 2 <= i < Ntypes+2, number of type i atoms + box : tf.Tensor + The box. Can be generated by deepmd.model.make_stat_input + mesh : tf.Tensor + For historical reasons, only the length of the Tensor matters. + if size of mesh == 6, pbc is assumed. + if size of mesh == 0, no-pbc is assumed. + + Returns + ------- + feed_dict : dict[str, tf.Tensor] + The output feed_dict of current descriptor + """ + # TODO: currently only SeA has this method, but I think the method can be + # moved here as it doesn't contain anything related to a specific descriptor + raise NotImplementedError diff --git a/deepmd/descriptor/hybrid.py b/deepmd/descriptor/hybrid.py index 013ee9f753..d4e6d795b7 100644 --- a/deepmd/descriptor/hybrid.py +++ b/deepmd/descriptor/hybrid.py @@ -12,6 +12,7 @@ # from deepmd.descriptor import DescrptSeAEbd # from deepmd.descriptor import DescrptSeAEf # from deepmd.descriptor import DescrptSeR +from .descriptor import Descriptor from .se_a import DescrptSeA from .se_r import DescrptSeR from .se_ar import DescrptSeAR @@ -20,7 +21,7 @@ from .se_a_ef import DescrptSeAEf from .loc_frame import DescrptLocFrame -class DescrptHybrid (): +class DescrptHybrid (Descriptor): """Concate a list of descriptors to form a new descriptor. Parameters diff --git a/deepmd/descriptor/loc_frame.py b/deepmd/descriptor/loc_frame.py index be57403d60..a664384ba6 100644 --- a/deepmd/descriptor/loc_frame.py +++ b/deepmd/descriptor/loc_frame.py @@ -7,8 +7,9 @@ from deepmd.env import op_module from deepmd.env import default_tf_session_config from deepmd.utils.sess import run_sess +from .descriptor import Descriptor -class DescrptLocFrame () : +class DescrptLocFrame (Descriptor) : """Defines a local frame at each atom, and the compute the descriptor as local coordinates under this frame. diff --git a/deepmd/descriptor/se_a.py b/deepmd/descriptor/se_a.py index 3777368c0f..494c7e5fa6 100644 --- a/deepmd/descriptor/se_a.py +++ b/deepmd/descriptor/se_a.py @@ -14,8 +14,9 @@ from deepmd.utils.type_embed import embed_atom_type from deepmd.utils.sess import run_sess from deepmd.utils.graph import load_graph_def, get_tensor_by_name_from_graph +from .descriptor import Descriptor -class DescrptSeA (): +class DescrptSeA (Descriptor): r"""DeepPot-SE constructed from all information (both angular and radial) of atomic configurations. The embedding takes the distance between atoms as input. diff --git a/deepmd/descriptor/se_a_ef.py b/deepmd/descriptor/se_a_ef.py index 996de6ff2d..e2424aeae4 100644 --- a/deepmd/descriptor/se_a_ef.py +++ b/deepmd/descriptor/se_a_ef.py @@ -10,8 +10,9 @@ from deepmd.env import op_module from deepmd.env import default_tf_session_config from .se_a import DescrptSeA +from .descriptor import Descriptor -class DescrptSeAEf (): +class DescrptSeAEf (Descriptor): """ Parameters diff --git a/deepmd/descriptor/se_ar.py b/deepmd/descriptor/se_ar.py index 8ded2c5849..518cf9315c 100644 --- a/deepmd/descriptor/se_ar.py +++ b/deepmd/descriptor/se_ar.py @@ -5,8 +5,9 @@ from .se_a import DescrptSeA from .se_r import DescrptSeR from deepmd.env import op_module +from .descriptor import Descriptor -class DescrptSeAR (): +class DescrptSeAR (Descriptor): def __init__ (self, jdata): args = ClassArg()\ .add('a', dict, must = True) \ diff --git a/deepmd/descriptor/se_r.py b/deepmd/descriptor/se_r.py index fafa03a350..b6de76be76 100644 --- a/deepmd/descriptor/se_r.py +++ b/deepmd/descriptor/se_r.py @@ -10,8 +10,9 @@ from deepmd.env import default_tf_session_config from deepmd.utils.network import embedding_net, embedding_net_rand_seed_shift from deepmd.utils.sess import run_sess +from .descriptor import Descriptor -class DescrptSeR (): +class DescrptSeR (Descriptor): """DeepPot-SE constructed from radial information of atomic configurations. The embedding takes the distance between atoms as input. diff --git a/deepmd/descriptor/se_t.py b/deepmd/descriptor/se_t.py index 94298c6eb4..29f9323b34 100644 --- a/deepmd/descriptor/se_t.py +++ b/deepmd/descriptor/se_t.py @@ -10,8 +10,9 @@ from deepmd.env import default_tf_session_config from deepmd.utils.network import embedding_net, embedding_net_rand_seed_shift from deepmd.utils.sess import run_sess +from .descriptor import Descriptor -class DescrptSeT (): +class DescrptSeT (Descriptor): """DeepPot-SE constructed from all information (both angular and radial) of atomic configurations. From aab124fe96f93fc20b90b4bf471e0798a270d4d4 Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Fri, 3 Sep 2021 16:03:57 +0800 Subject: [PATCH 20/34] Fix a potential slice bug in se_t descriptor (#1087) * fix a potential slice bug in se_t * fix UT error * address comments --- deepmd/descriptor/se_t.py | 2 +- source/tests/test_model_se_t.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deepmd/descriptor/se_t.py b/deepmd/descriptor/se_t.py index 29f9323b34..2ab7a732be 100644 --- a/deepmd/descriptor/se_t.py +++ b/deepmd/descriptor/se_t.py @@ -469,6 +469,7 @@ def _filter(self, inputs_i = tf.slice (inputs, [ 0, start_index_i *4], [-1, self.sel_a[type_i] *4] ) + start_index_j = start_index_i start_index_i += self.sel_a[type_i] nei_type_i = self.sel_a[type_i] shape_i = inputs_i.get_shape().as_list() @@ -477,7 +478,6 @@ def _filter(self, env_i = tf.reshape(inputs_i, [-1, nei_type_i, 4]) # with natom x nei_type_i x 3 env_i = tf.slice(env_i, [0, 0, 1], [-1, -1, -1]) - start_index_j = 0 for type_j in range(type_i, self.ntypes): # with natom x (nei_type_j x 4) inputs_j = tf.slice (inputs, diff --git a/source/tests/test_model_se_t.py b/source/tests/test_model_se_t.py index fabbe667a8..dead21c2d0 100644 --- a/source/tests/test_model_se_t.py +++ b/source/tests/test_model_se_t.py @@ -100,9 +100,9 @@ def test_model(self): np.savetxt('e.out', e.reshape([1, -1])) np.savetxt('f.out', f.reshape([1, -1]), delimiter = ',') np.savetxt('v.out', v.reshape([1, -1]), delimiter = ',') - refe = [4.826771866004193612e+01] - reff = [5.355088169393570574e+00,5.606772412401632266e+00,2.703270748296462966e-01,5.381408138049708967e+00,5.261355614357515975e+00,-4.079549918988090162e-01,-5.182324474551911919e+00,3.695481388907447262e-01,-5.238474288082559799e-02,1.665564584447352670e-01,-5.955401876564963892e+00,-2.217626865156164251e-01,-5.967343479332643419e+00,9.073821102416884665e-02,3.703103995504785639e-01,2.466151879965444438e-01,-5.373012500109097367e+00,4.146494691512622732e-02] - refv = [-1.336768232407933077e+01,4.818050125305787801e-01,3.589284283410607568e-01,4.818050125305786691e-01,-1.225345559839458964e+01,-1.701405121682751653e-01,3.589284283410607568e-01,-1.701405121682752486e-01,-3.428455515842296353e-02] + refe = [4.8436558582194039e+01] + reff = [5.2896335066946598e+00,5.5778402259211131e+00,2.6839994229557251e-01,5.3528786387686784e+00,5.2477755362164968e+00,-4.0486366542657343e-01,-5.1297084055340498e+00,3.4607112287117253e-01,-5.1800783428369482e-02,1.5557068351407846e-01,-5.9071343228741506e+00,-2.2012359669589748e-01,-5.9156735320857488e+00,8.8397615509389127e-02,3.6701215949753935e-01,2.4729910864238122e-01,-5.3529501776440211e+00,4.1375943757728552e-02] + refv = [-1.3159448660141607e+01,4.6952048725161544e-01,3.5482003698976106e-01,4.6952048725161577e-01,-1.2178990983673918e+01,-1.6867277410496895e-01,3.5482003698976106e-01,-1.6867277410496900e-01,-3.3986741457321945e-02] refe = np.reshape(refe, [-1]) reff = np.reshape(reff, [-1]) refv = np.reshape(refv, [-1]) From e2fc5e350f0d885f96cc01d04d84e4d0c2356065 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Sat, 4 Sep 2021 05:16:53 -0400 Subject: [PATCH 21/34] make compress work for hybrid descriptor composed of se_e2_a (#1094) * make compress work for hybrid descriptor composed of se_e2_a * fix `get_embedding_net_nodes_from_graph_def` * fix lint warning --- deepmd/descriptor/descriptor.py | 7 +++++-- deepmd/descriptor/hybrid.py | 33 +++++++++++++++++++++++++++++++++ deepmd/descriptor/se_a.py | 14 ++++++++++---- deepmd/entrypoints/compress.py | 7 +------ deepmd/train/trainer.py | 1 - deepmd/utils/graph.py | 6 ++++-- deepmd/utils/tabulate.py | 33 +++++++++++++++++++-------------- 7 files changed, 72 insertions(+), 29 deletions(-) diff --git a/deepmd/descriptor/descriptor.py b/deepmd/descriptor/descriptor.py index c7ca158e05..4516aa146c 100644 --- a/deepmd/descriptor/descriptor.py +++ b/deepmd/descriptor/descriptor.py @@ -188,7 +188,8 @@ def enable_compression(self, table_extrapolate: float = 5., table_stride_1: float = 0.01, table_stride_2: float = 0.1, - check_frequency: int = -1 + check_frequency: int = -1, + suffix: str = "", ) -> None: """ Reveive the statisitcs (distance, max_nbor_size and env_mat_range) of the @@ -208,13 +209,15 @@ def enable_compression(self, The uniform stride of the second table check_frequency : int, default: -1 The overflow check frequency + suffix : str, optional + The suffix of the scope Notes ----- This method is called by others when the descriptor supported compression. """ raise NotImplementedError( - "Descriptor %s doesn't support compression!" % self.__name__) + "Descriptor %s doesn't support compression!" % type(self).__name__) @abstractmethod def prod_force_virial(self, diff --git a/deepmd/descriptor/hybrid.py b/deepmd/descriptor/hybrid.py index d4e6d795b7..bff59518a1 100644 --- a/deepmd/descriptor/hybrid.py +++ b/deepmd/descriptor/hybrid.py @@ -220,3 +220,36 @@ def prod_force_virial(self, virial += vv atom_virial += av return force, virial, atom_virial + + def enable_compression(self, + min_nbor_dist: float, + model_file: str = 'frozon_model.pb', + table_extrapolate: float = 5., + table_stride_1: float = 0.01, + table_stride_2: float = 0.1, + check_frequency: int = -1, + suffix: str = "" + ) -> None: + """ + Reveive the statisitcs (distance, max_nbor_size and env_mat_range) of the + training data. + + Parameters + ---------- + min_nbor_dist : float + The nearest distance between atoms + model_file : str, default: 'frozon_model.pb' + The original frozen model, which will be compressed by the program + table_extrapolate : float, default: 5. + The scale of model extrapolation + table_stride_1 : float, default: 0.01 + The uniform stride of the first table + table_stride_2 : float, default: 0.1 + The uniform stride of the second table + check_frequency : int, default: -1 + The overflow check frequency + suffix : str, optional + The suffix of the scope + """ + for idx, ii in enumerate(self.descrpt_list): + ii.enable_compression(min_nbor_dist, model_file, table_extrapolate, table_stride_1, table_stride_2, check_frequency, suffix=f"{suffix}_{idx}") diff --git a/deepmd/descriptor/se_a.py b/deepmd/descriptor/se_a.py index 494c7e5fa6..da600848fb 100644 --- a/deepmd/descriptor/se_a.py +++ b/deepmd/descriptor/se_a.py @@ -297,7 +297,8 @@ def enable_compression(self, table_extrapolate : float = 5, table_stride_1 : float = 0.01, table_stride_2 : float = 0.1, - check_frequency : int = -1 + check_frequency : int = -1, + suffix : str = "", ) -> None: """ Reveive the statisitcs (distance, max_nbor_size and env_mat_range) of the training data. @@ -316,10 +317,15 @@ def enable_compression(self, The uniform stride of the second table check_frequency The overflow check frequency + suffix : str, optional + The suffix of the scope """ + assert ( + not self.filter_resnet_dt + ), "Model compression error: descriptor resnet_dt must be false!" self.compress = True self.table = DPTabulate( - model_file, self.type_one_side, self.exclude_types, self.compress_activation_fn) + model_file, self.type_one_side, self.exclude_types, self.compress_activation_fn, suffix=suffix) self.table_config = [table_extrapolate, table_stride_1, table_stride_2, check_frequency] self.lower, self.upper \ = self.table.build(min_nbor_dist, @@ -328,8 +334,8 @@ def enable_compression(self, table_stride_2) graph, _ = load_graph_def(model_file) - self.davg = get_tensor_by_name_from_graph(graph, 'descrpt_attr/t_avg') - self.dstd = get_tensor_by_name_from_graph(graph, 'descrpt_attr/t_std') + self.davg = get_tensor_by_name_from_graph(graph, 'descrpt_attr%s/t_avg' % suffix) + self.dstd = get_tensor_by_name_from_graph(graph, 'descrpt_attr%s/t_std' % suffix) diff --git a/deepmd/entrypoints/compress.py b/deepmd/entrypoints/compress.py index 1737ae4a75..0b0ffb4306 100644 --- a/deepmd/entrypoints/compress.py +++ b/deepmd/entrypoints/compress.py @@ -105,12 +105,7 @@ def compress( jdata = normalize(jdata) # check the descriptor info of the input file - assert ( - jdata["model"]["descriptor"]["type"] == "se_a" or jdata["model"]["descriptor"]["type"] == "se_e2_a" - ), "Model compression error: descriptor type must be se_a or se_e2_a!" - assert ( - jdata["model"]["descriptor"]["resnet_dt"] is False - ), "Model compression error: descriptor resnet_dt must be false!" + # move to the specific Descriptor class # stage 1: training or refining the model with tabulation log.info("\n\n") diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index 00ea76043d..0fa08e77a2 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -325,7 +325,6 @@ def build (self, name = 'train_attr/max_nbor_size', dtype = GLOBAL_TF_FLOAT_PRECISION) else : - assert 'rcut' in self.descrpt_param, "Error: descriptor must have attr rcut!" self.descrpt.enable_compression(self.model_param['compress']["min_nbor_dist"], self.model_param['compress']['model_file'], self.model_param['compress']['table_config'][0], self.model_param['compress']['table_config'][1], self.model_param['compress']['table_config'][2], self.model_param['compress']['table_config'][3]) self.fitting.init_variables(get_fitting_net_variables(self.model_param['compress']['model_file'])) diff --git a/deepmd/utils/graph.py b/deepmd/utils/graph.py index 31452be7f5..959f6bf51b 100644 --- a/deepmd/utils/graph.py +++ b/deepmd/utils/graph.py @@ -112,7 +112,7 @@ def get_tensor_by_type(node, return tensor -def get_embedding_net_nodes_from_graph_def(graph_def: tf.GraphDef) -> Dict: +def get_embedding_net_nodes_from_graph_def(graph_def: tf.GraphDef, suffix: str = "") -> Dict: """ Get the embedding net nodes with the given tf.GraphDef object @@ -120,6 +120,8 @@ def get_embedding_net_nodes_from_graph_def(graph_def: tf.GraphDef) -> Dict: ---------- graph_def The input tf.GraphDef object + suffix : str, optional + The scope suffix Returns ---------- @@ -127,7 +129,7 @@ def get_embedding_net_nodes_from_graph_def(graph_def: tf.GraphDef) -> Dict: The embedding net nodes within the given tf.GraphDef object """ embedding_net_nodes = {} - embedding_net_pattern = "filter_type_\d+/matrix_\d+_\d+|filter_type_\d+/bias_\d+_\d+|filter_type_\d+/idt_\d+_\d+|filter_type_all/matrix_\d+_\d+|filter_type_all/bias_\d+_\d+|filter_type_all/idt_\d+_\d" + embedding_net_pattern = f"filter_type_\d+{suffix}/matrix_\d+_\d+|filter_type_\d+{suffix}/bias_\d+_\d+|filter_type_\d+{suffix}/idt_\d+_\d+|filter_type_all{suffix}/matrix_\d+_\d+|filter_type_all{suffix}/bias_\d+_\d+|filter_type_all{suffix}/idt_\d+_\d" for node in graph_def.node: if re.fullmatch(embedding_net_pattern, node.name) != None: embedding_net_nodes[node.name] = node.attr["value"].tensor diff --git a/deepmd/utils/tabulate.py b/deepmd/utils/tabulate.py index f1057b38f2..9cbcac6d6a 100644 --- a/deepmd/utils/tabulate.py +++ b/deepmd/utils/tabulate.py @@ -34,12 +34,16 @@ class DPTabulate(): For example, `[[0, 1]]` means no interaction between type 0 and type 1. activation_function The activation function in the embedding net. Supported options are {"tanh","gelu"} in common.ACTIVATION_FN_DICT. + suffix : str, optional + The suffix of the scope """ def __init__(self, model_file : str, type_one_side : bool = False, exclude_types : List[List[int]] = [], - activation_fn : Callable[[tf.Tensor], tf.Tensor] = tf.nn.tanh) -> None: + activation_fn : Callable[[tf.Tensor], tf.Tensor] = tf.nn.tanh, + suffix : str = "", + ) -> None: """ Constructor """ @@ -47,8 +51,9 @@ def __init__(self, self.model_file = model_file self.type_one_side = type_one_side self.exclude_types = exclude_types + self.suffix = suffix if self.type_one_side and len(self.exclude_types) != 0: - raise RunTimeError('"type_one_side" is not compatible with "exclude_types"') + raise RuntimeError('"type_one_side" is not compatible with "exclude_types"') # functype if activation_fn == ACTIVATION_FN_DICT["tanh"]: @@ -56,7 +61,7 @@ def __init__(self, elif activation_fn == ACTIVATION_FN_DICT["gelu"]: self.functype = 2 else: - raise RunTimeError("Unknown actication function type!") + raise RuntimeError("Unknown actication function type!") self.activation_fn = activation_fn self.graph, self.graph_def = load_graph_def(self.model_file) @@ -72,15 +77,15 @@ def __init__(self, self.sel_a = self.graph.get_operation_by_name('DescrptSeA').get_attr('sel_a') self.descrpt = self.graph.get_operation_by_name ('DescrptSeA') - self.davg = get_tensor_by_name_from_graph(self.graph, 'descrpt_attr/t_avg') - self.dstd = get_tensor_by_name_from_graph(self.graph, 'descrpt_attr/t_std') + self.davg = get_tensor_by_name_from_graph(self.graph, f'descrpt_attr{self.suffix}/t_avg') + self.dstd = get_tensor_by_name_from_graph(self.graph, f'descrpt_attr{self.suffix}/t_std') self.ntypes = get_tensor_by_name_from_graph(self.graph, 'descrpt_attr/ntypes') self.rcut = self.descrpt.get_attr('rcut_r') self.rcut_smth = self.descrpt.get_attr('rcut_r_smth') - self.embedding_net_nodes = get_embedding_net_nodes_from_graph_def(self.graph_def) + self.embedding_net_nodes = get_embedding_net_nodes_from_graph_def(self.graph_def, suffix=self.suffix) for tt in self.exclude_types: if (tt[0] not in range(self.ntypes)) or (tt[1] not in range(self.ntypes)): @@ -174,14 +179,14 @@ def _get_bias(self): bias["layer_" + str(layer)] = [] if self.type_one_side: for ii in range(0, self.ntypes): - tensor_value = np.frombuffer (self.embedding_net_nodes["filter_type_all/bias_" + str(layer) + "_" + str(ii)].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes["filter_type_all/bias_" + str(layer) + "_" + str(ii)].tensor_shape).as_list() + tensor_value = np.frombuffer (self.embedding_net_nodes[f"filter_type_all{self.suffix}/bias_{layer}_{ii}"].tensor_content) + tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_all{self.suffix}/bias_{layer}_{ii}"].tensor_shape).as_list() bias["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: for ii in range(0, self.ntypes * self.ntypes): if (ii // self.ntypes, int(ii % self.ntypes)) not in self.exclude_types: - tensor_value = np.frombuffer(self.embedding_net_nodes["filter_type_" + str(ii // self.ntypes) + "/bias_" + str(layer) + "_" + str(int(ii % self.ntypes))].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes["filter_type_" + str(ii // self.ntypes) + "/bias_" + str(layer) + "_" + str(int(ii % self.ntypes))].tensor_shape).as_list() + tensor_value = np.frombuffer(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/bias_{layer}_{ii % self.ntypes}"].tensor_content) + tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/bias_{layer}_{ii % self.ntypes}"].tensor_shape).as_list() bias["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: bias["layer_" + str(layer)].append(np.array([])) @@ -193,14 +198,14 @@ def _get_matrix(self): matrix["layer_" + str(layer)] = [] if self.type_one_side: for ii in range(0, self.ntypes): - tensor_value = np.frombuffer (self.embedding_net_nodes["filter_type_all/matrix_" + str(layer) + "_" + str(ii)].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes["filter_type_all/matrix_" + str(layer) + "_" + str(ii)].tensor_shape).as_list() + tensor_value = np.frombuffer (self.embedding_net_nodes[f"filter_type_all{self.suffix}/matrix_{layer}_{ii}"].tensor_content) + tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_all{self.suffix}/matrix_{layer}_{ii}"].tensor_shape).as_list() matrix["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: for ii in range(0, self.ntypes * self.ntypes): if (ii // self.ntypes, int(ii % self.ntypes)) not in self.exclude_types: - tensor_value = np.frombuffer(self.embedding_net_nodes["filter_type_" + str(ii // self.ntypes) + "/matrix_" + str(layer) + "_" + str(int(ii % self.ntypes))].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes["filter_type_" + str(ii // self.ntypes) + "/matrix_" + str(layer) + "_" + str(int(ii % self.ntypes))].tensor_shape).as_list() + tensor_value = np.frombuffer(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/matrix_{layer}_{ii % self.ntypes}"].tensor_content) + tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/matrix_{layer}_{ii % self.ntypes}"].tensor_shape).as_list() matrix["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: matrix["layer_" + str(layer)].append(np.array([])) From a5bdd14f6fbcd1b174712c1e06fc45346acb586f Mon Sep 17 00:00:00 2001 From: Davide Tisi <47503434+DavideTisi@users.noreply.github.com> Date: Sat, 4 Sep 2021 13:39:56 +0200 Subject: [PATCH 22/34] interface for deepmd with the centroids atoms, full 3x3 "atomic-virial" (#1093) * done interface for deepmd with the centroids atoms * Update lammps-command.md Added documentation to the computation of the heat flux --- README.md | 1 + doc/third-party/lammps-command.md | 50 ++++++++++++++++++++++++++- source/lmp/pair_deepmd.cpp | 56 ++++++++++++++++++++++--------- 3 files changed, 91 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e27b6623a2..c05be445c8 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![GitHub release](https://img.shields.io/github/release/deepmodeling/deepmd-kit.svg?maxAge=86400)](https://github.com/deepmodeling/deepmd-kit/releases) [![doi:10.1016/j.cpc.2018.03.016](https://img.shields.io/badge/DOI-10.1016%2Fj.cpc.2018.03.016-blue)](https://doi.org/10.1016/j.cpc.2020.107206) [![offline packages](https://img.shields.io/github/downloads/deepmodeling/deepmd-kit/total?label=offline%20packages)](https://github.com/deepmodeling/deepmd-kit/releases) +[![conda install](https://img.shields.io/badge/downloads-9k%20total-green.svg?style=round-square&label=conda%20install)](https://anaconda.org/deepmodeling/deepmd-kit) [![pip install](https://img.shields.io/pypi/dm/deepmd-kit?label=pip%20install)](https://pypi.org/project/deepmd-kit) [![docker pull](https://img.shields.io/docker/pulls/deepmodeling/deepmd-kit)](https://hub.docker.com/r/deepmodeling/deepmd-kit) [![Documentation Status](https://readthedocs.org/projects/deepmd/badge/)](https://deepmd.readthedocs.io/) diff --git a/doc/third-party/lammps-command.md b/doc/third-party/lammps-command.md index 805361120b..7218b75090 100644 --- a/doc/third-party/lammps-command.md +++ b/doc/third-party/lammps-command.md @@ -94,5 +94,53 @@ kspace_modify gewald 0.45 ``` Please notice that the DeePMD does nothing to the direct space part of the electrostatic interaction, because this part is assumed to be fitted in the DeePMD model (the direct space cut-off is thus the cut-off of the DeePMD model). The splitting parameter `gewald` is modified by the `kspace_modify` command. +## Use of the centroid/stress/atom to get the full 3x3 "atomic-virial" + +The [DeePMD-kit](https://github.com/deepmodeling/deepmd-kit) allows also the computation of per-atom stress tensor defined as: + + + +Where is the atomic position of nth atom, velocity of atom and the derivative of the atomic energy. + +In LAMMPS one can get the per-atom stress using the command `centroid/stress/atom`: +```bash +compute ID group-ID centroid/stress/atom NULL virial +``` +see [LAMMPS doc page](https://docs.lammps.org/compute_stress_atom.html#thompson2) for more detailes on the meaning of the keywords. +### Examples +In order of computing the 9-component per-atom stress +```bash +compute stress all centroid/stress/atom NULL virial +``` +Thus `c_stress` is an array with 9 component in the order `xx,yy,zz,xy,xz,yz,yx,zx,zy`. + +If you use this feature please cite [D. Tisi, L. Zhang, R. Bertossa, H. Wang, R. Car, S. Baroni - arXiv preprint arXiv:2108.10850, 2021](https://arxiv.org/abs/2108.10850) + +## Computation of heat flux +Using per-atom stress tensor one can, for example, compute the heat flux defined as: + + + +to compute the heat flux with LAMMPS: +```bash +compute ke_ID all ke/atom +compute pe_ID all pe/atom +compute stress_ID group-ID centroid/stress/atom NULL virial +compute flux_ID all heat/flux ke_ID pe_ID stress_ID +``` + +### Examples + +```bash +compute ke all ke/atom +compute pe all pe/atom +compute stress all centroid/stress/atom NULL virial +compute flux all heat/flux ke pe stress +``` +`c_flux` is a global vector of length 6. The first three components are the `x`, `y` and `z` components of the full heat flux vector. The others are the components of the so-called convective portion, see [LAMMPS doc page](https://docs.lammps.org/compute_heat_flux.html) for more detailes. + +If you use these features please cite [D. Tisi, L. Zhang, R. Bertossa, H. Wang, R. Car, S. Baroni - arXiv preprint arXiv:2108.10850, 2021](https://arxiv.org/abs/2108.10850) + + [DP]:https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.120.143001 -[DP-SE]:https://dl.acm.org/doi/10.5555/3327345.3327356 \ No newline at end of file +[DP-SE]:https://dl.acm.org/doi/10.5555/3327345.3327356 diff --git a/source/lmp/pair_deepmd.cpp b/source/lmp/pair_deepmd.cpp index e1467631a4..80b64eefb9 100644 --- a/source/lmp/pair_deepmd.cpp +++ b/source/lmp/pair_deepmd.cpp @@ -238,6 +238,7 @@ PairDeepMD::PairDeepMD(LAMMPS *lmp) error->all(FLERR,"Pair deepmd requires metal unit, please set it by \"units metal\""); } restartinfo = 1; + centroidstressflag = 2 ; // set centroidstressflag = 2 to allow the use of the centroid/stress/atom. Added by Davide Tisi pppmflag = 1; respa_enable = 0; writedata = 0; @@ -366,7 +367,8 @@ void PairDeepMD::compute(int eflag, int vflag) if (do_ghost) { deepmd::InputNlist lmp_list (list->inum, list->ilist, list->numneigh, list->firstneigh); if (single_model || multi_models_no_mod_devi) { - if ( ! (eflag_atom || vflag_atom) ) { + //cvflag_atom is the right flag for the cvatom matrix + if ( ! (eflag_atom || cvflag_atom) ) { #ifdef HIGH_PREC deep_pot.compute (dener, dforce, dvirial, dcoord, dtype, dbox, nghost, lmp_list, ago, fparam, daparam); #else @@ -409,14 +411,26 @@ void PairDeepMD::compute(int eflag, int vflag) if (eflag_atom) { for (int ii = 0; ii < nlocal; ++ii) eatom[ii] += deatom[ii]; } - if (vflag_atom) { + // Added by Davide Tisi 2020 + // interface the atomic virial computed by DeepMD + // with the one used in centroid atoms + if (cvflag_atom) { for (int ii = 0; ii < nall; ++ii){ - vatom[ii][0] += 1.0 * dvatom[9*ii+0]; - vatom[ii][1] += 1.0 * dvatom[9*ii+4]; - vatom[ii][2] += 1.0 * dvatom[9*ii+8]; - vatom[ii][3] += 1.0 * dvatom[9*ii+3]; - vatom[ii][4] += 1.0 * dvatom[9*ii+6]; - vatom[ii][5] += 1.0 * dvatom[9*ii+7]; + //vatom[ii][0] += 1.0 * dvatom[9*ii+0]; + //vatom[ii][1] += 1.0 * dvatom[9*ii+4]; + //vatom[ii][2] += 1.0 * dvatom[9*ii+8]; + //vatom[ii][3] += 1.0 * dvatom[9*ii+3]; + //vatom[ii][4] += 1.0 * dvatom[9*ii+6]; + //vatom[ii][5] += 1.0 * dvatom[9*ii+7]; + cvatom[ii][0] += -1.0 * dvatom[9*ii+0]; // xx + cvatom[ii][1] += -1.0 * dvatom[9*ii+4]; // yy + cvatom[ii][2] += -1.0 * dvatom[9*ii+8]; // zz + cvatom[ii][3] += -1.0 * dvatom[9*ii+3]; // xy + cvatom[ii][4] += -1.0 * dvatom[9*ii+6]; // xz + cvatom[ii][5] += -1.0 * dvatom[9*ii+7]; // yz + cvatom[ii][6] += -1.0 * dvatom[9*ii+1]; // yx + cvatom[ii][7] += -1.0 * dvatom[9*ii+2]; // zx + cvatom[ii][8] += -1.0 * dvatom[9*ii+5]; // zy } } } @@ -489,14 +503,26 @@ void PairDeepMD::compute(int eflag, int vflag) if (eflag_atom) { for (int ii = 0; ii < nlocal; ++ii) eatom[ii] += deatom[ii]; } - if (vflag_atom) { + // Added by Davide Tisi 2020 + // interface the atomic virial computed by DeepMD + // with the one used in centroid atoms + if (cvflag_atom) { for (int ii = 0; ii < nall; ++ii){ - vatom[ii][0] += 1.0 * dvatom[9*ii+0]; - vatom[ii][1] += 1.0 * dvatom[9*ii+4]; - vatom[ii][2] += 1.0 * dvatom[9*ii+8]; - vatom[ii][3] += 1.0 * dvatom[9*ii+3]; - vatom[ii][4] += 1.0 * dvatom[9*ii+6]; - vatom[ii][5] += 1.0 * dvatom[9*ii+7]; + //vatom[ii][0] += 1.0 * dvatom[9*ii+0]; + //vatom[ii][1] += 1.0 * dvatom[9*ii+4]; + //vatom[ii][2] += 1.0 * dvatom[9*ii+8]; + //vatom[ii][3] += 1.0 * dvatom[9*ii+3]; + //vatom[ii][4] += 1.0 * dvatom[9*ii+6]; + //vatom[ii][5] += 1.0 * dvatom[9*ii+7]; + cvatom[ii][0] += -1.0 * dvatom[9*ii+0]; // xx + cvatom[ii][1] += -1.0 * dvatom[9*ii+4]; // yy + cvatom[ii][2] += -1.0 * dvatom[9*ii+8]; // zz + cvatom[ii][3] += -1.0 * dvatom[9*ii+3]; // xy + cvatom[ii][4] += -1.0 * dvatom[9*ii+6]; // xz + cvatom[ii][5] += -1.0 * dvatom[9*ii+7]; // yz + cvatom[ii][6] += -1.0 * dvatom[9*ii+1]; // yx + cvatom[ii][7] += -1.0 * dvatom[9*ii+2]; // zx + cvatom[ii][8] += -1.0 * dvatom[9*ii+5]; // zy } } if (out_freq > 0 && update->ntimestep % out_freq == 0) { From 32ccbb5461520089fbe55a879d9cefcf1910e779 Mon Sep 17 00:00:00 2001 From: Shaochen Shi Date: Mon, 6 Sep 2021 16:12:35 +0800 Subject: [PATCH 23/34] Fix gradient not averaged when parallel training. (#1104) * Fix gradient not averaged when parallel training. * Correct throughput metrics and explain CPU runtime in the parallel-training tutorial. --- deepmd/train/trainer.py | 8 ++++---- doc/train/parallel-training.md | 14 ++++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index 0fa08e77a2..0ae878bd7a 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -384,10 +384,10 @@ def _build_training(self): optimizer = self.run_opt._HVD.DistributedOptimizer(optimizer) else: optimizer = tf.train.AdamOptimizer(learning_rate = self.learning_rate) - grads = tf.gradients(self.l2_l, trainable_variables) - apply_op = optimizer.apply_gradients (zip (grads, trainable_variables), - global_step=self.global_step, - name='train_step') + apply_op = optimizer.minimize(loss=self.l2_l, + global_step=self.global_step, + var_list=trainable_variables, + name='train_step') train_ops = [apply_op] + self._extra_train_ops self.train_op = tf.group(*train_ops) log.info("built training") diff --git a/doc/train/parallel-training.md b/doc/train/parallel-training.md index 609dc8721d..d619569c8d 100644 --- a/doc/train/parallel-training.md +++ b/doc/train/parallel-training.md @@ -5,13 +5,19 @@ Currently, parallel training is enabled in a sychoronized way with help of [Horo Testing `examples/water/se_e2_a` on a 8-GPU host, linear acceleration can be observed with increasing number of cards. | Num of GPU cards | Seconds every 100 samples | Samples per second | Speed up | | -- | -- | -- | -- | -| 1 | 1.6116 | 62.05 | 1.00 | -| 2 | 1.6310 | 61.31 | 1.98 | -| 4 | 1.6168 | 61.85 | 3.99 | -| 8 | 1.6212 | 61.68 | 7.95 | +| 1 | 1.4515 | 68.89 | 1.00 | +| 2 | 1.5962 | 62.65*2 | 1.82 | +| 4 | 1.7635 | 56.71*4 | 3.29 | +| 8 | 1.7267 | 57.91*8 | 6.72 | To experience this powerful feature, please intall Horovod and [mpi4py](https://github.com/mpi4py/mpi4py) first. For better performance on GPU, please follow tuning steps in [Horovod on GPU](https://github.com/horovod/horovod/blob/master/docs/gpus.rst). ```bash +# With GPU, prefer NCCL as communicator. +HOROVOD_WITHOUT_GLOO=1 HOROVOD_WITH_TENSORFLOW=1 HOROVOD_GPU_OPERATIONS=NCCL HOROVOD_NCCL_HOME=/path/to/nccl pip3 install horovod mpi4py +``` + +If your work in CPU environment, please prepare runtime as below: +```bash # By default, MPI is used as communicator. HOROVOD_WITHOUT_GLOO=1 HOROVOD_WITH_TENSORFLOW=1 pip install horovod mpi4py ``` From d5a0f6fa883231f9c101308bdd6193a882095875 Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Mon, 6 Sep 2021 16:32:12 +0800 Subject: [PATCH 24/34] Enable init-frz-model support for the original model (#1102) * enable init-frz-model support for the original model within the dp train interface * add init_variables method for ABC * add doc for embedding_net method --- deepmd/descriptor/descriptor.py | 20 ++++++++++++++ deepmd/descriptor/se_a.py | 19 ++++++++++++- deepmd/train/trainer.py | 16 ++++++----- deepmd/utils/network.py | 48 ++++++++++++++++++++++----------- 4 files changed, 79 insertions(+), 24 deletions(-) diff --git a/deepmd/descriptor/descriptor.py b/deepmd/descriptor/descriptor.py index 4516aa146c..f241f6ee15 100644 --- a/deepmd/descriptor/descriptor.py +++ b/deepmd/descriptor/descriptor.py @@ -283,3 +283,23 @@ def get_feed_dict(self, # TODO: currently only SeA has this method, but I think the method can be # moved here as it doesn't contain anything related to a specific descriptor raise NotImplementedError + + def init_variables(self, + embedding_net_variables: dict + ) -> None: + """ + Init the embedding net variables with the given dict + + Parameters + ---------- + embedding_net_variables + The input dict which stores the embedding net variables + + Notes + ----- + This method is called by others when the descriptor supported initialization from the given variables. + """ + # TODO: currently only SeA has this method, but I think the method can be + # moved here as it doesn't contain anything related to a specific descriptor + raise NotImplementedError( + "Descriptor %s doesn't support initialization from the given variables!" % type(self).__name__) diff --git a/deepmd/descriptor/se_a.py b/deepmd/descriptor/se_a.py index da600848fb..47e28522a9 100644 --- a/deepmd/descriptor/se_a.py +++ b/deepmd/descriptor/se_a.py @@ -157,6 +157,7 @@ def __init__ (self, self.dstd = None self.davg = None self.compress = False + self.embedding_net_variables = None self.place_holders = {} nei_type = np.array([]) for ii in range(self.ntypes): @@ -521,6 +522,21 @@ def get_feed_dict(self, } return feed_dict + + def init_variables(self, + embedding_net_variables: dict + ) -> None: + """ + Init the embedding net variables with the given dict + + Parameters + ---------- + embedding_net_variables + The input dict which stores the embedding net variables + """ + self.embedding_net_variables = embedding_net_variables + + def prod_force_virial(self, atom_ener : tf.Tensor, natoms : tf.Tensor @@ -766,7 +782,8 @@ def _filter_lower( bavg = bavg, seed = self.seed, trainable = trainable, - uniform_seed = self.uniform_seed) + uniform_seed = self.uniform_seed, + initial_variables = self.embedding_net_variables) if (not self.uniform_seed) and (self.seed is not None): self.seed += self.seed_shift else: # we can safely return the final xyz_scatter filled with zero directly diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index 0ae878bd7a..1f8e2b9af1 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -26,7 +26,7 @@ from deepmd.utils.neighbor_stat import NeighborStat from deepmd.utils.sess import run_sess from deepmd.utils.type_embed import TypeEmbedNet -from deepmd.utils.graph import get_tensor_by_name, get_fitting_net_variables +from deepmd.utils.graph import get_tensor_by_name, get_embedding_net_variables, get_fitting_net_variables from tensorflow.python.client import timeline from deepmd.env import op_module @@ -278,7 +278,6 @@ def _init_param(self, jdata): # if init the graph with the frozen model self.frz_model = None self.model_type = None - self.init_from_frz_model = False def build (self, @@ -694,14 +693,17 @@ def _init_from_frz_model(self): "which is not supported by the 'dp train init-frz-model' interface. " % self.run_opt.init_frz_model ) from e + if self.fitting_type != 'ener': + raise RuntimeError("The 'dp train init-frz-model' command only supports the 'ener' type fitting net currently!") # self.frz_model will control the self.model to import the descriptor from the given frozen model instead of building from scratch... # initialize fitting net with the given compressed frozen model - if self.model_type == 'compressed_model' and self.fitting_type == 'ener': - self.init_from_frz_model = True + if self.model_type == 'original_model': + self.descrpt.init_variables(get_embedding_net_variables(self.run_opt.init_frz_model)) + self.fitting.init_variables(get_fitting_net_variables(self.run_opt.init_frz_model)) + tf.constant("original_model", name = 'model_type', dtype = tf.string) + elif self.model_type == 'compressed_model': self.frz_model = self.run_opt.init_frz_model self.fitting.init_variables(get_fitting_net_variables(self.frz_model)) tf.constant("compressed_model", name = 'model_type', dtype = tf.string) - elif self.fitting_type != 'ener': - raise RuntimeError("The 'dp train init-frz-model' command only supports the 'ener' type fitting net currently!") else: - raise RuntimeError("The 'dp train init-frz-model' command only supports the compressed model currently!") + raise RuntimeError("Unknown model type %s" % self.model_type) diff --git a/deepmd/utils/network.py b/deepmd/utils/network.py index d42f3a5c48..5c78031167 100644 --- a/deepmd/utils/network.py +++ b/deepmd/utils/network.py @@ -92,7 +92,8 @@ def embedding_net(xx, bavg = 0.0, seed = None, trainable = True, - uniform_seed = False): + uniform_seed = False, + initial_variables = None): r"""The embedding network. The embedding network function :math:`\mathcal{N}` is constructed by is the @@ -141,6 +142,11 @@ def embedding_net(xx, Random seed for initializing network parameters trainable: boolean If the network is trainable + uniform_seed : boolean + Only for the purpose of backward compatibility, retrieves the old behavior of using the random seed + initial_variables : dict + The input dict which stores the embedding net variables + References ---------- @@ -152,37 +158,47 @@ def embedding_net(xx, outputs_size = [input_shape[1]] + network_size for ii in range(1, len(outputs_size)): - w = tf.get_variable('matrix_'+str(ii)+name_suffix, + w_initializer = tf.random_normal_initializer( + stddev=stddev/np.sqrt(outputs_size[ii]+outputs_size[ii-1]), + seed = seed if (seed is None or uniform_seed) else seed + ii*3+0 + ) + b_initializer = tf.random_normal_initializer( + stddev=stddev, + mean = bavg, + seed = seed if (seed is None or uniform_seed) else seed + 3*ii+1 + ) + if initial_variables is not None: + scope = tf.get_variable_scope().name + w_initializer = tf.constant_initializer(initial_variables[scope+'/matrix_'+str(ii)+name_suffix]) + b_initializer = tf.constant_initializer(initial_variables[scope+'/bias_'+str(ii)+name_suffix]) + w = tf.get_variable('matrix_'+str(ii)+name_suffix, [outputs_size[ii - 1], outputs_size[ii]], precision, - tf.random_normal_initializer( - stddev=stddev/np.sqrt(outputs_size[ii]+outputs_size[ii-1]), - seed = seed if (seed is None or uniform_seed) else seed + ii*3+0 - ), + w_initializer, trainable = trainable) variable_summaries(w, 'matrix_'+str(ii)+name_suffix) b = tf.get_variable('bias_'+str(ii)+name_suffix, [1, outputs_size[ii]], precision, - tf.random_normal_initializer( - stddev=stddev, - mean = bavg, - seed = seed if (seed is None or uniform_seed) else seed + 3*ii+1 - ), + b_initializer, trainable = trainable) variable_summaries(b, 'bias_'+str(ii)+name_suffix) hidden = tf.reshape(activation_fn(tf.matmul(xx, w) + b), [-1, outputs_size[ii]]) if resnet_dt : + idt_initializer = tf.random_normal_initializer( + stddev=0.001, + mean = 1.0, + seed = seed if (seed is None or uniform_seed) else seed + 3*ii+2 + ) + if initial_variables is not None: + scope = tf.get_variable_scope().name + idt_initializer = tf.constant_initializer(initial_variables[scope+'/idt_'+str(ii)+name_suffix]) idt = tf.get_variable('idt_'+str(ii)+name_suffix, [1, outputs_size[ii]], precision, - tf.random_normal_initializer( - stddev=0.001, - mean = 1.0, - seed = seed if (seed is None or uniform_seed) else seed + 3*ii+2 - ), + idt_initializer, trainable = trainable) variable_summaries(idt, 'idt_'+str(ii)+name_suffix) From 8727956414e212cdf7da46450f553b9ecf894a60 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 6 Sep 2021 04:52:02 -0400 Subject: [PATCH 25/34] merge duplicated NeighborStat.get_stat (#1103) Note: this is a simple fix to resolve #1088, but I think we should design a clear architecture to call neighbor stat. This should reduce the half of the time, but it may be still too long. We can consider some better algorithm to calculate neighbour stat (like KDtree?) for further optimization. --- deepmd/entrypoints/train.py | 12 +++++++++++- deepmd/train/trainer.py | 13 +++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/deepmd/entrypoints/train.py b/deepmd/entrypoints/train.py index bbb1e55bd2..a91d0aa3cf 100755 --- a/deepmd/entrypoints/train.py +++ b/deepmd/entrypoints/train.py @@ -10,7 +10,7 @@ from typing import Dict, List, Optional, Any from deepmd.common import data_requirement, expand_sys_str, j_loader, j_must_have -from deepmd.env import tf, reset_default_tf_session_config +from deepmd.env import tf, reset_default_tf_session_config, GLOBAL_TF_FLOAT_PRECISION from deepmd.infer.data_modifier import DipoleChargeModifier from deepmd.train.run_options import BUILD, CITATION, WELCOME, RunOptions from deepmd.train.trainer import DPTrainer @@ -262,6 +262,16 @@ def get_nbor_stat(jdata, rcut): neistat = NeighborStat(ntypes, rcut) min_nbor_dist, max_nbor_size = neistat.get_stat(train_data) + + # moved from traier.py as duplicated + # TODO: this is a simple fix but we should have a clear + # architecture to call neighbor stat + tf.constant(min_nbor_dist, + name = 'train_attr/min_nbor_dist', + dtype = GLOBAL_TF_FLOAT_PRECISION) + tf.constant(max_nbor_size, + name = 'train_attr/max_nbor_size', + dtype = GLOBAL_TF_FLOAT_PRECISION) return min_nbor_dist, max_nbor_size def get_sel(jdata, rcut): diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index 1f8e2b9af1..4701ed0848 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -313,16 +313,9 @@ def build (self, if self.run_opt.init_mode == 'init_from_frz_model': self._init_from_frz_model() - self.neighbor_stat \ - = NeighborStat(self.ntypes, self.descrpt.get_rcut()) - self.min_nbor_dist, self.max_nbor_size \ - = self.neighbor_stat.get_stat(data) - tf.constant(self.min_nbor_dist, - name = 'train_attr/min_nbor_dist', - dtype = GLOBAL_TF_FLOAT_PRECISION) - tf.constant(self.max_nbor_size, - name = 'train_attr/max_nbor_size', - dtype = GLOBAL_TF_FLOAT_PRECISION) + # neighbor_stat is moved to train.py as duplicated + # TODO: this is a simple fix but we should have a clear + # architecture to call neighbor stat else : self.descrpt.enable_compression(self.model_param['compress']["min_nbor_dist"], self.model_param['compress']['model_file'], self.model_param['compress']['table_config'][0], self.model_param['compress']['table_config'][1], self.model_param['compress']['table_config'][2], self.model_param['compress']['table_config'][3]) self.fitting.init_variables(get_fitting_net_variables(self.model_param['compress']['model_file'])) From dd3c1de39c717d7fc724fffeab2ed91f94f3d271 Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Tue, 7 Sep 2021 09:41:25 +0800 Subject: [PATCH 26/34] Update doc for init-frz-model (#1107) * enable init-frz-model support for the original model within the dp train interface * add init_variables method for ABC * add doc for embedding_net method * update doc for init-frz-model --- doc/train/training-advanced.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/train/training-advanced.md b/doc/train/training-advanced.md index 32deaca906..ea9e1e8075 100644 --- a/doc/train/training-advanced.md +++ b/doc/train/training-advanced.md @@ -109,7 +109,7 @@ optional arguments: **`--restart model.ckpt`**, continues the training from the checkpoint `model.ckpt`. -**`--init-frz-model frozen_model.pb`**, initializes the training with an existing model that is stored in `frozen_model.pb`. Note that the `init-frz-model` command only supports the compressed model currently! +**`--init-frz-model frozen_model.pb`**, initializes the training with an existing model that is stored in `frozen_model.pb`. On some resources limited machines, one may want to control the number of threads used by DeePMD-kit. This is achieved by three environmental variables: `OMP_NUM_THREADS`, `TF_INTRA_OP_PARALLELISM_THREADS` and `TF_INTER_OP_PARALLELISM_THREADS`. `OMP_NUM_THREADS` controls the multithreading of DeePMD-kit implemented operations. `TF_INTRA_OP_PARALLELISM_THREADS` and `TF_INTER_OP_PARALLELISM_THREADS` controls `intra_op_parallelism_threads` and `inter_op_parallelism_threads`, which are Tensorflow configurations for multithreading. An explanation is found [here](https://stackoverflow.com/questions/41233635/meaning-of-inter-op-parallelism-threads-and-intra-op-parallelism-threads). From 904ec11ef61f4f04c967c7dcfbb714abb1e433b5 Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Tue, 7 Sep 2021 09:42:38 +0800 Subject: [PATCH 27/34] fix bug of single precision model compression (#1110) --- deepmd/entrypoints/compress.py | 6 +++--- deepmd/entrypoints/train.py | 6 +++--- deepmd/utils/graph.py | 4 ++-- deepmd/utils/tabulate.py | 20 ++++++++++++-------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/deepmd/entrypoints/compress.py b/deepmd/entrypoints/compress.py index 0b0ffb4306..58c3c2a075 100644 --- a/deepmd/entrypoints/compress.py +++ b/deepmd/entrypoints/compress.py @@ -5,8 +5,8 @@ import logging from typing import Optional -from deepmd.env import tf -from deepmd.common import j_loader, GLOBAL_TF_FLOAT_PRECISION +from deepmd.common import j_loader +from deepmd.env import tf, GLOBAL_ENER_FLOAT_PRECISION from deepmd.utils.argcheck import normalize from deepmd.utils.compat import updata_deepmd_input from deepmd.utils.errors import GraphTooLargeError, GraphWithoutTensorError @@ -89,7 +89,7 @@ def compress( tf.constant(t_min_nbor_dist, name = 'train_attr/min_nbor_dist', - dtype = GLOBAL_TF_FLOAT_PRECISION) + dtype = GLOBAL_ENER_FLOAT_PRECISION) jdata["model"]["compress"] = {} jdata["model"]["compress"]["type"] = 'se_e2_a' jdata["model"]["compress"]["compress"] = True diff --git a/deepmd/entrypoints/train.py b/deepmd/entrypoints/train.py index a91d0aa3cf..817d603f3c 100755 --- a/deepmd/entrypoints/train.py +++ b/deepmd/entrypoints/train.py @@ -10,7 +10,7 @@ from typing import Dict, List, Optional, Any from deepmd.common import data_requirement, expand_sys_str, j_loader, j_must_have -from deepmd.env import tf, reset_default_tf_session_config, GLOBAL_TF_FLOAT_PRECISION +from deepmd.env import tf, reset_default_tf_session_config, GLOBAL_ENER_FLOAT_PRECISION from deepmd.infer.data_modifier import DipoleChargeModifier from deepmd.train.run_options import BUILD, CITATION, WELCOME, RunOptions from deepmd.train.trainer import DPTrainer @@ -268,10 +268,10 @@ def get_nbor_stat(jdata, rcut): # architecture to call neighbor stat tf.constant(min_nbor_dist, name = 'train_attr/min_nbor_dist', - dtype = GLOBAL_TF_FLOAT_PRECISION) + dtype = GLOBAL_ENER_FLOAT_PRECISION) tf.constant(max_nbor_size, name = 'train_attr/max_nbor_size', - dtype = GLOBAL_TF_FLOAT_PRECISION) + dtype = tf.int32) return min_nbor_dist, max_nbor_size def get_sel(jdata, rcut): diff --git a/deepmd/utils/graph.py b/deepmd/utils/graph.py index 959f6bf51b..ed10108dbb 100644 --- a/deepmd/utils/graph.py +++ b/deepmd/utils/graph.py @@ -178,7 +178,7 @@ def get_embedding_net_variables_from_graph_def(graph_def : tf.GraphDef) -> Dict: dtype = tf.as_dtype(node.dtype).as_numpy_dtype tensor_shape = tf.TensorShape(node.tensor_shape).as_list() if (len(tensor_shape) != 1) or (tensor_shape[0] != 1): - tensor_value = np.frombuffer(node.tensor_content) + tensor_value = np.frombuffer(node.tensor_content, dtype = tf.as_dtype(node.dtype).as_numpy_dtype) else: tensor_value = get_tensor_by_type(node, dtype) embedding_net_variables[item] = np.reshape(tensor_value, tensor_shape) @@ -266,7 +266,7 @@ def get_fitting_net_variables_from_graph_def(graph_def : tf.GraphDef) -> Dict: dtype= tf.as_dtype(node.dtype).as_numpy_dtype tensor_shape = tf.TensorShape(node.tensor_shape).as_list() if (len(tensor_shape) != 1) or (tensor_shape[0] != 1): - tensor_value = np.frombuffer(node.tensor_content) + tensor_value = np.frombuffer(node.tensor_content, dtype = tf.as_dtype(node.dtype).as_numpy_dtype) else: tensor_value = get_tensor_by_type(node, dtype) fitting_net_variables[item] = np.reshape(tensor_value, tensor_shape) diff --git a/deepmd/utils/tabulate.py b/deepmd/utils/tabulate.py index 9cbcac6d6a..fe95173890 100644 --- a/deepmd/utils/tabulate.py +++ b/deepmd/utils/tabulate.py @@ -179,14 +179,16 @@ def _get_bias(self): bias["layer_" + str(layer)] = [] if self.type_one_side: for ii in range(0, self.ntypes): - tensor_value = np.frombuffer (self.embedding_net_nodes[f"filter_type_all{self.suffix}/bias_{layer}_{ii}"].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_all{self.suffix}/bias_{layer}_{ii}"].tensor_shape).as_list() + node = self.embedding_net_nodes[f"filter_type_all{self.suffix}/bias_{layer}_{ii}"] + tensor_value = np.frombuffer (node.tensor_content, dtype = tf.as_dtype(node.dtype).as_numpy_dtype) + tensor_shape = tf.TensorShape(node.tensor_shape).as_list() bias["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: for ii in range(0, self.ntypes * self.ntypes): if (ii // self.ntypes, int(ii % self.ntypes)) not in self.exclude_types: - tensor_value = np.frombuffer(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/bias_{layer}_{ii % self.ntypes}"].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/bias_{layer}_{ii % self.ntypes}"].tensor_shape).as_list() + node = self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/bias_{layer}_{ii % self.ntypes}"] + tensor_value = np.frombuffer(node.tensor_content, dtype = tf.as_dtype(node.dtype).as_numpy_dtype) + tensor_shape = tf.TensorShape(node.tensor_shape).as_list() bias["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: bias["layer_" + str(layer)].append(np.array([])) @@ -198,14 +200,16 @@ def _get_matrix(self): matrix["layer_" + str(layer)] = [] if self.type_one_side: for ii in range(0, self.ntypes): - tensor_value = np.frombuffer (self.embedding_net_nodes[f"filter_type_all{self.suffix}/matrix_{layer}_{ii}"].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_all{self.suffix}/matrix_{layer}_{ii}"].tensor_shape).as_list() + node = self.embedding_net_nodes[f"filter_type_all{self.suffix}/matrix_{layer}_{ii}"] + tensor_value = np.frombuffer (node.tensor_content, dtype = tf.as_dtype(node.dtype).as_numpy_dtype) + tensor_shape = tf.TensorShape(node.tensor_shape).as_list() matrix["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: for ii in range(0, self.ntypes * self.ntypes): if (ii // self.ntypes, int(ii % self.ntypes)) not in self.exclude_types: - tensor_value = np.frombuffer(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/matrix_{layer}_{ii % self.ntypes}"].tensor_content) - tensor_shape = tf.TensorShape(self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/matrix_{layer}_{ii % self.ntypes}"].tensor_shape).as_list() + node = self.embedding_net_nodes[f"filter_type_{ii // self.ntypes}{self.suffix}/matrix_{layer}_{ii % self.ntypes}"] + tensor_value = np.frombuffer(node.tensor_content, dtype = tf.as_dtype(node.dtype).as_numpy_dtype) + tensor_shape = tf.TensorShape(node.tensor_shape).as_list() matrix["layer_" + str(layer)].append(np.reshape(tensor_value, tensor_shape)) else: matrix["layer_" + str(layer)].append(np.array([])) From 2a71494189867ac08e420f61824fbb71901e094b Mon Sep 17 00:00:00 2001 From: Denghui Lu Date: Tue, 7 Sep 2021 09:42:59 +0800 Subject: [PATCH 28/34] fix bug of single precision transfer (#1111) --- deepmd/entrypoints/transfer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deepmd/entrypoints/transfer.py b/deepmd/entrypoints/transfer.py index 576df74c80..3a755fd61a 100644 --- a/deepmd/entrypoints/transfer.py +++ b/deepmd/entrypoints/transfer.py @@ -130,7 +130,7 @@ def transform_graph(raw_graph: tf.Graph, old_graph: tf.Graph) -> tf.Graph: if raw_graph_dtype == np.float16: if old_graph_dtype == np.float64 or old_graph_dtype == np.float32: if (len(tensor_shape) != 1) or (tensor_shape[0] != 1): - tensor = np.frombuffer(old_node.tensor_content).astype(raw_graph_dtype) + tensor = np.frombuffer(old_node.tensor_content, dtype = raw_graph_dtype) cp_attr.from_array(tensor, tf.float16, shape = tensor_shape) else: tensor = load_tensor(old_node, old_graph_dtype, raw_graph_dtype) @@ -143,7 +143,7 @@ def transform_graph(raw_graph: tf.Graph, old_graph: tf.Graph) -> tf.Graph: elif raw_graph_dtype == np.float64 or raw_graph_dtype == np.float32: if old_graph_dtype == np.float64 or old_graph_dtype == np.float32: if (len(tensor_shape) != 1) or (tensor_shape[0] != 1): - tensor = np.frombuffer(old_node.tensor_content).astype(raw_graph_dtype) + tensor = np.frombuffer(old_node.tensor_content, dtype = raw_graph_dtype) cp_attr.from_str(tensor) else: tensor = load_tensor(old_node, old_graph_dtype, raw_graph_dtype) From 1fbf4746a475788bed17fd0774fde5dddbe6dec5 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 8 Sep 2021 07:56:41 -0400 Subject: [PATCH 29/34] fix LAMMPS_VERSION_NUMBER condition (#1116) When I debug #1109, I accidentally find the LAMMPS_VERSION_NUMBER condition is wrong, making builds fail. (but this is not related to #1109) --- source/lmp/fix_dplr.cpp | 4 ++-- source/lmp/pppm_dplr.cpp | 2 +- source/lmp/pppm_dplr.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/lmp/fix_dplr.cpp b/source/lmp/fix_dplr.cpp index bfb2b9f543..1d2323a027 100644 --- a/source/lmp/fix_dplr.cpp +++ b/source/lmp/fix_dplr.cpp @@ -41,7 +41,7 @@ FixDPLR::FixDPLR(LAMMPS *lmp, int narg, char **arg) efield_fsum_all(4, 0.0), efield_force_flag(0) { -#if LAMMPS_VERSION_NUMBER>=20210702 +#if LAMMPS_VERSION_NUMBER>=20210210 // lammps/lammps#2560 energy_global_flag = 1; virial_global_flag = 1; @@ -123,7 +123,7 @@ FixDPLR::FixDPLR(LAMMPS *lmp, int narg, char **arg) int FixDPLR::setmask() { int mask = 0; -#if LAMMPS_VERSION_NUMBER<20210702 +#if LAMMPS_VERSION_NUMBER<20210210 // THERMO_ENERGY removed in lammps/lammps#2560 mask |= THERMO_ENERGY; #endif diff --git a/source/lmp/pppm_dplr.cpp b/source/lmp/pppm_dplr.cpp index cd4e7da2ba..0fda38e4f3 100644 --- a/source/lmp/pppm_dplr.cpp +++ b/source/lmp/pppm_dplr.cpp @@ -28,7 +28,7 @@ enum{FORWARD_IK,FORWARD_AD,FORWARD_IK_PERATOM,FORWARD_AD_PERATOM}; /* ---------------------------------------------------------------------- */ -#if LAMMPS_VERSION_NUMBER<20190201 +#if LAMMPS_VERSION_NUMBER<20181109 // See lammps/lammps#1165 PPPMDPLR::PPPMDPLR(LAMMPS *lmp, int narg, char **arg) : PPPM(lmp, narg, arg) diff --git a/source/lmp/pppm_dplr.h b/source/lmp/pppm_dplr.h index df436170f9..20e4107385 100644 --- a/source/lmp/pppm_dplr.h +++ b/source/lmp/pppm_dplr.h @@ -21,7 +21,7 @@ namespace LAMMPS_NS { class PPPMDPLR : public PPPM { public: -#if LAMMPS_VERSION_NUMBER<20190201 +#if LAMMPS_VERSION_NUMBER<20181109 // See lammps/lammps#1165 PPPMDPLR(class LAMMPS *, int, char **); #else From 60797e0ceb2da0d4871939ab4e258e79face67d9 Mon Sep 17 00:00:00 2001 From: Chenxing Luo Date: Wed, 8 Sep 2021 10:41:51 -0400 Subject: [PATCH 30/34] Fix missing `std::numeric_limits` (#1113) * Fix missing `std::numeric_limits` - Include `` header, fix missing `std::numeric_limits` when compiling with GCC 11.0. --- source/lib/src/neighbor_list.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/lib/src/neighbor_list.cc b/source/lib/src/neighbor_list.cc index c3cd376fbe..cae7630430 100644 --- a/source/lib/src/neighbor_list.cc +++ b/source/lib/src/neighbor_list.cc @@ -1,6 +1,7 @@ #include "neighbor_list.h" #include "device.h" #include +#include // #include // using namespace std; From 97be2f5a1014b9838af4235c7ca9248f8b8b1923 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 8 Sep 2021 10:50:28 -0400 Subject: [PATCH 31/34] support init_frz_model for hybrid descriptor (#1112) * support init_frz_model for hybrid descriptor Refactors some methods to implement it. Also fixes some typos. * rename `graph_def` to `model_file` Co-authored-by: Denghui Lu Co-authored-by: Denghui Lu --- deepmd/descriptor/descriptor.py | 57 ++++++++++++++++++++---- deepmd/descriptor/hybrid.py | 52 ++++++++++++++++++++++ deepmd/descriptor/se_a.py | 78 ++++++++++++--------------------- deepmd/model/ener.py | 7 +-- deepmd/model/tensor.py | 9 ++-- deepmd/train/trainer.py | 2 +- deepmd/utils/graph.py | 20 ++++++--- 7 files changed, 150 insertions(+), 75 deletions(-) diff --git a/deepmd/descriptor/descriptor.py b/deepmd/descriptor/descriptor.py index f241f6ee15..893493a201 100644 --- a/deepmd/descriptor/descriptor.py +++ b/deepmd/descriptor/descriptor.py @@ -280,26 +280,65 @@ def get_feed_dict(self, feed_dict : dict[str, tf.Tensor] The output feed_dict of current descriptor """ - # TODO: currently only SeA has this method, but I think the method can be - # moved here as it doesn't contain anything related to a specific descriptor - raise NotImplementedError + feed_dict = { + 't_coord:0' :coord_, + 't_type:0' :atype_, + 't_natoms:0' :natoms, + 't_box:0' :box, + 't_mesh:0' :mesh + } + return feed_dict def init_variables(self, - embedding_net_variables: dict - ) -> None: + model_file: str, + suffix : str = "", + ) -> None: """ Init the embedding net variables with the given dict Parameters ---------- - embedding_net_variables - The input dict which stores the embedding net variables + model_file : str + The input model file + suffix : str, optional + The suffix of the scope Notes ----- This method is called by others when the descriptor supported initialization from the given variables. """ - # TODO: currently only SeA has this method, but I think the method can be - # moved here as it doesn't contain anything related to a specific descriptor raise NotImplementedError( "Descriptor %s doesn't support initialization from the given variables!" % type(self).__name__) + + def get_tensor_names(self, suffix : str = "") -> Tuple[str]: + """Get names of tensors. + + Parameters + ---------- + suffix : str + The suffix of the scope + + Returns + ------- + Tuple[str] + Names of tensors + """ + raise NotImplementedError("Descriptor %s doesn't support this property!" % type(self).__name__) + + def pass_tensors_from_frz_model(self, + *tensors : tf.Tensor, + ) -> None: + """ + Pass the descrpt_reshape tensor as well as descrpt_deriv tensor from the frz graph_def + + Parameters + ---------- + *tensors : tf.Tensor + passed tensors + + Notes + ----- + The number of parameters in the method must be equal to the numbers of returns in + :meth:`get_tensor_names`. + """ + raise NotImplementedError("Descriptor %s doesn't support this method!" % type(self).__name__) diff --git a/deepmd/descriptor/hybrid.py b/deepmd/descriptor/hybrid.py index bff59518a1..37b9578b4e 100644 --- a/deepmd/descriptor/hybrid.py +++ b/deepmd/descriptor/hybrid.py @@ -253,3 +253,55 @@ def enable_compression(self, """ for idx, ii in enumerate(self.descrpt_list): ii.enable_compression(min_nbor_dist, model_file, table_extrapolate, table_stride_1, table_stride_2, check_frequency, suffix=f"{suffix}_{idx}") + + def init_variables(self, + model_file : str, + suffix : str = "", + ) -> None: + """ + Init the embedding net variables with the given dict + + Parameters + ---------- + model_file : str + The input frozen model file + suffix : str, optional + The suffix of the scope + """ + for idx, ii in enumerate(self.descrpt_list): + ii.init_variables(model_file, suffix=f"{suffix}_{idx}") + + def get_tensor_names(self, suffix : str = "") -> Tuple[str]: + """Get names of tensors. + + Parameters + ---------- + suffix : str + The suffix of the scope + + Returns + ------- + Tuple[str] + Names of tensors + """ + tensor_names = [] + for idx, ii in enumerate(self.descrpt_list): + tensor_names.extend(ii.get_tensor_names(suffix=f"{suffix}_{idx}")) + return tuple(tensor_names) + + def pass_tensors_from_frz_model(self, + *tensors : tf.Tensor, + ) -> None: + """ + Pass the descrpt_reshape tensor as well as descrpt_deriv tensor from the frz graph_def + + Parameters + ---------- + *tensors : tf.Tensor + passed tensors + """ + jj = 0 + for ii in self.descrpt_list: + n_tensors = len(ii.get_tensor_names()) + ii.pass_tensors_from_frz_model(*tensors[jj:jj+n_tensors]) + jj += n_tensors diff --git a/deepmd/descriptor/se_a.py b/deepmd/descriptor/se_a.py index 47e28522a9..39485463a9 100644 --- a/deepmd/descriptor/se_a.py +++ b/deepmd/descriptor/se_a.py @@ -13,7 +13,7 @@ from deepmd.utils.tabulate import DPTabulate from deepmd.utils.type_embed import embed_atom_type from deepmd.utils.sess import run_sess -from deepmd.utils.graph import load_graph_def, get_tensor_by_name_from_graph +from deepmd.utils.graph import load_graph_def, get_tensor_by_name_from_graph, get_embedding_net_variables from .descriptor import Descriptor class DescrptSeA (Descriptor): @@ -433,10 +433,10 @@ def build (self, tf.summary.histogram('nlist', self.nlist) self.descrpt_reshape = tf.reshape(self.descrpt, [-1, self.ndescrpt]) - self.descrpt_reshape = tf.identity(self.descrpt_reshape, name = 'o_rmat') - self.descrpt_deriv = tf.identity(self.descrpt_deriv, name = 'o_rmat_deriv') - self.rij = tf.identity(self.rij, name = 'o_rij') - self.nlist = tf.identity(self.nlist, name = 'o_nlist') + self.descrpt_reshape = tf.identity(self.descrpt_reshape, name = 'o_rmat' + suffix) + self.descrpt_deriv = tf.identity(self.descrpt_deriv, name = 'o_rmat_deriv' + suffix) + self.rij = tf.identity(self.rij, name = 'o_rij' + suffix) + self.nlist = tf.identity(self.nlist, name = 'o_nlist' + suffix) self.dout, self.qmat = self._pass_filter(self.descrpt_reshape, atype, @@ -456,6 +456,21 @@ def get_rot_mat(self) -> tf.Tensor: """ return self.qmat + def get_tensor_names(self, suffix : str = "") -> Tuple[str]: + """Get names of tensors. + + Parameters + ---------- + suffix : str + The suffix of the scope + + Returns + ------- + Tuple[str] + Names of tensors + """ + return (f'o_rmat{suffix}:0', f'o_rmat_deriv{suffix}:0', f'o_rij{suffix}:0', f'o_nlist{suffix}:0') + def pass_tensors_from_frz_model(self, descrpt_reshape : tf.Tensor, descrpt_deriv : tf.Tensor, @@ -481,60 +496,21 @@ def pass_tensors_from_frz_model(self, self.descrpt_deriv = descrpt_deriv self.descrpt_reshape = descrpt_reshape - def get_feed_dict(self, - coord_, - atype_, - natoms, - box, - mesh): - """ - generate the deed_dict for current descriptor - - Parameters - ---------- - coord_ - The coordinate of atoms - atype_ - The type of atoms - natoms - The number of atoms. This tensor has the length of Ntypes + 2 - natoms[0]: number of local atoms - natoms[1]: total number of atoms held by this processor - natoms[i]: 2 <= i < Ntypes+2, number of type i atoms - box - The box. Can be generated by deepmd.model.make_stat_input - mesh - For historical reasons, only the length of the Tensor matters. - if size of mesh == 6, pbc is assumed. - if size of mesh == 0, no-pbc is assumed. - - Returns - ------- - feed_dict - The output feed_dict of current descriptor - """ - feed_dict = { - 't_coord:0' :coord_, - 't_type:0' :atype_, - 't_natoms:0' :natoms, - 't_box:0' :box, - 't_mesh:0' :mesh - } - return feed_dict - - def init_variables(self, - embedding_net_variables: dict + model_file : str, + suffix : str = "", ) -> None: """ Init the embedding net variables with the given dict Parameters ---------- - embedding_net_variables - The input dict which stores the embedding net variables + model_file : str + The input frozen model file + suffix : str, optional + The suffix of the scope """ - self.embedding_net_variables = embedding_net_variables + self.embedding_net_variables = get_embedding_net_variables(model_file, suffix = suffix) def prod_force_virial(self, diff --git a/deepmd/model/ener.py b/deepmd/model/ener.py index dec6ca66f4..441709caff 100644 --- a/deepmd/model/ener.py +++ b/deepmd/model/ener.py @@ -173,10 +173,11 @@ def build (self, name = 'descrpt_attr/ntypes', dtype = tf.int32) feed_dict = self.descrpt.get_feed_dict(coord_, atype_, natoms, box, mesh) - return_elements = ['o_rmat:0', 'o_rmat_deriv:0', 'o_rij:0', 'o_nlist:0', 'o_descriptor:0'] - descrpt_reshape, descrpt_deriv, rij, nlist, dout \ + return_elements = [*self.descrpt.get_tensor_names(), 'o_descriptor:0'] + imported_tensors \ = self._import_graph_def_from_frz_model(frz_model, feed_dict, return_elements) - self.descrpt.pass_tensors_from_frz_model(descrpt_reshape, descrpt_deriv, rij, nlist) + dout = imported_tensors[-1] + self.descrpt.pass_tensors_from_frz_model(*imported_tensors[:-1]) if self.srtab is not None : diff --git a/deepmd/model/tensor.py b/deepmd/model/tensor.py index 5c996ec38d..2a63eda4d6 100644 --- a/deepmd/model/tensor.py +++ b/deepmd/model/tensor.py @@ -3,7 +3,7 @@ from deepmd.env import tf from deepmd.common import ClassArg -from deepmd.env import global_cvt_2_ener_float, MODEL_VERSION +from deepmd.env import global_cvt_2_ener_float, MODEL_VERSION, GLOBAL_TF_FLOAT_PRECISION from deepmd.env import op_module from deepmd.utils.graph import load_graph_def from .model_stat import make_stat_input, merge_sys_stat @@ -138,10 +138,11 @@ def build (self, name = 'descrpt_attr/ntypes', dtype = tf.int32) feed_dict = self.descrpt.get_feed_dict(coord_, atype_, natoms, box, mesh) - return_elements = ['o_rmat:0', 'o_rmat_deriv:0', 'o_rij:0', 'o_nlist:0', 'o_descriptor:0'] - descrpt_reshape, descrpt_deriv, rij, nlist, dout \ + return_elements = [*self.descrpt.get_tensor_names(), 'o_descriptor:0'] + imported_tensors \ = self._import_graph_def_from_frz_model(frz_model, feed_dict, return_elements) - self.descrpt.pass_tensors_from_frz_model(descrpt_reshape, descrpt_deriv, rij, nlist) + dout = imported_tensors[-1] + self.descrpt.pass_tensors_from_frz_model(*imported_tensors[:-1]) rot_mat = self.descrpt.get_rot_mat() rot_mat = tf.identity(rot_mat, name = 'o_rot_mat'+suffix) diff --git a/deepmd/train/trainer.py b/deepmd/train/trainer.py index 4701ed0848..dc888ad3e0 100644 --- a/deepmd/train/trainer.py +++ b/deepmd/train/trainer.py @@ -691,7 +691,7 @@ def _init_from_frz_model(self): # self.frz_model will control the self.model to import the descriptor from the given frozen model instead of building from scratch... # initialize fitting net with the given compressed frozen model if self.model_type == 'original_model': - self.descrpt.init_variables(get_embedding_net_variables(self.run_opt.init_frz_model)) + self.descrpt.init_variables(self.run_opt.init_frz_model) self.fitting.init_variables(get_fitting_net_variables(self.run_opt.init_frz_model)) tf.constant("original_model", name = 'model_type', dtype = tf.string) elif self.model_type == 'compressed_model': diff --git a/deepmd/utils/graph.py b/deepmd/utils/graph.py index ed10108dbb..53fd05cc67 100644 --- a/deepmd/utils/graph.py +++ b/deepmd/utils/graph.py @@ -108,7 +108,7 @@ def get_tensor_by_type(node, elif data_type == np.float32: tensor = np.array(node.float_val) else: - raise RunTimeError('model compression does not support the half precision') + raise RuntimeError('model compression does not support the half precision') return tensor @@ -139,7 +139,7 @@ def get_embedding_net_nodes_from_graph_def(graph_def: tf.GraphDef, suffix: str = return embedding_net_nodes -def get_embedding_net_nodes(model_file: str) -> Dict: +def get_embedding_net_nodes(model_file: str, suffix: str = "") -> Dict: """ Get the embedding net nodes with the given frozen model(model_file) @@ -147,6 +147,8 @@ def get_embedding_net_nodes(model_file: str) -> Dict: ---------- model_file The input frozen model path + suffix : str, optional + The suffix of the scope Returns ---------- @@ -154,10 +156,10 @@ def get_embedding_net_nodes(model_file: str) -> Dict: The embedding net nodes with the given frozen model """ _, graph_def = load_graph_def(model_file) - return get_embedding_net_nodes_from_graph_def(graph_def) + return get_embedding_net_nodes_from_graph_def(graph_def, suffix=suffix) -def get_embedding_net_variables_from_graph_def(graph_def : tf.GraphDef) -> Dict: +def get_embedding_net_variables_from_graph_def(graph_def : tf.GraphDef, suffix: str = "") -> Dict: """ Get the embedding net variables with the given tf.GraphDef object @@ -165,6 +167,8 @@ def get_embedding_net_variables_from_graph_def(graph_def : tf.GraphDef) -> Dict: ---------- graph_def The input tf.GraphDef object + suffix : str, optional + The suffix of the scope Returns ---------- @@ -172,7 +176,7 @@ def get_embedding_net_variables_from_graph_def(graph_def : tf.GraphDef) -> Dict: The embedding net variables within the given tf.GraphDef object """ embedding_net_variables = {} - embedding_net_nodes = get_embedding_net_nodes_from_graph_def(graph_def) + embedding_net_nodes = get_embedding_net_nodes_from_graph_def(graph_def, suffix=suffix) for item in embedding_net_nodes: node = embedding_net_nodes[item] dtype = tf.as_dtype(node.dtype).as_numpy_dtype @@ -184,7 +188,7 @@ def get_embedding_net_variables_from_graph_def(graph_def : tf.GraphDef) -> Dict: embedding_net_variables[item] = np.reshape(tensor_value, tensor_shape) return embedding_net_variables -def get_embedding_net_variables(model_file : str) -> Dict: +def get_embedding_net_variables(model_file : str, suffix: str = "") -> Dict: """ Get the embedding net variables with the given frozen model(model_file) @@ -192,6 +196,8 @@ def get_embedding_net_variables(model_file : str) -> Dict: ---------- model_file The input frozen model path + suffix : str, optional + The suffix of the scope Returns ---------- @@ -199,7 +205,7 @@ def get_embedding_net_variables(model_file : str) -> Dict: The embedding net variables within the given frozen model """ _, graph_def = load_graph_def(model_file) - return get_embedding_net_variables_from_graph_def(graph_def) + return get_embedding_net_variables_from_graph_def(graph_def, suffix=suffix) def get_fitting_net_nodes_from_graph_def(graph_def: tf.GraphDef) -> Dict: From ed36276d0d5f26695e3c713ae534febca0c7ec7e Mon Sep 17 00:00:00 2001 From: Han Wang Date: Thu, 9 Sep 2021 07:42:43 +0800 Subject: [PATCH 32/34] fix data_modifier OOM problem when set size is too large (#1117) Co-authored-by: Han Wang --- deepmd/infer/data_modifier.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/deepmd/infer/data_modifier.py b/deepmd/infer/data_modifier.py index 6b473e93e6..224b8fbd06 100644 --- a/deepmd/infer/data_modifier.py +++ b/deepmd/infer/data_modifier.py @@ -358,7 +358,16 @@ def _extend_system(self, coord, box, atype, charge): ref_coord = coord3[:,sel_idx_map,:] ref_coord = np.reshape(ref_coord, [nframes, nsel * 3]) - dipole = DeepDipole.eval(self, coord, box, atype) + batch_size = 8 + all_dipole = [] + for ii in range(0,nframes,batch_size): + dipole = DeepDipole.eval(self, + coord[ii:ii+batch_size], + box[ii:ii+batch_size], + atype) + all_dipole.append(dipole) + dipole = np.concatenate(all_dipole, axis = 0) + assert(dipole.shape[0] == nframes) dipole = np.reshape(dipole, [nframes, nsel * 3]) wfcc_coord = ref_coord + dipole From 1526587c24fded4b2f870f22f482ad47707f5337 Mon Sep 17 00:00:00 2001 From: Han Wang Date: Fri, 10 Sep 2021 19:42:29 +0800 Subject: [PATCH 33/34] fix bugs of dipole charge modifier: binary str and missing frozen nodes (#1124) Co-authored-by: Han Wang --- deepmd/entrypoints/freeze.py | 2 ++ deepmd/infer/deep_pot.py | 1 + 2 files changed, 3 insertions(+) diff --git a/deepmd/entrypoints/freeze.py b/deepmd/entrypoints/freeze.py index a6d8926109..511f58598d 100755 --- a/deepmd/entrypoints/freeze.py +++ b/deepmd/entrypoints/freeze.py @@ -111,10 +111,12 @@ def _make_node_names(model_type: str, modifier_type: Optional[str] = None) -> Li "modifier_attr/sys_charge_map", "modifier_attr/ewald_h", "modifier_attr/ewald_beta", + "dipole_charge/model_type", "dipole_charge/descrpt_attr/rcut", "dipole_charge/descrpt_attr/ntypes", "dipole_charge/model_attr/tmap", "dipole_charge/model_attr/model_type", + "dipole_charge/model_attr/model_version", "o_dm_force", "dipole_charge/model_attr/sel_type", "dipole_charge/o_dipole", diff --git a/deepmd/infer/deep_pot.py b/deepmd/infer/deep_pot.py index 3c5fb28f6e..63625905e8 100644 --- a/deepmd/infer/deep_pot.py +++ b/deepmd/infer/deep_pot.py @@ -137,6 +137,7 @@ def __init__( t_ewald_h = self._get_tensor("modifier_attr/ewald_h:0") t_ewald_beta = self._get_tensor("modifier_attr/ewald_beta:0") [mdl_name, mdl_charge_map, sys_charge_map, ewald_h, ewald_beta] = run_sess(self.sess, [t_mdl_name, t_mdl_charge_map, t_sys_charge_map, t_ewald_h, t_ewald_beta]) + mdl_name = mdl_name.decode("UTF-8") mdl_charge_map = [int(ii) for ii in mdl_charge_map.decode("UTF-8").split()] sys_charge_map = [int(ii) for ii in sys_charge_map.decode("UTF-8").split()] self.dm = DipoleChargeModifier(mdl_name, mdl_charge_map, sys_charge_map, ewald_h = ewald_h, ewald_beta = ewald_beta) From e263aa3ec820621e89529995f73fa7197a0f5b78 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Fri, 10 Sep 2021 07:44:21 -0400 Subject: [PATCH 34/34] fix "Call to method DeepTensor.__init__ with too many arguments" (#1125) As detected by LGTM, here is an error: Call to method DeepTensor.__init__ with too many arguments; should be no more than 4. I agree with the automatic code analysis tool. --- deepmd/infer/deep_polar.py | 1 - 1 file changed, 1 deletion(-) diff --git a/deepmd/infer/deep_polar.py b/deepmd/infer/deep_polar.py index 846efc9bde..d594be32f8 100644 --- a/deepmd/infer/deep_polar.py +++ b/deepmd/infer/deep_polar.py @@ -84,7 +84,6 @@ def __init__( DeepTensor.__init__( self, model_file, - 9, load_prefix=load_prefix, default_tf_graph=default_tf_graph, )