Beispiel #1
0
void test_functional(int functional)
{
  xc_func_type func;
  const xc_func_info_type *info;
  int i, j, k, p_max[6][5];
  double max_diff[6][5], avg_diff[6][5], val[5];

#if defined(HAVE_FEENABLEEXCEPT)
  feenableexcept(FE_INVALID | FE_OVERFLOW);
#endif

  /* initialize functional */
  if(xc_func_init(&func, functional, nspin) != 0){
    fprintf(stderr, "Functional '%d' not found\n", functional);
    exit(1);    
  }

  info = func.info;

  if(functional == XC_LDA_C_2D_PRM)
    xc_lda_c_2d_prm_set_params(&func, 10.0);
  
  for(k=0; k<6; k++)
    for(j=0; j<5; j++){
      avg_diff[k][j] = 0.0;
      
      p_max[k][j]    = 0;
      max_diff[k][j] = -1.0;
    }

  for(i=0; xc_trial_points[i][0]!=0.0; i++){
    double e, v_fd[5], f_fd[5][5], v_an[5], f_an[5][5];

    for(j=0; j<5; j++)
      v_fd[j] = v_an[j] = 0.0;

    get_val(xc_trial_points[i], val);

    /* first, get the analytic gradients */
    get_vxc(&func, val, &e, v_an);

    /* now get the numerical gradients */
    first_derivative(&func, val, v_fd, 0);

    if(info->flags & XC_FLAGS_HAVE_FXC){
      int i, j;
      
      /* initialize */
      for(i=0; i<5; i++)
	for(j=0; j<5; j++)
	  f_an[i][j] = f_fd[i][j] = 0.0;

      /* now get the second derivatives */
      second_derivatives(&func, val, f_fd);
      get_fxc(&func, val, f_an);
    }

    /* make statistics */
    for(j=0; j<5; j++){
      double diff = fabs(v_an[j] - v_fd[j]);

      /* do not test in case of spin unpolarized or if spin down is zero */
      if((nspin==1 || val[1]==0.0) && (j!=0 && j!=2))
	continue;

      avg_diff[0][j] += diff;
      if(diff > max_diff[0][j]){
	max_diff[0][j] = diff;
	p_max[0][j] = i;
      }

      if(info->flags & XC_FLAGS_HAVE_FXC){
	for(k=0; k<5; k++){
	  /* do not test in case of spin unpolarized or if spin down is zero */
	  if((nspin==1 || val[1]==0.0) && (k!=0 && k!=2))
	    continue;

	  diff = fabs(f_an[k][j] - f_fd[k][j]);

	  avg_diff[k+1][j] += diff;
	  if(diff > max_diff[k+1][j]){
	    max_diff[k+1][j] = diff;
	    p_max[k+1][j] = i;
	  }
	}
      }
    }

  }

  for(k=0; k<6; k++)
    for(j=0; j<5; j++){
      avg_diff[k][j] /= i;
    }

  /* print statistics */
  {
    double diff;
    int i, j;

    printf("Functional: %s\n", info->name);
    print_error("Avg.", "vrho", (avg_diff[0][0] + avg_diff[0][1])/2.0, NULL, NULL);
    j = (max_diff[0][0] > max_diff[0][1]) ? 0 : 1;
    get_val(xc_trial_points[p_max[0][j]], val);
    print_error("Max.", "vrho", max_diff[0][j], &func, val);

    if(info->family > XC_FAMILY_LDA){
      print_error("Avg.", "vsig", (avg_diff[0][2] + avg_diff[0][3] + avg_diff[0][4])/3.0, NULL, NULL);
      j = (max_diff[0][2] > max_diff[0][3]) ? 2 : 3;
      j = (max_diff[0][j] > max_diff[0][4]) ? j : 4;
      get_val(xc_trial_points[p_max[0][j]], val);
      print_error("Max.", "vsig", max_diff[0][j], &func, val);
    }

    if(info->flags & XC_FLAGS_HAVE_FXC){
      diff = avg_diff[1][0] + avg_diff[1][1] + avg_diff[2][1];
      diff = diff/3.0;
      print_error("Avg.", "v2rho2", diff, NULL, NULL);
      if(max_diff[1][0] > max_diff[1][1]) {i=1; j=0;} else {i=1; j=1;}
      if(max_diff[2][1] > max_diff[i][j]) {i=2; j=1;}
      get_val(xc_trial_points[p_max[i][j]], val);
      print_error("Max.", "v2rho2", max_diff[i][j], &func, val);

      if(info->family > XC_FAMILY_LDA){
	diff = avg_diff[3][0] + avg_diff[4][0] + avg_diff[5][0] + avg_diff[3][1] + avg_diff[4][1] + avg_diff[5][1];
	diff = diff/6.0;
	print_error("Avg.", "v2rhosig", diff, NULL, NULL);
	if(max_diff[3][0] > max_diff[4][0]) {i=3; j=0;} else {i=4; j=0;}
	if(max_diff[5][0] > max_diff[i][j]) {i=5; j=0;}
	if(max_diff[3][1] > max_diff[i][j]) {i=3; j=1;}
	if(max_diff[4][1] > max_diff[i][j]) {i=4; j=1;}
	if(max_diff[5][1] > max_diff[i][j]) {i=5; j=1;}
	get_val(xc_trial_points[p_max[i][j]], val);
	print_error("Max.", "v2rhosig", max_diff[i][j], &func, val);

	diff = avg_diff[3][2] + avg_diff[4][2] + avg_diff[5][2] + avg_diff[4][3] + avg_diff[5][3] + avg_diff[5][4];
	diff = diff/6.0;
	print_error("Avg.", "v2sig2", diff, NULL, NULL);
	if(max_diff[3][2] > max_diff[4][2]) {i=3; j=2;} else {i=4; j=2;}
	if(max_diff[5][2] > max_diff[i][j]) {i=5; j=2;}
	if(max_diff[4][3] > max_diff[i][j]) {i=4; j=3;}
	if(max_diff[5][3] > max_diff[i][j]) {i=5; j=3;}
	if(max_diff[5][4] > max_diff[i][j]) {i=5; j=4;}
	get_val(xc_trial_points[p_max[i][j]], val);
	print_error("Max.", "v2sig2", max_diff[i][j], &func, val);
      }
    }
  }

  xc_func_end(&func);
}
void test_functional(int functional)
{
  functionals_type func;
  const xc_func_info_type *info;
  int i, j, k, p_max[6][5];
  double max_diff[6][5], avg_diff[6][5], val[5];

  /* initialize functional */
  func.family = xc_family_from_id(functional);
  switch(func.family)
    {
    case XC_FAMILY_LDA:
      if(functional == XC_LDA_X)
	xc_lda_x_init(&(func.lda_func), nspin, 3, 0);
      else
	xc_lda_init(&(func.lda_func), functional, nspin);

      if(functional == XC_LDA_C_2D_PRM)
	xc_lda_c_2d_prm_set_params(&(func.lda_func), 10.0);

      info = func.lda_func.info;
      break;
    case XC_FAMILY_GGA:
      xc_gga_init(&(func.gga_func), functional, nspin);

      info = func.gga_func.info;
      break;
    case XC_FAMILY_HYB_GGA:
      xc_hyb_gga_init(&(func.hyb_gga_func), functional, nspin);

      info = func.hyb_gga_func.info;
      break;
    default:
      fprintf(stderr, "Functional '%d' not found\n", functional);
      exit(1);
    }
  
  for(k=0; k<6; k++)
    for(j=0; j<5; j++){
      avg_diff[k][j] = 0.0;
      
      p_max[k][j]    = 0;
      max_diff[k][j] = -1.0;
    }

  for(i=0; xc_trial_points[i][0]!=0.0; i++){
    double e, v_fd[5], f_fd[5][5], v_an[5], f_an[5][5];

    for(j=0; j<5; j++)
      v_fd[j] = v_an[j] = 0.0;

    get_val(xc_trial_points[i], val);

    /* first, get the analitic gradients */
    get_vxc(&func, val, &e, v_an);

    /* now get the numerical gradients */
    first_derivative(&func, val, v_fd, 0);

    if(info->provides & XC_PROVIDES_FXC){
      int i, j;
      
      /* initialize */
      for(i=0; i<5; i++)
	for(j=0; j<5; j++)
	  f_an[i][j] = f_fd[i][j] = 0.0;

      /* now get the second derivatives */
      second_derivatives(&func, val, f_fd);
      get_fxc(&func, val, f_an);
    }

    /* make statistics */
    for(j=0; j<5; j++){
      double diff = fabs(v_an[j] - v_fd[j]);

      /* do not test in case of spin unpolarized or if spin down is zero */
      if((nspin==1 || val[1]==0.0) && (j!=0 && j!=2))
	continue;

      avg_diff[0][j] += diff;
      if(diff > max_diff[0][j]){
	max_diff[0][j] = diff;
	p_max[0][j] = i;
      }

      if(info->provides & XC_PROVIDES_FXC){
	for(k=0; k<5; k++){
	  /* do not test in case of spin unpolarized or if spin down is zero */
	  if((nspin==1 || val[1]==0.0) && (k!=0 && k!=2))
	    continue;

	  diff = fabs(f_an[k][j] - f_fd[k][j]);

	  avg_diff[k+1][j] += diff;
	  if(diff > max_diff[k+1][j]){
	    max_diff[k+1][j] = diff;
	    p_max[k+1][j] = i;
	  }
	}
      }
    }

  }

  for(k=0; k<6; k++)
    for(j=0; j<5; j++){
      avg_diff[k][j] /= i;
    }

  /* print statistics */
  {
    double diff;
    int i, j;

    printf("Functional: %s\n", info->name);
    print_error("Avg.", "vrho", (avg_diff[0][0] + avg_diff[0][1])/2.0, NULL, NULL);
    j = (max_diff[0][0] > max_diff[0][1]) ? 0 : 1;
    get_val(xc_trial_points[p_max[0][j]], val);
    print_error("Max.", "vrho", max_diff[0][j], &func, val);

    if(func.family > XC_FAMILY_LDA){
      print_error("Avg.", "vsig", (avg_diff[0][2] + avg_diff[0][3] + avg_diff[0][4])/3.0, NULL, NULL);
      j = (max_diff[0][2] > max_diff[0][3]) ? 2 : 3;
      j = (max_diff[0][j] > max_diff[0][4]) ? j : 4;
      get_val(xc_trial_points[p_max[0][j]], val);
      print_error("Max.", "vsig", max_diff[0][j], &func, val);
    }

    if(info->provides & XC_PROVIDES_FXC){
      diff = avg_diff[1][0] + avg_diff[1][1] + avg_diff[2][1];
      diff = diff/3.0;
      print_error("Avg.", "v2rho2", diff, NULL, NULL);
      if(max_diff[1][0] > max_diff[1][1]) {i=1; j=0;} else {i=1; j=1;}
      if(max_diff[2][1] > max_diff[i][j]) {i=2; j=1;}
      get_val(xc_trial_points[p_max[i][j]], val);
      print_error("Max.", "v2rho2", max_diff[i][j], &func, val);

      if(func.family > XC_FAMILY_LDA){
	diff = avg_diff[3][0] + avg_diff[4][0] + avg_diff[5][0] + avg_diff[3][1] + avg_diff[4][1] + avg_diff[5][1];
	diff = diff/6.0;
	print_error("Avg.", "v2rhosig", diff, NULL, NULL);
	if(max_diff[3][0] > max_diff[4][0]) {i=3; j=0;} else {i=4; j=0;}
	if(max_diff[5][0] > max_diff[i][j]) {i=5; j=0;}
	if(max_diff[3][1] > max_diff[i][j]) {i=3; j=1;}
	if(max_diff[4][1] > max_diff[i][j]) {i=4; j=1;}
	if(max_diff[5][1] > max_diff[i][j]) {i=5; j=1;}
	get_val(xc_trial_points[p_max[i][j]], val);
	print_error("Max.", "v2rhosig", max_diff[i][j], &func, val);

	diff = avg_diff[3][2] + avg_diff[4][2] + avg_diff[5][2] + avg_diff[4][3] + avg_diff[5][3] + avg_diff[5][4];
	diff = diff/6.0;
	print_error("Avg.", "v2sig2", diff, NULL, NULL);
	if(max_diff[3][2] > max_diff[4][2]) {i=3; j=2;} else {i=4; j=2;}
	if(max_diff[5][2] > max_diff[i][j]) {i=5; j=2;}
	if(max_diff[4][3] > max_diff[i][j]) {i=4; j=3;}
	if(max_diff[5][3] > max_diff[i][j]) {i=5; j=3;}
	if(max_diff[5][4] > max_diff[i][j]) {i=5; j=4;}
	get_val(xc_trial_points[p_max[i][j]], val);
	print_error("Max.", "v2sig2", max_diff[i][j], &func, val);
      }
    }
  }
}