| [a0bcf1] | 1 | /** \file perturbed.c
 | 
|---|
 | 2 |  * Perturbation calculation due to external magnetic field.
 | 
|---|
 | 3 |  * 
 | 
|---|
 | 4 |  * Central function is MinimisePerturbed() wherein the actual minimisation of the two different operators with each
 | 
|---|
 | 5 |  * three components takes place subsequently. Helpful routines are CalculatePerturbationOperator_P() - which applies a
 | 
|---|
 | 6 |  * specified component of p on the current wave function - and CalculatePerturbationOperator_RxP() - which does the
 | 
|---|
 | 7 |  * same for the RxP operator. 
 | 
|---|
 | 8 |  * The actual minimisation loop FindPerturbedMinimum() depends on the same routines also used for the occupied orbitals,
 | 
|---|
 | 9 |  * however with a different energy functional and derivatives, evaluated in Calculate1stPerturbedDerivative() and 
 | 
|---|
 | 10 |  * Calculate2ndPerturbedDerivative(). InitPerturbedEnergyCalculation() calculates the total energy functional
 | 
|---|
 | 11 |  * perturbed in second order for all wave functions, UpdatePerturbedEnergyCalculation() just updates the one
 | 
|---|
 | 12 |  * for the wave function after it has been minimised during the line search. Both use CalculatePerturbedEnergy() which
 | 
|---|
 | 13 |  * evaluates the energy functional (and the gradient if specified).
 | 
|---|
 | 14 |  * Finally, FillCurrentDensity() evaluates the current density at a given point in space using the perturbed
 | 
|---|
 | 15 |  * wave functions. Afterwards by calling CalculateMagneticSusceptibility() or 
 | 
|---|
 | 16 |  * CalculateChemicalShieldingByReciprocalCurrentDensity() susceptibility respectively shielding tensor are possible uses
 | 
|---|
 | 17 |  * of this current density.
 | 
|---|
 | 18 |  * 
 | 
|---|
 | 19 |  * There are also some test routines: TestCurrent() checks whether the integrated current is zero in each component.
 | 
|---|
 | 20 |  * test_fft_symmetry() tests the "pulling out imaginary unit" before fourier transformation on a given wave function.
 | 
|---|
 | 21 |  * CheckOrbitalOverlap() outputs the overlap matrix for the wave functions of a given minimisation state, this might
 | 
|---|
 | 22 |  * be important for the additional \f$\Delta J{ij}\f$ contribution to the current density, which is non-zero for
 | 
|---|
 | 23 |  * non-zero mutual overlap, which is evaluated if FillDeltaCurrentDensity() is called.
 | 
|---|
 | 24 |  * 
 | 
|---|
 | 25 |  * Finally, there are also some smaller routines: truedist() gives the correct relative distance between two points
 | 
|---|
 | 26 |  * in the unit cell under periodic boundary conditions with minimum image convention. ApplyTotalHamiltonian() returns
 | 
|---|
 | 27 |  * the hamiltonian applied to a given wave function. sawtooth() is a sawtooth implementation which is needed in order
 | 
|---|
 | 28 |  * to avoid flipping of position eigenvalues for nodes close to or on the cell boundary. CalculateOverlap()
 | 
|---|
 | 29 |  * is used in the energy functional derivatives, keeping an overlap table between perturbed wave functions up to date.
 | 
|---|
 | 30 |  * fft_Psi() is very similar to CalculateOneDensityR(), it does the extension of the wave function to the upper level
 | 
|---|
 | 31 |  * RunStruct#Lev0 while fouriertransforming it to real space. cross() gives correct indices in evaluating a vector cross
 | 
|---|
 | 32 |  * product. AllocCurrentDensity() and DisAllocCurrentDensity() mark the current density arrays as currently being in use or not.
 | 
|---|
 | 33 |  * 
 | 
|---|
 | 34 |   Project: ParallelCarParrinello
 | 
|---|
 | 35 |  \author Frederik Heber
 | 
|---|
 | 36 |  \date 2006
 | 
|---|
 | 37 | 
 | 
|---|
 | 38 | */
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | #include <stdlib.h>
 | 
|---|
 | 41 | #include <stdio.h>
 | 
|---|
 | 42 | #include <math.h>
 | 
|---|
 | 43 | #include <string.h>
 | 
|---|
 | 44 | #include <time.h>
 | 
|---|
 | 45 | #include <gsl/gsl_matrix.h>
 | 
|---|
 | 46 | #include <gsl/gsl_eigen.h>
 | 
|---|
 | 47 | #include <gsl/gsl_complex.h>
 | 
|---|
 | 48 | #include <gsl/gsl_complex_math.h>
 | 
|---|
 | 49 | #include <gsl/gsl_sort_vector.h>
 | 
|---|
 | 50 | #include <gsl/gsl_linalg.h>
 | 
|---|
 | 51 | #include <gsl/gsl_multimin.h>
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 | #include "data.h"
 | 
|---|
 | 54 | #include "density.h"
 | 
|---|
 | 55 | #include "energy.h"
 | 
|---|
 | 56 | #include "excor.h"
 | 
|---|
 | 57 | #include "errors.h"
 | 
|---|
 | 58 | #include "grad.h"
 | 
|---|
 | 59 | #include "gramsch.h"
 | 
|---|
 | 60 | #include "mergesort2.h"
 | 
|---|
 | 61 | #include "helpers.h"
 | 
|---|
 | 62 | #include "init.h"
 | 
|---|
 | 63 | #include "myfft.h"
 | 
|---|
 | 64 | #include "mymath.h"
 | 
|---|
 | 65 | #include "output.h"
 | 
|---|
 | 66 | #include "pcp.h"
 | 
|---|
 | 67 | #include "perturbed.h"
 | 
|---|
 | 68 | #include "run.h"
 | 
|---|
 | 69 | #include "wannier.h"
 | 
|---|
 | 70 | 
 | 
|---|
 | 71 | /** evaluates perturbed energy functional.
 | 
|---|
 | 72 |  * \param norm norm of current Psi in functional
 | 
|---|
 | 73 |  * \param *params void-pointer to parameter array
 | 
|---|
 | 74 |  * \return evaluated functional at f(x) with \a norm
 | 
|---|
 | 75 |  */
 | 
|---|
 | 76 | double perturbed_function (double norm, void *params) {
 | 
|---|
 | 77 |   struct Problem *P = (struct Problem *)params;
 | 
|---|
 | 78 |   int i, n = P->R.LevS->MaxG;
 | 
|---|
 | 79 |   double old_norm  = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
 | 
|---|
 | 80 |   fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
 | 
|---|
 | 81 |   fprintf(stderr,"(%i) perturbed_function: setting norm to %lg ...", P->Par.me, norm);
 | 
|---|
 | 82 |   // set desired norm for current Psi
 | 
|---|
 | 83 |   for (i=0; i< n; i++) {
 | 
|---|
 | 84 |     currentPsi[i].re *= norm/old_norm; // real part
 | 
|---|
 | 85 |     currentPsi[i].im *= norm/old_norm; // imaginary part
 | 
|---|
 | 86 |   }
 | 
|---|
 | 87 |   P->R.PsiStep = 0; // make it not advance to next Psi
 | 
|---|
 | 88 |   
 | 
|---|
 | 89 |   //debug(P,"UpdateActualPsiNo");
 | 
|---|
 | 90 |   UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
 | 
|---|
 | 91 |   //debug(P,"UpdateEnergyArray");
 | 
|---|
 | 92 |   UpdateEnergyArray(P); // shift energy values in their array by one
 | 
|---|
 | 93 |   //debug(P,"UpdatePerturbedEnergyCalculation");
 | 
|---|
 | 94 |   UpdatePerturbedEnergyCalculation(P);  // re-calc energies (which is hopefully lower)
 | 
|---|
 | 95 |   EnergyAllReduce(P); // gather from all processes and sum up to total energy
 | 
|---|
 | 96 | /*
 | 
|---|
 | 97 |   for (i=0; i< n; i++) {
 | 
|---|
 | 98 |     currentPsi[i].re /= norm/old_norm; // real part
 | 
|---|
 | 99 |     currentPsi[i].im /= norm/old_norm; // imaginary part
 | 
|---|
 | 100 |   }*/
 | 
|---|
 | 101 |   
 | 
|---|
 | 102 |   fprintf(stderr,"%lg\n", P->Lat.E->TotalEnergy[0]);
 | 
|---|
 | 103 |   return P->Lat.E->TotalEnergy[0];   // and return evaluated functional
 | 
|---|
 | 104 | }
 | 
|---|
 | 105 | 
 | 
|---|
 | 106 | /** evaluates perturbed energy functional.
 | 
|---|
 | 107 |  * \param *x current position in functional
 | 
|---|
 | 108 |  * \param *params void-pointer to parameter array
 | 
|---|
 | 109 |  * \return evaluated functional at f(x)
 | 
|---|
 | 110 |  */
 | 
|---|
 | 111 | double perturbed_f (const gsl_vector *x, void *params) {
 | 
|---|
 | 112 |   struct Problem *P = (struct Problem *)params;
 | 
|---|
 | 113 |   int i, n = P->R.LevS->MaxG*2;
 | 
|---|
 | 114 |   fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
 | 
|---|
 | 115 |   //int diff = 0;
 | 
|---|
 | 116 |   //debug(P,"f");
 | 
|---|
 | 117 |   // put x into current Psi
 | 
|---|
 | 118 |   for (i=0; i< n; i+=2) {
 | 
|---|
 | 119 |     //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
 | 
|---|
 | 120 |     currentPsi[i/2].re = gsl_vector_get (x, i);   // real part
 | 
|---|
 | 121 |     currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
 | 
|---|
 | 122 |   }
 | 
|---|
 | 123 |   //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
 | 
|---|
 | 124 |   P->R.PsiStep = 0; // make it not advance to next Psi
 | 
|---|
 | 125 |   
 | 
|---|
 | 126 |   //debug(P,"UpdateActualPsiNo");
 | 
|---|
 | 127 |   UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
 | 
|---|
 | 128 |   //debug(P,"UpdateEnergyArray");
 | 
|---|
 | 129 |   UpdateEnergyArray(P); // shift energy values in their array by one
 | 
|---|
 | 130 |   //debug(P,"UpdatePerturbedEnergyCalculation");
 | 
|---|
 | 131 |   UpdatePerturbedEnergyCalculation(P);  // re-calc energies (which is hopefully lower)
 | 
|---|
 | 132 |   EnergyAllReduce(P); // gather from all processes and sum up to total energy
 | 
|---|
 | 133 |   
 | 
|---|
 | 134 |   return P->Lat.E->TotalEnergy[0];   // and return evaluated functional
 | 
|---|
 | 135 | }
 | 
|---|
 | 136 | 
 | 
|---|
 | 137 | /** evaluates perturbed energy gradient.
 | 
|---|
 | 138 |  * \param *x current position in functional
 | 
|---|
 | 139 |  * \param *params void-pointer to parameter array
 | 
|---|
 | 140 |  * \param *g array for gradient vector on return
 | 
|---|
 | 141 |  */
 | 
|---|
 | 142 | void perturbed_df (const gsl_vector *x, void *params, gsl_vector *g) {
 | 
|---|
 | 143 |   struct Problem *P = (struct Problem *)params;
 | 
|---|
 | 144 |   int i, n = P->R.LevS->MaxG*2;
 | 
|---|
 | 145 |   fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
 | 
|---|
 | 146 |   fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];
 | 
|---|
 | 147 |   //int diff = 0;
 | 
|---|
 | 148 |   //debug(P,"df");
 | 
|---|
 | 149 |   // put x into current Psi
 | 
|---|
 | 150 |   for (i=0; i< n; i+=2) {
 | 
|---|
 | 151 |     //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
 | 
|---|
 | 152 |     currentPsi[i/2].re = gsl_vector_get (x, i);   // real part
 | 
|---|
 | 153 |     currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
 | 
|---|
 | 154 |   }
 | 
|---|
 | 155 |   //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
 | 
|---|
 | 156 |   P->R.PsiStep = 0; // make it not advance to next Psi
 | 
|---|
 | 157 |   
 | 
|---|
 | 158 |   //debug(P,"UpdateActualPsiNo");
 | 
|---|
 | 159 |   UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
 | 
|---|
 | 160 |   //debug(P,"UpdateEnergyArray");
 | 
|---|
 | 161 |   UpdateEnergyArray(P); // shift energy values in their array by one
 | 
|---|
 | 162 |   //debug(P,"UpdatePerturbedEnergyCalculation");
 | 
|---|
 | 163 |   UpdatePerturbedEnergyCalculation(P);  // re-calc energies (which is hopefully lower)
 | 
|---|
 | 164 |   EnergyAllReduce(P); // gather from all processes and sum up to total energy
 | 
|---|
 | 165 |   
 | 
|---|
 | 166 |   // checkout gradient
 | 
|---|
 | 167 |   //diff = 0;
 | 
|---|
 | 168 |   for (i=0; i< n; i+=2) {
 | 
|---|
 | 169 |     //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1)))  diff++;
 | 
|---|
 | 170 |     gsl_vector_set (g, i, -gradient[i/2].re);   // real part
 | 
|---|
 | 171 |     gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part
 | 
|---|
 | 172 |   }
 | 
|---|
 | 173 |   //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);
 | 
|---|
 | 174 | }
 | 
|---|
 | 175 | 
 | 
|---|
 | 176 | /** evaluates perturbed energy functional and gradient.
 | 
|---|
 | 177 |  * \param *x current position in functional
 | 
|---|
 | 178 |  * \param *params void-pointer to parameter array
 | 
|---|
 | 179 |  * \param *f pointer to energy function value on return
 | 
|---|
 | 180 |  * \param *g array for gradient vector on return
 | 
|---|
 | 181 |  */
 | 
|---|
 | 182 | void perturbed_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *g) {
 | 
|---|
 | 183 |   struct Problem *P = (struct Problem *)params;
 | 
|---|
 | 184 |   int i, n = P->R.LevS->MaxG*2;
 | 
|---|
 | 185 |   fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
 | 
|---|
 | 186 |   fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];
 | 
|---|
 | 187 |   //int diff = 0;
 | 
|---|
 | 188 |   //debug(P,"fdf");
 | 
|---|
 | 189 |   // put x into current Psi
 | 
|---|
 | 190 |   for (i=0; i< n; i+=2) {
 | 
|---|
 | 191 |     //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
 | 
|---|
 | 192 |     currentPsi[i/2].re = gsl_vector_get (x, i);   // real part
 | 
|---|
 | 193 |     currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
 | 
|---|
 | 194 |   }
 | 
|---|
 | 195 |   //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
 | 
|---|
 | 196 |   P->R.PsiStep = 0; // make it not advance to next Psi
 | 
|---|
 | 197 |   
 | 
|---|
 | 198 |   //debug(P,"UpdateActualPsiNo");
 | 
|---|
 | 199 |   UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
 | 
|---|
 | 200 |   //debug(P,"UpdateEnergyArray");
 | 
|---|
 | 201 |   UpdateEnergyArray(P); // shift energy values in their array by one
 | 
|---|
 | 202 |   //debug(P,"UpdatePerturbedEnergyCalculation");
 | 
|---|
 | 203 |   UpdatePerturbedEnergyCalculation(P);  // re-calc energies (which is hopefully lower)
 | 
|---|
 | 204 |   EnergyAllReduce(P); // gather from all processes and sum up to total energy
 | 
|---|
 | 205 |   
 | 
|---|
 | 206 |   // checkout gradient
 | 
|---|
 | 207 |   //diff = 0;
 | 
|---|
 | 208 |   for (i=0; i< n; i+=2) {
 | 
|---|
 | 209 |     //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1)))  diff++;
 | 
|---|
 | 210 |     gsl_vector_set (g, i, -gradient[i/2].re);   // real part
 | 
|---|
 | 211 |     gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part
 | 
|---|
 | 212 |   }
 | 
|---|
 | 213 |   //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);
 | 
|---|
 | 214 |   
 | 
|---|
 | 215 |   *f = P->Lat.E->TotalEnergy[0];   // and return evaluated functional
 | 
|---|
 | 216 | }
 | 
|---|
 | 217 | 
 | 
|---|
 | 218 | /** Minimisation of the PsiTypeTag#Perturbed_RxP0, PsiTypeTag#Perturbed_P0 and other orbitals.
 | 
|---|
 | 219 |  * For each of the above PsiTypeTag we go through the following before the minimisation loop:
 | 
|---|
 | 220 |  * -# ResetGramSchTagType() resets current type that is to be minimised to NotOrthogonal.
 | 
|---|
 | 221 |  * -# UpdateActualPsiNo() steps on to next perturbed of current PsiTypeTag type.
 | 
|---|
 | 222 |  * -# GramSch() orthonormalizes perturbed wave functions.
 | 
|---|
 | 223 |  * -# TestGramSch() tests if orthonormality was achieved.
 | 
|---|
 | 224 |  * -# InitDensityCalculation() gathers densities from all wave functions (and all processes), within SpeedMeasure() DensityTime.
 | 
|---|
 | 225 |  * -# InitPerturbedEnergyCalculation() performs initial calculation of the perturbed energy functional.
 | 
|---|
 | 226 |  * -# RunStruct#OldActualLocalPsiNo is set to RunStruct#ActualLocalPsiNo, immediately followed by UpdateGramSchOldActualPsiNo()
 | 
|---|
 | 227 |  *    to bring info on all processes on par.
 | 
|---|
 | 228 |  * -# UpdatePerturbedEnergyCalculation() re-calculates Gradient and GradientTypes#H1cGradient for RunStruct#ActualLocalPsiNo
 | 
|---|
 | 229 |  * -# EnergyAllReduce() gathers various energy terms and sums up into Energy#TotalEnergy.
 | 
|---|
 | 230 |  * 
 | 
|---|
 | 231 |  * And during the minimisation loop:
 | 
|---|
 | 232 |  * -# FindPerturbedMinimum() performs the gradient conjugation, the line search and wave function update.
 | 
|---|
 | 233 |  * -# UpdateActualPsiNo() steps on to the next wave function, orthonormalizing by GramSch() if necessary.
 | 
|---|
 | 234 |  * -# UpdateEnergyArray() shifts TotalEnergy values to make space for new one.
 | 
|---|
 | 235 |  * -# There is no density update as the energy function does not depend on the changing perturbed density but only on the fixed
 | 
|---|
 | 236 |  *    unperturbed one.
 | 
|---|
 | 237 |  * -# UpdatePerturbedEnergyCalculation() re-calculates the perturbed energy of the changed wave function.
 | 
|---|
 | 238 |  * -# EnergyAllReduce() gathers energy terms and sums up.
 | 
|---|
 | 239 |  * -# CheckCPULIM() checks if external Stop signal has been given.
 | 
|---|
 | 240 |  * -# CalculateMinimumStop() checks whether we have dropped below a certain minimum change during minimisation of total energy.
 | 
|---|
 | 241 |  * -# finally step counters LatticeLevel#Step and SpeedStruct#Steps are increased.
 | 
|---|
 | 242 |  * 
 | 
|---|
 | 243 |  * After the minimisation loop:
 | 
|---|
 | 244 |  * -# SetGramSchExtraPsi() removes extra Psis from orthogonaliy check.
 | 
|---|
 | 245 |  * -# ResetGramSchTagType() sets GramSchToDoType to NotUsedtoOrtho.
 | 
|---|
 | 246 |  * 
 | 
|---|
 | 247 |  * And after all minimisation runs are done:
 | 
|---|
 | 248 |  * -# UpdateActualPsiNo() steps back to PsiTypeTag#Occupied type.
 | 
|---|
 | 249 |  * 
 | 
|---|
 | 250 |  * At the end we return to Occupied wave functions.
 | 
|---|
 | 251 |  * \param *P at hand
 | 
|---|
 | 252 |  * \param *Stop flag to determine if epsilon stop conditions have met
 | 
|---|
 | 253 |  * \param *SuperStop flag to determinte whether external signal's required end of calculations
 | 
|---|
 | 254 |  */
 | 
|---|
 | 255 | void MinimisePerturbed (struct Problem *P, int *Stop, int *SuperStop) {
 | 
|---|
 | 256 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 257 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 258 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 259 |   int type;
 | 
|---|
 | 260 |   //int i;
 | 
|---|
 | 261 |   
 | 
|---|
 | 262 |   // stuff for GSL minimization
 | 
|---|
 | 263 |   //size_t iter;
 | 
|---|
 | 264 |   //int status, Status
 | 
|---|
 | 265 |   int n = R->LevS->MaxG*2;
 | 
|---|
 | 266 |   const gsl_multimin_fdfminimizer_type *T_multi;
 | 
|---|
 | 267 |   const gsl_min_fminimizer_type *T;
 | 
|---|
 | 268 |   gsl_multimin_fdfminimizer *s_multi;
 | 
|---|
 | 269 |   gsl_min_fminimizer *s;
 | 
|---|
 | 270 |   gsl_vector *x;//, *ss;
 | 
|---|
 | 271 |   gsl_multimin_function_fdf my_func;
 | 
|---|
 | 272 |   gsl_function F;
 | 
|---|
 | 273 |   //fftw_complex *currentPsi;
 | 
|---|
 | 274 |   //double a,b,m, f_m, f_a, f_b;
 | 
|---|
 | 275 |   //double old_norm;
 | 
|---|
 | 276 |   
 | 
|---|
 | 277 |   my_func.f = &perturbed_f;
 | 
|---|
 | 278 |   my_func.df = &perturbed_df;
 | 
|---|
 | 279 |   my_func.fdf = &perturbed_fdf;
 | 
|---|
 | 280 |   my_func.n = n;
 | 
|---|
 | 281 |   my_func.params = P;
 | 
|---|
 | 282 |   F.function = &perturbed_function;
 | 
|---|
 | 283 |   F.params = P;
 | 
|---|
 | 284 |      
 | 
|---|
 | 285 |   x = gsl_vector_alloc (n);
 | 
|---|
 | 286 |   //ss = gsl_vector_alloc (Psi->NoOfPsis);
 | 
|---|
 | 287 |   T_multi = gsl_multimin_fdfminimizer_vector_bfgs;
 | 
|---|
 | 288 |   s_multi = gsl_multimin_fdfminimizer_alloc (T_multi, n);
 | 
|---|
 | 289 |   T = gsl_min_fminimizer_brent;
 | 
|---|
 | 290 |   s = gsl_min_fminimizer_alloc (T);
 | 
|---|
 | 291 |   
 | 
|---|
 | 292 |   for (type=Perturbed_P0;type<=Perturbed_RxP2;type++) {  // go through each perturbation group separately //
 | 
|---|
 | 293 |     *Stop=0;   // reset stop flag
 | 
|---|
 | 294 |     fprintf(stderr,"(%i)Beginning perturbed minimisation of type %s ...\n", P->Par.me, R->MinimisationName[type]);
 | 
|---|
 | 295 |     //OutputOrbitalPositions(P, Occupied);
 | 
|---|
 | 296 |     R->PsiStep = R->MaxPsiStep; // reset in-Psi-minimisation-counter, so that we really advance to the next wave function
 | 
|---|
 | 297 |     UpdateActualPsiNo(P, type); // step on to next perturbed one
 | 
|---|
 | 298 |     fprintf(stderr, "(%i) Re-initializing perturbed psi array for type %s ", P->Par.me, R->MinimisationName[type]);
 | 
|---|
 | 299 |     if (P->Call.ReadSrcFiles && ReadSrcPsiDensity(P,type,1, R->LevSNo)) {
 | 
|---|
 | 300 |       SpeedMeasure(P, InitSimTime, StartTimeDo);  
 | 
|---|
 | 301 |       fprintf(stderr,"from source file of recent calculation\n");
 | 
|---|
 | 302 |       ReadSrcPsiDensity(P,type, 0, R->LevSNo);
 | 
|---|
 | 303 |       ResetGramSchTagType(P, Psi, type, IsOrthogonal); // loaded values are orthonormal
 | 
|---|
 | 304 |       SpeedMeasure(P, DensityTime, StartTimeDo);
 | 
|---|
 | 305 |       //InitDensityCalculation(P);
 | 
|---|
 | 306 |       SpeedMeasure(P, DensityTime, StopTimeDo);
 | 
|---|
 | 307 |       R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
 | 
|---|
 | 308 |       UpdateGramSchOldActualPsiNo(P,Psi);
 | 
|---|
 | 309 |       InitPerturbedEnergyCalculation(P, 1);  // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
 | 
|---|
 | 310 |       UpdatePerturbedEnergyCalculation(P);  // H1cGradient and Gradient must be current ones
 | 
|---|
 | 311 |       EnergyAllReduce(P);   // gather energies for minimum search
 | 
|---|
 | 312 |       SpeedMeasure(P, InitSimTime, StopTimeDo);  
 | 
|---|
 | 313 |     }
 | 
|---|
 | 314 |     if (P->Call.ReadSrcFiles != 1) {
 | 
|---|
 | 315 |       SpeedMeasure(P, InitSimTime, StartTimeDo);  
 | 
|---|
 | 316 |       ResetGramSchTagType(P, Psi, type, NotOrthogonal); // perturbed now shall be orthonormalized
 | 
|---|
 | 317 |       if (P->Call.ReadSrcFiles != 2) {
 | 
|---|
 | 318 |         if (R->LevSNo == Lat->MaxLevel-1) { // is it the starting level? (see InitRunLevel())
 | 
|---|
 | 319 |           fprintf(stderr, "randomly.\n");
 | 
|---|
 | 320 |           InitPsisValue(P, Psi->TypeStartIndex[type], Psi->TypeStartIndex[type+1]);  // initialize perturbed array for this run
 | 
|---|
 | 321 |         } else {
 | 
|---|
 | 322 |           fprintf(stderr, "from source file of last level.\n");
 | 
|---|
 | 323 |           ReadSrcPerturbedPsis(P, type);
 | 
|---|
 | 324 |         }
 | 
|---|
 | 325 |       }
 | 
|---|
 | 326 |       SpeedMeasure(P, InitGramSchTime, StartTimeDo);  
 | 
|---|
 | 327 |       GramSch(P, R->LevS, Psi, Orthogonalize);
 | 
|---|
 | 328 |       SpeedMeasure(P, InitGramSchTime, StopTimeDo);  
 | 
|---|
 | 329 |       SpeedMeasure(P, InitDensityTime, StartTimeDo);
 | 
|---|
 | 330 |       //InitDensityCalculation(P);
 | 
|---|
 | 331 |       SpeedMeasure(P, InitDensityTime, StopTimeDo);
 | 
|---|
 | 332 |       InitPerturbedEnergyCalculation(P, 1);  // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
 | 
|---|
 | 333 |       R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
 | 
|---|
 | 334 |       UpdateGramSchOldActualPsiNo(P,Psi);
 | 
|---|
 | 335 |       UpdatePerturbedEnergyCalculation(P);  // H1cGradient and Gradient must be current ones
 | 
|---|
 | 336 |       EnergyAllReduce(P);   // gather energies for minimum search
 | 
|---|
 | 337 |       SpeedMeasure(P, InitSimTime, StopTimeDo);  
 | 
|---|
 | 338 |       R->LevS->Step++;
 | 
|---|
 | 339 |       EnergyOutput(P,0);
 | 
|---|
 | 340 |       while (*Stop != 1) {
 | 
|---|
 | 341 | /*        // copy current Psi into starting vector
 | 
|---|
 | 342 |         currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
 | 
|---|
 | 343 |         for (i=0; i< n; i+=2) {
 | 
|---|
 | 344 |           gsl_vector_set (x, i, currentPsi[i/2].re);   // real part
 | 
|---|
 | 345 |           gsl_vector_set (x, i+1, currentPsi[i/2].im); // imaginary part
 | 
|---|
 | 346 |         }
 | 
|---|
 | 347 |         gsl_multimin_fdfminimizer_set (s_multi, &my_func, x, 0.01, 1e-2);  
 | 
|---|
 | 348 |         iter = 0;
 | 
|---|
 | 349 |         status = 0;
 | 
|---|
 | 350 |         do {  // look for minimum along current local psi
 | 
|---|
 | 351 |           iter++;
 | 
|---|
 | 352 |           status = gsl_multimin_fdfminimizer_iterate (s_multi);
 | 
|---|
 | 353 |           MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);
 | 
|---|
 | 354 |           if (Status)
 | 
|---|
 | 355 |             break;
 | 
|---|
 | 356 |           status = gsl_multimin_test_gradient (s_multi->gradient, 1e-2);
 | 
|---|
 | 357 |           MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);
 | 
|---|
 | 358 |           //if (Status == GSL_SUCCESS)
 | 
|---|
 | 359 |             //printf ("Minimum found at:\n");
 | 
|---|
 | 360 |           if (P->Par.me == 0) fprintf (stderr,"(%i,%i,%i)S(%i,%i,%i):\t %5d %10.5f\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, (int)iter, s_multi->f);
 | 
|---|
 | 361 |           //TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?
 | 
|---|
 | 362 |         } while (Status == GSL_CONTINUE && iter < 3);
 | 
|---|
 | 363 | /*        // now minimize norm of currentPsi (one-dim)
 | 
|---|
 | 364 |         if (0) { 
 | 
|---|
 | 365 |           iter = 0;
 | 
|---|
 | 366 |         status = 0;
 | 
|---|
 | 367 |         m = 1.;
 | 
|---|
 | 368 |         a = MYEPSILON;
 | 
|---|
 | 369 |         b = 100.;
 | 
|---|
 | 370 |         f_a = perturbed_function (a, P);
 | 
|---|
 | 371 |         f_b = perturbed_function (b, P);
 | 
|---|
 | 372 |         f_m = perturbed_function (m, P);
 | 
|---|
 | 373 |         //if ((f_m < f_a) && (f_m < f_b)) {
 | 
|---|
 | 374 |           gsl_min_fminimizer_set (s, &F, m, a, b);
 | 
|---|
 | 375 |           do {  // look for minimum along current local psi
 | 
|---|
 | 376 |             iter++;
 | 
|---|
 | 377 |             status = gsl_min_fminimizer_iterate (s);
 | 
|---|
 | 378 |             m = gsl_min_fminimizer_x_minimum (s);
 | 
|---|
 | 379 |             a = gsl_min_fminimizer_x_lower (s);
 | 
|---|
 | 380 |             b = gsl_min_fminimizer_x_upper (s);         
 | 
|---|
 | 381 |             status = gsl_min_test_interval (a, b, 0.001, 0.0);
 | 
|---|
 | 382 |             if (status == GSL_SUCCESS)
 | 
|---|
 | 383 |               printf ("Minimum found at:\n");
 | 
|---|
 | 384 |             printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
 | 
|---|
 | 385 |                (int) iter, a, b,
 | 
|---|
 | 386 |                m, b - a);
 | 
|---|
 | 387 |           } while (status == GSL_CONTINUE && iter < 100);
 | 
|---|
 | 388 |           old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
 | 
|---|
 | 389 |           for (i=0; i< n; i++) {
 | 
|---|
 | 390 |             currentPsi[i].re *= m/old_norm; // real part
 | 
|---|
 | 391 |             currentPsi[i].im *= m/old_norm; // imaginary part
 | 
|---|
 | 392 |           }
 | 
|---|
 | 393 |         } else debug(P,"Norm not minimizable!");*/
 | 
|---|
 | 394 |         //P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi
 | 
|---|
 | 395 |         FindPerturbedMinimum(P);        
 | 
|---|
 | 396 |         //debug(P,"UpdateActualPsiNo");
 | 
|---|
 | 397 |         UpdateActualPsiNo(P, type); // step on to next perturbed Psi
 | 
|---|
 | 398 |         //debug(P,"UpdateEnergyArray");
 | 
|---|
 | 399 |         UpdateEnergyArray(P); // shift energy values in their array by one
 | 
|---|
 | 400 |         //debug(P,"UpdatePerturbedEnergyCalculation");
 | 
|---|
 | 401 |         UpdatePerturbedEnergyCalculation(P);  // re-calc energies (which is hopefully lower)
 | 
|---|
 | 402 |         EnergyAllReduce(P); // gather from all processes and sum up to total energy
 | 
|---|
 | 403 |         //ControlNativeDensity(P);  // check total density (summed up PertMixed must be zero!)
 | 
|---|
 | 404 |         //printf ("(%i,%i,%i)S(%i,%i,%i):\t %5d %10.5f\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, (int)iter, s_multi->f);
 | 
|---|
 | 405 |         if (*SuperStop != 1)
 | 
|---|
 | 406 |           *SuperStop = CheckCPULIM(P);
 | 
|---|
 | 407 |         *Stop = CalculateMinimumStop(P, *SuperStop);
 | 
|---|
 | 408 |         P->Speed.Steps++; // step on
 | 
|---|
 | 409 |         R->LevS->Step++; 
 | 
|---|
 | 410 |       }
 | 
|---|
 | 411 |       // now release normalization condition and minimize wrt to norm
 | 
|---|
 | 412 |  /*     *Stop = 0;
 | 
|---|
 | 413 |       while (*Stop != 1) {
 | 
|---|
 | 414 |         currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
 | 
|---|
 | 415 |         iter = 0;
 | 
|---|
 | 416 |         status = 0;
 | 
|---|
 | 417 |         m = 1.;
 | 
|---|
 | 418 |         a = 0.001;
 | 
|---|
 | 419 |         b = 10.;
 | 
|---|
 | 420 |         f_a = perturbed_function (a, P);
 | 
|---|
 | 421 |         f_b = perturbed_function (b, P);
 | 
|---|
 | 422 |         f_m = perturbed_function (m, P);
 | 
|---|
 | 423 |         if ((f_m < f_a) && (f_m < f_b)) {
 | 
|---|
 | 424 |           gsl_min_fminimizer_set (s, &F, m, a, b);
 | 
|---|
 | 425 |           do {  // look for minimum along current local psi
 | 
|---|
 | 426 |             iter++;
 | 
|---|
 | 427 |             status = gsl_min_fminimizer_iterate (s);
 | 
|---|
 | 428 |             m = gsl_min_fminimizer_x_minimum (s);
 | 
|---|
 | 429 |             a = gsl_min_fminimizer_x_lower (s);
 | 
|---|
 | 430 |             b = gsl_min_fminimizer_x_upper (s);         
 | 
|---|
 | 431 |             status = gsl_min_test_interval (a, b, 0.001, 0.0);
 | 
|---|
 | 432 |             if (status == GSL_SUCCESS)
 | 
|---|
 | 433 |               printf ("Minimum found at:\n");
 | 
|---|
 | 434 |             printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
 | 
|---|
 | 435 |                (int) iter, a, b,
 | 
|---|
 | 436 |                m, b - a);
 | 
|---|
 | 437 |           } while (status == GSL_CONTINUE && iter < 100);
 | 
|---|
 | 438 |           old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
 | 
|---|
 | 439 |           for (i=0; i< n; i++) {
 | 
|---|
 | 440 |             currentPsi[i].re *= m/old_norm; // real part
 | 
|---|
 | 441 |             currentPsi[i].im *= m/old_norm; // imaginary part
 | 
|---|
 | 442 |           }
 | 
|---|
 | 443 |         }
 | 
|---|
 | 444 |         P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi
 | 
|---|
 | 445 |         //debug(P,"UpdateActualPsiNo");
 | 
|---|
 | 446 |         UpdateActualPsiNo(P, type); // step on to next perturbed Psi
 | 
|---|
 | 447 |         if (*SuperStop != 1)
 | 
|---|
 | 448 |           *SuperStop = CheckCPULIM(P);
 | 
|---|
 | 449 |         *Stop = CalculateMinimumStop(P, *SuperStop);
 | 
|---|
 | 450 |         P->Speed.Steps++; // step on
 | 
|---|
 | 451 |         R->LevS->Step++; 
 | 
|---|
 | 452 |       }*/
 | 
|---|
 | 453 |       if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Write %s srcpsi to disk\n", P->Par.me, R->MinimisationName[type]);
 | 
|---|
 | 454 |       OutputSrcPsiDensity(P, type);
 | 
|---|
 | 455 | //      if (!TestReadnWriteSrcDensity(P,type))
 | 
|---|
 | 456 | //        Error(SomeError,"TestReadnWriteSrcDensity failed!");
 | 
|---|
 | 457 |     }
 | 
|---|
 | 458 | 
 | 
|---|
 | 459 |     TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?
 | 
|---|
 | 460 |     // calculate current density summands
 | 
|---|
 | 461 |     //if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Filling current density grid ...\n",P->Par.me);
 | 
|---|
 | 462 |     SpeedMeasure(P, CurrDensTime, StartTimeDo);
 | 
|---|
 | 463 |     if (*SuperStop != 1) {
 | 
|---|
 | 464 |       if ((R->DoFullCurrent == 1) || ((R->DoFullCurrent == 2) && (CheckOrbitalOverlap(P) == 1))) { //test to check whether orbitals have mutual overlap and thus \\DeltaJ_{xc} must not be dropped
 | 
|---|
 | 465 |         R->DoFullCurrent = 1; // set to 1 if it was 2 but Check...() yielded necessity
 | 
|---|
 | 466 |         //debug(P,"Filling with Delta j ...");
 | 
|---|
 | 467 |         //FillDeltaCurrentDensity(P);
 | 
|---|
 | 468 |       }// else
 | 
|---|
 | 469 |         //debug(P,"There is no overlap between orbitals.");
 | 
|---|
 | 470 |       //debug(P,"Filling with j ...");
 | 
|---|
 | 471 |       FillCurrentDensity(P);
 | 
|---|
 | 472 |     }
 | 
|---|
 | 473 |     SpeedMeasure(P, CurrDensTime, StopTimeDo);
 | 
|---|
 | 474 |     
 | 
|---|
 | 475 |     SetGramSchExtraPsi(P,Psi,NotUsedToOrtho); // remove extra Psis from orthogonality check
 | 
|---|
 | 476 |     ResetGramSchTagType(P, Psi, type, NotUsedToOrtho);  // remove this group from the check for the next minimisation group as well!
 | 
|---|
 | 477 |   }
 | 
|---|
 | 478 |   UpdateActualPsiNo(P, Occupied); // step on back to an occupied one
 | 
|---|
 | 479 |   
 | 
|---|
 | 480 |   gsl_multimin_fdfminimizer_free (s_multi);
 | 
|---|
 | 481 |   gsl_min_fminimizer_free (s);
 | 
|---|
 | 482 |   gsl_vector_free (x);
 | 
|---|
 | 483 |   //gsl_vector_free (ss);
 | 
|---|
 | 484 | }
 | 
|---|
 | 485 | 
 | 
|---|
 | 486 | /** Tests overlap matrix between each pair of orbitals for non-diagonal form.
 | 
|---|
 | 487 |  * We simply check whether the overlap matrix Psis#lambda has off-diagonal entries greater MYEPSILON or not.
 | 
|---|
 | 488 |  * \param *P Problem at hand
 | 
|---|
 | 489 |  * \note The routine is meant as atest criteria if \f$\Delta J_[ij]\f$ contribution is necessary, as it is only non-zero if
 | 
|---|
 | 490 |  *       there is mutual overlap between the two orbitals.
 | 
|---|
 | 491 |  */
 | 
|---|
 | 492 | int CheckOrbitalOverlap(struct Problem *P)
 | 
|---|
 | 493 | {
 | 
|---|
 | 494 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 495 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 496 |   int i,j;
 | 
|---|
 | 497 |   int counter = 0;
 | 
|---|
 | 498 | 
 | 
|---|
 | 499 |   // output matrix
 | 
|---|
 | 500 |   if (P->Par.me == 0) fprintf(stderr, "(%i) S_ij =\n", P->Par.me);
 | 
|---|
 | 501 |   for (i=0;i<Psi->NoOfPsis;i++) {
 | 
|---|
 | 502 |     for (j=0;j<Psi->NoOfPsis;j++) {
 | 
|---|
 | 503 |       if (fabs(Psi->lambda[i][j]) > MYEPSILON) counter++;
 | 
|---|
 | 504 |       if (P->Par.me == 0) fprintf(stderr, "%e\t", Psi->lambda[i][j]); //Overlap[i][j]
 | 
|---|
 | 505 |     }
 | 
|---|
 | 506 |     if (P->Par.me == 0) fprintf(stderr, "\n");
 | 
|---|
 | 507 |   }
 | 
|---|
 | 508 | 
 | 
|---|
 | 509 |   fprintf(stderr, "(%i) CheckOverlap: %i overlaps found.\t", P->Par.me, counter);
 | 
|---|
 | 510 |   if (counter > 0) return (1);
 | 
|---|
 | 511 |   else return(0);
 | 
|---|
 | 512 | }
 | 
|---|
 | 513 | 
 | 
|---|
 | 514 | /** Initialization of perturbed energy.
 | 
|---|
 | 515 |  * For each local wave function of the current minimisation type RunStruct#CurrentMin it is called:
 | 
|---|
 | 516 |  * - CalculateNonLocalEnergyNoRT(): for the coefficient-dependent form factors
 | 
|---|
 | 517 |  * - CalculatePerturbedEnergy(): for the perturbed energy, yet without gradient calculation
 | 
|---|
 | 518 |  * - CalculateOverlap(): for the overlap between the perturbed wave functions of the current RunStruct#CurrentMin state.
 | 
|---|
 | 519 |  * 
 | 
|---|
 | 520 |  * Afterwards for the two types AllPsiEnergyTypes#Perturbed1_0Energy and AllPsiEnergyTypes#Perturbed0_1Energy the
 | 
|---|
 | 521 |  * energy contribution from each wave function is added up in Energy#AllLocalPsiEnergy.
 | 
|---|
 | 522 |  * \param *P Problem at hand
 | 
|---|
 | 523 |  * \param first state whether it is the first (1) or successive call (0), which avoids some initial calculations. 
 | 
|---|
 | 524 |  * \sa UpdatePerturbedEnergy()
 | 
|---|
 | 525 |  * \note Afterwards EnergyAllReduce() must be called.
 | 
|---|
 | 526 |  */
 | 
|---|
 | 527 | void InitPerturbedEnergyCalculation(struct Problem *P, const int first)
 | 
|---|
 | 528 | {
 | 
|---|
 | 529 |   struct Lattice *Lat = &(P->Lat);
 | 
|---|
 | 530 |   int p,i;
 | 
|---|
 | 531 |   const enum PsiTypeTag state = P->R.CurrentMin;
 | 
|---|
 | 532 |   for (p=Lat->Psi.TypeStartIndex[state]; p < Lat->Psi.TypeStartIndex[state+1]; p++) {
 | 
|---|
 | 533 |     //if (p < 0 || p >= Lat->Psi.LocalNo) Error(SomeError,"InitPerturbedEnergyCalculation: p out of range");
 | 
|---|
 | 534 |     CalculateNonLocalEnergyNoRT(P, p); // recalculating non-local form factors which are coefficient dependent!
 | 
|---|
 | 535 |     CalculatePsiEnergy(P,p,1);
 | 
|---|
 | 536 |     CalculatePerturbedEnergy(P, p, 0, first);
 | 
|---|
 | 537 |     CalculateOverlap(P, p, state);
 | 
|---|
 | 538 |   }
 | 
|---|
 | 539 |   for (i=0; i<= Perturbed0_1Energy; i++) {
 | 
|---|
 | 540 |     Lat->E->AllLocalPsiEnergy[i] = 0.0;
 | 
|---|
 | 541 |     for (p=0; p < Lat->Psi.LocalNo; p++)
 | 
|---|
 | 542 |       if (P->Lat.Psi.LocalPsiStatus[p].PsiType == state)
 | 
|---|
 | 543 |         Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p];
 | 
|---|
 | 544 |   }
 | 
|---|
 | 545 | }
 | 
|---|
 | 546 | 
 | 
|---|
 | 547 | 
 | 
|---|
 | 548 | /** Updating of perturbed energy.
 | 
|---|
 | 549 |  * For current and former (if not the same) local wave function RunStruct#ActualLocal, RunStruct#OldActualLocalPsiNo it is called:
 | 
|---|
 | 550 |  * - CalculateNonLocalEnergyNoRT(): for the form factors
 | 
|---|
 | 551 |  * - CalculatePerturbedEnergy(): for the perturbed energy, gradient only for RunStruct#ActualLocal
 | 
|---|
 | 552 |  * - CalculatePerturbedOverlap(): for the overlap between the perturbed wave functions
 | 
|---|
 | 553 |  * 
 | 
|---|
 | 554 |  * Afterwards for the two types AllPsiEnergyTypes#Perturbed1_0Energy and AllPsiEnergyTypes#Perturbed0_1Energy the
 | 
|---|
 | 555 |  * energy contribution from each wave function is added up in Energy#AllLocalPsiEnergy.
 | 
|---|
 | 556 |  * \param *P Problem at hand
 | 
|---|
 | 557 |  * \sa CalculatePerturbedEnergy() called from here.
 | 
|---|
 | 558 |  * \note Afterwards EnergyAllReduce() must be called.
 | 
|---|
 | 559 |  */
 | 
|---|
 | 560 | void UpdatePerturbedEnergyCalculation(struct Problem *P)
 | 
|---|
 | 561 | {
 | 
|---|
 | 562 |   struct Lattice *Lat = &(P->Lat);
 | 
|---|
 | 563 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 564 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 565 |   const enum PsiTypeTag state = R->CurrentMin;
 | 
|---|
 | 566 |   int p = R->ActualLocalPsiNo;
 | 
|---|
 | 567 |   const int p_old = R->OldActualLocalPsiNo;
 | 
|---|
 | 568 |   int i;
 | 
|---|
 | 569 |   
 | 
|---|
 | 570 |   if (p != p_old) {
 | 
|---|
 | 571 |     //if (p_old < 0 || p_old >= Lat->Psi.LocalNo) Error(SomeError,"UpdatePerturbedEnergyCalculation: p_old out of range");
 | 
|---|
 | 572 |     CalculateNonLocalEnergyNoRT(P, p_old);
 | 
|---|
 | 573 |     CalculatePsiEnergy(P,p_old,0);
 | 
|---|
 | 574 |     CalculatePerturbedEnergy(P, p_old, 0, 0);
 | 
|---|
 | 575 |     CalculateOverlap(P, p_old, state);
 | 
|---|
 | 576 |   }
 | 
|---|
 | 577 |   //if (p < 0 || p >= Lat->Psi.LocalNo) Error(SomeError,"InitPerturbedEnergyCalculation: p out of range");
 | 
|---|
 | 578 |   // recalculating non-local form factors which are coefficient dependent!
 | 
|---|
 | 579 |   CalculateNonLocalEnergyNoRT(P,p);
 | 
|---|
 | 580 |   CalculatePsiEnergy(P,p,0);
 | 
|---|
 | 581 |   CalculatePerturbedEnergy(P, p, 1, 0);
 | 
|---|
 | 582 |   CalculateOverlap(P, p, state);
 | 
|---|
 | 583 |   
 | 
|---|
 | 584 |   for (i=0; i<= Perturbed0_1Energy; i++) {
 | 
|---|
 | 585 |     Lat->E->AllLocalPsiEnergy[i] = 0.0;
 | 
|---|
 | 586 |     for (p=0; p < Psi->LocalNo; p++)
 | 
|---|
 | 587 |       if (Psi->LocalPsiStatus[p].PsiType == state)
 | 
|---|
 | 588 |         Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p];
 | 
|---|
 | 589 |   }
 | 
|---|
 | 590 | }
 | 
|---|
 | 591 | 
 | 
|---|
 | 592 | /** Calculates gradient and evaluates second order perturbed energy functional for specific wave function.
 | 
|---|
 | 593 |  * The in second order perturbed energy functional reads as follows.
 | 
|---|
 | 594 |  * \f[
 | 
|---|
 | 595 |  * E^{(2)} = \sum_{kl} \langle \varphi_k^{(1)} | H^{(0)} \delta_{kl} - \lambda_{kl} | \varphi_l^{(1)} \rangle
 | 
|---|
 | 596 |  *  + \underbrace{\langle \varphi_l^{(0)} | H^{(1)} | \varphi_l^{(1)} \rangle + \langle \varphi_l^{(1)} | H^{(1)} | \varphi_l^{(0)} \rangle}_{2 {\cal R} \langle \varphi_l^{(1)} | H^{(1)} | \varphi_l^{(0)} \rangle}
 | 
|---|
 | 597 |  * \f]
 | 
|---|
 | 598 |  * And the gradient
 | 
|---|
 | 599 |  * \f[
 | 
|---|
 | 600 |  *  \widetilde{\varphi}_k^{(1)} = - \sum_l ({\cal H}^{(0)} \delta_{kl} - \lambda_{kl} | \varphi_l^{(1)} \rangle + {\cal H}^{(1)} | \varphi_k^{(0)} \rangle
 | 
|---|
 | 601 |  * \f]
 | 
|---|
 | 602 |  * First, the HGDensity is recalculated if \a first says so - see ApplyTotalHamiltonian().
 | 
|---|
 | 603 |  *
 | 
|---|
 | 604 |  * Next, we need the perturbation hamiltonian acting on both the respective occupied and current wave function,
 | 
|---|
 | 605 |  * see perturbed.c for respective function calls.
 | 
|---|
 | 606 |  * 
 | 
|---|
 | 607 |  * Finally, the scalar product between the wave function and Hc_Gradient yields the eigenvalue of the hamiltonian,
 | 
|---|
 | 608 |  * which is summed up over all reciprocal grid vectors and stored in OnePsiElementAddData#Lambda. The Gradient is
 | 
|---|
 | 609 |  * the inverse of Hc_Gradient and with the following summation over all perturbed wave functions (MPI exchange of
 | 
|---|
 | 610 |  * non-local coefficients) the gradient is computed. Here we need Psis#lambda, which is computed in CalculateHamiltonian().
 | 
|---|
 | 611 |  * 
 | 
|---|
 | 612 |  * Also \f${\cal H}^{(1)} | \varphi_l^{(0)} \rangle\f$ is stored in GradientTypes#H1cGradient.
 | 
|---|
 | 613 |  * \param *P Problem at hand, contains RunStruct, Lattice, LatticeLevel RunStruct#LevS
 | 
|---|
 | 614 |  * \param l offset of perturbed wave function within Psi#LocalPsiStatus (\f$\varphi_l^{(1)}\f$)
 | 
|---|
 | 615 |  * \param DoGradient (1 = yes, 0 = no) whether gradient shall be calculated or not
 | 
|---|
 | 616 |  * \param first recaculate HGDensity (1) or not (0)
 | 
|---|
 | 617 |  * \note DensityTypes#ActualPsiDensity must be recent for gradient calculation!
 | 
|---|
 | 618 |  * \sa CalculateGradientNoRT() - same procedure for evaluation of \f${\cal H}^{(0)}| \varphi_l^{(1)} \rangle\f$
 | 
|---|
 | 619 |  * \note without the simplification of \f$2 {\cal R} \langle \varphi_l^{(1)} | H^{(1)} | \varphi_l^{(0)} \rangle\f$ the
 | 
|---|
 | 620 |  *       calculation would be impossible due to non-local nature of perturbed wave functions. The position operator would
 | 
|---|
 | 621 |  *       be impossible to apply in a sensible manner.
 | 
|---|
 | 622 |  */
 | 
|---|
 | 623 | void CalculatePerturbedEnergy(struct Problem *P, const int l, const int DoGradient, const int first) 
 | 
|---|
 | 624 | {
 | 
|---|
 | 625 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 626 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 627 |   struct Energy *E = Lat->E;
 | 
|---|
 | 628 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
 | 629 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 630 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 631 |   const int state = R->CurrentMin;
 | 
|---|
 | 632 |   const int l_normal = Psi->TypeStartIndex[Occupied] + (l - Psi->TypeStartIndex[state]);  // offset l to \varphi_l^{(0)}
 | 
|---|
 | 633 |   const int ActNum = l - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[l].my_color_comm_ST_Psi;
 | 
|---|
 | 634 |   int g, i, m, j;
 | 
|---|
 | 635 |   double lambda, Lambda;
 | 
|---|
 | 636 |   double RElambda10, RELambda10;
 | 
|---|
 | 637 |   const fftw_complex *source = LevS->LPsi->LocalPsi[l];
 | 
|---|
 | 638 |   fftw_complex *grad = P->Grad.GradientArray[ActualGradient];
 | 
|---|
 | 639 |   fftw_complex *Hc_grad = P->Grad.GradientArray[HcGradient];
 | 
|---|
 | 640 |   fftw_complex *H1c_grad = P->Grad.GradientArray[H1cGradient];
 | 
|---|
 | 641 |   fftw_complex *TempPsi_0 = H1c_grad;
 | 
|---|
 | 642 |   fftw_complex *varphi_1, *varphi_0;
 | 
|---|
 | 643 |   struct OnePsiElement *OnePsiB, *LOnePsiB;
 | 
|---|
 | 644 |   fftw_complex *LPsiDatB=NULL;
 | 
|---|
 | 645 |   const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
 | 646 |   int RecvSource;
 | 
|---|
 | 647 |   MPI_Status status;
 | 
|---|
 | 648 |   
 | 
|---|
 | 649 |   // ============ Calculate H^(0) psi^(1) =============================
 | 
|---|
 | 650 |   //if (Hc_grad != P->Grad.GradientArray[HcGradient]) Error(SomeError,"CalculatePerturbedEnergy: Hc_grad corrupted");
 | 
|---|
 | 651 |   SetArrayToDouble0((double *)Hc_grad,2*R->InitLevS->MaxG);
 | 
|---|
 | 652 |   ApplyTotalHamiltonian(P,source,Hc_grad, PP->fnl[l], 1, first);
 | 
|---|
 | 653 |     
 | 
|---|
 | 654 |   // ============ ENERGY FUNCTIONAL Evaluation  PART 1 ================  
 | 
|---|
 | 655 |   //if (l_normal < 0 || l_normal >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l_normal out of range");
 | 
|---|
 | 656 |   varphi_0 = LevS->LPsi->LocalPsi[l_normal];
 | 
|---|
 | 657 |   //if (l < 0 || l >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l out of range");
 | 
|---|
 | 658 |   varphi_1 = LevS->LPsi->LocalPsi[l];
 | 
|---|
 | 659 |   //if (TempPsi_0 != P->Grad.GradientArray[H1cGradient]) Error(SomeError,"CalculatePerturbedEnergy: TempPsi_0 corrupted");
 | 
|---|
 | 660 |   SetArrayToDouble0((double *)TempPsi_0,2*R->InitLevS->MaxG);
 | 
|---|
 | 661 |   switch (state) {
 | 
|---|
 | 662 |     case Perturbed_P0:
 | 
|---|
 | 663 |       CalculatePerturbationOperator_P(P,varphi_0,TempPsi_0,0); //  \nabla_0 | \varphi_l^{(0)} \rangle
 | 
|---|
 | 664 |       break;
 | 
|---|
 | 665 |     case Perturbed_P1:
 | 
|---|
 | 666 |       CalculatePerturbationOperator_P(P,varphi_0,TempPsi_0,1); //  \nabla_1 | \varphi_l^{(0)} \rangle
 | 
|---|
 | 667 |       break;
 | 
|---|
 | 668 |     case Perturbed_P2:
 | 
|---|
 | 669 |       CalculatePerturbationOperator_P(P,varphi_0,TempPsi_0,2); //  \nabla_1 | \varphi_l^{(0)} \rangle
 | 
|---|
 | 670 |       break;
 | 
|---|
 | 671 |     case Perturbed_RxP0:
 | 
|---|
 | 672 |       CalculatePerturbationOperator_RxP(P,varphi_0,TempPsi_0,l_normal,0); //  r \times \nabla | \varphi_l^{(0)} \rangle
 | 
|---|
 | 673 |       break;
 | 
|---|
 | 674 |     case Perturbed_RxP1:
 | 
|---|
 | 675 |       CalculatePerturbationOperator_RxP(P,varphi_0,TempPsi_0,l_normal,1); //  r \times \nabla | \varphi_l^{(0)} \rangle
 | 
|---|
 | 676 |       break;
 | 
|---|
 | 677 |     case Perturbed_RxP2:
 | 
|---|
 | 678 |       CalculatePerturbationOperator_RxP(P,varphi_0,TempPsi_0,l_normal,2); //  r \times \nabla | \varphi_l^{(0)} \rangle
 | 
|---|
 | 679 |       break;
 | 
|---|
 | 680 |     default:
 | 
|---|
 | 681 |       fprintf(stderr,"(%i) CalculatePerturbedEnergy called whilst not within perturbation run: CurrentMin = %i !\n",P->Par.me, R->CurrentMin);
 | 
|---|
 | 682 |       break;
 | 
|---|
 | 683 |   }
 | 
|---|
 | 684 | 
 | 
|---|
 | 685 |   // ============ GRADIENT and EIGENVALUE Evaluation  Part 1==============
 | 
|---|
 | 686 |   lambda = 0.0;
 | 
|---|
 | 687 |   if ((DoGradient) && (grad != NULL)) {
 | 
|---|
 | 688 |     g = 0;
 | 
|---|
 | 689 |     if (LevS->GArray[0].GSq == 0.0) {
 | 
|---|
 | 690 |       lambda += Hc_grad[0].re*source[0].re;
 | 
|---|
 | 691 |       //if (grad != P->Grad.GradientArray[ActualGradient]) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
 | 
|---|
 | 692 |       grad[0].re = -(Hc_grad[0].re + TempPsi_0[0].re);
 | 
|---|
 | 693 |       grad[0].im = -(Hc_grad[0].im + TempPsi_0[0].im);
 | 
|---|
 | 694 |       g++;
 | 
|---|
 | 695 |     }
 | 
|---|
 | 696 |     for (;g<LevS->MaxG;g++) {
 | 
|---|
 | 697 |       lambda += 2.*(Hc_grad[g].re*source[g].re + Hc_grad[g].im*source[g].im);
 | 
|---|
 | 698 |       //if (grad != P->Grad.GradientArray[ActualGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
 | 
|---|
 | 699 |       grad[g].re = -(Hc_grad[g].re + TempPsi_0[g].re);
 | 
|---|
 | 700 |       grad[g].im = -(Hc_grad[g].im + TempPsi_0[g].im);
 | 
|---|
 | 701 |     }
 | 
|---|
 | 702 | 
 | 
|---|
 | 703 |     m = -1;
 | 
|---|
 | 704 |     for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) {  // go through all wave functions
 | 
|---|
 | 705 |       OnePsiB = &Psi->AllPsiStatus[j];    // grab OnePsiB
 | 
|---|
 | 706 |       if (OnePsiB->PsiType == state) {   // drop all but the ones of current min state
 | 
|---|
 | 707 |         m++;  // increase m if it is type-specific wave function
 | 
|---|
 | 708 |         if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
 | 
|---|
 | 709 |            LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
 | 
|---|
 | 710 |         else
 | 
|---|
 | 711 |            LOnePsiB = NULL;
 | 
|---|
 | 712 |         if (LOnePsiB == NULL) {   // if it's not local ... receive it from respective process into TempPsi
 | 
|---|
 | 713 |           RecvSource = OnePsiB->my_color_comm_ST_Psi;
 | 
|---|
 | 714 |           MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, PerturbedTag, P->Par.comm_ST_PsiT, &status );
 | 
|---|
 | 715 |           LPsiDatB=LevS->LPsi->TempPsi;
 | 
|---|
 | 716 |         } else {                  // .. otherwise send it to all other processes (Max_me... - 1)
 | 
|---|
 | 717 |           for (i=0;i<P->Par.Max_me_comm_ST_PsiT;i++)
 | 
|---|
 | 718 |             if (i != OnePsiB->my_color_comm_ST_Psi)
 | 
|---|
 | 719 |               MPI_Send( LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, i, PerturbedTag, P->Par.comm_ST_PsiT);
 | 
|---|
 | 720 |           LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
 | 
|---|
 | 721 |         } // LPsiDatB is now set to the coefficients of OnePsi either stored or MPI_Received
 | 
|---|
 | 722 |   
 | 
|---|
 | 723 |         g = 0;
 | 
|---|
 | 724 |         if (LevS->GArray[0].GSq == 0.0) { // perform the summation
 | 
|---|
 | 725 |           //if (grad != P->Grad.GradientArray[ActualGradient]) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
 | 
|---|
 | 726 |           grad[0].re += Lat->Psi.lambda[ActNum][m]*LPsiDatB[0].re;
 | 
|---|
 | 727 |           grad[0].im += Lat->Psi.lambda[ActNum][m]*LPsiDatB[0].im;
 | 
|---|
 | 728 |           g++;
 | 
|---|
 | 729 |         }
 | 
|---|
 | 730 |         for (;g<LevS->MaxG;g++) {
 | 
|---|
 | 731 |           //if (grad != P->Grad.GradientArray[ActualGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
 | 
|---|
 | 732 |           grad[g].re += Lat->Psi.lambda[ActNum][m]*LPsiDatB[g].re;
 | 
|---|
 | 733 |           grad[g].im += Lat->Psi.lambda[ActNum][m]*LPsiDatB[g].im;
 | 
|---|
 | 734 |         }
 | 
|---|
 | 735 |       }
 | 
|---|
 | 736 |     }
 | 
|---|
 | 737 |   } else {
 | 
|---|
 | 738 |     lambda = GradSP(P,LevS,Hc_grad,source);
 | 
|---|
 | 739 |   }
 | 
|---|
 | 740 |   MPI_Allreduce ( &lambda, &Lambda, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 741 |   //fprintf(stderr,"(%i) Lambda[%i] = %lg\n",P->Par.me, l, Lambda);
 | 
|---|
 | 742 |   //if (l < 0 || l >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l out of range");
 | 
|---|
 | 743 |   Lat->Psi.AddData[l].Lambda = Lambda; 
 | 
|---|
 | 744 | 
 | 
|---|
 | 745 |   // ============ ENERGY FUNCTIONAL Evaluation  PART 2 ================
 | 
|---|
 | 746 |   // varphi_1 jas negative symmetry, returning TempPsi_0 from CalculatePerturbedOperator also, thus real part of scalar product
 | 
|---|
 | 747 |   // "-" due to purely imaginary wave function is on left hand side, thus becomes complex conjugated: i -> -i
 | 
|---|
 | 748 |   // (-i goes into pert. op., "-" remains when on right hand side)  
 | 
|---|
 | 749 |   RElambda10 =  GradSP(P,LevS,varphi_1,TempPsi_0) * sqrt(Psi->LocalPsiStatus[l].PsiFactor * Psi->LocalPsiStatus[l_normal].PsiFactor);
 | 
|---|
 | 750 |   //RElambda01 = -GradSP(P,LevS,varphi_0,TempPsi_1) * sqrt(Psi->LocalPsiStatus[l].PsiFactor * Psi->LocalPsiStatus[l_normal].PsiFactor);
 | 
|---|
 | 751 |   
 | 
|---|
 | 752 |   MPI_Allreduce ( &RElambda10, &RELambda10, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 753 |   //MPI_Allreduce ( &RElambda01, &RELambda01, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 754 |   
 | 
|---|
 | 755 |   //if (l < 0 || l >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l out of range");
 | 
|---|
 | 756 |   E->PsiEnergy[Perturbed1_0Energy][l] = RELambda10;
 | 
|---|
 | 757 |   E->PsiEnergy[Perturbed0_1Energy][l] = RELambda10;
 | 
|---|
 | 758 | //  if (P->Par.me == 0) {
 | 
|---|
 | 759 | //    fprintf(stderr,"RE.Lambda10[%i-%i] = %lg\t RE.Lambda01[%i-%i] = %lg\n", l, l_normal, RELambda10, l_normal, l, RELambda01);
 | 
|---|
 | 760 | //  }
 | 
|---|
 | 761 |   // GradImSP() is only applicable to a product of wave functions with uneven symmetry!
 | 
|---|
 | 762 |   // Otherwise, due to the nature of symmetry, a sum over only half of the coefficients will in most cases not result in zero!
 | 
|---|
 | 763 | }
 | 
|---|
 | 764 | 
 | 
|---|
 | 765 | /** Applies \f$H^{(0)}\f$ to a given \a source.
 | 
|---|
 | 766 |  * The DensityTypes#HGDensity is computed, the exchange potential added and the
 | 
|---|
 | 767 |  * whole multiplied - coefficient by coefficient - with the current wave function, taken from its density coefficients,
 | 
|---|
 | 768 |  * on the upper LatticeLevel (RunStruct#Lev0), which (DensityTypes#ActualPsiDensity) is updated beforehand.
 | 
|---|
 | 769 |  * After an inverse fft (now G-dependent) the non-local potential is added and
 | 
|---|
 | 770 |  * within the reciprocal basis set, the kinetic energy can be evaluated easily. 
 | 
|---|
 | 771 |  * \param *P Problem at hand
 | 
|---|
 | 772 |  * \param *source pointer to source coefficient array, \f$| \varphi(G) \rangle\f$
 | 
|---|
 | 773 |  * \param *dest pointer to dest coefficient array,\f$H^{(0)} | \varphi(G) \rangle\f$
 | 
|---|
 | 774 |  * \param **fnl pointer to non-local form factor array
 | 
|---|
 | 775 |  * \param PsiFactor occupation number of orbital
 | 
|---|
 | 776 |  * \param first 1 - Re-calculate DensityTypes#HGDensity, 0 - don't 
 | 
|---|
 | 777 |  * \sa CalculateConDirHConDir() - same procedure
 | 
|---|
 | 778 |  */
 | 
|---|
 | 779 | void ApplyTotalHamiltonian(struct Problem *P, const fftw_complex *source, fftw_complex *dest, fftw_complex ***fnl, const double PsiFactor, const int first) {
 | 
|---|
 | 780 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 781 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 782 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 783 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 784 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 785 |   struct fft_plan_3d *plan = Lat->plan; 
 | 
|---|
 | 786 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
 | 787 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 788 |   fftw_complex *work = Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 789 |   fftw_real *HGcR = Dens0->DensityArray[HGcDensity];
 | 
|---|
 | 790 |   fftw_complex *HGcRC = (fftw_complex*)HGcR;
 | 
|---|
 | 791 |   fftw_complex *HGC = Dens0->DensityCArray[HGDensity];
 | 
|---|
 | 792 |   fftw_real *HGCR = (fftw_real *)HGC;
 | 
|---|
 | 793 |   fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
 | 794 |   fftw_real *PsiCR = (fftw_real *)PsiC;
 | 
|---|
 | 795 |   //const fftw_complex *dest_bak = dest;
 | 
|---|
 | 796 |   int nx,ny,nz,iS,i0;
 | 
|---|
 | 797 |   const int Nx = LevS->Plan0.plan->local_nx;
 | 
|---|
 | 798 |   const int Ny = LevS->Plan0.plan->N[1];
 | 
|---|
 | 799 |   const int Nz = LevS->Plan0.plan->N[2];
 | 
|---|
 | 800 |   const int NUpx = LevS->NUp[0];
 | 
|---|
 | 801 |   const int NUpy = LevS->NUp[1];
 | 
|---|
 | 802 |   const int NUpz = LevS->NUp[2];
 | 
|---|
 | 803 |   const double HGcRCFactor = 1./LevS->MaxN;
 | 
|---|
 | 804 |   int g, Index, i, it;
 | 
|---|
 | 805 |   fftw_complex vp,rp,rhog,TotalPsiDensity;
 | 
|---|
 | 806 |   double Fac;
 | 
|---|
 | 807 | 
 | 
|---|
 | 808 |   if (first) {
 | 
|---|
 | 809 |     // recalculate HGDensity
 | 
|---|
 | 810 |     //if (HGC != Dens0->DensityCArray[HGDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
 | 
|---|
 | 811 |     SetArrayToDouble0((double *)HGC,2*Dens0->TotalSize);
 | 
|---|
 | 812 |     g=0;
 | 
|---|
 | 813 |     if (Lev0->GArray[0].GSq == 0.0) {
 | 
|---|
 | 814 |       Index = Lev0->GArray[0].Index;
 | 
|---|
 | 815 |       c_re(vp) = 0.0;
 | 
|---|
 | 816 |       c_im(vp) = 0.0;
 | 
|---|
 | 817 |       for (it = 0; it < I->Max_Types; it++) {
 | 
|---|
 | 818 |         c_re(vp) += (c_re(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]); 
 | 
|---|
 | 819 |         c_im(vp) += (c_im(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]);
 | 
|---|
 | 820 |       }
 | 
|---|
 | 821 |       //if (HGC != Dens0->DensityCArray[HGDensity] || Index<0 || Index>=Dens0->LocalSizeC) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
 | 
|---|
 | 822 |       c_re(HGC[Index]) = c_re(vp);
 | 
|---|
 | 823 |       c_re(TotalPsiDensity) = c_re(Dens0->DensityCArray[TotalDensity][Index]);
 | 
|---|
 | 824 |       c_im(TotalPsiDensity) = c_im(Dens0->DensityCArray[TotalDensity][Index]);
 | 
|---|
 | 825 |   
 | 
|---|
 | 826 |       g++;
 | 
|---|
 | 827 |     }
 | 
|---|
 | 828 |     for (; g < Lev0->MaxG; g++) {
 | 
|---|
 | 829 |       Index = Lev0->GArray[g].Index;
 | 
|---|
 | 830 |       Fac = 4.*PI/(Lev0->GArray[g].GSq);
 | 
|---|
 | 831 |       c_re(vp) = 0.0;
 | 
|---|
 | 832 |       c_im(vp) = 0.0;
 | 
|---|
 | 833 |       c_re(rp) = 0.0;
 | 
|---|
 | 834 |       c_im(rp) = 0.0;
 | 
|---|
 | 835 |       for (it = 0; it < I->Max_Types; it++) {
 | 
|---|
 | 836 |         c_re(vp) += (c_re(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]); 
 | 
|---|
 | 837 |         c_im(vp) += (c_im(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]);
 | 
|---|
 | 838 |         c_re(rp) += (c_re(I->I[it].SFactor[g])*PP->FacGauss[it][g]); 
 | 
|---|
 | 839 |         c_im(rp) += (c_im(I->I[it].SFactor[g])*PP->FacGauss[it][g]);
 | 
|---|
 | 840 |       } // rp = n^{Gauss)(G)
 | 
|---|
 | 841 |   
 | 
|---|
 | 842 |       // n^{tot} = n^0 + \lambda n^1 + ...
 | 
|---|
 | 843 |       //if (isnan(c_re(Dens0->DensityCArray[TotalDensity][Index]))) { fprintf(stderr,"(%i) WARNING in CalculatePerturbedEnergy(): TotalDensity[%i] = NaN!\n", P->Par.me, Index); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
 | 844 |       c_re(TotalPsiDensity) = c_re(Dens0->DensityCArray[TotalDensity][Index]);
 | 
|---|
 | 845 |       c_im(TotalPsiDensity) = c_im(Dens0->DensityCArray[TotalDensity][Index]);
 | 
|---|
 | 846 |   
 | 
|---|
 | 847 |       c_re(rhog) = c_re(TotalPsiDensity)*R->HGcFactor+c_re(rp);
 | 
|---|
 | 848 |       c_im(rhog) = c_im(TotalPsiDensity)*R->HGcFactor+c_im(rp);
 | 
|---|
 | 849 |       // rhog = n(G) + n^{Gauss}(G), rhoe = n(G)
 | 
|---|
 | 850 |       //if (HGC != Dens0->DensityCArray[HGDensity] || Index<0 || Index>=Dens0->LocalSizeC) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
 | 
|---|
 | 851 |       c_re(HGC[Index]) = c_re(vp)+Fac*c_re(rhog);
 | 
|---|
 | 852 |       c_im(HGC[Index]) = c_im(vp)+Fac*c_im(rhog);
 | 
|---|
 | 853 |     }
 | 
|---|
 | 854 |     //
 | 
|---|
 | 855 |     for (i=0; i<Lev0->MaxDoubleG; i++) {
 | 
|---|
 | 856 |       //if (HGC != Dens0->DensityCArray[HGDensity] || Lev0->DoubleG[2*i+1]<0 || Lev0->DoubleG[2*i+1]>Dens0->LocalSizeC || Lev0->DoubleG[2*i]<0 || Lev0->DoubleG[2*i]>Dens0->LocalSizeC) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
 | 
|---|
 | 857 |       HGC[Lev0->DoubleG[2*i+1]].re =  HGC[Lev0->DoubleG[2*i]].re;
 | 
|---|
 | 858 |       HGC[Lev0->DoubleG[2*i+1]].im = -HGC[Lev0->DoubleG[2*i]].im;
 | 
|---|
 | 859 |     }
 | 
|---|
 | 860 |   }
 | 
|---|
 | 861 |   // ============ GRADIENT and EIGENVALUE Evaluation  Part 1==============
 | 
|---|
 | 862 |   // \lambda_l^{(1)} = \langle \varphi_l^{(1)} | H^{(0)} | \varphi_l^{(1)} \rangle and gradient calculation
 | 
|---|
 | 863 |   SpeedMeasure(P, LocTime, StartTimeDo);
 | 
|---|
 | 864 |   // back-transform HGDensity: (G) -> (R)
 | 
|---|
 | 865 |   //if (HGC != Dens0->DensityCArray[HGDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
 | 
|---|
 | 866 |   if (first) fft_3d_complex_to_real(plan, Lev0->LevelNo, FFTNF1, HGC, work);
 | 
|---|
 | 867 |   // evaluate exchange potential with this density, add up onto HGCR
 | 
|---|
 | 868 |   //if (HGCR != (fftw_real *)Dens0->DensityCArray[HGDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGCR corrupted");
 | 
|---|
 | 869 |   if (first) CalculateXCPotentialNoRT(P, HGCR); // add V^{xc} on V^H + V^{ps}
 | 
|---|
 | 870 |   // make sure that ActualPsiDensity is recent
 | 
|---|
 | 871 |   CalculateOneDensityR(Lat, LevS, Dens0, source, Dens0->DensityArray[ActualDensity], R->FactorDensityR*PsiFactor, 1);
 | 
|---|
 | 872 |   for (nx=0;nx<Nx;nx++)  
 | 
|---|
 | 873 |     for (ny=0;ny<Ny;ny++) 
 | 
|---|
 | 874 |       for (nz=0;nz<Nz;nz++) {
 | 
|---|
 | 875 |         i0 = nz*NUpz+Nz*NUpz*(ny*NUpy+Ny*NUpy*nx*NUpx);
 | 
|---|
 | 876 |         iS = nz+Nz*(ny+Ny*nx);
 | 
|---|
 | 877 |         //if (HGcR != Dens0->DensityArray[HGcDensity] || iS<0 || iS>=LevS->Dens->LocalSizeR) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
 | 
|---|
 | 878 |         HGcR[iS] = HGCR[i0]*PsiCR[i0]; /* Matrix Vector Mult */
 | 
|---|
 | 879 |       }
 | 
|---|
 | 880 |   // (R) -> (G)
 | 
|---|
 | 881 |   //if (HGcRC != (fftw_complex *)Dens0->DensityArray[HGcDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGcRC corrupted");
 | 
|---|
 | 882 |   fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, HGcRC, work);
 | 
|---|
 | 883 |   SpeedMeasure(P, LocTime, StopTimeDo);
 | 
|---|
 | 884 |   /* NonLocalPP */
 | 
|---|
 | 885 |   SpeedMeasure(P, NonLocTime, StartTimeDo);
 | 
|---|
 | 886 |   //if (dest != dest_bak) Error(SomeError,"ApplyTotalHamiltonian: dest corrupted");
 | 
|---|
 | 887 |   CalculateAddNLPot(P, dest, fnl, PsiFactor);  // wave function hidden in form factors fnl, also resets Hc_grad beforehand
 | 
|---|
 | 888 |   SpeedMeasure(P, NonLocTime, StopTimeDo);
 | 
|---|
 | 889 |   
 | 
|---|
 | 890 |   /* create final vector */
 | 
|---|
 | 891 |   for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
 | 892 |     Index = LevS->GArray[g].Index; /* FIXME - factoren */
 | 
|---|
 | 893 |     //if (dest != dest_bak || g<0 || g>=LevS->MaxG) Error(SomeError,"ApplyTotalHamiltonian: dest corrupted");
 | 
|---|
 | 894 |     dest[g].re += PsiFactor*(HGcRC[Index].re*HGcRCFactor + 0.5*LevS->GArray[g].GSq*source[g].re);
 | 
|---|
 | 895 |     dest[g].im += PsiFactor*(HGcRC[Index].im*HGcRCFactor + 0.5*LevS->GArray[g].GSq*source[g].im);
 | 
|---|
 | 896 |   }
 | 
|---|
 | 897 | }
 | 
|---|
 | 898 | 
 | 
|---|
 | 899 | #define stay_above 0.001 //!< value above which the coefficient of the wave function will always remain
 | 
|---|
 | 900 | 
 | 
|---|
 | 901 | /** Finds the minimum of perturbed energy in regards of actual wave function.
 | 
|---|
 | 902 |  * The following happens step by step:
 | 
|---|
 | 903 |  * -# The Gradient is copied into GradientTypes#GraSchGradient (which is nothing but a pointer to
 | 
|---|
 | 904 |  *    one array in LPsiDat) and orthonormalized via GramSch() to all occupied wave functions
 | 
|---|
 | 905 |  *    except to the current perturbed one.
 | 
|---|
 | 906 |  * -# Then comes pre-conditioning, analogous to CalculatePreConGrad().
 | 
|---|
 | 907 |  * -# The Gradient is projected onto the current perturbed wave function and this is subtracted, i.e.
 | 
|---|
 | 908 |  *    vector is the conjugate gradient.
 | 
|---|
 | 909 |  * -# Finally, Calculate1stPerturbedDerivative() and Calculate2ndPerturbedDerivative() are called and
 | 
|---|
 | 910 |  *    with these results and the current total energy, CalculateDeltaI() finds the parameter for the one-
 | 
|---|
 | 911 |  *    dimensional minimisation. The current wave function is set to newly found minimum and approximated
 | 
|---|
 | 912 |  *    total energy is printed.
 | 
|---|
 | 913 |  * 
 | 
|---|
 | 914 |  * \param *P Problem at hand
 | 
|---|
 | 915 |  * \sa CalculateNewWave() and functions therein
 | 
|---|
 | 916 |  */
 | 
|---|
 | 917 | void FindPerturbedMinimum(struct Problem *P)
 | 
|---|
 | 918 | {
 | 
|---|
 | 919 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 920 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 921 |   struct Psis *Psi = &Lat->Psi; 
 | 
|---|
 | 922 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
 | 923 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 924 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 925 |   struct Density *Dens = Lev0->Dens;
 | 
|---|
 | 926 |   struct Energy *En = Lat->E;
 | 
|---|
 | 927 |   struct FileData *F = &P->Files;
 | 
|---|
 | 928 |   int g,p,i;
 | 
|---|
 | 929 |   int step = R->PsiStep;
 | 
|---|
 | 930 |   double *GammaDiv = &Lat->Psi.AddData[R->ActualLocalPsiNo].Gamma;
 | 
|---|
 | 931 |   const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
 | 932 |   fftw_complex *source = LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
 | 
|---|
 | 933 |   fftw_complex *grad = P->Grad.GradientArray[ActualGradient];
 | 
|---|
 | 934 |   fftw_complex *GradOrtho = P->Grad.GradientArray[GraSchGradient];
 | 
|---|
 | 935 |   fftw_complex *PCgrad = P->Grad.GradientArray[PreConGradient];
 | 
|---|
 | 936 |   fftw_complex *PCOrtho = P->Grad.GradientArray[GraSchGradient];
 | 
|---|
 | 937 |   fftw_complex *ConDir = P->Grad.GradientArray[ConDirGradient];
 | 
|---|
 | 938 |   fftw_complex *ConDir_old = P->Grad.GradientArray[OldConDirGradient];
 | 
|---|
 | 939 |   fftw_complex *Ortho = P->Grad.GradientArray[GraSchGradient];
 | 
|---|
 | 940 |   const fftw_complex *Hc_grad = P->Grad.GradientArray[HcGradient];
 | 
|---|
 | 941 |   const fftw_complex *H1c_grad = P->Grad.GradientArray[H1cGradient];
 | 
|---|
 | 942 |   fftw_complex *HConDir = Dens->DensityCArray[ActualDensity];
 | 
|---|
 | 943 |   const double PsiFactor = Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor;
 | 
|---|
 | 944 |   //double Lambda = Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda;
 | 
|---|
 | 945 |   double T;
 | 
|---|
 | 946 |   double x, K; //, dK;
 | 
|---|
 | 947 |   double dS[2], S[2], Gamma, GammaDivOld = *GammaDiv;
 | 
|---|
 | 948 |   double LocalSP, PsiSP;
 | 
|---|
 | 949 |   double dEdt0, ddEddt0, ConDirHConDir, ConDirConDir;//, sourceHsource;
 | 
|---|
 | 950 |   double E0, E, delta;
 | 
|---|
 | 951 |   //double E0, E, dE, ddE, delta, dcos, dsin;
 | 
|---|
 | 952 |   //double EI, dEI, ddEI, deltaI, dcosI, dsinI;
 | 
|---|
 | 953 |   //double HartreeddEddt0, XCddEddt0;
 | 
|---|
 | 954 |   double d[4],D[4], Diff;
 | 
|---|
 | 955 |   const int Num = Psi->NoOfPsis;
 | 
|---|
 | 956 |   
 | 
|---|
 | 957 |   // ORTHOGONALIZED-GRADIENT
 | 
|---|
 | 958 |   for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
 | 959 |     //if (GradOrtho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: GradOrtho corrupted");
 | 
|---|
 | 960 |     GradOrtho[g].re = grad[g].re; //+Lambda*source[g].re;
 | 
|---|
 | 961 |     GradOrtho[g].im = grad[g].im; //+Lambda*source[g].im;
 | 
|---|
 | 962 |   }
 | 
|---|
 | 963 |   // include the ExtraPsi (which is the GraSchGradient!)
 | 
|---|
 | 964 |   SetGramSchExtraPsi(P, Psi, NotOrthogonal);
 | 
|---|
 | 965 |   // exclude the minimised Psi
 | 
|---|
 | 966 |   SetGramSchActualPsi(P, Psi, NotUsedToOrtho);
 | 
|---|
 | 967 |   SpeedMeasure(P, GramSchTime, StartTimeDo);
 | 
|---|
 | 968 |   // makes conjugate gradient orthogonal to all other orbits
 | 
|---|
 | 969 |   //fprintf(stderr,"CalculateCGGradient: GramSch() for extra orbital\n");
 | 
|---|
 | 970 |   GramSch(P, LevS, Psi, Orthogonalize);
 | 
|---|
 | 971 |   SpeedMeasure(P, GramSchTime, StopTimeDo);
 | 
|---|
 | 972 |   //if (grad != P->Grad.GradientArray[ActualGradient]) Error(SomeError,"FindPerturbedMinimum: grad corrupted");
 | 
|---|
 | 973 |   memcpy(grad, GradOrtho, ElementSize*LevS->MaxG*sizeof(double));
 | 
|---|
 | 974 |   //memcpy(PCOrtho, GradOrtho, ElementSize*LevS->MaxG*sizeof(double));
 | 
|---|
 | 975 | 
 | 
|---|
 | 976 |   // PRE-CONDITION-GRADIENT
 | 
|---|
 | 977 |   //if (fabs(T) < MYEPSILON) T = 1;
 | 
|---|
 | 978 |   T = 0.;
 | 
|---|
 | 979 |   for (i=0;i<Num;i++)
 | 
|---|
 | 980 |     T += Psi->lambda[i][i];
 | 
|---|
 | 981 |   for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
 | 982 |     x = .5*LevS->GArray[g].GSq;
 | 
|---|
 | 983 |     // FIXME: Good way of accessing reciprocal Lev0 Density coefficients on LevS! (not so trivial)  
 | 
|---|
 | 984 |     //x += sqrt(Dens->DensityCArray[HGDensity][g].re*Dens->DensityCArray[HGDensity][g].re+Dens->DensityCArray[HGDensity][g].im*Dens->DensityCArray[HGDensity][g].im);
 | 
|---|
 | 985 |     x -= T/(double)Num;
 | 
|---|
 | 986 |     K = x/(x*x+stay_above*stay_above);
 | 
|---|
 | 987 |     //if (PCOrtho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: PCOrtho corrupted");
 | 
|---|
 | 988 |     c_re(PCOrtho[g]) = K*c_re(grad[g]);
 | 
|---|
 | 989 |     c_im(PCOrtho[g]) = K*c_im(grad[g]);  
 | 
|---|
 | 990 |   }
 | 
|---|
 | 991 |   SetGramSchExtraPsi(P, Psi, NotOrthogonal);
 | 
|---|
 | 992 |   SpeedMeasure(P, GramSchTime, StartTimeDo);
 | 
|---|
 | 993 |   // preconditioned direction is orthogonalized
 | 
|---|
 | 994 |   //fprintf(stderr,"CalculatePreConGrad: GramSch() for extra orbital\n");
 | 
|---|
 | 995 |   GramSch(P, LevS, Psi, Orthogonalize);
 | 
|---|
 | 996 |   SpeedMeasure(P, GramSchTime, StopTimeDo);
 | 
|---|
 | 997 |   //if (PCgrad != P->Grad.GradientArray[PreConGradient]) Error(SomeError,"FindPerturbedMinimum: PCgrad corrupted");
 | 
|---|
 | 998 |   memcpy(PCgrad, PCOrtho, ElementSize*LevS->MaxG*sizeof(double));
 | 
|---|
 | 999 | 
 | 
|---|
 | 1000 |   //debug(P, "Before ConDir");
 | 
|---|
 | 1001 |   //fprintf(stderr,"|(%i)|^2 = %lg\t |PCgrad|^2 = %lg\t |PCgrad,(%i)| = %lg\n", R->ActualLocalPsiNo, GradSP(P,LevS,source,source),GradSP(P,LevS,PCgrad,PCgrad), R->ActualLocalPsiNo, GradSP(P,LevS,PCgrad,source));
 | 
|---|
 | 1002 |   // CONJUGATE-GRADIENT
 | 
|---|
 | 1003 |   LocalSP = GradSP(P, LevS, PCgrad, grad);
 | 
|---|
 | 1004 |   MPI_Allreduce ( &LocalSP, &PsiSP, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 1005 |   *GammaDiv = dS[0] = PsiSP;
 | 
|---|
 | 1006 |   dS[1] = GammaDivOld;
 | 
|---|
 | 1007 |   S[0]=dS[0]; S[1]=dS[1];
 | 
|---|
 | 1008 |   /*MPI_Allreduce ( dS, S, 2, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT);*/
 | 
|---|
 | 1009 |   if (step) { // only in later steps is the scalar product used, but always condir stored in oldcondir and Ortho (working gradient)
 | 
|---|
 | 1010 |     if (fabs(S[1]) < MYEPSILON) fprintf(stderr,"CalculateConDir: S[1] = %lg\n",S[1]);
 | 
|---|
 | 1011 |     Gamma = S[0]/S[1];
 | 
|---|
 | 1012 |     if (fabs(S[1]) < MYEPSILON) {
 | 
|---|
 | 1013 |       if (fabs(S[0]) < MYEPSILON)  
 | 
|---|
 | 1014 |         Gamma = 1.0;
 | 
|---|
 | 1015 |       else
 | 
|---|
 | 1016 |         Gamma = 0.0;
 | 
|---|
 | 1017 |     }
 | 
|---|
 | 1018 |     for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
 | 1019 |       //if (ConDir != P->Grad.GradientArray[ConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
 | 
|---|
 | 1020 |       c_re(ConDir[g]) = c_re(PCgrad[g]) + Gamma*c_re(ConDir_old[g]);
 | 
|---|
 | 1021 |       c_im(ConDir[g]) = c_im(PCgrad[g]) + Gamma*c_im(ConDir_old[g]);
 | 
|---|
 | 1022 |       //if (ConDir_old != P->Grad.GradientArray[OldConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir_old corrupted");
 | 
|---|
 | 1023 |       c_re(ConDir_old[g]) = c_re(ConDir[g]);
 | 
|---|
 | 1024 |       c_im(ConDir_old[g]) = c_im(ConDir[g]);
 | 
|---|
 | 1025 |       //if (Ortho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: Ortho corrupted");
 | 
|---|
 | 1026 |       c_re(Ortho[g]) = c_re(ConDir[g]);
 | 
|---|
 | 1027 |       c_im(Ortho[g]) = c_im(ConDir[g]);
 | 
|---|
 | 1028 |     }
 | 
|---|
 | 1029 |   } else {
 | 
|---|
 | 1030 |     Gamma = 0.0;
 | 
|---|
 | 1031 |     for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
 | 1032 |       //if (ConDir != P->Grad.GradientArray[ConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
 | 
|---|
 | 1033 |       c_re(ConDir[g]) = c_re(PCgrad[g]);
 | 
|---|
 | 1034 |       c_im(ConDir[g]) = c_im(PCgrad[g]);
 | 
|---|
 | 1035 |       //if (ConDir_old != P->Grad.GradientArray[OldConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir_old corrupted");
 | 
|---|
 | 1036 |       c_re(ConDir_old[g]) = c_re(ConDir[g]);
 | 
|---|
 | 1037 |       c_im(ConDir_old[g]) = c_im(ConDir[g]);
 | 
|---|
 | 1038 |       //if (Ortho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: Ortho corrupted");
 | 
|---|
 | 1039 |       c_re(Ortho[g]) = c_re(ConDir[g]);
 | 
|---|
 | 1040 |       c_im(Ortho[g]) = c_im(ConDir[g]);
 | 
|---|
 | 1041 |     }
 | 
|---|
 | 1042 |   }
 | 
|---|
 | 1043 |   // orthonormalize
 | 
|---|
 | 1044 |   SetGramSchExtraPsi(P, Psi, NotOrthogonal);
 | 
|---|
 | 1045 |   SpeedMeasure(P, GramSchTime, StartTimeDo);
 | 
|---|
 | 1046 |   //fprintf(stderr,"CalculateConDir: GramSch() for extra orbital\n");
 | 
|---|
 | 1047 |   GramSch(P, LevS, Psi, Orthogonalize);
 | 
|---|
 | 1048 |   SpeedMeasure(P, GramSchTime, StopTimeDo);
 | 
|---|
 | 1049 |   //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
 | 
|---|
 | 1050 |   memcpy(ConDir, Ortho, ElementSize*LevS->MaxG*sizeof(double));
 | 
|---|
 | 1051 |   //debug(P, "Before LineSearch");
 | 
|---|
 | 1052 |   //fprintf(stderr,"|(%i)|^2 = %lg\t |ConDir|^2 = %lg\t |ConDir,(%i)| = %lg\n", R->ActualLocalPsiNo, GradSP(P,LevS,source,source),GradSP(P,LevS,ConDir,ConDir), R->ActualLocalPsiNo, GradSP(P,LevS,ConDir,source));
 | 
|---|
 | 1053 |   SetGramSchActualPsi(P, Psi, IsOrthogonal);
 | 
|---|
 | 1054 |     
 | 
|---|
 | 1055 |   //fprintf(stderr,"(%i) Testing conjugate gradient for Orthogonality ...\n", P->Par.me);
 | 
|---|
 | 1056 |   //TestForOrth(P,LevS,ConDir);
 | 
|---|
 | 1057 | 
 | 
|---|
 | 1058 |   // ONE-DIMENSIONAL LINE-SEARCH
 | 
|---|
 | 1059 | 
 | 
|---|
 | 1060 |   // ========= dE / dt | 0 ============
 | 
|---|
 | 1061 |   p = Lat->Psi.TypeStartIndex[Occupied] + (R->ActualLocalPsiNo - Lat->Psi.TypeStartIndex[R->CurrentMin]);
 | 
|---|
 | 1062 |   //if (Hc_grad != P->Grad.GradientArray[HcGradient]) Error(SomeError,"FindPerturbedMinimum: Hc_grad corrupted");
 | 
|---|
 | 1063 |   //if (H1c_grad != P->Grad.GradientArray[H1cGradient]) Error(SomeError,"FindPerturbedMinimum: H1c_grad corrupted");
 | 
|---|
 | 1064 |   d[0] = Calculate1stPerturbedDerivative(P, LevS->LPsi->LocalPsi[p], source, ConDir, Hc_grad, H1c_grad);
 | 
|---|
 | 1065 |   //CalculateConDirHConDir(P, ConDir, PsiFactor, &d[1], &d[2], &d[3]);
 | 
|---|
 | 1066 |   //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
 | 
|---|
 | 1067 |   CalculateCDfnl(P, ConDir, PP->CDfnl); // calculate needed non-local form factors
 | 
|---|
 | 1068 |   //if (HConDir != Dens->DensityCArray[ActualDensity]) Error(SomeError,"FindPerturbedMinimum: HConDir corrupted");
 | 
|---|
 | 1069 |   SetArrayToDouble0((double *)HConDir,Dens->TotalSize*2);
 | 
|---|
 | 1070 |   //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
 | 
|---|
 | 1071 |   ApplyTotalHamiltonian(P,ConDir,HConDir, PP->CDfnl, PsiFactor, 0); // applies H^(0) with total perturbed density!
 | 
|---|
 | 1072 |   d[1] = GradSP(P,LevS,ConDir,HConDir);
 | 
|---|
 | 1073 |   d[2] = GradSP(P,LevS,ConDir,ConDir);
 | 
|---|
 | 1074 |   d[3] = 0.;
 | 
|---|
 | 1075 | 
 | 
|---|
 | 1076 |   // gather results  
 | 
|---|
 | 1077 |   MPI_Allreduce ( &d, &D, 4, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 1078 |   // ========== ddE / ddt | 0 =========
 | 
|---|
 | 1079 |   dEdt0 = D[0];
 | 
|---|
 | 1080 |   for (i=MAXOLD-1; i > 0; i--)
 | 
|---|
 | 1081 |     En->dEdt0[i] = En->dEdt0[i-1];
 | 
|---|
 | 1082 |   En->dEdt0[0] = dEdt0;
 | 
|---|
 | 1083 |   ConDirHConDir = D[1];
 | 
|---|
 | 1084 |   ConDirConDir = D[2];
 | 
|---|
 | 1085 |   ddEddt0 = 0.0;
 | 
|---|
 | 1086 |   //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
 | 
|---|
 | 1087 |   //if (H1c_grad != P->Grad.GradientArray[H1cGradient]) Error(SomeError,"FindPerturbedMinimum: H1c_grad corrupted");
 | 
|---|
 | 1088 |   ddEddt0 = Calculate2ndPerturbedDerivative(P, LevS->LPsi->LocalPsi[p], source, ConDir, Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda * Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor, ConDirHConDir, ConDirConDir);
 | 
|---|
 | 1089 | 
 | 
|---|
 | 1090 |   for (i=MAXOLD-1; i > 0; i--)
 | 
|---|
 | 1091 |     En->ddEddt0[i] = En->ddEddt0[i-1];
 | 
|---|
 | 1092 |   En->ddEddt0[0] = ddEddt0;
 | 
|---|
 | 1093 |   E0 = En->TotalEnergy[0];
 | 
|---|
 | 1094 |   // delta
 | 
|---|
 | 1095 |   //if (isnan(E0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): E0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
 | 1096 |   //if (isnan(dEdt0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): dEdt0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
 | 1097 |   //if (isnan(ddEddt0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): ddEddt0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
 | 1098 | 
 | 
|---|
 | 1099 |   ////deltaI = CalculateDeltaI(E0, dEdt0, ddEddt0, 
 | 
|---|
 | 1100 |   ////      &EI, &dEI, &ddEI, &dcosI, &dsinI);
 | 
|---|
 | 1101 |   ////delta = deltaI; E = EI; dE = dEI; ddE = ddEI; dcos = dcosI; dsin = dsinI;
 | 
|---|
 | 1102 |   if (ddEddt0 > 0) {
 | 
|---|
 | 1103 |     delta = - dEdt0/ddEddt0;
 | 
|---|
 | 1104 |     E = E0 + delta * dEdt0 + delta*delta/2. * ddEddt0;
 | 
|---|
 | 1105 |   } else {
 | 
|---|
 | 1106 |     delta = 0.;
 | 
|---|
 | 1107 |     E = E0;
 | 
|---|
 | 1108 |     fprintf(stderr,"(%i) Taylor approximation leads not to minimum!\n",P->Par.me);
 | 
|---|
 | 1109 |   } 
 | 
|---|
 | 1110 | 
 | 
|---|
 | 1111 |   // shift energy delta values
 | 
|---|
 | 1112 |   for (i=MAXOLD-1; i > 0; i--) {
 | 
|---|
 | 1113 |     En->delta[i] = En->delta[i-1];
 | 
|---|
 | 1114 |     En->ATE[i] = En->ATE[i-1];
 | 
|---|
 | 1115 |   }
 | 
|---|
 | 1116 |   // store new one
 | 
|---|
 | 1117 |   En->delta[0] = delta;
 | 
|---|
 | 1118 |   En->ATE[0] = E;
 | 
|---|
 | 1119 |   if (En->TotalEnergy[1] != 0.)
 | 
|---|
 | 1120 |     Diff = fabs(En->TotalEnergy[1] - E0)/(En->TotalEnergy[1] - E0)*fabs((E0 - En->ATE[1])/E0);
 | 
|---|
 | 1121 |   else
 | 
|---|
 | 1122 |     Diff = 0.;
 | 
|---|
 | 1123 |   R->Diffcount += pow(Diff,2);
 | 
|---|
 | 1124 |   
 | 
|---|
 | 1125 |   // reinstate actual density (only needed for UpdateDensityCalculation) ... 
 | 
|---|
 | 1126 |   //CalculateOneDensityR(Lat, LevS, Dens, source, Dens->DensityArray[ActualDensity], R->FactorDensityR*Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor, 1);
 | 
|---|
 | 1127 |   // ... before changing actual local Psi  
 | 
|---|
 | 1128 |   for (g = 0; g < LevS->MaxG; g++) {  // Here all coefficients are updated for the new found wave function
 | 
|---|
 | 1129 |     //if (isnan(ConDir[g].re)) { fprintf(stderr,"WARNGING: CalculateLineSearch(): ConDir_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
 | 1130 |     //if (source != LevS->LPsi->LocalPsi[R->ActualLocalPsiNo] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: source corrupted");
 | 
|---|
 | 1131 |     ////c_re(source[g]) = c_re(source[g])*dcos + c_re(ConDir[g])*dsin;
 | 
|---|
 | 1132 |     ////c_im(source[g]) = c_im(source[g])*dcos + c_im(ConDir[g])*dsin;
 | 
|---|
 | 1133 |     c_re(source[g]) = c_re(source[g]) + c_re(ConDir[g])*delta;
 | 
|---|
 | 1134 |     c_im(source[g]) = c_im(source[g]) + c_im(ConDir[g])*delta;
 | 
|---|
 | 1135 |   }
 | 
|---|
 | 1136 |   if (P->Call.out[StepLeaderOut]) {
 | 
|---|
 | 1137 |     fprintf(stderr, "(%i,%i,%i)S(%i,%i,%i):\tTE: %e\tATE: %e\t Diff: %e\t --- d: %e\tdEdt0: %e\tddEddt0: %e\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, E0, E, Diff,delta, dEdt0, ddEddt0);
 | 
|---|
 | 1138 |     //fprintf(stderr, "(%i,%i,%i)S(%i,%i,%i):\tp0: %e p1: %e p2: %e \tATE: %e\t Diff: %e\t --- d: %e\tdEdt0: %e\tddEddt0: %e\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, En->parts[0], En->parts[1], En->parts[2], E, Diff,delta, dEdt0, ddEddt0);
 | 
|---|
 | 1139 |   }
 | 
|---|
 | 1140 |   if (P->Par.me == 0) {
 | 
|---|
 | 1141 |     fprintf(F->MinimisationFile, "%i\t%i\t%i\t%e\t%e\t%e\t%e\t%e\n",R->MinStep, R->ActualLocalPsiNo, R->PsiStep, E0, E, delta, dEdt0, ddEddt0);
 | 
|---|
 | 1142 |     fflush(F->MinimisationFile);
 | 
|---|
 | 1143 |   }
 | 
|---|
 | 1144 | }
 | 
|---|
 | 1145 | 
 | 
|---|
 | 1146 | /** Applies perturbation operator \f$\nabla_{index}\f$ to \a *source.
 | 
|---|
 | 1147 |  * As wave functions are stored in the reciprocal basis set, the application is straight-forward,
 | 
|---|
 | 1148 |  * for every G vector, the by \a index specified component is multiplied with the respective
 | 
|---|
 | 1149 |  * coefficient. Afterwards, 1/i is applied by flipping real and imaginary components (and an additional minus sign on the new imaginary term).
 | 
|---|
 | 1150 |  * \param *P Problem at hand
 | 
|---|
 | 1151 |  * \param *source complex coefficients of wave function \f$\varphi(G)\f$
 | 
|---|
 | 1152 |  * \param *dest returned complex coefficients of wave function \f$\widehat{p}_{index}|\varphi(G)\f$
 | 
|---|
 | 1153 |  * \param index_g vectorial index of operator to be applied
 | 
|---|
 | 1154 |  */
 | 
|---|
 | 1155 | void CalculatePerturbationOperator_P(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const int index_g)
 | 
|---|
 | 1156 | {
 | 
|---|
 | 1157 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1158 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 1159 |   //const fftw_complex *dest_bak = dest;
 | 
|---|
 | 1160 |   int g = 0;
 | 
|---|
 | 1161 |   if (LevS->GArray[0].GSq == 0.0) {
 | 
|---|
 | 1162 |     //if (dest != dest_bak) Error(SomeError,"CalculatePerturbationOperator_P: dest corrupted");
 | 
|---|
 | 1163 |     dest[0].re =  LevS->GArray[0].G[index_g]*source[0].im;
 | 
|---|
 | 1164 |     dest[0].im = -LevS->GArray[0].G[index_g]*source[0].re; 
 | 
|---|
 | 1165 |     g++;
 | 
|---|
 | 1166 |   }
 | 
|---|
 | 1167 |   for (;g<LevS->MaxG;g++) {
 | 
|---|
 | 1168 |     //if (dest != dest_bak || g<0 || g>=LevS->MaxG) Error(SomeError,"CalculatePerturbationOperator_P: g out of range");
 | 
|---|
 | 1169 |     dest[g].re =  LevS->GArray[g].G[index_g]*source[g].im;
 | 
|---|
 | 1170 |     dest[g].im = -LevS->GArray[g].G[index_g]*source[g].re;
 | 
|---|
 | 1171 |   }
 | 
|---|
 | 1172 |   // don't put dest[0].im = 0! Otherwise real parts of perturbed01/10 are not the same anymore!
 | 
|---|
 | 1173 | }
 | 
|---|
 | 1174 | 
 | 
|---|
 | 1175 | /** Applies perturbation operator \f$\widehat{r}_{index}\f$ to \a *source.
 | 
|---|
 | 1176 |  * The \a *source wave function is blown up onto upper level LatticeLevel RunStruct#Lev0, fourier
 | 
|---|
 | 1177 |  * transformed. Afterwards, for each point on the real mesh the coefficient is multiplied times the real
 | 
|---|
 | 1178 |  * vector pointing within the cell to the mesh point, yet on LatticeLevel RunStruct#LevS. The new wave
 | 
|---|
 | 1179 |  * function is inverse fourier transformed and the resulting reciprocal coefficients stored in *dest.
 | 
|---|
 | 1180 |  * \param *P Problem at hand
 | 
|---|
 | 1181 |  * \param *source source coefficients
 | 
|---|
 | 1182 |  * \param *source2 second source coefficients, e.g. in the evaluation of a scalar product
 | 
|---|
 | 1183 |  * \param *dest destination coefficienta array, is overwrittten!
 | 
|---|
 | 1184 |  * \param index_r index of real vector.
 | 
|---|
 | 1185 |  * \param wavenr index of respective PsiTypeTag#Occupied(!) OnePsiElementAddData for the needed Wanner centre of the wave function.
 | 
|---|
 | 1186 |  */
 | 
|---|
 | 1187 | void CalculatePerturbationOperator_R(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const fftw_complex *source2, const int index_r, const int wavenr)
 | 
|---|
 | 1188 | {
 | 
|---|
 | 1189 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 1190 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1191 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 1192 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 1193 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 1194 |   struct fft_plan_3d *plan = Lat->plan;
 | 
|---|
 | 1195 |   fftw_complex *TempPsi = Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 1196 |   fftw_real *TempPsiR = (fftw_real *) TempPsi;
 | 
|---|
 | 1197 |   fftw_complex *workC = Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 1198 |   fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
 | 1199 |   fftw_real *PsiCR = (fftw_real *) PsiC;
 | 
|---|
 | 1200 |   fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityArray[TempDensity];
 | 
|---|
 | 1201 |   fftw_complex *posfac, *destsnd, *destrcv;
 | 
|---|
 | 1202 |   double x[NDIM], fac[NDIM], Wcentre[NDIM];
 | 
|---|
 | 1203 |   const int k_normal = Lat->Psi.TypeStartIndex[Occupied] + (wavenr - Lat->Psi.TypeStartIndex[R->CurrentMin]);
 | 
|---|
 | 1204 |   int n[NDIM], n0, g, Index, pos, iS, i0;
 | 
|---|
 | 1205 |   int N[NDIM], NUp[NDIM];
 | 
|---|
 | 1206 |   const int N0 = LevS->Plan0.plan->local_nx;
 | 
|---|
 | 1207 |   N[0] = LevS->Plan0.plan->N[0];
 | 
|---|
 | 1208 |   N[1] = LevS->Plan0.plan->N[1];
 | 
|---|
 | 1209 |   N[2] = LevS->Plan0.plan->N[2];
 | 
|---|
 | 1210 |   NUp[0] = LevS->NUp[0]; 
 | 
|---|
 | 1211 |   NUp[1] = LevS->NUp[1]; 
 | 
|---|
 | 1212 |   NUp[2] = LevS->NUp[2]; 
 | 
|---|
 | 1213 |   Wcentre[0] = Lat->Psi.AddData[k_normal].WannierCentre[0];
 | 
|---|
 | 1214 |   Wcentre[1] = Lat->Psi.AddData[k_normal].WannierCentre[1];
 | 
|---|
 | 1215 |   Wcentre[2] = Lat->Psi.AddData[k_normal].WannierCentre[2];
 | 
|---|
 | 1216 |   // init pointers and values
 | 
|---|
 | 1217 |   const int myPE = P->Par.me_comm_ST_Psi;
 | 
|---|
 | 1218 |   const double FFTFactor = 1./LevS->MaxN; 
 | 
|---|
 | 1219 |   double vector;
 | 
|---|
 | 1220 |   //double result, Result;
 | 
|---|
 | 1221 | 
 | 
|---|
 | 1222 |   // blow up source coefficients
 | 
|---|
 | 1223 |   LockDensityArray(Dens0,TempDensity,real); // tempdestRC
 | 
|---|
 | 1224 |   LockDensityArray(Dens0,Temp2Density,imag); // TempPsi
 | 
|---|
 | 1225 |   LockDensityArray(Dens0,ActualPsiDensity,imag); // PsiC
 | 
|---|
 | 1226 |   //if (tempdestRC != (fftw_complex *)Dens0->DensityArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: tempdestRC corrupted");
 | 
|---|
 | 1227 |   SetArrayToDouble0((double *)tempdestRC ,Dens0->TotalSize*2);
 | 
|---|
 | 1228 |   //if (TempPsi != Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculatePerturbationOperator_R: TempPsi corrupted");
 | 
|---|
 | 1229 |   SetArrayToDouble0((double *)TempPsi ,Dens0->TotalSize*2);
 | 
|---|
 | 1230 |   //if (PsiC != Dens0->DensityCArray[ActualPsiDensity]) Error(SomeError,"CalculatePerturbationOperator_R: PsiC corrupted");
 | 
|---|
 | 1231 |   SetArrayToDouble0((double *)PsiC,Dens0->TotalSize*2);
 | 
|---|
 | 1232 |   for (g=0; g<LevS->MaxG; g++) {
 | 
|---|
 | 1233 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 1234 |     posfac = &LevS->PosFactorUp[LevS->MaxNUp*g];
 | 
|---|
 | 1235 |     destrcv = &tempdestRC[LevS->MaxNUp*Index]; 
 | 
|---|
 | 1236 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 1237 |       //if (destrcv != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->LocalSizeC) Error(SomeError,"CalculatePerturbationOperator_R: destrcv corrupted");
 | 
|---|
 | 1238 |       destrcv [pos].re = (( source[g].re)*posfac[pos].re-(source[g].im)*posfac[pos].im);
 | 
|---|
 | 1239 |       destrcv [pos].im = (( source[g].re)*posfac[pos].im+(source[g].im)*posfac[pos].re);
 | 
|---|
 | 1240 |     }
 | 
|---|
 | 1241 |   }
 | 
|---|
 | 1242 |   for (g=0; g<LevS->MaxDoubleG; g++) {
 | 
|---|
 | 1243 |     destsnd  = &tempdestRC [LevS->DoubleG[2*g]*LevS->MaxNUp];
 | 
|---|
 | 1244 |     destrcv  = &tempdestRC [LevS->DoubleG[2*g+1]*LevS->MaxNUp];
 | 
|---|
 | 1245 |     for (pos=0; pos<LevS->MaxNUp; pos++) {
 | 
|---|
 | 1246 |       //if (destrcv != &tempdestRC [LevS->DoubleG[2*g+1]*LevS->MaxNUp] || LevS->DoubleG[2*g]*LevS->MaxNUp+pos<0 || LevS->DoubleG[2*g]*LevS->MaxNUp+pos>=Dens0->LocalSizeC|| LevS->DoubleG[2*g+1]*LevS->MaxNUp+pos<0 || LevS->DoubleG[2*g+1]*LevS->MaxNUp+pos>=Dens0->LocalSizeC) Error(SomeError,"CalculatePerturbationOperator_R: destrcv corrupted");
 | 
|---|
 | 1247 |       destrcv [pos].re =  destsnd [pos].re;
 | 
|---|
 | 1248 |       destrcv [pos].im = -destsnd [pos].im;
 | 
|---|
 | 1249 |     }    
 | 
|---|
 | 1250 |   }  
 | 
|---|
 | 1251 |   // fourier transform blown up wave function
 | 
|---|
 | 1252 |   //if (tempdestRC != (fftw_complex *)Dens0->DensityArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: tempdestRC corrupted");
 | 
|---|
 | 1253 |   //if (workC != Dens0->DensityCArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: workC corrupted");
 | 
|---|
 | 1254 |   fft_3d_complex_to_real(plan,LevS->LevelNo, FFTNFUp, tempdestRC , workC);
 | 
|---|
 | 1255 |   //if (tempdestRC != (fftw_complex *)Dens0->DensityArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: tempdestRC corrupted");
 | 
|---|
 | 1256 |   //if (TempPsiR != (fftw_real *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculatePerturbationOperator_R: TempPsiR corrupted");
 | 
|---|
 | 1257 |   DensityRTransformPos(LevS,(fftw_real*)tempdestRC ,TempPsiR );
 | 
|---|
 | 1258 |   UnLockDensityArray(Dens0,TempDensity,real); // TempdestRC
 | 
|---|
 | 1259 |  
 | 
|---|
 | 1260 |   //result = 0.;
 | 
|---|
 | 1261 |   // for every point on the real grid multiply with component of position vector
 | 
|---|
 | 1262 |   for (n0=0; n0<N0; n0++)
 | 
|---|
 | 1263 |     for (n[1]=0; n[1]<N[1]; n[1]++)
 | 
|---|
 | 1264 |       for (n[2]=0; n[2]<N[2]; n[2]++) {
 | 
|---|
 | 1265 |         n[0] = n0 + N0 * myPE;
 | 
|---|
 | 1266 |         fac[0] = (double)(n[0])/(double)((N[0]));
 | 
|---|
 | 1267 |         fac[1] = (double)(n[1])/(double)((N[1]));
 | 
|---|
 | 1268 |         fac[2] = (double)(n[2])/(double)((N[2]));
 | 
|---|
 | 1269 |         RMat33Vec3(x,Lat->RealBasis,fac);
 | 
|---|
 | 1270 |         iS = n[2] + N[2]*(n[1] + N[1]*n0);  // mind splitting of x axis due to multiple processes
 | 
|---|
 | 1271 |         i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
 | 
|---|
 | 1272 |         //PsiCR[iS] = ((double)n[0]/(double)N[0]*Lat->RealBasis[0] - fabs(Wcentre[0]))*TempPsiR[i0] - ((double)n[1]/(double)N[1]*Lat->RealBasis[4] - fabs(Wcentre[1]))*TempPsi2R[i0];
 | 
|---|
 | 1273 |         //fprintf(stderr,"(%i) R[%i] = (%lg,%lg,%lg)\n",P->Par.me, i0, x[0], x[1], x[2]);
 | 
|---|
 | 1274 |         //else fprintf(stderr,"(%i) WCentre[%i] = %e \n",P->Par.me, index_r, Wcentre[index_r]);
 | 
|---|
 | 1275 |         vector = sawtooth(Lat,MinImageConv(Lat,x[index_r],Wcentre[index_r],index_r),index_r);
 | 
|---|
 | 1276 |         //vector = 1.;//sin((double)(n[index_r])/(double)((N[index_r]))*2*PI);      
 | 
|---|
 | 1277 |          PsiCR[iS] = vector * TempPsiR[i0];
 | 
|---|
 | 1278 |         //fprintf(stderr,"(%i) vector(%i/%i,%i/%i,%i/%i): %lg\tx[%i] = %e\tWcentre[%i] = %e\tTempPsiR[%i] = %e\tPsiCR[%i] = %e\n",P->Par.me, n[0], N[0], n[1], N[1], n[2], N[2], vector, index_r, x[index_r],index_r, Wcentre[index_r],i0,TempPsiR[i0],iS,PsiCR[iS]);
 | 
|---|
 | 1279 |          
 | 
|---|
 | 1280 |         //truedist(Lat,x[cross(index_r,2)],Wcentre[cross(index_r,2)],cross(index_r,2)) * TempPsiR[i0]; 
 | 
|---|
 | 1281 |         //tmp += truedist(Lat,x[index_r],WCentre[index_r],index_r) * RealPhiR[i0];
 | 
|---|
 | 1282 |         //tmp += sawtooth(Lat,truedist(Lat,x[index_r],WCentre[index_r],index_r), index_r)*RealPhiR[i0];
 | 
|---|
 | 1283 |         //(Fehler mit falschem Ort ist vor dieser Stelle!): ueber result =  RealPhiR[i0] * (x[index_r]) * RealPhiR[i0]; gecheckt
 | 
|---|
 | 1284 |         //result += TempPsiR[i0] * PsiCR[iS];
 | 
|---|
 | 1285 |       }
 | 
|---|
 | 1286 |   UnLockDensityArray(Dens0,Temp2Density,imag); // TempPsi
 | 
|---|
 | 1287 |   //MPI_Allreduce( &result, &Result, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 1288 |   //if (P->Par.me == 0) fprintf(stderr,"(%i) PerturbationOpertator_R: %e\n",P->Par.me, Result/LevS->MaxN);
 | 
|---|
 | 1289 |   // inverse fourier transform 
 | 
|---|
 | 1290 |   fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, workC);
 | 
|---|
 | 1291 |   //fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, Psi2C, workC);
 | 
|---|
 | 1292 |   
 | 
|---|
 | 1293 |   // copy to destination array
 | 
|---|
 | 1294 |   for (g=0; g<LevS->MaxG; g++) {
 | 
|---|
 | 1295 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 1296 |     dest[g].re = ( PsiC[Index].re)*FFTFactor; 
 | 
|---|
 | 1297 |     dest[g].im = ( PsiC[Index].im)*FFTFactor;
 | 
|---|
 | 1298 |   }
 | 
|---|
 | 1299 |   UnLockDensityArray(Dens0,ActualPsiDensity,imag);  //PsiC
 | 
|---|
 | 1300 |   //if (LevS->GArray[0].GSq == 0)
 | 
|---|
 | 1301 |   //  dest[0].im = 0; // imaginary of G=0 is zero
 | 
|---|
 | 1302 | }
 | 
|---|
 | 1303 | /*
 | 
|---|
 | 1304 | {
 | 
|---|
 | 1305 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1306 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 1307 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 1308 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 1309 |   struct fft_plan_3d *plan = Lat->plan;
 | 
|---|
 | 1310 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 1311 |   fftw_complex *tempdestRC =  Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 1312 |   fftw_real *tempdestR = (fftw_real *) tempdestRC;
 | 
|---|
 | 1313 |   fftw_complex *work =  Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 1314 |   fftw_complex *PsiC = (fftw_complex *) Dens0->DensityCArray[ActualPsiDensity];;
 | 
|---|
 | 1315 |   fftw_real *PsiCR = (fftw_real *)  PsiC;
 | 
|---|
 | 1316 |   fftw_real *RealPhiR = (fftw_real *) Dens0->DensityArray[Temp2Density];
 | 
|---|
 | 1317 |   fftw_complex *posfac, *destsnd, *destrcv;
 | 
|---|
 | 1318 |   double x[NDIM], fac[NDIM], WCentre[NDIM];
 | 
|---|
 | 1319 |   int n[NDIM], N0, n0, g, Index, pos, iS, i0;
 | 
|---|
 | 1320 | 
 | 
|---|
 | 1321 |   // init pointers and values
 | 
|---|
 | 1322 |   int myPE = P->Par.me_comm_ST_Psi;
 | 
|---|
 | 1323 |   double FFTFactor = 1./LevS->MaxN; 
 | 
|---|
 | 1324 |   int N[NDIM], NUp[NDIM];
 | 
|---|
 | 1325 |   N[0] = LevS->Plan0.plan->N[0];
 | 
|---|
 | 1326 |   N[1] = LevS->Plan0.plan->N[1];
 | 
|---|
 | 1327 |   N[2] = LevS->Plan0.plan->N[2];
 | 
|---|
 | 1328 |   NUp[0] = LevS->NUp[0]; 
 | 
|---|
 | 1329 |   NUp[1] = LevS->NUp[1]; 
 | 
|---|
 | 1330 |   NUp[2] = LevS->NUp[2]; 
 | 
|---|
 | 1331 |   N0 = LevS->Plan0.plan->local_nx;
 | 
|---|
 | 1332 |   wavenr = Lat->Psi.TypeStartIndex[Occupied] + (wavenr - Lat->Psi.TypeStartIndex[R->CurrentMin]);
 | 
|---|
 | 1333 |   Wcentre[0] = Lat->Psi.AddData[wavenr].WannierCentre[0];
 | 
|---|
 | 1334 |   Wcentre[1] = Lat->Psi.AddData[wavenr].WannierCentre[1];
 | 
|---|
 | 1335 |   Wcentre[2] = Lat->Psi.AddData[wavenr].WannierCentre[2];
 | 
|---|
 | 1336 |   
 | 
|---|
 | 1337 |   // blow up source coefficients
 | 
|---|
 | 1338 |   SetArrayToDouble0((double *)tempdestRC,Dens0->TotalSize*2);
 | 
|---|
 | 1339 |   SetArrayToDouble0((double *)RealPhiR,Dens0->TotalSize*2);
 | 
|---|
 | 1340 |   SetArrayToDouble0((double *)PsiC,Dens0->TotalSize*2);
 | 
|---|
 | 1341 |   for (g=0; g<LevS->MaxG; g++) {
 | 
|---|
 | 1342 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 1343 |     posfac = &LevS->PosFactorUp[LevS->MaxNUp*g];
 | 
|---|
 | 1344 |     destrcv = &tempdestRC[LevS->MaxNUp*Index]; 
 | 
|---|
 | 1345 |     for (pos=0; pos<LevS->MaxNUp; pos++) {
 | 
|---|
 | 1346 |       destrcv[pos].re = (( source[g].re)*posfac[pos].re-( source[g].im)*posfac[pos].im);
 | 
|---|
 | 1347 |       destrcv[pos].im = (( source[g].re)*posfac[pos].im+( source[g].im)*posfac[pos].re);
 | 
|---|
 | 1348 |     }
 | 
|---|
 | 1349 |   }
 | 
|---|
 | 1350 |   for (g=0; g<LevS->MaxDoubleG; g++) {
 | 
|---|
 | 1351 |     destsnd = &tempdestRC[LevS->DoubleG[2*g]*LevS->MaxNUp];
 | 
|---|
 | 1352 |     destrcv = &tempdestRC[LevS->DoubleG[2*g+1]*LevS->MaxNUp];
 | 
|---|
 | 1353 |     for (pos=0; pos<LevS->MaxNUp; pos++) {
 | 
|---|
 | 1354 |       destrcv[pos].re =  destsnd[pos].re;
 | 
|---|
 | 1355 |       destrcv[pos].im = -destsnd[pos].im;
 | 
|---|
 | 1356 |     }    
 | 
|---|
 | 1357 |   }
 | 
|---|
 | 1358 |   
 | 
|---|
 | 1359 |   // fourier transform blown up wave function
 | 
|---|
 | 1360 |   fft_3d_complex_to_real(plan,LevS->LevelNo, FFTNFUp, tempdestRC, work);
 | 
|---|
 | 1361 |   DensityRTransformPos(LevS,tempdestR,RealPhiR);
 | 
|---|
 | 1362 | 
 | 
|---|
 | 1363 |   //fft_Psi(P,source,RealPhiR,0,0);
 | 
|---|
 | 1364 |   
 | 
|---|
 | 1365 |   // for every point on the real grid multiply with component of position vector
 | 
|---|
 | 1366 |   for (n0=0; n0<N0; n0++)
 | 
|---|
 | 1367 |     for (n[1]=0; n[1]<N[1]; n[1]++)
 | 
|---|
 | 1368 |       for (n[2]=0; n[2]<N[2]; n[2]++) {
 | 
|---|
 | 1369 |         n[0] = n0 + N0 * myPE;
 | 
|---|
 | 1370 |         fac[0] = (double)(n[0])/(double)((N[0]));
 | 
|---|
 | 1371 |         fac[1] = (double)(n[1])/(double)((N[1]));
 | 
|---|
 | 1372 |         fac[2] = (double)(n[2])/(double)((N[2]));
 | 
|---|
 | 1373 |         RMat33Vec3(x,Lat->RealBasis,fac);
 | 
|---|
 | 1374 |         iS = n[2] + N[2]*(n[1] + N[1]*n0);  // mind splitting of x axis due to multiple processes
 | 
|---|
 | 1375 |         i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
 | 
|---|
 | 1376 |         //PsiCR[iS] = (x[index_r]) * RealPhiR[i0]; //- WCentre[index_r] 
 | 
|---|
 | 1377 |         PsiCR[iS] = truedist(Lat,x[index_r],WCentre[index_r],index_r) * RealPhiR[i0];
 | 
|---|
 | 1378 |         //PsiCR[iS] = truedist(Lat,x[index_r],0.,index_r) * RealPhiR[i0];
 | 
|---|
 | 1379 |         //PsiCR[iS] = sawtooth(Lat,truedist(Lat,x[index_r],WCentre[index_r],index_r), index_r)*RealPhiR[i0];
 | 
|---|
 | 1380 |         //(Fehler mit falschem Ort ist vor dieser Stelle!): ueber result =  RealPhiR[i0] * (x[index_r]) * RealPhiR[i0]; gecheckt
 | 
|---|
 | 1381 |       }
 | 
|---|
 | 1382 |   
 | 
|---|
 | 1383 |   // inverse fourier transform 
 | 
|---|
 | 1384 |   fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, work);
 | 
|---|
 | 1385 |   
 | 
|---|
 | 1386 |   // copy to destination array
 | 
|---|
 | 1387 |   for (g=0; g<LevS->MaxG; g++) {
 | 
|---|
 | 1388 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 1389 |     dest[g].re = ( PsiC[Index].re)*FFTFactor; 
 | 
|---|
 | 1390 |     dest[g].im = ( PsiC[Index].im)*FFTFactor;
 | 
|---|
 | 1391 |     if (LevS->GArray[g].GSq == 0)
 | 
|---|
 | 1392 |       dest[g].im = 0; // imaginary of G=0 is zero
 | 
|---|
 | 1393 |   }
 | 
|---|
 | 1394 | }*/
 | 
|---|
 | 1395 | 
 | 
|---|
 | 1396 | /** Prints the positions of all unperturbed orbitals to screen.
 | 
|---|
 | 1397 |  * \param *P Problem at hand
 | 
|---|
 | 1398 |  * \param type PsiTypeTag specifying group of orbitals
 | 
|---|
 | 1399 |  * \sa CalculatePerturbationOperator_R() 
 | 
|---|
 | 1400 |  */
 | 
|---|
 | 1401 | void OutputOrbitalPositions(struct Problem *P, const enum PsiTypeTag type)
 | 
|---|
 | 1402 | {
 | 
|---|
 | 1403 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 1404 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 1405 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1406 |   struct LatticeLevel *LevS = R->LevS; 
 | 
|---|
 | 1407 |   fftw_complex *temp = LevS->LPsi->TempPsi;
 | 
|---|
 | 1408 |   fftw_complex *source; 
 | 
|---|
 | 1409 |   int wavenr, index;
 | 
|---|
 | 1410 |   double result[NDIM], Result[NDIM];
 | 
|---|
 | 1411 |   //double imsult[NDIM], Imsult[NDIM];
 | 
|---|
 | 1412 |   double norm[NDIM], Norm[NDIM];
 | 
|---|
 | 1413 |   //double imnorm[NDIM], imNorm[NDIM];
 | 
|---|
 | 1414 |   double Wcentre[NDIM];
 | 
|---|
 | 1415 | 
 | 
|---|
 | 1416 |   // for every unperturbed wave function
 | 
|---|
 | 1417 |   for (wavenr=Psi->TypeStartIndex[type]; wavenr<Psi->TypeStartIndex[type+1]; wavenr++) {
 | 
|---|
 | 1418 |     source = LevS->LPsi->LocalPsi[wavenr];
 | 
|---|
 | 1419 |     Wcentre[0] = Psi->AddData[wavenr].WannierCentre[0];
 | 
|---|
 | 1420 |     Wcentre[1] = Psi->AddData[wavenr].WannierCentre[1];
 | 
|---|
 | 1421 |     Wcentre[2] = Psi->AddData[wavenr].WannierCentre[2];
 | 
|---|
 | 1422 |     for (index=0; index<NDIM; index++) {
 | 
|---|
 | 1423 |       SetArrayToDouble0((double *)temp,2*R->InitLevS->MaxG);
 | 
|---|
 | 1424 |       // apply position operator      
 | 
|---|
 | 1425 |       CalculatePerturbationOperator_R(P,source,temp,source,index, wavenr + Psi->TypeStartIndex[R->CurrentMin]);
 | 
|---|
 | 1426 |       // take scalar product
 | 
|---|
 | 1427 |       result[index] = GradSP(P,LevS,source,temp);
 | 
|---|
 | 1428 |       //imsult[index] = GradImSP(P,LevS,source,temp);
 | 
|---|
 | 1429 |       norm[index] = GradSP(P,LevS,source,source);
 | 
|---|
 | 1430 |       //imnorm[index] = GradImSP(P,LevS,source,source);
 | 
|---|
 | 1431 |       MPI_Allreduce( result, Result, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 1432 |       //MPI_Allreduce( imsult, Imsult, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 1433 |       MPI_Allreduce( norm, Norm, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 1434 |       //MPI_Allreduce( imnorm, imNorm, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 1435 |     }
 | 
|---|
 | 1436 |     // print output to stderr
 | 
|---|
 | 1437 |     if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Position of Orbital %i: (%e,%e,%e)\n",P->Par.me, wavenr, Result[0]/Norm[0]+Wcentre[0], Result[1]/Norm[1]+Wcentre[1], Result[2]/Norm[2]+Wcentre[2]);
 | 
|---|
 | 1438 |     //fprintf(stderr,"(%i) Position of Orbital %i wrt Wannier: (%e,%e,%e)\n",P->Par.me, wavenr, Result[0]/Norm[0], Result[1]/Norm[1], Result[2]/Norm[2]);
 | 
|---|
 | 1439 |     //fprintf(stderr,"(%i) with Norm: (%e,%e,%e) + i (%e,%e,%e)\n",P->Par.me, Norm[0], Norm[1], Norm[2], imNorm[0], imNorm[1], imNorm[2]);
 | 
|---|
 | 1440 |     //if (P->Par.me == 0) fprintf(stderr,"(%i) Position of Orbital %i: (%e,%e,%e)\n",P->Par.me, wavenr, Result[0]/Norm[0], Result[1]/Norm[1], Result[2]/Norm[2]);
 | 
|---|
 | 1441 |   }
 | 
|---|
 | 1442 | }
 | 
|---|
 | 1443 | 
 | 
|---|
 | 1444 | #define borderstart 0.9
 | 
|---|
 | 1445 | 
 | 
|---|
 | 1446 | /** Applies perturbation operator \f$(\widehat{r} \times \nabla)_{index}\f$ to \a *source.
 | 
|---|
 | 1447 |  * The source is fourier-transformed by transforming it to a density (on the next higher level RunStruct#Lev0) 
 | 
|---|
 | 1448 |  * and at the same time multiply it with the respective component of the reciprocal G vector - the momentum. This
 | 
|---|
 | 1449 |  * is done by callinf fft_Psi(). Thus we get \f$\nabla_k | \varphi (R) \rangle\f$.
 | 
|---|
 | 1450 |  * 
 | 
|---|
 | 1451 |  * Next, we apply the two of three components of the position operator r, which ones stated by cross(), while going 
 | 
|---|
 | 1452 |  * in a loop through every point of the grid. In order to do this sensibly, truedist() is used to map the coordinates
 | 
|---|
 | 1453 |  * onto -L/2...L/2, by subtracting the OneElementPsiAddData#WannierCentre R and wrapping. Also, due to the breaking up
 | 
|---|
 | 1454 |  * of the x axis into equally sized chunks for each coefficient sharing process, we need to step only over local
 | 
|---|
 | 1455 |  * x-axis grid points, however shift them to the global position when being used as position. In the end, we get
 | 
|---|
 | 1456 |  * \f$\epsilon_{index,j,k} (\widehat{r}-R)_j \nabla_k | \varphi (R) \rangle\f$.
 | 
|---|
 | 1457 |  * 
 | 
|---|
 | 1458 |  * One last fft brings the wave function back to reciprocal basis and it is copied to \a *dest.
 | 
|---|
 | 1459 |  * \param *P Problem at hand
 | 
|---|
 | 1460 |  * \param *source complex coefficients of wave function \f$\varphi(G)\f$
 | 
|---|
 | 1461 |  * \param *dest returned complex coefficients of wave function \f$(\widehat{r} \times \widehat{p})_{index}|\varphi(G)\rangle\f$
 | 
|---|
 | 1462 |  * \param phi0nr number within LocalPsi of the unperturbed pendant of the given perturbed wavefunction \a *source.
 | 
|---|
 | 1463 |  * \param index_rxp index desired of the vector product
 | 
|---|
 | 1464 |  * \sa CalculateConDirHConDir() - the procedure of fft and inverse fft is very similar.
 | 
|---|
 | 1465 |  */
 | 
|---|
 | 1466 | void CalculatePerturbationOperator_RxP(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const int phi0nr, const int index_rxp)
 | 
|---|
 | 1467 | 
 | 
|---|
 | 1468 | {
 | 
|---|
 | 1469 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 1470 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1471 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 1472 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 1473 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 1474 |   struct fft_plan_3d *plan = Lat->plan;
 | 
|---|
 | 1475 |   fftw_complex *TempPsi = Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 1476 |   fftw_real *TempPsiR = (fftw_real *) TempPsi;
 | 
|---|
 | 1477 |   fftw_complex *TempPsi2 = (fftw_complex *)Dens0->DensityArray[Temp2Density];
 | 
|---|
 | 1478 |   fftw_real *TempPsi2R =  (fftw_real *) TempPsi2;
 | 
|---|
 | 1479 |   fftw_complex *workC = Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 1480 |   fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
 | 1481 |   fftw_real *PsiCR = (fftw_real *) PsiC;
 | 
|---|
 | 1482 |   double x[NDIM], fac[NDIM], Wcentre[NDIM];
 | 
|---|
 | 1483 |   int n[NDIM], n0, g, Index, iS, i0; //pos, 
 | 
|---|
 | 1484 |   int N[NDIM], NUp[NDIM];
 | 
|---|
 | 1485 |   const int N0 = LevS->Plan0.plan->local_nx;
 | 
|---|
 | 1486 |   N[0] = LevS->Plan0.plan->N[0];
 | 
|---|
 | 1487 |   N[1] = LevS->Plan0.plan->N[1];
 | 
|---|
 | 1488 |   N[2] = LevS->Plan0.plan->N[2];
 | 
|---|
 | 1489 |   NUp[0] = LevS->NUp[0]; 
 | 
|---|
 | 1490 |   NUp[1] = LevS->NUp[1]; 
 | 
|---|
 | 1491 |   NUp[2] = LevS->NUp[2]; 
 | 
|---|
 | 1492 |   Wcentre[0] = Lat->Psi.AddData[phi0nr].WannierCentre[0];
 | 
|---|
 | 1493 |   Wcentre[1] = Lat->Psi.AddData[phi0nr].WannierCentre[1];
 | 
|---|
 | 1494 |   Wcentre[2] = Lat->Psi.AddData[phi0nr].WannierCentre[2];
 | 
|---|
 | 1495 |   // init pointers and values
 | 
|---|
 | 1496 |   const int myPE = P->Par.me_comm_ST_Psi;
 | 
|---|
 | 1497 |   const double FFTFactor = 1./LevS->MaxN; //
 | 
|---|
 | 1498 | //  double max[NDIM], max_psi[NDIM];
 | 
|---|
 | 1499 | //  double max_n[NDIM];
 | 
|---|
 | 1500 |   int index[4];
 | 
|---|
 | 1501 | //  double smooth, wall[NDIM];
 | 
|---|
 | 1502 | //  for (g=0;g<NDIM;g++) {
 | 
|---|
 | 1503 | //    max[g] = 0.;
 | 
|---|
 | 1504 | //    max_psi[g] = 0.;
 | 
|---|
 | 1505 | //    max_n[g] = -1.;
 | 
|---|
 | 1506 | //  }
 | 
|---|
 | 1507 | 
 | 
|---|
 | 1508 |   //fprintf(stderr,"(%i) Wannier[%i] (%2.13e, %2.13e, %2.13e)\n", P->Par.me, phi0nr, 10.-Wcentre[0], 10.-Wcentre[1], 10.-Wcentre[2]);
 | 
|---|
 | 1509 |   for (g=0;g<4;g++)
 | 
|---|
 | 1510 |     index[g] = cross(index_rxp,g);
 | 
|---|
 | 1511 | 
 | 
|---|
 | 1512 |   // blow up source coefficients
 | 
|---|
 | 1513 |   LockDensityArray(Dens0,Temp2Density,imag); // TempPsi
 | 
|---|
 | 1514 |   LockDensityArray(Dens0,Temp2Density,real); // TempPsi2
 | 
|---|
 | 1515 |   LockDensityArray(Dens0,ActualPsiDensity,imag); // PsiC
 | 
|---|
 | 1516 | 
 | 
|---|
 | 1517 |   fft_Psi(P,source,TempPsiR ,index[1],7);
 | 
|---|
 | 1518 |   fft_Psi(P,source,TempPsi2R,index[3],7);
 | 
|---|
 | 1519 |   
 | 
|---|
 | 1520 |   //result = 0.;
 | 
|---|
 | 1521 |   // for every point on the real grid multiply with component of position vector
 | 
|---|
 | 1522 |   for (n0=0; n0<N0; n0++)
 | 
|---|
 | 1523 |     for (n[1]=0; n[1]<N[1]; n[1]++)
 | 
|---|
 | 1524 |       for (n[2]=0; n[2]<N[2]; n[2]++) {
 | 
|---|
 | 1525 |         n[0] = n0 + N0 * myPE;
 | 
|---|
 | 1526 |         fac[0] = (double)(n[0])/(double)((N[0]));
 | 
|---|
 | 1527 |         fac[1] = (double)(n[1])/(double)((N[1]));
 | 
|---|
 | 1528 |         fac[2] = (double)(n[2])/(double)((N[2]));
 | 
|---|
 | 1529 |         RMat33Vec3(x,Lat->RealBasis,fac);
 | 
|---|
 | 1530 | //        fac[0] = (fac[0] > .9) ? fac[0]-0.9 : 0.;
 | 
|---|
 | 1531 | //        fac[1] = (fac[1] > .9) ? fac[1]-0.9 : 0.;
 | 
|---|
 | 1532 | //        fac[2] = (fac[2] > .9) ? fac[2]-0.9 : 0.;
 | 
|---|
 | 1533 | //        RMat33Vec3(wall,Lat->RealBasis,fac);
 | 
|---|
 | 1534 | //        smooth = exp(wall[0]*wall[0]+wall[1]*wall[1]+wall[2]*wall[2]);  // smoothing near the borders of the virtual cell
 | 
|---|
 | 1535 |         iS = n[2] + N[2]*(n[1] + N[1]*n0);  // mind splitting of x axis due to multiple processes
 | 
|---|
 | 1536 |         i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
 | 
|---|
 | 1537 | 
 | 
|---|
 | 1538 | //        if (fabs(truedist(Lat,x[index[1]],Wcentre[index[1]],index[1])) >= borderstart * Lat->RealBasisQ[index[1]]/2.)
 | 
|---|
 | 1539 | //          if (max[index[1]] < sawtooth(Lat,truedist(Lat,x[index[1]],Wcentre[index[1]],index[1]),index[1]) * TempPsiR [i0]) {
 | 
|---|
 | 1540 | //            max[index[1]] = sawtooth(Lat,truedist(Lat,x[index[1]],Wcentre[index[1]],index[1]),index[1]) * TempPsiR [i0];  
 | 
|---|
 | 1541 | //            max_psi[index[1]] = TempPsiR [i0];
 | 
|---|
 | 1542 | //            max_n[index[1]] = truedist(Lat,x[index[1]],Wcentre[index[1]],index[1]);
 | 
|---|
 | 1543 | //          }
 | 
|---|
 | 1544 | //
 | 
|---|
 | 1545 | //        if (fabs(truedist(Lat,x[index[3]],Wcentre[index[3]],index[3])) >= borderstart * Lat->RealBasisQ[index[3]]/2.)
 | 
|---|
 | 1546 | //          if (max[index[3]] < sawtooth(Lat,truedist(Lat,x[index[3]],Wcentre[index[3]],index[3]),index[3]) * TempPsiR [i0]) {
 | 
|---|
 | 1547 | //            max[index[3]] = sawtooth(Lat,truedist(Lat,x[index[3]],Wcentre[index[3]],index[3]),index[3]) * TempPsiR [i0];  
 | 
|---|
 | 1548 | //            max_psi[index[3]] = TempPsiR [i0];  
 | 
|---|
 | 1549 | //            max_n[index[3]] = truedist(Lat,x[index[3]],Wcentre[index[3]],index[3]);
 | 
|---|
 | 1550 | //          }
 | 
|---|
 | 1551 |         
 | 
|---|
 | 1552 |          PsiCR[iS] = //vector * TempPsiR[i0]; 
 | 
|---|
 | 1553 |           sawtooth(Lat,MinImageConv(Lat,x[index[0]],Wcentre[index[0]],index[0]),index[0]) * TempPsiR [i0]
 | 
|---|
 | 1554 |          -sawtooth(Lat,MinImageConv(Lat,x[index[2]],Wcentre[index[2]],index[2]),index[2]) * TempPsi2R[i0];
 | 
|---|
 | 1555 | //          ShiftGaugeOrigin(P,truedist(Lat,x[index[0]],Wcentre[index[0]],index[0]),index[0]) * TempPsiR [i0]
 | 
|---|
 | 1556 | //         -ShiftGaugeOrigin(P,truedist(Lat,x[index[2]],Wcentre[index[2]],index[2]),index[2]) * TempPsi2R[i0];
 | 
|---|
 | 1557 | //        PsiCR[iS] = (x[index[0]] - Wcentre[index[0]]) * TempPsiR [i0] - (x[index[2]] - Wcentre[index[2]]) * TempPsi2R[i0];
 | 
|---|
 | 1558 |       }
 | 
|---|
 | 1559 |   //if (P->Par.me == 0) fprintf(stderr,"(%i) PerturbationOpertator_R(xP): %e\n",P->Par.me, Result/LevS->MaxN);
 | 
|---|
 | 1560 |   UnLockDensityArray(Dens0,Temp2Density,imag); // TempPsi
 | 
|---|
 | 1561 |   UnLockDensityArray(Dens0,Temp2Density,real); // TempPsi2
 | 
|---|
 | 1562 |   
 | 
|---|
 | 1563 | //  // print maximum values
 | 
|---|
 | 1564 | //  fprintf (stderr,"(%i) RxP: Maximum values = (",P->Par.me);
 | 
|---|
 | 1565 | //  for (g=0;g<NDIM;g++)
 | 
|---|
 | 1566 | //    fprintf(stderr,"%lg\t", max[g]);
 | 
|---|
 | 1567 | //  fprintf(stderr,"\b)\t(");
 | 
|---|
 | 1568 | //  for (g=0;g<NDIM;g++)
 | 
|---|
 | 1569 | //    fprintf(stderr,"%lg\t", max_psi[g]);
 | 
|---|
 | 1570 | //  fprintf(stderr,"\b)\t");
 | 
|---|
 | 1571 | //  fprintf (stderr,"at (");
 | 
|---|
 | 1572 | //  for (g=0;g<NDIM;g++)
 | 
|---|
 | 1573 | //    fprintf(stderr,"%lg\t", max_n[g]);
 | 
|---|
 | 1574 | //  fprintf(stderr,"\b)\n");
 | 
|---|
 | 1575 |   
 | 
|---|
 | 1576 |   // inverse fourier transform 
 | 
|---|
 | 1577 |   //if (PsiC != Dens0->DensityCArray[ActualPsiDensity]) Error(SomeError,"CalculatePerturbationOperator_RxP: PsiC corrupted");
 | 
|---|
 | 1578 |   fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, workC);
 | 
|---|
 | 1579 |   
 | 
|---|
 | 1580 |   // copy to destination array
 | 
|---|
 | 1581 |   SetArrayToDouble0((double *)dest, 2*R->InitLevS->MaxG);
 | 
|---|
 | 1582 |   for (g=0; g<LevS->MaxG; g++) {
 | 
|---|
 | 1583 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 1584 |     dest[g].re += ( PsiC[Index].re)*FFTFactor; // factor confirmed, see grad.c:CalculateConDirHConDir()
 | 
|---|
 | 1585 |     dest[g].im += ( PsiC[Index].im)*FFTFactor;
 | 
|---|
 | 1586 |     //fprintf(stderr,"(%i) PsiC[(%lg,%lg,%lg)] = %lg +i %lg\n", P->Par.me, LevS->GArray[g].G[0], LevS->GArray[g].G[1], LevS->GArray[g].G[2], dest[g].re, dest[g].im);
 | 
|---|
 | 1587 |   }
 | 
|---|
 | 1588 |   UnLockDensityArray(Dens0,ActualPsiDensity,imag); // PsiC
 | 
|---|
 | 1589 |   //if (LevS->GArray[0].GSq == 0.)
 | 
|---|
 | 1590 |     //dest[0].im = 0.; // don't do this, see ..._P()
 | 
|---|
 | 1591 | }
 | 
|---|
 | 1592 | 
 | 
|---|
 | 1593 | /** Applies perturbation operator \f$-(\nabla \times \widehat{r})_{index}\f$ to \a *source.
 | 
|---|
 | 1594 |  * Is analogous to CalculatePerturbationOperator_RxP(), only the order is reversed, first position operator, then
 | 
|---|
 | 1595 |  * momentum operator
 | 
|---|
 | 1596 |  * \param *P Problem at hand
 | 
|---|
 | 1597 |  * \param *source complex coefficients of wave function \f$\varphi(G)\f$
 | 
|---|
 | 1598 |  * \param *dest returned complex coefficients of wave function \f$(\widehat{r} \times \widehat{p})_{index}|\varphi(G)\rangle\f$
 | 
|---|
 | 1599 |  * \param phi0nr number within LocalPsi of the unperturbed pendant of the given perturbed wavefunction \a *source.
 | 
|---|
 | 1600 |  * \param index_pxr index of position operator
 | 
|---|
 | 1601 |  * \note Only third component is important due to initial rotiation of cell such that B field is aligned with z axis.
 | 
|---|
 | 1602 |  * \sa CalculateConDirHConDir() - the procedure of fft and inverse fft is very similar.
 | 
|---|
 | 1603 |  * \bug routine is not tested (but should work), as it offers no advantage over CalculatePerturbationOperator_RxP() 
 | 
|---|
 | 1604 |  */
 | 
|---|
 | 1605 | void CalculatePerturbationOperator_PxR(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const int phi0nr, const int index_pxr)
 | 
|---|
 | 1606 | 
 | 
|---|
 | 1607 | {
 | 
|---|
 | 1608 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 1609 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1610 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 1611 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 1612 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 1613 |   struct fft_plan_3d *plan = Lat->plan;
 | 
|---|
 | 1614 |   fftw_complex *TempPsi = Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 1615 |   fftw_real *TempPsiR = (fftw_real *) TempPsi;
 | 
|---|
 | 1616 |   fftw_complex *workC = Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 1617 |   fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
 | 1618 |   fftw_real *PsiCR = (fftw_real *) PsiC;
 | 
|---|
 | 1619 |   fftw_complex *Psi2C = Dens0->DensityCArray[ActualDensity];
 | 
|---|
 | 1620 |   fftw_real *Psi2CR = (fftw_real *) Psi2C;
 | 
|---|
 | 1621 |   fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityArray[Temp2Density];
 | 
|---|
 | 1622 |   fftw_complex *posfac, *destsnd, *destrcv;
 | 
|---|
 | 1623 |   double x[NDIM], fac[NDIM], Wcentre[NDIM];
 | 
|---|
 | 1624 |   int n[NDIM], n0, g, Index, pos, iS, i0;
 | 
|---|
 | 1625 |   int N[NDIM], NUp[NDIM];
 | 
|---|
 | 1626 |   const int N0 = LevS->Plan0.plan->local_nx;
 | 
|---|
 | 1627 |   N[0] = LevS->Plan0.plan->N[0];
 | 
|---|
 | 1628 |   N[1] = LevS->Plan0.plan->N[1];
 | 
|---|
 | 1629 |   N[2] = LevS->Plan0.plan->N[2];
 | 
|---|
 | 1630 |   NUp[0] = LevS->NUp[0]; 
 | 
|---|
 | 1631 |   NUp[1] = LevS->NUp[1]; 
 | 
|---|
 | 1632 |   NUp[2] = LevS->NUp[2]; 
 | 
|---|
 | 1633 |   Wcentre[0] = Lat->Psi.AddData[phi0nr].WannierCentre[0];
 | 
|---|
 | 1634 |   Wcentre[1] = Lat->Psi.AddData[phi0nr].WannierCentre[1];
 | 
|---|
 | 1635 |   Wcentre[2] = Lat->Psi.AddData[phi0nr].WannierCentre[2];
 | 
|---|
 | 1636 |   // init pointers and values
 | 
|---|
 | 1637 |   const int myPE = P->Par.me_comm_ST_Psi;
 | 
|---|
 | 1638 |   const double FFTFactor = 1./LevS->MaxN; 
 | 
|---|
 | 1639 | 
 | 
|---|
 | 1640 |   // blow up source coefficients
 | 
|---|
 | 1641 |   SetArrayToDouble0((double *)tempdestRC ,Dens0->TotalSize*2);
 | 
|---|
 | 1642 |   SetArrayToDouble0((double *)TempPsi ,Dens0->TotalSize*2);
 | 
|---|
 | 1643 |   SetArrayToDouble0((double *)PsiC,Dens0->TotalSize*2);
 | 
|---|
 | 1644 |   SetArrayToDouble0((double *)Psi2C,Dens0->TotalSize*2);
 | 
|---|
 | 1645 |   for (g=0; g<LevS->MaxG; g++) {
 | 
|---|
 | 1646 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 1647 |     posfac = &LevS->PosFactorUp[LevS->MaxNUp*g];
 | 
|---|
 | 1648 |     destrcv = &tempdestRC[LevS->MaxNUp*Index]; 
 | 
|---|
 | 1649 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 1650 |       destrcv [pos].re = (( source[g].re)*posfac[pos].re-( source[g].im)*posfac[pos].im);
 | 
|---|
 | 1651 |       destrcv [pos].im = (( source[g].re)*posfac[pos].im+( source[g].im)*posfac[pos].re);
 | 
|---|
 | 1652 |     }
 | 
|---|
 | 1653 |   }
 | 
|---|
 | 1654 |   for (g=0; g<LevS->MaxDoubleG; g++) {
 | 
|---|
 | 1655 |     destsnd  = &tempdestRC [LevS->DoubleG[2*g]*LevS->MaxNUp];
 | 
|---|
 | 1656 |     destrcv  = &tempdestRC [LevS->DoubleG[2*g+1]*LevS->MaxNUp];
 | 
|---|
 | 1657 |     for (pos=0; pos<LevS->MaxNUp; pos++) {
 | 
|---|
 | 1658 |       destrcv [pos].re =  destsnd [pos].re;
 | 
|---|
 | 1659 |       destrcv [pos].im = -destsnd [pos].im;
 | 
|---|
 | 1660 |     }    
 | 
|---|
 | 1661 |   }  
 | 
|---|
 | 1662 |   // fourier transform blown up wave function
 | 
|---|
 | 1663 |   fft_3d_complex_to_real(plan,LevS->LevelNo, FFTNFUp, tempdestRC , workC);
 | 
|---|
 | 1664 |   DensityRTransformPos(LevS,(fftw_real*)tempdestRC ,TempPsiR );
 | 
|---|
 | 1665 | 
 | 
|---|
 | 1666 |   //fft_Psi(P,source,TempPsiR ,cross(index_pxr,1),7);
 | 
|---|
 | 1667 |   //fft_Psi(P,source,TempPsi2R,cross(index_pxr,3),7);
 | 
|---|
 | 1668 |   
 | 
|---|
 | 1669 |   //result = 0.;
 | 
|---|
 | 1670 |   // for every point on the real grid multiply with component of position vector
 | 
|---|
 | 1671 |   for (n0=0; n0<N0; n0++)
 | 
|---|
 | 1672 |     for (n[1]=0; n[1]<N[1]; n[1]++)
 | 
|---|
 | 1673 |       for (n[2]=0; n[2]<N[2]; n[2]++) {
 | 
|---|
 | 1674 |         n[0] = n0 + N0 * myPE;
 | 
|---|
 | 1675 |         fac[0] = (double)(n[0])/(double)((N[0]));
 | 
|---|
 | 1676 |         fac[1] = (double)(n[1])/(double)((N[1]));
 | 
|---|
 | 1677 |         fac[2] = (double)(n[2])/(double)((N[2]));
 | 
|---|
 | 1678 |         RMat33Vec3(x,Lat->RealBasis,fac);
 | 
|---|
 | 1679 |         iS = n[2] + N[2]*(n[1] + N[1]*n0);  // mind splitting of x axis due to multiple processes
 | 
|---|
 | 1680 |         i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
 | 
|---|
 | 1681 | //         PsiCR[iS] = sawtooth(Lat,truedist(Lat,x[cross(index_pxr,1)],Wcentre[cross(index_pxr,1)],cross(index_pxr,1)),cross(index_pxr,1)) * TempPsiR[i0];
 | 
|---|
 | 1682 | //         Psi2CR[iS] = sawtooth(Lat,truedist(Lat,x[cross(index_pxr,3)],Wcentre[cross(index_pxr,3)],cross(index_pxr,3)),cross(index_pxr,3)) * TempPsiR[i0]; 
 | 
|---|
 | 1683 |          PsiCR[iS] = ShiftGaugeOrigin(P,MinImageConv(Lat,x[cross(index_pxr,1)],Wcentre[cross(index_pxr,1)],cross(index_pxr,1)),cross(index_pxr,1)) * TempPsiR[i0];
 | 
|---|
 | 1684 |          Psi2CR[iS] = ShiftGaugeOrigin(P,MinImageConv(Lat,x[cross(index_pxr,3)],Wcentre[cross(index_pxr,3)],cross(index_pxr,3)),cross(index_pxr,3)) * TempPsiR[i0]; 
 | 
|---|
 | 1685 |       }
 | 
|---|
 | 1686 |   
 | 
|---|
 | 1687 |   // inverse fourier transform 
 | 
|---|
 | 1688 |   fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, workC);
 | 
|---|
 | 1689 |   fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, Psi2C, workC);
 | 
|---|
 | 1690 |   
 | 
|---|
 | 1691 |   // copy to destination array
 | 
|---|
 | 1692 |   for (g=0; g<LevS->MaxG; g++) {
 | 
|---|
 | 1693 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 1694 |     dest[g].re = -LevS->GArray[g].G[cross(index_pxr,0)]*( PsiC[Index].im)*FFTFactor; 
 | 
|---|
 | 1695 |     dest[g].im = -LevS->GArray[g].G[cross(index_pxr,0)]*(-PsiC[Index].re)*FFTFactor;
 | 
|---|
 | 1696 |     dest[g].re -= -LevS->GArray[g].G[cross(index_pxr,2)]*( Psi2C[Index].im)*FFTFactor; 
 | 
|---|
 | 1697 |     dest[g].im -= -LevS->GArray[g].G[cross(index_pxr,2)]*(-Psi2C[Index].re)*FFTFactor;
 | 
|---|
 | 1698 |   }
 | 
|---|
 | 1699 |   if (LevS->GArray[0].GSq == 0.)
 | 
|---|
 | 1700 |     dest[0].im = 0.; // don't do this, see ..._P()
 | 
|---|
 | 1701 | }
 | 
|---|
 | 1702 | 
 | 
|---|
 | 1703 | /** Evaluates first derivative of perturbed energy functional with respect to minimisation parameter \f$\Theta\f$.
 | 
|---|
 | 1704 |  * \f[
 | 
|---|
 | 1705 |  *  \frac{\delta {\cal E}^{(2)}} {\delta \Theta} =
 | 
|---|
 | 1706 |  *    2 {\cal R} \langle \widetilde{\varphi}_i^{(1)} | {\cal H}^{(0)} | \varphi_i^{(1)} \rangle
 | 
|---|
 | 1707 |  *    - \sum_l \lambda_{il} \langle \widetilde{\varphi}_i^{(1)} | \varphi_l^{(1)} \rangle
 | 
|---|
 | 1708 |  *    - \sum_k \lambda_{ki} \langle \varphi_k^{(1)} | \widetilde{\varphi}_i^{(1)} \rangle
 | 
|---|
 | 1709 |  *    + 2 {\cal R} \langle \widetilde{\varphi}_i^{(1)} | {\cal H}^{(1)} | \varphi_i^{(0)} \rangle
 | 
|---|
 | 1710 |  * \f]
 | 
|---|
 | 1711 |  * 
 | 
|---|
 | 1712 |  * The summation over all Psis has again to be done with an MPI exchange of non-local coefficients, as the conjugate
 | 
|---|
 | 1713 |  * directions are not the same in situations where PePGamma > 1 (Psis split up among processes = multiple minimisation)
 | 
|---|
 | 1714 |  * \param *P Problem at hand
 | 
|---|
 | 1715 |  * \param source0 unperturbed wave function \f$\varphi_l^{(0)}\f$
 | 
|---|
 | 1716 |  * \param source perturbed wave function \f$\varphi_l^{(1)} (G)\f$
 | 
|---|
 | 1717 |  * \param ConDir normalized conjugate direction \f$\widetilde{\varphi}_l^{(1)} (G)\f$
 | 
|---|
 | 1718 |  * \param Hc_grad complex coefficients of \f$H^{(0)} | \varphi_l^{(1)} (G) \rangle\f$, see GradientArray#HcGradient
 | 
|---|
 | 1719 |  * \param H1c_grad complex coefficients of \f$H^{(1)} | \varphi_l^{(0)} (G) \rangle\f$, see GradientArray#H1cGradient
 | 
|---|
 | 1720 |  * \sa CalculateLineSearch() - used there, \sa CalculateConDirHConDir() - same principles
 | 
|---|
 | 1721 |  * \warning The MPI_Allreduce for the scalar product in the end has not been done and must not have been done for given
 | 
|---|
 | 1722 |  *          parameters yet!
 | 
|---|
 | 1723 |  */
 | 
|---|
 | 1724 | double Calculate1stPerturbedDerivative(struct Problem *P, const fftw_complex *source0, const fftw_complex *source, const fftw_complex *ConDir, const fftw_complex *Hc_grad, const fftw_complex *H1c_grad)
 | 
|---|
 | 1725 | {
 | 
|---|
 | 1726 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1727 |   struct Psis *Psi = &P->Lat.Psi;
 | 
|---|
 | 1728 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 1729 |   double result = 0., E0 = 0., Elambda = 0., E1 = 0.;//, E2 = 0.;
 | 
|---|
 | 1730 |   int i,m,j;
 | 
|---|
 | 1731 |   const int state = R->CurrentMin;
 | 
|---|
 | 1732 |   //const int l_normal = R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[Occupied]; 
 | 
|---|
 | 1733 |   const int ActNum =  R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[R->ActualLocalPsiNo].my_color_comm_ST_Psi;
 | 
|---|
 | 1734 |   //int l = R->ActualLocalPsiNo;
 | 
|---|
 | 1735 |   //int l_normal = Psi->TypeStartIndex[Occupied] + (l - Psi->TypeStartIndex[state]);  // offset l to \varphi_l^{(0)}
 | 
|---|
 | 1736 |   struct OnePsiElement *OnePsiB, *LOnePsiB;
 | 
|---|
 | 1737 |   //fftw_complex *HConGrad = LevS->LPsi->TempPsi;
 | 
|---|
 | 1738 |   fftw_complex *LPsiDatB=NULL;
 | 
|---|
 | 1739 |   const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
 | 1740 |   int RecvSource;
 | 
|---|
 | 1741 |   MPI_Status status;
 | 
|---|
 | 1742 | 
 | 
|---|
 | 1743 |   //CalculateCDfnl(P,ConDir,PP->CDfnl);  
 | 
|---|
 | 1744 |   //ApplyTotalHamiltonian(P,ConDir,HConDir, PP->CDfnl, 1, 0);
 | 
|---|
 | 1745 |   //E0 = (GradSP(P, LevS, ConDir, Hc_grad) + GradSP(P, LevS, source, HConDir)) * Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor;
 | 
|---|
 | 1746 |   E0 = 2.*GradSP(P, LevS, ConDir, Hc_grad) * Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor;
 | 
|---|
 | 1747 |   result = E0;
 | 
|---|
 | 1748 |   //fprintf(stderr,"(%i) 1st: E0 = \t\t%lg\n", P->Par.me, E0);
 | 
|---|
 | 1749 | 
 | 
|---|
 | 1750 |   m = -1;
 | 
|---|
 | 1751 |   for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) {  // go through all wave functions
 | 
|---|
 | 1752 |     OnePsiB = &Psi->AllPsiStatus[j];    // grab OnePsiB
 | 
|---|
 | 1753 |     if (OnePsiB->PsiType == state) {   // drop all but the ones of current min state
 | 
|---|
 | 1754 |       m++;  // increase m if it is type-specific wave function
 | 
|---|
 | 1755 |       if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
 | 
|---|
 | 1756 |          LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
 | 
|---|
 | 1757 |       else
 | 
|---|
 | 1758 |          LOnePsiB = NULL;
 | 
|---|
 | 1759 |       if (LOnePsiB == NULL) {   // if it's not local ... receive it from respective process into TempPsi
 | 
|---|
 | 1760 |         RecvSource = OnePsiB->my_color_comm_ST_Psi;
 | 
|---|
 | 1761 |         MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, PerturbedTag, P->Par.comm_ST_PsiT, &status );
 | 
|---|
 | 1762 |         LPsiDatB=LevS->LPsi->TempPsi;
 | 
|---|
 | 1763 |       } else {                  // .. otherwise send it to all other processes (Max_me... - 1)
 | 
|---|
 | 1764 |         for (i=0;i<P->Par.Max_me_comm_ST_PsiT;i++)
 | 
|---|
 | 1765 |           if (i != OnePsiB->my_color_comm_ST_Psi)
 | 
|---|
 | 1766 |             MPI_Send( LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, i, PerturbedTag, P->Par.comm_ST_PsiT);
 | 
|---|
 | 1767 |         LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
 | 
|---|
 | 1768 |       } // LPsiDatB is now set to the coefficients of OnePsi either stored or MPI_Received
 | 
|---|
 | 1769 | 
 | 
|---|
 | 1770 |       Elambda -= 2.*Psi->lambda[ActNum][m]*GradSP(P, LevS, ConDir, LPsiDatB) * OnePsiB->PsiFactor;  // lambda is symmetric
 | 
|---|
 | 1771 |     }
 | 
|---|
 | 1772 |   }
 | 
|---|
 | 1773 |   result += Elambda;
 | 
|---|
 | 1774 |   //fprintf(stderr,"(%i) 1st: Elambda = \t%lg\n", P->Par.me, Elambda);
 | 
|---|
 | 1775 | 
 | 
|---|
 | 1776 |   E1 =  2.*GradSP(P,LevS,ConDir,H1c_grad) * sqrt(Psi->AllPsiStatus[ActNum].PsiFactor*Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor);
 | 
|---|
 | 1777 |   result += E1;
 | 
|---|
 | 1778 |   //fprintf(stderr,"(%i) 1st: E1 = \t\t%lg\n", P->Par.me, E1);
 | 
|---|
 | 1779 | 
 | 
|---|
 | 1780 |   return result;
 | 
|---|
 | 1781 | }
 | 
|---|
 | 1782 | 
 | 
|---|
 | 1783 | 
 | 
|---|
 | 1784 | /** Evaluates second derivative of perturbed energy functional with respect to minimisation parameter \f$\Theta\f$.
 | 
|---|
 | 1785 |  * \f[
 | 
|---|
 | 1786 |  *   \frac{\delta^2 {\cal E}^{(2)}} {\delta \Theta^2} =
 | 
|---|
 | 1787 |  *        2 \bigl( \langle \widetilde{\varphi}_l^{(1)} | {\cal H}^{(0)} | \widetilde{\varphi}_l^{(1)} \rangle
 | 
|---|
 | 1788 |  *      - \langle \varphi_l^{(1)} | {\cal H}^{(0)} | \varphi_l^{(1)} \rangle \bigr )
 | 
|---|
 | 1789 |  *      + 2 \sum_{i,i \neq l } \lambda_{il} \langle \varphi_i^{(1)} | \varphi_l^{(1)} \rangle
 | 
|---|
 | 1790 |  *      - 2 {\cal R} \langle \varphi_l^{(1)} | {\cal H}^{(1)} | \varphi_l^{(0)} \rangle
 | 
|---|
 | 1791 |  * \f]
 | 
|---|
 | 1792 |  * 
 | 
|---|
 | 1793 |  * The energy eigenvalues of \a ConDir and \a source must be supplied, they can be calculated via CalculateConDirHConDir() and/or
 | 
|---|
 | 1794 |  * by the due to CalculatePerturbedEnergy() already present OnePsiElementAddData#Lambda eigenvalue. The summation over the
 | 
|---|
 | 1795 |  * unperturbed lambda within the scalar product of perturbed wave functions is evaluated with Psis#lambda and Psis#Overlap.
 | 
|---|
 | 1796 |  * Afterwards, the ConDir density is calculated and also the i-th perturbed density to first degree. With these in a sum over
 | 
|---|
 | 1797 |  * all real mesh points the exchange-correlation first and second derivatives and also the Hartree potential ones can be calculated
 | 
|---|
 | 1798 |  * and summed up.
 | 
|---|
 | 1799 |  * \param *P Problem at hand
 | 
|---|
 | 1800 |  * \param source0 unperturbed wave function \f$\varphi_l^{(0)}\f$
 | 
|---|
 | 1801 |  * \param source wave function \f$\varphi_l^{(1)}\f$
 | 
|---|
 | 1802 |  * \param ConDir conjugated direction \f$\widetilde{\varphi}_l^{(1)}\f$
 | 
|---|
 | 1803 |  * \param sourceHsource eigenvalue of wave function \f$\langle \varphi_l^{(1)} | H^{(0)} | \varphi_l^{(1)}\rangle\f$
 | 
|---|
 | 1804 |  * \param ConDirHConDir perturbed eigenvalue of conjugate direction \f$\langle \widetilde{\varphi}_l^{(1)} | H^{(0)} | \widetilde{\varphi}_l^{(1)}\rangle\f$
 | 
|---|
 | 1805 |  * \param ConDirConDir norm of conjugate direction \f$\langle \widetilde{\varphi}_l^{(1)} | \widetilde{\varphi}_l^{(1)}\rangle\f$
 | 
|---|
 | 1806 |  * \warning No MPI_AllReduce() takes place, parameters have to be reduced already.
 | 
|---|
 | 1807 |  */
 | 
|---|
 | 1808 | double Calculate2ndPerturbedDerivative(struct Problem *P, const fftw_complex *source0,const  fftw_complex *source, const fftw_complex *ConDir,const  double sourceHsource, const double ConDirHConDir, const double ConDirConDir)
 | 
|---|
 | 1809 | {
 | 
|---|
 | 1810 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1811 |   struct Psis *Psi = &P->Lat.Psi;
 | 
|---|
 | 1812 |   //struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 1813 |   //struct Energy *E = Lat->E;
 | 
|---|
 | 1814 |   double result = 0.;
 | 
|---|
 | 1815 |   double Con0 = 0., Elambda = 0.;//, E0 = 0., E1 = 0.;
 | 
|---|
 | 1816 |   //int i;
 | 
|---|
 | 1817 |   const int state = R->CurrentMin;
 | 
|---|
 | 1818 |   //const int l_normal = R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[Occupied]; 
 | 
|---|
 | 1819 |   const int ActNum =  R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[R->ActualLocalPsiNo].my_color_comm_ST_Psi;
 | 
|---|
 | 1820 | 
 | 
|---|
 | 1821 |   Con0 = 2.*ConDirHConDir;
 | 
|---|
 | 1822 |   result += Con0;
 | 
|---|
 | 1823 |   ////E0 = -2.*sourceHsource;
 | 
|---|
 | 1824 |   ////result += E0;
 | 
|---|
 | 1825 |   ////E1 = -E->PsiEnergy[Perturbed1_0Energy][R->ActualLocalPsiNo] - E->PsiEnergy[Perturbed0_1Energy][R->ActualLocalPsiNo];
 | 
|---|
 | 1826 |   ////result += E1;
 | 
|---|
 | 1827 |   //fprintf(stderr,"(%i) 2nd: E1 = \t%lg\n", P->Par.me, E1);
 | 
|---|
 | 1828 | 
 | 
|---|
 | 1829 |   ////for (i=0;i<Lat->Psi.NoOfPsis;i++) {
 | 
|---|
 | 1830 |   ////  if (i != ActNum) Elambda += Psi->lambda[i][ActNum]*Psi->Overlap[i][ActNum]+ Psi->lambda[ActNum][i]*Psi->Overlap[ActNum][i];   // overlap contains PsiFactor
 | 
|---|
 | 1831 |   ////}
 | 
|---|
 | 1832 |   ////Elambda = Psi->lambda[ActNum][ActNum]*Psi->Overlap[ActNum][ActNum];
 | 
|---|
 | 1833 |   Elambda = 2.*Psi->lambda[ActNum][ActNum]*ConDirConDir;
 | 
|---|
 | 1834 |   result -= Elambda;
 | 
|---|
 | 1835 | 
 | 
|---|
 | 1836 |   //fprintf(stderr,"(%i) 2ndPerturbedDerivative: Result = Con0 + E0 + E1 + Elambda + dEdt0_XC + ddEddt0_XC + dEdt0_H + ddEddt0_H = %lg + %lg + %lg + %lg + %lg + %lg + %lg + %lg = %lg\n", P->Par.me, Con0, E0, E1, Elambda, VolumeFactorR*dEdt0_XC, VolumeFactorR*ddEddt0_XC, dEdt0_H, ddEddt0_H, result);
 | 
|---|
 | 1837 | 
 | 
|---|
 | 1838 |   return (result);
 | 
|---|
 | 1839 | }
 | 
|---|
 | 1840 | 
 | 
|---|
 | 1841 | /** Returns index of specific component in 3x3 cross product.
 | 
|---|
 | 1842 |  * \param i vector product component index, ranging from 0..NDIM
 | 
|---|
 | 1843 |  * \param j index specifies which one of the four vectors in x*y - y*x, ranging from 0..3 (0,1 positive sign, 2,3 negative sign)
 | 
|---|
 | 1844 |  * \return Component 0..2 of vector to be taken to evaluate a vector product 
 | 
|---|
 | 1845 |  * \sa crossed() - is the same but vice versa, return value must be specified, \a i is returned.
 | 
|---|
 | 1846 |  */
 | 
|---|
 | 1847 | inline int cross(int i, int j)
 | 
|---|
 | 1848 | {
 | 
|---|
 | 1849 |   const int matrix[NDIM*4] = {1,2,2,1,2,0,0,2,0,1,1,0};
 | 
|---|
 | 1850 |   if (i>=0 && i<NDIM && j>=0 && j<4)
 | 
|---|
 | 1851 |     return (matrix[i*4+j]);
 | 
|---|
 | 1852 |   else {
 | 
|---|
 | 1853 |     Error(SomeError,"cross: i or j out of range!");
 | 
|---|
 | 1854 |     return (0);
 | 
|---|
 | 1855 |   }
 | 
|---|
 | 1856 | }
 | 
|---|
 | 1857 | 
 | 
|---|
 | 1858 | /** Returns index of resulting vector component in 3x3 cross product.
 | 
|---|
 | 1859 |  * In the column specified by the \a j index \a i is looked for and the found row index returned.  
 | 
|---|
 | 1860 |  * \param i vector component index, ranging from 0..NDIM
 | 
|---|
 | 1861 |  * \param j index specifies which one of the four vectors in x*y - y*x, ranging from 0..3 (0,1 positive sign, 2,3 negative sign)
 | 
|---|
 | 1862 |  * \return Component 0..2 of resulting vector
 | 
|---|
 | 1863 |  * \sa cross() - is the same but vice versa, return value must be specified, \a i is returned.
 | 
|---|
 | 1864 |  */
 | 
|---|
 | 1865 | inline int crossed(int i, int j)
 | 
|---|
 | 1866 | {
 | 
|---|
 | 1867 |   const int matrix[NDIM*4] = {1,2,2,1,2,0,0,2,0,1,1,0};
 | 
|---|
 | 1868 |   int k;
 | 
|---|
 | 1869 |   if (i>=0 && i<NDIM && j>=0 && j<4) {
 | 
|---|
 | 1870 |     for (k=0;k<NDIM;k++)
 | 
|---|
 | 1871 |       if (matrix[4*k+j] == i) return(k);
 | 
|---|
 | 1872 |     Error(SomeError,"crossed: given component not found!");
 | 
|---|
 | 1873 |     return(-1);
 | 
|---|
 | 1874 |   } else {
 | 
|---|
 | 1875 |     Error(SomeError,"crossed: i or j out of range!");
 | 
|---|
 | 1876 |     return (-1);
 | 
|---|
 | 1877 |   }
 | 
|---|
 | 1878 | }
 | 
|---|
 | 1879 | 
 | 
|---|
 | 1880 | #define Nsin 16  //!< should be dependent on MaxG/MaxN per axis!
 | 
|---|
 | 1881 | 
 | 
|---|
 | 1882 | /** Returns sawtooth shaped profile for position operator within cell.
 | 
|---|
 | 1883 |  * This is a mapping from -L/2...L/2 (L = Lattice#RealBasisQ) to -L/2 to L/2 with a smooth transition:
 | 
|---|
 | 1884 |  * \f[
 | 
|---|
 | 1885 |  *  f(x): x \rightarrow \left \{ 
 | 
|---|
 | 1886 |  *    \begin{array}{l} 
 | 
|---|
 | 1887 |  *      -\frac{L}{2} \cdot \sin \left ( \frac{x}{0,05\cdot L} \cdot \frac{\pi}{2} \right ), 0<x<0,05\cdot L \\ 
 | 
|---|
 | 1888 |  *      (x - 0,05\cdot L) \cdot \frac{10}{9} - \frac{L}{2}, 0,05\cdot L \leq x<0,95\cdot L \\
 | 
|---|
 | 1889 |  *       \frac{L}{2} \cdot \cos \left ( \frac{x-0,95\cdot L}{0,05\cdot L} \cdot \frac{\pi}{2} \right), 0,95\cdot L<x<L
 | 
|---|
 | 1890 |  *    \end{array} \right \}
 | 
|---|
 | 1891 |  * \f]
 | 
|---|
 | 1892 |  * \param *Lat pointer to Lattice structure for Lattice#RealBasisQ
 | 
|---|
 | 1893 |  * \param L parameter x
 | 
|---|
 | 1894 |  * \param index component index for Lattice#RealBasisQ
 | 
|---|
 | 1895 |  */
 | 
|---|
 | 1896 | inline double sawtooth(struct Lattice *Lat, double L, const int index)
 | 
|---|
 | 1897 | {
 | 
|---|
 | 1898 |   double axis = Lat->RealBasisQ[index];
 | 
|---|
 | 1899 |   double sawstart = Lat->SawtoothStart;
 | 
|---|
 | 1900 |   double sawend = 1. - sawstart;
 | 
|---|
 | 1901 |   double sawfactor = (sawstart+sawend)/(sawend-sawstart);
 | 
|---|
 | 1902 |   //return(L);
 | 
|---|
 | 1903 | 
 | 
|---|
 | 1904 |   //fprintf(stderr, "sawstart: %e\tsawend: %e\tsawfactor: %e\tL: %e\n", sawstart, sawend, sawfactor, L);
 | 
|---|
 | 1905 |   // transform and return (sawtooth profile checked, 04.08.06)
 | 
|---|
 | 1906 |   L += axis/2.; // transform to 0 ... L
 | 
|---|
 | 1907 |   if (L < (sawstart*axis)) return (-axis/(2*sawfactor)*sin(L/(sawstart*axis)*PI/2.));  // first smooth transition from 0 ... -L/2
 | 
|---|
 | 1908 |   if (L > (sawend*axis)) return ( axis/(2*sawfactor)*cos((L-sawend*axis)/(sawstart*axis)*PI/2.));  // second smooth transition from +L/2 ... 0
 | 
|---|
 | 1909 |   //fprintf(stderr,"L %e\t sawstart %e\t sawend %e\t sawfactor %e\t axis%e\n", L, sawstart, sawend, sawfactor, axis);
 | 
|---|
 | 1910 |   //return ((L - sawstart*axis) - axis/(2*sawfactor));  // area in between scale to -L/2 ... +L/2
 | 
|---|
 | 1911 |   return (L - axis/2);  // area in between return as it was 
 | 
|---|
 | 1912 | }
 | 
|---|
 | 1913 | 
 | 
|---|
 | 1914 | /** Shifts the origin of the gauge according to the CSDGT method.
 | 
|---|
 | 1915 |  * \f[
 | 
|---|
 | 1916 |  *  d(r) = r - \sum_{I_s,I_a} (r-R_{I_s,I_a}) exp{(-\alpha_{I_s,I_a}(r-R_{I_s,I_a})^4)}
 | 
|---|
 | 1917 |  * \f]
 | 
|---|
 | 1918 |  * This trafo is necessary as the current otherweise (CSGT) sensitively depends on the current around
 | 
|---|
 | 1919 |  * the core region inadequately/only moderately well approximated by a plane-wave-pseudo-potential-method.
 | 
|---|
 | 1920 |  * \param *P Problem at hand, containing Lattice and Ions
 | 
|---|
 | 1921 |  * \param r parameter r 
 | 
|---|
 | 1922 |  * \param index index of the basis vector
 | 
|---|
 | 1923 |  * \return \f$d(r)\f$ 
 | 
|---|
 | 1924 |  * \note Continuous Set of Damped Gauge Transformations according to Keith and Bader 
 | 
|---|
 | 1925 |  */
 | 
|---|
 | 1926 | inline double ShiftGaugeOrigin(struct Problem *P, double r, const int index)
 | 
|---|
 | 1927 | {
 | 
|---|
 | 1928 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 1929 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 1930 |   double x, tmp; 
 | 
|---|
 | 1931 |   int is,ia;
 | 
|---|
 | 1932 |   
 | 
|---|
 | 1933 |   // loop over all ions to calculate the sum
 | 
|---|
 | 1934 |   x = r;
 | 
|---|
 | 1935 |   for (is=0; is < I->Max_Types; is++)
 | 
|---|
 | 1936 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 1937 |       tmp = (r - I->I[is].R[NDIM*ia]);
 | 
|---|
 | 1938 |       x -= tmp*exp(- I->I[is].alpha[ia] * tpow(tmp,4));
 | 
|---|
 | 1939 |     }
 | 
|---|
 | 1940 |   
 | 
|---|
 | 1941 |   return(sawtooth(Lat,x,index));  // still use sawtooth due to the numerical instability around the border region of the cell
 | 
|---|
 | 1942 | }
 | 
|---|
 | 1943 | 
 | 
|---|
 | 1944 | /** Print sawtooth() for each node along one axis.
 | 
|---|
 | 1945 |  * \param *P Problem at hand, containing RunStruct, Lattice and LatticeLevel RunStruct#LevS
 | 
|---|
 | 1946 |  * \param index index of axis
 | 
|---|
 | 1947 |  */
 | 
|---|
 | 1948 | void TestSawtooth(struct Problem *P, const int index)
 | 
|---|
 | 1949 | {
 | 
|---|
 | 1950 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1951 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 1952 |   struct Lattice *Lat =&P->Lat;
 | 
|---|
 | 1953 |   double x;
 | 
|---|
 | 1954 |   int n;
 | 
|---|
 | 1955 |   int N[NDIM];
 | 
|---|
 | 1956 |   N[0] = LevS->Plan0.plan->N[0];
 | 
|---|
 | 1957 |   N[1] = LevS->Plan0.plan->N[1];
 | 
|---|
 | 1958 |   N[2] = LevS->Plan0.plan->N[2];
 | 
|---|
 | 1959 |   
 | 
|---|
 | 1960 |   for (n=0;n<N[index];n++) {
 | 
|---|
 | 1961 |     x = (double)n/(double)N[index] * Lat->RealBasisQ[index];
 | 
|---|
 | 1962 |     //fprintf(stderr,"(%i) x %e\t Axis/2 %e\n",P->Par.me, x, Lat->RealBasisQ[index]/2. );     
 | 
|---|
 | 1963 |     x = MinImageConv(Lat, x, Lat->RealBasisQ[index]/2., index);
 | 
|---|
 | 1964 |     fprintf(stderr,"%e\t%e\n", x, sawtooth(Lat,x,index));  
 | 
|---|
 | 1965 |   }  
 | 
|---|
 | 1966 | }
 | 
|---|
 | 1967 | 
 | 
|---|
 | 1968 | /** Secures minimum image convention between two given points \a R[] and \a r[] within periodic boundary.
 | 
|---|
 | 1969 |  * Each distance component within a periodic boundary must always be between -L/2 ... L/2
 | 
|---|
 | 1970 |  * \param *Lat pointer to Lattice structure
 | 
|---|
 | 1971 |  * \param R[] first vector, NDIM, each must be between 0...L
 | 
|---|
 | 1972 |  * \param r[] second vector, NDIM, each must be between 0...L
 | 
|---|
 | 1973 |  * \param index of component
 | 
|---|
 | 1974 |  * \return component between  -L/2 ... L/2
 | 
|---|
 | 1975 |  */
 | 
|---|
 | 1976 | inline double MinImageConv(struct Lattice *Lat, const double R, const double r, const int index)
 | 
|---|
 | 1977 | {
 | 
|---|
 | 1978 |   double axis = Lat->RealBasisQ[index];
 | 
|---|
 | 1979 |   double result = 0.;
 | 
|---|
 | 1980 | 
 | 
|---|
 | 1981 |   if (fabs(result = R - r + axis) < axis/2.) { }
 | 
|---|
 | 1982 |   else if (fabs(result = R - r) <= axis/2.) { }
 | 
|---|
 | 1983 |    else if (fabs(result = R - r - axis) < axis/2.) { }
 | 
|---|
 | 1984 |     else Error(SomeError, "MinImageConv: None of the three cases applied!");
 | 
|---|
 | 1985 |   return (result);
 | 
|---|
 | 1986 | }
 | 
|---|
 | 1987 | 
 | 
|---|
 | 1988 | 
 | 
|---|
 | 1989 | /** Fouriertransforms given \a source.
 | 
|---|
 | 1990 |  * By the use of the symmetry parameter an additional imaginary unit and/or the momentum operator can
 | 
|---|
 | 1991 |  * be applied at the same time.
 | 
|---|
 | 1992 |  * \param *P Problem at hand
 | 
|---|
 | 1993 |  * \param *Psi source array of reciprocal coefficients
 | 
|---|
 | 1994 |  * \param *PsiR destination array, becoming filled with real coefficients
 | 
|---|
 | 1995 |  * \param index_g component of G vector (only needed for symmetry=4..7)
 | 
|---|
 | 1996 |  * \param symmetry 0 - do nothing, 1 - factor by "-1", 2 - factor by "i", 3 - factor by "1/i = -i", from 4 to 7 the same 
 | 
|---|
 | 1997 |  *        but additionally with momentum operator 
 | 
|---|
 | 1998 |  */
 | 
|---|
 | 1999 | void fft_Psi(struct Problem *P, const fftw_complex *Psi, fftw_real *PsiR, const int index_g, const int symmetry)
 | 
|---|
 | 2000 | {
 | 
|---|
 | 2001 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 2002 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2003 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 2004 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 2005 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 2006 |   struct  fft_plan_3d *plan = Lat->plan;
 | 
|---|
 | 2007 |   fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityArray[TempDensity];
 | 
|---|
 | 2008 |   fftw_complex *work = Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 2009 |   fftw_complex *posfac, *destpos, *destRCS, *destRCD;
 | 
|---|
 | 2010 |   int i, Index, pos;
 | 
|---|
 | 2011 | 
 | 
|---|
 | 2012 |   LockDensityArray(Dens0,TempDensity,imag); // tempdestRC
 | 
|---|
 | 2013 |   SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
 | 
|---|
 | 2014 |   SetArrayToDouble0((double *)PsiR, Dens0->TotalSize*2);
 | 
|---|
 | 2015 |   switch (symmetry) {
 | 
|---|
 | 2016 |     case 0:
 | 
|---|
 | 2017 |       for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
 | 
|---|
 | 2018 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2019 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2020 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2021 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2022 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2023 |           destpos[pos].re = (Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im;
 | 
|---|
 | 2024 |           destpos[pos].im = (Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re;
 | 
|---|
 | 2025 |         }
 | 
|---|
 | 2026 |       }
 | 
|---|
 | 2027 |       break;
 | 
|---|
 | 2028 |     case 1:
 | 
|---|
 | 2029 |       for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is - positive
 | 
|---|
 | 2030 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2031 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2032 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2033 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2034 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2035 |           destpos[pos].re = -((Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im);
 | 
|---|
 | 2036 |           destpos[pos].im = -((Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re);
 | 
|---|
 | 2037 |         }
 | 
|---|
 | 2038 |       }
 | 
|---|
 | 2039 |       break;
 | 
|---|
 | 2040 |     case 2:
 | 
|---|
 | 2041 |       for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is negative
 | 
|---|
 | 2042 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2043 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2044 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2045 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2046 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2047 |           destpos[pos].re = (-Psi[i].im)*posfac[pos].re-(Psi[i].re)*posfac[pos].im;
 | 
|---|
 | 2048 |           destpos[pos].im = (-Psi[i].im)*posfac[pos].im+(Psi[i].re)*posfac[pos].re;
 | 
|---|
 | 2049 |         }
 | 
|---|
 | 2050 |       }
 | 
|---|
 | 2051 |       break;
 | 
|---|
 | 2052 |     case 3:
 | 
|---|
 | 2053 |       for (i=0;i<LevS->MaxG;i++) { // incoming is negative, outgoing is positive
 | 
|---|
 | 2054 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2055 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2056 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2057 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2058 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2059 |           destpos[pos].re = (Psi[i].im)*posfac[pos].re-(-Psi[i].re)*posfac[pos].im;
 | 
|---|
 | 2060 |           destpos[pos].im = (Psi[i].im)*posfac[pos].im+(-Psi[i].re)*posfac[pos].re;
 | 
|---|
 | 2061 |         }
 | 
|---|
 | 2062 |       }
 | 
|---|
 | 2063 |       break;
 | 
|---|
 | 2064 |     case 4:
 | 
|---|
 | 2065 |       for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
 | 
|---|
 | 2066 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2067 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2068 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2069 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2070 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2071 |           destpos[pos].re = LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im);
 | 
|---|
 | 2072 |           destpos[pos].im = LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re);
 | 
|---|
 | 2073 |         }
 | 
|---|
 | 2074 |       }
 | 
|---|
 | 2075 |       break;
 | 
|---|
 | 2076 |     case 5:
 | 
|---|
 | 2077 |       for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is - positive
 | 
|---|
 | 2078 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2079 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2080 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2081 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2082 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2083 |           destpos[pos].re = -LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im);
 | 
|---|
 | 2084 |           destpos[pos].im = -LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re);
 | 
|---|
 | 2085 |         }
 | 
|---|
 | 2086 |       }
 | 
|---|
 | 2087 |       break;
 | 
|---|
 | 2088 |     case 6:
 | 
|---|
 | 2089 |       for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is negative
 | 
|---|
 | 2090 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2091 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2092 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2093 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2094 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2095 |           destpos[pos].re = LevS->GArray[i].G[index_g]*((-Psi[i].im)*posfac[pos].re-(Psi[i].re)*posfac[pos].im);
 | 
|---|
 | 2096 |           destpos[pos].im = LevS->GArray[i].G[index_g]*((-Psi[i].im)*posfac[pos].im+(Psi[i].re)*posfac[pos].re);
 | 
|---|
 | 2097 |         }
 | 
|---|
 | 2098 |       }
 | 
|---|
 | 2099 |       break;
 | 
|---|
 | 2100 |     case 7:
 | 
|---|
 | 2101 |       for (i=0;i<LevS->MaxG;i++) { // incoming is negative, outgoing is positive
 | 
|---|
 | 2102 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 2103 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 2104 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 2105 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2106 |           //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
 | 
|---|
 | 2107 |           destpos[pos].re = LevS->GArray[i].G[index_g]*((Psi[i].im)*posfac[pos].re-(-Psi[i].re)*posfac[pos].im);
 | 
|---|
 | 2108 |           destpos[pos].im = LevS->GArray[i].G[index_g]*((Psi[i].im)*posfac[pos].im+(-Psi[i].re)*posfac[pos].re);
 | 
|---|
 | 2109 |         }
 | 
|---|
 | 2110 |       }
 | 
|---|
 | 2111 |       break;
 | 
|---|
 | 2112 |   }
 | 
|---|
 | 2113 |   for (i=0; i<LevS->MaxDoubleG; i++) {
 | 
|---|
 | 2114 |     destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
 | 
|---|
 | 2115 |     destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
 | 
|---|
 | 2116 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 2117 |       //if (destRCD != &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp] || LevS->DoubleG[2*i+1]*LevS->MaxNUp+pos<0 || LevS->DoubleG[2*i+1]*LevS->MaxNUp+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destRCD corrupted");
 | 
|---|
 | 2118 |       destRCD[pos].re =  destRCS[pos].re;
 | 
|---|
 | 2119 |       destRCD[pos].im = -destRCS[pos].im;
 | 
|---|
 | 2120 |     }
 | 
|---|
 | 2121 |   }
 | 
|---|
 | 2122 |   fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
 | 
|---|
 | 2123 |   DensityRTransformPos(LevS,(fftw_real*)tempdestRC, PsiR);
 | 
|---|
 | 2124 |   UnLockDensityArray(Dens0,TempDensity,imag); // tempdestRC
 | 
|---|
 | 2125 | }
 | 
|---|
 | 2126 | 
 | 
|---|
 | 2127 | /** Locks all NDIM_NDIM current density arrays
 | 
|---|
 | 2128 |  * \param Dens0 Density structure to be locked (in the current parts)
 | 
|---|
 | 2129 |  */
 | 
|---|
 | 2130 | void AllocCurrentDensity(struct Density *Dens0) {
 | 
|---|
 | 2131 |   // real
 | 
|---|
 | 2132 |   LockDensityArray(Dens0,CurrentDensity0,real); // CurrentDensity[B_index]
 | 
|---|
 | 2133 |   LockDensityArray(Dens0,CurrentDensity1,real); // CurrentDensity[B_index]
 | 
|---|
 | 2134 |   LockDensityArray(Dens0,CurrentDensity2,real); // CurrentDensity[B_index]
 | 
|---|
 | 2135 |   LockDensityArray(Dens0,CurrentDensity3,real); // CurrentDensity[B_index]
 | 
|---|
 | 2136 |   LockDensityArray(Dens0,CurrentDensity4,real); // CurrentDensity[B_index]
 | 
|---|
 | 2137 |   LockDensityArray(Dens0,CurrentDensity5,real); // CurrentDensity[B_index]
 | 
|---|
 | 2138 |   LockDensityArray(Dens0,CurrentDensity6,real); // CurrentDensity[B_index]
 | 
|---|
 | 2139 |   LockDensityArray(Dens0,CurrentDensity7,real); // CurrentDensity[B_index]
 | 
|---|
 | 2140 |   LockDensityArray(Dens0,CurrentDensity8,real); // CurrentDensity[B_index]
 | 
|---|
 | 2141 |   // imaginary
 | 
|---|
 | 2142 |   LockDensityArray(Dens0,CurrentDensity0,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2143 |   LockDensityArray(Dens0,CurrentDensity1,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2144 |   LockDensityArray(Dens0,CurrentDensity2,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2145 |   LockDensityArray(Dens0,CurrentDensity3,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2146 |   LockDensityArray(Dens0,CurrentDensity4,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2147 |   LockDensityArray(Dens0,CurrentDensity5,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2148 |   LockDensityArray(Dens0,CurrentDensity6,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2149 |   LockDensityArray(Dens0,CurrentDensity7,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2150 |   LockDensityArray(Dens0,CurrentDensity8,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2151 | }
 | 
|---|
 | 2152 | 
 | 
|---|
 | 2153 | /** Reset and unlocks all NDIM_NDIM current density arrays
 | 
|---|
 | 2154 |  * \param Dens0 Density structure to be unlocked/resetted (in the current parts)
 | 
|---|
 | 2155 |  */
 | 
|---|
 | 2156 | void DisAllocCurrentDensity(struct Density *Dens0) {
 | 
|---|
 | 2157 |   //int i;
 | 
|---|
 | 2158 |   // real
 | 
|---|
 | 2159 | //  for(i=0;i<NDIM*NDIM;i++)
 | 
|---|
 | 2160 | //    SetArrayToDouble0((double *)Dens0->DensityArray[i], Dens0->TotalSize*2);
 | 
|---|
 | 2161 |   UnLockDensityArray(Dens0,CurrentDensity0,real); // CurrentDensity[B_index]
 | 
|---|
 | 2162 |   UnLockDensityArray(Dens0,CurrentDensity1,real); // CurrentDensity[B_index]
 | 
|---|
 | 2163 |   UnLockDensityArray(Dens0,CurrentDensity2,real); // CurrentDensity[B_index]
 | 
|---|
 | 2164 |   UnLockDensityArray(Dens0,CurrentDensity3,real); // CurrentDensity[B_index]
 | 
|---|
 | 2165 |   UnLockDensityArray(Dens0,CurrentDensity4,real); // CurrentDensity[B_index]
 | 
|---|
 | 2166 |   UnLockDensityArray(Dens0,CurrentDensity5,real); // CurrentDensity[B_index]
 | 
|---|
 | 2167 |   UnLockDensityArray(Dens0,CurrentDensity6,real); // CurrentDensity[B_index]
 | 
|---|
 | 2168 |   UnLockDensityArray(Dens0,CurrentDensity7,real); // CurrentDensity[B_index]
 | 
|---|
 | 2169 |   UnLockDensityArray(Dens0,CurrentDensity8,real); // CurrentDensity[B_index]
 | 
|---|
 | 2170 |   // imaginary
 | 
|---|
 | 2171 | //  for(i=0;i<NDIM*NDIM;i++)
 | 
|---|
 | 2172 | //    SetArrayToDouble0((double *)Dens0->DensityCArray[i], Dens0->TotalSize*2);
 | 
|---|
 | 2173 |   UnLockDensityArray(Dens0,CurrentDensity0,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2174 |   UnLockDensityArray(Dens0,CurrentDensity1,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2175 |   UnLockDensityArray(Dens0,CurrentDensity2,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2176 |   UnLockDensityArray(Dens0,CurrentDensity3,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2177 |   UnLockDensityArray(Dens0,CurrentDensity4,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2178 |   UnLockDensityArray(Dens0,CurrentDensity5,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2179 |   UnLockDensityArray(Dens0,CurrentDensity6,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2180 |   UnLockDensityArray(Dens0,CurrentDensity7,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2181 |   UnLockDensityArray(Dens0,CurrentDensity8,imag); // CurrentDensity[B_index]
 | 
|---|
 | 2182 | }
 | 
|---|
 | 2183 | 
 | 
|---|
 | 2184 | // these defines safe-guard same symmetry for same kind of wave function
 | 
|---|
 | 2185 | #define Psi0symmetry 0  // //0 //0 //0 // regard psi0 as real
 | 
|---|
 | 2186 | #define Psi1symmetry 0  // //3 //0 //0 // regard psi0 as real
 | 
|---|
 | 2187 | #define Psip0symmetry 6 //6  //6 //6 //6 // momentum times "i" due to operation on left hand 
 | 
|---|
 | 2188 | #define Psip1symmetry 7 //7  //4 //6 //7 // momentum times "-i" as usual (right hand)
 | 
|---|
 | 2189 | 
 | 
|---|
 | 2190 | /** Evaluates the 3x3 current density arrays.
 | 
|---|
 | 2191 |  * The formula we want to evaluate is as follows
 | 
|---|
 | 2192 |  * \f[
 | 
|---|
 | 2193 |  *  j_k(r) = \langle \psi_k^{(0)} | \Bigl (  p|r'\rangle\langle r' | + | r' \rangle \langle r' | p \Bigr )
 | 
|---|
 | 2194 |               \Bigl [ | \psi_k^{(r\times p )} \rangle - r' \times | \psi_k^{(p)} \rangle \Bigr ] \cdot B.
 | 
|---|
 | 2195 |  * \f]
 | 
|---|
 | 2196 |  * Most of the DensityTypes-arrays are locked for temporary use. Pointers are set to their
 | 
|---|
 | 2197 |  * start address and afterwards the current density arrays locked and reset'ed. Then for every
 | 
|---|
 | 2198 |  * unperturbed wave function we do:
 | 
|---|
 | 2199 |  * -# FFT unperturbed p-perturbed and rxp-perturbed wave function
 | 
|---|
 | 2200 |  * -# FFT wave function with applied momentum operator for all three indices
 | 
|---|
 | 2201 |  * -# For each index of the momentum operator:
 | 
|---|
 | 2202 |  *  -# FFT p-perturbed wave function
 | 
|---|
 | 2203 |  *  -# For every index of the external field:
 | 
|---|
 | 2204 |  *    -# FFT rxp-perturbed wave function
 | 
|---|
 | 2205 |  *    -# Evaluate current density for these momentum index and external field indices
 | 
|---|
 | 2206 |  * 
 | 
|---|
 | 2207 |  * Afterwards the temporary densities are unlocked and the density ones gathered from all Psi-
 | 
|---|
 | 2208 |  * sharing processes. 
 | 
|---|
 | 2209 |  * 
 | 
|---|
 | 2210 |  * \param *P Problem at hand, containing Lattice and RunStruct
 | 
|---|
 | 2211 |  */ 
 | 
|---|
 | 2212 | void FillCurrentDensity(struct Problem *P)
 | 
|---|
 | 2213 | {
 | 
|---|
 | 2214 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 2215 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2216 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 2217 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 2218 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 2219 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 2220 |   fftw_complex *Psi0;
 | 
|---|
 | 2221 |   fftw_real *Psi0R, *Psip0R;
 | 
|---|
 | 2222 |   fftw_real *CurrentDensity[NDIM*NDIM];
 | 
|---|
 | 2223 |   fftw_real *Psi1R;
 | 
|---|
 | 2224 |   fftw_real *Psip1R;
 | 
|---|
 | 2225 |   fftw_real *tempArray; // intendedly the same
 | 
|---|
 | 2226 |   double r_bar[NDIM], x[NDIM], fac[NDIM];
 | 
|---|
 | 2227 |   double Current;//, current;
 | 
|---|
 | 2228 |   const double UnitsFactor = 1.; ///LevS->MaxN;  // 1/N (from ff-backtransform)
 | 
|---|
 | 2229 |   int i, index, B_index;
 | 
|---|
 | 2230 |   int k, j, i0;
 | 
|---|
 | 2231 |   int n[NDIM], n0;
 | 
|---|
 | 2232 |   int N[NDIM];
 | 
|---|
 | 2233 |   N[0] = Lev0->Plan0.plan->N[0];
 | 
|---|
 | 2234 |   N[1] = Lev0->Plan0.plan->N[1];
 | 
|---|
 | 2235 |   N[2] = Lev0->Plan0.plan->N[2];
 | 
|---|
 | 2236 |   const int N0 = Lev0->Plan0.plan->local_nx;
 | 
|---|
 | 2237 |   //int ActNum;
 | 
|---|
 | 2238 |   const int myPE =  P->Par.me_comm_ST_Psi;
 | 
|---|
 | 2239 |   const int type = R->CurrentMin;
 | 
|---|
 | 2240 |   MPI_Status status;
 | 
|---|
 | 2241 |   int cross_lookup_1[4], cross_lookup_3[4], l_1 = 0, l_3 = 0;
 | 
|---|
 | 2242 | 
 | 
|---|
 | 2243 |   //fprintf(stderr,"(%i) FactoR %e\n", P->Par.me, R->FactorDensityR);
 | 
|---|
 | 2244 | 
 | 
|---|
 | 2245 |   // Init values and pointers
 | 
|---|
 | 2246 |   if (P->Call.out[PsiOut]) {
 | 
|---|
 | 2247 |     fprintf(stderr,"(%i) LockArray: ", P->Par.me);
 | 
|---|
 | 2248 |     for(i=0;i<MaxDensityTypes;i++)
 | 
|---|
 | 2249 |       fprintf(stderr,"(%i,%i) ",Dens0->LockArray[i],Dens0->LockCArray[i]);
 | 
|---|
 | 2250 |     fprintf(stderr,"\n");
 | 
|---|
 | 2251 |   }
 | 
|---|
 | 2252 |   LockDensityArray(Dens0,Temp2Density,real); // Psi1R
 | 
|---|
 | 2253 |   LockDensityArray(Dens0,Temp2Density,imag); // Psip1R and tempArray
 | 
|---|
 | 2254 |   LockDensityArray(Dens0,GapDensity,real); // Psi0R
 | 
|---|
 | 2255 |   LockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
 | 
|---|
 | 2256 | 
 | 
|---|
 | 2257 |   Psi0R = (fftw_real *)Dens0->DensityArray[GapDensity];
 | 
|---|
 | 2258 |   Psip0R = (fftw_real *)Dens0->DensityArray[GapLocalDensity];  
 | 
|---|
 | 2259 |   Psi1R = (fftw_real *)Dens0->DensityArray[Temp2Density];
 | 
|---|
 | 2260 |   tempArray = Psip1R = (fftw_real *)Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 2261 |   SetArrayToDouble0((double *)Psi0R,Dens0->TotalSize*2);
 | 
|---|
 | 2262 |   SetArrayToDouble0((double *)Psip0R,Dens0->TotalSize*2);
 | 
|---|
 | 2263 |   SetArrayToDouble0((double *)Psi1R,Dens0->TotalSize*2);
 | 
|---|
 | 2264 |   SetArrayToDouble0((double *)Psip1R,Dens0->TotalSize*2);
 | 
|---|
 | 2265 | 
 | 
|---|
 | 2266 |   if (P->Call.out[PsiOut]) {
 | 
|---|
 | 2267 |     fprintf(stderr,"(%i) LockArray: ", P->Par.me);
 | 
|---|
 | 2268 |     for(i=0;i<MaxDensityTypes;i++)
 | 
|---|
 | 2269 |       fprintf(stderr,"(%i,%i) ",Dens0->LockArray[i],Dens0->LockCArray[i]);
 | 
|---|
 | 2270 |     fprintf(stderr,"\n");
 | 
|---|
 | 2271 |   }
 | 
|---|
 | 2272 |   
 | 
|---|
 | 2273 |   // don't put the following stuff into a for loop, they might not be continuous! (preprocessor values: CurrentDensity...) 
 | 
|---|
 | 2274 |   CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
 | 
|---|
 | 2275 |   CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
 | 
|---|
 | 2276 |   CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
 | 
|---|
 | 2277 |   CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
 | 
|---|
 | 2278 |   CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
 | 
|---|
 | 2279 |   CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
 | 
|---|
 | 2280 |   CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
 | 
|---|
 | 2281 |   CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
 | 
|---|
 | 2282 |   CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
 | 
|---|
 | 2283 |  
 | 
|---|
 | 2284 |   // initialize the array if it is the first of all six perturbation run
 | 
|---|
 | 2285 |   if ((R->DoFullCurrent == 0) && (R->CurrentMin == Perturbed_P0)) { // reset if FillDelta...() hasn't done it before 
 | 
|---|
 | 2286 |     debug(P,"resetting CurrentDensity...");
 | 
|---|
 | 2287 |     for (B_index=0; B_index<NDIM*NDIM; B_index++) // initialize current density array
 | 
|---|
 | 2288 |       SetArrayToDouble0((double *)CurrentDensity[B_index],Dens0->TotalSize*2); // DensityArray is fftw_real, no 2*LocalSizeR here!
 | 
|---|
 | 2289 |   } 
 | 
|---|
 | 2290 | 
 | 
|---|
 | 2291 |   switch(type) { // set j (which is linked to the index from derivation wrt to B^{ext})
 | 
|---|
 | 2292 |     case Perturbed_P0:
 | 
|---|
 | 2293 |     case Perturbed_P1:
 | 
|---|
 | 2294 |     case Perturbed_P2:
 | 
|---|
 | 2295 |       j = type - Perturbed_P0;
 | 
|---|
 | 2296 |       l_1 = crossed(j,1);
 | 
|---|
 | 2297 |       l_3 = crossed(j,3);
 | 
|---|
 | 2298 |       for(k=0;k<4;k++) {
 | 
|---|
 | 2299 |         cross_lookup_1[k] = cross(l_1,k);
 | 
|---|
 | 2300 |         cross_lookup_3[k] = cross(l_3,k);
 | 
|---|
 | 2301 |       }
 | 
|---|
 | 2302 |       break;
 | 
|---|
 | 2303 |     case Perturbed_RxP0:
 | 
|---|
 | 2304 |     case Perturbed_RxP1:
 | 
|---|
 | 2305 |     case Perturbed_RxP2:
 | 
|---|
 | 2306 |       j = type - Perturbed_RxP0;
 | 
|---|
 | 2307 |       break;
 | 
|---|
 | 2308 |     default:
 | 
|---|
 | 2309 |       j = 0;
 | 
|---|
 | 2310 |       Error(SomeError,"FillCurrentDensity() called while not in perturbed minimisation!");
 | 
|---|
 | 2311 |     break;
 | 
|---|
 | 2312 |   }
 | 
|---|
 | 2313 |   
 | 
|---|
 | 2314 |   int wished = -1;
 | 
|---|
 | 2315 |   FILE *file =  fopen(P->Call.MainParameterFile,"r");
 | 
|---|
| [961b75] | 2316 |   if (!ParseForParameter(1,file,"Orbital",0,1,1,int_type,&wished, 1, optional)) {
 | 
|---|
| [a0bcf1] | 2317 |     fprintf(stderr,"Desired Orbital missing!\n");
 | 
|---|
 | 2318 |     wished = -1;
 | 
|---|
 | 2319 |   } else if (wished != -1) {
 | 
|---|
 | 2320 |     fprintf(stderr,"Desired Orbital is: %i.\n", wished);
 | 
|---|
 | 2321 |   } else { 
 | 
|---|
 | 2322 |     fprintf(stderr,"Desired Orbital is: All.\n");
 | 
|---|
 | 2323 |   }
 | 
|---|
 | 2324 |   fclose(file);
 | 
|---|
 | 2325 |   
 | 
|---|
 | 2326 |    // Commence grid filling
 | 
|---|
 | 2327 |   for (k=Psi->TypeStartIndex[Occupied];k<Psi->TypeStartIndex[Occupied+1];k++)  // every local wave functions adds up its part of the current
 | 
|---|
 | 2328 |     if ((k + P->Par.me_comm_ST_PsiT*(Psi->TypeStartIndex[UnOccupied]-Psi->TypeStartIndex[Occupied]) == wished) || (wished == -1)) {  // compare with global number
 | 
|---|
 | 2329 |     if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i)Calculating Current Density Summand of type %s for Psi (%i/%i) ... \n", P->Par.me, R->MinimisationName[type], Psi->LocalPsiStatus[k].MyGlobalNo, k);
 | 
|---|
 | 2330 |     //ActNum = k - Psi->TypeStartIndex[Occupied] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[k].my_color_comm_ST_Psi; // global number of unperturbed Psi
 | 
|---|
 | 2331 |     Psi0 = LevS->LPsi->LocalPsi[k]; // Local unperturbed psi
 | 
|---|
 | 2332 | 
 | 
|---|
 | 2333 |     // now some preemptive ffts for the whole grid      
 | 
|---|
 | 2334 |     if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi0> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2335 |     fft_Psi(P, Psi0, Psi0R, 0, Psi0symmetry);  //0 // 0 //0
 | 
|---|
 | 2336 | 
 | 
|---|
 | 2337 |     if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi1> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2338 |     fft_Psi(P, LevS->LPsi->LocalPsi[Psi->TypeStartIndex[type]+k], Psi1R, 0, Psi1symmetry); //3 //0 //0
 | 
|---|
 | 2339 | 
 | 
|---|
 | 2340 |     for (index=0;index<NDIM;index++) { // for all NDIM components of momentum operator
 | 
|---|
 | 2341 |       
 | 
|---|
 | 2342 |       if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi0> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2343 |       fft_Psi(P, Psi0, Psip0R, index, Psip0symmetry); //6 //6 //6
 | 
|---|
 | 2344 | 
 | 
|---|
 | 2345 |       if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi1> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2346 |       fft_Psi(P, LevS->LPsi->LocalPsi[Psi->TypeStartIndex[type]+k], Psip1R, index, Psip1symmetry);  //4 //6 //7
 | 
|---|
 | 2347 |       
 | 
|---|
 | 2348 |       // then for every point on the grid in real space ...
 | 
|---|
 | 2349 | 
 | 
|---|
 | 2350 |       //if (Psi1R != (fftw_real *)Dens0->DensityArray[Temp2Density] || i0<0 || i0>=Dens0->LocalSizeR) Error(SomeError,"fft_Psi: Psi1R corrupted");
 | 
|---|
 | 2351 |        //Psi1R[i0] = (Psi1_rxp_R[j])[i0] - (r_bar[cross(j,0)] *  (Psi1_p_R[cross(j,1)])[i0] - r_bar[cross(j,2)] *  (Psi1_p_R[cross(j,3)])[i0]); // 
 | 
|---|
 | 2352 |       //if (Psip1R != (fftw_real *)Dens0->DensityCArray[Temp2Density] || i0<0 || i0>=Dens0->LocalSizeR) Error(SomeError,"fft_Psi: Psip1R corrupted");
 | 
|---|
 | 2353 |       //Psip1R[i0] = Psi1_rxp_pR[i0] - (r_bar[cross(j,0)] * (Psi1_p_pR[cross(j,1)])[i0] - r_bar[cross(j,2)] * (Psi1_p_pR[cross(j,3)])[i0]); //  
 | 
|---|
 | 2354 | 
 | 
|---|
 | 2355 |       switch(type) {
 | 
|---|
 | 2356 |         case Perturbed_P0:
 | 
|---|
 | 2357 |         case Perturbed_P1:
 | 
|---|
 | 2358 |         case Perturbed_P2:
 | 
|---|
 | 2359 |           for (n0=0;n0<N0;n0++)  // only local points on x axis
 | 
|---|
 | 2360 |             for (n[1]=0;n[1]<N[1];n[1]++)
 | 
|---|
 | 2361 |               for (n[2]=0;n[2]<N[2];n[2]++) {
 | 
|---|
 | 2362 |                 i0 = n[2]+N[2]*(n[1]+N[1]*n0);
 | 
|---|
 | 2363 |                 n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
 | 
|---|
 | 2364 |                 fac[0] = (double)n[0]/(double)N[0];
 | 
|---|
 | 2365 |                 fac[1] = (double)n[1]/(double)N[1];
 | 
|---|
 | 2366 |                 fac[2] = (double)n[2]/(double)N[2];
 | 
|---|
 | 2367 |                 RMat33Vec3(x, Lat->RealBasis, fac); // relative coordinate times basis matrix gives absolute ones
 | 
|---|
 | 2368 |                 for (i=0;i<NDIM;i++) // build gauge-translated r_bar evaluation point
 | 
|---|
 | 2369 |                   r_bar[i] = 
 | 
|---|
 | 2370 |                     sawtooth(Lat,MinImageConv(Lat, x[i], Psi->AddData[k].WannierCentre[i], i),i);
 | 
|---|
 | 2371 | //                    ShiftGaugeOrigin(P,truedist(Lat, x[i], Psi->AddData[k].WannierCentre[i], i),i);
 | 
|---|
 | 2372 |                     //truedist(Lat, x[i], Psi->AddData[k].WannierCentre[i], i);
 | 
|---|
 | 2373 |                 
 | 
|---|
 | 2374 |                 Current = Psip0R[i0] * (r_bar[cross_lookup_1[0]] * Psi1R[i0]);
 | 
|---|
 | 2375 |                 Current += (Psi0R[i0] * r_bar[cross_lookup_1[0]] * Psip1R[i0]);
 | 
|---|
 | 2376 |                 Current *= .5 * UnitsFactor * Psi->LocalPsiStatus[k].PsiFactor * R->FactorDensityR; // factor confirmed, see CalculateOneDensityR() and InitDensityCalculation()
 | 
|---|
 | 2377 |                 ////if (CurrentDensity[index+j*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+j*NDIM] || i0<0 || i0>=Dens0->LocalSizeR || (index+j*NDIM)<0 || (index+j*NDIM)>=NDIM*NDIM) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2378 |                 CurrentDensity[index+l_1*NDIM][i0] -= Current; // note: sign of cross product resides in Current itself (here: plus)
 | 
|---|
 | 2379 |                 
 | 
|---|
 | 2380 |                 Current = - Psip0R[i0] * (r_bar[cross_lookup_3[2]] * Psi1R[i0]);
 | 
|---|
 | 2381 |                 Current += - (Psi0R[i0] * r_bar[cross_lookup_3[2]] * Psip1R[i0]);
 | 
|---|
 | 2382 |                 Current *= .5 * UnitsFactor * Psi->LocalPsiStatus[k].PsiFactor * R->FactorDensityR; // factor confirmed, see CalculateOneDensityR() and InitDensityCalculation()
 | 
|---|
 | 2383 |                 ////if (CurrentDensity[index+j*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+j*NDIM] || i0<0 || i0>=Dens0->LocalSizeR || (index+j*NDIM)<0 || (index+j*NDIM)>=NDIM*NDIM) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2384 |                 CurrentDensity[index+l_3*NDIM][i0] -= Current; // note: sign of cross product resides in Current itself (here: minus)
 | 
|---|
 | 2385 |               }
 | 
|---|
 | 2386 |           break;
 | 
|---|
 | 2387 |         case Perturbed_RxP0:
 | 
|---|
 | 2388 |         case Perturbed_RxP1:
 | 
|---|
 | 2389 |         case Perturbed_RxP2:
 | 
|---|
 | 2390 |           for (n0=0;n0<N0;n0++)  // only local points on x axis
 | 
|---|
 | 2391 |             for (n[1]=0;n[1]<N[1];n[1]++)
 | 
|---|
 | 2392 |               for (n[2]=0;n[2]<N[2];n[2]++) {
 | 
|---|
 | 2393 |                 i0 = n[2]+N[2]*(n[1]+N[1]*n0);
 | 
|---|
 | 2394 |                 Current = (Psip0R[i0] * Psi1R[i0] + Psi0R[i0] * Psip1R[i0]);
 | 
|---|
 | 2395 |                 Current *= .5 * UnitsFactor * Psi->LocalPsiStatus[k].PsiFactor * R->FactorDensityR; // factor confirmed, see CalculateOneDensityR() and InitDensityCalculation()
 | 
|---|
 | 2396 |                 ////if (CurrentDensity[index+j*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+j*NDIM] || i0<0 || i0>=Dens0->LocalSizeR || (index+j*NDIM)<0 || (index+j*NDIM)>=NDIM*NDIM) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2397 |                 CurrentDensity[index+j*NDIM][i0] += Current;
 | 
|---|
 | 2398 |               }
 | 
|---|
 | 2399 |           break;
 | 
|---|
 | 2400 |          default:
 | 
|---|
 | 2401 |           break;
 | 
|---|
 | 2402 |       }
 | 
|---|
 | 2403 |     }
 | 
|---|
 | 2404 |     //OutputCurrentDensity(P);
 | 
|---|
 | 2405 |   }
 | 
|---|
 | 2406 |   
 | 
|---|
 | 2407 |   //debug(P,"Unlocking arrays");
 | 
|---|
 | 2408 |   //debug(P,"GapDensity");
 | 
|---|
 | 2409 |   UnLockDensityArray(Dens0,GapDensity,real); // Psi0R
 | 
|---|
 | 2410 |   //debug(P,"GapLocalDensity");
 | 
|---|
 | 2411 |   UnLockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
 | 
|---|
 | 2412 |   //debug(P,"Temp2Density");
 | 
|---|
 | 2413 |   UnLockDensityArray(Dens0,Temp2Density,real); // Psi1R
 | 
|---|
 | 2414 |   
 | 
|---|
 | 2415 | //  if (P->Call.out[StepLeaderOut]) 
 | 
|---|
 | 2416 | //    fprintf(stderr,"\n\n");
 | 
|---|
 | 2417 |     
 | 
|---|
 | 2418 |   //debug(P,"MPI operation");
 | 
|---|
 | 2419 |   // and in the end gather partial densities from other processes
 | 
|---|
 | 2420 |   if (type == Perturbed_RxP2) // exchange all (due to shared wave functions) only after last pertubation run
 | 
|---|
 | 2421 |     for (index=0;index<NDIM*NDIM;index++) {
 | 
|---|
 | 2422 |       //if (tempArray != (fftw_real *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"FillCurrentDensity: tempArray corrupted");
 | 
|---|
 | 2423 |       //debug(P,"tempArray to zero");
 | 
|---|
 | 2424 |       SetArrayToDouble0((double *)tempArray, Dens0->TotalSize*2);
 | 
|---|
 | 2425 |       ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index]) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2426 |       //debug(P,"CurrentDensity exchange");
 | 
|---|
 | 2427 |       MPI_Allreduce( CurrentDensity[index], tempArray, Dens0->LocalSizeR, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT); // gather results from all wave functions ...
 | 
|---|
 | 2428 |       switch(Psi->PsiST) {  // ... and also from SpinUp/Downs
 | 
|---|
 | 2429 |         default:
 | 
|---|
 | 2430 |             //debug(P,"CurrentDensity = tempArray");
 | 
|---|
 | 2431 |             for (i=0;i<Dens0->LocalSizeR;i++) {
 | 
|---|
 | 2432 |               ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index] || i<0 || i>=Dens0->LocalSizeR) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2433 |               CurrentDensity[index][i] = tempArray[i];
 | 
|---|
 | 2434 |             }
 | 
|---|
 | 2435 |             break;
 | 
|---|
 | 2436 |         case SpinUp:
 | 
|---|
 | 2437 |             //debug(P,"CurrentDensity exchange spinup");
 | 
|---|
 | 2438 |             MPI_Sendrecv(tempArray, Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag1,
 | 
|---|
 | 2439 |              CurrentDensity[index], Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag2, P->Par.comm_STInter, &status );
 | 
|---|
 | 2440 |             //debug(P,"CurrentDensity += tempArray");
 | 
|---|
 | 2441 |             for (i=0;i<Dens0->LocalSizeR;i++) {
 | 
|---|
 | 2442 |               ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index] || i<0 || i>=Dens0->LocalSizeR) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2443 |               CurrentDensity[index][i] += tempArray[i];
 | 
|---|
 | 2444 |             }
 | 
|---|
 | 2445 |             break;
 | 
|---|
 | 2446 |         case SpinDown:
 | 
|---|
 | 2447 |             //debug(P,"CurrentDensity exchange spindown");
 | 
|---|
 | 2448 |             MPI_Sendrecv(tempArray, Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag2,
 | 
|---|
 | 2449 |              CurrentDensity[index], Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag1, P->Par.comm_STInter, &status );
 | 
|---|
 | 2450 |             //debug(P,"CurrentDensity += tempArray");
 | 
|---|
 | 2451 |             for (i=0;i<Dens0->LocalSizeR;i++) {
 | 
|---|
 | 2452 |               ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index] || i<0 || i>=Dens0->LocalSizeR) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2453 |               CurrentDensity[index][i] += tempArray[i];
 | 
|---|
 | 2454 |             }
 | 
|---|
 | 2455 |             break;
 | 
|---|
 | 2456 |       }
 | 
|---|
 | 2457 |     }
 | 
|---|
 | 2458 |   //debug(P,"Temp2Density");
 | 
|---|
 | 2459 |   UnLockDensityArray(Dens0,Temp2Density,imag); // Psip1R and tempArray
 | 
|---|
 | 2460 |   //debug(P,"CurrentDensity end");
 | 
|---|
 | 2461 | }
 | 
|---|
 | 2462 | 
 | 
|---|
 | 2463 | /** Structure holding Problem at hand and two indices, defining the greens function to be inverted.
 | 
|---|
 | 2464 |  */
 | 
|---|
 | 2465 | struct params
 | 
|---|
 | 2466 | {
 | 
|---|
 | 2467 |   struct Problem *P;
 | 
|---|
 | 2468 |   int *k;
 | 
|---|
 | 2469 |   int *l;
 | 
|---|
 | 2470 |   int *iter;
 | 
|---|
 | 2471 |   fftw_complex *x_l;
 | 
|---|
 | 2472 | };
 | 
|---|
 | 2473 | 
 | 
|---|
 | 2474 | /** Wrapper function to solve G_kl x = b for x.
 | 
|---|
 | 2475 |  * \param *x above x
 | 
|---|
 | 2476 |  * \param *param additional parameters, here Problem at hand
 | 
|---|
 | 2477 |  * \return evaluated to be minimized functional \f$\frac{1}{2}x \cdot Ax - xb\f$ at \a x on return
 | 
|---|
 | 2478 |  */
 | 
|---|
 | 2479 | static double DeltaCurrent_f(const gsl_vector * x, void * param) 
 | 
|---|
 | 2480 | {
 | 
|---|
 | 2481 |   struct Problem *P = ((struct params *)param)->P;
 | 
|---|
 | 2482 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2483 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 2484 |   struct Psis *Psi = &P->Lat.Psi; 
 | 
|---|
 | 2485 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
 | 2486 |   const double PsiFactor = Psi->AllPsiStatus[*((struct params *)param)->k].PsiFactor;
 | 
|---|
 | 2487 |   double result = 0.;
 | 
|---|
 | 2488 |   fftw_complex *TempPsi = LevS->LPsi->TempPsi;
 | 
|---|
 | 2489 |   fftw_complex *TempPsi2 = LevS->LPsi->TempPsi2;
 | 
|---|
 | 2490 |   int u;
 | 
|---|
 | 2491 | 
 | 
|---|
 | 2492 |   //fprintf(stderr,"Evaluating f(%i,%i) for %i-th time\n", *((struct params *)param)->k, *((struct params *)param)->l, *((struct params *)param)->iter);
 | 
|---|
 | 2493 | 
 | 
|---|
 | 2494 |   // extract gsl_vector
 | 
|---|
 | 2495 |   for (u=0;u<LevS->MaxG;u++) {
 | 
|---|
 | 2496 |     TempPsi[u].re = gsl_vector_get(x, 2*u);
 | 
|---|
 | 2497 |     TempPsi[u].im = gsl_vector_get(x, 2*u+1);
 | 
|---|
 | 2498 |   }
 | 
|---|
 | 2499 |   // generate fnl
 | 
|---|
 | 2500 |   CalculateCDfnl(P, TempPsi, PP->CDfnl); // calculate needed non-local form factors
 | 
|---|
 | 2501 |   // Apply Hamiltonian to x
 | 
|---|
 | 2502 |   ApplyTotalHamiltonian(P,TempPsi,TempPsi2, PP->CDfnl,PsiFactor,0);
 | 
|---|
 | 2503 |   // take scalar product to get eigen value
 | 
|---|
 | 2504 |   result = .5 * PsiFactor * (((*((struct params *)param)->k == *((struct params *)param)->l ? GradSP(P,LevS,TempPsi,TempPsi2) : 0.) - Psi->lambda[*((struct params *)param)->k][*((struct params *)param)->l])) - GradSP(P,LevS,TempPsi,LevS->LPsi->LocalPsi[*((struct params *)param)->l]);
 | 
|---|
 | 2505 |   return result;
 | 
|---|
 | 2506 | }
 | 
|---|
 | 2507 | 
 | 
|---|
 | 2508 | /** Wrapper function to solve G_kl x = b for x.
 | 
|---|
 | 2509 |  * \param *x above x
 | 
|---|
 | 2510 |  * \param *param additional parameters, here Problem at hand
 | 
|---|
 | 2511 |  * \param *g gradient vector on return
 | 
|---|
 | 2512 |  * \return error code
 | 
|---|
 | 2513 |  */
 | 
|---|
 | 2514 | static void DeltaCurrent_df(const gsl_vector * x, void * param, gsl_vector * g)
 | 
|---|
 | 2515 | {
 | 
|---|
 | 2516 |   struct Problem *P = ((struct params *)param)->P;
 | 
|---|
 | 2517 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2518 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 2519 |   struct Psis *Psi = &P->Lat.Psi; 
 | 
|---|
 | 2520 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
 | 2521 |   const double PsiFactor = Psi->AllPsiStatus[*((struct params *)param)->k].PsiFactor;
 | 
|---|
 | 2522 |   fftw_complex *TempPsi = LevS->LPsi->TempPsi;
 | 
|---|
 | 2523 |   fftw_complex *TempPsi2 = LevS->LPsi->TempPsi2;
 | 
|---|
 | 2524 |   fftw_complex *x_l = ((struct params *)param)->x_l;
 | 
|---|
 | 2525 |   int u;
 | 
|---|
 | 2526 | 
 | 
|---|
 | 2527 |   //fprintf(stderr,"Evaluating df(%i,%i) for %i-th time\n", *((struct params *)param)->k, *((struct params *)param)->l, *((struct params *)param)->iter);
 | 
|---|
 | 2528 | 
 | 
|---|
 | 2529 |   // extract gsl_vector
 | 
|---|
 | 2530 |   for (u=0;u<LevS->MaxG;u++) {
 | 
|---|
 | 2531 |     TempPsi[u].re = gsl_vector_get(x, 2*u);
 | 
|---|
 | 2532 |     TempPsi[u].im = gsl_vector_get(x, 2*u+1);
 | 
|---|
 | 2533 |   }
 | 
|---|
 | 2534 |   // generate fnl
 | 
|---|
 | 2535 |   CalculateCDfnl(P, TempPsi, PP->CDfnl); // calculate needed non-local form factors
 | 
|---|
 | 2536 |   // Apply Hamiltonian to x
 | 
|---|
 | 2537 |   ApplyTotalHamiltonian(P,TempPsi,TempPsi2, PP->CDfnl,PsiFactor,0);
 | 
|---|
 | 2538 |   // put into returning vector
 | 
|---|
 | 2539 |   for (u=0;u<LevS->MaxG;u++) {
 | 
|---|
 | 2540 |     gsl_vector_set(g, 2*u, TempPsi2[u].re - x_l[u].re);
 | 
|---|
 | 2541 |     gsl_vector_set(g, 2*u+1, TempPsi2[u].im - x_l[u].im);
 | 
|---|
 | 2542 |   }
 | 
|---|
 | 2543 | }
 | 
|---|
 | 2544 | 
 | 
|---|
 | 2545 | /** Wrapper function to solve G_kl x = b for x.
 | 
|---|
 | 2546 |  * \param *x above x
 | 
|---|
 | 2547 |  * \param *param additional parameters, here Problem at hand
 | 
|---|
 | 2548 |  * \param *f evaluated to be minimized functional \f$\frac{1}{2}x \cdot Ax - xb\f$ at \a x on return
 | 
|---|
 | 2549 |  * \param *g gradient vector on return
 | 
|---|
 | 2550 |  * \return error code
 | 
|---|
 | 2551 |  */
 | 
|---|
 | 2552 | static void DeltaCurrent_fdf(const gsl_vector * x, void * param, double * f, gsl_vector * g)
 | 
|---|
 | 2553 | {
 | 
|---|
 | 2554 |   struct Problem *P = ((struct params *)param)->P;
 | 
|---|
 | 2555 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2556 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 2557 |   struct Psis *Psi = &P->Lat.Psi; 
 | 
|---|
 | 2558 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
 | 2559 |   const double PsiFactor = Psi->AllPsiStatus[*((struct params *)param)->k].PsiFactor;
 | 
|---|
 | 2560 |   fftw_complex *TempPsi = LevS->LPsi->TempPsi;
 | 
|---|
 | 2561 |   fftw_complex *TempPsi2 = LevS->LPsi->TempPsi2;
 | 
|---|
 | 2562 |   fftw_complex *x_l = ((struct params *)param)->x_l;
 | 
|---|
 | 2563 |   int u;
 | 
|---|
 | 2564 | 
 | 
|---|
 | 2565 |   //fprintf(stderr,"Evaluating fdf(%i,%i) for %i-th time\n", *((struct params *)param)->k, *((struct params *)param)->l, *((struct params *)param)->iter);
 | 
|---|
 | 2566 | 
 | 
|---|
 | 2567 |   // extract gsl_vector
 | 
|---|
 | 2568 |   for (u=0;u<LevS->MaxG;u++) {
 | 
|---|
 | 2569 |     TempPsi[u].re = gsl_vector_get(x, 2*u);
 | 
|---|
 | 2570 |     TempPsi[u].im = gsl_vector_get(x, 2*u+1);
 | 
|---|
 | 2571 |   }
 | 
|---|
 | 2572 |   // generate fnl
 | 
|---|
 | 2573 |   CalculateCDfnl(P, TempPsi, PP->CDfnl); // calculate needed non-local form factors
 | 
|---|
 | 2574 |   // Apply Hamiltonian to x
 | 
|---|
 | 2575 |   ApplyTotalHamiltonian(P,TempPsi,TempPsi2, PP->CDfnl,PsiFactor,0);
 | 
|---|
 | 2576 |   // put into returning vector
 | 
|---|
 | 2577 |   for (u=0;u<LevS->MaxG;u++) {
 | 
|---|
 | 2578 |     gsl_vector_set(g, 2*u, TempPsi[u].re - x_l[u].re);
 | 
|---|
 | 2579 |     gsl_vector_set(g, 2*u+1, TempPsi[u].im - x_l[u].im);
 | 
|---|
 | 2580 |   }
 | 
|---|
 | 2581 |   
 | 
|---|
 | 2582 |   *f = .5 * PsiFactor * (((*((struct params *)param)->k == *((struct params *)param)->l ? GradSP(P,LevS,TempPsi,TempPsi2) : 0.) - Psi->lambda[*((struct params *)param)->k][*((struct params *)param)->l])) - GradSP(P,LevS,TempPsi,LevS->LPsi->LocalPsi[*((struct params *)param)->l]);
 | 
|---|
 | 2583 | }
 | 
|---|
 | 2584 | 
 | 
|---|
 | 2585 | /** Evaluates the \f$\Delta j_k(r')\f$ component of the current density.
 | 
|---|
 | 2586 |  * \f[
 | 
|---|
 | 2587 |  *  \Delta j_k(r') = \frac{e}{m} \sum_l \langle \varphi^{(0)}_k | \left ( p |r'\rangle \langle r'| + | r'\rangle\langle r'|p \right ) {\cal G}_{kl} (d_k - d_l) \times p | \varphi^{(1)}_l \rangle \cdot B 
 | 
|---|
 | 2588 |  * \f]
 | 
|---|
 | 2589 |  * \param *P Problem at hand
 | 
|---|
 | 2590 |  * \note result has not yet been MPI_Allreduced for ParallelSimulationData#comm_ST_inter or ParallelSimulationData#comm_ST_PsiT groups!
 | 
|---|
 | 2591 |  * \warning the routine is checked but does  not yet produce sensible results.
 | 
|---|
 | 2592 |  */
 | 
|---|
 | 2593 | void FillDeltaCurrentDensity(struct Problem *P)
 | 
|---|
 | 2594 | {
 | 
|---|
 | 2595 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 2596 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2597 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 2598 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 2599 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 2600 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 2601 |   int i,j,s;
 | 
|---|
 | 2602 |   int k,l,u, in, dex, index,i0;
 | 
|---|
 | 2603 |   //const int Num = Psi->NoOfPsis;
 | 
|---|
 | 2604 |   int RecvSource;
 | 
|---|
 | 2605 |   MPI_Status status;
 | 
|---|
 | 2606 |   struct OnePsiElement *OnePsiB, *LOnePsiB, *OnePsiA, *LOnePsiA;
 | 
|---|
 | 2607 |   const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
 | 2608 |   int n[NDIM], n0;
 | 
|---|
 | 2609 |   int N[NDIM];
 | 
|---|
 | 2610 |   N[0] = Lev0->Plan0.plan->N[0];
 | 
|---|
 | 2611 |   N[1] = Lev0->Plan0.plan->N[1];
 | 
|---|
 | 2612 |   N[2] = Lev0->Plan0.plan->N[2];
 | 
|---|
 | 2613 |   const int N0 = Lev0->Plan0.plan->local_nx;
 | 
|---|
 | 2614 |   fftw_complex *LPsiDatB; 
 | 
|---|
 | 2615 |   fftw_complex *Psi0, *Psi1;
 | 
|---|
 | 2616 |   fftw_real *Psi0R, *Psip0R;
 | 
|---|
 | 2617 |   fftw_real *Psi1R, *Psip1R;
 | 
|---|
 | 2618 |   fftw_complex *x_l = LevS->LPsi->TempPsi;//, **x_l_bak;
 | 
|---|
 | 2619 |   fftw_real *CurrentDensity[NDIM*NDIM];
 | 
|---|
 | 2620 |   int mem_avail, MEM_avail;
 | 
|---|
 | 2621 |   double Current;
 | 
|---|
 | 2622 |   const double UnitsFactor = 1.;
 | 
|---|
 | 2623 |   int cross_lookup[4];
 | 
|---|
 | 2624 |   struct params param;
 | 
|---|
 | 2625 |   double factor;    // temporary factor in Psi1 pre-evaluation
 | 
|---|
 | 2626 |   
 | 
|---|
 | 2627 |   LockDensityArray(Dens0,GapDensity,real); // Psi0R
 | 
|---|
 | 2628 |   LockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
 | 
|---|
 | 2629 |   LockDensityArray(Dens0,Temp2Density,imag); // Psi1
 | 
|---|
 | 2630 |   LockDensityArray(Dens0,GapUpDensity,real); // Psi1R
 | 
|---|
 | 2631 |   LockDensityArray(Dens0,GapDownDensity,real); // Psip1R
 | 
|---|
 | 2632 | 
 | 
|---|
 | 2633 |   CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
 | 
|---|
 | 2634 |   CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
 | 
|---|
 | 2635 |   CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
 | 
|---|
 | 2636 |   CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
 | 
|---|
 | 2637 |   CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
 | 
|---|
 | 2638 |   CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
 | 
|---|
 | 2639 |   CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
 | 
|---|
 | 2640 |   CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
 | 
|---|
 | 2641 |   CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
 | 
|---|
 | 2642 | 
 | 
|---|
 | 2643 |   Psi0R = (fftw_real *)Dens0->DensityArray[GapDensity];
 | 
|---|
 | 2644 |   Psip0R = (fftw_real *)Dens0->DensityArray[GapLocalDensity];  
 | 
|---|
 | 2645 |   Psi1 = (fftw_complex *) Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 2646 |   Psi1R = (fftw_real *)Dens0->DensityArray[GapUpDensity];
 | 
|---|
 | 2647 |   Psip1R = (fftw_real *)Dens0->DensityArray[GapDownDensity];  
 | 
|---|
 | 2648 | 
 | 
|---|
 | 2649 | //  if (R->CurrentMin == Perturbed_P0)  
 | 
|---|
 | 2650 | //    for (B_index=0; B_index<NDIM*NDIM; B_index++) { // initialize current density array
 | 
|---|
 | 2651 | //      debug(P,"resetting CurrentDensity...");
 | 
|---|
 | 2652 | //      SetArrayToDouble0((double *)CurrentDensity[B_index],Dens0->TotalSize*2); // DensityArray is fftw_real, no 2*LocalSizeR here! 
 | 
|---|
 | 2653 | //    }
 | 
|---|
 | 2654 |   //if (Psi1 != (fftw_complex *) Dens0->DensityCArray[Temp2Density]) Error(SomeError,"FillDeltaCurrentDensity: Psi1 corrupted");
 | 
|---|
 | 2655 |   SetArrayToDouble0((double *)Psi1,2*Dens0->TotalSize);
 | 
|---|
 | 2656 |   
 | 
|---|
 | 2657 | //  gsl_vector *x = gsl_vector_alloc(Num);
 | 
|---|
 | 2658 | //  gsl_matrix *G = gsl_matrix_alloc(Num,Num);
 | 
|---|
 | 2659 | //  gsl_permutation *p = gsl_permutation_alloc(Num);
 | 
|---|
 | 2660 |   //int signum;
 | 
|---|
 | 2661 |   // begin of GSL linearer CG solver stuff
 | 
|---|
 | 2662 |   int iter, Status;
 | 
|---|
 | 2663 |  
 | 
|---|
 | 2664 |   const gsl_multimin_fdfminimizer_type *T;
 | 
|---|
 | 2665 |   gsl_multimin_fdfminimizer *minset;
 | 
|---|
 | 2666 |  
 | 
|---|
 | 2667 |   /* Position of the minimum (1,2). */
 | 
|---|
 | 2668 |   //double par[2] = { 1.0, 2.0 };
 | 
|---|
 | 2669 |  
 | 
|---|
 | 2670 |   gsl_vector *x;
 | 
|---|
 | 2671 |   gsl_multimin_function_fdf my_func;
 | 
|---|
 | 2672 |   
 | 
|---|
 | 2673 |   param.P = P;
 | 
|---|
 | 2674 |   param.k = &k;
 | 
|---|
 | 2675 |   param.l = &l;
 | 
|---|
 | 2676 |   param.iter = &iter;
 | 
|---|
 | 2677 |   param.x_l = x_l;
 | 
|---|
 | 2678 |   
 | 
|---|
 | 2679 |   my_func.f = &DeltaCurrent_f;
 | 
|---|
 | 2680 |   my_func.df = &DeltaCurrent_df;
 | 
|---|
 | 2681 |   my_func.fdf = &DeltaCurrent_fdf;
 | 
|---|
 | 2682 |   my_func.n = 2*LevS->MaxG;
 | 
|---|
 | 2683 |   my_func.params = (void *)¶m;
 | 
|---|
 | 2684 | 
 | 
|---|
 | 2685 |   T = gsl_multimin_fdfminimizer_conjugate_pr;
 | 
|---|
 | 2686 |   minset = gsl_multimin_fdfminimizer_alloc (T, 2*LevS->MaxG);
 | 
|---|
 | 2687 |   x = gsl_vector_alloc (2*LevS->MaxG);
 | 
|---|
 | 2688 |    // end of GSL CG stuff
 | 
|---|
 | 2689 | 
 | 
|---|
 | 2690 | 
 | 
|---|
 | 2691 | //  // construct G_kl = - (H^{(0)} \delta_{kl} -\langle \varphi^{(0)}_k |H^{(0)}| \varphi^{(0)}_l|rangle)^{-1} = A^{-1}
 | 
|---|
 | 2692 | //  for (k=0;k<Num;k++)
 | 
|---|
 | 2693 | //    for (l=0;l<Num;l++)
 | 
|---|
 | 2694 | //      gsl_matrix_set(G, k, l, k == l ? 0. : Psi->lambda[k][l]);
 | 
|---|
 | 2695 | //  // and decompose G_kl = L U
 | 
|---|
 | 2696 |   
 | 
|---|
 | 2697 |   mem_avail = MEM_avail = 0;
 | 
|---|
 | 2698 | //  x_l_bak = x_l = (fftw_complex **) Malloc(sizeof(fftw_complex *)*Num,"FillDeltaCurrentDensity: *x_l");
 | 
|---|
 | 2699 | //  for (i=0;i<Num;i++) {
 | 
|---|
 | 2700 | //    x_l[i] = NULL;
 | 
|---|
 | 2701 | //    x_l[i] = (fftw_complex *) malloc(sizeof(fftw_complex)*LevS->MaxG);
 | 
|---|
 | 2702 | //    if (x_l[i] == NULL) {
 | 
|---|
 | 2703 | //      mem_avail = 1;    // there was not enough memory for this node
 | 
|---|
 | 2704 | //      fprintf(stderr,"(%i) FillDeltaCurrentDensity: x_l[%i] ... insufficient memory.\n",P->Par.me,i);
 | 
|---|
 | 2705 | //    }
 | 
|---|
 | 2706 | //  }
 | 
|---|
 | 2707 | //  MPI_Allreduce(&mem_avail,&MEM_avail,1,MPI_INT,MPI_SUM,P->Par.comm_ST);  // sum results from all processes
 | 
|---|
 | 2708 | 
 | 
|---|
 | 2709 |   if (MEM_avail != 0) { // means at least node couldn't allocate sufficient memory, skipping...
 | 
|---|
 | 2710 |     fprintf(stderr,"(%i) FillDeltaCurrentDensity: x_l[], not enough memory: %i! Skipping FillDeltaCurrentDensity evaluation.", P->Par.me, MEM_avail);
 | 
|---|
 | 2711 |   } else {
 | 
|---|
 | 2712 |     // sum over k and calculate \Delta j_k(r')
 | 
|---|
 | 2713 |     k=-1;
 | 
|---|
 | 2714 |     for (i=0; i < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; i++) {  // go through all wave functions
 | 
|---|
 | 2715 |       //fprintf(stderr,"(%i) GlobalNo: %d\tLocalNo: %d\n", P->Par.me,Psi->AllPsiStatus[i].MyGlobalNo,Psi->AllPsiStatus[i].MyLocalNo);
 | 
|---|
 | 2716 |       OnePsiA = &Psi->AllPsiStatus[i];    // grab OnePsiA
 | 
|---|
 | 2717 |       if (OnePsiA->PsiType == Occupied) {   // drop the extra and perturbed ones
 | 
|---|
 | 2718 |         k++;
 | 
|---|
 | 2719 |         if (OnePsiA->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
 | 
|---|
 | 2720 |            LOnePsiA = &Psi->LocalPsiStatus[OnePsiA->MyLocalNo];
 | 
|---|
 | 2721 |         else 
 | 
|---|
 | 2722 |            LOnePsiA = NULL;
 | 
|---|
 | 2723 |         if (LOnePsiA != NULL) { 
 | 
|---|
 | 2724 |           Psi0=LevS->LPsi->LocalPsi[OnePsiA->MyLocalNo];
 | 
|---|
 | 2725 |           
 | 
|---|
 | 2726 |           if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi0> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2727 |           //if (Psi0R != (fftw_real *)Dens0->DensityArray[GapDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psi0R corrupted");
 | 
|---|
 | 2728 |           fft_Psi(P,Psi0,Psi0R, 0, Psi0symmetry);  //0 // 0 //0
 | 
|---|
 | 2729 | 
 | 
|---|
 | 2730 |           for (in=0;in<NDIM;in++) { // in is the index from derivation wrt to B^{ext}   
 | 
|---|
 | 2731 |             l = -1;
 | 
|---|
 | 2732 |             for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) {  // go through all wave functions
 | 
|---|
 | 2733 |               OnePsiB = &Psi->AllPsiStatus[j];    // grab OnePsiA
 | 
|---|
 | 2734 |               if (OnePsiB->PsiType == Occupied)
 | 
|---|
 | 2735 |                 l++;
 | 
|---|
 | 2736 |               if ((OnePsiB != OnePsiA) && (OnePsiB->PsiType == Occupied)) {   // drop the same and the extra ones
 | 
|---|
 | 2737 |                 if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
 | 
|---|
 | 2738 |                    LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
 | 
|---|
 | 2739 |                 else 
 | 
|---|
 | 2740 |                    LOnePsiB = NULL;
 | 
|---|
 | 2741 |                 if (LOnePsiB == NULL) {   // if it's not local ... receive x from respective process
 | 
|---|
 | 2742 |                   RecvSource = OnePsiB->my_color_comm_ST_Psi;
 | 
|---|
 | 2743 |                   MPI_Recv( x_l, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, HamiltonianTag, P->Par.comm_ST_PsiT, &status );
 | 
|---|
 | 2744 |                 } else {  // .. otherwise setup wave function as x ...             
 | 
|---|
 | 2745 |                   // Evaluate cross product: \epsilon_{ijm} (d_k - d_l)_j p_m | \varphi^{(0)} \rangle = b_i ... and
 | 
|---|
 | 2746 |                   LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
 | 
|---|
 | 2747 |                   //LPsiDatx=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo+Psi->TypeStartIndex[Perturbed_P0]];
 | 
|---|
 | 2748 |                   //CalculatePerturbationOperator_P(P,LPsiDatB,LPsiDatB_p0,cross(in,1),0);
 | 
|---|
 | 2749 |                   //CalculatePerturbationOperator_P(P,LPsiDatB,LPsiDatB_p1,cross(in,3),0);
 | 
|---|
 | 2750 |                   for (dex=0;dex<4;dex++)
 | 
|---|
 | 2751 |                     cross_lookup[dex] = cross(in,dex);
 | 
|---|
 | 2752 |                   for(s=0;s<LevS->MaxG;s++) {
 | 
|---|
 | 2753 |                     //if (x_l != x_l_bak || s<0 || s>LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: x_l[] corrupted");
 | 
|---|
 | 2754 |                     factor = 
 | 
|---|
 | 2755 |                       (MinImageConv(Lat,Psi->AddData[LOnePsiA->MyLocalNo].WannierCentre[cross_lookup[0]], 
 | 
|---|
 | 2756 |                                         Psi->AddData[LOnePsiB->MyLocalNo].WannierCentre[cross_lookup[0]],cross_lookup[0]) * LevS->GArray[s].G[cross_lookup[1]] -
 | 
|---|
 | 2757 |                        MinImageConv(Lat,Psi->AddData[LOnePsiA->MyLocalNo].WannierCentre[cross_lookup[2]], 
 | 
|---|
 | 2758 |                                         Psi->AddData[LOnePsiB->MyLocalNo].WannierCentre[cross_lookup[2]],cross_lookup[2]) * LevS->GArray[s].G[cross_lookup[3]]); 
 | 
|---|
 | 2759 |                     x_l[s].re = factor * (-LPsiDatB[s].im); // switched due to factorization with "-i G"
 | 
|---|
 | 2760 |                     x_l[s].im = factor * (LPsiDatB[s].re);
 | 
|---|
 | 2761 |                   }
 | 
|---|
 | 2762 |                   // ... and send it to all other processes (Max_me... - 1)
 | 
|---|
 | 2763 |                   for (u=0;u<P->Par.Max_me_comm_ST_PsiT;u++)
 | 
|---|
 | 2764 |                     if (u != OnePsiB->my_color_comm_ST_Psi) 
 | 
|---|
 | 2765 |                       MPI_Send( x_l, LevS->MaxG*ElementSize, MPI_DOUBLE, u, HamiltonianTag, P->Par.comm_ST_PsiT);
 | 
|---|
 | 2766 |                 } // x_l row is now filled (either by receiving result or evaluating it on its own)
 | 
|---|
 | 2767 |                 // Solve Ax = b by minimizing 1/2 xAx -xb (gradient is residual Ax - b) with conjugate gradient polak-ribiere
 | 
|---|
 | 2768 |     
 | 
|---|
 | 2769 |                 debug(P,"fill starting point x with values from b");
 | 
|---|
 | 2770 |                 /* Starting point, x = b */
 | 
|---|
 | 2771 |                 for (u=0;u<LevS->MaxG;u++) {
 | 
|---|
 | 2772 |                   gsl_vector_set (x, 2*u, x_l[u].re);
 | 
|---|
 | 2773 |                   gsl_vector_set (x, 2*u+1, x_l[u].im);
 | 
|---|
 | 2774 |                 }
 | 
|---|
 | 2775 |      
 | 
|---|
 | 2776 |                 gsl_multimin_fdfminimizer_set (minset, &my_func, x, 0.01, 1e-4);
 | 
|---|
 | 2777 |      
 | 
|---|
 | 2778 |                 fprintf(stderr,"(%i) Start solving for (%i,%i) and index %i\n",P->Par.me, k,l,in);
 | 
|---|
 | 2779 |                 // start solving
 | 
|---|
 | 2780 |                 iter = 0;
 | 
|---|
 | 2781 |                 do
 | 
|---|
 | 2782 |                 {
 | 
|---|
 | 2783 |                   iter++;
 | 
|---|
 | 2784 |                   Status = gsl_multimin_fdfminimizer_iterate (minset);
 | 
|---|
 | 2785 |      
 | 
|---|
 | 2786 |                   if (Status)
 | 
|---|
 | 2787 |                     break;
 | 
|---|
 | 2788 |      
 | 
|---|
 | 2789 |                   Status = gsl_multimin_test_gradient (minset->gradient, 1e-3);
 | 
|---|
 | 2790 |      
 | 
|---|
 | 2791 |                   if (Status == GSL_SUCCESS)
 | 
|---|
 | 2792 |                     fprintf (stderr,"(%i) Minimum found after %i iterations.\n", P->Par.me, iter);
 | 
|---|
 | 2793 |      
 | 
|---|
 | 2794 |                 } while (Status == GSL_CONTINUE && iter < 100);
 | 
|---|
 | 2795 |      
 | 
|---|
 | 2796 |                 debug(P,"Put solution into Psi1");
 | 
|---|
 | 2797 |                 // ... and what do we do now? Put solution into Psi1!
 | 
|---|
 | 2798 |                 for(s=0;s<LevS->MaxG;s++) {
 | 
|---|
 | 2799 |                   //if (Psi1 != (fftw_complex *) Dens0->DensityCArray[Temp2Density] || s<0 || s>LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: Psi1 corrupted");
 | 
|---|
 | 2800 |                   Psi1[s].re = gsl_vector_get (minset->x, 2*s);
 | 
|---|
 | 2801 |                   Psi1[s].im = gsl_vector_get (minset->x, 2*s+1);
 | 
|---|
 | 2802 |                 }
 | 
|---|
 | 2803 |                 
 | 
|---|
 | 2804 |     //            // Solve A^{-1} b_i = x
 | 
|---|
 | 2805 |     //            for(s=0;s<LevS->MaxG;s++) {
 | 
|---|
 | 2806 |     //              // REAL PART
 | 
|---|
 | 2807 |     //              // retrieve column from gathered matrix
 | 
|---|
 | 2808 |     //              for(u=0;u<Num;u++)
 | 
|---|
 | 2809 |     //                gsl_vector_set(x,u,x_l[u][s].re);
 | 
|---|
 | 2810 |     //      
 | 
|---|
 | 2811 |     //              // solve: sum_l A_{kl}^(-1) b_l (s) = x_k (s)
 | 
|---|
 | 2812 |     //              gsl_linalg_LU_svx (G, p, x);
 | 
|---|
 | 2813 |     //      
 | 
|---|
 | 2814 |     //              // put solution back into x_l[s]
 | 
|---|
 | 2815 |     //              for(u=0;u<Num;u++) {
 | 
|---|
 | 2816 |     //                //if (x_l != x_l_bak || s<0 || s>=LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: x_l[] corrupted");
 | 
|---|
 | 2817 |     //                x_l[u][s].re = gsl_vector_get(x,u);
 | 
|---|
 | 2818 |     //              }
 | 
|---|
 | 2819 |     //              
 | 
|---|
 | 2820 |     //              // IMAGINARY PART
 | 
|---|
 | 2821 |     //              // retrieve column from gathered matrix
 | 
|---|
 | 2822 |     //              for(u=0;u<Num;u++)
 | 
|---|
 | 2823 |     //                gsl_vector_set(x,u,x_l[u][s].im);
 | 
|---|
 | 2824 |     //      
 | 
|---|
 | 2825 |     //              // solve: sum_l A_{kl}^(-1) b_l (s) = x_k (s)
 | 
|---|
 | 2826 |     //              gsl_linalg_LU_svx (G, p, x);
 | 
|---|
 | 2827 |     //      
 | 
|---|
 | 2828 |     //              // put solution back into x_l[s]
 | 
|---|
 | 2829 |     //              for(u=0;u<Num;u++) {
 | 
|---|
 | 2830 |     //                //if (x_l != x_l_bak || s<0 || s>=LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: x_l[] corrupted");
 | 
|---|
 | 2831 |     //                x_l[u][s].im = gsl_vector_get(x,u);
 | 
|---|
 | 2832 |     //              }
 | 
|---|
 | 2833 |     //            } // now we have in x_l a vector similar to "Psi1" which we use to evaluate the current density
 | 
|---|
 | 2834 |     //      
 | 
|---|
 | 2835 |     //            // evaluate \Delta J_k ... mind the minus sign from G_kl!  
 | 
|---|
 | 2836 |     //            // fill Psi1
 | 
|---|
 | 2837 |     //            for(s=0;s<LevS->MaxG;s++) {
 | 
|---|
 | 2838 |     //              //if (Psi1 != (fftw_complex *) Dens0->DensityCArray[Temp2Density] || s<0 || s>LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: Psi1 corrupted");
 | 
|---|
 | 2839 |     //              Psi1[s].re = x_l[k][s].re;
 | 
|---|
 | 2840 |     //              Psi1[s].im = x_l[k][s].im;
 | 
|---|
 | 2841 |     //            }
 | 
|---|
 | 2842 |                             
 | 
|---|
 | 2843 |                 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi1> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2844 |                 //if (Psi1R != (fftw_real *)Dens0->DensityArray[GapUpDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psi1R corrupted");
 | 
|---|
 | 2845 |                 fft_Psi(P,Psi1,Psi1R, 0, Psi1symmetry);  //2 // 0 //0
 | 
|---|
 | 2846 |             
 | 
|---|
 | 2847 |                 for (index=0;index<NDIM;index++) { // for all NDIM components of momentum operator
 | 
|---|
 | 2848 |           
 | 
|---|
 | 2849 |                   if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi0> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2850 |                   //if (Psip0R != (fftw_real *)Dens0->DensityArray[GapLocalDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psip0R corrupted");
 | 
|---|
 | 2851 |                   fft_Psi(P,Psi0,Psip0R, index, Psip0symmetry); //6 //6 //6
 | 
|---|
 | 2852 |             
 | 
|---|
 | 2853 |                   if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi1> one level up and fftransforming\n", P->Par.me);
 | 
|---|
 | 2854 |                   //if (Psip1R != (fftw_real *)Dens0->DensityArray[GapDownDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psip1R corrupted");
 | 
|---|
 | 2855 |                   fft_Psi(P,Psi1,Psip1R, index, Psip1symmetry); //4 //6 //6
 | 
|---|
 | 2856 |             
 | 
|---|
 | 2857 |                     // then for every point on the grid in real space ...
 | 
|---|
 | 2858 |                     for (n0=0;n0<N0;n0++)  // only local points on x axis
 | 
|---|
 | 2859 |                       for (n[1]=0;n[1]<N[1];n[1]++)
 | 
|---|
 | 2860 |                         for (n[2]=0;n[2]<N[2];n[2]++) {
 | 
|---|
 | 2861 |                           i0 = n[2]+N[2]*(n[1]+N[1]*n0);
 | 
|---|
 | 2862 |                           // and take the product
 | 
|---|
 | 2863 |                           Current = (Psip0R[i0] * Psi1R[i0] + Psi0R[i0] * Psip1R[i0]);
 | 
|---|
 | 2864 |                           Current *= 0.5 * UnitsFactor * Psi->AllPsiStatus[OnePsiA->MyGlobalNo].PsiFactor * R->FactorDensityR;
 | 
|---|
 | 2865 |                           ////if (CurrentDensity[index+in*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+in*NDIM])  Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
 | 
|---|
 | 2866 |                           //if (i0<0 || i0>=Dens0->LocalSizeR)  Error(SomeError,"FillDeltaCurrentDensity: i0 out of range");
 | 
|---|
 | 2867 |                           //if ((index+in*NDIM)<0 || (index+in*NDIM)>=NDIM*NDIM) Error(SomeError,"FillDeltaCurrentDensity: index out of range");
 | 
|---|
 | 2868 |                           CurrentDensity[index+in*NDIM][i0] += Current; // minus sign is from G_kl
 | 
|---|
 | 2869 |                         }
 | 
|---|
 | 2870 |                 }
 | 
|---|
 | 2871 |               }
 | 
|---|
 | 2872 |             }
 | 
|---|
 | 2873 |           }
 | 
|---|
 | 2874 |         }
 | 
|---|
 | 2875 |       }
 | 
|---|
 | 2876 |     }
 | 
|---|
 | 2877 |   }
 | 
|---|
 | 2878 |   UnLockDensityArray(Dens0,GapDensity,real); // Psi0R
 | 
|---|
 | 2879 |   UnLockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
 | 
|---|
 | 2880 |   UnLockDensityArray(Dens0,Temp2Density,imag); // Psi1
 | 
|---|
 | 2881 |   UnLockDensityArray(Dens0,GapUpDensity,real); // Psi1R
 | 
|---|
 | 2882 |   UnLockDensityArray(Dens0,GapDownDensity,real); // Psip1R
 | 
|---|
 | 2883 | //  for (i=0;i<Num;i++)
 | 
|---|
| [64fa9e] | 2884 | //    if (x_l[i] != NULL) Free(x_l[i], "bla", "bla");         
 | 
|---|
 | 2885 | //  Free(x_l, "bla");
 | 
|---|
| [a0bcf1] | 2886 |   gsl_multimin_fdfminimizer_free (minset);
 | 
|---|
 | 2887 |   gsl_vector_free (x);            
 | 
|---|
 | 2888 | //  gsl_matrix_free(G);
 | 
|---|
 | 2889 | //  gsl_permutation_free(p);
 | 
|---|
 | 2890 | //  gsl_vector_free(x);
 | 
|---|
 | 2891 | }
 | 
|---|
 | 2892 | 
 | 
|---|
 | 2893 | 
 | 
|---|
 | 2894 | /** Evaluates the overlap integral between \a state wave functions.
 | 
|---|
 | 2895 |  * \f[
 | 
|---|
 | 2896 |  *  S_{kl} = \langle \varphi_k^{(1)} | \varphi_l^{(1)} \rangle
 | 
|---|
 | 2897 |  * \f]
 | 
|---|
 | 2898 |  * The scalar product is calculated via GradSP(), MPI_Allreduced among comm_ST_Psi and the result
 | 
|---|
 | 2899 |  * stored in Psis#Overlap. The rows have to be MPI exchanged, as otherwise processes will add
 | 
|---|
 | 2900 |  * to the TotalEnergy overlaps calculated with old wave functions - they have been minimised after
 | 
|---|
 | 2901 |  * the product with exchanged coefficients was taken.
 | 
|---|
 | 2902 |  * \param *P Problem at hand
 | 
|---|
 | 2903 |  * \param l local number of perturbed wave function.
 | 
|---|
 | 2904 |  * \param state PsiTypeTag minimisation state of wave functions to be overlapped
 | 
|---|
 | 2905 |  */
 | 
|---|
 | 2906 | void CalculateOverlap(struct Problem *P, const int l, const enum PsiTypeTag state) 
 | 
|---|
 | 2907 | {
 | 
|---|
 | 2908 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2909 |   struct Lattice *Lat = &(P->Lat);
 | 
|---|
 | 2910 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 2911 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 2912 |   struct OnePsiElement *OnePsiB, *LOnePsiB;
 | 
|---|
 | 2913 |   fftw_complex *LPsiDatB=NULL, *LPsiDatA=NULL;
 | 
|---|
 | 2914 |   const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
 | 2915 |   int RecvSource;
 | 
|---|
 | 2916 |   MPI_Status status;
 | 
|---|
 | 2917 |   int i,j,m,p;
 | 
|---|
 | 2918 |   //const int l_normal = l - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[Occupied]; 
 | 
|---|
 | 2919 |   const int ActNum = l - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[l].my_color_comm_ST_Psi;
 | 
|---|
 | 2920 |   double *sendbuf, *recvbuf;
 | 
|---|
 | 2921 |   double tmp,TMP;
 | 
|---|
 | 2922 |   const int gsize = P->Par.Max_me_comm_ST_PsiT;  //number of processes in PsiT
 | 
|---|
 | 2923 |   int p_num;  // number of wave functions (for overlap)
 | 
|---|
 | 2924 | 
 | 
|---|
 | 2925 |   // update overlap table after wave function has changed
 | 
|---|
 | 2926 |   LPsiDatA = LevS->LPsi->LocalPsi[l];
 | 
|---|
 | 2927 |   m = -1; // to access U matrix element (0..Num-1)
 | 
|---|
 | 2928 |   for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) {  // go through all wave functions
 | 
|---|
 | 2929 |     OnePsiB = &Psi->AllPsiStatus[j];    // grab OnePsiB
 | 
|---|
 | 2930 |     if (OnePsiB->PsiType == state) {   // drop all but the ones of current min state
 | 
|---|
 | 2931 |       m++;  // increase m if it is non-extra wave function
 | 
|---|
 | 2932 |       if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
 | 
|---|
 | 2933 |          LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
 | 
|---|
 | 2934 |       else
 | 
|---|
 | 2935 |          LOnePsiB = NULL;
 | 
|---|
 | 2936 |       if (LOnePsiB == NULL) {   // if it's not local ... receive it from respective process into TempPsi
 | 
|---|
 | 2937 |         RecvSource = OnePsiB->my_color_comm_ST_Psi;
 | 
|---|
 | 2938 |         MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, OverlapTag, P->Par.comm_ST_PsiT, &status );
 | 
|---|
 | 2939 |         LPsiDatB=LevS->LPsi->TempPsi;
 | 
|---|
 | 2940 |       } else {                  // .. otherwise send it to all other processes (Max_me... - 1)
 | 
|---|
 | 2941 |         for (p=0;p<P->Par.Max_me_comm_ST_PsiT;p++)
 | 
|---|
 | 2942 |           if (p != OnePsiB->my_color_comm_ST_Psi)
 | 
|---|
 | 2943 |             MPI_Send( LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, p, OverlapTag, P->Par.comm_ST_PsiT);
 | 
|---|
 | 2944 |         LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
 | 
|---|
 | 2945 |       } // LPsiDatB is now set to the coefficients of OnePsi either stored or MPI_Received
 | 
|---|
 | 2946 | 
 | 
|---|
 | 2947 |       tmp = GradSP(P, LevS, LPsiDatA, LPsiDatB) * sqrt(Psi->LocalPsiStatus[l].PsiFactor * OnePsiB->PsiFactor);
 | 
|---|
 | 2948 |       MPI_Allreduce ( &tmp, &TMP, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
 | 2949 |       //fprintf(stderr,"(%i) Setting Overlap [%i][%i] = %lg\n",P->Par.me, ActNum,m,TMP);
 | 
|---|
 | 2950 |       Psi->Overlap[ActNum][m] = TMP; //= Psi->Overlap[m][ActNum] 
 | 
|---|
 | 2951 |     }
 | 
|---|
 | 2952 |   }
 | 
|---|
 | 2953 |  
 | 
|---|
 | 2954 |   // exchange newly calculated rows among PsiT
 | 
|---|
 | 2955 |   p_num = (m+1) + 1;  // number of Psis: one more due to ActNum
 | 
|---|
 | 2956 |   sendbuf = (double *) Malloc(p_num * sizeof(double), "CalculateOverlap: sendbuf");
 | 
|---|
 | 2957 |   sendbuf[0] = ActNum;  // first entry is the global row number
 | 
|---|
 | 2958 |   for (i=1;i<p_num;i++)
 | 
|---|
 | 2959 |     sendbuf[i] = Psi->Overlap[ActNum][i-1]; // then follow up each entry of overlap row
 | 
|---|
 | 2960 |   recvbuf = (double *) Malloc(gsize * p_num * sizeof(double), "CalculateOverlap: recvbuf");
 | 
|---|
 | 2961 |   MPI_Allgather(sendbuf, p_num, MPI_DOUBLE, recvbuf, p_num, MPI_DOUBLE, P->Par.comm_ST_PsiT);
 | 
|---|
| [64fa9e] | 2962 |   Free(sendbuf, "bla");
 | 
|---|
| [a0bcf1] | 2963 |   for (i=0;i<gsize;i++) {// extract results from other processes out of receiving buffer
 | 
|---|
 | 2964 |     m = recvbuf[i*p_num]; // m is ActNum of the process whose results we've just received
 | 
|---|
 | 2965 |     //fprintf(stderr,"(%i) Received row %i from process %i\n", P->Par.me, m, i);
 | 
|---|
 | 2966 |     for (j=1;j<p_num;j++)
 | 
|---|
 | 2967 |       Psi->Overlap[m][j-1] = Psi->Overlap[j-1][m] = recvbuf[i*p_num+j]; // put each entry into correspondent Overlap row
 | 
|---|
 | 2968 |   }
 | 
|---|
| [64fa9e] | 2969 |   Free(recvbuf, "bla");
 | 
|---|
| [a0bcf1] | 2970 | }
 | 
|---|
 | 2971 | 
 | 
|---|
 | 2972 | 
 | 
|---|
 | 2973 | /** Calculates magnetic susceptibility from known current density.
 | 
|---|
 | 2974 |  * The bulk susceptibility tensor can be expressed as a function of the current density.
 | 
|---|
 | 2975 |  * \f[
 | 
|---|
 | 2976 |  *  \chi_{ij} = \frac{\mu_0}{2\Omega} \frac{\delta}{\delta B_i^{ext}} \int_\Omega d^3 r \left (r \times j(r) \right )_j
 | 
|---|
 | 2977 |  * \f]
 | 
|---|
 | 2978 |  * Thus the integral over real space and subsequent MPI_Allreduce() over results from ParallelSimulationData#comm_ST_Psi is 
 | 
|---|
 | 2979 |  * straightforward. Tensor is diagonalized afterwards and split into its various sub-tensors of lower rank (e.g., isometric
 | 
|---|
 | 2980 |  * value is tensor of rank 0) which are printed to screen and the tensorial elements to file '....chi.csv'
 | 
|---|
 | 2981 |   * \param *P Problem at hand
 | 
|---|
 | 2982 |   */
 | 
|---|
 | 2983 | void CalculateMagneticSusceptibility(struct Problem *P)
 | 
|---|
 | 2984 | {
 | 
|---|
 | 2985 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 2986 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 2987 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 2988 |   struct Density *Dens0 = R->Lev0->Dens;
 | 
|---|
 | 2989 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 2990 |   fftw_real *CurrentDensity[NDIM*NDIM];
 | 
|---|
 | 2991 |   int in, dex, i, i0, n0;
 | 
|---|
 | 2992 |   int n[NDIM];
 | 
|---|
 | 2993 |   const int N0 = Lev0->Plan0.plan->local_nx;
 | 
|---|
 | 2994 |   int N[NDIM];
 | 
|---|
 | 2995 |   N[0] = Lev0->Plan0.plan->N[0];
 | 
|---|
 | 2996 |   N[1] = Lev0->Plan0.plan->N[1];
 | 
|---|
 | 2997 |   N[2] = Lev0->Plan0.plan->N[2];
 | 
|---|
 | 2998 |   double chi[NDIM*NDIM],Chi[NDIM*NDIM], x[NDIM], fac[NDIM];
 | 
|---|
 | 2999 |   const double discrete_factor = Lat->Volume/Lev0->MaxN;
 | 
|---|
 | 3000 |   const int myPE =  P->Par.me_comm_ST_Psi;
 | 
|---|
 | 3001 |   double eta, delta_chi, S, A, iso;
 | 
|---|
 | 3002 |   int cross_lookup[4];
 | 
|---|
 | 3003 |   char filename[256];
 | 
|---|
 | 3004 |   FILE *ChiFile;
 | 
|---|
 | 3005 |   time_t seconds;  
 | 
|---|
 | 3006 |   time(&seconds); // get current time
 | 
|---|
 | 3007 | 
 | 
|---|
 | 3008 |  // set pointers onto current density
 | 
|---|
 | 3009 |   CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
 | 
|---|
 | 3010 |   CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
 | 
|---|
 | 3011 |   CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
 | 
|---|
 | 3012 |   CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
 | 
|---|
 | 3013 |   CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
 | 
|---|
 | 3014 |   CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
 | 
|---|
 | 3015 |   CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
 | 
|---|
 | 3016 |   CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
 | 
|---|
 | 3017 |   CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
 | 
|---|
 | 3018 |   //for(i=0;i<NDIM;i++) {
 | 
|---|
 | 3019 | //    field[i] = Dens0->DensityArray[TempDensity+i];
 | 
|---|
 | 3020 |     //LockDensityArray(Dens0,TempDensity+i,real);
 | 
|---|
 | 3021 | //    SetArrayToDouble0((double *)field[i],Dens0->TotalSize*2);  
 | 
|---|
 | 3022 |   //}
 | 
|---|
 | 3023 |   gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
 | 
|---|
 | 3024 |     
 | 
|---|
 | 3025 |   
 | 
|---|
 | 3026 |   if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) magnetic susceptibility tensor \\Chi_ij = \n",P->Par.me);
 | 
|---|
 | 3027 |   for (in=0; in<NDIM; in++) { // index i of integrand vector component
 | 
|---|
 | 3028 |     for(dex=0;dex<4;dex++)  // initialise cross lookup
 | 
|---|
 | 3029 |       cross_lookup[dex] = cross(in,dex);
 | 
|---|
 | 3030 |     for (dex=0; dex<NDIM; dex++) {  // index j of derivation wrt B field 
 | 
|---|
 | 3031 |       chi[in+dex*NDIM] = 0.;
 | 
|---|
 | 3032 |       // do the integration over real space
 | 
|---|
 | 3033 |       for(n0=0;n0<N0;n0++)
 | 
|---|
 | 3034 |         for(n[1]=0;n[1]<N[1];n[1]++)
 | 
|---|
 | 3035 |           for(n[2]=0;n[2]<N[2];n[2]++) {
 | 
|---|
 | 3036 |             n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
 | 
|---|
 | 3037 |             fac[0] = (double)(n[0])/(double)N[0];
 | 
|---|
 | 3038 |             fac[1] = (double)(n[1])/(double)N[1];
 | 
|---|
 | 3039 |             fac[2] = (double)(n[2])/(double)N[2];
 | 
|---|
 | 3040 |             RMat33Vec3(x, Lat->RealBasis, fac);
 | 
|---|
 | 3041 |             i0 = n[2]+N[2]*(n[1]+N[1]*(n0));  // the index of current density must match LocalSizeR!
 | 
|---|
 | 3042 |             chi[in+dex*NDIM] += MinImageConv(Lat,x[cross_lookup[0]], Lat->RealBasisQ[cross_lookup[0]]/2.,cross_lookup[0]) * CurrentDensity[dex*NDIM+cross_lookup[1]][i0]; // x[cross(in,0)], Lat->RealBasisQ[cross_lookup[0]]/2.
 | 
|---|
 | 3043 |             chi[in+dex*NDIM] -= MinImageConv(Lat,x[cross_lookup[2]], Lat->RealBasisQ[cross_lookup[2]]/2.,cross_lookup[2]) * CurrentDensity[dex*NDIM+cross_lookup[3]][i0]; // x[cross(in,2)], Lat->RealBasisQ[cross_lookup[2]]/2.
 | 
|---|
 | 3044 | //            if (in == dex) field[in][i0] = 
 | 
|---|
 | 3045 | //                truedist(Lat,x[cross_lookup[0]], Lat->RealBasisQ[c[0]]/2.,cross_lookup[0]) * CurrentDensity[dex*NDIM+cross_lookup[1]][i0] 
 | 
|---|
 | 3046 | //              - truedist(Lat,x[cross_lookup[2]], Lat->RealBasisQ[c[2]]/2.,cross_lookup[2]) * CurrentDensity[dex*NDIM+cross_lookup[3]][i0];
 | 
|---|
 | 3047 |             //fprintf(stderr,"(%i) temporary susceptiblity \\chi[%i][%i] += %e * %e = r[%i] * CurrDens[%i][%i] = %e\n",P->Par.me,in,dex,(double)n[cross_lookup[0]]/(double)N[cross_lookup[0]]*(Lat->RealBasisQ[cross_lookup[0]]),CurrentDensity[dex*NDIM+cross_lookup[1]][i0],cross_lookup[0],dex*NDIM+cross_lookup[1],i0,chi[in*NDIM+dex]);
 | 
|---|
 | 3048 |           }
 | 
|---|
 | 3049 |       chi[in+dex*NDIM] *= mu0*discrete_factor/(2.*Lat->Volume); // integral factor
 | 
|---|
 | 3050 |       chi[in+dex*NDIM] *= (-1625.); // empirical gauge factor ... sigh
 | 
|---|
 | 3051 |       MPI_Allreduce ( &chi[in+dex*NDIM], &Chi[in+dex*NDIM], 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);   // sum "LocalSize to TotalSize"
 | 
|---|
 | 3052 |       I->I[0].chi[in+dex*NDIM] = Chi[in+dex*NDIM];
 | 
|---|
 | 3053 |       Chi[in+dex*NDIM] *= Lat->Volume*loschmidt_constant; // factor for _molar_ susceptibility
 | 
|---|
 | 3054 |       if (P->Call.out[ValueOut]) {
 | 
|---|
 | 3055 |         fprintf(stderr,"%e\t", Chi[in+dex*NDIM]);
 | 
|---|
 | 3056 |         if (dex == NDIM-1) fprintf(stderr,"\n");
 | 
|---|
 | 3057 |       }
 | 
|---|
 | 3058 |     }
 | 
|---|
 | 3059 |   }
 | 
|---|
 | 3060 |   // store symmetrized matrix
 | 
|---|
 | 3061 |   for (in=0;in<NDIM;in++)
 | 
|---|
 | 3062 |     for (dex=0;dex<NDIM;dex++)
 | 
|---|
 | 3063 |       gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((Chi[in+dex*NDIM]+Chi[dex+in*NDIM])/2.,0));
 | 
|---|
 | 3064 |   // output tensor to file
 | 
|---|
 | 3065 |   if (P->Par.me == 0) {
 | 
|---|
 | 3066 |     sprintf(filename, ".chi.L%i.csv", Lev0->LevelNo);
 | 
|---|
 | 3067 |     OpenFile(P, &ChiFile, filename, "a", P->Call.out[ReadOut]);
 | 
|---|
 | 3068 |     fprintf(ChiFile,"# magnetic susceptibility tensor chi[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
 | 
|---|
 | 3069 |     fprintf(ChiFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
 | 
|---|
 | 3070 |     for (in=0;in<NDIM*NDIM;in++)
 | 
|---|
 | 3071 |       fprintf(ChiFile,"%e\t", Chi[in]);
 | 
|---|
 | 3072 |     fprintf(ChiFile,"\n");
 | 
|---|
 | 3073 |     fclose(ChiFile);
 | 
|---|
 | 3074 |   }
 | 
|---|
 | 3075 |   // diagonalize chi
 | 
|---|
 | 3076 |   gsl_vector *eval = gsl_vector_alloc(NDIM);
 | 
|---|
 | 3077 |   gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
 | 
|---|
 | 3078 |   gsl_eigen_herm(H, eval, w);
 | 
|---|
 | 3079 |   gsl_eigen_herm_free(w);
 | 
|---|
 | 3080 |   gsl_sort_vector(eval);  // sort eigenvalues
 | 
|---|
 | 3081 |   // print eigenvalues
 | 
|---|
 | 3082 |   iso = 0;
 | 
|---|
 | 3083 |   for (i=0;i<NDIM;i++) {
 | 
|---|
 | 3084 |     I->I[0].chi_PAS[i] = gsl_vector_get(eval,i);
 | 
|---|
 | 3085 |     iso += Chi[i+i*NDIM]/3.;
 | 
|---|
 | 3086 |   } 
 | 
|---|
 | 3087 |   eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
 | 
|---|
 | 3088 |   delta_chi = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
 | 
|---|
 | 3089 |   S = (delta_chi*delta_chi)*(1+1./3.*eta*eta);
 | 
|---|
 | 3090 |   A = 0.;
 | 
|---|
 | 3091 |   for (i=0;i<NDIM;i++) {
 | 
|---|
 | 3092 |     in = cross(i,0);
 | 
|---|
 | 3093 |     dex = cross(i,1);
 | 
|---|
 | 3094 |     A += pow(-1,i)*pow(0.5*(Chi[in+dex*NDIM]-Chi[dex+in*NDIM]),2);
 | 
|---|
 | 3095 |   }
 | 
|---|
 | 3096 |   if (P->Call.out[ValueOut]) {
 | 
|---|
 | 3097 |     fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
 | 
|---|
 | 3098 |     for (i=0;i<NDIM;i++)
 | 
|---|
 | 3099 |       fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
 | 
|---|
 | 3100 |     fprintf(stderr,"\nsusceptib. : %e\n", iso);
 | 
|---|
 | 3101 |     fprintf(stderr,"anisotropy : %e\n", delta_chi);
 | 
|---|
 | 3102 |     fprintf(stderr,"asymmetry  : %e\n", eta);
 | 
|---|
 | 3103 |     fprintf(stderr,"S          : %e\n", S);
 | 
|---|
 | 3104 |     fprintf(stderr,"A          : %e\n", A);
 | 
|---|
 | 3105 |     fprintf(stderr,"==================\n");
 | 
|---|
 | 3106 |   }
 | 
|---|
 | 3107 |   //for(i=0;i<NDIM;i++)
 | 
|---|
 | 3108 |     //UnLockDensityArray(Dens0,TempDensity+i,real);  
 | 
|---|
 | 3109 |   gsl_vector_free(eval);
 | 
|---|
 | 3110 |   gsl_matrix_complex_free(H);
 | 
|---|
 | 3111 | }
 | 
|---|
 | 3112 | 
 | 
|---|
 | 3113 | /** Fouriertransforms all nine current density components and calculates shielding tensor.
 | 
|---|
 | 3114 |  * \f[
 | 
|---|
 | 3115 |  *  \sigma_{ij} = \left ( \frac{G}{|G|^2} \times J_i(G) \right )_j
 | 
|---|
 | 3116 |  * \f]
 | 
|---|
 | 3117 |  * The CurrentDensity has to be fouriertransformed to reciprocal subspace in order to be useful, and the final
 | 
|---|
 | 3118 |  * product \f$\sigma_{ij}(G)\f$ has to be back-transformed to real space. However, the shielding is the only evaluated
 | 
|---|
 | 3119 |  * at the grid points and not where the real ion position is. The shieldings there are interpolated between the eight
 | 
|---|
 | 3120 |  * adjacent grid points by a simple linear weighting. Afterwards follows the same analaysis and printout of the rank-2-tensor
 | 
|---|
 | 3121 |  * as in the case of CalculateMagneticShielding().
 | 
|---|
 | 3122 |  * \param *P Problem at hand
 | 
|---|
 | 3123 |  * \note Lots of arrays are used temporarily during the routine for the fft'ed Current density tensor.
 | 
|---|
 | 3124 |  * \note MagneticSusceptibility is needed for G=0-component and thus has to be computed beforehand
 | 
|---|
 | 3125 |  */
 | 
|---|
 | 3126 | void CalculateChemicalShieldingByReciprocalCurrentDensity(struct Problem *P)
 | 
|---|
 | 3127 | {
 | 
|---|
 | 3128 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 3129 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 3130 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 3131 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 3132 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 3133 |   struct OneGData *GArray = Lev0->GArray;
 | 
|---|
 | 3134 |   struct fft_plan_3d *plan = Lat->plan; 
 | 
|---|
 | 3135 |   fftw_real *CurrentDensity[NDIM*NDIM];
 | 
|---|
 | 3136 |   fftw_complex *CurrentDensityC[NDIM*NDIM];
 | 
|---|
 | 3137 |   fftw_complex *work = (fftw_complex *)Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 3138 |   //fftw_complex *sigma_imag = (fftw_complex *)Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 3139 |   //fftw_real *sigma_real = (fftw_real *)sigma_imag;
 | 
|---|
 | 3140 |   fftw_complex *sigma_imag[NDIM_NDIM];
 | 
|---|
 | 3141 |   fftw_real *sigma_real[NDIM_NDIM];
 | 
|---|
 | 3142 |   double sigma,Sigma;
 | 
|---|
 | 3143 |   int it, ion, in, dex, g, n[2][NDIM], Index, i;
 | 
|---|
 | 3144 |   //const double FFTfactor = 1.;///Lev0->MaxN;
 | 
|---|
 | 3145 |   double eta, delta_sigma, S, A, iso, tmp;
 | 
|---|
 | 3146 |   FILE *SigmaFile;
 | 
|---|
 | 3147 |   char suffixsigma[255];
 | 
|---|
 | 3148 |   double x[2][NDIM];
 | 
|---|
 | 3149 |   const int myPE = P->Par.me_comm_ST_Psi;
 | 
|---|
 | 3150 |   int N[NDIM];
 | 
|---|
 | 3151 |   int cross_lookup[4]; // cross lookup table
 | 
|---|
 | 3152 |   N[0] = Lev0->Plan0.plan->N[0];
 | 
|---|
 | 3153 |   N[1] = Lev0->Plan0.plan->N[1];
 | 
|---|
 | 3154 |   N[2] = Lev0->Plan0.plan->N[2];
 | 
|---|
 | 3155 |   const int N0 = Lev0->Plan0.plan->local_nx;
 | 
|---|
 | 3156 |   const double factorDC = R->FactorDensityC;
 | 
|---|
 | 3157 |   gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
 | 
|---|
 | 3158 |   
 | 
|---|
 | 3159 |   time_t seconds;  
 | 
|---|
 | 3160 |   time(&seconds); // get current time
 | 
|---|
 | 3161 | 
 | 
|---|
 | 3162 |   // inverse Fourier transform current densities
 | 
|---|
 | 3163 |   CurrentDensityC[0] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity0];
 | 
|---|
 | 3164 |   CurrentDensityC[1] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity1];
 | 
|---|
 | 3165 |   CurrentDensityC[2] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity2];
 | 
|---|
 | 3166 |   CurrentDensityC[3] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity3];
 | 
|---|
 | 3167 |   CurrentDensityC[4] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity4];
 | 
|---|
 | 3168 |   CurrentDensityC[5] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity5];
 | 
|---|
 | 3169 |   CurrentDensityC[6] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity6];
 | 
|---|
 | 3170 |   CurrentDensityC[7] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity7];
 | 
|---|
 | 3171 |   CurrentDensityC[8] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity8];
 | 
|---|
 | 3172 |   // don't put the following stuff into a for loop, they are not continuous! (preprocessor values CurrentDensity.)
 | 
|---|
 | 3173 |   CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
 | 
|---|
 | 3174 |   CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
 | 
|---|
 | 3175 |   CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
 | 
|---|
 | 3176 |   CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
 | 
|---|
 | 3177 |   CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
 | 
|---|
 | 3178 |   CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
 | 
|---|
 | 3179 |   CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
 | 
|---|
 | 3180 |   CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
 | 
|---|
 | 3181 |   CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
 | 
|---|
 | 3182 | 
 | 
|---|
 | 3183 |   if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Checking J_{ij} (G=0) = 0 for each i,j ... \n",P->Par.me);
 | 
|---|
 | 3184 |   for (in=0;in<NDIM*NDIM;in++) {
 | 
|---|
 | 3185 |     CalculateOneDensityC(Lat, R->LevS, Dens0, CurrentDensity[in], CurrentDensityC[in], factorDC);
 | 
|---|
 | 3186 |     tmp = sqrt(CurrentDensityC[in][0].re*CurrentDensityC[in][0].re+CurrentDensityC[in][0].im*CurrentDensityC[in][0].im);
 | 
|---|
 | 3187 |     if (GArray[0].GSq < MYEPSILON) {
 | 
|---|
 | 3188 |       if (in % NDIM == 0) fprintf(stderr,"(%i) ",P->Par.me); 
 | 
|---|
 | 3189 |       if (tmp > MYEPSILON) {
 | 
|---|
 | 3190 |         fprintf(stderr,"J_{%i,%i} = |%e + i%e| < %e ? (%e)\t", in / NDIM, in%NDIM, CurrentDensityC[in][0].re, CurrentDensityC[in][0].im, MYEPSILON, tmp - MYEPSILON);
 | 
|---|
 | 3191 |       } else { 
 | 
|---|
 | 3192 |         fprintf(stderr,"J_{%i,%i} ok\t", in / NDIM, in%NDIM);
 | 
|---|
 | 3193 |       }
 | 
|---|
 | 3194 |       if (in % NDIM == (NDIM-1)) fprintf(stderr,"\n");
 | 
|---|
 | 3195 |     }   
 | 
|---|
 | 3196 |   }
 | 
|---|
 | 3197 | 
 | 
|---|
 | 3198 |   for (in=0;in<NDIM*NDIM;in++) {
 | 
|---|
 | 3199 |     LockDensityArray(Dens0,in,real); // Psi1R
 | 
|---|
 | 3200 |     sigma_imag[in] = (fftw_complex *) Dens0->DensityArray[in];
 | 
|---|
 | 3201 |     sigma_real[in] = (fftw_real *) sigma_imag[in];
 | 
|---|
 | 3202 |   }
 | 
|---|
 | 3203 | 
 | 
|---|
 | 3204 |   LockDensityArray(Dens0,TempDensity,imag); // work
 | 
|---|
 | 3205 |   LockDensityArray(Dens0,Temp2Density,imag); // tempdestRC and field
 | 
|---|
 | 3206 |   // go through reciprocal nodes and calculate shielding tensor sigma
 | 
|---|
 | 3207 |   for (in=0; in<NDIM; in++) {// index i of vector component in integrand
 | 
|---|
 | 3208 |     for(dex=0;dex<4;dex++)  // initialise cross lookup
 | 
|---|
 | 3209 |       cross_lookup[dex] = cross(in,dex);
 | 
|---|
 | 3210 |     for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
 | 
|---|
 | 3211 |       //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
 | 
|---|
 | 3212 |       SetArrayToDouble0((double *)sigma_imag[in+dex*NDIM],Dens0->TotalSize*2);
 | 
|---|
 | 3213 |       for (g=0; g < Lev0->MaxG; g++)
 | 
|---|
 | 3214 |         if (GArray[g].GSq > MYEPSILON) { // skip due to divisor
 | 
|---|
 | 3215 |           Index = GArray[g].Index; // re = im, im = -re due to "i" in formula
 | 
|---|
 | 3216 |           //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density] || Index<0 || Index>=Dens0->LocalSizeC) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
 | 
|---|
 | 3217 |           sigma_imag[in+dex*NDIM][Index].re  = GArray[g].G[cross_lookup[0]] * (-CurrentDensityC[dex*NDIM+cross_lookup[1]][Index].im)/GArray[g].GSq;//*FFTfactor;
 | 
|---|
 | 3218 |           sigma_imag[in+dex*NDIM][Index].re -= GArray[g].G[cross_lookup[2]] * (-CurrentDensityC[dex*NDIM+cross_lookup[3]][Index].im)/GArray[g].GSq;//*FFTfactor;
 | 
|---|
 | 3219 |           sigma_imag[in+dex*NDIM][Index].im  = GArray[g].G[cross_lookup[0]] * ( CurrentDensityC[dex*NDIM+cross_lookup[1]][Index].re)/GArray[g].GSq;//*FFTfactor;
 | 
|---|
 | 3220 |           sigma_imag[in+dex*NDIM][Index].im -= GArray[g].G[cross_lookup[2]] * ( CurrentDensityC[dex*NDIM+cross_lookup[3]][Index].re)/GArray[g].GSq;//*FFTfactor;
 | 
|---|
 | 3221 |         } else {  // G=0-component stems from magnetic susceptibility
 | 
|---|
 | 3222 |           sigma_imag[in+dex*NDIM][GArray[g].Index].re = 2./3.*I->I[0].chi[in+dex*NDIM];//-4.*M_PI*(0.5*I->I[0].chi[0+0*NDIM]+0.5*I->I[0].chi[1+1*NDIM]+2./3.*I->I[0].chi[2+2*NDIM]);
 | 
|---|
 | 3223 |         }
 | 
|---|
 | 3224 |       for (g=0; g<Lev0->MaxDoubleG; g++) { // apply symmetry
 | 
|---|
 | 3225 |         //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density] || Lev0->DoubleG[2*g+1]<0 || Lev0->DoubleG[2*g+1]>=Dens0->LocalSizeC) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
 | 
|---|
 | 3226 |         sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g+1]].re =  sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g]].re;
 | 
|---|
 | 3227 |         sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g+1]].im = -sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g]].im;
 | 
|---|
 | 3228 |       }
 | 
|---|
 | 3229 |       // fourier transformation of sigma
 | 
|---|
 | 3230 |       //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
 | 
|---|
 | 3231 |       fft_3d_complex_to_real(plan, Lev0->LevelNo, FFTNF1, sigma_imag[in+dex*NDIM], work);
 | 
|---|
 | 3232 | 
 | 
|---|
 | 3233 |       for (it=0; it < I->Max_Types; it++) {  // integration over all types
 | 
|---|
 | 3234 |         for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
 | 
|---|
 | 3235 |           // read transformed sigma at core position and MPI_Allreduce
 | 
|---|
 | 3236 |           for (g=0;g<NDIM;g++) {
 | 
|---|
 | 3237 |             n[0][g] = floor(I->I[it].R[NDIM*ion+g]/Lat->RealBasisQ[g]*(double)N[g]);
 | 
|---|
 | 3238 |             n[1][g] = ceil(I->I[it].R[NDIM*ion+g]/Lat->RealBasisQ[g]*(double)N[g]);
 | 
|---|
 | 3239 |             x[1][g] = I->I[it].R[NDIM*ion+g]/Lat->RealBasisQ[g]*(double)N[g] - (double)n[0][g];
 | 
|---|
 | 3240 |             x[0][g] = 1. - x[1][g];
 | 
|---|
 | 3241 |             //fprintf(stderr,"(%i) n_floor[%i] = %i\tn_ceil[%i] = %i --- x_floor[%i] = %e\tx_ceil[%i] = %e\n",P->Par.me, g,n[0][g], g,n[1][g], g,x[0][g], g,x[1][g]);
 | 
|---|
 | 3242 |           }
 | 
|---|
 | 3243 |           sigma = 0.;
 | 
|---|
 | 3244 |           for (i=0;i<2;i++) { // interpolate linearly between adjacent grid points per axis
 | 
|---|
 | 3245 |             if ((n[i][0] >= N0*myPE) && (n[i][0] < N0*(myPE+1))) {
 | 
|---|
 | 3246 | //              fprintf(stderr,"(%i) field[%i]: sigma = %e\n", P->Par.me,  n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), sigma);
 | 
|---|
 | 3247 |               sigma += (x[i][0]*x[0][1]*x[0][2])*sigma_real[in+dex*NDIM][n[0][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
 | 
|---|
 | 3248 |               //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me,  n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[0][1]*x[0][2]), field[n[0][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
 | 
|---|
 | 3249 |               sigma += (x[i][0]*x[0][1]*x[1][2])*sigma_real[in+dex*NDIM][n[1][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
 | 
|---|
 | 3250 |               //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me,  n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[0][1]*x[1][2]), field[n[1][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
 | 
|---|
 | 3251 |               sigma += (x[i][0]*x[1][1]*x[0][2])*sigma_real[in+dex*NDIM][n[0][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
 | 
|---|
 | 3252 |               //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me,  n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[1][1]*x[0][2]), field[n[0][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
 | 
|---|
 | 3253 |               sigma += (x[i][0]*x[1][1]*x[1][2])*sigma_real[in+dex*NDIM][n[1][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
 | 
|---|
 | 3254 |               //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me,  n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[1][1]*x[1][2]), field[n[1][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
 | 
|---|
 | 3255 |             }
 | 
|---|
 | 3256 |           }
 | 
|---|
 | 3257 |           sigma *= -R->FactorDensityR; // factor from inverse fft? (and its defined as negative proportionaly factor)
 | 
|---|
 | 3258 |           MPI_Allreduce ( &sigma, &Sigma, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);  // sum local to total
 | 
|---|
 | 3259 |           I->I[it].sigma_rezi[ion][in+dex*NDIM] = Sigma;
 | 
|---|
 | 3260 |         }
 | 
|---|
 | 3261 |       }
 | 
|---|
 | 3262 |       // fabs() all sigma values, as we need them as a positive density: OutputVis plots them in logarithmic scale and
 | 
|---|
 | 3263 |       // thus cannot deal with negative values!
 | 
|---|
 | 3264 |       for (i=0; i< Dens0->LocalSizeR; i++)
 | 
|---|
 | 3265 |         sigma_real[in+dex*NDIM][i] = fabs(sigma_real[in+dex*NDIM][i]);
 | 
|---|
 | 3266 |     }
 | 
|---|
 | 3267 |   }
 | 
|---|
 | 3268 |   UnLockDensityArray(Dens0,TempDensity,imag); // work
 | 
|---|
 | 3269 |   UnLockDensityArray(Dens0,Temp2Density,imag); // tempdestRC and field
 | 
|---|
 | 3270 | 
 | 
|---|
 | 3271 |   // output tensor to file
 | 
|---|
 | 3272 |   if (P->Par.me == 0) {
 | 
|---|
 | 3273 |     sprintf(&suffixsigma[0], ".sigma_chi_rezi.L%i.csv", Lev0->LevelNo);
 | 
|---|
 | 3274 |     OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
 | 
|---|
 | 3275 |     fprintf(SigmaFile,"# chemical shielding tensor sigma_rezi[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
 | 
|---|
 | 3276 |     fprintf(SigmaFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
 | 
|---|
 | 3277 |     for (in=0;in<NDIM;in++)
 | 
|---|
 | 3278 |       for (dex=0;dex<NDIM;dex++)
 | 
|---|
 | 3279 |         fprintf(SigmaFile,"%e\t", GSL_REAL(gsl_matrix_complex_get(H,in,dex)));
 | 
|---|
 | 3280 |     fprintf(SigmaFile,"\n");
 | 
|---|
 | 3281 |     fclose(SigmaFile);
 | 
|---|
 | 3282 |   }
 | 
|---|
 | 3283 | 
 | 
|---|
 | 3284 |   gsl_vector *eval = gsl_vector_alloc(NDIM);
 | 
|---|
 | 3285 |   gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
 | 
|---|
 | 3286 | 
 | 
|---|
 | 3287 |   for (it=0; it < I->Max_Types; it++) {  // integration over all types
 | 
|---|
 | 3288 |     for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
 | 
|---|
 | 3289 |       if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) Shielding Tensor for Ion %i of element %s \\sigma_ij = \n",P->Par.me, ion, I->I[it].Name);
 | 
|---|
 | 3290 |       for (in=0; in<NDIM; in++) { // index i of vector component in integrand
 | 
|---|
 | 3291 |         for (dex=0; dex<NDIM; dex++) {// index j of B component derivation in current density tensor
 | 
|---|
 | 3292 |           gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((I->I[it].sigma_rezi[ion][in+dex*NDIM]+I->I[it].sigma_rezi[ion][dex+in*NDIM])/2.,0));
 | 
|---|
 | 3293 |           if (P->Call.out[ValueOut]) fprintf(stderr,"%e\t", I->I[it].sigma_rezi[ion][in+dex*NDIM]);
 | 
|---|
 | 3294 |         }
 | 
|---|
 | 3295 |         if (P->Call.out[ValueOut]) fprintf(stderr,"\n");
 | 
|---|
 | 3296 |       }
 | 
|---|
 | 3297 |       // output tensor to file
 | 
|---|
 | 3298 |       if (P->Par.me == 0) {
 | 
|---|
 | 3299 |         sprintf(&suffixsigma[0], ".sigma_i%i_%s_rezi.L%i.csv", ion, I->I[it].Symbol, Lev0->LevelNo);
 | 
|---|
 | 3300 |         OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
 | 
|---|
 | 3301 |         fprintf(SigmaFile,"# chemical shielding tensor sigma_rezi[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
 | 
|---|
 | 3302 |         fprintf(SigmaFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
 | 
|---|
 | 3303 |         for (in=0;in<NDIM;in++)
 | 
|---|
 | 3304 |           for (dex=0;dex<NDIM;dex++)
 | 
|---|
 | 3305 |             fprintf(SigmaFile,"%e\t", I->I[it].sigma_rezi[ion][in+dex*NDIM]);
 | 
|---|
 | 3306 |         fprintf(SigmaFile,"\n");
 | 
|---|
 | 3307 |         fclose(SigmaFile);
 | 
|---|
 | 3308 |       }
 | 
|---|
 | 3309 |       // diagonalize sigma
 | 
|---|
 | 3310 |       gsl_eigen_herm(H, eval, w);
 | 
|---|
 | 3311 |       gsl_sort_vector(eval);  // sort eigenvalues
 | 
|---|
 | 3312 | //      print eigenvalues
 | 
|---|
 | 3313 | //      if (P->Call.out[ValueOut]) {
 | 
|---|
 | 3314 | //        fprintf(stderr,"(%i) diagonal shielding for Ion %i of element %s:", P->Par.me, ion, I->I[it].Name);
 | 
|---|
 | 3315 | //        for (in=0;in<NDIM;in++)
 | 
|---|
 | 3316 | //          fprintf(stderr,"\t%lg",gsl_vector_get(eval,in));
 | 
|---|
 | 3317 | //        fprintf(stderr,"\n\n");
 | 
|---|
 | 3318 | //      }
 | 
|---|
 | 3319 |       iso = 0.;
 | 
|---|
 | 3320 |       for (i=0;i<NDIM;i++) {
 | 
|---|
 | 3321 |         I->I[it].sigma_rezi_PAS[ion][i] = gsl_vector_get(eval,i);
 | 
|---|
 | 3322 |         iso += I->I[it].sigma_rezi[ion][i+i*NDIM]/3.;
 | 
|---|
 | 3323 |       } 
 | 
|---|
 | 3324 |       eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
 | 
|---|
 | 3325 |       delta_sigma = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
 | 
|---|
 | 3326 |       S = (delta_sigma*delta_sigma)*(1+1./3.*eta*eta);
 | 
|---|
 | 3327 |       A = 0.;
 | 
|---|
 | 3328 |       for (i=0;i<NDIM;i++) {
 | 
|---|
 | 3329 |         in = cross(i,0);
 | 
|---|
 | 3330 |         dex = cross(i,1);
 | 
|---|
 | 3331 |         A += pow(-1,i)*pow(0.5*(I->I[it].sigma_rezi[ion][in+dex*NDIM]-I->I[it].sigma_rezi[ion][dex+in*NDIM]),2);
 | 
|---|
 | 3332 |       }
 | 
|---|
 | 3333 |       if (P->Call.out[ValueOut]) {
 | 
|---|
 | 3334 |         fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
 | 
|---|
 | 3335 |         for (i=0;i<NDIM;i++)
 | 
|---|
 | 3336 |           fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
 | 
|---|
 | 3337 |         fprintf(stderr,"\nshielding  : %e\n", iso);
 | 
|---|
 | 3338 |         fprintf(stderr,"anisotropy : %e\n", delta_sigma);
 | 
|---|
 | 3339 |         fprintf(stderr,"asymmetry  : %e\n", eta);
 | 
|---|
 | 3340 |         fprintf(stderr,"S          : %e\n", S);
 | 
|---|
 | 3341 |         fprintf(stderr,"A          : %e\n", A);
 | 
|---|
 | 3342 |         fprintf(stderr,"==================\n");
 | 
|---|
 | 3343 |         
 | 
|---|
 | 3344 |       }
 | 
|---|
 | 3345 |     }
 | 
|---|
 | 3346 |   }
 | 
|---|
 | 3347 |   
 | 
|---|
 | 3348 |   // Output of magnetic field densities for each direction
 | 
|---|
 | 3349 |   for (i=0;i<NDIM*NDIM;i++)
 | 
|---|
 | 3350 |     OutputVis(P, sigma_real[i]);    
 | 
|---|
 | 3351 |   // Diagonalizing the tensor "field" B_ij [r]
 | 
|---|
 | 3352 |   fprintf(stderr,"(%i) Diagonalizing B_ij [r] ... \n", P->Par.me);
 | 
|---|
 | 3353 |   for (i=0; i< Dens0->LocalSizeR; i++) {
 | 
|---|
 | 3354 |     for (in=0; in<NDIM; in++) // index i of vector component in integrand
 | 
|---|
 | 3355 |       for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
 | 
|---|
 | 3356 |         //fprintf(stderr,"(%i) Setting B_(%i,%i)[%i] ... \n", P->Par.me, in,dex,i);
 | 
|---|
 | 3357 |         gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((sigma_real[in+dex*NDIM][i]+sigma_real[dex+in*NDIM][i])/2.,0));
 | 
|---|
 | 3358 |       }
 | 
|---|
 | 3359 |     gsl_eigen_herm(H, eval, w);
 | 
|---|
 | 3360 |     gsl_sort_vector(eval);  // sort eigenvalues
 | 
|---|
 | 3361 |     for (in=0;in<NDIM;in++)
 | 
|---|
 | 3362 |       sigma_real[in][i] = gsl_vector_get(eval,in);
 | 
|---|
 | 3363 |   }
 | 
|---|
 | 3364 |   // Output of diagonalized magnetic field densities for each direction
 | 
|---|
 | 3365 |   for (i=0;i<NDIM;i++)
 | 
|---|
 | 3366 |     OutputVis(P, sigma_real[i]);    
 | 
|---|
 | 3367 |   for (i=0;i<NDIM*NDIM;i++)
 | 
|---|
 | 3368 |     UnLockDensityArray(Dens0,i,real);  // sigma_imag/real free
 | 
|---|
 | 3369 | 
 | 
|---|
 | 3370 |   gsl_eigen_herm_free(w);
 | 
|---|
 | 3371 |   gsl_vector_free(eval);
 | 
|---|
 | 3372 |   gsl_matrix_complex_free(H);
 | 
|---|
 | 3373 | }
 | 
|---|
 | 3374 | 
 | 
|---|
 | 3375 | 
 | 
|---|
 | 3376 | /** Calculates the chemical shielding tensor at the positions of the nuclei.
 | 
|---|
 | 3377 |  * The chemical shielding tensor at position R is defined as the proportionality factor between the induced and
 | 
|---|
 | 3378 |  * the externally applied field.
 | 
|---|
 | 3379 |  * \f[
 | 
|---|
 | 3380 |  *  \sigma_{ij} (R) = \frac{\delta B_j^{ind} (R)}{\delta B_i^{ext}} 
 | 
|---|
 | 3381 |  *  = \frac{\mu_0}{4 \pi} \int d^3 r' \left ( \frac{r'-r}{| r' - r |^3} \times J_i (r') \right )_j 
 | 
|---|
 | 3382 |  * \f]
 | 
|---|
 | 3383 |  * One after another for each nuclear position is the tensor evaluated and the result printed
 | 
|---|
 | 3384 |  * to screen. Tensor is diagonalized afterwards.
 | 
|---|
 | 3385 |  * \param *P Problem at hand
 | 
|---|
 | 3386 |  * \sa CalculateMagneticSusceptibility() - similar calculation, yet without translation to ion centers.
 | 
|---|
 | 3387 |  * \warning This routine is out-dated due to being numerically unstable because of the singularity which is not
 | 
|---|
 | 3388 |  * considered carefully, recommendend replacement is CalculateChemicalShieldingByReciprocalCurrentDensity().
 | 
|---|
 | 3389 |  */
 | 
|---|
 | 3390 | void CalculateChemicalShielding(struct Problem *P)
 | 
|---|
 | 3391 | {
 | 
|---|
 | 3392 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 3393 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 3394 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 3395 |   struct Density *Dens0 = R->Lev0->Dens;
 | 
|---|
 | 3396 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 3397 |   double sigma[NDIM*NDIM],Sigma[NDIM*NDIM];
 | 
|---|
 | 3398 |   fftw_real *CurrentDensity[NDIM*NDIM];
 | 
|---|
 | 3399 |   int it, ion, in, dex, i0, n[NDIM], n0, i;//, *NUp;
 | 
|---|
 | 3400 |   double x,y,z; 
 | 
|---|
 | 3401 |   double dist;
 | 
|---|
 | 3402 |   double r[NDIM], fac[NDIM];
 | 
|---|
 | 3403 |   const double discrete_factor = Lat->Volume/Lev0->MaxN;
 | 
|---|
 | 3404 |   double eta, delta_sigma, S, A, iso;
 | 
|---|
 | 3405 |   const int myPE =  P->Par.me_comm_ST_Psi;
 | 
|---|
 | 3406 |   int N[NDIM];
 | 
|---|
 | 3407 |   N[0] = Lev0->Plan0.plan->N[0];
 | 
|---|
 | 3408 |   N[1] = Lev0->Plan0.plan->N[1];
 | 
|---|
 | 3409 |   N[2] = Lev0->Plan0.plan->N[2];
 | 
|---|
 | 3410 |   const int N0 = Lev0->Plan0.plan->local_nx;
 | 
|---|
 | 3411 |   FILE *SigmaFile;
 | 
|---|
 | 3412 |   char suffixsigma[255];
 | 
|---|
 | 3413 |   time_t seconds;  
 | 
|---|
 | 3414 |   time(&seconds); // get current time
 | 
|---|
 | 3415 |   
 | 
|---|
 | 3416 |   // set pointers onto current density
 | 
|---|
 | 3417 |   CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
 | 
|---|
 | 3418 |   CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
 | 
|---|
 | 3419 |   CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
 | 
|---|
 | 3420 |   CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
 | 
|---|
 | 3421 |   CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
 | 
|---|
 | 3422 |   CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
 | 
|---|
 | 3423 |   CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
 | 
|---|
 | 3424 |   CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
 | 
|---|
 | 3425 |   CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
 | 
|---|
 | 3426 |   gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
 | 
|---|
 | 3427 |   
 | 
|---|
 | 3428 |   for (it=0; it < I->Max_Types; it++) {  // integration over all types
 | 
|---|
 | 3429 |     for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
 | 
|---|
 | 3430 |       if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) Shielding Tensor for Ion %i of element %s \\sigma_ij = \n",P->Par.me, ion, I->I[it].Name);
 | 
|---|
 | 3431 |       for (in=0; in<NDIM; in++) {// index i of vector component in integrand
 | 
|---|
 | 3432 |         for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
 | 
|---|
 | 3433 |           sigma[in+dex*NDIM] = 0.;
 | 
|---|
 | 3434 |     
 | 
|---|
 | 3435 |           for(n0=0;n0<N0;n0++) // do the integration over real space
 | 
|---|
 | 3436 |             for(n[1]=0;n[1]<N[1];n[1]++)
 | 
|---|
 | 3437 |               for(n[2]=0;n[2]<N[2];n[2]++) {
 | 
|---|
 | 3438 |                 n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
 | 
|---|
 | 3439 |                 fac[0] = (double)n[0]/(double)N[0];
 | 
|---|
 | 3440 |                 fac[1] = (double)n[1]/(double)N[1];
 | 
|---|
 | 3441 |                 fac[2] = (double)n[2]/(double)N[2];
 | 
|---|
 | 3442 |                 RMat33Vec3(r, Lat->RealBasis, fac);
 | 
|---|
 | 3443 |                 i0 = n[2]+N[2]*(n[1]+N[1]*(n0));  // the index of current density must match LocalSizeR!
 | 
|---|
 | 3444 |                 x = MinImageConv(Lat,r[cross(in,0)], I->I[it].R[NDIM*ion+cross(in,0)],cross(in,0));
 | 
|---|
 | 3445 |                 y = MinImageConv(Lat,r[cross(in,2)], I->I[it].R[NDIM*ion+cross(in,2)],cross(in,2));
 | 
|---|
 | 3446 |                 z = MinImageConv(Lat,r[in], I->I[it].R[NDIM*ion+in],in);  // "in" always is missing third component in cross product
 | 
|---|
 | 3447 |                 dist = pow(x*x + y*y + z*z, 3./2.);
 | 
|---|
 | 3448 |                 if ((dist < pow(2.,3.)) && (dist > MYEPSILON)) sigma[in+dex*NDIM] += (x * CurrentDensity[dex*NDIM+cross(in,1)][i0] - y * CurrentDensity[dex*NDIM+cross(in,3)][i0])/dist;
 | 
|---|
 | 3449 |                 //if (it == 0 && ion == 0) fprintf(stderr,"(%i) sigma[%i][%i] += (%e * %e - %e * %e)/%e = %e\n", P->Par.me, in, dex, x,CurrentDensity[dex*NDIM+cross(in,1)][i0],y,CurrentDensity[dex*NDIM+cross(in,3)][i0],dist,sigma[in+dex*NDIM]); 
 | 
|---|
 | 3450 |               }
 | 
|---|
 | 3451 |           sigma[in+dex*NDIM] *= -mu0*discrete_factor/(4.*PI); // due to summation instead of integration
 | 
|---|
 | 3452 |           MPI_Allreduce ( &sigma[in+dex*NDIM], &Sigma[in+dex*NDIM], 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);  // sum "LocalSize to TotalSize"
 | 
|---|
 | 3453 |           I->I[it].sigma[ion][in+dex*NDIM] = Sigma[in+dex*NDIM];          
 | 
|---|
 | 3454 |           if (P->Call.out[ValueOut]) fprintf(stderr," %e", Sigma[in+dex*NDIM]);
 | 
|---|
 | 3455 |         }
 | 
|---|
 | 3456 |         if (P->Call.out[ValueOut]) fprintf(stderr,"\n");
 | 
|---|
 | 3457 |       }
 | 
|---|
 | 3458 |       // store symmetrized matrix
 | 
|---|
 | 3459 |       for (in=0;in<NDIM;in++)
 | 
|---|
 | 3460 |         for (dex=0;dex<NDIM;dex++)
 | 
|---|
 | 3461 |           gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((Sigma[in+dex*NDIM]+Sigma[dex+in*NDIM])/2.,0));
 | 
|---|
 | 3462 |       // output tensor to file
 | 
|---|
 | 3463 |       if (P->Par.me == 0) {
 | 
|---|
 | 3464 |         sprintf(&suffixsigma[0], ".sigma_i%i_%s.L%i.csv", ion, I->I[it].Symbol, Lev0->LevelNo);
 | 
|---|
 | 3465 |         OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
 | 
|---|
 | 3466 |         fprintf(SigmaFile,"# chemical shielding tensor sigma[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
 | 
|---|
 | 3467 |         fprintf(SigmaFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
 | 
|---|
 | 3468 |         for (in=0;in<NDIM*NDIM;in++)
 | 
|---|
 | 3469 |           fprintf(SigmaFile,"%e\t", Sigma[in]);
 | 
|---|
 | 3470 |         fprintf(SigmaFile,"\n");
 | 
|---|
 | 3471 |         fclose(SigmaFile);
 | 
|---|
 | 3472 |       }
 | 
|---|
 | 3473 |       // diagonalize sigma
 | 
|---|
 | 3474 |       gsl_vector *eval = gsl_vector_alloc(NDIM);
 | 
|---|
 | 3475 |       gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
 | 
|---|
 | 3476 |       gsl_eigen_herm(H, eval, w);
 | 
|---|
 | 3477 |       gsl_eigen_herm_free(w);
 | 
|---|
 | 3478 |       gsl_sort_vector(eval);  // sort eigenvalues
 | 
|---|
 | 3479 |       // print eigenvalues
 | 
|---|
 | 3480 | //      if (P->Call.out[ValueOut]) {
 | 
|---|
 | 3481 | //        fprintf(stderr,"(%i) diagonal shielding for Ion %i of element %s:", P->Par.me, ion, I->I[it].Name);
 | 
|---|
 | 3482 | //        for (in=0;in<NDIM;in++)
 | 
|---|
 | 3483 | //          fprintf(stderr,"\t%lg",gsl_vector_get(eval,in));
 | 
|---|
 | 3484 | //        fprintf(stderr,"\n\n");
 | 
|---|
 | 3485 | //      }
 | 
|---|
 | 3486 |       // print eigenvalues
 | 
|---|
 | 3487 |       iso = 0;
 | 
|---|
 | 3488 |       for (i=0;i<NDIM;i++) {
 | 
|---|
 | 3489 |         I->I[it].sigma[ion][i] = gsl_vector_get(eval,i);
 | 
|---|
 | 3490 |         iso += Sigma[i+i*NDIM]/3.;
 | 
|---|
 | 3491 |       } 
 | 
|---|
 | 3492 |       eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
 | 
|---|
 | 3493 |       delta_sigma = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
 | 
|---|
 | 3494 |       S = (delta_sigma*delta_sigma)*(1+1./3.*eta*eta);
 | 
|---|
 | 3495 |       A = 0.;
 | 
|---|
 | 3496 |       for (i=0;i<NDIM;i++) {
 | 
|---|
 | 3497 |         in = cross(i,0);
 | 
|---|
 | 3498 |         dex = cross(i,1);
 | 
|---|
 | 3499 |         A += pow(-1,i)*pow(0.5*(Sigma[in+dex*NDIM]-Sigma[dex+in*NDIM]),2);
 | 
|---|
 | 3500 |       }
 | 
|---|
 | 3501 |       if (P->Call.out[ValueOut]) {
 | 
|---|
 | 3502 |         fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
 | 
|---|
 | 3503 |         for (i=0;i<NDIM;i++)
 | 
|---|
 | 3504 |           fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
 | 
|---|
 | 3505 |         fprintf(stderr,"\nshielding  : %e\n", iso);
 | 
|---|
 | 3506 |         fprintf(stderr,"anisotropy : %e\n", delta_sigma);
 | 
|---|
 | 3507 |         fprintf(stderr,"asymmetry  : %e\n", eta);
 | 
|---|
 | 3508 |         fprintf(stderr,"S          : %e\n", S);
 | 
|---|
 | 3509 |         fprintf(stderr,"A          : %e\n", A);
 | 
|---|
 | 3510 |         fprintf(stderr,"==================\n");
 | 
|---|
 | 3511 |         
 | 
|---|
 | 3512 |       }
 | 
|---|
 | 3513 |       gsl_vector_free(eval);
 | 
|---|
 | 3514 |     }
 | 
|---|
 | 3515 |   }
 | 
|---|
 | 3516 | 
 | 
|---|
 | 3517 |   gsl_matrix_complex_free(H);
 | 
|---|
 | 3518 | }
 | 
|---|
 | 3519 | 
 | 
|---|
 | 3520 | /** Test if integrated current over cell is 0.
 | 
|---|
 | 3521 |  * In most cases we do not reach a numerical sensible zero as in MYEPSILON and remain satisfied as long
 | 
|---|
 | 3522 |  * as the integrated current density is very small (e.g. compared to single entries in the current density array)
 | 
|---|
 | 3523 |  * \param *P Problem at hand
 | 
|---|
 | 3524 |  * \param index index of current component
 | 
|---|
 | 3525 |  * \sa CalculateNativeIntDens() for integration of one current tensor component
 | 
|---|
 | 3526 |  */
 | 
|---|
 | 3527 |  void TestCurrent(struct Problem *P, const int index)
 | 
|---|
 | 3528 | {
 | 
|---|
 | 3529 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 3530 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 3531 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 3532 |   fftw_real *CurrentDensity[NDIM*NDIM];
 | 
|---|
 | 3533 |   int in;
 | 
|---|
 | 3534 |   double result[NDIM*NDIM], res = 0.;
 | 
|---|
 | 3535 | 
 | 
|---|
 | 3536 |   // set pointers onto current density array and get number of grid points in each direction
 | 
|---|
 | 3537 |   CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
 | 
|---|
 | 3538 |   CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
 | 
|---|
 | 3539 |   CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
 | 
|---|
 | 3540 |   CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
 | 
|---|
 | 3541 |   CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
 | 
|---|
 | 3542 |   CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
 | 
|---|
 | 3543 |   CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
 | 
|---|
 | 3544 |   CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
 | 
|---|
 | 3545 |   CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
 | 
|---|
 | 3546 |   for(in=0;in<NDIM;in++) {
 | 
|---|
 | 3547 |     result[in] = CalculateNativeIntDens(P,Lev0,CurrentDensity[in + NDIM*index],R->FactorDensityR);
 | 
|---|
 | 3548 |     res += pow(result[in],2.);
 | 
|---|
 | 3549 |   }
 | 
|---|
 | 3550 |   res = sqrt(res);
 | 
|---|
 | 3551 |   // if greater than 0, complain about it
 | 
|---|
 | 3552 |   if ((res > MYEPSILON) && (P->Call.out[LeaderOut])) 
 | 
|---|
 | 3553 |     fprintf(stderr, "(%i) \\int_\\Omega d^3 r j_%i(r) = (%e,%e,%e), %e > %e!\n",P->Par.me, index, result[0], result[1], result[2], res, MYEPSILON);
 | 
|---|
 | 3554 | }
 | 
|---|
 | 3555 | 
 | 
|---|
 | 3556 | /** Testing whether re<->im switches (due to symmetry) confuses fft.
 | 
|---|
 | 3557 |  * \param *P Problem at hand
 | 
|---|
 | 3558 |  * \param l local wave function number
 | 
|---|
 | 3559 |  */
 | 
|---|
 | 3560 | void test_fft_symmetry(struct Problem *P, const int l)
 | 
|---|
 | 3561 | {
 | 
|---|
 | 3562 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 3563 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 3564 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 3565 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 3566 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 3567 |   struct  fft_plan_3d *plan = Lat->plan;
 | 
|---|
 | 3568 |   fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityCArray[Temp2Density];
 | 
|---|
 | 3569 |   fftw_complex *work = Dens0->DensityCArray[TempDensity];
 | 
|---|
 | 3570 |   fftw_complex *workC = (fftw_complex *)Dens0->DensityArray[TempDensity];
 | 
|---|
 | 3571 |   fftw_complex *posfac, *destpos, *destRCS, *destRCD;
 | 
|---|
 | 3572 |   fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
 | 3573 |   fftw_real *PsiCR = (fftw_real *) PsiC;
 | 
|---|
 | 3574 |   fftw_complex *Psi0 = LevS->LPsi->LocalPsi[l];
 | 
|---|
 | 3575 |   fftw_complex *dest = LevS->LPsi->TempPsi;
 | 
|---|
 | 3576 |   fftw_real *Psi0R = (fftw_real *)Dens0->DensityArray[Temp2Density];
 | 
|---|
 | 3577 |   int i,Index, pos, i0, iS,g; //, NoOfPsis = Psi->TypeStartIndex[UnOccupied] - Psi->TypeStartIndex[Occupied];
 | 
|---|
 | 3578 |   int n[NDIM], n0;
 | 
|---|
 | 3579 |   const int N0 = LevS->Plan0.plan->local_nx; // we don't want to build global density, but local
 | 
|---|
 | 3580 |   int N[NDIM], NUp[NDIM];
 | 
|---|
 | 3581 |   N[0] = LevS->Plan0.plan->N[0];
 | 
|---|
 | 3582 |   N[1] = LevS->Plan0.plan->N[1];
 | 
|---|
 | 3583 |   N[2] = LevS->Plan0.plan->N[2];
 | 
|---|
 | 3584 |   NUp[0] = LevS->NUp[0]; 
 | 
|---|
 | 3585 |   NUp[1] = LevS->NUp[1]; 
 | 
|---|
 | 3586 |   NUp[2] = LevS->NUp[2]; 
 | 
|---|
 | 3587 |   //const int k_normal = Lat->Psi.TypeStartIndex[Occupied] + (l - Lat->Psi.TypeStartIndex[R->CurrentMin]);
 | 
|---|
 | 3588 |   //const double *Wcentre = Lat->Psi.AddData[k_normal].WannierCentre;
 | 
|---|
 | 3589 |   //double x[NDIM], fac[NDIM]; 
 | 
|---|
 | 3590 |   double result1=0., result2=0., result3=0., result4=0.;
 | 
|---|
 | 3591 |   double Result1=0., Result2=0., Result3=0., Result4=0.;
 | 
|---|
 | 3592 |   const double HGcRCFactor = 1./LevS->MaxN; // factor for inverse fft
 | 
|---|
 | 3593 | 
 | 
|---|
 | 3594 |   
 | 
|---|
 | 3595 |   // fft to real space
 | 
|---|
 | 3596 |   SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
 | 
|---|
 | 3597 |   SetArrayToDouble0((double *)PsiC, Dens0->TotalSize*2);
 | 
|---|
 | 3598 |   for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
 | 
|---|
 | 3599 |     Index = LevS->GArray[i].Index;
 | 
|---|
 | 3600 |     posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 3601 |     destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 3602 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 3603 |       destpos[pos].re = (Psi0[i].re)*posfac[pos].re-(Psi0[i].im)*posfac[pos].im;
 | 
|---|
 | 3604 |       destpos[pos].im = (Psi0[i].re)*posfac[pos].im+(Psi0[i].im)*posfac[pos].re;
 | 
|---|
 | 3605 |       //destpos[pos].re = (Psi0[i].im)*posfac[pos].re-(-Psi0[i].re)*posfac[pos].im;
 | 
|---|
 | 3606 |       //destpos[pos].im = (Psi0[i].im)*posfac[pos].im+(-Psi0[i].re)*posfac[pos].re;
 | 
|---|
 | 3607 |     }
 | 
|---|
 | 3608 |   }
 | 
|---|
 | 3609 |   for (i=0; i<LevS->MaxDoubleG; i++) {
 | 
|---|
 | 3610 |     destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
 | 
|---|
 | 3611 |     destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
 | 
|---|
 | 3612 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 3613 |       destRCD[pos].re =  destRCS[pos].re;
 | 
|---|
 | 3614 |       destRCD[pos].im = -destRCS[pos].im;
 | 
|---|
 | 3615 |     }
 | 
|---|
 | 3616 |   }
 | 
|---|
 | 3617 |   fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
 | 
|---|
 | 3618 |   DensityRTransformPos(LevS,(fftw_real*)tempdestRC, Psi0R);  
 | 
|---|
 | 3619 |   
 | 
|---|
 | 3620 |   // apply position operator and do first result
 | 
|---|
 | 3621 |   for (n0=0;n0<N0;n0++)  // only local points on x axis
 | 
|---|
 | 3622 |     for (n[1]=0;n[1]<N[1];n[1]++)
 | 
|---|
 | 3623 |       for (n[2]=0;n[2]<N[2];n[2]++) {
 | 
|---|
 | 3624 |         n[0]=n0 + LevS->Plan0.plan->start_nx; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
 | 
|---|
 | 3625 |         i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
 | 
|---|
 | 3626 |         iS = n[2]+N[2]*(n[1]+N[1]*n0);
 | 
|---|
 | 3627 |         //x[0] += 1; // shifting expectation value of x coordinate from 0 to 1 
 | 
|---|
 | 3628 |         PsiCR[iS] = Psi0R[i0]; // truedist(Lat, x[0], Wcentre[0],0) * 
 | 
|---|
 | 3629 |         result1 += PsiCR[iS] * Psi0R[i0];         
 | 
|---|
 | 3630 |       }               
 | 
|---|
 | 3631 |   result1 /= LevS->MaxN; // factor due to discrete integration
 | 
|---|
 | 3632 |   MPI_Allreduce ( &result1, &Result1, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);   // sum "LocalSize to TotalSize"
 | 
|---|
 | 3633 |   if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 1st result: %e\n",P->Par.me, Result1);
 | 
|---|
 | 3634 |     
 | 
|---|
 | 3635 |   // fft to reciprocal space and do second result
 | 
|---|
 | 3636 |   fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, PsiC, workC);
 | 
|---|
 | 3637 |   SetArrayToDouble0((double *)dest, 2*R->InitLevS->MaxG);
 | 
|---|
 | 3638 |   for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
 | 3639 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 3640 |     dest[g].re = (Psi0[Index].re)*HGcRCFactor; 
 | 
|---|
 | 3641 |     dest[g].im = (Psi0[Index].im)*HGcRCFactor; 
 | 
|---|
 | 3642 |   }
 | 
|---|
 | 3643 |   result2 = GradSP(P,LevS,Psi0,dest);  
 | 
|---|
 | 3644 |   MPI_Allreduce ( &result2, &Result2, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);   // sum "LocalSize to TotalSize"
 | 
|---|
 | 3645 |   if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 2nd result: %e\n",P->Par.me, Result2);  
 | 
|---|
 | 3646 |   
 | 
|---|
 | 3647 |   // fft again to real space, this time change symmetry
 | 
|---|
 | 3648 |   SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
 | 
|---|
 | 3649 |   SetArrayToDouble0((double *)PsiC, Dens0->TotalSize*2);
 | 
|---|
 | 3650 |   for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
 | 
|---|
 | 3651 |     Index = LevS->GArray[i].Index;
 | 
|---|
 | 3652 |     posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 3653 |     destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 3654 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 3655 |       destpos[pos].re = (Psi0[i].im)*posfac[pos].re-(-Psi0[i].re)*posfac[pos].im;
 | 
|---|
 | 3656 |       destpos[pos].im = (Psi0[i].im)*posfac[pos].im+(-Psi0[i].re)*posfac[pos].re;
 | 
|---|
 | 3657 |     }
 | 
|---|
 | 3658 |   }
 | 
|---|
 | 3659 |   for (i=0; i<LevS->MaxDoubleG; i++) {
 | 
|---|
 | 3660 |     destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
 | 
|---|
 | 3661 |     destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
 | 
|---|
 | 3662 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 3663 |       destRCD[pos].re =  destRCS[pos].re;
 | 
|---|
 | 3664 |       destRCD[pos].im = -destRCS[pos].im;
 | 
|---|
 | 3665 |     }
 | 
|---|
 | 3666 |   }
 | 
|---|
 | 3667 |   fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
 | 
|---|
 | 3668 |   DensityRTransformPos(LevS,(fftw_real*)tempdestRC, Psi0R);
 | 
|---|
 | 3669 |   
 | 
|---|
 | 3670 |   // bring down from Lev0 to LevS
 | 
|---|
 | 3671 |   for (n0=0;n0<N0;n0++)  // only local points on x axis
 | 
|---|
 | 3672 |     for (n[1]=0;n[1]<N[1];n[1]++)
 | 
|---|
 | 3673 |       for (n[2]=0;n[2]<N[2];n[2]++) {
 | 
|---|
 | 3674 |         i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
 | 
|---|
 | 3675 |         iS = n[2]+N[2]*(n[1]+N[1]*n0);
 | 
|---|
 | 3676 |         PsiCR[iS] = Psi0R[i0]; // truedist(Lat, x[0], Wcentre[0],0) * 
 | 
|---|
 | 3677 |         result3 += PsiCR[iS] * Psi0R[i0];         
 | 
|---|
 | 3678 |       }               
 | 
|---|
 | 3679 |   result3 /= LevS->MaxN; // factor due to discrete integration
 | 
|---|
 | 3680 |   MPI_Allreduce ( &result3, &Result3, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);   // sum "LocalSize to TotalSize"
 | 
|---|
 | 3681 |   if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 3rd result: %e\n",P->Par.me, Result3);  
 | 
|---|
 | 3682 |   
 | 
|---|
 | 3683 |   // fft back to reciprocal space, change symmetry back and do third result
 | 
|---|
 | 3684 |   fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, PsiC, workC);
 | 
|---|
 | 3685 |   SetArrayToDouble0((double *)dest, 2*R->InitLevS->MaxG);
 | 
|---|
 | 3686 |   for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
 | 3687 |     Index = LevS->GArray[g].Index;
 | 
|---|
 | 3688 |     dest[g].re = (-PsiC[Index].im)*HGcRCFactor; 
 | 
|---|
 | 3689 |     dest[g].im = ( PsiC[Index].re)*HGcRCFactor; 
 | 
|---|
 | 3690 |   }
 | 
|---|
 | 3691 |   result4 = GradSP(P,LevS,Psi0,dest);
 | 
|---|
 | 3692 |   MPI_Allreduce ( &result4, &Result4, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);   // sum "LocalSize to TotalSize"
 | 
|---|
 | 3693 |   if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 4th result: %e\n",P->Par.me, Result4);  
 | 
|---|
 | 3694 | }
 | 
|---|
 | 3695 | 
 | 
|---|
 | 3696 | 
 | 
|---|
 | 3697 | /** Test function to check RxP application.
 | 
|---|
 | 3698 |  * Checks applied solution to an analytic for a specific and simple wave function -
 | 
|---|
 | 3699 |  * where just one coefficient is unequal to zero.
 | 
|---|
 | 3700 |  * \param *P Problem at hand
 | 
|---|
 | 3701 |          exp(I b G) - I exp(I b G) b G - exp(I a G) + I exp(I a G) a G
 | 
|---|
 | 3702 |  -------------------------------------------------------------
 | 
|---|
 | 3703 |                                2                              
 | 
|---|
 | 3704 |                               G                               
 | 
|---|
 | 3705 |  */
 | 
|---|
 | 3706 | void test_rxp(struct Problem *P)
 | 
|---|
 | 3707 | {
 | 
|---|
 | 3708 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 3709 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 3710 |   //struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 3711 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
 | 3712 |   struct OneGData *GA = LevS->GArray;
 | 
|---|
 | 3713 |   //struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 3714 |   fftw_complex *Psi0 = LevS->LPsi->TempPsi;
 | 
|---|
 | 3715 |   fftw_complex *Psi2 = P->Grad.GradientArray[GraSchGradient];
 | 
|---|
 | 3716 |   fftw_complex *Psi3 = LevS->LPsi->TempPsi2;
 | 
|---|
 | 3717 |   int g, g_bar, i, j, k, k_normal = 0;
 | 
|---|
 | 3718 |   double tmp, a,b, G;
 | 
|---|
 | 3719 |   //const double *Wcentre = Lat->Psi.AddData[k_normal].WannierCentre;
 | 
|---|
 | 3720 |   const double discrete_factor = 1.;//Lat->Volume/LevS->MaxN;
 | 
|---|
 | 3721 |   fftw_complex integral;
 | 
|---|
 | 3722 |   
 | 
|---|
 | 3723 |   // reset coefficients
 | 
|---|
 | 3724 |   debug (P,"Creating RxP test function.");
 | 
|---|
 | 3725 |   SetArrayToDouble0((double *)Psi0,2*R->InitLevS->MaxG);
 | 
|---|
 | 3726 |   SetArrayToDouble0((double *)Psi2,2*R->InitLevS->MaxG);
 | 
|---|
 | 3727 | 
 | 
|---|
 | 3728 |   // pick one which becomes non-zero
 | 
|---|
 | 3729 |   g = 3;
 | 
|---|
 | 3730 |   
 | 
|---|
 | 3731 |   //for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
 | 3732 |     Psi0[g].re = 1.;
 | 
|---|
 | 3733 |     Psi0[g].im = 0.;
 | 
|---|
 | 3734 |   //}
 | 
|---|
 | 3735 |   fprintf(stderr,"(%i) G[%i] = (%e,%e,%e) \n",P->Par.me, g, GA[g].G[0], GA[g].G[1], GA[g].G[2]);
 | 
|---|
 | 3736 |   i = 0;
 | 
|---|
 | 3737 | 
 | 
|---|
 | 3738 |   // calculate analytic result
 | 
|---|
 | 3739 |   debug (P,"Calculating analytic solution.");
 | 
|---|
 | 3740 |   for (g_bar=0;g_bar<LevS->MaxG;g_bar++) {
 | 
|---|
 | 3741 |     for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
 | 3742 |       if (GA[g].G[i] == GA[g_bar].G[i]) {
 | 
|---|
 | 3743 |         j = cross(i,0);
 | 
|---|
 | 3744 |         k = cross(i,1);
 | 
|---|
 | 3745 |         if (GA[g].G[k] == GA[g_bar].G[k]) {
 | 
|---|
 | 3746 |           //b = truedist(Lat, Lat->RealBasisQ[j], Wcentre[j], j); 
 | 
|---|
 | 3747 |           b = Lat->RealBasisQ[j];
 | 
|---|
 | 3748 |           //a = truedist(Lat, 0., Wcentre[j], j);  
 | 
|---|
 | 3749 |           a = 0.;
 | 
|---|
 | 3750 |           G = 1; //GA[g].G[k];
 | 
|---|
 | 3751 |           if (GA[g].G[j] == GA[g_bar].G[j]) {
 | 
|---|
 | 3752 |             Psi2[g_bar].re += G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor;
 | 
|---|
 | 3753 |             Psi2[g_bar].im += G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor;
 | 
|---|
 | 3754 |             //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON))) 
 | 
|---|
 | 3755 |               //fprintf(stderr,"(%i) Psi[%i].re += %e +i %e\n",P->Par.me, g_bar, G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor, G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor);
 | 
|---|
 | 3756 |           } else {
 | 
|---|
 | 3757 |             tmp = GA[g].G[j]-GA[g_bar].G[j];
 | 
|---|
 | 3758 |             integral.re = (cos(tmp*b)+sin(tmp*b)*b*tmp - cos(tmp*a)-sin(tmp*a)*a*tmp) / (tmp * tmp);
 | 
|---|
 | 3759 |             integral.im = (sin(tmp*b)-cos(tmp*b)*b*tmp - sin(tmp*a)+cos(tmp*a)*a*tmp) / (tmp * tmp);
 | 
|---|
 | 3760 |             Psi2[g_bar].re += G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor; 
 | 
|---|
 | 3761 |             Psi2[g_bar].im += G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor;
 | 
|---|
 | 3762 |             //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))  
 | 
|---|
 | 3763 |               //fprintf(stderr,"(%i) Psi[%i].re += %e\tPsi[%i].im += %e \n",P->Par.me, g_bar, G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor, g_bar, G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor);
 | 
|---|
 | 3764 |           }
 | 
|---|
 | 3765 |         }
 | 
|---|
 | 3766 |         j = cross(i,2);
 | 
|---|
 | 3767 |         k = cross(i,3);
 | 
|---|
 | 3768 |         if (GA[g].G[k] == GA[g_bar].G[k]) {
 | 
|---|
 | 3769 |           //b = truedist(Lat, Lat->RealBasisQ[j], Wcentre[j], j); 
 | 
|---|
 | 3770 |           b = Lat->RealBasisQ[j];
 | 
|---|
 | 3771 |           //a = truedist(Lat, 0., Wcentre[j], j);  
 | 
|---|
 | 3772 |           a = 0.;
 | 
|---|
 | 3773 |           G = 1; //GA[g].G[k];
 | 
|---|
 | 3774 |           if (GA[g].G[j] == GA[g_bar].G[j]) {
 | 
|---|
 | 3775 |             Psi2[g_bar].re += G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor;
 | 
|---|
 | 3776 |             Psi2[g_bar].im += G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor;
 | 
|---|
 | 3777 |             //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON))) 
 | 
|---|
 | 3778 |               //fprintf(stderr,"(%i) Psi[%i].re += %e +i %e\n",P->Par.me, g_bar, G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor, G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor);
 | 
|---|
 | 3779 |           } else {
 | 
|---|
 | 3780 |             tmp = GA[g].G[j]-GA[g_bar].G[j];
 | 
|---|
 | 3781 |             integral.re = (cos(tmp*b)+sin(tmp*b)*b*tmp - cos(tmp*a)-sin(tmp*a)*a*tmp) / (tmp * tmp);
 | 
|---|
 | 3782 |             integral.im = (sin(tmp*b)-cos(tmp*b)*b*tmp - sin(tmp*a)+cos(tmp*a)*a*tmp) / (tmp * tmp);
 | 
|---|
 | 3783 |             Psi2[g_bar].re += G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor; 
 | 
|---|
 | 3784 |             Psi2[g_bar].im += G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor;
 | 
|---|
 | 3785 |             //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))  
 | 
|---|
 | 3786 |               //fprintf(stderr,"(%i) Psi[%i].re += %e\tPsi[%i].im += %e \n",P->Par.me, g_bar, G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor, g_bar, G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor);
 | 
|---|
 | 3787 |           }
 | 
|---|
 | 3788 |         }
 | 
|---|
 | 3789 |       }
 | 
|---|
 | 3790 |     }
 | 
|---|
 | 3791 |   }
 | 
|---|
 | 3792 | 
 | 
|---|
 | 3793 |   // apply rxp
 | 
|---|
 | 3794 |   debug (P,"Applying RxP to test function.");
 | 
|---|
 | 3795 |   CalculatePerturbationOperator_RxP(P,Psi0,Psi3,k_normal,i);
 | 
|---|
 | 3796 | 
 | 
|---|
 | 3797 |   // compare both coefficient arrays
 | 
|---|
 | 3798 |   debug(P,"Beginning comparison of analytic and Rxp applied solution.");
 | 
|---|
 | 3799 |   for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
 | 3800 |     if ((fabs(Psi3[g].re-Psi2[g].re) >= MYEPSILON) || (fabs(Psi3[g].im-Psi2[g].im) >= MYEPSILON))
 | 
|---|
 | 3801 |       fprintf(stderr,"(%i) Psi3[%i] = %e +i %e != Psi2[%i] = %e +i %e\n",P->Par.me, g, Psi3[g].re, Psi3[g].im, g, Psi2[g].re, Psi2[g].im);
 | 
|---|
 | 3802 |     //else
 | 
|---|
 | 3803 |       //fprintf(stderr,"(%i) Psi1[%i] == Psi2[%i] = %e +i %e\n",P->Par.me, g, g, Psi1[g].re, Psi1[g].im);
 | 
|---|
 | 3804 |   }    
 | 
|---|
 | 3805 |   fprintf(stderr,"(%i) <0|1> = <0|r|0> == %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi3), GradImSP(P,LevS,Psi0,Psi3));
 | 
|---|
 | 3806 |   fprintf(stderr,"(%i) <1|1> = |r|ᅵ == %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi3,Psi3), GradImSP(P,LevS,Psi3,Psi3));
 | 
|---|
 | 3807 |   fprintf(stderr,"(%i) <0|0> = %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi0), GradImSP(P,LevS,Psi0,Psi0));
 | 
|---|
 | 3808 |   fprintf(stderr,"(%i) <0|2> = %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi2), GradImSP(P,LevS,Psi0,Psi2));
 | 
|---|
 | 3809 | }
 | 
|---|
 | 3810 | 
 | 
|---|
 | 3811 | 
 | 
|---|
 | 3812 | /** Output of a (X,Y,DX,DY) 2d-vector plot.
 | 
|---|
 | 3813 |  * For a printable representation of the induced current two-dimensional vector plots are useful, as three-dimensional
 | 
|---|
 | 3814 |  * isospheres are sometimes mis-leading or do not represent the desired flow direction. The routine simply extracts a
 | 
|---|
 | 3815 |  * two-dimensional cut orthogonal to one of the lattice axis at a certain node. 
 | 
|---|
 | 3816 |  * \param *P Problem at hand
 | 
|---|
 | 3817 |  * \param B_index direction of B field
 | 
|---|
 | 3818 |  * \param n_orth grid node in B_index direction of the plane (the order in which the remaining two coordinate axis
 | 
|---|
 | 3819 |  *        appear is the same as in a cross product, which is used to determine orthogonality)
 | 
|---|
 | 3820 |  */
 | 
|---|
 | 3821 | void PlotVectorPlane(struct Problem *P, int B_index, int n_orth)
 | 
|---|
 | 3822 | {
 | 
|---|
 | 3823 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 3824 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
 | 3825 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
 | 3826 |   char filename[255];
 | 
|---|
 | 3827 |   char *suchpointer;
 | 
|---|
 | 3828 |   FILE *PlotFile = NULL;
 | 
|---|
 | 3829 |   const int myPE = P->Par.me_comm_ST;
 | 
|---|
 | 3830 |   time_t seconds;  
 | 
|---|
 | 3831 |   fftw_real *CurrentDensity[NDIM*NDIM];
 | 
|---|
 | 3832 |   CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
 | 
|---|
 | 3833 |   CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
 | 
|---|
 | 3834 |   CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
 | 
|---|
 | 3835 |   CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
 | 
|---|
 | 3836 |   CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
 | 
|---|
 | 3837 |   CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
 | 
|---|
 | 3838 |   CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
 | 
|---|
 | 3839 |   CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
 | 
|---|
 | 3840 |   CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
 | 
|---|
 | 3841 |   time(&seconds); // get current time
 | 
|---|
 | 3842 | 
 | 
|---|
 | 3843 |   if (!myPE) { // only process 0 writes to file
 | 
|---|
 | 3844 |     // open file
 | 
|---|
 | 3845 |     sprintf(&filename[0], ".current.L%i.csv", Lev0->LevelNo);
 | 
|---|
 | 3846 |     OpenFile(P, &PlotFile, filename, "w", P->Call.out[ReadOut]);
 | 
|---|
 | 3847 |     strcpy(filename, ctime(&seconds));
 | 
|---|
 | 3848 |     suchpointer = strchr(filename, '\n');
 | 
|---|
 | 3849 |     if (suchpointer != NULL)
 | 
|---|
 | 3850 |       *suchpointer = '\0'; 
 | 
|---|
 | 3851 |     if (PlotFile != NULL) {      
 | 
|---|
 | 3852 |       fprintf(PlotFile,"# current vector plot of plane perpendicular to direction e_%i at node %i, seed %i, config %s, run on %s, #cpus %i", B_index, n_orth, R->Seed, P->Files.default_path, filename, P->Par.Max_me_comm_ST_Psi);
 | 
|---|
 | 3853 |       fprintf(PlotFile,"\n");
 | 
|---|
 | 3854 |     } else { Error(SomeError, "PlotVectorPlane: Opening Plot File"); }
 | 
|---|
 | 3855 |   }
 | 
|---|
 | 3856 | 
 | 
|---|
 | 3857 |   // plot density
 | 
|---|
 | 3858 |   if (!P->Par.me_comm_ST_PsiT) // only first wave function group as current density of all psis was gathered
 | 
|---|
 | 3859 |     PlotRealDensity(P, Lev0, PlotFile, B_index, n_orth, CurrentDensity[B_index*NDIM+cross(B_index,0)], CurrentDensity[B_index*NDIM+cross(B_index,1)]);
 | 
|---|
 | 3860 | 
 | 
|---|
 | 3861 |   if (PlotFile != NULL) {      
 | 
|---|
 | 3862 |     // close file
 | 
|---|
 | 3863 |     fclose(PlotFile);
 | 
|---|
 | 3864 |   }
 | 
|---|
 | 3865 | }
 | 
|---|
 | 3866 | 
 | 
|---|
 | 3867 | 
 | 
|---|
 | 3868 | /** Reads psi coefficients of \a type from file and transforms to new level.
 | 
|---|
 | 3869 |  * \param *P Problem at hand
 | 
|---|
 | 3870 |  * \param type PsiTypeTag of which minimisation group to load from file
 | 
|---|
 | 3871 |  * \sa ReadSrcPsiDensity() - reading the coefficients, ChangePsiAndDensToLevUp() - transformation to upper level
 | 
|---|
 | 3872 |  */
 | 
|---|
 | 3873 | void ReadSrcPerturbedPsis(struct Problem *P, enum PsiTypeTag type)
 | 
|---|
 | 3874 | {
 | 
|---|
 | 3875 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 3876 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
 | 3877 |   struct LatticeLevel *Lev0 = &P->Lat.Lev[R->Lev0No+1]; // one level higher than current (ChangeLevUp already occurred)
 | 
|---|
 | 3878 |   struct LatticeLevel *LevS = &P->Lat.Lev[R->LevSNo+1];
 | 
|---|
 | 3879 |   struct Density *Dens = Lev0->Dens;
 | 
|---|
 | 3880 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
 | 3881 |   struct fft_plan_3d *plan = Lat->plan; 
 | 
|---|
 | 3882 |   fftw_complex *work = (fftw_complex *)Dens->DensityCArray[TempDensity];
 | 
|---|
 | 3883 |   fftw_complex *tempdestRC = (fftw_complex *)Dens->DensityArray[TempDensity];
 | 
|---|
 | 3884 |   fftw_complex *posfac, *destpos, *destRCS, *destRCD;
 | 
|---|
 | 3885 |   fftw_complex *source, *source0;
 | 
|---|
 | 3886 |   int Index,i,pos;
 | 
|---|
 | 3887 |   double factorC = 1./Lev0->MaxN; 
 | 
|---|
 | 3888 |   int p,g;
 | 
|---|
 | 3889 |   
 | 
|---|
 | 3890 |   // ================= read coefficients from file to LocalPsi ============
 | 
|---|
 | 3891 |   ReadSrcPsiDensity(P, type, 0, R->LevSNo+1);
 | 
|---|
 | 3892 |   
 | 
|---|
 | 3893 |   // ================= transform to upper level ===========================
 | 
|---|
 | 3894 |   // for all local Psis do the usual transformation (completing coefficients for all grid vectors, fft, permutation)
 | 
|---|
 | 3895 |   LockDensityArray(Dens, TempDensity, real);
 | 
|---|
 | 3896 |   LockDensityArray(Dens, TempDensity, imag);
 | 
|---|
 | 3897 |   for (p=Psi->LocalNo-1; p >= 0; p--) 
 | 
|---|
 | 3898 |     if (Psi->LocalPsiStatus[p].PsiType == type) { // only for the desired type
 | 
|---|
 | 3899 |       source = LevS->LPsi->LocalPsi[p];
 | 
|---|
 | 3900 |       source0 = Lev0->LPsi->LocalPsi[p];
 | 
|---|
 | 3901 |       //fprintf(stderr,"(%i) ReadSrcPerturbedPsis: LevSNo %i\t Lev0No %i\tp %i\t source %p\t source0 %p\n", P->Par.me, LevS->LevelNo, Lev0->LevelNo, p, source, source0);
 | 
|---|
 | 3902 |       SetArrayToDouble0((double *)tempdestRC, Dens->TotalSize*2);
 | 
|---|
 | 3903 |       for (i=0;i<LevS->MaxG;i++) {
 | 
|---|
 | 3904 |         Index = LevS->GArray[i].Index;
 | 
|---|
 | 3905 |         posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
 | 3906 |         destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
 | 3907 |         //if (isnan(source[i].re)) { fprintf(stderr,"(%i) WARNING in ReadSrcPerturbedPsis(): source_%i[%i] = NaN!\n", P->Par.me, p, i); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
 | 3908 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 3909 |           destpos[pos].re = source[i].re*posfac[pos].re-source[i].im*posfac[pos].im;
 | 
|---|
 | 3910 |           destpos[pos].im = source[i].re*posfac[pos].im+source[i].im*posfac[pos].re;
 | 
|---|
 | 3911 |        }
 | 
|---|
 | 3912 |       }
 | 
|---|
 | 3913 |       for (i=0; i<LevS->MaxDoubleG; i++) {
 | 
|---|
 | 3914 |         destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
 | 
|---|
 | 3915 |         destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
 | 
|---|
 | 3916 |         for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
 | 3917 |           destRCD[pos].re =  destRCS[pos].re;
 | 
|---|
 | 3918 |           destRCD[pos].im = -destRCS[pos].im;
 | 
|---|
 | 3919 |         }
 | 
|---|
 | 3920 |       }  
 | 
|---|
 | 3921 |       fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
 | 
|---|
 | 3922 |       DensityRTransformPos(LevS,(fftw_real*)tempdestRC,(fftw_real *)Dens->DensityCArray[ActualPsiDensity]);
 | 
|---|
 | 3923 |       // now we have density in the upper level, fft back to complex and store it as wave function coefficients
 | 
|---|
 | 3924 |       fft_3d_real_to_complex(plan, Lev0->LevelNo, FFTNF1, Dens->DensityCArray[ActualPsiDensity], work);
 | 
|---|
 | 3925 |       for (g=0; g < Lev0->MaxG; g++) {
 | 
|---|
 | 3926 |         Index = Lev0->GArray[g].Index;
 | 
|---|
 | 3927 |         source0[g].re = Dens->DensityCArray[ActualPsiDensity][Index].re*factorC; 
 | 
|---|
 | 3928 |         source0[g].im = Dens->DensityCArray[ActualPsiDensity][Index].im*factorC; 
 | 
|---|
 | 3929 |         //if (isnan(source0[g].re)) { fprintf(stderr,"(%i) WARNING in ReadSrcPerturbedPsis(): source0_%i[%i] = NaN!\n", P->Par.me, p, g); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
 | 3930 |       }
 | 
|---|
 | 3931 |       if (Lev0->GArray[0].GSq == 0.0)
 | 
|---|
 | 3932 |         source0[g].im = 0.0;
 | 
|---|
 | 3933 |     }
 | 
|---|
 | 3934 |   UnLockDensityArray(Dens, TempDensity, real);
 | 
|---|
 | 3935 |   UnLockDensityArray(Dens, TempDensity, imag);
 | 
|---|
 | 3936 |   // finished.
 | 
|---|
 | 3937 | }
 | 
|---|