source: pcp/src/perturbed.c@ 307fd1

Last change on this file since 307fd1 was 2f6ae6, checked in by Frederik Heber <heber@…>, 17 years ago

CalculateChemicalShieldingByReciprocalCurrentDensity(): .sigma_all_PAS.csv is written with highest values for all ions (used for BOSSANOVA reconstruction)

The setup of the file is similar to pcp.forces.csv, hence joiner may be used in the same way.

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