@@ -176,9 +176,23 @@ static void run_model(
176176 for (size_t ii = 0 ; ii < static_cast <size_t >(nframes) * nall * 3 ; ++ii) {
177177 dforce[ii] = of (ii);
178178 }
179+ if (output_ae.NumElements () % nframes != 0 ) {
180+ throw deepmd::deepmd_exception (
181+ " TensorFlow atomic-energy output is not divisible by nframes." );
182+ }
183+ const size_t nloc_energy = output_ae.NumElements () / nframes;
184+ if (nloc_energy > nall) {
185+ throw deepmd::deepmd_exception (
186+ " TensorFlow atomic-energy output has more atoms than the extended "
187+ " DeepSpin system." );
188+ }
189+ // Spin models emit atomic energies for physical atoms only. The extended
190+ // virtual atoms sort after all physical types, so keep their slots zero and
191+ // use the actual output width as the per-frame source stride.
179192 for (int ii = 0 ; ii < nframes; ++ii) {
180- for (int jj = 0 ; jj < nloc; ++jj) {
181- datom_energy[ii * nall + jj] = oae (ii * nloc + jj);
193+ for (size_t jj = 0 ; jj < nloc_energy; ++jj) {
194+ datom_energy[static_cast <size_t >(ii) * nall + jj] =
195+ oae (static_cast <size_t >(ii) * nloc_energy + jj);
182196 }
183197 }
184198 for (size_t ii = 0 ; ii < static_cast <size_t >(nframes) * nall * 9 ; ++ii) {
@@ -614,7 +628,7 @@ void DeepSpinTF::compute(ENERGYVTYPE& dener,
614628
615629 std::vector<VALUETYPE > extend_dcoord;
616630 std::vector<int > extend_atype;
617- extend_nlist (extend_dcoord, extend_atype, dcoord_, dspin_, datype_);
631+ extend_nlist (extend_dcoord, extend_atype, dcoord_, dspin_, datype_, nframes );
618632
619633 atommap = deepmd::AtomMap (extend_atype.begin (), extend_atype.end ());
620634
@@ -645,16 +659,43 @@ void DeepSpinTF::compute(ENERGYVTYPE& dener,
645659 atommap, nframes);
646660 }
647661 }
648- // backward force and mag.
662+ // Atomic outputs from the TensorFlow graph include the appended virtual spin
663+ // atoms. Keep a temporary copy so the public API can return the documented
664+ // real-atom layout, matching the neighbor-list overload below.
665+ std::vector<VALUETYPE > datom_energy_tmp, datom_virial_tmp;
666+ if (atomic) {
667+ datom_energy_tmp.swap (datom_energy_);
668+ datom_virial_tmp.swap (datom_virial_);
669+ datom_energy_.resize (static_cast <size_t >(nframes) * nloc);
670+ datom_virial_.resize (static_cast <size_t >(nframes) * nloc * 9 );
671+ }
672+
673+ // Backward force, magnetic force, and optional atomic outputs.
649674 dforce_.resize (static_cast <size_t >(nframes) * nloc * 3 );
650675 dforce_mag_.resize (static_cast <size_t >(nframes) * nloc * 3 );
651- for (int ii = 0 ; ii < nloc; ++ii) {
652- for (int dd = 0 ; dd < 3 ; ++dd) {
653- dforce_[3 * ii + dd] = dforce_tmp[3 * ii + dd];
654- if (datype_[ii] < ntypes_spin) {
655- dforce_mag_[3 * ii + dd] = dforce_tmp[3 * (ii + nloc) + dd];
656- } else {
657- dforce_mag_[3 * ii + dd] = 0.0 ;
676+ const size_t extend_nall = extend_atype.size ();
677+ for (int ff = 0 ; ff < nframes; ++ff) {
678+ for (int ii = 0 ; ii < nloc; ++ii) {
679+ const size_t output_atom = static_cast <size_t >(ff) * nloc + ii;
680+ const size_t extended_atom = static_cast <size_t >(ff) * extend_nall + ii;
681+ if (atomic) {
682+ datom_energy_[output_atom] = datom_energy_tmp[extended_atom];
683+ }
684+ for (int dd = 0 ; dd < 3 ; ++dd) {
685+ dforce_[output_atom * 3 + dd] = dforce_tmp[extended_atom * 3 + dd];
686+ if (datype_[ii] < ntypes_spin) {
687+ const size_t virtual_atom =
688+ static_cast <size_t >(ff) * extend_nall + ii + nloc;
689+ dforce_mag_[output_atom * 3 + dd] = dforce_tmp[virtual_atom * 3 + dd];
690+ } else {
691+ dforce_mag_[output_atom * 3 + dd] = 0.0 ;
692+ }
693+ }
694+ if (atomic) {
695+ for (int dd = 0 ; dd < 9 ; ++dd) {
696+ datom_virial_[output_atom * 9 + dd] =
697+ datom_virial_tmp[extended_atom * 9 + dd];
698+ }
658699 }
659700 }
660701 }
@@ -747,7 +788,7 @@ void DeepSpinTF::compute(ENERGYVTYPE& dener,
747788 extend (extend_inum, extend_ilist, extend_numneigh, extend_neigh,
748789 extend_firstneigh, extend_dcoord, extend_dtype, extend_nghost,
749790 new_idx_map, old_idx_map, lmp_list, dcoord_, datype_, nghost, dspin_,
750- ntypes, ntypes_spin);
791+ ntypes, ntypes_spin, nframes );
751792 InputNlist extend_lmp_list (extend_inum, &extend_ilist[0 ], &extend_numneigh[0 ],
752793 &extend_firstneigh[0 ]);
753794 extend_lmp_list.set_mask (lmp_list.mask );
@@ -820,22 +861,30 @@ void DeepSpinTF::compute(ENERGYVTYPE& dener,
820861 dforce_mag_.resize (static_cast <size_t >(nframes) * nall * 3 );
821862 datom_energy_.resize (static_cast <size_t >(nframes) * nall);
822863 datom_virial_.resize (static_cast <size_t >(nframes) * nall * 9 );
823- for (int ii = 0 ; ii < nall; ++ii) {
824- int new_idx = new_idx_map[ii];
825- for (int dd = 0 ; dd < 3 ; ++dd) {
826- dforce_[3 * ii + dd] = dforce_tmp[3 * new_idx + dd];
827- datom_energy_[ii] = datom_energy_tmp[new_idx];
828-
829- if (datype_[ii] < ntypes_spin && ii < nloc) {
830- dforce_mag_[3 * ii + dd] = dforce_tmp[3 * (new_idx + nloc) + dd];
831- } else if (datype_[ii] < ntypes_spin) {
832- dforce_mag_[3 * ii + dd] = dforce_tmp[3 * (new_idx + nghost) + dd];
833- } else {
834- dforce_mag_[3 * ii + dd] = 0.0 ;
864+ const size_t extended_nall = fwd_map.size ();
865+ for (int ff = 0 ; ff < nframes; ++ff) {
866+ for (int ii = 0 ; ii < nall; ++ii) {
867+ const int new_idx = new_idx_map[ii];
868+ const size_t output_atom = static_cast <size_t >(ff) * nall + ii;
869+ const size_t extended_atom =
870+ static_cast <size_t >(ff) * extended_nall + new_idx;
871+ datom_energy_[output_atom] = datom_energy_tmp[extended_atom];
872+ for (int dd = 0 ; dd < 3 ; ++dd) {
873+ dforce_[output_atom * 3 + dd] = dforce_tmp[extended_atom * 3 + dd];
874+
875+ if (datype_[ii] < ntypes_spin) {
876+ const int virtual_idx = new_idx + (ii < nloc ? nloc : nghost);
877+ const size_t virtual_atom =
878+ static_cast <size_t >(ff) * extended_nall + virtual_idx;
879+ dforce_mag_[output_atom * 3 + dd] = dforce_tmp[virtual_atom * 3 + dd];
880+ } else {
881+ dforce_mag_[output_atom * 3 + dd] = 0.0 ;
882+ }
883+ }
884+ for (int dd = 0 ; dd < 9 ; ++dd) {
885+ datom_virial_[output_atom * 9 + dd] =
886+ datom_virial_tmp[extended_atom * 9 + dd];
835887 }
836- }
837- for (int dd = 0 ; dd < 9 ; ++dd) {
838- datom_virial_[ii * 9 + dd] = datom_virial_tmp[new_idx * 9 + dd];
839888 }
840889 }
841890}
@@ -1016,7 +1065,8 @@ void DeepSpinTF::extend(int& extend_inum,
10161065 const int nghost,
10171066 const std::vector<VALUETYPE >& spin,
10181067 const int numb_types,
1019- const int numb_types_spin) {
1068+ const int numb_types_spin,
1069+ const int nframes) {
10201070 extend_ilist.clear ();
10211071 extend_numneigh.clear ();
10221072 extend_neigh.clear ();
@@ -1033,8 +1083,10 @@ void DeepSpinTF::extend(int& extend_inum,
10331083 get_vector<float >(spin_norm, " spin_attr/spin_norm" );
10341084 }
10351085
1036- int nall = dcoord .size () / 3 ;
1086+ int nall = atype .size ();
10371087 int nloc = nall - nghost;
1088+ assert (static_cast <size_t >(nframes) * nall * 3 == dcoord.size ());
1089+ assert (dcoord.size () == spin.size ());
10381090 assert (nloc == lmp_list.inum );
10391091
10401092 // record numb_types_real and nloc_virt
@@ -1140,26 +1192,36 @@ void DeepSpinTF::extend(int& extend_inum,
11401192 }
11411193
11421194 // extend coord
1143- extend_dcoord.resize (static_cast <size_t >(extend_nall) * 3 );
1144- for (int ii = 0 ; ii < nloc; ii++) {
1145- for (int jj = 0 ; jj < 3 ; jj++) {
1146- extend_dcoord[new_idx_map[ii] * 3 + jj] = dcoord[ii * 3 + jj];
1147- if (atype[ii] < numb_types_spin) {
1148- double temp_dcoord = dcoord[ii * 3 + jj] + spin[ii * 3 + jj] /
1149- spin_norm[atype[ii]] *
1150- virtual_len[atype[ii]];
1151- extend_dcoord[(new_idx_map[ii] + nloc) * 3 + jj] = temp_dcoord;
1195+ extend_dcoord.resize (static_cast <size_t >(nframes) * extend_nall * 3 );
1196+ for (int ff = 0 ; ff < nframes; ++ff) {
1197+ const size_t input_offset = static_cast <size_t >(ff) * nall * 3 ;
1198+ const size_t output_offset = static_cast <size_t >(ff) * extend_nall * 3 ;
1199+ for (int ii = 0 ; ii < nloc; ii++) {
1200+ for (int jj = 0 ; jj < 3 ; jj++) {
1201+ extend_dcoord[output_offset + new_idx_map[ii] * 3 + jj] =
1202+ dcoord[input_offset + ii * 3 + jj];
1203+ if (atype[ii] < numb_types_spin) {
1204+ const VALUETYPE temp_dcoord = dcoord[input_offset + ii * 3 + jj] +
1205+ spin[input_offset + ii * 3 + jj] /
1206+ spin_norm[atype[ii]] *
1207+ virtual_len[atype[ii]];
1208+ extend_dcoord[output_offset + (new_idx_map[ii] + nloc) * 3 + jj] =
1209+ temp_dcoord;
1210+ }
11521211 }
11531212 }
1154- }
1155- for (int ii = nloc; ii < nall; ii++) {
1156- for (int jj = 0 ; jj < 3 ; jj++) {
1157- extend_dcoord[new_idx_map[ii] * 3 + jj] = dcoord[ii * 3 + jj];
1158- if (atype[ii] < numb_types_spin) {
1159- double temp_dcoord = dcoord[ii * 3 + jj] + spin[ii * 3 + jj] /
1160- spin_norm[atype[ii]] *
1161- virtual_len[atype[ii]];
1162- extend_dcoord[(new_idx_map[ii] + nghost) * 3 + jj] = temp_dcoord;
1213+ for (int ii = nloc; ii < nall; ii++) {
1214+ for (int jj = 0 ; jj < 3 ; jj++) {
1215+ extend_dcoord[output_offset + new_idx_map[ii] * 3 + jj] =
1216+ dcoord[input_offset + ii * 3 + jj];
1217+ if (atype[ii] < numb_types_spin) {
1218+ const VALUETYPE temp_dcoord = dcoord[input_offset + ii * 3 + jj] +
1219+ spin[input_offset + ii * 3 + jj] /
1220+ spin_norm[atype[ii]] *
1221+ virtual_len[atype[ii]];
1222+ extend_dcoord[output_offset + (new_idx_map[ii] + nghost) * 3 + jj] =
1223+ temp_dcoord;
1224+ }
11631225 }
11641226 }
11651227 }
@@ -1195,7 +1257,8 @@ template void DeepSpinTF::extend<double>(
11951257 const int nghost,
11961258 const std::vector<double >& spin,
11971259 const int numb_types,
1198- const int numb_types_spin);
1260+ const int numb_types_spin,
1261+ const int nframes);
11991262
12001263template void DeepSpinTF::extend<float >(
12011264 int & extend_inum,
@@ -1214,14 +1277,16 @@ template void DeepSpinTF::extend<float>(
12141277 const int nghost,
12151278 const std::vector<float >& spin,
12161279 const int numb_types,
1217- const int numb_types_spin);
1280+ const int numb_types_spin,
1281+ const int nframes);
12181282
12191283template <typename VALUETYPE >
12201284void DeepSpinTF::extend_nlist (std::vector<VALUETYPE >& extend_dcoord,
12211285 std::vector<int >& extend_atype,
12221286 const std::vector<VALUETYPE >& dcoord_,
12231287 const std::vector<VALUETYPE >& dspin_,
1224- const std::vector<int >& datype_) {
1288+ const std::vector<int >& datype_,
1289+ const int nframes) {
12251290 if (dtype == tensorflow::DT_DOUBLE ) {
12261291 get_vector<double >(virtual_len, " spin_attr/virtual_len" );
12271292 get_vector<double >(spin_norm, " spin_attr/spin_norm" );
@@ -1240,20 +1305,27 @@ void DeepSpinTF::extend_nlist(std::vector<VALUETYPE>& extend_dcoord,
12401305 }
12411306 }
12421307 int extend_nall = nloc + nloc_spin;
1243- extend_dcoord.resize (static_cast <size_t >(extend_nall) * 3 );
1308+ assert (static_cast <size_t >(nframes) * nloc * 3 == dcoord_.size ());
1309+ assert (dcoord_.size () == dspin_.size ());
1310+ extend_dcoord.resize (static_cast <size_t >(nframes) * extend_nall * 3 );
12441311 extend_atype.resize (extend_nall);
12451312 for (int ii = 0 ; ii < nloc; ii++) {
12461313 extend_atype[ii] = datype_[ii];
12471314 if (datype_[ii] < ntypes_spin) {
12481315 extend_atype[ii + nloc] = datype_[ii] + ntypes - ntypes_spin;
12491316 }
1250- for (int jj = 0 ; jj < 3 ; jj++) {
1251- extend_dcoord[ii * 3 + jj] = dcoord_[ii * 3 + jj];
1252- if (datype_[ii] < ntypes_spin) {
1253- extend_dcoord[(ii + nloc) * 3 + jj] =
1254- dcoord_[ii * 3 + jj] + dspin_[ii * 3 + jj] /
1255- spin_norm[datype_[ii]] *
1256- virtual_len[datype_[ii]];
1317+ for (int ff = 0 ; ff < nframes; ++ff) {
1318+ const size_t input_offset = static_cast <size_t >(ff) * nloc * 3 ;
1319+ const size_t output_offset = static_cast <size_t >(ff) * extend_nall * 3 ;
1320+ for (int jj = 0 ; jj < 3 ; jj++) {
1321+ extend_dcoord[output_offset + ii * 3 + jj] =
1322+ dcoord_[input_offset + ii * 3 + jj];
1323+ if (datype_[ii] < ntypes_spin) {
1324+ extend_dcoord[output_offset + (ii + nloc) * 3 + jj] =
1325+ dcoord_[input_offset + ii * 3 + jj] +
1326+ dspin_[input_offset + ii * 3 + jj] / spin_norm[datype_[ii]] *
1327+ virtual_len[datype_[ii]];
1328+ }
12571329 }
12581330 }
12591331 }
@@ -1264,11 +1336,13 @@ template void DeepSpinTF::extend_nlist<double>(
12641336 std::vector<int >& extend_atype,
12651337 const std::vector<double >& dcoord_,
12661338 const std::vector<double >& dspin_,
1267- const std::vector<int >& datype_);
1339+ const std::vector<int >& datype_,
1340+ const int nframes);
12681341
12691342template void DeepSpinTF::extend_nlist<float >(std::vector<float >& extend_dcoord,
12701343 std::vector<int >& extend_atype,
12711344 const std::vector<float >& dcoord_,
12721345 const std::vector<float >& dspin_,
1273- const std::vector<int >& datype_);
1346+ const std::vector<int >& datype_,
1347+ const int nframes);
12741348#endif
0 commit comments