Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from numpy import einsum, triu_indices, zeros 

2from scipy.special import comb 

3 

4from mango.constants import c, asciistring 

5from mango.position import Communal, energy 

6from mango.boundaries import periodic 

7from mango.debug import debug 

8 

9 

10@debug(['energy']) 

11def conserv(e, pos, mom, mag, dist_matrix, dist, mass): 

12 """Calculate the energy of the system and its CoM and CoM momentum.""" 

13 # TODO 

14 # fix for proper array sizes (stats, multiple iterations) 

15 invmass = 1 / mass 

16 

17 CoM = einsum("aij, i, i -> aj", pos, mass, invmass) / pos.shape[0] 

18 

19 CoM_vel = einsum("aij, i -> aj", mom, invmass) 

20 

21 einsum('xyz, aix, aiy -> az', c.eijk, pos - CoM[:, None], mom, out=e.angular) # May fail due to CoM dimensions differ from pos 

22 

23 einsum("aij -> aj", mag, out=e.tmag) # unit: 1.e-12 emu 

24 

25 e.tot[:] = e.angular + e.tmag / c.GBARE 

26 

27 ekin_m = einsum("aij -> ai", 0.5 * einsum("aiz, i -> aiz", einsum("aiz, aiz -> aiz", mom, mom), invmass)) 

28 

29 ekin = einsum("ai -> a", ekin_m) 

30 

31 e.energy_vars(dist_matrix) 

32 e.vv_trans() 

33 

34 epot1_m = e.epot_tr 

35 epot2_m = e.vv_mag(mag, dist) 

36 

37 dims = ''.join(asciistring(epot1_m.ndim)) 

38 estr = '{} -> {}'.format(dims, dims[:-1]) 

39 

40 epot1 = einsum(estr, epot1_m) 

41 

42 epot2 = einsum(estr, epot2_m) 

43 

44 etot = ekin + epot1 + epot2 

45 

46 return {"total_M": e.tot, "total_mag": e.tmag, "total_angular": e.angular, 

47 "kinetic": ekin, "trans_pot": epot1, "mag_pot": epot2, 

48 "total_E": etot, "CoM": CoM, "CoM_vel": CoM_vel, 

49 "ekin_pm": ekin_m, 'trans_pot_pm': epot1_m, 'mag_pot_pm': epot2_m} 

50 

51 

52def energy_calc(pos, mom, mag, epsilon, sigma, limit, mass): 

53 """Direct energy calculation.""" 

54 nm = pos.shape[-2] 

55 tri = triu_indices(n=nm, k=1) 

56 cmb = (pos.shape[0], comb(nm, 2, exact=True)) 

57 dist, dist_matrix = periodic().setup_full(pos) 

58 e = energy(Communal(epsilon, sigma, tri, cmb, limit), singleframe=False) 

59 e.set_attr(['tot', 'tmag', 'angular'], zeros((pos.shape[0], 3))) 

60 

61 return conserv(e, pos, mom, mag, dist_matrix, dist, mass) 

62 

63 

64def get_eandm(reader, var, name=None): 

65 """Help function for getting energy and momenta data.""" 

66 return energy_calc(reader.read('position', name)[:var.skip_iters], 

67 reader.read("momentum", name)[:var.skip_iters], 

68 reader.read("magnetisation", name)[:var.skip_iters], 

69 var.epsilon, var.sigma, var.limit, var.mass)