11#include < memory>
22#include < array>
3+ #include < set>
34#include " module_parameter/parameter.h"
45#include " symmetry.h"
56#include " module_parameter/parameter.h"
67#include " module_base/libm/libm.h"
78#include " module_base/mathzone.h"
89#include " module_base/constants.h"
910#include " module_base/timer.h"
10-
11+ # include " module_io/output.h "
1112namespace ModuleSymmetry
1213{
1314int Symmetry::symm_flag = 0 ;
@@ -124,57 +125,16 @@ void Symmetry::analy_sys(const Lattice& lat, const Statistics& st, Atom* atoms,
124125 }
125126
126127 if (!pricell_loop && PARAM.inp .nspin == 2 )
127- {// analyze symmetry for spin-up atoms only
128- std::vector<double > pos_spinup;
129- for (int it = 0 ;it < ntype;++it)
130- {
131- int na_spinup = 0 ;
132- for (int ia = 0 ; ia < atoms[it].na ; ++ia) {
133- if (atoms[it].mag [ia] > -this ->epsilon ) {
134- ++na_spinup;
135- }
136- }
137- this ->na [it] = na_spinup;
138- // update newpos
139- for (int ia = 0 ;ia < atoms[it].na ;++ia)
140- {
141- if (atoms[it].mag [ia] > -this ->epsilon )
142- {
143- pos_spinup.push_back (this ->newpos [3 * (istart[it] + ia)]);
144- pos_spinup.push_back (this ->newpos [3 * (istart[it] + ia) + 1 ]);
145- pos_spinup.push_back (this ->newpos [3 * (istart[it] + ia) + 2 ]);
146- }
147- }
148- // update start to spin-up configuration
149- if (it > 0 ) {
150- istart[it] = istart[it - 1 ] + na[it - 1 ];
151- }
152- if (na[it] < na[itmin_type])
153- {
154- this ->itmin_type = it;
155- this ->itmin_start = istart[it];
156- }
157- }
158- this ->getgroup (nrot_out, nrotk_out, ofs_running, this ->nop , this ->symop , this ->gmatrix , this ->gtrans ,
159- pos_spinup.data (), this ->rotpos , this ->index , this ->itmin_type , this ->itmin_start , this ->istart , this ->na );
160- // recover na and istart
161- for (int it = 0 ;it < ntype;++it)
162- {
163- this ->na [it] = atoms[it].na ;
164- if (it > 0 ) {
165- istart[it] = istart[it - 1 ] + na[it - 1 ];
166- }
167- }
168- // For AFM analysis End
169- // ------------------------------------------------------------
128+ {
129+ this ->analyze_magnetic_group (atoms, st, nrot_out, nrotk_out);
170130 }
171131 else
172132 {
173133 // get the real symmetry operations according to the input structure
174134 // nrot_out: the number of pure point group rotations
175135 // nrotk_out: the number of all space group operations
176136 this ->getgroup (nrot_out, nrotk_out, ofs_running, this ->nop , this ->symop , this ->gmatrix , this ->gtrans ,
177- this ->newpos , this ->rotpos , this ->index , this ->itmin_type , this ->itmin_start , this ->istart , this ->na );
137+ this ->newpos , this ->rotpos , this ->index , this ->ntype , this -> itmin_type , this ->itmin_start , this ->istart , this ->na );
178138 }
179139 };
180140
@@ -889,7 +849,7 @@ void Symmetry::lattice_type(
889849
890850void Symmetry::getgroup (int & nrot, int & nrotk, std::ofstream& ofs_running, const int & nop,
891851 const ModuleBase::Matrix3* symop, ModuleBase::Matrix3* gmatrix, ModuleBase::Vector3<double >* gtrans,
892- double * pos, double * rotpos, int * index, const int itmin_type, const int itmin_start, int * istart, int * na)const
852+ double * pos, double * rotpos, int * index, const int ntype, const int itmin_type, const int itmin_start, int * istart, int * na)const
893853{
894854 ModuleBase::TITLE (" Symmetry" , " getgroup" );
895855
@@ -913,7 +873,7 @@ void Symmetry::getgroup(int& nrot, int& nrotk, std::ofstream& ofs_running, const
913873 // std::cout << "nop = " <<nop <<std::endl;
914874 for (int i = 0 ; i < nop; ++i)
915875 {
916- bool s_flag = this ->checksym (symop[i], gtrans[i], pos, rotpos, index, itmin_type, itmin_start, istart, na);
876+ bool s_flag = this ->checksym (symop[i], gtrans[i], pos, rotpos, index, ntype, itmin_type, itmin_start, istart, na);
917877 if (s_flag == 1 )
918878 {
919879 // ------------------------------
@@ -992,7 +952,7 @@ void Symmetry::getgroup(int& nrot, int& nrotk, std::ofstream& ofs_running, const
992952}
993953
994954bool Symmetry::checksym (const ModuleBase::Matrix3& s, ModuleBase::Vector3<double >& gtrans,
995- double * pos, double * rotpos, int * index, const int itmin_type, const int itmin_start, int * istart, int * na)const
955+ double * pos, double * rotpos, int * index, const int ntype, const int itmin_type, const int itmin_start, int * istart, int * na)const
996956{
997957 // ----------------------------------------------
998958 // checks whether a point group symmetry element
@@ -2297,4 +2257,70 @@ bool Symmetry::is_all_movable(const Atom* atoms, const Statistics& st)const
22972257 }
22982258 return all_mbl;
22992259}
2260+
2261+ void Symmetry::analyze_magnetic_group (const Atom* atoms, const Statistics& st, int & nrot_out, int & nrotk_out)
2262+ {
2263+ // 1. classify atoms with different magmom
2264+ // (use symmetry_prec to judge if two magmoms are the same)
2265+ std::vector<std::set<int >> mag_type_atoms;
2266+ for (int it = 0 ;it < ntype;++it)
2267+ {
2268+ for (int ia = 0 ; ia < atoms[it].na ; ++ia)
2269+ {
2270+ bool find = false ;
2271+ for (auto & mt : mag_type_atoms)
2272+ {
2273+ const int mag_iat = *mt.begin ();
2274+ const int mag_it = st.iat2it [mag_iat];
2275+ const int mag_ia = st.iat2ia [mag_iat];
2276+ if (it == mag_it && this ->equal (atoms[it].mag [ia], atoms[mag_it].mag [mag_ia]))
2277+ {
2278+ mt.insert (st.itia2iat (it, ia));
2279+ find = true ;
2280+ break ;
2281+ }
2282+ }
2283+ if (!find)
2284+ {
2285+ mag_type_atoms.push_back (std::set<int >({ st.itia2iat (it,ia) }));
2286+ }
2287+ }
2288+ }
2289+
2290+ // 2. get the start index, number of atoms and positions for each mag_type
2291+ std::vector<int > mag_istart (mag_type_atoms.size ());
2292+ std::vector<int > mag_na (mag_type_atoms.size ());
2293+ std::vector<double > mag_pos;
2294+ int mag_itmin_type = 0 ;
2295+ int mag_itmin_start = 0 ;
2296+ for (int mag_it = 0 ;mag_it < mag_type_atoms.size (); ++mag_it)
2297+ {
2298+ mag_na[mag_it] = mag_type_atoms.at (mag_it).size ();
2299+ if (mag_it > 0 )
2300+ {
2301+ mag_istart[mag_it] = mag_istart[mag_it - 1 ] + mag_na[mag_it - 1 ];
2302+ }
2303+ if (mag_na[mag_it] < mag_na[itmin_type])
2304+ {
2305+ mag_itmin_type = mag_it;
2306+ mag_itmin_start = mag_istart[mag_it];
2307+ }
2308+ for (auto & mag_iat : mag_type_atoms.at (mag_it))
2309+ {
2310+ // this->newpos have been ordered by original structure(ntype, na), it cannot be directly used here.
2311+ // we need to reset the calculate again the coordinate of the new structure.
2312+ const ModuleBase::Vector3<double > direct_tmp = atoms[st.iat2it [mag_iat]].tau [st.iat2ia [mag_iat]] * this ->optlat .Inverse ();
2313+ std::array<double , 3 > direct = { direct_tmp.x , direct_tmp.y , direct_tmp.z };
2314+ for (int i = 0 ; i < 3 ; ++i)
2315+ {
2316+ this ->check_translation (direct[i], -floor (direct[i]));
2317+ this ->check_boundary (direct[i]);
2318+ mag_pos.push_back (direct[i]);
2319+ }
2320+ }
2321+ }
2322+ // 3. analyze the effective structure
2323+ this ->getgroup (nrot_out, nrotk_out, GlobalV::ofs_running, this ->nop , this ->symop , this ->gmatrix , this ->gtrans ,
2324+ mag_pos.data (), this ->rotpos , this ->index , mag_type_atoms.size (), mag_itmin_type, mag_itmin_start, mag_istart.data (), mag_na.data ());
2325+ }
23002326}
0 commit comments