source: pcp/src/perturbed.c@ 88e890

Last change on this file since 88e890 was f5586e, checked in by Frederik Heber <heber@…>, 17 years ago

RealBasisQ[] removed

RealBasisQ[] is again replaced by sqrt(RealBasisSQ[]) as we are going to switch to a pure matrix transformation for calculating whether points are still within the periodic cell and so forth instead of "hoping" the simulation box is rectangular.

  • Property mode set to 100644
File size: 203.0 KB
Line 
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 */
76double 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 */
111double 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 */
142void 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 */
182void 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 */
255void 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 */
492int 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 */
527void 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 */
560void 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 */
623void 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 */
779void 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 */
917void 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 */
1155void 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 */
1187void 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 */
1401void 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 */
1466void 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 * sqrt(Lat->RealBasisSQ[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 * sqrt(Lat->RealBasisSQ[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 */
1605void 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 */
1724double 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 */
1808double 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 */
1847inline 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 */
1865inline 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 = length of unit cell derived from Lattice#RealBasisSQ) 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#RealBasisSQ
1893 * \param L parameter x
1894 * \param index component index for Lattice#RealBasisSQ
1895 */
1896inline double sawtooth(struct Lattice *Lat, double L, const int index)
1897{
1898 double axis = sqrt(Lat->RealBasisSQ[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 */
1926inline 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 */
1948void 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] * sqrt(Lat->RealBasisSQ[index]);
1962 //fprintf(stderr,"(%i) x %e\t Axis/2 %e\n",P->Par.me, x, sqrt(Lat->RealBasisSQ[index])/2. );
1963 x = MinImageConv(Lat, x, sqrt(Lat->RealBasisSQ[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 */
1976inline double MinImageConv(struct Lattice *Lat, const double R, const double r, const int index)
1977{
1978 double axis = sqrt(Lat->RealBasisSQ[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 */
1999void 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 */
2130void 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 */
2156void 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 */
2212void 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");
2316 if (!ParseForParameter(1,file,"Orbital",0,1,1,int_type,&wished, 1, optional)) {
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 */
2465struct 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 */
2479static 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 */
2514static 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 */
2552static 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 */
2593void 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 *)&param;
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++)
2884// if (x_l[i] != NULL) Free(x_l[i], "bla", "bla");
2885// Free(x_l, "bla");
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 */
2906void 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);
2962 Free(sendbuf, "bla");
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 }
2969 Free(recvbuf, "bla");
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 */
2983void 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]], sqrt(Lat->RealBasisSQ[cross_lookup[0]])/2.,cross_lookup[0]) * CurrentDensity[dex*NDIM+cross_lookup[1]][i0]; // x[cross(in,0)], sqrt(Lat->RealBasisSQ[cross_lookup[0]])/2.
3043 chi[in+dex*NDIM] -= MinImageConv(Lat,x[cross_lookup[2]], sqrt(Lat->RealBasisSQ[cross_lookup[2]])/2.,cross_lookup[2]) * CurrentDensity[dex*NDIM+cross_lookup[3]][i0]; // x[cross(in,2)], sqrt(Lat->RealBasisSQ[cross_lookup[2]])/2.
3044// if (in == dex) field[in][i0] =
3045// truedist(Lat,x[cross_lookup[0]], sqrt(Lat->RealBasisSQ[c[0]])/2.,cross_lookup[0]) * CurrentDensity[dex*NDIM+cross_lookup[1]][i0]
3046// - truedist(Lat,x[cross_lookup[2]], sqrt(Lat->RealBasisSQ[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]]*(sqrt(Lat->RealBasisSQ[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 */
3126void 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]/sqrt(Lat->RealBasisSQ[g])*(double)N[g]);
3238 n[1][g] = ceil(I->I[it].R[NDIM*ion+g]/sqrt(Lat->RealBasisSQ[g])*(double)N[g]);
3239 x[1][g] = I->I[it].R[NDIM*ion+g]/sqrt(Lat->RealBasisSQ[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 */
3390void 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 */
3560void 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 */
3706void 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, sqrt(Lat->RealBasisSQ[j]), Wcentre[j], j);
3747 b = sqrt(Lat->RealBasisSQ[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, sqrt(Lat->RealBasisSQ[j]), Wcentre[j], j);
3770 b = sqrt(Lat->RealBasisSQ[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 */
3821void 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 */
3873void 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}
Note: See TracBrowser for help on using the repository browser.