- Timestamp:
- Apr 22, 2008, 9:14:25 AM (17 years ago)
- Children:
- b0aa9c
- Parents:
- 0f2c43
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified pcp/src/perturbed.c ¶
r0f2c43 r6edeca 69 69 #include "wannier.h" 70 70 71 /** evaluates perturbed energy functional.72 * \param norm norm of current Psi in functional73 * \param *params void-pointer to parameter array74 * \return evaluated functional at f(x) with \a norm75 */76 double perturbed_function (double norm, void *params) {77 struct Problem *P = (struct Problem *)params;78 int i, n = P->R.LevS->MaxG;79 double old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);80 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];81 fprintf(stderr,"(%i) perturbed_function: setting norm to %lg ...", P->Par.me, norm);82 // set desired norm for current Psi83 for (i=0; i< n; i++) {84 currentPsi[i].re *= norm/old_norm; // real part85 currentPsi[i].im *= norm/old_norm; // imaginary part86 }87 P->R.PsiStep = 0; // make it not advance to next Psi88 89 //debug(P,"UpdateActualPsiNo");90 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize91 //debug(P,"UpdateEnergyArray");92 UpdateEnergyArray(P); // shift energy values in their array by one93 //debug(P,"UpdatePerturbedEnergyCalculation");94 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)95 EnergyAllReduce(P); // gather from all processes and sum up to total energy96 /*97 for (i=0; i< n; i++) {98 currentPsi[i].re /= norm/old_norm; // real part99 currentPsi[i].im /= norm/old_norm; // imaginary part100 }*/101 102 fprintf(stderr,"%lg\n", P->Lat.E->TotalEnergy[0]);103 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional104 }105 106 /** evaluates perturbed energy functional.107 * \param *x current position in functional108 * \param *params void-pointer to parameter array109 * \return evaluated functional at f(x)110 */111 double perturbed_f (const gsl_vector *x, void *params) {112 struct Problem *P = (struct Problem *)params;113 int i, n = P->R.LevS->MaxG*2;114 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];115 //int diff = 0;116 //debug(P,"f");117 // put x into current Psi118 for (i=0; i< n; i+=2) {119 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;120 currentPsi[i/2].re = gsl_vector_get (x, i); // real part121 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part122 }123 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);124 P->R.PsiStep = 0; // make it not advance to next Psi125 126 //debug(P,"UpdateActualPsiNo");127 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize128 //debug(P,"UpdateEnergyArray");129 UpdateEnergyArray(P); // shift energy values in their array by one130 //debug(P,"UpdatePerturbedEnergyCalculation");131 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)132 EnergyAllReduce(P); // gather from all processes and sum up to total energy133 134 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional135 }136 137 /** evaluates perturbed energy gradient.138 * \param *x current position in functional139 * \param *params void-pointer to parameter array140 * \param *g array for gradient vector on return141 */142 void perturbed_df (const gsl_vector *x, void *params, gsl_vector *g) {143 struct Problem *P = (struct Problem *)params;144 int i, n = P->R.LevS->MaxG*2;145 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];146 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];147 //int diff = 0;148 //debug(P,"df");149 // put x into current Psi150 for (i=0; i< n; i+=2) {151 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;152 currentPsi[i/2].re = gsl_vector_get (x, i); // real part153 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part154 }155 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);156 P->R.PsiStep = 0; // make it not advance to next Psi157 158 //debug(P,"UpdateActualPsiNo");159 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize160 //debug(P,"UpdateEnergyArray");161 UpdateEnergyArray(P); // shift energy values in their array by one162 //debug(P,"UpdatePerturbedEnergyCalculation");163 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)164 EnergyAllReduce(P); // gather from all processes and sum up to total energy165 166 // checkout gradient167 //diff = 0;168 for (i=0; i< n; i+=2) {169 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++;170 gsl_vector_set (g, i, -gradient[i/2].re); // real part171 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part172 }173 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);174 }175 176 /** evaluates perturbed energy functional and gradient.177 * \param *x current position in functional178 * \param *params void-pointer to parameter array179 * \param *f pointer to energy function value on return180 * \param *g array for gradient vector on return181 */182 void perturbed_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *g) {183 struct Problem *P = (struct Problem *)params;184 int i, n = P->R.LevS->MaxG*2;185 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];186 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];187 //int diff = 0;188 //debug(P,"fdf");189 // put x into current Psi190 for (i=0; i< n; i+=2) {191 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;192 currentPsi[i/2].re = gsl_vector_get (x, i); // real part193 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part194 }195 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);196 P->R.PsiStep = 0; // make it not advance to next Psi197 198 //debug(P,"UpdateActualPsiNo");199 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize200 //debug(P,"UpdateEnergyArray");201 UpdateEnergyArray(P); // shift energy values in their array by one202 //debug(P,"UpdatePerturbedEnergyCalculation");203 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)204 EnergyAllReduce(P); // gather from all processes and sum up to total energy205 206 // checkout gradient207 //diff = 0;208 for (i=0; i< n; i+=2) {209 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++;210 gsl_vector_set (g, i, -gradient[i/2].re); // real part211 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part212 }213 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);214 215 *f = P->Lat.E->TotalEnergy[0]; // and return evaluated functional216 }217 71 218 72 /** Minimisation of the PsiTypeTag#Perturbed_RxP0, PsiTypeTag#Perturbed_P0 and other orbitals. … … 258 112 struct Psis *Psi = &Lat->Psi; 259 113 int type; 260 //int i;261 262 // stuff for GSL minimization263 //size_t iter;264 //int status, Status265 int n = R->LevS->MaxG*2;266 const gsl_multimin_fdfminimizer_type *T_multi;267 const gsl_min_fminimizer_type *T;268 gsl_multimin_fdfminimizer *s_multi;269 gsl_min_fminimizer *s;270 gsl_vector *x;//, *ss;271 gsl_multimin_function_fdf my_func;272 gsl_function F;273 //fftw_complex *currentPsi;274 //double a,b,m, f_m, f_a, f_b;275 //double old_norm;276 277 my_func.f = &perturbed_f;278 my_func.df = &perturbed_df;279 my_func.fdf = &perturbed_fdf;280 my_func.n = n;281 my_func.params = P;282 F.function = &perturbed_function;283 F.params = P;284 285 x = gsl_vector_alloc (n);286 //ss = gsl_vector_alloc (Psi->NoOfPsis);287 T_multi = gsl_multimin_fdfminimizer_vector_bfgs;288 s_multi = gsl_multimin_fdfminimizer_alloc (T_multi, n);289 T = gsl_min_fminimizer_brent;290 s = gsl_min_fminimizer_alloc (T);291 114 292 115 for (type=Perturbed_P0;type<=Perturbed_RxP2;type++) { // go through each perturbation group separately // … … 339 162 EnergyOutput(P,0); 340 163 while (*Stop != 1) { 341 /* // copy current Psi into starting vector342 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];343 for (i=0; i< n; i+=2) {344 gsl_vector_set (x, i, currentPsi[i/2].re); // real part345 gsl_vector_set (x, i+1, currentPsi[i/2].im); // imaginary part346 }347 gsl_multimin_fdfminimizer_set (s_multi, &my_func, x, 0.01, 1e-2);348 iter = 0;349 status = 0;350 do { // look for minimum along current local psi351 iter++;352 status = gsl_multimin_fdfminimizer_iterate (s_multi);353 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);354 if (Status)355 break;356 status = gsl_multimin_test_gradient (s_multi->gradient, 1e-2);357 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);358 //if (Status == GSL_SUCCESS)359 //printf ("Minimum found at:\n");360 if (P->Par.me == 0) fprintf (stderr,"(%i,%i,%i)S(%i,%i,%i):\t %5d %10.5f\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, (int)iter, s_multi->f);361 //TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?362 } while (Status == GSL_CONTINUE && iter < 3);363 /* // now minimize norm of currentPsi (one-dim)364 if (0) {365 iter = 0;366 status = 0;367 m = 1.;368 a = MYEPSILON;369 b = 100.;370 f_a = perturbed_function (a, P);371 f_b = perturbed_function (b, P);372 f_m = perturbed_function (m, P);373 //if ((f_m < f_a) && (f_m < f_b)) {374 gsl_min_fminimizer_set (s, &F, m, a, b);375 do { // look for minimum along current local psi376 iter++;377 status = gsl_min_fminimizer_iterate (s);378 m = gsl_min_fminimizer_x_minimum (s);379 a = gsl_min_fminimizer_x_lower (s);380 b = gsl_min_fminimizer_x_upper (s);381 status = gsl_min_test_interval (a, b, 0.001, 0.0);382 if (status == GSL_SUCCESS)383 printf ("Minimum found at:\n");384 printf ("%5d [%.7f, %.7f] %.7f %.7f\n",385 (int) iter, a, b,386 m, b - a);387 } while (status == GSL_CONTINUE && iter < 100);388 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);389 for (i=0; i< n; i++) {390 currentPsi[i].re *= m/old_norm; // real part391 currentPsi[i].im *= m/old_norm; // imaginary part392 }393 } else debug(P,"Norm not minimizable!");*/394 164 //P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi 395 165 FindPerturbedMinimum(P); … … 410 180 } 411 181 // now release normalization condition and minimize wrt to norm 412 /* *Stop = 0;413 while (*Stop != 1) {414 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];415 iter = 0;416 status = 0;417 m = 1.;418 a = 0.001;419 b = 10.;420 f_a = perturbed_function (a, P);421 f_b = perturbed_function (b, P);422 f_m = perturbed_function (m, P);423 if ((f_m < f_a) && (f_m < f_b)) {424 gsl_min_fminimizer_set (s, &F, m, a, b);425 do { // look for minimum along current local psi426 iter++;427 status = gsl_min_fminimizer_iterate (s);428 m = gsl_min_fminimizer_x_minimum (s);429 a = gsl_min_fminimizer_x_lower (s);430 b = gsl_min_fminimizer_x_upper (s);431 status = gsl_min_test_interval (a, b, 0.001, 0.0);432 if (status == GSL_SUCCESS)433 printf ("Minimum found at:\n");434 printf ("%5d [%.7f, %.7f] %.7f %.7f\n",435 (int) iter, a, b,436 m, b - a);437 } while (status == GSL_CONTINUE && iter < 100);438 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);439 for (i=0; i< n; i++) {440 currentPsi[i].re *= m/old_norm; // real part441 currentPsi[i].im *= m/old_norm; // imaginary part442 }443 }444 P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi445 //debug(P,"UpdateActualPsiNo");446 UpdateActualPsiNo(P, type); // step on to next perturbed Psi447 if (*SuperStop != 1)448 *SuperStop = CheckCPULIM(P);449 *Stop = CalculateMinimumStop(P, *SuperStop);450 P->Speed.Steps++; // step on451 R->LevS->Step++;452 }*/453 182 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Write %s srcpsi to disk\n", P->Par.me, R->MinimisationName[type]); 454 183 OutputSrcPsiDensity(P, type); … … 477 206 } 478 207 UpdateActualPsiNo(P, Occupied); // step on back to an occupied one 479 480 gsl_multimin_fdfminimizer_free (s_multi);481 gsl_min_fminimizer_free (s);482 gsl_vector_free (x);483 //gsl_vector_free (ss);484 208 } 485 209 … … 3936 3660 // finished. 3937 3661 } 3662 3663 /** evaluates perturbed energy functional 3664 * \param norm norm of current Psi in functional 3665 * \param *params void-pointer to parameter array 3666 * \return evaluated functional at f(x) with \a norm 3667 */ 3668 double perturbed_function (double norm, void *params) { 3669 struct Problem *P = (struct Problem *)params; 3670 int i, n = P->R.LevS->MaxG; 3671 double old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]); 3672 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]; 3673 fprintf(stderr,"(%i) perturbed_function: setting norm to %lg ...", P->Par.me, norm); 3674 // set desired norm for current Psi 3675 for (i=0; i< n; i++) { 3676 currentPsi[i].re *= norm/old_norm; // real part 3677 currentPsi[i].im *= norm/old_norm; // imaginary part 3678 } 3679 P->R.PsiStep = 0; // make it not advance to next Psi 3680 3681 //debug(P,"UpdateActualPsiNo"); 3682 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize 3683 //debug(P,"UpdateEnergyArray"); 3684 UpdateEnergyArray(P); // shift energy values in their array by one 3685 //debug(P,"UpdatePerturbedEnergyCalculation"); 3686 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower) 3687 EnergyAllReduce(P); // gather from all processes and sum up to total energy 3688 /* 3689 for (i=0; i< n; i++) { 3690 currentPsi[i].re /= norm/old_norm; // real part 3691 currentPsi[i].im /= norm/old_norm; // imaginary part 3692 }*/ 3693 3694 fprintf(stderr,"%lg\n", P->Lat.E->TotalEnergy[0]); 3695 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional 3696 } 3697 3698 /** evaluates perturbed energy functional. 3699 * \param *x current position in functional 3700 * \param *params void-pointer to parameter array 3701 * \return evaluated functional at f(x) 3702 */ 3703 double perturbed_f (const gsl_vector *x, void *params) { 3704 struct Problem *P = (struct Problem *)params; 3705 int i, n = P->R.LevS->MaxG*2; 3706 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]; 3707 //int diff = 0; 3708 //debug(P,"f"); 3709 // put x into current Psi 3710 for (i=0; i< n; i+=2) { 3711 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++; 3712 currentPsi[i/2].re = gsl_vector_get (x, i); // real part 3713 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part 3714 } 3715 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff); 3716 P->R.PsiStep = 0; // make it not advance to next Psi 3717 3718 //debug(P,"UpdateActualPsiNo"); 3719 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize 3720 //debug(P,"UpdateEnergyArray"); 3721 UpdateEnergyArray(P); // shift energy values in their array by one 3722 //debug(P,"UpdatePerturbedEnergyCalculation"); 3723 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower) 3724 EnergyAllReduce(P); // gather from all processes and sum up to total energy 3725 3726 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional 3727 } 3728 3729 /** evaluates perturbed energy gradient. 3730 * \param *x current position in functional 3731 * \param *params void-pointer to parameter array 3732 * \param *g array for gradient vector on return 3733 */ 3734 void perturbed_df (const gsl_vector *x, void *params, gsl_vector *g) { 3735 struct Problem *P = (struct Problem *)params; 3736 int i, n = P->R.LevS->MaxG*2; 3737 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]; 3738 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient]; 3739 //int diff = 0; 3740 //debug(P,"df"); 3741 // put x into current Psi 3742 for (i=0; i< n; i+=2) { 3743 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++; 3744 currentPsi[i/2].re = gsl_vector_get (x, i); // real part 3745 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part 3746 } 3747 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff); 3748 P->R.PsiStep = 0; // make it not advance to next Psi 3749 3750 //debug(P,"UpdateActualPsiNo"); 3751 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize 3752 //debug(P,"UpdateEnergyArray"); 3753 UpdateEnergyArray(P); // shift energy values in their array by one 3754 //debug(P,"UpdatePerturbedEnergyCalculation"); 3755 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower) 3756 EnergyAllReduce(P); // gather from all processes and sum up to total energy 3757 3758 // checkout gradient 3759 //diff = 0; 3760 for (i=0; i< n; i+=2) { 3761 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++; 3762 gsl_vector_set (g, i, -gradient[i/2].re); // real part 3763 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part 3764 } 3765 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff); 3766 } 3767 3768 /** evaluates perturbed energy functional and gradient. 3769 * \param *x current position in functional 3770 * \param *params void-pointer to parameter array 3771 * \param *f pointer to energy function value on return 3772 * \param *g array for gradient vector on return 3773 */ 3774 void perturbed_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *g) { 3775 struct Problem *P = (struct Problem *)params; 3776 int i, n = P->R.LevS->MaxG*2; 3777 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]; 3778 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient]; 3779 //int diff = 0; 3780 //debug(P,"fdf"); 3781 // put x into current Psi 3782 for (i=0; i< n; i+=2) { 3783 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++; 3784 currentPsi[i/2].re = gsl_vector_get (x, i); // real part 3785 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part 3786 } 3787 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff); 3788 P->R.PsiStep = 0; // make it not advance to next Psi 3789 3790 //debug(P,"UpdateActualPsiNo"); 3791 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize 3792 //debug(P,"UpdateEnergyArray"); 3793 UpdateEnergyArray(P); // shift energy values in their array by one 3794 //debug(P,"UpdatePerturbedEnergyCalculation"); 3795 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower) 3796 EnergyAllReduce(P); // gather from all processes and sum up to total energy 3797 3798 // checkout gradient 3799 //diff = 0; 3800 for (i=0; i< n; i+=2) { 3801 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++; 3802 gsl_vector_set (g, i, -gradient[i/2].re); // real part 3803 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part 3804 } 3805 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff); 3806 3807 *f = P->Lat.E->TotalEnergy[0]; // and return evaluated functional 3808 } 3809 3810 /* MinimisePerturbed with all the brent minimisation approach 3811 void MinimisePerturbed (struct Problem *P, int *Stop, int *SuperStop) { 3812 struct RunStruct *R = &P->R; 3813 struct Lattice *Lat = &P->Lat; 3814 struct Psis *Psi = &Lat->Psi; 3815 int type; 3816 //int i; 3817 3818 // stuff for GSL minimization 3819 //size_t iter; 3820 //int status, Status 3821 int n = R->LevS->MaxG*2; 3822 const gsl_multimin_fdfminimizer_type *T_multi; 3823 const gsl_min_fminimizer_type *T; 3824 gsl_multimin_fdfminimizer *s_multi; 3825 gsl_min_fminimizer *s; 3826 gsl_vector *x;//, *ss; 3827 gsl_multimin_function_fdf my_func; 3828 gsl_function F; 3829 //fftw_complex *currentPsi; 3830 //double a,b,m, f_m, f_a, f_b; 3831 //double old_norm; 3832 3833 my_func.f = &perturbed_f; 3834 my_func.df = &perturbed_df; 3835 my_func.fdf = &perturbed_fdf; 3836 my_func.n = n; 3837 my_func.params = P; 3838 F.function = &perturbed_function; 3839 F.params = P; 3840 3841 x = gsl_vector_alloc (n); 3842 //ss = gsl_vector_alloc (Psi->NoOfPsis); 3843 T_multi = gsl_multimin_fdfminimizer_vector_bfgs; 3844 s_multi = gsl_multimin_fdfminimizer_alloc (T_multi, n); 3845 T = gsl_min_fminimizer_brent; 3846 s = gsl_min_fminimizer_alloc (T); 3847 3848 for (type=Perturbed_P0;type<=Perturbed_RxP2;type++) { // go through each perturbation group separately // 3849 *Stop=0; // reset stop flag 3850 fprintf(stderr,"(%i)Beginning perturbed minimisation of type %s ...\n", P->Par.me, R->MinimisationName[type]); 3851 //OutputOrbitalPositions(P, Occupied); 3852 R->PsiStep = R->MaxPsiStep; // reset in-Psi-minimisation-counter, so that we really advance to the next wave function 3853 UpdateActualPsiNo(P, type); // step on to next perturbed one 3854 fprintf(stderr, "(%i) Re-initializing perturbed psi array for type %s ", P->Par.me, R->MinimisationName[type]); 3855 if (P->Call.ReadSrcFiles && ReadSrcPsiDensity(P,type,1, R->LevSNo)) { 3856 SpeedMeasure(P, InitSimTime, StartTimeDo); 3857 fprintf(stderr,"from source file of recent calculation\n"); 3858 ReadSrcPsiDensity(P,type, 0, R->LevSNo); 3859 ResetGramSchTagType(P, Psi, type, IsOrthogonal); // loaded values are orthonormal 3860 SpeedMeasure(P, DensityTime, StartTimeDo); 3861 //InitDensityCalculation(P); 3862 SpeedMeasure(P, DensityTime, StopTimeDo); 3863 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash 3864 UpdateGramSchOldActualPsiNo(P,Psi); 3865 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it 3866 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones 3867 EnergyAllReduce(P); // gather energies for minimum search 3868 SpeedMeasure(P, InitSimTime, StopTimeDo); 3869 } 3870 if (P->Call.ReadSrcFiles != 1) { 3871 SpeedMeasure(P, InitSimTime, StartTimeDo); 3872 ResetGramSchTagType(P, Psi, type, NotOrthogonal); // perturbed now shall be orthonormalized 3873 if (P->Call.ReadSrcFiles != 2) { 3874 if (R->LevSNo == Lat->MaxLevel-1) { // is it the starting level? (see InitRunLevel()) 3875 fprintf(stderr, "randomly.\n"); 3876 InitPsisValue(P, Psi->TypeStartIndex[type], Psi->TypeStartIndex[type+1]); // initialize perturbed array for this run 3877 } else { 3878 fprintf(stderr, "from source file of last level.\n"); 3879 ReadSrcPerturbedPsis(P, type); 3880 } 3881 } 3882 SpeedMeasure(P, InitGramSchTime, StartTimeDo); 3883 GramSch(P, R->LevS, Psi, Orthogonalize); 3884 SpeedMeasure(P, InitGramSchTime, StopTimeDo); 3885 SpeedMeasure(P, InitDensityTime, StartTimeDo); 3886 //InitDensityCalculation(P); 3887 SpeedMeasure(P, InitDensityTime, StopTimeDo); 3888 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it 3889 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash 3890 UpdateGramSchOldActualPsiNo(P,Psi); 3891 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones 3892 EnergyAllReduce(P); // gather energies for minimum search 3893 SpeedMeasure(P, InitSimTime, StopTimeDo); 3894 R->LevS->Step++; 3895 EnergyOutput(P,0); 3896 while (*Stop != 1) { 3897 // copy current Psi into starting vector 3898 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo]; 3899 for (i=0; i< n; i+=2) { 3900 gsl_vector_set (x, i, currentPsi[i/2].re); // real part 3901 gsl_vector_set (x, i+1, currentPsi[i/2].im); // imaginary part 3902 } 3903 gsl_multimin_fdfminimizer_set (s_multi, &my_func, x, 0.01, 1e-2); 3904 iter = 0; 3905 status = 0; 3906 do { // look for minimum along current local psi 3907 iter++; 3908 status = gsl_multimin_fdfminimizer_iterate (s_multi); 3909 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi); 3910 if (Status) 3911 break; 3912 status = gsl_multimin_test_gradient (s_multi->gradient, 1e-2); 3913 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi); 3914 //if (Status == GSL_SUCCESS) 3915 //printf ("Minimum found at:\n"); 3916 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); 3917 //TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal? 3918 } while (Status == GSL_CONTINUE && iter < 3); 3919 // now minimize norm of currentPsi (one-dim) 3920 if (0) { 3921 iter = 0; 3922 status = 0; 3923 m = 1.; 3924 a = MYEPSILON; 3925 b = 100.; 3926 f_a = perturbed_function (a, P); 3927 f_b = perturbed_function (b, P); 3928 f_m = perturbed_function (m, P); 3929 //if ((f_m < f_a) && (f_m < f_b)) { 3930 gsl_min_fminimizer_set (s, &F, m, a, b); 3931 do { // look for minimum along current local psi 3932 iter++; 3933 status = gsl_min_fminimizer_iterate (s); 3934 m = gsl_min_fminimizer_x_minimum (s); 3935 a = gsl_min_fminimizer_x_lower (s); 3936 b = gsl_min_fminimizer_x_upper (s); 3937 status = gsl_min_test_interval (a, b, 0.001, 0.0); 3938 if (status == GSL_SUCCESS) 3939 printf ("Minimum found at:\n"); 3940 printf ("%5d [%.7f, %.7f] %.7f %.7f\n", 3941 (int) iter, a, b, 3942 m, b - a); 3943 } while (status == GSL_CONTINUE && iter < 100); 3944 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]); 3945 for (i=0; i< n; i++) { 3946 currentPsi[i].re *= m/old_norm; // real part 3947 currentPsi[i].im *= m/old_norm; // imaginary part 3948 } 3949 } else debug(P,"Norm not minimizable!"); 3950 //P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi 3951 FindPerturbedMinimum(P); 3952 //debug(P,"UpdateActualPsiNo"); 3953 UpdateActualPsiNo(P, type); // step on to next perturbed Psi 3954 //debug(P,"UpdateEnergyArray"); 3955 UpdateEnergyArray(P); // shift energy values in their array by one 3956 //debug(P,"UpdatePerturbedEnergyCalculation"); 3957 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower) 3958 EnergyAllReduce(P); // gather from all processes and sum up to total energy 3959 //ControlNativeDensity(P); // check total density (summed up PertMixed must be zero!) 3960 //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); 3961 if (*SuperStop != 1) 3962 *SuperStop = CheckCPULIM(P); 3963 *Stop = CalculateMinimumStop(P, *SuperStop); 3964 P->Speed.Steps++; // step on 3965 R->LevS->Step++; 3966 } 3967 // now release normalization condition and minimize wrt to norm 3968 *Stop = 0; 3969 while (*Stop != 1) { 3970 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo]; 3971 iter = 0; 3972 status = 0; 3973 m = 1.; 3974 a = 0.001; 3975 b = 10.; 3976 f_a = perturbed_function (a, P); 3977 f_b = perturbed_function (b, P); 3978 f_m = perturbed_function (m, P); 3979 if ((f_m < f_a) && (f_m < f_b)) { 3980 gsl_min_fminimizer_set (s, &F, m, a, b); 3981 do { // look for minimum along current local psi 3982 iter++; 3983 status = gsl_min_fminimizer_iterate (s); 3984 m = gsl_min_fminimizer_x_minimum (s); 3985 a = gsl_min_fminimizer_x_lower (s); 3986 b = gsl_min_fminimizer_x_upper (s); 3987 status = gsl_min_test_interval (a, b, 0.001, 0.0); 3988 if (status == GSL_SUCCESS) 3989 printf ("Minimum found at:\n"); 3990 printf ("%5d [%.7f, %.7f] %.7f %.7f\n", 3991 (int) iter, a, b, 3992 m, b - a); 3993 } while (status == GSL_CONTINUE && iter < 100); 3994 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]); 3995 for (i=0; i< n; i++) { 3996 currentPsi[i].re *= m/old_norm; // real part 3997 currentPsi[i].im *= m/old_norm; // imaginary part 3998 } 3999 } 4000 P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi 4001 //debug(P,"UpdateActualPsiNo"); 4002 UpdateActualPsiNo(P, type); // step on to next perturbed Psi 4003 if (*SuperStop != 1) 4004 *SuperStop = CheckCPULIM(P); 4005 *Stop = CalculateMinimumStop(P, *SuperStop); 4006 P->Speed.Steps++; // step on 4007 R->LevS->Step++; 4008 } 4009 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Write %s srcpsi to disk\n", P->Par.me, R->MinimisationName[type]); 4010 OutputSrcPsiDensity(P, type); 4011 // if (!TestReadnWriteSrcDensity(P,type)) 4012 // Error(SomeError,"TestReadnWriteSrcDensity failed!"); 4013 } 4014 4015 TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal? 4016 // calculate current density summands 4017 //if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Filling current density grid ...\n",P->Par.me); 4018 SpeedMeasure(P, CurrDensTime, StartTimeDo); 4019 if (*SuperStop != 1) { 4020 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 4021 R->DoFullCurrent = 1; // set to 1 if it was 2 but Check...() yielded necessity 4022 //debug(P,"Filling with Delta j ..."); 4023 //FillDeltaCurrentDensity(P); 4024 }// else 4025 //debug(P,"There is no overlap between orbitals."); 4026 //debug(P,"Filling with j ..."); 4027 FillCurrentDensity(P); 4028 } 4029 SpeedMeasure(P, CurrDensTime, StopTimeDo); 4030 4031 SetGramSchExtraPsi(P,Psi,NotUsedToOrtho); // remove extra Psis from orthogonality check 4032 ResetGramSchTagType(P, Psi, type, NotUsedToOrtho); // remove this group from the check for the next minimisation group as well! 4033 } 4034 UpdateActualPsiNo(P, Occupied); // step on back to an occupied one 4035 4036 gsl_multimin_fdfminimizer_free (s_multi); 4037 gsl_min_fminimizer_free (s); 4038 gsl_vector_free (x); 4039 //gsl_vector_free (ss); 4040 } 4041 */
Note:
See TracChangeset
for help on using the changeset viewer.