UnitCell.C 9.61 KB
Newer Older
Francois Gygi committed
1 2
////////////////////////////////////////////////////////////////////////////////
//
3
// UnitCell.C
Francois Gygi committed
4 5
//
////////////////////////////////////////////////////////////////////////////////
6
// $Id: UnitCell.C,v 1.13 2007-10-19 16:24:05 fgygi Exp $
Francois Gygi committed
7 8 9 10 11 12 13 14 15 16

#include "UnitCell.h"
#include <iostream>
#include <iomanip>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
void UnitCell::set(const D3vector& a0, const D3vector& a1, const D3vector& a2)
{
  a_[0] = a0; a_[1] = a1, a_[2] = a2;
17 18 19 20 21 22 23 24 25
  amat_[0] = a0.x;
  amat_[1] = a0.y;
  amat_[2] = a0.z;
  amat_[3] = a1.x;
  amat_[4] = a1.y;
  amat_[5] = a1.z;
  amat_[6] = a2.x;
  amat_[7] = a2.y;
  amat_[8] = a2.z;
26

27
  // volume = det(A)
Francois Gygi committed
28 29 30
  volume_ = a0 * ( a1 ^ a2 );
  if ( volume_ > 0.0 )
  {
31 32 33 34 35
    // Compute rows of A-1 (columns of A^-T)
    double fac = 1.0 / volume_;
    D3vector amt0 = fac * a1 ^ a2;
    D3vector amt1 = fac * a2 ^ a0;
    D3vector amt2 = fac * a0 ^ a1;
36

37 38 39 40 41 42 43 44 45
    amat_inv_[0] = amt0.x;
    amat_inv_[1] = amt1.x;
    amat_inv_[2] = amt2.x;
    amat_inv_[3] = amt0.y;
    amat_inv_[4] = amt1.y;
    amat_inv_[5] = amt2.y;
    amat_inv_[6] = amt0.z;
    amat_inv_[7] = amt1.z;
    amat_inv_[8] = amt2.z;
46

47 48 49 50 51 52 53 54 55
    amat_inv_t_[0] = amt0.x;
    amat_inv_t_[1] = amt0.y;
    amat_inv_t_[2] = amt0.z;
    amat_inv_t_[3] = amt1.x;
    amat_inv_t_[4] = amt1.y;
    amat_inv_t_[5] = amt1.z;
    amat_inv_t_[6] = amt2.x;
    amat_inv_t_[7] = amt2.y;
    amat_inv_t_[8] = amt2.z;
56

57 58 59 60 61 62 63 64 65 66 67 68 69 70
    // B = 2 pi A^-T
    b_[0] = 2.0 * M_PI * amt0;
    b_[1] = 2.0 * M_PI * amt1;
    b_[2] = 2.0 * M_PI * amt2;

    bmat_[0] = b_[0].x;
    bmat_[1] = b_[0].y;
    bmat_[2] = b_[0].z;
    bmat_[3] = b_[1].x;
    bmat_[4] = b_[1].y;
    bmat_[5] = b_[1].z;
    bmat_[6] = b_[2].x;
    bmat_[7] = b_[2].y;
    bmat_[8] = b_[2].z;
Francois Gygi committed
71 72 73 74
  }
  else
  {
    b_[0] = b_[1] = b_[2] = D3vector(0.0,0.0,0.0);
75 76
    amat_inv_[0] =  amat_inv_[1] =  amat_inv_[2] =
      amat_inv_[3] =  amat_inv_[4] =  amat_inv_[5] =
77
      amat_inv_[6] =  amat_inv_[7] =  amat_inv_[8] = 0.0;
78 79
    bmat_[0] =  bmat_[1] =  bmat_[2] =
      bmat_[3] =  bmat_[4] =  bmat_[5] =
80
      bmat_[6] =  bmat_[7] =  bmat_[8] = 0.0;
Francois Gygi committed
81
  }
82 83 84



Francois Gygi committed
85 86 87 88 89 90 91 92 93 94 95 96 97
  an_[0]  = a_[0];
  an_[1]  = a_[1];
  an_[2]  = a_[2];
  an_[3]  = a_[0] + a_[1];
  an_[4]  = a_[0] - a_[1];
  an_[5]  = a_[1] + a_[2];
  an_[6]  = a_[1] - a_[2];
  an_[7]  = a_[2] + a_[0];
  an_[8]  = a_[2] - a_[0];
  an_[9]  = a_[0] + a_[1] + a_[2];
  an_[10] = a_[0] - a_[1] - a_[2];
  an_[11] = a_[0] + a_[1] - a_[2];
  an_[12] = a_[0] - a_[1] + a_[2];
98

Francois Gygi committed
99 100 101 102 103 104 105 106 107 108 109 110 111
  bn_[0]  = b_[0];
  bn_[1]  = b_[1];
  bn_[2]  = b_[2];
  bn_[3]  = b_[0] + b_[1];
  bn_[4]  = b_[0] - b_[1];
  bn_[5]  = b_[1] + b_[2];
  bn_[6]  = b_[1] - b_[2];
  bn_[7]  = b_[2] + b_[0];
  bn_[8]  = b_[2] - b_[0];
  bn_[9]  = b_[0] + b_[1] + b_[2];
  bn_[10] = b_[0] - b_[1] - b_[2];
  bn_[11] = b_[0] + b_[1] - b_[2];
  bn_[12] = b_[0] - b_[1] + b_[2];
112

Francois Gygi committed
113 114 115 116 117 118
  for ( int i = 0; i < 13; i++ )
  {
    an2h_[i] = 0.5 * norm(an_[i]);
    bn2h_[i] = 0.5 * norm(bn_[i]);
  }
}
119

Francois Gygi committed
120 121 122 123 124 125 126 127 128 129 130 131
////////////////////////////////////////////////////////////////////////////////
bool UnitCell::in_ws(const D3vector& v) const
{
  bool in = true;
  int i = 0;
  while ( i < 13 && in )
  {
    in = ( abs(v*an_[i]) <= an2h_[i] ) ;
    i++;
  }
  return in;
}
132

Francois Gygi committed
133 134 135
////////////////////////////////////////////////////////////////////////////////
void UnitCell::fold_in_ws(D3vector& v) const
{
136
  const double epsilon = 1.e-10;
Francois Gygi committed
137
  bool done = false;
138 139 140
  const int maxiter = 10;
  int iter = 0;
  while ( !done && iter < maxiter )
Francois Gygi committed
141 142 143 144 145
  {
    done = true;
    for ( int i = 0; (i < 13) && done; i++ )
    {
      const double sp = v*an_[i];
146
      if ( sp > an2h_[i] + epsilon )
Francois Gygi committed
147 148 149 150
      {
        done = false;
        do
          v -= an_[i];
151
        while ( v*an_[i] > an2h_[i] + epsilon );
Francois Gygi committed
152
      }
153
      else if ( sp < -an2h_[i] - epsilon )
Francois Gygi committed
154 155 156 157
      {
        done = false;
        do
          v += an_[i];
158
        while ( v*an_[i] < -an2h_[i] - epsilon );
Francois Gygi committed
159 160
      }
    }
161
    iter++;
Francois Gygi committed
162
  }
163
  assert(iter < maxiter);
Francois Gygi committed
164
}
165

Francois Gygi committed
166 167 168 169 170 171 172 173 174 175 176 177
////////////////////////////////////////////////////////////////////////////////
bool UnitCell::in_bz(const D3vector& k) const
{
  bool in = true;
  int i = 0;
  while ( i < 13 && in )
  {
    in = ( abs(k*bn_[i]) <= bn2h_[i] ) ;
    i++;
  }
  return in;
}
178

Francois Gygi committed
179 180 181
////////////////////////////////////////////////////////////////////////////////
void UnitCell::fold_in_bz(D3vector& k) const
{
182
  const double epsilon = 1.e-10;
Francois Gygi committed
183
  bool done = false;
184 185 186
  const int maxiter = 10;
  int iter = 0;
  while ( !done && iter < maxiter )
Francois Gygi committed
187 188 189 190 191
  {
    done = true;
    for ( int i = 0; (i < 13) && done; i++ )
    {
      double sp = k*bn_[i];
192
      if ( sp > bn2h_[i] + epsilon )
Francois Gygi committed
193 194 195 196
      {
        done = false;
        do
          k -= bn_[i];
197
        while ( k*bn_[i] > bn2h_[i] + epsilon );
Francois Gygi committed
198
      }
199
      else if ( sp < -bn2h_[i] - epsilon )
Francois Gygi committed
200 201 202 203
      {
        done = false;
        do
          k += bn_[i];
204
        while ( k*bn_[i] < -bn2h_[i] - epsilon );
Francois Gygi committed
205 206
      }
    }
207
    iter++;
Francois Gygi committed
208
  }
209
  assert(iter < maxiter);
Francois Gygi committed
210
}
211

Francois Gygi committed
212 213 214 215 216 217 218
////////////////////////////////////////////////////////////////////////////////
bool UnitCell::encloses(const UnitCell& c) const
{
  bool in = true;
  int i = 0;
  while ( i < 13 && in )
  {
219 220 221 222
    in = ( contains(c.an_[i]) );
    if ( !in )
      cout << "UnitCell::encloses: " << c.an_[i] << " not in cell "
      << c << endl;
Francois Gygi committed
223 224 225 226 227 228 229 230 231 232 233 234
    i++;
  }
  return in;
}

////////////////////////////////////////////////////////////////////////////////
bool UnitCell::contains(D3vector v) const
{
  const double fac = 0.5 / ( 2.0 * M_PI );
  const double p0 = fac * v * b_[0];
  const double p1 = fac * v * b_[1];
  const double p2 = fac * v * b_[2];
235 236 237
  return ( (p0 > 0.0) && (p0 <= 1.0) &&
           (p1 > 0.0) && (p1 <= 1.0) &&
           (p2 > 0.0) && (p2 <= 1.0) );
Francois Gygi committed
238
}
239

Francois Gygi committed
240 241 242 243
////////////////////////////////////////////////////////////////////////////////
void UnitCell::print(ostream& os) const
{
  os.setf(ios::fixed,ios::floatfield);
Francois Gygi committed
244
  os << setprecision(8);
245 246
  os << "    <a> " << setw(12) << a_[0].x << " "
                   << setw(12) << a_[0].y << " "
Francois Gygi committed
247
                   << setw(12) << a_[0].z << " </a>" << endl;
248 249
  os << "    <b> " << setw(12) << a_[1].x << " "
                   << setw(12) << a_[1].y << " "
Francois Gygi committed
250
                   << setw(12) << a_[1].z << " </b>" << endl;
251 252
  os << "    <c> " << setw(12) << a_[2].x << " "
                   << setw(12) << a_[2].y << " "
Francois Gygi committed
253
                   << setw(12) << a_[2].z << " </c>" << endl;
Francois Gygi committed
254
}
255

Francois Gygi committed
256 257 258 259 260
////////////////////////////////////////////////////////////////////////////////
bool UnitCell::operator==(const UnitCell& c) const
{
  return ( a_[0]==c.a_[0] && a_[1]==c.a_[1] && a_[2]==c.a_[2] );
}
261

262 263 264 265 266 267 268 269 270 271 272 273
////////////////////////////////////////////////////////////////////////////////
bool UnitCell::operator!=(const UnitCell& c) const
{
  return ! ( *this == c );
}

////////////////////////////////////////////////////////////////////////////////
void UnitCell::vecmult3x3(const double* x, const double* y, double *z) const
{
  //  | z0 |     | x0 x3 x6 |     | y0 |
  //  | z1 |  =  | x1 x4 x7 |  *  | y1 |
  //  | z2 |     | x2 x5 x8 |     | y2 |
274

275 276 277 278 279 280 281
  const double z0 = x[0]*y[0]+x[3]*y[1]+x[6]*y[2];
  const double z1 = x[1]*y[0]+x[4]*y[1]+x[7]*y[2];
  const double z2 = x[2]*y[0]+x[5]*y[1]+x[8]*y[2];
  z[0] = z0;
  z[1] = z1;
  z[2] = z2;
}
282

283 284 285 286 287 288
////////////////////////////////////////////////////////////////////////////////
void UnitCell::matmult3x3(const double* x, const double* y, double *z) const
{
  //  | z0 z3 z6 |     | x0 x3 x6 |     | y0 y3 y6 |
  //  | z1 z4 z7 |  =  | x1 x4 x7 |  *  | y1 y4 y7 |
  //  | z2 z5 z8 |     | x2 x5 x8 |     | y2 y5 y8 |
289

290 291 292
  const double z00 = x[0]*y[0]+x[3]*y[1]+x[6]*y[2];
  const double z10 = x[1]*y[0]+x[4]*y[1]+x[7]*y[2];
  const double z20 = x[2]*y[0]+x[5]*y[1]+x[8]*y[2];
293

294 295 296
  const double z01 = x[0]*y[3]+x[3]*y[4]+x[6]*y[5];
  const double z11 = x[1]*y[3]+x[4]*y[4]+x[7]*y[5];
  const double z21 = x[2]*y[3]+x[5]*y[4]+x[8]*y[5];
297

298 299 300
  const double z02 = x[0]*y[6]+x[3]*y[7]+x[6]*y[8];
  const double z12 = x[1]*y[6]+x[4]*y[7]+x[7]*y[8];
  const double z22 = x[2]*y[6]+x[5]*y[7]+x[8]*y[8];
301

302 303 304
  z[0] = z00;
  z[1] = z10;
  z[2] = z20;
305

306 307 308
  z[3] = z01;
  z[4] = z11;
  z[5] = z21;
309

310 311
  z[6] = z02;
  z[7] = z12;
312
  z[8] = z22;
313
}
314

315 316 317 318 319 320
////////////////////////////////////////////////////////////////////////////////
void UnitCell::smatmult3x3(const double* xs, const double* y, double *z) const
{
  //  | z0 z3 z6 |     | xs0 xs3 xs5 |     | y0 y3 y6 |
  //  | z1 z4 z7 |  =  | xs3 xs1 xs4 |  *  | y1 y4 y7 |
  //  | z2 z5 z8 |     | xs5 xs4 xs2 |     | y2 y5 y8 |
321

322 323 324
  const double z00 = xs[0]*y[0]+xs[3]*y[1]+xs[5]*y[2];
  const double z10 = xs[3]*y[0]+xs[1]*y[1]+xs[4]*y[2];
  const double z20 = xs[5]*y[0]+xs[4]*y[1]+xs[2]*y[2];
325

326 327 328
  const double z01 = xs[0]*y[3]+xs[3]*y[4]+xs[5]*y[5];
  const double z11 = xs[3]*y[3]+xs[1]*y[4]+xs[4]*y[5];
  const double z21 = xs[5]*y[3]+xs[4]*y[4]+xs[2]*y[5];
329

330 331 332
  const double z02 = xs[0]*y[6]+xs[3]*y[7]+xs[5]*y[8];
  const double z12 = xs[3]*y[6]+xs[1]*y[7]+xs[4]*y[8];
  const double z22 = xs[5]*y[6]+xs[4]*y[7]+xs[2]*y[8];
333

334 335 336
  z[0] = z00;
  z[1] = z10;
  z[2] = z20;
337

338 339 340
  z[3] = z01;
  z[4] = z11;
  z[5] = z21;
341

342 343
  z[6] = z02;
  z[7] = z12;
344
  z[8] = z22;
345 346 347 348 349 350 351 352
}
////////////////////////////////////////////////////////////////////////////////
void UnitCell::compute_deda(const valarray<double>& sigma,
 valarray<double>& deda) const
{
  // Compute energy derivatives dE/da_ij from a symmetric stress tensor
  assert(sigma.size()==6);
  assert(deda.size()==9);
353

354 355 356
  //!! local copy of sigma to circumvent bug in icc compiler
  valarray<double> sigma_loc(6);
  sigma_loc = sigma;
357

358 359
  // deda = - omega * sigma * A^-T
  smatmult3x3(&sigma_loc[0],&amat_inv_t_[0],&deda[0]);
360

361 362
  deda *= -volume_;
}
363

Francois Gygi committed
364 365
////////////////////////////////////////////////////////////////////////////////
ostream& operator<< ( ostream& os, const UnitCell& cell )
366 367
{
  cell.print(os);
Francois Gygi committed
368 369
  return os;
}