source: pcp/src/perturbed.c@ 58ab18

Last change on this file since 58ab18 was c76393, checked in by Frederik Heber <heber@…>, 17 years ago

lots of changes only with regard to output of sigma, chi and moments

Basically, we just differentiate between ValueOut and ReadOut. This first only prints the interesting values without the rest of the PAS stuff

  • Property mode set to 100644
File size: 220.0 KB
Line 
1/** \file perturbed.c
2 * Perturbation calculation due to external magnetic field.
3 *
4 * Central function is MinimisePerturbed() wherein the actual minimisation of the two different operators with each
5 * three components takes place subsequently. Helpful routines are CalculatePerturbationOperator_P() - which applies a
6 * specified component of p on the current wave function - and CalculatePerturbationOperator_RxP() - which does the
7 * same for the RxP operator.
8 * The actual minimisation loop FindPerturbedMinimum() depends on the same routines also used for the occupied orbitals,
9 * however with a different energy functional and derivatives, evaluated in Calculate1stPerturbedDerivative() and
10 * Calculate2ndPerturbedDerivative(). InitPerturbedEnergyCalculation() calculates the total energy functional
11 * perturbed in second order for all wave functions, UpdatePerturbedEnergyCalculation() just updates the one
12 * for the wave function after it has been minimised during the line search. Both use CalculatePerturbedEnergy() which
13 * evaluates the energy functional (and the gradient if specified).
14 * Finally, FillCurrentDensity() evaluates the current density at a given point in space using the perturbed
15 * wave functions. Afterwards by calling CalculateMagneticSusceptibility() or
16 * CalculateChemicalShieldingByReciprocalCurrentDensity() susceptibility respectively shielding tensor are possible uses
17 * of this current density.
18 *
19 * There are also some test routines: TestCurrent() checks whether the integrated current is zero in each component.
20 * test_fft_symmetry() tests the "pulling out imaginary unit" before fourier transformation on a given wave function.
21 * CheckOrbitalOverlap() outputs the overlap matrix for the wave functions of a given minimisation state, this might
22 * be important for the additional \f$\Delta J{ij}\f$ contribution to the current density, which is non-zero for
23 * non-zero mutual overlap, which is evaluated if FillDeltaCurrentDensity() is called.
24 *
25 * Finally, there are also some smaller routines: truedist() gives the correct relative distance between two points
26 * in the unit cell under periodic boundary conditions with minimum image convention. ApplyTotalHamiltonian() returns
27 * the hamiltonian applied to a given wave function. sawtooth() is a sawtooth implementation which is needed in order
28 * to avoid flipping of position eigenvalues for nodes close to or on the cell boundary. CalculateOverlap()
29 * is used in the energy functional derivatives, keeping an overlap table between perturbed wave functions up to date.
30 * fft_Psi() is very similar to CalculateOneDensityR(), it does the extension of the wave function to the upper level
31 * RunStruct#Lev0 while fouriertransforming it to real space. cross() gives correct indices in evaluating a vector cross
32 * product. AllocCurrentDensity() and DisAllocCurrentDensity() mark the current density arrays as currently being in use or not.
33 *
34 Project: ParallelCarParrinello
35 \author Frederik Heber
36 \date 2006
37
38*/
39
40#include <stdlib.h>
41#include <stdio.h>
42#include <math.h>
43#include <string.h>
44#include <time.h>
45#include <gsl/gsl_matrix.h>
46#include <gsl/gsl_eigen.h>
47#include <gsl/gsl_complex.h>
48#include <gsl/gsl_complex_math.h>
49#include <gsl/gsl_sort_vector.h>
50#include <gsl/gsl_linalg.h>
51#include <gsl/gsl_multimin.h>
52
53#include "data.h"
54#include "density.h"
55#include "energy.h"
56#include "excor.h"
57#include "errors.h"
58#include "grad.h"
59#include "gramsch.h"
60#include "mergesort2.h"
61#include "helpers.h"
62#include "init.h"
63#include "myfft.h"
64#include "mymath.h"
65#include "output.h"
66#include "pcp.h"
67#include "perturbed.h"
68#include "run.h"
69#include "wannier.h"
70
71
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.L%i.csv", Lev0->LevelNo);
2986 OpenFile(P, &ChiFile, suffixchi, "a", P->Call.out[ReadOut]);
2987 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));
2988 fprintf(ChiFile,"%lg\t", Lev0->ECut/4.); // ECut is in Rydberg
2989 for (in=0;in<NDIM*NDIM;in++)
2990 fprintf(ChiFile,"%e\t", Chi[in]);
2991 fprintf(ChiFile,"\n");
2992 fclose(ChiFile);
2993 }
2994 // diagonalize chi
2995 gsl_vector *eval = gsl_vector_alloc(NDIM);
2996 gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
2997 gsl_eigen_herm(H, eval, w);
2998 gsl_eigen_herm_free(w);
2999 gsl_sort_vector(eval); // sort eigenvalues
3000 // print eigenvalues
3001 iso = 0;
3002 for (i=0;i<NDIM;i++) {
3003 I->I[0].chi_PAS[i] = gsl_vector_get(eval,i);
3004 iso += Chi[i+i*NDIM]/3.;
3005 }
3006 eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
3007 delta_chi = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
3008 S = (delta_chi*delta_chi)*(1+1./3.*eta*eta);
3009 A = 0.;
3010 for (i=0;i<NDIM;i++) {
3011 in = cross(i,0);
3012 dex = cross(i,1);
3013 A += pow(-1,i)*pow(0.5*(Chi[in+dex*NDIM]-Chi[dex+in*NDIM]),2);
3014 }
3015 if (P->Call.out[ReadOut]) {
3016 fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
3017 for (i=0;i<NDIM;i++)
3018 fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
3019 }
3020 if (P->Call.out[ValueOut]) {
3021 if (P->Call.out[ReadOut])
3022 fprintf(stderr,"\nsusceptib. : %e\n", iso);
3023 else
3024 fprintf(stderr,"%e\n", iso);
3025 }
3026 if (P->Call.out[ReadOut]) {
3027 fprintf(stderr,"anisotropy : %e\n", delta_chi);
3028 fprintf(stderr,"asymmetry : %e\n", eta);
3029 fprintf(stderr,"S : %e\n", S);
3030 fprintf(stderr,"A : %e\n", A);
3031 fprintf(stderr,"==================\n");
3032 }
3033 // output PAS tensor to file
3034 if (P->Par.me == 0) {
3035 time(&seconds); // get current time
3036 sprintf(&suffixchi[0], ".chi_PAS.csv");
3037 if (Lev0->LevelNo == Lat->MaxLevel-2) {
3038 OpenFile(P, &ChiFile, suffixchi, "w", P->Call.out[ReadOut]);
3039 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));
3040 fprintf(ChiFile,"# Ecut\tChi_XX\t\tChi_YY\t\tChi_ZZ\tShielding\tanisotropy\tasymmetry\tS\t\tA\n");
3041 } else
3042 OpenFile(P, &ChiFile, suffixchi, "a", P->Call.out[ReadOut]);
3043 fprintf(ChiFile,"%lg\t", Lev0->ECut/4.); // ECut is in Rydberg
3044 for (i=0;i<NDIM;i++)
3045 fprintf(ChiFile,"%e\t", gsl_vector_get(eval,i));
3046 fprintf(ChiFile,"%lg\t%lg\t%lg\t%lg\t%lg\t\n", iso, delta_chi, eta, S, A);
3047 fclose(ChiFile);
3048 }
3049 //for(i=0;i<NDIM;i++)
3050 //UnLockDensityArray(Dens0,TempDensity+i,real);
3051 gsl_vector_free(eval);
3052 gsl_matrix_complex_free(H);
3053 Free(suffixchi, "CalculateMagneticSusceptibility: *suffixchi");
3054}
3055
3056/** Fouriertransforms all nine current density components and calculates shielding tensor.
3057 * \f[
3058 * \sigma_{ij} = \left ( \frac{G}{|G|^2} \times J_i(G) \right )_j
3059 * \f]
3060 * The CurrentDensity has to be fouriertransformed to reciprocal subspace in order to be useful, and the final
3061 * product \f$\sigma_{ij}(G)\f$ has to be back-transformed to real space. However, the shielding is the only evaluated
3062 * at the grid points and not where the real ion position is. The shieldings there are interpolated between the eight
3063 * adjacent grid points by a simple linear weighting. Afterwards follows the same analaysis and printout of the rank-2-tensor
3064 * as in the case of CalculateMagneticShielding().
3065 * \param *P Problem at hand
3066 * \note Lots of arrays are used temporarily during the routine for the fft'ed Current density tensor.
3067 * \note MagneticSusceptibility is needed for G=0-component and thus has to be computed beforehand
3068 */
3069void CalculateChemicalShieldingByReciprocalCurrentDensity(struct Problem *P)
3070{
3071 struct RunStruct *R = &P->R;
3072 struct Lattice *Lat = &P->Lat;
3073 struct LatticeLevel *Lev0 = R->Lev0;
3074 struct FileData *F = &P->Files;
3075 struct Ions *I = &P->Ion;
3076 struct Density *Dens0 = Lev0->Dens;
3077 struct OneGData *GArray = Lev0->GArray;
3078 struct fft_plan_3d *plan = Lat->plan;
3079 fftw_real *CurrentDensity[NDIM*NDIM];
3080 fftw_complex *CurrentDensityC[NDIM*NDIM];
3081 fftw_complex *work = (fftw_complex *)Dens0->DensityCArray[TempDensity];
3082 //fftw_complex *sigma_imag = (fftw_complex *)Dens0->DensityCArray[Temp2Density];
3083 //fftw_real *sigma_real = (fftw_real *)sigma_imag;
3084 fftw_complex *sigma_imag[NDIM_NDIM];
3085 fftw_real *sigma_real[NDIM_NDIM];
3086 double sigma,Sigma;
3087 double x[NDIM];
3088 int it, g, ion, in, dex, Index, i, j, d;
3089 int n[NDIM];
3090 int *N = Lev0->Plan0.plan->N;
3091 //const double FFTfactor = 1.;///Lev0->MaxN;
3092 double eta, delta_sigma, S, A, iso;
3093 int cross_lookup[4]; // cross lookup table
3094 const double factorDC = R->FactorDensityC;
3095 gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
3096 FILE *SigmaFile;
3097 char *suffixsigma = (char *) Malloc(sizeof(char)*255, "CalculateChemicalShieldingByReciprocalCurrentDensity: *suffixsigma");
3098
3099 time_t seconds;
3100 time(&seconds); // get current time
3101
3102 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i)Calculating Chemical Shielding\n", P->Par.me);
3103
3104 // inverse Fourier transform current densities
3105 CurrentDensityC[0] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity0];
3106 CurrentDensityC[1] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity1];
3107 CurrentDensityC[2] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity2];
3108 CurrentDensityC[3] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity3];
3109 CurrentDensityC[4] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity4];
3110 CurrentDensityC[5] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity5];
3111 CurrentDensityC[6] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity6];
3112 CurrentDensityC[7] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity7];
3113 CurrentDensityC[8] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity8];
3114 // don't put the following stuff into a for loop, they are not continuous! (preprocessor values CurrentDensity.)
3115 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
3116 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
3117 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
3118 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
3119 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
3120 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
3121 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
3122 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
3123 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
3124
3125 // inverse Fourier transform current densities
3126 if (P->Call.out[LeaderOut]) fprintf(stderr,"(%i) Transforming and checking J_{ij} (G=0) = 0 for each i,j ... \n",P->Par.me);
3127 for (in=0;in<NDIM*NDIM;in++) {
3128 CalculateOneDensityC(Lat, R->LevS, Dens0, CurrentDensity[in], CurrentDensityC[in], factorDC);
3129 //TestReciprocalCurrent(P, CurrentDensityC[in], GArray, in);
3130 }
3131
3132 // linking pointers to the arrays
3133 for (in=0;in<NDIM*NDIM;in++) {
3134 LockDensityArray(Dens0,in,real); // Psi1R
3135 sigma_imag[in] = (fftw_complex *) Dens0->DensityArray[in];
3136 sigma_real[in] = (fftw_real *) sigma_imag[in];
3137 }
3138
3139 LockDensityArray(Dens0,TempDensity,imag); // work
3140 LockDensityArray(Dens0,Temp2Density,imag); // tempdestRC and field
3141 // go through reciprocal nodes and calculate shielding tensor sigma
3142 for (in=0; in<NDIM; in++) {// index i of vector component in integrand
3143 for(dex=0;dex<4;dex++) // initialise cross lookup
3144 cross_lookup[dex] = cross(in,dex);
3145 for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
3146 //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
3147 SetArrayToDouble0((double *)sigma_imag[in+dex*NDIM],Dens0->TotalSize*2);
3148 for (g=0; g < Lev0->MaxG; g++)
3149 if (GArray[g].GSq > MYEPSILON) { // skip due to divisor
3150 Index = GArray[g].Index; // re = im, im = -re due to "i" in formula
3151 //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density] || Index<0 || Index>=Dens0->LocalSizeC) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
3152 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;
3153 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;
3154 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;
3155 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;
3156 } else { // divergent G=0-component stems from magnetic susceptibility
3157 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]);
3158 }
3159 for (g=0; g<Lev0->MaxDoubleG; g++) { // apply symmetry
3160 //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");
3161 sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g+1]].re = sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g]].re;
3162 sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g+1]].im = -sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g]].im;
3163 }
3164 // fourier transformation of sigma
3165 //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
3166 fft_3d_complex_to_real(plan, Lev0->LevelNo, FFTNF1, sigma_imag[in+dex*NDIM], work);
3167
3168 for (it=0; it < I->Max_Types; it++) { // integration over all types
3169 for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
3170 // read transformed sigma at core position and MPI_Allreduce
3171 sigma = -LinearInterpolationBetweenGrid(P, Lat, Lev0, &I->I[it].R[NDIM*ion], sigma_real[in+dex*NDIM]) * R->FactorDensityR; // factor from inverse fft
3172
3173 MPI_Allreduce ( &sigma, &Sigma, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum local to total
3174 I->I[it].sigma_rezi[ion][in+dex*NDIM] = Sigma;
3175 }
3176 }
3177 }
3178 }
3179 UnLockDensityArray(Dens0,TempDensity,imag); // work
3180 UnLockDensityArray(Dens0,Temp2Density,imag); // tempdestRC and field
3181
3182 // output tensor to file
3183 if (P->Par.me == 0) {
3184 sprintf(suffixsigma, ".sigma_chi_rezi.L%i.csv", Lev0->LevelNo);
3185 OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
3186 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));
3187 fprintf(SigmaFile,"%lg\t", Lev0->ECut/4.);
3188 for (in=0;in<NDIM;in++)
3189 for (dex=0;dex<NDIM;dex++)
3190 fprintf(SigmaFile,"%e\t", GSL_REAL(gsl_matrix_complex_get(H,in,dex)));
3191 fprintf(SigmaFile,"\n");
3192 fclose(SigmaFile);
3193 }
3194
3195 gsl_vector *eval = gsl_vector_alloc(NDIM);
3196 gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
3197
3198 for (it=0; it < I->Max_Types; it++) { // integration over all types
3199 for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
3200 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);
3201 if (P->Call.out[ReadOut]) fprintf(stderr,"\n");
3202 for (in=0; in<NDIM; in++) { // index i of vector component in integrand
3203 for (dex=0; dex<NDIM; dex++) {// index j of B component derivation in current density tensor
3204 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));
3205 if (P->Call.out[ReadOut]) fprintf(stderr,"%e\t", I->I[it].sigma_rezi[ion][in+dex*NDIM]);
3206 }
3207 if (P->Call.out[ReadOut]) fprintf(stderr,"\n");
3208 }
3209 // output tensor to file
3210 if (P->Par.me == 0) {
3211 sprintf(suffixsigma, ".sigma_i%i_%s_rezi.L%i.csv", ion, I->I[it].Symbol, Lev0->LevelNo);
3212 OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
3213 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));
3214 fprintf(SigmaFile,"%lg\t", Lev0->ECut/4.); // ECut is in Rydberg
3215 for (in=0;in<NDIM;in++)
3216 for (dex=0;dex<NDIM;dex++)
3217 fprintf(SigmaFile,"%e\t", I->I[it].sigma_rezi[ion][in+dex*NDIM]);
3218 fprintf(SigmaFile,"\n");
3219 fclose(SigmaFile);
3220 }
3221 // diagonalize sigma
3222 gsl_eigen_herm(H, eval, w);
3223 gsl_sort_vector(eval); // sort eigenvalues
3224// print eigenvalues
3225// if (P->Call.out[ValueOut]) {
3226// fprintf(stderr,"(%i) diagonal shielding for Ion %i of element %s:", P->Par.me, ion, I->I[it].Name);
3227// for (in=0;in<NDIM;in++)
3228// fprintf(stderr,"\t%lg",gsl_vector_get(eval,in));
3229// fprintf(stderr,"\n\n");
3230// }
3231 iso = 0.;
3232 for (i=0;i<NDIM;i++) {
3233 I->I[it].sigma_rezi_PAS[ion][i] = gsl_vector_get(eval,i);
3234 iso += I->I[it].sigma_rezi[ion][i+i*NDIM]/3.;
3235 }
3236 eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
3237 delta_sigma = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
3238 S = (delta_sigma*delta_sigma)*(1+1./3.*eta*eta);
3239 A = 0.;
3240 for (i=0;i<NDIM;i++) {
3241 in = cross(i,0);
3242 dex = cross(i,1);
3243 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);
3244 }
3245 if (P->Call.out[ReadOut]) {
3246 fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
3247 for (i=0;i<NDIM;i++)
3248 fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
3249 }
3250 if (P->Call.out[ValueOut]) {
3251 if (P->Call.out[ReadOut])
3252 fprintf(stderr,"\nshielding : %e\n", iso);
3253 else
3254 fprintf(stderr,"%e\n", iso);
3255 }
3256 if (P->Call.out[ReadOut]) {
3257 fprintf(stderr,"anisotropy : %e\n", delta_sigma);
3258 fprintf(stderr,"asymmetry : %e\n", eta);
3259 fprintf(stderr,"S : %e\n", S);
3260 fprintf(stderr,"A : %e\n", A);
3261 fprintf(stderr,"==================\n");
3262 }
3263 if (P->Par.me == 0) {
3264 sprintf(suffixsigma, ".sigma_i%i_%s_PAS.csv", ion, I->I[it].Symbol);
3265 if (Lev0->LevelNo == Lat->MaxLevel-2) {
3266 OpenFile(P, &SigmaFile, suffixsigma, "w", P->Call.out[ReadOut]);
3267 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));
3268 fprintf(SigmaFile,"# Ecut\tSigma_XX\tSigma_YY\tSigma_ZZ\tShielding\tanisotropy\tasymmetry\tS\t\tA\n");
3269 } else
3270 OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
3271 fprintf(SigmaFile,"%lg\t", Lev0->ECut/4.); // ECut is in Rydberg
3272 for (i=0;i<NDIM;i++)
3273 fprintf(SigmaFile,"%lg\t", gsl_vector_get(eval,i));
3274 fprintf(SigmaFile,"%lg\t%lg\t%lg\t%lg\t%lg\t\n", iso, delta_sigma, eta, S, A);
3275 fclose(SigmaFile);
3276 }
3277 }
3278 }
3279
3280 if (R->MaxOuterStep > 0) { // if we do MD, calculate magnetic force with undiagonalised B fields
3281 for (it=0; it < I->Max_Types; it++) { // integration over all types
3282 for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
3283 // Finally use the magnetic moment in order to calculate the magnetic force
3284 RMat33Vec3(x, Lat->ReciBasis, &(I->I[it].R[NDIM*ion]));
3285 for (d=0;d<NDIM;d++)
3286 n[d] = (int)(x[d]/(2.*PI)*(double)N[d]); // round to next nearest mesh point
3287// n[d] = (int)(I->I[it].R[NDIM*ion+d]/Lat->RealBasisQ[d]*(double)N[d]);
3288 for (d=0;d<NDIM;d++) { // index of induced magnetic field
3289 I->I[it].FMagnetic[d+ion*NDIM] = 0.;
3290 for (j=0;j<NDIM;j++) {// we to sum over all external field components
3291 //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);
3292 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];
3293 }
3294 }
3295 }
3296 }
3297 }
3298
3299 // fabs() all sigma values, as we need them as a positive density: OutputVis plots them in logarithmic scale and
3300 // thus cannot deal with negative values!
3301 for (in=0; in<NDIM; in++) {// index i of vector component in integrand
3302 for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
3303 for (i=0; i< Dens0->LocalSizeR; i++)
3304 sigma_real[in+dex*NDIM][i] = fabs(sigma_real[in+dex*NDIM][i]);
3305 }
3306 }
3307 if (Lev0->LevelNo == 0) {
3308 if (!P->Par.me && P->Call.out[NormalOut]) fprintf(stderr,"(%i)Output of NICS map ...\n", P->Par.me);
3309 // Output of magnetic field densities for each direction
3310 //for (i=0;i<NDIM*NDIM;i++)
3311 // OutputVis(P, sigma_real[i]);
3312 // Diagonalizing the tensor "field" B_ij [r]
3313 if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) Diagonalizing B_ij [r] ... \n", P->Par.me);
3314 for (i=0; i< Dens0->LocalSizeR; i++) {
3315 for (in=0; in<NDIM; in++) // index i of vector component in integrand
3316 for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
3317 //fprintf(stderr,"(%i) Setting B_(%i,%i)[%i] ... \n", P->Par.me, in,dex,i);
3318 gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((sigma_real[in+dex*NDIM][i]+sigma_real[dex+in*NDIM][i])/2.,0.));
3319 }
3320 gsl_eigen_herm(H, eval, w);
3321 gsl_sort_vector(eval); // sort eigenvalues
3322 for (in=0;in<NDIM;in++)
3323 sigma_real[in][i] = gsl_vector_get(eval,in);
3324 }
3325 }
3326
3327 // now absolute the B values (as density scales them by log) and output
3328 if (F->DoOutNICS) {
3329 for (i=0; i< Dens0->LocalSizeR; i++)
3330 for (in=0;in<NDIM;in++)
3331 sigma_real[in][i] = fabs(sigma_real[in][i]);
3332 // Output of diagonalized magnetic field densities for each direction
3333 for (i=0;i<NDIM;i++)
3334 OutputVis(P, sigma_real[i]);
3335 }
3336 for (i=0;i<NDIM*NDIM;i++)
3337 UnLockDensityArray(Dens0,i,real); // sigma_imag/real free
3338
3339 gsl_eigen_herm_free(w);
3340 gsl_vector_free(eval);
3341 gsl_matrix_complex_free(H);
3342 Free(suffixsigma, "CalculateChemicalShieldingByReciprocalCurrentDensity: *suffixsigma");
3343}
3344
3345
3346/** Calculates the magnetic moment at the positions of the nuclei.
3347 * The magnetic moment at position R is defined as
3348 * \f[
3349 * m_{ij} (R) = \frac{1}{2} \int d^3 r' \left ( (r'-R) \times J_i (r') \right )_j
3350 * \f]
3351 * One after another for each nuclear position is the tensor evaluated and the result printed
3352 * to screen. Tensor is diagonalized afterwards.
3353 * \param *P Problem at hand
3354 * \sa CalculateMagneticSusceptibility() - similar calculation, yet without translation to ion centers.
3355 */
3356void CalculateMagneticMoment(struct Problem *P)
3357{
3358 struct RunStruct *R = &P->R;
3359 struct Lattice *Lat = &P->Lat;
3360 struct LatticeLevel *Lev0 = R->Lev0;
3361 struct Density *Dens0 = R->Lev0->Dens;
3362 struct Ions *I = &P->Ion;
3363 double moment[NDIM*NDIM],Moment[NDIM*NDIM];
3364 fftw_real *CurrentDensity[NDIM*NDIM];
3365 int it, ion, in, dex, i0, n[NDIM], n0, i;//, *NUp;
3366 double r[NDIM], fac[NDIM], X[NDIM];
3367 const double discrete_factor = Lat->Volume/Lev0->MaxN;
3368 double eta, delta_moment, S, A, iso;
3369 const int myPE = P->Par.me_comm_ST_Psi;
3370 int *N = Lev0->Plan0.plan->N;
3371 const int N0 = Lev0->Plan0.plan->local_nx;
3372 FILE *MomentFile;
3373 char *suffixmoment = (char *) Malloc(sizeof(char)*255, "CalculateMagneticMoment: *suffixmoment");
3374 time_t seconds;
3375 time(&seconds); // get current time
3376
3377 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Integrating current density to evaluate magnetic moment\n", P->Par.me);
3378
3379 // set pointers onto current density
3380 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
3381 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
3382 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
3383 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
3384 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
3385 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
3386 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
3387 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
3388 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
3389 gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
3390
3391 for (it=0; it < I->Max_Types; it++) { // integration over all types
3392 for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
3393 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);
3394 if (P->Call.out[ReadOut]) fprintf(stderr,"\n");
3395 for (in=0; in<NDIM; in++) {// index i of vector component in integrand
3396 for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
3397 moment[in+dex*NDIM] = 0.;
3398
3399 for(n0=0;n0<N0;n0++) // do the integration over real space
3400 for(n[1]=0;n[1]<N[1];n[1]++)
3401 for(n[2]=0;n[2]<N[2];n[2]++) {
3402 n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
3403 fac[0] = (double)n[0]/(double)N[0];
3404 fac[1] = (double)n[1]/(double)N[1];
3405 fac[2] = (double)n[2]/(double)N[2];
3406 RMat33Vec3(r, Lat->RealBasis, fac);
3407 MinImageConv(Lat,r, &(I->I[it].R[NDIM*ion]),X);
3408 i0 = n[2]+N[2]*(n[1]+N[1]*(n0)); // the index of current density must match LocalSizeR!
3409 //z = MinImageConv(Lat,r, I->I[it].R[NDIM*ion],in); // "in" always is missing third component in cross product
3410 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]);
3411 //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]);
3412 }
3413 //moment[in+dex*NDIM] *= -mu0*discrete_factor/(4.*PI); // due to summation instead of integration
3414 moment[in+dex*NDIM] *= 1./2.*discrete_factor; // due to summation instead of integration
3415 MPI_Allreduce ( &moment[in+dex*NDIM], &Moment[in+dex*NDIM], 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3416 I->I[it].moment[ion][in+dex*NDIM] = Moment[in+dex*NDIM];
3417 if (P->Call.out[ReadOut]) fprintf(stderr," %e", Moment[in+dex*NDIM]);
3418 }
3419 if (P->Call.out[ReadOut]) fprintf(stderr,"\n");
3420 }
3421 // store symmetrized matrix
3422 for (in=0;in<NDIM;in++)
3423 for (dex=0;dex<NDIM;dex++)
3424 gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((Moment[in+dex*NDIM]+Moment[dex+in*NDIM])/2.,0));
3425 // output tensor to file
3426 if (P->Par.me == 0) {
3427 sprintf(&suffixmoment[0], ".moment_i%i_%s.L%i.csv", ion, I->I[it].Symbol, Lev0->LevelNo);
3428 OpenFile(P, &MomentFile, suffixmoment, "a", P->Call.out[ReadOut]);
3429 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));
3430 fprintf(MomentFile,"%lg\t", Lev0->ECut/4.); // ECut is in Rydberg
3431 for (in=0;in<NDIM*NDIM;in++)
3432 fprintf(MomentFile,"%e\t", Moment[in]);
3433 fprintf(MomentFile,"\n");
3434 fclose(MomentFile);
3435 }
3436 // diagonalize moment
3437 gsl_vector *eval = gsl_vector_alloc(NDIM);
3438 gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
3439 gsl_eigen_herm(H, eval, w);
3440 gsl_eigen_herm_free(w);
3441 gsl_sort_vector(eval); // sort eigenvalues
3442 // print eigenvalues
3443// if (P->Call.out[ValueOut]) {
3444// fprintf(stderr,"(%i) diagonal shielding for Ion %i of element %s:", P->Par.me, ion, I->I[it].Name);
3445// for (in=0;in<NDIM;in++)
3446// fprintf(stderr,"\t%lg",gsl_vector_get(eval,in));
3447// fprintf(stderr,"\n\n");
3448// }
3449 // print eigenvalues
3450 iso = 0;
3451 for (i=0;i<NDIM;i++) {
3452 I->I[it].moment[ion][i] = gsl_vector_get(eval,i);
3453 iso += Moment[i+i*NDIM]/3.;
3454 }
3455 eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
3456 delta_moment = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
3457 S = (delta_moment*delta_moment)*(1+1./3.*eta*eta);
3458 A = 0.;
3459 for (i=0;i<NDIM;i++) {
3460 in = cross(i,0);
3461 dex = cross(i,1);
3462 A += pow(-1,i)*pow(0.5*(Moment[in+dex*NDIM]-Moment[dex+in*NDIM]),2);
3463 }
3464 if (P->Call.out[ReadOut]) {
3465 fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
3466 for (i=0;i<NDIM;i++)
3467 fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
3468 }
3469 if (P->Call.out[ValueOut]) {
3470 if (P->Call.out[ReadOut])
3471 fprintf(stderr,"moment : %e\n", iso);
3472 else
3473 fprintf(stderr,"%e\n", iso);
3474 }
3475 if (P->Call.out[ReadOut]) {
3476 fprintf(stderr,"anisotropy : %e\n", delta_moment);
3477 fprintf(stderr,"asymmetry : %e\n", eta);
3478 fprintf(stderr,"S : %e\n", S);
3479 fprintf(stderr,"A : %e\n", A);
3480 fprintf(stderr,"==================\n");
3481 }
3482 gsl_vector_free(eval);
3483 }
3484 }
3485
3486 gsl_matrix_complex_free(H);
3487 Free(suffixmoment, "CalculateMagneticMoment: *suffixmoment");
3488}
3489
3490/** Test if G=0-component of reciprocal current is 0.
3491 * In most cases we do not reach a numerical sensible zero as in MYEPSILON and remain satisfied as long
3492 * as the integrated current density is very small (e.g. compared to single entries in the current density array)
3493 * \param *P Problem at hand
3494 * \param *CurrentC pointer to reciprocal current density
3495 * \param *GArray pointer to array with G vectors
3496 * \param in index of current component
3497 * \sa TestCurrent() these two tests are equivalent and follow by fourier transformation
3498 */
3499void TestReciprocalCurrent(struct Problem *P, const fftw_complex *CurrentC, struct OneGData *GArray, int in)
3500{
3501 double tmp;
3502 tmp = sqrt(CurrentC[0].re*CurrentC[0].re+CurrentC[0].im*CurrentC[0].im);
3503 if ((P->Call.out[LeaderOut]) && (GArray[0].GSq < MYEPSILON)) {
3504 if (in % NDIM == 0) fprintf(stderr,"(%i) ",P->Par.me);
3505 if (tmp > MYEPSILON) {
3506 fprintf(stderr,"J_{%i,%i} = |%e + i%e| < %e ? (%e)\t", in / NDIM, in%NDIM, CurrentC[0].re, CurrentC[0].im, MYEPSILON, tmp - MYEPSILON);
3507 } else {
3508 fprintf(stderr,"J_{%i,%i} ok\t", in / NDIM, in%NDIM);
3509 }
3510 if (in % NDIM == (NDIM-1)) fprintf(stderr,"\n");
3511 }
3512}
3513
3514/** Test if integrated current over cell is 0.
3515 * In most cases we do not reach a numerical sensible zero as in MYEPSILON and remain satisfied as long
3516 * as the integrated current density is very small (e.g. compared to single entries in the current density array)
3517 * \param *P Problem at hand
3518 * \param index index of current component
3519 * \sa CalculateNativeIntDens() for integration of one current tensor component
3520 */
3521 void TestCurrent(struct Problem *P, const int index)
3522{
3523 struct RunStruct *R = &P->R;
3524 struct LatticeLevel *Lev0 = R->Lev0;
3525 struct Density *Dens0 = Lev0->Dens;
3526 fftw_real *CurrentDensity[NDIM*NDIM];
3527 int in;
3528 double result[NDIM*NDIM], res = 0.;
3529
3530 // set pointers onto current density array and get number of grid points in each direction
3531 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
3532 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
3533 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
3534 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
3535 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
3536 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
3537 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
3538 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
3539 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
3540 for(in=0;in<NDIM;in++) {
3541 result[in] = CalculateNativeIntDens(P,Lev0,CurrentDensity[in + NDIM*index],R->FactorDensityR);
3542 res += pow(result[in],2.);
3543 }
3544 res = sqrt(res);
3545 // if greater than 0, complain about it
3546 if ((res > MYEPSILON) && (P->Call.out[LeaderOut]))
3547 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);
3548}
3549
3550/** Testing whether re<->im switches (due to symmetry) confuses fft.
3551 * \param *P Problem at hand
3552 * \param l local wave function number
3553 */
3554void test_fft_symmetry(struct Problem *P, const int l)
3555{
3556 struct Lattice *Lat = &P->Lat;
3557 struct RunStruct *R = &P->R;
3558 struct LatticeLevel *LevS = R->LevS;
3559 struct LatticeLevel *Lev0 = R->Lev0;
3560 struct Density *Dens0 = Lev0->Dens;
3561 struct fft_plan_3d *plan = Lat->plan;
3562 fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityCArray[Temp2Density];
3563 fftw_complex *work = Dens0->DensityCArray[TempDensity];
3564 fftw_complex *workC = (fftw_complex *)Dens0->DensityArray[TempDensity];
3565 fftw_complex *posfac, *destpos, *destRCS, *destRCD;
3566 fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
3567 fftw_real *PsiCR = (fftw_real *) PsiC;
3568 fftw_complex *Psi0 = LevS->LPsi->LocalPsi[l];
3569 fftw_complex *dest = LevS->LPsi->TempPsi;
3570 fftw_real *Psi0R = (fftw_real *)Dens0->DensityArray[Temp2Density];
3571 int i,Index, pos, i0, iS,g; //, NoOfPsis = Psi->TypeStartIndex[UnOccupied] - Psi->TypeStartIndex[Occupied];
3572 int n[NDIM], n0;
3573 const int N0 = LevS->Plan0.plan->local_nx; // we don't want to build global density, but local
3574 int N[NDIM], NUp[NDIM];
3575 N[0] = LevS->Plan0.plan->N[0];
3576 N[1] = LevS->Plan0.plan->N[1];
3577 N[2] = LevS->Plan0.plan->N[2];
3578 NUp[0] = LevS->NUp[0];
3579 NUp[1] = LevS->NUp[1];
3580 NUp[2] = LevS->NUp[2];
3581 //const int k_normal = Lat->Psi.TypeStartIndex[Occupied] + (l - Lat->Psi.TypeStartIndex[R->CurrentMin]);
3582 //const double *Wcentre = Lat->Psi.AddData[k_normal].WannierCentre;
3583 //double x[NDIM], fac[NDIM];
3584 double result1=0., result2=0., result3=0., result4=0.;
3585 double Result1=0., Result2=0., Result3=0., Result4=0.;
3586 const double HGcRCFactor = 1./LevS->MaxN; // factor for inverse fft
3587
3588
3589 // fft to real space
3590 SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
3591 SetArrayToDouble0((double *)PsiC, Dens0->TotalSize*2);
3592 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
3593 Index = LevS->GArray[i].Index;
3594 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
3595 destpos = &tempdestRC[LevS->MaxNUp*Index];
3596 for (pos=0; pos < LevS->MaxNUp; pos++) {
3597 destpos[pos].re = (Psi0[i].re)*posfac[pos].re-(Psi0[i].im)*posfac[pos].im;
3598 destpos[pos].im = (Psi0[i].re)*posfac[pos].im+(Psi0[i].im)*posfac[pos].re;
3599 //destpos[pos].re = (Psi0[i].im)*posfac[pos].re-(-Psi0[i].re)*posfac[pos].im;
3600 //destpos[pos].im = (Psi0[i].im)*posfac[pos].im+(-Psi0[i].re)*posfac[pos].re;
3601 }
3602 }
3603 for (i=0; i<LevS->MaxDoubleG; i++) {
3604 destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
3605 destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
3606 for (pos=0; pos < LevS->MaxNUp; pos++) {
3607 destRCD[pos].re = destRCS[pos].re;
3608 destRCD[pos].im = -destRCS[pos].im;
3609 }
3610 }
3611 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
3612 DensityRTransformPos(LevS,(fftw_real*)tempdestRC, Psi0R);
3613
3614 // apply position operator and do first result
3615 for (n0=0;n0<N0;n0++) // only local points on x axis
3616 for (n[1]=0;n[1]<N[1];n[1]++)
3617 for (n[2]=0;n[2]<N[2];n[2]++) {
3618 n[0]=n0 + LevS->Plan0.plan->start_nx; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
3619 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
3620 iS = n[2]+N[2]*(n[1]+N[1]*n0);
3621 //x[0] += 1; // shifting expectation value of x coordinate from 0 to 1
3622 PsiCR[iS] = Psi0R[i0]; // truedist(Lat, x[0], Wcentre[0],0) *
3623 result1 += PsiCR[iS] * Psi0R[i0];
3624 }
3625 result1 /= LevS->MaxN; // factor due to discrete integration
3626 MPI_Allreduce ( &result1, &Result1, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3627 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 1st result: %e\n",P->Par.me, Result1);
3628
3629 // fft to reciprocal space and do second result
3630 fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, PsiC, workC);
3631 SetArrayToDouble0((double *)dest, 2*R->InitLevS->MaxG);
3632 for (g=0; g < LevS->MaxG; g++) {
3633 Index = LevS->GArray[g].Index;
3634 dest[g].re = (Psi0[Index].re)*HGcRCFactor;
3635 dest[g].im = (Psi0[Index].im)*HGcRCFactor;
3636 }
3637 result2 = GradSP(P,LevS,Psi0,dest);
3638 MPI_Allreduce ( &result2, &Result2, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3639 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 2nd result: %e\n",P->Par.me, Result2);
3640
3641 // fft again to real space, this time change symmetry
3642 SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
3643 SetArrayToDouble0((double *)PsiC, Dens0->TotalSize*2);
3644 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
3645 Index = LevS->GArray[i].Index;
3646 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
3647 destpos = &tempdestRC[LevS->MaxNUp*Index];
3648 for (pos=0; pos < LevS->MaxNUp; pos++) {
3649 destpos[pos].re = (Psi0[i].im)*posfac[pos].re-(-Psi0[i].re)*posfac[pos].im;
3650 destpos[pos].im = (Psi0[i].im)*posfac[pos].im+(-Psi0[i].re)*posfac[pos].re;
3651 }
3652 }
3653 for (i=0; i<LevS->MaxDoubleG; i++) {
3654 destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
3655 destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
3656 for (pos=0; pos < LevS->MaxNUp; pos++) {
3657 destRCD[pos].re = destRCS[pos].re;
3658 destRCD[pos].im = -destRCS[pos].im;
3659 }
3660 }
3661 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
3662 DensityRTransformPos(LevS,(fftw_real*)tempdestRC, Psi0R);
3663
3664 // bring down from Lev0 to LevS
3665 for (n0=0;n0<N0;n0++) // only local points on x axis
3666 for (n[1]=0;n[1]<N[1];n[1]++)
3667 for (n[2]=0;n[2]<N[2];n[2]++) {
3668 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
3669 iS = n[2]+N[2]*(n[1]+N[1]*n0);
3670 PsiCR[iS] = Psi0R[i0]; // truedist(Lat, x[0], Wcentre[0],0) *
3671 result3 += PsiCR[iS] * Psi0R[i0];
3672 }
3673 result3 /= LevS->MaxN; // factor due to discrete integration
3674 MPI_Allreduce ( &result3, &Result3, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3675 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 3rd result: %e\n",P->Par.me, Result3);
3676
3677 // fft back to reciprocal space, change symmetry back and do third 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 = (-PsiC[Index].im)*HGcRCFactor;
3683 dest[g].im = ( PsiC[Index].re)*HGcRCFactor;
3684 }
3685 result4 = GradSP(P,LevS,Psi0,dest);
3686 MPI_Allreduce ( &result4, &Result4, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3687 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 4th result: %e\n",P->Par.me, Result4);
3688}
3689
3690
3691/** Test function to check RxP application.
3692 * Checks applied solution to an analytic for a specific and simple wave function -
3693 * where just one coefficient is unequal to zero.
3694 * \param *P Problem at hand
3695 exp(I b G) - I exp(I b G) b G - exp(I a G) + I exp(I a G) a G
3696 -------------------------------------------------------------
3697 2
3698 G
3699 */
3700void test_rxp(struct Problem *P)
3701{
3702 struct RunStruct *R = &P->R;
3703 struct Lattice *Lat = &P->Lat;
3704 //struct LatticeLevel *Lev0 = R->Lev0;
3705 struct LatticeLevel *LevS = R->LevS;
3706 struct OneGData *GA = LevS->GArray;
3707 //struct Density *Dens0 = Lev0->Dens;
3708 fftw_complex *Psi0 = LevS->LPsi->TempPsi;
3709 fftw_complex *Psi2 = P->Grad.GradientArray[GraSchGradient];
3710 fftw_complex *Psi3 = LevS->LPsi->TempPsi2;
3711 int g, g_bar, i, j, k, k_normal = 0;
3712 double tmp, a,b, G;
3713 //const double *Wcentre = Lat->Psi.AddData[k_normal].WannierCentre;
3714 const double discrete_factor = 1.;//Lat->Volume/LevS->MaxN;
3715 fftw_complex integral;
3716
3717 // reset coefficients
3718 debug (P,"Creating RxP test function.");
3719 SetArrayToDouble0((double *)Psi0,2*R->InitLevS->MaxG);
3720 SetArrayToDouble0((double *)Psi2,2*R->InitLevS->MaxG);
3721
3722 // pick one which becomes non-zero
3723 g = 3;
3724
3725 //for (g=0;g<LevS->MaxG;g++) {
3726 Psi0[g].re = 1.;
3727 Psi0[g].im = 0.;
3728 //}
3729 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]);
3730 i = 0;
3731
3732 // calculate analytic result
3733 debug (P,"Calculating analytic solution.");
3734 for (g_bar=0;g_bar<LevS->MaxG;g_bar++) {
3735 for (g=0;g<LevS->MaxG;g++) {
3736 if (GA[g].G[i] == GA[g_bar].G[i]) {
3737 j = cross(i,0);
3738 k = cross(i,1);
3739 if (GA[g].G[k] == GA[g_bar].G[k]) {
3740 //b = truedist(Lat, sqrt(Lat->RealBasisSQ[j]), Wcentre[j], j);
3741 b = sqrt(Lat->RealBasisSQ[j]);
3742 //a = truedist(Lat, 0., Wcentre[j], j);
3743 a = 0.;
3744 G = 1; //GA[g].G[k];
3745 if (GA[g].G[j] == GA[g_bar].G[j]) {
3746 Psi2[g_bar].re += G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor;
3747 Psi2[g_bar].im += G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor;
3748 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3749 //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);
3750 } else {
3751 tmp = GA[g].G[j]-GA[g_bar].G[j];
3752 integral.re = (cos(tmp*b)+sin(tmp*b)*b*tmp - cos(tmp*a)-sin(tmp*a)*a*tmp) / (tmp * tmp);
3753 integral.im = (sin(tmp*b)-cos(tmp*b)*b*tmp - sin(tmp*a)+cos(tmp*a)*a*tmp) / (tmp * tmp);
3754 Psi2[g_bar].re += G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor;
3755 Psi2[g_bar].im += G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor;
3756 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3757 //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);
3758 }
3759 }
3760 j = cross(i,2);
3761 k = cross(i,3);
3762 if (GA[g].G[k] == GA[g_bar].G[k]) {
3763 //b = truedist(Lat, sqrt(Lat->RealBasisSQ[j]), Wcentre[j], j);
3764 b = sqrt(Lat->RealBasisSQ[j]);
3765 //a = truedist(Lat, 0., Wcentre[j], j);
3766 a = 0.;
3767 G = 1; //GA[g].G[k];
3768 if (GA[g].G[j] == GA[g_bar].G[j]) {
3769 Psi2[g_bar].re += G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor;
3770 Psi2[g_bar].im += G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor;
3771 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3772 //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);
3773 } else {
3774 tmp = GA[g].G[j]-GA[g_bar].G[j];
3775 integral.re = (cos(tmp*b)+sin(tmp*b)*b*tmp - cos(tmp*a)-sin(tmp*a)*a*tmp) / (tmp * tmp);
3776 integral.im = (sin(tmp*b)-cos(tmp*b)*b*tmp - sin(tmp*a)+cos(tmp*a)*a*tmp) / (tmp * tmp);
3777 Psi2[g_bar].re += G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor;
3778 Psi2[g_bar].im += G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor;
3779 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3780 //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);
3781 }
3782 }
3783 }
3784 }
3785 }
3786
3787 // apply rxp
3788 debug (P,"Applying RxP to test function.");
3789 CalculatePerturbationOperator_RxP(P,Psi0,Psi3,k_normal,i);
3790
3791 // compare both coefficient arrays
3792 debug(P,"Beginning comparison of analytic and Rxp applied solution.");
3793 for (g=0;g<LevS->MaxG;g++) {
3794 if ((fabs(Psi3[g].re-Psi2[g].re) >= MYEPSILON) || (fabs(Psi3[g].im-Psi2[g].im) >= MYEPSILON))
3795 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);
3796 //else
3797 //fprintf(stderr,"(%i) Psi1[%i] == Psi2[%i] = %e +i %e\n",P->Par.me, g, g, Psi1[g].re, Psi1[g].im);
3798 }
3799 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));
3800 fprintf(stderr,"(%i) <1|1> = |r|ᅵ == %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi3,Psi3), GradImSP(P,LevS,Psi3,Psi3));
3801 fprintf(stderr,"(%i) <0|0> = %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi0), GradImSP(P,LevS,Psi0,Psi0));
3802 fprintf(stderr,"(%i) <0|2> = %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi2), GradImSP(P,LevS,Psi0,Psi2));
3803}
3804
3805
3806/** Output of a (X,Y,DX,DY) 2d-vector plot.
3807 * For a printable representation of the induced current two-dimensional vector plots are useful, as three-dimensional
3808 * isospheres are sometimes mis-leading or do not represent the desired flow direction. The routine simply extracts a
3809 * two-dimensional cut orthogonal to one of the lattice axis at a certain node.
3810 * \param *P Problem at hand
3811 * \param B_index direction of B field
3812 * \param n_orth grid node in B_index direction of the plane (the order in which the remaining two coordinate axis
3813 * appear is the same as in a cross product, which is used to determine orthogonality)
3814 */
3815void PlotVectorPlane(struct Problem *P, int B_index, int n_orth)
3816{
3817 struct RunStruct *R = &P->R;
3818 struct LatticeLevel *Lev0 = R->Lev0;
3819 struct Density *Dens0 = Lev0->Dens;
3820 char *filename;
3821 char *suchpointer;
3822 FILE *PlotFile = NULL;
3823 const int myPE = P->Par.me_comm_ST;
3824 time_t seconds;
3825 fftw_real *CurrentDensity[NDIM*NDIM];
3826 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
3827 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
3828 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
3829 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
3830 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
3831 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
3832 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
3833 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
3834 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
3835 time(&seconds); // get current time
3836
3837 if (!myPE) { // only process 0 writes to file
3838 // open file
3839 filename = (char *) Malloc(sizeof(char)*255, "PlotVectorPlane: *filename");
3840 sprintf(&filename[0], ".current.L%i.csv", Lev0->LevelNo);
3841 OpenFile(P, &PlotFile, filename, "w", P->Call.out[ReadOut]);
3842 strcpy(filename, ctime(&seconds));
3843 suchpointer = strchr(filename, '\n');
3844 if (suchpointer != NULL)
3845 *suchpointer = '\0';
3846 if (PlotFile != NULL) {
3847 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);
3848 fprintf(PlotFile,"\n");
3849 } else { Error(SomeError, "PlotVectorPlane: Opening Plot File"); }
3850 Free(filename, "PlotVectorPlane: *filename");
3851 }
3852
3853 // plot density
3854 if (!P->Par.me_comm_ST_PsiT) // only first wave function group as current density of all psis was gathered
3855 PlotRealDensity(P, Lev0, PlotFile, B_index, n_orth, CurrentDensity[B_index*NDIM+cross(B_index,0)], CurrentDensity[B_index*NDIM+cross(B_index,1)]);
3856
3857 if (PlotFile != NULL) {
3858 // close file
3859 fclose(PlotFile);
3860 }
3861}
3862
3863
3864/** Reads psi coefficients of \a type from file and transforms to new level.
3865 * \param *P Problem at hand
3866 * \param type PsiTypeTag of which minimisation group to load from file
3867 * \sa ReadSrcPsiDensity() - reading the coefficients, ChangePsiAndDensToLevUp() - transformation to upper level
3868 */
3869void ReadSrcPerturbedPsis(struct Problem *P, enum PsiTypeTag type)
3870{
3871 struct RunStruct *R = &P->R;
3872 struct Lattice *Lat = &P->Lat;
3873 struct LatticeLevel *Lev0 = &P->Lat.Lev[R->Lev0No+1]; // one level higher than current (ChangeLevUp already occurred)
3874 struct LatticeLevel *LevS = &P->Lat.Lev[R->LevSNo+1];
3875 struct Density *Dens = Lev0->Dens;
3876 struct Psis *Psi = &Lat->Psi;
3877 struct fft_plan_3d *plan = Lat->plan;
3878 fftw_complex *work = (fftw_complex *)Dens->DensityCArray[TempDensity];
3879 fftw_complex *tempdestRC = (fftw_complex *)Dens->DensityArray[TempDensity];
3880 fftw_complex *posfac, *destpos, *destRCS, *destRCD;
3881 fftw_complex *source, *source0;
3882 int Index,i,pos;
3883 double factorC = 1./Lev0->MaxN;
3884 int p,g;
3885
3886 // ================= read coefficients from file to LocalPsi ============
3887 ReadSrcPsiDensity(P, type, 0, R->LevSNo+1);
3888
3889 // ================= transform to upper level ===========================
3890 // for all local Psis do the usual transformation (completing coefficients for all grid vectors, fft, permutation)
3891 LockDensityArray(Dens, TempDensity, real);
3892 LockDensityArray(Dens, TempDensity, imag);
3893 for (p=Psi->LocalNo-1; p >= 0; p--)
3894 if (Psi->LocalPsiStatus[p].PsiType == type) { // only for the desired type
3895 source = LevS->LPsi->LocalPsi[p];
3896 source0 = Lev0->LPsi->LocalPsi[p];
3897 //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);
3898 SetArrayToDouble0((double *)tempdestRC, Dens->TotalSize*2);
3899 for (i=0;i<LevS->MaxG;i++) {
3900 Index = LevS->GArray[i].Index;
3901 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
3902 destpos = &tempdestRC[LevS->MaxNUp*Index];
3903 //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!"); }
3904 for (pos=0; pos < LevS->MaxNUp; pos++) {
3905 destpos[pos].re = source[i].re*posfac[pos].re-source[i].im*posfac[pos].im;
3906 destpos[pos].im = source[i].re*posfac[pos].im+source[i].im*posfac[pos].re;
3907 }
3908 }
3909 for (i=0; i<LevS->MaxDoubleG; i++) {
3910 destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
3911 destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
3912 for (pos=0; pos < LevS->MaxNUp; pos++) {
3913 destRCD[pos].re = destRCS[pos].re;
3914 destRCD[pos].im = -destRCS[pos].im;
3915 }
3916 }
3917 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
3918 DensityRTransformPos(LevS,(fftw_real*)tempdestRC,(fftw_real *)Dens->DensityCArray[ActualPsiDensity]);
3919 // now we have density in the upper level, fft back to complex and store it as wave function coefficients
3920 fft_3d_real_to_complex(plan, Lev0->LevelNo, FFTNF1, Dens->DensityCArray[ActualPsiDensity], work);
3921 for (g=0; g < Lev0->MaxG; g++) {
3922 Index = Lev0->GArray[g].Index;
3923 source0[g].re = Dens->DensityCArray[ActualPsiDensity][Index].re*factorC;
3924 source0[g].im = Dens->DensityCArray[ActualPsiDensity][Index].im*factorC;
3925 //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!"); }
3926 }
3927 if (Lev0->GArray[0].GSq == 0.0)
3928 source0[g].im = 0.0;
3929 }
3930 UnLockDensityArray(Dens, TempDensity, real);
3931 UnLockDensityArray(Dens, TempDensity, imag);
3932 // finished.
3933}
3934
3935/** evaluates perturbed energy functional
3936 * \param norm norm of current Psi in functional
3937 * \param *params void-pointer to parameter array
3938 * \return evaluated functional at f(x) with \a norm
3939 */
3940double perturbed_function (double norm, void *params) {
3941 struct Problem *P = (struct Problem *)params;
3942 int i, n = P->R.LevS->MaxG;
3943 double old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
3944 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
3945 fprintf(stderr,"(%i) perturbed_function: setting norm to %lg ...", P->Par.me, norm);
3946 // set desired norm for current Psi
3947 for (i=0; i< n; i++) {
3948 currentPsi[i].re *= norm/old_norm; // real part
3949 currentPsi[i].im *= norm/old_norm; // imaginary part
3950 }
3951 P->R.PsiStep = 0; // make it not advance to next Psi
3952
3953 //debug(P,"UpdateActualPsiNo");
3954 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
3955 //debug(P,"UpdateEnergyArray");
3956 UpdateEnergyArray(P); // shift energy values in their array by one
3957 //debug(P,"UpdatePerturbedEnergyCalculation");
3958 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
3959 EnergyAllReduce(P); // gather from all processes and sum up to total energy
3960/*
3961 for (i=0; i< n; i++) {
3962 currentPsi[i].re /= norm/old_norm; // real part
3963 currentPsi[i].im /= norm/old_norm; // imaginary part
3964 }*/
3965
3966 fprintf(stderr,"%lg\n", P->Lat.E->TotalEnergy[0]);
3967 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional
3968}
3969
3970/** evaluates perturbed energy functional.
3971 * \param *x current position in functional
3972 * \param *params void-pointer to parameter array
3973 * \return evaluated functional at f(x)
3974 */
3975double perturbed_f (const gsl_vector *x, void *params) {
3976 struct Problem *P = (struct Problem *)params;
3977 int i, n = P->R.LevS->MaxG*2;
3978 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
3979 //int diff = 0;
3980 //debug(P,"f");
3981 // put x into current Psi
3982 for (i=0; i< n; i+=2) {
3983 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
3984 currentPsi[i/2].re = gsl_vector_get (x, i); // real part
3985 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
3986 }
3987 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
3988 P->R.PsiStep = 0; // make it not advance to next Psi
3989
3990 //debug(P,"UpdateActualPsiNo");
3991 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
3992 //debug(P,"UpdateEnergyArray");
3993 UpdateEnergyArray(P); // shift energy values in their array by one
3994 //debug(P,"UpdatePerturbedEnergyCalculation");
3995 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
3996 EnergyAllReduce(P); // gather from all processes and sum up to total energy
3997
3998 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional
3999}
4000
4001/** evaluates perturbed energy gradient.
4002 * \param *x current position in functional
4003 * \param *params void-pointer to parameter array
4004 * \param *g array for gradient vector on return
4005 */
4006void perturbed_df (const gsl_vector *x, void *params, gsl_vector *g) {
4007 struct Problem *P = (struct Problem *)params;
4008 int i, n = P->R.LevS->MaxG*2;
4009 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
4010 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];
4011 //int diff = 0;
4012 //debug(P,"df");
4013 // put x into current Psi
4014 for (i=0; i< n; i+=2) {
4015 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
4016 currentPsi[i/2].re = gsl_vector_get (x, i); // real part
4017 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
4018 }
4019 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
4020 P->R.PsiStep = 0; // make it not advance to next Psi
4021
4022 //debug(P,"UpdateActualPsiNo");
4023 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
4024 //debug(P,"UpdateEnergyArray");
4025 UpdateEnergyArray(P); // shift energy values in their array by one
4026 //debug(P,"UpdatePerturbedEnergyCalculation");
4027 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
4028 EnergyAllReduce(P); // gather from all processes and sum up to total energy
4029
4030 // checkout gradient
4031 //diff = 0;
4032 for (i=0; i< n; i+=2) {
4033 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++;
4034 gsl_vector_set (g, i, -gradient[i/2].re); // real part
4035 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part
4036 }
4037 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);
4038}
4039
4040/** evaluates perturbed energy functional and gradient.
4041 * \param *x current position in functional
4042 * \param *params void-pointer to parameter array
4043 * \param *f pointer to energy function value on return
4044 * \param *g array for gradient vector on return
4045 */
4046void perturbed_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *g) {
4047 struct Problem *P = (struct Problem *)params;
4048 int i, n = P->R.LevS->MaxG*2;
4049 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
4050 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];
4051 //int diff = 0;
4052 //debug(P,"fdf");
4053 // put x into current Psi
4054 for (i=0; i< n; i+=2) {
4055 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
4056 currentPsi[i/2].re = gsl_vector_get (x, i); // real part
4057 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
4058 }
4059 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
4060 P->R.PsiStep = 0; // make it not advance to next Psi
4061
4062 //debug(P,"UpdateActualPsiNo");
4063 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
4064 //debug(P,"UpdateEnergyArray");
4065 UpdateEnergyArray(P); // shift energy values in their array by one
4066 //debug(P,"UpdatePerturbedEnergyCalculation");
4067 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
4068 EnergyAllReduce(P); // gather from all processes and sum up to total energy
4069
4070 // checkout gradient
4071 //diff = 0;
4072 for (i=0; i< n; i+=2) {
4073 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++;
4074 gsl_vector_set (g, i, -gradient[i/2].re); // real part
4075 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part
4076 }
4077 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);
4078
4079 *f = P->Lat.E->TotalEnergy[0]; // and return evaluated functional
4080}
4081
4082/* MinimisePerturbed with all the brent minimisation approach
4083void MinimisePerturbed (struct Problem *P, int *Stop, int *SuperStop) {
4084 struct RunStruct *R = &P->R;
4085 struct Lattice *Lat = &P->Lat;
4086 struct Psis *Psi = &Lat->Psi;
4087 int type;
4088 //int i;
4089
4090 // stuff for GSL minimization
4091 //size_t iter;
4092 //int status, Status
4093 int n = R->LevS->MaxG*2;
4094 const gsl_multimin_fdfminimizer_type *T_multi;
4095 const gsl_min_fminimizer_type *T;
4096 gsl_multimin_fdfminimizer *s_multi;
4097 gsl_min_fminimizer *s;
4098 gsl_vector *x;//, *ss;
4099 gsl_multimin_function_fdf my_func;
4100 gsl_function F;
4101 //fftw_complex *currentPsi;
4102 //double a,b,m, f_m, f_a, f_b;
4103 //double old_norm;
4104
4105 my_func.f = &perturbed_f;
4106 my_func.df = &perturbed_df;
4107 my_func.fdf = &perturbed_fdf;
4108 my_func.n = n;
4109 my_func.params = P;
4110 F.function = &perturbed_function;
4111 F.params = P;
4112
4113 x = gsl_vector_alloc (n);
4114 //ss = gsl_vector_alloc (Psi->NoOfPsis);
4115 T_multi = gsl_multimin_fdfminimizer_vector_bfgs;
4116 s_multi = gsl_multimin_fdfminimizer_alloc (T_multi, n);
4117 T = gsl_min_fminimizer_brent;
4118 s = gsl_min_fminimizer_alloc (T);
4119
4120 for (type=Perturbed_P0;type<=Perturbed_RxP2;type++) { // go through each perturbation group separately //
4121 *Stop=0; // reset stop flag
4122 fprintf(stderr,"(%i)Beginning perturbed minimisation of type %s ...\n", P->Par.me, R->MinimisationName[type]);
4123 //OutputOrbitalPositions(P, Occupied);
4124 R->PsiStep = R->MaxPsiStep; // reset in-Psi-minimisation-counter, so that we really advance to the next wave function
4125 UpdateActualPsiNo(P, type); // step on to next perturbed one
4126 fprintf(stderr, "(%i) Re-initializing perturbed psi array for type %s ", P->Par.me, R->MinimisationName[type]);
4127 if (P->Call.ReadSrcFiles && ReadSrcPsiDensity(P,type,1, R->LevSNo)) {
4128 SpeedMeasure(P, InitSimTime, StartTimeDo);
4129 fprintf(stderr,"from source file of recent calculation\n");
4130 ReadSrcPsiDensity(P,type, 0, R->LevSNo);
4131 ResetGramSchTagType(P, Psi, type, IsOrthogonal); // loaded values are orthonormal
4132 SpeedMeasure(P, DensityTime, StartTimeDo);
4133 //InitDensityCalculation(P);
4134 SpeedMeasure(P, DensityTime, StopTimeDo);
4135 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
4136 UpdateGramSchOldActualPsiNo(P,Psi);
4137 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
4138 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones
4139 EnergyAllReduce(P); // gather energies for minimum search
4140 SpeedMeasure(P, InitSimTime, StopTimeDo);
4141 }
4142 if (P->Call.ReadSrcFiles != 1) {
4143 SpeedMeasure(P, InitSimTime, StartTimeDo);
4144 ResetGramSchTagType(P, Psi, type, NotOrthogonal); // perturbed now shall be orthonormalized
4145 if (P->Call.ReadSrcFiles != 2) {
4146 if (R->LevSNo == Lat->MaxLevel-1) { // is it the starting level? (see InitRunLevel())
4147 fprintf(stderr, "randomly.\n");
4148 InitPsisValue(P, Psi->TypeStartIndex[type], Psi->TypeStartIndex[type+1]); // initialize perturbed array for this run
4149 } else {
4150 fprintf(stderr, "from source file of last level.\n");
4151 ReadSrcPerturbedPsis(P, type);
4152 }
4153 }
4154 SpeedMeasure(P, InitGramSchTime, StartTimeDo);
4155 GramSch(P, R->LevS, Psi, Orthogonalize);
4156 SpeedMeasure(P, InitGramSchTime, StopTimeDo);
4157 SpeedMeasure(P, InitDensityTime, StartTimeDo);
4158 //InitDensityCalculation(P);
4159 SpeedMeasure(P, InitDensityTime, StopTimeDo);
4160 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
4161 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
4162 UpdateGramSchOldActualPsiNo(P,Psi);
4163 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones
4164 EnergyAllReduce(P); // gather energies for minimum search
4165 SpeedMeasure(P, InitSimTime, StopTimeDo);
4166 R->LevS->Step++;
4167 EnergyOutput(P,0);
4168 while (*Stop != 1) {
4169 // copy current Psi into starting vector
4170 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
4171 for (i=0; i< n; i+=2) {
4172 gsl_vector_set (x, i, currentPsi[i/2].re); // real part
4173 gsl_vector_set (x, i+1, currentPsi[i/2].im); // imaginary part
4174 }
4175 gsl_multimin_fdfminimizer_set (s_multi, &my_func, x, 0.01, 1e-2);
4176 iter = 0;
4177 status = 0;
4178 do { // look for minimum along current local psi
4179 iter++;
4180 status = gsl_multimin_fdfminimizer_iterate (s_multi);
4181 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);
4182 if (Status)
4183 break;
4184 status = gsl_multimin_test_gradient (s_multi->gradient, 1e-2);
4185 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);
4186 //if (Status == GSL_SUCCESS)
4187 //printf ("Minimum found at:\n");
4188 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);
4189 //TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?
4190 } while (Status == GSL_CONTINUE && iter < 3);
4191 // now minimize norm of currentPsi (one-dim)
4192 if (0) {
4193 iter = 0;
4194 status = 0;
4195 m = 1.;
4196 a = MYEPSILON;
4197 b = 100.;
4198 f_a = perturbed_function (a, P);
4199 f_b = perturbed_function (b, P);
4200 f_m = perturbed_function (m, P);
4201 //if ((f_m < f_a) && (f_m < f_b)) {
4202 gsl_min_fminimizer_set (s, &F, m, a, b);
4203 do { // look for minimum along current local psi
4204 iter++;
4205 status = gsl_min_fminimizer_iterate (s);
4206 m = gsl_min_fminimizer_x_minimum (s);
4207 a = gsl_min_fminimizer_x_lower (s);
4208 b = gsl_min_fminimizer_x_upper (s);
4209 status = gsl_min_test_interval (a, b, 0.001, 0.0);
4210 if (status == GSL_SUCCESS)
4211 printf ("Minimum found at:\n");
4212 printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
4213 (int) iter, a, b,
4214 m, b - a);
4215 } while (status == GSL_CONTINUE && iter < 100);
4216 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
4217 for (i=0; i< n; i++) {
4218 currentPsi[i].re *= m/old_norm; // real part
4219 currentPsi[i].im *= m/old_norm; // imaginary part
4220 }
4221 } else debug(P,"Norm not minimizable!");
4222 //P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi
4223 FindPerturbedMinimum(P);
4224 //debug(P,"UpdateActualPsiNo");
4225 UpdateActualPsiNo(P, type); // step on to next perturbed Psi
4226 //debug(P,"UpdateEnergyArray");
4227 UpdateEnergyArray(P); // shift energy values in their array by one
4228 //debug(P,"UpdatePerturbedEnergyCalculation");
4229 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
4230 EnergyAllReduce(P); // gather from all processes and sum up to total energy
4231 //ControlNativeDensity(P); // check total density (summed up PertMixed must be zero!)
4232 //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);
4233 if (*SuperStop != 1)
4234 *SuperStop = CheckCPULIM(P);
4235 *Stop = CalculateMinimumStop(P, *SuperStop);
4236 P->Speed.Steps++; // step on
4237 R->LevS->Step++;
4238 }
4239 // now release normalization condition and minimize wrt to norm
4240 *Stop = 0;
4241 while (*Stop != 1) {
4242 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
4243 iter = 0;
4244 status = 0;
4245 m = 1.;
4246 a = 0.001;
4247 b = 10.;
4248 f_a = perturbed_function (a, P);
4249 f_b = perturbed_function (b, P);
4250 f_m = perturbed_function (m, P);
4251 if ((f_m < f_a) && (f_m < f_b)) {
4252 gsl_min_fminimizer_set (s, &F, m, a, b);
4253 do { // look for minimum along current local psi
4254 iter++;
4255 status = gsl_min_fminimizer_iterate (s);
4256 m = gsl_min_fminimizer_x_minimum (s);
4257 a = gsl_min_fminimizer_x_lower (s);
4258 b = gsl_min_fminimizer_x_upper (s);
4259 status = gsl_min_test_interval (a, b, 0.001, 0.0);
4260 if (status == GSL_SUCCESS)
4261 printf ("Minimum found at:\n");
4262 printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
4263 (int) iter, a, b,
4264 m, b - a);
4265 } while (status == GSL_CONTINUE && iter < 100);
4266 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
4267 for (i=0; i< n; i++) {
4268 currentPsi[i].re *= m/old_norm; // real part
4269 currentPsi[i].im *= m/old_norm; // imaginary part
4270 }
4271 }
4272 P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi
4273 //debug(P,"UpdateActualPsiNo");
4274 UpdateActualPsiNo(P, type); // step on to next perturbed Psi
4275 if (*SuperStop != 1)
4276 *SuperStop = CheckCPULIM(P);
4277 *Stop = CalculateMinimumStop(P, *SuperStop);
4278 P->Speed.Steps++; // step on
4279 R->LevS->Step++;
4280 }
4281 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Write %s srcpsi to disk\n", P->Par.me, R->MinimisationName[type]);
4282 OutputSrcPsiDensity(P, type);
4283// if (!TestReadnWriteSrcDensity(P,type))
4284// Error(SomeError,"TestReadnWriteSrcDensity failed!");
4285 }
4286
4287 TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?
4288 // calculate current density summands
4289 //if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Filling current density grid ...\n",P->Par.me);
4290 SpeedMeasure(P, CurrDensTime, StartTimeDo);
4291 if (*SuperStop != 1) {
4292 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
4293 R->DoFullCurrent = 1; // set to 1 if it was 2 but Check...() yielded necessity
4294 //debug(P,"Filling with Delta j ...");
4295 //FillDeltaCurrentDensity(P);
4296 }// else
4297 //debug(P,"There is no overlap between orbitals.");
4298 //debug(P,"Filling with j ...");
4299 FillCurrentDensity(P);
4300 }
4301 SpeedMeasure(P, CurrDensTime, StopTimeDo);
4302
4303 SetGramSchExtraPsi(P,Psi,NotUsedToOrtho); // remove extra Psis from orthogonality check
4304 ResetGramSchTagType(P, Psi, type, NotUsedToOrtho); // remove this group from the check for the next minimisation group as well!
4305 }
4306 UpdateActualPsiNo(P, Occupied); // step on back to an occupied one
4307
4308 gsl_multimin_fdfminimizer_free (s_multi);
4309 gsl_min_fminimizer_free (s);
4310 gsl_vector_free (x);
4311 //gsl_vector_free (ss);
4312}
4313*/
Note: See TracBrowser for help on using the repository browser.