/// <summary> /// Simulates on timestep of the time evolution by performing the splitstep fourier method only once. /// </summary> /// <param name="FT">Algorithm which will be used for the Fouriertransformation</param> public void splitStepFourier(string FT) { int size = this.psi.Length; // psi=psi.*exp(-0.5*1i*dt*(V+(g1d/hbar)*abs(psi).ˆ2)); for (int i = 0; i < size; i++) { psi[i] = psi[i] * ComplexNumber.Exp(-0.5 * ComplexNumber.ImaginaryOne * deltaT * (V[i] + g1D / PhysConst.hbar * Math.Pow(psi[i].Norm(), 2))); } // decides which algorithm will be used for the FT switch (FT) { case "DFT": psi = FFT.DFT(psi); break; case "CT": psi = FFT.CT(psi); break; case "BR": psi = FFT.BR(psi, reversedBits); break; default: break; } psi = FFT.Shift(psi); // shift the lower half with the upper one to restore normal order for (int i = 0; i < size; i++) { psi[i] = psi[i] / size; } // psi_k=psi_k*exp(-0.5*dt*1i*(hbar/m)*kˆ2) for (int i = 0; i < size; i++) { psi[i] = psi[i] * ComplexNumber.Exp(-0.5 * ComplexNumber.ImaginaryOne * deltaT * PhysConst.hbar / mass * Math.Pow(K[i], 2)); } psi = FFT.Shift(psi); // shifts again, so that the result of the IFT will be normal orderd // decides which algorithm will be used for the IFT switch (FT) { case "DFT": psi = FFT.IDFT(psi); break; case "CT": psi = FFT.ICT(psi); break; case "BR": psi = FFT.IBR(psi, reversedBits); break; default: break; } for (int i = 0; i < size; i++) { psi[i] = psi[i] * size; } //psi = psi.* exp(-0.5 * 1i * dt * (V + (g1d / hbar) * abs(psi).ˆ2)); for (int i = 0; i < size; i++) { psi[i] = psi[i] * ComplexNumber.Exp(-0.5 * ComplexNumber.ImaginaryOne * deltaT * (V[i] + g1D / PhysConst.hbar * Math.Pow(psi[i].Norm(), 2))); } }
/// <summary> /// <c>getGroundState</c> deteremines the Groundstate of a the wavefunction saved in <c>this.psi</c> /// with the imaginary time method /// </summary> public void getGroundState() { //ComplexNumber[] psi_0 = psi; double mu = 1; double mu_old; double mu_error = 1; ComplexNumber[] psi_old = new ComplexNumber[psi.Length]; double NormOfPsi = 0; for (int i = 0; i < psi.Length; i++) { NormOfPsi += Math.Pow(psi[i].Norm(), 2); } NormOfPsi = Math.Sqrt(NormOfPsi) * deltaX; int j = 0; while (mu_error > Math.Pow(10, -8)) { // creation of new wave function psi_old = (ComplexNumber[])psi.Clone(); for (int i = 0; i < psi.Length; i++) { psi[i] = psi[i] * Math.Exp(-0.5 * deltaT * (V[i] + g1D / PhysConst.hbar * Math.Pow(psi[i].Norm(), 2))); } //ComplexNumber[] psi_k = new ComplexNumber[psi.Length]; psi = FFT.BR(psi, reversedBits); // Fourier transformation of the wave function with the Cooley-Tukey algorithm psi = FFT.Shift(psi); // for (int i = 0; i < psi.Length; i++) { psi[i] = psi[i] / xSteps; } // psi = psi*exp((-0.5*deltaT*hbar*|k|^2)/m) for (int i = 0; i < psi.Length; i++) { psi[i] = psi[i] * Math.Exp(-0.5 * deltaT * (PhysConst.hbar / this.mass * Math.Pow(K[i], 2))); } psi = FFT.Shift(psi); psi = FFT.IBR(psi, reversedBits); //Inverse fourier transformation of the wave function with the bit reverse algorithm for (int i = 0; i < psi.Length; i++) { psi[i] = psi[i] * kSteps; } // psi = psi*exp(-0.5*deltaT*V(x)+g1D/hbar * |psi|^2) for (int i = 0; i < psi.Length; i++) { psi[i] = psi[i] * Math.Exp(-0.5 * deltaT * (V[i] + g1D / PhysConst.hbar * Math.Pow(psi[i].Norm(), 2))); } mu_old = mu; mu = Math.Log((psi_old[psi_old.Length / 2] / psi[psi.Length / 2]).Norm()) / deltaT; mu_error = Math.Abs(mu - mu_old) / mu; double currentNormOfPsi = 0; for (int i = 0; i < psi.Length; i++) { currentNormOfPsi += Math.Pow(psi[i].Norm(), 2); } currentNormOfPsi = Math.Sqrt(currentNormOfPsi) * deltaX; for (int i = 0; i < psi.Length; i++) { psi[i] = psi[i] * Math.Sqrt(NormOfPsi) / Math.Sqrt(currentNormOfPsi); } if (j > Math.Pow(10, 8)) { break; } j++; } }
/// <summary> /// Initializes a new instance of the <see cref="T:OurMaths.GPESolver"/> class /// with basic definitions and external input. /// </summary> /// <param name="atomMass">Atom mass.</param> /// <param name="numberOfAtoms">Number of atoms.</param> /// <param name="scatteringlength">Scatteringlength.</param> /// <param name="wx">Wx.</param> /// <param name="wr">Wr.</param> public GPESolver(double atomMass, int numberOfAtoms, double scatteringlength, double wx, double wr) { // Physical Defintion mass = atomMass; // mass of an atom aSc = scatteringlength; // Scattering Length N = numberOfAtoms; // Atom number wX = wx; // trap freq lX = Math.Sqrt(PhysConst.hbar / (mass * wX)); //ho length of trap wR = wr; // radial trap freq lR = Math.Sqrt(PhysConst.hbar / (mass * wR)); // ho length of trap g1D = 2 * Math.Pow(PhysConst.hbar, 2) * aSc / (mass * lR * lR); // 1D interaction coefficient /// Grid definitions xSteps = 512; // number of points im Ortsraum; power of two kSteps = xSteps; // number of points in momentum space deltaX = 2 * Math.Pow(10, -7); // distance between points im Ortsraum deltaK = 2 * Math.PI / ((xSteps - 1) * deltaX); //distance between points in momentum space deltaT = Math.Pow(10, -6); // time intervall timeSteps = 10000; // Anzahl der Zeitentwicklungsschritte // create Grids X = new double[xSteps]; for (int i = 0; i < xSteps; i++) { X[i] = (i - xSteps / 2 + 1) * deltaX; } V = new double[xSteps]; for (int i = 0; i < xSteps; i++) { V[i] = 0.5 * mass * wX * wX * X[i] * X[i] / PhysConst.hbar; } K = new double[xSteps]; for (int i = 0; i < xSteps; i++) { K[i] = (i - xSteps / 2 + 1) * deltaK; } // prepare for bitReversal reversedBits = new uint[xSteps]; int a = 0; int findA = xSteps; while (findA > 1) { findA = findA >> 1; a++; } for (uint i = 0; i < xSteps; i++) { reversedBits[i] = FFT.BitReverse(i, a); } // create Starting wave function psi = new ComplexNumber[xSteps]; for (int i = 0; i < xSteps; i++) { psi[i] = Math.Sqrt(N / lX) * Math.Pow(Math.PI, -0.25) * Math.Exp(-X[i] * X[i] / (2.2 * lX * lX)); } }