Advertisement
mabruzzo

Untitled

Jul 30th, 2021
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.21 KB | None | 0 0
  1. #!/bin/python
  2.  
  3. # runs VLCT MHD Linear Wave Tests
  4. # - This should probably be transitioned to testing framework once it's created
  5. # - This script expects to be called from the root level of the repository
  6. # OR at the same level where its defined
  7. #
  8. # These tests draw loose inspiration from Linear Wave tests used by Athena++.
  9. # Specifically, this script:
  10. # 1.) Checks if that L1-norm of the error is appropriate for the inclined
  11. # fast wave, alfven wave, slow wave, and entropy for N=16 and N=32
  12. # 2.) Check that the L1-norm error is the same for left propagating and right
  13. # propagating fast waves
  14.  
  15. import os.path
  16. import shutil
  17. import sys
  18.  
  19. from functools import partial
  20.  
  21. import numpy as np
  22.  
  23. from testing_utils import \
  24. CalcSimL1Norm, EnzoEWrapper, isclose, standard_analyze, prep_cur_dir
  25.  
  26.  
  27. # this executes things in standalone mode
  28. l1_norm_calc_template = ("python tools/l1_error_norm.py sim {:s} {:s} -n {:d}"
  29. " -f density,velocity_x,velocity_y,velocity_z,"
  30. "pressure,bfield_x,bfield_y,bfield_z")
  31. data_dir_template = "method_vlct-{:d}-{:s}N{:d}_{:.1f}"
  32.  
  33. def run_tests(executable):
  34. temp = 'input/vlct/MHD_linear_wave/method_vlct_{}N{:d}{}.in'
  35. call_test = EnzoEWrapper(executable,temp)
  36.  
  37. call_test("fast",16,'')
  38. call_test("fast",32,'')
  39. call_test("fast",32,'_left')
  40.  
  41. call_test("alfven",16,'')
  42. call_test("alfven",32,'')
  43.  
  44. call_test("slow",16,'')
  45. call_test("slow",32,'')
  46.  
  47. call_test("entropy",16,'')
  48. call_test("entropy",32,'')
  49.  
  50. def format_pair(template, nblocks, res, wave_name, t1=0., t2=0., direction=''):
  51. # formats a pair of directory templates
  52. return (template.format(nblocks=nblocks, res=res, wave_name=wave_name,
  53. direction=direction, time=t1),
  54. template.format(nblocks=nblocks, res=res, wave_name=wave_name,
  55. direction=direction, time=t2))
  56.  
  57. def analyze_linwave(ref_l1_norm, wave_name, nblocks, res, target_template,
  58. name_template, l1_functor, final_times, verbose = False):
  59. """
  60. Both name_template and target_template are used to format strings based on
  61. other arguments with the `format` method. They should each employ named
  62. placeholders and expect `format` to be passed the following kwargs:
  63. `direction`, `wave_name`, `res`, and `nblocks`.
  64. Note that `direction` is set to ''. Additionally, target_template should
  65. also expect a `time` kwarg
  66. """
  67. common = dict(nblocks=nblocks, res=res, wave_name=wave_name, direction='')
  68. t1_dir, t2_dir = format_pair(target_template, t1 = 0.,
  69. t2 = final_times[wave_name], **common)
  70. test_case_name = '{wave_name} wave N={res}'.format(**common)
  71. functor_kwargs = dict(dir_name2 = t2_dir, res = res)
  72.  
  73. return standard_analyze(ref_l1_norm, l1_functor, target_path = t1_dir,
  74. test_case_name = test_case_name, verbose = verbose,
  75. functor_kwargs = functor_kwargs)
  76.  
  77.  
  78. # part of the following should probably be folded into standard_analyze
  79. def identical_l1_error_linwave(nblocks, wave_name, res, l1_functor, template,
  80. final_time, nblocks2 = None, prec = None,
  81. verbose = False):
  82. """
  83. Compares linear wave l1 norms that should be identical.
  84.  
  85. There are 2 main cases where this is expected:
  86. 1. Left propagation vs. right propation
  87. 2. Changing the number of blocks over which the simulation is distibuted.
  88.  
  89. Parameters
  90. ----------
  91. nblocks: int
  92. Number of blocks over which the primary simulation's grid is divided
  93. wave_name: string
  94. The wave type - "fast", "slow", "alfven", "entropy"
  95. res: int
  96. The resolution of the simulation. For linear waves, a value of N
  97. implies (2N,N,N) for (x,y,z).
  98. l1_functor : instance of CalcSimL1Norm
  99. This functor wraps the call to the l1_error_norm script.
  100. template : str
  101. Formatting this template string, should provide paths to directories
  102. holding the simulation data that are used to compute the norms of L1
  103. error vectors. The templates should used named placeholders for
  104. formatting. This function provides the following placeholders:
  105. `wave_name`, `res`, `nblocks`, `direction`, and `time`
  106. The first 3 placeholders will be substituted with the appropriate
  107. values passed by this function. The `direction` placeholder will only
  108. be substituted with `''` or `'-left'`. Finally, the `time` placeholder
  109. will be substituted by `0.0` and the value returned by
  110. `final_time[wave_type]`
  111. final_time : float
  112. The time at which the simulation of the wave ends
  113. nblocks2: int, optional
  114. Number of blocks over which the secondary simulation's grid is divided.
  115. If this value is not specified, then the number of blocks are assumed
  116. to be the same. In this case, the wave in the primary (secondary)
  117. simulation is assumed to propagate rightwards (leftwards)
  118. prec: int, optional
  119. Number of digits after the decimal that must match. Athena++
  120. traditionally just compares 6. If this is passed None (default), then
  121. all digits are compared.
  122. verbose : bool, optional
  123. If true, prints note about tests that have passed
  124. """
  125.  
  126. fmt_kwargs = dict(nblocks = nblocks, res = res, wave_name = wave_name,
  127. t1 = 0., t2 = final_time, direction = '')
  128. t0_dir,tf_dir = format_pair(template, **fmt_kwargs)
  129. ref_norm = l1_functor(t0_dir,tf_dir,res)
  130.  
  131. if nblocks2 is None:
  132. fmt_kwargs['direction'] = '-left'
  133. insert = 'right & left propagating {wave} waves'
  134. else:
  135. fmt_kwargs['nblocks'] = nblocks2
  136. insert = "{wave} waves split over {nblocks} and {nblocks2} blocks"
  137.  
  138. t0_dir,tf_dir = format_pair(template, **fmt_kwargs)
  139. comp_norm = l1_functor(t0_dir,tf_dir,res)
  140.  
  141. msg = None
  142. if prec is not None:
  143. ref_norm = '{:.{prec}e}'.format(ref_norm, prec=prec)
  144. comp_norm = '{:.{prec}e}'.format(comp_norm, prec=prec)
  145. passed = (ref_norm == comp_norm)
  146. if not passed:
  147. msg = "FAILED: L1 norms of " + insert + " don't match\n{ref} {comp}"
  148. elif verbose:
  149. msg = "PASSED: L1 norms of " + insert + " are both {ref}"
  150.  
  151. if msg is not None:
  152. print(msg.format(nblocks=nblocks, nblocks2=nblocks2, wave = wave_name,
  153. ref=repr(ref_norm), comp=repr(comp_norm)))
  154. return passed
  155.  
  156. def analyze_tests():
  157. # define the functor for evaluating the norm of the L1 error vector
  158. l1_func = CalcSimL1Norm("tools/l1_error_norm.py",
  159. ["density","velocity_x","velocity_y","velocity_z",
  160. "pressure","bfield_x","bfield_y","bfield_z"])
  161.  
  162. # define the template for the directory holding the simulation data
  163. template = "method_vlct-{nblocks}-{wave_name}N{res}{direction}_{time:.1f}"
  164.  
  165. final_times = {"fast" : 0.5, "alfven" : 1.0, "entropy" : 1.0, "slow" : 2.0}
  166.  
  167. err_compare = partial(analyze_linwave, target_template = template,
  168. name_template = '{wave_name} wave N={res}',
  169. l1_functor = l1_func, final_times = final_times,
  170. verbose = False)
  171.  
  172. r = []
  173. # first let's run the l1-norm of each value for 2 sizes to make sure we get
  174. # convergence (originally we were looking at the slope of convergence but
  175. # that allows the errors to be larger)
  176.  
  177. r.append(err_compare(1.697471230863441e-07, 'fast', 1, 16))
  178. r.append(err_compare(3.480274599766741e-08, 'fast', 1, 32))
  179.  
  180. r.append(err_compare(1.935556465271203e-07, 'alfven', 1, 16))
  181. r.append(err_compare(3.0278629262809005e-08, 'alfven', 1, 32))
  182.  
  183. r.append(err_compare(2.2380963049488006e-07, 'slow', 1, 16))
  184. r.append(err_compare(4.4210724002651586e-08, 'slow', 1, 32))
  185.  
  186. r.append(err_compare(1.0021263485338544e-07, 'entropy', 1, 16))
  187. r.append(err_compare(2.9194839706868883e-08, 'entropy', 1, 32))
  188.  
  189. # Check error between left and right propagating waves
  190. print("The following test has never passed in the history of this "
  191. "implementation")
  192. r.append(identical_l1_error_linwave(1, 'fast', 32, l1_func, template, 0.5,
  193. verbose = True))
  194.  
  195. n_passed = np.sum(r)
  196. n_tests = len(r)
  197. success = (n_passed == n_tests)
  198. print("{:d} Tests passed out of {:d} Tests.".format(n_passed,n_tests))
  199. if (np.sum(r) == (n_tests-1)):
  200. print("All tests that the this VL+CT implementation has ever passed, "
  201. "have suceeded")
  202. success = True
  203. return success
  204.  
  205. def cleanup():
  206.  
  207. dir_names = ["method_vlct-1-fastN16_0.0",
  208. "method_vlct-1-fastN16_0.5",
  209. "method_vlct-1-fastN32_0.0",
  210. "method_vlct-1-fastN32_0.5",
  211. "method_vlct-1-fastN32-left_0.0",
  212. "method_vlct-1-fastN32-left_0.5",
  213. "method_vlct-1-alfvenN16_0.0",
  214. "method_vlct-1-alfvenN16_1.0",
  215. "method_vlct-1-alfvenN32_0.0",
  216. "method_vlct-1-alfvenN32_1.0",
  217. "method_vlct-1-slowN16_0.0",
  218. "method_vlct-1-slowN16_2.0",
  219. "method_vlct-1-slowN32_0.0",
  220. "method_vlct-1-slowN32_2.0",
  221. "method_vlct-1-entropyN16_0.0",
  222. "method_vlct-1-entropyN16_1.0",
  223. "method_vlct-1-entropyN32_0.0",
  224. "method_vlct-1-entropyN32_1.0"]
  225.  
  226. for dir_name in dir_names:
  227. if os.path.isdir(dir_name):
  228. shutil.rmtree(dir_name)
  229.  
  230. if __name__ == '__main__':
  231.  
  232. executable = 'bin/enzo-e'
  233.  
  234. # this script can either be called from the base repository or from
  235. # the subdirectory: input/vlct
  236. prep_cur_dir(executable)
  237.  
  238. # run the tests
  239. tests_complete = run_tests(executable)
  240.  
  241. # analyze the tests
  242. tests_passed = analyze_tests()
  243.  
  244. # cleanup the tests
  245. cleanup()
  246.  
  247. if tests_passed:
  248. sys.exit(0)
  249. else:
  250. sys.exit(3)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement