/gpaw/test/poisson/test_poisson_extravacuum.py

https://gitlab.com/asod/gpaw
Python | 178 lines | 135 code | 30 blank | 13 comment | 17 complexity | 5202d3077c4980a72f68582ca7cdf437 MD5 | raw file
  1. import pytest
  2. from gpaw.mpi import world
  3. import time
  4. import numpy as np
  5. from gpaw.poisson import PoissonSolver
  6. from gpaw.poisson_extended import ExtendedPoissonSolver
  7. from gpaw.poisson_extravacuum import ExtraVacuumPoissonSolver
  8. from gpaw.grid_descriptor import GridDescriptor
  9. pytestmark = pytest.mark.skipif(world.size > 4,
  10. reason='world.size > 4')
  11. def test_poisson_poisson_extravacuum():
  12. do_output = False
  13. do_plot = False
  14. poissoneps = 1e-16
  15. if do_output:
  16. def equal(x, y, tol=0):
  17. res = {True: 'ok', False: 'not ok'}[abs(x - y) < tol]
  18. print('%.10e vs %.10e at %.10e is %s' % (x, y, tol, res))
  19. else:
  20. from gpaw.test import equal
  21. # Model grid
  22. N = 16
  23. N_c = np.array((1, 1, 3)) * N
  24. cell_c = N_c / float(N)
  25. gd = GridDescriptor(N_c, cell_c, False)
  26. # Construct model density
  27. coord_vg = gd.get_grid_point_coordinates()
  28. x_g = coord_vg[0, :]
  29. y_g = coord_vg[1, :]
  30. z_g = coord_vg[2, :]
  31. rho_g = gd.zeros()
  32. for z0 in [1, 2]:
  33. rho_g += 10 * (z_g - z0) * \
  34. np.exp(-20 * np.sum((coord_vg.T - np.array([.5, .5, z0])).T**2,
  35. axis=0))
  36. if do_plot:
  37. big_rho_g = gd.collect(rho_g)
  38. if gd.comm.rank == 0:
  39. import matplotlib.pyplot as plt
  40. fig, ax_ij = plt.subplots(3, 4, figsize=(20, 10))
  41. ax_i = ax_ij.ravel()
  42. ploti = 0
  43. Ng_c = gd.get_size_of_global_array()
  44. plt.sca(ax_i[ploti])
  45. ploti += 1
  46. plt.pcolormesh(big_rho_g[Ng_c[0] / 2])
  47. plt.sca(ax_i[ploti])
  48. ploti += 1
  49. plt.plot(big_rho_g[Ng_c[0] / 2, Ng_c[1] / 2])
  50. def plot_phi(phi_g):
  51. if do_plot:
  52. big_phi_g = gd.collect(phi_g)
  53. if gd.comm.rank == 0:
  54. global ploti
  55. if ploti == 4:
  56. ploti -= 2
  57. plt.sca(ax_i[ploti])
  58. ploti += 1
  59. plt.pcolormesh(big_phi_g[Ng_c[0] / 2])
  60. plt.sca(ax_i[ploti])
  61. ploti += 1
  62. plt.plot(big_phi_g[Ng_c[0] / 2, Ng_c[1] / 2])
  63. plt.ylim(np.array([-1, 1]) * 0.15)
  64. def poisson_solve(gd, rho_g, poisson):
  65. phi_g = gd.zeros()
  66. rho_g = rho_g
  67. t0 = time.time()
  68. npoisson = poisson.solve(phi_g, rho_g)
  69. t1 = time.time()
  70. if do_output:
  71. if gd.comm.rank == 0:
  72. print('Iterations: %s, Time: %.3f s' % (str(npoisson), t1 - t0))
  73. return phi_g, npoisson
  74. def poisson_init_solve(gd, rho_g, poisson):
  75. poisson.set_grid_descriptor(gd)
  76. phi_g, npoisson = poisson_solve(gd, rho_g, poisson)
  77. plot_phi(phi_g)
  78. return phi_g, npoisson
  79. def compare(phi1_g, phi2_g, val, eps=np.sqrt(poissoneps)):
  80. big_phi1_g = gd.collect(phi1_g)
  81. big_phi2_g = gd.collect(phi2_g)
  82. if gd.comm.rank == 0:
  83. diff = np.max(np.absolute(big_phi1_g - big_phi2_g))
  84. else:
  85. diff = 0.0
  86. diff = np.array([diff])
  87. gd.comm.broadcast(diff, 0)
  88. equal(diff[0], val, eps)
  89. # Get reference from default poissonsolver
  90. poisson = PoissonSolver('fd', eps=poissoneps)
  91. phiref_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  92. # Test agreement with default
  93. poisson = ExtraVacuumPoissonSolver(N_c, PoissonSolver('fd', eps=poissoneps))
  94. phi_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  95. compare(phi_g, phiref_g, 0.0, 1e-24)
  96. # New reference with extra vacuum
  97. gpts = N_c * 4
  98. poisson = ExtraVacuumPoissonSolver(gpts, PoissonSolver('fd', eps=poissoneps))
  99. phi_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  100. # print poisson.get_description()
  101. compare(phi_g, phiref_g, 2.6485385144e-02)
  102. phiref_g = phi_g
  103. # Compare to ExtendedPoissonSolver
  104. # TODO: remove this test when/if ExtendedPoissonSolver is deprecated
  105. poisson = ExtendedPoissonSolver(eps=poissoneps,
  106. extended={'gpts': gpts / 2,
  107. 'useprev': True})
  108. phi_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  109. compare(phi_g, phiref_g, 0.0, 1e-24)
  110. # Test with single coarsening
  111. poisson = ExtraVacuumPoissonSolver(gpts, PoissonSolver('fd', eps=poissoneps),
  112. PoissonSolver('fd', eps=poissoneps), 1)
  113. phi_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  114. compare(phi_g, phiref_g, 1.5043946611e-04)
  115. # Test with two coarsenings
  116. poisson = ExtraVacuumPoissonSolver(gpts, PoissonSolver('fd', eps=poissoneps),
  117. PoissonSolver('fd', eps=poissoneps), 2)
  118. phi_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  119. compare(phi_g, phiref_g, 1.2980906205e-03)
  120. # Test with cascaded single coarsenings
  121. poisson1 = ExtraVacuumPoissonSolver(gpts / 2,
  122. PoissonSolver('fd', eps=poissoneps),
  123. PoissonSolver('fd', eps=poissoneps), 1)
  124. poisson = ExtraVacuumPoissonSolver(gpts / 2, poisson1,
  125. PoissonSolver('fd', eps=poissoneps), 1)
  126. phi_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  127. # print poisson.get_description()
  128. compare(phi_g, phiref_g, 1.7086531461e-04)
  129. # Test auxgrid
  130. gpts = N_c * 4
  131. for coarses in [1, 2, 3]:
  132. for nn_refine in [1, 3]:
  133. for nn_laplace in [1, 3]:
  134. EVPS = ExtraVacuumPoissonSolver
  135. poisson = EVPS(gpts, PoissonSolver('fd', eps=poissoneps),
  136. PoissonSolver('fd', eps=poissoneps), coarses,
  137. use_aux_grid=False,
  138. nn_refine=nn_refine, nn_laplace=nn_laplace)
  139. phiref_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  140. poisson = EVPS(gpts, PoissonSolver('fd', eps=poissoneps),
  141. PoissonSolver('fd', eps=poissoneps), coarses,
  142. use_aux_grid=True,
  143. nn_refine=nn_refine, nn_laplace=nn_laplace)
  144. phi_g, npoisson = poisson_init_solve(gd, rho_g, poisson)
  145. compare(phi_g, phiref_g, 0.0, 1e-14)
  146. if do_plot:
  147. if gd.comm.rank == 0:
  148. plt.show()