00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "qcevolve.h"
00028
00029 QCEvolve::QCEvolve(void)
00030 {
00031 h_t = 1e-4;
00032 }
00033
00034 QCEvolve::~QCEvolve(void)
00035 {
00036 }
00037
00038 void QCEvolve::evolveForwards(bool forwards)
00039 {
00040 if(forwards && h_t < 0.0)
00041 h_t *= -1.0;
00042 else if(!forwards && h_t > 0.0)
00043 h_t *= -1.0;
00044 }
00045
00046 bool QCEvolve::isForward()
00047 {
00048 if(h_t < 0.0)
00049 return false;
00050 else
00051 return true;
00052 }
00053
00054 void QCEvolve::usingTDGP(QCComplexField<2> ¤tField, parameterType xOffset, parameterType yOffset, parameterType &h_x, parameterType &h_y, QCParameter &tdgpParameters)
00055 {
00056 Array<complexType,2> oldField = *currentField.accessArray();
00057 int maxIterations = 4, xExtent = currentField.noOfRows()-1, yExtent = currentField.noOfColumns()-1;
00058 Array<complexType,1> a(xExtent),b(xExtent),c(xExtent),d(xExtent),X(xExtent);
00059
00060 parameterType x, y, omegaSq = tdgpParameters.getParameter(0), g = tdgpParameters.getParameter(2), hbar = tdgpParameters.getParameter(3), m = tdgpParameters.getParameter(4);
00061
00062
00063 x = 4.0*h_x*h_x*m;
00064 y = 4.0*h_y*h_y*m;
00065 complexType alpha_x(0.0,(h_t*hbar)/x),
00066 alpha_y(0.0,(h_t*hbar)/y),
00067 gamma(0.0,(m*omegaSq)/(2.0*hbar)),
00068 beta(0.0,g/hbar),
00069 Psi, oldPsi;
00070
00071 for(int p = 0; p < maxIterations; p ++)
00072 {
00073 for(int k = 1; k < yExtent; k ++)
00074 {
00075 y = (k)*h_y - yOffset;
00076 for(int j = 1; j < xExtent; j ++)
00077 {
00078 x = (j)*h_x - xOffset;
00079 Psi = currentField.retrieveElement(j,k);
00080 oldPsi = oldField(j,k);
00081
00082 a(j) = -alpha_x;
00083 b(j) = 1.0 + 2.0*alpha_x;
00084 c(j) = -alpha_x;
00085 d(j) = oldPsi
00086 + alpha_x*( oldField(j+1,k) + oldField(j-1,k)
00087 + oldField(j,k+1) + oldField(j,k-1) - 4.0*oldPsi)
00088 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y) + g*norm(Psi))*Psi
00089 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y) + g*norm(oldPsi))*oldPsi;
00090
00091 }
00092
00093
00094 b(1) = b(1) + 2.0*a(1);
00095 c(1) = c(1) - a(1);
00096 a(xExtent-1) = a(xExtent-1) - c(xExtent-1);
00097 b(xExtent-1) = b(xExtent-1) + 2.0*c(xExtent-1);
00098
00099 LA.solveTridiagonal(a,b,c,X,d);
00100 for(int j = 1; j < xExtent; j ++)
00101 {
00102 currentField.assignElement(j,k,X(j));
00103
00104 }
00105
00106 }
00107
00108 for(int j = 1; j < xExtent; j ++)
00109 {
00110 for(int k = 1; k < yExtent; k ++)
00111 {
00112
00113
00114
00115 d(k) = currentField.retrieveElement(j,k);
00116 }
00117
00118
00119
00120
00121
00122
00123 LA.solveTridiagonal(a,b,c,X,d);
00124 for(int k = 1; k < yExtent; k ++)
00125 {
00126 currentField.assignElement(j,k,X(k));
00127
00128 }
00129
00130 }
00131
00132 setBoundaryGradZero(currentField,oldField);
00133 }
00134 }
00135
00136 void QCEvolve::usingTDGPLz(QCComplexField<2> ¤tField, parameterType xOffset, parameterType yOffset, parameterType &h_x, parameterType &h_y, QCParameter &tdgpParameters)
00137 {
00138 int maxIterations = 4, xExtent = currentField.noOfRows()-1, yExtent = currentField.noOfColumns()-1;
00139 Array<complexType,1> a(xExtent),b(xExtent),c(xExtent),d(xExtent),X(xExtent);
00140 Array<complexType,2> oldField = *currentField.accessArray();
00141
00142 parameterType x, y, omegaSq = tdgpParameters.getParameter(0), g = tdgpParameters.getParameter(2), hbar = tdgpParameters.getParameter(3), m = tdgpParameters.getParameter(4), bigOmega = tdgpParameters.getParameter(5);
00143
00144
00145 x = 4.0*h_x*h_x*m;
00146 y = 4.0*h_y*h_y*m;
00147 complexType alpha_x(0.0,(h_t*hbar)/x),
00148 alpha_y(0.0,(h_t*hbar)/y),
00149 gamma(0.0,(m*omegaSq)/(2.0*hbar)),
00150 beta(0.0,g/hbar),
00151 Psi, oldPsi;
00152
00153 for(int m = 0; m < maxIterations; m ++)
00154 {
00155 for(int k = 1; k < yExtent; k ++)
00156 {
00157 y = (k)*h_y - yOffset;
00158 for(int j = 1; j < xExtent; j ++)
00159 {
00160 x = (j)*h_x - xOffset;
00161 Psi = currentField.retrieveElement(j,k);
00162 oldPsi = oldField(j,k);
00163
00164 a(j) = -alpha_x;
00165 b(j) = 1.0 + 2.0*alpha_x;
00166 c(j) = -alpha_x;
00167 d(j) = oldPsi
00168 + alpha_x*(oldField(j+1,k) + oldField(j-1,k) - 2.0*oldPsi)
00169 + alpha_y*(oldField(j,k+1) + oldField(j,k-1) - 2.0*oldPsi)
00170 - h_t*0.25*bigOmega*(y/h_x*(currentField.retrieveElement(j+1,k) - currentField.retrieveElement(j-1,k)) - x/h_y*(currentField.retrieveElement(j,k+1) - currentField.retrieveElement(j,k-1))
00171 + y/h_x*(oldField(j+1,k) - oldField(j-1,k)) - x/h_y*(oldField(j,k+1) - oldField(j,k-1)))
00172 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y)
00173 + g*norm(Psi))*Psi - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y)
00174 + g*norm(oldPsi))*oldPsi;
00175 }
00176
00177 b(1) = b(1) + 2.0*a(1);
00178 c(1) = c(1) - a(1);
00179 a(xExtent-1) = a(xExtent-1) - c(xExtent-1);
00180 b(xExtent-1) = b(xExtent-1) + 2.0*c(xExtent-1);
00181
00182 LA.solveTridiagonal(a,b,c,X,d);
00183 for(int j = 1; j < xExtent; j ++)
00184 currentField.assignElement(j,k,X(j));
00185 }
00186
00187 for(int j = 1; j < xExtent; j ++)
00188 {
00189 for(int k = 1; k < yExtent; k ++)
00190 {
00191 a(k) = -alpha_y;
00192 b(k) = 1.0 + 2.0*alpha_y;
00193 c(k) = -alpha_y;
00194 d(k) = currentField.retrieveElement(j,k);
00195 }
00196
00197 b(1) = b(1) + 2.0*a(1);
00198 c(1) = c(1) - a(1);
00199 a(yExtent-1) = a(yExtent-1) - c(yExtent-1);
00200 b(yExtent-1) = b(yExtent-1) + 2.0*c(yExtent-1);
00201
00202 LA.solveTridiagonal(a,b,c,X,d);
00203 for(int k = 1; k < yExtent; k ++)
00204 currentField.assignElement(j,k,X(k));
00205 }
00206
00207 setBoundaryVanish(currentField);
00208 }
00209 }
00210
00211 void QCEvolve::usingTDGP2Component(QCComplexField<2> &component1, QCComplexField<2> &component2, parameterType xOffset, parameterType yOffset, parameterType &h_x, parameterType &h_y, QCParameter &tdgpParameters)
00212 {
00213 int maxIterations = 4, xExtent = component1.noOfRows()-1, yExtent = component1.noOfColumns()-1;
00214 Array<complexType,1> a1(xExtent),b1(xExtent),c1(xExtent),d1(xExtent),X1(xExtent);
00215 Array<complexType,1> a2(xExtent),b2(xExtent),c2(xExtent),d2(xExtent),X2(xExtent);
00216 Array<complexType,2> oldComponent1 = *component1.accessArray();
00217 Array<complexType,2> oldComponent2 = *component2.accessArray();
00218 parameterType x, y, omegaSq = tdgpParameters.getParameter(0), hbar = tdgpParameters.getParameter(3), m = tdgpParameters.getParameter(4), bigOmega = tdgpParameters.getParameter(5);
00219 parameterType g11 = tdgpParameters.getParameter(7), g22 = tdgpParameters.getParameter(8), g12 = tdgpParameters.getParameter(9), g21 = tdgpParameters.getParameter(10);
00220
00221
00222 x = 4.0*h_x*h_x*m;
00223 y = 4.0*h_y*h_y*m;
00224 complexType alpha_x(0.0,(h_t*hbar)/x),
00225 alpha_y(0.0,(h_t*hbar)/y);
00226
00227 for(int m = 0; m < maxIterations; m ++)
00228 {
00229 for(int k = 1; k < yExtent; k ++)
00230 {
00231 y = k*h_y - yOffset;
00232 for(int j = 1; j < xExtent; j ++)
00233 {
00234 x = j*h_x - xOffset;
00235
00236 a1(j) = a2(j) = -alpha_x;
00237 b1(j) = b2(j) = 1.0 + 2.0*alpha_x;
00238 c1(j) = c2(j) = -alpha_x;
00239 d1(j) = oldComponent1(j,k)
00240 + alpha_x*(oldComponent1(j+1,k) + oldComponent1(j-1,k) - 2.0*oldComponent1(j,k))
00241 + alpha_y*(oldComponent1(j,k+1) + oldComponent1(j,k-1) - 2.0*oldComponent1(j,k))
00242
00243
00244 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y)
00245 + g11*norm(component1.retrieveElement(j,k))
00246 + g12*norm(component2.retrieveElement(j,k)))*component1.retrieveElement(j,k)
00247 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y)
00248 + g11*norm(oldComponent1(j,k))
00249 + g12*norm(oldComponent2(j,k)))*oldComponent1(j,k);
00250 d2(j) = oldComponent2(j,k)
00251 + alpha_x*(oldComponent2(j+1,k) + oldComponent2(j-1,k) - 2.0*oldComponent2(j,k))
00252 + alpha_y*(oldComponent2(j,k+1) + oldComponent2(j,k-1) - 2.0*oldComponent2(j,k))
00253
00254
00255 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y)
00256 + g22*norm(component2.retrieveElement(j,k))
00257 + g21*norm(component1.retrieveElement(j,k)))*component2.retrieveElement(j,k)
00258 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y)
00259 + g22*norm(oldComponent2(j,k))
00260 + g21*norm(oldComponent1(j,k)))*oldComponent2(j,k);
00261 }
00262
00263
00264 b1(1) = b1(1) + 2.0*a1(1);
00265 c1(1) = c1(1) - a1(1);
00266 a1(xExtent-1) = a1(xExtent-1) - c1(xExtent-1);
00267 b1(xExtent-1) = b1(xExtent-1) + 2.0*c1(xExtent-1);
00268
00269 b2(1) = b2(1) + 2.0*a2(1);
00270 c2(1) = c2(1) - a2(1);
00271 a2(xExtent-1) = a2(xExtent-1) - c2(xExtent-1);
00272 b2(xExtent-1) = b2(xExtent-1) + 2.0*c2(xExtent-1);
00273
00274 LA.solveTridiagonal(a1,b1,c1,X1,d1);
00275 LA.solveTridiagonal(a2,b2,c2,X2,d2);
00276 for(int j = 1; j < xExtent; j ++)
00277 {
00278 component1.assignElement(j,k,X1(j));
00279 component2.assignElement(j,k,X2(j));
00280 }
00281 }
00282
00283 for(int j = 1; j < xExtent; j ++)
00284 {
00285 for(int k = 1; k < yExtent; k ++)
00286 {
00287 a1(k) = a2(k) = -alpha_y;
00288 b1(k) = b2(k) = 1.0 + 2.0*alpha_y;
00289 c1(k) = c2(k) = -alpha_y;
00290 d1(k) = component1.retrieveElement(j,k);
00291 d2(k) = component2.retrieveElement(j,k);
00292 }
00293
00294
00295 b1(1) = b1(1) + 2.0*a1(1);
00296 c1(1) = c1(1) - a1(1);
00297 a1(yExtent-1) = a1(yExtent-1) - c1(yExtent-1);
00298 b1(yExtent-1) = b1(yExtent-1) + 2.0*c1(yExtent-1);
00299
00300 b2(1) = b2(1) + 2.0*a2(1);
00301 c2(1) = c2(1) - a2(1);
00302 a2(yExtent-1) = a2(yExtent-1) - c2(yExtent-1);
00303 b2(yExtent-1) = b2(yExtent-1) + 2.0*c2(yExtent-1);
00304
00305 LA.solveTridiagonal(a1,b1,c1,X1,d1);
00306 LA.solveTridiagonal(a2,b2,c2,X2,d2);
00307 for(int k = 1; k < yExtent; k ++)
00308 {
00309 component1.assignElement(j,k,X1(k));
00310 component2.assignElement(j,k,X2(k));
00311 }
00312 }
00313
00314 setBoundaryVanish(component1);
00315 setBoundaryVanish(component2);
00316 }
00317 }
00318
00319 void QCEvolve::usingTDGP3D(QCComplexField<3> ¤tField, parameterType xOffset, parameterType yOffset, parameterType zOffset, parameterType &h_x, parameterType &h_y, parameterType &h_z, QCParameter &tdgpParameters)
00320 {
00321 Array<complexType,3> oldField = *currentField.accessArray();
00322 int maxIterations = 4, xExtent = currentField.noOfRows()-1, yExtent = currentField.noOfColumns()-1, zExtent = currentField.height()-1;
00323 Array<complexType,1> a(xExtent),b(xExtent),c(xExtent),d(xExtent),X(xExtent);
00324
00325 parameterType x, y, z, omegaSq = tdgpParameters.getParameter(0), g = tdgpParameters.getParameter(2), hbar = tdgpParameters.getParameter(3), m = tdgpParameters.getParameter(4);
00326
00327
00328 x = 4.0*h_x*h_x*m;
00329 y = 4.0*h_y*h_y*m;
00330 z = 4.0*h_z*h_z*m;
00331 complexType alpha_x(0.0,(h_t*hbar)/x),
00332 alpha_y(0.0,(h_t*hbar)/y),
00333 alpha_z(0.0,(h_t*hbar)/z),
00334 gamma(0.0,(m*omegaSq)/(2.0*hbar)),
00335 beta(0.0,g/hbar),
00336 Psi, oldPsi;
00337
00338 for(int m = 0; m < maxIterations; m ++)
00339 {
00340 for(int l = 1; l < zExtent; l ++)
00341 {
00342 z = (l)*h_z - zOffset;
00343 for(int k = 1; k < yExtent; k ++)
00344 {
00345 y = (k)*h_y - yOffset;
00346 for(int j = 1; j < xExtent; j ++)
00347 {
00348 x = (j)*h_x - xOffset;
00349 Psi = currentField.retrieveElement(j,k,l);
00350 oldPsi = oldField(j,k,l);
00351
00352 a(j) = -alpha_x;
00353 b(j) = 1.0 + 2.0*alpha_x;
00354 c(j) = -alpha_x;
00355 d(j) = oldPsi
00356 + alpha_x*( oldField(j+1,k,l) + oldField(j-1,k,l)
00357 + oldField(j,k+1,l) + oldField(j,k-1,l)
00358 + oldField(j,k,l+1) + oldField(j,k,l-1) - 6.0*oldPsi)
00359 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y + z*z) + g*norm(Psi))*Psi
00360 - h_t*0.5*i/hbar*(0.5*m*omegaSq*(x*x + y*y + z*z) + g*norm(oldPsi))*oldPsi;
00361 }
00362
00363 b(1) = b(1) + 2.0*a(1);
00364 c(1) = c(1) - a(1);
00365 a(xExtent-1) = a(xExtent-1) - c(xExtent-1);
00366 b(xExtent-1) = b(xExtent-1) + 2.0*c(xExtent-1);
00367
00368 LA.solveTridiagonal(a,b,c,X,d);
00369 for(int j = 1; j < xExtent; j ++)
00370 currentField.assignElement(j,k,l,X(j));
00371 }
00372 }
00373
00374 for(int l = 1; l < zExtent; l ++)
00375 {
00376 for(int j = 1; j < xExtent; j ++)
00377 {
00378 for(int k = 1; k < yExtent; k ++)
00379 {
00380 a(k) = -alpha_y;
00381 b(k) = 1.0 + 2.0*alpha_y;
00382 c(k) = -alpha_y;
00383 d(k) = currentField.retrieveElement(j,k,l);
00384 }
00385
00386 b(1) = b(1) + 2.0*a(1);
00387 c(1) = c(1) - a(1);
00388 a(yExtent-1) = a(yExtent-1) - c(yExtent-1);
00389 b(yExtent-1) = b(yExtent-1) + 2.0*c(yExtent-1);
00390
00391 LA.solveTridiagonal(a,b,c,X,d);
00392 for(int k = 1; k < yExtent; k ++)
00393 currentField.assignElement(j,k,l,X(k));
00394 }
00395 }
00396
00397 for(int j = 1; j < xExtent; j ++)
00398 {
00399 for(int k = 1; k < yExtent; k ++)
00400 {
00401 for(int l = 1; l < zExtent; l ++)
00402 {
00403 a(l) = -alpha_z;
00404 b(l) = 1.0 + 2.0*alpha_z;
00405 c(l) = -alpha_z;
00406 d(l) = currentField.retrieveElement(j,k,l);
00407 }
00408
00409 b(1) = b(1) + 2.0*a(1);
00410 c(1) = c(1) - a(1);
00411 a(zExtent-1) = a(zExtent-1) - c(zExtent-1);
00412 b(zExtent-1) = b(zExtent-1) + 2.0*c(zExtent-1);
00413
00414 LA.solveTridiagonal(a,b,c,X,d);
00415 for(int l = 1; l < zExtent; l ++)
00416 currentField.assignElement(j,k,l,X(l));
00417 }
00418 }
00419
00420
00421 setBoundaryVanish(currentField);
00422 }
00423 }
00424
00425 void QCEvolve::setBoundaryGradZero(QCComplexField<2> &field, Array<complexType,2> &old)
00426 {
00427 int xExtent = field.noOfRows()-1, yExtent = field.noOfColumns()-1;
00428
00429
00430 for(int j = 1; j < xExtent; j ++)
00431 {
00432 field.assignElement(j,0,old(j,0));
00433 field.assignElement(j,yExtent,old(j,yExtent));
00434 }
00435 for(int k = 1; k < yExtent; k ++)
00436 {
00437 field.assignElement(0,k,old(0,k));
00438 field.assignElement(xExtent,k,old(xExtent,k));
00439 }
00440 field.assignElement(0,0,old(0,0));
00441 field.assignElement(0,yExtent,old(0,yExtent));
00442 field.assignElement(xExtent,0,old(xExtent,0));
00443 field.assignElement(xExtent,yExtent,old(xExtent,yExtent));
00444 }
00445
00446 void QCEvolve::setBoundaryFree(QCComplexField<2> &field)
00447 {
00448 int xExtent = field.noOfRows()-1, yExtent = field.noOfColumns()-1;
00449
00450 for(int k = 1; k < xExtent; k ++)
00451 {
00452 field.assignElement(k,0,2.0*field.retrieveElement(k,1) - field.retrieveElement(k,2));
00453 field.assignElement(k,yExtent,2.0*field.retrieveElement(k,yExtent-1) - field.retrieveElement(k,yExtent-2));
00454 }
00455 for(int l = 0; l <= yExtent; l ++)
00456 {
00457 field.assignElement(0,l,2.0*field.retrieveElement(1,l) - field.retrieveElement(2,l));
00458 field.assignElement(xExtent,l,2.0*field.retrieveElement(xExtent-1,l) - field.retrieveElement(xExtent-2,l));
00459 }
00460 field.assignElement(0,0,2.0*field.retrieveElement(1,1) - field.retrieveElement(2,2));
00461 field.assignElement(0,yExtent,2.0*field.retrieveElement(1,yExtent-1) - field.retrieveElement(2,yExtent-2));
00462 field.assignElement(xExtent,0,2.0*field.retrieveElement(xExtent-1,1) - field.retrieveElement(xExtent-2,2));
00463 field.assignElement(xExtent,yExtent,2.0*field.retrieveElement(xExtent-1,yExtent-1) - field.retrieveElement(xExtent-2,yExtent-2));
00464 }
00465
00466 void QCEvolve::setBoundaryVanish(QCComplexField<2> &field)
00467 {
00468 int xExtent = field.noOfRows()-1, yExtent = field.noOfColumns()-1;
00469
00470
00471 for(int j = 1; j < xExtent; j ++)
00472 {
00473 field.assignElement(j,0,0.0*exp(i*arg(field.retrieveElement(j,0))));
00474 field.assignElement(j,yExtent,0.0*exp(i*arg(field.retrieveElement(j,yExtent))));
00475 }
00476 for(int k = 0; k <= yExtent; k ++)
00477 {
00478 field.assignElement(0,k,0.0*exp(i*arg(field.retrieveElement(0,k))));
00479 field.assignElement(xExtent,k,0.0*exp(i*arg(field.retrieveElement(xExtent,k))));
00480 }
00481 }
00482
00483 void QCEvolve::setBoundaryVanish(QCComplexField<3> &field)
00484 {
00485 int xExtent = field.noOfRows()-1, yExtent = field.noOfColumns()-1, zExtent = field.height()-1;
00486
00487
00488 for(int l = 1; l < zExtent; l ++)
00489 {
00490 for(int j = 1; j < xExtent; j ++)
00491 {
00492 field.assignElement(j,0,l,complexZero);
00493 field.assignElement(j,yExtent,l,complexZero);
00494 }
00495 for(int k = 0; k <= yExtent; k ++)
00496 {
00497 field.assignElement(0,k,l,complexZero);
00498 field.assignElement(xExtent,k,l,complexZero);
00499 }
00500 }
00501 for(int j = 0; j <= xExtent; j ++)
00502 for(int k = 0; k <= yExtent; k ++)
00503 {
00504 field.assignElement(j,k,0,complexZero);
00505 field.assignElement(j,k,zExtent,complexZero);
00506 }
00507 }