test_tensor.py 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218
  1. from sympy.concrete.summations import Sum
  2. from sympy.core.function import expand
  3. from sympy.core.numbers import Integer
  4. from sympy.matrices.dense import (Matrix, eye)
  5. from sympy.tensor.indexed import Indexed
  6. from sympy.combinatorics import Permutation
  7. from sympy.core import S, Rational, Symbol, Basic, Add, Wild, Function
  8. from sympy.core.containers import Tuple
  9. from sympy.core.symbol import symbols
  10. from sympy.functions.elementary.miscellaneous import sqrt
  11. from sympy.integrals import integrate
  12. from sympy.tensor.array import Array
  13. from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorSymmetry, \
  14. get_symmetric_group_sgs, TensorIndex, tensor_mul, TensAdd, \
  15. riemann_cyclic_replace, riemann_cyclic, TensMul, tensor_heads, \
  16. TensorManager, TensExpr, TensorHead, canon_bp, \
  17. tensorhead, tensorsymmetry, TensorType, substitute_indices, \
  18. WildTensorIndex, WildTensorHead, _WildTensExpr
  19. from sympy.testing.pytest import raises, XFAIL, warns_deprecated_sympy
  20. from sympy.matrices import diag
  21. def _is_equal(arg1, arg2):
  22. if isinstance(arg1, TensExpr):
  23. return arg1.equals(arg2)
  24. elif isinstance(arg2, TensExpr):
  25. return arg2.equals(arg1)
  26. return arg1 == arg2
  27. #################### Tests from tensor_can.py #######################
  28. def test_canonicalize_no_slot_sym():
  29. # A_d0 * B^d0; T_c = A^d0*B_d0
  30. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  31. a, b, d0, d1 = tensor_indices('a,b,d0,d1', Lorentz)
  32. A, B = tensor_heads('A,B', [Lorentz], TensorSymmetry.no_symmetry(1))
  33. t = A(-d0)*B(d0)
  34. tc = t.canon_bp()
  35. assert str(tc) == 'A(L_0)*B(-L_0)'
  36. # A^a * B^b; T_c = T
  37. t = A(a)*B(b)
  38. tc = t.canon_bp()
  39. assert tc == t
  40. # B^b * A^a
  41. t1 = B(b)*A(a)
  42. tc = t1.canon_bp()
  43. assert str(tc) == 'A(a)*B(b)'
  44. # A symmetric
  45. # A^{b}_{d0}*A^{d0, a}; T_c = A^{a d0}*A{b}_{d0}
  46. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  47. t = A(b, -d0)*A(d0, a)
  48. tc = t.canon_bp()
  49. assert str(tc) == 'A(a, L_0)*A(b, -L_0)'
  50. # A^{d1}_{d0}*B^d0*C_d1
  51. # T_c = A^{d0 d1}*B_d0*C_d1
  52. B, C = tensor_heads('B,C', [Lorentz], TensorSymmetry.no_symmetry(1))
  53. t = A(d1, -d0)*B(d0)*C(-d1)
  54. tc = t.canon_bp()
  55. assert str(tc) == 'A(L_0, L_1)*B(-L_0)*C(-L_1)'
  56. # A without symmetry
  57. # A^{d1}_{d0}*B^d0*C_d1 ord=[d0,-d0,d1,-d1]; g = [2,1,0,3,4,5]
  58. # T_c = A^{d0 d1}*B_d1*C_d0; can = [0,2,3,1,4,5]
  59. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.no_symmetry(2))
  60. t = A(d1, -d0)*B(d0)*C(-d1)
  61. tc = t.canon_bp()
  62. assert str(tc) == 'A(L_0, L_1)*B(-L_1)*C(-L_0)'
  63. # A, B without symmetry
  64. # A^{d1}_{d0}*B_{d1}^{d0}
  65. # T_c = A^{d0 d1}*B_{d0 d1}
  66. B = TensorHead('B', [Lorentz]*2, TensorSymmetry.no_symmetry(2))
  67. t = A(d1, -d0)*B(-d1, d0)
  68. tc = t.canon_bp()
  69. assert str(tc) == 'A(L_0, L_1)*B(-L_0, -L_1)'
  70. # A_{d0}^{d1}*B_{d1}^{d0}
  71. # T_c = A^{d0 d1}*B_{d1 d0}
  72. t = A(-d0, d1)*B(-d1, d0)
  73. tc = t.canon_bp()
  74. assert str(tc) == 'A(L_0, L_1)*B(-L_1, -L_0)'
  75. # A, B, C without symmetry
  76. # A^{d1 d0}*B_{a d0}*C_{d1 b}
  77. # T_c=A^{d0 d1}*B_{a d1}*C_{d0 b}
  78. C = TensorHead('C', [Lorentz]*2, TensorSymmetry.no_symmetry(2))
  79. t = A(d1, d0)*B(-a, -d0)*C(-d1, -b)
  80. tc = t.canon_bp()
  81. assert str(tc) == 'A(L_0, L_1)*B(-a, -L_1)*C(-L_0, -b)'
  82. # A symmetric, B and C without symmetry
  83. # A^{d1 d0}*B_{a d0}*C_{d1 b}
  84. # T_c = A^{d0 d1}*B_{a d0}*C_{d1 b}
  85. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  86. t = A(d1, d0)*B(-a, -d0)*C(-d1, -b)
  87. tc = t.canon_bp()
  88. assert str(tc) == 'A(L_0, L_1)*B(-a, -L_0)*C(-L_1, -b)'
  89. # A and C symmetric, B without symmetry
  90. # A^{d1 d0}*B_{a d0}*C_{d1 b} ord=[a,b,d0,-d0,d1,-d1]
  91. # T_c = A^{d0 d1}*B_{a d0}*C_{b d1}
  92. C = TensorHead('C', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  93. t = A(d1, d0)*B(-a, -d0)*C(-d1, -b)
  94. tc = t.canon_bp()
  95. assert str(tc) == 'A(L_0, L_1)*B(-a, -L_0)*C(-b, -L_1)'
  96. def test_canonicalize_no_dummies():
  97. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  98. a, b, c, d = tensor_indices('a, b, c, d', Lorentz)
  99. # A commuting
  100. # A^c A^b A^a
  101. # T_c = A^a A^b A^c
  102. A = TensorHead('A', [Lorentz], TensorSymmetry.no_symmetry(1))
  103. t = A(c)*A(b)*A(a)
  104. tc = t.canon_bp()
  105. assert str(tc) == 'A(a)*A(b)*A(c)'
  106. # A anticommuting
  107. # A^c A^b A^a
  108. # T_c = -A^a A^b A^c
  109. A = TensorHead('A', [Lorentz], TensorSymmetry.no_symmetry(1), 1)
  110. t = A(c)*A(b)*A(a)
  111. tc = t.canon_bp()
  112. assert str(tc) == '-A(a)*A(b)*A(c)'
  113. # A commuting and symmetric
  114. # A^{b,d}*A^{c,a}
  115. # T_c = A^{a c}*A^{b d}
  116. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  117. t = A(b, d)*A(c, a)
  118. tc = t.canon_bp()
  119. assert str(tc) == 'A(a, c)*A(b, d)'
  120. # A anticommuting and symmetric
  121. # A^{b,d}*A^{c,a}
  122. # T_c = -A^{a c}*A^{b d}
  123. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(2), 1)
  124. t = A(b, d)*A(c, a)
  125. tc = t.canon_bp()
  126. assert str(tc) == '-A(a, c)*A(b, d)'
  127. # A^{c,a}*A^{b,d}
  128. # T_c = A^{a c}*A^{b d}
  129. t = A(c, a)*A(b, d)
  130. tc = t.canon_bp()
  131. assert str(tc) == 'A(a, c)*A(b, d)'
  132. def test_tensorhead_construction_without_symmetry():
  133. L = TensorIndexType('Lorentz')
  134. A1 = TensorHead('A', [L, L])
  135. A2 = TensorHead('A', [L, L], TensorSymmetry.no_symmetry(2))
  136. assert A1 == A2
  137. A3 = TensorHead('A', [L, L], TensorSymmetry.fully_symmetric(2)) # Symmetric
  138. assert A1 != A3
  139. def test_no_metric_symmetry():
  140. # no metric symmetry; A no symmetry
  141. # A^d1_d0 * A^d0_d1
  142. # T_c = A^d0_d1 * A^d1_d0
  143. Lorentz = TensorIndexType('Lorentz', dummy_name='L', metric_symmetry=0)
  144. d0, d1, d2, d3 = tensor_indices('d:4', Lorentz)
  145. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.no_symmetry(2))
  146. t = A(d1, -d0)*A(d0, -d1)
  147. tc = t.canon_bp()
  148. assert str(tc) == 'A(L_0, -L_1)*A(L_1, -L_0)'
  149. # A^d1_d2 * A^d0_d3 * A^d2_d1 * A^d3_d0
  150. # T_c = A^d0_d1 * A^d1_d0 * A^d2_d3 * A^d3_d2
  151. t = A(d1, -d2)*A(d0, -d3)*A(d2, -d1)*A(d3, -d0)
  152. tc = t.canon_bp()
  153. assert str(tc) == 'A(L_0, -L_1)*A(L_1, -L_0)*A(L_2, -L_3)*A(L_3, -L_2)'
  154. # A^d0_d2 * A^d1_d3 * A^d3_d0 * A^d2_d1
  155. # T_c = A^d0_d1 * A^d1_d2 * A^d2_d3 * A^d3_d0
  156. t = A(d0, -d1)*A(d1, -d2)*A(d2, -d3)*A(d3, -d0)
  157. tc = t.canon_bp()
  158. assert str(tc) == 'A(L_0, -L_1)*A(L_1, -L_2)*A(L_2, -L_3)*A(L_3, -L_0)'
  159. def test_canonicalize1():
  160. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  161. a, a0, a1, a2, a3, b, d0, d1, d2, d3 = \
  162. tensor_indices('a,a0,a1,a2,a3,b,d0,d1,d2,d3', Lorentz)
  163. # A_d0*A^d0; ord = [d0,-d0]
  164. # T_c = A^d0*A_d0
  165. A = TensorHead('A', [Lorentz], TensorSymmetry.no_symmetry(1))
  166. t = A(-d0)*A(d0)
  167. tc = t.canon_bp()
  168. assert str(tc) == 'A(L_0)*A(-L_0)'
  169. # A commuting
  170. # A_d0*A_d1*A_d2*A^d2*A^d1*A^d0
  171. # T_c = A^d0*A_d0*A^d1*A_d1*A^d2*A_d2
  172. t = A(-d0)*A(-d1)*A(-d2)*A(d2)*A(d1)*A(d0)
  173. tc = t.canon_bp()
  174. assert str(tc) == 'A(L_0)*A(-L_0)*A(L_1)*A(-L_1)*A(L_2)*A(-L_2)'
  175. # A anticommuting
  176. # A_d0*A_d1*A_d2*A^d2*A^d1*A^d0
  177. # T_c 0
  178. A = TensorHead('A', [Lorentz], TensorSymmetry.no_symmetry(1), 1)
  179. t = A(-d0)*A(-d1)*A(-d2)*A(d2)*A(d1)*A(d0)
  180. tc = t.canon_bp()
  181. assert tc == 0
  182. # A commuting symmetric
  183. # A^{d0 b}*A^a_d1*A^d1_d0
  184. # T_c = A^{a d0}*A^{b d1}*A_{d0 d1}
  185. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  186. t = A(d0, b)*A(a, -d1)*A(d1, -d0)
  187. tc = t.canon_bp()
  188. assert str(tc) == 'A(a, L_0)*A(b, L_1)*A(-L_0, -L_1)'
  189. # A, B commuting symmetric
  190. # A^{d0 b}*A^d1_d0*B^a_d1
  191. # T_c = A^{b d0}*A_d0^d1*B^a_d1
  192. B = TensorHead('B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  193. t = A(d0, b)*A(d1, -d0)*B(a, -d1)
  194. tc = t.canon_bp()
  195. assert str(tc) == 'A(b, L_0)*A(-L_0, L_1)*B(a, -L_1)'
  196. # A commuting symmetric
  197. # A^{d1 d0 b}*A^{a}_{d1 d0}; ord=[a,b, d0,-d0,d1,-d1]
  198. # T_c = A^{a d0 d1}*A^{b}_{d0 d1}
  199. A = TensorHead('A', [Lorentz]*3, TensorSymmetry.fully_symmetric(3))
  200. t = A(d1, d0, b)*A(a, -d1, -d0)
  201. tc = t.canon_bp()
  202. assert str(tc) == 'A(a, L_0, L_1)*A(b, -L_0, -L_1)'
  203. # A^{d3 d0 d2}*A^a0_{d1 d2}*A^d1_d3^a1*A^{a2 a3}_d0
  204. # T_c = A^{a0 d0 d1}*A^a1_d0^d2*A^{a2 a3 d3}*A_{d1 d2 d3}
  205. t = A(d3, d0, d2)*A(a0, -d1, -d2)*A(d1, -d3, a1)*A(a2, a3, -d0)
  206. tc = t.canon_bp()
  207. assert str(tc) == 'A(a0, L_0, L_1)*A(a1, -L_0, L_2)*A(a2, a3, L_3)*A(-L_1, -L_2, -L_3)'
  208. # A commuting symmetric, B antisymmetric
  209. # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3
  210. # in this esxample and in the next three,
  211. # renaming dummy indices and using symmetry of A,
  212. # T = A^{d0 d1 d2} * A_{d0 d1 d3} * B_d2^d3
  213. # can = 0
  214. A = TensorHead('A', [Lorentz]*3, TensorSymmetry.fully_symmetric(3))
  215. B = TensorHead('B', [Lorentz]*2, TensorSymmetry.fully_symmetric(-2))
  216. t = A(d0, d1, d2)*A(-d2, -d3, -d1)*B(-d0, d3)
  217. tc = t.canon_bp()
  218. assert tc == 0
  219. # A anticommuting symmetric, B antisymmetric
  220. # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3
  221. # T_c = A^{d0 d1 d2} * A_{d0 d1}^d3 * B_{d2 d3}
  222. A = TensorHead('A', [Lorentz]*3, TensorSymmetry.fully_symmetric(3), 1)
  223. B = TensorHead('B', [Lorentz]*2, TensorSymmetry.fully_symmetric(-2))
  224. t = A(d0, d1, d2)*A(-d2, -d3, -d1)*B(-d0, d3)
  225. tc = t.canon_bp()
  226. assert str(tc) == 'A(L_0, L_1, L_2)*A(-L_0, -L_1, L_3)*B(-L_2, -L_3)'
  227. # A anticommuting symmetric, B antisymmetric commuting, antisymmetric metric
  228. # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3
  229. # T_c = -A^{d0 d1 d2} * A_{d0 d1}^d3 * B_{d2 d3}
  230. Spinor = TensorIndexType('Spinor', dummy_name='S', metric_symmetry=-1)
  231. a, a0, a1, a2, a3, b, d0, d1, d2, d3 = \
  232. tensor_indices('a,a0,a1,a2,a3,b,d0,d1,d2,d3', Spinor)
  233. A = TensorHead('A', [Spinor]*3, TensorSymmetry.fully_symmetric(3), 1)
  234. B = TensorHead('B', [Spinor]*2, TensorSymmetry.fully_symmetric(-2))
  235. t = A(d0, d1, d2)*A(-d2, -d3, -d1)*B(-d0, d3)
  236. tc = t.canon_bp()
  237. assert str(tc) == '-A(S_0, S_1, S_2)*A(-S_0, -S_1, S_3)*B(-S_2, -S_3)'
  238. # A anticommuting symmetric, B antisymmetric anticommuting,
  239. # no metric symmetry
  240. # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3
  241. # T_c = A^{d0 d1 d2} * A_{d0 d1 d3} * B_d2^d3
  242. Mat = TensorIndexType('Mat', metric_symmetry=0, dummy_name='M')
  243. a, a0, a1, a2, a3, b, d0, d1, d2, d3 = \
  244. tensor_indices('a,a0,a1,a2,a3,b,d0,d1,d2,d3', Mat)
  245. A = TensorHead('A', [Mat]*3, TensorSymmetry.fully_symmetric(3), 1)
  246. B = TensorHead('B', [Mat]*2, TensorSymmetry.fully_symmetric(-2))
  247. t = A(d0, d1, d2)*A(-d2, -d3, -d1)*B(-d0, d3)
  248. tc = t.canon_bp()
  249. assert str(tc) == 'A(M_0, M_1, M_2)*A(-M_0, -M_1, -M_3)*B(-M_2, M_3)'
  250. # Gamma anticommuting
  251. # Gamma_{mu nu} * gamma^rho * Gamma^{nu mu alpha}
  252. # T_c = -Gamma^{mu nu} * gamma^rho * Gamma_{alpha mu nu}
  253. alpha, beta, gamma, mu, nu, rho = \
  254. tensor_indices('alpha,beta,gamma,mu,nu,rho', Lorentz)
  255. Gamma = TensorHead('Gamma', [Lorentz],
  256. TensorSymmetry.fully_symmetric(1), 2)
  257. Gamma2 = TensorHead('Gamma', [Lorentz]*2,
  258. TensorSymmetry.fully_symmetric(-2), 2)
  259. Gamma3 = TensorHead('Gamma', [Lorentz]*3,
  260. TensorSymmetry.fully_symmetric(-3), 2)
  261. t = Gamma2(-mu, -nu)*Gamma(rho)*Gamma3(nu, mu, alpha)
  262. tc = t.canon_bp()
  263. assert str(tc) == '-Gamma(L_0, L_1)*Gamma(rho)*Gamma(alpha, -L_0, -L_1)'
  264. # Gamma_{mu nu} * Gamma^{gamma beta} * gamma_rho * Gamma^{nu mu alpha}
  265. # T_c = Gamma^{mu nu} * Gamma^{beta gamma} * gamma_rho * Gamma^alpha_{mu nu}
  266. t = Gamma2(mu, nu)*Gamma2(beta, gamma)*Gamma(-rho)*Gamma3(alpha, -mu, -nu)
  267. tc = t.canon_bp()
  268. assert str(tc) == 'Gamma(L_0, L_1)*Gamma(beta, gamma)*Gamma(-rho)*Gamma(alpha, -L_0, -L_1)'
  269. # f^a_{b,c} antisymmetric in b,c; A_mu^a no symmetry
  270. # f^c_{d a} * f_{c e b} * A_mu^d * A_nu^a * A^{nu e} * A^{mu b}
  271. # g = [8,11,5, 9,13,7, 1,10, 3,4, 2,12, 0,6, 14,15]
  272. # T_c = -f^{a b c} * f_a^{d e} * A^mu_b * A_{mu d} * A^nu_c * A_{nu e}
  273. Flavor = TensorIndexType('Flavor', dummy_name='F')
  274. a, b, c, d, e, ff = tensor_indices('a,b,c,d,e,f', Flavor)
  275. mu, nu = tensor_indices('mu,nu', Lorentz)
  276. f = TensorHead('f', [Flavor]*3, TensorSymmetry.direct_product(1, -2))
  277. A = TensorHead('A', [Lorentz, Flavor], TensorSymmetry.no_symmetry(2))
  278. t = f(c, -d, -a)*f(-c, -e, -b)*A(-mu, d)*A(-nu, a)*A(nu, e)*A(mu, b)
  279. tc = t.canon_bp()
  280. assert str(tc) == '-f(F_0, F_1, F_2)*f(-F_0, F_3, F_4)*A(L_0, -F_1)*A(-L_0, -F_3)*A(L_1, -F_2)*A(-L_1, -F_4)'
  281. def test_bug_correction_tensor_indices():
  282. # to make sure that tensor_indices does not return a list if creating
  283. # only one index:
  284. A = TensorIndexType("A")
  285. i = tensor_indices('i', A)
  286. assert not isinstance(i, (tuple, list))
  287. assert isinstance(i, TensorIndex)
  288. def test_riemann_invariants():
  289. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  290. d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11 = \
  291. tensor_indices('d0:12', Lorentz)
  292. # R^{d0 d1}_{d1 d0}; ord = [d0,-d0,d1,-d1]
  293. # T_c = -R^{d0 d1}_{d0 d1}
  294. R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann())
  295. t = R(d0, d1, -d1, -d0)
  296. tc = t.canon_bp()
  297. assert str(tc) == '-R(L_0, L_1, -L_0, -L_1)'
  298. # R_d11^d1_d0^d5 * R^{d6 d4 d0}_d5 * R_{d7 d2 d8 d9} *
  299. # R_{d10 d3 d6 d4} * R^{d2 d7 d11}_d1 * R^{d8 d9 d3 d10}
  300. # can = [0,2,4,6, 1,3,8,10, 5,7,12,14, 9,11,16,18, 13,15,20,22,
  301. # 17,19,21<F10,23, 24,25]
  302. # T_c = R^{d0 d1 d2 d3} * R_{d0 d1}^{d4 d5} * R_{d2 d3}^{d6 d7} *
  303. # R_{d4 d5}^{d8 d9} * R_{d6 d7}^{d10 d11} * R_{d8 d9 d10 d11}
  304. t = R(-d11,d1,-d0,d5)*R(d6,d4,d0,-d5)*R(-d7,-d2,-d8,-d9)* \
  305. R(-d10,-d3,-d6,-d4)*R(d2,d7,d11,-d1)*R(d8,d9,d3,d10)
  306. tc = t.canon_bp()
  307. assert str(tc) == 'R(L_0, L_1, L_2, L_3)*R(-L_0, -L_1, L_4, L_5)*R(-L_2, -L_3, L_6, L_7)*R(-L_4, -L_5, L_8, L_9)*R(-L_6, -L_7, L_10, L_11)*R(-L_8, -L_9, -L_10, -L_11)'
  308. def test_riemann_products():
  309. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  310. d0, d1, d2, d3, d4, d5, d6 = tensor_indices('d0:7', Lorentz)
  311. a0, a1, a2, a3, a4, a5 = tensor_indices('a0:6', Lorentz)
  312. a, b = tensor_indices('a,b', Lorentz)
  313. R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann())
  314. # R^{a b d0}_d0 = 0
  315. t = R(a, b, d0, -d0)
  316. tc = t.canon_bp()
  317. assert tc == 0
  318. # R^{d0 b a}_d0
  319. # T_c = -R^{a d0 b}_d0
  320. t = R(d0, b, a, -d0)
  321. tc = t.canon_bp()
  322. assert str(tc) == '-R(a, L_0, b, -L_0)'
  323. # R^d1_d2^b_d0 * R^{d0 a}_d1^d2; ord=[a,b,d0,-d0,d1,-d1,d2,-d2]
  324. # T_c = -R^{a d0 d1 d2}* R^b_{d0 d1 d2}
  325. t = R(d1, -d2, b, -d0)*R(d0, a, -d1, d2)
  326. tc = t.canon_bp()
  327. assert str(tc) == '-R(a, L_0, L_1, L_2)*R(b, -L_0, -L_1, -L_2)'
  328. # A symmetric commuting
  329. # R^{d6 d5}_d2^d1 * R^{d4 d0 d2 d3} * A_{d6 d0} A_{d3 d1} * A_{d4 d5}
  330. # g = [12,10,5,2, 8,0,4,6, 13,1, 7,3, 9,11,14,15]
  331. # T_c = -R^{d0 d1 d2 d3} * R_d0^{d4 d5 d6} * A_{d1 d4}*A_{d2 d5}*A_{d3 d6}
  332. V = TensorHead('V', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  333. t = R(d6, d5, -d2, d1)*R(d4, d0, d2, d3)*V(-d6, -d0)*V(-d3, -d1)*V(-d4, -d5)
  334. tc = t.canon_bp()
  335. assert str(tc) == '-R(L_0, L_1, L_2, L_3)*R(-L_0, L_4, L_5, L_6)*V(-L_1, -L_4)*V(-L_2, -L_5)*V(-L_3, -L_6)'
  336. # R^{d2 a0 a2 d0} * R^d1_d2^{a1 a3} * R^{a4 a5}_{d0 d1}
  337. # T_c = R^{a0 d0 a2 d1}*R^{a1 a3}_d0^d2*R^{a4 a5}_{d1 d2}
  338. t = R(d2, a0, a2, d0)*R(d1, -d2, a1, a3)*R(a4, a5, -d0, -d1)
  339. tc = t.canon_bp()
  340. assert str(tc) == 'R(a0, L_0, a2, L_1)*R(a1, a3, -L_0, L_2)*R(a4, a5, -L_1, -L_2)'
  341. ######################################################################
  342. def test_canonicalize2():
  343. D = Symbol('D')
  344. Eucl = TensorIndexType('Eucl', metric_symmetry=1, dim=D, dummy_name='E')
  345. i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14 = \
  346. tensor_indices('i0:15', Eucl)
  347. A = TensorHead('A', [Eucl]*3, TensorSymmetry.fully_symmetric(-3))
  348. # two examples from Cvitanovic, Group Theory page 59
  349. # of identities for antisymmetric tensors of rank 3
  350. # contracted according to the Kuratowski graph eq.(6.59)
  351. t = A(i0,i1,i2)*A(-i1,i3,i4)*A(-i3,i7,i5)*A(-i2,-i5,i6)*A(-i4,-i6,i8)
  352. t1 = t.canon_bp()
  353. assert t1 == 0
  354. # eq.(6.60)
  355. #t = A(i0,i1,i2)*A(-i1,i3,i4)*A(-i2,i5,i6)*A(-i3,i7,i8)*A(-i6,-i7,i9)*
  356. # A(-i8,i10,i13)*A(-i5,-i10,i11)*A(-i4,-i11,i12)*A(-i3,-i12,i14)
  357. t = A(i0,i1,i2)*A(-i1,i3,i4)*A(-i2,i5,i6)*A(-i3,i7,i8)*A(-i6,-i7,i9)*\
  358. A(-i8,i10,i13)*A(-i5,-i10,i11)*A(-i4,-i11,i12)*A(-i9,-i12,i14)
  359. t1 = t.canon_bp()
  360. assert t1 == 0
  361. def test_canonicalize3():
  362. D = Symbol('D')
  363. Spinor = TensorIndexType('Spinor', dim=D, metric_symmetry=-1, dummy_name='S')
  364. a0,a1,a2,a3,a4 = tensor_indices('a0:5', Spinor)
  365. chi, psi = tensor_heads('chi,psi', [Spinor], TensorSymmetry.no_symmetry(1), 1)
  366. t = chi(a1)*psi(a0)
  367. t1 = t.canon_bp()
  368. assert t1 == t
  369. t = psi(a1)*chi(a0)
  370. t1 = t.canon_bp()
  371. assert t1 == -chi(a0)*psi(a1)
  372. def test_canonicalize4():
  373. #Check whether TensAdd.canon_bp chokes on a case where the type of the expression changes on calling expand
  374. Cartesian = TensorIndexType('Cartesian', dim=3)
  375. p = tensor_indices("p", Cartesian)
  376. K = TensorHead("K", [Cartesian])
  377. expr = TensAdd( K(p) , - 2*K(p) )
  378. assert expr.canon_bp() == -K(p)
  379. def test_canonicalize5():
  380. R3 = TensorIndexType('R3', dim=3)
  381. p = tensor_indices("p", R3)
  382. K = TensorHead("K", [R3])
  383. f = symbols("f", cls=Function)
  384. x = symbols("x")
  385. expr = integrate(f(x), (x,0,1)) * K(p)
  386. assert expr.as_dummy().canon_bp() == integrate(f(x), (x,0,1)).as_dummy() * K(p)
  387. def test_TensorIndexType():
  388. D = Symbol('D')
  389. Lorentz = TensorIndexType('Lorentz', metric_name='g', metric_symmetry=1,
  390. dim=D, dummy_name='L')
  391. m0, m1, m2, m3, m4 = tensor_indices('m0:5', Lorentz)
  392. sym2 = TensorSymmetry.fully_symmetric(2)
  393. sym2n = TensorSymmetry(*get_symmetric_group_sgs(2))
  394. assert sym2 == sym2n
  395. g = Lorentz.metric
  396. assert str(g) == 'g(Lorentz,Lorentz)'
  397. assert Lorentz.eps_dim == Lorentz.dim
  398. TSpace = TensorIndexType('TSpace', dummy_name = 'TSpace')
  399. i0, i1 = tensor_indices('i0 i1', TSpace)
  400. g = TSpace.metric
  401. A = TensorHead('A', [TSpace]*2, sym2)
  402. assert str(A(i0,-i0).canon_bp()) == 'A(TSpace_0, -TSpace_0)'
  403. def test_indices():
  404. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  405. a, b, c, d = tensor_indices('a,b,c,d', Lorentz)
  406. assert a.tensor_index_type == Lorentz
  407. assert a != -a
  408. A, B = tensor_heads('A B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  409. t = A(a,b)*B(-b,c)
  410. indices = t.get_indices()
  411. L_0 = TensorIndex('L_0', Lorentz)
  412. assert indices == [a, L_0, -L_0, c]
  413. raises(ValueError, lambda: tensor_indices(3, Lorentz))
  414. raises(ValueError, lambda: A(a,b,c))
  415. A = TensorHead('A', [Lorentz, Lorentz])
  416. assert A('a', 'b') == A(TensorIndex('a', Lorentz),
  417. TensorIndex('b', Lorentz))
  418. assert A('a', '-b') == A(TensorIndex('a', Lorentz),
  419. TensorIndex('b', Lorentz, is_up=False))
  420. assert A('a', TensorIndex('b', Lorentz)) == A(TensorIndex('a', Lorentz),
  421. TensorIndex('b', Lorentz))
  422. def test_TensorSymmetry():
  423. assert TensorSymmetry.fully_symmetric(2) == \
  424. TensorSymmetry(get_symmetric_group_sgs(2))
  425. assert TensorSymmetry.fully_symmetric(-3) == \
  426. TensorSymmetry(get_symmetric_group_sgs(3, True))
  427. assert TensorSymmetry.direct_product(-4) == \
  428. TensorSymmetry.fully_symmetric(-4)
  429. assert TensorSymmetry.fully_symmetric(-1) == \
  430. TensorSymmetry.fully_symmetric(1)
  431. assert TensorSymmetry.direct_product(1, -1, 1) == \
  432. TensorSymmetry.no_symmetry(3)
  433. assert TensorSymmetry(get_symmetric_group_sgs(2)) == \
  434. TensorSymmetry(*get_symmetric_group_sgs(2))
  435. # TODO: add check for *get_symmetric_group_sgs(0)
  436. sym = TensorSymmetry.fully_symmetric(-3)
  437. assert sym.rank == 3
  438. assert sym.base == Tuple(0, 1)
  439. assert sym.generators == Tuple(Permutation(0, 1)(3, 4), Permutation(1, 2)(3, 4))
  440. def test_TensExpr():
  441. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  442. a, b, c, d = tensor_indices('a,b,c,d', Lorentz)
  443. g = Lorentz.metric
  444. A, B = tensor_heads('A B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  445. raises(ValueError, lambda: g(c, d)/g(a, b))
  446. raises(ValueError, lambda: S.One/g(a, b))
  447. raises(ValueError, lambda: (A(c, d) + g(c, d))/g(a, b))
  448. raises(ValueError, lambda: S.One/(A(c, d) + g(c, d)))
  449. raises(ValueError, lambda: A(a, b) + A(a, c))
  450. #t = A(a, b) + B(a, b) # assigned to t for below
  451. #raises(NotImplementedError, lambda: TensExpr.__mul__(t, 'a'))
  452. #raises(NotImplementedError, lambda: TensExpr.__add__(t, 'a'))
  453. #raises(NotImplementedError, lambda: TensExpr.__radd__(t, 'a'))
  454. #raises(NotImplementedError, lambda: TensExpr.__sub__(t, 'a'))
  455. #raises(NotImplementedError, lambda: TensExpr.__rsub__(t, 'a'))
  456. #raises(NotImplementedError, lambda: TensExpr.__truediv__(t, 'a'))
  457. #raises(NotImplementedError, lambda: TensExpr.__rtruediv__(t, 'a'))
  458. with warns_deprecated_sympy():
  459. # DO NOT REMOVE THIS AFTER DEPRECATION REMOVED:
  460. raises(ValueError, lambda: A(a, b)**2)
  461. raises(NotImplementedError, lambda: 2**A(a, b))
  462. raises(NotImplementedError, lambda: abs(A(a, b)))
  463. def test_TensorHead():
  464. # simple example of algebraic expression
  465. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  466. A = TensorHead('A', [Lorentz]*2)
  467. assert A.name == 'A'
  468. assert A.index_types == [Lorentz, Lorentz]
  469. assert A.rank == 2
  470. assert A.symmetry == TensorSymmetry.no_symmetry(2)
  471. assert A.comm == 0
  472. def test_add1():
  473. assert TensAdd().args == ()
  474. assert TensAdd().doit() == 0
  475. # simple example of algebraic expression
  476. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  477. a,b,d0,d1,i,j,k = tensor_indices('a,b,d0,d1,i,j,k', Lorentz)
  478. # A, B symmetric
  479. A, B = tensor_heads('A,B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  480. t1 = A(b, -d0)*B(d0, a)
  481. assert TensAdd(t1).equals(t1)
  482. t2a = B(d0, a) + A(d0, a)
  483. t2 = A(b, -d0)*t2a
  484. assert str(t2) == 'A(b, -L_0)*(A(L_0, a) + B(L_0, a))'
  485. t2 = t2.expand()
  486. assert str(t2) == 'A(b, -L_0)*A(L_0, a) + A(b, -L_0)*B(L_0, a)'
  487. t2 = t2.canon_bp()
  488. assert str(t2) == 'A(a, L_0)*A(b, -L_0) + A(b, L_0)*B(a, -L_0)'
  489. t2b = t2 + t1
  490. assert str(t2b) == 'A(a, L_0)*A(b, -L_0) + A(b, -L_0)*B(L_0, a) + A(b, L_0)*B(a, -L_0)'
  491. t2b = t2b.canon_bp()
  492. assert str(t2b) == 'A(a, L_0)*A(b, -L_0) + 2*A(b, L_0)*B(a, -L_0)'
  493. p, q, r = tensor_heads('p,q,r', [Lorentz])
  494. t = q(d0)*2
  495. assert str(t) == '2*q(d0)'
  496. t = 2*q(d0)
  497. assert str(t) == '2*q(d0)'
  498. t1 = p(d0) + 2*q(d0)
  499. assert str(t1) == '2*q(d0) + p(d0)'
  500. t2 = p(-d0) + 2*q(-d0)
  501. assert str(t2) == '2*q(-d0) + p(-d0)'
  502. t1 = p(d0)
  503. t3 = t1*t2
  504. assert str(t3) == 'p(L_0)*(2*q(-L_0) + p(-L_0))'
  505. t3 = t3.expand()
  506. assert str(t3) == 'p(L_0)*p(-L_0) + 2*p(L_0)*q(-L_0)'
  507. t3 = t2*t1
  508. t3 = t3.expand()
  509. assert str(t3) == 'p(-L_0)*p(L_0) + 2*q(-L_0)*p(L_0)'
  510. t3 = t3.canon_bp()
  511. assert str(t3) == 'p(L_0)*p(-L_0) + 2*p(L_0)*q(-L_0)'
  512. t1 = p(d0) + 2*q(d0)
  513. t3 = t1*t2
  514. t3 = t3.canon_bp()
  515. assert str(t3) == 'p(L_0)*p(-L_0) + 4*p(L_0)*q(-L_0) + 4*q(L_0)*q(-L_0)'
  516. t1 = p(d0) - 2*q(d0)
  517. assert str(t1) == '-2*q(d0) + p(d0)'
  518. t2 = p(-d0) + 2*q(-d0)
  519. t3 = t1*t2
  520. t3 = t3.canon_bp()
  521. assert t3 == p(d0)*p(-d0) - 4*q(d0)*q(-d0)
  522. t = p(i)*p(j)*(p(k) + q(k)) + p(i)*(p(j) + q(j))*(p(k) - 3*q(k))
  523. t = t.canon_bp()
  524. assert t == 2*p(i)*p(j)*p(k) - 2*p(i)*p(j)*q(k) + p(i)*p(k)*q(j) - 3*p(i)*q(j)*q(k)
  525. t1 = (p(i) + q(i) + 2*r(i))*(p(j) - q(j))
  526. t2 = (p(j) + q(j) + 2*r(j))*(p(i) - q(i))
  527. t = t1 + t2
  528. t = t.canon_bp()
  529. assert t == 2*p(i)*p(j) + 2*p(i)*r(j) + 2*p(j)*r(i) - 2*q(i)*q(j) - 2*q(i)*r(j) - 2*q(j)*r(i)
  530. t = p(i)*q(j)/2
  531. assert 2*t == p(i)*q(j)
  532. t = (p(i) + q(i))/2
  533. assert 2*t == p(i) + q(i)
  534. t = S.One - p(i)*p(-i)
  535. t = t.canon_bp()
  536. tz1 = t + p(-j)*p(j)
  537. assert tz1 != 1
  538. tz1 = tz1.canon_bp()
  539. assert tz1.equals(1)
  540. t = S.One + p(i)*p(-i)
  541. assert (t - p(-j)*p(j)).canon_bp().equals(1)
  542. t = A(a, b) + B(a, b)
  543. assert t.rank == 2
  544. t1 = t - A(a, b) - B(a, b)
  545. assert t1 == 0
  546. t = 1 - (A(a, -a) + B(a, -a))
  547. t1 = 1 + (A(a, -a) + B(a, -a))
  548. assert (t + t1).expand().equals(2)
  549. t2 = 1 + A(a, -a)
  550. assert t1 != t2
  551. assert t2 != TensMul.from_data(0, [], [], [])
  552. #Test whether TensAdd.doit chokes on subterms that are zero.
  553. assert TensAdd(p(a), TensMul(0, p(a)) ).doit() == p(a)
  554. def test_special_eq_ne():
  555. # test special equality cases:
  556. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  557. a, b, d0, d1, i, j, k = tensor_indices('a,b,d0,d1,i,j,k', Lorentz)
  558. # A, B symmetric
  559. A, B = tensor_heads('A,B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  560. p, q, r = tensor_heads('p,q,r', [Lorentz])
  561. t = 0*A(a, b)
  562. assert _is_equal(t, 0)
  563. assert _is_equal(t, S.Zero)
  564. assert p(i) != A(a, b)
  565. assert A(a, -a) != A(a, b)
  566. assert 0*(A(a, b) + B(a, b)) == 0
  567. assert 0*(A(a, b) + B(a, b)) is S.Zero
  568. assert 3*(A(a, b) - A(a, b)) is S.Zero
  569. assert p(i) + q(i) != A(a, b)
  570. assert p(i) + q(i) != A(a, b) + B(a, b)
  571. assert p(i) - p(i) == 0
  572. assert p(i) - p(i) is S.Zero
  573. assert _is_equal(A(a, b), A(b, a))
  574. def test_add2():
  575. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  576. m, n, p, q = tensor_indices('m,n,p,q', Lorentz)
  577. R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann())
  578. A = TensorHead('A', [Lorentz]*3, TensorSymmetry.fully_symmetric(-3))
  579. t1 = 2*R(m, n, p, q) - R(m, q, n, p) + R(m, p, n, q)
  580. t2 = t1*A(-n, -p, -q)
  581. t2 = t2.canon_bp()
  582. assert t2 == 0
  583. t1 = Rational(2, 3)*R(m,n,p,q) - Rational(1, 3)*R(m,q,n,p) + Rational(1, 3)*R(m,p,n,q)
  584. t2 = t1*A(-n, -p, -q)
  585. t2 = t2.canon_bp()
  586. assert t2 == 0
  587. t = A(m, -m, n) + A(n, p, -p)
  588. t = t.canon_bp()
  589. assert t == 0
  590. def test_add3():
  591. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  592. i0, i1 = tensor_indices('i0:2', Lorentz)
  593. E, px, py, pz = symbols('E px py pz')
  594. A = TensorHead('A', [Lorentz])
  595. B = TensorHead('B', [Lorentz])
  596. expr1 = A(i0)*A(-i0) - (E**2 - px**2 - py**2 - pz**2)
  597. assert expr1.args == (-E**2, px**2, py**2, pz**2, A(i0)*A(-i0))
  598. expr2 = E**2 - px**2 - py**2 - pz**2 - A(i0)*A(-i0)
  599. assert expr2.args == (E**2, -px**2, -py**2, -pz**2, -A(i0)*A(-i0))
  600. expr3 = A(i0)*A(-i0) - E**2 + px**2 + py**2 + pz**2
  601. assert expr3.args == (-E**2, px**2, py**2, pz**2, A(i0)*A(-i0))
  602. expr4 = B(i1)*B(-i1) + 2*E**2 - 2*px**2 - 2*py**2 - 2*pz**2 - A(i0)*A(-i0)
  603. assert expr4.args == (2*E**2, -2*px**2, -2*py**2, -2*pz**2, B(i1)*B(-i1), -A(i0)*A(-i0))
  604. def test_mul():
  605. from sympy.abc import x
  606. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  607. a, b, c, d = tensor_indices('a,b,c,d', Lorentz)
  608. t = TensMul.from_data(S.One, [], [], [])
  609. assert str(t) == '1'
  610. A, B = tensor_heads('A B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  611. t = (1 + x)*A(a, b)
  612. assert str(t) == '(x + 1)*A(a, b)'
  613. assert t.index_types == [Lorentz, Lorentz]
  614. assert t.rank == 2
  615. assert t.dum == []
  616. assert t.coeff == 1 + x
  617. assert sorted(t.free) == [(a, 0), (b, 1)]
  618. assert t.components == [A]
  619. ts = A(a, b)
  620. assert str(ts) == 'A(a, b)'
  621. assert ts.index_types == [Lorentz, Lorentz]
  622. assert ts.rank == 2
  623. assert ts.dum == []
  624. assert ts.coeff == 1
  625. assert sorted(ts.free) == [(a, 0), (b, 1)]
  626. assert ts.components == [A]
  627. t = A(-b, a)*B(-a, c)*A(-c, d)
  628. t1 = tensor_mul(*t.split())
  629. assert t == t1
  630. assert tensor_mul(*[]) == TensMul.from_data(S.One, [], [], [])
  631. t = TensMul.from_data(1, [], [], [])
  632. C = TensorHead('C', [])
  633. assert str(C()) == 'C'
  634. assert str(t) == '1'
  635. assert t == 1
  636. raises(ValueError, lambda: A(a, b)*A(a, c))
  637. def test_substitute_indices():
  638. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  639. i, j, k, l, m, n, p, q = tensor_indices('i,j,k,l,m,n,p,q', Lorentz)
  640. A, B = tensor_heads('A,B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  641. p = TensorHead('p', [Lorentz])
  642. t = p(i)
  643. t1 = t.substitute_indices((j, k))
  644. assert t1 == t
  645. t1 = t.substitute_indices((i, j))
  646. assert t1 == p(j)
  647. t1 = t.substitute_indices((i, -j))
  648. assert t1 == p(-j)
  649. t1 = t.substitute_indices((-i, j))
  650. assert t1 == p(-j)
  651. t1 = t.substitute_indices((-i, -j))
  652. assert t1 == p(j)
  653. t = A(m, n)
  654. t1 = t.substitute_indices((m, i), (n, -i))
  655. assert t1 == A(n, -n)
  656. t1 = substitute_indices(t, (m, i), (n, -i))
  657. assert t1 == A(n, -n)
  658. t = A(i, k)*B(-k, -j)
  659. t1 = t.substitute_indices((i, j), (j, k))
  660. t1a = A(j, l)*B(-l, -k)
  661. assert t1 == t1a
  662. t1 = substitute_indices(t, (i, j), (j, k))
  663. assert t1 == t1a
  664. t = A(i, j) + B(i, j)
  665. t1 = t.substitute_indices((j, -i))
  666. t1a = A(i, -i) + B(i, -i)
  667. assert t1 == t1a
  668. t1 = substitute_indices(t, (j, -i))
  669. assert t1 == t1a
  670. def test_riemann_cyclic_replace():
  671. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  672. m0, m1, m2, m3 = tensor_indices('m:4', Lorentz)
  673. R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann())
  674. t = R(m0, m2, m1, m3)
  675. t1 = riemann_cyclic_replace(t)
  676. t1a = Rational(-1, 3)*R(m0, m3, m2, m1) + Rational(1, 3)*R(m0, m1, m2, m3) + Rational(2, 3)*R(m0, m2, m1, m3)
  677. assert t1 == t1a
  678. def test_riemann_cyclic():
  679. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  680. i, j, k, l, m, n, p, q = tensor_indices('i,j,k,l,m,n,p,q', Lorentz)
  681. R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann())
  682. t = R(i,j,k,l) + R(i,l,j,k) + R(i,k,l,j) - \
  683. R(i,j,l,k) - R(i,l,k,j) - R(i,k,j,l)
  684. t2 = t*R(-i,-j,-k,-l)
  685. t3 = riemann_cyclic(t2)
  686. assert t3 == 0
  687. t = R(i,j,k,l)*(R(-i,-j,-k,-l) - 2*R(-i,-k,-j,-l))
  688. t1 = riemann_cyclic(t)
  689. assert t1 == 0
  690. t = R(i,j,k,l)
  691. t1 = riemann_cyclic(t)
  692. assert t1 == Rational(-1, 3)*R(i, l, j, k) + Rational(1, 3)*R(i, k, j, l) + Rational(2, 3)*R(i, j, k, l)
  693. t = R(i,j,k,l)*R(-k,-l,m,n)*(R(-m,-n,-i,-j) + 2*R(-m,-j,-n,-i))
  694. t1 = riemann_cyclic(t)
  695. assert t1 == 0
  696. @XFAIL
  697. def test_div():
  698. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  699. m0, m1, m2, m3 = tensor_indices('m0:4', Lorentz)
  700. R = TensorHead('R', [Lorentz]*4, TensorSymmetry.riemann())
  701. t = R(m0,m1,-m1,m3)
  702. t1 = t/S(4)
  703. assert str(t1) == '(1/4)*R(m0, L_0, -L_0, m3)'
  704. t = t.canon_bp()
  705. assert not t1._is_canon_bp
  706. t1 = t*4
  707. assert t1._is_canon_bp
  708. t1 = t1/4
  709. assert t1._is_canon_bp
  710. def test_contract_metric1():
  711. D = Symbol('D')
  712. Lorentz = TensorIndexType('Lorentz', dim=D, dummy_name='L')
  713. a, b, c, d, e = tensor_indices('a,b,c,d,e', Lorentz)
  714. g = Lorentz.metric
  715. p = TensorHead('p', [Lorentz])
  716. t = g(a, b)*p(-b)
  717. t1 = t.contract_metric(g)
  718. assert t1 == p(a)
  719. A, B = tensor_heads('A,B', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  720. # case with g with all free indices
  721. t1 = A(a,b)*B(-b,c)*g(d, e)
  722. t2 = t1.contract_metric(g)
  723. assert t1 == t2
  724. # case of g(d, -d)
  725. t1 = A(a,b)*B(-b,c)*g(-d, d)
  726. t2 = t1.contract_metric(g)
  727. assert t2 == D*A(a, d)*B(-d, c)
  728. # g with one free index
  729. t1 = A(a,b)*B(-b,-c)*g(c, d)
  730. t2 = t1.contract_metric(g)
  731. assert t2 == A(a, c)*B(-c, d)
  732. # g with both indices contracted with another tensor
  733. t1 = A(a,b)*B(-b,-c)*g(c, -a)
  734. t2 = t1.contract_metric(g)
  735. assert _is_equal(t2, A(a, b)*B(-b, -a))
  736. t1 = A(a,b)*B(-b,-c)*g(c, d)*g(-a, -d)
  737. t2 = t1.contract_metric(g)
  738. assert _is_equal(t2, A(a,b)*B(-b,-a))
  739. t1 = A(a,b)*g(-a,-b)
  740. t2 = t1.contract_metric(g)
  741. assert _is_equal(t2, A(a, -a))
  742. assert not t2.free
  743. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  744. a, b = tensor_indices('a,b', Lorentz)
  745. g = Lorentz.metric
  746. assert _is_equal(g(a, -a).contract_metric(g), Lorentz.dim) # no dim
  747. def test_contract_metric2():
  748. D = Symbol('D')
  749. Lorentz = TensorIndexType('Lorentz', dim=D, dummy_name='L')
  750. a, b, c, d, e, L_0 = tensor_indices('a,b,c,d,e,L_0', Lorentz)
  751. g = Lorentz.metric
  752. p, q = tensor_heads('p,q', [Lorentz])
  753. t1 = g(a,b)*p(c)*p(-c)
  754. t2 = 3*g(-a,-b)*q(c)*q(-c)
  755. t = t1*t2
  756. t = t.contract_metric(g)
  757. assert t == 3*D*p(a)*p(-a)*q(b)*q(-b)
  758. t1 = g(a,b)*p(c)*p(-c)
  759. t2 = 3*q(-a)*q(-b)
  760. t = t1*t2
  761. t = t.contract_metric(g)
  762. t = t.canon_bp()
  763. assert t == 3*p(a)*p(-a)*q(b)*q(-b)
  764. t1 = 2*g(a,b)*p(c)*p(-c)
  765. t2 = - 3*g(-a,-b)*q(c)*q(-c)
  766. t = t1*t2
  767. t = t.contract_metric(g)
  768. t = 6*g(a,b)*g(-a,-b)*p(c)*p(-c)*q(d)*q(-d)
  769. t = t.contract_metric(g)
  770. t1 = 2*g(a,b)*p(c)*p(-c)
  771. t2 = q(-a)*q(-b) + 3*g(-a,-b)*q(c)*q(-c)
  772. t = t1*t2
  773. t = t.contract_metric(g)
  774. assert t == (2 + 6*D)*p(a)*p(-a)*q(b)*q(-b)
  775. t1 = p(a)*p(b) + p(a)*q(b) + 2*g(a,b)*p(c)*p(-c)
  776. t2 = q(-a)*q(-b) - g(-a,-b)*q(c)*q(-c)
  777. t = t1*t2
  778. t = t.contract_metric(g)
  779. t1 = (1 - 2*D)*p(a)*p(-a)*q(b)*q(-b) + p(a)*q(-a)*p(b)*q(-b)
  780. assert canon_bp(t - t1) == 0
  781. t = g(a,b)*g(c,d)*g(-b,-c)
  782. t1 = t.contract_metric(g)
  783. assert t1 == g(a, d)
  784. t1 = g(a,b)*g(c,d) + g(a,c)*g(b,d) + g(a,d)*g(b,c)
  785. t2 = t1.substitute_indices((a,-a),(b,-b),(c,-c),(d,-d))
  786. t = t1*t2
  787. t = t.contract_metric(g)
  788. assert t.equals(3*D**2 + 6*D)
  789. t = 2*p(a)*g(b,-b)
  790. t1 = t.contract_metric(g)
  791. assert t1.equals(2*D*p(a))
  792. t = 2*p(a)*g(b,-a)
  793. t1 = t.contract_metric(g)
  794. assert t1 == 2*p(b)
  795. M = Symbol('M')
  796. t = (p(a)*p(b) + g(a, b)*M**2)*g(-a, -b) - D*M**2
  797. t1 = t.contract_metric(g)
  798. assert t1 == p(a)*p(-a)
  799. A = TensorHead('A', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  800. t = A(a, b)*p(L_0)*g(-a, -b)
  801. t1 = t.contract_metric(g)
  802. assert str(t1) == 'A(L_1, -L_1)*p(L_0)' or str(t1) == 'A(-L_1, L_1)*p(L_0)'
  803. def test_metric_contract3():
  804. D = Symbol('D')
  805. Spinor = TensorIndexType('Spinor', dim=D, metric_symmetry=-1, dummy_name='S')
  806. a0, a1, a2, a3, a4 = tensor_indices('a0:5', Spinor)
  807. C = Spinor.metric
  808. chi, psi = tensor_heads('chi,psi', [Spinor], TensorSymmetry.no_symmetry(1), 1)
  809. B = TensorHead('B', [Spinor]*2, TensorSymmetry.no_symmetry(2))
  810. t = C(a0,-a0)
  811. t1 = t.contract_metric(C)
  812. assert t1.equals(-D)
  813. t = C(-a0,a0)
  814. t1 = t.contract_metric(C)
  815. assert t1.equals(D)
  816. t = C(a0,a1)*C(-a0,-a1)
  817. t1 = t.contract_metric(C)
  818. assert t1.equals(D)
  819. t = C(a1,a0)*C(-a0,-a1)
  820. t1 = t.contract_metric(C)
  821. assert t1.equals(-D)
  822. t = C(-a0,a1)*C(a0,-a1)
  823. t1 = t.contract_metric(C)
  824. assert t1.equals(-D)
  825. t = C(a1,-a0)*C(a0,-a1)
  826. t1 = t.contract_metric(C)
  827. assert t1.equals(D)
  828. t = C(a0,a1)*B(-a1,-a0)
  829. t1 = t.contract_metric(C)
  830. t1 = t1.canon_bp()
  831. assert _is_equal(t1, B(a0,-a0))
  832. t = C(a1,a0)*B(-a1,-a0)
  833. t1 = t.contract_metric(C)
  834. assert _is_equal(t1, -B(a0,-a0))
  835. t = C(a0,-a1)*B(a1,-a0)
  836. t1 = t.contract_metric(C)
  837. assert _is_equal(t1, -B(a0,-a0))
  838. t = C(-a0,a1)*B(-a1,a0)
  839. t1 = t.contract_metric(C)
  840. assert _is_equal(t1, -B(a0,-a0))
  841. t = C(-a0,-a1)*B(a1,a0)
  842. t1 = t.contract_metric(C)
  843. assert _is_equal(t1, B(a0,-a0))
  844. t = C(-a1, a0)*B(a1,-a0)
  845. t1 = t.contract_metric(C)
  846. assert _is_equal(t1, B(a0,-a0))
  847. t = C(a0,a1)*psi(-a1)
  848. t1 = t.contract_metric(C)
  849. assert _is_equal(t1, psi(a0))
  850. t = C(a1,a0)*psi(-a1)
  851. t1 = t.contract_metric(C)
  852. assert _is_equal(t1, -psi(a0))
  853. t = C(a0,a1)*chi(-a0)*psi(-a1)
  854. t1 = t.contract_metric(C)
  855. assert _is_equal(t1, -chi(a1)*psi(-a1))
  856. t = C(a1,a0)*chi(-a0)*psi(-a1)
  857. t1 = t.contract_metric(C)
  858. assert _is_equal(t1, chi(a1)*psi(-a1))
  859. t = C(-a1,a0)*chi(-a0)*psi(a1)
  860. t1 = t.contract_metric(C)
  861. assert _is_equal(t1, chi(-a1)*psi(a1))
  862. t = C(a0,-a1)*chi(-a0)*psi(a1)
  863. t1 = t.contract_metric(C)
  864. assert _is_equal(t1, -chi(-a1)*psi(a1))
  865. t = C(-a0,-a1)*chi(a0)*psi(a1)
  866. t1 = t.contract_metric(C)
  867. assert _is_equal(t1, chi(-a1)*psi(a1))
  868. t = C(-a1,-a0)*chi(a0)*psi(a1)
  869. t1 = t.contract_metric(C)
  870. assert _is_equal(t1, -chi(-a1)*psi(a1))
  871. t = C(-a1,-a0)*B(a0,a2)*psi(a1)
  872. t1 = t.contract_metric(C)
  873. assert _is_equal(t1, -B(-a1,a2)*psi(a1))
  874. t = C(a1,a0)*B(-a2,-a0)*psi(-a1)
  875. t1 = t.contract_metric(C)
  876. assert _is_equal(t1, B(-a2,a1)*psi(-a1))
  877. def test_contract_metric4():
  878. R3 = TensorIndexType('R3', dim=3)
  879. p, q, r = tensor_indices("p q r", R3)
  880. delta = R3.delta
  881. eps = R3.epsilon
  882. K = TensorHead("K", [R3])
  883. #Check whether contract_metric chokes on an expandable expression which becomes zero on canonicalization (issue #24354)
  884. expr = eps(p,q,r)*( K(-p)*K(-q) + delta(-p,-q) )
  885. assert expr.contract_metric(delta) == 0
  886. def test_contract_metric5():
  887. R3 = TensorIndexType('R3', dim=3)
  888. p, q, r = tensor_indices("p q r", R3)
  889. delta = R3.delta
  890. K = TensorHead("K", [R3])
  891. F = Function("F")
  892. x = Symbol("x")
  893. #Check if contract_metric gets into an infinite loop when given a TensMul whose coeff is an Add
  894. expr = (2+F(x))*K(-p)*K(-q)
  895. assert expr.contract_metric(delta) == expr
  896. def test_epsilon():
  897. Lorentz = TensorIndexType('Lorentz', dim=4, dummy_name='L')
  898. a, b, c, d, e = tensor_indices('a,b,c,d,e', Lorentz)
  899. epsilon = Lorentz.epsilon
  900. p, q, r, s = tensor_heads('p,q,r,s', [Lorentz])
  901. t = epsilon(b,a,c,d)
  902. t1 = t.canon_bp()
  903. assert t1 == -epsilon(a,b,c,d)
  904. t = epsilon(c,b,d,a)
  905. t1 = t.canon_bp()
  906. assert t1 == epsilon(a,b,c,d)
  907. t = epsilon(c,a,d,b)
  908. t1 = t.canon_bp()
  909. assert t1 == -epsilon(a,b,c,d)
  910. t = epsilon(a,b,c,d)*p(-a)*q(-b)
  911. t1 = t.canon_bp()
  912. assert t1 == epsilon(c,d,a,b)*p(-a)*q(-b)
  913. t = epsilon(c,b,d,a)*p(-a)*q(-b)
  914. t1 = t.canon_bp()
  915. assert t1 == epsilon(c,d,a,b)*p(-a)*q(-b)
  916. t = epsilon(c,a,d,b)*p(-a)*q(-b)
  917. t1 = t.canon_bp()
  918. assert t1 == -epsilon(c,d,a,b)*p(-a)*q(-b)
  919. t = epsilon(c,a,d,b)*p(-a)*p(-b)
  920. t1 = t.canon_bp()
  921. assert t1 == 0
  922. t = epsilon(c,a,d,b)*p(-a)*q(-b) + epsilon(a,b,c,d)*p(-b)*q(-a)
  923. t1 = t.canon_bp()
  924. assert t1 == -2*epsilon(c,d,a,b)*p(-a)*q(-b)
  925. # Test that epsilon can be create with a SymPy integer:
  926. Lorentz = TensorIndexType('Lorentz', dim=Integer(4), dummy_name='L')
  927. epsilon = Lorentz.epsilon
  928. assert isinstance(epsilon, TensorHead)
  929. def test_contract_delta1():
  930. # see Group Theory by Cvitanovic page 9
  931. n = Symbol('n')
  932. Color = TensorIndexType('Color', dim=n, dummy_name='C')
  933. a, b, c, d, e, f = tensor_indices('a,b,c,d,e,f', Color)
  934. delta = Color.delta
  935. def idn(a, b, d, c):
  936. assert a.is_up and d.is_up
  937. assert not (b.is_up or c.is_up)
  938. return delta(a,c)*delta(d,b)
  939. def T(a, b, d, c):
  940. assert a.is_up and d.is_up
  941. assert not (b.is_up or c.is_up)
  942. return delta(a,b)*delta(d,c)
  943. def P1(a, b, c, d):
  944. return idn(a,b,c,d) - 1/n*T(a,b,c,d)
  945. def P2(a, b, c, d):
  946. return 1/n*T(a,b,c,d)
  947. t = P1(a, -b, e, -f)*P1(f, -e, d, -c)
  948. t1 = t.contract_delta(delta)
  949. assert canon_bp(t1 - P1(a, -b, d, -c)) == 0
  950. t = P2(a, -b, e, -f)*P2(f, -e, d, -c)
  951. t1 = t.contract_delta(delta)
  952. assert t1 == P2(a, -b, d, -c)
  953. t = P1(a, -b, e, -f)*P2(f, -e, d, -c)
  954. t1 = t.contract_delta(delta)
  955. assert t1 == 0
  956. t = P1(a, -b, b, -a)
  957. t1 = t.contract_delta(delta)
  958. assert t1.equals(n**2 - 1)
  959. def test_contract_delta2():
  960. R3 = TensorIndexType('R3', dim=3)
  961. p, q = tensor_indices("p q", R3)
  962. delta = R3.delta
  963. K = TensorHead("K", [R3])
  964. #Check if TensAdd.contract_delta can handle the case when the TensAdd has non-TensExpr args.
  965. expr = 1 + K(p)*K(q)*delta(-p,-q)
  966. assert expr.contract_delta(delta) == 1 + K(p)*K(-p)
  967. def test_fun():
  968. with warns_deprecated_sympy():
  969. D = Symbol('D')
  970. Lorentz = TensorIndexType('Lorentz', dim=D, dummy_name='L')
  971. a, b, c, d, e = tensor_indices('a,b,c,d,e', Lorentz)
  972. g = Lorentz.metric
  973. p, q = tensor_heads('p q', [Lorentz])
  974. t = q(c)*p(a)*q(b) + g(a,b)*g(c,d)*q(-d)
  975. assert t(a,b,c) == t
  976. assert canon_bp(t - t(b,a,c) - q(c)*p(a)*q(b) + q(c)*p(b)*q(a)) == 0
  977. assert t(b,c,d) == q(d)*p(b)*q(c) + g(b,c)*g(d,e)*q(-e)
  978. t1 = t.substitute_indices((a,b),(b,a))
  979. assert canon_bp(t1 - q(c)*p(b)*q(a) - g(a,b)*g(c,d)*q(-d)) == 0
  980. # check that g_{a b; c} = 0
  981. # example taken from L. Brewin
  982. # "A brief introduction to Cadabra" arxiv:0903.2085
  983. # dg_{a b c} = \partial_{a} g_{b c} is symmetric in b, c
  984. dg = TensorHead('dg', [Lorentz]*3, TensorSymmetry.direct_product(1, 2))
  985. # gamma^a_{b c} is the Christoffel symbol
  986. gamma = S.Half*g(a,d)*(dg(-b,-d,-c) + dg(-c,-b,-d) - dg(-d,-b,-c))
  987. # t = g_{a b; c}
  988. t = dg(-c,-a,-b) - g(-a,-d)*gamma(d,-b,-c) - g(-b,-d)*gamma(d,-a,-c)
  989. t = t.contract_metric(g)
  990. assert t == 0
  991. t = q(c)*p(a)*q(b)
  992. assert t(b,c,d) == q(d)*p(b)*q(c)
  993. def test_TensorManager():
  994. Lorentz = TensorIndexType('Lorentz', dummy_name='L')
  995. LorentzH = TensorIndexType('LorentzH', dummy_name='LH')
  996. i, j = tensor_indices('i,j', Lorentz)
  997. ih, jh = tensor_indices('ih,jh', LorentzH)
  998. p, q = tensor_heads('p q', [Lorentz])
  999. ph, qh = tensor_heads('ph qh', [LorentzH])
  1000. Gsymbol = Symbol('Gsymbol')
  1001. GHsymbol = Symbol('GHsymbol')
  1002. TensorManager.set_comm(Gsymbol, GHsymbol, 0)
  1003. G = TensorHead('G', [Lorentz], TensorSymmetry.no_symmetry(1), Gsymbol)
  1004. assert TensorManager._comm_i2symbol[G.comm] == Gsymbol
  1005. GH = TensorHead('GH', [LorentzH], TensorSymmetry.no_symmetry(1), GHsymbol)
  1006. ps = G(i)*p(-i)
  1007. psh = GH(ih)*ph(-ih)
  1008. t = ps + psh
  1009. t1 = t*t
  1010. assert canon_bp(t1 - ps*ps - 2*ps*psh - psh*psh) == 0
  1011. qs = G(i)*q(-i)
  1012. qsh = GH(ih)*qh(-ih)
  1013. assert _is_equal(ps*qsh, qsh*ps)
  1014. assert not _is_equal(ps*qs, qs*ps)
  1015. n = TensorManager.comm_symbols2i(Gsymbol)
  1016. assert TensorManager.comm_i2symbol(n) == Gsymbol
  1017. assert GHsymbol in TensorManager._comm_symbols2i
  1018. raises(ValueError, lambda: TensorManager.set_comm(GHsymbol, 1, 2))
  1019. TensorManager.set_comms((Gsymbol,GHsymbol,0),(Gsymbol,1,1))
  1020. assert TensorManager.get_comm(n, 1) == TensorManager.get_comm(1, n) == 1
  1021. TensorManager.clear()
  1022. assert TensorManager.comm == [{0:0, 1:0, 2:0}, {0:0, 1:1, 2:None}, {0:0, 1:None}]
  1023. assert GHsymbol not in TensorManager._comm_symbols2i
  1024. nh = TensorManager.comm_symbols2i(GHsymbol)
  1025. assert TensorManager.comm_i2symbol(nh) == GHsymbol
  1026. assert GHsymbol in TensorManager._comm_symbols2i
  1027. def test_hash():
  1028. D = Symbol('D')
  1029. Lorentz = TensorIndexType('Lorentz', dim=D, dummy_name='L')
  1030. a, b, c, d, e = tensor_indices('a,b,c,d,e', Lorentz)
  1031. g = Lorentz.metric
  1032. p, q = tensor_heads('p q', [Lorentz])
  1033. p_type = p.args[1]
  1034. t1 = p(a)*q(b)
  1035. t2 = p(a)*p(b)
  1036. assert hash(t1) != hash(t2)
  1037. t3 = p(a)*p(b) + g(a,b)
  1038. t4 = p(a)*p(b) - g(a,b)
  1039. assert hash(t3) != hash(t4)
  1040. assert a.func(*a.args) == a
  1041. assert Lorentz.func(*Lorentz.args) == Lorentz
  1042. assert g.func(*g.args) == g
  1043. assert p.func(*p.args) == p
  1044. assert p_type.func(*p_type.args) == p_type
  1045. assert p(a).func(*(p(a)).args) == p(a)
  1046. assert t1.func(*t1.args) == t1
  1047. assert t2.func(*t2.args) == t2
  1048. assert t3.func(*t3.args) == t3
  1049. assert t4.func(*t4.args) == t4
  1050. assert hash(a.func(*a.args)) == hash(a)
  1051. assert hash(Lorentz.func(*Lorentz.args)) == hash(Lorentz)
  1052. assert hash(g.func(*g.args)) == hash(g)
  1053. assert hash(p.func(*p.args)) == hash(p)
  1054. assert hash(p_type.func(*p_type.args)) == hash(p_type)
  1055. assert hash(p(a).func(*(p(a)).args)) == hash(p(a))
  1056. assert hash(t1.func(*t1.args)) == hash(t1)
  1057. assert hash(t2.func(*t2.args)) == hash(t2)
  1058. assert hash(t3.func(*t3.args)) == hash(t3)
  1059. assert hash(t4.func(*t4.args)) == hash(t4)
  1060. def check_all(obj):
  1061. return all(isinstance(_, Basic) for _ in obj.args)
  1062. assert check_all(a)
  1063. assert check_all(Lorentz)
  1064. assert check_all(g)
  1065. assert check_all(p)
  1066. assert check_all(p_type)
  1067. assert check_all(p(a))
  1068. assert check_all(t1)
  1069. assert check_all(t2)
  1070. assert check_all(t3)
  1071. assert check_all(t4)
  1072. tsymmetry = TensorSymmetry.direct_product(-2, 1, 3)
  1073. assert tsymmetry.func(*tsymmetry.args) == tsymmetry
  1074. assert hash(tsymmetry.func(*tsymmetry.args)) == hash(tsymmetry)
  1075. assert check_all(tsymmetry)
  1076. ### TEST VALUED TENSORS ###
  1077. def _get_valued_base_test_variables():
  1078. minkowski = Matrix((
  1079. (1, 0, 0, 0),
  1080. (0, -1, 0, 0),
  1081. (0, 0, -1, 0),
  1082. (0, 0, 0, -1),
  1083. ))
  1084. Lorentz = TensorIndexType('Lorentz', dim=4)
  1085. Lorentz.data = minkowski
  1086. i0, i1, i2, i3, i4 = tensor_indices('i0:5', Lorentz)
  1087. E, px, py, pz = symbols('E px py pz')
  1088. A = TensorHead('A', [Lorentz])
  1089. A.data = [E, px, py, pz]
  1090. B = TensorHead('B', [Lorentz], TensorSymmetry.no_symmetry(1), 'Gcomm')
  1091. B.data = range(4)
  1092. AB = TensorHead("AB", [Lorentz]*2)
  1093. AB.data = minkowski
  1094. ba_matrix = Matrix((
  1095. (1, 2, 3, 4),
  1096. (5, 6, 7, 8),
  1097. (9, 0, -1, -2),
  1098. (-3, -4, -5, -6),
  1099. ))
  1100. BA = TensorHead("BA", [Lorentz]*2)
  1101. BA.data = ba_matrix
  1102. # Let's test the diagonal metric, with inverted Minkowski metric:
  1103. LorentzD = TensorIndexType('LorentzD')
  1104. LorentzD.data = [-1, 1, 1, 1]
  1105. mu0, mu1, mu2 = tensor_indices('mu0:3', LorentzD)
  1106. C = TensorHead('C', [LorentzD])
  1107. C.data = [E, px, py, pz]
  1108. ### non-diagonal metric ###
  1109. ndm_matrix = (
  1110. (1, 1, 0,),
  1111. (1, 0, 1),
  1112. (0, 1, 0,),
  1113. )
  1114. ndm = TensorIndexType("ndm")
  1115. ndm.data = ndm_matrix
  1116. n0, n1, n2 = tensor_indices('n0:3', ndm)
  1117. NA = TensorHead('NA', [ndm])
  1118. NA.data = range(10, 13)
  1119. NB = TensorHead('NB', [ndm]*2)
  1120. NB.data = [[i+j for j in range(10, 13)] for i in range(10, 13)]
  1121. NC = TensorHead('NC', [ndm]*3)
  1122. NC.data = [[[i+j+k for k in range(4, 7)] for j in range(1, 4)] for i in range(2, 5)]
  1123. return (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1124. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4)
  1125. def test_valued_tensor_iter():
  1126. with warns_deprecated_sympy():
  1127. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1128. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1129. list_BA = [Array([1, 2, 3, 4]), Array([5, 6, 7, 8]), Array([9, 0, -1, -2]), Array([-3, -4, -5, -6])]
  1130. # iteration on VTensorHead
  1131. assert list(A) == [E, px, py, pz]
  1132. assert list(ba_matrix) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -1, -2, -3, -4, -5, -6]
  1133. assert list(BA) == list_BA
  1134. # iteration on VTensMul
  1135. assert list(A(i1)) == [E, px, py, pz]
  1136. assert list(BA(i1, i2)) == list_BA
  1137. assert list(3 * BA(i1, i2)) == [3 * i for i in list_BA]
  1138. assert list(-5 * BA(i1, i2)) == [-5 * i for i in list_BA]
  1139. # iteration on VTensAdd
  1140. # A(i1) + A(i1)
  1141. assert list(A(i1) + A(i1)) == [2*E, 2*px, 2*py, 2*pz]
  1142. assert BA(i1, i2) - BA(i1, i2) == 0
  1143. assert list(BA(i1, i2) - 2 * BA(i1, i2)) == [-i for i in list_BA]
  1144. def test_valued_tensor_covariant_contravariant_elements():
  1145. with warns_deprecated_sympy():
  1146. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1147. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1148. assert A(-i0)[0] == A(i0)[0]
  1149. assert A(-i0)[1] == -A(i0)[1]
  1150. assert AB(i0, i1)[1, 1] == -1
  1151. assert AB(i0, -i1)[1, 1] == 1
  1152. assert AB(-i0, -i1)[1, 1] == -1
  1153. assert AB(-i0, i1)[1, 1] == 1
  1154. def test_valued_tensor_get_matrix():
  1155. with warns_deprecated_sympy():
  1156. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1157. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1158. matab = AB(i0, i1).get_matrix()
  1159. assert matab == Matrix([
  1160. [1, 0, 0, 0],
  1161. [0, -1, 0, 0],
  1162. [0, 0, -1, 0],
  1163. [0, 0, 0, -1],
  1164. ])
  1165. # when alternating contravariant/covariant with [1, -1, -1, -1] metric
  1166. # it becomes the identity matrix:
  1167. assert AB(i0, -i1).get_matrix() == eye(4)
  1168. # covariant and contravariant forms:
  1169. assert A(i0).get_matrix() == Matrix([E, px, py, pz])
  1170. assert A(-i0).get_matrix() == Matrix([E, -px, -py, -pz])
  1171. def test_valued_tensor_contraction():
  1172. with warns_deprecated_sympy():
  1173. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1174. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1175. assert (A(i0) * A(-i0)).data == E ** 2 - px ** 2 - py ** 2 - pz ** 2
  1176. assert (A(i0) * A(-i0)).data == A ** 2
  1177. assert (A(i0) * A(-i0)).data == A(i0) ** 2
  1178. assert (A(i0) * B(-i0)).data == -px - 2 * py - 3 * pz
  1179. for i in range(4):
  1180. for j in range(4):
  1181. assert (A(i0) * B(-i1))[i, j] == [E, px, py, pz][i] * [0, -1, -2, -3][j]
  1182. # test contraction on the alternative Minkowski metric: [-1, 1, 1, 1]
  1183. assert (C(mu0) * C(-mu0)).data == -E ** 2 + px ** 2 + py ** 2 + pz ** 2
  1184. contrexp = A(i0) * AB(i1, -i0)
  1185. assert A(i0).rank == 1
  1186. assert AB(i1, -i0).rank == 2
  1187. assert contrexp.rank == 1
  1188. for i in range(4):
  1189. assert contrexp[i] == [E, px, py, pz][i]
  1190. def test_valued_tensor_self_contraction():
  1191. with warns_deprecated_sympy():
  1192. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1193. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1194. assert AB(i0, -i0).data == 4
  1195. assert BA(i0, -i0).data == 2
  1196. def test_valued_tensor_pow():
  1197. with warns_deprecated_sympy():
  1198. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1199. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1200. assert C**2 == -E**2 + px**2 + py**2 + pz**2
  1201. assert C**1 == sqrt(-E**2 + px**2 + py**2 + pz**2)
  1202. assert C(mu0)**2 == C**2
  1203. assert C(mu0)**1 == C**1
  1204. def test_valued_tensor_expressions():
  1205. with warns_deprecated_sympy():
  1206. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1207. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1208. x1, x2, x3 = symbols('x1:4')
  1209. # test coefficient in contraction:
  1210. rank2coeff = x1 * A(i3) * B(i2)
  1211. assert rank2coeff[1, 1] == x1 * px
  1212. assert rank2coeff[3, 3] == 3 * pz * x1
  1213. coeff_expr = ((x1 * A(i4)) * (B(-i4) / x2)).data
  1214. assert coeff_expr.expand() == -px*x1/x2 - 2*py*x1/x2 - 3*pz*x1/x2
  1215. add_expr = A(i0) + B(i0)
  1216. assert add_expr[0] == E
  1217. assert add_expr[1] == px + 1
  1218. assert add_expr[2] == py + 2
  1219. assert add_expr[3] == pz + 3
  1220. sub_expr = A(i0) - B(i0)
  1221. assert sub_expr[0] == E
  1222. assert sub_expr[1] == px - 1
  1223. assert sub_expr[2] == py - 2
  1224. assert sub_expr[3] == pz - 3
  1225. assert (add_expr * B(-i0)).data == -px - 2*py - 3*pz - 14
  1226. expr1 = x1*A(i0) + x2*B(i0)
  1227. expr2 = expr1 * B(i1) * (-4)
  1228. expr3 = expr2 + 3*x3*AB(i0, i1)
  1229. expr4 = expr3 / 2
  1230. assert expr4 * 2 == expr3
  1231. expr5 = (expr4 * BA(-i1, -i0))
  1232. assert expr5.data.expand() == 28*E*x1 + 12*px*x1 + 20*py*x1 + 28*pz*x1 + 136*x2 + 3*x3
  1233. def test_valued_tensor_add_scalar():
  1234. with warns_deprecated_sympy():
  1235. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1236. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1237. # one scalar summand after the contracted tensor
  1238. expr1 = A(i0)*A(-i0) - (E**2 - px**2 - py**2 - pz**2)
  1239. assert expr1.data == 0
  1240. # multiple scalar summands in front of the contracted tensor
  1241. expr2 = E**2 - px**2 - py**2 - pz**2 - A(i0)*A(-i0)
  1242. assert expr2.data == 0
  1243. # multiple scalar summands after the contracted tensor
  1244. expr3 = A(i0)*A(-i0) - E**2 + px**2 + py**2 + pz**2
  1245. assert expr3.data == 0
  1246. # multiple scalar summands and multiple tensors
  1247. expr4 = C(mu0)*C(-mu0) + 2*E**2 - 2*px**2 - 2*py**2 - 2*pz**2 - A(i0)*A(-i0)
  1248. assert expr4.data == 0
  1249. def test_noncommuting_components():
  1250. with warns_deprecated_sympy():
  1251. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1252. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1253. euclid = TensorIndexType('Euclidean')
  1254. euclid.data = [1, 1]
  1255. i1, i2, i3 = tensor_indices('i1:4', euclid)
  1256. a, b, c, d = symbols('a b c d', commutative=False)
  1257. V1 = TensorHead('V1', [euclid]*2)
  1258. V1.data = [[a, b], (c, d)]
  1259. V2 = TensorHead('V2', [euclid]*2)
  1260. V2.data = [[a, c], [b, d]]
  1261. vtp = V1(i1, i2) * V2(-i2, -i1)
  1262. assert vtp.data == a**2 + b**2 + c**2 + d**2
  1263. assert vtp.data != a**2 + 2*b*c + d**2
  1264. vtp2 = V1(i1, i2)*V1(-i2, -i1)
  1265. assert vtp2.data == a**2 + b*c + c*b + d**2
  1266. assert vtp2.data != a**2 + 2*b*c + d**2
  1267. Vc = (b * V1(i1, -i1)).data
  1268. assert Vc.expand() == b * a + b * d
  1269. def test_valued_non_diagonal_metric():
  1270. with warns_deprecated_sympy():
  1271. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1272. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1273. mmatrix = Matrix(ndm_matrix)
  1274. assert (NA(n0)*NA(-n0)).data == (NA(n0).get_matrix().T * mmatrix * NA(n0).get_matrix())[0, 0]
  1275. def test_valued_assign_numpy_ndarray():
  1276. with warns_deprecated_sympy():
  1277. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1278. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1279. # this is needed to make sure that a numpy.ndarray can be assigned to a
  1280. # tensor.
  1281. arr = [E+1, px-1, py, pz]
  1282. A.data = Array(arr)
  1283. for i in range(4):
  1284. assert A(i0).data[i] == arr[i]
  1285. qx, qy, qz = symbols('qx qy qz')
  1286. A(-i0).data = Array([E, qx, qy, qz])
  1287. for i in range(4):
  1288. assert A(i0).data[i] == [E, -qx, -qy, -qz][i]
  1289. assert A.data[i] == [E, -qx, -qy, -qz][i]
  1290. # test on multi-indexed tensors.
  1291. random_4x4_data = [[(i**3-3*i**2)%(j+7) for i in range(4)] for j in range(4)]
  1292. AB(-i0, -i1).data = random_4x4_data
  1293. for i in range(4):
  1294. for j in range(4):
  1295. assert AB(i0, i1).data[i, j] == random_4x4_data[i][j]*(-1 if i else 1)*(-1 if j else 1)
  1296. assert AB(-i0, i1).data[i, j] == random_4x4_data[i][j]*(-1 if j else 1)
  1297. assert AB(i0, -i1).data[i, j] == random_4x4_data[i][j]*(-1 if i else 1)
  1298. assert AB(-i0, -i1).data[i, j] == random_4x4_data[i][j]
  1299. AB(-i0, i1).data = random_4x4_data
  1300. for i in range(4):
  1301. for j in range(4):
  1302. assert AB(i0, i1).data[i, j] == random_4x4_data[i][j]*(-1 if i else 1)
  1303. assert AB(-i0, i1).data[i, j] == random_4x4_data[i][j]
  1304. assert AB(i0, -i1).data[i, j] == random_4x4_data[i][j]*(-1 if i else 1)*(-1 if j else 1)
  1305. assert AB(-i0, -i1).data[i, j] == random_4x4_data[i][j]*(-1 if j else 1)
  1306. def test_valued_metric_inverse():
  1307. with warns_deprecated_sympy():
  1308. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1309. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1310. # let's assign some fancy matrix, just to verify it:
  1311. # (this has no physical sense, it's just testing sympy);
  1312. # it is symmetrical:
  1313. md = [[2, 2, 2, 1], [2, 3, 1, 0], [2, 1, 2, 3], [1, 0, 3, 2]]
  1314. Lorentz.data = md
  1315. m = Matrix(md)
  1316. metric = Lorentz.metric
  1317. minv = m.inv()
  1318. meye = eye(4)
  1319. # the Kronecker Delta:
  1320. KD = Lorentz.get_kronecker_delta()
  1321. for i in range(4):
  1322. for j in range(4):
  1323. assert metric(i0, i1).data[i, j] == m[i, j]
  1324. assert metric(-i0, -i1).data[i, j] == minv[i, j]
  1325. assert metric(i0, -i1).data[i, j] == meye[i, j]
  1326. assert metric(-i0, i1).data[i, j] == meye[i, j]
  1327. assert metric(i0, i1)[i, j] == m[i, j]
  1328. assert metric(-i0, -i1)[i, j] == minv[i, j]
  1329. assert metric(i0, -i1)[i, j] == meye[i, j]
  1330. assert metric(-i0, i1)[i, j] == meye[i, j]
  1331. assert KD(i0, -i1)[i, j] == meye[i, j]
  1332. def test_valued_canon_bp_swapaxes():
  1333. with warns_deprecated_sympy():
  1334. (A, B, AB, BA, C, Lorentz, E, px, py, pz, LorentzD, mu0, mu1, mu2, ndm, n0, n1,
  1335. n2, NA, NB, NC, minkowski, ba_matrix, ndm_matrix, i0, i1, i2, i3, i4) = _get_valued_base_test_variables()
  1336. e1 = A(i1)*A(i0)
  1337. e2 = e1.canon_bp()
  1338. assert e2 == A(i0)*A(i1)
  1339. for i in range(4):
  1340. for j in range(4):
  1341. assert e1[i, j] == e2[j, i]
  1342. o1 = B(i2)*A(i1)*B(i0)
  1343. o2 = o1.canon_bp()
  1344. for i in range(4):
  1345. for j in range(4):
  1346. for k in range(4):
  1347. assert o1[i, j, k] == o2[j, i, k]
  1348. def test_valued_components_with_wrong_symmetry():
  1349. with warns_deprecated_sympy():
  1350. IT = TensorIndexType('IT', dim=3)
  1351. i0, i1, i2, i3 = tensor_indices('i0:4', IT)
  1352. IT.data = [1, 1, 1]
  1353. A_nosym = TensorHead('A', [IT]*2)
  1354. A_sym = TensorHead('A', [IT]*2, TensorSymmetry.fully_symmetric(2))
  1355. A_antisym = TensorHead('A', [IT]*2, TensorSymmetry.fully_symmetric(-2))
  1356. mat_nosym = Matrix([[1,2,3],[4,5,6],[7,8,9]])
  1357. mat_sym = mat_nosym + mat_nosym.T
  1358. mat_antisym = mat_nosym - mat_nosym.T
  1359. A_nosym.data = mat_nosym
  1360. A_nosym.data = mat_sym
  1361. A_nosym.data = mat_antisym
  1362. def assign(A, dat):
  1363. A.data = dat
  1364. A_sym.data = mat_sym
  1365. raises(ValueError, lambda: assign(A_sym, mat_nosym))
  1366. raises(ValueError, lambda: assign(A_sym, mat_antisym))
  1367. A_antisym.data = mat_antisym
  1368. raises(ValueError, lambda: assign(A_antisym, mat_sym))
  1369. raises(ValueError, lambda: assign(A_antisym, mat_nosym))
  1370. A_sym.data = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
  1371. A_antisym.data = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
  1372. def test_issue_10972_TensMul_data():
  1373. with warns_deprecated_sympy():
  1374. Lorentz = TensorIndexType('Lorentz', metric_symmetry=1, dummy_name='i', dim=2)
  1375. Lorentz.data = [-1, 1]
  1376. mu, nu, alpha, beta = tensor_indices('\\mu, \\nu, \\alpha, \\beta',
  1377. Lorentz)
  1378. u = TensorHead('u', [Lorentz])
  1379. u.data = [1, 0]
  1380. F = TensorHead('F', [Lorentz]*2, TensorSymmetry.fully_symmetric(-2))
  1381. F.data = [[0, 1],
  1382. [-1, 0]]
  1383. mul_1 = F(mu, alpha) * u(-alpha) * F(nu, beta) * u(-beta)
  1384. assert (mul_1.data == Array([[0, 0], [0, 1]]))
  1385. mul_2 = F(mu, alpha) * F(nu, beta) * u(-alpha) * u(-beta)
  1386. assert (mul_2.data == mul_1.data)
  1387. assert ((mul_1 + mul_1).data == 2 * mul_1.data)
  1388. def test_TensMul_data():
  1389. with warns_deprecated_sympy():
  1390. Lorentz = TensorIndexType('Lorentz', metric_symmetry=1, dummy_name='L', dim=4)
  1391. Lorentz.data = [-1, 1, 1, 1]
  1392. mu, nu, alpha, beta = tensor_indices('\\mu, \\nu, \\alpha, \\beta',
  1393. Lorentz)
  1394. u = TensorHead('u', [Lorentz])
  1395. u.data = [1, 0, 0, 0]
  1396. F = TensorHead('F', [Lorentz]*2, TensorSymmetry.fully_symmetric(-2))
  1397. Ex, Ey, Ez, Bx, By, Bz = symbols('E_x E_y E_z B_x B_y B_z')
  1398. F.data = [
  1399. [0, Ex, Ey, Ez],
  1400. [-Ex, 0, Bz, -By],
  1401. [-Ey, -Bz, 0, Bx],
  1402. [-Ez, By, -Bx, 0]]
  1403. E = F(mu, nu) * u(-nu)
  1404. assert ((E(mu) * E(nu)).data ==
  1405. Array([[0, 0, 0, 0],
  1406. [0, Ex ** 2, Ex * Ey, Ex * Ez],
  1407. [0, Ex * Ey, Ey ** 2, Ey * Ez],
  1408. [0, Ex * Ez, Ey * Ez, Ez ** 2]])
  1409. )
  1410. assert ((E(mu) * E(nu)).canon_bp().data == (E(mu) * E(nu)).data)
  1411. assert ((F(mu, alpha) * F(beta, nu) * u(-alpha) * u(-beta)).data ==
  1412. - (E(mu) * E(nu)).data
  1413. )
  1414. assert ((F(alpha, mu) * F(beta, nu) * u(-alpha) * u(-beta)).data ==
  1415. (E(mu) * E(nu)).data
  1416. )
  1417. g = TensorHead('g', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  1418. g.data = Lorentz.data
  1419. # tensor 'perp' is orthogonal to vector 'u'
  1420. perp = u(mu) * u(nu) + g(mu, nu)
  1421. mul_1 = u(-mu) * perp(mu, nu)
  1422. assert (mul_1.data == Array([0, 0, 0, 0]))
  1423. mul_2 = u(-mu) * perp(mu, alpha) * perp(nu, beta)
  1424. assert (mul_2.data == Array.zeros(4, 4, 4))
  1425. Fperp = perp(mu, alpha) * perp(nu, beta) * F(-alpha, -beta)
  1426. assert (Fperp.data[0, :] == Array([0, 0, 0, 0]))
  1427. assert (Fperp.data[:, 0] == Array([0, 0, 0, 0]))
  1428. mul_3 = u(-mu) * Fperp(mu, nu)
  1429. assert (mul_3.data == Array([0, 0, 0, 0]))
  1430. # Test the deleter
  1431. del g.data
  1432. def test_issue_11020_TensAdd_data():
  1433. with warns_deprecated_sympy():
  1434. Lorentz = TensorIndexType('Lorentz', metric_symmetry=1, dummy_name='i', dim=2)
  1435. Lorentz.data = [-1, 1]
  1436. a, b, c, d = tensor_indices('a, b, c, d', Lorentz)
  1437. i0, i1 = tensor_indices('i_0:2', Lorentz)
  1438. # metric tensor
  1439. g = TensorHead('g', [Lorentz]*2, TensorSymmetry.fully_symmetric(2))
  1440. g.data = Lorentz.data
  1441. u = TensorHead('u', [Lorentz])
  1442. u.data = [1, 0]
  1443. add_1 = g(b, c) * g(d, i0) * u(-i0) - g(b, c) * u(d)
  1444. assert (add_1.data == Array.zeros(2, 2, 2))
  1445. # Now let us replace index `d` with `a`:
  1446. add_2 = g(b, c) * g(a, i0) * u(-i0) - g(b, c) * u(a)
  1447. assert (add_2.data == Array.zeros(2, 2, 2))
  1448. # some more tests
  1449. # perp is tensor orthogonal to u^\mu
  1450. perp = u(a) * u(b) + g(a, b)
  1451. mul_1 = u(-a) * perp(a, b)
  1452. assert (mul_1.data == Array([0, 0]))
  1453. mul_2 = u(-c) * perp(c, a) * perp(d, b)
  1454. assert (mul_2.data == Array.zeros(2, 2, 2))
  1455. def test_index_iteration():
  1456. L = TensorIndexType("Lorentz", dummy_name="L")
  1457. i0, i1, i2, i3, i4 = tensor_indices('i0:5', L)
  1458. L0 = tensor_indices('L_0', L)
  1459. L1 = tensor_indices('L_1', L)
  1460. A = TensorHead("A", [L, L])
  1461. B = TensorHead("B", [L, L], TensorSymmetry.fully_symmetric(2))
  1462. e1 = A(i0,i2)
  1463. e2 = A(i0,-i0)
  1464. e3 = A(i0,i1)*B(i2,i3)
  1465. e4 = A(i0,i1)*B(i2,-i1)
  1466. e5 = A(i0,i1)*B(-i0,-i1)
  1467. e6 = e1 + e4
  1468. assert list(e1._iterate_free_indices) == [(i0, (1, 0)), (i2, (1, 1))]
  1469. assert list(e1._iterate_dummy_indices) == []
  1470. assert list(e1._iterate_indices) == [(i0, (1, 0)), (i2, (1, 1))]
  1471. assert list(e2._iterate_free_indices) == []
  1472. assert list(e2._iterate_dummy_indices) == [(L0, (1, 0)), (-L0, (1, 1))]
  1473. assert list(e2._iterate_indices) == [(L0, (1, 0)), (-L0, (1, 1))]
  1474. assert list(e3._iterate_free_indices) == [(i0, (0, 1, 0)), (i1, (0, 1, 1)), (i2, (1, 1, 0)), (i3, (1, 1, 1))]
  1475. assert list(e3._iterate_dummy_indices) == []
  1476. assert list(e3._iterate_indices) == [(i0, (0, 1, 0)), (i1, (0, 1, 1)), (i2, (1, 1, 0)), (i3, (1, 1, 1))]
  1477. assert list(e4._iterate_free_indices) == [(i0, (0, 1, 0)), (i2, (1, 1, 0))]
  1478. assert list(e4._iterate_dummy_indices) == [(L0, (0, 1, 1)), (-L0, (1, 1, 1))]
  1479. assert list(e4._iterate_indices) == [(i0, (0, 1, 0)), (L0, (0, 1, 1)), (i2, (1, 1, 0)), (-L0, (1, 1, 1))]
  1480. assert list(e5._iterate_free_indices) == []
  1481. assert list(e5._iterate_dummy_indices) == [(L0, (0, 1, 0)), (L1, (0, 1, 1)), (-L0, (1, 1, 0)), (-L1, (1, 1, 1))]
  1482. assert list(e5._iterate_indices) == [(L0, (0, 1, 0)), (L1, (0, 1, 1)), (-L0, (1, 1, 0)), (-L1, (1, 1, 1))]
  1483. assert list(e6._iterate_free_indices) == [(i0, (0, 0, 1, 0)), (i2, (0, 1, 1, 0)), (i0, (1, 1, 0)), (i2, (1, 1, 1))]
  1484. assert list(e6._iterate_dummy_indices) == [(L0, (0, 0, 1, 1)), (-L0, (0, 1, 1, 1))]
  1485. assert list(e6._iterate_indices) == [(i0, (0, 0, 1, 0)), (L0, (0, 0, 1, 1)), (i2, (0, 1, 1, 0)), (-L0, (0, 1, 1, 1)), (i0, (1, 1, 0)), (i2, (1, 1, 1))]
  1486. assert e1.get_indices() == [i0, i2]
  1487. assert e1.get_free_indices() == [i0, i2]
  1488. assert e2.get_indices() == [L0, -L0]
  1489. assert e2.get_free_indices() == []
  1490. assert e3.get_indices() == [i0, i1, i2, i3]
  1491. assert e3.get_free_indices() == [i0, i1, i2, i3]
  1492. assert e4.get_indices() == [i0, L0, i2, -L0]
  1493. assert e4.get_free_indices() == [i0, i2]
  1494. assert e5.get_indices() == [L0, L1, -L0, -L1]
  1495. assert e5.get_free_indices() == []
  1496. def test_tensor_expand():
  1497. L = TensorIndexType("L")
  1498. i, j, k = tensor_indices("i j k", L)
  1499. L_0 = TensorIndex("L_0", L)
  1500. A, B, C, D = tensor_heads("A B C D", [L])
  1501. F = Function("F")
  1502. x = Symbol("x")
  1503. assert isinstance(Add(A(i), B(i)), TensAdd)
  1504. assert isinstance(expand(A(i)+B(i)), TensAdd)
  1505. expr = A(i)*(A(-i)+B(-i))
  1506. assert expr.args == (A(L_0), A(-L_0) + B(-L_0))
  1507. assert expr != A(i)*A(-i) + A(i)*B(-i)
  1508. assert expr.expand() == A(i)*A(-i) + A(i)*B(-i)
  1509. assert str(expr) == "A(L_0)*(A(-L_0) + B(-L_0))"
  1510. expr = A(i)*A(j) + A(i)*B(j)
  1511. assert str(expr) == "A(i)*A(j) + A(i)*B(j)"
  1512. expr = A(-i)*(A(i)*A(j) + A(i)*B(j)*C(k)*C(-k))
  1513. assert expr != A(-i)*A(i)*A(j) + A(-i)*A(i)*B(j)*C(k)*C(-k)
  1514. assert expr.expand() == A(-i)*A(i)*A(j) + A(-i)*A(i)*B(j)*C(k)*C(-k)
  1515. assert str(expr) == "A(-L_0)*(A(L_0)*A(j) + A(L_0)*B(j)*C(L_1)*C(-L_1))"
  1516. assert str(expr.canon_bp()) == 'A(j)*A(L_0)*A(-L_0) + A(L_0)*A(-L_0)*B(j)*C(L_1)*C(-L_1)'
  1517. expr = A(-i)*(2*A(i)*A(j) + A(i)*B(j))
  1518. assert expr.expand() == 2*A(-i)*A(i)*A(j) + A(-i)*A(i)*B(j)
  1519. expr = 2*A(i)*A(-i)
  1520. assert expr.coeff == 2
  1521. expr = A(i)*(B(j)*C(k) + C(j)*(A(k) + D(k)))
  1522. assert str(expr) == "A(i)*(B(j)*C(k) + C(j)*(A(k) + D(k)))"
  1523. assert str(expr.expand()) == "A(i)*B(j)*C(k) + A(i)*C(j)*A(k) + A(i)*C(j)*D(k)"
  1524. assert isinstance(TensMul(3), TensMul)
  1525. tm = TensMul(3).doit()
  1526. assert tm == 3
  1527. assert isinstance(tm, Integer)
  1528. p1 = B(j)*B(-j) + B(j)*C(-j)
  1529. p2 = C(-i)*p1
  1530. p3 = A(i)*p2
  1531. assert p3.expand() == A(i)*C(-i)*B(j)*B(-j) + A(i)*C(-i)*B(j)*C(-j)
  1532. expr = A(i)*(B(-i) + C(-i)*(B(j)*B(-j) + B(j)*C(-j)))
  1533. assert expr.expand() == A(i)*B(-i) + A(i)*C(-i)*B(j)*B(-j) + A(i)*C(-i)*B(j)*C(-j)
  1534. expr = C(-i)*(B(j)*B(-j) + B(j)*C(-j))
  1535. assert expr.expand() == C(-i)*B(j)*B(-j) + C(-i)*B(j)*C(-j)
  1536. """
  1537. Test whether expand correctly handles the case where the coeff of a TensMul
  1538. is an add. We do not directly check expr_expand == 2*A(i) + F(x)*A(i) since
  1539. __add__ currently consolidates the coefficients automatically
  1540. """
  1541. expr = (2 + F(x))*A(i)
  1542. expr_expand = expr.expand()
  1543. assert isinstance(expr_expand, TensAdd)
  1544. assert expr_expand.args == (2*A(i), F(x)*A(i))
  1545. expr = (2 + F(x))*A(i) + B(i)
  1546. expr_expand = expr.expand()
  1547. assert isinstance(expr_expand, TensAdd)
  1548. assert expr_expand.args == (2*A(i), F(x)*A(i), B(i))
  1549. def test_tensor_alternative_construction():
  1550. L = TensorIndexType("L")
  1551. i0, i1, i2, i3 = tensor_indices('i0:4', L)
  1552. A = TensorHead("A", [L])
  1553. x, y = symbols("x y")
  1554. assert A(i0) == A(Symbol("i0"))
  1555. assert A(-i0) == A(-Symbol("i0"))
  1556. raises(TypeError, lambda: A(x+y))
  1557. raises(ValueError, lambda: A(2*x))
  1558. def test_tensor_replacement():
  1559. L = TensorIndexType("L")
  1560. L2 = TensorIndexType("L2", dim=2)
  1561. i, j, k, l = tensor_indices("i j k l", L)
  1562. A, B, C, D = tensor_heads("A B C D", [L])
  1563. H = TensorHead("H", [L, L])
  1564. K = TensorHead("K", [L]*4)
  1565. expr = H(i, j)
  1566. repl = {H(i,-j): [[1,2],[3,4]], L: diag(1, -1)}
  1567. assert expr._extract_data(repl) == ([i, j], Array([[1, -2], [3, -4]]))
  1568. assert expr.replace_with_arrays(repl) == Array([[1, -2], [3, -4]])
  1569. assert expr.replace_with_arrays(repl, [i, j]) == Array([[1, -2], [3, -4]])
  1570. assert expr.replace_with_arrays(repl, [i, -j]) == Array([[1, 2], [3, 4]])
  1571. assert expr.replace_with_arrays(repl, [Symbol("i"), -Symbol("j")]) == Array([[1, 2], [3, 4]])
  1572. assert expr.replace_with_arrays(repl, [-i, j]) == Array([[1, -2], [-3, 4]])
  1573. assert expr.replace_with_arrays(repl, [-i, -j]) == Array([[1, 2], [-3, -4]])
  1574. assert expr.replace_with_arrays(repl, [j, i]) == Array([[1, 3], [-2, -4]])
  1575. assert expr.replace_with_arrays(repl, [j, -i]) == Array([[1, -3], [-2, 4]])
  1576. assert expr.replace_with_arrays(repl, [-j, i]) == Array([[1, 3], [2, 4]])
  1577. assert expr.replace_with_arrays(repl, [-j, -i]) == Array([[1, -3], [2, -4]])
  1578. # Test stability of optional parameter 'indices'
  1579. assert expr.replace_with_arrays(repl) == Array([[1, -2], [3, -4]])
  1580. expr = H(i,j)
  1581. repl = {H(i,j): [[1,2],[3,4]], L: diag(1, -1)}
  1582. assert expr._extract_data(repl) == ([i, j], Array([[1, 2], [3, 4]]))
  1583. assert expr.replace_with_arrays(repl) == Array([[1, 2], [3, 4]])
  1584. assert expr.replace_with_arrays(repl, [i, j]) == Array([[1, 2], [3, 4]])
  1585. assert expr.replace_with_arrays(repl, [i, -j]) == Array([[1, -2], [3, -4]])
  1586. assert expr.replace_with_arrays(repl, [-i, j]) == Array([[1, 2], [-3, -4]])
  1587. assert expr.replace_with_arrays(repl, [-i, -j]) == Array([[1, -2], [-3, 4]])
  1588. assert expr.replace_with_arrays(repl, [j, i]) == Array([[1, 3], [2, 4]])
  1589. assert expr.replace_with_arrays(repl, [j, -i]) == Array([[1, -3], [2, -4]])
  1590. assert expr.replace_with_arrays(repl, [-j, i]) == Array([[1, 3], [-2, -4]])
  1591. assert expr.replace_with_arrays(repl, [-j, -i]) == Array([[1, -3], [-2, 4]])
  1592. # Not the same indices:
  1593. expr = H(i,k)
  1594. repl = {H(i,j): [[1,2],[3,4]], L: diag(1, -1)}
  1595. assert expr._extract_data(repl) == ([i, k], Array([[1, 2], [3, 4]]))
  1596. expr = A(i)*A(-i)
  1597. repl = {A(i): [1,2], L: diag(1, -1)}
  1598. assert expr._extract_data(repl) == ([], -3)
  1599. assert expr.replace_with_arrays(repl, []) == -3
  1600. expr = K(i, j, -j, k)*A(-i)*A(-k)
  1601. repl = {A(i): [1, 2], K(i,j,k,l): Array([1]*2**4).reshape(2,2,2,2), L: diag(1, -1)}
  1602. assert expr._extract_data(repl)
  1603. expr = H(j, k)
  1604. repl = {H(i,j): [[1,2],[3,4]], L: diag(1, -1)}
  1605. raises(ValueError, lambda: expr._extract_data(repl))
  1606. expr = A(i)
  1607. repl = {B(i): [1, 2]}
  1608. raises(ValueError, lambda: expr._extract_data(repl))
  1609. expr = A(i)
  1610. repl = {A(i): [[1, 2], [3, 4]]}
  1611. raises(ValueError, lambda: expr._extract_data(repl))
  1612. # TensAdd:
  1613. expr = A(k)*H(i, j) + B(k)*H(i, j)
  1614. repl = {A(k): [1], B(k): [1], H(i, j): [[1, 2],[3,4]], L:diag(1,1)}
  1615. assert expr._extract_data(repl) == ([k, i, j], Array([[[2, 4], [6, 8]]]))
  1616. assert expr.replace_with_arrays(repl, [k, i, j]) == Array([[[2, 4], [6, 8]]])
  1617. assert expr.replace_with_arrays(repl, [k, j, i]) == Array([[[2, 6], [4, 8]]])
  1618. expr = A(k)*A(-k) + 100
  1619. repl = {A(k): [2, 3], L: diag(1, 1)}
  1620. assert expr.replace_with_arrays(repl, []) == 113
  1621. ## Symmetrization:
  1622. expr = H(i, j) + H(j, i)
  1623. repl = {H(i, j): [[1, 2], [3, 4]]}
  1624. assert expr._extract_data(repl) == ([i, j], Array([[2, 5], [5, 8]]))
  1625. assert expr.replace_with_arrays(repl, [i, j]) == Array([[2, 5], [5, 8]])
  1626. assert expr.replace_with_arrays(repl, [j, i]) == Array([[2, 5], [5, 8]])
  1627. ## Anti-symmetrization:
  1628. expr = H(i, j) - H(j, i)
  1629. repl = {H(i, j): [[1, 2], [3, 4]]}
  1630. assert expr.replace_with_arrays(repl, [i, j]) == Array([[0, -1], [1, 0]])
  1631. assert expr.replace_with_arrays(repl, [j, i]) == Array([[0, 1], [-1, 0]])
  1632. # Tensors with contractions in replacements:
  1633. expr = K(i, j, k, -k)
  1634. repl = {K(i, j, k, -k): [[1, 2], [3, 4]]}
  1635. assert expr._extract_data(repl) == ([i, j], Array([[1, 2], [3, 4]]))
  1636. expr = H(i, -i)
  1637. repl = {H(i, -i): 42}
  1638. assert expr._extract_data(repl) == ([], 42)
  1639. expr = H(i, -i)
  1640. repl = {
  1641. H(-i, -j): Array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]]),
  1642. L: Array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]]),
  1643. }
  1644. assert expr._extract_data(repl) == ([], 4)
  1645. # Replace with array, raise exception if indices are not compatible:
  1646. expr = A(i)*A(j)
  1647. repl = {A(i): [1, 2]}
  1648. raises(ValueError, lambda: expr.replace_with_arrays(repl, [j]))
  1649. # Raise exception if array dimension is not compatible:
  1650. expr = A(i)
  1651. repl = {A(i): [[1, 2]]}
  1652. raises(ValueError, lambda: expr.replace_with_arrays(repl, [i]))
  1653. # TensorIndexType with dimension, wrong dimension in replacement array:
  1654. u1, u2, u3 = tensor_indices("u1:4", L2)
  1655. U = TensorHead("U", [L2])
  1656. expr = U(u1)*U(-u2)
  1657. repl = {U(u1): [[1]]}
  1658. raises(ValueError, lambda: expr.replace_with_arrays(repl, [u1, -u2]))
  1659. def test_rewrite_tensor_to_Indexed():
  1660. L = TensorIndexType("L", dim=4)
  1661. A = TensorHead("A", [L]*4)
  1662. B = TensorHead("B", [L])
  1663. i0, i1, i2, i3 = symbols("i0:4")
  1664. L_0, L_1 = symbols("L_0:2")
  1665. a1 = A(i0, i1, i2, i3)
  1666. assert a1.rewrite(Indexed) == Indexed(Symbol("A"), i0, i1, i2, i3)
  1667. a2 = A(i0, -i0, i2, i3)
  1668. assert a2.rewrite(Indexed) == Sum(Indexed(Symbol("A"), L_0, L_0, i2, i3), (L_0, 0, 3))
  1669. a3 = a2 + A(i2, i3, i0, -i0)
  1670. assert a3.rewrite(Indexed) == \
  1671. Sum(Indexed(Symbol("A"), L_0, L_0, i2, i3), (L_0, 0, 3)) +\
  1672. Sum(Indexed(Symbol("A"), i2, i3, L_0, L_0), (L_0, 0, 3))
  1673. b1 = B(-i0)*a1
  1674. assert b1.rewrite(Indexed) == Sum(Indexed(Symbol("B"), L_0)*Indexed(Symbol("A"), L_0, i1, i2, i3), (L_0, 0, 3))
  1675. b2 = B(-i3)*a2
  1676. assert b2.rewrite(Indexed) == Sum(Indexed(Symbol("B"), L_1)*Indexed(Symbol("A"), L_0, L_0, i2, L_1), (L_0, 0, 3), (L_1, 0, 3))
  1677. def test_tensor_matching():
  1678. """
  1679. Test match and replace with the pattern being a WildTensor or a WildTensorIndex
  1680. """
  1681. R3 = TensorIndexType('R3', dim=3)
  1682. p, q, r = tensor_indices("p q r", R3)
  1683. a,b,c = symbols("a b c", cls = WildTensorIndex, tensor_index_type=R3, ignore_updown=True)
  1684. g = WildTensorIndex("g", R3)
  1685. delta = R3.delta
  1686. eps = R3.epsilon
  1687. K = TensorHead("K", [R3])
  1688. V = TensorHead("V", [R3])
  1689. A = TensorHead("A", [R3, R3])
  1690. W = WildTensorHead('W', unordered_indices=True)
  1691. U = WildTensorHead('U')
  1692. assert a.matches(q) == {a:q}
  1693. assert a.matches(-q) == {a:-q}
  1694. assert g.matches(-q) == None
  1695. assert g.matches(q) == {g:q}
  1696. assert eps(p,-a,a).matches( eps(p,q,r) ) == None
  1697. assert eps(p,-b,a).matches( eps(p,q,r) ) == {a: r, -b: q}
  1698. assert eps(p,-q,r).replace(eps(a,b,c), 1) == 1
  1699. assert W().matches( K(p)*V(q) ) == {W(): K(p)*V(q)}
  1700. assert W(a).matches( K(p) ) == {a:p, W(a).head: _WildTensExpr(K(p))}
  1701. assert W(a,p).matches( K(p)*V(q) ) == {a:q, W(a,p).head: _WildTensExpr(K(p)*V(q))}
  1702. assert W(p,q).matches( K(p)*V(q) ) == {W(p,q).head: _WildTensExpr(K(p)*V(q))}
  1703. assert W(p,q).matches( A(q,p) ) == {W(p,q).head: _WildTensExpr(A(q, p))}
  1704. assert U(p,q).matches( A(q,p) ) == None
  1705. assert ( K(q)*K(p) ).replace( W(q,p), 1) == 1
  1706. #Some tests for matching without Wild
  1707. assert delta(p,q).matches(delta(q,p)) == {}
  1708. assert eps(p,q,r).matches(eps(q,p,r)) is None
  1709. assert eps(p,q,r).matches(eps(q,r,p)) == {}
  1710. def test_TensAdd_matching():
  1711. """
  1712. Test match and replace with the pattern being a TensAdd
  1713. """
  1714. R3 = TensorIndexType('R3', dim=3)
  1715. p, q = tensor_indices("p q", R3)
  1716. K = TensorHead("K", [R3])
  1717. V = TensorHead("V", [R3])
  1718. W = WildTensorHead('W', unordered_indices=True)
  1719. assert ( K(p)*K(q) + V(p)*V(q) ).matches( K(p)*K(q) + V(p)*V(q) ) == {}
  1720. assert ( K(p)*K(q) + V(p)*V(q) ).matches( K(p)*K(q) + V(p)*V(q) + K(p)*V(q) + V(p)*K(q) ) is None
  1721. assert ( K(p)*K(q) + V(p)*V(q) + K(p)*V(q) + K(q)*V(p) ).replace(
  1722. W(p,q) + K(p)*K(q) + V(p)*V(q),
  1723. W(p,q) + 3*K(p)*V(q)
  1724. ).doit() == K(q)*V(p) + 4*K(p)*V(q)
  1725. def test_TensMul_matching():
  1726. """
  1727. Test match and replace with the pattern being a TensMul
  1728. """
  1729. R3 = TensorIndexType('R3', dim=3)
  1730. p, q, r, s, t = tensor_indices("p q r s t", R3)
  1731. wi = Wild("wi")
  1732. a,b,c,d,e,f = symbols("a b c d e f", cls = WildTensorIndex, tensor_index_type=R3, ignore_updown=True)
  1733. delta = R3.delta
  1734. eps = R3.epsilon
  1735. K = TensorHead("K", [R3])
  1736. V = TensorHead("V", [R3])
  1737. W = WildTensorHead('W', unordered_indices=True)
  1738. U = WildTensorHead('U')
  1739. k = Symbol("K")
  1740. assert ( wi*K(p) ).matches( K(p) ) == {wi: 1}
  1741. assert ( wi * eps(p,q,r) ).matches(eps(p,r,q)) == {wi:-1}
  1742. assert ( K(p)*V(-p) ).replace( W(a)*V(-a), 1) == 1
  1743. assert ( K(q)*K(p)*V(-p) ).replace( W(q,a)*V(-a), 1) == 1
  1744. assert ( K(p)*V(-p) ).replace( K(-a)*V(a), 1 ) == 1
  1745. assert ( K(q)*K(p)*V(-p) ).replace( W(q)*U(p)*V(-p), 1) == 1
  1746. assert (
  1747. (K(p)*V(q)).replace(W()*K(p)*V(q), W()*V(p)*V(q)).doit()
  1748. == V(p)*V(q)
  1749. )
  1750. assert (
  1751. ( eps(r,p,q)*eps(-r,-s,-t) ).replace(
  1752. eps(e,a,b)*eps(-e,c,d),
  1753. delta(a,c)*delta(b,d) - delta(a,d)*delta(b,c),
  1754. ).doit().canon_bp()
  1755. == delta(p,-s)*delta(q,-t) - delta(p,-t)*delta(q,-s)
  1756. )
  1757. assert (
  1758. ( eps(r,p,q)*eps(-r,-p,-q) ).replace(
  1759. eps(c,a,b)*eps(-c,d,f),
  1760. delta(a,d)*delta(b,f) - delta(a,f)*delta(b,d),
  1761. ).contract_delta(delta).doit()
  1762. == 6
  1763. )
  1764. assert ( V(-p)*V(q)*V(-q) ).replace( wi*W()*V(a)*V(-a), wi*W() ).doit() == V(-p)
  1765. assert ( k**4*K(r)*K(-r) ).replace( wi*W()*K(a)*K(-a), wi*W()*k**2 ).doit() == k**6
  1766. #Multiple occurrence of WildTensor in value
  1767. assert (
  1768. ( K(p)*V(q) ).replace(W(q)*K(p), W(p)*W(q))
  1769. == V(p)*V(q)
  1770. )
  1771. assert (
  1772. ( K(p)*V(q)*V(r) ).replace(W(q,r)*K(p), W(p,r)*W(q,s)*V(-s) )
  1773. == V(p)*V(r)*V(q)*V(s)*V(-s)
  1774. )
  1775. #Edge case involving automatic index relabelling
  1776. D0, D1, D2, D3 = tensor_indices("R_0 R_1 R_2 R_3", R3)
  1777. expr = delta(-D0, -D1)*K(D2)*K(D3)*K(-D3)
  1778. m = ( W()*K(a)*K(-a) ).matches(expr)
  1779. assert D2 not in m.values()
  1780. def test_TensMul_subs():
  1781. """
  1782. Test subs and xreplace in TensMul. See bug #24337
  1783. """
  1784. R3 = TensorIndexType('R3', dim=3)
  1785. p, q, r = tensor_indices("p q r", R3)
  1786. K = TensorHead("K", [R3])
  1787. V = TensorHead("V", [R3])
  1788. A = TensorHead("A", [R3, R3])
  1789. C0 = TensorIndex(R3.dummy_name + "_0", R3, True)
  1790. a = WildTensorIndex("a", R3, ignore_updown=True)
  1791. assert ( K(p)*V(r)*K(-p) ).subs({V(r): K(q)*K(-q)}) == K(p)*K(q)*K(-q)*K(-p)
  1792. assert ( K(p)*V(r)*K(-p) ).xreplace({V(r): K(q)*K(-q)}) == K(p)*K(q)*K(-q)*K(-p)
  1793. assert ( K(p)*V(r) ).xreplace({p: C0, V(r): K(q)*K(-q)}) == K(C0)*K(q)*K(-q)
  1794. assert ( K(p)*A(q,-q)*K(-p) ).doit() == K(p)*A(q,-q)*K(-p)
  1795. assert ( K(p)*V(-p) ).replace( K(a), V(a)*V(q)*V(-q) ) == V(p)*V(q)*V(-q)*V(-p)
  1796. def test_tensorsymmetry():
  1797. with warns_deprecated_sympy():
  1798. tensorsymmetry([1]*2)
  1799. def test_tensorhead():
  1800. with warns_deprecated_sympy():
  1801. tensorhead('A', [])
  1802. def test_TensorType():
  1803. with warns_deprecated_sympy():
  1804. sym2 = TensorSymmetry.fully_symmetric(2)
  1805. Lorentz = TensorIndexType('Lorentz')
  1806. S2 = TensorType([Lorentz]*2, sym2)
  1807. assert isinstance(S2, TensorType)
  1808. def test_dummy_fmt():
  1809. with warns_deprecated_sympy():
  1810. TensorIndexType('Lorentz', dummy_fmt='L')
  1811. def test_postprocessor():
  1812. """
  1813. Test if substituting a Tensor into a Mul or Add automatically converts it
  1814. to TensMul or TensAdd respectively. See github issue #25051
  1815. """
  1816. R3 = TensorIndexType('R3', dim=3)
  1817. i = tensor_indices("i", R3)
  1818. K = TensorHead("K", [R3])
  1819. x,y,z = symbols("x y z")
  1820. assert isinstance((x*2).xreplace({x: K(i)}), TensMul)
  1821. assert isinstance((x+2).xreplace({x: K(i)*K(-i)}), TensAdd)
  1822. assert isinstance((x*2).subs({x: K(i)}), TensMul)
  1823. assert isinstance((x+2).subs({x: K(i)*K(-i)}), TensAdd)
  1824. assert isinstance((x*2).replace(x, K(i)), TensMul)
  1825. assert isinstance((x+2).replace(x, K(i)*K(-i)), TensAdd)
  1826. def test_TensMul_nocoeff():
  1827. """
  1828. Ensure that for any TensMul instance, self.coeff * self.nocoeff == self
  1829. """
  1830. R3 = TensorIndexType('R3', dim=3)
  1831. i, j = tensor_indices("i j", R3)
  1832. K = TensorHead("K", [R3])
  1833. P = TensorHead("P", [R3])
  1834. expr = TensMul(2, K(i), P(j))
  1835. assert expr.coeff * expr.nocoeff == expr