/*============================================================ * Function computing G matrix for the system using circular truncation @args: nG: the user given nG, will be changed reciprocalLattice: the reciprocal lattice Gx_mat: the G matrix in x direction Gy_mat: the G matrix in y direction ==============================================================*/ static void GSelCircular( int& nG, const Lattice& reciprocalLattice, RCWArMatrix& Gx_mat, RCWArMatrix& Gy_mat ){ double Lk[4] = { reciprocalLattice.bx[0] / (2 * M_PI), reciprocalLattice.bx[1] / (2 * M_PI), reciprocalLattice.by[0] / (2 * M_PI), reciprocalLattice.by[1] / (2 * M_PI), }; const double u = hypot(Lk[0],Lk[1]); const double v = hypot(Lk[2],Lk[3]); const double u2 = Lk[0]*Lk[0] + Lk[1]*Lk[1]; const double v2 = Lk[2]*Lk[2] + Lk[3]*Lk[3]; const double uv = Lk[0]*Lk[2] + Lk[1]*Lk[3]; double Lkprod[3] = { u2, 2*uv, v2 }; const double uxv = fabs(Lk[0]*Lk[3] - Lk[1]*Lk[2]); const double circ_area = nG * uxv; const double circ_radius = sqrt(circ_area/M_PI) + u + v; const int u_extent = 1+(int)(circ_radius/(u*sqrt(1.-uv*uv/(u2*v2)))); const int v_extent = 1+(int)(circ_radius/(v*sqrt(1.-uv*uv/(u2*v2)))); const int uext21 = 2*u_extent+1; const int vext21 = 2*v_extent+1; int *Gtemp = new int[2*uext21*vext21]; int i, j; for(i = 0; i < uext21; ++i){ for(j = 0; j < vext21; ++j){ Gtemp[2*(i+j*uext21)+0] = i-u_extent; Gtemp[2*(i+j*uext21)+1] = j-v_extent; } } UTILITY::Sort(Gtemp, uext21*vext21, 2*sizeof(int), &Gcmp, &Lkprod[0]); j = uext21*vext21; if(nG < j){ j = nG; } for(i = j; i > 0; --i){ if(!G_same(&Gtemp[2*(i-1)], &Gtemp[2*(i-0)], Lk)){ break; } } nG = i; Gx_mat.set_size(nG, 1); Gy_mat.set_size(nG, 1); for(i = 0; i < nG; ++i){ Gx_mat(i, 0) = Gtemp[2*i+0]; Gy_mat(i, 0) = Gtemp[2*i+1]; } RCWArMatrix GxMat_temp = Gx_mat * reciprocalLattice.bx[0] + Gy_mat * reciprocalLattice.by[0]; Gy_mat = Gx_mat * reciprocalLattice.bx[1] + Gy_mat * reciprocalLattice.by[1]; Gx_mat = GxMat_temp; delete [] Gtemp; }
static int Gsel_circular(unsigned int *NG, const double Lk[4], int *G) { // NG * |u x v| is approximately the area in k-space we will need cover // with a circular disc. (u and v are the 2 shortest lattice vectors) // From the area, we can find the radius (and round it up). Then, we // can find the minimum extends in each of the two lattice directions. const double u = hypot(Lk[0],Lk[1]); const double v = hypot(Lk[2],Lk[3]); const double u2 = Lk[0]*Lk[0] + Lk[1]*Lk[1]; const double v2 = Lk[2]*Lk[2] + Lk[3]*Lk[3]; const double uv = Lk[0]*Lk[2] + Lk[1]*Lk[3]; double Lkprod[3] = { u2, 2*uv, v2 }; const double uxv = fabs(Lk[0]*Lk[3] - Lk[1]*Lk[2]); const double circ_area = (double)(*NG) * uxv; const double circ_radius = sqrt(circ_area/M_PI) + u+v; const int u_extent = 1+(int)(circ_radius/(u*sqrt(1.-uv*uv/(u2*v2)))); const int v_extent = 1+(int)(circ_radius/(v*sqrt(1.-uv*uv/(u2*v2)))); const int uext21 = 2*u_extent+1; const int vext21 = 2*v_extent+1; int *Gtemp = (int*)malloc(sizeof(int)*2*uext21*vext21); int i, j; for(i = 0; i < uext21; ++i) { for(j = 0; j < vext21; ++j) { Gtemp[2*(i+j*uext21)+0] = i-u_extent; Gtemp[2*(i+j*uext21)+1] = j-v_extent; } } sort(Gtemp, uext21*vext21, 2*sizeof(int), &Gcmp, &Lkprod[0]); j = uext21*vext21; if((int)*NG < j) { j = *NG; } for(i = j; i > 0; --i) { if(!G_same(&Gtemp[2*(i-1)], &Gtemp[2*(i-0)], Lk)) { break; } } *NG = i; for(i = 0; i < (int)*NG; ++i) { G[2*i+0] = Gtemp[2*i+0]; G[2*i+1] = Gtemp[2*i+1]; } free(Gtemp); return 0; }