/// <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++; } }
/// <returns> /// The quotient of the current and another complex number. /// </returns> /// <param name="c">Complex number to be devided by.</param> public ComplexNumber Divide(ComplexNumber c) => new ComplexNumber((this.rr * c.rr + this.ii * c.ii) / (c.rr * c.rr + c.ii * c.ii), (this.ii * c.rr - this.rr * c.ii) / (c.rr * c.rr + c.ii * c.ii));
/// <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))); } }
/// <returns> /// The difference of the current and another complex number. /// </returns> /// <param name="c">Complex number to be substracted.</param> public ComplexNumber Substract(ComplexNumber c) => new ComplexNumber(this.rr - c.rr, this.ii - c.ii);
/// <returns> /// The product of the current and another complex number. /// </returns> /// <param name="c">Complex number to be multiplicated.</param> public ComplexNumber Multiply(ComplexNumber c) => new ComplexNumber(this.rr * c.rr - this.ii * c.ii, this.rr * c.ii + this.ii * c.rr);
/// <returns> /// The sum of the current and another complex number. /// </returns> /// <param name="c">Complex number to be added.</param> public ComplexNumber Add(ComplexNumber c) => new ComplexNumber(this.rr + c.rr, this.ii + c.ii);
/// <summary> /// Computes the exponantial of a complex number. /// </summary> /// <param name="c">Complex exponent.</param> /// <returns>e to the power of the complex parameter.</returns> public static ComplexNumber Exp(ComplexNumber c) => Math.Exp(c.rr) * (new ComplexNumber(Math.Cos(c.ii), Math.Sin(c.ii)));
/// <returns></returns> /// <param name="c">Complex number whose imaginary part is desired.</param> public static double imaginaryPart(ComplexNumber c) => c.imaginaryPart();
/// <returns></returns> /// <param name="c">Complex number whose real part is desired.</param> public static double realPart(ComplexNumber c) => c.realPart();
/// <summary> /// Transformation algorithm to perform a FFT using the Bit reversal structure. /// </summary> /// <remarks> /// The FT is performed by setting the <c>negativeTwidleFactor</c> to <c>true</c>, its inverse by setting it to <c>false</c>. /// </remarks> /// <returns>Transformed array</returns> /// <param name="negativeTwidleFactor">If set to <c>true</c> FT is performed, if <c>false</c> its inverse.</param> /// <param name="f">Array to be transformed</param> /// <param name="reversedBits">Reversed bit array, needs to be precalculated by <c>BitReverse</c></param> public static ComplexNumber[] Transform(bool negativeTwidleFactor, ComplexNumber[] f, uint[] reversedBits) { ComplexNumber[] workF = (ComplexNumber[])f.Clone(); int size = f.Length; if (size != reversedBits.Length) { throw new Exception("The arrays dont have the same lenght"); } int a = 0; int findA = size; while (findA > 1) { findA = findA >> 1; a++; } // sets the prefactor for the twiddle factor to perform either FFT or IFFT int preFactor; if (negativeTwidleFactor) { preFactor = -1; } else { preFactor = 1; } // prepare necassary variables ComplexNumber even, odd, wM, w; int shift, m; //orders the array according to the bit reversal for (int i = 0; i < f.Length; i++) { workF[i] = f[reversedBits[i]]; } // three for loops to process the full FFT/IFFT // the result of the loops gives the FFT/IFFT in the normal ordered form for (int s = 1; s <= a; s++) { shift = 1 << (s - 1); // = 2^(s-1) via bitshift m = 1 << s; // = 2^s wM = ComplexNumber.Exp(preFactor * ComplexNumber.ImaginaryOne * 2 * Math.PI / m); // twiddle factor, with prefactor for FFT/IFFT for (int i = 0; i < size; i += m) { w = 1; for (int j = 0; j < shift; j++) { // the call to the reverse bit structure accounts for the bitflipped order even = workF[i + j]; odd = w * workF[i + j + shift]; // joins together the desired even and odd parts, with the twidle factor multiplied to the odd part workF[i + j] = even + odd; workF[i + j + shift] = even - odd; // increase phase of twiddle factor w = w * wM; } } } return(workF); }