@@ -274,43 +274,95 @@ void DeltaSpin<OperatorLCAO<TK, TR>>::cal_force_IJR(const int& iat1,
274274 }
275275 double tmp[3 ] = {0.0 };
276276 // calculate the local matrix
277- for (int is = 1 ; is < nspin; is++)
277+ // For nspin=4, the constraint force is F = lambda · dM/dR where:
278+ // Mx = DM_ud + DM_du, My = -i*(DM_ud - DM_du), Mz = DM_uu - DM_dd
279+ // For real DM (dDM_ud = dDM_du), My contribution vanishes, so:
280+ // F = lambda_x * (dDM_ud + dDM_du) + lambda_z * (dDM_uu - dDM_dd)
281+ // We convert lambda from Pauli basis to spinor basis:
282+ // lambda_uu = lambda_z, lambda_dd = -lambda_z
283+ // lambda_ud = lambda_x, lambda_du = lambda_x
284+ if (nspin == 4 )
278285 {
279- const double lambda_tmp = nspin== 2 ?lambda[ 2 ]:lambda[is- 1 ];
280- const double * dm_pointer = dmR_pointer-> get_pointer () ;
281- for (int iw1l = 0 ; iw1l < row_indexes. size (); iw1l += npol )
286+ // lambda in spinor basis: (lambda_uu, lambda_ud, lambda_du, lambda_dd)
287+ const double lambda_spinor[ 4 ] = {lambda[ 2 ], lambda[ 0 ], lambda[ 0 ], -lambda[ 2 ]} ;
288+ for (int is = 0 ; is < 4 ; is++ )
282289 {
283- const std::vector<double >& nlm1 = nlm1_all.find (row_indexes[iw1l])->second ;
284- for (int iw2l = 0 ; iw2l < col_indexes.size (); iw2l += npol)
290+ const double lambda_tmp = lambda_spinor[is];
291+ if (std::abs (lambda_tmp) < 1e-15 ) continue ;
292+ const double * dm_pointer = dmR_pointer->get_pointer ();
293+ for (int iw1l = 0 ; iw1l < row_indexes.size (); iw1l += npol)
285294 {
286- const std::vector<double >& nlm2 = nlm2_all.find (col_indexes[iw2l])->second ;
295+ const std::vector<double >& nlm1 = nlm1_all.find (row_indexes[iw1l])->second ;
296+ for (int iw2l = 0 ; iw2l < col_indexes.size (); iw2l += npol)
297+ {
298+ const std::vector<double >& nlm2 = nlm2_all.find (col_indexes[iw2l])->second ;
287299#ifdef __DEBUG
288- assert (nlm1.size () == nlm2.size ());
300+ assert (nlm1.size () == nlm2.size ());
289301#endif
290- const int length = nlm1.size () / 4 ;
291- const int lmax = sqrt (length);
292- int index = 0 ;
293- for (int l = 0 ; l<lmax; l++)
302+ const int length = nlm1.size () / 4 ;
303+ const int lmax = sqrt (length);
304+ int index = 0 ;
305+ for (int l = 0 ; l<lmax; l++)
306+ {
307+ for (int m = 0 ; m < 2 *l+1 ; m++)
308+ {
309+ index = l*l + m;
310+ tmp[0 ] = lambda_tmp * nlm1[index + length] * nlm2[index] * dm_pointer[step_trace[is]];
311+ tmp[1 ] = lambda_tmp * nlm1[index + length * 2 ] * nlm2[index] * dm_pointer[step_trace[is]];
312+ tmp[2 ] = lambda_tmp * nlm1[index + length * 3 ] * nlm2[index] * dm_pointer[step_trace[is]];
313+ force1[0 ] += tmp[0 ];
314+ force1[1 ] += tmp[1 ];
315+ force1[2 ] += tmp[2 ];
316+ force2[0 ] -= tmp[0 ];
317+ force2[1 ] -= tmp[1 ];
318+ force2[2 ] -= tmp[2 ];
319+ }
320+ }
321+ dm_pointer += npol;
322+ }
323+ dm_pointer += (npol - 1 ) * col_indexes.size ();
324+ }
325+ }
326+ }
327+ else
328+ {
329+ // nspin=1 or nspin=2: original logic
330+ for (int is = 1 ; is < nspin; is++)
331+ {
332+ const double lambda_tmp = nspin==2 ?lambda[2 ]:lambda[is-1 ];
333+ const double * dm_pointer = dmR_pointer->get_pointer ();
334+ for (int iw1l = 0 ; iw1l < row_indexes.size (); iw1l += npol)
335+ {
336+ const std::vector<double >& nlm1 = nlm1_all.find (row_indexes[iw1l])->second ;
337+ for (int iw2l = 0 ; iw2l < col_indexes.size (); iw2l += npol)
294338 {
295- for (int m = 0 ; m < 2 *l+1 ; m++)
339+ const std::vector<double >& nlm2 = nlm2_all.find (col_indexes[iw2l])->second ;
340+ #ifdef __DEBUG
341+ assert (nlm1.size () == nlm2.size ());
342+ #endif
343+ const int length = nlm1.size () / 4 ;
344+ const int lmax = sqrt (length);
345+ int index = 0 ;
346+ for (int l = 0 ; l<lmax; l++)
296347 {
297- index = l*l + m;
298- tmp[0 ] = lambda_tmp * nlm1[index + length] * nlm2[index] * dm_pointer[step_trace[is]];
299- tmp[1 ] = lambda_tmp * nlm1[index + length * 2 ] * nlm2[index] * dm_pointer[step_trace[is]];
300- tmp[2 ] = lambda_tmp * nlm1[index + length * 3 ] * nlm2[index] * dm_pointer[step_trace[is]];
301- // force1 = - VU * <d phi_{I,R1}/d R1|chi_m> * <chi_m'|phi_{J,R2}>
302- // force2 = - VU * <phi_{I,R1}|d chi_m/d R0> * <chi_m'|phi_{J,R2>}
303- force1[0 ] += tmp[0 ];
304- force1[1 ] += tmp[1 ];
305- force1[2 ] += tmp[2 ];
306- force2[0 ] -= tmp[0 ];
307- force2[1 ] -= tmp[1 ];
308- force2[2 ] -= tmp[2 ];
348+ for (int m = 0 ; m < 2 *l+1 ; m++)
349+ {
350+ index = l*l + m;
351+ tmp[0 ] = lambda_tmp * nlm1[index + length] * nlm2[index] * dm_pointer[step_trace[is]];
352+ tmp[1 ] = lambda_tmp * nlm1[index + length * 2 ] * nlm2[index] * dm_pointer[step_trace[is]];
353+ tmp[2 ] = lambda_tmp * nlm1[index + length * 3 ] * nlm2[index] * dm_pointer[step_trace[is]];
354+ force1[0 ] += tmp[0 ];
355+ force1[1 ] += tmp[1 ];
356+ force1[2 ] += tmp[2 ];
357+ force2[0 ] -= tmp[0 ];
358+ force2[1 ] -= tmp[1 ];
359+ force2[2 ] -= tmp[2 ];
360+ }
309361 }
362+ dm_pointer += npol;
310363 }
311- dm_pointer += npol;
364+ dm_pointer += ( npol - 1 ) * col_indexes. size () ;
312365 }
313- dm_pointer += (npol - 1 ) * col_indexes.size ();
314366 }
315367 }
316368}
@@ -345,48 +397,102 @@ void DeltaSpin<OperatorLCAO<TK, TR>>::cal_stress_IJR(const int& iat1,
345397 step_trace[3 ] = col_indexes.size () + 1 ;
346398 }
347399 // calculate the local matrix
348- for (int is = 1 ; is < nspin; is++)
400+ // For nspin=4, convert lambda from Pauli basis to spinor basis
401+ if (nspin == 4 )
349402 {
350- const double lambda_tmp = nspin==2 ?lambda[2 ]:lambda[is-1 ];
351- const double * dm_pointer = dmR_pointer->get_pointer ();
352- for (int iw1l = 0 ; iw1l < row_indexes.size (); iw1l += npol)
403+ const double lambda_spinor[4 ] = {lambda[2 ], lambda[0 ], lambda[0 ], -lambda[2 ]};
404+ for (int is = 0 ; is < 4 ; is++)
353405 {
354- const std::vector<double >& nlm1 = nlm1_all.find (row_indexes[iw1l])->second ;
355- for (int iw2l = 0 ; iw2l < col_indexes.size (); iw2l += npol)
406+ const double lambda_tmp = lambda_spinor[is];
407+ if (std::abs (lambda_tmp) < 1e-15 ) continue ;
408+ const double * dm_pointer = dmR_pointer->get_pointer ();
409+ for (int iw1l = 0 ; iw1l < row_indexes.size (); iw1l += npol)
356410 {
357- const std::vector<double >& nlm2 = nlm2_all.find (col_indexes[iw2l])->second ;
411+ const std::vector<double >& nlm1 = nlm1_all.find (row_indexes[iw1l])->second ;
412+ for (int iw2l = 0 ; iw2l < col_indexes.size (); iw2l += npol)
413+ {
414+ const std::vector<double >& nlm2 = nlm2_all.find (col_indexes[iw2l])->second ;
358415#ifdef __DEBUG
359- assert (nlm1.size () == nlm2.size ());
416+ assert (nlm1.size () == nlm2.size ());
360417#endif
361- const int length = nlm1.size () / 4 ;
362- const int lmax = sqrt (length);
363- double tmp = lambda_tmp * dm_pointer[step_trace[is]];
364- int index = 0 ;
365- for (int l = 0 ; l<lmax; l++)
418+ const int length = nlm1.size () / 4 ;
419+ const int lmax = sqrt (length);
420+ double tmp = lambda_tmp * dm_pointer[step_trace[is]];
421+ int index = 0 ;
422+ for (int l = 0 ; l<lmax; l++)
423+ {
424+ for (int m = 0 ; m < 2 *l+1 ; m++)
425+ {
426+ index = l*l + m;
427+ stress[0 ]
428+ += tmp * (nlm1[index + length] * dis1.x * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.x );
429+ stress[1 ]
430+ += tmp * (nlm1[index + length] * dis1.y * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.y );
431+ stress[2 ]
432+ += tmp * (nlm1[index + length] * dis1.z * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.z );
433+ stress[3 ] += tmp
434+ * (nlm1[index + length * 2 ] * dis1.y * nlm2[index]
435+ + nlm1[index] * nlm2[index + length * 2 ] * dis2.y );
436+ stress[4 ] += tmp
437+ * (nlm1[index + length * 2 ] * dis1.z * nlm2[index]
438+ + nlm1[index] * nlm2[index + length * 2 ] * dis2.z );
439+ stress[5 ] += tmp
440+ * (nlm1[index + length * 3 ] * dis1.z * nlm2[index]
441+ + nlm1[index] * nlm2[index + length * 3 ] * dis2.z );
442+ }
443+ }
444+ dm_pointer += npol;
445+ }
446+ dm_pointer += (npol - 1 ) * col_indexes.size ();
447+ }
448+ }
449+ }
450+ else
451+ {
452+ // nspin=1 or nspin=2: original logic
453+ for (int is = 1 ; is < nspin; is++)
454+ {
455+ const double lambda_tmp = nspin==2 ?lambda[2 ]:lambda[is-1 ];
456+ const double * dm_pointer = dmR_pointer->get_pointer ();
457+ for (int iw1l = 0 ; iw1l < row_indexes.size (); iw1l += npol)
458+ {
459+ const std::vector<double >& nlm1 = nlm1_all.find (row_indexes[iw1l])->second ;
460+ for (int iw2l = 0 ; iw2l < col_indexes.size (); iw2l += npol)
366461 {
367- for (int m = 0 ; m < 2 *l+1 ; m++)
462+ const std::vector<double >& nlm2 = nlm2_all.find (col_indexes[iw2l])->second ;
463+ #ifdef __DEBUG
464+ assert (nlm1.size () == nlm2.size ());
465+ #endif
466+ const int length = nlm1.size () / 4 ;
467+ const int lmax = sqrt (length);
468+ double tmp = lambda_tmp * dm_pointer[step_trace[is]];
469+ int index = 0 ;
470+ for (int l = 0 ; l<lmax; l++)
368471 {
369- index = l*l + m;
370- stress[0 ]
371- += tmp * (nlm1[index + length] * dis1.x * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.x );
372- stress[1 ]
373- += tmp * (nlm1[index + length] * dis1.y * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.y );
374- stress[2 ]
375- += tmp * (nlm1[index + length] * dis1.z * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.z );
376- stress[3 ] += tmp
377- * (nlm1[index + length * 2 ] * dis1.y * nlm2[index]
378- + nlm1[index] * nlm2[index + length * 2 ] * dis2.y );
379- stress[4 ] += tmp
380- * (nlm1[index + length * 2 ] * dis1.z * nlm2[index]
381- + nlm1[index] * nlm2[index + length * 2 ] * dis2.z );
382- stress[5 ] += tmp
383- * (nlm1[index + length * 3 ] * dis1.z * nlm2[index]
384- + nlm1[index] * nlm2[index + length * 3 ] * dis2.z );
472+ for (int m = 0 ; m < 2 *l+1 ; m++)
473+ {
474+ index = l*l + m;
475+ stress[0 ]
476+ += tmp * (nlm1[index + length] * dis1.x * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.x );
477+ stress[1 ]
478+ += tmp * (nlm1[index + length] * dis1.y * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.y );
479+ stress[2 ]
480+ += tmp * (nlm1[index + length] * dis1.z * nlm2[index] + nlm1[index] * nlm2[index + length] * dis2.z );
481+ stress[3 ] += tmp
482+ * (nlm1[index + length * 2 ] * dis1.y * nlm2[index]
483+ + nlm1[index] * nlm2[index + length * 2 ] * dis2.y );
484+ stress[4 ] += tmp
485+ * (nlm1[index + length * 2 ] * dis1.z * nlm2[index]
486+ + nlm1[index] * nlm2[index + length * 2 ] * dis2.z );
487+ stress[5 ] += tmp
488+ * (nlm1[index + length * 3 ] * dis1.z * nlm2[index]
489+ + nlm1[index] * nlm2[index + length * 3 ] * dis2.z );
490+ }
385491 }
492+ dm_pointer += npol;
386493 }
387- dm_pointer += npol;
494+ dm_pointer += ( npol - 1 ) * col_indexes. size () ;
388495 }
389- dm_pointer += (npol - 1 ) * col_indexes.size ();
390496 }
391497 }
392498}
0 commit comments